service.go 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. package equip
  2. import (
  3. capp "f1-game/internal/cherry_app"
  4. "f1-game/internal/code"
  5. "f1-game/internal/component/redis"
  6. "f1-game/internal/constant"
  7. "f1-game/internal/data"
  8. "f1-game/internal/enum"
  9. "f1-game/internal/event"
  10. "f1-game/internal/extend/rand"
  11. facade "f1-game/internal/facade"
  12. nameRoute "f1-game/internal/name/route"
  13. "f1-game/internal/pb"
  14. "f1-game/internal/sessions"
  15. "f1-game/internal/types"
  16. "f1-game/nodes/game/internal/db"
  17. dbEquip "f1-game/nodes/game/internal/db/data/equip"
  18. ao "f1-game/nodes/game/player/asset/origin"
  19. clog "github.com/cherry-game/cherry/logger"
  20. cproto "github.com/cherry-game/cherry/net/proto"
  21. )
  22. var srv = &service{}
  23. type service struct {
  24. facade.PlayerServiceBase[*db.PlayerTable]
  25. }
  26. func Service() *service {
  27. return srv
  28. }
  29. // func (p *service) OnLogin(playerTable *db.PlayerTable, session *cproto.Session) {
  30. // }
  31. // func (p *service) OnLogined(playerTable *db.PlayerTable, session *cproto.Session) {
  32. // }
  33. // func (p *service) OnLogout(playerTable *db.PlayerTable) {
  34. // }
  35. // func (p *service) OnReset(playerTable *db.PlayerTable, time *cherryTime.CherryTime, byLogin bool) {
  36. // }
  37. func (p *service) Push(playerTable *db.PlayerTable, session *cproto.Session) {
  38. equipTable := db.GetEquipTable(playerTable.PlayerID)
  39. proto := equipTable.Equips.ToProto()
  40. sessions.PushWithSession(session, nameRoute.PushGamePlayer_EquipList, proto)
  41. }
  42. // Add 添加装备
  43. func (p *service) Add(playerID int64, equipID int32, num int64, origin ao.Origin, push bool) (types.Assets, int32) {
  44. var (
  45. equipTable = db.GetEquipTable(playerID)
  46. equipRow, ok = data.Equip.GetByID(equipID)
  47. equipList types.List[*dbEquip.Equip]
  48. retAssets = types.NoneAssets
  49. )
  50. if !ok {
  51. return retAssets, code.ConfigNotFound_Equip
  52. }
  53. // 随机生成装备
  54. for range num {
  55. equip, errCode := p.newEquip(equipRow)
  56. if errCode != code.OK {
  57. return retAssets, errCode
  58. }
  59. equipTable.Equips.Add(equip)
  60. equipList.Add(equip)
  61. retAssets.AddAsset(types.NewAssetWithGUID(equip.EquipID, 1, equip.GUID))
  62. }
  63. if !equipList.IsEmpty() {
  64. equipTable.EquipExtend.AddQualityCount(int32(equipRow.Quality), int32(len(equipList)))
  65. equipTable.Save2Queue()
  66. if push {
  67. // 变更推送
  68. p.ChangePush(playerID, nil, equipList...)
  69. }
  70. // 发送装备获得事件
  71. capp.PostEvent(event.NewEquipAdd(playerID, retAssets))
  72. }
  73. return retAssets, code.OK
  74. }
  75. // ChangePush 装备变更推送
  76. func (p *service) ChangePush(playerID int64, removeEquips []int64, updateEquips ...*dbEquip.Equip) {
  77. if len(updateEquips) > 0 {
  78. rsp := &pb.EquipList{}
  79. for _, equip := range updateEquips {
  80. rsp.List = append(rsp.List, equip.ToProto())
  81. }
  82. sessions.PushPlayer(playerID, nameRoute.PushGamePlayer_EquipChange, rsp)
  83. }
  84. if len(removeEquips) > 0 {
  85. sessions.PushPlayer(playerID, nameRoute.PushGamePlayer_EquipDel, &pb.I64List{
  86. List: removeEquips,
  87. })
  88. }
  89. }
  90. // newEquip 创建装备
  91. func (p *service) newEquip(equipRow *data.EquipRow) (*dbEquip.Equip, int32) {
  92. equip := &dbEquip.Equip{
  93. GUID: redis.GUID.NewGUID(),
  94. EquipID: equipRow.ID,
  95. Level: 0,
  96. BaseAttrs: types.Attrs{},
  97. ExtraAttrs: types.NewPairList[int32, int64](),
  98. }
  99. // 随机基础属性
  100. for _, baseAttrRange := range equipRow.BaseAttrRange {
  101. randomAttrValue := rand.RangeInt(baseAttrRange.Opt, baseAttrRange.Value)
  102. equip.BaseAttrs.Add(baseAttrRange.ID, int64(randomAttrValue))
  103. }
  104. // 随机额外属性
  105. extraAttrNum := equipRow.GetExtraAttrNum()
  106. if extraAttrNum > 0 {
  107. pool, found := data.EquipAttrExtra.GetWeighter(equipRow.ExtraAttrPool)
  108. if found {
  109. rows := pool.SelectUnique(int(extraAttrNum))
  110. for _, row := range rows {
  111. equip.ExtraAttrs.Append(types.NewPair(row.Key, row.RandomValue()))
  112. }
  113. } else {
  114. clog.Warnf("equip extra attr pool not found, equipID: %d, pool: %s", equipRow.ID, equipRow.ExtraAttrPool)
  115. }
  116. }
  117. // 随机
  118. if equipRow.RareSkillProb > 0 {
  119. // 随机是否触发稀有技能
  120. randomValue := int32(rand.RangeInt(0, constant.RatioBase))
  121. if randomValue <= equipRow.RareSkillProb {
  122. skillPool := equipRow.RandomSingleSkillPool()
  123. if skillPool > 0 {
  124. // 随机技能
  125. skillPoolRow, errCode := data.SkillPool.Random(skillPool)
  126. if code.IsFail(errCode) {
  127. return nil, errCode
  128. }
  129. equip.SpecialSkill.Key = skillPoolRow.SkillID
  130. equip.SpecialSkill.Value = 1
  131. }
  132. }
  133. }
  134. return equip, code.OK
  135. }
  136. // 获取装备
  137. func (p *service) GetEquip(playerID int64, equipGUID int64) (*dbEquip.Equip, int32) {
  138. equipTable := db.GetEquipTable(playerID)
  139. equip, found := equipTable.Equips.Get(equipGUID)
  140. if found {
  141. return equip, code.OK
  142. }
  143. return nil, code.EquipNotFound
  144. }
  145. // 更新装备状态
  146. func (p *service) UpdateEquipStatus(playerID int64, equipGUID int64, state enum.EquipState) int32 {
  147. equipTable := db.GetEquipTable(playerID)
  148. equip, found := equipTable.Equips.Get(equipGUID)
  149. if !found {
  150. return code.EquipNotFound
  151. }
  152. equip.State = state
  153. equipTable.Save2Queue()
  154. p.ChangePush(playerID, nil, equip)
  155. return code.OK
  156. }