local ConditionAnalysis = require "Battle/Logic/AI/Condition/ConditionAnalysis" local EventSystem = require("Event/EventSystem") local HurtFormulaStepEnumSaChange = LuaConst.HurtFormulaStepEnum.Step_SaChange local TriggerMissileSystem = {} local CheckBuffImmune = BuffManager.CheckBuffImmune local private = { } local ECantTriggerReason = { UNKNOW = nil, BLIND = 1, } local ipairs = ipairs local tonumberV2=FP.tonumberV2 local newV2=FP.newV2 local tonumberV1=FP.tonumberV1 local newV1=FP.newV1 local Const_Zero=FP.Const.Zero local releaseV2=FP.releaseV2 local _tempV1 = newV1(0) local RADIUS_CALC_DIAX_THRESHOLD = 2 local _tempHitEntityList = {} local LuaConst=LuaConst local PetMissileGroupDic = LuaConst.PetMissileGroupDic local LuaConst_CheckBattleLogType_Missile=LuaConst.CheckBattleLogType.Missile local LuaConst_MissileImpactType_Enemy=LuaConst.MissileImpactType.Enemy local LuaConst_MissileImpactType_Friend=LuaConst.MissileImpactType.Friend local LuaConst_MissileImpactType_Self=LuaConst.MissileImpactType.Self local LuaConst_MissileImpactType_Team=LuaConst.MissileImpactType.Team local LuaConst_MissileImpactType_EnemyAndFriend = LuaConst.MissileImpactType.EnemyAndFriend local LuaConst_MissileImpactType_NoPeace=LuaConst.MissileImpactType.NoPeace local LuaConst_MissileImpactType_TargetIfHas=LuaConst.MissileImpactType.TargetIfHas local LuaConst_CharacterType_Hero=LuaConst.CharacterType.Hero local LuaConst_CharacterType_Adjutant=LuaConst.CharacterType.Adjutant local LuaConst_CharacterType_Illusion=LuaConst.CharacterType.Illusion local LuaConst_SpecialBuffs_InWeakHit=LuaConst.SpecialBuffs.InWeakHit local LuaConst_SpecialBuffs_InDying=LuaConst.SpecialBuffs.InDying local LuaConst_SpecialBuffs_InFlyFlyingMonster=LuaConst.SpecialBuffs.InFlyFlyingMonster local LuaConst_SpecialBuffs_InHitFlyMonster=LuaConst.SpecialBuffs.InHitFlyMonster local LuaConst_SpecialBuffs_InHitUp=LuaConst.SpecialBuffs.InHitUp local LuaConst_SpecialBuffs_CantBeTrigger = LuaConst.SpecialBuffs.CantBeTrigger local Const_NegOne=FP.Const.NegOne local Math_Abs=FP.Math.Abs local table_insert=table.insert local table_remove=table.remove local DmgStartFrameLate = FP.newV1(2000) -- 2秒以上开始伤害的 ,认为是伤害开始晚 -- 需要每次计算伤害前算下可触碰列表 local DmgDurationLong = FP.newV1(2000) -- 子弹伤害时长大约2秒认为 是 持续时间长 --需要每次计算伤害前算下可触碰列表 local SetTriggerListInterval = FP.newV1(1000) -- 但子弹需要刷新碰撞列表是 ,刷新间隔不能低于这个值 (1秒) local temp_subV1 = FP.newV1(0) --[[ 子弹发射 --]] function TriggerMissileSystem.OnMissileFire(missile) missile.TriggerList = {} missile.IgnoreAttacker = false local missileData = missile.MissileData if not missile.IsTracker and (missileData.DamageStartFrame >= DmgStartFrameLate or temp_subV1:Reset(missileData.DamageEndFrame):Sub(missileData.DamageStartFrame) >= DmgDurationLong) then missile.UpdateTriggerList_Damage = true -- 目的:修复问题:子弹很晚才有伤害或者伤害时间很长 ,在子弹出生后出现的怪物就不会被子弹打到了 missile.LastSetTriggerListTime = FP.newV1(-1000000) -- -1000000 是为了保证 本子弹第一次SetTriggerList能够执行到 missile.SetTriggerListInterval = missileData.DamageIntervalFrame:cloneV1() if missileData.DamageIntervalFrame < SetTriggerListInterval then missile.SetTriggerListInterval:Reset(SetTriggerListInterval) end else TriggerMissileSystem.SetTriggerList(missile) end end function TriggerMissileSystem.SetTriggerList(missile) local missileData = missile.MissileData local impactType = missileData.ImpactType if impactType == LuaConst_MissileImpactType_Self then --自己 table_insert(missile.TriggerList, {missile.Attacker}) elseif impactType == LuaConst_MissileImpactType_Enemy then --敌方 --logging.error(LTAG.ERROR, "HYW : 1111111 :", impactType, " missile.Attacker:", missile.Attacker.EntityID) missile.TriggerList = TargetManager.Get2DNoFriendList(missile.Attacker)--new 这个地方(下面一样)会产生一个新的table,是否优化? elseif impactType == LuaConst_MissileImpactType_Friend --友方 or impactType == LuaConst_MissileImpactType_Team then --自己+友方 local newTriggerList = TargetManager.Get2DFriendList(missile.Attacker) --new missile.TriggerList = newTriggerList -- new missile.IgnoreAttacker = impactType == LuaConst_MissileImpactType_Friend elseif impactType == LuaConst_MissileImpactType_EnemyAndFriend then missile.TriggerList = TargetManager.Get2DNoPeaceListCopy() local removed = false for i,list in ipairs(missile.TriggerList) do for j,entity in ipairs(list) do if entity == missile.Attacker then removed = true table.remove(list, j) break end end if removed then break end end elseif impactType == LuaConst_MissileImpactType_NoPeace then missile.TriggerList = TargetManager.Get2DNoPeaceList() end -- 以下代码不适合在这个地方:原因missile.TriggerList 不全是copy的,不能直接做修改 --[[local impactConditionStr = missile.MissileData.ImpactCondition if not string.isNilOrEmpty(impactConditionStr) then -- 这个判断要加 ,因为空字符串的条件回返回true local conditionTree = ConditionManager.GetConditionDataTree(impactConditionStr) local count = #missile.TriggerList for i = count, 1, -1 do if not ConditionManager.MeetCondition(missile.TriggerList[i], conditionTree, missile) then table.remove(missile.TriggerList, i) else logging.error(LTAG.ERROR, " 可撞 : ", missile.TriggerList[i].EntityID) end end end--]] end local _tempfixp2_a = newV2(0,0) local _tempfixp2_b = newV2(0,0) local _tempfixp2_c = newV2(0,0) --[[ 子弹Tick --]] function TriggerMissileSystem.OnMissileUpdate(missile) local isInDamageRange = private.InDamageTimeRange(missile) if missile.hookEntity ~= nil then -- missile:IsHooked() --如果钩住目标了,需要刷新钩子的形状,即便isInDamageRange为false(注意仅刷新钩子形状) local targetPos = missile.hookEntity:GetLogicPos() local startPos = missile.hookStartEntity:GetLogicPos() local delta = _tempfixp2_a local newPos = _tempfixp2_b local dir = _tempfixp2_c delta:Reset(targetPos):Sub(startPos) newPos:Reset(delta):Mul(0.5):Add(startPos) local size = delta:Magnitude() size:Add(0.1) --钩子稍微加大一点,让钩子稳定能覆盖住钩子的目标,保持一致性 dir:Reset(delta):Normalize() missile.CurMissileShape.SetMissileTrigger(nil, newPos, dir) if missile.CurMissileShape.SetMissileHeight then missile.CurMissileShape.SetMissileHeight(missile,size) end end if isInDamageRange then if missile.UpdateTriggerList_Damage then -- 重新设置能打到的entity列表 if temp_subV1:Reset(missile.CurTime):Sub(missile.LastSetTriggerListTime) >= missile.SetTriggerListInterval then TriggerMissileSystem.SetTriggerList(missile) missile.LastSetTriggerListTime:Reset(missile.CurTime) end end private.SetMultiHit(missile) --清空上次撞击缓存 for i = #_tempHitEntityList ,1 ,-1 do table_remove(_tempHitEntityList) end local needDestroy = false if missile.hookEntity == nil then -- not missile:IsHooked() missile.CurMissileShape.SetMissileTrigger(missile.MissileData,missile.Pos, missile.MoveDir) end for key,entityList in ipairs(missile.TriggerList) do for i,hitEntity in ipairs(entityList) do --TODO 非激活的实体,理想情况下应该从源头就排除掉,不要参与任何战斗计算;放到底层再加状态判断跳出,还是会产生一定的损耗 if hitEntity.components.base.IsActive then needDestroy = private.TryToTrigger(missile, hitEntity) if needDestroy then break end end end if needDestroy then break end end -- CompareSyncLogManager.TryColectLog(LuaConst_CheckBattleLogType_Missile , missile , _tempHitEntityList ) --子弹撞到了人,被撞人的效果 for i , hitEntity in ipairs(_tempHitEntityList) do private.AddBuffEffect(missile,hitEntity) end --子弹撞到了人,发射子弹者的效果 if not missile.HasHit then if #_tempHitEntityList > 0 then missile.HasHit = true private.HitOnceEffectToSource(missile, _tempHitEntityList[1]) end end --添加无双值 if #_tempHitEntityList > 0 then if missile.MissileData.IsOnceSA then if not missile.HasAddSA then missile.HasAddSA = true private.AddOnceSA(missile) end else private.AddOnceSA(missile) end end if needDestroy then missile:Cancelled() end end end --[[ 记录伤害数,清除上次的碰撞entity列表 --]] function private.SetMultiHit(missile) if missile.MissileData.IsStartWhenTrigger or (missile.IsTracker and not missile.InFreeFly) then local timeOffset = missile.CurTime[1] - missile.MissileData.DamageIntervalFrame[1] -- 为了省内存用了【1】 for eid,lastHitTime in pairs(missile.HitEntityIdList) do if timeOffset >= lastHitTime then missile.HitEntityIdList[eid] = nil end end end missile.CurFrameHitEntityCount = 0 table.clearArray(missile.CurFrameHitEntityIdList) end function TriggerMissileSystem.TryTriggerHookMissile(missile) local canTrigger, cantTriggerReason = private.CheckCanTrigger(missile, missile.hookEntity, true) if canTrigger then private.AddBuffEffect(missile, missile.hookEntity) else if cantTriggerReason == ECantTriggerReason.BLIND then private.OnCantTriggerBecauseBlind(missile, missile.hookEntity) end end canTrigger, cantTriggerReason = private.CheckCanTrigger(missile, missile.hookStartEntity, true) if canTrigger then private.AddBuffEffect(missile, missile.hookStartEntity) else if cantTriggerReason == ECantTriggerReason.BLIND then private.OnCantTriggerBecauseBlind(missile, missile.hookStartEntity) end end end --[[ 尝试触发 --]] function private.TryToTrigger(missile, hitEntity) local canTrigger, cantTriggerReason = private.CheckCanTrigger(missile, hitEntity) if canTrigger then missile:OnHitEntity(hitEntity) table_insert(_tempHitEntityList,hitEntity) --尝试销毁子弹 local destroy = private.CanTriggerDestroy(missile, hitEntity) return destroy else if cantTriggerReason == ECantTriggerReason.BLIND then private.OnCantTriggerBecauseBlind(missile, hitEntity) end end return false end function private.OnCantTriggerBecauseBlind(missile, hitEntity) if missile.Attacker then missile.Attacker.ExpEntity:OnCantTriggerBecauseBlind(missile, hitEntity) end end function private.CanTriggerDestroy(missile, hitEntity) local can = false --碰撞次数检测 if missile:IsHook() then can = false --钩子子弹不走碰撞次数 else local totalTrigger = missile.MissileData.TriggerCountToDestroy if totalTrigger > 0 then if missile.TotalHitEntityCount >= totalTrigger then can = true end end local destroyConditionStr = missile.MissileData.DestroyConditionStr if (not can) and (not string.isNilOrEmpty(destroyConditionStr))then -- 这个判断要加 ,因为空字符串的条件回返回true local conditionTree = ConditionManager.GetConditionDataTree(destroyConditionStr) if ConditionManager.MeetCondition(hitEntity, conditionTree,missile) then can = true end end end return can end --[[ 检测能否触发 --]] function private.CheckCanTrigger(missile, hitEntity, isHook) --水平碰撞检测 local radius = 0 local ShoveDiameterX = hitEntity.components.base.CurModelData.ShoveDiameterX if ShoveDiameterX > RADIUS_CALC_DIAX_THRESHOLD then _tempV1:Reset(ShoveDiameterX):Mul(0.5) radius = tonumberV1(_tempV1) end if not isHook and not missile.CurMissileShape.CanEnterTrigger(missile, hitEntity.components.move.LogicPos,radius) then return false end local attacker = missile.Attacker if attacker then if attacker.components.target:IsIgnoreEnemey(hitEntity) then --忽略判定 return false end if hitEntity.isOnlyTriggerByMaster and attacker ~= hitEntity._logicInitData.RootMasterEntity then return false end end local missileData = missile.MissileData --当只打目标时,检测的这个entity不是目标 if missileData.OnlyHitTarget then if missileData.OnlyHitTarget == 1 or missileData.OnlyHitTarget == true then --以前OnlyHitTarget是bool类型,后来为了拓展改为了int类型,这里依旧保留对bool值的判断,向前兼容 local target = missile.IsTracker and missile.TrackerTarget or attacker.components.target.Target if not target or target ~= hitEntity then return false end elseif missileData.OnlyHitTarget == 2 then if hitEntity ~= missile.TrackerTarget then return false end end end if missile.IgnoreAttacker and attacker == hitEntity then return false end local condStr = missileData.ImpactCondition if not (condStr == nil or condStr == "") then -- 这个判断要加 ,因为空字符串的条件回返回true local conditionTree = ConditionManager.GetConditionDataTree(condStr) if not ConditionManager.MeetCondition(hitEntity, conditionTree, missile) then return false end end --排除 怪物配置表中的不能被撞,未激活 if not private.MatchState(hitEntity) then return false end --检测时间间隔 if missileData.IsStartWhenTrigger or missile.IsTracker then if missile.HitEntityIdList[hitEntity._logicInitData.EntityID] then return false end end --检测碰撞 --高度落差检测 if missileData.ColliderY > Const_Zero then if Math_Abs(_tempV1:Reset(missile.PosY):Sub(hitEntity.components.move:GetLogicPosY()) ) > missileData.ColliderY then return false end end if attacker and attacker.components.record.BlindFlagCount > 0 and CampManager.IsEnemyEntity(attacker,hitEntity) then --2022年9月26日 使用自身的致盲标记,这能解决一些bug,但是也会导致看上去是子弹的怪不受致盲影响 --致盲判定 return false, ECantTriggerReason.BLIND end return true end function private.MatchState(tempEntity) if not tempEntity.components.base.IsActive then --未激活 return false end -- 死亡的主将不能被子弹打中,否则出现受击光和声音 if (tempEntity.isHero or tempEntity.isIllusion) and tempEntity.components.attr.hp <= Const_Zero then return false end if tempEntity.components.buff:GetBuffUpdateData(LuaConst_SpecialBuffs_CantBeTrigger) then return false end return true end --[[ 是否在伤害时间内 --]] function private.InDamageTimeRange(missile) if missile.IsTracker then -- 追踪弹在自由飞行阶段不碰撞 return not missile.InFreeFly end local missileData = missile.MissileData if missileData.TriggerOnlyBeforeDie then return _tempV1:Reset(missile.CurTime):Add(LuaConst.TimeSpanMs) >= missile.TotalTime else local inHitTime = missile.CurTime >= missileData.DamageStartFrame and missile.CurTime < missileData.DamageEndFrame or (missileData.DamageEndFrame > Const_Zero and missile.LastTime < missileData.DamageStartFrame and missile.CurTime >= missileData.DamageEndFrame)--防止伤害因为时间加速被吞掉 -- 检测伤害间隔 if missile.MissileData.IsStartWhenTrigger then -- 以人为基础记录时间间隔 return inHitTime elseif inHitTime then -- 以子弹为基础记录生效间隔 -- if missile.CurTime[1] - missile.LastHitTime >= missile.MissileData.DamageIntervalFrame[1] then missile.LastHitTime = missile.CurTime[1] return true end end return false end end -- 子弹产生的各种效果 function private.AddBuffEffectByMissileBuffDataTable(buffDatas, missile, attacker, hitEntity) for i,buffData in ipairs(buffDatas) do if buffData.BuffID > 0 then if buffData.MaxCount == nil or buffData.MaxCount <= 0 or missile:GetMissileBuffDataAddedCount(buffData) < buffData.MaxCount then local canAddEntity = private.CheckBuffCanAddtoEntity(buffData.TriggerTargetType ,attacker, hitEntity, missile, buffData.ConditionAimType, buffData.ConditionStr) if canAddEntity then local missileBuffCtrl = RuntimeDataManager.New_BuffCtrl() if buffData.BuffFormula and buffData.BuffFormula ~= "" then missileBuffCtrl.BuffOverRideFomula = buffData.BuffFormula end missileBuffCtrl.ForceDuration:Reset(buffData.BuffDuration):Div(1000) local addbuffEntity = hitEntity--接受效果的人 if buffData.AimTargetType == 1 then addbuffEntity = attacker end missile:OnMissileBuffDataAddBuff(buffData) SystemManager.AddBuff(addbuffEntity,buffData.BuffID,attacker,missile,missileBuffCtrl) end end else if buffData.BuffID ~= -1 then logging.error(LTAG.ERROR, "HYW : missileData的MissileBuffData_Table里的BuffID不对,missileDataID :", missile.MissileData.ID, " buffID : ", buffData.BuffID) end end end end --子弹的buff产生的影响。 包括造成伤害和其他效果 function private.AddBuffEffect(missile, hitEntity) local missileData = missile.MissileData local attacker = missile.Attacker local beforeSubHPIsAlive = hitEntity.components.attr:IsAlive() -- 子弹除伤害外的其他效果,早于伤害生效 if beforeSubHPIsAlive then private.AddBuffEffectByMissileBuffDataTable(missileData.EarlyMissileBuffData_Table, missile, attacker, hitEntity) end -- 子弹伤害效果 if missileData.HurtBuffID > 0 then local canhurt = private.CheckBuffCanAddtoEntity(missileData.HurtTriggerTargetType ,attacker, hitEntity) if canhurt then local hurtEntity = hitEntity--接受效果的人 if missileData.HurtAimTargetType == 1 then hurtEntity = attacker end local hurtBuffCtrl = RuntimeDataManager.New_BuffCtrl() hurtBuffCtrl.IsTracker = missile.IsTracker hurtBuffCtrl.MissileHurtID = missileData.ID SystemManager.AddBuff(hurtEntity,missileData.HurtBuffID,attacker,missile,hurtBuffCtrl) end end -- 子弹除伤害外的其他效果,晚于伤害生效【1.不直接放在伤害前是因为增加攻击力在这次伤害不能加,2.不在此直接判断活着是因为一刀打死怪后没buff效果】 if beforeSubHPIsAlive then private.AddBuffEffectByMissileBuffDataTable(missileData.MissileBuffData_Table, missile, attacker, hitEntity) end ----给受击人加上特定伤害动作的buff ,并告知推动距离 start local characterType = hitEntity._logicInitData.CharacterType local isHitHero = false -- 子弹击中的是 玩家 local addBuffID = missileData.HitBuffID local hitMoveTime = missileData.HitMoveTime local hitDistance = missileData.HitDistance local hitMoveDir = missileData.HitMoveDirection local hitMoveDirOffsetAngle = missileData.HitMoveDirOffsetAngle if characterType == LuaConst_CharacterType_Hero or characterType == LuaConst_CharacterType_Adjutant or characterType == LuaConst_CharacterType_Illusion then addBuffID = missileData.PlayerHitBuffID hitMoveTime = missileData.PlayerHitMoveTime hitDistance = missileData.PlayerHitDistance hitMoveDir = missileData.PlayerHitMoveDirection hitMoveDirOffsetAngle = missileData.PlayerHitMoveDirOffsetAngle isHitHero = true end if missile.Attacker:GetCampID() == hitEntity:GetCampID() then addBuffID = 0 --如果是友方,不再添加受击buff end -- 有受击动作 if addBuffID ~= 0 then if hitEntity:IsActive() then local hitBuffCtrl = RuntimeDataManager.New_BuffCtrl() hitBuffCtrl.MissileHitMoveID = missileData.ID hitBuffCtrl.HitMoveTime:Reset(hitMoveTime) hitBuffCtrl.HitDistance:Reset(hitDistance) hitBuffCtrl.HitMoveDir = hitMoveDir hitBuffCtrl.HitMoveDirOffsetAngle = hitMoveDirOffsetAngle BattleEventSystem.AfterEntityMissileSetHitMoveInfo(attacker, missileData, isHitHero, missile, hitBuffCtrl.HitMoveTime, hitBuffCtrl.HitDistance) -- 被打死啦 if not hitEntity.components.attr:IsAlive() then local addBuffData = DataSheetManager.BuffData:GetDataByBuffID(addBuffID) local immuned = CheckBuffImmune(hitEntity, addBuffData) if not immuned then --如果受击buff没有被免疫,则进行受击buff死亡转换 addBuffID = LuaConst.DeadChangeBuff[addBuffID] or LuaConst_SpecialBuffs_InDying --else --do nothing --如果受击buff被免疫了,则不进行受击buff死亡转换,也不添加死亡buff --hitBuffCtrl = nil end else local buffComp = hitEntity.components.buff if buffComp:GetBuffUpdateData(LuaConst_SpecialBuffs_InHitUp) or buffComp:GetBuffUpdateData(LuaConst_SpecialBuffs_InHitFlyMonster) or buffComp:GetBuffUpdateData(LuaConst_SpecialBuffs_InFlyFlyingMonster) then if addBuffID ~= LuaConst_SpecialBuffs_InHitFlyMonster then addBuffID = LuaConst_SpecialBuffs_InFlyFlyingMonster end end end SystemManager.AddBuff(hitEntity, addBuffID, attacker, missile, hitBuffCtrl) end end ----给受击人加上特定伤害动作的buff ,并告知推动距离 end local isNotPlayHitSound = private.IsNotPlayHitSound(attacker, hitEntity) local timeScale = attacker.components.timeScale:GetCurMissileTimeScale() --玩家被打中后的屏幕特效 if hitEntity._logicInitData.IsPlayerSelf then SystemManager.ReceiveHitEffect(hitEntity, missileData.HitScreenResource, timeScale,missileData.HitScreenResourceTime, 0, 0, missileData.HitSoundLevel,isNotPlayHitSound) end --美术给的攻击特效都是从后向前的 ;默认特效的是(pos - sourcePos) if missile.hitResource ~= "" then if CampManager.IsEnemyEntity(attacker,hitEntity) then -- 策划需求:HitResource 只对敌方有子弹击打特效 local fx, fz = 0,0 if missile.EffForward then local forward = hitEntity.components.move.LogicPos - attacker.components.move.LogicPos forward:Normalize() fx, fz = tonumberV2(forward) local type = tonumberV1(missile.EffForward) if type == 1 then -- 从左到右 fx, fz = fz, -fx elseif type == 2 then -- 从右到左 fx, fz = -fz, fx end --type == 3 then -- 从前到后 releaseV2(forward) end SystemManager.ReceiveHitEffect(hitEntity, missile.hitResource, timeScale, -1, fx, fz,missileData.HitSoundLevel,isNotPlayHitSound) end end -- 宠物需要记录玩家打中人时的帧号 local petComp = attacker:GetOriginEntity().components.pet if petComp and PetMissileGroupDic[missileData.GroupID] == nil then -- 排除宠物子弹 petComp:SetLastHitOthersFrame(LogicUpdateManager._clientHandleFrame) end BattleEventSystem.AfterEntityHitByMissile(hitEntity,missileData,attacker,missile) end function private.IsNotPlayHitSound(attacker, hitEntity)--根据攻击者与受击者类型 是否播放pshitsoun 受击声音 if attacker._logicInitData.CharacterType == LuaConst.CharacterType.Hero then if hitEntity._logicInitData.CharacterType == LuaConst.CharacterType.Monster then if attacker._logicInitData.IsPlayerSelf and attacker:IsMainEntityOfPlayer() then --自己打怪 return false else--其他玩家打怪 return true end elseif hitEntity._logicInitData.CharacterType == LuaConst.CharacterType.Hero then if attacker._logicInitData.IsPlayerSelf and attacker:IsMainEntityOfPlayer() then -- 自己打其他玩家 return false elseif hitEntity._logicInitData.IsPlayerSelf and hitEntity:IsMainEntityOfPlayer() and ( BattleDataGetter.CheckCurLevelType(LuaConst.LevelType.SoloFight) or BattleDataGetter.CheckCurLevelType(LuaConst.LevelType.SyncSolo) or BattleDataGetter.CheckCurLevelType(LuaConst.LevelType.SyncSoloPractice)) then return false --其他玩家打自己 目前只有在 1v1上使用 else --其他玩家打其他玩家 或其他玩家打自己 return true end end elseif attacker._logicInitData.CharacterType == LuaConst.CharacterType.Monster then if hitEntity._logicInitData.CharacterType == LuaConst.CharacterType.Monster then return false --怪打怪 elseif hitEntity._logicInitData.CharacterType == LuaConst.CharacterType.Hero then if hitEntity._logicInitData.IsPlayerSelf and hitEntity:IsMainEntityOfPlayer() then return false -- 怪打自己 else return true --怪打其他玩家 end end end return false end function private.CanAddSa(attacker) if attacker:IsMainEntityOfPlayer() then return true else if LevelManager.CurLevelFunc:IsIndividualSa() then return true end if not attacker:IsHero() then local masterEntity = attacker:GetMasterEntity() if masterEntity == nil or masterEntity:IsMainEntityOfPlayer() then return true end end end return false end -- 子弹撞到人 ,给发射子弹者的一次性效果(策划说无论是加血还是其他任何效果都算撞到人) function private.HitOnceEffectToSource(missile,hitEntity) local missileData = missile.MissileData local attacker = missile.Attacker -- buff添加(反哺效果) local buffDatas = missileData.FeedBackBuff_Table for i,buffData in ipairs(buffDatas) do if private.ConditionCheck(attacker, hitEntity, missile, buffData.ConditionAimType, buffData.ConditionStr) then local ctrlParam = RuntimeDataManager.New_BuffCtrl() if buffData.BuffFormula and buffData.BuffFormula ~= "" then ctrlParam.BuffOverRideFomula = buffData.BuffFormula end ctrlParam.ForceDuration:Reset(buffData.BuffDuration):Div(1000) if buffData.DelayTime > 0 then -- DelayTime 毫秒 MissileManager.AddDelayAddBuff(buffData.DelayTime, attacker,buffData.BuffID,ctrlParam) else SystemManager.AddBuff(attacker,buffData.BuffID,attacker,missile,ctrlParam) end end end BattleEventSystem.AfterEntityMissileHitOnce(attacker, missileData, hitEntity, missile) end -- 无双值修改 function private.AddOnceSA(missile) local missileData = missile.MissileData local attacker = missile.Attacker -- 无双值修改 if private.CanAddSa(attacker) then local sa = missileData.AddSAVal if sa ~= Const_Zero then attacker.components.attr:AddSA(sa,attacker) EventSystem.Dispatch(EventID.TryAddAttackLog, HurtFormulaStepEnumSaChange, sa) -- local result = attacker.components.attr:GetAttrValue(LuaConst.RealtimeAttrType.sa):cloneV1() -- SystemManager.OnSAChange(attacker,sa,result) end end end function private.CheckBuffCanAddtoEntity(targetType ,attacker, hitEntity, missile, conditionAimType, conditionStr) local canAdd = false if targetType == LuaConst_MissileImpactType_Enemy or targetType == LuaConst_MissileImpactType_TargetIfHas and attacker.components.target.Target == nil then --子弹召唤者的敌方 canAdd = CampManager.IsEnemyEntity(attacker,hitEntity) elseif targetType == LuaConst_MissileImpactType_Friend then --子弹召唤者的友方 canAdd = (not CampManager.IsEnemyEntity(attacker,hitEntity) ) and attacker ~= hitEntity elseif targetType == LuaConst_MissileImpactType_Self then --子弹召唤者自己 canAdd = attacker == hitEntity elseif targetType == LuaConst_MissileImpactType_Team then --子弹召唤者的友方+自己 canAdd = not CampManager.IsEnemyEntity(attacker,hitEntity) elseif targetType == LuaConst_MissileImpactType_EnemyAndFriend then --子弹召唤者的友方+自己 canAdd = attacker ~= hitEntity elseif targetType == LuaConst_MissileImpactType_NoPeace then -- 非中立和平(目前等价于全部,因为目前没有中立和平 2021年2月2日) canAdd = true elseif targetType == LuaConst_MissileImpactType_TargetIfHas and attacker.components.target.Target then canAdd = (hitEntity == attacker.components.target.Target) --有目标时仅目标,无目标时跟LuaConst_MissileImpactType_Enemy一致 end if not canAdd then return canAdd else return private.ConditionCheck(attacker, hitEntity, missile, conditionAimType, conditionStr) --尾调用 end end function private.ConditionCheck(attacker, hitEntity, missile, conditionAimType, conditionStr) local result = true if conditionStr and conditionStr ~= "" then local conditionAim = nil if conditionAimType == 0 then conditionAim = hitEntity elseif conditionAimType == 1 then conditionAim = attacker else conditionAim = hitEntity end if conditionAim then local conditionTree = ConditionManager.GetConditionDataTree(conditionStr) result = ConditionManager.MeetCondition(conditionAim,conditionTree,missile) else logging.error(LTAG.ERROR, "HYW : 子弹条件判定的目标不存在! MissileID : " , missile.MissileData.ID , " conditionAimType : " , conditionAimType) end end return result end return TriggerMissileSystem