123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778 |
- --赤色要塞副本
- RedFortress = {}
- local this = {}
- local NoteType = { KILL = 1, RELIVE = 2 }
- -- @description 请求进入副本
- -- @param 玩家对象;cfg_rep的id
- -- @return
- function RedFortress.ReqEnterFortress(actor, configId)
- -- 验证等级
- local playerLevel = tonumber(getbaseinfo(actor, "level"))
- local levelConfig = ConfigDataManager.getTableValue("cfg_rep", "level", "id", configId)
- local levelList = string.split(levelConfig, "#")
- local minLevel = tonumber(levelList[1])
- local maxLevel = tonumber(levelList[2])
- if playerLevel < minLevel or playerLevel > maxLevel then
- tipinfo(actor, "等级不足")
- error(actor:toString() .. "赤色要塞副本进入等级不符合要求{" .. playerLevel .. "}{" .. configId .. "}")
- return
- end
- -- 寻找空闲副本
- local mapId = DuplicateCommon.FindEnterableDupCommon(configId, 1)
- if mapId == 0 then
- mapId = DuplicateCommon.CreateDupMapCommon(actor, configId, true)
- end
- local x, y = DuplicateCommon.GetEnterPointXYCommon(configId)
- --回蓝回血
- DuplicateCommon.RecoverHPMP(actor)
- enterduplicate(actor, mapId, x, y)
- end
- -- @description 副本阶段更新
- -- @param 系统id;地图唯一id;副本类型;副本阶段(1-准备 2-战斗 3-结算);下一阶段开始时间戳;配置id(cfg_rep的id)
- -- @return
- function RedFortress.RedFortressStateUpdate(system, mapId, state, nextStateStartTime, configId)
- if state == DuplicateState.PREPARE then
- --准备阶段
- -- 初始化副本数据
- -- 战斗区域
- local fightAreaConfig = ConfigDataManager.getTableValue("cfg_repRedfortress", "start", "repId", configId)
- local fightAreaList = string.split(fightAreaConfig, "#")
- setenvirvar(mapId, DuplicateVarConst.RED_FORTRESS_FIGHT_AREA, fightAreaList)
- setenvirvar(mapId, DuplicateVarConst.RED_FORTRESS_PHASE, 1) --地图每减少一次阶段+1
- elseif state == DuplicateState.FIGHT then
- --更新阶段信息
- this.ResAllPlayCurrencyStateInfo(mapId)
- --战斗阶段
- -- 生成怪物
- local config = ConfigDataManager.getTableFirst("cfg_repRedfortress", "repId", configId)
- local monsterConfig = config.monsterid
- local monsterList = string.split(monsterConfig, "#")
- local playerCount = getplaycountinmap(mapId)
- playerCount = tonumber(playerCount or 1)
- local maxUnit = config.maxunit
- local leftCount = tonumber(maxUnit) - playerCount
- for i = 1, leftCount do
- --怪物id
- local randomIndex = math.random(#monsterList)
- local monsterId = monsterList[randomIndex]
- --随机点位
- local x, y = this.RandomFightPointXY(mapId, 100)
- mongen(mapId, x, y, 0, monsterId, 1)
- end
- -- 玩家传送到战斗区域
- local players = getmapplayer(mapId)
- for index, player in ipairs(players) do
- --随机点位
- local x, y = this.RandomFightPointXY(mapId, 100)
- maptransfer(player, x, y, 0, 0, 0)
- end
- this.ResAllPlayersTaskInfo(mapId, maxUnit)
- elseif state == DuplicateState.FINISH then
- --结算阶段
- this.ResAllPlayCurrencyStateInfo(mapId)
- -- 计算积分
- this.CalcuAndSetPlayerPointRank(mapId)
- end
- end
- -- @description 副本5秒钟心跳
- -- @param
- -- @return
- function RedFortress.Dup5SecondHeart(mapId, dupConfig, state)
- if state == DuplicateState.FIGHT then
- local area = getenvirvar(mapId, DuplicateVarConst.RED_FORTRESS_FIGHT_AREA)
- local x1 = tonumber(area[1])
- local x2 = tonumber(area[2])
- local y1 = tonumber(area[3])
- local y2 = tonumber(area[4])
- -- 不在区域内的怪物死亡
- local monsterInfoList = mapbossinfo(mapId)
- for key, monInfo in pairs(monsterInfoList) do
- local monId = monInfo["id"]
- local px = monInfo["x"]
- local py = monInfo["y"]
- local isIn = this.IsPointInArea(px, py, x1, x2, y1, y2)
- if isIn == false then
- local monster = getactor(monId, mapId)
- removemapobject(monster)
- end
- end
- end
- end
- -- @description 玩家进入副本后
- -- @param 玩家对象;地图唯一id;副本类型;副本阶段(1-准备 2-战斗 3-结算);下一阶段开始时间戳;配置id(cfg_rep的id)
- -- @return
- function RedFortress.AfterRedFortressEnter(actor, mapId, state, nextStateStartTime, configId)
- -- 清除召唤兽
- local petId = getbaseinfo(actor, "petid")
- local petActor = getactor(petId, mapId)
- removemapobject(petActor)
- local playerDupInfo = getplaydef(actor, RedFortressPlayerConst.MAP_INFO)
- -- 是否是新进入的副本
- local newEnter = false
- if playerDupInfo == nil or playerDupInfo == "" then
- newEnter = true
- else
- local lastMapId = playerDupInfo[1]
- if mapId ~= lastMapId then
- newEnter = true
- end
- end
- if newEnter == true then
- -- 进入新的副本,初始化玩家变量
- playerDupInfo = { mapId, configId }
- setplaydef(actor, RedFortressPlayerConst.MAP_INFO, playerDupInfo)
- -- 复活次数
- setplaydef(actor, RedFortressPlayerConst.RELIVE_TIMES, 0)
- -- 积分
- setplaydef(actor, RedFortressPlayerConst.KILL_SCORES, 0)
- -- 击杀数
- setplaydef(actor, RedFortressPlayerConst.KILL_COUNT, 0)
- -- 排名
- setplaydef(actor, RedFortressPlayerConst.PLAYER_RANK, 0)
- end
- this.ResCurrencyStateInfo(actor, mapId)
- if state == DuplicateState.PREPARE then
- -- 发送副本人数
- this.ResAllPreparePlayerCount(mapId)
- elseif state == DuplicateState.FIGHT then
- -- 随机传送
- local x, y = this.RandomFightPointXY(mapId, 100)
- maptransfer(actor, x, y, 0, 0, 0)
- this.ResPlayerTaskInfo(actor, mapId)
- end
- end
- -- @description 玩家退出副本
- -- @param 玩家对象;地图唯一id;副本类型;副本阶段(1-准备 2-战斗 3-结算);下一阶段开始时间戳;配置id(cfg_rep的id)
- -- @return
- function RedFortress.AfterRedFortressQuit(actor, mapId, state, nextStateStartTime, configId)
- -- 排名更新;战斗阶段是人数;结算阶段是积分
- if state == DuplicateState.PREPARE then
- this.ResAllPreparePlayerCount(mapId)
- elseif state == DuplicateState.FIGHT then
- local players = getmapplayer(mapId)
- local playerCount = #players
- local monCount = getmoncount(mapId)
- local totalCount = monCount + playerCount
- setplaydef(actor, RedFortressPlayerConst.PLAYER_RANK, totalCount + 1)
- this.LeftCountChange(mapId, 0)
- end
- end
- -- @description 怪物死亡事件
- -- @param 地图id;击杀者
- -- @return
- function RedFortress.OnMonsterDie(mapId, killer)
- this.LeftCountChange(mapId, 0)
- local dupInfo = getduplicate(mapId)
- local configId = dupInfo["dupcfgid"]
- if killer:toString() ~= "0" then
- -- 击杀者加积分;显示图标
- local oldCount = getplaydef(killer, RedFortressPlayerConst.KILL_SCORES)
- local pointConfig = ConfigDataManager.getTableValue("cfg_repRedfortress", "points", "repId", configId)
- local pointList = string.split(pointConfig, "#")
- local addPoint = tonumber(pointList[2])
- local newPoint = oldCount + addPoint
- setplaydef(killer, RedFortressPlayerConst.KILL_SCORES, newPoint)
- -- 加击杀次数
- local oldKill = getplaydef(killer, RedFortressPlayerConst.KILL_COUNT)
- setplaydef(killer, RedFortressPlayerConst.KILL_COUNT, oldKill + 1)
- sendluamsg(killer, LuaMessageIdToClient.RES_RED_FORTRESS_KILL_RELIVE, { NoteType.KILL, oldKill + 1 })
- end
- end
- -- @description 击杀玩家
- -- @param 玩家对象;被击杀的玩家
- -- @return
- function RedFortress.KillPlayer(actor, diePlayer)
- local mapId = getbaseinfo(actor, "unimapid")
- local dupInfo = getduplicate(mapId)
- if dupInfo == nil or dupInfo == "" then
- return
- end
- local type = dupInfo["type"]
- if type ~= DuplicateType.RED_FORTRESS then
- return
- end
- local configId = dupInfo["dupcfgids"]
- -- 加积分
- local oldCount = getplaydef(actor, RedFortressPlayerConst.KILL_SCORES)
- local pointConfig = ConfigDataManager.getTableValue("cfg_repRedfortress", "points", "repId", configId)
- local pointList = string.split(pointConfig, "#")
- local addPoint = tonumber(pointList[1])
- local newPoint = oldCount + addPoint
- setplaydef(actor, RedFortressPlayerConst.KILL_SCORES, newPoint)
- -- 加击杀次数
- local oldKill = getplaydef(actor, RedFortressPlayerConst.KILL_COUNT)
- setplaydef(actor, RedFortressPlayerConst.KILL_COUNT, oldKill + 1)
- -- 击杀图标
- sendluamsg(actor, LuaMessageIdToClient.RES_RED_FORTRESS_KILL_RELIVE, { NoteType.KILL, oldKill + 1 })
- end
- -- @description 玩家死亡事件
- -- @param 玩家对象
- -- @return
- function RedFortress.PlayerDie(actor)
- local mapId = getbaseinfo(actor, "unimapid")
- local dupInfo = getduplicate(mapId)
- if dupInfo == nil then
- return
- end
- local type = dupInfo["type"]
- if type ~= DuplicateType.RED_FORTRESS then
- return
- end
- local configId = dupInfo["dupcfgid"]
- -- 更新死亡次数
- local oldCount = getplaydef(actor, RedFortressPlayerConst.RELIVE_TIMES)
- local maxCount = ConfigDataManager.getTableValue("cfg_repRedfortress", "rebornChance", "repId", configId)
- if oldCount >= tonumber(maxCount) then
- -- 退出副本并结算
- DuplicateCommon.ReqQuitDuplicate(actor)
- else
- -- 延迟执行复活
- local delaySec = ConfigDataManager.getTableValue("cfg_repRedfortress", "rebornTime", "repId", configId)
- local delayMillis = tonumber(delaySec) * 1000
- intervalcalldelay(actor, delayMillis, 0, 1, "redfortressdorelive")
- end
- end
- function redfortressdorelive(actor)
- playrevive(actor, 7, 3)
- end
- function redfortresskillnotinrange(system, mapId, isFinal)
- local area = getenvirvar(mapId, DuplicateVarConst.RED_FORTRESS_FIGHT_AREA)
- local x1 = tonumber(area[1])
- local x2 = tonumber(area[2])
- local y1 = tonumber(area[3])
- local y2 = tonumber(area[4])
- -- 不在区域内的怪物死亡
- local monsterInfoList = mapbossinfo(mapId)
- for key, monInfo in pairs(monsterInfoList) do
- local monId = monInfo["id"]
- local px = monInfo["x"]
- local py = monInfo["y"]
- local isIn = this.IsPointInArea(px, py, x1, x2, y1, y2)
- if isIn == false then
- local monster = getactor(monId, mapId)
- removemapobject(monster)
- end
- end
- -- 缩圈阻挡点
- this.ShrinkingCircleBlockPoint(system, mapId)
- local players = getmapplayer(mapId)
- for key, actor in pairs(players) do
- local px = getbaseinfo(actor, "x")
- local py = getbaseinfo(actor, "y")
- local isIn = this.IsPointInArea(px, py, x1, x2, y1, y2)
- if isIn == false then
- sethp(actor, 0)
- local dupInfo = getduplicate(mapId)
- local configId = dupInfo["dupcfgid"]
- -- 延迟执行复活
- local delaySec = ConfigDataManager.getTableValue("cfg_repRedfortress", "rebornTime", "repId", configId)
- local delayMillis = tonumber(delaySec) * 1000
- intervalcalldelay(actor, delayMillis, 0, 1, "redfortressdorelive")
- end
- end
- if isFinal then
- local dupInfo = getduplicate(mapId)
- local configId = dupInfo["dupcfgid"]
- local maxCount = ConfigDataManager.getTableValue("cfg_repRedfortress", "rebornChance", "repId", configId)
- maxCount = tonumber(maxCount)
- for key, player in pairs(players) do
- setplaydef(player, RedFortressPlayerConst.RELIVE_TIMES, maxCount)
- clearallbuff(player)
- end
- end
- end
- -- @description 缩圈阻挡点
- -- @param
- -- @return
- function this.ShrinkingCircleBlockPoint(system, mapId)
- local area = getenvirvar(mapId, DuplicateVarConst.RED_FORTRESS_FIGHT_AREA)
- local x1 = tonumber(area[1]) - 1
- local x2 = tonumber(area[2]) + 1
- local y1 = tonumber(area[3]) - 1
- local y2 = tonumber(area[4]) + 1
- for x = x1, x2 do
- setblockpoint(x, y1, true, mapId) -- 下边
- end
- for y = y1 + 1, y2 - 1 do
- setblockpoint(x2, y, true, mapId) -- 右边(不包括顶点)
- end
- for x = x2 - 1, x1 + 1, -1 do
- setblockpoint(x, y2, true, mapId) -- 上边(不包括顶点)
- end
- for y = y2 - 1, y1 + 1, -1 do
- setblockpoint(x1, y, true, mapId) -- 左边(不包括顶点)
- end
- -- 设置四个顶点
- setblockpoint(x1, y1, true, mapId) -- 左下角
- setblockpoint(x2, y1, true, mapId) -- 右下角
- setblockpoint(x1, y2, true, mapId) -- 左上角
- setblockpoint(x2, y2, true, mapId) -- 右上角
- end
- -- @description 玩家复活事件
- -- @param 玩家对象
- -- @return
- function RedFortress.PlayerRelive(actor)
- local mapId = getbaseinfo(actor, "unimapid")
- local dupInfo = getduplicate(mapId)
- if dupInfo == nil then
- return
- end
- local type = dupInfo["type"]
- if type ~= DuplicateType.RED_FORTRESS then
- return
- end
- local configId = dupInfo["dupcfgid"]
- local maxCount = ConfigDataManager.getTableValue("cfg_repRedfortress", "rebornChance", "repId", configId)
- maxCount = tonumber(maxCount)
- -- 扣除复活次数
- local oldCount = getplaydef(actor, RedFortressPlayerConst.RELIVE_TIMES)
- local newCount = oldCount + 1
- if newCount > maxCount then
- newCount = maxCount
- end
- setplaydef(actor, RedFortressPlayerConst.RELIVE_TIMES, newCount)
- -- 传送
- --随机点位
- local x, y = this.RandomFightPointXY(mapId, 100)
- maptransfer(actor, x, y, 0, 0, 0)
- -- 被击杀图标
- sendluamsg(actor, LuaMessageIdToClient.RES_RED_FORTRESS_KILL_RELIVE, { NoteType.RELIVE, newCount })
- -- 面板消息
- this.ResPlayerTaskInfo(actor, mapId)
- end
- -- @description 地图玩家怪物数量改变
- -- @param 地图id;偏移量
- -- @return
- function this.LeftCountChange(mapId, offset)
- -- 回包
- local dupInfo = getduplicate(mapId)
- local state = dupInfo["state"]
- local players = dupInfo["players"]
- local configId = dupInfo["dupcfgid"]
- local monCount = getmoncount(mapId)
- local totalCount = tonumber(monCount) + #players - offset
- if state == DuplicateState.PREPARE then
- elseif state == DuplicateState.FIGHT then
- this.ResAllPlayersTaskInfo(mapId, totalCount)
- -- 只剩最后一个玩家,则结束副本
- if totalCount <= 1 then
- setduplicatestate(mapId, SetDuplicateStateConst.TO_FINISH)
- return
- end
- -- 阶段更新,地形,
- local phase = getenvirvar(mapId, DuplicateVarConst.RED_FORTRESS_PHASE)
- local mapCutConfig = ConfigDataManager.getTableValue("cfg_repRedfortress", "mapCut", "repId", configId)
- local mapCutList = string.split(mapCutConfig, "|")
- if phase <= #mapCutList then
- local mapCutItemStr = mapCutList[phase]
- local mapCutItemList = string.split(mapCutItemStr, "#")
- local countCondition = mapCutItemList[1]
- if totalCount < tonumber(countCondition) then
- -- 阶段更新,地形
- local percentage = mapCutItemList[2]
- local area = getenvirvar(mapId, DuplicateVarConst.RED_FORTRESS_FIGHT_AREA)
- local oldX1 = tonumber(area[1])
- local oldX2 = tonumber(area[2])
- local oldY1 = tonumber(area[3])
- local oldY2 = tonumber(area[4])
- local newX1, newX2, newY1, newY2 = this.ShrinkRectangle(oldX1, oldX2, oldY1, oldY2, tonumber(percentage))
- -- 取整
- newX1 = math.floor(newX1)
- newX2 = math.floor(newX2)
- newY1 = math.floor(newY1)
- newY2 = math.floor(newY2)
- local newArea = { newX1, newX2, newY1, newY2 }
- setenvirvar(mapId, DuplicateVarConst.RED_FORTRESS_FIGHT_AREA, newArea)
- -- 回包
- this.ResAllShrinkingStage(mapId, phase, newArea)
- -- 延迟5秒,击杀所有不在区域内的玩家
- local warningCfg = ConfigDataManager.getTableValue("cfg_repRedfortress", "warning", "repId", configId)
- local warningList = string.split(warningCfg, "#")
- local delayMillis = tonumber(warningList[phase]) * 1000
- if phase >= #mapCutList then
- -- 如果是最后一个阶段,扣除玩家所有复活次数和增益效果
- -- local maxCount = ConfigDataManager.getTableValue("cfg_repRedfortress", "rebornChance", "repId", configId)
- -- for key, player in pairs(players) do
- -- setplaydef(player, RedFortressPlayerConst.RELIVE_TIMES, maxCount)
- -- clearallbuff(player)
- -- end
- setenvirontimer(mapId, delayMillis, 0, 1, "redfortresskillnotinrange", mapId, true)
- else
- setenvirontimer(mapId, delayMillis, 0, 1, "redfortresskillnotinrange", mapId, false)
- end
- setenvirvar(mapId, DuplicateVarConst.RED_FORTRESS_PHASE, phase + 1)
- end
- end
- end
- end
- -- @description 玩家进入任意地图事件
- -- @param 玩家对象;上一个地图配置id;当前地图配置id
- -- @return
- function RedFortress.EnterAllMap(actor, lastMapCfgId, mapCfgId)
- -- 判断发送副本结算
- local dupInfo = getplaydef(actor, RedFortressPlayerConst.MAP_INFO)
- if dupInfo == nil or dupInfo == "" then
- return
- end
- local bloodyId = dupInfo[1]
- local mapId = getbaseinfo(actor, "unimapid")
- local mapInfo = getmapinfobyid(mapId)
- local isDup = mapInfo["isdup"]
- if isDup == true and bloodyId ~= mapId then
- error(actor:toString() .. "赤色要塞有未结算的奖励")
- RedFortress.ClearPlayerDef(actor)
- return
- end
- if bloodyId ~= mapId then
- -- 结算
- this.Settlement(actor)
- end
- end
- -- @description 结算
- -- @param 玩家对象
- -- @return
- function this.Settlement(actor)
- local dupInfo = getplaydef(actor, RedFortressPlayerConst.MAP_INFO)
- if dupInfo == nil or dupInfo == "" then
- error("赤色要塞副本结算找不到副本信息")
- return
- end
- local killCount = getplaydef(actor, RedFortressPlayerConst.KILL_COUNT)
- local rank = getplaydef(actor, RedFortressPlayerConst.PLAYER_RANK)
- -- 发邮件奖励
- local configId = dupInfo[2]
- local rewardCfg = ConfigDataManager.getTableValue("cfg_repRedfortress", "reward", "repId", configId)
- local rewardRank = string.split(rewardCfg, "|")
- local itemBing = ConfigDataManager.getTableValue("cfg_bind", "bind", "id", 9)
- for key, value in pairs(rewardRank) do
- local innerList = string.split(value, "#")
- local min = tonumber(innerList[1])
- local max = tonumber(innerList[2])
- local itemId = innerList[3]
- local itemCount = innerList[4]
- if min <= rank and rank <= max then
- sendconfigmailbyrid(actor, actor:toString(), MailConfig.RED_FORTRESS_REWARD, { [tonumber(itemId)] = tonumber(itemCount == nil and 1 or itemCount) }, rank, itemBing)
- break
- end
- end
- -- 发包
- sendluamsg(actor, LuaMessageIdToClient.RES_RED_FORTRESS_SETTLEMENT_PANEL, { killCount, rank })
- -- 清楚玩家变量
- RedFortress.ClearPlayerDef(actor)
- end
- function RedFortress.ClearPlayerDef(actor)
- setplaydef(actor, RedFortressPlayerConst.MAP_INFO, nil)
- setplaydef(actor, RedFortressPlayerConst.RELIVE_TIMES, 0)
- setplaydef(actor, RedFortressPlayerConst.KILL_SCORES, 0)
- setplaydef(actor, RedFortressPlayerConst.KILL_COUNT, 0)
- setplaydef(actor, RedFortressPlayerConst.PLAYER_RANK, 0)
- end
- -- @description 准备阶段人数响应
- -- @param 地图id
- -- @return
- function this.ResAllPreparePlayerCount(mapId)
- local dupInfo = getduplicate(mapId)
- local state = dupInfo["state"]
- if state ~= DuplicateState.PREPARE then
- return
- end
- local players = dupInfo["players"]
- for index, actor in ipairs(players) do
- sendluamsg(actor, LuaMessageIdToClient.RES_RED_FORTRESS_PREPARE_COUNT, #players)
- end
- end
- -- @description 响应给客户端当前阶段
- -- @param 玩家对象;地图id
- -- @return
- function this.ResCurrencyStateInfo(actor, mapId)
- local dupInfo = getduplicate(mapId)
- local state = dupInfo["state"]
- local configId = dupInfo["dupcfgid"]
- local nextStateStartTime = dupInfo["nextstatetime"]
- sendluamsg(actor, LuaMessageIdToClient.RES_RED_FORTRESS_STATE_UPDATE, { state, tostring(nextStateStartTime), configId })
- end
- -- @description 通知地图所有玩家更新当前阶段
- -- @param 地图id
- -- @return
- function this.ResAllPlayCurrencyStateInfo(mapId)
- local dupInfo = getduplicate(mapId)
- local players = dupInfo["players"]
- for index, actor in ipairs(players) do
- this.ResCurrencyStateInfo(actor, mapId)
- end
- end
- -- @description 通知当前玩家任务数据
- -- @param 地图id
- -- @return
- function this.ResPlayerTaskInfo(actor, mapId, totalCount)
- totalCount = tonumber(totalCount)
- if totalCount == nil or totalCount <= 0 then
- local monCount = getmoncount(mapId)
- local players = getmapplayer(mapId)
- totalCount = monCount + #players
- end
- -- 剩余复活次数
- local reliveCount = getplaydef(actor, RedFortressPlayerConst.RELIVE_TIMES)
- local dupInfo = getplaydef(actor, RedFortressPlayerConst.MAP_INFO)
- local configId = dupInfo[2]
- local maxCount = ConfigDataManager.getTableValue("cfg_repRedfortress", "rebornChance", "repId", configId)
- local leftCount = maxCount - reliveCount
- -- 协议待定
- sendluamsg(actor, LuaMessageIdToClient.RES_RED_FORTRESS_TASK_INFO, { totalCount, leftCount })
- end
- -- @description 通知地图所有玩家任务数据
- -- @param 地图id
- -- @return
- function this.ResAllPlayersTaskInfo(mapId, totalCount)
- local dupInfo = getduplicate(mapId)
- local players = dupInfo["players"]
- for index, actor in ipairs(players) do
- this.ResPlayerTaskInfo(actor, mapId, totalCount)
- end
- end
- -- @description 通知地图所有玩家缩圈信息
- -- @param 地图id
- -- @return
- function this.ResAllShrinkingStage(mapId, phase, newArea)
- local dupInfo = getduplicate(mapId)
- local players = dupInfo["players"]
- for index, actor in ipairs(players) do
- sendluamsg(actor, LuaMessageIdToClient.RES_RED_FORTRESS_SHRINKING_STAGE, { phase, newArea })
- end
- end
- -- @description 找一个战斗区域可用的点
- -- @param 地图id;递归次数
- -- @return
- function this.RandomFightPointXY(mapId, times)
- -- 设置递归最大次数
- local maxTimes = 100
- if times > maxTimes then
- times = maxTimes
- end
- local area = getenvirvar(mapId, DuplicateVarConst.RED_FORTRESS_FIGHT_AREA)
- -- 检查 area 数据格式
- if not area or #area ~= 4 then
- gameDebug.printTraceback("获取战斗区域错误", area)
- return 0, 0
- end
- local x1 = tonumber(area[1])
- local x2 = tonumber(area[2])
- local y1 = tonumber(area[3])
- local y2 = tonumber(area[4])
- -- 检查转换后的数据是否为数字
- if not (x1 and x2 and y1 and y2) then
- gameDebug.printTraceback("参数错误", x1, x2, y1, y2)
- return 0, 0
- end
- local randomX = this.GetRandomInt(x1, x2)
- local randomY = this.GetRandomInt(y1, y2)
- local notEmpty = isnotemptyinmap(mapId, randomX, randomY)
- local notBlock = notblockpoint(randomX, randomY, mapId)
- if notEmpty == false or notBlock == false then
- if times > 0 then
- times = times - 1
- return this.RandomFightPointXY(mapId, times)
- else
- return 0, 0
- end
- else
- return randomX, randomY
- end
- end
- function this.GetRandomInt(a, b)
- -- 确保 a 小于等于 b
- if a > b then
- a, b = b, a
- end
- -- 生成 (a, b) 区间内的随机整数
- return math.random(a + 1, b - 1)
- end
- -- @description 计算缩小后的坐标点
- -- @param x1, x2, y1, y2坐标点;缩小的百分比,例如20
- -- @return x1, x2, y1, y2坐标点
- function this.ShrinkRectangle(x1, x2, y1, y2, percentage)
- if x1 > x2 then
- x1, x2 = x2, x1
- end
- if y1 > y2 then
- y1, y2 = y2, y1
- end
- local r = percentage / 100
- local center_x = (x1 + x2) / 2
- local center_y = (y1 + y2) / 2
- local width = math.abs(x2 - x1)
- local height = math.abs(y2 - y1)
- local new_width = width * (1 - r)
- local new_height = height * (1 - r)
- local x1_new = center_x - new_width / 2
- local y1_new = center_y - new_height / 2
- local x2_new = center_x + new_width / 2
- local y2_new = center_y + new_height / 2
- return x1_new, x2_new, y1_new, y2_new
- end
- -- @description 判断坐标点在不在矩形区域内
- -- @param
- -- @return
- function this.IsPointInArea(px, py, x1, x2, y1, y2)
- if x1 > x2 then
- x1, x2 = x2, x1
- end
- if y1 > y2 then
- y1, y2 = y2, y1
- end
- local isIn = not (px < x1 or px > x2 or py < y1 or py > y2)
- return isIn
- end
- -- @description 获取积分排名列表
- -- @param 地图id
- -- @return 列表<玩家id字符串;排名>
- function this.GetScoreRanking(mapId)
- local players = getmapplayer(mapId)
- local playerList = {}
- for index, actor in ipairs(players) do
- local score = getplaydef(actor, RedFortressPlayerConst.KILL_SCORES)
- table.insert(playerList, { actor = actor, score = score })
- end
- -- 按积分从高到低排序,如果积分相同,保持原有顺序
- table.sort(
- playerList,
- function(a, b)
- return a.score > b.score
- end
- )
- -- 计算排名
- local ranks = {}
- local rank = 1 -- 当前排名
- local sameRankCount = 0 -- 相同积分的计数
- local lowestRank = 1 -- 当前积分组的最低排名
- for i = 1, #playerList do
- local player = playerList[i]
- local nextPlayer = playerList[i + 1]
- -- 判断下一名玩家是否与当前玩家积分相同
- if nextPlayer and player.score == nextPlayer.score then
- sameRankCount = sameRankCount + 1
- else
- -- 更新最低排名为当前排名加上相同积分玩家的数量
- lowestRank = rank + sameRankCount
- -- 将当前积分相同的所有玩家设为最低排名
- for j = i - sameRankCount, i do
- ranks[playerList[j].actor.toString] = lowestRank
- end
- -- 更新排名和计数
- rank = lowestRank + 1
- sameRankCount = 0
- end
- end
- return ranks
- end
- -- @description 获取指定玩家的积分排名
- -- @param 玩家对象;地图id
- -- @return 排名
- function this.GetPlayerRank(actor, mapId)
- local ranking = this.GetScoreRanking(mapId)
- return ranking[actor.toString]
- end
- -- @description 计算并设置玩家积分
- -- @param 地图id
- -- @return
- function this.CalcuAndSetPlayerPointRank(mapId)
- local players = getmapplayer(mapId)
- if #players <= 0 then
- return
- end
- local playerList = {}
- for index, actor in ipairs(players) do
- local score = getplaydef(actor, RedFortressPlayerConst.KILL_SCORES)
- table.insert(playerList, { actor = actor, score = score })
- end
- -- 按积分从高到低排序,如果积分相同,保持原有顺序
- table.sort(
- playerList,
- function(a, b)
- return a.score > b.score
- end
- )
- -- 计算排名
- local rank = 1 -- 当前排名
- local sameRankCount = 0 -- 相同积分的计数
- local lowestRank = 1 -- 当前积分组的最低排名
- if #playerList > 1 then
- for i = 1, #playerList do
- local player = playerList[i]
- local nextPlayer = playerList[i + 1]
- -- 判断下一名玩家是否与当前玩家积分相同
- if nextPlayer and player.score == nextPlayer.score then
- sameRankCount = sameRankCount + 1
- else
- -- 更新最低排名为当前排名加上相同积分玩家的数量
- lowestRank = rank + sameRankCount
- -- 将当前积分相同的所有玩家设为最低排名
- for j = i - sameRankCount, i do
- local actor = playerList[j].actor
- setplaydef(actor, RedFortressPlayerConst.PLAYER_RANK, lowestRank)
- end
- -- 更新排名和计数
- rank = lowestRank + 1
- sameRankCount = 0
- end
- end
- else
- local player = playerList[1].actor
- setplaydef(player, RedFortressPlayerConst.PLAYER_RANK, 1)
- end
- end
|