-- 怪物来袭活动 MonAtk = {} local MONSTER_ATTACK_INFO_KEY = "G$MONSTER_ATTACK_INFO" local MOSNTER_ATTACKING_KEY = "G$MOSNTER_ATTACKING" local ITEM_PICK_COUNT_KEY = "J$_ITEM_PICK_COUNT" local DROP_INFO_KEY = "Q$_DROP_INFO_KEY" function MonAtk.getMonsterAttackInfo() local data = getsysvar(MONSTER_ATTACK_INFO_KEY) if data == nil then data = {} end return data end function MonAtk.setMonsterAttackInfo(monsterAttackInfo) setsysvar(MONSTER_ATTACK_INFO_KEY, monsterAttackInfo) end function MonAtk.isMonsterAttacking() local data = getsysvar(MOSNTER_ATTACKING_KEY) if data == nil then return false end return data end function MonAtk.setMonsterAttacking(ok) setsysvar(MOSNTER_ATTACKING_KEY, ok) end function MonAtk.getAttackConfig(actId) local configList = ConfigDataManager.getList("cfg_monster_attack") local result = {} for _, config in pairs(configList) do local ruleId = config["ruleid"] local items = string.split(ruleId, "#") if (table.contains(items, actId)) then table.insert(result, config) end end return result end function MonAtk.monsterGen(monsterAttackInfo, config) local safeTime = config["safetime"] local mapCfgId = config["mapid"] local lineId = config["line"] local monsterid = config["monid"] local coordinates = config["poz"] local range = config["range"] local count = 1 local xy = string.split(coordinates, "#") local lines = string.split(lineId, "#") local x = xy[1] local y = xy[2] for _, line in pairs(lines) do local mapId = gamemap.getMapKey(mapCfgId, line) --生成怪物 local monIds = mongen(mapId, x, y, range, monsterid, count) if table.isNullOrEmpty(monIds) then -- jprint("建怪物失败",monsterid,"mapid",mapId) else for _, mactor in pairs(monIds) do local monsterUid = mactor:toString() local now = getbaseinfo("now") local monsterInfo = { leaveAttackTime = now, safeTime = safeTime, mapId = mapId, monsterId = monsterid, invalid = false, } monsterAttackInfo[monsterUid] = monsterInfo --设置定时器 setontimer(mactor, 1, 2) -- jprint("怪物来袭创建怪物",monsterUid, monsterid, mapId, mapCfgId, x, y) end end end end function MonAtk.monsterInfo(actor, monsterCfgId) local result = {} local monInfo = MonAtk.getMonsterAttackInfo() for id, m in pairs(monInfo) do local invalid = table.getValue(m, "invalid") if not invalid then local mapId = table.getValue(m, "mapId") local mid = table.getValue(m, "monsterId") local mapCfgId, mapLine = gamemap.parseMapKey(mapId) if tostring(mid) == tostring(monsterCfgId) then table.insert(result, { monsterid = mid, mapid = mapId, mapCfgId = mapCfgId, mapLine = mapLine, }) end end end sendluamsg(actor, LuaMessageIdToClient.MONSTER_ATTACK_BOSS_INFO, result) end --在地图上移除怪物 function MonAtk.removeMonster(actor, reason) --setofftimer(actor,1) local ok = removemapobject(actor) jprint("怪物来袭移除怪物", actor:toString(), reason, ok) end --定时器心跳,用于检查怪物删除 function ontimer1(actor) --jprint(" MonAtk.isMonsterAttacking() ", MonAtk.isMonsterAttacking() ) if MonAtk.isMonsterAttacking() then return end local monsterAttackInfo = MonAtk.getMonsterAttackInfo() local monsterUid = actor:toString() local monsterInfo = monsterAttackInfo[monsterUid] if table.isNullOrEmpty(monsterInfo) then --出问题了,把定怪物移除 MonAtk.removeMonster(actor, "monsterinfo为空") return end local leaveAttackTime = monsterInfo["leaveAttackTime"] local isFighting = leaveAttackTime == 0 if isFighting then --怪物如果是战斗状态,不管 return end local now = getbaseinfo("now") local diffMills = tonumber(now) - tonumber(leaveAttackTime) local safeTime = monsterInfo["safeTime"] if string.isNullOrEmpty(safeTime) then safeTime = 0 end local safeTimeMills = tonumber(safeTime) * 1000 if not MonAtk.isMonsterAttacking() and diffMills >= safeTimeMills then --活动结束且怪物脱战时间大于指定的时间,则销毁怪物 MonAtk.removeMonster(actor, "正常移除") monsterInfo["invalid"] = true MonAtk.setMonsterAttackInfo(monsterAttackInfo) end end function MonAtk.start(actId) --清空或者初始化数据 MonAtk.setMonsterAttackInfo({}) actId = tostring(actId) local configs = MonAtk.getAttackConfig(actId) if table.isNullOrEmpty(configs) then return end local monsterAttackInfo = MonAtk.getMonsterAttackInfo() for _, value in pairs(configs) do MonAtk.monsterGen(monsterAttackInfo, value) end MonAtk.setMonsterAttackInfo(monsterAttackInfo) MonAtk.setMonsterAttacking(true) end function MonAtk.stop(actId) MonAtk.setMonsterAttacking(false) --MonAtk.setMonsterAttackInfo({}) end function MonAtk.monAtkMonsterEnterAttack(monActor, monsterConfgId) local monsterUid = tostring(monActor) local monsterInfo = MonAtk.getMonsterAttackInfo()[monsterUid] if table.isNullOrEmpty(monsterInfo) then return end monsterInfo["leaveAttackTime"] = 0 end function MonAtk.monAtkMonsterLeaveAttack(monActor, monsterConfgId) local monsterUid = tostring(monActor) local monsterInfo = MonAtk.getMonsterAttackInfo()[monsterUid] if table.isNullOrEmpty(monsterInfo) then return end local now = getbaseinfo("now") monsterInfo["leaveAttackTime"] = now end function MonAtk.run(activityId, action) -- jprint("活动开始", activityId, action) if tonumber(action) == 1 then MonAtk.start(activityId) elseif tonumber(action) == 0 then MonAtk.stop(activityId) end end function MonAtk.getDropInfo() local dropInfo = getsysvar(DROP_INFO_KEY) if dropInfo == nil then dropInfo = {} end return dropInfo end function MonAtk.setDropInfo(dropInfo) setsysvar(DROP_INFO_KEY, dropInfo) end function MonAtk.monsterDieDrop(actor, dropData) local monsterUid = tostring(table.getValue(dropData, "monsterid")) local monsterAttackInfo = MonAtk.getMonsterAttackInfo() local monsterItem = monsterAttackInfo[monsterUid] if table.isNullOrEmpty(monsterItem) then return end local dropItems = table.getValue(dropData, "dropitems") local dropInfo = MonAtk.getDropInfo() local dropTime = getbaseinfo("now") for _, dropItem in pairs(dropItems) do local id = table.getValue(dropItem, "id") local cfgId = table.getValue(dropItem, "cfgid") local count = table.getValue(dropItem, "count") local dataItem = { cfgid = cfgId, count = count, droptime = dropTime } dropInfo[tostring(id)] = dataItem end -- jprint("setdropinfo", dropInfo, dropData) MonAtk.setDropInfo(dropInfo) monsterItem["invalid"] = true -- jprint("monsterItem", monsterItem) MonAtk.setMonsterAttackInfo(monsterAttackInfo) end function MonAtk.pickUpItem(actor, items) -- jprint("拾取",items) if not MonAtk.isMonsterAttacking() then return end if table.isNullOrEmpty(items) then return nil end for _, item in pairs(items) do local itemId = item["id"] --只处理第一项即可 return MonAtk.checkPickUpItem(actor, itemId) end return nil end function MonAtk.addTodayPickUpCount(actor, itemId, itemCount) local pickCountInfo = getplaydef(actor, ITEM_PICK_COUNT_KEY) if pickCountInfo == nil then pickCountInfo = {} end local strItemId = tostring(itemId) local count = table.getValue(pickCountInfo, strItemId) if count == nil then count = 0 end count = count + tonumber(itemCount) pickCountInfo[strItemId] = count --jprint("pickCountInfo", pickCountInfo) setplaydef(actor, ITEM_PICK_COUNT_KEY, pickCountInfo) end function MonAtk.getTodayPickCount(actor, itemId) local pickCountInfo = getplaydef(actor, ITEM_PICK_COUNT_KEY) if pickCountInfo == nil then return 0 end local value = table.getValue(pickCountInfo, tostring(itemId)) if value == nil then return 0 end return tonumber(value) end function MonAtk.getPickCountLimit(itemCfgId) local value = ConfigDataManager.getTableValue("cfg_global", "value", "id", 3101) if value == nil then return -1 end local map = string.toStringStringMap(value, "#", "|") local value = table.getValue(map, tostring(itemCfgId)) if string.isNullOrEmpty(value) then return -1 end return tonumber(value) end function MonAtk.checkPickUpItem(actor, itemId) local dropInfo = MonAtk.getDropInfo() --jprint("dropinfo", dropInfo) local dropItem = table.getValue(dropInfo, tostring(itemId)) if dropItem == nil then return nil end local itemCfgId = table.getValue(dropItem, "cfgid") local count = table.getValue(dropItem, "count") local pickCount = MonAtk.getTodayPickCount(actor, itemCfgId) local pickLimit = MonAtk.getPickCountLimit(itemCfgId) jprint("checkPickUpItem", itemCfgId, pickCount, pickLimit) if pickLimit == -1 then return nil end if pickLimit > pickCount then MonAtk.addTodayPickUpCount(actor, itemCfgId, count) return true else jprint("该物品今日拾取达到上限", itemCfgId) noticeTip.noticeinfo(actor,StringIdConst.TEXT336) return false end end -- =================== 以下是public函数,测试用============================ -- --活动开始 -- function monatkstart(actor, actId) -- MonAtk.start(actId) -- end --活动结束 --function monatkend(actor, actId) -- MonAtk.stop(actId) --end