| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008 |
- WorldBoss = {}
- local this = {}
- -- 报名过的玩家
- local SIGNIN_ALL_PLAYER = "G$SignInWorldBossPlayers"
- local MonLowHp = "G$_WorldBossMonsterLowHP"
- local QUIT_TIME = "G$_WorldBossAfterquitduplicate_time"
- -- local CurBossRepId = "R$_WorldBoss_Cur_Activity_ID"
- -- local Activity_ID = 23001 -- 世界BOSS活动ID
- local Activity_TYPE = 30001 -- 世界BOSS活动类型
- local coolTime = 60 -- 退出副本后的冷却时间,单位秒
- local AucMailConst = {
- SUCCESS = 102061,
- FAIL = 102062,
- A_BONUS = 102063
- }
- function WorldBoss.start()
- local curRepId = WorldBoss.UpDataCurRepId()
- if curRepId == 0 then
- return
- end
- local nullActor = getactor(0, 0)
- local mapId = DuplicateCommon.CreateDupMapCommon(nullActor, curRepId, true)
- local x, y = DuplicateCommon.GetEnterPointXYCommon(curRepId)
- -- jprint("世界BOSS副本开始报名", mapId, x, y)
- noticeTip.noticeinfo(nullActor, 35013)
- end
- function WorldBoss.UpDataCurRepId()
- local openDay = getbaseinfo("serveropendays")
- local cfgVal = ConfigDataManager.getTableValue("cfg_repGlobal", "value", "id", 23001002)
- local data = string.split(cfgVal, "|")
- if table.notEmpty(data) then
- for _, d2 in ipairs(data) do
- local v = string.split(d2, "#")
- if #v == 3 then
- local LDay = tonumber(v[1])
- local HDay = tonumber(v[2])
- local Rid = tonumber(v[3])
- if openDay <= HDay and openDay >= LDay then
- return Rid
- end
- end
- end
- end
- return 0
- end
- function WorldBoss.stop(activityId)
- local existDupList = getduplicatelist(activityId)
- if table.isEmpty(existDupList) then
- return
- end
- local mapId = existDupList[1].id
- setduplicatestate(mapId, SetDuplicateStateConst.TO_FINISH)
- setduplicatestate(mapId, SetDuplicateStateConst.TO_CLOSED)
- closeactivity(DuplicateType.WORLD_BOSS)
- end
- function WorldBoss.Run(activityId, action)
- -- local serverType = getbaseinfo("servertype")
- -- info("WorldBoss副本 activityId:-------------------", activityId, " action:", action)
- if tonumber(action) == 1 then
- WorldBoss.start()
- elseif tonumber(action) == 0 then
- WorldBoss.stop(activityId)
- end
- end
- function WorldBoss.DupStateUpdate(system, mapId, state, nextStateStartTime, configId)
- if state == DuplicateState.PREPARE then
- -- info("WorldBoss副本进入准备阶段, mapId:", mapId, " state:", state, " nextStateStartTime:", nextStateStartTime, " configId:", configId)
- -- 准备阶段
- elseif state == DuplicateState.FIGHT then
- -- info("WorldBoss副本进入战斗阶段, mapId:", mapId, " state:", state, " nextStateStartTime:", nextStateStartTime, " configId:", configId)
- -- 战斗阶段
- local monsterId = ConfigDataManager.getTableValue("cfg_rep", "monster", "id", configId)
- DuplicateCommon.DupGenMonsterCommon(mapId, monsterId) --刷怪
- WorldBoss.upDataState(mapId)
- elseif state == DuplicateState.FINISH then
- -- info("WorldBoss副本进入结算阶段, mapId:", mapId, " state:", state, " nextStateStartTime:", nextStateStartTime, " configId:", configId)
- -- 结束阶段
- elseif state == DuplicateState.CLOSED then
- -- info("WorldBoss副本进入销毁阶段, mapId:", mapId, " state:", state, " nextStateStartTime:", nextStateStartTime, " configId:", configId)
- end
- end
- -- 更新当前状态
- function WorldBoss.upDataState(mapId)
- local players = getenvirvar(mapId, SIGNIN_ALL_PLAYER) or {}
- for k, v in pairs(players) do
- local actor = getactor(k)
- if actor then
- WorldBoss.SendWorldBossInfo(actor)
- end
- end
- end
- function WorldBoss.ReqWorldBossMsg(actor, msgData)
- local reqType = msgData["type"]
- if reqType == 1 then
- WorldBoss.SendWorldBossInfo(actor)
- elseif reqType == 2 then
- WorldBoss.ReqSignInWorldBoss(actor)
- -- WbAuction.Publish(23001)--测试拍卖
- end
- end
- -- 活动报名
- function WorldBoss.ReqSignInWorldBoss(actor)
- -- 检查是否拥有战盟
- local guildid = getbaseinfo(actor, "guildid")
- if guildid == 0 then
- tipinfo(actor, "不在战盟中")
- return
- end
- local existDupList = getduplicatelist(Activity_TYPE)
- if table.isEmpty(existDupList) then
- tipinfo(actor, "活动未开启,无法报名")
- return
- end
- local state = existDupList[1].state
- if state ~= DuplicateState.PREPARE then
- tipinfo(actor, "非报名时间,无法报名")
- return
- end
- local mapId = existDupList[1].id
- local players = getenvirvar(mapId, SIGNIN_ALL_PLAYER) or {}
- local rid = getbaseinfo(actor, "rid")
- if players[rid] then
- tipinfo(actor, "已报名,无需重复操作")
- return
- end
- players[rid] = 0
- setenvirvar(mapId, SIGNIN_ALL_PLAYER, players)
- WorldBoss.SendWorldBossInfo(actor)
- tipinfo(actor, "世界boss活动报名成功")
- end
- -- 发送当前状态信息
- function WorldBoss.SendWorldBossInfo(actor)
- local resData = {}
- local existDupList = getduplicatelist(Activity_TYPE)
- if table.isEmpty(existDupList) then
- return
- end
- -- id:副本地图唯一ID
- -- dupcfgid:配置表id,cfg_rep表的ID
- -- activityid:活动id
- -- players:玩家actor列表
- -- state:当前阶段
- -- nextstatetime:下一阶段开始时间戳(毫秒),
- -- type:副本类型
- local mapId = existDupList[1].id
- resData["signin"] = WorldBoss.GetSignInNUm(mapId)
- resData["mapid"] = mapId
- resData["dupcfgid"] = existDupList[1].dupcfgid
- resData["activityid"] = existDupList[1].activityid
- resData["state"] = existDupList[1].state
- resData["type"] = existDupList[1].type
- resData["nextstatetime"] = existDupList[1].nextstatetime
- resData["issignin"] = WorldBoss.GetisSignIn(mapId, getbaseinfo(actor, "rid"))
- local qtinfo = getenvirvar(mapId, QUIT_TIME) or {}
- resData["qtime"] = qtinfo[getbaseinfo(actor, "rid")] or 0
- sendluamsg(actor, LuaMessageIdToClient.RES_WORLD_BOSS_INFO, resData)
- end
- function WorldBoss.isWorldBoss(actor)
- local mapId = getbaseinfo(actor, "unimapid")
- local dupInfo = getduplicate(mapId)
- if not dupInfo then
- return false
- end
- local type = dupInfo["type"]
- if type ~= DuplicateType.WORLD_BOSS then
- return false
- end
- return true
- end
- -- 获取报名人数
- function WorldBoss.GetSignInNUm(mapId)
- local players = getenvirvar(mapId, SIGNIN_ALL_PLAYER) or {}
- return table.count(players)
- end
- function WorldBoss.GetisSignIn(mapId, rid)
- local players = getenvirvar(mapId, SIGNIN_ALL_PLAYER) or {}
- return players[rid] and true or false
- end
- -- @description 请求进入世界boss活动
- function WorldBoss.ReqEnterWorldBoss(actor)
- local activityInfo = getactivityinfo(Activity_TYPE)
- if not activityInfo["open"] then
- tipinfo(actor, "活动未开启")
- return
- end
- -- 检查是否拥有战盟
- local guildid = getbaseinfo(actor, "guildid")
- if guildid == 0 then
- tipinfo(actor, "不在战盟中")
- return
- end
- if WorldBoss.isWorldBoss(actor) then
- tipinfo(actor, "您已经在世界boss挑战中")
- return
- end
- -- 寻找是否有可进入的副本,如果没有创建副本
- local existDupList = getduplicatelist(Activity_TYPE)
- if table.isEmpty(existDupList) then
- tipinfo(actor, "活动副本未开启")
- return
- -- mapId = DuplicateCommon.CreateDupMapCommon(actor, Activity_ID, true)
- end
- local mapId = existDupList[1].id
- local curRepId = existDupList[1].dupcfgid
- local curState = existDupList[1].state
- if curState ~= DuplicateState.FIGHT then
- tipinfo(actor, "非战斗时间,无法进入")
- return
- end
- local players = getenvirvar(mapId, SIGNIN_ALL_PLAYER) or {}
- if not players[getbaseinfo(actor, "rid")] then
- tipinfo(actor, "未报名,无法进入")
- return
- end
- local LowNum = tonumber(ConfigDataManager.getTableValue("cfg_repGlobal", "value", "id", 23001001))
- if LowNum > 0 then
- local num = WorldBoss.GetSignInNUm(mapId)
- if num < LowNum then
- tipinfo(actor, "当前报名人数不足,无法进入")
- return
- end
- end
- if mapId ~= 0 and curRepId ~= 0 then
- local x, y = DuplicateCommon.GetEnterPointXYCommon(curRepId)
- enterduplicate(actor, mapId, x, y)
- end
- end
- function WorldBoss.afterenterduplicate(actor, mapId, dupType, state, nextStateStartTime, configId)
- sendluamsg(actor, LuaMessageIdToClient.RES_WORLD_BOSS_RANK, {})
- local pkStatus = 1
- local tip = getenvirvar(mapId, MonLowHp)
- if tonumber(tip) == 1 then
- pkStatus = 5
- end
- -- 设置pk状态
- setplayersetting(actor, 1, pkStatus) --1 和平 5战盟
- end
- function WorldBoss.afterquitduplicate(actor, mapId, dupType, state, nextStateStartTime, configId)
- local qtInfo = getenvirvar(mapId, QUIT_TIME) or {}
- qtInfo[getbaseinfo(actor, "rid")] = getbaseinfo("now") + coolTime * 1000
- setenvirvar(mapId, QUIT_TIME, qtInfo)
- end
- function WorldBoss.OnMonsterDie(mapId, killer, monCfgId, monActor)
- -- local timer = setenvirontimer(mapId,60000,1000,1,"worldboss_monsterdie",mapId)
- -- local exit = hasenvirtimer(mapId,timer)
- -- info(">>>boss死亡,上BOSS拍卖行:", mapId)
- local dupInfo = getduplicate(mapId)
- if dupInfo == nil then
- return
- end
- WbAuction.Publish(dupInfo.dupcfgid)
- local bossName = ConfigDataManager.getTableValue("cfg_monster", "name", "id", monCfgId)
- noticeTip.noticeinfo(monActor, 35014, bossName)
- end
- -- 关闭世界boss副本
- function worldboss_monsterdie(_, mapId)
- -- info("boss死亡,关闭世界boss副本mapId:", mapId)
- end
- function WorldBoss.calculatePlayerRankList(mapId, rankNum)
- local playerList = {}
- local guildList = {}
- local guildDamage = {}
- local guildName = {}
- local players = getenvirvar(mapId, SIGNIN_ALL_PLAYER)
- if players ~= nil then
- for id, damage in pairs(players) do
- if damage == 0 then
- goto continue
- end
- local actor = getactor(id)
- local guildid = getbaseinfo(actor, "guildid") or 0
- guildName[guildid] = getbaseinfo(actor, "guildname") or ""
- -- playerList[id] = { damage = damage ,name = tostring(getbaseinfo(actor, "rolename")) }
- table.insert(playerList, {id = id, damage = damage, name = tostring(getbaseinfo(actor, "rolename"))})
- -- local curDamage = guildList[guildid] and guildList[guildid].damage or 0
- -- guildList[guildid] = { damage = curDamage + damage ,name = getbaseinfo(actor, "guildname") }
- guildDamage[guildid] = (guildDamage[guildid] or 0) + damage
- ::continue::
- end
- for k, v in pairs(guildDamage) do
- table.insert(guildList, {id = k, damage = v, name = guildName[k] or ""})
- end
- end
- table.sort(playerList, this.SortFunc)
- table.sort(guildList, this.SortFunc)
- local topPlayerList = {}
- rankNum = rankNum or 50
- for i = 1, math.min(rankNum, #playerList) do
- table.insert(topPlayerList, playerList[i])
- end
- local topGuildList = {}
- for i = 1, math.min(50, #guildList) do
- table.insert(topGuildList, guildList[i])
- end
- return topPlayerList, topGuildList
- end
- function this.SortFunc(a, b)
- if a.damage ~= b.damage then
- return b.damage < a.damage
- end
- end
- -- 世界BOSS奖励分配
- -- 总奖励:10000钻石
- -- 战盟分配:第1名50%,第2名30%,第3名20%
- -- 玩家分配:第1名30%,第2名25%,第3名20%,第4名10%,第5名5%,剩余平均分配
- function WorldBoss.DistributeRewards(totalReward)
- local existDupList = getduplicatelist(Activity_TYPE)
- if table.isEmpty(existDupList) then
- this.print("活动副本未开启")
- return
- end
- local mapId = existDupList[1].id
- if not totalReward or totalReward <= 0 then
- this.print("世界BOSS奖励分配失败:奖励金额无效", totalReward)
- return
- end
- local playerList, guildList = WorldBoss.calculatePlayerRankList(mapId, 999)
- if table.isEmpty(playerList) or table.isEmpty(guildList) then
- this.print("世界BOSS奖励分配失败:没有玩家或战盟数据", mapId, playerList, guildList)
- return
- end
- -- jprint(string.format("=== 世界BOSS奖励分配开始,总奖励:%d钻石 ===", totalReward))
- -- 获取前3名战盟
- local top3Guilds = {}
- for i = 1, math.min(3, #guildList) do
- table.insert(top3Guilds, guildList[i])
- end
- -- 战盟分配比例
- local guildRewardRatios = {0.5, 0.3, 0.2} -- 50%, 30%, 20%
- -- 为每个前3名战盟计算奖励
- local guildRewards = {}
- local totalDistributedReward = 0
- for i, guild in ipairs(top3Guilds) do
- local guildTotalReward = totalReward * guildRewardRatios[i]
- totalDistributedReward = totalDistributedReward + guildTotalReward
- guildRewards[guild.id] = {
- totalReward = guildTotalReward,
- guildName = guild.name,
- guildRank = i,
- players = {}
- }
- -- jprint(string.format("第%d名战盟:%s,获得%.0f钻石(%.0f%%)",
- -- i, guild.name, guildTotalReward, guildRewardRatios[i] * 100))
- end
- -- 玩家分配比例(前5名)
- local playerRewardRatios = {0.3, 0.25, 0.2, 0.1, 0.05} -- 30%, 25%, 20%, 10%, 5%
- -- 为每个战盟的玩家分配奖励
- for guildId, guildData in pairs(guildRewards) do
- local guildPlayers = {}
- -- 获取该战盟的所有玩家(按照伤害排名)
- for _, player in ipairs(playerList) do
- local actor = getactor(player.id)
- local playerGuildId = getbaseinfo(actor, "guildid") or 0
- if playerGuildId == guildId then
- table.insert(guildPlayers, player)
- end
- end
- -- jprint(string.format(" 战盟%s共有%d名玩家参与", guildData.guildName, #guildPlayers))
- if #guildPlayers > 0 then
- -- 前5名玩家按比例分配
- local distributedReward = 0
- local top5Count = math.min(5, #guildPlayers)
- for i = 1, top5Count do
- local player = guildPlayers[i]
- local playerReward = guildData.totalReward * playerRewardRatios[i]
- distributedReward = distributedReward + playerReward
- table.insert(
- guildData.players,
- {
- playerId = player.id,
- playerName = player.name,
- damage = player.damage,
- rank = i,
- reward = playerReward,
- rewardType = i <= 5 and "排名奖励" or "参与奖励"
- }
- )
- -- jprint(string.format(" 第%d名:%s,%.0f钻石(%.0f%%),伤害:%d",
- -- i, player.name, playerReward, playerRewardRatios[i] * 100, player.damage))
- end
- -- 剩余玩家平均分配
- if #guildPlayers > 5 then
- local remainingCount = #guildPlayers - 5
- local remainingReward = guildData.totalReward - distributedReward
- local avgReward = remainingReward / remainingCount
- -- jprint(string.format(" 剩余%d名玩家,每人平均获得%.0f钻石", remainingCount, avgReward))
- for i = 6, #guildPlayers do
- local player = guildPlayers[i]
- table.insert(
- guildData.players,
- {
- playerId = player.id,
- playerName = player.name,
- damage = player.damage,
- rank = i,
- reward = avgReward,
- rewardType = "参与奖励"
- }
- )
- end
- end
- end
- end
- -- jprint(string.format("=== 奖励分配完成,总计分配%.0f钻石 ===", totalDistributedReward))
- -- 发送奖励
- WorldBoss.SendWorldBossRewards(guildRewards)
- return guildRewards
- end
- -- 发送世界BOSS奖励
- function WorldBoss.SendWorldBossRewards(guildRewards)
- this.debug("=== 世界BOSS奖励分配开始 ===", guildRewards)
- for guildId, guildData in pairs(guildRewards) do
- -- jprint(string.format("战盟:%s,总奖励:%.0f钻石", guildData.guildName, guildData.totalReward))
- for _, playerData in ipairs(guildData.players) do
- local actor = getactor(playerData.playerId)
- if actor then
- -- 发送钻石奖励
- local rewardItems = {[10040001] = math.floor(playerData.reward)} -- 钻石ID和数量
- -- 发送奖励邮件
- -- local title = "世界BOSS奖励"
- -- local content = string.format("恭喜您在世界BOSS活动中获得排名奖励!\n战盟:%s\n个人排名:第%d名\n伤害值:%d\n获得钻石:%.0f", guildData.guildName, guildData.guildName, playerData.damage, playerData.reward)
- -- sendmailbycompleteitems(actor, playerData.playerId, title, content, rewardItems)--getbaseinfo(actor, "rid")
- local param =
- guildData.guildName ..
- "#" .. guildData.guildRank .. "#" .. math.floor(guildData.totalReward) .. "#" .. playerData.rank
- sendconfigmailbyrid(actor, playerData.playerId, AucMailConst.A_BONUS, rewardItems, param)
- -- 记录日志
- -- jprint(string.format(" 玩家:%s,排名:%d,伤害:%d,奖励:%.0f钻石",
- -- playerData.playerName, playerData.rank, playerData.damage, playerData.reward))
- end
- end
- end
- this.debug("=== 世界BOSS奖励分配结束 ===")
- end
- -- 调试函数:查看排行榜详情
- -- function WorldBoss.DebugRankList(mapId)
- -- local playerList, guildList = WorldBoss.calculatePlayerRankList(mapId)
- -- jprint("=== 世界BOSS战盟排行榜 ===")
- -- for i = 1, math.min(3, #guildList) do
- -- local guild = guildList[i]
- -- jprint(string.format("第%d名战盟:%s,伤害:%d", i, guild.name, guild.damage))
- -- end
- -- jprint("=== 世界BOSS玩家排行榜 ===")
- -- for i = 1, math.min(10, #playerList) do
- -- local player = playerList[i]
- -- local actor = getactor(player.id)
- -- local guildName = ""
- -- if actor then
- -- guildName = getbaseinfo(actor, "guildname") or "无战盟"
- -- end
- -- jprint(string.format("第%d名:%s(%s),伤害:%d", i, player.name, guildName, player.damage))
- -- end
- -- end
- -- 攻击事件
- function WorldBoss.Attack(actor, fightData)
- local mapId = getbaseinfo(actor, "unimapid")
- local dupInfo = getduplicate(mapId)
- if dupInfo == nil then
- return
- end
- local type = dupInfo["type"]
- if type ~= DuplicateType.WORLD_BOSS then
- return
- end
- local casterType = fightData.castertype
- local targetType = fightData.targettype
- if casterType ~= MapObjectType.PLAYER or targetType ~= MapObjectType.MONSTER then
- return
- end
- -- 累计伤害
- local players = getenvirvar(mapId, SIGNIN_ALL_PLAYER) or {}
- local rid = getbaseinfo(actor, "rid")
- players[rid] = (players[rid] or 0) + fightData.targethurt
- setenvirvar(mapId, SIGNIN_ALL_PLAYER, players)
- WorldBoss.CheckMonsterHp(actor, mapId, fightData.target)
- end
- -- 检查怪当前血量是否低于30%
- function WorldBoss.CheckMonsterHp(actor, mapId, Monste)
- local tip = getenvirvar(mapId, MonLowHp)
- if tonumber(tip) == 1 then
- return
- end
- local mInfo = getmonsterinfo(Monste)
- if mInfo == nil then
- return
- end
- local hp = mInfo["hp"]
- local maxhp = mInfo["maxhp"]
- local bossName = mInfo["name"]
- if (hp / maxhp) <= 0.5 then
- setenvirvar(mapId, MonLowHp, 1)
- -- 本地通广播提示
- noticeTip.noticeinfo(Monste, StringIdConst.text35010, bossName)
- local dupInfo = getduplicate(mapId)
- if table.isEmpty(dupInfo) then
- return
- end
- local playerData = dupInfo.players or {}
- for _, act in pairs(playerData) do
- setplayersetting(act, 1, 5) --1 和平 5战盟
- end
- end
- end
- function WorldBoss.DupSecondHeart(mapId, dupConfig, state)
- if state == DuplicateState.PREPARE then
- elseif state == DuplicateState.FIGHT then
- -- 刷新排行榜
- this.sendPanelRankData(mapId)
- return
- end
- end
- function this.sendPanelRankData(mapId)
- local resData = {}
- local rankList, guildList = WorldBoss.calculatePlayerRankList(mapId)
- resData["playerRank"] = rankList
- resData["guildRank"] = guildList
- -- local existDupList = getduplicatelist(Activity_TYPE)
- local dupInfo = getduplicate(mapId)
- if table.isEmpty(dupInfo) then
- return
- end
- local playerData = dupInfo.players or {}
- for _, actor in pairs(playerData) do
- -- local actor = getactor(rid)
- sendluamsg(actor, LuaMessageIdToClient.RES_WORLD_BOSS_RANK, resData)
- end
- end
- -- ------------------------------------------------------------- --
- WbAuction = {}
- local aucDbFunc = {}
- local function __AuctionDbKey()
- return "R$_WORLD_BOSS_AUCTION_DATA"
- end
- local function _flushTime()
- return 5
- end
- local function _stallWay()
- return 11
- end
- function WbAuction.ontimer()
- this.onTimer()
- end
- function WbAuction.Publish(dupcfgid)
- callonserial("_wb_auction_publish_goods", dupcfgid)
- end
- function WbAuction.PlayerBidding(actor, msgData)
- callonserial(actor, "_wb_auction_player_bidding", msgData)
- end
- function WbAuction.login(actor)
- this.sendAuctionPanelData(actor)
- end
- -- 拍卖行上架道具
- function _wb_auction_publish_goods(_, dupcfgid)
- if not this.auctionIsOpen() then
- return
- end
- if not dupcfgid then
- return
- end
- local configList = ConfigDataManager.getTable("cfg_stall", "way", _stallWay())
- if table.isEmpty(configList) then
- return
- end
- local repId = dupcfgid --getsysvar(CurBossRepId) or Activity_ID
- local UIreward = ConfigDataManager.getTableValue("cfg_rep", "UIreward", "id", repId)
- local rewardMap = string.split(UIreward, "|")
- if table.isNullOrEmpty(rewardMap) then
- return
- end
- local RewardList = {}
- for _, uiId in pairs(rewardMap) do
- for _, cfg in pairs(configList) do
- if cfg.id == uiId then
- table.insert(RewardList, cfg)
- break
- end
- end
- end
- local now = getbaseinfo("now")
- local goodsMap = {}
- for _, config in pairs(RewardList) do
- local probability = string.tonumber(config["probability"])
- local cfgid = tonumber(config["id"])
- local count = tonumber(config["number"])
- if probability > 0 then
- local num = math.random(1, 10000)
- if probability < num then
- goto continue
- end
- end
- local goodsInfo = createitemsbymap({[cfgid] = count})
- if table.isEmpty(goodsInfo) then
- goto continue
- end
- local ready = tonumber(config["ready"]) or 0
- local endTime = now + (tonumber(config["time"]) + ready) * 60 * 1000
- for _, goods in pairs(goodsInfo) do
- goods["bidderId"] = 0
- goods["startTime"] = now
- goods["endTime"] = endTime
- goods["price"] = tonumber(config["startingprice"])
- goods["coinType"] = tonumber(config["money"])
- goods["fixedPrice"] = tonumber(config["fixedprice"])
- goods["auction"] = tonumber(config["auction"])
- goods["addTimes"] = tonumber(config["addtime"])
- goods["readyTime"] = now + ready * 60 * 1000 - 1000
- goods["isReady"] = ready == 0 and 0 or 1 -- 公示中
- goodsMap[goods["id"]] = goods
- end
- ::continue::
- end
- this.debug("---- 拍卖行上架道具 -----", goodsMap)
- aucDbFunc.setPublishGoods(goodsMap)
- GlobalTimer.setontimerex(TimerIds.WORLD_BOSS_AUCTION, _flushTime())
- end
- function _wb_auction_player_bidding(actor, msgData)
- local goodsId = string.tonumber(msgData["goodsId"])
- if goodsId < 1 then
- return
- end
- if not this.auctionIsOpen() then
- this.info(actor, "拍卖未开启")
- return
- end
- if not this.isParticipate(actor) then
- this.info(actor, "您未参与活动")
- return
- end
- local goodsMap = aucDbFunc.getPublishGoods()
- local goods = goodsMap[goodsId]
- if table.isEmpty(goods) then
- this.info(actor, "该商品已被购买或已下架")
- return
- end
- if goods["isReady"] == 1 then
- this.info(actor, "该商品处于公示阶段,无法竞拍")
- return
- end
- local now = getbaseinfo("now")
- local endTime = goods["endTime"]
- if endTime < now then
- this.info(actor, "该商品已下架")
- return
- end
- local buyNow = string.tonumber(msgData["type"]) == 1
- local rid = tonumber(actor:toString())
- local lastBidder = goods["bidderId"]
- if not buyNow and lastBidder == rid then
- this.info(actor, "您已参与竞拍, 请勿重复参与")
- return
- end
- local bidPrice = goods["price"]
- local fixedPrice = tonumber(goods["fixedPrice"])
- local newPrice = buyNow and fixedPrice or this.calculateNewPrice(goods)
- local coinType = goods["coinType"]
- local coinCount = getbagitemcountbyid(actor, coinType)
- if coinCount < newPrice then
- this.info(actor, "资源不足, 无法竞拍")
- return
- end
- removeitemfrombag(actor, coinType, newPrice, 0, 9999, "世界BOSS竞拍")
- goods["bidderId"] = rid
- goods["price"] = newPrice
- -- 一口价进入结算阶段
- if buyNow or newPrice == fixedPrice then
- this.toSettleAuction(goods)
- -- 结算并清理缓存
- goodsMap[goodsId] = nil
- goods["endTime"] = 0
- else
- -- 增加时间 保存变动内容
- local finalTime = (goods["addTimes"] or 0) * 1000 + endTime
- goods["endTime"] = finalTime
- goodsMap[goodsId] = goods
- end
- aucDbFunc.setPublishGoods(goodsMap)
- -- 返还上个竞拍玩家道具
- if lastBidder > 0 then
- this.bidFailMail(lastBidder, goodsId, coinType, bidPrice)
- end
- -- local result = { ["result"] = true, ["goods"] = goods }
- -- this.sendAuctionResult(actor, result)
- end
- -- function this.sendAuctionResult(actor, result)
- -- sendluamsg(actor, LuaMessageIdToClient.RES_KUN_DUN_AUCTION_BUY_RESULT, result)
- -- end
- -- ------------------------------------------------------------- --
- function this.sendAuctionPanelData(actor, goods)
- local data = {}
- if goods == nil then
- goods = aucDbFunc.getPublishGoods()
- end
- -- this.debug("---- 发送拍卖行面板数据 -----", goods, this.auctionIsOpen(), this.isParticipate(actor))
- if this.auctionIsOpen() and this.isParticipate(actor) and table.notEmpty(goods) then
- data["isOpen"] = true
- data["goods"] = goods
- else
- data["isOpen"] = false
- end
- sendluamsg(actor, LuaMessageIdToClient.RES_WORLD_BOSS_AUCTION_GOODS, data)
- end
- function this.sendOnLinePlayerPanel(func, resData)
- -- local data = dataFunc.getAllKunDunPlayerData()
- -- this.debug("---- 获取所有玩家数据 -----", resData, data)
- -- for rid, _ in pairs(data) do
- -- local actor = getactor(rid)
- -- local onlineState = tonumber(getbaseinfo(actor, "onlinestate"))
- -- if onlineState == 1 then
- -- func(actor, resData)
- -- end
- -- end
- end
- function this.bidFailMail(bidderId, goodsId, costType, costNum)
- local itemName = ConfigDataManager.getTableValue("cfg_item", "name", "id", goodsId)
- local costName = ConfigDataManager.getTableValue("cfg_item", "name", "id", costType)
- local param = itemName .. "#" .. costName
- local actor = getactor(bidderId)
- sendconfigmailbyrid(actor, bidderId, AucMailConst.FAIL, {[costType] = costNum}, param)
- end
- function this.calculateNewPrice(goods)
- local bidPrice = goods["price"]
- local auction = goods["auction"] or 1
- local fixedPrice = goods["fixedPrice"]
- -- local newPrice = math.ceil(bidPrice * (1 + auction * 0.0001))
- local newPrice = bidPrice + auction
- this.debug("---- 拍卖行计算价格 -----", goods, bidPrice, auction, "|", "fixedPrice", fixedPrice, "newPrice", newPrice)
- return math.min(newPrice, fixedPrice)
- end
- function this.onTimer()
- local goodsData = aucDbFunc.getPublishGoods()
- -- this.debug("---- 拍卖行定时器 -----", goodsData)
- if table.notEmpty(goodsData) then
- local clearIdList = {}
- local now = string.tonumber(getbaseinfo("now"))
- for goodsId, goods in pairs(goodsData) do
- local endTime = goods["endTime"]
- if endTime < now then
- table.insert(clearIdList, goodsId)
- elseif goods["isReady"] == 1 then
- -- 公示中,
- local readyTime = goods["readyTime"] or 0
- if readyTime < now then
- goods["isReady"] = 0
- goodsData[goodsId] = goods
- end
- else
- -- 拍卖中,
- end
- end
- -- this.debug("---- 需要清理的拍卖行道具 -----", clearIdList)
- -- 结算到期竞拍道具
- for _, goodsId in pairs(clearIdList) do
- local goods = goodsData[goodsId]
- this.toSettleAuction(goods)
- goodsData[goodsId] = nil
- end
- aucDbFunc.setPublishGoods(goodsData)
- end
- -- 没有物品后关闭定时器
- if table.isEmpty(goodsData) then
- GlobalTimer.setofftimer(TimerIds.WORLD_BOSS_AUCTION)
- end
- end
- function this.toSettleAuction(goods)
- if table.isEmpty(goods) then
- return
- end
- -- 发放拍卖道具
- local buyerId = goods["bidderId"]
- if buyerId < 1 then
- return
- end
- local buyer = getactor(buyerId)
- local mailConfig = ConfigDataManager.getById("cfg_mail", AucMailConst.SUCCESS)
- if table.notEmpty(mailConfig) then
- local title = mailConfig["title"]
- local content = mailConfig["content"]
- local itemName = ConfigDataManager.getTableValue("cfg_item", "name", "id", goods["cfgid"])
- content = string.format(content, itemName)
- sendmailbycompleteitems(buyer, buyerId, title, content, {goods})
- end
- local cfgId = goods["cfgid"]
- local coinType = goods["coinType"]
- local price = goods["price"]
- local taxStr = ConfigDataManager.getTableValue("cfg_stall", "tax", "id", cfgId, "way", _stallWay())
- -- this.debug("config_data", cfgId, _stallWay(), taxStr)
- local aBonus = this.calculationTax(price, taxStr)
- -- 发送邮件奖励
- this.print("发送邮件奖励", aBonus)
- WorldBoss.DistributeRewards(aBonus)
- -- 分红名单
- -- local ridList = {}
- -- -- 是否为稀有道具
- -- local rareItem = false
- -- if rareItem then
- -- local rankData = dataFunc.getKunDunFactionRankData()
- -- local faction = rankData[1]['faction']
- -- ridList = dataFunc.getFactionPlayers(faction)
- -- else
- -- local allPlayer = dataFunc.getAllKunDunPlayerData()
- -- for rid, _ in pairs(allPlayer) do
- -- table.insert(ridList, rid)
- -- end
- -- end
- -- local buyerName = getbaseinfo(buyer, "rolename")
- -- this.debug("---- 拍卖结算 ----", goods, buyerId, buyerName, "-- 分红名单 --", ridList)
- -- :: continue ::
- -- local reward = { [coinType] = aBonus }
- -- -- 解析文本配置
- -- local itemName = ConfigDataManager.getTableValue("cfg_item", "name", "id", cfgId)
- -- local priceTypeName = ConfigDataManager.getTableValue("cfg_item", "name", "id", coinType)
- -- local param = itemName .. "#" .. priceTypeName .. "#" .. aBonus .. "#" .. getABonus
- -- for _, rid in pairs(ridList) do
- -- if tonumber(rid) ~= buyerId then
- -- local player = getactor(rid)
- -- sendconfigmailbyrid(player, rid, AucMailConst.A_BONUS, reward, param)
- -- end
- -- end
- end
- -- 计算税率
- function this.calculationTax(price, taxStr)
- local tableTax = {}
- string.putIntIntMap(tableTax, taxStr)
- local deleteRate = tableTax[1]
- this.debug("---- 拍卖行税率 ----", price, taxStr, tableTax)
- local totalPrice = math.round(price * (100 - deleteRate) / 100)
- local deleteCount = tableTax[2]
- totalPrice = totalPrice - deleteCount
- return totalPrice
- end
- function this.auctionIsOpen()
- -- boss被击杀才开启
- -- local taskData = dataFunc.getKunDunTaskData()
- -- return taskData["stage"] == KunDun.TaskStage.DUP_FINISH
- return true
- end
- function this.isParticipate(actor)
- -- 参与了活动
- -- local data = dataFunc.getKunDunPlayerData(actor)
- -- return table.notEmpty(data)
- return true
- end
- function aucDbFunc.getAuctionData()
- -- return dataFunc.getCrossGlobalData(__AuctionDbKey())
- return getsysvar(__AuctionDbKey()) or {}
- end
- function aucDbFunc.setAuctionData(data)
- -- dataFunc.setCrossGlobalData(__AuctionDbKey(), data)
- setsysvar(__AuctionDbKey(), data)
- end
- function aucDbFunc.getPublishGoods()
- local data = aucDbFunc.getAuctionData()
- return data["publishgoods"] or {}
- end
- function aucDbFunc.setPublishGoods(goodsData)
- local data = aucDbFunc.getAuctionData()
- data["publishgoods"] = goodsData
- aucDbFunc.setAuctionData(data)
- end
- -- ------------------------------------------------------------- --
- this.log_open = true
- this.log_name = "[WorldBossAuction]"
- function this.debug(...)
- if not this.log_open then
- return
- end
- gameDebug.print(this.log_name, ...)
- end
- function this.print(...)
- if not this.log_open then
- return
- end
- if param == nil then
- param = "error! 输出内容为空. nil"
- end
- jprint(this.log_name, ...)
- end
- function this.info(actor, ...)
- tipinfo(actor, ...)
- this.print(...)
- end
- -- ------------------------------------------------------------- --
|