Skip to content

Commit f1a9b5a

Browse files
committed
Merge branch 'feature/medallions'
2 parents f71aaa3 + d9b83e2 commit f1a9b5a

File tree

9 files changed

+300
-154
lines changed

9 files changed

+300
-154
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
/ivan
22
/ivan.exe
33
/ivan_release_*
4+
/tags

README.md

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -54,23 +54,38 @@ Other keys:
5454
runs in the background).
5555

5656
## Hint tracker
57-
1. Press the key corresponding to your hint type (WotH, Barren, Sometimes,
58-
Always)
57+
1. Press the key corresponding to your hint type (**W**otH, **B**arren, **S**ometimes,
58+
**A**lways).
5959
2. Type your text.
60-
3. Press `Enter`
60+
3. Press `Enter`.
6161

62-
- `w` to enter a _WotH_ Hint (green background, fuzzy location search)
63-
- `b` to enter a _Barren_ Hint (red background, fuzzy location search)
64-
- `s` to enter a _Sometimes_ Hint (blue background, freeform text)
65-
- `a` to enter a _Always_ Hint (yellow background)
66-
- `Esc` to cancel your input
67-
- `Enter` to submit your input
62+
- `w` to enter a _WotH_ Hint (green background, fuzzy location search).
63+
- `b` to enter a _Barren_ Hint (red background, fuzzy location search).
64+
- `s` to enter a _Sometimes_ Hint (blue background, freeform text).
65+
- `a` to enter a _Always_ Hint (yellow background).
66+
- `Esc` to cancel your input.
67+
- `Enter` to submit your input.
6868

6969
As _Always Hints_ have a fixed slot, they get special treatment. The text you input
7070
is parsed as the slot name until the first space, then your text. eg. If you
7171
get _Nocturne of Shadows_ on _Ocarina of Time_ you might press `a` to start the
7272
prompt then `oot = nocturne` then `Enter`.
7373

74+
## Dungeon input
75+
Dungeon input allows you to quickly set which dungeons holds what medallions
76+
when reading the altar at the _Temple of Time_.
77+
78+
1. Press `d` to enter dungeon input mode.
79+
2. Dungeon mode always starts with the _Light Medallion_ and goes in the same
80+
order as the altar.
81+
3. Press the KP of the medallion that originally holds the dungeon. eg. if
82+
_Fire Temple_ holds the _Light Medallion_, press the key for _Fire
83+
Medallion_, ie. `5`.
84+
4. Dungeon mode will advance to the next medallion and you can go back to 3.
85+
5. When the last medallion is entered, dungeon mode is exited automatically.
86+
87+
You can also use `+` and `-` to cycle through medallions and `0` to exit.
88+
7489
## Customization
7590
The images in the [`assets`](./assets) folder can be changed if you wish to
7691
customize your background or your icons.

app.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package main
22

