85 lines
2.2 KiB
Go
85 lines
2.2 KiB
Go
package world
|
|
|
|
import (
|
|
"bd2server/internal/server/gamedata"
|
|
"bd2server/internal/server/player"
|
|
"fmt"
|
|
"math"
|
|
)
|
|
|
|
func (s *Service) AttachFieldBuffRuntime(root, version string) error {
|
|
d, e := gamedata.LoadFieldBuffDesign(root, version)
|
|
if e != nil {
|
|
return e
|
|
}
|
|
s.fieldBuffs = d
|
|
s.AttachFieldMonsterDamage(s.applyMonsterFieldDamage)
|
|
return nil
|
|
}
|
|
func (s *Service) applyMonsterFieldDamage(pack int, id uint64, identity string) ([][]byte, error) {
|
|
r, ok := s.fieldBuffs[id]
|
|
if !ok || (r.Type != 4 && r.Type != 5) || r.TargetType > 2 || math.IsNaN(r.Value) || math.IsInf(r.Value, 0) || r.Value < 0 {
|
|
return nil, fmt.Errorf("world: invalid damaging field buff")
|
|
}
|
|
if s.characters == nil || s.decks == nil {
|
|
return nil, fmt.Errorf("world: field health runtime unavailable")
|
|
}
|
|
entries := s.decks.CurrentFieldDeck()
|
|
indices := make([]uint64, 0, len(entries))
|
|
for _, entry := range entries {
|
|
indices = append(indices, entry.CharacterInvenIndex)
|
|
}
|
|
if r.TargetType == 0 {
|
|
party, e := s.ResolveStoryParty(pack, s.firstUnclearedQuestFor(pack))
|
|
if e != nil {
|
|
return nil, e
|
|
}
|
|
if len(party) > 0 && s.questDifficulty(pack) == 0 {
|
|
indices = []uint64{party[0].InvenIndex}
|
|
} else if s.decks.FieldControlType() == 0 || len(indices) == 0 {
|
|
indices = nil
|
|
for _, entry := range s.decks.CurrentDeck() {
|
|
indices = append(indices, entry.CharacterInvenIndex)
|
|
}
|
|
}
|
|
if len(indices) > 1 {
|
|
indices = indices[:1]
|
|
}
|
|
}
|
|
var response [][]byte
|
|
for _, index := range indices {
|
|
c, found := s.characters.Find(index)
|
|
if !found {
|
|
return nil, fmt.Errorf("world: field character missing")
|
|
}
|
|
hp, e := s.characters.CurrentHealth(c.InvenIndex)
|
|
if e != nil {
|
|
return nil, e
|
|
}
|
|
if hp == 0 && r.TargetType != 0 {
|
|
continue
|
|
}
|
|
damage := r.Value
|
|
if r.Type == 5 {
|
|
max, e := s.characters.MaxHealth(c.InvenIndex)
|
|
if e != nil {
|
|
return nil, e
|
|
}
|
|
damage = float64(max) * r.Value
|
|
}
|
|
remaining := uint64(0)
|
|
if damage < float64(hp) {
|
|
remaining = hp - uint64(damage)
|
|
}
|
|
if e = s.characters.SetCurrentHealth(c.InvenIndex, remaining); e != nil {
|
|
return nil, e
|
|
}
|
|
c.HP = remaining
|
|
response = append(response, player.CharacterWire(c))
|
|
if r.TargetType == 0 {
|
|
break
|
|
}
|
|
}
|
|
return response, nil
|
|
}
|