local MoveMissileSystem = {} local private = {} local newV1=FP.newV1 local newV2=FP.newV2 local _tempFixV1 = newV1(0) local _tempTimeV1 = newV1(0) local _tempAngleV1 = newV1(0) local _tempFixV2 = newV2(0,0) local GetRightByForward=FP.V2.GetRightByForward local Normalize= FP.V2.Normalize local Distance=FP.V2.Distance local Const_Zero=FP.Const.Zero local Const_V2Zero=FP.Const.Vector2_Zero local GetOffsetToAngle=FP.V2.GetOffsetToAngle local LuaConst_MissileMoveType_Bind=LuaConst.MissileMoveType.Bind local LuaConst_MissileMoveType_Parabola=LuaConst.MissileMoveType.Parabola local LuaConst_MissileMoveType_BindWithOutRotate=LuaConst.MissileMoveType.BindWithOutRotate local LuaConst_MissileMoveType_BindAndAroundRotate=LuaConst.MissileMoveType.BindAndAroundRotate local LuaConst_TimeSpanMs=LuaConst.TimeSpanMs local releaseV2=FP.releaseV2 --[[ 子弹发射 --]] function MoveMissileSystem.OnMissileFire(missile, paramData) missile.PosOffset:Reset(paramData.PosOffset) missile.OffsetY:Reset(paramData.OffsetY) missile.Pos:Reset(paramData.Pos) missile.PosY:Reset(paramData.PosY):Add(paramData.OffsetY) if missile.MoveType == LuaConst_MissileMoveType_Parabola then if paramData.ParabolaTargetPos == nil then logging.error(LTAG.ERROR, "[战斗策划] :抛物线子弹没有发现目标点(AI配置点或者敌人目标点),AI没配置或者target丢失") end local length = Distance(missile.Pos, paramData.ParabolaTargetPos) local flyTime = length / missile.MissileData.MoveSpeed --秒 missile.TotalTime = flyTime * 1000 -- 毫秒 missile.MoveDir:Reset(paramData.Forward) elseif missile.IsTracker then --追踪弹 missile.TotalTime = missile.MissileData.FreeFlyMaxTime + missile.MissileData.TrackFlyTime missile.FireDir:Reset(paramData.Forward) if missile.FireRotate and (missile.FireRotate.x > newV1(90) or missile.FireRotate.x < newV1(-90)) then missile.MoveDir:Reset(-paramData.Forward) else missile.MoveDir:Reset(paramData.Forward) end elseif missile.MoveType == LuaConst_MissileMoveType_BindAndAroundRotate then missile.TotalTime:Reset(missile.MissileData.TotalTime) missile.MoveDir:Reset(missile.Pos):Sub(missile.Attacker.components.move.LogicPos) -- 目前是偏移(PosOffset不一定有值) if missile.MoveDir == Const_V2Zero then logging.error(LTAG.ERROR, "【GWS】战斗策划:公转轨迹的子弹必须与发射者位置不能重叠。子弹ID = ", missile.MissileData.ID); missile.MoveDir:Reset(0,1) missile.PosOffsetDistance:Reset(1) else FP.V2.Magnitude(missile.MoveDir, missile.PosOffsetDistance)-- 计算PosOffsetDistance的值 end --missile.MoveDir:Normalize() else missile.TotalTime:Reset(missile.MissileData.TotalTime) missile.MoveDir:Reset(paramData.Forward) end Normalize(missile.MoveDir) missile.InitPos:Reset(missile.Pos) missile.InitPosY:Reset(missile.PosY) end --[[ 子弹Tick --]] function MoveMissileSystem.OnMissileUpdate(missile) if missile.hookEntity ~= nil then -- missile:IsHooked() --子弹钩住后,走钩子特有的运动机制 --实际上就是do nothing,钩子不需要运动 elseif missile.IsTracker then --追踪弹 local missilePos = missile.Pos if missile.InFreeFly then --自由飞行阶段 if missile.IsBinding then--跟随角色位移 local attackerMoveComponent = missile.Attacker.components.move missile.MoveDir:Reset(attackerMoveComponent.LogicRotateDir) local forward = missile.MoveDir local right = GetRightByForward(forward) _tempFixV2:Reset(forward):Mul(missile.PosOffset.z) missilePos:Reset(attackerMoveComponent.LogicPos):Add(_tempFixV2) _tempFixV2:Reset(right):Mul(missile.PosOffset.x) missilePos:Add(_tempFixV2) missile.PosY:Reset(attackerMoveComponent:GetLogicPosY()):Add(missile.OffsetY) releaseV2(right) elseif missile.MissileData.FreeFlyType == 1 then --直线 _tempFixV2:Reset(missile.MoveDir):Mul(missile.MissileData.FreeFlySpd):Mul(missile.FreeFlyTime):Div(1000) missilePos:Reset(missile.InitPos):Add(_tempFixV2) end else --追击阶段 local targetPos = missile.TrackerTarget and _tempFixV2:Reset(missile.TrackerTarget.components.move.LogicPos):Add(missile.TrackerOffset) or missile.TrackerVirtualPos missile.MoveDir:Reset(targetPos):Sub(missilePos) Normalize(missile.MoveDir) local timeScale = missile.AttackerTimescale:GetCurMissileTimeScale() _tempFixV2:Reset(missile.MoveDir):Mul(missile.TrackSpeed):Mul(LuaConst.TimeSpan):Mul(timeScale) missile.Pos:Add(_tempFixV2) end elseif missile.MoveType == LuaConst_MissileMoveType_Bind then--跟随角色位移 local attackerMoveComponent = missile.Attacker.components.move local missilePos = missile.Pos local forward = attackerMoveComponent.LogicRotateDir local right = GetRightByForward(forward) _tempFixV2:Reset(forward):Mul(missile.PosOffset.z) missilePos:Reset(attackerMoveComponent.LogicPos):Add(_tempFixV2) _tempFixV2:Reset(right):Mul(missile.PosOffset.x) missilePos:Add(_tempFixV2) missile.PosY:Reset(attackerMoveComponent:GetLogicPosY()):Add(missile.OffsetY) releaseV2(right) local data = missile.CallData if data.BornForwardType == 0 then missile.MoveDir:Reset(attackerMoveComponent.LogicRotateDir) elseif data.BornForwardType == 1 then -- 背离 missile.MoveDir:Reset(missilePos):Sub(attackerMoveComponent.LogicPos):Normalized() elseif data.BornForwardType == 2 then -- 面向 missile.MoveDir:Reset(attackerMoveComponent.LogicPos):Sub(missilePos):Normalized() end elseif missile.MoveType == LuaConst_MissileMoveType_BindWithOutRotate then local attackerMoveComponent = missile.Attacker.components.move missile.Pos:Reset(attackerMoveComponent.LogicPos):Add(missile.PosOffset) missile.PosY:Reset(attackerMoveComponent:GetLogicPosY()):Add(missile.OffsetY) elseif missile.MoveType == LuaConst_MissileMoveType_BindAndAroundRotate then -- 公转 private.MoveByBindAndAroundRotate(missile) elseif missile.MoveType == LuaConst_MissileMoveType_Parabola then--抛物线 if missile.CurTime > Const_Zero then local timeScale = missile.AttackerTimescale:GetCurMissileTimeScale() _tempFixV1:Reset(missile.MissileData.MoveSpeed):Mul(timeScale):Mul(missile.CurTime):Div(1000) --水平位移 missile.Pos:Reset(missile.MoveDir):Mul(_tempFixV1):Add(missile.InitPos) --missile.PosY:Reset(missile.OffsetY):Add(attackerMoveComponent.LogicPosY) TODO:gws: 需要逻辑上计算高度,但是目前通过二阶子弹搞定了,时间紧暂时不实现逻辑了 end else --直线 + 旋转 local missileData = missile.MissileData local timeScale = missile.AttackerTimescale:GetCurMissileTimeScale() _tempFixV1:Reset(missile.CurTime):Sub(missileData.DelayMoveFrame) --time if _tempFixV1 > Const_Zero then _tempTimeV1:Reset(LuaConst_TimeSpanMs):Mul(timeScale):Div(1000) -- 时间间隔 单位:秒 if missileData.AngleSpeed ~= Const_Zero then _tempAngleV1:Reset(_tempTimeV1):Mul(missileData.AngleSpeed) --角度变化量 local newDir = GetOffsetToAngle(_tempAngleV1, missile.MoveDir) missile.MoveDir:Reset(newDir) releaseV2(newDir) end local missilePos = missile.Pos _tempFixV2:Reset(missile.MoveDir):Mul(missileData.MoveSpeed):Mul(_tempTimeV1):Add(missilePos) missilePos:Reset(_tempFixV2) -- 要贴合地面 if missileData.FollowTerrainHeight then missile.isOnWalkTerrain = LuaShoveManager.GetHeightByPos(missilePos ,missile.PosY, true) elseif missile.SpeedY ~= Const_Zero then -- 可上下飞行 missile.PosY:Reset(missile.SpeedY):Mul(_tempFixV1):Div(1000):Add(missile.InitPosY) end end end end -- 公转计算(子弹的朝向始终远离发射者) function private.MoveByBindAndAroundRotate(missile) local attackerMoveComponent = missile.Attacker.components.move local missileData = missile.MissileData local timeScale = missile.AttackerTimescale:GetCurMissileTimeScale() _tempFixV1:Reset(missile.CurTime):Sub(missileData.DelayMoveFrame) --time if _tempFixV1 > Const_Zero then _tempTimeV1:Reset(LuaConst_TimeSpanMs):Mul(timeScale):Div(1000) -- 时间间隔 单位:秒 local angleSpd = missile.overrideAngleSpeed or missileData.AngleSpeed _tempAngleV1:Reset(_tempTimeV1):Mul(angleSpd) --角度变化量 local newDir = GetOffsetToAngle(_tempAngleV1, missile.MoveDir) -- 规律: missile.MoveDir始终等于 上一帧的人到子弹的向量,故用其旋转即是用人-子弹向量旋转 missile.MoveDir:Reset(newDir) releaseV2(newDir) end --计算子弹位置 _tempFixV2:Reset(missile.MoveDir):Mul(missile.PosOffsetDistance) -- 偏移量 missile.Pos:Reset(attackerMoveComponent.LogicPos):Add(_tempFixV2) -- 再算具体位置 -- 高度跟随发射者 missile.PosY:Reset(attackerMoveComponent:GetLogicPosY()):Add(missile.OffsetY) end return MoveMissileSystem