Save endgame progress, team presets, technique support and camera controls
This commit is contained in:
1 parent
a681affdb3
commit
639cef7d19
52 files changed
+11940
-766
No files matched your search
@@ -0,0 +1,173 @@
|
||||
package gameserver
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"gac-hkrpg-go/internal/common"
|
||||
goproto "gac-hkrpg-go/protocol/proto"
|
||||
)
|
||||
|
||||
func (s *Session) techniqueLineup() *goproto.LineupInfo {
|
||||
var lineup *goproto.LineupInfo
|
||||
if run := s.ChallengeRun; run != nil {
|
||||
lineup = run.activeLineup(0)
|
||||
} else if p := s.JSON(); p != nil {
|
||||
lineup = presetLineup(p, p.ActiveTeamPreset)
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
rules, err := common.LoadTechniqueRules()
|
||||
if err != nil {
|
||||
return lineup
|
||||
}
|
||||
if s.techniqueMP == nil {
|
||||
v := rules.InitialMP
|
||||
s.techniqueMP = &v
|
||||
}
|
||||
if *s.techniqueMP > lineup.MaxMp {
|
||||
*s.techniqueMP = lineup.MaxMp
|
||||
}
|
||||
lineup.Mp = *s.techniqueMP
|
||||
if int(s.leaderSlot) < len(lineup.AvatarList) {
|
||||
lineup.LeaderSlot = s.leaderSlot
|
||||
}
|
||||
return lineup
|
||||
}
|
||||
func (s *Session) techniqueAvatar(entity uint32) uint32 {
|
||||
lineup := s.techniqueLineup()
|
||||
if lineup == nil {
|
||||
return 0
|
||||
}
|
||||
if entity == 0 {
|
||||
entity = lineup.LeaderSlot + 1
|
||||
}
|
||||
for _, a := range lineup.AvatarList {
|
||||
if a.Slot+1 == entity {
|
||||
return a.Id
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
func (s *Session) resetTechniqueRoom() {
|
||||
s.techniqueMP = nil
|
||||
s.leaderSlot = 0
|
||||
s.paidTechniqueCasts = nil
|
||||
}
|
||||
func (s *Session) syncTechnique(reason goproto.SyncLineupReason) error {
|
||||
return s.Send(&goproto.SyncLineupNotify{Lineup: s.techniqueLineup(), ReasonList: []goproto.SyncLineupReason{reason}})
|
||||
}
|
||||
func techniqueMaterials(p *common.FreesrData) ([]*goproto.Material, error) {
|
||||
if err := p.EnsureTechniqueFoods(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var out []*goproto.Material
|
||||
for _, id := range sortedU32Keys2(p.TechniqueFoodStock) {
|
||||
out = append(out, &goproto.Material{Tid: id, Num: p.TechniqueFoodStock[id]})
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
func (s *Session) consumeTechniqueFood(id, count uint32) error {
|
||||
p := s.JSON()
|
||||
if p == nil {
|
||||
return fmt.Errorf("no player")
|
||||
}
|
||||
if _, active := CURRENT_BATTLE.Load(s.Token); active {
|
||||
return fmt.Errorf("cannot eat during battle")
|
||||
}
|
||||
rules, err := common.LoadTechniqueRules()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
food, ok := rules.Foods[id]
|
||||
if !ok || count == 0 || count > food.MaxUse {
|
||||
return fmt.Errorf("unsupported food or count")
|
||||
}
|
||||
if err := p.EnsureTechniqueFoods(); err != nil {
|
||||
return err
|
||||
}
|
||||
if p.TechniqueFoodStock[id] < count {
|
||||
return fmt.Errorf("food %d is exhausted", id)
|
||||
}
|
||||
lineup := s.techniqueLineup()
|
||||
if lineup == nil || lineup.Mp >= lineup.MaxMp {
|
||||
return fmt.Errorf("technique points are full")
|
||||
}
|
||||
oldStock, oldMP := p.TechniqueFoodStock[id], *s.techniqueMP
|
||||
p.TechniqueFoodStock[id] -= count
|
||||
gain := uint64(food.RecoverMP)*uint64(count) + uint64(oldMP)
|
||||
if gain > uint64(lineup.MaxMp) {
|
||||
gain = uint64(lineup.MaxMp)
|
||||
}
|
||||
*s.techniqueMP = uint32(gain)
|
||||
if err := p.SavePersistentChecked(); err != nil {
|
||||
p.TechniqueFoodStock[id] = oldStock
|
||||
*s.techniqueMP = oldMP
|
||||
return err
|
||||
}
|
||||
if err := s.Send(&goproto.PlayerSyncScNotify{MaterialList: []*goproto.Material{{Tid: id, Num: p.TechniqueFoodStock[id]}}}); err != nil {
|
||||
return err
|
||||
}
|
||||
SceneDebugLog("[TECHNIQUE] food=%d count=%d mp=%d/%d remaining=%d", id, count, *s.techniqueMP, lineup.MaxMp, p.TechniqueFoodStock[id])
|
||||
return s.syncTechnique(goproto.SyncLineupReason_SyncLineupReason_SyncReasonMpAdd)
|
||||
}
|
||||
func (s *Session) payTechnique(castID, skillIndex uint32) (uint32, error) {
|
||||
if s.paidTechniqueCasts[castID] {
|
||||
return 0, nil
|
||||
}
|
||||
rules, err := common.LoadTechniqueRules()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
avatar := s.techniqueAvatar(0)
|
||||
skills := rules.Avatars[avatar]
|
||||
if int(skillIndex) >= len(skills) {
|
||||
return uint32(goproto.Retcode_RET_MAZE_NO_ABILITY), nil
|
||||
}
|
||||
cost := skills[skillIndex].MPCost
|
||||
lineup := s.techniqueLineup()
|
||||
if lineup == nil {
|
||||
return uint32(goproto.Retcode_RET_LINEUP_IS_EMPTY), nil
|
||||
}
|
||||
p := s.JSON()
|
||||
if err := p.EnsureTechniqueFoods(); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if cost > lineup.MaxMp {
|
||||
return uint32(goproto.Retcode_RET_MAZE_MP_NOT_ENOUGH), nil
|
||||
}
|
||||
for *s.techniqueMP < cost && p.AutoTechniqueFood != nil && *p.AutoTechniqueFood {
|
||||
var selected uint32
|
||||
for _, id := range sortedU32Keys2(rules.Foods) {
|
||||
if p.TechniqueFoodStock[id] > 0 {
|
||||
selected = id
|
||||
break
|
||||
}
|
||||
}
|
||||
if selected == 0 {
|
||||
break
|
||||
}
|
||||
if err := s.consumeTechniqueFood(selected, 1); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
}
|
||||
if *s.techniqueMP < cost {
|
||||
return uint32(goproto.Retcode_RET_MAZE_MP_NOT_ENOUGH), nil
|
||||
}
|
||||
*s.techniqueMP -= cost
|
||||
if s.paidTechniqueCasts == nil {
|
||||
s.paidTechniqueCasts = map[uint32]bool{}
|
||||
}
|
||||
s.paidTechniqueCasts[castID] = true
|
||||
SceneDebugLog("[TECHNIQUE] cast=%d avatar=%d skill=%d cost=%d mp=%d/%d", castID, avatar, skillIndex, cost, *s.techniqueMP, lineup.MaxMp)
|
||||
return 0, s.Send(&goproto.SceneCastSkillMpUpdateScNotify{CastEntityId: castID, Mp: *s.techniqueMP})
|
||||
}
|
||||
func init() {
|
||||
handle("UseItem", func(s *Session, req *goproto.UseItemCsReq, rsp *goproto.UseItemScRsp) error {
|
||||
rsp.UseItemId = req.UseItemId
|
||||
rsp.UseItemCount = req.UseItemCount
|
||||
if err := s.consumeTechniqueFood(req.UseItemId, req.UseItemCount); err != nil {
|
||||
SceneDebugLog("[TECHNIQUE] use item rejected: %v", err)
|
||||
rsp.Retcode = uint32(goproto.Retcode_RET_ITEM_USE_TARGET_TYPE_INVALID)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
Reference in new issue
Block a user