Files
valheim/Assets/_Valheim/Scripts/Skill/SkillLogicBase.cs
2025-07-04 14:16:14 +08:00

277 lines
10 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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()
{
}
}