dirs
ci/woodpecker/push/ebitengine Pipeline was successful

This commit is contained in:
2026-08-30 23:21:06 +02:00
parent 28b1662195
commit c5c0c02c03
115 changed files with 1083 additions and 950 deletions
+121 -109
View File
@@ -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.<name>.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<Name>`, `Bg<Name>`
2. `inc/scene.<name>.go` — an `init()` registering a `Scene`
3. `inc/background.<name>.go` — an `init()` registering a `Background`
1. Constants in `inc/constants.go`: `Scene<Name>`, `Bg<Name>`
2. `inc/scene/scene.<name>.go` — an `init()` registering a `Scene`
3. `inc/background/background.<name>.go` — an `init()` registering a `Background`
4. A 640×380 PNG in `assets/bg/`
Nothing else moves. There is no list to update.
+54 -48
View File
@@ -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/<kind>.<name>.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.<name>.go` and `background.<name>.go`.
Nothing else moves.
Adding a scene means adding `inc/scene/scene.<name>.go` and
`inc/background/background.<name>.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.
@@ -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,
})
@@ -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,
})
@@ -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,
})
@@ -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,
})
@@ -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,
})
@@ -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,
})
@@ -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,
})
@@ -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,
})
@@ -1,7 +1,9 @@
package inc
package background
import (
inkwell "git.teletypegames.org/engines/inkwell"
)
type Background = inkwell.Asset
var Manager = inkwell.NewManager[Background]()
@@ -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,
})
@@ -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,
})
@@ -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,
})
@@ -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,
})
@@ -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,
})
@@ -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,
})
@@ -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,
})
@@ -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,
})
@@ -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,
})
@@ -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,
})
@@ -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,
})
@@ -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,
})
@@ -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,
})
@@ -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,
})
@@ -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,
})
@@ -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,
})
-64
View File
@@ -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
}
+63
View File
@@ -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
}
-14
View File
@@ -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,
})
}
-14
View File
@@ -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),
})
}
-19
View File
@@ -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,
})
}
-14
View File
@@ -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),
})
}
+16
View File
@@ -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,
})
}
@@ -1,7 +1,9 @@
package inc
package character
import (
inkwell "git.teletypegames.org/engines/inkwell"
)
type Character = inkwell.Character
var Manager = inkwell.NewManager[Character]()
+16
View File
@@ -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),
})
}
+21
View File
@@ -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,
})
}
+16
View File
@@ -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),
})
}
@@ -14,6 +14,11 @@ const (
ItemBlackArmilla = "black_market_armilla"
)
const (
RealWorld = "realworld-93"
NokiaPunk = "nokia-punk"
)
const (
DlgDex = "dex_talk"
DlgMysteryTape = "mystery_tape_silent"
@@ -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"),
},
},
@@ -1,7 +1,9 @@
package inc
package dialog
import (
inkwell "git.teletypegames.org/engines/inkwell"
)
type Dialog = inkwell.Dialogue
var Manager = inkwell.NewManager[Dialog]()
@@ -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"),
},
},
-22
View File
@@ -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."),
),
},
})
}
-16
View File
@@ -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."),
),
})
}
-16
View File
@@ -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."),
),
})
}
+23
View File
@@ -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."),
),
},
})
}
@@ -1,7 +1,9 @@
package inc
package item
import (
inkwell "git.teletypegames.org/engines/inkwell"
)
type Item = inkwell.Item
var Manager = inkwell.NewManager[Item]()
+17
View File
@@ -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."),
),
})
}
+17
View File
@@ -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."),
),
})
}
-100
View File
@@ -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."),
}
}
-28
View File
@@ -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."),
},
},
})
}
+101
View File
@@ -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."),
}
}
@@ -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",
@@ -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,
},
@@ -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,
},
@@ -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,
},
@@ -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,
},
@@ -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,
},
@@ -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,
},
@@ -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)
}
@@ -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,
},
@@ -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,
},
@@ -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,
},
@@ -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,
},
@@ -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,
},
@@ -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,
},
@@ -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,
},
@@ -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,
},
@@ -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,
},
@@ -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,
},
@@ -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
}
}
@@ -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,
},
@@ -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,
},
@@ -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,
},
@@ -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,
},
+29
View File
@@ -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."),
},
},
})
}
-23
View File
@@ -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"),
),
})
}
-16
View File
@@ -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?"),
),
})
}
-25
View File
@@ -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."),
),
})
}
+25
View File
@@ -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"),
),
})
}
@@ -1,7 +1,9 @@
package inc
package script
import (
inkwell "git.teletypegames.org/engines/inkwell"
)
type Script = inkwell.Script
var Manager = inkwell.NewManager[Script]()
+17
View File
@@ -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?"),
),
})
}
+27
View File
@@ -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."),
),
})
}
@@ -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)),
)
}
-8
View File
@@ -1,8 +0,0 @@
package inc
func init() {
TapeManager.Register(Tape{
Name: Dex,
Dialogue: DlgDex,
})
}
-32
View File
@@ -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
}
-9
View File
@@ -1,9 +0,0 @@
package inc
func init() {
TapeManager.Register(Tape{
Name: TapeMystery,
Item: ItemMysteryTape,
Dialogue: DlgMysteryTape,
})
}
-7
View File
@@ -1,7 +0,0 @@
package inc
func init() {
TapeManager.Register(Tape{
Name: TapeSupport,
})
}
+12
View File
@@ -0,0 +1,12 @@
package tape
import (
"git.teletypegames.org/games/realworld/inc"
)
func init() {
Manager.Register(Tape{
Name: inc.Dex,
Dialogue: inc.DlgDex,
})
}
+39
View File
@@ -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
}
+13
View File
@@ -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,
})
}
+11
View File
@@ -0,0 +1,11 @@
package tape
import (
"git.teletypegames.org/games/realworld/inc"
)
func init() {
Manager.Register(Tape{
Name: inc.TapeSupport,
})
}
@@ -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{
@@ -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),
@@ -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,
-15
View File
@@ -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,
})
}
@@ -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",
})
}
@@ -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,
@@ -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",
})
}
@@ -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",
})
}

Some files were not shown because too many files have changed in this diff Show More