role_equip.go 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101
  1. package model
  2. import (
  3. "math/rand"
  4. "rocommon/util"
  5. "roserver/baseserver/model"
  6. "roserver/baseserver/set"
  7. "roserver/serverproto"
  8. "sort"
  9. "strconv"
  10. )
  11. type RoleEquip struct {
  12. SaveObject
  13. equipList map[int32]*serverproto.EquipData
  14. //部件对应的装备
  15. equipTypeList map[int32]set.Interface
  16. }
  17. func newRoleEquip(r *Role) *RoleEquip {
  18. roleEquip := &RoleEquip{
  19. SaveObject: SaveObject{
  20. role: r,
  21. },
  22. }
  23. roleEquip.equipList = make(map[int32]*serverproto.EquipData)
  24. roleEquip.equipTypeList = make(map[int32]set.Interface)
  25. return roleEquip
  26. }
  27. func (this *RoleEquip) CopyData(data *serverproto.RoleEquip) {
  28. for _, equip := range this.equipList {
  29. data.EquipList = append(data.EquipList, equip)
  30. }
  31. }
  32. func (this *RoleEquip) equipTypeListAdd(equipType int32, configId int32) {
  33. if _, ok := this.equipTypeList[equipType]; !ok {
  34. this.equipTypeList[equipType] = set.New(set.NonThreadSafe)
  35. }
  36. this.equipTypeList[equipType].Add(configId)
  37. }
  38. func (this *RoleEquip) equipTypeListRemove(equipType int32, configId int32) {
  39. if _, ok := this.equipTypeList[equipType]; ok {
  40. this.equipTypeList[equipType].Remove(configId)
  41. }
  42. }
  43. func (this *RoleEquip) Load(msg interface{}) bool {
  44. proRole := msg.(*serverproto.Role)
  45. if proRole.RoleEquip != nil {
  46. for _, data := range proRole.RoleEquip.EquipList {
  47. cfgData, ok := serverproto.EquipCfgLoader[data.ConfigId]
  48. if ok {
  49. this.equipList[data.ConfigId] = data
  50. this.equipTypeListAdd(cfgData.Type, data.ConfigId)
  51. if data.Num <= 0 {
  52. util.ErrorF("uid=%v online equip num<=0 cfgid=%v", this.role.GetUUid(), data.ConfigId)
  53. }
  54. }
  55. }
  56. }
  57. util.DebugF("uid=%v RoleEquip equipTypeListLen=%v", this.role.GetUUid(), len(this.equipTypeList))
  58. return true
  59. }
  60. func (this *RoleEquip) Save() {
  61. this.SetDirty(false)
  62. util.DebugF("uid=%v RoleEquip save...", this.role.GetUUid())
  63. if len(this.equipList) > 0 {
  64. //先整体做保存,后期做部分保存,提高效率
  65. saveMsg := &serverproto.SSEquipDataSaveReq{
  66. Equip: &serverproto.RoleEquip{},
  67. }
  68. //优化提升效率
  69. saveMsg.Equip.EquipList = make([]*serverproto.EquipData, 0, 32)
  70. for _, data := range this.equipList {
  71. if data.Num > 0 {
  72. saveMsg.Equip.EquipList = append(saveMsg.Equip.EquipList, data)
  73. }
  74. }
  75. this.role.SendDb(saveMsg)
  76. }
  77. }
  78. func (this *RoleEquip) ChangeNtf(equipIdList set.Interface, ignore bool) {
  79. ntfMsg := &serverproto.SCEquipChangeNtf{
  80. Ignore: ignore,
  81. }
  82. for _, data := range equipIdList.List() {
  83. equipConfigId := data.(int32)
  84. equip := this.GetEquip(equipConfigId)
  85. if equip != nil {
  86. if equip.Num < 0 {
  87. equip.Num = 0
  88. }
  89. ntfMsg.EquipList = append(ntfMsg.EquipList, &serverproto.EquipData{
  90. ConfigId: equipConfigId,
  91. Num: equip.Num,
  92. })
  93. } else {
  94. ntfMsg.EquipList = append(ntfMsg.EquipList, &serverproto.EquipData{
  95. ConfigId: equipConfigId,
  96. Num: 0,
  97. })
  98. }
  99. }
  100. this.role.ReplayGate(ntfMsg, true)
  101. }
  102. func (this *RoleEquip) GetEquip(equipConfigId int32) *serverproto.EquipData {
  103. if equipData, ok := this.equipList[equipConfigId]; ok {
  104. if equipData.Num <= 0 {
  105. return nil
  106. }
  107. return equipData
  108. }
  109. return nil
  110. }
  111. func (this *RoleEquip) AddEquip(configId int32, num int32) (interface{}, bool) {
  112. cfgData, ok := serverproto.EquipCfgLoader[configId]
  113. if !ok || num <= 0 {
  114. util.DebugF("[AddEquip] load item config error, configId: %v ", configId)
  115. return nil, false
  116. }
  117. this.SetDirty(true)
  118. var oldNum int32 = 0
  119. equipData := this.GetEquip(configId)
  120. if equipData != nil {
  121. oldNum = equipData.Num
  122. equipData.Num += num
  123. TaskMagCheck(this.role, serverproto.TaskType_Equip_Quality_Num, 0)
  124. util.InfoF("uid=%v AddEquip configId=%v addNum=%v oldNum=%v curNum=%v", this.role.GetUUid(), configId, num, oldNum, equipData.Num)
  125. return equipData, false
  126. } else {
  127. this.equipList[configId] = &serverproto.EquipData{
  128. ConfigId: configId,
  129. Num: num,
  130. }
  131. this.equipTypeListAdd(cfgData.Type, configId)
  132. TaskMagCheck(this.role, serverproto.TaskType_Equip_Quality_Num, 0)
  133. util.InfoF("uid=%v AddEquip configId=%v addNum=%v oldNum=%v curNum=%v", this.role.GetUUid(), configId, num, oldNum, num)
  134. return this.equipList[configId], true
  135. }
  136. }
  137. func (this *RoleEquip) RemoveEquip(configId int32) {
  138. delete(this.equipList, configId)
  139. cfgData, ok := serverproto.EquipCfgLoader[configId]
  140. if !ok {
  141. this.equipTypeListRemove(cfgData.Type, configId)
  142. }
  143. }
  144. func (this *RoleEquip) ReduceEquipNum(configId int32, reduceNum int32, notify bool) {
  145. if reduceNum <= 0 {
  146. return
  147. }
  148. equipData := this.GetEquip(configId)
  149. if equipData != nil {
  150. oldNum := equipData.Num
  151. equipData.Num -= reduceNum
  152. if equipData.Num <= 0 {
  153. equipData.Num = 0
  154. util.InfoF("uid=%v ReduceEquipNum equip num configId=%v old=%v new=%v reducenum=%v", this.role.uuid, configId, oldNum, equipData.Num, reduceNum)
  155. this.RemoveEquip(configId)
  156. }
  157. if notify {
  158. changNtf := &serverproto.SCEquipChangeNtf{
  159. Ignore: true,
  160. }
  161. changNtf.EquipList = append(changNtf.EquipList, equipData)
  162. this.role.ReplayGate(changNtf, true)
  163. }
  164. util.InfoF("uid=%v ReduceEquipNum configId=%v reduceNum=%v oldNum=%v curNum=%v", this.role.GetUUid(), configId, reduceNum, oldNum, equipData.Num)
  165. }
  166. }
  167. func (this *RoleEquip) EquipForge(equipConfigId int32, once int32, equipType, subEquipType int32) {
  168. var ret = serverproto.ErrorCode_ERROR_OK
  169. //客户端显示使用
  170. ackMsg := &serverproto.SCEquipForgeAck{}
  171. //一键锻造
  172. if equipConfigId <= 0 {
  173. ret = this.equipForgeAll(equipType, subEquipType)
  174. } else {
  175. if once > 0 {
  176. ackMsg.Type = 1 //表示合成单件装备
  177. ret = this.equipSameForge(equipConfigId, once, ackMsg)
  178. if ret == serverproto.ErrorCode_ERROR_OK {
  179. this.role.BaseChangeNtf()
  180. this.SetDirty(true)
  181. }
  182. } else {
  183. ret = serverproto.ErrorCode_ERROR_FAIL
  184. }
  185. }
  186. ackMsg.Error = int32(ret)
  187. this.role.ReplayGate(ackMsg, true)
  188. }
  189. //合成该装备到下一个装备,根据给定limit是合成多次还是合成一次
  190. func (this *RoleEquip) equipSameForge(equipConfigId int32, limit int32, ackMsg *serverproto.SCEquipForgeAck) serverproto.ErrorCode {
  191. globalData, ok1 := serverproto.GlobalCfgLoader[int32(serverproto.GlobalType_Global_Equip_Forging_Num)]
  192. cfgData, ok2 := serverproto.EquipCfgLoader[equipConfigId]
  193. equipData, ok3 := this.equipList[cfgData.Id]
  194. //锻造的装备是否存在
  195. _, ok := serverproto.EquipCfgLoader[cfgData.Forge]
  196. if !ok {
  197. util.DebugF("EquipForging forge config data not found cfgid=%%v", cfgData.Forge)
  198. return serverproto.ErrorCode_ERROR_EQUIP_CONFIG_DATA_NOT_FOUND
  199. }
  200. if !ok1 || !ok2 || !ok3 {
  201. util.DebugF("EquipForging config data not found")
  202. return serverproto.ErrorCode_ERROR_EQUIP_CONFIG_DATA_NOT_FOUND
  203. }
  204. if equipData.Num < globalData.IVal {
  205. util.DebugF("uid=%v EquipForging num not enough cfgid=%v num=%v", this.role.GetUUid(), equipData.ConfigId, equipData.Num)
  206. return serverproto.ErrorCode_ERROR_EQUIP_FORGE_NUM_NOT_ENOUGH
  207. }
  208. if this.role.GetMoney() < uint64(cfgData.CostMoney) {
  209. util.DebugF("uid=%v EquipForging money not enough costmoney=%v", this.role.GetUUid(), cfgData.CostMoney)
  210. return serverproto.ErrorCode_ERROR_MONEY_NOT_ENOUGH
  211. }
  212. //同一个装备是否融合到不能融合为止
  213. addNum := equipData.Num / globalData.IVal
  214. costMoney := addNum * cfgData.CostMoney
  215. if this.role.GetMoney() < uint64(costMoney) {
  216. addNum = int32(this.role.GetMoney()) / cfgData.CostMoney
  217. costMoney = addNum * cfgData.CostMoney
  218. }
  219. if limit > addNum || limit <= 0 {
  220. limit = addNum
  221. }
  222. costMoney = limit * cfgData.CostMoney
  223. //消耗金钱
  224. this.role.AddMoney(AddItemST{ItemCount: costMoney}, false)
  225. //通知数据变化
  226. this.ReduceEquipNum(cfgData.Id, globalData.IVal*limit, true)
  227. addEquip, _ := this.AddEquip(cfgData.Forge, limit) //锻造成新的装备
  228. if addEquip != nil {
  229. changNtf := &serverproto.SCEquipChangeNtf{}
  230. changNtf.Ignore = false
  231. changNtf.EquipList = append(changNtf.EquipList, addEquip.(*serverproto.EquipData))
  232. this.role.ReplayGate(changNtf, true)
  233. }
  234. //任务条件处理
  235. TaskMagCheck(this.role, serverproto.TaskType_Equip_Forge_Count, limit)
  236. TaskMagCheck(this.role, serverproto.TaskType_Equip_Quality_Num, 0)
  237. TaskMagCheck(this.role, serverproto.TaskType_Eve_Merge_Equip, cfgData.Forge)
  238. return serverproto.ErrorCode_ERROR_OK
  239. }
  240. //根据装备部件进行锻造
  241. func (this *RoleEquip) equipForgeAll(equipType, subEquipType int32) serverproto.ErrorCode {
  242. if equipType <= Equip_Type_None || equipType >= Equip_Type_Max {
  243. return serverproto.ErrorCode_ERROR_FAIL
  244. }
  245. if equipType == Equip_Type_Weapon {
  246. if subEquipType <= Pro_Type_None || subEquipType >= Pro_Type_MAX {
  247. return serverproto.ErrorCode_ERROR_FAIL
  248. }
  249. }
  250. globalData, ok := serverproto.GlobalCfgLoader[int32(serverproto.GlobalType_Global_Equip_Forging_Num)]
  251. if !ok {
  252. return serverproto.ErrorCode_ERROR_EQUIP_CONFIG_DATA_NOT_FOUND
  253. }
  254. var idList []int32
  255. this.getEquipListByType(equipType, subEquipType, &idList)
  256. //需要按照ID顺序执行(ID从高到底)
  257. sort.Slice(idList, func(i, j int) bool {
  258. return (idList)[i] > (idList)[j]
  259. })
  260. var changList = set.New(set.NonThreadSafe)
  261. for i := 0; i < len(idList); i++ {
  262. //合并同一个装备(查找可以合并的同部件装备,同职业)
  263. this.equipForgeEnd(idList[i], globalData.IVal, changList)
  264. }
  265. if len(changList.List()) > 0 {
  266. this.ChangeNtf(changList, false)
  267. this.role.BaseChangeNtf()
  268. this.SetDirty(true)
  269. }
  270. return serverproto.ErrorCode_ERROR_OK
  271. }
  272. func (this *RoleEquip) getEquipListByType(equipType, subEquipType int32, idList *[]int32) {
  273. typeSet, ok := this.equipTypeList[equipType]
  274. if !ok {
  275. return
  276. }
  277. subEquipTypeStr := strconv.Itoa(int(subEquipType))
  278. if equipType == Equip_Type_Weapon {
  279. for _, idData := range typeSet.List() {
  280. equipId := idData.(int32)
  281. cfgData, ok2 := serverproto.EquipCfgLoader[equipId]
  282. if !ok2 || cfgData.Type != equipType {
  283. continue
  284. }
  285. if len(cfgData.JobType) > 0 {
  286. bFind := false
  287. for i := 0; i < len(cfgData.JobType); i++ {
  288. if cfgData.JobType[i] == subEquipTypeStr {
  289. bFind = true
  290. }
  291. }
  292. if !bFind {
  293. continue
  294. }
  295. }
  296. *idList = append(*idList, equipId)
  297. }
  298. } else {
  299. for _, idData := range typeSet.List() {
  300. equipId := idData.(int32)
  301. *idList = append(*idList, equipId)
  302. }
  303. }
  304. }
  305. //不考虑消耗获得能够合成的最大装备ID
  306. func (this *RoleEquip) equipForgeEndCheck(equipConfigId int32, baseNum int32, checkData map[int32]int32, maxEquipCfgId *int32) {
  307. cfgData, ok := serverproto.EquipCfgLoader[equipConfigId]
  308. equipData := this.GetEquip(equipConfigId)
  309. if !ok || equipData == nil {
  310. return
  311. }
  312. //同一个装备融合到不能融合为止
  313. addNum := equipData.Num / baseNum
  314. //消耗不够合成新装备
  315. if addNum <= 0 {
  316. return
  317. }
  318. _, okData := checkData[equipConfigId]
  319. if okData {
  320. checkData[equipConfigId] -= baseNum * addNum
  321. }
  322. _, okNewData := checkData[cfgData.Forge]
  323. if okNewData {
  324. checkData[cfgData.Forge] += addNum
  325. } else {
  326. checkData[cfgData.Forge] = addNum
  327. }
  328. if *maxEquipCfgId < cfgData.Forge {
  329. *maxEquipCfgId = cfgData.Forge
  330. }
  331. this.equipForgeEndCheck(cfgData.Forge, baseNum, checkData, maxEquipCfgId)
  332. }
  333. //给定装备合成到不能合成为止
  334. func (this *RoleEquip) equipForgeEnd(equipConfigId int32, baseNum int32, changIdList set.Interface) {
  335. cfgData, ok := serverproto.EquipCfgLoader[equipConfigId]
  336. equipData := this.GetEquip(equipConfigId)
  337. if !ok || equipData == nil {
  338. return
  339. }
  340. //判斷合成的装备是否存在
  341. _, ok1 := serverproto.EquipCfgLoader[cfgData.Forge]
  342. if !ok1 {
  343. return
  344. }
  345. //同一个装备融合到不能融合为止
  346. addNum := equipData.Num / baseNum
  347. costMoney := cfgData.CostMoney
  348. if this.role.GetMoney() < uint64(costMoney) || addNum <= 0 {
  349. return
  350. }
  351. for i := 0; i < int(addNum); i++ {
  352. if this.role.GetMoney() < uint64(costMoney) || equipData.Num < baseNum {
  353. break
  354. }
  355. this.role.AddMoney(AddItemST{ItemCount: costMoney}, false)
  356. //通知数据变化
  357. this.ReduceEquipNum(cfgData.Id, baseNum, false)
  358. //锻造成新的装备
  359. addEquip, _ := this.AddEquip(cfgData.Forge, 1)
  360. this.SetDirty(true)
  361. changIdList.Add(cfgData.Id)
  362. if addEquip != nil {
  363. changIdList.Add(cfgData.Forge)
  364. }
  365. //任务条件处理
  366. TaskMagCheck(this.role, serverproto.TaskType_Equip_Forge_Count, 1)
  367. TaskMagCheck(this.role, serverproto.TaskType_Eve_Merge_Equip, cfgData.Forge)
  368. this.equipForgeEnd(cfgData.Forge, baseNum, changIdList)
  369. }
  370. TaskMagCheck(this.role, serverproto.TaskType_Equip_Quality_Num, 0)
  371. }
  372. //获得最高阶装备
  373. func (this *RoleEquip) GetBeastEquip(equipType int32, jobType int32, detail *serverproto.SlotDetailData) int32 {
  374. if jobType < 0 {
  375. return 0
  376. }
  377. var bEquipLevel int32 = 0
  378. detailData := serverproto.EquipCfgLoader[detail.EquipId]
  379. if detailData != nil {
  380. bEquipLevel = detailData.EquipLevel
  381. }
  382. var equipId int32 = 0
  383. jobTypeStr := strconv.Itoa(int(jobType))
  384. for _, data := range this.equipList {
  385. cfgData, ok := serverproto.EquipCfgLoader[data.ConfigId]
  386. if !ok || cfgData.Type != equipType {
  387. continue
  388. }
  389. if data.Num <= 0 {
  390. continue
  391. }
  392. //职业装备查找()
  393. if jobType == 0 && equipType != Equip_Type_Weapon {
  394. //无职业要求
  395. if cfgData.EquipLevel > bEquipLevel {
  396. bEquipLevel = cfgData.EquipLevel
  397. equipId = data.ConfigId
  398. } else if cfgData.EquipLevel == bEquipLevel {
  399. if data.ConfigId > equipId {
  400. bEquipLevel = cfgData.EquipLevel
  401. equipId = data.ConfigId
  402. }
  403. }
  404. } else {
  405. for _, str := range cfgData.JobType {
  406. if str == jobTypeStr {
  407. if cfgData.EquipLevel > bEquipLevel {
  408. bEquipLevel = cfgData.EquipLevel
  409. equipId = data.ConfigId
  410. } else if cfgData.EquipLevel == bEquipLevel {
  411. if data.ConfigId > equipId {
  412. bEquipLevel = cfgData.EquipLevel
  413. equipId = data.ConfigId
  414. }
  415. }
  416. break
  417. }
  418. }
  419. }
  420. }
  421. return equipId
  422. }
  423. //一键装备
  424. func (this *RoleEquip) EquipUpAll(heroId int32, slotData *serverproto.SlotData) {
  425. var changIdList = set.New(set.NonThreadSafe)
  426. for i := Equip_Type_None; i < Equip_Type_Jew; i++ {
  427. detail := slotData.SlotList[i]
  428. slotIndex := int32(i + 1)
  429. slotType := this.role.GetRoleBase().GetSlotTypeByIndex(slotIndex)
  430. slotJobType := this.role.GetRoleHero().GetHeroJobType(heroId)
  431. //查找最高阶装备
  432. equipId := this.GetBeastEquip(slotType, slotJobType, detail)
  433. if detail.EquipId != 0 && detail.EquipId == equipId {
  434. continue
  435. }
  436. if equipId != 0 {
  437. if detail.EquipId != 0 {
  438. this.AddEquip(detail.EquipId, 1)
  439. changIdList.Add(detail.EquipId)
  440. }
  441. detail.EquipId = equipId
  442. this.ReduceEquipNum(equipId, 1, false)
  443. changIdList.Add(equipId)
  444. }
  445. }
  446. if len(changIdList.List()) > 0 {
  447. this.ChangeNtf(changIdList, true)
  448. //slot数据变更通知
  449. ntfMsg := &serverproto.SCSlotDataNtf{
  450. HeroId: heroId,
  451. Slot: &serverproto.SlotData{},
  452. }
  453. *ntfMsg.Slot = *slotData
  454. this.role.ReplayGate(ntfMsg, true)
  455. this.SetDirty(true)
  456. this.role.GetRoleBase().SetDirty(true)
  457. this.role.GetRoleHero().addHeroChange(heroId)
  458. this.onEquipUpAll(heroId)
  459. }
  460. TaskMagCheck(this.role, serverproto.TaskType_Eve_Battle_Role_Quality, 0)
  461. }
  462. func (this *RoleEquip) onEquipUpAll(heroId int32) {
  463. //this.role.roleFightPower.equipAttrChange(heroId)
  464. this.role.roleBattleAttr.AttrChange(
  465. AttrChangeST{
  466. ChangeType: Attr_Change_Equip,
  467. ChangeHeroData: this.role.GetRoleHero().GetHero(heroId),
  468. })
  469. }
  470. func (this *RoleEquip) EquipUp(heroId int32, slotData *serverproto.SlotData, equipId int32, slotIndex int32) serverproto.ErrorCode {
  471. detail := slotData.SlotList[slotIndex-1]
  472. if equipId != 0 {
  473. //判断类型是否一致
  474. equipCfgData, ok := serverproto.EquipCfgLoader[equipId]
  475. equipData := this.GetEquip(equipId)
  476. if !ok || equipData == nil {
  477. return serverproto.ErrorCode_ERROR_EQUIP_CONFIG_DATA_NOT_FOUND
  478. }
  479. typeIndex := this.role.GetRoleBase().GetSlotIndexByType(equipCfgData.Type)
  480. if typeIndex != slotIndex {
  481. return serverproto.ErrorCode_ERROR_EQUIP_TYPE_NOT_MATCH
  482. }
  483. bFind := false
  484. slotHeroJobType := this.role.GetRoleHero().GetHeroJobType(heroId)
  485. for idx := range equipCfgData.JobType {
  486. typeValue, _ := model.Str2Num(equipCfgData.JobType[idx])
  487. if int32(typeValue) == slotHeroJobType {
  488. bFind = true
  489. break
  490. }
  491. }
  492. if !bFind && equipCfgData.Type == Equip_Type_Weapon {
  493. return serverproto.ErrorCode_ERROR_EQUIP_TYPE_NOT_MATCH
  494. }
  495. var changIdList = set.New(set.NonThreadSafe)
  496. if detail.EquipId != 0 {
  497. //卸下之前的装备
  498. tmpEquipId := detail.EquipId
  499. detail.EquipId = 0
  500. this.AddEquip(tmpEquipId, 1)
  501. changIdList.Add(tmpEquipId)
  502. }
  503. if equipId != 0 {
  504. //替换新装备
  505. detail.EquipId = equipId
  506. this.ReduceEquipNum(equipId, 1, false)
  507. changIdList.Add(detail.EquipId)
  508. }
  509. //装备变化通知
  510. this.ChangeNtf(changIdList, true)
  511. //slot数据变更通知
  512. ntfMsg := &serverproto.SCSlotDataNtf{
  513. HeroId: heroId,
  514. Slot: &serverproto.SlotData{},
  515. }
  516. *ntfMsg.Slot = *slotData
  517. this.role.ReplayGate(ntfMsg, true)
  518. this.SetDirty(true)
  519. this.role.GetRoleBase().SetDirty(true)
  520. this.role.GetRoleHero().addHeroChange(heroId)
  521. }
  522. this.onEquipUp(heroId)
  523. TaskMagCheck(this.role, serverproto.TaskType_Eve_Battle_Role_Quality, 0)
  524. return serverproto.ErrorCode_ERROR_OK
  525. }
  526. func (this *RoleEquip) onEquipUp(heroId int32) {
  527. //this.role.roleFightPower.equipAttrChange(heroId)
  528. this.role.roleBattleAttr.AttrChange(
  529. AttrChangeST{
  530. ChangeType: Attr_Change_Equip,
  531. ChangeHeroData: this.role.GetRoleHero().GetHero(heroId),
  532. })
  533. }
  534. func (this *RoleEquip) EquipDown(heroId int32, slotData *serverproto.SlotData, subType int32) {
  535. detailNum := len(slotData.SlotList)
  536. var changIdList = set.New(set.NonThreadSafe)
  537. //一键卸下
  538. if subType == 0 {
  539. for i := 0; i < detailNum; i++ {
  540. detail := slotData.SlotList[i]
  541. if detail != nil && detail.EquipId != 0 {
  542. tmpEquipId := detail.EquipId
  543. detail.EquipId = 0
  544. this.AddEquip(tmpEquipId, 1)
  545. changIdList.Add(tmpEquipId)
  546. }
  547. }
  548. } else {
  549. if subType <= Equip_Type_None || subType >= Equip_Type_Max {
  550. return
  551. }
  552. subIndex := this.role.GetRoleBase().GetSlotIndexByType(subType)
  553. if slotData.SlotList == nil || int32(len(slotData.SlotList)) < subIndex {
  554. return
  555. }
  556. detail := slotData.SlotList[subIndex-1]
  557. if detail != nil && detail.EquipId != 0 {
  558. tmpEquipId := detail.EquipId
  559. detail.EquipId = 0
  560. this.AddEquip(tmpEquipId, 1)
  561. changIdList.Add(tmpEquipId)
  562. }
  563. }
  564. if len(changIdList.List()) > 0 {
  565. this.ChangeNtf(changIdList, true)
  566. //slot数据变更通知
  567. ntfMsg := &serverproto.SCSlotDataNtf{
  568. HeroId: heroId,
  569. Slot: &serverproto.SlotData{},
  570. }
  571. *ntfMsg.Slot = *slotData
  572. this.role.ReplayGate(ntfMsg, true)
  573. this.SetDirty(true)
  574. this.role.GetRoleHero().addHeroChange(heroId)
  575. }
  576. this.onEquipDown(heroId)
  577. }
  578. func (this *RoleEquip) onEquipDown(heroId int32) {
  579. //this.role.roleFightPower.equipAttrChange(heroId)
  580. this.role.roleBattleAttr.AttrChange(
  581. AttrChangeST{
  582. ChangeType: Attr_Change_Equip,
  583. ChangeHeroData: this.role.GetRoleHero().GetHero(heroId),
  584. })
  585. }
  586. func (this *RoleEquip) EquipLevelUpAll(heroId int32, slotData *serverproto.SlotData) bool {
  587. var changeEquipList = set.New(set.NonThreadSafe)
  588. bChange := false
  589. if this.role.GetRoleEquip().equipLevelUpAll(heroId, slotData, changeEquipList) {
  590. bChange = true
  591. }
  592. //合并到不能合并为止
  593. //for {
  594. // ret := this.role.GetRoleEquip().equipLevelUpAll(heroId, slotData, changeEquipList)
  595. // break
  596. // if ret {
  597. // bChange = true
  598. // } else {
  599. // break
  600. // }
  601. //}
  602. if bChange {
  603. //slot数据变更通知
  604. ntfMsg := &serverproto.SCSlotDataNtf{
  605. HeroId: heroId,
  606. Slot: &serverproto.SlotData{},
  607. }
  608. *ntfMsg.Slot = *slotData
  609. util.DebugF("uid=%v EquipLevelUpAll SlotData=%v", this.role.GetUUid(), *slotData)
  610. this.role.ReplayGate(ntfMsg, true)
  611. //装备数据变化通知
  612. this.ChangeNtf(changeEquipList, false)
  613. this.SetDirty(true)
  614. //资源变更通知
  615. if !this.role.GetRoleHero().addHeroChange(heroId) {
  616. this.role.BaseChangeNtf()
  617. }
  618. this.role.GetRoleEquip().onEquipLevelUpAll(heroId)
  619. return true
  620. } else {
  621. ackMsg := &serverproto.SCEquipLevelUpAllAck{
  622. Error: int32(serverproto.ErrorCode_ERROR_EQUIP_LEVEL_UP_ALL_NONE),
  623. }
  624. this.role.ReplayGate(ackMsg, true)
  625. return false
  626. }
  627. }
  628. func (this *RoleEquip) equipLevelUpAll(heroId int32, slotData *serverproto.SlotData, changeEquipList set.Interface) bool {
  629. bLevelUp := false
  630. var levelUpOrder = []int{
  631. Equip_Type_Weapon, Equip_Type_Body,
  632. Equip_Type_Jew, Equip_Type_Head,
  633. Equip_Type_Wrap, Equip_Type_Shoes}
  634. //获取最小等级,并升级
  635. var minListSet = set.New(set.NonThreadSafe)
  636. var minEquipLevel int32 = 0
  637. detailNum := len(slotData.SlotList)
  638. for i := 0; i < detailNum; i++ {
  639. detail := slotData.SlotList[i]
  640. if detail == nil || detail.EquipId == 0 {
  641. continue
  642. }
  643. if cfgData, ok := serverproto.EquipCfgLoader[detail.EquipId]; ok {
  644. minListSet.Add(cfgData.EquipLevel)
  645. if minEquipLevel == 0 {
  646. minEquipLevel = cfgData.EquipLevel
  647. } else if minEquipLevel > cfgData.EquipLevel {
  648. minEquipLevel = cfgData.EquipLevel
  649. }
  650. }
  651. }
  652. minLevelList := minListSet.List()
  653. sort.Slice(minLevelList, func(i, j int) bool {
  654. return minLevelList[i].(int32) < minLevelList[j].(int32)
  655. })
  656. //var changeEquipList = set.New(set.NonThreadSafe)
  657. var excludeSlotIdx = set.New(set.NonThreadSafe)
  658. bChange := false
  659. for {
  660. bLevelUp = false
  661. //升级当前minEquipLevel等级的所有槽位装备
  662. for i := 0; i < len(levelUpOrder); i++ {
  663. if levelUpOrder[i] > len(slotData.SlotList) || excludeSlotIdx.Has(i) {
  664. continue
  665. }
  666. detail := slotData.SlotList[levelUpOrder[i]-1]
  667. if detail == nil || detail.EquipId == 0 {
  668. continue
  669. }
  670. cfgData, ok := serverproto.EquipCfgLoader[detail.EquipId]
  671. if !ok || cfgData.EquipLevel != minEquipLevel {
  672. continue
  673. }
  674. var totalCostMoney uint64 = 0
  675. if this.slotEquipLevelUp(detail, changeEquipList, &totalCostMoney) {
  676. changeEquipList.Add(cfgData.Id)
  677. bLevelUp = true
  678. //消耗金钱
  679. this.role.DelItem(int32(serverproto.ResType_Res_Coin), int32(totalCostMoney), AddItemST{AddFrom: AddFrom_Equip})
  680. excludeSlotIdx.Add(i)
  681. }
  682. }
  683. minEquipLevel++
  684. if bLevelUp {
  685. bChange = true
  686. }
  687. bFind := false
  688. for _, data := range minLevelList {
  689. if minEquipLevel <= data.(int32) {
  690. minEquipLevel = data.(int32)
  691. bFind = true
  692. break
  693. }
  694. }
  695. if !bFind {
  696. break
  697. }
  698. }
  699. if bChange {
  700. return true
  701. }
  702. return false
  703. }
  704. func (this *RoleEquip) onEquipLevelUpAll(heroId int32) {
  705. //this.role.roleFightPower.equipAttrChange(heroId)
  706. this.role.roleBattleAttr.AttrChange(
  707. AttrChangeST{
  708. ChangeType: Attr_Change_Equip,
  709. ChangeHeroData: this.role.GetRoleHero().GetHero(heroId),
  710. })
  711. }
  712. //对应槽位进行升级
  713. func (this *RoleEquip) SlotLevelUp(slotData *serverproto.SlotData, heroId int32, subSlotIndex int32) serverproto.ErrorCode {
  714. if subSlotIndex > int32(len(slotData.SlotList)) || subSlotIndex <= 0 {
  715. return serverproto.ErrorCode_ERROR_FAIL
  716. }
  717. slotDetail := slotData.SlotList[subSlotIndex-1]
  718. if slotDetail.EquipId <= 0 {
  719. return serverproto.ErrorCode_ERROR_EQUIP_SLOT_NO_EQUIP
  720. }
  721. slotType := this.role.GetRoleBase().GetSlotTypeByIndex(subSlotIndex)
  722. cfgData, ok := serverproto.EquipRefineCfgLoader[slotDetail.Level+1]
  723. if !ok {
  724. return serverproto.ErrorCode_ERROR_EQUIP_REFINE_DATA_NOT_FOUND
  725. }
  726. //获取消耗
  727. ret := serverproto.ErrorCode_ERROR_OK
  728. var costZeny int32 = 0
  729. var costItemList = map[int32]int32{}
  730. slotTypeStr := strconv.Itoa(int(slotType))
  731. for index, _ := range cfgData.Place1 {
  732. if cfgData.Place1[index] == slotTypeStr {
  733. costZeny = cfgData.Costzeny1
  734. for index1, _ := range cfgData.Costitem1 {
  735. resType, resValue := model.Str2Res(cfgData.Costitem1[index1])
  736. costItemList[resType] = resValue
  737. }
  738. break
  739. }
  740. }
  741. if costZeny == 0 {
  742. for index, _ := range cfgData.Place2 {
  743. if cfgData.Place2[index] == slotTypeStr {
  744. costZeny = cfgData.Costzeny2
  745. for index1, _ := range cfgData.Costitem2 {
  746. resType, resValue := model.Str2Res(cfgData.Costitem2[index1])
  747. costItemList[resType] = resValue
  748. }
  749. break
  750. }
  751. }
  752. }
  753. if this.role.GetResNum(int32(serverproto.ResType_Res_Coin)) >= uint64(costZeny) &&
  754. this.role.CheckResLitNum(costItemList) {
  755. this.role.AddRes(int32(serverproto.ResType_Res_Coin), AddItemST{ItemCount: costZeny}, false)
  756. this.role.DelItemList(costItemList, AddItemST{AddFrom: AddFrom_Equip})
  757. //成功概率
  758. randNum := rand.Int31n(10000)
  759. if randNum <= cfgData.Rate {
  760. slotDetail.Level++
  761. //任务条件处理
  762. TaskMagCheck(this.role, serverproto.TaskType_Equip_Level_Num, 0)
  763. TaskMagCheck(this.role, serverproto.TaskType_Eve_Equip_Level_Role, 0)
  764. } else {
  765. ret = serverproto.ErrorCode_ERROR_EQUIP_REFINE_FAILED
  766. }
  767. //更新槽位信息
  768. ntfMsg := &serverproto.SCSlotDataNtf{
  769. HeroId: heroId,
  770. Slot: &serverproto.SlotData{},
  771. }
  772. *ntfMsg.Slot = *slotData
  773. this.role.ReplayGate(ntfMsg, true)
  774. this.SetDirty(true)
  775. if !this.role.GetRoleHero().addHeroChange(heroId) {
  776. this.role.GetRoleBase().BaseChangeNtf()
  777. }
  778. this.onSlotLevelUp(heroId)
  779. } else {
  780. ret = serverproto.ErrorCode_ERROR_RES_NOT_ENOUGH
  781. }
  782. return ret
  783. }
  784. func (this *RoleEquip) onSlotLevelUp(heroId int32) {
  785. //任务条件处理
  786. TaskMagCheck(this.role, serverproto.TaskType_Equip_Level_Count, 1)
  787. //this.role.roleFightPower.equipAttrChange(heroId)
  788. this.role.roleBattleAttr.AttrChange(
  789. AttrChangeST{
  790. ChangeType: Attr_Change_Equip,
  791. ChangeHeroData: this.role.GetRoleHero().GetHero(heroId),
  792. })
  793. }
  794. //对槽位中的装备升级
  795. func (this *RoleEquip) slotEquipLevelUp(detail *serverproto.SlotDetailData, changeList set.Interface, totalCostMoney *uint64) bool {
  796. globalData, ok1 := serverproto.GlobalCfgLoader[int32(serverproto.GlobalType_Global_Equip_Forging_Num)]
  797. cfgData, ok2 := serverproto.EquipCfgLoader[detail.EquipId]
  798. equipData, ok3 := this.equipList[cfgData.Id]
  799. if !ok1 || !ok2 {
  800. util.DebugF("slotEquipLevelUp config data not found id=%v", cfgData.Id)
  801. return false
  802. }
  803. //锻造的装备是否存在
  804. _, ok := serverproto.EquipCfgLoader[cfgData.Forge]
  805. if !ok {
  806. util.DebugF("slotEquipLevelUp forge config data not found id=%v forge=%v", cfgData.Forge)
  807. return false
  808. }
  809. if this.role.GetMoney() < *totalCostMoney+uint64(cfgData.CostMoney) {
  810. util.DebugF("uid=%v slotEquipLevelUp money not enough costmoney=%v", this.role.GetUUid(), cfgData.CostMoney)
  811. return false
  812. }
  813. //计算已经装备的装备
  814. var equipDataNum int32 = 1
  815. if ok3 {
  816. equipDataNum += equipData.Num
  817. }
  818. var tmpCheckCostMoney uint64 = 0
  819. if equipDataNum < globalData.IVal {
  820. checkNum := (globalData.IVal - equipDataNum) * globalData.IVal
  821. if !this.checkEquipNum(cfgData.Id, globalData.IVal-1, globalData.IVal, &tmpCheckCostMoney) {
  822. //if !this.checkEquipNum(cfgData.ForgeOld, checkNum, globalData.IVal, &tmpCheckCostMoney) {
  823. util.DebugF("uid=%v slotEquipLevelUp num not enough cfgid=%v num=%v", this.role.GetUUid(), cfgData.Id, equipDataNum)
  824. return false
  825. } else {
  826. *totalCostMoney += tmpCheckCostMoney
  827. if this.role.GetMoney() < *totalCostMoney+uint64(cfgData.CostMoney) {
  828. util.DebugF("uid=%v slotEquipLevelUp money not enough money=%v costmoney=%v", this.role.GetUUid(), this.role.GetMoney(), *totalCostMoney)
  829. return false
  830. }
  831. //可以升级并消耗装备
  832. this.consumeNeedEquip(cfgData.ForgeOld, checkNum, globalData.IVal, changeList)
  833. }
  834. }
  835. *totalCostMoney += uint64(cfgData.CostMoney)
  836. //消耗金钱
  837. //this.role.AddMoney(cfgData.CostMoney, false)
  838. //通知数据变化
  839. //this.ReduceEquipNum(cfgData.Id, globalData.IVal-1, false)
  840. if equipData != nil {
  841. oldNum := equipData.Num
  842. equipData.Num -= globalData.IVal - 1
  843. if equipData.Num <= 0 {
  844. equipData.Num = 0
  845. }
  846. util.InfoF("uid=%v equip num old=%v new=%v", this.role.uuid, oldNum, equipData.Num)
  847. }
  848. //部位装备高阶装备
  849. detail.EquipId = cfgData.Forge
  850. //任务处理
  851. TaskMagCheck(this.role, serverproto.TaskType_Equip_Forge_Count, 1)
  852. TaskMagCheck(this.role, serverproto.TaskType_Equip_Quality_Num, 0)
  853. TaskMagCheck(this.role, serverproto.TaskType_Eve_Merge_Equip, cfgData.Forge)
  854. return true
  855. }
  856. func (this *RoleEquip) checkEquipNum(equipConfigId int32, checkNum int32, baseNum int32, tmpCheckCostMoney *uint64) bool {
  857. cfgData, ok := serverproto.EquipCfgLoader[equipConfigId]
  858. if !ok {
  859. return false
  860. }
  861. var needNum int32
  862. equipData, ok := this.equipList[equipConfigId]
  863. if ok {
  864. if equipData.Num >= checkNum {
  865. return true
  866. } else {
  867. needNum = (checkNum - equipData.Num) * baseNum
  868. oldCfg, oldOk := serverproto.EquipCfgLoader[cfgData.ForgeOld]
  869. if oldOk {
  870. *tmpCheckCostMoney += uint64(oldCfg.CostMoney * (checkNum - equipData.Num))
  871. }
  872. }
  873. } else {
  874. needNum = checkNum * baseNum
  875. oldCfg, oldOk := serverproto.EquipCfgLoader[cfgData.ForgeOld]
  876. if oldOk {
  877. *tmpCheckCostMoney += uint64(oldCfg.CostMoney * checkNum)
  878. }
  879. }
  880. //做保护处理
  881. if needNum > 0xffffff {
  882. return false
  883. }
  884. return this.checkEquipNum(cfgData.ForgeOld, needNum, baseNum, tmpCheckCostMoney)
  885. }
  886. func (this *RoleEquip) consumeNeedEquip(equipConfigId int32, checkNum int32, baseNum int32, changList set.Interface) bool {
  887. cfgData, ok := serverproto.EquipCfgLoader[equipConfigId]
  888. if !ok {
  889. return false
  890. }
  891. var needNum int32
  892. equipData, ok := this.equipList[equipConfigId]
  893. if ok {
  894. if equipData.Num >= checkNum {
  895. this.ReduceEquipNum(equipConfigId, checkNum, false)
  896. changList.Add(equipConfigId)
  897. TaskMagCheck(this.role, serverproto.TaskType_Eve_Merge_Equip, cfgData.Forge)
  898. return true
  899. } else {
  900. needNum = (checkNum - equipData.Num) * baseNum
  901. this.ReduceEquipNum(equipConfigId, equipData.Num, false)
  902. changList.Add(equipConfigId)
  903. }
  904. } else {
  905. needNum = checkNum * baseNum
  906. }
  907. //做保护处理
  908. if needNum > 0xffffff {
  909. return false
  910. }
  911. TaskMagCheck(this.role, serverproto.TaskType_Eve_Merge_Equip, cfgData.Forge)
  912. return this.consumeNeedEquip(cfgData.ForgeOld, needNum, baseNum, changList)
  913. }
  914. ///Task
  915. func (this *RoleEquip) GetQualityEquipNum(quality int32) int32 {
  916. var retNum int32 = 0
  917. if quality <= 0 {
  918. for _, data := range this.equipList {
  919. retNum += data.Num
  920. }
  921. } else {
  922. for _, data := range this.equipList {
  923. itemCfgData := GetItemCfg(data.ConfigId)
  924. if itemCfgData != nil && itemCfgData.Quality >= quality {
  925. retNum += data.Num
  926. }
  927. }
  928. }
  929. //玩家身上的装备
  930. retNum += this.role.GetRoleHero().GetQualityEquipNum(quality)
  931. return retNum
  932. }
  933. ///Task
  934. func (this *RoleEquip) GetQualityEquipNumAll(quality int32) bool {
  935. //var retNum int32 = 0
  936. //玩家身上的装备
  937. if this.role.GetRoleBase() == nil || this.role.GetRoleBase().RoleData().HeroData == nil {
  938. return false
  939. }
  940. slot := this.role.GetRoleBase().RoleData().HeroData.Slot
  941. for _, data := range slot.SlotList {
  942. if data.EquipId <= 0 {
  943. return false
  944. }
  945. itemCfgData := GetItemCfg(data.EquipId)
  946. if itemCfgData == nil {
  947. return false
  948. }
  949. if itemCfgData.Quality < quality {
  950. return false
  951. }
  952. }
  953. hero := this.role.GetRoleHero()
  954. if hero == nil {
  955. return false
  956. }
  957. for _, heroData := range hero.heroList {
  958. if heroData.Slot == nil {
  959. continue
  960. }
  961. for _, slotdata := range heroData.Slot.SlotList {
  962. if slotdata.EquipId <= 0 {
  963. return false
  964. }
  965. itemCfgData := GetItemCfg(slotdata.EquipId)
  966. if itemCfgData != nil {
  967. return false
  968. }
  969. if itemCfgData.Quality < quality {
  970. return false
  971. }
  972. }
  973. }
  974. return true
  975. }