local UIStaticSkillJoystick = UIViewClass() local EffectType = LuaConst.EffectType --[[ 数据部分 --]] local MIN_DIR_EFFECT_STRIDE_30FPS = 1 local MIN_DIR_EFFECT_STRIDE = 1 local DIR_EFFECT_ROT_SPEED_RATIO_30FPS = 0.3 local DIR_EFFECT_ROT_SPEED_RATIO = 0.3 local AREA_EFFECT_POS_Y = 0.2 local Vector3_New=Vector3.New local VECTORFAR = Vector3_New(9999, 9999, 0) local MaxRadius = 120 local StartPntX = 0 local StartPntY = 0 local StartPntZ = 0 local Vector3TempDir = Vector3_New(0, 0, 0) --临时变量,无固定含义 local min = math.min local sqrt = math.sqrt local acos = math.acos local cos = math.cos local pi = math.pi local sin = math.sin local pow=math.pow local LuaConst=LuaConst local FP=FP local UIUtils=UIUtils local UEType_JOYSTICK_RANGE_STATIC_RANGE = LuaConst.ESkillJoystickUEType.JOYSTICK_RANGE_STATIC_RANGE local PLAY_EFFECT_DELAY = 0.15 --初始拖动距离跟MaxRadius的比值小于这个值,不算作有效输入 local torleranceRatio = 0.10 local StartTouchRelativePos = Vector3_New(0, 0, 0) local EEffectShapeType = LuaConst.ESkillJoystickShapeType function UIStaticSkillJoystick:OnCreated() self.isInTimeline = false self.rawAngle = 361 --世界坐标系下的角度 self.rawX = 0 --世界坐标系下(主要是旋转),目标点相对于主角的位置的x self.rawZ = 0 --世界坐标系下(主要是旋转),目标点相对于主角的位置的z self.rangeEffectLocalPosX = nil --主角模型坐标系下(主要是旋转)的x self.rangeEffectLocalPosZ = nil --主角模型坐标系下(主要是旋转)的z self.thisTrans=self.gameObject.transform self.curEntity = nil --为了方便,保存引用,但是这个用法不规范。 千万不要调用self.curEntity的设置接口,否则会导致不一致 self.hasObstacleTowardsAimPos = false --curEntity到双摇杆焦点位置之间有没有阻挡 self.obstaclePos = nil --如果curEntity到双摇杆焦点位置之间有阻挡,则这个就是最近的阻挡的位置;如果没有阻挡,则为nil self.exceedToleranceDragged = false --玩家的输入跟原点的距离是否超过了生效容限,只有超过一定距离的容限才算是有效输入 self.skillJoyStickData = nil --当技能为非副将技时,这个就是技能的双摇杆数据; 但当技能为副将技时,这个是副将技的通用基础双摇杆数据(副将技有2个双摇杆数据,1个基础的,1个副将技的) self.skillJoyStickControlRange = nil -- 控制技能摇杆的技能摇杆数据 中的摇杆范围值 --以下为变量 self.effectStarted = false --是否呼出了双摇杆 self.isEnabled = true --是否可用 end function UIStaticSkillJoystick:OnOpened(context) self:ShowStaticJoyStaticSkillRange(context.skillJoyStickData, context.skillData) if BattleDataGetter.IsPVPLevel() then PLAY_EFFECT_DELAY = FP.tonumberV1(DataSheetManager.ConstData:GetDataByID("SKILL_JOYSTICK_DELAY_PVP").FloatValue) else PLAY_EFFECT_DELAY = FP.tonumberV1(DataSheetManager.ConstData:GetDataByID("SKILL_JOYSTICK_DELAY_PVE").FloatValue) end DIR_EFFECT_ROT_SPEED_RATIO_30FPS = FP.tonumberV1(DataSheetManager.ConstData:GetDataByID("DIR_EFFECT_ROT_SPEED_RATIO_30FPS").FloatValue) MIN_DIR_EFFECT_STRIDE_30FPS = FP.tonumberV1(DataSheetManager.ConstData:GetDataByID("MIN_DIR_EFFECT_STRIDE_30FPS").FloatValue) self.Vector3Temp = Vector3_New(0, 0, 0) --临时变量,无固定含义 self.dragging = false self:RefreshCacheByFPS() --event self:RegisterEvents() end function UIStaticSkillJoystick:RefreshCacheByFPS() if SettingAPI.fpsLevel > 0 then MIN_DIR_EFFECT_STRIDE = MIN_DIR_EFFECT_STRIDE_30FPS / 2 DIR_EFFECT_ROT_SPEED_RATIO = DIR_EFFECT_ROT_SPEED_RATIO_30FPS / 2 else MIN_DIR_EFFECT_STRIDE = MIN_DIR_EFFECT_STRIDE_30FPS DIR_EFFECT_ROT_SPEED_RATIO = DIR_EFFECT_ROT_SPEED_RATIO_30FPS end end function UIStaticSkillJoystick:RegisterEvents() self:RegistSystemEvent(EventID.TimeLine_Update, self.OnTimeLine) self:RegistSystemEvent(EventID.UIBattle_StaticSkillJoy_Drag,self.OnDrag) self:RegistSystemEvent(EventID.UIBattle_StaticSkillJoy_EndDrag,self.OnEndDrag) self:RegistSystemEvent(EventID.Convey,self.OnConvey) self:RegistSystemEvent(EventID.Player_Dead,self.OnPlayerDead) self:RegistSystemEvent(EventID.Player_Revive,self.OnPlayerRevive) self:RegistSystemEvent(EventID.Player_SkillCoolDown,self.OnPlayerSkillCoolDown) self:RegistSystemEvent(EventID.UIBattle_StaticSkillJoy_PointerDown, self.OnPointerDown) self:RegistSystemEvent(EventID.UIBattle_StaticSkillJoy_PointerUp, self.OnPointerUp) self:RegistSystemEvent(EventID.UIBattle_StaticSkillJoy_BtnDown, self.OnSkillBtnDown) self:RegistSystemEvent(EventID.UIBattle_StaticSkillJoy_BtnUp, self.OnSkillBtnUp) self:RegistSystemEvent(EventID.Setting_SwitchLODLevel, self.OnSetQuality) self:RegistSystemEvent(EventID.UIBattle_ChangeAvatar, self.OnChangeAvatar) self:RegistSystemEvent(EventID.UIBattle_SkillJoystickOverrided, self.OnSkillJoystickOverrided) self:RegistSystemEvent(EventID.Player_BanKeyPositions, self.OnBanKeyPositions) self:RegistSystemEvent(EventID.Player_InterruptSkill, self.OnPlayerInterruptSkill) end function UIStaticSkillJoystick:OnPlayerDead() self:Stop() end function UIStaticSkillJoystick:OnPlayerRevive(entity) if entity:IsPlayerSelf() then self:TryEnableInput() end end function UIStaticSkillJoystick:OnConvey(entity) if self.curEntity == entity then self:Interrupt() end end function UIStaticSkillJoystick:OnTimeLine(value) --这里的value指的是是否要激活界面 if value then self.isInTimeline = false self:TryEnableInput() else self.isInTimeline = true self:DisableInput() end end local function GetAngleFromDir(x,z) if x==0 and z==0 then return 0 end local cosValue = z/(sqrt(x^2+z^2)) local angle = (acos(cosValue)*180)/pi if x < 0 then angle = 360 - angle end return angle end function UIStaticSkillJoystick:OnLateUpdateFun(deltaTime, timeSinceUpdate) if BattleDataGetter.IsMainPlayerManipulatingEntity(self.curEntity) then if self.curEntity then if self.curEntity.components.buff:CheckHasBuffState(LuaConst.SpecialBuffs.CanSkill) then if self.startEla >= PLAY_EFFECT_DELAY then self:Refresh() else self.startEla = self.startEla + timeSinceUpdate - self.lastTime self.lastTime = timeSinceUpdate if self.startEla >= PLAY_EFFECT_DELAY then self:StartPlayEffect() self:Refresh() end end else self:Interrupt() end end else --如果操作期间切换主将了,就stop。OnChangeCurEntity -> Stop self:OnChangeCurEntity() end end function UIStaticSkillJoystick:StartPlayEffect() if self.enableOnStart then self.enableOnStart = false self:TryEnableInput() end self.effectStarted = true if self.curEntity then local expEntity = self.curEntity.ExpEntity expEntity:PlayEffectByType(self.curAreaEffectType) if self.curAreaEffectType == EEffectShapeType.CIRCLE then local scale = self:GetAreaEffectScale(self.skillJoyStickData) expEntity:SetEffectScaleByType(self.curAreaEffectType,scale,1,scale) elseif self.curAreaEffectType == EEffectShapeType.FANSHAPE then local scaleX,scaleY,scaleZ = self:GetDirEffectScale(self.skillJoyStickData,self.curDirEffectType) expEntity:SetEffectScaleByType(self.curDirEffectType,scaleX,scaleY,scaleZ) else --这是没有实现的情况,随便设置了 local scale = self:GetAreaEffectScale(self.skillJoyStickData) expEntity:SetEffectScaleByType(self.curAreaEffectType,scale,1,scale) end self:PlayPsEffect(expEntity) end end local _tempRelativePos = FP.newV2(0, 0) function UIStaticSkillJoystick:SetRawXRawZ(rawX,rawZ) if self.obstaclePos then _tempRelativePos:Reset(self.obstaclePos) _tempRelativePos:Sub(self.curEntity:GetLogicPos()) self.rawX = FP.tonumberV1(_tempRelativePos.x) self.rawZ = FP.tonumberV1(_tempRelativePos.z) else self.rawX = rawX self.rawZ = rawZ end end function UIStaticSkillJoystick:GetCurEffectWorldPosition(effectType) local x = 0 local y = 0 local z = 0 if self.curEntity then -- local entityPos = self.curEntity:GetLogicPos() -- x = FP.tonumberV1(entityPos.x) + self.rawX -- z = FP.tonumberV1(entityPos.z) + self.rawZ x,y,z = self.curEntity.ExpEntity:GetWorldPosByType(effectType) end return FP.newV2(x or 0,z or 0) end --是否是方向型的范围特效 function UIStaticSkillJoystick:IsDirAreaEffectType(areaEffectType) return areaEffectType == EffectType.SkillDirFanshape or areaEffectType == EffectType.SkillDirRectWithArrow or areaEffectType == EffectType.SkillDirCircle or areaEffectType == EffectType.SkillDirRect end function UIStaticSkillJoystick:HasInput() return self.Vector3TempNormalizedX ~= 0 or self.Vector3TempNormalizedZ ~= 0 end --解析输入数据,把输入转换为更好使用的数据, 全部都存在self里,方便脚本内全局使用 --会计算出的数据: -- self.Vector3Temp -- self.Vector3TempNormalizedX、self.Vector3TempNormalizedZ -- self.rawAngle function UIStaticSkillJoystick:TransformInputData() --UIUtils.CameraTransformDirectionf返回摄像机变换后的摇杆方向(摇杆的上方映射为摄像机的forward,摇杆左映射为摄像机的left...,下映射为back,右映射为right) local vector3TempX, vector3TempY,vector3TempZ = UIUtils.CameraTransformDirection(Vector3TempDir.x,0,Vector3TempDir.y,nil,nil,nil) self.Vector3Temp:Set(vector3TempX, 0,vector3TempZ) local Vector3TempNormalized = self.Vector3Temp.normalized self.Vector3TempNormalizedX = Vector3TempNormalized.x self.Vector3TempNormalizedZ = Vector3TempNormalized.z if self.exceedToleranceDragged and self:HasInput() then --双摇杆有输入 self.rawAngle = GetAngleFromDir(self.Vector3TempNormalizedX, self.Vector3TempNormalizedZ) else --双摇杆没有输入 if self.effectStarted then --如果呼出了双摇杆,且没有双摇杆输入,策划要求方向保持初始方向 self.rawAngle = self.startRawAngle end end end function UIStaticSkillJoystick:Refresh() if self.curEntity then local expEntity = self.curEntity.ExpEntity if self.curDirEffectType or (self.dragging and self.skillJoyStickData and (self.skillJoyStickData.UEType == UEType_JOYSTICK_RANGE_STATIC_RANGE)) then local entityRotY = expEntity:GetEulerAngleY() self:TransformInputData() self.effectDirAngle = self:GetDirEffectAngleByRaw(self.rawAngle,entityRotY,self.curDirEffectType) if self.curDirEffectType then ---------------------------------箭头类型的特效---------------------------------------------- if self.exceedToleranceDragged or not self:HasInput() then --设置箭头特效的旋转 self:RefreshDirEffectRot(expEntity) --expEntity:SetEffectRotByType(self.curDirEffectType,self.effectDirAngle) end local scaleX,scaleY,scaleZ = self:GetDirEffectScale(self.skillJoyStickData,self.curDirEffectType) expEntity:SetEffectScaleByType(self.curDirEffectType,scaleX,scaleY,scaleZ) if self.curDirEffectType == EffectType.SkillDirFanshape then --设置扇形的角度 expEntity:SetEffectProjectorAngleByType(self.curDirEffectType,self:GetFanshapeEffectAngle(self.skillJoyStickData)) elseif self.curDirEffectType == EffectType.SkillDirRect then --expEntity:SetEffectSpriteRendererScaleByType(self.curDirEffectType,self.skillJoyStickData.ShapeParam1,self.skillJoyStickData.ShapeParam2) if scaleX ~= 0 then expEntity:SetEffectProjectorAspectRatio(self.curDirEffectType,self.skillJoyStickData.ShapeParam2 / 2 / scaleX) end if self.skillJoyStickData.ShapeParam3 == 0 then expEntity:SetEffectPosByType(self.curDirEffectType, 0, 0, 0) else if self.expEffectDirAngle then local localPosXWithOffset, localPosYWithOffset, localPosZWithOffset = self:GetEffectPosByAngle(self.expEffectDirAngle - 90, self.skillJoyStickData.ShapeParam3) expEntity:SetEffectPosByType(self.curDirEffectType, -localPosXWithOffset, -2, -localPosZWithOffset) end end elseif EffectType.SkillDirRectWithArrow then if scaleX ~= 0 then expEntity:SetEffectProjectorAspectRatio(self.curDirEffectType,self.skillJoyStickData.ShapeParam1 / scaleX) end end else ------------------------------非箭头类特效(目前就是范围类特效)------------------------------ if self.exceedToleranceDragged or not self:HasInput() then if not self:HasInput() then --没有输入,就设置到默认位置 self:SetAreaEffectToDefaultPos() else local dist = 0 self.rangeEffectLocalPosX,self.rangeEffectLocalPosY,self.rangeEffectLocalPosZ,dist = self:GetEffectPosByAngle(self.effectDirAngle) self:SetRawXRawZ(self.Vector3TempNormalizedX * dist,self.Vector3TempNormalizedZ * dist) end local curPos = self.curEntity:GetLogicPos() expEntity:SetEffectPosByType( self.curAreaEffectType, self.rangeEffectLocalPosX,self.rangeEffectLocalPosY,self.rangeEffectLocalPosZ) self.hasObstacleTowardsAimPos, self.obstaclePos = BattleDataGetter.HasObstacleTowardsPos(curPos,self:GetCurEffectWorldPosition(self.curAreaEffectType)) if self.curAreaEffectType == EffectType.SkillEffectAreaCircle or self.curAreaEffectType == EffectType.SkillEffectAreaCircle2 then expEntity:SetEffectRotByType(self.curAreaEffectType,-entityRotY) --这句如果移到self:SetAreaEffectToDefaultPos()下面,用左摇杆转向时,AreaEffect可以保持旋转角度,但是在主角转向时,无法保持角度 elseif self.curAreaEffectType == EffectType.SkillDirFanshape then self.effectDirAngle = self:GetDirEffectAngleByRaw(self.rawAngle,entityRotY,self.curAreaEffectType) expEntity:SetEffectRotByType(self.curAreaEffectType,self.effectDirAngle) --设置扇形的角度,角度越大 expEntity:SetEffectProjectorAngleByType(self.curAreaEffectType,self:GetFanshapeEffectAngle(self.skillJoyStickData)) elseif self.curAreaEffectType == EffectType.SkillEffectAreaRect then -- gws local scaleX = self.skillJoyStickData.ShapeParam1 / 2 expEntity:SetEffectScaleByType(self.curAreaEffectType,scaleX,1,1) -- 设置长(即垂直于朝向的方向) if scaleX ~= 0 then expEntity:SetEffectProjectorAspectRatio(self.curAreaEffectType,self.skillJoyStickData.ShapeParam2 / 2 / scaleX) --设置宽(即平行朝向的边) end self.effectDirAngle = self:GetDirEffectAngleByRaw(self.rawAngle,entityRotY,self.curAreaEffectType) expEntity:SetEffectRotByType(self.curAreaEffectType,self.effectDirAngle) -- 设置朝向 else --这里是还没有支持的类型,随便设了 expEntity:SetEffectRotByType(self.curAreaEffectType,-entityRotY) end end end if self.skillJoyStickData.UseSkillOnPress and LuaInputManager.KeyPosition == self.skillKeyPos and LuaInputManager.SpecialCommand == 0 then self:SetInput() end self.oldEntityRotY = entityRotY end end end --获取非轴点特效的位置 function UIStaticSkillJoystick:GetEffectPosByAngle(angle, distOffset) local worldDist local touchDist = sqrt(self.Vector3Temp.x*self.Vector3Temp.x+self.Vector3Temp.z*self.Vector3Temp.z) local ratio = min(touchDist / MaxRadius,1) worldDist = ratio * self.areaEffectMaxDist if distOffset then worldDist = worldDist + distOffset end local rad = angle / 180 * pi local z = cos(rad) local x = sin(rad) return x * worldDist,AREA_EFFECT_POS_Y,z * worldDist,worldDist end --返回箭头类(指向型)特效的角度。(不同特效类型在相同的rawAngle和entityRotY下,角度会不一样) function UIStaticSkillJoystick:GetDirEffectAngleByRaw(rawAngle, entityRotY, curDirEffectType) rawAngle = rawAngle - entityRotY if curDirEffectType == nil then -- do nothing elseif curDirEffectType == EffectType.SkillDirArrowLock then -- do nothing elseif curDirEffectType == EffectType.SkillDirRectWithArrow then -- do nothing elseif curDirEffectType == EffectType.SkillDirRect or curDirEffectType == EffectType.SkillEffectAreaRect then rawAngle = rawAngle + 270 else --现在的方向特效除了矩形的,x轴都有90的旋转,所以这里rotY要加180 rawAngle = rawAngle + 180 end if rawAngle >= 360 then rawAngle = rawAngle - 360 end return rawAngle end function UIStaticSkillJoystick:GetSkillDirArrowEffectAngleByEffectDirAngle(effectDirAngle, dirEffectType) if dirEffectType == nil then -- do nothing elseif dirEffectType == EffectType.SkillDirArrowLock then -- do nothing elseif dirEffectType == EffectType.SkillDirRectWithArrow then -- do nothing elseif dirEffectType == EffectType.SkillDirRect then -- do nothing else effectDirAngle = effectDirAngle + 90 end if effectDirAngle >= 360 then effectDirAngle = effectDirAngle - 360 end return effectDirAngle end function UIStaticSkillJoystick:GetFanshapeEffectAngle(skillJoyStickData) return skillJoyStickData.ShapeParam2 * 2 end function UIStaticSkillJoystick:GetDirEffectScale(skillJoyStickData,dirEffectType) if skillJoyStickData then if dirEffectType == EffectType.SkillDirRectWithArrow then return skillJoyStickData.ShapeParam2, 1, 1 elseif dirEffectType == EffectType.SkillDirRect then return skillJoyStickData.ShapeParam1 / 2,1,1 elseif dirEffectType == EffectType.SkillDirCircle then return skillJoyStickData.ShapeParam1,1,skillJoyStickData.ShapeParam1 else local scale = self:GetRangeEffectScale(skillJoyStickData) return scale , 1 , scale end else logging.log(LTAG.HYW,"HYW : self.skillJoyStickData nil Error!") return 1,1,1 end end function UIStaticSkillJoystick:OnClosed() self:Stop() end function UIStaticSkillJoystick:OnChangeCurEntity() self:Interrupt() end function UIStaticSkillJoystick:OnBanKeyPositions() self:Interrupt() end function UIStaticSkillJoystick:OnPlayerInterruptSkill() self:Interrupt() end function UIStaticSkillJoystick:Interrupt() self.rawAngle = 361 self.rawX = 0 self.rawZ = 0 self:Stop() LuaInputManager.SetSkillJoystickInterruptFlag(true) end -- isFromStop : 是否是抬手时的调用 function UIStaticSkillJoystick:SetInput() LuaInputManager.SetSkillJoystickInfo(self.rawX, self.rawZ, self.specialCommand) end function UIStaticSkillJoystick:TryBreakKeyPosition() if self.isInCancelArea and self.skillJoyStickData.UseSkillOnPress then LuaInputManager.SetKeyPosition(0, false) end end function UIStaticSkillJoystick:Stop() self:TryBreakKeyPosition() if self.skillBtnHoding then self:Refresh() end self.dragging = false self.effectStarted = false self.exceedToleranceDragged = false self.canCancel = true self.startEla = 0 self:StopRepeatFunc(self.OnLateUpdateFun) self.hasObstacleTowardsAimPos = false --这个得先调 self:StopEffects() --new 提了个方法 self.rangeEffectLocalPosX = nil self.rangeEffectLocalPosY = nil self.rangeEffectLocalPosZ = nil self.effectDirAngle = nil self.rawAngle = 361 self.rawX = 0 self.rawZ = 0 self.specialCommand = nil self.skillAimPos = nil self.oldEntityRotY = nil self.obstaclePos = nil self.expEffectDirAngle = nil Vector3TempDir:Set(0,0,0) end function UIStaticSkillJoystick:StopEffects() if self.curEntity then if self.curDirEffectType then self.curEntity.ExpEntity:StopEffectByType(self.curDirEffectType) end if self.skillJoyStickData then if self.skillJoyStickData.UEType == LuaConst.ESkillJoystickUEType.JOYSTICK_RANGE or self.skillJoyStickData.UEType == UEType_JOYSTICK_RANGE_STATIC_RANGE then self.curEntity.ExpEntity:StopEffectByType(self.curAreaEffectType) end end self:StopPsEffect(self.curEntity.ExpEntity) end self.curDirEffectType = nil end function UIStaticSkillJoystick:GetPositionBasedOnWidth(screenPosition) local vector3TempX,vector3TempY,vector3TempZ = UIUtils.GetPositionBasedOnWidth(self.thisTrans,screenPosition,nil,nil,nil) self.Vector3Temp:Set(vector3TempX, vector3TempY, vector3TempZ) return vector3TempX,vector3TempY,vector3TempZ end function UIStaticSkillJoystick:Dragging(touchPos) if self.dragging then local curPosX,curPosY,curPosZ = self:GetPositionBasedOnWidth(touchPos) curPosX = curPosX + VECTORFAR.x curPosY = curPosY + VECTORFAR.y curPosZ = curPosZ + VECTORFAR.z Vector3TempDir:Set(curPosX - StartPntX, curPosY - StartPntY, curPosZ - StartPntZ) local dist = (Vector3TempDir - StartTouchRelativePos).magnitude self.Vector3Temp = Vector3TempDir.normalized * Mathf.Min(Vector3TempDir.magnitude, MaxRadius) local vector3TempX, vector3TempY,vector3TempZ = UIUtils.CameraTransformDirection(Vector3TempDir.x,0,Vector3TempDir.y,nil,nil,nil) self.Vector3Temp:Set(vector3TempX, vector3TempY,vector3TempZ) local Vector3TempNormalized = self.Vector3Temp.normalized self.Vector3TempNormalizedX = Vector3TempNormalized.x self.Vector3TempNormalizedZ = Vector3TempNormalized.z if self.exceedToleranceDragged or dist > torleranceRatio * MaxRadius then self.exceedToleranceDragged = true end end end function UIStaticSkillJoystick:OnDrag(comp, eventData, skillJoyStickData, skillData) repeat if not self.isEnabled then break end if not skillJoyStickData then break end if not BattleDataGetter.CanMainPlayerUseSkill(skillData) then break end local eventDataPos = eventData.position if (not self.dragging) then self:OnStartDrag(eventDataPos,comp,skillJoyStickData) else self:Dragging(eventDataPos) end until true end function UIStaticSkillJoystick:OnStartDrag(eventDataPos,comp,skillJoyStickData) self.lastEventDataPos = eventDataPos self.lastComp = comp if self.enableOnStart then self.enableOnStart = false self:TryEnableInput() end LuaInputManager.SetSkillJoystickInterruptFlag(false) self.startEla = 0 if self.skillBtnHoding then -- 在按下摇杆时,发现技能按钮一直按着,则立刻设置下目标点 self.startEla = 10 self:StartPlayEffect() end self.dragging = true self:StartRepeatFunc(self.OnLateUpdateFun, 0, -1, false) self.lastTime = 0 local curPosX,curPosY,curPosZ = self:GetPositionBasedOnWidth(eventDataPos) curPosX = curPosX + VECTORFAR.x -- 目的:隐藏技能的摇杆 curPosY = curPosY + VECTORFAR.y curPosZ = curPosZ + VECTORFAR.z StartPntX,StartPntY,StartPntZ = curPosX,curPosY,curPosZ StartTouchRelativePos:Set(curPosX - StartPntX, curPosY - StartPntY, curPosZ - StartPntZ) if self.curEntity then if self.skillData then self.skillAimPos = BattleDataGetter.PredictSkillAimPos(self.curEntity, self.skillData.ID) end local expEntity = self.curEntity.ExpEntity local entityRotY = expEntity:GetEulerAngleY() self.startRawAngle = entityRotY self.rawAngle = self.startRawAngle if skillJoyStickData.ShapeType == EEffectShapeType.FANSHAPE then self.curAreaEffectType = EffectType.SkillDirFanshape elseif skillJoyStickData.ShapeType == EEffectShapeType.CIRCLE then if self.skillJoyStickData.AimPosType == LuaConst.ESkillJoystickAimPosType.Target then self.curAreaEffectType = EffectType.SkillEffectAreaCircleSimple else if skillJoyStickData.UEType == UEType_JOYSTICK_RANGE_STATIC_RANGE then self.curAreaEffectType = EffectType.SkillEffectAreaCircle2 else self.curAreaEffectType = EffectType.SkillEffectAreaCircle end end elseif skillJoyStickData.ShapeType == EEffectShapeType.RECT then self.curAreaEffectType = EffectType.SkillEffectAreaRect else logging.error(LTAG.ERROR, "HYW : 目前没有实现ShapeType类型为", skillJoyStickData.ShapeType, "的区域特效,SkillJoyStickData.ID : ", skillJoyStickData.ID) --默认是圆形 self.curAreaEffectType = EffectType.SkillEffectAreaCircle end if PLAY_EFFECT_DELAY <= 0 then expEntity:PlayEffectByType(self.curAreaEffectType) end local scale = self:GetAreaEffectScale(skillJoyStickData) expEntity:SetEffectScaleByType(self.curAreaEffectType,scale,1,scale) self:SetAreaEffectToDefaultPos() if PLAY_EFFECT_DELAY <= 0 then self:StartPlayEffect() end end end function UIStaticSkillJoystick:TransToLocalPosAndLimitWithinCtrlRange(worldPos) local posX,posZ = self:TransformToLocalPositionOfEntity(worldPos) return self:LimitPointWithinControlRange(posX,posZ) end function UIStaticSkillJoystick:ShowCurDirEffect(expEntity) expEntity:PlayEffectByType(self.curDirEffectType) local scaleX,scaleY,scaleZ = self:GetDirEffectScale(self.skillJoyStickData,self.curDirEffectType) expEntity:SetEffectScaleByType(self.curDirEffectType,scaleX,scaleY,scaleZ) if self.curDirEffectType == EffectType.SkillDirCircle then --圆形方向特效需要加偏移,因为原始特效的pivot在圆心。而矩形、扇形的都在图片的一端所以不用偏移 expEntity:SetEffectProjectorOffsetY(self.curDirEffectType, -self.skillJoyStickData.ShapeParam1) end end local ENTITY_NOT_ROTATE_TOLERANCE = 0 function UIStaticSkillJoystick:RefreshDirEffectRot(expEntity) if self.effectDirAngle >= 360 then self.effectDirAngle = self.effectDirAngle - 360 elseif self.effectDirAngle <= 0 then self.effectDirAngle = self.effectDirAngle + 360 end local expEffectAngle if self.exceedToleranceDragged and self.oldEffectDirAngle and (self.oldEntityRotY == nil or math.abs(expEntity:GetEulerAngleY() - self.oldEntityRotY) < ENTITY_NOT_ROTATE_TOLERANCE) then expEffectAngle = self.oldEffectDirAngle local delta = self.effectDirAngle - self.oldEffectDirAngle local sign if delta > 0 and delta < 180 or delta < -180 then sign = 1 else sign = -1 end if delta < -180 then delta = delta + 360 elseif delta > 180 then delta = 360 - delta end local absDelta = math.abs(delta) local stride = absDelta * DIR_EFFECT_ROT_SPEED_RATIO if absDelta > MIN_DIR_EFFECT_STRIDE and stride <= MIN_DIR_EFFECT_STRIDE then stride = MIN_DIR_EFFECT_STRIDE end stride = stride * sign expEffectAngle = self.oldEffectDirAngle + stride else expEffectAngle = self.effectDirAngle end if expEffectAngle >= 360 then expEffectAngle = expEffectAngle - 360 elseif expEffectAngle <= 0 then expEffectAngle = expEffectAngle + 360 end self.expEffectDirAngle = expEffectAngle expEntity:SetEffectRotByType(self.curDirEffectType, expEffectAngle) self.oldEffectDirAngle = expEffectAngle end function UIStaticSkillJoystick:SetAreaEffectToDefaultPos() if self.curEntity then if self.obstaclePos and self.rawX == 0 and self.rawZ == 0 then self:SetRawXRawZ()--啥也不用传,因为self.obstaclePos有值 end if self.areaEffectNoTargetPosX then self.curEntity.ExpEntity:SetEffectPosByType(self.curAreaEffectType,self.areaEffectNoTargetPosX,AREA_EFFECT_POS_Y,self.areaEffectNoTargetPosZ) if self.skillJoyStickData.AimPosType == LuaConst.ESkillJoystickAimPosType.Target then self.curEntity.ExpEntity:SetEffectPosByType(EffectType.SkillDirArrowLock,self.areaEffectNoTargetPosX,AREA_EFFECT_POS_Y,self.areaEffectNoTargetPosZ) end end end end --把坐标限制在ControlRange里面 function UIStaticSkillJoystick:LimitPointWithinControlRange(posX,posZ) local xSqr = posX * posX local zSqr = posZ * posZ if xSqr + zSqr > 0 then if xSqr + zSqr > self.rangeSqr then local tempPosX = pow( xSqr / (xSqr + zSqr),0.5) * self.skillJoyStickControlRange posX = posX > 0 and tempPosX or -tempPosX local tempPosZ = pow( zSqr / (xSqr + zSqr),0.5) * self.skillJoyStickControlRange posZ = posZ > 0 and tempPosZ or -tempPosZ end end return posX,posZ end --返回pos相对于主角的localPosition function UIStaticSkillJoystick:TransformToLocalPositionOfEntity(pos) if self.curEntity and pos then local targetX = pos.x local targetZ = pos.z local entityPosX,entityPosY,entityPosZ = self.curEntity.ExpEntity:GetPosition() local xDelta = FP.tonumberV1(targetX - entityPosX) local zDelta = FP.tonumberV1(targetZ - entityPosZ) local angle = GetAngleFromDir(xDelta,zDelta) local entityRotY = self.curEntity.ExpEntity:GetEulerAngleY() angle = self:GetDirEffectAngleByRaw(angle, entityRotY, EffectType.SkillDirArrowLock) local dist = sqrt(xDelta* xDelta+ zDelta * zDelta) local rad = angle / 180 * pi local poxX = sin(rad) * dist local posZ = cos(rad) * dist return poxX,posZ else return 0,0 end end function UIStaticSkillJoystick:GetRangeEffectScale(skillJoyStickData) if skillJoyStickData.IsShowControlRange then return self.skillJoyStickControlRange -- * 1.03 --美术资源稍微有点小,扩大1.03倍刚刚好 else return 0 --为了省事,隐藏外圈直接用scale返回0实现 end end function UIStaticSkillJoystick:GetAreaEffectScale(skillJoyStickData) return skillJoyStickData.ShapeParam1 -- * 1.06 --美术资源稍微有点小,扩大1.03倍刚刚好 end function UIStaticSkillJoystick:OnEndDrag(comp, eventData) self:Stop() end function UIStaticSkillJoystick:OnPointerDown(comp, eventData, skillData) self:TryEnableInput() end local temp_noJoyV2 = FP.newV2(0,0) function UIStaticSkillJoystick:OnSkillBtnDown(skillPos) if (not self.dragging) or (self.rawX == 0 and self.rawZ == 0) then -- 没有摇杆时,用默认位置 ,self.rawX == 0 and self.rawZ == 0表示无输入 local curPos = self.curEntity:GetLogicPos() if self.skillData then self.skillAimPos = BattleDataGetter.PredictSkillAimPos(self.curEntity, self.skillData.ID) if self.skillAimPos then temp_noJoyV2:Reset(self.skillAimPos):Sub(curPos) self:SetRawXRawZ(self:LimitPointWithinControlRange(FP.tonumberV1(temp_noJoyV2.x),FP.tonumberV1(temp_noJoyV2.z))) else local fx, fz = FP.tonumberV2(self.curEntity:GetLogicRotateDir()) local ox, oz = self.areaEffectNoTargetPosX,self.areaEffectNoTargetPosZ local rx = fz * ox + fx * oz local rz = -fx * ox + fz * oz temp_noJoyV2:Reset(rx,rz):Add(curPos) self.hasObstacleTowardsAimPos, self.obstaclePos = BattleDataGetter.HasObstacleTowardsPos(curPos,temp_noJoyV2) self:SetRawXRawZ(rx, rz) end if self.skillJoyStickData.UseSkillOnPress then self:StartRepeatFunc(self.OnLateUpdateFun_FindSkillAimPos, 0, -1, false) end end end if self.skillJoyStickData.UseSkillOnPress then self.skillBtnHoding = true end if LuaInputManager.SpecialCommand == 0 then -- 防止摇杆数据应用给了特殊指令 self:SetInput() end end function UIStaticSkillJoystick:OnSkillBtnUp(skillPos) if self.skillJoyStickData.UseSkillOnPress then self.startEla = 0 self.skillBtnHoding = false self:StopRepeatFunc(self.OnLateUpdateFun_FindSkillAimPos) end end function UIStaticSkillJoystick:OnLateUpdateFun_FindSkillAimPos(deltaTime, timeSinceUpdate) if LuaInputManager.KeyPosition ~= self.skillKeyPos or LuaInputManager.GetSpecialCommand() > 0 then -- 当有其他技能释放后,按键未抬起,但是输入已被清理,故需停止更新 (或者有类似副将技的也要停止) self:StopRepeatFunc(self.OnLateUpdateFun_FindSkillAimPos) return end if (not self.dragging) then self.skillAimPos = BattleDataGetter.PredictSkillAimPos(self.curEntity, self.skillData.ID) if self.skillAimPos then local curPos = self.curEntity:GetLogicPos() temp_noJoyV2:Reset(self.skillAimPos):Sub(curPos) self:SetRawXRawZ(self:LimitPointWithinControlRange(FP.tonumberV1(temp_noJoyV2.x),FP.tonumberV1(temp_noJoyV2.z))) self:SetInput() end end end function UIStaticSkillJoystick:OnPointerUp(comp, eventData, skillJoyStickData, skillData) if skillJoyStickData then end end function UIStaticSkillJoystick:DisableInput() self.isEnabled = false self:Stop() end function UIStaticSkillJoystick:TryEnableInput() if not self.isInTimeline then self.isEnabled = true end end function UIStaticSkillJoystick:OnPlayerSkillCoolDown(keyPos, cdTime) if self.skillData then local belongToSkill = DataSheetManager.SkillData:GetDataByID(self.skillData.BelongTo) --不需要通过entity获取,因为下面访问的数据预期不可能被重写 if self.skillData.KeyPosition == keyPos or (belongToSkill and belongToSkill.KeyPosition == keyPos) then if cdTime and FP.tonumberV1(cdTime) > 0 then self:Interrupt() end end end end function UIStaticSkillJoystick:OnSetQuality() self:RefreshCacheByFPS() end function UIStaticSkillJoystick:OnChangeAvatar() self:Stop() end function UIStaticSkillJoystick:OnSkillJoystickOverrided(replacedID, replacedByID) if self.dragging then self.oldStartEla = self.startEla self:StopEffects() self:OnStartDrag(self.lastEventDataPos, self.lastComp, BattleDataGetter.GetMainEntitySkillJoystickData(replacedByID)) self:StartPlayEffect() self.startEla = self.oldStartEla end end function UIStaticSkillJoystick:PlayPsEffect(expEntity) if not string.isNilOrEmpty(self.skillJoyStickData.PsEffectPath) then expEntity:PlayPsEffect(self.skillJoyStickData.PsEffectPath) end end function UIStaticSkillJoystick:StopPsEffect(expEntity) if not string.isNilOrEmpty(self.skillJoyStickData.PsEffectPath) then expEntity:BreakPsEffect(self.skillJoyStickData.PsEffectPath) end end function UIStaticSkillJoystick:ShowStaticJoyStaticSkillRange(skillJoyStickData, skillData) local curEntity = BattleDataGetter.GetMainPlayerManipulatingEntity() self.skillJoyStickData = skillJoyStickData self.skillJoyStickControlRange = curEntity.components.skillBase:GetSkillJoyStickOverrideData(skillJoyStickData.ID, "ControlRange") or skillJoyStickData.ControlRange self.skillData = skillData self.skillKeyPos = skillData.KeyPosition if curEntity then self.curEntity = curEntity local expEntity = curEntity.ExpEntity expEntity:PlayEffectByType(EffectType.StaticSkillRange) expEntity:SetEffectPosByType(EffectType.StaticSkillRange,0,0,0) local scale = self:GetRangeEffectScale(skillJoyStickData) expEntity:SetEffectScaleByType(EffectType.StaticSkillRange,scale,scale,1) -- 初始数据 self.areaEffectNoTargetPosX = 0 self.areaEffectNoTargetPosY = 0 self.areaEffectNoTargetPosZ = 0 if self.skillJoyStickData.DefaultCallPos and #self.skillJoyStickData.DefaultCallPos > 2 then self.areaEffectNoTargetPosX = self.skillJoyStickData.DefaultCallPos[1] self.areaEffectNoTargetPosY = self.skillJoyStickData.DefaultCallPos[2] self.areaEffectNoTargetPosZ = self.skillJoyStickData.DefaultCallPos[3] end self.rangeSqr = self.skillJoyStickControlRange * self.skillJoyStickControlRange self.areaEffectMaxDist = self.skillJoyStickControlRange --由触点偏移控制的特效能够远离中心的最大距离 end end function UIStaticSkillJoystick:OnClosed() if self.curEntity then self.curEntity.ExpEntity:StopEffectByType(EffectType.StaticSkillRange) if self.curAreaEffectType then self.curEntity.ExpEntity:StopEffectByType(self.curAreaEffectType) end end self.curEntity = nil self.skillJoyStickData = nil self.skillJoyStickControlRange = nil self.skillData = nil end return UIStaticSkillJoystick