Files
PolyphiaGame/Scripts/Game/Inventory.cs
T
2025-12-17 19:13:10 -08:00

511 lines
22 KiB
C#

using Godot;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
// Remove all the global positions from this file
public partial class Inventory : Panel {
Options _Options;
Reference _Reference;
[Export] PackedScene SplitFrame;
Vector2I InventorySize = new Vector2I(4, 15);
int MaxWeight;
List<GameItem> _Inventory;
Vector2 _GridSize;
ProgressBar _WeightBar;
HeldItem _itemBeingHeld;
HeldItem __h;
HeldItem _lastRightClickedItem {
get {
return __h;
}
set {
if (_splitFrame != null) {
_splitFrame.Free();
_splitFrame = null;
}
__h = value;
}
}
public Control _splitFrame;
public override void _EnterTree() {
_Options = GetNode<Options>( "/root/Options" );
_Reference = GetNode<Reference>("/root/Reference");
_Reference.Inventory = this;
_Inventory = new List<GameItem>();
MaxWeight = 400;
Control GridBackdrop = GetChild(0).GetChild<Control>( 0 );
_WeightBar = GetChild<ProgressBar>( 1 );
// Scale Scrollbar
Vector2 FrameSize = GetChild<Control>(0).Size;
GridBackdrop.CustomMinimumSize = new Vector2( GetChild<Control>(0).Size.X - 8 , InventorySize.Y * FrameSize.X / InventorySize.X );
GridBackdrop.Size = GridBackdrop.CustomMinimumSize;
_GridSize = new Vector2( GridBackdrop.Size.X / InventorySize.X, GridBackdrop.Size.Y / InventorySize.Y );
_WeightBar.MaxValue = MaxWeight;
// Horizontal Grid Bars
for (int y=0; y< InventorySize.Y - 1; y++) {
HSeparator cur = new HSeparator{
Position = new Vector2(0, _GridSize.Y * (y + 1) - 2),
Size = new Vector2(GridBackdrop.Size.X, 4)
};
GetChild(0).GetChild(0).AddChild( cur );
}
// Vertical Grid Bars
for (int x=0; x< InventorySize.X - 1; x++) {
VSeparator cur = new VSeparator{
Position = new Vector2(_GridSize.X * (x + 1) - 2, 0),
Size = new Vector2(4, GridBackdrop.Size.Y)
};
GetChild(0).GetChild(0).AddChild( cur );
}
GetWeight();
}
public void UpdateMaxWeight(int maxWeight){
MaxWeight = maxWeight;
_WeightBar.MaxValue = MaxWeight;
GetWeight();
}
//------------------------------//
// Public Functions //
//------------------------------//
public int GetWeight() {
int _w = 0;
foreach(GameItem cur in _Inventory ) {
_w += cur.ItemStats.InventoryWeight;
}
_WeightBar.Value = _w;
_WeightBar.GetChild<Label>( 0 ).Text = _w.ToString() + " / " + MaxWeight.ToString();
return _w;
}
public void UpdateItem( GameItem item ) {
foreach( GameItem cur in _Inventory ) {
if( item.Guid == cur.Guid ) {
cur.InventoryObject.Quantity = item.InventoryObject.Quantity;
cur.InventoryFrame.GetChild<MenuButton>( 0 ).Text = item.ItemStats.ItemName + "\n" +
item.InventoryObject.Quantity + " / " + item.ItemStats.MaxQuantity;
break;
}
}
}
public bool AddInventory( GameItem Item ) {
Item.InventoryObject.Rotated = false;
if( GetWeight() + Item.ItemStats.InventoryWeight > MaxWeight ) {
_Reference.Alert.PerformAlert( "Max weight!" );
return false;
}
for( int rotation = 0; rotation <= 1; rotation++ ) {
// Try both rotations of the block
Vector2I tempSize = Item.ItemStats.InventorySize;
if( rotation == 1 ) {
Item.InventoryObject.Rotated = true;
tempSize = new Vector2I( Item.ItemStats.InventorySize.Y, Item.ItemStats.InventorySize.X );
}
// Go through the inventory grid minus overflow from the size of the item were trying to place
for( int yindex = 0; yindex <= (InventorySize.Y - tempSize.Y); yindex++ ) {
for( int xindex = 0; xindex <= (InventorySize.X - tempSize.X); xindex++ ) {
if( CheckBlock( tempSize, new Vector2I( xindex, yindex ), null ) ) {
// We found our space
Panel ItemBackDrop = new Panel();
GetChild( 0 ).GetChild( 0 ).AddChild( ItemBackDrop );
ItemBackDrop.Size = new Vector2( _GridSize.X * tempSize.X - 10, _GridSize.Y * tempSize.Y - 10 );
ItemBackDrop.Position = new Vector2( xindex * _GridSize.X + 5, yindex * _GridSize.Y + 5 );
ItemBackDrop.GuiInput += frameInput;
MenuButton dropDown = new MenuButton();
if( Item.ItemStats.IsQuantityItem ) {
dropDown.Text = Item.ItemStats.ItemName + "\n" +
Item.InventoryObject.Quantity + " / " + Item.ItemStats.MaxQuantity;
} else {
dropDown.Text = Item.ItemStats.ItemName;
}
dropDown.SetAnchorsPreset( LayoutPreset.FullRect );
ItemBackDrop.AddChild( dropDown );
dropDown.ButtonMask = MouseButtonMask.Right;
dropDown.GuiInput += frameInput;
dropDown.GetPopup().IndexPressed += DropdownPressed;
foreach( string cur in Enum.GetNames( typeof( InventoryOptions ) ) ) {
if( cur == "Split" && !Item.ItemStats.IsQuantityItem ) {
continue;
}
dropDown.GetPopup().AddItem( cur );
}
Item.InventoryObject.GridPosition = new Vector2I( xindex, yindex );
_Inventory.Add( Item );
GetWeight();
// Add Tool if its a tool
if (!string.IsNullOrEmpty(Item.ItemStats.ToolPath)){
PackedScene toolCopy = GD.Load<PackedScene>(Item.ItemStats.ToolPath);
Label tool = toolCopy.Instantiate<Label>();
// Place tool into toolbar in the correct spot and shift everything down to zero if need be
Node[] toolbarChildren = _Reference.ToolBar.GetChildren().ToArray();
for( int i=0; i<toolbarChildren.Count(); i++ ){
Label cur = (Label)toolbarChildren[i];
if ( cur.Text.Substring(1, 2) == ". " ){
cur.Text = (i+1).ToString() + ". " + cur.Text.Substring(3);
}
}
Debug.WriteLine( tool.Text.Substring(1, 2) );
if ( tool.Text.Substring(1, 2) == ". " ){
tool.Text = (toolbarChildren.Count()+1).ToString() + ". " + tool.Text.Substring(3);
} else {
tool.Text = (toolbarChildren.Count()+1).ToString() + ". " + tool.Text;
}
_Reference.ToolBar.AddChild( tool );
}
return true;
}
}
}
}
_Reference.Alert.PerformAlert( "No Space" );
// No space was found
return false;
}
public void DropInventory( GameItem item ) {
string[] PickupItems = _Reference.ItemSpawner._SpawnableScenes;
PackedScene ps = GD.Load<PackedScene>(PickupItems[item.ItemID]);
Pickup prefab = ps.Instantiate<Pickup>();
prefab.GlobalTransform = _Reference.Humanoid.GlobalTransform;
prefab.Quantity = item.InventoryObject.Quantity;
_Reference.ItemSpawnPath.AddChild( prefab );
RemoveInventory( item );
}
public void RemoveInventory( GameItem item ) {
foreach(Label cur in _Reference.ToolBar.GetChildren()){
if ( cur.GetChild(0) is ITool ){
ITool x = (ITool)cur.GetChild(0);
if ( x.ToolID == item.ItemID ){
if(_Reference.Humanoid.EquippedTool == x){
_Reference.Humanoid.EquipTool(0);
}
cur.QueueFree();
break;
}
}
}
_Inventory.Remove( item ) ;
item.InventoryFrame.Free();
item.InventoryFrame = null;
GetWeight();
}
//------------------------------//
// Mouse Functions //
//------------------------------//
void MouseDown( Vector2 mousePos ) {
GameItem? clicked = GetItemFromScreen( mousePos );
if( clicked != null ) {
_itemBeingHeld = new HeldItem {
MouseStart = mousePos,
MouseOffset = clicked.InventoryFrame.Position - mousePos,
Item = clicked
};
}
}
void MouseMove( Vector2 mousePos ) {
if( _itemBeingHeld != null ) {
Vector2I TempSize = _itemBeingHeld.Item.ItemStats.InventorySize;
if( _itemBeingHeld.Item.InventoryObject.Rotated ) {
TempSize = new Vector2I( _itemBeingHeld.Item.ItemStats.InventorySize.Y, _itemBeingHeld.Item.ItemStats.InventorySize.X );
}
Vector2 newFramePos = mousePos + _itemBeingHeld.MouseOffset;
if( newFramePos.X < 0 ) {
newFramePos.X = 0;
}
if( newFramePos.Y < 0 ) {
newFramePos.Y = 0;
}
if( newFramePos.X > _GridSize.X * InventorySize.X - (_GridSize.X * TempSize.X) ) {
newFramePos.X = _GridSize.X * InventorySize.X - (_GridSize.X * TempSize.X);
}
if( newFramePos.Y > _GridSize.Y * InventorySize.Y - (_GridSize.Y * TempSize.Y) ) {
newFramePos.Y = _GridSize.Y * InventorySize.Y - (_GridSize.Y * TempSize.Y);
}
_itemBeingHeld.Item.InventoryFrame.Position = newFramePos;
}
}
void MouseUp( Vector2 mousePos ) {
if( _itemBeingHeld != null ) {
Vector2I TempSize = _itemBeingHeld.Item.ItemStats.InventorySize;
if( _itemBeingHeld.Item.InventoryObject.Rotated ) {
TempSize = new Vector2I( _itemBeingHeld.Item.ItemStats.InventorySize.Y, _itemBeingHeld.Item.ItemStats.InventorySize.X );
}
Vector2 FinalGrid = new Vector2(
Mathf.Round((mousePos.X + _itemBeingHeld.MouseOffset.X) / _GridSize.X),
Mathf.Round((mousePos.Y + _itemBeingHeld.MouseOffset.Y) / _GridSize.Y)
);
if( FinalGrid.X < 0 ) { FinalGrid.X = 0; }
if( FinalGrid.Y < 0 ) { FinalGrid.Y = 0; }
if( FinalGrid.X > (InventorySize.X - TempSize.X) ) { FinalGrid.X = InventorySize.X - TempSize.X; }
if( FinalGrid.Y > (InventorySize.Y - TempSize.Y) ) { FinalGrid.Y = InventorySize.Y - TempSize.Y; }
if( CheckBlock( TempSize, new Vector2I( Convert.ToInt32( FinalGrid.X ), Convert.ToInt32( FinalGrid.Y )), _itemBeingHeld.Item ) ) { // Check fitment
_itemBeingHeld.Item.InventoryObject.GridPosition = new Vector2I( Convert.ToInt32( FinalGrid.X ), Convert.ToInt32( FinalGrid.Y ) );
_itemBeingHeld.Item.InventoryFrame.Position = _GridSize * FinalGrid + new Vector2( 5, 5 );
} else {
GameItem? itemAtSpot = GetItemFromScreen( mousePos );
if( itemAtSpot.ItemStats.IsQuantityItem && itemAtSpot.ItemID == _itemBeingHeld.Item.ItemID ) {
// Try Combine
int MaxQuantity = _itemBeingHeld.Item.ItemStats.MaxQuantity;
int Total = itemAtSpot.InventoryObject.Quantity + _itemBeingHeld.Item.InventoryObject.Quantity;
if( Total > MaxQuantity ) {
int remainder = Total - MaxQuantity;
itemAtSpot.InventoryObject.Quantity = MaxQuantity;
_itemBeingHeld.Item.InventoryObject.Quantity = remainder;
_itemBeingHeld.Item.InventoryFrame.Position = new Vector2(
_itemBeingHeld.Item.InventoryObject.GridPosition.X * _GridSize.X + 5,
_itemBeingHeld.Item.InventoryObject.GridPosition.Y * _GridSize.Y + 5
);
} else {
itemAtSpot.InventoryObject.Quantity = Total;
MenuButton button = itemAtSpot.InventoryFrame.GetChild<MenuButton>(0);
button.Text = itemAtSpot.ItemStats.ItemName + "\n" +
itemAtSpot.InventoryObject.Quantity + " / " + itemAtSpot.ItemStats.MaxQuantity;
RemoveInventory( _itemBeingHeld.Item );
}
} else {
_itemBeingHeld.Item.InventoryFrame.Position = new Vector2(
_itemBeingHeld.Item.InventoryObject.GridPosition.X * _GridSize.X + 5,
_itemBeingHeld.Item.InventoryObject.GridPosition.Y * _GridSize.Y + 5
);
}
}
_itemBeingHeld = null;
}
}
void RightMouseDown( Vector2 mousePos ) {
GameItem? clicked = GetItemFromScreen( mousePos );
if( clicked != null ) {
_lastRightClickedItem = new HeldItem {
MouseStart = mousePos,
MouseOffset = clicked.InventoryFrame.Position - mousePos,
Item = clicked
};
}
}
//------------------------------//
// Screen Space Math //
//------------------------------//
GameItem? GetItemFromScreen( Vector2 screenPos ) {
Vector2 ClickedGrid = new Vector2( Mathf.Floor(screenPos.X / _GridSize.X), Mathf.Floor(screenPos.Y / _GridSize.Y) );
foreach( GameItem cur in _Inventory ) {
Vector2I TempSize = cur.ItemStats.InventorySize;
if( cur.InventoryObject.Rotated ) {
TempSize = new Vector2I( cur.ItemStats.InventorySize.Y, cur.ItemStats.InventorySize.X );
}
if( ClickedGrid.X >= cur.InventoryObject.GridPosition.X && ClickedGrid.X <= (cur.InventoryObject.GridPosition.X + TempSize.X - 1) &&
ClickedGrid.Y >= cur.InventoryObject.GridPosition.Y && ClickedGrid.Y <= (cur.InventoryObject.GridPosition.Y + TempSize.Y - 1) ) {
return cur;
}
}
return null;
}
Vector2 TranslateGlobalToFramePosition( Vector2 globalPos ) {
ScrollContainer InventoryFrame = GetChild<ScrollContainer>( 0 );
Vector2 FrameGlobalPos = InventoryFrame.GlobalPosition;
Vector2 ScrollAmount = new Vector2( InventoryFrame.ScrollHorizontal, InventoryFrame.ScrollVertical );
Vector2 localPos = globalPos - FrameGlobalPos + ScrollAmount;
return localPos;
}
bool CheckBlock( Vector2I BlockSize, Vector2I BlockGridPostion, GameItem Ignore ) {
for( int y = 0; y < BlockSize.Y; y++ ) {
for( int x = 0; x < BlockSize.X; x++ ) {
foreach( GameItem cur in _Inventory ) {
// Check Ignore
if( Ignore != null && cur.Guid == Ignore.Guid ) {
continue;
}
// Properly rotate block
Vector2I tempSize;
if( !cur.InventoryObject.Rotated ) {
tempSize = cur.ItemStats.InventorySize;
} else {
tempSize = new Vector2I( cur.ItemStats.InventorySize.Y, cur.ItemStats.InventorySize.X );
}
// Check fit
Vector2I curTopLeft = cur.InventoryObject.GridPosition;
Vector2I curBotRight = new Vector2I( cur.InventoryObject.GridPosition.X + tempSize.X - 1, cur.InventoryObject.GridPosition.Y + tempSize.Y - 1 );
if( (x + BlockGridPostion.X) >= curTopLeft.X && (x + BlockGridPostion.X) <= curBotRight.X &&
(y + BlockGridPostion.Y) >= curTopLeft.Y && (y + BlockGridPostion.Y) <= curBotRight.Y ) {
return false;
}
}
}
}
return true;
}
void frameInput( InputEvent iEvent ) {
if ( iEvent is InputEventMouseButton mouseButton) {
if( mouseButton.ButtonIndex == MouseButton.Left ) {
if( mouseButton.Pressed ) {
MouseDown( TranslateGlobalToFramePosition(mouseButton.GlobalPosition) );
} else {
MouseUp( TranslateGlobalToFramePosition( mouseButton.GlobalPosition ) );
}
} else if( mouseButton.ButtonIndex == MouseButton.Right ) {
if ( mouseButton.Pressed ) {
RightMouseDown( TranslateGlobalToFramePosition( mouseButton.GlobalPosition ) );
}
}
} else if( iEvent is InputEventMouseMotion mouseMotion) {
MouseMove( TranslateGlobalToFramePosition( mouseMotion.GlobalPosition ) );
}
}
//------------------------------//
// Right Click Functions //
//------------------------------//
(bool, Vector2I) TryRotate( GameItem item ) {
Vector2I tempSize;
if( item.InventoryObject.Rotated ) {
tempSize = item.ItemStats.InventorySize;
} else {
tempSize = new Vector2I( item.ItemStats.InventorySize.Y, item.ItemStats.InventorySize.X );
}
// Go through the inventory grid minus overflow from the size of the item were trying to place
for( int yindex = 0; yindex <= (InventorySize.Y - tempSize.Y); yindex++ ) {
for( int xindex = 0; xindex <= (InventorySize.X - tempSize.X); xindex++ ) {
if( CheckBlock( tempSize, new Vector2I( xindex, yindex ), item ) ) {
return (true, new Vector2I(xindex, yindex));
}
}
}
return (false, Vector2I.Zero);
}
string GetNumbers( String InputString ) {
String Result = "";
string Numbers = "0123456789";
int i = 0;
for( i = 0; i < InputString.Length; i++ ) {
if( Numbers.Contains( InputString.ElementAt( i ) ) ) {
Result += InputString.ElementAt( i );
}
}
return Result;
}
void SplitFrame_Split() {
int quantity = Convert.ToInt32( _splitFrame.GetChild<LineEdit>( 1 ).Text );
GameItem x = _lastRightClickedItem.Item;
if (quantity <= x.InventoryObject.Quantity ) {
GameItem test = new GameItem( x.ItemID );
test.InventoryObject.Quantity = quantity;
if( AddInventory( test ) ) {
_lastRightClickedItem.Item.InventoryObject.Quantity -= quantity;
UpdateItem( _lastRightClickedItem.Item );
} else {
_Reference.Alert.PerformAlert( "Not enough space to split" );
}
}
_splitFrame.Free();
_splitFrame = null;
}
void SplitFrame_Cancel() {
_splitFrame.Free();
_splitFrame = null;
}
void SplitFrame_TextChanged( string NewText ) {
string output = GetNumbers( NewText );
if ( string.IsNullOrEmpty( output ) ) {
output = "0";
}
int test = Convert.ToInt32(output);
if (test < 0) {
test = 0;
}else if (test > _lastRightClickedItem.Item.ItemStats.MaxQuantity) {
test = _lastRightClickedItem.Item.ItemStats.MaxQuantity;
}
_splitFrame.GetChild<LineEdit>( 1 ).Text = test.ToString();
_splitFrame.GetChild<LineEdit>( 1 ).CaretColumn = 50;
}
void DropdownPressed( long index ) {
InventoryOptions pressed = (InventoryOptions)index;
if( pressed == InventoryOptions.Drop ) {
DropInventory( _lastRightClickedItem.Item );
} else if( pressed == InventoryOptions.Rotate ) {
(bool, Vector2I) tryRotate = TryRotate( _lastRightClickedItem.Item );
if( tryRotate.Item1 ) {
_lastRightClickedItem.Item.InventoryObject.Rotated = !_lastRightClickedItem.Item.InventoryObject.Rotated;
Vector2 tempSize;
if( _lastRightClickedItem.Item.InventoryObject.Rotated ) {
tempSize = new Vector2( _lastRightClickedItem.Item.ItemStats.InventorySize.Y, _lastRightClickedItem.Item.ItemStats.InventorySize.X );
} else {
tempSize = _lastRightClickedItem.Item.ItemStats.InventorySize;
}
_lastRightClickedItem.Item.InventoryFrame.Size = new Vector2( _GridSize.X * tempSize.X - 10, _GridSize.Y * tempSize.Y - 10 );
_lastRightClickedItem.Item.InventoryFrame.Position = new Vector2( tryRotate.Item2.X * _GridSize.X + 5, tryRotate.Item2.Y * _GridSize.Y + 5 );
_lastRightClickedItem.Item.InventoryObject.GridPosition = tryRotate.Item2;
} else {
_Reference.Alert.PerformAlert( "Not enough space to rotate");
}
} else if( pressed == InventoryOptions.Split ) {
_splitFrame = SplitFrame.Instantiate<Control>();
GetNode( "/root/Game/UI/" ).AddChild( _splitFrame );
_splitFrame.GetChild<Button>( 2 ).ButtonDown += SplitFrame_Split;
_splitFrame.GetChild<Button>( 3 ).ButtonDown += SplitFrame_Cancel;
_splitFrame.GetChild<LineEdit>( 1 ).TextChanged += SplitFrame_TextChanged;
}
}
}
//------------------------------//
// Data Objects //
//------------------------------//
enum InventoryOptions {
Drop,
Rotate,
Split
}
public class HeldItem {
public Vector2 MouseStart { get; set; }
public Vector2 MouseOffset { get; set; }
public GameItem Item { get; set; }
}