FILES ----- client.config default_actor_movement.config default_movement.config dungeon_worlds.config instance_worlds.config interface.config player.config sky.config system_objects.config terrestrial_worlds.config universeflags.config universe_server.config versioning.config worldserver.config [NEW] ai\missioncultist1.aimission [NEW] ai\missioncultist1icon.png animations\dust1\dust1.animation [NEW] animations\shards\metalshard.animation [NEW] animations\shards\metalshard.png [NEW] animations\shards\swansongshard.animation [NEW] animations\swansongshock\swansongshock.animation [NEW] animations\swansongshock\swansongshock.frames [NEW] animations\swansongshock\swansongshock.png behaviors\monsters\modular\actions\hop.behavior [NEW] behaviors\nodes\bounty.nodes behaviors\nodes\dialog.nodes behaviors\nodes\module.nodes behaviors\nodes\npc.nodes behaviors\nodes\quest.nodes behaviors\nodes\world.nodes behaviors\npc\accuse.behavior behaviors\npc\attackthief.behavior [NEW] behaviors\npc\bounty.behavior [NEW] behaviors\npc\friendlynpccombat.behavior behaviors\npc\guard.behavior behaviors\npc\hostileguard.behavior [NEW] behaviors\npc\peacekeeper.behavior [NEW] behaviors\npc\rivalbountyhunter.behavior behaviors\npc\villageguard.behavior [NEW] behaviors\npc\bounty\bounty-arrest.behavior [NEW] behaviors\npc\bounty\bounty-beamout.behavior [NEW] behaviors\npc\bounty\bounty-bribe.behavior [NEW] behaviors\npc\bounty\bounty-crazy.behavior [NEW] behaviors\npc\bounty\bounty-disguise-capture.behavior [NEW] behaviors\npc\bounty\bounty-disguise.behavior [NEW] behaviors\npc\bounty\bounty-flee.behavior [NEW] behaviors\npc\bounty\bounty-interrogate.behavior [NEW] behaviors\npc\bounty\bounty-trick.behavior [NEW] biomes\surface\cyberspace.biome biomes\surface_detached\bones.biome [NEW] celestial\system\spacestation\peacekeeperspacestationicon.png [NEW] cinematics\peacekeeper\captain1.frames [NEW] cinematics\peacekeeper\captain1.png [NEW] cinematics\peacekeeper\captain2.frames [NEW] cinematics\peacekeeper\captain2.png [NEW] cinematics\peacekeeper\cityscape.frames [NEW] cinematics\peacekeeper\cityscape.png [NEW] cinematics\peacekeeper\emblem.frames [NEW] cinematics\peacekeeper\emblem.png [NEW] cinematics\peacekeeper\peacekeeper.cinematic [NEW] cinematics\peacekeeper\shadow.png cinematics\story\esther\esther.cinematic [NEW] codex\missions\cultist mission\cultistmission1.codex [NEW] codex\missions\cultist mission\cultistmission1.png [NEW] codex\missions\cultist mission\cultistmission2.codex collections\fossils.collection [NEW] dialog\bounty.config [NEW] dialog\bountytarget.config dialog\clues.config dialog\cultist.config dialog\miniknogthreats.config [NEW] dialog\peacekeeper.config [NEW] dialog\peacekeeperconverse.config dialog\rebel.config dialog\scientist.config dungeons\blankTemplate.json dungeons\microdungeons\biomes\garden\gardenmicrodungeons.dungeon [NEW] dungeons\microdungeons\biomes\garden\steps1.json [NEW] dungeons\microdungeons\bounty\boat.dungeon [NEW] dungeons\microdungeons\bounty\boatinteract.dungeon [NEW] dungeons\microdungeons\bounty\boatinteract_1.json [NEW] dungeons\microdungeons\bounty\boatinteract_2.json [NEW] dungeons\microdungeons\bounty\boatinteract_3.json [NEW] dungeons\microdungeons\bounty\boatvault.dungeon [NEW] dungeons\microdungeons\bounty\boatvault_1.json [NEW] dungeons\microdungeons\bounty\boatvault_2.json [NEW] dungeons\microdungeons\bounty\boatvault_3.json [NEW] dungeons\microdungeons\bounty\boat_1.json [NEW] dungeons\microdungeons\bounty\boat_2.json [NEW] dungeons\microdungeons\bounty\boat_3.json [NEW] dungeons\microdungeons\bounty\boat_4.json [NEW] dungeons\microdungeons\bounty\boat_5.json [NEW] dungeons\microdungeons\bounty\boat_6.json [NEW] dungeons\microdungeons\bounty\boat_7.json [NEW] dungeons\microdungeons\bounty\bountycamp.dungeon [NEW] dungeons\microdungeons\bounty\bountycamp_1.json [NEW] dungeons\microdungeons\bounty\bountycamp_2.json [NEW] dungeons\microdungeons\bounty\bountycamp_3.json [NEW] dungeons\microdungeons\bounty\interactobject.dungeon [NEW] dungeons\microdungeons\bounty\interactobject_1.json [NEW] dungeons\microdungeons\bounty\interactobject_2.json [NEW] dungeons\microdungeons\bounty\interactobject_3.json [NEW] dungeons\microdungeons\bounty\interactobject_4.json [NEW] dungeons\microdungeons\bounty\interactobject_5.json [NEW] dungeons\microdungeons\bounty\interactobject_6.json [NEW] dungeons\microdungeons\bounty\interactobject_7.json [NEW] dungeons\microdungeons\bounty\interactobject_8.json [NEW] dungeons\microdungeons\bounty\minor_spawn.dungeon [NEW] dungeons\microdungeons\bounty\minor_spawn.json [NEW] dungeons\microdungeons\bounty\safehouse.dungeon [NEW] dungeons\microdungeons\bounty\safehouse_1.json [NEW] dungeons\microdungeons\bounty\safehouse_10.json [NEW] dungeons\microdungeons\bounty\safehouse_11.json [NEW] dungeons\microdungeons\bounty\safehouse_12.json [NEW] dungeons\microdungeons\bounty\safehouse_13.json [NEW] dungeons\microdungeons\bounty\safehouse_14.json [NEW] dungeons\microdungeons\bounty\safehouse_15.json [NEW] dungeons\microdungeons\bounty\safehouse_16.json [NEW] dungeons\microdungeons\bounty\safehouse_17.json [NEW] dungeons\microdungeons\bounty\safehouse_2.json [NEW] dungeons\microdungeons\bounty\safehouse_3.json [NEW] dungeons\microdungeons\bounty\safehouse_4.json [NEW] dungeons\microdungeons\bounty\safehouse_5.json [NEW] dungeons\microdungeons\bounty\safehouse_6.json [NEW] dungeons\microdungeons\bounty\safehouse_7.json [NEW] dungeons\microdungeons\bounty\safehouse_8.json [NEW] dungeons\microdungeons\bounty\safehouse_9.json [NEW] dungeons\microdungeons\bounty\safehouse_template.json [NEW] dungeons\microdungeons\bounty\undergroundinteract.dungeon [NEW] dungeons\microdungeons\bounty\undergroundinteract_1.json [NEW] dungeons\microdungeons\bounty\undergroundinteract_2.json [NEW] dungeons\microdungeons\bounty\undergroundinteract_3.json [NEW] dungeons\microdungeons\bounty\undergroundinteract_4.json [NEW] dungeons\microdungeons\bounty\undergroundinteract_5.json [NEW] dungeons\microdungeons\bounty\undergroundinteract_6.json [NEW] dungeons\microdungeons\bounty\undergroundinteract_7.json [NEW] dungeons\microdungeons\bounty\undergroundinteract_template.json [NEW] dungeons\microdungeons\bounty\undergroundsafehouse.dungeon [NEW] dungeons\microdungeons\bounty\undergroundsafehouse_1.json [NEW] dungeons\microdungeons\bounty\undergroundsafehouse_2.json [NEW] dungeons\microdungeons\bounty\undergroundsafehouse_3.json [NEW] dungeons\microdungeons\bounty\undergroundsafehouse_4.json [NEW] dungeons\microdungeons\bounty\undergroundsafehouse_5.json [NEW] dungeons\microdungeons\bounty\undergroundsafehouse_6.json [NEW] dungeons\microdungeons\bounty\undergroundsafehouse_7.json [NEW] dungeons\microdungeons\bounty\undergroundsafehouse_8.json [NEW] dungeons\microdungeons\bounty\undergroundsafehouse_9.json [NEW] dungeons\microdungeons\bounty\undergroundsafehouse_template.json [NEW] dungeons\microdungeons\bounty\undergroundvault.dungeon [NEW] dungeons\microdungeons\bounty\undergroundvault_1.json [NEW] dungeons\microdungeons\bounty\undergroundvault_2.json [NEW] dungeons\microdungeons\bounty\undergroundvault_3.json [NEW] dungeons\microdungeons\bounty\vault.dungeon [NEW] dungeons\microdungeons\bounty\vault_1.json [NEW] dungeons\microdungeons\bounty\vault_2.json [NEW] dungeons\microdungeons\bounty\vault_3.json [NEW] dungeons\missions\cultistmissions\cultistmission1.dungeon [NEW] dungeons\missions\cultistmissions\cultistmission1.json [NEW] dungeons\other\bountylair\bountylair1.dungeon [NEW] dungeons\other\bountylair\bountylair1.json [NEW] dungeons\other\bountylair\bountylair2.dungeon [NEW] dungeons\other\bountylair\bountylair2.json [NEW] dungeons\other\bountylair\bountylair3.dungeon [NEW] dungeons\other\bountylair\bountylair3.json [NEW] dungeons\other\bountylair\bountylair4.dungeon [NEW] dungeons\other\bountylair\bountylair4.json [NEW] dungeons\other\cultistlair\cultistlair.dungeon [NEW] dungeons\other\cultistlair\lair_chamber1.json [NEW] dungeons\other\cultistlair\lair_entrance1.json [NEW] dungeons\other\cultistlair\lair_entrance1a.json [NEW] dungeons\other\cultistlair\lair_entrance1b.json [NEW] dungeons\other\cultistlair\lair_room1.json [NEW] dungeons\other\cultistlair\lair_room1a.json [NEW] dungeons\other\cultistlair\lair_room1b.json [NEW] dungeons\other\cultistlair\lair_room2.json [NEW] dungeons\other\cultistlair\lair_room2a.json [NEW] dungeons\other\cultistlair\lair_room2b.json [NEW] dungeons\other\cultistlair\lair_room3.json [NEW] dungeons\other\cultistlair\lair_room3a.json [NEW] dungeons\other\cultistlair\lair_room3b.json [NEW] dungeons\other\cultistlair\lair_room4.json [NEW] dungeons\other\cultistlair\lair_room4a.json [NEW] dungeons\other\cultistlair\lair_room5.json [NEW] dungeons\other\cultistlair\lair_room5a.json [NEW] dungeons\other\cultistlair\lair_room5b.json [NEW] dungeons\other\cultistlair\lair_room5c.json [NEW] dungeons\other\cultistlair\lair_room6.json [NEW] dungeons\other\cultistlair\lair_room6a.json [NEW] dungeons\other\cultistlair\lair_room6b.json [NEW] dungeons\other\cultistlair\lair_room7.json [NEW] dungeons\other\cultistlair\lair_room7a.json [NEW] dungeons\other\cultistlair\lair_room7b.json [NEW] dungeons\other\cultistlair\lair_room_template.json [NEW] dungeons\other\cultistlair\lair_shell_big1a.json [NEW] dungeons\other\cultistlair\lair_shell_big1b.json [NEW] dungeons\other\cultistlair\lair_shell_big2a.json [NEW] dungeons\other\cultistlair\lair_shell_big2b.json [NEW] dungeons\other\cultistlair\lair_shell_big3a.json [NEW] dungeons\other\cultistlair\lair_shell_big3b.json [NEW] dungeons\other\cultistlair\lair_shell_big4a.json [NEW] dungeons\other\cultistlair\lair_shell_big4b.json [NEW] dungeons\other\cultistlair\lair_shell_big5a.json [NEW] dungeons\other\cultistlair\lair_shell_big5b.json [NEW] dungeons\other\cultistlair\lair_shell_big6a.json [NEW] dungeons\other\cultistlair\lair_shell_big6b.json [NEW] dungeons\other\cultistlair\lair_shell_big_end1a.json [NEW] dungeons\other\cultistlair\lair_shell_big_end1b.json [NEW] dungeons\other\cultistlair\lair_shell_big_end2a.json [NEW] dungeons\other\cultistlair\lair_shell_big_end2b.json [NEW] dungeons\other\cultistlair\lair_shell_big_end3a.json [NEW] dungeons\other\cultistlair\lair_shell_big_end3b.json [NEW] dungeons\other\cultistlair\lair_shell_medium1a.json [NEW] dungeons\other\cultistlair\lair_shell_medium1b.json [NEW] dungeons\other\cultistlair\lair_shell_medium2a.json [NEW] dungeons\other\cultistlair\lair_shell_medium2b.json [NEW] dungeons\other\cultistlair\lair_shell_medium3a.json [NEW] dungeons\other\cultistlair\lair_shell_medium3b.json [NEW] dungeons\other\cultistlair\lair_shell_medium_end1a.json [NEW] dungeons\other\cultistlair\lair_shell_medium_end1b.json [NEW] dungeons\other\cultistlair\lair_shell_medium_end2a.json [NEW] dungeons\other\cultistlair\lair_shell_medium_end2b.json [NEW] dungeons\other\cultistlair\lair_shell_small1a.json [NEW] dungeons\other\cultistlair\lair_shell_small1b.json [NEW] dungeons\other\cultistlair\lair_shell_small_end1a.json [NEW] dungeons\other\cultistlair\lair_shell_small_end1b.json [NEW] dungeons\other\cultistlair\lair_template.json [NEW] dungeons\other\cultistlair\lair_vertical1a.json [NEW] dungeons\other\cultistlair\lair_vertical1b.json [NEW] dungeons\other\cultistlair\lair_vertical2a.json [NEW] dungeons\other\cultistlair\lair_vertical2b.json [NEW] dungeons\other\cultistlair\lair_vertical3a.json [NEW] dungeons\other\cultistlair\lair_vertical3b.json [NEW] dungeons\other\cultistlair\lair_vertical4a.json [NEW] dungeons\other\cultistlair\lair_vertical4b.json [NEW] dungeons\other\cultistlair\lair_vertical5a.json [NEW] dungeons\other\cultistlair\lair_vertical5b.json [NEW] dungeons\other\cultistlair\lair_vertical6a.json [NEW] dungeons\other\cultistlair\lair_vertical6b.json [NEW] dungeons\other\cultistlair\lair_vertical_template.json [NEW] dungeons\other\cultistlair\old\lair_shell_big_end1a.json [NEW] dungeons\other\cultistlair\old\lair_shell_big_end1b.json [NEW] dungeons\other\cultistlair\old\lair_shell_big_end2a.json [NEW] dungeons\other\cultistlair\old\lair_shell_big_end2b.json [NEW] dungeons\other\cultistlair\old\lair_shell_big_end3a.json [NEW] dungeons\other\cultistlair\old\lair_shell_big_end3b.json [NEW] dungeons\other\cultistlair\old\lair_shell_medium_end1a.json [NEW] dungeons\other\cultistlair\old\lair_shell_medium_end1b.json [NEW] dungeons\other\cultistlair\old\lair_shell_medium_end2a.json [NEW] dungeons\other\cultistlair\old\lair_shell_medium_end2b.json [NEW] dungeons\other\cultistlair\old\lair_shell_small_end1a.json [NEW] dungeons\other\cultistlair\old\lair_shell_small_end1b.json dungeons\other\outpost\outpost.json dungeons\other\outpost\outpost_full.json [NEW] dungeons\other\outpost\outpost_peacekeeper.dungeon [NEW] dungeons\other\outpost\outpost_peacekeeper.json [NEW] dungeons\space\bountyshipencounter\backend1.json [NEW] dungeons\space\bountyshipencounter\backend2.json [NEW] dungeons\space\bountyshipencounter\backend3.json [NEW] dungeons\space\bountyshipencounter\bountyshipencounter.dungeon [NEW] dungeons\space\bountyshipencounter\cockpit1.json [NEW] dungeons\space\bountyshipencounter\cockpit2.json [NEW] dungeons\space\bountyshipencounter\cockpit3.json [NEW] dungeons\space\bountyshipencounter\middle1a.json [NEW] dungeons\space\bountyshipencounter\middle1b.json [NEW] dungeons\space\bountyshipencounter\middle2a.json [NEW] dungeons\space\bountyshipencounter\middle2b.json [NEW] dungeons\space\bountyshipencounter\middle2c.json [NEW] dungeons\space\bountyshipencounter\middle2d.json [NEW] dungeons\space\bountyshipencounter\middle3a.json [NEW] dungeons\space\bountyshipencounter\middle3b.json [NEW] dungeons\space\bountyshipencounter\middle4a.json [NEW] dungeons\space\bountyshipencounter\middle4b.json [NEW] dungeons\space\bountyshipencounter\middle5a.json [NEW] dungeons\space\bountyshipencounter\middle5b.json [NEW] dungeons\space\bountyshipencounter\middle5c.json [NEW] dungeons\space\bountyshipencounter\middle5d.json [NEW] dungeons\space\bountyshipencounter\middle6a.json [NEW] dungeons\space\bountyshipencounter\middle6b.json [NEW] dungeons\space\bountyshipencounter\middle7a.json [NEW] dungeons\space\bountyshipencounter\middle7b.json [NEW] dungeons\space\bountyshipencounter\middle8a.json [NEW] dungeons\space\bountyshipencounter\middle8b.json [NEW] dungeons\space\bountyshipencounter\template_basic.json [NEW] dungeons\space\bountyspaceencounter\bounty.json [NEW] dungeons\space\bountyspaceencounter\bountyspaceencounter.dungeon [NEW] dungeons\space\bountyspaceencounter\encounter_1.json [NEW] dungeons\space\bountyspacesafehouse\bountyspacesafehouse.dungeon [NEW] dungeons\space\bountyspacesafehouse\end_1.json [NEW] dungeons\space\bountyspacesafehouse\end_2.json [NEW] dungeons\space\bountyspacesafehouse\end_3.json [NEW] dungeons\space\bountyspacesafehouse\end_4.json [NEW] dungeons\space\bountyspacesafehouse\end_5.json [NEW] dungeons\space\bountyspacesafehouse\end_6.json [NEW] dungeons\space\bountyspacesafehouse\entrance_1.json [NEW] dungeons\space\bountyspacesafehouse\room_1.json [NEW] dungeons\space\bountyspacesafehouse\room_2.json [NEW] dungeons\space\bountyspacesafehouse\room_3.json [NEW] dungeons\space\bountyspacesafehouse\room_4.json [NEW] dungeons\space\bountyspacesafehouse\room_5.json [NEW] dungeons\space\bountyspacesafehouse\room_6.json [NEW] dungeons\space\bountyspacesafehouse\room_7.json [NEW] dungeons\space\bountyspacesafehouse\room_8.json [NEW] dungeons\space\bountyspacesafehouse\room_9.json [NEW] dungeons\space\bountyspacevault\bountyspacevault.dungeon [NEW] dungeons\space\bountyspacevault\end_1.json [NEW] dungeons\space\bountyspacevault\end_2.json [NEW] dungeons\space\bountyspacevault\entrance_1.json [NEW] dungeons\space\bountyspacevault\room_1.json [NEW] dungeons\space\peacekeeperstation\entrance.json [NEW] dungeons\space\peacekeeperstation\peacekeeperstation1.dungeon [NEW] dungeons\space\peacekeeperstation\peacekeeperstation1.json [NEW] dungeons\space\peacekeeperstation\peacekeeperstation2.dungeon [NEW] dungeons\space\peacekeeperstation\peacekeeperstation2.json [NEW] dungeons\space\peacekeeperstation\peacekeeperstation3.dungeon [NEW] dungeons\space\peacekeeperstation\peacekeeperstation3.json [NEW] dungeons\space\peacekeeperstation\peacekeeperstation4.dungeon [NEW] dungeons\space\peacekeeperstation\peacekeeperstation4.json [NEW] dungeons\space\peacekeeperstation\peacekeeperstation5.dungeon [NEW] dungeons\space\peacekeeperstation\station5_end1.json [NEW] dungeons\space\peacekeeperstation\station5_end2.json [NEW] dungeons\space\peacekeeperstation\station5_end3.json [NEW] dungeons\space\peacekeeperstation\station5_entrance1.json [NEW] dungeons\space\peacekeeperstation\station5_entrance2.json [NEW] dungeons\space\peacekeeperstation\station5_entrance3.json [NEW] dungeons\space\peacekeeperstation\station5_middle1.json [NEW] dungeons\space\peacekeeperstation\station5_middle2.json [NEW] dungeons\space\peacekeeperstation\station5_middle3.json [NEW] dungeons\space\peacekeeperstation\station5_middle4.json [NEW] dungeons\space\peacekeeperstation\station5_middle5.json [NEW] effects\firesparks.effectsource [NEW] effects\rockettrail.effectsource [NEW] effects\smokefront.effectsource [NEW] events\events.config [NEW] events\events.lua [NEW] humanoid\novakid\hair\fem20.png [NEW] humanoid\novakid\hair\male20.png interface\deployhover.png [NEW] interface\inventoryglow.png [NEW] interface\inventoryglowhover.png [NEW] interface\actionbar\actionbarpickup.png.xb1 interface\ai\ai.config [NEW] interface\ai\listitemscrollhover.png [NEW] interface\chatbubbles\captain.frames [NEW] interface\chatbubbles\captain.png [NEW] interface\chatbubbles\captainrage.frames [NEW] interface\chatbubbles\captainrage.png [NEW] interface\chatbubbles\noxstatic.frames [NEW] interface\chatbubbles\noxstatic.png [NEW] interface\chatbubbles\soundonly.frames [NEW] interface\chatbubbles\soundonly.png interface\cockpit\cockpit.config interface\cockpit\cockpit.lua interface\cockpit\cockpitutil.lua interface\cockpit\cockpitview.lua [NEW] interface\cockpit\peacekeeperbutton.frames [NEW] interface\cockpit\peacekeeperbutton.png [NEW] interface\cockpit\trackedquestmarker.png [NEW] interface\cockpit\untrackedquestmarker.png interface\confirmation\teleportconfirmation.config [NEW] interface\crafting\beakeasyicon.png [NEW] interface\crafting\peacekeeperstoreicon.png [NEW] interface\crafting\trophiesicon.png interface\optionsmenu\optionsmenu.config [NEW] interface\scripted\bountyboard\bar_overlay.png [NEW] interface\scripted\bountyboard\bar_underlay.png [NEW] interface\scripted\bountyboard\body.png [NEW] interface\scripted\bountyboard\bountyboardgui.config [NEW] interface\scripted\bountyboard\bountyboardgui.lua [NEW] interface\scripted\bountyboard\bountyboardicon.png [NEW] interface\scripted\bountyboard\footer.png [NEW] interface\scripted\bountyboard\gangbar.png [NEW] interface\scripted\bountyboard\header.png [NEW] interface\scripted\bountyboard\loading.frames [NEW] interface\scripted\bountyboard\loading.png [NEW] interface\scripted\bountyboard\portrait_bg.png [NEW] interface\scripted\bountyboard\poster_large_7CBAF4.png [NEW] interface\scripted\bountyboard\poster_large_BCE68A.png [NEW] interface\scripted\bountyboard\poster_large_C4D993.png [NEW] interface\scripted\bountyboard\poster_large_F77EC8.png [NEW] interface\scripted\bountyboard\poster_large_FBBC64.png [NEW] interface\scripted\bountyboard\poster_large_FBBC65.png [NEW] interface\scripted\bountyboard\poster_small_7CBAF3.png [NEW] interface\scripted\bountyboard\poster_small_7CBAF4.png [NEW] interface\scripted\bountyboard\poster_small_BCE68A.png [NEW] interface\scripted\bountyboard\poster_small_BCE68B.png [NEW] interface\scripted\bountyboard\poster_small_F77EC8.png [NEW] interface\scripted\bountyboard\poster_small_FBBC65.png [NEW] interface\scripted\bountyboard\rank1.png [NEW] interface\scripted\bountyboard\rank2.png [NEW] interface\scripted\bountyboard\rank3.png [NEW] interface\scripted\bountyboard\rank4.png [NEW] interface\scripted\bountyboard\rank5.png [NEW] interface\scripted\bountyboard\title_1.png [NEW] interface\scripted\bountyboard\title_10.png [NEW] interface\scripted\bountyboard\title_11.png [NEW] interface\scripted\bountyboard\title_12.png [NEW] interface\scripted\bountyboard\title_13.png [NEW] interface\scripted\bountyboard\title_2.png [NEW] interface\scripted\bountyboard\title_3.png [NEW] interface\scripted\bountyboard\title_4.png [NEW] interface\scripted\bountyboard\title_5.png [NEW] interface\scripted\bountyboard\title_6.png [NEW] interface\scripted\bountyboard\title_7.png [NEW] interface\scripted\bountyboard\title_8.png [NEW] interface\scripted\bountyboard\title_9.png [NEW] interface\scripted\bountyboard\update_window.png [NEW] interface\scripted\keypad\asterisk.png [NEW] interface\scripted\keypad\body.png [NEW] interface\scripted\keypad\button_0.png [NEW] interface\scripted\keypad\button_1.png [NEW] interface\scripted\keypad\button_2.png [NEW] interface\scripted\keypad\button_3.png [NEW] interface\scripted\keypad\button_4.png [NEW] interface\scripted\keypad\button_5.png [NEW] interface\scripted\keypad\button_6.png [NEW] interface\scripted\keypad\button_7.png [NEW] interface\scripted\keypad\button_8.png [NEW] interface\scripted\keypad\button_9.png [NEW] interface\scripted\keypad\button_clear.png [NEW] interface\scripted\keypad\default.frames [NEW] interface\scripted\keypad\footer.png [NEW] interface\scripted\keypad\header.png [NEW] interface\scripted\keypad\keypadgui.config [NEW] interface\scripted\keypad\keypadgui.lua [NEW] interface\scripted\keypad\statuslight.frames [NEW] interface\scripted\keypad\statuslight.png interface\scripted\keytrader\keytradergui.lua [NEW] interface\scripted\papernote\body.png [NEW] interface\scripted\papernote\header.png [NEW] interface\scripted\papernote\papernotegui.config [NEW] interface\scripted\papernote\papernotegui.lua interface\scripted\techupgrade\listitem.frames interface\scripted\techupgrade\listitem.png interface\scripted\techupgrade\techupgradegui.config [NEW] interface\statuses\arrested.png [NEW] interface\warping\peacekeeperteleporter.config interface\windowconfig\newquestshort.config interface\windowconfig\questcomplete.config [NEW] interface\windowconfig\questcomplete_bounty.config interface\windowconfig\questfailed.config interface\windowconfig\questlog.config [NEW] interface\windowconfig\simpleconfirmation.config items\active\effects\lightning.lua items\active\randomblueprint\mechblueprint3.activeitem items\active\randomblueprint\mechblueprint4.activeitem items\active\randomblueprint\mechblueprint5.activeitem items\active\randomblueprint\mechblueprint6.activeitem items\active\randomblueprint\randomblueprint.lua [NEW] items\active\unsorted\arrester\arrester.activeitem [NEW] items\active\unsorted\arrester\arrester.animation [NEW] items\active\unsorted\arrester\arrester.lua [NEW] items\active\unsorted\arrester\arresteranimation.lua [NEW] items\active\unsorted\arrester\lock.png [NEW] items\active\unsorted\arrester\longarm.frames [NEW] items\active\unsorted\arrester\longarm.png [NEW] items\active\unsorted\arrester\longarm_fullbright.frames [NEW] items\active\unsorted\arrester\longarm_fullbright.png [NEW] items\active\unsorted\audiodisc\audiodisc.activeitem [NEW] items\active\unsorted\audiodisc\audiodisc.lua [NEW] items\active\unsorted\audiodisc\audiodisc.png [NEW] items\active\unsorted\handcuffs\default.frames [NEW] items\active\unsorted\handcuffs\handcuffs.activeitem [NEW] items\active\unsorted\handcuffs\handcuffs.animation [NEW] items\active\unsorted\handcuffs\handcuffs.lua [NEW] items\active\unsorted\handcuffs\handcuffs.png [NEW] items\active\unsorted\handcuffs\handcuffsfullbright.png [NEW] items\active\unsorted\handcuffs\handcuffsicon.png [NEW] items\active\unsorted\papernote\papernote.activeitem [NEW] items\active\unsorted\papernote\papernote.lua [NEW] items\active\unsorted\papernote\papernote.png [NEW] items\active\unsorted\papernote\vaultnote.activeitem [NEW] items\active\unsorted\stunmine\default.frames [NEW] items\active\unsorted\stunmine\iconfull.png [NEW] items\active\unsorted\stunmine\icontrigger.png [NEW] items\active\unsorted\stunmine\inhandmine.png [NEW] items\active\unsorted\stunmine\inhandtrigger.png [NEW] items\active\unsorted\stunmine\stunmine.activeitem [NEW] items\active\unsorted\stunmine\stunmine.animation [NEW] items\active\unsorted\stunmine\stunmine.lua items\active\weapons\melee\pickaxe\energypickaxe.activeitem items\active\weapons\melee\pickaxe\energypickaxe.animation items\active\weapons\melee\pickaxe\pickslash.lua items\active\weapons\other\drillspear\drillcharge.lua [NEW] items\active\weapons\ranged\unrand\neolaserlauncher\neolaserlauncher.png [NEW] items\active\weapons\ranged\unrand\neolaserlauncher\neolaserlauncherfullbright.png [NEW] items\active\weapons\ranged\unrand\neomagnum\neomagnum.png [NEW] items\active\weapons\ranged\unrand\neomagnum\neomagnumfullbright.png [NEW] items\active\weapons\ranged\unrand\neomagnum\neomagnum_l6.png [NEW] items\active\weapons\ranged\unrand\neoshotgun\neoshotgun.png [NEW] items\active\weapons\ranged\unrand\neoshotgun\neoshotgunfullbright.png [NEW] items\active\weapons\ranged\unrand\neotommygun\neotommygun.png [NEW] items\active\weapons\ranged\unrand\neotommygun\neotommygunfullbright.png [NEW] items\active\weapons\ranged\unrand\neotommygun\neotommygun_l6.png [NEW] items\armors\decorative\hats\groucho\groucho.head [NEW] items\armors\decorative\hats\groucho\head.png [NEW] items\armors\decorative\hats\groucho\icons.png [NEW] items\armors\decorative\hats\groucho\mask.png [NEW] items\armors\decorative\hats\pharaoh\Head.png [NEW] items\armors\decorative\hats\pharaoh\icons.png [NEW] items\armors\decorative\hats\pharaoh\mask.png [NEW] items\armors\decorative\hats\pharaoh\pharaoh.head [NEW] items\armors\decorative\hats\sheep\head.png [NEW] items\armors\decorative\hats\sheep\headicon.png [NEW] items\armors\decorative\hats\sheep\mask.png [NEW] items\armors\decorative\hats\sheep\sheep.head items\armors\other\armoredcultist\armoredcultist.back items\armors\other\armoredcultist\armoredcultist.head items\armors\other\armoredcultist\back.png items\armors\other\armoredcultist\head.png items\armors\other\armoredcultist\icons.png [NEW] items\armors\other\captainnoble\captainnoble.head [NEW] items\armors\other\captainnoble\head.png [NEW] items\armors\other\captainnoble\icons.png [NEW] items\armors\other\captainnoble\mask.png [NEW] items\armors\other\invisible\back.png [NEW] items\armors\other\invisible\icons.png [NEW] items\armors\other\invisible\invisible.back [NEW] items\armors\other\peacekeeper\BSleeve.png [NEW] items\armors\other\peacekeeper\ChestF.png [NEW] items\armors\other\peacekeeper\ChestM.png [NEW] items\armors\other\peacekeeper\FSleeve.png [NEW] items\armors\other\peacekeeper\Icons.png [NEW] items\armors\other\peacekeeper\pants.png [NEW] items\armors\other\peacekeeper\peacekeeper.chest [NEW] items\armors\other\peacekeeper\peacekeeper.legs items\fossils\large\trexfossil\trexfossil1.item items\fossils\large\trexfossil\trexfossil2.item items\fossils\large\trexfossil\trexfossil3.item items\fossils\large\trexfossil\trexfossil4.item items\fossils\large\trexfossil\trexfossil5.item items\generic\mechparts\arm\mecharmguidedmissiles.png [NEW] items\generic\mechparts\body\mechbodypeacekeeper.item [NEW] items\generic\mechparts\body\mechbodypeacekeeper.png [NEW] items\generic\other\peacecredit.item [NEW] items\generic\other\peacecredit.png [NEW] items\materials\slopedglasspanel.matitem [NEW] monsters\boss\ophanim\ophanim.animation [NEW] monsters\boss\ophanim\ophanim.lua [NEW] monsters\boss\ophanim\ophanim.monsterpart [NEW] monsters\boss\ophanim\ophanim.monstertype [NEW] monsters\boss\ophanim\ophanimbeam.lua [NEW] monsters\boss\ophanim\body\default.frames [NEW] monsters\boss\ophanim\body\ophanim.png [NEW] monsters\boss\ophanim\body\ophanimfullbright.png [NEW] monsters\boss\swansong\rocketmarker.png [NEW] monsters\boss\swansong\shrapnel1.png [NEW] monsters\boss\swansong\shrapnel2.png [NEW] monsters\boss\swansong\shrapnel3.png [NEW] monsters\boss\swansong\shrapnel4.png [NEW] monsters\boss\swansong\shrapnel5.png [NEW] monsters\boss\swansong\swansong.animation [NEW] monsters\boss\swansong\swansong.lua [NEW] monsters\boss\swansong\swansong.monstertype [NEW] monsters\boss\swansong\telegraph.lua [NEW] monsters\boss\swansong\beam\beamend.png [NEW] monsters\boss\swansong\beam\beammid.png [NEW] monsters\boss\swansong\beam\beamstart.png [NEW] monsters\boss\swansong\beam\default.frames [NEW] monsters\boss\swansong\parts\swansong.monsterpart [NEW] monsters\boss\swansong\parts\body\body.png [NEW] monsters\boss\swansong\parts\body\bodyfullbright.png [NEW] monsters\boss\swansong\parts\body\default.frames [NEW] monsters\boss\swansong\parts\chargeswoosh\chargeswoosh.png [NEW] monsters\boss\swansong\parts\chargeswoosh\default.frames [NEW] monsters\boss\swansong\parts\lefthand\default.frames [NEW] monsters\boss\swansong\parts\lefthand\lefthand.png [NEW] monsters\boss\swansong\parts\lefthand\lefthandfullbright.png [NEW] monsters\boss\swansong\parts\righthand\default.frames [NEW] monsters\boss\swansong\parts\righthand\righthand.png [NEW] monsters\boss\swansong\parts\righthand\righthandfullbright.png [NEW] monsters\boss\swansong\parts\wings\default.frames [NEW] monsters\boss\swansong\parts\wings\wings.png [NEW] monsters\boss\swansong\parts\wings\wingsfullbright.png [NEW] monsters\crawlers\crustoise\crustoise_ice.png [NEW] monsters\crawlers\iguarmor\iguarmor_ice.png [NEW] monsters\crawlers\oculob\oculob_fire.png [NEW] monsters\crawlers\pulpin\pulpin_poison.png [NEW] monsters\crawlers\snaggler\snaggler_ice.png [NEW] monsters\crawlers\tintic\tintic_electric.png [NEW] monsters\crawlers\tintic\tintic_electric_lit.png monsters\crawlers\triplod\triplod.animation monsters\crawlers\triplod\triplod.monstertype [NEW] monsters\events\envprobe\body.monsterpart [NEW] monsters\events\envprobe\body.png [NEW] monsters\events\envprobe\bodyfullbright.png [NEW] monsters\events\envprobe\default.frames [NEW] monsters\events\envprobe\envprobe.animation [NEW] monsters\events\envprobe\envprobe.lua [NEW] monsters\events\envprobe\envprobe.monstertype [NEW] monsters\events\envprobe\envprobe.png [NEW] monsters\events\ruinportal\default.frames [NEW] monsters\events\ruinportal\portal.monsterpart [NEW] monsters\events\ruinportal\portal.png [NEW] monsters\events\ruinportal\portalbg.monsterpart [NEW] monsters\events\ruinportal\portalbg.png [NEW] monsters\events\ruinportal\ruinportal.animation [NEW] monsters\events\ruinportal\ruinportal.lua [NEW] monsters\events\ruinportal\ruinportal.monstertype [NEW] monsters\flyers\agrobat\agrobatwingflipped_ice.png [NEW] monsters\flyers\agrobat\agrobatwing_ice.png [NEW] monsters\flyers\agrobat\agrobat_ice.png [NEW] monsters\flyers\batong\batong_poison.png [NEW] monsters\flyers\bobfae\bobfae_poison.png [NEW] monsters\flyers\monopus\monopus_fire.png [NEW] monsters\flyers\paratail\paratail_poison.png [NEW] monsters\flyers\pteropod\pteropod_fire.png [NEW] monsters\flyers\pteropod\pteropod_fire_lit.png [NEW] monsters\flyers\scandroid\scandroid_cultist.png [NEW] monsters\flyers\scandroid\scandroid_cultist_lit.png [NEW] monsters\ghosts\ignome\ignome_electric.png [NEW] monsters\ghosts\ignome\ignome_electric_lit.png [NEW] monsters\ghosts\pyromantle\pyromantle_poison.png [NEW] monsters\ghosts\pyromantle\pyromantle_poison_lit.png [NEW] monsters\ghosts\skimbus\skimbus_electric.png [NEW] monsters\ghosts\skimbus\skimbus_electric_lit.png [NEW] monsters\ghosts\spookit\spookit_fire.png [NEW] monsters\ghosts\spookit\spookit_fire_lit.png [NEW] monsters\ghosts\squeem\squeem_fire.png [NEW] monsters\ghosts\squeem\squeem_fire_lit.png [NEW] monsters\ghosts\wisper\wisper_fire.png [NEW] monsters\ghosts\wisper\wisper_fire_lit.png monsters\space\omnicannon\omnicannon.monstertype monsters\space\rustick\rustick.animation [NEW] monsters\walkers\adultpoptop\adultpoptop_albino.png [NEW] monsters\walkers\bobot\bobot_fire.png [NEW] monsters\walkers\bobot\bobot_fire_lit.png [NEW] monsters\walkers\capricoat\capricoat_electric.png [NEW] monsters\walkers\capricoat\capricoat_electric_lit.png [NEW] monsters\walkers\crabcano\crabcano_ice.png monsters\walkers\crutter\crutter.png [NEW] monsters\walkers\crutter\crutter_electric.png [NEW] monsters\walkers\crutter\crutter_electric_lit.png [NEW] monsters\walkers\fennix\fennix_ice.png [NEW] monsters\walkers\gleap\firegleap.monstertype [NEW] monsters\walkers\gleap\gleap_fire.png [NEW] monsters\walkers\gleap\gleap_fire_lit.png [NEW] monsters\walkers\kingnutmidgeling\kingnutmidgeling_poison.png [NEW] monsters\walkers\lilodon\lilodon_fire.png [NEW] monsters\walkers\miasmop\miasmop_ice.png [NEW] monsters\walkers\nutmidge\nutmidge_poison.png [NEW] monsters\walkers\nutmidgeling\nutmidgeling_poison.png [NEW] monsters\walkers\peblit\icepeblit.monstertype monsters\walkers\peblit\peblit.animation monsters\walkers\peblit\peblit.frames [NEW] monsters\walkers\peblit\peblit_ice.png [NEW] monsters\walkers\petricub\petricub_electric.png [NEW] monsters\walkers\poptop\poptop_albino.png [NEW] monsters\walkers\scaveran\scaveran_poison.png [NEW] monsters\walkers\smoglin\poisonsmoglin.monstertype [NEW] monsters\walkers\smoglin\smoglin_poison.png [NEW] monsters\walkers\snaunt\snaunt_electric.png [NEW] monsters\walkers\snuffish\snuffish_poison.png [NEW] monsters\walkers\voltip\electricvoltip.monstertype [NEW] monsters\walkers\voltip\voltip_electric.png [NEW] monsters\walkers\voltip\voltip_electric_lit.png [NEW] npcs\cultistgeneral.npctype [NEW] npcs\cultistpet.npctype [NEW] npcs\cultistscientist.npctype npcs\merchantpools.config [NEW] npcs\bounty\bountytarget.npctype [NEW] npcs\events\peacekeeper.npctype [NEW] npcs\events\rivalbountyhunter.npctype [NEW] npcs\events\spacecheesemerchant.npctype [NEW] npcs\outpost\captainnoble.npctype [NEW] npcs\space\peacekeepervillager.npctype npcs\space\spacevillager.npctype objects\ancient\monolithgate\monolithgate.animation objects\ancient\monolithgate\monolithgate.object [NEW] objects\ancient\monolithgate\keys\apex.frames [NEW] objects\ancient\monolithgate\keys\apex.png [NEW] objects\ancient\monolithgate\keys\avian.frames [NEW] objects\ancient\monolithgate\keys\avian.png [NEW] objects\ancient\monolithgate\keys\floran.frames [NEW] objects\ancient\monolithgate\keys\floran.png [NEW] objects\ancient\monolithgate\keys\glitch.frames [NEW] objects\ancient\monolithgate\keys\glitch.png [NEW] objects\ancient\monolithgate\keys\human.frames [NEW] objects\ancient\monolithgate\keys\human.png [NEW] objects\ancient\monolithgate\keys\hylotl.frames [NEW] objects\ancient\monolithgate\keys\hylotl.png objects\apex\apexofficechair\apexofficechair.object objects\biome\scorchedcity\explosivebarrel\explosivebarrel.object [NEW] objects\cultist\cultistairlockdoor\cultistairlockdoor.frames [NEW] objects\cultist\cultistairlockdoor\cultistairlockdoor.object [NEW] objects\cultist\cultistairlockdoor\cultistairlockdoor.png [NEW] objects\cultist\cultistairlockdoor\cultistairlockdooricon.png [NEW] objects\cultist\cultistairlockhatch\cultistairlockhatch.frames [NEW] objects\cultist\cultistairlockhatch\cultistairlockhatch.object [NEW] objects\cultist\cultistairlockhatch\cultistairlockhatch.png [NEW] objects\cultist\cultistairlockhatch\cultistairlockhatchicon.png [NEW] objects\cultist\cultistaltar\cultistaltar.animation [NEW] objects\cultist\cultistaltar\cultistaltar.frames [NEW] objects\cultist\cultistaltar\cultistaltar.object [NEW] objects\cultist\cultistaltar\cultistaltar.png [NEW] objects\cultist\cultistaltar\randomfountainicon.png [NEW] objects\cultist\cultistbannerlarge\cultistbannerlarge.object [NEW] objects\cultist\cultistbannerlarge\cultistbannerlarge.png [NEW] objects\cultist\cultistbannerlarge\cultistbannerlargeicon.png [NEW] objects\cultist\cultistbannerlarge\default.frames [NEW] objects\cultist\cultistchest\cultistchest.frames [NEW] objects\cultist\cultistchest\cultistchest.object [NEW] objects\cultist\cultistchest\cultistchest.png [NEW] objects\cultist\cultistchest\cultistchesticon.png [NEW] objects\cultist\cultistchest\cultistchestlit.frames [NEW] objects\cultist\cultistchest\cultistchestlit.png [NEW] objects\cultist\cultistdoor\cultistdoor.frames [NEW] objects\cultist\cultistdoor\cultistdoor.object [NEW] objects\cultist\cultistdoor\cultistdoor.png [NEW] objects\cultist\cultistdoor\icon.png [NEW] objects\events\extractordrill\extractordrill.animation [NEW] objects\events\extractordrill\extractordrill.lua [NEW] objects\events\extractordrill\extractordrill.object [NEW] objects\events\extractordrill\extractordrill.png [NEW] objects\events\extractordrill\extractordrillbg.png [NEW] objects\events\extractordrill\extractordrillcog.frames [NEW] objects\events\extractordrill\extractordrillcog.png [NEW] objects\events\extractordrill\extractordrillrack.png objects\floran\floranbench\floranbench.object objects\generic\mannequin\mannequin.lua objects\generic\metalbarrel2b\metalbarrel2bicon.png objects\glitch\toxicwastebarrel\toxicwastebarrel.object objects\human\bunkercabinet1\bunkercabinet1.png objects\human\bunkerconsole1\bunkerconsole1.object objects\human\bunkerconsole2\bunkerconsole2.png objects\human\bunkerconsole2\bunkerconsole2lit.png objects\human\bunkercorner\bunkercornergroundleft.png objects\human\bunkercorner\bunkercornergroundright.png objects\human\bunkercorner\bunkercornerleft.png objects\human\bunkercorner\bunkercornerright.png objects\human\bunkerdisplay2\bunkerdisplay2.png objects\human\bunkerdisplay2\bunkerdisplay2leftlit.png objects\human\bunkerdisplay2\bunkerdisplay2leftpreview.png objects\human\bunkerdisplay2\bunkerdisplay2rightlit.png objects\human\bunkerdisplay2\bunkerdisplay2rightpreview.png objects\human\bunkerpanel1\bunkerpanel1.object objects\human\bunkerpanel2\bunkerpanel2.object objects\human\bunkerpanel3\bunkerpanel3.object objects\human\bunkertable3\bunkertable3.object objects\human\microwave\microwave.png objects\human\microwave\microwavelit.png objects\hylotl\greenredlight\greenredlight.object objects\mission\apexmission\bigapescreen\bigapescreen.object [NEW] objects\mission\hangingguardian\hangingguardian.frames [NEW] objects\mission\hangingguardian\hangingguardian.object [NEW] objects\mission\hangingguardian\hangingguardian.png [NEW] objects\mission\hangingguardian\hangingguardianicon.png [NEW] objects\mission\hangingguardian\hangingguardianlit.frames [NEW] objects\mission\hangingguardian\hangingguardianlit.png [NEW] objects\mission\mechplatform\mechplatform.frames [NEW] objects\mission\mechplatform\mechplatform.lua [NEW] objects\mission\mechplatform\mechplatform.object [NEW] objects\mission\mechplatform\mechplatform.png [NEW] objects\mission\mechplatform\mechplatformicon.png [NEW] objects\mission\mechplatform\mechplatformlit.frames [NEW] objects\mission\mechplatform\mechplatformlit.png objects\mission\miningpowersign\miningpowersign.object [NEW] objects\neon\neonhologram\neonhologram.animation [NEW] objects\neon\neonhologram\neonhologram.frames [NEW] objects\neon\neonhologram\neonhologram.object [NEW] objects\neon\neonhologram\neonhologram.png [NEW] objects\neon\neonhologram\neonhologramicon.png [NEW] objects\neon\neonhologram\neonhologramlit.frames [NEW] objects\neon\neonhologram\neonhologramlit.png [NEW] objects\neon\neonlamppost\neonlamppost.frames [NEW] objects\neon\neonlamppost\neonlamppost.object [NEW] objects\neon\neonlamppost\neonlamppost.png [NEW] objects\neon\neonlamppost\neonlampposticon.png [NEW] objects\neon\neonlamppost\neonlamppostlit.frames [NEW] objects\neon\neonlamppost\neonlamppostlit.png [NEW] objects\neon\neonlight\neonlight.frames [NEW] objects\neon\neonlight\neonlight.object [NEW] objects\neon\neonlight\neonlight.png [NEW] objects\neon\neonlight\neonlighticon.png [NEW] objects\neon\neonlight\neonlightlit.frames [NEW] objects\neon\neonlight\neonlightlit.png [NEW] objects\neon\neonpeacekeeperemblem\neonpeacekeeperemblem.frames [NEW] objects\neon\neonpeacekeeperemblem\neonpeacekeeperemblem.object [NEW] objects\neon\neonpeacekeeperemblem\neonpeacekeeperemblem.png [NEW] objects\neon\neonpeacekeeperemblem\neonpeacekeeperemblemicon.png [NEW] objects\neon\neonpeacekeeperemblem\neonpeacekeeperemblemlit.frames [NEW] objects\neon\neonpeacekeeperemblem\neonpeacekeeperemblemlit.png [NEW] objects\neon\neonstore\icon.png [NEW] objects\neon\neonstore\neonstore.frames [NEW] objects\neon\neonstore\neonstore.object [NEW] objects\neon\neonstore\neonstore.png [NEW] objects\neon\neonstore\neonstore_fullbright.frames [NEW] objects\neon\neonstore\neonstore_fullbright.png [NEW] objects\neon\neontriangle\neontriangle.frames [NEW] objects\neon\neontriangle\neontriangle.object [NEW] objects\neon\neontriangle\neontriangle.png [NEW] objects\neon\neontriangle\neontriangleicon.png [NEW] objects\neon\neontriangle\neontrianglelit.frames [NEW] objects\neon\neontriangle\neontrianglelit.png [NEW] objects\office\officecabinet\default.frames [NEW] objects\office\officecabinet\officecabinet.object [NEW] objects\office\officecabinet\officecabinet.png [NEW] objects\office\officecabinet\officecabineticon.png [NEW] objects\office\officecomputer\default.frames [NEW] objects\office\officecomputer\officecomputer.animation [NEW] objects\office\officecomputer\officecomputer.object [NEW] objects\office\officecomputer\officecomputer.png [NEW] objects\office\officecomputer\officecomputericon.png [NEW] objects\office\officecomputer\officecomputerlit.png [NEW] objects\office\officedesk\officedesk.frames [NEW] objects\office\officedesk\officedesk.object [NEW] objects\office\officedesk\officedesk.png [NEW] objects\office\officedesk\officedeskicon.png [NEW] objects\office\officelamp\officelamp.frames [NEW] objects\office\officelamp\officelamp.object [NEW] objects\office\officelamp\officelamp.png [NEW] objects\office\officelamp\officelampicon.png [NEW] objects\office\officelamp\officelamplit.frames [NEW] objects\office\officelamp\officelamplit.png [NEW] objects\office\officenoticeboard\officenoticeboard.frames [NEW] objects\office\officenoticeboard\officenoticeboard.object [NEW] objects\office\officenoticeboard\officenoticeboard.png [NEW] objects\office\officenoticeboard\officenoticeboardicon.png [NEW] objects\office\officescanner\default.frames [NEW] objects\office\officescanner\officescanner.object [NEW] objects\office\officescanner\officescanner.png [NEW] objects\office\officescanner\officescannericon.png [NEW] objects\office\officeserver\default.frames [NEW] objects\office\officeserver\officeserver.object [NEW] objects\office\officeserver\officeserver.png [NEW] objects\office\officeserver\officeservericon.png [NEW] objects\office\officeserver\officeserverlit.png [NEW] objects\office\officestapler\default.frames [NEW] objects\office\officestapler\officestapler.object [NEW] objects\office\officestapler\officestapler.png [NEW] objects\office\officestapler\officestaplericon.png [NEW] objects\office\officetable\officetable.frames [NEW] objects\office\officetable\officetable.object [NEW] objects\office\officetable\officetable.png [NEW] objects\office\officetable\officetableicon.png [NEW] objects\outpost\bountyboard\bountyboard.frames [NEW] objects\outpost\bountyboard\bountyboard.lua [NEW] objects\outpost\bountyboard\bountyboard.object [NEW] objects\outpost\bountyboard\bountyboard.png [NEW] objects\outpost\bountyboard\bountyboardicon.png [NEW] objects\outpost\bountyboard\bountyboard_lit.frames [NEW] objects\outpost\bountyboard\bountyboard_lit.png objects\outpost\frogfurnishing\frogfurnishing.lua objects\outpost\frogfurnishing\frogfurnishing.object [NEW] objects\outpost\outpostpeacekeeperposter\outpostpeacekeeperposter.frames [NEW] objects\outpost\outpostpeacekeeperposter\outpostpeacekeeperposter.object [NEW] objects\outpost\outpostpeacekeeperposter\outpostpeacekeeperposter.png [NEW] objects\outpost\outpostpeacekeeperposter\outpostpeacekeeperpostericon.png objects\outpost\outpostsmallmonitor\outpostsmallmonitor.frames objects\outpost\outpostsmallmonitor\outpostsmallmonitor.object objects\outpost\penguinbar\penguinbartop2.object objects\outpost\penguinweaponshop\penguinweaponshop.lua objects\outpost\treasuredtrophies\treasuredtrophies.object [NEW] objects\peacekeeper\peacekeeperchair\peacekeeperchair.frames [NEW] objects\peacekeeper\peacekeeperchair\peacekeeperchair.object [NEW] objects\peacekeeper\peacekeeperchair\peacekeeperchair.png [NEW] objects\peacekeeper\peacekeeperchair\peacekeeperchairicon.png [NEW] objects\peacekeeper\peacekeepercomputer\peacekeepercomputer.animation [NEW] objects\peacekeeper\peacekeepercomputer\peacekeepercomputer.frames [NEW] objects\peacekeeper\peacekeepercomputer\peacekeepercomputer.object [NEW] objects\peacekeeper\peacekeepercomputer\peacekeepercomputer.png [NEW] objects\peacekeeper\peacekeepercomputer\peacekeepercomputericon.png [NEW] objects\peacekeeper\peacekeepercomputer\peacekeepercomputerlit.frames [NEW] objects\peacekeeper\peacekeepercomputer\peacekeepercomputerlit.png [NEW] objects\peacekeeper\peacekeeperdesk\icon.png [NEW] objects\peacekeeper\peacekeeperdesk\peacekeeperdesk.frames [NEW] objects\peacekeeper\peacekeeperdesk\peacekeeperdesk.object [NEW] objects\peacekeeper\peacekeeperdesk\peacekeeperdesk.png [NEW] objects\peacekeeper\peacekeeperdoor\peacekeeperdoor.frames [NEW] objects\peacekeeper\peacekeeperdoor\peacekeeperdoor.object [NEW] objects\peacekeeper\peacekeeperdoor\peacekeeperdoor.png [NEW] objects\peacekeeper\peacekeeperdoor\peacekeeperdooricon.png [NEW] objects\peacekeeper\peacekeeperemblem\peacekeeperemblem.frames [NEW] objects\peacekeeper\peacekeeperemblem\peacekeeperemblem.object [NEW] objects\peacekeeper\peacekeeperemblem\peacekeeperemblem.png [NEW] objects\peacekeeper\peacekeeperemblem\peacekeeperemblem2.frames [NEW] objects\peacekeeper\peacekeeperemblem\peacekeeperemblem2.object [NEW] objects\peacekeeper\peacekeeperemblem\peacekeeperemblem2.png [NEW] objects\peacekeeper\peacekeeperemblem\peacekeeperemblemicon.png [NEW] objects\peacekeeper\peacekeeperfurnishings\peacekeeperfurnishings.frames [NEW] objects\peacekeeper\peacekeeperfurnishings\peacekeeperfurnishings.object [NEW] objects\peacekeeper\peacekeeperfurnishings\peacekeeperfurnishings.png [NEW] objects\peacekeeper\peacekeeperfurnishings\peacekeeperfurnishingsicon.png [NEW] objects\peacekeeper\peacekeeperlamppost\peacekeeperlamppost.animation [NEW] objects\peacekeeper\peacekeeperlamppost\peacekeeperlamppost.frames [NEW] objects\peacekeeper\peacekeeperlamppost\peacekeeperlamppost.object [NEW] objects\peacekeeper\peacekeeperlamppost\peacekeeperlamppost.png [NEW] objects\peacekeeper\peacekeeperlamppost\peacekeeperlampposticon.png [NEW] objects\peacekeeper\peacekeeperlamppost\peacekeeperlamppostlit.frames [NEW] objects\peacekeeper\peacekeeperlamppost\peacekeeperlamppostlit.png [NEW] objects\peacekeeper\peacekeepermug\peacekeepermug.frames [NEW] objects\peacekeeper\peacekeepermug\peacekeepermug.object [NEW] objects\peacekeeper\peacekeepermug\peacekeepermug.png [NEW] objects\peacekeeper\peacekeepermug\peacekeepermugicon.png [NEW] objects\peacekeeper\peacekeepernotes\peacekeepernotes.frames [NEW] objects\peacekeeper\peacekeepernotes\peacekeepernotes.object [NEW] objects\peacekeeper\peacekeepernotes\peacekeepernotes.png [NEW] objects\peacekeeper\peacekeepernotes\peacekeepernotesicon.png [NEW] objects\peacekeeper\peacekeeperpainting\peacekeeperpainting.frames [NEW] objects\peacekeeper\peacekeeperpainting\peacekeeperpainting.object [NEW] objects\peacekeeper\peacekeeperpainting\peacekeeperpainting.png [NEW] objects\peacekeeper\peacekeeperpainting\peacekeeperpaintingicon.png [NEW] objects\peacekeeper\peacekeeperposter1\peacekeeperposter1.frames [NEW] objects\peacekeeper\peacekeeperposter1\peacekeeperposter1.object [NEW] objects\peacekeeper\peacekeeperposter1\peacekeeperposter1.png [NEW] objects\peacekeeper\peacekeeperposter1\peacekeeperposter1icon.png [NEW] objects\peacekeeper\peacekeeperposter2\peacekeeperposter2.frames [NEW] objects\peacekeeper\peacekeeperposter2\peacekeeperposter2.object [NEW] objects\peacekeeper\peacekeeperposter2\peacekeeperposter2.png [NEW] objects\peacekeeper\peacekeeperposter2\peacekeeperposter2icon.png [NEW] objects\peacekeeper\peacekeeperstore\icon.png [NEW] objects\peacekeeper\peacekeeperstore\peacekeeperstore.frames [NEW] objects\peacekeeper\peacekeeperstore\peacekeeperstore.object [NEW] objects\peacekeeper\peacekeeperstore\peacekeeperstore.png [NEW] objects\peacekeeper\peacekeeperstore\peacekeeperstore2.frames [NEW] objects\peacekeeper\peacekeeperstore\peacekeeperstore2.object [NEW] objects\peacekeeper\peacekeeperstore\peacekeeperstore2.png [NEW] objects\peacekeeper\peacekeeperstore\peacekeeperstore3.frames [NEW] objects\peacekeeper\peacekeeperstore\peacekeeperstore3.object [NEW] objects\peacekeeper\peacekeeperstore\peacekeeperstore3.png [NEW] objects\peacekeeper\peacekeeperstore\peacekeeperstore_fullbright.frames [NEW] objects\peacekeeper\peacekeeperstore\peacekeeperstore_fullbright.png [NEW] objects\peacekeeper\peacekeepertable\peacekeepertable.frames [NEW] objects\peacekeeper\peacekeepertable\peacekeepertable.object [NEW] objects\peacekeeper\peacekeepertable\peacekeepertable.png [NEW] objects\peacekeeper\peacekeepertable\peacekeepertableicon.png [NEW] objects\peacekeeper\peacekeepervendingmachine\default.frames [NEW] objects\peacekeeper\peacekeepervendingmachine\peacekeepervendingmachine.object [NEW] objects\peacekeeper\peacekeepervendingmachine\peacekeepervendingmachine.png [NEW] objects\peacekeeper\peacekeepervendingmachine\peacekeepervendingmachineicon.png [NEW] objects\peacekeeper\peacekeepervendingmachine\peacekeepervendingmachine_left.png objects\ship\apexshiplight\apexshiplight.object objects\space\astrocabinet\astrocabinet.object objects\spawner\colonydeed\colonydeed.lua [NEW] objects\teleporter\peacekeeperteleporter\peacekeeperteleporter.frames [NEW] objects\teleporter\peacekeeperteleporter\peacekeeperteleporter.object [NEW] objects\teleporter\peacekeeperteleporter\peacekeeperteleporter.png [NEW] objects\teleporter\peacekeeperteleporter\peacekeeperteleportericon.png [NEW] objects\teleporter\peacekeeperteleporter\peacekeeperteleporterlit.frames [NEW] objects\teleporter\peacekeeperteleporter\peacekeeperteleporterlit.png objects\themed\astronaut\earthmodel\earthmodel.object [NEW] objects\themed\egyptian\egyptianbed\egyptianbed.frames [NEW] objects\themed\egyptian\egyptianbed\egyptianbed.object [NEW] objects\themed\egyptian\egyptianbed\egyptianbed.png [NEW] objects\themed\egyptian\egyptianbed\egyptianbedcover.png [NEW] objects\themed\egyptian\egyptianbed\egyptianbedicon.png [NEW] objects\themed\egyptian\egyptianchair\egyptianchair.frames [NEW] objects\themed\egyptian\egyptianchair\egyptianchair.object [NEW] objects\themed\egyptian\egyptianchair\egyptianchair.png [NEW] objects\themed\egyptian\egyptianchair\egyptianchaircover.png [NEW] objects\themed\egyptian\egyptianchair\egyptianchairicon.png [NEW] objects\themed\egyptian\egyptiancrest\egyptiancrest.frames [NEW] objects\themed\egyptian\egyptiancrest\egyptiancrest.object [NEW] objects\themed\egyptian\egyptiancrest\egyptiancrest.png [NEW] objects\themed\egyptian\egyptiancrest\egyptiancresticon.png [NEW] objects\themed\egyptian\egyptianlamp\egyptianlamp.png [NEW] objects\themed\egyptian\egyptianlamp\egyptianlamp_fullbright.png [NEW] objects\themed\egyptian\egyptianpillar\egyptianpillar.frames [NEW] objects\themed\egyptian\egyptianpillar\egyptianpillar.object [NEW] objects\themed\egyptian\egyptianpillar\egyptianpillar.png [NEW] objects\themed\egyptian\egyptianpillar\egyptianpillaricon.png [NEW] objects\themed\egyptian\egyptianstatuette\egyptianstatuette.frames [NEW] objects\themed\egyptian\egyptianstatuette\egyptianstatuette.object [NEW] objects\themed\egyptian\egyptianstatuette\egyptianstatuette.png [NEW] objects\themed\egyptian\egyptianstatuette\egyptianstatuetteicon.png [NEW] objects\themed\egyptian\egyptiantable\egyptiantable.frames [NEW] objects\themed\egyptian\egyptiantable\egyptiantable.object [NEW] objects\themed\egyptian\egyptiantable\egyptiantable.png [NEW] objects\themed\egyptian\egyptiantable\egyptiantableicon.png objects\tiered\tier1spotlight\default.frames objects\tiered\tier1spotlight\tier1spotlightceiling1.png objects\tiered\tier1spotlight\tier1spotlightceiling2.png objects\tiered\tier1spotlight\tier1spotlightceilingleft1.png objects\tiered\tier1spotlight\tier1spotlightceilingleft2.png objects\tiered\tier1spotlight\tier1spotlightceilingright1.png objects\tiered\tier1spotlight\tier1spotlightceilingright2.png objects\tiered\tier1spotlight\tier1spotlightground1.png objects\tiered\tier1spotlight\tier1spotlightground2.png objects\tiered\tier1spotlight\tier1spotlightgroundleft1.png objects\tiered\tier1spotlight\tier1spotlightgroundleft2.png objects\tiered\tier1spotlight\tier1spotlightgroundright1.png objects\tiered\tier1spotlight\tier1spotlightgroundright2.png objects\tiered\tier1spotlight\tier1spotlightleft1.png objects\tiered\tier1spotlight\tier1spotlightleft2.png objects\tiered\tier1spotlight\tier1spotlightright1.png objects\tiered\tier1spotlight\tier1spotlightright2.png [NEW] objects\wired\keypad\keypad.lua [NEW] objects\wired\keypad\keypad.object [NEW] objects\wired\keypad\keypad.png [NEW] objects\wired\keypad\keypadicon.png [NEW] objects\wired\light\lighttogglebgfullbrightturning.animation objects\wired\logic\dlatch.lua [NEW] parallax\images\cyberspace1\base\1.png [NEW] parallax\images\cyberspace2\base\1.png [NEW] parallax\surface\cyberspace.parallax [NEW] particles\dust2front.particle particles\electricswoosh1.particle [NEW] particles\firebackspark.particle [NEW] particles\rocketbarreldownpuff.particle [NEW] particles\tinyrockettrail.particle [NEW] particles\shards\metalshard.particle projectiles\physics.config [NEW] projectiles\activeitems\stunmine\default.frames [NEW] projectiles\activeitems\stunmine\stunmine.png [NEW] projectiles\activeitems\stunmine\stunmine.projectile [NEW] projectiles\activeitems\stunmine\stunmineprojectile.lua [NEW] projectiles\activeitems\stunzone\default.frames [NEW] projectiles\activeitems\stunzone\stunzone.png [NEW] projectiles\activeitems\stunzone\stunzone.projectile projectiles\boss\eyeboss\spacemonsterspawner.lua [NEW] projectiles\boss\swansong\ophanimspawner\ophanimspawner.frames [NEW] projectiles\boss\swansong\ophanimspawner\ophanimspawner.lua [NEW] projectiles\boss\swansong\ophanimspawner\ophanimspawner.png [NEW] projectiles\boss\swansong\ophanimspawner\ophanimspawner.projectile [NEW] projectiles\boss\swansong\swansongbolt\default.frames [NEW] projectiles\boss\swansong\swansongbolt\swansongbolt.png [NEW] projectiles\boss\swansong\swansongbolt\swansongbolt.projectile [NEW] projectiles\boss\swansong\swansongdashswoosh\default.frames [NEW] projectiles\boss\swansong\swansongdashswoosh\swansongdashswoosh.png [NEW] projectiles\boss\swansong\swansongdashswoosh\swansongdashswoosh.projectile [NEW] projectiles\boss\swansong\swansongrocket\default.frames [NEW] projectiles\boss\swansong\swansongrocket\swansongrocket.lua [NEW] projectiles\boss\swansong\swansongrocket\swansongrocket.png [NEW] projectiles\boss\swansong\swansongrocket\swansongrocket.projectile [NEW] projectiles\boss\swansong\swansongslashswoosh\default.frames [NEW] projectiles\boss\swansong\swansongslashswoosh\swansongslashswoosh.png [NEW] projectiles\boss\swansong\swansongslashswoosh\swansongslashswoosh.projectile [NEW] projectiles\boss\swansong\wallmelt\default.frames [NEW] projectiles\boss\swansong\wallmelt\wallmelt.png [NEW] projectiles\boss\swansong\wallmelt\wallmelt.projectile [NEW] projectiles\events\spacepod\monsterspacepod.lua [NEW] projectiles\events\spacepod\monsterspacepod.projectile [NEW] projectiles\events\spacepod\spacepod.frames [NEW] projectiles\events\spacepod\spacepod.png [NEW] projectiles\explosions\vsmallregularexplosion\capsuleexplosion.config projectiles\mech\mechenergypickup\mechenergypickup.projectile [NEW] projectiles\vehicles\dropship\capsule\capsule.frames [NEW] projectiles\vehicles\dropship\capsule\capsule.lua [NEW] projectiles\vehicles\dropship\capsule\capsule.png [NEW] projectiles\vehicles\dropship\capsule\capsule.projectile quests\quests.config [NEW] quests\bounty\bounty.config [NEW] quests\bounty\bounty.lua [NEW] quests\bounty\bountyassignment.lua [NEW] quests\bounty\bountyassignment.questtemplate [NEW] quests\bounty\bounty_gen.lua [NEW] quests\bounty\bounty_gen.questtemplate [NEW] quests\bounty\bounty_mission.questtemplate [NEW] quests\bounty\bounty_monsters.config [NEW] quests\bounty\bounty_portraits.lua [NEW] quests\bounty\capture_bounty.questtemplate [NEW] quests\bounty\capture_ship_bounty.questtemplate [NEW] quests\bounty\capture_space_bounty.questtemplate [NEW] quests\bounty\clue_bounties.config [NEW] quests\bounty\clue_items.config [NEW] quests\bounty\clue_npcs.config [NEW] quests\bounty\clue_objects.config [NEW] quests\bounty\cultist_mission1.questtemplate [NEW] quests\bounty\dungeons.config [NEW] quests\bounty\find_clue_item.questtemplate [NEW] quests\bounty\find_clue_npc.questtemplate [NEW] quests\bounty\find_clue_object.questtemplate [NEW] quests\bounty\find_space_clue_item.questtemplate [NEW] quests\bounty\find_space_clue_npc.questtemplate [NEW] quests\bounty\find_space_clue_object.questtemplate [NEW] quests\bounty\gang.config [NEW] quests\bounty\generator.config [NEW] quests\bounty\kill_bounty_monster.questtemplate [NEW] quests\bounty\pre_bounty.lua [NEW] quests\bounty\pre_bounty_alive.questtemplate [NEW] quests\bounty\pre_bounty_capstone.questtemplate [NEW] quests\bounty\pre_bounty_dead.questtemplate [NEW] quests\bounty\pre_bounty_doa.questtemplate [NEW] quests\bounty\pre_bounty_minor_monster.questtemplate [NEW] quests\bounty\pre_bounty_minor_npc.questtemplate [NEW] quests\bounty\scan_planets.questtemplate [NEW] quests\bounty\stages.lua quests\generated\locations.config quests\scripts\conditions\scanning.lua quests\story\bootship.questtemplate quests\story\protectorate.questtemplate [NEW] radiomessages\bounty.radiomessages radiomessages\missions.radiomessages radiomessages\tutorial.radiomessages [NEW] recipes\mission\cultistmission1\cultistairlock.recipe [NEW] recipes\mission\cultistmission1\cultistairlockdoor.recipe [NEW] recipes\mission\cultistmission1\cultistairlockhatch.recipe [NEW] recipes\mission\cultistmission1\cultistbannerlarge.recipe [NEW] recipes\mission\cultistmission1\cultistchest.recipe [NEW] recipes\mission\cultistmission1\cultistdoor.recipe [NEW] recipes\peacekeeperstore\mechbodypeacekeeper.recipe [NEW] recipes\peacekeeperstore\peacekeeperchest.recipe [NEW] recipes\peacekeeperstore\peacekeeperpants.recipe [NEW] scripts\async.lua [NEW] scripts\bountygeneration.lua scripts\rect.lua scripts\stateMachine.lua scripts\util.lua scripts\vec2.lua [NEW] scripts\actions\bounty.lua scripts\actions\dialog.lua scripts\actions\merchant.lua scripts\actions\movement.lua scripts\actions\npc.lua scripts\actions\overrides.lua scripts\actions\quests.lua scripts\actions\world.lua scripts\actions\npc\tonauac.lua scripts\activeitem\stances.lua scripts\companions\capturable.lua scripts\deployment\playermechdeployment.lua sfx\instruments\drumkit\26.ogg sfx\instruments\drumkit\27.ogg sfx\instruments\drumkit\28.ogg sfx\instruments\drumkit\29.ogg sfx\instruments\drumkit\30.ogg sfx\instruments\drumkit\31.ogg sfx\instruments\drumkit\32.ogg sfx\instruments\drumkit\33a1.ogg sfx\instruments\drumkit\34.ogg sfx\instruments\drumkit\35.ogg sfx\instruments\drumkit\36.ogg sfx\instruments\drumkit\37.ogg sfx\instruments\drumkit\38.ogg sfx\instruments\drumkit\39.ogg sfx\instruments\drumkit\40.ogg sfx\instruments\drumkit\41.ogg sfx\instruments\drumkit\42.ogg sfx\instruments\drumkit\43.ogg sfx\instruments\drumkit\44.ogg sfx\instruments\drumkit\45a2.ogg sfx\instruments\drumkit\46.ogg sfx\instruments\drumkit\47.ogg sfx\instruments\drumkit\48.ogg sfx\instruments\drumkit\49.ogg sfx\instruments\drumkit\50.ogg sfx\instruments\drumkit\51.ogg sfx\instruments\drumkit\52.ogg sfx\instruments\drumkit\53.ogg sfx\instruments\drumkit\54.ogg sfx\instruments\drumkit\55.ogg sfx\instruments\drumkit\56.ogg sfx\instruments\drumkit\57a3.ogg sfx\instruments\drumkit\58.ogg sfx\instruments\drumkit\59.ogg sfx\instruments\drumkit\60.ogg sfx\instruments\drumkit\61.ogg sfx\instruments\drumkit\62.ogg sfx\instruments\drumkit\63.ogg sfx\instruments\drumkit\64.ogg sfx\instruments\drumkit\65.ogg sfx\instruments\drumkit\66.ogg sfx\instruments\drumkit\67.ogg sfx\instruments\drumkit\68.ogg sfx\instruments\drumkit\69a4.ogg sfx\instruments\drumkit\70.ogg sfx\instruments\drumkit\71.ogg sfx\instruments\drumkit\72.ogg sfx\instruments\drumkit\73.ogg sfx\instruments\drumkit\74.ogg sfx\instruments\drumkit\75.ogg sfx\instruments\drumkit\76.ogg sfx\instruments\drumkit\77.ogg sfx\instruments\drumkit\78.ogg sfx\instruments\drumkit\79.ogg sfx\instruments\drumkit\80.ogg sfx\instruments\drumkit\81a5.ogg sfx\instruments\drumkit\82.ogg sfx\instruments\drumkit\83.ogg sfx\instruments\drumkit\84.ogg sfx\instruments\drumkit\85.ogg sfx\instruments\drumkit\86.ogg sfx\instruments\drumkit\87.ogg sfx\instruments\drumkit\88.ogg sfx\instruments\dulcimer\a0.ogg sfx\instruments\dulcimer\a1.ogg sfx\instruments\dulcimer\a2.ogg sfx\instruments\dulcimer\a3.ogg sfx\instruments\dulcimer\a4.ogg sfx\instruments\dulcimer\a5.ogg sfx\instruments\dulcimer\a6.ogg sfx\instruments\dulcimer\a7.ogg species\novakid.species species\novakidnamegen.config [NEW] stagehands\bountymanager.lua [NEW] stagehands\bountymanager.stagehand stagehands\objecttracker.lua stagehands\objecttracker.stagehand stagehands\questlocation.lua [NEW] stagehands\waypoint.lua stagehands\waypoint.stagehand [NEW] stagehands\bounty\cluespawn.stagehand [NEW] stagehands\bounty\interactobject.stagehand [NEW] stagehands\bounty\monsterspawn.stagehand [NEW] stagehands\bounty\npcspawn.stagehand [NEW] stagehands\bounty\vaultitemspawn.stagehand [NEW] stagehands\bounty\vaultnpcspawn.stagehand [NEW] stagehands\events\banditattack.stagehand [NEW] stagehands\events\dropship.lua [NEW] stagehands\events\dropship.stagehand [NEW] stagehands\events\envprobe.stagehand [NEW] stagehands\events\npcattack.lua [NEW] stagehands\events\peacekeeperattack.stagehand [NEW] stagehands\events\rivalbountyhunter.stagehand [NEW] stagehands\events\ruininvasion.lua [NEW] stagehands\events\ruininvasion.stagehand [NEW] stagehands\events\spacepod.lua [NEW] stagehands\events\spacepod.stagehand [NEW] stagehands\events\spawnmonster.lua stats\fishing_primary.lua stats\monster_primary.lua stats\npc_primary.lua stats\player_primary.lua stats\spacemonster_primary.lua [NEW] stats\effects\arrested\arrested.lua [NEW] stats\effects\arrested\arrested.statuseffect [NEW] stats\effects\arresting\arresting.animation [NEW] stats\effects\arresting\arresting.lua [NEW] stats\effects\arresting\arresting.statuseffect stats\effects\beamin\beamin.lua stats\effects\beamout\beamout.lua stats\effects\beamout\beamout.statuseffect stats\effects\beamout\beamoutanddie.statuseffect stats\effects\beamout\beamoutandteleport.statuseffect [NEW] stats\effects\capturebeamout\capturebeamout.animation [NEW] stats\effects\capturebeamout\capturebeamout.frames [NEW] stats\effects\capturebeamout\capturebeamout.lua [NEW] stats\effects\capturebeamout\capturebeamout.png [NEW] stats\effects\capturebeamout\capturebeamout.statuseffect [NEW] stats\effects\maxprotection\loweredprotection.statuseffect [NEW] stats\effects\maxprotection\maxprotectionnogrit.statuseffect [NEW] stats\effects\neon\neon.lua [NEW] stats\effects\neon\neon.statuseffect [NEW] stats\effects\techstun\techstun.lua [NEW] stats\effects\techstun\techstun.statuseffect [NEW] stats\effects\ufobeamstun\ufobeamstun.animation [NEW] stats\effects\ufobeamstun\ufobeamstun.lua [NEW] stats\effects\ufobeamstun\ufobeamstun.statuseffect [NEW] stats\effects\wanted\wanted1.statuseffect [NEW] stats\effects\wanted\wanted2.statuseffect [NEW] stats\effects\wanted\wanted3.statuseffect [NEW] stats\effects\wanted\wanted4.statuseffect tiles\classicmaterialtemplate.config tiles\materials\concrete.png tiles\materials\ledgebrick.material tiles\materials\ridgebrick.material [NEW] tiles\materials\slopedglasspanel.material [NEW] tiles\materials\slopedglasspanel.png [NEW] tiles\materials\slopedpolygon.material [NEW] tiles\materials\slopedpolygon.png tilesets\packed\materials.json tilesets\packed\miscellaneous.json tilesets\packed\objects-by-category\breakable.json tilesets\packed\objects-by-category\crafting.json tilesets\packed\objects-by-category\decorative.json tilesets\packed\objects-by-category\door.json tilesets\packed\objects-by-category\furniture.json tilesets\packed\objects-by-category\generic.json tilesets\packed\objects-by-category\light.json tilesets\packed\objects-by-category\other.json tilesets\packed\objects-by-category\playerstation.json tilesets\packed\objects-by-category\storage.json tilesets\packed\objects-by-category\teleporter.json tilesets\packed\objects-by-category\teleportmarker.json tilesets\packed\objects-by-category\wire.json tilesets\packed\objects-by-colonytag\ancient.json tilesets\packed\objects-by-colonytag\avian.json tilesets\packed\objects-by-colonytag\commerce.json [NEW] tilesets\packed\objects-by-colonytag\cultist.json tilesets\packed\objects-by-colonytag\door.json [NEW] tilesets\packed\objects-by-colonytag\egyptian.json tilesets\packed\objects-by-colonytag\electronic.json tilesets\packed\objects-by-colonytag\human.json tilesets\packed\objects-by-colonytag\industrial.json tilesets\packed\objects-by-colonytag\light.json tilesets\packed\objects-by-colonytag\mechanical.json tilesets\packed\objects-by-colonytag\misc.json [NEW] tilesets\packed\objects-by-colonytag\neon.json [NEW] tilesets\packed\objects-by-colonytag\office.json [NEW] tilesets\packed\objects-by-colonytag\peacekeeper.json tilesets\packed\objects-by-colonytag\pretty.json tilesets\packed\objects-by-colonytag\space.json tilesets\packed\objects-by-colonytag\storage.json tilesets\packed\objects-by-colonytag\technology.json tilesets\packed\objects-by-colonytag\wired.json tilesets\packed\objects-by-race\ancient.json tilesets\packed\objects-by-race\apex.json tilesets\packed\objects-by-race\avian.json tilesets\packed\objects-by-race\generic.json tilesets\packed\objects-by-race\human.json tilesets\packed\objects-by-race\novakid.json tilesets\packed\objects-by-type\container.json tilesets\packed\objects-by-type\loungeable.json tilesets\packed\objects-by-type\teleporter.json treasure\common.treasurepools [NEW] treasure\Missions\cultistmission1.treasurepools [NEW] vehicles\dropship\background.png [NEW] vehicles\dropship\blinds.frames [NEW] vehicles\dropship\blinds.png [NEW] vehicles\dropship\bottomthruster.frames [NEW] vehicles\dropship\bottomthruster.png [NEW] vehicles\dropship\cannon.frames [NEW] vehicles\dropship\cannon.png [NEW] vehicles\dropship\dropship.animation [NEW] vehicles\dropship\dropship.lua [NEW] vehicles\dropship\dropship.png [NEW] vehicles\dropship\dropship.vehicle [NEW] vehicles\dropship\dropshipcontrol.lua [NEW] vehicles\dropship\eventdropship.lua vehicles\hoverbike\hoverbike.animation [NEW] vehicles\minitank\body.frames [NEW] vehicles\minitank\body.png [NEW] vehicles\minitank\bodyfront.png [NEW] vehicles\minitank\cannon.png [NEW] vehicles\minitank\minitank.animation [NEW] vehicles\minitank\minitank.lua [NEW] vehicles\minitank\minitank.vehicle [NEW] vehicles\miniufo\humanoidmask.png [NEW] vehicles\miniufo\miniufo.animation [NEW] vehicles\miniufo\miniufo.lua [NEW] vehicles\miniufo\miniufo.png [NEW] vehicles\miniufo\miniufo.vehicle [NEW] vehicles\miniufo\tractorbeam.png vehicles\modularmech\mechparts_body.config vehicles\modularmech\armscripts\beamarm.lua vehicles\modularmech\armscripts\drillarm.lua [NEW] vehicles\modularmech\body\peacekeeper_back.png [NEW] vehicles\modularmech\body\peacekeeper_front.png [NEW] vehicles\modularmech\body\peacekeeper_fullbright.png [NEW] vehicles\sportscar\default.frames [NEW] vehicles\sportscar\jeepbackground.png [NEW] vehicles\sportscar\jeepheadlights.frames [NEW] vehicles\sportscar\jeepheadlights.png [NEW] vehicles\sportscar\sportscar.animation [NEW] vehicles\sportscar\sportscar.lua [NEW] vehicles\sportscar\sportscar.vehicle [NEW] vehicles\sportscar\sportscarforeground.png [NEW] vehicles\sportscar\sportscarfullbright.png [NEW] versioning\MonsterEntity_4_5.lua DIFFS ----- client.config 109,110c109,110 < "luaGcPause" : 1.0, < "luaGcStepMultiplier" : 1.0, --- > "luaGcPause" : 1.2, > "luaGcStepMultiplier" : 1.2, default_actor_movement.config 71c71,73 < "gravityEnabled" : true --- > "gravityEnabled" : true, > > "pathExploreRate" : 50.0 default_movement.config 30c30,32 < "maximumPlatformCorrectionVelocityFactor" : 0.03 --- > "maximumPlatformCorrectionVelocityFactor" : 0.03, > > "restDuration" : 3 dungeon_worlds.config 200a201,215 > "cultistmission1" : { > "primaryDungeon" : "cultistmission1", > "threatLevel" : 6, > "gravity" : 80, > "worldSize" : [2500, 2000], > "dungeonBaseHeight" : 1000, > "dungeonSurfaceHeight" : 810, > "ambientLightLevel" : [32, 32, 32], > "ambientNoises" : "/sfx/environmental/space_loop4.ogg", > "musicTrack" : "/music/arctic-battle2-loop.ogg", > "environmentStatusEffects" : ["dontstarve"], > "worldEdgeForceRegions" : "TopAndBottom", > "biome" : "space" > }, > 297a313,344 > "bountyspaceencounter" : { > "primaryDungeon" : "bountyspacesafehouse", > "threatLevel" : 3, > "gravity" : 0, > "airless" : true, > "worldSize" : [1200, 200], > "dungeonBaseHeight" : 150, > "dungeonSurfaceHeight" : 150, > "ambientLightLevel" : [32, 32, 32], > "ambientNoises" : "/sfx/environmental/space_loop4.ogg", > "musicTrack" : "/music/lava-exploration1.ogg", > "environmentStatusEffects" : ["biomeairless", "dontstarve"], > "worldEdgeForceRegions" : "TopAndBottom", > "biome" : "space" > }, > > "bountyshipencounter" : { > "primaryDungeon" : "bountyshipencounter", > "threatLevel" : 3, > "gravity" : 0, > "airless" : true, > "worldSize" : [1200, 200], > "dungeonBaseHeight" : 150, > "dungeonSurfaceHeight" : 150, > "ambientLightLevel" : [32, 32, 32], > "ambientNoises" : "/sfx/environmental/space_loop4.ogg", > "musicTrack" : "/music/lava-exploration1.ogg", > "environmentStatusEffects" : ["biomeairless", "dontstarve"], > "worldEdgeForceRegions" : "TopAndBottom", > "biome" : "space" > }, > 457a505,584 > "spacestation_peacekeeper1" : { > "primaryDungeon" : "peacekeeperstation1", > "threatLevel" : 1, > "gravity" : 0, > "airless" : true, > "worldSize" : [1200, 500], > "dungeonBaseHeight" : 300, > "dungeonSurfaceHeight" : 300, > "ambientLightLevel" : [32, 32, 32], > "ambientNoises" : "/sfx/environmental/space_loop4.ogg", > "musicTrack" : "/music/tranquility-base.ogg", > "environmentStatusEffects" : ["biomeairless"], > "worldEdgeForceRegions" : "TopAndBottom", > "biome" : "space" > }, > > "spacestation_peacekeeper2" : { > "primaryDungeon" : "peacekeeperstation2", > "threatLevel" : 1, > "gravity" : 0, > "airless" : true, > "worldSize" : [1200, 500], > "dungeonBaseHeight" : 300, > "dungeonSurfaceHeight" : 300, > "ambientLightLevel" : [32, 32, 32], > "ambientNoises" : "/sfx/environmental/space_loop4.ogg", > "musicTrack" : "/music/tranquility-base.ogg", > "environmentStatusEffects" : ["biomeairless"], > "worldEdgeForceRegions" : "TopAndBottom", > "biome" : "space" > }, > > "spacestation_peacekeeper3" : { > "primaryDungeon" : "peacekeeperstation3", > "threatLevel" : 1, > "gravity" : 0, > "airless" : true, > "worldSize" : [1200, 500], > "dungeonBaseHeight" : 300, > "dungeonSurfaceHeight" : 300, > "ambientLightLevel" : [32, 32, 32], > "ambientNoises" : "/sfx/environmental/space_loop4.ogg", > "musicTrack" : "/music/tranquility-base.ogg", > "environmentStatusEffects" : ["biomeairless"], > "worldEdgeForceRegions" : "TopAndBottom", > "biome" : "space" > }, > > "spacestation_peacekeeper4" : { > "primaryDungeon" : "peacekeeperstation4", > "threatLevel" : 1, > "gravity" : 0, > "airless" : true, > "worldSize" : [1200, 500], > "dungeonBaseHeight" : 300, > "dungeonSurfaceHeight" : 300, > "ambientLightLevel" : [32, 32, 32], > "ambientNoises" : "/sfx/environmental/space_loop4.ogg", > "musicTrack" : "/music/tranquility-base.ogg", > "environmentStatusEffects" : ["biomeairless"], > "worldEdgeForceRegions" : "TopAndBottom", > "biome" : "space" > }, > > "spacestation_peacekeeper5" : { > "primaryDungeon" : "peacekeeperstation5", > "threatLevel" : 1, > "gravity" : 0, > "airless" : true, > "worldSize" : [1200, 500], > "dungeonBaseHeight" : 300, > "dungeonSurfaceHeight" : 300, > "ambientLightLevel" : [32, 32, 32], > "ambientNoises" : "/sfx/environmental/space_loop4.ogg", > "musicTrack" : "/music/tranquility-base.ogg", > "environmentStatusEffects" : ["biomeairless"], > "worldEdgeForceRegions" : "TopAndBottom", > "biome" : "space" > }, > 539a667,721 > }, > > "bountylair1" : { > "primaryDungeon" : "bountylair1", > "threatLevel" : 2, > "gravity" : 80, > "worldSize" : [2000, 2000], > "dungeonBaseHeight" : 1100, > "dungeonSurfaceHeight" : 1000, > "ambientLightLevel" : [32, 32, 32], > "biome" : "desert", > "musicTrack" : "/music/i-was-the-sun.ogg", > "environmentStatusEffects" : ["dontstarve"] > }, > > "bountylair2" : { > "primaryDungeon" : "bountylair2", > "threatLevel" : 3, > "gravity" : 80, > "worldSize" : [2000, 2000], > "dungeonBaseHeight" : 1100, > "dungeonSurfaceHeight" : 1000, > "ambientLightLevel" : [32, 32, 32], > "biome" : "snow", > "musicTrack" : "/music/i-was-the-sun.ogg", > "environmentStatusEffects" : ["dontstarve"] > }, > > "bountylair3" : { > "primaryDungeon" : "bountylair3", > "threatLevel" : 5, > "gravity" : 0, > "worldSize" : [1200, 500], > "dungeonBaseHeight" : 300, > "dungeonSurfaceHeight" : 300, > "ambientLightLevel" : [32, 32, 32], > "ambientNoises" : "/sfx/environmental/space_loop4.ogg", > "musicTrack" : "/music/i-was-the-sun.ogg", > "environmentStatusEffects" : ["dontstarve"], > "worldEdgeForceRegions" : "TopAndBottom", > "biome" : "space" > }, > > > "bountylair4" : { > "primaryDungeon" : "bountylair4", > "threatLevel" : 3, > "gravity" : 80, > "worldSize" : [2000, 2000], > "dungeonBaseHeight" : 1200, > "dungeonSurfaceHeight" : 1000, > "ambientLightLevel" : [32, 32, 32], > "biome" : "scorched", > "musicTrack" : "/music/i-was-the-sun.ogg", > "environmentStatusEffects" : ["dontstarve"] instance_worlds.config 703a704,734 > "cultistmission1" : { > "type" : "FloatingDungeon", > "dungeonWorld" : "cultistmission1", > "seed" : 1234, > "spawningEnabled" : false, > "beamUpRule" : "AnywhereWithWarning", > "disableDeathDrops" : true, > > "skyParameters" : { > "dayLength" : 10000, > "surfaceLevel" : 1000, > "spaceLevel" : 3000, > "seed" : -5288806180628666923, > > "skyType" : "barren", > "skyColoring" : { > "mainColor" : [200, 200, 255], > > "morningColors" : [[200, 200, 255], [200, 200, 255]], > "dayColors" : [[200, 200, 255], [200, 200, 255]], > "eveningColors" : [[200, 200, 255], [200, 200, 255]], > "nightColors" : [[200, 200, 255], [200, 200, 255]], > > "morningLightColor" : [120, 120, 120], > "dayLightColor" : [120, 120, 120], > "eveningLightColor" : [120, 120, 120], > "nightLightColor" : [120, 120, 120] > } > } > }, > 892a924,985 > "bountyspaceencounter" : { > "type" : "FloatingDungeon", > "dungeonWorld" : "bountyspaceencounter", > "beamUpRule" : "Anywhere", > "disableDeathDrops" : true, > > "tempWorldDeleteTime" : 600000, > > "skyParameters" : { > "dayLength" : 10000, > "surfaceLevel" : 1000, > "spaceLevel" : 3000, > "seed" : -5288806180628666923, > > "skyType" : "barren", > "skyColoring" : { > "mainColor" : [200, 200, 255], > > "morningColors" : [[200, 200, 255], [200, 200, 255]], > "dayColors" : [[200, 200, 255], [200, 200, 255]], > "eveningColors" : [[200, 200, 255], [200, 200, 255]], > "nightColors" : [[200, 200, 255], [200, 200, 255]], > > "morningLightColor" : [120, 120, 120], > "dayLightColor" : [120, 120, 120], > "eveningLightColor" : [120, 120, 120], > "nightLightColor" : [120, 120, 120] > } > } > }, > > "bountyshipencounter" : { > "type" : "FloatingDungeon", > "dungeonWorld" : "bountyshipencounter", > "beamUpRule" : "Anywhere", > "disableDeathDrops" : true, > > "tempWorldDeleteTime" : 600000, > > "skyParameters" : { > "dayLength" : 10000, > "surfaceLevel" : 1000, > "spaceLevel" : 3000, > "seed" : -5288806180628666923, > > "skyType" : "barren", > "skyColoring" : { > "mainColor" : [200, 200, 255], > > "morningColors" : [[200, 200, 255], [200, 200, 255]], > "dayColors" : [[200, 200, 255], [200, 200, 255]], > "eveningColors" : [[200, 200, 255], [200, 200, 255]], > "nightColors" : [[200, 200, 255], [200, 200, 255]], > > "morningLightColor" : [120, 120, 120], > "dayLightColor" : [120, 120, 120], > "eveningLightColor" : [120, 120, 120], > "nightLightColor" : [120, 120, 120] > } > } > }, > 1238a1332,1492 > "spacestation_peacekeeper1" : { > "type" : "FloatingDungeon", > "dungeonWorld" : "spacestation_peacekeeper1", > "spawningEnabled" : false, > "beamUpRule" : "Anywhere", > "disableDeathDrops" : true, > "persistent" : false, > "useUniverseClock" : true, > > "skyParameters" : { > "dayLength" : 10000, > "surfaceLevel" : 1000, > "spaceLevel" : 3000, > "seed" : -5288806180628666923, > > "skyType" : "barren", > "skyColoring" : { > "mainColor" : [200, 200, 255], > > "morningColors" : [[200, 200, 255], [200, 200, 255]], > "dayColors" : [[200, 200, 255], [200, 200, 255]], > "eveningColors" : [[200, 200, 255], [200, 200, 255]], > "nightColors" : [[200, 200, 255], [200, 200, 255]], > > "morningLightColor" : [120, 120, 120], > "dayLightColor" : [120, 120, 120], > "eveningLightColor" : [120, 120, 120], > "nightLightColor" : [120, 120, 120] > } > } > }, > > "spacestation_peacekeeper2" : { > "type" : "FloatingDungeon", > "dungeonWorld" : "spacestation_peacekeeper2", > "spawningEnabled" : false, > "beamUpRule" : "Anywhere", > "disableDeathDrops" : true, > "persistent" : false, > "useUniverseClock" : true, > > "skyParameters" : { > "dayLength" : 10000, > "surfaceLevel" : 1000, > "spaceLevel" : 3000, > "seed" : -5288806180628666923, > > "skyType" : "barren", > "skyColoring" : { > "mainColor" : [200, 200, 255], > > "morningColors" : [[200, 200, 255], [200, 200, 255]], > "dayColors" : [[200, 200, 255], [200, 200, 255]], > "eveningColors" : [[200, 200, 255], [200, 200, 255]], > "nightColors" : [[200, 200, 255], [200, 200, 255]], > > "morningLightColor" : [120, 120, 120], > "dayLightColor" : [120, 120, 120], > "eveningLightColor" : [120, 120, 120], > "nightLightColor" : [120, 120, 120] > } > } > }, > > "spacestation_peacekeeper3" : { > "type" : "FloatingDungeon", > "dungeonWorld" : "spacestation_peacekeeper3", > "spawningEnabled" : false, > "beamUpRule" : "Anywhere", > "disableDeathDrops" : true, > "persistent" : false, > "useUniverseClock" : true, > > "skyParameters" : { > "dayLength" : 10000, > "surfaceLevel" : 1000, > "spaceLevel" : 3000, > "seed" : -5288806180628666923, > > "skyType" : "barren", > "skyColoring" : { > "mainColor" : [200, 200, 255], > > "morningColors" : [[200, 200, 255], [200, 200, 255]], > "dayColors" : [[200, 200, 255], [200, 200, 255]], > "eveningColors" : [[200, 200, 255], [200, 200, 255]], > "nightColors" : [[200, 200, 255], [200, 200, 255]], > > "morningLightColor" : [120, 120, 120], > "dayLightColor" : [120, 120, 120], > "eveningLightColor" : [120, 120, 120], > "nightLightColor" : [120, 120, 120] > } > } > }, > > "spacestation_peacekeeper4" : { > "type" : "FloatingDungeon", > "dungeonWorld" : "spacestation_peacekeeper4", > "spawningEnabled" : false, > "beamUpRule" : "Anywhere", > "disableDeathDrops" : true, > "persistent" : false, > "useUniverseClock" : true, > > "skyParameters" : { > "dayLength" : 10000, > "surfaceLevel" : 1000, > "spaceLevel" : 3000, > "seed" : -5288806180628666923, > > "skyType" : "barren", > "skyColoring" : { > "mainColor" : [200, 200, 255], > > "morningColors" : [[200, 200, 255], [200, 200, 255]], > "dayColors" : [[200, 200, 255], [200, 200, 255]], > "eveningColors" : [[200, 200, 255], [200, 200, 255]], > "nightColors" : [[200, 200, 255], [200, 200, 255]], > > "morningLightColor" : [120, 120, 120], > "dayLightColor" : [120, 120, 120], > "eveningLightColor" : [120, 120, 120], > "nightLightColor" : [120, 120, 120] > } > } > }, > > "spacestation_peacekeeper5" : { > "type" : "FloatingDungeon", > "dungeonWorld" : "spacestation_peacekeeper5", > "spawningEnabled" : false, > "beamUpRule" : "Anywhere", > "disableDeathDrops" : true, > "persistent" : false, > "useUniverseClock" : true, > > "skyParameters" : { > "dayLength" : 10000, > "surfaceLevel" : 1000, > "spaceLevel" : 3000, > "seed" : -5288806180628666923, > > "skyType" : "barren", > "skyColoring" : { > "mainColor" : [200, 200, 255], > > "morningColors" : [[200, 200, 255], [200, 200, 255]], > "dayColors" : [[200, 200, 255], [200, 200, 255]], > "eveningColors" : [[200, 200, 255], [200, 200, 255]], > "nightColors" : [[200, 200, 255], [200, 200, 255]], > > "morningLightColor" : [120, 120, 120], > "dayLightColor" : [120, 120, 120], > "eveningLightColor" : [120, 120, 120], > "nightLightColor" : [120, 120, 120] > } > } > }, > > 1733a1988,2255 > } > }, > > "cyberspace" : { > "type" : "Terrestrial", > "planetType" : "cyberspace", > "planetSize" : "verysmall", > "beamUpRule" : "AnywhereWithWarning", > "disableDeathDrops" : true, > > "skyParameters" : { > "spaceLevel" : 3000, > "ambientLightLevel" : [255, 255, 255], > "skyType" : "atmospheric", > "skyColoring" : { > "mainColor" : [255, 255, 255], > > "morningColors" : [ [0, 0, 0], [0, 0, 0] ], > "dayColors" : [ [0, 0, 0], [0, 0, 0] ], > "eveningColors" : [ [0, 0, 0], [0, 0, 0] ], > "nightColors" : [ [0, 0, 0], [0, 0, 0] ], > > "morningLightColor" : [255, 255, 255], > "dayLightColor" : [255, 255, 255], > "eveningLightColor" : [255, 255, 255], > "nightLightColor" : [255, 255, 255] > }, > "satellites" : [], > "horizonImages" : [ ], > "dayLength" : 100000, > "surfaceLevel" : 1200, > "seed" : -5288806180628666923 > } > }, > > "bountylair1" : { > "type" : "FloatingDungeon", > "dungeonWorld" : "bountylair1", > "seed" : 1234, > "spawningEnabled" : false, > "beamUpRule" : "AnywhereWithWarning", > "disableDeathDrops" : true, > > "skyParameters" : { > "dayLength" : 10000, > "surfaceLevel" : 1000, > "spaceLevel" : 3000, > "seed" : -5288806180628666923, > > "skyType" : "atmospheric", > "skyColoring" : { > "mainColor" : [200, 200, 255], > > "morningColors" : [[245, 133, 73], [224, 99, 172]], > "dayColors" : [[245, 133, 73], [224, 99, 172]], > "eveningColors" : [[245, 133, 73], [224, 99, 172]], > "nightColors" : [[245, 133, 73], [224, 99, 172]], > > "morningLightColor" : [170, 130, 190], > "dayLightColor" : [170, 130, 190], > "eveningLightColor" : [170, 130, 190], > "nightLightColor" : [170, 130, 190] > }, > > "satellites" : [ { > "pos" : [ 0.310561, 0.35497 ], > "layers" : [ { > "scale" : 0.055, > "image" : "/celestial/system/terrestrial/liquids/water.png" > }, { > "scale" : 0.055, > "image" : "/celestial/system/terrestrial/biomes/forest/maskie3.png?hueshift=-45?addmask=/celestial/system/terrestrial/dynamics/temperate/2.png" > }, { > "scale" : 0.055, > "image" : "/celestial/system/terrestrial/biomes/forest/maskie2.png?hueshift=-45?addmask=/celestial/system/terrestrial/dynamics/temperate/20.png" > }, { > "scale" : 0.055, > "image" : "/celestial/system/terrestrial/biomes/forest/maskie1.png?hueshift=-45?addmask=/celestial/system/terrestrial/dynamics/temperate/5.png" > }, { > "scale" : 0.055, > "image" : "/celestial/system/terrestrial/shadows/9.png" > } ] > } ], > "planet" : { > "pos" : [ 0.00538729, 0.46961 ], > "layers" : [ { > "scale" : 0.15, > "image" : "/celestial/system/gas_giant/gas_giant_base.png?hueshift=-80" > }, { > "scale" : 0.15, > "image" : "/celestial/system/gas_giant/gas_giant_clouds_0.png?hueshift=-70?addmask=/celestial/system/gas_giant/gas_giant_dynamics/3.png+/celestial/system/gas_giant/gas_giant_dynamics/29.png" > }, { > "scale" : 0.15, > "image" : "/celestial/system/gas_giant/gas_giant_clouds_1.png?hueshift=-77?addmask=/celestial/system/gas_giant/gas_giant_dynamics/28.png+/celestial/system/gas_giant/gas_giant_dynamics/29.png" > }, { > "scale" : 0.15, > "image" : "/celestial/system/gas_giant/shadows/9.png" > } ] > }, > "horizonImages" : [ ] > } > }, > > "bountylair2" : { > "type" : "FloatingDungeon", > "dungeonWorld" : "bountylair2", > "seed" : 2017, > "spawningEnabled" : false, > "beamUpRule" : "AnywhereWithWarning", > "disableDeathDrops" : true, > > "skyParameters" : { > "dayLength" : 10000, > "surfaceLevel" : 1000, > "spaceLevel" : 3000, > "seed" : -5288806180628666923, > > "skyType" : "atmospheric", > "skyColoring" : { > "mainColor" : [200, 200, 255], > > "morningColors" : [[29, 129, 228], [51, 94, 176]], > "dayColors" : [[29, 129, 228], [51, 94, 176]], > "eveningColors" : [[29, 129, 228], [51, 94, 176]], > "nightColors" : [[29, 129, 228], [51, 94, 176]], > > "morningLightColor" : [170, 130, 190], > "dayLightColor" : [170, 130, 190], > "eveningLightColor" : [170, 130, 190], > "nightLightColor" : [170, 130, 190] > }, > > "satellites" : [ { > "pos" : [ 0.310561, 0.35497 ], > "layers" : [ { > "scale" : 0.055, > "image" : "/celestial/system/terrestrial/liquids/water.png" > }, { > "scale" : 0.055, > "image" : "/celestial/system/terrestrial/biomes/forest/maskie3.png?hueshift=-45?addmask=/celestial/system/terrestrial/dynamics/temperate/2.png" > }, { > "scale" : 0.055, > "image" : "/celestial/system/terrestrial/biomes/forest/maskie2.png?hueshift=-45?addmask=/celestial/system/terrestrial/dynamics/temperate/20.png" > }, { > "scale" : 0.055, > "image" : "/celestial/system/terrestrial/biomes/forest/maskie1.png?hueshift=-45?addmask=/celestial/system/terrestrial/dynamics/temperate/5.png" > }, { > "scale" : 0.055, > "image" : "/celestial/system/terrestrial/shadows/9.png" > } ] > } ], > "planet" : { > "pos" : [ 0.00538729, 0.46961 ], > "layers" : [ { > "scale" : 0.15, > "image" : "/celestial/system/gas_giant/gas_giant_base.png?hueshift=-80" > }, { > "scale" : 0.15, > "image" : "/celestial/system/gas_giant/gas_giant_clouds_0.png?hueshift=-70?addmask=/celestial/system/gas_giant/gas_giant_dynamics/3.png+/celestial/system/gas_giant/gas_giant_dynamics/29.png" > }, { > "scale" : 0.15, > "image" : "/celestial/system/gas_giant/gas_giant_clouds_1.png?hueshift=-77?addmask=/celestial/system/gas_giant/gas_giant_dynamics/28.png+/celestial/system/gas_giant/gas_giant_dynamics/29.png" > }, { > "scale" : 0.15, > "image" : "/celestial/system/gas_giant/shadows/9.png" > } ] > }, > "horizonImages" : [ ] > } > }, > > "bountylair3" : { > "type" : "FloatingDungeon", > "dungeonWorld" : "bountylair3", > "spawningEnabled" : false, > "beamUpRule" : "AnywhereWithWarning", > "disableDeathDrops" : true, > > "skyParameters" : { > "dayLength" : 10000, > "surfaceLevel" : 1000, > "spaceLevel" : 3000, > "seed" : -5288806180628666923, > > "skyType" : "barren", > "skyColoring" : { > "mainColor" : [200, 200, 255], > > "morningColors" : [[200, 200, 255], [200, 200, 255]], > "dayColors" : [[200, 200, 255], [200, 200, 255]], > "eveningColors" : [[200, 200, 255], [200, 200, 255]], > "nightColors" : [[200, 200, 255], [200, 200, 255]], > > "morningLightColor" : [200, 200, 200], > "dayLightColor" : [200, 200, 200], > "eveningLightColor" : [200, 200, 200], > "nightLightColor" : [200, 200, 200] > } > } > }, > > > > "bountylair4" : { > "type" : "FloatingDungeon", > "dungeonWorld" : "bountylair4", > "seed" : 2017, > "spawningEnabled" : false, > "beamUpRule" : "AnywhereWithWarning", > "disableDeathDrops" : true, > > "skyParameters" : { > "dayLength" : 10000, > "surfaceLevel" : 1000, > "spaceLevel" : 3000, > "seed" : -5288806180628666923, > > "skyType" : "atmospheric", > "skyColoring" : { > "mainColor" : [200, 200, 255], > > "morningColors" : [[57, 12, 71], [234, 78, 149]], > "dayColors" : [[57, 12, 71], [234, 78, 149]], > "eveningColors" : [[57, 12, 71], [234, 78, 149]], > "nightColors" : [[57, 12, 71], [234, 78, 149]], > > "morningLightColor" : [90, 20, 83], > "dayLightColor" : [90, 20, 83], > "eveningLightColor" : [90, 20, 83], > "nightLightColor" : [90, 20, 83] > }, > > "satellites" : [ { > "pos" : [ 0.310561, 0.35497 ], > "layers" : [ { > "scale" : 0.055, > "image" : "/celestial/system/terrestrial/liquids/water.png" > }, { > "scale" : 0.055, > "image" : "/celestial/system/terrestrial/biomes/forest/maskie3.png?hueshift=-45?addmask=/celestial/system/terrestrial/dynamics/temperate/2.png" > }, { > "scale" : 0.055, > "image" : "/celestial/system/terrestrial/biomes/forest/maskie2.png?hueshift=-45?addmask=/celestial/system/terrestrial/dynamics/temperate/20.png" > }, { > "scale" : 0.055, > "image" : "/celestial/system/terrestrial/biomes/forest/maskie1.png?hueshift=-45?addmask=/celestial/system/terrestrial/dynamics/temperate/5.png" > }, { > "scale" : 0.055, > "image" : "/celestial/system/terrestrial/shadows/9.png" > } ] > } ], > "planet" : { > "pos" : [ 0.00538729, 0.46961 ], > "layers" : [ { > "scale" : 0.15, > "image" : "/celestial/system/gas_giant/gas_giant_base.png?hueshift=-80" > }, { > "scale" : 0.15, > "image" : "/celestial/system/gas_giant/gas_giant_clouds_0.png?hueshift=-70?addmask=/celestial/system/gas_giant/gas_giant_dynamics/3.png+/celestial/system/gas_giant/gas_giant_dynamics/29.png" > }, { > "scale" : 0.15, > "image" : "/celestial/system/gas_giant/gas_giant_clouds_1.png?hueshift=-77?addmask=/celestial/system/gas_giant/gas_giant_dynamics/28.png+/celestial/system/gas_giant/gas_giant_dynamics/29.png" > }, { > "scale" : 0.15, > "image" : "/celestial/system/gas_giant/shadows/9.png" > } ] > }, > "horizonImages" : [ ] interface.config 116a117,118 > "glow" : "/interface/inventoryglow.png", > "glowHover" : "/interface/inventoryglowhover.png", player.config 780a781,784 > "genericScriptContexts" : { > "events" : "/events/events.lua" > }, > sky.config 11,12c11,12 < "hyperspaceSpeedupTime" : 8.0, < "flyingTimer" : 14.0, --- > "hyperspaceSpeedupTime" : 2.0, > "flyingTimer" : 4.0, 14c14 < "hyperspaceSlowdownTime" : 8.0, --- > "hyperspaceSlowdownTime" : 2.0, system_objects.config 103a104,228 > "spacestation_peacekeeper1" : { > "warpAction" : "InstanceWorld:spacestation_peacekeeper1", > "threatLevel" : 1, > "skyParameters" : { > "seed" : 0, > "horizonClouds" : false, > "horizonImages" : [ { "left": "/celestial/system/spacestation/stationhorizonleft.png", "right": "/celestial/system/spacestation/stationhorizonright.png" } ] > }, > > "permanent" : true, > > "moving" : false, > "speed" : 5.0, > "orbitRange" : [10, 10], > "lifeTime" : [0, 0], > "parameters" : { > "icon" : "/celestial/system/spacestation/peacekeeperspacestationicon.png", > > "displayName" : "Peacekeeper Station", > "description" : "Home of Peacekeepers, a.k.a. Laser Space Cops", > > "bookmarkIcon" : "spacestation" > } > }, > > "spacestation_peacekeeper2" : { > "warpAction" : "InstanceWorld:spacestation_peacekeeper2", > "threatLevel" : 1, > "skyParameters" : { > "seed" : 0, > "horizonClouds" : false, > "horizonImages" : [ { "left": "/celestial/system/spacestation/stationhorizonleft.png", "right": "/celestial/system/spacestation/stationhorizonright.png" } ] > }, > > "permanent" : true, > > "moving" : false, > "speed" : 5.0, > "orbitRange" : [10, 10], > "lifeTime" : [0, 0], > "parameters" : { > "icon" : "/celestial/system/spacestation/peacekeeperspacestationicon.png", > > "displayName" : "Peacekeeper Station", > "description" : "Home of Peacekeepers, a.k.a. Laser Space Cops", > > "bookmarkIcon" : "spacestation" > } > }, > > "spacestation_peacekeeper3" : { > "warpAction" : "InstanceWorld:spacestation_peacekeeper3", > "threatLevel" : 1, > "skyParameters" : { > "seed" : 0, > "horizonClouds" : false, > "horizonImages" : [ { "left": "/celestial/system/spacestation/stationhorizonleft.png", "right": "/celestial/system/spacestation/stationhorizonright.png" } ] > }, > > "permanent" : true, > > "moving" : false, > "speed" : 5.0, > "orbitRange" : [10, 10], > "lifeTime" : [0, 0], > "parameters" : { > "icon" : "/celestial/system/spacestation/peacekeeperspacestationicon.png", > > "displayName" : "Peacekeeper Station", > "description" : "Home of Peacekeepers, a.k.a. Laser Space Cops", > > "bookmarkIcon" : "spacestation" > } > }, > > "spacestation_peacekeeper4" : { > "warpAction" : "InstanceWorld:spacestation_peacekeeper4", > "threatLevel" : 1, > "skyParameters" : { > "seed" : 0, > "horizonClouds" : false, > "horizonImages" : [ { "left": "/celestial/system/spacestation/stationhorizonleft.png", "right": "/celestial/system/spacestation/stationhorizonright.png" } ] > }, > > "permanent" : true, > > "moving" : false, > "speed" : 5.0, > "orbitRange" : [10, 10], > "lifeTime" : [0, 0], > "parameters" : { > "icon" : "/celestial/system/spacestation/peacekeeperspacestationicon.png", > > "displayName" : "Peacekeeper Station", > "description" : "Home of Peacekeepers, a.k.a. Laser Space Cops", > > "bookmarkIcon" : "spacestation" > } > }, > > "spacestation_peacekeeper5" : { > "warpAction" : "InstanceWorld:spacestation_peacekeeper5", > "threatLevel" : 1, > "skyParameters" : { > "seed" : 0, > "horizonClouds" : false, > "horizonImages" : [ { "left": "/celestial/system/spacestation/stationhorizonleft.png", "right": "/celestial/system/spacestation/stationhorizonright.png" } ] > }, > > "permanent" : true, > > "moving" : false, > "speed" : 5.0, > "orbitRange" : [10, 10], > "lifeTime" : [0, 0], > "parameters" : { > "icon" : "/celestial/system/spacestation/peacekeeperspacestationicon.png", > > "displayName" : "Peacekeeper Station", > "description" : "Home of Peacekeepers, a.k.a. Laser Space Cops", > > "bookmarkIcon" : "spacestation" > } > }, > 266a392,430 > } > }, > > "bountyanomaly" : { > "warpAction" : "InstanceWorld:bountyspaceencounter", > "skyParameters" : { > "seed" : 0, > "horizonClouds" : false, > "horizonImages" : [ { "left": "/celestial/system/anomaly/anomalyhorizonleft.png", "right": "/celestial/system/anomaly/anomalyhorizonright.png" } ] > }, > > "moving" : false, > "speed" : 0, > "orbitRange" : [0, 0], > "lifeTime" : [1500, 2100], > "parameters" : { > "icon" : "/celestial/system/anomaly/anomaly.png", > "displayName" : "Criminal Hideout", > "description" : "This is where criminals hide out." > } > }, > > "bountyship" : { > "warpAction" : "InstanceWorld:bountyshipencounter", > "threatLevel" : 1, > "skyParameters" : { > "seed" : 0, > "horizonClouds" : false, > "horizonImages" : [ { "left": "/celestial/system/ships/shiphorizonleft.png", "right": "/celestial/system/ships/shiphorizonright.png" } ] > }, > > "moving" : true, > "speed" : 15.0, > "orbitRange" : [1, 1], > "lifeTime" : [1500, 2100], > "parameters" : { > "icon" : "/celestial/system/ships/npcship.png", > "displayName" : "Suspicious Ship", > "description" : "Whoever's flying this ship, we shouldn't get close without being prepared for a fight." terrestrial_worlds.config 651a652,682 > }, > > "cyberspace" : { > "threatRange" : [6, 6], > "layers" : { > "surface" : { > "primaryRegion" : ["cyberspace"], > "dungeons" : [] > }, > "subsurface" : { > "primaryRegion" : ["tentacleundergroundtentacles"] > }, > "underground1" : { > "primaryRegion" : ["tentacleundergroundtentacles"], > "secondaryRegions" : [] > }, > "underground2" : { > "primaryRegion" : ["tentacleundergroundceiling"], > "secondaryRegions" : [] > }, > "underground3" : { > "primaryRegion" : ["tentacleundergroundfloor"], > "secondaryRegions" : [], > "dungeons" : [[1.0, "tentacleboss"]], > "dungeonCountRange" : [1, 1] > }, > "core" : { > "primaryRegion" : ["tentacleundergroundcore"], > "secondaryRegions" : [] > } > } 949a981,989 > ] > }, > > "cyberspace" : { > "blockSelector" : [ "remixedFlatsSurface" ], > "fgCaveSelector" : [ "empty" ], > "bgCaveSelector" : [ "empty" ], > "biome" : [ > [0, [ "cyberspace" ]] universeflags.config 20a21,26 > }, > { > "type" : "placeDungeon", > "dungeonId" : "outpost_peacekeeper", > "targetInstance" : "outpost", > "targetPosition" : [310, 616] universe_server.config 37c37 < "queuedFlightWaitTime" : 35.0, --- > "queuedFlightWaitTime" : 11.0, versioning.config 11,12c11,12 < "PlayerEntity" : 30, < "MonsterEntity" : 4, --- > "PlayerEntity" : 31, > "MonsterEntity" : 5, worldserver.config 90,91c90,91 < "luaGcPause" : 1.0, < "luaGcStepMultiplier" : 1.0, --- > "luaGcPause" : 1.2, > "luaGcStepMultiplier" : 1.2, animations\dust1\dust1.animation 1,7c1,8 < { < "frames" : "dust1.png", < "variants" : 1, < "frameNumber" : 4, < "animationCycle" : 0.45, < "offset" : [0, 0] < } --- > { > "frames" : "dust1.png", > "variants" : 1, > "frameNumber" : 4, > "animationCycle" : 0.45, > "mode" : "stop", > "offset" : [0, 0] > } behaviors\monsters\modular\actions\hop.behavior 3c3 < "description": "", --- > "description": null, 21c21,22 < "hopControlForce": 10 --- > "hopControlForce": 10, > "burstEmitter": null 198a200,213 > } > }, > { > "title": "succeeder", > "type": "decorator", > "name": "succeeder", > "parameters": {}, > "child": { > "title": "burstParticleEmitter", > "type": "action", > "name": "burstParticleEmitter", > "parameters": { > "emitter": {"key": ""} > } behaviors\nodes\dialog.nodes 59a60,71 > }, > "setDialogTag": { > "type": "action", > "name": "setDialogTag", > "title": "", > "properties": { > "tag": {"type": "string", "value": null}, > "text": {"type": "string", "value": null} > }, > "category": "dialog", > "script": "/scripts/actions/dialog.lua", > "output": {} 61c73 < } --- > } \ No newline at end of file behaviors\nodes\module.nodes 2303c2303 < "action-pairbeam": { --- > "bounty": { 2305c2305 < "name": "action-pairbeam", --- > "name": "bounty", 2307,2310c2307 < "properties": { < "monsterType": {"type": "json", "value": {"type": "json", "value": null}}, < "range": {"type": "json", "value": {"type": "json", "value": 50}} < } --- > "properties": {} 2312c2309 < "approach-leadorbit": { --- > "bounty-arrest": { 2314c2311 < "name": "approach-leadorbit", --- > "name": "bounty-arrest", 2316,2320c2313 < "properties": { < "distance": {"type": "json", "value": 10}, < "tangentialSpeed": {"type": "json", "value": 5}, < "tangentialForce": {"type": "json", "value": 5} < } --- > "properties": {} 2322c2315 < "approach-fall": { --- > "bounty-bribe": { 2324c2317 < "name": "approach-fall", --- > "name": "bounty-bribe", 2326,2330c2319 < "properties": { < "flyState": {"type": "json", "value": "fly"}, < "idleState": {"type": "json", "value": "idle"}, < "friction": {"type": "json", "value": 1} < } --- > "properties": {} behaviors\nodes\npc.nodes 27,28c27 < "definition": {"type": "json", "value": "uncommonrocketlauncher"}, < "itemName": {"type": "string", "value": "generatedgun"}, --- > "itemName": {"type": "string", "value": null}, 310a310,356 > } > }, > "setPersistent": { > "type": "action", > "name": "setPersistent", > "title": "", > "properties": { > "persistent": {"type": "bool", "value": null} > }, > "category": "npc", > "script": "/scripts/actions/npc.lua", > "output": {} > }, > "unequipSlot": { > "type": "action", > "name": "unequipSlot", > "title": "", > "properties": { > "slot": {"type": "string", "value": null} > }, > "category": "npc", > "script": "/scripts/actions/npc.lua", > "output": {} > }, > "getItemFromTreasure": { > "type": "action", > "name": "getItemFromTreasure", > "title": "", > "properties": { > "pool": {"type": "string", "value": null}, > "level": {"type": "number", "value": null} > }, > "category": "npc", > "script": "/scripts/actions/merchant.lua", > "output": { > "item": {"type": "table", "key": null} > } > }, > "level": { > "type": "action", > "name": "level", > "title": "", > "properties": {}, > "category": "npc", > "script": "/scripts/actions/npc.lua", > "output": { > "level": {"type": "number", "key": null} behaviors\nodes\quest.nodes 152a153,161 > }, > "hasRole": { > "type": "action", > "name": "hasRole", > "title": "", > "properties": {}, > "category": "quest", > "script": "/scripts/actions/quests.lua", > "output": {} behaviors\nodes\world.nodes 305a306,338 > }, > "spawnItem": { > "type": "action", > "name": "spawnItem", > "title": "", > "properties": { > "item": {"type": "table", "value": null}, > "position": {"type": "position", "value": null}, > "count": {"type": "number", "value": null}, > "parameters": {"type": "table", "value": null}, > "velocity": {"type": "vec2", "value": null}, > "intangibleTime": {"type": "number", "value": null} > }, > "category": "world", > "script": "/scripts/actions/world.lua", > "output": {} > }, > "playerConfirm": { > "type": "action", > "name": "playerConfirm", > "title": "", > "properties": { > "player": {"type": "entity", "value": null}, > "title": {"type": "string", "value": null}, > "subtitle": {"type": "string", "value": null}, > "icon": {"type": "string", "value": null}, > "message": {"type": "string", "value": null}, > "okCaption": {"type": "string", "value": null}, > "cancelCaption": {"type": "string", "value": null} > }, > "category": "world", > "script": "/scripts/actions/world.lua", > "output": {} behaviors\npc\accuse.behavior 4a5,8 > "/scripts/actions/status.lua", > "/scripts/actions/math.lua", > "/scripts/actions/world.lua", > "/scripts/actions/entity.lua", 8d11 < "/scripts/actions/world.lua", 11d13 < "/scripts/actions/entity.lua", 18c20 < "title": "sequence", --- > "title": "dynamic", 20c22 < "name": "sequence", --- > "name": "dynamic", 24,36c26 < "title": "receivedNotification", < "type": "action", < "name": "receivedNotification", < "parameters": { < "type": {"value": "objectBroken"} < }, < "output": { < "target": "thiefTarget", < "targetPosition": "objectPosition" < } < }, < { < "title": "selector", --- > "title": "sequence", 38c28 < "name": "selector", --- > "name": "sequence", 42,44c32,34 < "title": "sequence", < "type": "composite", < "name": "sequence", --- > "title": "inverter", > "type": "decorator", > "name": "inverter", 46,53c36,63 < "children": [ < { < "title": "distance", < "type": "action", < "name": "distance", < "parameters": { < "from": {"key": "self"}, < "to": {"key": "objectPosition"} --- > "child": { > "title": "resourcePercentage", > "type": "action", > "name": "resourcePercentage", > "parameters": { > "percentage": {"value": 0}, > "resource": {"value": "health"} > } > } > }, > { > "title": "succeeder", > "type": "decorator", > "name": "succeeder", > "parameters": {}, > "child": { > "title": "sequence", > "type": "composite", > "name": "sequence", > "parameters": {}, > "children": [ > { > "title": "chance", > "type": "action", > "name": "chance", > "parameters": { > "chance": {"value": 0.25} > } 55,65c65,66 < "output": { < "vector": "toObject" < } < }, < { < "title": "inverter", < "type": "decorator", < "name": "inverter", < "parameters": {}, < "child": { < "title": "lineTileCollision", --- > { > "title": "sendEntityMessage", 67c68 < "name": "lineTileCollision", --- > "name": "sendEntityMessage", 69,71c70,72 < "collisionType": {"value": ["Null", "Block", "Dynamic"]}, < "offset": {"key": "toObject"}, < "position": {"key": "self"} --- > "arguments": {"value": [3]}, > "entity": {"key": "thiefTarget"}, > "message": {"value": "raiseWantedLevel"} 74,75c75,76 < } < ] --- > ] > } 78c79,95 < "title": "sequence", --- > "title": "setDying", > "type": "action", > "name": "setDying", > "parameters": { > "shouldDie": {"value": true} > } > } > ] > }, > { > "title": "sequence", > "type": "composite", > "name": "sequence", > "parameters": {}, > "children": [ > { > "title": "selector", 80c97 < "name": "sequence", --- > "name": "selector", 84c101 < "title": "entityPosition", --- > "title": "receivedNotification", 86c103 < "name": "entityPosition", --- > "name": "receivedNotification", 88c105 < "entity": {"key": "thiefTarget"} --- > "type": {"value": "objectBroken"} 91c108,109 < "position": "thiefPosition" --- > "target": "thiefTarget", > "targetPosition": "objectPosition" 95c113 < "title": "distance", --- > "title": "receivedNotification", 97c115 < "name": "distance", --- > "name": "receivedNotification", 99,100c117 < "from": {"key": "self"}, < "to": {"key": "thiefPosition"} --- > "type": {"value": "tileBroken"} 103c120,121 < "vector": "toThief" --- > "target": "thiefTarget", > "targetPosition": "objectPosition" 107,119c125,133 < "title": "inverter", < "type": "decorator", < "name": "inverter", < "parameters": {}, < "child": { < "title": "lineTileCollision", < "type": "action", < "name": "lineTileCollision", < "parameters": { < "collisionType": {"value": ["Null", "Block", "Dynamic"]}, < "offset": {"key": "toThief"}, < "position": {"key": "self"} < } --- > "title": "receivedNotification", > "type": "action", > "name": "receivedNotification", > "parameters": { > "type": {"value": "itemStolen"} > }, > "output": { > "target": "thiefTarget", > "targetPosition": "objectPosition" 123,131c137 < } < ] < }, < { < "title": "selector", < "type": "composite", < "name": "selector", < "parameters": {}, < "children": [ --- > }, 133,135c139,141 < "title": "limiter", < "type": "decorator", < "name": "limiter", --- > "title": "setDying", > "type": "action", > "name": "setDying", 137,147c143,153 < "limit": {"value": 2} < }, < "child": { < "title": "sayToEntity", < "type": "action", < "name": "sayToEntity", < "parameters": { < "dialogType": {"value": "dialog.accuse"}, < "entity": {"key": "thiefTarget"}, < "tags": {"value": {}} < } --- > "shouldDie": {"value": false} > } > }, > { > "title": "sendEntityMessage", > "type": "action", > "name": "sendEntityMessage", > "parameters": { > "arguments": {"value": [1]}, > "entity": {"key": "thiefTarget"}, > "message": {"value": "raiseWantedLevel"} 151c157 < "title": "sequence", --- > "title": "selector", 153c159 < "name": "sequence", --- > "name": "selector", 157,173c163,196 < "title": "setEntity", < "type": "action", < "name": "setEntity", < "parameters": { < "entity": {"key": "thiefTarget"} < }, < "output": { < "entity": "reactTarget" < } < }, < { < "title": "setDamageTeam", < "type": "action", < "name": "setDamageTeam", < "parameters": { < "damageTeam": {"key": ""} < } --- > "title": "sequence", > "type": "composite", > "name": "sequence", > "parameters": {}, > "children": [ > { > "title": "distance", > "type": "action", > "name": "distance", > "parameters": { > "from": {"key": "self"}, > "to": {"key": "objectPosition"} > }, > "output": { > "vector": "toObject" > } > }, > { > "title": "inverter", > "type": "decorator", > "name": "inverter", > "parameters": {}, > "child": { > "title": "lineTileCollision", > "type": "action", > "name": "lineTileCollision", > "parameters": { > "collisionType": {"value": ["Null", "Block", "Dynamic"]}, > "offset": {"key": "toObject"}, > "position": {"key": "self"} > } > } > } > ] 176c199 < "title": "parallel", --- > "title": "sequence", 178,182c201,202 < "name": "parallel", < "parameters": { < "fail": {"value": -1}, < "success": {"value": -1} < }, --- > "name": "sequence", > "parameters": {}, 185,187c205,218 < "title": "cooldown", < "type": "decorator", < "name": "cooldown", --- > "title": "entityPosition", > "type": "action", > "name": "entityPosition", > "parameters": { > "entity": {"key": "thiefTarget"} > }, > "output": { > "position": "thiefPosition" > } > }, > { > "title": "distance", > "type": "action", > "name": "distance", 189,191c220,221 < "cooldown": {"value": 1}, < "onFail": {"value": false}, < "onSuccess": {"value": true} --- > "from": {"key": "self"}, > "to": {"key": "thiefPosition"} 192a223,231 > "output": { > "vector": "toThief" > } > }, > { > "title": "inverter", > "type": "decorator", > "name": "inverter", > "parameters": {}, 194c233 < "title": "broadcastNotification", --- > "title": "lineTileCollision", 196c235 < "name": "broadcastNotification", --- > "name": "lineTileCollision", 198,202c237,239 < "entityTypes": {"value": ["npc"]}, < "position": {"key": "self"}, < "range": {"value": 40}, < "target": {"key": "reactTarget"}, < "type": {"value": "attackThief"} --- > "collisionType": {"value": ["Null", "Block", "Dynamic"]}, > "offset": {"key": "toThief"}, > "position": {"key": "self"} 204a242,286 > } > ] > } > ] > }, > { > "title": "selector", > "type": "composite", > "name": "selector", > "parameters": {}, > "children": [ > { > "title": "limiter", > "type": "decorator", > "name": "limiter", > "parameters": { > "limit": {"value": 2} > }, > "child": { > "title": "sayToEntity", > "type": "action", > "name": "sayToEntity", > "parameters": { > "dialogType": {"value": "dialog.accuse"}, > "entity": {"key": "thiefTarget"}, > "tags": {"value": {}} > } > } > }, > { > "title": "sequence", > "type": "composite", > "name": "sequence", > "parameters": {}, > "children": [ > { > "title": "setEntity", > "type": "action", > "name": "setEntity", > "parameters": { > "entity": {"key": "thiefTarget"} > }, > "output": { > "entity": "reactTarget" > } 207,209c289,291 < "title": "cooldown", < "type": "decorator", < "name": "cooldown", --- > "title": "sendEntityMessage", > "type": "action", > "name": "sendEntityMessage", 211,213c293,312 < "cooldown": {"value": 6}, < "onFail": {"value": false}, < "onSuccess": {"value": true} --- > "arguments": {"value": [2]}, > "entity": {"key": "thiefTarget"}, > "message": {"value": "raiseWantedLevel"} > } > }, > { > "title": "setDamageTeam", > "type": "action", > "name": "setDamageTeam", > "parameters": { > "damageTeam": {"key": ""} > } > }, > { > "title": "parallel", > "type": "composite", > "name": "parallel", > "parameters": { > "fail": {"value": -1}, > "success": {"value": -1} 215,227c314,322 < "child": { < "title": "sequence", < "type": "composite", < "name": "sequence", < "parameters": {}, < "children": [ < { < "title": "timer", < "type": "action", < "name": "timer", < "parameters": { < "time": {"value": 2} < } --- > "children": [ > { > "title": "cooldown", > "type": "decorator", > "name": "cooldown", > "parameters": { > "cooldown": {"value": 1}, > "onFail": {"value": false}, > "onSuccess": {"value": true} 229,230c324,325 < { < "title": "sayToEntity", --- > "child": { > "title": "broadcastNotification", 232c327 < "name": "sayToEntity", --- > "name": "broadcastNotification", 234,236c329,333 < "dialogType": {"value": "dialog.alert"}, < "entity": {"key": "reactTarget"}, < "tags": {"value": {}} --- > "entityTypes": {"value": ["npc"]}, > "position": {"key": "self"}, > "range": {"value": 40}, > "target": {"key": "reactTarget"}, > "type": {"value": "attackThief"} 239,249c336,382 < ] < } < }, < { < "title": "reaction-follow", < "type": "module", < "name": "reaction-follow", < "parameters": { < "creepy": {"value": false}, < "duration": {"value": 10} < } --- > }, > { > "title": "cooldown", > "type": "decorator", > "name": "cooldown", > "parameters": { > "cooldown": {"value": 6}, > "onFail": {"value": false}, > "onSuccess": {"value": true} > }, > "child": { > "title": "sequence", > "type": "composite", > "name": "sequence", > "parameters": {}, > "children": [ > { > "title": "timer", > "type": "action", > "name": "timer", > "parameters": { > "time": {"value": 2} > } > }, > { > "title": "sayToEntity", > "type": "action", > "name": "sayToEntity", > "parameters": { > "dialogType": {"value": "dialog.alert"}, > "entity": {"key": "reactTarget"}, > "tags": {"value": {}} > } > } > ] > } > }, > { > "title": "reaction-follow", > "type": "module", > "name": "reaction-follow", > "parameters": { > "creepy": {"value": false}, > "duration": {"value": 10} > } > } > ] behaviors\npc\attackthief.behavior 4a5,8 > "/scripts/actions/status.lua", > "/scripts/actions/math.lua", > "/scripts/actions/world.lua", > "/scripts/actions/entity.lua", 8d11 < "/scripts/actions/world.lua", 14,16c17,19 < "title": "failer", < "type": "decorator", < "name": "failer", --- > "title": "dynamic", > "type": "composite", > "name": "dynamic", 18,29c21,41 < "child": { < "title": "sequence", < "type": "composite", < "name": "sequence", < "parameters": {}, < "children": [ < { < "title": "receivedNotification", < "type": "action", < "name": "receivedNotification", < "parameters": { < "type": {"value": "objectBroken"} --- > "children": [ > { > "title": "sequence", > "type": "composite", > "name": "sequence", > "parameters": {}, > "children": [ > { > "title": "inverter", > "type": "decorator", > "name": "inverter", > "parameters": {}, > "child": { > "title": "resourcePercentage", > "type": "action", > "name": "resourcePercentage", > "parameters": { > "percentage": {"value": 0}, > "resource": {"value": "health"} > } > } 31,33c43,81 < "output": { < "target": "thiefTarget", < "targetPosition": "objectPosition" --- > { > "title": "succeeder", > "type": "decorator", > "name": "succeeder", > "parameters": {}, > "child": { > "title": "sequence", > "type": "composite", > "name": "sequence", > "parameters": {}, > "children": [ > { > "title": "chance", > "type": "action", > "name": "chance", > "parameters": { > "chance": {"value": 0.5} > } > }, > { > "title": "sendEntityMessage", > "type": "action", > "name": "sendEntityMessage", > "parameters": { > "arguments": {"value": [3]}, > "entity": {"key": "thiefTarget"}, > "message": {"value": "raiseWantedLevel"} > } > } > ] > } > }, > { > "title": "setDying", > "type": "action", > "name": "setDying", > "parameters": { > "shouldDie": {"value": true} > } 35,39c83,93 < }, < { < "title": "inverter", < "type": "decorator", < "name": "inverter", --- > ] > }, > { > "title": "failer", > "type": "decorator", > "name": "failer", > "parameters": {}, > "child": { > "title": "sequence", > "type": "composite", > "name": "sequence", 41,63c95,107 < "child": { < "title": "selector", < "type": "composite", < "name": "selector", < "parameters": {}, < "children": [ < { < "title": "sequence", < "type": "composite", < "name": "sequence", < "parameters": {}, < "children": [ < { < "title": "distance", < "type": "action", < "name": "distance", < "parameters": { < "from": {"key": "self"}, < "to": {"key": "objectPosition"} < }, < "output": { < "vector": "toObject" < } --- > "children": [ > { > "title": "selector", > "type": "composite", > "name": "selector", > "parameters": {}, > "children": [ > { > "title": "receivedNotification", > "type": "action", > "name": "receivedNotification", > "parameters": { > "type": {"value": "objectBroken"} 65,73c109,111 < { < "title": "lineTileCollision", < "type": "action", < "name": "lineTileCollision", < "parameters": { < "collisionType": {"value": ["Null", "Block", "Dynamic"]}, < "offset": {"key": "toObject"}, < "position": {"key": "self"} < } --- > "output": { > "target": "thiefTarget", > "targetPosition": "objectPosition" 75,92c113,119 < ] < }, < { < "title": "sequence", < "type": "composite", < "name": "sequence", < "parameters": {}, < "children": [ < { < "title": "entityPosition", < "type": "action", < "name": "entityPosition", < "parameters": { < "entity": {"key": "thiefTarget"} < }, < "output": { < "position": "thiefPosition" < } --- > }, > { > "title": "receivedNotification", > "type": "action", > "name": "receivedNotification", > "parameters": { > "type": {"value": "tileBroken"} 94,104c121,131 < { < "title": "distance", < "type": "action", < "name": "distance", < "parameters": { < "from": {"key": "self"}, < "to": {"key": "thiefPosition"} < }, < "output": { < "vector": "toThief" < } --- > "output": { > "target": "thiefTarget", > "targetPosition": "objectPosition" > } > }, > { > "title": "receivedNotification", > "type": "action", > "name": "receivedNotification", > "parameters": { > "type": {"value": "itemStolen"} 106,114c133,135 < { < "title": "lineTileCollision", < "type": "action", < "name": "lineTileCollision", < "parameters": { < "collisionType": {"value": ["Null", "Block", "Dynamic"]}, < "offset": {"key": "toThief"}, < "position": {"key": "self"} < } --- > "output": { > "target": "thiefTarget", > "targetPosition": "objectPosition" 116c137,145 < ] --- > } > ] > }, > { > "title": "setDying", > "type": "action", > "name": "setDying", > "parameters": { > "shouldDie": {"value": false} 118,126c147 < ] < } < }, < { < "title": "selector", < "type": "composite", < "name": "selector", < "parameters": {}, < "children": [ --- > }, 128c149 < "title": "limiter", --- > "title": "inverter", 130,133c151,152 < "name": "limiter", < "parameters": { < "limit": {"value": 2} < }, --- > "name": "inverter", > "parameters": {}, 135c154 < "title": "sequence", --- > "title": "selector", 137c156 < "name": "sequence", --- > "name": "selector", 141,148c160,187 < "title": "sayToEntity", < "type": "action", < "name": "sayToEntity", < "parameters": { < "dialogType": {"value": "dialog.accuse"}, < "entity": {"key": "thiefTarget"}, < "tags": {"value": {}} < } --- > "title": "sequence", > "type": "composite", > "name": "sequence", > "parameters": {}, > "children": [ > { > "title": "distance", > "type": "action", > "name": "distance", > "parameters": { > "from": {"key": "self"}, > "to": {"key": "objectPosition"} > }, > "output": { > "vector": "toObject" > } > }, > { > "title": "lineTileCollision", > "type": "action", > "name": "lineTileCollision", > "parameters": { > "collisionType": {"value": ["Null", "Block", "Dynamic"]}, > "offset": {"key": "toObject"}, > "position": {"key": "self"} > } > } > ] 151,156c190,228 < "title": "timer", < "type": "action", < "name": "timer", < "parameters": { < "time": {"value": 2} < } --- > "title": "sequence", > "type": "composite", > "name": "sequence", > "parameters": {}, > "children": [ > { > "title": "entityPosition", > "type": "action", > "name": "entityPosition", > "parameters": { > "entity": {"key": "thiefTarget"} > }, > "output": { > "position": "thiefPosition" > } > }, > { > "title": "distance", > "type": "action", > "name": "distance", > "parameters": { > "from": {"key": "self"}, > "to": {"key": "thiefPosition"} > }, > "output": { > "vector": "toThief" > } > }, > { > "title": "lineTileCollision", > "type": "action", > "name": "lineTileCollision", > "parameters": { > "collisionType": {"value": ["Null", "Block", "Dynamic"]}, > "offset": {"key": "toThief"}, > "position": {"key": "self"} > } > } > ] 162,179c234,311 < "title": "cooldown", < "type": "decorator", < "name": "cooldown", < "parameters": { < "cooldown": {"value": 1}, < "onFail": {"value": false}, < "onSuccess": {"value": true} < }, < "child": { < "title": "broadcastNotification", < "type": "action", < "name": "broadcastNotification", < "parameters": { < "entityTypes": {"value": ["npc"]}, < "position": {"key": "self"}, < "range": {"value": 40}, < "target": {"key": "reactTarget"}, < "type": {"value": "attackThief"} --- > "title": "selector", > "type": "composite", > "name": "selector", > "parameters": {}, > "children": [ > { > "title": "limiter", > "type": "decorator", > "name": "limiter", > "parameters": { > "limit": {"value": 2} > }, > "child": { > "title": "sequence", > "type": "composite", > "name": "sequence", > "parameters": {}, > "children": [ > { > "title": "sayToEntity", > "type": "action", > "name": "sayToEntity", > "parameters": { > "dialogType": {"value": "dialog.accuse"}, > "entity": {"key": "thiefTarget"}, > "tags": {"value": {}} > } > }, > { > "title": "timer", > "type": "action", > "name": "timer", > "parameters": { > "time": {"value": 2} > } > } > ] > } > }, > { > "title": "cooldown", > "type": "decorator", > "name": "cooldown", > "parameters": { > "cooldown": {"value": 1}, > "onFail": {"value": false}, > "onSuccess": {"value": true} > }, > "child": { > "title": "sequence", > "type": "composite", > "name": "sequence", > "parameters": {}, > "children": [ > { > "title": "sendEntityMessage", > "type": "action", > "name": "sendEntityMessage", > "parameters": { > "arguments": {"value": [2]}, > "entity": {"key": "thiefTarget"}, > "message": {"value": "raiseWantedLevel"} > } > }, > { > "title": "broadcastNotification", > "type": "action", > "name": "broadcastNotification", > "parameters": { > "entityTypes": {"value": ["npc"]}, > "position": {"key": "self"}, > "range": {"value": 40}, > "target": {"key": "reactTarget"}, > "type": {"value": "attackThief"} > } > } > ] > } 181c313 < } --- > ] 185,186c317,318 < ] < } --- > } > ] behaviors\npc\guard.behavior 3,10c3,4 < "description": "", < "scripts": [ < "/scripts/actions/npc.lua", < "/scripts/behavior.lua", < "/scripts/actions/math.lua", < "/scripts/actions/world.lua", < "/scripts/actions/dialog.lua" < ], --- > "description": null, > "scripts": [], 34,277c28,33 < "title": "selector", < "type": "composite", < "name": "selector", < "parameters": {}, < "children": [ < { < "title": "parallel", < "type": "composite", < "name": "parallel", < "parameters": { < "fail": {"value": 1}, < "success": {"value": -1} < }, < "children": [ < { < "title": "friendlyTargeting", < "type": "action", < "name": "friendlyTargeting", < "parameters": { < "attackOnSight": {"key": "attackOnSight"}, < "hostileDamageTeam": {"value": ""}, < "losTime": {"value": 8}, < "queryRange": {"value": 50}, < "trackingRange": {"value": 50} < }, < "output": { < "target": "target" < } < }, < { < "title": "sequence", < "type": "composite", < "name": "sequence", < "parameters": {}, < "children": [ < { < "title": "setFlag", < "type": "action", < "name": "setFlag", < "parameters": { < "name": {"value": "inCombat"} < } < }, < { < "title": "succeeder", < "type": "decorator", < "name": "succeeder", < "parameters": {}, < "child": { < "title": "selector", < "type": "composite", < "name": "selector", < "parameters": {}, < "children": [ < { < "title": "chance", < "type": "action", < "name": "chance", < "parameters": { < "chance": {"value": 0.75} < } < }, < { < "title": "sequence", < "type": "composite", < "name": "sequence", < "parameters": {}, < "children": [ < { < "title": "entityInTypes", < "type": "action", < "name": "entityInTypes", < "parameters": { < "entity": {"key": "target"}, < "types": {"value": ["player"]} < } < }, < { < "title": "selector", < "type": "composite", < "name": "selector", < "parameters": {}, < "children": [ < { < "title": "listContains", < "type": "action", < "name": "listContains", < "parameters": { < "entity": {"key": "target"}, < "list": {"key": "seenplayers"} < } < }, < { < "title": "failer", < "type": "decorator", < "name": "failer", < "parameters": {}, < "child": { < "title": "listPush", < "type": "action", < "name": "listPush", < "parameters": { < "entity": {"key": "target"}, < "list": {"key": "seenplayers"} < }, < "output" : { < "list" : "seenplayers" < } < } < } < ] < }, < { < "title": "sayToEntity", < "type": "action", < "name": "sayToEntity", < "parameters": { < "dialogType": {"value": "dialog.reattack"}, < "entity": {"key": "target"}, < "tags": {"value": {}} < } < } < ] < }, < { < "title": "sayToEntity", < "type": "action", < "name": "sayToEntity", < "parameters": { < "dialogType": {"value": "dialog.attack"}, < "entity": {"key": "target"}, < "tags": {"value": {}} < } < } < ] < } < }, < { < "title": "NPC Combat", < "type": "module", < "name": "npccombat", < "parameters": {} < } < ] < } < ] < }, < { < "title": "failer", < "type": "decorator", < "name": "failer", < "parameters": {}, < "child": { < "title": "selector", < "type": "composite", < "name": "selector", < "parameters": {}, < "children": [ < { < "title": "inverter", < "type": "decorator", < "name": "inverter", < "parameters": {}, < "child": { < "title": "hasFlag", < "type": "action", < "name": "hasFlag", < "parameters": { < "name": {"key": "inCombat"} < } < } < }, < { < "title": "sequence", < "type": "composite", < "name": "sequence", < "parameters": {}, < "children": [ < { < "title": "unsetFlag", < "type": "action", < "name": "unsetFlag", < "parameters": { < "name": {"value": "inCombat"} < } < }, < { < "title": "selector", < "type": "composite", < "name": "selector", < "parameters": {}, < "children": [ < { < "title": "chance", < "type": "action", < "name": "chance", < "parameters": { < "chance": {"value": 0.75} < } < }, < { < "title": "sequence", < "type": "composite", < "name": "sequence", < "parameters": {}, < "children": [ < { < "title": "entityExists", < "type": "action", < "name": "entityExists", < "parameters": { < "entity": {"key": "target"} < } < }, < { < "title": "sayToEntity", < "type": "action", < "name": "sayToEntity", < "parameters": { < "dialogType": {"value": "dialog.lostTarget"}, < "entity": {"key": "target"}, < "tags": {"value": {}} < } < } < ] < }, < { < "title": "sayToEntity", < "type": "action", < "name": "sayToEntity", < "parameters": { < "dialogType": {"value": "dialog.killedTarget"}, < "entity": {"key": "target"}, < "tags": {"value": {}} < } < } < ] < } < ] < } < ] < } < } < ] --- > "title": "friendlynpccombat", > "type": "module", > "name": "friendlynpccombat", > "parameters": { > "hostileDamageTeam": {"key": ""} > } 295c51 < } --- > } \ No newline at end of file behaviors\npc\hostileguard.behavior 25a26,31 > "title": "bounty", > "type": "module", > "name": "bounty", > "parameters": {} > }, > { 41c47 < "title": "NPC Hostile Tracking", --- > "title": "", 68,117c74,118 < "title": "selector", < "type": "composite", < "name": "selector", < "parameters": {}, < "children": [ < { < "title": "chance", < "type": "action", < "name": "chance", < "parameters": { < "chance": {"value": 0.75} < } < }, < { < "title": "sequence", < "type": "composite", < "name": "sequence", < "parameters": {}, < "children": [ < { < "title": "entityInTypes", < "type": "action", < "name": "entityInTypes", < "parameters": { < "entity": {"key": "target"}, < "types": {"value": ["player"]} < } < }, < { < "title": "selector", < "type": "composite", < "name": "selector", < "parameters": {}, < "children": [ < { < "title": "listContains", < "type": "action", < "name": "listContains", < "parameters": { < "entity": {"key": "target"}, < "list": {"key": "seenplayers"} < } < }, < { < "title": "failer", < "type": "decorator", < "name": "failer", < "parameters": {}, < "child": { < "title": "listPush", --- > "title": "cooldown", > "type": "decorator", > "name": "cooldown", > "parameters": { > "cooldown": {"value": 60}, > "onFail": {"value": false}, > "onSuccess": {"value": true} > }, > "child": { > "title": "selector", > "type": "composite", > "name": "selector", > "parameters": {}, > "children": [ > { > "title": "chance", > "type": "action", > "name": "chance", > "parameters": { > "chance": {"value": 0.75} > } > }, > { > "title": "sequence", > "type": "composite", > "name": "sequence", > "parameters": {}, > "children": [ > { > "title": "entityInTypes", > "type": "action", > "name": "entityInTypes", > "parameters": { > "entity": {"key": "target"}, > "types": {"value": ["player"]} > } > }, > { > "title": "selector", > "type": "composite", > "name": "selector", > "parameters": {}, > "children": [ > { > "title": "listContains", 119c120 < "name": "listPush", --- > "name": "listContains", 123,125c124,141 < }, < "output" : { < "list" : "seenplayers" --- > } > }, > { > "title": "failer", > "type": "decorator", > "name": "failer", > "parameters": {}, > "child": { > "title": "listPush", > "type": "action", > "name": "listPush", > "parameters": { > "entity": {"key": "target"}, > "list": {"key": "seenplayers"} > }, > "output": { > "list": "seenplayers" > } 127a144,153 > ] > }, > { > "title": "sayToEntity", > "type": "action", > "name": "sayToEntity", > "parameters": { > "dialogType": {"value": "dialog.reattack"}, > "entity": {"key": "target"}, > "tags": {"value": {}} 129,138d154 < ] < }, < { < "title": "sayToEntity", < "type": "action", < "name": "sayToEntity", < "parameters": { < "dialogType": {"value": "dialog.reattack"}, < "entity": {"key": "target"}, < "tags": {"value": {}} 139a156,165 > ] > }, > { > "title": "sayToEntity", > "type": "action", > "name": "sayToEntity", > "parameters": { > "dialogType": {"value": "dialog.attack"}, > "entity": {"key": "target"}, > "tags": {"value": {}} 141,150d166 < ] < }, < { < "title": "sayToEntity", < "type": "action", < "name": "sayToEntity", < "parameters": { < "dialogType": {"value": "dialog.attack"}, < "entity": {"key": "target"}, < "tags": {"value": {}} 152,153c168,169 < } < ] --- > ] > } 274c290 < } --- > } \ No newline at end of file behaviors\npc\villageguard.behavior 4,10c4 < "scripts": [ < "/scripts/actions/npc.lua", < "/scripts/behavior.lua", < "/scripts/actions/math.lua", < "/scripts/actions/world.lua", < "/scripts/actions/dialog.lua" < ], --- > "scripts": [], 33,278c27,32 < "title": "selector", < "type": "composite", < "name": "selector", < "parameters": {}, < "children": [ < { < "title": "parallel", < "type": "composite", < "name": "parallel", < "parameters": { < "fail": {"value": 1}, < "success": {"value": -1} < }, < "children": [ < { < "title": "friendlyTargeting", < "type": "action", < "name": "friendlyTargeting", < "parameters": { < "attackOnSight": {"key": "attackOnSight"}, < "broadcastInterval": {"value": 2}, < "hostileDamageTeam": {"value": {"type": "enemy", "team": 1}}, < "losTime": {"value": 8}, < "queryRange": {"value": 50}, < "trackingRange": {"value": 100} < }, < "output": { < "target": "target", < "attackOnSight": "attackOnSight" < } < }, < { < "title": "sequence", < "type": "composite", < "name": "sequence", < "parameters": {}, < "children": [ < { < "title": "setFlag", < "type": "action", < "name": "setFlag", < "parameters": { < "name": {"value": "inCombat"} < } < }, < { < "title": "succeeder", < "type": "decorator", < "name": "succeeder", < "parameters": {}, < "child": { < "title": "selector", < "type": "composite", < "name": "selector", < "parameters": {}, < "children": [ < { < "title": "chance", < "type": "action", < "name": "chance", < "parameters": { < "chance": {"value": 0.75} < } < }, < { < "title": "sequence", < "type": "composite", < "name": "sequence", < "parameters": {}, < "children": [ < { < "title": "entityInTypes", < "type": "action", < "name": "entityInTypes", < "parameters": { < "entity": {"key": "target"}, < "types": {"value": ["player"]} < } < }, < { < "title": "selector", < "type": "composite", < "name": "selector", < "parameters": {}, < "children": [ < { < "title": "listContains", < "type": "action", < "name": "listContains", < "parameters": { < "entity": {"key": "target"}, < "list": {"key": "seenplayers"} < } < }, < { < "title": "failer", < "type": "decorator", < "name": "failer", < "parameters": {}, < "child": { < "title": "listPush", < "type": "action", < "name": "listPush", < "parameters": { < "entity": {"key": "target"}, < "list": {"key": "seenplayers"} < }, < "output": { < "list": "seenplayers" < } < } < } < ] < }, < { < "title": "sayToEntity", < "type": "action", < "name": "sayToEntity", < "parameters": { < "dialogType": {"value": "dialog.reattack"}, < "entity": {"key": "target"}, < "tags": {"value": {}} < } < } < ] < }, < { < "title": "sayToEntity", < "type": "action", < "name": "sayToEntity", < "parameters": { < "dialogType": {"value": "dialog.attack"}, < "entity": {"key": "target"}, < "tags": {"value": {}} < } < } < ] < } < }, < { < "title": "NPC Combat", < "type": "module", < "name": "npccombat", < "parameters": {} < } < ] < } < ] < }, < { < "title": "failer", < "type": "decorator", < "name": "failer", < "parameters": {}, < "child": { < "title": "selector", < "type": "composite", < "name": "selector", < "parameters": {}, < "children": [ < { < "title": "inverter", < "type": "decorator", < "name": "inverter", < "parameters": {}, < "child": { < "title": "hasFlag", < "type": "action", < "name": "hasFlag", < "parameters": { < "name": {"key": "inCombat"} < } < } < }, < { < "title": "sequence", < "type": "composite", < "name": "sequence", < "parameters": {}, < "children": [ < { < "title": "unsetFlag", < "type": "action", < "name": "unsetFlag", < "parameters": { < "name": {"value": "inCombat"} < } < }, < { < "title": "selector", < "type": "composite", < "name": "selector", < "parameters": {}, < "children": [ < { < "title": "chance", < "type": "action", < "name": "chance", < "parameters": { < "chance": {"value": 0.75} < } < }, < { < "title": "sequence", < "type": "composite", < "name": "sequence", < "parameters": {}, < "children": [ < { < "title": "entityExists", < "type": "action", < "name": "entityExists", < "parameters": { < "entity": {"key": "target"} < } < }, < { < "title": "sayToEntity", < "type": "action", < "name": "sayToEntity", < "parameters": { < "dialogType": {"value": "dialog.lostTarget"}, < "entity": {"key": "target"}, < "tags": {"value": {}} < } < } < ] < }, < { < "title": "sayToEntity", < "type": "action", < "name": "sayToEntity", < "parameters": { < "dialogType": {"value": "dialog.killedTarget"}, < "entity": {"key": "target"}, < "tags": {"value": {}} < } < } < ] < } < ] < } < ] < } < } < ] --- > "title": "friendlynpccombat", > "type": "module", > "name": "friendlynpccombat", > "parameters": { > "hostileDamageTeam": {"value": {"type": "enemy", "team": 1}} > } biomes\surface_detached\bones.biome 9c9 < "pool" : [ --- > "pool" : [ 16,22c16,23 < [ 0.14, "vulturecritter" ], < [ 0.14, "apexscabcritter" ], < [ 0.14, "avianscabcritter" ], < [ 0.14, "floranscabcritter" ], < [ 0.14, "humanscabcritter" ], < [ 0.14, "glitchscabcritter" ], < [ 0.14, "penguinscabcritter" ] --- > [ 1.0, "vulturecritter" ], > [ 1.0, "apexscabcritter" ], > [ 1.0, "avianscabcritter" ], > [ 1.0, "floranscabcritter" ], > [ 1.0, "humanscabcritter" ], > [ 1.0, "glitchscabcritter" ], > [ 1.0, "penguinscabcritter" ], > [ 1.0, "hylotlscabcritter" ] 132c133 < --- > cinematics\story\esther\esther.cinematic 1,1362c1,1362 < { < "muteSfx" : true, < "muteMusic" : true, < "skippable" : false, < "letterbox" : false, < "backgroundColor" : [0, 0, 0, 255], < "backgroundFadeTime" : 0.5, < < "panels" : [ < // --------------------- statue 2 < { < "startTime" : 54, < "endTime" : 110, < "drawables" : [ < { < "image" : "/cinematics/story/esther/statue2.png" < } < ], < "keyframes" : [ < { < "timecode" : 0.0, < "alpha" : 0.0, < "zoom" : 1.5, < "position" : [600, -200], < "frame" : 0 < }, < { < "timecode" : 1, < "alpha" : 0, < "zoom" : 1.5, < "position" : [600, -200], < "frame" : 0 < }, < { < "timecode" : 55.49, < "alpha" : 1, < "position" : [600, 200] < }, < { < "timecode" : 55.5, < "position" : [600, 200], < "alpha" : 1 < }, < { < "timecode" : 56, < "frame" : 140, < "alpha" : 0 < } < ] < }, < < // --------------------- statue 1 < { < "startTime" : 40, < "endTime" : 110, < "drawables" : [ < { < "image" : "/cinematics/story/esther/statue1.png" < } < ], < "keyframes" : [ < { < "timecode" : 0.0, < "alpha" : 0.0, < "zoom" : 1.5, < "position" : [200, -200], < "frame" : 0 < }, < { < "timecode" : 1, < "alpha" : 0, < "zoom" : 1.5, < "position" : [200, -200], < "frame" : 0 < }, < { < "timecode" : 69.49, < "alpha" : 1, < "position" : [200, 120] < }, < { < "timecode" : 69.5, < "position" : [200, 120], < "alpha" : 1 < }, < { < "timecode" : 70, < "frame" : 140, < "alpha" : 0 < } < ] < }, < < < // -------------------------------- spotlight < { < "startTime" : 1, < "endTime" : 46, < "drawables" : [ < { < "image" : "/cinematics/story/esther/esthershadow.png" < } < ], < "keyframes" : [ < { < "timecode" : 0.0, < "alpha" : 0.0, < "zoom" : 1.5, < "position" : [485, 230] < }, < { < "timecode" : 0.5, < "alpha" : 1.0, < "zoom" : 1.5 < }, < { < "timecode" : 44, < "alpha" : 1 < }, < { < "timecode" : 44.5, < "alpha" : 0, < "frame" : 118 < } < ] < }, < < // -------------------------------- Esther < { < "startTime" : 1, < "endTime" : 46, < "drawables" : [ < { < "image" : "/cinematics/story/esther/esther.png:" < } < ], < "animationFrames" : 6, < "keyframes" : [ < { < "timecode" : 0.0, < "alpha" : 0.0, < "zoom" : 1.5, < "position" : [480, 280], < "frame" : 0 < }, < { < "timecode" : 0.5, < "alpha" : 1.0, < "zoom" : 1.5 < }, < { < "timecode" : 44, < "alpha" : 1, < "frame" : 110 < }, < { < "timecode" : 44.5, < "alpha" : 0, < "frame" : 110 < } < ] < }, < < // ------------------ radio message popup background < { < "startTime" : 1.5, < "endTime" : 148.5, < "drawables" : [ < { < "image" : "/cinematics/radiomessagebg.png:" < } < ], < "keyframes" : [ < { < "timecode" : 0.0, < "alpha" : 1.0, < "zoom" : 1.0, < "position" : [480, 100], < "frame" : 0 < }, < { < "timecode" : 0.5, < "frame" : 6 < }, < { < "timecode" : 146.5, < "frame" : 6 < }, < { < "timecode" : 147, < "frame" : 12 < } < ] < }, < < < < // ----------------- first radio message < { < "startTime" : 2.0, < "endTime" : 10.0, < "drawables" : [ < { < "image" : "/interface/chatbubbles/esthertalk.png:" < } < ], < "animationFrames" : 2, < "text" : "Hello, dear! Is that a Matter Manipulator you're carrying? Excellent, so you're a Protector.", < "textPosition" : { < "position" : [34, 21], < "vAnchor" : "top", < "wrapWidth" : 218 < }, < "keyframes" : [ < { < "timecode" : 0.0, < "alpha" : 1.0, < "zoom" : 1.0, < "position" : [366.5, 100], < "frame" : 0, < "textPercentage" : 0 < }, < { < "timecode" : 0.3, < "textPercentage" : 0 < }, < { < "timecode" : 2.5, < "frame" : 12, < "textPercentage" : 1 < } < < ] < }, < < // -------------------- second radio message < { < "startTime" : 10.0, < "endTime" : 18.0, < "drawables" : [ < { < "image" : "/interface/chatbubbles/esthersad.png:" < } < ], < "animationFrames" : 2, < "text" : "I'm sorry to say, perhaps the last, after the... The terrible destruction of Earth...", < "textPosition" : { < "position" : [34, 21], < "vAnchor" : "top", < "wrapWidth" : 218 < }, < "keyframes" : [ < { < "timecode" : 0.0, < "alpha" : 1.0, < "zoom" : 1.0, < "position" : [366.5, 100], < "frame" : 0, < "textPercentage" : 0 < }, < { < "timecode" : 0.3, < "textPercentage" : 0 < }, < { < "timecode" : 2.5, < "frame" : 12, < "textPercentage" : 1 < } < ] < }, < < //------------------------------- third radio message < { < "startTime" : 18.0, < "endTime" : 24.0, < "drawables" : [ < { < "image" : "/interface/chatbubbles/esthersad.png:" < } < ], < "animationFrames" : 2, < "text" : "It's sadly inevitable that we should meet now...", < "textPosition" : { < "position" : [34, 21], < "vAnchor" : "top", < "wrapWidth" : 218 < }, < "keyframes" : [ < { < "timecode" : 0.0, < "alpha" : 1.0, < "zoom" : 1.0, < "position" : [366.5, 100], < "frame" : 0, < "textPercentage" : 0 < }, < { < "timecode" : 0.3, < "textPercentage" : 0 < }, < { < "timecode" : 2.5, < "frame" : 12, < "textPercentage" : 1 < } < ] < }, < < // --------------- fourth radio message < { < "startTime" : 24.0, < "endTime" : 30.0, < "drawables" : [ < { < "image" : "/interface/chatbubbles/esthertalk.png:" < } < ], < "animationFrames" : 2, < "text" : "My name is ^orange;Esther Bright^white;, retired Grand Protector.", < "textPosition" : { < "position" : [34, 21], < "vAnchor" : "top", < "wrapWidth" : 218 < }, < "keyframes" : [ < { < "timecode" : 0.0, < "alpha" : 1.0, < "zoom" : 1.0, < "position" : [366.5, 100], < "frame" : 0, < "textPercentage" : 0 < }, < { < "timecode" : 0.3, < "textPercentage" : 0 < }, < { < "timecode" : 2.5, < "frame" : 12, < "textPercentage" : 1 < } < ] < }, < < // --------------- fifth radio message < { < "startTime" : 30.0, < "endTime" : 38.0, < "drawables" : [ < { < "image" : "/interface/chatbubbles/esthertalk.png:" < } < ], < "animationFrames" : 2, < "text" : "I left some years ago, an impossible decision; but my research could not be neglected.", < "textPosition" : { < "position" : [34, 21], < "vAnchor" : "top", < "wrapWidth" : 218 < }, < "keyframes" : [ < { < "timecode" : 0.0, < "alpha" : 1.0, < "zoom" : 1.0, < "position" : [366.5, 100], < "frame" : 0, < "textPercentage" : 0 < }, < { < "timecode" : 0.3, < "textPercentage" : 0 < }, < { < "timecode" : 2.5, < "frame" : 12, < "textPercentage" : 1 < } < ] < }, < < // --------------- sixth radio message < { < "startTime" : 38.0, < "endTime" : 46.0, < "drawables" : [ < { < "image" : "/interface/chatbubbles/estherthoughtful.png:" < } < ], < "animationFrames" : 2, < "text" : "I discovered things long forgotten that weigh heavy on the present.", < "textPosition" : { < "position" : [34, 21], < "vAnchor" : "top", < "wrapWidth" : 218 < }, < "keyframes" : [ < { < "timecode" : 0.0, < "alpha" : 1.0, < "zoom" : 1.0, < "position" : [366.5, 100], < "frame" : 0, < "textPercentage" : 0 < }, < { < "timecode" : 0.3, < "textPercentage" : 0 < }, < { < "timecode" : 2.5, < "frame" : 12, < "textPercentage" : 1 < } < ] < }, < < < // --------------------- background circle < { < "startTime" : 46, < "endTime" : 110, < "drawables" : [ < { < "image" : "/cinematics/story/esther/backgroundcircle.png:" < } < ], < "keyframes" : [ < { < "timecode" : 0.0, < "alpha" : 0.0, < "zoom" : 1.5, < "position" : [479, 280], < "frame" : 0 < }, < { < "timecode" : 0.5, < "alpha" : 1.0 < }, < { < "timecode" : 63.5, < "alpha" : 1.0 < }, < { < "timecode" : 64, < "frame" : 140, < "alpha" : 0 < } < ] < }, < < < // --------------------- Hologram 1 < { < "startTime" : 46, < "endTime" : 62, < "drawables" : [ < { < "image" : "/cinematics/story/esther/hologram1.png:" < } < ], < "animationFrames" : 2, < "keyframes" : [ < { < "timecode" : 0.0, < "alpha" : 0.0, < "zoom" : 1.35, < "position" : [479, 280], < "frame" : 0 < }, < { < "timecode" : 0.025, < "zoom" : 1.4 < }, < { < "timecode" : 0.25, < "alpha" : 0.5 < }, < { < "timecode" : 0.5, < "alpha" : 1.0 < }, < { < "timecode" : 3, < "alpha" : 1.0, < "zoom" : 1.5 < }, < { < "timecode" : 13, < "alpha" : 1.0 < }, < { < "timecode" : 14, < "frame" : 140, < "alpha" : 0 < } < ] < }, < < // --------------- eigth radio message < { < "startTime" : 46.0, < "endTime" : 54.0, < "drawables" : [ < { < "image" : "/interface/chatbubbles/esthertalk.png:" < } < ], < "animationFrames" : 2, < "text" : "Long ago, there was a force known as the Cultivator, it maintained balance in the universe.", < "textPosition" : { < "position" : [34, 21], < "vAnchor" : "top", < "wrapWidth" : 218 < }, < "keyframes" : [ < { < "timecode" : 0.0, < "alpha" : 1.0, < "zoom" : 1.0, < "position" : [366.5, 100], < "frame" : 0, < "textPercentage" : 0 < }, < { < "timecode" : 0.3, < "textPercentage" : 0 < }, < { < "timecode" : 2.5, < "frame" : 12, < "textPercentage" : 1 < } < ] < }, < < // --------------- ninth radio message < { < "startTime" : 54.0, < "endTime" : 62.0, < "drawables" : [ < { < "image" : "/interface/chatbubbles/esthertalk.png:" < } < ], < "animationFrames" : 2, < "text" : "Under its influence, harmony reigned. So it was for aeons.", < "textPosition" : { < "position" : [34, 21], < "vAnchor" : "top", < "wrapWidth" : 218 < }, < "keyframes" : [ < { < "timecode" : 0.0, < "alpha" : 1.0, < "zoom" : 1.0, < "position" : [366.5, 100], < "frame" : 0, < "textPercentage" : 0 < }, < { < "timecode" : 0.3, < "textPercentage" : 0 < }, < { < "timecode" : 2.5, < "frame" : 12, < "textPercentage" : 1 < } < ] < }, < < // --------------------- Hologram 2 < { < "startTime" : 62, < "endTime" : 86, < "drawables" : [ < { < "image" : "/cinematics/story/esther/hologram2.png:" < } < ], < "animationFrames" : 2, < "keyframes" : [ < { < "timecode" : 0.0, < "alpha" : 0.0, < "zoom" : 1.35, < "position" : [479, 280], < "frame" : 0 < }, < { < "timecode" : 0.025, < "zoom" : 1.4 < }, < { < "timecode" : 0.25, < "alpha" : 0.5 < }, < { < "timecode" : 0.5, < "alpha" : 1.0 < }, < { < "timecode" : 3, < "alpha" : 1.0, < "zoom" : 1.5 < }, < { < "timecode" : 23, < "alpha" : 1.0 < }, < { < "timecode" : 24, < "frame" : 240, < "alpha" : 0 < } < ] < }, < < < < // --------------- tenth radio message < { < "startTime" : 62.0, < "endTime" : 70.0, < "drawables" : [ < { < "image" : "/interface/chatbubbles/estherthoughtful.png:" < } < ], < "animationFrames" : 2, < "text" : "But this tranquility proved finite. A being arose, one of hate and destruction. It was the Ruin.", < "textPosition" : { < "position" : [34, 21], < "vAnchor" : "top", < "wrapWidth" : 218 < }, < "keyframes" : [ < { < "timecode" : 0.0, < "alpha" : 1.0, < "zoom" : 1.0, < "position" : [366.5, 100], < "frame" : 0, < "textPercentage" : 0 < }, < { < "timecode" : 0.3, < "textPercentage" : 0 < }, < { < "timecode" : 2.5, < "frame" : 12, < "textPercentage" : 1 < } < ] < }, < < // --------------- eleventh radio message < { < "startTime" : 70.0, < "endTime" : 78.0, < "drawables" : [ < { < "image" : "/interface/chatbubbles/esthersad.png:" < } < ], < "animationFrames" : 2, < "text" : "The Ruin could not abide life in any form, and reaped destruction upon the universe.", < "textPosition" : { < "position" : [34, 21], < "vAnchor" : "top", < "wrapWidth" : 218 < }, < "keyframes" : [ < { < "timecode" : 0.0, < "alpha" : 1.0, < "zoom" : 1.0, < "position" : [366.5, 100], < "frame" : 0, < "textPercentage" : 0 < }, < { < "timecode" : 0.3, < "textPercentage" : 0 < }, < { < "timecode" : 2.5, < "frame" : 12, < "textPercentage" : 1 < } < ] < }, < < // --------------- twelth radio message < { < "startTime" : 78.0, < "endTime" : 86.0, < "drawables" : [ < { < "image" : "/interface/chatbubbles/esthersad.png:" < } < ], < "animationFrames" : 2, < "text" : "It fought to blot out all life, and would have succeeded, but for the sacrifice of the Cultivator.", < "textPosition" : { < "position" : [34, 21], < "vAnchor" : "top", < "wrapWidth" : 218 < }, < "keyframes" : [ < { < "timecode" : 0.0, < "alpha" : 1.0, < "zoom" : 1.0, < "position" : [366.5, 100], < "frame" : 0, < "textPercentage" : 0 < }, < { < "timecode" : 0.3, < "textPercentage" : 0 < }, < { < "timecode" : 2.5, < "frame" : 12, < "textPercentage" : 1 < } < ] < }, < < // --------------------- Hologram 3 < { < "startTime" : 86, < "endTime" : 102, < "drawables" : [ < { < "image" : "/cinematics/story/esther/hologram3.png:" < } < ], < "animationFrames" : 2, < "keyframes" : [ < { < "timecode" : 0.0, < "alpha" : 0.0, < "zoom" : 1.35, < "position" : [479, 280], < "frame" : 0 < }, < { < "timecode" : 0.025, < "zoom" : 1.4 < }, < { < "timecode" : 0.25, < "alpha" : 0.5 < }, < { < "timecode" : 0.5, < "alpha" : 1.0 < }, < { < "timecode" : 3, < "alpha" : 1.0, < "zoom" : 1.5 < }, < { < "timecode" : 15, < "alpha" : 1.0 < }, < { < "timecode" : 16, < "frame" : 160, < "alpha" : 0 < } < ] < }, < < // --------------- thirteenth radio message < { < "startTime" : 86.0, < "endTime" : 94.0, < "drawables" : [ < { < "image" : "/interface/chatbubbles/esthertalk.png:" < } < ], < "animationFrames" : 2, < "text" : "The Cultivator rose against the Ruin, and succeeded in sealing it away.", < "textPosition" : { < "position" : [34, 21], < "vAnchor" : "top", < "wrapWidth" : 218 < }, < "keyframes" : [ < { < "timecode" : 0.0, < "alpha" : 1.0, < "zoom" : 1.0, < "position" : [366.5, 100], < "frame" : 0, < "textPercentage" : 0 < }, < { < "timecode" : 0.3, < "textPercentage" : 0 < }, < { < "timecode" : 2.5, < "frame" : 12, < "textPercentage" : 1 < } < ] < }, < < // --------------- fourteenth radio message < { < "startTime" : 94.0, < "endTime" : 102.0, < "drawables" : [ < { < "image" : "/interface/chatbubbles/esthersad.png:" < } < ], < "animationFrames" : 2, < "text" : "But in doing so, the Cultivator exhausted its power completely.", < "textPosition" : { < "position" : [34, 21], < "vAnchor" : "top", < "wrapWidth" : 218 < }, < "keyframes" : [ < { < "timecode" : 0.0, < "alpha" : 1.0, < "zoom" : 1.0, < "position" : [366.5, 100], < "frame" : 0, < "textPercentage" : 0 < }, < { < "timecode" : 0.3, < "textPercentage" : 0 < }, < { < "timecode" : 2.5, < "frame" : 12, < "textPercentage" : 1 < } < ] < }, < < // --------------------- Hologram 4 < { < "startTime" : 102, < "endTime" : 110, < "drawables" : [ < { < "image" : "/cinematics/story/esther/hologram4.png:" < } < ], < "animationFrames" : 2, < "keyframes" : [ < { < "timecode" : 0.0, < "alpha" : 0.0, < "zoom" : 1.35, < "position" : [479, 280], < "frame" : 0 < }, < { < "timecode" : 0.025, < "zoom" : 1.4 < }, < { < "timecode" : 0.25, < "alpha" : 0.5 < }, < { < "timecode" : 0.5, < "alpha" : 1.0 < }, < { < "timecode" : 3, < "alpha" : 1.0, < "zoom" : 1.5 < }, < { < "timecode" : 7, < "alpha" : 1.0 < }, < { < "timecode" : 8, < "frame" : 80, < "alpha" : 0 < } < ] < }, < < // --------------- fifteenth radio message < { < "startTime" : 102.0, < "endTime" : 110.0, < "drawables" : [ < { < "image" : "/interface/chatbubbles/estherthoughtful.png:" < } < ], < "animationFrames" : 2, < "text" : "Before its last energies dissipated, the Cultivator gifted six chosen races with precious artifacts.", < "textPosition" : { < "position" : [34, 21], < "vAnchor" : "top", < "wrapWidth" : 218 < }, < "keyframes" : [ < { < "timecode" : 0.0, < "alpha" : 1.0, < "zoom" : 1.0, < "position" : [366.5, 100], < "frame" : 0, < "textPercentage" : 0 < }, < { < "timecode" : 0.3, < "textPercentage" : 0 < }, < { < "timecode" : 2.5, < "frame" : 12, < "textPercentage" : 1 < } < ] < }, < < // --------------------- artifacts < { < "startTime" : 110, < "endTime" : 126, < "drawables" : [ < { < "image" : "/cinematics/story/esther/floatingartifacts.png:" < } < ], < "animationFrames" : 29, < "keyframes" : [ < { < "timecode" : 0.0, < "alpha" : 0.0, < "zoom" : 1.5, < "position" : [479, 280], < "frame" : 0 < }, < { < "timecode" : 0.5, < "alpha" : 1.0, < "zoom" : 1.5 < }, < { < "timecode" : 15, < "frame" : 170, < "alpha" : 1 < }, < { < "timecode" : 16, < "frame" : 170, < "alpha" : 0 < } < ] < }, < < // --------------- sixteenth radio message < { < "startTime" : 110.0, < "endTime" : 118.0, < "drawables" : [ < { < "image" : "/interface/chatbubbles/esthertalk.png:" < } < ], < "animationFrames" : 2, < "text" : "These six artifacts, when united, form the key that opens the gate to the Ruin.", < "textPosition" : { < "position" : [34, 21], < "vAnchor" : "top", < "wrapWidth" : 218 < }, < "keyframes" : [ < { < "timecode" : 0.0, < "alpha" : 1.0, < "zoom" : 1.0, < "position" : [366.5, 100], < "frame" : 0, < "textPercentage" : 0 < }, < { < "timecode" : 0.3, < "textPercentage" : 0 < }, < { < "timecode" : 2.5, < "frame" : 12, < "textPercentage" : 1 < } < ] < }, < < // --------------- seventeenth radio message < { < "startTime" : 118.0, < "endTime" : 126.0, < "drawables" : [ < { < "image" : "/interface/chatbubbles/esthertalk.png:" < } < ], < "animationFrames" : 2, < "text" : "The defenses are crumbling. We must unite the artifacts, reach the Ruin, and truly destroy it.", < "textPosition" : { < "position" : [34, 21], < "vAnchor" : "top", < "wrapWidth" : 218 < }, < "keyframes" : [ < { < "timecode" : 0.0, < "alpha" : 1.0, < "zoom" : 1.0, < "position" : [366.5, 100], < "frame" : 0, < "textPercentage" : 0 < }, < { < "timecode" : 0.3, < "textPercentage" : 0 < }, < { < "timecode" : 2.5, < "frame" : 12, < "textPercentage" : 1 < } < ] < }, < < // -------------------------------- spotlight 2 < { < "startTime" : 126, < "endTime" : 149, < "drawables" : [ < { < "image" : "/cinematics/respawn/spotlight.png" < } < ], < "keyframes" : [ < { < "timecode" : 0.0, < "alpha" : 0.0, < "zoom" : 1.5, < "position" : [480, 240] < }, < { < "timecode" : 0.5, < "alpha" : 1.0, < "zoom" : 1.5 < }, < { < "timecode" : 22, < "alpha" : 1 < }, < { < "timecode" : 22.5, < "alpha" : 0 < } < ] < }, < < // -------------------------------- Esther 2 < { < "startTime" : 126, < "endTime" : 149, < "drawables" : [ < { < "image" : "/cinematics/story/esther/esther.png:" < } < ], < "animationFrames" : 6, < "keyframes" : [ < { < "timecode" : 0.0, < "alpha" : 0.0, < "zoom" : 1.5, < "position" : [480, 280], < "frame" : 0 < }, < { < "timecode" : 0.5, < "alpha" : 1.0, < "zoom" : 1.5 < }, < { < "timecode" : 22, < "frame" : 50, < "alpha" : 1 < }, < { < "timecode" : 22.5, < "frame" : 50, < "alpha" : 0 < } < ] < }, < < // --------------- eighteenth radio message < { < "startTime" : 126.0, < "endTime" : 134.0, < "drawables" : [ < { < "image" : "/interface/chatbubbles/esthertalk.png:" < } < ], < "animationFrames" : 2, < "text" : "This is a lot to take in dear, and a huge request to make of you... But I would like your help.", < "textPosition" : { < "position" : [34, 21], < "vAnchor" : "top", < "wrapWidth" : 218 < }, < "keyframes" : [ < { < "timecode" : 0.0, < "alpha" : 1.0, < "zoom" : 1.0, < "position" : [366.5, 100], < "frame" : 0, < "textPercentage" : 0 < }, < { < "timecode" : 0.3, < "textPercentage" : 0 < }, < { < "timecode" : 2.5, < "frame" : 12, < "textPercentage" : 1 < } < ] < }, < < // --------------- nineteenth radio message < { < "startTime" : 134.0, < "endTime" : 140.0, < "drawables" : [ < { < "image" : "/interface/chatbubbles/esthertalk.png:" < } < ], < "animationFrames" : 2, < "text" : "The artifacts are scattered across the stars, I can't find them alone.", < "textPosition" : { < "position" : [34, 21], < "vAnchor" : "top", < "wrapWidth" : 218 < }, < "keyframes" : [ < { < "timecode" : 0.0, < "alpha" : 1.0, < "zoom" : 1.0, < "position" : [366.5, 100], < "frame" : 0, < "textPercentage" : 0 < }, < { < "timecode" : 0.3, < "textPercentage" : 0 < }, < { < "timecode" : 2.5, < "frame" : 12, < "textPercentage" : 1 < } < ] < }, < < // --------------- twentieth radio message < { < "startTime" : 140.0, < "endTime" : 148.0, < "drawables" : [ < { < "image" : "/interface/chatbubbles/esthertalk.png:" < } < ], < "animationFrames" : 2, < "text" : "We must find them and eradicate the Ruin, before other planets go the way of the Earth.", < "textPosition" : { < "position" : [34, 21], < "vAnchor" : "top", < "wrapWidth" : 218 < }, < "keyframes" : [ < { < "timecode" : 0.0, < "alpha" : 1.0, < "zoom" : 1.0, < "position" : [366.5, 100], < "frame" : 0, < "textPercentage" : 0 < }, < { < "timecode" : 0.3, < "textPercentage" : 0 < }, < { < "timecode" : 2.5, < "frame" : 12, < "textPercentage" : 1 < } < ] < } < < ], < < < < "audio" : [ < { < "timecode" : 2.25, < "endTimecode" : 4.5, < "loops" : -1, < "resource" : "/sfx/interface/aichatter1_loop.ogg" < }, < { < "timecode" : 10.25, < "endTimecode" : 12.5, < "loops" : -1, < "resource" : "/sfx/interface/aichatter1_loop.ogg" < }, < { < "timecode" : 18.25, < "endTimecode" : 20.5, < "loops" : -1, < "resource" : "/sfx/interface/aichatter1_loop.ogg" < }, < { < "timecode" : 24.25, < "endTimecode" : 26.5, < "loops" : -1, < "resource" : "/sfx/interface/aichatter1_loop.ogg" < }, < { < "timecode" : 30.25, < "endTimecode" : 32.5, < "loops" : -1, < "resource" : "/sfx/interface/aichatter1_loop.ogg" < }, < { < "timecode" : 38.25, < "endTimecode" : 40.5, < "loops" : -1, < "resource" : "/sfx/interface/aichatter1_loop.ogg" < }, < { < "timecode" : 46.25, < "endTimecode" : 48.5, < "loops" : -1, < "resource" : "/sfx/interface/aichatter1_loop.ogg" < }, < { < "timecode" : 54.25, < "endTimecode" : 56.5, < "loops" : -1, < "resource" : "/sfx/interface/aichatter1_loop.ogg" < }, < { < "timecode" : 62.25, < "endTimecode" : 64.5, < "loops" : -1, < "resource" : "/sfx/interface/aichatter1_loop.ogg" < }, < { < "timecode" : 70.25, < "endTimecode" : 72.5, < "loops" : -1, < "resource" : "/sfx/interface/aichatter1_loop.ogg" < }, < { < "timecode" : 78.25, < "endTimecode" : 80.5, < "loops" : -1, < "resource" : "/sfx/interface/aichatter1_loop.ogg" < }, < { < "timecode" : 86.25, < "endTimecode" : 88.5, < "loops" : -1, < "resource" : "/sfx/interface/aichatter1_loop.ogg" < }, < { < "timecode" : 94.25, < "endTimecode" : 96.5, < "loops" : -1, < "resource" : "/sfx/interface/aichatter1_loop.ogg" < }, < { < "timecode" : 102.25, < "endTimecode" : 104.5, < "loops" : -1, < "resource" : "/sfx/interface/aichatter1_loop.ogg" < }, < { < "timecode" : 110.25, < "endTimecode" : 112.5, < "loops" : -1, < "resource" : "/sfx/interface/aichatter1_loop.ogg" < }, < { < "timecode" : 118.25, < "endTimecode" : 120.5, < "loops" : -1, < "resource" : "/sfx/interface/aichatter1_loop.ogg" < }, < { < "timecode" : 126.25, < "endTimecode" : 128.5, < "loops" : -1, < "resource" : "/sfx/interface/aichatter1_loop.ogg" < }, < { < "timecode" : 134.25, < "endTimecode" : 136.5, < "loops" : -1, < "resource" : "/sfx/interface/aichatter1_loop.ogg" < }, < { < "timecode" : 140.25, < "endTimecode" : 142.5, < "loops" : -1, < "resource" : "/sfx/interface/aichatter1_loop.ogg" < }, < /* < { < "timecode" : 0, < "resource" : "/sfx/cinematics/esther_start.ogg" < }, < */ < { < "timecode" : 42, < "endTimeCode" : 156, < "resource" : "/sfx/cinematics/esther_story.ogg" < } < ] < } --- > { > "muteSfx" : true, > "muteMusic" : true, > "skippable" : false, > "letterbox" : false, > "backgroundColor" : [0, 0, 0, 255], > "backgroundFadeTime" : 0.5, > > "panels" : [ > // --------------------- statue 2 > { > "startTime" : 54, > "endTime" : 110, > "drawables" : [ > { > "image" : "/cinematics/story/esther/statue2.png" > } > ], > "keyframes" : [ > { > "timecode" : 0.0, > "alpha" : 0.0, > "zoom" : 1.5, > "position" : [600, -200], > "frame" : 0 > }, > { > "timecode" : 1, > "alpha" : 0, > "zoom" : 1.5, > "position" : [600, -200], > "frame" : 0 > }, > { > "timecode" : 55.49, > "alpha" : 1, > "position" : [600, 200] > }, > { > "timecode" : 55.5, > "position" : [600, 200], > "alpha" : 1 > }, > { > "timecode" : 56, > "frame" : 140, > "alpha" : 0 > } > ] > }, > > // --------------------- statue 1 > { > "startTime" : 40, > "endTime" : 110, > "drawables" : [ > { > "image" : "/cinematics/story/esther/statue1.png" > } > ], > "keyframes" : [ > { > "timecode" : 0.0, > "alpha" : 0.0, > "zoom" : 1.5, > "position" : [200, -200], > "frame" : 0 > }, > { > "timecode" : 1, > "alpha" : 0, > "zoom" : 1.5, > "position" : [200, -200], > "frame" : 0 > }, > { > "timecode" : 69.49, > "alpha" : 1, > "position" : [200, 120] > }, > { > "timecode" : 69.5, > "position" : [200, 120], > "alpha" : 1 > }, > { > "timecode" : 70, > "frame" : 140, > "alpha" : 0 > } > ] > }, > > > // -------------------------------- spotlight > { > "startTime" : 1, > "endTime" : 46, > "drawables" : [ > { > "image" : "/cinematics/story/esther/esthershadow.png" > } > ], > "keyframes" : [ > { > "timecode" : 0.0, > "alpha" : 0.0, > "zoom" : 1.5, > "position" : [485, 230] > }, > { > "timecode" : 0.5, > "alpha" : 1.0, > "zoom" : 1.5 > }, > { > "timecode" : 44, > "alpha" : 1 > }, > { > "timecode" : 44.5, > "alpha" : 0, > "frame" : 118 > } > ] > }, > > // -------------------------------- Esther > { > "startTime" : 1, > "endTime" : 46, > "drawables" : [ > { > "image" : "/cinematics/story/esther/esther.png:" > } > ], > "animationFrames" : 6, > "keyframes" : [ > { > "timecode" : 0.0, > "alpha" : 0.0, > "zoom" : 1.5, > "position" : [480, 280], > "frame" : 0 > }, > { > "timecode" : 0.5, > "alpha" : 1.0, > "zoom" : 1.5 > }, > { > "timecode" : 44, > "alpha" : 1, > "frame" : 110 > }, > { > "timecode" : 44.5, > "alpha" : 0, > "frame" : 110 > } > ] > }, > > // ------------------ radio message popup background > { > "startTime" : 1.5, > "endTime" : 148.5, > "drawables" : [ > { > "image" : "/cinematics/radiomessagebg.png:" > } > ], > "keyframes" : [ > { > "timecode" : 0.0, > "alpha" : 1.0, > "zoom" : 1.0, > "position" : [480, 100], > "frame" : 0 > }, > { > "timecode" : 0.5, > "frame" : 6 > }, > { > "timecode" : 146.5, > "frame" : 6 > }, > { > "timecode" : 147, > "frame" : 12 > } > ] > }, > > > > // ----------------- first radio message > { > "startTime" : 2.0, > "endTime" : 10.0, > "drawables" : [ > { > "image" : "/interface/chatbubbles/esthertalk.png:" > } > ], > "animationFrames" : 2, > "text" : "Hello, dear! Is that a Matter Manipulator you're carrying? Excellent, so you're a Protector.", > "textPosition" : { > "position" : [34, 21], > "vAnchor" : "top", > "wrapWidth" : 218 > }, > "keyframes" : [ > { > "timecode" : 0.0, > "alpha" : 1.0, > "zoom" : 1.0, > "position" : [366.5, 100], > "frame" : 0, > "textPercentage" : 0 > }, > { > "timecode" : 0.3, > "textPercentage" : 0 > }, > { > "timecode" : 2.5, > "frame" : 12, > "textPercentage" : 1 > } > > ] > }, > > // -------------------- second radio message > { > "startTime" : 10.0, > "endTime" : 18.0, > "drawables" : [ > { > "image" : "/interface/chatbubbles/esthersad.png:" > } > ], > "animationFrames" : 2, > "text" : "I'm sorry to say, perhaps the last, after the... The terrible destruction of Earth...", > "textPosition" : { > "position" : [34, 21], > "vAnchor" : "top", > "wrapWidth" : 218 > }, > "keyframes" : [ > { > "timecode" : 0.0, > "alpha" : 1.0, > "zoom" : 1.0, > "position" : [366.5, 100], > "frame" : 0, > "textPercentage" : 0 > }, > { > "timecode" : 0.3, > "textPercentage" : 0 > }, > { > "timecode" : 2.5, > "frame" : 12, > "textPercentage" : 1 > } > ] > }, > > //------------------------------- third radio message > { > "startTime" : 18.0, > "endTime" : 24.0, > "drawables" : [ > { > "image" : "/interface/chatbubbles/esthersad.png:" > } > ], > "animationFrames" : 2, > "text" : "It's sadly inevitable that we should meet now...", > "textPosition" : { > "position" : [34, 21], > "vAnchor" : "top", > "wrapWidth" : 218 > }, > "keyframes" : [ > { > "timecode" : 0.0, > "alpha" : 1.0, > "zoom" : 1.0, > "position" : [366.5, 100], > "frame" : 0, > "textPercentage" : 0 > }, > { > "timecode" : 0.3, > "textPercentage" : 0 > }, > { > "timecode" : 2.5, > "frame" : 12, > "textPercentage" : 1 > } > ] > }, > > // --------------- fourth radio message > { > "startTime" : 24.0, > "endTime" : 30.0, > "drawables" : [ > { > "image" : "/interface/chatbubbles/esthertalk.png:" > } > ], > "animationFrames" : 2, > "text" : "My name is ^orange;Esther Bright^white;, retired Grand Protector.", > "textPosition" : { > "position" : [34, 21], > "vAnchor" : "top", > "wrapWidth" : 218 > }, > "keyframes" : [ > { > "timecode" : 0.0, > "alpha" : 1.0, > "zoom" : 1.0, > "position" : [366.5, 100], > "frame" : 0, > "textPercentage" : 0 > }, > { > "timecode" : 0.3, > "textPercentage" : 0 > }, > { > "timecode" : 2.5, > "frame" : 12, > "textPercentage" : 1 > } > ] > }, > > // --------------- fifth radio message > { > "startTime" : 30.0, > "endTime" : 38.0, > "drawables" : [ > { > "image" : "/interface/chatbubbles/esthertalk.png:" > } > ], > "animationFrames" : 2, > "text" : "I left some years ago, an impossible decision; but my research could not be neglected.", > "textPosition" : { > "position" : [34, 21], > "vAnchor" : "top", > "wrapWidth" : 218 > }, > "keyframes" : [ > { > "timecode" : 0.0, > "alpha" : 1.0, > "zoom" : 1.0, > "position" : [366.5, 100], > "frame" : 0, > "textPercentage" : 0 > }, > { > "timecode" : 0.3, > "textPercentage" : 0 > }, > { > "timecode" : 2.5, > "frame" : 12, > "textPercentage" : 1 > } > ] > }, > > // --------------- sixth radio message > { > "startTime" : 38.0, > "endTime" : 46.0, > "drawables" : [ > { > "image" : "/interface/chatbubbles/estherthoughtful.png:" > } > ], > "animationFrames" : 2, > "text" : "I discovered things long forgotten that weigh heavy on the present.", > "textPosition" : { > "position" : [34, 21], > "vAnchor" : "top", > "wrapWidth" : 218 > }, > "keyframes" : [ > { > "timecode" : 0.0, > "alpha" : 1.0, > "zoom" : 1.0, > "position" : [366.5, 100], > "frame" : 0, > "textPercentage" : 0 > }, > { > "timecode" : 0.3, > "textPercentage" : 0 > }, > { > "timecode" : 2.5, > "frame" : 12, > "textPercentage" : 1 > } > ] > }, > > > // --------------------- background circle > { > "startTime" : 46, > "endTime" : 110, > "drawables" : [ > { > "image" : "/cinematics/story/esther/backgroundcircle.png:" > } > ], > "keyframes" : [ > { > "timecode" : 0.0, > "alpha" : 0.0, > "zoom" : 1.5, > "position" : [479, 280], > "frame" : 0 > }, > { > "timecode" : 0.5, > "alpha" : 1.0 > }, > { > "timecode" : 63.5, > "alpha" : 1.0 > }, > { > "timecode" : 64, > "frame" : 140, > "alpha" : 0 > } > ] > }, > > > // --------------------- Hologram 1 > { > "startTime" : 46, > "endTime" : 62, > "drawables" : [ > { > "image" : "/cinematics/story/esther/hologram1.png:" > } > ], > "animationFrames" : 2, > "keyframes" : [ > { > "timecode" : 0.0, > "alpha" : 0.0, > "zoom" : 1.35, > "position" : [479, 280], > "frame" : 0 > }, > { > "timecode" : 0.025, > "zoom" : 1.4 > }, > { > "timecode" : 0.25, > "alpha" : 0.5 > }, > { > "timecode" : 0.5, > "alpha" : 1.0 > }, > { > "timecode" : 3, > "alpha" : 1.0, > "zoom" : 1.5 > }, > { > "timecode" : 13, > "alpha" : 1.0 > }, > { > "timecode" : 14, > "frame" : 140, > "alpha" : 0 > } > ] > }, > > // --------------- eigth radio message > { > "startTime" : 46.0, > "endTime" : 54.0, > "drawables" : [ > { > "image" : "/interface/chatbubbles/esthertalk.png:" > } > ], > "animationFrames" : 2, > "text" : "Long ago, there was a force known as the Cultivator, it maintained balance in the universe.", > "textPosition" : { > "position" : [34, 21], > "vAnchor" : "top", > "wrapWidth" : 218 > }, > "keyframes" : [ > { > "timecode" : 0.0, > "alpha" : 1.0, > "zoom" : 1.0, > "position" : [366.5, 100], > "frame" : 0, > "textPercentage" : 0 > }, > { > "timecode" : 0.3, > "textPercentage" : 0 > }, > { > "timecode" : 2.5, > "frame" : 12, > "textPercentage" : 1 > } > ] > }, > > // --------------- ninth radio message > { > "startTime" : 54.0, > "endTime" : 62.0, > "drawables" : [ > { > "image" : "/interface/chatbubbles/esthertalk.png:" > } > ], > "animationFrames" : 2, > "text" : "Under its influence, harmony reigned. So it was for aeons.", > "textPosition" : { > "position" : [34, 21], > "vAnchor" : "top", > "wrapWidth" : 218 > }, > "keyframes" : [ > { > "timecode" : 0.0, > "alpha" : 1.0, > "zoom" : 1.0, > "position" : [366.5, 100], > "frame" : 0, > "textPercentage" : 0 > }, > { > "timecode" : 0.3, > "textPercentage" : 0 > }, > { > "timecode" : 2.5, > "frame" : 12, > "textPercentage" : 1 > } > ] > }, > > // --------------------- Hologram 2 > { > "startTime" : 62, > "endTime" : 86, > "drawables" : [ > { > "image" : "/cinematics/story/esther/hologram2.png:" > } > ], > "animationFrames" : 2, > "keyframes" : [ > { > "timecode" : 0.0, > "alpha" : 0.0, > "zoom" : 1.35, > "position" : [479, 280], > "frame" : 0 > }, > { > "timecode" : 0.025, > "zoom" : 1.4 > }, > { > "timecode" : 0.25, > "alpha" : 0.5 > }, > { > "timecode" : 0.5, > "alpha" : 1.0 > }, > { > "timecode" : 3, > "alpha" : 1.0, > "zoom" : 1.5 > }, > { > "timecode" : 23, > "alpha" : 1.0 > }, > { > "timecode" : 24, > "frame" : 240, > "alpha" : 0 > } > ] > }, > > > > // --------------- tenth radio message > { > "startTime" : 62.0, > "endTime" : 70.0, > "drawables" : [ > { > "image" : "/interface/chatbubbles/estherthoughtful.png:" > } > ], > "animationFrames" : 2, > "text" : "But this tranquility proved finite. A being arose, one of hate and destruction. It was the Ruin.", > "textPosition" : { > "position" : [34, 21], > "vAnchor" : "top", > "wrapWidth" : 218 > }, > "keyframes" : [ > { > "timecode" : 0.0, > "alpha" : 1.0, > "zoom" : 1.0, > "position" : [366.5, 100], > "frame" : 0, > "textPercentage" : 0 > }, > { > "timecode" : 0.3, > "textPercentage" : 0 > }, > { > "timecode" : 2.5, > "frame" : 12, > "textPercentage" : 1 > } > ] > }, > > // --------------- eleventh radio message > { > "startTime" : 70.0, > "endTime" : 78.0, > "drawables" : [ > { > "image" : "/interface/chatbubbles/esthersad.png:" > } > ], > "animationFrames" : 2, > "text" : "The Ruin could not abide life in any form, and reaped destruction upon the universe.", > "textPosition" : { > "position" : [34, 21], > "vAnchor" : "top", > "wrapWidth" : 218 > }, > "keyframes" : [ > { > "timecode" : 0.0, > "alpha" : 1.0, > "zoom" : 1.0, > "position" : [366.5, 100], > "frame" : 0, > "textPercentage" : 0 > }, > { > "timecode" : 0.3, > "textPercentage" : 0 > }, > { > "timecode" : 2.5, > "frame" : 12, > "textPercentage" : 1 > } > ] > }, > > // --------------- twelth radio message > { > "startTime" : 78.0, > "endTime" : 86.0, > "drawables" : [ > { > "image" : "/interface/chatbubbles/esthersad.png:" > } > ], > "animationFrames" : 2, > "text" : "It fought to blot out all life, and would have succeeded, but for the sacrifice of the Cultivator.", > "textPosition" : { > "position" : [34, 21], > "vAnchor" : "top", > "wrapWidth" : 218 > }, > "keyframes" : [ > { > "timecode" : 0.0, > "alpha" : 1.0, > "zoom" : 1.0, > "position" : [366.5, 100], > "frame" : 0, > "textPercentage" : 0 > }, > { > "timecode" : 0.3, > "textPercentage" : 0 > }, > { > "timecode" : 2.5, > "frame" : 12, > "textPercentage" : 1 > } > ] > }, > > // --------------------- Hologram 3 > { > "startTime" : 86, > "endTime" : 102, > "drawables" : [ > { > "image" : "/cinematics/story/esther/hologram3.png:" > } > ], > "animationFrames" : 2, > "keyframes" : [ > { > "timecode" : 0.0, > "alpha" : 0.0, > "zoom" : 1.35, > "position" : [479, 280], > "frame" : 0 > }, > { > "timecode" : 0.025, > "zoom" : 1.4 > }, > { > "timecode" : 0.25, > "alpha" : 0.5 > }, > { > "timecode" : 0.5, > "alpha" : 1.0 > }, > { > "timecode" : 3, > "alpha" : 1.0, > "zoom" : 1.5 > }, > { > "timecode" : 15, > "alpha" : 1.0 > }, > { > "timecode" : 16, > "frame" : 160, > "alpha" : 0 > } > ] > }, > > // --------------- thirteenth radio message > { > "startTime" : 86.0, > "endTime" : 94.0, > "drawables" : [ > { > "image" : "/interface/chatbubbles/esthertalk.png:" > } > ], > "animationFrames" : 2, > "text" : "The Cultivator rose against the Ruin, and succeeded in sealing it away.", > "textPosition" : { > "position" : [34, 21], > "vAnchor" : "top", > "wrapWidth" : 218 > }, > "keyframes" : [ > { > "timecode" : 0.0, > "alpha" : 1.0, > "zoom" : 1.0, > "position" : [366.5, 100], > "frame" : 0, > "textPercentage" : 0 > }, > { > "timecode" : 0.3, > "textPercentage" : 0 > }, > { > "timecode" : 2.5, > "frame" : 12, > "textPercentage" : 1 > } > ] > }, > > // --------------- fourteenth radio message > { > "startTime" : 94.0, > "endTime" : 102.0, > "drawables" : [ > { > "image" : "/interface/chatbubbles/esthersad.png:" > } > ], > "animationFrames" : 2, > "text" : "But in doing so, the Cultivator exhausted its power completely.", > "textPosition" : { > "position" : [34, 21], > "vAnchor" : "top", > "wrapWidth" : 218 > }, > "keyframes" : [ > { > "timecode" : 0.0, > "alpha" : 1.0, > "zoom" : 1.0, > "position" : [366.5, 100], > "frame" : 0, > "textPercentage" : 0 > }, > { > "timecode" : 0.3, > "textPercentage" : 0 > }, > { > "timecode" : 2.5, > "frame" : 12, > "textPercentage" : 1 > } > ] > }, > > // --------------------- Hologram 4 > { > "startTime" : 102, > "endTime" : 110, > "drawables" : [ > { > "image" : "/cinematics/story/esther/hologram4.png:" > } > ], > "animationFrames" : 2, > "keyframes" : [ > { > "timecode" : 0.0, > "alpha" : 0.0, > "zoom" : 1.35, > "position" : [479, 280], > "frame" : 0 > }, > { > "timecode" : 0.025, > "zoom" : 1.4 > }, > { > "timecode" : 0.25, > "alpha" : 0.5 > }, > { > "timecode" : 0.5, > "alpha" : 1.0 > }, > { > "timecode" : 3, > "alpha" : 1.0, > "zoom" : 1.5 > }, > { > "timecode" : 7, > "alpha" : 1.0 > }, > { > "timecode" : 8, > "frame" : 80, > "alpha" : 0 > } > ] > }, > > // --------------- fifteenth radio message > { > "startTime" : 102.0, > "endTime" : 110.0, > "drawables" : [ > { > "image" : "/interface/chatbubbles/estherthoughtful.png:" > } > ], > "animationFrames" : 2, > "text" : "Before its last energies dissipated, the Cultivator gifted six chosen races with precious artifacts.", > "textPosition" : { > "position" : [34, 21], > "vAnchor" : "top", > "wrapWidth" : 218 > }, > "keyframes" : [ > { > "timecode" : 0.0, > "alpha" : 1.0, > "zoom" : 1.0, > "position" : [366.5, 100], > "frame" : 0, > "textPercentage" : 0 > }, > { > "timecode" : 0.3, > "textPercentage" : 0 > }, > { > "timecode" : 2.5, > "frame" : 12, > "textPercentage" : 1 > } > ] > }, > > // --------------------- artifacts > { > "startTime" : 110, > "endTime" : 126, > "drawables" : [ > { > "image" : "/cinematics/story/esther/floatingartifacts.png:" > } > ], > "animationFrames" : 29, > "keyframes" : [ > { > "timecode" : 0.0, > "alpha" : 0.0, > "zoom" : 1.5, > "position" : [479, 280], > "frame" : 0 > }, > { > "timecode" : 0.5, > "alpha" : 1.0, > "zoom" : 1.5 > }, > { > "timecode" : 15, > "frame" : 170, > "alpha" : 1 > }, > { > "timecode" : 16, > "frame" : 170, > "alpha" : 0 > } > ] > }, > > // --------------- sixteenth radio message > { > "startTime" : 110.0, > "endTime" : 118.0, > "drawables" : [ > { > "image" : "/interface/chatbubbles/esthertalk.png:" > } > ], > "animationFrames" : 2, > "text" : "These six artifacts, when united, form the key that opens the gate to the Ruin.", > "textPosition" : { > "position" : [34, 21], > "vAnchor" : "top", > "wrapWidth" : 218 > }, > "keyframes" : [ > { > "timecode" : 0.0, > "alpha" : 1.0, > "zoom" : 1.0, > "position" : [366.5, 100], > "frame" : 0, > "textPercentage" : 0 > }, > { > "timecode" : 0.3, > "textPercentage" : 0 > }, > { > "timecode" : 2.5, > "frame" : 12, > "textPercentage" : 1 > } > ] > }, > > // --------------- seventeenth radio message > { > "startTime" : 118.0, > "endTime" : 126.0, > "drawables" : [ > { > "image" : "/interface/chatbubbles/esthertalk.png:" > } > ], > "animationFrames" : 2, > "text" : "The defenses are crumbling. We must unite the artifacts, reach the Ruin, and truly destroy it.", > "textPosition" : { > "position" : [34, 21], > "vAnchor" : "top", > "wrapWidth" : 218 > }, > "keyframes" : [ > { > "timecode" : 0.0, > "alpha" : 1.0, > "zoom" : 1.0, > "position" : [366.5, 100], > "frame" : 0, > "textPercentage" : 0 > }, > { > "timecode" : 0.3, > "textPercentage" : 0 > }, > { > "timecode" : 2.5, > "frame" : 12, > "textPercentage" : 1 > } > ] > }, > > // -------------------------------- spotlight 2 > { > "startTime" : 126, > "endTime" : 149, > "drawables" : [ > { > "image" : "/cinematics/respawn/spotlight.png" > } > ], > "keyframes" : [ > { > "timecode" : 0.0, > "alpha" : 0.0, > "zoom" : 1.5, > "position" : [480, 240] > }, > { > "timecode" : 0.5, > "alpha" : 1.0, > "zoom" : 1.5 > }, > { > "timecode" : 22, > "alpha" : 1 > }, > { > "timecode" : 22.5, > "alpha" : 0 > } > ] > }, > > // -------------------------------- Esther 2 > { > "startTime" : 126, > "endTime" : 149, > "drawables" : [ > { > "image" : "/cinematics/story/esther/esther.png:" > } > ], > "animationFrames" : 6, > "keyframes" : [ > { > "timecode" : 0.0, > "alpha" : 0.0, > "zoom" : 1.5, > "position" : [480, 280], > "frame" : 0 > }, > { > "timecode" : 0.5, > "alpha" : 1.0, > "zoom" : 1.5 > }, > { > "timecode" : 22, > "frame" : 50, > "alpha" : 1 > }, > { > "timecode" : 22.5, > "frame" : 50, > "alpha" : 0 > } > ] > }, > > // --------------- eighteenth radio message > { > "startTime" : 126.0, > "endTime" : 134.0, > "drawables" : [ > { > "image" : "/interface/chatbubbles/esthertalk.png:" > } > ], > "animationFrames" : 2, > "text" : "This is a lot to take in dear, and a huge request to make of you... But I would like your help.", > "textPosition" : { > "position" : [34, 21], > "vAnchor" : "top", > "wrapWidth" : 218 > }, > "keyframes" : [ > { > "timecode" : 0.0, > "alpha" : 1.0, > "zoom" : 1.0, > "position" : [366.5, 100], > "frame" : 0, > "textPercentage" : 0 > }, > { > "timecode" : 0.3, > "textPercentage" : 0 > }, > { > "timecode" : 2.5, > "frame" : 12, > "textPercentage" : 1 > } > ] > }, > > // --------------- nineteenth radio message > { > "startTime" : 134.0, > "endTime" : 140.0, > "drawables" : [ > { > "image" : "/interface/chatbubbles/esthertalk.png:" > } > ], > "animationFrames" : 2, > "text" : "The artifacts are scattered across the stars, I can't find them alone.", > "textPosition" : { > "position" : [34, 21], > "vAnchor" : "top", > "wrapWidth" : 218 > }, > "keyframes" : [ > { > "timecode" : 0.0, > "alpha" : 1.0, > "zoom" : 1.0, > "position" : [366.5, 100], > "frame" : 0, > "textPercentage" : 0 > }, > { > "timecode" : 0.3, > "textPercentage" : 0 > }, > { > "timecode" : 2.5, > "frame" : 12, > "textPercentage" : 1 > } > ] > }, > > // --------------- twentieth radio message > { > "startTime" : 140.0, > "endTime" : 148.0, > "drawables" : [ > { > "image" : "/interface/chatbubbles/esthertalk.png:" > } > ], > "animationFrames" : 2, > "text" : "We must find them and eradicate the Ruin, before other planets go the way of the Earth.", > "textPosition" : { > "position" : [34, 21], > "vAnchor" : "top", > "wrapWidth" : 218 > }, > "keyframes" : [ > { > "timecode" : 0.0, > "alpha" : 1.0, > "zoom" : 1.0, > "position" : [366.5, 100], > "frame" : 0, > "textPercentage" : 0 > }, > { > "timecode" : 0.3, > "textPercentage" : 0 > }, > { > "timecode" : 2.5, > "frame" : 12, > "textPercentage" : 1 > } > ] > } > > ], > > > > "audio" : [ > { > "timecode" : 2.25, > "endTimecode" : 4.5, > "loops" : -1, > "resource" : "/sfx/interface/aichatter1_loop.ogg" > }, > { > "timecode" : 10.25, > "endTimecode" : 12.5, > "loops" : -1, > "resource" : "/sfx/interface/aichatter1_loop.ogg" > }, > { > "timecode" : 18.25, > "endTimecode" : 20.5, > "loops" : -1, > "resource" : "/sfx/interface/aichatter1_loop.ogg" > }, > { > "timecode" : 24.25, > "endTimecode" : 26.5, > "loops" : -1, > "resource" : "/sfx/interface/aichatter1_loop.ogg" > }, > { > "timecode" : 30.25, > "endTimecode" : 32.5, > "loops" : -1, > "resource" : "/sfx/interface/aichatter1_loop.ogg" > }, > { > "timecode" : 38.25, > "endTimecode" : 40.5, > "loops" : -1, > "resource" : "/sfx/interface/aichatter1_loop.ogg" > }, > { > "timecode" : 46.25, > "endTimecode" : 48.5, > "loops" : -1, > "resource" : "/sfx/interface/aichatter1_loop.ogg" > }, > { > "timecode" : 54.25, > "endTimecode" : 56.5, > "loops" : -1, > "resource" : "/sfx/interface/aichatter1_loop.ogg" > }, > { > "timecode" : 62.25, > "endTimecode" : 64.5, > "loops" : -1, > "resource" : "/sfx/interface/aichatter1_loop.ogg" > }, > { > "timecode" : 70.25, > "endTimecode" : 72.5, > "loops" : -1, > "resource" : "/sfx/interface/aichatter1_loop.ogg" > }, > { > "timecode" : 78.25, > "endTimecode" : 80.5, > "loops" : -1, > "resource" : "/sfx/interface/aichatter1_loop.ogg" > }, > { > "timecode" : 86.25, > "endTimecode" : 88.5, > "loops" : -1, > "resource" : "/sfx/interface/aichatter1_loop.ogg" > }, > { > "timecode" : 94.25, > "endTimecode" : 96.5, > "loops" : -1, > "resource" : "/sfx/interface/aichatter1_loop.ogg" > }, > { > "timecode" : 102.25, > "endTimecode" : 104.5, > "loops" : -1, > "resource" : "/sfx/interface/aichatter1_loop.ogg" > }, > { > "timecode" : 110.25, > "endTimecode" : 112.5, > "loops" : -1, > "resource" : "/sfx/interface/aichatter1_loop.ogg" > }, > { > "timecode" : 118.25, > "endTimecode" : 120.5, > "loops" : -1, > "resource" : "/sfx/interface/aichatter1_loop.ogg" > }, > { > "timecode" : 126.25, > "endTimecode" : 128.5, > "loops" : -1, > "resource" : "/sfx/interface/aichatter1_loop.ogg" > }, > { > "timecode" : 134.25, > "endTimecode" : 136.5, > "loops" : -1, > "resource" : "/sfx/interface/aichatter1_loop.ogg" > }, > { > "timecode" : 140.25, > "endTimecode" : 142.5, > "loops" : -1, > "resource" : "/sfx/interface/aichatter1_loop.ogg" > }, > /* > { > "timecode" : 0, > "resource" : "/sfx/cinematics/esther_start.ogg" > }, > */ > { > "timecode" : 42, > "endTimecode" : 156, > "resource" : "/sfx/cinematics/esther_story.ogg" > } > ] > } collections\fossils.collection 147c147 < "title" : "T-Rex Fossil", --- > "title" : "T. rex Fossil", dialog\clues.config 4a5 > "I've heard rumours of powerful alien artifacts, somewhere out there in space..." 88c89 < } \ No newline at end of file --- > } dialog\cultist.config 4,5c4,5 < "default" : [ < "None shall pass!" --- > "default" : [ > "None shall pass!" 131c131 < } \ No newline at end of file --- > } dialog\miniknogthreats.config 5c5 < "Stand sharp, soldier!" --- > "Stand sharp, soldier!" 10,16c10,16 < "Enemies of the Miniknog!", < "Glory to Big Ape! Destroy the agitator!", < "Hostile sighted! Eliminate them!", < "For our glorious leader!", < "Enemy sighted! Fire at will!", < "Hostiles in sight!", < "Kill the dissident, get a promotion!" --- > "Enemies of the Miniknog!", > "Glory to Big Ape! Destroy the agitator!", > "Hostile sighted! Eliminate them!", > "For our glorious leader!", > "Enemy sighted! Fire at will!", > "Hostiles in sight!", > "Kill the dissident, get a promotion!" 20c20 < } \ No newline at end of file --- > } dialog\rebel.config 5c5 < "Stand sharp, soldier!" --- > "Stand sharp, soldier!" 17c17 < } \ No newline at end of file --- > } dialog\scientist.config 5c5 < "The Miniknog is not so easily overcome" --- > "The Miniknog is not so easily overcome" 24c24 < } \ No newline at end of file --- > } dungeons\blankTemplate.json [TMX file differences are left out for huge size.] dungeons\microdungeons\biomes\garden\gardenmicrodungeons.dungeon 7c7 < "anchor" : [ "archway", "archway1", "gardenbridge1", "gardenbridge2", "gardenhouseruin1", "grave1", "grave2", "graveyard", "graveyardflowers", "littlecave1", "mediumburriedruin", "mediumgardenflowers", "mediumgardenruin1", "mediumgardenruincamp", "mediumgardenruinplain", "mediumgardenruintall", "mediumruin", "smallcamp", "smallgardenflowers", "smallpile", "smallstonehouse", "smalltower", "smalltower2", "tunnelsmall1", "wall1", "wall2", "wall3", "well1", "well2", "well3" ], --- > "anchor" : [ "archway", "archway1", "gardenbridge1", "gardenbridge2", "gardenhouseruin1", "grave1", "grave2", "graveyard", "graveyardflowers", "littlecave1", "mediumburriedruin", "mediumgardenflowers", "mediumgardenruin1", "mediumgardenruincamp", "mediumgardenruinplain", "mediumgardenruintall", "mediumruin", "smallcamp", "smallgardenflowers", "smallpile", "smallstonehouse", "smalltower", "smalltower2", "tunnelsmall1", "wall1", "wall2", "wall3", "well1", "well2", "well3", "steps1" ], 224a225,231 > }, > { > "name" : "steps1", > "rules" : [ > [ "maxSpawnCount", [1] ] > ], > "def" : [ "tmx", "steps1.json" ] dungeons\other\outpost\outpost.json [TMX file differences are left out for huge size.] dungeons\other\outpost\outpost_full.json [TMX file differences are left out for huge size.] interface\ai\ai.config 197a198 > "hoverBG" : "/interface/ai/listitemscrollhover.png", 297a299 > "hoverBG" : "/interface/ai/listitemscrollhover.png", interface\cockpit\cockpit.config 428a429,439 > "goToPeacekeeper" : { > "zlevel" : 10, > "type" : "button", > "base" : "/interface/cockpit/peacekeeperbutton.png:inactive", > "hover" : "/interface/cockpit/peacekeeperbutton.png:hover", > "pressed" : "/interface/cockpit/peacekeeperbutton.png:inactive", > "position" : [4, 255], > "pressedOffset" : [0, 0], > "callback" : "goToPeacekeeper" > }, > 435c446 < "position" : [4, 255], --- > "position" : [4, 240], 838a850 > "goToPeacekeeper", 1263a1276 > "goToPeacekeeper", 1317a1331,1336 > > "trackedQuestMarkerImage" : "/interface/cockpit/trackedquestmarker.png", > "trackedQuestMarkerOffset" : [0, 9], > > "untrackedQuestMarkerImage" : "/interface/cockpit/untrackedquestmarker.png", > "untrackedQuestMarkerOffset" : [0, 9], interface\cockpit\cockpit.lua 107a108,112 > View.questLocations = {} > for _, p in pairs(player.questLocations()) do > table.insert(View.questLocations, {p[1], p[2] and "tracked" or "untracked"}) > end > 116c121,122 < if questWorldId and coordinate and player.isMapped(coordinate) then --- > local questLocation = player.currentQuestLocation() > if (questWorldId and coordinate) or questLocation then 121a128,134 > if player.getProperty("lastBountyAssignment") or player.getProperty("bountyAssignment") then > widget.setButtonEnabled("goToPeacekeeper", true) > else > > widget.setButtonEnabled("goToPeacekeeper", false) > end > 190c203,208 < self.focus = {system = coordinateSystem(coordinate), target = {"coordinate", coordinate}} --- > if player.isMapped(coordinate) then > self.focus = {system = coordinateSystem(coordinate), target = {"coordinate", coordinate}} > else > self.focus = {system = coordinateSystem(coordinate)} > end > return 192a211,226 > local questLocation = player.currentQuestLocation() > if questLocation then > self.focus = {system = locationCoordinate(questLocation.system), target = questLocation.location} > end > end > > function goToPeacekeeper() > local lastAssignment = player.getProperty("lastBountyAssignment") > local system > if not player.hasActiveQuest("bountyassignment") and lastAssignment ~= nil then > system = lastAssignment > else > local assignment = player.getProperty("bountyAssignment") > system = assignment.system > end > self.focus = {system = system, target = nil} 535c569,576 < return self.state:set(universeSystemTransition, systems, lines, self.focus.system, false) --- > if player.isMapped(self.focus.system) then > return self.state:set(universeSystemTransition, systems, lines, self.focus.system, false) > else > selection = self.focus.system > View:select(selection, {"coordinate", selection}) > View:showSystemInfo(selection) > self.focus = {} > end 875d915 < self.focus = {} 876a917 > self.focus = {} interface\cockpit\cockpitutil.lua 155a156,166 > function coordinateWorldId(coordinate) > worldId = string.format("CelestialWorld:%s:%s:%s", coordinate.location[1], coordinate.location[2], coordinate.location[3]) > if coordinate.planet ~= 0 then > worldId = string.format("%s:%s", worldId, coordinate.planet) > end > if coordinate.satellite ~= 0 then > worldId = string.format("%s:%s", worldId, coordinate.satellite) > end > return worldId > end > 163a175,249 > end > > celestialWrap = {} > > function celestialWrap.objectWarpActionWorld(uuid) > while true do > local world = celestial.objectWarpActionWorld(uuid) > if world ~= nil then > return world > end > coroutine.yield() > end > end > > function celestialWrap.planetParameters(p) > while true do > local parameters = celestial.planetParameters(p) > if parameters ~= nil then > return parameters > end > coroutine.yield() > end > end > > function celestialWrap.visitableParameters(p) > while true do > local parameters = celestial.visitableParameters(p) > -- visitableParameters can return nil if the planet isn't generated or if the planet isn't visitable > -- planetParameters only returns nil if the planet isn't generated > -- use planetParameters to see if the planet is generated > if celestial.planetParameters(p) ~= nil then > return parameters > end > coroutine.yield() > end > end > > function celestialWrap.planetName(p) > while true do > local name = celestial.planetName(p) > if name ~= nil then > return name > end > coroutine.yield() > end > end > > function celestialWrap.children(p) > while true do > local children = celestial.children(p) > if #children > 0 then > return children > end > coroutine.yield() > end > end > > function celestialWrap.scanSystems(region, includedTypes) > while true do > local systems = celestial.scanSystems(region, includedTypes) > if celestial.scanRegionFullyLoaded(region) then > return systems > end > coroutine.yield() > end > end > > function celestialWrap.scanConstellationLines(region) > while true do > local systems = celestial.scanConstellationLines(region) > if celestial.scanRegionFullyLoaded(region) then > return systems > end > coroutine.yield() > end interface\cockpit\cockpitview.lua 909a910 > self:questMarkUuid(uuid, self:sToScreen(position)) 923a925 > self:questMarkUuid(uuid, self:sToScreen(object.position)) 927a930 > self:questMarkUuid(uuid, self:sToScreen(position)) 983c986,987 < if compare(system, args.currentSystem) then --- > local isCurrentSystem = compare(system, args.currentSystem) > if isCurrentSystem then 990a995,1002 > > if not isCurrentSystem or not self.drawSystem then > for _, p in pairs(self.questLocations) do > if compare(system.location, p[1].system) then > self:drawQuestMarker(pos, p[2]) > end > end > end 1120c1132 < local position = celestial.planetPosition(planet) --- > local position = self:sToScreen(celestial.planetPosition(planet)) 1128c1140 < self.canvas:drawImage(image[1], self:sToScreen(position), scale, color, true) --- > self.canvas:drawImage(image[1], position, scale, color, true) 1142c1154 < self.canvas:drawImage(image, self:sToScreen(position), scale, color, true) --- > self.canvas:drawImage(image, position, scale, color, true) 1144a1157,1158 > > self:questMarkCoord(planet, position) 1165c1179 < local position = celestial.planetPosition(object) --- > local position = self:sToScreen(celestial.planetPosition(object)) 1171c1185,1203 < self.canvas:drawImageDrawable(image[1], self:sToScreen(position), scale, "white", angle) --- > self.canvas:drawImageDrawable(image[1], position, scale, "white", angle) > end > > self:questMarkCoord(object, position) > end > end > > function View:questMarkCoord(object, position) > for _, p in pairs(self.questLocations) do > if p[1].location and p[1].location[1] == "coordinate" and compare(object, p[1].location[2]) then > self:drawQuestMarker(position, p[2]) > end > end > end > > function View:questMarkUuid(uuid, position) > for _, p in pairs(self.questLocations) do > if p[1].location and p[1].location[1] == "object" and uuid == p[1].location[2] then > self:drawQuestMarker(position, p[2]) 1173a1206,1212 > end > > function View:drawQuestMarker(position, markerType) > local image = self.settings[markerType .. "QuestMarkerImage"] > local offset = self.settings[markerType .. "QuestMarkerOffset"] > position = vec2.add(position, offset) > self.canvas:drawImage(image, position, 0.5, "white", true) interface\confirmation\teleportconfirmation.config 161a162,170 > }, > "bounty" : { > "paneLayout" : "/interface/windowconfig/simpleconfirmation.config:paneLayout", > "icon" : "/interface/warping/icon.png", > "title" : "Teleport Confirmation", > "subtitle" : "Bounty Lair", > "message" : "\n\nThis console will teleport you to the target's hideout.", > "okCaption" : "Ready", > "cancelCaption" : "Not now" interface\optionsmenu\optionsmenu.config 107c107 < "value" : "MULTIPLAYER VIA STEAM / DISCORD" --- > "value" : "MULTIPLAYER VIA STEAM FRIENDS" interface\scripted\keytrader\keytradergui.lua 8c8 < self.seed = status.statusProperty("vaultKeySeed") --- > self.seed = player.getProperty("vaultKeySeed") 29c29 < status.setStatusProperty("vaultKeySeed", self.seed) --- > player.setProperty("vaultKeySeed", self.seed) interface\scripted\techupgrade\listitem.frames 1,10c1,11 < { < "frameGrid" : { < "size" : [119, 22], < "dimensions" : [1, 3], < "names" : [ < [ "inactive" ], < [ "active" ], < [ "disabled" ] < ] < } --- > { > "frameGrid" : { > "size" : [119, 22], > "dimensions" : [1, 4], > "names" : [ > [ "inactive" ], > [ "hover" ], > [ "active" ], > [ "disabled" ] > ] > } interface\scripted\techupgrade\techupgradegui.config 30a31 > "hoverBG" : "/interface/scripted/techupgrade/listitem.png:hover", interface\windowconfig\newquestshort.config 56c56 < "charLimit" : 12, --- > "charLimit" : 13, interface\windowconfig\questcomplete.config 37c37 < "charLimit" : 12, --- > "charLimit" : 13, interface\windowconfig\questfailed.config 35c35 < "charLimit" : 12, --- > "charLimit" : 13, interface\windowconfig\questlog.config 90c90 < "charLimit" : 12, --- > "charLimit" : 13, items\active\effects\lightning.lua 1,64c1,72 < require "/scripts/vec2.lua" < < function drawLightning(startLine, endLine, displacement, minDisplacement, forks, forkAngleRange, width, color) < if displacement < minDisplacement then < local position = startLine < endLine = vec2.sub(endLine, startLine) < startLine = {0,0} < localAnimator.addDrawable({line = {startLine, endLine}, width = width, color = color, position = position, fullbright = true}) < else < local mid = {(startLine[1] + endLine[1]) / 2, (startLine[2] + endLine[2]) / 2} < mid = vec2.add(mid, randomOffset(displacement)) < drawLightning(startLine, mid, displacement / 2, minDisplacement, forks - 1, forkAngleRange, width, color) < drawLightning(mid, endLine, displacement / 2, minDisplacement, forks - 1, forkAngleRange, width, color) < < if forks > 0 then < local direction = vec2.sub(mid, startLine) < local length = vec2.mag(direction) / 2 < local angle = math.atan(direction[2], direction[1]) + randomInRange(forkAngleRange) < forkEnd = vec2.mul({math.cos(angle), math.sin(angle)}, length) < drawLightning(mid, vec2.add(mid, forkEnd), displacement / 2, minDisplacement, forks - 1, forkAngleRange, width, color) < end < end < end < < function randomInRange(range) < return -range + math.random() * 2 * range < end < < function randomOffset(range) < return {randomInRange(range), randomInRange(range)} < end < < function update() < localAnimator.clearDrawables() < < local tickRate = animationConfig.animationParameter("lightningTickRate") or 25 < < local lightningSeed = animationConfig.animationParameter("lightningSeed") < if not lightningSeed then < local millis = math.floor((os.time() + (os.clock() % 1)) * 1000) < lightningSeed = math.floor(millis / tickRate) < end < math.randomseed(lightningSeed) < < local getLinePosition = function(bolt, positionType) < return bolt["world"..positionType.."Position"] < or (bolt["item"..positionType.."Position"] and vec2.add(activeItemAnimation.ownerPosition(), activeItemAnimation.handPosition(bolt["item"..positionType.."Position"]))) < or (bolt["part"..positionType.."Position"] and vec2.add(activeItemAnimation.ownerPosition(), < activeItemAnimation.handPosition(animationConfig.partPoint(bolt["part"..positionType.."Position"][1], bolt["part"..positionType.."Position"][2])))) < end < < local lightningBolts = animationConfig.animationParameter("lightning") < if lightningBolts then < for _, bolt in pairs(lightningBolts) do < local startPosition = getLinePosition(bolt, "Start") < local endPosition = getLinePosition(bolt, "End") < endPosition = vec2.add(startPosition, world.distance(endPosition, startPosition)) < if bolt.endPointDisplacement then < endPosition = vec2.add(endPosition, randomOffset(bolt.endPointDisplacement)) < end < drawLightning(startPosition, endPosition, bolt.displacement, bolt.minDisplacement, bolt.forks, bolt.forkAngleRange, bolt.width, bolt.color) < end < end < end --- > require "/scripts/vec2.lua" > > function drawLightning(startLine, endLine, displacement, minDisplacement, forks, forkAngleRange, width, color) > if displacement < minDisplacement then > local position = startLine > endLine = vec2.sub(endLine, startLine) > startLine = {0,0} > localAnimator.addDrawable({line = {startLine, endLine}, width = width, color = color, position = position, fullbright = true}) > else > local mid = {(startLine[1] + endLine[1]) / 2, (startLine[2] + endLine[2]) / 2} > mid = vec2.add(mid, randomOffset(displacement)) > drawLightning(startLine, mid, displacement / 2, minDisplacement, forks - 1, forkAngleRange, width, color) > drawLightning(mid, endLine, displacement / 2, minDisplacement, forks - 1, forkAngleRange, width, color) > > if forks > 0 then > local direction = vec2.sub(mid, startLine) > local length = vec2.mag(direction) / 2 > local angle = math.atan(direction[2], direction[1]) + randomInRange(forkAngleRange) > forkEnd = vec2.mul({math.cos(angle), math.sin(angle)}, length) > drawLightning(mid, vec2.add(mid, forkEnd), displacement / 2, minDisplacement, forks - 1, forkAngleRange, width, color) > end > end > end > > function randomInRange(range) > return -range + math.random() * 2 * range > end > > function randomOffset(range) > return {randomInRange(range), randomInRange(range)} > end > > function update() > localAnimator.clearDrawables() > > local tickRate = animationConfig.animationParameter("lightningTickRate") or 25 > > local lightningSeed = animationConfig.animationParameter("lightningSeed") > if not lightningSeed then > local millis = math.floor((os.time() + (os.clock() % 1)) * 1000) > lightningSeed = math.floor(millis / tickRate) > end > math.randomseed(lightningSeed) > > local ownerPosition = function() > if activeItemAnimation then > return activeItemAnimation.ownerPosition() > end > if entity then > return entity.position() > end > end > > local getLinePosition = function(bolt, positionType) > return bolt["world"..positionType.."Position"] > or (bolt["item"..positionType.."Position"] and vec2.add(ownerPosition(), activeItemAnimation.handPosition(bolt["item"..positionType.."Position"]))) > or (bolt["part"..positionType.."Position"] and vec2.add(ownerPosition(), animationConfig.partPoint(bolt["part"..positionType.."Position"][1], bolt["part"..positionType.."Position"][2]))) > end > > local lightningBolts = animationConfig.animationParameter("lightning") > if lightningBolts then > for _, bolt in pairs(lightningBolts) do > local startPosition = getLinePosition(bolt, "Start") > local endPosition = getLinePosition(bolt, "End") > endPosition = vec2.add(startPosition, world.distance(endPosition, startPosition)) > if bolt.endPointDisplacement then > endPosition = vec2.add(endPosition, randomOffset(bolt.endPointDisplacement)) > end > drawLightning(startPosition, endPosition, bolt.displacement, bolt.minDisplacement, bolt.forks, bolt.forkAngleRange, bolt.width, bolt.color) > end > end > end items\active\randomblueprint\mechblueprint3.activeitem 1,28c1,28 < { < "itemName" : "mechblueprint3", < "level" : 1, < "price" : 150, < "maxStack" : 1, < "rarity" : "Common", < "description" : "A blueprint for a simple mech part.", < "shortdescription" : "Simple Mech Blueprint", < "tooltipKind" : "base", < "category" : "Blueprint", < "twoHanded" : true, < < "inventoryIcon" : "mechblueprint3.png", < < "animation" : "randomblueprint.animation", < < "scripts" : ["randomblueprint.lua"], < < "swingTime" : 0.15, < < "allowDuplicateChance" : 0.15, < "recipes" : [ < ["mechbodypirate", "mechbodyreactor", "mechbodymilitary", "mechbodybad"], < ["mechboosterzed", "mechboosterstalwart", "mechboosterastro"], < ["mechlegstwinjet", "mechlegshopper", "mechlegsarc"], < ["mecharmheatrifle", "mecharmtommygun", "mecharmsplitshot"] < ] < } --- > { > "itemName" : "mechblueprint3", > "level" : 1, > "price" : 150, > "maxStack" : 1, > "rarity" : "Common", > "description" : "A blueprint for a simple mech part.", > "shortdescription" : "Simple Mech Blueprint", > "tooltipKind" : "base", > "category" : "Blueprint", > "twoHanded" : true, > > "inventoryIcon" : "mechblueprint3.png", > > "animation" : "randomblueprint.animation", > > "scripts" : ["randomblueprint.lua"], > > "swingTime" : 0.15, > > "allowDuplicateChance" : 0.1, > "recipes" : [ > ["mechbodypirate", "mechbodyreactor", "mechbodymilitary", "mechbodybad"], > ["mechboosterzed", "mechboosterstalwart", "mechboosterastro"], > ["mechlegstwinjet", "mechlegshopper", "mechlegsarc"], > ["mecharmheatrifle", "mecharmtommygun", "mecharmsplitshot"] > ] > } items\active\randomblueprint\mechblueprint4.activeitem 1,27c1,27 < { < "itemName" : "mechblueprint4", < "level" : 1, < "price" : 300, < "maxStack" : 1, < "rarity" : "Uncommon", < "description" : "A blueprint for an advanced mech part.", < "shortdescription" : "Advanced Mech Blueprint", < "tooltipKind" : "base", < "category" : "Blueprint", < "twoHanded" : true, < < "inventoryIcon" : "mechblueprint4.png", < < "animation" : "randomblueprint.animation", < < "scripts" : ["randomblueprint.lua"], < < "swingTime" : 0.15, < < "allowDuplicateChance" : 0.1, < "recipes" : [ < ["mechboostersleek"], < ["mechlegssleek"], < ["mecharmcannon", "mecharmgatling", "mecharmchainsaw", "mecharmhomingmissile", "mecharmplasmadrone", "mecharmclustermine", "mecharmwobbleshot"] < ] < } --- > { > "itemName" : "mechblueprint4", > "level" : 1, > "price" : 300, > "maxStack" : 1, > "rarity" : "Uncommon", > "description" : "A blueprint for an advanced mech part.", > "shortdescription" : "Advanced Mech Blueprint", > "tooltipKind" : "base", > "category" : "Blueprint", > "twoHanded" : true, > > "inventoryIcon" : "mechblueprint4.png", > > "animation" : "randomblueprint.animation", > > "scripts" : ["randomblueprint.lua"], > > "swingTime" : 0.15, > > "allowDuplicateChance" : 0.1, > "recipes" : [ > ["mechboostersleek"], > ["mechlegssleek"], > ["mecharmcannon", "mecharmgatling", "mecharmchainsaw", "mecharmhomingmissile", "mecharmplasmadrone", "mecharmclustermine", "mecharmwobbleshot"] > ] > } items\active\randomblueprint\mechblueprint5.activeitem 1,28c1,28 < { < "itemName" : "mechblueprint5", < "level" : 1, < "price" : 500, < "maxStack" : 1, < "rarity" : "Rare", < "description" : "A blueprint for a high-tech mech part.", < "shortdescription" : "High-Tech Mech Blueprint", < "tooltipKind" : "base", < "category" : "Blueprint", < "twoHanded" : true, < < "inventoryIcon" : "mechblueprint5.png", < < "animation" : "randomblueprint.animation", < < "scripts" : ["randomblueprint.lua"], < < "swingTime" : 0.15, < < "allowDuplicateChance" : 0.15, < "recipes" : [ < ["mechbodyhero", "mechbodyskull", "mechbodyshark"], < ["mechboostergallant", "mechboosterzero", "mechboosterhammer"], < ["mechlegsronin", "mechlegsintrepid", "mechlegshermes"], < ["mecharmenergyrifle", "mecharmdualrifle", "mecharmenergyblade", "mecharmguidedmissiles", "mecharmshielddrone", "mecharmspikefist", "mecharmbeamdrill"] < ] < } --- > { > "itemName" : "mechblueprint5", > "level" : 1, > "price" : 500, > "maxStack" : 1, > "rarity" : "Rare", > "description" : "A blueprint for a high-tech mech part.", > "shortdescription" : "High-Tech Mech Blueprint", > "tooltipKind" : "base", > "category" : "Blueprint", > "twoHanded" : true, > > "inventoryIcon" : "mechblueprint5.png", > > "animation" : "randomblueprint.animation", > > "scripts" : ["randomblueprint.lua"], > > "swingTime" : 0.15, > > "allowDuplicateChance" : 0.1, > "recipes" : [ > ["mechbodyhero", "mechbodyskull", "mechbodyshark"], > ["mechboostergallant", "mechboosterzero", "mechboosterhammer"], > ["mechlegsronin", "mechlegsintrepid", "mechlegshermes"], > ["mecharmenergyrifle", "mecharmdualrifle", "mecharmenergyblade", "mecharmguidedmissiles", "mecharmshielddrone", "mecharmspikefist", "mecharmbeamdrill"] > ] > } items\active\randomblueprint\mechblueprint6.activeitem 1,26c1,26 < { < "itemName" : "mechblueprint6", < "level" : 1, < "price" : 800, < "maxStack" : 1, < "rarity" : "Legendary", < "description" : "A blueprint for an experimental high-tech mech part.", < "shortdescription" : "Experimental Mech Blueprint", < "tooltipKind" : "base", < "category" : "Blueprint", < "twoHanded" : true, < < "inventoryIcon" : "mechblueprint6.png", < < "animation" : "randomblueprint.animation", < < "scripts" : ["randomblueprint.lua"], < < "swingTime" : 0.15, < < "allowDuplicateChance" : 0.1, < "recipes" : [ < ["mechbodyexodus", "mechbodyiris"], < ["mecharmteslastream", "mecharmmultidrone", "mecharmbeamsniper", "mecharmgravitymine"] < ] < } --- > { > "itemName" : "mechblueprint6", > "level" : 1, > "price" : 800, > "maxStack" : 1, > "rarity" : "Legendary", > "description" : "A blueprint for an experimental high-tech mech part.", > "shortdescription" : "Experimental Mech Blueprint", > "tooltipKind" : "base", > "category" : "Blueprint", > "twoHanded" : true, > > "inventoryIcon" : "mechblueprint6.png", > > "animation" : "randomblueprint.animation", > > "scripts" : ["randomblueprint.lua"], > > "swingTime" : 0.15, > > "allowDuplicateChance" : 0.1, > "recipes" : [ > ["mechbodyexodus", "mechbodyiris"], > ["mecharmteslastream", "mecharmmultidrone", "mecharmbeamsniper", "mecharmgravitymine"] > ] > } items\active\randomblueprint\randomblueprint.lua 1,55c1,55 < function init() < self.duplicateChance = config.getParameter("duplicateChance") < self.recipes = config.getParameter("recipes") < self.swingTime = config.getParameter("swingTime") < activeItem.setArmAngle(-math.pi / 2) < end < < function update(dt, fireMode, shiftHeld) < updateAim() < < if not self.swingTimer and fireMode == "primary" and player then < self.swingTimer = self.swingTime < end < < if self.swingTimer then < self.swingTimer = math.max(0, self.swingTimer - dt) < < activeItem.setArmAngle((-math.pi / 2) * (self.swingTimer / self.swingTime)) < < if self.swingTimer == 0 then < learnBlueprint() < end < end < end < < function learnBlueprint() < local itemName = chooseRecipe(self.recipes) < while player.blueprintKnown(recipe) and math.random() > self.duplicateChance do < itemName = chooseRecipe(self.recipes) < end < < if player.blueprintKnown(itemName) then < player.giveItem(itemName .. "-recipe") < else < player.giveBlueprint(itemName) < end < < animator.playSound("learnBlueprint") < < item.consume(1) < end < < function chooseRecipe(recipeOrRecipes) < if type(recipeOrRecipes) == "table" then < local choice = recipeOrRecipes[math.random(1, #recipeOrRecipes)] < return chooseRecipe(choice) < else < return recipeOrRecipes < end < end < < function updateAim() < self.aimAngle, self.aimDirection = activeItem.aimAngleAndDirection(0, activeItem.ownerAimPosition()) < activeItem.setFacingDirection(self.aimDirection) < end --- > function init() > self.duplicateChance = config.getParameter("allowDuplicateChance") > self.recipes = config.getParameter("recipes") > self.swingTime = config.getParameter("swingTime") > activeItem.setArmAngle(-math.pi / 2) > end > > function update(dt, fireMode, shiftHeld) > updateAim() > > if not self.swingTimer and fireMode == "primary" and player then > self.swingTimer = self.swingTime > end > > if self.swingTimer then > self.swingTimer = math.max(0, self.swingTimer - dt) > > activeItem.setArmAngle((-math.pi / 2) * (self.swingTimer / self.swingTime)) > > if self.swingTimer == 0 then > learnBlueprint() > end > end > end > > function learnBlueprint() > local itemName = chooseRecipe(self.recipes) > while player.blueprintKnown(itemName) and math.random() > self.duplicateChance do > itemName = chooseRecipe(self.recipes) > end > > if player.blueprintKnown(itemName) then > player.giveItem(itemName .. "-recipe") > else > player.giveBlueprint(itemName) > end > > animator.playSound("learnBlueprint") > > item.consume(1) > end > > function chooseRecipe(recipeOrRecipes) > if type(recipeOrRecipes) == "table" then > local choice = recipeOrRecipes[math.random(1, #recipeOrRecipes)] > return chooseRecipe(choice) > else > return recipeOrRecipes > end > end > > function updateAim() > self.aimAngle, self.aimDirection = activeItem.aimAngleAndDirection(0, activeItem.ownerAimPosition()) > activeItem.setFacingDirection(self.aimDirection) > end items\active\weapons\melee\pickaxe\energypickaxe.activeitem 1,62c1,65 < { < "itemName" : "energypickaxe", < "price" : 5000, < "maxStack" : 1, < "rarity" : "Legendary", < "category" : "tool", < "description" : "A mining tool unlike anything you've seen in other media.", < "shortdescription" : "Energy Pickaxe", < "tooltipKind" : "base", < "twoHanded" : true, < "itemTags" : ["miningtool", "pickaxe"], < < "inventoryIcon" : "energypickaxeicon.png", < < "animation" : "/items/active/weapons/melee/pickaxe/energypickaxe.animation", < "animationParts" : { < "handle" : "energypickaxehandle.png", < "blade" : "energypickaxehead.png" < }, < < "scripts" : ["/items/active/weapons/melee/meleeweapon.lua"], < < "elementalType" : "physical", < < "primaryAbilityType" : "pickslash", < "primaryAbility" : { < "layer" : "foreground", < < "activatingFireMode" : "primary", < "energyUsage" : 5, < < "requisiteAnimationStates" : { < "blade" : "active" < }, < "windupAnimationStates" : { < "blade" : "activating" < }, < "onLeaveAnimationStates" : { < "blade" : "deactivating" < } < }, < < "altAbilityType" : "pickslash", < "altAbility" : { < "layer" : "background", < < "activatingFireMode" : "alt", < "energyUsage" : 5, < < "requisiteAnimationStates" : { < "blade" : "active" < }, < "windupAnimationStates" : { < "blade" : "activating" < }, < "onLeaveAnimationStates" : { < "blade" : "deactivating" < } < }, < < "builder" : "/items/buildscripts/buildunrandweapon.lua" < } --- > { > "itemName" : "energypickaxe", > "price" : 5000, > "maxStack" : 1, > "rarity" : "Legendary", > "category" : "tool", > "description" : "A mining tool unlike anything you've seen in other media.", > "shortdescription" : "Energy Pickaxe", > "tooltipKind" : "base", > "twoHanded" : true, > "itemTags" : ["miningtool", "pickaxe"], > > "inventoryIcon" : "energypickaxeicon.png", > > "animation" : "/items/active/weapons/melee/pickaxe/energypickaxe.animation", > "animationParts" : { > "handle" : "energypickaxehandle.png", > "blade" : "energypickaxehead.png" > }, > > "scripts" : ["/items/active/weapons/melee/meleeweapon.lua"], > > "elementalType" : "physical", > > "primaryAbilityType" : "pickslash", > "primaryAbility" : { > "layer" : "foreground", > > "activatingFireMode" : "primary", > "energyUsage" : 5, > > "requisiteAnimationStates" : { > "blade" : "active" > }, > "windupAnimationStates" : { > "blade" : "activating" > }, > "onLeaveAnimationStates" : { > "blade" : "deactivating" > } > }, > > "altAbilityType" : "pickslash", > "altAbility" : { > "layer" : "background", > > "activatingFireMode" : "alt", > "energyUsage" : 5, > > "requisiteAnimationStates" : { > "blade" : "active" > }, > "windupAnimationStates" : { > "blade" : "activating" > }, > "onLeaveAnimationStates" : { > "blade" : "deactivating" > }, > "inactiveAnimationStates" : { > "blade" : "inactive" > } > }, > > "builder" : "/items/buildscripts/buildunrandweapon.lua" > } items\active\weapons\melee\pickaxe\energypickaxe.animation 1,133c1,134 < { < "globalTagDefaults" : { < "paletteSwaps" : "" < }, < < "animatedParts" : { < "stateTypes" : { < "blade" : { < "default" : "inactive", < "states" : { < "inactive" : { < "properties" : { < "lightsOff" : ["blade"] < } < }, < "activating" : { < "frames" : 5, < "cycle" : 0.4, < "mode" : "transition", < "transition" : "active", < "properties" : { < "lightsOn" : ["blade"], < "immediateSound" : "/sfx/tools/energypickaxe_start.ogg", < "particleEmittersOn" : ["activeparticles"] < } < }, < "active" : { < "frames" : 8, < "cycle" : 0.4, < "mode" : "loop", < "properties" : { < "lightsOn" : ["blade"], < "persistentSound" : "/sfx/tools/energypickaxe_idle.ogg", < "particleEmittersOn" : ["activeparticles"] < } < }, < "deactivating" : { < "frames" : 5, < "cycle" : 0.4, < "mode" : "transition", < "transition" : "inactive", < "properties" : { < "lightsOn" : ["blade"], < "immediateSound" : "/sfx/tools/energypickaxe_stop2.ogg", < "particleEmittersOff" : ["activeparticles"] < } < } < } < } < }, < < "parts" : { < "blade" : { < "properties" : { < "zLevel" : 0, < "centered" : true, < "offset" : [0, 1], < "transformationGroups" : ["weapon"], < "rotationCenter" : [0, 0], < "damageArea" : [ [-0.7, -1.0], [-0.7, 2.5], [0.5, 2.5], [0.5, -1.0] ], < "fullbright" : true < }, < "partStates" : { < "blade" : { < "inactive" : { < "properties" : { < "image" : ":inactive.??" < } < }, < "activating" : { < "properties" : { < "image" : ":activating.??" < } < }, < "active" : { < "properties" : { < "image" : ":active.??" < } < }, < "deactivating" : { < "properties" : { < "image" : ":deactivating.??" < } < } < } < } < }, < "handle" : { < "properties" : { < "zLevel" : 1, < "centered" : true, < "image" : "?", < "offset" : [0, 1], < "transformationGroups" : ["weapon"], < "rotationCenter" : [0, 0] < } < } < } < }, < < "transformationGroups" : { < "weapon" : {}, < "swoosh" : {} < }, < < "particleEmitters" : { < "activeparticles" : { < "active" : false, < "transformationGroups" : ["weapon"], < "emissionRate" : 3, < "offsetRegion" : [0.25, 3.5, 0.40, 0], < "particles" : [ < { "particle" : "energyblade"}, < { "particle" : "energyblade"}, < { "particle" : "energyblade2"}, < { "particle" : "energyblade2"} < ] < } < }, < < "lights" : { < "blade" : { < "active" : false, < "position" : [0, 0], < "color" : [164, 81, 196] < } < }, < < "sounds" : { < "fire" : [ "/sfx/tools/energypickaxe_hit2.ogg", "/sfx/tools/energypickaxe_hit3.ogg", "/sfx/tools/energypickaxe_hit4.ogg", "/sfx/tools/energypickaxe_hit5.ogg", "/sfx/tools/energypickaxe_hit6.ogg", "/sfx/tools/energypickaxe_hit7.ogg", "/sfx/tools/energypickaxe_hit8.ogg" ], < "blockSound" : [ ] < } < } --- > { > "globalTagDefaults" : { > "paletteSwaps" : "" > }, > > "animatedParts" : { > "stateTypes" : { > "blade" : { > "default" : "inactive", > "states" : { > "inactive" : { > "properties" : { > "lightsOff" : ["blade"], > "particleEmittersOff" : ["activeparticles"] > } > }, > "activating" : { > "frames" : 5, > "cycle" : 0.4, > "mode" : "transition", > "transition" : "active", > "properties" : { > "lightsOn" : ["blade"], > "immediateSound" : "/sfx/tools/energypickaxe_start.ogg", > "particleEmittersOn" : ["activeparticles"] > } > }, > "active" : { > "frames" : 8, > "cycle" : 0.4, > "mode" : "loop", > "properties" : { > "lightsOn" : ["blade"], > "persistentSound" : "/sfx/tools/energypickaxe_idle.ogg", > "particleEmittersOn" : ["activeparticles"] > } > }, > "deactivating" : { > "frames" : 5, > "cycle" : 0.4, > "mode" : "transition", > "transition" : "inactive", > "properties" : { > "lightsOn" : ["blade"], > "immediateSound" : "/sfx/tools/energypickaxe_stop2.ogg", > "particleEmittersOff" : ["activeparticles"] > } > } > } > } > }, > > "parts" : { > "blade" : { > "properties" : { > "zLevel" : 0, > "centered" : true, > "offset" : [0, 1], > "transformationGroups" : ["weapon"], > "rotationCenter" : [0, 0], > "damageArea" : [ [-0.7, -1.0], [-0.7, 2.5], [0.5, 2.5], [0.5, -1.0] ], > "fullbright" : true > }, > "partStates" : { > "blade" : { > "inactive" : { > "properties" : { > "image" : ":inactive.??" > } > }, > "activating" : { > "properties" : { > "image" : ":activating.??" > } > }, > "active" : { > "properties" : { > "image" : ":active.??" > } > }, > "deactivating" : { > "properties" : { > "image" : ":deactivating.??" > } > } > } > } > }, > "handle" : { > "properties" : { > "zLevel" : 1, > "centered" : true, > "image" : "?", > "offset" : [0, 1], > "transformationGroups" : ["weapon"], > "rotationCenter" : [0, 0] > } > } > } > }, > > "transformationGroups" : { > "weapon" : {}, > "swoosh" : {} > }, > > "particleEmitters" : { > "activeparticles" : { > "active" : false, > "transformationGroups" : ["weapon"], > "emissionRate" : 3, > "offsetRegion" : [0.25, 3.5, 0.40, 0], > "particles" : [ > { "particle" : "energyblade"}, > { "particle" : "energyblade"}, > { "particle" : "energyblade2"}, > { "particle" : "energyblade2"} > ] > } > }, > > "lights" : { > "blade" : { > "active" : false, > "position" : [0, 0], > "color" : [164, 81, 196] > } > }, > > "sounds" : { > "fire" : [ "/sfx/tools/energypickaxe_hit2.ogg", "/sfx/tools/energypickaxe_hit3.ogg", "/sfx/tools/energypickaxe_hit4.ogg", "/sfx/tools/energypickaxe_hit5.ogg", "/sfx/tools/energypickaxe_hit6.ogg", "/sfx/tools/energypickaxe_hit7.ogg", "/sfx/tools/energypickaxe_hit8.ogg" ], > "blockSound" : [ ] > } > } items\active\weapons\melee\pickaxe\pickslash.lua 1,148c1,149 < require "/scripts/util.lua" < require "/scripts/vec2.lua" < require "/items/active/weapons/weapon.lua" < < -- Pickaxe primary ability < PickSlash = WeaponAbility:new() < < function PickSlash:init() < self.weapon:setStance(self.stances.idle) < < self.weapon.onLeaveAbility = function() < self.weapon:setStance(self.stances.idle) < self:setAnimationStates(self.onLeaveAnimationStates) < end < end < < function PickSlash:setAnimationStates(states) < for stateType, state in pairs(states or {}) do < animator.setAnimationState(stateType, state) < end < end < < -- Ticks on every update regardless if this is the active ability < function PickSlash:update(dt, fireMode, shiftHeld) < WeaponAbility.update(self, dt, fireMode, shiftHeld) < < if not self.weapon.currentAbility and self:shouldFire() then < self:setState(self.windup) < end < end < < function PickSlash:bladeReady() < for stateType, state in pairs(self.requisiteAnimationStates or {}) do < if animator.animationState(stateType) ~= state then < return false < end < end < return true < end < < function PickSlash:canFire() < return not status.resourceLocked("energy") and status.resourcePositive("energy") < end < < function PickSlash:shouldFire() < return self:canFire() and self.fireMode == self.activatingFireMode < end < < -- State: windup < function PickSlash:windup() < self.weapon:setStance(self.stances.windup) < self.weapon:updateAim() < < if not self:bladeReady() then < self:setAnimationStates(self.windupAnimationStates) < end < < while not self:bladeReady() do < coroutine.yield() < end < < if self:shouldFire() then < self:setState(self.fire) < end < end < < -- State: fire < function PickSlash:fire() < local entityPosition = world.entityPosition(activeItem.ownerEntityId()) < self.hitPosition = activeItem.ownerAimPosition() < local distance = vec2.mag(world.distance(entityPosition, self.hitPosition)) < if distance > self.toolRange then < coroutine.yield() < self:setState(self.windup) < return < end < < local radius = self.shiftHeld and self.altBlockRadius or self.blockRadius < local brushArea = self:tileAreaBrush(radius, self.hitPosition) < < if not world.damageTiles(brushArea, self.layer, entityPosition, self.tileDamageType, self.tileDamage, self.harvestLevel) then < coroutine.yield() < self:setState(self.windup) < return < end < status.overConsumeResource("energy", self.energyUsage) < < animator.setSoundPool("blockSound", {self:getBlockSound(brushArea)}) < < self.weapon:setStance(self.stances.fire) < self.weapon:updateAim() < < coroutine.yield() < < animator.playSound("blockSound") < animator.playSound("fire") < < util.wait(self.stances.fire.duration) < < if self:shouldFire() then < self:setState(self.fire) < end < end < < function PickSlash:getBlockSound(brushArea) < local defaultFootstepSound = root.assetJson("/client.config:defaultFootstepSound") < < for _,pos in pairs(brushArea) do < if world.isTileProtected(pos) then < return root.assetJson("/client.config:defaultDingSound") < end < end < < for _,pos in pairs(brushArea) do < local material = world.material(pos, self.layer) < local mod = world.mod(pos, self.layer) < local blockSound = type(material) == "string" and root.materialMiningSound(material, mod) < if blockSound then return blockSound end < end < < for _,pos in pairs(brushArea) do < local material = world.material(pos, self.layer) < local mod = world.mod(pos, self.layer) < local blockSound = type(material) == "string" and root.materialFootstepSound(material, mod) < if blockSound and blockSound ~= defaultFootstepSound then < return blockSound < end < end < < return nil < end < < function PickSlash:tileAreaBrush(radius, centerPosition) < local result = jarray() < local offset = {-radius/2, -radius/2} < local intOffset = util.map(vec2.add(offset, centerPosition), util.round) < < for x = 0, radius-1 do < for y = 0, radius-1 do < local intPos = util.map({x, y}, util.round) < table.insert(result, vec2.add(intPos, intOffset)) < end < end < return result < end < < function PickSlash:uninit() < end --- > require "/scripts/util.lua" > require "/scripts/vec2.lua" > require "/items/active/weapons/weapon.lua" > > -- Pickaxe primary ability > PickSlash = WeaponAbility:new() > > function PickSlash:init() > self.weapon:setStance(self.stances.idle) > > self.weapon.onLeaveAbility = function() > self.weapon:setStance(self.stances.idle) > self:setAnimationStates(self.onLeaveAnimationStates) > end > end > > function PickSlash:setAnimationStates(states) > for stateType, state in pairs(states or {}) do > animator.setAnimationState(stateType, state) > end > end > > -- Ticks on every update regardless if this is the active ability > function PickSlash:update(dt, fireMode, shiftHeld) > WeaponAbility.update(self, dt, fireMode, shiftHeld) > > if not self.weapon.currentAbility and self:shouldFire() then > self:setState(self.windup) > end > end > > function PickSlash:bladeReady() > for stateType, state in pairs(self.requisiteAnimationStates or {}) do > if animator.animationState(stateType) ~= state then > return false > end > end > return true > end > > function PickSlash:canFire() > return not status.resourceLocked("energy") and status.resourcePositive("energy") > end > > function PickSlash:shouldFire() > return self:canFire() and self.fireMode == self.activatingFireMode > end > > -- State: windup > function PickSlash:windup() > self.weapon:setStance(self.stances.windup) > self.weapon:updateAim() > > if not self:bladeReady() then > self:setAnimationStates(self.windupAnimationStates) > end > > while not self:bladeReady() do > coroutine.yield() > end > > if self:shouldFire() then > self:setState(self.fire) > end > end > > -- State: fire > function PickSlash:fire() > local entityPosition = world.entityPosition(activeItem.ownerEntityId()) > self.hitPosition = activeItem.ownerAimPosition() > local distance = vec2.mag(world.distance(entityPosition, self.hitPosition)) > if distance > self.toolRange then > coroutine.yield() > self:setState(self.windup) > return > end > > local radius = self.shiftHeld and self.altBlockRadius or self.blockRadius > local brushArea = self:tileAreaBrush(radius, self.hitPosition) > > if not world.damageTiles(brushArea, self.layer, entityPosition, self.tileDamageType, self.tileDamage, self.harvestLevel, activeItem.ownerEntityId()) then > coroutine.yield() > self:setState(self.windup) > return > end > status.overConsumeResource("energy", self.energyUsage) > > animator.setSoundPool("blockSound", {self:getBlockSound(brushArea)}) > > self.weapon:setStance(self.stances.fire) > self.weapon:updateAim() > > coroutine.yield() > > animator.playSound("blockSound") > animator.playSound("fire") > > util.wait(self.stances.fire.duration) > > if self:shouldFire() then > self:setState(self.fire) > end > end > > function PickSlash:getBlockSound(brushArea) > local defaultFootstepSound = root.assetJson("/client.config:defaultFootstepSound") > > for _,pos in pairs(brushArea) do > if world.isTileProtected(pos) then > return root.assetJson("/client.config:defaultDingSound") > end > end > > for _,pos in pairs(brushArea) do > local material = world.material(pos, self.layer) > local mod = world.mod(pos, self.layer) > local blockSound = type(material) == "string" and root.materialMiningSound(material, mod) > if blockSound then return blockSound end > end > > for _,pos in pairs(brushArea) do > local material = world.material(pos, self.layer) > local mod = world.mod(pos, self.layer) > local blockSound = type(material) == "string" and root.materialFootstepSound(material, mod) > if blockSound and blockSound ~= defaultFootstepSound then > return blockSound > end > end > > return nil > end > > function PickSlash:tileAreaBrush(radius, centerPosition) > local result = jarray() > local offset = {-radius/2, -radius/2} > local intOffset = util.map(vec2.add(offset, centerPosition), util.round) > > for x = 0, radius-1 do > for y = 0, radius-1 do > local intPos = util.map({x, y}, util.round) > table.insert(result, vec2.add(intPos, intOffset)) > end > end > return result > end > > function PickSlash:uninit() > self:setAnimationStates(self.inactiveAnimationStates) > end items\active\weapons\other\drillspear\drillcharge.lua 117,118c117,118 < world.damageTiles(drillTiles, "foreground", sourcePosition, "blockish", self.tileDamage, 99) < world.damageTiles(drillTiles, "background", sourcePosition, "blockish", self.tileDamage, 99) --- > world.damageTiles(drillTiles, "foreground", sourcePosition, "blockish", self.tileDamage, 99, activeItem.ownerEntityId()) > world.damageTiles(drillTiles, "background", sourcePosition, "blockish", self.tileDamage, 99, activeItem.ownerEntityId()) items\armors\other\armoredcultist\armoredcultist.back 8c8 < "shortdescription" : "Armoured Cultist Tentacles", --- > "shortdescription" : "Cultist General Tentacles", 16,27c16,39 < { "ffca8a" : "fffdb0", "e0975c" : "cbc234", "a85636" : "926e19", "6f2919" : "563f0f" }, < { "ffca8a" : "e8a483", "e0975c" : "b16964", "a85636" : "693e3e", "6f2919" : "2c1b1c" }, < { "ffca8a" : "727272", "e0975c" : "414141", "a85636" : "1c1c1c", "6f2919" : "060606" }, < { "ffca8a" : "e9e9e9", "e0975c" : "727272", "a85636" : "333333", "6f2919" : "161616" }, < { "ffca8a" : "e6a49e", "e0975c" : "ac3b37", "a85636" : "521010", "6f2919" : "200407" }, < { "ffca8a" : "f3cea2", "e0975c" : "cf7d2c", "a85636" : "773611", "6f2919" : "221004" }, < { "ffca8a" : "f8f6da", "e0975c" : "d3be46", "a85636" : "745d16", "6f2919" : "1e1705" }, < { "ffca8a" : "bbe69d", "e0975c" : "5ba73c", "a85636" : "1d4e0f", "6f2919" : "051403" }, < { "ffca8a" : "99bee5", "e0975c" : "3e65b7", "a85636" : "151f5f", "6f2919" : "040619" }, < { "ffca8a" : "d29be8", "e0975c" : "933eb4", "a85636" : "47145b", "6f2919" : "0e0314" }, < { "ffca8a" : "edb8ee", "e0975c" : "c94ac7", "a85636" : "6f1768", "6f2919" : "1e051c" }, < { "ffca8a" : "ebd3c4", "e0975c" : "be8569", "a85636" : "763f28", "6f2919" : "1c0c06" } --- > // PURPLE > { "ffca8a" : "d29ce7", "e0975c" : "a451c4", "a85636" : "6a2284", "6f2919" : "320c40" }, > // BLACK > { "ffca8a" : "838383", "e0975c" : "555555", "a85636" : "383838", "6f2919" : "151515" }, > // GREY > { "ffca8a" : "b5b5b5", "e0975c" : "808080", "a85636" : "555555", "6f2919" : "303030" }, > // WHITE > { "ffca8a" : "e6e6e6", "e0975c" : "b6b6b6", "a85636" : "7b7b7b", "6f2919" : "373737" }, > // RED > { "ffca8a" : "f4988c", "e0975c" : "d93a3a", "a85636" : "932625", "6f2919" : "601119" }, > // ORANGE > { "ffca8a" : "ffd495", "e0975c" : "ea9931", "a85636" : "af4e00", "6f2919" : "6e2900" }, > // YELLOW > { "ffca8a" : "ffffa7", "e0975c" : "e2c344", "a85636" : "a46e06", "6f2919" : "642f00" }, > // GREEN > { "ffca8a" : "b2e89d", "e0975c" : "51bd3b", "a85636" : "247824", "6f2919" : "144216" }, > // BLUE > { "ffca8a" : "96cbe7", "e0975c" : "5588d4", "a85636" : "344495", "6f2919" : "1a1c51" }, > // PURPLE > { "ffca8a" : "d29ce7", "e0975c" : "a451c4", "a85636" : "6a2284", "6f2919" : "320c40" }, > // PINK > { "ffca8a" : "eab3db", "e0975c" : "d35eae", "a85636" : "97276d", "6f2919" : "59163f" }, > // BROWN > { "ffca8a" : "ccae7c", "e0975c" : "a47844", "a85636" : "754c23", "6f2919" : "472b13" } 29c41 < } --- > } \ No newline at end of file items\armors\other\armoredcultist\armoredcultist.head 9c9 < "shortdescription" : "Armoured Cultist Hood", --- > "shortdescription" : "Cultist General Hood", items\fossils\large\trexfossil\trexfossil1.item 6,7c6,7 < "shortdescription" : "T-Rex Skull", < "description" : "A fossilised T-Rex skull.", --- > "shortdescription" : "T. rex Skull", > "description" : "A fossilised T. rex skull.", 17c17 < "shortdescription" : "T-Rex Fossil", --- > "shortdescription" : "T. rex Fossil", items\fossils\large\trexfossil\trexfossil2.item 6,7c6,7 < "shortdescription" : "T-Rex Torso", < "description" : "A fossilised T-Rex torso.", --- > "shortdescription" : "T. rex Torso", > "description" : "A fossilised T. rex torso.", items\fossils\large\trexfossil\trexfossil3.item 6,7c6,7 < "shortdescription" : "T-Rex Legs", < "description" : "Fossilised T-Rex legs and hips.", --- > "shortdescription" : "T. rex Legs", > "description" : "Fossilised T. rex legs and hips.", items\fossils\large\trexfossil\trexfossil4.item 6,7c6,7 < "shortdescription" : "T-Rex Upper Tail;", < "description" : "A fossilised T-Rex tail fragment.", --- > "shortdescription" : "T. rex Upper Tail", > "description" : "A fossilised T. rex tail fragment.", items\fossils\large\trexfossil\trexfossil5.item 6,7c6,7 < "shortdescription" : "T-Rex Lower Tail", < "description" : "A fossilised T-Rex tail tip.", --- > "shortdescription" : "T. rex Lower Tail", > "description" : "A fossilised T. rex tail tip.", monsters\crawlers\triplod\triplod.animation 166c166 < "fire" : [ "/sfx/projectiles/electric_barrier_shock2.ogg" ] --- > "fire" : [ "/sfx/gun/plasma_pistol4.ogg" ] monsters\crawlers\triplod\triplod.monstertype 50c50 < "fireSound" : "", --- > "fireSound" : "fire", monsters\space\omnicannon\omnicannon.monstertype 11c11 < "dropPools" : [ ], --- > "dropPools" : ["spaceRobot"], monsters\space\rustick\rustick.animation 119a120,129 > "lights" : { > "glow" : { > "active" : true, > "position" : [0, 0], > "color" : [45, 48, 69], > "pointLight" : true, > "anchorPart" : "body" > } > }, > monsters\walkers\peblit\peblit.animation 17a18,26 > "skid" : { > "frames" : 3, > "cycle" : 0.15, > "mode" : "transition", > "transition" : "skidend" > }, > "skidend" : { > "frames" : 1 > }, 93a103,112 > } > }, > "skid" : { > "properties" : { > "image" : ":skid." > } > }, > "skidend" : { > "properties" : { > "image" : ":skidend." monsters\walkers\peblit\peblit.frames 9c9 < [ null, "walk.1", "walk.2", "walk.3", "walk.4", "walk.5", "walk.6", null, "skid.1" ], --- > [ null, "walk.1", "walk.2", "walk.3", "walk.4", "walk.5", "walk.6", null, "skidend.1" ], 15c15,19 < "fall.1" : "walk.2" --- > "fall.1" : "walk.2", > > "skid.1" : "walk.4", > "skid.2" : "walk.5", > "skid.3" : "walk.6" 17c21 < } \ No newline at end of file --- > } npcs\merchantpools.config 586a587,592 > "cheesemerchant" : [ > [0, [ > { "item" : { "name" : "cheese" } } > ]] > ], > npcs\space\spacevillager.npctype 7c7 < "greetingChance" : 0.5 --- > "greetingChance" : 0 objects\ancient\monolithgate\monolithgate.animation 1,250c1,256 < { < "animatedParts" : { < "stateTypes" : { < "apexkey" : { < "default" : "off", < "states" : { < "off" : {}, < "on" : { < "frames" : 32, < "cycle" : 2.0, < "mode" : "loop" < } < } < }, < "aviankey" : { < "default" : "off", < "states" : { < "off" : {}, < "on" : { < "frames" : 32, < "cycle" : 2.0, < "mode" : "loop" < } < } < }, < "florankey" : { < "default" : "off", < "states" : { < "off" : {}, < "on" : { < "frames" : 32, < "cycle" : 2.0, < "mode" : "loop" < } < } < }, < "glitchkey" : { < "default" : "off", < "states" : { < "off" : {}, < "on" : { < "frames" : 32, < "cycle" : 2.0, < "mode" : "loop" < } < } < }, < "humankey" : { < "default" : "off", < "states" : { < "off" : {}, < "on" : { < "frames" : 32, < "cycle" : 2.0, < "mode" : "loop" < } < } < }, < "hylotlkey" : { < "default" : "off", < "states" : { < "off" : {}, < "on" : { < "frames" : 32, < "cycle" : 2.0, < "mode" : "loop" < } < } < }, < "open" : { < "default" : "off", < "states" : { < "off" : {}, < "on" : { < "frames" : 16, < "cycle" : 2.0, < "mode" : "loop", < "properties" : { < "particleEmittersOn" : [ "starfield" ] < } < } < } < } < }, < < "parts" : { < "bg" : { < "properties" : { < "centered" : false, < "image" : "", < "fullbright" : true, < "zLevel" : 0 < } < }, < "fg" : { < "properties" : { < "centered" : false, < "image" : "", < "zLevel" : 1 < } < }, < "inner" : { < "properties" : { < "centered" : false, < "zLevel" : 3, < "offset" : [7.125, 0] < }, < < "partStates" : { < "open" : { < "on" : { < "properties" : { < "image" : ":" < } < } < } < } < }, < "apexkey" : { < "properties" : { < "centered" : false, < "fullbright" : true, < "zLevel" : 2 < }, < < "partStates" : { < "apexkey" : { < "on" : { < "properties" : { < "image" : ":" < } < } < } < } < }, < "aviankey" : { < "properties" : { < "centered" : false, < "fullbright" : true, < "zLevel" : 2 < }, < < "partStates" : { < "aviankey" : { < "on" : { < "properties" : { < "image" : ":" < } < } < } < } < }, < "florankey" : { < "properties" : { < "centered" : false, < "fullbright" : true, < "zLevel" : 2 < }, < < "partStates" : { < "florankey" : { < "on" : { < "properties" : { < "image" : ":" < } < } < } < } < }, < "glitchkey" : { < "properties" : { < "centered" : false, < "fullbright" : true, < "zLevel" : 2 < }, < < "partStates" : { < "glitchkey" : { < "on" : { < "properties" : { < "image" : ":" < } < } < } < } < }, < "humankey" : { < "properties" : { < "centered" : false, < "fullbright" : true, < "zLevel" : 2 < }, < < "partStates" : { < "humankey" : { < "on" : { < "properties" : { < "image" : ":" < } < } < } < } < }, < "hylotlkey" : { < "properties" : { < "centered" : false, < "fullbright" : true, < "zLevel" : 2 < }, < < "partStates" : { < "hylotlkey" : { < "on" : { < "properties" : { < "image" : ":" < } < } < } < } < } < } < }, < < "particleEmitters" : { < "starfield" : { < "emissionRate" : 15, < "offsetRegion" : [7.125, 0, 30.875, 25], < "particles" : [ < { "particle" : { < "type" : "ember", < "color" : [255, 255, 255], < "size" : 1, < "angularVelocity" : 20, < "destructionTime" : 3.0, < "destructionAction" : "fade", < "position" : [0, 0], < "initialVelocity" : [0, 0], < "finalVelocity" : [0, 0], < "approach" : [15, 15], < "timeToLive" : 0.85, < "layer" : "middle", < "variance" : { < "size" : 0.5 < } < } < } < ] < } < } < } --- > { > "animatedParts" : { > "stateTypes" : { > "apexkey" : { > "default" : "off", > "states" : { > "off" : {}, > "on" : { > "frames" : 32, > "cycle" : 2.0, > "mode" : "loop" > } > } > }, > "aviankey" : { > "default" : "off", > "states" : { > "off" : {}, > "on" : { > "frames" : 32, > "cycle" : 2.0, > "mode" : "loop" > } > } > }, > "florankey" : { > "default" : "off", > "states" : { > "off" : {}, > "on" : { > "frames" : 32, > "cycle" : 2.0, > "mode" : "loop" > } > } > }, > "glitchkey" : { > "default" : "off", > "states" : { > "off" : {}, > "on" : { > "frames" : 32, > "cycle" : 2.0, > "mode" : "loop" > } > } > }, > "humankey" : { > "default" : "off", > "states" : { > "off" : {}, > "on" : { > "frames" : 32, > "cycle" : 2.0, > "mode" : "loop" > } > } > }, > "hylotlkey" : { > "default" : "off", > "states" : { > "off" : {}, > "on" : { > "frames" : 32, > "cycle" : 2.0, > "mode" : "loop" > } > } > }, > "open" : { > "default" : "off", > "states" : { > "off" : {}, > "on" : { > "frames" : 16, > "cycle" : 2.0, > "mode" : "loop", > "properties" : { > "particleEmittersOn" : [ "starfield" ] > } > } > } > } > }, > > "parts" : { > "bg" : { > "properties" : { > "centered" : false, > "image" : "", > "fullbright" : true, > "zLevel" : 0 > } > }, > "fg" : { > "properties" : { > "centered" : false, > "image" : "", > "zLevel" : 1 > } > }, > "inner" : { > "properties" : { > "centered" : false, > "zLevel" : 3, > "offset" : [7.125, 0] > }, > > "partStates" : { > "open" : { > "on" : { > "properties" : { > "image" : ":" > } > } > } > } > }, > "apexkey" : { > "properties" : { > "centered" : false, > "fullbright" : true, > "zLevel" : 2, > "offset" : [23.875, 11.25] > }, > > "partStates" : { > "apexkey" : { > "on" : { > "properties" : { > "image" : ":" > } > } > } > } > }, > "aviankey" : { > "properties" : { > "centered" : false, > "fullbright" : true, > "zLevel" : 2, > "offset" : [17.125, 17.0] > }, > > "partStates" : { > "aviankey" : { > "on" : { > "properties" : { > "image" : ":" > } > } > } > } > }, > "florankey" : { > "properties" : { > "centered" : false, > "fullbright" : true, > "zLevel" : 2, > "offset" : [23.75, 14.0] > }, > > "partStates" : { > "florankey" : { > "on" : { > "properties" : { > "image" : ":" > } > } > } > } > }, > "glitchkey" : { > "properties" : { > "centered" : false, > "fullbright" : true, > "zLevel" : 2, > "offset" : [19.75, 17.25] > }, > > "partStates" : { > "glitchkey" : { > "on" : { > "properties" : { > "image" : ":" > } > } > } > } > }, > "humankey" : { > "properties" : { > "centered" : false, > "fullbright" : true, > "zLevel" : 2, > "offset" : [22.25, 15.875] > }, > > "partStates" : { > "humankey" : { > "on" : { > "properties" : { > "image" : ":" > } > } > } > } > }, > "hylotlkey" : { > "properties" : { > "centered" : false, > "fullbright" : true, > "zLevel" : 2, > "offset" : [23.125, 8.75] > }, > > "partStates" : { > "hylotlkey" : { > "on" : { > "properties" : { > "image" : ":" > } > } > } > } > } > } > }, > > "particleEmitters" : { > "starfield" : { > "emissionRate" : 15, > "offsetRegion" : [7.125, 0, 30.875, 25], > "particles" : [ > { "particle" : { > "type" : "ember", > "color" : [255, 255, 255], > "size" : 1, > "angularVelocity" : 20, > "destructionTime" : 3.0, > "destructionAction" : "fade", > "position" : [0, 0], > "initialVelocity" : [0, 0], > "finalVelocity" : [0, 0], > "approach" : [15, 15], > "timeToLive" : 0.85, > "layer" : "middle", > "variance" : { > "size" : 0.5 > } > } > } > ] > } > } > } objects\ancient\monolithgate\monolithgate.object 1,74c1,74 < { < "objectName" : "monolithgate", < "colonyTags" : ["ancient"], < "rarity" : "Legendary", < "description" : "A mysterious ancient gate.", < "shortdescription" : "Monolith Gate", < "race" : "ancient", < "category" : "decorative", < "price" : 0, < "printable" : false, < < "apexDescription" : "It's a gate of magnificent proportion. What's on the other side?", < "avianDescription" : "This glorious gate is like nothing I've seen before. But where does it lead?", < "floranDescription" : "Big gate makes Floran feel sssmall. Floran wants to know where it leadsss.", < "glitchDescription" : "Amazed. This is a gate of breathtaking proportion. Who built it? And where does it lead?", < "humanDescription" : "A magestic gate like nothing I've encountered before. Who created this wonder? And what's on the other side?", < "hylotlDescription" : "This is nothing short of a magnificent creation. This gate must have been constructed for a very special purpose.", < "novakidDescription" : "I lack the words to describe this magnificent gate. I will silently admire it...", < < "inventoryIcon" : "icon.png", < "orientations" : [ < { < "imageLayers" : [ { "image" : "monolithgate.png:", "fullbright" : true }, { "image" : "monolithgatelit.png:" } ], < "direction" : "right", < "flipImages" : false, < < "imagePosition" : [-152, 0], < < "spaceScan" : 0.1, < "fgAnchors" : [ [0, -1] ] < } < ], < < "animation" : "monolithgate.animation", < "animationPosition" : [-152, 0], < "animationParts" : { < "bg" : "monolithgate.png", < "fg" : "monolithgatelit.png", < "inner" : "monolithgateinner.png", < "apexkey" : "monolithgate_apex.png", < "aviankey" : "monolithgate_avian.png", < "florankey" : "monolithgate_floran.png", < "glitchkey" : "monolithgate_glitch.png", < "humankey" : "monolithgate_human.png", < "hylotlkey" : "monolithgate_hylotl.png" < }, < < "scripts" : ["monolithgate.lua"], < "scriptDelta" : 120, < < "flagAnimationStates" : { < "outpost_mission2" : "florankey", < "outpost_mission3" : "hylotlkey", < "outpost_mission4" : "aviankey", < "outpost_mission5" : "apexkey", < "outpost_mission6" : "glitchkey", < "final_gate_key" : "open" < }, < < "interactAction" : "OpenTeleportDialog", < "interactData" : { < "canBookmark" : false, < "destinations" : [ < { < "name" : "The Ruin", < "planetName" : "The Ruin", < "mission" : true, < "warpAction" : "InstanceWorld:tentaclemission", < "icon" : "default" < } < ], < "includePlayerBookmarks" : false < } < } --- > { > "objectName" : "monolithgate", > "colonyTags" : ["ancient"], > "rarity" : "Legendary", > "description" : "A mysterious ancient gate.", > "shortdescription" : "Monolith Gate", > "race" : "ancient", > "category" : "decorative", > "price" : 0, > "printable" : false, > > "apexDescription" : "It's a gate of magnificent proportion. What's on the other side?", > "avianDescription" : "This glorious gate is like nothing I've seen before. But where does it lead?", > "floranDescription" : "Big gate makes Floran feel sssmall. Floran wants to know where it leadsss.", > "glitchDescription" : "Amazed. This is a gate of breathtaking proportion. Who built it? And where does it lead?", > "humanDescription" : "A magestic gate like nothing I've encountered before. Who created this wonder? And what's on the other side?", > "hylotlDescription" : "This is nothing short of a magnificent creation. This gate must have been constructed for a very special purpose.", > "novakidDescription" : "I lack the words to describe this magnificent gate. I will silently admire it...", > > "inventoryIcon" : "icon.png", > "orientations" : [ > { > "imageLayers" : [ { "image" : "monolithgate.png:", "fullbright" : true }, { "image" : "monolithgatelit.png:" } ], > "direction" : "right", > "flipImages" : false, > > "imagePosition" : [-152, 0], > > "spaceScan" : 0.1, > "fgAnchors" : [ [0, -1] ] > } > ], > > "animation" : "monolithgate.animation", > "animationPosition" : [-152, 0], > "animationParts" : { > "bg" : "monolithgate.png", > "fg" : "monolithgatelit.png", > "inner" : "monolithgateinner.png", > "apexkey" : "keys/apex.png", > "aviankey" : "keys/avian.png", > "florankey" : "keys/floran.png", > "glitchkey" : "keys/glitch.png", > "humankey" : "keys/human.png", > "hylotlkey" : "keys/hylotl.png" > }, > > "scripts" : ["monolithgate.lua"], > "scriptDelta" : 120, > > "flagAnimationStates" : { > "outpost_mission2" : "florankey", > "outpost_mission3" : "hylotlkey", > "outpost_mission4" : "aviankey", > "outpost_mission5" : "apexkey", > "outpost_mission6" : "glitchkey", > "final_gate_key" : "open" > }, > > "interactAction" : "OpenTeleportDialog", > "interactData" : { > "canBookmark" : false, > "destinations" : [ > { > "name" : "The Ruin", > "planetName" : "The Ruin", > "mission" : true, > "warpAction" : "InstanceWorld:tentaclemission", > "icon" : "default" > } > ], > "includePlayerBookmarks" : false > } > } objects\apex\apexofficechair\apexofficechair.object 3c3 < "colonyTags" : ["apex","apexresearchlab"], --- > "colonyTags" : ["apex","apexresearchlab", "office"], objects\biome\scorchedcity\explosivebarrel\explosivebarrel.object 5c5 < "category" : "decorative", --- > "category" : "breakable", objects\floran\floranbench\floranbench.object 14c14 < "glitchDescription" : "Sceptical. There is logic in the construction of this bench that one would assume is beyond the Floran.", --- > "glitchDescription" : "Skeptical. There is logic in the construction of this bench that one would assume is beyond the Floran.", objects\generic\mannequin\mannequin.lua 0a1,2 > require "/scripts/util.lua" > 39c41 < animator.setPartTag(k, "frameSet", itemConfig.directory .. v) --- > animator.setPartTag(k, "frameSet", util.absolutePath(itemConfig.directory, v)) 43c45 < animator.setPartTag(slotName, "frameSet", itemConfig.directory .. frameSet) --- > animator.setPartTag(slotName, "frameSet", util.absolutePath(itemConfig.directory, frameSet)) objects\glitch\toxicwastebarrel\toxicwastebarrel.object 5c5 < "category" : "decorative", --- > "category" : "breakable", objects\human\bunkerconsole1\bunkerconsole1.object 31c31 < "soundEffect" : "/sfx/objects/bunkerconsole.ogg", --- > // "soundEffect" : "/sfx/objects/bunkerconsole.ogg", objects\human\bunkerpanel1\bunkerpanel1.object 19c19 < "lightColor" : [32, 70, 128], --- > "lightColor" : [38, 84, 153], objects\human\bunkerpanel2\bunkerpanel2.object 19c19 < "lightColor" : [32, 70, 128], --- > "lightColor" : [38, 84, 153], objects\human\bunkerpanel3\bunkerpanel3.object 19c19 < "lightColor" : [32, 70, 128], --- > "lightColor" : [38, 84, 153], objects\human\bunkertable3\bunkertable3.object 11c11 < "lightColor" : [69, 90, 115], --- > "lightColor" : [83, 120, 166], 12a13,15 > "pointLight" : true, > "pointBeam" : 2, > "beamAmbience" : 0.6, 30a34,36 > "lightPosition" : [0, 1], > "beamAngle" : 90, > 39a46,48 > > "lightPosition" : [0, 1], > "beamAngle" : 90, objects\hylotl\greenredlight\greenredlight.object 5c5 < "category" : "decorative", --- > "category" : "light", objects\mission\apexmission\bigapescreen\bigapescreen.object 7c7 < "description" : "", --- > "description" : "This screen displays a variety of propaganda messages from Big Ape.", 9a10,12 > > "floranDescription" : "Floran thinksss ssso-called 'big' ape not so big.", > "glitchDescription" : "Alarmed. These video clips contain numerous subliminal messages.", objects\mission\miningpowersign\miningpowersign.object 17a18 > "lightColorOff" : [77, 21, 21], 19c20 < "category" : "wire", --- > "category" : "light", 34,35c35,36 < "scripts" : [ "/objects/wired/switch/switchwithinputalwayslit.lua" ], < "scriptDelta" : 5, --- > "scripts" : [ "/objects/wired/light/light.lua" ], > "scriptDelta" : 60, 37c38 < "animation" : "/objects/wired/switch/switchtoggle2lit.animation", --- > "animation" : "/objects/wired/light/lighttogglebgfullbrightturning.animation", 40,41c41,42 < "on" : [ "/sfx/objects/apexconsole2switch.ogg" ], < "off" : [ "/sfx/objects/apexconsole2switch.ogg" ] --- > "on" : [ "/sfx/interface/ship_confirm1.ogg" ], > "off" : [ "/sfx/interface/ship_confirm2.ogg" ] 44a46,47 > "interactive" : false, > 50,51d52 < < "interactive" : false, objects\outpost\frogfurnishing\frogfurnishing.lua 0a1,2 > require "/scripts/util.lua" > 25c27 < math.randomseed(os.time()) --- > math.randomseed(util.seedTime()) objects\outpost\frogfurnishing\frogfurnishing.object 103c103,104 < [ "steampunkarmchair", "steampunkbed", "steampunkdesk", "steampunkglobe", "steampunklamp", "steampunkshelf" ] --- > [ "steampunkarmchair", "steampunkbed", "steampunkdesk", "steampunkglobe", "steampunklamp", "steampunkshelf" ], > [ "egyptianbed", "egyptianchair", "egyptiantable", "egyptianlamp", "egyptianpillar", "egyptianstatuette", "egyptiancrest" ] objects\outpost\outpostsmallmonitor\outpostsmallmonitor.frames 11c11,12 < "default.default" : "default.off" --- > "default.default" : "default.off", > "default.on" : "default.1" objects\outpost\outpostsmallmonitor\outpostsmallmonitor.object 27c27 < "image" : "outpostsmallmonitor.png:.", --- > "image" : "outpostsmallmonitor.png:.on", 36c36 < "image" : "outpostsmallmonitor.png:.", --- > "image" : "outpostsmallmonitor.png:.on", objects\outpost\penguinbar\penguinbartop2.object 26c26 < "file" : "/interface/bounty/beakeasyicon.png" --- > "file" : "/interface/crafting/beakeasyicon.png" 60c60 < --- > 62c62 < --- > objects\outpost\penguinweaponshop\penguinweaponshop.lua 0a1,2 > require "/scripts/util.lua" > 12c14 < math.randomseed(os.time()) --- > math.randomseed(util.seedTime()) objects\outpost\treasuredtrophies\treasuredtrophies.object 27c27 < "file" : "/interface/bounty/bountyicon.png" --- > "file" : "/interface/crafting/trophiesicon.png" objects\ship\apexshiplight\apexshiplight.object 6c6 < "lightColor" : [230, 230, 230], --- > "lightColor" : [220, 220, 220], objects\space\astrocabinet\astrocabinet.object 34,35c34,35 < "openSounds" : [ "/sfx/objects/gunchest_open.ogg" ], < "closeSounds" : [ "/sfx/objects/gunchest_close.ogg" ], --- > "openSounds" : [ "/sfx/objects/bunkercabinet_open.ogg" ], > "closeSounds" : [ "/sfx/objects/bunkercabinet_close.ogg" ], objects\spawner\colonydeed\colonydeed.lua 435c435 < math.randomseed(os.time()) --- > math.randomseed(util.seedTime()) objects\themed\astronaut\earthmodel\earthmodel.object 14c14 < "floranDescription" : "Sssad to remember my time on Earth. I misss it.", --- > "floranDescription" : "Sssad to remember my time on Earth. Floran missses it.", objects\tiered\tier1spotlight\default.frames 5c5 < "dimensions" : [2, 9], --- > "dimensions" : [2, 1], 7,15c7 < [ "default.on", "default.off" ], < [ "red.on", "red.off" ], < [ "blue.on", "blue.off" ], < [ "green.on", "green.off" ], < [ "yellow.on", "yellow.off" ], < [ "orange.on", "orange.off" ], < [ "pink.on", "pink.off" ], < [ "black.on", "black.off" ], < [ "white.on", "white.off" ] --- > [ "default.on", "default.off" ] 20,28c12 < "default.default" : "default.on", < "red.default" : "red.on", < "blue.default" : "blue.on", < "green.default" : "green.on", < "yellow.default" : "yellow.on", < "orange.default" : "orange.on", < "pink.default" : "pink.on", < "black.default" : "black.on", < "white.default" : "white.on" --- > "default.default" : "default.on" objects\wired\logic\dlatch.lua 1,27c1,28 < function init() < object.setInteractive(false) < if storage.state == nil then < output(false) < else < output(storage.state) < end < end < < function output(state) < if storage.state ~= state then < storage.state = state < object.setAllOutputNodes(state) < if state then < animator.setAnimationState("switchState", "on") < else < animator.setAnimationState("switchState", "off") < end < else < end < end < < function update(dt) < if object.getInputNodeLevel(1) then < output(object.getInputNodeLevel(0)) < end < end --- > function init() > object.setInteractive(false) > if storage.state == nil then > output(false) > else > output(storage.state) > object.setAllOutputNodes(storage.state) > animator.setAnimationState("switchState", storage.state and "on" or "off") > end > end > > function output(state) > if storage.state ~= state then > storage.state = state > object.setAllOutputNodes(state) > if state then > animator.setAnimationState("switchState", "on") > else > animator.setAnimationState("switchState", "off") > end > end > end > > function update(dt) > if object.getInputNodeLevel(1) then > output(object.getInputNodeLevel(0)) > end > end particles\electricswoosh1.particle 19c19,20 < "finalVelocity" : [1.5, 1.5] --- > "finalVelocity" : [1.5, 1.5], > "rotation" : 180 projectiles\physics.config 1194a1195,1208 > }, > > "mechbattery" : { > "mass" : 1.0, > "gravityMultiplier" : 0.6, > "bounceFactor" : 0.0, > "stopOnFirstBounce" : true, > "maxMovementPerStep" : 0.4, > "collisionPoly" : [ [0.75, 0.75], [0.75, -0.75], [-0.75, -0.75], [-0.75, 0.75] ], > "ignorePlatformCollision" : true, > "airFriction" : 0.0, > "liquidFriction" : 8.0, > "groundFriction" : 15.0, > "maximumCorrection" : 0.75 projectiles\boss\eyeboss\spacemonsterspawner.lua 1,44c1,47 < function sourceEntityAlive() < return world.entityExists(projectile.sourceEntity()) and world.entityHealth(projectile.sourceEntity())[1] > 0 < end < < function update() < if not sourceEntityAlive() then < projectile.die() < end < end < < function destroy() < if not sourceEntityAlive() then < return < end < < local monsterType = config.getParameter("monsterType") < local damageTeam = entity.damageTeam() < local parameters = { < level = config.getParameter("monsterLevel", 1), < aggressive = true, < level = world.threatLevel(), < damageTeam = damageTeam.team, < damageTeamType = damageTeam.type, < initialStatus = "blackmonsterrelease", < behaviorConfig = { < targetQueryRange = 150, < keepTargetInSight = false, < keepTargetInRange = 200 < } < } < parameters = sb.jsonMerge(parameters, config.getParameter("monsterParameters", {})) < local entityId = world.spawnMonster(monsterType, mcontroller.position(), parameters) < world.callScriptedEntity(entityId, "status.addEphemeralEffect", "blackmonsterrelease") < local position = world.callScriptedEntity(entityId, "findGroundPosition", world.entityPosition(entityId), -10, 10, false) < if position then < mcontroller.setPosition(position) < world.callScriptedEntity(entityId, "mcontroller.setPosition", position) < end < < world.sendEntityMessage(projectile.sourceEntity(), "notify", { < type = "monsterSpawned", < targetId = entityId < }) < end --- > function sourceEntityAlive() > return world.entityExists(projectile.sourceEntity()) and world.entityHealth(projectile.sourceEntity())[1] > 0 > end > > function update() > if not sourceEntityAlive() then > projectile.die() > end > end > > function destroy() > if not sourceEntityAlive() then > return > end > > local monsterType = config.getParameter("monsterType") > local damageTeam = entity.damageTeam() > local parameters = { > level = config.getParameter("monsterLevel", 1), > aggressive = true, > level = world.threatLevel(), > damageTeam = damageTeam.team, > damageTeamType = damageTeam.type, > initialStatus = "blackmonsterrelease", > behaviorConfig = { > targetQueryRange = 150, > keepTargetInSight = false, > keepTargetInRange = 200 > } > } > parameters = sb.jsonMerge(parameters, config.getParameter("monsterParameters", {})) > local entityId = world.spawnMonster(monsterType, mcontroller.position(), parameters) > world.callScriptedEntity(entityId, "status.addEphemeralEffect", "blackmonsterrelease") > local position = mcontroller.position() > if config.getParameter("onGround", true) then > position = world.callScriptedEntity(entityId, "findGroundPosition", position, -10, 10, false) > end > if position then > mcontroller.setPosition(position) > world.callScriptedEntity(entityId, "mcontroller.setPosition", position) > end > > world.sendEntityMessage(projectile.sourceEntity(), "notify", { > type = "monsterSpawned", > targetId = entityId > }) > end projectiles\mech\mechenergypickup\mechenergypickup.projectile 3,4c3,4 < "physics" : "illusion", < "bounces" : 0, --- > "physics" : "mechbattery", > "bounces" : -1, quests\quests.config 35a36,42 > "defaultGuiConfigs" : { > "newQuest" : "/interface/windowconfig/newquestshort.config", > "newQuestPortrait" : "/interface/windowconfig/newquest.config", > "questComplete" : "/interface/windowconfig/questcomplete.config", > "questFailed" : "/interface/windowconfig/questfailed.config" > }, > quests\generated\locations.config 151a152,156 > }, > "steps1" : { > "name" : "ruins", > "tags" : [ "generic", "friendly" ], > "range" : 600 quests\scripts\conditions\scanning.lua 47c47 < function scanObjectsCondition:onObjectScanned(message, isLocal, objectName) --- > function scanObjectsCondition:onObjectScanned(message, isLocal, objectName, objectId) quests\story\bootship.questtemplate 5,6c5,7 < "invisible" : false, < "logOnly" : true, --- > "showAcceptDialog" : false, > "showCompleteDialog" : false, > "showFailDialog" : false, 35c36 < } \ No newline at end of file --- > } quests\story\protectorate.questtemplate 9,10c9,11 < "invisible" : false, < "logOnly" : true, --- > "showAcceptDialog" : false, > "showCompleteDialog" : false, > "showFailDialog" : false, radiomessages\missions.radiomessages 335c335,401 < } --- > }, > > // --------- CULTIST MISSION -------- > > "cultistmission01a" : { > "unique" : false, > "type" : "mission", > "senderName" : "Esther Bright", > "portraitImage" : "/interface/chatbubbles/esthersad.png:", > "text" : "So you've found her... You've found Asra." > }, > > "cultistmission01b" : { > "unique" : false, > "type" : "mission", > "senderName" : "Captain Noble", > "portraitImage" : "/interface/chatbubbles/captainrage.png:", > "text" : "Is that the legendary Esther Bright on your communication line, partner?! Ma'm, it is an honour to meet you!" > }, > > "cultistmission01c" : { > "unique" : false, > "type" : "mission", > "senderName" : "Esther Bright", > "portraitImage" : "/interface/chatbubbles/esthertalk.png:", > "text" : "The pleasure is all mine, dear!" > }, > > "cultistmission02" : { > "unique" : false, > "type" : "mission", > "senderName" : "Koichi", > "portraitImage" : "/interface/chatbubbles/koichi.png:", > "text" : "It looks like you can, um, summon your mech with this platform. That should be useful in your current excursion." > }, > > "cultistmission03a" : { > "unique" : false, > "type" : "mission", > "senderName" : "Lana Blake", > "portraitImage" : "/interface/chatbubbles/lana.png:", > "text" : "It is fortunate that our enemy's flying fortress has such weak security protocols." > }, > > "cultistmission03b" : { > "unique" : false, > "type" : "mission", > "senderName" : "Captain Noble", > "portraitImage" : "/interface/chatbubbles/captain.png:", > "text" : "Let's see your mighty fine hackin' skills, partner!" > }, > > "cultistmission03c" : { > "unique" : false, > "type" : "mission", > "senderName" : "The Baron", > "portraitImage" : "/interface/chatbubbles/baron.png:", > "text" : "Impressed. Despite their deeds, these loathsome cultists at least know how to keep a privy chamber spotless! Ha ha!" > }, > > "cultistmission04a" : { > "unique" : false, > "type" : "mission", > "senderName" : "Nuru", > "portraitImage" : "/interface/chatbubbles/nuru.png:", > "text" : "A fridge! I wonder bad guyss eat for breakfast?" > }, 336a403,473 > "cultistmission04b" : { > "unique" : false, > "type" : "mission", > "senderName" : "The Baron", > "portraitImage" : "/interface/chatbubbles/baron.png:", > "text" : "Amused. Perhaps they eat... Bad apples? Ho ho! My wit is impeccable!" > }, > > "cultistmission05a" : { > "unique" : false, > "type" : "mission", > "senderName" : "Captain Noble", > "portraitImage" : "/interface/chatbubbles/captain.png:", > "text" : "You're makin' good progress, partner. This ship sure is vast, ain't it?" > }, > > "cultistmission05b" : { > "unique" : false, > "type" : "mission", > "senderName" : "Tonauac", > "portraitImage" : "/interface/chatbubbles/tonauactalk.png:", > "text" : "Why, it's big enough to rival the greatest of Kluex's divine temples!" > }, > > "cultistmission06a" : { > "unique" : false, > "type" : "mission", > "senderName" : "???", > "portraitImage" : "/interface/chatbubbles/noxstatic.png:", > "text" : "Who's communication channel is this?! Why are you aboard the Dantalion?!" > }, > > "cultistmission06b" : { > "unique" : false, > "type" : "mission", > "senderName" : "Asra Nox", > "portraitImage" : "/interface/chatbubbles/nox.png", > "text" : "Oh. It's ^orange;you^white;." > }, > > "cultistmission07" : { > "unique" : false, > "type" : "mission", > "senderName" : "Esther Bright", > "portraitImage" : "/interface/chatbubbles/esthersad.png:", > "text" : "Oh Asra, when will your obsession with the Ruin end?" > }, > > "cultistmission08" : { > "unique" : false, > "type" : "mission", > "senderName" : "Captain Noble", > "portraitImage" : "/interface/chatbubbles/captain.png:", > "text" : "I don't like the look of any of this, partner." > }, > > "cultistmission09a" : { > "unique" : false, > "type" : "mission", > "senderName" : "Asra Nox", > "portraitImage" : "/interface/chatbubbles/nox.png", > "text" : "Don't keep me waiting, \"Protector\"." > }, > > "cultistmission09b" : { > "unique" : false, > "type" : "mission", > "senderName" : "Esther Bright", > "portraitImage" : "/interface/chatbubbles/esthersad.png:", > "text" : "I think this is it, dear. I hope you're ready..." > } radiomessages\tutorial.radiomessages 113a114,143 > }, > > // Peacekeeper station intros > > "peacekeeper02" : { > "type" : "tutorial", > "senderName" : "Captain Noble", > "portraitImage" : "/interface/chatbubbles/captain.png:", > "text" : "It turns out that our first gang bust gave us enough public support to get an office! It ain't much, but it's a start!" > }, > > "peacekeeper03" : { > "type" : "tutorial", > "senderName" : "Captain Noble", > "portraitImage" : "/interface/chatbubbles/captain.png:", > "text" : "Hope you like the new station, partner! We've even got a ^orange;Peacekeeper supply store^white; now!" > }, > > "peacekeeper04" : { > "type" : "tutorial", > "senderName" : "Captain Noble", > "portraitImage" : "/interface/chatbubbles/captain.png:", > "text" : "Welcome to our mighty fine new place, partner! Why not check out our ^orange;Peacekeeper Furnishing store^white;?" > }, > > "peacekeeper05" : { > "type" : "tutorial", > "senderName" : "Captain Noble", > "portraitImage" : "/interface/chatbubbles/captainrage.png:", > "text" : "We've finally hit the big time, partner! The Peacekeepers are well an' truly back, and lookin' finer than ever!" scripts\rect.lua 1,131c1,139 < require "/scripts/vec2.lua" < < rect = {} < < function rect.zero() < return {0,0,0,0} < end < < function rect.translate(rectangle, offset) < return { < rectangle[1] + offset[1], rectangle[2] + offset[2], < rectangle[3] + offset[1], rectangle[4] + offset[2] < } < end < < function rect.ll(rectangle) < return {rectangle[1], rectangle[2]} < end < < function rect.ur(rectangle) < return {rectangle[3], rectangle[4]} < end < < function rect.fromVec2(min, max) < return {min[1], min[2], max[1], max[2]} < end < < function rect.withSize(min, size) < return {min[1], min[2], min[1] + size[1], min[2] + size[2]} < end < < function rect.withCenter(center, size) < return {center[1] - size[1] / 2, center[2] - size[2] / 2, center[1] + size[1] / 2, center[2] + size[2] / 2} < end < < function rect.size(rectangle) < return { < rectangle[3] - rectangle[1], < rectangle[4] - rectangle[2] < } < end < < function rect.center(rectangle) < return { < rectangle[1] + (rectangle[3] - rectangle[1]) * 0.5, < rectangle[2] + (rectangle[4] - rectangle[2]) * 0.5 < } < end < < function rect.randomPoint(rectangle) < return { < math.random() * (rectangle[3] - rectangle[1]) + rectangle[1], < math.random() * (rectangle[4] - rectangle[2]) + rectangle[2] < } < end < < function rect.intersects(first, second) < if first[1] > second[3] < or first[3] < second[1] < or first[2] > second[4] < or first[4] < second[2] then < return false < else < return true < end < end < < function rect.rotate(rectangle, angle) < local ll = rect.ll(rectangle) < local ur = rect.ur(rectangle) < ll = vec2.rotate(ll, angle) < ur = vec2.rotate(ur, angle) < < return { < math.min(ll[1], ur[1]), math.min(ll[2], ur[2]), < math.max(ll[1], ur[1]), math.max(ll[2], ur[2]) < } < end < < function rect.flipX(rectangle) < return {-rectangle[3], rectangle[2], -rectangle[1], rectangle[4]} < end < < function rect.scale(rectangle, scale) < if type(scale) == "table" then < return {rectangle[1] * scale[1], rectangle[2] * scale[2], rectangle[3] * scale[1], rectangle[4] * scale[2]} < else < return {rectangle[1] * scale, rectangle[2] * scale, rectangle[3] * scale, rectangle[4] * scale} < end < end < < function rect.pad(rectangle, padding) < if type(padding) == "table" then < return {rectangle[1] - padding[1], rectangle[2] - padding[2], rectangle[3] + padding[1], rectangle[4] + padding[2]} < else < return {rectangle[1] - padding, rectangle[2] - padding, rectangle[3] + padding, rectangle[4] + padding} < end < end < < function rect.contains(rectangle, point) < return point[1] >= rectangle[1] < and point[2] >= rectangle[2] < and point[1] <= rectangle[3] < and point[2] <= rectangle[4] < end < < function rect.snap(rect, point, direction) < if direction[1] < 0 then < return {rect[1], point[2]} < elseif direction[1] > 0 then < return {rect[3], point[2]} < elseif direction[2] < 0 then < return {point[1], rect[2]} < elseif direction[2] > 0 then < return {point[1], rect[4]} < end < end < < function rect.bound(inner, outer) < if inner[4] > outer[4] then < inner = rect.translate(inner, {0, outer[4] - inner[4]}) < elseif inner[2] < outer[2] then < inner = rect.translate(inner, {0, outer[2] - inner[2]}) < end < if inner[3] > outer[3] then < inner = rect.translate(inner, {outer[3] - inner[3], 0}) < elseif inner[1] < outer[1] then < inner = rect.translate(inner, {outer[1] - inner[1], 0}) < end < return inner < end --- > require "/scripts/vec2.lua" > > rect = {} > > function rect.zero() > return {0,0,0,0} > end > > function rect.translate(rectangle, offset) > return { > rectangle[1] + offset[1], rectangle[2] + offset[2], > rectangle[3] + offset[1], rectangle[4] + offset[2] > } > end > > function rect.ll(rectangle) > return {rectangle[1], rectangle[2]} > end > > function rect.lr(rectangle) > return {rectangle[3], rectangle[2]} > end > > function rect.ur(rectangle) > return {rectangle[3], rectangle[4]} > end > > function rect.ul(rectangle) > return {rectangle[1], rectangle[4]} > end > > function rect.fromVec2(min, max) > return {min[1], min[2], max[1], max[2]} > end > > function rect.withSize(min, size) > return {min[1], min[2], min[1] + size[1], min[2] + size[2]} > end > > function rect.withCenter(center, size) > return {center[1] - size[1] / 2, center[2] - size[2] / 2, center[1] + size[1] / 2, center[2] + size[2] / 2} > end > > function rect.size(rectangle) > return { > rectangle[3] - rectangle[1], > rectangle[4] - rectangle[2] > } > end > > function rect.center(rectangle) > return { > rectangle[1] + (rectangle[3] - rectangle[1]) * 0.5, > rectangle[2] + (rectangle[4] - rectangle[2]) * 0.5 > } > end > > function rect.randomPoint(rectangle) > return { > math.random() * (rectangle[3] - rectangle[1]) + rectangle[1], > math.random() * (rectangle[4] - rectangle[2]) + rectangle[2] > } > end > > function rect.intersects(first, second) > if first[1] > second[3] > or first[3] < second[1] > or first[2] > second[4] > or first[4] < second[2] then > return false > else > return true > end > end > > function rect.rotate(rectangle, angle) > local ll = rect.ll(rectangle) > local ur = rect.ur(rectangle) > ll = vec2.rotate(ll, angle) > ur = vec2.rotate(ur, angle) > > return { > math.min(ll[1], ur[1]), math.min(ll[2], ur[2]), > math.max(ll[1], ur[1]), math.max(ll[2], ur[2]) > } > end > > function rect.flipX(rectangle) > return {-rectangle[3], rectangle[2], -rectangle[1], rectangle[4]} > end > > function rect.scale(rectangle, scale) > if type(scale) == "table" then > return {rectangle[1] * scale[1], rectangle[2] * scale[2], rectangle[3] * scale[1], rectangle[4] * scale[2]} > else > return {rectangle[1] * scale, rectangle[2] * scale, rectangle[3] * scale, rectangle[4] * scale} > end > end > > function rect.pad(rectangle, padding) > if type(padding) == "table" then > return {rectangle[1] - padding[1], rectangle[2] - padding[2], rectangle[3] + padding[1], rectangle[4] + padding[2]} > else > return {rectangle[1] - padding, rectangle[2] - padding, rectangle[3] + padding, rectangle[4] + padding} > end > end > > function rect.contains(rectangle, point) > return point[1] >= rectangle[1] > and point[2] >= rectangle[2] > and point[1] <= rectangle[3] > and point[2] <= rectangle[4] > end > > function rect.snap(rect, point, direction) > if direction[1] < 0 then > return {rect[1], point[2]} > elseif direction[1] > 0 then > return {rect[3], point[2]} > elseif direction[2] < 0 then > return {point[1], rect[2]} > elseif direction[2] > 0 then > return {point[1], rect[4]} > end > end > > function rect.bound(inner, outer) > if inner[4] > outer[4] then > inner = rect.translate(inner, {0, outer[4] - inner[4]}) > elseif inner[2] < outer[2] then > inner = rect.translate(inner, {0, outer[2] - inner[2]}) > end > if inner[3] > outer[3] then > inner = rect.translate(inner, {outer[3] - inner[3], 0}) > elseif inner[1] < outer[1] then > inner = rect.translate(inner, {outer[1] - inner[1], 0}) > end > return inner > end scripts\stateMachine.lua 161c161 < math.randomseed(os.time()) --- > math.randomseed(math.floor((os.time() + (os.clock() % 1)) * 1000)) 251c251 < --- > scripts\util.lua 129a130,138 > function util.all(t, predicate) > for _,v in ipairs(t) do > if not predicate(v) then > return false > end > end > return true > end > 136c145,153 < function util.keys(t, func) --- > function util.values(t) > local vals = {} > for _, v in pairs(t) do > table.insert(vals, v) > end > return vals > end > > function util.keys(t) 143a161,166 > function util.orderedKeys(t) > local keys = util.keys(t) > table.sort(keys) > return keys > end > 372a396,403 > -- yields until a promise is finished > function util.await(promise) > while not promise:finished() do > coroutine.yield() > end > return promise > end > 481,484d511 < if seed then < math.randomseed(seed) < end < 490c517 < local choice = math.random() * totalWeight --- > local choice = (seed and sb.staticRandomDouble(seed) or math.random()) * totalWeight 567a595,597 > function util.toDegrees(radians) > return (radians * 180) / math.pi > end 591d620 < sb.logInfo("%s", math.sin((ratio - 1) * math.pi / 2)) 779a809,835 > end > end > > function util.generateTextTags(t) > local tags = {} > for k,v in pairs(t) do > if type(v) == "table" then > for tagName,tag in pairs(util.generateTextTags(v)) do > tags[k.."."..tagName] = tag > end > else > tags[k] = v > end > end > return tags > end > > function util.recReplaceTags(v, tags) > if type(v) == "table" then > for k, v2 in pairs(v) do > v[k] = util.recReplaceTags(v2, tags) > end > return v > elseif type(v) == "string" then > return sb.replaceTags(v, tags) > else > return v scripts\vec2.lua 129a130,133 > > function vec2.lerp(ratio, a, b) > return {a[1] + (b[1] - a[1]) * ratio, a[2] + (b[2] - a[2]) * ratio} > end scripts\actions\dialog.lua 55,56c55 < math.randomseed(context().seed()) < return list[math.random(1, #list)] --- > return list[sb.staticRandomI32Range(1, #list, context().seed())] 96a96,103 > -- param tag > -- param text > function setDialogTag(args, board) > self.dialogTags = self.dialogTags or {} > self.dialogTags[args.tag] = args.text > return true > end > 118,119c125,134 < args.tags.selfname = world.entityName(entity.id()) < if args.entity then args.tags.entityname = world.entityName(args.entity) end --- > local tags = sb.jsonMerge(self.dialogTags or {}, args.tags) > tags.selfname = world.entityName(entity.id()) > if args.entity then > tags.entityname = world.entityName(args.entity) > > local entityType = world.entityType(args.entity) > if entityType and entityType == "npc" then > tags.entitySpecies = world.entitySpecies(args.entity) > end > end 128c143 < context().say(dialog, args.tags, options) --- > context().say(dialog, tags, options) scripts\actions\merchant.lua 99c99 < math.randomseed(os.time()) --- > math.randomseed(util.seedTime()) 157a158,163 > > function getItemFromTreasure(args, board) > local items = root.createTreasure(args.pool, args.level) > local item = util.randomFromList(items, sb.makeRandomSource()) > return true, {item = item} > end \ No newline at end of file scripts\actions\movement.lua 267c267 < openDoorsAhead() --- > --openDoorsAhead() scripts\actions\npc.lua 43d42 < definition = args.definition, 89a89,96 > -- param slot > function unequipSlot(args, output) > npc.setItemSlot(args.slot, nil) > storage.itemSlots = storage.itemSlots or {} > storage.itemSlots[string.lower(args.slot)] = args.itemTable > return true > end > 99c106 < --- > 143a151,155 > function setPersistent(args, board) > npc.setPersistent(args.persistent) > return true > end > 373a386,389 > > function level(args, board) > return true, {level = npc.level()} > end \ No newline at end of file scripts\actions\overrides.lua 1,106c1,106 < require("/scripts/util.lua") < < -- Stores behavior trees for this context so they don't need to be rebuilt every time < OverridesTreeCache = {} < < function getOverrides() < storage.behaviorOverrides = storage.behaviorOverrides or {} < return storage.behaviorOverrides < end < < function getOverrideTypes() < if not self.behaviorOverrideTypes then < self.behaviorOverrideTypes = {} < for overrideType, overrides in pairs(getOverrides()) do < for id,_ in pairs(overrides) do < self.behaviorOverrideTypes[id] = overrideType < end < end < end < return self.behaviorOverrideTypes < end < < function addOverride(overrideId, override) < getOverrideTypes()[overrideId] = override.type < local overrides = getOverrides() < overrides[override.type] = overrides[override.type] or {} < overrides[override.type][overrideId] = override < end < < function removeOverride(overrideId) < local overrideType = getOverrideTypes()[overrideId] < if not overrideType then return end < local overrides = getOverrides() < overrides[overrideType] = overrides[overrideType] or {} < overrides[overrideType][overrideId] = nil < getOverrideTypes()[overrideId] = nil < end < < function hasOverride(overrideId) < local overrideType = getOverrideTypes()[overrideId] < return overrideType ~= nil < end < < function hasAnyOverride() < return not isEmpty(getOverrideTypes()) < end < < -- param overrideName < -- output list < function matchingOverrides(args, board) < local overrides = getOverrides()[args.overrideName] or {} < < local list = util.filter(util.toList(overrides), function (override) < if override.questId and override.questFlag then < return self.quest:getQuestValue(override.questId, override.questFlag) and true or false < end < return true < end) < < if isEmpty(list) then return false end < return true, {list = list} < end < < -- param override < -- param argumentName < -- output entity < function overrideEntity(args, output) < if not args.override then return false end < < local uniqueId = args.override[args.argumentName] < if not uniqueId then return false end < local entityId = world.loadUniqueEntity(uniqueId) < if not world.entityExists(entityId) then return false end < < return true, {entity = entityId} < end < < -- param override < -- param argumentName < -- output behavior < function overrideBehavior(args, board) < if not args.override then return false end < return true, {behavior = args.override[args.argumentName]} < end < < function playBehavior(args, board, nodeId, dt) < if not args.behavior then return false end < < local key = string.format("playBehavior-%s-%s", args.behavior.name, nodeId) < local tree = OverridesTreeCache[key] < if not tree then < tree = behavior.behavior(args.behavior.name, config.getParameter("behaviorConfig", {}), _ENV, board) < OverridesTreeCache[key] = tree < else < tree:clear() < end < < while true do < local result = tree:run(dt) < if result == false or result == true then < return result < else < dt = coroutine.yield() < end < end < end --- > require("/scripts/util.lua") > > -- Stores behavior trees for this context so they don't need to be rebuilt every time > OverridesTreeCache = {} > > function getOverrides() > storage.behaviorOverrides = storage.behaviorOverrides or {} > return storage.behaviorOverrides > end > > function getOverrideTypes() > if not self.behaviorOverrideTypes then > self.behaviorOverrideTypes = {} > for overrideType, overrides in pairs(getOverrides()) do > for id,_ in pairs(overrides) do > self.behaviorOverrideTypes[id] = overrideType > end > end > end > return self.behaviorOverrideTypes > end > > function addOverride(overrideId, override) > getOverrideTypes()[overrideId] = override.type > local overrides = getOverrides() > overrides[override.type] = overrides[override.type] or {} > overrides[override.type][overrideId] = override > end > > function removeOverride(overrideId) > local overrideType = getOverrideTypes()[overrideId] > if not overrideType then return end > local overrides = getOverrides() > overrides[overrideType] = overrides[overrideType] or {} > overrides[overrideType][overrideId] = nil > getOverrideTypes()[overrideId] = nil > end > > function hasOverride(overrideId) > local overrideType = getOverrideTypes()[overrideId] > return overrideType ~= nil > end > > function hasAnyOverride() > return not isEmpty(getOverrideTypes()) > end > > -- param overrideName > -- output list > function matchingOverrides(args, board) > local overrides = getOverrides()[args.overrideName] or {} > > local list = util.filter(util.toList(overrides), function (override) > if override.questId and override.questFlag then > return self.quest:getQuestValue(override.questId, override.questFlag) and true or false > end > return true > end) > > if isEmpty(list) then return false end > return true, {list = list} > end > > -- param override > -- param argumentName > -- output entity > function overrideEntity(args, output) > if not args.override then return false end > > local uniqueId = args.override[args.argumentName] > if not uniqueId then return false end > local entityId = world.loadUniqueEntity(uniqueId) > if not world.entityExists(entityId) then return false end > > return true, {entity = entityId} > end > > -- param override > -- param argumentName > -- output behavior > function overrideBehavior(args, board) > if not args.override then return false end > return true, {behavior = args.override[args.argumentName]} > end > > function playBehavior(args, board, nodeId, dt) > if not args.behavior then return false end > > local key = string.format("playBehavior-%s-%s", args.behavior.name, nodeId) > local tree = OverridesTreeCache[key] > if not tree then > tree = behavior.behavior(args.behavior.name, sb.jsonMerge(config.getParameter("behaviorConfig", {}), args.behavior.parameters or {}), _ENV, board) > OverridesTreeCache[key] = tree > else > tree:clear() > end > > while true do > local result = tree:run(dt) > if result == false or result == true then > return result > else > dt = coroutine.yield() > end > end > end scripts\actions\quests.lua 92a93,96 > function hasRole(args, board) > return self.quest:hasRole() > end > scripts\actions\world.lua 322a323,367 > > function spawnItem(args) > world.spawnItem(args.item, args.position, args.count, args.parameters, args.velocity, args.intangibleTime) > return true > end > > -- param player > -- param title > -- param subtitle > -- param icon > -- param message > -- param okCaption > -- param cancelCaption > function playerConfirm(args) > local dialogConfig = { > title = args.title, > subtitle = args.subtitle, > icon = args.icon, > message = args.message, > okCaption = args.okCaption, > cancelCaption = args.cancelCaption, > sourceEntityId = entity.id() > } > > -- ask player for confirmation, returns a uuid used for polling the result > local confirm = util.await(world.sendEntityMessage(args.player, "confirm", dialogConfig)) > if not confirm:succeeded() then > error("Confirm message failed") > end > > local uuid = confirm:result() > while true do > -- poll confirmation until the message fails (player is gone) or a result is returned > local confirmResult = util.await(world.sendEntityMessage(args.player, "confirmResult", uuid)) > if not confirmResult:succeeded() then > return false > end > local res = confirmResult:result() > if res == nil then > util.run(0.5) > else > return res == true > end > end > end \ No newline at end of file scripts\actions\npc\tonauac.lua 3,5c3,4 < math.randomseed(seed) < < local blessing = args.blessings[math.random(1,#args.blessings)] --- > > local blessing = args.blessings[sb.staticRandomI32Range(1, #args.blessings, seed)] scripts\activeitem\stances.lua 7a8 > self.aimAngle = 0 22a24,31 > if type(self.stance.armRotation) == "table" then > self.armRotation = self.stance.armRotation[1] > else > self.armRotation = self.stance.armRotation or 0 > end > if self.stance.resetAim then > self.aimAngle = 0 > end 29a39,44 > > if type(self.stance.armRotation) == "table" then > local stanceRatio = 1 - (self.stanceTimer / self.stance.duration) > self.armRotation = util.lerp(stanceRatio, self.stance.armRotation) > end > 51c66 < aimAngle = (self.aimAngle or 0) + util.toRadians(self.stance.armRotation) --- > aimAngle = self.aimAngle + util.toRadians(self.armRotation) scripts\companions\capturable.lua 1,287c1,286 < require "/scripts/companions/util.lua" < require "/scripts/achievements.lua" < < -- Functions for entities that can be captured with a capturepod < capturable = {} < < function capturable.init() < message.setHandler("pet.attemptCapture", function (_, _, ...) < return capturable.attemptCapture(...) < end) < message.setHandler("pet.attemptRelocate", function (_, _, ...) < return capturable.attemptRelocate(...) < end) < message.setHandler("pet.returnToPod", function(_, _, ...) < local status = capturable.captureStatus() < capturable.recall() < return status < end) < message.setHandler("pet.status", function(_, _, persistentEffects, damageTeam) < if persistentEffects then < status.setPersistentEffects("owner", persistentEffects) < end < if damageTeam then < monster.setDamageTeam(damageTeam) < end < return { status = capturable.captureStatus() } < end) < < local initialStatus = config.getParameter("initialStatus") < if initialStatus then < setCurrentStatus(initialStatus, "owner") < end < < if capturable.podUuid() then < capturable.startReleaseAnimation() < end < < if capturable.wasRelocated() and not storage.spawned then < status.addEphemeralEffect("monsterrelocatespawn") < storage = config.getParameter("relocateStorage", {}) < storage.spawned = true < end < end < < function capturable.startReleaseAnimation() < status.addEphemeralEffect("monsterrelease") < animator.setAnimationState("releaseParticles", "on") < end < < function capturable.update(dt) < if capturable.ownerUuid() then < if not capturable.optName() then < monster.setName("Pet") < end < monster.setDisplayNametag(true) < end < < if config.getParameter("uniqueId") then < if entity.uniqueId() == nil then < world.setUniqueId(entity.id(), config.getParameter("uniqueId")) < else < assert(entity.uniqueId() == config.getParameter("uniqueId")) < end < end < < if capturable.despawnTimer then < capturable.despawnTimer = capturable.despawnTimer - dt < if capturable.despawnTimer <= 0 then < capturable.despawn() < end < else < local spawner = capturable.tetherUniqueId() or capturable.ownerUuid() < if spawner then < if not world.entityExists(world.loadUniqueEntity(spawner)) then < capturable.recall() < end < end < end < < if capturable.confirmRelocate then < if capturable.confirmRelocate:finished() then < if capturable.confirmRelocate:result() then < capturable.despawnTimer = 0.3 < else < status.removeEphemeralEffect("monsterrelocate") < status.addEphemeralEffect("monsterrelocatespawn") < end < capturable.confirmRelocate = nil < end < end < end < < function capturable.die() < if capturable.ownerUuid() and not capturable.justCaptured then < local podUuid = capturable.podUuid() < if podUuid then < local uniqueId = entity.uniqueId() < local status = capturable.captureStatus() < status.dead = true < capturable.messageOwner("pets.updatePet", podUuid, uniqueId, status, true) < end < monster.setDropPool(nil) < end < end < < -- Extricate this pet from its pod until the next time the pod is 'healed'. < function capturable.disassociate() < local podUuid = capturable.podUuid() < if capturable.ownerUuid() and podUuid then < capturable.messageOwner("pets.disassociatePet", podUuid, entity.uniqueId()) < capturable.disassociated = true < end < end < < -- Associate another monster with this monster's pod. < function capturable.associate(pet) < assert(capturable.ownerUuid()) < local podUuid = config.getParameter("podUuid") < capturable.messageOwner("pets.associatePet", podUuid, pet) < end < < function capturable.tetherUniqueId() < return config.getParameter("tetherUniqueId") < end < < function capturable.ownerUuid() < return config.getParameter("ownerUuid") < end < < function capturable.podUuid() < if capturable.disassociated then < return nil < end < return config.getParameter("podUuid") < end < < function capturable.messageOwner(message, ...) < world.sendEntityMessage(capturable.tetherUniqueId() or capturable.ownerUuid(), message, ...) < end < < function capturable.captureStatus() < local currentStatus = getCurrentStatus() < -- Compute some artificial stats for displaying in the inventory, next to the < -- pet slot: < local stats = currentStatus.stats < stats.defense = stats.protection < stats.attack = 0 < local touchDamageConfig = config.getParameter("touchDamage") < if touchDamageConfig then < stats.attack = touchDamageConfig.damage < stats.attack = stats.attack * (config.getParameter("touchDamageMultiplier") or 1) < stats.attack = stats.attack * root.evalFunction("monsterLevelPowerMultiplier", monster.level()) < stats.attack = stats.attack * stats.powerMultiplier < end < < return currentStatus < end < < function capturable.recall() < animator.burstParticleEmitter("captureParticles") < status.addEphemeralEffect("monstercapture") < capturable.despawnTimer = 0.5 < end < < function capturable.despawn() < monster.setDropPool(nil) < monster.setDeathParticleBurst(nil) < < local projectileTarget = capturable.tetherUniqueId() or capturable.ownerUuid() < if projectileTarget then < projectileTarget = world.loadUniqueEntity(projectileTarget) < if not projectileTarget or not world.entityExists(projectileTarget) then < projectileTarget = nil < end < end < if projectileTarget then < local projectiles = 5 < for i = 1, projectiles do < local angle = math.pi * 2 / projectiles * i < local direction = { math.sin(angle), math.cos(angle) } < world.spawnProjectile("monstercaptureenergy", entity.position(), entity.id(), direction, false, { < target = projectileTarget < }) < end < end < < capturable.justCaptured = true < end < < function capturable.attemptCapture(podOwner) < -- Try to capture the monster. If successful, the monster is killed and the < -- pet configuration is returned. < if capturable.capturable() then < local petInfo = capturable.generatePet() < < recordEvent(podOwner, "captureMonster", entityEventFields(entity.id()), worldEventFields(), { < monsterLevel = monster.level() < }) < < capturable.recall() < return petInfo < end < return nil < end < < function capturable.wasRelocated() < return config.getParameter("wasRelocated", false) < end < < function capturable.attemptRelocate(sourceEntity) < if config.getParameter("relocatable", false) and not capturable.confirmRelocate then < --The point that the monster will scale toward < local scaleOffsetPart = config.getParameter("scaleOffsetPart", "body") < local attachPoint = vec2.div(animator.partPoint(scaleOffsetPart, "offset") or {0, 0}, 2) -- divide by two because partPoint adds offset to offset < local petInfo = { < monsterType = monster.type(), < collisionPoly = mcontroller.collisionPoly(), < parameters = monster.uniqueParameters(), < attachPoint = attachPoint < } < for k,v in pairs(config.getParameter("relocateParameters", {})) do < petInfo.parameters[k] = v < end < petInfo.parameters.relocateStorage = storage < petInfo.parameters.seed = monster.seed() < < status.addEphemeralEffect("monsterrelocate") < capturable.confirmRelocate = world.sendEntityMessage(sourceEntity, "confirmRelocate", entity.id(), petInfo) < return true < end < end < < function capturable.capturable(capturer) < if capturable.ownerUuid() or storage.respawner then < return false < end < < local isCapturable = config.getParameter("capturable") < if not isCapturable then < return false < end < < local captureHealthFraction = config.getParameter("captureHealthFraction", 0.5) < local healthFraction = status.resource("health") / status.resourceMax("health") < if healthFraction > captureHealthFraction then < return false < end < < return true < end < < function capturable.optName() < local name = world.entityName(entity.id()) < if name == "" then < return nil < end < return name < end < < function capturable.generatePet() < local parameters = monster.uniqueParameters() < parameters.aggressive = true < < parameters.seed = monster.seed() < parameters.level = monster.level() < parameters.familyIndex = monster.familyIndex() < < local poly = mcontroller.collisionPoly() < if #poly <= 0 then poly = nil end < < local monsterType = config.getParameter("capturedMonsterType", monster.type()) < local name = config.getParameter("capturedMonsterName", capturable.optName()) < local captureCollectables = config.getParameter("captureCollectables") < < return { < name = name, < description = world.entityDescription(entity.id()), < portrait = world.entityPortrait(entity.id(), "full"), < collisionPoly = poly, < status = capturable.captureStatus(), < collectables = captureCollectables, < config = { < type = monsterType, < parameters = parameters < } < } < end --- > require "/scripts/companions/util.lua" > require "/scripts/achievements.lua" > > -- Functions for entities that can be captured with a capturepod > capturable = {} > > function capturable.init() > message.setHandler("pet.attemptCapture", function (_, _, ...) > return capturable.attemptCapture(...) > end) > message.setHandler("pet.attemptRelocate", function (_, _, ...) > return capturable.attemptRelocate(...) > end) > message.setHandler("pet.returnToPod", function(_, _, ...) > local status = capturable.captureStatus() > capturable.recall() > return status > end) > message.setHandler("pet.status", function(_, _, persistentEffects, damageTeam) > if persistentEffects then > status.setPersistentEffects("owner", persistentEffects) > end > if damageTeam then > monster.setDamageTeam(damageTeam) > end > return { status = capturable.captureStatus() } > end) > > local initialStatus = config.getParameter("initialStatus") > if initialStatus then > setCurrentStatus(initialStatus, "owner") > end > > if capturable.podUuid() then > capturable.startReleaseAnimation() > end > > if capturable.wasRelocated() and not storage.spawned then > status.addEphemeralEffect("monsterrelocatespawn") > storage = config.getParameter("relocateStorage", {}) > storage.spawned = true > end > end > > function capturable.startReleaseAnimation() > status.addEphemeralEffect("monsterrelease") > animator.setAnimationState("releaseParticles", "on") > end > > function capturable.update(dt) > if capturable.ownerUuid() then > if not capturable.optName() then > monster.setName("Pet") > end > monster.setDisplayNametag(true) > end > > if config.getParameter("uniqueId") then > if entity.uniqueId() == nil then > world.setUniqueId(entity.id(), config.getParameter("uniqueId")) > else > assert(entity.uniqueId() == config.getParameter("uniqueId")) > end > end > > if capturable.despawnTimer then > capturable.despawnTimer = capturable.despawnTimer - dt > if capturable.despawnTimer <= 0 then > capturable.despawn() > end > else > local spawner = capturable.tetherUniqueId() or capturable.ownerUuid() > if spawner then > if not world.entityExists(world.loadUniqueEntity(spawner)) then > capturable.recall() > end > end > end > > if capturable.confirmRelocate then > if capturable.confirmRelocate:finished() then > if capturable.confirmRelocate:result() then > capturable.despawnTimer = 0.3 > else > status.removeEphemeralEffect("monsterrelocate") > status.addEphemeralEffect("monsterrelocatespawn") > end > capturable.confirmRelocate = nil > end > end > end > > function capturable.die() > if capturable.ownerUuid() and not capturable.justCaptured then > local podUuid = capturable.podUuid() > if podUuid then > local uniqueId = entity.uniqueId() > local status = capturable.captureStatus() > status.dead = true > capturable.messageOwner("pets.updatePet", podUuid, uniqueId, status, true) > end > monster.setDropPool(nil) > end > end > > -- Extricate this pet from its pod until the next time the pod is 'healed'. > function capturable.disassociate() > local podUuid = capturable.podUuid() > if capturable.ownerUuid() and podUuid then > capturable.messageOwner("pets.disassociatePet", podUuid, entity.uniqueId()) > capturable.disassociated = true > end > end > > -- Associate another monster with this monster's pod. > function capturable.associate(pet) > assert(capturable.ownerUuid()) > local podUuid = config.getParameter("podUuid") > capturable.messageOwner("pets.associatePet", podUuid, pet) > end > > function capturable.tetherUniqueId() > return config.getParameter("tetherUniqueId") > end > > function capturable.ownerUuid() > return config.getParameter("ownerUuid") > end > > function capturable.podUuid() > if capturable.disassociated then > return nil > end > return config.getParameter("podUuid") > end > > function capturable.messageOwner(message, ...) > world.sendEntityMessage(capturable.tetherUniqueId() or capturable.ownerUuid(), message, ...) > end > > function capturable.captureStatus() > local currentStatus = getCurrentStatus() > -- Compute some artificial stats for displaying in the inventory, next to the > -- pet slot: > local stats = currentStatus.stats > stats.defense = stats.protection > stats.attack = 0 > local touchDamageConfig = config.getParameter("touchDamage") > if touchDamageConfig then > stats.attack = touchDamageConfig.damage > stats.attack = stats.attack * (config.getParameter("touchDamageMultiplier") or 1) > stats.attack = stats.attack * root.evalFunction("monsterLevelPowerMultiplier", monster.level()) > stats.attack = stats.attack * stats.powerMultiplier > end > > return currentStatus > end > > function capturable.recall() > animator.burstParticleEmitter("captureParticles") > status.addEphemeralEffect("monstercapture") > capturable.despawnTimer = 0.5 > end > > function capturable.despawn() > monster.setDropPool(nil) > monster.setDeathParticleBurst(nil) > > local projectileTarget = capturable.tetherUniqueId() or capturable.ownerUuid() > if projectileTarget then > projectileTarget = world.loadUniqueEntity(projectileTarget) > if not projectileTarget or not world.entityExists(projectileTarget) then > projectileTarget = nil > end > end > if projectileTarget then > local projectiles = 5 > for i = 1, projectiles do > local angle = math.pi * 2 / projectiles * i > local direction = { math.sin(angle), math.cos(angle) } > world.spawnProjectile("monstercaptureenergy", entity.position(), entity.id(), direction, false, { > target = projectileTarget > }) > end > end > > capturable.justCaptured = true > end > > function capturable.attemptCapture(podOwner) > -- Try to capture the monster. If successful, the monster is killed and the > -- pet configuration is returned. > if capturable.capturable() then > local petInfo = capturable.generatePet() > > recordEvent(podOwner, "captureMonster", entityEventFields(entity.id()), worldEventFields(), { > monsterLevel = monster.level() > }) > > capturable.recall() > return petInfo > end > return nil > end > > function capturable.wasRelocated() > return config.getParameter("wasRelocated", false) > end > > function capturable.attemptRelocate(sourceEntity) > if config.getParameter("relocatable", false) and not capturable.confirmRelocate then > --The point that the monster will scale toward > local scaleOffsetPart = config.getParameter("scaleOffsetPart", "body") > local attachPoint = vec2.div(animator.partPoint(scaleOffsetPart, "offset") or {0, 0}, 2) -- divide by two because partPoint adds offset to offset > local petInfo = { > monsterType = monster.type(), > collisionPoly = mcontroller.collisionPoly(), > parameters = monster.uniqueParameters(), > attachPoint = attachPoint > } > for k,v in pairs(config.getParameter("relocateParameters", {})) do > petInfo.parameters[k] = v > end > petInfo.parameters.relocateStorage = storage > petInfo.parameters.seed = monster.seed() > > status.addEphemeralEffect("monsterrelocate") > capturable.confirmRelocate = world.sendEntityMessage(sourceEntity, "confirmRelocate", entity.id(), petInfo) > return true > end > end > > function capturable.capturable(capturer) > if capturable.ownerUuid() or storage.respawner then > return false > end > > local isCapturable = config.getParameter("capturable") > if not isCapturable then > return false > end > > local captureHealthFraction = config.getParameter("captureHealthFraction", 0.5) > local healthFraction = status.resource("health") / status.resourceMax("health") > if healthFraction > captureHealthFraction then > return false > end > > return true > end > > function capturable.optName() > local name = world.entityName(entity.id()) > if name == "" then > return nil > end > return name > end > > function capturable.generatePet() > local parameters = monster.uniqueParameters() > parameters.aggressive = true > > parameters.seed = monster.seed() > parameters.level = monster.level() > > local poly = mcontroller.collisionPoly() > if #poly <= 0 then poly = nil end > > local monsterType = config.getParameter("capturedMonsterType", monster.type()) > local name = config.getParameter("capturedMonsterName", capturable.optName()) > local captureCollectables = config.getParameter("captureCollectables") > > return { > name = name, > description = world.entityDescription(entity.id()), > portrait = world.entityPortrait(entity.id(), "full"), > collisionPoly = poly, > status = capturable.captureStatus(), > collectables = captureCollectables, > config = { > type = monsterType, > parameters = parameters > } > } > end scripts\deployment\playermechdeployment.lua 8c8 < status.setStatusProperty("mechUnlocked", true) --- > player.setProperty("mechUnlocked", true) 73,76c73,76 < self.unlocked = status.statusProperty("mechUnlocked", false) < self.itemSet = status.statusProperty("mechItemSet", {}) < self.primaryColorIndex = status.statusProperty("mechPrimaryColorIndex", 0) < self.secondaryColorIndex = status.statusProperty("mechSecondaryColorIndex", 0) --- > self.unlocked = player.getProperty("mechUnlocked", false) > self.itemSet = player.getProperty("mechItemSet", {}) > self.primaryColorIndex = player.getProperty("mechPrimaryColorIndex", 0) > self.secondaryColorIndex = player.getProperty("mechSecondaryColorIndex", 0) 128c128 < status.setStatusProperty("mechItemSet", self.itemSet) --- > player.setProperty("mechItemSet", self.itemSet) 135,136c135,136 < status.setStatusProperty("mechPrimaryColorIndex", self.primaryColorIndex) < status.setStatusProperty("mechSecondaryColorIndex", self.secondaryColorIndex) --- > player.setProperty("mechPrimaryColorIndex", self.primaryColorIndex) > player.setProperty("mechSecondaryColorIndex", self.secondaryColorIndex) species\novakid.species 103c103 < "hair" : [ "male0", "male1", "male2", "male3", "male4", "male5", "male6", "male7", "male8", "male9", "male10", "male11", "male12", "male13", "male14", "male15", "male16", "male17", "male18", "male19" ], --- > "hair" : [ "male0", "male1", "male2", "male3", "male4", "male5", "male6", "male7", "male8", "male9", "male10", "male11", "male12", "male13", "male14", "male15", "male16", "male17", "male18", "male19", "male20" ], 115c115 < "hair" : [ "fem0", "fem1", "fem2", "fem3", "fem4", "fem5", "fem6", "fem7", "fem8", "fem9", "fem10", "fem11", "fem12", "fem13", "fem14", "fem15", "fem16", "fem17", "fem18", "fem19" ], --- > "hair" : [ "fem0", "fem1", "fem2", "fem3", "fem4", "fem5", "fem6", "fem7", "fem8", "fem9", "fem10", "fem11", "fem12", "fem13", "fem14", "fem15", "fem16", "fem17", "fem18", "fem19", "fem20" ], species\novakidnamegen.config 6c6 < [ { "mode" : "alts" }, "Ace", "Acro", "Acryl", "Ammo", "Amyl", "Aqu", "Argon", "Axus", "Azen", "Azure", "Badde", "Bail", "Benze", "Benzy", "Beryl", "Billy", "Blaz", "Blue", "Boston", "Bronco", "Buck", "Bullet", "Butane", "Butch", "Butyl", "Byrd", "Carbo", "Cerise", "Clint", "Clem", "Cobalt", "Country", "Cetus", "Chloro", "Chrome", "Corvus", "Crimson", "Curie", "Cyan", "Cylo", "Dace", "Dandy", "Dash", "Decane", "Desert", "Dex", "Dice", "Ditch", "Diethyl", "Dioxie", "Dioxol", "Dodeca", "Domino", "Dowan", "Droe", "Dusty", "Dyme", "Epich", "Eryx", "Ethane", "Ethoxy", "Ethyl", "Farady", "Flint", "Freon", "Fuel", "Furan", "Furf", "Gibbs", "Goode", "Green", "Gun", "Gutter", "Helium", "Heptan", "Hexan", "Hexen", "Hydro", "Ion", "Indigo", "Isobu", "Jane", "Jesse", "Jet", "Kadi", "Kero", "Kid", "Lacto", "Lane", "Lasso", "Lead", "Leather", "Lefty", "Leo", "Lex", "Libra", "Luca", "Lucky", "Lumen", "Lynx", "Lyra", "Magie", "Marshall", "Merca", "Metha", "Methan", "Methox", "Methyl", "Milli", "Minera", "Montana", "Naptha", "Neon", "Nitric", "Nitro", "Nonane", "Octane", "Octyl", "Orio", "Oxy", "Pentan", "Perch", "Pers", "Pete", "Pheno", "Phenyl", "Pinen", "Pistol", "Propane", "Propyl", "Quark", "Quarren", "Randy", "Raider", "Raven", "Razor", "Red", "Ringo", "Ruby", "Rush", "Ryder", "Saddle", "Sawyer", "Scarlet", "Scout", "Seth", "Shade", "Silver", "Smokey", "Sonny", "Spike", "Styre", "Slang", "Target", "Teal", "Tert", "Tesla", "Tetra", "Topper", "Trigger", "Trix", "Ursa", "Varni", "Vela", "Vinyl", "Virgo", "Ward", "Warren", "Wayne", "Whip", "Wild", "Xylene", "Xenon", "Zane", "Zeke", "Zinc", "Zolan" ] --- > [ { "mode" : "alts" }, "Ace", "Acro", "Acryl", "Ammo", "Amyl", "Aqu", "Argon", "Axus", "Azen", "Azure", "Badde", "Bail", "Benze", "Benzy", "Beryl", "Billy", "Blaz", "Blue", "Boston", "Bronco", "Buck", "Bullet", "Butane", "Butch", "Butyl", "Byrd", "Carbo", "Cerise", "Clint", "Clem", "Cobalt", "Country", "Cetus", "Chloro", "Chrome", "Corvus", "Crimson", "Curie", "Cyan", "Cylo", "Dace", "Dandy", "Dash", "Decane", "Desert", "Dex", "Dice", "Ditch", "Diethyl", "Dioxie", "Dioxol", "Dodeca", "Domino", "Dowan", "Droe", "Dusty", "Dyme", "Epich", "Eryx", "Ethane", "Ethoxy", "Ethyl", "Farady", "Flint", "Freon", "Fuel", "Furan", "Furf", "Gibbs", "Goode", "Green", "Gun", "Gutter", "Helium", "Heptan", "Hexan", "Hexen", "Hydro", "Ion", "Indigo", "Isobu", "Jane", "Jesse", "Jet", "Kadi", "Kero", "Kid", "Lacto", "Lane", "Lasso", "Lead", "Lefty", "Leo", "Lex", "Libra", "Luca", "Lucky", "Lumen", "Lynx", "Lyra", "Magie", "Marshall", "Merca", "Metha", "Methan", "Methox", "Methyl", "Milli", "Minera", "Montana", "Naptha", "Neon", "Nitric", "Nitro", "Nonane", "Octane", "Octyl", "Orio", "Oxy", "Pentan", "Perch", "Pers", "Pete", "Pheno", "Phenyl", "Pinen", "Pistol", "Propane", "Propyl", "Quark", "Quarren", "Randy", "Raider", "Raven", "Razor", "Red", "Ringo", "Ruby", "Rush", "Ryder", "Saddle", "Sawyer", "Scarlet", "Scout", "Seth", "Shade", "Silver", "Smokey", "Sonny", "Spike", "Styre", "Slang", "Target", "Teal", "Tert", "Tesla", "Tetra", "Topper", "Trigger", "Trix", "Ursa", "Varni", "Vela", "Vinyl", "Virgo", "Ward", "Warren", "Wayne", "Whip", "Wild", "Xylene", "Xenon", "Zane", "Zeke", "Zinc", "Zolan" ] stagehands\objecttracker.lua 1,54c1,46 < require "/scripts/stagehandutil.lua" < require "/scripts/rect.lua" < require "/scripts/util.lua" < < function init() < end < < function update(dt) < local area = translateBroadcastArea() < if world.regionActive(area) then < local objects = world.entityQuery(rect.ll(area), rect.ur(area), { includedTypes = {"object"} }) < if self.objects then < local removed = util.filter(util.keys(self.objects), function(objectId) return not contains(objects, objectId) end) < if #removed > 0 then < for _,brokenId in pairs(removed) do < broadcastObjectBroken(self.objects[brokenId]) < end < setObjects(objects) < end < else < setObjects(objects) < end < end < end < < function setObjects(objectIds) < self.objects = {} < for _,objectId in pairs(objectIds) do < self.objects[objectId] = world.entityPosition(objectId) < end < end < < function broadcastObjectBroken(position) < local area = translateBroadcastArea() < < local players = world.entityQuery(rect.ll(area), rect.ur(area), { includedTypes = {"player"}}) < if #players > 0 then < table.sort(players, function(a,b) < return world.magnitude(world.entityPosition(a), position) < world.magnitude(world.entityPosition(b), position) < end) < local notification = { < type = "objectBroken", < sourceId = entity.id(), < targetPosition = position, < targetId = players[1] < } < local npcs = world.entityQuery(rect.ll(area), rect.ur(area), { includedTypes = {"npc"} }) < for _,npcId in pairs(npcs) do < if world.entityDamageTeam(npcId).team == 1 then < world.sendEntityMessage(npcId, "notify", notification) < end < end < end < end --- > require "/scripts/stagehandutil.lua" > require "/scripts/rect.lua" > require "/scripts/util.lua" > > function init() > self.region = translateBroadcastArea() > > message.setHandler("tileBroken", function(_, _, sourceId, pos) > if rect.contains(self.region, pos) then > broadcastTileBroken(sourceId, pos) > end > end) > > message.setHandler("objectBroken", function(_, _, sourceId, pos) > if rect.contains(self.region, pos) then > broadcastObjectBroken(sourceId, pos) > end > end) > end > > function broadcastTileBroken(sourceId, position) > broadcast(position, { > type = "tileBroken", > sourceId = entity.id(), > targetPosition = position, > targetId = sourceId, > }) > end > > function broadcastObjectBroken(sourceId, position) > broadcast(position, { > type = "objectBroken", > sourceId = entity.id(), > targetPosition = position, > targetId = sourceId, > }) > end > > function broadcast(position, notification) > local npcs = world.entityQuery(position, 30, { includedTypes = {"npc"} }) > for _,npcId in pairs(npcs) do > if world.entityDamageTeam(npcId).team == 1 then > world.sendEntityMessage(npcId, "notify", notification) > end > end > end \ No newline at end of file stagehands\objecttracker.stagehand 1,9c1,9 < { < // please don't modify this file, it's a generically configurable stagehand to be used by dungeons < "type" : "objecttracker", < < "scripts" : ["/stagehands/objecttracker.lua"], < "scriptDelta" : 30, < < "broadcastArea" : [-16, -16, 16, 16] < } --- > { > // please don't modify this file, it's a generically configurable stagehand to be used by dungeons > "type" : "objecttracker", > > "scripts" : ["/stagehands/objecttracker.lua"], > "scriptDelta" : 0, > > "broadcastArea" : [-16, -16, 16, 16] > } stagehands\questlocation.lua 1,110c1,111 < require "/scripts/quest/participant.lua" < require "/scripts/quest/location.lua" < require "/scripts/stagehandutil.lua" < require "/scripts/spawnPoint.lua" < < function init() < if not entity.uniqueId() then < stagehand.setUniqueId(sb.makeUuid()) < end < < self.region = translateBroadcastArea() < < local locationType = config.getParameter("locationType") < assert(locationType ~= nil) < self.location = Location.new(entity.uniqueId(), locationType, self.region, storage.locationTags) < if not storage.locationTags then < storage.locationTags = self.location.tags < storage.regionModified = false < self.location:register() < end < < self.integrityCheck = util.interval(config.getParameter("integrityCheckCooldown"), checkIntegrity, 0) < < local questOutbox = Outbox.new("questOutbox", ContactList.new("questContacts")) < self.quest = QuestParticipant.new("quest", questOutbox) < end < < function uninit() < self.quest:uninit() < end < < function update(dt) < self.quest:update() < < if not storage.regionModified then < self.integrityCheck(dt) < end < < if not storage.regionModified then < if self.location:isRegistered() and self.quest:hasQuest() then < self.location:unregister() < elseif not self.location:isRegistered() and not self.quest:hasQuest() then < self.location:register() < end < < elseif not self.quest:hasActiveQuest() then < util.debugLog("Not registered and have no quests. Dying") < self.location:unregister() < self.quest:die() < stagehand.die() < end < end < < function checkIntegrity() < if world.isPlayerModified(self.region) then < util.debugLog("questlocation %s region has been modified by player", entity.uniqueId()) < storage.regionModified = true < self.location:unregister() < end < end < < function findPosition(boundBox) < return findSpaceInRect(self.region, boundBox) < end < < function containerHasSpace(entityId, numSlots) < -- Gives false negatives on mostly-full chests because it doesn't check if < -- the new items can stack. < for i = 0, world.containerSize(entityId)-1 do < local slot = world.containerItemAt(entityId, i) < if not slot or slot.count == 0 then < numSlots = numSlots - 1 < if numSlots <= 0 then < return true < end < end < end < return false < end < < function findChestWithSpace(objectTypes, treasure) < local objects = world.objectQuery({self.region[1], self.region[2]}, {self.region[3], self.region[4]}) < for _,entityId in pairs(objects) do < if not contains(objectTypes, world.entityName(entityId)) then return nil end < if not containerHasSpace(entityId, #treasure) then return nil end < return entityId < end < end < < function addTreasure(treasurePool) < local objectTypes = config.getParameter("treasureChests", {"treasurechest"}) < local treasure = root.createTreasure(treasurePool, world.threatLevel()) < local chest = findChestWithSpace(objectTypes, treasure) < if chest then < for _,item in pairs(treasure) do < local overflow = world.containerAddItems(chest, item) < if overflow then < world.spawnItem(overflow.name, world.entityPosition(chest), overflow.count, overflow.parameters) < end < end < return true < end < < local position = findSpaceInRect(self.region, {-1, 0, 1, 2}) < if not position then return false end < local objectType = objectTypes[math.random(#objectTypes)] < return world.placeObject(objectType, position, nil, { < treasurePools = {treasurePool} < }) < end --- > require "/scripts/quest/participant.lua" > require "/scripts/quest/location.lua" > require "/scripts/stagehandutil.lua" > require "/scripts/spawnPoint.lua" > > function init() > if not entity.uniqueId() then > stagehand.setUniqueId(sb.makeUuid()) > end > > self.region = translateBroadcastArea() > message.setHandler("broadcastRegion", function() return self.region end) > > local locationType = config.getParameter("locationType") > assert(locationType ~= nil) > self.location = Location.new(entity.uniqueId(), locationType, self.region, storage.locationTags) > if not storage.locationTags then > storage.locationTags = self.location.tags > storage.regionModified = false > self.location:register() > end > > self.integrityCheck = util.interval(config.getParameter("integrityCheckCooldown"), checkIntegrity, 0) > > local questOutbox = Outbox.new("questOutbox", ContactList.new("questContacts")) > self.quest = QuestParticipant.new("quest", questOutbox) > end > > function uninit() > self.quest:uninit() > end > > function update(dt) > self.quest:update() > > if not storage.regionModified then > self.integrityCheck(dt) > end > > if not storage.regionModified then > if self.location:isRegistered() and self.quest:hasQuest() then > self.location:unregister() > elseif not self.location:isRegistered() and not self.quest:hasQuest() then > self.location:register() > end > > elseif not self.quest:hasActiveQuest() then > util.debugLog("Not registered and have no quests. Dying") > self.location:unregister() > self.quest:die() > stagehand.die() > end > end > > function checkIntegrity() > if world.isPlayerModified(self.region) then > util.debugLog("questlocation %s region has been modified by player", entity.uniqueId()) > storage.regionModified = true > self.location:unregister() > end > end > > function findPosition(boundBox) > return findSpaceInRect(self.region, boundBox) > end > > function containerHasSpace(entityId, numSlots) > -- Gives false negatives on mostly-full chests because it doesn't check if > -- the new items can stack. > for i = 0, world.containerSize(entityId)-1 do > local slot = world.containerItemAt(entityId, i) > if not slot or slot.count == 0 then > numSlots = numSlots - 1 > if numSlots <= 0 then > return true > end > end > end > return false > end > > function findChestWithSpace(objectTypes, treasure) > local objects = world.objectQuery({self.region[1], self.region[2]}, {self.region[3], self.region[4]}) > for _,entityId in pairs(objects) do > if not contains(objectTypes, world.entityName(entityId)) then return nil end > if not containerHasSpace(entityId, #treasure) then return nil end > return entityId > end > end > > function addTreasure(treasurePool) > local objectTypes = config.getParameter("treasureChests", {"treasurechest"}) > local treasure = root.createTreasure(treasurePool, world.threatLevel()) > local chest = findChestWithSpace(objectTypes, treasure) > if chest then > for _,item in pairs(treasure) do > local overflow = world.containerAddItems(chest, item) > if overflow then > world.spawnItem(overflow.name, world.entityPosition(chest), overflow.count, overflow.parameters) > end > end > return true > end > > local position = findSpaceInRect(self.region, {-1, 0, 1, 2}) > if not position then return false end > local objectType = objectTypes[math.random(#objectTypes)] > return world.placeObject(objectType, position, nil, { > treasurePools = {treasurePool} > }) > end stagehands\waypoint.stagehand 1,5c1,9 < { < "type" : "waypoint", < "keepAlive" : true, < < "broadcastArea" : [-5, -5, 5, 5] --- > { > "type" : "waypoint", > "keepAlive" : true, > > "broadcastArea" : [-5, -5, 5, 5], > > "scripts" : [ > "/stagehands/waypoint.lua" > ] stats\fishing_primary.lua 1,47c1,51 < require "/scripts/vec2.lua" < < function init() < message.setHandler("applyStatusEffect", function(_, _, effectConfig, duration, sourceEntityId) < status.addEphemeralEffect(effectConfig, duration, sourceEntityId) < end) < end < < function applyDamageRequest(damageRequest) < if world.getProperty("nonCombat") then < return {} < end < < local damage = 0 < if damageRequest.damageType == "Damage" or damageRequest.damageType == "Knockback" then < damage = damage + root.evalFunction2("protection", damageRequest.damage, status.stat("protection")) < elseif damageRequest.damageType == "IgnoresDef" then < damage = damage + damageRequest.damage < elseif damageRequest.damageType == "Environment" then < return {} < end < < local healthLost = math.min(damage, status.resource("health")) < if healthLost > 0 and damageRequest.damageType ~= "Knockback" then < status.modifyResource("health", -healthLost) < self.damageFlashTime = 0.07 < end < < return {{ < sourceEntityId = damageRequest.sourceEntityId, < targetEntityId = entity.id(), < position = mcontroller.position(), < damageDealt = damage, < healthLost = healthLost, < hitType = damageRequest.hitType, < kind = "Normal", < damageSourceKind = damageRequest.damageSourceKind, < targetMaterialKind = status.statusProperty("targetMaterialKind"), < killed = not status.resourcePositive("health") < }} < end < < function update(dt) < if mcontroller.atWorldLimit() then < status.setResourcePercentage("health", 0) < end < end --- > require "/scripts/vec2.lua" > > function init() > message.setHandler("applyStatusEffect", function(_, _, effectConfig, duration, sourceEntityId) > status.addEphemeralEffect(effectConfig, duration, sourceEntityId) > end) > end > > function applyDamageRequest(damageRequest) > if world.getProperty("nonCombat") then > return {} > end > > local damage = 0 > if damageRequest.damageType == "Damage" or damageRequest.damageType == "Knockback" then > damage = damage + root.evalFunction2("protection", damageRequest.damage, status.stat("protection")) > elseif damageRequest.damageType == "IgnoresDef" then > damage = damage + damageRequest.damage > elseif damageRequest.damageType == "Status" then > -- only apply status effects > status.addEphemeralEffects(damageRequest.statusEffects, damageRequest.sourceEntityId) > return {} > elseif damageRequest.damageType == "Environment" then > return {} > end > > local healthLost = math.min(damage, status.resource("health")) > if healthLost > 0 and damageRequest.damageType ~= "Knockback" then > status.modifyResource("health", -healthLost) > self.damageFlashTime = 0.07 > end > > return {{ > sourceEntityId = damageRequest.sourceEntityId, > targetEntityId = entity.id(), > position = mcontroller.position(), > damageDealt = damage, > healthLost = healthLost, > hitType = damageRequest.hitType, > kind = "Normal", > damageSourceKind = damageRequest.damageSourceKind, > targetMaterialKind = status.statusProperty("targetMaterialKind"), > killed = not status.resourcePositive("health") > }} > end > > function update(dt) > if mcontroller.atWorldLimit() then > status.setResourcePercentage("health", 0) > end > end stats\monster_primary.lua 1,116c1,125 < require "/scripts/vec2.lua" < < function init() < self.damageFlashTime = 0 < < message.setHandler("applyStatusEffect", function(_, _, effectConfig, duration, sourceEntityId) < status.addEphemeralEffect(effectConfig, duration, sourceEntityId) < end) < end < < function applyDamageRequest(damageRequest) < if world.getProperty("nonCombat") then < return {} < end < < local damage = 0 < if damageRequest.damageType == "Damage" or damageRequest.damageType == "Knockback" then < damage = damage + root.evalFunction2("protection", damageRequest.damage, status.stat("protection")) < elseif damageRequest.damageType == "IgnoresDef" then < damage = damage + damageRequest.damage < elseif damageRequest.damageType == "Environment" then < return {} < end < < if status.resourcePositive("shieldHealth") then < local shieldAbsorb = math.min(damage, status.resource("shieldHealth")) < status.modifyResource("shieldHealth", -shieldAbsorb) < damage = damage - shieldAbsorb < end < < local hitType = damageRequest.hitType < local elementalStat = root.elementalResistance(damageRequest.damageSourceKind) < local resistance = status.stat(elementalStat) < damage = damage - (resistance * damage) < if resistance ~= 0 and damage > 0 then < hitType = resistance > 0 and "weakhit" or "stronghit" < end < < local healthLost = math.min(damage, status.resource("health")) < if healthLost > 0 and damageRequest.damageType ~= "Knockback" then < status.modifyResource("health", -healthLost) < if hitType == "stronghit" then < self.damageFlashTime = 0.07 < self.damageFlashType = "strong" < elseif hitType == "weakhit" then < self.damageFlashTime = 0.07 < self.damageFlashType = "weak" < else < self.damageFlashTime = 0.07 < self.damageFlashType = "default" < end < end < < status.addEphemeralEffects(damageRequest.statusEffects, damageRequest.sourceEntityId) < < local knockbackFactor = (1 - status.stat("grit")) < local momentum = knockbackMomentum(vec2.mul(damageRequest.knockbackMomentum, knockbackFactor)) < if status.resourcePositive("health") and vec2.mag(momentum) > 0 then < self.applyKnockback = momentum < if vec2.mag(momentum) > status.stat("knockbackThreshold") then < status.setResource("stunned", math.max(status.resource("stunned"), status.stat("knockbackStunTime"))) < end < end < < if not status.resourcePositive("health") then < hitType = "kill" < end < return {{ < sourceEntityId = damageRequest.sourceEntityId, < targetEntityId = entity.id(), < position = mcontroller.position(), < damageDealt = damage, < healthLost = healthLost, < hitType = hitType, < kind = "Normal", < damageSourceKind = damageRequest.damageSourceKind, < targetMaterialKind = status.statusProperty("targetMaterialKind") < }} < end < < function knockbackMomentum(momentum) < local knockback = vec2.mag(momentum) < if mcontroller.baseParameters().gravityEnabled and math.abs(momentum[1]) > 0 then < local dir = momentum[1] > 0 and 1 or -1 < return {dir * knockback / 1.41, knockback / 1.41} < else < return momentum < end < end < < function update(dt) < if self.damageFlashTime > 0 then < local color = status.statusProperty("damageFlashColor") or "ff0000=0.85" < if self.damageFlashType == "strong" then < color = status.statusProperty("strongDamageFlashColor") or "ffffff=1.0" or color < elseif self.damageFlashType == "weak" then < color = status.statusProperty("weakDamageFlashColor") or "000000=0.0" or color < end < status.setPrimaryDirectives(string.format("fade=%s", color)) < else < status.setPrimaryDirectives() < end < self.damageFlashTime = math.max(0, self.damageFlashTime - dt) < < if self.applyKnockback then < mcontroller.setVelocity({0,0}) < if vec2.mag(self.applyKnockback) > status.stat("knockbackThreshold") then < mcontroller.addMomentum(self.applyKnockback) < end < self.applyKnockback = nil < end < < if mcontroller.atWorldLimit(true) then < status.setResourcePercentage("health", 0) < end < end --- > require "/scripts/vec2.lua" > > function init() > self.damageFlashTime = 0 > > message.setHandler("applyStatusEffect", function(_, _, effectConfig, duration, sourceEntityId) > status.addEphemeralEffect(effectConfig, duration, sourceEntityId) > end) > end > > function applyDamageRequest(damageRequest) > if world.getProperty("nonCombat") then > return {} > end > > -- don't get hit by knockback attacks if immune to knockback > if damageRequest.damageType == "Knockback" and status.stat("grit") >= 1 then > return {} > end > > local damage = 0 > if damageRequest.damageType == "Damage" or damageRequest.damageType == "Knockback" then > damage = damage + root.evalFunction2("protection", damageRequest.damage, status.stat("protection")) > elseif damageRequest.damageType == "IgnoresDef" then > damage = damage + damageRequest.damage > elseif damageRequest.damageType == "Status" then > -- only apply status effects > status.addEphemeralEffects(damageRequest.statusEffects, damageRequest.sourceEntityId) > return {} > elseif damageRequest.damageType == "Environment" then > return {} > end > > if status.resourcePositive("shieldHealth") then > local shieldAbsorb = math.min(damage, status.resource("shieldHealth")) > status.modifyResource("shieldHealth", -shieldAbsorb) > damage = damage - shieldAbsorb > end > > local hitType = damageRequest.hitType > local elementalStat = root.elementalResistance(damageRequest.damageSourceKind) > local resistance = status.stat(elementalStat) > damage = damage - (resistance * damage) > if resistance ~= 0 and damage > 0 then > hitType = resistance > 0 and "weakhit" or "stronghit" > end > > local healthLost = math.min(damage, status.resource("health")) > if healthLost > 0 and damageRequest.damageType ~= "Knockback" then > status.modifyResource("health", -healthLost) > if hitType == "stronghit" then > self.damageFlashTime = 0.07 > self.damageFlashType = "strong" > elseif hitType == "weakhit" then > self.damageFlashTime = 0.07 > self.damageFlashType = "weak" > else > self.damageFlashTime = 0.07 > self.damageFlashType = "default" > end > end > > status.addEphemeralEffects(damageRequest.statusEffects, damageRequest.sourceEntityId) > > local knockbackFactor = (1 - status.stat("grit")) > local momentum = knockbackMomentum(vec2.mul(damageRequest.knockbackMomentum, knockbackFactor)) > if status.resourcePositive("health") and vec2.mag(momentum) > 0 then > self.applyKnockback = momentum > if vec2.mag(momentum) > status.stat("knockbackThreshold") then > status.setResource("stunned", math.max(status.resource("stunned"), status.stat("knockbackStunTime"))) > end > end > > if not status.resourcePositive("health") then > hitType = "kill" > end > return {{ > sourceEntityId = damageRequest.sourceEntityId, > targetEntityId = entity.id(), > position = mcontroller.position(), > damageDealt = damage, > healthLost = healthLost, > hitType = hitType, > kind = "Normal", > damageSourceKind = damageRequest.damageSourceKind, > targetMaterialKind = status.statusProperty("targetMaterialKind") > }} > end > > function knockbackMomentum(momentum) > local knockback = vec2.mag(momentum) > if mcontroller.baseParameters().gravityEnabled and math.abs(momentum[1]) > 0 then > local dir = momentum[1] > 0 and 1 or -1 > return {dir * knockback / 1.41, knockback / 1.41} > else > return momentum > end > end > > function update(dt) > if self.damageFlashTime > 0 then > local color = status.statusProperty("damageFlashColor") or "ff0000=0.85" > if self.damageFlashType == "strong" then > color = status.statusProperty("strongDamageFlashColor") or "ffffff=1.0" or color > elseif self.damageFlashType == "weak" then > color = status.statusProperty("weakDamageFlashColor") or "000000=0.0" or color > end > status.setPrimaryDirectives(string.format("fade=%s", color)) > else > status.setPrimaryDirectives() > end > self.damageFlashTime = math.max(0, self.damageFlashTime - dt) > > if self.applyKnockback then > mcontroller.setVelocity({0,0}) > if vec2.mag(self.applyKnockback) > status.stat("knockbackThreshold") then > mcontroller.addMomentum(self.applyKnockback) > end > self.applyKnockback = nil > end > > if mcontroller.atWorldLimit(true) then > status.setResourcePercentage("health", 0) > end > end stats\npc_primary.lua 1,152c1,156 < function init() < self.damageFlashTime = 0 < self.hitInvulnerabilityTime = 0 < < message.setHandler("applyStatusEffect", function(_, _, effectConfig, duration, sourceEntityId) < status.addEphemeralEffect(effectConfig, duration, sourceEntityId) < end) < end < < function applyDamageRequest(damageRequest) < if self.hitInvulnerabilityTime > 0 or world.getProperty("nonCombat") then < return {} < end < < local damage = 0 < if damageRequest.damageType == "Damage" or damageRequest.damageType == "Knockback" then < damage = damage + root.evalFunction2("protection", damageRequest.damage, status.stat("protection")) < elseif damageRequest.damageType == "IgnoresDef" then < damage = damage + damageRequest.damage < elseif damageRequest.damageType == "Environment" then < return {} < end < < if damageRequest.hitType == "ShieldHit" and status.statPositive("shieldHealth") and status.resourcePositive("shieldStamina") then < status.modifyResource("shieldStamina", -damage / status.stat("shieldHealth")) < status.setResourcePercentage("shieldStaminaRegenBlock", 1.0) < damage = 0 < damageRequest.statusEffects = {} < damageRequest.damageSourceKind = "shield" < end < < local healthLost = math.min(damage, status.resource("health")) < if healthLost > 0 and damageRequest.damageType ~= "Knockback" then < status.modifyResource("health", -healthLost) < self.damageFlashTime = 0.07 < if status.statusProperty("hitInvulnerability") then < local damageHealthPercentage = healthLost / status.resourceMax("health") < if damageHealthPercentage > status.statusProperty("hitInvulnerabilityThreshold") then < self.hitInvulnerabilityTime = status.statusProperty("hitInvulnerabilityTime") < end < end < end < < status.addEphemeralEffects(damageRequest.statusEffects, damageRequest.sourceEntityId) < < local knockbackFactor = (1 - status.stat("grit")) < local momentum = knockbackMomentum(vec2.mul(damageRequest.knockbackMomentum, knockbackFactor)) < if status.resourcePositive("health") and vec2.mag(momentum) > 0 then < mcontroller.setVelocity({0,0}) < if vec2.mag(momentum) > status.stat("knockbackThreshold") then < mcontroller.addMomentum(momentum) < status.setResource("stunned", math.max(status.resource("stunned"), status.stat("knockbackStunTime"))) < end < end < < local hitType = damageRequest.hitType < if not status.resourcePositive("health") then < hitType = "kill" < end < return {{ < sourceEntityId = damageRequest.sourceEntityId, < targetEntityId = entity.id(), < position = mcontroller.position(), < damageDealt = damage, < healthLost = healthLost, < hitType = hitType, < kind = "Normal", < damageSourceKind = damageRequest.damageSourceKind, < targetMaterialKind = status.statusProperty("targetMaterialKind") < }} < end < < function notifyResourceConsumed(resourceName, amount) < if resourceName == "energy" and amount > 0 then < status.setResourcePercentage("energyRegenBlock", 1.0) < end < end < < function knockbackMomentum(momentum) < local knockback = vec2.mag(momentum) < if mcontroller.baseParameters().gravityEnabled and math.abs(momentum[1]) > 0 then < local dir = momentum[1] > 0 and 1 or -1 < return {dir * knockback / 1.41, knockback / 1.41} < else < return momentum < end < end < < function update(dt) < if self.damageFlashTime > 0 then < status.setPrimaryDirectives("fade=ff0000=0.85") < else < status.setPrimaryDirectives() < end < self.damageFlashTime = math.max(0, self.damageFlashTime - dt) < < if status.statusProperty("hitInvulnerability") then < self.hitInvulnerabilityTime = math.max(self.hitInvulnerabilityTime - dt, 0) < local flashTime = status.statusProperty("hitInvulnerabilityFlash") < < if self.hitInvulnerabilityTime > 0 then < if math.fmod(self.hitInvulnerabilityTime, flashTime) > flashTime / 2 then < status.setPrimaryDirectives(status.statusProperty("damageFlashOffDirectives")) < else < status.setPrimaryDirectives(status.statusProperty("damageFlashOnDirectives")) < end < else < status.setPrimaryDirectives() < end < end < < if status.resource("energy") == 0 then < status.setResourceLocked("energy", true) < elseif status.resourcePercentage("energy") == 1 then < status.setResourceLocked("energy", false) < end < < if not status.resourcePositive("energyRegenBlock") then < status.modifyResourcePercentage("energy", status.stat("energyRegenPercentageRate") * dt) < end < < if not status.resourcePositive("shieldStaminaRegenBlock") then < status.modifyResourcePercentage("shieldStamina", status.stat("shieldStaminaRegen") * dt) < end < < if mcontroller.atWorldLimit(true) then < status.setResourcePercentage("health", 0) < end < < -- drawDebugResources() < end < < function drawDebugResources() < local position = mcontroller.position() < < local y = 2 < local resourceName = "energy" < --Border < world.debugLine(vec2.add(position, {-2, y+0.125}), vec2.add(position, {-2, y + 0.75}), "black") < world.debugLine(vec2.add(position, {-2, y + 0.75}), vec2.add(position, {2, y + 0.75}), "black") < world.debugLine(vec2.add(position, {2, y + 0.75}), vec2.add(position, {2, y+0.125}), "black") < world.debugLine(vec2.add(position, {2, y+0.125}), vec2.add(position, {-2, y+0.125}), "black") < < local width = 3.75 * status.resource(resourceName) / status.resourceMax(resourceName) < world.debugLine(vec2.add(position, {-1.875, y + 0.25}), vec2.add(position, {-1.875 + width, y + 0.25}), "green") < world.debugLine(vec2.add(position, {-1.875, y + 0.375}), vec2.add(position, {-1.875 + width, y + 0.375}), "green") < world.debugLine(vec2.add(position, {-1.875, y + 0.5}), vec2.add(position, {-1.875 + width, y + 0.5}), "green") < world.debugLine(vec2.add(position, {-1.875, y + 0.625}), vec2.add(position, {-1.875 + width, y + 0.625}), "green") < < world.debugText(resourceName, vec2.add(position, {2.25, y - 0.125}), "blue") < y = y + 1 < end --- > function init() > self.damageFlashTime = 0 > self.hitInvulnerabilityTime = 0 > > message.setHandler("applyStatusEffect", function(_, _, effectConfig, duration, sourceEntityId) > status.addEphemeralEffect(effectConfig, duration, sourceEntityId) > end) > end > > function applyDamageRequest(damageRequest) > if self.hitInvulnerabilityTime > 0 or world.getProperty("nonCombat") then > return {} > end > > local damage = 0 > if damageRequest.damageType == "Damage" or damageRequest.damageType == "Knockback" then > damage = damage + root.evalFunction2("protection", damageRequest.damage, status.stat("protection")) > elseif damageRequest.damageType == "IgnoresDef" then > damage = damage + damageRequest.damage > elseif damageRequest.damageType == "Status" then > -- only apply status effects > status.addEphemeralEffects(damageRequest.statusEffects, damageRequest.sourceEntityId) > return {} > elseif damageRequest.damageType == "Environment" then > return {} > end > > if damageRequest.hitType == "ShieldHit" and status.statPositive("shieldHealth") and status.resourcePositive("shieldStamina") then > status.modifyResource("shieldStamina", -damage / status.stat("shieldHealth")) > status.setResourcePercentage("shieldStaminaRegenBlock", 1.0) > damage = 0 > damageRequest.statusEffects = {} > damageRequest.damageSourceKind = "shield" > end > > local healthLost = math.min(damage, status.resource("health")) > if healthLost > 0 and damageRequest.damageType ~= "Knockback" then > status.modifyResource("health", -healthLost) > self.damageFlashTime = 0.07 > if status.statusProperty("hitInvulnerability") then > local damageHealthPercentage = healthLost / status.resourceMax("health") > if damageHealthPercentage > status.statusProperty("hitInvulnerabilityThreshold") then > self.hitInvulnerabilityTime = status.statusProperty("hitInvulnerabilityTime") > end > end > end > > status.addEphemeralEffects(damageRequest.statusEffects, damageRequest.sourceEntityId) > > local knockbackFactor = (1 - status.stat("grit")) > local momentum = knockbackMomentum(vec2.mul(damageRequest.knockbackMomentum, knockbackFactor)) > if status.resourcePositive("health") and vec2.mag(momentum) > 0 then > mcontroller.setVelocity({0,0}) > if vec2.mag(momentum) > status.stat("knockbackThreshold") then > mcontroller.addMomentum(momentum) > status.setResource("stunned", math.max(status.resource("stunned"), status.stat("knockbackStunTime"))) > end > end > > local hitType = damageRequest.hitType > if not status.resourcePositive("health") then > hitType = "kill" > end > return {{ > sourceEntityId = damageRequest.sourceEntityId, > targetEntityId = entity.id(), > position = mcontroller.position(), > damageDealt = damage, > healthLost = healthLost, > hitType = hitType, > kind = "Normal", > damageSourceKind = damageRequest.damageSourceKind, > targetMaterialKind = status.statusProperty("targetMaterialKind") > }} > end > > function notifyResourceConsumed(resourceName, amount) > if resourceName == "energy" and amount > 0 then > status.setResourcePercentage("energyRegenBlock", 1.0) > end > end > > function knockbackMomentum(momentum) > local knockback = vec2.mag(momentum) > if mcontroller.baseParameters().gravityEnabled and math.abs(momentum[1]) > 0 then > local dir = momentum[1] > 0 and 1 or -1 > return {dir * knockback / 1.41, knockback / 1.41} > else > return momentum > end > end > > function update(dt) > if self.damageFlashTime > 0 then > status.setPrimaryDirectives("fade=ff0000=0.85") > else > status.setPrimaryDirectives() > end > self.damageFlashTime = math.max(0, self.damageFlashTime - dt) > > if status.statusProperty("hitInvulnerability") then > self.hitInvulnerabilityTime = math.max(self.hitInvulnerabilityTime - dt, 0) > local flashTime = status.statusProperty("hitInvulnerabilityFlash") > > if self.hitInvulnerabilityTime > 0 then > if math.fmod(self.hitInvulnerabilityTime, flashTime) > flashTime / 2 then > status.setPrimaryDirectives(status.statusProperty("damageFlashOffDirectives")) > else > status.setPrimaryDirectives(status.statusProperty("damageFlashOnDirectives")) > end > else > status.setPrimaryDirectives() > end > end > > if status.resource("energy") == 0 then > status.setResourceLocked("energy", true) > elseif status.resourcePercentage("energy") == 1 then > status.setResourceLocked("energy", false) > end > > if not status.resourcePositive("energyRegenBlock") then > status.modifyResourcePercentage("energy", status.stat("energyRegenPercentageRate") * dt) > end > > if not status.resourcePositive("shieldStaminaRegenBlock") then > status.modifyResourcePercentage("shieldStamina", status.stat("shieldStaminaRegen") * dt) > end > > if mcontroller.atWorldLimit(true) then > status.setResourcePercentage("health", 0) > end > > -- drawDebugResources() > end > > function drawDebugResources() > local position = mcontroller.position() > > local y = 2 > local resourceName = "energy" > --Border > world.debugLine(vec2.add(position, {-2, y+0.125}), vec2.add(position, {-2, y + 0.75}), "black") > world.debugLine(vec2.add(position, {-2, y + 0.75}), vec2.add(position, {2, y + 0.75}), "black") > world.debugLine(vec2.add(position, {2, y + 0.75}), vec2.add(position, {2, y+0.125}), "black") > world.debugLine(vec2.add(position, {2, y+0.125}), vec2.add(position, {-2, y+0.125}), "black") > > local width = 3.75 * status.resource(resourceName) / status.resourceMax(resourceName) > world.debugLine(vec2.add(position, {-1.875, y + 0.25}), vec2.add(position, {-1.875 + width, y + 0.25}), "green") > world.debugLine(vec2.add(position, {-1.875, y + 0.375}), vec2.add(position, {-1.875 + width, y + 0.375}), "green") > world.debugLine(vec2.add(position, {-1.875, y + 0.5}), vec2.add(position, {-1.875 + width, y + 0.5}), "green") > world.debugLine(vec2.add(position, {-1.875, y + 0.625}), vec2.add(position, {-1.875 + width, y + 0.625}), "green") > > world.debugText(resourceName, vec2.add(position, {2.25, y - 0.125}), "blue") > y = y + 1 > end stats\player_primary.lua 1,243c1,253 < require "/scripts/status.lua" < require "/scripts/achievements.lua" < < function init() < self.lastYPosition = 0 < self.lastYVelocity = 0 < self.fallDistance = 0 < self.hitInvulnerabilityTime = 0 < self.shieldHitInvulnerabilityTime = 0 < self.suffocateSoundTimer = 0 < < local ouchNoise = status.statusProperty("ouchNoise") < if ouchNoise then < animator.setSoundPool("ouch", {ouchNoise}) < end < < self.inflictedDamage = damageListener("inflictedDamage", inflictedDamageCallback) < < message.setHandler("applyStatusEffect", function(_, _, effectConfig, duration, sourceEntityId) < status.addEphemeralEffect(effectConfig, duration, sourceEntityId) < end) < end < < function inflictedDamageCallback(notifications) < for _,notification in ipairs(notifications) do < if notification.hitType == "Kill" then < if world.entityExists(notification.targetEntityId) then < local entityType = world.entityType(notification.targetEntityId) < local eventFields = entityEventFields(notification.targetEntityId) < util.mergeTable(eventFields, worldEventFields()) < eventFields.damageSourceKind = notification.damageSourceKind < < if entityType == "object" then < recordEvent(entity.id(), "killObject", eventFields) < < elseif entityType == "npc" or entityType == "monster" or entityType == "player" then < recordEvent(entity.id(), "kill", eventFields) < end < else < -- TODO: better method for getting data on killed entities < sb.logInfo("Skipped event recording for nonexistent entity %s", notification.targetEntityId) < end < end < end < end < < function applyDamageRequest(damageRequest) < if world.getProperty("invinciblePlayers") then < return {} < end < < local hitInvulnerability = self.hitInvulnerabilityTime > 0 and damageRequest.damageSourceKind ~= "applystatus" < if damageRequest.damageSourceKind ~= "falling" and (hitInvulnerability or world.getProperty("nonCombat")) then < return {} < end < < status.addEphemeralEffects(damageRequest.statusEffects, damageRequest.sourceEntityId) < if damageRequest.damageSourceKind == "applystatus" then < return {} < end < < local damage = 0 < if damageRequest.damageType == "Damage" or damageRequest.damageType == "Knockback" then < damage = damage + root.evalFunction2("protection", damageRequest.damage, status.stat("protection")) < elseif damageRequest.damageType == "IgnoresDef" or damageRequest.damageType == "Environment" then < damage = damage + damageRequest.damage < end < < if status.resourcePositive("damageAbsorption") then < local damageAbsorb = math.min(damage, status.resource("damageAbsorption")) < status.modifyResource("damageAbsorption", -damageAbsorb) < damage = damage - damageAbsorb < end < < if damageRequest.hitType == "ShieldHit" then < if self.shieldHitInvulnerabilityTime == 0 then < local preShieldDamageHealthPercentage = damage / status.resourceMax("health") < self.shieldHitInvulnerabilityTime = status.statusProperty("shieldHitInvulnerabilityTime") * math.min(preShieldDamageHealthPercentage, 1.0) < < if not status.resourcePositive("perfectBlock") then < status.modifyResource("shieldStamina", -damage / status.stat("shieldHealth")) < end < end < < status.setResourcePercentage("shieldStaminaRegenBlock", 1.0) < damage = 0 < damageRequest.statusEffects = {} < damageRequest.damageSourceKind = "shield" < end < < local elementalStat = root.elementalResistance(damageRequest.damageSourceKind) < local resistance = status.stat(elementalStat) < damage = damage - (resistance * damage) < < local healthLost = math.min(damage, status.resource("health")) < if healthLost > 0 and damageRequest.damageType ~= "Knockback" then < status.modifyResource("health", -healthLost) < animator.playSound("ouch") < < local damageHealthPercentage = damage / status.resourceMax("health") < if damageHealthPercentage > status.statusProperty("hitInvulnerabilityThreshold") then < self.hitInvulnerabilityTime = status.statusProperty("hitInvulnerabilityTime") < end < end < < local knockbackFactor = (1 - status.stat("grit")) < < local knockbackMomentum = vec2.mul(damageRequest.knockbackMomentum, knockbackFactor) < local knockback = vec2.mag(knockbackMomentum) < if knockback > status.stat("knockbackThreshold") then < mcontroller.setVelocity({0,0}) < local dir = knockbackMomentum[1] > 0 and 1 or -1 < mcontroller.addMomentum({dir * knockback / 1.41, knockback / 1.41}) < end < < local hitType = damageRequest.hitType < if not status.resourcePositive("health") then < hitType = "kill" < end < return {{ < sourceEntityId = damageRequest.sourceEntityId, < targetEntityId = entity.id(), < position = mcontroller.position(), < damageDealt = damage, < healthLost = healthLost, < hitType = hitType, < damageSourceKind = damageRequest.damageSourceKind, < targetMaterialKind = status.statusProperty("targetMaterialKind") < }} < end < < function notifyResourceConsumed(resourceName, amount) < if resourceName == "energy" and amount > 0 then < status.setResourcePercentage("energyRegenBlock", 1.0) < end < end < < function update(dt) < local minimumFallDistance = 14 < local fallDistanceDamageFactor = 3 < local minimumFallVel = 40 < local baseGravity = 80 < local gravityDiffFactor = 1 / 30.0 < < local curYPosition = mcontroller.yPosition() < local yPosChange = curYPosition - (self.lastYPosition or curYPosition) < < if self.fallDistance > minimumFallDistance and -self.lastYVelocity > minimumFallVel and mcontroller.onGround() then < local damage = (self.fallDistance - minimumFallDistance) * fallDistanceDamageFactor < damage = damage * (1.0 + (world.gravity(mcontroller.position()) - baseGravity) * gravityDiffFactor) < damage = damage * status.stat("fallDamageMultiplier") < status.applySelfDamageRequest({ < damageType = "IgnoresDef", < damage = damage, < damageSourceKind = "falling", < sourceEntityId = entity.id() < }) < end < < if mcontroller.yVelocity() < -minimumFallVel and not mcontroller.onGround() then < self.fallDistance = self.fallDistance + -yPosChange < else < self.fallDistance = 0 < end < < self.lastYPosition = curYPosition < self.lastYVelocity = mcontroller.yVelocity() < < local mouthPosition = vec2.add(mcontroller.position(), status.statusProperty("mouthPosition")) < if status.statPositive("breathProtection") or world.breathable(mouthPosition) then < status.modifyResource("breath", status.stat("breathRegenerationRate") * dt) < else < status.modifyResource("breath", -status.stat("breathDepletionRate") * dt) < end < < if not status.resourcePositive("breath") then < self.suffocateSoundTimer = self.suffocateSoundTimer - dt < if self.suffocateSoundTimer <= 0 then < self.suffocateSoundTimer = 0.5 + (0.5 * status.resourcePercentage("health")) < animator.playSound("suffocate") < end < status.modifyResourcePercentage("health", -status.statusProperty("breathHealthPenaltyPercentageRate") * dt) < else < self.suffocateSoundTimer = 0 < end < < self.hitInvulnerabilityTime = math.max(self.hitInvulnerabilityTime - dt, 0) < local flashTime = status.statusProperty("hitInvulnerabilityFlash") < < if self.hitInvulnerabilityTime > 0 then < if math.fmod(self.hitInvulnerabilityTime, flashTime) > flashTime / 2 then < status.setPrimaryDirectives(status.statusProperty("damageFlashOffDirectives")) < else < status.setPrimaryDirectives(status.statusProperty("damageFlashOnDirectives")) < end < else < status.setPrimaryDirectives() < end < < if status.resourceLocked("energy") and status.resourcePercentage("energy") == 1 then < animator.playSound("energyRegenDone") < end < < if status.resource("energy") == 0 then < if not status.resourceLocked("energy") then < animator.playSound("outOfEnergy") < animator.burstParticleEmitter("outOfEnergy") < end < < status.setResourceLocked("energy", true) < elseif status.resourcePercentage("energy") == 1 then < status.setResourceLocked("energy", false) < end < < if not status.resourcePositive("energyRegenBlock") then < status.modifyResourcePercentage("energy", status.stat("energyRegenPercentageRate") * dt) < end < < self.shieldHitInvulnerabilityTime = math.max(self.shieldHitInvulnerabilityTime - dt, 0) < if not status.resourcePositive("shieldStaminaRegenBlock") then < status.modifyResourcePercentage("shieldStamina", status.stat("shieldStaminaRegen") * dt) < status.modifyResourcePercentage("perfectBlockLimit", status.stat("perfectBlockLimitRegen") * dt) < end < < self.inflictedDamage:update() < < if mcontroller.atWorldLimit(true) then < status.setResourcePercentage("health", 0) < end < end < < function overheadBars() < local bars = {} < < if status.statPositive("shieldHealth") then < table.insert(bars, { < percentage = status.resource("shieldStamina"), < color = status.resourcePositive("perfectBlock") and {255, 255, 200, 255} or {200, 200, 0, 255} < }) < end < < return bars < end --- > require "/scripts/status.lua" > require "/scripts/achievements.lua" > > function init() > self.lastYPosition = 0 > self.lastYVelocity = 0 > self.fallDistance = 0 > self.hitInvulnerabilityTime = 0 > self.shieldHitInvulnerabilityTime = 0 > self.suffocateSoundTimer = 0 > self.ouchCooldown = 0 > > local ouchNoise = status.statusProperty("ouchNoise") > if ouchNoise then > animator.setSoundPool("ouch", {ouchNoise}) > end > > self.inflictedDamage = damageListener("inflictedDamage", inflictedDamageCallback) > > message.setHandler("applyStatusEffect", function(_, _, effectConfig, duration, sourceEntityId) > status.addEphemeralEffect(effectConfig, duration, sourceEntityId) > end) > end > > function inflictedDamageCallback(notifications) > for _,notification in ipairs(notifications) do > if notification.hitType == "Kill" then > if world.entityExists(notification.targetEntityId) then > local entityType = world.entityType(notification.targetEntityId) > local eventFields = entityEventFields(notification.targetEntityId) > util.mergeTable(eventFields, worldEventFields()) > eventFields.damageSourceKind = notification.damageSourceKind > > if entityType == "object" then > recordEvent(entity.id(), "killObject", eventFields) > > elseif entityType == "npc" or entityType == "monster" or entityType == "player" then > recordEvent(entity.id(), "kill", eventFields) > end > else > -- TODO: better method for getting data on killed entities > sb.logInfo("Skipped event recording for nonexistent entity %s", notification.targetEntityId) > end > end > end > end > > function applyDamageRequest(damageRequest) > if world.getProperty("invinciblePlayers") then > return {} > end > > local hitInvulnerability = self.hitInvulnerabilityTime > 0 and damageRequest.damageSourceKind ~= "applystatus" > if damageRequest.damageSourceKind ~= "falling" and (hitInvulnerability or world.getProperty("nonCombat")) then > return {} > end > > status.addEphemeralEffects(damageRequest.statusEffects, damageRequest.sourceEntityId) > if damageRequest.damageSourceKind == "applystatus" then > return {} > end > > local damage = 0 > if damageRequest.damageType == "Damage" or damageRequest.damageType == "Knockback" then > damage = damage + root.evalFunction2("protection", damageRequest.damage, status.stat("protection")) > elseif damageRequest.damageType == "IgnoresDef" or damageRequest.damageType == "Environment" then > damage = damage + damageRequest.damage > elseif damageRequest.damageType == "Status" then > -- only apply status effects > status.addEphemeralEffects(damageRequest.statusEffects, damageRequest.sourceEntityId) > return {} > end > > if status.resourcePositive("damageAbsorption") then > local damageAbsorb = math.min(damage, status.resource("damageAbsorption")) > status.modifyResource("damageAbsorption", -damageAbsorb) > damage = damage - damageAbsorb > end > > if damageRequest.hitType == "ShieldHit" then > if self.shieldHitInvulnerabilityTime == 0 then > local preShieldDamageHealthPercentage = damage / status.resourceMax("health") > self.shieldHitInvulnerabilityTime = status.statusProperty("shieldHitInvulnerabilityTime") * math.min(preShieldDamageHealthPercentage, 1.0) > > if not status.resourcePositive("perfectBlock") then > status.modifyResource("shieldStamina", -damage / status.stat("shieldHealth")) > end > end > > status.setResourcePercentage("shieldStaminaRegenBlock", 1.0) > damage = 0 > damageRequest.statusEffects = {} > damageRequest.damageSourceKind = "shield" > end > > local elementalStat = root.elementalResistance(damageRequest.damageSourceKind) > local resistance = status.stat(elementalStat) > damage = damage - (resistance * damage) > > local healthLost = math.min(damage, status.resource("health")) > if healthLost > 0 and damageRequest.damageType ~= "Knockback" then > status.modifyResource("health", -healthLost) > if self.ouchCooldown <= 0 then > animator.playSound("ouch") > self.ouchCooldown = 0.5 > end > > local damageHealthPercentage = damage / status.resourceMax("health") > if damageHealthPercentage > status.statusProperty("hitInvulnerabilityThreshold") then > self.hitInvulnerabilityTime = status.statusProperty("hitInvulnerabilityTime") > end > end > > local knockbackFactor = (1 - status.stat("grit")) > > local knockbackMomentum = vec2.mul(damageRequest.knockbackMomentum, knockbackFactor) > local knockback = vec2.mag(knockbackMomentum) > if knockback > status.stat("knockbackThreshold") then > mcontroller.setVelocity({0,0}) > local dir = knockbackMomentum[1] > 0 and 1 or -1 > mcontroller.addMomentum({dir * knockback / 1.41, knockback / 1.41}) > end > > local hitType = damageRequest.hitType > if not status.resourcePositive("health") then > hitType = "kill" > end > return {{ > sourceEntityId = damageRequest.sourceEntityId, > targetEntityId = entity.id(), > position = mcontroller.position(), > damageDealt = damage, > healthLost = healthLost, > hitType = hitType, > damageSourceKind = damageRequest.damageSourceKind, > targetMaterialKind = status.statusProperty("targetMaterialKind") > }} > end > > function notifyResourceConsumed(resourceName, amount) > if resourceName == "energy" and amount > 0 then > status.setResourcePercentage("energyRegenBlock", 1.0) > end > end > > function update(dt) > local minimumFallDistance = 14 > local fallDistanceDamageFactor = 3 > local minimumFallVel = 40 > local baseGravity = 80 > local gravityDiffFactor = 1 / 30.0 > > local curYPosition = mcontroller.yPosition() > local yPosChange = curYPosition - (self.lastYPosition or curYPosition) > > self.ouchCooldown = math.max(0.0, self.ouchCooldown - dt) > > if self.fallDistance > minimumFallDistance and -self.lastYVelocity > minimumFallVel and mcontroller.onGround() then > local damage = (self.fallDistance - minimumFallDistance) * fallDistanceDamageFactor > damage = damage * (1.0 + (world.gravity(mcontroller.position()) - baseGravity) * gravityDiffFactor) > damage = damage * status.stat("fallDamageMultiplier") > status.applySelfDamageRequest({ > damageType = "IgnoresDef", > damage = damage, > damageSourceKind = "falling", > sourceEntityId = entity.id() > }) > end > > if mcontroller.yVelocity() < -minimumFallVel and not mcontroller.onGround() then > self.fallDistance = self.fallDistance + -yPosChange > else > self.fallDistance = 0 > end > > self.lastYPosition = curYPosition > self.lastYVelocity = mcontroller.yVelocity() > > local mouthPosition = vec2.add(mcontroller.position(), status.statusProperty("mouthPosition")) > if status.statPositive("breathProtection") or world.breathable(mouthPosition) then > status.modifyResource("breath", status.stat("breathRegenerationRate") * dt) > else > status.modifyResource("breath", -status.stat("breathDepletionRate") * dt) > end > > if not status.resourcePositive("breath") then > self.suffocateSoundTimer = self.suffocateSoundTimer - dt > if self.suffocateSoundTimer <= 0 then > self.suffocateSoundTimer = 0.5 + (0.5 * status.resourcePercentage("health")) > animator.playSound("suffocate") > end > status.modifyResourcePercentage("health", -status.statusProperty("breathHealthPenaltyPercentageRate") * dt) > else > self.suffocateSoundTimer = 0 > end > > self.hitInvulnerabilityTime = math.max(self.hitInvulnerabilityTime - dt, 0) > local flashTime = status.statusProperty("hitInvulnerabilityFlash") > > if self.hitInvulnerabilityTime > 0 then > if math.fmod(self.hitInvulnerabilityTime, flashTime) > flashTime / 2 then > status.setPrimaryDirectives(status.statusProperty("damageFlashOffDirectives")) > else > status.setPrimaryDirectives(status.statusProperty("damageFlashOnDirectives")) > end > else > status.setPrimaryDirectives() > end > > if status.resourceLocked("energy") and status.resourcePercentage("energy") == 1 then > animator.playSound("energyRegenDone") > end > > if status.resource("energy") == 0 then > if not status.resourceLocked("energy") then > animator.playSound("outOfEnergy") > animator.burstParticleEmitter("outOfEnergy") > end > > status.setResourceLocked("energy", true) > elseif status.resourcePercentage("energy") == 1 then > status.setResourceLocked("energy", false) > end > > if not status.resourcePositive("energyRegenBlock") then > status.modifyResourcePercentage("energy", status.stat("energyRegenPercentageRate") * dt) > end > > self.shieldHitInvulnerabilityTime = math.max(self.shieldHitInvulnerabilityTime - dt, 0) > if not status.resourcePositive("shieldStaminaRegenBlock") then > status.modifyResourcePercentage("shieldStamina", status.stat("shieldStaminaRegen") * dt) > status.modifyResourcePercentage("perfectBlockLimit", status.stat("perfectBlockLimitRegen") * dt) > end > > self.inflictedDamage:update() > > if mcontroller.atWorldLimit(true) then > status.setResourcePercentage("health", 0) > end > end > > function overheadBars() > local bars = {} > > if status.statPositive("shieldHealth") then > table.insert(bars, { > percentage = status.resource("shieldStamina"), > color = status.resourcePositive("perfectBlock") and {255, 255, 200, 255} or {200, 200, 0, 255} > }) > end > > return bars > end stats\spacemonster_primary.lua 1,139c1,143 < require "/scripts/vec2.lua" < require "/scripts/util.lua" < require "/scripts/status.lua" < < function init() < self.damageFlashTime = 0 < < message.setHandler("applyStatusEffect", function(_, _, effectConfig, duration, sourceEntityId) < status.addEphemeralEffect(effectConfig, duration, sourceEntityId) < end) < < local reboundFactor = status.statusProperty("onHitReboundFactor", 0.65) < local minReboundSpeed = status.statusProperty("onHitMinReboundSpeed", 13) < < self.damageListener = damageListener("inflictedHits", function(notifications) < for _, notification in ipairs(notifications) do < if notification.damageSourceKind == "impact" then < local entityVelocity = world.entityVelocity(notification.targetEntityId) < local entityPosition = world.entityPosition(notification.targetEntityId) < if entityVelocity and entityPosition then < local relativeVelocity = vec2.sub(vec2.mul(entityVelocity, 0.85), mcontroller.velocity()) < local relativePosition = world.distance(mcontroller.position(), entityPosition) < local angleDiff = util.angleDiff(vec2.angle(relativeVelocity), vec2.angle(relativePosition)) < if math.abs(angleDiff) < math.pi / 2 then < local reboundSpeed = math.max(minReboundSpeed, vec2.mag(relativeVelocity) * reboundFactor) < local bounceVelocity = vec2.add(relativeVelocity, vec2.withAngle(vec2.angle(relativePosition), reboundSpeed)) < mcontroller.setVelocity(vec2.add(mcontroller.velocity(), bounceVelocity)) < end < end < end < end < end) < end < < function applyDamageRequest(damageRequest) < if world.getProperty("nonCombat") then < return {} < end < < local damage = 0 < if damageRequest.damageType == "Damage" or damageRequest.damageType == "Knockback" then < damage = damage + root.evalFunction2("protection", damageRequest.damage, status.stat("protection")) < elseif damageRequest.damageType == "IgnoresDef" then < damage = damage + damageRequest.damage < elseif damageRequest.damageType == "Environment" then < return {} < end < < if status.resourcePositive("shieldHealth") then < local shieldAbsorb = math.min(damage, status.resource("shieldHealth")) < status.modifyResource("shieldHealth", -shieldAbsorb) < damage = damage - shieldAbsorb < end < < local hitType = damageRequest.hitType < local elementalStat = root.elementalResistance(damageRequest.damageSourceKind) < local resistance = status.stat(elementalStat) < damage = damage - (resistance * damage) < if resistance ~= 0 and damage > 0 then < hitType = resistance > 0 and "weakhit" or "stronghit" < end < < local healthLost = math.min(damage, status.resource("health")) < if healthLost > 0 and damageRequest.damageType ~= "Knockback" then < status.modifyResource("health", -healthLost) < if hitType == "stronghit" then < self.damageFlashTime = 0.07 < self.damageFlashType = "strong" < elseif hitType == "weakhit" then < self.damageFlashTime = 0.07 < self.damageFlashType = "weak" < else < self.damageFlashTime = 0.07 < self.damageFlashType = "default" < end < end < < status.addEphemeralEffects(damageRequest.statusEffects, damageRequest.sourceEntityId) < < local knockbackFactor = (1 - status.stat("grit")) < local momentum = knockbackMomentum(vec2.mul(damageRequest.knockbackMomentum, knockbackFactor)) < if status.resourcePositive("health") and vec2.mag(momentum) > 0 then < self.applyKnockback = momentum < if vec2.mag(momentum) > status.stat("knockbackThreshold") then < status.setResource("stunned", math.max(status.resource("stunned"), status.stat("knockbackStunTime"))) < end < end < < if not status.resourcePositive("health") then < hitType = "kill" < end < return {{ < sourceEntityId = damageRequest.sourceEntityId, < targetEntityId = entity.id(), < position = mcontroller.position(), < damageDealt = damage, < healthLost = healthLost, < hitType = hitType, < kind = "Normal", < damageSourceKind = damageRequest.damageSourceKind, < targetMaterialKind = status.statusProperty("targetMaterialKind") < }} < end < < function knockbackMomentum(momentum) < local knockback = vec2.mag(momentum) < if mcontroller.baseParameters().gravityEnabled and math.abs(momentum[1]) > 0 then < local dir = momentum[1] > 0 and 1 or -1 < return {dir * knockback / 1.41, knockback / 1.41} < else < return momentum < end < end < < function update(dt) < if self.damageFlashTime > 0 then < local color = status.statusProperty("damageFlashColor") or "ff0000=0.85" < if self.damageFlashType == "strong" then < color = status.statusProperty("strongDamageFlashColor") or "ffffff=1.0" or color < elseif self.damageFlashType == "weak" then < color = status.statusProperty("weakDamageFlashColor") or "000000=0.0" or color < end < status.setPrimaryDirectives(string.format("fade=%s", color)) < else < status.setPrimaryDirectives() < end < self.damageFlashTime = math.max(0, self.damageFlashTime - dt) < < if self.applyKnockback then < mcontroller.addMomentum(self.applyKnockback) < self.applyKnockback = nil < end < < if mcontroller.atWorldLimit(true) then < status.setResourcePercentage("health", 0) < end < < self.damageListener:update() < end --- > require "/scripts/vec2.lua" > require "/scripts/util.lua" > require "/scripts/status.lua" > > function init() > self.damageFlashTime = 0 > > message.setHandler("applyStatusEffect", function(_, _, effectConfig, duration, sourceEntityId) > status.addEphemeralEffect(effectConfig, duration, sourceEntityId) > end) > > local reboundFactor = status.statusProperty("onHitReboundFactor", 0.65) > local minReboundSpeed = status.statusProperty("onHitMinReboundSpeed", 13) > > self.damageListener = damageListener("inflictedHits", function(notifications) > for _, notification in ipairs(notifications) do > if notification.damageSourceKind == "impact" then > local entityVelocity = world.entityVelocity(notification.targetEntityId) > local entityPosition = world.entityPosition(notification.targetEntityId) > if entityVelocity and entityPosition then > local relativeVelocity = vec2.sub(vec2.mul(entityVelocity, 0.85), mcontroller.velocity()) > local relativePosition = world.distance(mcontroller.position(), entityPosition) > local angleDiff = util.angleDiff(vec2.angle(relativeVelocity), vec2.angle(relativePosition)) > if math.abs(angleDiff) < math.pi / 2 then > local reboundSpeed = math.max(minReboundSpeed, vec2.mag(relativeVelocity) * reboundFactor) > local bounceVelocity = vec2.add(relativeVelocity, vec2.withAngle(vec2.angle(relativePosition), reboundSpeed)) > mcontroller.setVelocity(vec2.add(mcontroller.velocity(), bounceVelocity)) > end > end > end > end > end) > end > > function applyDamageRequest(damageRequest) > if world.getProperty("nonCombat") then > return {} > end > > local damage = 0 > if damageRequest.damageType == "Damage" or damageRequest.damageType == "Knockback" then > damage = damage + root.evalFunction2("protection", damageRequest.damage, status.stat("protection")) > elseif damageRequest.damageType == "IgnoresDef" then > damage = damage + damageRequest.damage > elseif damageRequest.damageType == "Environment" then > return {} > elseif damageRequest.damageType == "Status" then > -- only apply status effects > status.addEphemeralEffects(damageRequest.statusEffects, damageRequest.sourceEntityId) > return {} > end > > if status.resourcePositive("shieldHealth") then > local shieldAbsorb = math.min(damage, status.resource("shieldHealth")) > status.modifyResource("shieldHealth", -shieldAbsorb) > damage = damage - shieldAbsorb > end > > local hitType = damageRequest.hitType > local elementalStat = root.elementalResistance(damageRequest.damageSourceKind) > local resistance = status.stat(elementalStat) > damage = damage - (resistance * damage) > if resistance ~= 0 and damage > 0 then > hitType = resistance > 0 and "weakhit" or "stronghit" > end > > local healthLost = math.min(damage, status.resource("health")) > if healthLost > 0 and damageRequest.damageType ~= "Knockback" then > status.modifyResource("health", -healthLost) > if hitType == "stronghit" then > self.damageFlashTime = 0.07 > self.damageFlashType = "strong" > elseif hitType == "weakhit" then > self.damageFlashTime = 0.07 > self.damageFlashType = "weak" > else > self.damageFlashTime = 0.07 > self.damageFlashType = "default" > end > end > > status.addEphemeralEffects(damageRequest.statusEffects, damageRequest.sourceEntityId) > > local knockbackFactor = (1 - status.stat("grit")) > local momentum = knockbackMomentum(vec2.mul(damageRequest.knockbackMomentum, knockbackFactor)) > if status.resourcePositive("health") and vec2.mag(momentum) > 0 then > self.applyKnockback = momentum > if vec2.mag(momentum) > status.stat("knockbackThreshold") then > status.setResource("stunned", math.max(status.resource("stunned"), status.stat("knockbackStunTime"))) > end > end > > if not status.resourcePositive("health") then > hitType = "kill" > end > return {{ > sourceEntityId = damageRequest.sourceEntityId, > targetEntityId = entity.id(), > position = mcontroller.position(), > damageDealt = damage, > healthLost = healthLost, > hitType = hitType, > kind = "Normal", > damageSourceKind = damageRequest.damageSourceKind, > targetMaterialKind = status.statusProperty("targetMaterialKind") > }} > end > > function knockbackMomentum(momentum) > local knockback = vec2.mag(momentum) > if mcontroller.baseParameters().gravityEnabled and math.abs(momentum[1]) > 0 then > local dir = momentum[1] > 0 and 1 or -1 > return {dir * knockback / 1.41, knockback / 1.41} > else > return momentum > end > end > > function update(dt) > if self.damageFlashTime > 0 then > local color = status.statusProperty("damageFlashColor") or "ff0000=0.85" > if self.damageFlashType == "strong" then > color = status.statusProperty("strongDamageFlashColor") or "ffffff=1.0" or color > elseif self.damageFlashType == "weak" then > color = status.statusProperty("weakDamageFlashColor") or "000000=0.0" or color > end > status.setPrimaryDirectives(string.format("fade=%s", color)) > else > status.setPrimaryDirectives() > end > self.damageFlashTime = math.max(0, self.damageFlashTime - dt) > > if self.applyKnockback then > mcontroller.addMomentum(self.applyKnockback) > self.applyKnockback = nil > end > > if mcontroller.atWorldLimit(true) then > status.setResourcePercentage("health", 0) > end > > self.damageListener:update() > end stats\effects\beamin\beamin.lua 9a10,13 > > if status.isResource("stunned") then > status.setResource("stunned", math.max(status.resource("stunned"), effect.duration())) > end 14c18 < end \ No newline at end of file --- > end stats\effects\beamout\beamout.lua 9a10,20 > > self.triggerTimer = config.getParameter("triggerTime") > end > > function update(dt) > if self.triggerTimer > 0 then > self.triggerTimer = self.triggerTimer - dt > if self.triggerTimer <= 0 then > trigger() > end > end 12c23 < function onExpire() --- > function trigger() stats\effects\beamout\beamout.statuseffect 6c6,7 < } --- > }, > "triggerTime" : 0.75 8c9 < "defaultDuration" : 0.75, --- > "defaultDuration" : 0.8, stats\effects\beamout\beamoutanddie.statuseffect 7c7,8 < "die": true --- > "die": true, > "triggerTime" : 0.75 9c10 < "defaultDuration" : 0.75, --- > "defaultDuration" : 2.0, stats\effects\beamout\beamoutandteleport.statuseffect 7c7,8 < "teleport": true --- > "teleport": true, > "triggerTime" : 0.75 9c10 < "defaultDuration" : 0.75, --- > "defaultDuration" : 1.0, tiles\classicmaterialtemplate.config 164c164,165 < "type" : "EqualsSelf" --- > "type" : "EqualsSelf", > "matchHue" : true 171a173 > "matchHue" : true, tiles\materials\ledgebrick.material 18c18 < "variants" : 10, --- > "variants" : 8, tiles\materials\ridgebrick.material 18c18 < "variants" : 10, --- > "variants" : 8, tilesets\packed\materials.json 7c7 < "tilecount" : 195, --- > "tilecount" : 197, 647a648,659 > "195" : { > "//description" : "I can see my reflection.", > "//name" : "slopedglasspanel", > "//shortdescription" : "Glass Panel", > "material" : "slopedglasspanel" > }, > "196" : { > "//description" : " It's virtual!", > "//name" : "slopedpolygon", > "//shortdescription" : "Hull Panel", > "material" : "slopedpolygon" > }, 1495a1508,1513 > }, > "195" : { > "image" : "./../../../../tiled/packed/materials/slopedglasspanel.png" > }, > "196" : { > "image" : "./../../../../tiled/packed/materials/slopedpolygon.png" tilesets\packed\miscellaneous.json 8c8 < "tilecount":22, --- > "tilecount":23, 109a110,116 > "22": > { > "\/\/description":"Require that there be ocean liquid", > "\/\/shortdescription":"World Gen Must Contain Ocean Liquid", > "allowOverdrawing":"true", > "worldGenMustContainLiquid":"" > }, 217a225,228 > }, > "22": > { > "image":"..\/..\/..\/..\/tiled\/packed\/miscellaneous\/22.png" tilesets\packed\objects-by-category\breakable.json 7c7 < "tilecount" : 308, --- > "tilecount" : 310, 1956a1957,1974 > "308" : { > "//description" : "A toxic waste barrel. Don't spill any!", > "//name" : "toxicwastebarrel", > "//shortdescription" : "Toxic Waste Barrel", > "imagePositionX" : "-8", > "imagePositionY" : "0", > "object" : "toxicwastebarrel", > "tilesetDirection" : "right" > }, > "309" : { > "//description" : "An explosive metal barrel. It looks dangerous.", > "//name" : "explosivebarrel", > "//shortdescription" : " Explosive Barrel", > "imagePositionX" : "-8", > "imagePositionY" : "0", > "object" : "explosivebarrel", > "tilesetDirection" : "right" > }, 3295a3314,3319 > }, > "308" : { > "image" : "../../../../../tiled/packed/objects/toxicwastebarrel.png" > }, > "309" : { > "image" : "../../../../../tiled/packed/objects/explosivebarrel.png" tilesets\packed\objects-by-category\crafting.json 29c29 < "//description" : "The Avian flag. Use ^green;[E] to bookmark a teleportation location.", --- > "//description" : "The Avian flag. Use ^green;[E]^white; to bookmark a teleportation location.", 632c632 < "//description" : "The Avian flag. Use ^green;[E] to bookmark a teleportation location.", --- > "//description" : "The Avian flag. Use ^green;[E]^white; to bookmark a teleportation location.", tilesets\packed\objects-by-category\decorative.json 7c7 < "tilecount" : 1416, --- > "tilecount" : 1435, 3943c3943 < "//shortdescription" : "Station Console", --- > "//shortdescription" : "Space Station Console", 4015a4016,4050 > "1416" : { > "//description" : "A worn wall banner, spraypainted with the Ocassus cult emblem.", > "//name" : "cultistbannerlarge", > "//shortdescription" : "Cultist Banner", > "imagePositionX" : "-16", > "imagePositionY" : "-40", > "object" : "cultistbannerlarge", > "tilesetDirection" : "right" > }, > "1417" : { > "//description" : "A noticeboard where bounties for notorious criminals are posted!", > "//name" : "bountyboard", > "//shortdescription" : "Bounty Board", > "imagePositionX" : "-24", > "imagePositionY" : "0", > "object" : "bountyboard" > }, > "1418" : { > "//description" : "A worn wall banner, spraypainted with the Ocassus cult emblem.", > "//name" : "cultistbannerlarge_orientation2", > "//shortdescription" : "Cultist Banner", > "imagePositionX" : "-16", > "imagePositionY" : "-40", > "object" : "cultistbannerlarge", > "tilesetDirection" : "right" > }, > "1419" : { > "//description" : "A worn wall banner, spraypainted with the Ocassus cult emblem.", > "//name" : "cultistbannerlarge_orientation3", > "//shortdescription" : "Cultist Banner", > "imagePositionX" : "-16", > "imagePositionY" : "-40", > "object" : "cultistbannerlarge", > "tilesetDirection" : "right" > }, 4024a4060,4149 > "1420" : { > "//description" : "A jumbled collection of leads and evidence, used to track criminals.", > "//name" : "peacekeepernotes", > "//shortdescription" : "Peacekeeper Notes", > "imagePositionX" : "-24", > "imagePositionY" : "-16", > "object" : "peacekeepernotes", > "tilesetDirection" : "right" > }, > "1421" : { > "//description" : "A golden wall plaque, embossed with the Peacekeeper's emblem.", > "//name" : "peacekeeperemblem", > "//shortdescription" : "Peacekeeper Emblem", > "imagePositionX" : "-16", > "imagePositionY" : "-16", > "object" : "peacekeeperemblem", > "tilesetDirection" : "right" > }, > "1422" : { > "//description" : "A round desk, made for the Peacekeeper's HQ.", > "//name" : "peacekeeperdesk", > "//shortdescription" : "Peacekeeper Desk", > "imagePositionX" : "-24", > "imagePositionY" : "0", > "object" : "peacekeeperdesk", > "tilesetDirection" : "right" > }, > "1423" : { > "//description" : "A fresh mug of coffee. It seems perpetually steaming hot.", > "//name" : "peacekeepermug", > "//shortdescription" : "Peacekeeper Mug", > "imagePositionX" : "0", > "imagePositionY" : "0", > "object" : "peacekeepermug", > "tilesetDirection" : "right" > }, > "1424" : { > "//description" : "A poster with some faded photographs of criminals printed on it.", > "//name" : "peacekeeperposter1", > "//shortdescription" : "Peacekeeper Tall Poster", > "imagePositionX" : "-24", > "imagePositionY" : "-16", > "object" : "peacekeeperposter1", > "tilesetDirection" : "right" > }, > "1425" : { > "//description" : "A cool painting of a timeless, hazy beach sunset.", > "//name" : "peacekeeperpainting", > "//shortdescription" : "Peacekeeper Painting", > "imagePositionX" : "-32", > "imagePositionY" : "-16", > "object" : "peacekeeperpainting", > "tilesetDirection" : "right" > }, > "1426" : { > "//description" : "A poster with some faded photographs of criminals printed on it.", > "//name" : "peacekeeperposter2", > "//shortdescription" : "Peacekeeper Wide Poster", > "imagePositionX" : "-24", > "imagePositionY" : "-16", > "object" : "peacekeeperposter2", > "tilesetDirection" : "right" > }, > "1427" : { > "//description" : "-todo-", > "//name" : "egyptiancrest", > "//shortdescription" : "Egyptian Crest", > "imagePositionX" : "-24", > "imagePositionY" : "-8", > "object" : "egyptiancrest", > "tilesetDirection" : "right" > }, > "1428" : { > "//description" : "A rusty wall plaque, embossed with the Peacekeeper's emblem.", > "//name" : "peacekeeperemblem2", > "//shortdescription" : "Peacekeeper Rusty Emblem", > "imagePositionX" : "-16", > "imagePositionY" : "-16", > "object" : "peacekeeperemblem2", > "tilesetDirection" : "right" > }, > "1429" : { > "//description" : "A teleportation platform that summmons a player's mech.", > "//name" : "mechplatform", > "//shortdescription" : "Mech Platform", > "imagePositionX" : "-24", > "imagePositionY" : "0", > "object" : "mechplatform", > "tilesetDirection" : "right" > }, 4033a4159,4202 > "1430" : { > "//description" : "-todo-", > "//name" : "officeserver", > "//shortdescription" : "Office Server", > "imagePositionX" : "-16", > "imagePositionY" : "0", > "object" : "officeserver", > "tilesetDirection" : "right" > }, > "1431" : { > "//description" : "A tall antiquated device used for assisting in paperwork.", > "//name" : "officescanner", > "//shortdescription" : "Office Scanner", > "imagePositionX" : "-24", > "imagePositionY" : "0", > "object" : "officescanner", > "tilesetDirection" : "right" > }, > "1432" : { > "//description" : "-todo-", > "//name" : "officenoticeboard", > "//shortdescription" : "Office Noticeboard", > "imagePositionX" : "-16", > "imagePositionY" : "-8", > "object" : "officenoticeboard" > }, > "1433" : { > "//description" : "-todo-", > "//name" : "officestapler", > "//shortdescription" : "Office Stapler", > "imagePositionX" : "-8", > "imagePositionY" : "0", > "object" : "officestapler", > "tilesetDirection" : "right" > }, > "1434" : { > "//description" : "A poster advertising the Peacekeeper Initiative.", > "//name" : "outpostpeacekeeperposter", > "//shortdescription" : "Outpost Peacekeeper Poster", > "imagePositionX" : "-8", > "imagePositionY" : "-16", > "object" : "outpostpeacekeeperposter", > "tilesetDirection" : "right" > }, 10349c10518 < "//description" : "The Avian flag. Use ^green;[E] to bookmark a teleportation location.", --- > "//description" : "The Avian flag. Use ^green;[E]^white; to bookmark a teleportation location.", 10358c10527 < "//description" : "The Avian flag. Use ^green;[E] to bookmark a teleportation location.", --- > "//description" : "The Avian flag. Use ^green;[E]^white; to bookmark a teleportation location.", 13237a13407,13418 > "1416" : { > "image" : "../../../../../tiled/packed/objects/cultistbannerlarge.png" > }, > "1417" : { > "image" : "../../../../../tiled/packed/objects/bountyboard.png" > }, > "1418" : { > "image" : "../../../../../tiled/packed/objects/cultistbannerlarge_orientation2.png" > }, > "1419" : { > "image" : "../../../../../tiled/packed/objects/cultistbannerlarge_orientation3.png" > }, 13240a13422,13451 > "1420" : { > "image" : "../../../../../tiled/packed/objects/peacekeepernotes.png" > }, > "1421" : { > "image" : "../../../../../tiled/packed/objects/peacekeeperemblem.png" > }, > "1422" : { > "image" : "../../../../../tiled/packed/objects/peacekeeperdesk.png" > }, > "1423" : { > "image" : "../../../../../tiled/packed/objects/peacekeepermug.png" > }, > "1424" : { > "image" : "../../../../../tiled/packed/objects/peacekeeperposter1.png" > }, > "1425" : { > "image" : "../../../../../tiled/packed/objects/peacekeeperpainting.png" > }, > "1426" : { > "image" : "../../../../../tiled/packed/objects/peacekeeperposter2.png" > }, > "1427" : { > "image" : "../../../../../tiled/packed/objects/egyptiancrest.png" > }, > "1428" : { > "image" : "../../../../../tiled/packed/objects/peacekeeperemblem2.png" > }, > "1429" : { > "image" : "../../../../../tiled/packed/objects/mechplatform.png" > }, 13242a13454,13468 > }, > "1430" : { > "image" : "../../../../../tiled/packed/objects/officeserver.png" > }, > "1431" : { > "image" : "../../../../../tiled/packed/objects/officescanner.png" > }, > "1432" : { > "image" : "../../../../../tiled/packed/objects/officenoticeboard.png" > }, > "1433" : { > "image" : "../../../../../tiled/packed/objects/officestapler.png" > }, > "1434" : { > "image" : "../../../../../tiled/packed/objects/outpostpeacekeeperposter.png" tilesets\packed\objects-by-category\door.json 7c7 < "tilecount" : 128, --- > "tilecount" : 131, 297a298,315 > "128" : { > "//description" : "-todo-", > "//name" : "peacekeeperdoor", > "//shortdescription" : "Peacekeeper Door", > "imagePositionX" : "-24", > "imagePositionY" : "0", > "object" : "peacekeeperdoor", > "tilesetDirection" : "right" > }, > "129" : { > "//description" : "A crudely-made airlock door.", > "//name" : "cultistairlockdoor", > "//shortdescription" : "Cultist Airlock Door", > "imagePositionX" : "-8", > "imagePositionY" : "0", > "object" : "cultistairlockdoor", > "tilesetDirection" : "right" > }, 306a325,333 > "130" : { > "//description" : "A crudely-made airlock hatch.", > "//name" : "cultistairlockhatch", > "//shortdescription" : "Cultist Airlock Hatch", > "imagePositionX" : "-24", > "imagePositionY" : "-8", > "object" : "cultistairlockhatch", > "tilesetDirection" : "right" > }, 1197a1225,1230 > "128" : { > "image" : "../../../../../tiled/packed/objects/peacekeeperdoor.png" > }, > "129" : { > "image" : "../../../../../tiled/packed/objects/cultistairlockdoor.png" > }, 1199a1233,1235 > }, > "130" : { > "image" : "../../../../../tiled/packed/objects/cultistairlockhatch.png" tilesets\packed\objects-by-category\furniture.json 7c7 < "tilecount" : 346, --- > "tilecount" : 354, 2409a2410,2445 > "346" : { > "//description" : "-todo-", > "//name" : "peacekeeperchair", > "//shortdescription" : "Peacekeeper Chair", > "imagePositionX" : "-8", > "imagePositionY" : "0", > "object" : "peacekeeperchair", > "tilesetDirection" : "right" > }, > "347" : { > "//description" : "-todo-", > "//name" : "peacekeepertable", > "//shortdescription" : "Peacekeeper Table", > "imagePositionX" : "-16", > "imagePositionY" : "0", > "object" : "peacekeepertable", > "tilesetDirection" : "right" > }, > "348" : { > "//description" : "-todo-", > "//name" : "egyptianbed", > "//shortdescription" : "Egyptian Bed", > "imagePositionX" : "-24", > "imagePositionY" : "0", > "object" : "egyptianbed", > "tilesetDirection" : "right" > }, > "349" : { > "//description" : "-todo-", > "//name" : "egyptiantable", > "//shortdescription" : "Egyptian Table", > "imagePositionX" : "-24", > "imagePositionY" : "0", > "object" : "egyptiantable", > "tilesetDirection" : "right" > }, 2418a2455,2488 > "350" : { > "//description" : "-todo-", > "//name" : "egyptianpillar", > "//shortdescription" : "Egyptian Pillar", > "imagePositionX" : "-16", > "imagePositionY" : "0", > "object" : "egyptianpillar" > }, > "351" : { > "//description" : "-todo-", > "//name" : "egyptianchair", > "//shortdescription" : "Egyptian Chair", > "imagePositionX" : "-16", > "imagePositionY" : "0", > "object" : "egyptianchair", > "tilesetDirection" : "right" > }, > "352" : { > "//description" : "-todo-", > "//name" : "egyptianstatuette", > "//shortdescription" : "Egyptian Statuette", > "imagePositionX" : "-8", > "imagePositionY" : "0", > "object" : "egyptianstatuette" > }, > "353" : { > "//description" : "-todo-", > "//name" : "officetable", > "//shortdescription" : "Office Table", > "imagePositionX" : "-24", > "imagePositionY" : "0", > "object" : "officetable", > "tilesetDirection" : "right" > }, 3825a3896,3907 > "346" : { > "image" : "../../../../../tiled/packed/objects/peacekeeperchair.png" > }, > "347" : { > "image" : "../../../../../tiled/packed/objects/peacekeepertable.png" > }, > "348" : { > "image" : "../../../../../tiled/packed/objects/egyptianbed.png" > }, > "349" : { > "image" : "../../../../../tiled/packed/objects/egyptiantable.png" > }, 3827a3910,3921 > }, > "350" : { > "image" : "../../../../../tiled/packed/objects/egyptianpillar.png" > }, > "351" : { > "image" : "../../../../../tiled/packed/objects/egyptianchair.png" > }, > "352" : { > "image" : "../../../../../tiled/packed/objects/egyptianstatuette.png" > }, > "353" : { > "image" : "../../../../../tiled/packed/objects/officetable.png" tilesets\packed\objects-by-category\generic.json 7c7 < "tilecount" : 1, --- > "tilecount" : 2, 17a18,25 > }, > "1" : { > "//description" : "Extracts ores from the ground", > "//name" : "extractordrill", > "//shortdescription" : "Extractor Drill", > "imagePositionX" : "-16", > "imagePositionY" : "0", > "object" : "extractordrill" 22a31,33 > }, > "1" : { > "image" : "../../../../../tiled/packed/objects/extractordrill.png" tilesets\packed\objects-by-category\light.json 7c7 < "tilecount" : 442, --- > "tilecount" : 457, 3357a3358,3429 > "442" : { > "//description" : "A light that can switch between green and red.", > "//name" : "greenredlight", > "//shortdescription" : "Green Red Light", > "imagePositionX" : "0", > "imagePositionY" : "0", > "object" : "greenredlight", > "tilesetDirection" : "left" > }, > "443" : { > "//description" : "A light that can switch between green and red.", > "//name" : "greenredlight_orientation2", > "//shortdescription" : "Green Red Light", > "imagePositionX" : "0", > "imagePositionY" : "0", > "object" : "greenredlight", > "tilesetDirection" : "right" > }, > "444" : { > "//description" : "A light that can switch between green and red.", > "//name" : "greenredlight_orientation3", > "//shortdescription" : "Green Red Light", > "imagePositionX" : "0", > "imagePositionY" : "0", > "object" : "greenredlight", > "tilesetDirection" : "right" > }, > "445" : { > "//description" : "A light that can switch between green and red.", > "//name" : "greenredlight_orientation4", > "//shortdescription" : "Green Red Light", > "imagePositionX" : "0", > "imagePositionY" : "0", > "object" : "greenredlight", > "tilesetDirection" : "right" > }, > "446" : { > "//description" : "A light that can switch between green and red.", > "//name" : "greenredlight_orientation5", > "//shortdescription" : "Green Red Light", > "imagePositionX" : "0", > "imagePositionY" : "0", > "object" : "greenredlight", > "tilesetDirection" : "right" > }, > "447" : { > "//description" : "A light that can switch between green and red.", > "//name" : "greenredlight_orientation6", > "//shortdescription" : "Green Red Light", > "imagePositionX" : "0", > "imagePositionY" : "0", > "object" : "greenredlight", > "tilesetDirection" : "right" > }, > "448" : { > "//description" : "A light that can switch between green and red.", > "//name" : "greenredlight_orientation7", > "//shortdescription" : "Green Red Light", > "imagePositionX" : "0", > "imagePositionY" : "0", > "object" : "greenredlight", > "tilesetDirection" : "right" > }, > "449" : { > "//description" : "A bright lamp post, most commonly seen at the Peacekeeper Stations.", > "//name" : "peacekeeperlamppost", > "//shortdescription" : "Peacekeeper Lamp Post", > "imagePositionX" : "0", > "imagePositionY" : "0", > "object" : "peacekeeperlamppost", > "tilesetDirection" : "right" > }, 3366a3439,3501 > "450" : { > "//description" : "A sign that says either offline or online.", > "//name" : "miningpowersign", > "//shortdescription" : "Power Sign", > "imagePositionX" : "-16", > "imagePositionY" : "0", > "object" : "miningpowersign", > "tilesetDirection" : "right" > }, > "451" : { > "//description" : "A magenta street lamp post. Not the best colour for visibility, but it sure looks cool.", > "//name" : "neonlamppost", > "//shortdescription" : "Neon Lamp Post", > "imagePositionX" : "-16", > "imagePositionY" : "0", > "object" : "neonlamppost", > "tilesetDirection" : "right" > }, > "452" : { > "//description" : "This wall ornament glows with a bold magenta light.", > "//name" : "neontriangle", > "//shortdescription" : "Neon Triangle", > "imagePositionX" : "-8", > "imagePositionY" : "0", > "object" : "neontriangle", > "tilesetDirection" : "right" > }, > "453" : { > "//description" : "This chandelier is made of wrought-iron. It looks expensive.", > "//name" : "hangingguardian", > "//shortdescription" : "Hanging Guardian", > "imagePositionX" : "-32", > "imagePositionY" : "-40", > "object" : "hangingguardian", > "tilesetDirection" : "right" > }, > "454" : { > "//description" : "This wall ornament glows with a bold magenta light.", > "//name" : "neonpeacekeeperemblem", > "//shortdescription" : "Neon Peacekeeper Emblem", > "imagePositionX" : "-16", > "imagePositionY" : "-16", > "object" : "neonpeacekeeperemblem", > "tilesetDirection" : "right" > }, > "455" : { > "//description" : "A slick, understated magenta light.", > "//name" : "neonlight", > "//shortdescription" : "Neon Magenta Light", > "imagePositionX" : "-8", > "imagePositionY" : "0", > "object" : "neonlight", > "tilesetDirection" : "right" > }, > "456" : { > "//description" : "-todo-", > "//name" : "officelamp", > "//shortdescription" : "Office Desk Lamp", > "imagePositionX" : "-8", > "imagePositionY" : "0", > "object" : "officelamp", > "tilesetDirection" : "right" > }, 5027a5163,5186 > "442" : { > "image" : "../../../../../tiled/packed/objects/greenredlight.png" > }, > "443" : { > "image" : "../../../../../tiled/packed/objects/greenredlight_orientation2.png" > }, > "444" : { > "image" : "../../../../../tiled/packed/objects/greenredlight_orientation3.png" > }, > "445" : { > "image" : "../../../../../tiled/packed/objects/greenredlight_orientation4.png" > }, > "446" : { > "image" : "../../../../../tiled/packed/objects/greenredlight_orientation5.png" > }, > "447" : { > "image" : "../../../../../tiled/packed/objects/greenredlight_orientation6.png" > }, > "448" : { > "image" : "../../../../../tiled/packed/objects/greenredlight_orientation7.png" > }, > "449" : { > "image" : "../../../../../tiled/packed/objects/peacekeeperlamppost.png" > }, 5029a5189,5209 > }, > "450" : { > "image" : "../../../../../tiled/packed/objects/miningpowersign.png" > }, > "451" : { > "image" : "../../../../../tiled/packed/objects/neonlamppost.png" > }, > "452" : { > "image" : "../../../../../tiled/packed/objects/neontriangle.png" > }, > "453" : { > "image" : "../../../../../tiled/packed/objects/hangingguardian.png" > }, > "454" : { > "image" : "../../../../../tiled/packed/objects/neonpeacekeeperemblem.png" > }, > "455" : { > "image" : "../../../../../tiled/packed/objects/neonlight.png" > }, > "456" : { > "image" : "../../../../../tiled/packed/objects/officelamp.png" tilesets\packed\objects-by-category\other.json 7c7 < "tilecount" : 303, --- > "tilecount" : 310, 1313c1313 < "//description" : "", --- > "//description" : "This screen displays a variety of propaganda messages from Big Ape.", 1738a1739,1797 > "303" : { > "//description" : "-todo-", > "//name" : "peacekeeperstore", > "//shortdescription" : "Peacekeeper Store", > "imagePositionX" : "-24", > "imagePositionY" : "-24", > "object" : "peacekeeperstore" > }, > "304" : { > "//description" : "A vending machine that appears to cook and dispense only donuts.", > "//name" : "peacekeepervendingmachine", > "//shortdescription" : "Peacekeeper Vending Machine", > "imagePositionX" : "-16", > "imagePositionY" : "0", > "object" : "peacekeepervendingmachine", > "tilesetDirection" : "left" > }, > "305" : { > "//description" : "-todo-", > "//name" : "peacekeeperfurnishings", > "//shortdescription" : "Peacekeeper Furnishings", > "imagePositionX" : "-24", > "imagePositionY" : "0", > "object" : "peacekeeperfurnishings", > "tilesetDirection" : "right" > }, > "306" : { > "//description" : "A numeric security keypad that requires a specific combination.", > "//name" : "keypad", > "//shortdescription" : "Numeric Keypad", > "imagePositionX" : "-8", > "imagePositionY" : "-8", > "object" : "keypad", > "tilesetDirection" : "right" > }, > "307" : { > "//description" : "-todo-", > "//name" : "peacekeeperstore2", > "//shortdescription" : "Peacekeeper Store", > "imagePositionX" : "-24", > "imagePositionY" : "-24", > "object" : "peacekeeperstore2" > }, > "308" : { > "//description" : "-todo-", > "//name" : "peacekeeperstore3", > "//shortdescription" : "Peacekeeper Store", > "imagePositionX" : "-24", > "imagePositionY" : "-24", > "object" : "peacekeeperstore3" > }, > "309" : { > "//description" : "-todo-", > "//name" : "neonstore", > "//shortdescription" : "Neon Store", > "imagePositionX" : "-24", > "imagePositionY" : "-24", > "object" : "neonstore" > }, 3034a3094,3114 > }, > "303" : { > "image" : "../../../../../tiled/packed/objects/peacekeeperstore.png" > }, > "304" : { > "image" : "../../../../../tiled/packed/objects/peacekeepervendingmachine.png" > }, > "305" : { > "image" : "../../../../../tiled/packed/objects/peacekeeperfurnishings.png" > }, > "306" : { > "image" : "../../../../../tiled/packed/objects/keypad.png" > }, > "307" : { > "image" : "../../../../../tiled/packed/objects/peacekeeperstore2.png" > }, > "308" : { > "image" : "../../../../../tiled/packed/objects/peacekeeperstore3.png" > }, > "309" : { > "image" : "../../../../../tiled/packed/objects/neonstore.png" tilesets\packed\objects-by-category\playerstation.json 21c21 < "//shortdescription" : "Station Console", --- > "//shortdescription" : "Space Station Console", tilesets\packed\objects-by-category\storage.json 7c7 < "tilecount" : 231, --- > "tilecount" : 234, 1214c1214 < "//description" : "A pressurised cargo crate, designed to withstand the harsh conditions of space travel.", --- > "//description" : "A pressurised cargo crate, designed to withstand the conditions of space travel.", 1273a1274,1300 > "231" : { > "//description" : "A metal chest with a glowing eye emblem on it.", > "//name" : "cultistchestlarge", > "//shortdescription" : "Cultist Chest", > "imagePositionX" : "-16", > "imagePositionY" : "0", > "object" : "cultistchestlarge", > "tilesetDirection" : "right" > }, > "232" : { > "//description" : "-todo-", > "//name" : "officedesk", > "//shortdescription" : "Office Desk", > "imagePositionX" : "-24", > "imagePositionY" : "0", > "object" : "officedesk", > "tilesetDirection" : "right" > }, > "233" : { > "//description" : "A modern metal cabinet with floor mounting brackets.", > "//name" : "officecabinet", > "//shortdescription" : "Office Cabinet", > "imagePositionX" : "-16", > "imagePositionY" : "0", > "object" : "officecabinet", > "tilesetDirection" : "right" > }, 2404a2432,2440 > }, > "231" : { > "image" : "../../../../../tiled/packed/objects/cultistchestlarge.png" > }, > "232" : { > "image" : "../../../../../tiled/packed/objects/officedesk.png" > }, > "233" : { > "image" : "../../../../../tiled/packed/objects/officecabinet.png" tilesets\packed\objects-by-category\teleporter.json 7c7 < "tilecount" : 40, --- > "tilecount" : 41, 99c99 < "//description" : "The Avian flag. Use ^green;[E] to bookmark a teleportation location.", --- > "//description" : "The Avian flag. Use ^green;[E]^white; to bookmark a teleportation location.", 108c108 < "//description" : "The Avian flag. Use ^green;[E] to bookmark a teleportation location.", --- > "//description" : "The Avian flag. Use ^green;[E]^white; to bookmark a teleportation location.", 300a301,308 > "40" : { > "//description" : "This teleporter should get you back to the Peacekeeper HQ.", > "//name" : "peacekeeperteleporter", > "//shortdescription" : "Peacekeeper Teleporter", > "imagePositionX" : "-16", > "imagePositionY" : "0", > "object" : "peacekeeperteleporter" > }, 447a456,458 > }, > "40" : { > "image" : "../../../../../tiled/packed/objects/peacekeeperteleporter.png" tilesets\packed\objects-by-category\teleportmarker.json 101c101 < "//description" : "The Avian flag. Use ^green;[E] to bookmark a teleportation location.", --- > "//description" : "The Avian flag. Use ^green;[E]^white; to bookmark a teleportation location.", 110c110 < "//description" : "The Avian flag. Use ^green;[E] to bookmark a teleportation location.", --- > "//description" : "The Avian flag. Use ^green;[E]^white; to bookmark a teleportation location.", tilesets\packed\objects-by-category\wire.json 7c7 < "tilecount" : 217, --- > "tilecount" : 221, 1143a1144,1170 > "217" : { > "//description" : "A panel that generates electricity from solar energy.", > "//name" : "solarpanel", > "//shortdescription" : "Solar Panel", > "imagePositionX" : "-16", > "imagePositionY" : "0", > "object" : "solarpanel", > "tilesetDirection" : "right" > }, > "218" : { > "//description" : "An outdated metal computer. Standard issue for Peacekeeper research teams.", > "//name" : "peacekeepercomputer", > "//shortdescription" : "Peacekeeper Computer", > "imagePositionX" : "-16", > "imagePositionY" : "0", > "object" : "peacekeepercomputer", > "tilesetDirection" : "right" > }, > "219" : { > "//description" : "A magenta hologram of a palm tree.", > "//name" : "neonhologram", > "//shortdescription" : "Neon Hologram", > "imagePositionX" : "-32", > "imagePositionY" : "0", > "object" : "neonhologram", > "tilesetDirection" : "right" > }, 1152a1180,1188 > "220" : { > "//description" : "-todo-", > "//name" : "officecomputer", > "//shortdescription" : "Office Computer", > "imagePositionX" : "-16", > "imagePositionY" : "0", > "object" : "officecomputer", > "tilesetDirection" : "right" > }, 2269a2306,2314 > "217" : { > "image" : "../../../../../tiled/packed/objects/solarpanel.png" > }, > "218" : { > "image" : "../../../../../tiled/packed/objects/peacekeepercomputer.png" > }, > "219" : { > "image" : "../../../../../tiled/packed/objects/neonhologram.png" > }, 2271a2317,2319 > }, > "220" : { > "image" : "../../../../../tiled/packed/objects/officecomputer.png" tilesets\packed\objects-by-colonytag\ancient.json 7c7 < "tilecount" : 124, --- > "tilecount" : 125, 265a266,274 > "124" : { > "//description" : "This chandelier is made of wrought-iron. It looks expensive.", > "//name" : "hangingguardian", > "//shortdescription" : "Hanging Guardian", > "imagePositionX" : "-32", > "imagePositionY" : "-40", > "object" : "hangingguardian", > "tilesetDirection" : "right" > }, 1200a1210,1212 > }, > "124" : { > "image" : "../../../../../tiled/packed/objects/hangingguardian.png" tilesets\packed\objects-by-colonytag\avian.json 1579c1579 < "//description" : "The Avian flag. Use ^green;[E] to bookmark a teleportation location.", --- > "//description" : "The Avian flag. Use ^green;[E]^white; to bookmark a teleportation location.", 1588c1588 < "//description" : "The Avian flag. Use ^green;[E] to bookmark a teleportation location.", --- > "//description" : "The Avian flag. Use ^green;[E]^white; to bookmark a teleportation location.", tilesets\packed\objects-by-colonytag\commerce.json 7c7 < "tilecount" : 145, --- > "tilecount" : 156, 368c368 < "//description" : "A pressurised cargo crate, designed to withstand the harsh conditions of space travel.", --- > "//description" : "A pressurised cargo crate, designed to withstand the conditions of space travel.", 463a464,507 > "145" : { > "//description" : "-todo-", > "//name" : "peacekeeperstore", > "//shortdescription" : "Peacekeeper Store", > "imagePositionX" : "-24", > "imagePositionY" : "-24", > "object" : "peacekeeperstore" > }, > "146" : { > "//description" : "A vending machine that appears to cook and dispense only donuts.", > "//name" : "peacekeepervendingmachine", > "//shortdescription" : "Peacekeeper Vending Machine", > "imagePositionX" : "-16", > "imagePositionY" : "0", > "object" : "peacekeepervendingmachine", > "tilesetDirection" : "left" > }, > "147" : { > "//description" : "-todo-", > "//name" : "peacekeepertable", > "//shortdescription" : "Peacekeeper Table", > "imagePositionX" : "-16", > "imagePositionY" : "0", > "object" : "peacekeepertable", > "tilesetDirection" : "right" > }, > "148" : { > "//description" : "-todo-", > "//name" : "peacekeeperfurnishings", > "//shortdescription" : "Peacekeeper Furnishings", > "imagePositionX" : "-24", > "imagePositionY" : "0", > "object" : "peacekeeperfurnishings", > "tilesetDirection" : "right" > }, > "149" : { > "//description" : "-todo-", > "//name" : "egyptiantable", > "//shortdescription" : "Egyptian Table", > "imagePositionX" : "-24", > "imagePositionY" : "0", > "object" : "egyptiantable", > "tilesetDirection" : "right" > }, 471a516,565 > "150" : { > "//description" : "-todo-", > "//name" : "egyptianpillar", > "//shortdescription" : "Egyptian Pillar", > "imagePositionX" : "-16", > "imagePositionY" : "0", > "object" : "egyptianpillar" > }, > "151" : { > "//description" : "-todo-", > "//name" : "peacekeeperstore2", > "//shortdescription" : "Peacekeeper Store", > "imagePositionX" : "-24", > "imagePositionY" : "-24", > "object" : "peacekeeperstore2" > }, > "152" : { > "//description" : "-todo-", > "//name" : "peacekeeperstore3", > "//shortdescription" : "Peacekeeper Store", > "imagePositionX" : "-24", > "imagePositionY" : "-24", > "object" : "peacekeeperstore3" > }, > "153" : { > "//description" : "-todo-", > "//name" : "neonstore", > "//shortdescription" : "Neon Store", > "imagePositionX" : "-24", > "imagePositionY" : "-24", > "object" : "neonstore" > }, > "154" : { > "//description" : "-todo-", > "//name" : "officetable", > "//shortdescription" : "Office Table", > "imagePositionX" : "-24", > "imagePositionY" : "0", > "object" : "officetable", > "tilesetDirection" : "right" > }, > "155" : { > "//description" : "-todo-", > "//name" : "officedesk", > "//shortdescription" : "Office Desk", > "imagePositionX" : "-24", > "imagePositionY" : "0", > "object" : "officedesk", > "tilesetDirection" : "right" > }, 1445a1540,1554 > "145" : { > "image" : "../../../../../tiled/packed/objects/peacekeeperstore.png" > }, > "146" : { > "image" : "../../../../../tiled/packed/objects/peacekeepervendingmachine.png" > }, > "147" : { > "image" : "../../../../../tiled/packed/objects/peacekeepertable.png" > }, > "148" : { > "image" : "../../../../../tiled/packed/objects/peacekeeperfurnishings.png" > }, > "149" : { > "image" : "../../../../../tiled/packed/objects/egyptiantable.png" > }, 1447a1557,1574 > }, > "150" : { > "image" : "../../../../../tiled/packed/objects/egyptianpillar.png" > }, > "151" : { > "image" : "../../../../../tiled/packed/objects/peacekeeperstore2.png" > }, > "152" : { > "image" : "../../../../../tiled/packed/objects/peacekeeperstore3.png" > }, > "153" : { > "image" : "../../../../../tiled/packed/objects/neonstore.png" > }, > "154" : { > "image" : "../../../../../tiled/packed/objects/officetable.png" > }, > "155" : { > "image" : "../../../../../tiled/packed/objects/officedesk.png" tilesets\packed\objects-by-colonytag\door.json 7c7 < "tilecount" : 119, --- > "tilecount" : 122, 206a207,215 > "119" : { > "//description" : "-todo-", > "//name" : "peacekeeperdoor", > "//shortdescription" : "Peacekeeper Door", > "imagePositionX" : "-24", > "imagePositionY" : "0", > "object" : "peacekeeperdoor", > "tilesetDirection" : "right" > }, 215a225,242 > "120" : { > "//description" : "A crudely-made airlock door.", > "//name" : "cultistairlockdoor", > "//shortdescription" : "Cultist Airlock Door", > "imagePositionX" : "-8", > "imagePositionY" : "0", > "object" : "cultistairlockdoor", > "tilesetDirection" : "right" > }, > "121" : { > "//description" : "A crudely-made airlock hatch.", > "//name" : "cultistairlockhatch", > "//shortdescription" : "Cultist Airlock Hatch", > "imagePositionX" : "-24", > "imagePositionY" : "-8", > "object" : "cultistairlockhatch", > "tilesetDirection" : "right" > }, 1125a1153,1155 > "119" : { > "image" : "../../../../../tiled/packed/objects/peacekeeperdoor.png" > }, 1127a1158,1163 > }, > "120" : { > "image" : "../../../../../tiled/packed/objects/cultistairlockdoor.png" > }, > "121" : { > "image" : "../../../../../tiled/packed/objects/cultistairlockhatch.png" tilesets\packed\objects-by-colonytag\electronic.json 7c7 < "tilecount" : 127, --- > "tilecount" : 130, 280a281,307 > "127" : { > "//description" : "A numeric security keypad that requires a specific combination.", > "//name" : "keypad", > "//shortdescription" : "Numeric Keypad", > "imagePositionX" : "-8", > "imagePositionY" : "-8", > "object" : "keypad", > "tilesetDirection" : "right" > }, > "128" : { > "//description" : "An outdated metal computer. Standard issue for Peacekeeper research teams.", > "//name" : "peacekeepercomputer", > "//shortdescription" : "Peacekeeper Computer", > "imagePositionX" : "-16", > "imagePositionY" : "0", > "object" : "peacekeepercomputer", > "tilesetDirection" : "right" > }, > "129" : { > "//description" : "-todo-", > "//name" : "officecomputer", > "//shortdescription" : "Office Computer", > "imagePositionX" : "-16", > "imagePositionY" : "0", > "object" : "officecomputer", > "tilesetDirection" : "right" > }, 1197a1225,1233 > }, > "127" : { > "image" : "../../../../../tiled/packed/objects/keypad.png" > }, > "128" : { > "image" : "../../../../../tiled/packed/objects/peacekeepercomputer.png" > }, > "129" : { > "image" : "../../../../../tiled/packed/objects/officecomputer.png" tilesets\packed\objects-by-colonytag\human.json 1458c1458 < "//shortdescription" : "Station Console", --- > "//shortdescription" : "Space Station Console", tilesets\packed\objects-by-colonytag\industrial.json 83c83 < "//description" : "A pressurised cargo crate, designed to withstand the harsh conditions of space travel.", --- > "//description" : "A pressurised cargo crate, designed to withstand the conditions of space travel.", tilesets\packed\objects-by-colonytag\light.json 7c7 < "tilecount" : 360, --- > "tilecount" : 368, 2549a2550,2621 > "360" : { > "//description" : "A bright lamp post, most commonly seen at the Peacekeeper Stations.", > "//name" : "peacekeeperlamppost", > "//shortdescription" : "Peacekeeper Lamp Post", > "imagePositionX" : "0", > "imagePositionY" : "0", > "object" : "peacekeeperlamppost", > "tilesetDirection" : "right" > }, > "361" : { > "//description" : "A magenta street lamp post. Not the best colour for visibility, but it sure looks cool.", > "//name" : "neonlamppost", > "//shortdescription" : "Neon Lamp Post", > "imagePositionX" : "-16", > "imagePositionY" : "0", > "object" : "neonlamppost", > "tilesetDirection" : "right" > }, > "362" : { > "//description" : "This wall ornament glows with a bold magenta light.", > "//name" : "neontriangle", > "//shortdescription" : "Neon Triangle", > "imagePositionX" : "-8", > "imagePositionY" : "0", > "object" : "neontriangle", > "tilesetDirection" : "right" > }, > "363" : { > "//description" : "A magenta hologram of a palm tree.", > "//name" : "neonhologram", > "//shortdescription" : "Neon Hologram", > "imagePositionX" : "-32", > "imagePositionY" : "0", > "object" : "neonhologram", > "tilesetDirection" : "right" > }, > "364" : { > "//description" : "This chandelier is made of wrought-iron. It looks expensive.", > "//name" : "hangingguardian", > "//shortdescription" : "Hanging Guardian", > "imagePositionX" : "-32", > "imagePositionY" : "-40", > "object" : "hangingguardian", > "tilesetDirection" : "right" > }, > "365" : { > "//description" : "This wall ornament glows with a bold magenta light.", > "//name" : "neonpeacekeeperemblem", > "//shortdescription" : "Neon Peacekeeper Emblem", > "imagePositionX" : "-16", > "imagePositionY" : "-16", > "object" : "neonpeacekeeperemblem", > "tilesetDirection" : "right" > }, > "366" : { > "//description" : "A slick, understated magenta light.", > "//name" : "neonlight", > "//shortdescription" : "Neon Magenta Light", > "imagePositionX" : "-8", > "imagePositionY" : "0", > "object" : "neonlight", > "tilesetDirection" : "right" > }, > "367" : { > "//description" : "-todo-", > "//name" : "officelamp", > "//shortdescription" : "Office Desk Lamp", > "imagePositionX" : "-8", > "imagePositionY" : "0", > "object" : "officelamp", > "tilesetDirection" : "right" > }, 4027a4100,4123 > }, > "360" : { > "image" : "../../../../../tiled/packed/objects/peacekeeperlamppost.png" > }, > "361" : { > "image" : "../../../../../tiled/packed/objects/neonlamppost.png" > }, > "362" : { > "image" : "../../../../../tiled/packed/objects/neontriangle.png" > }, > "363" : { > "image" : "../../../../../tiled/packed/objects/neonhologram.png" > }, > "364" : { > "image" : "../../../../../tiled/packed/objects/hangingguardian.png" > }, > "365" : { > "image" : "../../../../../tiled/packed/objects/neonpeacekeeperemblem.png" > }, > "366" : { > "image" : "../../../../../tiled/packed/objects/neonlight.png" > }, > "367" : { > "image" : "../../../../../tiled/packed/objects/officelamp.png" tilesets\packed\objects-by-colonytag\mechanical.json 7c7 < "tilecount" : 70, --- > "tilecount" : 71, 611a612,620 > "70" : { > "//description" : "A vending machine that appears to cook and dispense only donuts.", > "//name" : "peacekeepervendingmachine", > "//shortdescription" : "Peacekeeper Vending Machine", > "imagePositionX" : "-16", > "imagePositionY" : "0", > "object" : "peacekeepervendingmachine", > "tilesetDirection" : "left" > }, 834a844,846 > }, > "70" : { > "image" : "../../../../../tiled/packed/objects/peacekeepervendingmachine.png" tilesets\packed\objects-by-colonytag\misc.json 7c7 < "tilecount" : 158, --- > "tilecount" : 165, 573a574,590 > "158" : { > "//description" : "This teleporter should get you back to the Peacekeeper HQ.", > "//name" : "peacekeeperteleporter", > "//shortdescription" : "Peacekeeper Teleporter", > "imagePositionX" : "-16", > "imagePositionY" : "0", > "object" : "peacekeeperteleporter" > }, > "159" : { > "//description" : "-todo-", > "//name" : "peacekeeperchair", > "//shortdescription" : "Peacekeeper Chair", > "imagePositionX" : "-8", > "imagePositionY" : "0", > "object" : "peacekeeperchair", > "tilesetDirection" : "right" > }, 581a599,643 > "160" : { > "//description" : "-todo-", > "//name" : "egyptianbed", > "//shortdescription" : "Egyptian Bed", > "imagePositionX" : "-24", > "imagePositionY" : "0", > "object" : "egyptianbed", > "tilesetDirection" : "right" > }, > "161" : { > "//description" : "-todo-", > "//name" : "egyptianchair", > "//shortdescription" : "Egyptian Chair", > "imagePositionX" : "-16", > "imagePositionY" : "0", > "object" : "egyptianchair", > "tilesetDirection" : "right" > }, > "162" : { > "//description" : "A teleportation platform that summmons a player's mech.", > "//name" : "mechplatform", > "//shortdescription" : "Mech Platform", > "imagePositionX" : "-24", > "imagePositionY" : "0", > "object" : "mechplatform", > "tilesetDirection" : "right" > }, > "163" : { > "//description" : "A tall antiquated device used for assisting in paperwork.", > "//name" : "officescanner", > "//shortdescription" : "Office Scanner", > "imagePositionX" : "-24", > "imagePositionY" : "0", > "object" : "officescanner", > "tilesetDirection" : "right" > }, > "164" : { > "//description" : "-todo-", > "//name" : "officestapler", > "//shortdescription" : "Office Stapler", > "imagePositionX" : "-8", > "imagePositionY" : "0", > "object" : "officestapler", > "tilesetDirection" : "right" > }, 1296c1358 < "//description" : "", --- > "//description" : "This screen displays a variety of propaganda messages from Big Ape.", 1528a1591,1596 > "158" : { > "image" : "../../../../../tiled/packed/objects/peacekeeperteleporter.png" > }, > "159" : { > "image" : "../../../../../tiled/packed/objects/peacekeeperchair.png" > }, 1530a1599,1613 > }, > "160" : { > "image" : "../../../../../tiled/packed/objects/egyptianbed.png" > }, > "161" : { > "image" : "../../../../../tiled/packed/objects/egyptianchair.png" > }, > "162" : { > "image" : "../../../../../tiled/packed/objects/mechplatform.png" > }, > "163" : { > "image" : "../../../../../tiled/packed/objects/officescanner.png" > }, > "164" : { > "image" : "../../../../../tiled/packed/objects/officestapler.png" tilesets\packed\objects-by-colonytag\pretty.json 7c7 < "tilecount" : 473, --- > "tilecount" : 477, 3637a3638,3671 > "473" : { > "//description" : "A cool painting of a timeless, hazy beach sunset.", > "//name" : "peacekeeperpainting", > "//shortdescription" : "Peacekeeper Painting", > "imagePositionX" : "-32", > "imagePositionY" : "-16", > "object" : "peacekeeperpainting", > "tilesetDirection" : "right" > }, > "474" : { > "//description" : "-todo-", > "//name" : "egyptiancrest", > "//shortdescription" : "Egyptian Crest", > "imagePositionX" : "-24", > "imagePositionY" : "-8", > "object" : "egyptiancrest", > "tilesetDirection" : "right" > }, > "475" : { > "//description" : "-todo-", > "//name" : "egyptianstatuette", > "//shortdescription" : "Egyptian Statuette", > "imagePositionX" : "-8", > "imagePositionY" : "0", > "object" : "egyptianstatuette" > }, > "476" : { > "//description" : "-todo-", > "//name" : "officenoticeboard", > "//shortdescription" : "Office Noticeboard", > "imagePositionX" : "-16", > "imagePositionY" : "-8", > "object" : "officenoticeboard" > }, 5386a5421,5432 > }, > "473" : { > "image" : "../../../../../tiled/packed/objects/peacekeeperpainting.png" > }, > "474" : { > "image" : "../../../../../tiled/packed/objects/egyptiancrest.png" > }, > "475" : { > "image" : "../../../../../tiled/packed/objects/egyptianstatuette.png" > }, > "476" : { > "image" : "../../../../../tiled/packed/objects/officenoticeboard.png" tilesets\packed\objects-by-colonytag\space.json 7c7 < "tilecount" : 1, --- > "tilecount" : 5, 17a18,53 > }, > "1" : { > "//description" : "A screen displaying a series of space-themed photographs.", > "//name" : "spaceslideshow", > "//shortdescription" : "Space Slideshow", > "imagePositionX" : "-32", > "imagePositionY" : "-16", > "object" : "spaceslideshow", > "tilesetDirection" : "right" > }, > "2" : { > "//description" : "A scientific telescope, perfect for observing the stars.", > "//name" : "telescope", > "//shortdescription" : "Astronomy Telescope", > "imagePositionX" : "-32", > "imagePositionY" : "0", > "object" : "telescope", > "tilesetDirection" : "right" > }, > "3" : { > "//description" : "A scientific telescope, perfect for observing the stars.", > "//name" : "telescope_orientation1", > "//shortdescription" : "Astronomy Telescope", > "imagePositionX" : "-24", > "imagePositionY" : "0", > "object" : "telescope", > "tilesetDirection" : "right" > }, > "4" : { > "//description" : "A panel that generates electricity from solar energy.", > "//name" : "solarpanel", > "//shortdescription" : "Solar Panel", > "imagePositionX" : "-16", > "imagePositionY" : "0", > "object" : "solarpanel", > "tilesetDirection" : "right" 22a59,70 > }, > "1" : { > "image" : "../../../../../tiled/packed/objects/spaceslideshow.png" > }, > "2" : { > "image" : "../../../../../tiled/packed/objects/telescope.png" > }, > "3" : { > "image" : "../../../../../tiled/packed/objects/telescope_orientation1.png" > }, > "4" : { > "image" : "../../../../../tiled/packed/objects/solarpanel.png" tilesets\packed\objects-by-colonytag\storage.json 7c7 < "tilecount" : 266, --- > "tilecount" : 269, 1596c1596 < "//description" : "A pressurised cargo crate, designed to withstand the harsh conditions of space travel.", --- > "//description" : "A pressurised cargo crate, designed to withstand the conditions of space travel.", 1646a1647,1673 > "266" : { > "//description" : "A metal chest with a glowing eye emblem on it.", > "//name" : "cultistchestlarge", > "//shortdescription" : "Cultist Chest", > "imagePositionX" : "-16", > "imagePositionY" : "0", > "object" : "cultistchestlarge", > "tilesetDirection" : "right" > }, > "267" : { > "//description" : "-todo-", > "//name" : "officedesk", > "//shortdescription" : "Office Desk", > "imagePositionX" : "-24", > "imagePositionY" : "0", > "object" : "officedesk", > "tilesetDirection" : "right" > }, > "268" : { > "//description" : "A modern metal cabinet with floor mounting brackets.", > "//name" : "officecabinet", > "//shortdescription" : "Office Cabinet", > "imagePositionX" : "-16", > "imagePositionY" : "0", > "object" : "officecabinet", > "tilesetDirection" : "right" > }, 2894a2922,2930 > }, > "266" : { > "image" : "../../../../../tiled/packed/objects/cultistchestlarge.png" > }, > "267" : { > "image" : "../../../../../tiled/packed/objects/officedesk.png" > }, > "268" : { > "image" : "../../../../../tiled/packed/objects/officecabinet.png" tilesets\packed\objects-by-colonytag\technology.json 13c13 < "//shortdescription" : "Station Console", --- > "//shortdescription" : "Space Station Console", tilesets\packed\objects-by-colonytag\wired.json 7c7 < "tilecount" : 176, --- > "tilecount" : 180, 752a753,788 > "176" : { > "//description" : "A panel that generates electricity from solar energy.", > "//name" : "solarpanel", > "//shortdescription" : "Solar Panel", > "imagePositionX" : "-16", > "imagePositionY" : "0", > "object" : "solarpanel", > "tilesetDirection" : "right" > }, > "177" : { > "//description" : "A numeric security keypad that requires a specific combination.", > "//name" : "keypad", > "//shortdescription" : "Numeric Keypad", > "imagePositionX" : "-8", > "imagePositionY" : "-8", > "object" : "keypad", > "tilesetDirection" : "right" > }, > "178" : { > "//description" : "An outdated metal computer. Standard issue for Peacekeeper research teams.", > "//name" : "peacekeepercomputer", > "//shortdescription" : "Peacekeeper Computer", > "imagePositionX" : "-16", > "imagePositionY" : "0", > "object" : "peacekeepercomputer", > "tilesetDirection" : "right" > }, > "179" : { > "//description" : "-todo-", > "//name" : "officecomputer", > "//shortdescription" : "Office Computer", > "imagePositionX" : "-16", > "imagePositionY" : "0", > "object" : "officecomputer", > "tilesetDirection" : "right" > }, 1796a1833,1844 > }, > "176" : { > "image" : "../../../../../tiled/packed/objects/solarpanel.png" > }, > "177" : { > "image" : "../../../../../tiled/packed/objects/keypad.png" > }, > "178" : { > "image" : "../../../../../tiled/packed/objects/peacekeepercomputer.png" > }, > "179" : { > "image" : "../../../../../tiled/packed/objects/officecomputer.png" tilesets\packed\objects-by-race\ancient.json 7c7 < "tilecount" : 162, --- > "tilecount" : 163, 631a632,640 > "162" : { > "//description" : "This chandelier is made of wrought-iron. It looks expensive.", > "//name" : "hangingguardian", > "//shortdescription" : "Hanging Guardian", > "imagePositionX" : "-32", > "imagePositionY" : "-40", > "object" : "hangingguardian", > "tilesetDirection" : "right" > }, 1659a1669,1671 > }, > "162" : { > "image" : "../../../../../tiled/packed/objects/hangingguardian.png" tilesets\packed\objects-by-race\apex.json 2332c2332 < "//description" : "", --- > "//description" : "This screen displays a variety of propaganda messages from Big Ape.", tilesets\packed\objects-by-race\avian.json 744c744 < "//description" : "The Avian flag. Use ^green;[E] to bookmark a teleportation location.", --- > "//description" : "The Avian flag. Use ^green;[E]^white; to bookmark a teleportation location.", 753c753 < "//description" : "The Avian flag. Use ^green;[E] to bookmark a teleportation location.", --- > "//description" : "The Avian flag. Use ^green;[E]^white; to bookmark a teleportation location.", tilesets\packed\objects-by-race\generic.json 7c7 < "tilecount" : 1925, --- > "tilecount" : 1971, 7656c7656 < "//description" : "A pressurised cargo crate, designed to withstand the harsh conditions of space travel.", --- > "//description" : "A pressurised cargo crate, designed to withstand the conditions of space travel.", 8560c8560 < "//shortdescription" : "Station Console", --- > "//shortdescription" : "Space Station Console", 8708a8709,8752 > "1925" : { > "//description" : "A panel that generates electricity from solar energy.", > "//name" : "solarpanel", > "//shortdescription" : "Solar Panel", > "imagePositionX" : "-16", > "imagePositionY" : "0", > "object" : "solarpanel", > "tilesetDirection" : "right" > }, > "1926" : { > "//description" : "A noticeboard where bounties for notorious criminals are posted!", > "//name" : "bountyboard", > "//shortdescription" : "Bounty Board", > "imagePositionX" : "-24", > "imagePositionY" : "0", > "object" : "bountyboard" > }, > "1927" : { > "//description" : "-todo-", > "//name" : "peacekeeperdoor", > "//shortdescription" : "Peacekeeper Door", > "imagePositionX" : "-24", > "imagePositionY" : "0", > "object" : "peacekeeperdoor", > "tilesetDirection" : "right" > }, > "1928" : { > "//description" : "A golden wall plaque, embossed with the Peacekeeper's emblem.", > "//name" : "peacekeeperemblem", > "//shortdescription" : "Peacekeeper Emblem", > "imagePositionX" : "-16", > "imagePositionY" : "-16", > "object" : "peacekeeperemblem", > "tilesetDirection" : "right" > }, > "1929" : { > "//description" : "A jumbled collection of leads and evidence, used to track criminals.", > "//name" : "peacekeepernotes", > "//shortdescription" : "Peacekeeper Notes", > "imagePositionX" : "-24", > "imagePositionY" : "-16", > "object" : "peacekeepernotes", > "tilesetDirection" : "right" > }, 8717a8762,8849 > "1930" : { > "//description" : "A round desk, made for the Peacekeeper's HQ.", > "//name" : "peacekeeperdesk", > "//shortdescription" : "Peacekeeper Desk", > "imagePositionX" : "-24", > "imagePositionY" : "0", > "object" : "peacekeeperdesk", > "tilesetDirection" : "right" > }, > "1931" : { > "//description" : "A fresh mug of coffee. It seems perpetually steaming hot.", > "//name" : "peacekeepermug", > "//shortdescription" : "Peacekeeper Mug", > "imagePositionX" : "0", > "imagePositionY" : "0", > "object" : "peacekeepermug", > "tilesetDirection" : "right" > }, > "1932" : { > "//description" : "This teleporter should get you back to the Peacekeeper HQ.", > "//name" : "peacekeeperteleporter", > "//shortdescription" : "Peacekeeper Teleporter", > "imagePositionX" : "-16", > "imagePositionY" : "0", > "object" : "peacekeeperteleporter" > }, > "1933" : { > "//description" : "-todo-", > "//name" : "peacekeeperstore", > "//shortdescription" : "Peacekeeper Store", > "imagePositionX" : "-24", > "imagePositionY" : "-24", > "object" : "peacekeeperstore" > }, > "1934" : { > "//description" : "A bright lamp post, most commonly seen at the Peacekeeper Stations.", > "//name" : "peacekeeperlamppost", > "//shortdescription" : "Peacekeeper Lamp Post", > "imagePositionX" : "0", > "imagePositionY" : "0", > "object" : "peacekeeperlamppost", > "tilesetDirection" : "right" > }, > "1935" : { > "//description" : "A vending machine that appears to cook and dispense only donuts.", > "//name" : "peacekeepervendingmachine", > "//shortdescription" : "Peacekeeper Vending Machine", > "imagePositionX" : "-16", > "imagePositionY" : "0", > "object" : "peacekeepervendingmachine", > "tilesetDirection" : "left" > }, > "1936" : { > "//description" : "-todo-", > "//name" : "peacekeeperchair", > "//shortdescription" : "Peacekeeper Chair", > "imagePositionX" : "-8", > "imagePositionY" : "0", > "object" : "peacekeeperchair", > "tilesetDirection" : "right" > }, > "1937" : { > "//description" : "-todo-", > "//name" : "peacekeepertable", > "//shortdescription" : "Peacekeeper Table", > "imagePositionX" : "-16", > "imagePositionY" : "0", > "object" : "peacekeepertable", > "tilesetDirection" : "right" > }, > "1938" : { > "//description" : "A poster with some faded photographs of criminals printed on it.", > "//name" : "peacekeeperposter1", > "//shortdescription" : "Peacekeeper Tall Poster", > "imagePositionX" : "-24", > "imagePositionY" : "-16", > "object" : "peacekeeperposter1", > "tilesetDirection" : "right" > }, > "1939" : { > "//description" : "A cool painting of a timeless, hazy beach sunset.", > "//name" : "peacekeeperpainting", > "//shortdescription" : "Peacekeeper Painting", > "imagePositionX" : "-32", > "imagePositionY" : "-16", > "object" : "peacekeeperpainting", > "tilesetDirection" : "right" > }, 8725a8858,8945 > "1940" : { > "//description" : "-todo-", > "//name" : "peacekeeperfurnishings", > "//shortdescription" : "Peacekeeper Furnishings", > "imagePositionX" : "-24", > "imagePositionY" : "0", > "object" : "peacekeeperfurnishings", > "tilesetDirection" : "right" > }, > "1941" : { > "//description" : "A poster with some faded photographs of criminals printed on it.", > "//name" : "peacekeeperposter2", > "//shortdescription" : "Peacekeeper Wide Poster", > "imagePositionX" : "-24", > "imagePositionY" : "-16", > "object" : "peacekeeperposter2", > "tilesetDirection" : "right" > }, > "1942" : { > "//description" : "A numeric security keypad that requires a specific combination.", > "//name" : "keypad", > "//shortdescription" : "Numeric Keypad", > "imagePositionX" : "-8", > "imagePositionY" : "-8", > "object" : "keypad", > "tilesetDirection" : "right" > }, > "1943" : { > "//description" : "-todo-", > "//name" : "egyptianbed", > "//shortdescription" : "Egyptian Bed", > "imagePositionX" : "-24", > "imagePositionY" : "0", > "object" : "egyptianbed", > "tilesetDirection" : "right" > }, > "1944" : { > "//description" : "-todo-", > "//name" : "egyptiantable", > "//shortdescription" : "Egyptian Table", > "imagePositionX" : "-24", > "imagePositionY" : "0", > "object" : "egyptiantable", > "tilesetDirection" : "right" > }, > "1945" : { > "//description" : "-todo-", > "//name" : "egyptiancrest", > "//shortdescription" : "Egyptian Crest", > "imagePositionX" : "-24", > "imagePositionY" : "-8", > "object" : "egyptiancrest", > "tilesetDirection" : "right" > }, > "1946" : { > "//description" : "Extracts ores from the ground", > "//name" : "extractordrill", > "//shortdescription" : "Extractor Drill", > "imagePositionX" : "-16", > "imagePositionY" : "0", > "object" : "extractordrill" > }, > "1947" : { > "//description" : "-todo-", > "//name" : "egyptianpillar", > "//shortdescription" : "Egyptian Pillar", > "imagePositionX" : "-16", > "imagePositionY" : "0", > "object" : "egyptianpillar" > }, > "1948" : { > "//description" : "-todo-", > "//name" : "egyptianchair", > "//shortdescription" : "Egyptian Chair", > "imagePositionX" : "-16", > "imagePositionY" : "0", > "object" : "egyptianchair", > "tilesetDirection" : "right" > }, > "1949" : { > "//description" : "A rusty wall plaque, embossed with the Peacekeeper's emblem.", > "//name" : "peacekeeperemblem2", > "//shortdescription" : "Peacekeeper Rusty Emblem", > "imagePositionX" : "-16", > "imagePositionY" : "-16", > "object" : "peacekeeperemblem2", > "tilesetDirection" : "right" > }, 8734a8955,9041 > "1950" : { > "//description" : "-todo-", > "//name" : "egyptianstatuette", > "//shortdescription" : "Egyptian Statuette", > "imagePositionX" : "-8", > "imagePositionY" : "0", > "object" : "egyptianstatuette" > }, > "1951" : { > "//description" : "An outdated metal computer. Standard issue for Peacekeeper research teams.", > "//name" : "peacekeepercomputer", > "//shortdescription" : "Peacekeeper Computer", > "imagePositionX" : "-16", > "imagePositionY" : "0", > "object" : "peacekeepercomputer", > "tilesetDirection" : "right" > }, > "1952" : { > "//description" : "A magenta street lamp post. Not the best colour for visibility, but it sure looks cool.", > "//name" : "neonlamppost", > "//shortdescription" : "Neon Lamp Post", > "imagePositionX" : "-16", > "imagePositionY" : "0", > "object" : "neonlamppost", > "tilesetDirection" : "right" > }, > "1953" : { > "//description" : "This wall ornament glows with a bold magenta light.", > "//name" : "neontriangle", > "//shortdescription" : "Neon Triangle", > "imagePositionX" : "-8", > "imagePositionY" : "0", > "object" : "neontriangle", > "tilesetDirection" : "right" > }, > "1954" : { > "//description" : "A magenta hologram of a palm tree.", > "//name" : "neonhologram", > "//shortdescription" : "Neon Hologram", > "imagePositionX" : "-32", > "imagePositionY" : "0", > "object" : "neonhologram", > "tilesetDirection" : "right" > }, > "1955" : { > "//description" : "A teleportation platform that summmons a player's mech.", > "//name" : "mechplatform", > "//shortdescription" : "Mech Platform", > "imagePositionX" : "-24", > "imagePositionY" : "0", > "object" : "mechplatform", > "tilesetDirection" : "right" > }, > "1956" : { > "//description" : "This wall ornament glows with a bold magenta light.", > "//name" : "neonpeacekeeperemblem", > "//shortdescription" : "Neon Peacekeeper Emblem", > "imagePositionX" : "-16", > "imagePositionY" : "-16", > "object" : "neonpeacekeeperemblem", > "tilesetDirection" : "right" > }, > "1957" : { > "//description" : "A slick, understated magenta light.", > "//name" : "neonlight", > "//shortdescription" : "Neon Magenta Light", > "imagePositionX" : "-8", > "imagePositionY" : "0", > "object" : "neonlight", > "tilesetDirection" : "right" > }, > "1958" : { > "//description" : "-todo-", > "//name" : "peacekeeperstore2", > "//shortdescription" : "Peacekeeper Store", > "imagePositionX" : "-24", > "imagePositionY" : "-24", > "object" : "peacekeeperstore2" > }, > "1959" : { > "//description" : "-todo-", > "//name" : "peacekeeperstore3", > "//shortdescription" : "Peacekeeper Store", > "imagePositionX" : "-24", > "imagePositionY" : "-24", > "object" : "peacekeeperstore3" > }, 8743a9051,9138 > "1960" : { > "//description" : "-todo-", > "//name" : "neonstore", > "//shortdescription" : "Neon Store", > "imagePositionX" : "-24", > "imagePositionY" : "-24", > "object" : "neonstore" > }, > "1961" : { > "//description" : "-todo-", > "//name" : "officecomputer", > "//shortdescription" : "Office Computer", > "imagePositionX" : "-16", > "imagePositionY" : "0", > "object" : "officecomputer", > "tilesetDirection" : "right" > }, > "1962" : { > "//description" : "-todo-", > "//name" : "officetable", > "//shortdescription" : "Office Table", > "imagePositionX" : "-24", > "imagePositionY" : "0", > "object" : "officetable", > "tilesetDirection" : "right" > }, > "1963" : { > "//description" : "-todo-", > "//name" : "officeserver", > "//shortdescription" : "Office Server", > "imagePositionX" : "-16", > "imagePositionY" : "0", > "object" : "officeserver", > "tilesetDirection" : "right" > }, > "1964" : { > "//description" : "A tall antiquated device used for assisting in paperwork.", > "//name" : "officescanner", > "//shortdescription" : "Office Scanner", > "imagePositionX" : "-24", > "imagePositionY" : "0", > "object" : "officescanner", > "tilesetDirection" : "right" > }, > "1965" : { > "//description" : "-todo-", > "//name" : "officedesk", > "//shortdescription" : "Office Desk", > "imagePositionX" : "-24", > "imagePositionY" : "0", > "object" : "officedesk", > "tilesetDirection" : "right" > }, > "1966" : { > "//description" : "A modern metal cabinet with floor mounting brackets.", > "//name" : "officecabinet", > "//shortdescription" : "Office Cabinet", > "imagePositionX" : "-16", > "imagePositionY" : "0", > "object" : "officecabinet", > "tilesetDirection" : "right" > }, > "1967" : { > "//description" : "-todo-", > "//name" : "officelamp", > "//shortdescription" : "Office Desk Lamp", > "imagePositionX" : "-8", > "imagePositionY" : "0", > "object" : "officelamp", > "tilesetDirection" : "right" > }, > "1968" : { > "//description" : "-todo-", > "//name" : "officenoticeboard", > "//shortdescription" : "Office Noticeboard", > "imagePositionX" : "-16", > "imagePositionY" : "-8", > "object" : "officenoticeboard" > }, > "1969" : { > "//description" : "-todo-", > "//name" : "officestapler", > "//shortdescription" : "Office Stapler", > "imagePositionX" : "-8", > "imagePositionY" : "0", > "object" : "officestapler", > "tilesetDirection" : "right" > }, 8752a9148,9156 > "1970" : { > "//description" : "A poster advertising the Peacekeeper Initiative.", > "//name" : "outpostpeacekeeperposter", > "//shortdescription" : "Outpost Peacekeeper Poster", > "imagePositionX" : "-8", > "imagePositionY" : "-16", > "object" : "outpostpeacekeeperposter", > "tilesetDirection" : "right" > }, 19312a19717,19731 > "1925" : { > "image" : "../../../../../tiled/packed/objects/solarpanel.png" > }, > "1926" : { > "image" : "../../../../../tiled/packed/objects/bountyboard.png" > }, > "1927" : { > "image" : "../../../../../tiled/packed/objects/peacekeeperdoor.png" > }, > "1928" : { > "image" : "../../../../../tiled/packed/objects/peacekeeperemblem.png" > }, > "1929" : { > "image" : "../../../../../tiled/packed/objects/peacekeepernotes.png" > }, 19315a19735,19764 > "1930" : { > "image" : "../../../../../tiled/packed/objects/peacekeeperdesk.png" > }, > "1931" : { > "image" : "../../../../../tiled/packed/objects/peacekeepermug.png" > }, > "1932" : { > "image" : "../../../../../tiled/packed/objects/peacekeeperteleporter.png" > }, > "1933" : { > "image" : "../../../../../tiled/packed/objects/peacekeeperstore.png" > }, > "1934" : { > "image" : "../../../../../tiled/packed/objects/peacekeeperlamppost.png" > }, > "1935" : { > "image" : "../../../../../tiled/packed/objects/peacekeepervendingmachine.png" > }, > "1936" : { > "image" : "../../../../../tiled/packed/objects/peacekeeperchair.png" > }, > "1937" : { > "image" : "../../../../../tiled/packed/objects/peacekeepertable.png" > }, > "1938" : { > "image" : "../../../../../tiled/packed/objects/peacekeeperposter1.png" > }, > "1939" : { > "image" : "../../../../../tiled/packed/objects/peacekeeperpainting.png" > }, 19318a19768,19797 > "1940" : { > "image" : "../../../../../tiled/packed/objects/peacekeeperfurnishings.png" > }, > "1941" : { > "image" : "../../../../../tiled/packed/objects/peacekeeperposter2.png" > }, > "1942" : { > "image" : "../../../../../tiled/packed/objects/keypad.png" > }, > "1943" : { > "image" : "../../../../../tiled/packed/objects/egyptianbed.png" > }, > "1944" : { > "image" : "../../../../../tiled/packed/objects/egyptiantable.png" > }, > "1945" : { > "image" : "../../../../../tiled/packed/objects/egyptiancrest.png" > }, > "1946" : { > "image" : "../../../../../tiled/packed/objects/extractordrill.png" > }, > "1947" : { > "image" : "../../../../../tiled/packed/objects/egyptianpillar.png" > }, > "1948" : { > "image" : "../../../../../tiled/packed/objects/egyptianchair.png" > }, > "1949" : { > "image" : "../../../../../tiled/packed/objects/peacekeeperemblem2.png" > }, 19321a19801,19830 > "1950" : { > "image" : "../../../../../tiled/packed/objects/egyptianstatuette.png" > }, > "1951" : { > "image" : "../../../../../tiled/packed/objects/peacekeepercomputer.png" > }, > "1952" : { > "image" : "../../../../../tiled/packed/objects/neonlamppost.png" > }, > "1953" : { > "image" : "../../../../../tiled/packed/objects/neontriangle.png" > }, > "1954" : { > "image" : "../../../../../tiled/packed/objects/neonhologram.png" > }, > "1955" : { > "image" : "../../../../../tiled/packed/objects/mechplatform.png" > }, > "1956" : { > "image" : "../../../../../tiled/packed/objects/neonpeacekeeperemblem.png" > }, > "1957" : { > "image" : "../../../../../tiled/packed/objects/neonlight.png" > }, > "1958" : { > "image" : "../../../../../tiled/packed/objects/peacekeeperstore2.png" > }, > "1959" : { > "image" : "../../../../../tiled/packed/objects/peacekeeperstore3.png" > }, 19324a19834,19863 > "1960" : { > "image" : "../../../../../tiled/packed/objects/neonstore.png" > }, > "1961" : { > "image" : "../../../../../tiled/packed/objects/officecomputer.png" > }, > "1962" : { > "image" : "../../../../../tiled/packed/objects/officetable.png" > }, > "1963" : { > "image" : "../../../../../tiled/packed/objects/officeserver.png" > }, > "1964" : { > "image" : "../../../../../tiled/packed/objects/officescanner.png" > }, > "1965" : { > "image" : "../../../../../tiled/packed/objects/officedesk.png" > }, > "1966" : { > "image" : "../../../../../tiled/packed/objects/officecabinet.png" > }, > "1967" : { > "image" : "../../../../../tiled/packed/objects/officelamp.png" > }, > "1968" : { > "image" : "../../../../../tiled/packed/objects/officenoticeboard.png" > }, > "1969" : { > "image" : "../../../../../tiled/packed/objects/officestapler.png" > }, 19326a19866,19868 > }, > "1970" : { > "image" : "../../../../../tiled/packed/objects/outpostpeacekeeperposter.png" tilesets\packed\objects-by-race\human.json 7c7 < "tilecount" : 281, --- > "tilecount" : 287, 1738a1739,1792 > "281" : { > "//description" : "A worn wall banner, spraypainted with the Ocassus cult emblem.", > "//name" : "cultistbannerlarge", > "//shortdescription" : "Cultist Banner", > "imagePositionX" : "-16", > "imagePositionY" : "-40", > "object" : "cultistbannerlarge", > "tilesetDirection" : "right" > }, > "282" : { > "//description" : "A worn wall banner, spraypainted with the Ocassus cult emblem.", > "//name" : "cultistbannerlarge_orientation2", > "//shortdescription" : "Cultist Banner", > "imagePositionX" : "-16", > "imagePositionY" : "-40", > "object" : "cultistbannerlarge", > "tilesetDirection" : "right" > }, > "283" : { > "//description" : "A worn wall banner, spraypainted with the Ocassus cult emblem.", > "//name" : "cultistbannerlarge_orientation3", > "//shortdescription" : "Cultist Banner", > "imagePositionX" : "-16", > "imagePositionY" : "-40", > "object" : "cultistbannerlarge", > "tilesetDirection" : "right" > }, > "284" : { > "//description" : "A crudely-made airlock door.", > "//name" : "cultistairlockdoor", > "//shortdescription" : "Cultist Airlock Door", > "imagePositionX" : "-8", > "imagePositionY" : "0", > "object" : "cultistairlockdoor", > "tilesetDirection" : "right" > }, > "285" : { > "//description" : "A crudely-made airlock hatch.", > "//name" : "cultistairlockhatch", > "//shortdescription" : "Cultist Airlock Hatch", > "imagePositionX" : "-24", > "imagePositionY" : "-8", > "object" : "cultistairlockhatch", > "tilesetDirection" : "right" > }, > "286" : { > "//description" : "A metal chest with a glowing eye emblem on it.", > "//name" : "cultistchestlarge", > "//shortdescription" : "Cultist Chest", > "imagePositionX" : "-16", > "imagePositionY" : "0", > "object" : "cultistchestlarge", > "tilesetDirection" : "right" > }, 1893c1947 < "//description" : "The Avian flag. Use ^green;[E] to bookmark a teleportation location.", --- > "//description" : "The Avian flag. Use ^green;[E]^white; to bookmark a teleportation location.", 1902c1956 < "//description" : "The Avian flag. Use ^green;[E] to bookmark a teleportation location.", --- > "//description" : "The Avian flag. Use ^green;[E]^white; to bookmark a teleportation location.", 3023a3078,3095 > }, > "281" : { > "image" : "../../../../../tiled/packed/objects/cultistbannerlarge.png" > }, > "282" : { > "image" : "../../../../../tiled/packed/objects/cultistbannerlarge_orientation2.png" > }, > "283" : { > "image" : "../../../../../tiled/packed/objects/cultistbannerlarge_orientation3.png" > }, > "284" : { > "image" : "../../../../../tiled/packed/objects/cultistairlockdoor.png" > }, > "285" : { > "image" : "../../../../../tiled/packed/objects/cultistairlockhatch.png" > }, > "286" : { > "image" : "../../../../../tiled/packed/objects/cultistchestlarge.png" tilesets\packed\objects-by-race\novakid.json 7c7 < "tilecount" : 63, --- > "tilecount" : 64, 537a538,546 > "63" : { > "//description" : "A jumbled collection of leads and evidence, used to track criminals.", > "//name" : "peacekeepernotes", > "//shortdescription" : "Peacekeeper Notes", > "imagePositionX" : "-24", > "imagePositionY" : "-16", > "object" : "peacekeepernotes", > "tilesetDirection" : "right" > }, 742a752,754 > }, > "63" : { > "image" : "../../../../../tiled/packed/objects/peacekeepernotes.png" tilesets\packed\objects-by-type\container.json 7c7 < "tilecount" : 282, --- > "tilecount" : 285, 1697c1697 < "//description" : "A pressurised cargo crate, designed to withstand the harsh conditions of space travel.", --- > "//description" : "A pressurised cargo crate, designed to withstand the conditions of space travel.", 1756a1757,1783 > "282" : { > "//description" : "A metal chest with a glowing eye emblem on it.", > "//name" : "cultistchestlarge", > "//shortdescription" : "Cultist Chest", > "imagePositionX" : "-16", > "imagePositionY" : "0", > "object" : "cultistchestlarge", > "tilesetDirection" : "right" > }, > "283" : { > "//description" : "-todo-", > "//name" : "officedesk", > "//shortdescription" : "Office Desk", > "imagePositionX" : "-24", > "imagePositionY" : "0", > "object" : "officedesk", > "tilesetDirection" : "right" > }, > "284" : { > "//description" : "A modern metal cabinet with floor mounting brackets.", > "//name" : "officecabinet", > "//shortdescription" : "Office Cabinet", > "imagePositionX" : "-16", > "imagePositionY" : "0", > "object" : "officecabinet", > "tilesetDirection" : "right" > }, 3006a3034,3042 > }, > "282" : { > "image" : "../../../../../tiled/packed/objects/cultistchestlarge.png" > }, > "283" : { > "image" : "../../../../../tiled/packed/objects/officedesk.png" > }, > "284" : { > "image" : "../../../../../tiled/packed/objects/officecabinet.png" tilesets\packed\objects-by-type\loungeable.json 7c7 < "tilecount" : 278, --- > "tilecount" : 281, 1748a1749,1766 > "278" : { > "//description" : "-todo-", > "//name" : "peacekeeperchair", > "//shortdescription" : "Peacekeeper Chair", > "imagePositionX" : "-8", > "imagePositionY" : "0", > "object" : "peacekeeperchair", > "tilesetDirection" : "right" > }, > "279" : { > "//description" : "-todo-", > "//name" : "egyptianbed", > "//shortdescription" : "Egyptian Bed", > "imagePositionX" : "-24", > "imagePositionY" : "0", > "object" : "egyptianbed", > "tilesetDirection" : "right" > }, 1757a1776,1784 > "280" : { > "//description" : "-todo-", > "//name" : "egyptianchair", > "//shortdescription" : "Egyptian Chair", > "imagePositionX" : "-16", > "imagePositionY" : "0", > "object" : "egyptianchair", > "tilesetDirection" : "right" > }, 3013a3041,3046 > "278" : { > "image" : "../../../../../tiled/packed/objects/peacekeeperchair.png" > }, > "279" : { > "image" : "../../../../../tiled/packed/objects/egyptianbed.png" > }, 3015a3049,3051 > }, > "280" : { > "image" : "../../../../../tiled/packed/objects/egyptianchair.png" tilesets\packed\objects-by-type\teleporter.json 7c7 < "tilecount" : 26, --- > "tilecount" : 27, 36c36 < "//description" : "The Avian flag. Use ^green;[E] to bookmark a teleportation location.", --- > "//description" : "The Avian flag. Use ^green;[E]^white; to bookmark a teleportation location.", 45c45 < "//description" : "The Avian flag. Use ^green;[E] to bookmark a teleportation location.", --- > "//description" : "The Avian flag. Use ^green;[E]^white; to bookmark a teleportation location.", 170a171,178 > "26" : { > "//description" : "This teleporter should get you back to the Peacekeeper HQ.", > "//name" : "peacekeeperteleporter", > "//shortdescription" : "Peacekeeper Teleporter", > "imagePositionX" : "-16", > "imagePositionY" : "0", > "object" : "peacekeeperteleporter" > }, 286a295,297 > }, > "26" : { > "image" : "../../../../../tiled/packed/objects/peacekeeperteleporter.png" treasure\common.treasurepools 1410a1411 > {"weight" : 0.0003, "item" : [ "grouchohead", 1]}, 1459c1460,1462 < {"weight" : 0.0001, "item" : [ "doghathead", 1]} --- > {"weight" : 0.0001, "item" : [ "doghathead", 1]}, > {"weight" : 0.0001, "item" : [ "sheephead", 1]}, > {"weight" : 0.0001, "item" : [ "pharaohhead", 1]} vehicles\hoverbike\hoverbike.animation 2,5d1 < "globalTagDefaults" : { < "colour" : "" < }, < 8,9d3 < < 13d6 < 19,20c12 < }, < --- > }, 26,27c18 < }, < --- > }, 29d19 < 35,36c25 < }, < --- > }, 42,43c31 < }, < --- > }, 45d32 < 48,49d34 < < 54d38 < 60d43 < 63d45 < 68d49 < 74d54 < 77d56 < 82d60 < 88d65 < 91,92c68 < < "headlights" : { --- > "headlights" : { 96d71 < 100,101d74 < < 105,106d77 < < 116d86 < 120d89 < 126d94 < 132d99 < 138d104 < 142d107 < 146d110 < 161d124 < 163d125 < 179d140 < 185d145 < 189d148 < 196d154 < 204d161 < 206d162 < 208d163 < 219,220d173 < < 224,225d176 < < 236,237d186 < < 241d189 < 245,247c193 < < < "lights" : { --- > "lights" : { 254d199 < 256d200 < 258d201 < 263d205 < 273d214 < 281d221 < 292,293d231 < < 302d239 < 308d244 < 315,316d250 < < 337,338d270 < < 340a273,275 > "globalTagDefaults" : { > "colour" : "" > }, 350d284 < 355c289 < "particles" : [{ "particle" : "hoverbikethrust"}] --- > "particles" : [ { "particle" : "hoverbikethrust"} ] 357d290 < 362c295 < "particles" : [{ "particle" : "hoverbikethrust"}] --- > "particles" : [ { "particle" : "hoverbikethrust"} ] 364d296 < 369c301 < "particles" : [{ "particle" : "hoverbikedownthrust"}] --- > "particles" : [ { "particle" : "hoverbikedownthrust"} ] 376c308 < "particles" : [{ "particle" : "hoverbikedownthrust"}] --- > "particles" : [ { "particle" : "hoverbikedownthrust"} ] 378,379d309 < < 384c314 < "particles" : [{ "particle" : "burningvehiclesmokefront"}] --- > "particles" : [ { "particle" : "burningvehiclesmokefront"} ] 386d315 < 391,395c320,325 < "particles" : [ { "particle" : "burningdust"}, < { "particle" : "campfireflames"}, < { "particle" : "fireshard"}, < { "particle" : "burningvehiclesmokeback"}] < --- > "particles" : [ > { "particle" : "burningdust"}, > { "particle" : "campfireflames"}, > { "particle" : "fireshard"}, > { "particle" : "burningvehiclesmokeback"} > ] 397d326 < 403,404c332,335 < "particles" : [{ "particle" : "burningvehiclesmokefront"}, < { "particle" : "fireshard"}] --- > "particles" : [ > { "particle" : "burningvehiclesmokefront"}, > { "particle" : "fireshard"} > ] 430,460c361,391 < "collisionNotification" : [ "/sfx/tech/hoverbike_bump1.ogg", < "/sfx/tech/hoverbike_bump2.ogg", < "/sfx/tech/hoverbike_bump3.ogg" ], < < "collisionDamage" : ["/sfx/melee/bite_robotic1.ogg"], < < < "changeDamageState" : [ "/sfx/gun/grenadeblast_small_fire1.ogg", < "/sfx/gun/grenadeblast_small_fire2.ogg", < "/sfx/gun/grenadeblast_small_fire3.ogg" ], < < "explode" : [ "/sfx/gun/grenadeblast_small_fire1.ogg", < "/sfx/gun/grenadeblast_small_fire2.ogg", < "/sfx/gun/grenadeblast_small_fire3.ogg" ], < < < "engineStart" : ["/sfx/tools/teleport_up.ogg"], < < "engineLoop" : ["/sfx/tech/hoverbike_drive_loop.ogg"], < < "engineStartDamaged" : ["/sfx/tools/teleport_up.ogg"], < < "engineLoopDamaged" : ["/sfx/tech/hoverbike_idle_loop.ogg"], < < "damageIntermittent" : [ "/sfx/gun/grenadeblast_small_fire1.ogg", < "/sfx/gun/grenadeblast_small_fire2.ogg", < "/sfx/gun/grenadeblast_small_fire3.ogg" ], < < "hornLoop" : ["/sfx/tech/honk.ogg"], < "headlightSwitchOn" : ["/sfx/objects/floodlights_on.ogg"], < "headlightSwitchOff" : ["/sfx/objects/floodlights_off.ogg"], --- > "collisionNotification" : [ > "/sfx/tech/hoverbike_bump1.ogg", > "/sfx/tech/hoverbike_bump2.ogg", > "/sfx/tech/hoverbike_bump3.ogg" > ], > "collisionDamage" : [ "/sfx/melee/bite_robotic1.ogg" ], > "changeDamageState" : [ > "/sfx/gun/grenadeblast_small_fire1.ogg", > "/sfx/gun/grenadeblast_small_fire2.ogg", > "/sfx/gun/grenadeblast_small_fire3.ogg" > ], > > "explode" : [ > "/sfx/gun/grenadeblast_small_fire1.ogg", > "/sfx/gun/grenadeblast_small_fire2.ogg", > "/sfx/gun/grenadeblast_small_fire3.ogg" > ], > > "engineStart" : [ "/sfx/tools/teleport_up.ogg" ], > "engineLoop" : [ "/sfx/tech/hoverbike_drive_loop.ogg" ], > "engineStartDamaged" : [ "/sfx/tools/teleport_up.ogg" ], > "engineLoopDamaged" : [ "/sfx/tech/hoverbike_idle_loop.ogg" ], > "damageIntermittent" : [ > "/sfx/gun/grenadeblast_small_fire1.ogg", > "/sfx/gun/grenadeblast_small_fire2.ogg", > "/sfx/gun/grenadeblast_small_fire3.ogg" > ], > > "hornLoop" : [ "/sfx/tech/honk.ogg" ], > "headlightSwitchOn" : [ "/sfx/objects/floodlights_on.ogg" ], > "headlightSwitchOff" : [ "/sfx/objects/floodlights_off.ogg" ], 462c393 < "returnvehicle" : ["/sfx/tech/vehicle_disappear1.ogg"] --- > "returnvehicle" : [ "/sfx/tech/vehicle_disappear1.ogg" ] vehicles\modularmech\mechparts_body.config 508a509,530 > "peacekeeper" : { > "stats" : { > "energy" : 5, > "protection" : 7 > }, > "partParameters" : { > "hazardImmunities" : ["biomeradiation", "biomecold", "biomeheat"] > }, > "partImages" : { > "bodyBack" : "body/peacekeeper_back.png", > "bodyFront" : "body/peacekeeper_front.png", > "bodyFullbright" : "body/peacekeeper_fullbright.png" > }, > "defaultPrimaryColors" : ["818c92", "626c71", "4e575b", "323739"], > "defaultSecondaryColors" : ["ffffa7", "e2c344", "a46e06", "642f00"], > "animationCustom" : { > "animatedParts" : { "parts" : { "bodyFront" : { "properties" : { > "sitPosition" : [0.65, 0.28] > }}}} > } > }, > vehicles\modularmech\armscripts\beamarm.lua 1,128c1,129 < require "/vehicles/modularmech/armscripts/base.lua" < < BeamArm = MechArm:extend() < < function BeamArm:init() < self.state = FSM:new() < end < < function BeamArm:update(dt) < if self.state.state then < self.state:update() < end < < if not self.state.state then < if self.isFiring then < self.state:set(self.windupState, self) < end < end < < if self.state.state then < self.bobLocked = true < else < animator.setAnimationState(self.armName, "idle") < self.bobLocked = false < end < end < < function BeamArm:windupState() < local stateTimer = self.windupTime < < animator.setAnimationState(self.armName, "windup") < animator.playSound(self.armName .. "Windup") < < while stateTimer > 0 do < animator.rotateTransformationGroup(self.armName, self.aimAngle, self.shoulderOffset) < < local dt = script.updateDt() < stateTimer = stateTimer - dt < coroutine.yield() < end < < if self.isFiring then < self.state:set(self.fireState, self) < else < self.state:set(self.winddownState, self) < animator.playSound(self.armName .. "WinddownNoFire") < end < end < < function BeamArm:fireState() < local stateTimer = self.fireTime < < animator.rotateTransformationGroup(self.armName, self.aimAngle, self.shoulderOffset) < < local endPoint, beamCollision, beamLength = self:updateBeam() < < animator.playSound(self.armName .. "Fire") < animator.setParticleEmitterBurstCount(self.armName .. "Beam", math.ceil(self.beamParticleDensity * beamLength)) < animator.burstParticleEmitter(self.armName .. "Beam") < animator.setAnimationState(self.armName .. "Beam", "fire", true) < < vehicle.setDamageSourceEnabled(self.armName .. "Beam", true) < < self.aimLocked = self.lockAim < < if beamCollision and self.beamTileDamage > 0 then < local maximumEndPoint = vec2.add(self.firePosition, vec2.mul(self.aimVector, self.beamLength)) < local damagePositions = world.collisionBlocksAlongLine(self.firePosition, maximumEndPoint, nil, self.beamTileDamageDepth) < world.damageTiles(damagePositions, "foreground", self.firePosition, "beamish", self.beamTileDamage, 99) < world.damageTiles(damagePositions, "background", self.firePosition, "beamish", self.beamTileDamage, 99) < end < < coroutine.yield() < < while stateTimer > 0 do < animator.rotateTransformationGroup(self.armName, self.aimAngle, self.shoulderOffset) < < self:updateBeam() < < local dt = script.updateDt() < stateTimer = stateTimer - dt < coroutine.yield() < end < < self.aimLocked = false < < vehicle.setDamageSourceEnabled(self.armName .. "Beam", false) < < if self.isFiring and self.repeatFire then < self.state:set(self.fireState, self) < else < self.state:set(self.winddownState, self) < end < end < < function BeamArm:winddownState() < local stateTimer = self.winddownTime or 0 < < animator.setAnimationState(self.armName, "winddown") < animator.playSound(self.armName .. "Winddown") < < while stateTimer > 0 do < animator.rotateTransformationGroup(self.armName, self.aimAngle, self.shoulderOffset) < < local dt = script.updateDt() < stateTimer = stateTimer - dt < coroutine.yield() < end < < self.state:set() < end < < function BeamArm:updateBeam() < local endPoint = vec2.add(self.firePosition, vec2.mul(self.aimVector, self.beamLength)) < local beamCollision = world.lineCollision(self.firePosition, endPoint) < if beamCollision then < endPoint = beamCollision < end < local beamLength = world.magnitude(self.firePosition, endPoint) < < animator.resetTransformationGroup(self.armName .. "Beam") < animator.scaleTransformationGroup(self.armName .. "Beam", {beamLength, 1}, {self.beamSourceOffset[1], self.beamSourceOffset[2] - self.beamHeight / 2}) < < local particleRegion = {self.beamSourceOffset[1], self.beamSourceOffset[2], self.beamSourceOffset[1] + beamLength, self.beamSourceOffset[2]} < animator.setParticleEmitterOffsetRegion(self.armName .. "Beam", particleRegion) < < return endPoint, beamCollision, beamLength < end --- > require "/vehicles/modularmech/armscripts/base.lua" > > BeamArm = MechArm:extend() > > function BeamArm:init() > self.state = FSM:new() > end > > function BeamArm:update(dt) > if self.state.state then > self.state:update() > end > > if not self.state.state then > if self.isFiring then > self.state:set(self.windupState, self) > end > end > > if self.state.state then > self.bobLocked = true > else > animator.setAnimationState(self.armName, "idle") > self.bobLocked = false > end > end > > function BeamArm:windupState() > local stateTimer = self.windupTime > > animator.setAnimationState(self.armName, "windup") > animator.playSound(self.armName .. "Windup") > > while stateTimer > 0 do > animator.rotateTransformationGroup(self.armName, self.aimAngle, self.shoulderOffset) > > local dt = script.updateDt() > stateTimer = stateTimer - dt > coroutine.yield() > end > > if self.isFiring then > self.state:set(self.fireState, self) > else > self.state:set(self.winddownState, self) > animator.playSound(self.armName .. "WinddownNoFire") > end > end > > function BeamArm:fireState() > local stateTimer = self.fireTime > > animator.rotateTransformationGroup(self.armName, self.aimAngle, self.shoulderOffset) > > local endPoint, beamCollision, beamLength = self:updateBeam() > > animator.playSound(self.armName .. "Fire") > animator.setParticleEmitterBurstCount(self.armName .. "Beam", math.ceil(self.beamParticleDensity * beamLength)) > animator.burstParticleEmitter(self.armName .. "Beam") > animator.setAnimationState(self.armName .. "Beam", "fire", true) > > vehicle.setDamageSourceEnabled(self.armName .. "Beam", true) > > self.aimLocked = self.lockAim > > if beamCollision and self.beamTileDamage > 0 then > local maximumEndPoint = vec2.add(self.firePosition, vec2.mul(self.aimVector, self.beamLength)) > local damagePositions = world.collisionBlocksAlongLine(self.firePosition, maximumEndPoint, nil, self.beamTileDamageDepth) > local driver = vehicle.entityLoungingIn("seat") > world.damageTiles(damagePositions, "foreground", self.firePosition, "beamish", self.beamTileDamage, 99, driver) > world.damageTiles(damagePositions, "background", self.firePosition, "beamish", self.beamTileDamage, 99, driver) > end > > coroutine.yield() > > while stateTimer > 0 do > animator.rotateTransformationGroup(self.armName, self.aimAngle, self.shoulderOffset) > > self:updateBeam() > > local dt = script.updateDt() > stateTimer = stateTimer - dt > coroutine.yield() > end > > self.aimLocked = false > > vehicle.setDamageSourceEnabled(self.armName .. "Beam", false) > > if self.isFiring and self.repeatFire then > self.state:set(self.fireState, self) > else > self.state:set(self.winddownState, self) > end > end > > function BeamArm:winddownState() > local stateTimer = self.winddownTime or 0 > > animator.setAnimationState(self.armName, "winddown") > animator.playSound(self.armName .. "Winddown") > > while stateTimer > 0 do > animator.rotateTransformationGroup(self.armName, self.aimAngle, self.shoulderOffset) > > local dt = script.updateDt() > stateTimer = stateTimer - dt > coroutine.yield() > end > > self.state:set() > end > > function BeamArm:updateBeam() > local endPoint = vec2.add(self.firePosition, vec2.mul(self.aimVector, self.beamLength)) > local beamCollision = world.lineCollision(self.firePosition, endPoint) > if beamCollision then > endPoint = beamCollision > end > local beamLength = world.magnitude(self.firePosition, endPoint) > > animator.resetTransformationGroup(self.armName .. "Beam") > animator.scaleTransformationGroup(self.armName .. "Beam", {beamLength, 1}, {self.beamSourceOffset[1], self.beamSourceOffset[2] - self.beamHeight / 2}) > > local particleRegion = {self.beamSourceOffset[1], self.beamSourceOffset[2], self.beamSourceOffset[1] + beamLength, self.beamSourceOffset[2]} > animator.setParticleEmitterOffsetRegion(self.armName .. "Beam", particleRegion) > > return endPoint, beamCollision, beamLength > end vehicles\modularmech\armscripts\drillarm.lua 1,54c1,55 < require "/vehicles/modularmech/armscripts/base.lua" < < DrillArm = MechArm:extend() < < function DrillArm:init() < self.spinTimer = 0 < self.tileDamageTimer = 0 < end < < function DrillArm:update(dt) < if self.isFiring then < self.spinTimer = math.min(self.spinUpDownTime, self.spinTimer + dt) < else < self.spinTimer = math.max(0, self.spinTimer - dt) < end < < if self.isFiring or self.spinTimer > 0 then < if self.spinTimer == self.spinUpDownTime then < vehicle.setDamageSourceEnabled(self.armName .. "Drill", true) < vehicle.setMovingCollisionEnabled(self.armName .. "Drill", true) < self.tileDamageTimer = math.max(0, self.tileDamageTimer - dt) < if self.tileDamageTimer == 0 then < self.tileDamageTimer = self.tileDamageRate < self:damageTiles() < end < animator.setAnimationState(self.armName, "active") < else < vehicle.setDamageSourceEnabled(self.armName .. "Drill", false) < vehicle.setMovingCollisionEnabled(self.armName .. "Drill", false) < self.tileDamageTimer = self.tileDamageRate < animator.setAnimationState(self.armName, self.isFiring and "windup" or "winddown") < end < < animator.rotateTransformationGroup(self.armName, self.aimAngle, self.shoulderOffset) < self.bobLocked = true < else < vehicle.setDamageSourceEnabled(self.armName .. "Drill", false) < vehicle.setMovingCollisionEnabled(self.armName .. "Drill", false) < animator.setAnimationState(self.armName, "idle") < self.bobLocked = true < end < end < < function DrillArm:damageTiles() < local tipPosition = self:transformOffset(self.drillTipOffset) < for _, sourceOffset in ipairs(self.drillSourceOffsets) do < local sourcePosition = self:transformOffset(sourceOffset) < local drillTiles = world.collisionBlocksAlongLine(sourcePosition, tipPosition, nil, self.damageTileDepth) < if #drillTiles > 0 then < world.damageTiles(drillTiles, "foreground", sourcePosition, "blockish", self.tileDamage, 99) < world.damageTiles(drillTiles, "background", sourcePosition, "blockish", self.tileDamage, 99) < end < end < end --- > require "/vehicles/modularmech/armscripts/base.lua" > > DrillArm = MechArm:extend() > > function DrillArm:init() > self.spinTimer = 0 > self.tileDamageTimer = 0 > end > > function DrillArm:update(dt) > if self.isFiring then > self.spinTimer = math.min(self.spinUpDownTime, self.spinTimer + dt) > else > self.spinTimer = math.max(0, self.spinTimer - dt) > end > > if self.isFiring or self.spinTimer > 0 then > if self.spinTimer == self.spinUpDownTime then > vehicle.setDamageSourceEnabled(self.armName .. "Drill", true) > vehicle.setMovingCollisionEnabled(self.armName .. "Drill", true) > self.tileDamageTimer = math.max(0, self.tileDamageTimer - dt) > if self.tileDamageTimer == 0 then > self.tileDamageTimer = self.tileDamageRate > self:damageTiles() > end > animator.setAnimationState(self.armName, "active") > else > vehicle.setDamageSourceEnabled(self.armName .. "Drill", false) > vehicle.setMovingCollisionEnabled(self.armName .. "Drill", false) > self.tileDamageTimer = self.tileDamageRate > animator.setAnimationState(self.armName, self.isFiring and "windup" or "winddown") > end > > animator.rotateTransformationGroup(self.armName, self.aimAngle, self.shoulderOffset) > self.bobLocked = true > else > vehicle.setDamageSourceEnabled(self.armName .. "Drill", false) > vehicle.setMovingCollisionEnabled(self.armName .. "Drill", false) > animator.setAnimationState(self.armName, "idle") > self.bobLocked = true > end > end > > function DrillArm:damageTiles() > local tipPosition = self:transformOffset(self.drillTipOffset) > for _, sourceOffset in ipairs(self.drillSourceOffsets) do > local sourcePosition = self:transformOffset(sourceOffset) > local drillTiles = world.collisionBlocksAlongLine(sourcePosition, tipPosition, nil, self.damageTileDepth) > if #drillTiles > 0 then > local driver = vehicle.entityLoungingIn("seat") > world.damageTiles(drillTiles, "foreground", sourcePosition, "blockish", self.tileDamage, 99, driver) > world.damageTiles(drillTiles, "background", sourcePosition, "blockish", self.tileDamage, 99, driver) > end > end > end