229 lines
6.8 KiB
C#
229 lines
6.8 KiB
C#
using System;
|
|
using EntityStates;
|
|
using JetBrains.Annotations;
|
|
using UnityEngine;
|
|
using UnityEngine.Serialization;
|
|
|
|
namespace RoR2.Skills;
|
|
|
|
[CreateAssetMenu(menuName = "RoR2/SkillDef/Generic")]
|
|
public class SkillDef : ScriptableObject
|
|
{
|
|
public class BaseSkillInstanceData
|
|
{
|
|
}
|
|
|
|
[Tooltip("The name of the skill. This is mainly for purposes of identification in the inspector and currently has no direct effect.")]
|
|
[Header("Skill Identifier")]
|
|
public string skillName = "";
|
|
|
|
[Tooltip("The language token with the name of this skill.")]
|
|
[Header("User-Facing Info")]
|
|
public string skillNameToken = "";
|
|
|
|
[Tooltip("The language token with the description of this skill.")]
|
|
public string skillDescriptionToken = "";
|
|
|
|
[Tooltip("Extra tooltips when hovered over in character select. Currently only used in that area!")]
|
|
public string[] keywordTokens;
|
|
|
|
[Tooltip("The icon to display for this skill.")]
|
|
[ShowThumbnail]
|
|
public Sprite icon;
|
|
|
|
[Header("State Machine Parameters")]
|
|
[Tooltip("The state machine this skill operates upon.")]
|
|
public string activationStateMachineName;
|
|
|
|
[Tooltip("The state to enter when this skill is activated.")]
|
|
public SerializableEntityStateType activationState;
|
|
|
|
[Tooltip("The priority of this skill.")]
|
|
public InterruptPriority interruptPriority = InterruptPriority.Skill;
|
|
|
|
[Tooltip("How long it takes for this skill to recharge after being used.")]
|
|
[Header("Stock and Cooldown")]
|
|
public float baseRechargeInterval = 1f;
|
|
|
|
[Tooltip("Maximum number of charges this skill can carry.")]
|
|
public int baseMaxStock = 1;
|
|
|
|
[Tooltip("How much stock to restore on a recharge.")]
|
|
public int rechargeStock = 1;
|
|
|
|
[Tooltip("How much stock is required to activate this skill.")]
|
|
public int requiredStock = 1;
|
|
|
|
[Tooltip("How much stock to deduct when the skill is activated.")]
|
|
public int stockToConsume = 1;
|
|
|
|
[Tooltip("Makes the skill restock interval divided by attack speed if checked.")]
|
|
public bool attackSpeedBuffsRestockSpeed;
|
|
|
|
[Tooltip("Increases the efficacy of attack speed on restock time.")]
|
|
[Range(1f, 10f)]
|
|
public float attackSpeedBuffsRestockSpeed_Multiplier = 1f;
|
|
|
|
[Tooltip("Whether or not it resets any progress on cooldowns.")]
|
|
[Header("Optional Parameters, Stock")]
|
|
[FormerlySerializedAs("isBullets")]
|
|
public bool resetCooldownTimerOnUse;
|
|
|
|
[Tooltip("Whether or not to fully restock this skill when it's assigned.")]
|
|
public bool fullRestockOnAssign = true;
|
|
|
|
[Tooltip("Whether or not this skill can hold past it's maximum stock.")]
|
|
public bool dontAllowPastMaxStocks;
|
|
|
|
[Tooltip("Whether or not the cooldown waits until it leaves the set state")]
|
|
public bool beginSkillCooldownOnSkillEnd;
|
|
|
|
[Tooltip("Whether or not activating the skill forces off sprinting.")]
|
|
[FormerlySerializedAs("noSprint")]
|
|
[Header("Optional Parameters, Sprinting")]
|
|
public bool cancelSprintingOnActivation = true;
|
|
|
|
[FormerlySerializedAs("mobilitySkill")]
|
|
[Tooltip("Whether or not this skill is considered 'mobility'. Currently just forces sprint.")]
|
|
public bool forceSprintDuringState;
|
|
|
|
[Tooltip("Whether or not sprinting sets the skill's state to be reset.")]
|
|
public bool canceledFromSprinting;
|
|
|
|
[Header("Optional Parameters, Misc")]
|
|
[Tooltip("Whether or not this is considered a combat skill.")]
|
|
public bool isCombatSkill = true;
|
|
|
|
[Tooltip("The skill can't be activated if the key is held.")]
|
|
public bool mustKeyPress;
|
|
|
|
[Tooltip("If true, CharacterBody handles LuminiousShot buffs. If false, the skill must handle it.")]
|
|
public bool autoHandleLuminousShot = true;
|
|
|
|
[Tooltip("If true, the SkillIcon will not show this skill's stock count.")]
|
|
public bool hideStockCount;
|
|
|
|
[Obsolete("Accessing UnityEngine.Object.Name causes allocations on read. Look up the name from the catalog instead. If absolutely necessary to perform direct access, cast to ScriptableObject first.")]
|
|
public new string name => null;
|
|
|
|
public int skillIndex { get; set; }
|
|
|
|
public virtual BaseSkillInstanceData OnAssigned([NotNull] GenericSkill skillSlot)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
public virtual void OnUnassigned([NotNull] GenericSkill skillSlot)
|
|
{
|
|
}
|
|
|
|
public virtual Sprite GetCurrentIcon([NotNull] GenericSkill skillSlot)
|
|
{
|
|
return icon;
|
|
}
|
|
|
|
public virtual string GetCurrentNameToken([NotNull] GenericSkill skillSlot)
|
|
{
|
|
return skillNameToken;
|
|
}
|
|
|
|
public virtual string GetCurrentDescriptionToken([NotNull] GenericSkill skillSlot)
|
|
{
|
|
return skillDescriptionToken;
|
|
}
|
|
|
|
protected bool HasRequiredStockAndDelay([NotNull] GenericSkill skillSlot)
|
|
{
|
|
return skillSlot.stock >= requiredStock;
|
|
}
|
|
|
|
public virtual bool CanExecute([NotNull] GenericSkill skillSlot)
|
|
{
|
|
if (HasRequiredStockAndDelay(skillSlot) && IsReady(skillSlot) && (bool)skillSlot.stateMachine && !skillSlot.stateMachine.HasPendingState())
|
|
{
|
|
return skillSlot.stateMachine.CanInterruptState(interruptPriority);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public virtual bool IsReady([NotNull] GenericSkill skillSlot)
|
|
{
|
|
return HasRequiredStockAndDelay(skillSlot);
|
|
}
|
|
|
|
protected virtual EntityState InstantiateNextState([NotNull] GenericSkill skillSlot)
|
|
{
|
|
EntityState entityState = EntityStateCatalog.InstantiateState(ref activationState);
|
|
if (entityState is ISkillState skillState)
|
|
{
|
|
skillState.activatorSkillSlot = skillSlot;
|
|
}
|
|
return entityState;
|
|
}
|
|
|
|
public virtual void OnExecute([NotNull] GenericSkill skillSlot)
|
|
{
|
|
skillSlot.stateMachine.SetInterruptState(InstantiateNextState(skillSlot), interruptPriority);
|
|
if (cancelSprintingOnActivation)
|
|
{
|
|
skillSlot.characterBody.isSprinting = false;
|
|
}
|
|
skillSlot.stock -= stockToConsume;
|
|
if (resetCooldownTimerOnUse)
|
|
{
|
|
skillSlot.rechargeStopwatch = 0f;
|
|
}
|
|
if ((bool)skillSlot.characterBody)
|
|
{
|
|
skillSlot.characterBody.OnSkillActivated(skillSlot);
|
|
}
|
|
}
|
|
|
|
public virtual void OnFixedUpdate([NotNull] GenericSkill skillSlot, float deltaTime)
|
|
{
|
|
skillSlot.RunRecharge(deltaTime);
|
|
if (((canceledFromSprinting && skillSlot.characterBody.isSprinting) || forceSprintDuringState) && skillSlot.stateMachine.state.GetType() == activationState.stateType)
|
|
{
|
|
if (canceledFromSprinting && skillSlot.characterBody.isSprinting)
|
|
{
|
|
skillSlot.stateMachine.SetNextStateToMain();
|
|
}
|
|
if (forceSprintDuringState)
|
|
{
|
|
skillSlot.characterBody.isSprinting = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
public bool IsAlreadyInState([NotNull] GenericSkill skillSlot)
|
|
{
|
|
return skillSlot?.stateMachine.state.GetType() == activationState.stateType;
|
|
}
|
|
|
|
public virtual int GetMaxStock([NotNull] GenericSkill skillSlot)
|
|
{
|
|
return baseMaxStock;
|
|
}
|
|
|
|
public virtual int GetRechargeStock([NotNull] GenericSkill skillSlot)
|
|
{
|
|
return rechargeStock;
|
|
}
|
|
|
|
public virtual float GetRechargeInterval([NotNull] GenericSkill skillSlot)
|
|
{
|
|
if (attackSpeedBuffsRestockSpeed)
|
|
{
|
|
float num = skillSlot.characterBody.attackSpeed - skillSlot.characterBody.baseAttackSpeed;
|
|
num *= attackSpeedBuffsRestockSpeed_Multiplier;
|
|
num += 1f;
|
|
if (num < 0.5f)
|
|
{
|
|
num = 0.5f;
|
|
}
|
|
return baseRechargeInterval / num;
|
|
}
|
|
return baseRechargeInterval;
|
|
}
|
|
}
|