(Feat) Add Remove Building
This commit is contained in:
@@ -4,21 +4,28 @@ using Ashwild.Inventory;
|
||||
namespace Ashwild.Player
|
||||
{
|
||||
/// <summary>
|
||||
/// Held-item logic for the build hammer, placed on its hand prefab. While equipped it
|
||||
/// listens to the secondary-use input (right-click) and asks the construction UI to
|
||||
/// open/close through the bus — it never reaches for the menu itself, so the hammer
|
||||
/// stays a pure input source and the UI owns its own state. Left-click placement will
|
||||
/// be added on top of this once the build menu exists.
|
||||
/// Held-item logic for the build hammer, placed on its hand prefab. It turns the single
|
||||
/// right-click into two gestures without any extra keybind: a quick <b>tap</b> opens/closes the
|
||||
/// construction menu through the bus, while <b>holding</b> right-click past a short threshold puts
|
||||
/// the hammer into demolition mode for as long as it is held (releasing leaves it). The hammer
|
||||
/// stays a pure input source — it only raises bus requests; BuildManager owns the menu and the
|
||||
/// world-facing targeting/destroy, so this never reaches for either.
|
||||
/// </summary>
|
||||
[DisallowMultipleComponent]
|
||||
public class BuildHammerBehaviour : MonoBehaviour, IHeldItemBehaviour
|
||||
{
|
||||
#region Serialized Fields
|
||||
|
||||
[Header("Cooldown")]
|
||||
[Header("Gestures")]
|
||||
/// <summary>
|
||||
/// Minimum time, in seconds, between two menu toggles so a held right-click
|
||||
/// does not flicker the menu open and shut.
|
||||
/// How long, in seconds, right-click must stay held before it counts as a demolition hold
|
||||
/// instead of a menu tap. A release before this opens/closes the menu.
|
||||
/// </summary>
|
||||
[SerializeField] private float holdThreshold = 0.2f;
|
||||
|
||||
/// <summary>
|
||||
/// Minimum time, in seconds, between two menu toggles so a burst of taps does not flicker the
|
||||
/// menu open and shut.
|
||||
/// </summary>
|
||||
[SerializeField] private float toggleCooldown = 0.25f;
|
||||
|
||||
@@ -31,24 +38,58 @@ namespace Ashwild.Player
|
||||
/// </summary>
|
||||
private float nextToggleTime;
|
||||
|
||||
/// <summary>
|
||||
/// True between an accepted press and its release. A press ignored at the gate (input locked
|
||||
/// or already placing) never sets this, so its release is ignored too.
|
||||
/// </summary>
|
||||
private bool secondaryDown;
|
||||
|
||||
/// <summary>
|
||||
/// Time, in seconds, the current accepted press began — measured against <see cref="holdThreshold"/>.
|
||||
/// </summary>
|
||||
private float secondaryDownTime;
|
||||
|
||||
/// <summary>
|
||||
/// True while the hold has crossed into demolition mode, so the release ends the mode rather
|
||||
/// than toggling the menu.
|
||||
/// </summary>
|
||||
private bool demoActive;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Unity Lifecycle
|
||||
|
||||
/// <summary>
|
||||
/// Subscribes to the secondary-use input for as long as the hammer is held.
|
||||
/// Subscribes to the right-click hold stream for as long as the hammer is held.
|
||||
/// </summary>
|
||||
private void OnEnable()
|
||||
{
|
||||
PlayerEvents.SecondaryUsePressed += HandleSecondaryUse;
|
||||
PlayerEvents.SecondaryUseHeld += HandleSecondaryUse;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Unsubscribes when the hammer is put away (the prefab is destroyed).
|
||||
/// Unsubscribes and leaves demolition mode cleanly when the hammer is put away (its prefab is
|
||||
/// destroyed mid-hold), so the mode never sticks on with no hammer to release it.
|
||||
/// </summary>
|
||||
private void OnDisable()
|
||||
{
|
||||
PlayerEvents.SecondaryUsePressed -= HandleSecondaryUse;
|
||||
PlayerEvents.SecondaryUseHeld -= HandleSecondaryUse;
|
||||
if (demoActive) ExitDemolition();
|
||||
secondaryDown = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Promotes a sustained press into demolition mode once it outlasts the tap threshold. Held
|
||||
/// out of Update (not a timer) so the mode drops instantly if input locks or a placement
|
||||
/// begins mid-hold.
|
||||
/// </summary>
|
||||
private void Update()
|
||||
{
|
||||
if (!secondaryDown || demoActive) return;
|
||||
if (PlayerEvents.InputLocked || PlayerEvents.IsPlacingBuild) return;
|
||||
if (Time.time - secondaryDownTime < holdThreshold) return;
|
||||
|
||||
EnterDemolition();
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -56,8 +97,8 @@ namespace Ashwild.Player
|
||||
#region IHeldItemBehaviour
|
||||
|
||||
/// <summary>
|
||||
/// Nothing to link yet: toggling the menu needs no player refs. Present to satisfy
|
||||
/// the held-item contract; placement logic added later will use the context.
|
||||
/// Nothing to link: the hammer only raises bus requests. Present to satisfy the held-item
|
||||
/// contract; BuildManager holds the player/world refs the build UX needs.
|
||||
/// </summary>
|
||||
public void Setup(HeldItemContext context, ItemData item)
|
||||
{
|
||||
@@ -68,20 +109,60 @@ namespace Ashwild.Player
|
||||
#region Event Handlers
|
||||
|
||||
/// <summary>
|
||||
/// Requests the construction menu to open/close on right-click, gated by lock and
|
||||
/// cooldown. While a ghost is being positioned, right-click cancels the placement instead
|
||||
/// (handled by the placement controller), so the menu is left alone here.
|
||||
/// The single right-click gesture, split by press and release: a press is tracked (unless
|
||||
/// input is locked or a ghost is being placed, where right-click means "cancel" and is left to
|
||||
/// BuildManager); its release either ends demolition mode (if the hold engaged it) or, for a
|
||||
/// quick tap, toggles the construction menu under the cooldown.
|
||||
/// </summary>
|
||||
private void HandleSecondaryUse()
|
||||
private void HandleSecondaryUse(bool held)
|
||||
{
|
||||
if (PlayerEvents.InputLocked) return;
|
||||
if (PlayerEvents.IsPlacingBuild) return;
|
||||
if (Time.time < nextToggleTime) return;
|
||||
if (held)
|
||||
{
|
||||
if (PlayerEvents.InputLocked || PlayerEvents.IsPlacingBuild) return;
|
||||
secondaryDown = true;
|
||||
secondaryDownTime = Time.time;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!secondaryDown) return;
|
||||
secondaryDown = false;
|
||||
|
||||
if (demoActive) ExitDemolition();
|
||||
else ToggleMenu();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Internal Helpers
|
||||
|
||||
/// <summary>
|
||||
/// Requests the construction menu to open/close, gated by the toggle cooldown.
|
||||
/// </summary>
|
||||
private void ToggleMenu()
|
||||
{
|
||||
if (Time.time < nextToggleTime) return;
|
||||
nextToggleTime = Time.time + toggleCooldown;
|
||||
PlayerEvents.RaiseBuildMenuToggleRequested();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Enters demolition mode and announces it on the bus.
|
||||
/// </summary>
|
||||
private void EnterDemolition()
|
||||
{
|
||||
demoActive = true;
|
||||
PlayerEvents.RaiseDemolishModeChanged(true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Leaves demolition mode and announces it on the bus.
|
||||
/// </summary>
|
||||
private void ExitDemolition()
|
||||
{
|
||||
demoActive = false;
|
||||
PlayerEvents.RaiseDemolishModeChanged(false);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user