Major Player refactor
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
using DialogueManagerRuntime;
|
||||
using Godot;
|
||||
|
||||
namespace GameJamDungeon;
|
||||
|
||||
public partial class DialogueController : Node
|
||||
{
|
||||
public static PackedScene DialogueBalloon { get; set; }
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
namespace GameJamDungeon
|
||||
namespace GameJamDungeon;
|
||||
|
||||
public enum ElementType
|
||||
{
|
||||
public enum ElementType
|
||||
{
|
||||
None,
|
||||
Aeolic,
|
||||
Telluric,
|
||||
Hydric,
|
||||
Igneous,
|
||||
Ferrum
|
||||
}
|
||||
None,
|
||||
Aeolic,
|
||||
Telluric,
|
||||
Hydric,
|
||||
Igneous,
|
||||
Ferrum
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@ namespace GameJamDungeon;
|
||||
|
||||
using Chickensoft.AutoInject;
|
||||
using Chickensoft.Introspection;
|
||||
using GameJamDungeon.src.item_rescue;
|
||||
using Godot;
|
||||
using System;
|
||||
|
||||
@@ -16,6 +15,8 @@ public partial class Game : Node3D, IGame
|
||||
|
||||
IGame IProvide<IGame>.Value() => this;
|
||||
|
||||
IPlayer IProvide<IPlayer>.Value() => Player;
|
||||
|
||||
IGameEventDepot IProvide<IGameEventDepot>.Value() => GameEventDepot;
|
||||
|
||||
public IInstantiator Instantiator { get; set; } = default!;
|
||||
@@ -61,6 +62,7 @@ public partial class Game : Node3D, IGame
|
||||
GameLogic.Set(GameRepo);
|
||||
GameLogic.Set(AppRepo);
|
||||
GameLogic.Set(GameEventDepot);
|
||||
GameLogic.Set(Player);
|
||||
Instantiator = new Instantiator(GetTree());
|
||||
RescuedItems = new RescuedItemDatabase();
|
||||
}
|
||||
@@ -117,29 +119,27 @@ public partial class Game : Node3D, IGame
|
||||
InGameUI.UseTeleportPrompt.TeleportToNextFloor += UseTeleportPrompt_TeleportToNextFloor;
|
||||
InGameUI.UseTeleportPrompt.CloseTeleportPrompt += UseTeleportPrompt_CloseTeleportPrompt;
|
||||
|
||||
GameRepo.PlayerData.Inventory.InventoryAtCapacity += PlayerInventory_InventoryAtCapacity;
|
||||
GameRepo.PlayerData.Inventory.PickedUpItem += Inventory_PickedUpItem;
|
||||
GameRepo.PlayerData.Inventory.RaiseStatRequest += Inventory_RaiseStatRequest;
|
||||
Player.Inventory.InventoryAtCapacity += PlayerInventory_InventoryAtCapacity;
|
||||
Player.Inventory.PickedUpItem += Inventory_PickedUpItem;
|
||||
Player.Inventory.RaiseStatRequest += Inventory_RaiseStatRequest;
|
||||
FloorClearMenu.GoToNextFloor += FloorClearMenu_GoToNextFloor;
|
||||
FloorClearMenu.SaveAndExit += FloorClearMenu_SaveAndExit;
|
||||
FloorClearMenu.TransitionCompleted += FloorClearMenu_TransitionCompleted;
|
||||
|
||||
Player.InventoryButtonPressed += Player_InventoryButtonPressed;
|
||||
Player.MinimapButtonHeld += Player_MinimapButtonHeld;
|
||||
Player.PauseButtonPressed += Player_PauseButtonPressed;
|
||||
|
||||
GameRepo.PlayerData.CurrentHP.Sync += CurrentHP_Sync;
|
||||
|
||||
GameEventDepot.EnemyDefeated += OnEnemyDefeated;
|
||||
GameEventDepot.RestorativePickedUp += GameEventDepot_RestorativePickedUp;
|
||||
|
||||
DoubleEXPTimer.Timeout += DoubleEXPTimer_Timeout;
|
||||
}
|
||||
|
||||
private void CurrentHP_Sync(int currentHP)
|
||||
public void ToggleInventory()
|
||||
{
|
||||
if (currentHP <= 0)
|
||||
GameLogic.Input(new GameLogic.Input.GameOver());
|
||||
GameLogic.Input(new GameLogic.Input.OpenInventory());
|
||||
}
|
||||
|
||||
public void ToggleMinimap()
|
||||
{
|
||||
GameLogic.Input(new GameLogic.Input.MiniMapButtonPressed());
|
||||
}
|
||||
|
||||
private void Inventory_PickedUpItem(string pickedUpItemName)
|
||||
@@ -160,14 +160,14 @@ public partial class Game : Node3D, IGame
|
||||
{
|
||||
var thrownScene = GD.Load<PackedScene>("res://src/items/thrown/ThrownItem.tscn");
|
||||
var thrown = thrownScene.Instantiate<ThrownItem>();
|
||||
thrown.ThrownItemStats = item.Info;
|
||||
thrown.ItemThatIsThrown = item;
|
||||
AddChild(thrown);
|
||||
thrown.Throw();
|
||||
}
|
||||
|
||||
private void OnEnemyDefeated(Vector3 vector, EnemyStatResource resource)
|
||||
{
|
||||
GameRepo.PlayerData.SetCurrentExp(GameRepo.PlayerData.CurrentExp.Value + (resource.ExpFromDefeat * GameRepo.EXPRate));
|
||||
Player.GainExp(resource.ExpFromDefeat * GameRepo.EXPRate);
|
||||
DropRestorative(vector);
|
||||
}
|
||||
|
||||
@@ -205,21 +205,11 @@ public partial class Game : Node3D, IGame
|
||||
GameLogic.Input(new GameLogic.Input.MiniMapButtonReleased());
|
||||
}
|
||||
|
||||
private void Player_MinimapButtonHeld()
|
||||
{
|
||||
GameLogic.Input(new GameLogic.Input.MiniMapButtonPressed());
|
||||
}
|
||||
|
||||
private void Player_InventoryButtonPressed()
|
||||
{
|
||||
GameLogic.Input(new GameLogic.Input.OpenInventory());
|
||||
}
|
||||
|
||||
private void FloorClearMenu_TransitionCompleted()
|
||||
{
|
||||
GameRepo.Resume();
|
||||
if (GameRepo.PlayerData.Inventory.EquippedWeapon.Value.WeaponStats.WeaponTags.Contains(WeaponTag.BreaksOnChange))
|
||||
GameRepo.PlayerData.Inventory.Unequip(GameRepo.PlayerData.Inventory.EquippedWeapon.Value);
|
||||
if (Player.Inventory.EquippedWeapon.Value.WeaponTags.Contains(WeaponTag.BreaksOnChange))
|
||||
Player.Inventory.Unequip(Player.Inventory.EquippedWeapon.Value);
|
||||
}
|
||||
|
||||
private void FloorClearMenu_GoToNextFloor()
|
||||
@@ -235,7 +225,7 @@ public partial class Game : Node3D, IGame
|
||||
}
|
||||
|
||||
private void GameEventDepot_RestorativePickedUp(Restorative obj)
|
||||
=> GameRepo.PlayerData.SetCurrentVT(GameRepo.PlayerData.CurrentVT.Value + obj.VTRestoreAmount);
|
||||
=> Player.Stats.SetCurrentVT(Player.Stats.CurrentVT.Value + obj.VTRestoreAmount);
|
||||
|
||||
private void Inventory_RaiseStatRequest(InventoryItemStats itemStats)
|
||||
{
|
||||
@@ -251,34 +241,34 @@ public partial class Game : Node3D, IGame
|
||||
|
||||
public void RaiseHP(int amountToRaise)
|
||||
{
|
||||
if (GameRepo.PlayerData.CurrentHP.Value == GameRepo.PlayerData.MaximumHP.Value)
|
||||
if (Player.Stats.CurrentHP.Value == Player.Stats.MaximumHP.Value)
|
||||
{
|
||||
GameRepo.PlayerData.SetMaximumHP(GameRepo.PlayerData.MaximumHP.Value + amountToRaise);
|
||||
GameRepo.PlayerData.SetCurrentHP(GameRepo.PlayerData.MaximumHP.Value);
|
||||
Player.Stats.SetMaximumHP(Player.Stats.MaximumHP.Value + amountToRaise);
|
||||
Player.Stats.SetCurrentHP(Player.Stats.MaximumHP.Value);
|
||||
EmitSignal(SignalName.StatRaisedAlert, $"{amountToRaise}MAXHP Up.");
|
||||
}
|
||||
}
|
||||
|
||||
public void HealHP(int amountToRestore)
|
||||
{
|
||||
GameRepo.PlayerData.SetCurrentHP(GameRepo.PlayerData.CurrentHP.Value + amountToRestore);
|
||||
Player.Stats.SetCurrentHP(Player.Stats.CurrentHP.Value + amountToRestore);
|
||||
var raiseString = amountToRestore == 1000 ? "MAX" : $"{amountToRestore}";
|
||||
EmitSignal(SignalName.StatRaisedAlert, $"{raiseString}HP Restored.");
|
||||
}
|
||||
|
||||
public void RaiseVT(int amountToRaise)
|
||||
{
|
||||
if (GameRepo.PlayerData.CurrentVT.Value == GameRepo.PlayerData.MaximumVT.Value)
|
||||
if (Player.Stats.CurrentVT.Value == Player.Stats.MaximumVT.Value)
|
||||
{
|
||||
GameRepo.PlayerData.SetMaximumVT(GameRepo.PlayerData.MaximumVT.Value + amountToRaise);
|
||||
GameRepo.PlayerData.SetCurrentVT(GameRepo.PlayerData.MaximumVT.Value);
|
||||
Player.Stats.SetMaximumVT(Player.Stats.MaximumVT.Value + amountToRaise);
|
||||
Player.Stats.SetCurrentVT(Player.Stats.MaximumVT.Value);
|
||||
EmitSignal(SignalName.StatRaisedAlert, $"{amountToRaise}MAXVT Up.");
|
||||
}
|
||||
}
|
||||
|
||||
public void HealVT(int amountToRestore)
|
||||
{
|
||||
GameRepo.PlayerData.SetCurrentVT(GameRepo.PlayerData.CurrentVT.Value + amountToRestore);
|
||||
Player.Stats.SetCurrentVT(Player.Stats.CurrentVT.Value + amountToRestore);
|
||||
var raiseString = amountToRestore == 1000 ? "MAX" : $"{amountToRestore}";
|
||||
EmitSignal(SignalName.StatRaisedAlert, $"{raiseString}VT Restored.");
|
||||
}
|
||||
@@ -309,7 +299,7 @@ public partial class Game : Node3D, IGame
|
||||
{
|
||||
var transform = Map.GetPlayerSpawnPosition();
|
||||
GameRepo.SetPlayerGlobalTransform(transform);
|
||||
GameRepo.SetPlayerGlobalPosition(new Vector3(transform.Origin.X, -2, transform.Origin.Z));
|
||||
Player.TeleportPlayer(new Vector3(transform.Origin.X, -1.75f, transform.Origin.Z));
|
||||
GameLogic.Input(new GameLogic.Input.HideFloorClearMenu());
|
||||
}
|
||||
|
||||
|
||||
@@ -48,7 +48,7 @@ process_mode = 1
|
||||
[node name="Player" parent="SubViewportContainer/SubViewport/PauseContainer" instance=ExtResource("3_kk6ly")]
|
||||
unique_name_in_owner = true
|
||||
process_mode = 1
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -2.74459, 1.22144)
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.283374, 1.22144)
|
||||
|
||||
[node name="Map" parent="SubViewportContainer/SubViewport/PauseContainer" instance=ExtResource("3_d8awv")]
|
||||
unique_name_in_owner = true
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
using Chickensoft.Introspection;
|
||||
using Chickensoft.Serialization;
|
||||
|
||||
namespace GameJamDungeon
|
||||
namespace GameJamDungeon;
|
||||
|
||||
[Meta, Id("game_data")]
|
||||
public partial record GameData
|
||||
{
|
||||
[Meta, Id("game_data")]
|
||||
public partial record GameData
|
||||
{
|
||||
[Save("player_data")]
|
||||
public required PlayerData PlayerData { get; init; }
|
||||
}
|
||||
[Save("player_data")]
|
||||
public required PlayerStats PlayerData { get; init; }
|
||||
}
|
||||
|
||||
@@ -1,114 +1,113 @@
|
||||
using Godot;
|
||||
using System;
|
||||
|
||||
namespace GameJamDungeon
|
||||
namespace GameJamDungeon;
|
||||
|
||||
public interface IGameEventDepot : IDisposable
|
||||
{
|
||||
public interface IGameEventDepot : IDisposable
|
||||
event Action? OverworldEntered;
|
||||
public void OnOverworldEntered();
|
||||
|
||||
event Action? DungeonAThemeAreaEntered;
|
||||
public void OnDungeonAThemeAreaEntered();
|
||||
|
||||
event Action? DungeonBThemeAreaEntered;
|
||||
public void OnDungeonBThemeAreaEntered();
|
||||
|
||||
event Action? DungeonCThemeAreaEntered;
|
||||
public void OnDungeonCThemeAreaEntered();
|
||||
|
||||
event Action? TeleportEntered;
|
||||
public void OnTeleportEntered();
|
||||
|
||||
event Action? MenuScrolled;
|
||||
public void OnMenuScrolled();
|
||||
|
||||
event Action? MenuBackedOut;
|
||||
public void OnMenuBackedOut();
|
||||
|
||||
event Action<Weapon>? EquippedWeapon;
|
||||
public void OnEquippedWeapon(Weapon equippedWeapon);
|
||||
|
||||
event Action? UnequippedWeapon;
|
||||
public void OnUnequippedWeapon();
|
||||
|
||||
event Action<Armor>? EquippedArmor;
|
||||
public void OnEquippedArmor(Armor equippedArmor);
|
||||
|
||||
event Action? UnequippedArmor;
|
||||
public void OnUnequippedArmor();
|
||||
|
||||
event Action<Accessory>? EquippedAccessory;
|
||||
public void OnEquippedAccessory(Accessory equippedAccessory);
|
||||
|
||||
event Action? UnequippedAccessory;
|
||||
public void OnUnequippedAccessory();
|
||||
|
||||
event Action? InventorySorted;
|
||||
public void OnInventorySorted();
|
||||
|
||||
event Action<ConsumableItemStats>? HealingItemConsumed;
|
||||
public void OnHealingItemConsumed(ConsumableItemStats item);
|
||||
|
||||
event Action<Vector3, EnemyStatResource>? EnemyDefeated;
|
||||
public void OnEnemyDefeated(Vector3 position, EnemyStatResource enemyStatResource);
|
||||
|
||||
event Action<Restorative>? RestorativePickedUp;
|
||||
public void OnRestorativePickedUp(Restorative restorative);
|
||||
}
|
||||
|
||||
public class GameEventDepot : IGameEventDepot
|
||||
{
|
||||
|
||||
public event Action? OverworldEntered;
|
||||
public event Action? DungeonAThemeAreaEntered;
|
||||
public event Action? DungeonBThemeAreaEntered;
|
||||
public event Action? DungeonCThemeAreaEntered;
|
||||
|
||||
public event Action? TeleportEntered;
|
||||
|
||||
public event Action? MenuScrolled;
|
||||
public event Action? MenuBackedOut;
|
||||
public event Action<Weapon>? EquippedWeapon;
|
||||
public event Action? UnequippedWeapon;
|
||||
public event Action<Armor>? EquippedArmor;
|
||||
public event Action? UnequippedArmor;
|
||||
public event Action<Accessory>? EquippedAccessory;
|
||||
public event Action? UnequippedAccessory;
|
||||
public event Action? InventorySorted;
|
||||
public event Action<ConsumableItemStats>? HealingItemConsumed;
|
||||
public event Action<Restorative>? RestorativePickedUp;
|
||||
|
||||
public event Action<Vector3, EnemyStatResource>? EnemyDefeated;
|
||||
|
||||
public void OnOverworldEntered() => OverworldEntered?.Invoke();
|
||||
public void OnDungeonAThemeAreaEntered() => DungeonAThemeAreaEntered?.Invoke();
|
||||
public void OnDungeonBThemeAreaEntered() => DungeonBThemeAreaEntered?.Invoke();
|
||||
public void OnDungeonCThemeAreaEntered() => DungeonCThemeAreaEntered?.Invoke();
|
||||
|
||||
public void OnTeleportEntered() => TeleportEntered?.Invoke();
|
||||
|
||||
public void OnMenuScrolled() => MenuScrolled?.Invoke();
|
||||
public void OnMenuBackedOut() => MenuBackedOut?.Invoke();
|
||||
|
||||
public void OnEquippedWeapon(Weapon equippedWeapon) => EquippedWeapon?.Invoke(equippedWeapon);
|
||||
public void OnUnequippedWeapon() => UnequippedWeapon?.Invoke();
|
||||
|
||||
public void OnEquippedArmor(Armor equippedArmor) => EquippedArmor?.Invoke(equippedArmor);
|
||||
public void OnUnequippedArmor() => UnequippedArmor?.Invoke();
|
||||
|
||||
public void OnEquippedAccessory(Accessory equippedAccessory) => EquippedAccessory?.Invoke(equippedAccessory);
|
||||
public void OnUnequippedAccessory() => UnequippedAccessory?.Invoke();
|
||||
|
||||
public void OnInventorySorted() => InventorySorted?.Invoke();
|
||||
public void OnHealingItemConsumed(ConsumableItemStats item) => HealingItemConsumed?.Invoke(item);
|
||||
public void OnRestorativePickedUp(Restorative restorative) => RestorativePickedUp?.Invoke(restorative);
|
||||
|
||||
public void OnEnemyDefeated(Vector3 position, EnemyStatResource enemyStatResource) => EnemyDefeated?.Invoke(position, enemyStatResource);
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
event Action? OverworldEntered;
|
||||
public void OnOverworldEntered();
|
||||
|
||||
event Action? DungeonAThemeAreaEntered;
|
||||
public void OnDungeonAThemeAreaEntered();
|
||||
|
||||
event Action? DungeonBThemeAreaEntered;
|
||||
public void OnDungeonBThemeAreaEntered();
|
||||
|
||||
event Action? DungeonCThemeAreaEntered;
|
||||
public void OnDungeonCThemeAreaEntered();
|
||||
|
||||
event Action? TeleportEntered;
|
||||
public void OnTeleportEntered();
|
||||
|
||||
event Action? MenuScrolled;
|
||||
public void OnMenuScrolled();
|
||||
|
||||
event Action? MenuBackedOut;
|
||||
public void OnMenuBackedOut();
|
||||
|
||||
event Action<Weapon>? EquippedWeapon;
|
||||
public void OnEquippedWeapon(Weapon equippedWeapon);
|
||||
|
||||
event Action? UnequippedWeapon;
|
||||
public void OnUnequippedWeapon();
|
||||
|
||||
event Action<Armor>? EquippedArmor;
|
||||
public void OnEquippedArmor(Armor equippedArmor);
|
||||
|
||||
event Action? UnequippedArmor;
|
||||
public void OnUnequippedArmor();
|
||||
|
||||
event Action<Accessory>? EquippedAccessory;
|
||||
public void OnEquippedAccessory(Accessory equippedAccessory);
|
||||
|
||||
event Action? UnequippedAccessory;
|
||||
public void OnUnequippedAccessory();
|
||||
|
||||
event Action? InventorySorted;
|
||||
public void OnInventorySorted();
|
||||
|
||||
event Action<ConsumableItemStats>? HealingItemConsumed;
|
||||
public void OnHealingItemConsumed(ConsumableItemStats item);
|
||||
|
||||
event Action<Vector3, EnemyStatResource>? EnemyDefeated;
|
||||
public void OnEnemyDefeated(Vector3 position, EnemyStatResource enemyStatResource);
|
||||
|
||||
event Action<Restorative>? RestorativePickedUp;
|
||||
public void OnRestorativePickedUp(Restorative restorative);
|
||||
}
|
||||
|
||||
public class GameEventDepot : IGameEventDepot
|
||||
{
|
||||
|
||||
public event Action? OverworldEntered;
|
||||
public event Action? DungeonAThemeAreaEntered;
|
||||
public event Action? DungeonBThemeAreaEntered;
|
||||
public event Action? DungeonCThemeAreaEntered;
|
||||
|
||||
public event Action? TeleportEntered;
|
||||
|
||||
public event Action? MenuScrolled;
|
||||
public event Action? MenuBackedOut;
|
||||
public event Action<Weapon>? EquippedWeapon;
|
||||
public event Action? UnequippedWeapon;
|
||||
public event Action<Armor>? EquippedArmor;
|
||||
public event Action? UnequippedArmor;
|
||||
public event Action<Accessory>? EquippedAccessory;
|
||||
public event Action? UnequippedAccessory;
|
||||
public event Action? InventorySorted;
|
||||
public event Action<ConsumableItemStats>? HealingItemConsumed;
|
||||
public event Action<Restorative>? RestorativePickedUp;
|
||||
|
||||
public event Action<Vector3, EnemyStatResource>? EnemyDefeated;
|
||||
|
||||
public void OnOverworldEntered() => OverworldEntered?.Invoke();
|
||||
public void OnDungeonAThemeAreaEntered() => DungeonAThemeAreaEntered?.Invoke();
|
||||
public void OnDungeonBThemeAreaEntered() => DungeonBThemeAreaEntered?.Invoke();
|
||||
public void OnDungeonCThemeAreaEntered() => DungeonCThemeAreaEntered?.Invoke();
|
||||
|
||||
public void OnTeleportEntered() => TeleportEntered?.Invoke();
|
||||
|
||||
public void OnMenuScrolled() => MenuScrolled?.Invoke();
|
||||
public void OnMenuBackedOut() => MenuBackedOut?.Invoke();
|
||||
|
||||
public void OnEquippedWeapon(Weapon equippedWeapon) => EquippedWeapon?.Invoke(equippedWeapon);
|
||||
public void OnUnequippedWeapon() => UnequippedWeapon?.Invoke();
|
||||
|
||||
public void OnEquippedArmor(Armor equippedArmor) => EquippedArmor?.Invoke(equippedArmor);
|
||||
public void OnUnequippedArmor() => UnequippedArmor?.Invoke();
|
||||
|
||||
public void OnEquippedAccessory(Accessory equippedAccessory) => EquippedAccessory?.Invoke(equippedAccessory);
|
||||
public void OnUnequippedAccessory() => UnequippedAccessory?.Invoke();
|
||||
|
||||
public void OnInventorySorted() => InventorySorted?.Invoke();
|
||||
public void OnHealingItemConsumed(ConsumableItemStats item) => HealingItemConsumed?.Invoke(item);
|
||||
public void OnRestorativePickedUp(Restorative restorative) => RestorativePickedUp?.Invoke(restorative);
|
||||
|
||||
public void OnEnemyDefeated(Vector3 position, EnemyStatResource enemyStatResource) => EnemyDefeated?.Invoke(position, enemyStatResource);
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,41 +1,40 @@
|
||||
namespace GameJamDungeon
|
||||
namespace GameJamDungeon;
|
||||
|
||||
public partial class GameLogic
|
||||
{
|
||||
public partial class GameLogic
|
||||
public static class Input
|
||||
{
|
||||
public static class Input
|
||||
{
|
||||
public readonly record struct StartGame;
|
||||
public readonly record struct StartGame;
|
||||
|
||||
public readonly record struct Initialize;
|
||||
public readonly record struct Initialize;
|
||||
|
||||
public readonly record struct GoToOverworld;
|
||||
public readonly record struct GoToOverworld;
|
||||
|
||||
public readonly record struct SaveGame;
|
||||
public readonly record struct SaveGame;
|
||||
|
||||
public readonly record struct OpenInventory;
|
||||
public readonly record struct OpenInventory;
|
||||
|
||||
public readonly record struct CloseInventory;
|
||||
public readonly record struct CloseInventory;
|
||||
|
||||
public readonly record struct MiniMapButtonPressed;
|
||||
public readonly record struct MiniMapButtonPressed;
|
||||
|
||||
public readonly record struct MiniMapButtonReleased;
|
||||
public readonly record struct MiniMapButtonReleased;
|
||||
|
||||
public readonly record struct FloorExitReached;
|
||||
public readonly record struct HideFloorClearMenu;
|
||||
public readonly record struct FloorExitReached;
|
||||
public readonly record struct HideFloorClearMenu;
|
||||
|
||||
public readonly record struct GameOver;
|
||||
public readonly record struct GameOver;
|
||||
|
||||
public readonly record struct GoToNextFloor;
|
||||
public readonly record struct GoToNextFloor;
|
||||
|
||||
public readonly record struct PauseGame;
|
||||
public readonly record struct PauseGame;
|
||||
|
||||
public readonly record struct UnpauseGame;
|
||||
public readonly record struct UnpauseGame;
|
||||
|
||||
public readonly record struct PauseMenuTransitioned;
|
||||
public readonly record struct PauseMenuTransitioned;
|
||||
|
||||
public readonly record struct AskForTeleport;
|
||||
public readonly record struct AskForTeleport;
|
||||
|
||||
public readonly record struct HideAskForTeleport;
|
||||
}
|
||||
public readonly record struct HideAskForTeleport;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,44 +1,41 @@
|
||||
using System.Collections.Generic;
|
||||
namespace GameJamDungeon;
|
||||
|
||||
namespace GameJamDungeon
|
||||
public partial class GameLogic
|
||||
{
|
||||
public partial class GameLogic
|
||||
public static class Output
|
||||
{
|
||||
public static class Output
|
||||
{
|
||||
public readonly record struct StartGame;
|
||||
public readonly record struct StartGame;
|
||||
|
||||
public readonly record struct ShowPauseMenu;
|
||||
public readonly record struct ShowPauseMenu;
|
||||
|
||||
public readonly record struct HidePauseMenu;
|
||||
public readonly record struct HidePauseMenu;
|
||||
|
||||
public readonly record struct ExitPauseMenu;
|
||||
public readonly record struct ExitPauseMenu;
|
||||
|
||||
public readonly record struct OpenInventory();
|
||||
public readonly record struct OpenInventory();
|
||||
|
||||
public readonly record struct HideInventory;
|
||||
public readonly record struct HideInventory;
|
||||
|
||||
public readonly record struct SetPauseMode(bool IsPaused);
|
||||
public readonly record struct SetPauseMode(bool IsPaused);
|
||||
|
||||
public readonly record struct ShowMiniMap;
|
||||
public readonly record struct ShowMiniMap;
|
||||
|
||||
public readonly record struct HideMiniMap;
|
||||
public readonly record struct HideMiniMap;
|
||||
|
||||
public readonly record struct ShowLostScreen;
|
||||
public readonly record struct ShowLostScreen;
|
||||
|
||||
public readonly record struct ExitLostScreen;
|
||||
public readonly record struct ExitLostScreen;
|
||||
|
||||
public readonly record struct LoadNextFloor;
|
||||
public readonly record struct LoadNextFloor;
|
||||
|
||||
public readonly record struct ShowFloorClearMenu;
|
||||
public readonly record struct ShowFloorClearMenu;
|
||||
|
||||
public readonly record struct ExitFloorClearMenu;
|
||||
public readonly record struct ExitFloorClearMenu;
|
||||
|
||||
public readonly record struct ShowAskForTeleport;
|
||||
public readonly record struct ShowAskForTeleport;
|
||||
|
||||
public readonly record struct HideAskForTeleport;
|
||||
public readonly record struct HideAskForTeleport;
|
||||
|
||||
public readonly record struct GoToOverworld;
|
||||
}
|
||||
public readonly record struct GoToOverworld;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,28 +1,27 @@
|
||||
using Chickensoft.Introspection;
|
||||
using Chickensoft.LogicBlocks;
|
||||
|
||||
namespace GameJamDungeon
|
||||
{
|
||||
public partial class GameLogic
|
||||
{
|
||||
[Meta]
|
||||
public abstract partial record State : StateLogic<State>
|
||||
{
|
||||
protected State()
|
||||
{
|
||||
OnAttach(() =>
|
||||
{
|
||||
var gameRepo = Get<IGameRepo>();
|
||||
gameRepo.IsPaused.Sync += OnIsPaused;
|
||||
});
|
||||
OnDetach(() =>
|
||||
{
|
||||
var gameRepo = Get<IGameRepo>();
|
||||
gameRepo.IsPaused.Sync -= OnIsPaused;
|
||||
});
|
||||
}
|
||||
namespace GameJamDungeon;
|
||||
|
||||
public void OnIsPaused(bool isPaused) => Output(new Output.SetPauseMode(isPaused));
|
||||
public partial class GameLogic
|
||||
{
|
||||
[Meta]
|
||||
public abstract partial record State : StateLogic<State>
|
||||
{
|
||||
protected State()
|
||||
{
|
||||
OnAttach(() =>
|
||||
{
|
||||
var gameRepo = Get<IGameRepo>();
|
||||
gameRepo.IsPaused.Sync += OnIsPaused;
|
||||
});
|
||||
OnDetach(() =>
|
||||
{
|
||||
var gameRepo = Get<IGameRepo>();
|
||||
gameRepo.IsPaused.Sync -= OnIsPaused;
|
||||
});
|
||||
}
|
||||
|
||||
public void OnIsPaused(bool isPaused) => Output(new Output.SetPauseMode(isPaused));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
using Chickensoft.Introspection;
|
||||
using Chickensoft.LogicBlocks;
|
||||
|
||||
namespace GameJamDungeon
|
||||
{
|
||||
public interface IGameLogic : ILogicBlock<GameLogic.State>;
|
||||
namespace GameJamDungeon;
|
||||
|
||||
[Meta]
|
||||
[LogicBlock(typeof(State), Diagram = true)]
|
||||
public partial class GameLogic : LogicBlock<GameLogic.State>, IGameLogic
|
||||
{
|
||||
public override Transition GetInitialState() => To<State.GameStarted>();
|
||||
}
|
||||
public interface IGameLogic : ILogicBlock<GameLogic.State>;
|
||||
|
||||
[Meta]
|
||||
[LogicBlock(typeof(State), Diagram = true)]
|
||||
public partial class GameLogic : LogicBlock<GameLogic.State>, IGameLogic
|
||||
{
|
||||
public override Transition GetInitialState() => To<State.GameStarted>();
|
||||
}
|
||||
|
||||
@@ -12,16 +12,6 @@ public interface IGameRepo : IDisposable
|
||||
|
||||
IAutoProp<bool> IsPaused { get; }
|
||||
|
||||
IAutoProp<Vector3> PlayerGlobalPosition { get; }
|
||||
|
||||
IAutoProp<Transform3D> PlayerGlobalTransform { get; }
|
||||
|
||||
PlayerData PlayerData { get; }
|
||||
|
||||
public void SetPlayerData(PlayerData playerData);
|
||||
|
||||
void SetPlayerGlobalPosition(Vector3 playerGlobalPosition);
|
||||
|
||||
void SetPlayerGlobalTransform(Transform3D playerGlobalTransform);
|
||||
|
||||
public int MaxItemSize { get; }
|
||||
@@ -35,18 +25,12 @@ public class GameRepo : IGameRepo
|
||||
{
|
||||
public event Action? Ended;
|
||||
|
||||
public IAutoProp<Vector3> PlayerGlobalPosition => _playerGlobalPosition;
|
||||
private readonly AutoProp<Vector3> _playerGlobalPosition;
|
||||
|
||||
public IAutoProp<Transform3D> PlayerGlobalTransform => _playerGlobalTransform;
|
||||
private readonly AutoProp<Transform3D> _playerGlobalTransform;
|
||||
|
||||
public IAutoProp<bool> IsPaused => _isPaused;
|
||||
private readonly AutoProp<bool> _isPaused;
|
||||
|
||||
public PlayerData PlayerData => _playerData;
|
||||
private PlayerData _playerData;
|
||||
|
||||
public int MaxItemSize => 20;
|
||||
|
||||
public int EXPRate { get; set; } = 1;
|
||||
@@ -58,7 +42,6 @@ public class GameRepo : IGameRepo
|
||||
public GameRepo()
|
||||
{
|
||||
_isPaused = new AutoProp<bool>(false);
|
||||
_playerGlobalPosition = new AutoProp<Vector3>(Vector3.Zero);
|
||||
_playerGlobalTransform = new AutoProp<Transform3D>(Transform3D.Identity);
|
||||
}
|
||||
|
||||
@@ -74,12 +57,8 @@ public class GameRepo : IGameRepo
|
||||
GD.Print("Resume");
|
||||
}
|
||||
|
||||
public void SetPlayerGlobalPosition(Vector3 playerGlobalPosition) => _playerGlobalPosition.OnNext(playerGlobalPosition);
|
||||
|
||||
public void SetPlayerGlobalTransform(Transform3D playerGlobalTransform) => _playerGlobalTransform.OnNext(playerGlobalTransform);
|
||||
|
||||
public void SetPlayerData(PlayerData playerData) => _playerData = playerData;
|
||||
|
||||
public void OnGameEnded()
|
||||
{
|
||||
Pause();
|
||||
@@ -92,8 +71,6 @@ public class GameRepo : IGameRepo
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
_playerGlobalPosition.OnCompleted();
|
||||
_playerGlobalPosition.Dispose();
|
||||
_isPaused.OnCompleted();
|
||||
_isPaused.Dispose();
|
||||
}
|
||||
|
||||
@@ -3,10 +3,9 @@ namespace GameJamDungeon;
|
||||
|
||||
using Chickensoft.AutoInject;
|
||||
using Chickensoft.GodotNodeInterfaces;
|
||||
using GameJamDungeon.src.item_rescue;
|
||||
using System;
|
||||
|
||||
public interface IGame : IProvide<IGameRepo>, IProvide<IGameEventDepot>, IProvide<IGame>, INode3D
|
||||
public interface IGame : IProvide<IGameRepo>, IProvide<IGameEventDepot>, IProvide<IGame>, IProvide<IPlayer>, INode3D
|
||||
{
|
||||
event Game.StatRaisedAlertEventHandler StatRaisedAlert;
|
||||
|
||||
@@ -25,4 +24,8 @@ public interface IGame : IProvide<IGameRepo>, IProvide<IGameEventDepot>, IProvid
|
||||
public void RaiseVT(int amountToRaise);
|
||||
|
||||
public void DoubleEXP(TimeSpan lengthOfEffect);
|
||||
|
||||
public void ToggleInventory();
|
||||
|
||||
public void ToggleMinimap();
|
||||
}
|
||||
|
||||
@@ -1,27 +1,25 @@
|
||||
using Chickensoft.Introspection;
|
||||
using Chickensoft.LogicBlocks;
|
||||
|
||||
namespace GameJamDungeon
|
||||
namespace GameJamDungeon;
|
||||
|
||||
public partial class GameLogic
|
||||
{
|
||||
public partial class GameLogic
|
||||
public partial record State
|
||||
{
|
||||
public partial record State
|
||||
[Meta]
|
||||
public partial record AskForTeleport : Playing, IGet<Input.FloorExitReached>, IGet<Input.HideAskForTeleport>
|
||||
{
|
||||
[Meta]
|
||||
public partial record AskForTeleport : Playing, IGet<Input.FloorExitReached>, IGet<Input.HideAskForTeleport>
|
||||
public AskForTeleport()
|
||||
{
|
||||
public AskForTeleport()
|
||||
{
|
||||
this.OnAttach(() => { Get<IGameRepo>().Pause(); Output(new Output.ShowAskForTeleport()); });
|
||||
this.OnDetach(() => { Output(new Output.HideAskForTeleport()); });
|
||||
}
|
||||
this.OnAttach(() => { Get<IGameRepo>().Pause(); Output(new Output.ShowAskForTeleport()); });
|
||||
this.OnDetach(() => { Output(new Output.HideAskForTeleport()); });
|
||||
}
|
||||
|
||||
public Transition On(in Input.FloorExitReached input) => To<FloorClearedDecisionState>();
|
||||
public Transition On(in Input.FloorExitReached input) => To<FloorClearedDecisionState>();
|
||||
|
||||
public Transition On(in Input.HideAskForTeleport input)
|
||||
{
|
||||
return To<Playing>();
|
||||
}
|
||||
public Transition On(in Input.HideAskForTeleport input)
|
||||
{
|
||||
return To<Playing>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,31 +1,29 @@
|
||||
using Chickensoft.Introspection;
|
||||
using Chickensoft.LogicBlocks;
|
||||
|
||||
namespace GameJamDungeon
|
||||
namespace GameJamDungeon;
|
||||
|
||||
public partial class GameLogic
|
||||
{
|
||||
public partial class GameLogic
|
||||
public partial record State
|
||||
{
|
||||
public partial record State
|
||||
[Meta]
|
||||
public partial record FloorClearedDecisionState : Playing, IGet<Input.GoToNextFloor>, IGet<Input.HideFloorClearMenu>
|
||||
{
|
||||
[Meta]
|
||||
public partial record FloorClearedDecisionState : Playing, IGet<Input.GoToNextFloor>, IGet<Input.HideFloorClearMenu>
|
||||
public FloorClearedDecisionState()
|
||||
{
|
||||
public FloorClearedDecisionState()
|
||||
{
|
||||
this.OnAttach(() => { Get<IGameRepo>().Pause(); Output(new Output.ShowFloorClearMenu()); });
|
||||
this.OnDetach(() => { Output(new Output.ExitFloorClearMenu()); });
|
||||
}
|
||||
this.OnAttach(() => { Get<IGameRepo>().Pause(); Output(new Output.ShowFloorClearMenu()); });
|
||||
this.OnDetach(() => { Output(new Output.ExitFloorClearMenu()); });
|
||||
}
|
||||
|
||||
public Transition On(in Input.GoToNextFloor input)
|
||||
{
|
||||
Output(new Output.LoadNextFloor());
|
||||
return ToSelf();
|
||||
}
|
||||
public Transition On(in Input.GoToNextFloor input)
|
||||
{
|
||||
Output(new Output.LoadNextFloor());
|
||||
return ToSelf();
|
||||
}
|
||||
|
||||
public Transition On(in Input.HideFloorClearMenu input)
|
||||
{
|
||||
return To<Playing>();
|
||||
}
|
||||
public Transition On(in Input.HideFloorClearMenu input)
|
||||
{
|
||||
return To<Playing>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,26 +1,25 @@
|
||||
using Chickensoft.Introspection;
|
||||
using Chickensoft.LogicBlocks;
|
||||
|
||||
namespace GameJamDungeon
|
||||
{
|
||||
public partial class GameLogic
|
||||
{
|
||||
public partial record State
|
||||
{
|
||||
[Meta]
|
||||
public partial record GameStarted : State, IGet<Input.Initialize>
|
||||
{
|
||||
public GameStarted()
|
||||
{
|
||||
this.OnEnter(() => { Get<IGameRepo>().Pause(); });
|
||||
this.OnExit(() => { Get<IGameRepo>().Resume(); });
|
||||
}
|
||||
namespace GameJamDungeon;
|
||||
|
||||
public Transition On(in Input.Initialize input)
|
||||
{
|
||||
Output(new Output.StartGame());
|
||||
return To<Playing>();
|
||||
}
|
||||
public partial class GameLogic
|
||||
{
|
||||
public partial record State
|
||||
{
|
||||
[Meta]
|
||||
public partial record GameStarted : State, IGet<Input.Initialize>
|
||||
{
|
||||
public GameStarted()
|
||||
{
|
||||
this.OnEnter(() => { Get<IGameRepo>().Pause(); });
|
||||
this.OnExit(() => { Get<IGameRepo>().Resume(); });
|
||||
}
|
||||
|
||||
public Transition On(in Input.Initialize input)
|
||||
{
|
||||
Output(new Output.StartGame());
|
||||
return To<Playing>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,25 +1,24 @@
|
||||
using Chickensoft.Introspection;
|
||||
using Chickensoft.LogicBlocks;
|
||||
|
||||
namespace GameJamDungeon
|
||||
{
|
||||
public partial class GameLogic
|
||||
{
|
||||
public partial record State
|
||||
{
|
||||
[Meta]
|
||||
public partial record InventoryOpened : Playing, IGet<Input.CloseInventory>
|
||||
{
|
||||
public InventoryOpened()
|
||||
{
|
||||
this.OnEnter(() => { Get<IGameRepo>().Pause(); Output(new Output.OpenInventory()); });
|
||||
this.OnExit(() => { Get<IGameRepo>().Resume(); Output(new Output.HideInventory()); });
|
||||
}
|
||||
namespace GameJamDungeon;
|
||||
|
||||
public Transition On(in Input.CloseInventory input)
|
||||
{
|
||||
return To<Playing>();
|
||||
}
|
||||
public partial class GameLogic
|
||||
{
|
||||
public partial record State
|
||||
{
|
||||
[Meta]
|
||||
public partial record InventoryOpened : Playing, IGet<Input.CloseInventory>
|
||||
{
|
||||
public InventoryOpened()
|
||||
{
|
||||
this.OnEnter(() => { Get<IGameRepo>().Pause(); Output(new Output.OpenInventory()); });
|
||||
this.OnExit(() => { Get<IGameRepo>().Resume(); Output(new Output.HideInventory()); });
|
||||
}
|
||||
|
||||
public Transition On(in Input.CloseInventory input)
|
||||
{
|
||||
return To<Playing>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,23 +1,22 @@
|
||||
using Chickensoft.Introspection;
|
||||
using Chickensoft.LogicBlocks;
|
||||
|
||||
namespace GameJamDungeon
|
||||
{
|
||||
public partial class GameLogic
|
||||
{
|
||||
public partial record State
|
||||
{
|
||||
[Meta]
|
||||
public partial record MinimapOpen : Playing, IGet<Input.MiniMapButtonReleased>
|
||||
{
|
||||
public MinimapOpen()
|
||||
{
|
||||
this.OnEnter(() => { Get<IGameRepo>().Pause(); Output(new Output.ShowMiniMap()); });
|
||||
this.OnExit(() => { Get<IGameRepo>().Resume(); Output(new Output.HideMiniMap()); });
|
||||
}
|
||||
namespace GameJamDungeon;
|
||||
|
||||
public Transition On(in Input.MiniMapButtonReleased input) => To<Playing>();
|
||||
public partial class GameLogic
|
||||
{
|
||||
public partial record State
|
||||
{
|
||||
[Meta]
|
||||
public partial record MinimapOpen : Playing, IGet<Input.MiniMapButtonReleased>
|
||||
{
|
||||
public MinimapOpen()
|
||||
{
|
||||
this.OnEnter(() => { Get<IGameRepo>().Pause(); Output(new Output.ShowMiniMap()); });
|
||||
this.OnExit(() => { Get<IGameRepo>().Resume(); Output(new Output.HideMiniMap()); });
|
||||
}
|
||||
|
||||
public Transition On(in Input.MiniMapButtonReleased input) => To<Playing>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,27 +1,26 @@
|
||||
using Chickensoft.Introspection;
|
||||
using Chickensoft.LogicBlocks;
|
||||
|
||||
namespace GameJamDungeon
|
||||
{
|
||||
public partial class GameLogic
|
||||
{
|
||||
public partial record State
|
||||
{
|
||||
[Meta]
|
||||
public partial record Paused : Playing, IGet<Input.UnpauseGame>
|
||||
{
|
||||
public Paused()
|
||||
{
|
||||
this.OnEnter(() =>
|
||||
{
|
||||
Get<IGameRepo>().Pause();
|
||||
Output(new Output.ShowPauseMenu());
|
||||
});
|
||||
this.OnExit(() => Output(new Output.ExitPauseMenu()));
|
||||
}
|
||||
namespace GameJamDungeon;
|
||||
|
||||
public virtual Transition On(in Input.UnpauseGame input) => To<Resuming>();
|
||||
public partial class GameLogic
|
||||
{
|
||||
public partial record State
|
||||
{
|
||||
[Meta]
|
||||
public partial record Paused : Playing, IGet<Input.UnpauseGame>
|
||||
{
|
||||
public Paused()
|
||||
{
|
||||
this.OnEnter(() =>
|
||||
{
|
||||
Get<IGameRepo>().Pause();
|
||||
Output(new Output.ShowPauseMenu());
|
||||
});
|
||||
this.OnExit(() => Output(new Output.ExitPauseMenu()));
|
||||
}
|
||||
|
||||
public virtual Transition On(in Input.UnpauseGame input) => To<Resuming>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,42 +1,40 @@
|
||||
using Chickensoft.Introspection;
|
||||
using Chickensoft.LogicBlocks;
|
||||
|
||||
namespace GameJamDungeon
|
||||
namespace GameJamDungeon;
|
||||
|
||||
public partial class GameLogic
|
||||
{
|
||||
public partial class GameLogic
|
||||
public partial record State
|
||||
{
|
||||
public partial record State
|
||||
[Meta]
|
||||
public partial record Playing : State,
|
||||
IGet<Input.OpenInventory>,
|
||||
IGet<Input.MiniMapButtonPressed>,
|
||||
IGet<Input.GameOver>,
|
||||
IGet<Input.AskForTeleport>,
|
||||
IGet<Input.PauseGame>,
|
||||
IGet<Input.GoToOverworld>
|
||||
{
|
||||
[Meta]
|
||||
public partial record Playing : State,
|
||||
IGet<Input.OpenInventory>,
|
||||
IGet<Input.MiniMapButtonPressed>,
|
||||
IGet<Input.GameOver>,
|
||||
IGet<Input.AskForTeleport>,
|
||||
IGet<Input.PauseGame>,
|
||||
IGet<Input.GoToOverworld>
|
||||
public Playing()
|
||||
{
|
||||
public Playing()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public void OnEnded() => Input(new Input.GameOver());
|
||||
public void OnEnded() => Input(new Input.GameOver());
|
||||
|
||||
public Transition On(in Input.OpenInventory input) => To<InventoryOpened>();
|
||||
public Transition On(in Input.OpenInventory input) => To<InventoryOpened>();
|
||||
|
||||
public Transition On(in Input.MiniMapButtonPressed input) => To<MinimapOpen>();
|
||||
public Transition On(in Input.MiniMapButtonPressed input) => To<MinimapOpen>();
|
||||
|
||||
public Transition On(in Input.GameOver input) => To<Quit>();
|
||||
public Transition On(in Input.GameOver input) => To<Quit>();
|
||||
|
||||
public Transition On(in Input.AskForTeleport input) => To<AskForTeleport>();
|
||||
public Transition On(in Input.AskForTeleport input) => To<AskForTeleport>();
|
||||
|
||||
public Transition On(in Input.PauseGame input) => To<Paused>();
|
||||
public Transition On(in Input.PauseGame input) => To<Paused>();
|
||||
|
||||
public Transition On(in Input.GoToOverworld input)
|
||||
{
|
||||
Output(new Output.GoToOverworld());
|
||||
return ToSelf();
|
||||
}
|
||||
public Transition On(in Input.GoToOverworld input)
|
||||
{
|
||||
Output(new Output.GoToOverworld());
|
||||
return ToSelf();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,19 +1,18 @@
|
||||
using Chickensoft.Introspection;
|
||||
using Chickensoft.LogicBlocks;
|
||||
|
||||
namespace GameJamDungeon
|
||||
namespace GameJamDungeon;
|
||||
|
||||
public partial class GameLogic
|
||||
{
|
||||
public partial class GameLogic
|
||||
public partial record State
|
||||
{
|
||||
public partial record State
|
||||
[Meta]
|
||||
public partial record Quit : State
|
||||
{
|
||||
[Meta]
|
||||
public partial record Quit : State
|
||||
public Quit()
|
||||
{
|
||||
public Quit()
|
||||
{
|
||||
this.OnEnter(() => Output(new Output.ShowLostScreen()));
|
||||
}
|
||||
this.OnEnter(() => Output(new Output.ShowLostScreen()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user