33
import (
44
"errors"
5+
"fmt"
56
"ivan/timer"
67
"ivan/tracker"
78
"log"
@@ -27,7 +28,7 @@ type App struct {
2728
func NewApp() (*App, error) {
2829
config, err := loadConfig(configPath)
2930
if err != nil {
30-
return nil, err
31+
return nil, fmt.Errorf("unable to load initial config: %w", err)
3132
}
3233

3334
size := config.windowSize()
@@ -46,6 +47,8 @@ func NewApp() (*App, error) {
4647
config.ZoneItemMap,
4748
config.Locations,
4849
config.Binds,
50+
config.DungeonInputMedallionOrder,
51+
config.DungeonInputDungeonKP,
4952
)
5053
if err != nil {
5154
return nil, err
@@ -79,7 +82,7 @@ func (app *App) Update(screen *ebiten.Image) error {
7982
if !app.timer.IsRunning() {
8083
config, err := loadConfig(configPath)
8184
if err != nil {
82-
return err
85+
return fmt.Errorf("unable to load config: %w", err)
8386
}
8487
app.config = config
8588
}

assets/config.json

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
"+": "Redo",
77
"w": "StartWOTHInput",
88
"b": "StartBarrenInput",
9+
"d": "StartDungeonInput",
910
"a": "StartAlwaysHintInput",
1011
"s": "StartSometimesHintInput",
1112
"7": "TopLeft",
@@ -18,6 +19,22 @@
1819
"2": "Bottom",
1920
"3": "BottomRight"
2021
},
22+
23+
"DungeonInputMedallionOrder": [
24+
"Light Medallion",
25+
"Forest Medallion",
26+
"Fire Medallion",
27+
"Water Medallion",
28+
"Shadow Medallion",
29+
"Spirit Medallion"
30+
],
31+
32+
"DungeonInputDungeonKP": [
33+
"Spirit Temple", "Shadow Temple", "Free",
34+
"Forest Temple", "Fire Temple", "Water Temple",
35+
"Deku Tree", "Dodongo's Cavern", "Jabu Jabu"
36+
],
37+
2138
"Dimensions": {
2239
"ItemTracker": {
2340
"Min": {"X": 0, "Y": 0},

config.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,10 @@ type config struct {
1212
Items []tracker.Item
1313
ZoneItemMap [9][9]string
1414
Locations []string // woth/barren "simple" locations
15-
Dimensions struct {
15+
16+
DungeonInputMedallionOrder, DungeonInputDungeonKP []string
17+
18+
Dimensions struct {
1619
ItemTracker image.Rectangle
1720
Timer image.Rectangle
1821
HintTracker image.Rectangle

tracker/draw.go

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
package tracker
2+
3+
import (
4+
"image"
5+
"image/color"
6+
"log"
7+
"strconv"
8+
9+
"github.com/hajimehoshi/ebiten"
10+
"github.com/hajimehoshi/ebiten/ebitenutil"
11+
"github.com/hajimehoshi/ebiten/text"
12+
)
13+
14+
func (tracker *Tracker) Draw(screen *ebiten.Image) {
15+
op := ebiten.DrawImageOptions{}
16+
drawState := func(state bool, sheet *ebiten.Image) {
17+
for k := range tracker.items {
18+
if tracker.items[k].Enabled != state {
19+
continue
20+
}
21+
22+
pos := tracker.items[k].Rect().Min.Add(tracker.pos)
23+
op.GeoM.Reset()
24+
op.GeoM.Translate(float64(pos.X), float64(pos.Y))
25+
26+
if err := screen.DrawImage(
27+
sheet.SubImage(tracker.items[k].SheetRect()).(*ebiten.Image),
28+
&op,
29+
); err != nil {
30+
log.Fatal(err)
31+
}
32+
}
33+
}
34+
35+
_ = screen.DrawImage(tracker.background, nil)
36+
if tracker.kbInputStateIsAny(inputStateItemKPZoneInput, inputStateItemInput) {
37+
_ = screen.DrawImage(tracker.backgroundHelp, nil)
38+
if tracker.input.activeKPZone > 0 {
39+
tracker.drawActiveItemSlot(screen, tracker.input.activeKPZone)
40+
}
41+
}
42+
43+
// Do two loops to avoid texture switches.
44+
drawState(false, tracker.sheetDisabled)
45+
drawState(true, tracker.sheetEnabled)
46+
47+
tracker.drawDungeons(screen)
48+
tracker.drawCapacities(screen)
49+
tracker.drawInputState(screen)
50+
tracker.drawHints(screen)
51+
}
52+
func (tracker *Tracker) drawActiveItemSlot(screen *ebiten.Image, slot int) {
53+
if slot <= 0 || slot > 9 {
54+
return
55+
}
56+
57+
slot = []int{ // make maths ez
58+
0,
59+
6, 7, 8,
60+
3, 4, 5,
61+
0, 1, 2,
62+
}[slot]
63+
64+
edge := gridSize * 3
65+
pos := image.Point{
66+
(slot % 3) * edge,
67+
(slot / 3) * edge,
68+
}
69+
size := image.Point{126, 126}
70+
71+
if slot == 2 { // KP 9
72+
pos.Y = 0
73+
size.X = gridSize
74+
size.Y = 4*gridSize + (gridSize / 2)
75+
} else if slot == 8 { // KP 3
76+
pos.Y = 4*gridSize + (gridSize / 2)
77+
size.X = gridSize
78+
size.Y = pos.Y
79+
}
80+
81+
ebitenutil.DrawRect(
82+
screen,
83+
float64(pos.X), float64(pos.Y),
84+
float64(size.X), float64(size.Y),
85+
color.RGBA{0xFF, 0xFF, 0xFF, 0x50},
86+
)
87+
}
88+
89+
func (tracker *Tracker) drawDungeons(screen *ebiten.Image) {
90+
for k := range tracker.items {
91+
if !tracker.items[k].IsMedallion {
92+
continue
93+
}
94+
95+
rect := tracker.items[k].Rect()
96+
x, y := rect.Min.X, rect.Max.Y
97+
text.Draw(screen, tracker.items[k].DungeonText(), tracker.fontSmall, x, y, color.White)
98+
}
99+
}
100+
101+
func (tracker *Tracker) drawCapacities(screen *ebiten.Image) {
102+
for k := range tracker.items {
103+
var count int
104+
switch {
105+
case tracker.items[k].HasCapacity():
106+
count = tracker.items[k].Capacity()
107+
case tracker.items[k].IsCountable():
108+
count = tracker.items[k].Count
109+
default:
110+
continue
111+
}
112+
113+
if !tracker.items[k].Enabled {
114+
continue
115+
}
116+
117+
rect := tracker.items[k].Rect()
118+
x, y := rect.Min.X, rect.Max.Y
119+
120+
// HACK, display skull count centered on the right slot
121+
if tracker.items[k].Name == "Gold Skulltula Token" {
122+
x, y = rect.Min.X+gridSize+marginLeft, rect.Min.Y+marginTop+(gridSize/2)
123+
if count == 100 {
124+
x -= 5
125+
} else if count < 10 {
126+
x += 5
127+
}
128+
}
129+
130+
str := strconv.Itoa(count)
131+
text.Draw(screen, str, tracker.font, x, y, color.White)
132+
}
133+
}

0 commit comments

Comments
 (0)