277 lines
10 KiB
C#
277 lines
10 KiB
C#
using System.Collections;
|
||
using System.Collections.Generic;
|
||
using UnityEngine;
|
||
|
||
using UnityEngine;
|
||
using System.Collections;
|
||
using DragonLi.Frame;
|
||
using UnityEngine.AI;
|
||
using Valheim;
|
||
|
||
public abstract class SkillLogicBase : ScriptableObject
|
||
{
|
||
[Header("技能基础数据")]
|
||
public SkillData skillData;
|
||
|
||
public int skillCount=1;//技能次数
|
||
/// <summary>
|
||
/// 判断是否可以使用技能,例如冷却、蓝量、距离等
|
||
/// 这里仅做示例,可根据项目需求扩展
|
||
/// </summary>
|
||
public virtual bool CanUseSkill(GameObject caster)
|
||
{
|
||
// 简单示例:若没有目标就不能释放
|
||
//if (target == null) return false;
|
||
//if (caster.GetComponent<Pet>() != null && !caster.GetComponent<Pet>().isUserSkill) return false;
|
||
// 其他逻辑检查,如距离、能量值、CD时间等
|
||
return true;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 技能执行的核心方法,通常使用协程
|
||
/// </summary>
|
||
public abstract IEnumerator ExecuteSkill(GameObject caster, GameObject target);
|
||
|
||
/// <summary>
|
||
/// 获取技能伤害区间
|
||
/// </summary>
|
||
public virtual float CalculateDamage()
|
||
{
|
||
// 简单随机
|
||
return Random.Range(skillData.MinAtk/skillCount, (skillData.MaxAtk + 1)/skillCount);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 单体伤害技能
|
||
/// </summary>
|
||
[CreateAssetMenu(fileName = "SingleAttackSkill", menuName = "Skills/SingleAttackSkill")]
|
||
public class SingleAttackSkill : SkillLogicBase
|
||
{
|
||
|
||
public override IEnumerator ExecuteSkill(GameObject caster, GameObject target)
|
||
{
|
||
skillCount = 1;
|
||
if (skillData.SkillId == 1)
|
||
{
|
||
skillCount = 2;
|
||
}
|
||
var agent = caster.GetComponent<Agent>();
|
||
|
||
// 1. 前摇等待
|
||
yield return new WaitForSeconds(skillData.UserTime);
|
||
GameManager.Ins.CreateSkill(skillData.SkillId,agent.skillPos.position,skillData.SkillTime,target.transform);
|
||
for (int i = 0; i < skillCount; i++)
|
||
{
|
||
// 2. 进行伤害计算
|
||
float damage = CalculateDamage();
|
||
// 根据需求,对目标进行伤害处理
|
||
// Debug.LogError($"技能[{skillData.SkillName}] 对目标造成了 {damage} 点伤害! 描述:{skillData.SkillDesc}");
|
||
|
||
// 如果技能有持续时长,可以继续等待
|
||
// if (skillData.SkillTime > 0)
|
||
// {
|
||
// yield return new WaitForSeconds(skillData.SkillTime);
|
||
// // 如果是持续伤害,可能需要多次结算
|
||
// // 这里只是演示一次结算
|
||
// }
|
||
if (target != null)
|
||
{
|
||
IDamagable damagable = target.GetComponent<IDamagable>();
|
||
if (damagable != null)
|
||
{
|
||
damagable.ApplyDamage(damage, false, caster.transform);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
// 5. 如果目标为 null,则进行自身范围检测
|
||
// 配置检测半径,可根据需求修改或放入配置数据中
|
||
float detectionRadius = 5f;
|
||
Collider[] hitColliders = Physics.OverlapSphere(caster.transform.position, detectionRadius);
|
||
foreach (var col in hitColliders)
|
||
{
|
||
// 只对标签为 "enemy" 的对象进行伤害处理
|
||
if (col.CompareTag("Enemy"))
|
||
{
|
||
IDamagable damagable = col.GetComponent<IDamagable>();
|
||
if (damagable != null)
|
||
{
|
||
damagable.ApplyDamage(damage, false, caster.transform);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
yield return new WaitForSeconds(0.2f);
|
||
}
|
||
Debug.Log("取消技能");
|
||
yield return new WaitForSeconds(skillData.SkillTime);
|
||
caster.GetComponent<Agent>().AnimatorComponent.SetBool("userSkill", false);
|
||
// 技能执行结束
|
||
yield break;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 范围伤害技能
|
||
/// </summary>
|
||
[CreateAssetMenu(fileName = "RangeAttackSkill", menuName = "Skills/RangeAttackSkill")]
|
||
public class RangeAttackSkill : SkillLogicBase
|
||
{
|
||
[Header("范围攻击配置")]
|
||
public float attackRadius = 30f; // 攻击半径
|
||
public LayerMask targetLayer; // 目标所属的图层
|
||
|
||
public override IEnumerator ExecuteSkill(GameObject caster, GameObject target)
|
||
{
|
||
skillCount = 1;
|
||
var agent = caster.GetComponent<Agent>();
|
||
// 1. 前摇等待
|
||
yield return new WaitForSeconds(skillData.UserTime);
|
||
GameManager.Ins.CreateSkill(skillData.SkillId,agent.skillPos.position,skillData.SkillTime,target.transform);
|
||
for (int i = 0; i < skillData.SkillTime; i++)
|
||
{
|
||
targetLayer=target.layer;
|
||
// 2. 查找范围内所有可攻击的目标
|
||
// 这里以 Physics.OverlapSphere 为例,需要目标带有 Collider
|
||
Collider[] hitColliders = Physics.OverlapSphere(caster.transform.position, attackRadius, targetLayer);
|
||
|
||
// 3. 对每个目标造成伤害
|
||
foreach (var col in hitColliders)
|
||
{
|
||
// 简单示例:计算伤害
|
||
float damage = CalculateDamage();
|
||
//Debug.LogError($"[范围攻击] 技能[{skillData.SkillName}] 对 [{col.name}] 造成 {damage} 点伤害!");
|
||
// 在这里可以调用目标的受伤方法(如 target.TakeDamage(damage))
|
||
IDamagable damagable = col.GetComponent<IDamagable>();
|
||
if (damagable != null)
|
||
{
|
||
damagable.ApplyDamage(damage, false, caster.transform);
|
||
}
|
||
}
|
||
yield return new WaitForSeconds(1f);
|
||
}
|
||
// 4. 如果技能有持续时间,可在这段时间内多次范围伤害
|
||
// 这里演示一次,如果需要多段伤害,可用循环或协程多次执行
|
||
// if (skillData.SkillTime > 0)
|
||
// {
|
||
// // 示例:间隔 0.5 秒,再次范围伤害一次
|
||
// yield return new WaitForSeconds(skillData.SkillTime);
|
||
// // 也可以再次执行范围伤害或结束
|
||
// // ...
|
||
// }
|
||
Debug.Log("取消技能");
|
||
yield return new WaitForSeconds(skillData.SkillTime);
|
||
caster.GetComponent<Agent>().AnimatorComponent.SetBool("userSkill", false);
|
||
// 技能执行结束
|
||
yield break;
|
||
}
|
||
}
|
||
|
||
//持续伤害技能
|
||
[CreateAssetMenu(fileName = "DotAttackSkill", menuName = "Skills/DotAttackSkill")]
|
||
public class DotAttackSkill : SkillLogicBase
|
||
{
|
||
[Header("持续伤害配置")]
|
||
public float tickInterval = 1f; // 每隔多少秒造成一次伤害
|
||
public int tickCount = 3; // 一共造成几次伤害
|
||
|
||
public override IEnumerator ExecuteSkill(GameObject caster, GameObject target)
|
||
{
|
||
// 1. 前摇等待
|
||
yield return new WaitForSeconds(skillData.UserTime);
|
||
var agent = caster.GetComponent<Agent>();
|
||
GameManager.Ins.CreateSkill(skillData.SkillId,agent.skillPos.position,10,target.transform);
|
||
// 2. 开始持续伤害
|
||
int currentTick = 0;
|
||
while (currentTick < tickCount)
|
||
{
|
||
// 计算伤害
|
||
float damage = CalculateDamage();
|
||
Debug.Log($"[持续伤害] 技能[{skillData.SkillName}] 第{currentTick + 1}次,对 [{target.name}] 造成 {damage} 点伤害!");
|
||
// 在这里可以调用目标的受伤方法(如 target.TakeDamage(damage))
|
||
|
||
currentTick++;
|
||
|
||
// 如果到了 tickCount 次或超过技能持续时间,则退出
|
||
if (currentTick >= tickCount || (skillData.SkillTime > 0 && currentTick * tickInterval >= skillData.SkillTime))
|
||
{
|
||
break;
|
||
}
|
||
|
||
// 等待下一次伤害
|
||
yield return new WaitForSeconds(tickInterval);
|
||
}
|
||
yield break;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Buff技能
|
||
/// </summary>
|
||
[CreateAssetMenu(fileName = "BuffSkill", menuName = "Skills/BuffSkill")]
|
||
public class BuffSkill : SkillLogicBase
|
||
{
|
||
[Header("Buff配置")]
|
||
public float buffValue = 1.2f; // 假设加成倍数,比如攻击力提升 20%
|
||
public bool isAttackBuff = true; // 简单示例:是否是攻击力Buff
|
||
|
||
public override IEnumerator ExecuteSkill(GameObject caster, GameObject target)
|
||
{
|
||
var agent = caster.GetComponent<Agent>();
|
||
GameManager.Ins.CreateSkill(skillData.SkillId,agent.skillPos.position,10,target.transform);
|
||
// 1. 前摇等待
|
||
yield return new WaitForSeconds(skillData.UserTime);
|
||
|
||
if (target != null)
|
||
{
|
||
Debug.Log($"[Buff] 技能[{skillData.SkillName}] 给 [{target.name}] 施加 Buff,持续 {skillData.SkillTime} 秒");
|
||
}
|
||
|
||
// 2. 给目标施加 Buff
|
||
|
||
|
||
// 在这里实现具体的 Buff 效果,例如:
|
||
// 1) 提升攻击力
|
||
// 2) 提升防御力
|
||
// 3) 提升移动速度
|
||
// 4) 免控、减伤等等
|
||
|
||
// 例如:如果目标有一个 PetStatus/CharacterStatus 脚本来管理属性
|
||
// var status = target.GetComponent<CharacterStatus>();
|
||
// if (status != null && isAttackBuff)
|
||
// {
|
||
// status.attack *= buffValue;
|
||
// }
|
||
|
||
// 3. 持续时间内维持 Buff 效果
|
||
if (skillData.SkillTime > 0)
|
||
{
|
||
yield return new WaitForSeconds(skillData.SkillTime);
|
||
// Buff 结束时,恢复属性
|
||
// if (status != null && isAttackBuff)
|
||
// {
|
||
// status.attack /= buffValue;
|
||
// }
|
||
if (skillData.SkillId == 3)
|
||
{
|
||
int index= Random.Range(1,GameManager.Ins.PetList.Count);
|
||
GameManager.Ins.PetList[index].AddBlood(0,GameManager.Ins.PetList[index].OriginHealth*0.25f);
|
||
}
|
||
Debug.Log($"[Buff] 技能[{skillData.SkillName}] Buff 效果结束");
|
||
}
|
||
agent.AnimatorComponent.SetBool("userSkill", false);
|
||
yield break;
|
||
}
|
||
|
||
public void AddHpSkill()
|
||
{
|
||
|
||
}
|
||
}
|
||
|
||
|
||
|
||
|
||
|