| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494 |
- local DynamicObstacleController = class('DynamicObstacleController', framework.Mediator)
- DynamicObstacleController.NAME = "DynamicObstacleController"
- local INVALID_MAP_POS = 0xFFFF
- function DynamicObstacleController:ctor()
- DynamicObstacleController.super.ctor(self, self.NAME)
- self._obstacles = {}
- end
- function DynamicObstacleController:destory()
- if DynamicObstacleController.instance then
- global.Facade:removeMediator( DynamicObstacleController.NAME )
- DynamicObstacleController.instance = nil
- end
- end
- function DynamicObstacleController:Inst()
- if not DynamicObstacleController.instance then
- DynamicObstacleController.instance = DynamicObstacleController.new()
- global.Facade:registerMediator(DynamicObstacleController.instance)
- end
- return DynamicObstacleController.instance
- end
- function DynamicObstacleController:onRegister()
- DynamicObstacleController.super.onRegister(self)
- local function actCallback(actor, act)
- -- 非移动类action
- if not IsMoveAction(act) then
- return
- end
- self:dynamicPathPoints()
- end
- global.gamePlayerController:AddHandleOnActCompleted(actCallback)
- end
- function DynamicObstacleController:listNotificationInterests()
- local noticeTable = global.NoticeTable
- return
- {
- noticeTable.ActorInOfView,
- noticeTable.ActorOutOfView,
- noticeTable.ActorPlayerDie,
- noticeTable.ActorMonsterDie,
- noticeTable.ActorMonsterDeath,
- noticeTable.ActorRevive,
- noticeTable.ActorEffectInOfView,
- noticeTable.ActorEffectOutOfView,
- noticeTable.PlayerStallStatucChange,
- noticeTable.ActorSafeZoneChange,
- noticeTable.ActorMapXYChange,
- noticeTable.MapData_Load_Success,
- noticeTable.Map_Refresh_Throug_HHum,
- }
- end
- function DynamicObstacleController:handleNotification(notification)
- local noticeTable = global.NoticeTable
- local noticeID = notification:getName()
- local data = notification:getBody()
- if noticeID == noticeTable.ActorInOfView then
- self:onActorInOfView(data)
- elseif noticeID == noticeTable.ActorOutOfView then
- self:onActorOutOfView(data)
- elseif noticeID == noticeTable.ActorPlayerDie then
- self:onActorPlayerDie(data)
- elseif noticeID == noticeTable.ActorMonsterDie then
- self:onActorMonsterDie(data)
- elseif noticeID == noticeTable.ActorMonsterDeath then
- self:onActorMonsterDeath(data)
-
- elseif noticeID == noticeTable.ActorRevive then
- self:onActorRevive(data)
- elseif noticeID == noticeTable.ActorEffectInOfView then
- self:onActorEffectInOfView(data)
- elseif noticeID == noticeTable.ActorEffectOutOfView then
- self:onActorEffectOutOfView(data)
- elseif noticeID == noticeTable.PlayerStallStatucChange then
- self:onPlayerStallStatucChange(data)
- elseif noticeID == noticeTable.ActorSafeZoneChange then
- self:onActorSafeZoneChange(data)
-
- elseif noticeID == noticeTable.ActorMapXYChange then
- self:onActorMapXYChange(data)
- elseif noticeID == noticeTable.MapData_Load_Success then
- self:onMapDataLoadSuccess()
- elseif noticeID == noticeTable.Map_Refresh_Throug_HHum then
- self:onUpdateAllObstacles()
- end
- end
- function DynamicObstacleController:checkActorIsObstacle(actor)
- -- main player
- if actor:IsPlayer() and actor:IsMainPlayer() then
- return false
- end
- -- 管理员不受控制
- local MapProxy = global.Facade:retrieveProxy(global.ProxyTable.Map)
- if MapProxy:IsAdmin() and MapProxy:IsGMRunAll() then
- return false
- end
- -- dead
- if actor:IsDie() or actor:IsDeath() then
- return false
- end
- -- 该actor服务器控制可穿
- if (actor:IsNPC() or actor:IsPlayer() or actor:IsMonster()) and actor:IsThroughAble() then
- return false
- end
- local MapProxy = global.Facade:retrieveProxy(global.ProxyTable.Map)
- local isCrossAllSafeArea = MapProxy:IsCrossAllSafeArea() -- 安全区 不受控制
- local isForbidCrossNPCSafeArea = MapProxy:IsFirbidCrossNpcSafeArea() -- 安全区 禁止穿 NPC
- local isFirbidCrossStallSafeArea = MapProxy:IsFirbidCrossStallSafeArea() -- 安全区 禁止穿 摆摊玩家
- local isFirbidCrossOfflineSafeArea = MapProxy:IsFirbidCrossOfflineSafeArea() -- 安全区 禁止穿 离线玩家
- -- new obstacle data
- local isObstacle = 0
- if actor:IsNPC() then
- isObstacle = MapProxy:IsCrossNpcEnable() and 0 or 1
- if actor:GetInSafeZone() then
- isObstacle = isCrossAllSafeArea and 0 or isObstacle
- isObstacle = isFirbidCrossStallSafeArea and 1 or isObstacle
- end
- elseif actor:IsPlayer() then
- isObstacle = (MapProxy:IsCrossPlayerEnable() and 0 or 1)
- if actor:GetInSafeZone() then
- isObstacle = isCrossAllSafeArea and 0 or isObstacle
- if actor:IsStallStatus() then
- isObstacle = isFirbidCrossStallSafeArea and 1 or isObstacle
- end
- if actor:GetIsOffLine() then
- isObstacle = isFirbidCrossOfflineSafeArea and 1 or isObstacle
- end
- end
- elseif actor:IsDefender() then
- isObstacle = (MapProxy:IsCrossDefenderEnable() and 0 or 1)
- if actor:GetInSafeZone() then
- isObstacle = isCrossAllSafeArea and 0 or isObstacle
- end
- elseif actor:IsMonster() then
- isObstacle = (MapProxy:IsCrossMonsterEnable() and 0 or 1)
- if actor:GetInSafeZone() then
- isObstacle = isCrossAllSafeArea and 0 or isObstacle
- end
- elseif actor:IsSEffect() then
- local mainPlayerID = global.gamePlayerController:GetMainPlayerID()
- isObstacle = (actor:GetEffectType() == global.MMO.EFFECT_TYPE_EMPTY and actor:GetDuranceID() == mainPlayerID) and 1 or 0
- end
- return isObstacle == 1
- end
- function DynamicObstacleController:addRef(x, y)
- local key = KEY_MAP_XY(x, y)
- self._obstacles[key] = self._obstacles[key] or 0
- self._obstacles[key] = self._obstacles[key] + 1
- -- 第一次增加引用计数,将地图置为阻挡状态
- if self._obstacles[key] == 1 then
- local mapData = global.sceneManager:GetMapData2DPtr()
- if not mapData then
- return nil
- end
- mapData:setObstacle(x, y, 1)
- end
- end
- function DynamicObstacleController:decRef(x, y)
- local key = KEY_MAP_XY(x, y)
- self._obstacles[key] = self._obstacles[key] or 0
- self._obstacles[key] = self._obstacles[key] - 1
- -- 警告
- if self._obstacles[key] < 0 then
- print("WARNING, dynamic obstacle less than 0!!!", self._obstacles[key], x, y)
- PrintTraceback()
- end
- -- 计数 < 0, 当前位置已无动态阻挡
- if self._obstacles[key] <= 0 then
- self._obstacles[key] = nil
- local mapData = global.sceneManager:GetMapData2DPtr()
- if not mapData then
- return nil
- end
- mapData:setObstacle(x, y, 0)
- end
- end
- function DynamicObstacleController:onActorMapXYChange(data)
- if not data or not data.actor then
- return
- end
- local actor = data.actor
- local lastMapX = actor:GetLastMapX()
- local lastMapY = actor:GetLastMapY()
- local currMapX = actor:GetMapX()
- local currMapY = actor:GetMapY()
-
- -- 该Actor无阻挡标记,不进行阻挡引用计数 +-
- if not actor:IsObstacleFlag() then
- return
- end
- -- 当前坐标点无效,可能是未执行进视野先执行了刷新
- if currMapX == INVALID_MAP_POS and currMapY == INVALID_MAP_POS then
- return
- end
- if lastMapX ~= INVALID_MAP_POS and lastMapY ~= INVALID_MAP_POS then
- self:decRef(lastMapX, lastMapY)
- end
- self:addRef(currMapX, currMapY)
- end
- function DynamicObstacleController:checkAddObstacle(data)
- if not data or not data.actor then
- return
- end
- local actor = data.actor
- -- 检测是否给阻挡标记
- local isObstacle = self:checkActorIsObstacle(actor)
- actor:SetObstacleFlag(isObstacle)
- -- 不存在阻挡标记
- if not actor:IsObstacleFlag() then
- return
- end
- -- 增加该位置引用计数
- local currMapX = actor:GetMapX()
- local currMapY = actor:GetMapY()
- self:addRef(currMapX, currMapY)
- end
- function DynamicObstacleController:checkRemoveObstacle(data)
- if not data or not data.actor then
- return
- end
- local actor = data.actor
- -- 不存在阻挡标记
- if not actor:IsObstacleFlag() then
- return
- end
- -- ???? 是否应该置为 false
- actor:SetObstacleFlag(false)
- -- 减少该位置引用计数
- local currMapX = actor:GetMapX()
- local currMapY = actor:GetMapY()
- self:decRef(currMapX, currMapY)
- end
- function DynamicObstacleController:checkUpdateObstacle(data)
- -- 注意这里刷新,坐标无改变,应认为 同位置刷新
- if not data or not data.actor then
- return
- end
- local actor = data.actor
- local currMapX = actor:GetMapX()
- local currMapY = actor:GetMapY()
- -- 当前坐标点无效,可能是未执行进视野先执行了刷新
- if currMapX == INVALID_MAP_POS and currMapY == INVALID_MAP_POS then
- return
- end
- -- 否是阻挡
- local lastObstacleFlag = actor:IsObstacleFlag()
- -- 检测是否给阻挡标记
- local isObstacle = self:checkActorIsObstacle(actor)
- actor:SetObstacleFlag(isObstacle)
- -- 阻挡数据无变化
- if lastObstacleFlag == actor:IsObstacleFlag() then
- return
- end
- -- 上次是阻挡,减引用计数
- if lastObstacleFlag then
- self:decRef(currMapX, currMapY)
- end
-
- -- 当前是阻挡,加引用计数
- if actor:IsObstacleFlag() then
- self:addRef(currMapX, currMapY)
- end
- end
- function DynamicObstacleController:onActorInOfView(data)
- self:checkAddObstacle(data)
- end
- function DynamicObstacleController:onActorEffectInOfView(data)
- self:checkAddObstacle(data)
- end
- function DynamicObstacleController:onActorOutOfView(data)
- self:checkRemoveObstacle(data)
- end
- function DynamicObstacleController:onActorPlayerDie(data)
- self:checkRemoveObstacle(data)
- end
- function DynamicObstacleController:onActorMonsterDie(data)
- self:checkRemoveObstacle(data)
- end
- function DynamicObstacleController:onActorMonsterDeath(data)
- self:checkRemoveObstacle(data)
- end
- function DynamicObstacleController:onActorRevive(data)
- self:checkUpdateObstacle(data)
- end
- function DynamicObstacleController:onActorEffectOutOfView(data)
- self:checkRemoveObstacle(data)
- end
- function DynamicObstacleController:onPlayerStallStatucChange(data)
- self:checkUpdateObstacle(data)
- end
- function DynamicObstacleController:onActorSafeZoneChange(data)
- self:checkUpdateObstacle(data)
- end
- function DynamicObstacleController:onMapDataLoadSuccess(data)
- self._obstacles = {}
- -- npc
- local actors, ncount = global.npcManager:GetNpcInCurrViewField()
- for i = 1, ncount do
- local actor = actors[i]
- if actor then
- self:checkAddObstacle({actor = actor, actorID = actor:GetID()})
- end
- end
- -- player
- local actors, ncount = global.playerManager:GetPlayersInCurrViewField()
- for i = 1, ncount do
- local actor = actors[i]
- if actor then
- self:checkAddObstacle({actor = actor, actorID = actor:GetID()})
- end
- end
- -- monsters
- local actors, ncount = global.monsterManager:GetMonstersInCurrViewField()
- for i = 1, ncount do
- local actor = actors[i]
- if actor then
- self:checkAddObstacle({actor = actor, actorID = actor:GetID()})
- end
- end
- end
- function DynamicObstacleController:onUpdateAllObstacles()
- -- npc
- local actors, ncount = global.npcManager:GetNpcInCurrViewField()
- for i = 1, ncount do
- local actor = actors[i]
- if actor then
- self:checkUpdateObstacle({actor = actor, actorID = actor:GetID()})
- end
- end
- -- player
- local actors, ncount = global.playerManager:GetPlayersInCurrViewField()
- for i = 1, ncount do
- local actor = actors[i]
- if actor then
- self:checkUpdateObstacle({actor = actor, actorID = actor:GetID()})
- end
- end
- -- monsters
- local actors, ncount = global.monsterManager:GetMonstersInCurrViewField()
- for i = 1, ncount do
- local actor = actors[i]
- if actor then
- self:checkUpdateObstacle({actor = actor, actorID = actor:GetID()})
- end
- end
- end
- function DynamicObstacleController:dynamicPathPoints()
- local mainPlayer = global.gamePlayerController:GetMainPlayer()
- if not mainPlayer then
- return nil
- end
- local mapData = global.sceneManager:GetMapData2DPtr()
- if not mapData then
- return nil
- end
- local PlayerInputProxy = global.Facade:retrieveProxy(global.ProxyTable.PlayerInputProxy)
- local currPathPoint = PlayerInputProxy:GetCurrPathPoint()
- local pathPoints = PlayerInputProxy:GetPathFindPoints()
- if currPathPoint <= 0 or #pathPoints <= 0 then
- return nil
- end
- local startPos = cc.p(mainPlayer:GetMapX(), mainPlayer:GetMapY())
- local destPos = nil
- local destIndex = nil
- -- find dest pos
- if pathPoints[currPathPoint] then
- local path = pathPoints[currPathPoint]
- if mapData:isObstacle(path.x, path.y) == 1 then
- for i = currPathPoint, 1, -1 do
- path = pathPoints[i]
- if mapData:isObstacle(path.x, path.y) == 0 then
- destPos = path
- destIndex = i
- break
- end
- end
- end
- end
- -- can't find obstacle
- if not destPos then
- return nil
- end
- print("--------------------- modify path")
- dump(destPos)
- -- it's current pos,nothing to do
- if startPos.x == destPos.x and startPos.y == destPos.y then
- return nil
- end
- -- find path
- local findPoints = global.PathFindController:FindPathAStarLimits(startPos, destPos)
- -- can't find dest
- if #findPoints <= 0 then
- return nil
- end
- -- new path points
- local newPathPoints = {}
- for i, v in ipairs(pathPoints) do
- if i == destIndex then
- break
- end
- table.insert(newPathPoints, v)
- end
- for i, v in ipairs(findPoints) do
- table.insert(newPathPoints, v)
- end
- PlayerInputProxy:SetPathFindPoints( newPathPoints )
- end
- return DynamicObstacleController
|