-- SyncMoveManager的补充脚本:镖车相关代码 local TownCartManager = { CartInfoList = {}, -- 存储所有的cart和其信息 {entity,info = objectSceneBasic} MyCartEntity = nil, -- 主视角 我的镖车 MyCartUniqid = nil, -- 主视角 我的镖车的uniqid MyCartDisIsFar = true, -- 主视角 我和我的镖车距离是否很远 FollowNPCPlayerListDic = {}, -- 跟随NPC的所有玩家 [uniqId] = {acid,acid,acid} CurFollowStateDic = {}, -- 当前entity的追随状态 字典 [acid] = EnumFollowState.Free FollowDic = {}, -- 跟随字典 [acid] = [followUnqid] ,只要有玩家这个就不销毁 FollowMoveInfo = {}, -- 当前跟随信息,如果跟随者或者被跟随者不存在,则值为nil。 [acid] = { speed } } local private = {CanSendStopFollowFrame = -1} local tonumberV2 = FP.tonumberV2 local releaseV2 = FP.releaseV2 local IsRotateClockwise = FP.V2.IsRotateClockwise local add_role_screen_pb = require("Proto/add_role_screen_pb") local team_operate_pb = require 'Proto/team_operate_pb' local math_sqrt = math.sqrt local EventSystem = require('Event/EventSystem') local EntityHeadUIModule = require("View/Battle/BattleEntityUI/EntityUIModule/EntityHeadUIModule") local PetSystem = require "Battle/Logic/Entity/System/PetSystem" local _posTemp = FP.newV2(0,0) local _dirTemp = FP.newV2(0,1) local Const_EscortRobNum = DataSheetManager.ConstData:GetDataByID("RobNum").IntValue -- 每辆车可劫镖次数 local Const_EscortCarLeaveDis = DataSheetManager.ConstData:GetDataByID("EscortCarLeaveDis").IntValue -- 我离开自己镖车是否远了的一个判断 local Const_EscortCarLeaveDisSqr = Const_EscortCarLeaveDis * Const_EscortCarLeaveDis local Const_RotateSpeedLmt = FP.newV1(5) local Const_HorseAimSpeed = 0.3 local Const_ChaseCartDis = FP.newV1(0.2) local EnumFollowState = { Free = 0, -- 自由行走 Chase = 1, -- 追赶镖车 Follow = 2, -- 阵容跟随 } -- 玩家跟随镖车的位置排布 local TeamPos = { [0] = {{0,-8}}, --正后方8米 [1] = {{0,-8}}, --正后方8米 [2] = {{2,-8} ,{-2, -8}}, [3] = {{0,-8},{3,-8},{-3, -8}} } local QualityColor = { [1] = "5c9764", [2] = "7292c2", [3] = "9c7dcb", [4] = "eea11a", } local CartNameIDS = { team = { [0] = "IDS_Escort_BlueName3", -- %s队伍的镖车 [1]= "IDS_Escort_BlueName4", -- %s队伍的残破镖车 }, person = { [0] = "IDS_Escort_BlueName1", -- %s的镖车 [1] = "IDS_Escort_BlueName2", -- %s的残破镖车 }, } function TownCartManager.Clear() TownCartManager.CartInfoList = {} TownCartManager.MyCartEntity = nil TownCartManager.MyCartUniqid = nil TownCartManager.MyCartDisIsFar = true TownCartManager.CurFollowStateDic = {} TownCartManager.FollowDic = {} TownCartManager.FollowMoveInfo = {} private.ClickObjectInfo = nil private.CanSendStopFollowFrame = -1 --防止重复发送停止跟随协议 end function TownCartManager.RegistMessage() NetManager.RegisterMsgCB(MessageEnums.MessageS2CGetCartPos, private.OnS2CGetCartPos) NetManager.RegisterMsgCB(MessageEnums.MessageS2CCartInfoChange, private.OnCartInfoChange) NetManager.RegisterMsgCB(MessageEnums.MessageS2CCartRoleListChange, private.OnCartRoleListChange) NetManager.RegisterMsgCB(MessageEnums.MessageS2CTeamFollowNpc,private.OnTeamFollowNpc) -- 以后如果有通用的,可以放在syncmovemanager 以复用 end function TownCartManager.OnLogicUpdate() if LuaInputManager.FixVirtualMoveDir ~= FP.Const.Vector2_Zero then local myFollowState = TownCartManager.CurFollowStateDic[BattleDataGetter.GetAcID()] if myFollowState and myFollowState ~= EnumFollowState.Free then -- 停止跟随,自己停止,同时通知其他人停止 if LogicUpdateManager._clientHandleFrame >= private.CanSendStopFollowFrame then local followMsg = team_operate_pb.C2STeamFollowNpc() followMsg.isFollow = false followMsg.npcId = TownCartManager.MyCartUniqid NetManager.SendMessage(MessageEnums.MessageC2STeamFollowNpc,followMsg) private.CanSendStopFollowFrame = LogicUpdateManager._clientHandleFrame + 20 end end end TownCartManager.CheckMyCartDistance() TownCartManager.HandleEntityMove() end function TownCartManager.CreateCartEntity(objectSceneBasic) local cartInfo = objectSceneBasic.cartInfo local posX,posZ = objectSceneBasic.SceneInfo.Pos.X,objectSceneBasic.SceneInfo.Pos.Z local acid,playerName = objectSceneBasic.ownerAcid,objectSceneBasic.ownerName local escortData = DataSheetManager.GuildEscortData:GetDataByID(cartInfo.quality) local modelId = escortData.CarNPCID local positionV2 = FP.newV2(0,0):Rawset(posX,posZ) local endPos = objectSceneBasic.cartInfo.destPos local forwardV2 = nil if endPos.X == posX and endPos.Z == posZ then forwardV2 = FP.newV2(0,1) else forwardV2 = FP.newV2(endPos.X-posX,endPos.Z-posZ) forwardV2:Normalize() end EntityFactory.SetPos_Dir(positionV2, forwardV2) EntityFactory.SetType_ID(LuaConst.CharacterType.NPC, modelId) local entity = EntityFactory.DoCreateEntity() private.RefreshCartName(entity, cartInfo, playerName) --标记主视角的镖车 local roleList = cartInfo.roleList local myCartAcid = BattleDataGetter.GetAcID() for i,acid in ipairs(roleList) do if acid == myCartAcid then TownCartManager.MyCartEntity = entity TownCartManager.MyCartUniqid = objectSceneBasic.uniqId end end return entity end -- 删除镖车 function TownCartManager.AfterRemoveCartByInfo(object) local cartUid = object.info.uniqId -- 从镖车列表中删除 local count = #TownCartManager.CartInfoList for i = count,1,-1 do local cartInfo = TownCartManager.CartInfoList[i] if cartInfo.info.uniqId == cartUid then table.remove(TownCartManager.CartInfoList, i) if TownCartManager.MyCartUniqid == cartUid then if CTL.GuildEscort.IsTransport() then -- 当删除镖车时,但是任务又存在的case:1.交付镖车时 2.远离镖车时 local myFollowState = TownCartManager.CurFollowStateDic[BattleDataGetter.GetAcID()] if myFollowState == EnumFollowState.Follow or myFollowState == EnumFollowState.Chase then --当我跟随时 ,镖车消失 ,则主动提示下玩家镖车太远了(交付镖车会误发,所以加个延迟) TimerUtil.Interval(function() if CTL.GuildEscort.IsTransport() then EventSystem.Dispatch(EventID.GuildEscort_MyCartIsFar, cartUid, true) TownCartManager.MyCartDisIsFar = true EventSystem.Dispatch(EventID.GuildEscort_MyCartFollow, false) end end , 1, 1) end end TownCartManager.MyCartEntity = nil TownCartManager.MyCartUniqid = nil TownCartManager.MyCartDisIsFar = true local followMsg = team_operate_pb.C2STeamFollowNpc() followMsg.isFollow = false NetManager.SendMessage(MessageEnums.MessageC2STeamFollowNpc,followMsg) end break end end -- 删除选中框 if private.ClickObjectInfo ~= nil and private.ClickObjectInfo.info.uniqId == cartUid then private.CancelClickEffect() end -- 跟随者行为恢复自由,但是数据还保存别删 local playerList = TownCartManager.FollowNPCPlayerListDic[cartUid] if playerList then for _,acid in ipairs(playerList) do TownCartManager.FollowMoveInfo[acid] = nil TownCartManager.CurFollowStateDic[acid] = nil end end TownCartManager.FollowNPCPlayerListDic[cartUid] = nil end function private.SortFollow(acid_a,acid_b) return acid_a > acid_b end function private.SortFollowList(followList,leaderAcid) local leader = nil for i,acid in ipairs(followList) do if acid == leaderAcid then leader = acid table.remove(followList,i) break end end if leader then table.insert(followList,leader) end end -- 有镖车npc出生 function TownCartManager.AddNewCartInfo(objectSceneBasic,entity) table.insert(TownCartManager.CartInfoList, {entity = entity, info = objectSceneBasic, inBattle = objectSceneBasic.cartInfo.inBattle, robCount = objectSceneBasic.cartInfo.robCount}) local ownerAcid = objectSceneBasic.cartInfo.ownerInfo.accid -- 统计跟随这个车的player 并让这些player去跟随 for acid,uniqId in pairs(TownCartManager.FollowDic) do if uniqId == objectSceneBasic.uniqId then if TownCartManager.FollowNPCPlayerListDic[uniqId] then local content = table.containValue(TownCartManager.FollowNPCPlayerListDic[uniqId], acid) if not content then local followList = TownCartManager.FollowNPCPlayerListDic[uniqId] table.insert(followList, acid) table.sort(followList, private.SortFollow) private.SortFollowList(followList,ownerAcid) end else TownCartManager.FollowNPCPlayerListDic[uniqId] = {acid} end -- 让这些player去跟随 : 在3米内则立刻follow,否则chase TownCartManager.CurFollowStateDic[acid] = EnumFollowState.Chase local playerEntity = SyncMoveManager.GetEntityByAcid(acid) if playerEntity then -- 如果以后出现了bug:车和人离着很远,人是追赶状态,把人的追随协议的isFollow改为 追随枚举 TownCartManager.BeginFollowCart(playerEntity) end end end --logging.error(LTAG.ERROR, "镖车出生 ") end --每帧检测我和镖车的距离限制 function TownCartManager.CheckMyCartDistance() if TownCartManager.MyCartEntity and LogicUpdateManager._curEntity then local mx, mz = tonumberV2(LogicUpdateManager._curEntity:GetLogicPos()) local ox, oz = tonumberV2(TownCartManager.MyCartEntity:GetLogicPos()) local dx = ox - mx local dz = oz - mz local isFar = dx * dx + dz * dz > Const_EscortCarLeaveDisSqr if isFar and not TownCartManager.MyCartDisIsFar then-- 跑出范围了 EventSystem.Dispatch(EventID.GuildEscort_MyCartIsFar, TownCartManager.MyCartUniqid, true) TownCartManager.MyCartDisIsFar = true elseif not isFar and TownCartManager.MyCartDisIsFar then --跑入范围了 EventSystem.Dispatch(EventID.GuildEscort_MyCartIsFar, TownCartManager.MyCartUniqid, false) TownCartManager.MyCartDisIsFar = false end end end --获取范围内的所有车 centerEntity 圆心 ;radiusSqr 半径的平方;outList 输出列表 function TownCartManager.GetCartsListByRange(centerEntity, radiusSqr, outList) local mx, mz = tonumberV2(centerEntity:GetLogicPos()) for _,info in ipairs(TownCartManager.CartInfoList) do local entity = info.entity local ox, oz = tonumberV2(entity:GetLogicPos()) local dx = ox - mx local dz = oz - mz if dx * dx + dz * dz < radiusSqr and -- 距离判断 info.info.cartInfo.robSuccessCount < Const_EscortRobNum and -- 判断被劫镖次数 not MDL.Guild.IsSameGuild(info.info.cartInfo.ownerInfo.guildShow.guildId) and -- 判断是否是同势力 not MDL.Country.IsSameCountry(info.info.cartInfo.ownerInfo.countryInfo.countryId) -- 判断是否是同国家 then table.insert(outList, info) end end end ---跟随相关代码 ↓↓↓ function TownCartManager.BeginFollowCart_MySelf(isConvey) -- 主视角代码 ,我开始跟随车 if CTL.Team.IsInTeam() and MDL.Team.GetSelfMemberInfo().state == MDL.Team.MemberState.Following then -- 如果我正在跟随队长,则停止跟随队长 MDL.Team.TeamFollowReq(false) end if TownCartManager.MyCartEntity == nil then local msg = add_role_screen_pb.C2SGetCartPos() NetManager.SendMessage(MessageEnums.MessageC2SGetCartPos,msg) --logging.error(LTAG.ERROR, "找车 ! ") else local followMsg = team_operate_pb.C2STeamFollowNpc() followMsg.npcId = TownCartManager.MyCartUniqid followMsg.isFollow = true followMsg.isConvey = isConvey or false --logging.error(LTAG.ERROR, "寻车 isConvey = ", followMsg.isConvey) NetManager.SendMessage(MessageEnums.MessageC2STeamFollowNpc,followMsg) end end -- 设置跟随信息(有玩家进入视野时) function TownCartManager.SetFollowInfo(accid, followUid, entity) if TownCartManager.FollowNPCPlayerListDic[followUid] == nil then TownCartManager.FollowNPCPlayerListDic[followUid] = {accid} else local content = table.containValue(TownCartManager.FollowNPCPlayerListDic[followUid], accid) if not content then local followList = TownCartManager.FollowNPCPlayerListDic[followUid] table.insert(followList, accid) table.sort(followList, private.SortFollow) local objectInfo = SyncMoveManager.TownObjectDic[followUid] if objectInfo then local ownerAcid = objectInfo.info.cartInfo.ownerInfo.accid private.SortFollowList(followList,ownerAcid) end end end TownCartManager.FollowDic[accid] = followUid local followEntity = SyncMoveManager.GetNpcEntityByUniqId(followUid) if followEntity then TownCartManager.BeginFollowCart(entity) end end -- 玩家消失时,清空跟随数据 function TownCartManager.RemoveFollowInfo(accid) local followUid = TownCartManager.FollowDic[accid] if TownCartManager.FollowNPCPlayerListDic[followUid] then table.removebyvalue(TownCartManager.FollowNPCPlayerListDic[followUid], accid) end TownCartManager.FollowDic[accid] = nil TownCartManager.CurFollowStateDic[accid] = nil TownCartManager.FollowMoveInfo[accid] = nil if private.ClickObjectInfo ~= nil and private.ClickObjectInfo.info.ownerAcid == accid then private.CancelClickEffect() end end function private.GetFollowIndexAndCount(cartUid, playerAcid) local followList = TownCartManager.FollowNPCPlayerListDic[cartUid] if followList then local count = #followList for i,acid in ipairs(followList) do if acid == playerAcid then return i, count end end end return 1,0 end -- 收到服务器下发的 跟随协议 function private.OnTeamFollowNpc(msg) local entity = SyncMoveManager.GetEntityByAcid(msg.acid) if entity then -- 自己在协议发送前已经处理了自己逻辑,所以这里不用处理自己相关 if msg.isFollow then TownCartManager.FollowDic[msg.acid] = msg.npcId local followEntity = SyncMoveManager.GetNpcEntityByUniqId(msg.npcId) if followEntity then if TownCartManager.FollowNPCPlayerListDic[msg.npcId] then local content = table.containValue(TownCartManager.FollowNPCPlayerListDic[msg.npcId], msg.acid) if not content then local followList = TownCartManager.FollowNPCPlayerListDic[msg.npcId] table.insert(followList, msg.acid) table.sort(followList, private.SortFollow) local objectInfo = SyncMoveManager.TownObjectDic[msg.npcId] if objectInfo then local ownerAcid = objectInfo.info.cartInfo.ownerInfo.accid private.SortFollowList(followList,ownerAcid) end end else TownCartManager.FollowNPCPlayerListDic[msg.npcId] = {msg.acid} end if msg.isConvey then --logging.error(LTAG.ERROR, "OnTeamFollowNpc = ", msg.isFollow, msg.isConvey) TownCartManager.BeginFollowCart(entity) else if TownCartManager.CurFollowStateDic[msg.acid] ~= EnumFollowState.Follow then NotSyncBattleSetter.RideHorse(entity) TownCartManager.CurFollowStateDic[msg.acid] = EnumFollowState.Chase else EventSystem.Dispatch(EventID.UI_Auto_Tips, LuaConst.AutoType.FollowingCart) end end end else local followNpcId = TownCartManager.FollowDic[msg.acid] TownCartManager.FollowDic[msg.acid] = nil TownCartManager.StopFollowCart(msg.acid, entity, followNpcId) end end end -- 收到服务器下发的 追踪镖车位置 function private.OnS2CGetCartPos(msg) if msg.success then NotSyncBattleSetter.RideHorse(LogicUpdateManager._curEntity) _posTemp:Rawset(msg.curPos.X, msg.curPos.Z) LogicUpdateManager._curEntity.components.autoFight:SetAutoFindPath(_posTemp, Const_ChaseCartDis, TownCartManager.BeginFollowCart_MySelf) end end -- 瞬间传送并开始阵型跟随 function TownCartManager.BeginFollowCart(playerEntity) local acid = SyncMoveManager.GetAcIdOfEntity(playerEntity) local cartUniqId = TownCartManager.FollowDic[acid] local followIndex, teamNum = private.GetFollowIndexAndCount(cartUniqId, acid) local offsetPosList = TeamPos[teamNum] local offset = offsetPosList[followIndex] local objectInfo = SyncMoveManager.TownObjectDic[cartUniqId] if objectInfo == nil then logging.log(LTAG.LOG,"[gws] : 开始跟随镖车 ,但是它不在视野中 cartUniqId = ", cartUniqId) return end local cartEntity = objectInfo.entity if cartEntity == nil then logging.log(LTAG.LOG,"[gws] : 开始跟随镖车 ,但是它的entity还没创建 cartUniqId = ", cartUniqId) return end SyncMoveManager.ClearEntityMoveTargetPos(playerEntity) local px, pz = tonumberV2(cartEntity:GetLogicPos()) local dirX,dirZ = tonumberV2(cartEntity.components.move.LogicRotateDir) -- 要瞬移到的点 local startPosX, startPosZ = private.GetOffsetToForward(px, pz, dirX, dirZ, offset[1], offset[2]) local moveComponent = playerEntity.components.move moveComponent.LastLogicPos:Reset(moveComponent.LogicPos) moveComponent.LogicPos:Reset(startPosX, startPosZ) -- 要缓慢移动到的点 local targetPosX,targetPosZ,speedFrame = SyncMoveManager.GetObjectMoveTargetPosAndSpeed(cartUniqId) local endPosX, endPosZ = private.GetOffsetToForward(targetPosX, targetPosZ, dirX, dirZ, offset[1], offset[2]) local disX = endPosX - startPosX local disZ = endPosZ - startPosZ local distance = math_sqrt(disX * disX + disZ * disZ) local playerDirX,playerDirZ if disX == 0 and disZ == 0 then logging.warn(LTAG.WARN, "起始和终止位置相同") playerDirX,playerDirZ = dirX, dirZ else playerDirX,playerDirZ = disX /distance , disZ / distance moveComponent.LogicRotateDir:Reset(playerDirX , playerDirZ) end SystemManager.ResetTransform(playerEntity) PetSystem.OnConvey(playerEntity) TownCartManager.CurFollowStateDic[acid] = EnumFollowState.Follow local moveInfo = TownCartManager.FollowMoveInfo[acid] --logging.error(LTAG.ERROR, "开始跟车速度 speed = ", speedFrame , moveInfo == nil) if moveInfo == nil then TownCartManager.FollowMoveInfo[acid] = {speed = speedFrame or 0 }-- -- speed 是每逻辑帧的位移 else moveInfo.speed = speedFrame or 0 end NotSyncBattleSetter.RideHorse(playerEntity) playerEntity.components.move:SetMoveStateHandledFlag(true)--标记这个单位的move在非cmd的代码中被处理过 -- 为了让马走 保持move状态 playerEntity.ExpEntity:PlayHorseRunAnimation(Const_HorseAimSpeed, 0) -- 为了让马走 SystemManager.SetNextState(LuaConst.StateType.Move, playerEntity) -- 为了让马走 SystemManager.DeleteBuff(playerEntity, LuaConst.SpecialBuffs.HorseUpdateSelfAnim) -- 为了让马走(不停) moveComponent.RideSpeedRate:Reset() -- 防止马继续大步前行 ExpSystemManager.PlayHorseWalkSound(playerEntity.ExpEntity) EventSystem.Dispatch(EventID.GuildEscort_CartFollow, playerEntity, true, speedFrame / LuaConst.TimeSpan) if playerEntity == LogicUpdateManager._curEntity then private.StopMyCartRange() end end --镖车的移动目标点变化 | 镖车开始移动 function TownCartManager.OnCartTargetPosChange(uniqId, speed, targetPosX, targetPosZ, moveDirX, moveDirZ) -- logging.error(LTAG.ERROR , "npc 目标位置:", targetPosX, targetPosZ) local playerList = TownCartManager.FollowNPCPlayerListDic[uniqId] if playerList then for _,acid in ipairs(playerList) do local entity = SyncMoveManager.GetEntityByAcid(acid) if entity then local moveInfo = TownCartManager.FollowMoveInfo[acid] if moveInfo then moveInfo.speed = speed * LuaConst.TimeSpan else TownCartManager.FollowMoveInfo[acid] = {speed = speed * LuaConst.TimeSpan } end end end end end -- 服务器下发了停止镖车移动 function TownCartManager.OnCartStopMove(uniqId) local playerList = TownCartManager.FollowNPCPlayerListDic[uniqId] if playerList then for _,acid in ipairs(playerList) do local followState = TownCartManager.CurFollowStateDic[acid] if followState == EnumFollowState.Follow then if TownCartManager.FollowMoveInfo[acid] then TownCartManager.FollowMoveInfo[acid].speed = 0 end local entity = SyncMoveManager.GetEntityByAcid(acid) if entity then SystemManager.SetNextState(LuaConst.StateType.Idle, entity) end if entity == LogicUpdateManager._curEntity then SyncMoveManager.C2SRoleMoveOrStop(0) end end end end end --玩家停止跟随 function TownCartManager.StopFollowCart(acid, playerEntity ,followNpcId) local followState = TownCartManager.CurFollowStateDic[acid] if followState ~= EnumFollowState.Free then TownCartManager.CurFollowStateDic[acid] = EnumFollowState.Free playerEntity.components.move:SetMoveStateHandledFlag(false)--可以根据自己摇杆移动了。 SystemManager.SetNextState(LuaConst.StateType.Idle, playerEntity) --logging.error(LTAG.ERROR, " StopFollowCart : entity = ", playerEntity.EntityID) end EventSystem.Dispatch(EventID.GuildEscort_CartFollow, playerEntity, false) local followList = TownCartManager.FollowNPCPlayerListDic[followNpcId] if followList then table.removebyvalue(followList, acid, true) end if playerEntity == LogicUpdateManager._curEntity then private.CanSendStopFollowFrame = -1 private.ShowMyCartRange() -- 显示镖车脱离范围 end end --自己chase上后的callback ,通知所有人变为follow local function ChasedCallBack() if TownCartManager.MyCartUniqid then -- 寻路完后,发现车没了 local followMsg = team_operate_pb.C2STeamFollowNpc() followMsg.npcId = TownCartManager.MyCartUniqid followMsg.isFollow = true followMsg.isConvey = true NetManager.SendMessage(MessageEnums.MessageC2STeamFollowNpc,followMsg) end end -- 执行跟随移动--- 目前只做我的跟随 ,其他玩家的后面看效果再说 function TownCartManager.HandleEntityMove() for acid,followState in pairs(TownCartManager.CurFollowStateDic) do local entity = SyncMoveManager.GetEntityByAcid(acid) if entity == nil then logging.error(LTAG.ERROR, "【gws】 追车的玩家都没了 ,追踪状态应该为 nil 了呀!") TownCartManager.CurFollowStateDic[acid] = nil break end if followState == EnumFollowState.Chase then -- 只有自己才能寻路,其他玩家都是同步位置 if entity == LogicUpdateManager._curEntity then --[[local chaseUid = TownCartManager.FollowDic[acid] local chaseEntity = SyncMoveManager.GetNpcEntityByUniqId(chaseUid) if chaseEntity == nil then logging.error(LTAG.ERROR, "【gws】 我的镖车不见了,不能追了 ,追踪状态应该为 nil 了呀!") TownCartManager.CurFollowStateDic[acid] = nil break end--]] local chaseEntity = TownCartManager.MyCartEntity if chaseEntity then _posTemp:Reset(chaseEntity:GetLogicPos()) local followIndex, teamNum = private.GetFollowIndexAndCount(TownCartManager.MyCartUniqid, acid) local offsetPosList = TeamPos[teamNum] local offset = offsetPosList[followIndex] local px, pz = tonumberV2(_posTemp) local dirX,dirZ = tonumberV2(chaseEntity.components.move.LogicRotateDir) local endPosX, endPosZ = private.GetOffsetToForward(px, pz, dirX, dirZ, offset[1], offset[2]) _posTemp:Reset(endPosX, endPosZ) entity.components.autoFight:SetAutoFindPath(_posTemp, Const_ChaseCartDis, ChasedCallBack) end end elseif followState == EnumFollowState.Follow then local moveComponent = entity.components.move local aiBaseComponent = entity.components.aiBase moveComponent:SetMoveStateHandledFlag(true) local cartUniqId = TownCartManager.FollowDic[acid] local followIndex, teamNum = private.GetFollowIndexAndCount(cartUniqId, acid) local offsetPosList = TeamPos[teamNum] local offset = offsetPosList[followIndex] local cartEntity = SyncMoveManager.GetNpcEntityByUniqId(cartUniqId) if cartEntity == nil then TownCartManager.CurFollowStateDic[acid] = nil break end local px, pz = tonumberV2(cartEntity:GetLogicPos()) local dirX,dirZ = tonumberV2(cartEntity.components.move.LogicRotateDir) local posX, posZ = private.GetOffsetToForward(px, pz, dirX, dirZ, offset[1], offset[2]) local logicPosX,logicPosZ = tonumberV2(moveComponent.LogicPos) local offsetX = posX - logicPosX local offsetZ = posZ - logicPosZ local distance = math.sqrt( offsetX * offsetX + offsetZ * offsetZ) -- 目标点位置的距离 --local e2fDisSqr = (px- logicPosX) * (px- logicPosX) + (pz- logicPosZ) * (pz - logicPosZ) -- 镖车和人的距离 local moveInfo = TownCartManager.FollowMoveInfo[acid] local speed = moveInfo.speed if speed == 0 then if aiBaseComponent.CurStateType ~= LuaConst.StateType.Idle then SystemManager.SetNextState(LuaConst.StateType.Idle, entity) end if entity == LogicUpdateManager._curEntity then SyncMoveManager.C2SRoleMoveOrStop(0) end else if distance > 0.5 then speed = speed * 1.3 end if distance >= speed then -- 动作 if aiBaseComponent.CurStateType ~= LuaConst.StateType.Move then --logging.error(LTAG.ERROR, " SetNextState Move: entity = ", entity.EntityID) SystemManager.SetNextState(LuaConst.StateType.Move, entity) if entity.components.buff:CheckHasBuffState(LuaConst.SpecialBuffs.InRiding) then entity.ExpEntity:PlayHorseRunAnimation(Const_HorseAimSpeed, 0) SystemManager.DeleteBuff(entity, LuaConst.SpecialBuffs.HorseUpdateSelfAnim) ExpSystemManager.PlayHorseWalkSound(entity.ExpEntity) end end -- 角度转弯(方案二:如果为了节约性能,可以对镖车进行慢转弯,跟随者直接设置朝向) _dirTemp:Reset(offsetX,offsetZ) _dirTemp:Normalize() if _dirTemp ~= moveComponent.LogicRotateDir then moveComponent.LastLogicRotateDir:Reset(moveComponent.LogicRotateDir) local headAngle = private.TryRotateFollower(_dirTemp, moveComponent.LogicRotateDir, moveComponent.LogicRotateDir) entity.ExpEntity:PlayHorseRunAnimation(Const_HorseAimSpeed, headAngle) end -- 前进 local moveDirX,moveDirZ = FP.tonumberV2(_dirTemp) moveComponent.LastLogicPos:Reset(moveComponent.LogicPos) moveComponent:SetLogicPosXZ(logicPosX + speed * moveDirX, logicPosZ + speed * moveDirZ) if entity == LogicUpdateManager._curEntity then SyncMoveManager.C2SRoleMoveOrStop(1) end --logging.error(LTAG.ERROR, "临时log : " , distanceSqr , speed * speed) end end end end end -- math.acos 结果范围时[0-3.14] function private.TryRotateFollower(targetDir, curDir, outDir) local angle = FP.V2.Angle(curDir, targetDir) local headAngle = 0.5 -- 取0.5是因为 Const_HorseAimSpeed 为0.3是 ,最大摆头是45度,旋转限制Const_RotateSpeedLmt 22.5,故用22.5/45 if angle > Const_RotateSpeedLmt then angle:Reset(Const_RotateSpeedLmt) local isClockwise = IsRotateClockwise(curDir, targetDir) if not isClockwise then angle:Negative() headAngle = -headAngle end local dir = FP.V2.GetOffsetToAngle(angle, curDir) outDir:Reset(dir) else outDir:Reset(targetDir) headAngle = 0 end return headAngle end --不跟随镖车时显示镖车的范围 (只对自己的镖车) function private.ShowMyCartRange() local cartExpEntity = TownCartManager.MyCartEntity and TownCartManager.MyCartEntity.ExpEntity if cartExpEntity then cartExpEntity:PlayEffectByType(LuaConst.EffectType.CartRange) cartExpEntity:SetEffectPosByType(LuaConst.EffectType.CartRange,0,0,0) cartExpEntity:SetEffectScaleByType(LuaConst.EffectType.CartRange,Const_EscortCarLeaveDis,Const_EscortCarLeaveDis,1) EventSystem.Dispatch(EventID.GuildEscort_MyCartFollow, false) end EventSystem.Dispatch(EventID.UI_Auto_Tips, LuaConst.AutoType.FollowingCart) end -- 跟随时,停止范围展示 function private.StopMyCartRange() local cartExpEntity = TownCartManager.MyCartEntity and TownCartManager.MyCartEntity.ExpEntity if cartExpEntity then cartExpEntity:StopEffectByType(LuaConst.EffectType.CartRange) EventSystem.Dispatch(EventID.GuildEscort_MyCartFollow, true) EventSystem.Dispatch(EventID.UI_Auto_Tips, LuaConst.AutoType.FollowingCart) end end ---跟随相关代码 ↑↑↑ -- 获取相对某点的偏移量 function private.GetOffsetToForward(starPosX, starPosZ, dirX, dirZ, offsetX, offsetZ) local orx = dirZ * offsetX + dirX * offsetZ --偏移量-左右 local orz = -dirX * offsetX + dirZ * offsetZ --偏移量-前后 local result_x = starPosX + orx --结果x local result_z = starPosZ + orz --结果z return result_x,result_z end function TownCartManager.StopFollowNPC(entity, isNoTask) if entity == LogicUpdateManager._curEntity then local myacid = BattleDataGetter.GetAcID() if TownCartManager.FollowDic[myacid] then local followMsg = team_operate_pb.C2STeamFollowNpc() followMsg.isFollow = false NetManager.SendMessage(MessageEnums.MessageC2STeamFollowNpc,followMsg) end if isNoTask then if not TownCartManager.FollowDic[myacid] then private.StopMyCartRange() end TownCartManager.MyCartEntity = nil end end end function TownCartManager.IsFollowingNPC(entity) local acid = SyncMoveManager.GetAcIdOfEntity(entity) if acid then return TownCartManager.CurFollowStateDic[acid] == EnumFollowState.Follow end return false end function TownCartManager.AcidIsFollowingNPC(acid) local followState = TownCartManager.CurFollowStateDic[acid] return followState == EnumFollowState.Follow end -- 刷新镖车的名字 function private.RefreshCartName(entity, cartInfo, playerName) local nameIDSDic = cartInfo.isTeam and CartNameIDS.team or CartNameIDS.person local ids = cartInfo.robSuccessCount > 0 and nameIDSDic[1] or nameIDSDic[0] local name = string.FormatByIdsKey(ids,QualityColor[cartInfo.quality],playerName) NotSyncBattleSetter.RefreshEntityUIName(entity, name) private.ShowCartGuildInfo(cartInfo, entity) --增加国家标识 ExpSystemManager.ChangeEntityCountry(entity, cartInfo.ownerInfo.countryInfo.countryId, cartInfo.ownerInfo.countryInfo.countryJobId) end function private.OnCartInfoChange(msg) local cartUniqId = msg.npcUniqId local objectInfo = SyncMoveManager.TownObjectDic[cartUniqId] private.RefreshCartData(msg) if objectInfo then local cartEntity = objectInfo.entity local cartInfo = objectInfo.info.cartInfo local playerName = objectInfo.info.ownerName if cartEntity then -- 设置战斗标记 if msg.inBattle then --战斗中特效 cartEntity.ExpEntity:PlayEffectByType(LuaConst.EffectType.CartFighting) cartEntity.ExpEntity:SetEffectPosByType(LuaConst.EffectType.CartFighting, 0, 4.5, 0) else cartEntity.ExpEntity:StopEffectByType(LuaConst.EffectType.CartFighting) end -- 设置镖车名字 local nameIDSDic = cartInfo.isTeam and CartNameIDS.team or CartNameIDS.person local ids = msg.robSuccessCount > 0 and nameIDSDic[1] or nameIDSDic[0] -- 抢夺次数 robCount-抢夺总次数 local name = string.FormatByIdsKey(ids,QualityColor[cartInfo.quality],playerName) NotSyncBattleSetter.RefreshEntityUIName(cartEntity, name) private.ShowCartGuildInfo(cartInfo, cartEntity) end end end function private.OnCartRoleListChange(msg) local cartUniqId = msg.npcUniqId local roleList = msg.roleList local objectInfo = SyncMoveManager.TownObjectDic[cartUniqId] if objectInfo then --标记主视角的镖车 local myCartAcid = BattleDataGetter.GetAcID() for i,acid in ipairs(roleList) do if acid == myCartAcid then TownCartManager.MyCartEntity = objectInfo.entity TownCartManager.MyCartUniqid = cartUniqId end end end end -- 将镖车添加军团信息 function private.ShowCartGuildInfo(cartInfo, entity) local guildInfo = cartInfo.ownerInfo.guildShow if string.isNilOrEmpty(guildInfo.guildName) == false then local guildName = string.FormatByIdsKey("IDS_Escort_GuildColor",QualityColor[cartInfo.quality], guildInfo.guildName) EventSystem.Dispatch(EventID.UIBattle_Element_SetHeadUI, entity.ExpEntity.RenderEntity, EntityHeadUIModule.HeadUIType.Guild, CTL.Guild.GetFramePath(guildInfo.emblemFrame), guildInfo.emblemContent, guildName) end end -- 更新镖车信息 function private.RefreshCartData(msg) local count = #TownCartManager.CartInfoList for i = count, 1, -1 do local cartInfo = TownCartManager.CartInfoList[i] if cartInfo.info.uniqId == msg.npcUniqId then cartInfo.inBattle = msg.inBattle cartInfo.robCount = msg.robCount end end end function TownCartManager.TryGetCurSpeed(acid) if TownCartManager.CurFollowStateDic[acid] == EnumFollowState.Follow then return TownCartManager.FollowMoveInfo[acid].speed end return false end return TownCartManager