Get character stats (kind of) displaying in-scenario
This commit is contained in:
@@ -119,7 +119,7 @@ func (m *Map) CharacterAt(x, y, z int) *maps.Character {
|
||||
// FIXME: don't iterate
|
||||
for i, _ := range m.raw.Characters {
|
||||
chr := &m.raw.Characters[i]
|
||||
if chr.XPos == x && chr.YPos == y && z == 1 { // FIXME: sort out ZPos
|
||||
if chr.XPos == x && chr.YPos == y && z == 0 { // FIXME: sort out ZPos
|
||||
return chr
|
||||
}
|
||||
}
|
||||
|
@@ -7,6 +7,7 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/hajimehoshi/ebiten"
|
||||
"github.com/hajimehoshi/ebiten/inpututil"
|
||||
|
||||
"code.ur.gs/lupine/ordoor/internal/assetstore"
|
||||
"code.ur.gs/lupine/ordoor/internal/config"
|
||||
@@ -118,6 +119,14 @@ func (f *Flow) Update(screenX, screenY int) error {
|
||||
if ebiten.IsKeyPressed(ebiten.KeyDown) {
|
||||
f.scenario.Viewpoint.Y += step
|
||||
}
|
||||
|
||||
if inpututil.IsMouseButtonJustReleased(ebiten.MouseButtonLeft) {
|
||||
f.scenario.SelectHighlightedCharacter()
|
||||
|
||||
// Now we need to update the info screens with data about the
|
||||
// selected character. FIXME: oh, for data binding
|
||||
f.selectedMainGameCharacter(f.scenario.SelectedCharacter())
|
||||
}
|
||||
}
|
||||
|
||||
if f.scenario != nil {
|
||||
|
@@ -1,5 +1,9 @@
|
||||
package flow
|
||||
|
||||
import (
|
||||
"code.ur.gs/lupine/ordoor/internal/maps"
|
||||
)
|
||||
|
||||
// TODO: There are Chaos and Ultramarine versions of MainGame. Do we really want
|
||||
// to duplicate everything for both?
|
||||
|
||||
@@ -154,3 +158,48 @@ func (f *Flow) linkMainGameViewMenu() {
|
||||
}))
|
||||
|
||||
}
|
||||
|
||||
func (f *Flow) maybeSetErr(next func() error) {
|
||||
if f.exit != nil {
|
||||
return
|
||||
}
|
||||
|
||||
f.exit = next()
|
||||
}
|
||||
|
||||
func (f *Flow) selectedMainGameCharacter(chr *maps.Character) {
|
||||
if chr == nil {
|
||||
chr = &maps.Character{}
|
||||
}
|
||||
|
||||
d := f.drivers[mainGame]
|
||||
|
||||
// 7.1 Portrait
|
||||
f.maybeSetErr(func() error { return d.SetValue("7.2", chr.Name) }) // Name
|
||||
// 7.3 doesn't exit
|
||||
// 7.4 more button (ignore)
|
||||
// 7.5 AP icon
|
||||
// f.maybeSetErr(func() error { return d.SetValueInt("7.6", chr.ActionPoints)}) // AP meter
|
||||
f.maybeSetErr(func() error { return d.SetValueInt("7.7", chr.ActionPoints) }) // AP value
|
||||
// 7.8 armor icon
|
||||
// 7.9 armor meter
|
||||
f.maybeSetErr(func() error { return d.SetValueInt("7.10", chr.Armor) }) // armor value
|
||||
// 7.11 health icon
|
||||
// 7.12 health meter
|
||||
f.maybeSetErr(func() error { return d.SetValueInt("7.13", chr.Health) }) // health value
|
||||
// 7.14 action points status bar
|
||||
// 7.15 armor status bar
|
||||
// 7.16 health status bar
|
||||
|
||||
// 8.1 to 8.10 are hot spots
|
||||
f.maybeSetErr(func() error { return d.SetValueInt("8.11", chr.ActionPoints) }) // AP
|
||||
f.maybeSetErr(func() error { return d.SetValueInt("8.12", chr.Health) }) // Health
|
||||
f.maybeSetErr(func() error { return d.SetValueInt("8.13", chr.Armor) }) // Armor
|
||||
f.maybeSetErr(func() error { return d.SetValueInt("8.14", chr.BallisticSkill) }) // Ballistic Skill
|
||||
f.maybeSetErr(func() error { return d.SetValueInt("8.15", chr.WeaponSkill) }) // Weapon Skill
|
||||
f.maybeSetErr(func() error { return d.SetValueInt("8.16", chr.Strength) }) // Strength
|
||||
f.maybeSetErr(func() error { return d.SetValueInt("8.17", chr.Toughness) }) // Toughness
|
||||
// 8.18 Initiative
|
||||
// 8.19 Attacks
|
||||
f.maybeSetErr(func() error { return d.SetValueInt("8.20", chr.Leadership) }) // Leadership
|
||||
}
|
||||
|
@@ -319,7 +319,8 @@ func loadMapFile(filename string) (*GameMap, error) {
|
||||
nullTerminate(&out.Title)
|
||||
nullTerminate(&out.Briefing)
|
||||
|
||||
for i, chr := range out.Characters {
|
||||
for i, _ := range out.Characters {
|
||||
chr := &out.Characters[i]
|
||||
nullTerminate(&chr.Name)
|
||||
fmt.Printf("Character %v: %s\n", i, chr.String())
|
||||
}
|
||||
|
@@ -33,7 +33,7 @@ const (
|
||||
SubTypeLineBriefing SubMenuType = 41
|
||||
SubTypeThumb SubMenuType = 45 // A "thumb" appears to be a vertical slider
|
||||
SubTypeInvokeButton SubMenuType = 50
|
||||
SubTypeDoorHotspot3 SubMenuType = 60 // Maybe? Appears in Arrange.mnu
|
||||
SubTypeClickText SubMenuType = 60
|
||||
SubTypeOverlay SubMenuType = 61
|
||||
SubTypeHypertext SubMenuType = 70
|
||||
SubTypeCheckbox SubMenuType = 91
|
||||
|
@@ -36,7 +36,7 @@ func (s *Scenario) Update(screenX, screenY int) error {
|
||||
}
|
||||
|
||||
// FIXME: adjust for Z level
|
||||
s.selectedCell = screenPos.ToISO()
|
||||
s.highlightedCell = screenPos.ToISO()
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -112,7 +112,7 @@ func (s *Scenario) Draw(screen *ebiten.Image) error {
|
||||
}
|
||||
|
||||
op := ebiten.DrawImageOptions{}
|
||||
geo := s.geoForCoords(int(s.selectedCell.X), int(s.selectedCell.Y), 0)
|
||||
geo := s.geoForCoords(int(s.highlightedCell.X), int(s.highlightedCell.Y), 0)
|
||||
op.GeoM = geo
|
||||
op.GeoM.Translate(-209, -332)
|
||||
op.GeoM.Translate(float64(spr.Rect.Min.X), float64(spr.Rect.Min.Y))
|
||||
@@ -125,7 +125,7 @@ func (s *Scenario) Draw(screen *ebiten.Image) error {
|
||||
x1, y1 := geo.Apply(0, 0)
|
||||
ebitenutil.DebugPrintAt(
|
||||
screen,
|
||||
fmt.Sprintf("(%d,%d)", int(s.selectedCell.X), int(s.selectedCell.Y)),
|
||||
fmt.Sprintf("(%d,%d)", int(s.highlightedCell.X), int(s.highlightedCell.Y)),
|
||||
int(x1),
|
||||
int(y1),
|
||||
)
|
||||
|
@@ -1,6 +1,8 @@
|
||||
package scenario
|
||||
|
||||
import (
|
||||
"log"
|
||||
|
||||
"code.ur.gs/lupine/ordoor/internal/maps"
|
||||
)
|
||||
|
||||
@@ -10,8 +12,23 @@ type CellPoint struct {
|
||||
}
|
||||
|
||||
func (s *Scenario) CellAtCursor() (*maps.Cell, CellPoint) {
|
||||
cell := s.area.Cell(int(s.selectedCell.X), int(s.selectedCell.Y), 0)
|
||||
return cell, CellPoint{IsoPt: s.selectedCell, Z: 0}
|
||||
cell := s.area.Cell(int(s.highlightedCell.X), int(s.highlightedCell.Y), 0)
|
||||
return cell, CellPoint{IsoPt: s.highlightedCell, Z: 0}
|
||||
}
|
||||
|
||||
func (s *Scenario) HighlightedCharacter() *maps.Character {
|
||||
// FIXME: characters are always at zIdx 0 right now
|
||||
return s.area.CharacterAt(int(s.highlightedCell.X), int(s.highlightedCell.Y), 0)
|
||||
}
|
||||
|
||||
func (s *Scenario) SelectedCharacter() *maps.Character {
|
||||
return s.selectedCharacter
|
||||
}
|
||||
|
||||
func (s *Scenario) SelectHighlightedCharacter() {
|
||||
chr := s.HighlightedCharacter()
|
||||
log.Printf("Selected character %s", chr)
|
||||
s.selectedCharacter = chr
|
||||
}
|
||||
|
||||
func (s *Scenario) ChangeZIdx(by int) {
|
||||
|
@@ -5,15 +5,18 @@ import (
|
||||
"image"
|
||||
|
||||
"code.ur.gs/lupine/ordoor/internal/assetstore"
|
||||
"code.ur.gs/lupine/ordoor/internal/maps"
|
||||
)
|
||||
|
||||
type Scenario struct {
|
||||
area *assetstore.Map
|
||||
specials *assetstore.Object
|
||||
|
||||
tick int
|
||||
turn int
|
||||
selectedCell IsoPt
|
||||
tick int
|
||||
turn int
|
||||
|
||||
highlightedCell IsoPt
|
||||
selectedCharacter *maps.Character
|
||||
|
||||
// All these must be modified by user actions somehow.
|
||||
// TODO: extract into the idea of a viewport passed to Update / Draw somehow?
|
||||
|
@@ -78,8 +78,10 @@ func (d *Driver) buildRecord(r *menus.Record) (*Widget, error) {
|
||||
switch r.Type {
|
||||
case menus.SubTypeSimpleButton, menus.SubTypeInvokeButton:
|
||||
_, widget, err = d.buildButton(r.Props())
|
||||
case menus.SubTypeDoorHotspot1, menus.SubTypeDoorHotspot2, menus.SubTypeDoorHotspot3:
|
||||
case menus.SubTypeDoorHotspot1, menus.SubTypeDoorHotspot2:
|
||||
_, widget, err = d.buildDoorHotspot(r.Props())
|
||||
case menus.SubTypeClickText:
|
||||
_, widget, err = d.buildClickText(r.Props())
|
||||
case menus.SubTypeOverlay:
|
||||
_, widget, err = d.buildOverlay(r.Props())
|
||||
case menus.SubTypeHypertext:
|
||||
|
@@ -157,9 +157,9 @@ func (l *listBox) refresh() {
|
||||
// FIXME: noninteractive isn't set up for dynamic text yet. Need to
|
||||
// generate textImg on demand instead of once at start.
|
||||
if ni.label != nil {
|
||||
ni.label.text = ""
|
||||
ni.label.str = ""
|
||||
if len(l.strings) > l.offset+i {
|
||||
ni.label.text = l.strings[l.offset+i]
|
||||
ni.label.str = l.strings[l.offset+i]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -32,12 +32,13 @@ type noninteractive struct {
|
||||
hoverImpl
|
||||
}
|
||||
|
||||
// Paint some text to screen
|
||||
// Paint some text to screen, possibly settable
|
||||
type label struct {
|
||||
align AlignMode
|
||||
rect image.Rectangle
|
||||
text string
|
||||
font *assetstore.Font
|
||||
locator string
|
||||
align AlignMode
|
||||
rect image.Rectangle
|
||||
font *assetstore.Font
|
||||
valueImpl
|
||||
}
|
||||
|
||||
// This particular animation has entry and exit sequences, which are invoked
|
||||
@@ -109,6 +110,33 @@ func (d *Driver) buildHypertext(p *menus.Properties) (*noninteractive, *Widget,
|
||||
return ni, widget, nil
|
||||
}
|
||||
|
||||
func (d *Driver) buildClickText(p *menus.Properties) (*noninteractive, *Widget, error) {
|
||||
ni, err := d.buildNoninteractive(p)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
fnt := d.menu.Font(p.FontType/10 - 1)
|
||||
|
||||
// FIXME: is this always right? Seems to make sense for Main.mnu
|
||||
ni.label = &label{
|
||||
locator: ni.locator,
|
||||
font: fnt,
|
||||
rect: ni.rect, // We will be centered by default
|
||||
// Starts with no text. The text specified in the menu is hovertext
|
||||
}
|
||||
|
||||
widget := &Widget{
|
||||
Locator: ni.locator,
|
||||
Active: p.Active,
|
||||
ownClickables: []clickable{ni},
|
||||
ownPaintables: []paintable{ni},
|
||||
ownValueables: []valueable{ni.label},
|
||||
}
|
||||
|
||||
return ni, widget, nil
|
||||
}
|
||||
|
||||
// An overlay is a static image + some text that needs to be rendered
|
||||
func (d *Driver) buildOverlay(p *menus.Properties) (*noninteractive, *Widget, error) {
|
||||
ni, err := d.buildNoninteractive(p)
|
||||
@@ -127,9 +155,9 @@ func (d *Driver) buildOverlay(p *menus.Properties) (*noninteractive, *Widget, er
|
||||
fnt := d.menu.Font(p.FontType/10 - 1)
|
||||
|
||||
ni.label = &label{
|
||||
font: fnt,
|
||||
rect: ni.rect, // We will be centered by default
|
||||
text: p.Text,
|
||||
font: fnt,
|
||||
rect: ni.rect, // We will be centered by default
|
||||
valueImpl: valueImpl{str: p.Text},
|
||||
}
|
||||
} else {
|
||||
log.Printf("Overlay without text detected in %v", p.Locator)
|
||||
@@ -253,6 +281,10 @@ func (a *animationHover) setHoverState(value bool) {
|
||||
a.hoverImpl.setHoverState(value)
|
||||
}
|
||||
|
||||
func (l *label) id() string {
|
||||
return l.locator
|
||||
}
|
||||
|
||||
// Top-left of where to start drawing the text. We want it to appear to be in
|
||||
// the centre of the rect.
|
||||
//
|
||||
@@ -260,7 +292,7 @@ func (a *animationHover) setHoverState(value bool) {
|
||||
func (l *label) pos() image.Point {
|
||||
pos := l.rect.Min
|
||||
|
||||
textRect := l.font.CalculateBounds(l.text)
|
||||
textRect := l.font.CalculateBounds(l.str)
|
||||
|
||||
// Centre the text horizontally
|
||||
if l.align == AlignModeCentre {
|
||||
@@ -287,7 +319,7 @@ func (l *label) regions(tick int) []region {
|
||||
|
||||
pt := l.pos()
|
||||
|
||||
for _, r := range l.text {
|
||||
for _, r := range l.str {
|
||||
glyph, err := l.font.Glyph(r)
|
||||
if err != nil {
|
||||
log.Printf("FIXME: ignoring misssing glyph %v", r)
|
||||
|
Reference in New Issue
Block a user