register logic
This commit is contained in:
@@ -22,8 +22,8 @@ one-to-one.
|
|||||||
|
|
||||||
### No tests
|
### No tests
|
||||||
|
|
||||||
Do not write tests, and do not add test cases to the ones that already exist.
|
Do not write tests and do not add test files. Correctness is checked by running
|
||||||
Correctness is checked by running the game.
|
the game.
|
||||||
|
|
||||||
### Struct literals are always multi-line
|
### Struct literals are always multi-line
|
||||||
|
|
||||||
@@ -52,15 +52,19 @@ file's name carries the structure, in the form `[category].[name].go`.
|
|||||||
`character`, `dialog`, `script`, `world`, `ui`, `theme`, `names`, `boot`,
|
`character`, `dialog`, `script`, `world`, `ui`, `theme`, `names`, `boot`,
|
||||||
`content`.
|
`content`.
|
||||||
- `[category].manager.go` is the file that ties a category together — its
|
- `[category].manager.go` is the file that ties a category together — its
|
||||||
`register…` function, its shared types, its list of entities.
|
manager, its entity type, whatever the category shares.
|
||||||
- Every other file in a category holds exactly one entity: one screen, one
|
- Every other file in a category holds exactly one entity: one screen, one
|
||||||
background, one item.
|
background, one item. The file registers it itself, in an `init()`.
|
||||||
|
|
||||||
```
|
```
|
||||||
main.go flags + inkwell.Run
|
main.go flags + inkwell.Run
|
||||||
|
inc/manager.manager.go Manager[T]: the generic registry every category uses
|
||||||
|
inc/manager.interface.go ManagerInterface and the compile-time assertions
|
||||||
inc/boot.manager.go wiring; New(Opts) builds the game
|
inc/boot.manager.go wiring; New(Opts) builds the game
|
||||||
inc/names.manager.go entity names and world-state keys
|
inc/names.manager.go entity names and world-state keys
|
||||||
inc/theme.manager.go realworld-93 + nokia-punk
|
inc/theme.manager.go the theme manager 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.manager.go unsaved runtime state
|
||||||
inc/world.action.go custom actions and the action pump
|
inc/world.action.go custom actions and the action pump
|
||||||
inc/ui.manager.go HUD layout and widget registration
|
inc/ui.manager.go HUD layout and widget registration
|
||||||
@@ -71,25 +75,130 @@ inc/character.*.go the cast, tapes included
|
|||||||
inc/item.*.go inventory
|
inc/item.*.go inventory
|
||||||
inc/dialog.*.go dialogue trees
|
inc/dialog.*.go dialogue trees
|
||||||
inc/script.*.go named action sequences
|
inc/script.*.go named action sequences
|
||||||
inc/screen.manager.go the deck, the scene builder
|
inc/screen.manager.go the Screen type, the deck, the scene builder
|
||||||
inc/screen.exit.go the connections between screens
|
inc/screen.exit.go the connections between screens
|
||||||
inc/screen.*.go one file per screen
|
inc/screen.*.go one file per screen
|
||||||
```
|
```
|
||||||
|
|
||||||
|
`manager` is the one category with no entities of its own: it holds the registry
|
||||||
|
every other category is built from.
|
||||||
|
|
||||||
|
## Managers
|
||||||
|
|
||||||
|
Every category that owns a collection of entities has a manager, and they are
|
||||||
|
all the same generic type — `Manager[T]` in `manager.manager.go`. It keeps one
|
||||||
|
slice in registration order and one `map[string]int` beside it, so `GetByName`
|
||||||
|
is a map lookup, not a scan.
|
||||||
|
|
||||||
|
Since the entity types are aliases of engine structs, no method can be attached
|
||||||
|
to them; the manager is told how to read a name instead, which is all it needs:
|
||||||
|
|
||||||
|
```go
|
||||||
|
type Character = inkwell.Character
|
||||||
|
|
||||||
|
var CharacterManager = NewManager(func(entity Character) string { return entity.Name })
|
||||||
|
```
|
||||||
|
|
||||||
|
That is the whole of a category's manager file — an alias and one line. There
|
||||||
|
are seven managers: `BackgroundManager`, `CharacterManager`, `DialogManager`,
|
||||||
|
`ItemManager`, `ScriptManager`, `ScreenManager`, `ThemeManager`.
|
||||||
|
|
||||||
|
`manager.interface.go` holds the contract they all keep, and asserts each one
|
||||||
|
against it. A new manager goes on that list.
|
||||||
|
|
||||||
|
```go
|
||||||
|
type ManagerInterface[T any] interface {
|
||||||
|
Register(entity T)
|
||||||
|
GetByName(name string) (T, bool)
|
||||||
|
GetAll() []T
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
`Register` replaces by name and keeps the entity's position, so registering
|
||||||
|
twice is an update, never a duplicate. `GetAll` returns the slice itself, in
|
||||||
|
registration order.
|
||||||
|
|
||||||
|
`Screen` is the one entity type that is not an alias: a screen carries exits and
|
||||||
|
an `OnSelector` flag that inkwell's `Scene` knows nothing about.
|
||||||
|
|
||||||
|
### Entities register themselves
|
||||||
|
|
||||||
|
An entity file is a literal and nothing else. No constructor function, no list
|
||||||
|
somewhere else to keep in step — the file hands itself to its manager in an
|
||||||
|
`init()`:
|
||||||
|
|
||||||
|
```go
|
||||||
|
package inc
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
BackgroundManager.Register(Background{
|
||||||
|
Name: BgServerFarm,
|
||||||
|
Path: "assets/bg/server_farm.png",
|
||||||
|
Kind: inkwell.AssetImage,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Adding an entity is adding a file. Deleting one is deleting a file. Package-level
|
||||||
|
variables are initialised before any `init()` runs, so the managers exist by the
|
||||||
|
time the first 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 screens,
|
||||||
|
which is simply the order the files sit in.
|
||||||
|
|
||||||
|
### Handing a category to the engine
|
||||||
|
|
||||||
|
Once the game exists, `registerAll` walks a manager and gives every entity to
|
||||||
|
the engine's own manager. `registerContent` is the whole of it:
|
||||||
|
|
||||||
|
```go
|
||||||
|
func registerContent() {
|
||||||
|
registerAll(BackgroundManager, World.G.AssetManager.Register)
|
||||||
|
registerAll(CharacterManager, World.G.CharacterManager.Register)
|
||||||
|
registerAll(ItemManager, World.G.ItemManager.Register)
|
||||||
|
registerAll(DialogManager, World.G.DialogueManager.Register)
|
||||||
|
registerAll(ScriptManager, World.G.ScriptManager.Register)
|
||||||
|
registerScreen()
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
`registerScreen` is the one that needs its own function, because a screen has to
|
||||||
|
be turned into an `inkwell.Scene` first, and because the selector's pins are
|
||||||
|
derived from whichever screens marked themselves `OnSelector`.
|
||||||
|
|
||||||
|
## 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.HUDVisible()`, `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.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
## Naming
|
## Naming
|
||||||
|
|
||||||
One package means one namespace, so an entity's constructor carries its
|
One package means one namespace, so an entity's constructor carries its
|
||||||
category as a prefix:
|
category as a prefix:
|
||||||
|
|
||||||
```go
|
```go
|
||||||
screenAlley() backgroundAlley()
|
screenFloor screenBuild registerScreen fillSelectorPins
|
||||||
itemMysteryTape() characterMysteryTape()
|
|
||||||
dialogDexTalk() scriptTapeInsert()
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Category-level functions follow the same shape: `registerScreen`,
|
Entities themselves need no name at all — they are anonymous literals inside
|
||||||
`registerBackground`, `registerItem`, and so on. Only `New` and `Opts` are
|
their file's `init()`, and the file name says which one it is.
|
||||||
exported — they are what `main.go` needs, and nothing else leaves the package.
|
|
||||||
|
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, and the action constructors
|
||||||
|
(`TapeSay`, `Paused`, `SetMode`, `EnterScene`, `Back`, `Fn`).
|
||||||
|
|
||||||
|
Everything else is machinery and stays unexported: the HUD widgets
|
||||||
|
(`tapeSlots`, `letterbox`, `hudFrame`, …), the `register…` functions, the
|
||||||
|
runners, `screenBuild`, `exit`.
|
||||||
|
|
||||||
The engine's word for a screen is `Scene`. Ours is **screen**, because the
|
The engine's word for a screen is `Scene`. Ours is **screen**, because the
|
||||||
wiki, the concept-art deck and the beat tables all count screens. "Scene"
|
wiki, the concept-art deck and the beat tables all count screens. "Scene"
|
||||||
@@ -112,14 +221,12 @@ other way round.
|
|||||||
|
|
||||||
## Adding a screen
|
## Adding a screen
|
||||||
|
|
||||||
1. `inc/screen.<name>.go` — `screen<Name>() screen`
|
1. Constants in `inc/names.manager.go`: `Screen<Name>`, `Bg<Name>`
|
||||||
2. `inc/background.<name>.go` — `background<Name>() inkwell.Asset`
|
2. `inc/screen.<name>.go` — an `init()` registering a `Screen`
|
||||||
3. One line in `screenDeck` (`inc/screen.manager.go`)
|
3. `inc/background.<name>.go` — an `init()` registering a `Background`
|
||||||
4. One line in `registerBackground` (`inc/background.manager.go`)
|
4. A 640×380 PNG in `assets/bg/`
|
||||||
5. Constants in `inc/names.manager.go`: `Screen<Name>`, `Bg<Name>`
|
|
||||||
6. A 640×380 PNG in `assets/bg/`
|
|
||||||
|
|
||||||
Nothing else moves.
|
Nothing else moves. There is no list to update.
|
||||||
|
|
||||||
## Commands
|
## Commands
|
||||||
|
|
||||||
|
|||||||
@@ -48,7 +48,6 @@ go mod edit -dropreplace git.teletypegames.org/engines/inkwell
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
make build # native binary into bin/
|
make build # native binary into bin/
|
||||||
make test # headless: validates content and HUD layout
|
|
||||||
make wasm # dist/game.wasm + wasm_exec.js
|
make wasm # dist/game.wasm + wasm_exec.js
|
||||||
make export VERSION=0.1 # zipped HTML/WASM bundle
|
make export VERSION=0.1 # zipped HTML/WASM bundle
|
||||||
make binaries VERSION=0.1 # win-x86, win-x64, linux-x64 zips
|
make binaries VERSION=0.1 # win-x86, win-x64, linux-x64 zips
|
||||||
@@ -63,13 +62,13 @@ Release metadata lives in `metadata.json`.
|
|||||||
|---|---|
|
|---|---|
|
||||||
| left click | run the selected verb |
|
| left click | run the selected verb |
|
||||||
| right click | verb coin (Look / Use / Talk / Take) |
|
| right click | verb coin (Look / Use / Talk / Take) |
|
||||||
| `←` `→` | previous / next screen, in concept-art order, wrapping |
|
| `←` `→` | previous / next screen, in file order, wrapping |
|
||||||
| `F1` | toggle hotspot outlines |
|
| `F1` | toggle hotspot outlines |
|
||||||
| `SPACE` | during a cutscene: let the tape speak, if it offered |
|
| `SPACE` | during a cutscene: let the tape speak, if it offered |
|
||||||
|
|
||||||
The screens are connected to each other (see **The map** below); the arrow keys
|
The screens are connected to each other (see **The map** below); the arrow keys
|
||||||
are a reviewing tool on top of that, walking the deck in concept-art order. The
|
are a reviewing tool on top of that, walking every screen in turn. The walk is
|
||||||
walk is inert during a cutscene, a menu, or a stopped world, so it can never cut
|
inert during a cutscene, a menu, or a stopped world, so it can never cut
|
||||||
across an authored beat.
|
across an authored beat.
|
||||||
|
|
||||||
Screenshots: `EBITEN_SCREENSHOT_KEY=q go run .`, then press `q` in the window.
|
Screenshots: `EBITEN_SCREENSHOT_KEY=q go run .`, then press `q` in the window.
|
||||||
@@ -154,20 +153,22 @@ licence.
|
|||||||
The game is one flat package, `inc`. There are no subdirectories: a file's
|
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
|
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
|
always singular, and `[category].manager.go` is the file that ties that category
|
||||||
together — its `register…`, its shared types, its list.
|
together — its manager, its shared types, its hand-off to the engine.
|
||||||
|
|
||||||
```
|
```
|
||||||
main.go flags + inkwell.Run
|
main.go flags + inkwell.Run
|
||||||
inc/names.manager.go entity names and world-state keys
|
inc/manager.manager.go Manager[T], the generic registry
|
||||||
inc/theme.manager.go realworld-93 + nokia-punk
|
inc/manager.interface.go ManagerInterface, the contract every manager keeps
|
||||||
inc/world.*.go unsaved runtime state, custom actions, action pump
|
inc/names.manager.go entity names and world-state keys
|
||||||
inc/ui.*.go HUD: layout, custom widgets, coloured text
|
inc/theme.*.go realworld-93 + nokia-punk
|
||||||
inc/<kind>.<name>.go one file per registered entity, by kind
|
inc/world.*.go unsaved runtime state, custom actions, action pump
|
||||||
inc/boot.manager.go wiring
|
inc/ui.*.go HUD: layout, custom widgets, coloured text
|
||||||
|
inc/<kind>.<name>.go one file per registered entity, by kind
|
||||||
|
inc/boot.manager.go wiring
|
||||||
```
|
```
|
||||||
|
|
||||||
Nothing is enforced by the compiler any more, so the layering is a rule the
|
Nothing is enforced by the compiler any more, so the layering is a rule the
|
||||||
code keeps by hand: the world knows nothing about the HUD or the content, and
|
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.
|
both build on it, never the other way round.
|
||||||
|
|
||||||
```
|
```
|
||||||
@@ -188,12 +189,60 @@ script.*.go script.tape_insert.go script.awakening_finale.go
|
|||||||
screen.*.go one file per screen: screen.alley.go, … + screen.exit.go
|
screen.*.go one file per screen: screen.alley.go, … + screen.exit.go
|
||||||
```
|
```
|
||||||
|
|
||||||
Adding a screen means adding `screen.<name>.go` and `background.<name>.go`, and
|
Adding a screen means adding `screen.<name>.go` and `background.<name>.go`.
|
||||||
one line in each category's manager list. Nothing else moves.
|
Nothing else moves.
|
||||||
|
|
||||||
Since everything shares one namespace, an entity's constructor carries its
|
Every category owns a manager, and they are all the same generic type,
|
||||||
category: `screenAlley()` is the screen, `backgroundAlley()` the painting behind
|
`Manager[T]` — one slice in registration order, one `map[string]int` beside it,
|
||||||
it, `itemMysteryTape()` the prop and `characterMysteryTape()` the voice on it.
|
so a lookup by name is a map hit rather than a scan. The entity types are
|
||||||
|
aliases of engine structs and cannot carry methods, so the manager is handed a
|
||||||
|
function that reads the name instead. A category's manager file is an alias and
|
||||||
|
one line:
|
||||||
|
|
||||||
|
```go
|
||||||
|
type Character = inkwell.Character
|
||||||
|
|
||||||
|
var CharacterManager = NewManager(func(entity Character) string { return entity.Name })
|
||||||
|
```
|
||||||
|
|
||||||
|
They all keep the same contract, asserted in `manager.interface.go`:
|
||||||
|
|
||||||
|
```go
|
||||||
|
type ManagerInterface[T any] interface {
|
||||||
|
Register(entity T)
|
||||||
|
GetByName(name string) (T, bool)
|
||||||
|
GetAll() []T
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
An entity file is a literal that hands itself over in an `init()`:
|
||||||
|
|
||||||
|
```go
|
||||||
|
func init() {
|
||||||
|
BackgroundManager.Register(Background{
|
||||||
|
Name: BgServerFarm,
|
||||||
|
Path: "assets/bg/server_farm.png",
|
||||||
|
Kind: inkwell.AssetImage,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
So adding an entity is adding a file, and there is no second list to keep in
|
||||||
|
step. The price is that registration order is file-name order: the arrow keys
|
||||||
|
walk the screens alphabetically rather than in the concept-art deck's order.
|
||||||
|
That was a deliberate trade — the deck order was a list that had to be kept in
|
||||||
|
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:
|
||||||
|
`ScreenManager.GetByName("alley")` answers before a single scene has been handed
|
||||||
|
over. `registerContent` is where the hand-off happens, one `registerAll` call
|
||||||
|
per category.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
**On the word "screen".** inkwell's entity is called a `Scene`, and that is the
|
**On the word "screen".** inkwell's entity is called a `Scene`, and that is the
|
||||||
type every `screen.*.go` file returns — but the wiki, the concept-art deck and
|
type every `screen.*.go` file returns — but the wiki, the concept-art deck and
|
||||||
@@ -231,9 +280,8 @@ convention every 1990s point & click used, and one field to re-aim later. A
|
|||||||
screen reached from several rooms has no fixed way out: the BBS terminal is the
|
screen reached from several rooms has no fixed way out: the BBS terminal is the
|
||||||
same terminal from the club, the flat or the roof, so its exit is `back`.
|
same terminal from the club, the flat or the roof, so its exit is `back`.
|
||||||
|
|
||||||
Three tests keep the map honest: every exit names a registered screen, every
|
The graph stays machine-readable: exit hotspots are named `exit:<target>`, so
|
||||||
screen has a way out, and every screen can be walked to from Paul's shop through
|
the connections can be read straight back out of the registered screens.
|
||||||
the exits alone — the arrow keys do not count.
|
|
||||||
|
|
||||||
## Engine workarounds
|
## Engine workarounds
|
||||||
|
|
||||||
@@ -297,9 +345,10 @@ Also: the inkwell README gives the module path as
|
|||||||
hides them; the deck wanted them struck through but visible, so the list
|
hides them; the deck wanted them struck through but visible, so the list
|
||||||
becomes a memory of what you already tried. Needs a thin override over
|
becomes a memory of what you already tried. Needs a thin override over
|
||||||
`DialogBox`.
|
`DialogBox`.
|
||||||
- **Only beat 3 exists.** The alley is a vertical slice; `boot.opening` sets the
|
- **Only beat 3 exists.** The alley is a vertical slice; `bootOpening` sets the
|
||||||
police-tip flag that beat 2 will eventually set.
|
police-tip flag that beat 2 will eventually set.
|
||||||
- **The render has only been inspected once, by the author of this repo.**
|
- **The render has only been inspected once, by the author of this repo.**
|
||||||
Geometry is covered by tests and a layout dump, but this environment cannot
|
Geometry is derived from one font cell and one screen size, but this
|
||||||
take a screenshot (both synthetic keystrokes and screen capture are blocked by
|
environment cannot take a screenshot (both synthetic keystrokes and screen
|
||||||
macOS privacy permissions), so every visual judgement has to come from you.
|
capture are blocked by macOS privacy permissions), so every visual judgement
|
||||||
|
has to come from you.
|
||||||
|
|||||||
@@ -4,10 +4,10 @@ import (
|
|||||||
inkwell "git.teletypegames.org/engines/inkwell"
|
inkwell "git.teletypegames.org/engines/inkwell"
|
||||||
)
|
)
|
||||||
|
|
||||||
func backgroundAlley() inkwell.Asset {
|
func init() {
|
||||||
return inkwell.Asset{
|
BackgroundManager.Register(Background{
|
||||||
Name: BgAlley,
|
Name: BgAlley,
|
||||||
Path: "assets/bg/alley.png",
|
Path: "assets/bg/alley.png",
|
||||||
Kind: inkwell.AssetImage,
|
Kind: inkwell.AssetImage,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,10 +4,10 @@ import (
|
|||||||
inkwell "git.teletypegames.org/engines/inkwell"
|
inkwell "git.teletypegames.org/engines/inkwell"
|
||||||
)
|
)
|
||||||
|
|
||||||
func backgroundBbsTerminal() inkwell.Asset {
|
func init() {
|
||||||
return inkwell.Asset{
|
BackgroundManager.Register(Background{
|
||||||
Name: BgBBSTerminal,
|
Name: BgBBSTerminal,
|
||||||
Path: "assets/bg/bbs_terminal.png",
|
Path: "assets/bg/bbs_terminal.png",
|
||||||
Kind: inkwell.AssetImage,
|
Kind: inkwell.AssetImage,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,10 +4,10 @@ import (
|
|||||||
inkwell "git.teletypegames.org/engines/inkwell"
|
inkwell "git.teletypegames.org/engines/inkwell"
|
||||||
)
|
)
|
||||||
|
|
||||||
func backgroundBvkBranch() inkwell.Asset {
|
func init() {
|
||||||
return inkwell.Asset{
|
BackgroundManager.Register(Background{
|
||||||
Name: BgBVKBranch,
|
Name: BgBVKBranch,
|
||||||
Path: "assets/bg/bvk_branch.png",
|
Path: "assets/bg/bvk_branch.png",
|
||||||
Kind: inkwell.AssetImage,
|
Kind: inkwell.AssetImage,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,10 +4,10 @@ import (
|
|||||||
inkwell "git.teletypegames.org/engines/inkwell"
|
inkwell "git.teletypegames.org/engines/inkwell"
|
||||||
)
|
)
|
||||||
|
|
||||||
func backgroundColumbarium() inkwell.Asset {
|
func init() {
|
||||||
return inkwell.Asset{
|
BackgroundManager.Register(Background{
|
||||||
Name: BgColumbarium,
|
Name: BgColumbarium,
|
||||||
Path: "assets/bg/columbarium.png",
|
Path: "assets/bg/columbarium.png",
|
||||||
Kind: inkwell.AssetImage,
|
Kind: inkwell.AssetImage,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,10 +4,10 @@ import (
|
|||||||
inkwell "git.teletypegames.org/engines/inkwell"
|
inkwell "git.teletypegames.org/engines/inkwell"
|
||||||
)
|
)
|
||||||
|
|
||||||
func backgroundCuratorShop() inkwell.Asset {
|
func init() {
|
||||||
return inkwell.Asset{
|
BackgroundManager.Register(Background{
|
||||||
Name: BgCuratorShop,
|
Name: BgCuratorShop,
|
||||||
Path: "assets/bg/curator_shop.png",
|
Path: "assets/bg/curator_shop.png",
|
||||||
Kind: inkwell.AssetImage,
|
Kind: inkwell.AssetImage,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,10 +4,10 @@ import (
|
|||||||
inkwell "git.teletypegames.org/engines/inkwell"
|
inkwell "git.teletypegames.org/engines/inkwell"
|
||||||
)
|
)
|
||||||
|
|
||||||
func backgroundHackerspace() inkwell.Asset {
|
func init() {
|
||||||
return inkwell.Asset{
|
BackgroundManager.Register(Background{
|
||||||
Name: BgHackerspace,
|
Name: BgHackerspace,
|
||||||
Path: "assets/bg/hackerspace.png",
|
Path: "assets/bg/hackerspace.png",
|
||||||
Kind: inkwell.AssetImage,
|
Kind: inkwell.AssetImage,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,10 +4,10 @@ import (
|
|||||||
inkwell "git.teletypegames.org/engines/inkwell"
|
inkwell "git.teletypegames.org/engines/inkwell"
|
||||||
)
|
)
|
||||||
|
|
||||||
func backgroundHospital() inkwell.Asset {
|
func init() {
|
||||||
return inkwell.Asset{
|
BackgroundManager.Register(Background{
|
||||||
Name: BgHospital,
|
Name: BgHospital,
|
||||||
Path: "assets/bg/hospital.png",
|
Path: "assets/bg/hospital.png",
|
||||||
Kind: inkwell.AssetImage,
|
Kind: inkwell.AssetImage,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,10 +4,10 @@ import (
|
|||||||
inkwell "git.teletypegames.org/engines/inkwell"
|
inkwell "git.teletypegames.org/engines/inkwell"
|
||||||
)
|
)
|
||||||
|
|
||||||
func backgroundIceCreamShop() inkwell.Asset {
|
func init() {
|
||||||
return inkwell.Asset{
|
BackgroundManager.Register(Background{
|
||||||
Name: BgIceCreamShop,
|
Name: BgIceCreamShop,
|
||||||
Path: "assets/bg/ice_cream_shop.png",
|
Path: "assets/bg/ice_cream_shop.png",
|
||||||
Kind: inkwell.AssetImage,
|
Kind: inkwell.AssetImage,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,33 +4,6 @@ import (
|
|||||||
inkwell "git.teletypegames.org/engines/inkwell"
|
inkwell "git.teletypegames.org/engines/inkwell"
|
||||||
)
|
)
|
||||||
|
|
||||||
func registerBackground(w *World) {
|
type Background = inkwell.Asset
|
||||||
for _, a := range []inkwell.Asset{
|
|
||||||
backgroundSelector(),
|
var BackgroundManager = NewManager(func(entity Background) string { return entity.Name })
|
||||||
backgroundPaulShop(),
|
|
||||||
backgroundNoodleHouse(),
|
|
||||||
backgroundNormanApartment(),
|
|
||||||
backgroundPoliceStation(),
|
|
||||||
backgroundAlley(),
|
|
||||||
backgroundHackerspace(),
|
|
||||||
backgroundIceCreamShop(),
|
|
||||||
backgroundTrinketShop(),
|
|
||||||
backgroundSmallRestaurant(),
|
|
||||||
backgroundSecretClub(),
|
|
||||||
backgroundBbsTerminal(),
|
|
||||||
backgroundStreet(),
|
|
||||||
backgroundHospital(),
|
|
||||||
backgroundServerFarm(),
|
|
||||||
backgroundSecretLab(),
|
|
||||||
backgroundRooftopHideout(),
|
|
||||||
backgroundPublicBBS(),
|
|
||||||
backgroundBvkBranch(),
|
|
||||||
backgroundCuratorShop(),
|
|
||||||
backgroundScrapMarket(),
|
|
||||||
backgroundSamizdatPress(),
|
|
||||||
backgroundShowroom(),
|
|
||||||
backgroundColumbarium(),
|
|
||||||
} {
|
|
||||||
w.G.AssetManager.Register(a)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -4,10 +4,10 @@ import (
|
|||||||
inkwell "git.teletypegames.org/engines/inkwell"
|
inkwell "git.teletypegames.org/engines/inkwell"
|
||||||
)
|
)
|
||||||
|
|
||||||
func backgroundNoodleHouse() inkwell.Asset {
|
func init() {
|
||||||
return inkwell.Asset{
|
BackgroundManager.Register(Background{
|
||||||
Name: BgNoodleHouse,
|
Name: BgNoodleHouse,
|
||||||
Path: "assets/bg/noodle_house.png",
|
Path: "assets/bg/noodle_house.png",
|
||||||
Kind: inkwell.AssetImage,
|
Kind: inkwell.AssetImage,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,10 +4,10 @@ import (
|
|||||||
inkwell "git.teletypegames.org/engines/inkwell"
|
inkwell "git.teletypegames.org/engines/inkwell"
|
||||||
)
|
)
|
||||||
|
|
||||||
func backgroundNormanApartment() inkwell.Asset {
|
func init() {
|
||||||
return inkwell.Asset{
|
BackgroundManager.Register(Background{
|
||||||
Name: BgNormanApartment,
|
Name: BgNormanApartment,
|
||||||
Path: "assets/bg/norman_apartment.png",
|
Path: "assets/bg/norman_apartment.png",
|
||||||
Kind: inkwell.AssetImage,
|
Kind: inkwell.AssetImage,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,10 +4,10 @@ import (
|
|||||||
inkwell "git.teletypegames.org/engines/inkwell"
|
inkwell "git.teletypegames.org/engines/inkwell"
|
||||||
)
|
)
|
||||||
|
|
||||||
func backgroundPaulShop() inkwell.Asset {
|
func init() {
|
||||||
return inkwell.Asset{
|
BackgroundManager.Register(Background{
|
||||||
Name: BgPaulShop,
|
Name: BgPaulShop,
|
||||||
Path: "assets/bg/paul_shop.png",
|
Path: "assets/bg/paul_shop.png",
|
||||||
Kind: inkwell.AssetImage,
|
Kind: inkwell.AssetImage,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,10 +4,10 @@ import (
|
|||||||
inkwell "git.teletypegames.org/engines/inkwell"
|
inkwell "git.teletypegames.org/engines/inkwell"
|
||||||
)
|
)
|
||||||
|
|
||||||
func backgroundPoliceStation() inkwell.Asset {
|
func init() {
|
||||||
return inkwell.Asset{
|
BackgroundManager.Register(Background{
|
||||||
Name: BgPoliceStation,
|
Name: BgPoliceStation,
|
||||||
Path: "assets/bg/police_station.png",
|
Path: "assets/bg/police_station.png",
|
||||||
Kind: inkwell.AssetImage,
|
Kind: inkwell.AssetImage,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,10 +4,10 @@ import (
|
|||||||
inkwell "git.teletypegames.org/engines/inkwell"
|
inkwell "git.teletypegames.org/engines/inkwell"
|
||||||
)
|
)
|
||||||
|
|
||||||
func backgroundPublicBBS() inkwell.Asset {
|
func init() {
|
||||||
return inkwell.Asset{
|
BackgroundManager.Register(Background{
|
||||||
Name: BgPublicBBS,
|
Name: BgPublicBBS,
|
||||||
Path: "assets/bg/public_bbs.png",
|
Path: "assets/bg/public_bbs.png",
|
||||||
Kind: inkwell.AssetImage,
|
Kind: inkwell.AssetImage,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,10 +4,10 @@ import (
|
|||||||
inkwell "git.teletypegames.org/engines/inkwell"
|
inkwell "git.teletypegames.org/engines/inkwell"
|
||||||
)
|
)
|
||||||
|
|
||||||
func backgroundRooftopHideout() inkwell.Asset {
|
func init() {
|
||||||
return inkwell.Asset{
|
BackgroundManager.Register(Background{
|
||||||
Name: BgRooftopHideout,
|
Name: BgRooftopHideout,
|
||||||
Path: "assets/bg/rooftop_hideout.png",
|
Path: "assets/bg/rooftop_hideout.png",
|
||||||
Kind: inkwell.AssetImage,
|
Kind: inkwell.AssetImage,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,10 +4,10 @@ import (
|
|||||||
inkwell "git.teletypegames.org/engines/inkwell"
|
inkwell "git.teletypegames.org/engines/inkwell"
|
||||||
)
|
)
|
||||||
|
|
||||||
func backgroundSamizdatPress() inkwell.Asset {
|
func init() {
|
||||||
return inkwell.Asset{
|
BackgroundManager.Register(Background{
|
||||||
Name: BgSamizdatPress,
|
Name: BgSamizdatPress,
|
||||||
Path: "assets/bg/samizdat_press.png",
|
Path: "assets/bg/samizdat_press.png",
|
||||||
Kind: inkwell.AssetImage,
|
Kind: inkwell.AssetImage,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,10 +4,10 @@ import (
|
|||||||
inkwell "git.teletypegames.org/engines/inkwell"
|
inkwell "git.teletypegames.org/engines/inkwell"
|
||||||
)
|
)
|
||||||
|
|
||||||
func backgroundScrapMarket() inkwell.Asset {
|
func init() {
|
||||||
return inkwell.Asset{
|
BackgroundManager.Register(Background{
|
||||||
Name: BgScrapMarket,
|
Name: BgScrapMarket,
|
||||||
Path: "assets/bg/scrap_market.png",
|
Path: "assets/bg/scrap_market.png",
|
||||||
Kind: inkwell.AssetImage,
|
Kind: inkwell.AssetImage,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,10 +4,10 @@ import (
|
|||||||
inkwell "git.teletypegames.org/engines/inkwell"
|
inkwell "git.teletypegames.org/engines/inkwell"
|
||||||
)
|
)
|
||||||
|
|
||||||
func backgroundSecretClub() inkwell.Asset {
|
func init() {
|
||||||
return inkwell.Asset{
|
BackgroundManager.Register(Background{
|
||||||
Name: BgSecretClub,
|
Name: BgSecretClub,
|
||||||
Path: "assets/bg/secret_club.png",
|
Path: "assets/bg/secret_club.png",
|
||||||
Kind: inkwell.AssetImage,
|
Kind: inkwell.AssetImage,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,10 +4,10 @@ import (
|
|||||||
inkwell "git.teletypegames.org/engines/inkwell"
|
inkwell "git.teletypegames.org/engines/inkwell"
|
||||||
)
|
)
|
||||||
|
|
||||||
func backgroundSecretLab() inkwell.Asset {
|
func init() {
|
||||||
return inkwell.Asset{
|
BackgroundManager.Register(Background{
|
||||||
Name: BgSecretLab,
|
Name: BgSecretLab,
|
||||||
Path: "assets/bg/secret_lab.png",
|
Path: "assets/bg/secret_lab.png",
|
||||||
Kind: inkwell.AssetImage,
|
Kind: inkwell.AssetImage,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,10 +4,10 @@ import (
|
|||||||
inkwell "git.teletypegames.org/engines/inkwell"
|
inkwell "git.teletypegames.org/engines/inkwell"
|
||||||
)
|
)
|
||||||
|
|
||||||
func backgroundSelector() inkwell.Asset {
|
func init() {
|
||||||
return inkwell.Asset{
|
BackgroundManager.Register(Background{
|
||||||
Name: BgSelector,
|
Name: BgSelector,
|
||||||
Path: "assets/bg/selector.png",
|
Path: "assets/bg/selector.png",
|
||||||
Kind: inkwell.AssetImage,
|
Kind: inkwell.AssetImage,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,10 +4,10 @@ import (
|
|||||||
inkwell "git.teletypegames.org/engines/inkwell"
|
inkwell "git.teletypegames.org/engines/inkwell"
|
||||||
)
|
)
|
||||||
|
|
||||||
func backgroundServerFarm() inkwell.Asset {
|
func init() {
|
||||||
return inkwell.Asset{
|
BackgroundManager.Register(Background{
|
||||||
Name: BgServerFarm,
|
Name: BgServerFarm,
|
||||||
Path: "assets/bg/server_farm.png",
|
Path: "assets/bg/server_farm.png",
|
||||||
Kind: inkwell.AssetImage,
|
Kind: inkwell.AssetImage,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,10 +4,10 @@ import (
|
|||||||
inkwell "git.teletypegames.org/engines/inkwell"
|
inkwell "git.teletypegames.org/engines/inkwell"
|
||||||
)
|
)
|
||||||
|
|
||||||
func backgroundShowroom() inkwell.Asset {
|
func init() {
|
||||||
return inkwell.Asset{
|
BackgroundManager.Register(Background{
|
||||||
Name: BgShowroom,
|
Name: BgShowroom,
|
||||||
Path: "assets/bg/showroom.png",
|
Path: "assets/bg/showroom.png",
|
||||||
Kind: inkwell.AssetImage,
|
Kind: inkwell.AssetImage,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,10 +4,10 @@ import (
|
|||||||
inkwell "git.teletypegames.org/engines/inkwell"
|
inkwell "git.teletypegames.org/engines/inkwell"
|
||||||
)
|
)
|
||||||
|
|
||||||
func backgroundSmallRestaurant() inkwell.Asset {
|
func init() {
|
||||||
return inkwell.Asset{
|
BackgroundManager.Register(Background{
|
||||||
Name: BgSmallRestaurant,
|
Name: BgSmallRestaurant,
|
||||||
Path: "assets/bg/small_restaurant.png",
|
Path: "assets/bg/small_restaurant.png",
|
||||||
Kind: inkwell.AssetImage,
|
Kind: inkwell.AssetImage,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,10 +4,10 @@ import (
|
|||||||
inkwell "git.teletypegames.org/engines/inkwell"
|
inkwell "git.teletypegames.org/engines/inkwell"
|
||||||
)
|
)
|
||||||
|
|
||||||
func backgroundStreet() inkwell.Asset {
|
func init() {
|
||||||
return inkwell.Asset{
|
BackgroundManager.Register(Background{
|
||||||
Name: BgStreet,
|
Name: BgStreet,
|
||||||
Path: "assets/bg/street.png",
|
Path: "assets/bg/street.png",
|
||||||
Kind: inkwell.AssetImage,
|
Kind: inkwell.AssetImage,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,10 +4,10 @@ import (
|
|||||||
inkwell "git.teletypegames.org/engines/inkwell"
|
inkwell "git.teletypegames.org/engines/inkwell"
|
||||||
)
|
)
|
||||||
|
|
||||||
func backgroundTrinketShop() inkwell.Asset {
|
func init() {
|
||||||
return inkwell.Asset{
|
BackgroundManager.Register(Background{
|
||||||
Name: BgTrinketShop,
|
Name: BgTrinketShop,
|
||||||
Path: "assets/bg/trinket_shop.png",
|
Path: "assets/bg/trinket_shop.png",
|
||||||
Kind: inkwell.AssetImage,
|
Kind: inkwell.AssetImage,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
+7
-7
@@ -18,21 +18,21 @@ func New(o Opts) *inkwell.Game {
|
|||||||
g := inkwell.NewGame("Real World", ScreenW, ScreenH)
|
g := inkwell.NewGame("Real World", ScreenW, ScreenH)
|
||||||
g.MaxLogLines = 64
|
g.MaxLogLines = 64
|
||||||
|
|
||||||
w := newWorld(g)
|
World.attach(g)
|
||||||
registerTheme(g)
|
registerTheme()
|
||||||
registerContent(w)
|
registerContent()
|
||||||
|
|
||||||
g.UseTheme(RealWorld)
|
g.UseTheme(RealWorld)
|
||||||
registerUI(w)
|
registerUI()
|
||||||
|
|
||||||
g.StartAt(start)
|
g.StartAt(start)
|
||||||
g.OnStart(inkwell.Seq(bootOpening(w, start, o.Finale)...))
|
g.OnStart(inkwell.Seq(bootOpening(start, o.Finale)...))
|
||||||
return g
|
return g
|
||||||
}
|
}
|
||||||
|
|
||||||
func bootOpening(w *World, start string, finale bool) []inkwell.Action {
|
func bootOpening(start string, finale bool) []inkwell.Action {
|
||||||
acts := []inkwell.Action{
|
acts := []inkwell.Action{
|
||||||
EnterScene(w, start),
|
EnterScene(start),
|
||||||
inkwell.SetFlag(FlagPoliceTip),
|
inkwell.SetFlag(FlagPoliceTip),
|
||||||
inkwell.Say(Paul, "Back alley. Just like the clerk said."),
|
inkwell.Say(Paul, "Back alley. Just like the clerk said."),
|
||||||
TapeSay(Dex, "A government office tipped you off to remove something from a scene. That doesn't strike you as odd?"),
|
TapeSay(Dex, "A government office tipped you off to remove something from a scene. That doesn't strike you as odd?"),
|
||||||
|
|||||||
@@ -1,12 +1,8 @@
|
|||||||
package inc
|
package inc
|
||||||
|
|
||||||
import (
|
func init() {
|
||||||
inkwell "git.teletypegames.org/engines/inkwell"
|
CharacterManager.Register(Character{
|
||||||
)
|
|
||||||
|
|
||||||
func characterDex() inkwell.Character {
|
|
||||||
return inkwell.Character{
|
|
||||||
Name: Dex,
|
Name: Dex,
|
||||||
SpeechColor: Amber,
|
SpeechColor: Amber,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,13 +4,6 @@ import (
|
|||||||
inkwell "git.teletypegames.org/engines/inkwell"
|
inkwell "git.teletypegames.org/engines/inkwell"
|
||||||
)
|
)
|
||||||
|
|
||||||
func registerCharacter(w *World) {
|
type Character = inkwell.Character
|
||||||
for _, c := range []inkwell.Character{
|
|
||||||
characterPaul(),
|
var CharacterManager = NewManager(func(entity Character) string { return entity.Name })
|
||||||
characterDex(),
|
|
||||||
characterMysteryTape(),
|
|
||||||
characterSupportTape(),
|
|
||||||
} {
|
|
||||||
w.G.CharacterManager.Register(c)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,12 +1,8 @@
|
|||||||
package inc
|
package inc
|
||||||
|
|
||||||
import (
|
func init() {
|
||||||
inkwell "git.teletypegames.org/engines/inkwell"
|
CharacterManager.Register(Character{
|
||||||
)
|
|
||||||
|
|
||||||
func characterMysteryTape() inkwell.Character {
|
|
||||||
return inkwell.Character{
|
|
||||||
Name: TapeMystery,
|
Name: TapeMystery,
|
||||||
SpeechColor: RGB(0xB9A98A),
|
SpeechColor: RGB(0xB9A98A),
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ import (
|
|||||||
inkwell "git.teletypegames.org/engines/inkwell"
|
inkwell "git.teletypegames.org/engines/inkwell"
|
||||||
)
|
)
|
||||||
|
|
||||||
func characterPaul() inkwell.Character {
|
func init() {
|
||||||
return inkwell.Character{
|
CharacterManager.Register(Character{
|
||||||
Name: Paul,
|
Name: Paul,
|
||||||
Speed: 96,
|
Speed: 96,
|
||||||
W: 28,
|
W: 28,
|
||||||
@@ -15,5 +15,5 @@ func characterPaul() inkwell.Character {
|
|||||||
Y: 232,
|
Y: 232,
|
||||||
},
|
},
|
||||||
SpeechColor: Ink,
|
SpeechColor: Ink,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,8 @@
|
|||||||
package inc
|
package inc
|
||||||
|
|
||||||
import (
|
func init() {
|
||||||
inkwell "git.teletypegames.org/engines/inkwell"
|
CharacterManager.Register(Character{
|
||||||
)
|
|
||||||
|
|
||||||
func characterSupportTape() inkwell.Character {
|
|
||||||
return inkwell.Character{
|
|
||||||
Name: TapeSupport,
|
Name: TapeSupport,
|
||||||
SpeechColor: RGB(0xE8C86A),
|
SpeechColor: RGB(0xE8C86A),
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
package inc
|
package inc
|
||||||
|
|
||||||
func registerContent(w *World) {
|
func registerContent() {
|
||||||
registerBackground(w)
|
registerAll(BackgroundManager, World.G.AssetManager.Register)
|
||||||
registerCharacter(w)
|
registerAll(CharacterManager, World.G.CharacterManager.Register)
|
||||||
registerItem(w)
|
registerAll(ItemManager, World.G.ItemManager.Register)
|
||||||
registerDialog(w)
|
registerAll(DialogManager, World.G.DialogueManager.Register)
|
||||||
registerScript(w)
|
registerAll(ScriptManager, World.G.ScriptManager.Register)
|
||||||
registerScreen(w)
|
registerScreen()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ import (
|
|||||||
inkwell "git.teletypegames.org/engines/inkwell"
|
inkwell "git.teletypegames.org/engines/inkwell"
|
||||||
)
|
)
|
||||||
|
|
||||||
func dialogDexTalk() inkwell.Dialogue {
|
func init() {
|
||||||
return inkwell.Dialogue{
|
DialogManager.Register(Dialog{
|
||||||
Name: DlgDex,
|
Name: DlgDex,
|
||||||
Start: "root",
|
Start: "root",
|
||||||
Nodes: []inkwell.DialogueNode{{
|
Nodes: []inkwell.DialogueNode{{
|
||||||
@@ -52,5 +52,5 @@ func dialogDexTalk() inkwell.Dialogue {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
}},
|
}},
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,11 +4,6 @@ import (
|
|||||||
inkwell "git.teletypegames.org/engines/inkwell"
|
inkwell "git.teletypegames.org/engines/inkwell"
|
||||||
)
|
)
|
||||||
|
|
||||||
func registerDialog(w *World) {
|
type Dialog = inkwell.Dialogue
|
||||||
for _, d := range []inkwell.Dialogue{
|
|
||||||
dialogDexTalk(),
|
var DialogManager = NewManager(func(entity Dialog) string { return entity.Name })
|
||||||
dialogMysteryTapeSilent(),
|
|
||||||
} {
|
|
||||||
w.G.DialogueManager.Register(d)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ import (
|
|||||||
inkwell "git.teletypegames.org/engines/inkwell"
|
inkwell "git.teletypegames.org/engines/inkwell"
|
||||||
)
|
)
|
||||||
|
|
||||||
func dialogMysteryTapeSilent() inkwell.Dialogue {
|
func init() {
|
||||||
return inkwell.Dialogue{
|
DialogManager.Register(Dialog{
|
||||||
Name: DlgMysteryTape,
|
Name: DlgMysteryTape,
|
||||||
Start: "root",
|
Start: "root",
|
||||||
Nodes: []inkwell.DialogueNode{{
|
Nodes: []inkwell.DialogueNode{{
|
||||||
@@ -28,5 +28,5 @@ func dialogMysteryTapeSilent() inkwell.Dialogue {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
}},
|
}},
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ import (
|
|||||||
inkwell "git.teletypegames.org/engines/inkwell"
|
inkwell "git.teletypegames.org/engines/inkwell"
|
||||||
)
|
)
|
||||||
|
|
||||||
func itemBlackMarketArmilla() inkwell.Item {
|
func init() {
|
||||||
return inkwell.Item{
|
ItemManager.Register(Item{
|
||||||
Name: ItemBlackArmilla,
|
Name: ItemBlackArmilla,
|
||||||
Description: "black-market Armilla",
|
Description: "black-market Armilla",
|
||||||
OnUseSelf: inkwell.Seq(
|
OnUseSelf: inkwell.Seq(
|
||||||
@@ -18,5 +18,5 @@ func itemBlackMarketArmilla() inkwell.Item {
|
|||||||
TapeSay(Dex, "Nothing. Which is what I'd charge for it."),
|
TapeSay(Dex, "Nothing. Which is what I'd charge for it."),
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-9
@@ -4,12 +4,6 @@ import (
|
|||||||
inkwell "git.teletypegames.org/engines/inkwell"
|
inkwell "git.teletypegames.org/engines/inkwell"
|
||||||
)
|
)
|
||||||
|
|
||||||
func registerItem(w *World) {
|
type Item = inkwell.Item
|
||||||
for _, i := range []inkwell.Item{
|
|
||||||
itemNoodleLetter(),
|
var ItemManager = NewManager(func(entity Item) string { return entity.Name })
|
||||||
itemBlackMarketArmilla(),
|
|
||||||
itemMysteryTape(),
|
|
||||||
} {
|
|
||||||
w.G.ItemManager.Register(i)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -4,13 +4,13 @@ import (
|
|||||||
inkwell "git.teletypegames.org/engines/inkwell"
|
inkwell "git.teletypegames.org/engines/inkwell"
|
||||||
)
|
)
|
||||||
|
|
||||||
func itemMysteryTape() inkwell.Item {
|
func init() {
|
||||||
return inkwell.Item{
|
ItemManager.Register(Item{
|
||||||
Name: ItemMysteryTape,
|
Name: ItemMysteryTape,
|
||||||
Description: "unmarked Personal Tape",
|
Description: "unmarked Personal Tape",
|
||||||
OnUseSelf: inkwell.Seq(
|
OnUseSelf: inkwell.Seq(
|
||||||
inkwell.Say(Paul, "Password-locked. Of course."),
|
inkwell.Say(Paul, "Password-locked. Of course."),
|
||||||
TapeSay(Dex, "Put it in the second slot if you care that much. I did warn you."),
|
TapeSay(Dex, "Put it in the second slot if you care that much. I did warn you."),
|
||||||
),
|
),
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,13 +4,13 @@ import (
|
|||||||
inkwell "git.teletypegames.org/engines/inkwell"
|
inkwell "git.teletypegames.org/engines/inkwell"
|
||||||
)
|
)
|
||||||
|
|
||||||
func itemNoodleLetter() inkwell.Item {
|
func init() {
|
||||||
return inkwell.Item{
|
ItemManager.Register(Item{
|
||||||
Name: ItemNoodleLetter,
|
Name: ItemNoodleLetter,
|
||||||
Description: "Noodle's letter",
|
Description: "Noodle's letter",
|
||||||
OnUseSelf: inkwell.Seq(
|
OnUseSelf: inkwell.Seq(
|
||||||
inkwell.Say(Paul, "“Come out, Paul. Not a phone conversation.” That's all it says."),
|
inkwell.Say(Paul, "“Come out, Paul. Not a phone conversation.” That's all it says."),
|
||||||
TapeSay(Dex, "And now you're here. And he isn't."),
|
TapeSay(Dex, "And now you're here. And he isn't."),
|
||||||
),
|
),
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
package inc
|
||||||
|
|
||||||
|
type ManagerInterface[T any] interface {
|
||||||
|
Register(entity T)
|
||||||
|
GetByName(name string) (T, bool)
|
||||||
|
GetAll() []T
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
_ ManagerInterface[Background] = BackgroundManager
|
||||||
|
_ ManagerInterface[Character] = CharacterManager
|
||||||
|
_ ManagerInterface[Dialog] = DialogManager
|
||||||
|
_ ManagerInterface[Item] = ItemManager
|
||||||
|
_ ManagerInterface[Script] = ScriptManager
|
||||||
|
_ ManagerInterface[Screen] = ScreenManager
|
||||||
|
_ ManagerInterface[Theme] = ThemeManager
|
||||||
|
)
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
package inc
|
||||||
|
|
||||||
|
type Manager[T any] struct {
|
||||||
|
nameOf func(T) string
|
||||||
|
entities []T
|
||||||
|
index map[string]int
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewManager[T any](nameOf func(T) string) *Manager[T] {
|
||||||
|
return &Manager[T]{
|
||||||
|
nameOf: nameOf,
|
||||||
|
index: map[string]int{},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Manager[T]) Register(entity T) {
|
||||||
|
name := m.nameOf(entity)
|
||||||
|
if i, ok := m.index[name]; ok {
|
||||||
|
m.entities[i] = entity
|
||||||
|
return
|
||||||
|
}
|
||||||
|
m.index[name] = len(m.entities)
|
||||||
|
m.entities = append(m.entities, entity)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Manager[T]) GetByName(name string) (T, bool) {
|
||||||
|
i, ok := m.index[name]
|
||||||
|
if !ok {
|
||||||
|
var missing T
|
||||||
|
return missing, false
|
||||||
|
}
|
||||||
|
return m.entities[i], true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Manager[T]) GetAll() []T {
|
||||||
|
return m.entities
|
||||||
|
}
|
||||||
|
|
||||||
|
func registerAll[T any](m *Manager[T], register func(T)) {
|
||||||
|
for _, entity := range m.GetAll() {
|
||||||
|
register(entity)
|
||||||
|
}
|
||||||
|
}
|
||||||
+10
-10
@@ -4,19 +4,19 @@ import (
|
|||||||
inkwell "git.teletypegames.org/engines/inkwell"
|
inkwell "git.teletypegames.org/engines/inkwell"
|
||||||
)
|
)
|
||||||
|
|
||||||
func screenAlley() screen {
|
func init() {
|
||||||
return screen{
|
ScreenManager.Register(Screen{
|
||||||
name: ScreenAlley,
|
Name: ScreenAlley,
|
||||||
title: "ALLEY — BEHIND NOODLE'S HOUSE",
|
Title: "ALLEY — BEHIND NOODLE'S HOUSE",
|
||||||
background: BgAlley,
|
Background: BgAlley,
|
||||||
exits: []exit{
|
Exits: []exit{
|
||||||
{
|
{
|
||||||
to: ScreenNoodleHouse,
|
to: ScreenNoodleHouse,
|
||||||
label: "back out to the street",
|
label: "back out to the street",
|
||||||
side: sideLeft,
|
side: sideLeft,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
actors: []inkwell.SceneActor{
|
Actors: []inkwell.SceneActor{
|
||||||
{
|
{
|
||||||
CharacterName: Paul,
|
CharacterName: Paul,
|
||||||
At: inkwell.Point{
|
At: inkwell.Point{
|
||||||
@@ -25,9 +25,9 @@ func screenAlley() screen {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
onEnter: setVarIfEmpty(VarArmillaStrip, "SRP: 1 tape"),
|
OnEnter: setVarIfEmpty(VarArmillaStrip, "SRP: 1 tape"),
|
||||||
hotspots: []inkwell.Hotspot{hidingPlace(), backDoor(), bin(), fireEscape()},
|
Hotspots: []inkwell.Hotspot{hidingPlace(), backDoor(), bin(), fireEscape()},
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func hidingPlace() inkwell.Hotspot {
|
func hidingPlace() inkwell.Hotspot {
|
||||||
|
|||||||
@@ -1,15 +1,15 @@
|
|||||||
package inc
|
package inc
|
||||||
|
|
||||||
func screenBbsTerminal() screen {
|
func init() {
|
||||||
return screen{
|
ScreenManager.Register(Screen{
|
||||||
name: ScreenBBSTerminal,
|
Name: ScreenBBSTerminal,
|
||||||
title: "TERMINAL — BBS ACCESS POINT",
|
Title: "TERMINAL — BBS ACCESS POINT",
|
||||||
background: BgBBSTerminal,
|
Background: BgBBSTerminal,
|
||||||
exits: []exit{
|
Exits: []exit{
|
||||||
{
|
{
|
||||||
label: "step back from the terminal",
|
label: "step back from the terminal",
|
||||||
side: sideNear,
|
side: sideNear,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
package inc
|
package inc
|
||||||
|
|
||||||
func screenBvkBranch() screen {
|
func init() {
|
||||||
return screen{
|
ScreenManager.Register(Screen{
|
||||||
name: ScreenBVKBranch,
|
Name: ScreenBVKBranch,
|
||||||
title: "BVK — SAN FRANCISCO BRANCH",
|
Title: "BVK — SAN FRANCISCO BRANCH",
|
||||||
background: BgBVKBranch,
|
Background: BgBVKBranch,
|
||||||
onSelector: true,
|
OnSelector: true,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
package inc
|
package inc
|
||||||
|
|
||||||
func screenColumbarium() screen {
|
func init() {
|
||||||
return screen{
|
ScreenManager.Register(Screen{
|
||||||
name: ScreenColumbarium,
|
Name: ScreenColumbarium,
|
||||||
title: "COLUMBARIUM — DEX'S MEMORIAL",
|
Title: "COLUMBARIUM — DEX'S MEMORIAL",
|
||||||
background: BgColumbarium,
|
Background: BgColumbarium,
|
||||||
onSelector: true,
|
OnSelector: true,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
package inc
|
package inc
|
||||||
|
|
||||||
func screenCuratorShop() screen {
|
func init() {
|
||||||
return screen{
|
ScreenManager.Register(Screen{
|
||||||
name: ScreenCuratorShop,
|
Name: ScreenCuratorShop,
|
||||||
title: "CURATOR SERVICE — THE MASTER'S WORKSHOP",
|
Title: "CURATOR SERVICE — THE MASTER'S WORKSHOP",
|
||||||
background: BgCuratorShop,
|
Background: BgCuratorShop,
|
||||||
onSelector: true,
|
OnSelector: true,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -52,10 +52,10 @@ func exitName(to string) string {
|
|||||||
return "exit:" + to
|
return "exit:" + to
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e exit) hotspot(w *World) inkwell.Hotspot {
|
func (e exit) hotspot() inkwell.Hotspot {
|
||||||
var travel inkwell.Action = inkwell.GoTo(e.to)
|
var travel inkwell.Action = inkwell.GoTo(e.to)
|
||||||
if e.to == "" {
|
if e.to == "" {
|
||||||
travel = Back(w)
|
travel = Back()
|
||||||
}
|
}
|
||||||
if e.needs != "" {
|
if e.needs != "" {
|
||||||
travel = inkwell.If(inkwell.Flag(e.needs), travel, inkwell.Say(Paul, e.blocked))
|
travel = inkwell.If(inkwell.Flag(e.needs), travel, inkwell.Say(Paul, e.blocked))
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
package inc
|
package inc
|
||||||
|
|
||||||
func screenHackerspace() screen {
|
func init() {
|
||||||
return screen{
|
ScreenManager.Register(Screen{
|
||||||
name: ScreenHackerspace,
|
Name: ScreenHackerspace,
|
||||||
title: "HACKERSPACE",
|
Title: "HACKERSPACE",
|
||||||
background: BgHackerspace,
|
Background: BgHackerspace,
|
||||||
onSelector: true,
|
OnSelector: true,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
package inc
|
package inc
|
||||||
|
|
||||||
func screenHospital() screen {
|
func init() {
|
||||||
return screen{
|
ScreenManager.Register(Screen{
|
||||||
name: ScreenHospital,
|
Name: ScreenHospital,
|
||||||
title: "HOSPITAL — PSYCHIATRIC WING",
|
Title: "HOSPITAL — PSYCHIATRIC WING",
|
||||||
background: BgHospital,
|
Background: BgHospital,
|
||||||
onSelector: true,
|
OnSelector: true,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
package inc
|
package inc
|
||||||
|
|
||||||
func screenIceCreamShop() screen {
|
func init() {
|
||||||
return screen{
|
ScreenManager.Register(Screen{
|
||||||
name: ScreenIceCreamShop,
|
Name: ScreenIceCreamShop,
|
||||||
title: "ICE CREAM SHOP — WHERE THE BAR WAS",
|
Title: "ICE CREAM SHOP — WHERE THE BAR WAS",
|
||||||
background: BgIceCreamShop,
|
Background: BgIceCreamShop,
|
||||||
onSelector: true,
|
OnSelector: true,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
+30
-57
@@ -4,55 +4,28 @@ import (
|
|||||||
inkwell "git.teletypegames.org/engines/inkwell"
|
inkwell "git.teletypegames.org/engines/inkwell"
|
||||||
)
|
)
|
||||||
|
|
||||||
type screen struct {
|
type Screen struct {
|
||||||
name string
|
Name string
|
||||||
title string
|
Title string
|
||||||
background string
|
Background string
|
||||||
|
|
||||||
exits []exit
|
Exits []exit
|
||||||
|
|
||||||
onSelector bool
|
OnSelector bool
|
||||||
|
|
||||||
hotspots []inkwell.Hotspot
|
Hotspots []inkwell.Hotspot
|
||||||
actors []inkwell.SceneActor
|
Actors []inkwell.SceneActor
|
||||||
walkboxes []inkwell.Polygon
|
Walkboxes []inkwell.Polygon
|
||||||
onEnter inkwell.Action
|
OnEnter inkwell.Action
|
||||||
}
|
}
|
||||||
|
|
||||||
var screenDeck = []func() screen{
|
var ScreenManager = NewManager(func(entity Screen) string { return entity.Name })
|
||||||
screenPaulShop,
|
|
||||||
screenNoodleHouse,
|
|
||||||
screenAlley,
|
|
||||||
screenNormanApartment,
|
|
||||||
screenPoliceStation,
|
|
||||||
screenHackerspace,
|
|
||||||
screenIceCreamShop,
|
|
||||||
screenTrinketShop,
|
|
||||||
screenSmallRestaurant,
|
|
||||||
screenSecretClub,
|
|
||||||
screenBbsTerminal,
|
|
||||||
screenStreet,
|
|
||||||
screenHospital,
|
|
||||||
screenServerFarm,
|
|
||||||
screenSecretLab,
|
|
||||||
screenRooftopHideout,
|
|
||||||
screenPublicBBS,
|
|
||||||
screenBvkBranch,
|
|
||||||
screenCuratorShop,
|
|
||||||
screenScrapMarket,
|
|
||||||
screenSamizdatPress,
|
|
||||||
screenShowroom,
|
|
||||||
screenColumbarium,
|
|
||||||
}
|
|
||||||
|
|
||||||
func registerScreen(w *World) {
|
func registerScreen() {
|
||||||
screens := make([]screen, 0, len(screenDeck)+1)
|
fillSelectorPins()
|
||||||
for _, f := range screenDeck {
|
registerAll(ScreenManager, func(entity Screen) {
|
||||||
screens = append(screens, f())
|
World.G.SceneManager.Register(screenBuild(entity))
|
||||||
}
|
})
|
||||||
for _, s := range append([]screen{screenSelector(screens)}, screens...) {
|
|
||||||
w.G.SceneManager.Register(screenBuild(w, s))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var screenFloor = []inkwell.Polygon{
|
var screenFloor = []inkwell.Polygon{
|
||||||
@@ -74,18 +47,18 @@ var screenFloor = []inkwell.Polygon{
|
|||||||
),
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
func screenBuild(w *World, s screen) inkwell.Scene {
|
func screenBuild(s Screen) inkwell.Scene {
|
||||||
exits := s.exits
|
exits := s.Exits
|
||||||
if s.onSelector {
|
if s.OnSelector {
|
||||||
exits = append(exits, toSelector())
|
exits = append(exits, toSelector())
|
||||||
}
|
}
|
||||||
hotspots := make([]inkwell.Hotspot, 0, len(exits)+len(s.hotspots))
|
hotspots := make([]inkwell.Hotspot, 0, len(exits)+len(s.Hotspots))
|
||||||
hotspots = append(hotspots, s.hotspots...)
|
hotspots = append(hotspots, s.Hotspots...)
|
||||||
for _, e := range exits {
|
for _, e := range exits {
|
||||||
hotspots = append(hotspots, e.hotspot(w))
|
hotspots = append(hotspots, e.hotspot())
|
||||||
}
|
}
|
||||||
|
|
||||||
actors := s.actors
|
actors := s.Actors
|
||||||
if actors == nil {
|
if actors == nil {
|
||||||
actors = []inkwell.SceneActor{
|
actors = []inkwell.SceneActor{
|
||||||
{
|
{
|
||||||
@@ -97,19 +70,19 @@ func screenBuild(w *World, s screen) inkwell.Scene {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
walkboxes := s.walkboxes
|
walkboxes := s.Walkboxes
|
||||||
if walkboxes == nil {
|
if walkboxes == nil {
|
||||||
walkboxes = screenFloor
|
walkboxes = screenFloor
|
||||||
}
|
}
|
||||||
onEnter := inkwell.Action(EnterScene(w, s.name))
|
onEnter := inkwell.Action(EnterScene(s.Name))
|
||||||
if s.onEnter != nil {
|
if s.OnEnter != nil {
|
||||||
onEnter = inkwell.Seq(onEnter, s.onEnter)
|
onEnter = inkwell.Seq(onEnter, s.OnEnter)
|
||||||
}
|
}
|
||||||
|
|
||||||
return inkwell.Scene{
|
return inkwell.Scene{
|
||||||
Name: s.name,
|
Name: s.Name,
|
||||||
Title: s.title,
|
Title: s.Title,
|
||||||
Background: s.background,
|
Background: s.Background,
|
||||||
Actors: actors,
|
Actors: actors,
|
||||||
Walkboxes: walkboxes,
|
Walkboxes: walkboxes,
|
||||||
Hotspots: hotspots,
|
Hotspots: hotspots,
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
package inc
|
package inc
|
||||||
|
|
||||||
func screenNoodleHouse() screen {
|
func init() {
|
||||||
return screen{
|
ScreenManager.Register(Screen{
|
||||||
name: ScreenNoodleHouse,
|
Name: ScreenNoodleHouse,
|
||||||
title: "NOODLE'S HOUSE — SEALED",
|
Title: "NOODLE'S HOUSE — SEALED",
|
||||||
background: BgNoodleHouse,
|
Background: BgNoodleHouse,
|
||||||
onSelector: true,
|
OnSelector: true,
|
||||||
exits: []exit{
|
Exits: []exit{
|
||||||
{
|
{
|
||||||
to: ScreenAlley,
|
to: ScreenAlley,
|
||||||
label: "the alley behind the house",
|
label: "the alley behind the house",
|
||||||
side: sideRight,
|
side: sideRight,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
package inc
|
package inc
|
||||||
|
|
||||||
func screenNormanApartment() screen {
|
func init() {
|
||||||
return screen{
|
ScreenManager.Register(Screen{
|
||||||
name: ScreenNormanApartment,
|
Name: ScreenNormanApartment,
|
||||||
title: "NORMAN'S APARTMENT",
|
Title: "NORMAN'S APARTMENT",
|
||||||
background: BgNormanApartment,
|
Background: BgNormanApartment,
|
||||||
onSelector: true,
|
OnSelector: true,
|
||||||
exits: []exit{
|
Exits: []exit{
|
||||||
{
|
{
|
||||||
to: ScreenRooftopHideout,
|
to: ScreenRooftopHideout,
|
||||||
label: "the stairs up to the roof",
|
label: "the stairs up to the roof",
|
||||||
@@ -18,5 +18,5 @@ func screenNormanApartment() screen {
|
|||||||
side: sideRight,
|
side: sideRight,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,16 +1,16 @@
|
|||||||
package inc
|
package inc
|
||||||
|
|
||||||
func screenPaulShop() screen {
|
func init() {
|
||||||
return screen{
|
ScreenManager.Register(Screen{
|
||||||
name: ScreenPaulShop,
|
Name: ScreenPaulShop,
|
||||||
title: "PAUL'S SHOP — JUNK AND GARAGE",
|
Title: "PAUL'S SHOP — JUNK AND GARAGE",
|
||||||
background: BgPaulShop,
|
Background: BgPaulShop,
|
||||||
exits: []exit{
|
Exits: []exit{
|
||||||
{
|
{
|
||||||
to: ScreenNoodleHouse,
|
to: ScreenNoodleHouse,
|
||||||
label: "the bus to San Francisco",
|
label: "the bus to San Francisco",
|
||||||
side: sideNear,
|
side: sideNear,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
package inc
|
package inc
|
||||||
|
|
||||||
func screenPoliceStation() screen {
|
func init() {
|
||||||
return screen{
|
ScreenManager.Register(Screen{
|
||||||
name: ScreenPoliceStation,
|
Name: ScreenPoliceStation,
|
||||||
title: "SFPD — STATION AND HOLDING",
|
Title: "SFPD — STATION AND HOLDING",
|
||||||
background: BgPoliceStation,
|
Background: BgPoliceStation,
|
||||||
onSelector: true,
|
OnSelector: true,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
package inc
|
package inc
|
||||||
|
|
||||||
func screenPublicBBS() screen {
|
func init() {
|
||||||
return screen{
|
ScreenManager.Register(Screen{
|
||||||
name: ScreenPublicBBS,
|
Name: ScreenPublicBBS,
|
||||||
title: "PUBLIC BBS TERMINAL",
|
Title: "PUBLIC BBS TERMINAL",
|
||||||
background: BgPublicBBS,
|
Background: BgPublicBBS,
|
||||||
onSelector: true,
|
OnSelector: true,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
package inc
|
package inc
|
||||||
|
|
||||||
func screenRooftopHideout() screen {
|
func init() {
|
||||||
return screen{
|
ScreenManager.Register(Screen{
|
||||||
name: ScreenRooftopHideout,
|
Name: ScreenRooftopHideout,
|
||||||
title: "NORMAN'S ROOFTOP HIDEOUT",
|
Title: "NORMAN'S ROOFTOP HIDEOUT",
|
||||||
background: BgRooftopHideout,
|
Background: BgRooftopHideout,
|
||||||
exits: []exit{
|
Exits: []exit{
|
||||||
{
|
{
|
||||||
to: ScreenNormanApartment,
|
to: ScreenNormanApartment,
|
||||||
label: "back down into the flat",
|
label: "back down into the flat",
|
||||||
@@ -17,5 +17,5 @@ func screenRooftopHideout() screen {
|
|||||||
side: sideRight,
|
side: sideRight,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
package inc
|
package inc
|
||||||
|
|
||||||
func screenSamizdatPress() screen {
|
func init() {
|
||||||
return screen{
|
ScreenManager.Register(Screen{
|
||||||
name: ScreenSamizdatPress,
|
Name: ScreenSamizdatPress,
|
||||||
title: "SAMIZDAT PRINTING HOUSE",
|
Title: "SAMIZDAT PRINTING HOUSE",
|
||||||
background: BgSamizdatPress,
|
Background: BgSamizdatPress,
|
||||||
onSelector: true,
|
OnSelector: true,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
package inc
|
package inc
|
||||||
|
|
||||||
func screenScrapMarket() screen {
|
func init() {
|
||||||
return screen{
|
ScreenManager.Register(Screen{
|
||||||
name: ScreenScrapMarket,
|
Name: ScreenScrapMarket,
|
||||||
title: "SCRAP MARKET",
|
Title: "SCRAP MARKET",
|
||||||
background: BgScrapMarket,
|
Background: BgScrapMarket,
|
||||||
onSelector: true,
|
OnSelector: true,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
package inc
|
package inc
|
||||||
|
|
||||||
func screenSecretClub() screen {
|
func init() {
|
||||||
return screen{
|
ScreenManager.Register(Screen{
|
||||||
name: ScreenSecretClub,
|
Name: ScreenSecretClub,
|
||||||
title: "SECRET CLUB — THE UNDERWATER SUN",
|
Title: "SECRET CLUB — THE UNDERWATER SUN",
|
||||||
background: BgSecretClub,
|
Background: BgSecretClub,
|
||||||
exits: []exit{
|
Exits: []exit{
|
||||||
{
|
{
|
||||||
to: ScreenBBSTerminal,
|
to: ScreenBBSTerminal,
|
||||||
label: "the terminal in the corner",
|
label: "the terminal in the corner",
|
||||||
@@ -17,5 +17,5 @@ func screenSecretClub() screen {
|
|||||||
side: sideNear,
|
side: sideNear,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
package inc
|
package inc
|
||||||
|
|
||||||
func screenSecretLab() screen {
|
func init() {
|
||||||
return screen{
|
ScreenManager.Register(Screen{
|
||||||
name: ScreenSecretLab,
|
Name: ScreenSecretLab,
|
||||||
title: "SECRET RESEARCH LABORATORY",
|
Title: "SECRET RESEARCH LABORATORY",
|
||||||
background: BgSecretLab,
|
Background: BgSecretLab,
|
||||||
onSelector: true,
|
OnSelector: true,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
+21
-13
@@ -6,26 +6,34 @@ import (
|
|||||||
inkwell "git.teletypegames.org/engines/inkwell"
|
inkwell "git.teletypegames.org/engines/inkwell"
|
||||||
)
|
)
|
||||||
|
|
||||||
func screenSelector(rest []screen) screen {
|
func init() {
|
||||||
|
ScreenManager.Register(Screen{
|
||||||
|
Name: ScreenSelector,
|
||||||
|
Title: "SAN FRANCISCO",
|
||||||
|
Background: BgSelector,
|
||||||
|
Actors: []inkwell.SceneActor{},
|
||||||
|
Walkboxes: []inkwell.Polygon{},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func fillSelectorPins() {
|
||||||
|
selector, ok := ScreenManager.GetByName(ScreenSelector)
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
var exits []exit
|
var exits []exit
|
||||||
for _, s := range rest {
|
for _, entity := range ScreenManager.GetAll() {
|
||||||
if !s.onSelector {
|
if !entity.OnSelector {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
exits = append(exits, exit{
|
exits = append(exits, exit{
|
||||||
to: s.name,
|
to: entity.Name,
|
||||||
label: pinLabel(s.title),
|
label: pinLabel(entity.Title),
|
||||||
area: pin(len(exits)),
|
area: pin(len(exits)),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
return screen{
|
selector.Exits = exits
|
||||||
name: ScreenSelector,
|
ScreenManager.Register(selector)
|
||||||
title: "SAN FRANCISCO",
|
|
||||||
background: BgSelector,
|
|
||||||
exits: exits,
|
|
||||||
actors: []inkwell.SceneActor{},
|
|
||||||
walkboxes: []inkwell.Polygon{},
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
package inc
|
package inc
|
||||||
|
|
||||||
func screenServerFarm() screen {
|
func init() {
|
||||||
return screen{
|
ScreenManager.Register(Screen{
|
||||||
name: ScreenServerFarm,
|
Name: ScreenServerFarm,
|
||||||
title: "SERVER FARM",
|
Title: "SERVER FARM",
|
||||||
background: BgServerFarm,
|
Background: BgServerFarm,
|
||||||
onSelector: true,
|
OnSelector: true,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
package inc
|
package inc
|
||||||
|
|
||||||
func screenShowroom() screen {
|
func init() {
|
||||||
return screen{
|
ScreenManager.Register(Screen{
|
||||||
name: ScreenShowroom,
|
Name: ScreenShowroom,
|
||||||
title: "NEUMATRONIC SHOWROOM",
|
Title: "NEUMATRONIC SHOWROOM",
|
||||||
background: BgShowroom,
|
Background: BgShowroom,
|
||||||
onSelector: true,
|
OnSelector: true,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,16 +1,16 @@
|
|||||||
package inc
|
package inc
|
||||||
|
|
||||||
func screenSmallRestaurant() screen {
|
func init() {
|
||||||
return screen{
|
ScreenManager.Register(Screen{
|
||||||
name: ScreenSmallRestaurant,
|
Name: ScreenSmallRestaurant,
|
||||||
title: "SMALL RESTAURANT — NEXT DOOR",
|
Title: "SMALL RESTAURANT — NEXT DOOR",
|
||||||
background: BgSmallRestaurant,
|
Background: BgSmallRestaurant,
|
||||||
exits: []exit{
|
Exits: []exit{
|
||||||
{
|
{
|
||||||
to: ScreenTrinketShop,
|
to: ScreenTrinketShop,
|
||||||
label: "back to the trinket shop",
|
label: "back to the trinket shop",
|
||||||
side: sideLeft,
|
side: sideLeft,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
package inc
|
package inc
|
||||||
|
|
||||||
func screenStreet() screen {
|
func init() {
|
||||||
return screen{
|
ScreenManager.Register(Screen{
|
||||||
name: ScreenStreet,
|
Name: ScreenStreet,
|
||||||
title: "STREET",
|
Title: "STREET",
|
||||||
background: BgStreet,
|
Background: BgStreet,
|
||||||
onSelector: true,
|
OnSelector: true,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
package inc
|
package inc
|
||||||
|
|
||||||
func screenTrinketShop() screen {
|
func init() {
|
||||||
return screen{
|
ScreenManager.Register(Screen{
|
||||||
name: ScreenTrinketShop,
|
Name: ScreenTrinketShop,
|
||||||
title: "CHINATOWN — TRINKET SHOP",
|
Title: "CHINATOWN — TRINKET SHOP",
|
||||||
background: BgTrinketShop,
|
Background: BgTrinketShop,
|
||||||
onSelector: true,
|
OnSelector: true,
|
||||||
exits: []exit{
|
Exits: []exit{
|
||||||
{
|
{
|
||||||
to: ScreenSmallRestaurant,
|
to: ScreenSmallRestaurant,
|
||||||
label: "the eating place next door",
|
label: "the eating place next door",
|
||||||
@@ -20,5 +20,5 @@ func screenTrinketShop() screen {
|
|||||||
blocked: "Just a shop, as far as the man behind the counter is concerned.",
|
blocked: "Just a shop, as far as the man behind the counter is concerned.",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,11 +4,11 @@ import (
|
|||||||
inkwell "git.teletypegames.org/engines/inkwell"
|
inkwell "git.teletypegames.org/engines/inkwell"
|
||||||
)
|
)
|
||||||
|
|
||||||
func scriptAwakeningFinale(w *World) inkwell.Script {
|
func init() {
|
||||||
return inkwell.Script{
|
ScriptManager.Register(Script{
|
||||||
Name: ScriptFinale,
|
Name: ScriptFinale,
|
||||||
Actions: inkwell.Seq(
|
Actions: inkwell.Seq(
|
||||||
SetMode(w, ModeCutscene),
|
SetMode(ModeCutscene),
|
||||||
inkwell.Wait(0.6),
|
inkwell.Wait(0.6),
|
||||||
inkwell.Say(Paul, "I'm putting it in. That's all this is."),
|
inkwell.Say(Paul, "I'm putting it in. That's all this is."),
|
||||||
inkwell.Wait(0.4),
|
inkwell.Wait(0.4),
|
||||||
@@ -19,5 +19,5 @@ func scriptAwakeningFinale(w *World) inkwell.Script {
|
|||||||
inkwell.Wait(1.0),
|
inkwell.Wait(1.0),
|
||||||
inkwell.ShowEnd("REAL WORLD — end of game two"),
|
inkwell.ShowEnd("REAL WORLD — end of game two"),
|
||||||
),
|
),
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,11 +4,6 @@ import (
|
|||||||
inkwell "git.teletypegames.org/engines/inkwell"
|
inkwell "git.teletypegames.org/engines/inkwell"
|
||||||
)
|
)
|
||||||
|
|
||||||
func registerScript(w *World) {
|
type Script = inkwell.Script
|
||||||
for _, s := range []inkwell.Script{
|
|
||||||
scriptTapeInsert(w),
|
var ScriptManager = NewManager(func(entity Script) string { return entity.Name })
|
||||||
scriptAwakeningFinale(w),
|
|
||||||
} {
|
|
||||||
w.G.ScriptManager.Register(s)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -4,16 +4,16 @@ import (
|
|||||||
inkwell "git.teletypegames.org/engines/inkwell"
|
inkwell "git.teletypegames.org/engines/inkwell"
|
||||||
)
|
)
|
||||||
|
|
||||||
func scriptTapeInsert(w *World) inkwell.Script {
|
func init() {
|
||||||
return inkwell.Script{
|
ScriptManager.Register(Script{
|
||||||
Name: ScriptTapeInsert,
|
Name: ScriptTapeInsert,
|
||||||
Actions: inkwell.Seq(
|
Actions: inkwell.Seq(
|
||||||
Fn(func(ctx *inkwell.Ctx) {
|
Fn(func(ctx *inkwell.Ctx) {
|
||||||
item := w.TakePending()
|
item := World.TakePending()
|
||||||
if item == "" {
|
if item == "" {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
w.SetSlot2(item)
|
World.SetSlot2(item)
|
||||||
ctx.Game.Inventory.Remove(item)
|
ctx.Game.Inventory.Remove(item)
|
||||||
ctx.Game.State.SetVar(VarArmillaStrip, "SLOT2: READING")
|
ctx.Game.State.SetVar(VarArmillaStrip, "SLOT2: READING")
|
||||||
}),
|
}),
|
||||||
@@ -21,5 +21,5 @@ func scriptTapeInsert(w *World) inkwell.Script {
|
|||||||
TapeSay(Dex, "Clicked in. Spinning. And now: nothing."),
|
TapeSay(Dex, "Clicked in. Spinning. And now: nothing."),
|
||||||
TapeSay(Dex, "A stranger's tape in your own Armilla, Paul. I hope you know what you're doing."),
|
TapeSay(Dex, "A stranger's tape in your own Armilla, Paul. I hope you know what you're doing."),
|
||||||
),
|
),
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
+6
-93
@@ -6,6 +6,10 @@ import (
|
|||||||
inkwell "git.teletypegames.org/engines/inkwell"
|
inkwell "git.teletypegames.org/engines/inkwell"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type Theme = inkwell.Theme
|
||||||
|
|
||||||
|
var ThemeManager = NewManager(func(entity Theme) string { return entity.Name })
|
||||||
|
|
||||||
const (
|
const (
|
||||||
RealWorld = "realworld-93"
|
RealWorld = "realworld-93"
|
||||||
NokiaPunk = "nokia-punk"
|
NokiaPunk = "nokia-punk"
|
||||||
@@ -29,97 +33,6 @@ func RGBA(hex uint32, a uint8) color.Color {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
func registerTheme() {
|
||||||
Ink = RGB(0xDCD5C4)
|
registerAll(ThemeManager, World.G.ThemeManager.Register)
|
||||||
InkDim = RGB(0x8A806B)
|
|
||||||
Amber = RGB(0xE0A33E)
|
|
||||||
AmberLo = RGB(0xA8701A)
|
|
||||||
black = RGB(0x14120E)
|
|
||||||
panel = RGB(0x0D0B08)
|
|
||||||
sceneBG = RGB(0x241F18)
|
|
||||||
)
|
|
||||||
|
|
||||||
func realWorldTheme() inkwell.Theme {
|
|
||||||
return inkwell.Theme{
|
|
||||||
Name: RealWorld,
|
|
||||||
PanelBG: black,
|
|
||||||
StatusText: Ink,
|
|
||||||
FlashText: Amber,
|
|
||||||
VerbButtonBG: RGB(0x1E1A14),
|
|
||||||
VerbButtonSelectedBG: AmberLo,
|
|
||||||
VerbButtonText: Ink,
|
|
||||||
InventorySlotBG: RGB(0x1E1A14),
|
|
||||||
InventorySlotSelectedBG: AmberLo,
|
|
||||||
SpeechBubbleBG: RGBA(0x14120E, 0xDC),
|
|
||||||
SpeechDefaultText: Ink,
|
|
||||||
DialogBG: RGBA(0x0D0B08, 0xF0),
|
|
||||||
DialogBorder: AmberLo,
|
|
||||||
DialogChoiceBG: RGB(0x1E1A14),
|
|
||||||
DialogChoiceHover: Amber,
|
|
||||||
DialogSpeaker: Amber,
|
|
||||||
DialogText: Ink,
|
|
||||||
EndCardBG: RGBA(0x000000, 0xFA),
|
|
||||||
EndCardText: Ink,
|
|
||||||
CursorColor: Amber,
|
|
||||||
HotspotOutline: RGB(0x7A6A44),
|
|
||||||
SceneBackdrop: sceneBG,
|
|
||||||
TopBarBG: panel,
|
|
||||||
TopBarText: InkDim,
|
|
||||||
TopBarAccent: Amber,
|
|
||||||
ChatLogBG: panel,
|
|
||||||
ChatLogPrompt: InkDim,
|
|
||||||
ChatLogResponse: Amber,
|
|
||||||
ChatLogSystem: RGB(0x6B6353),
|
|
||||||
CharacterPanelBG: panel,
|
|
||||||
CharacterPanelBorder: AmberLo,
|
|
||||||
CharacterPanelTitle: Amber,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
Green = RGB(0x3BE86B)
|
|
||||||
GreenLo = RGB(0x1F7A39)
|
|
||||||
npBlack = RGB(0x030603)
|
|
||||||
)
|
|
||||||
|
|
||||||
func nokiaPunkTheme() inkwell.Theme {
|
|
||||||
return inkwell.Theme{
|
|
||||||
Name: NokiaPunk,
|
|
||||||
PanelBG: npBlack,
|
|
||||||
StatusText: Green,
|
|
||||||
FlashText: RGB(0xD8F06A),
|
|
||||||
VerbButtonBG: RGB(0x08140A),
|
|
||||||
VerbButtonSelectedBG: GreenLo,
|
|
||||||
VerbButtonText: Green,
|
|
||||||
InventorySlotBG: RGB(0x08140A),
|
|
||||||
InventorySlotSelectedBG: GreenLo,
|
|
||||||
SpeechBubbleBG: RGBA(0x030603, 0xDC),
|
|
||||||
SpeechDefaultText: Green,
|
|
||||||
DialogBG: RGBA(0x030603, 0xF0),
|
|
||||||
DialogBorder: Green,
|
|
||||||
DialogChoiceBG: RGB(0x08140A),
|
|
||||||
DialogChoiceHover: RGB(0xB4FFC8),
|
|
||||||
DialogSpeaker: RGB(0xB4FFC8),
|
|
||||||
DialogText: Green,
|
|
||||||
EndCardBG: RGBA(0x000000, 0xFA),
|
|
||||||
EndCardText: Green,
|
|
||||||
CursorColor: Green,
|
|
||||||
HotspotOutline: GreenLo,
|
|
||||||
SceneBackdrop: npBlack,
|
|
||||||
TopBarBG: RGB(0x061006),
|
|
||||||
TopBarText: GreenLo,
|
|
||||||
TopBarAccent: Green,
|
|
||||||
ChatLogBG: RGB(0x040A04),
|
|
||||||
ChatLogPrompt: GreenLo,
|
|
||||||
ChatLogResponse: Green,
|
|
||||||
ChatLogSystem: RGB(0x156030),
|
|
||||||
CharacterPanelBG: RGB(0x040A04),
|
|
||||||
CharacterPanelBorder: Green,
|
|
||||||
CharacterPanelTitle: RGB(0xB4FFC8),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func registerTheme(g *inkwell.Game) {
|
|
||||||
g.ThemeManager.Register(realWorldTheme())
|
|
||||||
g.ThemeManager.Register(nokiaPunkTheme())
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,44 @@
|
|||||||
|
package inc
|
||||||
|
|
||||||
|
var (
|
||||||
|
Green = RGB(0x3BE86B)
|
||||||
|
GreenLo = RGB(0x1F7A39)
|
||||||
|
npBlack = RGB(0x030603)
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
ThemeManager.Register(Theme{
|
||||||
|
Name: NokiaPunk,
|
||||||
|
PanelBG: npBlack,
|
||||||
|
StatusText: Green,
|
||||||
|
FlashText: RGB(0xD8F06A),
|
||||||
|
VerbButtonBG: RGB(0x08140A),
|
||||||
|
VerbButtonSelectedBG: GreenLo,
|
||||||
|
VerbButtonText: Green,
|
||||||
|
InventorySlotBG: RGB(0x08140A),
|
||||||
|
InventorySlotSelectedBG: GreenLo,
|
||||||
|
SpeechBubbleBG: RGBA(0x030603, 0xDC),
|
||||||
|
SpeechDefaultText: Green,
|
||||||
|
DialogBG: RGBA(0x030603, 0xF0),
|
||||||
|
DialogBorder: Green,
|
||||||
|
DialogChoiceBG: RGB(0x08140A),
|
||||||
|
DialogChoiceHover: RGB(0xB4FFC8),
|
||||||
|
DialogSpeaker: RGB(0xB4FFC8),
|
||||||
|
DialogText: Green,
|
||||||
|
EndCardBG: RGBA(0x000000, 0xFA),
|
||||||
|
EndCardText: Green,
|
||||||
|
CursorColor: Green,
|
||||||
|
HotspotOutline: GreenLo,
|
||||||
|
SceneBackdrop: npBlack,
|
||||||
|
TopBarBG: RGB(0x061006),
|
||||||
|
TopBarText: GreenLo,
|
||||||
|
TopBarAccent: Green,
|
||||||
|
ChatLogBG: RGB(0x040A04),
|
||||||
|
ChatLogPrompt: GreenLo,
|
||||||
|
ChatLogResponse: Green,
|
||||||
|
ChatLogSystem: RGB(0x156030),
|
||||||
|
CharacterPanelBG: RGB(0x040A04),
|
||||||
|
CharacterPanelBorder: Green,
|
||||||
|
CharacterPanelTitle: RGB(0xB4FFC8),
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
package inc
|
||||||
|
|
||||||
|
var (
|
||||||
|
Ink = RGB(0xDCD5C4)
|
||||||
|
InkDim = RGB(0x8A806B)
|
||||||
|
Amber = RGB(0xE0A33E)
|
||||||
|
AmberLo = RGB(0xA8701A)
|
||||||
|
black = RGB(0x14120E)
|
||||||
|
panel = RGB(0x0D0B08)
|
||||||
|
sceneBG = RGB(0x241F18)
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
ThemeManager.Register(Theme{
|
||||||
|
Name: RealWorld,
|
||||||
|
PanelBG: black,
|
||||||
|
StatusText: Ink,
|
||||||
|
FlashText: Amber,
|
||||||
|
VerbButtonBG: RGB(0x1E1A14),
|
||||||
|
VerbButtonSelectedBG: AmberLo,
|
||||||
|
VerbButtonText: Ink,
|
||||||
|
InventorySlotBG: RGB(0x1E1A14),
|
||||||
|
InventorySlotSelectedBG: AmberLo,
|
||||||
|
SpeechBubbleBG: RGBA(0x14120E, 0xDC),
|
||||||
|
SpeechDefaultText: Ink,
|
||||||
|
DialogBG: RGBA(0x0D0B08, 0xF0),
|
||||||
|
DialogBorder: AmberLo,
|
||||||
|
DialogChoiceBG: RGB(0x1E1A14),
|
||||||
|
DialogChoiceHover: Amber,
|
||||||
|
DialogSpeaker: Amber,
|
||||||
|
DialogText: Ink,
|
||||||
|
EndCardBG: RGBA(0x000000, 0xFA),
|
||||||
|
EndCardText: Ink,
|
||||||
|
CursorColor: Amber,
|
||||||
|
HotspotOutline: RGB(0x7A6A44),
|
||||||
|
SceneBackdrop: sceneBG,
|
||||||
|
TopBarBG: panel,
|
||||||
|
TopBarText: InkDim,
|
||||||
|
TopBarAccent: Amber,
|
||||||
|
ChatLogBG: panel,
|
||||||
|
ChatLogPrompt: InkDim,
|
||||||
|
ChatLogResponse: Amber,
|
||||||
|
ChatLogSystem: RGB(0x6B6353),
|
||||||
|
CharacterPanelBG: panel,
|
||||||
|
CharacterPanelBorder: AmberLo,
|
||||||
|
CharacterPanelTitle: Amber,
|
||||||
|
})
|
||||||
|
}
|
||||||
+8
-9
@@ -7,26 +7,25 @@ import (
|
|||||||
"github.com/hajimehoshi/ebiten/v2/vector"
|
"github.com/hajimehoshi/ebiten/v2/vector"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Letterbox struct {
|
type letterbox struct {
|
||||||
Name string
|
Name string
|
||||||
W *World
|
|
||||||
Bar float64
|
Bar float64
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *Letterbox) GetName() string { return l.Name }
|
func (l *letterbox) GetName() string { return l.Name }
|
||||||
|
|
||||||
func (l *Letterbox) Tick(ctx *inkwell.UICtx) {
|
func (l *letterbox) Tick(ctx *inkwell.UICtx) {
|
||||||
if l.W.Mode() != ModeCutscene || !l.W.TapeWaiting() {
|
if World.Mode() != ModeCutscene || !World.TapeWaiting() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if inpututil.IsKeyJustPressed(ebiten.KeySpace) {
|
if inpututil.IsKeyJustPressed(ebiten.KeySpace) {
|
||||||
l.W.TakeTapeOffer()
|
World.TakeTapeOffer()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *Letterbox) Draw(dst *ebiten.Image, ctx *inkwell.UICtx) {
|
func (l *letterbox) Draw(dst *ebiten.Image, ctx *inkwell.UICtx) {
|
||||||
if l.W.Mode() != ModeCutscene {
|
if World.Mode() != ModeCutscene {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
g := ctx.Game
|
g := ctx.Game
|
||||||
@@ -40,7 +39,7 @@ func (l *Letterbox) Draw(dst *ebiten.Image, ctx *inkwell.UICtx) {
|
|||||||
vector.DrawFilledRect(dst, 0, 0, w, float32(bar), black, false)
|
vector.DrawFilledRect(dst, 0, 0, w, float32(bar), black, false)
|
||||||
vector.DrawFilledRect(dst, 0, h-float32(bar), w, float32(bar), black, false)
|
vector.DrawFilledRect(dst, 0, h-float32(bar), w, float32(bar), black, false)
|
||||||
|
|
||||||
if l.W.TapeWaiting() {
|
if World.TapeWaiting() {
|
||||||
msg := "SPACE — " + TapeDisplayName(Dex) + " has something to say"
|
msg := "SPACE — " + TapeDisplayName(Dex) + " has something to say"
|
||||||
drawTextC(dst, msg, g.Width-textW(msg)-4, g.Height-int(bar)+4, th.ChatLogResponse)
|
drawTextC(dst, msg, g.Width-textW(msg)-4, g.Height-int(bar)+4, th.ChatLogResponse)
|
||||||
}
|
}
|
||||||
|
|||||||
+17
-27
@@ -27,20 +27,17 @@ const (
|
|||||||
invGap = 4
|
invGap = 4
|
||||||
)
|
)
|
||||||
|
|
||||||
func registerUI(w *World) {
|
func registerUI() {
|
||||||
g := w.G
|
g := World.G
|
||||||
|
|
||||||
g.UIManager.Register(&UseWithGuard{
|
g.UIManager.Register(&useWithGuard{
|
||||||
Name: "usewith_guard",
|
Name: "usewith_guard",
|
||||||
W: w,
|
|
||||||
})
|
})
|
||||||
g.UIManager.Register(&ActionPump{
|
g.UIManager.Register(&actionPump{
|
||||||
Name: "pump",
|
Name: "pump",
|
||||||
W: w,
|
|
||||||
})
|
})
|
||||||
g.UIManager.Register(&screenNav{
|
g.UIManager.Register(&screenNav{
|
||||||
Name: "screen_nav",
|
Name: "screen_nav",
|
||||||
W: w,
|
|
||||||
})
|
})
|
||||||
g.UIManager.Register(&windowSizer{
|
g.UIManager.Register(&windowSizer{
|
||||||
Name: "window",
|
Name: "window",
|
||||||
@@ -55,26 +52,24 @@ func registerUI(w *World) {
|
|||||||
Height: TopBarH,
|
Height: TopBarH,
|
||||||
TimeVar: VarArmillaStrip,
|
TimeVar: VarArmillaStrip,
|
||||||
}
|
}
|
||||||
w.SetTopBar(top)
|
World.SetTopBar(top)
|
||||||
g.UIManager.Register(gated(w, "topbar_gate", top))
|
g.UIManager.Register(gated("topbar_gate", top))
|
||||||
|
|
||||||
g.UIManager.Register(&Letterbox{
|
g.UIManager.Register(&letterbox{
|
||||||
Name: "letterbox",
|
Name: "letterbox",
|
||||||
W: w,
|
|
||||||
Bar: 36,
|
Bar: 36,
|
||||||
})
|
})
|
||||||
g.UIManager.Register(&hudFrame{
|
g.UIManager.Register(&hudFrame{
|
||||||
Name: "hudframe",
|
Name: "hudframe",
|
||||||
W: w,
|
|
||||||
})
|
})
|
||||||
|
|
||||||
g.UIManager.Register(gated(w, "status_gate", &inkwell.StatusLine{
|
g.UIManager.Register(gated("status_gate", &inkwell.StatusLine{
|
||||||
Name: "status",
|
Name: "status",
|
||||||
Y: statusY,
|
Y: statusY,
|
||||||
Align: inkwell.AlignLeft,
|
Align: inkwell.AlignLeft,
|
||||||
ScreenWidth: DividerX,
|
ScreenWidth: DividerX,
|
||||||
}))
|
}))
|
||||||
g.UIManager.Register(gated(w, "inventory_gate", &inkwell.InventoryBar{
|
g.UIManager.Register(gated("inventory_gate", &inkwell.InventoryBar{
|
||||||
Name: "inventory",
|
Name: "inventory",
|
||||||
Origin: inkwell.Point{
|
Origin: inkwell.Point{
|
||||||
X: Pad + 2,
|
X: Pad + 2,
|
||||||
@@ -85,14 +80,12 @@ func registerUI(w *World) {
|
|||||||
SlotSize: invSlot,
|
SlotSize: invSlot,
|
||||||
Gap: invGap,
|
Gap: invGap,
|
||||||
}))
|
}))
|
||||||
g.UIManager.Register(&TapeSlots{
|
g.UIManager.Register(&tapeSlots{
|
||||||
Name: "tapes",
|
Name: "tapes",
|
||||||
W: w,
|
|
||||||
Bounds: inkwell.Rect(192, slotsY, 194, slotsH),
|
Bounds: inkwell.Rect(192, slotsY, 194, slotsH),
|
||||||
})
|
})
|
||||||
g.UIManager.Register(&TapeChannel{
|
g.UIManager.Register(&tapeChannel{
|
||||||
Name: "channel",
|
Name: "channel",
|
||||||
W: w,
|
|
||||||
Bounds: inkwell.Rect(DividerX+2, HUDTop+2, ScreenW-DividerX-4, ScreenH-HUDTop-4),
|
Bounds: inkwell.Rect(DividerX+2, HUDTop+2, ScreenW-DividerX-4, ScreenH-HUDTop-4),
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -150,14 +143,12 @@ func (s *windowSizer) Tick(ctx *inkwell.UICtx) {
|
|||||||
|
|
||||||
type gate struct {
|
type gate struct {
|
||||||
Name string
|
Name string
|
||||||
W *World
|
|
||||||
Inner inkwell.Widget
|
Inner inkwell.Widget
|
||||||
}
|
}
|
||||||
|
|
||||||
func gated(w *World, name string, inner inkwell.Widget) inkwell.Widget {
|
func gated(name string, inner inkwell.Widget) inkwell.Widget {
|
||||||
return &gate{
|
return &gate{
|
||||||
Name: name,
|
Name: name,
|
||||||
W: w,
|
|
||||||
Inner: inner,
|
Inner: inner,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -165,19 +156,19 @@ func gated(w *World, name string, inner inkwell.Widget) inkwell.Widget {
|
|||||||
func (n *gate) GetName() string { return n.Name }
|
func (n *gate) GetName() string { return n.Name }
|
||||||
|
|
||||||
func (n *gate) Tick(ctx *inkwell.UICtx) {
|
func (n *gate) Tick(ctx *inkwell.UICtx) {
|
||||||
if n.W.HUDVisible() {
|
if World.HUDVisible() {
|
||||||
n.Inner.Tick(ctx)
|
n.Inner.Tick(ctx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *gate) Draw(dst *ebiten.Image, ctx *inkwell.UICtx) {
|
func (n *gate) Draw(dst *ebiten.Image, ctx *inkwell.UICtx) {
|
||||||
if n.W.HUDVisible() {
|
if World.HUDVisible() {
|
||||||
n.Inner.Draw(dst, ctx)
|
n.Inner.Draw(dst, ctx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *gate) BlocksClickAt(p inkwell.Point) bool {
|
func (n *gate) BlocksClickAt(p inkwell.Point) bool {
|
||||||
if !n.W.HUDVisible() {
|
if !World.HUDVisible() {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
b, ok := n.Inner.(interface{ BlocksClickAt(inkwell.Point) bool })
|
b, ok := n.Inner.(interface{ BlocksClickAt(inkwell.Point) bool })
|
||||||
@@ -186,14 +177,13 @@ func (n *gate) BlocksClickAt(p inkwell.Point) bool {
|
|||||||
|
|
||||||
type hudFrame struct {
|
type hudFrame struct {
|
||||||
Name string
|
Name string
|
||||||
W *World
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *hudFrame) GetName() string { return h.Name }
|
func (h *hudFrame) GetName() string { return h.Name }
|
||||||
func (h *hudFrame) Tick(ctx *inkwell.UICtx) {}
|
func (h *hudFrame) Tick(ctx *inkwell.UICtx) {}
|
||||||
|
|
||||||
func (h *hudFrame) Draw(dst *ebiten.Image, ctx *inkwell.UICtx) {
|
func (h *hudFrame) Draw(dst *ebiten.Image, ctx *inkwell.UICtx) {
|
||||||
if !h.W.HUDVisible() {
|
if !World.HUDVisible() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
th := ctx.Game.Theme()
|
th := ctx.Game.Theme()
|
||||||
@@ -205,5 +195,5 @@ func (h *hudFrame) Draw(dst *ebiten.Image, ctx *inkwell.UICtx) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (h *hudFrame) BlocksClickAt(p inkwell.Point) bool {
|
func (h *hudFrame) BlocksClickAt(p inkwell.Point) bool {
|
||||||
return h.W.HUDVisible() && p.Y >= HUDTop
|
return World.HUDVisible() && p.Y >= HUDTop
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,14 +8,13 @@ import (
|
|||||||
|
|
||||||
type screenNav struct {
|
type screenNav struct {
|
||||||
Name string
|
Name string
|
||||||
W *World
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *screenNav) GetName() string { return n.Name }
|
func (n *screenNav) GetName() string { return n.Name }
|
||||||
func (n *screenNav) Draw(dst *ebiten.Image, ctx *inkwell.UICtx) {}
|
func (n *screenNav) Draw(dst *ebiten.Image, ctx *inkwell.UICtx) {}
|
||||||
|
|
||||||
func (n *screenNav) Tick(ctx *inkwell.UICtx) {
|
func (n *screenNav) Tick(ctx *inkwell.UICtx) {
|
||||||
if !n.W.HUDVisible() || n.W.Paused() {
|
if !World.HUDVisible() || World.Paused() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
step := 0
|
step := 0
|
||||||
@@ -29,7 +28,7 @@ func (n *screenNav) Tick(ctx *inkwell.UICtx) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
if next := n.neighbour(ctx.Game, step); next != "" {
|
if next := n.neighbour(ctx.Game, step); next != "" {
|
||||||
n.W.Do(inkwell.GoTo(next))
|
World.Do(inkwell.GoTo(next))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -39,7 +38,7 @@ func (n *screenNav) neighbour(g *inkwell.Game, step int) string {
|
|||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
for i, name := range deck {
|
for i, name := range deck {
|
||||||
if name == n.W.Scene() {
|
if name == World.Scene() {
|
||||||
return deck[((i+step)%len(deck)+len(deck))%len(deck)]
|
return deck[((i+step)%len(deck)+len(deck))%len(deck)]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,22 +8,21 @@ import (
|
|||||||
"github.com/hajimehoshi/ebiten/v2/vector"
|
"github.com/hajimehoshi/ebiten/v2/vector"
|
||||||
)
|
)
|
||||||
|
|
||||||
type TapeChannel struct {
|
type tapeChannel struct {
|
||||||
Name string
|
Name string
|
||||||
W *World
|
|
||||||
Bounds inkwell.Rectangle
|
Bounds inkwell.Rectangle
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *TapeChannel) GetName() string { return t.Name }
|
func (t *tapeChannel) GetName() string { return t.Name }
|
||||||
|
|
||||||
func (t *TapeChannel) Tick(ctx *inkwell.UICtx) {}
|
func (t *tapeChannel) Tick(ctx *inkwell.UICtx) {}
|
||||||
|
|
||||||
func (t *TapeChannel) BlocksClickAt(p inkwell.Point) bool {
|
func (t *tapeChannel) BlocksClickAt(p inkwell.Point) bool {
|
||||||
return t.W.HUDVisible() && t.Bounds.Contains(p)
|
return World.HUDVisible() && t.Bounds.Contains(p)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *TapeChannel) Draw(dst *ebiten.Image, ctx *inkwell.UICtx) {
|
func (t *tapeChannel) Draw(dst *ebiten.Image, ctx *inkwell.UICtx) {
|
||||||
if !t.W.HUDVisible() {
|
if !World.HUDVisible() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
g := ctx.Game
|
g := ctx.Game
|
||||||
@@ -84,7 +83,7 @@ func (t *TapeChannel) Draw(dst *ebiten.Image, ctx *inkwell.UICtx) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *TapeChannel) lastSpeaker(g *inkwell.Game, th inkwell.Theme) (string, color.Color) {
|
func (t *tapeChannel) lastSpeaker(g *inkwell.Game, th inkwell.Theme) (string, color.Color) {
|
||||||
msgs := g.Messages()
|
msgs := g.Messages()
|
||||||
for i := len(msgs) - 1; i >= 0; i-- {
|
for i := len(msgs) - 1; i >= 0; i-- {
|
||||||
m := msgs[i]
|
m := msgs[i]
|
||||||
|
|||||||
+23
-24
@@ -6,26 +6,25 @@ import (
|
|||||||
"github.com/hajimehoshi/ebiten/v2/vector"
|
"github.com/hajimehoshi/ebiten/v2/vector"
|
||||||
)
|
)
|
||||||
|
|
||||||
type TapeSlots struct {
|
type tapeSlots struct {
|
||||||
Name string
|
Name string
|
||||||
W *World
|
|
||||||
Bounds inkwell.Rectangle
|
Bounds inkwell.Rectangle
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *TapeSlots) GetName() string { return t.Name }
|
func (t *tapeSlots) GetName() string { return t.Name }
|
||||||
|
|
||||||
func (t *TapeSlots) BlocksClickAt(p inkwell.Point) bool {
|
func (t *tapeSlots) BlocksClickAt(p inkwell.Point) bool {
|
||||||
return t.W.HUDVisible() && t.Bounds.Contains(p)
|
return World.HUDVisible() && t.Bounds.Contains(p)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *TapeSlots) slotRects() (inkwell.Rectangle, inkwell.Rectangle) {
|
func (t *tapeSlots) slotRects() (inkwell.Rectangle, inkwell.Rectangle) {
|
||||||
b := t.Bounds
|
b := t.Bounds
|
||||||
w := (b.W - Pad) / 2
|
w := (b.W - Pad) / 2
|
||||||
return inkwell.Rect(b.X, b.Y, w, b.H), inkwell.Rect(b.X+w+Pad, b.Y, w, b.H)
|
return inkwell.Rect(b.X, b.Y, w, b.H), inkwell.Rect(b.X+w+Pad, b.Y, w, b.H)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *TapeSlots) Tick(ctx *inkwell.UICtx) {
|
func (t *tapeSlots) Tick(ctx *inkwell.UICtx) {
|
||||||
if !t.W.HUDVisible() {
|
if !World.HUDVisible() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
g := ctx.Game
|
g := ctx.Game
|
||||||
@@ -36,7 +35,7 @@ func (t *TapeSlots) Tick(ctx *inkwell.UICtx) {
|
|||||||
case r1.Contains(mp):
|
case r1.Contains(mp):
|
||||||
g.SetHoverLabel(TapeDisplayName(Dex))
|
g.SetHoverLabel(TapeDisplayName(Dex))
|
||||||
case r2.Contains(mp):
|
case r2.Contains(mp):
|
||||||
if s := t.W.Slot2(); s != "" {
|
if s := World.Slot2(); s != "" {
|
||||||
g.SetHoverLabel(itemLabel(g, s))
|
g.SetHoverLabel(itemLabel(g, s))
|
||||||
} else {
|
} else {
|
||||||
g.SetHoverLabel("empty tape slot")
|
g.SetHoverLabel("empty tape slot")
|
||||||
@@ -57,45 +56,45 @@ func (t *TapeSlots) Tick(ctx *inkwell.UICtx) {
|
|||||||
if slot2 && sel != "" {
|
if slot2 && sel != "" {
|
||||||
g.Inventory.Select("")
|
g.Inventory.Select("")
|
||||||
if IsTapeItem(sel) {
|
if IsTapeItem(sel) {
|
||||||
t.W.SetPending(sel)
|
World.SetPending(sel)
|
||||||
t.W.Do(inkwell.RunScript(ScriptTapeInsert))
|
World.Do(inkwell.RunScript(ScriptTapeInsert))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
t.W.Do(TapeSay(Dex, "That isn't a tape, Paul. That's an object. There is a difference."))
|
World.Do(TapeSay(Dex, "That isn't a tape, Paul. That's an object. There is a difference."))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if !slot2 && sel != "" {
|
if !slot2 && sel != "" {
|
||||||
g.Inventory.Select("")
|
g.Inventory.Select("")
|
||||||
t.W.Do(TapeSay(Dex, "The first slot is mine. I'm not moving."))
|
World.Do(TapeSay(Dex, "The first slot is mine. I'm not moving."))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
switch g.SelectedVerb() {
|
switch g.SelectedVerb() {
|
||||||
case "talk":
|
case "talk":
|
||||||
if !slot2 {
|
if !slot2 {
|
||||||
t.W.Do(Paused(t.W, inkwell.RunDialogue(DlgDex)))
|
World.Do(Paused(inkwell.RunDialogue(DlgDex)))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if s := t.W.Slot2(); s != "" {
|
if s := World.Slot2(); s != "" {
|
||||||
t.W.Do(Paused(t.W, inkwell.RunDialogue(TapeDialogue(s))))
|
World.Do(Paused(inkwell.RunDialogue(TapeDialogue(s))))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
t.W.Do(TapeSay(Dex, "Empty. Nobody to talk to."))
|
World.Do(TapeSay(Dex, "Empty. Nobody to talk to."))
|
||||||
default:
|
default:
|
||||||
if !slot2 {
|
if !slot2 {
|
||||||
t.W.Do(TapeSay(Dex, "Me. Four kilobytes of a dead man. Be grateful."))
|
World.Do(TapeSay(Dex, "Me. Four kilobytes of a dead man. Be grateful."))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if s := t.W.Slot2(); s != "" {
|
if s := World.Slot2(); s != "" {
|
||||||
t.W.Do(TapeSay(Dex, "That is the second slot. Be careful what you let in."))
|
World.Do(TapeSay(Dex, "That is the second slot. Be careful what you let in."))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
t.W.Do(TapeSay(Dex, "The second slot is empty. That's the rarer state."))
|
World.Do(TapeSay(Dex, "The second slot is empty. That's the rarer state."))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *TapeSlots) Draw(dst *ebiten.Image, ctx *inkwell.UICtx) {
|
func (t *tapeSlots) Draw(dst *ebiten.Image, ctx *inkwell.UICtx) {
|
||||||
if !t.W.HUDVisible() {
|
if !World.HUDVisible() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
g := ctx.Game
|
g := ctx.Game
|
||||||
@@ -116,7 +115,7 @@ func (t *TapeSlots) Draw(dst *ebiten.Image, ctx *inkwell.UICtx) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
drawSlot(r1, "SLOT 1", TapeDisplayName(Dex), true)
|
drawSlot(r1, "SLOT 1", TapeDisplayName(Dex), true)
|
||||||
if s := t.W.Slot2(); s != "" {
|
if s := World.Slot2(); s != "" {
|
||||||
drawSlot(r2, "SLOT 2", itemLabel(g, s), true)
|
drawSlot(r2, "SLOT 2", itemLabel(g, s), true)
|
||||||
} else {
|
} else {
|
||||||
drawSlot(r2, "SLOT 2", "empty", false)
|
drawSlot(r2, "SLOT 2", "empty", false)
|
||||||
|
|||||||
@@ -7,17 +7,16 @@ import (
|
|||||||
"github.com/hajimehoshi/ebiten/v2"
|
"github.com/hajimehoshi/ebiten/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
type UseWithGuard struct {
|
type useWithGuard struct {
|
||||||
Name string
|
Name string
|
||||||
W *World
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *UseWithGuard) GetName() string { return u.Name }
|
func (u *useWithGuard) GetName() string { return u.Name }
|
||||||
func (u *UseWithGuard) Draw(dst *ebiten.Image, ctx *inkwell.UICtx) {}
|
func (u *useWithGuard) Draw(dst *ebiten.Image, ctx *inkwell.UICtx) {}
|
||||||
|
|
||||||
func (u *UseWithGuard) Tick(ctx *inkwell.UICtx) {
|
func (u *useWithGuard) Tick(ctx *inkwell.UICtx) {
|
||||||
g := ctx.Game
|
g := ctx.Game
|
||||||
if !u.W.HUDVisible() || !g.Input.LeftClicked() {
|
if !World.HUDVisible() || !g.Input.LeftClicked() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
sel := g.Inventory.Selected()
|
sel := g.Inventory.Selected()
|
||||||
@@ -42,7 +41,7 @@ func (u *UseWithGuard) Tick(ctx *inkwell.UICtx) {
|
|||||||
g.State.NoteTalked(key)
|
g.State.NoteTalked(key)
|
||||||
n := g.State.Talked(key)
|
n := g.State.Talked(key)
|
||||||
|
|
||||||
u.W.Do(inkwell.Seq(
|
World.Do(inkwell.Seq(
|
||||||
inkwell.Say(Paul, pick(paulFails, n)),
|
inkwell.Say(Paul, pick(paulFails, n)),
|
||||||
TapeSay(Dex, dexFail(n)),
|
TapeSay(Dex, dexFail(n)),
|
||||||
))
|
))
|
||||||
|
|||||||
+23
-26
@@ -5,13 +5,13 @@ import (
|
|||||||
"github.com/hajimehoshi/ebiten/v2"
|
"github.com/hajimehoshi/ebiten/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (w *World) Do(a inkwell.Action) {
|
func (w *world) Do(a inkwell.Action) {
|
||||||
if a != nil {
|
if a != nil {
|
||||||
w.queue = append(w.queue, a)
|
w.queue = append(w.queue, a)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *World) PumpTick(dt float64) {
|
func (w *world) PumpTick(dt float64) {
|
||||||
|
|
||||||
if w.top != nil {
|
if w.top != nil {
|
||||||
title := w.sceneTitle()
|
title := w.sceneTitle()
|
||||||
@@ -40,7 +40,7 @@ func (w *World) PumpTick(dt float64) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *World) sceneTitle() string {
|
func (w *world) sceneTitle() string {
|
||||||
s, ok := w.G.SceneManager.Get(w.scene)
|
s, ok := w.G.SceneManager.Get(w.scene)
|
||||||
if !ok {
|
if !ok {
|
||||||
return ""
|
return ""
|
||||||
@@ -51,14 +51,13 @@ func (w *World) sceneTitle() string {
|
|||||||
return s.Name
|
return s.Name
|
||||||
}
|
}
|
||||||
|
|
||||||
type ActionPump struct {
|
type actionPump struct {
|
||||||
Name string
|
Name string
|
||||||
W *World
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *ActionPump) GetName() string { return p.Name }
|
func (p *actionPump) GetName() string { return p.Name }
|
||||||
func (p *ActionPump) Tick(ctx *inkwell.UICtx) { p.W.PumpTick(ctx.DT) }
|
func (p *actionPump) Tick(ctx *inkwell.UICtx) { World.PumpTick(ctx.DT) }
|
||||||
func (p *ActionPump) Draw(dst *ebiten.Image, ctx *inkwell.UICtx) {}
|
func (p *actionPump) Draw(dst *ebiten.Image, ctx *inkwell.UICtx) {}
|
||||||
|
|
||||||
type fnAction struct{ fn func(*inkwell.Ctx) }
|
type fnAction struct{ fn func(*inkwell.Ctx) }
|
||||||
|
|
||||||
@@ -85,25 +84,25 @@ func UseTheme(name string) inkwell.Action {
|
|||||||
return Fn(func(ctx *inkwell.Ctx) { ctx.Game.UseTheme(name) })
|
return Fn(func(ctx *inkwell.Ctx) { ctx.Game.UseTheme(name) })
|
||||||
}
|
}
|
||||||
|
|
||||||
func SetMode(w *World, m Mode) inkwell.Action {
|
func SetMode(m Mode) inkwell.Action {
|
||||||
return Fn(func(*inkwell.Ctx) { w.SetMode(m) })
|
return Fn(func(*inkwell.Ctx) { World.SetMode(m) })
|
||||||
}
|
}
|
||||||
|
|
||||||
func EnterScene(w *World, name string) inkwell.Action {
|
func EnterScene(name string) inkwell.Action {
|
||||||
return Fn(func(*inkwell.Ctx) {
|
return Fn(func(*inkwell.Ctx) {
|
||||||
if name != w.scene {
|
if name != World.scene {
|
||||||
w.prev = w.scene
|
World.prev = World.scene
|
||||||
}
|
}
|
||||||
w.scene = name
|
World.scene = name
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func Back(w *World) inkwell.Action {
|
func Back() inkwell.Action {
|
||||||
return Fn(func(ctx *inkwell.Ctx) {
|
return Fn(func(ctx *inkwell.Ctx) {
|
||||||
if w.prev == "" {
|
if World.prev == "" {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
inkwell.GoTo(w.prev).Start().Tick(ctx)
|
inkwell.GoTo(World.prev).Start().Tick(ctx)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -143,14 +142,14 @@ func (r *tapeSayRunner) Tick(ctx *inkwell.Ctx) inkwell.Status {
|
|||||||
return inkwell.StatusRunning
|
return inkwell.StatusRunning
|
||||||
}
|
}
|
||||||
|
|
||||||
func TapeOffer(w *World, line inkwell.Action) inkwell.Action {
|
func TapeOffer(line inkwell.Action) inkwell.Action {
|
||||||
return Fn(func(*inkwell.Ctx) {
|
return Fn(func(*inkwell.Ctx) {
|
||||||
w.tapeLine = line
|
World.tapeLine = line
|
||||||
w.tapeWaiting = true
|
World.tapeWaiting = true
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *World) TakeTapeOffer() {
|
func (w *world) TakeTapeOffer() {
|
||||||
if !w.tapeWaiting {
|
if !w.tapeWaiting {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -160,15 +159,13 @@ func (w *World) TakeTapeOffer() {
|
|||||||
w.Do(line)
|
w.Do(line)
|
||||||
}
|
}
|
||||||
|
|
||||||
func Paused(w *World, inner inkwell.Action) inkwell.Action {
|
func Paused(inner inkwell.Action) inkwell.Action {
|
||||||
return &pausedAction{
|
return &pausedAction{
|
||||||
w: w,
|
|
||||||
inner: inner,
|
inner: inner,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type pausedAction struct {
|
type pausedAction struct {
|
||||||
w *World
|
|
||||||
inner inkwell.Action
|
inner inkwell.Action
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -188,11 +185,11 @@ type pausedRunner struct {
|
|||||||
func (r *pausedRunner) Tick(ctx *inkwell.Ctx) inkwell.Status {
|
func (r *pausedRunner) Tick(ctx *inkwell.Ctx) inkwell.Status {
|
||||||
if !r.started {
|
if !r.started {
|
||||||
r.started = true
|
r.started = true
|
||||||
r.spec.w.paused = true
|
World.paused = true
|
||||||
}
|
}
|
||||||
s := r.inner.Tick(ctx)
|
s := r.inner.Tick(ctx)
|
||||||
if s != inkwell.StatusRunning {
|
if s != inkwell.StatusRunning {
|
||||||
r.spec.w.paused = false
|
World.paused = false
|
||||||
}
|
}
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|||||||
+27
-18
@@ -12,7 +12,7 @@ const (
|
|||||||
ModeMenu Mode = "menu"
|
ModeMenu Mode = "menu"
|
||||||
)
|
)
|
||||||
|
|
||||||
type World struct {
|
type world struct {
|
||||||
G *inkwell.Game
|
G *inkwell.Game
|
||||||
|
|
||||||
mode Mode
|
mode Mode
|
||||||
@@ -29,42 +29,51 @@ type World struct {
|
|||||||
tapeLine inkwell.Action
|
tapeLine inkwell.Action
|
||||||
}
|
}
|
||||||
|
|
||||||
func newWorld(g *inkwell.Game) *World {
|
var World = &world{}
|
||||||
return &World{
|
|
||||||
G: g,
|
func (w *world) attach(g *inkwell.Game) {
|
||||||
mode: ModePlay,
|
w.G = g
|
||||||
}
|
w.mode = ModePlay
|
||||||
|
w.scene = ""
|
||||||
|
w.prev = ""
|
||||||
|
w.paused = false
|
||||||
|
w.pending = ""
|
||||||
|
w.queue = nil
|
||||||
|
w.running = nil
|
||||||
|
w.top = nil
|
||||||
|
w.tapeWaiting = false
|
||||||
|
w.tapeLine = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *World) Mode() Mode { return w.mode }
|
func (w *world) Mode() Mode { return w.mode }
|
||||||
|
|
||||||
func (w *World) SetMode(m Mode) { w.mode = m }
|
func (w *world) SetMode(m Mode) { w.mode = m }
|
||||||
|
|
||||||
func (w *World) HUDVisible() bool { return w.mode == ModePlay }
|
func (w *world) HUDVisible() bool { return w.mode == ModePlay }
|
||||||
|
|
||||||
func (w *World) Scene() string { return w.scene }
|
func (w *world) Scene() string { return w.scene }
|
||||||
|
|
||||||
func (w *World) Previous() string { return w.prev }
|
func (w *world) Previous() string { return w.prev }
|
||||||
|
|
||||||
func (w *World) Paused() bool { return w.paused }
|
func (w *world) Paused() bool { return w.paused }
|
||||||
|
|
||||||
func (w *World) SetTopBar(t *inkwell.TopBar) { w.top = t }
|
func (w *world) SetTopBar(t *inkwell.TopBar) { w.top = t }
|
||||||
|
|
||||||
func (w *World) Slot2() string {
|
func (w *world) Slot2() string {
|
||||||
if v, ok := w.G.State.Var(VarSlot2).(string); ok {
|
if v, ok := w.G.State.Var(VarSlot2).(string); ok {
|
||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *World) SetSlot2(item string) { w.G.State.SetVar(VarSlot2, item) }
|
func (w *world) SetSlot2(item string) { w.G.State.SetVar(VarSlot2, item) }
|
||||||
|
|
||||||
func (w *World) SetPending(item string) { w.pending = item }
|
func (w *world) SetPending(item string) { w.pending = item }
|
||||||
|
|
||||||
func (w *World) TakePending() string {
|
func (w *world) TakePending() string {
|
||||||
item := w.pending
|
item := w.pending
|
||||||
w.pending = ""
|
w.pending = ""
|
||||||
return item
|
return item
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *World) TapeWaiting() bool { return w.tapeWaiting }
|
func (w *world) TapeWaiting() bool { return w.tapeWaiting }
|
||||||
|
|||||||
Reference in New Issue
Block a user