PvpAction.lua
9.87 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
local ipairs = ipairs
local table = table
local math = math
local redisproxy = redisproxy
local MsgPack = MsgPack
local httpc = require("http.httpc")
local remoteUrl = skynet.getenv("codeurl")
local _M = {}
local _pvpBattleInfoCacheC = {} --查询列表 缓存pvp战斗相关数据缓存
local _pvpStartBattleCache = nil --
local _pvpRecordInfoCache = {} -- 记录缓存
local _pvpRecordBattleInfoCache = {} -- 记录战斗数据缓存
local _revengeRecord = {} -- 复仇对单人1分钟间隔
local RevengeWaitTime = 60
function _M.formatCommonRpc(agent , data)
local role = agent.role
local roleId = role:getProperty("id")
local msg = MsgPack.unpack(data)
local pvpTC = role:getProperty("pvpTC")
for slot, heroId in pairs(msg.heros or {}) do
if not role.heros[heroId] then
return
end
end
if not msg.heros or not next(msg.heros) then
return
end
table.clear(pvpTC)
pvpTC.heros = {}
for slot, heroId in pairs(msg.heros) do
pvpTC.heros[slot] = heroId
end
pvpTC.leader = msg.leader
role:savePvpCTeam(pvpTC)
SendPacket(actionCodes.Pvp_formatCommonRpc, '')
return true
end
local function getMatchInfo(role, pvpList, battleCache)
table.clear(battleCache)
local redret = redisproxy:pipelining(function(red)
for _, info in ipairs(pvpList) do
if info.t == 1 then
red:zscore(RANK_PVP_COMMON, info.id)
end
end
end)
local matches = {}
local curIdx = 1
for idx, info in ipairs(pvpList) do
local curInfo = {idx = idx}
if info.t == 1 then --玩家
curInfo.roleId = info.id
curInfo.score = role:unpackPvpScore(redret[curIdx] or 0)
curIdx = curIdx + 1
-- name, level, headId, battleV, heros
local online, roleInfo = rpcRole(curInfo.roleId, "pvpCInfo")
for k , v in pairs(roleInfo) do
if k == "battleInfo" then
battleCache[curInfo.roleId] = v
else
curInfo[k] = v
end
end
elseif info.t == 2 then -- robot
curInfo.robot = info.id
end
table.insert(matches, curInfo)
end
return matches
end
-- 获取pvp信息
function _M.infoRpc(agent, data)
local role = agent.role
local roleId = role:getProperty("id")
local msg = MsgPack.unpack(data)
local ptype = msg.ptype or 1
local response = {}
if ptype == 1 then -- 普通pvp
local redret = redisproxy:pipelining(function(red)
red:zscore(RANK_PVP_COMMON, roleId)
red:zrevrank(RANK_PVP_COMMON, roleId)
end)
local score = role:unpackPvpScore(redret[1] or 0)
local rank = tonumber(redret[2] or -2) + 1 --排名 1 - ... -1 未上榜 没打过pvp
if rank == -1 then
score = globalCsv.pvp_base_score
end
local pvpMC = role:getProperty("pvpMC")
if not next(pvpMC) then --没有分配过对手
role:refreshPvpMatchC(score)
pvpMC = role:getProperty("pvpMC")
end
if not next(pvpMC) then return end
response.rank = rank
response.score = score
response.matches = getMatchInfo(role, pvpMC, _pvpBattleInfoCacheC)
elseif ptype == 2 then -- 高级pvp
return
else
return
end
SendPacket(actionCodes.Pvp_infoRpc, MsgPack.pack(response))
return true
end
function _M.refreshMatchCRpc(agent, data)
local role = agent.role
local msg = MsgPack.unpack(data)
role:refreshPvpMatchC()
local pvpMC = role:getProperty("pvpMC")
local matches = getMatchInfo(role, pvpMC, _pvpBattleInfoCacheC)
SendPacket(actionCodes.Pvp_refreshMatchCRpc, MsgPack.pack({matches = matches}))
return true
end
function _M.buyCountRpc(agent, data)
local role = agent.role
local msg = MsgPack.unpack(data)
local count = msg.count
if math.illegalNum(count, 1, math.huge) then
return 1
end
local cost = {[ItemId.Diamond] = globalCsv.pvp_buy_cost * count}
if not role:checkItemEnough(cost) then return 2 end
role:costItems(cost)
role:award({[ItemId.PvpKey] = count})
SendPacket(actionCodes.Pvp_buyCountRpc, '')
return true
end
function _M.startBattleRpc(agent, data)
local role = agent.role
local msg = MsgPack.unpack(data)
local idx = msg.idx
local revenge = msg.revenge
local pvpTC = role:getProperty("pvpTC")
if not pvpTC.heros or not next(pvpTC.heros) then return 1 end
local matchInfo, result, key, wait
local now = skynet.timex()
if revenge then --复仇
local temp = _pvpRecordInfoCache[idx]
if not temp then return 2 end
if not _revengeRecord[temp.id] or now >= _revengeRecord[temp.id] then
if temp.t == 1 then
matchInfo = _pvpRecordBattleInfoCache[temp.id]
elseif temp.t == 2 then
matchInfo = {robot = temp.id}
end
else
result = 1
wait = _revengeRecord[temp.id] - now
end
else --打正常
local pvpMC = role:getProperty("pvpMC")
if not pvpMC[idx] then return 3 end
if pvpMC[idx].t == 1 then
matchInfo = _pvpBattleInfoCacheC[pvpMC[idx].id]
elseif pvpMC[idx].t == 2 then
matchInfo = {robot = pvpMC[idx].id}
end
end
if not result and not matchInfo then return 4 end
if not result then
-- 次数扣一波
local pvpFree = role.dailyData:getProperty("pvpFree")
if pvpFree >= globalCsv.pvp_battle_free_count then
local cost = {[ItemId.PvpKey] = 1}
if not role:checkItemEnough(cost) then return 5 end
role:costItems(cost)
else
role.dailyData:updateProperty({field = "pvpFree", delta = 1})
end
key = tostring(math.random())
_pvpStartBattleCache = {idx = idx, key = key, revenge = revenge}
role:checkTaskEnter("PvpBattle")
end
SendPacket(actionCodes.Pvp_startBattleRpc, MsgPack.pack({matchInfo = matchInfo, key = key, result = result, wait = wait}))
return true
end
function _M.endBattleRpc(agent, data)
local role = agent.role
local roleId = role:getProperty("id")
local msg = MsgPack.unpack(data)
if not msg.key or not _pvpStartBattleCache or msg.key ~= _pvpStartBattleCache.key then
return 1
end
if not msg.idx or msg.idx ~= _pvpStartBattleCache.idx then
return 2
end
local isWin = msg.starNum and msg.starNum > 0
local now = skynet.timex()
local revenge = _pvpStartBattleCache.revenge
local match
if revenge then
match = _pvpRecordInfoCache[msg.idx]
_revengeRecord[match.id] = now + RevengeWaitTime -- 1分钟内不能再打
else
local pvpMC = role:getProperty("pvpMC")
match = pvpMC[msg.idx]
end
if not match then return end
local temp = string.randWeight(csvdb["player_expCsv"][role:getProperty("level")].pvpBonus, true)
local reward = role:award({[temp[1]] = temp[2]})
local myScore, matchScore, oldmyScore, oldMatchScore, myRank, oldMyRank = role:changePvpScoreCommon(match.t == 1 and match.id or -1, isWin)
_pvpBattleInfoCacheC = {} --重新发阵容了 没毛病
_pvpRecordInfoCache = {} -- 记录刷新了
_pvpRecordBattleInfoCache = {} -- 取新纪录的时候搞
_pvpStartBattleCache = nil
-- 请求上传录像
local params = {
["roleid"] = roleId,
["key"] = "zhaolugame20191016",
["time"] = now,
}
local status, body = httpc.get(remoteUrl, "/applyvideo?" .. httpGetFormatData(params), {}, {})
local video = nil
if tonumber(status) == 200 then
local result = json.decode(body)
video = result.name
else
skynet.error("applyvideo", "error", status, body, content)
end
-- 加入战斗记录
redisproxy:pipelining(function(red)
local dbKey = string.format(RECORD_PVP_COMMON, roleId)
red:lpush(dbKey, MsgPack.pack({
id = match.id,
t = match.t,
win = isWin,
time = now,
video = video,
sdelta = myScore - oldmyScore,
}))
red:trim(dbKey, 0, 9)
-- 对方加入战斗记录
if match.t == 1 then
dbKey = string.format(RECORD_PVP_COMMON, match.id)
red:lpush(dbKey, MsgPack.pack({
id = roleId,
t = 1,
win = not isWin,
time = now,
video = video,
sdelta = matchScore - oldMatchScore,
}))
red:trim(dbKey, 0, 9)
end
end)
if isWin then
role:checkTaskEnter("PvpWin", {score = myScore})
end
SendPacket(actionCodes.Pvp_endBattleRpc, MsgPack.pack({
reward = reward,
myScore = myScore,
matchScore = matchScore,
oldmyScore = oldmyScore,
oldMatchScore = oldMatchScore,
myRank = myRank,
oldMyRank = oldMyRank,
video = video,
}))
return true
end
function _M.rankListRpc(agent, data)
local role = agent.role
local roleId = role:getProperty("id")
local msg = MsgPack.unpack(data)
local ptype = msg.ptype or 1
local response = {}
if ptype == 1 then -- 普通pvp
local redret = redisproxy:pipelining(function(red)
red:zscore(RANK_PVP_COMMON, roleId)
red:zrevrank(RANK_PVP_COMMON, roleId)
red:zrevrange(RANK_PVP_COMMON, 0, 99, "WITHSCORES")
end)
local score = role:unpackPvpScore(redret[1] or 0)
local rank = tonumber(redret[2] or -2) + 1 --排名 1 - ... -1 未上榜 没打过pvp
if rank == -1 then
score = globalCsv.pvp_base_score
end
local rankList = {}
for i = 1, #redret[3], 2 do
local roleId = tonumber(redret[3][i])
local score = role:unpackPvpScore(redret[3][i + 1])
local online, curInfo = rpcRole(roleId, "friendSInfo")
curInfo.score = score
curInfo.roleId = roleId
table.insert(rankList, curInfo)
end
response.score = score
response.rank = rank
response.rankList = rankList
elseif ptype == 2 then -- 高级pvp
return
else
return
end
SendPacket(actionCodes.Pvp_rankListRpc, MsgPack.pack(response))
return true
end
function _M.recordListRpc(agent, data)
local role = agent.role
local roleId = role:getProperty("id")
local ptype = msg.ptype or 1
local recordList = {}
local now = skynet.timex()
if ptype == 1 then -- 普通pvp
local rlist = redisproxy:lrange(string.format(RECORD_PVP_COMMON, roleId), 0 , 9)
local tempList = {}
for _, temp in ipairs(rlist) do
local one = MsgPack.unpack(temp)
if now - one.time <= globalCsv.pvp_record_keep_time then -- 大于一天的弃之
table.insert(tempList, one)
end
end
_pvpRecordInfoCache = tempList
recordList = getMatchInfo(role, tempList, _pvpRecordBattleInfoCache)
for idx, info in ipairs(recordList) do
local temp = tempList[idx]
info.win = temp.win
info.time = temp.time
info.video = temp.video
info.sdelta = temp.sdelta
end
elseif ptype == 2 then -- 高级pvp
return
else
return
end
SendPacket(actionCodes.Pvp_recordListRpc, MsgPack.pack({list = recordList}))
return true
end
return _M