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
|
|
|
|
}
|
|
|
|
|
2024-06-08 15:33:18 +03:00
|
|
|
type Entity_BehaviorComponent struct {
|
|
|
|
Speed int
|
|
|
|
Behavior func() (complete, requeue bool)
|
2024-06-07 23:02:17 +03:00
|
|
|
}
|
|
|
|
|
2024-06-06 23:17:22 +03:00
|
|
|
type Entity_HealthComponent struct {
|
|
|
|
Health int
|
|
|
|
MaxHealth int
|
|
|
|
IsDead bool
|
|
|
|
}
|
|
|
|
|
2024-06-08 15:33:18 +03:00
|
|
|
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
|
|
|
|
|
2024-06-08 15:33:18 +03:00
|
|
|
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
|
2024-06-08 15:33:18 +03:00
|
|
|
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
|
|
|
|
|
2024-06-08 15:33:18 +03:00
|
|
|
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
|
2024-06-08 15:33:18 +03:00
|
|
|
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
|
|
|
|
}
|
|
|
|
|
2024-06-08 15:33:18 +03:00
|
|
|
func (be *BaseEntity) Behavior() *Entity_BehaviorComponent {
|
|
|
|
return be.behavior
|
|
|
|
}
|
|
|
|
|
|
|
|
func (be *BaseEntity) DropTable() *Entity_DropTableComponent {
|
|
|
|
return be.dropTable
|
2024-06-07 23:02:17 +03:00
|
|
|
}
|
|
|
|
|
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,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2024-06-07 23:02:17 +03:00
|
|
|
|
2024-06-08 15:33:18 +03:00
|
|
|
func WithBehavior(speed int, behavior func(npc Entity) (complete, requeue bool)) func(e *BaseEntity) {
|
2024-06-07 23:02:17 +03:00
|
|
|
return func(e *BaseEntity) {
|
2024-06-08 15:33:18 +03:00
|
|
|
e.behavior = &Entity_BehaviorComponent{
|
2024-06-07 23:02:17 +03:00
|
|
|
Speed: speed,
|
2024-06-08 15:33:18 +03:00
|
|
|
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,
|
2024-06-07 23:02:17 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|