last_light/game/model/entity.go

253 lines
4.8 KiB
Go
Raw Normal View History

2024-06-06 23:17:22 +03:00
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_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
}
type Entity_BehaviorComponent struct {
Speed int
Behavior func() (complete, requeue bool)
}
2024-06-06 23:17:22 +03:00
type Entity_HealthComponent struct {
Health int
MaxHealth int
IsDead bool
}
type Entity_DropTableComponent struct {
DropTable *LootTable
}
2024-06-06 23:28:06 +03:00
type Entity interface {
2024-06-06 23:17:22 +03:00
UniqueId() uuid.UUID
Behavior() *Entity_BehaviorComponent
2024-06-06 23:17:22 +03:00
Named() *Entity_NamedComponent
Described() *Entity_DescribedComponent
Presentable() *Entity_PresentableComponent
Positioned() *Entity_PositionedComponent
Equipped() *Entity_EquippedComponent
Stats() *Entity_StatsHolderComponent
HealthData() *Entity_HealthComponent
DropTable() *Entity_DropTableComponent
2024-06-06 23:17:22 +03:00
}
2024-06-06 23:28:06 +03:00
type BaseEntity struct {
2024-06-06 23:17:22 +03:00
id uuid.UUID
behavior *Entity_BehaviorComponent
2024-06-06 23:17:22 +03:00
named *Entity_NamedComponent
described *Entity_DescribedComponent
presentable *Entity_PresentableComponent
positioned *Entity_PositionedComponent
equipped *Entity_EquippedComponent
stats *Entity_StatsHolderComponent
damageable *Entity_HealthComponent
dropTable *Entity_DropTableComponent
2024-06-06 23:17:22 +03:00
}
2024-06-06 23:28:06 +03:00
func (be *BaseEntity) UniqueId() uuid.UUID {
2024-06-06 23:17:22 +03:00
return be.id
}
2024-06-06 23:28:06 +03:00
func (be *BaseEntity) Named() *Entity_NamedComponent {
2024-06-06 23:17:22 +03:00
return be.named
}
2024-06-06 23:28:06 +03:00
func (be *BaseEntity) Described() *Entity_DescribedComponent {
2024-06-06 23:17:22 +03:00
return be.described
}
2024-06-06 23:28:06 +03:00
func (be *BaseEntity) Presentable() *Entity_PresentableComponent {
2024-06-06 23:17:22 +03:00
return be.presentable
}
2024-06-06 23:28:06 +03:00
func (be *BaseEntity) Positioned() *Entity_PositionedComponent {
2024-06-06 23:17:22 +03:00
return be.positioned
}
2024-06-06 23:28:06 +03:00
func (be *BaseEntity) Equipped() *Entity_EquippedComponent {
2024-06-06 23:17:22 +03:00
return be.equipped
}
2024-06-06 23:28:06 +03:00
func (be *BaseEntity) Stats() *Entity_StatsHolderComponent {
2024-06-06 23:17:22 +03:00
return be.stats
}
2024-06-06 23:28:06 +03:00
func (be *BaseEntity) HealthData() *Entity_HealthComponent {
2024-06-06 23:17:22 +03:00
return be.damageable
}
func (be *BaseEntity) Behavior() *Entity_BehaviorComponent {
return be.behavior
}
func (be *BaseEntity) DropTable() *Entity_DropTableComponent {
return be.dropTable
}
2024-06-06 23:28:06 +03:00
func CreateEntity(components ...func(*BaseEntity)) *BaseEntity {
e := &BaseEntity{
2024-06-06 23:17:22 +03:00
id: uuid.New(),
}
for _, comp := range components {
comp(e)
}
return e
}
2024-06-06 23:28:06 +03:00
func WithName(name string) func(*BaseEntity) {
return func(e *BaseEntity) {
2024-06-06 23:17:22 +03:00
e.named = &Entity_NamedComponent{
Name: name,
}
}
}
2024-06-06 23:28:06 +03:00
func WithDescription(description string) func(e *BaseEntity) {
return func(e *BaseEntity) {
2024-06-06 23:17:22 +03:00
e.described = &Entity_DescribedComponent{
Description: description,
}
}
}
2024-06-06 23:28:06 +03:00
func WithPresentation(symbol rune, style tcell.Style) func(e *BaseEntity) {
return func(e *BaseEntity) {
2024-06-06 23:17:22 +03:00
e.presentable = &Entity_PresentableComponent{
Rune: symbol,
Style: style,
}
}
}
2024-06-06 23:28:06 +03:00
func WithPosition(pos engine.Position) func(e *BaseEntity) {
return func(e *BaseEntity) {
2024-06-06 23:17:22 +03:00
e.positioned = &Entity_PositionedComponent{
Position: pos,
}
}
}
2024-06-06 23:28:06 +03:00
func WithInventory(inv *EquippedInventory) func(e *BaseEntity) {
return func(e *BaseEntity) {
2024-06-06 23:17:22 +03:00
e.equipped = &Entity_EquippedComponent{
Inventory: inv,
}
}
}
2024-06-06 23:28:06 +03:00
func WithStats(baseStats map[Stat]int, statModifiers ...StatModifier) func(e *BaseEntity) {
return func(e *BaseEntity) {
2024-06-06 23:17:22 +03:00
e.stats = &Entity_StatsHolderComponent{
BaseStats: baseStats,
}
}
}
2024-06-06 23:28:06 +03:00
func WithHealthData(health, maxHealth int, isDead bool) func(e *BaseEntity) {
return func(e *BaseEntity) {
2024-06-06 23:17:22 +03:00
e.damageable = &Entity_HealthComponent{
Health: health,
MaxHealth: maxHealth,
IsDead: isDead,
}
}
}
func WithBehavior(speed int, behavior func(npc Entity) (complete, requeue bool)) func(e *BaseEntity) {
return func(e *BaseEntity) {
e.behavior = &Entity_BehaviorComponent{
Speed: speed,
Behavior: func() (complete bool, requeue bool) {
return behavior(e)
},
}
}
}
func WithDropTable(table map[int]ItemSupplier) func(e *BaseEntity) {
dropTable := CreateLootTable()
for k, v := range table {
dropTable.Add(k, v)
}
return func(e *BaseEntity) {
e.dropTable = &Entity_DropTableComponent{
DropTable: dropTable,
}
}
}