local ExpEntity = class("ExpEntity") --加载需要的模块 local ExpModelComponent = require "Battle/Expression/ExpEntity/Component/ExpModelComponent" local ExpAnimComponent = require "Battle/Expression/ExpEntity/Component/ExpAnimComponent" local ExpUIComponent = require "Battle/Expression/ExpEntity/Component/ExpUIComponent" local ExpDriveComponent = require "Battle/Expression/ExpEntity/Component/ExpDriveComponent" local ExpSoundComponent = require "Battle/Expression/ExpEntity/Component/ExpSoundComponent" local EventSystem = require('Event/EventSystem') local ExpBatchSystem = require("Battle.Expression.ExpBatchSystem") local EntityHeadUIModule = require("View/Battle/BattleEntityUI/EntityUIModule/EntityHeadUIModule") local EmptyModelPath = ConstAssetPathConfig.EmptyModelPath local FrozenMaterialPath = ConstAssetPathConfig.FrozenMaterialPath; local HeroTransparentShaderPath = ConstAssetPathConfig.HeroTransparentShaderPath; local TownCartManager = require "Battle/Logic/MainLoop/SyncMoveManager/TownCartManager" local ipairs = ipairs local pairs = pairs -- 临时的不剔除的怪物的组 local MonsterFeatureForceCullingModeDic = { [55] = LuaConst.EntityCullingMode.NoCulling, -- 马超的试炼关卡的马超boss } local LuaConst_SpecialBuffs_InSuperWeak = LuaConst.SpecialBuffs.InSuperWeak local ExpNormalHurtAnim = LuaConst.ExpHurtAnim.Hurt local ExpWeakHurtAnim = LuaConst.ExpHurtAnim.WeakHurt local HeroModel_VisualCost_PVP = 25 local PetModel_VisualCost_PVP = 15 local ForceAllEntityNeedCulling = false -- 设置为true来让所有实体参与剔除 local DEFAULT_MODEL_ID = 4 local DEFAULT_MAGIC_WEAPON_ID = 4 local WEAPON_HALO_PATH = ConstAssetPathConfig.WEAPON_HALO_PATH --彩金神兵铸魂天命 光轮 local WEAPON_HALO_WHEEL_PATH_PS_INSTANNCE = ConstAssetPathConfig.WEAPON_HALO_WHEEL_PATH_PS_INSTANNCE --光轮的主轮盘 local DEFAULT_MAGIC_WEAPON_PATH = ConstAssetPathConfig.DEFAULT_MAGIC_WEAPON_PATH local CONST_HEROMODELIDMAX = 1000 -- 主将的模型id最大值 local _selectedNpcEffect = nil local LuaConst=LuaConst local FP=FP local string=string local string_isNilOrEmpty=string.isNilOrEmpty --1:Dissolve,溶解,只有GPU小兵使用,C#设置,不支持Lua设置 local EMaterialType = LuaConst.EMaterialType --对应C#中材质状态的实际枚举值,GPUSkinning小兵使用 local EMaterialConvertedType = { FROZEN = 2, TRANSPARENT = 3, } local EModelPsEffectType = { All = 0, OnlyTown = 1, OnlyBattle = 2, } local EMaterialSetType = { None = 0, ReplaceShader = 1, --替换Shader ReplaceMaterial = 2, --替换材质 ChangeKeyword = 3 --修改keyword,Shader变体实现 } local WeaponHaloBallPos = { {{0,1}}, {{0,1},{0,-1}}, {{0,1},{-0.866,-0.5},{0.866,-0.5}}, {{0,1},{0,-1},{1,0},{-1,0}}, } local CONST_HALFMODELHIGHT = 1.2 -- 武将模型的一般身高 ExpEntity.ModelCtrlType_PVP = 1 ExpEntity.ModelCtrlType_Statue = 2 ExpEntity.ModelCtrlType_ZhuCheng = 3 ExpEntity.ModelCtrlType_SceneQuiz = 4 ExpEntity.ModelCtrlType_InBattle = 5 --[[ 初始化 --]] function ExpEntity:Init(entity, paramData) --数据 self.Entity = entity --组件 self.components = { model = ExpModelComponent:new(self), anim = ExpAnimComponent:new(), ui = ExpUIComponent:new(), drive = ExpDriveComponent:new(self), sound = ExpSoundComponent:new(self), } if entity._logicInitData.HorseModelData then self.needStandOnHorse = entity._logicInitData.HorseModelData.IsStandOnHorse end self._effectDict = {} self._countEffectCountDic = {} --key为effect(path),value为一个dic,这个dic的key为entityID,value为effect播放计数。 dic的计数总和 > 0表示effect播放,计数总和 <=0 表示effect停止 self._hasCreateModel = false --用来判断是否已创建了模型,防止重复调用c#层生成模型的代码 self._expTitleID = 0 self._visible = false -- 标记显隐 self._guildEscortQuality = 0 --小地图显示点类型 if paramData.BornItemID then local itemData = LevelItemManager.GetItemDataByID(paramData.BornItemID) self.ShowRedPointType = itemData.ShowRedPointType else self.ShowRedPointType = 0 end local isGroupMonster = entity.components.base.CurMonsterFeature.IsGroupBorn self.RenderEntity = self:CreateRenderEntity(entity, paramData) self:CreateModel(self.RenderEntity, isGroupMonster, paramData) self:CreatePetModel(entity) self:ApplyExpTrans() self:ApplyPetExpTrans() if isGroupMonster then-- 创建军团怪的额外renderentity+model self:CreateGroupMonsterRenderEntityModels(entity, paramData) end self.insertHurtAnimFrame = -20 self.IgnoreUIHpChange = false -- 忽略通用的HP变化导致的UI变化 self.components.drive:AfterInit() self:UpdateExpWeaponSoulInfo() ExpSystemManager.OnExpEntityInited(self) end function ExpEntity:CreateRenderEntity(entity, paramData) --与C#的表现层关联 local init = entity._logicInitData --目前只给需要点击的NPC生成Collider,其他的后面再添加LogicUpdateManager._entityDic local renderEntity = paramData.RenderEntity local layer = self.components.model.Layer local feature = entity.components.base.CurMonsterFeature if renderEntity == nil then local isPlayerSelf = init.IsPlayerSelf local masterEntity = entity:GetMasterEntity() local isMasterSelf = masterEntity and masterEntity._logicInitData.IsPlayerSelf and not entity.isIllusion -- 分身也要能被剔除 local visualPriority = feature.VisualPriority --1v1和3v3不做裁剪,因为这俩玩法对视野要求精确,并且人数少 if LevelManager.IsSolo() or LevelManager.IsSyncTeamPVP() or LevelManager.IsNoCullingLevel() then visualPriority = LuaConst.ESpecialVisualPriority.NEVER_CULL end if not GameAppInfo.IsVersionGreaterThan19000() then if entity:GetCharacterID() == 22 and entity:IsHero() then --吕布不裁剪,因为吕布会grab,如果裁剪会导致dummy状态下的吕布抓取的模型在吕布恢复可视后被连带放入RuntimeAssetPool中,然后可能被迅速地删除,导致stopGrab的时候丢失模型 --这只是一个临时解决方案 visualPriority = LuaConst.ESpecialVisualPriority.NEVER_CULL end end if paramData.ForceVisualPriority then -- 目前只有主城雕像、城池战雕像设置了 visualPriority = paramData.ForceVisualPriority end if visualPriority == LuaConst.ESpecialVisualPriority.ONLY_SAW_BY_FRIEND_NEVER_CULL then if LogicUpdateManager._curEntity and entity:GetCampID() == LogicUpdateManager._curEntity:GetCampID() then visualPriority = LuaConst.ESpecialVisualPriority.NEVER_CULL else self.dontShowVisualInst = true end end if GameAppInfo.IsVersionGreaterThan114000() then --某些模型剔除如果有问题,需要修改CullingMode为0,保留原来剔除的逻辑 local cullingMode if ForceAllEntityNeedCulling then cullingMode = LuaConst.EntityCullingMode.Normal elseif isPlayerSelf or isMasterSelf then cullingMode = LuaConst.EntityCullingMode.NoCulling elseif visualPriority == -1 then cullingMode = LuaConst.EntityCullingMode.PersistShow else cullingMode = LuaConst.EntityCullingMode.Normal end if MonsterFeatureForceCullingModeDic[feature.ID] then cullingMode = MonsterFeatureForceCullingModeDic[feature.ID] end renderEntity = AuxUtil.LoadRenderEntity(not LevelManager.IsNoBattleLevel(), layer, init.EntityCampID, visualPriority, init.EntityID, isPlayerSelf, cullingMode) --常驻显示的,暂时设置半径为20 if cullingMode == LuaConst.EntityCullingMode.PersistShow then renderEntity:SetCullingParams(20) end elseif GameAppInfo.IsVersionGreaterThan113000() then local needCulling = not (isPlayerSelf or isMasterSelf or visualPriority == -1) renderEntity = AuxUtil.LoadRenderEntity(not LevelManager.IsNoBattleLevel(), layer, init.EntityCampID, visualPriority, init.EntityID, isPlayerSelf, ForceAllEntityNeedCulling or needCulling) else renderEntity = AuxUtil.LoadRenderEntity(not LevelManager.IsNoBattleLevel(), layer, init.EntityCampID, visualPriority, init.EntityID, isPlayerSelf, isMasterSelf) end else renderEntity:ChangeEntityID(init.EntityID) self._hasCreateModel = true end --英雄和NPC类型的单位,不使用模拟重力来做Y轴的运动 local heroType = init.CharacterType == LuaConst.CharacterType.Hero renderEntity:InitEntityFlag(false, heroType or feature.IsBossLayer, feature.IsHitFlash) return renderEntity end function ExpEntity:CreatePetRenderEntity(entity) --与C#的表现层关联 local init = entity._logicInitData local layer = self.components.model.Layer local isMasterSelf = entity._logicInitData.IsPlayerSelf -- 防止被裁剪 local visualPriority = isMasterSelf and -1 or 40000 -- 要比主将低比怪物高或相等 local petRenderEntity local petEntityId = -init.EntityID-100 if GameAppInfo.IsVersionGreaterThan114000() then --某些模型剔除如果有问题,需要修改CullingMode为0,保留原来剔除的逻辑 local cullingMode if ForceAllEntityNeedCulling then cullingMode = LuaConst.EntityCullingMode.Normal elseif isMasterSelf then cullingMode = LuaConst.EntityCullingMode.NoCulling elseif visualPriority == -1 then cullingMode = LuaConst.EntityCullingMode.PersistShow else cullingMode = LuaConst.EntityCullingMode.Normal end petRenderEntity = AuxUtil.LoadRenderEntity(not LevelManager.IsNoBattleLevel(), layer, init.EntityCampID, visualPriority, petEntityId, false, cullingMode) --常驻显示的,暂时设置半径为20 if cullingMode == LuaConst.EntityCullingMode.PersistShow then petRenderEntity:SetCullingParams(20) end elseif GameAppInfo.IsVersionGreaterThan113000() then local needCulling = not (isMasterSelf or visualPriority == -1) petRenderEntity = AuxUtil.LoadRenderEntity(not LevelManager.IsNoBattleLevel(), layer, init.EntityCampID, visualPriority, petEntityId, false, ForceAllEntityNeedCulling or needCulling) else petRenderEntity = AuxUtil.LoadRenderEntity(not LevelManager.IsNoBattleLevel(), layer, init.EntityCampID, visualPriority, petEntityId, false, not isMasterSelf) end --使用模拟重力来做Y轴的运动 petRenderEntity:InitEntityFlag(false, false, false) return petRenderEntity end function ExpEntity:CreateModel(renderEntity ,forceEmptyModel, paramData) local comp_Base = self.Entity.components.base local logicInitData = self.Entity._logicInitData local modelData = self.Entity.components.replace:GetCurExpModelData() local characterData = comp_Base.CurCharacterData local pathId, combinePathId = 0, 0 local combinePath = modelData.CombinePath local withMagicWeapon = paramData.CharacterType == LuaConst.CharacterType.Hero or (paramData.CharacterType == LuaConst.CharacterType.Adjutant and paramData.MonsterID == paramData.AdjutantOriginID) or paramData.CharacterType == LuaConst.CharacterType.Illusion withMagicWeapon = withMagicWeapon or self.Entity.useDevelopOfHero local isPVPModel = self:IsPVPModel() local characterID, magicWeaponID, isActiveMagicWeapon, weaponBreak, heroBreakNums = logicInitData.CharacterID, logicInitData.MagicWeaponID, logicInitData.IsActiveMagicWeapon, logicInitData.WeaponBreak, logicInitData.HeroBreakNums local modelPath if string_isNilOrEmpty(combinePath) then modelPath, modelData, isPVPModel, characterID, magicWeaponID, isActiveMagicWeapon, weaponBreak, heroBreakNums = self:PreprocessModelData(modelData, isPVPModel, characterID, magicWeaponID, isActiveMagicWeapon, weaponBreak, heroBreakNums, logicInitData.isStatue) pathId = UTL.String.GetIdByString(modelPath) else combinePathId = UTL.String.GetIdByString(combinePath) end local equipmentID = modelData.EquipmentID local ctrlPathId,animAppendId = 0,0 if string_isNilOrEmpty(modelData.AnimAppend) then local ctrlPath = self:GetAnimatorCtrlPath(logicInitData.CharacterType,modelData,isPVPModel) ctrlPathId=UTL.String.GetIdByString(ctrlPath) else animAppendId = UTL.String.GetIdByString(modelData.AnimAppend) end local materialId=-1 if not string_isNilOrEmpty(modelData.material) then materialId=UTL.String.GetIdByString(modelData.material) end self.components.model.CurModelID = modelData.ID local visualCost = isPVPModel and HeroModel_VisualCost_PVP or modelData.VisualCost local modelScale = modelData.ModelScale if paramData.ExpModelScaleRate then modelScale = modelScale * paramData.ExpModelScaleRate end if paramData.RenderEntity == nil then -- 若paramData中已经存在RenderEntity,说明不需要再创建模型了 if forceEmptyModel then -- 军团怪写死逻辑:主体的model是个空模型 pathId = UTL.String.GetIdByString(EmptyModelPath) combinePathId = 0 renderEntity:SetModel(modelData.ID, pathId, combinePathId, modelScale, ctrlPathId, animAppendId, materialId, visualCost, modelData.DmgNumHeight, modelData.ModelSizeRate) else renderEntity:SetModel(modelData.ID, pathId, combinePathId, modelScale, ctrlPathId, animAppendId, materialId, visualCost, modelData.DmgNumHeight, modelData.ModelSizeRate) if renderEntity then if withMagicWeapon then self:CreateHeroWeapon(renderEntity, modelData.ID, characterID, magicWeaponID, isActiveMagicWeapon, weaponBreak, isPVPModel) end ExpEntity.CreateEquipPart(renderEntity, modelData.ID, equipmentID, isPVPModel) end end end if characterData.PreLoadModel then for i, modelID in ipairs(characterData.PreLoadModel) do if modelID == modelData.ID then logging.error(LTAG.ERROR, "[策划注意] : 怪物表中配置的预加载模型 ,填的和自己本身的模型一样了!怪物模型id = " ,characterData.ID) end local preloadData = DataSheetManager.MonsterModelData:GetDataByID(modelID) local animAppend = preloadData.AnimAppend local ctrlPath local preloadPath = self:GetModelPath(preloadData.Path, isPVPModel, false) if CTL.HotFix.CanAssetLoad(preloadPath) then if string_isNilOrEmpty(animAppend) then ctrlPath = self:GetAnimatorCtrlPath(logicInitData.CharacterType,preloadData,isPVPModel) end renderEntity:PreloadModel(preloadData.ID, preloadPath, preloadData.CombinePath, preloadData.ModelScale, ctrlPath, animAppend) end end end self:CreateDyeAppearance() if self.Entity:IsMainEntityOfPlayer() and self.Entity:IsPlayerSelf() then renderEntity:SetSoundListener(true) end self._isActiveState = true self._hasCreateModel = true self.hurtBlendRate = modelData.BlendRate self.canBlendHurtAnim = true self.withMagicWeapon = withMagicWeapon end --创建宠物。 宠物的状态机只有一个pvp的,可应用于到 高模、战斗模、pvp模 function ExpEntity:CreatePetModel(entity, petID, petStage) if not LevelManager.CurLevelCanUsePet() then return end local useMetaData = true if petID and petStage then useMetaData = false end local myPetId = entity:GetPetIDAndStage() if useMetaData and (myPetId == nil or myPetId == 0) then return end local petBattleData = useMetaData and entity.components.pet.petBattleData or DataSheetManager.PetBattleData:GetDataByID_Stage(petID, petStage) self.PetRenderEntity = self:CreatePetRenderEntity(entity) local isPVPModel = self:IsPVPModel() local modelData = DataSheetManager.MonsterModelData:GetDataByID(petBattleData.ModelID) local pathId, combinePathId = 0, 0 local modelPath = self:GetModelPath(modelData.Path, isPVPModel) if CTL.HotFix.CanAssetLoad(modelPath) == false then --更换成刘备的modelData modelData = DataSheetManager.MonsterModelData:GetDataByID(DEFAULT_MODEL_ID) modelPath = self:GetModelPath(modelData.Path, isPVPModel) end pathId = UTL.String.GetIdByString(modelPath) local ctrlPathId,animAppendId = 0,0 local ctrlPath = self:GetAnimatorCtrlPath(LuaConst.CharacterType.Monster, modelData, true) -- 宠物的动画状态机一定是用pvp的 ctrlPathId=UTL.String.GetIdByString(ctrlPath) local materialId=-1 if not string_isNilOrEmpty(modelData.material) then materialId=UTL.String.GetIdByString(modelData.material) end local visualCost = isPVPModel and PetModel_VisualCost_PVP or modelData.VisualCost local modelScale = modelData.ModelScale self.PetRenderEntity:SetModel(modelData.ID, pathId, combinePathId, modelScale, ctrlPathId, animAppendId, materialId, visualCost, modelData.DmgNumHeight, modelData.ModelSizeRate) self.petModelData = modelData end -- 典藏幻色 function ExpEntity:CreateDyeAppearance() if not self.RenderEntity then return end if self.Entity.isMonster or self.Entity.isNpc then return end local partList = self.Entity._logicInitData.DyeList if partList == nil or #partList == 0 then return end local mode = self:IsPVPModel() and 0 or 1 --mode:0=PVP模 1=战斗模 2=展示模 CTL.DyeAppearance.SetModelDye(self.RenderEntity, self.Entity._logicInitData.HeroAppearanceID, partList, mode) end function ExpEntity:UpdateExpWeaponSoulInfo() if not self.Entity:IsHero() then return end local logicWeaponSoulInfo = self.Entity._logicInitData.WeaponSoulInfo if not logicWeaponSoulInfo or not logicWeaponSoulInfo.isActive then if self.expWeaponSoulInfo then self.expWeaponSoulInfo = nil end return end local forgeSoulSkill = DataSheetManager.MagicWeaponForgeSoulData:GetDataByMagicWeaponID(self.Entity._logicInitData.CharacterID).ForgeSoulSkill if not self.expWeaponSoulInfo then self.expWeaponSoulInfo = {} end table.clear(self.expWeaponSoulInfo) for _, skillId in ipairs(forgeSoulSkill) do for _, v in ipairs(logicWeaponSoulInfo.skillSceneInfo) do if skillId == v.skillId then table.insert(self.expWeaponSoulInfo, {skillId = v.skillId, skillLv = v.level}) end end end end function ExpEntity:CreateWeaponHalo() if not self.expWeaponSoulInfo then return end if self.RenderEntity:IsDummy() then return end if not CTL.HotFix.CanAssetLoad(WEAPON_HALO_PATH) then return end local haloParent = self.RenderEntity:GetActorSlotNode(0) self.weaponHaloObj = TK2API.GetInstance(WEAPON_HALO_PATH, haloParent) --轮盘 local PlateParent = self.weaponHaloObj.transform:Find("Plate") self.haloPlatEffectId = AuxUtil.PlayDynamicObject(WEAPON_HALO_WHEEL_PATH_PS_INSTANNCE, -1, PlateParent, LuaConst.Layer.Hero_Self) if GameAppInfo.IsVersionGreaterThan119000() then AuxUtil.SetDynamicObjectIsPlayerSelf(self.haloPlatEffectId, self.Entity._logicInitData.IsPlayerSelf) end --加载光球 self:CreateWeaponHaloLightBallEffect() end function ExpEntity:CreateWeaponHaloLightBallEffect() if not self.weaponHaloObj then -- 如果被剔除后,则不需要显示了 return end self.weaponHaloLightBallEffect = {} local lightBallParent = self.weaponHaloObj.transform:Find("LightBall") local num = 0 for _, v in ipairs(self.expWeaponSoulInfo) do if v.skillLv > 0 then num = num + 1 local cfg = DataSheetManager.MagicWeaponForgeSoulEffect:GetDataByMagicWeaponForgeSoulSkillLevel(v.skillLv) local effectId = AuxUtil.PlayDynamicObject(cfg.SkillEffect2, -1, lightBallParent:GetChild(num-1), LuaConst.Layer.Hero_Self) if GameAppInfo.IsVersionGreaterThan119000() then AuxUtil.SetDynamicObjectIsPlayerSelf(effectId, self.Entity._logicInitData.IsPlayerSelf) end table.insert(self.weaponHaloLightBallEffect, effectId) end end local pos = WeaponHaloBallPos[num] for i = 1, num do lightBallParent:GetChild(i-1):SetLocalPosition(pos[i][1], pos[i][2], 0) end end function ExpEntity:DisposeWeaponHalo() self:DisposeWeaponHaloLightBallEffect() if self.haloPlatEffectId then AuxUtil.StopDynamicObject(self.haloPlatEffectId) self.haloPlatEffectId = nil end if self.weaponHaloObj then TK2API.ReturnInstance(WEAPON_HALO_PATH, self.weaponHaloObj) self.weaponHaloObj = nil end end function ExpEntity:DisposeWeaponHaloLightBallEffect() if self.weaponHaloLightBallEffect then for _, value in ipairs(self.weaponHaloLightBallEffect) do AuxUtil.StopDynamicObject(value) end self.weaponHaloLightBallEffect = nil end end function ExpEntity:ShowWeaponHaloLightBallEffect(isShow) if isShow then if not self.weaponHaloLightBallEffect then self:CreateWeaponHaloLightBallEffect() end else self:DisposeWeaponHaloLightBallEffect() end end -- 创建特殊的军团怪的多个model,同时显示 function ExpEntity:CreateGroupMonsterRenderEntityModels(entity, paramData) local move = entity.components.move local mainposX,mainposZ = FP.tonumberV2(move.LogicPos) local posAndDirList = paramData.GroupMonsterModelPosAndDir self.SubRenderEntityList = {} -- 只有军团怪才会有额外的renderentity self.SubRenderEntityOffsetList = {}-- 子模型相对与主模型的偏移 成对出现的 for i =1,#posAndDirList do local transinfo = posAndDirList[i] local posX,posZ = FP.tonumberV2(transinfo.position) local dirX,dirZ = FP.tonumberV2(transinfo.forward) local renderEntity = self:CreateRenderEntity(entity, paramData) renderEntity:SetTrans(posX, posZ, dirX, dirZ) self:CreateModel(renderEntity, false, paramData) table.insert(self.SubRenderEntityList ,renderEntity) table.insert(self.SubRenderEntityOffsetList ,posX - mainposX) table.insert(self.SubRenderEntityOffsetList ,posZ - mainposZ) end end function ExpEntity:GetSubRenderEntityOffsetList() return self.SubRenderEntityOffsetList end function ExpEntity:IsPVPModel() return LevelManager.IsNeedUsePVPModelLevel() and (self.Entity:IsHero() or self.Entity:IsAdjutant() or self.Entity:IsIllusion() or self.Entity.useDevelopOfHero) and not (self.Entity._logicInitData.isStatue) end function ExpEntity:GetModelPath(modelPath, isPVPModel, isStatue) local tempPath=modelPath --是否使用PVP定制模型 if isPVPModel and not isStatue then local dir, actorDir,prefab = string.match(modelPath, "(%S*)/(%S*)/(%S*)") local newPrefab = string.gsub(prefab, actorDir ,actorDir.."_PVP") tempPath = string.gsub(modelPath, prefab ,newPrefab) elseif isStatue then local modelPathWithOutEnd = string.match(modelPath, "^(.*)_R[0-9]") if modelPathWithOutEnd then tempPath = modelPathWithOutEnd .. "_Statue.prefab" else tempPath = string.gsub(tempPath, "T[0-9]+", "") tempPath = string.gsub(tempPath, ".prefab", "_Statue.prefab") end end return tempPath end --挂接一个ExpEntity到自身 function ExpEntity:AppendExpEntity(expEntity, node, offsetX, offsetY, offsetZ, angleX, angleY, angleZ) local handle = -1 if self.RenderEntity then if expEntity.RenderEntity then handle = self.RenderEntity:AppendRenderEntity(expEntity.RenderEntity, node, offsetX, offsetY, offsetZ, angleX, angleY, angleZ) end end return handle end --以handle解除ExpEntity的挂接(handle是AppendRenderEntity的返回值) function ExpEntity:CancelAppendRenderEntityByHandle(handle) if not self.RenderEntity then return end self.RenderEntity:RemoveAppendRenderEntityByHandle(handle) end function ExpEntity:CancelAppendExpEntity(expEntity) if not self.RenderEntity then return end self.RenderEntity:CancelAppendRenderEntity(expEntity.RenderEntity) end -- 创建武将的神兵 function ExpEntity:CreateHeroWeapon(renderEntity, modelID, characterID, magicWeaponID, isActiveMagicWeapon, weaponBreak, isPVPModel) if self.Entity:IsHero() or self.Entity:IsAdjutant() or self.Entity:IsIllusion() or self.Entity._logicInitData.isStatue or self.Entity.useDevelopOfHero then local battleModelId, effectLevel = self:GetWeaponIdAndLevel(characterID, magicWeaponID, isActiveMagicWeapon, weaponBreak) self:WearHeroMagicWeapon(renderEntity, modelID, battleModelId, isPVPModel) end end -- 武将穿戴神兵 magicWeaponModelID --神兵的模型ID function ExpEntity:WearHeroMagicWeapon(renderEntity, modelID, magicWeaponModelID, isPVPModel) if magicWeaponModelID == nil then return end local equipData = DataSheetManager.MagicWeaponModel:GetDataByID(magicWeaponModelID) if equipData == nil then return end for i, v in ipairs(equipData.ModelPart_Table) do local slotInt = ExpSystemManager.GetSlotInt(v.ModelSlotStr, v.SlotType, false) if slotInt then local weaponPath = v.Prefeb weaponPath = isPVPModel and string.gsub(weaponPath, "_Weapon", "_PVP_Weapon") or weaponPath local pathId = UTL.String.GetIdByString(weaponPath) if self.Entity._logicInitData.isStatue then -- 雕像换prefab local weaponPathWithOutEnd = string.match(weaponPath, "^(.*)_R[0-9]") local weaponPathStatue = nil if weaponPathWithOutEnd then weaponPathStatue = weaponPathWithOutEnd .."_Statue.prefab" else weaponPath = string.gsub(weaponPath, "T[0-9]+" , "") weaponPathStatue = string.gsub(weaponPath, ".prefab", "_Statue.prefab") end pathId = UTL.String.GetIdByString(weaponPathStatue) end --资源保护的代码应该放到最后 if CTL.HotFix.CanAssetLoad(weaponPath) == false then weaponPath = DEFAULT_MAGIC_WEAPON_PATH pathId = UTL.String.GetIdByString(weaponPath) end local animCtrlPath = "" if (isPVPModel or self.Entity._logicInitData.isStatue) and v.HasAnim then animCtrlPath = string.match(weaponPath, "^(.*)_R[0-9]") if animCtrlPath then animCtrlPath = animCtrlPath ..".controller" else animCtrlPath = string.gsub(weaponPath, ".prefab", ".controller") end else if LevelManager.IsNoBattleLevel() and v.HasAnimCity then animCtrlPath = string.match(weaponPath, "^(.*)_R[0-9]") if animCtrlPath then animCtrlPath = animCtrlPath .."_ZhuCheng.controller" else animCtrlPath = string.gsub(weaponPath, ".prefab", "_ZhuCheng.controller") end elseif v.HasAnim then animCtrlPath = string.match(weaponPath, "^(.*)_R[0-9]") if animCtrlPath then animCtrlPath = animCtrlPath ..".controller" else animCtrlPath = string.gsub(weaponPath, ".prefab", ".controller") end end end local animCtrlPathId = UTL.String.GetIdByString(animCtrlPath) renderEntity:SetEquipOrWeapon(modelID, pathId, slotInt, animCtrlPathId, false, true) else logging.error(LTAG.ERROR, "HYW : 未知的SlotType : ", v.SlotType, " ID (MagicWeaponModel表) : ", magicWeaponModelID) end end end -- 创建模型的普通准备 function ExpEntity.CreateEquipPart(renderEntity, modelID, equipID, isPVPModel) local equipData = equipID>0 and DataSheetManager.EquipPartsData:GetDataByID(equipID) or nil if not equipData then return end for i,v in ipairs(equipData.EquipPart_Table) do local slotInt = ExpSystemManager.GetEquipPartSlotInt(v) if slotInt then local animCtrlPath = "" if isPVPModel and v.HasAnim then animCtrlPath = string.gsub(v.Prefeb,".prefab" ,".controller") animCtrlPath = string.gsub(animCtrlPath, "_Weapon", "_PVP_Weapon") else if LevelManager.IsNoBattleLevel() and v.HasAnimCity then animCtrlPath = string.gsub(v.Prefeb,".prefab" ,"_ZhuCheng.controller") elseif v.HasAnim then animCtrlPath = string.gsub(v.Prefeb,".prefab" ,".controller") end end local animCtrlPathId = UTL.String.GetIdByString(animCtrlPath) local weaponPath = isPVPModel and string.gsub(v.Prefeb,"_Weapon" ,"_PVP_Weapon") or v.Prefeb local pathId = UTL.String.GetIdByString(weaponPath) renderEntity:SetEquipOrWeapon(modelID, pathId, slotInt, animCtrlPathId, v.IsParent, false) else logging.error(LTAG.ERROR, "HYW : 未知的SlotType : ", v.SlotType, " equipID (EquipPartsData表) : ", equipID) end end end --防止资源未下载,预处理资源参数 function ExpEntity:PreprocessModelData(modelData, isPVPModel, characterID, magicWeaponID, isActiveMagicWeapon, weaponBreak, heroBreakNums, isStatue) local modelPath = self:GetModelPath(modelData.Path, isPVPModel, isStatue) if CTL.HotFix.CanAssetLoad(modelPath) == false then --更换成刘备的modelData modelData = DataSheetManager.MonsterModelData:GetDataByID(DEFAULT_MODEL_ID) isPVPModel = false characterID = DEFAULT_MODEL_ID magicWeaponID = DEFAULT_MAGIC_WEAPON_ID isActiveMagicWeapon = false weaponBreak = 0 heroBreakNums = 0 modelPath = modelData.Path end return modelPath, modelData, isPVPModel, characterID, magicWeaponID, isActiveMagicWeapon, weaponBreak, heroBreakNums end --武将换神兵 function ExpEntity:ChangeHeroMagicWeapon() if not self.RenderEntity then return end local opModelID = self.Entity.components.replace:GetHeroOriginalModelID() -- 需要去掉神兵的模型id (如果目前处于小变身状态,则不能换神兵 。武将换了时装后,要替换武将时装的modelID) if self.components.model.CurModelID ~= opModelID then logging.log(LTAG.LOG, "gws:当前处于小变身状态,不能换神兵时装") return end local isPVPModel = self:IsPVPModel() local modelData = self.Entity.components.replace:GetCurExpModelData() local logicInitData = self.Entity._logicInitData local characterID, magicWeaponID, isActiveMagicWeapon, weaponBreak, heroBreakNums = logicInitData.CharacterID, logicInitData.MagicWeaponID, logicInitData.IsActiveMagicWeapon, logicInitData.WeaponBreak, logicInitData.HeroBreakNums local modelPath if self.Entity:IsHero() or self.Entity:IsAdjutant() or self.Entity:IsIllusion() or self.Entity.useDevelopOfHero then --先移除 self.RenderEntity:RemoveAllWeapon() --再添加 modelPath, modelData, isPVPModel, characterID, magicWeaponID, isActiveMagicWeapon, weaponBreak, heroBreakNums = self:PreprocessModelData(modelData, isPVPModel, characterID, magicWeaponID, isActiveMagicWeapon, weaponBreak, heroBreakNums) self:CreateHeroWeapon(self.RenderEntity, opModelID, characterID, magicWeaponID, isActiveMagicWeapon, weaponBreak, isPVPModel) -- 武器特效 local heroId = self.Entity:GetCharacterID() self:ChangeWeaponEffect(heroId, magicWeaponID, isActiveMagicWeapon, weaponBreak) end if self.Entity.components.buff:CheckHasBuffState(LuaConst.SpecialBuffs.InRiding) then if SyncMoveManager.IsFollowingNPC(self.Entity) then local animIntKey= UTL.String.GetIdByString(self.ExpHorseAnimID) self.RenderEntity:PlayAnimation(animIntKey ,false ,false, 0) end end end --改变神兵特效 function ExpEntity:ChangeMagicWeaponEffect() local opModelData = self.Entity.components.replace:GetCurExpModelData() if self.components.model.CurModelID ~= opModelData.ID then logging.log(LTAG.LOG, "gws:当前处于特显状态,不能换神兵特效") return end local logicInitData = self.Entity._logicInitData local heroId = self.Entity:GetCharacterID() self:ChangeWeaponEffect(heroId, logicInitData.MagicWeaponID, logicInitData.IsActiveMagicWeapon, logicInitData.WeaponBreak) end --解除作为单位父级存在的装备(通常是马) function ExpEntity:RemoveParentEquipment(unslotAnimsRandomIndex) if not self.RenderEntity then return end local CurModelData = self.Entity.components.replace:GetCurExpModelData() local equipData = DataSheetManager.EquipPartsData:GetDataByID(CurModelData.EquipmentID) local unslotAnimCount = 0 for i,equipPart in ipairs(equipData.EquipPart_Table) do if equipPart.IsParent then local slotInt = ExpSystemManager.GetEquipPartSlotInt(equipPart) if slotInt then local unslotAnim = "" if equipPart.UnslotAnims and #equipPart.UnslotAnims > 0 then --unslotAnim = equipPart.UnslotAnims[LogicRandom.GetIntegerValue(nil, 1, #equipPart.UnslotAnims ,2001)] --old 由视图层调用Random,会导致单机校验不一致 --new↓ 由逻辑层传随机数进来, 防止单机校验不一致 if unslotAnimsRandomIndex then unslotAnimCount = unslotAnimCount + 1 if unslotAnimsRandomIndex[unslotAnimCount] then unslotAnim = equipPart.UnslotAnims[unslotAnimsRandomIndex[unslotAnimCount]] else logging.error(LTAG.ERROR, "HYW : unslotAnimsRandomIndex[unslotAnimCount] nil Error! @ExpEntity:RemoveParentEquipment unslotAnimCount : ", unslotAnimCount) end else logging.error(LTAG.ERROR, "HYW : unslotAnimsRandomIndex nil Error! @ExpEntity:RemoveParentEquipment") end --new↑ end self.RenderEntity:RemoveEquipOrWeapon(CurModelData.ID, equipPart.Prefeb, slotInt, unslotAnim, false) end end end end function ExpEntity:PreLoadPsModel(isSyncLevel) if self.RenderEntity then local modelID = self.Entity._logicInitData._characterData.ModelID local preloadData = DataSheetManager.MonsterModelData:GetDataByID(modelID) if preloadData then local disableTimeLine = isSyncLevel or (not SystemManager.ShoulPlayMusouShow(self.Entity)) -- 不播小黑屋 self.RenderEntity:PreLoadPSConfig(preloadData.PreloadID, disableTimeLine) return true end end return false end function ExpEntity:PreLoadActorModel() if self.RenderEntity then self.RenderEntity:StartAsyncPreloadActorModel() return true end return false end function ExpEntity:ClearRenderEntity(needDissolve) if self.RenderEntity then self:ClearEffect() self:StopHeroBreakEffect() ExpBatchSystem.RemoveEntityAllBatchEffect(self.RenderEntity) self:DisposeRenderEntity(self.RenderEntity, needDissolve) self.RenderEntity = nil end if self.SubRenderEntityList then for i,renderEntity in ipairs(self.SubRenderEntityList) do self:DisposeRenderEntity(renderEntity, needDissolve) self.SubRenderEntityList[i] = nil end self.SubRenderEntityList = nil end if self.PetRenderEntity then self:StopPetModelEffect() ExpBatchSystem.RemoveEntityAllBatchEffect(self.PetRenderEntity) self:DisposeRenderEntity(self.PetRenderEntity, needDissolve) ExpBatchSystem.RemovePetRenderEntity(self.PetRenderEntity) self.PetRenderEntity = nil end self:DisposeWeaponHalo() ExpBatchSystem.RemoveEntity(self.Entity) end function ExpEntity:SetUseG(value) if not self.RenderEntity then return end self.RenderEntity.UseG = value end function ExpEntity:ForceVisual() if self.RenderEntity then self.RenderEntity:ForceVisual() end end function ExpEntity:SetAnimInvalid() self.animInvalid = true end function ExpEntity.GetCtrlPath(modelData, modelType, index) local modelPath local pattern if string.isNilOrEmpty(modelData.CombinePath) then modelPath = modelData.Path pattern = ".prefab" else modelPath = string.gsub(modelData.CombinePath, "/CombineConfig", "") pattern = ".asset" end if string_isNilOrEmpty(modelPath) then return "" end if modelType == ExpEntity.ModelCtrlType_PVP then if string_isNilOrEmpty(modelData.AnimCtlID) == false then return string.match(modelPath, "^(.*)/") .. "/" .. modelData.AnimCtlID .. "_PVP.controller" else return string.gsub(modelPath, pattern, "_PVP.controller") end end if modelType == ExpEntity.ModelCtrlType_Statue then if string_isNilOrEmpty(modelData.AnimCtlID) == false then return string.match(modelPath, "^(.*)/") .. "/" .. modelData.AnimCtlID .. ".controller" end end if modelType == ExpEntity.ModelCtrlType_ZhuCheng then if string_isNilOrEmpty(modelData.AnimCtlID) == false then return string.match(modelPath, "^(.*)/") .. "/" .. modelData.AnimCtlID .. "_ZhuCheng.controller" else return string.gsub(modelPath, pattern, "_ZhuCheng.controller") end end if modelType == ExpEntity.ModelCtrlType_SceneQuiz then if string_isNilOrEmpty(modelData.AnimCtlPath) == false then return modelData.AnimCtlPath end local animCtlID = nil if index == nil or index == 1 then animCtlID = modelData.AnimCtlID elseif index == 2 then animCtlID = modelData.AnimCtlID2 end if animCtlID and animCtlID ~= "" then return string.match(modelPath, "^(.*)/") .. "/" .. animCtlID .. ".controller" end end if modelType == ExpEntity.ModelCtrlType_InBattle then if string_isNilOrEmpty(modelData.AnimCtlPath) == false then return modelData.AnimCtlPath end local animCtlID = nil if index == nil or index == 1 then animCtlID = modelData.AnimCtlID elseif index == 2 then animCtlID = modelData.AnimCtlID2 end if animCtlID and animCtlID ~= "" then return string.match(modelPath, "^(.*)/") .. "/" .. animCtlID .. ".controller" end end return "" end function ExpEntity:GetAnimatorCtrlPath(characterType, modelData, isPVPModel, index) local animCtrlPath = "" if isPVPModel then animCtrlPath = ExpEntity.GetCtrlPath(modelData, ExpEntity.ModelCtrlType_PVP, index) elseif LevelManager.IsNoBattleLevel() and (characterType == LuaConst.CharacterType.Hero or characterType == LuaConst.CharacterType.Adjutant) then if self.Entity._logicInitData.isStatue then -- 雕像用战斗动画 animCtrlPath = ExpEntity.GetCtrlPath(modelData, ExpEntity.ModelCtrlType_Statue, index) elseif LevelManager.IsSceneQuizTown() then animCtrlPath = ExpEntity.GetCtrlPath(modelData, ExpEntity.ModelCtrlType_SceneQuiz, index) else animCtrlPath = ExpEntity.GetCtrlPath(modelData, ExpEntity.ModelCtrlType_ZhuCheng, index) end else animCtrlPath = ExpEntity.GetCtrlPath(modelData, ExpEntity.ModelCtrlType_InBattle, index) end return animCtrlPath end function ExpEntity:ClearEffect() for type, id in pairs(self._effectDict) do self:StopEffectByType(type) end end function ExpEntity:ChangeWeaponEffect(heroId, weaponId, isActiveMagicWeapon,weaponBreak) if LevelManager.IsMassivePvPLevel() then return end if not self.RenderEntity then return end if weaponBreak and weaponBreak > 0 or isActiveMagicWeapon then local opModelID = self.Entity.components.replace:GetHeroOriginalModelID() local battleModelId, effectLevel = self:GetWeaponIdAndLevel(heroId, weaponId, isActiveMagicWeapon, weaponBreak) if battleModelId then local weaponModelData = DataSheetManager.MagicWeaponModel:GetDataByID(battleModelId) if weaponModelData then for i,v in ipairs(weaponModelData.ModelPart_Table) do local slotInt = ExpSystemManager.GetSlotInt(v.ModelSlotStr, v.SlotType, false) self.RenderEntity:ChangeWeaponEffect(opModelID, slotInt, v.MagicWeaponInitialShowEffect[effectLevel]) end end end end end function ExpEntity:GetWeaponIdAndLevel(heroId, weaponId, isActiveMagicWeapon, weaponBreak) local battleModelId = nil local effectLevel = nil local weaponData = nil ---这里weaponData是null是正常的 变身后不需要加载神兵 if isActiveMagicWeapon then if weaponId and weaponId > 0 then weaponData = DataSheetManager.MagicWeaponStar:GetDataByMagicWeaponID_Star(weaponId, weaponBreak) if weaponData then effectLevel = weaponData.EffectLevel end end else local isSuccess isSuccess, weaponData = DataSheetManager.MagicWeaponData:TryGetDataByMagicWeaponID(heroId) end if weaponData then local isPVPModel = self:IsPVPModel() if (not isPVPModel) and LevelManager.IsNoBattleLevel() then battleModelId = weaponData.HomeModel else battleModelId = weaponData.BattleModel end if self.Entity._logicInitData.isStatue and weaponData.StatueModel > 0 then -- 有雕像优先用雕像的数据,如果没有配置则用其他的 battleModelId = weaponData.StatueModel end end return battleModelId, effectLevel end -- 这个方法是取巧了。RenderEntity无任何可停武器特效的接口,但VisualRenderEntity中的ChangeWeaponEffect会停止旧的武器特效。 function ExpEntity:StopWeaponEffect(heroId, weaponId, isActiveMagicWeapon,weaponBreak) if LevelManager.IsMassivePvPLevel() then return end if not self.RenderEntity then return end if weaponBreak and weaponBreak > 0 or isActiveMagicWeapon then local opModelID = self.Entity.components.replace:GetHeroOriginalModelID() local battleModelId, effectLevel = self:GetWeaponIdAndLevel(heroId, weaponId, isActiveMagicWeapon, weaponBreak) if battleModelId then local weaponModelData = DataSheetManager.MagicWeaponModel:GetDataByID(battleModelId) if weaponModelData then for i,v in ipairs(weaponModelData.ModelPart_Table) do local slotInt = ExpSystemManager.GetSlotInt(v.ModelSlotStr, v.SlotType, false) self.RenderEntity:ChangeWeaponEffect(opModelID, slotInt, "") -- 传空则停止了特效 end end end end end function ExpEntity:PlayHeroBreakEffect(heroId, heroBreakNums) if LevelManager.IsMassivePvPLevel() then return end self:StopHeroBreakEffect() if not heroBreakNums or heroBreakNums <= 0 then return end local isSuccess, starData = DataSheetManager.HeroStar:TryGetDataByHeroID_Star(heroId, heroBreakNums) if isSuccess then local starEffectPath = starData.HeroStarShowEffect if not string.isNilOrEmpty(starEffectPath) then self._breakEffect = SystemManager.PlayPsEffect(starEffectPath, self.Entity) end end end -- 播放当前模型的常驻特效 function ExpEntity:PlayCurModelEffect(modelData) if LevelManager.IsMassivePvPLevel() then return end if self._curModelEffect then AuxUtil.StopPsEffect(self._curModelEffect) end if not modelData then modelData = self.Entity.components.replace:GetCurExpModelData() end local effect = modelData.ModelPsEffect if not string.isNilOrEmpty(effect) then local canShow = false if modelData.ModelPsEffectType == EModelPsEffectType.All then canShow = true elseif modelData.ModelPsEffectType == EModelPsEffectType.OnlyTown then canShow = LevelManager.IsNoBattleLevel() elseif modelData.ModelPsEffectType == EModelPsEffectType.OnlyBattle then canShow = not LevelManager.IsNoBattleLevel() end if canShow then self._curModelEffect = SystemManager.ShowPSEffect(self.Entity, effect) end end end -- 播放当前pet模型的常驻特效 function ExpEntity:PlayPetModelEffect(modelData) if self._curPetModelEffect then self:StopPetModelEffect() end local effect = modelData.ModelPsEffect if not string.isNilOrEmpty(effect) then local effectId=UTL.String.GetIdByString(effect) self._curPetModelEffect = self.PetRenderEntity:PlayEffect(effectId, -1, false, 1, self.components.model.Layer, 1 ,true, nil) self.PetRenderEntity:RecordActorPsEffect(effectId, -1, false, 1, self.components.model.Layer, self._curPetModelEffect) end end -- 停止当前模型的常驻特效 function ExpEntity:StopCurModelEffect() if self._curModelEffect then AuxUtil.StopPsEffect(self._curModelEffect) self._curModelEffect = nil end end -- 停止当前模型的常驻特效 function ExpEntity:StopPetModelEffect() if self._curPetModelEffect then AuxUtil.StopPsEffect(self._curPetModelEffect) self._curPetModelEffect = nil end end -- 播放当前character的光效 function ExpEntity:PlayHeroLightEffect(lightEffectIDs, isShow) if lightEffectIDs then if LevelManager.IsShowHeroLightEffect() then -- 有的关卡不能显示 for _,lightEffectID in ipairs(lightEffectIDs) do SystemManager.ShowOrHideLightEffect(self.Entity, lightEffectID, isShow) -- 这个方法会先停止之前播放的光效,再播放新光效 end end end end function ExpEntity:ReplayAllBuffEffect() for i,v in ipairs(self.Entity.components.buff.CurBuffObjectList) do if v:GetBuffLayer() > 0 then v:ReplayBuffEffect() end end end function ExpEntity:StopHeroBreakEffect() if self._breakEffect then AuxUtil.StopPsEffect(self._breakEffect) self._breakEffect = nil end end function ExpEntity:SetKeepFallDown(value) self.RenderEntity.KeepFallDown = value end function ExpEntity:PlayEffectByType(type) if self.RenderEntity then local _id = nil if type == LuaConst.EffectType.BeingSelected then if _selectedNpcEffect == nil then _id = AuxUtil.PlayDynamicObject(ConstAssetPathConfig.AssetPath177, -1, self.RenderEntity.Transform, self.components.model.Layer) _selectedNpcEffect = _id end elseif type == LuaConst.EffectType.TeamLevelUp then _id = AuxUtil.PlayDynamicObject(ConstAssetPathConfig.AssetPath178, 2, self.RenderEntity.Transform, self.components.model.Layer) elseif type == LuaConst.EffectType.OtherLanguageTeamLevelUp then _id = AuxUtil.PlayDynamicObject(ConstAssetPathConfig.AssetPath179, 2, self.RenderEntity.Transform, self.components.model.Layer) elseif type == LuaConst.EffectType.TaskSign then _id = AuxUtil.PlayDynamicObject(ConstAssetPathConfig.AssetPath180, -1, self.RenderEntity.Transform, self.components.model.Layer) elseif type == LuaConst.EffectType.SkillRange or type == LuaConst.EffectType.StaticSkillRange then if self._effectDict[type] then return end _id = AuxUtil.PlayDynamicObject(ConstAssetPathConfig.AssetPath181, 9999, self.RenderEntity.Transform, self.components.model.Layer) elseif type == LuaConst.EffectType.SkillDirCircle then if self._effectDict[type] then return end _id = AuxUtil.PlayDynamicObject(ConstAssetPathConfig.AssetPath182, 9999, self.RenderEntity.Transform, self.components.model.Layer) elseif type == LuaConst.EffectType.SkillDirArrow then if self._effectDict[type] then return end _id = AuxUtil.PlayDynamicObject(ConstAssetPathConfig.AssetPath183, 9999, self.RenderEntity.Transform, self.components.model.Layer) elseif type == LuaConst.EffectType.SkillDirRect then if self._effectDict[type] then return end _id = AuxUtil.PlayDynamicObject(ConstAssetPathConfig.AssetPath184, 9999, self.RenderEntity.Transform, self.components.model.Layer) elseif type == LuaConst.EffectType.SkillDirRectWithArrow then if self._effectDict[type] then return end --SpriteRenderer类型 --_id = AuxUtil.PlayDynamicObject(ConstAssetPathConfig.AssetPath185, 9999, self.RenderEntity.Transform, self.components.model.Layer) --Projector类型 _id = AuxUtil.PlayDynamicObject(ConstAssetPathConfig.AssetPath186, 9999, self.RenderEntity.Transform, self.components.model.Layer) elseif type == LuaConst.EffectType.SkillDirCircleWithArrow then if self._effectDict[type] then return end _id = AuxUtil.PlayDynamicObject(ConstAssetPathConfig.AssetPath187, 9999, self.RenderEntity.Transform, self.components.model.Layer) elseif type == LuaConst.EffectType.SkillDirFanshape then if self._effectDict[type] then return end _id = AuxUtil.PlayDynamicObject(ConstAssetPathConfig.AssetPath188, 9999, self.RenderEntity.Transform, self.components.model.Layer) elseif type == LuaConst.EffectType.SkillDirArrowLock then if self._effectDict[type] then return end _id = AuxUtil.PlayDynamicObject(ConstAssetPathConfig.AssetPath189, 9999, self.RenderEntity.Transform, self.components.model.Layer) elseif type == LuaConst.EffectType.SkillEffectAreaRect then if self._effectDict[type] then return end _id = AuxUtil.PlayDynamicObject(ConstAssetPathConfig.AssetPath190, 9999, self.RenderEntity.Transform, self.components.model.Layer) elseif type == LuaConst.EffectType.SkillEffectAreaCircle then if self._effectDict[type] then return end _id = AuxUtil.PlayDynamicObject(ConstAssetPathConfig.AssetPath191, 9999, self.RenderEntity.Transform, self.components.model.Layer) elseif type == LuaConst.EffectType.SkillEffectAreaCircle2 then if self._effectDict[type] then return end _id = AuxUtil.PlayDynamicObject(ConstAssetPathConfig.AssetPath192, 9999, self.RenderEntity.Transform, self.components.model.Layer) elseif type == LuaConst.EffectType.SkillEffectAreaCircleSimple then if self._effectDict[type] then return end _id = AuxUtil.PlayDynamicObject(ConstAssetPathConfig.AssetPath181, 9999, self.RenderEntity.Transform, self.components.model.Layer) elseif type == LuaConst.EffectType.SkillAdjutant then if self._effectDict[type] then return end _id = AuxUtil.PlayDynamicObject(ConstAssetPathConfig.AssetPath193, 9999, self.RenderEntity.Transform, self.components.model.Layer) elseif type == LuaConst.EffectType.HeroSignFriend then if self._effectDict[type] then return end _id = AuxUtil.PlayDynamicObject(ConstAssetPathConfig.AssetPath194, -1, self.RenderEntity.Transform, self.components.model.Layer) elseif type == LuaConst.EffectType.HeroSighEnemy then if self._effectDict[type] then return end _id = AuxUtil.PlayDynamicObject(ConstAssetPathConfig.AssetPath195, -1, self.RenderEntity.Transform, self.components.model.Layer) elseif type == LuaConst.EffectType.Lock1 then if self._effectDict[type] then return end _id = AuxUtil.PlayDynamicObject(ConstAssetPathConfig.AssetPath196, 9999, self.RenderEntity.Transform, self.components.model.Layer) elseif type == LuaConst.EffectType.Lock2 then if self._effectDict[type] then return end _id = AuxUtil.PlayDynamicObject(ConstAssetPathConfig.AssetPath177, 9999, self.RenderEntity.Transform, self.components.model.Layer) elseif type == LuaConst.EffectType.Debug_Square then if self._effectDict[type] then return end _id = AuxUtil.PlayDynamicObject(ConstAssetPathConfig.AssetPath197, 9999, self.RenderEntity.Transform, self.components.model.Layer) elseif type == LuaConst.EffectType.RebelStrikeSelect then if self._effectDict[type] then return end _id = AuxUtil.PlayDynamicObject(ConstAssetPathConfig.AssetPath198, -1, self.RenderEntity.Transform, self.components.model.Layer) elseif type == LuaConst.EffectType.RebelStrikeFighting then if self._effectDict[type] then return end _id = AuxUtil.PlayDynamicObject(ConstAssetPathConfig.AssetPath199, -1, self.RenderEntity.Transform, self.components.model.Layer) elseif type == LuaConst.EffectType.PredictTarget then if self._effectDict[type] then return end _id = AuxUtil.PlayDynamicObject(ConstAssetPathConfig.AssetPath200, -1, self.RenderEntity.Transform, self.components.model.Layer) elseif type == LuaConst.EffectType.Occupier then if self._effectDict[type] then return end _id = AuxUtil.PlayDynamicObject(ConstAssetPathConfig.AssetPath201, -1, self.RenderEntity.Transform, self.components.model.Layer) elseif type == LuaConst.EffectType.OccupierFoot then if self._effectDict[type] then return end _id = AuxUtil.PlayDynamicObject(ConstAssetPathConfig.AssetPath202, -1, self.RenderEntity.Transform, self.components.model.Layer) elseif type == LuaConst.EffectType.CartRange then -- 镖车范围 if self._effectDict[type] then return end _id = AuxUtil.PlayDynamicObject(ConstAssetPathConfig.AssetPath181, -1, self.RenderEntity.Transform, self.components.model.Layer) elseif type == LuaConst.EffectType.CartFighting then if self._effectDict[type] then return end _id = AuxUtil.PlayDynamicObject(ConstAssetPathConfig.AssetPath199, -1, self.RenderEntity.Transform, self.components.model.Layer) elseif type == LuaConst.EffectType.PetCapturing then if self._effectDict[type] then return end _id = AuxUtil.PlayDynamicObject(ConstAssetPathConfig.AssetPath199, -1, self.RenderEntity.Transform, self.components.model.Layer) elseif type == LuaConst.EffectType.DragonArtery then if self._effectDict[type] then return end _id = AuxUtil.PlayDynamicObject(ConstAssetPathConfig.AssetPath203, -1, self.RenderEntity.Transform, self.components.model.Layer) elseif type == LuaConst.EffectType.FourCountryNo1 then if self._effectDict[type] then return end _id = AuxUtil.PlayDynamicObject(ConstAssetPathConfig.AssetPath204, -1, self.RenderEntity.Transform, self.components.model.Layer) end if _id then self._effectDict[type] = _id end --else --在断线重连的时候是正常现象 --logging.error(LTAG.ERROR, "HYW : self.RenderEntity nil ERROR: ", self) end end function ExpEntity:SetEffectScaleByType(type,scaleX,scaleY,scaleZ) if self._effectDict[type] then AuxUtil.SetDynamicObjectScale(self._effectDict[type],scaleX,scaleY,scaleZ) end end function ExpEntity:SetEffectRotByType(type,rotY) if self._effectDict[type] then AuxUtil.SetDynamicObjectRotationY(self._effectDict[type],rotY) end end --设置localPosition function ExpEntity:SetEffectPosByType(type,posX,posY,posZ) if self._effectDict[type] then if posX and posY and posZ then AuxUtil.SetDynamicObjectPos(self._effectDict[type],posX,posY,posZ) end end end function ExpEntity:GetWorldPosByType(type) if self._effectDict[type] then local pos = AuxUtil.GetDyamicObjectPos(self._effectDict[type]) return pos.x,pos.y,pos.z end end function ExpEntity:SetEffectProjectorAngleByType(type,angle) if self._effectDict[type] then AuxUtil.SetDynamicObjectProjectorAngle(self._effectDict[type],angle) end end function ExpEntity:SetEffectProjectorInCancel(type,isInCancel) if self._effectDict[type] then AuxUtil.SetDynamicObjectProjectorInCancel(self._effectDict[type],isInCancel) end end function ExpEntity:SetEffectProjectorAspectRatio(type,value) if self._effectDict[type] then AuxUtil.SetDynamicObjectProjectorAspectRatio(self._effectDict[type],value) end end function ExpEntity:SetEffectProjectorOffsetY(type, offsetY) if self._effectDict[type] then AuxUtil.SetDynamicObjectProjectOffsetY(self._effectDict[type], offsetY) end end function ExpEntity:SetEffectSpriteRendererScaleByType(type,width,height) if self._effectDict[type] then AuxUtil.SetDynamicObjectSpriteRendererScale(self._effectDict[type],width,height) end end function ExpEntity:SetMaterialByType(matType) if not self.RenderEntity then return end if matType == EMaterialType.FROZEN then self.RenderEntity:SetMaterial(EMaterialConvertedType.FROZEN, EMaterialSetType.ReplaceMaterial, FrozenMaterialPath, -1) elseif matType == EMaterialType.TRANSPARENT then self.RenderEntity:SetMaterial(EMaterialConvertedType.TRANSPARENT, EMaterialSetType.ReplaceShader, HeroTransparentShaderPath, 2510) if self.PetRenderEntity then self.PetRenderEntity:SetMaterial(EMaterialConvertedType.TRANSPARENT, EMaterialSetType.ReplaceShader, HeroTransparentShaderPath, 2510) end else logging.error(LTAG.ERROR, "HYW : @SetMaterialByType 不支持的材质类型 : ", matType) end self.lastMatType = matType end function ExpEntity:ResetMaterial() if not self.RenderEntity then return end self.RenderEntity:ResetMaterial() if self.PetRenderEntity then if self.lastMatType == EMaterialType.TRANSPARENT then self.PetRenderEntity:ResetMaterial() end end self.lastMatType = nil end function ExpEntity:SetActorVisible(isVisible, force) if not self.RenderEntity then return end if self.isActorVisible == nil or self.isActorVisible ~= isVisible or force then self.isActorVisible = isVisible self.RenderEntity:SetActorVisible(self.isActorVisible) if self.PetRenderEntity then self.PetRenderEntity:SetActorVisible(self.isActorVisible) end if self.isActorVisible then self:PlayCurModelEffect() else self:StopCurModelEffect() end end end function ExpEntity:StopEffectByType(type) if self._effectDict[type] then if type == LuaConst.EffectType.BeingSelected then if _selectedNpcEffect == self._effectDict[LuaConst.EffectType.BeingSelected] then AuxUtil.StopDynamicObject(self._effectDict[type]) self._effectDict[type] = nil _selectedNpcEffect = nil end else AuxUtil.StopDynamicObject(self._effectDict[type]) self._effectDict[type] = nil end end end --玩家头顶名字 --主城同步的entity和其他entity的数据源不同 function ExpEntity:GetPlayerModelName(forceNameColor) local entity = self.Entity local name = entity._logicInitData.Name if string_isNilOrEmpty(name) then return "" end local officialPosition = 0 local server = "" local nameColor = forceNameColor or UTL.Color.ModelNameColor.White if entity.isRetinue then local ownerName = entity._logicInitData.Name -- 在出生时已将随从名字设置为了和主人一样的名字 if BattleDataGetter.CheckCurLevelType(LuaConst.LevelType.DragonArteryRegistArea) then if entity._logicInitData.MasterEntity ~= LogicUpdateManager._curEntity then ownerName = UIUtils.GetLocalizedTxt(Const_IDS["IDS_DragonArtey_PlayerName"]) end end return string.FormatByIdsKey(entity:GetOriginCharacterData().MonsterNameIDS, ownerName) elseif entity._logicInitData.isStatue then local acid = entity._logicInitData.Acid local sourceData = CTL.HeroMatch1v1.GetStatueInfoByAcid(acid) or CTL.HeroMatch3v3.GetStatueInfoByAcid(acid) or CTL.Country.GetStatueGuildInfoByAcid(entity._logicInitData.Acid) if sourceData then officialPosition = sourceData.officialTitle if forceNameColor == nil and CTL.Team.IsMemberInTeam(acid) or MDL.Guild.IsSameGuild(sourceData.guildShow.guildId) then nameColor = UTL.Color.ModelNameColor.Blue end server = CTL.CrossServer.GetServerShowStr(sourceData.serverShowId, CTL.CrossServer.IsSameServer(sourceData.MergeServerId)) end elseif entity._logicInitData.isSyncMove then local acid = entity._logicInitData.Acid local sourceData = SyncMoveManager.GetTownRoleInfoByAcid(acid) if sourceData then officialPosition = sourceData.officialTitle if forceNameColor == nil and CTL.Team.IsMemberInTeam(acid) or MDL.Guild.IsSameGuild(sourceData.guildID) then nameColor = UTL.Color.ModelNameColor.Blue end server = CTL.CrossServer.GetServerShowStr(sourceData.serId, CTL.CrossServer.IsSameServer(sourceData.mergeServerId)) end else local isPlayerSelf = self.Entity._logicInitData.IsPlayerSelf local sourceData = LevelPlayerManager.GetPlayerInfoByPlayerIDInRoom(entity:GetPlayerID()) if sourceData then officialPosition = sourceData.officialPosition if isPlayerSelf then --玩家自己主单位才显示名字 if entity:IsMainEntityOfPlayer() then nameColor = forceNameColor or UTL.Color.ModelNameColor.Green if CTL.CrossServer.IsShowServerInPlayerModelName() then server = CTL.CrossServer.GetServerShowStr(sourceData.serId, true) end else return nil end else local myPlayerInfo = LevelPlayerManager.GetPlayerInfoByPlayerIDInRoom(LevelPlayerManager.MyPlayerIDInRoom) if forceNameColor == nil then --特定玩法显示红色 if not entity.isIllusion and (BattleDataGetter.CheckCurLevelType(LuaConst.LevelType.SyncSolo) or BattleDataGetter.CheckCurLevelType(LuaConst.LevelType.SoloFight) or BattleDataGetter.CheckCurLevelType(LuaConst.LevelType.SyncSoloPractice)) then nameColor = UTL.Color.ModelNameColor.Red elseif not entity.isIllusion and (LevelManager.IsSyncTeamPVP() or BattleDataGetter.CheckCurLevelType(LuaConst.LevelType.SyncUnfairTeamPVP)) then if CampManager.IsEnemyCamp(entity:GetCampID(), LevelPlayerManager.MainEntityCampID) == false then nameColor = UTL.Color.ModelNameColor.Blue else nameColor = UTL.Color.ModelNameColor.Red end else local isFriend = (not string.isNilOrEmpty(myPlayerInfo.guildID) and myPlayerInfo.guildID == sourceData.guildID) or myPlayerInfo.teamId == sourceData.teamId if isFriend or CampManager.IsEnemyCamp(entity:GetCampID(), LevelPlayerManager.MainEntityCampID) == false then nameColor = UTL.Color.ModelNameColor.Blue else nameColor = UTL.Color.ModelNameColor.Red end end end if CTL.CrossServer.IsShowServerInPlayerModelName() then if not string.isNilOrEmpty(sourceData.serId) then server = CTL.CrossServer.GetServerShowStr(sourceData.serId, sourceData.realSerId == myPlayerInfo.realSerId) end end end end end local countryId, countryJob = BattleDataGetter.GetEntityCountryInfo(entity) local prefix = self:GetModelNamePrefix(countryId, countryJob, officialPosition) self.curNameColor = nameColor return prefix .. UTL.Color.FormatTextByColor(nameColor, name) .. server end function ExpEntity:GetCurNameColor() return self.curNameColor end function ExpEntity:GetPetName(color) if self.PetRenderEntity then local name = self.Entity._logicInitData.PetName if string.isNilOrEmpty(name) then local petConfig = DataSheetManager.PetData:GetDataByID_Stage(self.Entity._logicInitData.PetID, self.Entity._logicInitData.PetStage) name = UIUtils.GetLocalizedTxt(Const_IDS[petConfig.PetName]) end return UTL.Color.FormatTextByColor(color or UTL.Color.ModelNameColor.White, name) end return "" end --玩家头顶势力信息 --主城同步的entity和其他entity的数据源不同 function ExpEntity:GetPlayerModelGuildInfo(sourceEntity) local entity = sourceEntity or self.Entity if entity._logicInitData.isStatue then local sourceData = CTL.Country.GetStatueGuildInfoByAcid(entity._logicInitData.Acid) or CTL.HeroMatch1v1.GetStatueInfoByAcid(entity._logicInitData.Acid) if sourceData then local guildShow = sourceData.guildShow return guildShow.guildName, guildShow.emblemFrame, guildShow.emblemContent, guildShow.jobTitle, guildShow.identity else sourceData = CTL.HeroMatch3v3.GetStatueInfoByAcid(entity._logicInitData.Acid) if sourceData then local guildShow = sourceData.guildShow local guildName = nil if sourceData.teamWarName then guildName = string.format("%s%s", sourceData.teamWarName, UIUtils.GetLocalizedTxt(Const_IDS["IDS_HeroMatch3v3_Team"])) end return guildName, guildShow.emblemFrame, guildShow.emblemContent, -1, guildShow.identity end end elseif entity._logicInitData.isSyncMove then -- 状态同步关卡中的非我玩家 local sourceData = SyncMoveManager.GetTownRoleInfoByAcid(entity._logicInitData.Acid) if sourceData then if (BattleDataGetter.CheckCurLevelType(LuaConst.LevelType.CrossHeroMatchTown3V3) or BattleDataGetter.CheckCurLevelType(LuaConst.LevelType.TeamFairChampionshipTown)) and not string.isNilOrEmpty(sourceData.teamWarName) then -- 天地群雄3v3等待区 优先显示战团名字 return sourceData.teamWarName, sourceData.guildEmblemFrame, sourceData.guildEmblemContent, -1, sourceData.guildIdentity end return sourceData.guildName, sourceData.guildEmblemFrame, sourceData.guildEmblemContent, sourceData.guildJob, sourceData.guildIdentity end else local sourceData = LevelPlayerManager.GetPlayerInfoByPlayerIDInRoom(entity:GetPlayerID()) if sourceData then if (BattleDataGetter.CheckCurLevelType(LuaConst.LevelType.CrossHeroMatchTown3V3) or BattleDataGetter.CheckCurLevelType(LuaConst.LevelType.TeamFairChampionshipTown)) and not string.isNilOrEmpty(sourceData.teamWarName) then -- 天地群雄3v3等待区 优先显示战团名字 return sourceData.teamWarName, sourceData.guildEmblemFrame, sourceData.guildEmblemContent, -1, sourceData.guildIdentity end return sourceData.guildName, sourceData.guildEmblemFrame, sourceData.guildEmblemContent, sourceData.guildJob, sourceData.guildIdentity end end return nil end -- 获取玩家势力Id function ExpEntity:GetGuildId() local entity = self.Entity if entity._logicInitData.isSyncMove then local sourceData = SyncMoveManager.GetTownRoleInfoByAcid(entity._logicInitData.Acid) if sourceData then return sourceData.guildID end else local sourceData = LevelPlayerManager.GetPlayerInfoByPlayerIDInRoom(entity:GetPlayerID()) if sourceData then return sourceData.guildID end end return nil end local BLIND_DMG_TYPE = LuaConst.UIDamageType.Blind function ExpEntity:OnCantTriggerBecauseBlind(missile, hitEntity) if self.Entity:SelfAndMasterIsPlayerSelf() then hitEntity.ExpEntity:CreateHurtNumber(0, true, BLIND_DMG_TYPE) end end function ExpEntity:OnCmdJoystickSetTargetAndUseSkill(command, skillJoyStickData, entity) if skillJoyStickData then if self.joystickTargetAimEffect then SystemManager.OnBreakPSEffect(self.joystickTarget, self.joystickTargetAimEffect, true, entity) end end self.joystickTargetAimEffect = nil self.joystickTarget = nil end function ExpEntity:OnCmdJoystickCancel(command) if self.joystickTargetAimEffect then SystemManager.OnBreakPSEffect(self.joystickTarget, self.joystickTargetAimEffect, true) self.joystickTargetAimEffect = nil self.joystickTarget = nil end end function ExpEntity:OnCmdJoystickSetTarget(command, entity, target, skillJoyStickData) if not skillJoyStickData.AimEffectOnlySelf or entity:IsPlayerSelf() then if target ~= self.joystickTarget then --拓展性警告!self.joystickTarget在未来的需求可能会变成一个list。尽可能拒掉,因为这个东西要求做成帧同步的,会比较麻烦。如果一定要做,需要估多点分,两天以上。 需要改造的包括外围输入/UI层的UISkillJoystick、视图层的ExpEntity、可能还需要改逻辑层的SkillBaseSystem、FilterManager if self.joystickTarget then SystemManager.OnBreakPSEffect(self.joystickTarget, skillJoyStickData.AimEffect, true, entity) self.joystickTargetAimEffect = nil end self.joystickTarget = target if target then self.joystickTargetAimEffect = skillJoyStickData.AimEffect SystemManager.OnReceivePsEffect(target, skillJoyStickData.AimEffect, true, entity) end end end end --region RenderEntity 封装 function ExpEntity:GetRenderEntity() return self.RenderEntity end function ExpEntity:GetModelHeight() if self.RenderEntity then return self.RenderEntity:GetModelHeight() else return 0 end end function ExpEntity:GetPosition() if self.RenderEntity then return self.RenderEntity.Transform:GetPosition() else local x,z = FP.tonumberV2(self.Entity:GetLogicPos()) local y = FP.tonumberV1(self.Entity:GetLogicPosY()) return x,y,z end end -- 获取摸个骨骼的世界坐标y function ExpEntity:GetEquipSlotHeight(solt , nilHigh) if self.RenderEntity then return self.RenderEntity:GetEquipSlotHeight(solt,nilHigh) else return nilHigh end end function ExpEntity:GetEulerAngleY() if self.RenderEntity then return self.RenderEntity:GetEulerAngleY() else return 0 end end function ExpEntity:ApplyExpTrans() if not self.RenderEntity then return end local entity = self.Entity local move = self.Entity.components.move local posX,posZ = FP.tonumberV2(move.LogicPos) local dirX,dirZ = FP.tonumberV2(move.LogicRotateDir) self.RenderEntity:SetTrans(posX, posZ, dirX, dirZ) ExpBatchSystem.SetEntityTrans(entity,move.LogicPos,move.LogicRotateDir) end function ExpEntity:ApplyExpTransY() if not self.RenderEntity then return end self.RenderEntity:SetTransY(FP.tonumberV1(self.Entity.components.move.LogicPosY)) end function ExpEntity:ApplyPetExpTrans(immediately) if not self.PetRenderEntity then return end local petComp = self.Entity.components.pet local posX,posZ = FP.tonumberV2(petComp.logicPos) local dirX,dirZ = FP.tonumberV2(petComp.logicDir) if immediately then self.PetRenderEntity:SetTrans(posX, posZ, dirX, dirZ) end ExpBatchSystem.SetPetEntityTrans(self.PetRenderEntity,posX,posZ,dirX,dirZ) end function ExpEntity:GetEffectCount(effect) local count = 0 local dic = self._countEffectCountDic[effect] if dic then for k,v in pairs(dic) do --pairs safe 数据统计对顺序不敏感 count = count + v end end return count end function ExpEntity:ChangeEffectCountOfEntity(effect, caster, delta) local dic = self._countEffectCountDic[effect] if not dic then dic = {} self._countEffectCountDic[effect] = dic end local count = dic[caster.EntityID] or 0 count = count + delta dic[caster.EntityID] = count -- if count > 0 then -- caster.ExpEntity:BindCountEffectRelationshipAsCaster(self, effect) -- else -- caster.ExpEntity:UnbindCountEffectRelationshipAsCaster(self, effect) -- end return count end -- function ExpEntity:BindCountEffectRelationshipAsCaster(receiver, effect) -- self.effectRelationShipDic = self.effectRelationShipDic or {} -- local list = self.effectRelationShipDic[effect] -- if list == nil then -- list = {} -- self.effectRelationShipDic[effect] = list -- end -- local exist = false -- for i, _receiver in ipairs(list) do -- if _receiver == receiver then -- exist = true -- end -- end -- if not exist then -- table.insert(list, receiver) -- end -- end -- function ExpEntity:UnbindCountEffectRelationshipAsCaster(receiver, effect) -- if self.effectRelationShipDic and self.effectRelationShipDic[effect] then -- for i,v in ipairs(self.effectRelationShipDic[effect]) do -- if v == receiver then -- table.remove(self.effectRelationShipDic[effect], i) --BindCountEffectRelationshipAsCaster保证了不会重复添加,所以这里可以提前break -- break -- end -- end -- end -- end function ExpEntity:ReceivePetPsEffect(effect) if string.isNilOrEmpty(effect) then return end if not self.PetRenderEntity then return end local effectId = UTL.String.GetIdByString(effect) local entity = self.Entity local effectAsPlayerSelf = ExpUpdateManager.IsEffectAsPlayerSelf(entity) local characterType = entity._logicInitData.CharacterType local timeScale = FP.tonumberV1(entity.components.timeScale:GetCurEffectTimeScale()) local layer = self.components.model.Layer ExpBatchSystem.BatchEffect(self.PetRenderEntity, effectId, effectAsPlayerSelf, characterType, timeScale, layer, false) end -- isCountEffect : 计数的effect,每次调用ReceivePsEffect都会增加1次计数,需要调用相同次数的BreakPsEffect才能停止 function ExpEntity:ReceivePsEffect(effect, isCountEffect, caster) if not self.RenderEntity then return end local effectId = UTL.String.GetIdByString(effect) local shouldPlay = true if isCountEffect then local count = self:GetEffectCount(effect) self:ChangeEffectCountOfEntity(effect, caster, 1) if count >= 1 then shouldPlay = false end end if shouldPlay then local entity = self.Entity local effectAsPlayerSelf = ExpUpdateManager.IsEffectAsPlayerSelf(entity) local characterType = entity._logicInitData.CharacterType local timeScale = FP.tonumberV1(entity.components.timeScale:GetCurEffectTimeScale()) local layer = self.components.model.Layer local disableTimeLine = (not SystemManager.ShoulPlayMusouShow(entity)) or (not LevelManager.IsLittleBlackRoomMusouLevel()) -- 不播小黑屋 ExpBatchSystem.BatchEffect(self.RenderEntity, effectId, effectAsPlayerSelf, characterType, timeScale, layer, disableTimeLine) end end function ExpEntity:ReceiveHitEffect(effect, timeScale, duration, fx, fz, hitSoundLevel, isNotPlayHitSound) if not self.RenderEntity then return end local effectId = UTL.String.GetIdByString(effect) local effectAsPlayerSelf = ExpUpdateManager.IsEffectAsPlayerSelf(self.Entity) local characterType = self.Entity._logicInitData.CharacterType ExpBatchSystem.BatchHitEffect(self.RenderEntity, effectId, effectAsPlayerSelf, characterType, FP.tonumberV1(timeScale), duration, fx, fz, hitSoundLevel, isNotPlayHitSound) end function ExpEntity:RefreshTimeScale(ignoreSound, timescaleChannel, expAimSpeed) if self.RenderEntity == nil then return end --self.RenderEntity:SetTimeScale(value,timescaleChannel) --old timescale改变时,只把引发改变的channel告诉了c#,这样不对。应该把所有channel都告诉c# --new↓ local comp_timeScale = self.Entity.components.timeScale local expSpeed = expAimSpeed or 1 if timescaleChannel == LuaConst.ETimeScaleChannel.ALL then self.RenderEntity:SetTimeScale(FP.tonumberV1(comp_timeScale:GetCurTimeScale()), LuaConst.ETimeScaleChannel.ALL) --ALL Channel优先级最低,应该最先调用 self.RenderEntity:SetTimeScale(FP.tonumberV1(comp_timeScale:GetCurSkillAnimSoundEntityPosRotTimeScale() * expSpeed), LuaConst.ETimeScaleChannel.SKILL_ANIM_SOUND_ENTITY_POS_ROT) self.RenderEntity:SetTimeScale(FP.tonumberV1(comp_timeScale:GetCurMissileTimeScale()), LuaConst.ETimeScaleChannel.MISSILE) self.RenderEntity:SetTimeScale(FP.tonumberV1(comp_timeScale:GetCurEffectTimeScale()), LuaConst.ETimeScaleChannel.EFFECT) ExpBatchSystem.ChangeBatchEffectTimeScale(self.RenderEntity, FP.tonumberV1(comp_timeScale:GetCurEffectTimeScale())) else if timescaleChannel == LuaConst.ETimeScaleChannel.SKILL_ANIM_SOUND_ENTITY_POS_ROT then self.RenderEntity:SetTimeScale(FP.tonumberV1(comp_timeScale:GetCurSkillAnimSoundEntityPosRotTimeScale() * expSpeed), LuaConst.ETimeScaleChannel.SKILL_ANIM_SOUND_ENTITY_POS_ROT) elseif timescaleChannel == LuaConst.ETimeScaleChannel.MISSILE then self.RenderEntity:SetTimeScale(FP.tonumberV1(comp_timeScale:GetCurMissileTimeScale()), LuaConst.ETimeScaleChannel.MISSILE) elseif timescaleChannel == LuaConst.ETimeScaleChannel.EFFECT then self.RenderEntity:SetTimeScale(FP.tonumberV1(comp_timeScale:GetCurEffectTimeScale()), LuaConst.ETimeScaleChannel.EFFECT) ExpBatchSystem.ChangeBatchEffectTimeScale(self.RenderEntity, FP.tonumberV1(comp_timeScale:GetCurEffectTimeScale())) end end --new↑ -- 声音部分 if not ignoreSound and timescaleChannel == LuaConst.ETimeScaleChannel.ALL then--声音播放仅用LuaConst.ETimeScaleChannel.ALL的 local value = FP.tonumberV1(comp_timeScale:GetCurTimeScale()) local renderEntity = self.RenderEntity if value <= 0 then CTL.Sound.PlayObjSound("pause",renderEntity) else CTL.Sound.PlayObjSound("resume",renderEntity) end end end function ExpEntity:ChangeModel(modelData, withMagicWeapon, notPVPModel) if not self.RenderEntity then return end local comp_ExpModel = self.components.model if not notPVPModel then if comp_ExpModel.CurModelID == modelData.ID then logging.log(LTAG.LOG, "GWS : 换模型执行失败: 当前已是这个模型了,无需更换!modelId = " , modelData.ID) return end end comp_ExpModel.NeedDissolve = modelData.IfDissolve local layer = comp_ExpModel.Layer local logicInitData = self.Entity._logicInitData local isPVPModel if notPVPModel then isPVPModel = false else isPVPModel = self:IsPVPModel() end if modelData.ID > CONST_HEROMODELIDMAX then isPVPModel = false end local pathId, combinePathId = 0, 0 local combinePath = modelData.CombinePath local characterID, magicWeaponID, isActiveMagicWeapon, weaponBreak, heroBreakNums = logicInitData.CharacterID, logicInitData.MagicWeaponID, logicInitData.IsActiveMagicWeapon, logicInitData.WeaponBreak, logicInitData.HeroBreakNums local modelPath if string_isNilOrEmpty(combinePath) then modelPath, modelData, isPVPModel, characterID, magicWeaponID, isActiveMagicWeapon, weaponBreak, heroBreakNums = self:PreprocessModelData(modelData, isPVPModel, characterID, magicWeaponID, isActiveMagicWeapon, weaponBreak, heroBreakNums) pathId = UTL.String.GetIdByString(modelPath) else combinePathId = UTL.String.GetIdByString(modelData.CombinePath) end local ctrlPath = self:GetAnimatorCtrlPath(logicInitData.CharacterType, modelData, isPVPModel) local equipmentID = modelData.EquipmentID local ctrlPathId=UTL.String.GetIdByString(ctrlPath) local animAppendId = UTL.String.GetIdByString(modelData.AnimAppend) local materialId=UTL.String.GetIdByString(modelData.material) local lastModel = DataSheetManager.MonsterModelData:GetDataByID (self.components.model.CurModelID) self.RenderEntity:PlayAnimationState(LuaConst.Animation_idle_loop ,0, 0) -- 为了回收再利用的使用 animator 能清除缓存【模型 】 self.components.model.CurModelID = modelData.ID -- 记录当前 RenderEntity.cs中的 ActorModelID self.RenderEntity:ChangeModel(modelData.ID, pathId, combinePathId, modelData.ModelScale, ctrlPathId, animAppendId, materialId, modelData.DmgNumHeight, modelData.ModelSizeRate) if withMagicWeapon or equipmentID == -1 then self:CreateHeroWeapon(self.RenderEntity, modelData.ID, characterID, magicWeaponID, isActiveMagicWeapon, weaponBreak, isPVPModel) end --因为时序问题插到这里 ExpEntity.CreateEquipPart(self.RenderEntity, modelData.ID, equipmentID, isPVPModel) if withMagicWeapon or equipmentID == -1 then self:ChangeWeaponEffect(characterID, magicWeaponID, isActiveMagicWeapon, weaponBreak) end self:CreateDyeAppearance() self:RemoveActorPsEffectRecord(lastModel.ModelPsEffect) self:PlayCurModelEffect(modelData) self:PlayHeroBreakEffect(characterID, heroBreakNums) end function ExpEntity:ChangeHorse(horseModelPath, horseShowEffect, modelScale) if not self.RenderEntity then return end self.RenderEntity:ChangeHorse(horseModelPath, horseShowEffect, modelScale) local oldNeedStandOnHorse = self.needStandOnHorse self.needStandOnHorse = self.Entity._logicInitData.HorseModelData.IsStandOnHorse if oldNeedStandOnHorse ~= self.needStandOnHorse then local animIntKey= UTL.String.GetIdByString(self.needStandOnHorse and LuaConst.Animation_idle_loop or LuaConst.Animation_horseIdle) self.RenderEntity:PlayAnimation(animIntKey ,false ,false, 0) end if self.needStandOnHorse then EventSystem.Dispatch(EventID.UIBattle_Element_OffsetY, self.RenderEntity, CONST_HALFMODELHIGHT) -- 名字板上移半身高(约是1.2米) else EventSystem.Dispatch(EventID.UIBattle_Element_OffsetY, self.RenderEntity, nil) -- 名字板上移半身高(约是1.2米) end end function ExpEntity:ChangeHorseNotRiding() self.needStandOnHorse = self.Entity._logicInitData.HorseModelData.IsStandOnHorse end function ExpEntity:ChangePet(petId, petStage) -- 先销毁之前的pet,再尝试创建现在的pet if self.PetRenderEntity then self:StopPetModelEffect() ExpBatchSystem.RemoveEntityAllBatchEffect(self.PetRenderEntity) ExpBatchSystem.RemovePetRenderEntity(self.PetRenderEntity) EventSystem.Dispatch(EventID.UIBattle_ExpEntity_UIDispose, self.PetRenderEntity) self.PetRenderEntity:Dispose(false) self.PetRenderEntity = nil end if petId and petId > 0 then self:CreatePetModel(self.Entity, petId, petStage) self:ApplyPetExpTrans() self.PetRenderEntity:SetVisible(true) end end -- flyRate 只有在击飞时,才不会为0 ;其他情况都是0 function ExpEntity:PlayAnimation(animID ,flyRate) --特殊注意:同一帧中设置两次动画,已后者为准,可以看成跳过前者的代码 if not self.RenderEntity or string.isNilOrEmpty(animID) then return end local animIntKey= UTL.String.GetIdByString(animID) local contentHorse = not self.Entity:CheckHasBuffState(LuaConst.SpecialBuffs.HorseUpdateSelfAnim) if self.needStandOnHorse and self.Entity:CheckHasBuffState(LuaConst.SpecialBuffs.InRiding) then -- 如果站立在马上,则一定为idle动画 if animID == LuaConst.Animation_horseShowPos or animID == LuaConst.Animation_horseIdle then self.RenderEntity:PlayAnimation(animIntKey ,contentHorse ,false, flyRate) end local animOnHorseIntKey = UTL.String.GetIdByString(LuaConst.Animation_idle_loop) self.RenderEntity:PlayAnimation(animOnHorseIntKey ,false ,false, flyRate) -- 人和武器的动画,无马 else self.RenderEntity:PlayAnimation(animIntKey ,contentHorse ,false, flyRate) -- 人和武器的动画 + 马 -- 当动骑马动作是idle、run、普攻时,不改变马的动作 end if contentHorse then self.ExpHorseAnimID = animID end if self.SubRenderEntityList then for i,renderEntity in ipairs(self.SubRenderEntityList) do renderEntity:PlayAnimation(animIntKey ,false,false, flyRate) end end end -- 宠物播放动画 function ExpEntity:PlayPetAnimation(animID) if not self.PetRenderEntity or string.isNilOrEmpty(animID) then return end local animIntKey= UTL.String.GetIdByString(animID) self.PetRenderEntity:PlayAnimation(animIntKey, false) end function ExpEntity:PlayHorseRunAnimation(speed, angSpeed) if not self.RenderEntity then return end if self.ExpHorseAnimID ~= LuaConst.Animation_horseRun then self.ExpHorseAnimID = LuaConst.Animation_horseRun local animIntKey= UTL.String.GetIdByString(self.ExpHorseAnimID) self.RenderEntity:PlayHorseRunAnimation(speed, angSpeed ,animIntKey) -- 只是马的动画 else self.RenderEntity:PlayHorseRunAnimation(speed, angSpeed) -- 只是马的动画 end end function ExpEntity:PlayAnimationDirectly(animID) if not self.RenderEntity then return end local animIntKey= UTL.String.GetIdByString(animID) self.RenderEntity:PlayAnimation(animIntKey, false, true) if self.SubRenderEntityList then for i,renderEntity in ipairs(self.SubRenderEntityList) do renderEntity:PlayAnimation(animIntKey, false, true) end end end function ExpEntity:ReplaceAnimation(fromAnim, toPath) if not self.RenderEntity then return end self.RenderEntity:ReplaceAnimation(fromAnim, toPath) end function ExpEntity:StartBubble(id,startIndex,endIndex) if not self.RenderEntity then return end self.RenderEntity:StartBubbleUI(id,startIndex,endIndex) end function ExpEntity:SetBlendHurtAnim(canBlend) self.canBlendHurtAnim = canBlend end function ExpEntity:InsertHurtAnim() if not self.canBlendHurtAnim then -- 不能融合 return end if not self.RenderEntity then return end if self.hurtBlendRate > 0 then if self.Entity:CheckType(LuaConst.CharacterType.Hero) or self.Entity.isIllusion then if LogicUpdateManager._clientHandleFrame - self.insertHurtAnimFrame > 9 then self.insertHurtAnimFrame = LogicUpdateManager._clientHandleFrame self.RenderEntity:InsertHurtAnim(self.hurtBlendRate ,ExpNormalHurtAnim) -- 只是人、马、武器的动画 end else if self.Entity.components.buff:GetBuffUpdateData(LuaConst_SpecialBuffs_InSuperWeak) then self.RenderEntity:InsertHurtAnim(1 ,ExpWeakHurtAnim) -- 只是人、马、武器的动画 else self.RenderEntity:InsertHurtAnim(self.hurtBlendRate ,ExpNormalHurtAnim) -- 只是人、马、武器的动画 end end end end --timeScale 得传FP --duration 得传number function ExpEntity:PlayPsEffect(effect, timeScale, duration, layer, callBack) if not self.RenderEntity then return 0 end local entity = self.Entity local effectAsPlayerSelf = ExpUpdateManager.IsEffectAsPlayerSelf(entity) local characterType = entity._logicInitData.CharacterType timeScale = timeScale or entity.components.timeScale:GetCurEffectTimeScale() duration = duration or -1 layer = layer or self.components.model.Layer local effectId=UTL.String.GetIdByString(effect) local disableTimeLine = (not SystemManager.ShoulPlayMusouShow(entity)) or (not LevelManager.IsLittleBlackRoomMusouLevel()) -- 不播小黑屋 return self.RenderEntity:PlayEffect(effectId, duration, effectAsPlayerSelf, characterType,layer,FP.tonumberV1(timeScale),disableTimeLine, callBack) end function ExpEntity:Record_PlayPsEffect(effect, playID) if not self.RenderEntity then return 0 end local entity = self.Entity local mainPlayerSelf = entity:IsPlayerSelf() and entity:IsMainEntityOfPlayer() local characterType = entity._logicInitData.CharacterType local layer = self.components.model.Layer local effectId=UTL.String.GetIdByString(effect) return self.RenderEntity:RecordActorPsEffect(effectId, -1, mainPlayerSelf,characterType,layer, playID) end function ExpEntity:StopPsEffect(effect) if not self.RenderEntity then return end local effectId=UTL.String.GetIdByString(effect) self.RenderEntity:StopEffect(effectId) ExpBatchSystem.RemoveEntityBatchEffect(self.RenderEntity, effectId) end function ExpEntity:BreakPsEffect(effect, isCountEffect, caster) if not self.RenderEntity then return end local effectId=UTL.String.GetIdByString(effect) local shouldBreak = true if isCountEffect then local count = self:GetEffectCount(effect) if count > 1 then shouldBreak = false end if count > 0 then self:ChangeEffectCountOfEntity(effect, caster, -1) end end if shouldBreak then self.RenderEntity:BreakEffect(effectId) ExpBatchSystem.RemoveEntityBatchEffect(self.RenderEntity, effectId) end end function ExpEntity:BreakPsEffectAll() if not self.RenderEntity then return end for k,v in pairs(self._countEffectCountDic) do self._countEffectCountDic[k] = nil end self.RenderEntity:BreakEffect() ExpBatchSystem.RemoveEntityAllBatchEffect(self.RenderEntity) end function ExpEntity:RecoverActorPsEffect() if not self.RenderEntity then return end self:StopRecordActorPsEffect() self.RenderEntity:RecoverActorPsEffect() end function ExpEntity:StopRecordActorPsEffect() if not self.RenderEntity then return end self.RenderEntity:StopRecordActorPsEffect() end function ExpEntity:ClearActorPsEffectRecord() if not self.RenderEntity then return end self.RenderEntity:ClearActorPsEffectRecord() end function ExpEntity:RemoveActorPsEffectRecord(effectStr) if not self.RenderEntity then return end local effectId = UTL.String.GetIdByString(effectStr) self.RenderEntity:RemoveActorPsEffectRecord(effectId) end function ExpEntity:ClearDynamicEffects() if not self.RenderEntity then return end self.RenderEntity:ClearDynamicEffects() end function ExpEntity:ForbidExpEntitySetVisible() self.forbidSetVisible = true end function ExpEntity:ApproveExpEntitySetVisible() self.forbidSetVisible = false end function ExpEntity:SetVisible(visible, contentPet) if not self.RenderEntity then return end if self.forbidSetVisible then return end if self._visible ~= visible then self:PlayHeroLightEffect(self.Entity._logicInitData.LightEffectIDs, visible) end self._visible = visible self.RenderEntity:SetVisible(visible) if self.SubRenderEntityList then for i,renderEntity in ipairs(self.SubRenderEntityList) do renderEntity:SetVisible(visible) end end self:PlayOrStopModelEffect(visible) if visible == false or self.Entity:IsAlive() then EventSystem.Dispatch(EventID.UIBattle_Element_Active, self.RenderEntity, visible) end if contentPet then self:SetPetVisible(visible) end end function ExpEntity:SetPetVisible(visible) if self.PetRenderEntity then self.PetRenderEntity:SetVisible(visible) if visible then self:PlayPetModelEffect(self.petModelData) else self:StopPetModelEffect() end EventSystem.Dispatch(EventID.UIBattle_Element_Active, self.PetRenderEntity, visible) end end function ExpEntity:PlayOrStopModelEffect(isPlay) if not self.RenderEntity then return end if isPlay then local logicInitData = self.Entity._logicInitData local modelData = self.Entity.components.replace:GetCurExpModelData() if not logicInitData.isStatue then -- 雕像不播放特效 self:PlayCurModelEffect(modelData) local characterID, magicWeaponID, isActiveMagicWeapon, weaponBreak, heroBreakNums = logicInitData.CharacterID, logicInitData.MagicWeaponID, logicInitData.IsActiveMagicWeapon, logicInitData.WeaponBreak, logicInitData.HeroBreakNums self:PlayHeroBreakEffect(characterID, heroBreakNums) if self.withMagicWeapon then self:ChangeWeaponEffect(characterID, magicWeaponID, isActiveMagicWeapon, weaponBreak) end end else self:StopCurModelEffect() self:StopHeroBreakEffect() if self.withMagicWeapon then local logicInitData = self.Entity._logicInitData local characterID, magicWeaponID, isActiveMagicWeapon, weaponBreak = logicInitData.CharacterID, logicInitData.MagicWeaponID, logicInitData.IsActiveMagicWeapon, logicInitData.WeaponBreak self:StopWeaponEffect(characterID, magicWeaponID, isActiveMagicWeapon, weaponBreak) end end end --重置角色相机挂点的挂载模式 -- mode=0:默认模式 mode=1:挂载在实体下的模式(吕布戳人用这种模式) function ExpEntity:SetCameraMode(mode) if not self.RenderEntity then return end self.RenderEntity:ResetCameraNode(mode) end -- 这个函数头顶版Create之后 需要调用一下 -- sourceEntity : 当一个entity使用另一个entity的信息创建自己的名字版时用 function ExpEntity:CreateHeadUI(sourceEntity) --增加称号显示 local entity = sourceEntity or self.Entity if entity._logicInitData.CartQuality == 0 then self:SetModelUI_Title(entity._logicInitData.TitleID) else self:SetModelUI_GuildEscort(entity._logicInitData.CartQuality) end --势力显示 self:UpdateModelHeadGuildShow(entity) --国家显示 self:UpdateModelHeadCountryShow(entity) self.hasModelUI = true end function ExpEntity:UpdateModelUIImageColor() local isEnemy = CampManager.IsEnemyCamp(self.Entity:GetCampID(), LevelPlayerManager.MainEntityCampID) local playerSelf = self.Entity:IsPlayerSelf() local mainPlayer = self.Entity:IsMainEntityOfPlayer() local colorType if playerSelf and mainPlayer then colorType = LuaConst.BloodBarColorType.Green else if isEnemy then colorType = LuaConst.BloodBarColorType.Red else colorType = LuaConst.BloodBarColorType.Blue end end self:SetModelUIImageColor(colorType) end function ExpEntity:CreateModel3DUI() if not self.RenderEntity then return false end local isEnemy = CampManager.IsEnemyCamp(self.Entity:GetCampID(),LevelPlayerManager.MainEntityCampID) self.RenderEntity:CreateModel3DUI(isEnemy) return true end function ExpEntity:CreateHurtNumber(num, isPlayerSelf, hurtType) if not self.RenderEntity then return end EventSystem.Dispatch(EventID.UIBattle_HurtNumber3D_Create, self.RenderEntity, num, isPlayerSelf, hurtType) end function ExpEntity:DisposeRenderEntity(renderEntity, needDissolve) EventSystem.Dispatch(EventID.UIBattle_ExpEntity_UIDispose, renderEntity) self.hasModelUI = false renderEntity:DisposeHurtNumber() renderEntity:Dispose(needDissolve) end function ExpEntity:SetModelUIVisible(visible, contentPet) if not self.RenderEntity then return end EventSystem.Dispatch(EventID.UIBattle_Element_Active, self.RenderEntity, visible) if contentPet and self.PetRenderEntity then EventSystem.Dispatch(EventID.UIBattle_Element_Active, self.PetRenderEntity, visible) end end function ExpEntity:SetModel3DUIVisible(visible) if not self.RenderEntity then return end self.RenderEntity:SetModel3DUIVisible(visible) end function ExpEntity:SetModelNo1IconVisible(isVisible) if not self.RenderEntity then return end if isVisible then EventSystem.Dispatch(EventID.UIBattle_Element_SetHeadUI, self.RenderEntity, EntityHeadUIModule.HeadUIType.WorldBossNo1) else EventSystem.Dispatch(EventID.UIBattle_Element_RemoveHeadUI, self.RenderEntity, EntityHeadUIModule.HeadUIType.WorldBossNo1) end end function ExpEntity:SetModelCDTimerVisible(isVisible,countdown) if not self.RenderEntity then return end if isVisible then EventSystem.Dispatch(EventID.UIBattle_Element_SetHeadUI, self.RenderEntity, EntityHeadUIModule.HeadUIType.CDTimer,countdown) else EventSystem.Dispatch(EventID.UIBattle_Element_RemoveHeadUI, self.RenderEntity, EntityHeadUIModule.HeadUIType.CDTimer) end end function ExpEntity:SetModelRivalVisible(visible) if not self.RenderEntity then return end local headUIType = Localization.IsAllChinese() and EntityHeadUIModule.HeadUIType.Rival or EntityHeadUIModule.HeadUIType.RivalNotChinese if visible then EventSystem.Dispatch(EventID.UIBattle_Element_SetHeadUI, self.RenderEntity, headUIType) else EventSystem.Dispatch(EventID.UIBattle_Element_RemoveHeadUI, self.RenderEntity, headUIType) end end function ExpEntity:SetModelFourCountryCrownVisible(visible) if not self.RenderEntity then return end if visible then EventSystem.Dispatch(EventID.UIBattle_Element_SetHeadUI, self.RenderEntity, EntityHeadUIModule.HeadUIType.FourCountryCrown) else EventSystem.Dispatch(EventID.UIBattle_Element_RemoveHeadUI, self.RenderEntity, EntityHeadUIModule.HeadUIType.FourCountryCrown) end end function ExpEntity:SetModelHelpIconVisible(isVisible) if not self.RenderEntity then return end if isVisible then EventSystem.Dispatch(EventID.UIBattle_Element_SetHeadUI, self.RenderEntity, EntityHeadUIModule.HeadUIType.WorldBossHelp) else EventSystem.Dispatch(EventID.UIBattle_Element_RemoveHeadUI, self.RenderEntity, EntityHeadUIModule.HeadUIType.WorldBossHelp) end end function ExpEntity:SetModelUIImageColor(type) if not self.RenderEntity then return end self.modelUIImageColorType = type EventSystem.Dispatch(EventID.UIBattle_HeroElement_SetImageColor, self.RenderEntity, type) end function ExpEntity:SetModelUINameColor(type) if not self.RenderEntity then return end self.modelUINameColorType = type EventSystem.Dispatch(EventID.UIBattle_HeroElement_SetNameColor, self.RenderEntity, type) end function ExpEntity:SetModelUIResScore(score, isFull) if not self.RenderEntity then return end if score > 0 then local content = isFull and UTL.Color.FormatTextByColor("ffe13c", score) or score EventSystem.Dispatch(EventID.UIBattle_Element_SetHeadUI, self.RenderEntity, EntityHeadUIModule.HeadUIType.GuildWar, content) else EventSystem.Dispatch(EventID.UIBattle_Element_RemoveHeadUI, self.RenderEntity, EntityHeadUIModule.HeadUIType.GuildWar) end end --国家标识 function ExpEntity:SetModelUICountry(countryId, countryJob) if self.RenderEntity then if countryId == nil or countryId == MDL.Country.CountryType.None then EventSystem.Dispatch(EventID.UIBattle_Element_RemoveHeadUI, self.RenderEntity, EntityHeadUIModule.HeadUIType.Country) else EventSystem.Dispatch(EventID.UIBattle_Element_SetHeadUI, self.RenderEntity, EntityHeadUIModule.HeadUIType.Country, countryId, countryJob) end end end --大乱斗头顶碎片 function ExpEntity:SetModelUIFightThronePiece(piece) if self.RenderEntity then if piece > 0 then EventSystem.Dispatch(EventID.UIBattle_Element_SetHeadUI, self.RenderEntity, EntityHeadUIModule.HeadUIType.FightThronePiece, piece) else EventSystem.Dispatch(EventID.UIBattle_Element_RemoveHeadUI, self.RenderEntity, EntityHeadUIModule.HeadUIType.FightThronePiece) end end end --大乱斗头顶令旗 function ExpEntity:SetModelUIFightThroneFlag(isVisible) if self.RenderEntity then if isVisible then EventSystem.Dispatch(EventID.UIBattle_Element_SetHeadUI, self.RenderEntity, EntityHeadUIModule.HeadUIType.FightThroneFlag) else EventSystem.Dispatch(EventID.UIBattle_Element_RemoveHeadUI, self.RenderEntity, EntityHeadUIModule.HeadUIType.FightThroneFlag) end end end --龙脉图腾-头顶UI function ExpEntity:SetModelUIDragonArteryTotem(isVisible) if self.RenderEntity then if isVisible then EventSystem.Dispatch(EventID.UIBattle_Element_SetHeadUI, self.RenderEntity, EntityHeadUIModule.HeadUIType.DragonArteryTotem) else EventSystem.Dispatch(EventID.UIBattle_Element_RemoveHeadUI, self.RenderEntity, EntityHeadUIModule.HeadUIType.DragonArteryTotem) end end end --龙脉大将-头顶UI function ExpEntity:SetModelUIDragonArteryGeneral(isVisible) if self.RenderEntity then if isVisible then EventSystem.Dispatch(EventID.UIBattle_Element_SetHeadUI, self.RenderEntity, EntityHeadUIModule.HeadUIType.DragonArteryGeneral) else EventSystem.Dispatch(EventID.UIBattle_Element_RemoveHeadUI, self.RenderEntity, EntityHeadUIModule.HeadUIType.DragonArteryGeneral) end end end --城池战-冲车的状态。 FEATUREID_CHONGCHE = 622001 ; local CityWarCrushCar2ExpItemID = {[62200121] = 2406, [62200122] = 2407} function ExpEntity:SetModelUICrushCar(isRunning, isAttack, isExpMonster) --Idle是灰色,Run是蓝色或者红色,AttackGate是蓝色或者红色 if self.RenderEntity then local state = LuaConst.ChangAnRushHUDState.Idle -- 停止行走 if isRunning then state = LuaConst.ChangAnRushHUDState.Run elseif isAttack then state = LuaConst.ChangAnRushHUDState.AttackGate end local toRenderEntity = self.RenderEntity if isExpMonster then local bornItemID = self.Entity._logicInitData.OriginBornItemID local list = LevelManager.CurLevelFunc.crushCarList for _, carEntity in ipairs(list) do local crushCarID = carEntity:GetCharacterID() if (bornItemID == 2406 and crushCarID == 62200121) or (bornItemID == 2407 and crushCarID == 62200122) then -- 没办法,除非让策划改AI和关卡配置,qa再增加一些测试case toRenderEntity = carEntity.ExpEntity.RenderEntity break end end end EventSystem.Dispatch(EventID.UIBattle_Element_SetHeadUI, toRenderEntity, EntityHeadUIModule.HeadUIType.ChangAnCarState, state) EventSystem.Dispatch(EventID.UIBattle_Element_SetExtendData, toRenderEntity, "UseZoom",false) EventSystem.Dispatch(EventID.UIBattle_Element_SetExtendData, toRenderEntity, "MaxDistSqrModelUI",300*300) end end --城池战-塔的状态。 local FEATUREID_TOWER_EMPTY = 622021 --基座的featureid function ExpEntity:SetModelUIDefendTower() if self.RenderEntity then local state = 1 -- 未建造 if self.Entity.featureID ~= 622021 then -- 基座属于未建造 if not self.hasModelUI then return end if self.Entity.components.drive.BeDrived then state = 3 -- 有人驾驶 else state = 2 -- 建造但没人驾驶 end end EventSystem.Dispatch(EventID.UIBattle_NameElement_Create, self, nil) if BattleDataGetter.GetMyCampID() == BattleDataGetter.GetCityWarDefendCampID() then EventSystem.Dispatch(EventID.UIBattle_Element_SetHeadUI, self.RenderEntity, EntityHeadUIModule.HeadUIType.ChangAnSiegeDefendTowerState, state) else EventSystem.Dispatch(EventID.UIBattle_Element_SetHeadUI, self.RenderEntity, EntityHeadUIModule.HeadUIType.ChangAnSiegeAttackTowerState, state) end local offset = state == 1 and 0 or -2.5 EventSystem.Dispatch(EventID.UIBattle_Element_OffsetY, self.RenderEntity, offset) EventSystem.Dispatch(EventID.UIBattle_Element_SetExtendData, self.RenderEntity, "UseZoom",false) EventSystem.Dispatch(EventID.UIBattle_Element_SetExtendData, self.RenderEntity, "MaxDistSqrModelUI", 85*85) end end --城池战-攻击型载具的驾驶状态。 function ExpEntity:SetModelUIAttackVehicle() if self.RenderEntity then EventSystem.Dispatch(EventID.UIBattle_NameElement_Create, self, nil) EventSystem.Dispatch(EventID.UIBattle_Element_SetHeadUI, self.RenderEntity, EntityHeadUIModule.HeadUIType.ChangAnVehicle, self.Entity.components.drive.BeDrived) EventSystem.Dispatch(EventID.UIBattle_Element_OffsetY, self.RenderEntity, -1.5) EventSystem.Dispatch(EventID.UIBattle_Element_SetExtendData, self.RenderEntity, "UseZoom",false) EventSystem.Dispatch(EventID.UIBattle_Element_SetExtendData, self.RenderEntity, "MaxDistSqrModelUI", 85*85) end end function ExpEntity:SetModelUI_HP(hp, pc, maxHp, init) if not self.RenderEntity then return end EventSystem.Dispatch(EventID.UIBattle_Element_UpdateHP, self.RenderEntity, hp, pc, maxHp, init) self.RenderEntity:SetModel3DUIHP(hp, pc, maxHp, init) end function ExpEntity:SetModelUI_AM(am, maxAm, init) if not self.RenderEntity then return end EventSystem.Dispatch(EventID.UIBattle_GeneralElement_UpdateArmor, self.RenderEntity, am, maxAm, init) end function ExpEntity:SetPetUI_Name(name) if not self.PetRenderEntity then return end EventSystem.Dispatch(EventID.UIBattle_Element_ChangeName, self.PetRenderEntity, name) end function ExpEntity:SetModelUI_Name(name) if not self.RenderEntity then return end EventSystem.Dispatch(EventID.UIBattle_Element_ChangeName, self.RenderEntity, name) end function ExpEntity:ChangeModelUI_NameColor(color) if not self.RenderEntity then return end if self.curNameColor == color then return end local newColorName = self:GetPlayerModelName(color) EventSystem.Dispatch(EventID.UIBattle_Element_ChangeColorName, self.RenderEntity, newColorName) end -- sourceEntity : 当一个entity使用另一个entity的信息创建自己的名字版时用 function ExpEntity:UpdateModelHeadGuildShow(sourceEntity) if not self.RenderEntity then return end EventSystem.Dispatch(EventID.UIBattle_Element_RemoveHeadUI, self.RenderEntity, EntityHeadUIModule.HeadUIType.Guild) if not BattleDataGetter.IsShowHeadUI_Guild() then return end local entity = sourceEntity or self.Entity if not entity._logicInitData.isStatue then if not entity:IsHero() and not entity:IsIllusion() then return end if entity:IsMainEntityOfPlayer() == false and not entity._logicInitData.isSyncMove then --如果是自己,必须是主单位才显示(雕像除外) return end end local guildName, guildEmblemFrame, guildEmblemContent, guildJob, guildIdentity = self:GetPlayerModelGuildInfo(entity) if string.isNilOrEmpty(guildName) == false then local countryId = BattleDataGetter.GetEntityCountryInfo(entity) if BattleDataGetter.IsShowHeadUI_Country() and (countryId and countryId > MDL.Country.CountryType.None) and BattleDataGetter.IsTownLevel() == false then local framePath, emblemContent, guildName, jobIDS = CTL.Guild.GetGuildDetailParam(guildEmblemFrame, guildEmblemContent, guildName, guildJob, guildIdentity) local guildDesc = CTL.Guild.GetBattleGuildDesc(guildName, jobIDS) EventSystem.Dispatch(EventID.UIBattle_Element_SetHeadUI, self.RenderEntity, EntityHeadUIModule.HeadUIType.Guild, nil, emblemContent, guildDesc) else local framePath, emblemContent, guildDesc = CTL.Guild.GetModelNameShowParam(guildEmblemFrame, guildEmblemContent, guildName, guildJob, guildIdentity) EventSystem.Dispatch(EventID.UIBattle_Element_SetHeadUI, self.RenderEntity, EntityHeadUIModule.HeadUIType.Guild, framePath, emblemContent, guildDesc) end --可能改了名字长度,导致国家UI不适配,重新计算一下 EventSystem.Dispatch(EventID.UIBattle_Element_RefreshHeadUI, self.RenderEntity) end end --获取头顶名字前缀(可能是官职、也可能是国家职位) function ExpEntity:GetModelNamePrefix(countryId, countryJob, officialPosition) if BattleDataGetter.IsShowHeadUI_Country() and countryJob and countryJob > 0 then --如果是平民隐藏职位 if countryJob == MDL.Country.CountryJob.CountryPopulace then return " " end return CTL.Country.GetColorHeadJobName(countryId, countryJob) end return CTL.OfficialPosition.GetModelNameShow(officialPosition) end function ExpEntity:UpdateModelHeadCountryShow(sourceEntity) if not self.RenderEntity then return end if BattleDataGetter.IsShowHeadUI_Country() then local entity = sourceEntity or self.Entity if not entity:IsHero() and not entity:IsIllusion() then return end if entity._logicInitData.IsPlayerSelf and entity:IsMainEntityOfPlayer() == false then --如果是自己,必须是主单位才显示 return end local countryId, countryJobId = BattleDataGetter.GetEntityCountryInfo(entity) self:SetModelUICountry(countryId, countryJobId) else self:SetModelUICountry(nil) end EventSystem.Dispatch(EventID.UIBattle_Element_RefreshHeadUI, self.RenderEntity) end function ExpEntity:SetModelUI_GuildEscort(quality) if not self.RenderEntity then return end if quality == self._guildEscortQuality then return end self._guildEscortQuality = quality if quality == 0 then if self._expTitleID == 0 then EventSystem.Dispatch(EventID.UIBattle_Element_RemoveHeadUI, self.RenderEntity, EntityHeadUIModule.HeadUIType.Title) else local oldExpTitleID = self._expTitleID self._expTitleID = 0 -- 这里先重置一下, 防止刷新拦截 self:SetModelUI_Title(oldExpTitleID) end else EventSystem.Dispatch(EventID.UIBattle_Element_SetHeadUI, self.RenderEntity, EntityHeadUIModule.HeadUIType.Title, CTL.GuildEscort.GetGuildEscortTitle(quality)) end end function ExpEntity:GetGuildEscortQuality() return self._guildEscortQuality end function ExpEntity:SetModelUI_Title(titleID) if not self.RenderEntity then return end if titleID == self._expTitleID then return end self._expTitleID = titleID if self._guildEscortQuality == 0 then if titleID == 0 then EventSystem.Dispatch(EventID.UIBattle_Element_RemoveHeadUI, self.RenderEntity, EntityHeadUIModule.HeadUIType.Title) else EventSystem.Dispatch(EventID.UIBattle_Element_SetHeadUI, self.RenderEntity, EntityHeadUIModule.HeadUIType.Title, CTL.Title.GetEntityTitleParam(titleID)) end end end -- 设置势力战的炸弹显示 function ExpEntity:SetModelUI_GuildBossBomb(visible, time) if not self.RenderEntity then return end if visible then EventSystem.Dispatch(EventID.UIBattle_Element_SetHeadUI, self.RenderEntity, EntityHeadUIModule.HeadUIType.GuildWarBomb, time) else EventSystem.Dispatch(EventID.UIBattle_Element_RemoveHeadUI, self.RenderEntity, EntityHeadUIModule.HeadUIType.GuildWarBomb) end end function ExpEntity:SetModelUI_PetTitle() -- isLineUp = 5; //宠物是否在槽位上(只有在槽位上的才显示称号) -- aptitudeSum = 6; //资质总和 -- runeSkillLevelSum = 7; //符文技能等级总和 local initData = self.Entity._logicInitData local result, content = BattleDataGetter.GetPetTitleContent(initData.PetIsLineUp, initData.PetRuneSkillLevelSum, initData.PetAptitudeSum) if result then EventSystem.Dispatch(EventID.UIBattle_Element_SetHeadUI, self.PetRenderEntity, EntityHeadUIModule.HeadUIType.PetTitle, content) else EventSystem.Dispatch(EventID.UIBattle_Element_RemoveHeadUI, self.PetRenderEntity) end end function ExpEntity:TopShowTitle() if not self.RenderEntity then return end EventSystem.Dispatch(EventID.UIBattle_Element_TopShowTitle, self.RenderEntity) end function ExpEntity:SetSoundListener(active) if not self.RenderEntity then return end self.RenderEntity:SetSoundListener(active) end --播放上马的特效,特效挂在马身上 function ExpEntity:PlayHorseEffect(horseEffect) if not self.RenderEntity then return end self.RenderEntity:PlayHorseEffect(horseEffect) end function ExpEntity:RideHorse(horsePath, horseShowEffect, horseScale) if not self.RenderEntity then return end self:UpdateFootEffectInterval() self.RenderEntity:RideHorse(horsePath, horseShowEffect, horseScale) if self.needStandOnHorse then EventSystem.Dispatch(EventID.UIBattle_Element_OffsetY, self.RenderEntity, CONST_HALFMODELHIGHT) -- 名字板上移半身高(约是1.2米) end end function ExpEntity:OffHorse() if not self.RenderEntity then return end self:UpdateFootEffectInterval() self.RenderEntity:OffHorse() if self.needStandOnHorse then EventSystem.Dispatch(EventID.UIBattle_Element_OffsetY, self.RenderEntity, nil) -- 名字板上移半身高(约是1.2米) end --潜规则,如果模型配置了animator2,则在下马时得替换为animator2 local modelData = self.Entity.components.replace:GetCurExpModelData() if modelData.AnimCtlID2 and modelData.AnimCtlID2 ~= "" then local logicInitData = self.Entity._logicInitData local ctrlPathId, animAppendId = 0,0 if string_isNilOrEmpty(modelData.AnimAppend) then ctrlPathId = UTL.String.GetIdByString(self:GetAnimatorCtrlPath(logicInitData.CharacterType, modelData, nil, 2)) else animAppendId = UTL.String.GetIdByString(modelData.AnimAppend) end self.RenderEntity:SetModelAnimator(ctrlPathId, animAppendId) end end function ExpEntity:SetModelLocalEulerX(eulerX,cameraRotateMode) if not self.RenderEntity then return end if GameAppInfo.IsVersionGreaterThan19000() then self.RenderEntity:SetModelLocalEulerX(eulerX,cameraRotateMode) else self.RenderEntity:SetModelLocalEulerX(eulerX) end end function ExpEntity:StartConfrontation(against, callback) if not self.RenderEntity or not against.RenderEntity then return end self.RenderEntity:PlayConfrontationEffect(against.RenderEntity, callback) end function ExpEntity:LookAtTarget(target) if not self.RenderEntity then return end self.RenderEntity:LookAtTarget(target) end function ExpEntity:SetOverrideTargetDirToTarget(targetRenderEntity) if self.RenderEntity and targetRenderEntity then self.RenderEntity:SetOverrideTargetDirToTarget(targetRenderEntity) end end --在RenderEntity的位置播放3D音效 function ExpEntity:PlayObjSound(name) if not self.RenderEntity then return end self.battleEffect3DSound = CTL.Sound.PlayObjSound(name, self.RenderEntity) end --停止RenderEntity的位置播放3D音效 function ExpEntity:StopObjSound(stopTime) if self.battleEffect3DSound then self.battleEffect3DSound = CTL.Sound.StopByIdWithTime(self.battleEffect3DSound, stopTime) self.battleEffect3DSound = nil end end function ExpEntity:PlayObject(path) if not self.RenderEntity or string_isNilOrEmpty(path) then return end local pathID = UTL.String.GetIdByString(path) self.RenderEntity:PlayObject(pathID) end function ExpEntity:StopObject(path) if not self.RenderEntity or string_isNilOrEmpty(path) then return end local pathID = UTL.String.GetIdByString(path) self.RenderEntity:StopObject(pathID) end --endregion function ExpEntity:TryStopJoystickAimEffect() if self.joystickTarget and self.joystickTargetAimEffect then SystemManager.OnBreakPSEffect(self.joystickTarget, self.joystickTargetAimEffect, true) end self.joystickTargetAimEffect = nil self.joystickTarget = nil end function ExpEntity:OnDead() self:TryStopJoystickAimEffect() end function ExpEntity:GetCurUINameOffsetY() if self.Entity.components.buff:CheckHasBuffState(LuaConst.SpecialBuffs.InRiding) then if self.needStandOnHorse then return CONST_HALFMODELHIGHT end end return nil end -- 当跟随状态改变时(包括骑乘状态) isFollow表示当前是否在跟随,followSpd表示跟随状态下的速度 function ExpEntity:OnFollowStateChange(isFollow, followSpd) local effectPathID, footEffectInterval = self:GetFootEffectData() if effectPathID == nil then --说明此时没有装备脚底特效 return end footEffectInterval = self:GetFootInterval(isFollow, followSpd, footEffectInterval) self:ChangeFootEffectInterval(effectPathID, footEffectInterval) end function ExpEntity:GetFootEffectData() for i, id in ipairs(self.components.model.lightEffectIDs) do local lightEffectData = DataSheetManager.LightEffect:GetDataByID(id) if lightEffectData.PlayPsType == LuaConst.LightEffectType.Footprint then local effectName = lightEffectData.EffectName local interval = lightEffectData.Interval local effectPathID = UTL.String.GetIdByString(effectName) return effectPathID, interval end end return nil end function ExpEntity:GetFootInterval(isFollow, followSpd, oldInterval, intervalScale) if not intervalScale then intervalScale = 1 end local interval = oldInterval if isFollow then local curSpeed = nil if self.Entity:CheckHasBuffState(LuaConst.SpecialBuffs.InRiding) then curSpeed = FP.tonumberV1(self.Entity.components.attr:GetAttrValue(LuaConst.AttrType.ridespd)) ---骑马跑步 else curSpeed = FP.tonumberV1(self.Entity.components.attr:GetAttrValue(LuaConst.AttrType.spd)) --- 不骑马跑步 end interval = (curSpeed / followSpd) * oldInterval interval = interval * intervalScale else end return interval end function ExpEntity:ChangeFootEffectInterval(effectPathID, footEffectInterval) self.RenderEntity:StopFootprintEffect() self.RenderEntity:StarFootprintEffect(effectPathID, footEffectInterval) end function ExpEntity:UpdateFootEffectInterval() local isFollow = TownCartManager.IsFollowingNPC(self.Entity) if isFollow then local acid = SyncMoveManager.GetAcIdOfEntity(self.Entity) local cartUniqId = TownCartManager.FollowDic[acid] local _, _, followSpeed = SyncMoveManager.GetObjectMoveTargetPosAndSpeed(cartUniqId) self:OnFollowStateChange(isFollow, followSpeed / LuaConst.TimeSpan) end end --加载renderEntity的通用方法 --TODO:暂时整合LevelItem_XXX重复的代码,ExpEntity中涉及多个版本的代码,后续再处理 function ExpEntity.LoadRenderEntity(modelData, withWeapon, px, pz, dx, dz, ...) local renderEntity = AuxUtil.LoadRenderEntity(...) if renderEntity then renderEntity:SetTrans(px, pz, dx, dz) local ctrlPath = ExpEntity.GetAnimatorCtrlPathByModelData(modelData) local equipmentID = modelData.EquipmentID local pathId, combinePathId = 0, 0 local combinePath = modelData.CombinePath if string_isNilOrEmpty(combinePath) then pathId = UTL.String.GetIdByString(modelData.Path) else combinePathId = UTL.String.GetIdByString(modelData.CombinePath) end local ctrlPathId, animAppendId = 0, 0 if string_isNilOrEmpty(modelData.AnimAppend) then ctrlPathId = UTL.String.GetIdByString(ctrlPath) else animAppendId = UTL.String.GetIdByString(modelData.AnimAppend) end local materialId = -1 if not string_isNilOrEmpty(modelData.material) then materialId = UTL.String.GetIdByString(modelData.material) end if renderEntity:SetModel(modelData.ID, pathId, combinePathId, modelData.ModelScale, ctrlPathId, animAppendId, materialId, modelData.VisualCost, modelData.DmgNumHeight, modelData.ModelSizeRate) then if withWeapon then ExpEntity.CreateEquipPart(renderEntity, modelData.ID, equipmentID) end end renderEntity:SetVisible(true) return renderEntity end return nil end function ExpEntity.GetAnimatorCtrlPathByModelData(modelData) local animCtrlPath = modelData.AnimCtlPath if animCtrlPath and animCtrlPath ~= "" then return animCtrlPath end local modelPath = modelData.Path local animCtlID = modelData.AnimCtlID if string.isNilOrEmpty(modelPath) == false and string.isNilOrEmpty(animCtlID) == false then animCtrlPath = string.match(modelPath, "^(.*)/") .. "/" .. animCtlID .. ".controller" end return animCtrlPath end return ExpEntity