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, _placeLimit = 8; 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 List _balls = new(); public List _ballSprites = new(); public List _workers = new(); public List _initialRackPositions = [ new Vector2I(0, 1), 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, // (0,0) denotes a ball that is not on the screen // 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"); Ball newBall; newBall = _ballScene.Instantiate(); newBall.SetSprite("res://art/cue_ball.png"); newBall._rackPosition = _initialRackPositions[0]; newBall._owner = this; newBall.OnHover += SetHovered; newBall.OnMovement += MovingChange; _balls.Add(newBall); BallSprite newBallSprite; newBallSprite = _ballSpriteScene.Instantiate(); newBallSprite.SetSprite(newBall._imagePath); newBallSprite._rackPosition = _initialRackPositions[0]; newBallSprite._owner = this; newBallSprite.OnHover += SetHovered; _ballSprites.Add(newBallSprite); for (int i = 1; i <= 15; i++) { newBall = _ballScene.Instantiate(); newBall.SetSprite("res://art/ball_" + i + ".png"); newBall._rackPosition = _initialRackPositions[i]; newBall._owner = this; newBall.OnHover += SetHovered; newBall.OnMovement += MovingChange; _balls.Add(newBall); newBallSprite = _ballSpriteScene.Instantiate(); newBallSprite.SetSprite(newBall._imagePath); newBallSprite._rackPosition = _initialRackPositions[i]; _rack.SetSprite((int)newBallSprite._rackPosition.Y, (int)newBallSprite._rackPosition.X, newBallSprite._imagePath); newBallSprite._owner = this; newBallSprite.OnHover += SetHovered; _ballSprites.Add(newBallSprite); } _managerPanel.SetManager(this); } public override void _Process(double DELTA_) { if (_ballsMoving == 0) { if (_ready) { if (_hoveredNode is Ball || _selectedNode is Ball) { if ((Ball)_selectedNode == null || ((Ball)_selectedNode != _hoveredNode && _hoveredNode is Ball)) { if (Input.IsActionJustReleased("left_click")) { _selectedNode = (Ball)_hoveredNode; ((Ball)_selectedNode)._selected = true; _cue.Don(((Ball)_selectedNode).Position); } } else if (Input.IsActionJustReleased("right_click")) { ((Ball)_selectedNode)._selected = false; _selectedNode = null; _cue.Doff(); } else if (_hoveredNode == null) { if (Input.IsActionJustReleased("left_click") && (Ball)_selectedNode != null && _cue._power == 0) { ((Ball)_selectedNode)._selected = false; _selectedNode = null; _cue.Doff(); } } } } else { if (_hoveredNode is BallSprite || _selectedNode is BallSprite) { if (_selectedNode != null) { Vector2 mousePosition = GetViewport().GetMousePosition(); ((BallSprite)_selectedNode).Position = mousePosition; if (Input.IsActionJustReleased("left_click")) { Ball ball = _balls.Single(b => b._rackPosition == ((BallSprite)_hoveredNode)._rackPosition); PlaceBall(ball, mousePosition); _hoveredNode = null; _selectedNode = null; if (_balls.Where(b => b._placed).ToList().Count >= _placeLimit) { _ready = true; } } } else { if (Input.IsActionJustReleased("left_click")) { _selectedNode = (BallSprite)_hoveredNode; } } } } } } public virtual void ChangeHealth(int CHANGE) { _health += CHANGE; _health = Math.Min(_health, _healthMax); if (_health < 0) { _dead = true; _health = 0; } GetNode("Panel").SetValue(_health); } public void MovingChange(Ball BALL, bool MOVING) { if (MOVING) { _ballsMoving++; } else { _ballsMoving--; } } public virtual void PlaceBall(Ball BALL, Vector2 POSITION) { BALL._available = true; BALL.Position = POSITION; BALL._active = true; BALL._placed = true; BALL._potted = false; BALL._active = true; if (!GetChildren().Contains(BALL)) { AddChild(BALL); } BallSprite ballSprite = _ballSprites.Single(s => s._rackPosition == BALL._rackPosition); ballSprite._active = false; if (GetChildren().Contains(ballSprite)) { RemoveChild(ballSprite); } _ballReturn._returnCount = _balls.Where(b => b._potted).ToList().Count; if (_ballReturn._returnCount > 0) { _ready = false; } else { _ready = true; } } 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; if (GetChildren().Contains(BALL)) { RemoveChild(BALL); } BallSprite ballSprite = _ballSprites.Single(s => s._rackPosition == BALL._rackPosition); int pottedCount = _ballReturn._returnCount; ballSprite.Position = new Vector2(_ballReturn.GlobalPosition.X + _ballReturn.Size.X / 2, _ballReturn.GlobalPosition.Y + 50 * (pottedCount + 1)); ballSprite._active = true; if (!GetChildren().Contains(ballSprite)) { CallDeferred(MethodName.AddChild, ballSprite); } _ballReturn._returnCount = _balls.Where(b => b._potted).ToList().Count; if (_ballReturn._returnCount > 0) { _ready = false; } else { _ready = true; } } 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) { int diameter = 36; int rows = _balls.Max(b => b._rackPosition.Y); Ball rackBall; int r, c; for (int i = 0; i < _balls.Count; i++) { rackBall = _balls[i]; c = rackBall._rackPosition.X; r = Math.Abs(rackBall._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(rackBall, position); } } TABLE.OnBallPotted += PotBall; // PLAYER.PotBall(); SetRack(); PotBall(_balls[0], null); } 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(); } } } }