using System.Collections.Generic; using UnityEngine; using System; using Sirenix.OdinInspector; using DG.Tweening; //各个状态 public enum SpecialState { Null = -1, FloatState = 0, BlownUp = 1, ShotDown = 2, Weak = 3, } public class AttributeStatus : MonoBehaviour { //组件 private MoveCharacter character; private Rigidbody rb; private Foot foot; private HitFeedbackSystem hitFeedbackSystem; //behit参数 [DisplayOnly] public SpecialState curSpecialStates = SpecialState.Null; public AttackController.AttackMethod attackMethod; [LabelText("控制时间")] [DisplayOnly] public float attributeTime; [TabGroup("漂浮")] [DisplayOnly] public int floatingState; //0:不漂浮;1:漂浮中;2:飘着;3:掉下去 private Vector3 origPos; //初始位置 private float curHeight; //当前所在高度 private float riseTime; //上升时间 private float backSpeed; //返回速度 private float rotateSpeed; //旋转速度 private float rotateDir; //旋转方向 private float height; //漂浮高度 private float rise = 1; private float normalFallSpeed = 15f; [TabGroup("击飞击落")] [DisplayOnly] public int hitState; [TabGroup("击飞击落")] [DisplayOnly] public bool isFly; [TabGroup("击飞击落")] [DisplayOnly] public int jumpNum; [TabGroup("击飞击落")] [LabelText("弹跳力比例")] public float jumpNumRate; [TabGroup("击飞击落")] [LabelText("X方向阻力")] public float decelerationRatioX = 2f; [TabGroup("击飞击落")] [LabelText("Y方向重力")] public float decelerationRatioY = 15f; public Character landingDamageFrom; private Vector3 startFlyPos; [TabGroup("击飞击落")] [LabelText("旋转中心高度")] public float rotateCenterHeight = 1f; [TabGroup("击飞击落")] [LabelText("起飞预设角度")] public float startFlyAngle = 15f; [Tooltip("x为最小值,y为最大值")] [TabGroup("击飞击落")] [LabelText("飞行预设角速度随机范围")] public Vector2 flyingRotateSpeedRange = new Vector2(15, 45); private float flyingRotateSpeed; private Vector3 scale; [TabGroup("击飞击落")] [LabelText("压缩程度")] public float compressionDegree = 0.8f; [Tooltip("x为向下压缩经过的时间,y为回弹经过的时间")] [TabGroup("击飞击落")] [LabelText("压缩速度")] public Vector2 compressionSpeed = new Vector2(0.2f, 0.4f); [TabGroup("击飞击落")] [LabelText("弹跳速度")] public float jumpVel = 5f; [TabGroup("击飞击落")] private Vector3 flyForce; [TabGroup("易伤")] [DisplayOnly] public bool haveVulnerable = false; [TabGroup("易伤")] [DisplayOnly] public float vulnerableRate = 0f; [DisplayOnly] public float vulnerableTime; [TabGroup("累伤")] [DisplayOnly] public float stackingWoudsTime; [TabGroup("累伤")] [DisplayOnly] public float stackingWords; //抗性 [Serializable] public struct Resistances { [LabelText("控制层级")] public int controlOrder; //控制效果抗性 [Range(0, 1)] [LabelText("漂浮抗性")] public float Float; [Range(0, 1)] [LabelText("击飞抗性")] public float BlowUp; [Range(0, 1)] [LabelText("击落抗性")] public float ShotDown; [Range(0, 1)] [LabelText("击晕抗性")] public float Weak; [Space] //非控制效果抗性 [LabelText("护甲值")] public int armor; [LabelText("闪避")] public int dodge; } [LabelText("抗性")] public Resistances resistances; public void Init() { stackingWoudsTime = 0; stackingWords = 0; } private void Awake() { character = GetComponentInParent(); rb = character.rb; foot = character.foot; hitFeedbackSystem = GetComponent(); scale = character.mecanim.transform.localScale; } public void Update() { //易伤 if (haveVulnerable) { vulnerableTime -= Time.deltaTime; if (vulnerableTime <= 0) { vulnerableRate = 0f; haveVulnerable = false; } } //累伤 if (stackingWords > 0) { stackingWoudsTime -= Time.deltaTime; if (stackingWoudsTime <= 0) { stackingWords = 0; } } } public void AddSpecialState(AttackController.AttackMethod attackMethod, Character attackFrom) { if (attackMethod.attackInfo.attackEffect.Count > 0) { AttackEffect attackEffect = AttackEffect.Null; foreach (AttackEffect ae in attackMethod.attackInfo.attackEffect) { switch (attackMethod.attackInfo.attackEffect[0]) { /*控制*/ //漂浮 case AttackEffect.FloatState: if (resistances.Float == 1) { break; } if (PriorityOrder(SpecialState.FloatState, attackMethod.attackInfo.floatState.ControlOrder)) { attackEffect = AttackEffect.FloatState; } break; //击飞 case AttackEffect.BlowUp: if (resistances.BlowUp == 1) { break; } if (!character.nowCanFly) { if (PriorityOrder(SpecialState.BlownUp,attackMethod.attackInfo.blowUp.ControlOrder)) { attackEffect = AttackEffect.BlowUp; } } break; //击落 case AttackEffect.ShotDown: if (resistances.ShotDown == 1) { break; } if (character.nowCanFly || !character.canNotShotDown) { if (PriorityOrder(SpecialState.ShotDown,attackMethod.attackInfo.shotDown.ControlOrder)) { attackEffect = AttackEffect.ShotDown; } } break; //击晕 case AttackEffect.Weak: if (resistances.Weak == 1) { break; } if (PriorityOrder(SpecialState.Weak,attackMethod.attackInfo.weak.ControlOrder)) { attackEffect = AttackEffect.Weak; } break; } } if (attackEffect != AttackEffect.Null) { switch (attackEffect) { /*控制*/ //漂浮 case AttackEffect.FloatState: AddFloat(attackMethod); break; //击飞 case AttackEffect.BlowUp: AddBlowUp(attackMethod, attackFrom.bodyTrans); if (attackMethod.attackInfo.blowUp.haveLandingDamage) { landingDamageFrom = attackFrom; } break; //击落 case AttackEffect.ShotDown: AddShotDown(attackMethod, attackFrom.bodyTrans); if (attackMethod.attackInfo.shotDown.haveLandingDamage) { landingDamageFrom = attackFrom; } break; //击晕 case AttackEffect.Weak: AddWeak(attackMethod); break; } return; } } if (curSpecialStates == SpecialState.Null) { hitFeedbackSystem.EnterHitStun(attackFrom); } else { hitFeedbackSystem.canBeHitStun = false; } } //CharacterState为SpecialStatus时调用此函数 public void SpecialStateEffect(SpecialState specialState) { switch (specialState) { //漂浮 case SpecialState.FloatState: switch (floatingState) { case 1: character.transform.localEulerAngles += new Vector3(0, 0, 1) * rotateDir * rotateSpeed * Time.deltaTime; curHeight = Mathf.SmoothDamp(curHeight, height, ref rise, riseTime); character.transform.position = new Vector3(origPos.x, curHeight, origPos.z); if (curHeight >= height - 0.02f) { floatingState = 2; height = character.transform.position.y; } break; case 2: character.transform.localEulerAngles += new Vector3(0, 0, 1) * rotateDir * rotateSpeed * Time.deltaTime; break; case 3: if (character.transform.position.y >= origPos.y + 0.05f) { curHeight -= normalFallSpeed * Time.deltaTime; character.transform.position = new Vector3(origPos.x, curHeight, origPos.z); } else if (foot.TrigGround || curHeight <= origPos.y + 0.05f) { floatingState = 0; character.bodyCollider.layer = character.gameObject.layer; character.isAdjustHeight = 1; OutSpecialState(); return; } break; } PlayerController playerController = GetComponent(); if (playerController != null) { if (playerController.mp > 0) { playerController.lostMp += playerController.mpReplySpeed * Time.deltaTime; playerController.mp -= playerController.mpReplySpeed * Time.deltaTime; } if (playerController.lostMp >= playerController.addMp) { PoolManager.Instantiate(playerController.soul, character.transform.position, new Quaternion(0, 0, 0, 0), null); playerController.lostMp = 0; } } attributeTime -= Time.deltaTime; if (attributeTime <= 0) { character.transform.localEulerAngles = Vector3.zero; floatingState = 3; rb.useGravity = true; } break; //击飞 case SpecialState.BlownUp: //击落 case SpecialState.ShotDown: Vector3 vel = rb.velocity; switch (hitState) { case -1: break; case 0: if (isFly && foot.TrigGround && vel.y < 0.1f) { if (!foot.haveGravity) { character.transform.position = new Vector3(transform.position.x, character.platformPosY, transform.position.z); } int landingDamage; if (specialState == SpecialState.BlownUp) { if (attackMethod.attackInfo.blowUp.haveLandingDamage) { landingDamage = (int)(Mathf.Abs(transform.position.x - startFlyPos.x) * attackMethod.attackInfo.blowUp.landingDamageRate)/* + GameManager.instance.blowUpDamage*/; if (landingDamage > 0) { character.BeHit(attackMethod, landingDamageFrom, landingDamage); } } } else { AttackInfo.ShotDown shotDown = attackMethod.attackInfo.shotDown; if (shotDown.haveLandingDamage) { landingDamage = (int)(Mathf.Abs(transform.position.y - startFlyPos.y) * shotDown.landingDamageRate * (1 - resistances.ShotDown)) /*+ GameManager.instance.downDamage*/; landingDamage = Mathf.Clamp(landingDamage, shotDown.minLandingDamage, landingDamage); if (landingDamage > 0) { character.BeHit(attackMethod, landingDamageFrom, landingDamage); } } } jumpNum--; if (jumpNum < 0) { vel = vel / 5f; vel.y = jumpVel; character.mecanim.transform.localPosition = Vector3.zero; character.mecanim.transform.localRotation = Quaternion.Euler(0, 0, 0); character.transform.rotation = Quaternion.Euler(transform.rotation.eulerAngles.x, transform.rotation.eulerAngles.y, character.platformRotZ); character.ani.Play(AnimatorHash.ANIMATOR_weak, 0, 0); character.bodyCollider.layer = character.gameObject.layer; hitState = 1; } else { flyForce *= jumpNumRate; rb.AddForce(flyForce, ForceMode.Impulse); } BounceEffect(); } else { if (vel.x > 0) { vel.x -= decelerationRatioX * Time.deltaTime; } else { vel.x += decelerationRatioX * Time.deltaTime; } vel.y -= decelerationRatioY * Time.deltaTime; character.mecanim.transform.RotateAround( character.transform.position + rotateCenterHeight * Vector3.up, Vector3.forward, flyingRotateSpeed * Time.deltaTime); isFly = true; } break; case 1: //眩晕状态 if (attributeTime <= 0) { character.isAdjustHeight = 1; character.nowCanFly = character.canFly; OutSpecialState(); } else { if (vel.x > 0) { vel.x -= decelerationRatioX * Time.deltaTime; } else { vel.x += decelerationRatioX * Time.deltaTime; } if (!foot.TrigGround || vel.y > 0.1f) { vel.y -= decelerationRatioY * Time.deltaTime; } attributeTime -= Time.deltaTime; } break; } rb.velocity = vel; break; //眩晕 case SpecialState.Weak: if (attributeTime <= 0) { OutSpecialState(); } else { if (!character.isFrozen) rb.velocity = Vector3.zero; attributeTime -= Time.deltaTime; } break; } } void BounceEffect() { Transform spine = character.mecanim.transform; Sequence landSequence = DOTween.Sequence(); landSequence.Append(spine.DOScaleY(scale.y * compressionDegree, compressionSpeed.x)); landSequence.Append(spine.DOScaleY(scale.y, compressionSpeed.y)); } public void OutSpecialState() { character.mecanim.transform.localRotation = Quaternion.Euler(0, 0, 0); curSpecialStates = SpecialState.Null; if (character.canFly) { rb.useGravity = false; character.isAdjustHeight = 1; } character.ChangeState(CharacterState.Idle); } //判断优先级,ture为优先级高于当前控制 public bool PriorityOrder(SpecialState specialState, int controlOrder) { //控制层级小于控制抗性层级,该控制效果无效 if (controlOrder < resistances.controlOrder) { return false; } if (curSpecialStates == SpecialState.Null) { curSpecialStates = specialState; return true; } else { if (curSpecialStates >= specialState) { curSpecialStates = specialState; return true; } } return false; } //受到漂浮 public void AddFloat(AttackController.AttackMethod attackMethod) { if (resistances.Float == 1) { return; } this.attackMethod = attackMethod; AttackInfo.FloatState floatState = attackMethod.attackInfo.floatState; rb.isKinematic = false; rb.useGravity = false; floatingState = 1; origPos = character.transform.position; curHeight = origPos.y; riseTime = UnityEngine.Random.Range(floatState.upTime.x, floatState.upTime.y); backSpeed = UnityEngine.Random.Range(floatState.backSpeed.x, floatState.backSpeed.y); if (gameObject.tag == "Enemy" || gameObject.tag == "Player") { backSpeed = -backSpeed; } rotateSpeed = UnityEngine.Random.Range(floatState.rotateSpeed.x, floatState.rotateSpeed.y); rotateDir = (1.5f - UnityEngine.Random.Range(1, 3)) * 2; height = UnityEngine.Random.Range(floatState.height.x, floatState.height.y); attributeTime = floatState.time * (1 - resistances.Float); character.ChangeState(CharacterState.SpecialStatus_Float); character.ChangeStateText(CharacterState.SpecialStatus_Float); } //受到击飞 public void AddBlowUp(AttackController.AttackMethod attackMethod, Transform attackFrom) { if (resistances.BlowUp == 1) { return; } this.attackMethod = attackMethod; AttackInfo.BlowUp blowUp = attackMethod.attackInfo.blowUp; attributeTime = blowUp.time * (1 - resistances.BlowUp); Vector3 vec3 = new Vector3( blowUp.dir.x + UnityEngine.Random.Range(-blowUp.dirRandom.x / 2f, blowUp.dirRandom.x / 2f), blowUp.dir.y + UnityEngine.Random.Range(-blowUp.dirRandom.y / 2f, blowUp.dirRandom.y / 2f), 0).normalized; int attackDir = 0; switch (blowUp.directionType) { case AttackInfo.BlowUp.DirectionType.Common: attackDir = attackFrom.localScale.x < 0 ? -1 : 1; break; case AttackInfo.BlowUp.DirectionType.Spread: attackDir = attackFrom.position.x < transform.position.x ? -1 : 1; break; case AttackInfo.BlowUp.DirectionType.Explosion: attackDir = 1; vec3 = transform.position - attackFrom.transform.position; vec3.y += 0.5f; break; } if (attackDir < 0) { vec3.x = -vec3.x; } hitState = -1; character.ChangeState(CharacterState.SpecialStatus_BlowUp); character.ChangeStateText(CharacterState.SpecialStatus_BlowUp); rb.useGravity = true; rb.constraints = RigidbodyConstraints.FreezeRotation | RigidbodyConstraints.FreezePositionZ; rb.velocity = Vector3.zero; flyForce = vec3 * blowUp.force * (1 - resistances.BlowUp); rb.AddForce(flyForce, ForceMode.Impulse); rb.transform.rotation = Quaternion.Euler(0, 0, 0); character.mecanim.transform.RotateAround( character.transform.position + rotateCenterHeight * Vector3.up, Vector3.forward, startFlyAngle * attackDir); flyingRotateSpeed = UnityEngine.Random.Range(flyingRotateSpeedRange.x, flyingRotateSpeedRange.y) * attackDir; startFlyPos = transform.position; hitState = 0; isFly = false; jumpNum = blowUp.jumpNum; character.ani.Play("hitted", 0, 0); } //受到击落 public void AddShotDown(AttackController.AttackMethod attackMethod, Transform attackFrom) { if (resistances.ShotDown == 1) { return; } this.attackMethod = attackMethod; AttackInfo.ShotDown shotDown = attackMethod.attackInfo.shotDown; attributeTime = shotDown.time; Vector3 vec3 = new Vector3( shotDown.dir.x + UnityEngine.Random.Range(-shotDown.dirRandom.x / 2f, shotDown.dirRandom.x / 2f), shotDown.dir.y + UnityEngine.Random.Range(-shotDown.dirRandom.y / 2f, shotDown.dirRandom.y / 2f), 0).normalized; int attackDir = 0; switch (shotDown.directionType) { case AttackInfo.ShotDown.DirectionType.Common: attackDir = attackFrom.localScale.x < 0 ? -1 : 1; break; case AttackInfo.ShotDown.DirectionType.Spread: attackDir = attackFrom.position.x < transform.position.x ? -1 : 1; break; } if (attackDir < 0) { vec3.x = -vec3.x; } rb.useGravity = true; rb.constraints = RigidbodyConstraints.FreezeRotation | RigidbodyConstraints.FreezePositionZ; rb.velocity = Vector3.zero; rb.AddForce(vec3 * shotDown.force, ForceMode.Impulse); rb.transform.rotation = Quaternion.Euler(0, 0, 0); character.ani.Play("hitted", 0, 0); character.nowCanFly = false; startFlyPos = transform.position; hitState = 0; isFly = false; character.ChangeState(CharacterState.SpecialStatus_ShotDown); character.ChangeStateText(CharacterState.SpecialStatus_ShotDown); } //受到击晕 public void AddWeak(AttackController.AttackMethod attackMethod) { if (resistances.Weak == 1) { return; } this.attackMethod = attackMethod; AttackInfo.Weak weak = attackMethod.attackInfo.weak; attributeTime = weak.time * (1 - resistances.Weak); character.ani.Play("weak", 0, 0); character.ChangeState(CharacterState.SpecialStatus_Weak); character.ChangeStateText(CharacterState.SpecialStatus_Weak); } public void AddWeak(float _attributeTime) { if (resistances.Weak == 1 || character.isDie) { return; } attributeTime = _attributeTime; character.ani.Play("weak", 0, 0); character.ChangeState(CharacterState.SpecialStatus_Weak); character.ChangeStateText(CharacterState.SpecialStatus_Weak); } //受到穿甲 public int AddArmorPiercing(AttackController.AttackMethod attackMethod) { this.attackMethod = attackMethod; AttackInfo.ArmorPiercing armor = attackMethod.attackInfo.armorPiercing; //计算护甲减免 int am = resistances.armor; if (am > 0) { am = am - armor.rate; if (am < 0) { am = 0; } } return am; } //受到易伤 public void AddVulnerable(float _vulnerableRate,float _vulnerableTime) { if(vulnerableRate < _vulnerableRate) vulnerableRate += _vulnerableRate; vulnerableTime = _vulnerableTime; haveVulnerable = true; Debug.Log("添加易伤,vulnerableTime:" + vulnerableTime + ",vulnerableRate:" + vulnerableRate); } //受到累伤 public void AddStackingWouds(AttackController.AttackMethod attackMethod) { this.attackMethod = attackMethod; AttackInfo.StackingWounds stackingWounds = attackMethod.attackInfo.stackingWounds; if(stackingWoudsTime > 0) { stackingWords += attackMethod.attackInfo.stackingWounds.damage; } stackingWoudsTime = stackingWounds.time; } }