package model import ( "mvvasilev/last_light/engine" "github.com/gdamore/tcell/v2" ) type ItemMetaType int const ( MetaItemType_Physical_Weapon ItemMetaType = iota MetaItemType_Magic_Weapon MetaItemType_Weapon MetaItemType_Physical_Armour MetaItemType_Magic_Armour MetaItemType_Armour MetaItemType_Consumable MetaItemType_Projectile MetaItemType_Potion ) type ProjectileDirection int const ( ProjectileDirection_NorthSouth ProjectileDirection = iota ProjectileDirection_EastWest ProjectileDirection_NorthEastSouthWest ProjectileDirection_NorthWestSouthEast ) type Item interface { TileIcon() rune Icon() string Style() tcell.Style Type() ItemType Quantifiable() *Item_QuantifiableComponent Usable() *Item_UsableComponent Equippable() *Item_EquippableComponent Named() *Item_NamedComponent Described() *Item_DescribedComponent Damaging() *Item_DamagingComponent StatModifier() *Item_StatModifierComponent MetaTypes() *Item_MetaTypesComponent ProjectileData() *Item_ProjectileComponent } type Item_ProjectileComponent struct { Sprites map[ProjectileDirection]rune AdditionalDamageRoll func() (dmg int, dmgType DamageType) } type Item_QuantifiableComponent struct { MaxQuantity int CurrentQuantity int } type Item_UsableComponent struct { IsUsableBy func(Entity) bool Use func(*engine.GameEventLog, *Dungeon, Entity) } type Item_EquippableComponent struct { Slot EquippedSlot } type Item_NamedComponent struct { Name string Style tcell.Style } type Item_DescribedComponent struct { Description string Style tcell.Style } type Item_DamagingComponent struct { IsRanged bool DamageRoll func() (damage int, dmgType DamageType) } type Item_StatModifierComponent struct { StatModifiers []StatModifier } type Item_MetaTypesComponent struct { Types []ItemMetaType } type BaseItem struct { tileIcon rune icon string style tcell.Style itemType ItemType quantifiable *Item_QuantifiableComponent usable *Item_UsableComponent equippable *Item_EquippableComponent named *Item_NamedComponent described *Item_DescribedComponent damaging *Item_DamagingComponent statModifier *Item_StatModifierComponent metaTypes *Item_MetaTypesComponent projectileData *Item_ProjectileComponent } func (i *BaseItem) TileIcon() rune { return i.tileIcon } func (i *BaseItem) Icon() string { return i.icon } func (i *BaseItem) Style() tcell.Style { return i.style } func (i *BaseItem) Type() ItemType { return i.itemType } func (i *BaseItem) Quantifiable() *Item_QuantifiableComponent { return i.quantifiable } func (i *BaseItem) Usable() *Item_UsableComponent { return i.usable } func (i *BaseItem) Equippable() *Item_EquippableComponent { return i.equippable } func (i *BaseItem) Named() *Item_NamedComponent { return i.named } func (i *BaseItem) Described() *Item_DescribedComponent { return i.described } func (i *BaseItem) Damaging() *Item_DamagingComponent { return i.damaging } func (i *BaseItem) StatModifier() *Item_StatModifierComponent { return i.statModifier } func (i *BaseItem) MetaTypes() *Item_MetaTypesComponent { return i.metaTypes } func (i *BaseItem) ProjectileData() *Item_ProjectileComponent { return i.projectileData } func createBaseItem(itemType ItemType, tileIcon rune, icon string, style tcell.Style, components ...func(*BaseItem)) *BaseItem { i := &BaseItem{ itemType: itemType, tileIcon: tileIcon, icon: icon, style: style, } for _, comp := range components { comp(i) } return i } func item_WithQuantity(quantity, maxQuantity int) func(*BaseItem) { return func(bi *BaseItem) { bi.quantifiable = &Item_QuantifiableComponent{ CurrentQuantity: quantity, MaxQuantity: maxQuantity, } } } func item_WithUsable(usabilityCheck func(Entity) bool, useFunc func(*engine.GameEventLog, *Dungeon, Entity)) func(*BaseItem) { return func(bi *BaseItem) { bi.usable = &Item_UsableComponent{ IsUsableBy: usabilityCheck, Use: useFunc, } } } func item_WithEquippable(slot EquippedSlot) func(*BaseItem) { return func(bi *BaseItem) { bi.equippable = &Item_EquippableComponent{ Slot: slot, } } } func item_WithDamaging(isRanged bool, damageFunc func() (damage int, dmgType DamageType)) func(*BaseItem) { return func(bi *BaseItem) { bi.damaging = &Item_DamagingComponent{ IsRanged: isRanged, DamageRoll: damageFunc, } } } func item_WithName(name string, style tcell.Style) func(*BaseItem) { return func(bi *BaseItem) { bi.named = &Item_NamedComponent{ Name: name, Style: style, } } } func item_WithDescription(description string, style tcell.Style) func(*BaseItem) { return func(bi *BaseItem) { bi.described = &Item_DescribedComponent{ Description: description, Style: style, } } } func item_WithStatModifiers(statModifiers []StatModifier) func(*BaseItem) { return func(bi *BaseItem) { bi.statModifier = &Item_StatModifierComponent{ StatModifiers: statModifiers, } } } func item_WithMetaTypes(metaTypes []ItemMetaType) func(*BaseItem) { return func(bi *BaseItem) { bi.metaTypes = &Item_MetaTypesComponent{ Types: metaTypes, } } } func item_WithProjectileData(sprites map[ProjectileDirection]rune, additionalDamageRoll func() (dmg int, dmgType DamageType)) func(*BaseItem) { return func(bi *BaseItem) { bi.projectileData = &Item_ProjectileComponent{ Sprites: sprites, AdditionalDamageRoll: additionalDamageRoll, } } }