local FP = FP local FP_ZERO = FP.Const.ZERO local RetinueSystem = {} local private = {} --传入masterEntity 和 RetinueData,返回随从的标准区域列表(这个方法不需要传入随从Entity) function RetinueSystem.GetRetinueBornAreaListByData(masterEntity, retinueData) local list = {} local radius = FP.newV1(retinueData.BornAreaRadius) for i=1,#retinueData.BornPosInfo / 2 do local theta = FP.Math.Radian(FP.newV1(retinueData.BornPosInfo[i*2-1])) -- 极坐标表示随从位置的极角,以主人朝向为0度,逆时针的角度 local rho = FP.newV1(retinueData.BornPosInfo[i*2]) -- 用极坐标表示随从位置的极径 if theta and rho then local pos = FP.V2.RotateAroundOrigin(masterEntity.components.move.LogicRotateDir, theta):Mul(rho):Add(masterEntity:GetLogicPos()) --logging.error(LTAG.ERROR, "HYW : pos : ", pos, " radius : ", radius, " ", i) table.insert(list, {pos = pos, radius = radius}) end end return list end -- 传入随从Entity,获取该随从的标准区域列表(随从可能有多个标准区域,所以返回列表),可能返回nil function RetinueSystem.GetRetinueBornAreaList(entity) -- Retinue 表需要有一列,类型为float数组,参数含义每3个为一组,分别表示 极径、极角、半径 local list repeat local masterEntity = entity:GetMasterEntity() if not masterEntity then break end list = entity.components.record:GetRetinueBornAreaListRecord(masterEntity:GetLogicPos()) if list then break end local retinueData = DataSheetManager.RetinueData:GetDataByID(entity:GetCharacterID()) if retinueData then list = RetinueSystem.GetRetinueBornAreaListByData(masterEntity, retinueData) entity.components.record:AddRetinueBornAreaListRecord(list, masterEntity:GetLogicPos()) else logging.error(LTAG.ERROR, "HYW : 策划注意!没有配置随从数据! CharacterID : ", entity:GetCharacterID()) end until true return list end --返回随从的跟随位置,可能返回nil function RetinueSystem.GetRetinueFollowPos(entity) local retinueData = DataSheetManager.RetinueData:GetDataByID(entity:GetCharacterID()) if retinueData then local masterEntity = entity:GetMasterEntity() if masterEntity then local theta = FP.Math.Radian(FP.newV1(retinueData.FollowPosInfo[1])) -- 极坐标表示随从位置的极角,以主人朝向为0度,逆时针的角度 local rho = FP.newV1(retinueData.FollowPosInfo[2]) -- 用极坐标表示随从位置的极径 if theta and rho then return FP.V2.RotateAroundOrigin(masterEntity.components.move.LogicRotateDir, theta):Mul(rho):Add(masterEntity:GetLogicPos()) end end else logging.error(LTAG.ERROR, "HYW : 策划注意!没有配置随从数据! CharacterID : ", entity:GetCharacterID()) end end --返回出生区域中的一个随机位置, 传入主人单位和随从数据 function RetinueSystem.GetRandomPosInBornAreaByData(masterEntity, retinueData) if retinueData then local retinueAreaList = RetinueSystem.GetRetinueBornAreaListByData(masterEntity, retinueData) if retinueAreaList and #retinueAreaList > 0 then local rand = (#retinueAreaList == 1 and 1 or LogicRandom.GetIntegerValue(masterEntity, 1, #retinueAreaList, 434243548)) local retinueArea = retinueAreaList[rand] local randomPos = LogicRandom.GetRandomPointInCircle(masterEntity, retinueArea.radius, 434243549) randomPos:Add(retinueArea.pos) return randomPos end end end -- 传入随从单位,返回这个随从预期应该处于的位置,可能返回nil function RetinueSystem.GetRetinueExpectedPos(entity) local isInRetinueExpectedArea, isTooFar = RetinueSystem.IsInRetinueExpectedArea(entity) if not isInRetinueExpectedArea then local target = entity.components.target.Target if target then local bornAreaList = RetinueSystem.GetRetinueBornAreaList(entity) if bornAreaList and #bornAreaList > 0 then return RetinueSystem.GetRandomPosInBornAreaByData(entity:GetMasterEntity(), DataSheetManager.RetinueData:GetDataByID(entity:GetCharacterID())), true end else if entity.components.target.FollowTarget then local retinueData = DataSheetManager.RetinueData:GetDataByID(entity:GetCharacterID()) if isTooFar then if entity.components.target.ToFollowTargetDisSqr > retinueData.NoTargetConveyDistSqr then return RetinueSystem.GetRandomPosInBornAreaByData(entity:GetMasterEntity(), retinueData), true else local expectedPos = entity.components.target.FollowTarget:GetLogicPos() - entity:GetLogicPos() expectedPos:Normalize() expectedPos.x:Mul(FP.Math.Sqrt(retinueData.NoTargetMaxDistSqr)) expectedPos.z:Mul(FP.Math.Sqrt(retinueData.NoTargetMaxDistSqr)) expectedPos:Add(entity.components.target.FollowTarget:GetLogicPos()) return expectedPos end else local expectedPos = entity:GetLogicPos() - entity.components.target.FollowTarget:GetLogicPos() expectedPos:Normalize() expectedPos.x:Mul(FP.Math.Sqrt(retinueData.NoTargetMinDistSqr)) expectedPos.z:Mul(FP.Math.Sqrt(retinueData.NoTargetMinDistSqr)) expectedPos:Add(entity.components.target.FollowTarget:GetLogicPos()) return expectedPos end end end end end -- 传入随从单位,返回这个随从是否在预期区域 function RetinueSystem.IsInRetinueExpectedArea(entity) local retinueData = DataSheetManager.RetinueData:GetDataByID(entity:GetCharacterID()) local target = entity.components.target.Target if target then return entity.components.target.ToTargetDisSqr < retinueData.HasTargetConveyDistSqr, true else local toFollowTargetDisSqr = entity.components.target.ToFollowTargetDisSqr return toFollowTargetDisSqr > retinueData.NoTargetMinDistSqr and toFollowTargetDisSqr < retinueData.NoTargetMaxDistSqr , toFollowTargetDisSqr > retinueData.NoTargetMinDistSqr end end -- 主人传送后 ,随从也要传送(天地群雄会用到) function RetinueSystem.OnConvey(masterEntity, pos, forward) if masterEntity.retinueList then for i,retinue in ipairs(masterEntity.retinueList) do SystemManager.OnConvey(retinue, pos,forward) end end end return RetinueSystem