--子弹发射子弹 local FireNextMissileSystem = {} local Const_TrackerHeightOffset = 1.5 function FireNextMissileSystem.CallNextBullet(missile,nextInfo , callType) local callBulletData = nextInfo.NextID>0 and missile.Attacker:GetCallData(nextInfo.NextID) or nil if not callBulletData then return end local entity = missile.Attacker local callBulletInfo = RuntimeDataManager.New_CallBulletInfo() local oldDynamicDmgFactor = missile:GetDynamicDamageFactor() if oldDynamicDmgFactor then callBulletInfo.DynamicSkillDmgFactor:Reset(oldDynamicDmgFactor) end callBulletInfo.IsNextMissile = true callBulletInfo.Entity = entity callBulletInfo.CallTime:Reset(callBulletData.DelayTime) callBulletInfo.Data = callBulletData callBulletInfo.SkillID = missile:GetSkillID() if callBulletData.IsNotBaseOnSkill then logging.error(LTAG.ERROR, "子弹召唤的二次call ,IsNotBaseOnSkill 不能是1,必须是0 ;程序填1也按照0逻辑来!") end callBulletInfo.ForceFireDir = missile.MoveDir -- 基础朝向就是子弹的飞行方向(和子弹面向一致) callBulletInfo.FireBasePos = missile.Pos -- 基础发射位置以前一个子弹的当前位置为基准 if missile.IsTracker then -- 追踪弹的二次子弹高度以表现为准 LuaShoveManager.GetHeightByPos(missile.Pos,callBulletInfo.FireBasePosY) if missile.TrackerTarget then local height = FP.newV1(missile.TrackerTarget.components.base.CurModelData.ModelScale):Mul(Const_TrackerHeightOffset) callBulletInfo.FireBasePosY:Add(height) end else if missile.MissileData.MoveType == LuaConst.MissileMoveType.Parabola and (callType == LuaConst.FireNextType.End or callType == LuaConst.FireNextType.WaitCancle or callType == LuaConst.FireNextType.CancelAndNoHit or callType == LuaConst.FireNextType.CancelAndHitted) then local hasTerrain = LuaShoveManager.GetHeightByPos(missile.Pos ,callBulletInfo.FireBasePosY) if not hasTerrain then -- 打到一个无行走的地方,不要发射二次子弹了 callBulletInfo.FireBasePosY:Reset(entity:GetLogicPosY()) end else callBulletInfo.FireBasePosY = missile.PosY:cloneV1() end end SystemManager.AddNewCall(callBulletInfo) end --- 发射弹射子弹 --- 弹射子弹:callID继承之前的missile,改变d有: 衰减、记录的次数、攻击目标 local BOUNCE_TARGET_FIND_PARAM = { campType = LuaConst.ETargetCampType.ENEMY, ignoreCanNotBeTargetBuff = true, ignoreBeSkillTargetBuff = true, ignoreEnemyListValid = true, noInvincible = true, -- 不选无敌的 conditionStr = "Not(CheckBuff(0,100044))", -- 不能被子弹打中的entity不要被选中 LuaConst.SpecialBuffs.CantBeTrigger exclusions = nil, -- 排除列表 regionParams = { shapeType = LuaConst.ERegionShapeType.CIRCLE, pos = FP.newV2(0,0), -- 位置 shapeNumParams = {0}, -- 距离 }, sortParams = { sortType = LuaConst.ETargetSortType.DIST_NEAR }, } -- hitEntity 从谁的坐标寻找目标并发射,且下次不再攻击这个目标 function FireNextMissileSystem.CallNextBounceBullet(attacker, missile, bounceInfo, hitEntity, callId) if hitEntity == nil then --logging.error(LTAG.ERROR, "[gws]: 发射弹射子弹时,发现弹射出发者entity是空的 , 弹射子弹不再发射!") return end if bounceInfo.leftCount <= 0 then -- 弹射次数用完了 return end local entity = attacker or missile.Attacker local exclusions = {} for i,oldEntity in ipairs(bounceInfo.exclusions) do if oldEntity:IsValid() then table.insert(exclusions, oldEntity) end end table.insert(exclusions, hitEntity) -- 不再攻击上一个目标 --寻敌(如以后需要寻找的是友方,则再添加个参数控制) BOUNCE_TARGET_FIND_PARAM.exclusions = exclusions--需要忽略的entity BOUNCE_TARGET_FIND_PARAM.regionParams.pos:Reset(hitEntity:GetLogicPos()) BOUNCE_TARGET_FIND_PARAM.regionParams.shapeNumParams[1] = bounceInfo.searchRadius local targetEntity = TargetManager.GetTarget(entity, BOUNCE_TARGET_FIND_PARAM) if targetEntity == nil then -- 寻不到目标 -- noTargetThenOpt :1= 找不到目标则停止弹射 2-找不到目标从旧的目标中找 3-找不到目标从新的目标中找再找不到则选择此次的受击目标 if bounceInfo.noTargetThenOpt == 1 then BOUNCE_TARGET_FIND_PARAM.exclusions = nil return elseif bounceInfo.noTargetThenOpt == 2 or bounceInfo.noTargetThenOpt == 3 then BOUNCE_TARGET_FIND_PARAM.exclusions = { hitEntity } targetEntity = TargetManager.GetTarget(entity, BOUNCE_TARGET_FIND_PARAM) if targetEntity == nil and bounceInfo.noTargetThenOpt == 3 then targetEntity = hitEntity end if targetEntity == nil or not targetEntity:IsAlive() then BOUNCE_TARGET_FIND_PARAM.exclusions = nil return -- 实在是找不到目标,不再发射 end end end local callBulletData = callId and missile.Attacker:GetCallData(callId) or missile.CallData local callBulletInfo = RuntimeDataManager.New_CallBulletInfo() local oldDynamicDmgFactor = missile:GetDynamicDamageFactor() if oldDynamicDmgFactor then -- 若是持续递减的子弹,则伤害 = base * dynamicDmgRate^count callBulletInfo.DynamicSkillDmgFactor:Reset(oldDynamicDmgFactor) if bounceInfo.dynamicDmgRateIsOnce then if bounceInfo.isFirst then callBulletInfo.DynamicSkillDmgFactor:Mul(bounceInfo.dynamicDmgRate) end else callBulletInfo.DynamicSkillDmgFactor:Mul(bounceInfo.dynamicDmgRate) end end callBulletInfo.IsNextMissile = true callBulletInfo.Entity = entity callBulletInfo.CallTime:Reset(callBulletData.DelayTime) callBulletInfo.Data = callBulletData callBulletInfo.SkillID = missile:GetSkillID() callBulletInfo.FireBasePos = hitEntity:GetLogicPos():cloneV2()-- 基础发射位置以前一个子弹打中的人位置为基准 callBulletInfo.FireBasePosY = hitEntity.components.move.LogicPosY:cloneV1() callBulletInfo.TrackerTarget = targetEntity callBulletInfo.ForceTarget = targetEntity -- 目的是覆盖entity.components.target.Target --设置子弹朝向 callBulletInfo.ForceFireDir = FP.newV2(0,0) callBulletInfo.ForceFireDir:Reset(targetEntity:GetLogicPos()):Sub(hitEntity:GetLogicPos()) -- 基础朝向就是子弹的飞行方向(和子弹面向一致) callBulletInfo.ForceFireDir:Normalize() callBulletInfo.bounceInfo = { leftCount = bounceInfo.leftCount-1, dynamicDmgRate = bounceInfo.dynamicDmgRate, dynamicDmgRateIsOnce = bounceInfo.dynamicDmgRateIsOnce, isFirst = false, searchRadius = bounceInfo.searchRadius, noTargetThenOpt = bounceInfo.noTargetThenOpt, exclusions = exclusions, } --清理下缓存数据 BOUNCE_TARGET_FIND_PARAM.exclusions = nil BOUNCE_TARGET_FIND_PARAM.regionParams.pos:Reset() BOUNCE_TARGET_FIND_PARAM.regionParams.shapeNumParams[1] = 0 --print( hitEntity.EntityID ," ------------------ ", targetEntity.EntityID) SystemManager.AddNewCall(callBulletInfo) end return FireNextMissileSystem