From c5c0c02c0369145242d56aefa58b158b10c66e65 Mon Sep 17 00:00:00 2001 From: Zsolt Tasnadi Date: Sun, 30 Aug 2026 23:21:06 +0200 Subject: [PATCH] dirs --- CLAUDE.md | 230 +++++++++--------- README.md | 102 ++++---- inc/{ => background}/background.alley.go | 7 +- .../background.bbs_terminal.go | 7 +- inc/{ => background}/background.bvk_branch.go | 7 +- .../background.columbarium.go | 7 +- .../background.curator_shop.go | 7 +- .../background.hackerspace.go | 7 +- inc/{ => background}/background.hospital.go | 7 +- .../background.ice_cream_shop.go | 7 +- inc/{ => background}/background.manager.go | 4 +- .../background.noodle_house.go | 7 +- .../background.norman_apartment.go | 7 +- inc/{ => background}/background.paul_shop.go | 7 +- .../background.police_station.go | 7 +- inc/{ => background}/background.public_bbs.go | 7 +- .../background.rooftop_hideout.go | 7 +- .../background.samizdat_press.go | 7 +- .../background.scrap_market.go | 7 +- .../background.secret_club.go | 7 +- inc/{ => background}/background.secret_lab.go | 7 +- inc/{ => background}/background.selector.go | 7 +- .../background.server_farm.go | 7 +- inc/{ => background}/background.showroom.go | 7 +- .../background.small_restaurant.go | 7 +- inc/{ => background}/background.street.go | 7 +- .../background.trinket_shop.go | 7 +- inc/boot.go | 64 ----- inc/boot/boot.go | 63 +++++ inc/character.dex.go | 14 -- inc/character.mystery_tape.go | 14 -- inc/character.paul.go | 19 -- inc/character.support_tape.go | 14 -- inc/character/character.dex.go | 16 ++ inc/{ => character}/character.manager.go | 4 +- inc/character/character.mystery_tape.go | 16 ++ inc/character/character.paul.go | 21 ++ inc/character/character.support_tape.go | 16 ++ inc/{names.manager.go => constants.go} | 5 + inc/{ => dialog}/dialog.dex_talk.go | 21 +- inc/{ => dialog}/dialog.manager.go | 4 +- .../dialog.mystery_tape_silent.go | 11 +- inc/item.black_market_armilla.go | 22 -- inc/item.mystery_tape.go | 16 -- inc/item.noodle_letter.go | 16 -- inc/item/item.black_market_armilla.go | 23 ++ inc/{ => item}/item.manager.go | 4 +- inc/item/item.mystery_tape.go | 17 ++ inc/item/item.noodle_letter.go | 17 ++ inc/scene.alley.go | 100 -------- inc/scene.trinket_shop.go | 28 --- inc/scene/scene.alley.go | 101 ++++++++ inc/{ => scene}/scene.bbs_terminal.go | 9 +- inc/{ => scene}/scene.bvk_branch.go | 9 +- inc/{ => scene}/scene.columbarium.go | 9 +- inc/{ => scene}/scene.curator_shop.go | 9 +- inc/{ => scene}/scene.hackerspace.go | 9 +- inc/{ => scene}/scene.hospital.go | 9 +- inc/{ => scene}/scene.ice_cream_shop.go | 9 +- inc/{ => scene}/scene.manager.go | 9 +- inc/{ => scene}/scene.noodle_house.go | 11 +- inc/{ => scene}/scene.norman_apartment.go | 13 +- inc/{ => scene}/scene.paul_shop.go | 11 +- inc/{ => scene}/scene.police_station.go | 9 +- inc/{ => scene}/scene.public_bbs.go | 9 +- inc/{ => scene}/scene.rooftop_hideout.go | 13 +- inc/{ => scene}/scene.samizdat_press.go | 9 +- inc/{ => scene}/scene.scrap_market.go | 9 +- inc/{ => scene}/scene.secret_club.go | 13 +- inc/{ => scene}/scene.secret_lab.go | 9 +- inc/{ => scene}/scene.selector.go | 21 +- inc/{ => scene}/scene.server_farm.go | 9 +- inc/{ => scene}/scene.showroom.go | 9 +- inc/{ => scene}/scene.small_restaurant.go | 11 +- inc/{ => scene}/scene.street.go | 9 +- inc/scene/scene.trinket_shop.go | 29 +++ inc/script.awakening_finale.go | 23 -- inc/script.opening.go | 16 -- inc/script.tape_insert.go | 25 -- inc/script/script.awakening_finale.go | 25 ++ inc/{ => script}/script.manager.go | 4 +- inc/script/script.opening.go | 17 ++ inc/script/script.tape_insert.go | 27 ++ inc/{ => script}/script.usewith_fail.go | 14 +- inc/tape.dex.go | 8 - inc/tape.manager.go | 32 --- inc/tape.mystery.go | 9 - inc/tape.support.go | 7 - inc/tape/tape.dex.go | 12 + inc/tape/tape.manager.go | 39 +++ inc/tape/tape.mystery.go | 13 + inc/tape/tape.support.go | 11 + inc/{ => theme}/theme.manager.go | 7 +- inc/{ => theme}/theme.nokia_punk.go | 10 +- inc/{ => theme}/theme.realworld.go | 10 +- inc/widget.top_bar.go | 15 -- inc/{ => widget}/widget.cursor.go | 4 +- inc/{ => widget}/widget.dialog_box.go | 4 +- inc/{ => widget}/widget.end_card.go | 4 +- inc/{ => widget}/widget.hotspot_debug.go | 4 +- inc/{ => widget}/widget.hud_frame.go | 4 +- inc/{ => widget}/widget.inventory_bar.go | 4 +- inc/{ => widget}/widget.letterbox.go | 17 +- inc/{ => widget}/widget.manager.go | 12 +- inc/{ => widget}/widget.radial_verbs.go | 4 +- inc/{ => widget}/widget.scene_nav.go | 4 +- inc/{ => widget}/widget.speech_bubble.go | 4 +- inc/{ => widget}/widget.status_line.go | 4 +- inc/{ => widget}/widget.tape_channel.go | 12 +- inc/{ => widget}/widget.tape_slots.go | 41 ++-- inc/widget/widget.top_bar.go | 16 ++ inc/world.manager.go | 65 ----- inc/{ => world}/world.action.go | 27 +- inc/world/world.manager.go | 57 +++++ main.go | 6 +- 115 files changed, 1083 insertions(+), 950 deletions(-) rename inc/{ => background}/background.alley.go (55%) rename inc/{ => background}/background.bbs_terminal.go (55%) rename inc/{ => background}/background.bvk_branch.go (55%) rename inc/{ => background}/background.columbarium.go (54%) rename inc/{ => background}/background.curator_shop.go (55%) rename inc/{ => background}/background.hackerspace.go (54%) rename inc/{ => background}/background.hospital.go (54%) rename inc/{ => background}/background.ice_cream_shop.go (55%) rename inc/{ => background}/background.manager.go (58%) rename inc/{ => background}/background.noodle_house.go (55%) rename inc/{ => background}/background.norman_apartment.go (54%) rename inc/{ => background}/background.paul_shop.go (55%) rename inc/{ => background}/background.police_station.go (54%) rename inc/{ => background}/background.public_bbs.go (55%) rename inc/{ => background}/background.rooftop_hideout.go (54%) rename inc/{ => background}/background.samizdat_press.go (54%) rename inc/{ => background}/background.scrap_market.go (55%) rename inc/{ => background}/background.secret_club.go (55%) rename inc/{ => background}/background.secret_lab.go (55%) rename inc/{ => background}/background.selector.go (54%) rename inc/{ => background}/background.server_farm.go (55%) rename inc/{ => background}/background.showroom.go (54%) rename inc/{ => background}/background.small_restaurant.go (54%) rename inc/{ => background}/background.street.go (55%) rename inc/{ => background}/background.trinket_shop.go (55%) delete mode 100644 inc/boot.go create mode 100644 inc/boot/boot.go delete mode 100644 inc/character.dex.go delete mode 100644 inc/character.mystery_tape.go delete mode 100644 inc/character.paul.go delete mode 100644 inc/character.support_tape.go create mode 100644 inc/character/character.dex.go rename inc/{ => character}/character.manager.go (59%) create mode 100644 inc/character/character.mystery_tape.go create mode 100644 inc/character/character.paul.go create mode 100644 inc/character/character.support_tape.go rename inc/{names.manager.go => constants.go} (97%) rename inc/{ => dialog}/dialog.dex_talk.go (52%) rename inc/{ => dialog}/dialog.manager.go (61%) rename inc/{ => dialog}/dialog.mystery_tape_silent.go (68%) delete mode 100644 inc/item.black_market_armilla.go delete mode 100644 inc/item.mystery_tape.go delete mode 100644 inc/item.noodle_letter.go create mode 100644 inc/item/item.black_market_armilla.go rename inc/{ => item}/item.manager.go (61%) create mode 100644 inc/item/item.mystery_tape.go create mode 100644 inc/item/item.noodle_letter.go delete mode 100644 inc/scene.alley.go delete mode 100644 inc/scene.trinket_shop.go create mode 100644 inc/scene/scene.alley.go rename inc/{ => scene}/scene.bbs_terminal.go (61%) rename inc/{ => scene}/scene.bvk_branch.go (54%) rename inc/{ => scene}/scene.columbarium.go (53%) rename inc/{ => scene}/scene.curator_shop.go (55%) rename inc/{ => scene}/scene.hackerspace.go (51%) rename inc/{ => scene}/scene.hospital.go (54%) rename inc/{ => scene}/scene.ice_cream_shop.go (54%) rename inc/{ => scene}/scene.manager.go (69%) rename inc/{ => scene}/scene.noodle_house.go (58%) rename inc/{ => scene}/scene.norman_apartment.go (58%) rename inc/{ => scene}/scene.paul_shop.go (57%) rename inc/{ => scene}/scene.police_station.go (52%) rename inc/{ => scene}/scene.public_bbs.go (52%) rename inc/{ => scene}/scene.rooftop_hideout.go (57%) rename inc/{ => scene}/scene.samizdat_press.go (52%) rename inc/{ => scene}/scene.scrap_market.go (51%) rename inc/{ => scene}/scene.secret_club.go (59%) rename inc/{ => scene}/scene.secret_lab.go (54%) rename inc/{ => scene}/scene.selector.go (74%) rename inc/{ => scene}/scene.server_farm.go (51%) rename inc/{ => scene}/scene.showroom.go (53%) rename inc/{ => scene}/scene.small_restaurant.go (55%) rename inc/{ => scene}/scene.street.go (52%) create mode 100644 inc/scene/scene.trinket_shop.go delete mode 100644 inc/script.awakening_finale.go delete mode 100644 inc/script.opening.go delete mode 100644 inc/script.tape_insert.go create mode 100644 inc/script/script.awakening_finale.go rename inc/{ => script}/script.manager.go (60%) create mode 100644 inc/script/script.opening.go create mode 100644 inc/script/script.tape_insert.go rename inc/{ => script}/script.usewith_fail.go (74%) delete mode 100644 inc/tape.dex.go delete mode 100644 inc/tape.manager.go delete mode 100644 inc/tape.mystery.go delete mode 100644 inc/tape.support.go create mode 100644 inc/tape/tape.dex.go create mode 100644 inc/tape/tape.manager.go create mode 100644 inc/tape/tape.mystery.go create mode 100644 inc/tape/tape.support.go rename inc/{ => theme}/theme.manager.go (83%) rename inc/{ => theme}/theme.nokia_punk.go (90%) rename inc/{ => theme}/theme.realworld.go (90%) delete mode 100644 inc/widget.top_bar.go rename inc/{ => widget}/widget.cursor.go (65%) rename inc/{ => widget}/widget.dialog_box.go (79%) rename inc/{ => widget}/widget.end_card.go (65%) rename inc/{ => widget}/widget.hotspot_debug.go (64%) rename inc/{ => widget}/widget.hud_frame.go (95%) rename inc/{ => widget}/widget.inventory_bar.go (81%) rename inc/{ => widget}/widget.letterbox.go (74%) rename inc/{ => widget}/widget.manager.go (60%) rename inc/{ => widget}/widget.radial_verbs.go (81%) rename inc/{ => widget}/widget.scene_nav.go (69%) rename inc/{ => widget}/widget.speech_bubble.go (75%) rename inc/{ => widget}/widget.status_line.go (79%) rename inc/{ => widget}/widget.tape_channel.go (89%) rename inc/{ => widget}/widget.tape_slots.go (68%) create mode 100644 inc/widget/widget.top_bar.go delete mode 100644 inc/world.manager.go rename inc/{ => world}/world.action.go (77%) create mode 100644 inc/world/world.manager.go diff --git a/CLAUDE.md b/CLAUDE.md index bb75925..87eaaac 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -45,71 +45,72 @@ This holds for nested literals too, including small ones such as ## Layout -All game code lives in one flat package, `inc`. There are no subdirectories: a -file's name carries the structure, in the form `[category].[name].go`. +One category, one package, one directory. A file keeps the category in its own +name anyway — `[category].[name].go` inside `inc/[category]/` — because the +prefix is what makes a file findable in a list of editor tabs, a grep, or a +diff, where the directory has already fallen off. - The category is always **singular**: `item`, `scene`, `background`, - `character`, `tape`, `dialog`, `script`, `world`, `widget`, `theme`, `names`. -- `[category].manager.go` is the file that ties a category together — its - entity type and whatever else the category shares. -- Every other file in a category holds exactly one entity: one scene, one + `character`, `tape`, `dialog`, `script`, `world`, `widget`, `theme`. +- `[category].manager.go` is the file that ties a package together — its entity + type, its `Manager`, and whatever else the category shares. +- Every other file in a package holds exactly one entity: one scene, one background, one item. The file registers it itself, in an `init()`. -- `boot.go` is the exception that has no category: it declares every manager - and builds the game. +- Two files have no category. `inc/constants.go` is the vocabulary every + package imports, and `inc/boot/boot.go` builds the game. ``` -main.go flags + inkwell.Run -inc/boot.go the managers; New(Opts) builds the game -inc/names.manager.go entity names and world-state keys -inc/theme.manager.go the Theme alias and the colour helpers -inc/theme.realworld.go realworld-93 -inc/theme.nokia_punk.go nokia-punk -inc/world.manager.go unsaved runtime state -inc/world.action.go custom actions -inc/widget.manager.go the Widget alias, HUD layout, the shared conditions -inc/widget.*.go one widget per file, registering itself -inc/background.*.go one image asset per scene -inc/character.*.go the cast, tapes included -inc/tape.manager.go the Tape entity and the lookups over it -inc/tape.*.go one tape per file -inc/item.*.go inventory -inc/dialog.*.go dialogue trees -inc/script.*.go named action sequences -inc/scene.manager.go the Scene alias, the defaults every scene gets -inc/scene.selector.go the map screen: its pins are derived from the graph -inc/scene.*.go one file per scene +main.go flags + inkwell.Run +inc/constants.go entity names and world-state keys +inc/boot/boot.go New(Opts) builds the game +inc/theme/theme.manager.go the Theme alias, its Manager, RGB/RGBA +inc/theme/theme.realworld.go realworld-93 +inc/theme/theme.nokia_punk.go nokia-punk +inc/world/world.manager.go unsaved runtime state +inc/world/world.action.go custom actions +inc/tape/tape.manager.go the Tape entity and the lookups over it +inc/tape/tape.*.go one tape per file +inc/widget/widget.manager.go the Widget alias, HUD layout, the conditions +inc/widget/widget.*.go one widget per file, registering itself +inc/background/background.*.go one image asset per scene +inc/character/character.*.go the cast, tapes included +inc/item/item.*.go inventory +inc/dialog/dialog.*.go dialogue trees +inc/script/script.*.go named action sequences +inc/scene/scene.manager.go the Scene alias, its Manager, the floor +inc/scene/scene.selector.go the map screen: pins derived from the graph +inc/scene/scene.*.go one file per scene ``` +`inc` is constants and nothing else, so every package can import it and it can +import none of them. That is also why `New` sits in `inc/boot` rather than in +`inc`: a package cannot be imported by what it imports, and the assembly is the +one thing that has to name every package at once. + ## Managers Every category that owns a collection of entities has a manager, and they are all the engine's own `inkwell.Manager[T]` — the same registry type the `*Game` hangs its content off. The game defines no registry of its own. -All nine are declared together, in `boot.go`, so the list of what the game -holds is one block rather than a line hidden in each category file: +Each one is declared in its own package's manager file, beside the alias it +holds, and it needs no prefix because the package already is one: ```go -var ( - BackgroundManager = inkwell.NewManager[Background]() - CharacterManager = inkwell.NewManager[Character]() - DialogManager = inkwell.NewManager[Dialog]() - ItemManager = inkwell.NewManager[Item]() - SceneManager = inkwell.NewManager[Scene]() - ScriptManager = inkwell.NewManager[Script]() - TapeManager = inkwell.NewManager[Tape]() - ThemeManager = inkwell.NewManager[Theme]() - WidgetManager = inkwell.NewManager[Widget]() -) -``` +// inc/character/character.manager.go +package character -The entity types stay in their own category files, one alias each, and that is -all a manager file holds now: - -```go type Character = inkwell.Character + +var Manager = inkwell.NewManager[Character]() ``` +Read from `inc/boot` the nine of them still line up as a list — +`background.Manager`, `character.Manager`, `dialog.Manager`, `item.Manager`, +`scene.Manager`, `script.Manager`, `tape.Manager`, `theme.Manager`, +`widget.Manager` — only now the list is a consequence of the imports rather +than a block someone has to keep in step. + Aliases of engine structs already carry `GetName()` and satisfy `inkwell.Named`, which is the whole of what a manager asks of them. @@ -126,8 +127,8 @@ the engine, so there is nothing left for a second type to hold. `Tape` is the exception, and it is a real one: a tape is a cassette that speaks, a thing inkwell has no notion of. It names the character whose voice it is, the item that carries it and the dialogue it plays, and `tape.manager.go` holds the -four lookups over the registry — `IsTape`, `TapeOf`, `IsTapeItem`, -`TapeDialogue`. What a tape *sounds* like is not in it: the display name and the +four lookups over the registry — `tape.Is`, `tape.Of`, `tape.IsItem`, +`tape.Dialogue`. What a tape *sounds* like is not in it: the display name and the log-only voice are `Character.Label` and `Character.Voice`, because those are facts about a speaker, not about a cassette. @@ -138,11 +139,11 @@ somewhere else to keep in step — the file hands itself to its manager in an `init()`: ```go -package inc +package background func init() { - BackgroundManager.Register(Background{ - Name: BgServerFarm, + Manager.Register(Background{ + Name: inc.BgServerFarm, Path: "assets/bg/server_farm.png", Kind: inkwell.AssetImage, }) @@ -151,13 +152,18 @@ func init() { Adding an entity is adding a file. Deleting one is deleting a file. Package-level variables are initialised before any `init()` runs, whatever file each sits in, -so the managers in `boot.go` exist by the time the first entity file registers -into one. +so a package's `Manager` exists by the time its first entity file registers into +one. `init()` order is file-name order, so **registration order is alphabetical**. Nothing may depend on it — including the order the arrow keys walk the scenes, which is simply the order the files sit in. +An `init()` only runs if something imports the package. `inc/boot` names eight +of the nine for their `Manager`, which is import enough; `tape` is the one +nobody names, so it is there as a blank import. That list is **per package, not +per entity** — a new scene file still touches nothing but itself. + ### Widgets name their layer instead of their order A widget is a file like any other entity — `widget..go`, one widget, @@ -166,7 +172,7 @@ which the game registers as literals the same way it registers a background: ```go func init() { - WidgetManager.Register(&inkwell.Cursor{ + Manager.Register(&inkwell.Cursor{ Name: "cursor", }) } @@ -193,7 +199,7 @@ hidden for a cutscene, and that is a condition over game state, not a wrapper and not an `if` at the top of every `Draw`: ```go -WidgetManager.Register(&inkwell.StatusLine{ +Manager.Register(&inkwell.StatusLine{ Name: "status", When: whenPlaying, Y: statusY, @@ -201,7 +207,7 @@ WidgetManager.Register(&inkwell.StatusLine{ ``` `whenPlaying`, `whenCutscene` and `whenUnpaused` are in `widget.manager.go`, and -they read `VarMode` and `VarNote` out of the engine's own `State`. A widget of +they read `inc.VarMode` and `inc.VarNote` out of the engine's own `State`. A widget of ours says the same thing with a method — `VisibleWhen() inkwell.Condition` — because it has no literal to put a field in. A widget that is switched off neither ticks nor draws nor blocks a click, so nothing else has to ask. @@ -213,14 +219,14 @@ hands ours over in their place — the types are identical, so the engine and th game end up sharing one registry per category rather than two in step: ```go -g.AssetManager = BackgroundManager -g.CharacterManager = CharacterManager -g.DialogueManager = DialogManager -g.ItemManager = ItemManager -g.SceneManager = SceneManager -g.ScriptManager = ScriptManager -g.WidgetManager = WidgetManager -ThemeManager.Each(g.ThemeManager.Register) +g.AssetManager = background.Manager +g.CharacterManager = character.Manager +g.DialogueManager = dialog.Manager +g.ItemManager = item.Manager +g.SceneManager = scene.Manager +g.ScriptManager = script.Manager +g.WidgetManager = widget.Manager +theme.Manager.Each(g.ThemeManager.Register) ``` Themes are the odd one out and stay a copy: `NewGame` puts four preset themes @@ -241,14 +247,14 @@ saying "the usual", and the selector opts out by declaring both empty. ### What runs at boot `New` names two scripts and nothing else — the opening a player sees is content -like every other script, in `script.opening.go`, not a slice built in the +like every other script, in `script/script.opening.go`, not a slice built in the wiring: ```go g.StartAt(start) -g.OnStart(ScriptOpening) +g.OnStart(inc.ScriptOpening) if o.Finale { - g.OnFinale(ScriptFinale) + g.OnFinale(inc.ScriptFinale) } ``` @@ -261,60 +267,64 @@ something this package used to carry itself: ```go g.WindowScale = 2 -g.Player = Paul -g.Walkboxes = sceneFloor -g.UseWithFail = useWithFail +g.Player = inc.Paul +g.Walkboxes = scene.Floor +g.UseWithFail = script.UseWithFail ``` `UseWithFail` is the response to a use-with pair nobody authored — the engine asks for it the same way it asks for `ExitLook` and `ExitTake`, and the lines -live with the rest of the writing, in `script.usewith_fail.go`. +live with the rest of the writing, in `script/script.usewith_fail.go`. ## The world -There is exactly one game, so there is exactly one world: `World`, a -package-level singleton in `world.manager.go`. Nothing takes a `*world` -parameter and no widget holds a back-reference — `World.Do(…)`, `World.Mode()`, -`World.Slot2()` are reachable from anywhere in the package. `New` calls -`World.attach(g)`, which binds the engine and resets the runtime state, so -building the game twice is clean. +There is exactly one game, so there is exactly one world — and since there is +exactly one, the **package is the singleton**. There is no `World` value to pass +around and no back-reference for a widget to hold: `world.Do(…)`, +`world.Slot2()`, `world.SetPending(…)` are reachable from anywhere that imports +`world`. `New` calls `world.Attach(g)`, which binds the engine and resets the +run state, so building the game twice is clean. -`World` holds as little as it can get away with. The mode and the top bar's -note are `State` vars (`VarMode`, `VarNote`), because state the engine can see -is state a `Condition` can read — that is what makes a widget's `When` possible -and what puts "— paused" in the top bar without anyone pushing it there. -`World.Do` hands its action to `g.Do`, the engine's queue, so the game runs one -action at a time without a pump of its own. What is left in the struct is the -two things the engine has no notion of: the tape waiting to speak, and the -cassette on its way into slot 2. +`world` holds as little as it can get away with. The mode and the top bar's note +are `State` vars (`inc.VarMode`, `inc.VarNote`), because state the engine can +see is state a `Condition` can read — that is what makes a widget's `When` +possible and what puts "— paused" in the top bar without anyone pushing it +there. `world.Do` hands its action to `g.Do`, the engine's queue, so the game +runs one action at a time without a pump of its own. What is left in package +variables is the two things the engine has no notion of: the tape waiting to +speak, and the cassette on its way into slot 2. Only `world.Attach` resets them. This is what lets an entity file be a literal: the tape-insert script closes -over `World`, not over a parameter it would have had to be handed. +over the `world` package, not over a parameter it would have had to be handed. ## Naming -One package means one namespace, so an entity's constructor carries its -category as a prefix: +The package is the namespace now, so an identifier never repeats what the +package already says. It is `scene.Floor`, not `scene.SceneFloor`; +`tape.Dialogue`, not `tape.TapeDialogue`; `widget.Manager`, not +`widget.WidgetManager`; `world.Do`, not `world.WorldDo`. Read the call site, not +the declaration, when choosing a name: ```go -sceneFloor fillSelectorPins tapeSlots useWithFail +scene.FillSelectorPins() tape.Is(speaker) world.Do(a) widget.ScreenW ``` Entities themselves need no name at all — they are anonymous literals inside their file's `init()`, and the file name says which one it is. Exported names are the authoring vocabulary — what a content file spells out: -`New` and `Opts`, `World`, the managers and the entity types they hold, the -constants in `names.manager.go`, the colour tokens, the tape lookups -(`IsTape`, `TapeOf`, `IsTapeItem`, `TapeDialogue`) and the action constructors -(`Paused`, `SetMode`, `UseTheme`, `TapeOffer`, `Fn`). A tape's line is -`inkwell.Say` like anyone else's — the tape voice is on the character, not on a -second spelling of Say. +`boot.New` and `boot.Opts`, the constants in `inc/constants.go`, each package's +`Manager` and entity type, the colour tokens, the tape lookups (`tape.Is`, +`tape.Of`, `tape.IsItem`, `tape.Dialogue`), the world (`world.Do`, +`world.Slot2`, …) and the action constructors (`world.Paused`, `world.SetMode`, +`world.UseTheme`, `world.TapeOffer`, `world.Fn`). A tape's line is `inkwell.Say` +like anyone else's — the tape voice is on the character, not on a second +spelling of Say. -Everything else is machinery and stays unexported: the HUD widgets -(`tapeSlots`, `letterbox`, `hudFrame`, …), the conditions (`whenPlaying`, -`whenCutscene`, `whenUnpaused`), the runners, `useWithFail`, -`fillSelectorPins`. +Everything else stays unexported, and now the compiler holds the line: the HUD +widgets (`tapeSlots`, `letterbox`, `hudFrame`, …), the conditions +(`whenPlaying`, `whenCutscene`, `whenUnpaused`), the runners, `setMode`, +`setNote`, `setVarIfEmpty`. The word is **scene**, the engine's own. The wiki and the concept-art deck count *screens*, and this code used to as well, but everything a screen had that a @@ -323,23 +333,25 @@ display: `ScreenW`, `ScreenH`. ## Layering -Nothing is enforced by the compiler any more, so the layering is a rule kept by -hand: +The layering is the import graph, so the compiler keeps it: ``` -names ← theme ← world ← widget - ↑ ↑ - content ───┴── boot ← main +inc ← theme ← world ← tape ← widget ← boot ← main + ↑ ↑ ↑ + └── content ───────────────────-┘ ``` -`world` knows nothing about the HUD or the content. Both build on it, never the -other way round. +`inc` imports nothing and everything imports it. `world` knows nothing about the +HUD or the content; both build on it, never the other way round — and an arrow +pointing back is now an import cycle, not a review comment. The one edge worth +knowing is `widget → tape`: the tape slots ask which cassette a tape is in, so +the tape concept sits below the HUD rather than beside it. ## Adding a scene -1. Constants in `inc/names.manager.go`: `Scene`, `Bg` -2. `inc/scene..go` — an `init()` registering a `Scene` -3. `inc/background..go` — an `init()` registering a `Background` +1. Constants in `inc/constants.go`: `Scene`, `Bg` +2. `inc/scene/scene..go` — an `init()` registering a `Scene` +3. `inc/background/background..go` — an `init()` registering a `Background` 4. A 640×380 PNG in `assets/bg/` Nothing else moves. There is no list to update. diff --git a/README.md b/README.md index 21d6dcc..3f9d8d0 100644 --- a/README.md +++ b/README.md @@ -110,7 +110,7 @@ Every pixel it gives back is a pixel of art. ``` Every vertical measurement derives from `LineH` (glyph cell + leading) and from -`ScreenH`, both in `widget.manager.go`, not from the wireframe deck's ratios, so +`ScreenH`, both in `widget/widget.manager.go`, not from the wireframe deck's ratios, so the layout cannot drift out of step with the font — or with the art — again; `TestLayoutFitsTheFont` guards it. The tape channel comes out at 4 rows of 38 columns, which is about one and a half of Dex's remarks on screen at once. @@ -150,74 +150,76 @@ licence. ## Structure -The game is one flat package, `inc`. There are no subdirectories: a file's -name says where it belongs, in the form `[category].[name].go`. The category is -always singular, and `[category].manager.go` is the file that ties that category -together — its entity type and whatever else the category shares. `boot.go` is -the one file with no category: it declares every manager and builds the game. +One category, one package, one directory. A file still says which entity it +holds in its own name — `[category].[name].go`, the prefix repeated inside the +directory that already carries it, because a file called `alley.go` tells you +nothing in a list of open editor tabs. ``` -main.go flags + inkwell.Run -inc/boot.go the managers, and New(Opts) -inc/names.manager.go entity names and world-state keys -inc/theme.*.go realworld-93 + nokia-punk -inc/world.*.go unsaved runtime state and custom actions -inc/widget.manager.go HUD layout and the shared visibility conditions -inc/widget.*.go one widget per file -inc/..go one file per registered entity, by kind +main.go flags + inkwell.Run +inc/constants.go every name and state key; imports nothing +inc/boot/ New(Opts): the hand-off to the engine +inc/theme/ the Theme alias, RGB, realworld-93, nokia-punk +inc/world/ the run state and the custom actions +inc/tape/ the Tape entity and the lookups over it +inc/widget/ HUD layout, the visibility conditions, 14 widgets +inc/scene/ inc/background/ one file per location, twice +inc/item/ inc/character/ inc/dialog/ inc/script/ ``` -Nothing is enforced by the compiler any more, so the layering is a rule the -code keeps by hand: the world holds no opinion about the HUD or the content, and -both build on it, never the other way round. +`inc` itself holds nothing but constants, which is why every package can import +it and it can import none of them. The consequence is that the assembly moved +down rather than up: `New` lives in `inc/boot`, because a package cannot be +imported by what it imports. + +The layering is no longer a rule kept by hand — it is the import graph, and the +compiler rejects the arrow that points the wrong way: ``` -names ← theme ← world ← widget - ↑ ↑ - content ───┴── boot ← main +inc ← theme ← world ← tape ← widget ← boot ← main + ↑ ↑ ↑ + └── content ───────────────────-┘ ``` -Content is one registered entity per file, and the category prefix groups them -the way directories used to: - -``` -background.*.go one file per scene: background.paul_shop.go, … -character.*.go character.paul.go character.dex.go character.mystery_tape.go -item.*.go item.noodle_letter.go item.black_market_armilla.go … -dialog.*.go dialog.dex_talk.go dialog.mystery_tape_silent.go -script.*.go script.tape_insert.go script.awakening_finale.go -scene.*.go one file per scene: scene.alley.go, … + scene.selector.go -``` - -Adding a scene means adding `scene..go` and `background..go`. -Nothing else moves. +Adding a scene means adding `inc/scene/scene..go` and +`inc/background/background..go`. Nothing else moves. Every category owns a manager, and they are all the engine's own `inkwell.Manager[T]` — the same registry the `*Game` hangs its content off, kept in registration order and addressed by name. There is no second registry type here: the entity types are aliases of engine structs, so they already satisfy -`inkwell.Named` and need no help reading their own name. The eight of them are -declared as one block in `boot.go`, and a category's manager file is left -holding the alias: +`inkwell.Named` and need no help reading their own name. Each one lives in its +own package's manager file, next to the alias it holds, and it needs no prefix +because the package already is one: ```go +// inc/character/character.manager.go type Character = inkwell.Character + +var Manager = inkwell.NewManager[Character]() ``` An entity file is a literal that hands itself over in an `init()`: ```go +package background + func init() { - BackgroundManager.Register(Background{ - Name: BgServerFarm, + Manager.Register(Background{ + Name: inc.BgServerFarm, Path: "assets/bg/server_farm.png", Kind: inkwell.AssetImage, }) } ``` -Widgets go the same way, the engine's own included: `widget.cursor.go` registers -an `inkwell.Cursor` exactly as `background.street.go` registers an image. What +The `init()` only runs if something imports the package, so a package whose +entities nobody names by symbol needs a blank import in `inc/boot`. Exactly one +does — `tape`, everything else is imported for its `Manager` — and the list is +per package, not per entity, so adding a file is still adding a file. + +Widgets go the same way, the engine's own included: `widget/widget.cursor.go` registers +an `inkwell.Cursor` exactly as `background/background.street.go` registers an image. What they cannot take from alphabetical order is their place in the stack, so each widget names a **layer** — `LayerScene`, `LayerPanel`, `LayerHUD`, `LayerSpeech`, `LayerDialog`, `LayerMenu`, `LayerCurtain`, `LayerCursor` — and inkwell draws @@ -248,7 +250,7 @@ step with the files by hand, and the deck is a thing to look at, not a thing to play through. The game's own catalogue is readable without going through the engine: -`SceneManager.Get("alley")` answers long before there is a `*Game` to ask. And +`scene.Manager.Get("alley")` answers long before there is a `*Game` to ask. And when the game is built, nothing is copied into it — `New` assigns our managers onto the `*Game` in place of the empty ones `NewGame` made, so engine and game share one registry per category instead of keeping two of them in step. Themes @@ -261,12 +263,16 @@ his `Start`, and `g.Walkboxes` is the floor a scene without one walks on. Both are fields on the `*Game`, so a scene file that says nothing about either means "the usual", and the selector opts out by declaring both empty. What is still written back before the hand-off is the derived half of the map: -`fillSelectorPins` reads the exit graph backwards and `Set`s the selector. +`scene.FillSelectorPins` reads the exit graph backwards and `Set`s the selector. -There is one world, and it is a package-level singleton: `World`. Nothing takes -a `*world` parameter and no widget holds a back-reference, which is what lets a -script file be a literal — the tape-insert script closes over `World` rather -than over a parameter someone would have had to thread to it. +There is one world, and now the package *is* the singleton: `world.Do(…)`, +`world.Slot2()`, `world.SetPending(…)`. Nothing takes a world parameter and no +widget holds a back-reference, which is what lets a script file be a literal — +the tape-insert script closes over the `world` package rather than over a +parameter someone would have had to thread to it. What little it still keeps is +in package-level variables that only `world.Attach` may reset; the mode and the +top bar's note are not among them, because those are `State` vars the engine +itself can see. **On the word "scene".** The wiki, the concept-art deck and the beat tables all count *screens*, and this code used to as well: it carried its own `Screen` @@ -293,7 +299,7 @@ edge and so does the code: - **The selector** — the wiki centres its map on a *Helyszínválasztó*, "nem valódi helyszín, hanem a menü-képernyő": a scene every main location connects to both ways. A main location lists `exitToSelector` among its exits, and - `scene.selector.go` derives the other half of each edge by reading the graph + `scene/scene.selector.go` derives the other half of each edge by reading the graph backwards — every scene with an exit to the selector gets a pin on it. The list of locations on the map is never written down twice. diff --git a/inc/background.alley.go b/inc/background/background.alley.go similarity index 55% rename from inc/background.alley.go rename to inc/background/background.alley.go index 3e41030..b6c7c89 100644 --- a/inc/background.alley.go +++ b/inc/background/background.alley.go @@ -1,12 +1,13 @@ -package inc +package background import ( inkwell "git.teletypegames.org/engines/inkwell" + "git.teletypegames.org/games/realworld/inc" ) func init() { - BackgroundManager.Register(Background{ - Name: BgAlley, + Manager.Register(Background{ + Name: inc.BgAlley, Path: "assets/bg/alley.png", Kind: inkwell.AssetImage, }) diff --git a/inc/background.bbs_terminal.go b/inc/background/background.bbs_terminal.go similarity index 55% rename from inc/background.bbs_terminal.go rename to inc/background/background.bbs_terminal.go index 554c26c..b89d026 100644 --- a/inc/background.bbs_terminal.go +++ b/inc/background/background.bbs_terminal.go @@ -1,12 +1,13 @@ -package inc +package background import ( inkwell "git.teletypegames.org/engines/inkwell" + "git.teletypegames.org/games/realworld/inc" ) func init() { - BackgroundManager.Register(Background{ - Name: BgBBSTerminal, + Manager.Register(Background{ + Name: inc.BgBBSTerminal, Path: "assets/bg/bbs_terminal.png", Kind: inkwell.AssetImage, }) diff --git a/inc/background.bvk_branch.go b/inc/background/background.bvk_branch.go similarity index 55% rename from inc/background.bvk_branch.go rename to inc/background/background.bvk_branch.go index 34dc762..effed6b 100644 --- a/inc/background.bvk_branch.go +++ b/inc/background/background.bvk_branch.go @@ -1,12 +1,13 @@ -package inc +package background import ( inkwell "git.teletypegames.org/engines/inkwell" + "git.teletypegames.org/games/realworld/inc" ) func init() { - BackgroundManager.Register(Background{ - Name: BgBVKBranch, + Manager.Register(Background{ + Name: inc.BgBVKBranch, Path: "assets/bg/bvk_branch.png", Kind: inkwell.AssetImage, }) diff --git a/inc/background.columbarium.go b/inc/background/background.columbarium.go similarity index 54% rename from inc/background.columbarium.go rename to inc/background/background.columbarium.go index 6ae9602..b2bbc68 100644 --- a/inc/background.columbarium.go +++ b/inc/background/background.columbarium.go @@ -1,12 +1,13 @@ -package inc +package background import ( inkwell "git.teletypegames.org/engines/inkwell" + "git.teletypegames.org/games/realworld/inc" ) func init() { - BackgroundManager.Register(Background{ - Name: BgColumbarium, + Manager.Register(Background{ + Name: inc.BgColumbarium, Path: "assets/bg/columbarium.png", Kind: inkwell.AssetImage, }) diff --git a/inc/background.curator_shop.go b/inc/background/background.curator_shop.go similarity index 55% rename from inc/background.curator_shop.go rename to inc/background/background.curator_shop.go index 89a79a0..b3be621 100644 --- a/inc/background.curator_shop.go +++ b/inc/background/background.curator_shop.go @@ -1,12 +1,13 @@ -package inc +package background import ( inkwell "git.teletypegames.org/engines/inkwell" + "git.teletypegames.org/games/realworld/inc" ) func init() { - BackgroundManager.Register(Background{ - Name: BgCuratorShop, + Manager.Register(Background{ + Name: inc.BgCuratorShop, Path: "assets/bg/curator_shop.png", Kind: inkwell.AssetImage, }) diff --git a/inc/background.hackerspace.go b/inc/background/background.hackerspace.go similarity index 54% rename from inc/background.hackerspace.go rename to inc/background/background.hackerspace.go index 314e26d..dc43a07 100644 --- a/inc/background.hackerspace.go +++ b/inc/background/background.hackerspace.go @@ -1,12 +1,13 @@ -package inc +package background import ( inkwell "git.teletypegames.org/engines/inkwell" + "git.teletypegames.org/games/realworld/inc" ) func init() { - BackgroundManager.Register(Background{ - Name: BgHackerspace, + Manager.Register(Background{ + Name: inc.BgHackerspace, Path: "assets/bg/hackerspace.png", Kind: inkwell.AssetImage, }) diff --git a/inc/background.hospital.go b/inc/background/background.hospital.go similarity index 54% rename from inc/background.hospital.go rename to inc/background/background.hospital.go index ffb5f34..04f8eda 100644 --- a/inc/background.hospital.go +++ b/inc/background/background.hospital.go @@ -1,12 +1,13 @@ -package inc +package background import ( inkwell "git.teletypegames.org/engines/inkwell" + "git.teletypegames.org/games/realworld/inc" ) func init() { - BackgroundManager.Register(Background{ - Name: BgHospital, + Manager.Register(Background{ + Name: inc.BgHospital, Path: "assets/bg/hospital.png", Kind: inkwell.AssetImage, }) diff --git a/inc/background.ice_cream_shop.go b/inc/background/background.ice_cream_shop.go similarity index 55% rename from inc/background.ice_cream_shop.go rename to inc/background/background.ice_cream_shop.go index 78229e8..9f68421 100644 --- a/inc/background.ice_cream_shop.go +++ b/inc/background/background.ice_cream_shop.go @@ -1,12 +1,13 @@ -package inc +package background import ( inkwell "git.teletypegames.org/engines/inkwell" + "git.teletypegames.org/games/realworld/inc" ) func init() { - BackgroundManager.Register(Background{ - Name: BgIceCreamShop, + Manager.Register(Background{ + Name: inc.BgIceCreamShop, Path: "assets/bg/ice_cream_shop.png", Kind: inkwell.AssetImage, }) diff --git a/inc/background.manager.go b/inc/background/background.manager.go similarity index 58% rename from inc/background.manager.go rename to inc/background/background.manager.go index 0750b98..027233d 100644 --- a/inc/background.manager.go +++ b/inc/background/background.manager.go @@ -1,7 +1,9 @@ -package inc +package background import ( inkwell "git.teletypegames.org/engines/inkwell" ) type Background = inkwell.Asset + +var Manager = inkwell.NewManager[Background]() diff --git a/inc/background.noodle_house.go b/inc/background/background.noodle_house.go similarity index 55% rename from inc/background.noodle_house.go rename to inc/background/background.noodle_house.go index 741c02b..17deb3c 100644 --- a/inc/background.noodle_house.go +++ b/inc/background/background.noodle_house.go @@ -1,12 +1,13 @@ -package inc +package background import ( inkwell "git.teletypegames.org/engines/inkwell" + "git.teletypegames.org/games/realworld/inc" ) func init() { - BackgroundManager.Register(Background{ - Name: BgNoodleHouse, + Manager.Register(Background{ + Name: inc.BgNoodleHouse, Path: "assets/bg/noodle_house.png", Kind: inkwell.AssetImage, }) diff --git a/inc/background.norman_apartment.go b/inc/background/background.norman_apartment.go similarity index 54% rename from inc/background.norman_apartment.go rename to inc/background/background.norman_apartment.go index 0a53152..627e686 100644 --- a/inc/background.norman_apartment.go +++ b/inc/background/background.norman_apartment.go @@ -1,12 +1,13 @@ -package inc +package background import ( inkwell "git.teletypegames.org/engines/inkwell" + "git.teletypegames.org/games/realworld/inc" ) func init() { - BackgroundManager.Register(Background{ - Name: BgNormanApartment, + Manager.Register(Background{ + Name: inc.BgNormanApartment, Path: "assets/bg/norman_apartment.png", Kind: inkwell.AssetImage, }) diff --git a/inc/background.paul_shop.go b/inc/background/background.paul_shop.go similarity index 55% rename from inc/background.paul_shop.go rename to inc/background/background.paul_shop.go index 9dc2a5e..3b3be10 100644 --- a/inc/background.paul_shop.go +++ b/inc/background/background.paul_shop.go @@ -1,12 +1,13 @@ -package inc +package background import ( inkwell "git.teletypegames.org/engines/inkwell" + "git.teletypegames.org/games/realworld/inc" ) func init() { - BackgroundManager.Register(Background{ - Name: BgPaulShop, + Manager.Register(Background{ + Name: inc.BgPaulShop, Path: "assets/bg/paul_shop.png", Kind: inkwell.AssetImage, }) diff --git a/inc/background.police_station.go b/inc/background/background.police_station.go similarity index 54% rename from inc/background.police_station.go rename to inc/background/background.police_station.go index 345718c..fd19810 100644 --- a/inc/background.police_station.go +++ b/inc/background/background.police_station.go @@ -1,12 +1,13 @@ -package inc +package background import ( inkwell "git.teletypegames.org/engines/inkwell" + "git.teletypegames.org/games/realworld/inc" ) func init() { - BackgroundManager.Register(Background{ - Name: BgPoliceStation, + Manager.Register(Background{ + Name: inc.BgPoliceStation, Path: "assets/bg/police_station.png", Kind: inkwell.AssetImage, }) diff --git a/inc/background.public_bbs.go b/inc/background/background.public_bbs.go similarity index 55% rename from inc/background.public_bbs.go rename to inc/background/background.public_bbs.go index 77fd301..df52791 100644 --- a/inc/background.public_bbs.go +++ b/inc/background/background.public_bbs.go @@ -1,12 +1,13 @@ -package inc +package background import ( inkwell "git.teletypegames.org/engines/inkwell" + "git.teletypegames.org/games/realworld/inc" ) func init() { - BackgroundManager.Register(Background{ - Name: BgPublicBBS, + Manager.Register(Background{ + Name: inc.BgPublicBBS, Path: "assets/bg/public_bbs.png", Kind: inkwell.AssetImage, }) diff --git a/inc/background.rooftop_hideout.go b/inc/background/background.rooftop_hideout.go similarity index 54% rename from inc/background.rooftop_hideout.go rename to inc/background/background.rooftop_hideout.go index 2fd6e3c..42e1455 100644 --- a/inc/background.rooftop_hideout.go +++ b/inc/background/background.rooftop_hideout.go @@ -1,12 +1,13 @@ -package inc +package background import ( inkwell "git.teletypegames.org/engines/inkwell" + "git.teletypegames.org/games/realworld/inc" ) func init() { - BackgroundManager.Register(Background{ - Name: BgRooftopHideout, + Manager.Register(Background{ + Name: inc.BgRooftopHideout, Path: "assets/bg/rooftop_hideout.png", Kind: inkwell.AssetImage, }) diff --git a/inc/background.samizdat_press.go b/inc/background/background.samizdat_press.go similarity index 54% rename from inc/background.samizdat_press.go rename to inc/background/background.samizdat_press.go index ec0848e..9994faa 100644 --- a/inc/background.samizdat_press.go +++ b/inc/background/background.samizdat_press.go @@ -1,12 +1,13 @@ -package inc +package background import ( inkwell "git.teletypegames.org/engines/inkwell" + "git.teletypegames.org/games/realworld/inc" ) func init() { - BackgroundManager.Register(Background{ - Name: BgSamizdatPress, + Manager.Register(Background{ + Name: inc.BgSamizdatPress, Path: "assets/bg/samizdat_press.png", Kind: inkwell.AssetImage, }) diff --git a/inc/background.scrap_market.go b/inc/background/background.scrap_market.go similarity index 55% rename from inc/background.scrap_market.go rename to inc/background/background.scrap_market.go index c1d1d8f..8080628 100644 --- a/inc/background.scrap_market.go +++ b/inc/background/background.scrap_market.go @@ -1,12 +1,13 @@ -package inc +package background import ( inkwell "git.teletypegames.org/engines/inkwell" + "git.teletypegames.org/games/realworld/inc" ) func init() { - BackgroundManager.Register(Background{ - Name: BgScrapMarket, + Manager.Register(Background{ + Name: inc.BgScrapMarket, Path: "assets/bg/scrap_market.png", Kind: inkwell.AssetImage, }) diff --git a/inc/background.secret_club.go b/inc/background/background.secret_club.go similarity index 55% rename from inc/background.secret_club.go rename to inc/background/background.secret_club.go index 3562278..cd7cef6 100644 --- a/inc/background.secret_club.go +++ b/inc/background/background.secret_club.go @@ -1,12 +1,13 @@ -package inc +package background import ( inkwell "git.teletypegames.org/engines/inkwell" + "git.teletypegames.org/games/realworld/inc" ) func init() { - BackgroundManager.Register(Background{ - Name: BgSecretClub, + Manager.Register(Background{ + Name: inc.BgSecretClub, Path: "assets/bg/secret_club.png", Kind: inkwell.AssetImage, }) diff --git a/inc/background.secret_lab.go b/inc/background/background.secret_lab.go similarity index 55% rename from inc/background.secret_lab.go rename to inc/background/background.secret_lab.go index 4df46c0..1c41dec 100644 --- a/inc/background.secret_lab.go +++ b/inc/background/background.secret_lab.go @@ -1,12 +1,13 @@ -package inc +package background import ( inkwell "git.teletypegames.org/engines/inkwell" + "git.teletypegames.org/games/realworld/inc" ) func init() { - BackgroundManager.Register(Background{ - Name: BgSecretLab, + Manager.Register(Background{ + Name: inc.BgSecretLab, Path: "assets/bg/secret_lab.png", Kind: inkwell.AssetImage, }) diff --git a/inc/background.selector.go b/inc/background/background.selector.go similarity index 54% rename from inc/background.selector.go rename to inc/background/background.selector.go index 89f749d..fec08a5 100644 --- a/inc/background.selector.go +++ b/inc/background/background.selector.go @@ -1,12 +1,13 @@ -package inc +package background import ( inkwell "git.teletypegames.org/engines/inkwell" + "git.teletypegames.org/games/realworld/inc" ) func init() { - BackgroundManager.Register(Background{ - Name: BgSelector, + Manager.Register(Background{ + Name: inc.BgSelector, Path: "assets/bg/selector.png", Kind: inkwell.AssetImage, }) diff --git a/inc/background.server_farm.go b/inc/background/background.server_farm.go similarity index 55% rename from inc/background.server_farm.go rename to inc/background/background.server_farm.go index 7429316..1bc01ca 100644 --- a/inc/background.server_farm.go +++ b/inc/background/background.server_farm.go @@ -1,12 +1,13 @@ -package inc +package background import ( inkwell "git.teletypegames.org/engines/inkwell" + "git.teletypegames.org/games/realworld/inc" ) func init() { - BackgroundManager.Register(Background{ - Name: BgServerFarm, + Manager.Register(Background{ + Name: inc.BgServerFarm, Path: "assets/bg/server_farm.png", Kind: inkwell.AssetImage, }) diff --git a/inc/background.showroom.go b/inc/background/background.showroom.go similarity index 54% rename from inc/background.showroom.go rename to inc/background/background.showroom.go index 3e6df5a..95accf5 100644 --- a/inc/background.showroom.go +++ b/inc/background/background.showroom.go @@ -1,12 +1,13 @@ -package inc +package background import ( inkwell "git.teletypegames.org/engines/inkwell" + "git.teletypegames.org/games/realworld/inc" ) func init() { - BackgroundManager.Register(Background{ - Name: BgShowroom, + Manager.Register(Background{ + Name: inc.BgShowroom, Path: "assets/bg/showroom.png", Kind: inkwell.AssetImage, }) diff --git a/inc/background.small_restaurant.go b/inc/background/background.small_restaurant.go similarity index 54% rename from inc/background.small_restaurant.go rename to inc/background/background.small_restaurant.go index d55a428..0e91730 100644 --- a/inc/background.small_restaurant.go +++ b/inc/background/background.small_restaurant.go @@ -1,12 +1,13 @@ -package inc +package background import ( inkwell "git.teletypegames.org/engines/inkwell" + "git.teletypegames.org/games/realworld/inc" ) func init() { - BackgroundManager.Register(Background{ - Name: BgSmallRestaurant, + Manager.Register(Background{ + Name: inc.BgSmallRestaurant, Path: "assets/bg/small_restaurant.png", Kind: inkwell.AssetImage, }) diff --git a/inc/background.street.go b/inc/background/background.street.go similarity index 55% rename from inc/background.street.go rename to inc/background/background.street.go index df179f1..89da64f 100644 --- a/inc/background.street.go +++ b/inc/background/background.street.go @@ -1,12 +1,13 @@ -package inc +package background import ( inkwell "git.teletypegames.org/engines/inkwell" + "git.teletypegames.org/games/realworld/inc" ) func init() { - BackgroundManager.Register(Background{ - Name: BgStreet, + Manager.Register(Background{ + Name: inc.BgStreet, Path: "assets/bg/street.png", Kind: inkwell.AssetImage, }) diff --git a/inc/background.trinket_shop.go b/inc/background/background.trinket_shop.go similarity index 55% rename from inc/background.trinket_shop.go rename to inc/background/background.trinket_shop.go index 5accce1..b1d287d 100644 --- a/inc/background.trinket_shop.go +++ b/inc/background/background.trinket_shop.go @@ -1,12 +1,13 @@ -package inc +package background import ( inkwell "git.teletypegames.org/engines/inkwell" + "git.teletypegames.org/games/realworld/inc" ) func init() { - BackgroundManager.Register(Background{ - Name: BgTrinketShop, + Manager.Register(Background{ + Name: inc.BgTrinketShop, Path: "assets/bg/trinket_shop.png", Kind: inkwell.AssetImage, }) diff --git a/inc/boot.go b/inc/boot.go deleted file mode 100644 index c51f820..0000000 --- a/inc/boot.go +++ /dev/null @@ -1,64 +0,0 @@ -package inc - -import ( - inkwell "git.teletypegames.org/engines/inkwell" -) - -var ( - BackgroundManager = inkwell.NewManager[Background]() - CharacterManager = inkwell.NewManager[Character]() - DialogManager = inkwell.NewManager[Dialog]() - ItemManager = inkwell.NewManager[Item]() - SceneManager = inkwell.NewManager[Scene]() - ScriptManager = inkwell.NewManager[Script]() - TapeManager = inkwell.NewManager[Tape]() - ThemeManager = inkwell.NewManager[Theme]() - WidgetManager = inkwell.NewManager[Widget]() -) - -type Opts struct { - Scene string - Finale bool -} - -func New(o Opts) *inkwell.Game { - start := o.Scene - if start == "" { - start = SceneAlley - } - - fillSelectorPins() - - g := inkwell.NewGame("Real World", ScreenW, ScreenH) - g.MaxLogLines = 64 - g.WindowScale = 2 - g.SceneRect = inkwell.Rect(0, TopBarH, ScreenW, HUDTop-TopBarH) - g.Player = Paul - g.Walkboxes = sceneFloor - g.ExitLook = func(e inkwell.Exit) inkwell.Action { - return inkwell.Say(Paul, "That way: "+e.Label+".") - } - g.ExitTake = func(inkwell.Exit) inkwell.Action { - return inkwell.Say(Paul, "It's a way out, not a thing.") - } - g.UseWithFail = useWithFail - - g.AssetManager = BackgroundManager - g.CharacterManager = CharacterManager - g.DialogueManager = DialogManager - g.ItemManager = ItemManager - g.SceneManager = SceneManager - g.ScriptManager = ScriptManager - g.WidgetManager = WidgetManager - ThemeManager.Each(g.ThemeManager.Register) - - World.attach(g) - g.UseTheme(RealWorld) - - g.StartAt(start) - g.OnStart(ScriptOpening) - if o.Finale { - g.OnFinale(ScriptFinale) - } - return g -} diff --git a/inc/boot/boot.go b/inc/boot/boot.go new file mode 100644 index 0000000..2e93127 --- /dev/null +++ b/inc/boot/boot.go @@ -0,0 +1,63 @@ +package boot + +import ( + inkwell "git.teletypegames.org/engines/inkwell" + "git.teletypegames.org/games/realworld/inc" + "git.teletypegames.org/games/realworld/inc/background" + "git.teletypegames.org/games/realworld/inc/character" + "git.teletypegames.org/games/realworld/inc/dialog" + "git.teletypegames.org/games/realworld/inc/item" + "git.teletypegames.org/games/realworld/inc/scene" + "git.teletypegames.org/games/realworld/inc/script" + _ "git.teletypegames.org/games/realworld/inc/tape" + "git.teletypegames.org/games/realworld/inc/theme" + "git.teletypegames.org/games/realworld/inc/widget" + "git.teletypegames.org/games/realworld/inc/world" +) + +type Opts struct { + Scene string + Finale bool +} + +func New(o Opts) *inkwell.Game { + start := o.Scene + if start == "" { + start = inc.SceneAlley + } + + scene.FillSelectorPins() + + g := inkwell.NewGame("Real World", widget.ScreenW, widget.ScreenH) + g.MaxLogLines = 64 + g.WindowScale = 2 + g.SceneRect = inkwell.Rect(0, widget.TopBarH, widget.ScreenW, widget.HUDTop-widget.TopBarH) + g.Player = inc.Paul + g.Walkboxes = scene.Floor + g.ExitLook = func(e inkwell.Exit) inkwell.Action { + return inkwell.Say(inc.Paul, "That way: "+e.Label+".") + } + g.ExitTake = func(inkwell.Exit) inkwell.Action { + return inkwell.Say(inc.Paul, "It's a way out, not a thing.") + } + g.UseWithFail = script.UseWithFail + + g.AssetManager = background.Manager + g.CharacterManager = character.Manager + g.DialogueManager = dialog.Manager + g.ItemManager = item.Manager + g.SceneManager = scene.Manager + g.ScriptManager = script.Manager + g.WidgetManager = widget.Manager + theme.Manager.Each(g.ThemeManager.Register) + + world.Attach(g) + g.UseTheme(inc.RealWorld) + + g.StartAt(start) + g.OnStart(inc.ScriptOpening) + if o.Finale { + g.OnFinale(inc.ScriptFinale) + } + return g +} diff --git a/inc/character.dex.go b/inc/character.dex.go deleted file mode 100644 index d8ac78e..0000000 --- a/inc/character.dex.go +++ /dev/null @@ -1,14 +0,0 @@ -package inc - -import ( - inkwell "git.teletypegames.org/engines/inkwell" -) - -func init() { - CharacterManager.Register(Character{ - Name: Dex, - Label: "DEX", - Voice: inkwell.VoiceLog, - SpeechColor: Amber, - }) -} diff --git a/inc/character.mystery_tape.go b/inc/character.mystery_tape.go deleted file mode 100644 index b10f417..0000000 --- a/inc/character.mystery_tape.go +++ /dev/null @@ -1,14 +0,0 @@ -package inc - -import ( - inkwell "git.teletypegames.org/engines/inkwell" -) - -func init() { - CharacterManager.Register(Character{ - Name: TapeMystery, - Label: "UNKNOWN TAPE", - Voice: inkwell.VoiceLog, - SpeechColor: RGB(0xB9A98A), - }) -} diff --git a/inc/character.paul.go b/inc/character.paul.go deleted file mode 100644 index 34c3e77..0000000 --- a/inc/character.paul.go +++ /dev/null @@ -1,19 +0,0 @@ -package inc - -import ( - inkwell "git.teletypegames.org/engines/inkwell" -) - -func init() { - CharacterManager.Register(Character{ - Name: Paul, - Speed: 96, - W: 28, - H: 68, - Start: inkwell.Point{ - X: 320, - Y: 232, - }, - SpeechColor: Ink, - }) -} diff --git a/inc/character.support_tape.go b/inc/character.support_tape.go deleted file mode 100644 index 02e0fef..0000000 --- a/inc/character.support_tape.go +++ /dev/null @@ -1,14 +0,0 @@ -package inc - -import ( - inkwell "git.teletypegames.org/engines/inkwell" -) - -func init() { - CharacterManager.Register(Character{ - Name: TapeSupport, - Label: "TECH SUPPORT", - Voice: inkwell.VoiceLog, - SpeechColor: RGB(0xE8C86A), - }) -} diff --git a/inc/character/character.dex.go b/inc/character/character.dex.go new file mode 100644 index 0000000..508d6c8 --- /dev/null +++ b/inc/character/character.dex.go @@ -0,0 +1,16 @@ +package character + +import ( + inkwell "git.teletypegames.org/engines/inkwell" + "git.teletypegames.org/games/realworld/inc" + "git.teletypegames.org/games/realworld/inc/theme" +) + +func init() { + Manager.Register(Character{ + Name: inc.Dex, + Label: "DEX", + Voice: inkwell.VoiceLog, + SpeechColor: theme.Amber, + }) +} diff --git a/inc/character.manager.go b/inc/character/character.manager.go similarity index 59% rename from inc/character.manager.go rename to inc/character/character.manager.go index 5130b94..d9207bc 100644 --- a/inc/character.manager.go +++ b/inc/character/character.manager.go @@ -1,7 +1,9 @@ -package inc +package character import ( inkwell "git.teletypegames.org/engines/inkwell" ) type Character = inkwell.Character + +var Manager = inkwell.NewManager[Character]() diff --git a/inc/character/character.mystery_tape.go b/inc/character/character.mystery_tape.go new file mode 100644 index 0000000..5c24b32 --- /dev/null +++ b/inc/character/character.mystery_tape.go @@ -0,0 +1,16 @@ +package character + +import ( + inkwell "git.teletypegames.org/engines/inkwell" + "git.teletypegames.org/games/realworld/inc" + "git.teletypegames.org/games/realworld/inc/theme" +) + +func init() { + Manager.Register(Character{ + Name: inc.TapeMystery, + Label: "UNKNOWN TAPE", + Voice: inkwell.VoiceLog, + SpeechColor: theme.RGB(0xB9A98A), + }) +} diff --git a/inc/character/character.paul.go b/inc/character/character.paul.go new file mode 100644 index 0000000..dd22268 --- /dev/null +++ b/inc/character/character.paul.go @@ -0,0 +1,21 @@ +package character + +import ( + inkwell "git.teletypegames.org/engines/inkwell" + "git.teletypegames.org/games/realworld/inc" + "git.teletypegames.org/games/realworld/inc/theme" +) + +func init() { + Manager.Register(Character{ + Name: inc.Paul, + Speed: 96, + W: 28, + H: 68, + Start: inkwell.Point{ + X: 320, + Y: 232, + }, + SpeechColor: theme.Ink, + }) +} diff --git a/inc/character/character.support_tape.go b/inc/character/character.support_tape.go new file mode 100644 index 0000000..8182973 --- /dev/null +++ b/inc/character/character.support_tape.go @@ -0,0 +1,16 @@ +package character + +import ( + inkwell "git.teletypegames.org/engines/inkwell" + "git.teletypegames.org/games/realworld/inc" + "git.teletypegames.org/games/realworld/inc/theme" +) + +func init() { + Manager.Register(Character{ + Name: inc.TapeSupport, + Label: "TECH SUPPORT", + Voice: inkwell.VoiceLog, + SpeechColor: theme.RGB(0xE8C86A), + }) +} diff --git a/inc/names.manager.go b/inc/constants.go similarity index 97% rename from inc/names.manager.go rename to inc/constants.go index 1dcc42d..2a3c269 100644 --- a/inc/names.manager.go +++ b/inc/constants.go @@ -14,6 +14,11 @@ const ( ItemBlackArmilla = "black_market_armilla" ) +const ( + RealWorld = "realworld-93" + NokiaPunk = "nokia-punk" +) + const ( DlgDex = "dex_talk" DlgMysteryTape = "mystery_tape_silent" diff --git a/inc/dialog.dex_talk.go b/inc/dialog/dialog.dex_talk.go similarity index 52% rename from inc/dialog.dex_talk.go rename to inc/dialog/dialog.dex_talk.go index 27b66a2..6c15cc4 100644 --- a/inc/dialog.dex_talk.go +++ b/inc/dialog/dialog.dex_talk.go @@ -1,40 +1,41 @@ -package inc +package dialog import ( inkwell "git.teletypegames.org/engines/inkwell" + "git.teletypegames.org/games/realworld/inc" ) func init() { - DialogManager.Register(Dialog{ - Name: DlgDex, + Manager.Register(Dialog{ + Name: inc.DlgDex, Start: "root", Nodes: []inkwell.DialogueNode{{ Name: "root", Lines: []inkwell.DialogueLine{{ - Speaker: Dex, + Speaker: inc.Dex, Text: "Talk.", }}, Choices: []inkwell.DialogueChoice{ { Text: "What am I doing here, Dex?", Actions: []inkwell.Action{ - inkwell.Say(Dex, "You got a letter from a man you hadn't seen in twenty years. And you came. That says more about you than it does about him."), + inkwell.Say(inc.Dex, "You got a letter from a man you hadn't seen in twenty years. And you came. That says more about you than it does about him."), inkwell.GotoNode("root"), }, }, { Text: "What do you know about Noodle?", - Show: inkwell.Not(inkwell.Flag(FlagHasTape)), + Show: inkwell.Not(inkwell.Flag(inc.FlagHasTape)), Actions: []inkwell.Action{ - inkwell.Say(Dex, "He traded cracked Armillas. That isn't charity, Paul, that's a business. The kind they take you in for."), + inkwell.Say(inc.Dex, "He traded cracked Armillas. That isn't charity, Paul, that's a business. The kind they take you in for."), inkwell.GotoNode("root"), }, }, { Text: "What do you make of this tape?", - Show: inkwell.Flag(FlagHasTape), + Show: inkwell.Flag(inc.FlagHasTape), Actions: []inkwell.Action{ - inkwell.Say(Dex, "I make of it that you found a password-locked tape in a gap between two bins, on a tip from a government office. Count how many times that has ended well."), + inkwell.Say(inc.Dex, "I make of it that you found a password-locked tape in a gap between two bins, on a tip from a government office. Count how many times that has ended well."), inkwell.GotoNode("root"), }, }, @@ -42,7 +43,7 @@ func init() { Text: "I miss you.", Once: true, Actions: []inkwell.Action{ - inkwell.Say(Dex, "I'm four kilobytes of a dead man. Don't do this to yourself."), + inkwell.Say(inc.Dex, "I'm four kilobytes of a dead man. Don't do this to yourself."), inkwell.GotoNode("root"), }, }, diff --git a/inc/dialog.manager.go b/inc/dialog/dialog.manager.go similarity index 61% rename from inc/dialog.manager.go rename to inc/dialog/dialog.manager.go index a7038f8..0df4e13 100644 --- a/inc/dialog.manager.go +++ b/inc/dialog/dialog.manager.go @@ -1,7 +1,9 @@ -package inc +package dialog import ( inkwell "git.teletypegames.org/engines/inkwell" ) type Dialog = inkwell.Dialogue + +var Manager = inkwell.NewManager[Dialog]() diff --git a/inc/dialog.mystery_tape_silent.go b/inc/dialog/dialog.mystery_tape_silent.go similarity index 68% rename from inc/dialog.mystery_tape_silent.go rename to inc/dialog/dialog.mystery_tape_silent.go index ae19a27..93af76c 100644 --- a/inc/dialog.mystery_tape_silent.go +++ b/inc/dialog/dialog.mystery_tape_silent.go @@ -1,24 +1,25 @@ -package inc +package dialog import ( inkwell "git.teletypegames.org/engines/inkwell" + "git.teletypegames.org/games/realworld/inc" ) func init() { - DialogManager.Register(Dialog{ - Name: DlgMysteryTape, + Manager.Register(Dialog{ + Name: inc.DlgMysteryTape, Start: "root", Nodes: []inkwell.DialogueNode{{ Name: "root", Lines: []inkwell.DialogueLine{{ - Speaker: Dex, + Speaker: inc.Dex, Text: "Nothing. Warm, spinning, and silent.", }}, Choices: []inkwell.DialogueChoice{ { Text: "Are you sure it works?", Actions: []inkwell.Action{ - inkwell.Say(Dex, "It works. It just isn't talking to you. That is not the same as silence."), + inkwell.Say(inc.Dex, "It works. It just isn't talking to you. That is not the same as silence."), inkwell.GotoNode("root"), }, }, diff --git a/inc/item.black_market_armilla.go b/inc/item.black_market_armilla.go deleted file mode 100644 index 8fa23b2..0000000 --- a/inc/item.black_market_armilla.go +++ /dev/null @@ -1,22 +0,0 @@ -package inc - -import ( - inkwell "git.teletypegames.org/engines/inkwell" -) - -func init() { - ItemManager.Register(Item{ - Name: ItemBlackArmilla, - Description: "black-market Armilla", - OnUseSelf: inkwell.Seq( - inkwell.Say(Paul, "Jailbroken. Pushes ads, but it was cheap."), - inkwell.Say(Dex, "Two slots, and both of them lie about the temperature. Don't trade me in for it."), - ), - OnUseWith: map[string]inkwell.Action{ - ItemNoodleLetter: inkwell.Seq( - inkwell.Say(Paul, "A letter and a bracelet. Brilliant."), - inkwell.Say(Dex, "Nothing. Which is what I'd charge for it."), - ), - }, - }) -} diff --git a/inc/item.mystery_tape.go b/inc/item.mystery_tape.go deleted file mode 100644 index b61608d..0000000 --- a/inc/item.mystery_tape.go +++ /dev/null @@ -1,16 +0,0 @@ -package inc - -import ( - inkwell "git.teletypegames.org/engines/inkwell" -) - -func init() { - ItemManager.Register(Item{ - Name: ItemMysteryTape, - Description: "unmarked Personal Tape", - OnUseSelf: inkwell.Seq( - inkwell.Say(Paul, "Password-locked. Of course."), - inkwell.Say(Dex, "Put it in the second slot if you care that much. I did warn you."), - ), - }) -} diff --git a/inc/item.noodle_letter.go b/inc/item.noodle_letter.go deleted file mode 100644 index b6f2365..0000000 --- a/inc/item.noodle_letter.go +++ /dev/null @@ -1,16 +0,0 @@ -package inc - -import ( - inkwell "git.teletypegames.org/engines/inkwell" -) - -func init() { - ItemManager.Register(Item{ - Name: ItemNoodleLetter, - Description: "Noodle's letter", - OnUseSelf: inkwell.Seq( - inkwell.Say(Paul, "“Come out, Paul. Not a phone conversation.” That's all it says."), - inkwell.Say(Dex, "And now you're here. And he isn't."), - ), - }) -} diff --git a/inc/item/item.black_market_armilla.go b/inc/item/item.black_market_armilla.go new file mode 100644 index 0000000..75ade05 --- /dev/null +++ b/inc/item/item.black_market_armilla.go @@ -0,0 +1,23 @@ +package item + +import ( + inkwell "git.teletypegames.org/engines/inkwell" + "git.teletypegames.org/games/realworld/inc" +) + +func init() { + Manager.Register(Item{ + Name: inc.ItemBlackArmilla, + Description: "black-market Armilla", + OnUseSelf: inkwell.Seq( + inkwell.Say(inc.Paul, "Jailbroken. Pushes ads, but it was cheap."), + inkwell.Say(inc.Dex, "Two slots, and both of them lie about the temperature. Don't trade me in for it."), + ), + OnUseWith: map[string]inkwell.Action{ + inc.ItemNoodleLetter: inkwell.Seq( + inkwell.Say(inc.Paul, "A letter and a bracelet. Brilliant."), + inkwell.Say(inc.Dex, "Nothing. Which is what I'd charge for it."), + ), + }, + }) +} diff --git a/inc/item.manager.go b/inc/item/item.manager.go similarity index 61% rename from inc/item.manager.go rename to inc/item/item.manager.go index 8fa2c89..357992c 100644 --- a/inc/item.manager.go +++ b/inc/item/item.manager.go @@ -1,7 +1,9 @@ -package inc +package item import ( inkwell "git.teletypegames.org/engines/inkwell" ) type Item = inkwell.Item + +var Manager = inkwell.NewManager[Item]() diff --git a/inc/item/item.mystery_tape.go b/inc/item/item.mystery_tape.go new file mode 100644 index 0000000..129d0f5 --- /dev/null +++ b/inc/item/item.mystery_tape.go @@ -0,0 +1,17 @@ +package item + +import ( + inkwell "git.teletypegames.org/engines/inkwell" + "git.teletypegames.org/games/realworld/inc" +) + +func init() { + Manager.Register(Item{ + Name: inc.ItemMysteryTape, + Description: "unmarked Personal Tape", + OnUseSelf: inkwell.Seq( + inkwell.Say(inc.Paul, "Password-locked. Of course."), + inkwell.Say(inc.Dex, "Put it in the second slot if you care that much. I did warn you."), + ), + }) +} diff --git a/inc/item/item.noodle_letter.go b/inc/item/item.noodle_letter.go new file mode 100644 index 0000000..eda87df --- /dev/null +++ b/inc/item/item.noodle_letter.go @@ -0,0 +1,17 @@ +package item + +import ( + inkwell "git.teletypegames.org/engines/inkwell" + "git.teletypegames.org/games/realworld/inc" +) + +func init() { + Manager.Register(Item{ + Name: inc.ItemNoodleLetter, + Description: "Noodle's letter", + OnUseSelf: inkwell.Seq( + inkwell.Say(inc.Paul, "“Come out, Paul. Not a phone conversation.” That's all it says."), + inkwell.Say(inc.Dex, "And now you're here. And he isn't."), + ), + }) +} diff --git a/inc/scene.alley.go b/inc/scene.alley.go deleted file mode 100644 index 0afe6de..0000000 --- a/inc/scene.alley.go +++ /dev/null @@ -1,100 +0,0 @@ -package inc - -import ( - inkwell "git.teletypegames.org/engines/inkwell" -) - -func init() { - SceneManager.Register(Scene{ - Name: SceneAlley, - Title: "ALLEY — BEHIND NOODLE'S HOUSE", - Background: BgAlley, - Exits: []inkwell.Exit{ - { - To: SceneNoodleHouse, - Label: "back out to the street", - Side: inkwell.ExitLeft, - }, - }, - Actors: []inkwell.SceneActor{ - { - CharacterName: Paul, - At: inkwell.Point{ - X: 120, - Y: 232, - }, - }, - }, - OnEnter: setVarIfEmpty(VarArmillaStrip, "SRP: 1 tape"), - Hotspots: []inkwell.Hotspot{hidingPlace(), backDoor(), bin(), fireEscape()}, - }) -} - -func hidingPlace() inkwell.Hotspot { - return inkwell.Hotspot{ - Name: "hiding_place", - Label: "gap at the foot of the wall", - Area: inkwell.Rect(416, 150, 68, 52), - OnLook: inkwell.If(inkwell.Flag(FlagHasTape), - inkwell.Say(Paul, "Empty. Whatever was in there is on me now."), - inkwell.Say(Paul, "Loose brick. There's a gap behind it."), - ), - OnUse: inkwell.If(inkwell.Flag(FlagPoliceTip), - inkwell.If(inkwell.Flag(FlagHasTape), - inkwell.Say(Paul, "There's nothing else in there."), - inkwell.Seq( - inkwell.Say(Paul, "“Behind the brick.” All right then."), - inkwell.Give(ItemMysteryTape), - inkwell.SetFlag(FlagHasTape), - inkwell.Say(Paul, "A Personal Tape. No label, no seal."), - inkwell.Say(Dex, "Password-locked. And somebody very much did not want it found."), - ), - ), - inkwell.Say(Paul, "One loose brick. I'm not taking the alley apart over it."), - ), - OnTake: inkwell.Say(Paul, "I'm not carrying a wall."), - } -} - -func backDoor() inkwell.Hotspot { - return inkwell.Hotspot{ - Name: "back_door", - Label: "locked back door", - Area: inkwell.Rect(72, 106, 80, 124), - OnLook: inkwell.Say(Paul, "Keypad. Four digits, worn keys."), - OnUse: inkwell.Seq( - inkwell.Say(Paul, "Locked. And I'm not guessing four digits."), - inkwell.Say(Dex, "The wear is heaviest on the two and the seven. That isn't a code. It's fewer options."), - ), - OnTalk: inkwell.Say(Paul, "To the door? I'm not there yet."), - OnUseWith: map[string]inkwell.Action{ - ItemBlackArmilla: inkwell.Seq( - inkwell.Say(Paul, "A black-market bracelet doesn't open a keypad."), - inkwell.Say(Dex, "But you do get an advert out of it."), - ), - }, - } -} - -func bin() inkwell.Hotspot { - return inkwell.Hotspot{ - Name: "bin", - Label: "toppled bin", - Area: inkwell.Rect(240, 170, 88, 60), - OnLook: inkwell.Say(Paul, "Somebody's been through it. Thoroughly."), - OnUse: inkwell.Seq( - inkwell.Say(Paul, "Already turned out. I'm not going to be the second one."), - inkwell.Say(Dex, "The police don't go through bins. So who did?"), - ), - } -} - -func fireEscape() inkwell.Hotspot { - return inkwell.Hotspot{ - Name: "fire_escape", - Label: "fire escape", - Area: inkwell.Rect(528, 44, 88, 160), - OnLook: inkwell.Say(Paul, "Runs all the way to the roof. Bottom rung is two metres over my head."), - OnUse: inkwell.Say(Paul, "Can't reach it. I'd need something to stand on."), - } -} diff --git a/inc/scene.trinket_shop.go b/inc/scene.trinket_shop.go deleted file mode 100644 index b2c4853..0000000 --- a/inc/scene.trinket_shop.go +++ /dev/null @@ -1,28 +0,0 @@ -package inc - -import ( - inkwell "git.teletypegames.org/engines/inkwell" -) - -func init() { - SceneManager.Register(Scene{ - Name: SceneTrinketShop, - Title: "CHINATOWN — TRINKET SHOP", - Background: BgTrinketShop, - Exits: []inkwell.Exit{ - exitToSelector, - { - To: SceneSmallRestaurant, - Label: "the eating place next door", - Side: inkwell.ExitRight, - }, - { - To: SceneSecretClub, - Label: "the way in at the back", - Side: inkwell.ExitBack, - Needs: FlagClubEntry, - Blocked: inkwell.Say(Paul, "Just a shop, as far as the man behind the counter is concerned."), - }, - }, - }) -} diff --git a/inc/scene/scene.alley.go b/inc/scene/scene.alley.go new file mode 100644 index 0000000..8c4c24f --- /dev/null +++ b/inc/scene/scene.alley.go @@ -0,0 +1,101 @@ +package scene + +import ( + inkwell "git.teletypegames.org/engines/inkwell" + "git.teletypegames.org/games/realworld/inc" +) + +func init() { + Manager.Register(Scene{ + Name: inc.SceneAlley, + Title: "ALLEY — BEHIND NOODLE'S HOUSE", + Background: inc.BgAlley, + Exits: []inkwell.Exit{ + { + To: inc.SceneNoodleHouse, + Label: "back out to the street", + Side: inkwell.ExitLeft, + }, + }, + Actors: []inkwell.SceneActor{ + { + CharacterName: inc.Paul, + At: inkwell.Point{ + X: 120, + Y: 232, + }, + }, + }, + OnEnter: setVarIfEmpty(inc.VarArmillaStrip, "SRP: 1 tape"), + Hotspots: []inkwell.Hotspot{hidingPlace(), backDoor(), bin(), fireEscape()}, + }) +} + +func hidingPlace() inkwell.Hotspot { + return inkwell.Hotspot{ + Name: "hiding_place", + Label: "gap at the foot of the wall", + Area: inkwell.Rect(416, 150, 68, 52), + OnLook: inkwell.If(inkwell.Flag(inc.FlagHasTape), + inkwell.Say(inc.Paul, "Empty. Whatever was in there is on me now."), + inkwell.Say(inc.Paul, "Loose brick. There's a gap behind it."), + ), + OnUse: inkwell.If(inkwell.Flag(inc.FlagPoliceTip), + inkwell.If(inkwell.Flag(inc.FlagHasTape), + inkwell.Say(inc.Paul, "There's nothing else in there."), + inkwell.Seq( + inkwell.Say(inc.Paul, "“Behind the brick.” All right then."), + inkwell.Give(inc.ItemMysteryTape), + inkwell.SetFlag(inc.FlagHasTape), + inkwell.Say(inc.Paul, "A Personal Tape. No label, no seal."), + inkwell.Say(inc.Dex, "Password-locked. And somebody very much did not want it found."), + ), + ), + inkwell.Say(inc.Paul, "One loose brick. I'm not taking the alley apart over it."), + ), + OnTake: inkwell.Say(inc.Paul, "I'm not carrying a wall."), + } +} + +func backDoor() inkwell.Hotspot { + return inkwell.Hotspot{ + Name: "back_door", + Label: "locked back door", + Area: inkwell.Rect(72, 106, 80, 124), + OnLook: inkwell.Say(inc.Paul, "Keypad. Four digits, worn keys."), + OnUse: inkwell.Seq( + inkwell.Say(inc.Paul, "Locked. And I'm not guessing four digits."), + inkwell.Say(inc.Dex, "The wear is heaviest on the two and the seven. That isn't a code. It's fewer options."), + ), + OnTalk: inkwell.Say(inc.Paul, "To the door? I'm not there yet."), + OnUseWith: map[string]inkwell.Action{ + inc.ItemBlackArmilla: inkwell.Seq( + inkwell.Say(inc.Paul, "A black-market bracelet doesn't open a keypad."), + inkwell.Say(inc.Dex, "But you do get an advert out of it."), + ), + }, + } +} + +func bin() inkwell.Hotspot { + return inkwell.Hotspot{ + Name: "bin", + Label: "toppled bin", + Area: inkwell.Rect(240, 170, 88, 60), + OnLook: inkwell.Say(inc.Paul, "Somebody's been through it. Thoroughly."), + OnUse: inkwell.Seq( + inkwell.Say(inc.Paul, "Already turned out. I'm not going to be the second one."), + inkwell.Say(inc.Dex, "The police don't go through bins. So who did?"), + ), + } +} + +func fireEscape() inkwell.Hotspot { + return inkwell.Hotspot{ + Name: "fire_escape", + Label: "fire escape", + Area: inkwell.Rect(528, 44, 88, 160), + OnLook: inkwell.Say(inc.Paul, "Runs all the way to the roof. Bottom rung is two metres over my head."), + OnUse: inkwell.Say(inc.Paul, "Can't reach it. I'd need something to stand on."), + } +} diff --git a/inc/scene.bbs_terminal.go b/inc/scene/scene.bbs_terminal.go similarity index 61% rename from inc/scene.bbs_terminal.go rename to inc/scene/scene.bbs_terminal.go index 2ee213d..543b6e7 100644 --- a/inc/scene.bbs_terminal.go +++ b/inc/scene/scene.bbs_terminal.go @@ -1,14 +1,15 @@ -package inc +package scene import ( inkwell "git.teletypegames.org/engines/inkwell" + "git.teletypegames.org/games/realworld/inc" ) func init() { - SceneManager.Register(Scene{ - Name: SceneBBSTerminal, + Manager.Register(Scene{ + Name: inc.SceneBBSTerminal, Title: "TERMINAL — BBS ACCESS POINT", - Background: BgBBSTerminal, + Background: inc.BgBBSTerminal, Exits: []inkwell.Exit{ { Label: "step back from the terminal", diff --git a/inc/scene.bvk_branch.go b/inc/scene/scene.bvk_branch.go similarity index 54% rename from inc/scene.bvk_branch.go rename to inc/scene/scene.bvk_branch.go index 5dbb9d4..4e71e53 100644 --- a/inc/scene.bvk_branch.go +++ b/inc/scene/scene.bvk_branch.go @@ -1,14 +1,15 @@ -package inc +package scene import ( inkwell "git.teletypegames.org/engines/inkwell" + "git.teletypegames.org/games/realworld/inc" ) func init() { - SceneManager.Register(Scene{ - Name: SceneBVKBranch, + Manager.Register(Scene{ + Name: inc.SceneBVKBranch, Title: "BVK — SAN FRANCISCO BRANCH", - Background: BgBVKBranch, + Background: inc.BgBVKBranch, Exits: []inkwell.Exit{ exitToSelector, }, diff --git a/inc/scene.columbarium.go b/inc/scene/scene.columbarium.go similarity index 53% rename from inc/scene.columbarium.go rename to inc/scene/scene.columbarium.go index a68a997..151afdd 100644 --- a/inc/scene.columbarium.go +++ b/inc/scene/scene.columbarium.go @@ -1,14 +1,15 @@ -package inc +package scene import ( inkwell "git.teletypegames.org/engines/inkwell" + "git.teletypegames.org/games/realworld/inc" ) func init() { - SceneManager.Register(Scene{ - Name: SceneColumbarium, + Manager.Register(Scene{ + Name: inc.SceneColumbarium, Title: "COLUMBARIUM — DEX'S MEMORIAL", - Background: BgColumbarium, + Background: inc.BgColumbarium, Exits: []inkwell.Exit{ exitToSelector, }, diff --git a/inc/scene.curator_shop.go b/inc/scene/scene.curator_shop.go similarity index 55% rename from inc/scene.curator_shop.go rename to inc/scene/scene.curator_shop.go index 3893124..b51d095 100644 --- a/inc/scene.curator_shop.go +++ b/inc/scene/scene.curator_shop.go @@ -1,14 +1,15 @@ -package inc +package scene import ( inkwell "git.teletypegames.org/engines/inkwell" + "git.teletypegames.org/games/realworld/inc" ) func init() { - SceneManager.Register(Scene{ - Name: SceneCuratorShop, + Manager.Register(Scene{ + Name: inc.SceneCuratorShop, Title: "CURATOR SERVICE — THE MASTER'S WORKSHOP", - Background: BgCuratorShop, + Background: inc.BgCuratorShop, Exits: []inkwell.Exit{ exitToSelector, }, diff --git a/inc/scene.hackerspace.go b/inc/scene/scene.hackerspace.go similarity index 51% rename from inc/scene.hackerspace.go rename to inc/scene/scene.hackerspace.go index cdd0fbf..d3fedab 100644 --- a/inc/scene.hackerspace.go +++ b/inc/scene/scene.hackerspace.go @@ -1,14 +1,15 @@ -package inc +package scene import ( inkwell "git.teletypegames.org/engines/inkwell" + "git.teletypegames.org/games/realworld/inc" ) func init() { - SceneManager.Register(Scene{ - Name: SceneHackerspace, + Manager.Register(Scene{ + Name: inc.SceneHackerspace, Title: "HACKERSPACE", - Background: BgHackerspace, + Background: inc.BgHackerspace, Exits: []inkwell.Exit{ exitToSelector, }, diff --git a/inc/scene.hospital.go b/inc/scene/scene.hospital.go similarity index 54% rename from inc/scene.hospital.go rename to inc/scene/scene.hospital.go index 7598060..0557a7f 100644 --- a/inc/scene.hospital.go +++ b/inc/scene/scene.hospital.go @@ -1,14 +1,15 @@ -package inc +package scene import ( inkwell "git.teletypegames.org/engines/inkwell" + "git.teletypegames.org/games/realworld/inc" ) func init() { - SceneManager.Register(Scene{ - Name: SceneHospital, + Manager.Register(Scene{ + Name: inc.SceneHospital, Title: "HOSPITAL — PSYCHIATRIC WING", - Background: BgHospital, + Background: inc.BgHospital, Exits: []inkwell.Exit{ exitToSelector, }, diff --git a/inc/scene.ice_cream_shop.go b/inc/scene/scene.ice_cream_shop.go similarity index 54% rename from inc/scene.ice_cream_shop.go rename to inc/scene/scene.ice_cream_shop.go index df96462..a73818a 100644 --- a/inc/scene.ice_cream_shop.go +++ b/inc/scene/scene.ice_cream_shop.go @@ -1,14 +1,15 @@ -package inc +package scene import ( inkwell "git.teletypegames.org/engines/inkwell" + "git.teletypegames.org/games/realworld/inc" ) func init() { - SceneManager.Register(Scene{ - Name: SceneIceCreamShop, + Manager.Register(Scene{ + Name: inc.SceneIceCreamShop, Title: "ICE CREAM SHOP — WHERE THE BAR WAS", - Background: BgIceCreamShop, + Background: inc.BgIceCreamShop, Exits: []inkwell.Exit{ exitToSelector, }, diff --git a/inc/scene.manager.go b/inc/scene/scene.manager.go similarity index 69% rename from inc/scene.manager.go rename to inc/scene/scene.manager.go index fa4a9da..b660afb 100644 --- a/inc/scene.manager.go +++ b/inc/scene/scene.manager.go @@ -1,12 +1,15 @@ -package inc +package scene import ( inkwell "git.teletypegames.org/engines/inkwell" + "git.teletypegames.org/games/realworld/inc/world" ) type Scene = inkwell.Scene -var sceneFloor = []inkwell.Polygon{ +var Manager = inkwell.NewManager[Scene]() + +var Floor = []inkwell.Polygon{ inkwell.Poly( inkwell.Point{ X: 16, @@ -26,7 +29,7 @@ var sceneFloor = []inkwell.Polygon{ } func setVarIfEmpty(name string, v any) inkwell.Action { - return Fn(func(ctx *inkwell.Ctx) { + return world.Fn(func(ctx *inkwell.Ctx) { if ctx.Game.State.Var(name) == nil { ctx.Game.State.SetVar(name, v) } diff --git a/inc/scene.noodle_house.go b/inc/scene/scene.noodle_house.go similarity index 58% rename from inc/scene.noodle_house.go rename to inc/scene/scene.noodle_house.go index e88f4e0..b0daa8f 100644 --- a/inc/scene.noodle_house.go +++ b/inc/scene/scene.noodle_house.go @@ -1,18 +1,19 @@ -package inc +package scene import ( inkwell "git.teletypegames.org/engines/inkwell" + "git.teletypegames.org/games/realworld/inc" ) func init() { - SceneManager.Register(Scene{ - Name: SceneNoodleHouse, + Manager.Register(Scene{ + Name: inc.SceneNoodleHouse, Title: "NOODLE'S HOUSE — SEALED", - Background: BgNoodleHouse, + Background: inc.BgNoodleHouse, Exits: []inkwell.Exit{ exitToSelector, { - To: SceneAlley, + To: inc.SceneAlley, Label: "the alley behind the house", Side: inkwell.ExitRight, }, diff --git a/inc/scene.norman_apartment.go b/inc/scene/scene.norman_apartment.go similarity index 58% rename from inc/scene.norman_apartment.go rename to inc/scene/scene.norman_apartment.go index cd9df4c..1b04a6d 100644 --- a/inc/scene.norman_apartment.go +++ b/inc/scene/scene.norman_apartment.go @@ -1,23 +1,24 @@ -package inc +package scene import ( inkwell "git.teletypegames.org/engines/inkwell" + "git.teletypegames.org/games/realworld/inc" ) func init() { - SceneManager.Register(Scene{ - Name: SceneNormanApartment, + Manager.Register(Scene{ + Name: inc.SceneNormanApartment, Title: "NORMAN'S APARTMENT", - Background: BgNormanApartment, + Background: inc.BgNormanApartment, Exits: []inkwell.Exit{ exitToSelector, { - To: SceneRooftopHideout, + To: inc.SceneRooftopHideout, Label: "the stairs up to the roof", Side: inkwell.ExitBack, }, { - To: SceneBBSTerminal, + To: inc.SceneBBSTerminal, Label: "Norman's terminal", Side: inkwell.ExitRight, }, diff --git a/inc/scene.paul_shop.go b/inc/scene/scene.paul_shop.go similarity index 57% rename from inc/scene.paul_shop.go rename to inc/scene/scene.paul_shop.go index fe69966..7d0ab03 100644 --- a/inc/scene.paul_shop.go +++ b/inc/scene/scene.paul_shop.go @@ -1,17 +1,18 @@ -package inc +package scene import ( inkwell "git.teletypegames.org/engines/inkwell" + "git.teletypegames.org/games/realworld/inc" ) func init() { - SceneManager.Register(Scene{ - Name: ScenePaulShop, + Manager.Register(Scene{ + Name: inc.ScenePaulShop, Title: "PAUL'S SHOP — JUNK AND GARAGE", - Background: BgPaulShop, + Background: inc.BgPaulShop, Exits: []inkwell.Exit{ { - To: SceneNoodleHouse, + To: inc.SceneNoodleHouse, Label: "the bus to San Francisco", Side: inkwell.ExitNear, }, diff --git a/inc/scene.police_station.go b/inc/scene/scene.police_station.go similarity index 52% rename from inc/scene.police_station.go rename to inc/scene/scene.police_station.go index 4398c5f..d053dc0 100644 --- a/inc/scene.police_station.go +++ b/inc/scene/scene.police_station.go @@ -1,14 +1,15 @@ -package inc +package scene import ( inkwell "git.teletypegames.org/engines/inkwell" + "git.teletypegames.org/games/realworld/inc" ) func init() { - SceneManager.Register(Scene{ - Name: ScenePoliceStation, + Manager.Register(Scene{ + Name: inc.ScenePoliceStation, Title: "SFPD — STATION AND HOLDING", - Background: BgPoliceStation, + Background: inc.BgPoliceStation, Exits: []inkwell.Exit{ exitToSelector, }, diff --git a/inc/scene.public_bbs.go b/inc/scene/scene.public_bbs.go similarity index 52% rename from inc/scene.public_bbs.go rename to inc/scene/scene.public_bbs.go index fdb7d44..0dafc4d 100644 --- a/inc/scene.public_bbs.go +++ b/inc/scene/scene.public_bbs.go @@ -1,14 +1,15 @@ -package inc +package scene import ( inkwell "git.teletypegames.org/engines/inkwell" + "git.teletypegames.org/games/realworld/inc" ) func init() { - SceneManager.Register(Scene{ - Name: ScenePublicBBS, + Manager.Register(Scene{ + Name: inc.ScenePublicBBS, Title: "PUBLIC BBS TERMINAL", - Background: BgPublicBBS, + Background: inc.BgPublicBBS, Exits: []inkwell.Exit{ exitToSelector, }, diff --git a/inc/scene.rooftop_hideout.go b/inc/scene/scene.rooftop_hideout.go similarity index 57% rename from inc/scene.rooftop_hideout.go rename to inc/scene/scene.rooftop_hideout.go index 9bfb167..8b4eddc 100644 --- a/inc/scene.rooftop_hideout.go +++ b/inc/scene/scene.rooftop_hideout.go @@ -1,22 +1,23 @@ -package inc +package scene import ( inkwell "git.teletypegames.org/engines/inkwell" + "git.teletypegames.org/games/realworld/inc" ) func init() { - SceneManager.Register(Scene{ - Name: SceneRooftopHideout, + Manager.Register(Scene{ + Name: inc.SceneRooftopHideout, Title: "NORMAN'S ROOFTOP HIDEOUT", - Background: BgRooftopHideout, + Background: inc.BgRooftopHideout, Exits: []inkwell.Exit{ { - To: SceneNormanApartment, + To: inc.SceneNormanApartment, Label: "back down into the flat", Side: inkwell.ExitNear, }, { - To: SceneBBSTerminal, + To: inc.SceneBBSTerminal, Label: "the old terminal", Side: inkwell.ExitRight, }, diff --git a/inc/scene.samizdat_press.go b/inc/scene/scene.samizdat_press.go similarity index 52% rename from inc/scene.samizdat_press.go rename to inc/scene/scene.samizdat_press.go index b9cf637..119173a 100644 --- a/inc/scene.samizdat_press.go +++ b/inc/scene/scene.samizdat_press.go @@ -1,14 +1,15 @@ -package inc +package scene import ( inkwell "git.teletypegames.org/engines/inkwell" + "git.teletypegames.org/games/realworld/inc" ) func init() { - SceneManager.Register(Scene{ - Name: SceneSamizdatPress, + Manager.Register(Scene{ + Name: inc.SceneSamizdatPress, Title: "SAMIZDAT PRINTING HOUSE", - Background: BgSamizdatPress, + Background: inc.BgSamizdatPress, Exits: []inkwell.Exit{ exitToSelector, }, diff --git a/inc/scene.scrap_market.go b/inc/scene/scene.scrap_market.go similarity index 51% rename from inc/scene.scrap_market.go rename to inc/scene/scene.scrap_market.go index 7475331..c833c2b 100644 --- a/inc/scene.scrap_market.go +++ b/inc/scene/scene.scrap_market.go @@ -1,14 +1,15 @@ -package inc +package scene import ( inkwell "git.teletypegames.org/engines/inkwell" + "git.teletypegames.org/games/realworld/inc" ) func init() { - SceneManager.Register(Scene{ - Name: SceneScrapMarket, + Manager.Register(Scene{ + Name: inc.SceneScrapMarket, Title: "SCRAP MARKET", - Background: BgScrapMarket, + Background: inc.BgScrapMarket, Exits: []inkwell.Exit{ exitToSelector, }, diff --git a/inc/scene.secret_club.go b/inc/scene/scene.secret_club.go similarity index 59% rename from inc/scene.secret_club.go rename to inc/scene/scene.secret_club.go index 23a303c..cd82f30 100644 --- a/inc/scene.secret_club.go +++ b/inc/scene/scene.secret_club.go @@ -1,22 +1,23 @@ -package inc +package scene import ( inkwell "git.teletypegames.org/engines/inkwell" + "git.teletypegames.org/games/realworld/inc" ) func init() { - SceneManager.Register(Scene{ - Name: SceneSecretClub, + Manager.Register(Scene{ + Name: inc.SceneSecretClub, Title: "SECRET CLUB — THE UNDERWATER SUN", - Background: BgSecretClub, + Background: inc.BgSecretClub, Exits: []inkwell.Exit{ { - To: SceneBBSTerminal, + To: inc.SceneBBSTerminal, Label: "the terminal in the corner", Side: inkwell.ExitBack, }, { - To: SceneTrinketShop, + To: inc.SceneTrinketShop, Label: "back out through the shop", Side: inkwell.ExitNear, }, diff --git a/inc/scene.secret_lab.go b/inc/scene/scene.secret_lab.go similarity index 54% rename from inc/scene.secret_lab.go rename to inc/scene/scene.secret_lab.go index 96ca536..87d9562 100644 --- a/inc/scene.secret_lab.go +++ b/inc/scene/scene.secret_lab.go @@ -1,14 +1,15 @@ -package inc +package scene import ( inkwell "git.teletypegames.org/engines/inkwell" + "git.teletypegames.org/games/realworld/inc" ) func init() { - SceneManager.Register(Scene{ - Name: SceneSecretLab, + Manager.Register(Scene{ + Name: inc.SceneSecretLab, Title: "SECRET RESEARCH LABORATORY", - Background: BgSecretLab, + Background: inc.BgSecretLab, Exits: []inkwell.Exit{ exitToSelector, }, diff --git a/inc/scene.selector.go b/inc/scene/scene.selector.go similarity index 74% rename from inc/scene.selector.go rename to inc/scene/scene.selector.go index cec7db0..0243ffe 100644 --- a/inc/scene.selector.go +++ b/inc/scene/scene.selector.go @@ -1,34 +1,35 @@ -package inc +package scene import ( "strings" inkwell "git.teletypegames.org/engines/inkwell" + "git.teletypegames.org/games/realworld/inc" ) var exitToSelector = inkwell.Exit{ - To: SceneSelector, + To: inc.SceneSelector, Label: "the rest of the city", Side: inkwell.ExitNear, } func init() { - SceneManager.Register(Scene{ - Name: SceneSelector, + Manager.Register(Scene{ + Name: inc.SceneSelector, Title: "SAN FRANCISCO", - Background: BgSelector, + Background: inc.BgSelector, Actors: []inkwell.SceneActor{}, Walkboxes: []inkwell.Polygon{}, }) } -func fillSelectorPins() { - selector, ok := SceneManager.Get(SceneSelector) +func FillSelectorPins() { + selector, ok := Manager.Get(inc.SceneSelector) if !ok { return } var exits []inkwell.Exit - for _, entity := range SceneManager.All() { + for _, entity := range Manager.All() { if !leadsToSelector(entity) { continue } @@ -39,12 +40,12 @@ func fillSelectorPins() { }) } selector.Exits = exits - SceneManager.Set(selector) + Manager.Set(selector) } func leadsToSelector(s Scene) bool { for _, e := range s.Exits { - if e.To == SceneSelector { + if e.To == inc.SceneSelector { return true } } diff --git a/inc/scene.server_farm.go b/inc/scene/scene.server_farm.go similarity index 51% rename from inc/scene.server_farm.go rename to inc/scene/scene.server_farm.go index 09f43f9..708fbe7 100644 --- a/inc/scene.server_farm.go +++ b/inc/scene/scene.server_farm.go @@ -1,14 +1,15 @@ -package inc +package scene import ( inkwell "git.teletypegames.org/engines/inkwell" + "git.teletypegames.org/games/realworld/inc" ) func init() { - SceneManager.Register(Scene{ - Name: SceneServerFarm, + Manager.Register(Scene{ + Name: inc.SceneServerFarm, Title: "SERVER FARM", - Background: BgServerFarm, + Background: inc.BgServerFarm, Exits: []inkwell.Exit{ exitToSelector, }, diff --git a/inc/scene.showroom.go b/inc/scene/scene.showroom.go similarity index 53% rename from inc/scene.showroom.go rename to inc/scene/scene.showroom.go index d27cb31..679c24a 100644 --- a/inc/scene.showroom.go +++ b/inc/scene/scene.showroom.go @@ -1,14 +1,15 @@ -package inc +package scene import ( inkwell "git.teletypegames.org/engines/inkwell" + "git.teletypegames.org/games/realworld/inc" ) func init() { - SceneManager.Register(Scene{ - Name: SceneShowroom, + Manager.Register(Scene{ + Name: inc.SceneShowroom, Title: "NEUMATRONIC SHOWROOM", - Background: BgShowroom, + Background: inc.BgShowroom, Exits: []inkwell.Exit{ exitToSelector, }, diff --git a/inc/scene.small_restaurant.go b/inc/scene/scene.small_restaurant.go similarity index 55% rename from inc/scene.small_restaurant.go rename to inc/scene/scene.small_restaurant.go index 58e80f4..09fba53 100644 --- a/inc/scene.small_restaurant.go +++ b/inc/scene/scene.small_restaurant.go @@ -1,17 +1,18 @@ -package inc +package scene import ( inkwell "git.teletypegames.org/engines/inkwell" + "git.teletypegames.org/games/realworld/inc" ) func init() { - SceneManager.Register(Scene{ - Name: SceneSmallRestaurant, + Manager.Register(Scene{ + Name: inc.SceneSmallRestaurant, Title: "SMALL RESTAURANT — NEXT DOOR", - Background: BgSmallRestaurant, + Background: inc.BgSmallRestaurant, Exits: []inkwell.Exit{ { - To: SceneTrinketShop, + To: inc.SceneTrinketShop, Label: "back to the trinket shop", Side: inkwell.ExitLeft, }, diff --git a/inc/scene.street.go b/inc/scene/scene.street.go similarity index 52% rename from inc/scene.street.go rename to inc/scene/scene.street.go index c918ba0..d872696 100644 --- a/inc/scene.street.go +++ b/inc/scene/scene.street.go @@ -1,14 +1,15 @@ -package inc +package scene import ( inkwell "git.teletypegames.org/engines/inkwell" + "git.teletypegames.org/games/realworld/inc" ) func init() { - SceneManager.Register(Scene{ - Name: SceneStreet, + Manager.Register(Scene{ + Name: inc.SceneStreet, Title: "STREET", - Background: BgStreet, + Background: inc.BgStreet, Exits: []inkwell.Exit{ exitToSelector, }, diff --git a/inc/scene/scene.trinket_shop.go b/inc/scene/scene.trinket_shop.go new file mode 100644 index 0000000..cdf7412 --- /dev/null +++ b/inc/scene/scene.trinket_shop.go @@ -0,0 +1,29 @@ +package scene + +import ( + inkwell "git.teletypegames.org/engines/inkwell" + "git.teletypegames.org/games/realworld/inc" +) + +func init() { + Manager.Register(Scene{ + Name: inc.SceneTrinketShop, + Title: "CHINATOWN — TRINKET SHOP", + Background: inc.BgTrinketShop, + Exits: []inkwell.Exit{ + exitToSelector, + { + To: inc.SceneSmallRestaurant, + Label: "the eating place next door", + Side: inkwell.ExitRight, + }, + { + To: inc.SceneSecretClub, + Label: "the way in at the back", + Side: inkwell.ExitBack, + Needs: inc.FlagClubEntry, + Blocked: inkwell.Say(inc.Paul, "Just a shop, as far as the man behind the counter is concerned."), + }, + }, + }) +} diff --git a/inc/script.awakening_finale.go b/inc/script.awakening_finale.go deleted file mode 100644 index c6cebee..0000000 --- a/inc/script.awakening_finale.go +++ /dev/null @@ -1,23 +0,0 @@ -package inc - -import ( - inkwell "git.teletypegames.org/engines/inkwell" -) - -func init() { - ScriptManager.Register(Script{ - Name: ScriptFinale, - Actions: inkwell.Seq( - SetMode(ModeCutscene), - inkwell.Wait(0.6), - inkwell.Say(Paul, "I'm putting it in. That's all this is."), - inkwell.Wait(0.4), - UseTheme(NokiaPunk), - inkwell.Say("norman", "No — this isn't what you were supposed to do!"), - inkwell.Wait(0.6), - inkwell.Say(TapeMystery, "Thank you, Paul. You did exactly what I asked, the whole way through."), - inkwell.Wait(1.0), - inkwell.ShowEnd("REAL WORLD — end of game two"), - ), - }) -} diff --git a/inc/script.opening.go b/inc/script.opening.go deleted file mode 100644 index c1b420a..0000000 --- a/inc/script.opening.go +++ /dev/null @@ -1,16 +0,0 @@ -package inc - -import ( - inkwell "git.teletypegames.org/engines/inkwell" -) - -func init() { - ScriptManager.Register(Script{ - Name: ScriptOpening, - Actions: inkwell.Seq( - inkwell.SetFlag(FlagPoliceTip), - inkwell.Say(Paul, "Back alley. Just like the clerk said."), - inkwell.Say(Dex, "A government office tipped you off to remove something from a scene. That doesn't strike you as odd?"), - ), - }) -} diff --git a/inc/script.tape_insert.go b/inc/script.tape_insert.go deleted file mode 100644 index 5b7c843..0000000 --- a/inc/script.tape_insert.go +++ /dev/null @@ -1,25 +0,0 @@ -package inc - -import ( - inkwell "git.teletypegames.org/engines/inkwell" -) - -func init() { - ScriptManager.Register(Script{ - Name: ScriptTapeInsert, - Actions: inkwell.Seq( - Fn(func(ctx *inkwell.Ctx) { - item := World.TakePending() - if item == "" { - return - } - World.SetSlot2(item) - ctx.Game.Inventory.Remove(item) - ctx.Game.State.SetVar(VarArmillaStrip, "SLOT2: READING") - }), - inkwell.Say(Paul, "Right. Let's see who you are."), - inkwell.Say(Dex, "Clicked in. Spinning. And now: nothing."), - inkwell.Say(Dex, "A stranger's tape in your own Armilla, Paul. I hope you know what you're doing."), - ), - }) -} diff --git a/inc/script/script.awakening_finale.go b/inc/script/script.awakening_finale.go new file mode 100644 index 0000000..08567aa --- /dev/null +++ b/inc/script/script.awakening_finale.go @@ -0,0 +1,25 @@ +package script + +import ( + inkwell "git.teletypegames.org/engines/inkwell" + "git.teletypegames.org/games/realworld/inc" + "git.teletypegames.org/games/realworld/inc/world" +) + +func init() { + Manager.Register(Script{ + Name: inc.ScriptFinale, + Actions: inkwell.Seq( + world.SetMode(world.ModeCutscene), + inkwell.Wait(0.6), + inkwell.Say(inc.Paul, "I'm putting it in. That's all this is."), + inkwell.Wait(0.4), + world.UseTheme(inc.NokiaPunk), + inkwell.Say("norman", "No — this isn't what you were supposed to do!"), + inkwell.Wait(0.6), + inkwell.Say(inc.TapeMystery, "Thank you, Paul. You did exactly what I asked, the whole way through."), + inkwell.Wait(1.0), + inkwell.ShowEnd("REAL WORLD — end of game two"), + ), + }) +} diff --git a/inc/script.manager.go b/inc/script/script.manager.go similarity index 60% rename from inc/script.manager.go rename to inc/script/script.manager.go index 2fc6af8..69f95e7 100644 --- a/inc/script.manager.go +++ b/inc/script/script.manager.go @@ -1,7 +1,9 @@ -package inc +package script import ( inkwell "git.teletypegames.org/engines/inkwell" ) type Script = inkwell.Script + +var Manager = inkwell.NewManager[Script]() diff --git a/inc/script/script.opening.go b/inc/script/script.opening.go new file mode 100644 index 0000000..54d5498 --- /dev/null +++ b/inc/script/script.opening.go @@ -0,0 +1,17 @@ +package script + +import ( + inkwell "git.teletypegames.org/engines/inkwell" + "git.teletypegames.org/games/realworld/inc" +) + +func init() { + Manager.Register(Script{ + Name: inc.ScriptOpening, + Actions: inkwell.Seq( + inkwell.SetFlag(inc.FlagPoliceTip), + inkwell.Say(inc.Paul, "Back alley. Just like the clerk said."), + inkwell.Say(inc.Dex, "A government office tipped you off to remove something from a scene. That doesn't strike you as odd?"), + ), + }) +} diff --git a/inc/script/script.tape_insert.go b/inc/script/script.tape_insert.go new file mode 100644 index 0000000..e385016 --- /dev/null +++ b/inc/script/script.tape_insert.go @@ -0,0 +1,27 @@ +package script + +import ( + inkwell "git.teletypegames.org/engines/inkwell" + "git.teletypegames.org/games/realworld/inc" + "git.teletypegames.org/games/realworld/inc/world" +) + +func init() { + Manager.Register(Script{ + Name: inc.ScriptTapeInsert, + Actions: inkwell.Seq( + world.Fn(func(ctx *inkwell.Ctx) { + item := world.TakePending() + if item == "" { + return + } + world.SetSlot2(item) + ctx.Game.Inventory.Remove(item) + ctx.Game.State.SetVar(inc.VarArmillaStrip, "SLOT2: READING") + }), + inkwell.Say(inc.Paul, "Right. Let's see who you are."), + inkwell.Say(inc.Dex, "Clicked in. Spinning. And now: nothing."), + inkwell.Say(inc.Dex, "A stranger's tape in your own Armilla, Paul. I hope you know what you're doing."), + ), + }) +} diff --git a/inc/script.usewith_fail.go b/inc/script/script.usewith_fail.go similarity index 74% rename from inc/script.usewith_fail.go rename to inc/script/script.usewith_fail.go index 64281db..6010366 100644 --- a/inc/script.usewith_fail.go +++ b/inc/script/script.usewith_fail.go @@ -1,19 +1,21 @@ -package inc +package script import ( "math/rand" inkwell "git.teletypegames.org/engines/inkwell" + "git.teletypegames.org/games/realworld/inc" + "git.teletypegames.org/games/realworld/inc/world" ) -func useWithFail(item string, h *inkwell.Hotspot) inkwell.Action { +func UseWithFail(item string, h *inkwell.Hotspot) inkwell.Action { key := "fail." + item + "." + h.Name - World.G.State.NoteTalked(key) - n := World.G.State.Talked(key) + world.Game().State.NoteTalked(key) + n := world.Game().State.Talked(key) return inkwell.Seq( - inkwell.Say(Paul, pick(paulFails, n)), - inkwell.Say(Dex, dexFail(n)), + inkwell.Say(inc.Paul, pick(paulFails, n)), + inkwell.Say(inc.Dex, dexFail(n)), ) } diff --git a/inc/tape.dex.go b/inc/tape.dex.go deleted file mode 100644 index ae0dbc6..0000000 --- a/inc/tape.dex.go +++ /dev/null @@ -1,8 +0,0 @@ -package inc - -func init() { - TapeManager.Register(Tape{ - Name: Dex, - Dialogue: DlgDex, - }) -} diff --git a/inc/tape.manager.go b/inc/tape.manager.go deleted file mode 100644 index 50e1a92..0000000 --- a/inc/tape.manager.go +++ /dev/null @@ -1,32 +0,0 @@ -package inc - -type Tape struct { - Name string - Item string - Dialogue string -} - -func (t Tape) GetName() string { return t.Name } - -func IsTape(name string) bool { return TapeManager.Has(name) } - -func TapeOf(item string) (Tape, bool) { - for _, t := range TapeManager.All() { - if t.Item != "" && t.Item == item { - return t, true - } - } - return Tape{}, false -} - -func IsTapeItem(item string) bool { - _, ok := TapeOf(item) - return ok -} - -func TapeDialogue(item string) string { - if t, ok := TapeOf(item); ok && t.Dialogue != "" { - return t.Dialogue - } - return DlgDex -} diff --git a/inc/tape.mystery.go b/inc/tape.mystery.go deleted file mode 100644 index 3ebf404..0000000 --- a/inc/tape.mystery.go +++ /dev/null @@ -1,9 +0,0 @@ -package inc - -func init() { - TapeManager.Register(Tape{ - Name: TapeMystery, - Item: ItemMysteryTape, - Dialogue: DlgMysteryTape, - }) -} diff --git a/inc/tape.support.go b/inc/tape.support.go deleted file mode 100644 index 1c575e2..0000000 --- a/inc/tape.support.go +++ /dev/null @@ -1,7 +0,0 @@ -package inc - -func init() { - TapeManager.Register(Tape{ - Name: TapeSupport, - }) -} diff --git a/inc/tape/tape.dex.go b/inc/tape/tape.dex.go new file mode 100644 index 0000000..dee2141 --- /dev/null +++ b/inc/tape/tape.dex.go @@ -0,0 +1,12 @@ +package tape + +import ( + "git.teletypegames.org/games/realworld/inc" +) + +func init() { + Manager.Register(Tape{ + Name: inc.Dex, + Dialogue: inc.DlgDex, + }) +} diff --git a/inc/tape/tape.manager.go b/inc/tape/tape.manager.go new file mode 100644 index 0000000..cb8fc84 --- /dev/null +++ b/inc/tape/tape.manager.go @@ -0,0 +1,39 @@ +package tape + +import ( + inkwell "git.teletypegames.org/engines/inkwell" + "git.teletypegames.org/games/realworld/inc" +) + +type Tape struct { + Name string + Item string + Dialogue string +} + +var Manager = inkwell.NewManager[Tape]() + +func (t Tape) GetName() string { return t.Name } + +func Is(name string) bool { return Manager.Has(name) } + +func Of(item string) (Tape, bool) { + for _, t := range Manager.All() { + if t.Item != "" && t.Item == item { + return t, true + } + } + return Tape{}, false +} + +func IsItem(item string) bool { + _, ok := Of(item) + return ok +} + +func Dialogue(item string) string { + if t, ok := Of(item); ok && t.Dialogue != "" { + return t.Dialogue + } + return inc.DlgDex +} diff --git a/inc/tape/tape.mystery.go b/inc/tape/tape.mystery.go new file mode 100644 index 0000000..fa77ee7 --- /dev/null +++ b/inc/tape/tape.mystery.go @@ -0,0 +1,13 @@ +package tape + +import ( + "git.teletypegames.org/games/realworld/inc" +) + +func init() { + Manager.Register(Tape{ + Name: inc.TapeMystery, + Item: inc.ItemMysteryTape, + Dialogue: inc.DlgMysteryTape, + }) +} diff --git a/inc/tape/tape.support.go b/inc/tape/tape.support.go new file mode 100644 index 0000000..aabf06a --- /dev/null +++ b/inc/tape/tape.support.go @@ -0,0 +1,11 @@ +package tape + +import ( + "git.teletypegames.org/games/realworld/inc" +) + +func init() { + Manager.Register(Tape{ + Name: inc.TapeSupport, + }) +} diff --git a/inc/theme.manager.go b/inc/theme/theme.manager.go similarity index 83% rename from inc/theme.manager.go rename to inc/theme/theme.manager.go index 9958316..121ea9e 100644 --- a/inc/theme.manager.go +++ b/inc/theme/theme.manager.go @@ -1,4 +1,4 @@ -package inc +package theme import ( "image/color" @@ -8,10 +8,7 @@ import ( type Theme = inkwell.Theme -const ( - RealWorld = "realworld-93" - NokiaPunk = "nokia-punk" -) +var Manager = inkwell.NewManager[Theme]() func RGB(hex uint32) color.Color { return color.RGBA{ diff --git a/inc/theme.nokia_punk.go b/inc/theme/theme.nokia_punk.go similarity index 90% rename from inc/theme.nokia_punk.go rename to inc/theme/theme.nokia_punk.go index e909cc4..51fa207 100644 --- a/inc/theme.nokia_punk.go +++ b/inc/theme/theme.nokia_punk.go @@ -1,4 +1,8 @@ -package inc +package theme + +import ( + "git.teletypegames.org/games/realworld/inc" +) var ( Green = RGB(0x3BE86B) @@ -7,8 +11,8 @@ var ( ) func init() { - ThemeManager.Register(Theme{ - Name: NokiaPunk, + Manager.Register(Theme{ + Name: inc.NokiaPunk, PanelBG: npBlack, StatusText: Green, FlashText: RGB(0xD8F06A), diff --git a/inc/theme.realworld.go b/inc/theme/theme.realworld.go similarity index 90% rename from inc/theme.realworld.go rename to inc/theme/theme.realworld.go index e646dea..1f51c45 100644 --- a/inc/theme.realworld.go +++ b/inc/theme/theme.realworld.go @@ -1,4 +1,8 @@ -package inc +package theme + +import ( + "git.teletypegames.org/games/realworld/inc" +) var ( Ink = RGB(0xDCD5C4) @@ -11,8 +15,8 @@ var ( ) func init() { - ThemeManager.Register(Theme{ - Name: RealWorld, + Manager.Register(Theme{ + Name: inc.RealWorld, PanelBG: black, StatusText: Ink, FlashText: Amber, diff --git a/inc/widget.top_bar.go b/inc/widget.top_bar.go deleted file mode 100644 index ccd79ab..0000000 --- a/inc/widget.top_bar.go +++ /dev/null @@ -1,15 +0,0 @@ -package inc - -import ( - inkwell "git.teletypegames.org/engines/inkwell" -) - -func init() { - WidgetManager.Register(&inkwell.TopBar{ - Name: "topbar", - When: whenPlaying, - Height: TopBarH, - TimeVar: VarArmillaStrip, - NoteVar: VarNote, - }) -} diff --git a/inc/widget.cursor.go b/inc/widget/widget.cursor.go similarity index 65% rename from inc/widget.cursor.go rename to inc/widget/widget.cursor.go index 424a56b..3390f63 100644 --- a/inc/widget.cursor.go +++ b/inc/widget/widget.cursor.go @@ -1,11 +1,11 @@ -package inc +package widget import ( inkwell "git.teletypegames.org/engines/inkwell" ) func init() { - WidgetManager.Register(&inkwell.Cursor{ + Manager.Register(&inkwell.Cursor{ Name: "cursor", }) } diff --git a/inc/widget.dialog_box.go b/inc/widget/widget.dialog_box.go similarity index 79% rename from inc/widget.dialog_box.go rename to inc/widget/widget.dialog_box.go index 931ceac..9fa3cc4 100644 --- a/inc/widget.dialog_box.go +++ b/inc/widget/widget.dialog_box.go @@ -1,11 +1,11 @@ -package inc +package widget import ( inkwell "git.teletypegames.org/engines/inkwell" ) func init() { - WidgetManager.Register(&inkwell.DialogBox{ + Manager.Register(&inkwell.DialogBox{ Name: "dialog", Bounds: inkwell.Rect(0, ScreenH-LineH*9, DividerX, LineH*9), LineHeight: LineH, diff --git a/inc/widget.end_card.go b/inc/widget/widget.end_card.go similarity index 65% rename from inc/widget.end_card.go rename to inc/widget/widget.end_card.go index 181da2b..9fec8fc 100644 --- a/inc/widget.end_card.go +++ b/inc/widget/widget.end_card.go @@ -1,11 +1,11 @@ -package inc +package widget import ( inkwell "git.teletypegames.org/engines/inkwell" ) func init() { - WidgetManager.Register(&inkwell.EndCard{ + Manager.Register(&inkwell.EndCard{ Name: "endcard", }) } diff --git a/inc/widget.hotspot_debug.go b/inc/widget/widget.hotspot_debug.go similarity index 64% rename from inc/widget.hotspot_debug.go rename to inc/widget/widget.hotspot_debug.go index df3b934..dead46d 100644 --- a/inc/widget.hotspot_debug.go +++ b/inc/widget/widget.hotspot_debug.go @@ -1,11 +1,11 @@ -package inc +package widget import ( inkwell "git.teletypegames.org/engines/inkwell" ) func init() { - WidgetManager.Register(&inkwell.HotspotDebug{ + Manager.Register(&inkwell.HotspotDebug{ Name: "hotspot_debug", }) } diff --git a/inc/widget.hud_frame.go b/inc/widget/widget.hud_frame.go similarity index 95% rename from inc/widget.hud_frame.go rename to inc/widget/widget.hud_frame.go index 0eda796..f200324 100644 --- a/inc/widget.hud_frame.go +++ b/inc/widget/widget.hud_frame.go @@ -1,4 +1,4 @@ -package inc +package widget import ( inkwell "git.teletypegames.org/engines/inkwell" @@ -7,7 +7,7 @@ import ( ) func init() { - WidgetManager.Register(&hudFrame{ + Manager.Register(&hudFrame{ Name: "hudframe", }) } diff --git a/inc/widget.inventory_bar.go b/inc/widget/widget.inventory_bar.go similarity index 81% rename from inc/widget.inventory_bar.go rename to inc/widget/widget.inventory_bar.go index 104f4ba..abb792c 100644 --- a/inc/widget.inventory_bar.go +++ b/inc/widget/widget.inventory_bar.go @@ -1,11 +1,11 @@ -package inc +package widget import ( inkwell "git.teletypegames.org/engines/inkwell" ) func init() { - WidgetManager.Register(&inkwell.InventoryBar{ + Manager.Register(&inkwell.InventoryBar{ Name: "inventory", When: whenPlaying, Origin: inkwell.Point{ diff --git a/inc/widget.letterbox.go b/inc/widget/widget.letterbox.go similarity index 74% rename from inc/widget.letterbox.go rename to inc/widget/widget.letterbox.go index 90478c8..d8b805d 100644 --- a/inc/widget.letterbox.go +++ b/inc/widget/widget.letterbox.go @@ -1,14 +1,17 @@ -package inc +package widget import ( inkwell "git.teletypegames.org/engines/inkwell" + "git.teletypegames.org/games/realworld/inc" + "git.teletypegames.org/games/realworld/inc/theme" + "git.teletypegames.org/games/realworld/inc/world" "github.com/hajimehoshi/ebiten/v2" "github.com/hajimehoshi/ebiten/v2/inpututil" "github.com/hajimehoshi/ebiten/v2/vector" ) func init() { - WidgetManager.Register(&letterbox{ + Manager.Register(&letterbox{ Name: "letterbox", Bar: 36, }) @@ -24,11 +27,11 @@ func (l *letterbox) VisibleWhen() inkwell.Condition { return whenCutscene } func (l *letterbox) Layer() inkwell.Layer { return inkwell.LayerScene } func (l *letterbox) Tick(ctx *inkwell.UICtx) { - if !World.TapeWaiting() { + if !world.TapeWaiting() { return } if inpututil.IsKeyJustPressed(ebiten.KeySpace) { - World.TakeTapeOffer() + world.TakeTapeOffer() } } @@ -40,12 +43,12 @@ func (l *letterbox) Draw(dst *ebiten.Image, ctx *inkwell.UICtx) { bar = 18 } w, h := float32(g.Width), float32(g.Height) - black := RGB(0x000000) + black := theme.RGB(0x000000) vector.DrawFilledRect(dst, 0, 0, w, float32(bar), black, false) vector.DrawFilledRect(dst, 0, h-float32(bar), w, float32(bar), black, false) - if World.TapeWaiting() { - msg := "SPACE — " + g.CharacterLabel(Dex) + " has something to say" + if world.TapeWaiting() { + msg := "SPACE — " + g.CharacterLabel(inc.Dex) + " has something to say" g.DrawText(dst, msg, g.Width-inkwell.TextWidth(msg)-4, g.Height-int(bar)+4, th.ChatLogResponse) } } diff --git a/inc/widget.manager.go b/inc/widget/widget.manager.go similarity index 60% rename from inc/widget.manager.go rename to inc/widget/widget.manager.go index 562c209..edfaf60 100644 --- a/inc/widget.manager.go +++ b/inc/widget/widget.manager.go @@ -1,11 +1,15 @@ -package inc +package widget import ( inkwell "git.teletypegames.org/engines/inkwell" + "git.teletypegames.org/games/realworld/inc" + "git.teletypegames.org/games/realworld/inc/world" ) type Widget = inkwell.Widget +var Manager = inkwell.NewManager[Widget]() + const ( ScreenW = 640 ScreenH = 380 @@ -28,7 +32,7 @@ const ( ) var ( - whenPlaying = inkwell.VarEq(VarMode, string(ModePlay)) - whenCutscene = inkwell.VarEq(VarMode, string(ModeCutscene)) - whenUnpaused = inkwell.And(whenPlaying, inkwell.Not(inkwell.VarEq(VarNote, NotePaused))) + whenPlaying = inkwell.VarEq(inc.VarMode, string(world.ModePlay)) + whenCutscene = inkwell.VarEq(inc.VarMode, string(world.ModeCutscene)) + whenUnpaused = inkwell.And(whenPlaying, inkwell.Not(inkwell.VarEq(inc.VarNote, inc.NotePaused))) ) diff --git a/inc/widget.radial_verbs.go b/inc/widget/widget.radial_verbs.go similarity index 81% rename from inc/widget.radial_verbs.go rename to inc/widget/widget.radial_verbs.go index 3a3ee7b..2c71181 100644 --- a/inc/widget.radial_verbs.go +++ b/inc/widget/widget.radial_verbs.go @@ -1,11 +1,11 @@ -package inc +package widget import ( inkwell "git.teletypegames.org/engines/inkwell" ) func init() { - WidgetManager.Register(&inkwell.RadialVerbs{ + Manager.Register(&inkwell.RadialVerbs{ Name: "verbs", Trigger: inkwell.MouseButtonRight, Radius: 58, diff --git a/inc/widget.scene_nav.go b/inc/widget/widget.scene_nav.go similarity index 69% rename from inc/widget.scene_nav.go rename to inc/widget/widget.scene_nav.go index 3e6a81f..0001875 100644 --- a/inc/widget.scene_nav.go +++ b/inc/widget/widget.scene_nav.go @@ -1,11 +1,11 @@ -package inc +package widget import ( inkwell "git.teletypegames.org/engines/inkwell" ) func init() { - WidgetManager.Register(&inkwell.SceneNav{ + Manager.Register(&inkwell.SceneNav{ Name: "scene_nav", When: whenUnpaused, }) diff --git a/inc/widget.speech_bubble.go b/inc/widget/widget.speech_bubble.go similarity index 75% rename from inc/widget.speech_bubble.go rename to inc/widget/widget.speech_bubble.go index 53585d7..2ba1383 100644 --- a/inc/widget.speech_bubble.go +++ b/inc/widget/widget.speech_bubble.go @@ -1,11 +1,11 @@ -package inc +package widget import ( inkwell "git.teletypegames.org/engines/inkwell" ) func init() { - WidgetManager.Register(&inkwell.SpeechBubble{ + Manager.Register(&inkwell.SpeechBubble{ Name: "speech", MaxWidth: 360, Padding: Pad, diff --git a/inc/widget.status_line.go b/inc/widget/widget.status_line.go similarity index 79% rename from inc/widget.status_line.go rename to inc/widget/widget.status_line.go index 664f590..4f39d47 100644 --- a/inc/widget.status_line.go +++ b/inc/widget/widget.status_line.go @@ -1,11 +1,11 @@ -package inc +package widget import ( inkwell "git.teletypegames.org/engines/inkwell" ) func init() { - WidgetManager.Register(&inkwell.StatusLine{ + Manager.Register(&inkwell.StatusLine{ Name: "status", When: whenPlaying, Y: statusY, diff --git a/inc/widget.tape_channel.go b/inc/widget/widget.tape_channel.go similarity index 89% rename from inc/widget.tape_channel.go rename to inc/widget/widget.tape_channel.go index e82a728..045b617 100644 --- a/inc/widget.tape_channel.go +++ b/inc/widget/widget.tape_channel.go @@ -1,15 +1,17 @@ -package inc +package widget import ( "image/color" inkwell "git.teletypegames.org/engines/inkwell" + "git.teletypegames.org/games/realworld/inc" + "git.teletypegames.org/games/realworld/inc/tape" "github.com/hajimehoshi/ebiten/v2" "github.com/hajimehoshi/ebiten/v2/vector" ) func init() { - WidgetManager.Register(&tapeChannel{ + Manager.Register(&tapeChannel{ Name: "channel", Bounds: inkwell.Rect(DividerX+2, HUDTop+2, ScreenW-DividerX-4, ScreenH-HUDTop-4), }) @@ -59,7 +61,7 @@ func (t *tapeChannel) Draw(dst *ebiten.Image, ctx *inkwell.UICtx) { col, txt = th.ChatLogPrompt, m.Text case inkwell.LogResponse: - if !IsTape(m.Speaker) { + if !tape.Is(m.Speaker) { continue } col, txt = speechColor(g, m.Speaker, th.ChatLogResponse), m.Text @@ -91,11 +93,11 @@ func (t *tapeChannel) lastSpeaker(g *inkwell.Game, th inkwell.Theme) (string, co msgs := g.Messages() for i := len(msgs) - 1; i >= 0; i-- { m := msgs[i] - if m.Kind == inkwell.LogResponse && IsTape(m.Speaker) { + if m.Kind == inkwell.LogResponse && tape.Is(m.Speaker) { return g.CharacterLabel(m.Speaker), speechColor(g, m.Speaker, th.ChatLogResponse) } } - return g.CharacterLabel(Dex), speechColor(g, Dex, th.ChatLogResponse) + return g.CharacterLabel(inc.Dex), speechColor(g, inc.Dex, th.ChatLogResponse) } func speechColor(g *inkwell.Game, name string, fallback color.Color) color.Color { diff --git a/inc/widget.tape_slots.go b/inc/widget/widget.tape_slots.go similarity index 68% rename from inc/widget.tape_slots.go rename to inc/widget/widget.tape_slots.go index 8b3db74..0b86c66 100644 --- a/inc/widget.tape_slots.go +++ b/inc/widget/widget.tape_slots.go @@ -1,13 +1,16 @@ -package inc +package widget import ( inkwell "git.teletypegames.org/engines/inkwell" + "git.teletypegames.org/games/realworld/inc" + "git.teletypegames.org/games/realworld/inc/tape" + "git.teletypegames.org/games/realworld/inc/world" "github.com/hajimehoshi/ebiten/v2" "github.com/hajimehoshi/ebiten/v2/vector" ) func init() { - WidgetManager.Register(&tapeSlots{ + Manager.Register(&tapeSlots{ Name: "tapes", Bounds: inkwell.Rect(192, slotsY, 194, slotsH), }) @@ -37,9 +40,9 @@ func (t *tapeSlots) Tick(ctx *inkwell.UICtx) { switch { case r1.Contains(mp): - g.SetHoverLabel(g.CharacterLabel(Dex)) + g.SetHoverLabel(g.CharacterLabel(inc.Dex)) case r2.Contains(mp): - if s := World.Slot2(); s != "" { + if s := world.Slot2(); s != "" { g.SetHoverLabel(itemLabel(g, s)) } else { g.SetHoverLabel("empty tape slot") @@ -59,41 +62,41 @@ func (t *tapeSlots) Tick(ctx *inkwell.UICtx) { if slot2 && sel != "" { g.Inventory.Select("") - if IsTapeItem(sel) { - World.SetPending(sel) - World.Do(inkwell.RunScript(ScriptTapeInsert)) + if tape.IsItem(sel) { + world.SetPending(sel) + world.Do(inkwell.RunScript(inc.ScriptTapeInsert)) return } - World.Do(inkwell.Say(Dex, "That isn't a tape, Paul. That's an object. There is a difference.")) + world.Do(inkwell.Say(inc.Dex, "That isn't a tape, Paul. That's an object. There is a difference.")) return } if !slot2 && sel != "" { g.Inventory.Select("") - World.Do(inkwell.Say(Dex, "The first slot is mine. I'm not moving.")) + world.Do(inkwell.Say(inc.Dex, "The first slot is mine. I'm not moving.")) return } switch g.SelectedVerb() { case "talk": if !slot2 { - World.Do(Paused(inkwell.RunDialogue(DlgDex))) + world.Do(world.Paused(inkwell.RunDialogue(inc.DlgDex))) return } - if s := World.Slot2(); s != "" { - World.Do(Paused(inkwell.RunDialogue(TapeDialogue(s)))) + if s := world.Slot2(); s != "" { + world.Do(world.Paused(inkwell.RunDialogue(tape.Dialogue(s)))) return } - World.Do(inkwell.Say(Dex, "Empty. Nobody to talk to.")) + world.Do(inkwell.Say(inc.Dex, "Empty. Nobody to talk to.")) default: if !slot2 { - World.Do(inkwell.Say(Dex, "Me. Four kilobytes of a dead man. Be grateful.")) + world.Do(inkwell.Say(inc.Dex, "Me. Four kilobytes of a dead man. Be grateful.")) return } - if s := World.Slot2(); s != "" { - World.Do(inkwell.Say(Dex, "That is the second slot. Be careful what you let in.")) + if s := world.Slot2(); s != "" { + world.Do(inkwell.Say(inc.Dex, "That is the second slot. Be careful what you let in.")) return } - World.Do(inkwell.Say(Dex, "The second slot is empty. That's the rarer state.")) + world.Do(inkwell.Say(inc.Dex, "The second slot is empty. That's the rarer state.")) } } @@ -115,8 +118,8 @@ func (t *tapeSlots) Draw(dst *ebiten.Image, ctx *inkwell.UICtx) { g.DrawText(dst, inkwell.ClipText(body, inner), x, int(r.Y)+Pad/2+LineH, col) } - drawSlot(r1, "SLOT 1", g.CharacterLabel(Dex), true) - if s := World.Slot2(); s != "" { + drawSlot(r1, "SLOT 1", g.CharacterLabel(inc.Dex), true) + if s := world.Slot2(); s != "" { drawSlot(r2, "SLOT 2", itemLabel(g, s), true) } else { drawSlot(r2, "SLOT 2", "empty", false) diff --git a/inc/widget/widget.top_bar.go b/inc/widget/widget.top_bar.go new file mode 100644 index 0000000..fe4efdf --- /dev/null +++ b/inc/widget/widget.top_bar.go @@ -0,0 +1,16 @@ +package widget + +import ( + inkwell "git.teletypegames.org/engines/inkwell" + "git.teletypegames.org/games/realworld/inc" +) + +func init() { + Manager.Register(&inkwell.TopBar{ + Name: "topbar", + When: whenPlaying, + Height: TopBarH, + TimeVar: inc.VarArmillaStrip, + NoteVar: inc.VarNote, + }) +} diff --git a/inc/world.manager.go b/inc/world.manager.go deleted file mode 100644 index e382b6f..0000000 --- a/inc/world.manager.go +++ /dev/null @@ -1,65 +0,0 @@ -package inc - -import ( - inkwell "git.teletypegames.org/engines/inkwell" -) - -type Mode string - -const ( - ModePlay Mode = "play" - ModeCutscene Mode = "cutscene" - ModeMenu Mode = "menu" -) - -type world struct { - G *inkwell.Game - - pending string - - tapeWaiting bool - tapeLine inkwell.Action -} - -var World = &world{} - -func (w *world) attach(g *inkwell.Game) { - w.G = g - w.pending = "" - w.tapeWaiting = false - w.tapeLine = nil - w.SetMode(ModePlay) - w.SetNote("") -} - -func (w *world) Mode() Mode { - if v, ok := w.G.State.Var(VarMode).(string); ok { - return Mode(v) - } - return ModePlay -} - -func (w *world) SetMode(m Mode) { w.G.State.SetVar(VarMode, string(m)) } - -func (w *world) SetNote(text string) { w.G.State.SetVar(VarNote, text) } - -func (w *world) Paused() bool { return w.G.State.Var(VarNote) == NotePaused } - -func (w *world) Slot2() string { - if v, ok := w.G.State.Var(VarSlot2).(string); ok { - return v - } - return "" -} - -func (w *world) SetSlot2(item string) { w.G.State.SetVar(VarSlot2, item) } - -func (w *world) SetPending(item string) { w.pending = item } - -func (w *world) TakePending() string { - item := w.pending - w.pending = "" - return item -} - -func (w *world) TapeWaiting() bool { return w.tapeWaiting } diff --git a/inc/world.action.go b/inc/world/world.action.go similarity index 77% rename from inc/world.action.go rename to inc/world/world.action.go index 50368d9..184bb3c 100644 --- a/inc/world.action.go +++ b/inc/world/world.action.go @@ -1,10 +1,11 @@ -package inc +package world import ( inkwell "git.teletypegames.org/engines/inkwell" + "git.teletypegames.org/games/realworld/inc" ) -func (w *world) Do(a inkwell.Action) { w.G.Do(a) } +func Do(a inkwell.Action) { game.Do(a) } type fnAction struct{ fn func(*inkwell.Ctx) } @@ -32,24 +33,24 @@ func UseTheme(name string) inkwell.Action { } func SetMode(m Mode) inkwell.Action { - return Fn(func(*inkwell.Ctx) { World.SetMode(m) }) + return Fn(func(*inkwell.Ctx) { setMode(m) }) } func TapeOffer(line inkwell.Action) inkwell.Action { return Fn(func(*inkwell.Ctx) { - World.tapeLine = line - World.tapeWaiting = true + tapeLine = line + tapeWaiting = true }) } -func (w *world) TakeTapeOffer() { - if !w.tapeWaiting { +func TakeTapeOffer() { + if !tapeWaiting { return } - w.tapeWaiting = false - line := w.tapeLine - w.tapeLine = nil - w.Do(line) + tapeWaiting = false + line := tapeLine + tapeLine = nil + Do(line) } func Paused(inner inkwell.Action) inkwell.Action { @@ -78,11 +79,11 @@ type pausedRunner struct { func (r *pausedRunner) Tick(ctx *inkwell.Ctx) inkwell.Status { if !r.started { r.started = true - World.SetNote(NotePaused) + setNote(inc.NotePaused) } s := r.inner.Tick(ctx) if s != inkwell.StatusRunning { - World.SetNote("") + setNote("") } return s } diff --git a/inc/world/world.manager.go b/inc/world/world.manager.go new file mode 100644 index 0000000..1c1ff35 --- /dev/null +++ b/inc/world/world.manager.go @@ -0,0 +1,57 @@ +package world + +import ( + inkwell "git.teletypegames.org/engines/inkwell" + "git.teletypegames.org/games/realworld/inc" +) + +type Mode string + +const ( + ModePlay Mode = "play" + ModeCutscene Mode = "cutscene" + ModeMenu Mode = "menu" +) + +var ( + game *inkwell.Game + + pending string + + tapeWaiting bool + tapeLine inkwell.Action +) + +func Attach(g *inkwell.Game) { + game = g + pending = "" + tapeWaiting = false + tapeLine = nil + setMode(ModePlay) + setNote("") +} + +func Game() *inkwell.Game { return game } + +func setMode(m Mode) { game.State.SetVar(inc.VarMode, string(m)) } + +func setNote(text string) { game.State.SetVar(inc.VarNote, text) } + +func Slot2() string { + if v, ok := game.State.Var(inc.VarSlot2).(string); ok { + return v + } + return "" +} + +func SetSlot2(item string) { game.State.SetVar(inc.VarSlot2, item) } + +func SetPending(item string) { pending = item } + +func TakePending() string { + item := pending + pending = "" + return item +} + +func TapeWaiting() bool { return tapeWaiting } diff --git a/main.go b/main.go index 6f7f572..f1dcf6f 100644 --- a/main.go +++ b/main.go @@ -7,7 +7,7 @@ import ( inkwell "git.teletypegames.org/engines/inkwell" - "git.teletypegames.org/games/realworld/inc" + "git.teletypegames.org/games/realworld/inc/boot" ) //go:embed assets @@ -16,13 +16,13 @@ var assets embed.FS func init() { inkwell.AssetFS = assets } func main() { - var o inc.Opts + var o boot.Opts flag.StringVar(&o.Scene, "scene", "", "starting scene (empty: the alley)") flag.BoolVar(&o.Finale, "finale", false, "start with the finale, to try the Nokia-punk theme switch") flag.Parse() - if err := inkwell.Run(inc.New(o)); err != nil { + if err := inkwell.Run(boot.New(o)); err != nil { log.Fatal(err) } }