Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion pkg/conditional/conditional.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,11 @@ func Eval(c *core.Core, fields []string) (any, error) {
if key, ok := shortcut.CharNameToKey[name]; ok {
return evalCharacter(c, key, fields)
}
return 0, fmt.Errorf("invalid character %v in character condition", name)

if trg, err := parseTarget(c, name); err == nil {
return evalTarget(c, trg, fields)
}

return 0, fmt.Errorf("invalid token %v in condition", name)
}
}
63 changes: 43 additions & 20 deletions pkg/conditional/enemy.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@ package conditional

import (
"fmt"
"log"
"regexp"
"strconv"
"strings"

"github.com/genshinsim/gcsim/pkg/core"
"github.com/genshinsim/gcsim/pkg/core/attributes"
Expand All @@ -12,7 +13,35 @@ import (
"github.com/genshinsim/gcsim/pkg/reactable"
)

func evalDebuff(c *core.Core, fields []string) (bool, error) {
func evalTarget(c *core.Core, trg *enemy.Enemy, fields []string) (any, error) {
typ := fields[1]
switch typ {
case "mods", "status":
if err := fieldsCheck(fields, 3, "target "+typ); err != nil {
return 0, err
}
return trg.StatusDuration(fields[2]), nil
case "element":
if err := fieldsCheck(fields, 3, "target "+typ); err != nil {
return 0, err
}
ele := fields[2]
elekey := attributes.StringToEle(ele)
if elekey == attributes.UnknownElement {
return 0, fmt.Errorf("bad element condition: invalid element %v", ele)
}
result := combat.Durability(0)
for i := reactable.ModifierInvalid; i < reactable.EndReactableModifier; i++ {
if i.Element() == elekey && trg.Durability[i] > reactable.ZeroDur && trg.Durability[i] > result {
result = trg.Durability[i]
}
}
return float64(result), nil
}
return nil, fmt.Errorf("bad target condition: invalid type %v", typ)
}

func evalDebuff(c *core.Core, fields []string) (any, error) {
//.debuff.res.t1.name
if err := fieldsCheck(fields, 4, "debuff"); err != nil {
return false, err
Expand All @@ -27,16 +56,15 @@ func evalDebuff(c *core.Core, fields []string) (bool, error) {
}

switch typ {
case "def":
return e.DefModIsActive(mod), nil
case "res":
return e.ResistModIsActive(mod), nil
case "def", "res":
log.Printf("WARN: .debuff.%v.t0.%v is deprecated, use .target0.mods.%v", typ, mod, mod)
return e.StatusIsActive(mod), nil
default:
return false, fmt.Errorf("bad debuff condition: invalid type %v", typ)
}
}

func evalElement(c *core.Core, fields []string) (float64, error) {
func evalElement(c *core.Core, fields []string) (any, error) {
//.element.t1.pyro
if err := fieldsCheck(fields, 3, "element"); err != nil {
return 0, err
Expand All @@ -49,22 +77,17 @@ func evalElement(c *core.Core, fields []string) (float64, error) {
return 0, fmt.Errorf("bad element condition: %v", err)
}

elekey := attributes.StringToEle(ele)
if elekey == attributes.UnknownElement {
return 0, fmt.Errorf("bad element condition: invalid element %v", ele)
}
result := combat.Durability(0)
for i := reactable.ModifierInvalid; i < reactable.EndReactableModifier; i++ {
if i.Element() == elekey && e.Durability[i] > reactable.ZeroDur && e.Durability[i] > result {
result = e.Durability[i]
}
}
return float64(result), nil
log.Printf("WARN: .element.t0.%v is deprecated, use .target0.element.%v", ele, ele)
return evalTarget(c, e, []string{"", "element", ele})
}

func parseTarget(c *core.Core, trg string) (*enemy.Enemy, error) {
trg = strings.TrimPrefix(trg, "t")
tid, err := strconv.ParseInt(trg, 10, 64)
pat := regexp.MustCompile(`t(?:arget)?(\d+)`)
matches := pat.FindStringSubmatch(trg)
if len(matches) < 2 {
return nil, fmt.Errorf("invalid target %v", trg)
}
tid, err := strconv.ParseInt(matches[1], 10, 64)
if err != nil {
return nil, fmt.Errorf("invalid target %v", trg)
}
Expand Down
18 changes: 15 additions & 3 deletions pkg/enemy/mods.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,21 +77,33 @@ func (e *Enemy) StatusIsActive(key string) bool { return e.modIsActive(key) }
func (e *Enemy) ResistModIsActive(key string) bool { return e.modIsActive(key) }
func (e *Enemy) DefModIsActive(key string) bool { return e.modIsActive(key) }

//Expiry
// Duration
func (e *Enemy) getModDuration(key string) int {
m := modifier.Find(&e.mods, key)
if m == -1 {
return 0
}
if e.mods[m].Expiry() > e.Core.F {
return e.mods[m].Expiry() - e.Core.F
}
return 0
}
func (e *Enemy) StatusDuration(key string) int { return e.getModDuration(key) }

// Expiry
func (e *Enemy) getModExpiry(key string) int {
m := modifier.Find(&e.mods, key)
if m != -1 {
return e.mods[m].Expiry()
}
//must be 0 if doesn't exist. avoid using -1 b/c that's infinite
// must be 0 if doesn't exist. avoid using -1 b/c that's infinite
return 0
}
func (e *Enemy) StatusExpiry(key string) int { return e.getModExpiry(key) }

// Amount.

//TODO: this needs to purge if done?
// TODO: this needs to purge if done?
func (e *Enemy) Resist(ai *combat.AttackInfo, evt glog.Event) float64 {
var logDetails []interface{}
var sb strings.Builder
Expand Down