From 6bcb59867e7e9283f2be84bf1a40b1ea6b58d01e Mon Sep 17 00:00:00 2001 From: mvvasilev Date: Sat, 1 Jun 2024 11:20:51 +0300 Subject: [PATCH] Damaging NPCs --- game/npc/entity.go | 10 ++- game/npc/npc.go | 30 +++++-- game/npc/rpg_npc.go | 58 ++++++++++++++ game/player/player.go | 23 +++--- game/rpg/rpg_entity.go | 20 ++++- game/rpg/rpg_items.go | 19 +++-- game/rpg/rpg_system.go | 103 ++++++++++++++++++++++++- game/state/character_creation_state.go | 29 +++---- game/state/playing_state.go | 60 ++++++++++++-- game/world/dungeon.go | 9 ++- game/world/entity_map.go | 18 +++-- game/world/tile.go | 11 +-- 12 files changed, 318 insertions(+), 72 deletions(-) create mode 100644 game/npc/rpg_npc.go diff --git a/game/npc/entity.go b/game/npc/entity.go index 4a72a64..1c528b6 100644 --- a/game/npc/entity.go +++ b/game/npc/entity.go @@ -2,6 +2,7 @@ package npc import ( "mvvasilev/last_light/engine" + "mvvasilev/last_light/game/item" "github.com/gdamore/tcell/v2" "github.com/google/uuid" @@ -49,8 +50,7 @@ func MovementDirectionOffset(dir Direction) (int, int) { type Entity interface { UniqueId() uuid.UUID - Input(e *tcell.EventKey) - Tick(dt int64) + Presentation() (rune, tcell.Style) } type MovableEntity interface { @@ -59,3 +59,9 @@ type MovableEntity interface { Entity } + +type EquippedEntity interface { + Inventory() *item.EquippedInventory + + Entity +} diff --git a/game/npc/npc.go b/game/npc/npc.go index 8aa4b47..58a2ae5 100644 --- a/game/npc/npc.go +++ b/game/npc/npc.go @@ -7,18 +7,34 @@ import ( "github.com/google/uuid" ) +type NPC interface { + Name() string + + MovableEntity +} + type BasicNPC struct { - id uuid.UUID + id uuid.UUID + name string + presentation rune + style tcell.Style engine.Positioned } -func CreateNPC(pos engine.Position) *BasicNPC { +func CreateNPC(pos engine.Position, name string, presentation rune, style tcell.Style) *BasicNPC { return &BasicNPC{ - id: uuid.New(), - Positioned: engine.WithPosition(pos), + id: uuid.New(), + name: name, + presentation: presentation, + style: style, + Positioned: engine.WithPosition(pos), } } +func (c *BasicNPC) Name() string { + return c.name +} + func (c *BasicNPC) MoveTo(newPosition engine.Position) { c.Positioned.SetPosition(newPosition) } @@ -27,8 +43,6 @@ func (c *BasicNPC) UniqueId() uuid.UUID { return c.id } -func (c *BasicNPC) Input(e *tcell.EventKey) { -} - -func (c *BasicNPC) Tick(dt int64) { +func (c *BasicNPC) Presentation() (rune, tcell.Style) { + return c.presentation, c.style } diff --git a/game/npc/rpg_npc.go b/game/npc/rpg_npc.go new file mode 100644 index 0000000..559008e --- /dev/null +++ b/game/npc/rpg_npc.go @@ -0,0 +1,58 @@ +package npc + +import ( + "mvvasilev/last_light/engine" + "mvvasilev/last_light/game/item" + "mvvasilev/last_light/game/rpg" + + "github.com/gdamore/tcell/v2" +) + +type RPGNPC interface { + NPC + rpg.RPGEntity + EquippedEntity +} + +type BasicRPGNPC struct { + inventory *item.EquippedInventory + + *BasicNPC + *rpg.BasicRPGEntity +} + +func CreateRPGNPC(x, y int, name string, representation rune, style tcell.Style, stats map[rpg.Stat]int) *BasicRPGNPC { + rpgnpc := &BasicRPGNPC{ + inventory: item.CreateEquippedInventory(), + BasicNPC: CreateNPC( + engine.PositionAt(x, y), + name, + representation, + style, + ), + BasicRPGEntity: rpg.CreateBasicRPGEntity( + 0, + stats, + map[rpg.Stat][]rpg.StatModifier{}, + ), + } + + rpgnpc.Heal(rpg.BaseMaxHealth(rpgnpc)) + + return rpgnpc +} + +func (rnpc *BasicRPGNPC) Inventory() *item.EquippedInventory { + return rnpc.inventory +} + +func (p *BasicRPGNPC) CalculateAttack(other rpg.RPGEntity) (hit bool, precisionRoll, evasionRoll int, damage int, damageType rpg.DamageType) { + mainHand := p.inventory.AtSlot(item.EquippedSlotDominantHand) + + switch mh := mainHand.(type) { + case rpg.RPGItem: + return rpg.PhysicalWeaponAttack(p, mh, other) + default: + return rpg.UnarmedAttack(p, other) + } +} diff --git a/game/player/player.go b/game/player/player.go index 20a05b4..4507560 100644 --- a/game/player/player.go +++ b/game/player/player.go @@ -25,10 +25,13 @@ func CreatePlayer(x, y int, playerStats map[rpg.Stat]int) *Player { p.position = engine.PositionAt(x, y) p.inventory = item.CreateEquippedInventory() p.BasicRPGEntity = rpg.CreateBasicRPGEntity( + 0, playerStats, map[rpg.Stat][]rpg.StatModifier{}, ) + p.Heal(rpg.BaseMaxHealth(p)) + return p } @@ -48,21 +51,17 @@ func (p *Player) Presentation() (rune, tcell.Style) { return '@', tcell.StyleDefault } -func (p *Player) Passable() bool { - return false -} - -func (p *Player) Transparent() bool { - return false -} - func (p *Player) Inventory() *item.EquippedInventory { return p.inventory } -func (p *Player) Input(e *tcell.EventKey) { -} - -func (p *Player) Tick(dt int64) { +func (p *Player) CalculateAttack(other rpg.RPGEntity) (hit bool, precisionRoll, evasionRoll int, damage int, damageType rpg.DamageType) { + mainHand := p.inventory.AtSlot(item.EquippedSlotDominantHand) + switch mh := mainHand.(type) { + case rpg.RPGItem: + return rpg.PhysicalWeaponAttack(p, mh, other) + default: + return rpg.UnarmedAttack(p, other) + } } diff --git a/game/rpg/rpg_entity.go b/game/rpg/rpg_entity.go index e59b066..ba4f565 100644 --- a/game/rpg/rpg_entity.go +++ b/game/rpg/rpg_entity.go @@ -1,5 +1,7 @@ package rpg +import "slices" + type RPGEntity interface { BaseStat(stat Stat) int SetBaseStat(stat Stat, value int) @@ -11,6 +13,8 @@ type RPGEntity interface { CurrentHealth() int Heal(health int) Damage(damage int) + + CalculateAttack(other RPGEntity) (hit bool, precisionRoll, evasionRoll int, damage int, damageType DamageType) } type BasicRPGEntity struct { @@ -21,11 +25,11 @@ type BasicRPGEntity struct { currentHealth int } -func CreateBasicRPGEntity(baseStats map[Stat]int, statModifiers map[Stat][]StatModifier) *BasicRPGEntity { +func CreateBasicRPGEntity(health int, baseStats map[Stat]int, statModifiers map[Stat][]StatModifier) *BasicRPGEntity { return &BasicRPGEntity{ stats: baseStats, statModifiers: statModifiers, - currentHealth: 0, + currentHealth: health, } } @@ -60,7 +64,13 @@ func (brpg *BasicRPGEntity) AddStatModifier(modifier StatModifier) { } func (brpg *BasicRPGEntity) RemoveStatModifier(id StatModifierId) { - // TODO + for k, v := range brpg.statModifiers { + for i, sm := range v { + if sm.Id == id { + brpg.statModifiers[k] = slices.Delete(v, i, i+1) + } + } + } } func (brpg *BasicRPGEntity) CurrentHealth() int { @@ -88,3 +98,7 @@ func (brpg *BasicRPGEntity) Damage(damage int) { brpg.currentHealth -= damage } + +func (brpg *BasicRPGEntity) CalculateAttack(other RPGEntity) (hit bool, precisionRoll, evasionRoll int, damage int, damageType DamageType) { + return UnarmedAttack(brpg, other) +} diff --git a/game/rpg/rpg_items.go b/game/rpg/rpg_items.go index f323dc7..62dfdb1 100644 --- a/game/rpg/rpg_items.go +++ b/game/rpg/rpg_items.go @@ -24,12 +24,6 @@ type RPGItemType interface { item.ItemType } -type RPGItem interface { - Modifiers() []StatModifier - - item.Item -} - type BasicRPGItemType struct { damageRollFunc func(victim, attacker RPGEntity) (damage int, dmgType DamageType) @@ -258,8 +252,16 @@ func ItemTypeSpear() RPGItemType { } } +type RPGItem interface { + Modifiers() []StatModifier + RPGType() RPGItemType + + item.Item +} + type BasicRPGItem struct { modifiers []StatModifier + rpgType RPGItemType item.BasicItem } @@ -268,9 +270,14 @@ func (i *BasicRPGItem) Modifiers() []StatModifier { return i.modifiers } +func (i *BasicRPGItem) RPGType() RPGItemType { + return i.rpgType +} + func CreateRPGItem(name string, style tcell.Style, itemType RPGItemType, modifiers []StatModifier) RPGItem { return &BasicRPGItem{ modifiers: modifiers, + rpgType: itemType, BasicItem: item.CreateBasicItemWithName( name, style, diff --git a/game/rpg/rpg_system.go b/game/rpg/rpg_system.go index fd86903..132af13 100644 --- a/game/rpg/rpg_system.go +++ b/game/rpg/rpg_system.go @@ -2,6 +2,7 @@ package rpg import ( "math/rand" + "mvvasilev/last_light/engine" ) type Stat int @@ -51,6 +52,36 @@ func StatLongName(stat Stat) string { } } +func RandomStats(pointsAvailable int, min, max int, stats []Stat) (result map[Stat]int) { + result = map[Stat]int{} + + for { + if pointsAvailable == 0 { + break + } + + for _, s := range stats { + if pointsAvailable == 0 { + break + } + + limit := pointsAvailable + + if limit > max { + limit = max + } + + value := engine.RandInt(min+1, limit+min) + + result[s] += value + + pointsAvailable -= value - min + } + } + + return +} + type StatModifierId string type StatModifier struct { @@ -129,6 +160,33 @@ const ( DamageType_Magic_Poison DamageType = 9 ) +func DamageTypeName(dmgType DamageType) string { + switch dmgType { + case DamageType_Physical_Unarmed: + return "Unarmed" + case DamageType_Physical_Slashing: + return "Slashing" + case DamageType_Physical_Piercing: + return "Piercing" + case DamageType_Physical_Bludgeoning: + return "Bludgeoning" + case DamageType_Magic_Fire: + return "Fire" + case DamageType_Magic_Cold: + return "Cold" + case DamageType_Magic_Necrotic: + return "Necrotic" + case DamageType_Magic_Thunder: + return "Thunder" + case DamageType_Magic_Acid: + return "Acid" + case DamageType_Magic_Poison: + return "Poison" + default: + return "Unknown" + } +} + func DamageTypeToBonusStat(dmgType DamageType) Stat { switch dmgType { case DamageType_Physical_Unarmed: @@ -142,7 +200,7 @@ func DamageTypeToBonusStat(dmgType DamageType) Stat { case DamageType_Magic_Fire: return Stat_DamageBonus_Magic_Fire case DamageType_Magic_Cold: - return Stat_DamageBonus_Magic_Fire + return Stat_DamageBonus_Magic_Cold case DamageType_Magic_Necrotic: return Stat_DamageBonus_Magic_Necrotic case DamageType_Magic_Thunder: @@ -201,8 +259,12 @@ func MagicHitRoll(attacker RPGEntity, victim RPGEntity) bool { } // true = hit lands, false = hit does not land -func PhysicalHitRoll(attacker RPGEntity, victim RPGEntity) bool { - return hitRoll(EvasionRoll(victim), PhysicalPrecisionRoll(attacker)) +func PhysicalHitRoll(attacker RPGEntity, victim RPGEntity) (hit bool, evasion, precision int) { + evasion = EvasionRoll(victim) + precision = PhysicalPrecisionRoll(attacker) + hit = hitRoll(evasion, precision) + + return } func hitRoll(evasionRoll, precisionRoll int) bool { @@ -212,3 +274,38 @@ func hitRoll(evasionRoll, precisionRoll int) bool { func UnarmedDamage(attacker RPGEntity) int { return RollD4(1) + StatValue(attacker, Stat_DamageBonus_Physical_Unarmed) } + +func PhysicalWeaponDamange(attacker RPGEntity, weapon RPGItem, victim RPGEntity) (totalDamage int, dmgType DamageType) { + totalDamage, dmgType = weapon.RPGType().RollDamage()(victim, attacker) + + bonusDmgStat := DamageTypeToBonusStat(dmgType) + + totalDamage = totalDamage + StatValue(attacker, bonusDmgStat) + + return +} + +func UnarmedAttack(attacker RPGEntity, victim RPGEntity) (hit bool, precisionRoll, evasionRoll int, damage int, damageType DamageType) { + hit, evasionRoll, precisionRoll = PhysicalHitRoll(attacker, victim) + + if !hit { + return + } + + damage = UnarmedDamage(attacker) + damageType = DamageType_Physical_Unarmed + + return +} + +func PhysicalWeaponAttack(attacker RPGEntity, weapon RPGItem, victim RPGEntity) (hit bool, precisionRoll, evasionRoll int, damage int, damageType DamageType) { + hit, evasionRoll, precisionRoll = PhysicalHitRoll(attacker, victim) + + if !hit { + return + } + + damage, damageType = PhysicalWeaponDamange(attacker, weapon, victim) + + return +} diff --git a/game/state/character_creation_state.go b/game/state/character_creation_state.go index 474de3c..003291f 100644 --- a/game/state/character_creation_state.go +++ b/game/state/character_creation_state.go @@ -58,21 +58,16 @@ func CreateCharacterCreationState(turnSystem *turns.TurnSystem, inputSystem *inp } ccs.menuState.RandomizeCharacter = func() { - ccs.menuState.AvailablePoints = 21 + stats := rpg.RandomStats(21, 1, 20, []rpg.Stat{rpg.Stat_Attributes_Strength, rpg.Stat_Attributes_Constitution, rpg.Stat_Attributes_Intelligence, rpg.Stat_Attributes_Dexterity}) - for _, s := range ccs.menuState.Stats { - if ccs.menuState.AvailablePoints == 0 { - break - } + ccs.menuState.AvailablePoints = 0 + ccs.menuState.Stats = []*menu.StatState{} - limit := ccs.menuState.AvailablePoints - - if limit > 20 { - limit = 20 - } - - s.Value = engine.RandInt(1, limit+1) - ccs.menuState.AvailablePoints -= s.Value - 1 + for k, v := range stats { + ccs.menuState.Stats = append(ccs.menuState.Stats, &menu.StatState{ + Stat: k, + Value: v, + }) } ccs.ccMenu.UpdateState(ccs.menuState) @@ -147,8 +142,16 @@ func (ccs *CharacterCreationState) OnTick(dt int64) GameState { case input.InputAction_Menu_HighlightLeft: ccs.DecreaseStatValue() case input.InputAction_Menu_HighlightDown: + if ccs.menuState.CurrentHighlight > len(ccs.menuState.Stats) { + break + } + ccs.menuState.CurrentHighlight++ case input.InputAction_Menu_HighlightUp: + if ccs.menuState.CurrentHighlight == 0 { + break + } + ccs.menuState.CurrentHighlight-- case input.InputAction_Menu_Select: ccs.ccMenu.SelectHighlight() diff --git a/game/state/playing_state.go b/game/state/playing_state.go index 456427b..7ad0686 100644 --- a/game/state/playing_state.go +++ b/game/state/playing_state.go @@ -1,6 +1,7 @@ package state import ( + "fmt" "mvvasilev/last_light/engine" "mvvasilev/last_light/game/input" "mvvasilev/last_light/game/npc" @@ -19,7 +20,7 @@ type PlayingState struct { inputSystem *input.InputSystem player *player.Player - someNPC *npc.BasicNPC + someNPC npc.RPGNPC eventLog *engine.GameEventLog uiEventLog *ui.UIEventLog @@ -52,7 +53,6 @@ func CreatePlayingState(turnSystem *turns.TurnSystem, inputSystem *input.InputSy s.dungeon.CurrentLevel().PlayerSpawnPoint().Y(), playerStats, ) - s.player.Heal(rpg.BaseMaxHealth(s.player)) s.turnSystem.Schedule(10, func() (complete bool, requeue bool) { requeue = true @@ -89,7 +89,14 @@ func CreatePlayingState(turnSystem *turns.TurnSystem, inputSystem *input.InputSy return }) - s.someNPC = npc.CreateNPC(s.dungeon.CurrentLevel().NextLevelStaircase()) + s.someNPC = npc.CreateRPGNPC( + s.dungeon.CurrentLevel().NextLevelStaircase().X(), + s.dungeon.CurrentLevel().NextLevelStaircase().Y(), + "NPC", + 'n', + tcell.StyleDefault, + rpg.RandomStats(21, 1, 20, []rpg.Stat{rpg.Stat_Attributes_Strength, rpg.Stat_Attributes_Constitution, rpg.Stat_Attributes_Intelligence, rpg.Stat_Attributes_Dexterity}), + ) s.turnSystem.Schedule(20, func() (complete bool, requeue bool) { s.CalcPathToPlayerAndMove() @@ -102,8 +109,8 @@ func CreatePlayingState(turnSystem *turns.TurnSystem, inputSystem *input.InputSy s.uiEventLog = ui.CreateUIEventLog(0, 17, 80, 7, s.eventLog, tcell.StyleDefault) s.healthBar = ui.CreateHealthBar(68, 0, 12, 3, s.player.CurrentHealth(), rpg.BaseMaxHealth(s.player), tcell.StyleDefault) - s.dungeon.CurrentLevel().AddEntity(s.player, '@', tcell.StyleDefault) - s.dungeon.CurrentLevel().AddEntity(s.someNPC, 'N', tcell.StyleDefault) + s.dungeon.CurrentLevel().AddEntity(s.player) + s.dungeon.CurrentLevel().AddEntity(s.someNPC) s.viewport = engine.CreateViewport( engine.PositionAt(0, 0), @@ -132,9 +139,27 @@ func (ps *PlayingState) MovePlayer(direction npc.Direction) { dx, dy := npc.MovementDirectionOffset(direction) ps.dungeon.CurrentLevel().MoveEntity(ps.player.UniqueId(), dx, dy) ps.viewport.SetCenter(ps.player.Position()) + + ps.eventLog.Log("You moved " + npc.DirectionName(direction)) } - ps.eventLog.Log("You moved " + npc.DirectionName(direction)) + ent := ps.dungeon.CurrentLevel().EntityAt(newPlayerPos.XY()) + + // We are moving into an entity. Attack it. + if ent != nil { + switch rpge := ent.(type) { + case npc.RPGNPC: + hit, precision, evasion, dmg, dmgType := ps.player.CalculateAttack(rpge) + + if !hit { + ps.eventLog.Log(fmt.Sprintf("You attacked %v, but missed ( %v Evasion vs %v Precision)", rpge.Name(), evasion, precision)) + return + } + + rpge.Damage(dmg) + ps.eventLog.Log(fmt.Sprintf("You attacked %v, and hit for %v %v damage", rpge.Name(), dmg, rpg.DamageTypeName(dmgType))) + } + } } func (ps *PlayingState) InteractBelowPlayer() { @@ -184,7 +209,7 @@ func (ps *PlayingState) SwitchToNextLevel() { tcell.StyleDefault, ) - ps.dungeon.CurrentLevel().AddEntity(ps.player, '@', tcell.StyleDefault) + ps.dungeon.CurrentLevel().AddEntity(ps.player) } func (ps *PlayingState) SwitchToPreviousLevel() { @@ -220,7 +245,7 @@ func (ps *PlayingState) SwitchToPreviousLevel() { tcell.StyleDefault, ) - ps.dungeon.CurrentLevel().AddEntity(ps.player, '@', tcell.StyleDefault) + ps.dungeon.CurrentLevel().AddEntity(ps.player) } func (ps *PlayingState) PickUpItemUnderPlayer() { @@ -255,6 +280,10 @@ func (ps *PlayingState) HasLineOfSight(start, end engine.Position) bool { return true } +func (ps *PlayingState) PlayerWithinHitRange(pos engine.Position) bool { + return pos.WithOffset(-1, 0) == ps.player.Position() || pos.WithOffset(+1, 0) == ps.player.Position() || pos.WithOffset(0, -1) == ps.player.Position() || pos.WithOffset(0, +1) == ps.player.Position() +} + func (ps *PlayingState) CalcPathToPlayerAndMove() { playerVisibleAndInRange := false @@ -291,6 +320,21 @@ func (ps *PlayingState) CalcPathToPlayerAndMove() { return } + if ps.PlayerWithinHitRange(ps.someNPC.Position()) { + hit, precision, evasion, dmg, dmgType := ps.player.CalculateAttack(ps.player) + + if !hit { + ps.eventLog.Log(fmt.Sprintf("%v attacked you, but missed ( %v Evasion vs %v Precision)", ps.someNPC.Name(), evasion, precision)) + return + } + + ps.player.Damage(dmg) + ps.healthBar.SetHealth(ps.player.CurrentHealth()) + ps.eventLog.Log(fmt.Sprintf("%v attacked you, and hit for %v %v damage", ps.someNPC.Name(), dmg, rpg.DamageTypeName(dmgType))) + + return + } + pathToPlayer := engine.FindPath( ps.someNPC.Position(), ps.player.Position(), diff --git a/game/world/dungeon.go b/game/world/dungeon.go index f0872e3..c7abb1d 100644 --- a/game/world/dungeon.go +++ b/game/world/dungeon.go @@ -8,7 +8,6 @@ import ( "mvvasilev/last_light/game/rpg" "slices" - "github.com/gdamore/tcell/v2" "github.com/google/uuid" ) @@ -240,8 +239,8 @@ func (d *DungeonLevel) DropEntity(uuid uuid.UUID) { d.entityLevel.DropEntity(uuid) } -func (d *DungeonLevel) AddEntity(entity npc.MovableEntity, presentation rune, style tcell.Style) { - d.entityLevel.AddEntity(entity, presentation, style) +func (d *DungeonLevel) AddEntity(entity npc.MovableEntity) { + d.entityLevel.AddEntity(entity) } func (d *DungeonLevel) MoveEntity(uuid uuid.UUID, dx, dy int) { @@ -291,6 +290,10 @@ func (d *DungeonLevel) IsTilePassable(x, y int) bool { return d.TileAt(x, y).Passable() } +func (d *DungeonLevel) EntityAt(x, y int) (e npc.MovableEntity) { + return d.entityLevel.EntityAt(x, y) +} + func (d *DungeonLevel) IsGroundTileOpaque(x, y int) bool { if !d.groundLevel.Size().Contains(x, y) { return false diff --git a/game/world/entity_map.go b/game/world/entity_map.go index f294276..c7ab689 100644 --- a/game/world/entity_map.go +++ b/game/world/entity_map.go @@ -5,7 +5,6 @@ import ( "mvvasilev/last_light/engine" "mvvasilev/last_light/game/npc" - "github.com/gdamore/tcell/v2" "github.com/google/uuid" ) @@ -43,13 +42,13 @@ func (em *EntityMap) FindEntityByUuid(uuid uuid.UUID) (key int, entity EntityTil return -1, nil } -func (em *EntityMap) AddEntity(entity npc.MovableEntity, presentation rune, style tcell.Style) { +func (em *EntityMap) AddEntity(entity npc.MovableEntity) { if !em.FitsWithin(entity.Position().XY()) { return } key := em.Size().AsArrayIndex(entity.Position().XY()) - et := CreateBasicEntityTile(entity, presentation, style) + et := CreateBasicEntityTile(entity) em.entities[key] = et } @@ -111,6 +110,16 @@ func (em *EntityMap) TileAt(x int, y int) Tile { return em.entities[key] } +func (em *EntityMap) EntityAt(x, y int) (ent npc.MovableEntity) { + tile := em.TileAt(x, y) + + if tile == nil { + return nil + } + + return tile.(EntityTile).Entity() +} + func (em *EntityMap) IsInBounds(x, y int) bool { return em.FitsWithin(x, y) } @@ -124,7 +133,4 @@ func (em *EntityMap) ExploredTileAt(x, y int) Tile { } func (em *EntityMap) Tick(dt int64) { - for _, e := range em.entities { - e.Entity().Tick(dt) - } } diff --git a/game/world/tile.go b/game/world/tile.go index ed277a1..48b8f31 100644 --- a/game/world/tile.go +++ b/game/world/tile.go @@ -237,16 +237,11 @@ type EntityTile interface { type BasicEntityTile struct { entity npc.MovableEntity - - presentation rune - style tcell.Style } -func CreateBasicEntityTile(entity npc.MovableEntity, presentation rune, style tcell.Style) *BasicEntityTile { +func CreateBasicEntityTile(entity npc.MovableEntity) *BasicEntityTile { return &BasicEntityTile{ - entity: entity, - presentation: presentation, - style: style, + entity: entity, } } @@ -259,7 +254,7 @@ func (bet *BasicEntityTile) Position() engine.Position { } func (bet *BasicEntityTile) Presentation() (rune, tcell.Style) { - return bet.presentation, bet.style + return bet.entity.Presentation() } func (bet *BasicEntityTile) Passable() bool {