void DrawAttackState(ProjectedGameState projectedState) { Sprite tileTargetedSprite = ScenarioImageManager.GetTileTargetedSprite(); for (int i = 0; i < projectedState.attackedPositions.Count; i++) { EntityData activeEntity = projectedState.activeEntity; Vector2Int attackedPosition = projectedState.attackedPositions[i]; GenerateAndPositionCellImage(attackedPosition, 0f, tileTargetedSprite, activeEntity.IdentifyingColor); AttackCardData cardData = projectedState.action.card as AttackCardData; Sprite pointerSprite = cardData.cardImage; float rotation = GetImageRotation(projectedState.action.direction); GameObject abilityPointer = ScenarioImageManager.GetAbilityPointer(pointerSprite, rotation, transform); abilityPointer.transform.position = GetPointerImagePosition(activeEntity.Position, projectedState.action.direction); if (!drawingSelectedEntity) { Color pointerColor = Color.white; pointerColor.a = deselectedEntityActionOpacity; abilityPointer.GetComponent <Image>().color = pointerColor; } } }
public void DrawUpcomingStates(ScenarioState currentState, List <ProjectedGameState> upcomingStates) { Clear(); drawingSelectedEntity = true; EntityData lastActiveEntity = null; for (int i = 0; i < upcomingStates.Count; i++) { ProjectedGameState projectedState = upcomingStates[i]; if (projectedState.IsDummyState) { continue; } ProjectedGameState nextState = i == upcomingStates.Count - 1 ? null : upcomingStates[i + 1]; DrawState(projectedState, nextState, lastActiveEntity); lastActiveEntity = projectedState.activeEntity; } DrawItemDurations(currentState.items); DrawEntityHealths(currentState.GetAllEntities()); }
void UpdateCurrentlyResolvingState(ProjectedGameState projectedState) { ResetTurnOutlines(); int turnIndex = currentlyDepictedTurns.FindIndex(t => t.Entity == projectedState.activeEntity); turnOutlines[turnIndex].effectColor = Color.yellow; }
void DrawMove(ProjectedGameState projectedState, ProjectedGameState nextState, EntityData movingEntity, EntityData lastActiveEntity) { Vector2Int positionThisState = movingEntity.Position; Vector2Int positionLastState = projectedState .scenarioState .lastGameState .GetEntityWhere(e => e.ID == movingEntity.ID) .Position; Vector2Int positionTwoStatesAgo = projectedState .scenarioState .lastGameState .lastGameState .GetEntityWhere(e => e.ID == movingEntity.ID) .Position; bool isEntitysFirstMove = positionLastState == positionTwoStatesAgo || movingEntity != lastActiveEntity; bool isEntitysLastMove = nextState == null || !nextState.scenarioState.HasEntityWhere(e => e == movingEntity) || nextState.scenarioState.GetEntityWhere(e => e == movingEntity).Position == movingEntity.Position; if (isEntitysLastMove) { DrawPath_Ending(movingEntity, positionLastState, positionThisState); } else { if (isEntitysFirstMove) { DrawPath_Beginning(movingEntity, positionLastState, positionThisState); } DrawPath_Between(movingEntity, positionLastState, positionThisState, nextState.scenarioState.GetEntityWhere(e => e == movingEntity).Position); } int distanceCovered = BoardHelperFunctions.GetLinearDistanceBetweenPositions(positionLastState, positionThisState); if (distanceCovered > 1) { Direction directionToDestination = BoardHelperFunctions.GetDirectionFromPosition(positionLastState, positionThisState); GameBoard currentBoard = BoardController.CurrentBoard; Tile lastTile = currentBoard.GetTileAtPosition(positionLastState); Tile currentTile = lastTile.GetDirectionalNeighbor(directionToDestination); Tile nextTile = currentTile.GetDirectionalNeighbor(directionToDestination); int intermediaryPathCount = 0; while (intermediaryPathCount < distanceCovered - 1) { DrawPath_Between(movingEntity, lastTile.Position, currentTile.Position, nextTile.Position); lastTile = currentTile; currentTile = nextTile; nextTile = currentTile.GetDirectionalNeighbor(directionToDestination); intermediaryPathCount++; } } }
static ProjectedGameState GetNextStateFromAction_Self(ScenarioState newState, EntityData entity, Action action) { SelfCardData card = action.card as SelfCardData; ProjectedGameState newProjectedState = new ProjectedGameState(entity, newState, action); entity.ChangeHealthValue_Scenario(card.healthChange, newState); card.modifiers.ForEach(m => entity.activeModifiers.Add(Object.Instantiate(m))); return(newProjectedState); }
IEnumerator ProcessCurrentRoundActions() { isResolvingTurn = true; DeselectEverything(); Queue <ProjectedGameState> upcomingStateQueue = new Queue <ProjectedGameState>(upcomingScenarioStates); while (upcomingStateQueue.Count > 0) { ProjectedGameState dequeuedProjectedState = upcomingStateQueue.Dequeue(); GameStateDelegates.OnResolvingState?.Invoke(dequeuedProjectedState); ScenarioState nextScenarioState = dequeuedProjectedState.scenarioState; if (dequeuedProjectedState.bumps.Count > 0) { dequeuedProjectedState.bumps.ForEach(b => Debug.Log(b.bumpingEntity + " bumping " + b.bumpedEntity)); } UpdateScenarioState(nextScenarioState); upcomingScenarioStates = new List <ProjectedGameState>(upcomingStateQueue); GameStateDelegates.OnCurrentScenarioStateChange(CurrentScenarioState, upcomingScenarioStates); dequeuedProjectedState.attackedPositions.ForEach(pos => GameStateDelegates.OnPositionAttacked(pos)); yield return(new WaitForSeconds(0.5f)); } if (CurrentScenarioState.isBossScenario && CurrentScenarioState.enemies.Count == 0) { winScreen.SetActive(true); yield break; } CurrentScenarioState.items = UpdateItemDurations(CurrentScenarioState); UpdateExitArrowVisibility(); GameStateDelegates.OnRoundEnded?.Invoke(CurrentScenarioState); isResolvingTurn = false; upcomingScenarioStates.Clear(); if (Player.CurrentHealth == 0) { lostScreen.SetActive(true); yield break; } GameStateDelegates.OnCurrentScenarioStateChange?.Invoke(CurrentScenarioState, upcomingScenarioStates); GenerateNextTurnStack(CurrentScenarioState); }
void DrawBump(EntityData bumpingEntity, ProjectedGameState projectedState, ProjectedGameState nextState, Bump bump) { Vector2Int positionTwoStatesAgo = projectedState .scenarioState .lastGameState .lastGameState .GetEntityWhere(e => e.ID == bumpingEntity.ID) .Position; Vector2Int positionThisState = bumpingEntity.Position; Vector2Int positionLastState = projectedState .scenarioState .lastGameState .GetEntityWhere(e => e.ID == bumpingEntity.ID) .Position; bool isEntitysFirstMove = positionLastState == positionTwoStatesAgo; bool bumpSucceeds = bumpingEntity.Position != positionLastState; if (bumpSucceeds) { DrawPath_Ending(bumpingEntity, positionLastState, positionThisState); DrawSuccessfulBumpEffect(positionThisState, BoardHelperFunctions.GetDirectionFromPosition(positionThisState, positionLastState)); DrawPath_Beginning(bump.bumpedEntity, positionThisState, bump.bumpedEntity.Position); } else if (isEntitysFirstMove) { Vector2Int bumpedEntityPosition = bump.bumpedEntity.Position; Sprite pathSprite = ScenarioImageManager.GetPathSprite(PathType.Beginning); Direction directionOfEntrance = BoardHelperFunctions.GetDirectionFromPosition(bumpedEntityPosition, positionThisState); GenerateAndPositionCellImage(positionThisState, GetImageRotation(directionOfEntrance), pathSprite, bumpingEntity.IdentifyingColor); DrawFailedBumpEffect(positionThisState, BoardHelperFunctions.GetDirectionFromPosition(positionThisState, bumpedEntityPosition)); } else { PathType pathType = GetFailedBumpPathType(positionTwoStatesAgo, positionThisState, bump.bumpedEntity.Position); Sprite pathSprite = ScenarioImageManager.GetPathSprite(pathType); Vector2Int bumpedEntityPosition = bump.bumpedEntity.Position; Direction directionOfEntrance = BoardHelperFunctions.GetDirectionFromPosition(positionThisState, positionTwoStatesAgo); GenerateAndPositionCellImage(positionThisState, GetImageRotation(directionOfEntrance), pathSprite, bumpingEntity.IdentifyingColor); DrawFailedBumpEffect(positionThisState, BoardHelperFunctions.GetDirectionFromPosition(positionThisState, bumpedEntityPosition)); } }
void DrawState(ProjectedGameState projectedState, ProjectedGameState nextState, EntityData lastActiveEntity) { CardCategory actionCardCategory = projectedState.action.card.category; projectedState.GetMovedEntities().ForEach(e => DrawMove(projectedState, nextState, e, lastActiveEntity)); //if (actionCardCategory == CardCategory.Movement) //{ // DrawMoveState(projectedState, nextState, lastActiveEntity); //} if (actionCardCategory == CardCategory.Attack) { DrawAttackState(projectedState); } projectedState.bumps.ForEach(b => DrawBump(b.bumpingEntity, projectedState, nextState, b)); }
void DrawPath(EntityData activeEntity, ProjectedGameState projectedState, ProjectedGameState nextState) { bool isEntityAliveNextState = nextState == null || nextState .scenarioState .HasEntityWhere(e => e == activeEntity); bool isEntitysLastMove = projectedState.action.card.category == CardCategory.Movement && (nextState == null || nextState.action.card.category != CardCategory.Movement || nextState.activeEntity.ID != activeEntity.ID); Vector2Int positionLastState = projectedState .scenarioState .lastGameState .GetEntityWhere(e => e.ID == activeEntity.ID) .Position; Vector2Int positionThisState = activeEntity.Position; if (isEntitysLastMove) { DrawPath_Ending(activeEntity, positionLastState, positionThisState); return; } bool isNextMoveFailedBump = nextState.DoesEntityBump(nextState.activeEntity) && nextState.activeEntity.Position == activeEntity.Position; if (projectedState.action.card.category == CardCategory.Movement && !isEntitysLastMove && !isNextMoveFailedBump && isEntityAliveNextState) { Vector2Int positionNextState = nextState .scenarioState .GetEntityWhere(e => e == activeEntity) .Position; DrawPath_Between(activeEntity, positionLastState, positionThisState, positionNextState); } }
void DrawMoveState(ProjectedGameState projectedState, ProjectedGameState nextState, EntityData lastActiveEntity) { EntityData activeEntity = projectedState.activeEntity; Vector2Int positionThisState = activeEntity.Position; Vector2Int positionLastState = projectedState .scenarioState .lastGameState .GetEntityWhere(e => e.ID == activeEntity.ID) .Position; EntityData activeEntityTwoStatesAgo = projectedState .scenarioState .lastGameState .lastGameState .GetEntityWhere(e => e.ID == activeEntity.ID); bool isEntitysFirstMove = lastActiveEntity == null || activeEntity.ID != lastActiveEntity.ID || (activeEntity.ID == activeEntityTwoStatesAgo.ID && activeEntity.Position == activeEntityTwoStatesAgo.Position); bool isFailedBump = projectedState.DoesEntityBump(activeEntity) && positionLastState == positionThisState; if (isEntitysFirstMove && !isFailedBump) { DrawPath_Beginning(activeEntity, positionLastState, positionThisState); } if (!projectedState.DoesEntityBump(activeEntity)) { DrawPath(activeEntity, projectedState, nextState); } else { projectedState.bumps.ForEach(b => DrawBump(activeEntity, projectedState, nextState, b)); } }
void HighlightSelectedEntityStates(EntityData selectedEntity, ScenarioState currentGameState, List <ProjectedGameState> upcomingStates) { Clear(); EntityData lastActiveEntity = null; for (int i = 0; i < upcomingStates.Count; i++) { ProjectedGameState projectedState = upcomingStates[i]; if (projectedState.IsDummyState) { continue; } ProjectedGameState nextState = i == upcomingStates.Count - 1 ? null : upcomingStates[i + 1]; bool isEntityDeadThisState = !projectedState.scenarioState.HasEntityWhere(e => e == selectedEntity); bool didEntityDieThisState = projectedState.scenarioState.lastGameState.HasEntityWhere(e => selectedEntity == e); if (isEntityDeadThisState) { if (!didEntityDieThisState) { drawingSelectedEntity = false; DrawState(projectedState, nextState, lastActiveEntity); lastActiveEntity = projectedState.activeEntity; continue; } else { drawingSelectedEntity = true; DrawState(projectedState, nextState, lastActiveEntity); lastActiveEntity = projectedState.activeEntity; Vector2Int entityPositionLastState = projectedState.scenarioState .lastGameState .GetEntityWhere(e => e == selectedEntity) .Position; if (!projectedState.scenarioState.HasEntityWhere(e => e.Position == selectedEntity.Position) && selectedEntity.Position != entityPositionLastState) { GenerateAndPositionCellImage(entityPositionLastState, 0f, selectedEntity.entitySprite, translucent); } GenerateAndPositionCellImage(entityPositionLastState, 0f, deadEntitySprite, Color.white); continue; } } Vector2Int selectedEntityPositionThisState = projectedState .scenarioState .GetEntityWhere(e => e == selectedEntity) .Position; bool isSelectedEntityState = projectedState.activeEntity == selectedEntity; bool isSelectedEntityBumped = projectedState.IsEntityBumped(selectedEntity); bool isSelectedEntityAttacked = projectedState.attackedPositions.Contains(selectedEntityPositionThisState); if (isSelectedEntityState || isSelectedEntityBumped || isSelectedEntityAttacked) { drawingSelectedEntity = true; // Draw entity under attack targeting reticule if // (A) selected entity is hit OR // (B) selected entity is attacking & hits someone. projectedState .attackedPositions .Select(position => projectedState .scenarioState .GetTileOccupant(position)) .Where(attackTarget => attackTarget != null && isSelectedEntityState || attackTarget == selectedEntity) .ToList() .ForEach(entity => boardController.DrawEntityAtPosition(entity, translucent)); // Draw entities killed this turn. projectedState .scenarioState .lastGameState .GetAllEntities() .ForEach(e => { if (!projectedState.scenarioState.HasEntityWhere(projectedEntity => e == projectedEntity)) { if (!currentGameState.HasEntityWhere(currentEntity => currentEntity.Position == e.Position)) { GenerateAndPositionCellImage(e.Position, 0f, e.entitySprite, translucent); } GenerateAndPositionCellImage(e.Position, 0f, deadEntitySprite, Color.white); } }); } else { drawingSelectedEntity = false; } DrawState(projectedState, nextState, lastActiveEntity); lastActiveEntity = projectedState.activeEntity; } DrawEntityHealth(selectedEntity); DrawItemDurations(currentGameState.items); }
void ResolvingStateHandler(ProjectedGameState projectedState) { endRoundButton.interactable = false; }
static ProjectedGameState GetNextStateFromAction_Attack(ScenarioState newState, EntityData entity, Action action) { GameBoard testBoard = BoardController.CurrentBoard; AttackCardData card = action.card as AttackCardData; TargetType attackTargetType = card.targetType; Tile attackOriginTile = BoardController.CurrentBoard.GetTileAtPosition(entity.Position); List <Tile> targetTiles = new List <Tile>(); switch (attackTargetType) { case TargetType.Single: targetTiles.Add(newState.FindFirstOccupiedTileInDirection(attackOriginTile, action.direction, action.distance)); break; case TargetType.AreaOfEffect: Tile impactTile = newState.FindFirstOccupiedTileInDirection(attackOriginTile, action.direction, action.distance); targetTiles.Add(impactTile); targetTiles.AddRange(impactTile.Neighbors); break; case TargetType.Line: targetTiles.AddRange(attackOriginTile.GetAllTilesInDirection(action.direction, action.card.range)); break; default: break; } ProjectedGameState newProjectedState = new ProjectedGameState(entity, newState, action); newProjectedState.AddAttackedPositions(targetTiles.Select(t => t.Position)); List <EntityData> affectedEntities = targetTiles .Select(t => newState.GetTileOccupant(t)) .Where(o => o != null) .ToList(); if (affectedEntities.Count == 0) { List <ModifierData> modifiersToResolve = action.card.modifiers .Where(m => m.modifierCategory == ModifierCategory.Blowback || m.modifierCategory == ModifierCategory.FollowUp) .ToList(); for (int i = 0; i < modifiersToResolve.Count; i++) { ModifierData modifier = modifiersToResolve[i]; ApplyModifierToAttack_BlowbackFollowUp(modifier, entity, newState, action.direction, modifier.modifierCategory); } return(newProjectedState); } for (int i = 0; i < affectedEntities.Count; i++) { EntityData affectedEntity = affectedEntities[i]; int cardDamage = card.damage + entity.GetAttackModifierValue(); affectedEntity.DealDamage(cardDamage, newState); List <ModifierData> attackModifiers = action.card.modifiers; if (attackModifiers != null && attackModifiers.Count > 0) { for (int j = 0; i < attackModifiers.Count; i++) { ApplyModifierToAttack(affectedEntity, attackModifiers[j], entity, newState, action.direction); } } } return(newProjectedState); }
public static List <ProjectedGameState> CalculateUpcomingStates(ScenarioState currentState, GameBoard board) { List <ProjectedGameState> projectedGameStates = new List <ProjectedGameState>(); ScenarioState mostRecentState = currentState.DeepCopy(); mostRecentState.lastGameState = currentState; Vector2Int lastPlayerPosition = currentState.player.Position; while (mostRecentState.turnStack.Count > 0) { Turn turn = mostRecentState.turnStack.Pop(); EntityData entity = turn.Entity; foreach (Direction move in turn.moves) { bool entityIsAliveToMove = mostRecentState.HasEntityWhere(e => e == entity); if (!entityIsAliveToMove) { break; } ProjectedGameState updatedState = GetNextGameStateFromMove(mostRecentState, entity, move); entity = updatedState.activeEntity; projectedGameStates.Add(updatedState); mostRecentState = updatedState.scenarioState; if (updatedState.bumps.Count > 0) { break; } } if (projectedGameStates.Count > 0) { projectedGameStates.Last().scenarioState.CollectFinishMoveItems(); } bool entityIsStillAlive = mostRecentState.HasEntityWhere(e => e == entity); if (!entityIsStillAlive) { continue; } if (turn.action.card != null) { ProjectedGameState updatedState = GetNextGameStateFromAction(mostRecentState, entity, turn.action); entity = updatedState.activeEntity; projectedGameStates.Add(updatedState); mostRecentState = updatedState.scenarioState; } UpdateEntityModifiers(entity, mostRecentState); } // TODO: As-is, this was causing a bunch of problems with state calculation. Gotta bugfix it. // If enemies dead, duplicate current gamestate, just for stagnation projection purposes. //if (projectedGameStates.Count == 0) //{ // ProjectedGameState fillerGameState = new ProjectedGameState(currentState.DeepCopy()); // projectedGameStates.Add(fillerGameState); //} //ScenarioState lastCalculatedState = projectedGameStates.Last().scenarioState; //lastCalculatedState.UpdateStagnation(board); //lastCalculatedState.stagnatedPositions.ForEach(p => //{ // EntityData stagnatedEntity = lastCalculatedState.GetTileOccupant(p); // if (stagnatedEntity != null) // { // stagnatedEntity.DealDamage(1, lastCalculatedState); // } //}); return(projectedGameStates); }