From b00fa58fc4a1092f736f8712773fe6f0b11355f7 Mon Sep 17 00:00:00 2001 From: Ziemas Date: Sun, 28 Jun 2020 00:58:41 +0200 Subject: [PATCH] Object Highlights (#476) * Add PushBrightness to surface * Highlight selectable objects Check if mapentity is selectable. (seems reasonable) Request objects to highlight themselves is required (idk) --- d2core/d2map/d2mapentity/map_entity.go | 9 +++++++++ d2core/d2map/d2mapentity/npc.go | 8 ++++++++ d2core/d2map/d2mapentity/object.go | 22 ++++++++++++++++++++-- d2core/d2map/d2mapentity/player.go | 5 +++++ d2core/d2render/ebiten/ebiten_surface.go | 8 ++++++++ d2core/d2render/ebiten/surface_state.go | 1 + d2core/d2render/surface.go | 1 + d2game/d2gamescreen/game.go | 1 - d2game/d2player/game_controls.go | 3 ++- 9 files changed, 54 insertions(+), 4 deletions(-) diff --git a/d2core/d2map/d2mapentity/map_entity.go b/d2core/d2map/d2mapentity/map_entity.go index 5257989f..c050bd39 100644 --- a/d2core/d2map/d2mapentity/map_entity.go +++ b/d2core/d2map/d2mapentity/map_entity.go @@ -15,6 +15,8 @@ type MapEntity interface { GetLayer() (int) GetPositionF() (float64, float64) Name() string + Selectable() bool + Highlight() } // mapEntity represents an entity on the map that can be animated @@ -190,3 +192,10 @@ func (m *mapEntity) GetPositionF() (float64, float64) { func (m *mapEntity) Name() string { return "" } + +func (m *mapEntity) Highlight() { +} + +func (m *mapEntity) Selectable() bool { + return false +} diff --git a/d2core/d2map/d2mapentity/npc.go b/d2core/d2map/d2mapentity/npc.go index 156d268d..04af91aa 100644 --- a/d2core/d2map/d2mapentity/npc.go +++ b/d2core/d2map/d2mapentity/npc.go @@ -165,6 +165,14 @@ func (v *NPC) SetMode(animationMode, weaponClass string, direction int) error { return err } +func (m *NPC) Selectable() bool { + // is there something handy that determines selectable npc's? + if m.name != "" { + return true + } + return false +} + func (m *NPC) Name() string { return m.name } diff --git a/d2core/d2map/d2mapentity/object.go b/d2core/d2map/d2mapentity/object.go index 18be356a..4b298477 100644 --- a/d2core/d2map/d2mapentity/object.go +++ b/d2core/d2map/d2mapentity/object.go @@ -12,6 +12,7 @@ type Object struct { mapEntity composite *d2asset.Composite direction int + highlight bool objectRecord *d2datadict.ObjectRecord objectLookup *d2datadict.ObjectLookupRecord } @@ -45,24 +46,41 @@ func (ob *Object) SetMode(animationMode, weaponClass string, direction int) erro err = ob.composite.SetMode(animationMode, "HTH", direction) ob.weaponClass = "HTH" } - ob.mapEntity.drawLayer = ob.objectRecord.OrderFlag[d2enum.ObjectAnimationModeFromString(animationMode)] + + mode := d2enum.ObjectAnimationModeFromString(animationMode) + ob.mapEntity.drawLayer = ob.objectRecord.OrderFlag[mode] // For objects their txt record entry overrides animationdata - speed := ob.objectRecord.FrameDelta[d2enum.ObjectAnimationModeFromString(animationMode)] + speed := ob.objectRecord.FrameDelta[mode] if speed != 0 { ob.composite.SetSpeed(speed) } + return err } +func (ob *Object) Highlight() { + ob.highlight = true +} + +func (ob *Object) Selectable() bool { + mode := d2enum.ObjectAnimationModeFromString(ob.composite.GetAnimationMode()) + return ob.objectRecord.Selectable[mode] +} + // Render draws this animated entity onto the target func (ob *Object) Render(target d2render.Surface) { target.PushTranslation( ob.offsetX+int((ob.subcellX-ob.subcellY)*16), ob.offsetY+int(((ob.subcellX+ob.subcellY)*8)-5), ) + if ob.highlight { + target.PushBrightness(2) + defer target.Pop() + } defer target.Pop() ob.composite.Render(target) + ob.highlight = false } // rotate sets direction and changes animation diff --git a/d2core/d2map/d2mapentity/player.go b/d2core/d2map/d2mapentity/player.go index 4fc41f74..4381a4d9 100644 --- a/d2core/d2map/d2mapentity/player.go +++ b/d2core/d2map/d2mapentity/player.go @@ -207,3 +207,8 @@ func (v *Player) SetCasting() { v.isCasting = true v.SetAnimationMode(d2enum.AnimationModePlayerCast.String()) } + +func (v *Player) Selectable() bool { + // Players are selectable when in town + return v.IsInTown() +} diff --git a/d2core/d2render/ebiten/ebiten_surface.go b/d2core/d2render/ebiten/ebiten_surface.go index 6ac26a04..88137234 100644 --- a/d2core/d2render/ebiten/ebiten_surface.go +++ b/d2core/d2render/ebiten/ebiten_surface.go @@ -38,6 +38,11 @@ func (s *ebitenSurface) PushColor(color color.Color) { s.stateCurrent.color = color } +func (s *ebitenSurface) PushBrightness(brightness float64) { + s.stateStack = append(s.stateStack, s.stateCurrent) + s.stateCurrent.brightness = brightness +} + func (s *ebitenSurface) Pop() { count := len(s.stateStack) if count == 0 { @@ -61,6 +66,9 @@ func (s *ebitenSurface) Render(sfc d2render.Surface) error { if s.stateCurrent.color != nil { opts.ColorM = ColorToColorM(s.stateCurrent.color) } + if s.stateCurrent.brightness != 0 { + opts.ColorM.ChangeHSV(0, 1, s.stateCurrent.brightness) + } var img = sfc.(*ebitenSurface).image return s.image.DrawImage(img, opts) diff --git a/d2core/d2render/ebiten/surface_state.go b/d2core/d2render/ebiten/surface_state.go index 5b9086e7..02c0bb9c 100644 --- a/d2core/d2render/ebiten/surface_state.go +++ b/d2core/d2render/ebiten/surface_state.go @@ -12,4 +12,5 @@ type surfaceState struct { mode ebiten.CompositeMode filter ebiten.Filter color color.Color + brightness float64 } diff --git a/d2core/d2render/surface.go b/d2core/d2render/surface.go index c5ec5fa2..3d167988 100644 --- a/d2core/d2render/surface.go +++ b/d2core/d2render/surface.go @@ -18,6 +18,7 @@ type Surface interface { PushCompositeMode(mode CompositeMode) PushFilter(filter Filter) PushTranslation(x, y int) + PushBrightness(brightness float64) Render(surface Surface) error ReplacePixels(pixels []byte) error Screenshot() *image.RGBA diff --git a/d2game/d2gamescreen/game.go b/d2game/d2gamescreen/game.go index e160aac8..7394a1c3 100644 --- a/d2game/d2gamescreen/game.go +++ b/d2game/d2gamescreen/game.go @@ -88,7 +88,6 @@ func (v *Game) Advance(tickTime float64) error { tile := v.gameClient.MapEngine.TileAt(v.localPlayer.TileX, v.localPlayer.TileY) if tile != nil { musicInfo := d2common.GetMusicDef(tile.RegionType) - v.localPlayer.SetIsInTown(musicInfo.InTown) d2audio.PlayBGM(musicInfo.MusicFile) // skip showing zone change text the first time we enter the world diff --git a/d2game/d2player/game_controls.go b/d2game/d2player/game_controls.go index 5ec7630f..91a01582 100644 --- a/d2game/d2player/game_controls.go +++ b/d2game/d2player/game_controls.go @@ -337,7 +337,7 @@ func (g *GameControls) isInActiveMenusRect(px int, py int) bool { func (g *GameControls) Render(target d2render.Surface) { for entityIdx := range *g.mapEngine.Entities() { entity := (*g.mapEngine.Entities())[entityIdx] - if entity.Name() == "" { + if !entity.Selectable() { continue } @@ -350,6 +350,7 @@ func (g *GameControls) Render(target d2render.Surface) { g.nameLabel.SetText(entity.Name()) g.nameLabel.SetPosition(entScreenX, entScreenY-100) g.nameLabel.Render(target) + entity.Highlight() break } }