PlayerPkValue.lua 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489
  1. -- 玩家PK值功能
  2. pk = {}
  3. DropEquipType = { 1, 2, 3, 4, 5, 6, 7, 8, 9 }
  4. ---设置玩家pk值
  5. ---@param actor 玩家对象
  6. ---@param pkValue PK值
  7. function pk.setpkvalue(actor, pkValue)
  8. --特定的线路不增加PK值
  9. local mapUid = getbaseinfo(actor, "unimapid")
  10. local mapInfo = getmapinfobyid(actor, mapUid)
  11. if not table.isNullOrEmpty(mapInfo) then
  12. local mapCfgId = table.getValue(mapInfo, "cfgid")
  13. local mapLine = table.getValue(mapInfo, "line")
  14. local pkLine = ConfigDataManager.getTableValue("cfg_map_line", "pkline", "id", mapCfgId)
  15. if not string.isNullOrEmpty(pkLine) then
  16. local pkLines = string.split(pkLine, "|")
  17. for _, line in pairs(pkLines) do
  18. if tonumber(mapLine) == tonumber(line) then
  19. -- jprint("pk线路不增加PK值", mapUid, mapCfgId, mapLine, actor)
  20. return
  21. end
  22. end
  23. end
  24. -- 副本世界boss不增加PK值
  25. local dupInfo = getduplicate(mapUid)
  26. if dupInfo ~= nil then
  27. local dupType = dupInfo["type"]
  28. if dupType == DuplicateType.WORLD_BOSS then
  29. return
  30. end
  31. end
  32. end
  33. setplaydef(actor, PlayerDefKey.pkValue.PK_VALUE, pkValue)
  34. -- 获取附近角色,给每一个角色发送对应角色PK值变化的消息
  35. local sendPlayerIds = {}
  36. local nearPlayers = getnarplayer(actor)
  37. if nearPlayers or #nearPlayers > 0 then
  38. for i = 1, #nearPlayers do
  39. sendPlayerIds[i] = nearPlayers[i].luaplayer
  40. end
  41. sendPlayerIds[#sendPlayerIds + 1] = actor
  42. if sendPlayerIds and #sendPlayerIds > 0 then
  43. for i = 1, #sendPlayerIds do
  44. sendluamsg(
  45. sendPlayerIds[i],
  46. LuaMessageIdToClient.PK_VALUE_CHANGE,
  47. {
  48. rid = actor,
  49. pkValue = pkValue
  50. }
  51. )
  52. end
  53. end
  54. else
  55. sendluamsg(
  56. actor,
  57. LuaMessageIdToClient.PK_VALUE_CHANGE,
  58. {
  59. rid = actor,
  60. pkValue = tonumber(pk.getpkvalue(actor))
  61. }
  62. )
  63. end
  64. end
  65. ---获取指定玩家PK值
  66. ---@param actor 玩家对象
  67. ---@return PK值
  68. function pk.getpkvalue(actor)
  69. local pkValue = getplaydef(actor, PlayerDefKey.pkValue.PK_VALUE)
  70. if not pkValue then
  71. return 0
  72. end
  73. return pkValue
  74. end
  75. ---击杀玩家处理
  76. ---@param actor 攻击玩家对象
  77. ---@param diePlayer 死亡玩家对象
  78. function pk.killplayerpkvaluehandle(actor, diePlayer)
  79. if RolandSeige.IsPlayerInRoland(actor) then
  80. return
  81. end
  82. -- 清除diePlayer身上存储的防卫时间信息
  83. setplaydef(diePlayer, PlayerDefKey.pkValue.LAST_ATTACK, {})
  84. -- 判断是否在防卫时间内击杀的玩家,如果在防卫时间内击杀玩家则不增加PK值
  85. local attackInfo = getplaydef(actor, PlayerDefKey.pkValue.LAST_ATTACK)
  86. local now = tonumber(getbaseinfo("now"))
  87. local defenseTime = ConfigDataManager.getTableValue("cfg_global", "value", "id", GlobalConfigId.DEFENSE_TIME)
  88. local attackerName = getbaseinfo(actor, "rolename")
  89. local defenserName = getbaseinfo(diePlayer, "rolename")
  90. if attackInfo and next(attackInfo) then
  91. for index = 1, #attackInfo do
  92. if attackInfo[index].attackId == diePlayer then
  93. if defenseTime and now - tonumber(attackInfo[index].timeStamp) <= tonumber(defenseTime) then
  94. gameDebug.print(actor:toString() .. "在防卫时间内击杀了" .. tostring(diePlayer) .. " 不增加PK值")
  95. noticeTip.noticeinfo(actor, StringIdConst.TEXT506, attackerName, "在防卫时间内击杀了", defenserName)
  96. return
  97. end
  98. end
  99. end
  100. end
  101. -- 判断击杀的玩家是否是红名玩家,是红名玩家不增加PK值
  102. local redNameNeed = ConfigDataManager.getTableValue("cfg_pk_count", "redNameNeed", "id", 1)
  103. local diePlayerPkValue = pk.getpkvalue(diePlayer)
  104. if redNameNeed and redNameNeed ~= "" and diePlayerPkValue and tonumber(diePlayerPkValue) >= tonumber(redNameNeed) then
  105. gameDebug.print(actor:toString() .. "击杀了红名玩家" .. tostring(diePlayer) .. " 不增加PK值")
  106. noticeTip.noticeinfo(actor, StringIdConst.TEXT506, attackerName, "击杀了红名玩家", defenserName)
  107. return
  108. end
  109. -- 根据配表增加PK值
  110. local curPkValue = pk.getpkvalue(actor)
  111. if curPkValue and curPkValue ~= "" and curPkValue > 0 then
  112. local addByKill = 0
  113. local pkCountTable = ConfigDataManager.getList("cfg_pk_count")
  114. if pkCountTable or next(pkCountTable) then
  115. local maxPkValue = 0
  116. for i = 1, #pkCountTable do
  117. local nameColor = pkCountTable[i].namecolor
  118. local minPkValue = pk.getSplitByHash(nameColor)[1]
  119. maxPkValue = pk.getSplitByHash(nameColor)[2]
  120. if curPkValue >= tonumber(minPkValue) and curPkValue <= tonumber(maxPkValue) then
  121. addByKill = pkCountTable[i].addbykill
  122. end
  123. end
  124. if tonumber(addByKill) == 0 and tonumber(curPkValue) > tonumber(maxPkValue) then
  125. addByKill = pkCountTable[#pkCountTable].addbykill
  126. end
  127. if addByKill == 0 then
  128. addByKill = pkCountTable[1].addbykill
  129. end
  130. end
  131. pk.setpkvalue(actor, tonumber(addByKill) + tonumber(curPkValue))
  132. else
  133. local addByKill = ConfigDataManager.getTableValue("cfg_pk_count", "addByKill", "id", 1)
  134. pk.setpkvalue(actor, addByKill)
  135. end
  136. local reduceByTime = ConfigDataManager.getTableValue("cfg_pk_count", "reduceByTime", "id", 1)
  137. local splitString = pk.getSplitByHash(reduceByTime)
  138. if splitString then
  139. setplaydef(actor, PlayerDefKey.pkValue.PK_REDUCE_TIME, splitString[1])
  140. noticeTip.noticeinfo(actor, StringIdConst.TEXT506, attackerName, "击杀了玩家", defenserName)
  141. else
  142. gameDebug.print("killplayerpkvaluehandle cfg_pk_count表reduceByTime is null")
  143. return
  144. end
  145. end
  146. ---玩家被攻击处理
  147. ---@param actor 玩家对象
  148. ---@param fightParam 被攻击参数 caster:攻击者对象、target:被攻击者对象、mapid:地图id、skillid:技能id、skilllevel:技能等级、castertype:攻击者类型、targettype:被攻击者类型
  149. function pk.underattackpkvaluehandle(actor, fightParam)
  150. -- 当玩家攻击玩家时进行后面的逻辑
  151. if fightParam.castertype and fightParam.targettype and fightParam.castertype == 1 and fightParam.targettype == 1 then
  152. local lastAttackInfo = getplaydef(actor, PlayerDefKey.pkValue.LAST_ATTACK)
  153. if not lastAttackInfo or lastAttackInfo == "" or not next(lastAttackInfo) then
  154. -- 没有玩家攻击时间信息存入新的
  155. local attackInfo = {
  156. attackId = fightParam.caster,
  157. timeStamp = tonumber(getbaseinfo("now"))
  158. }
  159. setplaydef(actor, PlayerDefKey.pkValue.LAST_ATTACK, attackInfo)
  160. else
  161. -- 有玩家攻击时间信息遍历判断是否已经存在攻击者id
  162. -- 如果存在,判断时间是否超时,如果超时存入新的时间戳
  163. local exists = false
  164. local now = tonumber(getbaseinfo("now"))
  165. local defenseTime =
  166. ConfigDataManager.getTableValue("cfg_global", "value", "id", GlobalConfigId.DEFENSE_TIME)
  167. for index = 1, #lastAttackInfo do
  168. if tonumber(lastAttackInfo[index].attackId) == tonumber(fightParam.caster) then
  169. exists = true
  170. local lastTime = lastAttackInfo[index].timeStamp
  171. if defenseTime and (now - tonumber(lastTime)) > tonumber(defenseTime) then
  172. table.remove(lastAttackInfo, index)
  173. lastAttackInfo[#lastAttackInfo + 1] = {
  174. attackId = fightParam.caster,
  175. timeStamp = now
  176. }
  177. setplaydef(actor, PlayerDefKey.pkValue.LAST_ATTACK, lastAttackInfo)
  178. end
  179. break
  180. end
  181. end
  182. -- 如果不存在则存入
  183. if not exists then
  184. lastAttackInfo[#lastAttackInfo + 1] = {
  185. attackId = fightParam.caster,
  186. timeStamp = tonumber(getbaseinfo("now"))
  187. }
  188. setplaydef(actor, PlayerDefKey.pkValue.LAST_ATTACK, lastAttackInfo)
  189. end
  190. end
  191. pk.processGrayState(fightParam.caster, fightParam.target)
  192. end
  193. end
  194. ---怪物击杀PK值处理
  195. ---@param actor 玩家对象
  196. ---@param monsterCfgId 怪物configId
  197. ---@param monsterLevel 怪物等级
  198. function pk.killmonsterpkvaluehandle(actor, monsterCfgId, monsterLevel)
  199. local levelDiff = ConfigDataManager.getTableValue("cfg_pk_count", "levelDiff", "id", 1)
  200. local level = getbaseinfo(actor, "level")
  201. if levelDiff == nil or levelDiff == "" or tonumber(level) - tonumber(levelDiff) >= tonumber(monsterLevel) then
  202. return
  203. end
  204. local pkValue = pk.getpkvalue(actor)
  205. if pkValue and pkValue > 0 then
  206. local monsterType = ConfigDataManager.getTableValue("cfg_monster", "type", "id", monsterCfgId)
  207. local reduceByMonster = ConfigDataManager.getTableValue("cfg_pk_count", "reduceByMonster", "id", 1)
  208. local time = pk.getSplitByHash(reduceByMonster)
  209. if time and next(time) then
  210. local reduceTime = getplaydef(actor, PlayerDefKey.pkValue.REDUCE_TIME)
  211. if reduceTime and reduceTime ~= "" then
  212. setplaydef(
  213. actor,
  214. PlayerDefKey.pkValue.REDUCE_TIME,
  215. tonumber(reduceTime) + tonumber(time[tonumber(monsterType)])
  216. )
  217. else
  218. setplaydef(actor, PlayerDefKey.pkValue.REDUCE_TIME, tonumber(time[tonumber(monsterType)]))
  219. end
  220. end
  221. end
  222. end
  223. ---角色PK值心跳
  224. ---@param actor 玩家对象
  225. function pk.SecondHeartPkValue(actor)
  226. local pkValue = pk.getpkvalue(actor)
  227. if pkValue and tonumber(pkValue) > 0 then
  228. local pkValueReduceTime = getplaydef(actor, PlayerDefKey.pkValue.PK_REDUCE_TIME)
  229. if pkValueReduceTime and tonumber(pkValueReduceTime) > 0 then
  230. local reduceTime = getplaydef(actor, PlayerDefKey.pkValue.REDUCE_TIME)
  231. if reduceTime and tonumber(reduceTime) > 0 then
  232. if tonumber(reduceTime) >= tonumber(pkValueReduceTime) then
  233. setplaydef(
  234. actor,
  235. PlayerDefKey.pkValue.REDUCE_TIME,
  236. tonumber(reduceTime) - tonumber(pkValueReduceTime)
  237. )
  238. setplaydef(actor, PlayerDefKey.pkValue.PK_REDUCE_TIME, 0)
  239. pkValueReduceTime = 0
  240. else
  241. setplaydef(
  242. actor,
  243. PlayerDefKey.pkValue.PK_REDUCE_TIME,
  244. tonumber(pkValueReduceTime) - tonumber(reduceTime)
  245. )
  246. setplaydef(actor, PlayerDefKey.pkValue.REDUCE_TIME, 0)
  247. return
  248. end
  249. else
  250. pkValueReduceTime = tonumber(pkValueReduceTime) - 5
  251. if pkValueReduceTime > 0 then
  252. setplaydef(actor, PlayerDefKey.pkValue.PK_REDUCE_TIME, pkValueReduceTime)
  253. return
  254. end
  255. end
  256. end
  257. if pkValueReduceTime and pkValueReduceTime <= 0 then
  258. local reduceByTime = ConfigDataManager.getTableValue("cfg_pk_count", "reduceByTime", "id", 1)
  259. local splitString = pk.getSplitByHash(reduceByTime)
  260. if splitString and next(splitString) then
  261. pk.setpkvalue(actor, pkValue - splitString[2])
  262. setplaydef(actor, PlayerDefKey.pkValue.PK_REDUCE_TIME, splitString[1])
  263. end
  264. end
  265. else
  266. return
  267. end
  268. end
  269. ---免罪符使用PK值处理
  270. ---@param actor 玩家对象
  271. ---@param itemConfigId 道具configId
  272. ---@param count 数量
  273. function pk.exonerationcharmpkvaluehnadle(actor, itemConfigId, count)
  274. local value =
  275. ConfigDataManager.getTableValue("cfg_global", "value", "id", GlobalConfigId.EXONERATION_CHARM_MINUS_COUNT)
  276. for i = 1, tonumber(count) do
  277. if itemConfigId == ItemConfigId.EXONERATION_CHARM then
  278. if value then
  279. local pkValue = pk.getpkvalue(actor)
  280. if pkValue and pkValue > 0 then
  281. pkValue = tonumber(pkValue) - tonumber(value)
  282. if pkValue < 0 then
  283. pkValue = 0
  284. end
  285. end
  286. pk.setpkvalue(actor, pkValue)
  287. end
  288. end
  289. end
  290. end
  291. ---角色进入视野发送玩家的PK值
  292. ---@param actor 玩家对象
  293. function pk.sendenterviewpkvalue(actor, targetPlayer)
  294. sendluamsg(
  295. targetPlayer,
  296. LuaMessageIdToClient.PK_VALUE_CHANGE,
  297. {
  298. rid = actor,
  299. pkValue = tonumber(pk.getpkvalue(actor))
  300. }
  301. )
  302. sendluamsg(
  303. actor,
  304. LuaMessageIdToClient.PK_VALUE_CHANGE,
  305. {
  306. rid = targetPlayer,
  307. pkValue = tonumber(pk.getpkvalue(targetPlayer))
  308. }
  309. )
  310. sendluamsg(
  311. actor,
  312. LuaMessageIdToClient.PK_VALUE_CHANGE,
  313. {
  314. rid = actor,
  315. pkValue = tonumber(pk.getpkvalue(actor))
  316. }
  317. )
  318. end
  319. ---获取字符串井号切割后的结果
  320. ---@param str 原字符串
  321. ---@return 切割后的table
  322. function pk.getSplitByHash(str)
  323. local data = string.split(str, "#")
  324. if data and next(data) then
  325. return data
  326. else
  327. return nil
  328. end
  329. end
  330. -- 玩家被击杀
  331. function pk.PlayerDie(actor, dieInfo, killInfo)
  332. local killerType = killInfo.type
  333. if killerType ~= MapObjectType.PLAYER then
  334. return
  335. end
  336. local killerId = killInfo.id
  337. local killer = getactor(actor, killerId)
  338. local killerName = killInfo.name
  339. local mapCfgId = dieInfo.mapCfgId
  340. local pkValue = pk.getpkvalue(actor)
  341. -- 根据表数据获取掉落道具及掉落装备概率
  342. if not pkValue or pkValue == "" or pkValue <= 0 then
  343. return
  344. end
  345. local oneTable
  346. local pkCountTable = ConfigDataManager.getList("cfg_pk_count")
  347. if pkCountTable or next(pkCountTable) then
  348. for i = 1, #pkCountTable do
  349. local nameColor = pkCountTable[i].namecolor
  350. local minPkValue = pk.getSplitByHash(nameColor)[1]
  351. local maxPkValue = pk.getSplitByHash(nameColor)[2]
  352. if pkValue >= tonumber(minPkValue) and pkValue <= tonumber(maxPkValue) then
  353. oneTable = pkCountTable[i]
  354. end
  355. end
  356. end
  357. if oneTable == nil then
  358. return
  359. end
  360. local mapId = getbaseinfo(actor, "unimapid")
  361. local x = getbaseinfo(actor, "x")
  362. local y = getbaseinfo(actor, "y")
  363. -- 被击杀掉落道具
  364. local dropItem = string.split(oneTable.dropitem, "#")
  365. local itemCfgId = tonumber(dropItem[1]) or 0
  366. local count = tonumber(dropItem[2])
  367. local itemConfig = ConfigDataManager.getById("cfg_item", itemCfgId)
  368. if itemConfig then
  369. if tonumber(itemConfig.type) == ItemType.EQUIP then
  370. -- 暂时不会配置装备
  371. else
  372. -- 非装备扣除数量然后地上生成
  373. local ownCount = getbagitemcountbyid(actor, itemCfgId)
  374. if ownCount < count then
  375. count = ownCount
  376. end
  377. if count > 0 and itemCfgId > 0 then
  378. local dropTime = string.tonumber(ConfigDataManager.getTableValue("cfg_item", "dropTime", "id", itemCfgId)) + 1000
  379. removeitemfrombag(actor, itemCfgId, count, 0, 9999, "红名惩罚")
  380. throwitem(killer, mapId, x, y, 1, itemCfgId, count, dropTime, 3, 0)
  381. -- info("红名惩罚:玩家死亡掉落道具。", actor:toString(), itemCfgId, count)
  382. -- 发邮件
  383. local itemName = itemConfig.name
  384. sendconfigmailbyrid(actor, getbaseinfo(actor, "rid"), MailConfig.PK_DROP_ITEM, {}, killerName .. "#" .. count .. "#" .. itemName)
  385. end
  386. end
  387. end
  388. -- 被击杀掉落穿戴装备概率
  389. local dropRate = string.tonumber(oneTable.dropequip) / 10000
  390. local finalDropRate = LineManager.applyDropRate(actor, dropRate) -- 应用线路掉落倍率 2025.08.23 拓展地图线路
  391. if math.selectRate(finalDropRate) then
  392. -- 先从背包找
  393. local isDroped = false
  394. local allItemInfo = getallbagiteminfo(actor)
  395. math.shuffleTable(allItemInfo)
  396. for _, oneItem in pairs(allItemInfo) do
  397. -- 装备且非绑定状态
  398. if oneItem.type == ItemType.EQUIP then
  399. if oneItem.isbind == false then
  400. local equipCfgId = oneItem.cfgid
  401. local subType = tonumber(ConfigDataManager.getTableValue("cfg_item", "subType", "id", equipCfgId))
  402. if table.contains(DropEquipType, subType) then
  403. isDroped = true
  404. -- 从背包掉落道具
  405. local dropTime = string.tonumber(ConfigDataManager.getTableValue("cfg_item", "dropTime", "id", equipCfgId)) + 1000
  406. dropequip(actor, oneItem.id, killerId, dropTime)
  407. -- info("红名惩罚:玩家死亡掉落装备。", actor:toString(), oneItem)
  408. -- 发邮件
  409. local equipName = ConfigDataManager.getTableValue("cfg_item", "name", "id", equipCfgId)
  410. sendconfigmailbyrid(actor, getbaseinfo(actor, "rid"), MailConfig.PK_DROP_EQUIP, {}, killerName .. "#" .. equipName)
  411. break
  412. end
  413. end
  414. end
  415. end
  416. if not isDroped then
  417. -- 从穿戴栏找
  418. local allEquip = getputonequipinfo(actor)
  419. math.shuffleTable(allEquip)
  420. for _, oneEquip in pairs(allEquip) do
  421. if oneEquip.isbind == false then
  422. if table.contains(DropEquipType, oneEquip.subtype) then
  423. local equipCfgId = oneEquip.cfgid
  424. local dropTime = string.tonumber(ConfigDataManager.getTableValue("cfg_item", "dropTime", "id", equipCfgId)) + 1000
  425. dropequip(actor, oneEquip.id, killerId, dropTime)
  426. -- info("红名惩罚:玩家死亡掉落装备。", actor:toString(), oneEquip)
  427. -- 发邮件
  428. local equipName = ConfigDataManager.getTableValue("cfg_item", "name", "id", equipCfgId)
  429. sendconfigmailbyrid(actor, getbaseinfo(actor, "rid"), MailConfig.PK_DROP_EQUIP, {}, killerName .. "#" .. equipName)
  430. break
  431. end
  432. end
  433. end
  434. end
  435. end
  436. end
  437. -- 修改PK值增加逻辑
  438. function pk.addpkvalue(actor, pkValue)
  439. -- 特定的线路不增加PK值
  440. local mapUid = getbaseinfo(actor, "unimapid")
  441. local mapInfo = getmapinfobyid(actor, mapUid)
  442. if not table.isNullOrEmpty(mapInfo) then
  443. local mapCfgId = table.getValue(mapInfo, "cfgid")
  444. local mapLine = table.getValue(mapInfo, "line")
  445. -- 通过策略ID判断是否增加PK值
  446. local policy = GoldLine.GetLinePolicy(actor, mapCfgId, mapLine)
  447. if policy and policy.pvpEnabled == 0 then
  448. -- jprint("该线路禁止PK,不增加PK值", mapUid, mapCfgId, mapLine, actor)
  449. return
  450. end
  451. end
  452. -- 原有PK值增加逻辑...
  453. end
  454. -- 灰名处理
  455. function pk.processGrayState(actor, target)
  456. -- local actor = getactor(caster)
  457. local curPkValue = pk.getpkvalue(actor)
  458. local curtargetPkValue = pk.getpkvalue(target)
  459. if curPkValue <= 1 and curtargetPkValue <= 0 then
  460. if curPkValue < 1 then
  461. pk.setpkvalue(actor, 1)
  462. end
  463. local reduceByTime = ConfigDataManager.getTableValue("cfg_pk_count", "reduceByTime", "id", 1)
  464. local splitString = pk.getSplitByHash(reduceByTime)
  465. if splitString then
  466. setplaydef(actor, PlayerDefKey.pkValue.PK_REDUCE_TIME, splitString[1])
  467. end
  468. end
  469. end