about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--CHANGELOG.md180
-rw-r--r--README.md190
-rw-r--r--apworld/__init__.py119
-rw-r--r--apworld/client/animationListener.gd38
-rw-r--r--apworld/client/apworld_runtime.gd44
-rw-r--r--apworld/client/assets/goal.pngbin0 -> 215 bytes
-rw-r--r--apworld/client/assets/location.pngbin0 -> 311 bytes
-rw-r--r--apworld/client/assets/worldport.pngbin0 -> 219 bytes
-rw-r--r--apworld/client/client.gd265
-rw-r--r--apworld/client/collectable.gd16
-rw-r--r--apworld/client/compass.gd66
-rw-r--r--apworld/client/compass_overlay.gd17
-rw-r--r--apworld/client/door.gd46
-rw-r--r--apworld/client/effects.gd32
-rw-r--r--apworld/client/gamedata.gd286
-rw-r--r--apworld/client/keyHolder.gd38
-rw-r--r--apworld/client/keyHolderChecker.gd24
-rw-r--r--apworld/client/keyHolderResetterListener.gd8
-rw-r--r--apworld/client/keyboard.gd231
-rw-r--r--apworld/client/locationListener.gd20
-rw-r--r--apworld/client/main.gd296
-rw-r--r--apworld/client/manager.gd603
-rw-r--r--apworld/client/messages.gd74
-rw-r--r--apworld/client/minimap.gd175
-rw-r--r--apworld/client/painting.gd38
-rw-r--r--apworld/client/panel.gd101
-rw-r--r--apworld/client/pauseMenu.gd91
-rw-r--r--apworld/client/player.gd346
-rw-r--r--apworld/client/rainbowText.gd10
-rw-r--r--apworld/client/run_from_apworld.tscn30
-rw-r--r--apworld/client/run_from_source.tscn22
-rw-r--r--apworld/client/saver.gd23
-rw-r--r--apworld/client/settings_screen.gd153
-rw-r--r--apworld/client/source_runtime.gd29
-rw-r--r--apworld/client/teleport.gd38
-rw-r--r--apworld/client/teleportListener.gd49
-rw-r--r--apworld/client/textclient.gd310
-rw-r--r--apworld/client/vendor/LICENSE21
-rw-r--r--apworld/client/vendor/WebSocketServer.gd173
-rw-r--r--apworld/client/victoryListener.gd20
-rw-r--r--apworld/client/visibilityListener.gd38
-rw-r--r--apworld/client/worldport.gd61
-rw-r--r--apworld/client/worldportListener.gd8
-rw-r--r--apworld/context.py630
-rw-r--r--apworld/docs/en_Lingo_2.md4
-rw-r--r--apworld/items.py26
-rw-r--r--apworld/locations.py3
-rw-r--r--apworld/logo.pngbin0 -> 9429 bytes
-rw-r--r--apworld/options.py171
-rw-r--r--apworld/player_logic.py431
-rw-r--r--apworld/regions.py151
-rw-r--r--apworld/requirements.txt2
-rw-r--r--apworld/rules.py53
-rw-r--r--apworld/static_logic.py122
-rw-r--r--apworld/tracker.py112
-rw-r--r--data/README.md13
-rw-r--r--data/connections.txtpb679
-rw-r--r--data/door_groups.txtpb163
-rw-r--r--data/ids.yaml448
-rw-r--r--data/maps/control_center/connections.txtpb85
-rw-r--r--data/maps/control_center/doors.txtpb172
-rw-r--r--data/maps/control_center/metadata.txtpb1
-rw-r--r--data/maps/control_center/rooms/Ancient Entrance.txtpb10
-rw-r--r--data/maps/control_center/rooms/Between Entrance.txtpb15
-rw-r--r--data/maps/control_center/rooms/Desert Room.txtpb8
-rw-r--r--data/maps/control_center/rooms/Entry Entrance.txtpb15
-rw-r--r--data/maps/control_center/rooms/Entry.txtpb15
-rw-r--r--data/maps/control_center/rooms/Hide Room.txtpb8
-rw-r--r--data/maps/control_center/rooms/Main Area.txtpb81
-rw-r--r--data/maps/control_center/rooms/Mint Ending.txtpb5
-rw-r--r--data/maps/control_center/rooms/Partial Entrance.txtpb17
-rw-r--r--data/maps/control_center/rooms/Perceptive Entrance.txtpb25
-rw-r--r--data/maps/control_center/rooms/Repetitive Entrance.txtpb10
-rw-r--r--data/maps/control_center/rooms/Shop Entrance.txtpb9
-rw-r--r--data/maps/control_center/rooms/Stormy Entrance.txtpb8
-rw-r--r--data/maps/control_center/rooms/Tenacious Entrance.txtpb17
-rw-r--r--data/maps/control_center/rooms/Unkempt Entrance.txtpb17
-rw-r--r--data/maps/control_center/rooms/Unyielding Entrance.txtpb15
-rw-r--r--data/maps/control_center/rooms/White Ending.txtpb5
-rw-r--r--data/maps/daedalus/connections.txtpb364
-rw-r--r--data/maps/daedalus/doors.txtpb242
-rw-r--r--data/maps/daedalus/rooms/After Bee Room.txtpb2
-rw-r--r--data/maps/daedalus/rooms/Amber North 2.txtpb2
-rw-r--r--data/maps/daedalus/rooms/Bee Room Obverse.txtpb2
-rw-r--r--data/maps/daedalus/rooms/Bee Room Reverse.txtpb2
-rw-r--r--data/maps/daedalus/rooms/Beehalls Intersection.txtpb2
-rw-r--r--data/maps/daedalus/rooms/Black Hex.txtpb2
-rw-r--r--data/maps/daedalus/rooms/Blue Hallway Cut Side.txtpb2
-rw-r--r--data/maps/daedalus/rooms/Blue Hallway Tall Side.txtpb2
-rw-r--r--data/maps/daedalus/rooms/Blue Hallway.txtpb2
-rw-r--r--data/maps/daedalus/rooms/Blue Room.txtpb2
-rw-r--r--data/maps/daedalus/rooms/Blue Smiley Annex.txtpb2
-rw-r--r--data/maps/daedalus/rooms/Blue Smiley.txtpb2
-rw-r--r--data/maps/daedalus/rooms/Book Room.txtpb2
-rw-r--r--data/maps/daedalus/rooms/Bow Side.txtpb3
-rw-r--r--data/maps/daedalus/rooms/Brown Smiley.txtpb2
-rw-r--r--data/maps/daedalus/rooms/C Keyholder.txtpb3
-rw-r--r--data/maps/daedalus/rooms/Castle.txtpb2
-rw-r--r--data/maps/daedalus/rooms/Coin Tower.txtpb2
-rw-r--r--data/maps/daedalus/rooms/Composite Room NE.txtpb2
-rw-r--r--data/maps/daedalus/rooms/Composite Room NW.txtpb2
-rw-r--r--data/maps/daedalus/rooms/Composite Room S.txtpb5
-rw-r--r--data/maps/daedalus/rooms/Computer Room Seal.txtpb2
-rw-r--r--data/maps/daedalus/rooms/Computer Room.txtpb2
-rw-r--r--data/maps/daedalus/rooms/Cyan Room.txtpb2
-rw-r--r--data/maps/daedalus/rooms/D Keyholder.txtpb3
-rw-r--r--data/maps/daedalus/rooms/D2 Room.txtpb2
-rw-r--r--data/maps/daedalus/rooms/Dark Light Exit.txtpb2
-rw-r--r--data/maps/daedalus/rooms/Dark Light Room.txtpb2
-rw-r--r--data/maps/daedalus/rooms/Ending.txtpb2
-rw-r--r--data/maps/daedalus/rooms/Entry Shortcut.txtpb6
-rw-r--r--data/maps/daedalus/rooms/Eye Painting.txtpb2
-rw-r--r--data/maps/daedalus/rooms/Eye Temple 1F Side.txtpb2
-rw-r--r--data/maps/daedalus/rooms/Eye Temple 1F.txtpb2
-rw-r--r--data/maps/daedalus/rooms/Eye Temple 2F Side.txtpb2
-rw-r--r--data/maps/daedalus/rooms/Eye Temple 2F.txtpb2
-rw-r--r--data/maps/daedalus/rooms/Eye Temple Pillar 1.txtpb2
-rw-r--r--data/maps/daedalus/rooms/Eye Temple Pillar 2.txtpb2
-rw-r--r--data/maps/daedalus/rooms/F Keyholder.txtpb3
-rw-r--r--data/maps/daedalus/rooms/F2 Prize.txtpb2
-rw-r--r--data/maps/daedalus/rooms/F2 Room.txtpb2
-rw-r--r--data/maps/daedalus/rooms/Flip Painting Destination.txtpb2
-rw-r--r--data/maps/daedalus/rooms/Flip Painting Hidden Panel.txtpb3
-rw-r--r--data/maps/daedalus/rooms/Flip Painting.txtpb2
-rw-r--r--data/maps/daedalus/rooms/Gallery Entrance.txtpb2
-rw-r--r--data/maps/daedalus/rooms/Globe Room.txtpb2
-rw-r--r--data/maps/daedalus/rooms/Godot Room.txtpb2
-rw-r--r--data/maps/daedalus/rooms/Gray Color Backside.txtpb2
-rw-r--r--data/maps/daedalus/rooms/Gray Color Door.txtpb2
-rw-r--r--data/maps/daedalus/rooms/Green Color Door.txtpb2
-rw-r--r--data/maps/daedalus/rooms/Green Room.txtpb2
-rw-r--r--data/maps/daedalus/rooms/Green Smiley.txtpb2
-rw-r--r--data/maps/daedalus/rooms/Hedges Tower.txtpb4
-rw-r--r--data/maps/daedalus/rooms/Hedges.txtpb2
-rw-r--r--data/maps/daedalus/rooms/Hotel.txtpb2
-rw-r--r--data/maps/daedalus/rooms/House Entrance.txtpb2
-rw-r--r--data/maps/daedalus/rooms/House.txtpb2
-rw-r--r--data/maps/daedalus/rooms/I2 Room.txtpb2
-rw-r--r--data/maps/daedalus/rooms/Intense Room.txtpb2
-rw-r--r--data/maps/daedalus/rooms/J2 Room.txtpb2
-rw-r--r--data/maps/daedalus/rooms/J2 Vestibule.txtpb3
-rw-r--r--data/maps/daedalus/rooms/Magic Room.txtpb2
-rw-r--r--data/maps/daedalus/rooms/Maze Paintings Area.txtpb2
-rw-r--r--data/maps/daedalus/rooms/Maze.txtpb2
-rw-r--r--data/maps/daedalus/rooms/Moat.txtpb5
-rw-r--r--data/maps/daedalus/rooms/North Castle Area.txtpb2
-rw-r--r--data/maps/daedalus/rooms/Number Paintings Area.txtpb3
-rw-r--r--data/maps/daedalus/rooms/Nursery.txtpb3
-rw-r--r--data/maps/daedalus/rooms/O2 Prize.txtpb2
-rw-r--r--data/maps/daedalus/rooms/O2 Room.txtpb2
-rw-r--r--data/maps/daedalus/rooms/Orange Room Hallway.txtpb4
-rw-r--r--data/maps/daedalus/rooms/Orange Room.txtpb2
-rw-r--r--data/maps/daedalus/rooms/Outside Book Room.txtpb2
-rw-r--r--data/maps/daedalus/rooms/Outside Eye Temple.txtpb2
-rw-r--r--data/maps/daedalus/rooms/Outside Hedges.txtpb5
-rw-r--r--data/maps/daedalus/rooms/Outside Hotel.txtpb3
-rw-r--r--data/maps/daedalus/rooms/Outside House.txtpb3
-rw-r--r--data/maps/daedalus/rooms/Outside Magic Room.txtpb2
-rw-r--r--data/maps/daedalus/rooms/Outside Orange Room.txtpb2
-rw-r--r--data/maps/daedalus/rooms/Outside Pyramid.txtpb2
-rw-r--r--data/maps/daedalus/rooms/Outside Red Room.txtpb2
-rw-r--r--data/maps/daedalus/rooms/Outside Salt Room.txtpb3
-rw-r--r--data/maps/daedalus/rooms/Outside Snake Room.txtpb2
-rw-r--r--data/maps/daedalus/rooms/Pains Room.txtpb2
-rw-r--r--data/maps/daedalus/rooms/Pairs Room.txtpb2
-rw-r--r--data/maps/daedalus/rooms/Pepper Room.txtpb3
-rw-r--r--data/maps/daedalus/rooms/Plum Room.txtpb2
-rw-r--r--data/maps/daedalus/rooms/Post Orange Smiley Three Way.txtpb2
-rw-r--r--data/maps/daedalus/rooms/Pumpkin Entrance.txtpb2
-rw-r--r--data/maps/daedalus/rooms/Pumpkin Room.txtpb2
-rw-r--r--data/maps/daedalus/rooms/Purple Hallway From Great.txtpb5
-rw-r--r--data/maps/daedalus/rooms/Purple NW Vestibule.txtpb2
-rw-r--r--data/maps/daedalus/rooms/Purple Room East.txtpb2
-rw-r--r--data/maps/daedalus/rooms/Purple Room South.txtpb2
-rw-r--r--data/maps/daedalus/rooms/Purple Room West.txtpb2
-rw-r--r--data/maps/daedalus/rooms/Purple Room.txtpb2
-rw-r--r--data/maps/daedalus/rooms/Purple SE Vestibule.txtpb2
-rw-r--r--data/maps/daedalus/rooms/Purple SW Vestibule.txtpb2
-rw-r--r--data/maps/daedalus/rooms/Purple Smiley.txtpb2
-rw-r--r--data/maps/daedalus/rooms/Pyramid 3.txtpb2
-rw-r--r--data/maps/daedalus/rooms/Pyramid 4.txtpb2
-rw-r--r--data/maps/daedalus/rooms/Pyramid 5.txtpb2
-rw-r--r--data/maps/daedalus/rooms/Pyramid 6.txtpb2
-rw-r--r--data/maps/daedalus/rooms/Pyramid 7.txtpb2
-rw-r--r--data/maps/daedalus/rooms/Pyramid 8.txtpb3
-rw-r--r--data/maps/daedalus/rooms/Pyramid Entry.txtpb2
-rw-r--r--data/maps/daedalus/rooms/Pyramid Second Floor.txtpb3
-rw-r--r--data/maps/daedalus/rooms/Pyramid Top.txtpb2
-rw-r--r--data/maps/daedalus/rooms/Quiet Entrance.txtpb6
-rw-r--r--data/maps/daedalus/rooms/Rain Side.txtpb6
-rw-r--r--data/maps/daedalus/rooms/Rainbow Blue.txtpb3
-rw-r--r--data/maps/daedalus/rooms/Rainbow Color Backside.txtpb3
-rw-r--r--data/maps/daedalus/rooms/Rainbow Color Doors.txtpb2
-rw-r--r--data/maps/daedalus/rooms/Rainbow Cyan.txtpb3
-rw-r--r--data/maps/daedalus/rooms/Rainbow End.txtpb2
-rw-r--r--data/maps/daedalus/rooms/Rainbow Green.txtpb3
-rw-r--r--data/maps/daedalus/rooms/Rainbow Orange.txtpb3
-rw-r--r--data/maps/daedalus/rooms/Rainbow Purple.txtpb3
-rw-r--r--data/maps/daedalus/rooms/Rainbow Red.txtpb3
-rw-r--r--data/maps/daedalus/rooms/Rainbow Start.txtpb2
-rw-r--r--data/maps/daedalus/rooms/Rainbow Yellow.txtpb3
-rw-r--r--data/maps/daedalus/rooms/Red Color Door.txtpb5
-rw-r--r--data/maps/daedalus/rooms/Red Room.txtpb2
-rw-r--r--data/maps/daedalus/rooms/Red Smiley.txtpb2
-rw-r--r--data/maps/daedalus/rooms/Roof.txtpb1
-rw-r--r--data/maps/daedalus/rooms/Salt Room.txtpb3
-rw-r--r--data/maps/daedalus/rooms/Seasoning Room.txtpb2
-rw-r--r--data/maps/daedalus/rooms/Snake Room.txtpb2
-rw-r--r--data/maps/daedalus/rooms/South Castle Area.txtpb4
-rw-r--r--data/maps/daedalus/rooms/Starting Room.txtpb5
-rw-r--r--data/maps/daedalus/rooms/Sweet Foyer.txtpb8
-rw-r--r--data/maps/daedalus/rooms/Tree Entrance.txtpb5
-rw-r--r--data/maps/daedalus/rooms/U2 Prize.txtpb2
-rw-r--r--data/maps/daedalus/rooms/U2 Room.txtpb2
-rw-r--r--data/maps/daedalus/rooms/Unkempt Entrance.txtpb5
-rw-r--r--data/maps/daedalus/rooms/Welcome Back Area.txtpb2
-rw-r--r--data/maps/daedalus/rooms/Welcome Back Exit.txtpb3
-rw-r--r--data/maps/daedalus/rooms/West Castle Area.txtpb2
-rw-r--r--data/maps/daedalus/rooms/West Spire.txtpb2
-rw-r--r--data/maps/daedalus/rooms/White Hallway From Entry.txtpb11
-rw-r--r--data/maps/daedalus/rooms/Wisdom Panel.txtpb2
-rw-r--r--data/maps/daedalus/rooms/Wonderland.txtpb6
-rw-r--r--data/maps/daedalus/rooms/Yellow Color Backside.txtpb2
-rw-r--r--data/maps/daedalus/rooms/Yellow Color Door.txtpb7
-rw-r--r--data/maps/daedalus/rooms/Yellow Room.txtpb2
-rw-r--r--data/maps/daedalus/rooms/Yellow Smiley Annex.txtpb2
-rw-r--r--data/maps/daedalus/rooms/Z2 Prize.txtpb2
-rw-r--r--data/maps/daedalus/rooms/Z2 Room.txtpb2
-rw-r--r--data/maps/daedalus/rooms/Zoo Center.txtpb2
-rw-r--r--data/maps/daedalus/rooms/Zoo E.txtpb2
-rw-r--r--data/maps/daedalus/rooms/Zoo N.txtpb3
-rw-r--r--data/maps/daedalus/rooms/Zoo NE.txtpb2
-rw-r--r--data/maps/daedalus/rooms/Zoo S.txtpb3
-rw-r--r--data/maps/daedalus/rooms/Zoo SE.txtpb2
-rw-r--r--data/maps/four_rooms/doors.txtpb4
-rw-r--r--data/maps/four_rooms/rooms/A2 Room.txtpb1
-rw-r--r--data/maps/four_rooms/rooms/Examples Room.txtpb5
-rw-r--r--data/maps/four_rooms/rooms/Hallway.txtpb1
-rw-r--r--data/maps/four_rooms/rooms/Intensify Room.txtpb5
-rw-r--r--data/maps/four_rooms/rooms/Keyholder Room.txtpb2
-rw-r--r--data/maps/four_rooms/rooms/Synonyms Room.txtpb5
-rw-r--r--data/maps/four_rooms/rooms/Time Room.txtpb5
-rw-r--r--data/maps/the_ancient/doors.txtpb33
-rw-r--r--data/maps/the_ancient/rooms/Ending.txtpb1
-rw-r--r--data/maps/the_ancient/rooms/Inside.txtpb2
-rw-r--r--data/maps/the_ancient/rooms/Outside.txtpb2
-rw-r--r--data/maps/the_bearer/connections.txtpb5
-rw-r--r--data/maps/the_bearer/doors.txtpb5
-rw-r--r--data/maps/the_bearer/rooms/Back Area.txtpb11
-rw-r--r--data/maps/the_bearer/rooms/Blue Animal (View).txtpb1
-rw-r--r--data/maps/the_bearer/rooms/Blue Animal.txtpb1
-rw-r--r--data/maps/the_bearer/rooms/Blue Planet (View).txtpb1
-rw-r--r--data/maps/the_bearer/rooms/Blue Planet.txtpb1
-rw-r--r--data/maps/the_bearer/rooms/Blue Town (View).txtpb1
-rw-r--r--data/maps/the_bearer/rooms/Blue Town.txtpb1
-rw-r--r--data/maps/the_bearer/rooms/Blue Vegetable (View).txtpb1
-rw-r--r--data/maps/the_bearer/rooms/Blue Vegetable.txtpb1
-rw-r--r--data/maps/the_bearer/rooms/Butterfly Room.txtpb1
-rw-r--r--data/maps/the_bearer/rooms/Entry.txtpb5
-rw-r--r--data/maps/the_bearer/rooms/Green Animal.txtpb1
-rw-r--r--data/maps/the_bearer/rooms/Green Planet (View).txtpb1
-rw-r--r--data/maps/the_bearer/rooms/Green Planet.txtpb1
-rw-r--r--data/maps/the_bearer/rooms/Green Town.txtpb1
-rw-r--r--data/maps/the_bearer/rooms/Green Vegetable (View).txtpb1
-rw-r--r--data/maps/the_bearer/rooms/Green Vegetable.txtpb1
-rw-r--r--data/maps/the_bearer/rooms/Orange Planet.txtpb1
-rw-r--r--data/maps/the_bearer/rooms/Orange Vegetable.txtpb1
-rw-r--r--data/maps/the_bearer/rooms/Overlook.txtpb1
-rw-r--r--data/maps/the_bearer/rooms/Purple Animal (View).txtpb1
-rw-r--r--data/maps/the_bearer/rooms/Purple Animal.txtpb1
-rw-r--r--data/maps/the_bearer/rooms/Purple Planet (View).txtpb1
-rw-r--r--data/maps/the_bearer/rooms/Purple Planet.txtpb1
-rw-r--r--data/maps/the_bearer/rooms/Purple Town (View).txtpb1
-rw-r--r--data/maps/the_bearer/rooms/Purple Town.txtpb1
-rw-r--r--data/maps/the_bearer/rooms/Purple Vegetable (View).txtpb1
-rw-r--r--data/maps/the_bearer/rooms/Purple Vegetable.txtpb1
-rw-r--r--data/maps/the_bearer/rooms/Q2 Room.txtpb1
-rw-r--r--data/maps/the_bearer/rooms/Red Animal.txtpb1
-rw-r--r--data/maps/the_bearer/rooms/Red Planet.txtpb1
-rw-r--r--data/maps/the_bearer/rooms/Red Town.txtpb1
-rw-r--r--data/maps/the_bearer/rooms/Red Vegetable.txtpb1
-rw-r--r--data/maps/the_bearer/rooms/Tree Entrance.txtpb8
-rw-r--r--data/maps/the_bearer/rooms/Yellow Planet.txtpb1
-rw-r--r--data/maps/the_bearer/rooms/Yellow Vegetable.txtpb1
-rw-r--r--data/maps/the_between/rooms/B2 Back Room.txtpb1
-rw-r--r--data/maps/the_between/rooms/B2 Front Room.txtpb1
-rw-r--r--data/maps/the_between/rooms/Control Center Side.txtpb9
-rw-r--r--data/maps/the_between/rooms/Main Area.txtpb5
-rw-r--r--data/maps/the_between/rooms/Plaza Entrance.txtpb5
-rw-r--r--data/maps/the_butterfly/rooms/Main Area.txtpb5
-rw-r--r--data/maps/the_butterfly/rooms/Mastery.txtpb1
-rw-r--r--data/maps/the_colorful/doors.txtpb3
-rw-r--r--data/maps/the_colorful/rooms/Black Room.txtpb1
-rw-r--r--data/maps/the_colorful/rooms/Blue Room.txtpb1
-rw-r--r--data/maps/the_colorful/rooms/Brown Room.txtpb1
-rw-r--r--data/maps/the_colorful/rooms/Cyan Hallway.txtpb9
-rw-r--r--data/maps/the_colorful/rooms/Cyan Room.txtpb1
-rw-r--r--data/maps/the_colorful/rooms/Ending.txtpb1
-rw-r--r--data/maps/the_colorful/rooms/Gray Room.txtpb1
-rw-r--r--data/maps/the_colorful/rooms/Green Room.txtpb1
-rw-r--r--data/maps/the_colorful/rooms/Orange Room.txtpb1
-rw-r--r--data/maps/the_colorful/rooms/P2 Room.txtpb1
-rw-r--r--data/maps/the_colorful/rooms/Purple Room.txtpb2
-rw-r--r--data/maps/the_colorful/rooms/Red Room.txtpb1
-rw-r--r--data/maps/the_colorful/rooms/White Room.txtpb5
-rw-r--r--data/maps/the_colorful/rooms/Window Room.txtpb1
-rw-r--r--data/maps/the_colorful/rooms/Yellow Room.txtpb1
-rw-r--r--data/maps/the_congruent/doors.txtpb13
-rw-r--r--data/maps/the_congruent/rooms/C Keyholder.txtpb1
-rw-r--r--data/maps/the_congruent/rooms/C2 Room.txtpb1
-rw-r--r--data/maps/the_congruent/rooms/Flipped Magenta Room.txtpb1
-rw-r--r--data/maps/the_congruent/rooms/Flipped Yellow Room.txtpb1
-rw-r--r--data/maps/the_congruent/rooms/G Keyholder.txtpb1
-rw-r--r--data/maps/the_congruent/rooms/G2 Room.txtpb1
-rw-r--r--data/maps/the_congruent/rooms/Main Area.txtpb5
-rw-r--r--data/maps/the_congruent/rooms/Obverse Magenta Room.txtpb1
-rw-r--r--data/maps/the_congruent/rooms/Obverse Yellow Room.txtpb1
-rw-r--r--data/maps/the_congruent/rooms/T Keyholder.txtpb2
-rw-r--r--data/maps/the_darkroom/connections.txtpb29
-rw-r--r--data/maps/the_darkroom/doors.txtpb11
-rw-r--r--data/maps/the_darkroom/rooms/Congruent Entrance.txtpb9
-rw-r--r--data/maps/the_darkroom/rooms/Cyan Hallway.txtpb9
-rw-r--r--data/maps/the_darkroom/rooms/Double Sided Entrance.txtpb9
-rw-r--r--data/maps/the_darkroom/rooms/First Room Exit.txtpb9
-rw-r--r--data/maps/the_darkroom/rooms/First Room.txtpb24
-rw-r--r--data/maps/the_darkroom/rooms/S Room.txtpb1
-rw-r--r--data/maps/the_darkroom/rooms/Second Room Exit.txtpb9
-rw-r--r--data/maps/the_darkroom/rooms/Second Room.txtpb18
-rw-r--r--data/maps/the_darkroom/rooms/Third Room.txtpb6
-rw-r--r--data/maps/the_digital/connections.txtpb5
-rw-r--r--data/maps/the_digital/rooms/C Room.txtpb1
-rw-r--r--data/maps/the_digital/rooms/Chamber.txtpb1
-rw-r--r--data/maps/the_digital/rooms/Gallery Maze.txtpb5
-rw-r--r--data/maps/the_digital/rooms/Main Area.txtpb13
-rw-r--r--data/maps/the_digital/rooms/Tree Area.txtpb6
-rw-r--r--data/maps/the_digital/rooms/U Room.txtpb1
-rw-r--r--data/maps/the_digital/rooms/Unyielding Entrance.txtpb4
-rw-r--r--data/maps/the_door/rooms/Ending.txtpb1
-rw-r--r--data/maps/the_door/rooms/Main Area.txtpb1
-rw-r--r--data/maps/the_double_sided/rooms/Brown Area.txtpb1
-rw-r--r--data/maps/the_double_sided/rooms/Flipped Black Area.txtpb1
-rw-r--r--data/maps/the_double_sided/rooms/Flipped Blue Area.txtpb1
-rw-r--r--data/maps/the_double_sided/rooms/Flipped Green Area.txtpb1
-rw-r--r--data/maps/the_double_sided/rooms/Flipped Orange Area.txtpb1
-rw-r--r--data/maps/the_double_sided/rooms/Flipped Pink Area.txtpb1
-rw-r--r--data/maps/the_double_sided/rooms/Flipped Purple Area.txtpb1
-rw-r--r--data/maps/the_double_sided/rooms/Flipped Red Area.txtpb1
-rw-r--r--data/maps/the_double_sided/rooms/Flipped Yellow Back Area.txtpb1
-rw-r--r--data/maps/the_double_sided/rooms/Flipped Yellow Front Area.txtpb1
-rw-r--r--data/maps/the_double_sided/rooms/Obverse Black Area.txtpb1
-rw-r--r--data/maps/the_double_sided/rooms/Obverse Blue Area.txtpb1
-rw-r--r--data/maps/the_double_sided/rooms/Obverse Green Area.txtpb1
-rw-r--r--data/maps/the_double_sided/rooms/Obverse Orange Back Area.txtpb1
-rw-r--r--data/maps/the_double_sided/rooms/Obverse Orange Front Area.txtpb1
-rw-r--r--data/maps/the_double_sided/rooms/Obverse Orange Isolated Section.txtpb1
-rw-r--r--data/maps/the_double_sided/rooms/Obverse Pink Area.txtpb1
-rw-r--r--data/maps/the_double_sided/rooms/Obverse Purple Area.txtpb1
-rw-r--r--data/maps/the_double_sided/rooms/Obverse Red Area.txtpb1
-rw-r--r--data/maps/the_double_sided/rooms/Obverse Yellow Area.txtpb1
-rw-r--r--data/maps/the_double_sided/rooms/Start.txtpb5
-rw-r--r--data/maps/the_entry/connections.txtpb42
-rw-r--r--data/maps/the_entry/doors.txtpb29
-rw-r--r--data/maps/the_entry/metadata.txtpb2
-rw-r--r--data/maps/the_entry/rooms/Blue Alcove.txtpb2
-rw-r--r--data/maps/the_entry/rooms/Colored Doors Area.txtpb2
-rw-r--r--data/maps/the_entry/rooms/Composite Room Entrance.txtpb6
-rw-r--r--data/maps/the_entry/rooms/Ctrl Tutorial.txtpb2
-rw-r--r--data/maps/the_entry/rooms/D Room Final.txtpb2
-rw-r--r--data/maps/the_entry/rooms/D Room.txtpb2
-rw-r--r--data/maps/the_entry/rooms/Daedalus Entrance.txtpb6
-rw-r--r--data/maps/the_entry/rooms/Digital Entrance.txtpb6
-rw-r--r--data/maps/the_entry/rooms/Entry Exit.txtpb6
-rw-r--r--data/maps/the_entry/rooms/Eye Room.txtpb6
-rw-r--r--data/maps/the_entry/rooms/Flipped Link Area.txtpb5
-rw-r--r--data/maps/the_entry/rooms/Flipped Pyramid Area.txtpb2
-rw-r--r--data/maps/the_entry/rooms/Flipped Right Eye.txtpb2
-rw-r--r--data/maps/the_entry/rooms/Flipped Second Room.txtpb9
-rw-r--r--data/maps/the_entry/rooms/Four Rooms Entrance.txtpb9
-rw-r--r--data/maps/the_entry/rooms/Gallery Return.txtpb6
-rw-r--r--data/maps/the_entry/rooms/Least Blue Last.txtpb6
-rw-r--r--data/maps/the_entry/rooms/Liberated Entrance.txtpb8
-rw-r--r--data/maps/the_entry/rooms/Lime Room.txtpb8
-rw-r--r--data/maps/the_entry/rooms/Link Area.txtpb15
-rw-r--r--data/maps/the_entry/rooms/Literate Entrance.txtpb8
-rw-r--r--data/maps/the_entry/rooms/Parthenon Return.txtpb8
-rw-r--r--data/maps/the_entry/rooms/Rabbit Hole Lock.txtpb18
-rw-r--r--data/maps/the_entry/rooms/Rabbit Hole.txtpb8
-rw-r--r--data/maps/the_entry/rooms/Red Alcove.txtpb2
-rw-r--r--data/maps/the_entry/rooms/Red Blue Halls.txtpb2
-rw-r--r--data/maps/the_entry/rooms/Repetitive Entrance.txtpb9
-rw-r--r--data/maps/the_entry/rooms/Revitalized Entrance.txtpb9
-rw-r--r--data/maps/the_entry/rooms/Right Eye.txtpb2
-rw-r--r--data/maps/the_entry/rooms/Shop Entrance.txtpb6
-rw-r--r--data/maps/the_entry/rooms/Starting Room.txtpb7
-rw-r--r--data/maps/the_entry/rooms/Trick Room.txtpb2
-rw-r--r--data/maps/the_entry/rooms/White Hallway To Daedalus.txtpb6
-rw-r--r--data/maps/the_entry/rooms/Wrath Room.txtpb18
-rw-r--r--data/maps/the_entry/rooms/X Area.txtpb6
-rw-r--r--data/maps/the_extravagant/rooms/E Room.txtpb1
-rw-r--r--data/maps/the_extravagant/rooms/Engine Room.txtpb5
-rw-r--r--data/maps/the_extravagant/rooms/Hat Chamber.txtpb1
-rw-r--r--data/maps/the_extravagant/rooms/X Minus Middle Leg.txtpb1
-rw-r--r--data/maps/the_extravagant/rooms/X Minus Right Leg.txtpb1
-rw-r--r--data/maps/the_extravagant/rooms/X Minus.txtpb1
-rw-r--r--data/maps/the_extravagant/rooms/X Plus Middle Leg.txtpb1
-rw-r--r--data/maps/the_extravagant/rooms/X Plus Right Leg.txtpb1
-rw-r--r--data/maps/the_extravagant/rooms/X Plus.txtpb2
-rw-r--r--data/maps/the_extravagant/rooms/Y Minus First Floor.txtpb1
-rw-r--r--data/maps/the_extravagant/rooms/Y Minus Second Floor.txtpb1
-rw-r--r--data/maps/the_extravagant/rooms/Y Minus Third Floor.txtpb1
-rw-r--r--data/maps/the_extravagant/rooms/Y Plus First Floor.txtpb1
-rw-r--r--data/maps/the_extravagant/rooms/Y Plus Third Floor.txtpb1
-rw-r--r--data/maps/the_gallery/doors.txtpb122
-rw-r--r--data/maps/the_gallery/rooms/Back Room.txtpb1
-rw-r--r--data/maps/the_gallery/rooms/Daedalus Extension.txtpb1
-rw-r--r--data/maps/the_gallery/rooms/Ending.txtpb1
-rw-r--r--data/maps/the_gallery/rooms/Main Area.txtpb6
-rw-r--r--data/maps/the_gold/rooms/The Whole Thing.txtpb1
-rw-r--r--data/maps/the_graveyard/doors.txtpb5
-rw-r--r--data/maps/the_graveyard/rooms/Inside.txtpb1
-rw-r--r--data/maps/the_graveyard/rooms/Outside.txtpb1
-rw-r--r--data/maps/the_great/doors.txtpb33
-rw-r--r--data/maps/the_great/rooms/Back Area.txtpb18
-rw-r--r--data/maps/the_great/rooms/Behind Question Area.txtpb2
-rw-r--r--data/maps/the_great/rooms/Colorful Entrance.txtpb6
-rw-r--r--data/maps/the_great/rooms/Daedalus Entrance.txtpb6
-rw-r--r--data/maps/the_great/rooms/East Landscape.txtpb2
-rw-r--r--data/maps/the_great/rooms/G Room.txtpb2
-rw-r--r--data/maps/the_great/rooms/Hive Entrance.txtpb6
-rw-r--r--data/maps/the_great/rooms/Jail Part 1.txtpb2
-rw-r--r--data/maps/the_great/rooms/Jail Part 2.txtpb2
-rw-r--r--data/maps/the_great/rooms/Jubilant Entrance.txtpb6
-rw-r--r--data/maps/the_great/rooms/Magnet Room.txtpb2
-rw-r--r--data/maps/the_great/rooms/Main Area.txtpb23
-rw-r--r--data/maps/the_great/rooms/Maze Center.txtpb2
-rw-r--r--data/maps/the_great/rooms/Maze Cold Area.txtpb2
-rw-r--r--data/maps/the_great/rooms/Maze Empty Vestibule.txtpb2
-rw-r--r--data/maps/the_great/rooms/Maze In Area.txtpb2
-rw-r--r--data/maps/the_great/rooms/Maze Moon Area.txtpb2
-rw-r--r--data/maps/the_great/rooms/Maze Off Area.txtpb2
-rw-r--r--data/maps/the_great/rooms/Maze Slice Area.txtpb2
-rw-r--r--data/maps/the_great/rooms/Maze Smooth Area.txtpb2
-rw-r--r--data/maps/the_great/rooms/Maze South Area.txtpb2
-rw-r--r--data/maps/the_great/rooms/Maze Start.txtpb2
-rw-r--r--data/maps/the_great/rooms/Maze Tower.txtpb2
-rw-r--r--data/maps/the_great/rooms/Maze Up Area.txtpb2
-rw-r--r--data/maps/the_great/rooms/Maze Wreck Area.txtpb2
-rw-r--r--data/maps/the_great/rooms/Nature Room.txtpb2
-rw-r--r--data/maps/the_great/rooms/North Landscape.txtpb8
-rw-r--r--data/maps/the_great/rooms/Outside Jail.txtpb2
-rw-r--r--data/maps/the_great/rooms/Pillar Room.txtpb2
-rw-r--r--data/maps/the_great/rooms/Purple Room.txtpb6
-rw-r--r--data/maps/the_great/rooms/Question Room How.txtpb5
-rw-r--r--data/maps/the_great/rooms/Question Room What.txtpb13
-rw-r--r--data/maps/the_great/rooms/Question Room When.txtpb5
-rw-r--r--data/maps/the_great/rooms/Question Room Who.txtpb5
-rw-r--r--data/maps/the_great/rooms/Salmon Room.txtpb6
-rw-r--r--data/maps/the_great/rooms/Talented Entrance.txtpb6
-rw-r--r--data/maps/the_great/rooms/Under Question Room.txtpb4
-rw-r--r--data/maps/the_great/rooms/West Side.txtpb15
-rw-r--r--data/maps/the_great/rooms/Whole Room.txtpb2
-rw-r--r--data/maps/the_great/rooms/Y Room.txtpb2
-rw-r--r--data/maps/the_great/rooms/Zero Room.txtpb2
-rw-r--r--data/maps/the_hinterlands/rooms/Main Area.txtpb9
-rw-r--r--data/maps/the_hive/doors.txtpb3
-rw-r--r--data/maps/the_hive/rooms/Main Area.txtpb18
-rw-r--r--data/maps/the_hive/rooms/Mastery Room.txtpb1
-rw-r--r--data/maps/the_hive/rooms/Room 8.txtpb1
-rw-r--r--data/maps/the_impressive/rooms/Green Eye.txtpb6
-rw-r--r--data/maps/the_impressive/rooms/Lobby.txtpb6
-rw-r--r--data/maps/the_impressive/rooms/M Room.txtpb2
-rw-r--r--data/maps/the_impressive/rooms/M2 Room.txtpb2
-rw-r--r--data/maps/the_impressive/rooms/Side Area.txtpb6
-rw-r--r--data/maps/the_impressive/rooms/W Room.txtpb2
-rw-r--r--data/maps/the_impressive/rooms/WM Room.txtpb3
-rw-r--r--data/maps/the_invisible/rooms/Entrance.txtpb5
-rw-r--r--data/maps/the_invisible/rooms/Maze.txtpb6
-rw-r--r--data/maps/the_jubilant/rooms/J Room.txtpb1
-rw-r--r--data/maps/the_jubilant/rooms/Main Area.txtpb5
-rw-r--r--data/maps/the_jubilant/rooms/Side Area.txtpb2
-rw-r--r--data/maps/the_keen/rooms/K Room.txtpb1
-rw-r--r--data/maps/the_keen/rooms/Main Area.txtpb5
-rw-r--r--data/maps/the_liberated/doors.txtpb1
-rw-r--r--data/maps/the_liberated/rooms/Painting Room.txtpb1
-rw-r--r--data/maps/the_liberated/rooms/Puzzle Room.txtpb5
-rw-r--r--data/maps/the_linear/doors.txtpb1
-rw-r--r--data/maps/the_linear/rooms/Room.txtpb5
-rw-r--r--data/maps/the_lionized/rooms/E2 Room.txtpb1
-rw-r--r--data/maps/the_lionized/rooms/Puzzle Room.txtpb5
-rw-r--r--data/maps/the_literate/doors.txtpb1
-rw-r--r--data/maps/the_literate/rooms/Painting Room.txtpb1
-rw-r--r--data/maps/the_literate/rooms/Puzzle Room.txtpb5
-rw-r--r--data/maps/the_lively/rooms/L2 Room.txtpb1
-rw-r--r--data/maps/the_lively/rooms/Puzzle Room.txtpb4
-rw-r--r--data/maps/the_nuanced/connections.txtpb2
-rw-r--r--data/maps/the_nuanced/doors.txtpb6
-rw-r--r--data/maps/the_nuanced/rooms/Back Room.txtpb1
-rw-r--r--data/maps/the_nuanced/rooms/Main Room.txtpb6
-rw-r--r--data/maps/the_nuanced/rooms/N2 Room.txtpb1
-rw-r--r--data/maps/the_orb/connections.txtpb12
-rw-r--r--data/maps/the_orb/rooms/B Room.txtpb16
-rw-r--r--data/maps/the_orb/rooms/Main Area.txtpb5
-rw-r--r--data/maps/the_orb/rooms/Middle Room.txtpb12
-rw-r--r--data/maps/the_orb/rooms/O Room.txtpb1
-rw-r--r--data/maps/the_orb/rooms/R Room.txtpb1
-rw-r--r--data/maps/the_owl/connections.txtpb39
-rw-r--r--data/maps/the_owl/doors.txtpb31
-rw-r--r--data/maps/the_owl/rooms/Blue Room.txtpb1
-rw-r--r--data/maps/the_owl/rooms/Connected Area.txtpb12
-rw-r--r--data/maps/the_owl/rooms/Magenta Hallway.txtpb5
-rw-r--r--data/maps/the_owl/rooms/R1C4 Left.txtpb1
-rw-r--r--data/maps/the_owl/rooms/R2C1 Left.txtpb1
-rw-r--r--data/maps/the_owl/rooms/R2C2 Bottom.txtpb8
-rw-r--r--data/maps/the_owl/rooms/R2C2 Top.txtpb1
-rw-r--r--data/maps/the_owl/rooms/R2C3 Bottom.txtpb (renamed from data/maps/the_owl/rooms/R2C2.5 Bottom.txtpb)10
-rw-r--r--data/maps/the_owl/rooms/Z Room.txtpb1
-rw-r--r--data/maps/the_parthenon/connections.txtpb1
-rw-r--r--data/maps/the_parthenon/doors.txtpb17
-rw-r--r--data/maps/the_parthenon/rooms/Ending.txtpb1
-rw-r--r--data/maps/the_parthenon/rooms/K2 Room.txtpb1
-rw-r--r--data/maps/the_parthenon/rooms/Lavender Area.txtpb1
-rw-r--r--data/maps/the_parthenon/rooms/Main Area.txtpb25
-rw-r--r--data/maps/the_parthenon/rooms/U Keyholder.txtpb2
-rw-r--r--data/maps/the_partial/doors.txtpb1
-rw-r--r--data/maps/the_partial/rooms/Control Center Entrance.txtpb7
-rw-r--r--data/maps/the_partial/rooms/F Room.txtpb1
-rw-r--r--data/maps/the_partial/rooms/Obverse Side.txtpb6
-rw-r--r--data/maps/the_partial/rooms/P Room.txtpb1
-rw-r--r--data/maps/the_partial/rooms/Reverse Side.txtpb1
-rw-r--r--data/maps/the_perceptive/rooms/Main Area.txtpb7
-rw-r--r--data/maps/the_plaza/connections.txtpb8
-rw-r--r--data/maps/the_plaza/doors.txtpb17
-rw-r--r--data/maps/the_plaza/rooms/Bottom Left Room.txtpb1
-rw-r--r--data/maps/the_plaza/rooms/Bottom Right Room.txtpb1
-rw-r--r--data/maps/the_plaza/rooms/Center Room.txtpb1
-rw-r--r--data/maps/the_plaza/rooms/Main Area.txtpb13
-rw-r--r--data/maps/the_plaza/rooms/Mastery.txtpb1
-rw-r--r--data/maps/the_plaza/rooms/Repetitive Entrance.txtpb5
-rw-r--r--data/maps/the_plaza/rooms/Sirenic Entrance.txtpb5
-rw-r--r--data/maps/the_plaza/rooms/Symbolic Entrance.txtpb5
-rw-r--r--data/maps/the_plaza/rooms/Top Left Room.txtpb3
-rw-r--r--data/maps/the_plaza/rooms/Top Right Room.txtpb3
-rw-r--r--data/maps/the_quiet/rooms/Keyholder Room.txtpb2
-rw-r--r--data/maps/the_quiet/rooms/Main Area.txtpb5
-rw-r--r--data/maps/the_quiet/rooms/Q Room.txtpb1
-rw-r--r--data/maps/the_relentless/rooms/All.txtpb1
-rw-r--r--data/maps/the_relentless/rooms/Left And Turn.txtpb1
-rw-r--r--data/maps/the_relentless/rooms/Left Room.txtpb1
-rw-r--r--data/maps/the_relentless/rooms/Mastery.txtpb1
-rw-r--r--data/maps/the_relentless/rooms/Shop Room.txtpb1
-rw-r--r--data/maps/the_relentless/rooms/Turn And Shop.txtpb1
-rw-r--r--data/maps/the_relentless/rooms/Turn Room.txtpb1
-rw-r--r--data/maps/the_repetitive/connections.txtpb4
-rw-r--r--data/maps/the_repetitive/doors.txtpb8
-rw-r--r--data/maps/the_repetitive/metadata.txtpb4
-rw-r--r--data/maps/the_repetitive/rooms/Anti Room.txtpb12
-rw-r--r--data/maps/the_repetitive/rooms/Cyan Room.txtpb1
-rw-r--r--data/maps/the_repetitive/rooms/Dot Area.txtpb3
-rw-r--r--data/maps/the_repetitive/rooms/Entry Connector.txtpb8
-rw-r--r--data/maps/the_repetitive/rooms/Lime Room.txtpb1
-rw-r--r--data/maps/the_repetitive/rooms/Magenta Room.txtpb1
-rw-r--r--data/maps/the_repetitive/rooms/Main Room.txtpb7
-rw-r--r--data/maps/the_repetitive/rooms/Mastery Room.txtpb1
-rw-r--r--data/maps/the_repetitive/rooms/Plaza Connector.txtpb5
-rw-r--r--data/maps/the_repetitive/rooms/Yellow Room.txtpb1
-rw-r--r--data/maps/the_revitalized/rooms/Bye Room.txtpb5
-rw-r--r--data/maps/the_revitalized/rooms/Hidden Room.txtpb1
-rw-r--r--data/maps/the_revitalized/rooms/Hide Room.txtpb1
-rw-r--r--data/maps/the_revitalized/rooms/High Room.txtpb1
-rw-r--r--data/maps/the_revitalized/rooms/Return Room.txtpb1
-rw-r--r--data/maps/the_revitalized/rooms/Too Room.txtpb1
-rw-r--r--data/maps/the_revitalized/rooms/Won Room.txtpb1
-rw-r--r--data/maps/the_shop/rooms/Main Area.txtpb5
-rw-r--r--data/maps/the_sirenic/rooms/Mastery.txtpb1
-rw-r--r--data/maps/the_sirenic/rooms/Puzzles.txtpb1
-rw-r--r--data/maps/the_sirenic/rooms/Start.txtpb5
-rw-r--r--data/maps/the_stormy/rooms/Center.txtpb7
-rw-r--r--data/maps/the_stormy/rooms/Nuclear Side.txtpb1
-rw-r--r--data/maps/the_stormy/rooms/Nuclear Vestibule.txtpb1
-rw-r--r--data/maps/the_stormy/rooms/Rain Side.txtpb3
-rw-r--r--data/maps/the_stormy/rooms/Tornado Side.txtpb1
-rw-r--r--data/maps/the_stormy/rooms/Tornado Vestibule.txtpb1
-rw-r--r--data/maps/the_stormy/rooms/Volcano Side.txtpb1
-rw-r--r--data/maps/the_stormy/rooms/X2 Room.txtpb1
-rw-r--r--data/maps/the_sturdy/rooms/Main Area.txtpb23
-rw-r--r--data/maps/the_sturdy/rooms/S2 Area.txtpb1
-rw-r--r--data/maps/the_sun_temple/connections.txtpb1
-rw-r--r--data/maps/the_sun_temple/rooms/Ending.txtpb1
-rw-r--r--data/maps/the_sun_temple/rooms/Entrance.txtpb6
-rw-r--r--data/maps/the_sun_temple/rooms/Mastery.txtpb1
-rw-r--r--data/maps/the_sun_temple/rooms/Temple.txtpb15
-rw-r--r--data/maps/the_sweet/rooms/Main Area.txtpb7
-rw-r--r--data/maps/the_sweet/rooms/Y2 Room.txtpb1
-rw-r--r--data/maps/the_symbolic/doors.txtpb43
-rw-r--r--data/maps/the_symbolic/rooms/Poetry Room 1.txtpb4
-rw-r--r--data/maps/the_symbolic/rooms/Poetry Room 3.txtpb2
-rw-r--r--data/maps/the_symbolic/rooms/Poetry Room Left.txtpb2
-rw-r--r--data/maps/the_symbolic/rooms/Poetry Room Right.txtpb2
-rw-r--r--data/maps/the_symbolic/rooms/Red Blue Room.txtpb4
-rw-r--r--data/maps/the_symbolic/rooms/White Room.txtpb3
-rw-r--r--data/maps/the_talented/rooms/Main Area.txtpb4
-rw-r--r--data/maps/the_tenacious/rooms/Control Center Entrance.txtpb5
-rw-r--r--data/maps/the_tenacious/rooms/Main Area.txtpb1
-rw-r--r--data/maps/the_three_doors/doors.txtpb1
-rw-r--r--data/maps/the_three_doors/rooms/Dead End Room.txtpb6
-rw-r--r--data/maps/the_three_doors/rooms/First Second Room.txtpb6
-rw-r--r--data/maps/the_three_doors/rooms/Loose Strings Room.txtpb3
-rw-r--r--data/maps/the_three_doors/rooms/One Luck Room.txtpb3
-rw-r--r--data/maps/the_three_doors/rooms/Silver Portal Room.txtpb6
-rw-r--r--data/maps/the_tower/rooms/First Floor.txtpb3
-rw-r--r--data/maps/the_tree/doors.txtpb1
-rw-r--r--data/maps/the_tree/rooms/Bearer Entrance.txtpb3
-rw-r--r--data/maps/the_tree/rooms/Main Area.txtpb14
-rw-r--r--data/maps/the_unkempt/connections.txtpb60
-rw-r--r--data/maps/the_unkempt/doors.txtpb184
-rw-r--r--data/maps/the_unkempt/metadata.txtpb1
-rw-r--r--data/maps/the_unkempt/rooms/Control Center Entrance.txtpb17
-rw-r--r--data/maps/the_unkempt/rooms/Daedalus Entrance.txtpb8
-rw-r--r--data/maps/the_unkempt/rooms/Exit Room 2.txtpb29
-rw-r--r--data/maps/the_unkempt/rooms/Exit Room 3.txtpb8
-rw-r--r--data/maps/the_unkempt/rooms/Main Area.txtpb238
-rw-r--r--data/maps/the_unkempt/rooms/Middle Room.txtpb29
-rw-r--r--data/maps/the_unkempt/rooms/Right Area.txtpb163
-rw-r--r--data/maps/the_unkempt/rooms/Unsymmetry Room.txtpb99
-rw-r--r--data/maps/the_unkempt/rooms/V Keyholder.txtpb6
-rw-r--r--data/maps/the_unkempt/rooms/V1 Room.txtpb5
-rw-r--r--data/maps/the_unkempt/rooms/W Keyholder.txtpb6
-rw-r--r--data/maps/the_unkempt/rooms/W2 Room.txtpb6
-rw-r--r--data/maps/the_unyielding/doors.txtpb26
-rw-r--r--data/maps/the_unyielding/rooms/Bearer Entrance.txtpb3
-rw-r--r--data/maps/the_unyielding/rooms/Digital Entrance.txtpb3
-rw-r--r--data/maps/the_unyielding/rooms/Nuanced Entrance.txtpb3
-rw-r--r--data/maps/the_unyielding/rooms/Plaza Entrance.txtpb3
-rw-r--r--data/maps/the_unyielding/rooms/Yellow Left.txtpb1
-rw-r--r--data/maps/the_unyielding/rooms/Yellow Right.txtpb1
-rw-r--r--data/maps/the_wise/connections.txtpb10
-rw-r--r--data/maps/the_wise/doors.txtpb36
-rw-r--r--data/maps/the_wise/metadata.txtpb3
-rw-r--r--data/maps/the_wise/rooms/Entry.txtpb12
-rw-r--r--data/maps/the_wise/rooms/Mastery.txtpb5
-rw-r--r--data/maps/the_wise/rooms/Puzzles.txtpb151
-rw-r--r--data/maps/the_wondrous/connections.txtpb10
-rw-r--r--data/maps/the_wondrous/doors.txtpb24
-rw-r--r--data/maps/the_wondrous/metadata.txtpb1
-rw-r--r--data/maps/the_wondrous/rooms/Entry.txtpb14
-rw-r--r--data/maps/the_wondrous/rooms/Huge.txtpb57
-rw-r--r--data/maps/the_wondrous/rooms/Regular.txtpb8
-rw-r--r--data/maps/the_words/connections.txtpb5
-rw-r--r--data/maps/the_words/doors.txtpb12
-rw-r--r--data/maps/the_words/metadata.txtpb11
-rw-r--r--data/maps/the_words/rooms/Ending.txtpb5
-rw-r--r--data/maps/the_words/rooms/Main Area.txtpb64
-rw-r--r--data/metadata.txtpb54
-rw-r--r--data/progressives.txtpb11
-rw-r--r--proto/data.proto83
-rw-r--r--proto/human.proto76
-rw-r--r--tools/assign_ids/main.cpp195
-rw-r--r--tools/datapacker/container.cpp38
-rw-r--r--tools/datapacker/container.h6
-rw-r--r--tools/datapacker/main.cpp141
-rw-r--r--tools/util/godot_scene.cpp6
-rw-r--r--tools/util/ids_yaml_format.cpp39
-rw-r--r--tools/validator/CMakeLists.txt3
-rw-r--r--tools/validator/human_processor.cpp184
-rw-r--r--tools/validator/structs.h35
-rw-r--r--tools/validator/validator.cpp673
-rw-r--r--tools/validator/validator.h2
-rw-r--r--vcpkg.json3
-rw-r--r--vendor/godobuf/LICENSE29
-rw-r--r--vendor/godobuf/README4
-rw-r--r--vendor/godobuf/addons/protobuf/parser.gd2254
-rw-r--r--vendor/godobuf/addons/protobuf/plugin.cfg7
-rw-r--r--vendor/godobuf/addons/protobuf/protobuf_cmdln.gd66
-rw-r--r--vendor/godobuf/addons/protobuf/protobuf_core.gd668
-rw-r--r--vendor/godobuf/addons/protobuf/protobuf_util.gd46
-rw-r--r--vendor/godobuf/default_env.tres7
-rw-r--r--vendor/godobuf/logo.pngbin0 -> 19026 bytes
-rw-r--r--vendor/godobuf/logo.png.import35
-rw-r--r--vendor/godobuf/project.godot26
680 files changed, 15272 insertions, 1419 deletions
diff --git a/.gitignore b/.gitignore index b30b031..05901b2 100644 --- a/.gitignore +++ b/.gitignore
@@ -5,3 +5,4 @@ apworld/generated/
5__pycache__ 5__pycache__
6.vs/ 6.vs/
7^out/ 7^out/
8client/Archipelago/generated/
diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..e32a5fd --- /dev/null +++ b/CHANGELOG.md
@@ -0,0 +1,180 @@
1# lingo2-archipelago Releases
2
3## v7.0.0 - 2025-09-30
4
5- Major update! First and foremost: the client and apworld are no longer
6 separate! There is only an apworld now, which you install into your
7 Archipelago custom worlds folder as per normal. In order to play a randomized
8 world, you open the Archipelago Launcher and click Lingo 2 Client. The first
9 time you do this, it will ask you for the location of your Lingo2.exe, which
10 you can find by right clicking on the game in Steam and clicking Browse Local
11 Files.
12- **Built-in tracker**: The in-game text client has a new tab called "Locations"
13 which lists the currently accessible locations similar to how Universal
14 Tracker does it. There is also an optional overlay you can enable in the
15 settings, which shows you some of your accessible locations on screen while
16 you're playing. If you're playing with vanilla letters, the tracker won't show
17 you locations that are solvable with letters until you collect the actual
18 letters, in order to help direct you better. More features will be coming to
19 the tracker in the future!
20- **Worldport shuffle**: The first part of entrance randomization is here!
21 Enabling this shuffles the destinations of the worldports, which are the
22 loading zones you walk into in order to change maps. Some restrictions apply,
23 which are noted in the option description. The tracker will show a list of
24 worldports you haven't entered yet, and will also not show you what lies
25 beyond a worldport until you've entered it. There is also a tab in the
26 textclient showing you the mapping between worldports you've already entered.
27- **Minimap**: There is an option in the settings to show a minimap in the
28 corner of the screen. This shows an overhead view of the map you're on, and
29 where you are in it. More features will be coming to the minimap in the
30 future!
31- Fixed the gate outside the Daedalus entrance in The Great not opening when
32 control center colors are shuffled.
33
34Download:
35[lingo2.apworld](https://files.fourisland.com/releases/lingo2-archipelago/apworld/v7.0.0/lingo2.apworld)<br/>
36Template YAML:
37[Lingo 2.yaml](https://files.fourisland.com/releases/lingo2-archipelago/apworld/v7.0.0/Lingo%202.yaml)<br/>
38Source: [v7.0.0](https://code.fourisland.com/lingo2-archipelago/tag/?h=v7.0.0)
39
40## Legacy Client v6.7 - 2025-09-19
41
42- Added a compass overlay. This makes it clearer which direction corresponds to
43 which compass direction, which is useful since many location/item names
44 reference compass directions. It can be enabled in the settings screen on the
45 pause menu.
46- Compatability update for the changes in v6.6 of the apworld.
47
48Download:
49[lingo2-archipelago-client-v6.7.zip](https://files.fourisland.com/releases/lingo2-archipelago/client/lingo2-archipelago-client-v6.7.zip)<br/>
50Source:
51[v6.7](https://code.fourisland.com/lingo2-archipelago/tag/?h=client-v6.7)
52
53## Legacy Apworld v6.6 - 2025-09-19
54
55- Added options that make the requirements for Purple Ending and Cyan Ending
56 stricter. With the strict options on, players are required to have all purple
57 (level 1) letters in order to get Purple Ending, and all cyan (level 2)
58 letters to get Cyan Ending. These options are on by default.
59- Renamed several items and locations, mostly regarding changing relative
60 directions (left, right, etc) to compass directions. The colored SMILE panels
61 in Daedalus now have clearer names too.
62- Fixed some minor logic errors.
63
64Download:
65[lingo2.apworld](https://files.fourisland.com/releases/lingo2-archipelago/apworld/v6.6/lingo2.apworld)<br/>
66Template YAML:
67[Lingo 2.yaml](https://files.fourisland.com/releases/lingo2-archipelago/apworld/v6.6/Lingo%202.yaml)<br/>
68Source:
69[v6.6](https://code.fourisland.com/lingo2-archipelago/tag/?h=apworld-v6.6)
70
71## Legacy Client v5.6 - 2025-09-17
72
73- Letter locations will no longer reappear after being collected.
74- This also prevents a potential scenario in which it is impossible to access
75 the location "The Congruent - Obverse Yellow Puzzles" when door shuffle is
76 disabled.
77
78Download:
79[lingo2-archipelago-client-v5.6.zip](https://files.fourisland.com/releases/lingo2-archipelago/client/lingo2-archipelago-client-v5.6.zip)<br/>
80Source:
81[v5.6](https://code.fourisland.com/lingo2-archipelago/tag/?h=client-v5.6)
82
83## Legacy Client v5.5 - 2025-09-16
84
85- Compatability update for v5.5 of the apworld.
86
87Download:
88[lingo2-archipelago-client-v5.5.zip](https://files.fourisland.com/releases/lingo2-archipelago/client/lingo2-archipelago-client-v5.5.zip)<br/>
89Source:
90[v5.5](https://code.fourisland.com/lingo2-archipelago/tag/?h=client-v5.5)
91
92## Legacy Apworld v5.5 - 2025-09-16
93
94- Fixed a panel in The Ancient that was missing a symbol.
95- Fixed an issue where you could be expected to get S1 in The Darkroom without
96 having U.
97- Renamed a few locations.
98
99Download:
100[lingo2.apworld](https://files.fourisland.com/releases/lingo2-archipelago/apworld/v5.5/lingo2.apworld)<br/>
101Template YAML:
102[Lingo 2.yaml](https://files.fourisland.com/releases/lingo2-archipelago/apworld/v5.5/Lingo%202.yaml)<br/>
103Source:
104[v5.5](https://code.fourisland.com/lingo2-archipelago/tag/?h=apworld-v5.5)
105
106## Legacy Apworld v4.4 - 2025-09-14
107
108- Fixed panel set location names.
109
110Download:
111[lingo2.apworld](https://files.fourisland.com/releases/lingo2-archipelago/apworld/v4.4/lingo2.apworld)<br/>
112Template YAML:
113[Lingo 2.yaml](https://files.fourisland.com/releases/lingo2-archipelago/apworld/v4.4/Lingo%202.yaml)<br/>
114Source:
115[v4.4](https://code.fourisland.com/lingo2-archipelago/tag/?h=apworld-v4.4)
116
117## Legacy Client v4.4 - 2025-09-13
118
119- Added support for anti-collectable trap items.
120- Fixed entrance to The Jubilant not opening properly when using control center
121 color shuffle.
122- Fixed the location "The Entry (Colored Doors Area) - OPEN" not sending.
123- Fixed level 2 letters not activating properly when letter shuffle is set to
124 Item Cyan.
125- Messages are now cleared out when returning to the main menu.
126- The player is prevented from accidentally breaking roof access logic when
127 returning to Daedalus from Icarus.
128
129Download:
130[lingo2-archipelago-client-v4.4.zip](https://files.fourisland.com/releases/lingo2-archipelago/client/lingo2-archipelago-client-v4.4.zip)<br/>
131Source:
132[v4.4](https://code.fourisland.com/lingo2-archipelago/tag/?h=client-v4.4)
133
134## Legacy Apworld v4.3 - 2025-09-13
135
136- Added a location for the anti-collectable in The Repetitive.
137- Added trap items. These remove letters from your keyboard until you use the
138 Key Return in The Entry, similar to the anti-collectable in The Repetitive.
139 This can be controlled using the `trap_percentage` option, which defaults to
140 zero.
141- Fixed crash on load when using Python 3.11.
142
143Download:
144[lingo2.apworld](https://files.fourisland.com/releases/lingo2-archipelago/apworld/v4.3/lingo2.apworld)<br/>
145Template YAML:
146[Lingo 2.yaml](https://files.fourisland.com/releases/lingo2-archipelago/apworld/v4.3/Lingo%202.yaml)<br/>
147Source:
148[v4.3](https://code.fourisland.com/lingo2-archipelago/tag/?h=apworld-v4.3)
149
150## Legacy Client v3.3 - 2025-09-12
151
152- Fixed issue downloading large datapackages (such as TUNIC's).
153- Connection failures now show error messages.
154
155Download:
156[lingo2-archipelago-client-v3.3.zip](https://files.fourisland.com/releases/lingo2-archipelago/client/lingo2-archipelago-client-v3.3.zip)<br/>
157Source:
158[v3.3](https://code.fourisland.com/lingo2-archipelago/tag/?h=client-v3.3)
159
160## Legacy Client v3.2 - 2025-09-12
161
162- Initial release for testing. Features include door shuffle, letter shuffle,
163 and symbol shuffle.
164
165Download:
166[lingo2-archipelago-client-v3.2.zip](https://files.fourisland.com/releases/lingo2-archipelago/client/lingo2-archipelago-client-v3.2.zip)<br/>
167Source:
168[v3.2](https://code.fourisland.com/lingo2-archipelago/tag/?h=client-v3.2)
169
170## Legacy Apworld v3.2 - 2025-09-12
171
172- Initial release for testing. Features include door shuffle, letter shuffle,
173 and symbol shuffle.
174
175Download:
176[lingo2.apworld](https://files.fourisland.com/releases/lingo2-archipelago/apworld/v3.2/lingo2.apworld)<br/>
177Template YAML:
178[Lingo 2.yaml](https://files.fourisland.com/releases/lingo2-archipelago/apworld/v3.2/Lingo%202.yaml)<br/>
179Source:
180[v3.2](https://code.fourisland.com/lingo2-archipelago/tag/?h=apworld-v3.2)
diff --git a/README.md b/README.md new file mode 100644 index 0000000..2899e4a --- /dev/null +++ b/README.md
@@ -0,0 +1,190 @@
1# lingo2-archipelago
2
3[Archipelago](https://archipelago.gg/) is an open-source project that supports
4randomizing a number of different games and combining them into one cooperative
5experience. Items from each game are hidden in other games. For more information
6about Archipelago, you can look at their website.
7
8This is a project that modifies the game
9[Lingo 2](https://www.lingothegame.com/lingo2.html) so that it can be played as
10part of an Archipelago multiworld game.
11
12## Installation
13
141. Download the Lingo 2 Apworld from
15 [the releases page](https://code.fourisland.com/lingo2-archipelago/about/CHANGELOG.md).
162. If you do not already have it, download and install the
17 [Archipelago software](https://github.com/ArchipelagoMW/Archipelago/releases/).
183. Double click on `lingo2.apworld` to install it, or copy it manually to the
19 `custom_worlds` folder of your Archipelago installation.
20
21## Joining a Multiworld game
22
231. Open the Archipelago Launcher.
242. Select "Lingo 2 Client".
253. The first time you do this, Archipelago will prompt you for the location of
26 the Lingo 2 executable file ("Lingo2.exe"). You can find this by
27 right-clicking on Lingo 2 in Steam, going to "Manage", and clicking "Browse
28 local files".
294. Lingo 2 will open, and you will see a form asking for your connection
30 details. Enter the Archipelago address, slot name, and password into the
31 fields.
325. Press Connect.
336. Enjoy!
34
35To continue an earlier game, you can perform the exact same steps as above.
36
37## Frequently Asked Questions
38
39### Why aren't the starting room letters shuffled?
40
41The letter requirements for solving puzzles are very restrictive, especially in
42the early game. It is possible for the generator to find some subset of letters
43and doors to place in the starting room such that you are not trapped, but this
44places a lot of strain on generation and leads to significantly more generation
45failures.
46
47As a result, the starting room letters (H1, I1, N1, and T1) are always present
48in the starting room, even when remote letter shuffle is enabled. These letters
49will _also_ count as clearing a check, so you will send out another item at the
50same time as collecting the letter.
51
52### What areas are randomized?
53
54Almost all maps that you can access from the base game are randomized. The
55exceptions are:
56
57- Icarus (this will be randomized at some point, although it will be optional)
58- Demo
59- The Hinterlands (this will probably be repurposed)
60- The beta tester gift maps
61
62### Is my progress saved locally?
63
64Lingo 2 autosaves your progress every time you solve a puzzle, get a
65collectable, or interact with a keyholder. The randomizer generates a savefile
66name based on your Multiworld seed and slot number, so you should be able to
67seamlessly switch between multiworlds and even slots within a multiworld.
68
69The exception to this is different rooms created from the same multiworld seed.
70The client is unable to tell rooms in a seed apart (this is a limitation of the
71Archipelago API), so the client will use the same save file for the same slot in
72different rooms on the same seed. You can work around this by manually moving or
73removing the save folder from the users directory in Lingo 2's game files.
74
75If you play the base game again, you will see one or more save files with a long
76name that begins with "zzAP\_". These are the saves for your multiworlds. They
77can be safely deleted after you have completed the associated multiworld. It is
78not recommended to load these save files outside of the randomizer.
79
80A connection to Archipelago is required to resume playing a multiworld. This is
81because the set of items you have received is not stored locally.
82
83### What about wall snipes?
84
85"Wall sniping" refers to the fact that you are able to solve puzzles on the
86other side of opaque walls. The player is never expected to or required to do
87this in normal gameplay. This randomizer does not change how wall snipes work,
88but it will likewise never require the use of them.
89
90### How do cyan doors work?
91
92In the base game, there are a number of cyan-colored doors that ordinarily open
93once you collect H2 in The Repetitive. There are also a handful of panels that
94only appear upon getting H2 as well, which the apworld treats the same as the
95cyan doors.
96
97There is an option that lets you choose how these doors and panels behave. By
98default, they act the same as in the base game: they only open or appear after
99collecting H2. Note that this means the actual H2 collectable in The Repetitive.
100Receiving H2 via remote letter shuffle does not count for this requirement.
101However, you can also make cyan doors activate upon collecting or receiving your
102first double letter, regardless of what it is or if it's remote. Finally, you
103can lock cyan doors behind an item called "Cyan Doors".
104
105It is important to note, however, that the Cyan Door Behavior option only
106applies to cyan doors that are not already affected by another type of
107shuffling. When door shuffle is on, the following cyan doors are activated by
108individual items and are not impacted by your choice of Cyan Door Behavior:
109
110- The entrance to The Tower from The Great (The Great - Tower Entrance)
111- The entrance to The Butterfly from The Bearer (The Bearer - Butterfly
112 Entrance)
113- The entrance to The Repetitive from The Entry (The Entry - Repetitive
114 Entrance)
115- The eye painting near the yellow color hallway in Daedalus (Daedalus - Eye
116 Painting)
117- The Red I room in The Repetitive (The Repetitive - Anti Collectable Room)
118
119Additionally, when control center color shuffle is enabled, the orange door in
120The Unkempt (which ordinarily doubles as a cyan door) opens upon receiving the
121Control Center Orange Doors item, instead of following the Cyan Door Behavior
122option.
123
124### Help! I lost C/G in The Congruent!
125
126If you place C or G into the relevant keyholders in The Congruent, the keyholder
127disappears. You can retrieve your letter immediately by pressing C or G again
128before leaving solve mode, as the keyholder will still be considered to be
129"focused", even though it has moved. If you have already moved, though, there is
130another way to get your letters back: just use the Key Return in The Entry.
131
132### Why is the tracker telling me to solve a panel that's currently red?
133
134Red usually indicates that a panel cannot be solved because of missing letters.
135However, that only applies to the puzzle's main answer. If a puzzle has
136alternate answers, you may be expected to use one of those instead of the main
137one. As long as you have all of the necessary letters, an alternate answer can
138be typed into a red panel even though it does not show you typing. When you
139finish typing the answer, the panel will solve as normal.
140
141## Running from source
142
143The randomizer is mostly written in Python and GDScript, which do not need to be
144compiled. However, there are three files that need to be generated before the
145apworld can be used.
146
147The first file is `data.binpb`, the datafile containing the randomizer logic.
148You can read about how to generate it on
149[its own README page](https://code.fourisland.com/lingo2-archipelago/about/data/README.md).
150Once you have it, put it in a subfolder of `apworld` called `generated`.
151
152The second generated file is `data_pb2.py`. This file allows Archipelago to read
153the datafile. We use `protoc`, the Protocol Buffer compiler, to generate it. As
154of 0.6.3, Archipelago has protobuf 3.20.3 packaged with it, which means we need
155to compile our proto file with a similar version.
156
157If you followed the steps to generate `data.binpb` and compiled the `datapacker`
158tool yourself, you will already have protobuf version 3.21.12 installed through
159vcpkg. You can then run a command similar to this in order to generate the
160python file.
161
162```shell
163.\out\build\x64-Debug\vcpkg_installed\x64-windows\tools\protobuf\protoc.exe -Iproto\ ^
164 --python_out=apworld\generated\ .\proto\data.proto
165```
166
167The exact path to `protoc.exe` is going to depend on where vcpkg installed its
168packages. The above location is where Visual Studio will probably put it.
169
170The third generated file is `proto.gd`. This is the GDScript version of the
171previous file. We use a Godot script to generate it, which means
172[the Godot Editor](https://godotengine.org/download/) is required. From the root
173of the repository:
174
175```shell
176cd vendor\godobuf
177godot --headless -s addons\protobuf\protobuf_cmdln.gd --input=..\..\proto\data.proto ^
178 --output=..\..\apworld\generated\proto.gd
179```
180
181If you are not on Windows, replace the forward slashes with backslashes as
182appropriate (and the caret with a forward slash). You will also probably need to
183replace "godot" at the start of the second line with a path to a Godot Editor
184executable.
185
186After generating those three files, the apworld should be functional. You can
187copy it into an Archipelago source tree (rename the folder `apworld` to `lingo2`
188if you do so) if you want to edit/debug the code. Otherwise, you can zip up the
189folder and rename it to `lingo2.apworld` in order to package it for
190distribution.
diff --git a/apworld/__init__.py b/apworld/__init__.py index 07e3982..96f6804 100644 --- a/apworld/__init__.py +++ b/apworld/__init__.py
@@ -1,18 +1,38 @@
1""" 1"""
2Archipelago init file for Lingo 2 2Archipelago init file for Lingo 2
3""" 3"""
4from BaseClasses import ItemClassification, Item 4from typing import ClassVar
5
6from BaseClasses import ItemClassification, Item, Tutorial
7from settings import Group, UserFilePath
5from worlds.AutoWorld import WebWorld, World 8from worlds.AutoWorld import WebWorld, World
6from .items import Lingo2Item 9from .items import Lingo2Item, ANTI_COLLECTABLE_TRAPS
7from .options import Lingo2Options 10from .options import Lingo2Options
8from .player_logic import Lingo2PlayerLogic 11from .player_logic import Lingo2PlayerLogic
9from .regions import create_regions 12from .regions import create_regions, shuffle_entrances, connect_ports_from_ut
10from .static_logic import Lingo2StaticLogic 13from .static_logic import Lingo2StaticLogic
14from ..LauncherComponents import Component, Type, components, launch as launch_component, icon_paths
11 15
12 16
13class Lingo2WebWorld(WebWorld): 17class Lingo2WebWorld(WebWorld):
14 rich_text_options_doc = True 18 rich_text_options_doc = True
15 theme = "grass" 19 theme = "grass"
20 tutorials = [Tutorial(
21 "Multiworld Setup Guide",
22 "A guide to playing Lingo 2 with Archipelago.",
23 "English",
24 "en_Lingo_2.md",
25 "setup/en",
26 ["hatkirby"]
27 )]
28
29
30class Lingo2Settings(Group):
31 class ExecutableFile(UserFilePath):
32 """Path to the Lingo 2 executable"""
33 is_exe = True
34
35 exe_file: ExecutableFile = ExecutableFile()
16 36
17 37
18class Lingo2World(World): 38class Lingo2World(World):
@@ -24,21 +44,43 @@ class Lingo2World(World):
24 game = "Lingo 2" 44 game = "Lingo 2"
25 web = Lingo2WebWorld() 45 web = Lingo2WebWorld()
26 46
47 settings: ClassVar[Lingo2Settings]
48 settings_key = "lingo2_options"
49
50 topology_present = True
51
27 options_dataclass = Lingo2Options 52 options_dataclass = Lingo2Options
28 options: Lingo2Options 53 options: Lingo2Options
29 54
30 static_logic = Lingo2StaticLogic() 55 static_logic = Lingo2StaticLogic()
31 item_name_to_id = static_logic.item_name_to_id 56 item_name_to_id = static_logic.item_name_to_id
32 location_name_to_id = static_logic.location_name_to_id 57 location_name_to_id = static_logic.location_name_to_id
58 item_name_groups = static_logic.item_name_groups
59 location_name_groups = static_logic.location_name_groups
60
61 for_tracker: ClassVar[bool] = False
33 62
34 player_logic: Lingo2PlayerLogic 63 player_logic: Lingo2PlayerLogic
35 64
65 port_pairings: dict[int, int]
66
36 def generate_early(self): 67 def generate_early(self):
37 self.player_logic = Lingo2PlayerLogic(self) 68 self.player_logic = Lingo2PlayerLogic(self)
69 self.port_pairings = {}
38 70
39 def create_regions(self): 71 def create_regions(self):
40 create_regions(self) 72 create_regions(self)
41 73
74 def connect_entrances(self):
75 if self.options.shuffle_worldports:
76 if hasattr(self.multiworld, "re_gen_passthrough") and "Lingo 2" in self.multiworld.re_gen_passthrough:
77 slot_value = self.multiworld.re_gen_passthrough["Lingo 2"]["port_pairings"]
78 self.port_pairings = {int(fp): int(tp) for fp, tp in slot_value.items()}
79
80 connect_ports_from_ut(self.port_pairings, self)
81 else:
82 shuffle_entrances(self)
83
42 from Utils import visualize_regions 84 from Utils import visualize_regions
43 85
44 visualize_regions(self.multiworld.get_region("Menu", self.player), "my_world.puml") 86 visualize_regions(self.multiworld.get_region("Menu", self.player), "my_world.puml")
@@ -49,11 +91,78 @@ class Lingo2World(World):
49 total_locations = sum(len(locs) for locs in self.player_logic.locations_by_room.values()) 91 total_locations = sum(len(locs) for locs in self.player_logic.locations_by_room.values())
50 92
51 item_difference = total_locations - len(pool) 93 item_difference = total_locations - len(pool)
94
95 if self.options.trap_percentage > 0:
96 num_traps = int(item_difference * self.options.trap_percentage / 100)
97 item_difference = item_difference - num_traps
98
99 trap_names = []
100 trap_weights = []
101 for letter_name, weight in self.static_logic.letter_weights.items():
102 trap_names.append(f"Anti {letter_name}")
103 trap_weights.append(weight)
104
105 bad_letters = self.random.choices(trap_names, weights=trap_weights, k=num_traps)
106 pool += [self.create_item(trap_name) for trap_name in bad_letters]
107
52 for i in range(0, item_difference): 108 for i in range(0, item_difference):
53 pool.append(self.create_item("Nothing")) 109 pool.append(self.create_item(self.get_filler_item_name()))
54 110
55 self.multiworld.itempool += pool 111 self.multiworld.itempool += pool
56 112
57 def create_item(self, name: str) -> Item: 113 def create_item(self, name: str) -> Item:
58 return Lingo2Item(name, ItemClassification.filler if name == "Nothing" else ItemClassification.progression, 114 return Lingo2Item(name, ItemClassification.filler if name == self.get_filler_item_name() else
115 ItemClassification.trap if name in ANTI_COLLECTABLE_TRAPS else
116 ItemClassification.progression,
59 self.item_name_to_id.get(name), self.player) 117 self.item_name_to_id.get(name), self.player)
118
119 def set_rules(self):
120 self.multiworld.completion_condition[self.player] = lambda state: state.has("Victory", self.player)
121
122 def fill_slot_data(self):
123 slot_options = [
124 "cyan_door_behavior",
125 "daedalus_roof_access",
126 "keyholder_sanity",
127 "shuffle_control_center_colors",
128 "shuffle_doors",
129 "shuffle_gallery_paintings",
130 "shuffle_letters",
131 "shuffle_symbols",
132 "shuffle_worldports",
133 "strict_cyan_ending",
134 "strict_purple_ending",
135 "victory_condition",
136 ]
137
138 slot_data: dict[str, object] = {
139 **self.options.as_dict(*slot_options),
140 "version": self.static_logic.get_data_version(),
141 }
142
143 if self.options.shuffle_worldports:
144 slot_data["port_pairings"] = self.port_pairings
145
146 return slot_data
147
148 def get_filler_item_name(self) -> str:
149 return "A Job Well Done"
150
151 # for the universal tracker, doesn't get called in standard gen
152 # docs: https://github.com/FarisTheAncient/Archipelago/blob/tracker/worlds/tracker/docs/re-gen-passthrough.md
153 @staticmethod
154 def interpret_slot_data(slot_data: dict[str, object]) -> dict[str, object]:
155 # returning slot_data so it regens, giving it back in multiworld.re_gen_passthrough
156 # we are using re_gen_passthrough over modifying the world here due to complexities with ER
157 return slot_data
158
159
160def launch_client(*args):
161 from .context import client_main
162 launch_component(client_main, name="Lingo2Client", args=args)
163
164
165icon_paths["lingo2_ico"] = f"ap:{__name__}/logo.png"
166component = Component("Lingo 2 Client", component_type=Type.CLIENT, func=launch_client,
167 description="Open Lingo 2.", supports_uri=True, game_name="Lingo 2", icon="lingo2_ico")
168components.append(component)
diff --git a/apworld/client/animationListener.gd b/apworld/client/animationListener.gd new file mode 100644 index 0000000..c3b26db --- /dev/null +++ b/apworld/client/animationListener.gd
@@ -0,0 +1,38 @@
1extends "res://scripts/nodes/listeners/animationListener.gd"
2
3var item_id
4var item_amount
5
6
7func _ready():
8 var node_path = String(
9 get_tree().get_root().get_node("scene").get_path_to(self).get_concatenated_names()
10 )
11
12 var gamedata = global.get_node("Gamedata")
13 var door_id = gamedata.get_door_for_map_node_path(global.map, node_path)
14 if door_id != null:
15 var ap = global.get_node("Archipelago")
16 var item_lock = ap.get_item_id_for_door(door_id)
17
18 if item_lock != null:
19 item_id = item_lock[0]
20 item_amount = item_lock[1]
21
22 self.senders = []
23 self.senderGroup = []
24 self.nested = false
25 self.complete_at = 0
26 self.max_length = 0
27 self.excludeSenders = []
28
29 call_deferred("_readier")
30
31 super._ready()
32
33
34func _readier():
35 var ap = global.get_node("Archipelago")
36
37 if ap.client.getItemAmount(item_id) >= item_amount:
38 handleTriggered()
diff --git a/apworld/client/apworld_runtime.gd b/apworld/client/apworld_runtime.gd new file mode 100644 index 0000000..faf8e0c --- /dev/null +++ b/apworld/client/apworld_runtime.gd
@@ -0,0 +1,44 @@
1extends Node
2
3var apworld_reader
4
5
6func _init(path):
7 apworld_reader = ZIPReader.new()
8 apworld_reader.open(path)
9
10
11func _get_true_path(path):
12 if path.begins_with("../"):
13 return "lingo2/%s" % path.substr(3)
14 else:
15 return "lingo2/client/%s" % path
16
17
18func load_script(path):
19 var true_path = _get_true_path(path)
20
21 var script = GDScript.new()
22 script.source_code = apworld_reader.read_file(true_path).get_string_from_utf8()
23 script.reload()
24
25 return script
26
27
28func read_path(path):
29 var true_path = _get_true_path(path)
30 return apworld_reader.read_file(true_path)
31
32
33func load_script_as_scene(path, scene_name):
34 var script = load_script(path)
35 var instance = script.new()
36 instance.name = scene_name
37
38 get_tree().unload_current_scene()
39 _load_scene.call_deferred(instance)
40
41
42func _load_scene(instance):
43 get_tree().get_root().add_child(instance)
44 get_tree().current_scene = instance
diff --git a/apworld/client/assets/goal.png b/apworld/client/assets/goal.png new file mode 100644 index 0000000..bd1650d --- /dev/null +++ b/apworld/client/assets/goal.png
Binary files differ
diff --git a/apworld/client/assets/location.png b/apworld/client/assets/location.png new file mode 100644 index 0000000..5304deb --- /dev/null +++ b/apworld/client/assets/location.png
Binary files differ
diff --git a/apworld/client/assets/worldport.png b/apworld/client/assets/worldport.png new file mode 100644 index 0000000..19dfdc3 --- /dev/null +++ b/apworld/client/assets/worldport.png
Binary files differ
diff --git a/apworld/client/client.gd b/apworld/client/client.gd new file mode 100644 index 0000000..62d7fd8 --- /dev/null +++ b/apworld/client/client.gd
@@ -0,0 +1,265 @@
1extends Node
2
3const ap_version = {"major": 0, "minor": 6, "build": 3, "class": "Version"}
4
5var SCRIPT_websocketserver
6
7var _server
8var _should_process = false
9
10var _remote_version = {"major": 0, "minor": 0, "build": 0}
11var _gen_version = {"major": 0, "minor": 0, "build": 0}
12
13var ap_server = ""
14var ap_user = ""
15var ap_pass = ""
16
17var _seed = ""
18var _team = 0
19var _slot = 0
20var _checked_locations = []
21var _checked_worldports = []
22var _received_indexes = []
23var _received_items = {}
24var _slot_data = {}
25var _accessible_locations = []
26var _accessible_worldports = []
27var _goal_accessible = false
28
29signal could_not_connect
30signal connect_status
31signal client_connected(slot_data)
32signal item_received(item, amount)
33signal location_scout_received(location_id, item_name, player_name, flags, for_self)
34signal text_message_received(message)
35signal item_sent_notification(message)
36signal hint_received(message)
37signal accessible_locations_updated
38signal checked_locations_updated
39signal checked_worldports_updated
40signal keyboard_update_received
41
42
43func _init():
44 set_process_mode(Node.PROCESS_MODE_ALWAYS)
45
46 global._print("Instantiated APClient")
47
48
49func _ready():
50 _server = SCRIPT_websocketserver.new()
51 _server.client_connected.connect(_on_web_socket_server_client_connected)
52 _server.client_disconnected.connect(_on_web_socket_server_client_disconnected)
53 _server.message_received.connect(_on_web_socket_server_message_received)
54 add_child(_server)
55 _server.listen(43182)
56
57
58func _reset_state():
59 _should_process = false
60 _received_items = {}
61 _received_indexes = []
62 _checked_worldports = []
63 _accessible_locations = []
64 _accessible_worldports = []
65 _goal_accessible = false
66
67
68func disconnect_from_ap():
69 sendMessage([{"cmd": "Disconnect"}])
70
71
72func _on_web_socket_server_client_connected(peer_id: int) -> void:
73 var peer: WebSocketPeer = _server.peers[peer_id]
74 print("Remote client connected: %d. Protocol: %s" % [peer_id, peer.get_selected_protocol()])
75 _server.send(-peer_id, "[%d] connected" % peer_id)
76
77
78func _on_web_socket_server_client_disconnected(peer_id: int) -> void:
79 var peer: WebSocketPeer = _server.peers[peer_id]
80 print(
81 (
82 "Remote client disconnected: %d. Code: %d, Reason: %s"
83 % [peer_id, peer.get_close_code(), peer.get_close_reason()]
84 )
85 )
86 _server.send(-peer_id, "[%d] disconnected" % peer_id)
87
88
89func _on_web_socket_server_message_received(_peer_id: int, packet: String) -> void:
90 global._print("Got data from server: " + packet)
91 var json = JSON.new()
92 var jserror = json.parse(packet)
93 if jserror != OK:
94 global._print("Error parsing packet from AP: " + jserror.error_string)
95 return
96
97 for message in json.data:
98 var cmd = message["cmd"]
99 global._print("Received command: " + cmd)
100
101 if cmd == "Connected":
102 _seed = message["seed_name"]
103 _remote_version = message["version"]
104 _gen_version = message["generator_version"]
105 _team = message["team"]
106 _slot = message["slot"]
107 _slot_data = message["slot_data"]
108
109 _checked_locations = []
110 for location in message["checked_locations"]:
111 _checked_locations.append(int(message["checked_locations"]))
112
113 client_connected.emit(_slot_data)
114
115 elif cmd == "ConnectionRefused":
116 could_not_connect.emit(message["text"])
117 global._print("Connection to AP refused")
118
119 elif cmd == "UpdateLocations":
120 for location in message["locations"]:
121 var lint = int(location)
122 if not _checked_locations.has(lint):
123 _checked_locations.append(lint)
124
125 checked_locations_updated.emit()
126
127 elif cmd == "UpdateWorldports":
128 for port_id in message["worldports"]:
129 var lint = int(port_id)
130 if not _checked_worldports.has(lint):
131 _checked_worldports.append(lint)
132
133 checked_worldports_updated.emit()
134
135 elif cmd == "ItemReceived":
136 for item in message["items"]:
137 var index = int(item["index"])
138 if _received_indexes.has(index):
139 # Do not re-process items.
140 continue
141
142 _received_indexes.append(index)
143
144 var item_id = int(item["id"])
145 _received_items[item_id] = _received_items.get(item_id, 0) + 1
146
147 item_received.emit(item, _received_items[item_id])
148
149 elif cmd == "TextMessage":
150 text_message_received.emit(message["data"])
151
152 elif cmd == "ItemSentNotif":
153 item_sent_notification.emit(message)
154
155 elif cmd == "HintReceived":
156 hint_received.emit(message)
157
158 elif cmd == "LocationInfo":
159 for loc in message["locations"]:
160 location_scout_received.emit(
161 int(loc["id"]),
162 loc["item"],
163 loc["player"],
164 int(loc["flags"]),
165 int(loc["for_self"])
166 )
167
168 elif cmd == "AccessibleLocations":
169 _accessible_locations.clear()
170 _accessible_worldports.clear()
171
172 for loc in message["locations"]:
173 _accessible_locations.append(int(loc))
174
175 if "worldports" in message:
176 for port_id in message["worldports"]:
177 _accessible_worldports.append(int(port_id))
178
179 _goal_accessible = bool(message.get("goal", false))
180
181 accessible_locations_updated.emit()
182
183 elif cmd == "UpdateKeyboard":
184 var updates = {}
185 for k in message["updates"]:
186 updates[k] = int(message["updates"][k])
187
188 keyboard_update_received.emit(updates)
189
190
191func connectToServer(server, un, pw):
192 sendMessage([{"cmd": "Connect", "server": server, "player": un, "password": pw}])
193
194 ap_server = server
195 ap_user = un
196 ap_pass = pw
197
198 _should_process = true
199
200 connect_status.emit("Connecting...")
201
202
203func sendMessage(msg):
204 var payload = JSON.stringify(msg)
205 _server.send(0, payload)
206
207
208func connectToRoom():
209 connect_status.emit("Authenticating...")
210
211 sendMessage(
212 [
213 {
214 "cmd": "Connect",
215 "password": ap_pass,
216 "game": "Lingo 2",
217 "name": ap_user,
218 }
219 ]
220 )
221
222
223func requestSync():
224 sendMessage([{"cmd": "Sync"}])
225
226
227func sendLocation(loc_id):
228 sendMessage([{"cmd": "LocationChecks", "locations": [loc_id]}])
229
230
231func sendLocations(loc_ids):
232 sendMessage([{"cmd": "LocationChecks", "locations": loc_ids}])
233
234
235func say(textdata):
236 sendMessage([{"cmd": "Say", "text": textdata}])
237
238
239func completedGoal():
240 sendMessage([{"cmd": "StatusUpdate", "status": 30}]) # CLIENT_GOAL
241
242
243func scoutLocations(loc_ids):
244 sendMessage([{"cmd": "LocationScouts", "locations": loc_ids}])
245
246
247func updateKeyboard(updates):
248 sendMessage([{"cmd": "UpdateKeyboard", "keyboard": updates}])
249
250
251func checkWorldport(port_id):
252 if not _checked_worldports.has(port_id):
253 sendMessage([{"cmd": "CheckWorldport", "port_id": port_id}])
254
255
256func sendQuit():
257 sendMessage([{"cmd": "Quit"}])
258
259
260func hasItem(item_id):
261 return _received_items.has(item_id)
262
263
264func getItemAmount(item_id):
265 return _received_items.get(item_id, 0)
diff --git a/apworld/client/collectable.gd b/apworld/client/collectable.gd new file mode 100644 index 0000000..4a17a2a --- /dev/null +++ b/apworld/client/collectable.gd
@@ -0,0 +1,16 @@
1extends "res://scripts/nodes/collectable.gd"
2
3
4func pickedUp():
5 if unlock_type == "key":
6 var ap = global.get_node("Archipelago")
7 if ap.get_letter_behavior(unlock_key, level == 2) == ap.kLETTER_BEHAVIOR_VANILLA:
8 ap.keyboard.collect_local_letter(unlock_key, level)
9 else:
10 ap.keyboard.update_unlocks()
11
12 super.pickedUp()
13
14
15func setScoutedText(text):
16 get_node("MeshInstance3D").mesh.text = text.replace(" ", "\n")
diff --git a/apworld/client/compass.gd b/apworld/client/compass.gd new file mode 100644 index 0000000..c90475a --- /dev/null +++ b/apworld/client/compass.gd
@@ -0,0 +1,66 @@
1extends Node2D
2
3const RADIUS = 48
4
5var _font
6
7
8func _ready():
9 _font = load("res://assets/fonts/Lingo2.ttf")
10
11
12func _draw():
13 draw_circle(Vector2.ZERO, RADIUS, Color(1.0, 1.0, 1.0, 0.8), true)
14 draw_circle(Vector2.ZERO, RADIUS, Color.BLACK, false)
15 draw_string(
16 _font,
17 Vector2(-4, -RADIUS * 3.0 / 4.0),
18 "N",
19 HorizontalAlignment.HORIZONTAL_ALIGNMENT_LEFT,
20 -1,
21 16,
22 Color.BLACK
23 )
24 draw_set_transform(Vector2.ZERO, PI / 2)
25 draw_string(
26 _font,
27 Vector2(-4, -RADIUS * 3.0 / 4.0),
28 "E",
29 HorizontalAlignment.HORIZONTAL_ALIGNMENT_LEFT,
30 -1,
31 16,
32 Color.BLACK
33 )
34 draw_set_transform(Vector2.ZERO, PI)
35 draw_string(
36 _font,
37 Vector2(-4, -RADIUS * 3.0 / 4.0),
38 "S",
39 HorizontalAlignment.HORIZONTAL_ALIGNMENT_LEFT,
40 -1,
41 16,
42 Color.BLACK
43 )
44 draw_set_transform(Vector2.ZERO, PI * 3.0 / 2.0)
45 draw_string(
46 _font,
47 Vector2(-4, -RADIUS * 3.0 / 4.0),
48 "W",
49 HorizontalAlignment.HORIZONTAL_ALIGNMENT_LEFT,
50 -1,
51 16,
52 Color.BLACK
53 )
54 draw_set_transform(Vector2.ZERO)
55 draw_colored_polygon(
56 PackedVector2Array(
57 [Vector2(0, -RADIUS * 5.0 / 8.0), Vector2(-RADIUS / 6.0, 0), Vector2(RADIUS / 6.0, 0)]
58 ),
59 Color.RED
60 )
61 draw_colored_polygon(
62 PackedVector2Array(
63 [Vector2(0, RADIUS * 5.0 / 8.0), Vector2(-RADIUS / 6.0, 0), Vector2(RADIUS / 6.0, 0)]
64 ),
65 Color.GRAY
66 )
diff --git a/apworld/client/compass_overlay.gd b/apworld/client/compass_overlay.gd new file mode 100644 index 0000000..56e81ff --- /dev/null +++ b/apworld/client/compass_overlay.gd
@@ -0,0 +1,17 @@
1extends CanvasLayer
2
3var SCRIPT_compass
4
5var compass
6
7
8func _ready():
9 compass = SCRIPT_compass.new()
10 compass.position = Vector2(1840, 80)
11 add_child(compass)
12
13 visible = false
14
15
16func update_rotation(ry):
17 compass.rotation = ry
diff --git a/apworld/client/door.gd b/apworld/client/door.gd new file mode 100644 index 0000000..49f5728 --- /dev/null +++ b/apworld/client/door.gd
@@ -0,0 +1,46 @@
1extends "res://scripts/nodes/door.gd"
2
3var item_id
4var item_amount
5
6
7func _ready():
8 var node_path = String(
9 get_tree().get_root().get_node("scene").get_path_to(self).get_concatenated_names()
10 )
11
12 var gamedata = global.get_node("Gamedata")
13 var door_id = gamedata.get_door_for_map_node_path(global.map, node_path)
14 if door_id != null:
15 var ap = global.get_node("Archipelago")
16 var item_lock = ap.get_item_id_for_door(door_id)
17
18 if item_lock != null:
19 item_id = item_lock[0]
20 item_amount = item_lock[1]
21
22 self.senders = []
23 self.senderGroup = []
24 self.nested = false
25 self.complete_at = 0
26 self.max_length = 0
27 self.excludeSenders = []
28
29 call_deferred("_readier")
30
31 if global.map == "the_sun_temple":
32 if name == "spe_EndPlatform" or name == "spe_entry_2":
33 senders = [NodePath("/root/scene/Panels/EndCheck_dog")]
34
35 if global.map == "the_parthenon":
36 if name == "spe_entry_1":
37 senders = [NodePath("/root/scene/Panels/EndCheck_dog")]
38
39 super._ready()
40
41
42func _readier():
43 var ap = global.get_node("Archipelago")
44
45 if ap.client.getItemAmount(item_id) >= item_amount:
46 handleTriggered()
diff --git a/apworld/client/effects.gd b/apworld/client/effects.gd new file mode 100644 index 0000000..9dc1dd8 --- /dev/null +++ b/apworld/client/effects.gd
@@ -0,0 +1,32 @@
1extends CanvasLayer
2
3var _label
4
5var _disconnected = false
6
7
8func _ready():
9 _label = Label.new()
10 _label.name = "Label"
11 _label.offset_left = 20
12 _label.offset_top = 20
13 _label.horizontal_alignment = HORIZONTAL_ALIGNMENT_LEFT
14 _label.vertical_alignment = VERTICAL_ALIGNMENT_TOP
15 _label.theme = preload("res://assets/themes/baseUI.tres")
16 _label.add_theme_font_size_override("font_size", 36)
17 add_child(_label)
18
19
20func set_connection_lost(arg):
21 _disconnected = arg
22
23 _update_label()
24
25
26func _update_label():
27 var text = []
28
29 if _disconnected:
30 text.append("Disconnected from multiworld.")
31
32 _label.text = "\n".join(text)
diff --git a/apworld/client/gamedata.gd b/apworld/client/gamedata.gd new file mode 100644 index 0000000..334d42a --- /dev/null +++ b/apworld/client/gamedata.gd
@@ -0,0 +1,286 @@
1extends Node
2
3var SCRIPT_proto
4
5var objects
6var door_id_by_map_node_path = {}
7var painting_id_by_map_node_path = {}
8var panel_id_by_map_node_path = {}
9var port_id_by_map_node_path = {}
10var door_id_by_ap_id = {}
11var map_id_by_name = {}
12var progressive_id_by_ap_id = {}
13var letter_id_by_ap_id = {}
14var symbol_item_ids = []
15var anti_trap_ids = {}
16var location_name_by_id = {}
17var ending_display_name_by_name = {}
18
19var kSYMBOL_ITEMS
20
21
22func _init(proto_script):
23 SCRIPT_proto = proto_script
24
25 kSYMBOL_ITEMS = {
26 SCRIPT_proto.PuzzleSymbol.SUN: "Sun Symbol",
27 SCRIPT_proto.PuzzleSymbol.SPARKLES: "Sparkles Symbol",
28 SCRIPT_proto.PuzzleSymbol.ZERO: "Zero Symbol",
29 SCRIPT_proto.PuzzleSymbol.EXAMPLE: "Example Symbol",
30 SCRIPT_proto.PuzzleSymbol.BOXES: "Boxes Symbol",
31 SCRIPT_proto.PuzzleSymbol.PLANET: "Planet Symbol",
32 SCRIPT_proto.PuzzleSymbol.PYRAMID: "Pyramid Symbol",
33 SCRIPT_proto.PuzzleSymbol.CROSS: "Cross Symbol",
34 SCRIPT_proto.PuzzleSymbol.SWEET: "Sweet Symbol",
35 SCRIPT_proto.PuzzleSymbol.GENDER: "Gender Symbol",
36 SCRIPT_proto.PuzzleSymbol.AGE: "Age Symbol",
37 SCRIPT_proto.PuzzleSymbol.SOUND: "Sound Symbol",
38 SCRIPT_proto.PuzzleSymbol.ANAGRAM: "Anagram Symbol",
39 SCRIPT_proto.PuzzleSymbol.JOB: "Job Symbol",
40 SCRIPT_proto.PuzzleSymbol.STARS: "Stars Symbol",
41 SCRIPT_proto.PuzzleSymbol.NULL: "Null Symbol",
42 SCRIPT_proto.PuzzleSymbol.EVAL: "Eval Symbol",
43 SCRIPT_proto.PuzzleSymbol.LINGO: "Lingo Symbol",
44 SCRIPT_proto.PuzzleSymbol.QUESTION: "Question Symbol",
45 }
46
47
48func load(data_bytes):
49 objects = SCRIPT_proto.AllObjects.new()
50
51 var result_code = objects.from_bytes(data_bytes)
52 if result_code != SCRIPT_proto.PB_ERR.NO_ERRORS:
53 print("Could not load generated data: %d" % result_code)
54 return
55
56 for map in objects.get_maps():
57 map_id_by_name[map.get_name()] = map.get_id()
58
59 for door in objects.get_doors():
60 var map = objects.get_maps()[door.get_map_id()]
61
62 if not map.get_name() in door_id_by_map_node_path:
63 door_id_by_map_node_path[map.get_name()] = {}
64
65 var map_data = door_id_by_map_node_path[map.get_name()]
66 for receiver in door.get_receivers():
67 map_data[receiver] = door.get_id()
68
69 for painting_id in door.get_move_paintings():
70 var painting = objects.get_paintings()[painting_id]
71 map_data[painting.get_path()] = door.get_id()
72
73 if door.has_ap_id():
74 door_id_by_ap_id[door.get_ap_id()] = door.get_id()
75 location_name_by_id[door.get_ap_id()] = _get_door_location_name(door)
76
77 for painting in objects.get_paintings():
78 var room = objects.get_rooms()[painting.get_room_id()]
79 var map = objects.get_maps()[room.get_map_id()]
80
81 if not map.get_name() in painting_id_by_map_node_path:
82 painting_id_by_map_node_path[map.get_name()] = {}
83
84 var _map_data = painting_id_by_map_node_path[map.get_name()]
85
86 for port in objects.get_ports():
87 var room = objects.get_rooms()[port.get_room_id()]
88 var map = objects.get_maps()[room.get_map_id()]
89
90 if not map.get_name() in port_id_by_map_node_path:
91 port_id_by_map_node_path[map.get_name()] = {}
92
93 var map_data = port_id_by_map_node_path[map.get_name()]
94 map_data[port.get_path()] = port.get_id()
95
96 for progressive in objects.get_progressives():
97 progressive_id_by_ap_id[progressive.get_ap_id()] = progressive.get_id()
98
99 for letter in objects.get_letters():
100 letter_id_by_ap_id[letter.get_ap_id()] = letter.get_id()
101 location_name_by_id[letter.get_ap_id()] = _get_letter_location_name(letter)
102
103 for mastery in objects.get_masteries():
104 location_name_by_id[mastery.get_ap_id()] = _get_mastery_location_name(mastery)
105
106 for ending in objects.get_endings():
107 var location_name = _get_ending_location_name(ending)
108 location_name_by_id[ending.get_ap_id()] = location_name
109 ending_display_name_by_name[ending.get_name()] = location_name
110
111 for keyholder in objects.get_keyholders():
112 if keyholder.has_key():
113 location_name_by_id[keyholder.get_ap_id()] = _get_keyholder_location_name(keyholder)
114
115 for panel in objects.get_panels():
116 var room = objects.get_rooms()[panel.get_room_id()]
117 var map = objects.get_maps()[room.get_map_id()]
118
119 if not map.get_name() in panel_id_by_map_node_path:
120 panel_id_by_map_node_path[map.get_name()] = {}
121
122 var map_data = panel_id_by_map_node_path[map.get_name()]
123 map_data[panel.get_path()] = panel.get_id()
124
125 for symbol_name in kSYMBOL_ITEMS.values():
126 symbol_item_ids.append(objects.get_special_ids()[symbol_name])
127
128 for special_name in objects.get_special_ids().keys():
129 if special_name.begins_with("Anti "):
130 anti_trap_ids[objects.get_special_ids()[special_name]] = (
131 special_name.substr(5).to_lower()
132 )
133
134
135func get_door_for_map_node_path(map_name, node_path):
136 if not door_id_by_map_node_path.has(map_name):
137 return null
138
139 var map_data = door_id_by_map_node_path[map_name]
140 return map_data.get(node_path, null)
141
142
143func get_panel_for_map_node_path(map_name, node_path):
144 if not panel_id_by_map_node_path.has(map_name):
145 return null
146
147 var map_data = panel_id_by_map_node_path[map_name]
148 return map_data.get(node_path, null)
149
150
151func get_port_for_map_node_path(map_name, node_path):
152 if not port_id_by_map_node_path.has(map_name):
153 return null
154
155 var map_data = port_id_by_map_node_path[map_name]
156 return map_data.get(node_path, null)
157
158
159func get_door_ap_id(door_id):
160 var door = objects.get_doors()[door_id]
161 if door.has_ap_id():
162 return door.get_ap_id()
163 else:
164 return null
165
166
167func get_door_map_name(door_id):
168 var door = objects.get_doors()[door_id]
169 var room = objects.get_rooms()[door.get_room_id()]
170 var map = objects.get_maps()[room.get_map_id()]
171 return map.get_name()
172
173
174func get_door_receivers(door_id):
175 var door = objects.get_doors()[door_id]
176 return door.get_receivers()
177
178
179func get_worldport_display_name(port_id):
180 var port = objects.get_ports()[port_id]
181 return "%s - %s" % [_get_room_object_map_name(port), port.get_display_name()]
182
183
184func _get_map_object_map_name(obj):
185 return objects.get_maps()[obj.get_map_id()].get_display_name()
186
187
188func _get_room_object_map_name(obj):
189 return _get_map_object_map_name(objects.get_rooms()[obj.get_room_id()])
190
191
192func _get_room_object_location_prefix(obj):
193 var room = objects.get_rooms()[obj.get_room_id()]
194 var game_map = objects.get_maps()[room.get_map_id()]
195
196 if room.has_panel_display_name():
197 return "%s (%s)" % [game_map.get_display_name(), room.get_panel_display_name()]
198 else:
199 return game_map.get_display_name()
200
201
202func _get_door_location_name(door):
203 var map_part = _get_room_object_location_prefix(door)
204
205 if door.has_location_name():
206 return "%s - %s" % [map_part, door.get_location_name()]
207
208 var generated_location_name = _get_generated_door_location_name(door)
209 if generated_location_name != null:
210 return generated_location_name
211
212 return "%s - %s" % [map_part, door.get_name()]
213
214
215func _get_generated_door_location_name(door):
216 if door.get_type() != SCRIPT_proto.DoorType.STANDARD:
217 return null
218
219 if door.get_keyholders().size() > 0 or door.get_endings().size() > 0 or door.has_complete_at():
220 return null
221
222 if door.get_panels().size() > 4:
223 return null
224
225 var map_areas = []
226 for panel_id in door.get_panels():
227 var panel = objects.get_panels()[panel_id.get_panel()]
228 var panel_room = objects.get_rooms()[panel.get_room_id()]
229 # It's okay if panel_display_name is not present because then it's coalesced with other unnamed areas.
230 if not map_areas.has(panel_room.get_panel_display_name()):
231 map_areas.append(panel_room.get_panel_display_name())
232
233 if map_areas.size() > 1:
234 return null
235
236 var game_map = objects.get_maps()[door.get_map_id()]
237 var map_area = map_areas[0]
238 var map_part
239 if map_area == "":
240 map_part = game_map.get_display_name()
241 else:
242 map_part = "%s (%s)" % [game_map.get_display_name(), map_area]
243
244 var panel_names = []
245 for panel_id in door.get_panels():
246 var panel_data = objects.get_panels()[panel_id.get_panel()]
247 var panel_name
248 if panel_data.has_display_name():
249 panel_name = panel_data.get_display_name()
250 else:
251 panel_name = panel_data.get_name()
252
253 var location_part
254 if panel_id.has_answer():
255 location_part = "%s/%s" % [panel_name, panel_id.get_answer().to_upper()]
256 else:
257 location_part = panel_name
258
259 panel_names.append(location_part)
260
261 panel_names.sort()
262
263 return map_part + " - " + ", ".join(panel_names)
264
265
266func _get_letter_location_name(letter):
267 var letter_level = 2 if letter.get_level2() else 1
268 var letter_name = "%s%d" % [letter.get_key().to_upper(), letter_level]
269 return "%s - %s" % [_get_room_object_map_name(letter), letter_name]
270
271
272func _get_mastery_location_name(mastery):
273 return "%s - Mastery" % _get_room_object_map_name(mastery)
274
275
276func _get_ending_location_name(ending):
277 return (
278 "%s - %s Ending" % [_get_room_object_map_name(ending), ending.get_name().to_pascal_case()]
279 )
280
281
282func _get_keyholder_location_name(keyholder):
283 return (
284 "%s - %s Keyholder"
285 % [_get_room_object_location_prefix(keyholder), keyholder.get_key().to_upper()]
286 )
diff --git a/apworld/client/keyHolder.gd b/apworld/client/keyHolder.gd new file mode 100644 index 0000000..3c037ff --- /dev/null +++ b/apworld/client/keyHolder.gd
@@ -0,0 +1,38 @@
1extends "res://scripts/nodes/keyHolder.gd"
2
3
4func setFromAp(key, level):
5 if level > 0:
6 has_key = true
7 is_complete = "%s%d" % [key, level]
8 held_key = key
9 held_level = level
10 get_node("Hinge/Letter").mesh.text = held_key
11 get_node("Hinge/Letter2").mesh.text = held_key
12 setMaterial()
13 emit_signal("trigger")
14 else:
15 has_key = false
16 held_key = ""
17 held_level = 0
18 setMaterial()
19 get_node("Hinge/Letter").mesh.text = "-"
20 get_node("Hinge/Letter2").mesh.text = "-"
21 is_complete = ""
22 emit_signal("untrigger")
23
24
25func addKey(key):
26 var node_path = String(
27 get_tree().get_root().get_node("scene").get_path_to(self).get_concatenated_names()
28 )
29 var ap = global.get_node("Archipelago")
30 ap.keyboard.put_in_keyholder(key, global.map, node_path)
31
32
33func removeKey():
34 var node_path = String(
35 get_tree().get_root().get_node("scene").get_path_to(self).get_concatenated_names()
36 )
37 var ap = global.get_node("Archipelago")
38 ap.keyboard.remove_from_keyholder(held_key, global.map, node_path)
diff --git a/apworld/client/keyHolderChecker.gd b/apworld/client/keyHolderChecker.gd new file mode 100644 index 0000000..a75a9e4 --- /dev/null +++ b/apworld/client/keyHolderChecker.gd
@@ -0,0 +1,24 @@
1extends "res://scripts/nodes/listeners/keyHolderChecker.gd"
2
3
4func check():
5 var ap = global.get_node("Archipelago")
6 var matches = []
7 for map in ap.keyboard.keyholder_state.keys():
8 var nodes = ap.keyboard.keyholder_state[map]
9 for node in nodes.keys():
10 matches.append([nodes[node], 1, map, "/root/scene/%s" % node])
11
12 var count = 0
13 for key_match in matches:
14 var active = (
15 key_match[2] + String(key_match[3]).replace("/root/scene/Components/KeyHolders/", ".")
16 )
17 if map[active] == key_match[0]:
18 emit_signal("trigger_letter", key_match[0], true)
19 count += 1
20 else:
21 emit_signal("trigger_letter", key_match[0], false)
22
23 if count > 25:
24 emit_signal("trigger")
diff --git a/apworld/client/keyHolderResetterListener.gd b/apworld/client/keyHolderResetterListener.gd new file mode 100644 index 0000000..d5300f3 --- /dev/null +++ b/apworld/client/keyHolderResetterListener.gd
@@ -0,0 +1,8 @@
1extends "res://scripts/nodes/listeners/keyHolderResetterListener.gd"
2
3
4func reset():
5 var ap = global.get_node("Archipelago")
6 var was_removed = ap.keyboard.reset_keyholders()
7 if was_removed:
8 sfxPlayer.sfx_play("pickup")
diff --git a/apworld/client/keyboard.gd b/apworld/client/keyboard.gd new file mode 100644 index 0000000..a59c4d0 --- /dev/null +++ b/apworld/client/keyboard.gd
@@ -0,0 +1,231 @@
1extends Node
2
3const kALL_LETTERS = "abcdefghjiklmnopqrstuvwxyz"
4
5var letters_saved = {}
6var letters_in_keyholders = []
7var letters_blocked = []
8var letters_dynamic = {}
9var keyholder_state = {}
10
11var filename = ""
12
13
14func _init():
15 reset()
16
17
18func reset():
19 letters_saved.clear()
20 letters_in_keyholders.clear()
21 letters_blocked.clear()
22 letters_dynamic.clear()
23 keyholder_state.clear()
24
25
26func load_seed():
27 var ap = global.get_node("Archipelago")
28
29 reset()
30
31 filename = "user://archipelago_keys/%s_%d" % [ap.client._seed, ap.client._slot]
32
33 if FileAccess.file_exists(filename):
34 var ap_file = FileAccess.open(filename, FileAccess.READ)
35 var localdata = []
36 if ap_file != null:
37 localdata = ap_file.get_var(true)
38 ap_file.close()
39
40 if typeof(localdata) != TYPE_ARRAY:
41 print("AP keyboard file is corrupted")
42 localdata = []
43
44 if localdata.size() > 0:
45 letters_saved = localdata[0]
46 if localdata.size() > 1:
47 letters_in_keyholders = localdata[1]
48 if localdata.size() > 2:
49 keyholder_state = localdata[2]
50
51 if not letters_saved.is_empty():
52 ap.client.updateKeyboard(letters_saved)
53
54 for k in kALL_LETTERS:
55 var level = 0
56
57 if ap.get_letter_behavior(k, false) == ap.kLETTER_BEHAVIOR_UNLOCKED:
58 level += 1
59 if ap.get_letter_behavior(k, true) == ap.kLETTER_BEHAVIOR_UNLOCKED:
60 level += 1
61
62 letters_dynamic[k] = level
63
64 update_unlocks()
65
66
67func save():
68 var dir = DirAccess.open("user://")
69 var folder = "archipelago_keys"
70 if not dir.dir_exists(folder):
71 dir.make_dir(folder)
72
73 var file = FileAccess.open(filename, FileAccess.WRITE)
74
75 var data = [
76 letters_saved,
77 letters_in_keyholders,
78 keyholder_state,
79 ]
80 file.store_var(data, true)
81 file.close()
82
83
84func update_unlocks():
85 unlocks.resetKeys()
86
87 var has_doubles = false
88
89 for k in kALL_LETTERS:
90 var level = 0
91
92 if not letters_in_keyholders.has(k):
93 level = letters_saved.get(k, 0) + letters_dynamic.get(k, 0)
94
95 if level >= 2:
96 level = 2
97 has_doubles = true
98
99 if letters_blocked.has(k):
100 level = 0
101
102 unlocks.unlockKey(k, level)
103
104 if has_doubles and unlocks.data["double_letters"] != "unlocked":
105 var ap = global.get_node("Archipelago")
106 if ap.cyan_door_behavior == ap.kCYAN_DOOR_BEHAVIOR_DOUBLE_LETTER:
107 unlocks.setData("double_letters", "unlocked")
108
109
110func collect_local_letter(key, level):
111 var ap = global.get_node("Archipelago")
112 var true_level = 0
113
114 if ap.get_letter_behavior(key, false) == ap.kLETTER_BEHAVIOR_VANILLA:
115 true_level += 1
116 if level == 2 and ap.get_letter_behavior(key, true) == ap.kLETTER_BEHAVIOR_VANILLA:
117 true_level += 1
118
119 if true_level < letters_saved.get(key, 0):
120 return
121
122 letters_saved[key] = true_level
123
124 ap.client.updateKeyboard({key: true_level})
125
126 if letters_blocked.has(key):
127 letters_blocked.erase(key)
128
129 update_unlocks()
130 save()
131
132
133func collect_remote_letter(key, level):
134 if level < 0 or level > 2 or level < letters_dynamic.get(key, 0):
135 return
136
137 letters_dynamic[key] = level
138
139 if letters_blocked.has(key):
140 letters_blocked.erase(key)
141
142 update_unlocks()
143 save()
144
145
146func put_in_keyholder(key, map, kh_path):
147 if not keyholder_state.has(map):
148 keyholder_state[map] = {}
149
150 keyholder_state[map][kh_path] = key
151 letters_in_keyholders.append(key)
152
153 get_tree().get_root().get_node("scene").get_node(kh_path).setFromAp(
154 key, min(letters_saved.get(key, 0) + letters_dynamic.get(key, 0), 2)
155 )
156
157 update_unlocks()
158 save()
159
160
161func remove_from_keyholder(key, map, kh_path):
162 if not keyholder_state.has(map):
163 # This... shouldn't happen.
164 keyholder_state[map] = {}
165
166 keyholder_state[map].erase(kh_path)
167 letters_in_keyholders.erase(key)
168
169 get_tree().get_root().get_node("scene").get_node(kh_path).setFromAp(key, 0)
170
171 update_unlocks()
172 save()
173
174
175func block_letter(key):
176 if not letters_blocked.has(key):
177 letters_blocked.append(key)
178
179 update_unlocks()
180
181
182func load_keyholders(map):
183 if keyholder_state.has(map):
184 var khs = keyholder_state[map]
185
186 for path in khs.keys():
187 var key = khs[path]
188 get_tree().get_root().get_node("scene").get_node(path).setFromAp(
189 key, min(letters_saved.get(key, 0) + letters_dynamic.get(key, 0), 2)
190 )
191
192
193func reset_keyholders():
194 if letters_in_keyholders.is_empty() and letters_blocked.is_empty():
195 return false
196
197 var cleared_anything = not letters_in_keyholders.is_empty() or not letters_blocked.is_empty()
198
199 if keyholder_state.has(global.map):
200 for path in keyholder_state[global.map]:
201 get_tree().get_root().get_node("scene").get_node(path).setFromAp(
202 keyholder_state[global.map][path], 0
203 )
204
205 keyholder_state.clear()
206 letters_in_keyholders.clear()
207 letters_blocked.clear()
208
209 update_unlocks()
210 save()
211
212 return cleared_anything
213
214
215func remote_keyboard_updated(updates):
216 var reverse = {}
217 var should_update = false
218
219 for k in updates:
220 if not letters_saved.has(k) or updates[k] > letters_saved[k]:
221 letters_saved[k] = updates[k]
222 should_update = true
223 elif updates[k] < letters_saved[k]:
224 reverse[k] = letters_saved[k]
225
226 if should_update:
227 update_unlocks()
228
229 if not reverse.is_empty():
230 var ap = global.get_node("Archipelago")
231 ap.client.updateKeyboard(reverse)
diff --git a/apworld/client/locationListener.gd b/apworld/client/locationListener.gd new file mode 100644 index 0000000..71792ed --- /dev/null +++ b/apworld/client/locationListener.gd
@@ -0,0 +1,20 @@
1extends Receiver
2
3var location_id
4
5
6func _ready():
7 super._ready()
8
9
10func handleTriggered():
11 triggered += 1
12 if triggered >= total:
13 var ap = global.get_node("Archipelago")
14 ap.send_location(location_id)
15
16
17func handleUntriggered():
18 triggered -= 1
19 if triggered < total:
20 pass
diff --git a/apworld/client/main.gd b/apworld/client/main.gd new file mode 100644 index 0000000..e1f9610 --- /dev/null +++ b/apworld/client/main.gd
@@ -0,0 +1,296 @@
1extends Node
2
3
4func _ready():
5 var runtime = global.get_node("Runtime")
6
7 # Some helpful logging.
8 if Steam.isSubscribed():
9 global._print("Provisioning successful! Build ID: %d" % Steam.getAppBuildId())
10 else:
11 global._print("Provisioning failed.")
12
13 # Undo the load screen removing our cursor
14 get_tree().get_root().set_disable_input(false)
15 Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE)
16
17 # Increase the WebSocket input buffer size so that we can download large
18 # data packages.
19 ProjectSettings.set_setting("network/limits/websocket_client/max_in_buffer_kb", 8192)
20
21 switcher.layer = 4
22
23 # Create the global AP manager, if it doesn't already exist.
24 if not global.has_node("Archipelago"):
25 var ap_script = runtime.load_script("manager.gd")
26 var ap_instance = ap_script.new()
27 ap_instance.name = "Archipelago"
28
29 ap_instance.SCRIPT_client = runtime.load_script("client.gd")
30 ap_instance.SCRIPT_keyboard = runtime.load_script("keyboard.gd")
31 ap_instance.SCRIPT_locationListener = runtime.load_script("locationListener.gd")
32 ap_instance.SCRIPT_minimap = runtime.load_script("minimap.gd")
33 ap_instance.SCRIPT_victoryListener = runtime.load_script("victoryListener.gd")
34 ap_instance.SCRIPT_websocketserver = runtime.load_script("vendor/WebSocketServer.gd")
35
36 global.add_child(ap_instance)
37
38 # Let's also inject any scripts we need to inject now.
39 installScriptExtension(runtime.load_script("animationListener.gd"))
40 installScriptExtension(runtime.load_script("collectable.gd"))
41 installScriptExtension(runtime.load_script("door.gd"))
42 installScriptExtension(runtime.load_script("keyHolder.gd"))
43 installScriptExtension(runtime.load_script("keyHolderChecker.gd"))
44 installScriptExtension(runtime.load_script("keyHolderResetterListener.gd"))
45 installScriptExtension(runtime.load_script("painting.gd"))
46 installScriptExtension(runtime.load_script("panel.gd"))
47 installScriptExtension(runtime.load_script("pauseMenu.gd"))
48 installScriptExtension(runtime.load_script("player.gd"))
49 installScriptExtension(runtime.load_script("saver.gd"))
50 installScriptExtension(runtime.load_script("teleport.gd"))
51 installScriptExtension(runtime.load_script("teleportListener.gd"))
52 installScriptExtension(runtime.load_script("visibilityListener.gd"))
53 installScriptExtension(runtime.load_script("worldport.gd"))
54 installScriptExtension(runtime.load_script("worldportListener.gd"))
55
56 var proto_script = runtime.load_script("../generated/proto.gd")
57 var gamedata_script = runtime.load_script("gamedata.gd")
58 var gamedata_instance = gamedata_script.new(proto_script)
59 gamedata_instance.load(runtime.read_path("../generated/data.binpb"))
60 gamedata_instance.name = "Gamedata"
61 global.add_child(gamedata_instance)
62
63 var messages_script = runtime.load_script("messages.gd")
64 var messages_instance = messages_script.new()
65 messages_instance.name = "Messages"
66 messages_instance.SCRIPT_rainbowText = runtime.load_script("rainbowText.gd")
67 global.add_child(messages_instance)
68
69 var effects_script = runtime.load_script("effects.gd")
70 var effects_instance = effects_script.new()
71 effects_instance.name = "Effects"
72 global.add_child(effects_instance)
73
74 var textclient_script = runtime.load_script("textclient.gd")
75 var textclient_instance = textclient_script.new()
76 textclient_instance.name = "Textclient"
77 global.add_child(textclient_instance)
78
79 var compass_overlay_script = runtime.load_script("compass_overlay.gd")
80 var compass_overlay_instance = compass_overlay_script.new()
81 compass_overlay_instance.name = "Compass"
82 compass_overlay_instance.SCRIPT_compass = runtime.load_script("compass.gd")
83 global.add_child(compass_overlay_instance)
84
85 var ap = global.get_node("Archipelago")
86 var gamedata = global.get_node("Gamedata")
87 ap.ap_connected.connect(connectionSuccessful)
88 ap.could_not_connect.connect(connectionUnsuccessful)
89 ap.connect_status.connect(connectionStatus)
90
91 # Populate textboxes with AP settings.
92 get_node("../Panel/server_box").text = ap.ap_server
93 get_node("../Panel/player_box").text = ap.ap_user
94 get_node("../Panel/password_box").text = ap.ap_pass
95
96 var history_box = get_node("../Panel/connection_history")
97 if ap.connection_history.is_empty():
98 history_box.disabled = true
99 else:
100 history_box.disabled = false
101
102 var i = 0
103 for details in ap.connection_history:
104 history_box.get_popup().add_item("%s (%s)" % [details[1], details[0]], i)
105 i += 1
106
107 history_box.get_popup().id_pressed.connect(historySelected)
108
109 # Show client version.
110 var version = gamedata.objects.get_version()
111 get_node("../Panel/title").text = (
112 "ARCHIPELAGO (%d.%d.%d)" % [version.get_major(), version.get_minor(), version.get_patch()]
113 )
114
115 # Increase font size in text boxes.
116 get_node("../Panel/server_box").add_theme_font_size_override("font_size", 36)
117 get_node("../Panel/player_box").add_theme_font_size_override("font_size", 36)
118 get_node("../Panel/password_box").add_theme_font_size_override("font_size", 36)
119
120 # Set up version mismatch dialog.
121 get_node("../Panel/VersionMismatch").confirmed.connect(startGame)
122 get_node("../Panel/VersionMismatch").get_cancel_button().pressed.connect(
123 versionMismatchDeclined
124 )
125
126 # Set up buttons.
127 get_node("../Panel/connect_button").pressed.connect(_connect_pressed)
128 get_node("../Panel/quit_button").pressed.connect(_back_pressed)
129
130
131func _connect_pressed():
132 get_node("../Panel/connect_button").disabled = true
133
134 var ap = global.get_node("Archipelago")
135 ap.ap_server = get_node("../Panel/server_box").text
136 ap.ap_user = get_node("../Panel/player_box").text
137 ap.ap_pass = get_node("../Panel/password_box").text
138 ap.saveSettings()
139
140 ap.connectToServer()
141
142
143func _back_pressed():
144 var ap = global.get_node("Archipelago")
145 ap.disconnect_from_ap()
146 ap.client.sendQuit()
147
148 get_tree().quit()
149
150
151# Adapted from https://gitlab.com/Delta-V-Modding/Mods/-/blob/main/game/ModLoader.gd
152func installScriptExtension(childScript: Resource):
153 # Force Godot to compile the script now.
154 # We need to do this here to ensure that the inheritance chain is
155 # properly set up, and multiple mods can chain-extend the same
156 # class multiple times.
157 # This is also needed to make Godot instantiate the extended class
158 # when creating singletons.
159 # The actual instance is thrown away.
160 childScript.new()
161
162 var parentScript = childScript.get_base_script()
163 var parentScriptPath = parentScript.resource_path
164 global._print("ModLoader: Installing script extension over %s" % parentScriptPath)
165 childScript.take_over_path(parentScriptPath)
166
167
168func connectionStatus(message):
169 var popup = get_node("../Panel/AcceptDialog")
170 popup.title = "Connecting to Archipelago"
171 popup.dialog_text = message
172 popup.exclusive = true
173 popup.get_ok_button().visible = false
174 popup.popup_centered()
175
176
177func connectionSuccessful():
178 var ap = global.get_node("Archipelago")
179 var gamedata = global.get_node("Gamedata")
180
181 # Check for major version mismatch.
182 if ap.apworld_version[0] != gamedata.objects.get_version().get_major():
183 get_node("../Panel/AcceptDialog").exclusive = false
184
185 var popup = get_node("../Panel/VersionMismatch")
186 popup.title = "Version Mismatch!"
187 popup.dialog_text = (
188 "This slot was generated using v%d.%d.%d of the Lingo 2 apworld,\nwhich has a different major version than this client (v%d.%d.%d).\nIt is highly recommended to play using the correct version of the client.\nYou may experience bugs or logic issues if you continue."
189 % [
190 ap.apworld_version[0],
191 ap.apworld_version[1],
192 ap.apworld_version[2],
193 gamedata.objects.get_version().get_major(),
194 gamedata.objects.get_version().get_minor(),
195 gamedata.objects.get_version().get_patch()
196 ]
197 )
198 popup.exclusive = true
199 popup.popup_centered()
200
201 return
202
203 startGame()
204
205
206func startGame():
207 var ap = global.get_node("Archipelago")
208
209 # Save connection details
210 var connection_details = [ap.ap_server, ap.ap_user, ap.ap_pass]
211 if ap.connection_history.has(connection_details):
212 ap.connection_history.erase(connection_details)
213 ap.connection_history.push_front(connection_details)
214 if ap.connection_history.size() > 10:
215 ap.connection_history.resize(10)
216 ap.saveSettings()
217
218 # Switch to the_entry
219 Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
220 global.user = ap.getSaveFileName()
221 global.universe = "lingo"
222 global.map = "the_entry"
223
224 unlocks.resetCollectables()
225 unlocks.resetData()
226
227 ap.setup_keys()
228
229 unlocks.loadCollectables()
230 unlocks.loadData()
231 unlocks.unlockKey("capslock", 1)
232
233 if ap.shuffle_worldports:
234 settings.worldport_fades = "default"
235 else:
236 settings.worldport_fades = "never"
237
238 clearResourceCache("res://objects/meshes/gridDoor.tscn")
239 clearResourceCache("res://objects/nodes/collectable.tscn")
240 clearResourceCache("res://objects/nodes/door.tscn")
241 clearResourceCache("res://objects/nodes/keyHolder.tscn")
242 clearResourceCache("res://objects/nodes/listeners/animationListener.tscn")
243 clearResourceCache("res://objects/nodes/listeners/keyHolderChecker.tscn")
244 clearResourceCache("res://objects/nodes/listeners/keyHolderResetterListener.tscn")
245 clearResourceCache("res://objects/nodes/listeners/teleportListener.tscn")
246 clearResourceCache("res://objects/nodes/listeners/visibilityListener.tscn")
247 clearResourceCache("res://objects/nodes/listeners/worldportListener.tscn")
248 clearResourceCache("res://objects/nodes/panel.tscn")
249 clearResourceCache("res://objects/nodes/player.tscn")
250 clearResourceCache("res://objects/nodes/saver.tscn")
251 clearResourceCache("res://objects/nodes/teleport.tscn")
252 clearResourceCache("res://objects/nodes/worldport.tscn")
253 clearResourceCache("res://objects/scenes/menus/pause_menu.tscn")
254
255 var paintings_dir = DirAccess.open("res://objects/meshes/paintings")
256 if paintings_dir:
257 paintings_dir.list_dir_begin()
258 var file_name = paintings_dir.get_next()
259 while file_name != "":
260 if not paintings_dir.current_is_dir() and file_name.ends_with(".tscn"):
261 clearResourceCache("res://objects/meshes/paintings/" + file_name)
262 file_name = paintings_dir.get_next()
263
264 switcher.switch_map.call_deferred("res://objects/scenes/the_entry.tscn")
265
266
267func connectionUnsuccessful(error_message):
268 get_node("../Panel/connect_button").disabled = false
269
270 var popup = get_node("../Panel/AcceptDialog")
271 popup.title = "Could not connect to Archipelago"
272 popup.dialog_text = error_message
273 popup.exclusive = true
274 popup.get_ok_button().visible = true
275 popup.popup_centered()
276
277
278func versionMismatchDeclined():
279 get_node("../Panel/AcceptDialog").hide()
280 get_node("../Panel/connect_button").disabled = false
281
282 var ap = global.get_node("Archipelago")
283 ap.disconnect_from_ap()
284
285
286func historySelected(index):
287 var ap = global.get_node("Archipelago")
288 var details = ap.connection_history[index]
289
290 get_node("../Panel/server_box").text = details[0]
291 get_node("../Panel/player_box").text = details[1]
292 get_node("../Panel/password_box").text = details[2]
293
294
295func clearResourceCache(path):
296 ResourceLoader.load(path, "", ResourceLoader.CACHE_MODE_REPLACE)
diff --git a/apworld/client/manager.gd b/apworld/client/manager.gd new file mode 100644 index 0000000..9212233 --- /dev/null +++ b/apworld/client/manager.gd
@@ -0,0 +1,603 @@
1extends Node
2
3var SCRIPT_client
4var SCRIPT_keyboard
5var SCRIPT_locationListener
6var SCRIPT_minimap
7var SCRIPT_victoryListener
8var SCRIPT_websocketserver
9
10var ap_server = ""
11var ap_user = ""
12var ap_pass = ""
13var connection_history = []
14var show_compass = false
15var show_locations = false
16var show_minimap = false
17
18var client
19var keyboard
20
21var _localdata_file = ""
22var _last_new_item = -1
23var _batch_locations = false
24var _held_locations = []
25var _held_location_scouts = []
26var _location_scouts = {}
27var _item_locks = {}
28var _inverse_item_locks = {}
29var _held_letters = {}
30var _letters_setup = false
31var _already_connected = false
32
33const kSHUFFLE_LETTERS_VANILLA = 0
34const kSHUFFLE_LETTERS_UNLOCKED = 1
35const kSHUFFLE_LETTERS_PROGRESSIVE = 2
36const kSHUFFLE_LETTERS_VANILLA_CYAN = 3
37const kSHUFFLE_LETTERS_ITEM_CYAN = 4
38
39const kLETTER_BEHAVIOR_VANILLA = 0
40const kLETTER_BEHAVIOR_ITEM = 1
41const kLETTER_BEHAVIOR_UNLOCKED = 2
42
43const kCYAN_DOOR_BEHAVIOR_H2 = 0
44const kCYAN_DOOR_BEHAVIOR_DOUBLE_LETTER = 1
45const kCYAN_DOOR_BEHAVIOR_ITEM = 2
46
47const kEndingNameByVictoryValue = {
48 0: "GRAY",
49 1: "PURPLE",
50 2: "MINT",
51 3: "BLACK",
52 4: "BLUE",
53 5: "CYAN",
54 6: "RED",
55 7: "PLUM",
56 8: "ORANGE",
57 9: "GOLD",
58 10: "YELLOW",
59 11: "GREEN",
60 12: "WHITE",
61}
62
63var apworld_version = [0, 0, 0]
64var cyan_door_behavior = kCYAN_DOOR_BEHAVIOR_H2
65var daedalus_roof_access = false
66var keyholder_sanity = false
67var port_pairings = {}
68var shuffle_control_center_colors = false
69var shuffle_doors = false
70var shuffle_gallery_paintings = false
71var shuffle_letters = kSHUFFLE_LETTERS_VANILLA
72var shuffle_symbols = false
73var shuffle_worldports = false
74var strict_cyan_ending = false
75var strict_purple_ending = false
76var victory_condition = -1
77
78signal could_not_connect
79signal connect_status
80signal ap_connected
81
82
83func _init():
84 # Read AP settings from file, if there are any
85 if FileAccess.file_exists("user://ap_settings"):
86 var file = FileAccess.open("user://ap_settings", FileAccess.READ)
87 var data = file.get_var(true)
88 file.close()
89
90 if typeof(data) != TYPE_ARRAY:
91 global._print("AP settings file is corrupted")
92 data = []
93
94 if data.size() > 0:
95 ap_server = data[0]
96
97 if data.size() > 1:
98 ap_user = data[1]
99
100 if data.size() > 2:
101 ap_pass = data[2]
102
103 if data.size() > 3:
104 connection_history = data[3]
105
106 if data.size() > 4:
107 show_compass = data[4]
108
109 if data.size() > 5:
110 show_locations = data[5]
111
112 if data.size() > 6:
113 show_minimap = data[6]
114
115
116func _ready():
117 client = SCRIPT_client.new()
118 client.SCRIPT_websocketserver = SCRIPT_websocketserver
119
120 client.item_received.connect(_process_item)
121 client.location_scout_received.connect(_process_location_scout)
122 client.text_message_received.connect(_process_text_message)
123 client.item_sent_notification.connect(_process_item_sent_notification)
124 client.hint_received.connect(_process_hint_received)
125 client.accessible_locations_updated.connect(_on_accessible_locations_updated)
126 client.checked_locations_updated.connect(_on_checked_locations_updated)
127 client.checked_worldports_updated.connect(_on_checked_worldports_updated)
128
129 client.could_not_connect.connect(_client_could_not_connect)
130 client.connect_status.connect(_client_connect_status)
131 client.client_connected.connect(_client_connected)
132
133 add_child(client)
134
135 keyboard = SCRIPT_keyboard.new()
136 add_child(keyboard)
137 client.keyboard_update_received.connect(keyboard.remote_keyboard_updated)
138
139
140func saveSettings():
141 # Save the AP settings to disk.
142 var path = "user://ap_settings"
143 var file = FileAccess.open(path, FileAccess.WRITE)
144
145 var data = [
146 ap_server,
147 ap_user,
148 ap_pass,
149 connection_history,
150 show_compass,
151 show_locations,
152 show_minimap,
153 ]
154 file.store_var(data, true)
155 file.close()
156
157
158func saveLocaldata():
159 # Save the MW/slot specific settings to disk.
160 var dir = DirAccess.open("user://")
161 var folder = "archipelago_data"
162 if not dir.dir_exists(folder):
163 dir.make_dir(folder)
164
165 var file = FileAccess.open(_localdata_file, FileAccess.WRITE)
166
167 var data = [
168 _last_new_item,
169 ]
170 file.store_var(data, true)
171 file.close()
172
173
174func connectToServer():
175 _last_new_item = -1
176 _batch_locations = false
177 _held_locations = []
178 _held_location_scouts = []
179 _location_scouts = {}
180 _letters_setup = false
181 _held_letters = {}
182 _already_connected = false
183
184 client.connectToServer(ap_server, ap_user, ap_pass)
185
186
187func getSaveFileName():
188 return "zzAP_%s_%d" % [client._seed, client._slot]
189
190
191func disconnect_from_ap():
192 _already_connected = false
193
194 var effects = global.get_node("Effects")
195 effects.set_connection_lost(false)
196
197 client.disconnect_from_ap()
198
199
200func get_item_id_for_door(door_id):
201 return _item_locks.get(door_id, null)
202
203
204func _process_item(item, amount):
205 var gamedata = global.get_node("Gamedata")
206
207 var item_id = int(item["id"])
208 var prog_id = null
209 if _inverse_item_locks.has(item_id):
210 for lock in _inverse_item_locks.get(item_id):
211 if lock[1] != amount:
212 continue
213
214 if gamedata.progressive_id_by_ap_id.has(item_id):
215 prog_id = lock[0]
216
217 if gamedata.get_door_map_name(lock[0]) != global.map:
218 continue
219
220 # TODO: fix doors opening from door groups
221 var receivers = gamedata.get_door_receivers(lock[0])
222 var scene = get_tree().get_root().get_node_or_null("scene")
223 if scene != null:
224 for receiver in receivers:
225 var rnode = scene.get_node_or_null(receiver)
226 if rnode != null:
227 rnode.handleTriggered()
228
229 var letter_id = gamedata.letter_id_by_ap_id.get(item_id, null)
230 if letter_id != null:
231 var letter = gamedata.objects.get_letters()[letter_id]
232 if not letter.has_level2() or not letter.get_level2():
233 _process_key_item(letter.get_key(), amount)
234
235 if gamedata.symbol_item_ids.has(item_id):
236 var player = get_tree().get_root().get_node_or_null("scene/player")
237 if player != null:
238 player.evaluate_solvability.emit()
239
240 # Show a message about the item if it's new.
241 if int(item["index"]) > _last_new_item:
242 _last_new_item = int(item["index"])
243 saveLocaldata()
244
245 var full_item_name = item["text"]
246 if prog_id != null:
247 var door = gamedata.objects.get_doors()[prog_id]
248 full_item_name = "%s (%s)" % [full_item_name, door.get_name()]
249
250 var message
251 if "sender" in item:
252 message = (
253 "Received %s from %s"
254 % [wrapInItemColorTags(full_item_name, item["flags"]), item["sender"]]
255 )
256 else:
257 message = "Found %s" % wrapInItemColorTags(full_item_name, item["flags"])
258
259 if gamedata.anti_trap_ids.has(item):
260 keyboard.block_letter(gamedata.anti_trap_ids[item])
261
262 global._print(message)
263
264 global.get_node("Messages").showMessage(message)
265
266
267func _process_item_sent_notification(message):
268 var sentMsg = (
269 "Sent %s to %s"
270 % [
271 wrapInItemColorTags(message["item_name"], message["item_flags"]),
272 message["receiver_name"]
273 ]
274 )
275 #if _hinted_locations.has(message["item"]["location"]):
276 # sentMsg += " ([color=#fafad2]Hinted![/color])"
277 global.get_node("Messages").showMessage(sentMsg)
278
279
280func _process_hint_received(message):
281 var is_for = ""
282 if message["self"] == 0:
283 is_for = " for %s" % message["receiver_name"]
284
285 global.get_node("Messages").showMessage(
286 (
287 "Hint: %s%s is on %s"
288 % [
289 wrapInItemColorTags(message["item_name"], message["item_flags"]),
290 is_for,
291 message["location_name"]
292 ]
293 )
294 )
295
296
297func _process_text_message(message):
298 var parts = []
299 for message_part in message:
300 if message_part["type"] == "text":
301 parts.append(message_part["text"])
302 elif message_part["type"] == "player":
303 if message_part["self"] == 1:
304 parts.append("[color=#ee00ee]%s[/color]" % message_part["text"])
305 else:
306 parts.append("[color=#fafad2]%s[/color]" % message_part["text"])
307 elif message_part["type"] == "item":
308 parts.append(wrapInItemColorTags(message_part["text"], int(message_part["flags"])))
309 elif message_part["type"] == "location":
310 parts.append("[color=#00ff7f]%s[/color]" % message_part["text"])
311
312 var textclient_node = global.get_node("Textclient")
313 if textclient_node != null:
314 textclient_node.parse_printjson("".join(parts))
315
316
317func _process_location_scout(location_id, item_name, player_name, flags, for_self):
318 _location_scouts[location_id] = {
319 "item": item_name, "player": player_name, "flags": flags, "for_self": for_self
320 }
321
322 if for_self and flags & 4 != 0:
323 # This is a trap for us, so let's not display it.
324 return
325
326 var gamedata = global.get_node("Gamedata")
327 var map_id = gamedata.map_id_by_name.get(global.map)
328
329 var letter_id = gamedata.letter_id_by_ap_id.get(location_id, null)
330 if letter_id != null:
331 var letter = gamedata.objects.get_letters()[letter_id]
332 var room = gamedata.objects.get_rooms()[letter.get_room_id()]
333 if room.get_map_id() == map_id:
334 var collectable = get_tree().get_root().get_node("scene").get_node_or_null(
335 letter.get_path()
336 )
337 if collectable != null:
338 collectable.setScoutedText(item_name)
339
340
341func _on_accessible_locations_updated():
342 var textclient_node = global.get_node("Textclient")
343 if textclient_node != null:
344 textclient_node.update_locations()
345
346
347func _on_checked_locations_updated():
348 var textclient_node = global.get_node("Textclient")
349 if textclient_node != null:
350 textclient_node.update_locations()
351
352
353func _on_checked_worldports_updated():
354 var textclient_node = global.get_node("Textclient")
355 if textclient_node != null:
356 textclient_node.update_locations()
357 textclient_node.update_worldports()
358
359
360func _client_could_not_connect(message):
361 could_not_connect.emit(message)
362
363 if global.loaded:
364 var effects = global.get_node("Effects")
365 effects.set_connection_lost(true)
366
367 var messages = global.get_node("Messages")
368 messages.showMessage("Connection to multiworld lost.")
369
370
371func _client_connect_status(message):
372 connect_status.emit(message)
373
374
375func _client_connected(slot_data):
376 var effects = global.get_node("Effects")
377 effects.set_connection_lost(false)
378
379 if _already_connected:
380 var messages = global.get_node("Messages")
381 messages.showMessage("Reconnected to multiworld!")
382 return
383
384 _already_connected = true
385
386 var gamedata = global.get_node("Gamedata")
387
388 _localdata_file = "user://archipelago_data/%s_%d" % [client._seed, client._slot]
389 _last_new_item = -1
390
391 if FileAccess.file_exists(_localdata_file):
392 var ap_file = FileAccess.open(_localdata_file, FileAccess.READ)
393 var localdata = []
394 if ap_file != null:
395 localdata = ap_file.get_var(true)
396 ap_file.close()
397
398 if typeof(localdata) != TYPE_ARRAY:
399 print("AP localdata file is corrupted")
400 localdata = []
401
402 if localdata.size() > 0:
403 _last_new_item = localdata[0]
404
405 # Read slot data.
406 cyan_door_behavior = int(slot_data.get("cyan_door_behavior", 0))
407 daedalus_roof_access = bool(slot_data.get("daedalus_roof_access", false))
408 keyholder_sanity = bool(slot_data.get("keyholder_sanity", false))
409 shuffle_control_center_colors = bool(slot_data.get("shuffle_control_center_colors", false))
410 shuffle_doors = bool(slot_data.get("shuffle_doors", false))
411 shuffle_gallery_paintings = bool(slot_data.get("shuffle_gallery_paintings", false))
412 shuffle_letters = int(slot_data.get("shuffle_letters", 0))
413 shuffle_symbols = bool(slot_data.get("shuffle_symbols", false))
414 shuffle_worldports = bool(slot_data.get("shuffle_worldports", false))
415 strict_cyan_ending = bool(slot_data.get("strict_cyan_ending", false))
416 strict_purple_ending = bool(slot_data.get("strict_purple_ending", false))
417 victory_condition = int(slot_data.get("victory_condition", 0))
418
419 if slot_data.has("version"):
420 var version_msg = slot_data["version"]
421 apworld_version = [int(version_msg[0]), int(version_msg[1]), 0]
422 if version_msg.size() > 2:
423 apworld_version[2] = int(version_msg[2])
424
425 port_pairings.clear()
426 if slot_data.has("port_pairings"):
427 var raw_pp = slot_data.get("port_pairings")
428
429 for p1 in raw_pp.keys():
430 port_pairings[int(p1)] = int(raw_pp[p1])
431
432 # Set up item locks.
433 _item_locks = {}
434
435 if shuffle_doors:
436 for door in gamedata.objects.get_doors():
437 if (
438 door.get_type() == gamedata.SCRIPT_proto.DoorType.STANDARD
439 or door.get_type() == gamedata.SCRIPT_proto.DoorType.ITEM_ONLY
440 ):
441 _item_locks[door.get_id()] = [door.get_ap_id(), 1]
442
443 for progressive in gamedata.objects.get_progressives():
444 for i in range(0, progressive.get_doors().size()):
445 var door = gamedata.objects.get_doors()[progressive.get_doors()[i]]
446 _item_locks[door.get_id()] = [progressive.get_ap_id(), i + 1]
447
448 for door_group in gamedata.objects.get_door_groups():
449 if door_group.get_type() == gamedata.SCRIPT_proto.DoorGroupType.CONNECTOR:
450 if shuffle_worldports:
451 continue
452 elif door_group.get_type() != gamedata.SCRIPT_proto.DoorGroupType.SHUFFLE_GROUP:
453 continue
454
455 for door in door_group.get_doors():
456 _item_locks[door] = [door_group.get_ap_id(), 1]
457
458 if shuffle_control_center_colors:
459 for door in gamedata.objects.get_doors():
460 if door.get_type() == gamedata.SCRIPT_proto.DoorType.CONTROL_CENTER_COLOR:
461 _item_locks[door.get_id()] = [door.get_ap_id(), 1]
462
463 for door_group in gamedata.objects.get_door_groups():
464 if (
465 door_group.get_type() == gamedata.SCRIPT_proto.DoorGroupType.COLOR_CONNECTOR
466 and not shuffle_worldports
467 ):
468 for door in door_group.get_doors():
469 _item_locks[door] = [door_group.get_ap_id(), 1]
470
471 if shuffle_gallery_paintings:
472 for door in gamedata.objects.get_doors():
473 if door.get_type() == gamedata.SCRIPT_proto.DoorType.GALLERY_PAINTING:
474 _item_locks[door.get_id()] = [door.get_ap_id(), 1]
475
476 if cyan_door_behavior == kCYAN_DOOR_BEHAVIOR_ITEM:
477 for door_group in gamedata.objects.get_door_groups():
478 if door_group.get_type() == gamedata.SCRIPT_proto.DoorGroupType.CYAN_DOORS:
479 for door in door_group.get_doors():
480 if not _item_locks.has(door):
481 _item_locks[door] = [door_group.get_ap_id(), 1]
482
483 # Create a reverse item locks map for processing items.
484 _inverse_item_locks = {}
485
486 for door_id in _item_locks.keys():
487 var lock = _item_locks.get(door_id)
488
489 if not _inverse_item_locks.has(lock[0]):
490 _inverse_item_locks[lock[0]] = []
491
492 _inverse_item_locks[lock[0]].append([door_id, lock[1]])
493
494 if shuffle_worldports:
495 var textclient = global.get_node("Textclient")
496 textclient.setup_worldports()
497
498 ap_connected.emit()
499
500
501func start_batching_locations():
502 _batch_locations = true
503
504
505func send_location(loc_id):
506 if _batch_locations:
507 _held_locations.append(loc_id)
508 else:
509 client.sendLocation(loc_id)
510
511
512func scout_location(loc_id):
513 if _location_scouts.has(loc_id):
514 return _location_scouts.get(loc_id)
515
516 if _batch_locations:
517 _held_location_scouts.append(loc_id)
518 else:
519 client.scoutLocation(loc_id)
520
521 return null
522
523
524func stop_batching_locations():
525 _batch_locations = false
526
527 if not _held_locations.is_empty():
528 client.sendLocations(_held_locations)
529 _held_locations.clear()
530
531 if not _held_location_scouts.is_empty():
532 client.scoutLocations(_held_location_scouts)
533 _held_location_scouts.clear()
534
535
536func colorForItemType(flags):
537 var int_flags = int(flags)
538 if int_flags & 1: # progression
539 if int_flags & 2: # proguseful
540 return "#f0d200"
541 else:
542 return "#bc51e0"
543 elif int_flags & 2: # useful
544 return "#2b67ff"
545 elif int_flags & 4: # trap
546 return "#d63a22"
547 else: # filler
548 return "#14de9e"
549
550
551func wrapInItemColorTags(text, flags):
552 var int_flags = int(flags)
553 if int_flags & 1 and int_flags & 2: # proguseful
554 return "[rainbow]%s[/rainbow]" % text
555 else:
556 return "[color=%s]%s[/color]" % [colorForItemType(flags), text]
557
558
559func get_letter_behavior(key, level2):
560 if shuffle_letters == kSHUFFLE_LETTERS_UNLOCKED:
561 return kLETTER_BEHAVIOR_UNLOCKED
562
563 if [kSHUFFLE_LETTERS_VANILLA_CYAN, kSHUFFLE_LETTERS_ITEM_CYAN].has(shuffle_letters):
564 if level2:
565 if shuffle_letters == kSHUFFLE_LETTERS_VANILLA_CYAN:
566 return kLETTER_BEHAVIOR_VANILLA
567 else:
568 return kLETTER_BEHAVIOR_ITEM
569 else:
570 return kLETTER_BEHAVIOR_UNLOCKED
571
572 if not level2 and ["h", "i", "n", "t"].has(key):
573 # This differs from the equivalent function in the apworld. Logically it is
574 # the same as UNLOCKED since they are in the starting room, but VANILLA
575 # means the player still has to actually pick up the letters.
576 return kLETTER_BEHAVIOR_VANILLA
577
578 if shuffle_letters == kSHUFFLE_LETTERS_PROGRESSIVE:
579 return kLETTER_BEHAVIOR_ITEM
580
581 return kLETTER_BEHAVIOR_VANILLA
582
583
584func setup_keys():
585 keyboard.load_seed()
586
587 _letters_setup = true
588
589 for k in _held_letters.keys():
590 _process_key_item(k, _held_letters[k])
591
592 _held_letters.clear()
593
594
595func _process_key_item(key, level):
596 if not _letters_setup:
597 _held_letters[key] = max(_held_letters.get(key, 0), level)
598 return
599
600 if shuffle_letters == kSHUFFLE_LETTERS_ITEM_CYAN:
601 level += 1
602
603 keyboard.collect_remote_letter(key, level)
diff --git a/apworld/client/messages.gd b/apworld/client/messages.gd new file mode 100644 index 0000000..ab4f071 --- /dev/null +++ b/apworld/client/messages.gd
@@ -0,0 +1,74 @@
1extends CanvasLayer
2
3var SCRIPT_rainbowText
4
5var _message_queue = []
6var _font
7var _container
8var _ordered_labels = []
9
10
11func _ready():
12 _container = VBoxContainer.new()
13 _container.set_name("Container")
14 _container.anchor_bottom = 1
15 _container.offset_left = 20.0
16 _container.offset_right = 1920.0
17 _container.offset_top = 0.0
18 _container.offset_bottom = -20.0
19 _container.alignment = BoxContainer.ALIGNMENT_END
20 _container.mouse_filter = Control.MOUSE_FILTER_IGNORE
21 self.add_child(_container)
22
23 _font = load("res://assets/fonts/Lingo2.ttf")
24
25
26func _add_message(text):
27 var new_label = RichTextLabel.new()
28 new_label.install_effect(SCRIPT_rainbowText.new())
29 new_label.push_font(_font)
30 new_label.push_font_size(36)
31 new_label.push_outline_color(Color(0, 0, 0, 1))
32 new_label.push_outline_size(2)
33 new_label.append_text(text)
34 new_label.fit_content = true
35
36 _container.add_child(new_label)
37 _ordered_labels.push_back(new_label)
38
39
40func showMessage(text):
41 if _ordered_labels.size() >= 9:
42 _message_queue.append(text)
43 return
44
45 _add_message(text)
46
47 if _ordered_labels.size() > 1:
48 return
49
50 var timeout = 10.0
51 while !_ordered_labels.is_empty():
52 await get_tree().create_timer(timeout).timeout
53
54 if !_ordered_labels.is_empty():
55 var to_remove = _ordered_labels.pop_front()
56 var to_tween = get_tree().create_tween().bind_node(to_remove)
57 to_tween.tween_property(to_remove, "modulate:a", 0.0, 0.5)
58 to_tween.tween_callback(to_remove.queue_free)
59
60 if !_message_queue.is_empty():
61 var next_msg = _message_queue.pop_front()
62 _add_message(next_msg)
63
64 if timeout > 4:
65 timeout -= 3
66
67
68func clear():
69 _message_queue.clear()
70
71 for message_label in _ordered_labels:
72 message_label.queue_free()
73
74 _ordered_labels.clear()
diff --git a/apworld/client/minimap.gd b/apworld/client/minimap.gd new file mode 100644 index 0000000..5640716 --- /dev/null +++ b/apworld/client/minimap.gd
@@ -0,0 +1,175 @@
1extends CanvasLayer
2
3var player
4var drawer
5var sprite
6var label
7
8var cell_left
9var cell_top
10var cell_right
11var cell_bottom
12var cell_width
13var cell_height
14var center_x_min
15var center_x_max
16var center_y_min
17var center_y_max
18
19
20func _ready():
21 player = get_tree().get_root().get_node("scene/player")
22
23 var svc = PanelContainer.new()
24 svc.anchor_left = 1.0
25 svc.anchor_top = 1.0
26 svc.anchor_right = 1.0
27 svc.anchor_bottom = 1.0
28 svc.offset_left = -320.0
29 svc.offset_top = -320.0
30 svc.offset_right = -64.0
31 svc.offset_bottom = -64.0
32 svc.clip_contents = true
33 add_child(svc)
34
35 var background_color = Color.WHITE
36
37 var world_env = get_tree().get_root().get_node("scene/WorldEnvironment")
38 if world_env != null and world_env.environment != null:
39 if world_env.environment.background_mode == Environment.BG_COLOR:
40 background_color = world_env.environment.background_color
41 elif (
42 world_env.environment.background_mode == Environment.BG_SKY
43 and world_env.environment.sky != null
44 and world_env.environment.sky.sky_material != null
45 ):
46 var sky = world_env.environment.sky.sky_material
47 if sky is PhysicalSkyMaterial:
48 background_color = sky.ground_color
49 elif sky is ProceduralSkyMaterial:
50 background_color = sky.sky_top_color
51
52 var stylebox = StyleBoxFlat.new()
53 stylebox.bg_color = Color(background_color, 0.6)
54 svc.add_theme_stylebox_override("panel", stylebox)
55
56 drawer = Node2D.new()
57 svc.add_child(drawer)
58
59 var gridmap = get_tree().get_root().get_node("scene/GridMap")
60 if gridmap == null:
61 visible = false
62 return
63
64 cell_left = 0
65 cell_top = 0
66 cell_right = 0
67 cell_bottom = 0
68
69 for pos in gridmap.get_used_cells():
70 if pos.x < cell_left:
71 cell_left = pos.x
72 if pos.x > cell_right:
73 cell_right = pos.x
74 if pos.z < cell_top:
75 cell_top = pos.z
76 if pos.z > cell_bottom:
77 cell_bottom = pos.z
78
79 cell_width = cell_right - cell_left + 1
80 cell_height = cell_bottom - cell_top + 1
81
82 var rendered = _renderMap(gridmap)
83
84 var image_texture = ImageTexture.create_from_image(rendered)
85 sprite = Sprite2D.new()
86 sprite.texture = image_texture
87 sprite.texture_filter = CanvasItem.TEXTURE_FILTER_NEAREST
88 sprite.scale = Vector2(2, 2)
89 sprite.centered = false
90 drawer.add_child(sprite)
91
92 label = Label.new()
93 label.theme = preload("res://assets/themes/baseUI.tres")
94 label.add_theme_font_size_override("font_size", 32)
95 label.text = "@"
96 drawer.add_child(label)
97
98 #var local_tl = gridmap.map_to_local(Vector3i(cell_left, 0, cell_top))
99 #var global_tl = gridmap.to_global(local_tl)
100 #var local_br = gridmap.map_to_local(Vector3i(cell_right, 0, cell_bottom))
101 #var global_br = gridmap.to_global(local_br)
102
103 center_x_min = 0
104 center_x_max = cell_width - 128
105 center_y_min = 0
106 center_y_max = cell_height - 128
107
108 if center_x_max < center_x_min:
109 center_x_min = (center_x_min + center_x_max) / 2
110 center_x_max = center_x_min
111
112 if center_y_max < center_y_min:
113 center_y_min = (center_y_min + center_y_max) / 2
114 center_y_max = center_y_min
115
116
117func _process(_delta):
118 if visible == false:
119 return
120
121 drawer.position.x = clamp(player.position.x - cell_left - 64, center_x_min, center_x_max) * -2
122 drawer.position.y = clamp(player.position.z - cell_top - 64, center_y_min, center_y_max) * -2
123
124 label.position.x = (player.position.x - cell_left) * 2 - 16
125 label.position.y = (player.position.z - cell_top) * 2 - 16
126
127
128func _renderMap(gridmap):
129 var heights = {}
130
131 var rendered = Image.create_empty(cell_width, cell_height, false, Image.FORMAT_RGBA8)
132 rendered.fill(Color.TRANSPARENT)
133
134 var meshes_node = get_tree().get_root().get_node("scene/Meshes")
135 if meshes_node != null:
136 _renderMeshNode(gridmap, meshes_node, rendered)
137
138 for pos in gridmap.get_used_cells():
139 var in_plane = Vector2i(pos.x, pos.z)
140
141 if in_plane in heights and heights[in_plane] > pos.y:
142 continue
143
144 heights[in_plane] = pos.y
145
146 var cell_item = gridmap.get_cell_item(pos)
147 var mesh = gridmap.mesh_library.get_item_mesh(cell_item)
148 var material = mesh.surface_get_material(0)
149 var color = material.albedo_color
150
151 rendered.set_pixel(pos.x - cell_left, pos.z - cell_top, color)
152
153 return rendered
154
155
156func _renderMeshNode(gridmap, mesh, rendered):
157 if mesh is MeshInstance3D:
158 var local_tl = gridmap.map_to_local(Vector3i(cell_left, 0, cell_top))
159 var global_tl = gridmap.to_global(local_tl)
160 var mesh_material = mesh.get_surface_override_material(0)
161 if mesh_material != null:
162 var mesh_color = mesh_material.albedo_color
163
164 for y in range(
165 max(mesh.position.z - mesh.scale.z / 2 - global_tl.z, 0),
166 min(mesh.position.z + mesh.scale.z / 2 - global_tl.z, cell_height)
167 ):
168 for x in range(
169 max(mesh.position.x - mesh.scale.x / 2 - global_tl.x, 0),
170 min(mesh.position.x + mesh.scale.x / 2 - global_tl.x, cell_width)
171 ):
172 rendered.set_pixel(x, y, mesh_color)
173
174 for child in mesh.get_children():
175 _renderMeshNode(gridmap, child, rendered)
diff --git a/apworld/client/painting.gd b/apworld/client/painting.gd new file mode 100644 index 0000000..276d4eb --- /dev/null +++ b/apworld/client/painting.gd
@@ -0,0 +1,38 @@
1extends "res://scripts/nodes/painting.gd"
2
3var item_id
4var item_amount
5
6
7func _ready():
8 var node_path = String(
9 get_tree().get_root().get_node("scene").get_path_to(self).get_concatenated_names()
10 )
11
12 var gamedata = global.get_node("Gamedata")
13 var door_id = gamedata.get_door_for_map_node_path(global.map, node_path)
14 if door_id != null:
15 var ap = global.get_node("Archipelago")
16 var item_lock = ap.get_item_id_for_door(door_id)
17
18 if item_lock != null:
19 item_id = item_lock[0]
20 item_amount = item_lock[1]
21
22 self.senders = []
23 self.senderGroup = []
24 self.nested = false
25 self.complete_at = 0
26 self.max_length = 0
27 self.excludeSenders = []
28
29 call_deferred("_readier")
30
31 super._ready()
32
33
34func _readier():
35 var ap = global.get_node("Archipelago")
36
37 if ap.client.getItemAmount(item_id) >= item_amount:
38 handleTriggered()
diff --git a/apworld/client/panel.gd b/apworld/client/panel.gd new file mode 100644 index 0000000..2cef28e --- /dev/null +++ b/apworld/client/panel.gd
@@ -0,0 +1,101 @@
1extends "res://scripts/nodes/panel.gd"
2
3var panel_logic = null
4var symbol_solvable = true
5
6var black = load("res://assets/materials/black.material")
7
8
9func _ready():
10 super._ready()
11
12 var node_path = String(
13 get_tree().get_root().get_node("scene").get_path_to(self).get_concatenated_names()
14 )
15
16 var gamedata = global.get_node("Gamedata")
17 var panel_id = gamedata.get_panel_for_map_node_path(global.map, node_path)
18 if panel_id != null:
19 var ap = global.get_node("Archipelago")
20 if ap.shuffle_symbols:
21 if global.map == "the_entry" and node_path == "Panels/Entry/front_1":
22 clue = "i"
23 symbol = ""
24
25 setField("clue", clue)
26 setField("symbol", symbol)
27
28 panel_logic = gamedata.objects.get_panels()[panel_id]
29 checkSymbolSolvable()
30
31 if not symbol_solvable:
32 get_tree().get_root().get_node("scene/player").evaluate_solvability.connect(
33 evaluateSolvability
34 )
35
36
37func checkSymbolSolvable():
38 var old_solvable = symbol_solvable
39 symbol_solvable = true
40
41 if panel_logic == null:
42 # There's no logic for this panel.
43 return
44
45 var ap = global.get_node("Archipelago")
46 if not ap.shuffle_symbols:
47 # Symbols aren't item-locked.
48 return
49
50 var gamedata = global.get_node("Gamedata")
51 for symbol in panel_logic.get_symbols():
52 var item_name = gamedata.kSYMBOL_ITEMS.get(symbol)
53 var item_id = gamedata.objects.get_special_ids()[item_name]
54 if ap.client.getItemAmount(item_id) < 1:
55 symbol_solvable = false
56 break
57
58 if symbol_solvable != old_solvable:
59 if symbol_solvable:
60 setField("clue", clue)
61 setField("symbol", symbol)
62 setField("answer", answer)
63 else:
64 quad_mesh.surface_set_material(0, black)
65 get_node("Hinge/clue").text = "missing"
66 get_node("Hinge/answer").text = "symbols"
67
68
69func checkSolvable(key):
70 checkSymbolSolvable()
71 if not symbol_solvable:
72 return false
73
74 return super.checkSolvable(key)
75
76
77func evaluateSolvability():
78 checkSolvable("")
79
80
81func passedInput(key, skip_focus_check = false):
82 if not symbol_solvable:
83 return
84
85 super.passedInput(key, skip_focus_check)
86
87
88func focus():
89 if not symbol_solvable:
90 has_focus = false
91 return
92
93 super.focus()
94
95
96func unfocus():
97 if not symbol_solvable:
98 has_focus = false
99 return
100
101 super.unfocus()
diff --git a/apworld/client/pauseMenu.gd b/apworld/client/pauseMenu.gd new file mode 100644 index 0000000..72b45e8 --- /dev/null +++ b/apworld/client/pauseMenu.gd
@@ -0,0 +1,91 @@
1extends "res://scripts/ui/pauseMenu.gd"
2
3var compass_button
4var locations_button
5var minimap_button
6
7
8func _ready():
9 var ap_panel = Panel.new()
10 ap_panel.name = "Archipelago"
11 get_node("menu/settings/settingsInner/TabContainer").add_child(ap_panel)
12
13 var ap = global.get_node("Archipelago")
14
15 compass_button = CheckBox.new()
16 compass_button.text = "show compass"
17 compass_button.button_pressed = ap.show_compass
18 compass_button.position = Vector2(65, 100)
19 compass_button.theme = preload("res://assets/themes/baseUI.tres")
20 compass_button.add_theme_font_size_override("font_size", 60)
21 compass_button.pressed.connect(_toggle_compass)
22 ap_panel.add_child(compass_button)
23
24 locations_button = CheckBox.new()
25 locations_button.text = "show locations overlay"
26 locations_button.button_pressed = ap.show_locations
27 locations_button.position = Vector2(65, 200)
28 locations_button.theme = preload("res://assets/themes/baseUI.tres")
29 locations_button.add_theme_font_size_override("font_size", 60)
30 locations_button.pressed.connect(_toggle_locations)
31 ap_panel.add_child(locations_button)
32
33 minimap_button = CheckBox.new()
34 minimap_button.text = "show minimap"
35 minimap_button.button_pressed = ap.show_minimap
36 minimap_button.position = Vector2(65, 300)
37 minimap_button.theme = preload("res://assets/themes/baseUI.tres")
38 minimap_button.add_theme_font_size_override("font_size", 60)
39 minimap_button.pressed.connect(_toggle_minimap)
40 ap_panel.add_child(minimap_button)
41
42 super._ready()
43
44
45func _pause_game():
46 global.get_node("Textclient").dismiss()
47 super._pause_game()
48
49
50func _main_menu():
51 global.loaded = false
52 global.get_node("Archipelago").disconnect_from_ap()
53 global.get_node("Messages").clear()
54 global.get_node("Compass").visible = false
55 global.get_node("Textclient").reset()
56
57 autosplitter.reset()
58 _unpause_game()
59 Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE)
60 musicPlayer.stop()
61
62 var runtime = global.get_node("Runtime")
63 runtime.load_script_as_scene.call_deferred("settings_screen.gd", "settings_screen")
64
65
66func _toggle_compass():
67 var ap = global.get_node("Archipelago")
68 ap.show_compass = compass_button.button_pressed
69 ap.saveSettings()
70
71 var compass = global.get_node("Compass")
72 compass.visible = compass_button.button_pressed
73
74
75func _toggle_locations():
76 var ap = global.get_node("Archipelago")
77 ap.show_locations = locations_button.button_pressed
78 ap.saveSettings()
79
80 var textclient = global.get_node("Textclient")
81 textclient.update_locations_visibility()
82
83
84func _toggle_minimap():
85 var ap = global.get_node("Archipelago")
86 ap.show_minimap = minimap_button.button_pressed
87 ap.saveSettings()
88
89 var minimap = get_tree().get_root().get_node("scene/Minimap")
90 if minimap != null:
91 minimap.visible = ap.show_minimap
diff --git a/apworld/client/player.gd b/apworld/client/player.gd new file mode 100644 index 0000000..5417a48 --- /dev/null +++ b/apworld/client/player.gd
@@ -0,0 +1,346 @@
1extends "res://scripts/nodes/player.gd"
2
3signal evaluate_solvability
4
5var compass
6
7
8func _ready():
9 var khl_script = load("res://scripts/nodes/keyHolderListener.gd")
10
11 var pause_menu = get_node("pause_menu")
12 pause_menu.layer = 3
13
14 var ap = global.get_node("Archipelago")
15 var gamedata = global.get_node("Gamedata")
16
17 compass = global.get_node("Compass")
18 compass.visible = ap.show_compass
19
20 ap.start_batching_locations()
21
22 # Set up door locations.
23 var map_id = gamedata.map_id_by_name.get(global.map)
24 for door in gamedata.objects.get_doors():
25 if door.get_map_id() != map_id:
26 continue
27
28 if not door.has_ap_id():
29 continue
30
31 if (
32 door.get_type() == gamedata.SCRIPT_proto.DoorType.ITEM_ONLY
33 or door.get_type() == gamedata.SCRIPT_proto.DoorType.GALLERY_PAINTING
34 ):
35 continue
36
37 var locationListener = ap.SCRIPT_locationListener.new()
38 locationListener.location_id = door.get_ap_id()
39 locationListener.name = "locationListener_%d" % door.get_ap_id()
40
41 for panel_ref in door.get_panels():
42 var panel_data = gamedata.objects.get_panels()[panel_ref.get_panel()]
43 var panel_path = panel_data.get_path()
44
45 if panel_ref.has_answer():
46 for proxy in panel_data.get_proxies():
47 if proxy.get_answer() == panel_ref.get_answer():
48 panel_path = proxy.get_path()
49 break
50
51 locationListener.senders.append(NodePath("/root/scene/" + panel_path))
52
53 for keyholder_ref in door.get_keyholders():
54 var keyholder_data = gamedata.objects.get_keyholders()[keyholder_ref.get_keyholder()]
55
56 var khl = khl_script.new()
57 khl.name = (
58 "location_%d_keyholder_%d" % [door.get_ap_id(), keyholder_ref.get_keyholder()]
59 )
60 khl.answer = keyholder_ref.get_key()
61 khl.senders.append(NodePath("/root/scene/" + keyholder_data.get_path()))
62 get_parent().add_child.call_deferred(khl)
63
64 locationListener.senders.append(NodePath("../" + khl.name))
65
66 for sender in door.get_senders():
67 locationListener.senders.append(NodePath("/root/scene/" + sender))
68
69 if door.has_complete_at():
70 locationListener.complete_at = door.get_complete_at()
71
72 get_parent().add_child.call_deferred(locationListener)
73
74 # Set up letter locations.
75 for letter in gamedata.objects.get_letters():
76 var room = gamedata.objects.get_rooms()[letter.get_room_id()]
77 if room.get_map_id() != map_id:
78 continue
79
80 var locationListener = ap.SCRIPT_locationListener.new()
81 locationListener.location_id = letter.get_ap_id()
82 locationListener.name = "locationListener_%d" % letter.get_ap_id()
83 locationListener.senders.append(NodePath("/root/scene/" + letter.get_path()))
84
85 get_parent().add_child.call_deferred(locationListener)
86
87 if (
88 ap.get_letter_behavior(letter.get_key(), letter.has_level2() and letter.get_level2())
89 != ap.kLETTER_BEHAVIOR_VANILLA
90 ):
91 var scout = ap.scout_location(letter.get_ap_id())
92 if scout != null and not (scout["for_self"] and scout["flags"] & 4 != 0):
93 var collectable = get_tree().get_root().get_node("scene").get_node_or_null(
94 letter.get_path()
95 )
96 if collectable != null:
97 collectable.setScoutedText.call_deferred(scout["item"])
98
99 # Set up mastery locations.
100 for mastery in gamedata.objects.get_masteries():
101 var room = gamedata.objects.get_rooms()[mastery.get_room_id()]
102 if room.get_map_id() != map_id:
103 continue
104
105 var locationListener = ap.SCRIPT_locationListener.new()
106 locationListener.location_id = mastery.get_ap_id()
107 locationListener.name = "locationListener_%d" % mastery.get_ap_id()
108 locationListener.senders.append(NodePath("/root/scene/" + mastery.get_path()))
109
110 get_parent().add_child.call_deferred(locationListener)
111
112 # Set up ending locations.
113 for ending in gamedata.objects.get_endings():
114 var room = gamedata.objects.get_rooms()[ending.get_room_id()]
115 if room.get_map_id() != map_id:
116 continue
117
118 var locationListener = ap.SCRIPT_locationListener.new()
119 locationListener.location_id = ending.get_ap_id()
120 locationListener.name = "locationListener_%d" % ending.get_ap_id()
121 locationListener.senders.append(NodePath("/root/scene/" + ending.get_path()))
122
123 get_parent().add_child.call_deferred(locationListener)
124
125 if ap.kEndingNameByVictoryValue.get(ap.victory_condition, null) == ending.get_name():
126 var victoryListener = ap.SCRIPT_victoryListener.new()
127 victoryListener.name = "victoryListener"
128 victoryListener.senders.append(NodePath("/root/scene/" + ending.get_path()))
129
130 get_parent().add_child.call_deferred(victoryListener)
131
132 # Set up keyholder locations, in keyholder sanity.
133 if ap.keyholder_sanity:
134 for keyholder in gamedata.objects.get_keyholders():
135 if not keyholder.has_key():
136 continue
137
138 var room = gamedata.objects.get_rooms()[keyholder.get_room_id()]
139 if room.get_map_id() != map_id:
140 continue
141
142 var locationListener = ap.SCRIPT_locationListener.new()
143 locationListener.location_id = keyholder.get_ap_id()
144 locationListener.name = "locationListener_%d" % keyholder.get_ap_id()
145
146 var khl = khl_script.new()
147 khl.name = "location_%d_keyholder" % keyholder.get_ap_id()
148 khl.answer = keyholder.get_key()
149 khl.senders.append(NodePath("/root/scene/" + keyholder.get_path()))
150 get_parent().add_child.call_deferred(khl)
151
152 locationListener.senders.append(NodePath("../" + khl.name))
153
154 get_parent().add_child.call_deferred(locationListener)
155
156 # Block off roof access in Daedalus.
157 if global.map == "daedalus" and not ap.daedalus_roof_access:
158 _set_up_invis_wall(75.5, 11, -24.5, 1, 10, 49)
159 _set_up_invis_wall(51.5, 11, -17, 16, 10, 1)
160 _set_up_invis_wall(46, 10, -9.5, 1, 10, 10)
161 _set_up_invis_wall(67.5, 11, 17, 16, 10, 1)
162 _set_up_invis_wall(50.5, 11, 14, 10, 10, 1)
163 _set_up_invis_wall(39, 10, 18.5, 1, 10, 22)
164 _set_up_invis_wall(20, 15, 18.5, 1, 10, 16)
165 _set_up_invis_wall(11.5, 15, 3, 32, 10, 1)
166 _set_up_invis_wall(11.5, 16, -20, 14, 20, 1)
167 _set_up_invis_wall(14, 16, -26.5, 1, 20, 4)
168 _set_up_invis_wall(28.5, 20.5, -26.5, 1, 15, 25)
169 _set_up_invis_wall(40.5, 20.5, -11, 30, 15, 1)
170 _set_up_invis_wall(50.5, 15, 5.5, 7, 10, 1)
171 _set_up_invis_wall(83.5, 33.5, 5.5, 1, 7, 11)
172 _set_up_invis_wall(83.5, 33.5, -5.5, 1, 7, 11)
173
174 var warp_exit_prefab = preload("res://objects/nodes/exit.tscn")
175 var warp_exit = warp_exit_prefab.instantiate()
176 warp_exit.name = "roof_access_blocker_warp_exit"
177 warp_exit.position = Vector3(58, 10, 0)
178 warp_exit.rotation_degrees.y = 90
179 get_parent().add_child.call_deferred(warp_exit)
180
181 var warp_enter_prefab = preload("res://objects/nodes/teleportAuto.tscn")
182 var warp_enter = warp_enter_prefab.instantiate()
183 warp_enter.target = warp_exit
184 warp_enter.position = Vector3(76.5, 30, 1)
185 warp_enter.scale = Vector3(4, 1.5, 1)
186 warp_enter.rotation_degrees.y = 90
187 get_parent().add_child.call_deferred(warp_enter)
188
189 if global.map == "the_entry":
190 # Remove door behind X1.
191 var door_node = get_tree().get_root().get_node("/root/scene/Components/Doors/exit_1")
192 door_node.handleTriggered()
193
194 # Display win condition.
195 var sign_prefab = preload("res://objects/nodes/sign.tscn")
196 var sign1 = sign_prefab.instantiate()
197 sign1.position = Vector3(-7, 5, -15.01)
198 sign1.text = "victory"
199 get_parent().add_child.call_deferred(sign1)
200
201 var sign2 = sign_prefab.instantiate()
202 sign2.position = Vector3(-7, 4, -15.01)
203 sign2.text = "%s ending" % ap.kEndingNameByVictoryValue.get(ap.victory_condition, "?")
204
205 var sign2_color = ap.kEndingNameByVictoryValue.get(ap.victory_condition, "coral").to_lower()
206 if sign2_color == "white":
207 sign2_color = "silver"
208
209 sign2.material = load("res://assets/materials/%s.material" % sign2_color)
210 get_parent().add_child.call_deferred(sign2)
211
212 # Add the strict purple ending validation.
213 if global.map == "the_sun_temple" and ap.strict_purple_ending:
214 var panel_prefab = preload("res://objects/nodes/panel.tscn")
215 var tpl_prefab = preload("res://objects/nodes/listeners/teleportListener.tscn")
216 var reverse_prefab = preload("res://objects/nodes/listeners/reversingListener.tscn")
217
218 var previous_panel = null
219 var next_y = -100
220 var words = ["quick", "brown", "fox", "jumps", "over", "the", "lazy", "dog"]
221 for word in words:
222 var panel = panel_prefab.instantiate()
223 panel.position = Vector3(0, next_y, 0)
224 next_y -= 10
225 panel.clue = word
226 panel.symbol = ""
227 panel.answer = word
228 panel.name = "EndCheck_%s" % word
229
230 var tpl = tpl_prefab.instantiate()
231 tpl.teleport_point = Vector3(0, 1, 0)
232 tpl.teleport_rotate = Vector3(-45, 180, 0)
233 tpl.target_path = panel
234 tpl.name = "Teleport"
235
236 if previous_panel == null:
237 tpl.senders.append(NodePath("/root/scene/Panels/End/panel_24"))
238 else:
239 tpl.senders.append(NodePath("../../%s" % previous_panel.name))
240
241 var reversing = reverse_prefab.instantiate()
242 reversing.senders.append(NodePath(".."))
243 reversing.name = "Reversing"
244 tpl.senders.append(NodePath("../Reversing"))
245
246 panel.add_child.call_deferred(tpl)
247 panel.add_child.call_deferred(reversing)
248 get_parent().get_node("Panels").add_child.call_deferred(panel)
249
250 previous_panel = panel
251
252 # Duplicate the doors that usually wait on EQUINOX. We can't set the senders
253 # here for some reason so we actually set them in the door ready function.
254 var endplat = get_node("/root/scene/Components/Doors/EndPlatform")
255 var endplat2 = endplat.duplicate()
256 endplat2.name = "spe_EndPlatform"
257 endplat.get_parent().add_child.call_deferred(endplat2)
258 endplat.queue_free()
259
260 var entry2 = get_node("/root/scene/Components/Doors/entry_2")
261 var entry22 = entry2.duplicate()
262 entry22.name = "spe_entry_2"
263 entry2.get_parent().add_child.call_deferred(entry22)
264 entry2.queue_free()
265
266 # Add the strict cyan ending validation.
267 if global.map == "the_parthenon" and ap.strict_cyan_ending:
268 var panel_prefab = preload("res://objects/nodes/panel.tscn")
269 var tpl_prefab = preload("res://objects/nodes/listeners/teleportListener.tscn")
270 var reverse_prefab = preload("res://objects/nodes/listeners/reversingListener.tscn")
271
272 var previous_panel = null
273 var next_y = -100
274 var words = ["quick", "brown", "fox", "jumps", "over", "the", "lazy", "dog"]
275 for word in words:
276 var panel = panel_prefab.instantiate()
277 panel.position = Vector3(0, next_y, 0)
278 next_y -= 10
279 panel.clue = word
280 panel.symbol = "."
281 panel.answer = "%s%s" % [word, word]
282 panel.name = "EndCheck_%s" % word
283
284 var tpl = tpl_prefab.instantiate()
285 tpl.teleport_point = Vector3(0, 1, -11)
286 tpl.teleport_rotate = Vector3(-45, 0, 0)
287 tpl.target_path = panel
288 tpl.name = "Teleport"
289
290 if previous_panel == null:
291 tpl.senderGroup.append(NodePath("/root/scene/Panels/Rulers"))
292 else:
293 tpl.senders.append(NodePath("../../%s" % previous_panel.name))
294
295 var reversing = reverse_prefab.instantiate()
296 reversing.senders.append(NodePath(".."))
297 reversing.name = "Reversing"
298 tpl.senders.append(NodePath("../Reversing"))
299
300 panel.add_child.call_deferred(tpl)
301 panel.add_child.call_deferred(reversing)
302 get_parent().get_node("Panels").add_child.call_deferred(panel)
303
304 previous_panel = panel
305
306 # Duplicate the door that usually waits on the rulers. We can't set the
307 # senders here for some reason so we actually set them in the door ready
308 # function.
309 var entry1 = get_node("/root/scene/Components/Doors/entry_1")
310 var entry12 = entry1.duplicate()
311 entry12.name = "spe_entry_1"
312 entry1.get_parent().add_child.call_deferred(entry12)
313 entry1.queue_free()
314
315 var minimap = ap.SCRIPT_minimap.new()
316 minimap.name = "Minimap"
317 minimap.visible = ap.show_minimap
318 get_parent().add_child.call_deferred(minimap)
319
320 super._ready()
321
322 await get_tree().process_frame
323 await get_tree().process_frame
324
325 ap.stop_batching_locations()
326
327
328func _set_up_invis_wall(x, y, z, sx, sy, sz):
329 var prefab = preload("res://objects/nodes/block.tscn")
330 var newwall = prefab.instantiate()
331 newwall.position.x = x
332 newwall.position.y = y
333 newwall.position.z = z
334 newwall.scale.x = sz
335 newwall.scale.y = sy
336 newwall.scale.z = sx
337 newwall.set_surface_override_material(0, preload("res://assets/materials/blackMatte.material"))
338 newwall.visibility_range_end = 3
339 newwall.visibility_range_end_margin = 1
340 newwall.visibility_range_fade_mode = RenderingServer.VISIBILITY_RANGE_FADE_SELF
341 newwall.skeleton = ".."
342 get_parent().add_child.call_deferred(newwall)
343
344
345func _process(_dt):
346 compass.update_rotation(global_rotation.y)
diff --git a/apworld/client/rainbowText.gd b/apworld/client/rainbowText.gd new file mode 100644 index 0000000..9a4c1d0 --- /dev/null +++ b/apworld/client/rainbowText.gd
@@ -0,0 +1,10 @@
1extends RichTextEffect
2
3var bbcode = "rainbow"
4
5
6func _process_custom_fx(char_fx: CharFXTransform):
7 char_fx.color = Color.from_hsv(
8 char_fx.elapsed_time - floor(char_fx.elapsed_time), 1.0, 1.0, 1.0
9 )
10 return true
diff --git a/apworld/client/run_from_apworld.tscn b/apworld/client/run_from_apworld.tscn new file mode 100644 index 0000000..11373e0 --- /dev/null +++ b/apworld/client/run_from_apworld.tscn
@@ -0,0 +1,30 @@
1[gd_scene load_steps=11 format=2]
2
3[sub_resource id=2 type="GDScript"]
4script/source = "extends Node2D
5
6
7func _ready():
8 var args = OS.get_cmdline_user_args()
9 var apworld_path = args[0]
10
11 var zip_reader = ZIPReader.new()
12 zip_reader.open(apworld_path)
13
14 var runtime_script = GDScript.new()
15 runtime_script.source_code = zip_reader.read_file(\"lingo2/client/apworld_runtime.gd\").get_string_from_utf8()
16 runtime_script.reload()
17
18 zip_reader.close()
19
20 var runtime = runtime_script.new(apworld_path)
21 runtime.name = \"Runtime\"
22
23 global.add_child(runtime)
24
25 runtime.load_script_as_scene.call_deferred(\"settings_screen.gd\", \"settings_screen\")
26
27"
28
29[node name="loader" type="Node2D"]
30script = SubResource( 2 )
diff --git a/apworld/client/run_from_source.tscn b/apworld/client/run_from_source.tscn new file mode 100644 index 0000000..59a914d --- /dev/null +++ b/apworld/client/run_from_source.tscn
@@ -0,0 +1,22 @@
1[gd_scene load_steps=11 format=2]
2
3[sub_resource id=2 type="GDScript"]
4script/source = "extends Node2D
5
6
7func _ready():
8 var args = OS.get_cmdline_user_args()
9 var source_path = args[0]
10
11 var runtime_script = ResourceLoader.load(\"%s/source_runtime.gd\" % source_path)
12 var runtime = runtime_script.new(source_path)
13 runtime.name = \"Runtime\"
14
15 global.add_child(runtime)
16
17 runtime.load_script_as_scene.call_deferred(\"settings_screen.gd\", \"settings_screen\")
18
19"
20
21[node name="loader" type="Node2D"]
22script = SubResource( 2 )
diff --git a/apworld/client/saver.gd b/apworld/client/saver.gd new file mode 100644 index 0000000..44bc179 --- /dev/null +++ b/apworld/client/saver.gd
@@ -0,0 +1,23 @@
1extends "res://scripts/nodes/saver.gd"
2
3
4func levelLoaded():
5 if type == "keyholders":
6 var ap = global.get_node("Archipelago")
7 ap.keyboard.load_keyholders.call_deferred(global.map)
8 else:
9 reload.call_deferred()
10
11
12func reload():
13 # Just rewriting this whole thing so I can remove Chris's safeguard.
14 var file = FileAccess.open(path + type + ".save", FileAccess.READ)
15 if file:
16 var data = file.get_var(true)
17 file.close()
18 for datum in data:
19 var saveable = get_node_or_null(datum[0])
20 if saveable != null:
21 saveable.is_complete = datum[1]
22 if saveable.is_complete:
23 saveable.loadData(saveable.is_complete)
diff --git a/apworld/client/settings_screen.gd b/apworld/client/settings_screen.gd new file mode 100644 index 0000000..b430b17 --- /dev/null +++ b/apworld/client/settings_screen.gd
@@ -0,0 +1,153 @@
1extends Node
2
3
4func _ready():
5 var theme = preload("res://assets/themes/baseUI.tres")
6
7 var simple_style_box = StyleBoxFlat.new()
8 simple_style_box.bg_color = Color(0, 0, 0, 0)
9
10 var panel = Panel.new()
11 panel.name = "Panel"
12 panel.offset_right = 1920.0
13 panel.offset_bottom = 1080.0
14 add_child(panel)
15
16 var title = Label.new()
17 title.name = "title"
18 title.offset_left = 0.0
19 title.offset_top = 75.0
20 title.offset_right = 1920.0
21 title.offset_bottom = 225.0
22 title.text = "ARCHIPELAGO"
23 title.vertical_alignment = VERTICAL_ALIGNMENT_CENTER
24 title.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
25 title.theme = theme
26 panel.add_child(title)
27
28 var connect_button = Button.new()
29 connect_button.name = "connect_button"
30 connect_button.offset_left = 255.0
31 connect_button.offset_top = 875.0
32 connect_button.offset_right = 891.0
33 connect_button.offset_bottom = 1025.0
34 connect_button.add_theme_color_override("font_color_hover", Color(1, 0.501961, 0, 1))
35 connect_button.text = "CONNECT"
36 connect_button.theme = theme
37 panel.add_child(connect_button)
38
39 var quit_button = Button.new()
40 quit_button.name = "quit_button"
41 quit_button.offset_left = 1102.0
42 quit_button.offset_top = 875.0
43 quit_button.offset_right = 1738.0
44 quit_button.offset_bottom = 1025.0
45 quit_button.add_theme_color_override("font_color_hover", Color(1, 0, 0, 1))
46 quit_button.text = "QUIT"
47 quit_button.theme = theme
48 panel.add_child(quit_button)
49
50 var credit2 = Label.new()
51 credit2.name = "credit2"
52 credit2.offset_left = -105.0
53 credit2.offset_top = 346.0
54 credit2.offset_right = 485.0
55 credit2.offset_bottom = 410.0
56 credit2.add_theme_stylebox_override("normal", simple_style_box)
57 credit2.text = "SERVER"
58 credit2.horizontal_alignment = HORIZONTAL_ALIGNMENT_RIGHT
59 credit2.theme = theme
60 panel.add_child(credit2)
61
62 var credit3 = Label.new()
63 credit3.name = "credit3"
64 credit3.offset_left = -105.0
65 credit3.offset_top = 519.0
66 credit3.offset_right = 485.0
67 credit3.offset_bottom = 583.0
68 credit3.add_theme_stylebox_override("normal", simple_style_box)
69 credit3.text = "PLAYER"
70 credit3.horizontal_alignment = HORIZONTAL_ALIGNMENT_RIGHT
71 credit3.theme = theme
72 panel.add_child(credit3)
73
74 var credit4 = Label.new()
75 credit4.name = "credit4"
76 credit4.offset_left = -105.0
77 credit4.offset_top = 704.0
78 credit4.offset_right = 485.0
79 credit4.offset_bottom = 768.0
80 credit4.add_theme_stylebox_override("normal", simple_style_box)
81 credit4.text = "PASSWORD"
82 credit4.horizontal_alignment = HORIZONTAL_ALIGNMENT_RIGHT
83 credit4.theme = theme
84 panel.add_child(credit4)
85
86 var credit5 = Label.new()
87 credit5.name = "credit5"
88 credit5.offset_left = 1239.0
89 credit5.offset_top = 422.0
90 credit5.offset_right = 1829.0
91 credit5.offset_bottom = 486.0
92 credit5.add_theme_stylebox_override("normal", simple_style_box)
93 credit5.text = "OPTIONS"
94 credit5.theme = theme
95 panel.add_child(credit5)
96
97 var server_box = LineEdit.new()
98 server_box.name = "server_box"
99 server_box.offset_left = 502.0
100 server_box.offset_top = 295.0
101 server_box.offset_right = 1144.0
102 server_box.offset_bottom = 445.0
103 server_box.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
104 server_box.caret_blink = true
105 panel.add_child(server_box)
106
107 var player_box = LineEdit.new()
108 player_box.name = "player_box"
109 player_box.offset_left = 502.0
110 player_box.offset_top = 477.0
111 player_box.offset_right = 1144.0
112 player_box.offset_bottom = 627.0
113 player_box.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
114 player_box.caret_blink = true
115 panel.add_child(player_box)
116
117 var password_box = LineEdit.new()
118 password_box.name = "password_box"
119 password_box.offset_left = 502.0
120 password_box.offset_top = 659.0
121 password_box.offset_right = 1144.0
122 password_box.offset_bottom = 809.0
123 password_box.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
124 password_box.caret_blink = true
125 panel.add_child(password_box)
126
127 var accept_dialog = AcceptDialog.new()
128 accept_dialog.name = "AcceptDialog"
129 accept_dialog.offset_right = 83.0
130 accept_dialog.offset_bottom = 58.0
131 panel.add_child(accept_dialog)
132
133 var version_mismatch = ConfirmationDialog.new()
134 version_mismatch.name = "VersionMismatch"
135 version_mismatch.offset_right = 83.0
136 version_mismatch.offset_bottom = 58.0
137 panel.add_child(version_mismatch)
138
139 var connection_history = MenuButton.new()
140 connection_history.name = "connection_history"
141 connection_history.offset_left = 1239.0
142 connection_history.offset_top = 276.0
143 connection_history.offset_right = 1829.0
144 connection_history.offset_bottom = 372.0
145 connection_history.text = "connection history"
146 connection_history.flat = false
147 panel.add_child(connection_history)
148
149 var runtime = global.get_node("Runtime")
150 var main_script = runtime.load_script("main.gd")
151 var main_node = main_script.new()
152 main_node.name = "Main"
153 add_child(main_node)
diff --git a/apworld/client/source_runtime.gd b/apworld/client/source_runtime.gd new file mode 100644 index 0000000..35428ea --- /dev/null +++ b/apworld/client/source_runtime.gd
@@ -0,0 +1,29 @@
1extends Node
2
3var source_path
4
5
6func _init(path):
7 source_path = path
8
9
10func load_script(path):
11 return ResourceLoader.load("%s/%s" % [source_path, path])
12
13
14func read_path(path):
15 return FileAccess.get_file_as_bytes("%s/%s" % [source_path, path])
16
17
18func load_script_as_scene(path, scene_name):
19 var script = load_script(path)
20 var instance = script.new()
21 instance.name = scene_name
22
23 get_tree().unload_current_scene()
24 _load_scene.call_deferred(instance)
25
26
27func _load_scene(instance):
28 get_tree().get_root().add_child(instance)
29 get_tree().current_scene = instance
diff --git a/apworld/client/teleport.gd b/apworld/client/teleport.gd new file mode 100644 index 0000000..428d50b --- /dev/null +++ b/apworld/client/teleport.gd
@@ -0,0 +1,38 @@
1extends "res://scripts/nodes/teleport.gd"
2
3var item_id
4var item_amount
5
6
7func _ready():
8 var node_path = String(
9 get_tree().get_root().get_node("scene").get_path_to(self).get_concatenated_names()
10 )
11
12 var gamedata = global.get_node("Gamedata")
13 var door_id = gamedata.get_door_for_map_node_path(global.map, node_path)
14 if door_id != null:
15 var ap = global.get_node("Archipelago")
16 var item_lock = ap.get_item_id_for_door(door_id)
17
18 if item_lock != null:
19 item_id = item_lock[0]
20 item_amount = item_lock[1]
21
22 self.senders = []
23 self.senderGroup = []
24 self.nested = false
25 self.complete_at = 0
26 self.max_length = 0
27 self.excludeSenders = []
28
29 call_deferred("_readier")
30
31 super._ready()
32
33
34func _readier():
35 var ap = global.get_node("Archipelago")
36
37 if ap.client.getItemAmount(item_id) >= item_amount:
38 handleTriggered()
diff --git a/apworld/client/teleportListener.gd b/apworld/client/teleportListener.gd new file mode 100644 index 0000000..6f363af --- /dev/null +++ b/apworld/client/teleportListener.gd
@@ -0,0 +1,49 @@
1extends "res://scripts/nodes/listeners/teleportListener.gd"
2
3var item_id
4var item_amount
5
6
7func _ready():
8 var node_path = String(
9 get_tree().get_root().get_node("scene").get_path_to(self).get_concatenated_names()
10 )
11
12 if (
13 global.map == "daedalus"
14 and (
15 node_path == "Components/Triggers/teleportListenerConnections"
16 or node_path == "Components/Triggers/teleportListenerConnections2"
17 )
18 ):
19 # Effectively disable these.
20 teleport_point = target_path.position
21 return
22
23 var gamedata = global.get_node("Gamedata")
24 var door_id = gamedata.get_door_for_map_node_path(global.map, node_path)
25 if door_id != null:
26 var ap = global.get_node("Archipelago")
27 var item_lock = ap.get_item_id_for_door(door_id)
28
29 if item_lock != null:
30 item_id = item_lock[0]
31 item_amount = item_lock[1]
32
33 self.senders = []
34 self.senderGroup = []
35 self.nested = false
36 self.complete_at = 0
37 self.max_length = 0
38 self.excludeSenders = []
39
40 call_deferred("_readier")
41
42 super._ready()
43
44
45func _readier():
46 var ap = global.get_node("Archipelago")
47
48 if ap.client.getItemAmount(item_id) >= item_amount:
49 handleTriggered()
diff --git a/apworld/client/textclient.gd b/apworld/client/textclient.gd new file mode 100644 index 0000000..530eddb --- /dev/null +++ b/apworld/client/textclient.gd
@@ -0,0 +1,310 @@
1extends CanvasLayer
2
3var tabs
4var panel
5var label
6var entry
7var tracker_label
8var is_open = false
9
10var locations_overlay
11var location_texture
12var worldport_texture
13var goal_texture
14
15var worldports_tab
16var worldports_tree
17var port_tree_item_by_map = {}
18var port_tree_item_by_map_port = {}
19
20
21func _ready():
22 process_mode = ProcessMode.PROCESS_MODE_ALWAYS
23 layer = 2
24
25 locations_overlay = RichTextLabel.new()
26 locations_overlay.name = "LocationsOverlay"
27 locations_overlay.offset_top = 220
28 locations_overlay.offset_bottom = 720
29 locations_overlay.offset_left = 20
30 locations_overlay.anchor_right = 1.0
31 locations_overlay.offset_right = -10
32 locations_overlay.scroll_active = false
33 locations_overlay.mouse_filter = Control.MOUSE_FILTER_IGNORE
34 locations_overlay.texture_filter = CanvasItem.TEXTURE_FILTER_NEAREST
35 add_child(locations_overlay)
36 update_locations_visibility()
37
38 tabs = TabContainer.new()
39 tabs.name = "Tabs"
40 tabs.offset_left = 100
41 tabs.offset_right = 1820
42 tabs.offset_top = 100
43 tabs.offset_bottom = 980
44 tabs.visible = false
45 tabs.theme = preload("res://assets/themes/baseUI.tres")
46 tabs.add_theme_font_size_override("font_size", 36)
47 add_child(tabs)
48
49 panel = MarginContainer.new()
50 panel.name = "Text Client"
51 panel.add_theme_constant_override("margin_top", 60)
52 panel.add_theme_constant_override("margin_left", 60)
53 panel.add_theme_constant_override("margin_right", 60)
54 panel.add_theme_constant_override("margin_bottom", 60)
55 tabs.add_child(panel)
56
57 label = RichTextLabel.new()
58 label.set_name("Label")
59 label.scroll_following = true
60 label.selection_enabled = true
61 label.size_flags_horizontal = Control.SIZE_EXPAND_FILL
62 label.size_flags_vertical = Control.SIZE_EXPAND_FILL
63 label.push_font(preload("res://assets/fonts/Lingo2.ttf"))
64 label.push_font_size(36)
65
66 var entry_style = StyleBoxFlat.new()
67 entry_style.bg_color = Color(0.9, 0.9, 0.9, 1)
68
69 entry = LineEdit.new()
70 entry.set_name("Entry")
71 entry.add_theme_font_override("font", preload("res://assets/fonts/Lingo2.ttf"))
72 entry.add_theme_font_size_override("font_size", 36)
73 entry.add_theme_color_override("font_color", Color(0, 0, 0, 1))
74 entry.add_theme_color_override("cursor_color", Color(0, 0, 0, 1))
75 entry.add_theme_stylebox_override("focus", entry_style)
76 entry.text_submitted.connect(text_entered)
77
78 var tc_arranger = VBoxContainer.new()
79 tc_arranger.add_child(label)
80 tc_arranger.add_child(entry)
81 tc_arranger.add_theme_constant_override("separation", 40)
82 panel.add_child(tc_arranger)
83
84 var tracker_margins = MarginContainer.new()
85 tracker_margins.name = "Locations"
86 tracker_margins.add_theme_constant_override("margin_top", 60)
87 tracker_margins.add_theme_constant_override("margin_left", 60)
88 tracker_margins.add_theme_constant_override("margin_right", 60)
89 tracker_margins.add_theme_constant_override("margin_bottom", 60)
90 tabs.add_child(tracker_margins)
91
92 tracker_label = RichTextLabel.new()
93 tracker_margins.add_child(tracker_label)
94
95 worldports_tab = MarginContainer.new()
96 worldports_tab.name = "Worldports"
97 worldports_tab.add_theme_constant_override("margin_top", 60)
98 worldports_tab.add_theme_constant_override("margin_left", 60)
99 worldports_tab.add_theme_constant_override("margin_right", 60)
100 worldports_tab.add_theme_constant_override("margin_bottom", 60)
101 tabs.add_child(worldports_tab)
102 tabs.set_tab_hidden(2, true)
103
104 worldports_tree = Tree.new()
105 worldports_tree.columns = 2
106 worldports_tree.hide_root = true
107 worldports_tree.theme = preload("res://assets/themes/baseUI.tres")
108 worldports_tree.add_theme_font_size_override("font_size", 24)
109 worldports_tab.add_child(worldports_tree)
110
111 var runtime = global.get_node("Runtime")
112 var location_image = Image.new()
113 location_image.load_png_from_buffer(runtime.read_path("assets/location.png"))
114 location_texture = ImageTexture.create_from_image(location_image)
115
116 var worldport_image = Image.new()
117 worldport_image.load_png_from_buffer(runtime.read_path("assets/worldport.png"))
118 worldport_texture = ImageTexture.create_from_image(worldport_image)
119
120 var goal_image = Image.new()
121 goal_image.load_png_from_buffer(runtime.read_path("assets/goal.png"))
122 goal_texture = ImageTexture.create_from_image(goal_image)
123
124
125func _input(event):
126 if global.loaded and event is InputEventKey and event.pressed:
127 if event.keycode == KEY_TAB and !Input.is_key_pressed(KEY_SHIFT):
128 if !get_tree().paused:
129 is_open = true
130 get_tree().paused = true
131 Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE)
132 tabs.visible = true
133 entry.grab_focus()
134 get_viewport().set_input_as_handled()
135 else:
136 dismiss()
137 elif event.keycode == KEY_ESCAPE:
138 if is_open:
139 dismiss()
140 get_viewport().set_input_as_handled()
141
142
143func dismiss():
144 if is_open:
145 get_tree().paused = false
146 Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
147 tabs.visible = false
148 is_open = false
149
150
151func parse_printjson(text):
152 label.append_text("[p]" + text + "[/p]")
153
154
155func text_entered(text):
156 var ap = global.get_node("Archipelago")
157 var cmd = text.trim_suffix("\n")
158 entry.text = ""
159 if OS.is_debug_build():
160 if cmd.begins_with("/tp_map "):
161 var new_map = cmd.substr(8)
162 global.map = new_map
163 global.sets_entry_point = false
164 switcher.switch_map("res://objects/scenes/%s.tscn" % new_map)
165 return
166
167 ap.client.say(cmd)
168
169
170func update_locations():
171 var ap = global.get_node("Archipelago")
172 var gamedata = global.get_node("Gamedata")
173
174 tracker_label.clear()
175 tracker_label.push_font(preload("res://assets/fonts/Lingo2.ttf"))
176 tracker_label.push_font_size(24)
177
178 locations_overlay.clear()
179 locations_overlay.push_font(preload("res://assets/fonts/Lingo2.ttf"))
180 locations_overlay.push_font_size(24)
181 locations_overlay.push_color(Color(0.9, 0.9, 0.9, 1))
182 locations_overlay.push_outline_color(Color(0, 0, 0, 1))
183 locations_overlay.push_outline_size(2)
184
185 const kLocation = 0
186 const kWorldport = 1
187 const kGoal = 2
188
189 var location_names = []
190 var type_by_name = {}
191 for location_id in ap.client._accessible_locations:
192 if not ap.client._checked_locations.has(location_id):
193 var location_name = gamedata.location_name_by_id.get(location_id, "(Unknown)")
194 location_names.append(location_name)
195 type_by_name[location_name] = kLocation
196
197 for port_id in ap.client._accessible_worldports:
198 if not ap.client._checked_worldports.has(port_id):
199 var port_name = gamedata.get_worldport_display_name(port_id)
200 location_names.append(port_name)
201 type_by_name[port_name] = kWorldport
202
203 location_names.sort()
204
205 if ap.client._goal_accessible:
206 var location_name = gamedata.ending_display_name_by_name[ap.kEndingNameByVictoryValue[
207 ap.victory_condition
208 ]]
209 location_names.push_front(location_name)
210 type_by_name[location_name] = kGoal
211
212 var count = 0
213 for location_name in location_names:
214 tracker_label.append_text("[p]%s[/p]" % location_name)
215 if count < 18:
216 locations_overlay.push_paragraph(HORIZONTAL_ALIGNMENT_RIGHT)
217 locations_overlay.append_text(location_name)
218 locations_overlay.append_text(" ")
219 if type_by_name[location_name] == kLocation:
220 locations_overlay.add_image(location_texture)
221 elif type_by_name[location_name] == kWorldport:
222 locations_overlay.add_image(worldport_texture)
223 elif type_by_name[location_name] == kGoal:
224 locations_overlay.add_image(goal_texture)
225 locations_overlay.pop()
226 count += 1
227
228 if count > 18:
229 locations_overlay.append_text("[p align=right][lb]...[rb][/p]")
230
231
232func update_locations_visibility():
233 var ap = global.get_node("Archipelago")
234 locations_overlay.visible = ap.show_locations
235
236
237func setup_worldports():
238 tabs.set_tab_hidden(2, false)
239
240 var root_ti = worldports_tree.create_item(null)
241
242 var ports_by_map_id = {}
243 var display_names_by_map_id = {}
244 var display_names_by_port_id = {}
245
246 var ap = global.get_node("Archipelago")
247 var gamedata = global.get_node("Gamedata")
248 for fpid in ap.port_pairings:
249 var port = gamedata.objects.get_ports()[fpid]
250 var room = gamedata.objects.get_rooms()[port.get_room_id()]
251
252 if not ports_by_map_id.has(room.get_map_id()):
253 ports_by_map_id[room.get_map_id()] = []
254
255 var map = gamedata.objects.get_maps()[room.get_map_id()]
256 display_names_by_map_id[map.get_id()] = map.get_display_name()
257
258 ports_by_map_id[room.get_map_id()].append(fpid)
259 display_names_by_port_id[fpid] = port.get_display_name()
260
261 var sorted_map_ids = ports_by_map_id.keys().duplicate()
262 sorted_map_ids.sort_custom(
263 func(a, b): return display_names_by_map_id[a] < display_names_by_map_id[b]
264 )
265
266 for map_id in sorted_map_ids:
267 var map_ti = root_ti.create_child()
268 map_ti.set_text(0, display_names_by_map_id[map_id])
269 map_ti.visible = false
270 map_ti.collapsed = true
271 port_tree_item_by_map[map_id] = map_ti
272 port_tree_item_by_map_port[map_id] = {}
273
274 var port_ids = ports_by_map_id[map_id]
275 port_ids.sort_custom(
276 func(a, b): return display_names_by_port_id[a] < display_names_by_port_id[b]
277 )
278
279 for port_id in port_ids:
280 var port_ti = map_ti.create_child()
281 port_ti.set_text(0, display_names_by_port_id[port_id])
282 port_ti.set_text(1, gamedata.get_worldport_display_name(ap.port_pairings[port_id]))
283 port_ti.visible = false
284 port_tree_item_by_map_port[map_id][port_id] = port_ti
285
286 update_worldports()
287
288
289func update_worldports():
290 var ap = global.get_node("Archipelago")
291
292 for map_id in port_tree_item_by_map_port.keys():
293 var map_visible = false
294
295 for port_id in port_tree_item_by_map_port[map_id].keys():
296 var ti = port_tree_item_by_map_port[map_id][port_id]
297 ti.visible = ap.client._checked_worldports.has(port_id)
298
299 if ti.visible:
300 map_visible = true
301
302 port_tree_item_by_map[map_id].visible = map_visible
303
304
305func reset():
306 locations_overlay.clear()
307 tabs.set_tab_hidden(2, true)
308 port_tree_item_by_map.clear()
309 port_tree_item_by_map_port.clear()
310 worldports_tree.clear()
diff --git a/apworld/client/vendor/LICENSE b/apworld/client/vendor/LICENSE new file mode 100644 index 0000000..12763b1 --- /dev/null +++ b/apworld/client/vendor/LICENSE
@@ -0,0 +1,21 @@
1WebSocketServer.gd:
2
3Copyright (c) 2014-present Godot Engine contributors. Copyright (c) 2007-2014
4Juan Linietsky, Ariel Manzur.
5
6Permission is hereby granted, free of charge, to any person obtaining a copy of
7this software and associated documentation files (the "Software"), to deal in
8the Software without restriction, including without limitation the rights to
9use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
10the Software, and to permit persons to whom the Software is furnished to do so,
11subject to the following conditions:
12
13The above copyright notice and this permission notice shall be included in all
14copies or substantial portions of the Software.
15
16THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
18FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
19COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
20IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/apworld/client/vendor/WebSocketServer.gd b/apworld/client/vendor/WebSocketServer.gd new file mode 100644 index 0000000..2cee494 --- /dev/null +++ b/apworld/client/vendor/WebSocketServer.gd
@@ -0,0 +1,173 @@
1class_name WebSocketServer
2extends Node
3
4signal message_received(peer_id: int, message: String)
5signal client_connected(peer_id: int)
6signal client_disconnected(peer_id: int)
7
8@export var handshake_headers := PackedStringArray()
9@export var supported_protocols := PackedStringArray()
10@export var handshake_timout := 3000
11@export var use_tls := false
12@export var tls_cert: X509Certificate
13@export var tls_key: CryptoKey
14@export var refuse_new_connections := false:
15 set(refuse):
16 if refuse:
17 pending_peers.clear()
18
19
20class PendingPeer:
21 var connect_time: int
22 var tcp: StreamPeerTCP
23 var connection: StreamPeer
24 var ws: WebSocketPeer
25
26 func _init(p_tcp: StreamPeerTCP) -> void:
27 tcp = p_tcp
28 connection = p_tcp
29 connect_time = Time.get_ticks_msec()
30
31
32var tcp_server := TCPServer.new()
33var pending_peers: Array[PendingPeer] = []
34var peers: Dictionary
35
36
37func listen(port: int) -> int:
38 assert(not tcp_server.is_listening())
39 return tcp_server.listen(port)
40
41
42func stop() -> void:
43 tcp_server.stop()
44 pending_peers.clear()
45 peers.clear()
46
47
48func send(peer_id: int, message: String) -> int:
49 var type := typeof(message)
50 if peer_id <= 0:
51 # Send to multiple peers, (zero = broadcast, negative = exclude one).
52 for id: int in peers:
53 if id == -peer_id:
54 continue
55 if type == TYPE_STRING:
56 peers[id].send_text(message)
57 else:
58 peers[id].put_packet(message)
59 return OK
60
61 assert(peers.has(peer_id))
62 var socket: WebSocketPeer = peers[peer_id]
63 if type == TYPE_STRING:
64 return socket.send_text(message)
65 return socket.send(var_to_bytes(message))
66
67
68func get_message(peer_id: int) -> Variant:
69 assert(peers.has(peer_id))
70 var socket: WebSocketPeer = peers[peer_id]
71 if socket.get_available_packet_count() < 1:
72 return null
73 var pkt: PackedByteArray = socket.get_packet()
74 if socket.was_string_packet():
75 return pkt.get_string_from_utf8()
76 return bytes_to_var(pkt)
77
78
79func has_message(peer_id: int) -> bool:
80 assert(peers.has(peer_id))
81 return peers[peer_id].get_available_packet_count() > 0
82
83
84func _create_peer() -> WebSocketPeer:
85 var ws := WebSocketPeer.new()
86 ws.supported_protocols = supported_protocols
87 ws.handshake_headers = handshake_headers
88 return ws
89
90
91func poll() -> void:
92 if not tcp_server.is_listening():
93 return
94
95 while not refuse_new_connections and tcp_server.is_connection_available():
96 var conn: StreamPeerTCP = tcp_server.take_connection()
97 assert(conn != null)
98 pending_peers.append(PendingPeer.new(conn))
99
100 var to_remove := []
101
102 for p in pending_peers:
103 if not _connect_pending(p):
104 if p.connect_time + handshake_timout < Time.get_ticks_msec():
105 # Timeout.
106 to_remove.append(p)
107 continue # Still pending.
108
109 to_remove.append(p)
110
111 for r: RefCounted in to_remove:
112 pending_peers.erase(r)
113
114 to_remove.clear()
115
116 for id: int in peers:
117 var p: WebSocketPeer = peers[id]
118 p.poll()
119
120 if p.get_ready_state() != WebSocketPeer.STATE_OPEN:
121 client_disconnected.emit(id)
122 to_remove.append(id)
123 continue
124
125 while p.get_available_packet_count():
126 message_received.emit(id, get_message(id))
127
128 for r: int in to_remove:
129 peers.erase(r)
130 to_remove.clear()
131
132
133func _connect_pending(p: PendingPeer) -> bool:
134 if p.ws != null:
135 # Poll websocket client if doing handshake.
136 p.ws.poll()
137 var state := p.ws.get_ready_state()
138 if state == WebSocketPeer.STATE_OPEN:
139 var id := randi_range(2, 1 << 30)
140 peers[id] = p.ws
141 client_connected.emit(id)
142 return true # Success.
143 elif state != WebSocketPeer.STATE_CONNECTING:
144 return true # Failure.
145 return false # Still connecting.
146 elif p.tcp.get_status() != StreamPeerTCP.STATUS_CONNECTED:
147 return true # TCP disconnected.
148 elif not use_tls:
149 # TCP is ready, create WS peer.
150 p.ws = _create_peer()
151 p.ws.accept_stream(p.tcp)
152 return false # WebSocketPeer connection is pending.
153
154 else:
155 if p.connection == p.tcp:
156 assert(tls_key != null and tls_cert != null)
157 var tls := StreamPeerTLS.new()
158 tls.accept_stream(p.tcp, TLSOptions.server(tls_key, tls_cert))
159 p.connection = tls
160 p.connection.poll()
161 var status: StreamPeerTLS.Status = p.connection.get_status()
162 if status == StreamPeerTLS.STATUS_CONNECTED:
163 p.ws = _create_peer()
164 p.ws.accept_stream(p.connection)
165 return false # WebSocketPeer connection is pending.
166 if status != StreamPeerTLS.STATUS_HANDSHAKING:
167 return true # Failure.
168
169 return false
170
171
172func _process(_delta: float) -> void:
173 poll()
diff --git a/apworld/client/victoryListener.gd b/apworld/client/victoryListener.gd new file mode 100644 index 0000000..e9089d7 --- /dev/null +++ b/apworld/client/victoryListener.gd
@@ -0,0 +1,20 @@
1extends Receiver
2
3
4func _ready():
5 super._ready()
6
7
8func handleTriggered():
9 triggered += 1
10 if triggered >= total:
11 var ap = global.get_node("Archipelago")
12 ap.client.completedGoal()
13
14 global.get_node("Messages").showMessage("You have completed your goal!")
15
16
17func handleUntriggered():
18 triggered -= 1
19 if triggered < total:
20 pass
diff --git a/apworld/client/visibilityListener.gd b/apworld/client/visibilityListener.gd new file mode 100644 index 0000000..5ea17a0 --- /dev/null +++ b/apworld/client/visibilityListener.gd
@@ -0,0 +1,38 @@
1extends "res://scripts/nodes/listeners/visibilityListener.gd"
2
3var item_id
4var item_amount
5
6
7func _ready():
8 var node_path = String(
9 get_tree().get_root().get_node("scene").get_path_to(self).get_concatenated_names()
10 )
11
12 var gamedata = global.get_node("Gamedata")
13 var door_id = gamedata.get_door_for_map_node_path(global.map, node_path)
14 if door_id != null:
15 var ap = global.get_node("Archipelago")
16 var item_lock = ap.get_item_id_for_door(door_id)
17
18 if item_lock != null:
19 item_id = item_lock[0]
20 item_amount = item_lock[1]
21
22 self.senders = []
23 self.senderGroup = []
24 self.nested = false
25 self.complete_at = 0
26 self.max_length = 0
27 self.excludeSenders = []
28
29 call_deferred("_readier")
30
31 super._ready()
32
33
34func _readier():
35 var ap = global.get_node("Archipelago")
36
37 if ap.client.getItemAmount(item_id) >= item_amount:
38 handleTriggered()
diff --git a/apworld/client/worldport.gd b/apworld/client/worldport.gd new file mode 100644 index 0000000..ed9891e --- /dev/null +++ b/apworld/client/worldport.gd
@@ -0,0 +1,61 @@
1extends "res://scripts/nodes/worldport.gd"
2
3var absolute_rotation = false
4var target_rotation = 0
5
6var port_id = null
7
8
9func _ready():
10 var node_path = String(
11 get_tree().get_root().get_node("scene").get_path_to(self).get_concatenated_names()
12 )
13
14 var ap = global.get_node("Archipelago")
15
16 if ap.shuffle_worldports:
17 var gamedata = global.get_node("Gamedata")
18 port_id = gamedata.get_port_for_map_node_path(global.map, node_path)
19 if port_id != null:
20 if port_id in ap.port_pairings:
21 var target_port = gamedata.objects.get_ports()[ap.port_pairings[port_id]]
22 var target_room = gamedata.objects.get_rooms()[target_port.get_room_id()]
23 var target_map = gamedata.objects.get_maps()[target_room.get_map_id()]
24
25 exit = target_map.get_name()
26 entry_point.x = target_port.get_destination().get_x()
27 entry_point.y = target_port.get_destination().get_y()
28 entry_point.z = target_port.get_destination().get_z()
29 absolute_rotation = true
30 target_rotation = target_port.get_rotation()
31 sets_entry_point = true
32 invisible = false
33 fades = true
34 else:
35 port_id = null
36
37 if global.map == "icarus" and exit == "daedalus":
38 if not ap.daedalus_roof_access:
39 entry_point = Vector3(58, 10, 0)
40
41 super._ready()
42
43
44func bodyEntered(body):
45 if body.is_in_group("player"):
46 if port_id != null:
47 var ap = global.get_node("Archipelago")
48 ap.client.checkWorldport(port_id)
49
50 if absolute_rotation:
51 entry_rotate.y = target_rotation - body.rotation_degrees.y
52
53 super.bodyEntered(body)
54
55
56func changeScene():
57 var player = get_tree().get_root().get_node("scene/player")
58 if player != null:
59 player.playable = false
60
61 super.changeScene()
diff --git a/apworld/client/worldportListener.gd b/apworld/client/worldportListener.gd new file mode 100644 index 0000000..5c2faff --- /dev/null +++ b/apworld/client/worldportListener.gd
@@ -0,0 +1,8 @@
1extends "res://scripts/nodes/listeners/worldportListener.gd"
2
3
4func handleTriggered():
5 if exit == "menus/credits":
6 return
7
8 super.handleTriggered()
diff --git a/apworld/context.py b/apworld/context.py new file mode 100644 index 0000000..63645a4 --- /dev/null +++ b/apworld/context.py
@@ -0,0 +1,630 @@
1import asyncio
2import os
3import pkgutil
4import subprocess
5import sys
6from typing import Any
7
8import websockets
9
10import Utils
11import settings
12from BaseClasses import ItemClassification
13from CommonClient import CommonContext, server_loop, gui_enabled, logger, get_base_parser, handle_url_arg
14from NetUtils import Endpoint, decode, encode, ClientStatus
15from Utils import async_start
16from . import Lingo2World
17from .tracker import Tracker
18
19ALL_LETTERS = "abcdefghijklmnopqrstuvwxyz"
20MESSAGE_MAX_SIZE = 16*1024*1024
21PORT = 43182
22
23KEY_STORAGE_MAPPING = {
24 "a": (1, 0), "b": (1, 1), "c": (1, 2), "d": (1, 3), "e": (1, 4), "f": (1, 5), "g": (1, 6), "h": (1, 7), "i": (1, 8),
25 "j": (1, 9), "k": (1, 10), "l": (1, 11), "m": (1, 12), "n": (2, 0), "o": (2, 1), "p": (2, 2), "q": (2, 3),
26 "r": (2, 4), "s": (2, 5), "t": (2, 6), "u": (2, 7), "v": (2, 8), "w": (2, 9), "x": (2, 10), "y": (2, 11),
27 "z": (2, 12),
28}
29
30REVERSE_KEY_STORAGE_MAPPING = {t: k for k, t in KEY_STORAGE_MAPPING.items()}
31
32
33class Lingo2Manager:
34 game_ctx: "Lingo2GameContext"
35 client_ctx: "Lingo2ClientContext"
36 tracker: Tracker
37
38 keyboard: dict[str, int]
39 worldports: set[int]
40 goaled: bool
41
42 def __init__(self, game_ctx: "Lingo2GameContext", client_ctx: "Lingo2ClientContext"):
43 self.game_ctx = game_ctx
44 self.game_ctx.manager = self
45 self.client_ctx = client_ctx
46 self.client_ctx.manager = self
47 self.tracker = Tracker(self)
48 self.keyboard = {}
49 self.worldports = set()
50
51 self.reset()
52
53 def reset(self):
54 for k in ALL_LETTERS:
55 self.keyboard[k] = 0
56
57 self.worldports = set()
58 self.goaled = False
59
60 def update_keyboard(self, new_keyboard: dict[str, int]) -> dict[str, int]:
61 ret: dict[str, int] = {}
62
63 for k, v in new_keyboard.items():
64 if v > self.keyboard.get(k, 0):
65 self.keyboard[k] = v
66 ret[k] = v
67
68 if len(ret) > 0:
69 self.tracker.refresh_state()
70 self.game_ctx.send_accessible_locations()
71
72 return ret
73
74 def update_worldports(self, new_worldports: set[int]) -> set[int]:
75 ret = new_worldports.difference(self.worldports)
76 self.worldports.update(new_worldports)
77
78 if len(ret) > 0:
79 self.tracker.refresh_state()
80 self.game_ctx.send_accessible_locations()
81
82 return ret
83
84
85class Lingo2GameContext:
86 server: Endpoint | None
87 manager: Lingo2Manager
88
89 def __init__(self):
90 self.server = None
91
92 def send_connected(self):
93 if self.server is None:
94 return
95
96 msg = {
97 "cmd": "Connected",
98 "user": self.manager.client_ctx.username,
99 "seed_name": self.manager.client_ctx.seed_name,
100 "version": self.manager.client_ctx.server_version,
101 "generator_version": self.manager.client_ctx.generator_version,
102 "team": self.manager.client_ctx.team,
103 "slot": self.manager.client_ctx.slot,
104 "checked_locations": self.manager.client_ctx.checked_locations,
105 "slot_data": self.manager.client_ctx.slot_data,
106 }
107
108 async_start(self.send_msgs([msg]), name="game Connected")
109
110 def send_connection_refused(self, text):
111 if self.server is None:
112 return
113
114 msg = {
115 "cmd": "ConnectionRefused",
116 "text": text,
117 }
118
119 async_start(self.send_msgs([msg]), name="game ConnectionRefused")
120
121 def send_item_sent_notification(self, item_name, receiver_name, item_flags):
122 if self.server is None:
123 return
124
125 msg = {
126 "cmd": "ItemSentNotif",
127 "item_name": item_name,
128 "receiver_name": receiver_name,
129 "item_flags": item_flags,
130 }
131
132 async_start(self.send_msgs([msg]), name="item sent notif")
133
134 def send_hint_received(self, item_name, location_name, receiver_name, item_flags, for_self):
135 if self.server is None:
136 return
137
138 msg = {
139 "cmd": "HintReceived",
140 "item_name": item_name,
141 "location_name": location_name,
142 "receiver_name": receiver_name,
143 "item_flags": item_flags,
144 "self": int(for_self),
145 }
146
147 async_start(self.send_msgs([msg]), name="hint received notif")
148
149 def send_item_received(self, items):
150 if self.server is None:
151 return
152
153 msg = {
154 "cmd": "ItemReceived",
155 "items": items,
156 }
157
158 async_start(self.send_msgs([msg]), name="item received")
159
160 def send_location_info(self, locations):
161 if self.server is None:
162 return
163
164 msg = {
165 "cmd": "LocationInfo",
166 "locations": locations,
167 }
168
169 async_start(self.send_msgs([msg]), name="location info")
170
171 def send_text_message(self, parts):
172 if self.server is None:
173 return
174
175 msg = {
176 "cmd": "TextMessage",
177 "data": parts,
178 }
179
180 async_start(self.send_msgs([msg]), name="notif")
181
182 def send_accessible_locations(self):
183 if self.server is None:
184 return
185
186 msg = {
187 "cmd": "AccessibleLocations",
188 "locations": list(self.manager.tracker.accessible_locations),
189 }
190
191 if len(self.manager.tracker.accessible_worldports) > 0:
192 msg["worldports"] = list(self.manager.tracker.accessible_worldports)
193
194 if self.manager.tracker.goal_accessible and not self.manager.goaled:
195 msg["goal"] = True
196
197 async_start(self.send_msgs([msg]), name="accessible locations")
198
199 def send_update_locations(self, locations):
200 if self.server is None:
201 return
202
203 msg = {
204 "cmd": "UpdateLocations",
205 "locations": locations,
206 }
207
208 async_start(self.send_msgs([msg]), name="update locations")
209
210 def send_update_keyboard(self, updates):
211 if self.server is None:
212 return
213
214 msg = {
215 "cmd": "UpdateKeyboard",
216 "updates": updates,
217 }
218
219 async_start(self.send_msgs([msg]), name="update keyboard")
220
221 def send_update_worldports(self, worldports):
222 if self.server is None:
223 return
224
225 msg = {
226 "cmd": "UpdateWorldports",
227 "worldports": worldports,
228 }
229
230 async_start(self.send_msgs([msg]), name="update worldports")
231
232 async def send_msgs(self, msgs: list[Any]) -> None:
233 """ `msgs` JSON serializable """
234 if not self.server or not self.server.socket.open or self.server.socket.closed:
235 return
236 await self.server.socket.send(encode(msgs))
237
238
239class Lingo2ClientContext(CommonContext):
240 manager: Lingo2Manager
241
242 game = "Lingo 2"
243 items_handling = 0b111
244
245 slot_data: dict[str, Any] | None
246 victory_data_storage_key: str
247
248 def __init__(self, server_address: str | None = None, password: str | None = None):
249 super().__init__(server_address, password)
250
251 def make_gui(self):
252 ui = super().make_gui()
253 ui.base_title = "Archipelago Lingo 2 Client"
254 return ui
255
256 async def server_auth(self, password_requested: bool = False):
257 if password_requested:
258 if self.password is None:
259 self.manager.game_ctx.send_connection_refused("Slot requires a password.")
260 else:
261 self.manager.game_ctx.send_connection_refused("Invalid password.")
262 else:
263 self.auth = self.username
264 await self.send_connect()
265
266 def handle_connection_loss(self, msg: str):
267 super().handle_connection_loss(msg)
268
269 exc_info = sys.exc_info()
270 self.manager.game_ctx.send_connection_refused(str(exc_info[1]))
271
272 def on_package(self, cmd: str, args: dict):
273 if cmd == "RoomInfo":
274 self.seed_name = args.get("seed_name", None)
275 elif cmd == "Connected":
276 self.slot_data = args.get("slot_data", None)
277
278 self.manager.reset()
279
280 self.manager.game_ctx.send_connected()
281
282 self.manager.tracker.setup_slot(self.slot_data)
283 self.manager.tracker.set_checked_locations(self.checked_locations)
284 self.manager.game_ctx.send_accessible_locations()
285
286 self.victory_data_storage_key = f"_read_client_status_{self.team}_{self.slot}"
287
288 self.set_notify(self.get_datastorage_key("keyboard1"), self.get_datastorage_key("keyboard2"),
289 self.victory_data_storage_key)
290 msg_batch = [{
291 "cmd": "Set",
292 "key": self.get_datastorage_key("keyboard1"),
293 "default": 0,
294 "want_reply": True,
295 "operations": [{"operation": "default", "value": 0}]
296 }, {
297 "cmd": "Set",
298 "key": self.get_datastorage_key("keyboard2"),
299 "default": 0,
300 "want_reply": True,
301 "operations": [{"operation": "default", "value": 0}]
302 }]
303
304 if self.slot_data.get("shuffle_worldports", False):
305 self.set_notify(self.get_datastorage_key("worldports"))
306 msg_batch.append({
307 "cmd": "Set",
308 "key": self.get_datastorage_key("worldports"),
309 "default": [],
310 "want_reply": True,
311 "operations": [{"operation": "default", "value": []}]
312 })
313
314 async_start(self.send_msgs(msg_batch), name="default keys")
315 elif cmd == "RoomUpdate":
316 if "checked_locations" in args:
317 self.manager.tracker.set_checked_locations(self.checked_locations)
318 self.manager.game_ctx.send_update_locations(args["checked_locations"])
319 elif cmd == "ReceivedItems":
320 self.manager.tracker.set_collected_items(self.items_received)
321
322 cur_index = 0
323 items = []
324
325 for item in args["items"]:
326 index = cur_index + args["index"]
327 cur_index += 1
328
329 item_msg = {
330 "id": item.item,
331 "index": index,
332 "flags": item.flags,
333 "text": self.item_names.lookup_in_slot(item.item, self.slot),
334 }
335
336 if item.player != self.slot:
337 item_msg["sender"] = self.player_names.get(item.player)
338
339 items.append(item_msg)
340
341 self.manager.game_ctx.send_item_received(items)
342
343 if any(ItemClassification.progression in ItemClassification(item.flags) for item in args["items"]):
344 self.manager.game_ctx.send_accessible_locations()
345 elif cmd == "PrintJSON":
346 if "receiving" in args and "item" in args and args["item"].player == self.slot:
347 item_name = self.item_names.lookup_in_slot(args["item"].item, args["receiving"])
348 location_name = self.location_names.lookup_in_slot(args["item"].location, args["item"].player)
349 receiver_name = self.player_names.get(args["receiving"])
350
351 if args["type"] == "Hint" and not args.get("found", False):
352 self.manager.game_ctx.send_hint_received(item_name, location_name, receiver_name, args["item"].flags,
353 int(args["receiving"]) == self.slot)
354 elif args["receiving"] != self.slot:
355 self.manager.game_ctx.send_item_sent_notification(item_name, receiver_name, args["item"].flags)
356
357 parts = []
358 for message_part in args["data"]:
359 if "type" not in message_part and "text" in message_part:
360 parts.append({"type": "text", "text": message_part["text"]})
361 elif message_part["type"] == "player_id":
362 parts.append({
363 "type": "player",
364 "text": self.player_names.get(int(message_part["text"])),
365 "self": int(int(message_part["text"]) == self.slot),
366 })
367 elif message_part["type"] == "item_id":
368 parts.append({
369 "type": "item",
370 "text": self.item_names.lookup_in_slot(int(message_part["text"]), message_part["player"]),
371 "flags": message_part["flags"],
372 })
373 elif message_part["type"] == "location_id":
374 parts.append({
375 "type": "location",
376 "text": self.location_names.lookup_in_slot(int(message_part["text"]),
377 message_part["player"])
378 })
379 elif "text" in message_part:
380 parts.append({"type": "text", "text": message_part["text"]})
381
382 self.manager.game_ctx.send_text_message(parts)
383 elif cmd == "LocationInfo":
384 locations = []
385
386 for location in args["locations"]:
387 locations.append({
388 "id": location.location,
389 "item": self.item_names.lookup_in_slot(location.item, location.player),
390 "player": self.player_names.get(location.player),
391 "flags": location.flags,
392 "self": int(location.player) == self.slot,
393 })
394
395 self.manager.game_ctx.send_location_info(locations)
396 elif cmd == "Retrieved":
397 for k, v in args["keys"].items():
398 if k == self.victory_data_storage_key:
399 self.handle_status_update(v)
400 elif cmd == "SetReply":
401 if args["key"] == self.get_datastorage_key("keyboard1"):
402 self.handle_keyboard_update(1, args)
403 elif args["key"] == self.get_datastorage_key("keyboard2"):
404 self.handle_keyboard_update(2, args)
405 elif args["key"] == self.get_datastorage_key("worldports"):
406 updates = self.manager.update_worldports(set(args["value"]))
407 if len(updates) > 0:
408 self.manager.game_ctx.send_update_worldports(updates)
409 elif args["key"] == self.victory_data_storage_key:
410 self.handle_status_update(args["value"])
411
412 def get_datastorage_key(self, name: str):
413 return f"Lingo2_{self.slot}_{name}"
414
415 async def update_keyboard(self, updates: dict[str, int]):
416 kb1 = 0
417 kb2 = 0
418
419 for k, v in updates.items():
420 if v == 0:
421 continue
422
423 effect = 0
424 if v >= 1:
425 effect |= 1
426 if v == 2:
427 effect |= 2
428
429 pos = KEY_STORAGE_MAPPING[k]
430 if pos[0] == 1:
431 kb1 |= (effect << pos[1] * 2)
432 else:
433 kb2 |= (effect << pos[1] * 2)
434
435 msgs = []
436
437 if kb1 != 0:
438 msgs.append({
439 "cmd": "Set",
440 "key": self.get_datastorage_key("keyboard1"),
441 "want_reply": True,
442 "operations": [{
443 "operation": "or",
444 "value": kb1
445 }]
446 })
447
448 if kb2 != 0:
449 msgs.append({
450 "cmd": "Set",
451 "key": self.get_datastorage_key("keyboard2"),
452 "want_reply": True,
453 "operations": [{
454 "operation": "or",
455 "value": kb2
456 }]
457 })
458
459 if len(msgs) > 0:
460 await self.send_msgs(msgs)
461
462 def handle_keyboard_update(self, field: int, args: dict[str, Any]):
463 keys = {}
464 value = args["value"]
465
466 for i in range(0, 13):
467 if (value & (1 << (i * 2))) != 0:
468 keys[REVERSE_KEY_STORAGE_MAPPING[(field, i)]] = 1
469 if (value & (1 << (i * 2 + 1))) != 0:
470 keys[REVERSE_KEY_STORAGE_MAPPING[(field, i)]] = 2
471
472 updates = self.manager.update_keyboard(keys)
473 if len(updates) > 0:
474 self.manager.game_ctx.send_update_keyboard(updates)
475
476 async def update_worldports(self, updates: set[int]):
477 await self.send_msgs([{
478 "cmd": "Set",
479 "key": self.get_datastorage_key("worldports"),
480 "want_reply": True,
481 "operations": [{
482 "operation": "update",
483 "value": updates
484 }]
485 }])
486
487 def handle_status_update(self, value: int):
488 self.manager.goaled = (value == ClientStatus.CLIENT_GOAL)
489 self.manager.tracker.refresh_state()
490 self.manager.game_ctx.send_accessible_locations()
491
492
493async def pipe_loop(manager: Lingo2Manager):
494 while not manager.client_ctx.exit_event.is_set():
495 try:
496 socket = await websockets.connect("ws://localhost", port=PORT, ping_timeout=None, ping_interval=None,
497 max_size=MESSAGE_MAX_SIZE)
498 manager.game_ctx.server = Endpoint(socket)
499 logger.info("Connected to Lingo 2!")
500 if manager.client_ctx.auth is not None:
501 manager.game_ctx.send_connected()
502 manager.game_ctx.send_accessible_locations()
503 async for data in manager.game_ctx.server.socket:
504 for msg in decode(data):
505 await process_game_cmd(manager, msg)
506 except ConnectionRefusedError:
507 logger.info("Could not connect to Lingo 2.")
508 finally:
509 manager.game_ctx.server = None
510
511
512async def process_game_cmd(manager: Lingo2Manager, args: dict):
513 cmd = args["cmd"]
514
515 if cmd == "Connect":
516 manager.client_ctx.seed_name = None
517
518 server = args.get("server")
519 player = args.get("player")
520 password = args.get("password")
521
522 if password != "":
523 server_address = f"{player}:{password}@{server}"
524 else:
525 server_address = f"{player}:None@{server}"
526
527 async_start(manager.client_ctx.connect(server_address), name="client connect")
528 elif cmd == "Disconnect":
529 manager.client_ctx.seed_name = None
530
531 async_start(manager.client_ctx.disconnect(), name="client disconnect")
532 elif cmd in ["Sync", "LocationChecks", "Say", "StatusUpdate", "LocationScouts"]:
533 async_start(manager.client_ctx.send_msgs([args]), name="client forward")
534 elif cmd == "UpdateKeyboard":
535 updates = manager.update_keyboard(args["keyboard"])
536 if len(updates) > 0:
537 async_start(manager.client_ctx.update_keyboard(updates), name="client update keyboard")
538 elif cmd == "CheckWorldport":
539 port_id = args["port_id"]
540 worldports = {port_id}
541 if str(port_id) in manager.client_ctx.slot_data["port_pairings"]:
542 worldports.add(manager.client_ctx.slot_data["port_pairings"][str(port_id)])
543
544 updates = manager.update_worldports(worldports)
545 if len(updates) > 0:
546 async_start(manager.client_ctx.update_worldports(updates), name="client update worldports")
547 manager.game_ctx.send_update_worldports(updates)
548 elif cmd == "Quit":
549 manager.client_ctx.exit_event.set()
550
551
552async def run_game():
553 exe_file = settings.get_settings().lingo2_options.exe_file
554
555 # This ensures we can use Steam features without having to open the game
556 # through steam.
557 steam_appid_path = os.path.join(os.path.dirname(exe_file), "steam_appid.txt")
558 with open(steam_appid_path, "w") as said_handle:
559 said_handle.write("2523310")
560
561 if Lingo2World.zip_path is not None:
562 # This is a packaged apworld.
563 init_scene = pkgutil.get_data(__name__, "client/run_from_apworld.tscn")
564 init_path = Utils.local_path("data", "lingo2_init.tscn")
565
566 with open(init_path, "wb") as file_handle:
567 file_handle.write(init_scene)
568
569 subprocess.Popen(
570 [
571 exe_file,
572 "--scene",
573 init_path,
574 "--",
575 str(Lingo2World.zip_path.absolute()),
576 ],
577 cwd=os.path.dirname(exe_file),
578 )
579 else:
580 # The world is unzipped and being run in source.
581 subprocess.Popen(
582 [
583 exe_file,
584 "--scene",
585 Utils.local_path("worlds", "lingo2", "client", "run_from_source.tscn"),
586 "--",
587 Utils.local_path("worlds", "lingo2", "client"),
588 ],
589 cwd=os.path.dirname(exe_file),
590 )
591
592
593def client_main(*launch_args: str) -> None:
594 async def main(args):
595 async_start(run_game())
596
597 client_ctx = Lingo2ClientContext(args.connect, args.password)
598 game_ctx = Lingo2GameContext()
599 manager = Lingo2Manager(game_ctx, client_ctx)
600
601 client_ctx.server_task = asyncio.create_task(server_loop(client_ctx), name="ServerLoop")
602
603 if gui_enabled:
604 client_ctx.run_gui()
605 client_ctx.run_cli()
606
607 pipe_task = asyncio.create_task(pipe_loop(manager), name="GameWatcher")
608
609 try:
610 await pipe_task
611 except Exception as e:
612 logger.exception(e)
613
614 await client_ctx.exit_event.wait()
615 client_ctx.ui.stop()
616 await client_ctx.shutdown()
617
618 Utils.init_logging("Lingo2Client", exception_logger="Client")
619 import colorama
620
621 parser = get_base_parser(description="Lingo 2 Archipelago Client")
622 parser.add_argument('--name', default=None, help="Slot Name to connect as.")
623 parser.add_argument("url", nargs="?", help="Archipelago connection url")
624 args = parser.parse_args(launch_args)
625
626 args = handle_url_arg(args, parser=parser)
627
628 colorama.just_fix_windows_console()
629 asyncio.run(main(args))
630 colorama.deinit()
diff --git a/apworld/docs/en_Lingo_2.md b/apworld/docs/en_Lingo_2.md new file mode 100644 index 0000000..977795a --- /dev/null +++ b/apworld/docs/en_Lingo_2.md
@@ -0,0 +1,4 @@
1# Lingo 2
2
3See [the project README](https://code.fourisland.com/lingo2-archipelago/about/)
4for installation instructions and frequently asked questions. \ No newline at end of file
diff --git a/apworld/items.py b/apworld/items.py index 971a709..28158c3 100644 --- a/apworld/items.py +++ b/apworld/items.py
@@ -1,5 +1,31 @@
1from .generated import data_pb2 as data_pb2
1from BaseClasses import Item 2from BaseClasses import Item
2 3
3 4
4class Lingo2Item(Item): 5class Lingo2Item(Item):
5 game: str = "Lingo 2" 6 game: str = "Lingo 2"
7
8
9SYMBOL_ITEMS: dict[data_pb2.PuzzleSymbol, str] = {
10 data_pb2.PuzzleSymbol.SUN: "Sun Symbol",
11 data_pb2.PuzzleSymbol.SPARKLES: "Sparkles Symbol",
12 data_pb2.PuzzleSymbol.ZERO: "Zero Symbol",
13 data_pb2.PuzzleSymbol.EXAMPLE: "Example Symbol",
14 data_pb2.PuzzleSymbol.BOXES: "Boxes Symbol",
15 data_pb2.PuzzleSymbol.PLANET: "Planet Symbol",
16 data_pb2.PuzzleSymbol.PYRAMID: "Pyramid Symbol",
17 data_pb2.PuzzleSymbol.CROSS: "Cross Symbol",
18 data_pb2.PuzzleSymbol.SWEET: "Sweet Symbol",
19 data_pb2.PuzzleSymbol.GENDER: "Gender Symbol",
20 data_pb2.PuzzleSymbol.AGE: "Age Symbol",
21 data_pb2.PuzzleSymbol.SOUND: "Sound Symbol",
22 data_pb2.PuzzleSymbol.ANAGRAM: "Anagram Symbol",
23 data_pb2.PuzzleSymbol.JOB: "Job Symbol",
24 data_pb2.PuzzleSymbol.STARS: "Stars Symbol",
25 data_pb2.PuzzleSymbol.NULL: "Null Symbol",
26 data_pb2.PuzzleSymbol.EVAL: "Eval Symbol",
27 data_pb2.PuzzleSymbol.LINGO: "Lingo Symbol",
28 data_pb2.PuzzleSymbol.QUESTION: "Question Symbol",
29}
30
31ANTI_COLLECTABLE_TRAPS: list[str] = [f"Anti {letter}" for letter in "ABCDEFGHIJKLMNOPQRSTUVWXYZ"]
diff --git a/apworld/locations.py b/apworld/locations.py index 108decb..3d619dc 100644 --- a/apworld/locations.py +++ b/apworld/locations.py
@@ -3,3 +3,6 @@ from BaseClasses import Location
3 3
4class Lingo2Location(Location): 4class Lingo2Location(Location):
5 game: str = "Lingo 2" 5 game: str = "Lingo 2"
6
7 port_id: int
8 goal: bool
diff --git a/apworld/logo.png b/apworld/logo.png new file mode 100644 index 0000000..b9d00ba --- /dev/null +++ b/apworld/logo.png
Binary files differ
diff --git a/apworld/options.py b/apworld/options.py index 77f0ae3..3d7c9a5 100644 --- a/apworld/options.py +++ b/apworld/options.py
@@ -1,13 +1,180 @@
1from dataclasses import dataclass 1from dataclasses import dataclass
2 2
3from Options import PerGameCommonOptions, Toggle 3from Options import PerGameCommonOptions, Toggle, Choice, DefaultOnToggle, Range
4 4
5 5
6class ShuffleDoors(Toggle): 6class ShuffleDoors(DefaultOnToggle):
7 """If enabled, most doors will open from receiving an item rather than fulfilling the in-game requirements.""" 7 """If enabled, most doors will open from receiving an item rather than fulfilling the in-game requirements."""
8 display_name = "Shuffle Doors" 8 display_name = "Shuffle Doors"
9 9
10 10
11class ShuffleControlCenterColors(Toggle):
12 """
13 Some doors open after solving the COLOR panel in the Control Center. If this option is enabled, these doors will
14 instead open upon receiving an item.
15 """
16 display_name = "Shuffle Control Center Colors"
17
18
19class ShuffleGalleryPaintings(Toggle):
20 """If enabled, gallery paintings will appear from receiving an item rather than by triggering them normally."""
21 display_name = "Shuffle Gallery Paintings"
22
23
24class ShuffleLetters(Choice):
25 """
26 Controls how letter unlocks are handled. Note that H1, I1, N1, and T1 will always be present at their vanilla
27 locations in the starting room, even if letters are shuffled remotely.
28
29 - **Vanilla**: All letters will be present at their vanilla locations.
30 - **Unlocked**: Players will start with their keyboards fully unlocked.
31 - **Progressive**: Two items will be added to the pool for every letter (one for H, I, N, and T). Receiving the
32 first item gives you the corresponding level 1 letter, and the second item gives you the corresponding level 2
33 letter.
34 - **Vanilla Cyan**: Players will start with all level 1 (purple) letters unlocked. Level 2 (cyan) letters will be
35 present at their vanilla locations.
36 - **Item Cyan**: Players will start with all level 1 (purple) letters unlocked. One item will be added to the pool
37 for every level 2 (cyan) letter.
38 """
39 display_name = "Shuffle Letters"
40 option_vanilla = 0
41 option_unlocked = 1
42 option_progressive = 2
43 option_vanilla_cyan = 3
44 option_item_cyan = 4
45
46
47class ShuffleSymbols(Toggle):
48 """
49 If enabled, 19 items will be added to the pool, representing the different symbols that can appear on a panel.
50 Players will be prevented from solving puzzles with symbols on them until all of the required symbols are unlocked.
51 """
52 display_name = "Shuffle Symbols"
53
54
55class ShuffleWorldports(Toggle):
56 """
57 Randomizes the connections between maps. This affects worldports only, which are the loading zones you walk into in
58 order to change maps. This does not affect paintings, panels that teleport you, or certain other special connections
59 like the one between The Shop and Control Center. Connections that depend on placing letters in keyholders are also
60 currently not shuffled.
61
62 NOTE: It is highly recommended that you turn on Shuffle Control Center Colors when using Shuffle Worldports. Not
63 doing so runs the risk of creating an unfinishable seed.
64 """
65 display_name = "Shuffle Worldports"
66
67
68class KeyholderSanity(Toggle):
69 """
70 If enabled, 26 locations will be created for placing each key into its respective Green Ending keyholder.
71
72 NOTE: This does not apply to the two disappearing keyholders in The Congruent, as they are not part of Green Ending.
73 """
74 display_name = "Keyholder Sanity"
75
76
77class CyanDoorBehavior(Choice):
78 """
79 Cyan-colored doors usually only open upon unlocking double letters. Some panels also only appear upon unlocking
80 double letters. This option determines how these unlocks should behave.
81
82 - **Collect H2**: In the base game, H2 is the first double letter you are intended to collect, so cyan doors only
83 open when you collect the H2 pickup in The Repetitive. Collecting the actual pickup is still required even with
84 remote letter shuffle enabled.
85 - **Any Double Letter**: Cyan doors will open when you have unlocked any cyan letter on your keyboard. In letter
86 shuffle, this means receiving a cyan letter, not picking up a cyan letter collectable.
87 - **Item**: Cyan doors will be grouped together in a single item.
88
89 Note that some cyan doors are impacted by door shuffle (e.g. the entrance to The Tower). When door shuffle is
90 enabled, these doors won't be affected by the value of this option.
91 """
92 display_name = "Cyan Door Behavior"
93 option_collect_h2 = 0
94 option_any_double_letter = 1
95 option_item = 2
96
97
98class DaedalusRoofAccess(Toggle):
99 """
100 If enabled, the player will be logically expected to be able to go from the castle entrance to any part of Daedalus
101 that is open to the air. If disabled, the player will only be expected to be able to enter the castle, the moat,
102 Icarus, and the area at the bottom of the stairs. Invisible walls that become opaque as you approach them are added
103 to the level to prevent the player from accidentally breaking logic.
104 """
105 display_name = "Allow Daedalus Roof Access"
106
107
108class StrictPurpleEnding(DefaultOnToggle):
109 """
110 If enabled, the player will be required to have all purple (level 1) letters in order to get Purple Ending.
111 Otherwise, some of the letters may be skippable depending on the other options.
112 """
113 display_name = "Strict Purple Ending"
114
115
116class StrictCyanEnding(DefaultOnToggle):
117 """
118 If enabled, the player will be required to have all cyan (level 2) letters in order to get Cyan Ending. Otherwise,
119 at least J2, Q2, and V2 are skippable. Others may also be skippable depending on the options chosen.
120 """
121 display_name = "Strict Cyan Ending"
122
123
124class VictoryCondition(Choice):
125 """
126 This option determines what your goal is.
127
128 - **Gray Ending** (The Colorful)
129 - **Purple Ending** (The Sun Temple). This ordinarily requires all level 1 (purple) letters.
130 - **Mint Ending** (typing EXIT into the keyholders in Control Center)
131 - **Black Ending** (The Graveyard)
132 - **Blue Ending** (The Words)
133 - **Cyan Ending** (The Parthenon). This ordinarily requires almost all level 2 (cyan) letters.
134 - **Red Ending** (The Tower)
135 - **Plum Ending** (The Wondrous / The Door)
136 - **Orange Ending** (the castle in Daedalus)
137 - **Gold Ending** (The Gold). This involves going through the color rooms in Daedalus.
138 - **Yellow Ending** (The Gallery). This requires unlocking all gallery paintings.
139 - **Green Ending** (The Ancient). This requires filling all keyholders with specific letters.
140 - **White Ending** (Control Center). This combines every other ending.
141 """
142 display_name = "Victory Condition"
143 option_gray_ending = 0
144 option_purple_ending = 1
145 option_mint_ending = 2
146 option_black_ending = 3
147 option_blue_ending = 4
148 option_cyan_ending = 5
149 option_red_ending = 6
150 option_plum_ending = 7
151 option_orange_ending = 8
152 option_gold_ending = 9
153 option_yellow_ending = 10
154 option_green_ending = 11
155 option_white_ending = 12
156
157
158class TrapPercentage(Range):
159 """Replaces junk items with traps, at the specified rate."""
160 display_name = "Trap Percentage"
161 range_start = 0
162 range_end = 100
163 default = 0
164
165
11@dataclass 166@dataclass
12class Lingo2Options(PerGameCommonOptions): 167class Lingo2Options(PerGameCommonOptions):
13 shuffle_doors: ShuffleDoors 168 shuffle_doors: ShuffleDoors
169 shuffle_control_center_colors: ShuffleControlCenterColors
170 shuffle_gallery_paintings: ShuffleGalleryPaintings
171 shuffle_letters: ShuffleLetters
172 shuffle_symbols: ShuffleSymbols
173 shuffle_worldports: ShuffleWorldports
174 keyholder_sanity: KeyholderSanity
175 cyan_door_behavior: CyanDoorBehavior
176 daedalus_roof_access: DaedalusRoofAccess
177 strict_purple_ending: StrictPurpleEnding
178 strict_cyan_ending: StrictCyanEnding
179 victory_condition: VictoryCondition
180 trap_percentage: TrapPercentage
diff --git a/apworld/player_logic.py b/apworld/player_logic.py index edf8c4f..5be066d 100644 --- a/apworld/player_logic.py +++ b/apworld/player_logic.py
@@ -1,6 +1,11 @@
1from enum import IntEnum, auto
2
1from .generated import data_pb2 as data_pb2 3from .generated import data_pb2 as data_pb2
4from .items import SYMBOL_ITEMS
2from typing import TYPE_CHECKING, NamedTuple 5from typing import TYPE_CHECKING, NamedTuple
3 6
7from .options import VictoryCondition, ShuffleLetters, CyanDoorBehavior
8
4if TYPE_CHECKING: 9if TYPE_CHECKING:
5 from . import Lingo2World 10 from . import Lingo2World
6 11
@@ -10,60 +15,197 @@ def calculate_letter_histogram(solution: str) -> dict[str, int]:
10 for l in solution: 15 for l in solution:
11 if l.isalpha(): 16 if l.isalpha():
12 real_l = l.upper() 17 real_l = l.upper()
13 histogram[real_l] = min(histogram.get(l, 0) + 1, 2) 18 histogram[real_l] = min(histogram.get(real_l, 0) + 1, 2)
14 19
15 return histogram 20 return histogram
16 21
17 22
18class AccessRequirements: 23class AccessRequirements:
19 items: set[str] 24 items: set[str]
25 progressives: dict[str, int]
20 rooms: set[str] 26 rooms: set[str]
21 symbols: set[str]
22 letters: dict[str, int] 27 letters: dict[str, int]
28 cyans: bool
23 29
24 # This is an AND of ORs. 30 # This is an AND of ORs.
25 or_logic: list[list["AccessRequirements"]] 31 or_logic: list[list["AccessRequirements"]]
26 32
33 # When complete_at is set, at least that many of the requirements in possibilities must be accessible. This should
34 # only be used for doors with complete_at > 1, as or_logic is more efficient for complete_at == 1.
35 complete_at: int | None
36 possibilities: list["AccessRequirements"]
37
27 def __init__(self): 38 def __init__(self):
28 self.items = set() 39 self.items = set()
40 self.progressives = dict()
29 self.rooms = set() 41 self.rooms = set()
30 self.symbols = set()
31 self.letters = dict() 42 self.letters = dict()
43 self.cyans = False
32 self.or_logic = list() 44 self.or_logic = list()
45 self.complete_at = None
46 self.possibilities = list()
33 47
34 def add_solution(self, solution: str): 48 def copy(self) -> "AccessRequirements":
35 histogram = calculate_letter_histogram(solution) 49 reqs = AccessRequirements()
36 50 reqs.items = self.items.copy()
37 for l, a in histogram.items(): 51 reqs.progressives = self.progressives.copy()
38 self.letters[l] = max(self.letters.get(l, 0), histogram.get(l)) 52 reqs.rooms = self.rooms.copy()
53 reqs.letters = self.letters.copy()
54 reqs.cyans = self.cyans
55 reqs.or_logic = [[other_req.copy() for other_req in disjunction] for disjunction in self.or_logic]
56 reqs.complete_at = self.complete_at
57 reqs.possibilities = self.possibilities.copy()
58 return reqs
39 59
40 def merge(self, other: "AccessRequirements"): 60 def merge(self, other: "AccessRequirements"):
41 for item in other.items: 61 for item in other.items:
42 self.items.add(item) 62 self.items.add(item)
43 63
64 for item, amount in other.progressives.items():
65 self.progressives[item] = max(amount, self.progressives.get(item, 0))
66
44 for room in other.rooms: 67 for room in other.rooms:
45 self.rooms.add(room) 68 self.rooms.add(room)
46 69
47 for symbol in other.symbols:
48 self.symbols.add(symbol)
49
50 for letter, level in other.letters.items(): 70 for letter, level in other.letters.items():
51 self.letters[letter] = max(self.letters.get(letter, 0), level) 71 self.letters[letter] = max(self.letters.get(letter, 0), level)
52 72
73 self.cyans = self.cyans or other.cyans
74
53 for disjunction in other.or_logic: 75 for disjunction in other.or_logic:
54 self.or_logic.append(disjunction) 76 self.or_logic.append(disjunction)
55 77
78 if other.complete_at is not None:
79 # Merging multiple requirements that use complete_at sucks, and is part of why we want to minimize use of
80 # it. If both requirements use complete_at, we will cheat by using the or_logic field, which supports
81 # conjunctions of requirements.
82 if self.complete_at is not None:
83 print("Merging requirements with complete_at > 1. This is messy and should be avoided!")
84
85 left_req = AccessRequirements()
86 left_req.complete_at = self.complete_at
87 left_req.possibilities = self.possibilities
88 self.or_logic.append([left_req])
89
90 self.complete_at = None
91 self.possibilities = list()
92
93 right_req = AccessRequirements()
94 right_req.complete_at = other.complete_at
95 right_req.possibilities = other.possibilities
96 self.or_logic.append([right_req])
97 else:
98 self.complete_at = other.complete_at
99 self.possibilities = other.possibilities
100
101 def is_empty(self) -> bool:
102 return (len(self.items) == 0 and len(self.progressives) == 0 and len(self.rooms) == 0 and len(self.letters) == 0
103 and not self.cyans and len(self.or_logic) == 0 and self.complete_at is None)
104
105 def __eq__(self, other: "AccessRequirements"):
106 return (self.items == other.items and self.progressives == other.progressives and self.rooms == other.rooms and
107 self.letters == other.letters and self.cyans == other.cyans and self.or_logic == other.or_logic and
108 self.complete_at == other.complete_at and self.possibilities == other.possibilities)
109
110 def simplify(self):
111 resimplify = False
112
113 if len(self.or_logic) > 0:
114 old_or_logic = self.or_logic
115
116 def remove_redundant(sub_reqs: "AccessRequirements"):
117 new_reqs = sub_reqs.copy()
118 new_reqs.letters = {l: v for l, v in new_reqs.letters.items() if self.letters.get(l, 0) < v}
119 if new_reqs != sub_reqs:
120 return new_reqs
121 else:
122 return sub_reqs
123
124 self.or_logic = []
125 for disjunction in old_or_logic:
126 new_disjunction = []
127 for ssr in disjunction:
128 new_ssr = remove_redundant(ssr)
129 if not new_ssr.is_empty():
130 new_disjunction.append(new_ssr)
131 else:
132 new_disjunction.clear()
133 break
134 if len(new_disjunction) == 1:
135 self.merge(new_disjunction[0])
136 resimplify = True
137 elif len(new_disjunction) > 1:
138 if all(cjr == new_disjunction[0] for cjr in new_disjunction):
139 self.merge(new_disjunction[0])
140 resimplify = True
141 else:
142 self.or_logic.append(new_disjunction)
143
144 if resimplify:
145 self.simplify()
146
147 def get_referenced_rooms(self):
148 result = set(self.rooms)
149
150 for disjunction in self.or_logic:
151 for sub_req in disjunction:
152 result = result.union(sub_req.get_referenced_rooms())
153
154 for sub_req in self.possibilities:
155 result = result.union(sub_req.get_referenced_rooms())
156
157 return result
158
159 def remove_room(self, room: str):
160 if room in self.rooms:
161 self.rooms.remove(room)
162
163 for disjunction in self.or_logic:
164 for sub_req in disjunction:
165 sub_req.remove_room(room)
166
167 for sub_req in self.possibilities:
168 sub_req.remove_room(room)
169
170 def __repr__(self):
171 parts = []
172 if len(self.items) > 0:
173 parts.append(f"items={self.items}")
174 if len(self.progressives) > 0:
175 parts.append(f"progressives={self.progressives}")
176 if len(self.rooms) > 0:
177 parts.append(f"rooms={self.rooms}")
178 if len(self.letters) > 0:
179 parts.append(f"letters={self.letters}")
180 if self.cyans:
181 parts.append(f"cyans=True")
182 if len(self.or_logic) > 0:
183 parts.append(f"or_logic={self.or_logic}")
184 if self.complete_at is not None:
185 parts.append(f"complete_at={self.complete_at}")
186 if len(self.possibilities) > 0:
187 parts.append(f"possibilities={self.possibilities}")
188 return "AccessRequirements(" + ", ".join(parts) + ")"
189
56 190
57class PlayerLocation(NamedTuple): 191class PlayerLocation(NamedTuple):
58 code: int | None 192 code: int | None
59 reqs: AccessRequirements 193 reqs: AccessRequirements
60 194
61 195
196class LetterBehavior(IntEnum):
197 VANILLA = auto()
198 ITEM = auto()
199 UNLOCKED = auto()
200
201
62class Lingo2PlayerLogic: 202class Lingo2PlayerLogic:
63 world: "Lingo2World" 203 world: "Lingo2World"
64 204
65 locations_by_room: dict[int, list[PlayerLocation]] 205 locations_by_room: dict[int, list[PlayerLocation]]
66 item_by_door: dict[int, str] 206 event_loc_item_by_room: dict[int, dict[str, str]]
207
208 item_by_door: dict[int, tuple[str, int]]
67 209
68 panel_reqs: dict[int, AccessRequirements] 210 panel_reqs: dict[int, AccessRequirements]
69 proxy_reqs: dict[int, dict[str, AccessRequirements]] 211 proxy_reqs: dict[int, dict[str, AccessRequirements]]
@@ -71,22 +213,79 @@ class Lingo2PlayerLogic:
71 213
72 real_items: list[str] 214 real_items: list[str]
73 215
216 double_letter_amount: dict[str, int]
217
74 def __init__(self, world: "Lingo2World"): 218 def __init__(self, world: "Lingo2World"):
75 self.world = world 219 self.world = world
76 self.locations_by_room = {} 220 self.locations_by_room = {}
221 self.event_loc_item_by_room = {}
77 self.item_by_door = {} 222 self.item_by_door = {}
78 self.panel_reqs = dict() 223 self.panel_reqs = dict()
79 self.proxy_reqs = dict() 224 self.proxy_reqs = dict()
80 self.door_reqs = dict() 225 self.door_reqs = dict()
81 self.real_items = list() 226 self.real_items = list()
227 self.double_letter_amount = dict()
228
229 if self.world.options.shuffle_doors:
230 for progressive in world.static_logic.objects.progressives:
231 for i in range(0, len(progressive.doors)):
232 self.item_by_door[progressive.doors[i]] = (progressive.name, i + 1)
233 self.real_items.append(progressive.name)
234
235 for door_group in world.static_logic.objects.door_groups:
236 if door_group.type == data_pb2.DoorGroupType.CONNECTOR:
237 if not self.world.options.shuffle_doors or self.world.options.shuffle_worldports:
238 continue
239 elif door_group.type == data_pb2.DoorGroupType.COLOR_CONNECTOR:
240 if not self.world.options.shuffle_control_center_colors or self.world.options.shuffle_worldports:
241 continue
242 elif door_group.type == data_pb2.DoorGroupType.SHUFFLE_GROUP:
243 if not self.world.options.shuffle_doors:
244 continue
245 else:
246 continue
247
248 for door in door_group.doors:
249 self.item_by_door[door] = (door_group.name, 1)
250
251 self.real_items.append(door_group.name)
82 252
83 # We iterate through the doors in two parts because it is essential that we determine which doors are shuffled 253 # We iterate through the doors in two parts because it is essential that we determine which doors are shuffled
84 # before we calculate any access requirements. 254 # before we calculate any access requirements.
85 for door in world.static_logic.objects.doors: 255 for door in world.static_logic.objects.doors:
86 if door.type in [data_pb2.DoorType.STANDARD, data_pb2.DoorType.ITEM_ONLY] and self.world.options.shuffle_doors: 256 if door.type in [data_pb2.DoorType.EVENT, data_pb2.DoorType.LOCATION_ONLY, data_pb2.DoorType.GRAVESTONE]:
87 door_item_name = self.world.static_logic.get_door_item_name(door.id) 257 continue
88 self.item_by_door[door.id] = door_item_name 258
89 self.real_items.append(door_item_name) 259 if door.id in self.item_by_door:
260 continue
261
262 if (door.type in [data_pb2.DoorType.STANDARD, data_pb2.DoorType.ITEM_ONLY] and
263 not self.world.options.shuffle_doors):
264 continue
265
266 if (door.type == data_pb2.DoorType.CONTROL_CENTER_COLOR and
267 not self.world.options.shuffle_control_center_colors):
268 continue
269
270 if door.type == data_pb2.DoorType.GALLERY_PAINTING and not self.world.options.shuffle_gallery_paintings:
271 continue
272
273 door_item_name = self.world.static_logic.get_door_item_name(door)
274 self.item_by_door[door.id] = (door_item_name, 1)
275 self.real_items.append(door_item_name)
276
277 # We handle cyan_door_behavior = Item after door shuffle, because cyan doors that are impacted by door shuffle
278 # should be exempt from cyan_door_behavior.
279 if world.options.cyan_door_behavior == CyanDoorBehavior.option_item:
280 for door_group in world.static_logic.objects.door_groups:
281 if door_group.type != data_pb2.DoorGroupType.CYAN_DOORS:
282 continue
283
284 for door in door_group.doors:
285 if not door in self.item_by_door:
286 self.item_by_door[door] = (door_group.name, 1)
287
288 self.real_items.append(door_group.name)
90 289
91 for door in world.static_logic.objects.doors: 290 for door in world.static_logic.objects.doors:
92 if door.type in [data_pb2.DoorType.STANDARD, data_pb2.DoorType.LOCATION_ONLY, data_pb2.DoorType.GRAVESTONE]: 291 if door.type in [data_pb2.DoorType.STANDARD, data_pb2.DoorType.LOCATION_ONLY, data_pb2.DoorType.GRAVESTONE]:
@@ -96,14 +295,55 @@ class Lingo2PlayerLogic:
96 for letter in world.static_logic.objects.letters: 295 for letter in world.static_logic.objects.letters:
97 self.locations_by_room.setdefault(letter.room_id, []).append(PlayerLocation(letter.ap_id, 296 self.locations_by_room.setdefault(letter.room_id, []).append(PlayerLocation(letter.ap_id,
98 AccessRequirements())) 297 AccessRequirements()))
298 behavior = self.get_letter_behavior(letter.key, letter.level2)
299 if behavior == LetterBehavior.VANILLA:
300 if not world.for_tracker:
301 letter_name = f"{letter.key.upper()}{'2' if letter.level2 else '1'}"
302 event_name = f"{letter_name} (Collected)"
303 self.event_loc_item_by_room.setdefault(letter.room_id, {})[event_name] = letter.key.upper()
304
305 if letter.level2:
306 event_name = f"{letter_name} (Double Collected)"
307 self.event_loc_item_by_room.setdefault(letter.room_id, {})[event_name] = letter.key.upper()
308 elif behavior == LetterBehavior.ITEM:
309 self.real_items.append(letter.key.upper())
310
311 if behavior != LetterBehavior.UNLOCKED:
312 self.double_letter_amount[letter.key.upper()] = self.double_letter_amount.get(letter.key.upper(), 0) + 1
99 313
100 for mastery in world.static_logic.objects.masteries: 314 for mastery in world.static_logic.objects.masteries:
101 self.locations_by_room.setdefault(mastery.room_id, []).append(PlayerLocation(mastery.ap_id, 315 self.locations_by_room.setdefault(mastery.room_id, []).append(PlayerLocation(mastery.ap_id,
102 AccessRequirements())) 316 AccessRequirements()))
103 317
104 for ending in world.static_logic.objects.endings: 318 for ending in world.static_logic.objects.endings:
105 self.locations_by_room.setdefault(ending.room_id, []).append(PlayerLocation(ending.ap_id, 319 # Don't create a location for your selected ending, and never create a location for White Ending.
106 AccessRequirements())) 320 if world.options.victory_condition.current_key.removesuffix("_ending").upper() != ending.name\
321 and ending.name != "WHITE":
322 self.locations_by_room.setdefault(ending.room_id, []).append(PlayerLocation(ending.ap_id,
323 AccessRequirements()))
324
325 event_name = f"{ending.name.capitalize()} Ending (Achieved)"
326 item_name = event_name
327
328 if world.options.victory_condition.current_key.removesuffix("_ending").upper() == ending.name:
329 item_name = "Victory"
330
331 self.event_loc_item_by_room.setdefault(ending.room_id, {})[event_name] = item_name
332
333 if self.world.options.keyholder_sanity:
334 for keyholder in world.static_logic.objects.keyholders:
335 if keyholder.HasField("key"):
336 reqs = AccessRequirements()
337
338 if self.get_letter_behavior(keyholder.key, False) != LetterBehavior.UNLOCKED:
339 reqs.letters[keyholder.key.upper()] = 1
340
341 self.locations_by_room.setdefault(keyholder.room_id, []).append(PlayerLocation(keyholder.ap_id,
342 reqs))
343
344 if self.world.options.shuffle_symbols:
345 for symbol_name in SYMBOL_ITEMS.values():
346 self.real_items.append(symbol_name)
107 347
108 def get_panel_reqs(self, panel_id: int, answer: str | None) -> AccessRequirements: 348 def get_panel_reqs(self, panel_id: int, answer: str | None) -> AccessRequirements:
109 if answer is None: 349 if answer is None:
@@ -124,18 +364,38 @@ class Lingo2PlayerLogic:
124 reqs.rooms.add(self.world.static_logic.get_room_region_name(panel.room_id)) 364 reqs.rooms.add(self.world.static_logic.get_room_region_name(panel.room_id))
125 365
126 if answer is not None: 366 if answer is not None:
127 reqs.add_solution(answer) 367 self.add_solution_reqs(reqs, answer)
128 elif len(panel.proxies) > 0: 368 elif len(panel.proxies) > 0:
369 possibilities = []
370 already_filled = False
371
129 for proxy in panel.proxies: 372 for proxy in panel.proxies:
130 proxy_reqs = AccessRequirements() 373 proxy_reqs = AccessRequirements()
131 proxy_reqs.add_solution(proxy.answer) 374 self.add_solution_reqs(proxy_reqs, proxy.answer)
375
376 if not proxy_reqs.is_empty():
377 possibilities.append(proxy_reqs)
378 else:
379 already_filled = True
380 break
381
382 if not already_filled and not any(proxy.answer == panel.answer for proxy in panel.proxies):
383 proxy_reqs = AccessRequirements()
384 self.add_solution_reqs(proxy_reqs, panel.answer)
132 385
133 reqs.or_logic.append([proxy_reqs]) 386 if not proxy_reqs.is_empty():
387 possibilities.append(proxy_reqs)
388 else:
389 already_filled = True
390
391 if not already_filled:
392 reqs.or_logic.append(possibilities)
134 else: 393 else:
135 reqs.add_solution(panel.answer) 394 self.add_solution_reqs(reqs, panel.answer)
136 395
137 for symbol in panel.symbols: 396 if self.world.options.shuffle_symbols:
138 reqs.symbols.add(symbol) 397 for symbol in panel.symbols:
398 reqs.items.add(SYMBOL_ITEMS.get(symbol))
139 399
140 if panel.HasField("required_door"): 400 if panel.HasField("required_door"):
141 door_reqs = self.get_door_open_reqs(panel.required_door) 401 door_reqs = self.get_door_open_reqs(panel.required_door)
@@ -158,32 +418,67 @@ class Lingo2PlayerLogic:
158 door = self.world.static_logic.objects.doors[door_id] 418 door = self.world.static_logic.objects.doors[door_id]
159 reqs = AccessRequirements() 419 reqs = AccessRequirements()
160 420
161 use_item = False 421 if not door.HasField("complete_at") or door.complete_at == 0:
162 if door.type in [data_pb2.DoorType.STANDARD, data_pb2.DoorType.ITEM_ONLY] and self.world.options.shuffle_doors: 422 for proxy in door.panels:
163 use_item = True 423 panel_reqs = self.get_panel_reqs(proxy.panel, proxy.answer if proxy.HasField("answer") else None)
164 424 reqs.merge(panel_reqs)
165 if use_item: 425 elif door.complete_at == 1:
166 reqs.items.add(self.world.static_logic.get_door_item_name(door.id)) 426 disjunction = []
427 for proxy in door.panels:
428 proxy_reqs = self.get_panel_reqs(proxy.panel, proxy.answer if proxy.HasField("answer") else None)
429 if proxy_reqs.is_empty():
430 disjunction.clear()
431 break
432 else:
433 disjunction.append(proxy_reqs)
434 if len(disjunction) > 0:
435 reqs.or_logic.append(disjunction)
167 else: 436 else:
168 # TODO: complete_at, control_center_color, switches, keyholders 437 reqs.complete_at = door.complete_at
169 if not door.HasField("complete_at") or door.complete_at == 0: 438 for proxy in door.panels:
170 for proxy in door.panels: 439 panel_reqs = self.get_panel_reqs(proxy.panel, proxy.answer if proxy.HasField("answer") else None)
171 panel_reqs = self.get_panel_reqs(proxy.panel, proxy.answer if proxy.HasField("answer") else None) 440 reqs.possibilities.append(panel_reqs)
172 reqs.merge(panel_reqs) 441
173 elif door.complete_at == 1: 442 if door.HasField("control_center_color"):
174 reqs.or_logic.append([self.get_panel_reqs(proxy.panel, 443 # TODO: Logic for ensuring two CC states aren't needed at once.
175 proxy.answer if proxy.HasField("answer") else None) 444 reqs.rooms.add("Control Center - Main Area")
176 for proxy in door.panels]) 445 self.add_solution_reqs(reqs, door.control_center_color)
177 else: 446
178 # TODO: Handle complete_at > 1 447 if door.double_letters:
448 if self.world.options.cyan_door_behavior == CyanDoorBehavior.option_collect_h2:
449 reqs.rooms.add("The Repetitive - Main Room")
450 elif self.world.options.cyan_door_behavior == CyanDoorBehavior.option_any_double_letter:
451 if self.world.options.shuffle_letters != ShuffleLetters.option_unlocked:
452 reqs.cyans = True
453 elif self.world.options.cyan_door_behavior == CyanDoorBehavior.option_item:
454 # There shouldn't be any locations that are cyan doors.
179 pass 455 pass
180 456
181 for room in door.rooms: 457 for keyholder_uses in door.keyholders:
182 reqs.rooms.add(self.world.static_logic.get_room_region_name(room)) 458 key_name = keyholder_uses.key.upper()
459 if (self.get_letter_behavior(keyholder_uses.key, False) != LetterBehavior.UNLOCKED
460 and key_name not in reqs.letters):
461 reqs.letters[key_name] = 1
462
463 keyholder = self.world.static_logic.objects.keyholders[keyholder_uses.keyholder]
464 reqs.rooms.add(self.world.static_logic.get_room_region_name(keyholder.room_id))
465
466 for room in door.rooms:
467 reqs.rooms.add(self.world.static_logic.get_room_region_name(room))
468
469 for ending_id in door.endings:
470 ending = self.world.static_logic.objects.endings[ending_id]
471
472 if self.world.options.victory_condition.current_key.removesuffix("_ending").upper() == ending.name:
473 reqs.items.add("Victory")
474 else:
475 reqs.items.add(f"{ending.name.capitalize()} Ending (Achieved)")
476
477 for sub_door_id in door.doors:
478 sub_reqs = self.get_door_open_reqs(sub_door_id)
479 reqs.merge(sub_reqs)
183 480
184 for sub_door_id in door.doors: 481 reqs.simplify()
185 sub_reqs = self.get_door_open_reqs(sub_door_id)
186 reqs.merge(sub_reqs)
187 482
188 return reqs 483 return reqs
189 484
@@ -192,8 +487,50 @@ class Lingo2PlayerLogic:
192 def get_door_open_reqs(self, door_id: int) -> AccessRequirements: 487 def get_door_open_reqs(self, door_id: int) -> AccessRequirements:
193 if door_id in self.item_by_door: 488 if door_id in self.item_by_door:
194 reqs = AccessRequirements() 489 reqs = AccessRequirements()
195 reqs.items.add(self.item_by_door.get(door_id)) 490
491 item_name, amount = self.item_by_door.get(door_id)
492 if amount == 1:
493 reqs.items.add(item_name)
494 else:
495 reqs.progressives[item_name] = amount
196 496
197 return reqs 497 return reqs
198 else: 498 else:
199 return self.get_door_reqs(door_id) 499 return self.get_door_reqs(door_id)
500
501 def get_letter_behavior(self, letter: str, level2: bool) -> LetterBehavior:
502 if self.world.options.shuffle_letters == ShuffleLetters.option_unlocked:
503 return LetterBehavior.UNLOCKED
504
505 if self.world.options.shuffle_letters in [ShuffleLetters.option_vanilla_cyan, ShuffleLetters.option_item_cyan]:
506 if level2:
507 if self.world.options.shuffle_letters == ShuffleLetters.option_vanilla_cyan:
508 return LetterBehavior.VANILLA
509 else:
510 return LetterBehavior.ITEM
511 else:
512 return LetterBehavior.UNLOCKED
513
514 if not level2 and letter in ["h", "i", "n", "t"]:
515 return LetterBehavior.UNLOCKED
516
517 if self.world.options.shuffle_letters == ShuffleLetters.option_progressive:
518 return LetterBehavior.ITEM
519
520 return LetterBehavior.VANILLA
521
522 def add_solution_reqs(self, reqs: AccessRequirements, solution: str):
523 histogram = calculate_letter_histogram(solution)
524
525 for l, a in histogram.items():
526 needed = min(a, 2)
527 level2 = (needed == 2)
528
529 if level2 and self.get_letter_behavior(l.lower(), True) == LetterBehavior.UNLOCKED:
530 needed = 1
531
532 if self.get_letter_behavior(l.lower(), False) == LetterBehavior.UNLOCKED:
533 needed = needed - 1
534
535 if needed > 0:
536 reqs.letters[l] = max(reqs.letters.get(l, 0), needed)
diff --git a/apworld/regions.py b/apworld/regions.py index 1c8e672..3735858 100644 --- a/apworld/regions.py +++ b/apworld/regions.py
@@ -1,6 +1,9 @@
1from typing import TYPE_CHECKING 1from typing import TYPE_CHECKING
2 2
3from BaseClasses import Region 3import BaseClasses
4from BaseClasses import Region, ItemClassification, Entrance
5from entrance_rando import randomize_entrances
6from .items import Lingo2Item
4from .locations import Lingo2Location 7from .locations import Lingo2Location
5from .player_logic import AccessRequirements 8from .player_logic import AccessRequirements
6from .rules import make_location_lambda 9from .rules import make_location_lambda
@@ -10,15 +13,42 @@ if TYPE_CHECKING:
10 13
11 14
12def create_region(room, world: "Lingo2World") -> Region: 15def create_region(room, world: "Lingo2World") -> Region:
13 new_region = Region(world.static_logic.get_room_region_name(room.id), world.player, world.multiworld) 16 return Region(world.static_logic.get_room_region_name(room.id), world.player, world.multiworld)
14 17
18
19def create_locations(room, new_region: Region, world: "Lingo2World", regions: dict[str, Region]):
15 for location in world.player_logic.locations_by_room.get(room.id, {}): 20 for location in world.player_logic.locations_by_room.get(room.id, {}):
21 reqs = location.reqs.copy()
22 reqs.remove_room(new_region.name)
23
16 new_location = Lingo2Location(world.player, world.static_logic.location_id_to_name[location.code], 24 new_location = Lingo2Location(world.player, world.static_logic.location_id_to_name[location.code],
17 location.code, new_region) 25 location.code, new_region)
18 new_location.access_rule = make_location_lambda(location.reqs, world) 26 new_location.access_rule = make_location_lambda(reqs, world, regions)
27 new_region.locations.append(new_location)
28
29 for event_name, item_name in world.player_logic.event_loc_item_by_room.get(room.id, {}).items():
30 new_location = Lingo2Location(world.player, event_name, None, new_region)
31 if world.for_tracker and item_name == "Victory":
32 new_location.goal = True
33
34 event_item = Lingo2Item(item_name, ItemClassification.progression, None, world.player)
35 new_location.place_locked_item(event_item)
19 new_region.locations.append(new_location) 36 new_region.locations.append(new_location)
20 37
21 return new_region 38 if world.for_tracker and world.options.shuffle_worldports:
39 for port_id in room.ports:
40 port = world.static_logic.objects.ports[port_id]
41 if port.no_shuffle:
42 continue
43
44 new_location = Lingo2Location(world.player, f"Worldport {port.id} Entered", None, new_region)
45 new_location.port_id = port.id
46
47 if port.HasField("required_door"):
48 new_location.access_rule = \
49 make_location_lambda(world.player_logic.get_door_open_reqs(port.required_door), world, regions)
50
51 new_region.locations.append(new_location)
22 52
23 53
24def create_regions(world: "Lingo2World"): 54def create_regions(world: "Lingo2World"):
@@ -26,16 +56,34 @@ def create_regions(world: "Lingo2World"):
26 "Menu": Region("Menu", world.player, world.multiworld) 56 "Menu": Region("Menu", world.player, world.multiworld)
27 } 57 }
28 58
59 region_and_room = []
60
61 # Create the regions in two stages. First, make the actual region objects and memoize them. Then, add all of the
62 # locations. This allows us to reference the actual region objects in the access rules for the locations, which is
63 # faster than having to look them up during access checking.
29 for room in world.static_logic.objects.rooms: 64 for room in world.static_logic.objects.rooms:
30 region = create_region(room, world) 65 region = create_region(room, world)
31 regions[region.name] = region 66 regions[region.name] = region
67 region_and_room.append((region, room))
68
69 for (region, room) in region_and_room:
70 create_locations(room, region, world, regions)
32 71
33 regions["Menu"].connect(regions["The Entry - Starting Room"], "Start Game") 72 regions["Menu"].connect(regions["The Entry - Starting Room"], "Start Game")
34 73
35 # TODO: The requirements of the opposite trigger also matter.
36 for connection in world.static_logic.objects.connections: 74 for connection in world.static_logic.objects.connections:
75 if connection.roof_access and not world.options.daedalus_roof_access:
76 continue
77
78 if connection.vanilla_only and world.options.shuffle_doors:
79 continue
80
37 from_region = world.static_logic.get_room_region_name(connection.from_room) 81 from_region = world.static_logic.get_room_region_name(connection.from_room)
38 to_region = world.static_logic.get_room_region_name(connection.to_room) 82 to_region = world.static_logic.get_room_region_name(connection.to_room)
83
84 if from_region not in regions or to_region not in regions:
85 continue
86
39 connection_name = f"{from_region} -> {to_region}" 87 connection_name = f"{from_region} -> {to_region}"
40 88
41 reqs = AccessRequirements() 89 reqs = AccessRequirements()
@@ -51,6 +99,9 @@ def create_regions(world: "Lingo2World"):
51 port = world.static_logic.objects.ports[connection.port] 99 port = world.static_logic.objects.ports[connection.port]
52 connection_name = f"{connection_name} (via port {port.name})" 100 connection_name = f"{connection_name} (via port {port.name})"
53 101
102 if world.options.shuffle_worldports and not port.no_shuffle:
103 continue
104
54 if port.HasField("required_door"): 105 if port.HasField("required_door"):
55 reqs.merge(world.player_logic.get_door_open_reqs(port.required_door)) 106 reqs.merge(world.player_logic.get_door_open_reqs(port.required_door))
56 107
@@ -72,7 +123,93 @@ def create_regions(world: "Lingo2World"):
72 else: 123 else:
73 connection_name = f"{connection_name} (via panel {panel.name})" 124 connection_name = f"{connection_name} (via panel {panel.name})"
74 125
75 if from_region in regions and to_region in regions: 126 if connection.HasField("purple_ending") and connection.purple_ending and world.options.strict_purple_ending:
76 regions[from_region].connect(regions[to_region], connection_name, make_location_lambda(reqs, world)) 127 world.player_logic.add_solution_reqs(reqs, "abcdefghijklmnopqrstuvwxyz")
128
129 if connection.HasField("cyan_ending") and connection.cyan_ending and world.options.strict_cyan_ending:
130 world.player_logic.add_solution_reqs(reqs, "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz")
131
132 reqs.simplify()
133 reqs.remove_room(from_region)
134
135 connection = Entrance(world.player, connection_name, regions[from_region])
136 connection.access_rule = make_location_lambda(reqs, world, regions)
137
138 regions[from_region].exits.append(connection)
139 connection.connect(regions[to_region])
140
141 for region in reqs.get_referenced_rooms():
142 world.multiworld.register_indirect_condition(regions[region], connection)
77 143
78 world.multiworld.regions += regions.values() 144 world.multiworld.regions += regions.values()
145
146
147def shuffle_entrances(world: "Lingo2World"):
148 er_entrances: list[Entrance] = []
149 er_exits: list[Entrance] = []
150
151 port_id_by_name: dict[str, int] = {}
152
153 for port in world.static_logic.objects.ports:
154 if port.no_shuffle:
155 continue
156
157 port_region_name = world.static_logic.get_room_region_name(port.room_id)
158 port_region = world.multiworld.get_region(port_region_name, world.player)
159
160 connection_name = f"{port_region_name} - {port.name}"
161 port_id_by_name[connection_name] = port.id
162
163 entrance = port_region.create_er_target(connection_name)
164 entrance.randomization_type = BaseClasses.EntranceType.TWO_WAY
165
166 er_exit = port_region.create_exit(connection_name)
167 er_exit.randomization_type = BaseClasses.EntranceType.TWO_WAY
168
169 if port.HasField("required_door"):
170 door_reqs = world.player_logic.get_door_open_reqs(port.required_door)
171 er_exit.access_rule = make_location_lambda(door_reqs, world, None)
172
173 for region in door_reqs.get_referenced_rooms():
174 world.multiworld.register_indirect_condition(world.multiworld.get_region(region, world.player),
175 er_exit)
176
177 er_entrances.append(entrance)
178 er_exits.append(er_exit)
179
180 result = randomize_entrances(world, True, {0:[0]}, False, er_entrances,
181 er_exits)
182
183 for (f, to) in result.pairings:
184 world.port_pairings[port_id_by_name[f]] = port_id_by_name[to]
185
186
187def connect_ports_from_ut(port_pairings: dict[int, int], world: "Lingo2World"):
188 for fpid, tpid in port_pairings.items():
189 from_port = world.static_logic.objects.ports[fpid]
190 to_port = world.static_logic.objects.ports[tpid]
191
192 from_region_name = world.static_logic.get_room_region_name(from_port.room_id)
193 to_region_name = world.static_logic.get_room_region_name(to_port.room_id)
194
195 from_region = world.multiworld.get_region(from_region_name, world.player)
196 to_region = world.multiworld.get_region(to_region_name, world.player)
197
198 connection = Entrance(world.player, f"{from_region_name} - {from_port.name}", from_region)
199
200 reqs = AccessRequirements()
201 if from_port.HasField("required_door"):
202 reqs = world.player_logic.get_door_open_reqs(from_port.required_door).copy()
203
204 if world.for_tracker:
205 reqs.items.add(f"Worldport {fpid} Entered")
206
207 if not reqs.is_empty():
208 connection.access_rule = make_location_lambda(reqs, world, None)
209
210 for region in reqs.get_referenced_rooms():
211 world.multiworld.register_indirect_condition(world.multiworld.get_region(region, world.player),
212 connection)
213
214 from_region.exits.append(connection)
215 connection.connect(to_region)
diff --git a/apworld/requirements.txt b/apworld/requirements.txt index b701d11..dbc395b 100644 --- a/apworld/requirements.txt +++ b/apworld/requirements.txt
@@ -1 +1 @@
protobuf>=5.29.3 \ No newline at end of file protobuf==3.20.3
diff --git a/apworld/rules.py b/apworld/rules.py index 05689e9..f859e75 100644 --- a/apworld/rules.py +++ b/apworld/rules.py
@@ -1,27 +1,66 @@
1from collections.abc import Callable 1from collections.abc import Callable
2from typing import TYPE_CHECKING 2from typing import TYPE_CHECKING
3 3
4from BaseClasses import CollectionState 4from BaseClasses import CollectionState, Region
5from .player_logic import AccessRequirements 5from .player_logic import AccessRequirements
6 6
7if TYPE_CHECKING: 7if TYPE_CHECKING:
8 from . import Lingo2World 8 from . import Lingo2World
9 9
10 10
11def lingo2_can_satisfy_requirements(state: CollectionState, reqs: AccessRequirements, world: "Lingo2World") -> bool: 11def lingo2_can_satisfy_requirements(state: CollectionState, reqs: AccessRequirements, regions: list[Region],
12 world: "Lingo2World") -> bool:
12 if not all(state.has(item, world.player) for item in reqs.items): 13 if not all(state.has(item, world.player) for item in reqs.items):
13 return False 14 return False
14 15
16 if not all(state.has(item, world.player, amount) for item, amount in reqs.progressives.items()):
17 return False
18
15 if not all(state.can_reach_region(region_name, world.player) for region_name in reqs.rooms): 19 if not all(state.can_reach_region(region_name, world.player) for region_name in reqs.rooms):
16 return False 20 return False
17 21
18 # TODO: symbols, letters 22 if not all(state.can_reach(region) for region in regions):
23 return False
24
25 for letter_key, letter_level in reqs.letters.items():
26 if not state.has(letter_key, world.player, letter_level):
27 return False
28
29 if reqs.cyans:
30 if not any(state.has(letter, world.player, amount)
31 for letter, amount in world.player_logic.double_letter_amount.items()):
32 return False
33
34 if len(reqs.or_logic) > 0:
35 if not all(any(lingo2_can_satisfy_requirements(state, sub_reqs, [], world) for sub_reqs in subjunction)
36 for subjunction in reqs.or_logic):
37 return False
19 38
20 for disjunction in reqs.or_logic: 39 if reqs.complete_at is not None:
21 if not any(lingo2_can_satisfy_requirements(state, sub_reqs, world) for sub_reqs in disjunction): 40 completed = 0
41 checked = 0
42 for possibility in reqs.possibilities:
43 checked += 1
44 if lingo2_can_satisfy_requirements(state, possibility, [], world):
45 completed += 1
46 if completed >= reqs.complete_at:
47 break
48 elif len(reqs.possibilities) - checked + completed < reqs.complete_at:
49 # There aren't enough remaining possibilities for the check to pass.
50 return False
51 if completed < reqs.complete_at:
22 return False 52 return False
23 53
24 return True 54 return True
25 55
26def make_location_lambda(reqs: AccessRequirements, world: "Lingo2World") -> Callable[[CollectionState], bool]: 56def make_location_lambda(reqs: AccessRequirements, world: "Lingo2World",
27 return lambda state: lingo2_can_satisfy_requirements(state, reqs, world) 57 regions: dict[str, Region] | None) -> Callable[[CollectionState], bool]:
58 # Replace required rooms with regions for the top level requirement, which saves looking up the regions during rule
59 # checking.
60 if regions is not None:
61 required_regions = [regions[room_name] for room_name in reqs.rooms]
62 else:
63 required_regions = [world.multiworld.get_region(room_name, world.player) for room_name in reqs.rooms]
64 new_reqs = reqs.copy()
65 new_reqs.rooms.clear()
66 return lambda state: lingo2_can_satisfy_requirements(state, new_reqs, required_regions, world)
diff --git a/apworld/static_logic.py b/apworld/static_logic.py index 965ce3e..e59a47d 100644 --- a/apworld/static_logic.py +++ b/apworld/static_logic.py
@@ -1,6 +1,8 @@
1from .generated import data_pb2 as data_pb2 1from .generated import data_pb2 as data_pb2
2from .items import SYMBOL_ITEMS, ANTI_COLLECTABLE_TRAPS
2import pkgutil 3import pkgutil
3 4
5
4class Lingo2StaticLogic: 6class Lingo2StaticLogic:
5 item_id_to_name: dict[int, str] 7 item_id_to_name: dict[int, str]
6 location_id_to_name: dict[int, str] 8 location_id_to_name: dict[int, str]
@@ -8,9 +10,17 @@ class Lingo2StaticLogic:
8 item_name_to_id: dict[str, int] 10 item_name_to_id: dict[str, int]
9 location_name_to_id: dict[str, int] 11 location_name_to_id: dict[str, int]
10 12
13 item_name_groups: dict[str, list[str]]
14 location_name_groups: dict[str, list[str]]
15
16 letter_weights: dict[str, int]
17
11 def __init__(self): 18 def __init__(self):
12 self.item_id_to_name = {} 19 self.item_id_to_name = {}
13 self.location_id_to_name = {} 20 self.location_id_to_name = {}
21 self.item_name_groups = {}
22 self.location_name_groups = {}
23 self.letter_weights = {}
14 24
15 file = pkgutil.get_data(__name__, "generated/data.binpb") 25 file = pkgutil.get_data(__name__, "generated/data.binpb")
16 self.objects = data_pb2.AllObjects() 26 self.objects = data_pb2.AllObjects()
@@ -18,38 +28,125 @@ class Lingo2StaticLogic:
18 28
19 for door in self.objects.doors: 29 for door in self.objects.doors:
20 if door.type in [data_pb2.DoorType.STANDARD, data_pb2.DoorType.LOCATION_ONLY, data_pb2.DoorType.GRAVESTONE]: 30 if door.type in [data_pb2.DoorType.STANDARD, data_pb2.DoorType.LOCATION_ONLY, data_pb2.DoorType.GRAVESTONE]:
21 location_name = f"{self.get_map_object_map_name(door)} - {door.name}" 31 location_name = self.get_door_location_name(door)
22 self.location_id_to_name[door.ap_id] = location_name 32 self.location_id_to_name[door.ap_id] = location_name
23 33
24 if door.type not in [data_pb2.DoorType.EVENT, data_pb2.DoorType.LOCATION_ONLY, data_pb2.DoorType.GRAVESTONE]: 34 if door.type not in [data_pb2.DoorType.EVENT, data_pb2.DoorType.LOCATION_ONLY, data_pb2.DoorType.GRAVESTONE]:
25 item_name = self.get_door_item_name(door.id) 35 item_name = self.get_door_item_name(door)
26 self.item_id_to_name[door.ap_id] = item_name 36 self.item_id_to_name[door.ap_id] = item_name
27 37
28 for letter in self.objects.letters: 38 for letter in self.objects.letters:
29 letter_name = f"{letter.key.upper()}{'2' if letter.level2 else '1'}" 39 letter_name = f"{letter.key.upper()}{'2' if letter.level2 else '1'}"
30 location_name = f"{self.get_room_object_map_name(letter)} - {letter_name}" 40 location_name = f"{self.get_room_object_map_name(letter)} - {letter_name}"
31 self.location_id_to_name[letter.ap_id] = location_name 41 self.location_id_to_name[letter.ap_id] = location_name
42 self.location_name_groups.setdefault("Letters", []).append(location_name)
32 43
33 if not letter.level2: 44 if not letter.level2:
34 self.item_id_to_name[letter.ap_id] = letter_name 45 self.item_id_to_name[letter.ap_id] = letter.key.upper()
46 self.item_name_groups.setdefault("Letters", []).append(letter.key.upper())
35 47
36 for mastery in self.objects.masteries: 48 for mastery in self.objects.masteries:
37 location_name = f"{self.get_room_object_map_name(mastery)} - Mastery" 49 location_name = f"{self.get_room_object_map_name(mastery)} - Mastery"
38 self.location_id_to_name[mastery.ap_id] = location_name 50 self.location_id_to_name[mastery.ap_id] = location_name
51 self.location_name_groups.setdefault("Masteries", []).append(location_name)
39 52
40 for ending in self.objects.endings: 53 for ending in self.objects.endings:
41 location_name = f"{self.get_room_object_map_name(ending)} - {ending.name.title()} Ending" 54 location_name = f"{self.get_room_object_map_name(ending)} - {ending.name.title()} Ending"
42 self.location_id_to_name[ending.ap_id] = location_name 55 self.location_id_to_name[ending.ap_id] = location_name
56 self.location_name_groups.setdefault("Endings", []).append(location_name)
57
58 for progressive in self.objects.progressives:
59 self.item_id_to_name[progressive.ap_id] = progressive.name
60
61 for door_group in self.objects.door_groups:
62 self.item_id_to_name[door_group.ap_id] = door_group.name
63
64 for keyholder in self.objects.keyholders:
65 if keyholder.HasField("key"):
66 location_name = f"{self.get_room_object_location_prefix(keyholder)} - {keyholder.key.upper()} Keyholder"
67 self.location_id_to_name[keyholder.ap_id] = location_name
68 self.location_name_groups.setdefault("Keyholders", []).append(location_name)
69
70 self.item_id_to_name[self.objects.special_ids["A Job Well Done"]] = "A Job Well Done"
71
72 for symbol_name in SYMBOL_ITEMS.values():
73 self.item_id_to_name[self.objects.special_ids[symbol_name]] = symbol_name
43 74
44 self.item_id_to_name[self.objects.special_ids["Nothing"]] = "Nothing" 75 for trap_name in ANTI_COLLECTABLE_TRAPS:
76 self.item_id_to_name[self.objects.special_ids[trap_name]] = trap_name
45 77
46 self.item_name_to_id = {name: ap_id for ap_id, name in self.item_id_to_name.items()} 78 self.item_name_to_id = {name: ap_id for ap_id, name in self.item_id_to_name.items()}
47 self.location_name_to_id = {name: ap_id for ap_id, name in self.location_id_to_name.items()} 79 self.location_name_to_id = {name: ap_id for ap_id, name in self.location_id_to_name.items()}
48 80
49 def get_door_item_name(self, door_id: int) -> str: 81 for panel in self.objects.panels:
50 door = self.objects.doors[door_id] 82 for letter in panel.answer.upper():
83 self.letter_weights[letter] = self.letter_weights.get(letter, 0) + 1
84
85 def get_door_item_name(self, door: data_pb2.Door) -> str:
51 return f"{self.get_map_object_map_name(door)} - {door.name}" 86 return f"{self.get_map_object_map_name(door)} - {door.name}"
52 87
88 def get_door_item_name_by_id(self, door_id: int) -> str:
89 door = self.objects.doors[door_id]
90 return self.get_door_item_name(door_id)
91
92 def get_door_location_name(self, door: data_pb2.Door) -> str:
93 map_part = self.get_room_object_location_prefix(door)
94
95 if door.HasField("location_name"):
96 return f"{map_part} - {door.location_name}"
97
98 generated_location_name = self.get_generated_door_location_name(door)
99 if generated_location_name is not None:
100 return generated_location_name
101
102 return f"{map_part} - {door.name}"
103
104 def get_generated_door_location_name(self, door: data_pb2.Door) -> str | None:
105 if door.type != data_pb2.DoorType.STANDARD:
106 return None
107
108 if len(door.keyholders) > 0 or len(door.endings) > 0 or door.HasField("complete_at"):
109 return None
110
111 if len(door.panels) > 4:
112 return None
113
114 map_areas = set()
115 for panel_id in door.panels:
116 panel = self.objects.panels[panel_id.panel]
117 panel_room = self.objects.rooms[panel.room_id]
118 # It's okay if panel_display_name is not present because then it's coalesced with other unnamed areas.
119 map_areas.add(panel_room.panel_display_name)
120
121 if len(map_areas) > 1:
122 return None
123
124 game_map = self.objects.maps[door.map_id]
125 map_area = map_areas.pop()
126 if map_area == "":
127 map_part = game_map.display_name
128 else:
129 map_part = f"{game_map.display_name} ({map_area})"
130
131 def get_panel_display_name(panel: data_pb2.ProxyIdentifier) -> str:
132 panel_data = self.objects.panels[panel.panel]
133 panel_name = panel_data.display_name if panel_data.HasField("display_name") else panel_data.name
134
135 if panel.HasField("answer"):
136 return f"{panel_name}/{panel.answer.upper()}"
137 else:
138 return panel_name
139
140 panel_names = [get_panel_display_name(panel_id)
141 for panel_id in door.panels]
142 panel_names.sort()
143
144 return map_part + " - " + ", ".join(panel_names)
145
146 def get_door_location_name_by_id(self, door_id: int) -> str:
147 door = self.objects.doors[door_id]
148 return self.get_door_location_name(door)
149
53 def get_room_region_name(self, room_id: int) -> str: 150 def get_room_region_name(self, room_id: int) -> str:
54 room = self.objects.rooms[room_id] 151 room = self.objects.rooms[room_id]
55 return f"{self.get_map_object_map_name(room)} - {room.name}" 152 return f"{self.get_map_object_map_name(room)} - {room.name}"
@@ -59,3 +156,16 @@ class Lingo2StaticLogic:
59 156
60 def get_room_object_map_name(self, obj) -> str: 157 def get_room_object_map_name(self, obj) -> str:
61 return self.get_map_object_map_name(self.objects.rooms[obj.room_id]) 158 return self.get_map_object_map_name(self.objects.rooms[obj.room_id])
159
160 def get_room_object_location_prefix(self, obj) -> str:
161 room = self.objects.rooms[obj.room_id]
162 game_map = self.objects.maps[room.map_id]
163
164 if room.HasField("panel_display_name"):
165 return f"{game_map.display_name} ({room.panel_display_name})"
166 else:
167 return game_map.display_name
168
169 def get_data_version(self) -> list[int]:
170 version = self.objects.version
171 return [version.major, version.minor, version.patch]
diff --git a/apworld/tracker.py b/apworld/tracker.py new file mode 100644 index 0000000..7239b65 --- /dev/null +++ b/apworld/tracker.py
@@ -0,0 +1,112 @@
1from typing import TYPE_CHECKING
2
3from BaseClasses import MultiWorld, CollectionState, ItemClassification
4from NetUtils import NetworkItem
5from . import Lingo2World, Lingo2Item
6from .regions import connect_ports_from_ut
7from .options import Lingo2Options, ShuffleLetters
8
9if TYPE_CHECKING:
10 from .context import Lingo2Manager
11
12PLAYER_NUM = 1
13
14
15class Tracker:
16 manager: "Lingo2Manager"
17
18 multiworld: MultiWorld
19 world: Lingo2World
20
21 collected_items: dict[int, int]
22 checked_locations: set[int]
23 accessible_locations: set[int]
24 accessible_worldports: set[int]
25 goal_accessible: bool
26
27 state: CollectionState
28
29 def __init__(self, manager: "Lingo2Manager"):
30 self.manager = manager
31 self.collected_items = {}
32 self.checked_locations = set()
33 self.accessible_locations = set()
34 self.accessible_worldports = set()
35 self.goal_accessible = False
36
37 def setup_slot(self, slot_data):
38 Lingo2World.for_tracker = True
39
40 self.multiworld = MultiWorld(players=PLAYER_NUM)
41 self.world = Lingo2World(self.multiworld, PLAYER_NUM)
42 self.multiworld.worlds[1] = self.world
43 self.world.options = Lingo2Options(**{k: t(slot_data.get(k, t.default))
44 for k, t in Lingo2Options.type_hints.items()})
45
46 self.world.generate_early()
47 self.world.create_regions()
48
49 if self.world.options.shuffle_worldports:
50 port_pairings = {int(fp): int(tp) for fp, tp in slot_data["port_pairings"].items()}
51 connect_ports_from_ut(port_pairings, self.world)
52
53 self.refresh_state()
54
55 def set_checked_locations(self, checked_locations: set[int]):
56 self.checked_locations = checked_locations.copy()
57
58 def set_collected_items(self, network_items: list[NetworkItem]):
59 self.collected_items = {}
60
61 for item in network_items:
62 self.collected_items[item.item] = self.collected_items.get(item.item, 0) + 1
63
64 self.refresh_state()
65
66 def refresh_state(self):
67 self.state = CollectionState(self.multiworld)
68
69 for item_id, item_amount in self.collected_items.items():
70 for i in range(item_amount):
71 self.state.collect(Lingo2Item(Lingo2World.static_logic.item_id_to_name.get(item_id),
72 ItemClassification.progression, item_id, PLAYER_NUM), prevent_sweep=True)
73
74 for k, v in self.manager.keyboard.items():
75 # Unless all level 1 letters are pre-unlocked, H1 I1 N1 and T1 act differently between the generator and
76 # game. The generator considers them to be unlocked, which means they are not included in logic
77 # requirements, and only one item/event is needed to unlock their level 2 forms. The game considers them to
78 # be vanilla, which means you still have to pick them up in the Starting Room in order for them to appear on
79 # your keyboard. This also means that whether or not you have the level 1 forms should be synced to the
80 # multiworld. The tracker specifically should collect one fewer item for these letters in this scenario.
81 tv = v
82 if k in "hint" and self.world.options.shuffle_letters in [ShuffleLetters.option_vanilla,
83 ShuffleLetters.option_progressive]:
84 tv = max(0, v - 1)
85
86 if tv > 0:
87 for i in range(tv):
88 self.state.collect(Lingo2Item(k.upper(), ItemClassification.progression, None, PLAYER_NUM),
89 prevent_sweep=True)
90
91 for port_id in self.manager.worldports:
92 self.state.collect(Lingo2Item(f"Worldport {port_id} Entered", ItemClassification.progression, None,
93 PLAYER_NUM), prevent_sweep=True)
94
95 self.state.sweep_for_advancements()
96
97 self.accessible_locations = set()
98 self.accessible_worldports = set()
99 self.goal_accessible = False
100
101 for region in self.state.reachable_regions[PLAYER_NUM]:
102 for location in region.locations:
103 if location.access_rule(self.state):
104 if location.address is not None:
105 if location.address not in self.checked_locations:
106 self.accessible_locations.add(location.address)
107 elif hasattr(location, "port_id"):
108 if location.port_id not in self.manager.worldports:
109 self.accessible_worldports.add(location.port_id)
110 elif hasattr(location, "goal") and location.goal:
111 if not self.manager.goaled:
112 self.goal_accessible = True
diff --git a/data/README.md b/data/README.md new file mode 100644 index 0000000..bf0a51b --- /dev/null +++ b/data/README.md
@@ -0,0 +1,13 @@
1# Lingo 2 Randomizer Data
2
3This folder contains the logic for the Lingo 2 randomizer in a human-readable
4format. This data is compiled into a single file and used in the various parts
5of the randomizer project (client, apworld, etc).
6
7The data is structured using [Protocol Buffers](https://protobuf.dev/). The
8schema for the human-readable format is
9[located in the repository](https://code.fourisland.com/lingo2-archipelago/tree/proto/human.proto).
10
11## Compiling
12
13Hi.
diff --git a/data/connections.txtpb b/data/connections.txtpb index 9f5c48f..ae7d9fd 100644 --- a/data/connections.txtpb +++ b/data/connections.txtpb
@@ -1,30 +1,5 @@
1# TODO 1# TODO
2# the_entry/Starting Room/HI/thewords
3# the_entry/Link Area/PYRAMID
4# control center -> the_ancient
5# the_between/Control Center Side/CC
6# the_gallery/Main Area/WISE
7# the_gallery/Main Area/CC
8# the_gallery/Main Area/WORDS
9# the_gallery/Main Area/WONDROUS
10# the_great/West Side/CC
11# the_great/Back Area/UNKEMPT
12# the_hinterlands/Main Area/LEFT
13# the_hinterlands/Main Area/RIGHT
14# the_liberated/Painting Room/PYRAMID
15# the_literate/Painting Room/PYRAMID
16# the_partial/Control Center Entrance/CC
17# the_perceptive/Main Area/CC
18# cc -> relentless (don't use port objects)
19# the_repetitive/Main Room/CC
20# cc <-> the shop (keyholder door only needed one way)
21# the_sun_temple/Entrance/UNKEMPT
22# the_unyielding/Central Connected Area/BACK (panel)
23# daedalus/roof -> icarus 2# daedalus/roof -> icarus
24# daedalus/Unkempt Entrance/UNKEMPT
25# daedalus/Wonderland/WONDROUS
26# the_tenacious/Control Center Entrance/CC
27# the_tree/Main Area/UNKEMPT
28connections { 3connections {
29 from { 4 from {
30 port { 5 port {
@@ -45,7 +20,7 @@ connections {
45 from { 20 from {
46 port { 21 port {
47 map: "the_entry" 22 map: "the_entry"
48 room: "Flipped Second Room" 23 room: "Four Rooms Entrance"
49 name: "FOUR" 24 name: "FOUR"
50 } 25 }
51 } 26 }
@@ -166,7 +141,7 @@ connections {
166 to { 141 to {
167 port { 142 port {
168 map: "the_darkroom" 143 map: "the_darkroom"
169 room: "First Room" 144 room: "Cyan Hallway"
170 name: "COLORFUL" 145 name: "COLORFUL"
171 } 146 }
172 } 147 }
@@ -182,7 +157,7 @@ connections {
182 to { 157 to {
183 port { 158 port {
184 map: "the_darkroom" 159 map: "the_darkroom"
185 room: "Second Room" 160 room: "Congruent Entrance"
186 name: "CONGRUENT" 161 name: "CONGRUENT"
187 } 162 }
188 } 163 }
@@ -258,7 +233,7 @@ connections {
258 from { 233 from {
259 port { 234 port {
260 map: "the_darkroom" 235 map: "the_darkroom"
261 room: "First Room" 236 room: "Double Sided Entrance"
262 name: "DOUBLESIDED" 237 name: "DOUBLESIDED"
263 } 238 }
264 } 239 }
@@ -333,6 +308,23 @@ connections {
333 name: "GALLERY" 308 name: "GALLERY"
334 } 309 }
335 } 310 }
311 oneway: true
312}
313connections {
314 from {
315 port {
316 map: "the_butterfly"
317 room: "Main Area"
318 name: "GALLERY"
319 }
320 }
321 to {
322 room {
323 map: "the_gallery"
324 name: "Main Area"
325 }
326 }
327 oneway: true
336} 328}
337connections { 329connections {
338 from { 330 from {
@@ -643,7 +635,7 @@ connections {
643 from { 635 from {
644 port { 636 port {
645 map: "the_entry" 637 map: "the_entry"
646 room: "Link Area" 638 room: "Liberated Entrance"
647 name: "BLUE" 639 name: "BLUE"
648 } 640 }
649 } 641 }
@@ -691,7 +683,7 @@ connections {
691 from { 683 from {
692 port { 684 port {
693 map: "the_entry" 685 map: "the_entry"
694 room: "Link Area" 686 room: "Literate Entrance"
695 name: "BROWN" 687 name: "BROWN"
696 } 688 }
697 } 689 }
@@ -739,7 +731,7 @@ connections {
739 from { 731 from {
740 port { 732 port {
741 map: "the_orb" 733 map: "the_orb"
742 room: "B Room" 734 room: "Middle Room"
743 name: "MID" 735 name: "MID"
744 } 736 }
745 } 737 }
@@ -866,6 +858,8 @@ connections {
866 } 858 }
867 oneway: true 859 oneway: true
868} 860}
861# Two one-way connections because the CLUE panel only needs to be solved to
862# go from The Great to The Partial.
869connections { 863connections {
870 from { 864 from {
871 port { 865 port {
@@ -881,6 +875,25 @@ connections {
881 name: "GREAT" 875 name: "GREAT"
882 } 876 }
883 } 877 }
878 oneway: true
879}
880connections {
881 from {
882 port {
883 map: "the_partial"
884 room: "Obverse Side"
885 name: "GREAT"
886 }
887 }
888 to {
889 port {
890 map: "the_great"
891 room: "West Side"
892 name: "PARTIAL"
893 }
894 }
895 oneway: true
896 bypass_target_door: true
884} 897}
885connections { 898connections {
886 from { 899 from {
@@ -950,7 +963,7 @@ connections {
950 from { 963 from {
951 port { 964 port {
952 map: "the_entry" 965 map: "the_entry"
953 room: "Lime Room" 966 room: "Revitalized Entrance"
954 name: "REVITALIZED" 967 name: "REVITALIZED"
955 } 968 }
956 } 969 }
@@ -1218,6 +1231,7 @@ connections {
1218 } 1231 }
1219 } 1232 }
1220 oneway: true 1233 oneway: true
1234 roof_access: true
1221} 1235}
1222connections { 1236connections {
1223 from { 1237 from {
@@ -1423,7 +1437,7 @@ connections {
1423 to { 1437 to {
1424 room { 1438 room {
1425 map: "daedalus" 1439 map: "daedalus"
1426 name: "Roof" 1440 name: "Castle"
1427 } 1441 }
1428 } 1442 }
1429 oneway: true 1443 oneway: true
@@ -1459,7 +1473,6 @@ connections {
1459 name: "GREAT" 1473 name: "GREAT"
1460 } 1474 }
1461 } 1475 }
1462 door { map: "the_great" name: "Daedalus Entrance" }
1463 oneway: true 1476 oneway: true
1464} 1477}
1465connections { 1478connections {
@@ -1478,6 +1491,7 @@ connections {
1478 } 1491 }
1479 } 1492 }
1480 oneway: true 1493 oneway: true
1494 bypass_target_door: true
1481} 1495}
1482connections { 1496connections {
1483 from { 1497 from {
@@ -1773,12 +1787,13 @@ connections {
1773 } 1787 }
1774 } 1788 }
1775 oneway: true 1789 oneway: true
1790 bypass_target_door: true
1776} 1791}
1777connections { 1792connections {
1778 from { 1793 from {
1779 port { 1794 port {
1780 map: "the_bearer" 1795 map: "the_bearer"
1781 room: "Back Area" 1796 room: "Tree Entrance"
1782 name: "TREE" 1797 name: "TREE"
1783 } 1798 }
1784 } 1799 }
@@ -1854,3 +1869,595 @@ connections {
1854 } 1869 }
1855 } 1870 }
1856} 1871}
1872connections {
1873 from {
1874 port {
1875 map: "the_great"
1876 room: "Back Area"
1877 name: "UNKEMPT"
1878 }
1879 }
1880 to {
1881 port {
1882 map: "the_unkempt"
1883 room: "Main Area"
1884 name: "GREAT"
1885 }
1886 }
1887}
1888connections {
1889 # Two one-way connections because the door only blocks one direction.
1890 from {
1891 port {
1892 map: "the_unkempt"
1893 room: "Main Area"
1894 name: "SUNTEMPLE"
1895 }
1896 }
1897 to {
1898 port {
1899 map: "the_sun_temple"
1900 room: "Entrance"
1901 name: "UNKEMPT"
1902 }
1903 }
1904 oneway: true
1905}
1906connections {
1907 from {
1908 port {
1909 map: "the_sun_temple"
1910 room: "Entrance"
1911 name: "UNKEMPT"
1912 }
1913 }
1914 to {
1915 port {
1916 map: "the_unkempt"
1917 room: "Main Area"
1918 name: "SUNTEMPLE"
1919 }
1920 }
1921 oneway: true
1922 bypass_target_door: true
1923}
1924connections {
1925 from {
1926 port {
1927 map: "the_unkempt"
1928 room: "Daedalus Entrance"
1929 name: "DAEDALUS"
1930 }
1931 }
1932 to {
1933 port {
1934 map: "daedalus"
1935 room: "Unkempt Entrance"
1936 name: "UNKEMPT"
1937 }
1938 }
1939}
1940connections {
1941 from {
1942 port {
1943 map: "the_unkempt"
1944 room: "Main Area"
1945 name: "TREE"
1946 }
1947 }
1948 to {
1949 port {
1950 map: "the_tree"
1951 room: "Main Area"
1952 name: "UNKEMPT"
1953 }
1954 }
1955}
1956connections {
1957 from {
1958 painting {
1959 map: "the_entry"
1960 room: "Link Area"
1961 name: "PYRAMID"
1962 }
1963 }
1964 to {
1965 room {
1966 map: "the_wise"
1967 name: "Entry"
1968 }
1969 }
1970 oneway: true
1971}
1972connections {
1973 from {
1974 painting {
1975 map: "the_gallery"
1976 room: "Main Area"
1977 name: "WISE"
1978 }
1979 }
1980 to {
1981 room {
1982 map: "the_wise"
1983 name: "Entry"
1984 }
1985 }
1986 oneway: true
1987}
1988connections {
1989 from {
1990 painting {
1991 map: "the_liberated"
1992 room: "Painting Room"
1993 name: "PYRAMID"
1994 }
1995 }
1996 to {
1997 room {
1998 map: "the_wise"
1999 name: "Entry"
2000 }
2001 }
2002 oneway: true
2003}
2004connections {
2005 from {
2006 painting {
2007 map: "the_literate"
2008 room: "Painting Room"
2009 name: "PYRAMID"
2010 }
2011 }
2012 to {
2013 room {
2014 map: "the_wise"
2015 name: "Entry"
2016 }
2017 }
2018 oneway: true
2019}
2020connections {
2021 from {
2022 painting {
2023 map: "the_wise"
2024 room: "Entry"
2025 name: "TRIANGLE"
2026 }
2027 }
2028 to {
2029 room {
2030 map: "the_gallery"
2031 name: "Main Area"
2032 }
2033 }
2034 oneway: true
2035}
2036connections {
2037 from {
2038 room {
2039 map: "the_wondrous"
2040 name: "Huge"
2041 }
2042 }
2043 to {
2044 room {
2045 map: "the_door"
2046 name: "Main Area"
2047 }
2048 }
2049 door {
2050 map: "the_wondrous"
2051 name: "Big Door"
2052 }
2053 oneway: true
2054}
2055connections {
2056 from {
2057 painting {
2058 map: "the_gallery"
2059 room: "Main Area"
2060 name: "WONDROUS"
2061 }
2062 }
2063 to {
2064 room {
2065 map: "the_wondrous"
2066 name: "Huge"
2067 }
2068 }
2069 oneway: true
2070}
2071connections {
2072 from {
2073 port {
2074 map: "daedalus"
2075 room: "Wonderland"
2076 name: "WONDROUS"
2077 }
2078 }
2079 to {
2080 port {
2081 map: "the_wondrous"
2082 room: "Entry"
2083 name: "DAEDALUS"
2084 }
2085 }
2086}
2087connections {
2088 from {
2089 panel {
2090 map: "the_entry"
2091 room: "Starting Room"
2092 name: "HI"
2093 answer: "thewords"
2094 }
2095 }
2096 to {
2097 room {
2098 map: "the_words"
2099 name: "Main Area"
2100 }
2101 }
2102 oneway: true
2103}
2104connections {
2105 from {
2106 port {
2107 map: "the_words"
2108 room: "Main Area"
2109 name: "ENTRY"
2110 }
2111 }
2112 to {
2113 room {
2114 map: "the_entry"
2115 name: "Starting Room"
2116 }
2117 }
2118 oneway: true
2119}
2120connections {
2121 from {
2122 painting {
2123 map: "the_gallery"
2124 room: "Main Area"
2125 name: "WORDS"
2126 }
2127 }
2128 to {
2129 room {
2130 map: "the_words"
2131 name: "Main Area"
2132 }
2133 }
2134 oneway: true
2135}
2136connections {
2137 from {
2138 room {
2139 map: "control_center"
2140 name: "Main Area"
2141 }
2142 }
2143 to {
2144 room {
2145 map: "the_relentless"
2146 name: "Turn Room"
2147 }
2148 }
2149 door {
2150 map: "control_center"
2151 name: "Relentless Turn Door"
2152 }
2153}
2154connections {
2155 from {
2156 room {
2157 map: "control_center"
2158 name: "Main Area"
2159 }
2160 }
2161 to {
2162 room {
2163 map: "the_relentless"
2164 name: "Shop Room"
2165 }
2166 }
2167 door {
2168 map: "control_center"
2169 name: "Relentless Shop Door"
2170 }
2171}
2172connections {
2173 from {
2174 room {
2175 map: "control_center"
2176 name: "Main Area"
2177 }
2178 }
2179 to {
2180 room {
2181 map: "the_relentless"
2182 name: "Left Room"
2183 }
2184 }
2185 door {
2186 map: "control_center"
2187 name: "Relentless Left Door"
2188 }
2189}
2190connections {
2191 from {
2192 port {
2193 map: "control_center"
2194 room: "Ancient Entrance"
2195 name: "ANCIENT"
2196 }
2197 }
2198 to {
2199 room {
2200 map: "the_ancient"
2201 name: "Outside"
2202 }
2203 }
2204 oneway: true
2205}
2206connections {
2207 from {
2208 port {
2209 map: "the_between"
2210 room: "Control Center Side"
2211 name: "CC"
2212 }
2213 }
2214 to {
2215 port {
2216 map: "control_center"
2217 room: "Between Entrance"
2218 name: "BETWEEN"
2219 }
2220 }
2221}
2222connections {
2223 from {
2224 painting {
2225 map: "the_gallery"
2226 room: "Main Area"
2227 name: "CC"
2228 }
2229 }
2230 to {
2231 room {
2232 map: "control_center"
2233 name: "Desert Room"
2234 }
2235 }
2236 oneway: true
2237}
2238connections {
2239 from {
2240 port {
2241 map: "the_great"
2242 room: "West Side"
2243 name: "CC"
2244 }
2245 }
2246 to {
2247 port {
2248 map: "control_center"
2249 room: "Entry"
2250 name: "GREAT"
2251 }
2252 }
2253}
2254connections {
2255 from {
2256 port {
2257 map: "the_hinterlands"
2258 room: "Main Area"
2259 name: "LEFT"
2260 }
2261 }
2262 to {
2263 port {
2264 map: "control_center"
2265 room: "Main Area"
2266 name: "LEFT"
2267 }
2268 }
2269}
2270connections {
2271 from {
2272 port {
2273 map: "the_hinterlands"
2274 room: "Main Area"
2275 name: "RIGHT"
2276 }
2277 }
2278 to {
2279 port {
2280 map: "control_center"
2281 room: "Main Area"
2282 name: "RIGHT"
2283 }
2284 }
2285}
2286connections {
2287 from {
2288 port {
2289 map: "the_partial"
2290 room: "Control Center Entrance"
2291 name: "CC"
2292 }
2293 }
2294 to {
2295 port {
2296 map: "control_center"
2297 room: "Partial Entrance"
2298 name: "PARTIAL"
2299 }
2300 }
2301}
2302connections {
2303 from {
2304 port {
2305 map: "the_perceptive"
2306 room: "Main Area"
2307 name: "CC"
2308 }
2309 }
2310 to {
2311 port {
2312 map: "control_center"
2313 room: "Perceptive Entrance"
2314 name: "PERCEPTIVE"
2315 }
2316 }
2317}
2318connections {
2319 from {
2320 port {
2321 map: "the_repetitive"
2322 room: "Main Room"
2323 name: "CC"
2324 }
2325 }
2326 to {
2327 port {
2328 map: "control_center"
2329 room: "Repetitive Entrance"
2330 name: "REPETITIVE"
2331 }
2332 }
2333}
2334connections {
2335 from {
2336 room {
2337 map: "the_shop"
2338 name: "Main Area"
2339 }
2340 }
2341 to {
2342 room {
2343 map: "control_center"
2344 name: "Shop Entrance"
2345 }
2346 }
2347 door {
2348 map: "the_shop"
2349 name: "N Entered"
2350 }
2351 oneway: true
2352}
2353connections {
2354 from {
2355 room {
2356 map: "control_center"
2357 name: "Shop Entrance"
2358 }
2359 }
2360 to {
2361 room {
2362 map: "the_shop"
2363 name: "Main Area"
2364 }
2365 }
2366 oneway: true
2367}
2368connections {
2369 from {
2370 panel {
2371 map: "the_unyielding"
2372 room: "Central Connected Area"
2373 name: "BACK"
2374 }
2375 }
2376 to {
2377 panel {
2378 map: "control_center"
2379 room: "Unyielding Entrance"
2380 name: "FORTH"
2381 }
2382 }
2383}
2384connections {
2385 from {
2386 port {
2387 map: "the_tenacious"
2388 room: "Control Center Entrance"
2389 name: "CC"
2390 }
2391 }
2392 to {
2393 port {
2394 map: "control_center"
2395 room: "Tenacious Entrance"
2396 name: "TENACIOUS"
2397 }
2398 }
2399}
2400connections {
2401 from {
2402 port {
2403 map: "the_unkempt"
2404 room: "Control Center Entrance"
2405 name: "CC"
2406 }
2407 }
2408 to {
2409 port {
2410 map: "control_center"
2411 room: "Unkempt Entrance"
2412 name: "UNKEMPT"
2413 }
2414 }
2415}
2416connections {
2417 from {
2418 panel {
2419 map: "control_center"
2420 room: "Stormy Entrance"
2421 name: "TURN"
2422 }
2423 }
2424 to {
2425 room {
2426 map: "the_stormy"
2427 name: "Center"
2428 }
2429 }
2430 oneway: true
2431}
2432connections {
2433 from {
2434 port {
2435 map: "the_entry"
2436 room: "X Area"
2437 name: "CC"
2438 }
2439 }
2440 to {
2441 port {
2442 map: "control_center"
2443 room: "Entry Entrance"
2444 name: "ENTRY"
2445 }
2446 }
2447}
2448connections {
2449 from {
2450 painting {
2451 map: "the_entry"
2452 room: "Eye Room"
2453 name: "GALLERY"
2454 }
2455 }
2456 to {
2457 room {
2458 map: "the_gallery"
2459 name: "Main Area"
2460 }
2461 }
2462 oneway: true
2463}
diff --git a/data/door_groups.txtpb b/data/door_groups.txtpb new file mode 100644 index 0000000..ca94223 --- /dev/null +++ b/data/door_groups.txtpb
@@ -0,0 +1,163 @@
1door_groups {
2 name: "The Entry - Repetitive Entrance"
3 # This *should* be a CONNECTOR, but currently we're not shuffling these
4 # entrances because we want to guarantee that there's a way to The Repetitive
5 # without missing keys in vanilla doors. Hopefully can be changed eventually.
6 type: SHUFFLE_GROUP
7 doors {
8 map: "the_entry"
9 name: "Starting Room West Wall North Door"
10 }
11 doors {
12 map: "the_repetitive"
13 name: "Entry Entrance"
14 }
15}
16door_groups {
17 name: "The Repetitive - Plaza Entrance"
18 type: CONNECTOR
19 doors {
20 map: "the_repetitive"
21 name: "Black Hallway"
22 }
23 doors {
24 map: "the_plaza"
25 name: "Repetitive Entrance"
26 }
27}
28door_groups {
29 name: "Control Center White Doors"
30 type: COLOR_CONNECTOR
31 doors {
32 map: "daedalus"
33 name: "White Hallway From Entry"
34 }
35 doors {
36 map: "the_entry"
37 name: "Control Center White Door"
38 }
39}
40door_groups {
41 name: "Control Center Purple Doors"
42 type: COLOR_CONNECTOR
43 doors {
44 map: "daedalus"
45 name: "Purple Hallway From Great"
46 }
47 doors {
48 map: "the_great"
49 name: "Control Center Purple Door"
50 }
51}
52door_groups {
53 name: "Control Center Orange Doors"
54 type: COLOR_CONNECTOR
55 doors {
56 map: "daedalus"
57 name: "Control Center Orange Door"
58 }
59 doors {
60 map: "the_unkempt"
61 name: "Control Center Orange Door"
62 }
63}
64door_groups {
65 name: "Control Center Brown Doors"
66 type: COLOR_CONNECTOR
67 doors {
68 map: "the_bearer"
69 name: "Control Center Brown Door"
70 }
71 doors {
72 map: "the_tree"
73 name: "Control Center Brown Door"
74 }
75}
76door_groups {
77 name: "Control Center Blue Doors"
78 type: COLOR_CONNECTOR
79 doors {
80 map: "the_digital"
81 name: "Control Center Blue Door"
82 }
83 doors {
84 map: "the_unyielding"
85 name: "Digital Entrance"
86 }
87}
88door_groups {
89 name: "Cyan Doors"
90 type: CYAN_DOORS
91 doors {
92 map: "daedalus"
93 name: "Eye Painting"
94 }
95 doors {
96 map: "the_bearer"
97 name: "Butterfly Entrance"
98 }
99 doors {
100 map: "the_darkroom"
101 name: "Double Letter Panel Blockers"
102 }
103 doors {
104 map: "the_entry"
105 name: "Starting Room West Wall North Door"
106 }
107 doors {
108 map: "the_entry"
109 name: "Flipped Pyramid Area Entrance"
110 }
111 doors {
112 map: "the_entry"
113 name: "Near D Room Painting"
114 }
115 doors {
116 map: "the_graveyard"
117 name: "Double Letters"
118 }
119 doors {
120 map: "the_great"
121 name: "Tower Entrance"
122 }
123 doors {
124 map: "the_great"
125 name: "Cyan Doors"
126 }
127 doors {
128 map: "the_parthenon"
129 name: "Double Letters"
130 }
131 doors {
132 map: "the_unkempt"
133 name: "Cyan Doors"
134 }
135 doors {
136 map: "the_unkempt"
137 name: "Control Center Orange Door"
138 }
139 doors {
140 map: "the_unyielding"
141 name: "Cyan Doors"
142 }
143}
144door_groups {
145 name: "Lavender Cubes"
146 type: SHUFFLE_GROUP
147 doors {
148 map: "daedalus"
149 name: "C Keyholder Blocker"
150 }
151 doors {
152 map: "the_congruent"
153 name: "T Keyholder Blocker"
154 }
155 doors {
156 map: "the_great"
157 name: "Lavender Cube"
158 }
159 doors {
160 map: "the_parthenon"
161 name: "Lavender Cubes"
162 }
163}
diff --git a/data/ids.yaml b/data/ids.yaml index 9c5f4eb..80ace1a 100644 --- a/data/ids.yaml +++ b/data/ids.yaml
@@ -1,4 +1,66 @@
1maps: 1maps:
2 control_center:
3 rooms:
4 Between Entrance:
5 panels:
6 RIGHT: 2721
7 Desert Room:
8 panels:
9 LESS: 2722
10 Entry:
11 panels:
12 HELLO: 2724
13 Entry Entrance:
14 panels:
15 ENTRY: 2723
16 Hide Room:
17 panels:
18 HIDE: 2725
19 Main Area:
20 panels:
21 COLOR: 2726
22 Letters: 2727
23 keyholders:
24 1: 2760
25 2: 2761
26 3: 2762
27 4: 2763
28 Partial Entrance:
29 panels:
30 PARTIAL: 2729
31 Perceptive Entrance:
32 panels:
33 COLORS: 2731
34 PART: 2730
35 Shop Entrance:
36 panels:
37 HOPS: 2732
38 Stormy Entrance:
39 panels:
40 TURN: 2733
41 Tenacious Entrance:
42 panels:
43 HERO: 2734
44 Unkempt Entrance:
45 panels:
46 RETURN: 2735
47 Unyielding Entrance:
48 panels:
49 FORTH: 2736
50 SEEK: 2737
51 doors:
52 Ancient Entrance: 2715
53 Between Door: 2716
54 Desert Door: 2717
55 Front Door: 2709
56 Partial Door: 2713
57 Repetitive Entrance: 2714
58 Shop Door: 2718
59 Stormy Entrance: 2710
60 Tenacious Door: 2719
61 Unkempt Door: 2712
62 Unyielding Door: 2720
63 X1 Door: 2711
2 daedalus: 64 daedalus:
3 rooms: 65 rooms:
4 After Bee Room: 66 After Bee Room:
@@ -98,6 +160,9 @@ maps:
98 Brown Smiley: 160 Brown Smiley:
99 panels: 161 panels:
100 OTHERS: 1667 162 OTHERS: 1667
163 C Keyholder:
164 keyholders:
165 C: 2755
101 Castle: 166 Castle:
102 panels: 167 panels:
103 FIVE (Blue): 1673 168 FIVE (Blue): 1673
@@ -208,6 +273,9 @@ maps:
208 SUMMER: 1754 273 SUMMER: 1754
209 WORD: 1753 274 WORD: 1753
210 WORDWORD: 1761 275 WORDWORD: 1761
276 D Keyholder:
277 keyholders:
278 D: 2759
211 Dark Light Exit: 279 Dark Light Exit:
212 panels: 280 panels:
213 GASKET: 1763 281 GASKET: 1763
@@ -230,6 +298,9 @@ maps:
230 Eye Painting: 298 Eye Painting:
231 panels: 299 panels:
232 REVILED: 1777 300 REVILED: 1777
301 F Keyholder:
302 keyholders:
303 F: 2756
233 F2 Room: 304 F2 Room:
234 panels: 305 panels:
235 CAST: 1782 306 CAST: 1782
@@ -423,6 +494,8 @@ maps:
423 panels: 494 panels:
424 GOING: 1934 495 GOING: 1934
425 TURN: 1935 496 TURN: 1935
497 keyholders:
498 G: 2757
426 Nursery: 499 Nursery:
427 panels: 500 panels:
428 "?": 1937 501 "?": 1937
@@ -490,6 +563,8 @@ maps:
490 WALLS: 1986 563 WALLS: 1986
491 WHISPER: 1978 564 WHISPER: 1978
492 WING: 1979 565 WING: 1979
566 keyholders:
567 H: 2758
493 Outside Magic Room: 568 Outside Magic Room:
494 panels: 569 panels:
495 WIZARD: 1988 570 WIZARD: 1988
@@ -673,7 +748,7 @@ maps:
673 Back (2): 2090 748 Back (2): 2090
674 Colors: 2097 749 Colors: 2097
675 FIR: 2095 750 FIR: 2095
676 Left: 2088 751 Near Obscured Puzzles: 2088
677 OAK: 2093 752 OAK: 2093
678 PINE: 2094 753 PINE: 2094
679 WALK BACK: 2091 754 WALK BACK: 2091
@@ -822,7 +897,6 @@ maps:
822 REDACTED: 2274 897 REDACTED: 2274
823 STRINGS: 2205 898 STRINGS: 2205
824 WINDS: 2204 899 WINDS: 2204
825 "[REDACTED]": 2207
826 Yellow Color Door: 900 Yellow Color Door:
827 panels: 901 panels:
828 Paintings: 2210 902 Paintings: 2210
@@ -913,7 +987,6 @@ maps:
913 Blue Rainbow Room: 1538 987 Blue Rainbow Room: 1538
914 Blue Room: 1477 988 Blue Room: 1477
915 Blue Room Entrance: 1476 989 Blue Room Entrance: 1476
916 Blue Smiley Entrance: 1478
917 Blue Smiley Exit To Red: 1547 990 Blue Smiley Exit To Red: 1547
918 Book Room Entrance: 1588 991 Book Room Entrance: 1588
919 Book Room Exit: 1592 992 Book Room Exit: 1592
@@ -941,12 +1014,13 @@ maps:
941 Dark Light Room Exit: 1570 1014 Dark Light Room Exit: 1570
942 Dark Light Room Exit Panel: 1571 1015 Dark Light Room Exit Panel: 1571
943 Entry Shortcut Secret Exit: 1437 1016 Entry Shortcut Secret Exit: 1437
1017 Eye Painting: 2751
944 Eye Painting Exit: 1446 1018 Eye Painting Exit: 1446
945 F Keyholder Door: 1551 1019 F Keyholder Door: 1551
946 F2 Room Back Left Door: 1491 1020 F2 Room Northwest Door: 1491
947 F2 Room Back Middle Door: 1492 1021 F2 Room Southeast Door: 1487
948 F2 Room Back Right Door: 1490 1022 F2 Room Southwest Door: 1490
949 F2 Room Entrance: 1487 1023 F2 Room West Door: 1492
950 Flip Painting Blocker: 1552 1024 Flip Painting Blocker: 1552
951 Globe Room East Door: 1589 1025 Globe Room East Door: 1589
952 Globe Room South Door: 1591 1026 Globe Room South Door: 1591
@@ -969,6 +1043,7 @@ maps:
969 House Entrance: 1495 1043 House Entrance: 1495
970 House Side Door: 1566 1044 House Side Door: 1566
971 Intense Room Entrance: 1522 1045 Intense Room Entrance: 1522
1046 Lime Hexes: 2810
972 Magenta Hexes: 2272 1047 Magenta Hexes: 2272
973 Magic Room Entrance: 1500 1048 Magic Room Entrance: 1500
974 Magic Room Panels: 1499 1049 Magic Room Panels: 1499
@@ -980,7 +1055,9 @@ maps:
980 Near Sweet Blue Door: 1573 1055 Near Sweet Blue Door: 1573
981 Near Sweet Brown Door: 1561 1056 Near Sweet Brown Door: 1561
982 Near Yellow Room Door: 1565 1057 Near Yellow Room Door: 1565
983 O2 Room Back Door: 1485 1058 North Castle Panel: 2742
1059 O2 Room Northeast Door: 1485
1060 O2 Room Southeast Door: 1478
984 Orange Rainbow Panel: 2267 1061 Orange Rainbow Panel: 2267
985 Orange Rainbow Room: 1535 1062 Orange Rainbow Room: 1535
986 Orange Room: 1507 1063 Orange Room: 1507
@@ -1007,6 +1084,7 @@ maps:
1007 Purple NW Vestibule: 1459 1084 Purple NW Vestibule: 1459
1008 Purple Rainbow Panel: 2271 1085 Purple Rainbow Panel: 2271
1009 Purple Rainbow Room: 1539 1086 Purple Rainbow Room: 1539
1087 Purple Room: 2741
1010 Purple Room East Entrance: 1472 1088 Purple Room East Entrance: 1472
1011 Purple Room North Entrance: 1469 1089 Purple Room North Entrance: 1469
1012 Purple Room South Entrance: 1470 1090 Purple Room South Entrance: 1470
@@ -1031,9 +1109,10 @@ maps:
1031 Snake Room Entrance: 1514 1109 Snake Room Entrance: 1514
1032 South Castle Area Back Door: 1574 1110 South Castle Area Back Door: 1574
1033 South Castle Area Entrance: 1575 1111 South Castle Area Entrance: 1575
1112 South Castle Panel: 2744
1034 Southwest Area Intersection: 1475 1113 Southwest Area Intersection: 1475
1035 Splintering Exit Left Door: 1449 1114 Splintering Exit North Door: 1449
1036 Splintering Exit Right Door: 1450 1115 Splintering Exit South Door: 1450
1037 Starting Room East Wall Center Door: 1439 1116 Starting Room East Wall Center Door: 1439
1038 Starting Room East Wall North Door: 1440 1117 Starting Room East Wall North Door: 1440
1039 Starting Room North Wall Center Door: 1432 1118 Starting Room North Wall Center Door: 1432
@@ -1046,15 +1125,17 @@ maps:
1046 Starting Room West Wall South Door: 1433 1125 Starting Room West Wall South Door: 1433
1047 Sticks And Stones Door: 1593 1126 Sticks And Stones Door: 1593
1048 Temple of the Eyes Entrance: 1444 1127 Temple of the Eyes Entrance: 1444
1049 U2 Room Back Door: 1497 1128 Theo Panels: 2811
1050 U2 Room Back Right Door: 1496 1129 U2 Room East Door: 1498
1051 U2 Room Entrance: 1498 1130 U2 Room Southeast Door: 1493
1052 U2 Room Shortcut: 1493 1131 U2 Room Southwest Door: 1496
1132 U2 Room West Door: 1497
1053 Welcome Back Door: 1435 1133 Welcome Back Door: 1435
1054 Welcome Back Secret Door: 1434 1134 Welcome Back Secret Door: 1434
1135 West Castle Panel: 2743
1055 White Hallway From Entry: 1488 1136 White Hallway From Entry: 1488
1056 Wonderland Left Door: 1520 1137 Wonderland North Door: 1520
1057 Wonderland Right Door: 1504 1138 Wonderland South Door: 1504
1058 Yellow Rainbow Panel: 2268 1139 Yellow Rainbow Panel: 2268
1059 Yellow Rainbow Room: 1536 1140 Yellow Rainbow Room: 1536
1060 Yellow Room: 1568 1141 Yellow Room: 1568
@@ -1098,6 +1179,9 @@ maps:
1098 SWAY: 24 1179 SWAY: 24
1099 TERROR: 20 1180 TERROR: 20
1100 TURN: 22 1181 TURN: 22
1182 Keyholder Room:
1183 keyholders:
1184 A: 2773
1101 Synonyms Room: 1185 Synonyms Room:
1102 panels: 1186 panels:
1103 ADORE: 26 1187 ADORE: 26
@@ -1121,7 +1205,7 @@ maps:
1121 doors: 1205 doors:
1122 A2 Door: 4 1206 A2 Door: 4
1123 Examples Door: 1 1207 Examples Door: 1
1124 Intensify Door: 0 1208 Intensify Door: 2739
1125 Keyholder Door: 5 1209 Keyholder Door: 5
1126 Synonyms Door: 2 1210 Synonyms Door: 2
1127 Time Door: 3 1211 Time Door: 3
@@ -1134,7 +1218,6 @@ maps:
1134 panels: 1218 panels:
1135 THIS: 45 1219 THIS: 45
1136 doors: 1220 doors:
1137 End Door: 42
1138 Front Door: 41 1221 Front Door: 41
1139 Lavender Cubes: 43 1222 Lavender Cubes: 43
1140 the_bearer: 1223 the_bearer:
@@ -1215,7 +1298,6 @@ maps:
1215 Control Center Brown Door: 49 1298 Control Center Brown Door: 49
1216 Exit Door: 47 1299 Exit Door: 47
1217 Overlook Door: 46 1300 Overlook Door: 46
1218 Q2 Door: 48
1219 the_between: 1301 the_between:
1220 rooms: 1302 rooms:
1221 Control Center Side: 1303 Control Center Side:
@@ -1390,6 +1472,9 @@ maps:
1390 panels: 1472 panels:
1391 CIVIL: 216 1473 CIVIL: 216
1392 CRABS: 217 1474 CRABS: 217
1475 T Keyholder:
1476 keyholders:
1477 T: 2754
1393 doors: 1478 doors:
1394 C Keyholder Blocker: 176 1479 C Keyholder Blocker: 176
1395 C2 Door: 177 1480 C2 Door: 177
@@ -1401,7 +1486,6 @@ maps:
1401 Obverse Magenta Door: 173 1486 Obverse Magenta Door: 173
1402 Obverse Yellow Door: 178 1487 Obverse Yellow Door: 178
1403 Obverse Yellow Puzzles: 179 1488 Obverse Yellow Puzzles: 179
1404 T Keyholder Blocker: 183
1405 the_darkroom: 1489 the_darkroom:
1406 rooms: 1490 rooms:
1407 First Room: 1491 First Room:
@@ -1432,9 +1516,7 @@ maps:
1432 doors: 1516 doors:
1433 Colorful Entrance: 222 1517 Colorful Entrance: 222
1434 Congruent Entrance: 223 1518 Congruent Entrance: 223
1435 Double Letter Panel Blockers: 218
1436 Double Sided Entrance: 224 1519 Double Sided Entrance: 224
1437 S1 Door: 221
1438 Second Room Entrance: 219 1520 Second Room Entrance: 219
1439 Third Room Entrance: 220 1521 Third Room Entrance: 220
1440 the_digital: 1522 the_digital:
@@ -1594,6 +1676,10 @@ maps:
1594 Rabbit Hole: 1676 Rabbit Hole:
1595 panels: 1677 panels:
1596 PUZZLE: 364 1678 PUZZLE: 364
1679 Rabbit Hole Lock:
1680 panels:
1681 HOLE: 2749
1682 RABBIT: 2748
1597 Red Alcove: 1683 Red Alcove:
1598 panels: 1684 panels:
1599 BROW: 365 1685 BROW: 365
@@ -1630,8 +1716,6 @@ maps:
1630 panels: 1716 panels:
1631 CORN: 393 1717 CORN: 393
1632 DICE: 392 1718 DICE: 392
1633 HOLE: 390
1634 RABBIT: 389
1635 WREATH: 391 1719 WREATH: 391
1636 doors: 1720 doors:
1637 Blue Alcove Entrance: 297 1721 Blue Alcove Entrance: 297
@@ -1643,7 +1727,6 @@ maps:
1643 D Room Entrance: 319 1727 D Room Entrance: 319
1644 Daedalus Entrance: 311 1728 Daedalus Entrance: 311
1645 Flip Area Entrance: 310 1729 Flip Area Entrance: 310
1646 Flipped Pyramid Area Entrance: 315
1647 Flipped Second Room Left Door: 300 1730 Flipped Second Room Left Door: 300
1648 Flipped Second Room Right Door: 299 1731 Flipped Second Room Right Door: 299
1649 Gallery Entrance: 321 1732 Gallery Entrance: 321
@@ -1661,13 +1744,13 @@ maps:
1661 Red Blue Area Left Door: 302 1744 Red Blue Area Left Door: 302
1662 Red Blue Area Right Door: 303 1745 Red Blue Area Right Door: 303
1663 Red Room Painting: 323 1746 Red Room Painting: 323
1664 Repetitive Entrance: 312
1665 Revitalized Entrance: 306 1747 Revitalized Entrance: 306
1666 Right Eye Entrance: 301 1748 Right Eye Entrance: 301
1667 Scarf Door: 296 1749 Scarf Door: 296
1668 Second Room Left Door: 298 1750 Second Room Left Door: 298
1669 Second Room Right Door: 290 1751 Second Room Right Door: 290
1670 Shop Entrance: 313 1752 Shop Entrance: 313
1753 Starting Room West Wall North Door: 2781
1671 Third Eye Painting: 324 1754 Third Eye Painting: 324
1672 Trick Door: 287 1755 Trick Door: 287
1673 Trick To Shop Door: 289 1756 Trick To Shop Door: 289
@@ -1694,6 +1777,8 @@ maps:
1694 X Plus: 1777 X Plus:
1695 panels: 1778 panels:
1696 ROSE: 405 1779 ROSE: 405
1780 keyholders:
1781 M: 2766
1697 X Plus Middle Leg: 1782 X Plus Middle Leg:
1698 panels: 1783 panels:
1699 COLONY: 403 1784 COLONY: 403
@@ -1723,6 +1808,9 @@ maps:
1723 Daedalus Extension: 1808 Daedalus Extension:
1724 panels: 1809 panels:
1725 WHERE: 433 1810 WHERE: 433
1811 Main Area:
1812 keyholders:
1813 P: 2765
1726 doors: 1814 doors:
1727 Ancient Painting: 428 1815 Ancient Painting: 428
1728 Between Painting: 414 1816 Between Painting: 414
@@ -1907,6 +1995,8 @@ maps:
1907 LAUGH FINISHED: 573 1995 LAUGH FINISHED: 573
1908 PLANTS: 570 1996 PLANTS: 570
1909 WEATHER: 568 1997 WEATHER: 568
1998 keyholders:
1999 X: 2770
1910 Outside Jail: 2000 Outside Jail:
1911 panels: 2001 panels:
1912 GUT: 575 2002 GUT: 575
@@ -1995,7 +2085,6 @@ maps:
1995 Into The Mouth Gravestone: 457 2085 Into The Mouth Gravestone: 457
1996 Invisible Entrance: 465 2086 Invisible Entrance: 465
1997 Jail Entrance: 451 2087 Jail Entrance: 451
1998 Lavender Cube: 469
1999 Magnet Room Entrance: 449 2088 Magnet Room Entrance: 449
2000 Nature Room Door: 466 2089 Nature Room Door: 466
2001 Nature Room Panels: 467 2090 Nature Room Panels: 467
@@ -2054,6 +2143,8 @@ maps:
2054 WAS: 631 2143 WAS: 631
2055 WINGS: 662 2144 WINGS: 662
2056 YELL: 636 2145 YELL: 636
2146 keyholders:
2147 B: 2769
2057 Mastery Room: 2148 Mastery Room:
2058 masteries: 2149 masteries:
2059 MASTERY: 666 2150 MASTERY: 666
@@ -2120,6 +2211,8 @@ maps:
2120 FLASHBACK: 705 2211 FLASHBACK: 705
2121 PUSH: 703 2212 PUSH: 703
2122 PUSHBACK: 702 2213 PUSHBACK: 702
2214 keyholders:
2215 J: 2772
2123 doors: 2216 doors:
2124 Side Door: 687 2217 Side Door: 687
2125 the_keen: 2218 the_keen:
@@ -2231,10 +2324,12 @@ maps:
2231 NAY: 774 2324 NAY: 774
2232 NIGH: 781 2325 NIGH: 781
2233 TORE: 787 2326 TORE: 787
2327 keyholders:
2328 S: 2767
2234 doors: 2329 doors:
2235 Left Room Puzzles: 763 2330 Blue Side Puzzles: 763
2236 Main Room Puzzles: 765 2331 Green Side Puzzles: 764
2237 Right Room Puzzles: 764 2332 Main Room Door: 2750
2238 the_orb: 2333 the_orb:
2239 rooms: 2334 rooms:
2240 Main Area: 2335 Main Area:
@@ -2261,6 +2356,7 @@ maps:
2261 COLOR: 823 2356 COLOR: 823
2262 ETCH: 837 2357 ETCH: 837
2263 FAINT: 821 2358 FAINT: 821
2359 FIZZLE: 2745
2264 HAD: 830 2360 HAD: 830
2265 HEAVY: 829 2361 HEAVY: 829
2266 LAY: 834 2362 LAY: 834
@@ -2293,11 +2389,10 @@ maps:
2293 panels: 2389 panels:
2294 CRUSH: 845 2390 CRUSH: 845
2295 RAY: 846 2391 RAY: 846
2296 R2C2.5 Bottom: 2392 R2C3 Bottom:
2297 panels: 2393 panels:
2298 BLACK: 849 2394 BLACK: 2747
2299 FIGMENT: 848 2395 FIGMENT: 2746
2300 FIZZLE: 847
2301 Z Room: 2396 Z Room:
2302 panels: 2397 panels:
2303 MAZE: 850 2398 MAZE: 850
@@ -2332,6 +2427,9 @@ maps:
2332 CLEOPATRA: 859 2427 CLEOPATRA: 859
2333 NAPOLEON: 860 2428 NAPOLEON: 860
2334 XERXES: 857 2429 XERXES: 857
2430 U Keyholder:
2431 keyholders:
2432 U: 2777
2335 doors: 2433 doors:
2336 K2 Door: 852 2434 K2 Door: 852
2337 the_partial: 2435 the_partial:
@@ -2355,6 +2453,8 @@ maps:
2355 TON: 878 2453 TON: 878
2356 TURN: 875 2454 TURN: 875
2357 UP: 870 2455 UP: 870
2456 keyholders:
2457 L: 2771
2358 Reverse Side: 2458 Reverse Side:
2359 panels: 2459 panels:
2360 BRO: 884 2460 BRO: 884
@@ -2459,20 +2559,23 @@ maps:
2459 TYPIST BEAR RIGHT WING: 968 2559 TYPIST BEAR RIGHT WING: 968
2460 WING: 950 2560 WING: 950
2461 doors: 2561 doors:
2462 Bottom Left Door: 894 2562 Northeast Door: 893
2463 Bottom Left Puzzles: 898 2563 Northeast Puzzles: 897
2464 Bottom Right Door: 895 2564 Northwest Door: 892
2465 Bottom Right Puzzles: 899 2565 Northwest Puzzles: 896
2466 Repetitive Entrance: 888 2566 Repetitive Entrance: 888
2467 Sirenic Entrance: 890 2567 Sirenic Entrance: 890
2568 Southeast Door: 895
2569 Southeast Puzzles: 899
2570 Southwest Door: 894
2571 Southwest Puzzles: 898
2468 Symbolic Entrance: 889 2572 Symbolic Entrance: 889
2469 Top Left Door: 892
2470 Top Left Puzzles: 896
2471 Top Right Door: 893
2472 Top Right Puzzles: 897
2473 Turtle Entrance: 891 2573 Turtle Entrance: 891
2474 the_quiet: 2574 the_quiet:
2475 rooms: 2575 rooms:
2576 Keyholder Room:
2577 keyholders:
2578 Q: 2778
2476 Main Area: 2579 Main Area:
2477 panels: 2580 panels:
2478 BEE: 979 2581 BEE: 979
@@ -2549,7 +2652,8 @@ maps:
2549 rooms: 2652 rooms:
2550 Anti Room: 2653 Anti Room:
2551 panels: 2654 panels:
2552 EYE: 1041 2655 EYE (1): 1041
2656 EYE (2): 2813
2553 HA (1): 1035 2657 HA (1): 1035
2554 HA (2): 1036 2658 HA (2): 1036
2555 HA (3): 1037 2659 HA (3): 1037
@@ -2656,7 +2760,9 @@ maps:
2656 W: 1117 2760 W: 1117
2657 ZEROING: 1118 2761 ZEROING: 1118
2658 doors: 2762 doors:
2763 Anti-Collectable: 2812
2659 Anti-Collectable Room: 1025 2764 Anti-Collectable Room: 1025
2765 Black Hallway: 2780
2660 Cyan Door: 1028 2766 Cyan Door: 1028
2661 Cyan Puzzles: 1032 2767 Cyan Puzzles: 1032
2662 Dot Area Entrance: 1026 2768 Dot Area Entrance: 1026
@@ -2665,7 +2771,6 @@ maps:
2665 Lime Puzzles: 1031 2771 Lime Puzzles: 1031
2666 Magenta Door: 1029 2772 Magenta Door: 1029
2667 Magenta Puzzles: 1033 2773 Magenta Puzzles: 1033
2668 Plaza Entrance: 1024
2669 Yellow Door: 1030 2774 Yellow Door: 1030
2670 Yellow Puzzles: 1034 2775 Yellow Puzzles: 1034
2671 the_revitalized: 2776 the_revitalized:
@@ -2719,6 +2824,8 @@ maps:
2719 STIM: 1148 2824 STIM: 1148
2720 STONE: 1142 2825 STONE: 1142
2721 TADPOLES: 1159 2826 TADPOLES: 1159
2827 keyholders:
2828 N: 2779
2722 doors: 2829 doors:
2723 Books Puzzles: 1136 2830 Books Puzzles: 1136
2724 Games Puzzles: 1137 2831 Games Puzzles: 1137
@@ -3029,22 +3136,15 @@ maps:
3029 panels: 3136 panels:
3030 WHOLE: 2426 3137 WHOLE: 2426
3031 doors: 3138 doors:
3032 Black Door: 2276
3033 Blue Door: 2278
3034 Green Door: 2279
3035 Main Area Fifth Row: 2290 3139 Main Area Fifth Row: 2290
3036 Main Area First Row: 2286 3140 Main Area First Row: 2286
3037 Main Area Fourth Row: 2289 3141 Main Area Fourth Row: 2289
3038 Main Area Second Row: 2287 3142 Main Area Second Row: 2287
3039 Main Area Third Row: 2288 3143 Main Area Third Row: 2288
3040 Orange Door: 2282
3041 Poetry Room Panels: 2285 3144 Poetry Room Panels: 2285
3042 Purple Door: 2281 3145 Tutorial Door: 2754
3043 Red Door: 2277
3044 Tutorial Panels: 2283 3146 Tutorial Panels: 2283
3045 Whirred Room Panels: 2284 3147 Whirred Room Panels: 2284
3046 White Door: 2275
3047 Yellow Door: 2280
3048 the_talented: 3148 the_talented:
3049 rooms: 3149 rooms:
3050 Back Room: 3150 Back Room:
@@ -3073,6 +3173,8 @@ maps:
3073 SWINE (Brown): 2446 3173 SWINE (Brown): 2446
3074 WIFE (Black): 2440 3174 WIFE (Black): 2440
3075 WIFE (Brown): 2447 3175 WIFE (Brown): 2447
3176 keyholders:
3177 Y: 2764
3076 doors: 3178 doors:
3077 Black Side Panels: 2427 3179 Black Side Panels: 2427
3078 Brown Side Panels: 2428 3180 Brown Side Panels: 2428
@@ -3085,6 +3187,9 @@ maps:
3085 Control Center Entrance: 3187 Control Center Entrance:
3086 panels: 3188 panels:
3087 ZERO: 2455 3189 ZERO: 2455
3190 Main Area:
3191 keyholders:
3192 K: 2768
3088 Mastery: 3193 Mastery:
3089 masteries: 3194 masteries:
3090 MASTERY: 2456 3195 MASTERY: 2456
@@ -3243,6 +3348,115 @@ maps:
3243 doors: 3348 doors:
3244 Control Center Brown Door: 2548 3349 Control Center Brown Door: 2548
3245 The Tree Gravestone: 2549 3350 The Tree Gravestone: 2549
3351 the_unkempt:
3352 rooms:
3353 Control Center Entrance:
3354 panels:
3355 RETURN: 2587
3356 Exit Room 2:
3357 panels:
3358 DOOR: 2590
3359 FOUR: 2588
3360 MINE: 2589
3361 WINE: 2591
3362 Exit Room 3:
3363 panels:
3364 ENTER: 2592
3365 Main Area:
3366 panels:
3367 AISLE: 2614
3368 CONTRITE: 2604
3369 COUP: 2610
3370 CRUTCH: 2603
3371 DOUBTER: 2608
3372 EYE: 2597
3373 FLEW: 2611
3374 GUILE: 2612
3375 HEFT: 2596
3376 I: 2593
3377 MOON: 2618
3378 MOONLIGHT: 2602
3379 MUCH: 2609
3380 NOON: 2617
3381 PHASE: 2619
3382 QUITE: 2600
3383 ROUTER: 2605
3384 SCALE: 2620
3385 SHY: 2599
3386 SIGHT: 2598
3387 SOON: 2616
3388 SPY: 2594
3389 STOUTER: 2607
3390 SUCH: 2601
3391 THEFT: 2595
3392 TONIGHT: 2606
3393 TRAIL: 2622
3394 WAYS: 2621
3395 WHILE: 2613
3396 ZOO: 2615
3397 keyholders:
3398 I: 2775
3399 Middle Room:
3400 panels:
3401 FELLOW: 2624
3402 FIDDLE: 2626
3403 RIDDLE: 2623
3404 YELLOW: 2625
3405 Right Area:
3406 panels:
3407 BEEN: 2642
3408 BLUFF: 2638
3409 COLOR: 2649
3410 CORN: 2635
3411 DIET: 2647
3412 FLOWER: 2633
3413 FORTH: 2645
3414 FOURTH: 2648
3415 INN: 2639
3416 MOURN: 2634
3417 OFF: 2640
3418 OUTDO: 2629
3419 QUIET: 2646
3420 SCOFF: 2643
3421 SCUFF: 2636
3422 SOUR: 2631
3423 TATTOO: 2630
3424 TOUGH: 2644
3425 TOWER: 2627
3426 TROUGH: 2641
3427 UNTRUE: 2632
3428 WARN: 2628
3429 WIN: 2637
3430 Unsymmetry Room:
3431 panels:
3432 ACCEPT: 2660
3433 ACCIDENTAL: 2657
3434 COMPLETE: 2658
3435 CONFUSE: 2653
3436 DISPROVE: 2661
3437 ENROLL: 2659
3438 ENTERTAIN: 2652
3439 IMPARTIAL: 2651
3440 SCRUTINIZE (Cyan): 2663
3441 SCRUTINIZE (Purple): 2662
3442 UNEXPECTED: 2655
3443 UNINTERESTED: 2650
3444 UNIRONIC: 2656
3445 UNLUCKY: 2654
3446 V Keyholder:
3447 keyholders:
3448 V: 2776
3449 W Keyholder:
3450 keyholders:
3451 W: 2774
3452 doors:
3453 Cog Rhino Hug Rug: 2586
3454 Control Center Orange Door: 2582
3455 East Door: 2580
3456 Honor Our Hint: 2585
3457 Let Untrue Tie: 2583
3458 Routine Out Chute: 2584
3459 W2 Room Door: 2581
3246 the_unyielding: 3460 the_unyielding:
3247 rooms: 3461 rooms:
3248 Behind Northeast: 3462 Behind Northeast:
@@ -3480,9 +3694,9 @@ maps:
3480 HEALTH: 1428 3694 HEALTH: 1428
3481 doors: 3695 doors:
3482 Bearer Entrance: 1259 3696 Bearer Entrance: 1259
3483 Black Alcove: 2265
3484 Brown Alcove: 1255 3697 Brown Alcove: 1255
3485 Digital Entrance: 1257 3698 Digital Entrance: 1257
3699 East Room 1: 2740
3486 East Room 1 Entrance: 1251 3700 East Room 1 Entrance: 1251
3487 Hero Room Entrance: 1252 3701 Hero Room Entrance: 1252
3488 Jay Painting: 1253 3702 Jay Painting: 1253
@@ -3493,6 +3707,70 @@ maps:
3493 Southwest Corner Behind: 1254 3707 Southwest Corner Behind: 1254
3494 Southwest Room: 1431 3708 Southwest Room: 1431
3495 Yellow Room Puzzles: 1250 3709 Yellow Room Puzzles: 1250
3710 the_wise:
3711 rooms:
3712 Entry:
3713 panels:
3714 INK: 2667
3715 Mastery:
3716 masteries:
3717 MASTERY: 2668
3718 Puzzles:
3719 panels:
3720 BATH: 2679
3721 BOTTLE: 2687
3722 CHAOTIC: 2680
3723 DARKNESS: 2677
3724 EARTHWAR: 2685
3725 ERAS: 2676
3726 EYES: 2681
3727 INTELLIGENCE: 2684
3728 OBSCURE: 2674
3729 PASSED: 2671
3730 PRINCE: 2678
3731 PROPHET: 2675
3732 QUEENDOOM: 2682
3733 RHYME: 2673
3734 SHOUTS: 2683
3735 SLEEPER: 2686
3736 SLUMBERING: 2672
3737 STORY: 2669
3738 VENTURE: 2670
3739 WORDS: 2688
3740 doors:
3741 Front Door: 2666
3742 the_wondrous:
3743 rooms:
3744 Entry:
3745 panels:
3746 WONDER: 2690
3747 Huge:
3748 panels:
3749 BARK: 2695
3750 BRIE: 2693
3751 CHIME: 2697
3752 HARE: 2696
3753 IRE: 2692
3754 LIBRARY: 2698
3755 SHRINK: 2691
3756 WICK: 2694
3757 Regular:
3758 panels:
3759 SHRINK: 2699
3760 doors:
3761 Shrink Door: 2689
3762 the_words:
3763 rooms:
3764 Main Area:
3765 panels:
3766 CLOTHES: 2707
3767 DAIRY: 2704
3768 FLOWER: 2702
3769 FRUIT: 2701
3770 GEM: 2703
3771 METAL: 2706
3772 SPICE: 2708
3773 TREE: 2705
3496letters: 3774letters:
3497 a1: 596 3775 a1: 596
3498 a2: 6 3776 a2: 6
@@ -3536,8 +3814,10 @@ letters:
3536 t2: 2452 3814 t2: 2452
3537 u1: 263 3815 u1: 263
3538 u2: 2140 3816 u2: 2140
3817 v1: 2664
3539 v2: 2246 3818 v2: 2246
3540 w1: 681 3819 w1: 681
3820 w2: 2665
3541 x1: 394 3821 x1: 394
3542 x2: 1192 3822 x2: 1192
3543 y1: 621 3823 y1: 621
@@ -3546,14 +3826,74 @@ letters:
3546 z2: 2224 3826 z2: 2224
3547endings: 3827endings:
3548 BLACK: 1208 3828 BLACK: 1208
3829 BLUE: 2700
3549 CYAN: 1209 3830 CYAN: 1209
3550 GOLD: 1207 3831 GOLD: 1207
3551 GRAY: 1204 3832 GRAY: 1204
3552 GREEN: 1203 3833 GREEN: 1203
3834 MINT: 2728
3553 ORANGE: 1775 3835 ORANGE: 1775
3554 PLUM: 1205 3836 PLUM: 1205
3555 PURPLE: 1211 3837 PURPLE: 1211
3556 RED: 2483 3838 RED: 2483
3839 WHITE: 2738
3557 YELLOW: 1206 3840 YELLOW: 1206
3558special: 3841special:
3559 Nothing: 1160 3842 A Job Well Done: 1160
3843 Age Symbol: 2791
3844 Anagram Symbol: 2792
3845 Anti A: 2814
3846 Anti B: 2815
3847 Anti C: 2816
3848 Anti D: 2817
3849 Anti E: 2818
3850 Anti F: 2819
3851 Anti G: 2820
3852 Anti H: 2821
3853 Anti I: 2822
3854 Anti J: 2823
3855 Anti K: 2824
3856 Anti L: 2825
3857 Anti M: 2826
3858 Anti N: 2827
3859 Anti O: 2828
3860 Anti P: 2829
3861 Anti Q: 2830
3862 Anti R: 2831
3863 Anti S: 2832
3864 Anti T: 2833
3865 Anti U: 2834
3866 Anti V: 2835
3867 Anti W: 2836
3868 Anti X: 2837
3869 Anti Y: 2838
3870 Anti Z: 2839
3871 Boxes Symbol: 2793
3872 Cross Symbol: 2794
3873 Eval Symbol: 2795
3874 Example Symbol: 2796
3875 Gender Symbol: 2797
3876 Job Symbol: 2798
3877 Lingo Symbol: 2799
3878 Null Symbol: 2800
3879 Planet Symbol: 2801
3880 Pyramid Symbol: 2802
3881 Question Symbol: 2803
3882 Sound Symbol: 2804
3883 Sparkles Symbol: 2805
3884 Stars Symbol: 2806
3885 Sun Symbol: 2807
3886 Sweet Symbol: 2808
3887 Zero Symbol: 2809
3888progressives:
3889 Progressive Gold Ending: 2753
3890door_groups:
3891 Control Center Blue Doors: 2788
3892 Control Center Brown Doors: 2787
3893 Control Center Orange Doors: 2786
3894 Control Center Purple Doors: 2785
3895 Control Center White Doors: 2784
3896 Cyan Doors: 2789
3897 Lavender Cubes: 2790
3898 The Entry - Repetitive Entrance: 2782
3899 The Repetitive - Plaza Entrance: 2783
diff --git a/data/maps/control_center/connections.txtpb b/data/maps/control_center/connections.txtpb new file mode 100644 index 0000000..432d39d --- /dev/null +++ b/data/maps/control_center/connections.txtpb
@@ -0,0 +1,85 @@
1connections {
2 from_room: "Entry"
3 to_room: "Main Area"
4 door { name: "Front Door" }
5}
6connections {
7 from_room: "Main Area"
8 to_room: "Stormy Entrance"
9 door { name: "Stormy Entrance" }
10}
11connections {
12 from_room: "Entry"
13 to_room: "Hide Room"
14 door { name: "Hidden Door" }
15}
16connections {
17 from_room: "Main Area"
18 to_room: "Mint Ending"
19 door { name: "Mint Ending Door" }
20}
21connections {
22 from_room: "Main Area"
23 to_room: "Entry Entrance"
24 door { name: "X1 Door" }
25}
26connections {
27 from_room: "Main Area"
28 to_room: "Unkempt Entrance"
29 door { name: "Unkempt Door" }
30}
31connections {
32 from_room: "Main Area"
33 to_room: "Partial Entrance"
34 door { name: "Partial Door" }
35}
36connections {
37 from_room: "Main Area"
38 to_room: "White Ending"
39 door { name: "White Ending Door" }
40}
41connections {
42 from_room: "Main Area"
43 to_room: "Repetitive Entrance"
44 door { name: "Repetitive Entrance" }
45}
46connections {
47 from_room: "Main Area"
48 to_room: "Perceptive Entrance"
49 door { name: "Perceptive From Outside" }
50}
51connections {
52 from_room: "Main Area"
53 to_room: "Perceptive Entrance"
54 door { name: "Perceptive From Inside" }
55}
56connections {
57 from_room: "Main Area"
58 to_room: "Ancient Entrance"
59 door { name: "Ancient Entrance" }
60}
61connections {
62 from_room: "Main Area"
63 to_room: "Between Entrance"
64 door { name: "Between Door" }
65}
66connections {
67 from_room: "Main Area"
68 to_room: "Desert Room"
69 door { name: "Desert Door" }
70}
71connections {
72 from_room: "Main Area"
73 to_room: "Shop Entrance"
74 door { name: "Shop Door" }
75}
76connections {
77 from_room: "Main Area"
78 to_room: "Tenacious Entrance"
79 door { name: "Tenacious Door" }
80}
81connections {
82 from_room: "Main Area"
83 to_room: "Unyielding Entrance"
84 door { name: "Unyielding Door" }
85}
diff --git a/data/maps/control_center/doors.txtpb b/data/maps/control_center/doors.txtpb new file mode 100644 index 0000000..08476a7 --- /dev/null +++ b/data/maps/control_center/doors.txtpb
@@ -0,0 +1,172 @@
1doors {
2 name: "Front Door"
3 type: STANDARD
4 receivers: "Components/Doors/entry_1"
5 panels { room: "Entry" name: "HELLO" }
6 location_room: "Entry"
7}
8doors {
9 name: "Stormy Entrance"
10 type: STANDARD
11 receivers: "Components/Doors/entry_13"
12 panels { room: "Hide Room" name: "HIDE" }
13 location_room: "Hide Room"
14}
15doors {
16 name: "Hidden Door"
17 type: EVENT
18 keyholders { room: "Main Area" name: "1" key: "h" }
19 keyholders { room: "Main Area" name: "2" key: "i" }
20 keyholders { room: "Main Area" name: "3" key: "d" }
21 keyholders { room: "Main Area" name: "4" key: "e" }
22}
23doors {
24 name: "Mint Ending Door"
25 type: EVENT
26 keyholders { room: "Main Area" name: "1" key: "e" }
27 keyholders { room: "Main Area" name: "2" key: "x" }
28 keyholders { room: "Main Area" name: "3" key: "i" }
29 keyholders { room: "Main Area" name: "4" key: "t" }
30}
31doors {
32 name: "Relentless Left Door"
33 type: EVENT
34 keyholders { room: "Main Area" name: "1" key: "l" }
35 keyholders { room: "Main Area" name: "2" key: "e" }
36 keyholders { room: "Main Area" name: "3" key: "f" }
37 keyholders { room: "Main Area" name: "4" key: "t" }
38}
39doors {
40 name: "Relentless Shop Door"
41 type: EVENT
42 keyholders { room: "Main Area" name: "1" key: "s" }
43 keyholders { room: "Main Area" name: "2" key: "h" }
44 keyholders { room: "Main Area" name: "3" key: "o" }
45 keyholders { room: "Main Area" name: "4" key: "p" }
46}
47doors {
48 name: "Relentless Turn Door"
49 type: EVENT
50 keyholders { room: "Main Area" name: "1" key: "t" }
51 keyholders { room: "Main Area" name: "2" key: "u" }
52 keyholders { room: "Main Area" name: "3" key: "r" }
53 keyholders { room: "Main Area" name: "4" key: "n" }
54}
55doors {
56 name: "X1 Door"
57 type: STANDARD
58 receivers: "Components/Doors/entry_3"
59 panels { room: "Entry Entrance" name: "ENTRY" }
60 location_room: "Entry Entrance"
61}
62doors {
63 name: "Unkempt Door"
64 type: STANDARD
65 receivers: "Components/Doors/entry_4"
66 panels { room: "Unkempt Entrance" name: "RETURN" }
67 location_room: "Unkempt Entrance"
68}
69doors {
70 name: "Partial Door"
71 type: STANDARD
72 receivers: "Components/Doors/entry_5"
73 panels { room: "Partial Entrance" name: "PARTIAL" }
74 location_room: "Partial Entrance"
75}
76doors {
77 name: "Link Blocker"
78 type: EVENT
79 panels { room: "Unkempt Entrance" name: "RETURN" }
80 panels { room: "Partial Entrance" name: "PARTIAL" }
81 panels { room: "Shop Entrance" name: "HOPS" }
82 panels { room: "Tenacious Entrance" name: "HERO" }
83}
84doors {
85 name: "White Ending Door"
86 type: EVENT
87 # This is the only time a door depends on endings. However, it's nice to do it
88 # this way instead of just checking for ending room access because this lets
89 # us use events, which makes the playthrough more readable.
90 endings: "MINT"
91 endings: "ORANGE"
92 endings: "GREEN"
93 endings: "GRAY"
94 endings: "PLUM"
95 endings: "YELLOW"
96 endings: "GOLD"
97 endings: "BLACK"
98 endings: "CYAN"
99 endings: "PURPLE"
100 endings: "RED"
101 endings: "BLUE"
102}
103doors {
104 name: "Repetitive Entrance"
105 type: STANDARD
106 receivers: "Components/Doors/entry_7"
107 keyholders { room: "Main Area" name: "1" key: "m" }
108 keyholders { room: "Main Area" name: "2" key: "o" }
109 keyholders { room: "Main Area" name: "3" key: "r" }
110 keyholders { room: "Main Area" name: "4" key: "e" }
111 location_room: "Main Area"
112 location_name: "Keyword MORE"
113}
114doors {
115 name: "Perceptive From Outside"
116 type: EVENT
117 keyholders { room: "Main Area" name: "1" key: "p" }
118 keyholders { room: "Main Area" name: "2" key: "a" }
119 keyholders { room: "Main Area" name: "3" key: "r" }
120 keyholders { room: "Main Area" name: "4" key: "t" }
121}
122doors {
123 name: "Perceptive From Inside"
124 type: EVENT
125 panels { room: "Perceptive Entrance" name: "PART" }
126}
127doors {
128 name: "Ancient Entrance"
129 type: STANDARD
130 receivers: "Components/Doors/entry_20"
131 keyholders { room: "Main Area" name: "1" key: "z" }
132 keyholders { room: "Main Area" name: "2" key: "e" }
133 keyholders { room: "Main Area" name: "3" key: "r" }
134 keyholders { room: "Main Area" name: "4" key: "o" }
135 location_room: "Main Area"
136 location_name: "Keyword ZERO"
137}
138doors {
139 name: "Between Door"
140 type: STANDARD
141 receivers: "Components/Doors/entry_8"
142 panels { room: "Between Entrance" name: "RIGHT" }
143 location_room: "Between Entrance"
144}
145doors {
146 name: "Desert Door"
147 type: STANDARD
148 receivers: "Components/Doors/entry_9"
149 panels { room: "Desert Room" name: "LESS" }
150 location_room: "Desert Room"
151}
152doors {
153 name: "Shop Door"
154 type: STANDARD
155 receivers: "Components/Doors/entry_23"
156 panels { room: "Shop Entrance" name: "HOPS" }
157 location_room: "Shop Entrance"
158}
159doors {
160 name: "Tenacious Door"
161 type: STANDARD
162 receivers: "Components/Doors/entry_24"
163 panels { room: "Tenacious Entrance" name: "HERO" }
164 location_room: "Tenacious Entrance"
165}
166doors {
167 name: "Unyielding Door"
168 type: STANDARD
169 receivers: "Components/Doors/entry_11"
170 panels { room: "Unyielding Entrance" name: "SEEK" }
171 location_room: "Unyielding Entrance"
172}
diff --git a/data/maps/control_center/metadata.txtpb b/data/maps/control_center/metadata.txtpb new file mode 100644 index 0000000..bf89670 --- /dev/null +++ b/data/maps/control_center/metadata.txtpb
@@ -0,0 +1 @@
display_name: "Control Center"
diff --git a/data/maps/control_center/rooms/Ancient Entrance.txtpb b/data/maps/control_center/rooms/Ancient Entrance.txtpb new file mode 100644 index 0000000..5b65d9a --- /dev/null +++ b/data/maps/control_center/rooms/Ancient Entrance.txtpb
@@ -0,0 +1,10 @@
1name: "Ancient Entrance"
2ports {
3 name: "ANCIENT"
4 display_name: "Ancient Entrance"
5 path: "Components/Warps/worldport8"
6 destination { x: -27 y: 0 z: -34 }
7 rotation: 90
8 # TODO: shuffle entrances with dependent keyholders
9 no_shuffle: true
10}
diff --git a/data/maps/control_center/rooms/Between Entrance.txtpb b/data/maps/control_center/rooms/Between Entrance.txtpb new file mode 100644 index 0000000..9da5344 --- /dev/null +++ b/data/maps/control_center/rooms/Between Entrance.txtpb
@@ -0,0 +1,15 @@
1name: "Between Entrance"
2panels {
3 name: "RIGHT"
4 path: "Panels/Hallway Right/entry_4"
5 clue: "right"
6 answer: "left"
7 symbols: SUN
8}
9ports {
10 name: "BETWEEN"
11 display_name: "Between Connector"
12 path: "Components/Warps/worldport5"
13 destination { x: 39 y: 0 z: -17 }
14 rotation: 270
15}
diff --git a/data/maps/control_center/rooms/Desert Room.txtpb b/data/maps/control_center/rooms/Desert Room.txtpb new file mode 100644 index 0000000..fb24faf --- /dev/null +++ b/data/maps/control_center/rooms/Desert Room.txtpb
@@ -0,0 +1,8 @@
1name: "Desert Room"
2panels {
3 name: "LESS"
4 path: "Panels/Hallway Right/entry_5"
5 clue: "less"
6 answer: "more"
7 symbols: SUN
8}
diff --git a/data/maps/control_center/rooms/Entry Entrance.txtpb b/data/maps/control_center/rooms/Entry Entrance.txtpb new file mode 100644 index 0000000..ad882f5 --- /dev/null +++ b/data/maps/control_center/rooms/Entry Entrance.txtpb
@@ -0,0 +1,15 @@
1name: "Entry Entrance"
2panels {
3 name: "ENTRY"
4 path: "Panels/Hallway Right/entry_3"
5 clue: "entry"
6 answer: "exit"
7 symbols: SUN
8}
9ports {
10 name: "ENTRY"
11 display_name: "Entry Connector"
12 path: "Components/Warps/worldport2"
13 destination { x: 26 y: 0 z: -16.5 }
14 rotation: 0
15}
diff --git a/data/maps/control_center/rooms/Entry.txtpb b/data/maps/control_center/rooms/Entry.txtpb new file mode 100644 index 0000000..09c21aa --- /dev/null +++ b/data/maps/control_center/rooms/Entry.txtpb
@@ -0,0 +1,15 @@
1name: "Entry"
2panels {
3 name: "HELLO"
4 path: "Panels/Doors/entry_1"
5 clue: "hello"
6 answer: "hi"
7 symbols: SUN
8}
9ports {
10 name: "GREAT"
11 display_name: "Main Entrance"
12 path: "Components/Warps/worldport"
13 destination { x: 0 y: 0 z: -1.5 }
14 rotation: 0
15}
diff --git a/data/maps/control_center/rooms/Hide Room.txtpb b/data/maps/control_center/rooms/Hide Room.txtpb new file mode 100644 index 0000000..826293b --- /dev/null +++ b/data/maps/control_center/rooms/Hide Room.txtpb
@@ -0,0 +1,8 @@
1name: "Hide Room"
2panels {
3 name: "HIDE"
4 path: "Panels/Doors/entry_4"
5 clue: "hide"
6 answer: "unmask"
7 symbols: SUN
8}
diff --git a/data/maps/control_center/rooms/Main Area.txtpb b/data/maps/control_center/rooms/Main Area.txtpb new file mode 100644 index 0000000..2c1e418 --- /dev/null +++ b/data/maps/control_center/rooms/Main Area.txtpb
@@ -0,0 +1,81 @@
1name: "Main Area"
2panels {
3 name: "COLOR"
4 path: "Panels/Doors/entry_2"
5 clue: "color"
6 answer: "red"
7 proxies { answer: "red" path: "Panels/Colors/color_1" }
8 proxies { answer: "blue" path: "Panels/Colors/color_2" }
9 proxies { answer: "green" path: "Panels/Colors/color_3" }
10 proxies { answer: "yellow" path: "Panels/Colors/color_4" }
11 proxies { answer: "white" path: "Panels/Colors/color_5" }
12 proxies { answer: "black" path: "Panels/Colors/color_6" }
13 proxies { answer: "orange" path: "Panels/Colors/color_7" }
14 proxies { answer: "purple" path: "Panels/Colors/color_8" }
15 proxies { answer: "brown" path: "Panels/Colors/color_9" }
16 proxies { answer: "silver" path: "Panels/Colors/color_10" }
17 proxies { answer: "gold" path: "Panels/Colors/color_11" }
18 proxies { answer: "brass" path: "Panels/Colors/color_12" }
19 proxies { answer: "gray" path: "Panels/Colors/color_13" }
20 proxies { answer: "magenta" path: "Panels/Colors/color_14" }
21}
22panels {
23 name: "Letters"
24 path: "Panels/Doors/entry_6"
25 clue: ""
26 answer: "link"
27 symbols: LINGO
28 required_door { name: "Link Blocker" }
29}
30keyholders {
31 name: "1"
32 path: "Components/KeyHolders/keyHolder"
33 key: "z"
34}
35keyholders {
36 name: "2"
37 path: "Components/KeyHolders/keyHolder2"
38 key: "e"
39}
40keyholders {
41 name: "3"
42 path: "Components/KeyHolders/keyHolder3"
43 key: "r"
44}
45keyholders {
46 name: "4"
47 path: "Components/KeyHolders/keyHolder4"
48 key: "o"
49}
50ports {
51 name: "RIGHT"
52 display_name: "Hinterlands South Entrance"
53 path: "Components/Warps/worldport6"
54 destination { x: 82 y: 0 z: -10 }
55 rotation: 90
56}
57ports {
58 name: "LEFT"
59 display_name: "Hinterlands North Entrance"
60 path: "Components/Warps/worldport7"
61 destination { x: 82 y: 0 z: -48 }
62 rotation: 90
63}
64ports {
65 name: "RELENTLESS_LEFT"
66 display_name: "Relentless LEFT Entrance"
67 path: "Components/Warps/worldport9"
68 no_shuffle: true
69}
70ports {
71 name: "RELENTLESS_SHOP"
72 display_name: "Relentless SHOP Entrance"
73 path: "Components/Warps/worldport11"
74 no_shuffle: true
75}
76ports {
77 name: "RELENTLESS_TURN"
78 display_name: "Relentless TURN Entrance"
79 path: "Components/Warps/worldport10"
80 no_shuffle: true
81}
diff --git a/data/maps/control_center/rooms/Mint Ending.txtpb b/data/maps/control_center/rooms/Mint Ending.txtpb new file mode 100644 index 0000000..7ff9fc4 --- /dev/null +++ b/data/maps/control_center/rooms/Mint Ending.txtpb
@@ -0,0 +1,5 @@
1name: "Mint Ending"
2endings {
3 name: "MINT"
4 path: "Components/Endings/mint_ending"
5}
diff --git a/data/maps/control_center/rooms/Partial Entrance.txtpb b/data/maps/control_center/rooms/Partial Entrance.txtpb new file mode 100644 index 0000000..5771afc --- /dev/null +++ b/data/maps/control_center/rooms/Partial Entrance.txtpb
@@ -0,0 +1,17 @@
1name: "Partial Entrance"
2panels {
3 name: "PARTIAL"
4 path: "Panels/Hallway Left/entry_5"
5 clue: "partial"
6 answer: "part"
7 symbols: SPARKLES
8}
9ports {
10 name: "PARTIAL"
11 display_name: "Partial Connector"
12 path: "Components/Warps/worldport4"
13 destination { x: 21 y: 0 z: -41 }
14 rotation: 270
15 # TODO: shuffle entrances with dependent keyholders
16 no_shuffle: true
17}
diff --git a/data/maps/control_center/rooms/Perceptive Entrance.txtpb b/data/maps/control_center/rooms/Perceptive Entrance.txtpb new file mode 100644 index 0000000..cf5a82c --- /dev/null +++ b/data/maps/control_center/rooms/Perceptive Entrance.txtpb
@@ -0,0 +1,25 @@
1name: "Perceptive Entrance"
2panels {
3 name: "PART"
4 path: "Panels/Doors/stormyPanel2"
5 clue: "part"
6 answer: "hole"
7 symbols: SUN
8 symbols: ZERO
9}
10panels {
11 name: "COLORS"
12 path: "Panels/Doors/stormyPanel3"
13 clue: "colors"
14 answer: "hues"
15 symbols: SUN
16}
17ports {
18 name: "PERCEPTIVE"
19 display_name: "Perceptive Entrance"
20 path: "Components/Warps/worldport12"
21 destination { x: -23 y: 0 z: -11 }
22 rotation: 0
23 # TODO: shuffle entrances with dependent keyholders
24 no_shuffle: true
25}
diff --git a/data/maps/control_center/rooms/Repetitive Entrance.txtpb b/data/maps/control_center/rooms/Repetitive Entrance.txtpb new file mode 100644 index 0000000..6e242f3 --- /dev/null +++ b/data/maps/control_center/rooms/Repetitive Entrance.txtpb
@@ -0,0 +1,10 @@
1name: "Repetitive Entrance"
2ports {
3 name: "REPETITIVE"
4 display_name: "Repetitive Entrance"
5 path: "Components/Warps/worldport14"
6 destination { x: -16 y: 0 z: -17.5 }
7 rotation: 0
8 # TODO: shuffle entrances with dependent keyholders
9 no_shuffle: true
10}
diff --git a/data/maps/control_center/rooms/Shop Entrance.txtpb b/data/maps/control_center/rooms/Shop Entrance.txtpb new file mode 100644 index 0000000..154c55b --- /dev/null +++ b/data/maps/control_center/rooms/Shop Entrance.txtpb
@@ -0,0 +1,9 @@
1name: "Shop Entrance"
2# The connection to The Shop isn't a worldport.
3panels {
4 name: "HOPS"
5 path: "Panels/Hallway Left/entry_6"
6 clue: "hops"
7 answer: "shop"
8 symbols: ANAGRAM
9}
diff --git a/data/maps/control_center/rooms/Stormy Entrance.txtpb b/data/maps/control_center/rooms/Stormy Entrance.txtpb new file mode 100644 index 0000000..23e48b5 --- /dev/null +++ b/data/maps/control_center/rooms/Stormy Entrance.txtpb
@@ -0,0 +1,8 @@
1name: "Stormy Entrance"
2panels {
3 name: "TURN"
4 path: "Components/Warps/stormyPanel"
5 clue: "turn"
6 answer: "spin"
7 symbols: SUN
8}
diff --git a/data/maps/control_center/rooms/Tenacious Entrance.txtpb b/data/maps/control_center/rooms/Tenacious Entrance.txtpb new file mode 100644 index 0000000..2689589 --- /dev/null +++ b/data/maps/control_center/rooms/Tenacious Entrance.txtpb
@@ -0,0 +1,17 @@
1name: "Tenacious Entrance"
2panels {
3 name: "HERO"
4 path: "Panels/Hallway Left/entry_7"
5 clue: "hero"
6 answer: "zero"
7 symbols: ZERO
8}
9ports {
10 name: "TENACIOUS"
11 display_name: "Tenacious Connector"
12 path: "Components/Warps/worldport13"
13 destination { x: 56 y: 0 z: -38 }
14 rotation: 180
15 # TODO: shuffle entrances with dependent keyholders
16 no_shuffle: true
17}
diff --git a/data/maps/control_center/rooms/Unkempt Entrance.txtpb b/data/maps/control_center/rooms/Unkempt Entrance.txtpb new file mode 100644 index 0000000..5e65254 --- /dev/null +++ b/data/maps/control_center/rooms/Unkempt Entrance.txtpb
@@ -0,0 +1,17 @@
1name: "Unkempt Entrance"
2panels {
3 name: "RETURN"
4 path: "Panels/Hallway Left/entry_4"
5 clue: "return"
6 answer: "turn"
7 symbols: SPARKLES
8}
9ports {
10 name: "UNKEMPT"
11 display_name: "Unkempt Connector"
12 path: "Components/Warps/worldport3"
13 destination { x: 34 y: 0 z: -38.5 }
14 rotation: 90
15 # TODO: shuffle entrances with dependent keyholders
16 no_shuffle: true
17}
diff --git a/data/maps/control_center/rooms/Unyielding Entrance.txtpb b/data/maps/control_center/rooms/Unyielding Entrance.txtpb new file mode 100644 index 0000000..ca22b23 --- /dev/null +++ b/data/maps/control_center/rooms/Unyielding Entrance.txtpb
@@ -0,0 +1,15 @@
1name: "Unyielding Entrance"
2panels {
3 name: "FORTH"
4 path: "Components/UnlockListeners/panelPorter"
5 clue: "forth"
6 answer: "back"
7 symbols: SUN
8}
9panels {
10 name: "SEEK"
11 path: "Panels/Hallway Right/entry_6"
12 clue: "seek"
13 answer: "hide"
14 symbols: SUN
15}
diff --git a/data/maps/control_center/rooms/White Ending.txtpb b/data/maps/control_center/rooms/White Ending.txtpb new file mode 100644 index 0000000..62d4a56 --- /dev/null +++ b/data/maps/control_center/rooms/White Ending.txtpb
@@ -0,0 +1,5 @@
1name: "White Ending"
2endings {
3 name: "WHITE"
4 path: "Components/Endings/white_ending"
5}
diff --git a/data/maps/daedalus/connections.txtpb b/data/maps/daedalus/connections.txtpb index fc0af60..cb27c38 100644 --- a/data/maps/daedalus/connections.txtpb +++ b/data/maps/daedalus/connections.txtpb
@@ -100,6 +100,11 @@ connections {
100 oneway: true 100 oneway: true
101} 101}
102connections { 102connections {
103 from_room: "Outside House"
104 to_room: "Blue Hallway Tall Side"
105 door { name: "House Side Door" }
106}
107connections {
103 from_room: "Purple SE Vestibule" 108 from_room: "Purple SE Vestibule"
104 to_room: "Welcome Back Area" 109 to_room: "Welcome Back Area"
105 oneway: true 110 oneway: true
@@ -200,11 +205,16 @@ connections {
200 door { name: "Temple of the Eyes Entrance" } 205 door { name: "Temple of the Eyes Entrance" }
201} 206}
202connections { 207connections {
203 from_room: "Outside Eye Temple" 208 from_room: "Eye Painting"
204 to_room: "Starting Room" 209 to_room: "Starting Room"
205 door { name: "Starting Room South Wall West Door" } 210 door { name: "Starting Room South Wall West Door" }
206} 211}
207connections { 212connections {
213 from_room: "Eye Painting"
214 to_room: "Outside Eye Temple"
215 door { name: "Eye Painting Exit" }
216}
217connections {
208 from_room: "Outside Pyramid" 218 from_room: "Outside Pyramid"
209 to_room: "Number Paintings Area" 219 to_room: "Number Paintings Area"
210 door { name: "Near Pyramid Gate" } 220 door { name: "Near Pyramid Gate" }
@@ -217,12 +227,12 @@ connections {
217connections { 227connections {
218 from_room: "West Castle Area" 228 from_room: "West Castle Area"
219 to_room: "Post Orange Smiley Three Way" 229 to_room: "Post Orange Smiley Three Way"
220 door { name: "Splintering Exit Left Door" } 230 door { name: "Splintering Exit North Door" }
221} 231}
222connections { 232connections {
223 from_room: "West Castle Area" 233 from_room: "West Castle Area"
224 to_room: "Amber North 2" 234 to_room: "Amber North 2"
225 door { name: "Splintering Exit Right Door" } 235 door { name: "Splintering Exit South Door" }
226} 236}
227connections { 237connections {
228 from_room: "Z2 Room" 238 from_room: "Z2 Room"
@@ -373,7 +383,7 @@ connections {
373connections { 383connections {
374 from_room: "O2 Room" 384 from_room: "O2 Room"
375 to_room: "Blue Smiley" 385 to_room: "Blue Smiley"
376 door { name: "Blue Smiley Entrance" } 386 door { name: "O2 Room Southeast Door" }
377} 387}
378connections { 388connections {
379 from_room: "O2 Room" 389 from_room: "O2 Room"
@@ -403,7 +413,7 @@ connections {
403connections { 413connections {
404 from_room: "O2 Room" 414 from_room: "O2 Room"
405 to_room: "Blue Hallway" 415 to_room: "Blue Hallway"
406 door { name: "O2 Room Back Door" } 416 door { name: "O2 Room Northeast Door" }
407} 417}
408connections { 418connections {
409 from_room: "O2 Room" 419 from_room: "O2 Room"
@@ -418,7 +428,7 @@ connections {
418connections { 428connections {
419 from_room: "Sweet Foyer" 429 from_room: "Sweet Foyer"
420 to_room: "F2 Room" 430 to_room: "F2 Room"
421 door { name: "F2 Room Entrance" } 431 door { name: "F2 Room Southeast Door" }
422} 432}
423connections { 433connections {
424 from_room: "Globe Room" 434 from_room: "Globe Room"
@@ -433,17 +443,17 @@ connections {
433connections { 443connections {
434 from_room: "F2 Room" 444 from_room: "F2 Room"
435 to_room: "Blue Hallway" 445 to_room: "Blue Hallway"
436 door { name: "F2 Room Back Right Door" } 446 door { name: "F2 Room Southwest Door" }
437} 447}
438connections { 448connections {
439 from_room: "F2 Room" 449 from_room: "F2 Room"
440 to_room: "Outside Salt Room" 450 to_room: "Outside Salt Room"
441 door { name: "F2 Room Back Left Door" } 451 door { name: "F2 Room Northwest Door" }
442} 452}
443connections { 453connections {
444 from_room: "F2 Room" 454 from_room: "F2 Room"
445 to_room: "Red Color Door" 455 to_room: "Red Color Door"
446 door { name: "F2 Room Back Middle Door" } 456 door { name: "F2 Room West Door" }
447 oneway: true 457 oneway: true
448 # This is the red backside, which has nothing in it. Maybe could be its own 458 # This is the red backside, which has nothing in it. Maybe could be its own
449 # region at some point. 459 # region at some point.
@@ -456,7 +466,7 @@ connections {
456connections { 466connections {
457 from_room: "U2 Room" 467 from_room: "U2 Room"
458 to_room: "Maze Paintings Area" 468 to_room: "Maze Paintings Area"
459 door { name: "U2 Room Shortcut" } 469 door { name: "U2 Room Southeast Door" }
460} 470}
461connections { 471connections {
462 from_room: "Maze Paintings Area" 472 from_room: "Maze Paintings Area"
@@ -471,17 +481,17 @@ connections {
471connections { 481connections {
472 from_room: "U2 Room" 482 from_room: "U2 Room"
473 to_room: "Purple SE Vestibule" 483 to_room: "Purple SE Vestibule"
474 door { name: "U2 Room Back Right Door" } 484 door { name: "U2 Room Southwest Door" }
475} 485}
476connections { 486connections {
477 from_room: "U2 Room" 487 from_room: "U2 Room"
478 to_room: "Purple Room East" 488 to_room: "Purple Room East"
479 door { name: "U2 Room Back Door" } 489 door { name: "U2 Room West Door" }
480} 490}
481connections { 491connections {
482 from_room: "Maze" 492 from_room: "Maze"
483 to_room: "U2 Room" 493 to_room: "U2 Room"
484 door { name: "U2 Room Entrance" } 494 door { name: "U2 Room East Door" }
485} 495}
486connections { 496connections {
487 from_room: "Outside Magic Room" 497 from_room: "Outside Magic Room"
@@ -506,7 +516,7 @@ connections {
506connections { 516connections {
507 from_room: "Wonderland" 517 from_room: "Wonderland"
508 to_room: "Black Hex" 518 to_room: "Black Hex"
509 door { name: "Wonderland Right Door" } 519 door { name: "Wonderland South Door" }
510} 520}
511connections { 521connections {
512 from_room: "Outside Pyramid" 522 from_room: "Outside Pyramid"
@@ -530,6 +540,11 @@ connections {
530} 540}
531connections { 541connections {
532 from_room: "Z2 Room" 542 from_room: "Z2 Room"
543 to_room: "Orange Room Hallway"
544 door { name: "Z2 Room Southeast Door" }
545}
546connections {
547 from_room: "Orange Room Hallway"
533 to_room: "Orange Room" 548 to_room: "Orange Room"
534 door { name: "Z2 Room Southeast Door" } 549 door { name: "Z2 Room Southeast Door" }
535} 550}
@@ -591,7 +606,7 @@ connections {
591connections { 606connections {
592 from_room: "Wonderland" 607 from_room: "Wonderland"
593 to_room: "Number Paintings Area" 608 to_room: "Number Paintings Area"
594 door { name: "Wonderland Left Door" } 609 door { name: "Wonderland North Door" }
595} 610}
596connections { 611connections {
597 from_room: "Outside House" 612 from_room: "Outside House"
@@ -1540,3 +1555,322 @@ connections {
1540 to_room: "Pyramid Top" 1555 to_room: "Pyramid Top"
1541 door { name: "Pyramid Third Floor Door" } 1556 door { name: "Pyramid Third Floor Door" }
1542} 1557}
1558connections {
1559 from_room: "Roof"
1560 to_room: "After Bee Room"
1561 oneway: true
1562 roof_access: true
1563}
1564connections {
1565 from_room: "Roof"
1566 to_room: "Amber North 2"
1567 oneway: true
1568 roof_access: true
1569}
1570connections {
1571 from_room: "Roof"
1572 to_room: "Black Hex"
1573 oneway: true
1574 roof_access: true
1575}
1576connections {
1577 from_room: "Roof"
1578 to_room: "Blue Hallway Tall Side"
1579 oneway: true
1580 roof_access: true
1581}
1582connections {
1583 from_room: "Roof"
1584 to_room: "Blue Hallway"
1585 oneway: true
1586 roof_access: true
1587}
1588# Blue Hallway Cut Side is inside.
1589connections {
1590 from_room: "Roof"
1591 to_room: "Eye Painting"
1592 oneway: true
1593 roof_access: true
1594}
1595connections {
1596 from_room: "Roof"
1597 to_room: "Globe Room"
1598 oneway: true
1599 roof_access: true
1600}
1601connections {
1602 from_room: "Roof"
1603 to_room: "Gray Color Door"
1604 oneway: true
1605 roof_access: true
1606}
1607connections {
1608 from_room: "Roof"
1609 to_room: "Green Color Door"
1610 oneway: true
1611 roof_access: true
1612}
1613connections {
1614 from_room: "Roof"
1615 to_room: "Green Smiley"
1616 oneway: true
1617 roof_access: true
1618}
1619connections {
1620 from_room: "Roof"
1621 to_room: "Hedges"
1622 oneway: true
1623 roof_access: true
1624}
1625connections {
1626 from_room: "Roof"
1627 to_room: "Maze Paintings Area"
1628 oneway: true
1629 roof_access: true
1630}
1631connections {
1632 from_room: "Roof"
1633 to_room: "Maze"
1634 oneway: true
1635 roof_access: true
1636}
1637connections {
1638 from_room: "Roof"
1639 to_room: "North Castle Area"
1640 oneway: true
1641 roof_access: true
1642}
1643connections {
1644 from_room: "Roof"
1645 to_room: "Number Paintings Area"
1646 oneway: true
1647 roof_access: true
1648}
1649connections {
1650 from_room: "Roof"
1651 to_room: "Orange Room Hallway"
1652 oneway: true
1653 roof_access: true
1654}
1655connections {
1656 from_room: "Roof"
1657 to_room: "Outside Book Room"
1658 oneway: true
1659 roof_access: true
1660}
1661connections {
1662 from_room: "Roof"
1663 to_room: "Outside Eye Temple"
1664 oneway: true
1665 roof_access: true
1666}
1667connections {
1668 from_room: "Roof"
1669 to_room: "Outside Hedges"
1670 oneway: true
1671 roof_access: true
1672}
1673connections {
1674 from_room: "Roof"
1675 to_room: "Outside Hotel"
1676 oneway: true
1677 roof_access: true
1678}
1679connections {
1680 from_room: "Roof"
1681 to_room: "Outside House"
1682 oneway: true
1683 roof_access: true
1684}
1685connections {
1686 from_room: "Roof"
1687 to_room: "Outside Magic Room"
1688 oneway: true
1689 roof_access: true
1690}
1691connections {
1692 from_room: "Roof"
1693 to_room: "Outside Orange Room"
1694 oneway: true
1695 roof_access: true
1696}
1697connections {
1698 from_room: "Roof"
1699 to_room: "Outside Pyramid"
1700 oneway: true
1701 roof_access: true
1702}
1703connections {
1704 from_room: "Roof"
1705 to_room: "Outside Red Room"
1706 oneway: true
1707 roof_access: true
1708}
1709connections {
1710 from_room: "Roof"
1711 to_room: "Outside Salt Room"
1712 oneway: true
1713 roof_access: true
1714}
1715connections {
1716 from_room: "Roof"
1717 to_room: "Outside Snake Room"
1718 oneway: true
1719 roof_access: true
1720}
1721connections {
1722 from_room: "Roof"
1723 to_room: "Post Orange Smiley Three Way"
1724 oneway: true
1725 roof_access: true
1726}
1727connections {
1728 from_room: "Roof"
1729 to_room: "Purple NW Vestibule"
1730 oneway: true
1731 roof_access: true
1732}
1733connections {
1734 from_room: "Roof"
1735 to_room: "Purple Room East"
1736 oneway: true
1737 roof_access: true
1738}
1739connections {
1740 from_room: "Roof"
1741 to_room: "Purple Room South"
1742 oneway: true
1743 roof_access: true
1744}
1745connections {
1746 from_room: "Roof"
1747 to_room: "Purple Room West"
1748 oneway: true
1749 roof_access: true
1750}
1751connections {
1752 from_room: "Roof"
1753 to_room: "Purple SE Vestibule"
1754 oneway: true
1755 roof_access: true
1756}
1757connections {
1758 from_room: "Roof"
1759 to_room: "Pyramid Second Floor"
1760 oneway: true
1761 roof_access: true
1762}
1763connections {
1764 from_room: "Roof"
1765 to_room: "Pyramid Top"
1766 oneway: true
1767 roof_access: true
1768}
1769connections {
1770 from_room: "Roof"
1771 to_room: "Quiet Entrance"
1772 oneway: true
1773 roof_access: true
1774}
1775connections {
1776 from_room: "Roof"
1777 to_room: "Red Color Door"
1778 oneway: true
1779 roof_access: true
1780}
1781connections {
1782 from_room: "Roof"
1783 to_room: "South Castle Area"
1784 oneway: true
1785 roof_access: true
1786}
1787connections {
1788 from_room: "Roof"
1789 to_room: "Starting Room"
1790 oneway: true
1791 roof_access: true
1792}
1793connections {
1794 from_room: "Roof"
1795 to_room: "Sweet Foyer"
1796 oneway: true
1797 roof_access: true
1798}
1799connections {
1800 from_room: "Roof"
1801 to_room: "Tree Entrance"
1802 oneway: true
1803 roof_access: true
1804}
1805connections {
1806 from_room: "Roof"
1807 to_room: "West Castle Area"
1808 oneway: true
1809 roof_access: true
1810}
1811connections {
1812 from_room: "Roof"
1813 to_room: "West Spire"
1814 oneway: true
1815 roof_access: true
1816}
1817connections {
1818 from_room: "Roof"
1819 to_room: "Yellow Color Door"
1820 oneway: true
1821 roof_access: true
1822}
1823connections {
1824 from_room: "Roof"
1825 to_room: "Z2 Room"
1826 oneway: true
1827 roof_access: true
1828}
1829connections {
1830 from_room: "Roof"
1831 to_room: "Zoo Center"
1832 oneway: true
1833 roof_access: true
1834}
1835connections {
1836 from_room: "Roof"
1837 to_room: "Zoo E"
1838 oneway: true
1839 roof_access: true
1840}
1841connections {
1842 from_room: "Roof"
1843 to_room: "Zoo N"
1844 oneway: true
1845 roof_access: true
1846}
1847connections {
1848 from_room: "Roof"
1849 to_room: "Zoo NE"
1850 oneway: true
1851 roof_access: true
1852}
1853connections {
1854 from_room: "Roof"
1855 to_room: "Zoo S"
1856 oneway: true
1857 roof_access: true
1858}
1859connections {
1860 from_room: "Roof"
1861 to_room: "Zoo SE"
1862 oneway: true
1863 roof_access: true
1864}
1865connections {
1866 from_room: "Roof"
1867 to_room: "F Keyholder"
1868 oneway: true
1869 roof_access: true
1870}
1871connections {
1872 from_room: "Roof"
1873 to_room: "Yellow Color Backside"
1874 oneway: true
1875 roof_access: true
1876}
diff --git a/data/maps/daedalus/doors.txtpb b/data/maps/daedalus/doors.txtpb index 1ae6cc6..6097e57 100644 --- a/data/maps/daedalus/doors.txtpb +++ b/data/maps/daedalus/doors.txtpb
@@ -188,16 +188,15 @@ doors {
188} 188}
189doors { 189doors {
190 name: "Welcome Back Secret Door" 190 name: "Welcome Back Secret Door"
191 type: STANDARD 191 type: ITEM_ONLY
192 receivers: "Components/Doors/Entry/entry_13" 192 receivers: "Components/Doors/Entry/entry_13"
193 panels { room: "Welcome Back Area" name: "FAREWELL LITTLE LAMB" } 193 panels { room: "Welcome Back Area" name: "FAREWELL LITTLE LAMB" }
194 panels { room: "West Spire" name: "BYE" } 194 panels { room: "West Spire" name: "BYE" }
195 location_room: "West Spire"
196} 195}
197doors { 196doors {
198 name: "Welcome Back Door" 197 name: "Welcome Back Door"
199 type: STANDARD 198 type: LOCATION_ONLY
200 receivers: "Components/Doors/Entry/entry_14" 199 #receivers: "Components/Doors/Entry/entry_14"
201 panels { room: "Welcome Back Area" name: "GREETINGS OLD FRIEND" } 200 panels { room: "Welcome Back Area" name: "GREETINGS OLD FRIEND" }
202 location_room: "Welcome Back Area" 201 location_room: "Welcome Back Area"
203} 202}
@@ -296,9 +295,10 @@ doors {
296 panels { room: "Black Hex" name: "CLUES" } 295 panels { room: "Black Hex" name: "CLUES" }
297 panels { room: "Black Hex" name: "SECRET" } 296 panels { room: "Black Hex" name: "SECRET" }
298 location_room: "Black Hex" 297 location_room: "Black Hex"
298 location_name: "Black Hex"
299} 299}
300doors { 300doors {
301 name: "Splintering Exit Left Door" 301 name: "Splintering Exit North Door"
302 type: STANDARD 302 type: STANDARD
303 receivers: "Components/Doors/Entry/gate_4" 303 receivers: "Components/Doors/Entry/gate_4"
304 panels { room: "West Castle Area" name: "EVER" } 304 panels { room: "West Castle Area" name: "EVER" }
@@ -308,7 +308,7 @@ doors {
308 location_room: "West Castle Area" 308 location_room: "West Castle Area"
309} 309}
310doors { 310doors {
311 name: "Splintering Exit Right Door" 311 name: "Splintering Exit South Door"
312 type: ITEM_ONLY 312 type: ITEM_ONLY
313 receivers: "Components/Doors/Entry/gate_5" 313 receivers: "Components/Doors/Entry/gate_5"
314 panels { room: "West Castle Area" name: "EVER" } 314 panels { room: "West Castle Area" name: "EVER" }
@@ -382,6 +382,7 @@ doors {
382 panels { room: "Z2 Room" name: "CAPE" } 382 panels { room: "Z2 Room" name: "CAPE" }
383 panels { room: "Z2 Room" name: "GLANCE" } 383 panels { room: "Z2 Room" name: "GLANCE" }
384 location_room: "Z2 Room" 384 location_room: "Z2 Room"
385 location_name: "West Puzzles"
385} 386}
386doors { 387doors {
387 name: "Z2 Room Northwest Door" 388 name: "Z2 Room Northwest Door"
@@ -413,6 +414,7 @@ doors {
413 panels { room: "Z2 Room" name: "DISCORD" } 414 panels { room: "Z2 Room" name: "DISCORD" }
414 panels { room: "Z2 Room" name: "CAT" } 415 panels { room: "Z2 Room" name: "CAT" }
415 location_room: "Z2 Room" 416 location_room: "Z2 Room"
417 location_name: "East Puzzles"
416} 418}
417doors { 419doors {
418 name: "Z2 Room Southeast Door" 420 name: "Z2 Room Southeast Door"
@@ -517,6 +519,7 @@ doors {
517 panels { room: "Outside House" name: "BLITHELY" } 519 panels { room: "Outside House" name: "BLITHELY" }
518 panels { room: "Purple Room South" name: "THESE" } 520 panels { room: "Purple Room South" name: "THESE" }
519 location_room: "Outside House" 521 location_room: "Outside House"
522 location_name: "West Purple Vestibules"
520} 523}
521doors { 524doors {
522 name: "Purple West Area South Door" 525 name: "Purple West Area South Door"
@@ -545,6 +548,7 @@ doors {
545 panels { room: "Godot Room" name: "TRAIN" } 548 panels { room: "Godot Room" name: "TRAIN" }
546 panels { room: "Godot Room" name: "RECORDING" } 549 panels { room: "Godot Room" name: "RECORDING" }
547 location_room: "Godot Room" 550 location_room: "Godot Room"
551 location_name: "Godot Room"
548} 552}
549doors { 553doors {
550 name: "Beehalls Intersection" 554 name: "Beehalls Intersection"
@@ -576,6 +580,7 @@ doors {
576 panels { room: "Purple Room South" name: "ANY" } 580 panels { room: "Purple Room South" name: "ANY" }
577 panels { room: "Outside House" name: "A" } 581 panels { room: "Outside House" name: "A" }
578 location_room: "Outside House" 582 location_room: "Outside House"
583 location_name: "East Purple Vestibules"
579} 584}
580doors { 585doors {
581 name: "Purple East Area North Door" 586 name: "Purple East Area North Door"
@@ -593,6 +598,7 @@ doors {
593 panels { room: "Outside House" name: "BLITHELY" } 598 panels { room: "Outside House" name: "BLITHELY" }
594 panels { room: "Purple Room South" name: "THESE" } 599 panels { room: "Purple Room South" name: "THESE" }
595 location_room: "Outside House" 600 location_room: "Outside House"
601 location_name: "Purple Vestibules"
596} 602}
597doors { 603doors {
598 name: "Purple Room South Entrance" 604 name: "Purple Room South Entrance"
@@ -622,6 +628,20 @@ doors {
622 panels { room: "Purple Room South" name: "THESE" } 628 panels { room: "Purple Room South" name: "THESE" }
623} 629}
624doors { 630doors {
631 name: "Purple Room"
632 type: LOCATION_ONLY
633 panels { room: "Purple Room" name: "HOIST" }
634 panels { room: "Purple Room" name: "CORE" }
635 panels { room: "Purple Room" name: "FISH" }
636 panels { room: "Purple Room" name: "ALLOW" }
637 panels { room: "Purple Room" name: "BIRD" }
638 panels { room: "Purple Room" name: "HONK" }
639 panels { room: "Purple Room" name: "APE" }
640 panels { room: "Purple Room" name: "APATHY" }
641 location_room: "Purple Room"
642 location_name: "Puzzles"
643}
644doors {
625 name: "Hedges Tower" 645 name: "Hedges Tower"
626 type: LOCATION_ONLY 646 type: LOCATION_ONLY
627 # TODO: Not making this an item right now in order to force the player to 647 # TODO: Not making this an item right now in order to force the player to
@@ -676,6 +696,7 @@ doors {
676 panels { room: "Blue Room" name: "CELEBRATORY" } 696 panels { room: "Blue Room" name: "CELEBRATORY" }
677 panels { room: "Blue Room" name: "DETECTIVE" } 697 panels { room: "Blue Room" name: "DETECTIVE" }
678 location_room: "Blue Room" 698 location_room: "Blue Room"
699 location_name: "Puzzles"
679} 700}
680doors { 701doors {
681 name: "O2 Prize" 702 name: "O2 Prize"
@@ -694,7 +715,7 @@ doors {
694 panels { room: "O2 Room" name: "UNBLOCKED" } 715 panels { room: "O2 Room" name: "UNBLOCKED" }
695} 716}
696doors { 717doors {
697 name: "Blue Smiley Entrance" 718 name: "O2 Room Southeast Door"
698 type: STANDARD 719 type: STANDARD
699 receivers: "Components/Doors/Halls/oroom_2" 720 receivers: "Components/Doors/Halls/oroom_2"
700 panels { room: "O2 Room" name: "HONEST" } 721 panels { room: "O2 Room" name: "HONEST" }
@@ -734,6 +755,7 @@ doors {
734 panels { room: "Composite Room S" name: "BLEAKCARD" } 755 panels { room: "Composite Room S" name: "BLEAKCARD" }
735 panels { room: "Composite Room S" name: "MISSIONMISSION" } 756 panels { room: "Composite Room S" name: "MISSIONMISSION" }
736 location_room: "Composite Room S" 757 location_room: "Composite Room S"
758 location_name: "East Rooms"
737} 759}
738doors { 760doors {
739 name: "Composite Room North Door" 761 name: "Composite Room North Door"
@@ -762,6 +784,7 @@ doors {
762 panels { room: "Composite Room NW" name: "OUTGARDEN" } 784 panels { room: "Composite Room NW" name: "OUTGARDEN" }
763 panels { room: "Composite Room NW" name: "HELLOTALE" } 785 panels { room: "Composite Room NW" name: "HELLOTALE" }
764 location_room: "Composite Room NE" 786 location_room: "Composite Room NE"
787 location_name: "North Rooms"
765} 788}
766doors { 789doors {
767 name: "Composite Room West Door" 790 name: "Composite Room West Door"
@@ -792,12 +815,13 @@ doors {
792 panels { room: "Composite Room S" name: "OUTEAT" } 815 panels { room: "Composite Room S" name: "OUTEAT" }
793 panels { room: "Composite Room S" name: "SUMMERIN" } 816 panels { room: "Composite Room S" name: "SUMMERIN" }
794 location_room: "Composite Room NW" 817 location_room: "Composite Room NW"
818 location_name: "West Rooms"
795} 819}
796doors { 820doors {
797 name: "Composite Room NW Entrance" 821 name: "Composite Room NW Entrance"
798 type: STANDARD 822 type: STANDARD
799 receivers: "Components/Doors/Halls/oroom_10" 823 receivers: "Components/Doors/Halls/oroom_10"
800 panels { room: "Red Color Door" name: "Left" } 824 panels { room: "Red Color Door" name: "Near Obscured Puzzles" }
801 location_room: "Red Color Door" 825 location_room: "Red Color Door"
802} 826}
803doors { 827doors {
@@ -829,9 +853,10 @@ doors {
829 panels { room: "Composite Room S" name: "OUTEAT" } 853 panels { room: "Composite Room S" name: "OUTEAT" }
830 panels { room: "Composite Room S" name: "SUMMERIN" } 854 panels { room: "Composite Room S" name: "SUMMERIN" }
831 location_room: "Composite Room S" 855 location_room: "Composite Room S"
856 location_name: "South Rooms"
832} 857}
833doors { 858doors {
834 name: "O2 Room Back Door" 859 name: "O2 Room Northeast Door"
835 type: STANDARD 860 type: STANDARD
836 receivers: "Components/Doors/Halls/oroom_4" 861 receivers: "Components/Doors/Halls/oroom_4"
837 panels { room: "O2 Room" name: "UNBLOCKED" } 862 panels { room: "O2 Room" name: "UNBLOCKED" }
@@ -858,7 +883,7 @@ doors {
858 panels { room: "F2 Room" name: "SHAPE" } 883 panels { room: "F2 Room" name: "SHAPE" }
859} 884}
860doors { 885doors {
861 name: "F2 Room Entrance" 886 name: "F2 Room Southeast Door"
862 type: STANDARD 887 type: STANDARD
863 receivers: "Components/Doors/Halls/froom_2" 888 receivers: "Components/Doors/Halls/froom_2"
864 panels { room: "Sweet Foyer" name: "RENT (1)" } 889 panels { room: "Sweet Foyer" name: "RENT (1)" }
@@ -866,36 +891,32 @@ doors {
866} 891}
867doors { 892doors {
868 name: "White Hallway From Entry" 893 name: "White Hallway From Entry"
869 # TODO: This should be combined with the corresponding door in the_entry, at
870 # least when connections are not shuffled.
871 type: CONTROL_CENTER_COLOR 894 type: CONTROL_CENTER_COLOR
872 receivers: "Components/Doors/Halls/froom_6" 895 receivers: "Components/Doors/Halls/froom_6"
873 control_center_color: "white" 896 control_center_color: "white"
874} 897}
875doors { 898doors {
876 name: "Purple Hallway From Great" 899 name: "Purple Hallway From Great"
877 # TODO: This should be combined with the corresponding door in the_great, at
878 # least when connections are not shuffled.
879 type: CONTROL_CENTER_COLOR 900 type: CONTROL_CENTER_COLOR
880 receivers: "Components/Doors/Halls/froom_7" 901 receivers: "Components/Doors/Halls/froom_7"
881 control_center_color: "purple" 902 control_center_color: "purple"
882} 903}
883doors { 904doors {
884 name: "F2 Room Back Right Door" 905 name: "F2 Room Southwest Door"
885 type: STANDARD 906 type: STANDARD
886 receivers: "Components/Doors/Halls/froom_3" 907 receivers: "Components/Doors/Halls/froom_3"
887 panels { room: "F2 Room" name: "RISKY" } 908 panels { room: "F2 Room" name: "RISKY" }
888 location_room: "F2 Room" 909 location_room: "F2 Room"
889} 910}
890doors { 911doors {
891 name: "F2 Room Back Left Door" 912 name: "F2 Room Northwest Door"
892 type: STANDARD 913 type: STANDARD
893 receivers: "Components/Doors/Halls/froom_4" 914 receivers: "Components/Doors/Halls/froom_4"
894 panels { room: "F2 Room" name: "SHAPE" } 915 panels { room: "F2 Room" name: "SHAPE" }
895 location_room: "F2 Room" 916 location_room: "F2 Room"
896} 917}
897doors { 918doors {
898 name: "F2 Room Back Middle Door" 919 name: "F2 Room West Door"
899 type: STANDARD 920 type: STANDARD
900 receivers: "Components/Doors/Halls/froom_5" 921 receivers: "Components/Doors/Halls/froom_5"
901 panels { room: "F2 Room" name: "DIRT" } 922 panels { room: "F2 Room" name: "DIRT" }
@@ -916,7 +937,7 @@ doors {
916 panels { room: "U2 Room" name: "HEAVEN" } 937 panels { room: "U2 Room" name: "HEAVEN" }
917} 938}
918doors { 939doors {
919 name: "U2 Room Shortcut" 940 name: "U2 Room Southeast Door"
920 type: STANDARD 941 type: STANDARD
921 receivers: "Components/Doors/Halls/uroom_2" 942 receivers: "Components/Doors/Halls/uroom_2"
922 panels { room: "U2 Room" name: "WICKED" } 943 panels { room: "U2 Room" name: "WICKED" }
@@ -937,21 +958,21 @@ doors {
937 location_room: "House Entrance" 958 location_room: "House Entrance"
938} 959}
939doors { 960doors {
940 name: "U2 Room Back Right Door" 961 name: "U2 Room Southwest Door"
941 type: STANDARD 962 type: STANDARD
942 receivers: "Components/Doors/Halls/uroom_3" 963 receivers: "Components/Doors/Halls/uroom_3"
943 panels { room: "U2 Room" name: "HEAVEN" } 964 panels { room: "U2 Room" name: "HEAVEN" }
944 location_room: "U2 Room" 965 location_room: "U2 Room"
945} 966}
946doors { 967doors {
947 name: "U2 Room Back Door" 968 name: "U2 Room West Door"
948 type: ITEM_ONLY 969 type: ITEM_ONLY
949 receivers: "Components/Doors/Halls/uroom_5" 970 receivers: "Components/Doors/Halls/uroom_5"
950 panels { room: "Purple Room South" name: "ANY" } 971 panels { room: "Purple Room South" name: "ANY" }
951 panels { room: "Outside House" name: "A" } 972 panels { room: "Outside House" name: "A" }
952} 973}
953doors { 974doors {
954 name: "U2 Room Entrance" 975 name: "U2 Room East Door"
955 type: ITEM_ONLY 976 type: ITEM_ONLY
956 receivers: "Components/Doors/Halls/uroom_4" 977 receivers: "Components/Doors/Halls/uroom_4"
957 panels { room: "Outside Magic Room" name: "WIZARD" } 978 panels { room: "Outside Magic Room" name: "WIZARD" }
@@ -995,7 +1016,7 @@ doors {
995 panels { room: "Outside Magic Room" name: "WIZARD" } 1016 panels { room: "Outside Magic Room" name: "WIZARD" }
996} 1017}
997doors { 1018doors {
998 name: "Wonderland Right Door" 1019 name: "Wonderland South Door"
999 type: STANDARD 1020 type: STANDARD
1000 receivers: "Components/Doors/Halls/wonderland_1" 1021 receivers: "Components/Doors/Halls/wonderland_1"
1001 panels { room: "Wonderland" name: "APRIL" } 1022 panels { room: "Wonderland" name: "APRIL" }
@@ -1004,6 +1025,7 @@ doors {
1004 panels { room: "Wonderland" name: "ARTS" } 1025 panels { room: "Wonderland" name: "ARTS" }
1005 panels { room: "Wonderland" name: "SONG" } 1026 panels { room: "Wonderland" name: "SONG" }
1006 location_room: "Wonderland" 1027 location_room: "Wonderland"
1028 location_name: "Wonderland"
1007} 1029}
1008doors { 1030doors {
1009 name: "Pyramid Entrance" 1031 name: "Pyramid Entrance"
@@ -1034,6 +1056,7 @@ doors {
1034 panels { room: "Orange Room" name: "COAL" } 1056 panels { room: "Orange Room" name: "COAL" }
1035 panels { room: "Orange Room" name: "OWED" } 1057 panels { room: "Orange Room" name: "OWED" }
1036 location_room: "Orange Room" 1058 location_room: "Orange Room"
1059 location_name: "Puzzles"
1037} 1060}
1038doors { 1061doors {
1039 name: "Hedges Entrance" 1062 name: "Hedges Entrance"
@@ -1052,6 +1075,7 @@ doors {
1052 panels { room: "Outside Snake Room" name: "SONG (South)" } 1075 panels { room: "Outside Snake Room" name: "SONG (South)" }
1053 panels { room: "West Castle Area" name: "SONG (2)" } 1076 panels { room: "West Castle Area" name: "SONG (2)" }
1054 location_room: "West Castle Area" 1077 location_room: "West Castle Area"
1078 location_name: "South SONGs"
1055} 1079}
1056doors { 1080doors {
1057 name: "Amber North Door" 1081 name: "Amber North Door"
@@ -1060,6 +1084,7 @@ doors {
1060 panels { room: "Outside Snake Room" name: "SONG (North)" } 1084 panels { room: "Outside Snake Room" name: "SONG (North)" }
1061 panels { room: "Amber North 2" name: "SONG" } 1085 panels { room: "Amber North 2" name: "SONG" }
1062 location_room: "Amber North 2" 1086 location_room: "Amber North 2"
1087 location_name: "North SONGs"
1063} 1088}
1064doors { 1089doors {
1065 name: "Amber East Doors" 1090 name: "Amber East Doors"
@@ -1182,70 +1207,37 @@ doors {
1182 type: ITEM_ONLY 1207 type: ITEM_ONLY
1183 receivers: "Components/Doors/Halls/connections_1" 1208 receivers: "Components/Doors/Halls/connections_1"
1184 receivers: "Components/Doors/Halls/connections_3" 1209 receivers: "Components/Doors/Halls/connections_3"
1210 # These have the same effect as the above, but including them here prevents
1211 # them from opening in door shuffle when the J2 door opens.
1212 receivers: "Components/Triggers/teleportListenerConnections3"
1213 receivers: "Components/Triggers/teleportListenerConnections4"
1214 # This door can open from either solving all panels, or just the smiley ones,
1215 # and the latter is obviously a subset of the former so let's just check for
1216 # that.
1185 panels { room: "Hotel" name: "PARKA" } 1217 panels { room: "Hotel" name: "PARKA" }
1186 panels { room: "Hotel" name: "MARLIN" }
1187 panels { room: "Hotel" name: "WHO" }
1188 panels { room: "Hotel" name: "CLOAK" } 1218 panels { room: "Hotel" name: "CLOAK" }
1189 panels { room: "Hotel" name: "MANE" }
1190 panels { room: "Hotel" name: "WHAT" }
1191 panels { room: "Hotel" name: "BLAZER" }
1192 panels { room: "Hotel" name: "WHERE" }
1193 panels { room: "Hotel" name: "DOROTHY" } 1219 panels { room: "Hotel" name: "DOROTHY" }
1194 panels { room: "Hotel" name: "JACKET" }
1195 panels { room: "Hotel" name: "TAIL" }
1196 panels { room: "Hotel" name: "JAWS" } 1220 panels { room: "Hotel" name: "JAWS" }
1197 panels { room: "Hotel" name: "FLOUNDER" }
1198 panels { room: "Hotel" name: "WHEN" } 1221 panels { room: "Hotel" name: "WHEN" }
1199 panels { room: "Hotel" name: "CLAWS" } 1222 panels { room: "Hotel" name: "CLAWS" }
1200 panels { room: "Hotel" name: "BRUCE" }
1201 panels { room: "Hotel" name: "POTATO" } 1223 panels { room: "Hotel" name: "POTATO" }
1202 panels { room: "Hotel" name: "SALAD" }
1203 panels { room: "Hotel" name: "BATHING" }
1204 panels { room: "Hotel" name: "MICRO" } 1224 panels { room: "Hotel" name: "MICRO" }
1205 panels { room: "Hotel" name: "BUSINESS" }
1206 panels { room: "Hotel" name: "WEDDING" }
1207 panels { room: "Hotel" name: "TREE" }
1208 panels { room: "Hotel" name: "RIVER" }
1209 panels { room: "Hotel" name: "TUNING" } 1225 panels { room: "Hotel" name: "TUNING" }
1210 panels { room: "Hotel" name: "BOXING" }
1211 panels { room: "Hotel" name: "TELEPHONE" }
1212 panels { room: "Hotel" name: "LAW" } 1226 panels { room: "Hotel" name: "LAW" }
1213 panels { room: "Hotel" name: "POKER" }
1214 panels { room: "Hotel" name: "CARD" } 1227 panels { room: "Hotel" name: "CARD" }
1215 panels { room: "Hotel" name: "ROAD" } 1228 panels { room: "Hotel" name: "ROAD" }
1216 panels { room: "Hotel" name: "CHOCOLATE" }
1217 panels { room: "Hotel" name: "DEPART" } 1229 panels { room: "Hotel" name: "DEPART" }
1218 panels { room: "Hotel" name: "WITHDRAW" }
1219 panels { room: "Hotel" name: "QUIT" }
1220 panels { room: "Hotel" name: "LEAVE" } 1230 panels { room: "Hotel" name: "LEAVE" }
1221 panels { room: "Hotel" name: "PALE" }
1222 panels { room: "Hotel" name: "JUST" }
1223 panels { room: "Hotel" name: "NEW" }
1224 panels { room: "Hotel" name: "UNTALENTED" }
1225 panels { room: "Hotel" name: "SERVICE" } 1231 panels { room: "Hotel" name: "SERVICE" }
1226 panels { room: "Hotel" name: "FULL" }
1227 panels { room: "Hotel" name: "EVIL" }
1228 panels { room: "Hotel" name: "HONEY" } 1232 panels { room: "Hotel" name: "HONEY" }
1229 panels { room: "Hotel" name: "CRESCENT" }
1230 panels { room: "Hotel" name: "INVALID" } 1233 panels { room: "Hotel" name: "INVALID" }
1231 panels { room: "Hotel" name: "FESTIVAL" } 1234 panels { room: "Hotel" name: "FESTIVAL" }
1232 panels { room: "Hotel" name: "BEAUTIFUL" }
1233 panels { room: "Hotel" name: "WILTED" } 1235 panels { room: "Hotel" name: "WILTED" }
1234 panels { room: "Hotel" name: "DROOPED" }
1235 panels { room: "Hotel" name: "FADED" }
1236 panels { room: "Hotel" name: "WANED" } 1236 panels { room: "Hotel" name: "WANED" }
1237 panels { room: "Hotel" name: "TALL" }
1238 panels { room: "Hotel" name: "CANVAS" }
1239 panels { room: "Hotel" name: "LEVER" }
1240 panels { room: "Hotel" name: "SCULPTURE" }
1241 panels { room: "Hotel" name: "RAGE" } 1237 panels { room: "Hotel" name: "RAGE" }
1242 panels { room: "Hotel" name: "BALL" }
1243 panels { room: "Hotel" name: "FOOL" }
1244 panels { room: "Hotel" name: "VERGE" } 1238 panels { room: "Hotel" name: "VERGE" }
1245 panels { room: "Hotel" name: "ART" }
1246 panels { room: "Hotel" name: "EVER" } 1239 panels { room: "Hotel" name: "EVER" }
1247 panels { room: "Hotel" name: "PAIN" } 1240 panels { room: "Hotel" name: "PAIN" }
1248 panels { room: "Hotel" name: "FOOT" }
1249} 1241}
1250doors { 1242doors {
1251 name: "J2 Door 1" 1243 name: "J2 Door 1"
@@ -1281,7 +1273,7 @@ doors {
1281 panels { room: "J2 Vestibule" name: "COLORFUL" } 1273 panels { room: "J2 Vestibule" name: "COLORFUL" }
1282} 1274}
1283doors { 1275doors {
1284 name: "Wonderland Left Door" 1276 name: "Wonderland North Door"
1285 type: ITEM_ONLY 1277 type: ITEM_ONLY
1286 receivers: "Components/Doors/Halls/wonderland_2" 1278 receivers: "Components/Doors/Halls/wonderland_2"
1287 panels { room: "Wonderland" name: "APRIL" } 1279 panels { room: "Wonderland" name: "APRIL" }
@@ -1389,12 +1381,32 @@ doors {
1389} 1381}
1390doors { 1382doors {
1391 name: "Roof Access" 1383 name: "Roof Access"
1392 type: STANDARD 1384 type: ITEM_ONLY
1393 receivers: "Components/Doors/Castle/entry_stairs_big" 1385 receivers: "Components/Doors/Castle/entry_stairs_big"
1394 receivers: "Components/Doors/Castle/entry_stairs_big2" 1386 receivers: "Components/Doors/Castle/entry_stairs_big2"
1387 receivers: "Meshes/Stairs/staircase31/teleportListener"
1388 receivers: "Meshes/Stairs/staircase32/teleportListener2"
1389 receivers: "Meshes/Stairs/staircase33/teleportListener3"
1395 panels { room: "North Castle Area" name: "A SUMMER PLACE" } 1390 panels { room: "North Castle Area" name: "A SUMMER PLACE" }
1396 panels { room: "West Castle Area" name: "SONG FACE" } 1391 panels { room: "West Castle Area" name: "SONG FACE" }
1397 panels { room: "South Castle Area" name: "AN OFFER VILLAGE BEFORE LAIR" } 1392 panels { room: "South Castle Area" name: "AN OFFER VILLAGE BEFORE LAIR" }
1393}
1394doors {
1395 name: "North Castle Panel"
1396 type: LOCATION_ONLY
1397 panels { room: "North Castle Area" name: "A SUMMER PLACE" }
1398 location_room: "North Castle Area"
1399}
1400doors {
1401 name: "West Castle Panel"
1402 type: LOCATION_ONLY
1403 panels { room: "West Castle Area" name: "SONG FACE" }
1404 location_room: "West Castle Area"
1405}
1406doors {
1407 name: "South Castle Panel"
1408 type: LOCATION_ONLY
1409 panels { room: "South Castle Area" name: "AN OFFER VILLAGE BEFORE LAIR" }
1398 location_room: "South Castle Area" 1410 location_room: "South Castle Area"
1399} 1411}
1400doors { 1412doors {
@@ -1411,6 +1423,7 @@ doors {
1411 panels { room: "West Spire" name: "CUT" } 1423 panels { room: "West Spire" name: "CUT" }
1412 panels { room: "West Spire" name: "STONES" } 1424 panels { room: "West Spire" name: "STONES" }
1413 location_room: "West Spire" 1425 location_room: "West Spire"
1426 location_name: "Pairs Room Puzzles"
1414} 1427}
1415doors { 1428doors {
1416 name: "Pairs Room West Door" 1429 name: "Pairs Room West Door"
@@ -1453,87 +1466,87 @@ doors {
1453} 1466}
1454doors { 1467doors {
1455 name: "Red Rainbow Room" 1468 name: "Red Rainbow Room"
1456 type: ITEM_ONLY 1469 type: STANDARD
1457 receivers: "Components/Doors/Color Reading/door_3" 1470 receivers: "Components/Doors/Color Reading/door_3"
1458 panels { room: "Rainbow Start" name: "PAINTING" } 1471 panels { room: "Rainbow Start" name: "PAINTING" }
1459 panels { room: "Red Smiley" name: "SMILE" } 1472 location_room: "Rainbow Start"
1460} 1473}
1461doors { 1474doors {
1462 name: "Orange Rainbow Room" 1475 name: "Orange Rainbow Room"
1463 type: ITEM_ONLY 1476 type: ITEM_ONLY
1464 receivers: "Components/Doors/Color Reading/door_4" 1477 receivers: "Components/Doors/Color Reading/door_4"
1465 panels { room: "Rainbow Red" name: "THEME" } 1478 panels { room: "Rainbow Red" name: "THEME" }
1466 panels { room: "Outside Orange Room" name: "SMILE" } 1479 panels { room: "Red Smiley" name: "SMILE" }
1467} 1480}
1468doors { 1481doors {
1469 name: "Yellow Rainbow Room" 1482 name: "Yellow Rainbow Room"
1470 type: ITEM_ONLY 1483 type: ITEM_ONLY
1471 receivers: "Components/Doors/Color Reading/door_17" 1484 receivers: "Components/Doors/Color Reading/door_17"
1472 panels { room: "Rainbow Orange" name: "THEME" } 1485 panels { room: "Rainbow Orange" name: "THEME" }
1473 panels { room: "Hedges" name: "SMILE" } 1486 panels { room: "Outside Orange Room" name: "SMILE" }
1474} 1487}
1475doors { 1488doors {
1476 name: "Green Rainbow Room" 1489 name: "Green Rainbow Room"
1477 type: ITEM_ONLY 1490 type: ITEM_ONLY
1478 receivers: "Components/Doors/Color Reading/door_5" 1491 receivers: "Components/Doors/Color Reading/door_5"
1479 panels { room: "Rainbow Yellow" name: "THEME" } 1492 panels { room: "Rainbow Yellow" name: "THEME" }
1480 panels { room: "Green Smiley" name: "SMILE" } 1493 panels { room: "Hedges" name: "SMILE" }
1481} 1494}
1482doors { 1495doors {
1483 name: "Blue Rainbow Room" 1496 name: "Blue Rainbow Room"
1484 type: ITEM_ONLY 1497 type: ITEM_ONLY
1485 receivers: "Components/Doors/Color Reading/door_6" 1498 receivers: "Components/Doors/Color Reading/door_6"
1486 panels { room: "Rainbow Green" name: "THEME" } 1499 panels { room: "Rainbow Green" name: "THEME" }
1487 panels { room: "Blue Smiley" name: "SMILE" } 1500 panels { room: "Green Smiley" name: "SMILE" }
1488} 1501}
1489doors { 1502doors {
1490 name: "Purple Rainbow Room" 1503 name: "Purple Rainbow Room"
1491 type: ITEM_ONLY 1504 type: ITEM_ONLY
1492 receivers: "Components/Doors/Color Reading/door_7" 1505 receivers: "Components/Doors/Color Reading/door_7"
1493 panels { room: "Rainbow Blue" name: "THEME" } 1506 panels { room: "Rainbow Blue" name: "THEME" }
1494 panels { room: "Purple Smiley" name: "SMILE" } 1507 panels { room: "Blue Smiley" name: "SMILE" }
1495} 1508}
1496doors { 1509doors {
1497 name: "Red Rainbow Panel" 1510 name: "Red Rainbow Panel"
1498 type: LOCATION_ONLY 1511 type: LOCATION_ONLY
1499 panels { room: "Rainbow Start" name: "PAINTING" }
1500 location_room: "Rainbow Start"
1501}
1502doors {
1503 name: "Orange Rainbow Panel"
1504 type: LOCATION_ONLY
1505 panels { room: "Rainbow Red" name: "THEME" } 1512 panels { room: "Rainbow Red" name: "THEME" }
1506 location_room: "Rainbow Red" 1513 location_room: "Rainbow Red"
1507} 1514}
1508doors { 1515doors {
1509 name: "Yellow Rainbow Panel" 1516 name: "Orange Rainbow Panel"
1510 type: LOCATION_ONLY 1517 type: LOCATION_ONLY
1511 panels { room: "Rainbow Orange" name: "THEME" } 1518 panels { room: "Rainbow Orange" name: "THEME" }
1512 location_room: "Rainbow Orange" 1519 location_room: "Rainbow Orange"
1513} 1520}
1514doors { 1521doors {
1515 name: "Green Rainbow Panel" 1522 name: "Yellow Rainbow Panel"
1516 type: LOCATION_ONLY 1523 type: LOCATION_ONLY
1517 panels { room: "Rainbow Yellow" name: "THEME" } 1524 panels { room: "Rainbow Yellow" name: "THEME" }
1518 location_room: "Rainbow Yellow" 1525 location_room: "Rainbow Yellow"
1519} 1526}
1520doors { 1527doors {
1521 name: "Blue Rainbow Panel" 1528 name: "Green Rainbow Panel"
1522 type: LOCATION_ONLY 1529 type: LOCATION_ONLY
1523 panels { room: "Rainbow Green" name: "THEME" } 1530 panels { room: "Rainbow Green" name: "THEME" }
1524 location_room: "Rainbow Green" 1531 location_room: "Rainbow Green"
1525} 1532}
1526doors { 1533doors {
1527 name: "Purple Rainbow Panel" 1534 name: "Blue Rainbow Panel"
1528 type: LOCATION_ONLY 1535 type: LOCATION_ONLY
1529 panels { room: "Rainbow Blue" name: "THEME" } 1536 panels { room: "Rainbow Blue" name: "THEME" }
1530 location_room: "Rainbow Blue" 1537 location_room: "Rainbow Blue"
1531} 1538}
1532doors { 1539doors {
1533 name: "Cyan Rainbow Room" 1540 name: "Cyan Rainbow Room"
1534 type: STANDARD 1541 type: ITEM_ONLY
1535 receivers: "Components/Doors/Color Reading/door_18" 1542 receivers: "Components/Doors/Color Reading/door_18"
1536 panels { room: "Rainbow Purple" name: "THEME" } 1543 panels { room: "Rainbow Purple" name: "THEME" }
1544 panels { room: "Purple Smiley" name: "SMILE" }
1545}
1546doors {
1547 name: "Purple Rainbow Panel"
1548 type: LOCATION_ONLY
1549 panels { room: "Rainbow Purple" name: "THEME" }
1537 location_room: "Rainbow Purple" 1550 location_room: "Rainbow Purple"
1538} 1551}
1539doors { 1552doors {
@@ -1542,6 +1555,7 @@ doors {
1542 receivers: "Components/Doors/Color Reading/door_8" 1555 receivers: "Components/Doors/Color Reading/door_8"
1543 panels { room: "Rainbow Cyan" name: "THEME" } 1556 panels { room: "Rainbow Cyan" name: "THEME" }
1544 location_room: "Rainbow Cyan" 1557 location_room: "Rainbow Cyan"
1558 location_name: "Cyan Rainbow Panel"
1545} 1559}
1546doors { 1560doors {
1547 name: "Pepper Room Entrance" 1561 name: "Pepper Room Entrance"
@@ -1565,6 +1579,7 @@ doors {
1565 panels { room: "Salt Room" name: "SEASONING" } 1579 panels { room: "Salt Room" name: "SEASONING" }
1566 panels { room: "Pepper Room" name: "SEASONING" } 1580 panels { room: "Pepper Room" name: "SEASONING" }
1567 location_room: "Pepper Room" 1581 location_room: "Pepper Room"
1582 location_name: "Seasonings"
1568} 1583}
1569doors { 1584doors {
1570 name: "Bow Side" 1585 name: "Bow Side"
@@ -1600,6 +1615,7 @@ doors {
1600 # Components/Doors/Smileys/blue_1 1615 # Components/Doors/Smileys/blue_1
1601 panels { room: "Blue Smiley" name: "SMILE" } 1616 panels { room: "Blue Smiley" name: "SMILE" }
1602 location_room: "Blue Smiley" 1617 location_room: "Blue Smiley"
1618 location_name: "Blue SMILE"
1603} 1619}
1604doors { 1620doors {
1605 name: "Blue Smiley Annex" 1621 name: "Blue Smiley Annex"
@@ -1631,6 +1647,7 @@ doors {
1631 receivers: "Components/Doors/Smileys/yellow_2" 1647 receivers: "Components/Doors/Smileys/yellow_2"
1632 panels { room: "Hedges" name: "SMILE" } 1648 panels { room: "Hedges" name: "SMILE" }
1633 location_room: "Hedges" 1649 location_room: "Hedges"
1650 location_name: "Yellow SMILE"
1634} 1651}
1635doors { 1652doors {
1636 name: "Green Smiley" 1653 name: "Green Smiley"
@@ -1639,6 +1656,7 @@ doors {
1639 receivers: "Components/Doors/Smileys/green_2" 1656 receivers: "Components/Doors/Smileys/green_2"
1640 panels { room: "Green Smiley" name: "SMILE" } 1657 panels { room: "Green Smiley" name: "SMILE" }
1641 location_room: "Green Smiley" 1658 location_room: "Green Smiley"
1659 location_name: "Green SMILE"
1642} 1660}
1643doors { 1661doors {
1644 name: "Orange Smiley Exit" 1662 name: "Orange Smiley Exit"
@@ -1646,6 +1664,7 @@ doors {
1646 receivers: "Components/Doors/Smileys/orange_1" 1664 receivers: "Components/Doors/Smileys/orange_1"
1647 panels { room: "Outside Orange Room" name: "SMILE" } 1665 panels { room: "Outside Orange Room" name: "SMILE" }
1648 location_room: "Outside Orange Room" 1666 location_room: "Outside Orange Room"
1667 location_name: "Orange SMILE"
1649} 1668}
1650doors { 1669doors {
1651 name: "F Keyholder Door" 1670 name: "F Keyholder Door"
@@ -1670,6 +1689,7 @@ doors {
1670 type: LOCATION_ONLY 1689 type: LOCATION_ONLY
1671 panels { room: "Red Smiley" name: "SMILE" } 1690 panels { room: "Red Smiley" name: "SMILE" }
1672 location_room: "Red Smiley" 1691 location_room: "Red Smiley"
1692 location_name: "Red SMILE"
1673} 1693}
1674doors { 1694doors {
1675 name: "Pink Hallway" 1695 name: "Pink Hallway"
@@ -1708,6 +1728,7 @@ doors {
1708 panels { room: "Cyan Room" name: "COLD" } 1728 panels { room: "Cyan Room" name: "COLD" }
1709 panels { room: "Cyan Room" name: "WORDWORD" } 1729 panels { room: "Cyan Room" name: "WORDWORD" }
1710 location_room: "Cyan Room" 1730 location_room: "Cyan Room"
1731 location_name: "Puzzles"
1711} 1732}
1712doors { 1733doors {
1713 name: "Green Room Entrance" 1734 name: "Green Room Entrance"
@@ -1731,6 +1752,7 @@ doors {
1731 panels { room: "Green Room" name: "DOUBLE" } 1752 panels { room: "Green Room" name: "DOUBLE" }
1732 panels { room: "Green Room" name: "BADMINTON" } 1753 panels { room: "Green Room" name: "BADMINTON" }
1733 location_room: "Green Room" 1754 location_room: "Green Room"
1755 location_name: "Puzzles"
1734} 1756}
1735doors { 1757doors {
1736 name: "Blue Hallway South Divider" 1758 name: "Blue Hallway South Divider"
@@ -1769,6 +1791,7 @@ doors {
1769 panels { room: "Red Room" name: "TESTAMENT" } 1791 panels { room: "Red Room" name: "TESTAMENT" }
1770 panels { room: "Red Room" name: "TAKEOUT" } 1792 panels { room: "Red Room" name: "TAKEOUT" }
1771 location_room: "Red Room" 1793 location_room: "Red Room"
1794 location_name: "Puzzles"
1772} 1795}
1773doors { 1796doors {
1774 name: "Blue Hallway To Red Room" 1797 name: "Blue Hallway To Red Room"
@@ -1782,6 +1805,7 @@ doors {
1782 panels { room: "Blue Hallway" name: "CHOP" } 1805 panels { room: "Blue Hallway" name: "CHOP" }
1783 panels { room: "Blue Hallway Tall Side" name: "TALL" } 1806 panels { room: "Blue Hallway Tall Side" name: "TALL" }
1784 location_room: "Blue Hallway Tall Side" 1807 location_room: "Blue Hallway Tall Side"
1808 location_name: "CHOP, TALL"
1785} 1809}
1786doors { 1810doors {
1787 name: "Near Yellow Room Door" 1811 name: "Near Yellow Room Door"
@@ -1794,6 +1818,7 @@ doors {
1794 panels { room: "Blue Hallway Tall Side" name: "CHILD" } 1818 panels { room: "Blue Hallway Tall Side" name: "CHILD" }
1795 panels { room: "Blue Hallway Tall Side" name: "NEW" } 1819 panels { room: "Blue Hallway Tall Side" name: "NEW" }
1796 location_room: "Blue Hallway Tall Side" 1820 location_room: "Blue Hallway Tall Side"
1821 location_name: "Pink Hex"
1797} 1822}
1798doors { 1823doors {
1799 name: "House Side Door" 1824 name: "House Side Door"
@@ -1830,6 +1855,7 @@ doors {
1830 panels { room: "Yellow Room" name: "PROTON" } 1855 panels { room: "Yellow Room" name: "PROTON" }
1831 panels { room: "Yellow Room" name: "SPIRIT" } 1856 panels { room: "Yellow Room" name: "SPIRIT" }
1832 location_room: "Yellow Room" 1857 location_room: "Yellow Room"
1858 location_name: "Puzzles"
1833} 1859}
1834doors { 1860doors {
1835 name: "Dark Light Room Entrance" 1861 name: "Dark Light Room Entrance"
@@ -1865,6 +1891,7 @@ doors {
1865 type: LOCATION_ONLY 1891 type: LOCATION_ONLY
1866 panels { room: "Dark Light Exit" name: "GASKET" } 1892 panels { room: "Dark Light Exit" name: "GASKET" }
1867 location_room: "Dark Light Exit" 1893 location_room: "Dark Light Exit"
1894 location_name: "GASKET"
1868} 1895}
1869doors { 1896doors {
1870 name: "Dark Light Room Divider" 1897 name: "Dark Light Room Divider"
@@ -1884,6 +1911,7 @@ doors {
1884 # Not technically true; it's complete_at=11 with both rooms, but you couldn't 1911 # Not technically true; it's complete_at=11 with both rooms, but you couldn't
1885 # get to the other side in vanilla doors anyway. 1912 # get to the other side in vanilla doors anyway.
1886 location_room: "Dark Light Room" 1913 location_room: "Dark Light Room"
1914 location_name: "Main Puzzles"
1887} 1915}
1888doors { 1916doors {
1889 name: "Near Sweet Blue Door" 1917 name: "Near Sweet Blue Door"
@@ -1896,6 +1924,7 @@ doors {
1896 panels { room: "Gray Color Backside" name: "LAST" } 1924 panels { room: "Gray Color Backside" name: "LAST" }
1897 panels { room: "Gray Color Backside" name: "RISE" } 1925 panels { room: "Gray Color Backside" name: "RISE" }
1898 location_room: "Gray Color Backside" 1926 location_room: "Gray Color Backside"
1927 location_name: "Light Green Hex"
1899} 1928}
1900doors { 1929doors {
1901 name: "South Castle Area Back Door" 1930 name: "South Castle Area Back Door"
@@ -1935,6 +1964,7 @@ doors {
1935 panels { room: "Plum Room" name: "SNAKE" } 1964 panels { room: "Plum Room" name: "SNAKE" }
1936 panels { room: "Plum Room" name: "CENTER" } 1965 panels { room: "Plum Room" name: "CENTER" }
1937 location_room: "Plum Room" 1966 location_room: "Plum Room"
1967 location_name: "Plum Room"
1938} 1968}
1939doors { 1969doors {
1940 name: "D Keyholder Blocker" 1970 name: "D Keyholder Blocker"
@@ -2036,6 +2066,7 @@ doors {
2036 panels { room: "Computer Room" name: "MOUSE (2)" } 2066 panels { room: "Computer Room" name: "MOUSE (2)" }
2037 panels { room: "Computer Room" name: "KEYBOARD (2)" } 2067 panels { room: "Computer Room" name: "KEYBOARD (2)" }
2038 location_room: "Computer Room" 2068 location_room: "Computer Room"
2069 location_name: "Main Puzzles"
2039} 2070}
2040doors { 2071doors {
2041 name: "Computer Room Entrance" 2072 name: "Computer Room Entrance"
@@ -2048,12 +2079,17 @@ doors {
2048 panels { room: "Rainbow Color Doors" name: "MISCHIEF" } 2079 panels { room: "Rainbow Color Doors" name: "MISCHIEF" }
2049 panels { room: "Rainbow Color Doors" name: "CASUAL" } 2080 panels { room: "Rainbow Color Doors" name: "CASUAL" }
2050 location_room: "Rainbow Color Doors" 2081 location_room: "Rainbow Color Doors"
2082 location_name: "Red Tower"
2051} 2083}
2052doors { 2084doors {
2053 name: "C Keyholder Blocker" 2085 name: "C Keyholder Blocker"
2054 type: EVENT 2086 type: EVENT
2055 # Components/Doors/Unincorporated/temple_foyer_7 2087 receivers: "Components/Doors/Unincorporated/temple_foyer_7"
2056 switches: "lavender_cubes" 2088 panels {
2089 map: "the_ancient"
2090 room: "Inside"
2091 name: "COLOR"
2092 }
2057} 2093}
2058doors { 2094doors {
2059 name: "Computer Room Back Door" 2095 name: "Computer Room Back Door"
@@ -2115,6 +2151,7 @@ doors {
2115 panels { room: "Book Room" name: "BOOK (11)" } 2151 panels { room: "Book Room" name: "BOOK (11)" }
2116 panels { room: "Book Room" name: "BOOK (12)" } 2152 panels { room: "Book Room" name: "BOOK (12)" }
2117 location_room: "Book Room" 2153 location_room: "Book Room"
2154 location_name: "Book Room"
2118} 2155}
2119doors { 2156doors {
2120 name: "Sticks And Stones Door" 2157 name: "Sticks And Stones Door"
@@ -2122,6 +2159,7 @@ doors {
2122 receivers: "Components/Doors/Unincorporated/temple_foyer_6" 2159 receivers: "Components/Doors/Unincorporated/temple_foyer_6"
2123 panels { room: "Globe Room" name: "WORD" } 2160 panels { room: "Globe Room" name: "WORD" }
2124 location_room: "Globe Room" 2161 location_room: "Globe Room"
2162 location_name: "Sticks and Stones"
2125} 2163}
2126doors { 2164doors {
2127 name: "Castle Numbers Puzzle" 2165 name: "Castle Numbers Puzzle"
@@ -2141,6 +2179,7 @@ doors {
2141 panels { room: "Black Hex" name: "BARK" } 2179 panels { room: "Black Hex" name: "BARK" }
2142 panels { room: "Zoo N" name: "LEAF" } 2180 panels { room: "Zoo N" name: "LEAF" }
2143 location_room: "Zoo N" 2181 location_room: "Zoo N"
2182 location_name: "BARK, LEAF"
2144} 2183}
2145doors { 2184doors {
2146 name: "Zoo East Entrance" 2185 name: "Zoo East Entrance"
@@ -2226,3 +2265,38 @@ doors {
2226 panels { room: "Yellow Color Backside" name: "REDACTED" } 2265 panels { room: "Yellow Color Backside" name: "REDACTED" }
2227 location_room: "Yellow Color Backside" 2266 location_room: "Yellow Color Backside"
2228} 2267}
2268doors {
2269 name: "Tenacious Color Painting"
2270 type: EVENT
2271 panels { room: "South Castle Area" name: "COLOR (1)" answer: "red" }
2272 panels { room: "South Castle Area" name: "COLOR (2)" answer: "yellow" }
2273 panels { room: "South Castle Area" name: "COLOR (3)" answer: "purple" }
2274 panels { room: "South Castle Area" name: "COLOR (4)" answer: "green" }
2275}
2276doors {
2277 name: "Eye Painting"
2278 type: ITEM_ONLY
2279 receivers: "Components/Paintings/Temple of the Eyes/eyeRedStart/teleportListener"
2280 double_letters: true
2281}
2282doors {
2283 name: "Lime Hexes"
2284 type: LOCATION_ONLY
2285 panels { room: "Tree Entrance" name: "RAT" }
2286 panels { room: "Tree Entrance" name: "DIFFERENCE" }
2287 panels { room: "Tree Entrance" name: "LEANS" }
2288 panels { room: "Tree Entrance" name: "QUESTION" }
2289 panels { room: "Tree Entrance" name: "WHERE" }
2290 panels { room: "Tree Entrance" name: "SUNDER" }
2291 location_room: "Tree Entrance"
2292}
2293doors {
2294 name: "Theo Panels"
2295 type: LOCATION_ONLY
2296 panels { room: "House" name: "GOAT" }
2297 panels { room: "House" name: "AMAZE" }
2298 panels { room: "House" name: "SKINNYHIM" }
2299 panels { room: "House" name: "THEO" }
2300 location_room: "House"
2301 location_name: "All Puzzles"
2302}
diff --git a/data/maps/daedalus/rooms/After Bee Room.txtpb b/data/maps/daedalus/rooms/After Bee Room.txtpb index f38bd7d..c2dfc0f 100644 --- a/data/maps/daedalus/rooms/After Bee Room.txtpb +++ b/data/maps/daedalus/rooms/After Bee Room.txtpb
@@ -1,5 +1,5 @@
1name: "After Bee Room" 1name: "After Bee Room"
2display_name: "North Area" 2panel_display_name: "North Area"
3panels { 3panels {
4 name: "GAS" 4 name: "GAS"
5 path: "Panels/Beehalls/beehalls_2" 5 path: "Panels/Beehalls/beehalls_2"
diff --git a/data/maps/daedalus/rooms/Amber North 2.txtpb b/data/maps/daedalus/rooms/Amber North 2.txtpb index 8fbaccd..7029695 100644 --- a/data/maps/daedalus/rooms/Amber North 2.txtpb +++ b/data/maps/daedalus/rooms/Amber North 2.txtpb
@@ -1,5 +1,5 @@
1name: "Amber North 2" 1name: "Amber North 2"
2display_name: "West Area" 2panel_display_name: "West Area"
3panels { 3panels {
4 name: "SONG" 4 name: "SONG"
5 path: "Panels/Amber/amber_north_2" 5 path: "Panels/Amber/amber_north_2"
diff --git a/data/maps/daedalus/rooms/Bee Room Obverse.txtpb b/data/maps/daedalus/rooms/Bee Room Obverse.txtpb index 1badbc0..7677ed1 100644 --- a/data/maps/daedalus/rooms/Bee Room Obverse.txtpb +++ b/data/maps/daedalus/rooms/Bee Room Obverse.txtpb
@@ -1,5 +1,5 @@
1name: "Bee Room Obverse" 1name: "Bee Room Obverse"
2display_name: "Bee Room" 2panel_display_name: "Bee Room"
3panels { 3panels {
4 name: "SINGLE" 4 name: "SINGLE"
5 path: "Panels/Bee Room/bee_1" 5 path: "Panels/Bee Room/bee_1"
diff --git a/data/maps/daedalus/rooms/Bee Room Reverse.txtpb b/data/maps/daedalus/rooms/Bee Room Reverse.txtpb index f455f06..cba8285 100644 --- a/data/maps/daedalus/rooms/Bee Room Reverse.txtpb +++ b/data/maps/daedalus/rooms/Bee Room Reverse.txtpb
@@ -1,5 +1,5 @@
1name: "Bee Room Reverse" 1name: "Bee Room Reverse"
2display_name: "Bee Room" 2panel_display_name: "Bee Room"
3panels { 3panels {
4 name: "POCKET" 4 name: "POCKET"
5 path: "Panels/Bee Room/bee_9" 5 path: "Panels/Bee Room/bee_9"
diff --git a/data/maps/daedalus/rooms/Beehalls Intersection.txtpb b/data/maps/daedalus/rooms/Beehalls Intersection.txtpb index fecf71d..7ecbe50 100644 --- a/data/maps/daedalus/rooms/Beehalls Intersection.txtpb +++ b/data/maps/daedalus/rooms/Beehalls Intersection.txtpb
@@ -1,5 +1,5 @@
1name: "Beehalls Intersection" 1name: "Beehalls Intersection"
2display_name: "North Area" 2panel_display_name: "North Area"
3panels { 3panels {
4 name: "CLOUDS" 4 name: "CLOUDS"
5 path: "Panels/Halls/beehalls_4" 5 path: "Panels/Halls/beehalls_4"
diff --git a/data/maps/daedalus/rooms/Black Hex.txtpb b/data/maps/daedalus/rooms/Black Hex.txtpb index bd8359e..1276685 100644 --- a/data/maps/daedalus/rooms/Black Hex.txtpb +++ b/data/maps/daedalus/rooms/Black Hex.txtpb
@@ -1,5 +1,5 @@
1name: "Black Hex" 1name: "Black Hex"
2display_name: "Northwest Area" 2panel_display_name: "Northwest Area"
3panels { 3panels {
4 name: "HIDE" 4 name: "HIDE"
5 path: "Panels/Hexes/black_1" 5 path: "Panels/Hexes/black_1"
diff --git a/data/maps/daedalus/rooms/Blue Hallway Cut Side.txtpb b/data/maps/daedalus/rooms/Blue Hallway Cut Side.txtpb index ea2ffef..5a6c081 100644 --- a/data/maps/daedalus/rooms/Blue Hallway Cut Side.txtpb +++ b/data/maps/daedalus/rooms/Blue Hallway Cut Side.txtpb
@@ -1,5 +1,5 @@
1name: "Blue Hallway Cut Side" 1name: "Blue Hallway Cut Side"
2display_name: "South Area" 2panel_display_name: "South Area"
3panels { 3panels {
4 name: "CUT" 4 name: "CUT"
5 path: "Panels/Halls/halls_6" 5 path: "Panels/Halls/halls_6"
diff --git a/data/maps/daedalus/rooms/Blue Hallway Tall Side.txtpb b/data/maps/daedalus/rooms/Blue Hallway Tall Side.txtpb index 93d4136..4a775d8 100644 --- a/data/maps/daedalus/rooms/Blue Hallway Tall Side.txtpb +++ b/data/maps/daedalus/rooms/Blue Hallway Tall Side.txtpb
@@ -1,5 +1,5 @@
1name: "Blue Hallway Tall Side" 1name: "Blue Hallway Tall Side"
2display_name: "Northeast Area" 2panel_display_name: "Northeast Area"
3panels { 3panels {
4 name: "TALL" 4 name: "TALL"
5 path: "Panels/Halls/halls_9" 5 path: "Panels/Halls/halls_9"
diff --git a/data/maps/daedalus/rooms/Blue Hallway.txtpb b/data/maps/daedalus/rooms/Blue Hallway.txtpb index 0bac459..81bc428 100644 --- a/data/maps/daedalus/rooms/Blue Hallway.txtpb +++ b/data/maps/daedalus/rooms/Blue Hallway.txtpb
@@ -1,5 +1,5 @@
1name: "Blue Hallway" 1name: "Blue Hallway"
2display_name: "South Area" 2panel_display_name: "South Area"
3panels { 3panels {
4 name: "CHOP" 4 name: "CHOP"
5 path: "Panels/Halls/halls_10" 5 path: "Panels/Halls/halls_10"
diff --git a/data/maps/daedalus/rooms/Blue Room.txtpb b/data/maps/daedalus/rooms/Blue Room.txtpb index 98d933b..1d060d8 100644 --- a/data/maps/daedalus/rooms/Blue Room.txtpb +++ b/data/maps/daedalus/rooms/Blue Room.txtpb
@@ -1,5 +1,5 @@
1name: "Blue Room" 1name: "Blue Room"
2display_name: "East Area" 2panel_display_name: "Blue Room"
3panels { 3panels {
4 name: "RED" 4 name: "RED"
5 path: "Panels/Blue Room/panel_1" 5 path: "Panels/Blue Room/panel_1"
diff --git a/data/maps/daedalus/rooms/Blue Smiley Annex.txtpb b/data/maps/daedalus/rooms/Blue Smiley Annex.txtpb index c39aeb5..d44bf1a 100644 --- a/data/maps/daedalus/rooms/Blue Smiley Annex.txtpb +++ b/data/maps/daedalus/rooms/Blue Smiley Annex.txtpb
@@ -1,5 +1,5 @@
1name: "Blue Smiley Annex" 1name: "Blue Smiley Annex"
2display_name: "South Area" 2panel_display_name: "South Area"
3panels { 3panels {
4 name: "ORANGE (1)" 4 name: "ORANGE (1)"
5 path: "Panels/Miscellaneous/yellow" 5 path: "Panels/Miscellaneous/yellow"
diff --git a/data/maps/daedalus/rooms/Blue Smiley.txtpb b/data/maps/daedalus/rooms/Blue Smiley.txtpb index 5ddb330..8464525 100644 --- a/data/maps/daedalus/rooms/Blue Smiley.txtpb +++ b/data/maps/daedalus/rooms/Blue Smiley.txtpb
@@ -1,5 +1,5 @@
1name: "Blue Smiley" 1name: "Blue Smiley"
2display_name: "South Area" 2panel_display_name: "South Area"
3panels { 3panels {
4 name: "SMILE" 4 name: "SMILE"
5 path: "Panels/Smiley Rooms/blue" 5 path: "Panels/Smiley Rooms/blue"
diff --git a/data/maps/daedalus/rooms/Book Room.txtpb b/data/maps/daedalus/rooms/Book Room.txtpb index 7571ec1..534fbfe 100644 --- a/data/maps/daedalus/rooms/Book Room.txtpb +++ b/data/maps/daedalus/rooms/Book Room.txtpb
@@ -1,5 +1,5 @@
1name: "Book Room" 1name: "Book Room"
2display_name: "Southwest Area" 2panel_display_name: "Southwest Area"
3panels { 3panels {
4 name: "BOOK (1)" 4 name: "BOOK (1)"
5 path: "Panels/Book Room/book_1" 5 path: "Panels/Book Room/book_1"
diff --git a/data/maps/daedalus/rooms/Bow Side.txtpb b/data/maps/daedalus/rooms/Bow Side.txtpb index 6e07925..f04065d 100644 --- a/data/maps/daedalus/rooms/Bow Side.txtpb +++ b/data/maps/daedalus/rooms/Bow Side.txtpb
@@ -1,9 +1,10 @@
1name: "Bow Side" 1name: "Bow Side"
2display_name: "Rainbow" 2panel_display_name: "Rainbow"
3panels { 3panels {
4 name: "?" 4 name: "?"
5 path: "Panels/Smiley Rooms/bow" 5 path: "Panels/Smiley Rooms/bow"
6 clue: "" 6 clue: ""
7 answer: "bow" 7 answer: "bow"
8 symbols: QUESTION 8 symbols: QUESTION
9 display_name: "? (2)"
9} 10}
diff --git a/data/maps/daedalus/rooms/Brown Smiley.txtpb b/data/maps/daedalus/rooms/Brown Smiley.txtpb index 91ba963..53783c1 100644 --- a/data/maps/daedalus/rooms/Brown Smiley.txtpb +++ b/data/maps/daedalus/rooms/Brown Smiley.txtpb
@@ -1,5 +1,5 @@
1name: "Brown Smiley" 1name: "Brown Smiley"
2display_name: "Rainbow" 2panel_display_name: "Rainbow"
3panels { 3panels {
4 name: "OTHERS" 4 name: "OTHERS"
5 path: "Panels/Smiley Rooms/rainbow2" 5 path: "Panels/Smiley Rooms/rainbow2"
diff --git a/data/maps/daedalus/rooms/C Keyholder.txtpb b/data/maps/daedalus/rooms/C Keyholder.txtpb index a8ad9aa..28793b2 100644 --- a/data/maps/daedalus/rooms/C Keyholder.txtpb +++ b/data/maps/daedalus/rooms/C Keyholder.txtpb
@@ -1,6 +1,7 @@
1name: "C Keyholder" 1name: "C Keyholder"
2display_name: "North Area" 2panel_display_name: "East Area"
3keyholders { 3keyholders {
4 name: "C" 4 name: "C"
5 path: "Components/KeyHolders/keyHolderC" 5 path: "Components/KeyHolders/keyHolderC"
6 key: "c"
6} 7}
diff --git a/data/maps/daedalus/rooms/Castle.txtpb b/data/maps/daedalus/rooms/Castle.txtpb index 4797e80..7fd9a81 100644 --- a/data/maps/daedalus/rooms/Castle.txtpb +++ b/data/maps/daedalus/rooms/Castle.txtpb
@@ -1,5 +1,5 @@
1name: "Castle" 1name: "Castle"
2display_name: "Castle" 2panel_display_name: "Castle"
3panels { 3panels {
4 name: "REVERSE" 4 name: "REVERSE"
5 path: "Panels/Castle Interior/panel_flip" 5 path: "Panels/Castle Interior/panel_flip"
diff --git a/data/maps/daedalus/rooms/Coin Tower.txtpb b/data/maps/daedalus/rooms/Coin Tower.txtpb index 032ece3..177fc6e 100644 --- a/data/maps/daedalus/rooms/Coin Tower.txtpb +++ b/data/maps/daedalus/rooms/Coin Tower.txtpb
@@ -1,5 +1,5 @@
1name: "Coin Tower" 1name: "Coin Tower"
2display_name: "Northeast Area" 2panel_display_name: "Northeast Area"
3panels { 3panels {
4 name: "RAIN" 4 name: "RAIN"
5 path: "Panels/Entry/db_2" 5 path: "Panels/Entry/db_2"
diff --git a/data/maps/daedalus/rooms/Composite Room NE.txtpb b/data/maps/daedalus/rooms/Composite Room NE.txtpb index a4b13cd..c91a06f 100644 --- a/data/maps/daedalus/rooms/Composite Room NE.txtpb +++ b/data/maps/daedalus/rooms/Composite Room NE.txtpb
@@ -1,5 +1,5 @@
1name: "Composite Room NE" 1name: "Composite Room NE"
2display_name: "Composite Room" 2panel_display_name: "Composite Room"
3panels { 3panels {
4 name: "<-" 4 name: "<-"
5 path: "Panels/Combo Room NE/panel_1" 5 path: "Panels/Combo Room NE/panel_1"
diff --git a/data/maps/daedalus/rooms/Composite Room NW.txtpb b/data/maps/daedalus/rooms/Composite Room NW.txtpb index 94f987b..949fe31 100644 --- a/data/maps/daedalus/rooms/Composite Room NW.txtpb +++ b/data/maps/daedalus/rooms/Composite Room NW.txtpb
@@ -1,5 +1,5 @@
1name: "Composite Room NW" 1name: "Composite Room NW"
2display_name: "Composite Room" 2panel_display_name: "Composite Room"
3panels { 3panels {
4 name: "BEHOUSE" 4 name: "BEHOUSE"
5 path: "Panels/Combo Room NW/panel_1" 5 path: "Panels/Combo Room NW/panel_1"
diff --git a/data/maps/daedalus/rooms/Composite Room S.txtpb b/data/maps/daedalus/rooms/Composite Room S.txtpb index ec36ac3..0cb69bf 100644 --- a/data/maps/daedalus/rooms/Composite Room S.txtpb +++ b/data/maps/daedalus/rooms/Composite Room S.txtpb
@@ -1,5 +1,5 @@
1name: "Composite Room S" 1name: "Composite Room S"
2display_name: "Composite Room" 2panel_display_name: "Composite Room"
3panels { 3panels {
4 name: "CONCAVE" 4 name: "CONCAVE"
5 path: "Panels/Combo Room SW/panel_1" 5 path: "Panels/Combo Room SW/panel_1"
@@ -194,5 +194,8 @@ panels {
194} 194}
195ports { 195ports {
196 name: "ENTRY" 196 name: "ENTRY"
197 display_name: "Composite Room Worldport"
197 path: "Components/Warps/Worldports/worldport16" 198 path: "Components/Warps/Worldports/worldport16"
199 destination { x: -84 y: 0 z: 81 }
200 rotation: 270
198} 201}
diff --git a/data/maps/daedalus/rooms/Computer Room Seal.txtpb b/data/maps/daedalus/rooms/Computer Room Seal.txtpb index 19dcf3a..b271a5c 100644 --- a/data/maps/daedalus/rooms/Computer Room Seal.txtpb +++ b/data/maps/daedalus/rooms/Computer Room Seal.txtpb
@@ -1,5 +1,5 @@
1name: "Computer Room Seal" 1name: "Computer Room Seal"
2display_name: "Computer Room" 2panel_display_name: "Computer Room"
3panels { 3panels {
4 name: "SCROLL" 4 name: "SCROLL"
5 path: "Panels/Computer/computer_11" 5 path: "Panels/Computer/computer_11"
diff --git a/data/maps/daedalus/rooms/Computer Room.txtpb b/data/maps/daedalus/rooms/Computer Room.txtpb index 9cc6cbf..1d5a56d 100644 --- a/data/maps/daedalus/rooms/Computer Room.txtpb +++ b/data/maps/daedalus/rooms/Computer Room.txtpb
@@ -1,5 +1,5 @@
1name: "Computer Room" 1name: "Computer Room"
2display_name: "Computer Room" 2panel_display_name: "Computer Room"
3panels { 3panels {
4 name: "MONITOR (1)" 4 name: "MONITOR (1)"
5 path: "Panels/Computer/computer_1" 5 path: "Panels/Computer/computer_1"
diff --git a/data/maps/daedalus/rooms/Cyan Room.txtpb b/data/maps/daedalus/rooms/Cyan Room.txtpb index 8430dcd..60a3595 100644 --- a/data/maps/daedalus/rooms/Cyan Room.txtpb +++ b/data/maps/daedalus/rooms/Cyan Room.txtpb
@@ -1,5 +1,5 @@
1name: "Cyan Room" 1name: "Cyan Room"
2display_name: "West Area" 2panel_display_name: "Cyan Room"
3panels { 3panels {
4 name: "LIFE" 4 name: "LIFE"
5 path: "Panels/Brown Room/panel_1" 5 path: "Panels/Brown Room/panel_1"
diff --git a/data/maps/daedalus/rooms/D Keyholder.txtpb b/data/maps/daedalus/rooms/D Keyholder.txtpb index d2f226b..a5852be 100644 --- a/data/maps/daedalus/rooms/D Keyholder.txtpb +++ b/data/maps/daedalus/rooms/D Keyholder.txtpb
@@ -1,6 +1,7 @@
1name: "D Keyholder" 1name: "D Keyholder"
2display_name: "Plum Room" 2panel_display_name: "Plum Room"
3keyholders { 3keyholders {
4 name: "D" 4 name: "D"
5 path: "Components/KeyHolders/keyHolderD" 5 path: "Components/KeyHolders/keyHolderD"
6 key: "d"
6} 7}
diff --git a/data/maps/daedalus/rooms/D2 Room.txtpb b/data/maps/daedalus/rooms/D2 Room.txtpb index cfc645d..ec41086 100644 --- a/data/maps/daedalus/rooms/D2 Room.txtpb +++ b/data/maps/daedalus/rooms/D2 Room.txtpb
@@ -1,5 +1,5 @@
1name: "D2 Room" 1name: "D2 Room"
2display_name: "Intense Room" 2panel_display_name: "Intense Room"
3letters { 3letters {
4 key: "d" 4 key: "d"
5 level2: true 5 level2: true
diff --git a/data/maps/daedalus/rooms/Dark Light Exit.txtpb b/data/maps/daedalus/rooms/Dark Light Exit.txtpb index 9c4d674..9b6ae28 100644 --- a/data/maps/daedalus/rooms/Dark Light Exit.txtpb +++ b/data/maps/daedalus/rooms/Dark Light Exit.txtpb
@@ -1,5 +1,5 @@
1name: "Dark Light Exit" 1name: "Dark Light Exit"
2display_name: "Outside Pumpkin" 2panel_display_name: "Dark Light Room"
3panels { 3panels {
4 name: "GASKET" 4 name: "GASKET"
5 path: "Panels/Dark Light Room/dark_7" 5 path: "Panels/Dark Light Room/dark_7"
diff --git a/data/maps/daedalus/rooms/Dark Light Room.txtpb b/data/maps/daedalus/rooms/Dark Light Room.txtpb index 4716a36..45526fd 100644 --- a/data/maps/daedalus/rooms/Dark Light Room.txtpb +++ b/data/maps/daedalus/rooms/Dark Light Room.txtpb
@@ -1,5 +1,5 @@
1name: "Dark Light Room" 1name: "Dark Light Room"
2display_name: "Outside Pumpkin" 2panel_display_name: "Dark Light Room"
3panels { 3panels {
4 name: "COIN (1)" 4 name: "COIN (1)"
5 path: "Panels/Dark Light Room/dark_1" 5 path: "Panels/Dark Light Room/dark_1"
diff --git a/data/maps/daedalus/rooms/Ending.txtpb b/data/maps/daedalus/rooms/Ending.txtpb index b8d91c0..6b7843c 100644 --- a/data/maps/daedalus/rooms/Ending.txtpb +++ b/data/maps/daedalus/rooms/Ending.txtpb
@@ -1,5 +1,5 @@
1name: "Ending" 1name: "Ending"
2display_name: "Castle" 2panel_display_name: "Castle"
3endings { 3endings {
4 name: "ORANGE" 4 name: "ORANGE"
5 path: "Components/Triggers/orange_ending" 5 path: "Components/Triggers/orange_ending"
diff --git a/data/maps/daedalus/rooms/Entry Shortcut.txtpb b/data/maps/daedalus/rooms/Entry Shortcut.txtpb index a94d84c..3c3abb7 100644 --- a/data/maps/daedalus/rooms/Entry Shortcut.txtpb +++ b/data/maps/daedalus/rooms/Entry Shortcut.txtpb
@@ -1,13 +1,17 @@
1name: "Entry Shortcut" 1name: "Entry Shortcut"
2display_name: "Central" 2panel_display_name: "Central"
3panels { 3panels {
4 name: "WELCOME" 4 name: "WELCOME"
5 path: "Panels/Entry/entry_3" 5 path: "Panels/Entry/entry_3"
6 clue: "welcome" 6 clue: "welcome"
7 answer: "back" 7 answer: "back"
8 symbols: QUESTION 8 symbols: QUESTION
9 display_name: "WELCOME (Red/Blue)"
9} 10}
10ports { 11ports {
11 name: "ENTRY" 12 name: "ENTRY"
13 display_name: "Starting Room West Wall Middle Worldport"
12 path: "Components/Warps/Worldports/worldport4" 14 path: "Components/Warps/Worldports/worldport4"
15 destination { x: -21 y: 0 z: -4 }
16 rotation: 90
13} 17}
diff --git a/data/maps/daedalus/rooms/Eye Painting.txtpb b/data/maps/daedalus/rooms/Eye Painting.txtpb index d4c7cc6..4214811 100644 --- a/data/maps/daedalus/rooms/Eye Painting.txtpb +++ b/data/maps/daedalus/rooms/Eye Painting.txtpb
@@ -1,5 +1,5 @@
1name: "Eye Painting" 1name: "Eye Painting"
2display_name: "Temple of the Eyes" 2panel_display_name: "Temple of the Eyes"
3panels { 3panels {
4 name: "REVILED" 4 name: "REVILED"
5 path: "Panels/Entry/entry_5" 5 path: "Panels/Entry/entry_5"
diff --git a/data/maps/daedalus/rooms/Eye Temple 1F Side.txtpb b/data/maps/daedalus/rooms/Eye Temple 1F Side.txtpb index 0e914d5..3eb1a6b 100644 --- a/data/maps/daedalus/rooms/Eye Temple 1F Side.txtpb +++ b/data/maps/daedalus/rooms/Eye Temple 1F Side.txtpb
@@ -1,5 +1,5 @@
1name: "Eye Temple 1F Side" 1name: "Eye Temple 1F Side"
2display_name: "Temple of the Eyes" 2panel_display_name: "Temple of the Eyes"
3paintings { 3paintings {
4 name: "EYEREDSIDE1" 4 name: "EYEREDSIDE1"
5 path: "Components/Paintings/Temple of the Eyes/eyeRedSide1" 5 path: "Components/Paintings/Temple of the Eyes/eyeRedSide1"
diff --git a/data/maps/daedalus/rooms/Eye Temple 1F.txtpb b/data/maps/daedalus/rooms/Eye Temple 1F.txtpb index 9e8dc12..e15afc1 100644 --- a/data/maps/daedalus/rooms/Eye Temple 1F.txtpb +++ b/data/maps/daedalus/rooms/Eye Temple 1F.txtpb
@@ -1,5 +1,5 @@
1name: "Eye Temple 1F" 1name: "Eye Temple 1F"
2display_name: "Temple of the Eyes" 2panel_display_name: "Temple of the Eyes"
3paintings { 3paintings {
4 name: "EYEREDTOEXITMAIN2" 4 name: "EYEREDTOEXITMAIN2"
5 path: "Components/Paintings/Temple of the Eyes/eyeRedToExitMain2" 5 path: "Components/Paintings/Temple of the Eyes/eyeRedToExitMain2"
diff --git a/data/maps/daedalus/rooms/Eye Temple 2F Side.txtpb b/data/maps/daedalus/rooms/Eye Temple 2F Side.txtpb index b78a413..7a1eb0a 100644 --- a/data/maps/daedalus/rooms/Eye Temple 2F Side.txtpb +++ b/data/maps/daedalus/rooms/Eye Temple 2F Side.txtpb
@@ -1,5 +1,5 @@
1name: "Eye Temple 2F Side" 1name: "Eye Temple 2F Side"
2display_name: "Temple of the Eyes" 2panel_display_name: "Temple of the Eyes"
3paintings { 3paintings {
4 name: "EYEREDTOEXITMAIN4" 4 name: "EYEREDTOEXITMAIN4"
5 path: "Components/Paintings/Temple of the Eyes/eyeRedToExitMain4" 5 path: "Components/Paintings/Temple of the Eyes/eyeRedToExitMain4"
diff --git a/data/maps/daedalus/rooms/Eye Temple 2F.txtpb b/data/maps/daedalus/rooms/Eye Temple 2F.txtpb index b564e7e..d9e06d9 100644 --- a/data/maps/daedalus/rooms/Eye Temple 2F.txtpb +++ b/data/maps/daedalus/rooms/Eye Temple 2F.txtpb
@@ -1,5 +1,5 @@
1name: "Eye Temple 2F" 1name: "Eye Temple 2F"
2display_name: "Temple of the Eyes" 2panel_display_name: "Temple of the Eyes"
3paintings { 3paintings {
4 name: "EYEREDEXITTOP1" 4 name: "EYEREDEXITTOP1"
5 path: "Components/Paintings/Temple of the Eyes/eyeRedExitTop1" 5 path: "Components/Paintings/Temple of the Eyes/eyeRedExitTop1"
diff --git a/data/maps/daedalus/rooms/Eye Temple Pillar 1.txtpb b/data/maps/daedalus/rooms/Eye Temple Pillar 1.txtpb index 7fccfb2..8243704 100644 --- a/data/maps/daedalus/rooms/Eye Temple Pillar 1.txtpb +++ b/data/maps/daedalus/rooms/Eye Temple Pillar 1.txtpb
@@ -1,5 +1,5 @@
1name: "Eye Temple Pillar 1" 1name: "Eye Temple Pillar 1"
2display_name: "Temple of the Eyes" 2panel_display_name: "Temple of the Eyes"
3paintings { 3paintings {
4 name: "EYEREDEXITPILLAR1" 4 name: "EYEREDEXITPILLAR1"
5 path: "Components/Paintings/Temple of the Eyes/eyeRedExitPillar1" 5 path: "Components/Paintings/Temple of the Eyes/eyeRedExitPillar1"
diff --git a/data/maps/daedalus/rooms/Eye Temple Pillar 2.txtpb b/data/maps/daedalus/rooms/Eye Temple Pillar 2.txtpb index 88b468e..445649a 100644 --- a/data/maps/daedalus/rooms/Eye Temple Pillar 2.txtpb +++ b/data/maps/daedalus/rooms/Eye Temple Pillar 2.txtpb
@@ -1,5 +1,5 @@
1name: "Eye Temple Pillar 2" 1name: "Eye Temple Pillar 2"
2display_name: "Temple of the Eyes" 2panel_display_name: "Temple of the Eyes"
3paintings { 3paintings {
4 name: "EYEREDEXITPILLAR2" 4 name: "EYEREDEXITPILLAR2"
5 path: "Components/Paintings/Temple of the Eyes/eyeRedExitPillar2" 5 path: "Components/Paintings/Temple of the Eyes/eyeRedExitPillar2"
diff --git a/data/maps/daedalus/rooms/F Keyholder.txtpb b/data/maps/daedalus/rooms/F Keyholder.txtpb index 8063161..b424c6a 100644 --- a/data/maps/daedalus/rooms/F Keyholder.txtpb +++ b/data/maps/daedalus/rooms/F Keyholder.txtpb
@@ -1,6 +1,7 @@
1name: "F Keyholder" 1name: "F Keyholder"
2display_name: "West Area" 2panel_display_name: "West Area"
3keyholders { 3keyholders {
4 name: "F" 4 name: "F"
5 path: "Components/KeyHolders/keyHolderF" 5 path: "Components/KeyHolders/keyHolderF"
6 key: "f"
6} 7}
diff --git a/data/maps/daedalus/rooms/F2 Prize.txtpb b/data/maps/daedalus/rooms/F2 Prize.txtpb index 7a062f1..ac95340 100644 --- a/data/maps/daedalus/rooms/F2 Prize.txtpb +++ b/data/maps/daedalus/rooms/F2 Prize.txtpb
@@ -1,5 +1,5 @@
1name: "F2 Prize" 1name: "F2 Prize"
2display_name: "F2 Room" 2panel_display_name: "F2 Room"
3letters { 3letters {
4 key: "f" 4 key: "f"
5 level2: true 5 level2: true
diff --git a/data/maps/daedalus/rooms/F2 Room.txtpb b/data/maps/daedalus/rooms/F2 Room.txtpb index 49872ec..96b609e 100644 --- a/data/maps/daedalus/rooms/F2 Room.txtpb +++ b/data/maps/daedalus/rooms/F2 Room.txtpb
@@ -1,5 +1,5 @@
1name: "F2 Room" 1name: "F2 Room"
2display_name: "F2 Room" 2panel_display_name: "F2 Room"
3panels { 3panels {
4 name: "DULLS" 4 name: "DULLS"
5 path: "Panels/The Big F/o_1" 5 path: "Panels/The Big F/o_1"
diff --git a/data/maps/daedalus/rooms/Flip Painting Destination.txtpb b/data/maps/daedalus/rooms/Flip Painting Destination.txtpb index 99ceb25..b3ec055 100644 --- a/data/maps/daedalus/rooms/Flip Painting Destination.txtpb +++ b/data/maps/daedalus/rooms/Flip Painting Destination.txtpb
@@ -1,5 +1,5 @@
1name: "Flip Painting Destination" 1name: "Flip Painting Destination"
2display_name: "Central" 2panel_display_name: "Central"
3paintings { 3paintings {
4 name: "FLIP" 4 name: "FLIP"
5 path: "Components/Paintings/Group2/flip" 5 path: "Components/Paintings/Group2/flip"
diff --git a/data/maps/daedalus/rooms/Flip Painting Hidden Panel.txtpb b/data/maps/daedalus/rooms/Flip Painting Hidden Panel.txtpb index 71d345e..d597114 100644 --- a/data/maps/daedalus/rooms/Flip Painting Hidden Panel.txtpb +++ b/data/maps/daedalus/rooms/Flip Painting Hidden Panel.txtpb
@@ -1,5 +1,5 @@
1name: "Flip Painting Hidden Panel" 1name: "Flip Painting Hidden Panel"
2display_name: "Central" 2panel_display_name: "Central"
3panels { 3panels {
4 name: "HIDDEN" 4 name: "HIDDEN"
5 path: "Panels/Halls/halls_2" 5 path: "Panels/Halls/halls_2"
@@ -8,4 +8,5 @@ panels {
8 symbols: SUN 8 symbols: SUN
9 proxies { answer: "covert" path: "Panels/Halls/secret_proxy_1" } 9 proxies { answer: "covert" path: "Panels/Halls/secret_proxy_1" }
10 proxies { answer: "secret" path: "Panels/Halls/secret_proxy_2" } 10 proxies { answer: "secret" path: "Panels/Halls/secret_proxy_2" }
11 display_name: "HIDDEN (East)"
11} 12}
diff --git a/data/maps/daedalus/rooms/Flip Painting.txtpb b/data/maps/daedalus/rooms/Flip Painting.txtpb index cea1273..6d9bf06 100644 --- a/data/maps/daedalus/rooms/Flip Painting.txtpb +++ b/data/maps/daedalus/rooms/Flip Painting.txtpb
@@ -1,5 +1,5 @@
1name: "Flip Painting" 1name: "Flip Painting"
2display_name: "West Area" 2panel_display_name: "West Area"
3paintings { 3paintings {
4 name: "FLIP2" 4 name: "FLIP2"
5 path: "Components/Paintings/Group2/flip2" 5 path: "Components/Paintings/Group2/flip2"
diff --git a/data/maps/daedalus/rooms/Gallery Entrance.txtpb b/data/maps/daedalus/rooms/Gallery Entrance.txtpb index bed708f..3616bf7 100644 --- a/data/maps/daedalus/rooms/Gallery Entrance.txtpb +++ b/data/maps/daedalus/rooms/Gallery Entrance.txtpb
@@ -1,5 +1,5 @@
1name: "Gallery Entrance" 1name: "Gallery Entrance"
2display_name: "Central" 2panel_display_name: "Central"
3paintings { 3paintings {
4 name: "GALLERY" 4 name: "GALLERY"
5 path: "Components/Warps/eyeWorldport" 5 path: "Components/Warps/eyeWorldport"
diff --git a/data/maps/daedalus/rooms/Globe Room.txtpb b/data/maps/daedalus/rooms/Globe Room.txtpb index 49488f0..b090ac6 100644 --- a/data/maps/daedalus/rooms/Globe Room.txtpb +++ b/data/maps/daedalus/rooms/Globe Room.txtpb
@@ -1,5 +1,5 @@
1name: "Globe Room" 1name: "Globe Room"
2display_name: "Southwest Area" 2panel_display_name: "Southwest Area"
3panels { 3panels {
4 name: "NORTH" 4 name: "NORTH"
5 path: "Panels/Halls/directions_1" 5 path: "Panels/Halls/directions_1"
diff --git a/data/maps/daedalus/rooms/Godot Room.txtpb b/data/maps/daedalus/rooms/Godot Room.txtpb index a9c89ec..92cf009 100644 --- a/data/maps/daedalus/rooms/Godot Room.txtpb +++ b/data/maps/daedalus/rooms/Godot Room.txtpb
@@ -1,5 +1,5 @@
1name: "Godot Room" 1name: "Godot Room"
2display_name: "Central" 2panel_display_name: "Central"
3panels { 3panels {
4 name: "MOTORCYCLE" 4 name: "MOTORCYCLE"
5 path: "Panels/Southwest Room/sw_1" 5 path: "Panels/Southwest Room/sw_1"
diff --git a/data/maps/daedalus/rooms/Gray Color Backside.txtpb b/data/maps/daedalus/rooms/Gray Color Backside.txtpb index 8afb97e..7d90b7f 100644 --- a/data/maps/daedalus/rooms/Gray Color Backside.txtpb +++ b/data/maps/daedalus/rooms/Gray Color Backside.txtpb
@@ -1,5 +1,5 @@
1name: "Gray Color Backside" 1name: "Gray Color Backside"
2display_name: "Outside Pumpkin" 2panel_display_name: "Outside Pumpkin"
3panels { 3panels {
4 name: "ORANGE" 4 name: "ORANGE"
5 path: "Panels/Hexes/lightgreen_1" 5 path: "Panels/Hexes/lightgreen_1"
diff --git a/data/maps/daedalus/rooms/Gray Color Door.txtpb b/data/maps/daedalus/rooms/Gray Color Door.txtpb index f8298ff..db46389 100644 --- a/data/maps/daedalus/rooms/Gray Color Door.txtpb +++ b/data/maps/daedalus/rooms/Gray Color Door.txtpb
@@ -1,5 +1,5 @@
1name: "Gray Color Door" 1name: "Gray Color Door"
2display_name: "Outside Pumpkin" 2panel_display_name: "Outside Pumpkin"
3panels { 3panels {
4 name: "PATCH" 4 name: "PATCH"
5 path: "Panels/Halls/halls_3" 5 path: "Panels/Halls/halls_3"
diff --git a/data/maps/daedalus/rooms/Green Color Door.txtpb b/data/maps/daedalus/rooms/Green Color Door.txtpb index 275a3fa..fe52c09 100644 --- a/data/maps/daedalus/rooms/Green Color Door.txtpb +++ b/data/maps/daedalus/rooms/Green Color Door.txtpb
@@ -1,5 +1,5 @@
1name: "Green Color Door" 1name: "Green Color Door"
2display_name: "Outside Pumpkin" 2panel_display_name: "Outside Pumpkin"
3panels { 3panels {
4 name: "OLD (1)" 4 name: "OLD (1)"
5 path: "Panels/Halls/halls_20" 5 path: "Panels/Halls/halls_20"
diff --git a/data/maps/daedalus/rooms/Green Room.txtpb b/data/maps/daedalus/rooms/Green Room.txtpb index 3b1cde1..d93ee4a 100644 --- a/data/maps/daedalus/rooms/Green Room.txtpb +++ b/data/maps/daedalus/rooms/Green Room.txtpb
@@ -1,5 +1,5 @@
1name: "Green Room" 1name: "Green Room"
2display_name: "Green Room" 2panel_display_name: "Green Room"
3panels { 3panels {
4 name: "TIMESCALE" 4 name: "TIMESCALE"
5 path: "Panels/Green Room/panel_1" 5 path: "Panels/Green Room/panel_1"
diff --git a/data/maps/daedalus/rooms/Green Smiley.txtpb b/data/maps/daedalus/rooms/Green Smiley.txtpb index 7827f45..18f067f 100644 --- a/data/maps/daedalus/rooms/Green Smiley.txtpb +++ b/data/maps/daedalus/rooms/Green Smiley.txtpb
@@ -1,5 +1,5 @@
1name: "Green Smiley" 1name: "Green Smiley"
2display_name: "Southwest Area" 2panel_display_name: "Southwest Area"
3panels { 3panels {
4 name: "SMILE" 4 name: "SMILE"
5 path: "Panels/Smiley Rooms/green" 5 path: "Panels/Smiley Rooms/green"
diff --git a/data/maps/daedalus/rooms/Hedges Tower.txtpb b/data/maps/daedalus/rooms/Hedges Tower.txtpb index 97fe935..3b88cd7 100644 --- a/data/maps/daedalus/rooms/Hedges Tower.txtpb +++ b/data/maps/daedalus/rooms/Hedges Tower.txtpb
@@ -1,6 +1,8 @@
1name: "Hedges Tower" 1name: "Hedges Tower"
2display_name: "Hedges" 2panel_display_name: "Hedges"
3ports { 3ports {
4 name: "TENACIOUS" 4 name: "TENACIOUS"
5 display_name: "Hedge Maze Tower"
5 path: "Components/Warps/Worldports/worldport13" 6 path: "Components/Warps/Worldports/worldport13"
7 no_shuffle: true
6} 8}
diff --git a/data/maps/daedalus/rooms/Hedges.txtpb b/data/maps/daedalus/rooms/Hedges.txtpb index e467f7c..69c66a9 100644 --- a/data/maps/daedalus/rooms/Hedges.txtpb +++ b/data/maps/daedalus/rooms/Hedges.txtpb
@@ -1,5 +1,5 @@
1name: "Hedges" 1name: "Hedges"
2display_name: "Hedges" 2panel_display_name: "Hedges"
3panels { 3panels {
4 name: "SOLVE" 4 name: "SOLVE"
5 path: "Panels/Tower Maze/maze_1" 5 path: "Panels/Tower Maze/maze_1"
diff --git a/data/maps/daedalus/rooms/Hotel.txtpb b/data/maps/daedalus/rooms/Hotel.txtpb index 9834c3f..d2a05db 100644 --- a/data/maps/daedalus/rooms/Hotel.txtpb +++ b/data/maps/daedalus/rooms/Hotel.txtpb
@@ -1,5 +1,5 @@
1name: "Hotel" 1name: "Hotel"
2display_name: "Southwest Area" 2panel_display_name: "Southwest Area"
3# TODO: Something has to be changed in-game so that the puzzles don't disappear 3# TODO: Something has to be changed in-game so that the puzzles don't disappear
4# and thus cause them to become unsolvable. 4# and thus cause them to become unsolvable.
5panels { 5panels {
diff --git a/data/maps/daedalus/rooms/House Entrance.txtpb b/data/maps/daedalus/rooms/House Entrance.txtpb index 99bf58e..06dcb3f 100644 --- a/data/maps/daedalus/rooms/House Entrance.txtpb +++ b/data/maps/daedalus/rooms/House Entrance.txtpb
@@ -1,5 +1,5 @@
1name: "House Entrance" 1name: "House Entrance"
2display_name: "Maze" 2panel_display_name: "Maze"
3panels { 3panels {
4 name: "ADULT" 4 name: "ADULT"
5 path: "Panels/Entry/entry_6" 5 path: "Panels/Entry/entry_6"
diff --git a/data/maps/daedalus/rooms/House.txtpb b/data/maps/daedalus/rooms/House.txtpb index fcf938d..3cfd4d8 100644 --- a/data/maps/daedalus/rooms/House.txtpb +++ b/data/maps/daedalus/rooms/House.txtpb
@@ -1,5 +1,5 @@
1name: "House" 1name: "House"
2display_name: "House" 2panel_display_name: "House"
3panels { 3panels {
4 name: "GOAT" 4 name: "GOAT"
5 path: "Panels/Theos House/panel_1" 5 path: "Panels/Theos House/panel_1"
diff --git a/data/maps/daedalus/rooms/I2 Room.txtpb b/data/maps/daedalus/rooms/I2 Room.txtpb index ac9e7d5..2735a3b 100644 --- a/data/maps/daedalus/rooms/I2 Room.txtpb +++ b/data/maps/daedalus/rooms/I2 Room.txtpb
@@ -1,5 +1,5 @@
1name: "I2 Room" 1name: "I2 Room"
2display_name: "Temple of the Eyes" 2panel_display_name: "Temple of the Eyes"
3letters { 3letters {
4 key: "i" 4 key: "i"
5 level2: true 5 level2: true
diff --git a/data/maps/daedalus/rooms/Intense Room.txtpb b/data/maps/daedalus/rooms/Intense Room.txtpb index ce1cd08..30780f9 100644 --- a/data/maps/daedalus/rooms/Intense Room.txtpb +++ b/data/maps/daedalus/rooms/Intense Room.txtpb
@@ -1,5 +1,5 @@
1name: "Intense Room" 1name: "Intense Room"
2display_name: "Intense Room" 2panel_display_name: "Intense Room"
3panels { 3panels {
4 name: "BRILLIANT" 4 name: "BRILLIANT"
5 path: "Panels/Intense Room/intense_1" 5 path: "Panels/Intense Room/intense_1"
diff --git a/data/maps/daedalus/rooms/J2 Room.txtpb b/data/maps/daedalus/rooms/J2 Room.txtpb index 48ae0c2..20211d9 100644 --- a/data/maps/daedalus/rooms/J2 Room.txtpb +++ b/data/maps/daedalus/rooms/J2 Room.txtpb
@@ -1,5 +1,5 @@
1name: "J2 Room" 1name: "J2 Room"
2display_name: "Southwest Area" 2panel_display_name: "Southwest Area"
3letters { 3letters {
4 key: "j" 4 key: "j"
5 level2: true 5 level2: true
diff --git a/data/maps/daedalus/rooms/J2 Vestibule.txtpb b/data/maps/daedalus/rooms/J2 Vestibule.txtpb index a7f786d..57f5a4f 100644 --- a/data/maps/daedalus/rooms/J2 Vestibule.txtpb +++ b/data/maps/daedalus/rooms/J2 Vestibule.txtpb
@@ -1,9 +1,10 @@
1name: "J2 Vestibule" 1name: "J2 Vestibule"
2display_name: "Southwest Area" 2panel_display_name: "Southwest Area"
3panels { 3panels {
4 name: "COLORFUL" 4 name: "COLORFUL"
5 path: "Panels/Entry/hotel_entry2" 5 path: "Panels/Entry/hotel_entry2"
6 clue: "colorful" 6 clue: "colorful"
7 answer: "vivid" 7 answer: "vivid"
8 symbols: SUN 8 symbols: SUN
9 display_name: "COLORFUL (2)"
9} 10}
diff --git a/data/maps/daedalus/rooms/Magic Room.txtpb b/data/maps/daedalus/rooms/Magic Room.txtpb index c16dca6..66c63ca 100644 --- a/data/maps/daedalus/rooms/Magic Room.txtpb +++ b/data/maps/daedalus/rooms/Magic Room.txtpb
@@ -1,5 +1,5 @@
1name: "Magic Room" 1name: "Magic Room"
2display_name: "Maze" 2panel_display_name: "Maze"
3panels { 3panels {
4 name: "1" 4 name: "1"
5 path: "Panels/Magic Maze/maze_1" 5 path: "Panels/Magic Maze/maze_1"
diff --git a/data/maps/daedalus/rooms/Maze Paintings Area.txtpb b/data/maps/daedalus/rooms/Maze Paintings Area.txtpb index 42a45c5..3b070f7 100644 --- a/data/maps/daedalus/rooms/Maze Paintings Area.txtpb +++ b/data/maps/daedalus/rooms/Maze Paintings Area.txtpb
@@ -1,5 +1,5 @@
1name: "Maze Paintings Area" 1name: "Maze Paintings Area"
2display_name: "Maze" 2panel_display_name: "Maze"
3panels { 3panels {
4 name: "Paintings" 4 name: "Paintings"
5 path: "Panels/Halls/halls_28" 5 path: "Panels/Halls/halls_28"
diff --git a/data/maps/daedalus/rooms/Maze.txtpb b/data/maps/daedalus/rooms/Maze.txtpb index 0329465..a2bb5a3 100644 --- a/data/maps/daedalus/rooms/Maze.txtpb +++ b/data/maps/daedalus/rooms/Maze.txtpb
@@ -1,2 +1,2 @@
1name: "Maze" 1name: "Maze"
2display_name: "Maze" 2panel_display_name: "Maze"
diff --git a/data/maps/daedalus/rooms/Moat.txtpb b/data/maps/daedalus/rooms/Moat.txtpb index f834609..7bdb040 100644 --- a/data/maps/daedalus/rooms/Moat.txtpb +++ b/data/maps/daedalus/rooms/Moat.txtpb
@@ -1,10 +1,13 @@
1name: "Moat" 1name: "Moat"
2display_name: "East Area" 2panel_display_name: "East Area"
3paintings { 3paintings {
4 name: "CASTLE" 4 name: "CASTLE"
5 path: "Components/Paintings/Group1/castle" 5 path: "Components/Paintings/Group1/castle"
6} 6}
7ports { 7ports {
8 name: "HIVE" 8 name: "HIVE"
9 display_name: "Moat Worldport"
9 path: "Components/Warps/Worldports/worldport9" 10 path: "Components/Warps/Worldports/worldport9"
11 destination { x: 64 y: 1 z: 24.5 }
12 rotation: 0
10} 13}
diff --git a/data/maps/daedalus/rooms/North Castle Area.txtpb b/data/maps/daedalus/rooms/North Castle Area.txtpb index 6d177c9..a549245 100644 --- a/data/maps/daedalus/rooms/North Castle Area.txtpb +++ b/data/maps/daedalus/rooms/North Castle Area.txtpb
@@ -1,5 +1,5 @@
1name: "North Castle Area" 1name: "North Castle Area"
2display_name: "North Area" 2panel_display_name: "North Area"
3panels { 3panels {
4 name: "A" 4 name: "A"
5 path: "Panels/Castle Entrance/castle_north_helper" 5 path: "Panels/Castle Entrance/castle_north_helper"
diff --git a/data/maps/daedalus/rooms/Number Paintings Area.txtpb b/data/maps/daedalus/rooms/Number Paintings Area.txtpb index fb01075..c89bfcf 100644 --- a/data/maps/daedalus/rooms/Number Paintings Area.txtpb +++ b/data/maps/daedalus/rooms/Number Paintings Area.txtpb
@@ -1,5 +1,5 @@
1name: "Number Paintings Area" 1name: "Number Paintings Area"
2display_name: "Northwest Area" 2panel_display_name: "Northwest Area"
3panels { 3panels {
4 name: "GOING" 4 name: "GOING"
5 path: "Panels/Entry/g_hedge_1" 5 path: "Panels/Entry/g_hedge_1"
@@ -17,6 +17,7 @@ panels {
17keyholders { 17keyholders {
18 name: "G" 18 name: "G"
19 path: "Components/KeyHolders/keyHolderG" 19 path: "Components/KeyHolders/keyHolderG"
20 key: "g"
20} 21}
21paintings { 22paintings {
22 name: "WON" 23 name: "WON"
diff --git a/data/maps/daedalus/rooms/Nursery.txtpb b/data/maps/daedalus/rooms/Nursery.txtpb index cd1b5e3..c73072d 100644 --- a/data/maps/daedalus/rooms/Nursery.txtpb +++ b/data/maps/daedalus/rooms/Nursery.txtpb
@@ -1,5 +1,5 @@
1name: "Nursery" 1name: "Nursery"
2display_name: "Central" 2panel_display_name: "Central"
3panels { 3panels {
4 name: "Paintings" 4 name: "Paintings"
5 path: "Panels/Entry/entry_2" 5 path: "Panels/Entry/entry_2"
@@ -12,6 +12,7 @@ panels {
12 path: "Panels/Halls/halls_17" 12 path: "Panels/Halls/halls_17"
13 clue: "" 13 clue: ""
14 answer: "welcome" 14 answer: "welcome"
15 display_name: "Nursery Behind"
15} 16}
16paintings { 17paintings {
17 name: "ARE" 18 name: "ARE"
diff --git a/data/maps/daedalus/rooms/O2 Prize.txtpb b/data/maps/daedalus/rooms/O2 Prize.txtpb index 0a81954..a810182 100644 --- a/data/maps/daedalus/rooms/O2 Prize.txtpb +++ b/data/maps/daedalus/rooms/O2 Prize.txtpb
@@ -1,5 +1,5 @@
1name: "O2 Prize" 1name: "O2 Prize"
2display_name: "O2 Room" 2panel_display_name: "O2 Room"
3letters { 3letters {
4 key: "o" 4 key: "o"
5 level2: true 5 level2: true
diff --git a/data/maps/daedalus/rooms/O2 Room.txtpb b/data/maps/daedalus/rooms/O2 Room.txtpb index 7ea3ce2..b1a839f 100644 --- a/data/maps/daedalus/rooms/O2 Room.txtpb +++ b/data/maps/daedalus/rooms/O2 Room.txtpb
@@ -1,5 +1,5 @@
1name: "O2 Room" 1name: "O2 Room"
2display_name: "O2 Room" 2panel_display_name: "O2 Room"
3panels { 3panels {
4 name: "LISTEN" 4 name: "LISTEN"
5 path: "Panels/The Big O/o_1" 5 path: "Panels/The Big O/o_1"
diff --git a/data/maps/daedalus/rooms/Orange Room Hallway.txtpb b/data/maps/daedalus/rooms/Orange Room Hallway.txtpb new file mode 100644 index 0000000..915e698 --- /dev/null +++ b/data/maps/daedalus/rooms/Orange Room Hallway.txtpb
@@ -0,0 +1,4 @@
1name: "Orange Room Hallway"
2panel_display_name: "Orange Room"
3# This has the same door at both sides, and mainly just connects Z2 Room and
4# Orange Room. It's separate because you can also get here from the Roof.
diff --git a/data/maps/daedalus/rooms/Orange Room.txtpb b/data/maps/daedalus/rooms/Orange Room.txtpb index ba1bedd..08a0ff2 100644 --- a/data/maps/daedalus/rooms/Orange Room.txtpb +++ b/data/maps/daedalus/rooms/Orange Room.txtpb
@@ -1,5 +1,5 @@
1name: "Orange Room" 1name: "Orange Room"
2display_name: "East Area" 2panel_display_name: "Orange Room"
3panels { 3panels {
4 name: "FRANCE" 4 name: "FRANCE"
5 path: "Panels/Orange Room/panel_1" 5 path: "Panels/Orange Room/panel_1"
diff --git a/data/maps/daedalus/rooms/Outside Book Room.txtpb b/data/maps/daedalus/rooms/Outside Book Room.txtpb index a8e647f..1592217 100644 --- a/data/maps/daedalus/rooms/Outside Book Room.txtpb +++ b/data/maps/daedalus/rooms/Outside Book Room.txtpb
@@ -1,5 +1,5 @@
1name: "Outside Book Room" 1name: "Outside Book Room"
2display_name: "Southwest Area" 2panel_display_name: "Southwest Area"
3# This is behind a teal wall. 3# This is behind a teal wall.
4panels { 4panels {
5 name: "TEAL" 5 name: "TEAL"
diff --git a/data/maps/daedalus/rooms/Outside Eye Temple.txtpb b/data/maps/daedalus/rooms/Outside Eye Temple.txtpb index c7d35fd..85a9c19 100644 --- a/data/maps/daedalus/rooms/Outside Eye Temple.txtpb +++ b/data/maps/daedalus/rooms/Outside Eye Temple.txtpb
@@ -1,5 +1,5 @@
1name: "Outside Eye Temple" 1name: "Outside Eye Temple"
2display_name: "Temple of the Eyes" 2panel_display_name: "Temple of the Eyes"
3panels { 3panels {
4 name: "Entrance" 4 name: "Entrance"
5 path: "Panels/Halls/eye_temple_entry_1" 5 path: "Panels/Halls/eye_temple_entry_1"
diff --git a/data/maps/daedalus/rooms/Outside Hedges.txtpb b/data/maps/daedalus/rooms/Outside Hedges.txtpb index b157beb..fc765d9 100644 --- a/data/maps/daedalus/rooms/Outside Hedges.txtpb +++ b/data/maps/daedalus/rooms/Outside Hedges.txtpb
@@ -1,5 +1,5 @@
1name: "Outside Hedges" 1name: "Outside Hedges"
2display_name: "Hedges" 2panel_display_name: "Hedges"
3panels { 3panels {
4 name: "GOURD (1)" 4 name: "GOURD (1)"
5 path: "Panels/Halls/halls_11" 5 path: "Panels/Halls/halls_11"
@@ -76,5 +76,8 @@ paintings {
76} 76}
77ports { 77ports {
78 name: "REVITALIZED" 78 name: "REVITALIZED"
79 display_name: "Near Hedges Plum Hallway"
79 path: "Components/Warps/Worldports/worldport7" 80 path: "Components/Warps/Worldports/worldport7"
81 destination { x: 45 y: 0 z: 94 }
82 rotation: 270
80} 83}
diff --git a/data/maps/daedalus/rooms/Outside Hotel.txtpb b/data/maps/daedalus/rooms/Outside Hotel.txtpb index 62b5a41..7766c7d 100644 --- a/data/maps/daedalus/rooms/Outside Hotel.txtpb +++ b/data/maps/daedalus/rooms/Outside Hotel.txtpb
@@ -1,9 +1,10 @@
1name: "Outside Hotel" 1name: "Outside Hotel"
2display_name: "Southwest Area" 2panel_display_name: "Southwest Area"
3panels { 3panels {
4 name: "COLORFUL" 4 name: "COLORFUL"
5 path: "Panels/Entry/hotel_entry" 5 path: "Panels/Entry/hotel_entry"
6 clue: "colorful" 6 clue: "colorful"
7 answer: "bright" 7 answer: "bright"
8 symbols: SUN 8 symbols: SUN
9 display_name: "COLORFUL (1)"
9} 10}
diff --git a/data/maps/daedalus/rooms/Outside House.txtpb b/data/maps/daedalus/rooms/Outside House.txtpb index 8a5e911..fed9dda 100644 --- a/data/maps/daedalus/rooms/Outside House.txtpb +++ b/data/maps/daedalus/rooms/Outside House.txtpb
@@ -1,5 +1,5 @@
1name: "Outside House" 1name: "Outside House"
2display_name: "Maze" 2panel_display_name: "Maze"
3panels { 3panels {
4 name: "WHISPER" 4 name: "WHISPER"
5 path: "Panels/Beehalls/beehalls_1" 5 path: "Panels/Beehalls/beehalls_1"
@@ -75,6 +75,7 @@ panels {
75keyholders { 75keyholders {
76 name: "H" 76 name: "H"
77 path: "Components/KeyHolders/keyHolderH" 77 path: "Components/KeyHolders/keyHolderH"
78 key: "h"
78} 79}
79paintings { 80paintings {
80 name: "CASTLE2" 81 name: "CASTLE2"
diff --git a/data/maps/daedalus/rooms/Outside Magic Room.txtpb b/data/maps/daedalus/rooms/Outside Magic Room.txtpb index ef45563..2aa7848 100644 --- a/data/maps/daedalus/rooms/Outside Magic Room.txtpb +++ b/data/maps/daedalus/rooms/Outside Magic Room.txtpb
@@ -1,5 +1,5 @@
1name: "Outside Magic Room" 1name: "Outside Magic Room"
2display_name: "Maze" 2panel_display_name: "Maze"
3panels { 3panels {
4 name: "WIZARD" 4 name: "WIZARD"
5 path: "Panels/Magic Maze/maze_entry_1" 5 path: "Panels/Magic Maze/maze_entry_1"
diff --git a/data/maps/daedalus/rooms/Outside Orange Room.txtpb b/data/maps/daedalus/rooms/Outside Orange Room.txtpb index a50db78..55efe34 100644 --- a/data/maps/daedalus/rooms/Outside Orange Room.txtpb +++ b/data/maps/daedalus/rooms/Outside Orange Room.txtpb
@@ -1,5 +1,5 @@
1name: "Outside Orange Room" 1name: "Outside Orange Room"
2display_name: "East Area" 2panel_display_name: "East Area"
3panels { 3panels {
4 name: "SMILE" 4 name: "SMILE"
5 path: "Panels/Smiley Rooms/orange" 5 path: "Panels/Smiley Rooms/orange"
diff --git a/data/maps/daedalus/rooms/Outside Pyramid.txtpb b/data/maps/daedalus/rooms/Outside Pyramid.txtpb index fd7ef21..247d3a8 100644 --- a/data/maps/daedalus/rooms/Outside Pyramid.txtpb +++ b/data/maps/daedalus/rooms/Outside Pyramid.txtpb
@@ -1,5 +1,5 @@
1name: "Outside Pyramid" 1name: "Outside Pyramid"
2display_name: "Pyramid" 2panel_display_name: "Pyramid"
3panels { 3panels {
4 name: "PEER" 4 name: "PEER"
5 path: "Panels/Pyramid/pyramid_entry" 5 path: "Panels/Pyramid/pyramid_entry"
diff --git a/data/maps/daedalus/rooms/Outside Red Room.txtpb b/data/maps/daedalus/rooms/Outside Red Room.txtpb index e5be363..307633b 100644 --- a/data/maps/daedalus/rooms/Outside Red Room.txtpb +++ b/data/maps/daedalus/rooms/Outside Red Room.txtpb
@@ -1,5 +1,5 @@
1name: "Outside Red Room" 1name: "Outside Red Room"
2display_name: "Red Room" 2panel_display_name: "Red Room"
3panels { 3panels {
4 name: "ROCK" 4 name: "ROCK"
5 path: "Panels/Red Room/red_entry" 5 path: "Panels/Red Room/red_entry"
diff --git a/data/maps/daedalus/rooms/Outside Salt Room.txtpb b/data/maps/daedalus/rooms/Outside Salt Room.txtpb index 3d374f8..f5c4833 100644 --- a/data/maps/daedalus/rooms/Outside Salt Room.txtpb +++ b/data/maps/daedalus/rooms/Outside Salt Room.txtpb
@@ -1,9 +1,10 @@
1name: "Outside Salt Room" 1name: "Outside Salt Room"
2display_name: "Southwest Area" 2panel_display_name: "Southwest Area"
3panels { 3panels {
4 name: "Colors" 4 name: "Colors"
5 path: "Panels/Color Reading/cr_1" 5 path: "Panels/Color Reading/cr_1"
6 clue: "" 6 clue: ""
7 answer: "rob" 7 answer: "rob"
8 symbols: LINGO 8 symbols: LINGO
9 display_name: "Colors (White)"
9} 10}
diff --git a/data/maps/daedalus/rooms/Outside Snake Room.txtpb b/data/maps/daedalus/rooms/Outside Snake Room.txtpb index b65ee77..31f3281 100644 --- a/data/maps/daedalus/rooms/Outside Snake Room.txtpb +++ b/data/maps/daedalus/rooms/Outside Snake Room.txtpb
@@ -1,5 +1,5 @@
1name: "Outside Snake Room" 1name: "Outside Snake Room"
2display_name: "West Area" 2panel_display_name: "West Area"
3panels { 3panels {
4 name: "TONGUE" 4 name: "TONGUE"
5 path: "Panels/Pairs Room/pairs_7" 5 path: "Panels/Pairs Room/pairs_7"
diff --git a/data/maps/daedalus/rooms/Pains Room.txtpb b/data/maps/daedalus/rooms/Pains Room.txtpb index cc0c7bb..d5c9c4a 100644 --- a/data/maps/daedalus/rooms/Pains Room.txtpb +++ b/data/maps/daedalus/rooms/Pains Room.txtpb
@@ -1,5 +1,5 @@
1name: "Pains Room" 1name: "Pains Room"
2display_name: "Central" 2panel_display_name: "Central"
3panels { 3panels {
4 name: "MOO" 4 name: "MOO"
5 path: "Panels/Gold/gold_1" 5 path: "Panels/Gold/gold_1"
diff --git a/data/maps/daedalus/rooms/Pairs Room.txtpb b/data/maps/daedalus/rooms/Pairs Room.txtpb index ca5e885..ba484bf 100644 --- a/data/maps/daedalus/rooms/Pairs Room.txtpb +++ b/data/maps/daedalus/rooms/Pairs Room.txtpb
@@ -1,2 +1,2 @@
1name: "Pairs Room" 1name: "Pairs Room"
2display_name: "West Area" 2panel_display_name: "West Area"
diff --git a/data/maps/daedalus/rooms/Pepper Room.txtpb b/data/maps/daedalus/rooms/Pepper Room.txtpb index 074869f..104efa7 100644 --- a/data/maps/daedalus/rooms/Pepper Room.txtpb +++ b/data/maps/daedalus/rooms/Pepper Room.txtpb
@@ -1,9 +1,10 @@
1name: "Pepper Room" 1name: "Pepper Room"
2display_name: "Southwest Area" 2panel_display_name: "Southwest Area"
3panels { 3panels {
4 name: "SEASONING" 4 name: "SEASONING"
5 path: "Panels/Color Reading/cr_4" 5 path: "Panels/Color Reading/cr_4"
6 clue: "seasoning" 6 clue: "seasoning"
7 answer: "pepper" 7 answer: "pepper"
8 symbols: EXAMPLE 8 symbols: EXAMPLE
9 display_name: "SEASONING (Black)"
9} 10}
diff --git a/data/maps/daedalus/rooms/Plum Room.txtpb b/data/maps/daedalus/rooms/Plum Room.txtpb index 90243a4..36185b9 100644 --- a/data/maps/daedalus/rooms/Plum Room.txtpb +++ b/data/maps/daedalus/rooms/Plum Room.txtpb
@@ -1,5 +1,5 @@
1name: "Plum Room" 1name: "Plum Room"
2display_name: "Plum Room" 2panel_display_name: "Plum Room"
3panels { 3panels {
4 name: "GOD" 4 name: "GOD"
5 path: "Panels/Plum Room/plum_1" 5 path: "Panels/Plum Room/plum_1"
diff --git a/data/maps/daedalus/rooms/Post Orange Smiley Three Way.txtpb b/data/maps/daedalus/rooms/Post Orange Smiley Three Way.txtpb index 868ff86..63463f0 100644 --- a/data/maps/daedalus/rooms/Post Orange Smiley Three Way.txtpb +++ b/data/maps/daedalus/rooms/Post Orange Smiley Three Way.txtpb
@@ -1,2 +1,2 @@
1name: "Post Orange Smiley Three Way" 1name: "Post Orange Smiley Three Way"
2display_name: "West Area" 2panel_display_name: "West Area"
diff --git a/data/maps/daedalus/rooms/Pumpkin Entrance.txtpb b/data/maps/daedalus/rooms/Pumpkin Entrance.txtpb index c7fc3d1..a746746 100644 --- a/data/maps/daedalus/rooms/Pumpkin Entrance.txtpb +++ b/data/maps/daedalus/rooms/Pumpkin Entrance.txtpb
@@ -1,5 +1,5 @@
1name: "Pumpkin Entrance" 1name: "Pumpkin Entrance"
2display_name: "East Area" 2panel_display_name: "East Area"
3panels { 3panels {
4 name: "JACK" 4 name: "JACK"
5 path: "Panels/Pumpkin Room/pumpkin_2" 5 path: "Panels/Pumpkin Room/pumpkin_2"
diff --git a/data/maps/daedalus/rooms/Pumpkin Room.txtpb b/data/maps/daedalus/rooms/Pumpkin Room.txtpb index 345b372..e40693b 100644 --- a/data/maps/daedalus/rooms/Pumpkin Room.txtpb +++ b/data/maps/daedalus/rooms/Pumpkin Room.txtpb
@@ -1,5 +1,5 @@
1name: "Pumpkin Room" 1name: "Pumpkin Room"
2display_name: "East Area" 2panel_display_name: "East Area"
3panels { 3panels {
4 name: "BONE" 4 name: "BONE"
5 path: "Panels/Pumpkin Room/pumpkin_3" 5 path: "Panels/Pumpkin Room/pumpkin_3"
diff --git a/data/maps/daedalus/rooms/Purple Hallway From Great.txtpb b/data/maps/daedalus/rooms/Purple Hallway From Great.txtpb index fef68e9..73f8391 100644 --- a/data/maps/daedalus/rooms/Purple Hallway From Great.txtpb +++ b/data/maps/daedalus/rooms/Purple Hallway From Great.txtpb
@@ -1,6 +1,9 @@
1name: "Purple Hallway From Great" 1name: "Purple Hallway From Great"
2display_name: "South Area" 2panel_display_name: "South Area"
3ports { 3ports {
4 name: "GREAT" 4 name: "GREAT"
5 display_name: "Near Sweet Purple Hallway"
5 path: "Components/Warps/Worldports/worldport17" 6 path: "Components/Warps/Worldports/worldport17"
7 destination { x: -24 y: 0 z: 61 }
8 rotation: 270
6} 9}
diff --git a/data/maps/daedalus/rooms/Purple NW Vestibule.txtpb b/data/maps/daedalus/rooms/Purple NW Vestibule.txtpb index 6aedce9..0244e6c 100644 --- a/data/maps/daedalus/rooms/Purple NW Vestibule.txtpb +++ b/data/maps/daedalus/rooms/Purple NW Vestibule.txtpb
@@ -1,5 +1,5 @@
1name: "Purple NW Vestibule" 1name: "Purple NW Vestibule"
2display_name: "Central" 2panel_display_name: "Central"
3panels { 3panels {
4 name: "MESSAGES" 4 name: "MESSAGES"
5 path: "Panels/Purple Exterior/purple_8" 5 path: "Panels/Purple Exterior/purple_8"
diff --git a/data/maps/daedalus/rooms/Purple Room East.txtpb b/data/maps/daedalus/rooms/Purple Room East.txtpb index a866868..6fa31bd 100644 --- a/data/maps/daedalus/rooms/Purple Room East.txtpb +++ b/data/maps/daedalus/rooms/Purple Room East.txtpb
@@ -1,2 +1,2 @@
1name: "Purple Room East" 1name: "Purple Room East"
2display_name: "Central" 2panel_display_name: "Central"
diff --git a/data/maps/daedalus/rooms/Purple Room South.txtpb b/data/maps/daedalus/rooms/Purple Room South.txtpb index b6a25e6..68a6264 100644 --- a/data/maps/daedalus/rooms/Purple Room South.txtpb +++ b/data/maps/daedalus/rooms/Purple Room South.txtpb
@@ -1,5 +1,5 @@
1name: "Purple Room South" 1name: "Purple Room South"
2display_name: "Central" 2panel_display_name: "Central"
3panels { 3panels {
4 name: "LITTLE" 4 name: "LITTLE"
5 path: "Panels/Halls/hof_1" 5 path: "Panels/Halls/hof_1"
diff --git a/data/maps/daedalus/rooms/Purple Room West.txtpb b/data/maps/daedalus/rooms/Purple Room West.txtpb index 8c20399..9971cd2 100644 --- a/data/maps/daedalus/rooms/Purple Room West.txtpb +++ b/data/maps/daedalus/rooms/Purple Room West.txtpb
@@ -1,2 +1,2 @@
1name: "Purple Room West" 1name: "Purple Room West"
2display_name: "Central" 2panel_display_name: "Central"
diff --git a/data/maps/daedalus/rooms/Purple Room.txtpb b/data/maps/daedalus/rooms/Purple Room.txtpb index 612f8d8..f34d26c 100644 --- a/data/maps/daedalus/rooms/Purple Room.txtpb +++ b/data/maps/daedalus/rooms/Purple Room.txtpb
@@ -1,5 +1,5 @@
1name: "Purple Room" 1name: "Purple Room"
2display_name: "Central" 2panel_display_name: "Purple Room"
3panels { 3panels {
4 name: "HOIST" 4 name: "HOIST"
5 path: "Panels/Purple Room/purple_1" 5 path: "Panels/Purple Room/purple_1"
diff --git a/data/maps/daedalus/rooms/Purple SE Vestibule.txtpb b/data/maps/daedalus/rooms/Purple SE Vestibule.txtpb index 5f34151..be86861 100644 --- a/data/maps/daedalus/rooms/Purple SE Vestibule.txtpb +++ b/data/maps/daedalus/rooms/Purple SE Vestibule.txtpb
@@ -1,5 +1,5 @@
1name: "Purple SE Vestibule" 1name: "Purple SE Vestibule"
2display_name: "Central" 2panel_display_name: "Central"
3panels { 3panels {
4 name: "RUN" 4 name: "RUN"
5 path: "Panels/Purple Exterior/purple_1" 5 path: "Panels/Purple Exterior/purple_1"
diff --git a/data/maps/daedalus/rooms/Purple SW Vestibule.txtpb b/data/maps/daedalus/rooms/Purple SW Vestibule.txtpb index 05acc75..fbc5fff 100644 --- a/data/maps/daedalus/rooms/Purple SW Vestibule.txtpb +++ b/data/maps/daedalus/rooms/Purple SW Vestibule.txtpb
@@ -1,5 +1,5 @@
1name: "Purple SW Vestibule" 1name: "Purple SW Vestibule"
2display_name: "Central" 2panel_display_name: "Central"
3panels { 3panels {
4 name: "LETTERS" 4 name: "LETTERS"
5 path: "Panels/Purple Exterior/purple_11" 5 path: "Panels/Purple Exterior/purple_11"
diff --git a/data/maps/daedalus/rooms/Purple Smiley.txtpb b/data/maps/daedalus/rooms/Purple Smiley.txtpb index 515336f..5f6c989 100644 --- a/data/maps/daedalus/rooms/Purple Smiley.txtpb +++ b/data/maps/daedalus/rooms/Purple Smiley.txtpb
@@ -1,5 +1,5 @@
1name: "Purple Smiley" 1name: "Purple Smiley"
2display_name: "Northeast Area" 2panel_display_name: "Northeast Area"
3panels { 3panels {
4 name: "SMILE" 4 name: "SMILE"
5 path: "Panels/Smiley Rooms/purple" 5 path: "Panels/Smiley Rooms/purple"
diff --git a/data/maps/daedalus/rooms/Pyramid 3.txtpb b/data/maps/daedalus/rooms/Pyramid 3.txtpb index f760ab0..be862d1 100644 --- a/data/maps/daedalus/rooms/Pyramid 3.txtpb +++ b/data/maps/daedalus/rooms/Pyramid 3.txtpb
@@ -1,5 +1,5 @@
1name: "Pyramid 3" 1name: "Pyramid 3"
2display_name: "Pyramid" 2panel_display_name: "Pyramid"
3panels { 3panels {
4 name: "VEHICLE" 4 name: "VEHICLE"
5 path: "Panels/Pyramid/pyramid_3" 5 path: "Panels/Pyramid/pyramid_3"
diff --git a/data/maps/daedalus/rooms/Pyramid 4.txtpb b/data/maps/daedalus/rooms/Pyramid 4.txtpb index 3247ffa..e67e1c6 100644 --- a/data/maps/daedalus/rooms/Pyramid 4.txtpb +++ b/data/maps/daedalus/rooms/Pyramid 4.txtpb
@@ -1,5 +1,5 @@
1name: "Pyramid 4" 1name: "Pyramid 4"
2display_name: "Pyramid" 2panel_display_name: "Pyramid"
3panels { 3panels {
4 name: "CAT" 4 name: "CAT"
5 path: "Panels/Pyramid/pyramid_4" 5 path: "Panels/Pyramid/pyramid_4"
diff --git a/data/maps/daedalus/rooms/Pyramid 5.txtpb b/data/maps/daedalus/rooms/Pyramid 5.txtpb index fc05e50..42e8a52 100644 --- a/data/maps/daedalus/rooms/Pyramid 5.txtpb +++ b/data/maps/daedalus/rooms/Pyramid 5.txtpb
@@ -1,5 +1,5 @@
1name: "Pyramid 5" 1name: "Pyramid 5"
2display_name: "Pyramid" 2panel_display_name: "Pyramid"
3panels { 3panels {
4 name: "ROYAL" 4 name: "ROYAL"
5 path: "Panels/Pyramid/pyramid_5" 5 path: "Panels/Pyramid/pyramid_5"
diff --git a/data/maps/daedalus/rooms/Pyramid 6.txtpb b/data/maps/daedalus/rooms/Pyramid 6.txtpb index 78efb0c..3a7346b 100644 --- a/data/maps/daedalus/rooms/Pyramid 6.txtpb +++ b/data/maps/daedalus/rooms/Pyramid 6.txtpb
@@ -1,5 +1,5 @@
1name: "Pyramid 6" 1name: "Pyramid 6"
2display_name: "Pyramid" 2panel_display_name: "Pyramid"
3panels { 3panels {
4 name: "TEA" 4 name: "TEA"
5 path: "Panels/Pyramid/pyramid_6" 5 path: "Panels/Pyramid/pyramid_6"
diff --git a/data/maps/daedalus/rooms/Pyramid 7.txtpb b/data/maps/daedalus/rooms/Pyramid 7.txtpb index bf4ebc6..2db71ea 100644 --- a/data/maps/daedalus/rooms/Pyramid 7.txtpb +++ b/data/maps/daedalus/rooms/Pyramid 7.txtpb
@@ -1,5 +1,5 @@
1name: "Pyramid 7" 1name: "Pyramid 7"
2display_name: "Pyramid" 2panel_display_name: "Pyramid"
3panels { 3panels {
4 name: "ARTIST" 4 name: "ARTIST"
5 path: "Panels/Pyramid/pyramid_7" 5 path: "Panels/Pyramid/pyramid_7"
diff --git a/data/maps/daedalus/rooms/Pyramid 8.txtpb b/data/maps/daedalus/rooms/Pyramid 8.txtpb index f65fc69..6f61340 100644 --- a/data/maps/daedalus/rooms/Pyramid 8.txtpb +++ b/data/maps/daedalus/rooms/Pyramid 8.txtpb
@@ -1,9 +1,10 @@
1name: "Pyramid 8" 1name: "Pyramid 8"
2display_name: "Pyramid" 2panel_display_name: "Pyramid"
3panels { 3panels {
4 name: "INSTRUMENT" 4 name: "INSTRUMENT"
5 path: "Panels/Pyramid/pyramid_8" 5 path: "Panels/Pyramid/pyramid_8"
6 clue: "instrument" 6 clue: "instrument"
7 answer: "drum" 7 answer: "drum"
8 symbols: EXAMPLE 8 symbols: EXAMPLE
9 display_name: "INSTRUMENT (1F)"
9} 10}
diff --git a/data/maps/daedalus/rooms/Pyramid Entry.txtpb b/data/maps/daedalus/rooms/Pyramid Entry.txtpb index 3bb531f..2c9e841 100644 --- a/data/maps/daedalus/rooms/Pyramid Entry.txtpb +++ b/data/maps/daedalus/rooms/Pyramid Entry.txtpb
@@ -1,5 +1,5 @@
1name: "Pyramid Entry" 1name: "Pyramid Entry"
2display_name: "Pyramid" 2panel_display_name: "Pyramid"
3panels { 3panels {
4 name: "TREE" 4 name: "TREE"
5 path: "Panels/Pyramid/pyramid_1" 5 path: "Panels/Pyramid/pyramid_1"
diff --git a/data/maps/daedalus/rooms/Pyramid Second Floor.txtpb b/data/maps/daedalus/rooms/Pyramid Second Floor.txtpb index e7578e8..86f5f2a 100644 --- a/data/maps/daedalus/rooms/Pyramid Second Floor.txtpb +++ b/data/maps/daedalus/rooms/Pyramid Second Floor.txtpb
@@ -1,5 +1,5 @@
1name: "Pyramid Second Floor" 1name: "Pyramid Second Floor"
2display_name: "Pyramid" 2panel_display_name: "Pyramid"
3panels { 3panels {
4 name: "TOOL" 4 name: "TOOL"
5 path: "Panels/Pyramid/pyramid_10" 5 path: "Panels/Pyramid/pyramid_10"
@@ -36,6 +36,7 @@ panels {
36 answer: "organ" 36 answer: "organ"
37 symbols: EXAMPLE 37 symbols: EXAMPLE
38 required_door { name: "Pyramid 13 Blocker" } 38 required_door { name: "Pyramid 13 Blocker" }
39 display_name: "INSTRUMENT (2F)"
39} 40}
40panels { 41panels {
41 name: "BEVERAGE" 42 name: "BEVERAGE"
diff --git a/data/maps/daedalus/rooms/Pyramid Top.txtpb b/data/maps/daedalus/rooms/Pyramid Top.txtpb index b3938fd..c017cd6 100644 --- a/data/maps/daedalus/rooms/Pyramid Top.txtpb +++ b/data/maps/daedalus/rooms/Pyramid Top.txtpb
@@ -1,5 +1,5 @@
1name: "Pyramid Top" 1name: "Pyramid Top"
2display_name: "Pyramid" 2panel_display_name: "Pyramid"
3letters { 3letters {
4 key: "r" 4 key: "r"
5 level2: true 5 level2: true
diff --git a/data/maps/daedalus/rooms/Quiet Entrance.txtpb b/data/maps/daedalus/rooms/Quiet Entrance.txtpb index 21e0f68..cd0d0ed 100644 --- a/data/maps/daedalus/rooms/Quiet Entrance.txtpb +++ b/data/maps/daedalus/rooms/Quiet Entrance.txtpb
@@ -1,5 +1,5 @@
1name: "Quiet Entrance" 1name: "Quiet Entrance"
2display_name: "Central" 2panel_display_name: "Central"
3panels { 3panels {
4 name: "HIDDEN" 4 name: "HIDDEN"
5 path: "Panels/Halls/halls_7" 5 path: "Panels/Halls/halls_7"
@@ -8,6 +8,7 @@ panels {
8 symbols: SUN 8 symbols: SUN
9 proxies { answer: "covert" path: "Panels/Halls/secret_proxy_3" } 9 proxies { answer: "covert" path: "Panels/Halls/secret_proxy_3" }
10 proxies { answer: "secret" path: "Panels/Halls/secret_proxy_4" } 10 proxies { answer: "secret" path: "Panels/Halls/secret_proxy_4" }
11 display_name: "HIDDEN (West)"
11} 12}
12paintings { 13paintings {
13 name: "PLANET2" 14 name: "PLANET2"
@@ -15,5 +16,8 @@ paintings {
15} 16}
16ports { 17ports {
17 name: "QUIET" 18 name: "QUIET"
19 display_name: "Near Planet Painting Worldport"
18 path: "Components/Warps/Worldports/worldport5" 20 path: "Components/Warps/Worldports/worldport5"
21 destination { x: -32 y: 0 z: -40 }
22 rotation: 90
19} 23}
diff --git a/data/maps/daedalus/rooms/Rain Side.txtpb b/data/maps/daedalus/rooms/Rain Side.txtpb index 63e95c8..2a62525 100644 --- a/data/maps/daedalus/rooms/Rain Side.txtpb +++ b/data/maps/daedalus/rooms/Rain Side.txtpb
@@ -1,13 +1,17 @@
1name: "Rain Side" 1name: "Rain Side"
2display_name: "Rainbow" 2panel_display_name: "Rainbow"
3panels { 3panels {
4 name: "?" 4 name: "?"
5 path: "Panels/Smiley Rooms/rain" 5 path: "Panels/Smiley Rooms/rain"
6 clue: "" 6 clue: ""
7 answer: "rain" 7 answer: "rain"
8 symbols: QUESTION 8 symbols: QUESTION
9 display_name: "? (1)"
9} 10}
10ports { 11ports {
11 name: "BEARER" 12 name: "BEARER"
13 display_name: "Rain Panel Worldport"
12 path: "Components/Warps/Worldports/worldport11" 14 path: "Components/Warps/Worldports/worldport11"
15 destination { x: 93.5 y: 0 z: 27 }
16 rotation: 90
13} 17}
diff --git a/data/maps/daedalus/rooms/Rainbow Blue.txtpb b/data/maps/daedalus/rooms/Rainbow Blue.txtpb index b566cbb..516a9b6 100644 --- a/data/maps/daedalus/rooms/Rainbow Blue.txtpb +++ b/data/maps/daedalus/rooms/Rainbow Blue.txtpb
@@ -1,9 +1,10 @@
1name: "Rainbow Blue" 1name: "Rainbow Blue"
2display_name: "Rainbow" 2panel_display_name: "Rainbow"
3panels { 3panels {
4 name: "THEME" 4 name: "THEME"
5 path: "Panels/Smiley Rooms/blue2" 5 path: "Panels/Smiley Rooms/blue2"
6 clue: "theme" 6 clue: "theme"
7 answer: "seasonings" 7 answer: "seasonings"
8 symbols: QUESTION 8 symbols: QUESTION
9 display_name: "THEME (Blue)"
9} 10}
diff --git a/data/maps/daedalus/rooms/Rainbow Color Backside.txtpb b/data/maps/daedalus/rooms/Rainbow Color Backside.txtpb index 3fb3a5c..d9b49c5 100644 --- a/data/maps/daedalus/rooms/Rainbow Color Backside.txtpb +++ b/data/maps/daedalus/rooms/Rainbow Color Backside.txtpb
@@ -1,5 +1,5 @@
1name: "Rainbow Color Backside" 1name: "Rainbow Color Backside"
2display_name: "Central" 2panel_display_name: "Central"
3panels { 3panels {
4 name: "BACKSIDE" 4 name: "BACKSIDE"
5 path: "Panels/Halls/halls_1" 5 path: "Panels/Halls/halls_1"
@@ -11,4 +11,5 @@ panels {
11 path: "Panels/Halls/halls_4" 11 path: "Panels/Halls/halls_4"
12 clue: "" 12 clue: ""
13 answer: "side" 13 answer: "side"
14 display_name: "Backside Behind"
14} 15}
diff --git a/data/maps/daedalus/rooms/Rainbow Color Doors.txtpb b/data/maps/daedalus/rooms/Rainbow Color Doors.txtpb index 3204d28..df44979 100644 --- a/data/maps/daedalus/rooms/Rainbow Color Doors.txtpb +++ b/data/maps/daedalus/rooms/Rainbow Color Doors.txtpb
@@ -1,5 +1,5 @@
1name: "Rainbow Color Doors" 1name: "Rainbow Color Doors"
2display_name: "East Area" 2panel_display_name: "East Area"
3panels { 3panels {
4 name: "CROW" 4 name: "CROW"
5 path: "Panels/Blue Room/panel_entry" 5 path: "Panels/Blue Room/panel_entry"
diff --git a/data/maps/daedalus/rooms/Rainbow Cyan.txtpb b/data/maps/daedalus/rooms/Rainbow Cyan.txtpb index 9ce8b3f..f55b0d2 100644 --- a/data/maps/daedalus/rooms/Rainbow Cyan.txtpb +++ b/data/maps/daedalus/rooms/Rainbow Cyan.txtpb
@@ -1,9 +1,10 @@
1name: "Rainbow Cyan" 1name: "Rainbow Cyan"
2display_name: "Rainbow" 2panel_display_name: "Rainbow"
3panels { 3panels {
4 name: "THEME" 4 name: "THEME"
5 path: "Panels/Smiley Rooms/cyan" 5 path: "Panels/Smiley Rooms/cyan"
6 clue: "theme" 6 clue: "theme"
7 answer: "apocalypse" 7 answer: "apocalypse"
8 symbols: QUESTION 8 symbols: QUESTION
9 display_name: "THEME (Cyan)"
9} 10}
diff --git a/data/maps/daedalus/rooms/Rainbow End.txtpb b/data/maps/daedalus/rooms/Rainbow End.txtpb index 27f3c4f..ec623c7 100644 --- a/data/maps/daedalus/rooms/Rainbow End.txtpb +++ b/data/maps/daedalus/rooms/Rainbow End.txtpb
@@ -1,5 +1,5 @@
1name: "Rainbow End" 1name: "Rainbow End"
2display_name: "Rainbow" 2panel_display_name: "Rainbow"
3panels { 3panels {
4 name: "POT" 4 name: "POT"
5 path: "Components/Warps/gold" 5 path: "Components/Warps/gold"
diff --git a/data/maps/daedalus/rooms/Rainbow Green.txtpb b/data/maps/daedalus/rooms/Rainbow Green.txtpb index 84de8a5..85bb8be 100644 --- a/data/maps/daedalus/rooms/Rainbow Green.txtpb +++ b/data/maps/daedalus/rooms/Rainbow Green.txtpb
@@ -1,9 +1,10 @@
1name: "Rainbow Green" 1name: "Rainbow Green"
2display_name: "Rainbow" 2panel_display_name: "Rainbow"
3panels { 3panels {
4 name: "THEME" 4 name: "THEME"
5 path: "Panels/Smiley Rooms/green2" 5 path: "Panels/Smiley Rooms/green2"
6 clue: "theme" 6 clue: "theme"
7 answer: "tea" 7 answer: "tea"
8 symbols: QUESTION 8 symbols: QUESTION
9 display_name: "THEME (Green)"
9} 10}
diff --git a/data/maps/daedalus/rooms/Rainbow Orange.txtpb b/data/maps/daedalus/rooms/Rainbow Orange.txtpb index 290c061..785eda8 100644 --- a/data/maps/daedalus/rooms/Rainbow Orange.txtpb +++ b/data/maps/daedalus/rooms/Rainbow Orange.txtpb
@@ -1,9 +1,10 @@
1name: "Rainbow Orange" 1name: "Rainbow Orange"
2display_name: "Rainbow" 2panel_display_name: "Rainbow"
3panels { 3panels {
4 name: "THEME" 4 name: "THEME"
5 path: "Panels/Smiley Rooms/orange2" 5 path: "Panels/Smiley Rooms/orange2"
6 clue: "theme" 6 clue: "theme"
7 answer: "fish" 7 answer: "fish"
8 symbols: QUESTION 8 symbols: QUESTION
9 display_name: "THEME (Orange)"
9} 10}
diff --git a/data/maps/daedalus/rooms/Rainbow Purple.txtpb b/data/maps/daedalus/rooms/Rainbow Purple.txtpb index 698af59..1f585dd 100644 --- a/data/maps/daedalus/rooms/Rainbow Purple.txtpb +++ b/data/maps/daedalus/rooms/Rainbow Purple.txtpb
@@ -1,9 +1,10 @@
1name: "Rainbow Purple" 1name: "Rainbow Purple"
2display_name: "Rainbow" 2panel_display_name: "Rainbow"
3panels { 3panels {
4 name: "THEME" 4 name: "THEME"
5 path: "Panels/Smiley Rooms/purple2" 5 path: "Panels/Smiley Rooms/purple2"
6 clue: "theme" 6 clue: "theme"
7 answer: "fruit" 7 answer: "fruit"
8 symbols: QUESTION 8 symbols: QUESTION
9 display_name: "THEME (Purple)"
9} 10}
diff --git a/data/maps/daedalus/rooms/Rainbow Red.txtpb b/data/maps/daedalus/rooms/Rainbow Red.txtpb index 92dbda0..7ef4db3 100644 --- a/data/maps/daedalus/rooms/Rainbow Red.txtpb +++ b/data/maps/daedalus/rooms/Rainbow Red.txtpb
@@ -1,9 +1,10 @@
1name: "Rainbow Red" 1name: "Rainbow Red"
2display_name: "Rainbow" 2panel_display_name: "Rainbow"
3panels { 3panels {
4 name: "THEME" 4 name: "THEME"
5 path: "Panels/Smiley Rooms/red2" 5 path: "Panels/Smiley Rooms/red2"
6 clue: "theme" 6 clue: "theme"
7 answer: "names" 7 answer: "names"
8 symbols: QUESTION 8 symbols: QUESTION
9 display_name: "THEME (Red)"
9} 10}
diff --git a/data/maps/daedalus/rooms/Rainbow Start.txtpb b/data/maps/daedalus/rooms/Rainbow Start.txtpb index e0d5dc1..c46b762 100644 --- a/data/maps/daedalus/rooms/Rainbow Start.txtpb +++ b/data/maps/daedalus/rooms/Rainbow Start.txtpb
@@ -1,5 +1,5 @@
1name: "Rainbow Start" 1name: "Rainbow Start"
2display_name: "Rainbow" 2panel_display_name: "Rainbow"
3panels { 3panels {
4 name: "PAINTING" 4 name: "PAINTING"
5 path: "Panels/Smiley Rooms/rainbow" 5 path: "Panels/Smiley Rooms/rainbow"
diff --git a/data/maps/daedalus/rooms/Rainbow Yellow.txtpb b/data/maps/daedalus/rooms/Rainbow Yellow.txtpb index bbbdce4..bd2cfc5 100644 --- a/data/maps/daedalus/rooms/Rainbow Yellow.txtpb +++ b/data/maps/daedalus/rooms/Rainbow Yellow.txtpb
@@ -1,9 +1,10 @@
1name: "Rainbow Yellow" 1name: "Rainbow Yellow"
2display_name: "Rainbow" 2panel_display_name: "Rainbow"
3panels { 3panels {
4 name: "THEME" 4 name: "THEME"
5 path: "Panels/Smiley Rooms/yellow2" 5 path: "Panels/Smiley Rooms/yellow2"
6 clue: "theme" 6 clue: "theme"
7 answer: "music" 7 answer: "music"
8 symbols: QUESTION 8 symbols: QUESTION
9 display_name: "THEME (Yellow)"
9} 10}
diff --git a/data/maps/daedalus/rooms/Red Color Door.txtpb b/data/maps/daedalus/rooms/Red Color Door.txtpb index a2f40a5..344193e 100644 --- a/data/maps/daedalus/rooms/Red Color Door.txtpb +++ b/data/maps/daedalus/rooms/Red Color Door.txtpb
@@ -1,7 +1,7 @@
1name: "Red Color Door" 1name: "Red Color Door"
2display_name: "Southwest Area" 2panel_display_name: "Southwest Area"
3panels { 3panels {
4 name: "Left" 4 name: "Near Obscured Puzzles"
5 path: "Panels/Halls/wb_1" 5 path: "Panels/Halls/wb_1"
6 clue: "" 6 clue: ""
7 answer: "sidewalk" 7 answer: "sidewalk"
@@ -67,4 +67,5 @@ panels {
67 clue: "" 67 clue: ""
68 answer: "bank" 68 answer: "bank"
69 symbols: LINGO 69 symbols: LINGO
70 display_name: "Colors (Black)"
70} 71}
diff --git a/data/maps/daedalus/rooms/Red Room.txtpb b/data/maps/daedalus/rooms/Red Room.txtpb index 99f0a1e..d73f591 100644 --- a/data/maps/daedalus/rooms/Red Room.txtpb +++ b/data/maps/daedalus/rooms/Red Room.txtpb
@@ -1,5 +1,5 @@
1name: "Red Room" 1name: "Red Room"
2display_name: "Red Room" 2panel_display_name: "Red Room"
3panels { 3panels {
4 name: "BLINDING" 4 name: "BLINDING"
5 path: "Panels/Red Room/red_1" 5 path: "Panels/Red Room/red_1"
diff --git a/data/maps/daedalus/rooms/Red Smiley.txtpb b/data/maps/daedalus/rooms/Red Smiley.txtpb index 6f7c41c..28f2a03 100644 --- a/data/maps/daedalus/rooms/Red Smiley.txtpb +++ b/data/maps/daedalus/rooms/Red Smiley.txtpb
@@ -1,5 +1,5 @@
1name: "Red Smiley" 1name: "Red Smiley"
2display_name: "Northwest Area" 2panel_display_name: "Northwest Area"
3panels { 3panels {
4 name: "SMILE" 4 name: "SMILE"
5 path: "Panels/Smiley Rooms/red" 5 path: "Panels/Smiley Rooms/red"
diff --git a/data/maps/daedalus/rooms/Roof.txtpb b/data/maps/daedalus/rooms/Roof.txtpb index c027a72..3aba765 100644 --- a/data/maps/daedalus/rooms/Roof.txtpb +++ b/data/maps/daedalus/rooms/Roof.txtpb
@@ -1,4 +1,5 @@
1name: "Roof" 1name: "Roof"
2panel_display_name: "Roof"
2panels { 3panels {
3 name: "?" 4 name: "?"
4 path: "Panels/Castle Entrance/moat" 5 path: "Panels/Castle Entrance/moat"
diff --git a/data/maps/daedalus/rooms/Salt Room.txtpb b/data/maps/daedalus/rooms/Salt Room.txtpb index 0c7fe73..39c9c9f 100644 --- a/data/maps/daedalus/rooms/Salt Room.txtpb +++ b/data/maps/daedalus/rooms/Salt Room.txtpb
@@ -1,9 +1,10 @@
1name: "Salt Room" 1name: "Salt Room"
2display_name: "Southwest Area" 2panel_display_name: "Southwest Area"
3panels { 3panels {
4 name: "SEASONING" 4 name: "SEASONING"
5 path: "Panels/Color Reading/cr_3" 5 path: "Panels/Color Reading/cr_3"
6 clue: "seasoning" 6 clue: "seasoning"
7 answer: "salt" 7 answer: "salt"
8 symbols: EXAMPLE 8 symbols: EXAMPLE
9 display_name: "SEASONING (White)"
9} 10}
diff --git a/data/maps/daedalus/rooms/Seasoning Room.txtpb b/data/maps/daedalus/rooms/Seasoning Room.txtpb index d3123b9..6159134 100644 --- a/data/maps/daedalus/rooms/Seasoning Room.txtpb +++ b/data/maps/daedalus/rooms/Seasoning Room.txtpb
@@ -1,5 +1,5 @@
1name: "Seasoning Room" 1name: "Seasoning Room"
2display_name: "Southwest Area" 2panel_display_name: "Southwest Area"
3panels { 3panels {
4 name: "PARITY" 4 name: "PARITY"
5 path: "Panels/Color Reading/cr_5" 5 path: "Panels/Color Reading/cr_5"
diff --git a/data/maps/daedalus/rooms/Snake Room.txtpb b/data/maps/daedalus/rooms/Snake Room.txtpb index f3cea2e..fb947ab 100644 --- a/data/maps/daedalus/rooms/Snake Room.txtpb +++ b/data/maps/daedalus/rooms/Snake Room.txtpb
@@ -1,5 +1,5 @@
1name: "Snake Room" 1name: "Snake Room"
2display_name: "West Area" 2panel_display_name: "West Area"
3panels { 3panels {
4 name: "HISS" 4 name: "HISS"
5 path: "Panels/Snake Room/snake_1" 5 path: "Panels/Snake Room/snake_1"
diff --git a/data/maps/daedalus/rooms/South Castle Area.txtpb b/data/maps/daedalus/rooms/South Castle Area.txtpb index 9f620b7..4bb73f3 100644 --- a/data/maps/daedalus/rooms/South Castle Area.txtpb +++ b/data/maps/daedalus/rooms/South Castle Area.txtpb
@@ -1,5 +1,5 @@
1name: "South Castle Area" 1name: "South Castle Area"
2display_name: "Outside Pumpkin" 2panel_display_name: "Outside Pumpkin"
3# There is a teal wall in the middle of this room. 3# There is a teal wall in the middle of this room.
4panels { 4panels {
5 name: "AN" 5 name: "AN"
@@ -107,5 +107,5 @@ paintings {
107 path: "Components/Paintings/Group2/triangle" 107 path: "Components/Paintings/Group2/triangle"
108 move: true 108 move: true
109 enter_only: true 109 enter_only: true
110 # TODO: required_door 110 required_door { name: "Tenacious Color Painting" }
111} 111}
diff --git a/data/maps/daedalus/rooms/Starting Room.txtpb b/data/maps/daedalus/rooms/Starting Room.txtpb index 615104b..1b07eb4 100644 --- a/data/maps/daedalus/rooms/Starting Room.txtpb +++ b/data/maps/daedalus/rooms/Starting Room.txtpb
@@ -1,5 +1,5 @@
1name: "Starting Room" 1name: "Starting Room"
2display_name: "Central" 2panel_display_name: "Central"
3panels { 3panels {
4 name: "ENTRANCE" 4 name: "ENTRANCE"
5 path: "Panels/Entry/entry_1" 5 path: "Panels/Entry/entry_1"
@@ -9,5 +9,8 @@ panels {
9} 9}
10ports { 10ports {
11 name: "GREAT" 11 name: "GREAT"
12 display_name: "Starting Room South Wall Middle Worldport"
12 path: "Components/Warps/Worldports/worldport" 13 path: "Components/Warps/Worldports/worldport"
14 destination { x: 0 y: 0 z: 11 }
15 rotation: 0
13} 16}
diff --git a/data/maps/daedalus/rooms/Sweet Foyer.txtpb b/data/maps/daedalus/rooms/Sweet Foyer.txtpb index d337e7e..d1167eb 100644 --- a/data/maps/daedalus/rooms/Sweet Foyer.txtpb +++ b/data/maps/daedalus/rooms/Sweet Foyer.txtpb
@@ -1,5 +1,5 @@
1name: "Sweet Foyer" 1name: "Sweet Foyer"
2display_name: "South Area" 2panel_display_name: "South Area"
3panels { 3panels {
4 name: "QUALITY" 4 name: "QUALITY"
5 path: "Panels/Sweet Foyer/panel_1" 5 path: "Panels/Sweet Foyer/panel_1"
@@ -51,9 +51,15 @@ paintings {
51} 51}
52ports { 52ports {
53 name: "SWEET1" 53 name: "SWEET1"
54 display_name: "Sweet East Entrance"
54 path: "Components/Warps/Worldports/worldport14" 55 path: "Components/Warps/Worldports/worldport14"
56 destination { x: -27 y: 0 z: 76.5 }
57 rotation: 270
55} 58}
56ports { 59ports {
57 name: "SWEET2" 60 name: "SWEET2"
61 display_name: "Sweet West Entrance"
58 path: "Components/Warps/Worldports/worldport15" 62 path: "Components/Warps/Worldports/worldport15"
63 destination { x: -36 y: 0 z: 76.5 }
64 rotation: 90
59} 65}
diff --git a/data/maps/daedalus/rooms/Tree Entrance.txtpb b/data/maps/daedalus/rooms/Tree Entrance.txtpb index df2db7e..1453790 100644 --- a/data/maps/daedalus/rooms/Tree Entrance.txtpb +++ b/data/maps/daedalus/rooms/Tree Entrance.txtpb
@@ -1,5 +1,5 @@
1name: "Tree Entrance" 1name: "Tree Entrance"
2display_name: "Outside Pumpkin" 2panel_display_name: "Outside Pumpkin"
3panels { 3panels {
4 name: "RAT" 4 name: "RAT"
5 path: "Panels/Hexes/lime_1" 5 path: "Panels/Hexes/lime_1"
@@ -48,5 +48,8 @@ panels {
48} 48}
49ports { 49ports {
50 name: "TREE" 50 name: "TREE"
51 display_name: "Near Pumpkin Brown Hallway"
51 path: "Components/Warps/Worldports/worldport12" 52 path: "Components/Warps/Worldports/worldport12"
53 destination { x: 41 y: 0 z: 50.5 }
54 rotation: 0
52} 55}
diff --git a/data/maps/daedalus/rooms/U2 Prize.txtpb b/data/maps/daedalus/rooms/U2 Prize.txtpb index 947af67..571b0c8 100644 --- a/data/maps/daedalus/rooms/U2 Prize.txtpb +++ b/data/maps/daedalus/rooms/U2 Prize.txtpb
@@ -1,5 +1,5 @@
1name: "U2 Prize" 1name: "U2 Prize"
2display_name: "U2 Room" 2panel_display_name: "U2 Room"
3letters { 3letters {
4 key: "u" 4 key: "u"
5 level2: true 5 level2: true
diff --git a/data/maps/daedalus/rooms/U2 Room.txtpb b/data/maps/daedalus/rooms/U2 Room.txtpb index c9907eb..1e5879a 100644 --- a/data/maps/daedalus/rooms/U2 Room.txtpb +++ b/data/maps/daedalus/rooms/U2 Room.txtpb
@@ -1,5 +1,5 @@
1name: "U2 Room" 1name: "U2 Room"
2display_name: "U2 Room" 2panel_display_name: "U2 Room"
3panels { 3panels {
4 name: "DREAMSCAPE" 4 name: "DREAMSCAPE"
5 path: "Panels/The Big U/o_1" 5 path: "Panels/The Big U/o_1"
diff --git a/data/maps/daedalus/rooms/Unkempt Entrance.txtpb b/data/maps/daedalus/rooms/Unkempt Entrance.txtpb index 192ba9c..0a39ee0 100644 --- a/data/maps/daedalus/rooms/Unkempt Entrance.txtpb +++ b/data/maps/daedalus/rooms/Unkempt Entrance.txtpb
@@ -1,6 +1,9 @@
1name: "Unkempt Entrance" 1name: "Unkempt Entrance"
2display_name: "O2 Room" 2panel_display_name: "O2 Room"
3ports { 3ports {
4 name: "UNKEMPT" 4 name: "UNKEMPT"
5 display_name: "O2 Room Worldport"
5 path: "Components/Warps/Worldports/worldport6" 6 path: "Components/Warps/Worldports/worldport6"
7 destination { x: -61 y: 0 z: 95 }
8 rotation: 270
6} 9}
diff --git a/data/maps/daedalus/rooms/Welcome Back Area.txtpb b/data/maps/daedalus/rooms/Welcome Back Area.txtpb index 3f320a3..701baca 100644 --- a/data/maps/daedalus/rooms/Welcome Back Area.txtpb +++ b/data/maps/daedalus/rooms/Welcome Back Area.txtpb
@@ -1,5 +1,5 @@
1name: "Welcome Back Area" 1name: "Welcome Back Area"
2display_name: "Central" 2panel_display_name: "Central"
3panels { 3panels {
4 name: "FAREWELL LITTLE LAMB" 4 name: "FAREWELL LITTLE LAMB"
5 path: "Panels/Entry/wb_2" 5 path: "Panels/Entry/wb_2"
diff --git a/data/maps/daedalus/rooms/Welcome Back Exit.txtpb b/data/maps/daedalus/rooms/Welcome Back Exit.txtpb index a4a23e2..ac221c7 100644 --- a/data/maps/daedalus/rooms/Welcome Back Exit.txtpb +++ b/data/maps/daedalus/rooms/Welcome Back Exit.txtpb
@@ -1,5 +1,5 @@
1name: "Welcome Back Exit" 1name: "Welcome Back Exit"
2display_name: "Central" 2panel_display_name: "Central"
3panels { 3panels {
4 name: "WELCOME" 4 name: "WELCOME"
5 path: "Panels/Entry/wb_1" 5 path: "Panels/Entry/wb_1"
@@ -7,4 +7,5 @@ panels {
7 answer: "welcome" 7 answer: "welcome"
8 symbols: QUESTION 8 symbols: QUESTION
9 proxies { answer: "back" path: "Panels/Entry/wb_proxy" } 9 proxies { answer: "back" path: "Panels/Entry/wb_proxy" }
10 display_name: "WELCOME (White)"
10} 11}
diff --git a/data/maps/daedalus/rooms/West Castle Area.txtpb b/data/maps/daedalus/rooms/West Castle Area.txtpb index 88722f5..010e5d6 100644 --- a/data/maps/daedalus/rooms/West Castle Area.txtpb +++ b/data/maps/daedalus/rooms/West Castle Area.txtpb
@@ -1,5 +1,5 @@
1name: "West Castle Area" 1name: "West Castle Area"
2display_name: "West Area" 2panel_display_name: "West Area"
3panels { 3panels {
4 name: "SONG (1)" 4 name: "SONG (1)"
5 path: "Panels/Castle Entrance/castle_west_helper" 5 path: "Panels/Castle Entrance/castle_west_helper"
diff --git a/data/maps/daedalus/rooms/West Spire.txtpb b/data/maps/daedalus/rooms/West Spire.txtpb index fdf8f9a..7cc579f 100644 --- a/data/maps/daedalus/rooms/West Spire.txtpb +++ b/data/maps/daedalus/rooms/West Spire.txtpb
@@ -1,5 +1,5 @@
1name: "West Spire" 1name: "West Spire"
2display_name: "West Area" 2panel_display_name: "West Area"
3panels { 3panels {
4 name: "MISSING" 4 name: "MISSING"
5 path: "Panels/Entry/wb_5" 5 path: "Panels/Entry/wb_5"
diff --git a/data/maps/daedalus/rooms/White Hallway From Entry.txtpb b/data/maps/daedalus/rooms/White Hallway From Entry.txtpb index 2af7584..d3659d3 100644 --- a/data/maps/daedalus/rooms/White Hallway From Entry.txtpb +++ b/data/maps/daedalus/rooms/White Hallway From Entry.txtpb
@@ -1,12 +1,9 @@
1name: "White Hallway From Entry" 1name: "White Hallway From Entry"
2display_name: "Southwest Area" 2panel_display_name: "Southwest Area"
3# Not exactly sure what to do with this yet. In unshuffled connections, the door
4# here should be paired with the door on the other end (which is vanilla) even
5# if control center color doors are shuffled. But when connections are shuffled
6# maybe this should be shuffled separately? I might also want to find a way to
7# register when there's a door immediately outside of a connection so that when
8# two connections behind doors are shuffled together, their doors can be paired.
9ports { 3ports {
10 name: "ENTRY" 4 name: "ENTRY"
5 display_name: "Near Globe White Hallway"
11 path: "Components/Warps/Worldports/worldport10" 6 path: "Components/Warps/Worldports/worldport10"
7 destination { x: -46 y: 0 z: 23 }
8 rotation: 90
12} 9}
diff --git a/data/maps/daedalus/rooms/Wisdom Panel.txtpb b/data/maps/daedalus/rooms/Wisdom Panel.txtpb index 5cbf051..d789f2b 100644 --- a/data/maps/daedalus/rooms/Wisdom Panel.txtpb +++ b/data/maps/daedalus/rooms/Wisdom Panel.txtpb
@@ -1,5 +1,5 @@
1name: "Wisdom Panel" 1name: "Wisdom Panel"
2display_name: "Castle" 2panel_display_name: "Castle"
3panels { 3panels {
4 name: "INTELLIGENCE" 4 name: "INTELLIGENCE"
5 path: "Components/Warps/numbers" 5 path: "Components/Warps/numbers"
diff --git a/data/maps/daedalus/rooms/Wonderland.txtpb b/data/maps/daedalus/rooms/Wonderland.txtpb index 99c124e..b4782d2 100644 --- a/data/maps/daedalus/rooms/Wonderland.txtpb +++ b/data/maps/daedalus/rooms/Wonderland.txtpb
@@ -1,6 +1,5 @@
1name: "Wonderland" 1name: "Wonderland"
2display_name: "Northwest Area" 2panel_display_name: "Northwest Area"
3# TODO: There's a warp from The Entry into here.
4panels { 3panels {
5 name: "APRIL" 4 name: "APRIL"
6 path: "Panels/Wonderland/wonderland_1" 5 path: "Panels/Wonderland/wonderland_1"
@@ -38,5 +37,8 @@ panels {
38} 37}
39ports { 38ports {
40 name: "WONDROUS" 39 name: "WONDROUS"
40 display_name: "Wonderland Worldport"
41 path: "Components/Warps/Worldports/worldport3" 41 path: "Components/Warps/Worldports/worldport3"
42 destination { x: -104 y: 0 z: -69 }
43 rotation: 180
42} 44}
diff --git a/data/maps/daedalus/rooms/Yellow Color Backside.txtpb b/data/maps/daedalus/rooms/Yellow Color Backside.txtpb index 931e501..1c29b43 100644 --- a/data/maps/daedalus/rooms/Yellow Color Backside.txtpb +++ b/data/maps/daedalus/rooms/Yellow Color Backside.txtpb
@@ -1,5 +1,5 @@
1name: "Yellow Color Backside" 1name: "Yellow Color Backside"
2display_name: "Northeast Area" 2panel_display_name: "Northeast Area"
3panels { 3panels {
4 name: "WINDS" 4 name: "WINDS"
5 path: "Panels/Halls/halls_24" 5 path: "Panels/Halls/halls_24"
diff --git a/data/maps/daedalus/rooms/Yellow Color Door.txtpb b/data/maps/daedalus/rooms/Yellow Color Door.txtpb index a098c91..61d206b 100644 --- a/data/maps/daedalus/rooms/Yellow Color Door.txtpb +++ b/data/maps/daedalus/rooms/Yellow Color Door.txtpb
@@ -1,5 +1,5 @@
1name: "Yellow Color Door" 1name: "Yellow Color Door"
2display_name: "Northeast Area" 2panel_display_name: "Northeast Area"
3panels { 3panels {
4 name: "SUN" 4 name: "SUN"
5 path: "Panels/Yellow Room/panel_entry" 5 path: "Panels/Yellow Room/panel_entry"
@@ -26,9 +26,12 @@ paintings {
26 path: "Components/Paintings/Temple of the Eyes/eyeRedStart" 26 path: "Components/Paintings/Temple of the Eyes/eyeRedStart"
27 move: true 27 move: true
28 enter_only: true 28 enter_only: true
29 # TODO: requires double letters 29 required_door { name: "Eye Painting" }
30} 30}
31ports { 31ports {
32 name: "FOURROOMS" 32 name: "FOURROOMS"
33 display_name: "Near Yellow Worldport"
33 path: "Components/Warps/Worldports/worldport8" 34 path: "Components/Warps/Worldports/worldport8"
35 destination { x: 92.5 y: 0 z: -62 }
36 rotation: 90
34} 37}
diff --git a/data/maps/daedalus/rooms/Yellow Room.txtpb b/data/maps/daedalus/rooms/Yellow Room.txtpb index 1e84965..b4d8ff0 100644 --- a/data/maps/daedalus/rooms/Yellow Room.txtpb +++ b/data/maps/daedalus/rooms/Yellow Room.txtpb
@@ -1,5 +1,5 @@
1name: "Yellow Room" 1name: "Yellow Room"
2display_name: "Northeast Area" 2panel_display_name: "Yellow Room"
3panels { 3panels {
4 name: "FREE" 4 name: "FREE"
5 path: "Panels/Yellow Room/panel_1" 5 path: "Panels/Yellow Room/panel_1"
diff --git a/data/maps/daedalus/rooms/Yellow Smiley Annex.txtpb b/data/maps/daedalus/rooms/Yellow Smiley Annex.txtpb index fa059c4..cb6c402 100644 --- a/data/maps/daedalus/rooms/Yellow Smiley Annex.txtpb +++ b/data/maps/daedalus/rooms/Yellow Smiley Annex.txtpb
@@ -1,5 +1,5 @@
1name: "Yellow Smiley Annex" 1name: "Yellow Smiley Annex"
2display_name: "Hedges" 2panel_display_name: "Hedges"
3panels { 3panels {
4 name: "COW" 4 name: "COW"
5 path: "Panels/Miscellaneous/plum1" 5 path: "Panels/Miscellaneous/plum1"
diff --git a/data/maps/daedalus/rooms/Z2 Prize.txtpb b/data/maps/daedalus/rooms/Z2 Prize.txtpb index a7dd8fb..7b1ceae 100644 --- a/data/maps/daedalus/rooms/Z2 Prize.txtpb +++ b/data/maps/daedalus/rooms/Z2 Prize.txtpb
@@ -1,5 +1,5 @@
1name: "Z2 Prize" 1name: "Z2 Prize"
2display_name: "Northwest Area" 2panel_display_name: "Z2 Room"
3letters { 3letters {
4 key: "z" 4 key: "z"
5 level2: true 5 level2: true
diff --git a/data/maps/daedalus/rooms/Z2 Room.txtpb b/data/maps/daedalus/rooms/Z2 Room.txtpb index 1e84dbc..513150a 100644 --- a/data/maps/daedalus/rooms/Z2 Room.txtpb +++ b/data/maps/daedalus/rooms/Z2 Room.txtpb
@@ -1,5 +1,5 @@
1name: "Z2 Room" 1name: "Z2 Room"
2display_name: "Northwest Area" 2panel_display_name: "Z2 Room"
3panels { 3panels {
4 name: "EXHIBIT" 4 name: "EXHIBIT"
5 path: "Panels/V Maze/entry" 5 path: "Panels/V Maze/entry"
diff --git a/data/maps/daedalus/rooms/Zoo Center.txtpb b/data/maps/daedalus/rooms/Zoo Center.txtpb index fcf72a1..5a788db 100644 --- a/data/maps/daedalus/rooms/Zoo Center.txtpb +++ b/data/maps/daedalus/rooms/Zoo Center.txtpb
@@ -1,5 +1,5 @@
1name: "Zoo Center" 1name: "Zoo Center"
2display_name: "Zoo" 2panel_display_name: "Zoo"
3letters { 3letters {
4 key: "v" 4 key: "v"
5 level2: true 5 level2: true
diff --git a/data/maps/daedalus/rooms/Zoo E.txtpb b/data/maps/daedalus/rooms/Zoo E.txtpb index 59479dc..3195623 100644 --- a/data/maps/daedalus/rooms/Zoo E.txtpb +++ b/data/maps/daedalus/rooms/Zoo E.txtpb
@@ -1,5 +1,5 @@
1name: "Zoo E" 1name: "Zoo E"
2display_name: "Zoo" 2panel_display_name: "Zoo"
3panels { 3panels {
4 name: "WING" 4 name: "WING"
5 path: "Panels/V Maze/four_1" 5 path: "Panels/V Maze/four_1"
diff --git a/data/maps/daedalus/rooms/Zoo N.txtpb b/data/maps/daedalus/rooms/Zoo N.txtpb index e2c1f5d..d621ed4 100644 --- a/data/maps/daedalus/rooms/Zoo N.txtpb +++ b/data/maps/daedalus/rooms/Zoo N.txtpb
@@ -1,5 +1,5 @@
1name: "Zoo N" 1name: "Zoo N"
2display_name: "Zoo" 2panel_display_name: "Zoo"
3panels { 3panels {
4 name: "BILL" 4 name: "BILL"
5 path: "Panels/V Maze/four_13" 5 path: "Panels/V Maze/four_13"
@@ -13,6 +13,7 @@ panels {
13 clue: "fin" 13 clue: "fin"
14 answer: "whale" 14 answer: "whale"
15 symbols: BOXES 15 symbols: BOXES
16 display_name: "FIN (N)"
16} 17}
17panels { 18panels {
18 name: "BLOWHOLE" 19 name: "BLOWHOLE"
diff --git a/data/maps/daedalus/rooms/Zoo NE.txtpb b/data/maps/daedalus/rooms/Zoo NE.txtpb index 155172d..89bedae 100644 --- a/data/maps/daedalus/rooms/Zoo NE.txtpb +++ b/data/maps/daedalus/rooms/Zoo NE.txtpb
@@ -1,5 +1,5 @@
1name: "Zoo NE" 1name: "Zoo NE"
2display_name: "Zoo" 2panel_display_name: "Zoo"
3panels { 3panels {
4 name: "FANG" 4 name: "FANG"
5 path: "Panels/V Maze/four_5" 5 path: "Panels/V Maze/four_5"
diff --git a/data/maps/daedalus/rooms/Zoo S.txtpb b/data/maps/daedalus/rooms/Zoo S.txtpb index f4ddaea..3f3a8de 100644 --- a/data/maps/daedalus/rooms/Zoo S.txtpb +++ b/data/maps/daedalus/rooms/Zoo S.txtpb
@@ -1,5 +1,5 @@
1name: "Zoo S" 1name: "Zoo S"
2display_name: "Zoo" 2panel_display_name: "Zoo"
3panels { 3panels {
4 name: "SHELL" 4 name: "SHELL"
5 path: "Panels/V Maze/four_9" 5 path: "Panels/V Maze/four_9"
@@ -13,6 +13,7 @@ panels {
13 clue: "fin" 13 clue: "fin"
14 answer: "fish" 14 answer: "fish"
15 symbols: BOXES 15 symbols: BOXES
16 display_name: "FIN (S)"
16} 17}
17panels { 18panels {
18 name: "PINCER" 19 name: "PINCER"
diff --git a/data/maps/daedalus/rooms/Zoo SE.txtpb b/data/maps/daedalus/rooms/Zoo SE.txtpb index 906d009..199f234 100644 --- a/data/maps/daedalus/rooms/Zoo SE.txtpb +++ b/data/maps/daedalus/rooms/Zoo SE.txtpb
@@ -1,2 +1,2 @@
1name: "Zoo SE" 1name: "Zoo SE"
2display_name: "Zoo" 2panel_display_name: "Zoo"
diff --git a/data/maps/four_rooms/doors.txtpb b/data/maps/four_rooms/doors.txtpb index f0bf060..e58adb2 100644 --- a/data/maps/four_rooms/doors.txtpb +++ b/data/maps/four_rooms/doors.txtpb
@@ -11,6 +11,7 @@ doors {
11 panels { room: "Intensify Room" name: "INJURY" } 11 panels { room: "Intensify Room" name: "INJURY" }
12 panels { room: "Intensify Room" name: "SWAY" } 12 panels { room: "Intensify Room" name: "SWAY" }
13 location_room: "Intensify Room" 13 location_room: "Intensify Room"
14 location_name: "Intensify Room"
14} 15}
15doors { 16doors {
16 name: "Examples Door" 17 name: "Examples Door"
@@ -25,6 +26,7 @@ doors {
25 panels { room: "Examples Room" name: "URN" } 26 panels { room: "Examples Room" name: "URN" }
26 panels { room: "Examples Room" name: "ART" } 27 panels { room: "Examples Room" name: "ART" }
27 location_room: "Examples Room" 28 location_room: "Examples Room"
29 location_name: "Examples Room"
28} 30}
29doors { 31doors {
30 name: "Synonyms Door" 32 name: "Synonyms Door"
@@ -39,6 +41,7 @@ doors {
39 panels { room: "Synonyms Room" name: "SERIOUS" } 41 panels { room: "Synonyms Room" name: "SERIOUS" }
40 panels { room: "Synonyms Room" name: "FURY" } 42 panels { room: "Synonyms Room" name: "FURY" }
41 location_room: "Synonyms Room" 43 location_room: "Synonyms Room"
44 location_name: "Synonyms Room"
42} 45}
43doors { 46doors {
44 name: "Time Door" 47 name: "Time Door"
@@ -53,6 +56,7 @@ doors {
53 panels { room: "Time Room" name: "HOLE" } 56 panels { room: "Time Room" name: "HOLE" }
54 panels { room: "Time Room" name: "RHYTHM" } 57 panels { room: "Time Room" name: "RHYTHM" }
55 location_room: "Time Room" 58 location_room: "Time Room"
59 location_name: "Time Room"
56} 60}
57doors { 61doors {
58 name: "A2 Door" 62 name: "A2 Door"
diff --git a/data/maps/four_rooms/rooms/A2 Room.txtpb b/data/maps/four_rooms/rooms/A2 Room.txtpb index 236ce01..ea2ae64 100644 --- a/data/maps/four_rooms/rooms/A2 Room.txtpb +++ b/data/maps/four_rooms/rooms/A2 Room.txtpb
@@ -1,5 +1,4 @@
1name: "A2 Room" 1name: "A2 Room"
2display_name: "Hallway"
3letters { 2letters {
4 key: "a" 3 key: "a"
5 level2: true 4 level2: true
diff --git a/data/maps/four_rooms/rooms/Examples Room.txtpb b/data/maps/four_rooms/rooms/Examples Room.txtpb index 3d82e22..4146120 100644 --- a/data/maps/four_rooms/rooms/Examples Room.txtpb +++ b/data/maps/four_rooms/rooms/Examples Room.txtpb
@@ -1,5 +1,4 @@
1name: "Examples Room" 1name: "Examples Room"
2display_name: "Examples Room"
3panels { 2panels {
4 name: "SIZE (1)" 3 name: "SIZE (1)"
5 path: "Panels/Room 2 Examples/entry_1" 4 path: "Panels/Room 2 Examples/entry_1"
@@ -58,6 +57,8 @@ panels {
58} 57}
59ports { 58ports {
60 name: "DAEDALUS" 59 name: "DAEDALUS"
60 display_name: "Examples Room Worldport"
61 path: "Components/Warps/worldport2" 61 path: "Components/Warps/worldport2"
62 orientation: "north" 62 destination { x: 0 y: 0 z: -40.5 }
63 rotation: 180
63} 64}
diff --git a/data/maps/four_rooms/rooms/Hallway.txtpb b/data/maps/four_rooms/rooms/Hallway.txtpb index f80cf73..124a5b3 100644 --- a/data/maps/four_rooms/rooms/Hallway.txtpb +++ b/data/maps/four_rooms/rooms/Hallway.txtpb
@@ -1,5 +1,4 @@
1name: "Hallway" 1name: "Hallway"
2display_name: "Hallway"
3panels { 2panels {
4 name: "SUSPICION" 3 name: "SUSPICION"
5 path: "Panels/Reward Room/reward_1" 4 path: "Panels/Reward Room/reward_1"
diff --git a/data/maps/four_rooms/rooms/Intensify Room.txtpb b/data/maps/four_rooms/rooms/Intensify Room.txtpb index fb95a1e..8c6924a 100644 --- a/data/maps/four_rooms/rooms/Intensify Room.txtpb +++ b/data/maps/four_rooms/rooms/Intensify Room.txtpb
@@ -1,5 +1,4 @@
1name: "Intensify Room" 1name: "Intensify Room"
2display_name: "Intensify Room"
3panels { 2panels {
4 name: "SMALL" 3 name: "SMALL"
5 path: "Panels/Room 1 Intensify/entry_1" 4 path: "Panels/Room 1 Intensify/entry_1"
@@ -58,6 +57,8 @@ panels {
58} 57}
59ports { 58ports {
60 name: "IMPRESSIVE" 59 name: "IMPRESSIVE"
60 display_name: "Intensify Room Worldport"
61 path: "Components/Warps/worldport" 61 path: "Components/Warps/worldport"
62 orientation: "south" 62 destination { x: 0 y: 0 z: 6.5 }
63 rotation: 0
63} 64}
diff --git a/data/maps/four_rooms/rooms/Keyholder Room.txtpb b/data/maps/four_rooms/rooms/Keyholder Room.txtpb index 9605fad..13c3dce 100644 --- a/data/maps/four_rooms/rooms/Keyholder Room.txtpb +++ b/data/maps/four_rooms/rooms/Keyholder Room.txtpb
@@ -1,6 +1,6 @@
1name: "Keyholder Room" 1name: "Keyholder Room"
2display_name: "Hallway"
3keyholders { 2keyholders {
4 name: "A" 3 name: "A"
5 path: "Components/KeyHolders/keyHolderA" 4 path: "Components/KeyHolders/keyHolderA"
5 key: "a"
6} 6}
diff --git a/data/maps/four_rooms/rooms/Synonyms Room.txtpb b/data/maps/four_rooms/rooms/Synonyms Room.txtpb index 054e4ef..bcbf64e 100644 --- a/data/maps/four_rooms/rooms/Synonyms Room.txtpb +++ b/data/maps/four_rooms/rooms/Synonyms Room.txtpb
@@ -1,5 +1,4 @@
1name: "Synonyms Room" 1name: "Synonyms Room"
2display_name: "Synonyms Room"
3panels { 2panels {
4 name: "MINUTE" 3 name: "MINUTE"
5 path: "Panels/Room 3 Synonyms/entry_1" 4 path: "Panels/Room 3 Synonyms/entry_1"
@@ -58,6 +57,8 @@ panels {
58} 57}
59ports { 58ports {
60 name: "ENTRY" 59 name: "ENTRY"
60 display_name: "Synonyms Room Worldport"
61 path: "Components/Warps/worldport3" 61 path: "Components/Warps/worldport3"
62 orientation: "south" 62 destination { x: 20 y: 0 z: 6.5 }
63 rotation: 0
63} 64}
diff --git a/data/maps/four_rooms/rooms/Time Room.txtpb b/data/maps/four_rooms/rooms/Time Room.txtpb index 38f529d..74f951d 100644 --- a/data/maps/four_rooms/rooms/Time Room.txtpb +++ b/data/maps/four_rooms/rooms/Time Room.txtpb
@@ -1,5 +1,4 @@
1name: "Time Room" 1name: "Time Room"
2display_name: "Time Room"
3panels { 2panels {
4 name: "BROODING" 3 name: "BROODING"
5 path: "Panels/Room 4 Time/entry_1" 4 path: "Panels/Room 4 Time/entry_1"
@@ -58,6 +57,8 @@ panels {
58} 57}
59ports { 58ports {
60 name: "OWL" 59 name: "OWL"
60 display_name: "Time Room Worldport"
61 path: "Components/Warps/worldport4" 61 path: "Components/Warps/worldport4"
62 orientation: "north" 62 destination { x: 20 y: 0 z: -40.5 }
63 rotation: 180
63} 64}
diff --git a/data/maps/the_ancient/doors.txtpb b/data/maps/the_ancient/doors.txtpb index 894fbf5..e550306 100644 --- a/data/maps/the_ancient/doors.txtpb +++ b/data/maps/the_ancient/doors.txtpb
@@ -1,18 +1,45 @@
1doors { 1doors {
2 name: "Front Door" 2 name: "Front Door"
3 type: STANDARD 3 type: STANDARD
4 receivers: "Components/Doors/Front N Tree"
4 panels { room: "Outside" name: "THIS" } 5 panels { room: "Outside" name: "THIS" }
5 location_room: "Outside" 6 location_room: "Outside"
6} 7}
7doors { 8doors {
8 name: "End Door" 9 name: "End Door"
9 type: STANDARD 10 type: EVENT
10 # TODO: all the keyholders! 11 keyholders { map: "four_rooms" room: "Keyholder Room" name: "A" key: "a" }
12 keyholders { map: "the_hive" room: "Main Area" name: "B" key: "b" }
13 keyholders { map: "daedalus" room: "C Keyholder" name: "C" key: "c" }
14 keyholders { map: "daedalus" room: "D Keyholder" name: "D" key: "d" }
15 keyholders { map: "control_center" room: "Main Area" name: "2" key: "e" }
16 keyholders { map: "daedalus" room: "F Keyholder" name: "F" key: "f" }
17 keyholders { map: "daedalus" room: "Number Paintings Area" name: "G" key: "g" }
18 keyholders { map: "daedalus" room: "Outside House" name: "H" key: "h" }
19 keyholders { map: "the_unkempt" room: "Main Area" name: "I" key: "i" }
20 keyholders { map: "the_jubilant" room: "Side Area" name: "J" key: "j" }
21 keyholders { map: "the_tenacious" room: "Main Area" name: "K" key: "k" }
22 keyholders { map: "the_partial" room: "Obverse Side" name: "L" key: "l" }
23 keyholders { map: "the_extravagant" room: "X Plus" name: "M" key: "m" }
24 keyholders { map: "the_shop" room: "Main Area" name: "N" key: "n" }
25 keyholders { map: "control_center" room: "Main Area" name: "4" key: "o" }
26 keyholders { map: "the_gallery" room: "Main Area" name: "P" key: "p" }
27 keyholders { map: "the_quiet" room: "Keyholder Room" name: "Q" key: "q" }
28 keyholders { map: "control_center" room: "Main Area" name: "3" key: "r" }
29 keyholders { map: "the_nuanced" room: "Main Room" name: "S" key: "s" }
30 keyholders { map: "the_congruent" room: "T Keyholder" name: "T" key: "t" }
31 keyholders { map: "the_parthenon" room: "U Keyholder" name: "U" key: "u" }
32 keyholders { map: "the_unkempt" room: "V Keyholder" name: "V" key: "v" }
33 keyholders { map: "the_unkempt" room: "W Keyholder" name: "W" key: "w" }
34 keyholders { map: "the_great" room: "North Landscape" name: "X" key: "x" }
35 keyholders { map: "the_talented" room: "Main Area" name: "Y" key: "y" }
36 keyholders { map: "control_center" room: "Main Area" name: "1" key: "z" }
11 location_room: "Inside" 37 location_room: "Inside"
12} 38}
13doors { 39doors {
14 name: "Lavender Cubes" 40 name: "Lavender Cubes"
15 type: STANDARD 41 type: LOCATION_ONLY
16 panels { room: "Inside" name: "COLOR" } 42 panels { room: "Inside" name: "COLOR" }
17 location_room: "Inside" 43 location_room: "Inside"
44 location_name: "COLOR"
18} 45}
diff --git a/data/maps/the_ancient/rooms/Ending.txtpb b/data/maps/the_ancient/rooms/Ending.txtpb index eea1228..df3fe01 100644 --- a/data/maps/the_ancient/rooms/Ending.txtpb +++ b/data/maps/the_ancient/rooms/Ending.txtpb
@@ -1,5 +1,4 @@
1name: "Ending" 1name: "Ending"
2display_name: "Ending"
3endings { 2endings {
4 name: "GREEN" 3 name: "GREEN"
5 path: "Components/Ending/green_ending" 4 path: "Components/Ending/green_ending"
diff --git a/data/maps/the_ancient/rooms/Inside.txtpb b/data/maps/the_ancient/rooms/Inside.txtpb index d088682..3723b2d 100644 --- a/data/maps/the_ancient/rooms/Inside.txtpb +++ b/data/maps/the_ancient/rooms/Inside.txtpb
@@ -1,10 +1,8 @@
1name: "Inside" 1name: "Inside"
2display_name: "Inside"
3panels { 2panels {
4 name: "COLOR" 3 name: "COLOR"
5 path: "Panels/panel_2" 4 path: "Panels/panel_2"
6 clue: "color" 5 clue: "color"
7 answer: "lavender" 6 answer: "lavender"
8 symbols: EXAMPLE 7 symbols: EXAMPLE
9 # TODO: how does this connect to the "lavender_cubes" switch?
10} 8}
diff --git a/data/maps/the_ancient/rooms/Outside.txtpb b/data/maps/the_ancient/rooms/Outside.txtpb index 6f49bba..1458357 100644 --- a/data/maps/the_ancient/rooms/Outside.txtpb +++ b/data/maps/the_ancient/rooms/Outside.txtpb
@@ -1,8 +1,8 @@
1name: "Outside" 1name: "Outside"
2display_name: "Outside"
3panels { 2panels {
4 name: "THIS" 3 name: "THIS"
5 path: "Panels/panel_1" 4 path: "Panels/panel_1"
6 clue: "this" 5 clue: "this"
7 answer: "sphinx" 6 answer: "sphinx"
7 symbols: QUESTION
8} 8}
diff --git a/data/maps/the_bearer/connections.txtpb b/data/maps/the_bearer/connections.txtpb index 23410f0..ba14d83 100644 --- a/data/maps/the_bearer/connections.txtpb +++ b/data/maps/the_bearer/connections.txtpb
@@ -263,3 +263,8 @@ connections {
263 to_room: "Butterfly Room" 263 to_room: "Butterfly Room"
264 door { name: "Butterfly Entrance" } 264 door { name: "Butterfly Entrance" }
265} 265}
266connections {
267 from_room: "Back Area"
268 to_room: "Tree Entrance"
269 door { name: "Control Center Brown Door" }
270}
diff --git a/data/maps/the_bearer/doors.txtpb b/data/maps/the_bearer/doors.txtpb index 1faddef..f1f5a57 100644 --- a/data/maps/the_bearer/doors.txtpb +++ b/data/maps/the_bearer/doors.txtpb
@@ -211,7 +211,7 @@ doors {
211} 211}
212doors { 212doors {
213 name: "Q2 Door" 213 name: "Q2 Door"
214 type: STANDARD 214 type: EVENT
215 receivers: "Components/Doors/entry_3" 215 receivers: "Components/Doors/entry_3"
216 panels { room: "Entry" name: "SQUISH" } 216 panels { room: "Entry" name: "SQUISH" }
217 panels { room: "Entry" name: "MANE" } 217 panels { room: "Entry" name: "MANE" }
@@ -237,7 +237,6 @@ doors {
237 panels { room: "Red Vegetable" name: "CARD" } 237 panels { room: "Red Vegetable" name: "CARD" }
238 panels { room: "Yellow Planet" name: "ZEUS" } 238 panels { room: "Yellow Planet" name: "ZEUS" }
239 panels { room: "Yellow Vegetable" name: "CAKE" } 239 panels { room: "Yellow Vegetable" name: "CAKE" }
240 location_room: "Entry"
241} 240}
242doors { 241doors {
243 name: "Control Center Brown Door" 242 name: "Control Center Brown Door"
@@ -249,5 +248,5 @@ doors {
249 name: "Butterfly Entrance" 248 name: "Butterfly Entrance"
250 type: ITEM_ONLY 249 type: ITEM_ONLY
251 receivers: "Components/Doors/brown_2" 250 receivers: "Components/Doors/brown_2"
252 switches: "double_letters" 251 double_letters: true
253} 252}
diff --git a/data/maps/the_bearer/rooms/Back Area.txtpb b/data/maps/the_bearer/rooms/Back Area.txtpb index bd90b50..2be4cb4 100644 --- a/data/maps/the_bearer/rooms/Back Area.txtpb +++ b/data/maps/the_bearer/rooms/Back Area.txtpb
@@ -1,5 +1,4 @@
1name: "Back Area" 1name: "Back Area"
2display_name: "Back Area"
3panels { 2panels {
4 name: "COLOR" 3 name: "COLOR"
5 path: "Panels/Entry/panel_3" 4 path: "Panels/Entry/panel_3"
@@ -8,13 +7,9 @@ panels {
8 symbols: EXAMPLE 7 symbols: EXAMPLE
9} 8}
10ports { 9ports {
11 name: "TREE"
12 path: "Components/Warps/worldport3"
13 orientation: "north"
14 required_door { name: "Control Center Brown Door" }
15}
16ports {
17 name: "DAEDALUS" 10 name: "DAEDALUS"
11 display_name: "Dark Hallway"
18 path: "Components/Warps/worldport2" 12 path: "Components/Warps/worldport2"
19 orientation: "north" 13 destination { x: 10 y: 0 z: -84.5 }
14 rotation: 180
20} 15}
diff --git a/data/maps/the_bearer/rooms/Blue Animal (View).txtpb b/data/maps/the_bearer/rooms/Blue Animal (View).txtpb index a13ce1d..33c278c 100644 --- a/data/maps/the_bearer/rooms/Blue Animal (View).txtpb +++ b/data/maps/the_bearer/rooms/Blue Animal (View).txtpb
@@ -1,5 +1,4 @@
1name: "Blue Animal (View)" 1name: "Blue Animal (View)"
2display_name: "Main Area"
3panels { 2panels {
4 name: "HALF" 3 name: "HALF"
5 path: "Panels/Blue/panel_2" 4 path: "Panels/Blue/panel_2"
diff --git a/data/maps/the_bearer/rooms/Blue Animal.txtpb b/data/maps/the_bearer/rooms/Blue Animal.txtpb index 49ac048..e503c93 100644 --- a/data/maps/the_bearer/rooms/Blue Animal.txtpb +++ b/data/maps/the_bearer/rooms/Blue Animal.txtpb
@@ -1,2 +1 @@
1name: "Blue Animal" name: "Blue Animal"
2display_name: "Main Area"
diff --git a/data/maps/the_bearer/rooms/Blue Planet (View).txtpb b/data/maps/the_bearer/rooms/Blue Planet (View).txtpb index 172565b..e745718 100644 --- a/data/maps/the_bearer/rooms/Blue Planet (View).txtpb +++ b/data/maps/the_bearer/rooms/Blue Planet (View).txtpb
@@ -1,5 +1,4 @@
1name: "Blue Planet (View)" 1name: "Blue Planet (View)"
2display_name: "Main Area"
3panels { 2panels {
4 name: "TUNE" 3 name: "TUNE"
5 path: "Panels/Blue/panel_4" 4 path: "Panels/Blue/panel_4"
diff --git a/data/maps/the_bearer/rooms/Blue Planet.txtpb b/data/maps/the_bearer/rooms/Blue Planet.txtpb index b291c35..b044590 100644 --- a/data/maps/the_bearer/rooms/Blue Planet.txtpb +++ b/data/maps/the_bearer/rooms/Blue Planet.txtpb
@@ -1,2 +1 @@
1name: "Blue Planet" name: "Blue Planet"
2display_name: "Main Area"
diff --git a/data/maps/the_bearer/rooms/Blue Town (View).txtpb b/data/maps/the_bearer/rooms/Blue Town (View).txtpb index f66eae9..f57fc9b 100644 --- a/data/maps/the_bearer/rooms/Blue Town (View).txtpb +++ b/data/maps/the_bearer/rooms/Blue Town (View).txtpb
@@ -1,5 +1,4 @@
1name: "Blue Town (View)" 1name: "Blue Town (View)"
2display_name: "Main Area"
3panels { 2panels {
4 name: "LICE" 3 name: "LICE"
5 path: "Panels/Blue/panel_3" 4 path: "Panels/Blue/panel_3"
diff --git a/data/maps/the_bearer/rooms/Blue Town.txtpb b/data/maps/the_bearer/rooms/Blue Town.txtpb index b24af76..5ceed12 100644 --- a/data/maps/the_bearer/rooms/Blue Town.txtpb +++ b/data/maps/the_bearer/rooms/Blue Town.txtpb
@@ -1,2 +1 @@
1name: "Blue Town" name: "Blue Town"
2display_name: "Main Area"
diff --git a/data/maps/the_bearer/rooms/Blue Vegetable (View).txtpb b/data/maps/the_bearer/rooms/Blue Vegetable (View).txtpb index f9443fd..cf1ffd3 100644 --- a/data/maps/the_bearer/rooms/Blue Vegetable (View).txtpb +++ b/data/maps/the_bearer/rooms/Blue Vegetable (View).txtpb
@@ -1,5 +1,4 @@
1name: "Blue Vegetable (View)" 1name: "Blue Vegetable (View)"
2display_name: "Main Area"
3panels { 2panels {
4 name: "THORN" 3 name: "THORN"
5 path: "Panels/Blue/panel_1" 4 path: "Panels/Blue/panel_1"
diff --git a/data/maps/the_bearer/rooms/Blue Vegetable.txtpb b/data/maps/the_bearer/rooms/Blue Vegetable.txtpb index 9034471..64ce77d 100644 --- a/data/maps/the_bearer/rooms/Blue Vegetable.txtpb +++ b/data/maps/the_bearer/rooms/Blue Vegetable.txtpb
@@ -1,2 +1 @@
1name: "Blue Vegetable" name: "Blue Vegetable"
2display_name: "Main Area"
diff --git a/data/maps/the_bearer/rooms/Butterfly Room.txtpb b/data/maps/the_bearer/rooms/Butterfly Room.txtpb index bd20505..a702737 100644 --- a/data/maps/the_bearer/rooms/Butterfly Room.txtpb +++ b/data/maps/the_bearer/rooms/Butterfly Room.txtpb
@@ -1,5 +1,4 @@
1name: "Butterfly Room" 1name: "Butterfly Room"
2display_name: "Back Area"
3panels { 2panels {
4 name: "VIBRANT" 3 name: "VIBRANT"
5 path: "Panels/Entry/panel_4" 4 path: "Panels/Entry/panel_4"
diff --git a/data/maps/the_bearer/rooms/Entry.txtpb b/data/maps/the_bearer/rooms/Entry.txtpb index d7a8db6..517088d 100644 --- a/data/maps/the_bearer/rooms/Entry.txtpb +++ b/data/maps/the_bearer/rooms/Entry.txtpb
@@ -1,5 +1,4 @@
1name: "Entry" 1name: "Entry"
2display_name: "Main Area"
3panels { 2panels {
4 name: "VIEW" 3 name: "VIEW"
5 path: "Panels/Entry/panel_1" 4 path: "Panels/Entry/panel_1"
@@ -58,6 +57,8 @@ panels {
58} 57}
59ports { 58ports {
60 name: "UNYIELDING" 59 name: "UNYIELDING"
60 display_name: "Main Entrance"
61 path: "Components/Warps/worldport" 61 path: "Components/Warps/worldport"
62 orientation: "east" 62 destination { x: 3 y: 4 z: 15 }
63 rotation: 90
63} 64}
diff --git a/data/maps/the_bearer/rooms/Green Animal.txtpb b/data/maps/the_bearer/rooms/Green Animal.txtpb index 61522cc..147f825 100644 --- a/data/maps/the_bearer/rooms/Green Animal.txtpb +++ b/data/maps/the_bearer/rooms/Green Animal.txtpb
@@ -1,2 +1 @@
1name: "Green Animal" name: "Green Animal"
2display_name: "Main Area"
diff --git a/data/maps/the_bearer/rooms/Green Planet (View).txtpb b/data/maps/the_bearer/rooms/Green Planet (View).txtpb index 79363bc..4d9f449 100644 --- a/data/maps/the_bearer/rooms/Green Planet (View).txtpb +++ b/data/maps/the_bearer/rooms/Green Planet (View).txtpb
@@ -1,5 +1,4 @@
1name: "Green Planet (View)" 1name: "Green Planet (View)"
2display_name: "Main Area"
3panels { 2panels {
4 name: "SOIL" 3 name: "SOIL"
5 path: "Panels/Green/panel_4" 4 path: "Panels/Green/panel_4"
diff --git a/data/maps/the_bearer/rooms/Green Planet.txtpb b/data/maps/the_bearer/rooms/Green Planet.txtpb index b97b731..efe000a 100644 --- a/data/maps/the_bearer/rooms/Green Planet.txtpb +++ b/data/maps/the_bearer/rooms/Green Planet.txtpb
@@ -1,2 +1 @@
1name: "Green Planet" name: "Green Planet"
2display_name: "Main Area"
diff --git a/data/maps/the_bearer/rooms/Green Town.txtpb b/data/maps/the_bearer/rooms/Green Town.txtpb index 184ded3..fd80201 100644 --- a/data/maps/the_bearer/rooms/Green Town.txtpb +++ b/data/maps/the_bearer/rooms/Green Town.txtpb
@@ -1,2 +1 @@
1name: "Green Town" name: "Green Town"
2display_name: "Main Area"
diff --git a/data/maps/the_bearer/rooms/Green Vegetable (View).txtpb b/data/maps/the_bearer/rooms/Green Vegetable (View).txtpb index 4bbab5d..98fbbe8 100644 --- a/data/maps/the_bearer/rooms/Green Vegetable (View).txtpb +++ b/data/maps/the_bearer/rooms/Green Vegetable (View).txtpb
@@ -1,5 +1,4 @@
1name: "Green Vegetable (View)" 1name: "Green Vegetable (View)"
2display_name: "Main Area"
3panels { 2panels {
4 name: "SPIN" 3 name: "SPIN"
5 path: "Panels/Green/panel_1" 4 path: "Panels/Green/panel_1"
diff --git a/data/maps/the_bearer/rooms/Green Vegetable.txtpb b/data/maps/the_bearer/rooms/Green Vegetable.txtpb index ccb817a..051a6d3 100644 --- a/data/maps/the_bearer/rooms/Green Vegetable.txtpb +++ b/data/maps/the_bearer/rooms/Green Vegetable.txtpb
@@ -1,2 +1 @@
1name: "Green Vegetable" name: "Green Vegetable"
2display_name: "Main Area"
diff --git a/data/maps/the_bearer/rooms/Orange Planet.txtpb b/data/maps/the_bearer/rooms/Orange Planet.txtpb index 0fbd929..15fae66 100644 --- a/data/maps/the_bearer/rooms/Orange Planet.txtpb +++ b/data/maps/the_bearer/rooms/Orange Planet.txtpb
@@ -1,5 +1,4 @@
1name: "Orange Planet" 1name: "Orange Planet"
2display_name: "Main Area"
3panels { 2panels {
4 name: "MAR" 3 name: "MAR"
5 path: "Panels/Red/panel_4" 4 path: "Panels/Red/panel_4"
diff --git a/data/maps/the_bearer/rooms/Orange Vegetable.txtpb b/data/maps/the_bearer/rooms/Orange Vegetable.txtpb index d4f7b82..e4d59e6 100644 --- a/data/maps/the_bearer/rooms/Orange Vegetable.txtpb +++ b/data/maps/the_bearer/rooms/Orange Vegetable.txtpb
@@ -1,5 +1,4 @@
1name: "Orange Vegetable" 1name: "Orange Vegetable"
2display_name: "Main Area"
3panels { 2panels {
4 name: "POTATO" 3 name: "POTATO"
5 path: "Panels/Red/panel_1" 4 path: "Panels/Red/panel_1"
diff --git a/data/maps/the_bearer/rooms/Overlook.txtpb b/data/maps/the_bearer/rooms/Overlook.txtpb index 384802c..9eadf8f 100644 --- a/data/maps/the_bearer/rooms/Overlook.txtpb +++ b/data/maps/the_bearer/rooms/Overlook.txtpb
@@ -1,2 +1 @@
1name: "Overlook" name: "Overlook"
2display_name: "Main Area"
diff --git a/data/maps/the_bearer/rooms/Purple Animal (View).txtpb b/data/maps/the_bearer/rooms/Purple Animal (View).txtpb index 7122059..04ae0f8 100644 --- a/data/maps/the_bearer/rooms/Purple Animal (View).txtpb +++ b/data/maps/the_bearer/rooms/Purple Animal (View).txtpb
@@ -1,5 +1,4 @@
1name: "Purple Animal (View)" 1name: "Purple Animal (View)"
2display_name: "Main Area"
3panels { 2panels {
4 name: "SUNBASS" 3 name: "SUNBASS"
5 path: "Panels/Purple/panel_2" 4 path: "Panels/Purple/panel_2"
diff --git a/data/maps/the_bearer/rooms/Purple Animal.txtpb b/data/maps/the_bearer/rooms/Purple Animal.txtpb index 9ddb70e..1c3a52c 100644 --- a/data/maps/the_bearer/rooms/Purple Animal.txtpb +++ b/data/maps/the_bearer/rooms/Purple Animal.txtpb
@@ -1,2 +1 @@
1name: "Purple Animal" name: "Purple Animal"
2display_name: "Main Area"
diff --git a/data/maps/the_bearer/rooms/Purple Planet (View).txtpb b/data/maps/the_bearer/rooms/Purple Planet (View).txtpb index 4ab506d..bacfae6 100644 --- a/data/maps/the_bearer/rooms/Purple Planet (View).txtpb +++ b/data/maps/the_bearer/rooms/Purple Planet (View).txtpb
@@ -1,5 +1,4 @@
1name: "Purple Planet (View)" 1name: "Purple Planet (View)"
2display_name: "Main Area"
3panels { 2panels {
4 name: "DOG" 3 name: "DOG"
5 path: "Panels/Purple/panel_4" 4 path: "Panels/Purple/panel_4"
diff --git a/data/maps/the_bearer/rooms/Purple Planet.txtpb b/data/maps/the_bearer/rooms/Purple Planet.txtpb index 37f7ddc..03021d5 100644 --- a/data/maps/the_bearer/rooms/Purple Planet.txtpb +++ b/data/maps/the_bearer/rooms/Purple Planet.txtpb
@@ -1,2 +1 @@
1name: "Purple Planet" name: "Purple Planet"
2display_name: "Main Area"
diff --git a/data/maps/the_bearer/rooms/Purple Town (View).txtpb b/data/maps/the_bearer/rooms/Purple Town (View).txtpb index 40927f4..855e3ea 100644 --- a/data/maps/the_bearer/rooms/Purple Town (View).txtpb +++ b/data/maps/the_bearer/rooms/Purple Town (View).txtpb
@@ -1,5 +1,4 @@
1name: "Purple Town (View)" 1name: "Purple Town (View)"
2display_name: "Main Area"
3panels { 2panels {
4 name: "GRACEFUL" 3 name: "GRACEFUL"
5 path: "Panels/Purple/panel_3" 4 path: "Panels/Purple/panel_3"
diff --git a/data/maps/the_bearer/rooms/Purple Town.txtpb b/data/maps/the_bearer/rooms/Purple Town.txtpb index 768f378..b077178 100644 --- a/data/maps/the_bearer/rooms/Purple Town.txtpb +++ b/data/maps/the_bearer/rooms/Purple Town.txtpb
@@ -1,2 +1 @@
1name: "Purple Town" name: "Purple Town"
2display_name: "Main Area"
diff --git a/data/maps/the_bearer/rooms/Purple Vegetable (View).txtpb b/data/maps/the_bearer/rooms/Purple Vegetable (View).txtpb index 182a5bb..1a6ab04 100644 --- a/data/maps/the_bearer/rooms/Purple Vegetable (View).txtpb +++ b/data/maps/the_bearer/rooms/Purple Vegetable (View).txtpb
@@ -1,5 +1,4 @@
1name: "Purple Vegetable (View)" 1name: "Purple Vegetable (View)"
2display_name: "Main Area"
3panels { 2panels {
4 name: "AUBERGINE" 3 name: "AUBERGINE"
5 path: "Panels/Purple/panel_1" 4 path: "Panels/Purple/panel_1"
diff --git a/data/maps/the_bearer/rooms/Purple Vegetable.txtpb b/data/maps/the_bearer/rooms/Purple Vegetable.txtpb index ef5dd7e..380b909 100644 --- a/data/maps/the_bearer/rooms/Purple Vegetable.txtpb +++ b/data/maps/the_bearer/rooms/Purple Vegetable.txtpb
@@ -1,2 +1 @@
1name: "Purple Vegetable" name: "Purple Vegetable"
2display_name: "Main Area"
diff --git a/data/maps/the_bearer/rooms/Q2 Room.txtpb b/data/maps/the_bearer/rooms/Q2 Room.txtpb index ab5032a..5cdea80 100644 --- a/data/maps/the_bearer/rooms/Q2 Room.txtpb +++ b/data/maps/the_bearer/rooms/Q2 Room.txtpb
@@ -1,5 +1,4 @@
1name: "Q2 Room" 1name: "Q2 Room"
2display_name: "Back Area"
3letters { 2letters {
4 key: "q" 3 key: "q"
5 level2: true 4 level2: true
diff --git a/data/maps/the_bearer/rooms/Red Animal.txtpb b/data/maps/the_bearer/rooms/Red Animal.txtpb index 845fbed..d5ae244 100644 --- a/data/maps/the_bearer/rooms/Red Animal.txtpb +++ b/data/maps/the_bearer/rooms/Red Animal.txtpb
@@ -1,5 +1,4 @@
1name: "Red Animal" 1name: "Red Animal"
2display_name: "Main Area"
3panels { 2panels {
4 name: "FOOLSHARK" 3 name: "FOOLSHARK"
5 path: "Panels/Orange/panel_2" 4 path: "Panels/Orange/panel_2"
diff --git a/data/maps/the_bearer/rooms/Red Planet.txtpb b/data/maps/the_bearer/rooms/Red Planet.txtpb index 55a105d..dd3f2ec 100644 --- a/data/maps/the_bearer/rooms/Red Planet.txtpb +++ b/data/maps/the_bearer/rooms/Red Planet.txtpb
@@ -1,5 +1,4 @@
1name: "Red Planet" 1name: "Red Planet"
2display_name: "Main Area"
3panels { 2panels {
4 name: "FUEL" 3 name: "FUEL"
5 path: "Panels/Red/panel_3" 4 path: "Panels/Red/panel_3"
diff --git a/data/maps/the_bearer/rooms/Red Town.txtpb b/data/maps/the_bearer/rooms/Red Town.txtpb index 8a29ced..ed608cc 100644 --- a/data/maps/the_bearer/rooms/Red Town.txtpb +++ b/data/maps/the_bearer/rooms/Red Town.txtpb
@@ -1,5 +1,4 @@
1name: "Red Town" 1name: "Red Town"
2display_name: "Main Area"
3panels { 2panels {
4 name: "DESTRUCTION" 3 name: "DESTRUCTION"
5 path: "Panels/Orange/panel_3" 4 path: "Panels/Orange/panel_3"
diff --git a/data/maps/the_bearer/rooms/Red Vegetable.txtpb b/data/maps/the_bearer/rooms/Red Vegetable.txtpb index 1494e26..fb694db 100644 --- a/data/maps/the_bearer/rooms/Red Vegetable.txtpb +++ b/data/maps/the_bearer/rooms/Red Vegetable.txtpb
@@ -1,5 +1,4 @@
1name: "Red Vegetable" 1name: "Red Vegetable"
2display_name: "Main Area"
3panels { 2panels {
4 name: "CARD" 3 name: "CARD"
5 path: "Panels/Red/panel_2" 4 path: "Panels/Red/panel_2"
diff --git a/data/maps/the_bearer/rooms/Tree Entrance.txtpb b/data/maps/the_bearer/rooms/Tree Entrance.txtpb new file mode 100644 index 0000000..1b50ddd --- /dev/null +++ b/data/maps/the_bearer/rooms/Tree Entrance.txtpb
@@ -0,0 +1,8 @@
1name: "Tree Entrance"
2ports {
3 name: "TREE"
4 display_name: "Brown Hallway"
5 path: "Components/Warps/worldport3"
6 destination { x: -19 y: 0 z: -83.5 }
7 rotation: 180
8}
diff --git a/data/maps/the_bearer/rooms/Yellow Planet.txtpb b/data/maps/the_bearer/rooms/Yellow Planet.txtpb index 9c6d39d..7f8a86b 100644 --- a/data/maps/the_bearer/rooms/Yellow Planet.txtpb +++ b/data/maps/the_bearer/rooms/Yellow Planet.txtpb
@@ -1,5 +1,4 @@
1name: "Yellow Planet" 1name: "Yellow Planet"
2display_name: "Main Area"
3panels { 2panels {
4 name: "ZEUS" 3 name: "ZEUS"
5 path: "Panels/Orange/panel_4" 4 path: "Panels/Orange/panel_4"
diff --git a/data/maps/the_bearer/rooms/Yellow Vegetable.txtpb b/data/maps/the_bearer/rooms/Yellow Vegetable.txtpb index 26ef491..f37faa5 100644 --- a/data/maps/the_bearer/rooms/Yellow Vegetable.txtpb +++ b/data/maps/the_bearer/rooms/Yellow Vegetable.txtpb
@@ -1,5 +1,4 @@
1name: "Yellow Vegetable" 1name: "Yellow Vegetable"
2display_name: "Main Area"
3panels { 2panels {
4 name: "CAKE" 3 name: "CAKE"
5 path: "Panels/Orange/panel_1" 4 path: "Panels/Orange/panel_1"
diff --git a/data/maps/the_between/rooms/B2 Back Room.txtpb b/data/maps/the_between/rooms/B2 Back Room.txtpb index 132ba56..0972ed9 100644 --- a/data/maps/the_between/rooms/B2 Back Room.txtpb +++ b/data/maps/the_between/rooms/B2 Back Room.txtpb
@@ -1,5 +1,4 @@
1name: "B2 Back Room" 1name: "B2 Back Room"
2display_name: "B2 Room"
3letters { 2letters {
4 key: "b" 3 key: "b"
5 level2: true 4 level2: true
diff --git a/data/maps/the_between/rooms/B2 Front Room.txtpb b/data/maps/the_between/rooms/B2 Front Room.txtpb index 02c09fb..f23ed20 100644 --- a/data/maps/the_between/rooms/B2 Front Room.txtpb +++ b/data/maps/the_between/rooms/B2 Front Room.txtpb
@@ -1,5 +1,4 @@
1name: "B2 Front Room" 1name: "B2 Front Room"
2display_name: "B2 Room"
3paintings { 2paintings {
4 name: "EYES" 3 name: "EYES"
5 path: "Components/Paintings/eyes" 4 path: "Components/Paintings/eyes"
diff --git a/data/maps/the_between/rooms/Control Center Side.txtpb b/data/maps/the_between/rooms/Control Center Side.txtpb index 81bae60..b308586 100644 --- a/data/maps/the_between/rooms/Control Center Side.txtpb +++ b/data/maps/the_between/rooms/Control Center Side.txtpb
@@ -1,5 +1,4 @@
1name: "Control Center Side" 1name: "Control Center Side"
2display_name: "Control Center Side"
3panels { 2panels {
4 name: "RIGHT" 3 name: "RIGHT"
5 path: "Panels/Helpers/panel_1" 4 path: "Panels/Helpers/panel_1"
@@ -14,11 +13,15 @@ paintings {
14} 13}
15ports { 14ports {
16 name: "CC" 15 name: "CC"
16 display_name: "Lavender Structure"
17 path: "Components/Warps/worldport3" 17 path: "Components/Warps/worldport3"
18 orientation: "north" 18 destination { x: 36 y: 0 z: 1 }
19 rotation: 180
19} 20}
20ports { 21ports {
21 name: "LIVELY" 22 name: "LIVELY"
23 display_name: "Near Painting Worldport"
22 path: "Components/Warps/worldport2" 24 path: "Components/Warps/worldport2"
23 orientation: "south" 25 destination { x: 24 y: 0 z: 6.5 }
26 rotation: 0
24} 27}
diff --git a/data/maps/the_between/rooms/Main Area.txtpb b/data/maps/the_between/rooms/Main Area.txtpb index a8e15a9..898b265 100644 --- a/data/maps/the_between/rooms/Main Area.txtpb +++ b/data/maps/the_between/rooms/Main Area.txtpb
@@ -1,5 +1,4 @@
1name: "Main Area" 1name: "Main Area"
2display_name: "Main Area"
3panels { 2panels {
4 name: "NEW" 3 name: "NEW"
5 path: "Panels/Room 1/panel_1" 4 path: "Panels/Room 1/panel_1"
@@ -198,6 +197,8 @@ panels {
198} 197}
199ports { 198ports {
200 name: "GREAT" 199 name: "GREAT"
200 display_name: "Salmon Hallway"
201 path: "Components/Warps/worldport" 201 path: "Components/Warps/worldport"
202 orientation: "east" 202 destination { x: -1 y: 0 z: 20 }
203 rotation: 90
203} 204}
diff --git a/data/maps/the_between/rooms/Plaza Entrance.txtpb b/data/maps/the_between/rooms/Plaza Entrance.txtpb index b99081a..894ebae 100644 --- a/data/maps/the_between/rooms/Plaza Entrance.txtpb +++ b/data/maps/the_between/rooms/Plaza Entrance.txtpb
@@ -1,7 +1,8 @@
1name: "Plaza Entrance" 1name: "Plaza Entrance"
2display_name: "Main Area"
3ports { 2ports {
4 name: "PLAZA" 3 name: "PLAZA"
4 display_name: "Trick or Treat Worldport"
5 path: "Components/Warps/worldport4" 5 path: "Components/Warps/worldport4"
6 orientation: "north" 6 destination { x: -38 y: 0 z: 1 }
7 rotation: 180
7} 8}
diff --git a/data/maps/the_butterfly/rooms/Main Area.txtpb b/data/maps/the_butterfly/rooms/Main Area.txtpb index 9a8b3d5..453e64a 100644 --- a/data/maps/the_butterfly/rooms/Main Area.txtpb +++ b/data/maps/the_butterfly/rooms/Main Area.txtpb
@@ -1,5 +1,4 @@
1name: "Main Area" 1name: "Main Area"
2display_name: "Main Area"
3panels { 2panels {
4 name: "SPECIES" 3 name: "SPECIES"
5 path: "Panels/Room_1/panel_1" 4 path: "Panels/Room_1/panel_1"
@@ -128,6 +127,8 @@ panels {
128} 127}
129ports { 128ports {
130 name: "GALLERY" 129 name: "GALLERY"
130 display_name: "Worldport"
131 path: "Components/Warps/worldport" 131 path: "Components/Warps/worldport"
132 orientation: "southwest" # uhhhh this is new 132 destination { x: -19 y: 0 z: 19 }
133 rotation: 315
133} 134}
diff --git a/data/maps/the_butterfly/rooms/Mastery.txtpb b/data/maps/the_butterfly/rooms/Mastery.txtpb index f494fde..bbe8742 100644 --- a/data/maps/the_butterfly/rooms/Mastery.txtpb +++ b/data/maps/the_butterfly/rooms/Mastery.txtpb
@@ -1,5 +1,4 @@
1name: "Mastery" 1name: "Mastery"
2display_name: "Main Area"
3masteries { 2masteries {
4 name: "MASTERY" 3 name: "MASTERY"
5 path: "Components/Collectables/collectable" 4 path: "Components/Collectables/collectable"
diff --git a/data/maps/the_colorful/doors.txtpb b/data/maps/the_colorful/doors.txtpb index 32470b2..003c9a9 100644 --- a/data/maps/the_colorful/doors.txtpb +++ b/data/maps/the_colorful/doors.txtpb
@@ -46,13 +46,14 @@ doors {
46 type: STANDARD 46 type: STANDARD
47 receivers: "Components/Doors/entry_7" 47 receivers: "Components/Doors/entry_7"
48 panels { room: "Yellow Room" name: "CIRCLE" } 48 panels { room: "Yellow Room" name: "CIRCLE" }
49 panels { room: "Purple Room" name: "FISH" } 49 panels { room: "Purple Room" name: "FISH" answer: "fish" }
50 location_room: "Purple Room" 50 location_room: "Purple Room"
51} 51}
52doors { 52doors {
53 name: "Purple Side Entrance" 53 name: "Purple Side Entrance"
54 type: STANDARD 54 type: STANDARD
55 receivers: "Components/Doors/entry_7b3" 55 receivers: "Components/Doors/entry_7b3"
56 receivers: "Components/Doors/entry_7b4"
56 panels { room: "Cyan Hallway" name: "KOI" } 57 panels { room: "Cyan Hallway" name: "KOI" }
57 panels { room: "Cyan Hallway" name: "WISH" } 58 panels { room: "Cyan Hallway" name: "WISH" }
58 location_room: "Cyan Hallway" 59 location_room: "Cyan Hallway"
diff --git a/data/maps/the_colorful/rooms/Black Room.txtpb b/data/maps/the_colorful/rooms/Black Room.txtpb index 75aec81..21a0d41 100644 --- a/data/maps/the_colorful/rooms/Black Room.txtpb +++ b/data/maps/the_colorful/rooms/Black Room.txtpb
@@ -1,5 +1,4 @@
1name: "Black Room" 1name: "Black Room"
2display_name: "Black Room"
3panels { 2panels {
4 name: "STARK" 3 name: "STARK"
5 path: "Panels/Hallway/panel_2" 4 path: "Panels/Hallway/panel_2"
diff --git a/data/maps/the_colorful/rooms/Blue Room.txtpb b/data/maps/the_colorful/rooms/Blue Room.txtpb index c334f6e..ec9337d 100644 --- a/data/maps/the_colorful/rooms/Blue Room.txtpb +++ b/data/maps/the_colorful/rooms/Blue Room.txtpb
@@ -1,5 +1,4 @@
1name: "Blue Room" 1name: "Blue Room"
2display_name: "Blue Room"
3panels { 2panels {
4 name: "VINE" 3 name: "VINE"
5 path: "Panels/Hallway/panel_4" 4 path: "Panels/Hallway/panel_4"
diff --git a/data/maps/the_colorful/rooms/Brown Room.txtpb b/data/maps/the_colorful/rooms/Brown Room.txtpb index 8eec879..a5f590b 100644 --- a/data/maps/the_colorful/rooms/Brown Room.txtpb +++ b/data/maps/the_colorful/rooms/Brown Room.txtpb
@@ -1,5 +1,4 @@
1name: "Brown Room" 1name: "Brown Room"
2display_name: "Brown Room"
3panels { 2panels {
4 name: "FIRE" 3 name: "FIRE"
5 path: "Panels/Hallway/panel_9" 4 path: "Panels/Hallway/panel_9"
diff --git a/data/maps/the_colorful/rooms/Cyan Hallway.txtpb b/data/maps/the_colorful/rooms/Cyan Hallway.txtpb index d6a2425..d94a0a6 100644 --- a/data/maps/the_colorful/rooms/Cyan Hallway.txtpb +++ b/data/maps/the_colorful/rooms/Cyan Hallway.txtpb
@@ -1,5 +1,4 @@
1name: "Cyan Hallway" 1name: "Cyan Hallway"
2display_name: "Cyan Hallway"
3panels { 2panels {
4 name: "KOI" 3 name: "KOI"
5 path: "Panels/Extra/panel_12" 4 path: "Panels/Extra/panel_12"
@@ -24,11 +23,15 @@ panels {
24} 23}
25ports { 24ports {
26 name: "STURDY" 25 name: "STURDY"
26 display_name: "North Cyan Worldport"
27 path: "Components/Warps/worldport3" 27 path: "Components/Warps/worldport3"
28 orientation: "west" 28 destination { x: -17 y: 0 z: -75 }
29 rotation: 270
29} 30}
30ports { 31ports {
31 name: "DARKROOM" 32 name: "DARKROOM"
33 display_name: "South Cyan Worldport"
32 path: "Components/Warps/worldport2" 34 path: "Components/Warps/worldport2"
33 orientation: "west" 35 destination { x: -17 y: 0 z: -51 }
36 rotation: 270
34} 37}
diff --git a/data/maps/the_colorful/rooms/Cyan Room.txtpb b/data/maps/the_colorful/rooms/Cyan Room.txtpb index 09150ab..3568ec1 100644 --- a/data/maps/the_colorful/rooms/Cyan Room.txtpb +++ b/data/maps/the_colorful/rooms/Cyan Room.txtpb
@@ -1,5 +1,4 @@
1name: "Cyan Room" 1name: "Cyan Room"
2display_name: "Cyan Room"
3panels { 2panels {
4 name: "BROTHER" 3 name: "BROTHER"
5 path: "Panels/Cyan/panel_cyan_1" 4 path: "Panels/Cyan/panel_cyan_1"
diff --git a/data/maps/the_colorful/rooms/Ending.txtpb b/data/maps/the_colorful/rooms/Ending.txtpb index 060e72e..3aa2b3c 100644 --- a/data/maps/the_colorful/rooms/Ending.txtpb +++ b/data/maps/the_colorful/rooms/Ending.txtpb
@@ -1,5 +1,4 @@
1name: "Ending" 1name: "Ending"
2display_name: "Ending"
3endings { 2endings {
4 name: "GRAY" 3 name: "GRAY"
5 path: "Components/Endings/gray_ending" 4 path: "Components/Endings/gray_ending"
diff --git a/data/maps/the_colorful/rooms/Gray Room.txtpb b/data/maps/the_colorful/rooms/Gray Room.txtpb index 9d62ebf..6ae6c9c 100644 --- a/data/maps/the_colorful/rooms/Gray Room.txtpb +++ b/data/maps/the_colorful/rooms/Gray Room.txtpb
@@ -1,5 +1,4 @@
1name: "Gray Room" 1name: "Gray Room"
2display_name: "Gray Room"
3panels { 2panels {
4 name: "MEND" 3 name: "MEND"
5 path: "Panels/Hallway/panel_11" 4 path: "Panels/Hallway/panel_11"
diff --git a/data/maps/the_colorful/rooms/Green Room.txtpb b/data/maps/the_colorful/rooms/Green Room.txtpb index 3e9dfd5..e438176 100644 --- a/data/maps/the_colorful/rooms/Green Room.txtpb +++ b/data/maps/the_colorful/rooms/Green Room.txtpb
@@ -1,5 +1,4 @@
1name: "Green Room" 1name: "Green Room"
2display_name: "Green Room"
3panels { 2panels {
4 name: "MOTHER" 3 name: "MOTHER"
5 path: "Panels/Hallway/panel_5" 4 path: "Panels/Hallway/panel_5"
diff --git a/data/maps/the_colorful/rooms/Orange Room.txtpb b/data/maps/the_colorful/rooms/Orange Room.txtpb index b8aa5f8..6728080 100644 --- a/data/maps/the_colorful/rooms/Orange Room.txtpb +++ b/data/maps/the_colorful/rooms/Orange Room.txtpb
@@ -1,5 +1,4 @@
1name: "Orange Room" 1name: "Orange Room"
2display_name: "Orange Room"
3panels { 2panels {
4 name: "CLOUD" 3 name: "CLOUD"
5 path: "Panels/Hallway/panel_8" 4 path: "Panels/Hallway/panel_8"
diff --git a/data/maps/the_colorful/rooms/P2 Room.txtpb b/data/maps/the_colorful/rooms/P2 Room.txtpb index 85dbf20..054d4b4 100644 --- a/data/maps/the_colorful/rooms/P2 Room.txtpb +++ b/data/maps/the_colorful/rooms/P2 Room.txtpb
@@ -1,5 +1,4 @@
1name: "P2 Room" 1name: "P2 Room"
2display_name: "Cyan Room"
3letters { 2letters {
4 key: "p" 3 key: "p"
5 level2: true 4 level2: true
diff --git a/data/maps/the_colorful/rooms/Purple Room.txtpb b/data/maps/the_colorful/rooms/Purple Room.txtpb index 4175c8d..71b6ad6 100644 --- a/data/maps/the_colorful/rooms/Purple Room.txtpb +++ b/data/maps/the_colorful/rooms/Purple Room.txtpb
@@ -1,10 +1,10 @@
1name: "Purple Room" 1name: "Purple Room"
2display_name: "Purple Room"
3panels { 2panels {
4 name: "FISH" 3 name: "FISH"
5 path: "Panels/Hallway/panel_7" 4 path: "Panels/Hallway/panel_7"
6 clue: "fish" 5 clue: "fish"
7 answer: "fish" 6 answer: "fish"
8 symbols: PLANET 7 symbols: PLANET
8 proxies { answer: "fish" path: "Panels/Hallway/panel_7a" }
9 proxies { answer: "fishes" path: "Panels/Hallway/panel_7b" } 9 proxies { answer: "fishes" path: "Panels/Hallway/panel_7b" }
10} 10}
diff --git a/data/maps/the_colorful/rooms/Red Room.txtpb b/data/maps/the_colorful/rooms/Red Room.txtpb index 4d262e4..53bbd3a 100644 --- a/data/maps/the_colorful/rooms/Red Room.txtpb +++ b/data/maps/the_colorful/rooms/Red Room.txtpb
@@ -1,5 +1,4 @@
1name: "Red Room" 1name: "Red Room"
2display_name: "Red Room"
3panels { 2panels {
4 name: "SANDWICH" 3 name: "SANDWICH"
5 path: "Panels/Hallway/panel_3" 4 path: "Panels/Hallway/panel_3"
diff --git a/data/maps/the_colorful/rooms/White Room.txtpb b/data/maps/the_colorful/rooms/White Room.txtpb index 497ecff..73557ed 100644 --- a/data/maps/the_colorful/rooms/White Room.txtpb +++ b/data/maps/the_colorful/rooms/White Room.txtpb
@@ -1,5 +1,4 @@
1name: "White Room" 1name: "White Room"
2display_name: "White Room"
3panels { 2panels {
4 name: "BRIGHT" 3 name: "BRIGHT"
5 path: "Panels/Hallway/panel_1" 4 path: "Panels/Hallway/panel_1"
@@ -9,6 +8,8 @@ panels {
9} 8}
10ports { 9ports {
11 name: "GREAT" 10 name: "GREAT"
11 display_name: "Main Entrance"
12 path: "Components/Warps/worldport" 12 path: "Components/Warps/worldport"
13 orientation: "west" 13 destination { x: -3.5 y: 0 z: 19 }
14 rotation: 270
14} 15}
diff --git a/data/maps/the_colorful/rooms/Window Room.txtpb b/data/maps/the_colorful/rooms/Window Room.txtpb index 9e3f8f4..e11d88c 100644 --- a/data/maps/the_colorful/rooms/Window Room.txtpb +++ b/data/maps/the_colorful/rooms/Window Room.txtpb
@@ -1,5 +1,4 @@
1name: "Window Room" 1name: "Window Room"
2display_name: "Window Room"
3panels { 2panels {
4 name: "FADING" 3 name: "FADING"
5 path: "Panels/Hallway/panel_10" 4 path: "Panels/Hallway/panel_10"
diff --git a/data/maps/the_colorful/rooms/Yellow Room.txtpb b/data/maps/the_colorful/rooms/Yellow Room.txtpb index c65e886..40a4b14 100644 --- a/data/maps/the_colorful/rooms/Yellow Room.txtpb +++ b/data/maps/the_colorful/rooms/Yellow Room.txtpb
@@ -1,5 +1,4 @@
1name: "Yellow Room" 1name: "Yellow Room"
2display_name: "Yellow Room"
3panels { 2panels {
4 name: "CIRCLE" 3 name: "CIRCLE"
5 path: "Panels/Hallway/panel_6" 4 path: "Panels/Hallway/panel_6"
diff --git a/data/maps/the_congruent/doors.txtpb b/data/maps/the_congruent/doors.txtpb index 7c21f55..a714eba 100644 --- a/data/maps/the_congruent/doors.txtpb +++ b/data/maps/the_congruent/doors.txtpb
@@ -17,6 +17,7 @@ doors {
17 panels { room: "Main Area" name: "LABS (1)" } 17 panels { room: "Main Area" name: "LABS (1)" }
18 panels { room: "Main Area" name: "LABS (2)" } 18 panels { room: "Main Area" name: "LABS (2)" }
19 location_room: "Main Area" 19 location_room: "Main Area"
20 location_name: "Obverse Cyan Large Room"
20} 21}
21doors { 22doors {
22 name: "Flipped Yellow Door" 23 name: "Flipped Yellow Door"
@@ -33,6 +34,7 @@ doors {
33 panels { room: "Flipped Magenta Room" name: "LUST" } 34 panels { room: "Flipped Magenta Room" name: "LUST" }
34 panels { room: "Flipped Magenta Room" name: "LAND" } 35 panels { room: "Flipped Magenta Room" name: "LAND" }
35 location_room: "Flipped Magenta Room" 36 location_room: "Flipped Magenta Room"
37 location_name: "Flipped Magenta Room"
36} 38}
37doors { 39doors {
38 name: "C Keyholder Blocker" 40 name: "C Keyholder Blocker"
@@ -47,6 +49,7 @@ doors {
47 panels { room: "Flipped Yellow Room" name: "CAVE (1)" } 49 panels { room: "Flipped Yellow Room" name: "CAVE (1)" }
48 panels { room: "Flipped Yellow Room" name: "CAVE (2)" } 50 panels { room: "Flipped Yellow Room" name: "CAVE (2)" }
49 location_room: "Flipped Yellow Room" 51 location_room: "Flipped Yellow Room"
52 location_name: "Flipped Yellow Room"
50} 53}
51doors { 54doors {
52 name: "C2 Door" 55 name: "C2 Door"
@@ -59,6 +62,7 @@ doors {
59 key: "c" 62 key: "c"
60 } 63 }
61 location_room: "C Keyholder" 64 location_room: "C Keyholder"
65 location_name: "C Keyholder"
62} 66}
63doors { 67doors {
64 name: "Obverse Yellow Door" 68 name: "Obverse Yellow Door"
@@ -111,10 +115,15 @@ doors {
111 key: "g" 115 key: "g"
112 } 116 }
113 location_room: "G Keyholder" 117 location_room: "G Keyholder"
118 location_name: "G Keyholder"
114} 119}
115doors { 120doors {
116 name: "T Keyholder Blocker" 121 name: "T Keyholder Blocker"
117 type: ITEM_ONLY 122 type: EVENT
118 receivers: "Components/Doors/magenta_enterer3" 123 receivers: "Components/Doors/magenta_enterer3"
119 switches: "lavender_cubes" 124 panels {
125 map: "the_ancient"
126 room: "Inside"
127 name: "COLOR"
128 }
120} 129}
diff --git a/data/maps/the_congruent/rooms/C Keyholder.txtpb b/data/maps/the_congruent/rooms/C Keyholder.txtpb index 0af0f32..75ef920 100644 --- a/data/maps/the_congruent/rooms/C Keyholder.txtpb +++ b/data/maps/the_congruent/rooms/C Keyholder.txtpb
@@ -1,5 +1,4 @@
1name: "C Keyholder" 1name: "C Keyholder"
2display_name: "Main Area"
3keyholders { 2keyholders {
4 name: "C" 3 name: "C"
5 path: "Components/KeyHolders/keyHolder" 4 path: "Components/KeyHolders/keyHolder"
diff --git a/data/maps/the_congruent/rooms/C2 Room.txtpb b/data/maps/the_congruent/rooms/C2 Room.txtpb index 852d4e2..ff53ebd 100644 --- a/data/maps/the_congruent/rooms/C2 Room.txtpb +++ b/data/maps/the_congruent/rooms/C2 Room.txtpb
@@ -1,5 +1,4 @@
1name: "C2 Room" 1name: "C2 Room"
2display_name: "Main Area"
3letters { 2letters {
4 key: "c" 3 key: "c"
5 level2: true 4 level2: true
diff --git a/data/maps/the_congruent/rooms/Flipped Magenta Room.txtpb b/data/maps/the_congruent/rooms/Flipped Magenta Room.txtpb index 402e9e0..a51b667 100644 --- a/data/maps/the_congruent/rooms/Flipped Magenta Room.txtpb +++ b/data/maps/the_congruent/rooms/Flipped Magenta Room.txtpb
@@ -1,5 +1,4 @@
1name: "Flipped Magenta Room" 1name: "Flipped Magenta Room"
2display_name: "Flipped Magenta Room"
3panels { 2panels {
4 name: "LOOK" 3 name: "LOOK"
5 path: "Panels/Side Up 1/panel_1" 4 path: "Panels/Side Up 1/panel_1"
diff --git a/data/maps/the_congruent/rooms/Flipped Yellow Room.txtpb b/data/maps/the_congruent/rooms/Flipped Yellow Room.txtpb index 3952373..b407f0d 100644 --- a/data/maps/the_congruent/rooms/Flipped Yellow Room.txtpb +++ b/data/maps/the_congruent/rooms/Flipped Yellow Room.txtpb
@@ -1,5 +1,4 @@
1name: "Flipped Yellow Room" 1name: "Flipped Yellow Room"
2display_name: "Flipped Yellow Room"
3panels { 2panels {
4 name: "DANCER" 3 name: "DANCER"
5 path: "Panels/Back 1/panel_1" 4 path: "Panels/Back 1/panel_1"
diff --git a/data/maps/the_congruent/rooms/G Keyholder.txtpb b/data/maps/the_congruent/rooms/G Keyholder.txtpb index c52d7ba..8184703 100644 --- a/data/maps/the_congruent/rooms/G Keyholder.txtpb +++ b/data/maps/the_congruent/rooms/G Keyholder.txtpb
@@ -1,5 +1,4 @@
1name: "G Keyholder" 1name: "G Keyholder"
2display_name: "Obverse Yellow Room"
3keyholders { 2keyholders {
4 name: "G" 3 name: "G"
5 path: "Components/KeyHolders/keyHolder2" 4 path: "Components/KeyHolders/keyHolder2"
diff --git a/data/maps/the_congruent/rooms/G2 Room.txtpb b/data/maps/the_congruent/rooms/G2 Room.txtpb index 80a23cb..25490a8 100644 --- a/data/maps/the_congruent/rooms/G2 Room.txtpb +++ b/data/maps/the_congruent/rooms/G2 Room.txtpb
@@ -1,5 +1,4 @@
1name: "G2 Room" 1name: "G2 Room"
2display_name: "Main Area"
3letters { 2letters {
4 key: "g" 3 key: "g"
5 level2: true 4 level2: true
diff --git a/data/maps/the_congruent/rooms/Main Area.txtpb b/data/maps/the_congruent/rooms/Main Area.txtpb index a783eab..2b3f62e 100644 --- a/data/maps/the_congruent/rooms/Main Area.txtpb +++ b/data/maps/the_congruent/rooms/Main Area.txtpb
@@ -1,5 +1,4 @@
1name: "Main Area" 1name: "Main Area"
2display_name: "Main Area"
3panels { 2panels {
4 name: "LANE (1)" 3 name: "LANE (1)"
5 path: "Panels/Main/panel_1" 4 path: "Panels/Main/panel_1"
@@ -86,8 +85,10 @@ panels {
86} 85}
87ports { 86ports {
88 name: "DARKROOM" 87 name: "DARKROOM"
88 display_name: "Entrance"
89 path: "Components/Warps/worldport2" 89 path: "Components/Warps/worldport2"
90 orientation: "north" 90 destination { x: -19 y: 0 z: 7.5 }
91 rotation: 180
91} 92}
92paintings { 93paintings {
93 name: "P" 94 name: "P"
diff --git a/data/maps/the_congruent/rooms/Obverse Magenta Room.txtpb b/data/maps/the_congruent/rooms/Obverse Magenta Room.txtpb index b69a4d4..895c4da 100644 --- a/data/maps/the_congruent/rooms/Obverse Magenta Room.txtpb +++ b/data/maps/the_congruent/rooms/Obverse Magenta Room.txtpb
@@ -1,5 +1,4 @@
1name: "Obverse Magenta Room" 1name: "Obverse Magenta Room"
2display_name: "Obverse Magenta Room"
3# TODO: Should these two maybe not be randomizable because they hint the keyholder? 2# TODO: Should these two maybe not be randomizable because they hint the keyholder?
4paintings { 3paintings {
5 name: "TEA" 4 name: "TEA"
diff --git a/data/maps/the_congruent/rooms/Obverse Yellow Room.txtpb b/data/maps/the_congruent/rooms/Obverse Yellow Room.txtpb index 334df67..c87efdf 100644 --- a/data/maps/the_congruent/rooms/Obverse Yellow Room.txtpb +++ b/data/maps/the_congruent/rooms/Obverse Yellow Room.txtpb
@@ -1,5 +1,4 @@
1name: "Obverse Yellow Room" 1name: "Obverse Yellow Room"
2display_name: "Obverse Yellow Room"
3panels { 2panels {
4 name: "CIVIL" 3 name: "CIVIL"
5 path: "Panels/Main/panel_6" 4 path: "Panels/Main/panel_6"
diff --git a/data/maps/the_congruent/rooms/T Keyholder.txtpb b/data/maps/the_congruent/rooms/T Keyholder.txtpb index 1cfd2bd..143ea53 100644 --- a/data/maps/the_congruent/rooms/T Keyholder.txtpb +++ b/data/maps/the_congruent/rooms/T Keyholder.txtpb
@@ -1,6 +1,6 @@
1name: "T Keyholder" 1name: "T Keyholder"
2display_name: "Obverse Magenta Room"
3keyholders { 2keyholders {
4 name: "T" 3 name: "T"
5 path: "Components/KeyHolders/keyHolderT" 4 path: "Components/KeyHolders/keyHolderT"
5 key: "t"
6} 6}
diff --git a/data/maps/the_darkroom/connections.txtpb b/data/maps/the_darkroom/connections.txtpb index 4093585..43bca70 100644 --- a/data/maps/the_darkroom/connections.txtpb +++ b/data/maps/the_darkroom/connections.txtpb
@@ -1,7 +1,12 @@
1connections { 1connections {
2 from_room: "First Room"
3 to_room: "First Room Exit"
4 door { name: "Second Room Entrance" }
5}
6connections {
2 from { 7 from {
3 port { 8 port {
4 room: "First Room" 9 room: "First Room Exit"
5 name: "NEXT" 10 name: "NEXT"
6 } 11 }
7 } 12 }
@@ -14,9 +19,14 @@ connections {
14 oneway: true 19 oneway: true
15} 20}
16connections { 21connections {
22 from_room: "Second Room"
23 to_room: "Second Room Exit"
24 door { name: "Third Room Entrance" }
25}
26connections {
17 from { 27 from {
18 port { 28 port {
19 room: "Second Room" 29 room: "Second Room Exit"
20 name: "NEXT" 30 name: "NEXT"
21 } 31 }
22 } 32 }
@@ -33,3 +43,18 @@ connections {
33 to_room: "S Room" 43 to_room: "S Room"
34 door { name: "S1 Door" } 44 door { name: "S1 Door" }
35} 45}
46connections {
47 from_room: "First Room"
48 to_room: "Cyan Hallway"
49 door { name: "Colorful Entrance" }
50}
51connections {
52 from_room: "Second Room"
53 to_room: "Congruent Entrance"
54 door { name: "Congruent Entrance" }
55}
56connections {
57 from_room: "First Room"
58 to_room: "Double Sided Entrance"
59 door { name: "Double Sided Entrance" }
60}
diff --git a/data/maps/the_darkroom/doors.txtpb b/data/maps/the_darkroom/doors.txtpb index bbf6a1d..047c7d0 100644 --- a/data/maps/the_darkroom/doors.txtpb +++ b/data/maps/the_darkroom/doors.txtpb
@@ -1,11 +1,10 @@
1# TODO: gallery painting 1# TODO: gallery painting
2doors { 2doors {
3 name: "Double Letter Panel Blockers" 3 name: "Double Letter Panel Blockers"
4 type: ITEM_ONLY 4 type: EVENT
5 receivers: "Panels/Room 1/panel_3/visibilityListener" 5 receivers: "Panels/Room 1/panel_3/visibilityListener"
6 receivers: "Panels/Room 2/panel_3/visibilityListener" 6 receivers: "Panels/Room 2/panel_3/visibilityListener"
7 # TODO: honestly idk if this should even exist 7 double_letters: true
8 switches: "double_letters"
9} 8}
10doors { 9doors {
11 name: "Second Room Entrance" 10 name: "Second Room Entrance"
@@ -23,8 +22,7 @@ doors {
23} 22}
24doors { 23doors {
25 name: "S1 Door" 24 name: "S1 Door"
26 type: LOCATION_ONLY 25 type: EVENT
27 receivers: "Components/Doors/entry_3"
28 panels { room: "Third Room" name: "CULTS" } 26 panels { room: "Third Room" name: "CULTS" }
29 panels { room: "Third Room" name: "TURNS" } 27 panels { room: "Third Room" name: "TURNS" }
30 panels { room: "Third Room" name: "COINS" } 28 panels { room: "Third Room" name: "COINS" }
@@ -34,7 +32,6 @@ doors {
34 panels { room: "Third Room" name: "LOCKS" } 32 panels { room: "Third Room" name: "LOCKS" }
35 panels { room: "Third Room" name: "TOUCHES" } 33 panels { room: "Third Room" name: "TOUCHES" }
36 panels { room: "Third Room" name: "KOI" } 34 panels { room: "Third Room" name: "KOI" }
37 location_room: "Third Room"
38} 35}
39doors { 36doors {
40 name: "Colorful Entrance" 37 name: "Colorful Entrance"
@@ -46,6 +43,7 @@ doors {
46 panels { room: "First Room" name: "KOI" } 43 panels { room: "First Room" name: "KOI" }
47 panels { room: "First Room" name: "TUNA" } 44 panels { room: "First Room" name: "TUNA" }
48 location_room: "First Room" 45 location_room: "First Room"
46 location_name: "All Puzzles"
49} 47}
50doors { 48doors {
51 name: "Congruent Entrance" 49 name: "Congruent Entrance"
@@ -57,6 +55,7 @@ doors {
57 panels { room: "Second Room" name: "KOI" } 55 panels { room: "Second Room" name: "KOI" }
58 panels { room: "Second Room" name: "TUNA" } 56 panels { room: "Second Room" name: "TUNA" }
59 location_room: "Second Room" 57 location_room: "Second Room"
58 location_name: "All Puzzles"
60} 59}
61doors { 60doors {
62 name: "Double Sided Entrance" 61 name: "Double Sided Entrance"
diff --git a/data/maps/the_darkroom/rooms/Congruent Entrance.txtpb b/data/maps/the_darkroom/rooms/Congruent Entrance.txtpb new file mode 100644 index 0000000..e6600a2 --- /dev/null +++ b/data/maps/the_darkroom/rooms/Congruent Entrance.txtpb
@@ -0,0 +1,9 @@
1name: "Congruent Entrance"
2panel_display_name: "Second Room"
3ports {
4 name: "CONGRUENT"
5 display_name: "Second Room Gray Hallway"
6 path: "Components/Warps/worldport7"
7 destination { x: 51.5 y: 0 z: 29 }
8 rotation: 90
9}
diff --git a/data/maps/the_darkroom/rooms/Cyan Hallway.txtpb b/data/maps/the_darkroom/rooms/Cyan Hallway.txtpb new file mode 100644 index 0000000..bce0e5b --- /dev/null +++ b/data/maps/the_darkroom/rooms/Cyan Hallway.txtpb
@@ -0,0 +1,9 @@
1name: "Cyan Hallway"
2panel_display_name: "First Room"
3ports {
4 name: "COLORFUL"
5 display_name: "First Room Cyan Hallway"
6 path: "Components/Warps/worldport8"
7 destination { x: 20 y: 0 z: -12 }
8 rotation: 180
9}
diff --git a/data/maps/the_darkroom/rooms/Double Sided Entrance.txtpb b/data/maps/the_darkroom/rooms/Double Sided Entrance.txtpb new file mode 100644 index 0000000..79ca839 --- /dev/null +++ b/data/maps/the_darkroom/rooms/Double Sided Entrance.txtpb
@@ -0,0 +1,9 @@
1name: "Double Sided Entrance"
2panel_display_name: "First Room"
3ports {
4 name: "DOUBLESIDED"
5 display_name: "First Room White Hallway"
6 path: "Components/Warps/worldport6"
7 destination { x: 15 y: 0 z: 23 }
8 rotation: 90
9}
diff --git a/data/maps/the_darkroom/rooms/First Room Exit.txtpb b/data/maps/the_darkroom/rooms/First Room Exit.txtpb new file mode 100644 index 0000000..4a7ebc2 --- /dev/null +++ b/data/maps/the_darkroom/rooms/First Room Exit.txtpb
@@ -0,0 +1,9 @@
1name: "First Room Exit"
2panel_display_name: "First Room"
3ports {
4 name: "NEXT"
5 display_name: "First Room Exit"
6 path: "Components/Warps/worldport2"
7 destination { x: 0 y: 0 z: -15 }
8 rotation: 180
9}
diff --git a/data/maps/the_darkroom/rooms/First Room.txtpb b/data/maps/the_darkroom/rooms/First Room.txtpb index f79d055..1113435 100644 --- a/data/maps/the_darkroom/rooms/First Room.txtpb +++ b/data/maps/the_darkroom/rooms/First Room.txtpb
@@ -1,5 +1,5 @@
1name: "First Room" 1name: "First Room"
2display_name: "First Room" 2panel_display_name: "First Room"
3panels { 3panels {
4 name: "BISON" 4 name: "BISON"
5 path: "Panels/Room 1/panel_1" 5 path: "Panels/Room 1/panel_1"
@@ -33,24 +33,8 @@ panels {
33} 33}
34ports { 34ports {
35 name: "ENTRY" 35 name: "ENTRY"
36 display_name: "First Room Entrance"
36 path: "Components/Warps/worldport" 37 path: "Components/Warps/worldport"
37 orientation: "south" 38 destination { x: -10 y: 0 z: 10 }
38} 39 rotation: 0
39ports {
40 name: "NEXT"
41 path: "Components/Warps/worldport2"
42 orientation: "north"
43 required_door { name: "Second Room Entrance" }
44}
45ports {
46 name: "COLORFUL"
47 path: "Components/Warps/worldport8"
48 orientation: "north"
49 required_door { name: "Colorful Entrance" }
50}
51ports {
52 name: "DOUBLESIDED"
53 path: "Components/Warps/worldport6"
54 orientation: "east"
55 required_door { name: "Double Sided Entrance" }
56} 40}
diff --git a/data/maps/the_darkroom/rooms/S Room.txtpb b/data/maps/the_darkroom/rooms/S Room.txtpb index 0f56af1..9960b86 100644 --- a/data/maps/the_darkroom/rooms/S Room.txtpb +++ b/data/maps/the_darkroom/rooms/S Room.txtpb
@@ -1,5 +1,4 @@
1name: "S Room" 1name: "S Room"
2display_name: "Third Room"
3letters { 2letters {
4 key: "s" 3 key: "s"
5 path: "Components/Collectables/collectable" 4 path: "Components/Collectables/collectable"
diff --git a/data/maps/the_darkroom/rooms/Second Room Exit.txtpb b/data/maps/the_darkroom/rooms/Second Room Exit.txtpb new file mode 100644 index 0000000..d500691 --- /dev/null +++ b/data/maps/the_darkroom/rooms/Second Room Exit.txtpb
@@ -0,0 +1,9 @@
1name: "Second Room Exit"
2panel_display_name: "Second Room"
3ports {
4 name: "NEXT"
5 display_name: "Second Room Exit"
6 path: "Components/Warps/worldport4"
7 destination { x: 48 y: 0 z: -15 }
8 rotation: 180
9}
diff --git a/data/maps/the_darkroom/rooms/Second Room.txtpb b/data/maps/the_darkroom/rooms/Second Room.txtpb index ce780f3..2219895 100644 --- a/data/maps/the_darkroom/rooms/Second Room.txtpb +++ b/data/maps/the_darkroom/rooms/Second Room.txtpb
@@ -1,5 +1,5 @@
1name: "Second Room" 1name: "Second Room"
2display_name: "Second Room" 2panel_display_name: "Second Room"
3panels { 3panels {
4 name: "BISON" 4 name: "BISON"
5 path: "Panels/Room 2/panel_1" 5 path: "Panels/Room 2/panel_1"
@@ -38,18 +38,8 @@ panels {
38} 38}
39ports { 39ports {
40 name: "ENTRY" 40 name: "ENTRY"
41 display_name: "Second Room Entrance"
41 path: "Components/Warps/worldport3" 42 path: "Components/Warps/worldport3"
42 orientation: "south" 43 destination { x: 38 y: 0 z: 10 }
43} 44 rotation: 0
44ports {
45 name: "NEXT"
46 path: "Components/Warps/worldport4"
47 orientation: "north"
48 required_door { name: "Third Room Entrance" }
49}
50ports {
51 name: "CONGRUENT"
52 path: "Components/Warps/worldport7"
53 orientation: "east"
54 required_door { name: "Congruent Entrance" }
55} 45}
diff --git a/data/maps/the_darkroom/rooms/Third Room.txtpb b/data/maps/the_darkroom/rooms/Third Room.txtpb index 5202243..0400476 100644 --- a/data/maps/the_darkroom/rooms/Third Room.txtpb +++ b/data/maps/the_darkroom/rooms/Third Room.txtpb
@@ -1,5 +1,5 @@
1name: "Third Room" 1name: "Third Room"
2display_name: "Third Room" 2panel_display_name: "Third Room"
3panels { 3panels {
4 name: "CULTS" 4 name: "CULTS"
5 path: "Panels/Room 3/panel_1" 5 path: "Panels/Room 3/panel_1"
@@ -65,6 +65,8 @@ panels {
65} 65}
66ports { 66ports {
67 name: "ENTRY" 67 name: "ENTRY"
68 display_name: "Third Room Entrance"
68 path: "Components/Warps/worldport5" 69 path: "Components/Warps/worldport5"
69 orientation: "south" 70 destination { x: 97 y: 0 z: 10 }
71 rotation: 0
70} 72}
diff --git a/data/maps/the_digital/connections.txtpb b/data/maps/the_digital/connections.txtpb index 67cd4dc..a4b02a5 100644 --- a/data/maps/the_digital/connections.txtpb +++ b/data/maps/the_digital/connections.txtpb
@@ -24,11 +24,6 @@ connections {
24 door { name: "Gallery Entrance" } 24 door { name: "Gallery Entrance" }
25} 25}
26connections { 26connections {
27 from_room: "Gallery Maze"
28 to_room: "Main Area"
29 oneway: true
30}
31connections {
32 from_room: "Tree Area" 27 from_room: "Tree Area"
33 to_room: "Main Area" 28 to_room: "Main Area"
34 door { name: "Tree Entrance" } 29 door { name: "Tree Entrance" }
diff --git a/data/maps/the_digital/rooms/C Room.txtpb b/data/maps/the_digital/rooms/C Room.txtpb index 5fdc526..050f090 100644 --- a/data/maps/the_digital/rooms/C Room.txtpb +++ b/data/maps/the_digital/rooms/C Room.txtpb
@@ -1,5 +1,4 @@
1name: "C Room" 1name: "C Room"
2display_name: "Chamber"
3letters { 2letters {
4 key: "c" 3 key: "c"
5 path: "Components/Collectables/c" 4 path: "Components/Collectables/c"
diff --git a/data/maps/the_digital/rooms/Chamber.txtpb b/data/maps/the_digital/rooms/Chamber.txtpb index 19d4b27..d731372 100644 --- a/data/maps/the_digital/rooms/Chamber.txtpb +++ b/data/maps/the_digital/rooms/Chamber.txtpb
@@ -1,5 +1,4 @@
1name: "Chamber" 1name: "Chamber"
2display_name: "Chamber"
3panels { 2panels {
4 name: "I" 3 name: "I"
5 path: "Panels/c1" 4 path: "Panels/c1"
diff --git a/data/maps/the_digital/rooms/Gallery Maze.txtpb b/data/maps/the_digital/rooms/Gallery Maze.txtpb index 9190728..31fa98d 100644 --- a/data/maps/the_digital/rooms/Gallery Maze.txtpb +++ b/data/maps/the_digital/rooms/Gallery Maze.txtpb
@@ -1,7 +1,8 @@
1name: "Gallery Maze" 1name: "Gallery Maze"
2display_name: "Main Area"
3ports { 2ports {
4 name: "GALLERY" 3 name: "GALLERY"
4 display_name: "Gallery Maze Worldport"
5 path: "Components/Warps/worldport4" 5 path: "Components/Warps/worldport4"
6 orientation: "east" 6 destination { x: -58 y: 0 z: -76 }
7 rotation: 90
7} 8}
diff --git a/data/maps/the_digital/rooms/Main Area.txtpb b/data/maps/the_digital/rooms/Main Area.txtpb index ee5c208..26770c2 100644 --- a/data/maps/the_digital/rooms/Main Area.txtpb +++ b/data/maps/the_digital/rooms/Main Area.txtpb
@@ -1,5 +1,4 @@
1name: "Main Area" 1name: "Main Area"
2display_name: "Main Area"
3panels { 2panels {
4 name: "HIT" 3 name: "HIT"
5 path: "Panels/open_c" 4 path: "Panels/open_c"
@@ -28,16 +27,22 @@ panels {
28} 27}
29ports { 28ports {
30 name: "ENTRY1" 29 name: "ENTRY1"
30 display_name: "Maze NW Worldport"
31 path: "Components/Worldports/worldport3" 31 path: "Components/Worldports/worldport3"
32 orientation: "west" 32 destination { x: -33 y: 0 z: 28 }
33 rotation: 270
33} 34}
34ports { 35ports {
35 name: "ENTRY2" 36 name: "ENTRY2"
37 display_name: "Maze SW Worldport"
36 path: "Components/Worldports/worldport" 38 path: "Components/Worldports/worldport"
37 orientation: "south" 39 destination { x: -30 y: 0 z: 51 }
40 rotation: 0
38} 41}
39ports { 42ports {
40 name: "ENTRY3" 43 name: "ENTRY3"
44 display_name: "Maze SE Worldport"
41 path: "Components/Worldports/worldport2" 45 path: "Components/Worldports/worldport2"
42 orientation: "south" 46 destination { x: 0 y: 0 z: 51 }
47 rotation: 0
43} 48}
diff --git a/data/maps/the_digital/rooms/Tree Area.txtpb b/data/maps/the_digital/rooms/Tree Area.txtpb index fb90353..c2dc6b9 100644 --- a/data/maps/the_digital/rooms/Tree Area.txtpb +++ b/data/maps/the_digital/rooms/Tree Area.txtpb
@@ -1,5 +1,4 @@
1name: "Tree Area" 1name: "Tree Area"
2display_name: "Main Area"
3panels { 2panels {
4 name: "TREE" 3 name: "TREE"
5 path: "Panels/open_tree" 4 path: "Panels/open_tree"
@@ -9,7 +8,8 @@ panels {
9} 8}
10ports { 9ports {
11 name: "TREE" 10 name: "TREE"
11 display_name: "Brown Hallway"
12 path: "Components/Worldports/worldport4" 12 path: "Components/Worldports/worldport4"
13 orientation: "east" 13 destination { x: -16 y: 0 z: -31 }
14 # This is double sided. 14 rotation: 270
15} 15}
diff --git a/data/maps/the_digital/rooms/U Room.txtpb b/data/maps/the_digital/rooms/U Room.txtpb index 5b3e1cb..6b657d5 100644 --- a/data/maps/the_digital/rooms/U Room.txtpb +++ b/data/maps/the_digital/rooms/U Room.txtpb
@@ -1,5 +1,4 @@
1name: "U Room" 1name: "U Room"
2display_name: "Chamber"
3letters { 2letters {
4 key: "u" 3 key: "u"
5 path: "Components/Collectables/u" 4 path: "Components/Collectables/u"
diff --git a/data/maps/the_digital/rooms/Unyielding Entrance.txtpb b/data/maps/the_digital/rooms/Unyielding Entrance.txtpb index 0370928..f4bc663 100644 --- a/data/maps/the_digital/rooms/Unyielding Entrance.txtpb +++ b/data/maps/the_digital/rooms/Unyielding Entrance.txtpb
@@ -1,6 +1,8 @@
1name: "Unyielding Entrance" 1name: "Unyielding Entrance"
2ports { 2ports {
3 name: "UNYIELDING" 3 name: "UNYIELDING"
4 display_name: "Blue Door Worldport"
4 path: "Components/Warps/worldport5" 5 path: "Components/Warps/worldport5"
5 orientation: "east" 6 destination { x: 14 y: 0 z: 5 }
7 rotation: 90
6} 8}
diff --git a/data/maps/the_door/rooms/Ending.txtpb b/data/maps/the_door/rooms/Ending.txtpb index 4a4a995..37737e3 100644 --- a/data/maps/the_door/rooms/Ending.txtpb +++ b/data/maps/the_door/rooms/Ending.txtpb
@@ -1,5 +1,4 @@
1name: "Ending" 1name: "Ending"
2display_name: "Main Area"
3endings { 2endings {
4 name: "PLUM" 3 name: "PLUM"
5 path: "Components/plum_ending" 4 path: "Components/plum_ending"
diff --git a/data/maps/the_door/rooms/Main Area.txtpb b/data/maps/the_door/rooms/Main Area.txtpb index eb8944f..71e99b1 100644 --- a/data/maps/the_door/rooms/Main Area.txtpb +++ b/data/maps/the_door/rooms/Main Area.txtpb
@@ -1,5 +1,4 @@
1name: "Main Area" 1name: "Main Area"
2display_name: "Main Area"
3panels { 2panels {
4 name: "HAIR" 3 name: "HAIR"
5 path: "Panels/Room_1/panel" 4 path: "Panels/Room_1/panel"
diff --git a/data/maps/the_double_sided/rooms/Brown Area.txtpb b/data/maps/the_double_sided/rooms/Brown Area.txtpb index 079a8f2..1752257 100644 --- a/data/maps/the_double_sided/rooms/Brown Area.txtpb +++ b/data/maps/the_double_sided/rooms/Brown Area.txtpb
@@ -1,5 +1,4 @@
1name: "Brown Area" 1name: "Brown Area"
2display_name: "Maze"
3masteries { 2masteries {
4 name: "MASTERY" 3 name: "MASTERY"
5 path: "Components/Collectables/smiley" 4 path: "Components/Collectables/smiley"
diff --git a/data/maps/the_double_sided/rooms/Flipped Black Area.txtpb b/data/maps/the_double_sided/rooms/Flipped Black Area.txtpb index 38eeee6..082d889 100644 --- a/data/maps/the_double_sided/rooms/Flipped Black Area.txtpb +++ b/data/maps/the_double_sided/rooms/Flipped Black Area.txtpb
@@ -1,5 +1,4 @@
1name: "Flipped Black Area" 1name: "Flipped Black Area"
2display_name: "Maze"
3panels { 2panels {
4 name: "SEAPLANE" 3 name: "SEAPLANE"
5 path: "Panels/Maze/panel_15" 4 path: "Panels/Maze/panel_15"
diff --git a/data/maps/the_double_sided/rooms/Flipped Blue Area.txtpb b/data/maps/the_double_sided/rooms/Flipped Blue Area.txtpb index 7a285b9..f650be9 100644 --- a/data/maps/the_double_sided/rooms/Flipped Blue Area.txtpb +++ b/data/maps/the_double_sided/rooms/Flipped Blue Area.txtpb
@@ -1,5 +1,4 @@
1name: "Flipped Blue Area" 1name: "Flipped Blue Area"
2display_name: "Maze"
3panels { 2panels {
4 name: "SKY" 3 name: "SKY"
5 path: "Panels/Maze/panel_5" 4 path: "Panels/Maze/panel_5"
diff --git a/data/maps/the_double_sided/rooms/Flipped Green Area.txtpb b/data/maps/the_double_sided/rooms/Flipped Green Area.txtpb index 68ac4c7..2621f6f 100644 --- a/data/maps/the_double_sided/rooms/Flipped Green Area.txtpb +++ b/data/maps/the_double_sided/rooms/Flipped Green Area.txtpb
@@ -1,5 +1,4 @@
1name: "Flipped Green Area" 1name: "Flipped Green Area"
2display_name: "Maze"
3panels { 2panels {
4 name: "HIGH" 3 name: "HIGH"
5 path: "Panels/Maze/panel_3" 4 path: "Panels/Maze/panel_3"
diff --git a/data/maps/the_double_sided/rooms/Flipped Orange Area.txtpb b/data/maps/the_double_sided/rooms/Flipped Orange Area.txtpb index 30c62f1..58f1a76 100644 --- a/data/maps/the_double_sided/rooms/Flipped Orange Area.txtpb +++ b/data/maps/the_double_sided/rooms/Flipped Orange Area.txtpb
@@ -1,5 +1,4 @@
1name: "Flipped Orange Area" 1name: "Flipped Orange Area"
2display_name: "Maze"
3panels { 2panels {
4 name: "HEAVEN" 3 name: "HEAVEN"
5 path: "Panels/Maze/panel_6" 4 path: "Panels/Maze/panel_6"
diff --git a/data/maps/the_double_sided/rooms/Flipped Pink Area.txtpb b/data/maps/the_double_sided/rooms/Flipped Pink Area.txtpb index dce2880..976dd58 100644 --- a/data/maps/the_double_sided/rooms/Flipped Pink Area.txtpb +++ b/data/maps/the_double_sided/rooms/Flipped Pink Area.txtpb
@@ -1,2 +1 @@
1name: "Flipped Pink Area" name: "Flipped Pink Area"
2display_name: "Maze"
diff --git a/data/maps/the_double_sided/rooms/Flipped Purple Area.txtpb b/data/maps/the_double_sided/rooms/Flipped Purple Area.txtpb index 6228004..02697a8 100644 --- a/data/maps/the_double_sided/rooms/Flipped Purple Area.txtpb +++ b/data/maps/the_double_sided/rooms/Flipped Purple Area.txtpb
@@ -1,5 +1,4 @@
1name: "Flipped Purple Area" 1name: "Flipped Purple Area"
2display_name: "Maze"
3panels { 2panels {
4 name: "CEILING" 3 name: "CEILING"
5 path: "Panels/Maze/panel_8" 4 path: "Panels/Maze/panel_8"
diff --git a/data/maps/the_double_sided/rooms/Flipped Red Area.txtpb b/data/maps/the_double_sided/rooms/Flipped Red Area.txtpb index 9ca8571..9f10cb2 100644 --- a/data/maps/the_double_sided/rooms/Flipped Red Area.txtpb +++ b/data/maps/the_double_sided/rooms/Flipped Red Area.txtpb
@@ -1,5 +1,4 @@
1name: "Flipped Red Area" 1name: "Flipped Red Area"
2display_name: "Maze"
3panels { 2panels {
4 name: "RAISED" 3 name: "RAISED"
5 path: "Panels/Maze/panel_12" 4 path: "Panels/Maze/panel_12"
diff --git a/data/maps/the_double_sided/rooms/Flipped Yellow Back Area.txtpb b/data/maps/the_double_sided/rooms/Flipped Yellow Back Area.txtpb index 81cf7ad..1c3193a 100644 --- a/data/maps/the_double_sided/rooms/Flipped Yellow Back Area.txtpb +++ b/data/maps/the_double_sided/rooms/Flipped Yellow Back Area.txtpb
@@ -1,5 +1,4 @@
1name: "Flipped Yellow Back Area" 1name: "Flipped Yellow Back Area"
2display_name: "Maze"
3panels { 2panels {
4 name: "ANGELS" 3 name: "ANGELS"
5 path: "Panels/Maze/panel_13" 4 path: "Panels/Maze/panel_13"
diff --git a/data/maps/the_double_sided/rooms/Flipped Yellow Front Area.txtpb b/data/maps/the_double_sided/rooms/Flipped Yellow Front Area.txtpb index 00b26b8..00a221d 100644 --- a/data/maps/the_double_sided/rooms/Flipped Yellow Front Area.txtpb +++ b/data/maps/the_double_sided/rooms/Flipped Yellow Front Area.txtpb
@@ -1,2 +1 @@
1name: "Flipped Yellow Front Area" name: "Flipped Yellow Front Area"
2display_name: "Maze"
diff --git a/data/maps/the_double_sided/rooms/Obverse Black Area.txtpb b/data/maps/the_double_sided/rooms/Obverse Black Area.txtpb index e0f631d..ece5789 100644 --- a/data/maps/the_double_sided/rooms/Obverse Black Area.txtpb +++ b/data/maps/the_double_sided/rooms/Obverse Black Area.txtpb
@@ -1,5 +1,4 @@
1name: "Obverse Black Area" 1name: "Obverse Black Area"
2display_name: "Maze"
3panels { 2panels {
4 name: "MOUNTAIN" 3 name: "MOUNTAIN"
5 path: "Panels/Maze/panel_16" 4 path: "Panels/Maze/panel_16"
diff --git a/data/maps/the_double_sided/rooms/Obverse Blue Area.txtpb b/data/maps/the_double_sided/rooms/Obverse Blue Area.txtpb index d576195..1a21952 100644 --- a/data/maps/the_double_sided/rooms/Obverse Blue Area.txtpb +++ b/data/maps/the_double_sided/rooms/Obverse Blue Area.txtpb
@@ -1,2 +1 @@
1name: "Obverse Blue Area" name: "Obverse Blue Area"
2display_name: "Maze"
diff --git a/data/maps/the_double_sided/rooms/Obverse Green Area.txtpb b/data/maps/the_double_sided/rooms/Obverse Green Area.txtpb index 5fe37cf..d66361e 100644 --- a/data/maps/the_double_sided/rooms/Obverse Green Area.txtpb +++ b/data/maps/the_double_sided/rooms/Obverse Green Area.txtpb
@@ -1,5 +1,4 @@
1name: "Obverse Green Area" 1name: "Obverse Green Area"
2display_name: "Maze"
3panels { 2panels {
4 name: "UPSIDE" 3 name: "UPSIDE"
5 path: "Panels/Maze/panel_7" 4 path: "Panels/Maze/panel_7"
diff --git a/data/maps/the_double_sided/rooms/Obverse Orange Back Area.txtpb b/data/maps/the_double_sided/rooms/Obverse Orange Back Area.txtpb index 724e56b..43642f9 100644 --- a/data/maps/the_double_sided/rooms/Obverse Orange Back Area.txtpb +++ b/data/maps/the_double_sided/rooms/Obverse Orange Back Area.txtpb
@@ -1,5 +1,4 @@
1name: "Obverse Orange Back Area" 1name: "Obverse Orange Back Area"
2display_name: "Maze"
3panels { 2panels {
4 name: "OVER" 3 name: "OVER"
5 path: "Panels/Maze/panel_2b" 4 path: "Panels/Maze/panel_2b"
diff --git a/data/maps/the_double_sided/rooms/Obverse Orange Front Area.txtpb b/data/maps/the_double_sided/rooms/Obverse Orange Front Area.txtpb index ff393b6..28ec555 100644 --- a/data/maps/the_double_sided/rooms/Obverse Orange Front Area.txtpb +++ b/data/maps/the_double_sided/rooms/Obverse Orange Front Area.txtpb
@@ -1,5 +1,4 @@
1name: "Obverse Orange Front Area" 1name: "Obverse Orange Front Area"
2display_name: "Maze"
3panels { 2panels {
4 name: "UP" 3 name: "UP"
5 path: "Panels/Maze/panel_2" 4 path: "Panels/Maze/panel_2"
diff --git a/data/maps/the_double_sided/rooms/Obverse Orange Isolated Section.txtpb b/data/maps/the_double_sided/rooms/Obverse Orange Isolated Section.txtpb index 713d737..b563be9 100644 --- a/data/maps/the_double_sided/rooms/Obverse Orange Isolated Section.txtpb +++ b/data/maps/the_double_sided/rooms/Obverse Orange Isolated Section.txtpb
@@ -1,5 +1,4 @@
1name: "Obverse Orange Isolated Section" 1name: "Obverse Orange Isolated Section"
2display_name: "Maze"
3panels { 2panels {
4 name: "TOP" 3 name: "TOP"
5 path: "Panels/Maze/panel_4" 4 path: "Panels/Maze/panel_4"
diff --git a/data/maps/the_double_sided/rooms/Obverse Pink Area.txtpb b/data/maps/the_double_sided/rooms/Obverse Pink Area.txtpb index 936be17..2e64a37 100644 --- a/data/maps/the_double_sided/rooms/Obverse Pink Area.txtpb +++ b/data/maps/the_double_sided/rooms/Obverse Pink Area.txtpb
@@ -1,5 +1,4 @@
1name: "Obverse Pink Area" 1name: "Obverse Pink Area"
2display_name: "Maze"
3panels { 2panels {
4 name: "CLOUD" 3 name: "CLOUD"
5 path: "Panels/Maze/panel_14" 4 path: "Panels/Maze/panel_14"
diff --git a/data/maps/the_double_sided/rooms/Obverse Purple Area.txtpb b/data/maps/the_double_sided/rooms/Obverse Purple Area.txtpb index c77032e..ffe3b80 100644 --- a/data/maps/the_double_sided/rooms/Obverse Purple Area.txtpb +++ b/data/maps/the_double_sided/rooms/Obverse Purple Area.txtpb
@@ -1,5 +1,4 @@
1name: "Obverse Purple Area" 1name: "Obverse Purple Area"
2display_name: "Maze"
3panels { 2panels {
4 name: "DRAGON" 3 name: "DRAGON"
5 path: "Panels/Maze/panel_18" 4 path: "Panels/Maze/panel_18"
diff --git a/data/maps/the_double_sided/rooms/Obverse Red Area.txtpb b/data/maps/the_double_sided/rooms/Obverse Red Area.txtpb index 509a997..90ad07d 100644 --- a/data/maps/the_double_sided/rooms/Obverse Red Area.txtpb +++ b/data/maps/the_double_sided/rooms/Obverse Red Area.txtpb
@@ -1,2 +1 @@
1name: "Obverse Red Area" name: "Obverse Red Area"
2display_name: "Maze"
diff --git a/data/maps/the_double_sided/rooms/Obverse Yellow Area.txtpb b/data/maps/the_double_sided/rooms/Obverse Yellow Area.txtpb index 0e40a34..801fa28 100644 --- a/data/maps/the_double_sided/rooms/Obverse Yellow Area.txtpb +++ b/data/maps/the_double_sided/rooms/Obverse Yellow Area.txtpb
@@ -1,2 +1 @@
1name: "Obverse Yellow Area" name: "Obverse Yellow Area"
2display_name: "Maze"
diff --git a/data/maps/the_double_sided/rooms/Start.txtpb b/data/maps/the_double_sided/rooms/Start.txtpb index f47580f..54efb93 100644 --- a/data/maps/the_double_sided/rooms/Start.txtpb +++ b/data/maps/the_double_sided/rooms/Start.txtpb
@@ -1,5 +1,4 @@
1name: "Start" 1name: "Start"
2display_name: "Maze"
3panels { 2panels {
4 name: "ATTIC" 3 name: "ATTIC"
5 path: "Panels/Maze/panel_11" 4 path: "Panels/Maze/panel_11"
@@ -16,6 +15,8 @@ panels {
16} 15}
17ports { 16ports {
18 name: "DARKROOM" 17 name: "DARKROOM"
18 display_name: "Entrance"
19 path: "Components/Warps/worldport" 19 path: "Components/Warps/worldport"
20 orientation: "west" 20 destination { x: -3 y: 0 z: 8 }
21 rotation: 270
21} 22}
diff --git a/data/maps/the_entry/connections.txtpb b/data/maps/the_entry/connections.txtpb index 68aa344..7ab15ff 100644 --- a/data/maps/the_entry/connections.txtpb +++ b/data/maps/the_entry/connections.txtpb
@@ -90,8 +90,19 @@ connections {
90} 90}
91connections { 91connections {
92 from_room: "Red Blue Halls" 92 from_room: "Red Blue Halls"
93 to_room: "Least Blue Last"
94 oneway: true
95}
96connections {
97 from_room: "Red Blue Halls"
93 to_room: "Wrath Room" 98 to_room: "Wrath Room"
94 door { name: "Noon Door" } 99 door { name: "Noon Door" }
100 oneway: true
101}
102connections {
103 from_room: "Wrath Room"
104 to_room: "Least Blue Last"
105 oneway: true
95} 106}
96connections { 107connections {
97 from_room: "Red Blue Halls" 108 from_room: "Red Blue Halls"
@@ -100,6 +111,11 @@ connections {
100} 111}
101connections { 112connections {
102 from_room: "Wrath Room" 113 from_room: "Wrath Room"
114 to_room: "Rabbit Hole Lock"
115 door { name: "Noon Door" }
116}
117connections {
118 from_room: "Wrath Room"
103 to_room: "Rabbit Hole" 119 to_room: "Rabbit Hole"
104 door { name: "Rabbithole Door" } 120 door { name: "Rabbithole Door" }
105} 121}
@@ -116,7 +132,7 @@ connections {
116connections { 132connections {
117 from_room: "Blue Alcove" 133 from_room: "Blue Alcove"
118 to_room: "Least Blue Last" 134 to_room: "Least Blue Last"
119 door { name: "Red Alcove Exit" } 135 door { name: "Blue Alcove Exit" }
120} 136}
121connections { 137connections {
122 from_room: "Parthenon Return" 138 from_room: "Parthenon Return"
@@ -144,6 +160,11 @@ connections {
144 door { name: "Lime Room Entrance" } 160 door { name: "Lime Room Entrance" }
145} 161}
146connections { 162connections {
163 from_room: "Lime Room"
164 to_room: "Revitalized Entrance"
165 door { name: "Revitalized Entrance" }
166}
167connections {
147 from { painting { room: "Link Area" name: "NEAR" } } 168 from { painting { room: "Link Area" name: "NEAR" } }
148 to { painting { room: "Flipped Link Area" name: "NEAR" } } 169 to { painting { room: "Flipped Link Area" name: "NEAR" } }
149 oneway: true 170 oneway: true
@@ -162,12 +183,12 @@ connections {
162 from_room: "Starting Room" 183 from_room: "Starting Room"
163 to_room: "Digital Entrance" 184 to_room: "Digital Entrance"
164 door { name: "Second Room Left Door" } 185 door { name: "Second Room Left Door" }
165 oneway: true
166} 186}
167connections { 187connections {
168 from_room: "Digital Entrance" 188 from_room: "Digital Entrance"
169 to_room: "Starting Room" 189 to_room: "Starting Room"
170 oneway: true 190 oneway: true
191 vanilla_only: true
171} 192}
172connections { 193connections {
173 from_room: "Starting Room" 194 from_room: "Starting Room"
@@ -182,10 +203,25 @@ connections {
182connections { 203connections {
183 from_room: "Starting Room" 204 from_room: "Starting Room"
184 to_room: "Repetitive Entrance" 205 to_room: "Repetitive Entrance"
185 door { name: "Repetitive Entrance" } 206 door { name: "Starting Room West Wall North Door" }
186} 207}
187connections { 208connections {
188 from_room: "Lime Room" 209 from_room: "Lime Room"
189 to_room: "White Hallway To Daedalus" 210 to_room: "White Hallway To Daedalus"
190 door { name: "Control Center White Door" } 211 door { name: "Control Center White Door" }
191} 212}
213connections {
214 from_room: "Flipped Second Room"
215 to_room: "Four Rooms Entrance"
216 door { name: "Flipped Second Room Right Door" }
217}
218connections {
219 from_room: "Link Area"
220 to_room: "Liberated Entrance"
221 door { name: "Liberated Entrance" }
222}
223connections {
224 from_room: "Link Area"
225 to_room: "Literate Entrance"
226 door { name: "Literate Entrance" }
227}
diff --git a/data/maps/the_entry/doors.txtpb b/data/maps/the_entry/doors.txtpb index 917edc7..466f5ce 100644 --- a/data/maps/the_entry/doors.txtpb +++ b/data/maps/the_entry/doors.txtpb
@@ -62,9 +62,9 @@ doors {
62 name: "Rabbithole Door" 62 name: "Rabbithole Door"
63 type: STANDARD 63 type: STANDARD
64 receivers: "Components/Doors/second_right8" 64 receivers: "Components/Doors/second_right8"
65 panels { room: "Wrath Room" name: "RABBIT" } 65 panels { room: "Rabbit Hole Lock" name: "RABBIT" }
66 panels { room: "Wrath Room" name: "HOLE" } 66 panels { room: "Rabbit Hole Lock" name: "HOLE" }
67 location_room: "Wrath Room" 67 location_room: "Rabbit Hole Lock"
68} 68}
69# second_right is vanilla because it's like LOST door. 69# second_right is vanilla because it's like LOST door.
70doors { 70doors {
@@ -113,10 +113,9 @@ doors {
113} 113}
114doors { 114doors {
115 name: "Right Eye Entrance" 115 name: "Right Eye Entrance"
116 type: STANDARD 116 type: ITEM_ONLY
117 receivers: "Components/Doors/third_right" 117 receivers: "Components/Doors/third_right"
118 panels { room: "Trick Room" name: "INK" } 118 panels { room: "Trick Room" name: "INK" }
119 location_room: "Trick Room"
120} 119}
121doors { 120doors {
122 name: "Red Blue Area Left Door" 121 name: "Red Blue Area Left Door"
@@ -138,8 +137,10 @@ doors {
138 type: STANDARD 137 type: STANDARD
139 receivers: "Components/Doors/back_left_2" 138 receivers: "Components/Doors/back_left_2"
140 panels { room: "Colored Doors Area" name: "OPEN" answer: "orange" } 139 panels { room: "Colored Doors Area" name: "OPEN" answer: "orange" }
141 # "wall" is supposed to also work. idk man 140 panels { room: "Colored Doors Area" name: "OPEN" answer: "wall" }
141 complete_at: 1
142 location_room: "Colored Doors Area" 142 location_room: "Colored Doors Area"
143 location_name: "OPEN"
143} 144}
144doors { 145doors {
145 name: "Lime Room Entrance" 146 name: "Lime Room Entrance"
@@ -194,10 +195,10 @@ doors {
194 location_room: "Starting Room" 195 location_room: "Starting Room"
195} 196}
196doors { 197doors {
197 name: "Repetitive Entrance" 198 name: "Starting Room West Wall North Door"
198 type: ITEM_ONLY 199 type: ITEM_ONLY
199 receivers: "Components/Doors/Entry/entry_proxied_9" 200 receivers: "Components/Doors/Entry/entry_proxied_9"
200 switches: "double_letters" 201 double_letters: true
201} 202}
202doors { 203doors {
203 name: "Shop Entrance" 204 name: "Shop Entrance"
@@ -215,9 +216,9 @@ doors {
215} 216}
216doors { 217doors {
217 name: "Flipped Pyramid Area Entrance" 218 name: "Flipped Pyramid Area Entrance"
218 type: ITEM_ONLY 219 type: EVENT
219 receivers: "Components/Doors/Entry/entry_proxied_12" 220 receivers: "Components/Doors/Entry/entry_proxied_12"
220 switches: "double_letters" 221 double_letters: true
221} 222}
222doors { 223doors {
223 name: "Literate Entrance" 224 name: "Literate Entrance"
@@ -252,7 +253,7 @@ doors {
252 type: ITEM_ONLY 253 type: ITEM_ONLY
253 receivers: "Components/Doors/Entry/d_3" 254 receivers: "Components/Doors/Entry/d_3"
254 receivers: "Components/Doors/Entry/d_4" 255 receivers: "Components/Doors/Entry/d_4"
255 switches: "double_letters" 256 double_letters: true
256} 257}
257doors { 258doors {
258 name: "D Room Panels" 259 name: "D Room Panels"
@@ -287,7 +288,8 @@ doors {
287doors { 288doors {
288 name: "Least Blue Last Panels" 289 name: "Least Blue Last Panels"
289 type: EVENT 290 type: EVENT
290 move_paintings { room: "Starting Room" name: "OWL" } 291 #move_paintings { room: "Starting Room" name: "OWL" }
292 #receivers: "Components/Paintings/owl/visibilityListener"
291 panels { room: "Least Blue Last" name: "CAPABLE (1)" } 293 panels { room: "Least Blue Last" name: "CAPABLE (1)" }
292 panels { room: "Least Blue Last" name: "CAPABLE (2)" } 294 panels { room: "Least Blue Last" name: "CAPABLE (2)" }
293 panels { room: "Least Blue Last" name: "LUSTRE" } 295 panels { room: "Least Blue Last" name: "LUSTRE" }
@@ -301,7 +303,8 @@ doors {
301doors { 303doors {
302 name: "Red Room Painting" 304 name: "Red Room Painting"
303 type: STANDARD 305 type: STANDARD
304 move_paintings { room: "Right Eye" name: "PSYCHIC" } 306 #move_paintings { room: "Right Eye" name: "PSYCHIC" }
307 receivers: "Components/Paintings/psychic/teleportListener"
305 panels { room: "Right Eye" name: "FAINT" } 308 panels { room: "Right Eye" name: "FAINT" }
306 location_room: "Right Eye" 309 location_room: "Right Eye"
307} 310}
diff --git a/data/maps/the_entry/metadata.txtpb b/data/maps/the_entry/metadata.txtpb index 679454a..0eeb29a 100644 --- a/data/maps/the_entry/metadata.txtpb +++ b/data/maps/the_entry/metadata.txtpb
@@ -9,3 +9,5 @@ excluded_nodes: "Panels/Back Left/backleft_3_proxied_1"
9excluded_nodes: "Panels/Back Left/backleft_3_proxied_2" 9excluded_nodes: "Panels/Back Left/backleft_3_proxied_2"
10excluded_nodes: "Panels/Back Left/backleft_4_proxied_1" 10excluded_nodes: "Panels/Back Left/backleft_4_proxied_1"
11excluded_nodes: "Panels/Back Left/backleft_4_proxied_2" 11excluded_nodes: "Panels/Back Left/backleft_4_proxied_2"
12# This is a proxy related to the first panel and it doesn't seem useful.
13excluded_nodes: "Panels/Entry/entry_proxied_fake"
diff --git a/data/maps/the_entry/rooms/Blue Alcove.txtpb b/data/maps/the_entry/rooms/Blue Alcove.txtpb index 4c2c48c..3df58b9 100644 --- a/data/maps/the_entry/rooms/Blue Alcove.txtpb +++ b/data/maps/the_entry/rooms/Blue Alcove.txtpb
@@ -1,5 +1,5 @@
1name: "Blue Alcove" 1name: "Blue Alcove"
2display_name: "Red Blue Area" 2panel_display_name: "Red Blue Area"
3panels { 3panels {
4 name: "BLUE" 4 name: "BLUE"
5 path: "Panels/Back Right/br_11" 5 path: "Panels/Back Right/br_11"
diff --git a/data/maps/the_entry/rooms/Colored Doors Area.txtpb b/data/maps/the_entry/rooms/Colored Doors Area.txtpb index 29e89b5..4767387 100644 --- a/data/maps/the_entry/rooms/Colored Doors Area.txtpb +++ b/data/maps/the_entry/rooms/Colored Doors Area.txtpb
@@ -1,5 +1,5 @@
1name: "Colored Doors Area" 1name: "Colored Doors Area"
2display_name: "Colored Doors Area" 2panel_display_name: "Colored Doors Area"
3panels { 3panels {
4 name: "OPEN" 4 name: "OPEN"
5 path: "Panels/Back Left/backleft_proxying_1" 5 path: "Panels/Back Left/backleft_proxying_1"
diff --git a/data/maps/the_entry/rooms/Composite Room Entrance.txtpb b/data/maps/the_entry/rooms/Composite Room Entrance.txtpb index 4c18625..ca9e7f4 100644 --- a/data/maps/the_entry/rooms/Composite Room Entrance.txtpb +++ b/data/maps/the_entry/rooms/Composite Room Entrance.txtpb
@@ -1,7 +1,9 @@
1name: "Composite Room Entrance" 1name: "Composite Room Entrance"
2display_name: "Starting Room" 2panel_display_name: "Starting Room"
3ports { 3ports {
4 name: "COMPOSITE" 4 name: "COMPOSITE"
5 display_name: "Starting Room NE Worldport"
5 path: "Components/Warps/worldport12" 6 path: "Components/Warps/worldport12"
6 orientation: "east" 7 destination { x: 16 y: 0 z: -20 }
8 rotation: 90
7} 9}
diff --git a/data/maps/the_entry/rooms/Ctrl Tutorial.txtpb b/data/maps/the_entry/rooms/Ctrl Tutorial.txtpb index 0819953..fabcd60 100644 --- a/data/maps/the_entry/rooms/Ctrl Tutorial.txtpb +++ b/data/maps/the_entry/rooms/Ctrl Tutorial.txtpb
@@ -1,5 +1,5 @@
1name: "Ctrl Tutorial" 1name: "Ctrl Tutorial"
2display_name: "Colored Doors Area" 2panel_display_name: "Colored Doors Area"
3panels { 3panels {
4 name: "RIGHT" 4 name: "RIGHT"
5 path: "Panels/Back Left/backleft_proxying_2" 5 path: "Panels/Back Left/backleft_proxying_2"
diff --git a/data/maps/the_entry/rooms/D Room Final.txtpb b/data/maps/the_entry/rooms/D Room Final.txtpb index 960cb1c..bb8ee87 100644 --- a/data/maps/the_entry/rooms/D Room Final.txtpb +++ b/data/maps/the_entry/rooms/D Room Final.txtpb
@@ -1,5 +1,5 @@
1name: "D Room Final" 1name: "D Room Final"
2display_name: "D Room" 2panel_display_name: "D Room"
3letters { 3letters {
4 key: "d" 4 key: "d"
5 path: "Components/Collectables/d" 5 path: "Components/Collectables/d"
diff --git a/data/maps/the_entry/rooms/D Room.txtpb b/data/maps/the_entry/rooms/D Room.txtpb index 27a975b..fdf6846 100644 --- a/data/maps/the_entry/rooms/D Room.txtpb +++ b/data/maps/the_entry/rooms/D Room.txtpb
@@ -1,5 +1,5 @@
1name: "D Room" 1name: "D Room"
2display_name: "D Room" 2panel_display_name: "D Room"
3panels { 3panels {
4 name: "BASEBALL" 4 name: "BASEBALL"
5 path: "Panels/D/d_2" 5 path: "Panels/D/d_2"
diff --git a/data/maps/the_entry/rooms/Daedalus Entrance.txtpb b/data/maps/the_entry/rooms/Daedalus Entrance.txtpb index 60b41cb..76dc278 100644 --- a/data/maps/the_entry/rooms/Daedalus Entrance.txtpb +++ b/data/maps/the_entry/rooms/Daedalus Entrance.txtpb
@@ -1,7 +1,9 @@
1name: "Daedalus Entrance" 1name: "Daedalus Entrance"
2display_name: "Starting Room" 2panel_display_name: "Starting Room"
3ports { 3ports {
4 name: "DAEDALUS" 4 name: "DAEDALUS"
5 display_name: "Starting Room North Wall West Worldport"
5 path: "Components/Warps/worldport6" 6 path: "Components/Warps/worldport6"
6 orientation: "west" 7 destination { x: -16 y: 0 z: -20 }
8 rotation: 270
7} 9}
diff --git a/data/maps/the_entry/rooms/Digital Entrance.txtpb b/data/maps/the_entry/rooms/Digital Entrance.txtpb index 5713a8d..b7689bd 100644 --- a/data/maps/the_entry/rooms/Digital Entrance.txtpb +++ b/data/maps/the_entry/rooms/Digital Entrance.txtpb
@@ -1,7 +1,9 @@
1name: "Digital Entrance" 1name: "Digital Entrance"
2display_name: "Starting Room" 2panel_display_name: "Starting Room"
3ports { 3ports {
4 name: "DIGITAL" 4 name: "DIGITAL"
5 display_name: "Second Room Left Worldport"
5 path: "Components/Warps/worldport" 6 path: "Components/Warps/worldport"
6 orientation: "west" 7 destination { x: -78 y: 0 z: -24 }
8 rotation: 270
7} 9}
diff --git a/data/maps/the_entry/rooms/Entry Exit.txtpb b/data/maps/the_entry/rooms/Entry Exit.txtpb index 6b4fadd..e270bf8 100644 --- a/data/maps/the_entry/rooms/Entry Exit.txtpb +++ b/data/maps/the_entry/rooms/Entry Exit.txtpb
@@ -1,7 +1,9 @@
1name: "Entry Exit" 1name: "Entry Exit"
2display_name: "Starting Room" 2panel_display_name: "Starting Room"
3ports { 3ports {
4 name: "GREAT" 4 name: "GREAT"
5 display_name: "Second Room Right Worldport"
5 path: "Components/Warps/worldport2" 6 path: "Components/Warps/worldport2"
6 orientation: "north" 7 destination { x: 18 y: 0 z: -36 }
8 rotation: 180
7} 9}
diff --git a/data/maps/the_entry/rooms/Eye Room.txtpb b/data/maps/the_entry/rooms/Eye Room.txtpb index 8c6290b..00f2534 100644 --- a/data/maps/the_entry/rooms/Eye Room.txtpb +++ b/data/maps/the_entry/rooms/Eye Room.txtpb
@@ -1,5 +1,5 @@
1name: "Eye Room" 1name: "Eye Room"
2display_name: "Eye Room" 2panel_display_name: "Eye Room"
3panels { 3panels {
4 name: "I" 4 name: "I"
5 path: "Panels/Entry/eyes_1" 5 path: "Panels/Entry/eyes_1"
@@ -31,6 +31,8 @@ paintings {
31} 31}
32ports { 32ports {
33 name: "LIONIZED" 33 name: "LIONIZED"
34 display_name: "Eye Room Worldport"
34 path: "Components/Warps/worldport10" 35 path: "Components/Warps/worldport10"
35 orientation: "north" 36 destination { x: 18 y: 0 z: -88.5 }
37 rotation: 180
36} 38}
diff --git a/data/maps/the_entry/rooms/Flipped Link Area.txtpb b/data/maps/the_entry/rooms/Flipped Link Area.txtpb index 5251023..950e9b1 100644 --- a/data/maps/the_entry/rooms/Flipped Link Area.txtpb +++ b/data/maps/the_entry/rooms/Flipped Link Area.txtpb
@@ -1,18 +1,19 @@
1name: "Flipped Link Area" 1name: "Flipped Link Area"
2display_name: "Pyramid Area" 2panel_display_name: "Pyramid Area"
3panels { 3panels {
4 name: "WANDER" 4 name: "WANDER"
5 path: "Panels/Pilgrimage/cream_4" 5 path: "Panels/Pilgrimage/cream_4"
6 clue: "wander" 6 clue: "wander"
7 answer: "roam" 7 answer: "roam"
8 symbols: SUN 8 symbols: SUN
9 display_name: "WANDER (Flipped)"
9} 10}
10paintings { 11paintings {
11 name: "NEAR" 12 name: "NEAR"
12 path: "Components/Paintings/aches2" 13 path: "Components/Paintings/aches2"
13 orientation: "north" 14 orientation: "north"
14 gravity: Y_PLUS 15 gravity: Y_PLUS
15 display_name: "Flipper Near Painting" 16 display_name: "Flipped Near Painting"
16} 17}
17paintings { 18paintings {
18 name: "FAR" 19 name: "FAR"
diff --git a/data/maps/the_entry/rooms/Flipped Pyramid Area.txtpb b/data/maps/the_entry/rooms/Flipped Pyramid Area.txtpb index e2dd992..c0be783 100644 --- a/data/maps/the_entry/rooms/Flipped Pyramid Area.txtpb +++ b/data/maps/the_entry/rooms/Flipped Pyramid Area.txtpb
@@ -1,5 +1,5 @@
1name: "Flipped Pyramid Area" 1name: "Flipped Pyramid Area"
2display_name: "Pyramid Area" 2panel_display_name: "Pyramid Area"
3panels { 3panels {
4 name: "TURN (1)" 4 name: "TURN (1)"
5 path: "Panels/Entry/l_opener_3" 5 path: "Panels/Entry/l_opener_3"
diff --git a/data/maps/the_entry/rooms/Flipped Right Eye.txtpb b/data/maps/the_entry/rooms/Flipped Right Eye.txtpb index 429d63e..14f3f5a 100644 --- a/data/maps/the_entry/rooms/Flipped Right Eye.txtpb +++ b/data/maps/the_entry/rooms/Flipped Right Eye.txtpb
@@ -1,5 +1,5 @@
1name: "Flipped Right Eye" 1name: "Flipped Right Eye"
2display_name: "Flip Area" 2panel_display_name: "Flip Area"
3panels { 3panels {
4 name: "WHERE" 4 name: "WHERE"
5 path: "Panels/Pilgrimage/cream_5" 5 path: "Panels/Pilgrimage/cream_5"
diff --git a/data/maps/the_entry/rooms/Flipped Second Room.txtpb b/data/maps/the_entry/rooms/Flipped Second Room.txtpb index d4ee780..0d518bb 100644 --- a/data/maps/the_entry/rooms/Flipped Second Room.txtpb +++ b/data/maps/the_entry/rooms/Flipped Second Room.txtpb
@@ -1,5 +1,5 @@
1name: "Flipped Second Room" 1name: "Flipped Second Room"
2display_name: "Flip Area" 2panel_display_name: "Flip Area"
3panels { 3panels {
4 name: "CLUE" 4 name: "CLUE"
5 path: "Panels/Entry/second_right_top" 5 path: "Panels/Entry/second_right_top"
@@ -21,10 +21,3 @@ paintings {
21 gravity: Y_PLUS 21 gravity: Y_PLUS
22 display_name: "Eye Painting" 22 display_name: "Eye Painting"
23} 23}
24ports {
25 name: "FOUR"
26 path: "Components/Warps/worldport9"
27 orientation: "south"
28 gravity: Y_PLUS
29 required_door { name: "Flipped Second Room Right Door" }
30} \ No newline at end of file
diff --git a/data/maps/the_entry/rooms/Four Rooms Entrance.txtpb b/data/maps/the_entry/rooms/Four Rooms Entrance.txtpb new file mode 100644 index 0000000..4d94d5a --- /dev/null +++ b/data/maps/the_entry/rooms/Four Rooms Entrance.txtpb
@@ -0,0 +1,9 @@
1name: "Four Rooms Entrance"
2ports {
3 name: "FOUR"
4 display_name: "Flipped Second Room Right Worldport"
5 path: "Components/Warps/worldport9"
6 destination { x: -41 y: 6 z: -17.5 }
7 rotation: 0
8 gravity: Y_PLUS
9}
diff --git a/data/maps/the_entry/rooms/Gallery Return.txtpb b/data/maps/the_entry/rooms/Gallery Return.txtpb index 1273928..7235d80 100644 --- a/data/maps/the_entry/rooms/Gallery Return.txtpb +++ b/data/maps/the_entry/rooms/Gallery Return.txtpb
@@ -1,5 +1,5 @@
1name: "Gallery Return" 1name: "Gallery Return"
2display_name: "Starting Room" 2panel_display_name: "Gallery Return"
3panels { 3panels {
4 name: "RETURN" 4 name: "RETURN"
5 path: "Panels/Entry/gallery_return" 5 path: "Panels/Entry/gallery_return"
@@ -9,6 +9,8 @@ panels {
9} 9}
10ports { 10ports {
11 name: "GALLERY" 11 name: "GALLERY"
12 display_name: "Gallery Return"
12 path: "Components/Warps/worldport4" 13 path: "Components/Warps/worldport4"
13 orientation: "north" 14 destination { x: -38 y: 0 z: 8.5 }
15 rotation: 180
14} \ No newline at end of file 16} \ No newline at end of file
diff --git a/data/maps/the_entry/rooms/Least Blue Last.txtpb b/data/maps/the_entry/rooms/Least Blue Last.txtpb index 0f198b7..dde203a 100644 --- a/data/maps/the_entry/rooms/Least Blue Last.txtpb +++ b/data/maps/the_entry/rooms/Least Blue Last.txtpb
@@ -1,5 +1,5 @@
1name: "Least Blue Last" 1name: "Least Blue Last"
2display_name: "Red Blue Area" 2panel_display_name: "Red Blue Area"
3panels { 3panels {
4 name: "CAPABLE (1)" 4 name: "CAPABLE (1)"
5 path: "Panels/LBL/lbl_1" 5 path: "Panels/LBL/lbl_1"
@@ -72,8 +72,10 @@ panels {
72} 72}
73ports { 73ports {
74 name: "DARKROOM" 74 name: "DARKROOM"
75 display_name: "Near L1 Worldport"
75 path: "Components/Warps/worldport5" 76 path: "Components/Warps/worldport5"
76 orientation: "south" 77 destination { x: 43 y: 0 z: -10 }
78 rotation: 0
77} 79}
78paintings { 80paintings {
79 name: "PAINS" 81 name: "PAINS"
diff --git a/data/maps/the_entry/rooms/Liberated Entrance.txtpb b/data/maps/the_entry/rooms/Liberated Entrance.txtpb new file mode 100644 index 0000000..56cc597 --- /dev/null +++ b/data/maps/the_entry/rooms/Liberated Entrance.txtpb
@@ -0,0 +1,8 @@
1name: "Liberated Entrance"
2ports {
3 name: "BLUE"
4 display_name: "Pyramid Area Blue Worldport"
5 path: "worldport8"
6 destination { x: 18 y: 0 z: 55 }
7 rotation: 270
8}
diff --git a/data/maps/the_entry/rooms/Lime Room.txtpb b/data/maps/the_entry/rooms/Lime Room.txtpb index 6054dd7..603fbdc 100644 --- a/data/maps/the_entry/rooms/Lime Room.txtpb +++ b/data/maps/the_entry/rooms/Lime Room.txtpb
@@ -1,5 +1,5 @@
1name: "Lime Room" 1name: "Lime Room"
2display_name: "Colored Doors Area" 2panel_display_name: "Colored Doors Area"
3panels { 3panels {
4 name: "HIDE" 4 name: "HIDE"
5 path: "Panels/Back Left/backleft_proxying_3" 5 path: "Panels/Back Left/backleft_proxying_3"
@@ -19,9 +19,3 @@ panels {
19 answer: "white" 19 answer: "white"
20 symbols: EXAMPLE 20 symbols: EXAMPLE
21} 21}
22ports {
23 name: "REVITALIZED"
24 path: "worldport7"
25 orientation: "north"
26 required_door { name: "Revitalized Entrance" }
27} \ No newline at end of file
diff --git a/data/maps/the_entry/rooms/Link Area.txtpb b/data/maps/the_entry/rooms/Link Area.txtpb index 2866abd..5b68279 100644 --- a/data/maps/the_entry/rooms/Link Area.txtpb +++ b/data/maps/the_entry/rooms/Link Area.txtpb
@@ -1,11 +1,12 @@
1name: "Link Area" 1name: "Link Area"
2display_name: "Pyramid Area" 2panel_display_name: "Pyramid Area"
3panels { 3panels {
4 name: "WANDER" 4 name: "WANDER"
5 path: "Panels/Pilgrimage/cream_3" 5 path: "Panels/Pilgrimage/cream_3"
6 clue: "wander" 6 clue: "wander"
7 answer: "amble" 7 answer: "amble"
8 symbols: SUN 8 symbols: SUN
9 display_name: "WANDER (Obverse)"
9} 10}
10paintings { 11paintings {
11 name: "NEAR" 12 name: "NEAR"
@@ -25,15 +26,3 @@ paintings {
25 orientation: "south" 26 orientation: "south"
26 display_name: "Center Painting" 27 display_name: "Center Painting"
27} 28}
28ports {
29 name: "BLUE"
30 path: "worldport8"
31 orientation: "west"
32 required_door { name: "Liberated Entrance" }
33}
34ports {
35 name: "BROWN"
36 path: "worldport9"
37 orientation: "east"
38 required_door { name: "Literate Entrance" }
39} \ No newline at end of file
diff --git a/data/maps/the_entry/rooms/Literate Entrance.txtpb b/data/maps/the_entry/rooms/Literate Entrance.txtpb new file mode 100644 index 0000000..b86ac80 --- /dev/null +++ b/data/maps/the_entry/rooms/Literate Entrance.txtpb
@@ -0,0 +1,8 @@
1name: "Literate Entrance"
2ports {
3 name: "BROWN"
4 display_name: "Pyramid Area Brown Worldport"
5 path: "worldport9"
6 destination { x: 39 y: 0 z: 55 }
7 rotation: 90
8}
diff --git a/data/maps/the_entry/rooms/Parthenon Return.txtpb b/data/maps/the_entry/rooms/Parthenon Return.txtpb index 5a7f6b8..bb12964 100644 --- a/data/maps/the_entry/rooms/Parthenon Return.txtpb +++ b/data/maps/the_entry/rooms/Parthenon Return.txtpb
@@ -1,5 +1,5 @@
1name: "Parthenon Return" 1name: "Parthenon Return"
2display_name: "Starting Room" 2panel_display_name: "Parthenon Return"
3panels { 3panels {
4 name: "RETURN" 4 name: "RETURN"
5 path: "Panels/Back Left/backleft_return" 5 path: "Panels/Back Left/backleft_return"
@@ -9,6 +9,8 @@ panels {
9} 9}
10ports { 10ports {
11 name: "PARTHENON" 11 name: "PARTHENON"
12 display_name: "Parthenon Return"
12 path: "Components/Warps/worldport8" 13 path: "Components/Warps/worldport8"
13 orientation: "north" 14 destination { x: -5.5 y: 0 z: 18 }
14} \ No newline at end of file 15 rotation: 180
16}
diff --git a/data/maps/the_entry/rooms/Rabbit Hole Lock.txtpb b/data/maps/the_entry/rooms/Rabbit Hole Lock.txtpb new file mode 100644 index 0000000..78b4f3b --- /dev/null +++ b/data/maps/the_entry/rooms/Rabbit Hole Lock.txtpb
@@ -0,0 +1,18 @@
1name: "Rabbit Hole Lock"
2panel_display_name: "Red Blue Area"
3panels {
4 name: "RABBIT"
5 path: "Panels/Back Right/br_4"
6 clue: "rabbit"
7 answer: "hair"
8 symbols: SUN
9 symbols: ZERO
10}
11panels {
12 name: "HOLE"
13 path: "Panels/Back Right/br_5"
14 clue: "hole"
15 answer: "part"
16 symbols: ZERO
17 symbols: BOXES
18}
diff --git a/data/maps/the_entry/rooms/Rabbit Hole.txtpb b/data/maps/the_entry/rooms/Rabbit Hole.txtpb index 9b18bc8..4ffeb84 100644 --- a/data/maps/the_entry/rooms/Rabbit Hole.txtpb +++ b/data/maps/the_entry/rooms/Rabbit Hole.txtpb
@@ -1,5 +1,5 @@
1name: "Rabbit Hole" 1name: "Rabbit Hole"
2display_name: "Red Blue Area" 2panel_display_name: "Red Blue Area"
3panels { 3panels {
4 name: "PUZZLE" 4 name: "PUZZLE"
5 path: "Panels/Back Right/br_6" 5 path: "Panels/Back Right/br_6"
@@ -8,6 +8,8 @@ panels {
8} 8}
9ports { 9ports {
10 name: "HOLE" 10 name: "HOLE"
11 display_name: "Rabbit Hole"
11 path: "worldport4" 12 path: "worldport4"
12 orientation: "down" 13 destination { x: 74 y: 0 z: -43 }
13} \ No newline at end of file 14 rotation: 0
15}
diff --git a/data/maps/the_entry/rooms/Red Alcove.txtpb b/data/maps/the_entry/rooms/Red Alcove.txtpb index 5c4085e..503b4a9 100644 --- a/data/maps/the_entry/rooms/Red Alcove.txtpb +++ b/data/maps/the_entry/rooms/Red Alcove.txtpb
@@ -1,5 +1,5 @@
1name: "Red Alcove" 1name: "Red Alcove"
2display_name: "Red Blue Area" 2panel_display_name: "Red Blue Area"
3panels { 3panels {
4 name: "BROW" 4 name: "BROW"
5 path: "Panels/Back Right/br_10" 5 path: "Panels/Back Right/br_10"
diff --git a/data/maps/the_entry/rooms/Red Blue Halls.txtpb b/data/maps/the_entry/rooms/Red Blue Halls.txtpb index 7d07f9e..789ca42 100644 --- a/data/maps/the_entry/rooms/Red Blue Halls.txtpb +++ b/data/maps/the_entry/rooms/Red Blue Halls.txtpb
@@ -1,5 +1,5 @@
1name: "Red Blue Halls" 1name: "Red Blue Halls"
2display_name: "Red Blue Area" 2panel_display_name: "Red Blue Area"
3panels { 3panels {
4 name: "CENTER" 4 name: "CENTER"
5 path: "Panels/Back Right/br_1" 5 path: "Panels/Back Right/br_1"
diff --git a/data/maps/the_entry/rooms/Repetitive Entrance.txtpb b/data/maps/the_entry/rooms/Repetitive Entrance.txtpb index 982e3f3..25c3307 100644 --- a/data/maps/the_entry/rooms/Repetitive Entrance.txtpb +++ b/data/maps/the_entry/rooms/Repetitive Entrance.txtpb
@@ -1,7 +1,12 @@
1name: "Repetitive Entrance" 1name: "Repetitive Entrance"
2display_name: "Starting Room" 2panel_display_name: "Starting Room"
3ports { 3ports {
4 name: "REPETITIVE" 4 name: "REPETITIVE"
5 display_name: "Starting Room West Wall North Worldport"
5 path: "Components/Warps/worldport7" 6 path: "Components/Warps/worldport7"
6 orientation: "north" 7 destination { x: -20 y: 0 z: -16 }
8 rotation: 180
9 # TODO: this is part of what makes the keyholder dependent connection from CC
10 # safe in vanilla doors
11 no_shuffle: true
7} 12}
diff --git a/data/maps/the_entry/rooms/Revitalized Entrance.txtpb b/data/maps/the_entry/rooms/Revitalized Entrance.txtpb new file mode 100644 index 0000000..fb5e7e0 --- /dev/null +++ b/data/maps/the_entry/rooms/Revitalized Entrance.txtpb
@@ -0,0 +1,9 @@
1name: "Revitalized Entrance"
2panel_display_name: "Colored Doors Area"
3ports {
4 name: "REVITALIZED"
5 display_name: "Plum Hallway"
6 path: "worldport7"
7 destination { x: -58 y: 0 z: 31.5 }
8 rotation: 180
9}
diff --git a/data/maps/the_entry/rooms/Right Eye.txtpb b/data/maps/the_entry/rooms/Right Eye.txtpb index 1c7bf68..8f6c431 100644 --- a/data/maps/the_entry/rooms/Right Eye.txtpb +++ b/data/maps/the_entry/rooms/Right Eye.txtpb
@@ -1,5 +1,5 @@
1name: "Right Eye" 1name: "Right Eye"
2display_name: "Right Eye Area" 2panel_display_name: "Right Eye Area"
3panels { 3panels {
4 name: "EYE" 4 name: "EYE"
5 path: "Panels/Entry/front_2" 5 path: "Panels/Entry/front_2"
diff --git a/data/maps/the_entry/rooms/Shop Entrance.txtpb b/data/maps/the_entry/rooms/Shop Entrance.txtpb index b52cde7..4a99efa 100644 --- a/data/maps/the_entry/rooms/Shop Entrance.txtpb +++ b/data/maps/the_entry/rooms/Shop Entrance.txtpb
@@ -1,5 +1,5 @@
1name: "Shop Entrance" 1name: "Shop Entrance"
2display_name: "Starting Room" 2panel_display_name: "Shop Entrance"
3panels { 3panels {
4 name: "TURN" 4 name: "TURN"
5 path: "Panels/Entry/l_opener_2" 5 path: "Panels/Entry/l_opener_2"
@@ -9,6 +9,8 @@ panels {
9} 9}
10ports { 10ports {
11 name: "SHOP" 11 name: "SHOP"
12 display_name: "Shop Entrance"
12 path: "Components/Warps/worldport13" 13 path: "Components/Warps/worldport13"
13 orientation: "east" 14 destination { x: 18 y: 0 z: 49 }
15 rotation: 90
14} \ No newline at end of file 16} \ No newline at end of file
diff --git a/data/maps/the_entry/rooms/Starting Room.txtpb b/data/maps/the_entry/rooms/Starting Room.txtpb index aeb66ab..8e8373b 100644 --- a/data/maps/the_entry/rooms/Starting Room.txtpb +++ b/data/maps/the_entry/rooms/Starting Room.txtpb
@@ -1,10 +1,11 @@
1name: "Starting Room" 1name: "Starting Room"
2display_name: "Starting Room" 2panel_display_name: "Starting Room"
3panels { 3panels {
4 name: "HI" 4 name: "HI"
5 path: "Panels/Entry/entry_proxying_1" 5 path: "Panels/Entry/entry_proxying_1"
6 clue: "hi" 6 clue: "hi"
7 answer: "hi" 7 answer: "hi"
8 proxies { answer: "hi" path: "Panels/Entry/entry_proxied_1" }
8 proxies { answer: "bye" path: "Panels/Entry/entry_proxied_2" } 9 proxies { answer: "bye" path: "Panels/Entry/entry_proxied_2" }
9 proxies { answer: "hidden" path: "Panels/Entry/entry_proxied_5" } 10 proxies { answer: "hidden" path: "Panels/Entry/entry_proxied_5" }
10 proxies { answer: "high" path: "Panels/Entry/entry_proxied_3" } 11 proxies { answer: "high" path: "Panels/Entry/entry_proxied_3" }
@@ -23,7 +24,9 @@ panels {
23 path: "Panels/Entry/front_1" 24 path: "Panels/Entry/front_1"
24 clue: "eye" 25 clue: "eye"
25 answer: "i" 26 answer: "i"
26 symbols: ZERO 27 #symbols: ZERO
28 # This panel blocks getting N1 and T1. We will mod it to be I/I with no symbol
29 # when symbol shuffle is on.
27} 30}
28panels { 31panels {
29 name: "HINT" 32 name: "HINT"
diff --git a/data/maps/the_entry/rooms/Trick Room.txtpb b/data/maps/the_entry/rooms/Trick Room.txtpb index ff9be38..d20502e 100644 --- a/data/maps/the_entry/rooms/Trick Room.txtpb +++ b/data/maps/the_entry/rooms/Trick Room.txtpb
@@ -1,5 +1,5 @@
1name: "Trick Room" 1name: "Trick Room"
2display_name: "Starting Room" 2panel_display_name: "Starting Room"
3panels { 3panels {
4 name: "INK" 4 name: "INK"
5 path: "Panels/Entry/l_opener_1" 5 path: "Panels/Entry/l_opener_1"
diff --git a/data/maps/the_entry/rooms/White Hallway To Daedalus.txtpb b/data/maps/the_entry/rooms/White Hallway To Daedalus.txtpb index bf1398d..de0cec2 100644 --- a/data/maps/the_entry/rooms/White Hallway To Daedalus.txtpb +++ b/data/maps/the_entry/rooms/White Hallway To Daedalus.txtpb
@@ -1,7 +1,9 @@
1name: "White Hallway To Daedalus" 1name: "White Hallway To Daedalus"
2display_name: "Colored Doors Area" 2panel_display_name: "Colored Doors Area"
3ports { 3ports {
4 name: "DAEDALUS" 4 name: "DAEDALUS"
5 display_name: "White Control Center Hallway"
5 path: "Components/Warps/worldport11" 6 path: "Components/Warps/worldport11"
6 orientation: "west" 7 destination { x: -45 y: 0 z: 24 }
8 rotation: 270
7} 9}
diff --git a/data/maps/the_entry/rooms/Wrath Room.txtpb b/data/maps/the_entry/rooms/Wrath Room.txtpb index 29bd1cb..903a0b7 100644 --- a/data/maps/the_entry/rooms/Wrath Room.txtpb +++ b/data/maps/the_entry/rooms/Wrath Room.txtpb
@@ -1,21 +1,5 @@
1name: "Wrath Room" 1name: "Wrath Room"
2display_name: "Red Blue Area" 2panel_display_name: "Red Blue Area"
3panels {
4 name: "RABBIT"
5 path: "Panels/Back Right/br_4"
6 clue: "rabbit"
7 answer: "hair"
8 symbols: SUN
9 symbols: ZERO
10}
11panels {
12 name: "HOLE"
13 path: "Panels/Back Right/br_5"
14 clue: "hole"
15 answer: "part"
16 symbols: ZERO
17 symbols: BOXES
18}
19panels { 3panels {
20 name: "WREATH" 4 name: "WREATH"
21 path: "Panels/Back Right/br_17" 5 path: "Panels/Back Right/br_17"
diff --git a/data/maps/the_entry/rooms/X Area.txtpb b/data/maps/the_entry/rooms/X Area.txtpb index ada16f8..8388b4e 100644 --- a/data/maps/the_entry/rooms/X Area.txtpb +++ b/data/maps/the_entry/rooms/X Area.txtpb
@@ -1,11 +1,13 @@
1name: "X Area" 1name: "X Area"
2display_name: "Starting Room" 2panel_display_name: "Starting Room"
3letters { 3letters {
4 key: "x" 4 key: "x"
5 path: "Components/Collectables/x" 5 path: "Components/Collectables/x"
6} 6}
7ports { 7ports {
8 name: "CC" 8 name: "CC"
9 display_name: "Near X1 Worldport"
9 path: "Components/Warps/worldport3" 10 path: "Components/Warps/worldport3"
10 orientation: "west" 11 destination { x: -12.5 y: 0 z: 60 }
12 rotation: 270
11} 13}
diff --git a/data/maps/the_extravagant/rooms/E Room.txtpb b/data/maps/the_extravagant/rooms/E Room.txtpb index 4b1f284..2f91764 100644 --- a/data/maps/the_extravagant/rooms/E Room.txtpb +++ b/data/maps/the_extravagant/rooms/E Room.txtpb
@@ -1,5 +1,4 @@
1name: "E Room" 1name: "E Room"
2display_name: "3"
3letters { 2letters {
4 key: "e" 3 key: "e"
5 path: "Components/Collectables/e" 4 path: "Components/Collectables/e"
diff --git a/data/maps/the_extravagant/rooms/Engine Room.txtpb b/data/maps/the_extravagant/rooms/Engine Room.txtpb index 79b60fc..7157757 100644 --- a/data/maps/the_extravagant/rooms/Engine Room.txtpb +++ b/data/maps/the_extravagant/rooms/Engine Room.txtpb
@@ -1,5 +1,4 @@
1name: "Engine Room" 1name: "Engine Room"
2display_name: "Engine Room"
3panels { 2panels {
4 name: "ENGINE" 3 name: "ENGINE"
5 path: "Panels/panel_8" 4 path: "Panels/panel_8"
@@ -23,7 +22,9 @@ paintings {
23} 22}
24ports { 23ports {
25 name: "GALLERY" 24 name: "GALLERY"
25 display_name: "Engine Room Worldport"
26 path: "Components/Warps/worldport2" 26 path: "Components/Warps/worldport2"
27 gravity: Z_PLUS 27 gravity: Z_PLUS
28 # TODO: orientation is not well defined with Z-axis gravity 28 # TODO: entrance shuffling for non Y axis gravity
29 no_shuffle: true
29} 30}
diff --git a/data/maps/the_extravagant/rooms/Hat Chamber.txtpb b/data/maps/the_extravagant/rooms/Hat Chamber.txtpb index 049959c..a100130 100644 --- a/data/maps/the_extravagant/rooms/Hat Chamber.txtpb +++ b/data/maps/the_extravagant/rooms/Hat Chamber.txtpb
@@ -1,5 +1,4 @@
1name: "Hat Chamber" 1name: "Hat Chamber"
2display_name: "3"
3panels { 2panels {
4 name: "BRIM" 3 name: "BRIM"
5 path: "Panels/panel_14" 4 path: "Panels/panel_14"
diff --git a/data/maps/the_extravagant/rooms/X Minus Middle Leg.txtpb b/data/maps/the_extravagant/rooms/X Minus Middle Leg.txtpb index 660a7dd..1455a4b 100644 --- a/data/maps/the_extravagant/rooms/X Minus Middle Leg.txtpb +++ b/data/maps/the_extravagant/rooms/X Minus Middle Leg.txtpb
@@ -1,5 +1,4 @@
1name: "X Minus Middle Leg" 1name: "X Minus Middle Leg"
2display_name: "W"
3panels { 2panels {
4 name: "ANTENNA" 3 name: "ANTENNA"
5 path: "Panels/panel_7" 4 path: "Panels/panel_7"
diff --git a/data/maps/the_extravagant/rooms/X Minus Right Leg.txtpb b/data/maps/the_extravagant/rooms/X Minus Right Leg.txtpb index ce731b6..ea45e10 100644 --- a/data/maps/the_extravagant/rooms/X Minus Right Leg.txtpb +++ b/data/maps/the_extravagant/rooms/X Minus Right Leg.txtpb
@@ -1,5 +1,4 @@
1name: "X Minus Right Leg" 1name: "X Minus Right Leg"
2display_name: "W"
3panels { 2panels {
4 name: "ROWBOAT" 3 name: "ROWBOAT"
5 path: "Panels/panel_13" 4 path: "Panels/panel_13"
diff --git a/data/maps/the_extravagant/rooms/X Minus.txtpb b/data/maps/the_extravagant/rooms/X Minus.txtpb index 3f389f1..92b15dc 100644 --- a/data/maps/the_extravagant/rooms/X Minus.txtpb +++ b/data/maps/the_extravagant/rooms/X Minus.txtpb
@@ -1,5 +1,4 @@
1name: "X Minus" 1name: "X Minus"
2display_name: "W"
3panels { 2panels {
4 name: "DUO" 3 name: "DUO"
5 path: "Panels/panel_1" 4 path: "Panels/panel_1"
diff --git a/data/maps/the_extravagant/rooms/X Plus Middle Leg.txtpb b/data/maps/the_extravagant/rooms/X Plus Middle Leg.txtpb index c656593..cb7cba6 100644 --- a/data/maps/the_extravagant/rooms/X Plus Middle Leg.txtpb +++ b/data/maps/the_extravagant/rooms/X Plus Middle Leg.txtpb
@@ -1,5 +1,4 @@
1name: "X Plus Middle Leg" 1name: "X Plus Middle Leg"
2display_name: "M"
3panels { 2panels {
4 name: "COLONY" 3 name: "COLONY"
5 path: "Panels/panel_10" 4 path: "Panels/panel_10"
diff --git a/data/maps/the_extravagant/rooms/X Plus Right Leg.txtpb b/data/maps/the_extravagant/rooms/X Plus Right Leg.txtpb index 7c75550..98dfad6 100644 --- a/data/maps/the_extravagant/rooms/X Plus Right Leg.txtpb +++ b/data/maps/the_extravagant/rooms/X Plus Right Leg.txtpb
@@ -1,5 +1,4 @@
1name: "X Plus Right Leg" 1name: "X Plus Right Leg"
2display_name: "M"
3panels { 2panels {
4 name: "HEAD" 3 name: "HEAD"
5 path: "Panels/panel_4" 4 path: "Panels/panel_4"
diff --git a/data/maps/the_extravagant/rooms/X Plus.txtpb b/data/maps/the_extravagant/rooms/X Plus.txtpb index db42770..a1c4b9d 100644 --- a/data/maps/the_extravagant/rooms/X Plus.txtpb +++ b/data/maps/the_extravagant/rooms/X Plus.txtpb
@@ -1,5 +1,4 @@
1name: "X Plus" 1name: "X Plus"
2display_name: "M"
3panels { 2panels {
4 name: "ROSE" 3 name: "ROSE"
5 path: "Panels/panel_16" 4 path: "Panels/panel_16"
@@ -24,4 +23,5 @@ paintings {
24keyholders { 23keyholders {
25 name: "M" 24 name: "M"
26 path: "Components/KeyHolders/keyHolderM" 25 path: "Components/KeyHolders/keyHolderM"
26 key: "m"
27} 27}
diff --git a/data/maps/the_extravagant/rooms/Y Minus First Floor.txtpb b/data/maps/the_extravagant/rooms/Y Minus First Floor.txtpb index 1429fa8..f80d68a 100644 --- a/data/maps/the_extravagant/rooms/Y Minus First Floor.txtpb +++ b/data/maps/the_extravagant/rooms/Y Minus First Floor.txtpb
@@ -1,5 +1,4 @@
1name: "Y Minus First Floor" 1name: "Y Minus First Floor"
2display_name: "3"
3panels { 2panels {
4 name: "RHINO" 3 name: "RHINO"
5 path: "Panels/panel_2" 4 path: "Panels/panel_2"
diff --git a/data/maps/the_extravagant/rooms/Y Minus Second Floor.txtpb b/data/maps/the_extravagant/rooms/Y Minus Second Floor.txtpb index be3238a..34a3c9d 100644 --- a/data/maps/the_extravagant/rooms/Y Minus Second Floor.txtpb +++ b/data/maps/the_extravagant/rooms/Y Minus Second Floor.txtpb
@@ -1,5 +1,4 @@
1name: "Y Minus Second Floor" 1name: "Y Minus Second Floor"
2display_name: "3"
3panels { 2panels {
4 name: "COMPASS" 3 name: "COMPASS"
5 path: "Panels/panel_5" 4 path: "Panels/panel_5"
diff --git a/data/maps/the_extravagant/rooms/Y Minus Third Floor.txtpb b/data/maps/the_extravagant/rooms/Y Minus Third Floor.txtpb index 881d42d..7aa5e1c 100644 --- a/data/maps/the_extravagant/rooms/Y Minus Third Floor.txtpb +++ b/data/maps/the_extravagant/rooms/Y Minus Third Floor.txtpb
@@ -1,5 +1,4 @@
1name: "Y Minus Third Floor" 1name: "Y Minus Third Floor"
2display_name: "3"
3panels { 2panels {
4 name: "WHISKERS" 3 name: "WHISKERS"
5 path: "Panels/panel_11" 4 path: "Panels/panel_11"
diff --git a/data/maps/the_extravagant/rooms/Y Plus First Floor.txtpb b/data/maps/the_extravagant/rooms/Y Plus First Floor.txtpb index 9c8120c..6226aa6 100644 --- a/data/maps/the_extravagant/rooms/Y Plus First Floor.txtpb +++ b/data/maps/the_extravagant/rooms/Y Plus First Floor.txtpb
@@ -1,5 +1,4 @@
1name: "Y Plus First Floor" 1name: "Y Plus First Floor"
2display_name: "E"
3paintings { 2paintings {
4 name: "UNDUE" 3 name: "UNDUE"
5 path: "Components/Paintings/undue4" 4 path: "Components/Paintings/undue4"
diff --git a/data/maps/the_extravagant/rooms/Y Plus Third Floor.txtpb b/data/maps/the_extravagant/rooms/Y Plus Third Floor.txtpb index bdc45b9..1cf0480 100644 --- a/data/maps/the_extravagant/rooms/Y Plus Third Floor.txtpb +++ b/data/maps/the_extravagant/rooms/Y Plus Third Floor.txtpb
@@ -1,6 +1,5 @@
1name: "Y Plus Third Floor" 1name: "Y Plus Third Floor"
2# It's the second floor too... 2# It's the second floor too...
3display_name: "E"
4panels { 3panels {
5 name: "CACTUS" 4 name: "CACTUS"
6 path: "Panels/panel_6" 5 path: "Panels/panel_6"
diff --git a/data/maps/the_gallery/doors.txtpb b/data/maps/the_gallery/doors.txtpb index 916acb8..adbc766 100644 --- a/data/maps/the_gallery/doors.txtpb +++ b/data/maps/the_gallery/doors.txtpb
@@ -1,8 +1,9 @@
1# The Gallery is interesting because there's so many cross-map requirements. 1# The Gallery is interesting because there's so many cross-map requirements.
2doors { 2doors {
3 name: "Darkroom Painting" 3 name: "Darkroom Painting"
4 type: ITEM_ONLY 4 type: GALLERY_PAINTING
5 move_paintings { room: "Main Area" name: "DARKROOM" } 5 #move_paintings { room: "Main Area" name: "DARKROOM" }
6 receivers: "Components/Paintings/darkroom/teleportListener"
6 panels { map: "the_darkroom" room: "First Room" name: "BISON" } 7 panels { map: "the_darkroom" room: "First Room" name: "BISON" }
7 panels { map: "the_darkroom" room: "First Room" name: "FISH" } 8 panels { map: "the_darkroom" room: "First Room" name: "FISH" }
8 panels { map: "the_darkroom" room: "First Room" name: "SHEEP" } 9 panels { map: "the_darkroom" room: "First Room" name: "SHEEP" }
@@ -26,14 +27,16 @@ doors {
26} 27}
27doors { 28doors {
28 name: "Butterfly Painting" 29 name: "Butterfly Painting"
29 type: ITEM_ONLY 30 type: GALLERY_PAINTING
30 move_paintings { room: "Main Area" name: "BUTTERFLY" } 31 #move_paintings { room: "Main Area" name: "BUTTERFLY" }
32 receivers: "Components/Paintings/butterfly/teleportListener"
31 rooms { map: "the_butterfly" name: "Main Area" } 33 rooms { map: "the_butterfly" name: "Main Area" }
32} 34}
33doors { 35doors {
34 name: "Between Painting" 36 name: "Between Painting"
35 type: ITEM_ONLY 37 type: GALLERY_PAINTING
36 move_paintings { room: "Main Area" name: "BETWEEN" } 38 #move_paintings { room: "Main Area" name: "BETWEEN" }
39 receivers: "Components/Paintings/between/teleportListener"
37 panels { map: "the_between" room: "Main Area" name: "SUN" } 40 panels { map: "the_between" room: "Main Area" name: "SUN" }
38 panels { map: "the_between" room: "Main Area" name: "KOI" } 41 panels { map: "the_between" room: "Main Area" name: "KOI" }
39 panels { map: "the_between" room: "Main Area" name: "SUN KOI" } 42 panels { map: "the_between" room: "Main Area" name: "SUN KOI" }
@@ -67,20 +70,44 @@ doors {
67} 70}
68doors { 71doors {
69 name: "Entry Painting" 72 name: "Entry Painting"
70 type: ITEM_ONLY 73 type: GALLERY_PAINTING
71 move_paintings { room: "Main Area" name: "ENTRY" } 74 #move_paintings { room: "Main Area" name: "ENTRY" }
75 receivers: "Components/Paintings/eyes/teleportListener"
72 panels { map: "the_entry" room: "Eye Room" name: "I" } 76 panels { map: "the_entry" room: "Eye Room" name: "I" }
73} 77}
74doors { 78doors {
75 name: "Wise Painting" 79 name: "Wise Painting"
76 type: ITEM_ONLY 80 type: GALLERY_PAINTING
77 move_paintings { room: "Main Area" name: "WISE" } 81 #move_paintings { room: "Main Area" name: "WISE" }
78 # TODO: any panel in The Wise 82 receivers: "Components/Paintings/triangle/teleportListener"
83 panels { map: "the_wise" room: "Entry" name: "INK" }
84 panels { map: "the_wise" room: "Puzzles" name: "STORY" }
85 panels { map: "the_wise" room: "Puzzles" name: "VENTURE" }
86 panels { map: "the_wise" room: "Puzzles" name: "PASSED" }
87 panels { map: "the_wise" room: "Puzzles" name: "SLUMBERING" }
88 panels { map: "the_wise" room: "Puzzles" name: "RHYME" }
89 panels { map: "the_wise" room: "Puzzles" name: "OBSCURE" }
90 panels { map: "the_wise" room: "Puzzles" name: "PROPHET" }
91 panels { map: "the_wise" room: "Puzzles" name: "ERAS" }
92 panels { map: "the_wise" room: "Puzzles" name: "DARKNESS" }
93 panels { map: "the_wise" room: "Puzzles" name: "PRINCE" }
94 panels { map: "the_wise" room: "Puzzles" name: "BATH" }
95 panels { map: "the_wise" room: "Puzzles" name: "CHAOTIC" }
96 panels { map: "the_wise" room: "Puzzles" name: "EYES" }
97 panels { map: "the_wise" room: "Puzzles" name: "QUEENDOOM" }
98 panels { map: "the_wise" room: "Puzzles" name: "SHOUTS" }
99 panels { map: "the_wise" room: "Puzzles" name: "INTELLIGENCE" }
100 panels { map: "the_wise" room: "Puzzles" name: "EARTHWAR" }
101 panels { map: "the_wise" room: "Puzzles" name: "SLEEPER" }
102 panels { map: "the_wise" room: "Puzzles" name: "BOTTLE" }
103 panels { map: "the_wise" room: "Puzzles" name: "WORDS" }
104 complete_at: 1
79} 105}
80doors { 106doors {
81 name: "Tree Painting" 107 name: "Tree Painting"
82 type: ITEM_ONLY 108 type: GALLERY_PAINTING
83 move_paintings { room: "Main Area" name: "TREE" } 109 #move_paintings { room: "Main Area" name: "TREE" }
110 receivers: "Components/Paintings/Clue Maps/tree/teleportListener"
84 panels { map: "the_tree" room: "Main Area" name: "COLOR" } 111 panels { map: "the_tree" room: "Main Area" name: "COLOR" }
85 panels { map: "the_tree" room: "Main Area" name: "DAMAGE (1)" } 112 panels { map: "the_tree" room: "Main Area" name: "DAMAGE (1)" }
86 panels { map: "the_tree" room: "Main Area" name: "DAMAGE (2)" } 113 panels { map: "the_tree" room: "Main Area" name: "DAMAGE (2)" }
@@ -115,68 +142,89 @@ doors {
115} 142}
116doors { 143doors {
117 name: "Unyielding Painting" 144 name: "Unyielding Painting"
118 type: ITEM_ONLY 145 type: GALLERY_PAINTING
119 move_paintings { room: "Main Area" name: "UNYIELDING" } 146 #move_paintings { room: "Main Area" name: "UNYIELDING" }
147 receivers: "Components/Paintings/Clue Maps/unyielding/teleportListener"
120 rooms { map: "the_unyielding" name: "Digital Entrance" } 148 rooms { map: "the_unyielding" name: "Digital Entrance" }
121} 149}
122doors { 150doors {
123 name: "Graveyard Painting" 151 name: "Graveyard Painting"
124 type: ITEM_ONLY 152 type: GALLERY_PAINTING
125 move_paintings { room: "Main Area" name: "GRAVEYARD" } 153 #move_paintings { room: "Main Area" name: "GRAVEYARD" }
154 receivers: "Components/Paintings/Endings/grave/teleportListener"
126 rooms { map: "the_graveyard" name: "Outside" } 155 rooms { map: "the_graveyard" name: "Outside" }
127} 156}
128doors { 157doors {
129 name: "Control Center Painting" 158 name: "Control Center Painting"
130 type: ITEM_ONLY 159 type: GALLERY_PAINTING
131 move_paintings { room: "Main Area" name: "CC" } 160 #move_paintings { room: "Main Area" name: "CC" }
161 receivers: "Components/Paintings/Endings/desert/teleportListener"
132 rooms { map: "the_impressive" name: "M2 Room" } 162 rooms { map: "the_impressive" name: "M2 Room" }
133} 163}
134doors { 164doors {
135 name: "Tower Painting" 165 name: "Tower Painting"
136 type: ITEM_ONLY 166 type: GALLERY_PAINTING
137 move_paintings { room: "Main Area" name: "TOWER" } 167 #move_paintings { room: "Main Area" name: "TOWER" }
168 receivers: "Components/Paintings/Endings/red/teleportListener"
138 rooms { map: "the_tower" name: "First Floor" } 169 rooms { map: "the_tower" name: "First Floor" }
139} 170}
140doors { 171doors {
141 name: "Wondrous Painting" 172 name: "Wondrous Painting"
142 type: ITEM_ONLY 173 type: GALLERY_PAINTING
143 move_paintings { room: "Main Area" name: "WONDROUS" } 174 #move_paintings { room: "Main Area" name: "WONDROUS" }
144 # TODO: any panel in The Wondrous 175 receivers: "Components/Paintings/Endings/window/teleportListener"
176 panels { map: "the_wondrous" room: "Entry" name: "WONDER" }
177 panels { map: "the_wondrous" room: "Regular" name: "SHRINK" }
178 panels { map: "the_wondrous" room: "Huge" name: "SHRINK" }
179 panels { map: "the_wondrous" room: "Huge" name: "IRE" }
180 panels { map: "the_wondrous" room: "Huge" name: "BRIE" }
181 panels { map: "the_wondrous" room: "Huge" name: "WICK" }
182 panels { map: "the_wondrous" room: "Huge" name: "BARK" }
183 panels { map: "the_wondrous" room: "Huge" name: "HARE" }
184 panels { map: "the_wondrous" room: "Huge" name: "CHIME" }
185 panels { map: "the_wondrous" room: "Huge" name: "LIBRARY" }
186 complete_at: 1
145} 187}
146doors { 188doors {
147 name: "Rainbow Painting" 189 name: "Rainbow Painting"
148 type: ITEM_ONLY 190 type: GALLERY_PAINTING
149 move_paintings { room: "Main Area" name: "RAINBOW" } 191 #move_paintings { room: "Main Area" name: "RAINBOW" }
192 receivers: "Components/Paintings/Endings/rainbow/teleportListener"
150 rooms { map: "daedalus" name: "Rainbow Start" } 193 rooms { map: "daedalus" name: "Rainbow Start" }
151} 194}
152doors { 195doors {
153 name: "Words Painting" 196 name: "Words Painting"
154 type: ITEM_ONLY 197 type: GALLERY_PAINTING
155 move_paintings { room: "Main Area" name: "WORDS" } 198 #move_paintings { room: "Main Area" name: "WORDS" }
156 # TODO: Enter The Words 199 receivers: "Components/Paintings/Endings/words/teleportListener"
200 rooms { map: "the_words" name: "Main Area" }
157} 201}
158doors { 202doors {
159 name: "Colorful Painting" 203 name: "Colorful Painting"
160 type: ITEM_ONLY 204 type: GALLERY_PAINTING
161 move_paintings { room: "Main Area" name: "COLORFUL" } 205 #move_paintings { room: "Main Area" name: "COLORFUL" }
206 receivers: "Components/Paintings/Endings/colorful/teleportListener"
162 rooms { map: "the_colorful" name: "White Room" } 207 rooms { map: "the_colorful" name: "White Room" }
163} 208}
164doors { 209doors {
165 name: "Castle Painting" 210 name: "Castle Painting"
166 type: ITEM_ONLY 211 type: GALLERY_PAINTING
167 move_paintings { room: "Main Area" name: "CASTLE" } 212 #move_paintings { room: "Main Area" name: "CASTLE" }
213 receivers: "Components/Paintings/Endings/castle/teleportListener"
168 rooms { map: "daedalus" name: "Castle" } 214 rooms { map: "daedalus" name: "Castle" }
169} 215}
170doors { 216doors {
171 name: "Sun Temple Painting" 217 name: "Sun Temple Painting"
172 type: ITEM_ONLY 218 type: GALLERY_PAINTING
173 move_paintings { room: "Main Area" name: "SUNTEMPLE" } 219 #move_paintings { room: "Main Area" name: "SUNTEMPLE" }
220 receivers: "Components/Paintings/Endings/temple/teleportListener"
174 rooms { map: "the_sun_temple" name: "Entrance" } 221 rooms { map: "the_sun_temple" name: "Entrance" }
175} 222}
176doors { 223doors {
177 name: "Ancient Painting" 224 name: "Ancient Painting"
178 type: ITEM_ONLY 225 type: GALLERY_PAINTING
179 move_paintings { room: "Main Area" name: "ANCIENT" } 226 #move_paintings { room: "Main Area" name: "ANCIENT" }
227 receivers: "Components/Paintings/Endings/cubes/teleportListener"
180 rooms { map: "the_ancient" name: "Outside" } 228 rooms { map: "the_ancient" name: "Outside" }
181} 229}
182doors { 230doors {
diff --git a/data/maps/the_gallery/rooms/Back Room.txtpb b/data/maps/the_gallery/rooms/Back Room.txtpb index baf7270..74d5304 100644 --- a/data/maps/the_gallery/rooms/Back Room.txtpb +++ b/data/maps/the_gallery/rooms/Back Room.txtpb
@@ -1,5 +1,4 @@
1name: "Back Room" 1name: "Back Room"
2display_name: "Back Room"
3panels { 2panels {
4 name: "UNYIELDING" 3 name: "UNYIELDING"
5 path: "Panels/entry_2" 4 path: "Panels/entry_2"
diff --git a/data/maps/the_gallery/rooms/Daedalus Extension.txtpb b/data/maps/the_gallery/rooms/Daedalus Extension.txtpb index e525a2c..51d2be5 100644 --- a/data/maps/the_gallery/rooms/Daedalus Extension.txtpb +++ b/data/maps/the_gallery/rooms/Daedalus Extension.txtpb
@@ -1,5 +1,4 @@
1name: "Daedalus Extension" 1name: "Daedalus Extension"
2display_name: "Daedalus Extension"
3panels { 2panels {
4 name: "WHERE" 3 name: "WHERE"
5 path: "Panels/entry_1" 4 path: "Panels/entry_1"
diff --git a/data/maps/the_gallery/rooms/Ending.txtpb b/data/maps/the_gallery/rooms/Ending.txtpb index 72c8e72..f713acc 100644 --- a/data/maps/the_gallery/rooms/Ending.txtpb +++ b/data/maps/the_gallery/rooms/Ending.txtpb
@@ -1,5 +1,4 @@
1name: "Ending" 1name: "Ending"
2display_name: "Back Room"
3endings { 2endings {
4 name: "YELLOW" 3 name: "YELLOW"
5 path: "Components/Endings/yellow_ending" 4 path: "Components/Endings/yellow_ending"
diff --git a/data/maps/the_gallery/rooms/Main Area.txtpb b/data/maps/the_gallery/rooms/Main Area.txtpb index a8fb3c6..e88dc48 100644 --- a/data/maps/the_gallery/rooms/Main Area.txtpb +++ b/data/maps/the_gallery/rooms/Main Area.txtpb
@@ -1,8 +1,8 @@
1name: "Main Area" 1name: "Main Area"
2display_name: "Main Area"
3keyholders { 2keyholders {
4 name: "P" 3 name: "P"
5 path: "Components/KeyHolders/keyHolderP" 4 path: "Components/KeyHolders/keyHolderP"
5 key: "p"
6} 6}
7paintings { 7paintings {
8 name: "OWL" 8 name: "OWL"
@@ -162,6 +162,8 @@ paintings {
162} 162}
163ports { 163ports {
164 name: "ENTRY" 164 name: "ENTRY"
165 display_name: "Entrance"
165 path: "Components/Warps/worldport" 166 path: "Components/Warps/worldport"
166 orientation: "west" 167 destination { x: -3.5 y: 0 z: 16 }
168 rotation: 270
167} 169}
diff --git a/data/maps/the_gold/rooms/The Whole Thing.txtpb b/data/maps/the_gold/rooms/The Whole Thing.txtpb index 026e709..4848c1f 100644 --- a/data/maps/the_gold/rooms/The Whole Thing.txtpb +++ b/data/maps/the_gold/rooms/The Whole Thing.txtpb
@@ -1,5 +1,4 @@
1name: "The Whole Thing" 1name: "The Whole Thing"
2display_name: "The Whole Thing"
3panels { 2panels {
4 name: "PANEL" 3 name: "PANEL"
5 path: "Panels/Room_1/panel_1" 4 path: "Panels/Room_1/panel_1"
diff --git a/data/maps/the_graveyard/doors.txtpb b/data/maps/the_graveyard/doors.txtpb index f06d40d..a10d8f6 100644 --- a/data/maps/the_graveyard/doors.txtpb +++ b/data/maps/the_graveyard/doors.txtpb
@@ -19,6 +19,7 @@ doors {
19doors { 19doors {
20 name: "Double Letters" 20 name: "Double Letters"
21 type: EVENT 21 type: EVENT
22 switches: "double_letters" 22 receivers: "Panels/panel_3/teleportListener"
23 # TODO: once again, not sure whether this is how it should work 23 receivers: "Components/Paintings/omrt/teleportListener"
24 double_letters: true
24} 25}
diff --git a/data/maps/the_graveyard/rooms/Inside.txtpb b/data/maps/the_graveyard/rooms/Inside.txtpb index fd2fc9d..1f58d3f 100644 --- a/data/maps/the_graveyard/rooms/Inside.txtpb +++ b/data/maps/the_graveyard/rooms/Inside.txtpb
@@ -1,5 +1,4 @@
1name: "Inside" 1name: "Inside"
2display_name: "Inside"
3panels { 2panels {
4 name: "REMEMBER" 3 name: "REMEMBER"
5 path: "Panels/panel_3" 4 path: "Panels/panel_3"
diff --git a/data/maps/the_graveyard/rooms/Outside.txtpb b/data/maps/the_graveyard/rooms/Outside.txtpb index b0e5ee9..db9de1b 100644 --- a/data/maps/the_graveyard/rooms/Outside.txtpb +++ b/data/maps/the_graveyard/rooms/Outside.txtpb
@@ -1,5 +1,4 @@
1name: "Outside" 1name: "Outside"
2display_name: "Outside"
3panels { 2panels {
4 name: "FOOT" 3 name: "FOOT"
5 path: "Panels/panel_1" 4 path: "Panels/panel_1"
diff --git a/data/maps/the_great/doors.txtpb b/data/maps/the_great/doors.txtpb index 463eaba..628715f 100644 --- a/data/maps/the_great/doors.txtpb +++ b/data/maps/the_great/doors.txtpb
@@ -49,6 +49,7 @@ doors {
49 type: LOCATION_ONLY 49 type: LOCATION_ONLY
50 panels { room: "West Side" name: "ERASE" } 50 panels { room: "West Side" name: "ERASE" }
51 location_room: "West Side" 51 location_room: "West Side"
52 location_name: "ERASE"
52} 53}
53doors { 54doors {
54 name: "Control Center Purple Door" 55 name: "Control Center Purple Door"
@@ -59,13 +60,13 @@ doors {
59doors { 60doors {
60 name: "Control Center Gray Door" 61 name: "Control Center Gray Door"
61 type: CONTROL_CENTER_COLOR 62 type: CONTROL_CENTER_COLOR
62 receivers: "Components/Doors/Gates/Gate" 63 receivers: "Components/Doors/Gates/Gate/animationListener"
63 control_center_color: "gray" 64 control_center_color: "gray"
64} 65}
65doors { 66doors {
66 name: "Control Center Red Door" 67 name: "Control Center Red Door"
67 type: CONTROL_CENTER_COLOR 68 type: CONTROL_CENTER_COLOR
68 receivers: "Components/Doors/Gates/Gate" 69 receivers: "Components/Doors/entry_18"
69 control_center_color: "red" 70 control_center_color: "red"
70} 71}
71doors { 72doors {
@@ -98,7 +99,8 @@ doors {
98doors { 99doors {
99 name: "Savory Painting" 100 name: "Savory Painting"
100 type: STANDARD 101 type: STANDARD
101 move_paintings { room: "West Side" name: "EXTRAVAGANT" } 102 #move_paintings { room: "West Side" name: "EXTRAVAGANT" }
103 receivers: "Components/Paintings/unless/teleportListener"
102 panels { room: "West Side" name: "SAVORY" } 104 panels { room: "West Side" name: "SAVORY" }
103 panels { room: "West Side" name: "FLAVORS" } 105 panels { room: "West Side" name: "FLAVORS" }
104 location_room: "West Side" 106 location_room: "West Side"
@@ -141,6 +143,7 @@ doors {
141 panels { room: "Pillar Room" name: "CAUGHT" } 143 panels { room: "Pillar Room" name: "CAUGHT" }
142 panels { room: "Pillar Room" name: "TEN" } 144 panels { room: "Pillar Room" name: "TEN" }
143 location_room: "Pillar Room" 145 location_room: "Pillar Room"
146 location_name: "Puzzles"
144} 147}
145doors { 148doors {
146 name: "North Landscape Entrance" 149 name: "North Landscape Entrance"
@@ -224,7 +227,7 @@ doors {
224 name: "Tower Entrance" 227 name: "Tower Entrance"
225 type: ITEM_ONLY 228 type: ITEM_ONLY
226 receivers: "Components/Doors/entry_25" 229 receivers: "Components/Doors/entry_25"
227 switches: "double_letters" 230 double_letters: true
228} 231}
229doors { 232doors {
230 name: "Maze Out/South Door" 233 name: "Maze Out/South Door"
@@ -390,11 +393,13 @@ doors {
390 name: "Big Y" 393 name: "Big Y"
391 type: STANDARD 394 type: STANDARD
392 receivers: "Components/Doors/question_3" 395 receivers: "Components/Doors/question_3"
396 receivers: "Components/Doors/question_12"
393 panels { room: "Question Room What" name: "QUESTION" answer: "why" } 397 panels { room: "Question Room What" name: "QUESTION" answer: "why" }
394 panels { room: "Question Room How" name: "QUESTION" answer: "why" } 398 panels { room: "Question Room How" name: "QUESTION" answer: "why" }
395 panels { room: "Question Room When" name: "QUESTION" answer: "why" } 399 panels { room: "Question Room When" name: "QUESTION" answer: "why" }
396 panels { room: "Question Room Who" name: "QUESTION" answer: "why" } 400 panels { room: "Question Room Who" name: "QUESTION" answer: "why" }
397 location_room: "Question Room Who" 401 location_room: "Question Room Who"
402 location_name: "Whys"
398} 403}
399doors { 404doors {
400 name: "Talented Entrance" 405 name: "Talented Entrance"
@@ -417,6 +422,7 @@ doors {
417 panels { room: "Back Area" name: "Right Landscape Top" answer: "tell" } 422 panels { room: "Back Area" name: "Right Landscape Top" answer: "tell" }
418 panels { room: "Back Area" name: "Right Landscape Left" answer: "eyes" } 423 panels { room: "Back Area" name: "Right Landscape Left" answer: "eyes" }
419 location_room: "Back Area" 424 location_room: "Back Area"
425 location_name: "Landscapes Room Alternate Answers"
420} 426}
421doors { 427doors {
422 name: "Nature Room Door" 428 name: "Nature Room Door"
@@ -465,9 +471,13 @@ doors {
465} 471}
466doors { 472doors {
467 name: "Lavender Cube" 473 name: "Lavender Cube"
468 type: ITEM_ONLY 474 type: EVENT
469 receivers: "Components/Doors/entry_28" 475 receivers: "Components/Doors/entry_28"
470 switches: "lavender_cubes" 476 panels {
477 map: "the_ancient"
478 room: "Inside"
479 name: "COLOR"
480 }
471} 481}
472doors { 482doors {
473 name: "Zero Entrance" 483 name: "Zero Entrance"
@@ -492,3 +502,14 @@ doors {
492 panels { room: "Back Area" name: "PAINTING" } 502 panels { room: "Back Area" name: "PAINTING" }
493 location_room: "Back Area" 503 location_room: "Back Area"
494} 504}
505doors {
506 name: "Cyan Doors"
507 type: EVENT
508 receivers: "Panels/General/entry_7/teleportListener"
509 double_letters: true
510}
511doors {
512 name: "Partial Entrance"
513 type: EVENT
514 panels { room: "West Side" name: "CLUE" }
515}
diff --git a/data/maps/the_great/rooms/Back Area.txtpb b/data/maps/the_great/rooms/Back Area.txtpb index 3701249..c57a76f 100644 --- a/data/maps/the_great/rooms/Back Area.txtpb +++ b/data/maps/the_great/rooms/Back Area.txtpb
@@ -1,5 +1,5 @@
1name: "Back Area" 1name: "Back Area"
2display_name: "Back Area" 2panel_display_name: "Back Area"
3panels { 3panels {
4 name: "PLANT" 4 name: "PLANT"
5 path: "Panels/General/entry_14" 5 path: "Panels/General/entry_14"
@@ -124,23 +124,31 @@ paintings {
124} 124}
125ports { 125ports {
126 name: "UNKEMPT" 126 name: "UNKEMPT"
127 display_name: "Unkempt Entrance"
127 path: "Meshes/Blocks/Warps/worldport5" 128 path: "Meshes/Blocks/Warps/worldport5"
128 orientation: "north" 129 destination { x: 72 y: 0 z: 10.5 }
130 rotation: 180
129} 131}
130ports { 132ports {
131 name: "THREEDOORS" 133 name: "THREEDOORS"
134 display_name: "Three Doors Entrance"
132 path: "Meshes/Blocks/Warps/worldport16" 135 path: "Meshes/Blocks/Warps/worldport16"
133 orientation: "south" 136 destination { x: 77 y: 0 z: 33.5 }
137 rotation: 0
134} 138}
135ports { 139ports {
136 name: "TOWER" 140 name: "TOWER"
141 display_name: "Tower Entrance"
137 path: "Meshes/Blocks/Warps/worldport10" 142 path: "Meshes/Blocks/Warps/worldport10"
138 orientation: "south" 143 destination { x: 0 y: 0 z: 52 }
144 rotation: 0
139 required_door { name: "Tower Entrance" } 145 required_door { name: "Tower Entrance" }
140 # The reverse warp bypasses the door, so there needs to be two oneway connections. 146 # The reverse warp bypasses the door, so there needs to be two oneway connections.
141} 147}
142ports { 148ports {
143 name: "TREE" 149 name: "TREE"
150 display_name: "Tree Entrance"
144 path: "Meshes/Blocks/Warps/worldport17" 151 path: "Meshes/Blocks/Warps/worldport17"
145 orientation: "north" 152 destination { x: 26 y: 0 z: 58 }
153 rotation: 180
146} 154}
diff --git a/data/maps/the_great/rooms/Behind Question Area.txtpb b/data/maps/the_great/rooms/Behind Question Area.txtpb index 88f800f..744d4c4 100644 --- a/data/maps/the_great/rooms/Behind Question Area.txtpb +++ b/data/maps/the_great/rooms/Behind Question Area.txtpb
@@ -1,5 +1,5 @@
1name: "Behind Question Area" 1name: "Behind Question Area"
2display_name: "Main Area" 2panel_display_name: "Question Room"
3panels { 3panels {
4 name: "DEW" 4 name: "DEW"
5 path: "Panels/General/uc_4" 5 path: "Panels/General/uc_4"
diff --git a/data/maps/the_great/rooms/Colorful Entrance.txtpb b/data/maps/the_great/rooms/Colorful Entrance.txtpb index 5d7c9b2..5464698 100644 --- a/data/maps/the_great/rooms/Colorful Entrance.txtpb +++ b/data/maps/the_great/rooms/Colorful Entrance.txtpb
@@ -1,7 +1,9 @@
1name: "Colorful Entrance" 1name: "Colorful Entrance"
2display_name: "Pillar Room" 2panel_display_name: "Pillar Room"
3ports { 3ports {
4 name: "COLORFUL" 4 name: "COLORFUL"
5 display_name: "Pillar Room Worldport"
5 path: "Meshes/Blocks/Warps/worldport13" 6 path: "Meshes/Blocks/Warps/worldport13"
6 orientation: "west" 7 destination { x: -37.5 y: 0 z: 74 }
8 rotation: 270
7} 9}
diff --git a/data/maps/the_great/rooms/Daedalus Entrance.txtpb b/data/maps/the_great/rooms/Daedalus Entrance.txtpb index 7e1d477..abfab99 100644 --- a/data/maps/the_great/rooms/Daedalus Entrance.txtpb +++ b/data/maps/the_great/rooms/Daedalus Entrance.txtpb
@@ -1,5 +1,5 @@
1name: "Daedalus Entrance" 1name: "Daedalus Entrance"
2display_name: "Main Area" 2panel_display_name: "Main Area"
3panels { 3panels {
4 name: "MISSING" 4 name: "MISSING"
5 path: "Panels/General/entry_2" 5 path: "Panels/General/entry_2"
@@ -9,8 +9,10 @@ panels {
9} 9}
10ports { 10ports {
11 name: "DAEDALUS" 11 name: "DAEDALUS"
12 display_name: "Daedalus Entrance"
12 path: "Meshes/Blocks/Warps/worldport8" 13 path: "Meshes/Blocks/Warps/worldport8"
13 orientation: "south" 14 destination { x: 98 y: 2 z: 27.5 }
15 rotation: 0
14 required_door { name: "Daedalus Entrance" } 16 required_door { name: "Daedalus Entrance" }
15 # The reverse warp bypasses the door, so there needs to be two oneway connections. 17 # The reverse warp bypasses the door, so there needs to be two oneway connections.
16} 18}
diff --git a/data/maps/the_great/rooms/East Landscape.txtpb b/data/maps/the_great/rooms/East Landscape.txtpb index 84fc182..44ed2c5 100644 --- a/data/maps/the_great/rooms/East Landscape.txtpb +++ b/data/maps/the_great/rooms/East Landscape.txtpb
@@ -1,5 +1,5 @@
1name: "East Landscape" 1name: "East Landscape"
2display_name: "East Landscape" 2panel_display_name: "East Landscape"
3panels { 3panels {
4 name: "COLOR" 4 name: "COLOR"
5 path: "Panels/General/entry_10" 5 path: "Panels/General/entry_10"
diff --git a/data/maps/the_great/rooms/G Room.txtpb b/data/maps/the_great/rooms/G Room.txtpb index 218a9c1..f93c899 100644 --- a/data/maps/the_great/rooms/G Room.txtpb +++ b/data/maps/the_great/rooms/G Room.txtpb
@@ -1,5 +1,5 @@
1name: "G Room" 1name: "G Room"
2display_name: "Courtyard" 2panel_display_name: "Courtyard"
3letters { 3letters {
4 key: "g" 4 key: "g"
5 path: "Components/Collectables/g" 5 path: "Components/Collectables/g"
diff --git a/data/maps/the_great/rooms/Hive Entrance.txtpb b/data/maps/the_great/rooms/Hive Entrance.txtpb index ba886b1..56acc22 100644 --- a/data/maps/the_great/rooms/Hive Entrance.txtpb +++ b/data/maps/the_great/rooms/Hive Entrance.txtpb
@@ -1,5 +1,5 @@
1name: "Hive Entrance" 1name: "Hive Entrance"
2display_name: "West Side" 2panel_display_name: "West Side"
3panels { 3panels {
4 name: "LOST" 4 name: "LOST"
5 path: "Panels/Hive Room/hive_1" 5 path: "Panels/Hive Room/hive_1"
@@ -9,6 +9,8 @@ panels {
9} 9}
10ports { 10ports {
11 name: "HIVE" 11 name: "HIVE"
12 display_name: "Hive Entrance"
12 path: "Meshes/Blocks/Warps/worldport19" 13 path: "Meshes/Blocks/Warps/worldport19"
13 orientation: "east" 14 destination { x: -91.5 y: 0 z: 37 }
15 rotation: 90
14} 16}
diff --git a/data/maps/the_great/rooms/Jail Part 1.txtpb b/data/maps/the_great/rooms/Jail Part 1.txtpb index bd468bd..452841b 100644 --- a/data/maps/the_great/rooms/Jail Part 1.txtpb +++ b/data/maps/the_great/rooms/Jail Part 1.txtpb
@@ -1,5 +1,5 @@
1name: "Jail Part 1" 1name: "Jail Part 1"
2display_name: "Jail" 2panel_display_name: "Jail"
3panels { 3panels {
4 name: "FLAP" 4 name: "FLAP"
5 path: "Panels/Throat/throat_1" 5 path: "Panels/Throat/throat_1"
diff --git a/data/maps/the_great/rooms/Jail Part 2.txtpb b/data/maps/the_great/rooms/Jail Part 2.txtpb index 1f54dd5..1a0c975 100644 --- a/data/maps/the_great/rooms/Jail Part 2.txtpb +++ b/data/maps/the_great/rooms/Jail Part 2.txtpb
@@ -1,5 +1,5 @@
1name: "Jail Part 2" 1name: "Jail Part 2"
2display_name: "Jail" 2panel_display_name: "Jail"
3panels { 3panels {
4 name: "DIGEST" 4 name: "DIGEST"
5 path: "Panels/Bowels3/bowels_1" 5 path: "Panels/Bowels3/bowels_1"
diff --git a/data/maps/the_great/rooms/Jubilant Entrance.txtpb b/data/maps/the_great/rooms/Jubilant Entrance.txtpb index eaf9811..b254cc0 100644 --- a/data/maps/the_great/rooms/Jubilant Entrance.txtpb +++ b/data/maps/the_great/rooms/Jubilant Entrance.txtpb
@@ -1,7 +1,9 @@
1name: "Jubilant Entrance" 1name: "Jubilant Entrance"
2display_name: "West Side" 2panel_display_name: "West Side"
3ports { 3ports {
4 name: "JUBILANT" 4 name: "JUBILANT"
5 display_name: "Jubilant Entrance"
5 path: "Meshes/Blocks/Warps/worldport12" 6 path: "Meshes/Blocks/Warps/worldport12"
6 orientation: "east" 7 destination { x: -62 y: 0 z: -19 }
8 rotation: 90
7} 9}
diff --git a/data/maps/the_great/rooms/Magnet Room.txtpb b/data/maps/the_great/rooms/Magnet Room.txtpb index 4cf6433..2d122a4 100644 --- a/data/maps/the_great/rooms/Magnet Room.txtpb +++ b/data/maps/the_great/rooms/Magnet Room.txtpb
@@ -1,5 +1,5 @@
1name: "Magnet Room" 1name: "Magnet Room"
2display_name: "Magnet Room" 2panel_display_name: "Magnet Room"
3panels { 3panels {
4 name: "AIRPLANE" 4 name: "AIRPLANE"
5 path: "Panels/Magnet Room/magnet_2" 5 path: "Panels/Magnet Room/magnet_2"
diff --git a/data/maps/the_great/rooms/Main Area.txtpb b/data/maps/the_great/rooms/Main Area.txtpb index 40c7fbb..a5ed9f3 100644 --- a/data/maps/the_great/rooms/Main Area.txtpb +++ b/data/maps/the_great/rooms/Main Area.txtpb
@@ -1,5 +1,5 @@
1name: "Main Area" 1name: "Main Area"
2display_name: "Main Area" 2panel_display_name: "Main Area"
3panels { 3panels {
4 name: "INTRO" 4 name: "INTRO"
5 path: "Panels/General/entry_8" 5 path: "Panels/General/entry_8"
@@ -111,6 +111,7 @@ panels {
111 answer: "high" 111 answer: "high"
112 symbols: SUN 112 symbols: SUN
113 symbols: ZERO 113 symbols: ZERO
114 required_door { name: "Cyan Doors" }
114} 115}
115panels { 116panels {
116 name: "CURT" 117 name: "CURT"
@@ -121,27 +122,37 @@ panels {
121} 122}
122ports { 123ports {
123 name: "ENTRY" 124 name: "ENTRY"
125 display_name: "Entry Building"
124 path: "Meshes/Blocks/Warps/worldport" 126 path: "Meshes/Blocks/Warps/worldport"
125 orientation: "south" 127 destination { x: 33 y: 0 z: 15 }
128 rotation: 0
126} 129}
127ports { 130ports {
128 name: "KEEN" 131 name: "KEEN"
132 display_name: "Keen Building Front"
129 path: "Meshes/Blocks/Warps/worldport6" 133 path: "Meshes/Blocks/Warps/worldport6"
130 orientation: "north" 134 destination { x: 33 y: 0 z: -21 }
135 rotation: 180
131} 136}
132ports { 137ports {
133 name: "ORB" 138 name: "ORB"
139 display_name: "Orb Building"
134 path: "Meshes/Blocks/Warps/worldport3" 140 path: "Meshes/Blocks/Warps/worldport3"
135 orientation: "north" 141 destination { x: 62 y: 0 z: -13 }
142 rotation: 180
136} 143}
137ports { 144ports {
138 name: "LINEAR" 145 name: "LINEAR"
146 display_name: "Keen Building Back"
139 path: "Meshes/Blocks/Warps/worldport15" 147 path: "Meshes/Blocks/Warps/worldport15"
140 orientation: "south" 148 destination { x: 33 y: 0 z: -42.5 }
149 rotation: 0
141} 150}
142ports { 151ports {
143 name: "DIGITAL" 152 name: "DIGITAL"
153 display_name: "Digital Hole"
144 path: "Meshes/Blocks/Warps/worldport4" 154 path: "Meshes/Blocks/Warps/worldport4"
145 orientation: "down" 155 destination { x: -6.5 y: 0 z: 7.5 }
156 rotation: 0
146 required_door { name: "Digital Entrance" } 157 required_door { name: "Digital Entrance" }
147} 158}
diff --git a/data/maps/the_great/rooms/Maze Center.txtpb b/data/maps/the_great/rooms/Maze Center.txtpb index f557eaa..97ff146 100644 --- a/data/maps/the_great/rooms/Maze Center.txtpb +++ b/data/maps/the_great/rooms/Maze Center.txtpb
@@ -1,5 +1,5 @@
1name: "Maze Center" 1name: "Maze Center"
2display_name: "Courtyard" 2panel_display_name: "Courtyard"
3panels { 3panels {
4 name: "POOR" 4 name: "POOR"
5 path: "Panels/Maze/maze_7" 5 path: "Panels/Maze/maze_7"
diff --git a/data/maps/the_great/rooms/Maze Cold Area.txtpb b/data/maps/the_great/rooms/Maze Cold Area.txtpb index 5886ca8..70b311e 100644 --- a/data/maps/the_great/rooms/Maze Cold Area.txtpb +++ b/data/maps/the_great/rooms/Maze Cold Area.txtpb
@@ -1,5 +1,5 @@
1name: "Maze Cold Area" 1name: "Maze Cold Area"
2display_name: "Courtyard" 2panel_display_name: "Courtyard"
3panels { 3panels {
4 name: "COLD" 4 name: "COLD"
5 path: "Panels/Maze/maze_11" 5 path: "Panels/Maze/maze_11"
diff --git a/data/maps/the_great/rooms/Maze Empty Vestibule.txtpb b/data/maps/the_great/rooms/Maze Empty Vestibule.txtpb index d6f265f..1540ee2 100644 --- a/data/maps/the_great/rooms/Maze Empty Vestibule.txtpb +++ b/data/maps/the_great/rooms/Maze Empty Vestibule.txtpb
@@ -1,2 +1,2 @@
1name: "Maze Empty Vestibule" 1name: "Maze Empty Vestibule"
2display_name: "Courtyard" 2panel_display_name: "Courtyard"
diff --git a/data/maps/the_great/rooms/Maze In Area.txtpb b/data/maps/the_great/rooms/Maze In Area.txtpb index 13597a0..8c556aa 100644 --- a/data/maps/the_great/rooms/Maze In Area.txtpb +++ b/data/maps/the_great/rooms/Maze In Area.txtpb
@@ -1,5 +1,5 @@
1name: "Maze In Area" 1name: "Maze In Area"
2display_name: "Courtyard" 2panel_display_name: "Courtyard"
3panels { 3panels {
4 name: "IN" 4 name: "IN"
5 path: "Panels/Maze/maze_3" 5 path: "Panels/Maze/maze_3"
diff --git a/data/maps/the_great/rooms/Maze Moon Area.txtpb b/data/maps/the_great/rooms/Maze Moon Area.txtpb index b515224..10af4a1 100644 --- a/data/maps/the_great/rooms/Maze Moon Area.txtpb +++ b/data/maps/the_great/rooms/Maze Moon Area.txtpb
@@ -1,5 +1,5 @@
1name: "Maze Moon Area" 1name: "Maze Moon Area"
2display_name: "Courtyard" 2panel_display_name: "Courtyard"
3panels { 3panels {
4 name: "MOON" 4 name: "MOON"
5 path: "Panels/Maze/maze_9" 5 path: "Panels/Maze/maze_9"
diff --git a/data/maps/the_great/rooms/Maze Off Area.txtpb b/data/maps/the_great/rooms/Maze Off Area.txtpb index 2fe7bed..c577129 100644 --- a/data/maps/the_great/rooms/Maze Off Area.txtpb +++ b/data/maps/the_great/rooms/Maze Off Area.txtpb
@@ -1,5 +1,5 @@
1name: "Maze Off Area" 1name: "Maze Off Area"
2display_name: "Courtyard" 2panel_display_name: "Courtyard"
3panels { 3panels {
4 name: "OFF" 4 name: "OFF"
5 path: "Panels/Maze/maze_14" 5 path: "Panels/Maze/maze_14"
diff --git a/data/maps/the_great/rooms/Maze Slice Area.txtpb b/data/maps/the_great/rooms/Maze Slice Area.txtpb index d720501..f59d6e5 100644 --- a/data/maps/the_great/rooms/Maze Slice Area.txtpb +++ b/data/maps/the_great/rooms/Maze Slice Area.txtpb
@@ -1,5 +1,5 @@
1name: "Maze Slice Area" 1name: "Maze Slice Area"
2display_name: "Courtyard" 2panel_display_name: "Courtyard"
3panels { 3panels {
4 name: "SLICE" 4 name: "SLICE"
5 path: "Panels/Maze/maze_4" 5 path: "Panels/Maze/maze_4"
diff --git a/data/maps/the_great/rooms/Maze Smooth Area.txtpb b/data/maps/the_great/rooms/Maze Smooth Area.txtpb index 8145357..156e885 100644 --- a/data/maps/the_great/rooms/Maze Smooth Area.txtpb +++ b/data/maps/the_great/rooms/Maze Smooth Area.txtpb
@@ -1,5 +1,5 @@
1name: "Maze Smooth Area" 1name: "Maze Smooth Area"
2display_name: "Courtyard" 2panel_display_name: "Courtyard"
3panels { 3panels {
4 name: "SMOOTH" 4 name: "SMOOTH"
5 path: "Panels/Maze/maze_5" 5 path: "Panels/Maze/maze_5"
diff --git a/data/maps/the_great/rooms/Maze South Area.txtpb b/data/maps/the_great/rooms/Maze South Area.txtpb index b3708db..e65778d 100644 --- a/data/maps/the_great/rooms/Maze South Area.txtpb +++ b/data/maps/the_great/rooms/Maze South Area.txtpb
@@ -1,5 +1,5 @@
1name: "Maze South Area" 1name: "Maze South Area"
2display_name: "Courtyard" 2panel_display_name: "Courtyard"
3panels { 3panels {
4 name: "SOUTH" 4 name: "SOUTH"
5 path: "Panels/Maze/maze_2" 5 path: "Panels/Maze/maze_2"
diff --git a/data/maps/the_great/rooms/Maze Start.txtpb b/data/maps/the_great/rooms/Maze Start.txtpb index 1e89cbe..16a57f5 100644 --- a/data/maps/the_great/rooms/Maze Start.txtpb +++ b/data/maps/the_great/rooms/Maze Start.txtpb
@@ -1,5 +1,5 @@
1name: "Maze Start" 1name: "Maze Start"
2display_name: "Courtyard" 2panel_display_name: "Courtyard"
3panels { 3panels {
4 name: "OUT" 4 name: "OUT"
5 path: "Panels/Maze/maze_1" 5 path: "Panels/Maze/maze_1"
diff --git a/data/maps/the_great/rooms/Maze Tower.txtpb b/data/maps/the_great/rooms/Maze Tower.txtpb index 6a815aa..44c30d7 100644 --- a/data/maps/the_great/rooms/Maze Tower.txtpb +++ b/data/maps/the_great/rooms/Maze Tower.txtpb
@@ -1,5 +1,5 @@
1name: "Maze Tower" 1name: "Maze Tower"
2display_name: "Courtyard" 2panel_display_name: "Courtyard"
3panels { 3panels {
4 name: "FEEL" 4 name: "FEEL"
5 path: "Panels/Maze/maze_12" 5 path: "Panels/Maze/maze_12"
diff --git a/data/maps/the_great/rooms/Maze Up Area.txtpb b/data/maps/the_great/rooms/Maze Up Area.txtpb index 29f175b..0046cef 100644 --- a/data/maps/the_great/rooms/Maze Up Area.txtpb +++ b/data/maps/the_great/rooms/Maze Up Area.txtpb
@@ -1,5 +1,5 @@
1name: "Maze Up Area" 1name: "Maze Up Area"
2display_name: "Courtyard" 2panel_display_name: "Courtyard"
3panels { 3panels {
4 name: "UP" 4 name: "UP"
5 path: "Panels/Maze/maze_15" 5 path: "Panels/Maze/maze_15"
diff --git a/data/maps/the_great/rooms/Maze Wreck Area.txtpb b/data/maps/the_great/rooms/Maze Wreck Area.txtpb index 6808fc2..5710df5 100644 --- a/data/maps/the_great/rooms/Maze Wreck Area.txtpb +++ b/data/maps/the_great/rooms/Maze Wreck Area.txtpb
@@ -1,5 +1,5 @@
1name: "Maze Wreck Area" 1name: "Maze Wreck Area"
2display_name: "Courtyard" 2panel_display_name: "Courtyard"
3panels { 3panels {
4 name: "WRECK" 4 name: "WRECK"
5 path: "Panels/Maze/maze_8" 5 path: "Panels/Maze/maze_8"
diff --git a/data/maps/the_great/rooms/Nature Room.txtpb b/data/maps/the_great/rooms/Nature Room.txtpb index 9f798f3..464d3a2 100644 --- a/data/maps/the_great/rooms/Nature Room.txtpb +++ b/data/maps/the_great/rooms/Nature Room.txtpb
@@ -1,5 +1,5 @@
1name: "Nature Room" 1name: "Nature Room"
2display_name: "North Landscape" 2panel_display_name: "North Landscape"
3panels { 3panels {
4 name: "SEVERE" 4 name: "SEVERE"
5 path: "Panels/General/nature_2" 5 path: "Panels/General/nature_2"
diff --git a/data/maps/the_great/rooms/North Landscape.txtpb b/data/maps/the_great/rooms/North Landscape.txtpb index 959f351..f738ed3 100644 --- a/data/maps/the_great/rooms/North Landscape.txtpb +++ b/data/maps/the_great/rooms/North Landscape.txtpb
@@ -1,5 +1,5 @@
1name: "North Landscape" 1name: "North Landscape"
2display_name: "North Landscape" 2panel_display_name: "North Landscape"
3panels { 3panels {
4 name: "WEATHER" 4 name: "WEATHER"
5 path: "Panels/General/platforms_1" 5 path: "Panels/General/platforms_1"
@@ -52,11 +52,13 @@ panels {
52keyholders { 52keyholders {
53 name: "X" 53 name: "X"
54 path: "Components/KeyHolders/keyHolderX" 54 path: "Components/KeyHolders/keyHolderX"
55 key: "x"
55} 56}
56ports { 57ports {
57 name: "INVISIBLE" 58 name: "INVISIBLE"
59 display_name: "Eye Worldport"
58 path: "Meshes/Blocks/Warps/worldport20" 60 path: "Meshes/Blocks/Warps/worldport20"
59 orientation: "north" 61 destination { x: 33 y: 0 z: -66.5 }
60 # Note that this can be easily entered from the other side. 62 rotation: 0
61 required_door { name: "Invisible Entrance" } 63 required_door { name: "Invisible Entrance" }
62} 64}
diff --git a/data/maps/the_great/rooms/Outside Jail.txtpb b/data/maps/the_great/rooms/Outside Jail.txtpb index ab30761..d6dfa71 100644 --- a/data/maps/the_great/rooms/Outside Jail.txtpb +++ b/data/maps/the_great/rooms/Outside Jail.txtpb
@@ -1,5 +1,5 @@
1name: "Outside Jail" 1name: "Outside Jail"
2display_name: "Jail" 2panel_display_name: "Jail"
3panels { 3panels {
4 name: "GUT" 4 name: "GUT"
5 path: "Panels/Head/head_1" 5 path: "Panels/Head/head_1"
diff --git a/data/maps/the_great/rooms/Pillar Room.txtpb b/data/maps/the_great/rooms/Pillar Room.txtpb index 01ff309..648b7b4 100644 --- a/data/maps/the_great/rooms/Pillar Room.txtpb +++ b/data/maps/the_great/rooms/Pillar Room.txtpb
@@ -1,5 +1,5 @@
1name: "Pillar Room" 1name: "Pillar Room"
2display_name: "Pillar Room" 2panel_display_name: "Pillar Room"
3panels { 3panels {
4 name: "EYE" 4 name: "EYE"
5 path: "Panels/Impressive/entry_2" 5 path: "Panels/Impressive/entry_2"
diff --git a/data/maps/the_great/rooms/Purple Room.txtpb b/data/maps/the_great/rooms/Purple Room.txtpb index ff9bd9a..12e79e7 100644 --- a/data/maps/the_great/rooms/Purple Room.txtpb +++ b/data/maps/the_great/rooms/Purple Room.txtpb
@@ -1,7 +1,9 @@
1name: "Purple Room" 1name: "Purple Room"
2display_name: "Main Area" 2panel_display_name: "Main Area"
3ports { 3ports {
4 name: "DAEDALUS" 4 name: "DAEDALUS"
5 display_name: "Purple Hallway"
5 path: "Meshes/Blocks/Warps/worldport18" 6 path: "Meshes/Blocks/Warps/worldport18"
6 orientation: "north" 7 destination { x: 158 y: 0 z: 14 }
8 rotation: 180
7} 9}
diff --git a/data/maps/the_great/rooms/Question Room How.txtpb b/data/maps/the_great/rooms/Question Room How.txtpb index 2f759b8..8f087d0 100644 --- a/data/maps/the_great/rooms/Question Room How.txtpb +++ b/data/maps/the_great/rooms/Question Room How.txtpb
@@ -1,17 +1,18 @@
1name: "Question Room How" 1name: "Question Room How"
2display_name: "Question Room" 2panel_display_name: "Question Room"
3panels { 3panels {
4 name: "QUESTION" 4 name: "QUESTION"
5 path: "Panels/Questions/question_3" 5 path: "Panels/Questions/question_3"
6 clue: "question" 6 clue: "question"
7 answer: "how" 7 answer: "how"
8 symbols: EXAMPLE 8 symbols: EXAMPLE
9 # "Panels/Question Proxies/question_3_proxied" <- this is just how again 9 proxies { answer: "how" path: "Panels/Question Proxies/question_3_proxied" }
10 proxies { answer: "who" path: "Panels/Question Proxies/question_3_proxied2" } 10 proxies { answer: "who" path: "Panels/Question Proxies/question_3_proxied2" }
11 proxies { answer: "why" path: "Panels/Question Proxies/question_3_proxied3" } 11 proxies { answer: "why" path: "Panels/Question Proxies/question_3_proxied3" }
12 proxies { answer: "what" path: "Panels/Question Proxies/question_3_proxied4" } 12 proxies { answer: "what" path: "Panels/Question Proxies/question_3_proxied4" }
13 proxies { answer: "when" path: "Panels/Question Proxies/question_3_proxied5" } 13 proxies { answer: "when" path: "Panels/Question Proxies/question_3_proxied5" }
14 proxies { answer: "where" path: "Panels/Question Proxies/question_3_proxied6" } 14 proxies { answer: "where" path: "Panels/Question Proxies/question_3_proxied6" }
15 display_name: "QUESTION (How)"
15} 16}
16paintings { 17paintings {
17 name: "WHY" 18 name: "WHY"
diff --git a/data/maps/the_great/rooms/Question Room What.txtpb b/data/maps/the_great/rooms/Question Room What.txtpb index 9cfd667..a61ccef 100644 --- a/data/maps/the_great/rooms/Question Room What.txtpb +++ b/data/maps/the_great/rooms/Question Room What.txtpb
@@ -1,15 +1,16 @@
1name: "Question Room What" 1name: "Question Room What"
2display_name: "Question Room" 2panel_display_name: "Question Room"
3panels { 3panels {
4 name: "QUESTION" 4 name: "QUESTION"
5 path: "Panels/Questions/question_4" 5 path: "Panels/Questions/question_4"
6 clue: "question" 6 clue: "question"
7 answer: "what" 7 answer: "what"
8 symbols: EXAMPLE 8 symbols: EXAMPLE
9 proxies { answer: "why" path: "Panels/Question Proxies/question_4_proxied" } 9 proxies { answer: "what" path: "Panels/Question Proxies/question_4_proxied" }
10 proxies { answer: "who" path: "Panels/Question Proxies/question_4_proxied2" } 10 proxies { answer: "why" path: "Panels/Question Proxies/question_4_proxied2" }
11 proxies { answer: "where" path: "Panels/Question Proxies/question_4_proxied3" } 11 proxies { answer: "when" path: "Panels/Question Proxies/question_4_proxied3" }
12 proxies { answer: "how" path: "Panels/Question Proxies/question_4_proxied4" } 12 proxies { answer: "how" path: "Panels/Question Proxies/question_4_proxied4" }
13 # "Panels/Question Proxies/question_4_proxied5" <- this is just what again 13 proxies { answer: "who" path: "Panels/Question Proxies/question_4_proxied5" }
14 proxies { answer: "when" path: "Panels/Question Proxies/question_4_proxied6" } 14 proxies { answer: "where" path: "Panels/Question Proxies/question_4_proxied6" }
15 display_name: "QUESTION (What)"
15} 16}
diff --git a/data/maps/the_great/rooms/Question Room When.txtpb b/data/maps/the_great/rooms/Question Room When.txtpb index e046edd..b3ee2db 100644 --- a/data/maps/the_great/rooms/Question Room When.txtpb +++ b/data/maps/the_great/rooms/Question Room When.txtpb
@@ -1,5 +1,5 @@
1name: "Question Room When" 1name: "Question Room When"
2display_name: "Question Room" 2panel_display_name: "Question Room"
3panels { 3panels {
4 name: "QUESTION" 4 name: "QUESTION"
5 path: "Panels/Questions/question_1" 5 path: "Panels/Questions/question_1"
@@ -8,10 +8,11 @@ panels {
8 symbols: EXAMPLE 8 symbols: EXAMPLE
9 proxies { answer: "when" path: "Panels/Question Proxies/question_1_proxied" } 9 proxies { answer: "when" path: "Panels/Question Proxies/question_1_proxied" }
10 proxies { answer: "why" path: "Panels/Question Proxies/question_1_proxied2" } 10 proxies { answer: "why" path: "Panels/Question Proxies/question_1_proxied2" }
11 # "Panels/Question Proxies/question_1_proxied3" <- this is just what again 11 proxies { answer: "what" path: "Panels/Question Proxies/question_1_proxied3" }
12 proxies { answer: "who" path: "Panels/Question Proxies/question_1_proxied4" } 12 proxies { answer: "who" path: "Panels/Question Proxies/question_1_proxied4" }
13 proxies { answer: "how" path: "Panels/Question Proxies/question_1_proxied5" } 13 proxies { answer: "how" path: "Panels/Question Proxies/question_1_proxied5" }
14 proxies { answer: "where" path: "Panels/Question Proxies/question_1_proxied6" } 14 proxies { answer: "where" path: "Panels/Question Proxies/question_1_proxied6" }
15 display_name: "QUESTION (When)"
15} 16}
16paintings { 17paintings {
17 name: "WHY" 18 name: "WHY"
diff --git a/data/maps/the_great/rooms/Question Room Who.txtpb b/data/maps/the_great/rooms/Question Room Who.txtpb index cbaba4b..eb80882 100644 --- a/data/maps/the_great/rooms/Question Room Who.txtpb +++ b/data/maps/the_great/rooms/Question Room Who.txtpb
@@ -1,5 +1,5 @@
1name: "Question Room Who" 1name: "Question Room Who"
2display_name: "Question Room" 2panel_display_name: "Question Room"
3panels { 3panels {
4 name: "QUESTION" 4 name: "QUESTION"
5 path: "Panels/Questions/question_2" 5 path: "Panels/Questions/question_2"
@@ -7,9 +7,10 @@ panels {
7 answer: "who" 7 answer: "who"
8 symbols: EXAMPLE 8 symbols: EXAMPLE
9 proxies { answer: "why" path: "Panels/Question Proxies/question_2_proxied" } 9 proxies { answer: "why" path: "Panels/Question Proxies/question_2_proxied" }
10 # "Panels/Question Proxies/question_2_proxied2" <- this is just who again 10 proxies { answer: "who" path: "Panels/Question Proxies/question_2_proxied2" }
11 proxies { answer: "where" path: "Panels/Question Proxies/question_2_proxied3" } 11 proxies { answer: "where" path: "Panels/Question Proxies/question_2_proxied3" }
12 proxies { answer: "how" path: "Panels/Question Proxies/question_2_proxied4" } 12 proxies { answer: "how" path: "Panels/Question Proxies/question_2_proxied4" }
13 proxies { answer: "what" path: "Panels/Question Proxies/question_2_proxied5" } 13 proxies { answer: "what" path: "Panels/Question Proxies/question_2_proxied5" }
14 proxies { answer: "when" path: "Panels/Question Proxies/question_2_proxied6" } 14 proxies { answer: "when" path: "Panels/Question Proxies/question_2_proxied6" }
15 display_name: "QUESTION (Who)"
15} 16}
diff --git a/data/maps/the_great/rooms/Salmon Room.txtpb b/data/maps/the_great/rooms/Salmon Room.txtpb index 96efd1a..8458829 100644 --- a/data/maps/the_great/rooms/Salmon Room.txtpb +++ b/data/maps/the_great/rooms/Salmon Room.txtpb
@@ -1,7 +1,9 @@
1name: "Salmon Room" 1name: "Salmon Room"
2display_name: "Main Area" 2panel_display_name: "Main Area"
3ports { 3ports {
4 name: "BETWEEN" 4 name: "BETWEEN"
5 display_name: "Salmon Hallway"
5 path: "Meshes/Blocks/Warps/worldport11" 6 path: "Meshes/Blocks/Warps/worldport11"
6 orientation: "east" 7 destination { x: 83 y: 0 z: -21 }
8 rotation: 90
7} 9}
diff --git a/data/maps/the_great/rooms/Talented Entrance.txtpb b/data/maps/the_great/rooms/Talented Entrance.txtpb index 038c7e7..53c27dc 100644 --- a/data/maps/the_great/rooms/Talented Entrance.txtpb +++ b/data/maps/the_great/rooms/Talented Entrance.txtpb
@@ -1,7 +1,9 @@
1name: "Talented Entrance" 1name: "Talented Entrance"
2display_name: "Question Room" 2panel_display_name: "Question Room"
3ports { 3ports {
4 name: "TALENTED" 4 name: "TALENTED"
5 display_name: "Under Question Room Worldport"
5 path: "Meshes/Blocks/Warps/worldport14" 6 path: "Meshes/Blocks/Warps/worldport14"
6 orientation: "south" 7 destination { x: 109 y: -6 z: -26.5 }
8 rotation: 0
7} 9}
diff --git a/data/maps/the_great/rooms/Under Question Room.txtpb b/data/maps/the_great/rooms/Under Question Room.txtpb index 249c0b4..db751bb 100644 --- a/data/maps/the_great/rooms/Under Question Room.txtpb +++ b/data/maps/the_great/rooms/Under Question Room.txtpb
@@ -1,10 +1,12 @@
1name: "Under Question Room" 1name: "Under Question Room"
2display_name: "Question Room" 2panel_display_name: "Question Room"
3panels { 3panels {
4 name: "QUESTION" 4 name: "QUESTION"
5 path: "Panels/General/question_1" 5 path: "Panels/General/question_1"
6 clue: "question" 6 clue: "question"
7 answer: "which" 7 answer: "which"
8 symbols: EXAMPLE 8 symbols: EXAMPLE
9 proxies { answer: "which" path: "Panels/General/question_1_proxy_1" }
9 proxies { answer: "where" path: "Panels/General/question_1_proxy_2" } 10 proxies { answer: "where" path: "Panels/General/question_1_proxy_2" }
11 display_name: "QUESTION (Where)"
10} 12}
diff --git a/data/maps/the_great/rooms/West Side.txtpb b/data/maps/the_great/rooms/West Side.txtpb index 4723213..9f098ee 100644 --- a/data/maps/the_great/rooms/West Side.txtpb +++ b/data/maps/the_great/rooms/West Side.txtpb
@@ -1,5 +1,5 @@
1name: "West Side" 1name: "West Side"
2display_name: "West Side" 2panel_display_name: "West Side"
3panels { 3panels {
4 name: "ERASE" 4 name: "ERASE"
5 path: "Panels/General/entry_9" 5 path: "Panels/General/entry_9"
@@ -63,17 +63,24 @@ paintings {
63} 63}
64ports { 64ports {
65 name: "IMPRESSIVE" 65 name: "IMPRESSIVE"
66 display_name: "Impressive Entrance"
66 path: "Meshes/Blocks/Warps/worldport2" 67 path: "Meshes/Blocks/Warps/worldport2"
67 orientation: "south" 68 destination { x: -34 y: 0 z: 22.5 }
69 rotation: 0
68} 70}
69ports { 71ports {
70 name: "CC" 72 name: "CC"
73 display_name: "Control Center"
71 path: "Meshes/Blocks/Warps/worldport9" 74 path: "Meshes/Blocks/Warps/worldport9"
72 orientation: "north" 75 destination { x: -59 y: 0 z: -50.5 }
76 rotation: 180
73} 77}
74ports { 78ports {
75 name: "PARTIAL" 79 name: "PARTIAL"
80 display_name: "Red Hallway"
76 path: "Meshes/Blocks/Warps/worldport7" 81 path: "Meshes/Blocks/Warps/worldport7"
77 orientation: "east" 82 destination { x: -62 y: 0 z: 11 }
83 rotation: 90
78 # ER with this is weird; make sure to place on the surface 84 # ER with this is weird; make sure to place on the surface
85 required_door { name: "Partial Entrance" }
79} 86}
diff --git a/data/maps/the_great/rooms/Whole Room.txtpb b/data/maps/the_great/rooms/Whole Room.txtpb index 2f5c855..daa174c 100644 --- a/data/maps/the_great/rooms/Whole Room.txtpb +++ b/data/maps/the_great/rooms/Whole Room.txtpb
@@ -1,5 +1,5 @@
1name: "Whole Room" 1name: "Whole Room"
2display_name: "North Landscape" 2panel_display_name: "North Landscape"
3panels { 3panels {
4 name: "VAULT" 4 name: "VAULT"
5 path: "Panels/Whole Room/whole_1" 5 path: "Panels/Whole Room/whole_1"
diff --git a/data/maps/the_great/rooms/Y Room.txtpb b/data/maps/the_great/rooms/Y Room.txtpb index b20420c..46c83ea 100644 --- a/data/maps/the_great/rooms/Y Room.txtpb +++ b/data/maps/the_great/rooms/Y Room.txtpb
@@ -1,5 +1,5 @@
1name: "Y Room" 1name: "Y Room"
2display_name: "Question Room" 2panel_display_name: "Question Room"
3letters { 3letters {
4 key: "y" 4 key: "y"
5 path: "Components/Collectables/y" 5 path: "Components/Collectables/y"
diff --git a/data/maps/the_great/rooms/Zero Room.txtpb b/data/maps/the_great/rooms/Zero Room.txtpb index dcbe067..54675bf 100644 --- a/data/maps/the_great/rooms/Zero Room.txtpb +++ b/data/maps/the_great/rooms/Zero Room.txtpb
@@ -1,5 +1,5 @@
1name: "Zero Room" 1name: "Zero Room"
2display_name: "Zero Room" 2panel_display_name: "Zero Room"
3panels { 3panels {
4 name: "HERO" 4 name: "HERO"
5 path: "Panels/General/zero_1" 5 path: "Panels/General/zero_1"
diff --git a/data/maps/the_hinterlands/rooms/Main Area.txtpb b/data/maps/the_hinterlands/rooms/Main Area.txtpb index ad44b38..5cd626b 100644 --- a/data/maps/the_hinterlands/rooms/Main Area.txtpb +++ b/data/maps/the_hinterlands/rooms/Main Area.txtpb
@@ -1,13 +1,16 @@
1name: "Main Area" 1name: "Main Area"
2display_name: "Main Area"
3# I'm probably not going to include any of the panels in here. 2# I'm probably not going to include any of the panels in here.
4ports { 3ports {
5 name: "RIGHT" 4 name: "RIGHT"
5 display_name: "South Worldport"
6 path: "Components/Warps/worldport" 6 path: "Components/Warps/worldport"
7 orientation: "east" 7 destination { x: 30 y: 0 z: 19 }
8 rotation: 270
8} 9}
9ports { 10ports {
10 name: "LEFT" 11 name: "LEFT"
12 display_name: "North Worldport"
11 path: "Components/Warps/worldport2" 13 path: "Components/Warps/worldport2"
12 orientation: "east" 14 destination { x: 30 y: 0 z: -76 }
15 rotation: 270
13} 16}
diff --git a/data/maps/the_hive/doors.txtpb b/data/maps/the_hive/doors.txtpb index 4d86e13..48dc892 100644 --- a/data/maps/the_hive/doors.txtpb +++ b/data/maps/the_hive/doors.txtpb
@@ -1,6 +1,7 @@
1doors { 1doors {
2 name: "Room 8 Door" 2 name: "Room 8 Door"
3 type: LOCATION_ONLY 3 type: STANDARD
4 receivers: "Components/Doors/entry_10"
4 panels { room: "Main Area" name: "STEM" } 5 panels { room: "Main Area" name: "STEM" }
5 panels { room: "Main Area" name: "PETAL" } 6 panels { room: "Main Area" name: "PETAL" }
6 panels { room: "Main Area" name: "SOIL" } 7 panels { room: "Main Area" name: "SOIL" }
diff --git a/data/maps/the_hive/rooms/Main Area.txtpb b/data/maps/the_hive/rooms/Main Area.txtpb index de7bdec..aaf8e2a 100644 --- a/data/maps/the_hive/rooms/Main Area.txtpb +++ b/data/maps/the_hive/rooms/Main Area.txtpb
@@ -1,5 +1,4 @@
1name: "Main Area" 1name: "Main Area"
2display_name: "Hive"
3panels { 2panels {
4 name: "ASP" 3 name: "ASP"
5 path: "Panels/Room 1/panel_1" 4 path: "Panels/Room 1/panel_1"
@@ -269,24 +268,33 @@ panels {
269keyholders { 268keyholders {
270 name: "B" 269 name: "B"
271 path: "Components/KeyHolders/keyHolderB" 270 path: "Components/KeyHolders/keyHolderB"
271 key: "b"
272} 272}
273ports { 273ports {
274 name: "DAED1" 274 name: "DAED1"
275 display_name: "Blue Area Worldport"
275 path: "Components/Warps/worldport" 276 path: "Components/Warps/worldport"
276 orientation: "west" 277 destination { x: -1.5 y: 0 z: 24 }
278 rotation: 270
277} 279}
278ports { 280ports {
279 name: "DAED2" 281 name: "DAED2"
282 display_name: "Pink Area South Worldport"
280 path: "Components/Warps/worldport2" 283 path: "Components/Warps/worldport2"
281 orientation: "west" 284 destination { x: -26.5 y: 0 z: -22 }
285 rotation: 270
282} 286}
283ports { 287ports {
284 name: "DAED3" 288 name: "DAED3"
289 display_name: "Lime Area Worldport"
285 path: "Components/Warps/worldport3" 290 path: "Components/Warps/worldport3"
286 orientation: "east" 291 destination { x: -44.5 y: 0 z: -13 }
292 rotation: 90
287} 293}
288ports { 294ports {
289 name: "GREAT" 295 name: "GREAT"
296 display_name: "Pink Area North Worldport"
290 path: "Components/Warps/worldport4" 297 path: "Components/Warps/worldport4"
291 orientation: "west" 298 destination { x: -29.5 y: 0 z: -62 }
299 rotation: 270
292} 300}
diff --git a/data/maps/the_hive/rooms/Mastery Room.txtpb b/data/maps/the_hive/rooms/Mastery Room.txtpb index 1884cfd..5e3326c 100644 --- a/data/maps/the_hive/rooms/Mastery Room.txtpb +++ b/data/maps/the_hive/rooms/Mastery Room.txtpb
@@ -1,5 +1,4 @@
1name: "Mastery Room" 1name: "Mastery Room"
2display_name: "Hive"
3masteries { 2masteries {
4 name: "MASTERY" 3 name: "MASTERY"
5 path: "Components/Collectables/smiley" 4 path: "Components/Collectables/smiley"
diff --git a/data/maps/the_hive/rooms/Room 8.txtpb b/data/maps/the_hive/rooms/Room 8.txtpb index e8cbb60..c96440c 100644 --- a/data/maps/the_hive/rooms/Room 8.txtpb +++ b/data/maps/the_hive/rooms/Room 8.txtpb
@@ -1,5 +1,4 @@
1name: "Room 8" 1name: "Room 8"
2display_name: "Hive"
3panels { 2panels {
4 name: "BUMBLE" 3 name: "BUMBLE"
5 path: "Panels/Room 8/panel_1" 4 path: "Panels/Room 8/panel_1"
diff --git a/data/maps/the_impressive/rooms/Green Eye.txtpb b/data/maps/the_impressive/rooms/Green Eye.txtpb index 195099d..aa31b07 100644 --- a/data/maps/the_impressive/rooms/Green Eye.txtpb +++ b/data/maps/the_impressive/rooms/Green Eye.txtpb
@@ -1,5 +1,5 @@
1name: "Green Eye" 1name: "Green Eye"
2display_name: "Impressive" 2panel_display_name: "Outside"
3panels { 3panels {
4 name: "RETURN" 4 name: "RETURN"
5 path: "Panels/entry_5" 5 path: "Panels/entry_5"
@@ -22,6 +22,8 @@ panels {
22} 22}
23ports { 23ports {
24 name: "PLAZA" 24 name: "PLAZA"
25 display_name: "Green Hallway"
25 path: "Components/Warps/worldport3" 26 path: "Components/Warps/worldport3"
26 orientation: "east" 27 destination { x: -33 y: 0 z: 1 }
28 rotation: 90
27} 29}
diff --git a/data/maps/the_impressive/rooms/Lobby.txtpb b/data/maps/the_impressive/rooms/Lobby.txtpb index 5492d67..577a051 100644 --- a/data/maps/the_impressive/rooms/Lobby.txtpb +++ b/data/maps/the_impressive/rooms/Lobby.txtpb
@@ -1,5 +1,5 @@
1name: "Lobby" 1name: "Lobby"
2display_name: "Impressive" 2panel_display_name: "Outside"
3panels { 3panels {
4 name: "RIGHT" 4 name: "RIGHT"
5 path: "Panels/entry_1" 5 path: "Panels/entry_1"
@@ -9,6 +9,8 @@ panels {
9} 9}
10ports { 10ports {
11 name: "GREAT" 11 name: "GREAT"
12 display_name: "Main Entrance"
12 path: "Components/Warps/worldport" 13 path: "Components/Warps/worldport"
13 orientation: "south" 14 destination { x: 0 y: 0 z: 11.5 }
15 rotation: 0
14} 16}
diff --git a/data/maps/the_impressive/rooms/M Room.txtpb b/data/maps/the_impressive/rooms/M Room.txtpb index 1796bb3..2cc71be 100644 --- a/data/maps/the_impressive/rooms/M Room.txtpb +++ b/data/maps/the_impressive/rooms/M Room.txtpb
@@ -1,5 +1,5 @@
1name: "M Room" 1name: "M Room"
2display_name: "Impressive" 2panel_display_name: "Inside"
3letters { 3letters {
4 key: "m" 4 key: "m"
5 path: "Components/Collectables/collectable" 5 path: "Components/Collectables/collectable"
diff --git a/data/maps/the_impressive/rooms/M2 Room.txtpb b/data/maps/the_impressive/rooms/M2 Room.txtpb index d229cbc..3684441 100644 --- a/data/maps/the_impressive/rooms/M2 Room.txtpb +++ b/data/maps/the_impressive/rooms/M2 Room.txtpb
@@ -1,5 +1,5 @@
1name: "M2 Room" 1name: "M2 Room"
2display_name: "Impressive" 2panel_display_name: "Inside"
3letters { 3letters {
4 key: "m" 4 key: "m"
5 level2: true 5 level2: true
diff --git a/data/maps/the_impressive/rooms/Side Area.txtpb b/data/maps/the_impressive/rooms/Side Area.txtpb index 7c3dbd8..d1b28a3 100644 --- a/data/maps/the_impressive/rooms/Side Area.txtpb +++ b/data/maps/the_impressive/rooms/Side Area.txtpb
@@ -1,5 +1,5 @@
1name: "Side Area" 1name: "Side Area"
2display_name: "Impressive" 2panel_display_name: "Outside"
3panels { 3panels {
4 name: "COLOR" 4 name: "COLOR"
5 path: "Panels/entry_4" 5 path: "Panels/entry_4"
@@ -9,6 +9,8 @@ panels {
9} 9}
10ports { 10ports {
11 name: "FOURROOMS" 11 name: "FOURROOMS"
12 display_name: "Four Rooms Entrance"
12 path: "Components/Warps/worldport2" 13 path: "Components/Warps/worldport2"
13 orientation: "south" 14 destination { x: -27 y: 0 z: 25.5 }
15 rotation: 0
14} 16}
diff --git a/data/maps/the_impressive/rooms/W Room.txtpb b/data/maps/the_impressive/rooms/W Room.txtpb index c0616f9..21f1eab 100644 --- a/data/maps/the_impressive/rooms/W Room.txtpb +++ b/data/maps/the_impressive/rooms/W Room.txtpb
@@ -1,5 +1,5 @@
1name: "W Room" 1name: "W Room"
2display_name: "Impressive" 2panel_display_name: "Inside"
3letters { 3letters {
4 key: "w" 4 key: "w"
5 path: "Components/Collectables/collectable2" 5 path: "Components/Collectables/collectable2"
diff --git a/data/maps/the_impressive/rooms/WM Room.txtpb b/data/maps/the_impressive/rooms/WM Room.txtpb index a66f614..dce77ed 100644 --- a/data/maps/the_impressive/rooms/WM Room.txtpb +++ b/data/maps/the_impressive/rooms/WM Room.txtpb
@@ -1,5 +1,5 @@
1name: "WM Room" 1name: "WM Room"
2display_name: "Impressive" 2panel_display_name: "Inside"
3panels { 3panels {
4 name: "LEFT" 4 name: "LEFT"
5 path: "Panels/entry_2" 5 path: "Panels/entry_2"
@@ -13,4 +13,5 @@ panels {
13 clue: "right" 13 clue: "right"
14 answer: "right" 14 answer: "right"
15 proxies { answer: "left" path: "Panels/proxied_1" } 15 proxies { answer: "left" path: "Panels/proxied_1" }
16 proxies { answer: "right" path: "Panels/proxied_2" }
16} 17}
diff --git a/data/maps/the_invisible/rooms/Entrance.txtpb b/data/maps/the_invisible/rooms/Entrance.txtpb index 7fafcb5..c74b968 100644 --- a/data/maps/the_invisible/rooms/Entrance.txtpb +++ b/data/maps/the_invisible/rooms/Entrance.txtpb
@@ -1,5 +1,4 @@
1name: "Entrance" 1name: "Entrance"
2display_name: "Invisible"
3panels { 2panels {
4 name: "VISIBLE" 3 name: "VISIBLE"
5 path: "Panels/Room_1/panel_1" 4 path: "Panels/Room_1/panel_1"
@@ -9,6 +8,8 @@ panels {
9} 8}
10ports { 9ports {
11 name: "ENTRY" 10 name: "ENTRY"
11 display_name: "Entrance"
12 path: "Components/Warps/worldport2" 12 path: "Components/Warps/worldport2"
13 orientation: "north" 13 destination { x: 0 y: 0 z: -57 }
14 rotation: 180
14} 15}
diff --git a/data/maps/the_invisible/rooms/Maze.txtpb b/data/maps/the_invisible/rooms/Maze.txtpb index 4461f08..46f3fbc 100644 --- a/data/maps/the_invisible/rooms/Maze.txtpb +++ b/data/maps/the_invisible/rooms/Maze.txtpb
@@ -1,11 +1,13 @@
1name: "Maze" 1name: "Maze"
2display_name: "Invisible"
3masteries { 2masteries {
4 name: "MASTERY" 3 name: "MASTERY"
5 path: "Components/Collectables/smiley" 4 path: "Components/Collectables/smiley"
6} 5}
7ports { 6ports {
8 name: "ENTRY" 7 name: "ENTRY"
8 display_name: "Exit"
9 path: "Components/Warps/worldport" 9 path: "Components/Warps/worldport"
10 orientation: "south" 10 # Should this be shuffleable? It skips the maze lol.
11 destination { x: 0 y: 0 z: 9.5 }
12 rotation: 0
11} 13}
diff --git a/data/maps/the_jubilant/rooms/J Room.txtpb b/data/maps/the_jubilant/rooms/J Room.txtpb index 35abc54..19425f1 100644 --- a/data/maps/the_jubilant/rooms/J Room.txtpb +++ b/data/maps/the_jubilant/rooms/J Room.txtpb
@@ -1,5 +1,4 @@
1name: "J Room" 1name: "J Room"
2display_name: "Jubilant"
3letters { 2letters {
4 key: "j" 3 key: "j"
5 path: "Components/Collectables/q" # yeah lol 4 path: "Components/Collectables/q" # yeah lol
diff --git a/data/maps/the_jubilant/rooms/Main Area.txtpb b/data/maps/the_jubilant/rooms/Main Area.txtpb index 3d7d31f..b38fafd 100644 --- a/data/maps/the_jubilant/rooms/Main Area.txtpb +++ b/data/maps/the_jubilant/rooms/Main Area.txtpb
@@ -1,5 +1,4 @@
1name: "Main Area" 1name: "Main Area"
2display_name: "Jubilant"
3panels { 2panels {
4 name: "GEMSTONE" 3 name: "GEMSTONE"
5 path: "Panels/Main/panel_1" 4 path: "Panels/Main/panel_1"
@@ -98,6 +97,8 @@ panels {
98} 97}
99ports { 98ports {
100 name: "GREAT" 99 name: "GREAT"
100 display_name: "Entrance"
101 path: "Components/Warps/worldport" 101 path: "Components/Warps/worldport"
102 orientation: "west" 102 destination { x: -3 y: 0 z: 9 }
103 rotation: 270
103} 104}
diff --git a/data/maps/the_jubilant/rooms/Side Area.txtpb b/data/maps/the_jubilant/rooms/Side Area.txtpb index 0e904aa..807f044 100644 --- a/data/maps/the_jubilant/rooms/Side Area.txtpb +++ b/data/maps/the_jubilant/rooms/Side Area.txtpb
@@ -1,5 +1,4 @@
1name: "Side Area" 1name: "Side Area"
2display_name: "Jubilant"
3panels { 2panels {
4 name: "CALLBACK" 3 name: "CALLBACK"
5 path: "Panels/Back Helpers/back_1" 4 path: "Panels/Back Helpers/back_1"
@@ -39,4 +38,5 @@ panels {
39keyholders { 38keyholders {
40 name: "J" 39 name: "J"
41 path: "Components/KeyHolders/keyHolderJ" 40 path: "Components/KeyHolders/keyHolderJ"
41 key: "j"
42} 42}
diff --git a/data/maps/the_keen/rooms/K Room.txtpb b/data/maps/the_keen/rooms/K Room.txtpb index 3485856..d8108f5 100644 --- a/data/maps/the_keen/rooms/K Room.txtpb +++ b/data/maps/the_keen/rooms/K Room.txtpb
@@ -1,5 +1,4 @@
1name: "K Room" 1name: "K Room"
2display_name: "Keen"
3letters { 2letters {
4 key: "k" 3 key: "k"
5 path: "Components/Collectables/collectable" 4 path: "Components/Collectables/collectable"
diff --git a/data/maps/the_keen/rooms/Main Area.txtpb b/data/maps/the_keen/rooms/Main Area.txtpb index 616e7e7..32d399a 100644 --- a/data/maps/the_keen/rooms/Main Area.txtpb +++ b/data/maps/the_keen/rooms/Main Area.txtpb
@@ -1,5 +1,4 @@
1name: "Main Area" 1name: "Main Area"
2display_name: "Keen"
3panels { 2panels {
4 name: "TIN (1)" 3 name: "TIN (1)"
5 path: "Panels/entry_3" 4 path: "Panels/entry_3"
@@ -70,6 +69,8 @@ panels {
70} 69}
71ports { 70ports {
72 name: "GREAT" 71 name: "GREAT"
72 display_name: "Entrance"
73 path: "Components/Warps/worldport" 73 path: "Components/Warps/worldport"
74 orientation: "south" 74 destination { x: 0 y: 0 z: 7.5 }
75 rotation: 0
75} 76}
diff --git a/data/maps/the_liberated/doors.txtpb b/data/maps/the_liberated/doors.txtpb index becddf9..a7d3c24 100644 --- a/data/maps/the_liberated/doors.txtpb +++ b/data/maps/the_liberated/doors.txtpb
@@ -11,4 +11,5 @@ doors {
11 panels { room: "Puzzle Room" name: "WOLF" } 11 panels { room: "Puzzle Room" name: "WOLF" }
12 panels { room: "Puzzle Room" name: "FOOT" } 12 panels { room: "Puzzle Room" name: "FOOT" }
13 location_room: "Puzzle Room" 13 location_room: "Puzzle Room"
14 location_name: "Puzzles"
14} 15}
diff --git a/data/maps/the_liberated/rooms/Painting Room.txtpb b/data/maps/the_liberated/rooms/Painting Room.txtpb index 025281a..f22929c 100644 --- a/data/maps/the_liberated/rooms/Painting Room.txtpb +++ b/data/maps/the_liberated/rooms/Painting Room.txtpb
@@ -1,5 +1,4 @@
1name: "Painting Room" 1name: "Painting Room"
2display_name: "Liberated"
3paintings { 2paintings {
4 name: "PYRAMID" 3 name: "PYRAMID"
5 path: "Components/triangle" 4 path: "Components/triangle"
diff --git a/data/maps/the_liberated/rooms/Puzzle Room.txtpb b/data/maps/the_liberated/rooms/Puzzle Room.txtpb index dcb29c4..2103bfa 100644 --- a/data/maps/the_liberated/rooms/Puzzle Room.txtpb +++ b/data/maps/the_liberated/rooms/Puzzle Room.txtpb
@@ -1,5 +1,4 @@
1name: "Puzzle Room" 1name: "Puzzle Room"
2display_name: "Liberated"
3panels { 2panels {
4 name: "CORPSE" 3 name: "CORPSE"
5 path: "Panels/entry_1" 4 path: "Panels/entry_1"
@@ -58,6 +57,8 @@ panels {
58} 57}
59ports { 58ports {
60 name: "ENTRY" 59 name: "ENTRY"
60 display_name: "Entrance"
61 path: "Components/Warps/worldport" 61 path: "Components/Warps/worldport"
62 orientation: "south" 62 destination { x: 0 y: 0 z: 7.5 }
63 rotation: 0
63} 64}
diff --git a/data/maps/the_linear/doors.txtpb b/data/maps/the_linear/doors.txtpb index 63d8ae8..9a57158 100644 --- a/data/maps/the_linear/doors.txtpb +++ b/data/maps/the_linear/doors.txtpb
@@ -10,4 +10,5 @@ doors {
10 panels { room: "Room" name: "INTO" } 10 panels { room: "Room" name: "INTO" }
11 panels { room: "Room" name: "NOR" } 11 panels { room: "Room" name: "NOR" }
12 location_room: "Room" 12 location_room: "Room"
13 location_name: "Gravestone"
13} 14}
diff --git a/data/maps/the_linear/rooms/Room.txtpb b/data/maps/the_linear/rooms/Room.txtpb index abb89c8..ac03fd9 100644 --- a/data/maps/the_linear/rooms/Room.txtpb +++ b/data/maps/the_linear/rooms/Room.txtpb
@@ -1,5 +1,4 @@
1name: "Room" 1name: "Room"
2display_name: "Room"
3panels { 2panels {
4 name: "HORN" 3 name: "HORN"
5 path: "Panels/entry_1" 4 path: "Panels/entry_1"
@@ -58,6 +57,8 @@ panels {
58} 57}
59ports { 58ports {
60 name: "GREAT" 59 name: "GREAT"
60 display_name: "Entrance"
61 path: "Components/Warps/worldport" 61 path: "Components/Warps/worldport"
62 orientation: "south" 62 destination { x: 0 y: 0 z: 7.5 }
63 rotation: 0
63} 64}
diff --git a/data/maps/the_lionized/rooms/E2 Room.txtpb b/data/maps/the_lionized/rooms/E2 Room.txtpb index b07d820..e8f81c1 100644 --- a/data/maps/the_lionized/rooms/E2 Room.txtpb +++ b/data/maps/the_lionized/rooms/E2 Room.txtpb
@@ -1,5 +1,4 @@
1name: "E2 Room" 1name: "E2 Room"
2display_name: "Lionized"
3letters { 2letters {
4 key: "e" 3 key: "e"
5 level2: true 4 level2: true
diff --git a/data/maps/the_lionized/rooms/Puzzle Room.txtpb b/data/maps/the_lionized/rooms/Puzzle Room.txtpb index 5754c71..3a5e267 100644 --- a/data/maps/the_lionized/rooms/Puzzle Room.txtpb +++ b/data/maps/the_lionized/rooms/Puzzle Room.txtpb
@@ -1,5 +1,4 @@
1name: "Puzzle Room" 1name: "Puzzle Room"
2display_name: "Lionized"
3panels { 2panels {
4 name: "CHILD" 3 name: "CHILD"
5 path: "Panels/entry_1" 4 path: "Panels/entry_1"
@@ -58,6 +57,8 @@ panels {
58} 57}
59ports { 58ports {
60 name: "ENTRY" 59 name: "ENTRY"
60 display_name: "Entrance"
61 path: "Components/Warps/worldport" 61 path: "Components/Warps/worldport"
62 orientation: "south" 62 destination { x: 0 y: 0 z: 6.5 }
63 rotation: 0
63} 64}
diff --git a/data/maps/the_literate/doors.txtpb b/data/maps/the_literate/doors.txtpb index 480f54d..d17d02b 100644 --- a/data/maps/the_literate/doors.txtpb +++ b/data/maps/the_literate/doors.txtpb
@@ -11,4 +11,5 @@ doors {
11 panels { room: "Puzzle Room" name: "STICK" } 11 panels { room: "Puzzle Room" name: "STICK" }
12 panels { room: "Puzzle Room" name: "BREAD" } 12 panels { room: "Puzzle Room" name: "BREAD" }
13 location_room: "Puzzle Room" 13 location_room: "Puzzle Room"
14 location_name: "Puzzles"
14} 15}
diff --git a/data/maps/the_literate/rooms/Painting Room.txtpb b/data/maps/the_literate/rooms/Painting Room.txtpb index 254e174..f22929c 100644 --- a/data/maps/the_literate/rooms/Painting Room.txtpb +++ b/data/maps/the_literate/rooms/Painting Room.txtpb
@@ -1,5 +1,4 @@
1name: "Painting Room" 1name: "Painting Room"
2display_name: "Literate"
3paintings { 2paintings {
4 name: "PYRAMID" 3 name: "PYRAMID"
5 path: "Components/triangle" 4 path: "Components/triangle"
diff --git a/data/maps/the_literate/rooms/Puzzle Room.txtpb b/data/maps/the_literate/rooms/Puzzle Room.txtpb index 610a87a..c65d408 100644 --- a/data/maps/the_literate/rooms/Puzzle Room.txtpb +++ b/data/maps/the_literate/rooms/Puzzle Room.txtpb
@@ -1,5 +1,4 @@
1name: "Puzzle Room" 1name: "Puzzle Room"
2display_name: "Literate"
3panels { 2panels {
4 name: "WATER" 3 name: "WATER"
5 path: "Panels/entry_1" 4 path: "Panels/entry_1"
@@ -58,6 +57,8 @@ panels {
58} 57}
59ports { 58ports {
60 name: "ENTRY" 59 name: "ENTRY"
60 display_name: "Entrance"
61 path: "Components/Warps/worldport" 61 path: "Components/Warps/worldport"
62 orientation: "south" 62 destination { x: 0 y: 0 z: 7.5 }
63 rotation: 0
63} 64}
diff --git a/data/maps/the_lively/rooms/L2 Room.txtpb b/data/maps/the_lively/rooms/L2 Room.txtpb index 094ab10..cd75bbd 100644 --- a/data/maps/the_lively/rooms/L2 Room.txtpb +++ b/data/maps/the_lively/rooms/L2 Room.txtpb
@@ -1,5 +1,4 @@
1name: "L2 Room" 1name: "L2 Room"
2display_name: "Lively"
3letters { 2letters {
4 key: "l" 3 key: "l"
5 level2: true 4 level2: true
diff --git a/data/maps/the_lively/rooms/Puzzle Room.txtpb b/data/maps/the_lively/rooms/Puzzle Room.txtpb index f202453..4918476 100644 --- a/data/maps/the_lively/rooms/Puzzle Room.txtpb +++ b/data/maps/the_lively/rooms/Puzzle Room.txtpb
@@ -1,5 +1,4 @@
1name: "Puzzle Room" 1name: "Puzzle Room"
2display_name: "Lively"
3panels { 2panels {
4 name: "LIONESS" 3 name: "LIONESS"
5 path: "Panels/entry_1" 4 path: "Panels/entry_1"
@@ -58,5 +57,8 @@ panels {
58} 57}
59ports { 58ports {
60 name: "BETWEEN" 59 name: "BETWEEN"
60 display_name: "Entrance"
61 path: "Components/Warps/worldport" 61 path: "Components/Warps/worldport"
62 destination { x: 0 y: 0 z: 6.5 }
63 rotation: 0
62} 64}
diff --git a/data/maps/the_nuanced/connections.txtpb b/data/maps/the_nuanced/connections.txtpb index 6c4b0f6..a530472 100644 --- a/data/maps/the_nuanced/connections.txtpb +++ b/data/maps/the_nuanced/connections.txtpb
@@ -1,7 +1,7 @@
1connections { 1connections {
2 from_room: "Main Room" 2 from_room: "Main Room"
3 to_room: "Back Room" 3 to_room: "Back Room"
4 door { name: "Main Room Puzzles" } 4 door { name: "Main Room Door" }
5} 5}
6connections { 6connections {
7 from_room: "Back Room" 7 from_room: "Back Room"
diff --git a/data/maps/the_nuanced/doors.txtpb b/data/maps/the_nuanced/doors.txtpb index 0c66799..cd29766 100644 --- a/data/maps/the_nuanced/doors.txtpb +++ b/data/maps/the_nuanced/doors.txtpb
@@ -1,5 +1,5 @@
1doors { 1doors {
2 name: "Left Room Puzzles" 2 name: "Blue Side Puzzles"
3 type: LOCATION_ONLY 3 type: LOCATION_ONLY
4 panels { room: "Main Room" name: "HOARSE" } 4 panels { room: "Main Room" name: "HOARSE" }
5 panels { room: "Main Room" name: "NAY" } 5 panels { room: "Main Room" name: "NAY" }
@@ -11,7 +11,7 @@ doors {
11 location_room: "Main Room" 11 location_room: "Main Room"
12} 12}
13doors { 13doors {
14 name: "Right Room Puzzles" 14 name: "Green Side Puzzles"
15 type: LOCATION_ONLY 15 type: LOCATION_ONLY
16 panels { room: "Main Room" name: "HOSE" } 16 panels { room: "Main Room" name: "HOSE" }
17 panels { room: "Main Room" name: "NIGH" } 17 panels { room: "Main Room" name: "NIGH" }
@@ -23,7 +23,7 @@ doors {
23 location_room: "Main Room" 23 location_room: "Main Room"
24} 24}
25doors { 25doors {
26 name: "Main Room Puzzles" 26 name: "Main Room Door"
27 type: ITEM_ONLY 27 type: ITEM_ONLY
28 receivers: "Components/Doors/entry_1" 28 receivers: "Components/Doors/entry_1"
29 panels { room: "Main Room" name: "HOARSE" } 29 panels { room: "Main Room" name: "HOARSE" }
diff --git a/data/maps/the_nuanced/rooms/Back Room.txtpb b/data/maps/the_nuanced/rooms/Back Room.txtpb index 37a1c7a..b61e18b 100644 --- a/data/maps/the_nuanced/rooms/Back Room.txtpb +++ b/data/maps/the_nuanced/rooms/Back Room.txtpb
@@ -1,5 +1,4 @@
1name: "Back Room" 1name: "Back Room"
2display_name: "Nuanced"
3panels { 2panels {
4 name: "COURSE" 3 name: "COURSE"
5 path: "Panels/Rhymes/panel_1" 4 path: "Panels/Rhymes/panel_1"
diff --git a/data/maps/the_nuanced/rooms/Main Room.txtpb b/data/maps/the_nuanced/rooms/Main Room.txtpb index 8523b38..ce4310e 100644 --- a/data/maps/the_nuanced/rooms/Main Room.txtpb +++ b/data/maps/the_nuanced/rooms/Main Room.txtpb
@@ -1,5 +1,4 @@
1name: "Main Room" 1name: "Main Room"
2display_name: "Nuanced"
3panels { 2panels {
4 name: "HOARSE" 3 name: "HOARSE"
5 path: "Panels/Eyes/panel_1" 4 path: "Panels/Eyes/panel_1"
@@ -107,10 +106,13 @@ panels {
107} 106}
108ports { 107ports {
109 name: "UNYIELDING" 108 name: "UNYIELDING"
109 display_name: "Entrance"
110 path: "Components/Warps/worldport" 110 path: "Components/Warps/worldport"
111 orientation: "west" 111 destination { x: -3.5 y: 0 z: 21 }
112 rotation: 270
112} 113}
113keyholders { 114keyholders {
114 name: "S" 115 name: "S"
115 path: "Components/KeyHolders/keyHolderS" 116 path: "Components/KeyHolders/keyHolderS"
117 key: "s"
116} 118}
diff --git a/data/maps/the_nuanced/rooms/N2 Room.txtpb b/data/maps/the_nuanced/rooms/N2 Room.txtpb index 492d4a3..eb9f67c 100644 --- a/data/maps/the_nuanced/rooms/N2 Room.txtpb +++ b/data/maps/the_nuanced/rooms/N2 Room.txtpb
@@ -1,5 +1,4 @@
1name: "N2 Room" 1name: "N2 Room"
2display_name: "Nuanced"
3letters { 2letters {
4 key: "n" 3 key: "n"
5 level2: true 4 level2: true
diff --git a/data/maps/the_orb/connections.txtpb b/data/maps/the_orb/connections.txtpb index 62a7643..b902711 100644 --- a/data/maps/the_orb/connections.txtpb +++ b/data/maps/the_orb/connections.txtpb
@@ -10,10 +10,20 @@ connections {
10} 10}
11connections { 11connections {
12 from_room: "Main Area" 12 from_room: "Main Area"
13 to_room: "B Room" 13 to_room: "Middle Room"
14 door { name: "B Puzzles" } 14 door { name: "B Puzzles" }
15} 15}
16connections { 16connections {
17 from_room: "Middle Room"
18 to_room: "B Room"
19 oneway: true
20}
21connections {
22 from_room: "Middle Room"
23 to_room: "Main Area"
24 oneway: true
25}
26connections {
17 from_room: "B Room" 27 from_room: "B Room"
18 to_room: "Main Area" 28 to_room: "Main Area"
19 oneway: true 29 oneway: true
diff --git a/data/maps/the_orb/rooms/B Room.txtpb b/data/maps/the_orb/rooms/B Room.txtpb index 833c659..633232f 100644 --- a/data/maps/the_orb/rooms/B Room.txtpb +++ b/data/maps/the_orb/rooms/B Room.txtpb
@@ -1,5 +1,4 @@
1name: "B Room" 1name: "B Room"
2display_name: "Orb"
3letters { 2letters {
4 key: "b" 3 key: "b"
5 path: "Components/Collectables/b" 4 path: "Components/Collectables/b"
@@ -10,19 +9,10 @@ paintings {
10 # TODO: This is too high up to enter. It's also a hint painting. 9 # TODO: This is too high up to enter. It's also a hint painting.
11 exit_only: true 10 exit_only: true
12} 11}
13# TODO: Should these two be independent for shuffling purposes, or always tied
14# to the Main Area's port?
15ports {
16 name: "MID"
17 path: "Components/Warps/worldport4"
18 orientation: "south"
19 # This port is in the room immediately after solving the B puzzles, which
20 # means it seems like it would be inaccessible if you enter the map from the
21 # painting or from the final port, but entering the O or R areas brings you
22 # back to the beginning.
23}
24ports { 12ports {
25 name: "FINAL" 13 name: "FINAL"
14 display_name: "Final Worldport"
26 path: "Components/Warps/worldport5" 15 path: "Components/Warps/worldport5"
27 orientation: "south" 16 destination { x: -69 y: 0 z: 87 }
17 rotation: 90
28} 18}
diff --git a/data/maps/the_orb/rooms/Main Area.txtpb b/data/maps/the_orb/rooms/Main Area.txtpb index 8d7b7b1..976c489 100644 --- a/data/maps/the_orb/rooms/Main Area.txtpb +++ b/data/maps/the_orb/rooms/Main Area.txtpb
@@ -1,5 +1,4 @@
1name: "Main Area" 1name: "Main Area"
2display_name: "Orb"
3panels { 2panels {
4 name: "STRIKE" 3 name: "STRIKE"
5 path: "Panels/O/entry_1" 4 path: "Panels/O/entry_1"
@@ -86,6 +85,8 @@ panels {
86} 85}
87ports { 86ports {
88 name: "GREAT" 87 name: "GREAT"
88 display_name: "Main Entrance"
89 path: "Components/Warps/worldport" 89 path: "Components/Warps/worldport"
90 orientation: "south" 90 destination { x: 38 y: 0 z: 39 }
91 rotation: 90
91} 92}
diff --git a/data/maps/the_orb/rooms/Middle Room.txtpb b/data/maps/the_orb/rooms/Middle Room.txtpb new file mode 100644 index 0000000..ed1a00c --- /dev/null +++ b/data/maps/the_orb/rooms/Middle Room.txtpb
@@ -0,0 +1,12 @@
1name: "Middle Room"
2# This is the room after solving the B puzzles but before getting to B1 itself.
3# It has to be a separate region because if you are shuffling worldports and you
4# warp to the B1 room port, you can't access this port if you're not able to
5# solve the B puzzles.
6ports {
7 name: "MID"
8 display_name: "Middle Worldport"
9 path: "Components/Warps/worldport4"
10 destination { x: -69 y: 0 z: 43 }
11 rotation: 90
12}
diff --git a/data/maps/the_orb/rooms/O Room.txtpb b/data/maps/the_orb/rooms/O Room.txtpb index f997780..cc254a4 100644 --- a/data/maps/the_orb/rooms/O Room.txtpb +++ b/data/maps/the_orb/rooms/O Room.txtpb
@@ -1,5 +1,4 @@
1name: "O Room" 1name: "O Room"
2display_name: "Orb"
3letters { 2letters {
4 key: "o" 3 key: "o"
5 path: "Components/Collectables/o" 4 path: "Components/Collectables/o"
diff --git a/data/maps/the_orb/rooms/R Room.txtpb b/data/maps/the_orb/rooms/R Room.txtpb index c53b7eb..a01726a 100644 --- a/data/maps/the_orb/rooms/R Room.txtpb +++ b/data/maps/the_orb/rooms/R Room.txtpb
@@ -1,5 +1,4 @@
1name: "R Room" 1name: "R Room"
2display_name: "Orb"
3letters { 2letters {
4 key: "r" 3 key: "r"
5 path: "Components/Collectables/r" 4 path: "Components/Collectables/r"
diff --git a/data/maps/the_owl/connections.txtpb b/data/maps/the_owl/connections.txtpb index 87c98b3..cb4bee3 100644 --- a/data/maps/the_owl/connections.txtpb +++ b/data/maps/the_owl/connections.txtpb
@@ -10,12 +10,27 @@ connections {
10} 10}
11connections { 11connections {
12 from_room: "R2C2 Bottom" 12 from_room: "R2C2 Bottom"
13 to_room: "R2C2.5 Bottom" 13 to_room: "R2C2 Top"
14 door { name: "Sky Owl" }
15}
16connections {
17 from_room: "R2C2 Bottom"
18 to_room: "Connected Area"
14 door { name: "Gray Owl" } 19 door { name: "Gray Owl" }
15} 20}
16connections { 21connections {
17 from_room: "R2C2 Bottom" 22 from_room: "R2C2 Bottom"
18 to_room: "R2C2.5 Bottom" 23 to_room: "Connected Area"
24 door { name: "Sky Owl" }
25}
26connections {
27 from_room: "R2C3 Bottom"
28 to_room: "Connected Area"
29 oneway: true
30}
31connections {
32 from_room: "R2C2 Bottom"
33 to_room: "Connected Area"
19 door { name: "First Room Shortcut" } 34 door { name: "First Room Shortcut" }
20} 35}
21connections { 36connections {
@@ -30,18 +45,18 @@ connections {
30} 45}
31connections { 46connections {
32 from_room: "R2C2 Top" 47 from_room: "R2C2 Top"
33 to_room: "R2C2.5 Bottom" 48 to_room: "R2C3 Bottom"
34 door { name: "Gray Bottom Door" } 49 door { name: "Gray Bottom Door" }
35} 50}
36connections { 51connections {
37 from_room: "R2C2 Top" 52 from_room: "Connected Area"
38 to_room: "R2C2.5 Bottom" 53 to_room: "R2C3 Bottom"
39 door { name: "Gray Owl" } 54 door { name: "Gray Owl" }
40} 55}
41connections { 56connections {
42 from_room: "Connected Area" 57 from_room: "Connected Area"
43 to_room: "R2C2.5 Bottom" 58 to_room: "R2C3 Bottom"
44 door { name: "Gray Owl" } 59 door { name: "Sky Owl" }
45} 60}
46connections { 61connections {
47 from_room: "Connected Area" 62 from_room: "Connected Area"
@@ -70,6 +85,11 @@ connections {
70} 85}
71connections { 86connections {
72 from_room: "Connected Area" 87 from_room: "Connected Area"
88 to_room: "R1C4 Left"
89 door { name: "Sky Owl" }
90}
91connections {
92 from_room: "Connected Area"
73 to_room: "R2C1 Left" 93 to_room: "R2C1 Left"
74 door { name: "Sky Top Doors" } 94 door { name: "Sky Top Doors" }
75} 95}
@@ -84,6 +104,11 @@ connections {
84 door { name: "Gray Owl" } 104 door { name: "Gray Owl" }
85} 105}
86connections { 106connections {
107 from_room: "Connected Area"
108 to_room: "R2C1 Left"
109 door { name: "Sky Owl" }
110}
111connections {
87 from { 112 from {
88 painting { 113 painting {
89 room: "Connected Area" 114 room: "Connected Area"
diff --git a/data/maps/the_owl/doors.txtpb b/data/maps/the_owl/doors.txtpb index 2c7f449..9254c2a 100644 --- a/data/maps/the_owl/doors.txtpb +++ b/data/maps/the_owl/doors.txtpb
@@ -25,8 +25,8 @@ doors {
25 name: "First Room Shortcut" 25 name: "First Room Shortcut"
26 type: STANDARD 26 type: STANDARD
27 receivers: "Components/Doors/entry_6" 27 receivers: "Components/Doors/entry_6"
28 panels { room: "R2C2.5 Bottom" name: "FIZZLE" } 28 panels { room: "Connected Area" name: "FIZZLE" }
29 location_room: "R2C2.5 Bottom" 29 location_room: "Connected Area"
30} 30}
31doors { 31doors {
32 name: "First Door" 32 name: "First Door"
@@ -171,8 +171,8 @@ doors {
171 receivers: "Components/Owl/Room 10/WG" 171 receivers: "Components/Owl/Room 10/WG"
172 receivers: "Components/Owl/Room 11/W" 172 receivers: "Components/Owl/Room 11/W"
173 receivers: "Components/Owl/Room 11/WG" 173 receivers: "Components/Owl/Room 11/WG"
174 panels { room: "R2C2.5 Bottom" name: "BLACK" } 174 panels { room: "R2C3 Bottom" name: "BLACK" }
175 location_room: "R2C2.5 Bottom" 175 location_room: "R2C3 Bottom"
176} 176}
177doors { 177doors {
178 name: "Black Owl" 178 name: "Black Owl"
@@ -233,19 +233,20 @@ doors {
233doors { 233doors {
234 name: "Gray Panel" 234 name: "Gray Panel"
235 type: EVENT 235 type: EVENT
236 # TODO: Is it okay to have an event with an in-game effect? 236 #receivers: "Panels/Colors/owl_2/animationListener2"
237 receivers: "Panels/Colors/owl_2/animationListener2" 237 panels { room: "Connected Area" name: "RANGE" }
238 doors { name: "Orange Owl" } 238 panels { room: "Connected Area" name: "WHITE" }
239 doors { name: "Black Owl" } 239 panels { room: "Blue Room" name: "SKY" }
240 doors { name: "Blue Owl" }
241} 240}
242doors { 241doors {
243 name: "Owl Painting" 242 name: "Owl Painting"
244 type: EVENT 243 type: EVENT
245 move_paintings { room: "Connected Area" name: "OWL" } 244 #move_paintings { room: "Connected Area" name: "OWL" }
246 doors { name: "Orange Owl" } 245 #receivers: "Components/Paintings/owl/teleportListener"
247 doors { name: "Black Owl" } 246 panels { room: "R2C1 Left" name: "DUSKY" }
248 doors { name: "Blue Owl" } 247 panels { room: "R2C2 Top" name: "RAY" }
249 doors { name: "White Owl" } 248 panels { room: "Connected Area" name: "RANGE" }
250 doors { name: "Sky Owl" } 249 panels { room: "R2C3 Bottom" name: "BLACK" }
250 panels { room: "Connected Area" name: "WHITE" }
251 panels { room: "Blue Room" name: "SKY" }
251} 252}
diff --git a/data/maps/the_owl/rooms/Blue Room.txtpb b/data/maps/the_owl/rooms/Blue Room.txtpb index 7c2d69a..a7298cd 100644 --- a/data/maps/the_owl/rooms/Blue Room.txtpb +++ b/data/maps/the_owl/rooms/Blue Room.txtpb
@@ -1,5 +1,4 @@
1name: "Blue Room" 1name: "Blue Room"
2display_name: "Owl"
3panels { 2panels {
4 name: "SKY" 3 name: "SKY"
5 path: "Panels/Colors/owl_7" 4 path: "Panels/Colors/owl_7"
diff --git a/data/maps/the_owl/rooms/Connected Area.txtpb b/data/maps/the_owl/rooms/Connected Area.txtpb index 18388be..432d6b2 100644 --- a/data/maps/the_owl/rooms/Connected Area.txtpb +++ b/data/maps/the_owl/rooms/Connected Area.txtpb
@@ -1,5 +1,4 @@
1name: "Connected Area" 1name: "Connected Area"
2display_name: "Owl"
3panels { 2panels {
4 name: "MODE" 3 name: "MODE"
5 path: "Panels/Noncritical/owl_12" 4 path: "Panels/Noncritical/owl_12"
@@ -133,6 +132,13 @@ panels {
133 answer: "orange" 132 answer: "orange"
134 symbols: SPARKLES 133 symbols: SPARKLES
135} 134}
135panels {
136 name: "FIZZLE"
137 path: "Panels/Bottom Mid/owl_10"
138 clue: "fizzle"
139 answer: "chisel"
140 symbols: ZERO
141}
136paintings { 142paintings {
137 name: "OWL" 143 name: "OWL"
138 path: "Components/Paintings/owl" 144 path: "Components/Paintings/owl"
@@ -143,7 +149,9 @@ paintings {
143} 149}
144ports { 150ports {
145 name: "FOURROOMS" 151 name: "FOURROOMS"
152 display_name: "Four Rooms Entrance"
146 path: "Components/Warps/worldport2" 153 path: "Components/Warps/worldport2"
147 orientation: "east" 154 destination { x: 71.5 y: 0 z: -9 }
155 rotation: 90
148 # Note that this is behind teal walls. 156 # Note that this is behind teal walls.
149} 157}
diff --git a/data/maps/the_owl/rooms/Magenta Hallway.txtpb b/data/maps/the_owl/rooms/Magenta Hallway.txtpb index 58a4a5d..14d6f0d 100644 --- a/data/maps/the_owl/rooms/Magenta Hallway.txtpb +++ b/data/maps/the_owl/rooms/Magenta Hallway.txtpb
@@ -1,7 +1,8 @@
1name: "Magenta Hallway" 1name: "Magenta Hallway"
2display_name: "Owl"
3ports { 2ports {
4 name: "STURDY" 3 name: "STURDY"
4 display_name: "Magenta Hallway"
5 path: "Components/Warps/worldport3" 5 path: "Components/Warps/worldport3"
6 orientation: "west" 6 destination { x: 17 y: 0 z: -46 }
7 rotation: 270
7} 8}
diff --git a/data/maps/the_owl/rooms/R1C4 Left.txtpb b/data/maps/the_owl/rooms/R1C4 Left.txtpb index 73c1520..3714842 100644 --- a/data/maps/the_owl/rooms/R1C4 Left.txtpb +++ b/data/maps/the_owl/rooms/R1C4 Left.txtpb
@@ -1,5 +1,4 @@
1name: "R1C4 Left" 1name: "R1C4 Left"
2display_name: "Owl"
3panels { 2panels {
4 name: "WALK" 3 name: "WALK"
5 path: "Panels/Noncritical/owl_5" 4 path: "Panels/Noncritical/owl_5"
diff --git a/data/maps/the_owl/rooms/R2C1 Left.txtpb b/data/maps/the_owl/rooms/R2C1 Left.txtpb index 0f9a2b5..72e7331 100644 --- a/data/maps/the_owl/rooms/R2C1 Left.txtpb +++ b/data/maps/the_owl/rooms/R2C1 Left.txtpb
@@ -1,5 +1,4 @@
1name: "R2C1 Left" 1name: "R2C1 Left"
2display_name: "Owl"
3panels { 2panels {
4 name: "VERB" 3 name: "VERB"
5 path: "Panels/Bottom Left/owl_8" 4 path: "Panels/Bottom Left/owl_8"
diff --git a/data/maps/the_owl/rooms/R2C2 Bottom.txtpb b/data/maps/the_owl/rooms/R2C2 Bottom.txtpb index e7eb9e4..2cfd340 100644 --- a/data/maps/the_owl/rooms/R2C2 Bottom.txtpb +++ b/data/maps/the_owl/rooms/R2C2 Bottom.txtpb
@@ -1,5 +1,4 @@
1name: "R2C2 Bottom" 1name: "R2C2 Bottom"
2display_name: "Owl"
3panels { 2panels {
4 name: "FOUL" 3 name: "FOUL"
5 path: "Panels/Bottom Mid/owl_11" 4 path: "Panels/Bottom Mid/owl_11"
@@ -9,7 +8,10 @@ panels {
9} 8}
10ports { 9ports {
11 name: "GALLERY" 10 name: "GALLERY"
11 display_name: "Gallery Worldport"
12 path: "Components/Warps/worldport" 12 path: "Components/Warps/worldport"
13 orientation: "south" 13 destination { x: 0 y: 0 z: 9 }
14 # Note that this port is accessible from the other side in the Z1 room. Hmm. 14 rotation: 0
15 # TODO: Note that this port is accessible from the other side in the Z1
16 # room. Hmm.
15} 17}
diff --git a/data/maps/the_owl/rooms/R2C2 Top.txtpb b/data/maps/the_owl/rooms/R2C2 Top.txtpb index 87b7705..78ce270 100644 --- a/data/maps/the_owl/rooms/R2C2 Top.txtpb +++ b/data/maps/the_owl/rooms/R2C2 Top.txtpb
@@ -1,5 +1,4 @@
1name: "R2C2 Top" 1name: "R2C2 Top"
2display_name: "Owl"
3panels { 2panels {
4 name: "CRUSH" 3 name: "CRUSH"
5 path: "Panels/Bottom Mid/owl_1" 4 path: "Panels/Bottom Mid/owl_1"
diff --git a/data/maps/the_owl/rooms/R2C2.5 Bottom.txtpb b/data/maps/the_owl/rooms/R2C3 Bottom.txtpb index 41b6265..2b49e26 100644 --- a/data/maps/the_owl/rooms/R2C2.5 Bottom.txtpb +++ b/data/maps/the_owl/rooms/R2C3 Bottom.txtpb
@@ -1,12 +1,4 @@
1name: "R2C2.5 Bottom" 1name: "R2C3 Bottom"
2display_name: "Owl"
3panels {
4 name: "FIZZLE"
5 path: "Panels/Bottom Mid/owl_10"
6 clue: "fizzle"
7 answer: "chisel"
8 symbols: ZERO
9}
10panels { 2panels {
11 name: "FIGMENT" 3 name: "FIGMENT"
12 path: "Panels/Noncritical/owl_14" 4 path: "Panels/Noncritical/owl_14"
diff --git a/data/maps/the_owl/rooms/Z Room.txtpb b/data/maps/the_owl/rooms/Z Room.txtpb index 035d0b4..ab28655 100644 --- a/data/maps/the_owl/rooms/Z Room.txtpb +++ b/data/maps/the_owl/rooms/Z Room.txtpb
@@ -1,5 +1,4 @@
1name: "Z Room" 1name: "Z Room"
2display_name: "Owl"
3panels { 2panels {
4 name: "MAZE" 3 name: "MAZE"
5 path: "Panels/Noncritical/owl_10" 4 path: "Panels/Noncritical/owl_10"
diff --git a/data/maps/the_parthenon/connections.txtpb b/data/maps/the_parthenon/connections.txtpb index a07d858..331ac66 100644 --- a/data/maps/the_parthenon/connections.txtpb +++ b/data/maps/the_parthenon/connections.txtpb
@@ -7,6 +7,7 @@ connections {
7 from_room: "Main Area" 7 from_room: "Main Area"
8 to_room: "Ending" 8 to_room: "Ending"
9 door { name: "Ending Door" } 9 door { name: "Ending Door" }
10 cyan_ending: true
10} 11}
11connections { 12connections {
12 from_room: "Main Area" 13 from_room: "Main Area"
diff --git a/data/maps/the_parthenon/doors.txtpb b/data/maps/the_parthenon/doors.txtpb index 82a2748..1161917 100644 --- a/data/maps/the_parthenon/doors.txtpb +++ b/data/maps/the_parthenon/doors.txtpb
@@ -1,12 +1,24 @@
1doors { 1doors {
2 name: "Double Letters" 2 name: "Double Letters"
3 type: EVENT 3 type: EVENT
4 switches: "double_letters" 4 receivers: "Components/Doors/entry_11"
5 receivers: "Components/Doors/entry_5"
6 receivers: "Components/Doors/entry_6"
7 receivers: "Components/Doors/entry_7"
8 receivers: "Components/Doors/entry_8"
9 receivers: "Components/Doors/entry_9"
10 receivers: "Components/Doors/entry_10"
11 double_letters: true
5} 12}
6doors { 13doors {
7 name: "Lavender Cubes" 14 name: "Lavender Cubes"
8 type: EVENT 15 type: EVENT
9 switches: "lavender_cubes" 16 receivers: "Components/Doors/entry_3"
17 panels {
18 map: "the_ancient"
19 room: "Inside"
20 name: "COLOR"
21 }
10} 22}
11doors { 23doors {
12 name: "K2 Door" 24 name: "K2 Door"
@@ -19,6 +31,7 @@ doors {
19 panels { room: "Main Area" name: "ALEXANDER" answer: "greece" } 31 panels { room: "Main Area" name: "ALEXANDER" answer: "greece" }
20 panels { room: "Main Area" name: "CAESAR" answer: "rome" } 32 panels { room: "Main Area" name: "CAESAR" answer: "rome" }
21 location_room: "Main Area" 33 location_room: "Main Area"
34 location_name: "Empires"
22} 35}
23doors { 36doors {
24 name: "Ending Door" 37 name: "Ending Door"
diff --git a/data/maps/the_parthenon/rooms/Ending.txtpb b/data/maps/the_parthenon/rooms/Ending.txtpb index 8fa805f..789e906 100644 --- a/data/maps/the_parthenon/rooms/Ending.txtpb +++ b/data/maps/the_parthenon/rooms/Ending.txtpb
@@ -1,5 +1,4 @@
1name: "Ending" 1name: "Ending"
2display_name: "Parthenon"
3endings { 2endings {
4 name: "CYAN" 3 name: "CYAN"
5 path: "Components/cyan_end" 4 path: "Components/cyan_end"
diff --git a/data/maps/the_parthenon/rooms/K2 Room.txtpb b/data/maps/the_parthenon/rooms/K2 Room.txtpb index 1c95ad5..596b489 100644 --- a/data/maps/the_parthenon/rooms/K2 Room.txtpb +++ b/data/maps/the_parthenon/rooms/K2 Room.txtpb
@@ -1,5 +1,4 @@
1name: "K2 Room" 1name: "K2 Room"
2display_name: "Parthenon"
3letters { 2letters {
4 key: "k" 3 key: "k"
5 level2: true 4 level2: true
diff --git a/data/maps/the_parthenon/rooms/Lavender Area.txtpb b/data/maps/the_parthenon/rooms/Lavender Area.txtpb index 6f67214..9e62498 100644 --- a/data/maps/the_parthenon/rooms/Lavender Area.txtpb +++ b/data/maps/the_parthenon/rooms/Lavender Area.txtpb
@@ -1,5 +1,4 @@
1name: "Lavender Area" 1name: "Lavender Area"
2display_name: "Parthenon"
3panels { 2panels {
4 name: "ME" 3 name: "ME"
5 path: "Panels/Lavender/panel_7" 4 path: "Panels/Lavender/panel_7"
diff --git a/data/maps/the_parthenon/rooms/Main Area.txtpb b/data/maps/the_parthenon/rooms/Main Area.txtpb index db62c2c..2d989f8 100644 --- a/data/maps/the_parthenon/rooms/Main Area.txtpb +++ b/data/maps/the_parthenon/rooms/Main Area.txtpb
@@ -1,12 +1,11 @@
1name: "Main Area" 1name: "Main Area"
2display_name: "Parthenon"
3panels { 2panels {
4 name: "XERXES" 3 name: "XERXES"
5 path: "Panels/Main/panel_1" 4 path: "Panels/Main/panel_1"
6 clue: "xerxes" 5 clue: "xerxes"
7 answer: "xerxes" 6 answer: "xerxes"
8 proxies { answer: "persia" path: "Panels/Empires/panel_7" } 7 proxies { answer: "persia" path: "Panels/Empires/panel_7" }
9 #proxies { answer: "xerxes" path: "Panels/Rulers/panel_13" } 8 proxies { answer: "xerxes" path: "Panels/Rulers/panel_13" }
10 required_door { name: "Double Letters" } 9 required_door { name: "Double Letters" }
11} 10}
12panels { 11panels {
@@ -15,7 +14,7 @@ panels {
15 clue: "arthur" 14 clue: "arthur"
16 answer: "arthur" 15 answer: "arthur"
17 proxies { answer: "england" path: "Panels/Empires/panel_8" } 16 proxies { answer: "england" path: "Panels/Empires/panel_8" }
18 #proxies { answer: "arthur" path: "Panels/Rulers/panel_14" } 17 proxies { answer: "arthur" path: "Panels/Rulers/panel_14" }
19 required_door { name: "Double Letters" } 18 required_door { name: "Double Letters" }
20} 19}
21panels { 20panels {
@@ -24,7 +23,7 @@ panels {
24 clue: "cleopatra" 23 clue: "cleopatra"
25 answer: "cleopatra" 24 answer: "cleopatra"
26 proxies { answer: "egypt" path: "Panels/Empires/panel_9" } 25 proxies { answer: "egypt" path: "Panels/Empires/panel_9" }
27 #proxies { answer: "cleopatra" path: "Panels/Rulers/panel_15" } 26 proxies { answer: "cleopatra" path: "Panels/Rulers/panel_15" }
28 required_door { name: "Double Letters" } 27 required_door { name: "Double Letters" }
29} 28}
30panels { 29panels {
@@ -33,7 +32,7 @@ panels {
33 clue: "napoleon" 32 clue: "napoleon"
34 answer: "napoleon" 33 answer: "napoleon"
35 proxies { answer: "france" path: "Panels/Empires/panel_10" } 34 proxies { answer: "france" path: "Panels/Empires/panel_10" }
36 #proxies { answer: "napoleon" path: "Panels/Rulers/panel_16" } 35 proxies { answer: "napoleon" path: "Panels/Rulers/panel_16" }
37 required_door { name: "Double Letters" } 36 required_door { name: "Double Letters" }
38} 37}
39panels { 38panels {
@@ -42,7 +41,7 @@ panels {
42 clue: "alexander" 41 clue: "alexander"
43 answer: "alexander" 42 answer: "alexander"
44 proxies { answer: "greece" path: "Panels/Empires/panel_11" } 43 proxies { answer: "greece" path: "Panels/Empires/panel_11" }
45 #proxies { answer: "alexander" path: "Panels/Rulers/panel_17" } 44 proxies { answer: "alexander" path: "Panels/Rulers/panel_17" }
46 required_door { name: "Double Letters" } 45 required_door { name: "Double Letters" }
47} 46}
48panels { 47panels {
@@ -51,21 +50,27 @@ panels {
51 clue: "caesar" 50 clue: "caesar"
52 answer: "caesar" 51 answer: "caesar"
53 proxies { answer: "rome" path: "Panels/Empires/panel_12" } 52 proxies { answer: "rome" path: "Panels/Empires/panel_12" }
54 #proxies { answer: "caesar" path: "Panels/Rulers/panel_18" } 53 proxies { answer: "caesar" path: "Panels/Rulers/panel_18" }
55 required_door { name: "Double Letters" } 54 required_door { name: "Double Letters" }
56} 55}
57ports { 56ports {
58 name: "GALLERY" 57 name: "GALLERY"
58 display_name: "Columns Worldport"
59 path: "Components/Warps/worldport" 59 path: "Components/Warps/worldport"
60 orientation: "south" 60 destination { x: 0 y: 0 z: 0 }
61 rotation: 0
61} 62}
62ports { 63ports {
63 name: "ENTRY" 64 name: "ENTRY"
65 display_name: "Building Worldport"
64 path: "Components/Warps/worldport2" 66 path: "Components/Warps/worldport2"
65 orientation: "south" 67 destination { x: 0 y: 0 z: -21 }
68 rotation: 0
66} 69}
67ports { 70ports {
68 name: "REVITALIZED" 71 name: "REVITALIZED"
72 display_name: "Plum Hallway"
69 path: "Components/Warps/worldport3" 73 path: "Components/Warps/worldport3"
70 orientation: "north" 74 destination { x: -24 y: 0 z: -39 }
75 rotation: 180
71} 76}
diff --git a/data/maps/the_parthenon/rooms/U Keyholder.txtpb b/data/maps/the_parthenon/rooms/U Keyholder.txtpb index d3107b4..0a5c31b 100644 --- a/data/maps/the_parthenon/rooms/U Keyholder.txtpb +++ b/data/maps/the_parthenon/rooms/U Keyholder.txtpb
@@ -1,6 +1,6 @@
1name: "U Keyholder" 1name: "U Keyholder"
2display_name: "Parthenon"
3keyholders { 2keyholders {
4 name: "U" 3 name: "U"
5 path: "Components/KeyHolders/keyHolderU" 4 path: "Components/KeyHolders/keyHolderU"
5 key: "u"
6} 6}
diff --git a/data/maps/the_partial/doors.txtpb b/data/maps/the_partial/doors.txtpb index 2b233db..c51062a 100644 --- a/data/maps/the_partial/doors.txtpb +++ b/data/maps/the_partial/doors.txtpb
@@ -22,6 +22,7 @@ doors {
22 panels { room: "Obverse Side" name: "CUT" } 22 panels { room: "Obverse Side" name: "CUT" }
23 panels { room: "Obverse Side" name: "FUN" } 23 panels { room: "Obverse Side" name: "FUN" }
24 location_room: "Obverse Side" 24 location_room: "Obverse Side"
25 location_name: "Obverse Side Room"
25} 26}
26doors { 27doors {
27 name: "Giant P" 28 name: "Giant P"
diff --git a/data/maps/the_partial/rooms/Control Center Entrance.txtpb b/data/maps/the_partial/rooms/Control Center Entrance.txtpb index 8d7e228..02f3e69 100644 --- a/data/maps/the_partial/rooms/Control Center Entrance.txtpb +++ b/data/maps/the_partial/rooms/Control Center Entrance.txtpb
@@ -1,5 +1,4 @@
1name: "Control Center Entrance" 1name: "Control Center Entrance"
2display_name: "Partial"
3panels { 2panels {
4 name: "RETURN" 3 name: "RETURN"
5 path: "Panels/Control/panel_10" 4 path: "Panels/Control/panel_10"
@@ -9,6 +8,10 @@ panels {
9} 8}
10ports { 9ports {
11 name: "CC" 10 name: "CC"
11 display_name: "Control Center Connector"
12 path: "Components/Warps/worldport2" 12 path: "Components/Warps/worldport2"
13 orientation: "north" 13 destination { x: -19 y: 0 z: 8 }
14 rotation: 180
15 # TODO: shuffle entrances with dependent keyholders
16 no_shuffle: true
14} 17}
diff --git a/data/maps/the_partial/rooms/F Room.txtpb b/data/maps/the_partial/rooms/F Room.txtpb index 358c936..d41d039 100644 --- a/data/maps/the_partial/rooms/F Room.txtpb +++ b/data/maps/the_partial/rooms/F Room.txtpb
@@ -1,5 +1,4 @@
1name: "F Room" 1name: "F Room"
2display_name: "Partial"
3letters { 2letters {
4 key: "f" 3 key: "f"
5 path: "Components/Collectables/collectable2" 4 path: "Components/Collectables/collectable2"
diff --git a/data/maps/the_partial/rooms/Obverse Side.txtpb b/data/maps/the_partial/rooms/Obverse Side.txtpb index 0d83c34..462888c 100644 --- a/data/maps/the_partial/rooms/Obverse Side.txtpb +++ b/data/maps/the_partial/rooms/Obverse Side.txtpb
@@ -1,5 +1,4 @@
1name: "Obverse Side" 1name: "Obverse Side"
2display_name: "Partial"
3panels { 2panels {
4 name: "PUN" 3 name: "PUN"
5 path: "Panels/Main/panel_1" 4 path: "Panels/Main/panel_1"
@@ -100,13 +99,16 @@ panels {
100} 99}
101ports { 100ports {
102 name: "GREAT" 101 name: "GREAT"
102 display_name: "Main Entrance"
103 path: "Components/Warps/worldport" 103 path: "Components/Warps/worldport"
104 orientation: "west" 104 destination { x: -3 y: 0 z: 20 }
105 rotation: 270
105} 106}
106keyholders { 107keyholders {
107 # This is one of the ones that's misnamed within the game. 108 # This is one of the ones that's misnamed within the game.
108 name: "L" 109 name: "L"
109 path: "Components/KeyHolders/keyHolderI" 110 path: "Components/KeyHolders/keyHolderI"
111 key: "l"
110} 112}
111paintings { 113paintings {
112 name: "F" 114 name: "F"
diff --git a/data/maps/the_partial/rooms/P Room.txtpb b/data/maps/the_partial/rooms/P Room.txtpb index e7a7a60..618ebd9 100644 --- a/data/maps/the_partial/rooms/P Room.txtpb +++ b/data/maps/the_partial/rooms/P Room.txtpb
@@ -1,5 +1,4 @@
1name: "P Room" 1name: "P Room"
2display_name: "Partial"
3letters { 2letters {
4 key: "p" 3 key: "p"
5 path: "Components/Collectables/collectable" 4 path: "Components/Collectables/collectable"
diff --git a/data/maps/the_partial/rooms/Reverse Side.txtpb b/data/maps/the_partial/rooms/Reverse Side.txtpb index a286737..01858d6 100644 --- a/data/maps/the_partial/rooms/Reverse Side.txtpb +++ b/data/maps/the_partial/rooms/Reverse Side.txtpb
@@ -1,5 +1,4 @@
1name: "Reverse Side" 1name: "Reverse Side"
2display_name: "Partial"
3panels { 2panels {
4 name: "BRO" 3 name: "BRO"
5 path: "Panels/Side 2/panel_2" 4 path: "Panels/Side 2/panel_2"
diff --git a/data/maps/the_perceptive/rooms/Main Area.txtpb b/data/maps/the_perceptive/rooms/Main Area.txtpb index 75a0343..90bfb41 100644 --- a/data/maps/the_perceptive/rooms/Main Area.txtpb +++ b/data/maps/the_perceptive/rooms/Main Area.txtpb
@@ -1,7 +1,10 @@
1name: "Main Area" 1name: "Main Area"
2display_name: "Perceptive"
3ports { 2ports {
4 name: "CC" 3 name: "CC"
4 display_name: "Entrance"
5 path: "Components/Warps/worldport" 5 path: "Components/Warps/worldport"
6 orientation: "east" 6 destination { x: 3 y: 0 z: 13 }
7 rotation: 90
8 # TODO: shuffle entrances with dependent keyholders
9 no_shuffle: true
7} 10}
diff --git a/data/maps/the_plaza/connections.txtpb b/data/maps/the_plaza/connections.txtpb index 44586be..6da201c 100644 --- a/data/maps/the_plaza/connections.txtpb +++ b/data/maps/the_plaza/connections.txtpb
@@ -21,22 +21,22 @@ connections {
21connections { 21connections {
22 from_room: "Center Room" 22 from_room: "Center Room"
23 to_room: "Top Left Room" 23 to_room: "Top Left Room"
24 door { name: "Top Left Door" } 24 door { name: "Northwest Door" }
25} 25}
26connections { 26connections {
27 from_room: "Center Room" 27 from_room: "Center Room"
28 to_room: "Top Right Room" 28 to_room: "Top Right Room"
29 door { name: "Top Right Door" } 29 door { name: "Northeast Door" }
30} 30}
31connections { 31connections {
32 from_room: "Center Room" 32 from_room: "Center Room"
33 to_room: "Bottom Left Room" 33 to_room: "Bottom Left Room"
34 door { name: "Bottom Left Door" } 34 door { name: "Southwest Door" }
35} 35}
36connections { 36connections {
37 from_room: "Center Room" 37 from_room: "Center Room"
38 to_room: "Bottom Right Room" 38 to_room: "Bottom Right Room"
39 door { name: "Bottom Right Door" } 39 door { name: "Southeast Door" }
40} 40}
41connections { 41connections {
42 from_room: "Center Room" 42 from_room: "Center Room"
diff --git a/data/maps/the_plaza/doors.txtpb b/data/maps/the_plaza/doors.txtpb index be491ed..d95273c 100644 --- a/data/maps/the_plaza/doors.txtpb +++ b/data/maps/the_plaza/doors.txtpb
@@ -31,7 +31,7 @@ doors {
31 location_room: "Main Area" 31 location_room: "Main Area"
32} 32}
33doors { 33doors {
34 name: "Top Left Door" 34 name: "Northwest Door"
35 type: STANDARD 35 type: STANDARD
36 receivers: "Components/Doors/entry_6" 36 receivers: "Components/Doors/entry_6"
37 panels { room: "Center Room" name: "REPORTER" } 37 panels { room: "Center Room" name: "REPORTER" }
@@ -41,9 +41,10 @@ doors {
41 panels { room: "Center Room" name: "DENTIST" } 41 panels { room: "Center Room" name: "DENTIST" }
42 panels { room: "Center Room" name: "SQUIRREL" } 42 panels { room: "Center Room" name: "SQUIRREL" }
43 location_room: "Center Room" 43 location_room: "Center Room"
44 location_name: "First Room"
44} 45}
45doors { 46doors {
46 name: "Top Right Door" 47 name: "Northeast Door"
47 type: ITEM_ONLY 48 type: ITEM_ONLY
48 receivers: "Components/Doors/entry_7" 49 receivers: "Components/Doors/entry_7"
49 panels { room: "Center Room" name: "REPORTER" } 50 panels { room: "Center Room" name: "REPORTER" }
@@ -54,7 +55,7 @@ doors {
54 panels { room: "Center Room" name: "SQUIRREL" } 55 panels { room: "Center Room" name: "SQUIRREL" }
55} 56}
56doors { 57doors {
57 name: "Bottom Left Door" 58 name: "Southwest Door"
58 type: ITEM_ONLY 59 type: ITEM_ONLY
59 receivers: "Components/Doors/entry_5" 60 receivers: "Components/Doors/entry_5"
60 panels { room: "Center Room" name: "REPORTER" } 61 panels { room: "Center Room" name: "REPORTER" }
@@ -65,7 +66,7 @@ doors {
65 panels { room: "Center Room" name: "SQUIRREL" } 66 panels { room: "Center Room" name: "SQUIRREL" }
66} 67}
67doors { 68doors {
68 name: "Bottom Right Door" 69 name: "Southeast Door"
69 type: ITEM_ONLY 70 type: ITEM_ONLY
70 receivers: "Components/Doors/entry_4" 71 receivers: "Components/Doors/entry_4"
71 panels { room: "Center Room" name: "REPORTER" } 72 panels { room: "Center Room" name: "REPORTER" }
@@ -76,7 +77,7 @@ doors {
76 panels { room: "Center Room" name: "SQUIRREL" } 77 panels { room: "Center Room" name: "SQUIRREL" }
77} 78}
78doors { 79doors {
79 name: "Top Left Puzzles" 80 name: "Northwest Puzzles"
80 type: LOCATION_ONLY 81 type: LOCATION_ONLY
81 panels { room: "Top Left Room" name: "BARE SOD" } 82 panels { room: "Top Left Room" name: "BARE SOD" }
82 panels { room: "Top Left Room" name: "SOD" } 83 panels { room: "Top Left Room" name: "SOD" }
@@ -103,7 +104,7 @@ doors {
103 location_room: "Top Left Room" 104 location_room: "Top Left Room"
104} 105}
105doors { 106doors {
106 name: "Top Right Puzzles" 107 name: "Northeast Puzzles"
107 type: LOCATION_ONLY 108 type: LOCATION_ONLY
108 panels { room: "Top Right Room" name: "RIGHT WING" } 109 panels { room: "Top Right Room" name: "RIGHT WING" }
109 panels { room: "Top Right Room" name: "WING" } 110 panels { room: "Top Right Room" name: "WING" }
@@ -129,7 +130,7 @@ doors {
129 location_room: "Top Right Room" 130 location_room: "Top Right Room"
130} 131}
131doors { 132doors {
132 name: "Bottom Left Puzzles" 133 name: "Southwest Puzzles"
133 type: LOCATION_ONLY 134 type: LOCATION_ONLY
134 panels { room: "Bottom Left Room" name: "SHELL (1)" } 135 panels { room: "Bottom Left Room" name: "SHELL (1)" }
135 panels { room: "Bottom Left Room" name: "SHELL (2)" } 136 panels { room: "Bottom Left Room" name: "SHELL (2)" }
@@ -140,7 +141,7 @@ doors {
140 location_room: "Bottom Left Room" 141 location_room: "Bottom Left Room"
141} 142}
142doors { 143doors {
143 name: "Bottom Right Puzzles" 144 name: "Southeast Puzzles"
144 type: LOCATION_ONLY 145 type: LOCATION_ONLY
145 panels { room: "Bottom Right Room" name: "FLY" } 146 panels { room: "Bottom Right Room" name: "FLY" }
146 panels { room: "Bottom Right Room" name: "DECLOG" } 147 panels { room: "Bottom Right Room" name: "DECLOG" }
diff --git a/data/maps/the_plaza/rooms/Bottom Left Room.txtpb b/data/maps/the_plaza/rooms/Bottom Left Room.txtpb index 833ccce..138efc6 100644 --- a/data/maps/the_plaza/rooms/Bottom Left Room.txtpb +++ b/data/maps/the_plaza/rooms/Bottom Left Room.txtpb
@@ -1,5 +1,4 @@
1name: "Bottom Left Room" 1name: "Bottom Left Room"
2display_name: "Plaza"
3panels { 2panels {
4 name: "SHELL (1)" 3 name: "SHELL (1)"
5 path: "Panels/Room 4/panel_1" 4 path: "Panels/Room 4/panel_1"
diff --git a/data/maps/the_plaza/rooms/Bottom Right Room.txtpb b/data/maps/the_plaza/rooms/Bottom Right Room.txtpb index cc38e23..fcd8d37 100644 --- a/data/maps/the_plaza/rooms/Bottom Right Room.txtpb +++ b/data/maps/the_plaza/rooms/Bottom Right Room.txtpb
@@ -1,5 +1,4 @@
1name: "Bottom Right Room" 1name: "Bottom Right Room"
2display_name: "Plaza"
3panels { 2panels {
4 name: "FLY" 3 name: "FLY"
5 path: "Panels/Room 3/panel_1" 4 path: "Panels/Room 3/panel_1"
diff --git a/data/maps/the_plaza/rooms/Center Room.txtpb b/data/maps/the_plaza/rooms/Center Room.txtpb index 4f1c62a..dea2d06 100644 --- a/data/maps/the_plaza/rooms/Center Room.txtpb +++ b/data/maps/the_plaza/rooms/Center Room.txtpb
@@ -1,5 +1,4 @@
1name: "Center Room" 1name: "Center Room"
2display_name: "Plaza"
3panels { 2panels {
4 name: "REPORTER" 3 name: "REPORTER"
5 path: "Panels/Room 2/panel_1" 4 path: "Panels/Room 2/panel_1"
diff --git a/data/maps/the_plaza/rooms/Main Area.txtpb b/data/maps/the_plaza/rooms/Main Area.txtpb index cabfc94..c2fca13 100644 --- a/data/maps/the_plaza/rooms/Main Area.txtpb +++ b/data/maps/the_plaza/rooms/Main Area.txtpb
@@ -1,5 +1,4 @@
1name: "Main Area" 1name: "Main Area"
2display_name: "Plaza"
3panels { 2panels {
4 name: "COURTYARD" 3 name: "COURTYARD"
5 path: "Panels/Entrances/panel_1" 4 path: "Panels/Entrances/panel_1"
@@ -37,16 +36,22 @@ panels {
37} 36}
38ports { 37ports {
39 name: "UNYIELDING" 38 name: "UNYIELDING"
39 display_name: "Unyielding Hallway"
40 path: "Components/Warps/worldport" 40 path: "Components/Warps/worldport"
41 orientation: "west" 41 destination { x: 1 y: 0 z: 10 }
42 rotation: 270
42} 43}
43ports { 44ports {
44 name: "IMPRESSIVE" 45 name: "IMPRESSIVE"
46 display_name: "Impressive Hallway"
45 path: "Components/Warps/worldport2" 47 path: "Components/Warps/worldport2"
46 orientation: "west" 48 destination { x: 11 y: 0 z: 10 }
49 rotation: 270
47} 50}
48ports { 51ports {
49 name: "BETWEEN" 52 name: "BETWEEN"
53 display_name: "Between Hallway"
50 path: "Components/Warps/worldport3" 54 path: "Components/Warps/worldport3"
51 orientation: "west" 55 destination { x: -9 y: 0 z: 10 }
56 rotation: 270
52} 57}
diff --git a/data/maps/the_plaza/rooms/Mastery.txtpb b/data/maps/the_plaza/rooms/Mastery.txtpb index 6b8fd5b..749837e 100644 --- a/data/maps/the_plaza/rooms/Mastery.txtpb +++ b/data/maps/the_plaza/rooms/Mastery.txtpb
@@ -1,5 +1,4 @@
1name: "Mastery" 1name: "Mastery"
2display_name: "Plaza"
3masteries { 2masteries {
4 name: "MASTERY" 3 name: "MASTERY"
5 path: "Components/Collectables/smiley" 4 path: "Components/Collectables/smiley"
diff --git a/data/maps/the_plaza/rooms/Repetitive Entrance.txtpb b/data/maps/the_plaza/rooms/Repetitive Entrance.txtpb index 1690c11..59faaa8 100644 --- a/data/maps/the_plaza/rooms/Repetitive Entrance.txtpb +++ b/data/maps/the_plaza/rooms/Repetitive Entrance.txtpb
@@ -1,5 +1,4 @@
1name: "Repetitive Entrance" 1name: "Repetitive Entrance"
2display_name: "Plaza"
3panels { 2panels {
4 name: "TEDIOUS" 3 name: "TEDIOUS"
5 path: "Panels/Entrances/panel_6" 4 path: "Panels/Entrances/panel_6"
@@ -9,6 +8,8 @@ panels {
9} 8}
10ports { 9ports {
11 name: "REPETITIVE" 10 name: "REPETITIVE"
11 display_name: "Repetitive Entrance"
12 path: "Components/Warps/worldport5" 12 path: "Components/Warps/worldport5"
13 orientation: "north" 13 destination { x: -19 y: 0 z: 16 }
14 rotation: 180
14} 15}
diff --git a/data/maps/the_plaza/rooms/Sirenic Entrance.txtpb b/data/maps/the_plaza/rooms/Sirenic Entrance.txtpb index 048359d..524de2b 100644 --- a/data/maps/the_plaza/rooms/Sirenic Entrance.txtpb +++ b/data/maps/the_plaza/rooms/Sirenic Entrance.txtpb
@@ -1,5 +1,4 @@
1name: "Sirenic Entrance" 1name: "Sirenic Entrance"
2display_name: "Plaza"
3panels { 2panels {
4 name: "SIREN" 3 name: "SIREN"
5 path: "Panels/Entrances/panel_8" 4 path: "Panels/Entrances/panel_8"
@@ -9,6 +8,8 @@ panels {
9} 8}
10ports { 9ports {
11 name: "SIRENIC" 10 name: "SIRENIC"
11 display_name: "Sirenic Entrance"
12 path: "Components/Warps/worldport6" 12 path: "Components/Warps/worldport6"
13 orientation: "west" 13 destination { x: -51 y: 0 z: -43 }
14 rotation: 270
14} 15}
diff --git a/data/maps/the_plaza/rooms/Symbolic Entrance.txtpb b/data/maps/the_plaza/rooms/Symbolic Entrance.txtpb index 36b6a9b..e2719b8 100644 --- a/data/maps/the_plaza/rooms/Symbolic Entrance.txtpb +++ b/data/maps/the_plaza/rooms/Symbolic Entrance.txtpb
@@ -1,5 +1,4 @@
1name: "Symbolic Entrance" 1name: "Symbolic Entrance"
2display_name: "Plaza"
3panels { 2panels {
4 name: "FIGURATIVE" 3 name: "FIGURATIVE"
5 path: "Panels/Entrances/panel_5" 4 path: "Panels/Entrances/panel_5"
@@ -9,6 +8,8 @@ panels {
9} 8}
10ports { 9ports {
11 name: "SYMBOLIC" 10 name: "SYMBOLIC"
11 display_name: "Symbolic Entrance"
12 path: "Components/Warps/worldport4" 12 path: "Components/Warps/worldport4"
13 orientation: "south" 13 destination { x: 28 y: 0 z: 4 }
14 rotation: 0
14} 15}
diff --git a/data/maps/the_plaza/rooms/Top Left Room.txtpb b/data/maps/the_plaza/rooms/Top Left Room.txtpb index 4f562e0..d5b7056 100644 --- a/data/maps/the_plaza/rooms/Top Left Room.txtpb +++ b/data/maps/the_plaza/rooms/Top Left Room.txtpb
@@ -1,5 +1,4 @@
1name: "Top Left Room" 1name: "Top Left Room"
2display_name: "Plaza"
3panels { 2panels {
4 name: "BARE SOD" 3 name: "BARE SOD"
5 path: "Panels/Room 6/panel_1" 4 path: "Panels/Room 6/panel_1"
@@ -42,6 +41,7 @@ panels {
42 clue: "knot" 41 clue: "knot"
43 answer: "not" 42 answer: "not"
44 symbols: ZERO 43 symbols: ZERO
44 display_name: "KNOT (TL)"
45} 45}
46panels { 46panels {
47 name: "SURE TEMPER" 47 name: "SURE TEMPER"
@@ -129,6 +129,7 @@ panels {
129 clue: "bear" 129 clue: "bear"
130 answer: "bearer" 130 answer: "bearer"
131 symbols: SPARKLES 131 symbols: SPARKLES
132 display_name: "BEAR (TL)"
132} 133}
133panels { 134panels {
134 name: "CHILL" 135 name: "CHILL"
diff --git a/data/maps/the_plaza/rooms/Top Right Room.txtpb b/data/maps/the_plaza/rooms/Top Right Room.txtpb index 2a169af..7e91cbe 100644 --- a/data/maps/the_plaza/rooms/Top Right Room.txtpb +++ b/data/maps/the_plaza/rooms/Top Right Room.txtpb
@@ -1,5 +1,4 @@
1name: "Top Right Room" 1name: "Top Right Room"
2display_name: "Plaza"
3panels { 2panels {
4 name: "RIGHT WING" 3 name: "RIGHT WING"
5 path: "Panels/Room 5/panel_1" 4 path: "Panels/Room 5/panel_1"
@@ -34,6 +33,7 @@ panels {
34 clue: "bear" 33 clue: "bear"
35 answer: "cave" 34 answer: "cave"
36 symbols: STARS 35 symbols: STARS
36 display_name: "BEAR (TR)"
37} 37}
38panels { 38panels {
39 name: "TYPIST" 39 name: "TYPIST"
@@ -125,6 +125,7 @@ panels {
125 clue: "knot" 125 clue: "knot"
126 answer: "not" 126 answer: "not"
127 symbols: ZERO 127 symbols: ZERO
128 display_name: "KNOT (TR)"
128} 129}
129panels { 130panels {
130 name: "HALVES ANNOYED SOUR GOOD" 131 name: "HALVES ANNOYED SOUR GOOD"
diff --git a/data/maps/the_quiet/rooms/Keyholder Room.txtpb b/data/maps/the_quiet/rooms/Keyholder Room.txtpb index e2322a8..d3cab73 100644 --- a/data/maps/the_quiet/rooms/Keyholder Room.txtpb +++ b/data/maps/the_quiet/rooms/Keyholder Room.txtpb
@@ -1,6 +1,6 @@
1name: "Keyholder Room" 1name: "Keyholder Room"
2display_name: "Quiet"
3keyholders { 2keyholders {
4 name: "Q" 3 name: "Q"
5 path: "Components/KeyHolders/keyHolderQ" 4 path: "Components/KeyHolders/keyHolderQ"
5 key: "q"
6} 6}
diff --git a/data/maps/the_quiet/rooms/Main Area.txtpb b/data/maps/the_quiet/rooms/Main Area.txtpb index d9c2361..72c0a1e 100644 --- a/data/maps/the_quiet/rooms/Main Area.txtpb +++ b/data/maps/the_quiet/rooms/Main Area.txtpb
@@ -1,5 +1,4 @@
1name: "Main Area" 1name: "Main Area"
2display_name: "Quiet"
3panels { 2panels {
4 name: "SOLID" 3 name: "SOLID"
5 path: "Panels/Main/panel_1" 4 path: "Panels/Main/panel_1"
@@ -98,6 +97,8 @@ panels {
98} 97}
99ports { 98ports {
100 name: "DAEDALUS" 99 name: "DAEDALUS"
100 display_name: "Entrance"
101 path: "Components/Warps/worldport" 101 path: "Components/Warps/worldport"
102 orientation: "east" 102 destination { x: 3 y: 0 z: 8 }
103 rotation: 90
103} 104}
diff --git a/data/maps/the_quiet/rooms/Q Room.txtpb b/data/maps/the_quiet/rooms/Q Room.txtpb index 224e71b..368f366 100644 --- a/data/maps/the_quiet/rooms/Q Room.txtpb +++ b/data/maps/the_quiet/rooms/Q Room.txtpb
@@ -1,5 +1,4 @@
1name: "Q Room" 1name: "Q Room"
2display_name: "Quiet"
3letters { 2letters {
4 key: "q" 3 key: "q"
5 path: "Components/Collectables/q" 4 path: "Components/Collectables/q"
diff --git a/data/maps/the_relentless/rooms/All.txtpb b/data/maps/the_relentless/rooms/All.txtpb index 12705ba..19238c9 100644 --- a/data/maps/the_relentless/rooms/All.txtpb +++ b/data/maps/the_relentless/rooms/All.txtpb
@@ -1,5 +1,4 @@
1name: "All" 1name: "All"
2display_name: "Relentless"
3panels { 2panels {
4 name: "LEFT (1)" 3 name: "LEFT (1)"
5 path: "Panels/Room_1/panel_6" 4 path: "Panels/Room_1/panel_6"
diff --git a/data/maps/the_relentless/rooms/Left And Turn.txtpb b/data/maps/the_relentless/rooms/Left And Turn.txtpb index 5037f20..f79bb54 100644 --- a/data/maps/the_relentless/rooms/Left And Turn.txtpb +++ b/data/maps/the_relentless/rooms/Left And Turn.txtpb
@@ -1,5 +1,4 @@
1name: "Left And Turn" 1name: "Left And Turn"
2display_name: "Relentless"
3panels { 2panels {
4 name: "HIDE (1)" 3 name: "HIDE (1)"
5 path: "Panels/Room_1/panel_2" 4 path: "Panels/Room_1/panel_2"
diff --git a/data/maps/the_relentless/rooms/Left Room.txtpb b/data/maps/the_relentless/rooms/Left Room.txtpb index 52b5154..4db0075 100644 --- a/data/maps/the_relentless/rooms/Left Room.txtpb +++ b/data/maps/the_relentless/rooms/Left Room.txtpb
@@ -1,5 +1,4 @@
1name: "Left Room" 1name: "Left Room"
2display_name: "Relentless"
3panels { 2panels {
4 name: "HIDE" 3 name: "HIDE"
5 path: "Panels/Room_1/panel_1" 4 path: "Panels/Room_1/panel_1"
diff --git a/data/maps/the_relentless/rooms/Mastery.txtpb b/data/maps/the_relentless/rooms/Mastery.txtpb index 8b12c56..749837e 100644 --- a/data/maps/the_relentless/rooms/Mastery.txtpb +++ b/data/maps/the_relentless/rooms/Mastery.txtpb
@@ -1,5 +1,4 @@
1name: "Mastery" 1name: "Mastery"
2display_name: "Relentless"
3masteries { 2masteries {
4 name: "MASTERY" 3 name: "MASTERY"
5 path: "Components/Collectables/smiley" 4 path: "Components/Collectables/smiley"
diff --git a/data/maps/the_relentless/rooms/Shop Room.txtpb b/data/maps/the_relentless/rooms/Shop Room.txtpb index 22b7acc..be3ff7a 100644 --- a/data/maps/the_relentless/rooms/Shop Room.txtpb +++ b/data/maps/the_relentless/rooms/Shop Room.txtpb
@@ -1,5 +1,4 @@
1name: "Shop Room" 1name: "Shop Room"
2display_name: "Relentless"
3panels { 2panels {
4 name: "LEFT (1)" 3 name: "LEFT (1)"
5 path: "Panels/Room_3/panel_5" 4 path: "Panels/Room_3/panel_5"
diff --git a/data/maps/the_relentless/rooms/Turn And Shop.txtpb b/data/maps/the_relentless/rooms/Turn And Shop.txtpb index 9e61769..b9e257c 100644 --- a/data/maps/the_relentless/rooms/Turn And Shop.txtpb +++ b/data/maps/the_relentless/rooms/Turn And Shop.txtpb
@@ -1,5 +1,4 @@
1name: "Turn And Shop" 1name: "Turn And Shop"
2display_name: "Relentless"
3panels { 2panels {
4 name: "LEFT (1)" 3 name: "LEFT (1)"
5 path: "Panels/Room_2/panel_5" 4 path: "Panels/Room_2/panel_5"
diff --git a/data/maps/the_relentless/rooms/Turn Room.txtpb b/data/maps/the_relentless/rooms/Turn Room.txtpb index 3b5caef..525786c 100644 --- a/data/maps/the_relentless/rooms/Turn Room.txtpb +++ b/data/maps/the_relentless/rooms/Turn Room.txtpb
@@ -1,5 +1,4 @@
1name: "Turn Room" 1name: "Turn Room"
2display_name: "Relentless"
3panels { 2panels {
4 name: "HIDE (1)" 3 name: "HIDE (1)"
5 path: "Panels/Room_2/panel_2" 4 path: "Panels/Room_2/panel_2"
diff --git a/data/maps/the_repetitive/connections.txtpb b/data/maps/the_repetitive/connections.txtpb index 2b115a9..f4c06f2 100644 --- a/data/maps/the_repetitive/connections.txtpb +++ b/data/maps/the_repetitive/connections.txtpb
@@ -6,13 +6,13 @@ connections {
6connections { 6connections {
7 from_room: "Main Room" 7 from_room: "Main Room"
8 to_room: "Plaza Connector" 8 to_room: "Plaza Connector"
9 door { name: "Plaza Entrance" } 9 door { name: "Black Hallway" }
10 oneway: true
11} 10}
12connections { 11connections {
13 from_room: "Plaza Connector" 12 from_room: "Plaza Connector"
14 to_room: "Main Room" 13 to_room: "Main Room"
15 oneway: true 14 oneway: true
15 vanilla_only: true
16} 16}
17connections { 17connections {
18 from_room: "Main Room" 18 from_room: "Main Room"
diff --git a/data/maps/the_repetitive/doors.txtpb b/data/maps/the_repetitive/doors.txtpb index 9e63c1d..d964928 100644 --- a/data/maps/the_repetitive/doors.txtpb +++ b/data/maps/the_repetitive/doors.txtpb
@@ -6,7 +6,7 @@ doors {
6 location_room: "Main Room" 6 location_room: "Main Room"
7} 7}
8doors { 8doors {
9 name: "Plaza Entrance" 9 name: "Black Hallway"
10 type: STANDARD 10 type: STANDARD
11 receivers: "Components/Doors/Door12" 11 receivers: "Components/Doors/Door12"
12 panels { room: "Main Room" name: "I" } 12 panels { room: "Main Room" name: "I" }
@@ -194,3 +194,9 @@ doors {
194 panels { room: "Yellow Room" name: "ASSESSES" } 194 panels { room: "Yellow Room" name: "ASSESSES" }
195 panels { room: "Yellow Room" name: "TINTING" } 195 panels { room: "Yellow Room" name: "TINTING" }
196} 196}
197doors {
198 name: "Anti-Collectable"
199 type: LOCATION_ONLY
200 senders: "Components/Collectables/anticollectable"
201 location_room: "Anti Room"
202}
diff --git a/data/maps/the_repetitive/metadata.txtpb b/data/maps/the_repetitive/metadata.txtpb index 6f5c459..76a0f50 100644 --- a/data/maps/the_repetitive/metadata.txtpb +++ b/data/maps/the_repetitive/metadata.txtpb
@@ -1,10 +1,6 @@
1display_name: "The Repetitive" 1display_name: "The Repetitive"
2# The anti-collectable doesn't fit into our system right now so let's ignore it.
3excluded_nodes: "Components/Collectables/anticollectable"
4# These paintings are directly above/behind panels and thus can't be entered. 2# These paintings are directly above/behind panels and thus can't be entered.
5excluded_nodes: "Meshes/eyeRed3" 3excluded_nodes: "Meshes/eyeRed3"
6excluded_nodes: "Meshes/eyeRed4" 4excluded_nodes: "Meshes/eyeRed4"
7# I do not know what this is.
8excluded_nodes: "Components/Doors/Door3/Hinge/panel_i"
9# This has something to do with the magenta room entrance proxy panel. 5# This has something to do with the magenta room entrance proxy panel.
10excluded_nodes: "Panels/Eval/panel_26_proxyied_fake" 6excluded_nodes: "Panels/Eval/panel_26_proxyied_fake"
diff --git a/data/maps/the_repetitive/rooms/Anti Room.txtpb b/data/maps/the_repetitive/rooms/Anti Room.txtpb index 5451977..65a99ff 100644 --- a/data/maps/the_repetitive/rooms/Anti Room.txtpb +++ b/data/maps/the_repetitive/rooms/Anti Room.txtpb
@@ -1,6 +1,4 @@
1name: "Anti Room" 1name: "Anti Room"
2display_name: "Repetitive"
3# Ignore the collectible. The mod should remove it and the back wall too.
4panels { 2panels {
5 name: "HA (1)" 3 name: "HA (1)"
6 path: "Panels/Entry/panel_7" 4 path: "Panels/Entry/panel_7"
@@ -39,9 +37,17 @@ panels {
39 symbols: EXAMPLE 37 symbols: EXAMPLE
40} 38}
41panels { 39panels {
42 name: "EYE" 40 name: "EYE (1)"
43 path: "Panels/Entry/panel4" 41 path: "Panels/Entry/panel4"
44 clue: "eye" 42 clue: "eye"
45 answer: "iris" 43 answer: "iris"
46 symbols: BOXES 44 symbols: BOXES
47} 45}
46panels {
47 # This appears after grabbing the anti-collectable.
48 name: "EYE (2)"
49 path: "Components/Doors/Door3/Hinge/panel_i"
50 clue: "eye"
51 answer: "i"
52 symbols: ZERO
53}
diff --git a/data/maps/the_repetitive/rooms/Cyan Room.txtpb b/data/maps/the_repetitive/rooms/Cyan Room.txtpb index fb56ac7..d6790f5 100644 --- a/data/maps/the_repetitive/rooms/Cyan Room.txtpb +++ b/data/maps/the_repetitive/rooms/Cyan Room.txtpb
@@ -1,5 +1,4 @@
1name: "Cyan Room" 1name: "Cyan Room"
2display_name: "Repetitive"
3panels { 2panels {
4 name: "ALFA" 3 name: "ALFA"
5 path: "Panels/Lingo2/panel_3" 4 path: "Panels/Lingo2/panel_3"
diff --git a/data/maps/the_repetitive/rooms/Dot Area.txtpb b/data/maps/the_repetitive/rooms/Dot Area.txtpb index 202ed92..c4f4583 100644 --- a/data/maps/the_repetitive/rooms/Dot Area.txtpb +++ b/data/maps/the_repetitive/rooms/Dot Area.txtpb
@@ -1,5 +1,4 @@
1name: "Dot Area" 1name: "Dot Area"
2display_name: "Repetitive"
3panels { 2panels {
4 name: "TUTU (1)" 3 name: "TUTU (1)"
5 path: "Panels/Lingo2/panel" 4 path: "Panels/Lingo2/panel"
@@ -96,7 +95,7 @@ panels {
96 clue: "door" 95 clue: "door"
97 answer: "door" 96 answer: "door"
98 symbols: EVAL 97 symbols: EVAL
99 #proxies { answer: "door" path: "Panels/Eval/panel_26_proxyied_1" } 98 proxies { answer: "door" path: "Panels/Eval/panel_26_proxyied_1" }
100 proxies { answer: "do" path: "Panels/Eval/panel_26_proxyied_2" } 99 proxies { answer: "do" path: "Panels/Eval/panel_26_proxyied_2" }
101} 100}
102panels { 101panels {
diff --git a/data/maps/the_repetitive/rooms/Entry Connector.txtpb b/data/maps/the_repetitive/rooms/Entry Connector.txtpb index 8addc7f..16dc116 100644 --- a/data/maps/the_repetitive/rooms/Entry Connector.txtpb +++ b/data/maps/the_repetitive/rooms/Entry Connector.txtpb
@@ -1,7 +1,11 @@
1name: "Entry Connector" 1name: "Entry Connector"
2display_name: "Repetitive"
3ports { 2ports {
4 name: "ENTRY" 3 name: "ENTRY"
4 display_name: "Northwest Worldport"
5 path: "Components/Warps/worldport2" 5 path: "Components/Warps/worldport2"
6 orientation: "south" 6 destination { x: -11 y: 0 z: 13 }
7 rotation: 0
8 # TODO: this is part of what makes the keyholder dependent connection form CC
9 # safe in vanilla doors
10 no_shuffle: true
7} 11}
diff --git a/data/maps/the_repetitive/rooms/Lime Room.txtpb b/data/maps/the_repetitive/rooms/Lime Room.txtpb index 71e4c2c..37d4937 100644 --- a/data/maps/the_repetitive/rooms/Lime Room.txtpb +++ b/data/maps/the_repetitive/rooms/Lime Room.txtpb
@@ -1,5 +1,4 @@
1name: "Lime Room" 1name: "Lime Room"
2display_name: "Repetitive"
3panels { 2panels {
4 name: "RAT" 3 name: "RAT"
5 path: "Panels/Lingo2/panel_1" 4 path: "Panels/Lingo2/panel_1"
diff --git a/data/maps/the_repetitive/rooms/Magenta Room.txtpb b/data/maps/the_repetitive/rooms/Magenta Room.txtpb index 827d058..d38e485 100644 --- a/data/maps/the_repetitive/rooms/Magenta Room.txtpb +++ b/data/maps/the_repetitive/rooms/Magenta Room.txtpb
@@ -1,5 +1,4 @@
1name: "Magenta Room" 1name: "Magenta Room"
2display_name: "Repetitive"
3panels { 2panels {
4 name: "WRITE" 3 name: "WRITE"
5 path: "Panels/Eval/panel_9" 4 path: "Panels/Eval/panel_9"
diff --git a/data/maps/the_repetitive/rooms/Main Room.txtpb b/data/maps/the_repetitive/rooms/Main Room.txtpb index 9fd36d4..3e624a7 100644 --- a/data/maps/the_repetitive/rooms/Main Room.txtpb +++ b/data/maps/the_repetitive/rooms/Main Room.txtpb
@@ -1,5 +1,4 @@
1name: "Main Room" 1name: "Main Room"
2display_name: "Repetitive"
3panels { 2panels {
4 name: "HOTS (2)" 3 name: "HOTS (2)"
5 path: "Panels/Entry/panel_3" 4 path: "Panels/Entry/panel_3"
@@ -139,6 +138,10 @@ paintings {
139} 138}
140ports { 139ports {
141 name: "CC" 140 name: "CC"
141 display_name: "Southwest Worldport"
142 path: "Components/Warps/worldport3" 142 path: "Components/Warps/worldport3"
143 orientation: "east" 143 destination { x: -5.5 y: 0 z: 56 }
144 rotation: 90
145 # TODO: shuffle entrances with dependent keyholders
146 no_shuffle: true
144} 147}
diff --git a/data/maps/the_repetitive/rooms/Mastery Room.txtpb b/data/maps/the_repetitive/rooms/Mastery Room.txtpb index 074a825..5e3326c 100644 --- a/data/maps/the_repetitive/rooms/Mastery Room.txtpb +++ b/data/maps/the_repetitive/rooms/Mastery Room.txtpb
@@ -1,5 +1,4 @@
1name: "Mastery Room" 1name: "Mastery Room"
2display_name: "Repetitive"
3masteries { 2masteries {
4 name: "MASTERY" 3 name: "MASTERY"
5 path: "Components/Collectables/smiley" 4 path: "Components/Collectables/smiley"
diff --git a/data/maps/the_repetitive/rooms/Plaza Connector.txtpb b/data/maps/the_repetitive/rooms/Plaza Connector.txtpb index 88f7fc4..b26fdb0 100644 --- a/data/maps/the_repetitive/rooms/Plaza Connector.txtpb +++ b/data/maps/the_repetitive/rooms/Plaza Connector.txtpb
@@ -1,7 +1,8 @@
1name: "Plaza Connector" 1name: "Plaza Connector"
2display_name: "Repetitive"
3ports { 2ports {
4 name: "PLAZA" 3 name: "PLAZA"
4 display_name: "Northeast Worldport"
5 path: "Components/Warps/worldport" 5 path: "Components/Warps/worldport"
6 orientation: "north" 6 destination { x: 15 y: 0 z: 13 }
7 rotation: 0
7} 8}
diff --git a/data/maps/the_repetitive/rooms/Yellow Room.txtpb b/data/maps/the_repetitive/rooms/Yellow Room.txtpb index 65d665f..9b7d619 100644 --- a/data/maps/the_repetitive/rooms/Yellow Room.txtpb +++ b/data/maps/the_repetitive/rooms/Yellow Room.txtpb
@@ -1,5 +1,4 @@
1name: "Yellow Room" 1name: "Yellow Room"
2display_name: "Repetitive"
3panels { 2panels {
4 name: "W" 3 name: "W"
5 path: "Panels/Eval/panel_1" 4 path: "Panels/Eval/panel_1"
diff --git a/data/maps/the_revitalized/rooms/Bye Room.txtpb b/data/maps/the_revitalized/rooms/Bye Room.txtpb index 60726c2..52d8c42 100644 --- a/data/maps/the_revitalized/rooms/Bye Room.txtpb +++ b/data/maps/the_revitalized/rooms/Bye Room.txtpb
@@ -1,5 +1,4 @@
1name: "Bye Room" 1name: "Bye Room"
2display_name: "Revitalized"
3panels { 2panels {
4 name: "BYE" 3 name: "BYE"
5 path: "Panels/panel_1" 4 path: "Panels/panel_1"
@@ -9,6 +8,8 @@ panels {
9} 8}
10ports { 9ports {
11 name: "PARTHENON" 10 name: "PARTHENON"
11 display_name: "Entrance"
12 path: "Components/Warps/worldport" 12 path: "Components/Warps/worldport"
13 orientation: "south" 13 destination { x: 30 y: 0 z: 16 }
14 rotation: 0
14} 15}
diff --git a/data/maps/the_revitalized/rooms/Hidden Room.txtpb b/data/maps/the_revitalized/rooms/Hidden Room.txtpb index c9ec310..61f2e4d 100644 --- a/data/maps/the_revitalized/rooms/Hidden Room.txtpb +++ b/data/maps/the_revitalized/rooms/Hidden Room.txtpb
@@ -1,5 +1,4 @@
1name: "Hidden Room" 1name: "Hidden Room"
2display_name: "Revitalized"
3panels { 2panels {
4 name: "HIDDEN" 3 name: "HIDDEN"
5 path: "Panels/panel_3" 4 path: "Panels/panel_3"
diff --git a/data/maps/the_revitalized/rooms/Hide Room.txtpb b/data/maps/the_revitalized/rooms/Hide Room.txtpb index 6660787..92b29bf 100644 --- a/data/maps/the_revitalized/rooms/Hide Room.txtpb +++ b/data/maps/the_revitalized/rooms/Hide Room.txtpb
@@ -1,5 +1,4 @@
1name: "Hide Room" 1name: "Hide Room"
2display_name: "Revitalized"
3panels { 2panels {
4 name: "HIDE" 3 name: "HIDE"
5 path: "Panels/panel_2" 4 path: "Panels/panel_2"
diff --git a/data/maps/the_revitalized/rooms/High Room.txtpb b/data/maps/the_revitalized/rooms/High Room.txtpb index de8fdaf..e876801 100644 --- a/data/maps/the_revitalized/rooms/High Room.txtpb +++ b/data/maps/the_revitalized/rooms/High Room.txtpb
@@ -1,5 +1,4 @@
1name: "High Room" 1name: "High Room"
2display_name: "Revitalized"
3panels { 2panels {
4 name: "HIGH" 3 name: "HIGH"
5 path: "Panels/panel_4" 4 path: "Panels/panel_4"
diff --git a/data/maps/the_revitalized/rooms/Return Room.txtpb b/data/maps/the_revitalized/rooms/Return Room.txtpb index 1d9d094..d629c8d 100644 --- a/data/maps/the_revitalized/rooms/Return Room.txtpb +++ b/data/maps/the_revitalized/rooms/Return Room.txtpb
@@ -1,5 +1,4 @@
1name: "Return Room" 1name: "Return Room"
2display_name: "Revitalized"
3panels { 2panels {
4 name: "RETURN" 3 name: "RETURN"
5 path: "Components/panel_7" 4 path: "Components/panel_7"
diff --git a/data/maps/the_revitalized/rooms/Too Room.txtpb b/data/maps/the_revitalized/rooms/Too Room.txtpb index a35b80f..819c3cf 100644 --- a/data/maps/the_revitalized/rooms/Too Room.txtpb +++ b/data/maps/the_revitalized/rooms/Too Room.txtpb
@@ -1,5 +1,4 @@
1name: "Too Room" 1name: "Too Room"
2display_name: "Revitalized"
3panels { 2panels {
4 name: "TOO" 3 name: "TOO"
5 path: "Panels/panel_6" 4 path: "Panels/panel_6"
diff --git a/data/maps/the_revitalized/rooms/Won Room.txtpb b/data/maps/the_revitalized/rooms/Won Room.txtpb index 16766fb..8cedd1d 100644 --- a/data/maps/the_revitalized/rooms/Won Room.txtpb +++ b/data/maps/the_revitalized/rooms/Won Room.txtpb
@@ -1,5 +1,4 @@
1name: "Won Room" 1name: "Won Room"
2display_name: "Revitalized"
3panels { 2panels {
4 name: "WON" 3 name: "WON"
5 path: "Panels/panel_5" 4 path: "Panels/panel_5"
diff --git a/data/maps/the_shop/rooms/Main Area.txtpb b/data/maps/the_shop/rooms/Main Area.txtpb index eb0e696..df1cb14 100644 --- a/data/maps/the_shop/rooms/Main Area.txtpb +++ b/data/maps/the_shop/rooms/Main Area.txtpb
@@ -1,5 +1,4 @@
1name: "Main Area" 1name: "Main Area"
2display_name: "Shop"
3panels { 2panels {
4 name: "DUCKS" 3 name: "DUCKS"
5 path: "Panels/Books/panel_1" 4 path: "Panels/Books/panel_1"
@@ -156,9 +155,13 @@ panels {
156} 155}
157ports { 156ports {
158 name: "ENTRY" 157 name: "ENTRY"
158 display_name: "Entrance"
159 path: "Components/Warps/worldport" 159 path: "Components/Warps/worldport"
160 destination { x: 4 y: 0 z: 12 }
161 rotation: 90
160} 162}
161keyholders { 163keyholders {
162 name: "N" 164 name: "N"
163 path: "Components/KeyHolders/keyHolderN" 165 path: "Components/KeyHolders/keyHolderN"
166 key: "n"
164} 167}
diff --git a/data/maps/the_sirenic/rooms/Mastery.txtpb b/data/maps/the_sirenic/rooms/Mastery.txtpb index 849202b..749837e 100644 --- a/data/maps/the_sirenic/rooms/Mastery.txtpb +++ b/data/maps/the_sirenic/rooms/Mastery.txtpb
@@ -1,5 +1,4 @@
1name: "Mastery" 1name: "Mastery"
2display_name: "Sirenic"
3masteries { 2masteries {
4 name: "MASTERY" 3 name: "MASTERY"
5 path: "Components/Collectables/smiley" 4 path: "Components/Collectables/smiley"
diff --git a/data/maps/the_sirenic/rooms/Puzzles.txtpb b/data/maps/the_sirenic/rooms/Puzzles.txtpb index 6784163..0f62cbd 100644 --- a/data/maps/the_sirenic/rooms/Puzzles.txtpb +++ b/data/maps/the_sirenic/rooms/Puzzles.txtpb
@@ -1,5 +1,4 @@
1name: "Puzzles" 1name: "Puzzles"
2display_name: "Sirenic"
3panels { 2panels {
4 name: "Left Top 1" 3 name: "Left Top 1"
5 path: "Panels/Room_1/pip_1" 4 path: "Panels/Room_1/pip_1"
diff --git a/data/maps/the_sirenic/rooms/Start.txtpb b/data/maps/the_sirenic/rooms/Start.txtpb index 61150d9..532d951 100644 --- a/data/maps/the_sirenic/rooms/Start.txtpb +++ b/data/maps/the_sirenic/rooms/Start.txtpb
@@ -1,5 +1,4 @@
1name: "Start" 1name: "Start"
2display_name: "Sirenic"
3panels { 2panels {
4 name: "Flipped" 3 name: "Flipped"
5 path: "Panels/Entry/entry_2" 4 path: "Panels/Entry/entry_2"
@@ -16,6 +15,8 @@ panels {
16} 15}
17ports { 16ports {
18 name: "PLAZA" 17 name: "PLAZA"
18 display_name: "Entrance"
19 path: "Components/Warps/worldport" 19 path: "Components/Warps/worldport"
20 orientation: "south" 20 destination { x: 0 y: 0 z: 26 }
21 rotation: 0
21} 22}
diff --git a/data/maps/the_stormy/rooms/Center.txtpb b/data/maps/the_stormy/rooms/Center.txtpb index 62395ba..6a929a7 100644 --- a/data/maps/the_stormy/rooms/Center.txtpb +++ b/data/maps/the_stormy/rooms/Center.txtpb
@@ -1,5 +1,4 @@
1name: "Center" 1name: "Center"
2display_name: "Stormy"
3panels { 2panels {
4 name: "REACTOR" 3 name: "REACTOR"
5 path: "Panels/Room_1/panel_7" 4 path: "Panels/Room_1/panel_7"
@@ -20,6 +19,7 @@ panels {
20 clue: "cloud" 19 clue: "cloud"
21 answer: "rain" 20 answer: "rain"
22 symbols: AGE 21 symbols: AGE
22 display_name: "CLOUD (1)"
23} 23}
24panels { 24panels {
25 name: "WIND" 25 name: "WIND"
@@ -27,9 +27,12 @@ panels {
27 clue: "wind" 27 clue: "wind"
28 answer: "tornado" 28 answer: "tornado"
29 symbols: CROSS 29 symbols: CROSS
30 display_name: "WIND (1)"
30} 31}
31ports { 32ports {
32 name: "ENTRY" 33 name: "ENTRY"
34 display_name: "Worldport"
33 path: "Components/Warps/worldport" 35 path: "Components/Warps/worldport"
34 orientation: "west" 36 destination { x: -8.5 y: 0 z: 6 }
37 rotation: 270
35} 38}
diff --git a/data/maps/the_stormy/rooms/Nuclear Side.txtpb b/data/maps/the_stormy/rooms/Nuclear Side.txtpb index 15d393b..7704cfb 100644 --- a/data/maps/the_stormy/rooms/Nuclear Side.txtpb +++ b/data/maps/the_stormy/rooms/Nuclear Side.txtpb
@@ -1,5 +1,4 @@
1name: "Nuclear Side" 1name: "Nuclear Side"
2display_name: "Stormy"
3panels { 2panels {
4 name: "GERM" 3 name: "GERM"
5 path: "Panels/Room_1/panel_2" 4 path: "Panels/Room_1/panel_2"
diff --git a/data/maps/the_stormy/rooms/Nuclear Vestibule.txtpb b/data/maps/the_stormy/rooms/Nuclear Vestibule.txtpb index 1d9c46d..34a6715 100644 --- a/data/maps/the_stormy/rooms/Nuclear Vestibule.txtpb +++ b/data/maps/the_stormy/rooms/Nuclear Vestibule.txtpb
@@ -1,5 +1,4 @@
1name: "Nuclear Vestibule" 1name: "Nuclear Vestibule"
2display_name: "Stormy"
3panels { 2panels {
4 name: "STORM" 3 name: "STORM"
5 path: "Panels/Room 2/panel_11" 4 path: "Panels/Room 2/panel_11"
diff --git a/data/maps/the_stormy/rooms/Rain Side.txtpb b/data/maps/the_stormy/rooms/Rain Side.txtpb index cb59a6d..1babef2 100644 --- a/data/maps/the_stormy/rooms/Rain Side.txtpb +++ b/data/maps/the_stormy/rooms/Rain Side.txtpb
@@ -1,11 +1,11 @@
1name: "Rain Side" 1name: "Rain Side"
2display_name: "Stormy"
3panels { 2panels {
4 name: "CLOUD" 3 name: "CLOUD"
5 path: "Panels/Room_1/panel_4" 4 path: "Panels/Room_1/panel_4"
6 clue: "cloud" 5 clue: "cloud"
7 answer: "lightning" 6 answer: "lightning"
8 symbols: CROSS 7 symbols: CROSS
8 display_name: "CLOUD (2)"
9} 9}
10panels { 10panels {
11 name: "WIND" 11 name: "WIND"
@@ -13,4 +13,5 @@ panels {
13 clue: "wind" 13 clue: "wind"
14 answer: "whirlwind" 14 answer: "whirlwind"
15 symbols: PYRAMID 15 symbols: PYRAMID
16 display_name: "WIND (2)"
16} 17}
diff --git a/data/maps/the_stormy/rooms/Tornado Side.txtpb b/data/maps/the_stormy/rooms/Tornado Side.txtpb index d91d057..1e5ca69 100644 --- a/data/maps/the_stormy/rooms/Tornado Side.txtpb +++ b/data/maps/the_stormy/rooms/Tornado Side.txtpb
@@ -1,5 +1,4 @@
1name: "Tornado Side" 1name: "Tornado Side"
2display_name: "Stormy"
3panels { 2panels {
4 name: "PUDDLE" 3 name: "PUDDLE"
5 path: "Panels/Room_1/panel_6" 4 path: "Panels/Room_1/panel_6"
diff --git a/data/maps/the_stormy/rooms/Tornado Vestibule.txtpb b/data/maps/the_stormy/rooms/Tornado Vestibule.txtpb index 9a98c3e..e6c7e60 100644 --- a/data/maps/the_stormy/rooms/Tornado Vestibule.txtpb +++ b/data/maps/the_stormy/rooms/Tornado Vestibule.txtpb
@@ -1,5 +1,4 @@
1name: "Tornado Vestibule" 1name: "Tornado Vestibule"
2display_name: "Stormy"
3panels { 2panels {
4 name: "SHIP" 3 name: "SHIP"
5 path: "Panels/Room 2/panel_12" 4 path: "Panels/Room 2/panel_12"
diff --git a/data/maps/the_stormy/rooms/Volcano Side.txtpb b/data/maps/the_stormy/rooms/Volcano Side.txtpb index bd823d5..73c7ae4 100644 --- a/data/maps/the_stormy/rooms/Volcano Side.txtpb +++ b/data/maps/the_stormy/rooms/Volcano Side.txtpb
@@ -1,5 +1,4 @@
1name: "Volcano Side" 1name: "Volcano Side"
2display_name: "Stormy"
3panels { 2panels {
4 name: "SNOW" 3 name: "SNOW"
5 path: "Panels/Room_1/panel_1" 4 path: "Panels/Room_1/panel_1"
diff --git a/data/maps/the_stormy/rooms/X2 Room.txtpb b/data/maps/the_stormy/rooms/X2 Room.txtpb index 7d46956..3be4def 100644 --- a/data/maps/the_stormy/rooms/X2 Room.txtpb +++ b/data/maps/the_stormy/rooms/X2 Room.txtpb
@@ -1,5 +1,4 @@
1name: "X2 Room" 1name: "X2 Room"
2display_name: "Stormy"
3letters { 2letters {
4 key: "x" 3 key: "x"
5 level2: true 4 level2: true
diff --git a/data/maps/the_sturdy/rooms/Main Area.txtpb b/data/maps/the_sturdy/rooms/Main Area.txtpb index 39a425f..8c81a1e 100644 --- a/data/maps/the_sturdy/rooms/Main Area.txtpb +++ b/data/maps/the_sturdy/rooms/Main Area.txtpb
@@ -1,5 +1,4 @@
1name: "Main Area" 1name: "Main Area"
2display_name: "Sturdy"
3panels { 2panels {
4 name: "MOVE (1)" 3 name: "MOVE (1)"
5 path: "Panels/Main/panel_1" 4 path: "Panels/Main/panel_1"
@@ -11,7 +10,7 @@ panels {
11 proxies { answer: "down" path: "Panels/Down/down_1" } 10 proxies { answer: "down" path: "Panels/Down/down_1" }
12 proxies { answer: "left" path: "Panels/Left/left_1" } 11 proxies { answer: "left" path: "Panels/Left/left_1" }
13 proxies { answer: "right" path: "Panels/Right/right_1" } 12 proxies { answer: "right" path: "Panels/Right/right_1" }
14 #proxies { answer: "move" path: "Panels/Secret/secret_1" } 13 proxies { answer: "move" path: "Panels/Secret/secret_1" }
15} 14}
16panels { 15panels {
17 name: "MOVE (2)" 16 name: "MOVE (2)"
@@ -24,7 +23,7 @@ panels {
24 proxies { answer: "down" path: "Panels/Down/down_2" } 23 proxies { answer: "down" path: "Panels/Down/down_2" }
25 proxies { answer: "left" path: "Panels/Left/left_2" } 24 proxies { answer: "left" path: "Panels/Left/left_2" }
26 proxies { answer: "right" path: "Panels/Right/right_2" } 25 proxies { answer: "right" path: "Panels/Right/right_2" }
27 #proxies { answer: "move" path: "Panels/Secret/secret_2" } 26 proxies { answer: "move" path: "Panels/Secret/secret_2" }
28} 27}
29panels { 28panels {
30 name: "MOVE (3)" 29 name: "MOVE (3)"
@@ -37,7 +36,7 @@ panels {
37 proxies { answer: "down" path: "Panels/Down/down_3" } 36 proxies { answer: "down" path: "Panels/Down/down_3" }
38 proxies { answer: "left" path: "Panels/Left/left_3" } 37 proxies { answer: "left" path: "Panels/Left/left_3" }
39 proxies { answer: "right" path: "Panels/Right/right_3" } 38 proxies { answer: "right" path: "Panels/Right/right_3" }
40 #proxies { answer: "move" path: "Panels/Secret/secret_3" } 39 proxies { answer: "move" path: "Panels/Secret/secret_3" }
41} 40}
42panels { 41panels {
43 name: "MOVE (4)" 42 name: "MOVE (4)"
@@ -50,7 +49,7 @@ panels {
50 proxies { answer: "down" path: "Panels/Down/down_4" } 49 proxies { answer: "down" path: "Panels/Down/down_4" }
51 proxies { answer: "left" path: "Panels/Left/left_4" } 50 proxies { answer: "left" path: "Panels/Left/left_4" }
52 proxies { answer: "right" path: "Panels/Right/right_4" } 51 proxies { answer: "right" path: "Panels/Right/right_4" }
53 #proxies { answer: "move" path: "Panels/Secret/secret_4" } 52 proxies { answer: "move" path: "Panels/Secret/secret_4" }
54} 53}
55panels { 54panels {
56 name: "MOVE (5)" 55 name: "MOVE (5)"
@@ -63,7 +62,7 @@ panels {
63 proxies { answer: "down" path: "Panels/Down/down_5" } 62 proxies { answer: "down" path: "Panels/Down/down_5" }
64 proxies { answer: "left" path: "Panels/Left/left_5" } 63 proxies { answer: "left" path: "Panels/Left/left_5" }
65 proxies { answer: "right" path: "Panels/Right/right_5" } 64 proxies { answer: "right" path: "Panels/Right/right_5" }
66 #proxies { answer: "move" path: "Panels/Secret/secret_5" } 65 proxies { answer: "move" path: "Panels/Secret/secret_5" }
67} 66}
68panels { 67panels {
69 name: "MOVE (6)" 68 name: "MOVE (6)"
@@ -76,7 +75,7 @@ panels {
76 proxies { answer: "down" path: "Panels/Down/down_6" } 75 proxies { answer: "down" path: "Panels/Down/down_6" }
77 proxies { answer: "left" path: "Panels/Left/left_6" } 76 proxies { answer: "left" path: "Panels/Left/left_6" }
78 proxies { answer: "right" path: "Panels/Right/right_6" } 77 proxies { answer: "right" path: "Panels/Right/right_6" }
79 #proxies { answer: "move" path: "Panels/Secret/secret_6" } 78 proxies { answer: "move" path: "Panels/Secret/secret_6" }
80} 79}
81panels { 80panels {
82 name: "MOVE (7)" 81 name: "MOVE (7)"
@@ -89,7 +88,7 @@ panels {
89 proxies { answer: "down" path: "Panels/Down/down_7" } 88 proxies { answer: "down" path: "Panels/Down/down_7" }
90 proxies { answer: "left" path: "Panels/Left/left_7" } 89 proxies { answer: "left" path: "Panels/Left/left_7" }
91 proxies { answer: "right" path: "Panels/Right/right_7" } 90 proxies { answer: "right" path: "Panels/Right/right_7" }
92 #proxies { answer: "move" path: "Panels/Secret/secret_7" } 91 proxies { answer: "move" path: "Panels/Secret/secret_7" }
93} 92}
94panels { 93panels {
95 name: "MOVE (8)" 94 name: "MOVE (8)"
@@ -102,13 +101,19 @@ panels {
102 proxies { answer: "down" path: "Panels/Down/down_8" } 101 proxies { answer: "down" path: "Panels/Down/down_8" }
103 proxies { answer: "left" path: "Panels/Left/left_8" } 102 proxies { answer: "left" path: "Panels/Left/left_8" }
104 proxies { answer: "right" path: "Panels/Right/right_8" } 103 proxies { answer: "right" path: "Panels/Right/right_8" }
105 #proxies { answer: "move" path: "Panels/Secret/secret_8" } 104 proxies { answer: "move" path: "Panels/Secret/secret_8" }
106} 105}
107ports { 106ports {
108 name: "OWL" 107 name: "OWL"
108 display_name: "Magenta Hallway"
109 path: "Components/Warps/worldport" 109 path: "Components/Warps/worldport"
110 destination { x: 17 y: 0 z: 41 }
111 rotation: 90
110} 112}
111ports { 113ports {
112 name: "COLORFUL" 114 name: "COLORFUL"
115 display_name: "Cyan Hallway"
113 path: "Components/Warps/worldport2" 116 path: "Components/Warps/worldport2"
117 destination { x: 17 y: 0 z: -33 }
118 rotation: 90
114} 119}
diff --git a/data/maps/the_sturdy/rooms/S2 Area.txtpb b/data/maps/the_sturdy/rooms/S2 Area.txtpb index 118b914..38fad5e 100644 --- a/data/maps/the_sturdy/rooms/S2 Area.txtpb +++ b/data/maps/the_sturdy/rooms/S2 Area.txtpb
@@ -1,5 +1,4 @@
1name: "S2 Area" 1name: "S2 Area"
2display_name: "Sturdy"
3panels { 2panels {
4 name: "COLORS" 3 name: "COLORS"
5 path: "Panels/Rainbow/panel_1" 4 path: "Panels/Rainbow/panel_1"
diff --git a/data/maps/the_sun_temple/connections.txtpb b/data/maps/the_sun_temple/connections.txtpb index b0b3a0a..ffe4d5d 100644 --- a/data/maps/the_sun_temple/connections.txtpb +++ b/data/maps/the_sun_temple/connections.txtpb
@@ -7,6 +7,7 @@ connections {
7 from_room: "Temple" 7 from_room: "Temple"
8 to_room: "Ending" 8 to_room: "Ending"
9 door { name: "Ending" } 9 door { name: "Ending" }
10 purple_ending: true
10} 11}
11connections { 12connections {
12 from_room: "Temple" 13 from_room: "Temple"
diff --git a/data/maps/the_sun_temple/rooms/Ending.txtpb b/data/maps/the_sun_temple/rooms/Ending.txtpb index a94e606..975374a 100644 --- a/data/maps/the_sun_temple/rooms/Ending.txtpb +++ b/data/maps/the_sun_temple/rooms/Ending.txtpb
@@ -1,5 +1,4 @@
1name: "Ending" 1name: "Ending"
2display_name: "Sun Temple"
3endings { 2endings {
4 name: "PURPLE" 3 name: "PURPLE"
5 path: "Components/purple_ending" 4 path: "Components/purple_ending"
diff --git a/data/maps/the_sun_temple/rooms/Entrance.txtpb b/data/maps/the_sun_temple/rooms/Entrance.txtpb index 0b2a0bd..07d6e38 100644 --- a/data/maps/the_sun_temple/rooms/Entrance.txtpb +++ b/data/maps/the_sun_temple/rooms/Entrance.txtpb
@@ -1,14 +1,16 @@
1name: "Entrance" 1name: "Entrance"
2display_name: "Sun Temple"
3panels { 2panels {
4 name: "SUN" 3 name: "SUN"
5 path: "Panels/Main/panel_1" 4 path: "Panels/Main/panel_1"
6 clue: "sun" 5 clue: "sun"
7 answer: "sun" 6 answer: "sun"
8 #proxies { answer: "sun" path: "Panels/Sun/panel_8" } 7 proxies { answer: "sun" path: "Panels/Sun/panel_8" }
9 proxies { answer: "moon" path: "Panels/Moon/panel_15" } 8 proxies { answer: "moon" path: "Panels/Moon/panel_15" }
10} 9}
11ports { 10ports {
12 name: "UNKEMPT" 11 name: "UNKEMPT"
12 display_name: "Entrance"
13 path: "Components/Warps/worldport" 13 path: "Components/Warps/worldport"
14 destination { x: 0 y: 0 z: 13 }
15 rotation: 0
14} 16}
diff --git a/data/maps/the_sun_temple/rooms/Mastery.txtpb b/data/maps/the_sun_temple/rooms/Mastery.txtpb index b416a9a..bbe8742 100644 --- a/data/maps/the_sun_temple/rooms/Mastery.txtpb +++ b/data/maps/the_sun_temple/rooms/Mastery.txtpb
@@ -1,5 +1,4 @@
1name: "Mastery" 1name: "Mastery"
2display_name: "Sun Temple"
3masteries { 2masteries {
4 name: "MASTERY" 3 name: "MASTERY"
5 path: "Components/Collectables/collectable" 4 path: "Components/Collectables/collectable"
diff --git a/data/maps/the_sun_temple/rooms/Temple.txtpb b/data/maps/the_sun_temple/rooms/Temple.txtpb index 6281584..4f39737 100644 --- a/data/maps/the_sun_temple/rooms/Temple.txtpb +++ b/data/maps/the_sun_temple/rooms/Temple.txtpb
@@ -1,12 +1,11 @@
1name: "Temple" 1name: "Temple"
2display_name: "Sun Temple"
3panels { 2panels {
4 name: "DELAY" 3 name: "DELAY"
5 path: "Panels/Main/panel_2" 4 path: "Panels/Main/panel_2"
6 clue: "delay" 5 clue: "delay"
7 answer: "day" 6 answer: "day"
8 symbols: SPARKLES 7 symbols: SPARKLES
9 #proxies { answer: "day" path: "Panels/Sun/panel_9" } 8 proxies { answer: "day" path: "Panels/Sun/panel_9" }
10 proxies { answer: "night" path: "Panels/Moon/panel_16" } 9 proxies { answer: "night" path: "Panels/Moon/panel_16" }
11} 10}
12panels { 11panels {
@@ -15,7 +14,7 @@ panels {
15 clue: "lawn" 14 clue: "lawn"
16 answer: "dawn" 15 answer: "dawn"
17 symbols: SPARKLES 16 symbols: SPARKLES
18 #proxies { answer: "dawn" path: "Panels/Sun/panel_10" } 17 proxies { answer: "dawn" path: "Panels/Sun/panel_10" }
19 proxies { answer: "dusk" path: "Panels/Moon/panel_17" } 18 proxies { answer: "dusk" path: "Panels/Moon/panel_17" }
20} 19}
21panels { 20panels {
@@ -24,7 +23,7 @@ panels {
24 clue: "jump" 23 clue: "jump"
25 answer: "spring" 24 answer: "spring"
26 symbols: SUN 25 symbols: SUN
27 #proxies { answer: "spring" path: "Panels/Sun/panel_11" } 26 proxies { answer: "spring" path: "Panels/Sun/panel_11" }
28 proxies { answer: "autumn" path: "Panels/Moon/panel_18" } 27 proxies { answer: "autumn" path: "Panels/Moon/panel_18" }
29} 28}
30panels { 29panels {
@@ -33,7 +32,7 @@ panels {
33 clue: "heavy" 32 clue: "heavy"
34 answer: "light" 33 answer: "light"
35 symbols: SUN 34 symbols: SUN
36 #proxies { answer: "light" path: "Panels/Sun/panel_12" } 35 proxies { answer: "light" path: "Panels/Sun/panel_12" }
37 proxies { answer: "dark" path: "Panels/Moon/panel_19" } 36 proxies { answer: "dark" path: "Panels/Moon/panel_19" }
38} 37}
39panels { 38panels {
@@ -42,7 +41,7 @@ panels {
42 clue: "knife" 41 clue: "knife"
43 answer: "life" 42 answer: "life"
44 symbols: ZERO 43 symbols: ZERO
45 #proxies { answer: "life" path: "Panels/Sun/panel_13" } 44 proxies { answer: "life" path: "Panels/Sun/panel_13" }
46 proxies { answer: "death" path: "Panels/Moon/panel_20" } 45 proxies { answer: "death" path: "Panels/Moon/panel_20" }
47} 46}
48panels { 47panels {
@@ -51,7 +50,7 @@ panels {
51 clue: "arm" 50 clue: "arm"
52 answer: "warmth" 51 answer: "warmth"
53 symbols: SPARKLES 52 symbols: SPARKLES
54 #proxies { answer: "warmth" path: "Panels/Sun/panel_14" } 53 proxies { answer: "warmth" path: "Panels/Sun/panel_14" }
55 proxies { answer: "chill" path: "Panels/Moon/panel_21" } 54 proxies { answer: "chill" path: "Panels/Moon/panel_21" }
56} 55}
57panels { 56panels {
@@ -60,5 +59,5 @@ panels {
60 clue: "equinox" 59 clue: "equinox"
61 answer: "equinox" 60 answer: "equinox"
62 proxies { answer: "solstice" path: "Panels/End/panel_23" } 61 proxies { answer: "solstice" path: "Panels/End/panel_23" }
63 #proxies { answer: "equinox" path: "Panels/End/panel_24" } 62 proxies { answer: "equinox" path: "Panels/End/panel_24" }
64} 63}
diff --git a/data/maps/the_sweet/rooms/Main Area.txtpb b/data/maps/the_sweet/rooms/Main Area.txtpb index b72b6d4..a8976f7 100644 --- a/data/maps/the_sweet/rooms/Main Area.txtpb +++ b/data/maps/the_sweet/rooms/Main Area.txtpb
@@ -1,5 +1,4 @@
1name: "Main Area" 1name: "Main Area"
2display_name: "Sweet"
3panels { 2panels {
4 name: "POTATO" 3 name: "POTATO"
5 path: "Panels/Sweetening Room/panel_1" 4 path: "Panels/Sweetening Room/panel_1"
@@ -201,9 +200,15 @@ panels {
201} 200}
202ports { 201ports {
203 name: "EXIT1" 202 name: "EXIT1"
203 display_name: "South Worldport"
204 path: "Components/Warps/worldport" 204 path: "Components/Warps/worldport"
205 destination { x: 0 y: 0 z: -11.5 }
206 rotation: 180
205} 207}
206ports { 208ports {
207 name: "EXIT2" 209 name: "EXIT2"
210 display_name: "North Worldport"
208 path: "Components/Warps/worldport2" 211 path: "Components/Warps/worldport2"
212 destination { x: 0 y: 0 z: -17.5 }
213 rotation: 0
209} 214}
diff --git a/data/maps/the_sweet/rooms/Y2 Room.txtpb b/data/maps/the_sweet/rooms/Y2 Room.txtpb index 4da87f3..d448f57 100644 --- a/data/maps/the_sweet/rooms/Y2 Room.txtpb +++ b/data/maps/the_sweet/rooms/Y2 Room.txtpb
@@ -1,5 +1,4 @@
1name: "Y2 Room" 1name: "Y2 Room"
2display_name: "Sweet"
3letters { 2letters {
4 key: "y" 3 key: "y"
5 level2: true 4 level2: true
diff --git a/data/maps/the_symbolic/doors.txtpb b/data/maps/the_symbolic/doors.txtpb index e84811e..5a443e7 100644 --- a/data/maps/the_symbolic/doors.txtpb +++ b/data/maps/the_symbolic/doors.txtpb
@@ -1,62 +1,55 @@
1doors { 1doors {
2 name: "White Door" 2 name: "White Door"
3 type: STANDARD 3 type: EVENT
4 receivers: "Components/Doors/Door18" 4 #receivers: "Components/Doors/Door18"
5 panels { room: "White Room" name: "WRITE" } 5 panels { room: "White Room" name: "WRITE" }
6 location_room: "White Room"
7} 6}
8doors { 7doors {
9 name: "Black Door" 8 name: "Black Door"
10 type: STANDARD 9 type: EVENT
11 receivers: "Components/Doors/Door19" 10 #receivers: "Components/Doors/Door19"
12 panels { room: "Black Room" name: "HERE" } 11 panels { room: "Black Room" name: "HERE" }
13 location_room: "Black Room"
14} 12}
15doors { 13doors {
16 name: "Red Door" 14 name: "Red Door"
17 type: STANDARD 15 type: EVENT
18 receivers: "Components/Doors/Door20" 16 #receivers: "Components/Doors/Door20"
19 panels { room: "Red Room" name: "SYNONYM" } 17 panels { room: "Red Room" name: "SYNONYM" }
20 location_room: "Red Room"
21} 18}
22doors { 19doors {
23 name: "Blue Door" 20 name: "Blue Door"
24 type: STANDARD 21 type: EVENT
25 receivers: "Components/Doors/Door21" 22 #receivers: "Components/Doors/Door21"
26 panels { room: "Blue Room" name: "DEPLETE" } 23 panels { room: "Blue Room" name: "DEPLETE" }
27 location_room: "Blue Room"
28} 24}
29doors { 25doors {
30 name: "Green Door" 26 name: "Green Door"
31 type: STANDARD 27 type: EVENT
32 receivers: "Components/Doors/Door22" 28 #receivers: "Components/Doors/Door22"
33 panels { room: "Green Room" name: "INERT" } 29 panels { room: "Green Room" name: "INERT" }
34 location_room: "Green Room"
35} 30}
36doors { 31doors {
37 name: "Yellow Door" 32 name: "Yellow Door"
38 type: STANDARD 33 type: EVENT
39 receivers: "Components/Doors/Door23" 34 #receivers: "Components/Doors/Door23"
40 panels { room: "Yellow Room" name: "WHOLE" } 35 panels { room: "Yellow Room" name: "WHOLE" }
41 location_room: "Yellow Room"
42} 36}
43doors { 37doors {
44 name: "Purple Door" 38 name: "Purple Door"
45 type: STANDARD 39 type: EVENT
46 receivers: "Components/Doors/Door24" 40 #receivers: "Components/Doors/Door24"
47 panels { room: "Purple Room" name: "TIME" } 41 panels { room: "Purple Room" name: "TIME" }
48 location_room: "Purple Room"
49} 42}
50doors { 43doors {
51 name: "Orange Door" 44 name: "Orange Door"
52 type: STANDARD 45 type: EVENT
53 receivers: "Components/Doors/Door25" 46 #receivers: "Components/Doors/Door25"
54 panels { room: "Orange Room" name: "YOUNG" } 47 panels { room: "Orange Room" name: "YOUNG" }
55 location_room: "Orange Room"
56} 48}
57doors { 49doors {
58 name: "Tutorial Door" 50 name: "Tutorial Door"
59 type: EVENT 51 type: ITEM_ONLY
52 receivers: "Components/Doors/Door"
60 panels { room: "Tutorial" name: "<- (1)" } 53 panels { room: "Tutorial" name: "<- (1)" }
61 panels { room: "Tutorial" name: "<- (2)" } 54 panels { room: "Tutorial" name: "<- (2)" }
62 panels { room: "Tutorial" name: "<- (3)" } 55 panels { room: "Tutorial" name: "<- (3)" }
diff --git a/data/maps/the_symbolic/rooms/Poetry Room 1.txtpb b/data/maps/the_symbolic/rooms/Poetry Room 1.txtpb index 523e260..a6ae04c 100644 --- a/data/maps/the_symbolic/rooms/Poetry Room 1.txtpb +++ b/data/maps/the_symbolic/rooms/Poetry Room 1.txtpb
@@ -5,7 +5,7 @@ panels {
5 clue: "absorbed" 5 clue: "absorbed"
6 answer: "abs" 6 answer: "abs"
7 symbols: EVAL 7 symbols: EVAL
8 #proxies { answer: "abs" path: "Panels/Proxy/absorbed_proxied_1" } 8 proxies { answer: "abs" path: "Panels/Proxy/absorbed_proxied_1" }
9 proxies { answer: "bed" path: "Panels/Proxy/absorbed_proxied_2" } 9 proxies { answer: "bed" path: "Panels/Proxy/absorbed_proxied_2" }
10} 10}
11panels { 11panels {
@@ -14,6 +14,6 @@ panels {
14 clue: "primordial" 14 clue: "primordial"
15 answer: "prim" 15 answer: "prim"
16 symbols: EVAL 16 symbols: EVAL
17 #proxies { answer: "prim" path: "Panels/Proxy/primordial_proxied_1" } 17 proxies { answer: "prim" path: "Panels/Proxy/primordial_proxied_1" }
18 proxies { answer: "dial" path: "Panels/Proxy/primordial_proxied_2" } 18 proxies { answer: "dial" path: "Panels/Proxy/primordial_proxied_2" }
19} 19}
diff --git a/data/maps/the_symbolic/rooms/Poetry Room 3.txtpb b/data/maps/the_symbolic/rooms/Poetry Room 3.txtpb index 5c62301..e70be1c 100644 --- a/data/maps/the_symbolic/rooms/Poetry Room 3.txtpb +++ b/data/maps/the_symbolic/rooms/Poetry Room 3.txtpb
@@ -18,6 +18,6 @@ panels {
18 answer: "ugly" 18 answer: "ugly"
19 symbols: EVAL 19 symbols: EVAL
20 symbols: LINGO 20 symbols: LINGO
21 #proxies { answer: "ugly" path: "Panels/NotNoT/not_pretty_proxied_1" } 21 proxies { answer: "ugly" path: "Panels/NotNoT/not_pretty_proxied_1" }
22 proxies { answer: "prey" path: "Panels/NotNoT/not_pretty_proxied_2" } 22 proxies { answer: "prey" path: "Panels/NotNoT/not_pretty_proxied_2" }
23} 23}
diff --git a/data/maps/the_symbolic/rooms/Poetry Room Left.txtpb b/data/maps/the_symbolic/rooms/Poetry Room Left.txtpb index 561c034..2d2eb3f 100644 --- a/data/maps/the_symbolic/rooms/Poetry Room Left.txtpb +++ b/data/maps/the_symbolic/rooms/Poetry Room Left.txtpb
@@ -18,6 +18,6 @@ panels {
18 answer: "false" 18 answer: "false"
19 symbols: EVAL 19 symbols: EVAL
20 symbols: LINGO 20 symbols: LINGO
21 #proxies { answer: "false" path: "Panels/NotNoT/not_true_proxied_1" } 21 proxies { answer: "false" path: "Panels/NotNoT/not_true_proxied_1" }
22 proxies { answer: "rue" path: "Panels/NotNoT/not_true_proxied_2" } 22 proxies { answer: "rue" path: "Panels/NotNoT/not_true_proxied_2" }
23} 23}
diff --git a/data/maps/the_symbolic/rooms/Poetry Room Right.txtpb b/data/maps/the_symbolic/rooms/Poetry Room Right.txtpb index 4928191..490a6a7 100644 --- a/data/maps/the_symbolic/rooms/Poetry Room Right.txtpb +++ b/data/maps/the_symbolic/rooms/Poetry Room Right.txtpb
@@ -18,6 +18,6 @@ panels {
18 answer: "worse" 18 answer: "worse"
19 symbols: EVAL 19 symbols: EVAL
20 symbols: LINGO 20 symbols: LINGO
21 #proxies { answer: "worse" path: "Panels/NotNoT/not_better_proxied_1" } 21 proxies { answer: "worse" path: "Panels/NotNoT/not_better_proxied_1" }
22 proxies { answer: "beer" path: "Panels/NotNoT/not_better_proxied_2" } 22 proxies { answer: "beer" path: "Panels/NotNoT/not_better_proxied_2" }
23} 23}
diff --git a/data/maps/the_symbolic/rooms/Red Blue Room.txtpb b/data/maps/the_symbolic/rooms/Red Blue Room.txtpb index cb057b0..c246853 100644 --- a/data/maps/the_symbolic/rooms/Red Blue Room.txtpb +++ b/data/maps/the_symbolic/rooms/Red Blue Room.txtpb
@@ -6,7 +6,7 @@ panels {
6 answer: "word" 6 answer: "word"
7 symbols: ZERO 7 symbols: ZERO
8 symbols: EVAL 8 symbols: EVAL
9 #proxies { answer: "word" path: "Panels/Entry/rightward_proxyied_1" } 9 proxies { answer: "word" path: "Panels/Entry/rightward_proxyied_1" }
10 proxies { answer: "whirred" path: "Panels/Entry/rightward_proxyied_2" } 10 proxies { answer: "whirred" path: "Panels/Entry/rightward_proxyied_2" }
11} 11}
12panels { 12panels {
@@ -15,6 +15,6 @@ panels {
15 clue: "typewriting" 15 clue: "typewriting"
16 answer: "writing" 16 answer: "writing"
17 symbols: EVAL 17 symbols: EVAL
18 #proxies { answer: "writing" path: "Panels/Entry/typewriter_proxied_1" } 18 proxies { answer: "writing" path: "Panels/Entry/typewriter_proxied_1" }
19 proxies { answer: "poetry" path: "Panels/Entry/typewriter_proxied_2" } 19 proxies { answer: "poetry" path: "Panels/Entry/typewriter_proxied_2" }
20} 20}
diff --git a/data/maps/the_symbolic/rooms/White Room.txtpb b/data/maps/the_symbolic/rooms/White Room.txtpb index 808588e..d3509cb 100644 --- a/data/maps/the_symbolic/rooms/White Room.txtpb +++ b/data/maps/the_symbolic/rooms/White Room.txtpb
@@ -7,5 +7,8 @@ panels {
7} 7}
8ports { 8ports {
9 name: "PLAZA" 9 name: "PLAZA"
10 display_name: "Entrance"
10 path: "Components/Warps/worldport" 11 path: "Components/Warps/worldport"
12 destination { x: 0 y: 0 z: 2.5 }
13 rotation: 0
11} 14}
diff --git a/data/maps/the_talented/rooms/Main Area.txtpb b/data/maps/the_talented/rooms/Main Area.txtpb index cc3e222..a0dac7b 100644 --- a/data/maps/the_talented/rooms/Main Area.txtpb +++ b/data/maps/the_talented/rooms/Main Area.txtpb
@@ -107,8 +107,12 @@ panels {
107keyholders { 107keyholders {
108 name: "Y" 108 name: "Y"
109 path: "Components/KeyHolders/keyHolderY" 109 path: "Components/KeyHolders/keyHolderY"
110 key: "y"
110} 111}
111ports { 112ports {
112 name: "GREAT" 113 name: "GREAT"
114 display_name: "Entrance"
113 path: "Components/Warps/worldport" 115 path: "Components/Warps/worldport"
116 destination { x: -3.5 y: 0 z: 21 }
117 rotation: 270
114} 118}
diff --git a/data/maps/the_tenacious/rooms/Control Center Entrance.txtpb b/data/maps/the_tenacious/rooms/Control Center Entrance.txtpb index 45a0d12..873fabe 100644 --- a/data/maps/the_tenacious/rooms/Control Center Entrance.txtpb +++ b/data/maps/the_tenacious/rooms/Control Center Entrance.txtpb
@@ -8,5 +8,10 @@ panels {
8} 8}
9ports { 9ports {
10 name: "CC" 10 name: "CC"
11 display_name: "Control Center Connector"
11 path: "Components/Warps/worldport" 12 path: "Components/Warps/worldport"
13 destination { x: 0 y: 0 z: 10 }
14 rotation: 0
15 # TODO: shuffle entrances with dependent keyholders
16 no_shuffle: true
12} 17}
diff --git a/data/maps/the_tenacious/rooms/Main Area.txtpb b/data/maps/the_tenacious/rooms/Main Area.txtpb index 8190827..18356e7 100644 --- a/data/maps/the_tenacious/rooms/Main Area.txtpb +++ b/data/maps/the_tenacious/rooms/Main Area.txtpb
@@ -2,4 +2,5 @@ name: "Main Area"
2keyholders { 2keyholders {
3 name: "K" 3 name: "K"
4 path: "Components/KeyHolders/keyHolderK" 4 path: "Components/KeyHolders/keyHolderK"
5 key: "k"
5} 6}
diff --git a/data/maps/the_three_doors/doors.txtpb b/data/maps/the_three_doors/doors.txtpb index 99fbcee..5ae9d90 100644 --- a/data/maps/the_three_doors/doors.txtpb +++ b/data/maps/the_three_doors/doors.txtpb
@@ -50,4 +50,5 @@ doors {
50 panels { room: "Dead End Room" name: "DEAD" } 50 panels { room: "Dead End Room" name: "DEAD" }
51 panels { room: "Dead End Room" name: "END" } 51 panels { room: "Dead End Room" name: "END" }
52 location_room: "Loose Strings Room" 52 location_room: "Loose Strings Room"
53 location_name: "Gravestone"
53} 54}
diff --git a/data/maps/the_three_doors/rooms/Dead End Room.txtpb b/data/maps/the_three_doors/rooms/Dead End Room.txtpb index c752368..8bfe193 100644 --- a/data/maps/the_three_doors/rooms/Dead End Room.txtpb +++ b/data/maps/the_three_doors/rooms/Dead End Room.txtpb
@@ -29,9 +29,15 @@ panels {
29} 29}
30ports { 30ports {
31 name: "BEGIN" 31 name: "BEGIN"
32 display_name: "Door Ways Worldport"
32 path: "Components/Warps/worldport6" 33 path: "Components/Warps/worldport6"
34 destination { x: -38 y: 0 z: 41.5 }
35 rotation: 0
33} 36}
34ports { 37ports {
35 name: "BEGIN2" 38 name: "BEGIN2"
39 display_name: "Dead End Worldport"
36 path: "Components/Warps/worldport5" 40 path: "Components/Warps/worldport5"
41 destination { x: -38 y: 0 z: 27.5 }
42 rotation: 180
37} 43}
diff --git a/data/maps/the_three_doors/rooms/First Second Room.txtpb b/data/maps/the_three_doors/rooms/First Second Room.txtpb index 1bee8c7..bdf5b49 100644 --- a/data/maps/the_three_doors/rooms/First Second Room.txtpb +++ b/data/maps/the_three_doors/rooms/First Second Room.txtpb
@@ -29,9 +29,15 @@ panels {
29} 29}
30ports { 30ports {
31 name: "GREAT" 31 name: "GREAT"
32 display_name: "First Worldport"
32 path: "Components/Warps/worldport" 33 path: "Components/Warps/worldport"
34 destination { x: -16 y: 0 z: 0.5 }
35 rotation: 180
33} 36}
34ports { 37ports {
35 name: "TTD" 38 name: "TTD"
39 display_name: "Second Worldport"
36 path: "Components/Warps/worldport2" 40 path: "Components/Warps/worldport2"
41 destination { x: -16 y: 0 z: 14.5 }
42 rotation: 0
37} 43}
diff --git a/data/maps/the_three_doors/rooms/Loose Strings Room.txtpb b/data/maps/the_three_doors/rooms/Loose Strings Room.txtpb index 9d4430f..21e3c64 100644 --- a/data/maps/the_three_doors/rooms/Loose Strings Room.txtpb +++ b/data/maps/the_three_doors/rooms/Loose Strings Room.txtpb
@@ -15,5 +15,8 @@ panels {
15} 15}
16ports { 16ports {
17 name: "BEGIN" 17 name: "BEGIN"
18 display_name: "Loose Strings Worldport"
18 path: "Components/Warps/worldport7" 19 path: "Components/Warps/worldport7"
20 destination { x: -16 y: 0 z: 41.5 }
21 rotation: 0
19} 22}
diff --git a/data/maps/the_three_doors/rooms/One Luck Room.txtpb b/data/maps/the_three_doors/rooms/One Luck Room.txtpb index 816b4e3..f5053be 100644 --- a/data/maps/the_three_doors/rooms/One Luck Room.txtpb +++ b/data/maps/the_three_doors/rooms/One Luck Room.txtpb
@@ -15,5 +15,8 @@ panels {
15} 15}
16ports { 16ports {
17 name: "BEGIN" 17 name: "BEGIN"
18 display_name: "Lone Chance Worldport"
18 path: "Components/Warps/worldport8" 19 path: "Components/Warps/worldport8"
20 destination { x: -16 y: 0 z: 27.5 }
21 rotation: 180
19} 22}
diff --git a/data/maps/the_three_doors/rooms/Silver Portal Room.txtpb b/data/maps/the_three_doors/rooms/Silver Portal Room.txtpb index aeab9da..1c00045 100644 --- a/data/maps/the_three_doors/rooms/Silver Portal Room.txtpb +++ b/data/maps/the_three_doors/rooms/Silver Portal Room.txtpb
@@ -27,9 +27,15 @@ panels {
27} 27}
28ports { 28ports {
29 name: "BEGIN" 29 name: "BEGIN"
30 display_name: "Third Fourth Worldport"
30 path: "Components/Warps/worldport3" 31 path: "Components/Warps/worldport3"
32 destination { x: -38 y: 0 z: 14.5 }
33 rotation: 0
31} 34}
32ports { 35ports {
33 name: "NEXT" 36 name: "NEXT"
37 display_name: "Silver Portal Worldport"
34 path: "Components/Warps/worldport4" 38 path: "Components/Warps/worldport4"
39 destination { x: -38 y: 0 z: 0.5 }
40 rotation: 180
35} 41}
diff --git a/data/maps/the_tower/rooms/First Floor.txtpb b/data/maps/the_tower/rooms/First Floor.txtpb index 33398a3..7a811bf 100644 --- a/data/maps/the_tower/rooms/First Floor.txtpb +++ b/data/maps/the_tower/rooms/First Floor.txtpb
@@ -97,5 +97,8 @@ panels {
97} 97}
98ports { 98ports {
99 name: "GREAT" 99 name: "GREAT"
100 display_name: "Entrance"
100 path: "Components/Warps/worldport" 101 path: "Components/Warps/worldport"
102 destination { x: -0 y: 0 z: 13 }
103 rotation: 0
101} 104}
diff --git a/data/maps/the_tree/doors.txtpb b/data/maps/the_tree/doors.txtpb index b62a881..6cb4086 100644 --- a/data/maps/the_tree/doors.txtpb +++ b/data/maps/the_tree/doors.txtpb
@@ -38,4 +38,5 @@ doors {
38 panels { room: "Main Area" name: "SMALL (3)" } 38 panels { room: "Main Area" name: "SMALL (3)" }
39 panels { room: "Main Area" name: "SPRINKLE" } 39 panels { room: "Main Area" name: "SPRINKLE" }
40 location_room: "Main Area" 40 location_room: "Main Area"
41 location_name: "Gravestone"
41} 42}
diff --git a/data/maps/the_tree/rooms/Bearer Entrance.txtpb b/data/maps/the_tree/rooms/Bearer Entrance.txtpb index 797e5d0..263a8e8 100644 --- a/data/maps/the_tree/rooms/Bearer Entrance.txtpb +++ b/data/maps/the_tree/rooms/Bearer Entrance.txtpb
@@ -1,5 +1,8 @@
1name: "Bearer Entrance" 1name: "Bearer Entrance"
2ports { 2ports {
3 name: "BEARER" 3 name: "BEARER"
4 display_name: "Brown Control Center Hallway"
4 path: "Components/Warps/worldport" 5 path: "Components/Warps/worldport"
6 destination { x: -15.5 y: 0 z: 20 }
7 rotation: 270
5} 8}
diff --git a/data/maps/the_tree/rooms/Main Area.txtpb b/data/maps/the_tree/rooms/Main Area.txtpb index b232d1e..bd22c2b 100644 --- a/data/maps/the_tree/rooms/Main Area.txtpb +++ b/data/maps/the_tree/rooms/Main Area.txtpb
@@ -211,19 +211,33 @@ panels {
211} 211}
212ports { 212ports {
213 name: "UNKEMPT" 213 name: "UNKEMPT"
214 display_name: "SW Worldport"
214 path: "Components/Warps/worldport4" 215 path: "Components/Warps/worldport4"
216 destination { x: -21 y: 0 z: 7 }
217 rotation: 0
218 # enterable from either side
215} 219}
216ports { 220ports {
217 name: "DIGITAL" 221 name: "DIGITAL"
222 display_name: "NW Worldport"
218 path: "Components/Warps/worldport5" 223 path: "Components/Warps/worldport5"
224 destination { x: -21 y: 0 z: -7 }
225 rotation: 180
226 # enterable from either side
219} 227}
220ports { 228ports {
221 name: "GREAT" 229 name: "GREAT"
230 display_name: "E Worldport"
222 path: "Components/Warps/worldport2" 231 path: "Components/Warps/worldport2"
232 destination { x: 21 y: 0 z: -4 }
233 rotation: 180
223} 234}
224ports { 235ports {
225 name: "DAEDALUS" 236 name: "DAEDALUS"
237 display_name: "NE Worldport"
226 path: "Components/Warps/worldport3" 238 path: "Components/Warps/worldport3"
239 destination { x: 15.5 y: 0 z: -19 }
240 rotation: 90
227} 241}
228paintings { 242paintings {
229 name: "SEA" 243 name: "SEA"
diff --git a/data/maps/the_unkempt/connections.txtpb b/data/maps/the_unkempt/connections.txtpb new file mode 100644 index 0000000..d4a046c --- /dev/null +++ b/data/maps/the_unkempt/connections.txtpb
@@ -0,0 +1,60 @@
1connections {
2 from_room: "Main Area"
3 to_room: "Right Area"
4 door { name: "East Door" }
5}
6connections {
7 from_room: "Middle Room"
8 to_room: "Unsymmetry Room"
9 door { name: "W2 Room Door" }
10}
11connections {
12 from_room: "Main Area"
13 to_room: "Middle Room"
14 door { name: "Cyan Doors" }
15}
16connections {
17 from_room: "Main Area"
18 to_room: "Exit Room 2"
19 door { name: "Exit Door 1" }
20}
21connections {
22 from_room: "Exit Room 2"
23 to_room: "Exit Room 3"
24 door { name: "Exit Door 2" }
25}
26connections {
27 from_room: "Main Area"
28 to_room: "Control Center Entrance"
29 door { name: "I Entered" }
30}
31connections {
32 from_room: "Main Area"
33 to_room: "Control Center Entrance"
34 door { name: "Control Center Entrance" }
35}
36connections {
37 from_room: "Right Area"
38 to_room: "V1 Room"
39 door { name: "V1 Door" }
40}
41connections {
42 from_room: "Right Area"
43 to_room: "Daedalus Entrance"
44 door { name: "Control Center Orange Door" }
45}
46connections {
47 from_room: "Unsymmetry Room"
48 to_room: "W2 Room"
49 door { name: "W2 Door" }
50}
51connections {
52 from_room: "Unsymmetry Room"
53 to_room: "V Keyholder"
54 door { name: "V Keyholder" }
55}
56connections {
57 from_room: "Unsymmetry Room"
58 to_room: "W Keyholder"
59 door { name: "W Keyholder" }
60}
diff --git a/data/maps/the_unkempt/doors.txtpb b/data/maps/the_unkempt/doors.txtpb new file mode 100644 index 0000000..29065ec --- /dev/null +++ b/data/maps/the_unkempt/doors.txtpb
@@ -0,0 +1,184 @@
1doors {
2 name: "East Door"
3 type: STANDARD
4 receivers: "Components/Doors/entry_2"
5 panels { room: "Main Area" name: "EYE" }
6 panels { room: "Main Area" name: "SIGHT" }
7 panels { room: "Main Area" name: "SHY" }
8 panels { room: "Main Area" name: "QUITE" }
9 location_room: "Main Area"
10}
11doors {
12 name: "W2 Room Door"
13 type: STANDARD
14 receivers: "Components/Doors/entry_1"
15 panels { room: "Middle Room" name: "RIDDLE" }
16 panels { room: "Middle Room" name: "FELLOW" }
17 panels { room: "Middle Room" name: "YELLOW" }
18 panels { room: "Middle Room" name: "FIDDLE" }
19 location_room: "Middle Room"
20}
21doors {
22 name: "Cyan Doors"
23 type: EVENT
24 receivers: "Components/Doors/entry_12"
25 double_letters: true
26}
27doors {
28 name: "Sun Temple Entrance"
29 type: EVENT
30 panels { room: "Exit Room 3" name: "ENTER" }
31}
32doors {
33 name: "Exit Door 1"
34 type: EVENT
35 panels { room: "Main Area" name: "PHASE" }
36 panels { room: "Main Area" name: "SCALE" }
37 panels { room: "Main Area" name: "WAYS" }
38 panels { room: "Main Area" name: "TRAIL" }
39}
40doors {
41 name: "Exit Door 2"
42 type: EVENT
43 panels { room: "Exit Room 2" name: "FOUR" }
44 panels { room: "Exit Room 2" name: "MINE" }
45 panels { room: "Exit Room 2" name: "DOOR" }
46 panels { room: "Exit Room 2" name: "WINE" }
47}
48doors {
49 name: "I Entered"
50 type: EVENT
51 keyholders { room: "Main Area" name: "I" key: "i" }
52}
53doors {
54 name: "Control Center Entrance"
55 type: EVENT
56 panels { room: "Control Center Entrance" name: "RETURN" }
57}
58doors {
59 name: "V1 Door"
60 type: EVENT
61 panels { room: "Right Area" name: "QUIET" }
62 panels { room: "Right Area" name: "DIET" }
63 panels { room: "Right Area" name: "FOURTH" }
64 panels { room: "Right Area" name: "FORTH" }
65}
66doors {
67 name: "Control Center Orange Door"
68 type: CONTROL_CENTER_COLOR
69 receivers: "Components/Doors/entry_6"
70 receivers: "Components/Doors/entry_13"
71 receivers: "Panels/Assorted/panel_1/teleportListener"
72 control_center_color: "orange"
73 double_letters: true
74}
75doors {
76 name: "W2 Door"
77 type: EVENT
78 panels { room: "Unsymmetry Room" name: "UNINTERESTED" }
79 panels { room: "Unsymmetry Room" name: "IMPARTIAL" }
80 panels { room: "Unsymmetry Room" name: "ENTERTAIN" }
81 panels { room: "Unsymmetry Room" name: "CONFUSE" }
82 panels { room: "Unsymmetry Room" name: "UNLUCKY" }
83 panels { room: "Unsymmetry Room" name: "UNEXPECTED" }
84 panels { room: "Unsymmetry Room" name: "UNIRONIC" }
85 panels { room: "Unsymmetry Room" name: "ACCIDENTAL" }
86 panels { room: "Unsymmetry Room" name: "COMPLETE" }
87 panels { room: "Unsymmetry Room" name: "ENROLL" }
88 panels { room: "Unsymmetry Room" name: "ACCEPT" }
89 panels { room: "Unsymmetry Room" name: "DISPROVE" }
90 panels { room: "Unsymmetry Room" name: "SCRUTINIZE (Purple)" }
91 panels { room: "Unsymmetry Room" name: "SCRUTINIZE (Cyan)" }
92}
93doors {
94 name: "V Keyholder"
95 type: EVENT
96 panels { room: "Unsymmetry Room" name: "UNINTERESTED" }
97 panels { room: "Unsymmetry Room" name: "IMPARTIAL" }
98 panels { room: "Unsymmetry Room" name: "ENTERTAIN" }
99 panels { room: "Unsymmetry Room" name: "CONFUSE" }
100 panels { room: "Unsymmetry Room" name: "UNLUCKY" }
101 panels { room: "Unsymmetry Room" name: "UNEXPECTED" }
102 panels { room: "Unsymmetry Room" name: "UNIRONIC" }
103 panels { room: "Unsymmetry Room" name: "ACCIDENTAL" }
104 panels { room: "Unsymmetry Room" name: "COMPLETE" }
105 panels { room: "Unsymmetry Room" name: "ENROLL" }
106 panels { room: "Unsymmetry Room" name: "ACCEPT" }
107 panels { room: "Unsymmetry Room" name: "DISPROVE" }
108 panels { room: "Unsymmetry Room" name: "SCRUTINIZE (Purple)" }
109 panels { room: "Unsymmetry Room" name: "SCRUTINIZE (Cyan)" }
110}
111doors {
112 name: "W Keyholder"
113 type: EVENT
114 panels { room: "Unsymmetry Room" name: "UNINTERESTED" }
115 panels { room: "Unsymmetry Room" name: "IMPARTIAL" }
116 panels { room: "Unsymmetry Room" name: "ENTERTAIN" }
117 panels { room: "Unsymmetry Room" name: "CONFUSE" }
118 panels { room: "Unsymmetry Room" name: "UNLUCKY" }
119 panels { room: "Unsymmetry Room" name: "UNEXPECTED" }
120 panels { room: "Unsymmetry Room" name: "UNIRONIC" }
121 panels { room: "Unsymmetry Room" name: "ACCIDENTAL" }
122 panels { room: "Unsymmetry Room" name: "COMPLETE" }
123 panels { room: "Unsymmetry Room" name: "ENROLL" }
124 panels { room: "Unsymmetry Room" name: "ACCEPT" }
125 panels { room: "Unsymmetry Room" name: "DISPROVE" }
126 panels { room: "Unsymmetry Room" name: "SCRUTINIZE (Purple)" }
127 panels { room: "Unsymmetry Room" name: "SCRUTINIZE (Cyan)" }
128}
129doors {
130 name: "Let Untrue Tie"
131 type: LOCATION_ONLY
132 panels { room: "Main Area" name: "COUP" }
133 panels { room: "Main Area" name: "FLEW" }
134 panels { room: "Main Area" name: "GUILE" }
135 panels { room: "Main Area" name: "WHILE" }
136 panels { room: "Main Area" name: "AISLE" }
137 panels { room: "Main Area" name: "ZOO" }
138 panels { room: "Main Area" name: "SOON" }
139 panels { room: "Main Area" name: "NOON" }
140 panels { room: "Main Area" name: "MOON" }
141 location_room: "Main Area"
142}
143doors {
144 name: "Routine Out Chute"
145 type: LOCATION_ONLY
146 panels { room: "Main Area" name: "SUCH" }
147 panels { room: "Main Area" name: "MOONLIGHT" }
148 panels { room: "Main Area" name: "CRUTCH" }
149 panels { room: "Main Area" name: "CONTRITE" }
150 panels { room: "Main Area" name: "ROUTER" }
151 panels { room: "Main Area" name: "TONIGHT" }
152 panels { room: "Main Area" name: "STOUTER" }
153 panels { room: "Main Area" name: "DOUBTER" }
154 panels { room: "Main Area" name: "MUCH" }
155 location_room: "Main Area"
156}
157doors {
158 name: "Honor Our Hint"
159 type: LOCATION_ONLY
160 panels { room: "Right Area" name: "TOWER" }
161 panels { room: "Right Area" name: "WARN" }
162 panels { room: "Right Area" name: "OUTDO" }
163 panels { room: "Right Area" name: "TATTOO" }
164 panels { room: "Right Area" name: "SOUR" }
165 panels { room: "Right Area" name: "UNTRUE" }
166 panels { room: "Right Area" name: "FLOWER" }
167 panels { room: "Right Area" name: "MOURN" }
168 panels { room: "Right Area" name: "CORN" }
169 location_room: "Right Area"
170}
171doors {
172 name: "Cog Rhino Hug Rug"
173 type: LOCATION_ONLY
174 panels { room: "Right Area" name: "SCUFF" }
175 panels { room: "Right Area" name: "WIN" }
176 panels { room: "Right Area" name: "BLUFF" }
177 panels { room: "Right Area" name: "INN" }
178 panels { room: "Right Area" name: "OFF" }
179 panels { room: "Right Area" name: "TROUGH" }
180 panels { room: "Right Area" name: "BEEN" }
181 panels { room: "Right Area" name: "SCOFF" }
182 panels { room: "Right Area" name: "TOUGH" }
183 location_room: "Right Area"
184}
diff --git a/data/maps/the_unkempt/metadata.txtpb b/data/maps/the_unkempt/metadata.txtpb new file mode 100644 index 0000000..f2862bc --- /dev/null +++ b/data/maps/the_unkempt/metadata.txtpb
@@ -0,0 +1 @@
display_name: "The Unkempt"
diff --git a/data/maps/the_unkempt/rooms/Control Center Entrance.txtpb b/data/maps/the_unkempt/rooms/Control Center Entrance.txtpb new file mode 100644 index 0000000..847b8ad --- /dev/null +++ b/data/maps/the_unkempt/rooms/Control Center Entrance.txtpb
@@ -0,0 +1,17 @@
1name: "Control Center Entrance"
2panels {
3 name: "RETURN"
4 path: "Panels/Entry/panel_1"
5 clue: "return"
6 answer: "turn"
7 symbols: SPARKLES
8}
9ports {
10 name: "CC"
11 display_name: "Control Center Connector"
12 path: "Components/Warps/worldport2"
13 destination { x: -4.5 y: 0 z: 7 }
14 rotation: 0
15 # TODO: shuffle entrances with dependent keyholders
16 no_shuffle: true
17}
diff --git a/data/maps/the_unkempt/rooms/Daedalus Entrance.txtpb b/data/maps/the_unkempt/rooms/Daedalus Entrance.txtpb new file mode 100644 index 0000000..f20d2cf --- /dev/null +++ b/data/maps/the_unkempt/rooms/Daedalus Entrance.txtpb
@@ -0,0 +1,8 @@
1name: "Daedalus Entrance"
2ports {
3 name: "DAEDALUS"
4 display_name: "Orange Hallway"
5 path: "Components/Warps/worldport4"
6 destination { x: 33 y: 0 z: -10 }
7 rotation: 90
8}
diff --git a/data/maps/the_unkempt/rooms/Exit Room 2.txtpb b/data/maps/the_unkempt/rooms/Exit Room 2.txtpb new file mode 100644 index 0000000..9212780 --- /dev/null +++ b/data/maps/the_unkempt/rooms/Exit Room 2.txtpb
@@ -0,0 +1,29 @@
1name: "Exit Room 2"
2panels {
3 name: "FOUR"
4 path: "Panels/Room 9/panel_5"
5 clue: "four"
6 answer: "more"
7 symbols: ZERO
8}
9panels {
10 name: "MINE"
11 path: "Panels/Room 9/panel_6"
12 clue: "mine"
13 answer: "vine"
14 symbols: ZERO
15}
16panels {
17 name: "DOOR"
18 path: "Panels/Room 9/panel_7"
19 clue: "door"
20 answer: "more"
21 symbols: ZERO
22}
23panels {
24 name: "WINE"
25 path: "Panels/Room 9/panel_8"
26 clue: "wine"
27 answer: "vine"
28 symbols: ZERO
29}
diff --git a/data/maps/the_unkempt/rooms/Exit Room 3.txtpb b/data/maps/the_unkempt/rooms/Exit Room 3.txtpb new file mode 100644 index 0000000..3f996b5 --- /dev/null +++ b/data/maps/the_unkempt/rooms/Exit Room 3.txtpb
@@ -0,0 +1,8 @@
1name: "Exit Room 3"
2panels {
3 name: "ENTER"
4 path: "Panels/Room 9/panel_9"
5 clue: "enter"
6 answer: "exit"
7 symbols: SUN
8}
diff --git a/data/maps/the_unkempt/rooms/Main Area.txtpb b/data/maps/the_unkempt/rooms/Main Area.txtpb new file mode 100644 index 0000000..f98220d --- /dev/null +++ b/data/maps/the_unkempt/rooms/Main Area.txtpb
@@ -0,0 +1,238 @@
1name: "Main Area"
2panels {
3 name: "I"
4 path: "Panels/Room 1/panel_1"
5 clue: "i"
6 answer: "hi"
7 symbols: ZERO
8}
9panels {
10 name: "SPY"
11 path: "Panels/Room 1/panel_2"
12 clue: "spy"
13 answer: "hi"
14 symbols: ZERO
15}
16panels {
17 name: "THEFT"
18 path: "Panels/Room 1/panel_3"
19 clue: "theft"
20 answer: "left"
21 symbols: ZERO
22}
23panels {
24 name: "HEFT"
25 path: "Panels/Room 1/panel_4"
26 clue: "heft"
27 answer: "left"
28 symbols: ZERO
29}
30panels {
31 name: "EYE"
32 path: "Panels/Room 2/panel_1"
33 clue: "eye"
34 answer: "hi"
35 symbols: ZERO
36}
37panels {
38 name: "SIGHT"
39 path: "Panels/Room 2/panel_2"
40 clue: "sight"
41 answer: "right"
42 symbols: ZERO
43}
44panels {
45 name: "SHY"
46 path: "Panels/Room 2/panel_3"
47 clue: "shy"
48 answer: "hi"
49 symbols: ZERO
50}
51panels {
52 name: "QUITE"
53 path: "Panels/Room 2/panel_4"
54 clue: "quite"
55 answer: "right"
56 symbols: ZERO
57}
58panels {
59 name: "SUCH"
60 path: "Panels/Room 6/panel_1"
61 clue: "such"
62 answer: "touch"
63 symbols: ZERO
64}
65panels {
66 name: "MOONLIGHT"
67 path: "Panels/Room 6/panel_2"
68 clue: "moonlight"
69 answer: "unite"
70 symbols: ZERO
71}
72panels {
73 name: "CRUTCH"
74 path: "Panels/Room 6/panel_3"
75 clue: "crutch"
76 answer: "touch"
77 symbols: ZERO
78}
79panels {
80 name: "CONTRITE"
81 path: "Panels/Room 6/panel_4"
82 clue: "contrite"
83 answer: "unite"
84 symbols: ZERO
85}
86panels {
87 name: "ROUTER"
88 path: "Panels/Room 6/panel_5"
89 clue: "router"
90 answer: "outer"
91 symbols: ZERO
92}
93panels {
94 name: "TONIGHT"
95 path: "Panels/Room 6/panel_6"
96 clue: "tonight"
97 answer: "unite"
98 symbols: ZERO
99}
100panels {
101 name: "STOUTER"
102 path: "Panels/Room 6/panel_7"
103 clue: "stouter"
104 answer: "outer"
105 symbols: ZERO
106}
107panels {
108 name: "DOUBTER"
109 path: "Panels/Room 6/panel_8"
110 clue: "doubter"
111 answer: "outer"
112 symbols: ZERO
113}
114panels {
115 name: "MUCH"
116 path: "Panels/Room 6/panel_9"
117 clue: "much"
118 answer: "touch"
119 symbols: ZERO
120}
121panels {
122 name: "COUP"
123 path: "Panels/Room 7/panel_1"
124 clue: "coup"
125 answer: "true"
126 symbols: ZERO
127}
128panels {
129 name: "FLEW"
130 path: "Panels/Room 7/panel_2"
131 clue: "flew"
132 answer: "true"
133 symbols: ZERO
134}
135panels {
136 name: "GUILE"
137 path: "Panels/Room 7/panel_3"
138 clue: "guile"
139 answer: "tile"
140 symbols: ZERO
141}
142panels {
143 name: "WHILE"
144 path: "Panels/Room 7/panel_4"
145 clue: "while"
146 answer: "tile"
147 symbols: ZERO
148}
149panels {
150 name: "AISLE"
151 path: "Panels/Room 7/panel_5"
152 clue: "aisle"
153 answer: "tile"
154 symbols: ZERO
155}
156panels {
157 name: "ZOO"
158 path: "Panels/Room 7/panel_6"
159 clue: "zoo"
160 answer: "true"
161 symbols: ZERO
162}
163panels {
164 name: "SOON"
165 path: "Panels/Room 7/panel_7"
166 clue: "soon"
167 answer: "tune"
168 symbols: ZERO
169}
170panels {
171 name: "NOON"
172 path: "Panels/Room 7/panel_8"
173 clue: "noon"
174 answer: "tune"
175 symbols: ZERO
176}
177panels {
178 name: "MOON"
179 path: "Panels/Room 7/panel_9"
180 clue: "moon"
181 answer: "tune"
182 symbols: ZERO
183}
184panels {
185 name: "PHASE"
186 path: "Panels/Room 9/panel_1"
187 clue: "phase"
188 answer: "maze"
189 symbols: ZERO
190}
191panels {
192 name: "SCALE"
193 path: "Panels/Room 9/panel_2"
194 clue: "scale"
195 answer: "jail"
196 symbols: ZERO
197}
198panels {
199 name: "WAYS"
200 path: "Panels/Room 9/panel_3"
201 clue: "ways"
202 answer: "maze"
203 symbols: ZERO
204}
205panels {
206 name: "TRAIL"
207 path: "Panels/Room 9/panel_4"
208 clue: "trail"
209 answer: "jail"
210 symbols: ZERO
211}
212keyholders {
213 name: "I"
214 path: "Components/KeyHolders/keyHolderL"
215 key: "i"
216}
217ports {
218 name: "GREAT"
219 display_name: "Main Entrance"
220 path: "Components/Warps/worldport"
221 destination { x: -3 y: 0 z: 11 }
222 rotation: 270
223}
224ports {
225 name: "TREE"
226 display_name: "Brown Hallway"
227 path: "Components/Warps/worldport5"
228 destination { x: -34 y: 0 z: 7 }
229 rotation: 270
230}
231ports {
232 name: "SUNTEMPLE"
233 display_name: "Sun Temple Entrance"
234 path: "Components/Warps/worldport3"
235 destination { x: -42 y: 0 z: -2 }
236 rotation: 270
237 required_door { name: "Sun Temple Entrance" }
238}
diff --git a/data/maps/the_unkempt/rooms/Middle Room.txtpb b/data/maps/the_unkempt/rooms/Middle Room.txtpb new file mode 100644 index 0000000..f47f37b --- /dev/null +++ b/data/maps/the_unkempt/rooms/Middle Room.txtpb
@@ -0,0 +1,29 @@
1name: "Middle Room"
2panels {
3 name: "RIDDLE"
4 path: "Panels/Room 5/panel_1"
5 clue: "riddle"
6 answer: "middle"
7 symbols: ZERO
8}
9panels {
10 name: "FELLOW"
11 path: "Panels/Room 5/panel_2"
12 clue: "fellow"
13 answer: "hello"
14 symbols: ZERO
15}
16panels {
17 name: "YELLOW"
18 path: "Panels/Room 5/panel_3"
19 clue: "yellow"
20 answer: "hello"
21 symbols: ZERO
22}
23panels {
24 name: "FIDDLE"
25 path: "Panels/Room 5/panel_4"
26 clue: "fiddle"
27 answer: "middle"
28 symbols: ZERO
29}
diff --git a/data/maps/the_unkempt/rooms/Right Area.txtpb b/data/maps/the_unkempt/rooms/Right Area.txtpb new file mode 100644 index 0000000..03d7cea --- /dev/null +++ b/data/maps/the_unkempt/rooms/Right Area.txtpb
@@ -0,0 +1,163 @@
1name: "Right Area"
2panels {
3 name: "TOWER"
4 path: "Panels/Room 3/panel_1"
5 clue: "tower"
6 answer: "hour"
7 symbols: ZERO
8}
9panels {
10 name: "WARN"
11 path: "Panels/Room 3/panel_2"
12 clue: "warn"
13 answer: "horn"
14 symbols: ZERO
15}
16panels {
17 name: "OUTDO"
18 path: "Panels/Room 3/panel_3"
19 clue: "outdo"
20 answer: "into"
21 symbols: ZERO
22}
23panels {
24 name: "TATTOO"
25 path: "Panels/Room 3/panel_4"
26 clue: "tattoo"
27 answer: "into"
28 symbols: ZERO
29}
30panels {
31 name: "SOUR"
32 path: "Panels/Room 3/panel_5"
33 clue: "sour"
34 answer: "hour"
35 symbols: ZERO
36}
37panels {
38 name: "UNTRUE"
39 path: "Panels/Room 3/panel_6"
40 clue: "untrue"
41 answer: "into"
42 symbols: ZERO
43}
44panels {
45 name: "FLOWER"
46 path: "Panels/Room 3/panel_7"
47 clue: "flower"
48 answer: "hour"
49 symbols: ZERO
50}
51panels {
52 name: "MOURN"
53 path: "Panels/Room 3/panel_8"
54 clue: "mourn"
55 answer: "horn"
56 symbols: ZERO
57}
58panels {
59 name: "CORN"
60 path: "Panels/Room 3/panel_9"
61 clue: "corn"
62 answer: "horn"
63 symbols: ZERO
64}
65panels {
66 name: "SCUFF"
67 path: "Panels/Room 4/panel_1"
68 clue: "scuff"
69 answer: "rough"
70 symbols: ZERO
71}
72panels {
73 name: "WIN"
74 path: "Panels/Room 4/panel_2"
75 clue: "win"
76 answer: "grin"
77 symbols: ZERO
78}
79panels {
80 name: "BLUFF"
81 path: "Panels/Room 4/panel_3"
82 clue: "bluff"
83 answer: "rough"
84 symbols: ZERO
85}
86panels {
87 name: "INN"
88 path: "Panels/Room 4/panel_4"
89 clue: "inn"
90 answer: "grin"
91 symbols: ZERO
92}
93panels {
94 name: "OFF"
95 path: "Panels/Room 4/panel_5"
96 clue: "off"
97 answer: "cough"
98 symbols: ZERO
99}
100panels {
101 name: "TROUGH"
102 path: "Panels/Room 4/panel_6"
103 clue: "trough"
104 answer: "cough"
105 symbols: ZERO
106}
107panels {
108 name: "BEEN"
109 path: "Panels/Room 4/panel_7"
110 clue: "been"
111 answer: "grin"
112 symbols: ZERO
113}
114panels {
115 name: "SCOFF"
116 path: "Panels/Room 4/panel_8"
117 clue: "scoff"
118 answer: "cough"
119 symbols: ZERO
120}
121panels {
122 name: "TOUGH"
123 path: "Panels/Room 4/panel_9"
124 clue: "tough"
125 answer: "rough"
126 symbols: ZERO
127}
128panels {
129 name: "FORTH"
130 path: "Panels/Room 8/panel_1"
131 clue: "forth"
132 answer: "north"
133 symbols: ZERO
134}
135panels {
136 name: "QUIET"
137 path: "Panels/Room 8/panel_2"
138 clue: "quiet"
139 answer: "riot"
140 symbols: ZERO
141}
142panels {
143 name: "DIET"
144 path: "Panels/Room 8/panel_3"
145 clue: "diet"
146 answer: "riot"
147 symbols: ZERO
148}
149panels {
150 name: "FOURTH"
151 path: "Panels/Room 8/panel_4"
152 clue: "fourth"
153 answer: "north"
154 symbols: ZERO
155}
156panels {
157 name: "COLOR"
158 path: "Panels/Assorted/panel_1"
159 clue: "color"
160 answer: "orange"
161 symbols: EXAMPLE
162 required_door { name: "Control Center Orange Door" }
163}
diff --git a/data/maps/the_unkempt/rooms/Unsymmetry Room.txtpb b/data/maps/the_unkempt/rooms/Unsymmetry Room.txtpb new file mode 100644 index 0000000..ff96ba1 --- /dev/null +++ b/data/maps/the_unkempt/rooms/Unsymmetry Room.txtpb
@@ -0,0 +1,99 @@
1name: "Unsymmetry Room"
2panels {
3 name: "UNINTERESTED"
4 path: "Panels/Unsymmetry Room/panel_a_1"
5 clue: "uninterested"
6 answer: "interested"
7 symbols: SUN
8}
9panels {
10 name: "IMPARTIAL"
11 path: "Panels/Unsymmetry Room/panel_b_1"
12 clue: "impartial"
13 answer: "disinterested"
14 symbols: SUN
15}
16panels {
17 name: "ENTERTAIN"
18 path: "Panels/Unsymmetry Room/panel_a_2"
19 clue: "entertain"
20 answer: "amuse"
21 symbols: SUN
22}
23panels {
24 name: "CONFUSE"
25 path: "Panels/Unsymmetry Room/panel_b_2"
26 clue: "confuse"
27 answer: "bemuse"
28 symbols: SUN
29}
30panels {
31 name: "UNLUCKY"
32 path: "Panels/Unsymmetry Room/panel_a_3"
33 clue: "unlucky"
34 answer: "lucky"
35 symbols: SUN
36}
37panels {
38 name: "UNEXPECTED"
39 path: "Panels/Unsymmetry Room/panel_b_3"
40 clue: "unexpected"
41 answer: "fortuitous"
42 symbols: SUN
43}
44panels {
45 name: "UNIRONIC"
46 path: "Panels/Unsymmetry Room/panel_a_4"
47 clue: "unironic"
48 answer: "ironic"
49 symbols: SUN
50}
51panels {
52 name: "ACCIDENTAL"
53 path: "Panels/Unsymmetry Room/panel_b_4"
54 clue: "accidental"
55 answer: "coincidental"
56 symbols: SUN
57}
58panels {
59 name: "COMPLETE"
60 path: "Panels/Unsymmetry Room/panel_a_5"
61 clue: "complete"
62 answer: "graduate"
63 symbols: SUN
64}
65panels {
66 name: "ENROLL"
67 path: "Panels/Unsymmetry Room/panel_b_5"
68 clue: "enroll"
69 answer: "matriculate"
70 symbols: SUN
71}
72panels {
73 name: "ACCEPT"
74 path: "Panels/Unsymmetry Room/panel_a_6"
75 clue: "accept"
76 answer: "deny"
77 symbols: SUN
78}
79panels {
80 name: "DISPROVE"
81 path: "Panels/Unsymmetry Room/panel_b_6"
82 clue: "disprove"
83 answer: "refute"
84 symbols: SUN
85}
86panels {
87 name: "SCRUTINIZE (Purple)"
88 path: "Panels/Unsymmetry Room/panel_a_7"
89 clue: "scrutinize"
90 answer: "skim"
91 symbols: SUN
92}
93panels {
94 name: "SCRUTINIZE (Cyan)"
95 path: "Panels/Unsymmetry Room/panel_b_7"
96 clue: "scrutinize"
97 answer: "peruse"
98 symbols: SUN
99}
diff --git a/data/maps/the_unkempt/rooms/V Keyholder.txtpb b/data/maps/the_unkempt/rooms/V Keyholder.txtpb new file mode 100644 index 0000000..8a4941d --- /dev/null +++ b/data/maps/the_unkempt/rooms/V Keyholder.txtpb
@@ -0,0 +1,6 @@
1name: "V Keyholder"
2keyholders {
3 name: "V"
4 path: "Components/KeyHolders/keyHolderV"
5 key: "v"
6}
diff --git a/data/maps/the_unkempt/rooms/V1 Room.txtpb b/data/maps/the_unkempt/rooms/V1 Room.txtpb new file mode 100644 index 0000000..078cb37 --- /dev/null +++ b/data/maps/the_unkempt/rooms/V1 Room.txtpb
@@ -0,0 +1,5 @@
1name: "V1 Room"
2letters {
3 key: "v"
4 path: "Components/Collectables/v"
5}
diff --git a/data/maps/the_unkempt/rooms/W Keyholder.txtpb b/data/maps/the_unkempt/rooms/W Keyholder.txtpb new file mode 100644 index 0000000..e16f997 --- /dev/null +++ b/data/maps/the_unkempt/rooms/W Keyholder.txtpb
@@ -0,0 +1,6 @@
1name: "W Keyholder"
2keyholders {
3 name: "W"
4 path: "Components/KeyHolders/keyHolderW"
5 key: "w"
6}
diff --git a/data/maps/the_unkempt/rooms/W2 Room.txtpb b/data/maps/the_unkempt/rooms/W2 Room.txtpb new file mode 100644 index 0000000..2fa07d4 --- /dev/null +++ b/data/maps/the_unkempt/rooms/W2 Room.txtpb
@@ -0,0 +1,6 @@
1name: "W2 Room"
2letters {
3 key: "w"
4 level2: true
5 path: "Components/Collectables/w2"
6}
diff --git a/data/maps/the_unyielding/doors.txtpb b/data/maps/the_unyielding/doors.txtpb index b969c0b..a3c3999 100644 --- a/data/maps/the_unyielding/doors.txtpb +++ b/data/maps/the_unyielding/doors.txtpb
@@ -183,6 +183,21 @@ doors {
183 panels { room: "Central Connected Area" name: "CHIN" } 183 panels { room: "Central Connected Area" name: "CHIN" }
184 panels { room: "Central Connected Area" name: "DING" } 184 panels { room: "Central Connected Area" name: "DING" }
185 location_room: "Central Connected Area" 185 location_room: "Central Connected Area"
186 location_name: "East Room 2"
187}
188doors {
189 name: "East Room 1"
190 type: LOCATION_ONLY
191 panels { room: "East Room 1" name: "CHIN" }
192 panels { room: "East Room 1" name: "HEAT" }
193 panels { room: "East Room 1" name: "END" }
194 panels { room: "East Room 1" name: "FLY" }
195 panels { room: "East Room 1" name: "OUCH" }
196 panels { room: "East Room 1" name: "HAG" }
197 panels { room: "East Room 1" name: "TIN" }
198 panels { room: "East Room 1" name: "RID" }
199 panels { room: "East Room 1" name: "TUG" }
200 location_room: "East Room 1"
186} 201}
187doors { 202doors {
188 name: "Orange Alcove" 203 name: "Orange Alcove"
@@ -199,6 +214,7 @@ doors {
199} 214}
200doors { 215doors {
201 name: "Black Alcove" 216 name: "Black Alcove"
217 type: EVENT
202 panels { room: "Star Rooms" name: "TURN" } 218 panels { room: "Star Rooms" name: "TURN" }
203 panels { room: "Central Connected Area" name: "HAD" } 219 panels { room: "Central Connected Area" name: "HAD" }
204 panels { room: "Central Connected Area" name: "SOW" } 220 panels { room: "Central Connected Area" name: "SOW" }
@@ -218,6 +234,7 @@ doors {
218 panels { room: "Northeast Room 1" name: "CAR" } 234 panels { room: "Northeast Room 1" name: "CAR" }
219 panels { room: "Northeast Room 1" name: "SIR" } 235 panels { room: "Northeast Room 1" name: "SIR" }
220 location_room: "Northeast Room 1" 236 location_room: "Northeast Room 1"
237 location_name: "Northeast Room 1"
221} 238}
222doors { 239doors {
223 name: "Northeast Corner Behind" 240 name: "Northeast Corner Behind"
@@ -245,6 +262,7 @@ doors {
245 panels { room: "Northwest Room" name: "HER" } 262 panels { room: "Northwest Room" name: "HER" }
246 panels { room: "Northwest Room" name: "DAM" } 263 panels { room: "Northwest Room" name: "DAM" }
247 location_room: "Northwest Room" 264 location_room: "Northwest Room"
265 location_name: "Northwest Room"
248} 266}
249doors { 267doors {
250 name: "Cyan Alcove" 268 name: "Cyan Alcove"
@@ -274,6 +292,7 @@ doors {
274 panels { room: "Southwest Room 3" name: "HOST" } 292 panels { room: "Southwest Room 3" name: "HOST" }
275 panels { room: "Southwest Room 3" name: "MUG" } 293 panels { room: "Southwest Room 3" name: "MUG" }
276 location_room: "Southwest Room 3" 294 location_room: "Southwest Room 3"
295 location_name: "Southwest Room 3"
277} 296}
278doors { 297doors {
279 name: "Southwest Room 2 Entrance" 298 name: "Southwest Room 2 Entrance"
@@ -293,6 +312,7 @@ doors {
293 panels { room: "Southwest Room 2" name: "ION" } 312 panels { room: "Southwest Room 2" name: "ION" }
294 panels { room: "Southwest Room 2" name: "INN" } 313 panels { room: "Southwest Room 2" name: "INN" }
295 location_room: "Southwest Room 2" 314 location_room: "Southwest Room 2"
315 location_name: "Southwest Room 2"
296} 316}
297doors { 317doors {
298 name: "Southwest 4" 318 name: "Southwest 4"
@@ -411,6 +431,7 @@ doors {
411 panels { room: "Central Connected Area" name: "SON (1)" } 431 panels { room: "Central Connected Area" name: "SON (1)" }
412 panels { room: "Central Connected Area" name: "URGE" } 432 panels { room: "Central Connected Area" name: "URGE" }
413 location_room: "Central Connected Area" 433 location_room: "Central Connected Area"
434 location_name: "Northeast Room 2"
414} 435}
415doors { 436doors {
416 name: "South Right Painting" 437 name: "South Right Painting"
@@ -478,5 +499,8 @@ doors {
478doors { 499doors {
479 name: "Cyan Doors" 500 name: "Cyan Doors"
480 type: EVENT 501 type: EVENT
481 switches: "double_letters" 502 receivers: "Components/Doors/entry_4"
503 receivers: "Panels/Miscellaneous/entry_2/teleportListener"
504 receivers: "Panels/Miscellaneous/entry_3/teleportListener"
505 double_letters: true
482} 506}
diff --git a/data/maps/the_unyielding/rooms/Bearer Entrance.txtpb b/data/maps/the_unyielding/rooms/Bearer Entrance.txtpb index 4c1440f..6ce69da 100644 --- a/data/maps/the_unyielding/rooms/Bearer Entrance.txtpb +++ b/data/maps/the_unyielding/rooms/Bearer Entrance.txtpb
@@ -1,5 +1,8 @@
1name: "Bearer Entrance" 1name: "Bearer Entrance"
2ports { 2ports {
3 name: "BEARER" 3 name: "BEARER"
4 display_name: "East of Yellow Worldport"
4 path: "Components/Warps/worldport4" 5 path: "Components/Warps/worldport4"
6 destination { x: 23 y: 0 z: -29 }
7 rotation: 90
5} 8}
diff --git a/data/maps/the_unyielding/rooms/Digital Entrance.txtpb b/data/maps/the_unyielding/rooms/Digital Entrance.txtpb index 74665a2..853c5f0 100644 --- a/data/maps/the_unyielding/rooms/Digital Entrance.txtpb +++ b/data/maps/the_unyielding/rooms/Digital Entrance.txtpb
@@ -8,5 +8,8 @@ panels {
8} 8}
9ports { 9ports {
10 name: "DIGITAL" 10 name: "DIGITAL"
11 display_name: "South of Yellow Worldport"
11 path: "Components/Warps/worldport" 12 path: "Components/Warps/worldport"
13 destination { x: 0 y: 0 z: 0 }
14 rotation: 0
12} 15}
diff --git a/data/maps/the_unyielding/rooms/Nuanced Entrance.txtpb b/data/maps/the_unyielding/rooms/Nuanced Entrance.txtpb index f011b32..454dc3f 100644 --- a/data/maps/the_unyielding/rooms/Nuanced Entrance.txtpb +++ b/data/maps/the_unyielding/rooms/Nuanced Entrance.txtpb
@@ -1,5 +1,8 @@
1name: "Nuanced Entrance" 1name: "Nuanced Entrance"
2ports { 2ports {
3 name: "NUANCED" 3 name: "NUANCED"
4 display_name: "West of Yellow Worldport"
4 path: "Components/Warps/worldport3" 5 path: "Components/Warps/worldport3"
6 destination { x: -23 y: 0 z: -29 }
7 rotation: 270
5} 8}
diff --git a/data/maps/the_unyielding/rooms/Plaza Entrance.txtpb b/data/maps/the_unyielding/rooms/Plaza Entrance.txtpb index 0bc60a7..f866d87 100644 --- a/data/maps/the_unyielding/rooms/Plaza Entrance.txtpb +++ b/data/maps/the_unyielding/rooms/Plaza Entrance.txtpb
@@ -15,5 +15,8 @@ panels {
15} 15}
16ports { 16ports {
17 name: "PLAZA" 17 name: "PLAZA"
18 display_name: "Dark Hallway"
18 path: "Components/Warps/worldport5" 19 path: "Components/Warps/worldport5"
20 destination { x: 35 y: 0 z: 44 }
21 rotation: 270
19} 22}
diff --git a/data/maps/the_unyielding/rooms/Yellow Left.txtpb b/data/maps/the_unyielding/rooms/Yellow Left.txtpb index 9c7d023..192d901 100644 --- a/data/maps/the_unyielding/rooms/Yellow Left.txtpb +++ b/data/maps/the_unyielding/rooms/Yellow Left.txtpb
@@ -5,4 +5,5 @@ panels {
5 clue: "sickness" 5 clue: "sickness"
6 answer: "health" 6 answer: "health"
7 symbols: SUN 7 symbols: SUN
8 required_door { name: "Cyan Doors" }
8} 9}
diff --git a/data/maps/the_unyielding/rooms/Yellow Right.txtpb b/data/maps/the_unyielding/rooms/Yellow Right.txtpb index 0599f29..d554c73 100644 --- a/data/maps/the_unyielding/rooms/Yellow Right.txtpb +++ b/data/maps/the_unyielding/rooms/Yellow Right.txtpb
@@ -5,4 +5,5 @@ panels {
5 clue: "health" 5 clue: "health"
6 answer: "sickness" 6 answer: "sickness"
7 symbols: SUN 7 symbols: SUN
8 required_door { name: "Cyan Doors" }
8} 9}
diff --git a/data/maps/the_wise/connections.txtpb b/data/maps/the_wise/connections.txtpb new file mode 100644 index 0000000..e3aa07b --- /dev/null +++ b/data/maps/the_wise/connections.txtpb
@@ -0,0 +1,10 @@
1connections {
2 from_room: "Entry"
3 to_room: "Puzzles"
4 door { name: "Front Door" }
5}
6connections {
7 from_room: "Puzzles"
8 to_room: "Mastery"
9 door { name: "Mastery" }
10}
diff --git a/data/maps/the_wise/doors.txtpb b/data/maps/the_wise/doors.txtpb new file mode 100644 index 0000000..cef4af3 --- /dev/null +++ b/data/maps/the_wise/doors.txtpb
@@ -0,0 +1,36 @@
1doors {
2 name: "Front Door"
3 type: STANDARD
4 receivers: "Components/Doors/entry_2"
5 panels { room: "Entry" name: "INK" }
6 location_room: "Entry"
7}
8doors {
9 name: "Seasons"
10 type: EVENT
11 panels { room: "Puzzles" name: "ERAS" answer: "seasons" }
12}
13doors {
14 name: "Mastery"
15 type: EVENT
16 panels { room: "Puzzles" name: "STORY" }
17 panels { room: "Puzzles" name: "VENTURE" }
18 panels { room: "Puzzles" name: "PASSED" }
19 panels { room: "Puzzles" name: "SLUMBERING" }
20 panels { room: "Puzzles" name: "RHYME" }
21 panels { room: "Puzzles" name: "OBSCURE" }
22 panels { room: "Puzzles" name: "PROPHET" }
23 panels { room: "Puzzles" name: "ERAS" }
24 panels { room: "Puzzles" name: "DARKNESS" }
25 panels { room: "Puzzles" name: "PRINCE" }
26 panels { room: "Puzzles" name: "BATH" }
27 panels { room: "Puzzles" name: "CHAOTIC" }
28 panels { room: "Puzzles" name: "EYES" }
29 panels { room: "Puzzles" name: "QUEENDOOM" }
30 panels { room: "Puzzles" name: "SHOUTS" }
31 panels { room: "Puzzles" name: "INTELLIGENCE" }
32 panels { room: "Puzzles" name: "EARTHWAR" }
33 panels { room: "Puzzles" name: "SLEEPER" }
34 panels { room: "Puzzles" name: "BOTTLE" }
35 panels { room: "Puzzles" name: "WORDS" }
36}
diff --git a/data/maps/the_wise/metadata.txtpb b/data/maps/the_wise/metadata.txtpb new file mode 100644 index 0000000..91af34e --- /dev/null +++ b/data/maps/the_wise/metadata.txtpb
@@ -0,0 +1,3 @@
1display_name: "The Wise"
2# This port is out of bounds.
3excluded_nodes: "Components/Warps/worldport"
diff --git a/data/maps/the_wise/rooms/Entry.txtpb b/data/maps/the_wise/rooms/Entry.txtpb new file mode 100644 index 0000000..789d555 --- /dev/null +++ b/data/maps/the_wise/rooms/Entry.txtpb
@@ -0,0 +1,12 @@
1name: "Entry"
2panels {
3 name: "INK"
4 path: "Panels/Entry/entry_1"
5 clue: "ink"
6 answer: "link"
7 symbols: SPARKLES
8}
9paintings {
10 name: "TRIANGLE"
11 path: "Components/Paintings/triangle"
12}
diff --git a/data/maps/the_wise/rooms/Mastery.txtpb b/data/maps/the_wise/rooms/Mastery.txtpb new file mode 100644 index 0000000..749837e --- /dev/null +++ b/data/maps/the_wise/rooms/Mastery.txtpb
@@ -0,0 +1,5 @@
1name: "Mastery"
2masteries {
3 name: "MASTERY"
4 path: "Components/Collectables/smiley"
5}
diff --git a/data/maps/the_wise/rooms/Puzzles.txtpb b/data/maps/the_wise/rooms/Puzzles.txtpb new file mode 100644 index 0000000..ab34f13 --- /dev/null +++ b/data/maps/the_wise/rooms/Puzzles.txtpb
@@ -0,0 +1,151 @@
1name: "Puzzles"
2panels {
3 name: "STORY"
4 path: "Panels/Room_1/panel_1"
5 clue: "story"
6 answer: "legend"
7 symbols: SUN
8 required_door { name: "Seasons" }
9}
10panels {
11 name: "VENTURE"
12 path: "Panels/Room_1/panel_2"
13 clue: "venture"
14 answer: "adventure"
15 symbols: SPARKLES
16 required_door { name: "Seasons" }
17}
18panels {
19 name: "PASSED"
20 path: "Panels/Room_1/panel_3"
21 clue: "passed"
22 answer: "past"
23 symbols: ZERO
24}
25panels {
26 name: "SLUMBERING"
27 path: "Panels/Room_1/panel_4"
28 clue: "slumbering"
29 answer: "awakening"
30 symbols: SUN
31 required_door { name: "Seasons" }
32}
33panels {
34 name: "RHYME"
35 path: "Panels/Room_1/panel_5"
36 clue: "rhyme"
37 answer: "time"
38 symbols: ZERO
39}
40panels {
41 name: "OBSCURE"
42 path: "Panels/Room_1/panel_6"
43 clue: "obscure"
44 answer: "mask"
45 symbols: PYRAMID
46}
47panels {
48 name: "PROPHET"
49 path: "Panels/Room_1/panel_7"
50 clue: "prophet"
51 answer: "oracle"
52 symbols: SUN
53}
54panels {
55 name: "ERAS"
56 path: "Panels/Room_1/panel_8"
57 clue: "eras"
58 answer: "gsae"
59 symbols: SUN
60 proxies { answer: "ages" path: "Panels/Proxies/panel_8_proxy_1" }
61 proxies { answer: "seasons" path: "Panels/Proxies/panel_8_proxy_2" }
62}
63panels {
64 name: "DARKNESS"
65 path: "Panels/Room_1/panel_9"
66 clue: "darkness"
67 answer: "twilight"
68 symbols: PYRAMID
69 required_door { name: "Seasons" }
70}
71panels {
72 name: "PRINCE"
73 path: "Panels/Room_1/panel_10"
74 clue: "prince"
75 answer: "princess"
76 symbols: GENDER
77 required_door { name: "Seasons" }
78}
79panels {
80 name: "BATH"
81 path: "Panels/Room_1/panel_11"
82 clue: "bath"
83 answer: "breath"
84 symbols: SPARKLES
85}
86panels {
87 name: "CHAOTIC"
88 path: "Panels/Room_1/panel_12"
89 clue: "chaotic"
90 answer: "wild"
91 symbols: SUN
92}
93panels {
94 name: "EYES"
95 path: "Panels/Room_1/panel_13"
96 clue: "eyes"
97 answer: "tears"
98 symbols: STARS
99}
100panels {
101 name: "QUEENDOOM"
102 path: "Panels/Room_1/panel_14"
103 clue: "queendoom"
104 answer: "kingdom"
105 symbols: SUN
106 symbols: SPARKLES
107}
108panels {
109 name: "SHOUTS"
110 path: "Panels/Room_1/panel_15"
111 clue: "shouts"
112 answer: "echoes"
113 symbols: AGE
114 required_door { name: "Seasons" }
115}
116panels {
117 name: "INTELLIGENCE"
118 path: "Panels/Room_1/panel_16"
119 clue: "intelligence"
120 answer: "wisdom"
121 symbols: AGE
122}
123panels {
124 name: "EARTHWAR"
125 path: "Panels/Room_1/panel_17"
126 clue: "earthwar"
127 answer: "skyward"
128 symbols: SUN
129 symbols: SPARKLES
130}
131panels {
132 name: "SLEEPER"
133 path: "Panels/Room_1/panel_19"
134 clue: "sleeper"
135 answer: "waker"
136 symbols: SUN
137}
138panels {
139 name: "BOTTLE"
140 path: "Panels/Room_1/panel_20"
141 clue: "bottle"
142 answer: "cap"
143 symbols: BOXES
144}
145panels {
146 name: "WORDS"
147 path: "Panels/Room_1/panel_18"
148 clue: "words"
149 answer: "sword"
150 symbols: ANAGRAM
151}
diff --git a/data/maps/the_wondrous/connections.txtpb b/data/maps/the_wondrous/connections.txtpb new file mode 100644 index 0000000..0bd773a --- /dev/null +++ b/data/maps/the_wondrous/connections.txtpb
@@ -0,0 +1,10 @@
1connections {
2 from_room: "Entry"
3 to_room: "Regular"
4 door { name: "Front Door" }
5}
6connections {
7 from_room: "Regular"
8 to_room: "Huge"
9 door { name: "Shrink Door" }
10}
diff --git a/data/maps/the_wondrous/doors.txtpb b/data/maps/the_wondrous/doors.txtpb new file mode 100644 index 0000000..3951604 --- /dev/null +++ b/data/maps/the_wondrous/doors.txtpb
@@ -0,0 +1,24 @@
1doors {
2 name: "Front Door"
3 type: EVENT
4 panels { room: "Entry" name: "WONDER" }
5}
6doors {
7 name: "Shrink Door"
8 type: STANDARD
9 receivers: "Components/Doors/wonderlandDoor2/animationListener2"
10 panels { room: "Regular" name: "SHRINK" }
11 location_room: "Regular"
12}
13doors {
14 name: "Big Door"
15 type: EVENT
16 panels { room: "Huge" name: "SHRINK" }
17 panels { room: "Huge" name: "IRE" }
18 panels { room: "Huge" name: "BRIE" }
19 panels { room: "Huge" name: "WICK" }
20 panels { room: "Huge" name: "BARK" }
21 panels { room: "Huge" name: "HARE" }
22 panels { room: "Huge" name: "CHIME" }
23 panels { room: "Huge" name: "LIBRARY" }
24}
diff --git a/data/maps/the_wondrous/metadata.txtpb b/data/maps/the_wondrous/metadata.txtpb new file mode 100644 index 0000000..0b96cf2 --- /dev/null +++ b/data/maps/the_wondrous/metadata.txtpb
@@ -0,0 +1 @@
display_name: "The Wondrous"
diff --git a/data/maps/the_wondrous/rooms/Entry.txtpb b/data/maps/the_wondrous/rooms/Entry.txtpb new file mode 100644 index 0000000..543d193 --- /dev/null +++ b/data/maps/the_wondrous/rooms/Entry.txtpb
@@ -0,0 +1,14 @@
1name: "Entry"
2panels {
3 name: "WONDER"
4 path: "Panels/panel_1"
5 clue: "wonder"
6 answer: "wonder"
7}
8ports {
9 name: "DAEDALUS"
10 display_name: "Entrance"
11 path: "Components/Warps/worldport"
12 destination { x: 18 y: 0 z: 41 }
13 rotation: 180
14}
diff --git a/data/maps/the_wondrous/rooms/Huge.txtpb b/data/maps/the_wondrous/rooms/Huge.txtpb new file mode 100644 index 0000000..6ca6ef8 --- /dev/null +++ b/data/maps/the_wondrous/rooms/Huge.txtpb
@@ -0,0 +1,57 @@
1name: "Huge"
2panels {
3 name: "SHRINK"
4 path: "Panels/panel_3"
5 clue: "shrink"
6 answer: "shrink"
7 display_name: "SHRINK (2)"
8}
9panels {
10 name: "IRE"
11 path: "Panels/panel_4"
12 clue: "ire"
13 answer: "fire"
14 symbols: SPARKLES
15}
16panels {
17 name: "BRIE"
18 path: "Panels/panel_5"
19 clue: "brie"
20 answer: "three"
21 symbols: ZERO
22}
23panels {
24 name: "WICK"
25 path: "Panels/panel_6"
26 clue: "wick"
27 answer: "candle"
28 symbols: BOXES
29}
30panels {
31 name: "BARK"
32 path: "Panels/panel_7"
33 clue: "bark"
34 answer: "tree"
35 symbols: BOXES
36}
37panels {
38 name: "HARE"
39 path: "Panels/panel_8"
40 clue: "hare"
41 answer: "chair"
42 symbols: ZERO
43}
44panels {
45 name: "CHIME"
46 path: "Panels/panel_9"
47 clue: "chime"
48 answer: "chimney"
49 symbols: SPARKLES
50}
51panels {
52 name: "LIBRARY"
53 path: "Panels/panel_10"
54 clue: "library"
55 answer: "book"
56 symbols: BOXES
57}
diff --git a/data/maps/the_wondrous/rooms/Regular.txtpb b/data/maps/the_wondrous/rooms/Regular.txtpb new file mode 100644 index 0000000..65df029 --- /dev/null +++ b/data/maps/the_wondrous/rooms/Regular.txtpb
@@ -0,0 +1,8 @@
1name: "Regular"
2panels {
3 name: "SHRINK"
4 path: "Panels/panel_2"
5 clue: "shrink"
6 answer: "shrink"
7 display_name: "SHRINK (1)"
8}
diff --git a/data/maps/the_words/connections.txtpb b/data/maps/the_words/connections.txtpb new file mode 100644 index 0000000..f25ac2b --- /dev/null +++ b/data/maps/the_words/connections.txtpb
@@ -0,0 +1,5 @@
1connections {
2 from_room: "Main Area"
3 to_room: "Ending"
4 door { name: "Ending" }
5}
diff --git a/data/maps/the_words/doors.txtpb b/data/maps/the_words/doors.txtpb new file mode 100644 index 0000000..20f439b --- /dev/null +++ b/data/maps/the_words/doors.txtpb
@@ -0,0 +1,12 @@
1doors {
2 name: "Ending"
3 type: EVENT
4 panels { room: "Main Area" name: "FRUIT" }
5 panels { room: "Main Area" name: "FLOWER" }
6 panels { room: "Main Area" name: "GEM" }
7 panels { room: "Main Area" name: "DAIRY" }
8 panels { room: "Main Area" name: "TREE" }
9 panels { room: "Main Area" name: "METAL" }
10 panels { room: "Main Area" name: "CLOTHES" }
11 panels { room: "Main Area" name: "SPICE" }
12}
diff --git a/data/maps/the_words/metadata.txtpb b/data/maps/the_words/metadata.txtpb new file mode 100644 index 0000000..2dadcae --- /dev/null +++ b/data/maps/the_words/metadata.txtpb
@@ -0,0 +1,11 @@
1display_name: "The Words"
2# These are old proxies of the main room's panels that are not linked up
3# anymore.
4excluded_nodes: "Panels/Proxies/panel_3"
5excluded_nodes: "Panels/Proxies/panel_4"
6excluded_nodes: "Panels/Proxies/panel_6"
7excluded_nodes: "Panels/Proxies/panel_9"
8# These are all tantalyzingly hidden out of bounds. What's up with that?
9excluded_nodes: "Panels/Proxies/panel_backside_1"
10excluded_nodes: "Panels/Proxies/panel_backside_2"
11excluded_nodes: "Panels/Proxies/panel_backside_3"
diff --git a/data/maps/the_words/rooms/Ending.txtpb b/data/maps/the_words/rooms/Ending.txtpb new file mode 100644 index 0000000..79bd569 --- /dev/null +++ b/data/maps/the_words/rooms/Ending.txtpb
@@ -0,0 +1,5 @@
1name: "Ending"
2endings {
3 name: "BLUE"
4 path: "Components/Endings/blue_ending"
5}
diff --git a/data/maps/the_words/rooms/Main Area.txtpb b/data/maps/the_words/rooms/Main Area.txtpb new file mode 100644 index 0000000..ae57252 --- /dev/null +++ b/data/maps/the_words/rooms/Main Area.txtpb
@@ -0,0 +1,64 @@
1name: "Main Area"
2panels {
3 name: "FRUIT"
4 path: "Panels/Room_1/panel_2"
5 clue: "fruit"
6 answer: "peach"
7 symbols: EXAMPLE
8}
9panels {
10 name: "FLOWER"
11 path: "Panels/Room_1/panel_3"
12 clue: "flower"
13 answer: "rose"
14 symbols: EXAMPLE
15}
16panels {
17 name: "GEM"
18 path: "Panels/Room_1/panel_4"
19 clue: "gem"
20 answer: "jade"
21 symbols: EXAMPLE
22}
23panels {
24 name: "DAIRY"
25 path: "Panels/Room_1/panel_5"
26 clue: "dairy"
27 answer: "cream"
28 symbols: EXAMPLE
29}
30panels {
31 name: "TREE"
32 path: "Panels/Room_1/panel_6"
33 clue: "tree"
34 answer: "walnut"
35 symbols: EXAMPLE
36}
37panels {
38 name: "METAL"
39 path: "Panels/Room_1/panel_7"
40 clue: "metal"
41 answer: "silver"
42 symbols: EXAMPLE
43}
44panels {
45 name: "CLOTHES"
46 path: "Panels/Room_1/panel_8"
47 clue: "clothes"
48 answer: "denim"
49 symbols: EXAMPLE
50}
51panels {
52 name: "SPICE"
53 path: "Panels/Room_1/panel_9"
54 clue: "spice"
55 answer: "sage"
56 symbols: EXAMPLE
57}
58ports {
59 name: "ENTRY"
60 display_name: "Worldport"
61 path: "Components/Warps/worldport"
62 destination { x: 0 y: 0 z: 9.5 }
63 rotation: 0
64}
diff --git a/data/metadata.txtpb b/data/metadata.txtpb new file mode 100644 index 0000000..c7dc650 --- /dev/null +++ b/data/metadata.txtpb
@@ -0,0 +1,54 @@
1version {
2 major: 7
3 minor: 0
4 patch: 1
5}
6# Filler item.
7special_names: "A Job Well Done"
8# Symbol items.
9special_names: "Age Symbol"
10special_names: "Anagram Symbol"
11special_names: "Boxes Symbol"
12special_names: "Cross Symbol"
13special_names: "Eval Symbol"
14special_names: "Example Symbol"
15special_names: "Gender Symbol"
16special_names: "Job Symbol"
17special_names: "Lingo Symbol"
18special_names: "Null Symbol"
19special_names: "Planet Symbol"
20special_names: "Pyramid Symbol"
21special_names: "Question Symbol"
22special_names: "Sound Symbol"
23special_names: "Sparkles Symbol"
24special_names: "Stars Symbol"
25special_names: "Sun Symbol"
26special_names: "Sweet Symbol"
27special_names: "Zero Symbol"
28# Anti collectable traps
29special_names: "Anti A"
30special_names: "Anti B"
31special_names: "Anti C"
32special_names: "Anti D"
33special_names: "Anti E"
34special_names: "Anti F"
35special_names: "Anti G"
36special_names: "Anti H"
37special_names: "Anti I"
38special_names: "Anti J"
39special_names: "Anti K"
40special_names: "Anti L"
41special_names: "Anti M"
42special_names: "Anti N"
43special_names: "Anti O"
44special_names: "Anti P"
45special_names: "Anti Q"
46special_names: "Anti R"
47special_names: "Anti S"
48special_names: "Anti T"
49special_names: "Anti U"
50special_names: "Anti V"
51special_names: "Anti W"
52special_names: "Anti X"
53special_names: "Anti Y"
54special_names: "Anti Z"
diff --git a/data/progressives.txtpb b/data/progressives.txtpb new file mode 100644 index 0000000..0eba2bf --- /dev/null +++ b/data/progressives.txtpb
@@ -0,0 +1,11 @@
1progressives {
2 name: "Progressive Gold Ending"
3 doors { map: "daedalus" name: "Red Rainbow Room" }
4 doors { map: "daedalus" name: "Orange Rainbow Room" }
5 doors { map: "daedalus" name: "Yellow Rainbow Room" }
6 doors { map: "daedalus" name: "Green Rainbow Room" }
7 doors { map: "daedalus" name: "Blue Rainbow Room" }
8 doors { map: "daedalus" name: "Purple Rainbow Room" }
9 doors { map: "daedalus" name: "Cyan Rainbow Room" }
10 doors { map: "daedalus" name: "Brown Rainbow Room" }
11}
diff --git a/proto/data.proto b/proto/data.proto index d3933c4..d79f47d 100644 --- a/proto/data.proto +++ b/proto/data.proto
@@ -27,6 +27,29 @@ enum DoorType {
27 27
28 // This door is an item if gravestone shuffle is enabled, and is a location as long as panelsanity is not on. 28 // This door is an item if gravestone shuffle is enabled, and is a location as long as panelsanity is not on.
29 GRAVESTONE = 6; 29 GRAVESTONE = 6;
30
31 // This door is never a location, and is an item as long as gallery painting shuffle is on.
32 GALLERY_PAINTING = 7;
33}
34
35enum DoorGroupType {
36 DOOR_GROUP_TYPE_UNKNOWN = 0;
37
38 // These doors border a worldport. They should be grouped when connections are
39 // not shuffled.
40 CONNECTOR = 1;
41
42 // Similar to CONNECTOR, but these doors are also ordinarily opened by solving
43 // the COLOR panel in the Control Center. These should be grouped when
44 // connections are not shuffled, but are not items at all when control center
45 // colors are not shuffled.
46 COLOR_CONNECTOR = 2;
47
48 // Groups with this type become an item if cyan door behavior is set to item.
49 CYAN_DOORS = 3;
50
51 // Groups with this type always become an item if door shuffle is on.
52 SHUFFLE_GROUP = 4;
30} 53}
31 54
32enum AxisDirection { 55enum AxisDirection {
@@ -64,6 +87,18 @@ enum PuzzleSymbol {
64 QUESTION = 19; 87 QUESTION = 19;
65} 88}
66 89
90message Vec3d {
91 optional double x = 1;
92 optional double y = 2;
93 optional double z = 3;
94}
95
96message VersionNumber {
97 optional uint64 major = 1;
98 optional uint64 minor = 2;
99 optional uint64 patch = 3;
100}
101
67message ProxyIdentifier { 102message ProxyIdentifier {
68 optional uint64 panel = 1; 103 optional uint64 panel = 1;
69 optional string answer = 2; 104 optional string answer = 2;
@@ -84,6 +119,11 @@ message Connection {
84 uint64 painting = 5; 119 uint64 painting = 5;
85 ProxyIdentifier panel = 6; 120 ProxyIdentifier panel = 6;
86 } 121 }
122
123 optional bool roof_access = 7;
124 optional bool purple_ending = 8;
125 optional bool cyan_ending = 9;
126 optional bool vanilla_only = 10;
87} 127}
88 128
89message Door { 129message Door {
@@ -100,12 +140,16 @@ message Door {
100 optional uint64 complete_at = 12; 140 optional uint64 complete_at = 12;
101 141
102 optional string control_center_color = 6; 142 optional string control_center_color = 6;
103 repeated string switches = 7;
104 repeated KeyholderAnswer keyholders = 13; 143 repeated KeyholderAnswer keyholders = 13;
105 repeated uint64 rooms = 14; 144 repeated uint64 rooms = 14;
106 repeated uint64 doors = 15; 145 repeated uint64 doors = 15;
146 repeated uint64 endings = 16;
147 optional bool double_letters = 18;
148 repeated string senders = 19;
107 149
108 optional DoorType type = 8; 150 optional DoorType type = 8;
151
152 optional string location_name = 17;
109} 153}
110 154
111message PanelData { 155message PanelData {
@@ -123,9 +167,11 @@ message PanelData {
123 167
124 optional uint64 required_door = 9; 168 optional uint64 required_door = 9;
125 optional uint64 required_room = 11; 169 optional uint64 required_room = 11;
170
171 optional string display_name = 12;
126} 172}
127 173
128message Painting { 174message PaintingData {
129 optional uint64 id = 1; 175 optional uint64 id = 1;
130 optional uint64 room_id = 2; 176 optional uint64 room_id = 2;
131 optional string name = 9; 177 optional string name = 9;
@@ -147,19 +193,24 @@ message Port {
147 optional uint64 room_id = 2; 193 optional uint64 room_id = 2;
148 optional string name = 3; 194 optional string name = 3;
149 195
196 optional string display_name = 10;
150 optional string path = 4; 197 optional string path = 4;
151 optional string orientation = 5; 198 optional Vec3d destination = 5;
199 optional double rotation = 8;
152 optional AxisDirection gravity = 7; 200 optional AxisDirection gravity = 7;
201 optional bool no_shuffle = 9;
153 202
154 optional uint64 required_door = 6; 203 optional uint64 required_door = 6;
155} 204}
156 205
157message Keyholder { 206message KeyholderData {
158 optional uint64 id = 1; 207 optional uint64 id = 1;
208 optional uint64 ap_id = 6;
159 optional uint64 room_id = 2; 209 optional uint64 room_id = 2;
160 210
161 optional string name = 3; 211 optional string name = 3;
162 optional string path = 4; 212 optional string path = 4;
213 optional string key = 5;
163} 214}
164 215
165message Letter { 216message Letter {
@@ -197,6 +248,7 @@ message Room {
197 optional uint64 map_id = 8; 248 optional uint64 map_id = 8;
198 optional string name = 2; 249 optional string name = 2;
199 optional string display_name = 3; 250 optional string display_name = 3;
251 optional string panel_display_name = 13;
200 252
201 repeated uint64 panels = 4; 253 repeated uint64 panels = 4;
202 repeated uint64 paintings = 5; 254 repeated uint64 paintings = 5;
@@ -214,17 +266,36 @@ message Map {
214 optional string display_name = 3; 266 optional string display_name = 3;
215} 267}
216 268
269message Progressive {
270 optional uint64 id = 1;
271 optional string name = 2;
272 optional uint64 ap_id = 3;
273 repeated uint64 doors = 4;
274}
275
276message DoorGroup {
277 optional uint64 id = 1;
278 optional string name = 2;
279 optional uint64 ap_id = 3;
280 optional DoorGroupType type = 4;
281 repeated uint64 doors = 5;
282}
283
217message AllObjects { 284message AllObjects {
285 optional VersionNumber version = 15;
286
218 repeated Map maps = 7; 287 repeated Map maps = 7;
219 repeated Room rooms = 1; 288 repeated Room rooms = 1;
220 repeated Door doors = 2; 289 repeated Door doors = 2;
221 repeated PanelData panels = 3; 290 repeated PanelData panels = 3;
222 repeated Painting paintings = 4; 291 repeated PaintingData paintings = 4;
223 repeated Port ports = 5; 292 repeated Port ports = 5;
224 repeated Keyholder keyholders = 11; 293 repeated KeyholderData keyholders = 11;
225 repeated Letter letters = 9; 294 repeated Letter letters = 9;
226 repeated Mastery masteries = 10; 295 repeated Mastery masteries = 10;
227 repeated Ending endings = 12; 296 repeated Ending endings = 12;
228 repeated Connection connections = 6; 297 repeated Connection connections = 6;
298 repeated Progressive progressives = 13;
299 repeated DoorGroup door_groups = 14;
229 map<string, uint64> special_ids = 8; 300 map<string, uint64> special_ids = 8;
230} 301}
diff --git a/proto/human.proto b/proto/human.proto index e0021c2..8e7767a 100644 --- a/proto/human.proto +++ b/proto/human.proto
@@ -62,6 +62,25 @@ message HumanConnection {
62 62
63 optional bool oneway = 3; 63 optional bool oneway = 3;
64 optional DoorIdentifier door = 4; 64 optional DoorIdentifier door = 4;
65
66 // If true, this connection will only be logically allowed if the Daedalus
67 // Roof Access option is enabled.
68 optional bool roof_access = 7;
69
70 // This means that the connection intentionally skips the target object's
71 // required door.
72 optional bool bypass_target_door = 8;
73
74 // This means that the connection should additionally require all purple
75 // letters when the Strict Purple Ending option is on.
76 optional bool purple_ending = 9;
77
78 // This means that the connection should additionally require all cyan letters
79 // when the Strict Cyan Ending option is on.
80 optional bool cyan_ending = 10;
81
82 // This means that the connection only exists when doors are not shuffled.
83 optional bool vanilla_only = 11;
65} 84}
66 85
67message HumanConnections { 86message HumanConnections {
@@ -82,13 +101,19 @@ message HumanDoor {
82 optional uint64 complete_at = 9; 101 optional uint64 complete_at = 9;
83 102
84 optional string control_center_color = 6; 103 optional string control_center_color = 6;
85 repeated string switches = 7;
86 repeated KeyholderIdentifier keyholders = 10; 104 repeated KeyholderIdentifier keyholders = 10;
87 repeated RoomIdentifier rooms = 11; 105 repeated RoomIdentifier rooms = 11;
88 repeated DoorIdentifier doors = 12; 106 repeated DoorIdentifier doors = 12;
107 repeated string endings = 13;
108 optional bool double_letters = 15;
109
110 // Sender nodes to be added to the list of requirements for triggering the
111 // location. Only for senders that have no logic requirements.
112 repeated string senders = 16;
89 113
90 optional DoorType type = 4; 114 optional DoorType type = 4;
91 optional string location_room = 5; 115 optional string location_room = 5;
116 optional string location_name = 14;
92} 117}
93 118
94message HumanDoors { 119message HumanDoors {
@@ -107,6 +132,8 @@ message HumanPanel {
107 132
108 optional DoorIdentifier required_door = 7; 133 optional DoorIdentifier required_door = 7;
109 optional RoomIdentifier required_room = 8; 134 optional RoomIdentifier required_room = 8;
135
136 optional string display_name = 9;
110} 137}
111 138
112message HumanPainting { 139message HumanPainting {
@@ -126,9 +153,16 @@ message HumanPainting {
126 153
127message HumanPort { 154message HumanPort {
128 optional string name = 1; 155 optional string name = 1;
156 optional string display_name = 8;
129 optional string path = 2; 157 optional string path = 2;
130 158
131 optional string orientation = 3; 159 optional bool no_shuffle = 7;
160
161 // These specify how the player should be placed when a randomized entrance
162 // sends them to this port. "rotation" is in degrees and is counter-clockwise
163 // from the positive X axis.
164 optional Vec3d destination = 3;
165 optional double rotation = 6;
132 optional AxisDirection gravity = 5 [default = Y_MINUS]; 166 optional AxisDirection gravity = 5 [default = Y_MINUS];
133 167
134 optional DoorIdentifier required_door = 4; 168 optional DoorIdentifier required_door = 4;
@@ -137,6 +171,13 @@ message HumanPort {
137message HumanKeyholder { 171message HumanKeyholder {
138 optional string name = 1; 172 optional string name = 1;
139 optional string path = 2; 173 optional string path = 2;
174
175 // If this is set, the keyholder will become a location when keyholder shuffle
176 // is enabled. This value specifies the key that is required to clear the
177 // location. It should be the same as the key needed for Green Ending. The
178 // only cases when this shouldn't be set is the two disappearing keyholders in
179 // The Congruent.
180 optional string key = 3;
140} 181}
141 182
142message HumanLetter { 183message HumanLetter {
@@ -160,6 +201,10 @@ message HumanRoom {
160 optional string name = 1; 201 optional string name = 1;
161 optional string display_name = 2; 202 optional string display_name = 2;
162 203
204 // This is used in panelsanity location names and location names for STANDARD
205 // doors generated from panels in the same area.
206 optional string panel_display_name = 10;
207
163 repeated HumanPanel panels = 3; 208 repeated HumanPanel panels = 3;
164 repeated HumanPainting paintings = 4; 209 repeated HumanPainting paintings = 4;
165 repeated HumanLetter letters = 5; 210 repeated HumanLetter letters = 5;
@@ -174,10 +219,35 @@ message HumanMap {
174 repeated string excluded_nodes = 2; 219 repeated string excluded_nodes = 2;
175} 220}
176 221
222message HumanProgressive {
223 optional string name = 1;
224 repeated DoorIdentifier doors = 2;
225}
226
227message HumanProgressives {
228 repeated HumanProgressive progressives = 1;
229}
230
231message HumanDoorGroup {
232 optional string name = 1;
233 optional DoorGroupType type = 2;
234 repeated DoorIdentifier doors = 3;
235}
236
237message HumanDoorGroups {
238 repeated HumanDoorGroup door_groups = 1;
239}
240
241message HumanGlobalMetadata {
242 repeated string special_names = 1;
243 optional VersionNumber version = 2;
244}
245
177message IdMappings { 246message IdMappings {
178 message RoomIds { 247 message RoomIds {
179 map<string, uint64> panels = 1; 248 map<string, uint64> panels = 1;
180 map<string, uint64> masteries = 2; 249 map<string, uint64> masteries = 2;
250 map<string, uint64> keyholders = 3;
181 } 251 }
182 252
183 message MapIds { 253 message MapIds {
@@ -189,4 +259,6 @@ message IdMappings {
189 map<string, uint64> special = 2; 259 map<string, uint64> special = 2;
190 map<string, uint64> letters = 3; 260 map<string, uint64> letters = 3;
191 map<string, uint64> endings = 4; 261 map<string, uint64> endings = 4;
262 map<string, uint64> progressives = 5;
263 map<string, uint64> door_groups = 6;
192} 264}
diff --git a/tools/assign_ids/main.cpp b/tools/assign_ids/main.cpp index 77c0e5a..3e16f78 100644 --- a/tools/assign_ids/main.cpp +++ b/tools/assign_ids/main.cpp
@@ -2,6 +2,7 @@
2#include <google/protobuf/text_format.h> 2#include <google/protobuf/text_format.h>
3 3
4#include <cstdint> 4#include <cstdint>
5#include <filesystem>
5#include <fstream> 6#include <fstream>
6#include <iostream> 7#include <iostream>
7#include <map> 8#include <map>
@@ -40,6 +41,10 @@ class AssignIds {
40 ReadIds(ids_path); 41 ReadIds(ids_path);
41 42
42 ProcessMaps(datadir_path); 43 ProcessMaps(datadir_path);
44 ProcessSpecialIds();
45 ProcessProgressivesFile(datadir_path / "progressives.txtpb");
46 ProcessDoorGroupsFile(datadir_path / "door_groups.txtpb");
47 ProcessGlobalMetadataFile(datadir_path / "metadata.txtpb");
43 48
44 WriteIds(ids_path); 49 WriteIds(ids_path);
45 50
@@ -54,50 +59,26 @@ class AssignIds {
54 id_mappings_ = ReadIdsFromYaml(path.string()); 59 id_mappings_ = ReadIdsFromYaml(path.string());
55 60
56 for (const auto& [_, map] : id_mappings_.maps()) { 61 for (const auto& [_, map] : id_mappings_.maps()) {
57 for (const auto& [_, id] : map.doors()) { 62 UpdateNextId(map.doors());
58 if (id > next_id_) {
59 next_id_ = id;
60 }
61 }
62 63
63 for (const auto& [_, room] : map.rooms()) { 64 for (const auto& [_, room] : map.rooms()) {
64 for (const auto& [_, id] : room.panels()) { 65 UpdateNextId(room.panels());
65 if (id > next_id_) { 66 UpdateNextId(room.masteries());
66 next_id_ = id; 67 UpdateNextId(room.keyholders());
67 }
68 }
69
70 for (const auto& [_, id] : room.masteries()) {
71 if (id > next_id_) {
72 next_id_ = id;
73 }
74 }
75 }
76 }
77
78 for (const auto& [_, id] : id_mappings_.special()) {
79 if (id > next_id_) {
80 next_id_ = id;
81 }
82 }
83
84 for (const auto& [_, id] : id_mappings_.letters()) {
85 if (id > next_id_) {
86 next_id_ = id;
87 } 68 }
88 } 69 }
89 70
90 for (const auto& [_, id] : id_mappings_.endings()) { 71 UpdateNextId(id_mappings_.special());
91 if (id > next_id_) { 72 UpdateNextId(id_mappings_.letters());
92 next_id_ = id; 73 UpdateNextId(id_mappings_.endings());
93 } 74 UpdateNextId(id_mappings_.progressives());
94 } 75 UpdateNextId(id_mappings_.door_groups());
95 76
96 next_id_++; 77 next_id_++;
97 } 78 }
98 79
99 void WriteIds(std::filesystem::path path) { 80 void WriteIds(std::filesystem::path path) {
100 WriteIdsAsYaml(id_mappings_, path.string()); 81 WriteIdsAsYaml(output_, path.string());
101 } 82 }
102 83
103 void ProcessMaps(std::filesystem::path path) { 84 void ProcessMaps(std::filesystem::path path) {
@@ -134,14 +115,18 @@ class AssignIds {
134 return; 115 return;
135 } 116 }
136 117
118 auto& maps = *output_.mutable_maps();
119 auto& doors = *maps[current_map_name].mutable_doors();
120
137 if (!id_mappings_.maps().contains(current_map_name) || 121 if (!id_mappings_.maps().contains(current_map_name) ||
138 !id_mappings_.maps() 122 !id_mappings_.maps()
139 .at(current_map_name) 123 .at(current_map_name)
140 .doors() 124 .doors()
141 .contains(h_door.name())) { 125 .contains(h_door.name())) {
142 auto& maps = *id_mappings_.mutable_maps();
143 auto& doors = *maps[current_map_name].mutable_doors();
144 doors[h_door.name()] = next_id_++; 126 doors[h_door.name()] = next_id_++;
127 } else {
128 doors[h_door.name()] =
129 id_mappings_.maps().at(current_map_name).doors().at(h_door.name());
145 } 130 }
146 } 131 }
147 132
@@ -156,6 +141,10 @@ class AssignIds {
156 void ProcessRoom(const HumanRoom& h_room, 141 void ProcessRoom(const HumanRoom& h_room,
157 const std::string& current_map_name) { 142 const std::string& current_map_name) {
158 for (const HumanPanel& h_panel : h_room.panels()) { 143 for (const HumanPanel& h_panel : h_room.panels()) {
144 auto& maps = *output_.mutable_maps();
145 auto& rooms = *maps[current_map_name].mutable_rooms();
146 auto& panels = *rooms[h_room.name()].mutable_panels();
147
159 if (!id_mappings_.maps().contains(current_map_name) || 148 if (!id_mappings_.maps().contains(current_map_name) ||
160 !id_mappings_.maps() 149 !id_mappings_.maps()
161 .at(current_map_name) 150 .at(current_map_name)
@@ -167,23 +156,33 @@ class AssignIds {
167 .at(h_room.name()) 156 .at(h_room.name())
168 .panels() 157 .panels()
169 .contains(h_panel.name())) { 158 .contains(h_panel.name())) {
170 auto& maps = *id_mappings_.mutable_maps();
171 auto& rooms = *maps[current_map_name].mutable_rooms();
172 auto& panels = *rooms[h_room.name()].mutable_panels();
173 panels[h_panel.name()] = next_id_++; 159 panels[h_panel.name()] = next_id_++;
160 } else {
161 panels[h_panel.name()] = id_mappings_.maps()
162 .at(current_map_name)
163 .rooms()
164 .at(h_room.name())
165 .panels()
166 .at(h_panel.name());
174 } 167 }
175 } 168 }
176 169
177 for (const HumanLetter& h_letter : h_room.letters()) { 170 for (const HumanLetter& h_letter : h_room.letters()) {
178 std::string lettername = GetLetterName(h_letter.key(), h_letter.level2()); 171 std::string lettername = GetLetterName(h_letter.key(), h_letter.level2());
179 172
173 auto& letters = *output_.mutable_letters();
180 if (!id_mappings_.letters().contains(lettername)) { 174 if (!id_mappings_.letters().contains(lettername)) {
181 auto& letters = *id_mappings_.mutable_letters();
182 letters[lettername] = next_id_++; 175 letters[lettername] = next_id_++;
176 } else {
177 letters[lettername] = id_mappings_.letters().at(lettername);
183 } 178 }
184 } 179 }
185 180
186 for (const HumanMastery& h_mastery : h_room.masteries()) { 181 for (const HumanMastery& h_mastery : h_room.masteries()) {
182 auto& maps = *output_.mutable_maps();
183 auto& rooms = *maps[current_map_name].mutable_rooms();
184 auto& masteries = *rooms[h_room.name()].mutable_masteries();
185
187 if (!id_mappings_.maps().contains(current_map_name) || 186 if (!id_mappings_.maps().contains(current_map_name) ||
188 !id_mappings_.maps() 187 !id_mappings_.maps()
189 .at(current_map_name) 188 .at(current_map_name)
@@ -195,27 +194,133 @@ class AssignIds {
195 .at(h_room.name()) 194 .at(h_room.name())
196 .masteries() 195 .masteries()
197 .contains(h_mastery.name())) { 196 .contains(h_mastery.name())) {
198 auto& maps = *id_mappings_.mutable_maps();
199 auto& rooms = *maps[current_map_name].mutable_rooms();
200 auto& masteries = *rooms[h_room.name()].mutable_masteries();
201 masteries[h_mastery.name()] = next_id_++; 197 masteries[h_mastery.name()] = next_id_++;
198 } else {
199 masteries[h_mastery.name()] = id_mappings_.maps()
200 .at(current_map_name)
201 .rooms()
202 .at(h_room.name())
203 .masteries()
204 .at(h_mastery.name());
202 } 205 }
203 } 206 }
204 207
205 for (const HumanEnding& h_ending : h_room.endings()) { 208 for (const HumanEnding& h_ending : h_room.endings()) {
209 auto& endings = *output_.mutable_endings();
210
206 if (!id_mappings_.endings().contains(h_ending.name())) { 211 if (!id_mappings_.endings().contains(h_ending.name())) {
207 auto& endings = *id_mappings_.mutable_endings();
208 endings[h_ending.name()] = next_id_++; 212 endings[h_ending.name()] = next_id_++;
213 } else {
214 endings[h_ending.name()] = id_mappings_.endings().at(h_ending.name());
215 }
216 }
217
218 for (const HumanKeyholder& h_keyholder : h_room.keyholders()) {
219 if (!h_keyholder.has_key()) {
220 continue;
221 }
222
223 auto& maps = *output_.mutable_maps();
224 auto& rooms = *maps[current_map_name].mutable_rooms();
225 auto& keyholders = *rooms[h_room.name()].mutable_keyholders();
226
227 if (!id_mappings_.maps().contains(current_map_name) ||
228 !id_mappings_.maps()
229 .at(current_map_name)
230 .rooms()
231 .contains(h_room.name()) ||
232 !id_mappings_.maps()
233 .at(current_map_name)
234 .rooms()
235 .at(h_room.name())
236 .keyholders()
237 .contains(h_keyholder.name())) {
238 keyholders[h_keyholder.name()] = next_id_++;
239 } else {
240 keyholders[h_keyholder.name()] = id_mappings_.maps()
241 .at(current_map_name)
242 .rooms()
243 .at(h_room.name())
244 .keyholders()
245 .at(h_keyholder.name());
246 }
247 }
248 }
249
250 void ProcessSpecialIds() {
251 auto& specials = *output_.mutable_special();
252
253 for (const auto& [special_name, ap_id] : id_mappings_.special()) {
254 specials[special_name] = ap_id;
255 }
256 }
257
258 void ProcessProgressivesFile(std::filesystem::path path) {
259 if (!std::filesystem::exists(path)) {
260 return;
261 }
262
263 auto h_progs = ReadMessageFromFile<HumanProgressives>(path.string());
264 auto& progs = *output_.mutable_progressives();
265
266 for (const HumanProgressive& h_prog : h_progs.progressives()) {
267 if (!id_mappings_.progressives().contains(h_prog.name())) {
268 progs[h_prog.name()] = next_id_++;
269 } else {
270 progs[h_prog.name()] = id_mappings_.progressives().at(h_prog.name());
271 }
272 }
273 }
274
275 void ProcessDoorGroupsFile(std::filesystem::path path) {
276 if (!std::filesystem::exists(path)) {
277 return;
278 }
279
280 auto h_groups = ReadMessageFromFile<HumanDoorGroups>(path.string());
281 auto& groups = *output_.mutable_door_groups();
282
283 for (const HumanDoorGroup& h_group : h_groups.door_groups()) {
284 if (!id_mappings_.door_groups().contains(h_group.name())) {
285 groups[h_group.name()] = next_id_++;
286 } else {
287 groups[h_group.name()] = id_mappings_.door_groups().at(h_group.name());
288 }
289 }
290 }
291
292 void ProcessGlobalMetadataFile(std::filesystem::path path) {
293 if (!std::filesystem::exists(path)) {
294 return;
295 }
296
297 auto h_metadata = ReadMessageFromFile<HumanGlobalMetadata>(path.string());
298 auto& specials = *output_.mutable_special();
299
300 for (const std::string& h_special : h_metadata.special_names()) {
301 if (!id_mappings_.special().contains(h_special)) {
302 specials[h_special] = next_id_++;
303 } else {
304 specials[h_special] = id_mappings_.special().at(h_special);
209 } 305 }
210 } 306 }
211 } 307 }
212 308
213 private: 309 private:
310 void UpdateNextId(const google::protobuf::Map<std::string, uint64_t>& ids) {
311 for (const auto& [_, id] : ids) {
312 if (id > next_id_) {
313 next_id_ = id;
314 }
315 }
316 }
317
214 std::string mapdir_; 318 std::string mapdir_;
215 319
216 uint64_t next_id_ = 0; 320 uint64_t next_id_ = 1;
217 321
218 IdMappings id_mappings_; 322 IdMappings id_mappings_;
323 IdMappings output_;
219}; 324};
220 325
221} // namespace 326} // namespace
diff --git a/tools/datapacker/container.cpp b/tools/datapacker/container.cpp index 0d3417e..4a656b3 100644 --- a/tools/datapacker/container.cpp +++ b/tools/datapacker/container.cpp
@@ -79,7 +79,7 @@ uint64_t Container::FindOrAddPainting(
79 auto it = room_container.find(painting_name); 79 auto it = room_container.find(painting_name);
80 if (it == room_container.end()) { 80 if (it == room_container.end()) {
81 uint64_t new_id = all_objects_.paintings_size(); 81 uint64_t new_id = all_objects_.paintings_size();
82 Painting* painting = all_objects_.add_paintings(); 82 PaintingData* painting = all_objects_.add_paintings();
83 painting->set_id(new_id); 83 painting->set_id(new_id);
84 painting->set_room_id(FindOrAddRoom(map_name, *room_name, std::nullopt)); 84 painting->set_room_id(FindOrAddRoom(map_name, *room_name, std::nullopt));
85 painting->set_name(painting_name); 85 painting->set_name(painting_name);
@@ -289,7 +289,7 @@ uint64_t Container::FindOrAddKeyholder(
289 auto it = room_container.find(keyholder_name); 289 auto it = room_container.find(keyholder_name);
290 if (it == room_container.end()) { 290 if (it == room_container.end()) {
291 uint64_t new_id = all_objects_.keyholders_size(); 291 uint64_t new_id = all_objects_.keyholders_size();
292 Keyholder* keyholder = all_objects_.add_keyholders(); 292 KeyholderData* keyholder = all_objects_.add_keyholders();
293 keyholder->set_id(new_id); 293 keyholder->set_id(new_id);
294 keyholder->set_room_id(FindOrAddRoom(map_name, *room_name, std::nullopt)); 294 keyholder->set_room_id(FindOrAddRoom(map_name, *room_name, std::nullopt));
295 keyholder->set_name(keyholder_name); 295 keyholder->set_name(keyholder_name);
@@ -331,6 +331,40 @@ uint64_t Container::FindOrAddDoor(std::optional<std::string> map_name,
331 } 331 }
332} 332}
333 333
334uint64_t Container::FindOrAddProgressive(std::string prog_name) {
335 auto it = progressive_id_by_name_.find(prog_name);
336
337 if (it == progressive_id_by_name_.end()) {
338 uint64_t new_id = all_objects_.progressives_size();
339 Progressive* progressive = all_objects_.add_progressives();
340 progressive->set_id(new_id);
341 progressive->set_name(prog_name);
342
343 progressive_id_by_name_[prog_name] = new_id;
344
345 return new_id;
346 } else {
347 return it->second;
348 }
349}
350
351uint64_t Container::FindOrAddDoorGroup(std::string group_name) {
352 auto it = door_group_id_by_name_.find(group_name);
353
354 if (it == door_group_id_by_name_.end()) {
355 uint64_t new_id = all_objects_.door_groups_size();
356 DoorGroup* door_group = all_objects_.add_door_groups();
357 door_group->set_id(new_id);
358 door_group->set_name(group_name);
359
360 door_group_id_by_name_[group_name] = new_id;
361
362 return new_id;
363 } else {
364 return it->second;
365 }
366}
367
334void Container::AddConnection(const Connection& connection) { 368void Container::AddConnection(const Connection& connection) {
335 *all_objects_.add_connections() = connection; 369 *all_objects_.add_connections() = connection;
336} 370}
diff --git a/tools/datapacker/container.h b/tools/datapacker/container.h index 68f5875..bc02ba4 100644 --- a/tools/datapacker/container.h +++ b/tools/datapacker/container.h
@@ -60,6 +60,10 @@ class Container {
60 60
61 void AddConnection(const Connection& connection); 61 void AddConnection(const Connection& connection);
62 62
63 uint64_t FindOrAddProgressive(std::string prog_name);
64
65 uint64_t FindOrAddDoorGroup(std::string group_name);
66
63 AllObjects& all_objects() { return all_objects_; } 67 AllObjects& all_objects() { return all_objects_; }
64 68
65 private: 69 private:
@@ -82,6 +86,8 @@ class Container {
82 std::map<std::string, std::map<std::string, uint64_t>> 86 std::map<std::string, std::map<std::string, uint64_t>>
83 door_id_by_map_door_names_; 87 door_id_by_map_door_names_;
84 std::map<std::string, uint64_t> ending_id_by_name_; 88 std::map<std::string, uint64_t> ending_id_by_name_;
89 std::map<std::string, uint64_t> progressive_id_by_name_;
90 std::map<std::string, uint64_t> door_group_id_by_name_;
85}; 91};
86 92
87} // namespace com::fourisland::lingo2_archipelago 93} // namespace com::fourisland::lingo2_archipelago
diff --git a/tools/datapacker/main.cpp b/tools/datapacker/main.cpp index 3ddb11f..e807d74 100644 --- a/tools/datapacker/main.cpp +++ b/tools/datapacker/main.cpp
@@ -43,6 +43,9 @@ class DataPacker {
43 43
44 ProcessConnectionsFile(datadir_path / "connections.txtpb", std::nullopt); 44 ProcessConnectionsFile(datadir_path / "connections.txtpb", std::nullopt);
45 ProcessMaps(datadir_path); 45 ProcessMaps(datadir_path);
46 ProcessProgressivesFile(datadir_path / "progressives.txtpb");
47 ProcessDoorGroupsFile(datadir_path / "door_groups.txtpb");
48 ProcessGlobalMetadataFile(datadir_path / "metadata.txtpb");
46 ProcessIdsFile(datadir_path / "ids.yaml"); 49 ProcessIdsFile(datadir_path / "ids.yaml");
47 50
48 { 51 {
@@ -104,7 +107,11 @@ class DataPacker {
104 container_.FindOrAddRoom(current_map_name, h_room.name(), std::nullopt); 107 container_.FindOrAddRoom(current_map_name, h_room.name(), std::nullopt);
105 Room& room = *container_.all_objects().mutable_rooms(room_id); 108 Room& room = *container_.all_objects().mutable_rooms(room_id);
106 109
107 room.set_display_name(h_room.display_name()); 110 // room.set_display_name(h_room.display_name());
111
112 if (h_room.has_panel_display_name()) {
113 room.set_panel_display_name(h_room.panel_display_name());
114 }
108 115
109 for (const HumanPanel& h_panel : h_room.panels()) { 116 for (const HumanPanel& h_panel : h_room.panels()) {
110 room.add_panels(ProcessPanel(h_panel, current_map_name, room.name())); 117 room.add_panels(ProcessPanel(h_panel, current_map_name, room.name()));
@@ -175,6 +182,10 @@ class DataPacker {
175 map_name, h_panel.required_room().name(), current_map_name)); 182 map_name, h_panel.required_room().name(), current_map_name));
176 } 183 }
177 184
185 if (h_panel.has_display_name()) {
186 panel.set_display_name(h_panel.display_name());
187 }
188
178 return panel_id; 189 return panel_id;
179 } 190 }
180 191
@@ -184,7 +195,7 @@ class DataPacker {
184 uint64_t painting_id = container_.FindOrAddPainting( 195 uint64_t painting_id = container_.FindOrAddPainting(
185 current_map_name, current_room_name, h_painting.name(), std::nullopt, 196 current_map_name, current_room_name, h_painting.name(), std::nullopt,
186 std::nullopt); 197 std::nullopt);
187 Painting& painting = 198 PaintingData& painting =
188 *container_.all_objects().mutable_paintings(painting_id); 199 *container_.all_objects().mutable_paintings(painting_id);
189 200
190 painting.set_path(h_painting.path()); 201 painting.set_path(h_painting.path());
@@ -228,7 +239,14 @@ class DataPacker {
228 Port& port = *container_.all_objects().mutable_ports(port_id); 239 Port& port = *container_.all_objects().mutable_ports(port_id);
229 240
230 port.set_path(h_port.path()); 241 port.set_path(h_port.path());
231 port.set_orientation(h_port.orientation()); 242 port.set_display_name(h_port.display_name());
243
244 if (h_port.no_shuffle()) {
245 port.set_no_shuffle(h_port.no_shuffle());
246 } else {
247 *port.mutable_destination() = h_port.destination();
248 port.set_rotation(h_port.rotation());
249 }
232 250
233 // Setting this explicitly because the Godot protobuf doesn't support 251 // Setting this explicitly because the Godot protobuf doesn't support
234 // custom defaults. 252 // custom defaults.
@@ -279,11 +297,15 @@ class DataPacker {
279 uint64_t keyholder_id = container_.FindOrAddKeyholder( 297 uint64_t keyholder_id = container_.FindOrAddKeyholder(
280 current_map_name, current_room_name, h_keyholder.name(), std::nullopt, 298 current_map_name, current_room_name, h_keyholder.name(), std::nullopt,
281 std::nullopt); 299 std::nullopt);
282 Keyholder& keyholder = 300 KeyholderData& keyholder =
283 *container_.all_objects().mutable_keyholders(keyholder_id); 301 *container_.all_objects().mutable_keyholders(keyholder_id);
284 302
285 keyholder.set_path(h_keyholder.path()); 303 keyholder.set_path(h_keyholder.path());
286 304
305 if (h_keyholder.has_key()) {
306 keyholder.set_key(h_keyholder.key());
307 }
308
287 return keyholder_id; 309 return keyholder_id;
288 } 310 }
289 311
@@ -331,8 +353,8 @@ class DataPacker {
331 h_door.receivers().begin(), h_door.receivers().end(), 353 h_door.receivers().begin(), h_door.receivers().end(),
332 google::protobuf::RepeatedFieldBackInserter(door.mutable_receivers())); 354 google::protobuf::RepeatedFieldBackInserter(door.mutable_receivers()));
333 std::copy( 355 std::copy(
334 h_door.switches().begin(), h_door.switches().end(), 356 h_door.senders().begin(), h_door.senders().end(),
335 google::protobuf::RepeatedFieldBackInserter(door.mutable_switches())); 357 google::protobuf::RepeatedFieldBackInserter(door.mutable_senders()));
336 358
337 for (const PaintingIdentifier& pi : h_door.move_paintings()) { 359 for (const PaintingIdentifier& pi : h_door.move_paintings()) {
338 std::optional<std::string> map_name = 360 std::optional<std::string> map_name =
@@ -381,6 +403,10 @@ class DataPacker {
381 container_.FindOrAddDoor(map_name, di.name(), current_map_name)); 403 container_.FindOrAddDoor(map_name, di.name(), current_map_name));
382 } 404 }
383 405
406 for (const std::string& ending_name : h_door.endings()) {
407 door.add_endings(container_.FindOrAddEnding(ending_name));
408 }
409
384 if (h_door.has_control_center_color()) { 410 if (h_door.has_control_center_color()) {
385 door.set_control_center_color(h_door.control_center_color()); 411 door.set_control_center_color(h_door.control_center_color());
386 } 412 }
@@ -390,6 +416,14 @@ class DataPacker {
390 } 416 }
391 417
392 door.set_type(h_door.type()); 418 door.set_type(h_door.type());
419
420 if (h_door.has_location_name()) {
421 door.set_location_name(h_door.location_name());
422 }
423
424 if (h_door.has_double_letters()) {
425 door.set_double_letters(h_door.double_letters());
426 }
393 } 427 }
394 428
395 void ProcessConnectionsFile(std::filesystem::path path, 429 void ProcessConnectionsFile(std::filesystem::path path,
@@ -441,6 +475,26 @@ class DataPacker {
441 r_connection.set_required_door(door_id); 475 r_connection.set_required_door(door_id);
442 } 476 }
443 477
478 if (human_connection.has_roof_access()) {
479 f_connection.set_roof_access(human_connection.roof_access());
480 r_connection.set_roof_access(human_connection.roof_access());
481 }
482
483 if (human_connection.has_purple_ending()) {
484 f_connection.set_purple_ending(human_connection.purple_ending());
485 r_connection.set_purple_ending(human_connection.purple_ending());
486 }
487
488 if (human_connection.has_cyan_ending()) {
489 f_connection.set_cyan_ending(human_connection.cyan_ending());
490 r_connection.set_cyan_ending(human_connection.cyan_ending());
491 }
492
493 if (human_connection.has_vanilla_only()) {
494 f_connection.set_vanilla_only(human_connection.vanilla_only());
495 r_connection.set_vanilla_only(human_connection.vanilla_only());
496 }
497
444 container_.AddConnection(f_connection); 498 container_.AddConnection(f_connection);
445 if (!human_connection.oneway()) { 499 if (!human_connection.oneway()) {
446 container_.AddConnection(r_connection); 500 container_.AddConnection(r_connection);
@@ -524,6 +578,63 @@ class DataPacker {
524 } 578 }
525 } 579 }
526 580
581 void ProcessProgressivesFile(std::filesystem::path path) {
582 if (!std::filesystem::exists(path)) {
583 return;
584 }
585
586 auto h_progs = ReadMessageFromFile<HumanProgressives>(path.string());
587
588 for (const HumanProgressive& h_prog : h_progs.progressives()) {
589 ProcessProgressive(h_prog);
590 }
591 }
592
593 void ProcessProgressive(const HumanProgressive& h_prog) {
594 uint64_t prog_id = container_.FindOrAddProgressive(h_prog.name());
595 Progressive& prog = *container_.all_objects().mutable_progressives(prog_id);
596
597 for (const DoorIdentifier& di : h_prog.doors()) {
598 uint64_t door_id =
599 container_.FindOrAddDoor(di.map(), di.name(), std::nullopt);
600 prog.add_doors(door_id);
601 }
602 }
603
604 void ProcessDoorGroupsFile(std::filesystem::path path) {
605 if (!std::filesystem::exists(path)) {
606 return;
607 }
608
609 auto h_groups = ReadMessageFromFile<HumanDoorGroups>(path.string());
610
611 for (const HumanDoorGroup& h_group : h_groups.door_groups()) {
612 ProcessDoorGroup(h_group);
613 }
614 }
615
616 void ProcessDoorGroup(const HumanDoorGroup& h_group) {
617 uint64_t group_id = container_.FindOrAddDoorGroup(h_group.name());
618 DoorGroup& group = *container_.all_objects().mutable_door_groups(group_id);
619
620 group.set_type(h_group.type());
621
622 for (const DoorIdentifier& di : h_group.doors()) {
623 uint64_t door_id =
624 container_.FindOrAddDoor(di.map(), di.name(), std::nullopt);
625 group.add_doors(door_id);
626 }
627 }
628
629 void ProcessGlobalMetadataFile(std::filesystem::path path) {
630 if (!std::filesystem::exists(path)) {
631 return;
632 }
633
634 auto h_metadata = ReadMessageFromFile<HumanGlobalMetadata>(path.string());
635 *container_.all_objects().mutable_version() = h_metadata.version();
636 }
637
527 void ProcessIdsFile(std::filesystem::path path) { 638 void ProcessIdsFile(std::filesystem::path path) {
528 auto ids = ReadIdsFromYaml(path.string()); 639 auto ids = ReadIdsFromYaml(path.string());
529 640
@@ -548,6 +659,14 @@ class DataPacker {
548 .mutable_masteries(mastery_id) 659 .mutable_masteries(mastery_id)
549 ->set_ap_id(ap_id); 660 ->set_ap_id(ap_id);
550 } 661 }
662
663 for (const auto& [keyholder_name, ap_id] : room.keyholders()) {
664 uint64_t keyholder_id = container_.FindOrAddKeyholder(
665 map_name, room_name, keyholder_name, std::nullopt, std::nullopt);
666 container_.all_objects()
667 .mutable_keyholders(keyholder_id)
668 ->set_ap_id(ap_id);
669 }
551 } 670 }
552 } 671 }
553 672
@@ -565,6 +684,16 @@ class DataPacker {
565 uint64_t ending_id = container_.FindOrAddEnding(ending_name); 684 uint64_t ending_id = container_.FindOrAddEnding(ending_name);
566 container_.all_objects().mutable_endings(ending_id)->set_ap_id(ap_id); 685 container_.all_objects().mutable_endings(ending_id)->set_ap_id(ap_id);
567 } 686 }
687
688 for (const auto& [prog_name, ap_id] : ids.progressives()) {
689 uint64_t prog_id = container_.FindOrAddProgressive(prog_name);
690 container_.all_objects().mutable_progressives(prog_id)->set_ap_id(ap_id);
691 }
692
693 for (const auto& [group_name, ap_id] : ids.door_groups()) {
694 uint64_t group_id = container_.FindOrAddDoorGroup(group_name);
695 container_.all_objects().mutable_door_groups(group_id)->set_ap_id(ap_id);
696 }
568 } 697 }
569 698
570 std::string mapdir_; 699 std::string mapdir_;
diff --git a/tools/util/godot_scene.cpp b/tools/util/godot_scene.cpp index 1e77c9e..f788d21 100644 --- a/tools/util/godot_scene.cpp +++ b/tools/util/godot_scene.cpp
@@ -1,10 +1,8 @@
1#include "godot_scene.h" 1#include "godot_scene.h"
2 2
3#include <absl/strings/str_split.h>
4#include <absl/strings/string_view.h>
5
6#include <fstream> 3#include <fstream>
7#include <sstream> 4#include <sstream>
5#include <string_view>
8#include <variant> 6#include <variant>
9 7
10namespace com::fourisland::lingo2_archipelago { 8namespace com::fourisland::lingo2_archipelago {
@@ -23,7 +21,7 @@ struct Heading {
23 GodotInstanceType instance_type; 21 GodotInstanceType instance_type;
24}; 22};
25 23
26Heading ParseTscnHeading(absl::string_view line) { 24Heading ParseTscnHeading(std::string_view line) {
27 std::string original_line(line); 25 std::string original_line(line);
28 Heading heading; 26 Heading heading;
29 27
diff --git a/tools/util/ids_yaml_format.cpp b/tools/util/ids_yaml_format.cpp index f72f60e..71bfd63 100644 --- a/tools/util/ids_yaml_format.cpp +++ b/tools/util/ids_yaml_format.cpp
@@ -56,6 +56,14 @@ IdMappings ReadIdsFromYaml(const std::string& filename) {
56 mastery_it.second.as<uint64_t>(); 56 mastery_it.second.as<uint64_t>();
57 } 57 }
58 } 58 }
59
60 if (room_it.second["keyholders"]) {
61 for (const auto& keyholder_it : room_it.second["keyholders"]) {
62 (*room_ids.mutable_keyholders())[keyholder_it.first
63 .as<std::string>()] =
64 keyholder_it.second.as<uint64_t>();
65 }
66 }
59 } 67 }
60 } 68 }
61 69
@@ -89,6 +97,20 @@ IdMappings ReadIdsFromYaml(const std::string& filename) {
89 } 97 }
90 } 98 }
91 99
100 if (document["progressives"]) {
101 for (const auto& prog_it : document["progressives"]) {
102 (*result.mutable_progressives())[prog_it.first.as<std::string>()] =
103 prog_it.second.as<uint64_t>();
104 }
105 }
106
107 if (document["door_groups"]) {
108 for (const auto& group_it : document["door_groups"]) {
109 (*result.mutable_door_groups())[group_it.first.as<std::string>()] =
110 group_it.second.as<uint64_t>();
111 }
112 }
113
92 return result; 114 return result;
93} 115}
94 116
@@ -117,6 +139,13 @@ void WriteIdsAsYaml(const IdMappings& ids, const std::string& filename) {
117 mastery_id; 139 mastery_id;
118 }); 140 });
119 141
142 OperateOnSortedMap(room_ids.keyholders(),
143 [&room_node](const std::string& keyholder_name,
144 uint64_t keyholder_id) {
145 room_node["keyholders"][keyholder_name] =
146 keyholder_id;
147 });
148
120 map_node["rooms"][room_name] = std::move(room_node); 149 map_node["rooms"][room_name] = std::move(room_node);
121 }); 150 });
122 151
@@ -144,6 +173,16 @@ void WriteIdsAsYaml(const IdMappings& ids, const std::string& filename) {
144 result["special"][special_name] = special_id; 173 result["special"][special_name] = special_id;
145 }); 174 });
146 175
176 OperateOnSortedMap(ids.progressives(),
177 [&result](const std::string& prog_name, uint64_t prog_id) {
178 result["progressives"][prog_name] = prog_id;
179 });
180
181 OperateOnSortedMap(ids.door_groups(), [&result](const std::string& group_name,
182 uint64_t group_id) {
183 result["door_groups"][group_name] = group_id;
184 });
185
147 std::ofstream output_stream(filename); 186 std::ofstream output_stream(filename);
148 output_stream << result << std::endl; 187 output_stream << result << std::endl;
149} 188}
diff --git a/tools/validator/CMakeLists.txt b/tools/validator/CMakeLists.txt index 967b890..1a8fd9c 100644 --- a/tools/validator/CMakeLists.txt +++ b/tools/validator/CMakeLists.txt
@@ -1,3 +1,4 @@
1find_package(fmt REQUIRED)
1find_package(Protobuf REQUIRED) 2find_package(Protobuf REQUIRED)
2 3
3add_executable(validator 4add_executable(validator
@@ -9,4 +10,4 @@ add_executable(validator
9set_property(TARGET validator PROPERTY CXX_STANDARD 20) 10set_property(TARGET validator PROPERTY CXX_STANDARD 20)
10set_property(TARGET validator PROPERTY CXX_STANDARD_REQUIRED ON) 11set_property(TARGET validator PROPERTY CXX_STANDARD_REQUIRED ON)
11target_include_directories(validator PUBLIC ${CMAKE_BINARY_DIR} ${CMAKE_SOURCE_DIR}/tools) 12target_include_directories(validator PUBLIC ${CMAKE_BINARY_DIR} ${CMAKE_SOURCE_DIR}/tools)
12target_link_libraries(validator PUBLIC protos util protobuf::libprotobuf) 13target_link_libraries(validator PUBLIC protos util fmt::fmt protobuf::libprotobuf)
diff --git a/tools/validator/human_processor.cpp b/tools/validator/human_processor.cpp index 5a7e78a..2c978bf 100644 --- a/tools/validator/human_processor.cpp +++ b/tools/validator/human_processor.cpp
@@ -1,5 +1,6 @@
1#include "human_processor.h" 1#include "human_processor.h"
2 2
3#include <fmt/core.h>
3#include <google/protobuf/message.h> 4#include <google/protobuf/message.h>
4#include <google/protobuf/text_format.h> 5#include <google/protobuf/text_format.h>
5 6
@@ -12,6 +13,7 @@
12#include <string> 13#include <string>
13 14
14#include "structs.h" 15#include "structs.h"
16#include "util/ids_yaml_format.h"
15 17
16namespace com::fourisland::lingo2_archipelago { 18namespace com::fourisland::lingo2_archipelago {
17namespace { 19namespace {
@@ -40,7 +42,9 @@ class HumanProcessor {
40 42
41 ProcessConnectionsFile(datadir_path / "connections.txtpb", std::nullopt); 43 ProcessConnectionsFile(datadir_path / "connections.txtpb", std::nullopt);
42 ProcessMaps(datadir_path); 44 ProcessMaps(datadir_path);
43 ProcessIdsFile(datadir_path / "ids.txtpb"); 45 ProcessProgressivesFile(datadir_path / "progressives.txtpb");
46 ProcessDoorGroupsFile(datadir_path / "door_groups.txtpb");
47 ProcessIdsFile(datadir_path / "ids.yaml");
44 } 48 }
45 49
46 private: 50 private:
@@ -93,7 +97,7 @@ class HumanProcessor {
93 room_info.definitions.push_back(h_room); 97 room_info.definitions.push_back(h_room);
94 98
95 for (const HumanPanel& h_panel : h_room.panels()) { 99 for (const HumanPanel& h_panel : h_room.panels()) {
96 ProcessPanel(h_panel, current_map_name, h_room.name()); 100 ProcessPanel(h_panel, current_map_name, h_room);
97 } 101 }
98 102
99 for (const HumanPainting& h_painting : h_room.paintings()) { 103 for (const HumanPainting& h_painting : h_room.paintings()) {
@@ -123,15 +127,14 @@ class HumanProcessor {
123 127
124 void ProcessPanel(const HumanPanel& h_panel, 128 void ProcessPanel(const HumanPanel& h_panel,
125 const std::string& current_map_name, 129 const std::string& current_map_name,
126 const std::string& current_room_name) { 130 const HumanRoom& h_room) {
127 PanelIdentifier panel_identifier; 131 PanelIdentifier panel_identifier;
128 panel_identifier.set_map(current_map_name); 132 panel_identifier.set_map(current_map_name);
129 panel_identifier.set_room(current_room_name); 133 panel_identifier.set_room(h_room.name());
130 panel_identifier.set_name(h_panel.name()); 134 panel_identifier.set_name(h_panel.name());
131 135
132 PanelInfo& panel_info = info_.panels[panel_identifier]; 136 PanelInfo& panel_info = info_.panels[panel_identifier];
133 panel_info.definitions.push_back(h_panel); 137 panel_info.definitions.push_back(h_panel);
134 panel_info.proxies[h_panel.answer()].definitions.push_back(Proxy());
135 138
136 MapInfo& map_info = info_.maps[current_map_name]; 139 MapInfo& map_info = info_.maps[current_map_name];
137 map_info.game_nodes[h_panel.path()].uses++; 140 map_info.game_nodes[h_panel.path()].uses++;
@@ -156,6 +159,24 @@ class HumanProcessor {
156 RoomInfo& required_room_info = info_.rooms[required_room_identifier]; 159 RoomInfo& required_room_info = info_.rooms[required_room_identifier];
157 required_room_info.panels_referenced_by.push_back(panel_identifier); 160 required_room_info.panels_referenced_by.push_back(panel_identifier);
158 } 161 }
162
163 std::string map_area_name = current_map_name;
164 if (h_room.has_panel_display_name()) {
165 map_area_name =
166 fmt::format("{} ({})", current_map_name, h_room.panel_display_name());
167 }
168
169 panel_info.map_area_name = map_area_name;
170
171 std::string panelsanity_name;
172 if (h_panel.has_display_name()) {
173 panelsanity_name =
174 fmt::format("{} - {}", map_area_name, h_panel.display_name());
175 } else {
176 panelsanity_name = fmt::format("{} - {}", map_area_name, h_panel.name());
177 }
178 info_.panel_names[panelsanity_name].panels_used_by.push_back(
179 panel_identifier);
159 } 180 }
160 181
161 void ProcessPainting(const HumanPainting& h_painting, 182 void ProcessPainting(const HumanPainting& h_painting,
@@ -337,6 +358,11 @@ class HumanProcessor {
337 DoorInfo& other_door_info = info_.doors[complete_door_identifier]; 358 DoorInfo& other_door_info = info_.doors[complete_door_identifier];
338 other_door_info.doors_referenced_by.push_back(door_identifier); 359 other_door_info.doors_referenced_by.push_back(door_identifier);
339 } 360 }
361
362 for (const std::string& ei : h_door.endings()) {
363 EndingInfo& ending_info = info_.endings[ei];
364 ending_info.doors_referenced_by.push_back(door_identifier);
365 }
340 } 366 }
341 367
342 void ProcessConnectionsFile(std::filesystem::path path, 368 void ProcessConnectionsFile(std::filesystem::path path,
@@ -368,7 +394,9 @@ class HumanProcessor {
368 } 394 }
369 } else if (human_connection.has_from()) { 395 } else if (human_connection.has_from()) {
370 ProcessSingleConnection(human_connection, human_connection.from(), 396 ProcessSingleConnection(human_connection, human_connection.from(),
371 current_map_name); 397 current_map_name,
398 /*is_target=*/!human_connection.oneway() &&
399 !human_connection.bypass_target_door());
372 } 400 }
373 401
374 if (human_connection.has_to_room()) { 402 if (human_connection.has_to_room()) {
@@ -384,8 +412,9 @@ class HumanProcessor {
384 std::cout << "A global connection used to_room." << std::endl; 412 std::cout << "A global connection used to_room." << std::endl;
385 } 413 }
386 } else if (human_connection.has_to()) { 414 } else if (human_connection.has_to()) {
387 ProcessSingleConnection(human_connection, human_connection.to(), 415 ProcessSingleConnection(
388 current_map_name); 416 human_connection, human_connection.to(), current_map_name,
417 /*is_target=*/!human_connection.bypass_target_door());
389 } 418 }
390 419
391 if (human_connection.has_door()) { 420 if (human_connection.has_door()) {
@@ -406,7 +435,7 @@ class HumanProcessor {
406 void ProcessSingleConnection( 435 void ProcessSingleConnection(
407 const HumanConnection& human_connection, 436 const HumanConnection& human_connection,
408 const HumanConnection::Endpoint& endpoint, 437 const HumanConnection::Endpoint& endpoint,
409 const std::optional<std::string>& current_map_name) { 438 const std::optional<std::string>& current_map_name, bool is_target) {
410 if (endpoint.has_room()) { 439 if (endpoint.has_room()) {
411 auto room_identifier = 440 auto room_identifier =
412 GetCompleteRoomIdentifier(endpoint.room(), current_map_name); 441 GetCompleteRoomIdentifier(endpoint.room(), current_map_name);
@@ -425,6 +454,11 @@ class HumanProcessor {
425 if (painting_identifier) { 454 if (painting_identifier) {
426 PaintingInfo& painting_info = info_.paintings[*painting_identifier]; 455 PaintingInfo& painting_info = info_.paintings[*painting_identifier];
427 painting_info.connections_referenced_by.push_back(human_connection); 456 painting_info.connections_referenced_by.push_back(human_connection);
457
458 if (is_target) {
459 painting_info.target_connections_referenced_by.push_back(
460 human_connection);
461 }
428 } else { 462 } else {
429 // Not sure where else to store this right now. 463 // Not sure where else to store this right now.
430 std::cout 464 std::cout
@@ -437,6 +471,11 @@ class HumanProcessor {
437 if (port_identifier) { 471 if (port_identifier) {
438 PortInfo& port_info = info_.ports[*port_identifier]; 472 PortInfo& port_info = info_.ports[*port_identifier];
439 port_info.connections_referenced_by.push_back(human_connection); 473 port_info.connections_referenced_by.push_back(human_connection);
474
475 if (is_target) {
476 port_info.target_connections_referenced_by.push_back(
477 human_connection);
478 }
440 } else { 479 } else {
441 // Not sure where else to store this right now. 480 // Not sure where else to store this right now.
442 std::cout 481 std::cout
@@ -454,12 +493,137 @@ class HumanProcessor {
454 panel_info.proxies[endpoint.panel().answer()] 493 panel_info.proxies[endpoint.panel().answer()]
455 .connections_referenced_by.push_back(human_connection); 494 .connections_referenced_by.push_back(human_connection);
456 } 495 }
496
497 if (is_target) {
498 panel_info.target_connections_referenced_by.push_back(
499 human_connection);
500 }
501 }
502 }
503 }
504
505 void ProcessProgressivesFile(std::filesystem::path path) {
506 if (!std::filesystem::exists(path)) {
507 return;
508 }
509
510 auto h_progs = ReadMessageFromFile<HumanProgressives>(path.string());
511
512 for (const HumanProgressive& h_prog : h_progs.progressives()) {
513 ProcessProgressive(h_prog);
514 }
515 }
516
517 void ProcessProgressive(const HumanProgressive& h_prog) {
518 ProgressiveInfo& prog_info = info_.progressives[h_prog.name()];
519 prog_info.definitions.push_back(h_prog);
520
521 for (const DoorIdentifier& di : h_prog.doors()) {
522 if (!di.has_map()) {
523 prog_info.malformed_doors.push_back(di);
524 continue;
457 } 525 }
526
527 DoorInfo& door_info = info_.doors[di];
528 door_info.progressives_referenced_by.push_back(h_prog.name());
529 }
530 }
531
532 void ProcessDoorGroupsFile(std::filesystem::path path) {
533 if (!std::filesystem::exists(path)) {
534 return;
535 }
536
537 auto h_groups = ReadMessageFromFile<HumanDoorGroups>(path.string());
538
539 for (const HumanDoorGroup& h_group : h_groups.door_groups()) {
540 ProcessDoorGroup(h_group);
541 }
542 }
543
544 void ProcessDoorGroup(const HumanDoorGroup& h_group) {
545 DoorGroupInfo& group_info = info_.door_groups[h_group.name()];
546 group_info.definitions.push_back(h_group);
547
548 for (const DoorIdentifier& di : h_group.doors()) {
549 if (!di.has_map()) {
550 group_info.malformed_doors.push_back(di);
551 continue;
552 }
553
554 DoorInfo& door_info = info_.doors[di];
555 door_info.door_groups_referenced_by.push_back(h_group.name());
458 } 556 }
459 } 557 }
460 558
461 void ProcessIdsFile(std::filesystem::path path) { 559 void ProcessIdsFile(std::filesystem::path path) {
462 // Ignore this for now. 560 auto ids = ReadIdsFromYaml(path.string());
561
562 DoorIdentifier di;
563 PanelIdentifier pi;
564 KeyholderIdentifier ki;
565
566 for (const auto& [map_name, map] : ids.maps()) {
567 di.set_map(map_name);
568 pi.set_map(map_name);
569 ki.set_map(map_name);
570
571 for (const auto& [door_name, ap_id] : map.doors()) {
572 di.set_name(door_name);
573
574 DoorInfo& door_info = info_.doors[di];
575 door_info.has_id = true;
576 }
577
578 for (const auto& [room_name, room] : map.rooms()) {
579 pi.set_room(room_name);
580 ki.set_room(room_name);
581
582 for (const auto& [panel_name, ap_id] : room.panels()) {
583 pi.set_name(panel_name);
584
585 PanelInfo& panel_info = info_.panels[pi];
586 panel_info.has_id = true;
587 }
588
589 for (const auto& [mastery_name, ap_id] : room.masteries()) {
590 // TODO: Mastery
591 }
592
593 for (const auto& [keyholder_name, ap_id] : room.keyholders()) {
594 ki.set_name(keyholder_name);
595
596 KeyholderInfo& keyholder_info = info_.keyholders[ki];
597 keyholder_info.has_id = true;
598 }
599 }
600 }
601
602 for (const auto& [tag, id] : ids.special()) {
603 // TODO: Specials
604 }
605
606 for (const auto& [letter_name, ap_id] : ids.letters()) {
607 LetterIdentifier li =
608 std::make_tuple(letter_name[0], letter_name[1] == '2');
609 LetterInfo& letter_info = info_.letters[li];
610 letter_info.has_id = true;
611 }
612
613 for (const auto& [ending_name, ap_id] : ids.endings()) {
614 EndingInfo& ending_info = info_.endings[ending_name];
615 ending_info.has_id = true;
616 }
617
618 for (const auto& [prog_name, ap_id] : ids.progressives()) {
619 ProgressiveInfo& prog_info = info_.progressives[prog_name];
620 prog_info.has_id = true;
621 }
622
623 for (const auto& [group_name, ap_id] : ids.door_groups()) {
624 DoorGroupInfo& group_info = info_.door_groups[group_name];
625 group_info.has_id = true;
626 }
463 } 627 }
464 628
465 std::string mapdir_; 629 std::string mapdir_;
diff --git a/tools/validator/structs.h b/tools/validator/structs.h index f7d9dc1..d1d45f2 100644 --- a/tools/validator/structs.h +++ b/tools/validator/structs.h
@@ -39,12 +39,15 @@ struct RoomInfo {
39 39
40struct DoorInfo { 40struct DoorInfo {
41 std::vector<HumanDoor> definitions; 41 std::vector<HumanDoor> definitions;
42 bool has_id = false;
42 43
43 std::vector<HumanConnection> connections_referenced_by; 44 std::vector<HumanConnection> connections_referenced_by;
44 std::vector<DoorIdentifier> doors_referenced_by; 45 std::vector<DoorIdentifier> doors_referenced_by;
45 std::vector<PanelIdentifier> panels_referenced_by; 46 std::vector<PanelIdentifier> panels_referenced_by;
46 std::vector<PaintingIdentifier> paintings_referenced_by; 47 std::vector<PaintingIdentifier> paintings_referenced_by;
47 std::vector<PortIdentifier> ports_referenced_by; 48 std::vector<PortIdentifier> ports_referenced_by;
49 std::vector<std::string> progressives_referenced_by;
50 std::vector<std::string> door_groups_referenced_by;
48 51
49 MalformedIdentifiers malformed_identifiers; 52 MalformedIdentifiers malformed_identifiers;
50}; 53};
@@ -53,12 +56,14 @@ struct PortInfo {
53 std::vector<HumanPort> definitions; 56 std::vector<HumanPort> definitions;
54 57
55 std::vector<HumanConnection> connections_referenced_by; 58 std::vector<HumanConnection> connections_referenced_by;
59 std::vector<HumanConnection> target_connections_referenced_by;
56}; 60};
57 61
58struct PaintingInfo { 62struct PaintingInfo {
59 std::vector<HumanPainting> definitions; 63 std::vector<HumanPainting> definitions;
60 64
61 std::vector<HumanConnection> connections_referenced_by; 65 std::vector<HumanConnection> connections_referenced_by;
66 std::vector<HumanConnection> target_connections_referenced_by;
62 std::vector<DoorIdentifier> doors_referenced_by; 67 std::vector<DoorIdentifier> doors_referenced_by;
63}; 68};
64 69
@@ -71,8 +76,12 @@ struct ProxyInfo {
71 76
72struct PanelInfo { 77struct PanelInfo {
73 std::vector<HumanPanel> definitions; 78 std::vector<HumanPanel> definitions;
79 bool has_id = false;
80
81 std::string map_area_name;
74 82
75 std::vector<HumanConnection> connections_referenced_by; 83 std::vector<HumanConnection> connections_referenced_by;
84 std::vector<HumanConnection> target_connections_referenced_by;
76 std::vector<DoorIdentifier> doors_referenced_by; 85 std::vector<DoorIdentifier> doors_referenced_by;
77 86
78 std::map<std::string, ProxyInfo> proxies; 87 std::map<std::string, ProxyInfo> proxies;
@@ -80,6 +89,7 @@ struct PanelInfo {
80 89
81struct KeyholderInfo { 90struct KeyholderInfo {
82 std::vector<HumanKeyholder> definitions; 91 std::vector<HumanKeyholder> definitions;
92 bool has_id = false;
83 93
84 std::vector<DoorIdentifier> doors_referenced_by; 94 std::vector<DoorIdentifier> doors_referenced_by;
85}; 95};
@@ -88,10 +98,32 @@ using LetterIdentifier = std::tuple<char, bool>;
88 98
89struct LetterInfo { 99struct LetterInfo {
90 std::vector<RoomIdentifier> defined_in; 100 std::vector<RoomIdentifier> defined_in;
101 bool has_id = false;
91}; 102};
92 103
93struct EndingInfo { 104struct EndingInfo {
94 std::vector<RoomIdentifier> defined_in; 105 std::vector<RoomIdentifier> defined_in;
106 bool has_id = false;
107
108 std::vector<DoorIdentifier> doors_referenced_by;
109};
110
111struct PanelNameInfo {
112 std::vector<PanelIdentifier> panels_used_by;
113};
114
115struct ProgressiveInfo {
116 std::vector<HumanProgressive> definitions;
117 bool has_id = false;
118
119 std::vector<DoorIdentifier> malformed_doors;
120};
121
122struct DoorGroupInfo {
123 std::vector<HumanDoorGroup> definitions;
124 bool has_id = false;
125
126 std::vector<DoorIdentifier> malformed_doors;
95}; 127};
96 128
97struct CollectedInfo { 129struct CollectedInfo {
@@ -105,6 +137,9 @@ struct CollectedInfo {
105 keyholders; 137 keyholders;
106 std::map<LetterIdentifier, LetterInfo> letters; 138 std::map<LetterIdentifier, LetterInfo> letters;
107 std::map<std::string, EndingInfo> endings; 139 std::map<std::string, EndingInfo> endings;
140 std::map<std::string, PanelNameInfo> panel_names;
141 std::map<std::string, ProgressiveInfo> progressives;
142 std::map<std::string, DoorGroupInfo> door_groups;
108}; 143};
109 144
110} // namespace com::fourisland::lingo2_archipelago 145} // namespace com::fourisland::lingo2_archipelago
diff --git a/tools/validator/validator.cpp b/tools/validator/validator.cpp index b33f602..93efdc6 100644 --- a/tools/validator/validator.cpp +++ b/tools/validator/validator.cpp
@@ -9,282 +9,557 @@
9namespace com::fourisland::lingo2_archipelago { 9namespace com::fourisland::lingo2_archipelago {
10namespace { 10namespace {
11 11
12void ValidateMap(const std::string& map_name, const MapInfo& map_info) { 12class Validator {
13 for (const auto& [node_path, node_info] : map_info.game_nodes) { 13 public:
14 if (node_info.uses > 1) { 14 explicit Validator(const CollectedInfo& info) : info_(info) {}
15 std::cout << "Map " << map_name << " node " << node_path
16 << " is used in multiple places." << std::endl;
17 } else if (node_info.uses == 0) {
18 std::cout << "Map " << map_name << " node " << node_path
19 << " is not used." << std::endl;
20 }
21 15
22 if (!node_info.defined) { 16 void Validate() const {
23 std::cout << "Map " << map_name << " node " << node_path 17 for (const auto& [map_name, map_info] : info_.maps) {
24 << " is not defined in the game file." << std::endl; 18 ValidateMap(map_name, map_info);
19 }
20 for (const auto& [room_identifier, room_info] : info_.rooms) {
21 ValidateRoom(room_identifier, room_info);
22 }
23 for (const auto& [door_identifier, door_info] : info_.doors) {
24 ValidateDoor(door_identifier, door_info);
25 }
26 for (const auto& [port_identifier, port_info] : info_.ports) {
27 ValidatePort(port_identifier, port_info);
28 }
29 for (const auto& [painting_identifier, painting_info] : info_.paintings) {
30 ValidatePainting(painting_identifier, painting_info);
31 }
32 for (const auto& [panel_identifier, panel_info] : info_.panels) {
33 ValidatePanel(panel_identifier, panel_info);
34 }
35 for (const auto& [keyholder_identifier, keyholder_info] :
36 info_.keyholders) {
37 ValidateKeyholder(keyholder_identifier, keyholder_info);
38 }
39 for (const auto& [letter_identifier, letter_info] : info_.letters) {
40 ValidateLetter(letter_identifier, letter_info);
41 }
42 for (const auto& [ending_name, ending_info] : info_.endings) {
43 ValidateEnding(ending_name, ending_info);
44 }
45 for (const auto& [panel_name, panel_info] : info_.panel_names) {
46 ValidatePanelName(panel_name, panel_info);
47 }
48 for (const auto& [prog_name, prog_info] : info_.progressives) {
49 ValidateProgressive(prog_name, prog_info);
50 }
51 for (const auto& [group_name, group_info] : info_.door_groups) {
52 ValidateDoorGroup(group_name, group_info);
25 } 53 }
26 } 54 }
27}
28 55
29void ValidateRoom(const RoomIdentifier& room_identifier, 56 private:
30 const RoomInfo& room_info) { 57 void ValidateMap(const std::string& map_name, const MapInfo& map_info) const {
31 if (room_info.definitions.empty()) { 58 for (const auto& [node_path, node_info] : map_info.game_nodes) {
32 std::cout << "Room " << room_identifier.ShortDebugString() 59 if (node_info.uses > 1) {
33 << " has no definition, but was referenced:" << std::endl; 60 std::cout << "Map " << map_name << " node " << node_path
61 << " is used in multiple places." << std::endl;
62 } else if (node_info.uses == 0) {
63 std::cout << "Map " << map_name << " node " << node_path
64 << " is not used." << std::endl;
65 }
34 66
35 for (const DoorIdentifier& door_identifier : 67 if (!node_info.defined) {
36 room_info.doors_referenced_by) { 68 std::cout << "Map " << map_name << " node " << node_path
37 std::cout << " DOOR " << door_identifier.ShortDebugString() 69 << " is not defined in the game file." << std::endl;
38 << std::endl; 70 }
39 } 71 }
72 }
40 73
41 for (const PanelIdentifier& panel_identifier : 74 void ValidateRoom(const RoomIdentifier& room_identifier,
42 room_info.panels_referenced_by) { 75 const RoomInfo& room_info) const {
43 std::cout << " PANEL " << panel_identifier.ShortDebugString() 76 if (room_info.definitions.empty()) {
44 << std::endl; 77 std::cout << "Room " << room_identifier.ShortDebugString()
45 } 78 << " has no definition, but was referenced:" << std::endl;
46 79
47 for (const HumanConnection& connection : 80 for (const DoorIdentifier& door_identifier :
48 room_info.connections_referenced_by) { 81 room_info.doors_referenced_by) {
49 std::cout << " CONNECTION " << connection.ShortDebugString() 82 std::cout << " DOOR " << door_identifier.ShortDebugString()
50 << std::endl; 83 << std::endl;
84 }
85
86 for (const PanelIdentifier& panel_identifier :
87 room_info.panels_referenced_by) {
88 std::cout << " PANEL " << panel_identifier.ShortDebugString()
89 << std::endl;
90 }
91
92 for (const HumanConnection& connection :
93 room_info.connections_referenced_by) {
94 std::cout << " CONNECTION " << connection.ShortDebugString()
95 << std::endl;
96 }
97 } else if (room_info.definitions.size() > 1) {
98 std::cout << "Room " << room_identifier.ShortDebugString()
99 << " was defined multiple times." << std::endl;
51 } 100 }
52 } else if (room_info.definitions.size() > 1) {
53 std::cout << "Room " << room_identifier.ShortDebugString()
54 << " was defined multiple times." << std::endl;
55 } 101 }
56}
57 102
58void ValidateDoor(const DoorIdentifier& door_identifier, 103 bool DoesDoorNeedLocationName(const HumanDoor& h_door,
59 const DoorInfo& door_info) { 104 const std::string& map_name) const {
60 if (door_info.definitions.empty()) { 105 if (h_door.type() != DoorType::STANDARD) {
61 std::cout << "Door " << door_identifier.ShortDebugString() 106 return false;
62 << " has no definition, but was referenced:" << std::endl;
63
64 for (const DoorIdentifier& other_door_identifier :
65 door_info.doors_referenced_by) {
66 std::cout << " DOOR " << other_door_identifier.ShortDebugString()
67 << std::endl;
68 } 107 }
69 108
70 for (const PanelIdentifier& panel_identifier : 109 if (h_door.keyholders_size() > 0 || h_door.endings_size() > 0 ||
71 door_info.panels_referenced_by) { 110 h_door.complete_at() > 0) {
72 std::cout << " PANEL " << panel_identifier.ShortDebugString() 111 return true;
73 << std::endl;
74 } 112 }
75 113
76 for (const PaintingIdentifier& painting_identifier : 114 if (h_door.panels_size() > 4) {
77 door_info.paintings_referenced_by) { 115 return true;
78 std::cout << " PAINTING " << painting_identifier.ShortDebugString()
79 << std::endl;
80 } 116 }
81 117
82 for (const PortIdentifier& port_identifier : 118 std::set<std::string> map_areas;
83 door_info.ports_referenced_by) { 119 for (const PanelIdentifier& pi : h_door.panels()) {
84 std::cout << " PORT " << port_identifier.ShortDebugString() 120 auto full_pi =
85 << std::endl; 121 GetCompletePanelIdentifierWithoutAnswer(pi, map_name, std::nullopt);
122 if (full_pi) {
123 auto panel_info_it = info_.panels.find(*full_pi);
124 if (panel_info_it != info_.panels.end()) {
125 const PanelInfo& panel_info = panel_info_it->second;
126
127 map_areas.insert(panel_info.map_area_name);
128 }
129 }
86 } 130 }
87 131
88 for (const HumanConnection& connection : 132 if (map_areas.size() > 1) {
89 door_info.connections_referenced_by) { 133 return true;
90 std::cout << " CONNECTION " << connection.ShortDebugString()
91 << std::endl;
92 } 134 }
93 } else if (door_info.definitions.size() > 1) { 135
94 std::cout << "Door " << door_identifier.ShortDebugString() 136 return false;
95 << " was defined multiple times." << std::endl;
96 } 137 }
97 138
98 if (door_info.malformed_identifiers.HasAny()) { 139 void ValidateDoor(const DoorIdentifier& door_identifier,
99 std::cout << "Door " << door_identifier.ShortDebugString() 140 const DoorInfo& door_info) const {
100 << " has malformed identifiers:" << std::endl; 141 if (door_info.definitions.empty()) {
142 std::cout << "Door " << door_identifier.ShortDebugString()
143 << " has no definition, but was referenced:" << std::endl;
101 144
102 for (const PaintingIdentifier& painting_identifier : 145 for (const DoorIdentifier& other_door_identifier :
103 door_info.malformed_identifiers.paintings) { 146 door_info.doors_referenced_by) {
104 std::cout << " PAINTING " << painting_identifier.ShortDebugString() 147 std::cout << " DOOR " << other_door_identifier.ShortDebugString()
105 << std::endl; 148 << std::endl;
106 } 149 }
107 150
108 for (const PanelIdentifier& panel_identifier : 151 for (const PanelIdentifier& panel_identifier :
109 door_info.malformed_identifiers.panels) { 152 door_info.panels_referenced_by) {
110 std::cout << " PANEL " << panel_identifier.ShortDebugString() 153 std::cout << " PANEL " << panel_identifier.ShortDebugString()
111 << std::endl; 154 << std::endl;
155 }
156
157 for (const PaintingIdentifier& painting_identifier :
158 door_info.paintings_referenced_by) {
159 std::cout << " PAINTING " << painting_identifier.ShortDebugString()
160 << std::endl;
161 }
162
163 for (const PortIdentifier& port_identifier :
164 door_info.ports_referenced_by) {
165 std::cout << " PORT " << port_identifier.ShortDebugString()
166 << std::endl;
167 }
168
169 for (const HumanConnection& connection :
170 door_info.connections_referenced_by) {
171 std::cout << " CONNECTION " << connection.ShortDebugString()
172 << std::endl;
173 }
174
175 for (const std::string& prog_name :
176 door_info.progressives_referenced_by) {
177 std::cout << " PROGRESSIVE " << prog_name << std::endl;
178 }
179
180 for (const std::string& group_name :
181 door_info.door_groups_referenced_by) {
182 std::cout << " DOOR GROUP " << group_name << std::endl;
183 }
184
185 if (door_info.has_id) {
186 std::cout << " An AP ID is present." << std::endl;
187 }
188 } else if (door_info.definitions.size() > 1) {
189 std::cout << "Door " << door_identifier.ShortDebugString()
190 << " was defined multiple times." << std::endl;
112 } 191 }
113 192
114 for (const KeyholderIdentifier& keyholder_identifier : 193 if (door_info.malformed_identifiers.HasAny()) {
115 door_info.malformed_identifiers.keyholders) { 194 std::cout << "Door " << door_identifier.ShortDebugString()
116 std::cout << " KEYHOLDER " << keyholder_identifier.ShortDebugString() 195 << " has malformed identifiers:" << std::endl;
117 << std::endl; 196
197 for (const PaintingIdentifier& painting_identifier :
198 door_info.malformed_identifiers.paintings) {
199 std::cout << " PAINTING " << painting_identifier.ShortDebugString()
200 << std::endl;
201 }
202
203 for (const PanelIdentifier& panel_identifier :
204 door_info.malformed_identifiers.panels) {
205 std::cout << " PANEL " << panel_identifier.ShortDebugString()
206 << std::endl;
207 }
208
209 for (const KeyholderIdentifier& keyholder_identifier :
210 door_info.malformed_identifiers.keyholders) {
211 std::cout << " KEYHOLDER " << keyholder_identifier.ShortDebugString()
212 << std::endl;
213 }
118 } 214 }
119 }
120}
121 215
122void ValidatePort(const PortIdentifier& port_identifier, 216 for (const HumanDoor& h_door : door_info.definitions) {
123 const PortInfo& port_info) { 217 if (DoesDoorNeedLocationName(h_door, door_identifier.map()) &&
124 if (port_info.definitions.empty()) { 218 !h_door.has_location_name()) {
125 std::cout << "Port " << port_identifier.ShortDebugString() 219 std::cout << "Door " << door_identifier.ShortDebugString()
126 << " has no definition, but was referenced:" << std::endl; 220 << " needs an explicit location name." << std::endl;
221 }
127 222
128 for (const HumanConnection& connection : 223 if (h_door.double_letters() &&
129 port_info.connections_referenced_by) { 224 (h_door.type() == DoorType::STANDARD ||
130 std::cout << " CONNECTION " << connection.ShortDebugString() 225 h_door.type() == DoorType::LOCATION_ONLY ||
131 << std::endl; 226 h_door.type() == DoorType::GRAVESTONE)) {
227 std::cout << "Door " << door_identifier.ShortDebugString()
228 << " is a location that depends on double_letters."
229 << std::endl;
230 }
231
232 bool needs_id = (h_door.type() != DoorType::EVENT);
233 if (door_info.has_id != needs_id) {
234 if (needs_id) {
235 std::cout << "Door " << door_identifier.ShortDebugString()
236 << " is missing an AP ID." << std::endl;
237 } else {
238 std::cout << "Door " << door_identifier.ShortDebugString()
239 << " should not have an AP ID." << std::endl;
240 }
241 }
132 } 242 }
133 } else if (port_info.definitions.size() > 1) {
134 std::cout << "Port " << port_identifier.ShortDebugString()
135 << " was defined multiple times." << std::endl;
136 } 243 }
137}
138 244
139void ValidatePainting(const PaintingIdentifier& painting_identifier, 245 void ValidatePort(const PortIdentifier& port_identifier,
140 const PaintingInfo& painting_info) { 246 const PortInfo& port_info) const {
141 if (painting_info.definitions.empty()) { 247 if (port_info.definitions.empty()) {
142 std::cout << "Painting " << painting_identifier.ShortDebugString() 248 std::cout << "Port " << port_identifier.ShortDebugString()
143 << " has no definition, but was referenced:" << std::endl; 249 << " has no definition, but was referenced:" << std::endl;
144 250
145 for (const DoorIdentifier& door_identifier : 251 for (const HumanConnection& connection :
146 painting_info.doors_referenced_by) { 252 port_info.connections_referenced_by) {
147 std::cout << " DOOR " << door_identifier.ShortDebugString() 253 std::cout << " CONNECTION " << connection.ShortDebugString()
148 << std::endl; 254 << std::endl;
255 }
256 } else if (port_info.definitions.size() > 1) {
257 std::cout << "Port " << port_identifier.ShortDebugString()
258 << " was defined multiple times." << std::endl;
149 } 259 }
150 260
151 for (const HumanConnection& connection : 261 if (!port_info.target_connections_referenced_by.empty()) {
152 painting_info.connections_referenced_by) { 262 for (const HumanPort& port : port_info.definitions) {
153 std::cout << " CONNECTION " << connection.ShortDebugString() 263 if (port.has_required_door()) {
154 << std::endl; 264 std::cout << "Port " << port_identifier.ShortDebugString()
265 << " has a required door but is the target of a connection:"
266 << std::endl;
267
268 for (const HumanConnection& connection :
269 port_info.target_connections_referenced_by) {
270 std::cout << " CONNECTION " << connection.ShortDebugString()
271 << std::endl;
272 }
273 }
274 }
155 } 275 }
156 } else if (painting_info.definitions.size() > 1) {
157 std::cout << "Painting " << painting_identifier.ShortDebugString()
158 << " was defined multiple times." << std::endl;
159 }
160}
161 276
162void ValidatePanel(const PanelIdentifier& panel_identifier, 277 for (const HumanPort& port : port_info.definitions) {
163 const PanelInfo& panel_info) { 278 if (!port.no_shuffle()) {
164 if (panel_identifier.name().empty()) { 279 if (!port.has_destination()) {
165 std::cout << "Panel " << panel_identifier.ShortDebugString() 280 std::cout << "Port " << port_identifier.ShortDebugString()
166 << " has no name." << std::endl; 281 << " is shuffleable and missing a destination."
282 << std::endl;
283 }
284 if (!port.has_rotation()) {
285 std::cout << "Port " << port_identifier.ShortDebugString()
286 << " is shuffleable and missing a rotation."
287 << std::endl;
288 }
289 }
290 }
167 } 291 }
168 292
169 if (panel_info.definitions.empty()) { 293 void ValidatePainting(const PaintingIdentifier& painting_identifier,
170 std::cout << "Panel " << panel_identifier.ShortDebugString() 294 const PaintingInfo& painting_info) const {
171 << " has no definition, but was referenced:" << std::endl; 295 if (painting_info.definitions.empty()) {
296 std::cout << "Painting " << painting_identifier.ShortDebugString()
297 << " has no definition, but was referenced:" << std::endl;
172 298
173 for (const DoorIdentifier& door_identifier : 299 for (const DoorIdentifier& door_identifier :
174 panel_info.doors_referenced_by) { 300 painting_info.doors_referenced_by) {
175 std::cout << " DOOR " << door_identifier.ShortDebugString() 301 std::cout << " DOOR " << door_identifier.ShortDebugString()
176 << std::endl; 302 << std::endl;
303 }
304
305 for (const HumanConnection& connection :
306 painting_info.connections_referenced_by) {
307 std::cout << " CONNECTION " << connection.ShortDebugString()
308 << std::endl;
309 }
310 } else if (painting_info.definitions.size() > 1) {
311 std::cout << "Painting " << painting_identifier.ShortDebugString()
312 << " was defined multiple times." << std::endl;
177 } 313 }
178 314
179 for (const HumanConnection& connection : 315 if (!painting_info.target_connections_referenced_by.empty()) {
180 panel_info.connections_referenced_by) { 316 for (const HumanPainting& painting : painting_info.definitions) {
181 std::cout << " CONNECTION " << connection.ShortDebugString() 317 if (painting.has_required_door()) {
182 << std::endl; 318 std::cout << "Painting " << painting_identifier.ShortDebugString()
319 << " has a required door but is the target of a connection:"
320 << std::endl;
321
322 for (const HumanConnection& connection :
323 painting_info.target_connections_referenced_by) {
324 std::cout << " CONNECTION " << connection.ShortDebugString()
325 << std::endl;
326 }
327 }
328 }
183 } 329 }
184 } else if (panel_info.definitions.size() > 1) {
185 std::cout << "Panel " << panel_identifier.ShortDebugString()
186 << " was defined multiple times." << std::endl;
187 } 330 }
188 331
189 for (const auto& [answer, proxy_info] : panel_info.proxies) { 332 void ValidatePanel(const PanelIdentifier& panel_identifier,
190 if (proxy_info.definitions.empty()) { 333 const PanelInfo& panel_info) const {
334 if (panel_identifier.name().empty()) {
191 std::cout << "Panel " << panel_identifier.ShortDebugString() 335 std::cout << "Panel " << panel_identifier.ShortDebugString()
192 << " with answer \"" << answer 336 << " has no name." << std::endl;
193 << "\" has no definition, but was referenced:" << std::endl; 337 }
338
339 if (panel_info.definitions.empty()) {
340 std::cout << "Panel " << panel_identifier.ShortDebugString()
341 << " has no definition, but was referenced:" << std::endl;
194 342
195 for (const DoorIdentifier& door_identifier : 343 for (const DoorIdentifier& door_identifier :
196 proxy_info.doors_referenced_by) { 344 panel_info.doors_referenced_by) {
197 std::cout << " DOOR " << door_identifier.ShortDebugString() 345 std::cout << " DOOR " << door_identifier.ShortDebugString()
198 << std::endl; 346 << std::endl;
199 } 347 }
200 348
201 for (const HumanConnection& connection : 349 for (const HumanConnection& connection :
202 proxy_info.connections_referenced_by) { 350 panel_info.connections_referenced_by) {
203 std::cout << " CONNECTION " << connection.ShortDebugString() 351 std::cout << " CONNECTION " << connection.ShortDebugString()
204 << std::endl; 352 << std::endl;
205 } 353 }
206 } else if (proxy_info.definitions.size() > 1) { 354
355 if (panel_info.has_id) {
356 std::cout << " An AP ID is present." << std::endl;
357 }
358 } else if (panel_info.definitions.size() > 1) {
207 std::cout << "Panel " << panel_identifier.ShortDebugString() 359 std::cout << "Panel " << panel_identifier.ShortDebugString()
208 << " with answer \"" << answer 360 << " was defined multiple times." << std::endl;
209 << "\" was defined multiple times." << std::endl; 361 }
362
363 for (const auto& [answer, proxy_info] : panel_info.proxies) {
364 if (proxy_info.definitions.empty()) {
365 std::cout << "Panel " << panel_identifier.ShortDebugString()
366 << " with answer \"" << answer
367 << "\" has no definition, but was referenced:" << std::endl;
368
369 for (const DoorIdentifier& door_identifier :
370 proxy_info.doors_referenced_by) {
371 std::cout << " DOOR " << door_identifier.ShortDebugString()
372 << std::endl;
373 }
374
375 for (const HumanConnection& connection :
376 proxy_info.connections_referenced_by) {
377 std::cout << " CONNECTION " << connection.ShortDebugString()
378 << std::endl;
379 }
380 } else if (proxy_info.definitions.size() > 1) {
381 std::cout << "Panel " << panel_identifier.ShortDebugString()
382 << " with answer \"" << answer
383 << "\" was defined multiple times." << std::endl;
384 }
210 } 385 }
211 }
212}
213 386
214void ValidateKeyholder(const KeyholderIdentifier& keyholder_identifier, 387 if (!panel_info.has_id) {
215 const KeyholderInfo& keyholder_info) { 388 std::cout << "Panel " << panel_identifier.ShortDebugString()
216 if (keyholder_info.definitions.empty()) { 389 << " is missing an AP ID." << std::endl;
217 std::cout << "Keyholder " << keyholder_identifier.ShortDebugString() 390 }
218 << " has no definition, but was referenced:" << std::endl;
219 391
220 for (const DoorIdentifier& door_identifier : 392 if (!panel_info.target_connections_referenced_by.empty()) {
221 keyholder_info.doors_referenced_by) { 393 for (const HumanPanel& panel : panel_info.definitions) {
222 std::cout << " DOOR " << door_identifier.ShortDebugString() 394 if (panel.has_required_door()) {
223 << std::endl; 395 std::cout << "Panel " << panel_identifier.ShortDebugString()
396 << " has a required door but is the target of a connection:"
397 << std::endl;
398
399 for (const HumanConnection& connection :
400 panel_info.target_connections_referenced_by) {
401 std::cout << " CONNECTION " << connection.ShortDebugString()
402 << std::endl;
403 }
404 }
405 }
224 } 406 }
225 } else if (keyholder_info.definitions.size() > 1) {
226 std::cout << "Keyholder " << keyholder_identifier.ShortDebugString()
227 << " was defined multiple times." << std::endl;
228 } 407 }
229}
230 408
231void ValidateLetter(const LetterIdentifier& letter_identifier, 409 void ValidateKeyholder(const KeyholderIdentifier& keyholder_identifier,
232 const LetterInfo& letter_info) { 410 const KeyholderInfo& keyholder_info) const {
233 std::string letter_name = std::string(1, std::get<0>(letter_identifier)) + 411 if (keyholder_info.definitions.empty()) {
234 (std::get<1>(letter_identifier) ? "2" : "1"); 412 std::cout << "Keyholder " << keyholder_identifier.ShortDebugString()
413 << " has no definition, but was referenced:" << std::endl;
235 414
236 if (letter_info.defined_in.size() > 1) { 415 for (const DoorIdentifier& door_identifier :
237 std::cout << "Letter " << letter_name 416 keyholder_info.doors_referenced_by) {
238 << " was defined in multiple places:" << std::endl; 417 std::cout << " DOOR " << door_identifier.ShortDebugString()
418 << std::endl;
419 }
239 420
240 for (const RoomIdentifier& room_identifier : letter_info.defined_in) { 421 if (keyholder_info.has_id) {
241 std::cout << " " << room_identifier.ShortDebugString() << std::endl; 422 std::cout << " An AP ID is present." << std::endl;
423 }
424 } else if (keyholder_info.definitions.size() > 1) {
425 std::cout << "Keyholder " << keyholder_identifier.ShortDebugString()
426 << " was defined multiple times." << std::endl;
427 }
428
429 for (const HumanKeyholder& h_keyholder : keyholder_info.definitions) {
430 bool needs_id = (h_keyholder.has_key());
431
432 if (needs_id != keyholder_info.has_id) {
433 if (needs_id) {
434 std::cout << "Keyholder " << keyholder_identifier.ShortDebugString()
435 << " is missing an AP ID." << std::endl;
436 } else {
437 std::cout << "Keyholder " << keyholder_identifier.ShortDebugString()
438 << " should not have an AP ID." << std::endl;
439 }
440 }
242 } 441 }
243 } 442 }
244}
245 443
246void ValidateEnding(const std::string& ending_name, 444 void ValidateLetter(const LetterIdentifier& letter_identifier,
247 const EndingInfo& ending_info) { 445 const LetterInfo& letter_info) const {
248 if (ending_info.defined_in.size() > 1) { 446 std::string letter_name = std::string(1, std::get<0>(letter_identifier)) +
249 std::cout << "Ending " << ending_name 447 (std::get<1>(letter_identifier) ? "2" : "1");
250 << " was defined in multiple places:" << std::endl; 448
449 if (letter_info.defined_in.empty()) {
450 std::cout << "Letter " << letter_name
451 << " has no definition, but was referenced:" << std::endl;
251 452
252 for (const RoomIdentifier& room_identifier : ending_info.defined_in) { 453 if (letter_info.has_id) {
253 std::cout << " " << room_identifier.ShortDebugString() << std::endl; 454 std::cout << " An AP ID is present." << std::endl;
455 }
456 } else if (letter_info.defined_in.size() > 1) {
457 std::cout << "Letter " << letter_name
458 << " was defined in multiple places:" << std::endl;
459
460 for (const RoomIdentifier& room_identifier : letter_info.defined_in) {
461 std::cout << " " << room_identifier.ShortDebugString() << std::endl;
462 }
463 }
464
465 if (!letter_info.has_id) {
466 std::cout << "Letter " << letter_name << " is missing an AP ID."
467 << std::endl;
254 } 468 }
255 } 469 }
256}
257 470
258} // namespace 471 void ValidateEnding(const std::string& ending_name,
472 const EndingInfo& ending_info) const {
473 if (ending_info.defined_in.empty()) {
474 std::cout << "Ending " << ending_name
475 << " has no definition, but was referenced:" << std::endl;
259 476
260void ValidateCollectedInfo(const CollectedInfo& info) { 477 for (const DoorIdentifier& door_identifier :
261 for (const auto& [map_name, map_info] : info.maps) { 478 ending_info.doors_referenced_by) {
262 ValidateMap(map_name, map_info); 479 std::cout << " DOOR " << door_identifier.ShortDebugString()
263 } 480 << std::endl;
264 for (const auto& [room_identifier, room_info] : info.rooms) { 481 }
265 ValidateRoom(room_identifier, room_info); 482
266 } 483 if (ending_info.has_id) {
267 for (const auto& [door_identifier, door_info] : info.doors) { 484 std::cout << " An AP ID is present." << std::endl;
268 ValidateDoor(door_identifier, door_info); 485 }
269 } 486 } else if (ending_info.defined_in.size() > 1) {
270 for (const auto& [port_identifier, port_info] : info.ports) { 487 std::cout << "Ending " << ending_name
271 ValidatePort(port_identifier, port_info); 488 << " was defined in multiple places:" << std::endl;
272 } 489
273 for (const auto& [painting_identifier, painting_info] : info.paintings) { 490 for (const RoomIdentifier& room_identifier : ending_info.defined_in) {
274 ValidatePainting(painting_identifier, painting_info); 491 std::cout << " " << room_identifier.ShortDebugString() << std::endl;
275 } 492 }
276 for (const auto& [panel_identifier, panel_info] : info.panels) { 493 }
277 ValidatePanel(panel_identifier, panel_info); 494
495 if (!ending_info.has_id) {
496 std::cout << "Ending " << ending_name << " is missing an AP ID."
497 << std::endl;
498 }
278 } 499 }
279 for (const auto& [keyholder_identifier, keyholder_info] : info.keyholders) { 500
280 ValidateKeyholder(keyholder_identifier, keyholder_info); 501 void ValidatePanelName(const std::string& panel_name,
502 const PanelNameInfo& panel_info) const {
503 if (panel_info.panels_used_by.size() > 1) {
504 std::cout << "The location name \"" << panel_name
505 << "\" is used by multiple panels:" << std::endl;
506
507 for (const PanelIdentifier& panel_identifier :
508 panel_info.panels_used_by) {
509 std::cout << " PANEL " << panel_identifier.ShortDebugString()
510 << std::endl;
511 }
512 }
281 } 513 }
282 for (const auto& [letter_identifier, letter_info] : info.letters) { 514
283 ValidateLetter(letter_identifier, letter_info); 515 void ValidateProgressive(const std::string& prog_name,
516 const ProgressiveInfo& prog_info) const {
517 if (prog_info.definitions.empty()) {
518 std::cout << "Progressive \"" << prog_name
519 << "\" has no definition, but was referenced:" << std::endl;
520
521 if (prog_info.has_id) {
522 std::cout << " An AP ID is present." << std::endl;
523 }
524 } else if (prog_info.definitions.size() > 1) {
525 std::cout << "Progressive \"" << prog_name
526 << "\" has multiple definitions." << std::endl;
527 }
528
529 if (!prog_info.has_id) {
530 std::cout << "Progressive \"" << prog_name << "\" is missing an AP ID."
531 << std::endl;
532 }
284 } 533 }
285 for (const auto& [ending_name, ending_info] : info.endings) { 534
286 ValidateEnding(ending_name, ending_info); 535 void ValidateDoorGroup(const std::string& group_name,
536 const DoorGroupInfo& group_info) const {
537 if (group_info.definitions.empty()) {
538 std::cout << "Door group \"" << group_name
539 << "\" has no definition, but was referenced:" << std::endl;
540
541 if (group_info.has_id) {
542 std::cout << " An AP ID is present." << std::endl;
543 }
544 } else if (group_info.definitions.size() > 1) {
545 std::cout << "Door group \"" << group_name
546 << "\" has multiple definitions." << std::endl;
547 }
548
549 if (!group_info.has_id) {
550 std::cout << "Door group \"" << group_name << "\" is missing an AP ID."
551 << std::endl;
552 }
287 } 553 }
554
555 const CollectedInfo& info_;
556};
557
558} // namespace
559
560void ValidateCollectedInfo(const CollectedInfo& info) {
561 Validator validator(info);
562 validator.Validate();
288} 563}
289 564
290} // namespace com::fourisland::lingo2_archipelago 565} // namespace com::fourisland::lingo2_archipelago
diff --git a/tools/validator/validator.h b/tools/validator/validator.h index b710429..33bc7c9 100644 --- a/tools/validator/validator.h +++ b/tools/validator/validator.h
@@ -1,4 +1,4 @@
1#ifndef TOOLS_VALIDATOR_VALIDATOR_H_ 1#ifndef TOOLS_VALIDATOR_VALIDATOR_H
2#define TOOLS_VALIDATOR_VALIDATOR_H 2#define TOOLS_VALIDATOR_VALIDATOR_H
3 3
4namespace com::fourisland::lingo2_archipelago { 4namespace com::fourisland::lingo2_archipelago {
diff --git a/vcpkg.json b/vcpkg.json index 6517f7e..ba6833f 100644 --- a/vcpkg.json +++ b/vcpkg.json
@@ -1,12 +1,13 @@
1{ 1{
2 "dependencies": [ 2 "dependencies": [
3 "fmt",
3 "protobuf", 4 "protobuf",
4 "yaml-cpp" 5 "yaml-cpp"
5 ], 6 ],
6 "overrides": [ 7 "overrides": [
7 { 8 {
8 "name": "protobuf", 9 "name": "protobuf",
9 "version": "5.29.3" 10 "version": "3.21.12"
10 } 11 }
11 ] 12 ]
12} \ No newline at end of file 13} \ No newline at end of file
diff --git a/vendor/godobuf/LICENSE b/vendor/godobuf/LICENSE new file mode 100644 index 0000000..5d473d8 --- /dev/null +++ b/vendor/godobuf/LICENSE
@@ -0,0 +1,29 @@
1BSD 3-Clause License
2
3Copyright (c) 2018, oniksan
4All rights reserved.
5
6Redistribution and use in source and binary forms, with or without
7modification, are permitted provided that the following conditions are met:
8
9* Redistributions of source code must retain the above copyright notice, this
10 list of conditions and the following disclaimer.
11
12* Redistributions in binary form must reproduce the above copyright notice,
13 this list of conditions and the following disclaimer in the documentation
14 and/or other materials provided with the distribution.
15
16* Neither the name of the copyright holder nor the names of its
17 contributors may be used to endorse or promote products derived from
18 this software without specific prior written permission.
19
20THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
24FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/vendor/godobuf/README b/vendor/godobuf/README new file mode 100644 index 0000000..ce716bb --- /dev/null +++ b/vendor/godobuf/README
@@ -0,0 +1,4 @@
1This is a fork of https://github.com/oniksan/godobuf with some minor changes so
2that it is able to compile the Lingo 2 randomizer proto files. The plugin parts
3of the project have also been removed since we only need the command line
4script.
diff --git a/vendor/godobuf/addons/protobuf/parser.gd b/vendor/godobuf/addons/protobuf/parser.gd new file mode 100644 index 0000000..dfc0bdd --- /dev/null +++ b/vendor/godobuf/addons/protobuf/parser.gd
@@ -0,0 +1,2254 @@
1#
2# BSD 3-Clause License
3#
4# Copyright (c) 2018 - 2023, Oleg Malyavkin
5# All rights reserved.
6#
7# Redistribution and use in source and binary forms, with or without
8# modification, are permitted provided that the following conditions are met:
9#
10# * Redistributions of source code must retain the above copyright notice, this
11# list of conditions and the following disclaimer.
12#
13# * Redistributions in binary form must reproduce the above copyright notice,
14# this list of conditions and the following disclaimer in the documentation
15# and/or other materials provided with the distribution.
16#
17# * Neither the name of the copyright holder nor the names of its
18# contributors may be used to endorse or promote products derived from
19# this software without specific prior written permission.
20#
21# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
25# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31
32extends Node
33
34const PROTO_VERSION_CONST : String = "const PROTO_VERSION = "
35const PROTO_VERSION_DEFAULT : String = PROTO_VERSION_CONST + "0"
36
37class Document:
38
39 func _init(doc_name : String, doc_text : String):
40 name = doc_name
41 text = doc_text
42
43 var name : String
44 var text : String
45
46class TokenPosition:
47 func _init(b : int, e : int):
48 begin = b
49 end = e
50 var begin : int = 0
51 var end : int = 0
52
53class Helper:
54
55 class StringPosition:
56 func _init(s : int, c : int, l : int):
57 str_num = s
58 column = c
59 length = l
60 var str_num : int
61 var column : int
62 var length : int
63
64 static func str_pos(text : String, position : TokenPosition) -> StringPosition:
65 var cur_str : int = 1
66 var cur_col : int = 1
67 var res_str : int = 0
68 var res_col : int = 0
69 var res_length : int = 0
70 for i in range(text.length()):
71 if text[i] == "\n":
72 cur_str += 1
73 cur_col = 0
74 if position.begin == i:
75 res_str = cur_str
76 res_col = cur_col
77 res_length = position.end - position.begin + 1
78 break
79 cur_col += 1
80 return StringPosition.new(res_str, res_col, res_length)
81
82 static func text_pos(tokens : Array, index : int) -> TokenPosition:
83 var res_begin : int = 0
84 var res_end : int = 0
85 if index < tokens.size() && index >= 0:
86 res_begin = tokens[index].position.begin
87 res_end = tokens[index].position.end
88 return TokenPosition.new(res_begin, res_end)
89
90 static func error_string(file_name, col, row, error_text):
91 return file_name + ":" + str(col) + ":" + str(row) + ": error: " + error_text
92
93class AnalyzeResult:
94 var classes : Array = []
95 var fields : Array = []
96 var groups : Array = []
97 var version : int = 0
98 var state : bool = false
99 var tokens : Array = []
100 var syntax : Analysis.TranslationResult
101 var imports : Array = []
102 var doc : Document
103
104 func soft_copy() -> AnalyzeResult:
105 var res : AnalyzeResult = AnalyzeResult.new()
106 res.classes = classes
107 res.fields = fields
108 res.groups = groups
109 res.version = version
110 res.state = state
111 res.tokens = tokens
112 res.syntax = syntax
113 res.imports = imports
114 res.doc = doc
115 return res
116
117class Analysis:
118
119 func _init(path : String, doc : Document):
120 path_dir = path
121 document = doc
122
123 var document : Document
124 var path_dir : String
125
126 const LEX = {
127 LETTER = "[A-Za-z]",
128 DIGIT_DEC = "[0-9]",
129 DIGIT_OCT = "[0-7]",
130 DIGIT_HEX = "[0-9]|[A-F]|[a-f]",
131 BRACKET_ROUND_LEFT = "\\(",
132 BRACKET_ROUND_RIGHT = "\\)",
133 BRACKET_CURLY_LEFT = "\\{",
134 BRACKET_CURLY_RIGHT = "\\}",
135 BRACKET_SQUARE_LEFT = "\\[",
136 BRACKET_SQUARE_RIGHT = "\\]",
137 BRACKET_ANGLE_LEFT = "\\<",
138 BRACKET_ANGLE_RIGHT = "\\>",
139 SEMICOLON = ";",
140 COMMA = ",",
141 EQUAL = "=",
142 SIGN = "\\+|\\-",
143 SPACE = "\\s",
144 QUOTE_SINGLE = "'",
145 QUOTE_DOUBLE = "\"",
146 }
147
148 const TOKEN_IDENT : String = "(" + LEX.LETTER + "+" + "(" + LEX.LETTER + "|" + LEX.DIGIT_DEC + "|" + "_)*)"
149 const TOKEN_FULL_IDENT : String = TOKEN_IDENT + "{0,1}(\\." + TOKEN_IDENT + ")+"
150 const TOKEN_BRACKET_ROUND_LEFT : String = "(" + LEX.BRACKET_ROUND_LEFT + ")"
151 const TOKEN_BRACKET_ROUND_RIGHT : String = "(" + LEX.BRACKET_ROUND_RIGHT + ")"
152 const TOKEN_BRACKET_CURLY_LEFT : String = "(" + LEX.BRACKET_CURLY_LEFT + ")"
153 const TOKEN_BRACKET_CURLY_RIGHT : String = "(" + LEX.BRACKET_CURLY_RIGHT + ")"
154 const TOKEN_BRACKET_SQUARE_LEFT : String = "(" + LEX.BRACKET_SQUARE_LEFT + ")"
155 const TOKEN_BRACKET_SQUARE_RIGHT : String = "(" + LEX.BRACKET_SQUARE_RIGHT + ")"
156 const TOKEN_BRACKET_ANGLE_LEFT : String = "(" + LEX.BRACKET_ANGLE_LEFT + ")"
157 const TOKEN_BRACKET_ANGLE_RIGHT : String = "(" + LEX.BRACKET_ANGLE_RIGHT + ")"
158 const TOKEN_SEMICOLON : String = "(" + LEX.SEMICOLON + ")"
159 const TOKEN_EUQAL : String = "(" + LEX.EQUAL + ")"
160 const TOKEN_SIGN : String = "(" + LEX.SIGN + ")"
161 const TOKEN_LITERAL_DEC : String = "(([1-9])" + LEX.DIGIT_DEC +"*)"
162 const TOKEN_LITERAL_OCT : String = "(0" + LEX.DIGIT_OCT +"*)"
163 const TOKEN_LITERAL_HEX : String = "(0(x|X)(" + LEX.DIGIT_HEX +")+)"
164 const TOKEN_LITERAL_INT : String = "((\\+|\\-){0,1}" + TOKEN_LITERAL_DEC + "|" + TOKEN_LITERAL_OCT + "|" + TOKEN_LITERAL_HEX + ")"
165 const TOKEN_LITERAL_FLOAT_DEC : String = "(" + LEX.DIGIT_DEC + "+)"
166 const TOKEN_LITERAL_FLOAT_EXP : String = "((e|E)(\\+|\\-)?" + TOKEN_LITERAL_FLOAT_DEC + "+)"
167 const TOKEN_LITERAL_FLOAT : String = "((\\+|\\-){0,1}(" + TOKEN_LITERAL_FLOAT_DEC + "\\." + TOKEN_LITERAL_FLOAT_DEC + "?" + TOKEN_LITERAL_FLOAT_EXP + "?)|(" + TOKEN_LITERAL_FLOAT_DEC + TOKEN_LITERAL_FLOAT_EXP + ")|(\\." + TOKEN_LITERAL_FLOAT_DEC + TOKEN_LITERAL_FLOAT_EXP + "?))"
168 const TOKEN_SPACE : String = "(" + LEX.SPACE + ")+"
169 const TOKEN_COMMA : String = "(" + LEX.COMMA + ")"
170 const TOKEN_CHAR_ESC : String = "[\\\\(a|b|f|n|r|t|v|\\\\|'|\")]"
171 const TOKEN_OCT_ESC : String = "[\\\\" + LEX.DIGIT_OCT + "{3}]"
172 const TOKEN_HEX_ESC : String = "[\\\\(x|X)" + LEX.DIGIT_HEX + "{2}]"
173 const TOKEN_CHAR_EXCLUDE : String = "[^\\0\\n\\\\]"
174 const TOKEN_CHAR_VALUE : String = "(" + TOKEN_HEX_ESC + "|" + TOKEN_OCT_ESC + "|" + TOKEN_CHAR_ESC + "|" + TOKEN_CHAR_EXCLUDE + ")"
175 const TOKEN_STRING_SINGLE : String = "('" + TOKEN_CHAR_VALUE + "*?')"
176 const TOKEN_STRING_DOUBLE : String = "(\"" + TOKEN_CHAR_VALUE + "*?\")"
177 const TOKEN_COMMENT_SINGLE : String = "((//[^\\n\\r]*[^\\s])|//)"
178 const TOKEN_COMMENT_MULTI : String = "/\\*(.|[\\n\\r])*?\\*/"
179
180 const TOKEN_SECOND_MESSAGE : String = "^message$"
181 const TOKEN_SECOND_SIMPLE_DATA_TYPE : String = "^(double|float|int32|int64|uint32|uint64|sint32|sint64|fixed32|fixed64|sfixed32|sfixed64|bool|string|bytes)$"
182 const TOKEN_SECOND_ENUM : String = "^enum$"
183 const TOKEN_SECOND_MAP : String = "^map$"
184 const TOKEN_SECOND_ONEOF : String = "^oneof$"
185 const TOKEN_SECOND_LITERAL_BOOL : String = "^(true|false)$"
186 const TOKEN_SECOND_SYNTAX : String = "^syntax$"
187 const TOKEN_SECOND_IMPORT : String = "^import$"
188 const TOKEN_SECOND_PACKAGE : String = "^package$"
189 const TOKEN_SECOND_OPTION : String = "^option$"
190 const TOKEN_SECOND_SERVICE : String = "^service$"
191 const TOKEN_SECOND_RESERVED : String = "^reserved$"
192 const TOKEN_SECOND_IMPORT_QUALIFICATION : String = "^(weak|public)$"
193 const TOKEN_SECOND_FIELD_QUALIFICATION : String = "^(repeated|required|optional)$"
194 const TOKEN_SECOND_ENUM_OPTION : String = "^allow_alias$"
195 const TOKEN_SECOND_QUALIFICATION : String = "^(custom_option|extensions)$"
196 const TOKEN_SECOND_FIELD_OPTION : String = "^packed$"
197
198 class TokenEntrance:
199 func _init(i : int, b : int, e : int, t : String):
200 position = TokenPosition.new(b, e)
201 text = t
202 id = i
203 var position : TokenPosition
204 var text : String
205 var id : int
206
207 enum RANGE_STATE {
208 INCLUDE = 0,
209 EXCLUDE_LEFT = 1,
210 EXCLUDE_RIGHT = 2,
211 OVERLAY = 3,
212 EQUAL = 4,
213 ENTERS = 5
214 }
215
216 class TokenRange:
217 func _init(b : int, e : int, s):
218 position = TokenPosition.new(b, e)
219 state = s
220 var position : TokenPosition
221 var state
222
223 class Token:
224 var _regex : RegEx
225 var _entrance : TokenEntrance = null
226 var _entrances : Array = []
227 var _entrance_index : int = 0
228 var _id : int
229 var _ignore : bool
230 var _clarification : String
231
232 func _init(id : int, clarification : String, regex_str : String, ignore = false):
233 _id = id
234 _regex = RegEx.new()
235 _regex.compile(regex_str)
236 _clarification = clarification
237 _ignore = ignore
238
239 func find(text : String, start : int) -> TokenEntrance:
240 _entrance = null
241 if !_regex.is_valid():
242 return null
243 var match_result : RegExMatch = _regex.search(text, start)
244 if match_result != null:
245 var capture
246 capture = match_result.get_string(0)
247 if capture.is_empty():
248 return null
249 _entrance = TokenEntrance.new(_id, match_result.get_start(0), capture.length() - 1 + match_result.get_start(0), capture)
250 return _entrance
251
252 func find_all(text : String) -> Array:
253 var pos : int = 0
254 clear()
255 while find(text, pos) != null:
256 _entrances.append(_entrance)
257 pos = _entrance.position.end + 1
258 return _entrances
259
260 func add_entrance(entrance) -> void:
261 _entrances.append(entrance)
262
263 func clear() -> void:
264 _entrance = null
265 _entrances = []
266 _entrance_index = 0
267
268 func get_entrances() -> Array:
269 return _entrances
270
271 func remove_entrance(index) -> void:
272 if index < _entrances.size():
273 _entrances.remove_at(index)
274
275 func get_index() -> int:
276 return _entrance_index
277
278 func set_index(index : int) -> void:
279 if index < _entrances.size():
280 _entrance_index = index
281 else:
282 _entrance_index = 0
283
284 func is_ignore() -> bool:
285 return _ignore
286
287 func get_clarification() -> String:
288 return _clarification
289
290 class TokenResult:
291 var tokens : Array = []
292 var errors : Array = []
293
294 enum TOKEN_ID {
295 UNDEFINED = -1,
296 IDENT = 0,
297 FULL_IDENT = 1,
298 BRACKET_ROUND_LEFT = 2,
299 BRACKET_ROUND_RIGHT = 3,
300 BRACKET_CURLY_LEFT = 4,
301 BRACKET_CURLY_RIGHT = 5,
302 BRACKET_SQUARE_LEFT = 6,
303 BRACKET_SQUARE_RIGHT = 7,
304 BRACKET_ANGLE_LEFT = 8,
305 BRACKET_ANGLE_RIGHT = 9,
306 SEMICOLON = 10,
307 EUQAL = 11,
308 SIGN = 12,
309 INT = 13,
310 FLOAT = 14,
311 SPACE = 15,
312 COMMA = 16,
313 STRING_SINGLE = 17,
314 STRING_DOUBLE = 18,
315 COMMENT_SINGLE = 19,
316 COMMENT_MULTI = 20,
317
318 MESSAGE = 21,
319 SIMPLE_DATA_TYPE = 22,
320 ENUM = 23,
321 MAP = 24,
322 ONEOF = 25,
323 LITERAL_BOOL = 26,
324 SYNTAX = 27,
325 IMPORT = 28,
326 PACKAGE = 29,
327 OPTION = 30,
328 SERVICE = 31,
329 RESERVED = 32,
330 IMPORT_QUALIFICATION = 33,
331 FIELD_QUALIFICATION = 34,
332 ENUM_OPTION = 35,
333 QUALIFICATION = 36,
334 FIELD_OPTION = 37,
335
336 STRING = 38
337 }
338
339 var TOKEN = {
340 TOKEN_ID.IDENT: Token.new(TOKEN_ID.IDENT, "Identifier", TOKEN_IDENT),
341 TOKEN_ID.FULL_IDENT: Token.new(TOKEN_ID.FULL_IDENT, "Full identifier", TOKEN_FULL_IDENT),
342 TOKEN_ID.BRACKET_ROUND_LEFT: Token.new(TOKEN_ID.BRACKET_ROUND_LEFT, "(", TOKEN_BRACKET_ROUND_LEFT),
343 TOKEN_ID.BRACKET_ROUND_RIGHT: Token.new(TOKEN_ID.BRACKET_ROUND_RIGHT, ")", TOKEN_BRACKET_ROUND_RIGHT),
344 TOKEN_ID.BRACKET_CURLY_LEFT: Token.new(TOKEN_ID.BRACKET_CURLY_LEFT, "{", TOKEN_BRACKET_CURLY_LEFT),
345 TOKEN_ID.BRACKET_CURLY_RIGHT: Token.new(TOKEN_ID.BRACKET_CURLY_RIGHT, "}", TOKEN_BRACKET_CURLY_RIGHT),
346 TOKEN_ID.BRACKET_SQUARE_LEFT: Token.new(TOKEN_ID.BRACKET_SQUARE_LEFT, "[", TOKEN_BRACKET_SQUARE_LEFT),
347 TOKEN_ID.BRACKET_SQUARE_RIGHT: Token.new(TOKEN_ID.BRACKET_SQUARE_RIGHT, "]", TOKEN_BRACKET_SQUARE_RIGHT),
348 TOKEN_ID.BRACKET_ANGLE_LEFT: Token.new(TOKEN_ID.BRACKET_ANGLE_LEFT, "<", TOKEN_BRACKET_ANGLE_LEFT),
349 TOKEN_ID.BRACKET_ANGLE_RIGHT: Token.new(TOKEN_ID.BRACKET_ANGLE_RIGHT, ">", TOKEN_BRACKET_ANGLE_RIGHT),
350 TOKEN_ID.SEMICOLON: Token.new(TOKEN_ID.SEMICOLON, ";", TOKEN_SEMICOLON),
351 TOKEN_ID.EUQAL: Token.new(TOKEN_ID.EUQAL, "=", TOKEN_EUQAL),
352 TOKEN_ID.INT: Token.new(TOKEN_ID.INT, "Integer", TOKEN_LITERAL_INT),
353 TOKEN_ID.FLOAT: Token.new(TOKEN_ID.FLOAT, "Float", TOKEN_LITERAL_FLOAT),
354 TOKEN_ID.SPACE: Token.new(TOKEN_ID.SPACE, "Space", TOKEN_SPACE),
355 TOKEN_ID.COMMA: Token.new(TOKEN_ID.COMMA, ",", TOKEN_COMMA),
356 TOKEN_ID.STRING_SINGLE: Token.new(TOKEN_ID.STRING_SINGLE, "'String'", TOKEN_STRING_SINGLE),
357 TOKEN_ID.STRING_DOUBLE: Token.new(TOKEN_ID.STRING_DOUBLE, "\"String\"", TOKEN_STRING_DOUBLE),
358 TOKEN_ID.COMMENT_SINGLE: Token.new(TOKEN_ID.COMMENT_SINGLE, "//Comment", TOKEN_COMMENT_SINGLE),
359 TOKEN_ID.COMMENT_MULTI: Token.new(TOKEN_ID.COMMENT_MULTI, "/*Comment*/", TOKEN_COMMENT_MULTI),
360
361 TOKEN_ID.MESSAGE: Token.new(TOKEN_ID.MESSAGE, "Message", TOKEN_SECOND_MESSAGE, true),
362 TOKEN_ID.SIMPLE_DATA_TYPE: Token.new(TOKEN_ID.SIMPLE_DATA_TYPE, "Data type", TOKEN_SECOND_SIMPLE_DATA_TYPE, true),
363 TOKEN_ID.ENUM: Token.new(TOKEN_ID.ENUM, "Enum", TOKEN_SECOND_ENUM, true),
364 TOKEN_ID.MAP: Token.new(TOKEN_ID.MAP, "Map", TOKEN_SECOND_MAP, true),
365 TOKEN_ID.ONEOF: Token.new(TOKEN_ID.ONEOF, "OneOf", TOKEN_SECOND_ONEOF, true),
366 TOKEN_ID.LITERAL_BOOL: Token.new(TOKEN_ID.LITERAL_BOOL, "Bool literal", TOKEN_SECOND_LITERAL_BOOL, true),
367 TOKEN_ID.SYNTAX: Token.new(TOKEN_ID.SYNTAX, "Syntax", TOKEN_SECOND_SYNTAX, true),
368 TOKEN_ID.IMPORT: Token.new(TOKEN_ID.IMPORT, "Import", TOKEN_SECOND_IMPORT, true),
369 TOKEN_ID.PACKAGE: Token.new(TOKEN_ID.PACKAGE, "Package", TOKEN_SECOND_PACKAGE, true),
370 TOKEN_ID.OPTION: Token.new(TOKEN_ID.OPTION, "Option", TOKEN_SECOND_OPTION, true),
371 TOKEN_ID.SERVICE: Token.new(TOKEN_ID.SERVICE, "Service", TOKEN_SECOND_SERVICE, true),
372 TOKEN_ID.RESERVED: Token.new(TOKEN_ID.RESERVED, "Reserved", TOKEN_SECOND_RESERVED, true),
373 TOKEN_ID.IMPORT_QUALIFICATION: Token.new(TOKEN_ID.IMPORT_QUALIFICATION, "Import qualification", TOKEN_SECOND_IMPORT_QUALIFICATION, true),
374 TOKEN_ID.FIELD_QUALIFICATION: Token.new(TOKEN_ID.FIELD_QUALIFICATION, "Field qualification", TOKEN_SECOND_FIELD_QUALIFICATION, true),
375 TOKEN_ID.ENUM_OPTION: Token.new(TOKEN_ID.ENUM_OPTION, "Enum option", TOKEN_SECOND_ENUM_OPTION, true),
376 TOKEN_ID.QUALIFICATION: Token.new(TOKEN_ID.QUALIFICATION, "Qualification", TOKEN_SECOND_QUALIFICATION, true),
377 TOKEN_ID.FIELD_OPTION: Token.new(TOKEN_ID.FIELD_OPTION, "Field option", TOKEN_SECOND_FIELD_OPTION, true),
378
379 TOKEN_ID.STRING: Token.new(TOKEN_ID.STRING, "String", "", true)
380 }
381
382 static func check_range(main : TokenEntrance, current : TokenEntrance) -> TokenRange:
383 if main.position.begin > current.position.begin:
384 if main.position.end > current.position.end:
385 if main.position.begin >= current.position.end:
386 return TokenRange.new(current.position.begin, current.position.end, RANGE_STATE.EXCLUDE_LEFT)
387 else:
388 return TokenRange.new(main.position.begin, current.position.end, RANGE_STATE.OVERLAY)
389 else:
390 return TokenRange.new(current.position.begin, current.position.end, RANGE_STATE.ENTERS)
391 elif main.position.begin < current.position.begin:
392 if main.position.end >= current.position.end:
393 return TokenRange.new(main.position.begin, main.position.end, RANGE_STATE.INCLUDE)
394 else:
395 if main.position.end < current.position.begin:
396 return TokenRange.new(main.position.begin, main.position.end, RANGE_STATE.EXCLUDE_RIGHT)
397 else:
398 return TokenRange.new(main.position.begin, current.position.end, RANGE_STATE.OVERLAY)
399 else:
400 if main.position.end == current.position.end:
401 return TokenRange.new(main.position.begin, main.position.end, RANGE_STATE.EQUAL)
402 elif main.position.end > current.position.end:
403 return TokenRange.new(main.position.begin, main.position.end, RANGE_STATE.INCLUDE)
404 else:
405 return TokenRange.new(current.position.begin, current.position.end, RANGE_STATE.ENTERS)
406
407 func tokenizer() -> TokenResult:
408 for k in TOKEN:
409 if !TOKEN[k].is_ignore():
410 TOKEN[k].find_all(document.text)
411 var second_tokens : Array = []
412 second_tokens.append(TOKEN[TOKEN_ID.MESSAGE])
413 second_tokens.append(TOKEN[TOKEN_ID.SIMPLE_DATA_TYPE])
414 second_tokens.append(TOKEN[TOKEN_ID.ENUM])
415 second_tokens.append(TOKEN[TOKEN_ID.MAP])
416 second_tokens.append(TOKEN[TOKEN_ID.ONEOF])
417 second_tokens.append(TOKEN[TOKEN_ID.LITERAL_BOOL])
418 second_tokens.append(TOKEN[TOKEN_ID.SYNTAX])
419 second_tokens.append(TOKEN[TOKEN_ID.IMPORT])
420 second_tokens.append(TOKEN[TOKEN_ID.PACKAGE])
421 second_tokens.append(TOKEN[TOKEN_ID.OPTION])
422 second_tokens.append(TOKEN[TOKEN_ID.SERVICE])
423 second_tokens.append(TOKEN[TOKEN_ID.RESERVED])
424 second_tokens.append(TOKEN[TOKEN_ID.IMPORT_QUALIFICATION])
425 second_tokens.append(TOKEN[TOKEN_ID.FIELD_QUALIFICATION])
426 second_tokens.append(TOKEN[TOKEN_ID.ENUM_OPTION])
427 second_tokens.append(TOKEN[TOKEN_ID.QUALIFICATION])
428 second_tokens.append(TOKEN[TOKEN_ID.FIELD_OPTION])
429
430 var ident_token : Token = TOKEN[TOKEN_ID.IDENT]
431 for sec_token in second_tokens:
432 var remove_indexes : Array = []
433 for i in range(ident_token.get_entrances().size()):
434 var entrance : TokenEntrance = sec_token.find(ident_token.get_entrances()[i].text, 0)
435 if entrance != null:
436 entrance.position.begin = ident_token.get_entrances()[i].position.begin
437 entrance.position.end = ident_token.get_entrances()[i].position.end
438 sec_token.add_entrance(entrance)
439 remove_indexes.append(i)
440 for i in range(remove_indexes.size()):
441 ident_token.remove_entrance(remove_indexes[i] - i)
442 for v in TOKEN[TOKEN_ID.STRING_DOUBLE].get_entrances():
443 v.id = TOKEN_ID.STRING
444 TOKEN[TOKEN_ID.STRING].add_entrance(v)
445 TOKEN[TOKEN_ID.STRING_DOUBLE].clear()
446 for v in TOKEN[TOKEN_ID.STRING_SINGLE].get_entrances():
447 v.id = TOKEN_ID.STRING
448 TOKEN[TOKEN_ID.STRING].add_entrance(v)
449 TOKEN[TOKEN_ID.STRING_SINGLE].clear()
450 var main_token : TokenEntrance
451 var cur_token : TokenEntrance
452 var main_index : int = -1
453 var token_index_flag : bool = false
454 var result : TokenResult = TokenResult.new()
455 var check : TokenRange
456 var end : bool = false
457 var all : bool = false
458 var repeat : bool = false
459 while true:
460 all = true
461 for k in TOKEN:
462 if main_index == k:
463 continue
464 repeat = false
465 while TOKEN[k].get_entrances().size() > 0:
466 all = false
467 if !token_index_flag:
468 main_index = k
469 main_token = TOKEN[main_index].get_entrances()[0]
470 token_index_flag = true
471 break
472 else:
473 cur_token = TOKEN[k].get_entrances()[0]
474 check = check_range(main_token, cur_token)
475 if check.state == RANGE_STATE.INCLUDE:
476 TOKEN[k].remove_entrance(0)
477 end = true
478 elif check.state == RANGE_STATE.EXCLUDE_LEFT:
479 main_token = cur_token
480 main_index = k
481 end = false
482 repeat = true
483 break
484 elif check.state == RANGE_STATE.EXCLUDE_RIGHT:
485 end = true
486 break
487 elif check.state == RANGE_STATE.OVERLAY || check.state == RANGE_STATE.EQUAL:
488 result.errors.append(check)
489 TOKEN[main_index].remove_entrance(0)
490 TOKEN[k].remove_entrance(0)
491 token_index_flag = false
492 end = false
493 repeat = true
494 break
495 elif check.state == RANGE_STATE.ENTERS:
496 TOKEN[main_index].remove_entrance(0)
497 main_token = cur_token
498 main_index = k
499 end = false
500 repeat = true
501 break
502 if repeat:
503 break
504 if end:
505 if TOKEN[main_index].get_entrances().size() > 0:
506 result.tokens.append(main_token)
507 TOKEN[main_index].remove_entrance(0)
508 token_index_flag = false
509 if all:
510 break
511 return result
512
513 static func check_tokens_integrity(tokens : Array, end : int) -> Array:
514 var cur_index : int = 0
515 var result : Array = []
516 for v in tokens:
517 if v.position.begin > cur_index:
518 result.append(TokenPosition.new(cur_index, v.position.begin))
519 cur_index = v.position.end + 1
520 if cur_index < end:
521 result.append(TokenPosition.new(cur_index, end))
522 return result
523
524 static func comment_space_processing(tokens : Array) -> void:
525 var remove_indexes : Array = []
526 for i in range(tokens.size()):
527 if tokens[i].id == TOKEN_ID.COMMENT_SINGLE || tokens[i].id == TOKEN_ID.COMMENT_MULTI:
528 tokens[i].id = TOKEN_ID.SPACE
529 var space_index : int = -1
530 for i in range(tokens.size()):
531 if tokens[i].id == TOKEN_ID.SPACE:
532 if space_index >= 0:
533 tokens[space_index].position.end = tokens[i].position.end
534 tokens[space_index].text = tokens[space_index].text + tokens[i].text
535 remove_indexes.append(i)
536 else:
537 space_index = i
538 else:
539 space_index = -1
540 for i in range(remove_indexes.size()):
541 tokens.remove_at(remove_indexes[i] - i)
542
543 #Analysis rule
544 enum AR {
545 MAYBE = 1,
546 MUST_ONE = 2,
547 ANY = 3,
548 OR = 4,
549 MAYBE_BEGIN = 5,
550 MAYBE_END = 6,
551 ANY_BEGIN = 7,
552 ANY_END = 8
553 }
554
555 #Space rule (space after token)
556 enum SP {
557 MAYBE = 1,
558 MUST = 2,
559 NO = 3
560 }
561
562 #Analysis Syntax Description
563 class ASD:
564 func _init(t, s : int = SP.MAYBE, r : int = AR.MUST_ONE, i : bool = false):
565 token = t
566 space = s
567 rule = r
568 importance = i
569 var token
570 var space : int
571 var rule : int
572 var importance : bool
573
574 var TEMPLATE_SYNTAX : Array = [
575 Callable(self, "desc_syntax"),
576 ASD.new(TOKEN_ID.SYNTAX),
577 ASD.new(TOKEN_ID.EUQAL),
578 ASD.new(TOKEN_ID.STRING, SP.MAYBE, AR.MUST_ONE, true),
579 ASD.new(TOKEN_ID.SEMICOLON)
580 ]
581
582 var TEMPLATE_IMPORT : Array = [
583 Callable(self, "desc_import"),
584 ASD.new(TOKEN_ID.IMPORT, SP.MUST),
585 ASD.new(TOKEN_ID.IMPORT_QUALIFICATION, SP.MUST, AR.MAYBE, true),
586 ASD.new(TOKEN_ID.STRING, SP.MAYBE, AR.MUST_ONE, true),
587 ASD.new(TOKEN_ID.SEMICOLON)
588 ]
589
590 var TEMPLATE_PACKAGE : Array = [
591 Callable(self, "desc_package"),
592 ASD.new(TOKEN_ID.PACKAGE, SP.MUST),
593 ASD.new([TOKEN_ID.IDENT, TOKEN_ID.FULL_IDENT], SP.MAYBE, AR.OR, true),
594 ASD.new(TOKEN_ID.SEMICOLON)
595 ]
596
597 var TEMPLATE_OPTION : Array = [
598 Callable(self, "desc_option"),
599 ASD.new(TOKEN_ID.OPTION, SP.MUST),
600 ASD.new([TOKEN_ID.IDENT, TOKEN_ID.FULL_IDENT], SP.MAYBE, AR.OR, true),
601 ASD.new(TOKEN_ID.EUQAL),
602 ASD.new([TOKEN_ID.STRING, TOKEN_ID.INT, TOKEN_ID.FLOAT, TOKEN_ID.LITERAL_BOOL], SP.MAYBE, AR.OR, true),
603 ASD.new(TOKEN_ID.SEMICOLON)
604 ]
605
606 var TEMPLATE_FIELD : Array = [
607 Callable(self, "desc_field"),
608 ASD.new(TOKEN_ID.FIELD_QUALIFICATION, SP.MUST, AR.MAYBE, true),
609 ASD.new([TOKEN_ID.SIMPLE_DATA_TYPE, TOKEN_ID.IDENT, TOKEN_ID.FULL_IDENT], SP.MAYBE, AR.OR, true),
610 ASD.new(TOKEN_ID.IDENT, SP.MAYBE, AR.MUST_ONE, true),
611 ASD.new(TOKEN_ID.EUQAL),
612 ASD.new(TOKEN_ID.INT, SP.MAYBE, AR.MUST_ONE, true),
613 ASD.new(TOKEN_ID.BRACKET_SQUARE_LEFT, SP.MAYBE, AR.MAYBE_BEGIN),
614 ASD.new(TOKEN_ID.FIELD_OPTION, SP.MAYBE, AR.MUST_ONE, true),
615 ASD.new(TOKEN_ID.EUQAL),
616 ASD.new(TOKEN_ID.LITERAL_BOOL, SP.MAYBE, AR.MUST_ONE, true),
617 ASD.new(TOKEN_ID.BRACKET_SQUARE_RIGHT, SP.MAYBE, AR.MAYBE_END),
618 ASD.new(TOKEN_ID.SEMICOLON)
619 ]
620
621 var TEMPLATE_FIELD_ONEOF : Array = TEMPLATE_FIELD
622
623 var TEMPLATE_MAP_FIELD : Array = [
624 Callable(self, "desc_map_field"),
625 ASD.new(TOKEN_ID.MAP),
626 ASD.new(TOKEN_ID.BRACKET_ANGLE_LEFT),
627 ASD.new(TOKEN_ID.SIMPLE_DATA_TYPE, SP.MAYBE, AR.MUST_ONE, true),
628 ASD.new(TOKEN_ID.COMMA),
629 ASD.new([TOKEN_ID.SIMPLE_DATA_TYPE, TOKEN_ID.IDENT, TOKEN_ID.FULL_IDENT], SP.MAYBE, AR.OR, true),
630 ASD.new(TOKEN_ID.BRACKET_ANGLE_RIGHT, SP.MUST),
631 ASD.new(TOKEN_ID.IDENT, SP.MAYBE, AR.MUST_ONE, true),
632 ASD.new(TOKEN_ID.EUQAL),
633 ASD.new(TOKEN_ID.INT, SP.MAYBE, AR.MUST_ONE, true),
634 ASD.new(TOKEN_ID.BRACKET_SQUARE_LEFT, SP.MAYBE, AR.MAYBE_BEGIN),
635 ASD.new(TOKEN_ID.FIELD_OPTION, SP.MAYBE, AR.MUST_ONE, true),
636 ASD.new(TOKEN_ID.EUQAL),
637 ASD.new(TOKEN_ID.LITERAL_BOOL, SP.MAYBE, AR.MUST_ONE, true),
638 ASD.new(TOKEN_ID.BRACKET_SQUARE_RIGHT, SP.MAYBE, AR.MAYBE_END),
639 ASD.new(TOKEN_ID.SEMICOLON)
640 ]
641
642 var TEMPLATE_MAP_FIELD_ONEOF : Array = TEMPLATE_MAP_FIELD
643
644 var TEMPLATE_ENUM : Array = [
645 Callable(self, "desc_enum"),
646 ASD.new(TOKEN_ID.ENUM, SP.MUST),
647 ASD.new(TOKEN_ID.IDENT, SP.MAYBE, AR.MUST_ONE, true),
648 ASD.new(TOKEN_ID.BRACKET_CURLY_LEFT),
649 ASD.new(TOKEN_ID.OPTION, SP.MUST, AR.MAYBE_BEGIN),
650 ASD.new(TOKEN_ID.ENUM_OPTION, SP.MAYBE, AR.MUST_ONE, true),
651 ASD.new(TOKEN_ID.EUQAL),
652 ASD.new(TOKEN_ID.LITERAL_BOOL, SP.MAYBE, AR.MUST_ONE, true),
653 ASD.new(TOKEN_ID.SEMICOLON, SP.MAYBE, AR.MAYBE_END),
654 ASD.new(TOKEN_ID.IDENT, SP.MAYBE, AR.ANY_BEGIN, true),
655 ASD.new(TOKEN_ID.EUQAL),
656 ASD.new(TOKEN_ID.INT, SP.MAYBE, AR.MUST_ONE, true),
657 ASD.new(TOKEN_ID.SEMICOLON, SP.MAYBE, AR.ANY_END),
658 ASD.new(TOKEN_ID.BRACKET_CURLY_RIGHT)
659 ]
660
661 var TEMPLATE_MESSAGE_HEAD : Array = [
662 Callable(self, "desc_message_head"),
663 ASD.new(TOKEN_ID.MESSAGE, SP.MUST),
664 ASD.new(TOKEN_ID.IDENT, SP.MAYBE, AR.MUST_ONE, true),
665 ASD.new(TOKEN_ID.BRACKET_CURLY_LEFT)
666 ]
667
668 var TEMPLATE_MESSAGE_TAIL : Array = [
669 Callable(self, "desc_message_tail"),
670 ASD.new(TOKEN_ID.BRACKET_CURLY_RIGHT)
671 ]
672
673 var TEMPLATE_ONEOF_HEAD : Array = [
674 Callable(self, "desc_oneof_head"),
675 ASD.new(TOKEN_ID.ONEOF, SP.MUST),
676 ASD.new(TOKEN_ID.IDENT, SP.MAYBE, AR.MUST_ONE, true),
677 ASD.new(TOKEN_ID.BRACKET_CURLY_LEFT),
678 ]
679
680 var TEMPLATE_ONEOF_TAIL : Array = [
681 Callable(self, "desc_oneof_tail"),
682 ASD.new(TOKEN_ID.BRACKET_CURLY_RIGHT)
683 ]
684
685 var TEMPLATE_BEGIN : Array = [
686 null,
687 ASD.new(TOKEN_ID.SPACE, SP.NO, AR.MAYBE)
688 ]
689
690 var TEMPLATE_END : Array = [
691 null
692 ]
693
694 func get_token_id(tokens : Array, index : int) -> int:
695 if index < tokens.size():
696 return tokens[index].id
697 return TOKEN_ID.UNDEFINED
698
699 enum COMPARE_STATE {
700 DONE = 0,
701 MISMATCH = 1,
702 INCOMPLETE = 2,
703 ERROR_VALUE = 3
704 }
705
706 class TokenCompare:
707 func _init(s : int, i : int, d : String = ""):
708 state = s
709 index = i
710 description = d
711 var state : int
712 var index : int
713 var description : String
714
715 func check_space(tokens : Array, index : int, space) -> int:
716 if get_token_id(tokens, index) == TOKEN_ID.SPACE:
717 if space == SP.MAYBE:
718 return 1
719 elif space == SP.MUST:
720 return 1
721 elif space == SP.NO:
722 return -1
723 else:
724 if space == SP.MUST:
725 return -2
726 return 0
727
728 class IndexedToken:
729 func _init(t : TokenEntrance, i : int):
730 token = t
731 index = i
732 var token : TokenEntrance
733 var index : int
734
735 func token_importance_checkadd(template : ASD, token : TokenEntrance, index : int, importance : Array) -> void:
736 if template.importance:
737 importance.append(IndexedToken.new(token, index))
738
739 class CompareSettings:
740 func _init(ci : int, n : int, pi : int, pn : String = ""):
741 construction_index = ci
742 nesting = n
743 parent_index = pi
744 parent_name = pn
745
746 var construction_index : int
747 var nesting : int
748 var parent_index : int
749 var parent_name : String
750
751 func description_compare(template : Array, tokens : Array, index : int, settings : CompareSettings) -> TokenCompare:
752 var j : int = index
753 var space : int
754 var rule : int
755 var rule_flag : bool
756 var cont : bool
757 var check : int
758 var maybe_group_skip : bool = false
759 var any_group_index : int = -1
760 var any_end_group_index : int = -1
761 var i : int = 0
762 var importance : Array = []
763 while true:
764 i += 1
765 if i >= template.size():
766 break
767 rule_flag = false
768 cont = false
769 rule = template[i].rule
770 space = template[i].space
771 if rule == AR.MAYBE_END && maybe_group_skip:
772 maybe_group_skip = false
773 continue
774 if maybe_group_skip:
775 continue
776 if rule == AR.MAYBE:
777 if template[i].token == get_token_id(tokens, j):
778 token_importance_checkadd(template[i], tokens[j], j, importance)
779 rule_flag = true
780 else:
781 continue
782 elif rule == AR.MUST_ONE || rule == AR.MAYBE_END || rule == AR.ANY_END:
783 if template[i].token == get_token_id(tokens, j):
784 token_importance_checkadd(template[i], tokens[j], j, importance)
785 rule_flag = true
786 elif rule == AR.ANY:
787 var find_any : bool = false
788 while true:
789 if template[i].token == get_token_id(tokens, j):
790 token_importance_checkadd(template[i], tokens[j], j, importance)
791 find_any = true
792 j += 1
793 check = check_space(tokens, j, space)
794 if check < 0:
795 return TokenCompare.new(COMPARE_STATE.INCOMPLETE, j)
796 else:
797 j += check
798 else:
799 if find_any:
800 cont = true
801 break
802 elif rule == AR.OR:
803 var or_tokens = template[i].token
804 for v in or_tokens:
805 if v == get_token_id(tokens, j):
806 token_importance_checkadd(template[i], tokens[j], j, importance)
807 j += 1
808 check = check_space(tokens, j, space)
809 if check < 0:
810 return TokenCompare.new(COMPARE_STATE.INCOMPLETE, j)
811 else:
812 j += check
813 cont = true
814 break
815 elif rule == AR.MAYBE_BEGIN:
816 if template[i].token == get_token_id(tokens, j):
817 token_importance_checkadd(template[i], tokens[j], j, importance)
818 rule_flag = true
819 else:
820 maybe_group_skip = true
821 continue
822 elif rule == AR.ANY_BEGIN:
823 if template[i].token == get_token_id(tokens, j):
824 token_importance_checkadd(template[i], tokens[j], j, importance)
825 rule_flag = true
826 any_group_index = i
827 else:
828 if any_end_group_index > 0:
829 any_group_index = -1
830 i = any_end_group_index
831 any_end_group_index = -1
832 continue
833 if cont:
834 continue
835 if rule_flag:
836 j += 1
837 check = check_space(tokens, j, space)
838 if check < 0:
839 return TokenCompare.new(COMPARE_STATE.INCOMPLETE, j)
840 else:
841 j += check
842 else:
843 if j > index:
844 return TokenCompare.new(COMPARE_STATE.INCOMPLETE, j)
845 else:
846 return TokenCompare.new(COMPARE_STATE.MISMATCH, j)
847 if any_group_index >= 0 && rule == AR.ANY_END:
848 any_end_group_index = i
849 i = any_group_index - 1
850 if template[0] != null:
851 var result : DescriptionResult = template[0].call(importance, settings)
852 if !result.success:
853 return TokenCompare.new(COMPARE_STATE.ERROR_VALUE, result.error, result.description)
854 return TokenCompare.new(COMPARE_STATE.DONE, j)
855
856 var DESCRIPTION : Array = [
857 TEMPLATE_BEGIN, #0
858 TEMPLATE_SYNTAX, #1
859 TEMPLATE_IMPORT, #2
860 TEMPLATE_PACKAGE, #3
861 TEMPLATE_OPTION, #4
862 TEMPLATE_FIELD, #5
863 TEMPLATE_FIELD_ONEOF, #6
864 TEMPLATE_MAP_FIELD, #7
865 TEMPLATE_MAP_FIELD_ONEOF, #8
866 TEMPLATE_ENUM, #9
867 TEMPLATE_MESSAGE_HEAD, #10
868 TEMPLATE_MESSAGE_TAIL, #11
869 TEMPLATE_ONEOF_HEAD, #12
870 TEMPLATE_ONEOF_TAIL, #13
871 TEMPLATE_END #14
872 ]
873
874 enum JUMP {
875 NOTHING = 0, #nothing
876 SIMPLE = 1, #simple jump
877 NESTED_INCREMENT = 2, #nested increment
878 NESTED_DECREMENT = 3, #nested decrement
879 MUST_NESTED_SIMPLE = 4, #check: must be nested > 0
880 MUST_NESTED_INCREMENT = 5, #check: must be nested > 0, then nested increment
881 MUST_NESTED_DECREMENT = 6, #nested decrement, then check: must be nested > 0
882 }
883
884 var TRANSLATION_TABLE : Array = [
885 # BEGIN SYNTAX IMPORT PACKAGE OPTION FIELD FIELD_O MAP_F MAP_F_O ENUM MES_H MES_T ONEOF_H ONEOF_T END
886 [ 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], #BEGIN
887 [ 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 2, 0, 0, 0, 1], #SYNTAX
888 [ 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 2, 0, 0, 0, 1], #IMPORT
889 [ 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 2, 0, 0, 0, 1], #PACKAGE
890 [ 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 2, 0, 0, 0, 1], #OPTION
891 [ 0, 0, 0, 0, 0, 4, 0, 4, 0, 1, 2, 3, 5, 0, 0], #FIELD
892 [ 0, 0, 0, 0, 0, 0, 4, 0, 4, 0, 0, 0, 0, 6, 0], #FIELD_ONEOF
893 [ 0, 0, 0, 0, 0, 4, 0, 4, 0, 1, 2, 3, 5, 0, 0], #MAP_F
894 [ 0, 0, 0, 0, 0, 0, 4, 0, 4, 0, 0, 0, 0, 6, 0], #MAP_F_ONEOF
895 [ 0, 0, 0, 0, 0, 4, 0, 4, 0, 1, 2, 3, 5, 0, 1], #ENUM
896 [ 0, 0, 0, 0, 0, 4, 0, 4, 0, 1, 2, 3, 5, 0, 0], #MES_H
897 [ 0, 0, 0, 0, 0, 4, 0, 4, 0, 1, 2, 3, 5, 0, 1], #MES_T
898 [ 0, 0, 0, 0, 0, 0, 4, 0, 4, 0, 0, 0, 0, 0, 0], #ONEOF_H
899 [ 0, 0, 0, 0, 0, 4, 0, 4, 0, 1, 2, 3, 5, 0, 1], #ONEOF_T
900 [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] #END
901 ]
902
903 class Construction:
904 func _init(b : int, e : int, d : int):
905 begin_token_index = b
906 end_token_index = e
907 description = d
908 var begin_token_index : int
909 var end_token_index : int
910 var description : int
911
912 class TranslationResult:
913 var constructions : Array = []
914 var done : bool = false
915 var error_description_id : int = -1
916 var error_description_text : String = ""
917 var parse_token_index : int = 0
918 var error_token_index : int = 0
919
920 func analyze_tokens(tokens : Array) -> TranslationResult:
921 var i : int = 0
922 var result : TranslationResult = TranslationResult.new()
923 var comp : TokenCompare
924 var cur_template_id : int = 0
925 var error : bool = false
926 var template_index : int
927 var comp_set : CompareSettings = CompareSettings.new(result.constructions.size(), 0, -1)
928 comp = description_compare(DESCRIPTION[cur_template_id], tokens, i, comp_set)
929 if comp.state == COMPARE_STATE.DONE:
930 i = comp.index
931 while true:
932 var end : bool = true
933 var find : bool = false
934 for j in range(TRANSLATION_TABLE[cur_template_id].size()):
935 template_index = j
936 if j == DESCRIPTION.size() - 1 && i < tokens.size():
937 end = false
938 if result.error_description_id < 0:
939 error = true
940 break
941 if TRANSLATION_TABLE[cur_template_id][j] > 0:
942 end = false
943 comp_set.construction_index = result.constructions.size()
944 comp = description_compare(DESCRIPTION[j], tokens, i, comp_set)
945 if comp.state == COMPARE_STATE.DONE:
946 if TRANSLATION_TABLE[cur_template_id][j] == JUMP.NESTED_INCREMENT:
947 comp_set.nesting += 1
948 elif TRANSLATION_TABLE[cur_template_id][j] == JUMP.NESTED_DECREMENT:
949 comp_set.nesting -= 1
950 if comp_set.nesting < 0:
951 error = true
952 break
953 elif TRANSLATION_TABLE[cur_template_id][j] == JUMP.MUST_NESTED_SIMPLE:
954 if comp_set.nesting <= 0:
955 error = true
956 break
957 elif TRANSLATION_TABLE[cur_template_id][j] == JUMP.MUST_NESTED_INCREMENT:
958 if comp_set.nesting <= 0:
959 error = true
960 break
961 comp_set.nesting += 1
962 elif TRANSLATION_TABLE[cur_template_id][j] == JUMP.MUST_NESTED_DECREMENT:
963 comp_set.nesting -= 1
964 if comp_set.nesting <= 0:
965 error = true
966 break
967 result.constructions.append(Construction.new(i, comp.index, j))
968 find = true
969 i = comp.index
970 cur_template_id = j
971 if i == tokens.size():
972 if TRANSLATION_TABLE[cur_template_id][DESCRIPTION.size() - 1] == JUMP.SIMPLE:
973 if comp_set.nesting == 0:
974 end = true
975 else:
976 error = true
977 else:
978 error = true
979 elif i > tokens.size():
980 error = true
981 break
982 elif comp.state == COMPARE_STATE.INCOMPLETE:
983 error = true
984 break
985 elif comp.state == COMPARE_STATE.ERROR_VALUE:
986 error = true
987 break
988 if error:
989 result.error_description_text = comp.description
990 result.error_description_id = template_index
991 result.parse_token_index = i
992 if comp.index >= tokens.size():
993 result.error_token_index = tokens.size() - 1
994 else:
995 result.error_token_index = comp.index
996 if end:
997 result.done = true
998 result.error_description_id = -1
999 break
1000 if !find:
1001 break
1002 return result
1003
1004 enum CLASS_TYPE {
1005 ENUM = 0,
1006 MESSAGE = 1,
1007 MAP = 2
1008 }
1009
1010 enum FIELD_TYPE {
1011 UNDEFINED = -1,
1012 INT32 = 0,
1013 SINT32 = 1,
1014 UINT32 = 2,
1015 INT64 = 3,
1016 SINT64 = 4,
1017 UINT64 = 5,
1018 BOOL = 6,
1019 ENUM = 7,
1020 FIXED32 = 8,
1021 SFIXED32 = 9,
1022 FLOAT = 10,
1023 FIXED64 = 11,
1024 SFIXED64 = 12,
1025 DOUBLE = 13,
1026 STRING = 14,
1027 BYTES = 15,
1028 MESSAGE = 16,
1029 MAP = 17
1030 }
1031
1032 enum FIELD_QUALIFICATOR {
1033 OPTIONAL = 0,
1034 REQUIRED = 1,
1035 REPEATED = 2,
1036 RESERVED = 3
1037 }
1038
1039 enum FIELD_OPTION {
1040 PACKED = 0,
1041 NOT_PACKED = 1
1042 }
1043
1044 class ASTClass:
1045 func _init(n : String, t : int, p : int, pn : String, o : String, ci : int):
1046 name = n
1047 type = t
1048 parent_index = p
1049 parent_name = pn
1050 option = o
1051 construction_index = ci
1052 values = []
1053
1054 var name : String
1055 var type : int
1056 var parent_index : int
1057 var parent_name : String
1058 var option : String
1059 var construction_index
1060 var values : Array
1061
1062 func copy() -> ASTClass:
1063 var res : ASTClass = ASTClass.new(name, type, parent_index, parent_name, option, construction_index)
1064 for v in values:
1065 res.values.append(v.copy())
1066 return res
1067
1068 class ASTEnumValue:
1069 func _init(n : String, v : String):
1070 name = n
1071 value = v
1072
1073 var name : String
1074 var value : String
1075
1076 func copy() -> ASTEnumValue:
1077 return ASTEnumValue.new(name, value)
1078
1079 class ASTField:
1080 func _init(t, n : String, tn : String, p : int, q : int, o : int, ci : int, mf : bool):
1081 tag = t
1082 name = n
1083 type_name = tn
1084 parent_class_id = p
1085 qualificator = q
1086 option = o
1087 construction_index = ci
1088 is_map_field = mf
1089
1090 var tag
1091 var name : String
1092 var type_name : String
1093 var parent_class_id : int
1094 var qualificator : int
1095 var option : int
1096 var construction_index : int
1097 var is_map_field : bool
1098 var field_type : int = FIELD_TYPE.UNDEFINED
1099 var type_class_id : int = -1
1100
1101 func copy() -> ASTField:
1102 var res : ASTField = ASTField.new(tag, name, type_name, parent_class_id, qualificator, option, construction_index, is_map_field)
1103 res.field_type = field_type
1104 res.type_class_id = type_class_id
1105 return res
1106
1107 enum AST_GROUP_RULE {
1108 ONEOF = 0,
1109 ALL = 1
1110 }
1111
1112 class ASTFieldGroup:
1113 func _init(n : String, pi : int, r : int):
1114 name = n
1115 parent_class_id = pi
1116 rule = r
1117 opened = true
1118
1119 var name : String
1120 var parent_class_id : int
1121 var rule : int
1122 var field_indexes : Array = []
1123 var opened : bool
1124
1125 func copy() -> ASTFieldGroup:
1126 var res : ASTFieldGroup = ASTFieldGroup.new(name, parent_class_id, rule)
1127 res.opened = opened
1128 for fi in field_indexes:
1129 res.field_indexes.append(fi)
1130 return res
1131
1132 class ASTImport:
1133 func _init(a_path : String, a_public : bool, sha : String):
1134 path = a_path
1135 public = a_public
1136 sha256 = sha
1137
1138 var path : String
1139 var public : bool
1140 var sha256 : String
1141
1142 var class_table : Array = []
1143 var field_table : Array = []
1144 var group_table : Array = []
1145 var import_table : Array = []
1146 var proto_version : int = 0
1147
1148 class DescriptionResult:
1149 func _init(s : bool = true, e = null, d : String = ""):
1150 success = s
1151 error = e
1152 description = d
1153 var success : bool
1154 var error
1155 var description : String
1156
1157 static func get_text_from_token(string_token : TokenEntrance) -> String:
1158 return string_token.text.substr(1, string_token.text.length() - 2)
1159
1160 func desc_syntax(indexed_tokens : Array, settings : CompareSettings) -> DescriptionResult:
1161 var result : DescriptionResult = DescriptionResult.new()
1162 var s : String = get_text_from_token(indexed_tokens[0].token)
1163 if s == "proto2":
1164 proto_version = 2
1165 elif s == "proto3":
1166 proto_version = 3
1167 else:
1168 result.success = false
1169 result.error = indexed_tokens[0].index
1170 result.description = "Unspecified version of the protocol. Use \"proto2\" or \"proto3\" syntax string."
1171 return result
1172
1173 func desc_import(indexed_tokens : Array, settings : CompareSettings) -> DescriptionResult:
1174 var result : DescriptionResult = DescriptionResult.new()
1175 var offset : int = 0
1176 var public : bool = false
1177 if indexed_tokens[offset].token.id == TOKEN_ID.IMPORT_QUALIFICATION:
1178 if indexed_tokens[offset].token.text == "public":
1179 public = true
1180 offset += 1
1181 var f_name : String = path_dir + get_text_from_token(indexed_tokens[offset].token)
1182 var sha : String = FileAccess.get_sha256(f_name)
1183 if FileAccess.file_exists(f_name):
1184 for i in import_table:
1185 if i.path == f_name:
1186 result.success = false
1187 result.error = indexed_tokens[offset].index
1188 result.description = "File '" + f_name + "' already imported."
1189 return result
1190 if i.sha256 == sha:
1191 result.success = false
1192 result.error = indexed_tokens[offset].index
1193 result.description = "File '" + f_name + "' with matching SHA256 already imported."
1194 return result
1195 import_table.append(ASTImport.new(f_name, public, sha))
1196 else:
1197 result.success = false
1198 result.error = indexed_tokens[offset].index
1199 result.description = "Import file '" + f_name + "' not found."
1200 return result
1201
1202 func desc_package(indexed_tokens : Array, settings : CompareSettings) -> DescriptionResult:
1203 printerr("UNRELEASED desc_package: ", indexed_tokens.size(), ", nesting: ", settings.nesting)
1204 var result : DescriptionResult = DescriptionResult.new()
1205 return result
1206
1207 func desc_option(indexed_tokens : Array, settings : CompareSettings) -> DescriptionResult:
1208 printerr("UNRELEASED desc_option: ", indexed_tokens.size(), ", nesting: ", settings.nesting)
1209 var result : DescriptionResult = DescriptionResult.new()
1210 return result
1211
1212 func desc_field(indexed_tokens : Array, settings : CompareSettings) -> DescriptionResult:
1213 var result : DescriptionResult = DescriptionResult.new()
1214 var qualifcator : int = FIELD_QUALIFICATOR.OPTIONAL
1215 var option : int
1216 var offset : int = 0
1217
1218 if proto_version == 3:
1219 option = FIELD_OPTION.PACKED
1220 if indexed_tokens[offset].token.id == TOKEN_ID.FIELD_QUALIFICATION:
1221 if indexed_tokens[offset].token.text == "repeated":
1222 qualifcator = FIELD_QUALIFICATOR.REPEATED
1223 elif indexed_tokens[offset].token.text == "required" || indexed_tokens[offset].token.text == "optional":
1224 result.success = false
1225 result.error = indexed_tokens[offset].index
1226 result.description = "Using the 'required' or 'optional' qualificator is unacceptable in Protobuf v3."
1227 return result
1228 offset += 1
1229 if proto_version == 2:
1230 option = FIELD_OPTION.NOT_PACKED
1231 if !(group_table.size() > 0 && group_table[group_table.size() - 1].opened):
1232 if indexed_tokens[offset].token.id == TOKEN_ID.FIELD_QUALIFICATION:
1233 if indexed_tokens[offset].token.text == "repeated":
1234 qualifcator = FIELD_QUALIFICATOR.REPEATED
1235 elif indexed_tokens[offset].token.text == "required":
1236 qualifcator = FIELD_QUALIFICATOR.REQUIRED
1237 elif indexed_tokens[offset].token.text == "optional":
1238 qualifcator = FIELD_QUALIFICATOR.OPTIONAL
1239 offset += 1
1240 else:
1241 if class_table[settings.parent_index].type == CLASS_TYPE.MESSAGE:
1242 result.success = false
1243 result.error = indexed_tokens[offset].index
1244 result.description = "Using the 'required', 'optional' or 'repeated' qualificator necessarily in Protobuf v2."
1245 return result
1246 var type_name : String = indexed_tokens[offset].token.text; offset += 1
1247 var field_name : String = indexed_tokens[offset].token.text; offset += 1
1248 var tag : String = indexed_tokens[offset].token.text; offset += 1
1249
1250 if indexed_tokens.size() == offset + 2:
1251 if indexed_tokens[offset].token.text == "packed":
1252 offset += 1
1253 if indexed_tokens[offset].token.text == "true":
1254 option = FIELD_OPTION.PACKED
1255 else:
1256 option = FIELD_OPTION.NOT_PACKED
1257 else:
1258 result.success = false
1259 result.error = indexed_tokens[offset].index
1260 result.description = "Undefined field option."
1261 return result
1262
1263 if group_table.size() > 0:
1264 if group_table[group_table.size() - 1].opened:
1265 if indexed_tokens[0].token.id == TOKEN_ID.FIELD_QUALIFICATION:
1266 result.success = false
1267 result.error = indexed_tokens[0].index
1268 result.description = "Using the 'required', 'optional' or 'repeated' qualificator is unacceptable in 'OneOf' field."
1269 return result
1270 group_table[group_table.size() - 1].field_indexes.append(field_table.size())
1271 field_table.append(ASTField.new(tag, field_name, type_name, settings.parent_index, qualifcator, option, settings.construction_index, false))
1272 return result
1273
1274 func desc_map_field(indexed_tokens : Array, settings : CompareSettings) -> DescriptionResult:
1275 var result : DescriptionResult = DescriptionResult.new()
1276 var qualifcator : int = FIELD_QUALIFICATOR.REPEATED
1277 var option : int
1278 var offset : int = 0
1279
1280 if proto_version == 3:
1281 option = FIELD_OPTION.PACKED
1282 if proto_version == 2:
1283 option = FIELD_OPTION.NOT_PACKED
1284
1285 var key_type_name : String = indexed_tokens[offset].token.text; offset += 1
1286 if key_type_name == "float" || key_type_name == "double" || key_type_name == "bytes":
1287 result.success = false
1288 result.error = indexed_tokens[offset - 1].index
1289 result.description = "Map 'key_type' can't be floating point types and bytes."
1290 var type_name : String = indexed_tokens[offset].token.text; offset += 1
1291 var field_name : String = indexed_tokens[offset].token.text; offset += 1
1292 var tag : String = indexed_tokens[offset].token.text; offset += 1
1293
1294 if indexed_tokens.size() == offset + 2:
1295 if indexed_tokens[offset].token.text == "packed":
1296 offset += 1
1297 if indexed_tokens[offset] == "true":
1298 option = FIELD_OPTION.PACKED
1299 else:
1300 option = FIELD_OPTION.NOT_PACKED
1301 else:
1302 result.success = false
1303 result.error = indexed_tokens[offset].index
1304 result.description = "Undefined field option."
1305
1306 if group_table.size() > 0:
1307 if group_table[group_table.size() - 1].opened:
1308 group_table[group_table.size() - 1].field_indexes.append(field_table.size())
1309
1310 class_table.append(ASTClass.new("map_type_" + field_name, CLASS_TYPE.MAP, settings.parent_index, settings.parent_name, "", settings.construction_index))
1311 field_table.append(ASTField.new(tag, field_name, "map_type_" + field_name, settings.parent_index, qualifcator, option, settings.construction_index, false))
1312
1313 field_table.append(ASTField.new(1, "key", key_type_name, class_table.size() - 1, FIELD_QUALIFICATOR.OPTIONAL, option, settings.construction_index, true))
1314 field_table.append(ASTField.new(2, "value", type_name, class_table.size() - 1, FIELD_QUALIFICATOR.OPTIONAL, option, settings.construction_index, true))
1315
1316 return result
1317
1318 func desc_enum(indexed_tokens : Array, settings : CompareSettings) -> DescriptionResult:
1319 var result : DescriptionResult = DescriptionResult.new()
1320 var option : String = ""
1321 var offset : int = 0
1322 var type_name : String = indexed_tokens[offset].token.text; offset += 1
1323 if indexed_tokens[offset].token.id == TOKEN_ID.ENUM_OPTION:
1324 if indexed_tokens[offset].token.text == "allow_alias" && indexed_tokens[offset + 1].token.text == "true":
1325 option = "allow_alias"
1326 offset += 2
1327 var value : ASTEnumValue
1328 var enum_class : ASTClass = ASTClass.new(type_name, CLASS_TYPE.ENUM, settings.parent_index, settings.parent_name, option, settings.construction_index)
1329 var first_value : bool = true
1330 while offset < indexed_tokens.size():
1331 if first_value:
1332 if indexed_tokens[offset + 1].token.text != "0":
1333 result.success = false
1334 result.error = indexed_tokens[offset + 1].index
1335 result.description = "For Enums, the default value is the first defined enum value, which must be 0."
1336 break
1337 first_value = false
1338 #if indexed_tokens[offset + 1].token.text[0] == "+" || indexed_tokens[offset + 1].token.text[0] == "-":
1339 # result.success = false
1340 # result.error = indexed_tokens[offset + 1].index
1341 # result.description = "For Enums, signed values are not allowed."
1342 # break
1343 value = ASTEnumValue.new(indexed_tokens[offset].token.text, indexed_tokens[offset + 1].token.text)
1344 enum_class.values.append(value)
1345 offset += 2
1346
1347 class_table.append(enum_class)
1348 return result
1349
1350 func desc_message_head(indexed_tokens : Array, settings : CompareSettings) -> DescriptionResult:
1351 var result : DescriptionResult = DescriptionResult.new()
1352 class_table.append(ASTClass.new(indexed_tokens[0].token.text, CLASS_TYPE.MESSAGE, settings.parent_index, settings.parent_name, "", settings.construction_index))
1353 settings.parent_index = class_table.size() - 1
1354 settings.parent_name = settings.parent_name + "." + indexed_tokens[0].token.text
1355 return result
1356
1357 func desc_message_tail(indexed_tokens : Array, settings : CompareSettings) -> DescriptionResult:
1358 settings.parent_index = class_table[settings.parent_index].parent_index
1359 settings.parent_name = class_table[settings.parent_index + 1].parent_name
1360 var result : DescriptionResult = DescriptionResult.new()
1361 return result
1362
1363 func desc_oneof_head(indexed_tokens : Array, settings : CompareSettings) -> DescriptionResult:
1364 var result : DescriptionResult = DescriptionResult.new()
1365 for g in group_table:
1366 if g.parent_class_id == settings.parent_index && g.name == indexed_tokens[0].token.text:
1367 result.success = false
1368 result.error = indexed_tokens[0].index
1369 result.description = "OneOf name must be unique."
1370 return result
1371 group_table.append(ASTFieldGroup.new(indexed_tokens[0].token.text, settings.parent_index, AST_GROUP_RULE.ONEOF))
1372 return result
1373
1374 func desc_oneof_tail(indexed_tokens : Array, settings : CompareSettings) -> DescriptionResult:
1375 group_table[group_table.size() - 1].opened = false
1376 var result : DescriptionResult = DescriptionResult.new()
1377 return result
1378
1379 func analyze() -> AnalyzeResult:
1380 var analyze_result : AnalyzeResult = AnalyzeResult.new()
1381 analyze_result.doc = document
1382 analyze_result.classes = class_table
1383 analyze_result.fields = field_table
1384 analyze_result.groups = group_table
1385 analyze_result.state = false
1386 var result : TokenResult = tokenizer()
1387 if result.errors.size() > 0:
1388 for v in result.errors:
1389 var spos : Helper.StringPosition = Helper.str_pos(document.text, v.position)
1390 var err_text : String = "Unexpected token intersection " + "'" + document.text.substr(v.position.begin, spos.length) + "'"
1391 printerr(Helper.error_string(document.name, spos.str_num, spos.column, err_text))
1392 else:
1393 var integrity = check_tokens_integrity(result.tokens, document.text.length() - 1)
1394 if integrity.size() > 0:
1395 for v in integrity:
1396 var spos: Helper.StringPosition = Helper.str_pos(document.text, TokenPosition.new(v.begin, v.end))
1397 var err_text : String = "Unexpected token " + "'" + document.text.substr(v.begin, spos.length) + "'"
1398 printerr(Helper.error_string(document.name, spos.str_num, spos.column, err_text))
1399 else:
1400 analyze_result.tokens = result.tokens
1401 comment_space_processing(result.tokens)
1402 var syntax : TranslationResult = analyze_tokens(result.tokens)
1403 if !syntax.done:
1404 var pos_main : TokenPosition = Helper.text_pos(result.tokens, syntax.parse_token_index)
1405 var pos_inner : TokenPosition = Helper.text_pos(result.tokens, syntax.error_token_index)
1406 var spos_main : Helper.StringPosition = Helper.str_pos(document.text, pos_main)
1407 var spos_inner : Helper.StringPosition = Helper.str_pos(document.text, pos_inner)
1408 var err_text : String = "Syntax error in construction '" + result.tokens[syntax.parse_token_index].text + "'. "
1409 err_text += "Unacceptable use '" + result.tokens[syntax.error_token_index].text + "' at:" + str(spos_inner.str_num) + ":" + str(spos_inner.column)
1410 err_text += "\n" + syntax.error_description_text
1411 printerr(Helper.error_string(document.name, spos_main.str_num, spos_main.column, err_text))
1412 else:
1413 analyze_result.version = proto_version
1414 analyze_result.imports = import_table
1415 analyze_result.syntax = syntax
1416 analyze_result.state = true
1417 return analyze_result
1418
1419class Semantic:
1420
1421 var class_table : Array
1422 var field_table : Array
1423 var group_table : Array
1424 var syntax : Analysis.TranslationResult
1425 var tokens : Array
1426 var document : Document
1427
1428 func _init(analyze_result : AnalyzeResult):
1429 class_table = analyze_result.classes
1430 field_table = analyze_result.fields
1431 group_table = analyze_result.groups
1432 syntax = analyze_result.syntax
1433 tokens = analyze_result.tokens
1434 document = analyze_result.doc
1435
1436
1437 enum CHECK_SUBJECT {
1438 CLASS_NAME = 0,
1439 FIELD_NAME = 1,
1440 FIELD_TAG_NUMBER = 2,
1441 FIELD_TYPE = 3
1442 }
1443
1444 var STRING_FIELD_TYPE = {
1445 "int32": Analysis.FIELD_TYPE.INT32,
1446 "sint32": Analysis.FIELD_TYPE.SINT32,
1447 "uint32": Analysis.FIELD_TYPE.UINT32,
1448 "int64": Analysis.FIELD_TYPE.INT64,
1449 "sint64": Analysis.FIELD_TYPE.SINT64,
1450 "uint64": Analysis.FIELD_TYPE.UINT64,
1451 "bool": Analysis.FIELD_TYPE.BOOL,
1452 "fixed32": Analysis.FIELD_TYPE.FIXED32,
1453 "sfixed32": Analysis.FIELD_TYPE.SFIXED32,
1454 "float": Analysis.FIELD_TYPE.FLOAT,
1455 "fixed64": Analysis.FIELD_TYPE.FIXED64,
1456 "sfixed64": Analysis.FIELD_TYPE.SFIXED64,
1457 "double": Analysis.FIELD_TYPE.DOUBLE,
1458 "string": Analysis.FIELD_TYPE.STRING,
1459 "bytes": Analysis.FIELD_TYPE.BYTES,
1460 "map": Analysis.FIELD_TYPE.MAP
1461 }
1462
1463 class CheckResult:
1464 func _init(mci : int, aci : int, ti : int, s : int):
1465 main_construction_index = mci
1466 associated_construction_index = aci
1467 table_index = ti
1468 subject = s
1469
1470 var main_construction_index: int = -1
1471 var associated_construction_index: int = -1
1472 var table_index: int = -1
1473 var subject : int
1474
1475 func check_class_names() -> Array:
1476 var result : Array = []
1477 for i in range(class_table.size()):
1478 var the_class_name : String = class_table[i].parent_name + "." + class_table[i].name
1479 for j in range(i + 1, class_table.size(), 1):
1480 var inner_name : String = class_table[j].parent_name + "." + class_table[j].name
1481 if inner_name == the_class_name:
1482 var check : CheckResult = CheckResult.new(class_table[j].construction_index, class_table[i].construction_index, j, CHECK_SUBJECT.CLASS_NAME)
1483 result.append(check)
1484 break
1485 return result
1486
1487 func check_field_names() -> Array:
1488 var result : Array = []
1489 for i in range(field_table.size()):
1490 var the_class_name : String = class_table[field_table[i].parent_class_id].parent_name + "." + class_table[field_table[i].parent_class_id].name
1491 for j in range(i + 1, field_table.size(), 1):
1492 var inner_name : String = class_table[field_table[j].parent_class_id].parent_name + "." + class_table[field_table[j].parent_class_id].name
1493 if inner_name == the_class_name:
1494 if field_table[i].name == field_table[j].name:
1495 var check : CheckResult = CheckResult.new(field_table[j].construction_index, field_table[i].construction_index, j, CHECK_SUBJECT.FIELD_NAME)
1496 result.append(check)
1497 break
1498 if field_table[i].tag == field_table[j].tag:
1499 var check : CheckResult = CheckResult.new(field_table[j].construction_index, field_table[i].construction_index, j, CHECK_SUBJECT.FIELD_TAG_NUMBER)
1500 result.append(check)
1501 break
1502 return result
1503
1504 func find_full_class_name(the_class_name : String) -> int:
1505 for i in range(class_table.size()):
1506 if the_class_name == class_table[i].parent_name + "." + class_table[i].name:
1507 return i
1508 return -1
1509
1510 func find_class_name(the_class_name : String) -> int:
1511 for i in range(class_table.size()):
1512 if the_class_name == class_table[i].name:
1513 return i
1514 return -1
1515
1516 func get_class_childs(class_index : int) -> Array:
1517 var result : Array = []
1518 for i in range(class_table.size()):
1519 if class_table[i].parent_index == class_index:
1520 result.append(i)
1521 return result
1522
1523 func find_in_childs(the_class_name : String, child_indexes : Array) -> int:
1524 for c in child_indexes:
1525 if the_class_name == class_table[c].name:
1526 return c
1527 return -1
1528
1529 func determine_field_types() -> Array:
1530 var result : Array = []
1531 for f in field_table:
1532 if STRING_FIELD_TYPE.has(f.type_name):
1533 f.field_type = STRING_FIELD_TYPE[f.type_name]
1534 else:
1535 if f.type_name[0] == ".":
1536 f.type_class_id = find_full_class_name(f.type_name)
1537 else:
1538 # Reset result from previous assignment, that can be incorrect because of merging of imports
1539 f.type_class_id = -1
1540 var splited_name : Array = f.type_name.split(".", false)
1541 var cur_class_index : int = f.parent_class_id
1542 var exit : bool = false
1543 while(true):
1544 var find : bool = false
1545 if cur_class_index == -1:
1546 break
1547 for n in splited_name:
1548 var childs_and_parent : Array = get_class_childs(cur_class_index)
1549 var res_index : int = find_in_childs(n, childs_and_parent)
1550 if res_index >= 0:
1551 find = true
1552 cur_class_index = res_index
1553 else:
1554 if find:
1555 exit = true
1556 else:
1557 cur_class_index = class_table[cur_class_index].parent_index
1558 break
1559 if exit:
1560 break
1561 if find:
1562 f.type_class_id = cur_class_index
1563 break
1564 if f.type_class_id == -1:
1565 f.type_class_id = find_full_class_name("." + f.type_name)
1566 for i in range(field_table.size()):
1567 if field_table[i].field_type == Analysis.FIELD_TYPE.UNDEFINED:
1568 if field_table[i].type_class_id == -1:
1569 result.append(CheckResult.new(field_table[i].construction_index, field_table[i].construction_index, i, CHECK_SUBJECT.FIELD_TYPE))
1570 else:
1571 if class_table[field_table[i].type_class_id].type == Analysis.CLASS_TYPE.ENUM:
1572 field_table[i].field_type = Analysis.FIELD_TYPE.ENUM
1573 elif class_table[field_table[i].type_class_id].type == Analysis.CLASS_TYPE.MESSAGE:
1574 field_table[i].field_type = Analysis.FIELD_TYPE.MESSAGE
1575 elif class_table[field_table[i].type_class_id].type == Analysis.CLASS_TYPE.MAP:
1576 field_table[i].field_type = Analysis.FIELD_TYPE.MAP
1577 else:
1578 result.append(CheckResult.new(field_table[i].construction_index, field_table[i].construction_index, i, CHECK_SUBJECT.FIELD_TYPE))
1579 return result
1580
1581 func check_constructions() -> Array:
1582 var cl : Array = check_class_names()
1583 var fl : Array = check_field_names()
1584 var ft : Array = determine_field_types()
1585 return cl + fl + ft
1586
1587 func check() -> bool:
1588 var check_result : Array = check_constructions()
1589 if check_result.size() == 0:
1590 return true
1591 else:
1592 for v in check_result:
1593 var main_tok : int = syntax.constructions[v.main_construction_index].begin_token_index
1594 var assoc_tok : int = syntax.constructions[v.associated_construction_index].begin_token_index
1595 var main_err_pos : Helper.StringPosition = Helper.str_pos(document.text, Helper.text_pos(tokens, main_tok))
1596 var assoc_err_pos : Helper.StringPosition = Helper.str_pos(document.text, Helper.text_pos(tokens, assoc_tok))
1597 var err_text : String
1598 if v.subject == CHECK_SUBJECT.CLASS_NAME:
1599 var class_type = "Undefined"
1600 if class_table[v.table_index].type == Analysis.CLASS_TYPE.ENUM:
1601 class_type = "Enum"
1602 elif class_table[v.table_index].type == Analysis.CLASS_TYPE.MESSAGE:
1603 class_type = "Message"
1604 elif class_table[v.table_index].type == Analysis.CLASS_TYPE.MAP:
1605 class_type = "Map"
1606 err_text = class_type + " name '" + class_table[v.table_index].name + "' is already defined at:" + str(assoc_err_pos.str_num) + ":" + str(assoc_err_pos.column)
1607 elif v.subject == CHECK_SUBJECT.FIELD_NAME:
1608 err_text = "Field name '" + field_table[v.table_index].name + "' is already defined at:" + str(assoc_err_pos.str_num) + ":" + str(assoc_err_pos.column)
1609 elif v.subject == CHECK_SUBJECT.FIELD_TAG_NUMBER:
1610 err_text = "Tag number '" + field_table[v.table_index].tag + "' is already defined at:" + str(assoc_err_pos.str_num) + ":" + str(assoc_err_pos.column)
1611 elif v.subject == CHECK_SUBJECT.FIELD_TYPE:
1612 err_text = "Type '" + field_table[v.table_index].type_name + "' of the '" + field_table[v.table_index].name + "' field undefined"
1613 else:
1614 err_text = "Undefined error"
1615 printerr(Helper.error_string(document.name, main_err_pos.str_num, main_err_pos.column, err_text))
1616 return false
1617
1618class Translator:
1619
1620 var class_table : Array
1621 var field_table : Array
1622 var group_table : Array
1623 var proto_version : int
1624
1625 func _init(analyzer_result : AnalyzeResult):
1626 class_table = analyzer_result.classes
1627 field_table = analyzer_result.fields
1628 group_table = analyzer_result.groups
1629 proto_version = analyzer_result.version
1630
1631 func tabulate(text : String, nesting : int) -> String:
1632 var tab : String = ""
1633 for i in range(nesting):
1634 tab += "\t"
1635 return tab + text
1636
1637 func default_dict_text() -> String:
1638 if proto_version == 2:
1639 return "DEFAULT_VALUES_2"
1640 elif proto_version == 3:
1641 return "DEFAULT_VALUES_3"
1642 return "TRANSLATION_ERROR"
1643
1644 func generate_field_type(field : Analysis.ASTField) -> String:
1645 var text : String = "PB_DATA_TYPE."
1646 if field.field_type == Analysis.FIELD_TYPE.INT32:
1647 return text + "INT32"
1648 elif field.field_type == Analysis.FIELD_TYPE.SINT32:
1649 return text + "SINT32"
1650 elif field.field_type == Analysis.FIELD_TYPE.UINT32:
1651 return text + "UINT32"
1652 elif field.field_type == Analysis.FIELD_TYPE.INT64:
1653 return text + "INT64"
1654 elif field.field_type == Analysis.FIELD_TYPE.SINT64:
1655 return text + "SINT64"
1656 elif field.field_type == Analysis.FIELD_TYPE.UINT64:
1657 return text + "UINT64"
1658 elif field.field_type == Analysis.FIELD_TYPE.BOOL:
1659 return text + "BOOL"
1660 elif field.field_type == Analysis.FIELD_TYPE.ENUM:
1661 return text + "ENUM"
1662 elif field.field_type == Analysis.FIELD_TYPE.FIXED32:
1663 return text + "FIXED32"
1664 elif field.field_type == Analysis.FIELD_TYPE.SFIXED32:
1665 return text + "SFIXED32"
1666 elif field.field_type == Analysis.FIELD_TYPE.FLOAT:
1667 return text + "FLOAT"
1668 elif field.field_type == Analysis.FIELD_TYPE.FIXED64:
1669 return text + "FIXED64"
1670 elif field.field_type == Analysis.FIELD_TYPE.SFIXED64:
1671 return text + "SFIXED64"
1672 elif field.field_type == Analysis.FIELD_TYPE.DOUBLE:
1673 return text + "DOUBLE"
1674 elif field.field_type == Analysis.FIELD_TYPE.STRING:
1675 return text + "STRING"
1676 elif field.field_type == Analysis.FIELD_TYPE.BYTES:
1677 return text + "BYTES"
1678 elif field.field_type == Analysis.FIELD_TYPE.MESSAGE:
1679 return text + "MESSAGE"
1680 elif field.field_type == Analysis.FIELD_TYPE.MAP:
1681 return text + "MAP"
1682 return text
1683
1684 func generate_field_rule(field : Analysis.ASTField) -> String:
1685 var text : String = "PB_RULE."
1686 if field.qualificator == Analysis.FIELD_QUALIFICATOR.OPTIONAL:
1687 return text + "OPTIONAL"
1688 elif field.qualificator == Analysis.FIELD_QUALIFICATOR.REQUIRED:
1689 return text + "REQUIRED"
1690 elif field.qualificator == Analysis.FIELD_QUALIFICATOR.REPEATED:
1691 return text + "REPEATED"
1692 elif field.qualificator == Analysis.FIELD_QUALIFICATOR.RESERVED:
1693 return text + "RESERVED"
1694 return text
1695
1696 func generate_gdscript_type(field : Analysis.ASTField) -> String:
1697 if field.field_type == Analysis.FIELD_TYPE.MESSAGE:
1698 var type_name : String = class_table[field.type_class_id].parent_name + "." + class_table[field.type_class_id].name
1699 return type_name.substr(1, type_name.length() - 1)
1700 return generate_gdscript_simple_type(field)
1701
1702 func generate_gdscript_simple_type(field : Analysis.ASTField) -> String:
1703 if field.field_type == Analysis.FIELD_TYPE.INT32:
1704 return "int"
1705 elif field.field_type == Analysis.FIELD_TYPE.SINT32:
1706 return "int"
1707 elif field.field_type == Analysis.FIELD_TYPE.UINT32:
1708 return "int"
1709 elif field.field_type == Analysis.FIELD_TYPE.INT64:
1710 return "int"
1711 elif field.field_type == Analysis.FIELD_TYPE.SINT64:
1712 return "int"
1713 elif field.field_type == Analysis.FIELD_TYPE.UINT64:
1714 return "int"
1715 elif field.field_type == Analysis.FIELD_TYPE.BOOL:
1716 return "bool"
1717 elif field.field_type == Analysis.FIELD_TYPE.ENUM:
1718 return ""
1719 elif field.field_type == Analysis.FIELD_TYPE.FIXED32:
1720 return "int"
1721 elif field.field_type == Analysis.FIELD_TYPE.SFIXED32:
1722 return "int"
1723 elif field.field_type == Analysis.FIELD_TYPE.FLOAT:
1724 return "float"
1725 elif field.field_type == Analysis.FIELD_TYPE.FIXED64:
1726 return "int"
1727 elif field.field_type == Analysis.FIELD_TYPE.SFIXED64:
1728 return "int"
1729 elif field.field_type == Analysis.FIELD_TYPE.DOUBLE:
1730 return "float"
1731 elif field.field_type == Analysis.FIELD_TYPE.STRING:
1732 return "String"
1733 elif field.field_type == Analysis.FIELD_TYPE.BYTES:
1734 return "PackedByteArray"
1735 return ""
1736
1737 func generate_field_constructor(field_index : int, nesting : int) -> String:
1738 var text : String = ""
1739 var f : Analysis.ASTField = field_table[field_index]
1740 var field_name : String = "__" + f.name
1741 var pbfield_text : String
1742 var default_var_name := field_name + "_default"
1743 if f.qualificator == Analysis.FIELD_QUALIFICATOR.REPEATED:
1744 var type_name := generate_gdscript_type(f)
1745 if type_name:
1746 text = tabulate("var %s: Array[%s] = []\n" % [default_var_name, type_name], nesting)
1747 else:
1748 text = tabulate("var %s: Array = []\n" % [default_var_name], nesting)
1749 pbfield_text += field_name + " = PBField.new("
1750 pbfield_text += "\"" + f.name + "\", "
1751 pbfield_text += generate_field_type(f) + ", "
1752 pbfield_text += generate_field_rule(f) + ", "
1753 pbfield_text += str(f.tag) + ", "
1754 if f.option == Analysis.FIELD_OPTION.PACKED:
1755 pbfield_text += "true"
1756 elif f.option == Analysis.FIELD_OPTION.NOT_PACKED:
1757 pbfield_text += "false"
1758 if f.qualificator == Analysis.FIELD_QUALIFICATOR.REPEATED:
1759 pbfield_text += ", " + default_var_name
1760 else:
1761 pbfield_text += ", " + default_dict_text() + "[" + generate_field_type(f) + "]"
1762 pbfield_text += ")\n"
1763 text += tabulate(pbfield_text, nesting)
1764 if f.is_map_field:
1765 text += tabulate(field_name + ".is_map_field = true\n", nesting)
1766 text += tabulate("service = PBServiceField.new()\n", nesting)
1767 text += tabulate("service.field = " + field_name + "\n", nesting)
1768 if f.field_type == Analysis.FIELD_TYPE.MESSAGE:
1769 if f.qualificator == Analysis.FIELD_QUALIFICATOR.REPEATED:
1770 text += tabulate("service.func_ref = Callable(self, \"add_" + f.name + "\")\n", nesting)
1771 else:
1772 text += tabulate("service.func_ref = Callable(self, \"new_" + f.name + "\")\n", nesting)
1773 elif f.field_type == Analysis.FIELD_TYPE.MAP:
1774 text += tabulate("service.func_ref = Callable(self, \"add_empty_" + f.name + "\")\n", nesting)
1775 text += tabulate("data[" + field_name + ".tag] = service\n", nesting)
1776
1777 return text
1778
1779 func generate_group_clear(field_index : int, nesting : int) -> String:
1780 for g in group_table:
1781 var text : String = ""
1782 var find : bool = false
1783 if g.parent_class_id == field_table[field_index].parent_class_id:
1784 for i in g.field_indexes:
1785 if field_index == i:
1786 find = true
1787 text += tabulate("data[" + field_table[i].tag + "].state = PB_SERVICE_STATE.FILLED\n", nesting)
1788 else:
1789 text += tabulate("__" + field_table[i].name + ".value = " + default_dict_text() + "[" + generate_field_type(field_table[i]) + "]\n", nesting)
1790 text += tabulate("data[" + field_table[i].tag + "].state = PB_SERVICE_STATE.UNFILLED\n", nesting)
1791 if find:
1792 return text
1793 return ""
1794
1795 func generate_has_oneof(field_index : int, nesting : int) -> String:
1796 for g in group_table:
1797 var text : String = ""
1798 if g.parent_class_id == field_table[field_index].parent_class_id:
1799 for i in g.field_indexes:
1800 if field_index == i:
1801 text += tabulate("func has_" + field_table[i].name + "() -> bool:\n", nesting)
1802 nesting += 1
1803 text += tabulate("return data[" + field_table[i].tag + "].state == PB_SERVICE_STATE.FILLED\n", nesting)
1804 return text
1805 return ""
1806
1807 func generate_field(field_index : int, nesting : int) -> String:
1808 var text : String = ""
1809 var f : Analysis.ASTField = field_table[field_index]
1810 var varname : String = "__" + f.name
1811 text += tabulate("var " + varname + ": PBField\n", nesting)
1812 if f.field_type == Analysis.FIELD_TYPE.MESSAGE:
1813 var the_class_name : String = class_table[f.type_class_id].parent_name + "." + class_table[f.type_class_id].name
1814 the_class_name = the_class_name.substr(1, the_class_name.length() - 1)
1815 if f.qualificator != Analysis.FIELD_QUALIFICATOR.OPTIONAL:
1816 text += generate_has_oneof(field_index, nesting)
1817 if f.qualificator == Analysis.FIELD_QUALIFICATOR.REPEATED:
1818 text += tabulate("func get_" + f.name + "() -> Array[" + the_class_name + "]:\n", nesting)
1819 else:
1820 if f.qualificator == Analysis.FIELD_QUALIFICATOR.OPTIONAL:
1821 text += tabulate("func has_" + f.name + "() -> bool:\n", nesting)
1822 nesting += 1
1823 text += tabulate("if " + varname + ".value != null:\n", nesting)
1824 nesting += 1
1825 text += tabulate("return true\n", nesting)
1826 nesting -= 1
1827 text += tabulate("return false\n", nesting)
1828 nesting -= 1
1829 text += tabulate("func get_" + f.name + "() -> " + the_class_name + ":\n", nesting)
1830 nesting += 1
1831 text += tabulate("return " + varname + ".value\n", nesting)
1832 nesting -= 1
1833 text += tabulate("func clear_" + f.name + "() -> void:\n", nesting)
1834 nesting += 1
1835 text += tabulate("data[" + str(f.tag) + "].state = PB_SERVICE_STATE.UNFILLED\n", nesting)
1836 if f.qualificator == Analysis.FIELD_QUALIFICATOR.REPEATED:
1837 text += tabulate(varname + ".value.clear()\n", nesting)
1838 nesting -= 1
1839 text += tabulate("func add_" + f.name + "() -> " + the_class_name + ":\n", nesting)
1840 nesting += 1
1841 text += tabulate("var element = " + the_class_name + ".new()\n", nesting)
1842 text += tabulate(varname + ".value.append(element)\n", nesting)
1843 text += tabulate("return element\n", nesting)
1844 else:
1845 text += tabulate(varname + ".value = " + default_dict_text() + "[" + generate_field_type(f) + "]\n", nesting)
1846 nesting -= 1
1847 text += tabulate("func new_" + f.name + "() -> " + the_class_name + ":\n", nesting)
1848 nesting += 1
1849 text += generate_group_clear(field_index, nesting)
1850 text += tabulate(varname + ".value = " + the_class_name + ".new()\n", nesting)
1851 text += tabulate("return " + varname + ".value\n", nesting)
1852 elif f.field_type == Analysis.FIELD_TYPE.MAP:
1853 var the_parent_class_name : String = class_table[f.type_class_id].parent_name
1854 the_parent_class_name = the_parent_class_name.substr(1, the_parent_class_name.length() - 1)
1855 var the_class_name : String = the_parent_class_name + "." + class_table[f.type_class_id].name
1856
1857 text += generate_has_oneof(field_index, nesting)
1858 text += tabulate("func get_raw_" + f.name + "():\n", nesting)
1859 nesting += 1
1860 text += tabulate("return " + varname + ".value\n", nesting)
1861 nesting -= 1
1862 text += tabulate("func get_" + f.name + "():\n", nesting)
1863 nesting += 1
1864 text += tabulate("return PBPacker.construct_map(" + varname + ".value)\n", nesting)
1865 nesting -= 1
1866 text += tabulate("func clear_" + f.name + "():\n", nesting)
1867 nesting += 1
1868 text += tabulate("data[" + str(f.tag) + "].state = PB_SERVICE_STATE.UNFILLED\n", nesting)
1869 text += tabulate(varname + ".value = " + default_dict_text() + "[" + generate_field_type(f) + "]\n", nesting)
1870 nesting -= 1
1871 for i in range(field_table.size()):
1872 if field_table[i].parent_class_id == f.type_class_id && field_table[i].name == "value":
1873 var gd_type : String = generate_gdscript_simple_type(field_table[i])
1874 var return_type : String = " -> " + the_class_name
1875 var value_return_type : String = ""
1876 if gd_type != "":
1877 value_return_type = return_type
1878 elif field_table[i].field_type == Analysis.FIELD_TYPE.MESSAGE:
1879 value_return_type = " -> " + the_parent_class_name + "." + field_table[i].type_name
1880 text += tabulate("func add_empty_" + f.name + "()" + return_type + ":\n", nesting)
1881 nesting += 1
1882 text += generate_group_clear(field_index, nesting)
1883 text += tabulate("var element = " + the_class_name + ".new()\n", nesting)
1884 text += tabulate(varname + ".value.append(element)\n", nesting)
1885 text += tabulate("return element\n", nesting)
1886 nesting -= 1
1887 if field_table[i].field_type == Analysis.FIELD_TYPE.MESSAGE:
1888 text += tabulate("func add_" + f.name + "(a_key)" + value_return_type + ":\n", nesting)
1889 nesting += 1
1890 text += generate_group_clear(field_index, nesting)
1891 text += tabulate("var idx = -1\n", nesting)
1892 text += tabulate("for i in range(" + varname + ".value.size()):\n", nesting)
1893 nesting += 1
1894 text += tabulate("if " + varname + ".value[i].get_key() == a_key:\n", nesting)
1895 nesting += 1
1896 text += tabulate("idx = i\n", nesting)
1897 text += tabulate("break\n", nesting)
1898 nesting -= 2
1899 text += tabulate("var element = " + the_class_name + ".new()\n", nesting)
1900 text += tabulate("element.set_key(a_key)\n", nesting)
1901 text += tabulate("if idx != -1:\n", nesting)
1902 nesting += 1
1903 text += tabulate(varname + ".value[idx] = element\n", nesting)
1904 nesting -= 1
1905 text += tabulate("else:\n", nesting)
1906 nesting += 1
1907 text += tabulate(varname + ".value.append(element)\n", nesting)
1908 nesting -= 1
1909 text += tabulate("return element.new_value()\n", nesting)
1910 else:
1911 text += tabulate("func add_" + f.name + "(a_key, a_value) -> void:\n", nesting)
1912 nesting += 1
1913 text += generate_group_clear(field_index, nesting)
1914 text += tabulate("var idx = -1\n", nesting)
1915 text += tabulate("for i in range(" + varname + ".value.size()):\n", nesting)
1916 nesting += 1
1917 text += tabulate("if " + varname + ".value[i].get_key() == a_key:\n", nesting)
1918 nesting += 1
1919 text += tabulate("idx = i\n", nesting)
1920 text += tabulate("break\n", nesting)
1921 nesting -= 2
1922 text += tabulate("var element = " + the_class_name + ".new()\n", nesting)
1923 text += tabulate("element.set_key(a_key)\n", nesting)
1924 text += tabulate("element.set_value(a_value)\n", nesting)
1925 text += tabulate("if idx != -1:\n", nesting)
1926 nesting += 1
1927 text += tabulate(varname + ".value[idx] = element\n", nesting)
1928 nesting -= 1
1929 text += tabulate("else:\n", nesting)
1930 nesting += 1
1931 text += tabulate(varname + ".value.append(element)\n", nesting)
1932 nesting -= 1
1933 break
1934 else:
1935 var gd_type : String = generate_gdscript_simple_type(f)
1936 var return_type : String = ""
1937 var argument_type : String = ""
1938 if gd_type != "":
1939 return_type = " -> " + gd_type
1940 argument_type = " : " + gd_type
1941 if f.qualificator != Analysis.FIELD_QUALIFICATOR.OPTIONAL:
1942 text += generate_has_oneof(field_index, nesting)
1943 if f.qualificator == Analysis.FIELD_QUALIFICATOR.REPEATED:
1944 var array_type := "[" + gd_type + "]" if gd_type else ""
1945 text += tabulate("func get_" + f.name + "() -> Array" + array_type + ":\n", nesting)
1946 else:
1947 if f.qualificator == Analysis.FIELD_QUALIFICATOR.OPTIONAL:
1948 text += tabulate("func has_" + f.name + "() -> bool:\n", nesting)
1949 nesting += 1
1950 text += tabulate("if " + varname + ".value != null:\n", nesting)
1951 nesting += 1
1952 text += tabulate("return true\n", nesting)
1953 nesting -= 1
1954 text += tabulate("return false\n", nesting)
1955 nesting -= 1
1956 text += tabulate("func get_" + f.name + "()" + return_type + ":\n", nesting)
1957 nesting += 1
1958 text += tabulate("return " + varname + ".value\n", nesting)
1959 nesting -= 1
1960 text += tabulate("func clear_" + f.name + "() -> void:\n", nesting)
1961 nesting += 1
1962 text += tabulate("data[" + str(f.tag) + "].state = PB_SERVICE_STATE.UNFILLED\n", nesting)
1963 if f.qualificator == Analysis.FIELD_QUALIFICATOR.REPEATED:
1964 text += tabulate(varname + ".value.clear()\n", nesting)
1965 nesting -= 1
1966 text += tabulate("func add_" + f.name + "(value" + argument_type + ") -> void:\n", nesting)
1967 nesting += 1
1968 text += tabulate(varname + ".value.append(value)\n", nesting)
1969 else:
1970 text += tabulate(varname + ".value = " + default_dict_text() + "[" + generate_field_type(f) + "]\n", nesting)
1971 nesting -= 1
1972 text += tabulate("func set_" + f.name + "(value" + argument_type + ") -> void:\n", nesting)
1973 nesting += 1
1974 text += generate_group_clear(field_index, nesting)
1975 text += tabulate(varname + ".value = value\n", nesting)
1976 return text
1977
1978 func generate_class(class_index : int, nesting : int) -> String:
1979 var text : String = ""
1980 if class_table[class_index].type == Analysis.CLASS_TYPE.MESSAGE || class_table[class_index].type == Analysis.CLASS_TYPE.MAP:
1981 var cls_pref : String = ""
1982 cls_pref += tabulate("class " + class_table[class_index].name + ":\n", nesting)
1983 nesting += 1
1984 cls_pref += tabulate("func _init():\n", nesting)
1985 text += cls_pref
1986 nesting += 1
1987 text += tabulate("var service\n", nesting)
1988 text += tabulate("\n", nesting)
1989 var field_text : String = ""
1990 for i in range(field_table.size()):
1991 if field_table[i].parent_class_id == class_index:
1992 text += generate_field_constructor(i, nesting)
1993 text += tabulate("\n", nesting)
1994 field_text += generate_field(i, nesting - 1)
1995 field_text += tabulate("\n", nesting - 1)
1996 nesting -= 1
1997 text += tabulate("var data = {}\n", nesting)
1998 text += tabulate("\n", nesting)
1999 text += field_text
2000 for j in range(class_table.size()):
2001 if class_table[j].parent_index == class_index:
2002 var cl_text = generate_class(j, nesting)
2003 text += cl_text
2004 if class_table[j].type == Analysis.CLASS_TYPE.MESSAGE || class_table[j].type == Analysis.CLASS_TYPE.MAP:
2005 text += generate_class_services(nesting + 1)
2006 text += tabulate("\n", nesting + 1)
2007 elif class_table[class_index].type == Analysis.CLASS_TYPE.ENUM:
2008 text += tabulate("enum " + class_table[class_index].name + " {\n", nesting)
2009 nesting += 1
2010
2011 var expected_prefix = class_table[class_index].name.to_snake_case().to_upper() + "_"
2012 var all_have_prefix = true
2013 for en in range(class_table[class_index].values.size()):
2014 var value_name = class_table[class_index].values[en].name
2015 all_have_prefix = all_have_prefix and value_name.begins_with(expected_prefix) and value_name != expected_prefix
2016
2017 for en in range(class_table[class_index].values.size()):
2018 var value_name = class_table[class_index].values[en].name
2019 if all_have_prefix:
2020 value_name = value_name.substr(expected_prefix.length())
2021 var enum_val = value_name + " = " + class_table[class_index].values[en].value
2022 if en == class_table[class_index].values.size() - 1:
2023 text += tabulate(enum_val + "\n", nesting)
2024 else:
2025 text += tabulate(enum_val + ",\n", nesting)
2026 nesting -= 1
2027 text += tabulate("}\n", nesting)
2028 text += tabulate("\n", nesting)
2029
2030 return text
2031
2032 func generate_class_services(nesting : int) -> String:
2033 var text : String = ""
2034 text += tabulate("func _to_string() -> String:\n", nesting)
2035 nesting += 1
2036 text += tabulate("return PBPacker.message_to_string(data)\n", nesting)
2037 text += tabulate("\n", nesting)
2038 nesting -= 1
2039 text += tabulate("func to_bytes() -> PackedByteArray:\n", nesting)
2040 nesting += 1
2041 text += tabulate("return PBPacker.pack_message(data)\n", nesting)
2042 text += tabulate("\n", nesting)
2043 nesting -= 1
2044 text += tabulate("func from_bytes(bytes : PackedByteArray, offset : int = 0, limit : int = -1) -> int:\n", nesting)
2045 nesting += 1
2046 text += tabulate("var cur_limit = bytes.size()\n", nesting)
2047 text += tabulate("if limit != -1:\n", nesting)
2048 nesting += 1
2049 text += tabulate("cur_limit = limit\n", nesting)
2050 nesting -= 1
2051 text += tabulate("var result = PBPacker.unpack_message(data, bytes, offset, cur_limit)\n", nesting)
2052 text += tabulate("if result == cur_limit:\n", nesting)
2053 nesting += 1
2054 text += tabulate("if PBPacker.check_required(data):\n", nesting)
2055 nesting += 1
2056 text += tabulate("if limit == -1:\n", nesting)
2057 nesting += 1
2058 text += tabulate("return PB_ERR.NO_ERRORS\n", nesting)
2059 nesting -= 2
2060 text += tabulate("else:\n", nesting)
2061 nesting += 1
2062 text += tabulate("return PB_ERR.REQUIRED_FIELDS\n", nesting)
2063 nesting -= 2
2064 text += tabulate("elif limit == -1 && result > 0:\n", nesting)
2065 nesting += 1
2066 text += tabulate("return PB_ERR.PARSE_INCOMPLETE\n", nesting)
2067 nesting -= 1
2068 text += tabulate("return result\n", nesting)
2069 return text
2070
2071 func translate(file_name : String, core_file_name : String) -> bool:
2072
2073 var file : FileAccess = FileAccess.open(file_name, FileAccess.WRITE)
2074 if file == null:
2075 printerr("File: '", file_name, "' save error.")
2076 return false
2077
2078 if !FileAccess.file_exists(core_file_name):
2079 printerr("File: '", core_file_name, "' not found.")
2080 return false
2081
2082 var core_file : FileAccess = FileAccess.open(core_file_name, FileAccess.READ)
2083 if core_file == null:
2084 printerr("File: '", core_file_name, "' read error.")
2085 return false
2086 var core_text : String = core_file.get_as_text()
2087 core_file.close()
2088
2089 var text : String = ""
2090 var nesting : int = 0
2091 core_text = core_text.replace(PROTO_VERSION_DEFAULT, PROTO_VERSION_CONST + str(proto_version))
2092 text += core_text + "\n\n\n"
2093 text += "############### USER DATA BEGIN ################\n"
2094 var cls_user : String = ""
2095 for i in range(class_table.size()):
2096 if class_table[i].parent_index == -1:
2097 var cls_text = generate_class(i, nesting)
2098 cls_user += cls_text
2099 if class_table[i].type == Analysis.CLASS_TYPE.MESSAGE:
2100 nesting += 1
2101 cls_user += generate_class_services(nesting)
2102 cls_user += tabulate("\n", nesting)
2103 nesting -= 1
2104 text += "\n\n"
2105 text += cls_user
2106 text += "################ USER DATA END #################\n"
2107 file.store_string(text)
2108 file.close()
2109 if !FileAccess.file_exists(file_name):
2110 printerr("File: '", file_name, "' save error.")
2111 return false
2112 return true
2113
2114
2115class ImportFile:
2116 func _init(sha : String, a_path : String, a_parent : int):
2117 sha256 = sha
2118 path = a_path
2119 parent_index = a_parent
2120
2121 var sha256 : String
2122 var path : String
2123 var parent_index : int
2124
2125func parse_all(analyzes : Dictionary, imports : Array, path : String, full_name : String, parent_index : int) -> bool:
2126
2127 if !FileAccess.file_exists(full_name):
2128 printerr(full_name, ": not found.")
2129 return false
2130
2131 var file : FileAccess = FileAccess.open(full_name, FileAccess.READ)
2132 if file == null:
2133 printerr(full_name, ": read error.")
2134 return false
2135 var doc : Document = Document.new(full_name, file.get_as_text())
2136 var sha : String = file.get_sha256(full_name)
2137 file.close()
2138
2139 if !analyzes.has(sha):
2140 print(full_name, ": parsing.")
2141 var analysis : Analysis = Analysis.new(path, doc)
2142 var an_result : AnalyzeResult = analysis.analyze()
2143 if an_result.state:
2144 analyzes[sha] = an_result
2145 var parent : int = imports.size()
2146 imports.append(ImportFile.new(sha, doc.name, parent_index))
2147 for im in an_result.imports:
2148 if !parse_all(analyzes, imports, path, im.path, parent):
2149 return false
2150 else:
2151 printerr(doc.name + ": parsing error.")
2152 return false
2153 else:
2154 print(full_name, ": retrieving data from cache.")
2155 imports.append(ImportFile.new(sha, doc.name, parent_index))
2156 return true
2157
2158func union_analyses(a1 : AnalyzeResult, a2 : AnalyzeResult, only_classes : bool = true) -> void:
2159 var class_offset : int = a1.classes.size()
2160 var field_offset = a1.fields.size()
2161 for cl in a2.classes:
2162 var cur_class : Analysis.ASTClass = cl.copy()
2163 if cur_class.parent_index != -1:
2164 cur_class.parent_index += class_offset
2165 a1.classes.append(cur_class)
2166 if only_classes:
2167 return
2168 for fl in a2.fields:
2169 var cur_field : Analysis.ASTField = fl.copy()
2170 cur_field.parent_class_id += class_offset
2171 cur_field.type_class_id = -1
2172 a1.fields.append(cur_field)
2173 for gr in a2.groups:
2174 var cur_group : Analysis.ASTFieldGroup = gr.copy()
2175 cur_group.parent_class_id += class_offset
2176 var indexes : Array = []
2177 for i in cur_group.field_indexes:
2178 indexes.append(i + field_offset)
2179 cur_group.field_indexes = indexes
2180 a1.groups.append(cur_group)
2181
2182func union_imports(analyzes : Dictionary, key : String, result : AnalyzeResult, keys : Array, nesting : int, use_public : bool = true, only_classes : bool = true) -> void:
2183 nesting += 1
2184 for im in analyzes[key].imports:
2185 var find : bool = false
2186 for k in keys:
2187 if im.sha256 == k:
2188 find = true
2189 break
2190 if find:
2191 continue
2192 if (!use_public) || (use_public && ((im.public && nesting > 1) || nesting < 2)):
2193 keys.append(im.sha256)
2194 union_analyses(result, analyzes[im.sha256], only_classes)
2195 union_imports(analyzes, im.sha256, result, keys, nesting, use_public, only_classes)
2196
2197func semantic_all(analyzes : Dictionary, imports : Array)-> bool:
2198 for k in analyzes.keys():
2199 print(analyzes[k].doc.name, ": analysis.")
2200 var keys : Array = []
2201 var analyze : AnalyzeResult = analyzes[k].soft_copy()
2202 keys.append(k)
2203 analyze.classes = []
2204 for cl in analyzes[k].classes:
2205 analyze.classes.append(cl.copy())
2206 union_imports(analyzes, k, analyze, keys, 0)
2207 var semantic : Semantic = Semantic.new(analyze)
2208 if !semantic.check():
2209 printerr(analyzes[k].doc.name, ": analysis error.")
2210 return false
2211 return true
2212
2213func translate_all(analyzes : Dictionary, file_name : String, core_file_name : String) -> bool:
2214 var first_key : String = analyzes.keys()[0]
2215 var analyze : AnalyzeResult = analyzes[first_key]
2216 var keys : Array = []
2217 keys.append(first_key)
2218 union_imports(analyzes, first_key, analyze, keys, 0, false, false)
2219 print("Performing full semantic analysis.")
2220 var semantic : Semantic = Semantic.new(analyze)
2221 if !semantic.check():
2222 return false
2223 print("Performing translation.")
2224 var translator : Translator = Translator.new(analyze)
2225 if !translator.translate(file_name, core_file_name):
2226 return false
2227 var first : bool = true
2228 return true
2229
2230func work(path : String, in_file : String, out_file : String, core_file : String) -> bool:
2231 var in_full_name : String = path + in_file
2232 var imports : Array = []
2233 var analyzes : Dictionary = {}
2234
2235 print("Compiling source: '", in_full_name, "', output: '", out_file, "'.")
2236 print("\n1. Parsing:")
2237 if parse_all(analyzes, imports, path, in_full_name, -1):
2238 print("* Parsing completed successfully. *")
2239 else:
2240 return false
2241 print("\n2. Perfoming semantic analysis:")
2242 if semantic_all(analyzes, imports):
2243 print("* Semantic analysis completed successfully. *")
2244 else:
2245 return false
2246 print("\n3. Output file creating:")
2247 if translate_all(analyzes, out_file, core_file):
2248 print("* Output file was created successfully. *")
2249 else:
2250 return false
2251 return true
2252
2253func _ready():
2254 pass
diff --git a/vendor/godobuf/addons/protobuf/plugin.cfg b/vendor/godobuf/addons/protobuf/plugin.cfg new file mode 100644 index 0000000..6456a11 --- /dev/null +++ b/vendor/godobuf/addons/protobuf/plugin.cfg
@@ -0,0 +1,7 @@
1[plugin]
2
3name="Godobuf"
4description="Google Protobuf implementation for Godot/GDScript"
5author="oniksan"
6version="0.6.1 for Godot 4.x.y"
7script="protobuf_ui.gd"
diff --git a/vendor/godobuf/addons/protobuf/protobuf_cmdln.gd b/vendor/godobuf/addons/protobuf/protobuf_cmdln.gd new file mode 100644 index 0000000..97d7ba4 --- /dev/null +++ b/vendor/godobuf/addons/protobuf/protobuf_cmdln.gd
@@ -0,0 +1,66 @@
1#
2# BSD 3-Clause License
3#
4# Copyright (c) 2018, Oleg Malyavkin
5# All rights reserved.
6#
7# Redistribution and use in source and binary forms, with or without
8# modification, are permitted provided that the following conditions are met:
9#
10# * Redistributions of source code must retain the above copyright notice, this
11# list of conditions and the following disclaimer.
12#
13# * Redistributions in binary form must reproduce the above copyright notice,
14# this list of conditions and the following disclaimer in the documentation
15# and/or other materials provided with the distribution.
16#
17# * Neither the name of the copyright holder nor the names of its
18# contributors may be used to endorse or promote products derived from
19# this software without specific prior written permission.
20#
21# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
25# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31
32extends SceneTree
33
34var Parser = preload("res://addons/protobuf/parser.gd")
35var Util = preload("res://addons/protobuf/protobuf_util.gd")
36
37func error(msg : String):
38 push_error(msg)
39 quit()
40
41func _init():
42 var arguments = {}
43 for argument in OS.get_cmdline_args():
44 if argument.find("=") > -1:
45 var key_value = argument.split("=")
46 arguments[key_value[0].lstrip("--")] = key_value[1]
47
48 if !arguments.has("input") || !arguments.has("output"):
49 error("Expected 2 Parameters: input and output")
50
51 var input_file_name = arguments["input"]
52 var output_file_name = arguments["output"]
53
54 var file = FileAccess.open(input_file_name, FileAccess.READ)
55 if file == null:
56 error("File: '" + input_file_name + "' not found.")
57
58 var parser = Parser.new()
59
60 if parser.work(Util.extract_dir(input_file_name), Util.extract_filename(input_file_name), \
61 output_file_name, "res://addons/protobuf/protobuf_core.gd"):
62 print("Compiled '", input_file_name, "' to '", output_file_name, "'.")
63 else:
64 error("Compilation failed.")
65
66 quit()
diff --git a/vendor/godobuf/addons/protobuf/protobuf_core.gd b/vendor/godobuf/addons/protobuf/protobuf_core.gd new file mode 100644 index 0000000..7098413 --- /dev/null +++ b/vendor/godobuf/addons/protobuf/protobuf_core.gd
@@ -0,0 +1,668 @@
1#
2# BSD 3-Clause License
3#
4# Copyright (c) 2018 - 2023, Oleg Malyavkin
5# All rights reserved.
6#
7# Redistribution and use in source and binary forms, with or without
8# modification, are permitted provided that the following conditions are met:
9#
10# * Redistributions of source code must retain the above copyright notice, this
11# list of conditions and the following disclaimer.
12#
13# * Redistributions in binary form must reproduce the above copyright notice,
14# this list of conditions and the following disclaimer in the documentation
15# and/or other materials provided with the distribution.
16#
17# * Neither the name of the copyright holder nor the names of its
18# contributors may be used to endorse or promote products derived from
19# this software without specific prior written permission.
20#
21# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
25# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31
32# DEBUG_TAB redefine this " " if you need, example: const DEBUG_TAB = "\t"
33
34const PROTO_VERSION = 0
35
36const DEBUG_TAB : String = " "
37
38enum PB_ERR {
39 NO_ERRORS = 0,
40 VARINT_NOT_FOUND = -1,
41 REPEATED_COUNT_NOT_FOUND = -2,
42 REPEATED_COUNT_MISMATCH = -3,
43 LENGTHDEL_SIZE_NOT_FOUND = -4,
44 LENGTHDEL_SIZE_MISMATCH = -5,
45 PACKAGE_SIZE_MISMATCH = -6,
46 UNDEFINED_STATE = -7,
47 PARSE_INCOMPLETE = -8,
48 REQUIRED_FIELDS = -9
49}
50
51enum PB_DATA_TYPE {
52 INT32 = 0,
53 SINT32 = 1,
54 UINT32 = 2,
55 INT64 = 3,
56 SINT64 = 4,
57 UINT64 = 5,
58 BOOL = 6,
59 ENUM = 7,
60 FIXED32 = 8,
61 SFIXED32 = 9,
62 FLOAT = 10,
63 FIXED64 = 11,
64 SFIXED64 = 12,
65 DOUBLE = 13,
66 STRING = 14,
67 BYTES = 15,
68 MESSAGE = 16,
69 MAP = 17
70}
71
72const DEFAULT_VALUES_2 = {
73 PB_DATA_TYPE.INT32: null,
74 PB_DATA_TYPE.SINT32: null,
75 PB_DATA_TYPE.UINT32: null,
76 PB_DATA_TYPE.INT64: null,
77 PB_DATA_TYPE.SINT64: null,
78 PB_DATA_TYPE.UINT64: null,
79 PB_DATA_TYPE.BOOL: null,
80 PB_DATA_TYPE.ENUM: null,
81 PB_DATA_TYPE.FIXED32: null,
82 PB_DATA_TYPE.SFIXED32: null,
83 PB_DATA_TYPE.FLOAT: null,
84 PB_DATA_TYPE.FIXED64: null,
85 PB_DATA_TYPE.SFIXED64: null,
86 PB_DATA_TYPE.DOUBLE: null,
87 PB_DATA_TYPE.STRING: null,
88 PB_DATA_TYPE.BYTES: null,
89 PB_DATA_TYPE.MESSAGE: null,
90 PB_DATA_TYPE.MAP: null
91}
92
93const DEFAULT_VALUES_3 = {
94 PB_DATA_TYPE.INT32: 0,
95 PB_DATA_TYPE.SINT32: 0,
96 PB_DATA_TYPE.UINT32: 0,
97 PB_DATA_TYPE.INT64: 0,
98 PB_DATA_TYPE.SINT64: 0,
99 PB_DATA_TYPE.UINT64: 0,
100 PB_DATA_TYPE.BOOL: false,
101 PB_DATA_TYPE.ENUM: 0,
102 PB_DATA_TYPE.FIXED32: 0,
103 PB_DATA_TYPE.SFIXED32: 0,
104 PB_DATA_TYPE.FLOAT: 0.0,
105 PB_DATA_TYPE.FIXED64: 0,
106 PB_DATA_TYPE.SFIXED64: 0,
107 PB_DATA_TYPE.DOUBLE: 0.0,
108 PB_DATA_TYPE.STRING: "",
109 PB_DATA_TYPE.BYTES: [],
110 PB_DATA_TYPE.MESSAGE: null,
111 PB_DATA_TYPE.MAP: []
112}
113
114enum PB_TYPE {
115 VARINT = 0,
116 FIX64 = 1,
117 LENGTHDEL = 2,
118 STARTGROUP = 3,
119 ENDGROUP = 4,
120 FIX32 = 5,
121 UNDEFINED = 8
122}
123
124enum PB_RULE {
125 OPTIONAL = 0,
126 REQUIRED = 1,
127 REPEATED = 2,
128 RESERVED = 3
129}
130
131enum PB_SERVICE_STATE {
132 FILLED = 0,
133 UNFILLED = 1
134}
135
136class PBField:
137 func _init(a_name : String, a_type : int, a_rule : int, a_tag : int, packed : bool, a_value = null):
138 name = a_name
139 type = a_type
140 rule = a_rule
141 tag = a_tag
142 option_packed = packed
143 value = a_value
144
145 var name : String
146 var type : int
147 var rule : int
148 var tag : int
149 var option_packed : bool
150 var value
151 var is_map_field : bool = false
152 var option_default : bool = false
153
154class PBTypeTag:
155 var ok : bool = false
156 var type : int
157 var tag : int
158 var offset : int
159
160class PBServiceField:
161 var field : PBField
162 var func_ref = null
163 var state : int = PB_SERVICE_STATE.UNFILLED
164
165class PBPacker:
166 static func convert_signed(n : int) -> int:
167 if n < -2147483648:
168 return (n << 1) ^ (n >> 63)
169 else:
170 return (n << 1) ^ (n >> 31)
171
172 static func deconvert_signed(n : int) -> int:
173 if n & 0x01:
174 return ~(n >> 1)
175 else:
176 return (n >> 1)
177
178 static func pack_varint(value) -> PackedByteArray:
179 var varint : PackedByteArray = PackedByteArray()
180 if typeof(value) == TYPE_BOOL:
181 if value:
182 value = 1
183 else:
184 value = 0
185 for _i in range(9):
186 var b = value & 0x7F
187 value >>= 7
188 if value:
189 varint.append(b | 0x80)
190 else:
191 varint.append(b)
192 break
193 if varint.size() == 9 && (varint[8] & 0x80 != 0):
194 varint.append(0x01)
195 return varint
196
197 static func pack_bytes(value, count : int, data_type : int) -> PackedByteArray:
198 var bytes : PackedByteArray = PackedByteArray()
199 if data_type == PB_DATA_TYPE.FLOAT:
200 var spb : StreamPeerBuffer = StreamPeerBuffer.new()
201 spb.put_float(value)
202 bytes = spb.get_data_array()
203 elif data_type == PB_DATA_TYPE.DOUBLE:
204 var spb : StreamPeerBuffer = StreamPeerBuffer.new()
205 spb.put_double(value)
206 bytes = spb.get_data_array()
207 else:
208 for _i in range(count):
209 bytes.append(value & 0xFF)
210 value >>= 8
211 return bytes
212
213 static func unpack_bytes(bytes : PackedByteArray, index : int, count : int, data_type : int):
214 if data_type == PB_DATA_TYPE.FLOAT:
215 return bytes.decode_float(index)
216 elif data_type == PB_DATA_TYPE.DOUBLE:
217 return bytes.decode_double(index)
218 else:
219 # Convert to big endian
220 var slice: PackedByteArray = bytes.slice(index, index + count)
221 slice.reverse()
222 return slice
223
224 static func unpack_varint(varint_bytes) -> int:
225 var value : int = 0
226 var i: int = varint_bytes.size() - 1
227 while i > -1:
228 value = (value << 7) | (varint_bytes[i] & 0x7F)
229 i -= 1
230 return value
231
232 static func pack_type_tag(type : int, tag : int) -> PackedByteArray:
233 return pack_varint((tag << 3) | type)
234
235 static func isolate_varint(bytes : PackedByteArray, index : int) -> PackedByteArray:
236 var i: int = index
237 while i <= index + 10: # Protobuf varint max size is 10 bytes
238 if !(bytes[i] & 0x80):
239 return bytes.slice(index, i + 1)
240 i += 1
241 return [] # Unreachable
242
243 static func unpack_type_tag(bytes : PackedByteArray, index : int) -> PBTypeTag:
244 var varint_bytes : PackedByteArray = isolate_varint(bytes, index)
245 var result : PBTypeTag = PBTypeTag.new()
246 if varint_bytes.size() != 0:
247 result.ok = true
248 result.offset = varint_bytes.size()
249 var unpacked : int = unpack_varint(varint_bytes)
250 result.type = unpacked & 0x07
251 result.tag = unpacked >> 3
252 return result
253
254 static func pack_length_delimeted(type : int, tag : int, bytes : PackedByteArray) -> PackedByteArray:
255 var result : PackedByteArray = pack_type_tag(type, tag)
256 result.append_array(pack_varint(bytes.size()))
257 result.append_array(bytes)
258 return result
259
260 static func pb_type_from_data_type(data_type : int) -> int:
261 if data_type == PB_DATA_TYPE.INT32 || data_type == PB_DATA_TYPE.SINT32 || data_type == PB_DATA_TYPE.UINT32 || data_type == PB_DATA_TYPE.INT64 || data_type == PB_DATA_TYPE.SINT64 || data_type == PB_DATA_TYPE.UINT64 || data_type == PB_DATA_TYPE.BOOL || data_type == PB_DATA_TYPE.ENUM:
262 return PB_TYPE.VARINT
263 elif data_type == PB_DATA_TYPE.FIXED32 || data_type == PB_DATA_TYPE.SFIXED32 || data_type == PB_DATA_TYPE.FLOAT:
264 return PB_TYPE.FIX32
265 elif data_type == PB_DATA_TYPE.FIXED64 || data_type == PB_DATA_TYPE.SFIXED64 || data_type == PB_DATA_TYPE.DOUBLE:
266 return PB_TYPE.FIX64
267 elif data_type == PB_DATA_TYPE.STRING || data_type == PB_DATA_TYPE.BYTES || data_type == PB_DATA_TYPE.MESSAGE || data_type == PB_DATA_TYPE.MAP:
268 return PB_TYPE.LENGTHDEL
269 else:
270 return PB_TYPE.UNDEFINED
271
272 static func pack_field(field : PBField) -> PackedByteArray:
273 var type : int = pb_type_from_data_type(field.type)
274 var type_copy : int = type
275 if field.rule == PB_RULE.REPEATED && field.option_packed:
276 type = PB_TYPE.LENGTHDEL
277 var head : PackedByteArray = pack_type_tag(type, field.tag)
278 var data : PackedByteArray = PackedByteArray()
279 if type == PB_TYPE.VARINT:
280 var value
281 if field.rule == PB_RULE.REPEATED:
282 for v in field.value:
283 data.append_array(head)
284 if field.type == PB_DATA_TYPE.SINT32 || field.type == PB_DATA_TYPE.SINT64:
285 value = convert_signed(v)
286 else:
287 value = v
288 data.append_array(pack_varint(value))
289 return data
290 else:
291 if field.type == PB_DATA_TYPE.SINT32 || field.type == PB_DATA_TYPE.SINT64:
292 value = convert_signed(field.value)
293 else:
294 value = field.value
295 data = pack_varint(value)
296 elif type == PB_TYPE.FIX32:
297 if field.rule == PB_RULE.REPEATED:
298 for v in field.value:
299 data.append_array(head)
300 data.append_array(pack_bytes(v, 4, field.type))
301 return data
302 else:
303 data.append_array(pack_bytes(field.value, 4, field.type))
304 elif type == PB_TYPE.FIX64:
305 if field.rule == PB_RULE.REPEATED:
306 for v in field.value:
307 data.append_array(head)
308 data.append_array(pack_bytes(v, 8, field.type))
309 return data
310 else:
311 data.append_array(pack_bytes(field.value, 8, field.type))
312 elif type == PB_TYPE.LENGTHDEL:
313 if field.rule == PB_RULE.REPEATED:
314 if type_copy == PB_TYPE.VARINT:
315 if field.type == PB_DATA_TYPE.SINT32 || field.type == PB_DATA_TYPE.SINT64:
316 var signed_value : int
317 for v in field.value:
318 signed_value = convert_signed(v)
319 data.append_array(pack_varint(signed_value))
320 else:
321 for v in field.value:
322 data.append_array(pack_varint(v))
323 return pack_length_delimeted(type, field.tag, data)
324 elif type_copy == PB_TYPE.FIX32:
325 for v in field.value:
326 data.append_array(pack_bytes(v, 4, field.type))
327 return pack_length_delimeted(type, field.tag, data)
328 elif type_copy == PB_TYPE.FIX64:
329 for v in field.value:
330 data.append_array(pack_bytes(v, 8, field.type))
331 return pack_length_delimeted(type, field.tag, data)
332 elif field.type == PB_DATA_TYPE.STRING:
333 for v in field.value:
334 var obj = v.to_utf8_buffer()
335 data.append_array(pack_length_delimeted(type, field.tag, obj))
336 return data
337 elif field.type == PB_DATA_TYPE.BYTES:
338 for v in field.value:
339 data.append_array(pack_length_delimeted(type, field.tag, v))
340 return data
341 elif typeof(field.value[0]) == TYPE_OBJECT:
342 for v in field.value:
343 var obj : PackedByteArray = v.to_bytes()
344 data.append_array(pack_length_delimeted(type, field.tag, obj))
345 return data
346 else:
347 if field.type == PB_DATA_TYPE.STRING:
348 var str_bytes : PackedByteArray = field.value.to_utf8_buffer()
349 if PROTO_VERSION == 2 || (PROTO_VERSION == 3 && str_bytes.size() > 0):
350 data.append_array(str_bytes)
351 return pack_length_delimeted(type, field.tag, data)
352 if field.type == PB_DATA_TYPE.BYTES:
353 if PROTO_VERSION == 2 || (PROTO_VERSION == 3 && field.value.size() > 0):
354 data.append_array(field.value)
355 return pack_length_delimeted(type, field.tag, data)
356 elif typeof(field.value) == TYPE_OBJECT:
357 var obj : PackedByteArray = field.value.to_bytes()
358 if obj.size() > 0:
359 data.append_array(obj)
360 return pack_length_delimeted(type, field.tag, data)
361 else:
362 pass
363 if data.size() > 0:
364 head.append_array(data)
365 return head
366 else:
367 return data
368
369 static func skip_unknown_field(bytes : PackedByteArray, offset : int, type : int) -> int:
370 if type == PB_TYPE.VARINT:
371 return offset + isolate_varint(bytes, offset).size()
372 if type == PB_TYPE.FIX64:
373 return offset + 8
374 if type == PB_TYPE.LENGTHDEL:
375 var length_bytes : PackedByteArray = isolate_varint(bytes, offset)
376 var length : int = unpack_varint(length_bytes)
377 return offset + length_bytes.size() + length
378 if type == PB_TYPE.FIX32:
379 return offset + 4
380 return PB_ERR.UNDEFINED_STATE
381
382 static func unpack_field(bytes : PackedByteArray, offset : int, field : PBField, type : int, message_func_ref) -> int:
383 if field.rule == PB_RULE.REPEATED && type != PB_TYPE.LENGTHDEL && field.option_packed:
384 var count = isolate_varint(bytes, offset)
385 if count.size() > 0:
386 offset += count.size()
387 count = unpack_varint(count)
388 if type == PB_TYPE.VARINT:
389 var val
390 var counter = offset + count
391 while offset < counter:
392 val = isolate_varint(bytes, offset)
393 if val.size() > 0:
394 offset += val.size()
395 val = unpack_varint(val)
396 if field.type == PB_DATA_TYPE.SINT32 || field.type == PB_DATA_TYPE.SINT64:
397 val = deconvert_signed(val)
398 elif field.type == PB_DATA_TYPE.BOOL:
399 if val:
400 val = true
401 else:
402 val = false
403 field.value.append(val)
404 else:
405 return PB_ERR.REPEATED_COUNT_MISMATCH
406 return offset
407 elif type == PB_TYPE.FIX32 || type == PB_TYPE.FIX64:
408 var type_size
409 if type == PB_TYPE.FIX32:
410 type_size = 4
411 else:
412 type_size = 8
413 var val
414 var counter = offset + count
415 while offset < counter:
416 if (offset + type_size) > bytes.size():
417 return PB_ERR.REPEATED_COUNT_MISMATCH
418 val = unpack_bytes(bytes, offset, type_size, field.type)
419 offset += type_size
420 field.value.append(val)
421 return offset
422 else:
423 return PB_ERR.REPEATED_COUNT_NOT_FOUND
424 else:
425 if type == PB_TYPE.VARINT:
426 var val = isolate_varint(bytes, offset)
427 if val.size() > 0:
428 offset += val.size()
429 val = unpack_varint(val)
430 if field.type == PB_DATA_TYPE.SINT32 || field.type == PB_DATA_TYPE.SINT64:
431 val = deconvert_signed(val)
432 elif field.type == PB_DATA_TYPE.BOOL:
433 if val:
434 val = true
435 else:
436 val = false
437 if field.rule == PB_RULE.REPEATED:
438 field.value.append(val)
439 else:
440 field.value = val
441 else:
442 return PB_ERR.VARINT_NOT_FOUND
443 return offset
444 elif type == PB_TYPE.FIX32 || type == PB_TYPE.FIX64:
445 var type_size
446 if type == PB_TYPE.FIX32:
447 type_size = 4
448 else:
449 type_size = 8
450 var val
451 if (offset + type_size) > bytes.size():
452 return PB_ERR.REPEATED_COUNT_MISMATCH
453 val = unpack_bytes(bytes, offset, type_size, field.type)
454 offset += type_size
455 if field.rule == PB_RULE.REPEATED:
456 field.value.append(val)
457 else:
458 field.value = val
459 return offset
460 elif type == PB_TYPE.LENGTHDEL:
461 var inner_size = isolate_varint(bytes, offset)
462 if inner_size.size() > 0:
463 offset += inner_size.size()
464 inner_size = unpack_varint(inner_size)
465 if inner_size >= 0:
466 if inner_size + offset > bytes.size():
467 return PB_ERR.LENGTHDEL_SIZE_MISMATCH
468 if message_func_ref != null:
469 var message = message_func_ref.call()
470 if inner_size > 0:
471 var sub_offset = message.from_bytes(bytes, offset, inner_size + offset)
472 if sub_offset > 0:
473 if sub_offset - offset >= inner_size:
474 offset = sub_offset
475 return offset
476 else:
477 return PB_ERR.LENGTHDEL_SIZE_MISMATCH
478 return sub_offset
479 else:
480 return offset
481 elif field.type == PB_DATA_TYPE.STRING:
482 var str_bytes : PackedByteArray = bytes.slice(offset, inner_size + offset)
483 if field.rule == PB_RULE.REPEATED:
484 field.value.append(str_bytes.get_string_from_utf8())
485 else:
486 field.value = str_bytes.get_string_from_utf8()
487 return offset + inner_size
488 elif field.type == PB_DATA_TYPE.BYTES:
489 var val_bytes : PackedByteArray = bytes.slice(offset, inner_size + offset)
490 if field.rule == PB_RULE.REPEATED:
491 field.value.append(val_bytes)
492 else:
493 field.value = val_bytes
494 return offset + inner_size
495 else:
496 return PB_ERR.LENGTHDEL_SIZE_NOT_FOUND
497 else:
498 return PB_ERR.LENGTHDEL_SIZE_NOT_FOUND
499 return PB_ERR.UNDEFINED_STATE
500
501 static func unpack_message(data, bytes : PackedByteArray, offset : int, limit : int) -> int:
502 while true:
503 var tt : PBTypeTag = unpack_type_tag(bytes, offset)
504 if tt.ok:
505 offset += tt.offset
506 if data.has(tt.tag):
507 var service : PBServiceField = data[tt.tag]
508 var type : int = pb_type_from_data_type(service.field.type)
509 if type == tt.type || (tt.type == PB_TYPE.LENGTHDEL && service.field.rule == PB_RULE.REPEATED && service.field.option_packed):
510 var res : int = unpack_field(bytes, offset, service.field, type, service.func_ref)
511 if res > 0:
512 service.state = PB_SERVICE_STATE.FILLED
513 offset = res
514 if offset == limit:
515 return offset
516 elif offset > limit:
517 return PB_ERR.PACKAGE_SIZE_MISMATCH
518 elif res < 0:
519 return res
520 else:
521 break
522 else:
523 var res : int = skip_unknown_field(bytes, offset, tt.type)
524 if res > 0:
525 offset = res
526 if offset == limit:
527 return offset
528 elif offset > limit:
529 return PB_ERR.PACKAGE_SIZE_MISMATCH
530 elif res < 0:
531 return res
532 else:
533 break
534 else:
535 return offset
536 return PB_ERR.UNDEFINED_STATE
537
538 static func pack_message(data) -> PackedByteArray:
539 var DEFAULT_VALUES
540 if PROTO_VERSION == 2:
541 DEFAULT_VALUES = DEFAULT_VALUES_2
542 elif PROTO_VERSION == 3:
543 DEFAULT_VALUES = DEFAULT_VALUES_3
544 var result : PackedByteArray = PackedByteArray()
545 var keys : Array = data.keys()
546 keys.sort()
547 for i in keys:
548 if data[i].field.value != null:
549 if data[i].state == PB_SERVICE_STATE.UNFILLED \
550 && !data[i].field.is_map_field \
551 && typeof(data[i].field.value) == typeof(DEFAULT_VALUES[data[i].field.type]) \
552 && data[i].field.value == DEFAULT_VALUES[data[i].field.type]:
553 continue
554 elif data[i].field.rule == PB_RULE.REPEATED && data[i].field.value.size() == 0:
555 continue
556 result.append_array(pack_field(data[i].field))
557 elif data[i].field.rule == PB_RULE.REQUIRED:
558 print("Error: required field is not filled: Tag:", data[i].field.tag)
559 return PackedByteArray()
560 return result
561
562 static func check_required(data) -> bool:
563 var keys : Array = data.keys()
564 for i in keys:
565 if data[i].field.rule == PB_RULE.REQUIRED && data[i].state == PB_SERVICE_STATE.UNFILLED:
566 return false
567 return true
568
569 static func construct_map(key_values):
570 var result = {}
571 for kv in key_values:
572 result[kv.get_key()] = kv.get_value()
573 return result
574
575 static func tabulate(text : String, nesting : int) -> String:
576 var tab : String = ""
577 for _i in range(nesting):
578 tab += DEBUG_TAB
579 return tab + text
580
581 static func value_to_string(value, field : PBField, nesting : int) -> String:
582 var result : String = ""
583 var text : String
584 if field.type == PB_DATA_TYPE.MESSAGE:
585 result += "{"
586 nesting += 1
587 text = message_to_string(value.data, nesting)
588 if text != "":
589 result += "\n" + text
590 nesting -= 1
591 result += tabulate("}", nesting)
592 else:
593 nesting -= 1
594 result += "}"
595 elif field.type == PB_DATA_TYPE.BYTES:
596 result += "<"
597 for i in range(value.size()):
598 result += str(value[i])
599 if i != (value.size() - 1):
600 result += ", "
601 result += ">"
602 elif field.type == PB_DATA_TYPE.STRING:
603 result += "\"" + value + "\""
604 elif field.type == PB_DATA_TYPE.ENUM:
605 result += "ENUM::" + str(value)
606 else:
607 result += str(value)
608 return result
609
610 static func field_to_string(field : PBField, nesting : int) -> String:
611 var result : String = tabulate(field.name + ": ", nesting)
612 if field.type == PB_DATA_TYPE.MAP:
613 if field.value.size() > 0:
614 result += "(\n"
615 nesting += 1
616 for i in range(field.value.size()):
617 var local_key_value = field.value[i].data[1].field
618 result += tabulate(value_to_string(local_key_value.value, local_key_value, nesting), nesting) + ": "
619 local_key_value = field.value[i].data[2].field
620 result += value_to_string(local_key_value.value, local_key_value, nesting)
621 if i != (field.value.size() - 1):
622 result += ","
623 result += "\n"
624 nesting -= 1
625 result += tabulate(")", nesting)
626 else:
627 result += "()"
628 elif field.rule == PB_RULE.REPEATED:
629 if field.value.size() > 0:
630 result += "[\n"
631 nesting += 1
632 for i in range(field.value.size()):
633 result += tabulate(str(i) + ": ", nesting)
634 result += value_to_string(field.value[i], field, nesting)
635 if i != (field.value.size() - 1):
636 result += ","
637 result += "\n"
638 nesting -= 1
639 result += tabulate("]", nesting)
640 else:
641 result += "[]"
642 else:
643 result += value_to_string(field.value, field, nesting)
644 result += ";\n"
645 return result
646
647 static func message_to_string(data, nesting : int = 0) -> String:
648 var DEFAULT_VALUES
649 if PROTO_VERSION == 2:
650 DEFAULT_VALUES = DEFAULT_VALUES_2
651 elif PROTO_VERSION == 3:
652 DEFAULT_VALUES = DEFAULT_VALUES_3
653 var result : String = ""
654 var keys : Array = data.keys()
655 keys.sort()
656 for i in keys:
657 if data[i].field.value != null:
658 if data[i].state == PB_SERVICE_STATE.UNFILLED \
659 && !data[i].field.is_map_field \
660 && typeof(data[i].field.value) == typeof(DEFAULT_VALUES[data[i].field.type]) \
661 && data[i].field.value == DEFAULT_VALUES[data[i].field.type]:
662 continue
663 elif data[i].field.rule == PB_RULE.REPEATED && data[i].field.value.size() == 0:
664 continue
665 result += field_to_string(data[i].field, nesting)
666 elif data[i].field.rule == PB_RULE.REQUIRED:
667 result += data[i].field.name + ": " + "error"
668 return result
diff --git a/vendor/godobuf/addons/protobuf/protobuf_util.gd b/vendor/godobuf/addons/protobuf/protobuf_util.gd new file mode 100644 index 0000000..5941cb8 --- /dev/null +++ b/vendor/godobuf/addons/protobuf/protobuf_util.gd
@@ -0,0 +1,46 @@
1#
2# BSD 3-Clause License
3#
4# Copyright (c) 2018, Oleg Malyavkin
5# All rights reserved.
6#
7# Redistribution and use in source and binary forms, with or without
8# modification, are permitted provided that the following conditions are met:
9#
10# * Redistributions of source code must retain the above copyright notice, this
11# list of conditions and the following disclaimer.
12#
13# * Redistributions in binary form must reproduce the above copyright notice,
14# this list of conditions and the following disclaimer in the documentation
15# and/or other materials provided with the distribution.
16#
17# * Neither the name of the copyright holder nor the names of its
18# contributors may be used to endorse or promote products derived from
19# this software without specific prior written permission.
20#
21# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
25# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31
32static func extract_dir(file_path):
33 var parts = file_path.split("/", false)
34 parts.remove_at(parts.size() - 1)
35 var path
36 if file_path.begins_with("/"):
37 path = "/"
38 else:
39 path = ""
40 for part in parts:
41 path += part + "/"
42 return path
43
44static func extract_filename(file_path):
45 var parts = file_path.split("/", false)
46 return parts[parts.size() - 1]
diff --git a/vendor/godobuf/default_env.tres b/vendor/godobuf/default_env.tres new file mode 100644 index 0000000..20207a4 --- /dev/null +++ b/vendor/godobuf/default_env.tres
@@ -0,0 +1,7 @@
1[gd_resource type="Environment" load_steps=2 format=2]
2
3[sub_resource type="ProceduralSky" id=1]
4
5[resource]
6background_mode = 2
7background_sky = SubResource( 1 )
diff --git a/vendor/godobuf/logo.png b/vendor/godobuf/logo.png new file mode 100644 index 0000000..4ff9029 --- /dev/null +++ b/vendor/godobuf/logo.png
Binary files differ
diff --git a/vendor/godobuf/logo.png.import b/vendor/godobuf/logo.png.import new file mode 100644 index 0000000..43df7a6 --- /dev/null +++ b/vendor/godobuf/logo.png.import
@@ -0,0 +1,35 @@
1[remap]
2
3importer="texture"
4type="StreamTexture"
5path="res://.import/logo.png-cca8726399059c8d4f806e28e356b14d.stex"
6metadata={
7"vram_texture": false
8}
9
10[deps]
11
12source_file="res://logo.png"
13dest_files=[ "res://.import/logo.png-cca8726399059c8d4f806e28e356b14d.stex" ]
14
15[params]
16
17compress/mode=0
18compress/lossy_quality=0.7
19compress/hdr_mode=0
20compress/bptc_ldr=0
21compress/normal_map=0
22flags/repeat=0
23flags/filter=true
24flags/mipmaps=false
25flags/anisotropic=false
26flags/srgb=2
27process/fix_alpha_border=true
28process/premult_alpha=false
29process/HDR_as_SRGB=false
30process/invert_color=false
31process/normal_map_invert_y=false
32stream=false
33size_limit=0
34detect_3d=true
35svg/scale=1.0
diff --git a/vendor/godobuf/project.godot b/vendor/godobuf/project.godot new file mode 100644 index 0000000..8cef0a4 --- /dev/null +++ b/vendor/godobuf/project.godot
@@ -0,0 +1,26 @@
1; Engine configuration file.
2; It's best edited using the editor UI and not directly,
3; since the parameters that go here are not all obvious.
4;
5; Format:
6; [section] ; section goes between []
7; param=value ; assign values to parameters
8
9config_version=4
10
11_global_script_classes=[ ]
12_global_script_class_icons={
13}
14
15[application]
16
17config/name="Protobuf Plugin"
18config/icon="res://logo.png"
19
20[editor_plugins]
21
22enabled=PoolStringArray( "res://addons/protobuf/plugin.cfg" )
23
24[rendering]
25
26environment/default_environment="res://default_env.tres"