Class DeflectBuffTemplate
Buff template that turns incoming ability objects away instead of absorbing them — the Deflect half of block and deflect.
[CreateAssetMenu(fileName = "New Deflect Buff Template", menuName = "FishMMO/Character/Buff/Deflect Buff", order = 4)]
public class DeflectBuffTemplate : BaseBuffTemplate, ICachedObject, ITooltip
- Inheritance
-
ObjectScriptableObjectDeflectBuffTemplate
- Implements
- Inherited Members
-
ScriptableObject.SetDirty()ScriptableObject.CreateInstance<T>()Object.GetEntityId()Object.GetInstanceID()Object.GetHashCode()Object.InstantiateAsync<T>(T)Object.InstantiateAsync<T>(T, Transform)Object.InstantiateAsync<T>(T, Vector3, Quaternion)Object.InstantiateAsync<T>(T, Transform, Vector3, Quaternion)Object.Instantiate(Object, Vector3, Quaternion)Object.Instantiate(Object, Vector3, Quaternion, Transform)Object.Instantiate(Object)Object.Instantiate(Object, Scene)Object.Instantiate<T>(T, InstantiateParameters)Object.Instantiate<T>(T, Vector3, Quaternion, InstantiateParameters)Object.Instantiate(Object, Transform)Object.Instantiate<T>(T)Object.Instantiate<T>(T, Vector3, Quaternion)Object.Instantiate<T>(T, Vector3, Quaternion, Transform)Object.Instantiate<T>(T, Transform)Object.Destroy(Object)Object.DestroyImmediate(Object)Object.DontDestroyOnLoad(Object)Object.DestroyObject(Object)Object.FindObjectsOfType<T>()Object.FindObjectsByType<T>(FindObjectsSortMode)Object.FindObjectsByType<T>(FindObjectsInactive, FindObjectsSortMode)Object.FindObjectOfType<T>()Object.FindFirstObjectByType<T>()Object.FindAnyObjectByType<T>()Object.FindFirstObjectByType<T>(FindObjectsInactive)Object.FindAnyObjectByType<T>(FindObjectsInactive)Object.FindObjectsByType<T>()Object.FindObjectsByType<T>(FindObjectsInactive)Object.ToString()Object.nameObject.hideFlags
- Extension Methods
Remarks
A deflect is a REJECTED hit, not a mitigated one. Damage negation runs inside
CharacterDamageController.Damage, after the projectile has already connected; this
runs earlier, in AbilityObject.ApplyHit, before the hit is accepted at all. The
projectile never counts as having struck the defender, its OnHit events never fire, and it
carries on along a new heading — so nothing downstream has to know a deflect happened.
Which way it goes is not a choice. The new heading is the incoming one reflected about
the impact normal, and both the server and every observer compute it from the SAME normal —
the one the server measured inside its rewind scope and put in
AbilityObjectHitBroadcast. No new field on that message beyond the one bit that says a
deflection happened, and no way for two peers to disagree about where the projectile went.
Two authored limits, and they compose. DeflectAngleDegrees decides what can be deflected — a narrow guard covers the sword in front and nothing else — and MaxDeflections decides how often, spending RemainingCharges so a parry that turns one arrow ends the moment it does its job. Leave MaxDeflections at zero for a window that deflects everything that arrives while it is up, which is the short reactive parry the deflect ability wants.
Fields
DeflectAngleDegrees
Total spread of the deflecting arc in degrees — 120 deflects things arriving from within 60 degrees either side of forward.
[Tooltip("Total spread of the deflecting arc in degrees. 120 covers 60 degrees either side of forward.")]
[Range(0, 360)]
public float DeflectAngleDegrees
Field Value
Remarks
Measured through IsWithinCone(Vector3, Vector3, Vector3, float), the same test every cone in the project uses, against the direction the incoming object came FROM. 360 deflects from any direction; a projectile sitting exactly on the defender is deflected by nothing, because a direction test cannot be satisfied by a point with no direction.
MaxDeflections
How many objects this buff may turn away before it ends. Zero means no limit — the window's duration is the only bound.
[Tooltip("Objects this buff may deflect before ending. 0 means unlimited for the buff's duration.")]
[Min(0)]
public int MaxDeflections
Field Value
Remarks
Zero and one are the two abilities: a timed parry window that turns away everything arriving during it, and a single-use guard that is consumed by the first thing it stops.
Properties
InitialCharges
Called when the buff is applied to a character. Must be implemented by derived classes. When reached through OnApplyStack(Buff, ICharacter), Stacks still contains the pre-increment stack count; stack-aware templates should account for that ordering or override OnApplyStack(Buff, ICharacter) directly.
public override int InitialCharges { get; }
Property Value
Remarks
The unit is this template's own: DamageNegationBuffTemplate counts damage points, DeflectBuffTemplate counts deflections. See RemainingCharges for why there is one counter rather than one per template.
A property rather than a serialized field so a template can derive it from whatever it already authors, instead of asking a designer to keep two numbers in step.
Methods
OnApply(Buff, ICharacter)
Nothing to install — the window is read at hit time. See OnApply(Buff, ICharacter) for why this is empty rather than absent.
public override void OnApply(Buff buff, ICharacter target)
Parameters
buffBufftargetICharacter
OnApplyStack(Buff, ICharacter)
Refills the deflection count when a stack lands.
public override void OnApplyStack(Buff buff, ICharacter target)
Parameters
buffBufftargetICharacter
Remarks
Buff.AddStack increments AFTER this returns, so the post-operation count is
Stacks + 1 — the convention OnApplyStack(Buff, ICharacter)
documents.
OnRemove(Buff, ICharacter)
Nothing to reverse — see OnApply(Buff, ICharacter).
public override void OnRemove(Buff buff, ICharacter target)
Parameters
buffBufftargetICharacter
OnRemoveStack(Buff, ICharacter)
Trims the deflection count back to what the remaining stacks are worth, never raising it.
public override void OnRemoveStack(Buff buff, ICharacter target)
Parameters
buffBufftargetICharacter
ResolveDeflectedHeading(Vector3, Vector3)
The heading an object should leave on after being turned away by this buff.
public static Vector3 ResolveDeflectedHeading(Vector3 incomingHeading, Vector3 impactNormal)
Parameters
incomingHeadingVector3The direction the object was travelling.
impactNormalVector3Surface normal the server measured at the impact.
Returns
- Vector3
The heading to redirect the object along.
Remarks
A mirror about the impact surface, which is both the physically obvious answer and the
only one every peer can reproduce: impactNormal is measured once, on
the server, inside the rewind scope, and travels in the hit broadcast.
A degenerate normal — a query that could not produce one — falls back to reversing the incoming heading. Straight back at the attacker is a worse deflection than a mirror but a far better one than UnityEngine.Quaternion.LookRotation(UnityEngine.Vector3, UnityEngine.Vector3) being handed a zero vector, and it is still identical on every peer.
SecondaryTooltip(TooltipContent)
Appends a secondary tooltip describing the deflect window.
public override void SecondaryTooltip(TooltipContent content)
Parameters
contentTooltipContent