瀏覽代碼

修改对战

huangyuhao 1 年之前
父節點
當前提交
572f474c65

+ 39 - 0
dev/adapt/boxAdapt.lua

@@ -1,3 +1,11 @@
1
+--[[
2
+Descripttion:
3
+version:
4
+Author: Neo,Huang
5
+Date: 2023-11-17 22:23:09
6
+LastEditors: Neo,Huang
7
+LastEditTime: 2023-11-17 23:23:51
8
+--]]
1 9
 -- 箱子配置
2 10
 local baseAdapt = require "base.baseAdapt"
3 11
 
@@ -70,6 +78,12 @@ function root:battle_is_box_list_valid(boxIdList)
70 78
     if is_empty(boxIdList) then
71 79
         return false
72 80
     end
81
+    -- 数量
82
+    local minCount = self:battle_const("battle_box_min")
83
+    local maxCount = self:battle_const("battle_box_max")
84
+    if #boxIdList < minCount or #boxIdList > maxCount then
85
+        return false
86
+    end
73 87
     for _, v in ipairs(boxIdList) do
74 88
         local conf = self:battle_get_box_key_info(v)
75 89
         if is_empty(conf) or is_empty(conf.price) then
@@ -79,4 +93,29 @@ function root:battle_is_box_list_valid(boxIdList)
79 93
     return true
80 94
 end
81 95
 
96
+-- 常量
97
+function root:battle_const(key)
98
+    if is_empty(key) then
99
+        return
100
+    end
101
+    local conf = baseAdapt:getConfig("BattleConstConfig")
102
+    for _, v in ipairs(conf) do
103
+        if v.main_key == key then
104
+            return v.value
105
+        end
106
+    end
107
+end
108
+
109
+-- 箱子物品列表
110
+function root:battle_get_box_item_list(boxId)
111
+    local confList = {}
112
+    local conf = baseAdapt:getConfig("BattleBoxAwardConfig")
113
+    for _, v in ipairs(conf) do
114
+        if v.boxId == boxId then
115
+            table.insert(confList, table.copy(v))
116
+        end
117
+    end
118
+    return confList
119
+end
120
+
82 121
 return root

+ 36 - 0
dev/modules/battlerecord.lua

@@ -0,0 +1,36 @@
1
+--[[
2
+Descripttion:战斗记录
3
+version:
4
+Author: Neo,Huang
5
+Date: 2023-11-18 12:13:14
6
+LastEditors: Neo,Huang
7
+LastEditTime: 2023-11-18 12:13:46
8
+--]]
9
+local root = class("battlerecord", require("base.baseModule"))
10
+
11
+function root:ctor(id)
12
+	root.super.ctor(self, id, "battlerecord", "id", true, false)
13
+	self.id = id
14
+end
15
+
16
+function root:mysql_get_init_columns()
17
+	return {
18
+		id = "bigint(20) NOT NULL COMMENT '邮件ID'",
19
+		roomId = "bigint(20) DEFAULT 0 COMMENT '房间号'",
20
+		battleBoxList = "json COMMENT '战斗箱子ID列表'",
21
+		createTime = "int(11) DEFAULT 0 COMMENT '房间创建时间'",
22
+		battleTime = "int(11) DEFAULT 0 COMMENT '战斗开始时间'",
23
+		battleId = "varchar(50) DEFAULT '' COMMENT '战斗编号'",
24
+		winUid = "int(11) DEFAULT 0 COMMENT '胜利玩家ID'",
25
+		totalPrice = "int(11) DEFAULT 0 COMMENT '掉落饰品总价格'",
26
+		battlePlayerList = "json COMMENT '战斗玩家列表'",
27
+		expireTime = "int(11) DEFAULT 0 COMMENT '过期时间'",
28
+		battleUid1 = "int(11) DEFAULT 0 COMMENT '战斗玩家ID'",
29
+		battleUid2 = "int(11) DEFAULT 0 COMMENT '战斗玩家ID'",
30
+		battleUid3 = "int(11) DEFAULT 0 COMMENT '战斗玩家ID'",
31
+		battleUid4 = "int(11) DEFAULT 0 COMMENT '战斗玩家ID'",
32
+		battleUid5 = "int(11) DEFAULT 0 COMMENT '战斗玩家ID'"
33
+	}
34
+end
35
+
36
+return root

