PlayerPkValue_1.lua 20 KB

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