last_light/game/model/entity.go
2024-06-06 23:17:22 +03:00

226 lines
4.2 KiB
Go

package model
import (
"mvvasilev/last_light/engine"
"github.com/gdamore/tcell/v2"
"github.com/google/uuid"
)
type Direction int
const (
DirectionNone Direction = iota
North
South
West
East
)
func DirectionName(dir Direction) string {
switch dir {
case North:
return "North"
case South:
return "South"
case West:
return "West"
case East:
return "East"
default:
return "Unknown"
}
}
func MovementDirectionOffset(dir Direction) (int, int) {
switch dir {
case North:
return 0, -1
case South:
return 0, 1
case West:
return -1, 0
case East:
return 1, 0
}
return 0, 0
}
// type Entity interface {
// UniqueId() uuid.UUID
// Presentation() (rune, tcell.Style)
// }
// type MovableEntity interface {
// Position() engine.Position
// MoveTo(newPosition engine.Position)
// Entity
// }
// type EquippedEntity interface {
// Inventory() *EquippedInventory
// Entity
// }
type Entity_NamedComponent struct {
Name string
}
type Entity_DescribedComponent struct {
Description string
}
type Entity_PresentableComponent struct {
Rune rune
Style tcell.Style
}
type Entity_PositionedComponent struct {
Position engine.Position
}
type Entity_EquippedComponent struct {
Inventory *EquippedInventory
}
type Entity_StatsHolderComponent struct {
BaseStats map[Stat]int
// StatModifiers []StatModifier
}
type Entity_HealthComponent struct {
Health int
MaxHealth int
IsDead bool
}
type Entity_V2 interface {
UniqueId() uuid.UUID
Named() *Entity_NamedComponent
Described() *Entity_DescribedComponent
Presentable() *Entity_PresentableComponent
Positioned() *Entity_PositionedComponent
Equipped() *Entity_EquippedComponent
Stats() *Entity_StatsHolderComponent
HealthData() *Entity_HealthComponent
}
type BaseEntity_V2 struct {
id uuid.UUID
named *Entity_NamedComponent
described *Entity_DescribedComponent
presentable *Entity_PresentableComponent
positioned *Entity_PositionedComponent
equipped *Entity_EquippedComponent
stats *Entity_StatsHolderComponent
damageable *Entity_HealthComponent
}
func (be *BaseEntity_V2) UniqueId() uuid.UUID {
return be.id
}
func (be *BaseEntity_V2) Named() *Entity_NamedComponent {
return be.named
}
func (be *BaseEntity_V2) Described() *Entity_DescribedComponent {
return be.described
}
func (be *BaseEntity_V2) Presentable() *Entity_PresentableComponent {
return be.presentable
}
func (be *BaseEntity_V2) Positioned() *Entity_PositionedComponent {
return be.positioned
}
func (be *BaseEntity_V2) Equipped() *Entity_EquippedComponent {
return be.equipped
}
func (be *BaseEntity_V2) Stats() *Entity_StatsHolderComponent {
return be.stats
}
func (be *BaseEntity_V2) HealthData() *Entity_HealthComponent {
return be.damageable
}
func CreateEntity(components ...func(*BaseEntity_V2)) *BaseEntity_V2 {
e := &BaseEntity_V2{
id: uuid.New(),
}
for _, comp := range components {
comp(e)
}
return e
}
func WithName(name string) func(*BaseEntity_V2) {
return func(e *BaseEntity_V2) {
e.named = &Entity_NamedComponent{
Name: name,
}
}
}
func WithDescription(description string) func(e *BaseEntity_V2) {
return func(e *BaseEntity_V2) {
e.described = &Entity_DescribedComponent{
Description: description,
}
}
}
func WithPresentation(symbol rune, style tcell.Style) func(e *BaseEntity_V2) {
return func(e *BaseEntity_V2) {
e.presentable = &Entity_PresentableComponent{
Rune: symbol,
Style: style,
}
}
}
func WithPosition(pos engine.Position) func(e *BaseEntity_V2) {
return func(e *BaseEntity_V2) {
e.positioned = &Entity_PositionedComponent{
Position: pos,
}
}
}
func WithInventory(inv *EquippedInventory) func(e *BaseEntity_V2) {
return func(e *BaseEntity_V2) {
e.equipped = &Entity_EquippedComponent{
Inventory: inv,
}
}
}
func WithStats(baseStats map[Stat]int, statModifiers ...StatModifier) func(e *BaseEntity_V2) {
return func(e *BaseEntity_V2) {
e.stats = &Entity_StatsHolderComponent{
BaseStats: baseStats,
// StatModifiers: statModifiers,
}
}
}
func WithHealthData(health, maxHealth int, isDead bool) func(e *BaseEntity_V2) {
return func(e *BaseEntity_V2) {
e.damageable = &Entity_HealthComponent{
Health: health,
MaxHealth: maxHealth,
IsDead: isDead,
}
}
}