2025-05-18 01:04:31 +08:00

783 lines
16 KiB
C#

// ***********************************************************************
// Assembly : Game
// Author : Kimch
// Created : 2020-11-21
// Description :
// Last Modified By :
// Last Modified On :
// ***********************************************************************
// <copyright file= "Cha_Moves" company="Kunpo"></copyright>
// <summary></summary>
// ***********************************************************************
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace G
{
/// <summary>
/// 处理招式逻辑
/// </summary>
public class Cha_Moves : MonoBehaviour
{
public enum ArgIndex
{
Probability = 0,
ExtraDamage = 1,
ExtraDamagePercent = 2,
Cooltime = 3,
CooltimePercent = 4,
ReduceTime = 5,
Amount = 6,
Duration = 7,
Special1 = 8,
Special2 = 9,
}
public class MovesInfo
{
public const int MAX_ARGS_COUNT = 10;
/// <summary>
///
/// </summary>
public int id;
/// <summary>
///
/// </summary>
public int parentId;
/// <summary>
///
/// </summary>
public int trigger;
/// <summary>
///
/// </summary>
public readonly int[] kindArgs = new int[MAX_ARGS_COUNT];
/// <summary>
/// 1技能 2buff
/// </summary>
public int targetType;
/// <summary>
/// 相关技能参数
/// </summary>
public int targetId;
public int skillKind;
public int[] skillKindArgs;
/// <summary>
/// 累计等级
/// </summary>
public int level;
/// <summary>
/// 生命周期
/// </summary>
public float lifeTime;
/// <summary>
/// 上次使用时间
/// </summary>
public float lastApplyTime = -999f;
/// <summary>
/// 概率
/// </summary>
public int probability
{
get { return kindArgs[0]; }
}
/// <summary>
/// 数量
/// </summary>
public int amount
{
get { return kindArgs[6]; }
}
/// <summary>
/// 持续时间
/// </summary>
public float duration
{
get { return kindArgs[7] * 0.001f; }
}
/// <summary>
/// 减少的时间
/// </summary>
public float reduceTime
{
get { return kindArgs[5] * 0.001f; }
}
/// <summary>
/// 冷却时间
/// </summary>
public float cooltime
{
get { return kindArgs[3] * kindArgs[4] * 0.00001f; }
}
/// <summary>
///
/// </summary>
public int extraDamage
{
get { return kindArgs[1]; }
}
/// <summary>
///
/// </summary>
public int extraDamagePercent
{
get { return kindArgs[2] - 100; }
}
/// <summary>
///
/// </summary>
public float elapse
{
get { return Time.time - lastApplyTime; }
set { lastApplyTime = Time.time - value; }
}
/// <summary>
///
/// </summary>
public MovesInfo root;
public float uiSkillCoolDown;
public float uiSkillCoolTime;
/// <summary>
/// 减少
/// </summary>
/// <param name="time"></param>
public void Reduce(float time)
{
if (root != null)
root.Reduce(time);
else
lastApplyTime -= time;
}
/// <summary>
///
/// </summary>
public void ReduceAll()
{
lastApplyTime = 0;
}
/// <summary>
///
/// </summary>
/// <param name="damage"></param>
/// <returns></returns>
public int GetDamage(int damage)
{
return damage * kindArgs[2] + kindArgs[1];
}
public void OnTrigger()
{
float reduce = reduceTime;
if (reduce > 0f)
{
Reduce(reduce);
}
}
}
/// <summary>
///
/// </summary>
#region Field
/// <summary>
///
/// </summary>
private readonly Dictionary<int, MovesInfo> _buffDict = new Dictionary<int, MovesInfo>();
/// <summary>
/// 目标类型
/// </summary>
private readonly Dictionary<int, List<MovesInfo>> _typeBuffDict = new Dictionary<int, List<MovesInfo>>();
private EntityPlayer _scriptCha;
#endregion
#region Property
/// <summary>
/// 全局减cd参数
/// </summary>
public float skillCdRate
{
get { return (100 - _scriptCha.reduceCd) * 0.01f; }
}
// 翻滚穿刺
private MovesInfo _dodgeBuff;
//跳劈逻辑
private MovesInfo _thumpBuff;
/// <summary>
/// 跳劈暴击
/// </summary>
private MovesInfo _thumpCriticalBuff;
//反击
private MovesInfo _counterBuff;
//濒死
private MovesInfo _avoidDeathBuff;
/// <summary>
/// 清cd buff
/// </summary>
private MovesInfo _attackClearSkillCdBuff;
/// <summary>
/// 翻滚穿刺
/// </summary>
public int dodgeType
{
get { return _dodgeBuff != null ? 1 : 0; }
}
/// <summary>
/// 跳劈
/// </summary>
public bool canThump
{
get
{
if (_thumpBuff != null && Time.time - _thumpBuff.lastApplyTime > _thumpBuff.cooltime)
{
_thumpBuff.lastApplyTime = Time.time;
if (_thumpCriticalBuff != null)
{
_thumpCriticalBuff.lifeTime = Time.time + _thumpCriticalBuff.duration;
}
return true;
}
return false;
}
}
public int thumpType
{
get { return _thumpBuff.amount; }
}
public int thumpExtraDamage
{
get { return _thumpBuff.extraDamage; }
}
public int thumpExtraDamagePercent
{
get { return _thumpBuff.extraDamagePercent; }
}
public int CalcThumpDamage(int damage)
{
if (_thumpBuff != null)
{
return _thumpBuff.GetDamage(damage);
}
return damage;
}
/// <summary>
/// 跳劈一秒暴击
/// </summary>
public bool canCritical
{
get
{
if (_thumpCriticalBuff != null && _thumpCriticalBuff.lifeTime - Time.time > 0f)
{
return true;
}
return false;
}
}
/// <summary>
/// 受伤反击
/// </summary>
public bool counterAttack
{
get
{
if (_counterBuff != null && _counterBuff.probability > GlobalUtils.RndHundred)
{
return true;
}
return false;
}
}
/// <summary>
/// 免死
/// </summary>
public bool avoidDeath
{
get
{
if (_avoidDeathBuff != null)
{
_avoidDeathBuff = null;
return true;
}
return false;
}
}
/// <summary>
///
/// </summary>
private MovesInfo _autoCastSkill;
/// <summary>
/// 自动施法
/// </summary>
public bool autoCastSkill
{
get { return _scriptCha.autoCastSkill; }
set { _scriptCha.autoCastSkill = value; }
}
#endregion
#region Method
/// <summary>
///
/// </summary>
/// <param name="id"></param>
/// <param name="doubleValue"></param>
public void AddMoves(int id, bool doubleValue)
{
if (!_buffDict.ContainsKey(id))
{
var movesItem = ItemProxy.Instance.GetStaticItem<ItemMoves>(id);
var moves = new MovesInfo
{
id = movesItem.id,
parentId = movesItem.parent,
trigger = movesItem.trigger,
targetType = movesItem.targetType,
targetId = movesItem.targetId,
level = doubleValue ? 2 : 1,
};
//本体
var args = movesItem.targetArgs;
if (args != null)
for (int i = Mathf.Min(MovesInfo.MAX_ARGS_COUNT, args.Length) - 1; i >= 0; i--)
moves.kindArgs[i] = args[i];
//全局
_scriptCha.ApplyGlobalMovesArgs(movesItem.id, moves.kindArgs);
//args = _scriptCha.GetGlobalMovesArgs(movesItem.id);
//if (args != null)
// for (int i = Mathf.Min(MovesInfo.MAX_ARGS_COUNT, args.Length) - 1; i >= 0; i--)
// moves.kindArgs[i] += args[i];
if (moves.parentId > 0 && _buffDict.TryGetValue(moves.parentId, out var parentMoves))
{
//get root
while (parentMoves.parentId > 0 && _buffDict.TryGetValue(parentMoves.parentId, out parentMoves))
{
};
if (parentMoves != null)
{
moves.root = parentMoves;
for (int i = MovesInfo.MAX_ARGS_COUNT - 1; i >= 0; i--)
parentMoves.kindArgs[i] += moves.kindArgs[i];
}
}
AddMoves(moves.trigger, moves);
InitMoves(moves, doubleValue);
}
else
{
Debug.Log($"武学不能重复学习 {id}");
}
}
/// <summary>
///
/// </summary>
/// <param name="id"></param>
/// <param name="doubleValue"></param>
public void AddMovesByBuff(int id, bool doubleValue)
{
var buffItem = ItemProxy.Instance.GetStaticItem<ItemBuff>(id);
if (buffItem != null)
{
var kind = buffItem.kind;
var kindArgs = buffItem.kindArgs;
if (buffItem.kind == 1)
{
_scriptCha.AttributeUp(kindArgs[0], (!doubleValue ? kindArgs[1] : kindArgs[1] * 2), 0);
}
else if (kind == 2)
{
_scriptCha.AttributeUp(kindArgs[0], 0, (!doubleValue ? kindArgs[1] : kindArgs[1] * 2));
}
else if (kind == 3)//特殊类型固定值
{
var sf = kindArgs[0];
if (sf == 1)
{
_scriptCha.HpUp(kindArgs[1], 0);
}
}
else if (kind == 4)//特殊类型百分比
{
var sf = kindArgs[0];
if (sf == 1)
{
_scriptCha.HpUp(0, kindArgs[1]);
}
}
}
}
/// <summary>
///
/// </summary>
/// <param name="id"></param>
public void AddMovesBySkill(int id)
{
}
/// <summary>
///
/// </summary>
/// <param name="trigger"></param>
/// <param name="moves"></param>
private void AddMoves(int trigger, MovesInfo moves)
{
_buffDict.Add(moves.id, moves);
if (trigger > 0)
{
if (_typeBuffDict.TryGetValue(trigger, out List<MovesInfo> buffList))
{
buffList.Add(moves);
}
else
{
_typeBuffDict.Add(trigger, new List<MovesInfo> { moves });
}
}
}
/// <summary>
///
/// </summary>
/// <param name="moves"></param>
/// <param name="doubleValue"></param>
private void InitMoves(MovesInfo moves, bool doubleValue)
{
//Skill
if (moves.targetType == 1)
{
var skillItem = ItemProxy.Instance.GetStaticItem<ItemSkill>(moves.targetId);
if (skillItem != null)
{
moves.skillKind = skillItem.kind;
moves.skillKindArgs = skillItem.kindArgs;
//添加技能图标
if (moves.trigger == 1)
{
GlobalNotifier.PostNotification(GlobalDefine.EVENT_SKILL_STATE, moves, "add_skill");
}
}
}
else if (moves.targetType == 2)
{
var buffItem = ItemProxy.Instance.GetStaticItem<ItemBuff>(moves.targetId);
if (buffItem != null)
{
moves.skillKind = buffItem.kind;
moves.skillKindArgs = buffItem.kindArgs;
if (moves.skillKind == 1)
{
_scriptCha.AttributeUp(moves.skillKindArgs[0], (!doubleValue ? moves.skillKindArgs[1] : moves.skillKindArgs[1] * 2), 0);
}
else if (moves.skillKind == 2)
{
_scriptCha.AttributeUp(moves.skillKindArgs[0], 0, (!doubleValue ? moves.skillKindArgs[1] : moves.skillKindArgs[1] * 2));
}
else if (moves.skillKind == 3)//
{
var sf = moves.skillKindArgs[0];
if (sf == 1)
{
_scriptCha.HpUp(moves.skillKindArgs[1], 0);
}
}
//特殊类型百分比
else if (moves.skillKind == 4)//
{
var sf = moves.skillKindArgs[0];
if (sf == 1)
{
_scriptCha.HpUp(0, moves.skillKindArgs[1]);
}
}
}
}
else
{
//特殊武学
if (moves.targetId == 10013)
{
if (moves.parentId == 0)
_thumpBuff = moves;
}
else if (moves.targetId == 10017)
{
_dodgeBuff = moves;
}
else if (moves.targetId == 10018)
{
_attackClearSkillCdBuff = moves;
}
else if (moves.targetId == 10021)
{
_thumpCriticalBuff = moves;
}
else if (moves.targetId == 10026)
{
_avoidDeathBuff = moves;
}
else if (moves.targetId == 10027)
{
if (moves.parentId == 0)
_counterBuff = moves;
}
else if (moves.targetId == 10029)
{
autoCastSkill = true;
_autoCastSkill = moves;
}
else if (moves.targetId == 10001)
{
GameLevel.Instance.gameSpeed = 2f;
}
}
}
/// <summary>
///
/// </summary>
/// <param name="moves"></param>
/// <param name="trigger"></param>
/// <returns></returns>
private bool ApplyMoves(MovesInfo moves, int trigger = 0)
{
if ((moves.trigger & trigger) != 0)
{
moves.OnTrigger();
//其它
}
if (moves.targetType == 1)
{
// 可以释放
if (moves.parentId == 0)
{
float cooltime = moves.cooltime * this.skillCdRate;/// (1000 * 100);
if (moves.elapse > cooltime && moves.probability > GlobalUtils.RndHundred)
{
moves.elapse = 0;
if (moves.skillKind > 0)
_scriptCha.scriptSkill.FireSkill(moves.skillKind, moves.kindArgs);
else
Debug.LogError("无效技能类型 " + moves.targetId);
return true;
}
}
}
else if (moves.targetType == 2)
{
//
return true;
}
return false;
}
//TODO 采用更新的方法
private void UpdateBuff()
{
if (_typeBuffDict.TryGetValue(1, out List<MovesInfo> skillBuffs))
{
for (int i = 0; i < skillBuffs.Count; i++)
{
var buff = skillBuffs[i];
buff.uiSkillCoolTime = buff.cooltime * skillCdRate;
buff.uiSkillCoolDown = buff.uiSkillCoolTime - buff.elapse;
}
}
}
/// <summary>
/// 触发类型(4)
/// </summary>
/// <param name="style"></param>
private void OnAttack(int style)
{
if (_typeBuffDict.TryGetValue(4, out List<MovesInfo> skillBuffs))
foreach (var buff in skillBuffs)
{
ApplyMoves(buff, 4);
//
//if (clearCd)
//{
// buff.ReduceAll();
//}
}
//if (_typeBuffDict.TryGetValue(2 | 4, out List<MovesInfo> buffBuffs))
// foreach (var buff in buffBuffs)
// {
// ApplyBuff(buff, 4);
// }
}
/// <summary>
/// 触发类型(16)
/// </summary>
private void OnKill(int type)
{
if (_attackClearSkillCdBuff != null && _attackClearSkillCdBuff.probability > GlobalUtils.RndHundred)
{
ReduceAllSkillCD();
}
else
{
int killCooldown = _scriptCha.GetCurrentValue(CombatAttributeId.KillCooldown);
if (killCooldown > 0)
{
ReduceSkillCD(0.01f * killCooldown);
}
}
if (_typeBuffDict.TryGetValue(16, out List<MovesInfo> skillBuffs))
foreach (var buff in skillBuffs)
{
ApplyMoves(buff, 16);
}
}
/// <summary>
///
/// </summary>
/// <param name="damage"></param>
private void OnHurt(int damage)
{
if (this.counterAttack)
_scriptCha.scriptSkill.BoomOn(0, true);
}
/// <summary>
/// 触发类型(8)
/// </summary>
private void OnDodge(int type)
{
if (_typeBuffDict.TryGetValue(8, out List<MovesInfo> skillBuffs))
foreach (var buff in skillBuffs)
{
ApplyMoves(buff, 8);
}
}
/// <summary>
///
/// </summary>
/// <param name="moves"></param>
/// <returns></returns>
public bool CastSkill(MovesInfo moves)
{
if (moves != null && moves.targetType == 1 && moves.parentId == 0)
{
return ApplyMoves(moves, 0);
}
return false;
}
public void AutoCastSkill()
{
if (autoCastSkill && _typeBuffDict.TryGetValue(1, out List<MovesInfo> skillBuffs) && skillBuffs != null)
{
for (int i = 0; i < skillBuffs.Count; i++)
{
var buff = skillBuffs[i];
if (ApplyMoves(buff, 0))
break;
}
}
}
public void ReduceSkillCD(float reduce)
{
if (_typeBuffDict.TryGetValue(1, out List<MovesInfo> skillBuffs))
{
for (int i = 0; i < skillBuffs.Count; i++)
{
var buff = skillBuffs[i];
if (reduce > 0f)
{
buff.Reduce(reduce);
}
}
}
}
public void ReduceAllSkillCD()
{
if (_typeBuffDict.TryGetValue(1, out List<MovesInfo> skillBuffs))
{
for (int i = 0; i < skillBuffs.Count; i++)
{
var buff = skillBuffs[i];
buff.ReduceAll();
}
}
}
#endregion
#region Unity
private void Awake()
{
_scriptCha = GetComponent<EntityMainPlayer>();
_scriptCha.OnAttack += this.OnAttack;
_scriptCha.OnDodge += this.OnDodge;
_scriptCha.OnHurt += this.OnHurt;
_scriptCha.OnKill += this.OnKill;
}
private void Update()
{
UpdateBuff();
}
#endregion
}
}