+ 155 - 0
dev/utils/util_battle.lua

@@ -0,0 +1,155 @@
1
+--[[
2
+Descripttion:战斗
3
+version:
4
+Author: Neo,Huang
5
+Date: 2023-11-18 12:21:05
6
+LastEditors: Neo,Huang
7
+LastEditTime: 2023-11-18 12:26:57
8
+--]]
9
+local timeUtil = require("utils.timeUtil")
10
+local mysqlUtil = require("utils.mysqlUtil")
11
+local util_player = require("utils.util_player")
12
+
13
+local boxAdapt = require("adapt.boxAdapt")
14
+
15
+local root = {}
16
+
17
+-- 新增记录
18
+function root:add_battle_record(settle, totalPrice)
19
+    if is_empty(settle) then
20
+        return false
21
+    end
22
+    if
23
+        is_empty(settle.roomId) or is_empty(settle.battleBoxList) or is_empty(settle.createTime) or
24
+            is_empty(settle.battleTime) or
25
+            is_empty(settle.battleId) or
26
+            is_empty(settle.winUid) or
27
+            is_empty(settle.battlePlayerList)
28
+     then
29
+        return false
30
+    end
31
+    local expireTime = timeUtil.now() + timeUtil.SEC_PER_DAY * 365
32
+    local columns =
33
+        "`roomId`,`battleBoxList`,`createTime`,`battleTime`,`battleId`,`winUid`,`totalPrice`,`battlePlayerList`,`expireTime`"
34
+    local values =
35
+        string.format(
36
+        "%s,'%s',%s,%s,'%s',%s,%s,'%s',%s",
37
+        tostring(settle.roomId),
38
+        cjson_encode(settle.battleBoxList),
39
+        tostring(settle.createTime),
40
+        tostring(settle.battleTime),
41
+        tostring(settle.battleId),
42
+        tostring(settle.winUid),
43
+        tostring(totalPrice),
44
+        cjson_encode(settle.battlePlayerList),
45
+        tostring(expireTime)
46
+    )
47
+    for k, v in ipairs(settle.battlePlayerList) do
48
+        local key = string.format("`battleUid%s`", tostring(k))
49
+        columns = columns .. "," .. key
50
+        values = values .. string.format(",%s", tostring(v.uid))
51
+    end
52
+
53
+    local sql = string.format("INSERT INTO `mdl_battlerecord` (%s) VALUES (%s); ", columns, values)
54
+
55
+    local ok = mysqlUtil:insert(sql)
56
+    log.info("add_battle_record sql[%s] ok[%s]", tostring(sql), tostring(ok))
57
+    return ok
58
+end
59
+
60
+-- 打包历史战绩
61
+function root:pack_battle_record_list(data)
62
+    local list = {}
63
+    if is_empty(data) then
64
+        return list
65
+    end
66
+    for _, v in ipairs(data) do
67
+        -- 房间信息
68
+        local roomInfo = {
69
+            roomId = tonumber(v.roomId),
70
+            battleBoxList = cjson_decode(v.battleBoxList),
71
+            status = 2,
72
+            createTime = tonumber(v.createTime),
73
+            battleTime = tonumber(v.battleTime),
74
+            playerList = {}
75
+        }
76
+        -- 战斗玩家列表
77
+        local battlePlayerList = cjson_decode(v.battlePlayerList)
78
+        for _, _v in ipairs(battlePlayerList) do
79
+            local info = {
80
+                playerInfo = util_player:get_base_info(v.uid),
81
+                seatId = _v.seatId
82
+            }
83
+            table.insert(roomInfo.playerList, info)
84
+        end
85
+        local info = {
86
+            roomInfo = roomInfo,
87
+            battleId = v.battleId,
88
+            winUid = tonumber(v.winUid),
89
+            battlePlayerList = battlePlayerList
90
+        }
91
+        table.insert(list, info)
92
+    end
93
+    return list
94
+end
95
+
96
+-- 获取精彩对战记录
97
+function root:get_brilliant_record_list()
98
+    local minTotalPrice = boxAdapt:battle_const("battle_box_open_total_price_is_exciting_battle") or 10000
99
+    local count = boxAdapt:battle_const("exciting_battle_record_num") or 20
100
+    local sql =
101
+        string.format(
102
+        "SELECT * FROM `mdl_battlerecord` WHERE `totalPrice`>=%s ORDER BY battleTime DESC limit %s",
103
+        tostring(minTotalPrice),
104
+        tostring(count)
105
+    )
106
+    local ok, ret = mysqlUtil:select(sql)
107
+    if not ok or is_empty(ret) then
108
+        return
109
+    end
110
+    return self:pack_battle_record_list(ret)
111
+end
112
+
113
+-- 获取对战记录
114
+function root:get_record_list(lastTime)
115
+    lastTime = lastTime or timeUtil.now()
116
+    local count = 20
117
+    local sql =
118
+        string.format(
119
+        "SELECT * FROM `mdl_battlerecord` WHERE `battleTime`<%s ORDER BY battleTime DESC limit %s",
120
+        tostring(lastTime),
121
+        tostring(count)
122
+    )
123
+    local ok, ret = mysqlUtil:select(sql)
124
+    if not ok or is_empty(ret) then
125
+        return
126
+    end
127
+    return self:pack_battle_record_list(ret)
128
+end
129
+
130
+-- 获取玩家个人对战记录
131
+function root:get_player_record_list(uid, lastTime)
132
+    if is_empty(uid) then
133
+        return
134
+    end
135
+    lastTime = lastTime or timeUtil.now()
136
+    local count = 20
137
+    local sql =
138
+        string.format(
139
+        "SELECT * FROM `mdl_battlerecord` WHERE `battleTime`<%s and (`battleUid1`=%s or `battleUid2`=%s or `battleUid3`=%s or `battleUid4`=%s or `battleUid5`=%s) ORDER BY battleTime DESC limit %s",
140
+        tostring(lastTime),
141
+        tostring(uid),
142
+        tostring(uid),
143
+        tostring(uid),
144
+        tostring(uid),
145
+        tostring(uid),
146
+        tostring(count)
147
+    )
148
+    local ok, ret = mysqlUtil:select(sql)
149
+    if not ok or is_empty(ret) then
150
+        return
151
+    end
152
+    return self:pack_battle_record_list(ret)
153
+end
154
+
155
+return root

