(Feat) Add Build
This commit is contained in:
@@ -29,6 +29,10 @@ namespace Ashwild.Player
|
||||
public static bool IsPlacingBuild { get; private set; }
|
||||
// True while the build hammer is in demolition mode (right-click held, menu closed, not placing).
|
||||
public static bool IsDemolishing { get; private set; }
|
||||
// Composite "the player is actively building" flag — true whenever the construction menu is open,
|
||||
// a ghost is being positioned, or the hammer is demolishing. Recomputed from those three states
|
||||
// (never set directly) and used to widen the crosshair and to suppress item pickup while building.
|
||||
public static bool IsBuilding { get; private set; }
|
||||
public static bool IsPaused { get; private set; }
|
||||
|
||||
// True when a networked session is live (host or client).
|
||||
@@ -103,7 +107,11 @@ namespace Ashwild.Player
|
||||
|
||||
public static event Action<int> InventorySlotChanged;
|
||||
public static event Action<int> SelectedHotbarSlotChanged;
|
||||
public static event Action<ItemData, int> ItemAdded;
|
||||
// (item, quantity, isTransfer) — isTransfer is true when the stack merely moved between the
|
||||
// player's own containers (a chest withdrawal, a refund) instead of being newly acquired from
|
||||
// the world. Consumers that announce a gain (notifications) skip transfers; consumers that only
|
||||
// track "the player has held this" (craft discovery) treat both the same.
|
||||
public static event Action<ItemData, int, bool> ItemAdded;
|
||||
public static event Action<ItemData, int> ItemDropped;
|
||||
public static event Action<ItemData> ItemConsumed;
|
||||
public static event Action<ItemData, int> ItemPickedUp;
|
||||
@@ -134,9 +142,11 @@ namespace Ashwild.Player
|
||||
// ============================================================
|
||||
|
||||
public static event Action BuildMenuToggleRequested; // the build hammer asks to open/close the construction menu
|
||||
public static event Action BuildCancelRequested; // the build hammer asks to cancel/exit the current ghost placement (right-click while placing)
|
||||
public static event Action<bool> BuildMenuOpenChanged; // the construction menu opened (true) or closed (false)
|
||||
public static event Action<bool> BuildPlacingChanged; // a build ghost started (true) / stopped (false) being positioned
|
||||
public static event Action<bool> DemolishModeChanged; // the hammer entered (true) / left (false) demolition mode (right-click held)
|
||||
public static event Action<bool> BuildModeChanged; // the composite build mode turned on (true) / off (false) — see IsBuilding
|
||||
public static event Action<IReadOnlyList<BuildCostView>> BuildCostChanged; // the active build's cost to display near the crosshair (null/empty = clear)
|
||||
|
||||
// ============================================================
|
||||
@@ -256,7 +266,7 @@ namespace Ashwild.Player
|
||||
|
||||
public static void RaiseInventorySlotChanged(int i) { InventorySlotChanged?.Invoke(i); }
|
||||
public static void RaiseSelectedHotbarSlotChanged(int i) { Log(nameof(SelectedHotbarSlotChanged)); SelectedHotbarSlotChanged?.Invoke(i); }
|
||||
public static void RaiseItemAdded(ItemData d, int q) { Log(nameof(ItemAdded)); ItemAdded?.Invoke(d, q); }
|
||||
public static void RaiseItemAdded(ItemData d, int q, bool isTransfer = false) { Log(nameof(ItemAdded)); ItemAdded?.Invoke(d, q, isTransfer); }
|
||||
public static void RaiseItemDropped(ItemData d, int q) { Log(nameof(ItemDropped)); ItemDropped?.Invoke(d, q); }
|
||||
public static void RaiseItemConsumed(ItemData d) { Log(nameof(ItemConsumed)); ItemConsumed?.Invoke(d); }
|
||||
public static void RaiseItemPickedUp(ItemData d, int q) { Log(nameof(ItemPickedUp)); ItemPickedUp?.Invoke(d, q); }
|
||||
@@ -295,17 +305,20 @@ namespace Ashwild.Player
|
||||
public static void RaiseUnequipAnimComplete() { UnequipAnimComplete?.Invoke(); }
|
||||
|
||||
public static void RaiseBuildMenuToggleRequested() { Log(nameof(BuildMenuToggleRequested)); BuildMenuToggleRequested?.Invoke(); }
|
||||
public static void RaiseBuildCancelRequested() { Log(nameof(BuildCancelRequested)); BuildCancelRequested?.Invoke(); }
|
||||
public static void RaiseBuildMenuOpenChanged(bool open)
|
||||
{
|
||||
IsBuildMenuOpen = open;
|
||||
Log(nameof(BuildMenuOpenChanged));
|
||||
BuildMenuOpenChanged?.Invoke(open);
|
||||
RefreshBuildMode();
|
||||
}
|
||||
public static void RaiseBuildPlacingChanged(bool placing)
|
||||
{
|
||||
IsPlacingBuild = placing;
|
||||
Log(nameof(BuildPlacingChanged));
|
||||
BuildPlacingChanged?.Invoke(placing);
|
||||
RefreshBuildMode();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -328,6 +341,21 @@ namespace Ashwild.Player
|
||||
IsDemolishing = on;
|
||||
Log(nameof(DemolishModeChanged));
|
||||
DemolishModeChanged?.Invoke(on);
|
||||
RefreshBuildMode();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Recomputes the composite build-mode flag from its three sub-states and raises BuildModeChanged
|
||||
/// only when it actually flips, so consumers (crosshair spacing, pickup gating) react exactly once
|
||||
/// per transition instead of on every sub-state change.
|
||||
/// </summary>
|
||||
private static void RefreshBuildMode()
|
||||
{
|
||||
bool building = IsBuildMenuOpen || IsPlacingBuild || IsDemolishing;
|
||||
if (building == IsBuilding) return;
|
||||
IsBuilding = building;
|
||||
Log(nameof(BuildModeChanged));
|
||||
BuildModeChanged?.Invoke(building);
|
||||
}
|
||||
|
||||
public static void RaiseFoodPlacedToCook(ItemData raw) { Log(nameof(FoodPlacedToCook)); FoodPlacedToCook?.Invoke(raw); }
|
||||
@@ -413,6 +441,7 @@ namespace Ashwild.Player
|
||||
IsBuildMenuOpen = false;
|
||||
IsPlacingBuild = false;
|
||||
IsDemolishing = false;
|
||||
IsBuilding = false;
|
||||
IsPaused = false;
|
||||
HoveredInteractable = null;
|
||||
}
|
||||
|
||||
@@ -4,12 +4,15 @@ using Ashwild.Inventory;
|
||||
namespace Ashwild.Player
|
||||
{
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// Held-item logic for the build hammer, placed on its hand prefab. It is the single arbiter of the
|
||||
/// right-click gesture in a build context, so the menu can never fight a placement over the same
|
||||
/// click. One right-click is a <b>tap</b>, resolved on release as a clean build-mode toggle: while
|
||||
/// placing a ghost it cancels the placement (back to idle, no menu), otherwise it opens/closes the
|
||||
/// construction menu. <b>Holding</b> right-click past a short threshold instead enters demolition
|
||||
/// mode for as long as it is held. The tap is gated only by hard UI locks (dead, inventory, chest,
|
||||
/// pause) — not by the build menu being open (so a tap closes it) nor by a placement being active
|
||||
/// (so a tap cancels 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
|
||||
@@ -109,16 +112,18 @@ namespace Ashwild.Player
|
||||
#region Event Handlers
|
||||
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// The single right-click gesture, split by press and release. A press is tracked unless a hard
|
||||
/// UI lock is up; the build menu being open or a placement being active do NOT block it, because
|
||||
/// this gesture is what drives those states. The release resolves the gesture in priority order:
|
||||
/// a hold that engaged demolition leaves demolition; a tap while placing a ghost cancels it
|
||||
/// (the single arbiter — BuildManager no longer listens to the raw click, so the menu can't
|
||||
/// reopen on the same click); otherwise a tap toggles the construction menu.
|
||||
/// </summary>
|
||||
private void HandleSecondaryUse(bool held)
|
||||
{
|
||||
if (held)
|
||||
{
|
||||
if (PlayerEvents.InputLocked || PlayerEvents.IsPlacingBuild) return;
|
||||
if (HardLocked) return;
|
||||
secondaryDown = true;
|
||||
secondaryDownTime = Time.time;
|
||||
return;
|
||||
@@ -127,14 +132,24 @@ namespace Ashwild.Player
|
||||
if (!secondaryDown) return;
|
||||
secondaryDown = false;
|
||||
|
||||
if (demoActive) ExitDemolition();
|
||||
else ToggleMenu();
|
||||
if (demoActive) { ExitDemolition(); return; }
|
||||
if (PlayerEvents.IsPlacingBuild) { PlayerEvents.RaiseBuildCancelRequested(); return; }
|
||||
ToggleMenu();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Internal Helpers
|
||||
|
||||
/// <summary>
|
||||
/// A hard UI lock (dead, inventory, chest, pause) where right-click must do nothing. Unlike the
|
||||
/// bus's InputLocked, it deliberately ignores the build menu being open and a placement being
|
||||
/// active — both are build states this gesture is meant to drive (close the menu, cancel the
|
||||
/// placement), not locks that should swallow the click.
|
||||
/// </summary>
|
||||
private static bool HardLocked =>
|
||||
PlayerEvents.IsDead || PlayerEvents.IsInventoryOpen || PlayerEvents.IsChestOpen || PlayerEvents.IsPaused;
|
||||
|
||||
/// <summary>
|
||||
/// Requests the construction menu to open/close, gated by the toggle cooldown.
|
||||
/// </summary>
|
||||
|
||||
Reference in New Issue
Block a user