using Godot; using System; using System.Collections.Generic; using System.Linq; /// TODO alter code to player vs computer to account for differing logic public partial class Manager : Node { public bool _dead, _ready; public int _ballsMoving = 0, _health = 10, _healthMax; public string _imagePath; public Node _hoveredNode = null; public Node _selectedNode = null; public CollisionShape2D _startArea; public Cue _cue; public ManagerPanel _managerPanel = null; public BallReturn _ballReturn = null; public Rack _rack = null; public Table _table; public Area2D _kitchen; public Ball _cueBall; public BallSprite _cueBallSprite; public List _balls = new(); public List _ballSprites = new(); public List _workers = new(); public List _initialRackPositions = [ new Vector2I(1, 1), new Vector2I(3, 1), new Vector2I(4, 1), new Vector2I(2, 2), new Vector2I(4, 2), new Vector2I(1, 3), new Vector2I(2, 4), new Vector2I(2, 3), new Vector2I(2, 1), new Vector2I(5, 1), new Vector2I(1, 2), new Vector2I(3, 2), new Vector2I(3, 3), new Vector2I(1, 4), new Vector2I(1, 5) ]; // denoted by c1r1 notation where (3,1) translates to row 1 column 3 // column 0 represents the ball return where the row represents its order in the return, // cue ball reserves the position (0,0) // (0, 1+) denotes a ballin the ball return // (0,-1+) denotes a ball that is not on the screen, the closer to 0 numbers get placed in the return first if the cool down is equal // numbers should increase from top to bottom and left to right from the player's perspective // // PACKED SCENES public PackedScene _ballScene = ResourceLoader.Load("res://Gameplay/ball.tscn"); public PackedScene _ballSpriteScene = ResourceLoader.Load("res://Gameplay/ball_sprite.tscn"); public PackedScene _cueScene = ResourceLoader.Load("res://Gameplay/cue.tscn"); public PackedScene _workerScene = ResourceLoader.Load("res://Gameplay/worker.tscn"); public override void _Ready() { _healthMax = _health; _cue = GetNode("Cue"); _cue.OnShoot += OnCueShoot; _cue.Doff(); SetSprite("res://art/ness.png"); _managerPanel = GetNode("Panel"); _ballReturn = _managerPanel.GetNode("BallReturn"); _rack = _managerPanel.GetNode("Rack"); AddBall("res://art/cue_ball.png", new Vector2I(0, 0), true); for (int i = 1; i <= 15; i++) { AddBall("res://art/ball_" + i + ".png", _initialRackPositions[i - 1], false); } _managerPanel.SetManager(this); } public override void _Process(double DELTA_) { if (_ballsMoving == 0) { if (_cueBall._placed) { if (_selectedNode is Ball) { if (Input.IsActionJustReleased("right_click")) { ((Ball)_selectedNode)._selected = false; _selectedNode = null; _cue.Doff(); } if (Input.IsActionJustReleased("left_click") && _cue._power == 0) { ((Ball)_selectedNode)._selected = false; _cue.Doff(); if (_hoveredNode != null) { _selectedNode = (Ball)_hoveredNode; ((Ball)_selectedNode)._selected = true; if (_selectedNode == _cueBall) { _cue.Don(_cueBall.Position); } } else { _selectedNode = null; } } } else if (_hoveredNode is Ball) { if ((Ball)_selectedNode != _hoveredNode && _cue._power == 0) { if (Input.IsActionJustReleased("left_click")) { _selectedNode = (Ball)_hoveredNode; ((Ball)_selectedNode)._selected = true; if (_selectedNode == _cueBall) { _cue.Don(((Ball)_selectedNode).Position); } else { _cue.Doff(); } } } } else if (_selectedNode is BallSprite) { Vector2 mousePosition = GetViewport().GetMousePosition(); ((BallSprite)_selectedNode).Position = mousePosition; if (Input.IsActionJustReleased("left_click")) { if (!_table._kitchenHovered) { PlaceBall(((BallSprite)_selectedNode), mousePosition); _hoveredNode = null; _selectedNode = null; } } } else if (_hoveredNode is BallSprite) { if (Input.IsActionJustReleased("left_click")) { _selectedNode = (BallSprite)_hoveredNode; } } } else { if (_selectedNode == _cueBallSprite) { Vector2 mousePosition = GetViewport().GetMousePosition(); _cueBallSprite.Position = mousePosition; if (Input.IsActionJustReleased("left_click")) { if (_table._kitchenHovered) { PlaceBall(_cueBallSprite, mousePosition); _hoveredNode = null; _selectedNode = null; } } } else if (_hoveredNode == _cueBallSprite) { if (Input.IsActionJustReleased("left_click")) { _selectedNode = _cueBallSprite; } } } } } public virtual void AddBall(string IMAGEPATH, Vector2I RACKPOSITION, bool ISCUE) { Ball newBall; BallSprite newBallSprite; Guid ballGuid = Guid.NewGuid(); string ballId = ballGuid.ToString(); newBall = _ballScene.Instantiate(); newBall.SetSprite(IMAGEPATH); newBall._rackPosition = RACKPOSITION; newBall._isCue = ISCUE; newBall._owner = this; newBall._id = ballId; newBall.OnHover += SetHovered; newBall.OnMovement += MovingChange; if (newBall._isCue) { _cueBall = newBall; } else { _balls.Add(newBall); } newBallSprite = _ballSpriteScene.Instantiate(); newBallSprite.SetSprite(newBall._imagePath); newBallSprite._rackPosition = newBall._rackPosition; newBallSprite._owner = this; newBallSprite._id = newBall._id; newBallSprite.OnHover += SetHovered; if (newBall._isCue) { _cueBallSprite = newBallSprite; } else { _ballSprites.Add(newBallSprite); _rack.SetSprite((int)newBallSprite._rackPosition.Y, (int)newBallSprite._rackPosition.X, newBallSprite._imagePath, newBall._id); } } public void ChangeHealth(int CHANGE) { _health += CHANGE; _health = Math.Min(_health, _healthMax); if (_health < 0) { _dead = true; _health = 0; } GetNode("Panel").SetValue(_health); } public BallSprite GetSpriteFromBall(Ball BALL) { BallSprite ballSprite = _cueBallSprite._id == BALL._id ? _cueBallSprite : _ballSprites.Single(b => b._id == BALL._id); return ballSprite; } public Ball GetBallFromSprite(BallSprite BALLSPRITE) { Ball ball = _cueBall._id == BALLSPRITE._id ? _cueBall : _balls.Single(b => b._id == BALLSPRITE._id); return ball; } public void MovingChange(Ball BALL, bool MOVING) { if (MOVING) { _ballsMoving++; } else { _ballsMoving--; } } public virtual void PlaceBall(BallSprite BALLSSPRITE, Vector2 POSITION) { Ball ball = GetBallFromSprite(BALLSSPRITE); ball._available = true; ball.Position = POSITION; ball._active = true; ball._placed = true; ball._potted = false; ball._active = true; ball.Rotation = 0; if (!GetChildren().Contains(ball)) { AddChild(ball); } BALLSSPRITE._active = false; if (GetChildren().Contains(BALLSSPRITE)) { RemoveChild(BALLSSPRITE); } // _ballReturn._returnCount = _balls.Where(b => b._potted).ToList().Count; // _ready = _ballReturn._returnCount > 0; } public virtual void PotBall(Ball BALL, Pocket POCKET) { BALL.Sleeping = true; BALL._available = false; BALL._moving = false; BALL._active = false; BALL._placed = false; BALL._potted = true; BALL._active = false; MovingChange(BALL, false); if (GetChildren().Contains(BALL)) { RemoveChild(BALL); } BallSprite ballSprite = GetSpriteFromBall(BALL); int pottedCount = _ballReturn._returnCount; Vector2 position; if (BALL._isCue) { position = _kitchen.GlobalPosition; } else { position = new Vector2(_ballReturn.GlobalPosition.X + _ballReturn.Size.X / 2, _ballReturn.GlobalPosition.Y + 50 * (pottedCount + 1)); } ballSprite.Position = position; ballSprite._active = true; if (!GetChildren().Contains(ballSprite)) { CallDeferred(MethodName.AddChild, ballSprite); } // _ballReturn._returnCount = _balls.Where(b => b._potted).ToList().Count; // _ready = _ballReturn._returnCount > 0; } public void SetHovered(Node NODE, bool HOVERED) { if (HOVERED) { if (_hoveredNode == null) { if (NODE is Ball) { _hoveredNode = (Ball)NODE; } else if (NODE is BallSprite) { _hoveredNode = (BallSprite)NODE; } } } else { _hoveredNode = null; } } // public void SetRack() // { // for (int i = 0; i < _ballSprites.Count; i++) // { // if ((int)_ballSprites[i]._rackPosition.Y > 0 && (int)_ballSprites[i]._rackPosition.X > 0) // { // _rack.SetSprite((int)_ballSprites[i]._rackPosition.Y, (int)_ballSprites[i]._rackPosition.X, _ballSprites[i]._imagePath); // } // } // } public void SetSprite(string PATH) { _imagePath = PATH; } public virtual void Start(Table TABLE) { _table = TABLE; int diameter = 36; int rows = _balls.Max(b => b._rackPosition.Y); BallSprite rackBallSprite; int r, c; for (int i = 0; i < _ballSprites.Count; i++) { rackBallSprite = _ballSprites[i]; c = rackBallSprite._rackPosition.X; r = Math.Abs(rackBallSprite._rackPosition.Y - rows); if (c > 0) { Vector2 position = new Vector2(TABLE.GlobalPosition.X - (r * (diameter / 2)) + ((c - 1) * diameter), TABLE.GlobalPosition.Y - TABLE.Texture.GetSize().Y / 4 - (r * diameter)); PlaceBall(rackBallSprite, position); } } TABLE.OnBallPotted += PotBall; // PLAYER.PotBall(); // SetRack(); _kitchen = _table.GetNode("Kitchen"); _cueBallSprite.Position = _kitchen.GlobalPosition; _cueBallSprite._active = true; AddChild(_cueBallSprite); } private void OnCueShoot(Vector2 IMPULSE) { if (_selectedNode is Ball) { Ball selectedBall = (Ball)_selectedNode; if (selectedBall != null && selectedBall._placed) { selectedBall.ApplyCentralImpulse(IMPULSE); selectedBall._selected = false; selectedBall.Launch(); _selectedNode = null; _cue.Doff(); } } } }