+ 22 - 1
dev/utils/util_box.lua

@@ -117,7 +117,7 @@ function root:dream_add_record(uid, itemId, odds, dropItem, isWin)
117 117
     end
118 118
 
119 119
     local dropTime = timeUtil.now()
120
-    local expireTime = dropItem + timeUtil.SEC_PER_DAY * 365
120
+    local expireTime = dropTime + timeUtil.SEC_PER_DAY * 365
121 121
     local sql =
122 122
         string.format(
123 123
         "INSERT INTO `mdl_dream` (`uid`,`itemId`,`dropItem`,`price`,`odds`,`isWin`,`dropTime`,`expireTime`)" ..
@@ -242,4 +242,25 @@ function root:dream_del_day_statement(ti)
242 242
     lib_game_redis:del(key)
243 243
 end
244 244
 
245
+----------------------------------------
246
+-- 对战
247
+----------------------------------------
248
+-- 获取开箱物品
249
+function root:battle_get_box_drop_item_and_count(boxId)
250
+    local confList = boxAdapt:battle_get_box_item_list(boxId)
251
+    if is_empty(confList) then
252
+        return
253
+    end
254
+    -- 更新权重
255
+    for _, v in ipairs(confList) do
256
+        v.weight = 0
257
+        local price = resAdapt:get_item_price(v.itemId)
258
+        if not is_empty(price) then
259
+            v.weight = math.floor(v.weightByPrice / price)
260
+        end
261
+    end
262
+    local index = random_list_by_weight(confList)
263
+    return confList[index].itemId, confList[index].count
264
+end
265
+
245 266
 return root

+ 127 - 1
dev/utils/util_match.lua

@@ -10,9 +10,16 @@ local lib_battle_redis = require("lib_battle_redis")
10 10
 local timeUtil = require("utils.timeUtil")
11 11
 local redisBattleUtil = require("redisBattleUtil")
12 12
 local util_player = require("utils.util_player")
13
+local util_box = require("utils.util_box")
14
+local gameConst = require("const.gameConst")
15
+local util_user = require("utils.util_user")
16
+local nodeMgr = require("nodeMgr")
17
+local util_battle = require("utils.util_battle")
13 18
 
14 19
 local battleData = require("data.battle")
20
+local bagData = require("data.bag")
15 21
 local boxAdapt = require("adapt.boxAdapt")
22
+local resAdapt = require("adapt.resAdapt")
16 23
 
17 24
 local root = {}
18 25
 
@@ -349,12 +356,15 @@ function root:is_wait_battle_end(roomId)
349 356
     end
350 357
     local currTime = timeUtil.now()
351 358
     local createTime = redisBattleUtil.hget_int(key, "createTime")
352
-    local waitSeconds = 10
359
+    local waitSeconds = boxAdapt:battle_const("no_full_close_room_time") or 10
353 360
     if currTime < createTime + waitSeconds then
354 361
         return false
355 362
     end
356 363
     return true
357 364
 end
365
+----------------------------------------
366
+-- 战斗
367
+---------------------------------------
358 368
 -- 房间是否开始战斗
359 369
 function root:is_room_start_battle(roomId)
360 370
     local status = self:get_room_status(roomId)
@@ -372,8 +382,123 @@ function root:is_room_start_battle(roomId)
372 382
     local playCount = redisBattleUtil.hget_int(key, "playCount")
373 383
     return seatCount >= playCount
374 384
 end
385
+-- 生成战斗编号
386
+function root:gen_battle_id(roomId)
387
+    local currTime = timeUtil.now()
388
+    return string.format("BT%s%08d", os.date("%Y%m%d", currTime), roomId)
389
+end
390
+-- 战斗
391
+function root:start_battle(roomId)
392
+    if is_empty(roomId) then
393
+        return false
394
+    end
395
+    local key = _get_room_key(roomId)
396
+    -- 房间是否存在
397
+    local isExist = lib_battle_redis:exists(key)
398
+    if not isExist then
399
+        -- 从活跃房间集合删除
400
+        lib_battle_redis:sismerber(_get_active_room_id_key(), roomId)
401
+        return false
402
+    end
403
+    -- 更新状态
404
+    redisBattleUtil.hset(key, "status", 1)
405
+    local battleId = self:gen_battle_id(roomId)
406
+    local battleBoxList = redisBattleUtil.hget_json(key, "boxIdList")
407
+    local playerList = redisBattleUtil.hget_json(key, "playerList")
408
+    -- 射击轮次
409
+    local rounds = {}
410
+    local totalPrice = 0
411
+    for k, v in ipairs(battleBoxList) do
412
+        local roundInfo = {round = k, shotList = {}}
413
+        for _, _v in ipairs(playerList) do
414
+            if _v.seatId and _v.seatId > 0 then
415
+                local itemId = util_box:battle_get_box_drop_item_and_count(v)
416
+                local price = resAdapt:get_item_price(itemId)
417
+                local shotInfo = {
418
+                    uid = _v.uid,
419
+                    itemId = itemId,
420
+                    price = price
421
+                }
422
+                table.insert(roundInfo.shotList, shotInfo)
423
+
424
+                totalPrice = totalPrice + price
425
+            end
426
+        end
427
+        table.insert(rounds, roundInfo)
428
+    end
429
+    -- 胜利玩家
430
+    local mapUidPrice = {}
431
+    for _, v in ipairs(rounds) do
432
+        for _, _v in ipairs(v.shotList) do
433
+            mapUidPrice[_v.uid] = (mapUidPrice[_v.uid] or 0) + _v.price
434
+        end
435
+    end
436
+    local winUid = nil
437
+    local maxPrice = nil
438
+    for uid, price in pairs(mapUidPrice) do
439
+        if maxPrice == nil or price > maxPrice then
440
+            winUid = uid
441
+        end
442
+    end
443
+    -- 战斗玩家列表
444
+    local n1Price = resAdapt:get_item_price(gameConst.ITEM_ID.N1)
445
+    local battlePlayerList = {}
446
+    for _, v in ipairs(playerList) do
447
+        if v.seatId and v.seatId > 0 then
448
+            if v.uid == winUid then
449
+                -- 收集所有玩家射击
450
+                local info = {uid = v.uid, seatId = v.seatId, shotList = {}}
451
+                for _, _v in ipairs(rounds) do
452
+                    for _, __v in ipairs(_v.shotList) do
453
+                        table.insert(info.shotList, {itemId = __v.itemId, price = __v.price})
454
+                    end
455
+                end
456
+                table.insert(battlePlayerList, info)
457
+            else
458
+                -- 安慰奖
459
+                local info = {
460
+                    uid = v.uid,
461
+                    seatId = v.seatId,
462
+                    shotList = {{itemId = gameConst.ITEM_ID.N1, price = n1Price}}
463
+                }
464
+                table.insert(battlePlayerList, info)
465
+            end
466
+        end
467
+    end
468
+    -- 发放奖励
469
+    for _, v in ipairs(battleBoxList) do
470
+        local items = {}
471
+        for _, _v in ipairs(v.shotList) do
472
+            table.insert(items, {id = v.itemId, count = 1})
473
+        end
474
+        local keyEvent = string.format("battle-settle-%s-%s", battleId, tostring(v.uid == winUid and 1 or 0))
475
+        bagData:add_items(v.uid, items, keyEvent)
476
+    end
477
+
478
+    redisBattleUtil.hset(key, "status", 2)
479
+    local settle = {
480
+        roomInfo = self:pack_room_info(roomId),
481
+        winUid = winUid,
482
+        battleId = battleId,
483
+        rounds = rounds,
484
+        battlePlayerList = battlePlayerList
485
+    }
486
+    -- 通知所有房间玩家
487
+    for _, v in ipairs(playerList) do
488
+        util_user:user_proto_notify(v.uid, "on_room_battle_settle", {settle = settle})
489
+    end
490
+    -- 新增战斗记录
491
+    util_battle:add_battle_record(settle, totalPrice)
492
+    -- 关闭房间
493
+    -- 删除房间信息
494
+    lib_battle_redis:del(key)
495
+    -- 从活跃房间集合删除
496
+    lib_battle_redis:sismerber(_get_active_room_id_key(), roomId)
497
+    -- 通知在线玩家 - 销毁房间
498
+    nodeMgr.broadcast_proto_notify("on_room_destroy", {roomId = roomId})
499
+end
375 500
 ----------------------------------------
501
+-- 玩家战斗信息
376 502
 ----------------------------------------
377 503
 local bagData = require("data.bag")
378 504
 -- 绑定房间

+ 27 - 0
nodes/game/interface/room.lua

@@ -11,6 +11,7 @@ local util_match = require("utils.util_match")
11 11
 local gameConst = require("const.gameConst")
12 12
 local nodeMgr = require("nodeMgr")
13 13
 local nodeUtil = require("utils.nodeUtil")
14
+local util_battle = require("utils.util_battle")
14 15
 
15 16
 local boxAdapt = require("adapt.boxAdapt")
16 17
 local bagData = require("data.bag")
@@ -37,6 +38,12 @@ function root:room_create_room(role, msg)
37 38
     if not boxAdapt:battle_is_box_list_valid(battleBoxList) then
38 39
         return code.UNKNOWN
39 40
     end
41
+    -- 对战人数限制
42
+    local minPlayCount = boxAdapt:battle_const("min_play_count") or 2
43
+    local maxPlayCount = boxAdapt:battle_const("max_play_count") or 3
44
+    if playCount < minPlayCount or playCount > maxPlayCount then
45
+        return code.UNKNOWN
46
+    end
40 47
     -- 消耗
41 48
     local price = boxAdapt:battle_get_box_price(battleBoxList)
42 49
     local ok, costItems = bagData:is_enough(uid, {{id = gameConst.ITEM_ID.DIAMOND, count = price}})
@@ -174,4 +181,24 @@ function root:room_player_leave(role, msg)
174 181
     return code.OK
175 182
 end
176 183
 
184
+-- 获取房间对战记录列表 - 每次请求返回20条
185
+function root:room_get_record_list(role, msg)
186
+    local lastTime = msg.lastTime
187
+    local list = util_battle:get_record_list(lastTime)
188
+    return code.OK, {list = list}
189
+end
190
+
191
+-- 获取玩家个人对战记录 - 每次请求返回20条
192
+function root:room_get_player_record_list(role, msg)
193
+    local lastTime = msg.lastTime
194
+    local list = util_battle:get_player_record_list(role.uid, lastTime)
195
+    return code.OK, {list = list}
196
+end
197
+
198
+-- 获取精彩对战记录列表 - 仅返回当前最近20(配置)条记录
199
+function root:room_get_brilliant_record_list(role, msg)
200
+    local list = util_battle:get_brilliant_record_list()
201
+    return code.OK, {list = list}
202
+end
203
+
177 204
 return root

+ 7 - 5
nodes/global/main.lua

@@ -1,9 +1,10 @@
1 1
 --[[
2
-Author: zkj
3
-Date: 2021-06-24 10:54:08
4
-LastEditTime: 2021-07-13 17:00:28
5
-LastEditors: Please set LastEditors
6
-Description: 全局业务服
2
+Descripttion:全局业务服
3
+version:
4
+Author: Neo,Huang
5
+Date: 2023-11-16 21:45:09
6
+LastEditors: Neo,Huang
7
+LastEditTime: 2023-11-18 13:58:16
7 8
 --]]
8 9
 local skynet = require "skynet"
9 10
 require "skynet.manager"
@@ -26,6 +27,7 @@ skynet.start(
26 27
         skynet.uniqueservice("backupSrv")
27 28
         skynet.uniqueservice("mailSrv")
28 29
         skynet.uniqueservice("dreamSrv")
30
+        skynet.uniqueservice("battlerecordSrv")
29 31
 
30 32
         -- 集群
31 33
         init_nodes:init_cluster()

+ 34 - 0
nodes/global/service/battlerecordSrv.lua

@@ -0,0 +1,34 @@
1
+--[[
2
+Descripttion:战斗记录
3
+version:
4
+Author: Neo,Huang
5
+Date: 2023-11-18 13:56:05
6
+LastEditors: Neo,Huang
7
+LastEditTime: 2023-11-18 13:57:08
8
+--]]
9
+local timer = require("timer")
10
+local baseService = require("baseService")
11
+local lib_game_mysql = require("lib_game_mysql")
12
+
13
+local timerDelExpire = nil
14
+
15
+local CMD = {}
16
+
17
+-- 清理过期追梦记录
18
+local function l_del_expire_record()
19
+	local currTime = skynet_time()
20
+	local sql = string.format("delete from mdl_battlerecord where expireTime >0 and expireTime < %s;", tostring(currTime))
21
+	local ret = lib_game_mysql:query(sql)
22
+	log.info("l_del_expire_record sql[%s] ret[%s]", tostring(sql), tostring(ret))
23
+end
24
+
25
+function CMD.onStart()
26
+	timerDelExpire = timer.timeOut(60, l_del_expire_record)
27
+end
28
+
29
+function CMD.onStop()
30
+	-- 取消定时器
31
+	timerDelExpire.func = nil
32
+end
33
+
34
+baseService.start(CMD, ".battlerecordCenter", true)

+ 7 - 0
nodes/match/service/srvRoom.lua

@@ -10,6 +10,8 @@ local code = require("code")
10 10
 local baseService = require("baseService")
11 11
 local util_match = require("utils.util_match")
12 12
 local util_user = require("utils.util_user")
13
+local nodeMgr = require("nodeMgr")
14
+local gameConst = require("const.gameConst")
13 15
 
14 16
 local battleData = require("data.battle")
15 17
 local bagData = require("data.bag")
@@ -116,6 +118,11 @@ function root.seat_down(uid, roomId, seatId)
116 118
         changeRoomPlayer = {util_match:pack_room_player_info(roomId, uid)}
117 119
     }
118 120
     nodeMgr.broadcast_proto_notify("on_room_player_change", pack)
121
+
122
+    -- 是否开始战斗
123
+    if util_match:is_room_start_battle(roomId) then
124
+        util_match:start_battle(roomId)
125
+    end
119 126
 end
120 127
 
121 128
 function root.onStart()