internal void UpdatePlayerRemainingMovement(ActorData actor, bool send = true) { ActorTurnSM turnSm = actor.gameObject.GetComponent <ActorTurnSM>(); ActorController actorController = actor.gameObject.GetComponent <ActorController>(); ActorMovement actorMovement = actor.GetActorMovement(); float movementCost = GetActorMovementCost(actor, out float lastStepCost); bool cannotExceedMaxMovement = GameplayData.Get()?.m_movementMaximumType == GameplayData.MovementMaximumType.CannotExceedMax; List <ActorTargeting.AbilityRequestData> abilityRequest = actor.TeamSensitiveData_authority.GetAbilityRequestData(); bool abilitySet = !abilityRequest.IsNullOrEmpty() && abilityRequest[0].m_actionType != AbilityData.ActionType.INVALID_ACTION; actor.RemainingHorizontalMovement = actorMovement.CalculateMaxHorizontalMovement() - movementCost; actor.RemainingMovementWithQueuedAbility = abilitySet ? actor.RemainingHorizontalMovement : actorMovement.CalculateMaxHorizontalMovement(true) - movementCost; actor.QueuedMovementAllowsAbility = abilitySet || (cannotExceedMaxMovement ? actor.RemainingMovementWithQueuedAbility >= 0 : actor.RemainingMovementWithQueuedAbility + lastStepCost > 0); Log.Info($"UpdatePlayerMovement: Basic: {actor.m_postAbilityHorizontalMovement}/{actor.m_maxHorizontalMovement}, +", $"Remaining: {actor.RemainingMovementWithQueuedAbility}/{actor.RemainingHorizontalMovement}, " + $"Movement cost: {movementCost}, Ability set: {abilitySet}, Ability allowed: {actor.QueuedMovementAllowsAbility}, " + $"Movement max type: {GameplayData.Get()?.m_movementMaximumType}"); actorMovement.UpdateSquaresCanMoveTo(); if (send) { actorController.CallRpcUpdateRemainingMovement(actor.RemainingHorizontalMovement, actor.RemainingMovementWithQueuedAbility); } }
private float GetActorMovementCost(ActorData actor, out float lastStepCost) { float movementCost = 0; lastStepCost = 0; ActorMovement actorMovement = actor.GetActorMovement(); LineData.LineInstance movementLine = actor.TeamSensitiveData_authority.MovementLine; if (movementLine != null) { GridPos prevPos = actor.InitialMoveStartSquare.GetGridPosition(); foreach (var curPos in movementLine.m_positions) { lastStepCost = actorMovement.BuildPathTo(Board.Get().GetSquare(prevPos), Board.Get().GetSquare(curPos)).next?.moveCost ?? 0f; // TODO optimize this atrocity movementCost += lastStepCost; prevPos = curPos; } } return(movementCost); }
private BoardSquarePathInfo ResolveMovement(ActorData actor) { ActorTeamSensitiveData atsd = actor.TeamSensitiveData_authority; ActorMovement actorMovement = actor.GetActorMovement(); BoardSquare start = actor.InitialMoveStartSquare; BoardSquare end = actor.MoveFromBoardSquare; BoardSquarePathInfo path; if (atsd.MovementLine != null) { path = BuildPathAlongMovementLine(actor); } else { path = actorMovement.BuildPathTo(start, end); } if (path == null) { path = actorMovement.BuildPathTo(start, start); } for (var pathNode = path; pathNode.next != null; pathNode = pathNode.next) { pathNode.m_unskippable = true; // so that aestetic path is not optimized (see CreateRunAndVaultAesteticPath) } var path2 = path; while (path2.next != null) { Log.Info($"FINAL PATH {path2.square.GetGridPosition()}"); path2 = path2.next; } Log.Info($"FINAL PATH {path2.square.GetGridPosition()}"); return(path); }
private static BoardSquarePathInfo BuildPathAlongMovementLine(ActorData actor) { ActorTeamSensitiveData atsd = actor.TeamSensitiveData_authority; ActorMovement actorMovement = actor.GetActorMovement(); BoardSquare start = actor.InitialMoveStartSquare; BoardSquare end = actor.MoveFromBoardSquare; // TODO refactor this atrocity BoardSquarePathInfo path = actorMovement.BuildPathTo(start, start); BoardSquarePathInfo node = path; foreach (var curPos in atsd.MovementLine.m_positions) { node.next = actorMovement.BuildPathTo(node.square, Board.Get().GetSquare(curPos)).next; if (node.next == null) { continue; } node.next.moveCost += node.moveCost; node.next.prev = node; node = node.next; } return(path); }
public void CmdSetSquare(ActorTurnSM actorTurnSM, int x, int y, bool setWaypoint) { ActorData actor = actorTurnSM.gameObject.GetComponent <ActorData>(); if (!GameFlowData.Get().IsInDecisionState()) { Log.Info($"Recieved CmdSetSquare not in desicion state! {actor.DisplayName} [{x}, {y}] (setWaypoint = {setWaypoint})"); actorTurnSM.CallRpcTurnMessage((int)TurnMessage.MOVEMENT_REJECTED, 0); return; } Log.Info($"CmdSetSquare {actor.DisplayName} [{x}, {y}] (setWaypoint = {setWaypoint})"); BoardSquare boardSquare = Board.Get().GetSquare(x, y); ActorMovement actorMovement = actor.GetActorMovement(); if (!setWaypoint) { ClearMovementRequest(actor, false); } actorMovement.UpdateSquaresCanMoveTo(); if (!actor.CanMoveToBoardSquare(boardSquare)) { boardSquare = actorMovement.GetClosestMoveableSquareTo(boardSquare, false); } if (actor.TeamSensitiveData_authority.MovementLine == null) { actor.TeamSensitiveData_authority.MovementLine = new LineData.LineInstance(); } if (actor.TeamSensitiveData_authority.MovementLine.m_positions.Count == 0) { actor.TeamSensitiveData_authority.MovementLine.m_positions.Add(actor.InitialMoveStartSquare.GetGridPosition()); } BoardSquarePathInfo path = actorMovement.BuildPathTo(actor.TeamSensitiveData_authority.MoveFromBoardSquare, boardSquare); if (path == null) // TODO check cost { Log.Info($"CmdSetSquare: Movement rejected"); UpdatePlayerRemainingMovement(actor); // TODO updating because we cancelled movement - perhaps we should not cancel in this case actorTurnSM.CallRpcTurnMessage((int)TurnMessage.MOVEMENT_REJECTED, 0); return; } //List<GridPos> posList = path.ToGridPosPath(); List <GridPos> posList = new List <GridPos>(); for (var pathNode = path; pathNode.next != null; pathNode = pathNode.next) { posList.Add(pathNode.next.square.GetGridPosition()); // TODO why doesnt path.ToGridPosPath() work? } actor.TeamSensitiveData_authority.MovementLine.m_positions.AddRange(posList); actor.TeamSensitiveData_authority.MoveFromBoardSquare = boardSquare; actor.MoveFromBoardSquare = boardSquare; UpdatePlayerRemainingMovement(actor); actorTurnSM.CallRpcTurnMessage((int)TurnMessage.MOVEMENT_ACCEPTED, 0); }
private BoardSquarePathInfo BackOff(ActorData actor, BoardSquarePathInfo pathEnd, HashSet <GridPos> occupiedSquares) { if (actor == null) { Log.Error($"Backoff failed because actor is null!"); return(null); } Log.Info($"Calculating backoff for {actor.DisplayName}"); BoardSquare dest = pathEnd.prev?.square ?? pathEnd.square; if (occupiedSquares.Contains(dest.GetGridPosition())) { bool diagMovementAllowed = GameplayData.Get().m_diagonalMovement != GameplayData.DiagonalMovement.Disabled; List <BoardSquare> neighbours = new List <BoardSquare>(8); Queue <BoardSquare> candidates = new Queue <BoardSquare>(); candidates.Enqueue(pathEnd.square); while (candidates.Count > 0) { BoardSquare s = candidates.Dequeue(); if (!occupiedSquares.Contains(s.GetGridPosition())) { dest = s; break; } neighbours.Clear(); if (!diagMovementAllowed) { Board.Get().GetStraightAdjacentSquares(s.x, s.y, ref neighbours); } else { Board.Get().GetAllAdjacentSquares(s.x, s.y, ref neighbours); } neighbours.Sort(delegate(BoardSquare a, BoardSquare b) { return(dest.HorizontalDistanceInWorldTo(a).CompareTo(dest.HorizontalDistanceInWorldTo(b))); }); foreach (var n in neighbours) { if (n.IsBoardHeight()) { candidates.Enqueue(n); } } } } if (occupiedSquares.Contains(dest.GetGridPosition())) { Log.Error($"Backoff failed to find a free square for {actor.DisplayName}!"); } occupiedSquares.Add(dest.GetGridPosition()); BoardSquarePathInfo result = actor.GetActorMovement().BuildPathTo_IgnoreBarriers(pathEnd.square, dest); result.heuristicCost += pathEnd.heuristicCost; // not actually correct but shouldn't matter result.moveCost += pathEnd.moveCost; result.m_moverBumpedFromClash = true; return(result); }