public ClientMovementResults( ActorData triggeringMover, BoardSquarePathInfo triggeringPath, List <ServerClientUtils.SequenceStartData> seqStartDataList, ClientEffectResults effectResults, ClientBarrierResults barrierResults, ClientAbilityResults powerupResults, ClientAbilityResults gameModeResults) { m_triggeringMover = triggeringMover; m_triggeringPath = triggeringPath; m_seqStartDataList = seqStartDataList; m_effectResults = effectResults; m_barrierResults = barrierResults; m_powerupResults = powerupResults; m_gameModeResults = gameModeResults; if (m_effectResults != null) { m_effectResults.MarkActorHitsAsMovementHits(); } if (m_barrierResults != null) { m_barrierResults.MarkActorHitsAsMovementHits(); } if (m_powerupResults != null) { m_powerupResults.MarkActorHitsAsMovementHits(); } if (m_gameModeResults != null) { m_gameModeResults.MarkActorHitsAsMovementHits(); } m_alreadyReacted = false; }
public void ResolveMovement() { Dictionary <int, BoardSquarePathInfo> paths = new Dictionary <int, BoardSquarePathInfo>(); foreach (ActorData actor in GameFlowData.Get().GetActors()) { paths.Add(actor.ActorIndex, ResolveMovement(actor)); } Dictionary <int, BoardSquarePathInfo> nodes = new Dictionary <int, BoardSquarePathInfo>(paths); bool finished = false; for (float time = 0; !finished; time += RESOLUTION_STEP) { if (!ResolveSubstep(nodes, time, out finished)) { // TODO optimize time = -RESOLUTION_STEP; nodes = new Dictionary <int, BoardSquarePathInfo>(paths); Log.Info("Restarting movement resolution loop"); } } var movementActions = ArtemisServerBarrierManager.Get().OnMovement(paths); ArtemisServerResolutionManager.Get().SendMovementActions(movementActions); // TODO ClientMovementManager.MsgServerMovementStarting foreach (ActorData actor in GameFlowData.Get().GetActors()) { BoardSquarePathInfo start = paths[actor.ActorIndex]; BoardSquarePathInfo end = start; while (end.next != null) { end = end.next; } ActorTeamSensitiveData atsd = actor.TeamSensitiveData_authority; // TODO GetPathEndpoint everywhere // TODO movement camera bounds actor.MoveFromBoardSquare = end.square; actor.InitialMoveStartSquare = end.square; atsd.CallRpcMovement( GameEventManager.EventType.Invalid, GridPosProp.FromGridPos(start.square.GetGridPosition()), GridPosProp.FromGridPos(end.square.GetGridPosition()), MovementUtils.SerializePath(start), ActorData.MovementType.Normal, false, false); atsd.MovementLine?.m_positions.Clear(); } Log.Info("Movement resolved"); }
public void OnActorMoved_ClientResolutionAction(ActorData mover, BoardSquarePathInfo curPath) { if (!m_moveResults.TriggerMatchesMovement(mover, curPath)) { return; } m_moveResults.ReactToMovement(mover); }
public bool TriggerMatchesMovement(ActorData mover, BoardSquarePathInfo curPath) { if (m_alreadyReacted || mover != m_triggeringMover) { return(false); } return(MovementUtils.ArePathSegmentsEquivalent_FromBeginning(m_triggeringPath, curPath)); }
public override void Deserialize(NetworkReader reader, GameObject context) { var board = context.GameManager.Board; EventType = (GameEventManager.EventType)reader.ReadInt32(); Start = GeneratedNetworkCode._ReadGridPosProp_None(reader); EndGridPos = GeneratedNetworkCode._ReadGridPosProp_None(reader); EndSquare = board.GetBoardSquare(GridPos.FromGridPosProp(EndGridPos)); var pathBytes = reader.ReadBytesAndSize(); Path = MovementUtils.DeSerializePath(board, pathBytes); MovementType = (ActorData.MovementType)reader.ReadInt32(); DisappearAfterMovement = reader.ReadBoolean(); Respawning = reader.ReadBoolean(); }
public static bool ArePathSegmentsEquivalent_FromBeginning( BoardSquarePathInfo pathA, BoardSquarePathInfo pathB) { if (pathA == null || pathB == null || (pathA.square == null || pathB.square == null) || pathA.square != pathB.square) { return(false); } var flag = true; var boardSquarePathInfo1 = pathA; var boardSquarePathInfo2 = pathB; int num; for (num = 0; flag && num < 100; ++num) { boardSquarePathInfo1 = boardSquarePathInfo1.prev; boardSquarePathInfo2 = boardSquarePathInfo2.prev; if (boardSquarePathInfo1 != null || boardSquarePathInfo2 != null) { if (boardSquarePathInfo1 == null && boardSquarePathInfo2 != null) { flag = false; } else if (boardSquarePathInfo1 != null && boardSquarePathInfo2 == null) { flag = false; } else if (boardSquarePathInfo1.square != boardSquarePathInfo2.square) { flag = false; } } else { break; } } if (num >= 100) { Log.Print(LogType.Error, "Infinite/circular (or maybe just massive) loop detected in ArePathSegmentsEquivalent_FromBeginning."); } return(flag); }
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); }
private bool ResolveSubstep(Dictionary <int, BoardSquarePathInfo> nodes, float time, out bool finished) { // Advancing finished = true; foreach (var node in new Dictionary <int, BoardSquarePathInfo>(nodes)) { if (node.Value.next != null) { finished = false; if (node.Value.next.moveCost < time) { nodes[node.Key] = node.Value.next; } } } // Grouping by square var nodesBySquare = new Dictionary <GridPos, List <KeyValuePair <int, BoardSquarePathInfo> > >(); foreach (var node in nodes) { GridPos square = node.Value.square.GetGridPosition(); if (!nodesBySquare.ContainsKey(square)) { nodesBySquare[square] = new List <KeyValuePair <int, BoardSquarePathInfo> > { node }; } else { nodesBySquare[square].Add(node); } } // Detecting clashes foreach (var node in nodesBySquare) { GridPos pos = node.Key; List <KeyValuePair <int, BoardSquarePathInfo> > pathInfos = node.Value; if (pathInfos.Count > 1) { pathInfos.Sort(delegate(KeyValuePair <int, BoardSquarePathInfo> a, KeyValuePair <int, BoardSquarePathInfo> b) { return(a.Value.moveCost.CompareTo(b.Value.moveCost)); }); for (int i = 0; i < pathInfos.Count - 1; ++i) { for (int j = i + 1; j < pathInfos.Count; ++j) { BoardSquarePathInfo a = pathInfos[i].Value; BoardSquarePathInfo b = pathInfos[j].Value; bool mutualClash = b.moveCost - a.moveCost < CLASH_THRESHOLD; if (mutualClash) { a.m_moverClashesHere = true; b.m_moverClashesHere = true; } // if both stop if (a.next == null && b.next == null) { if (mutualClash) { var occupiedSquares = new HashSet <GridPos>(nodesBySquare.Keys); ActorData aActor = Utils.GetActorByIndex(pathInfos[i].Key); a.next = BackOff(aActor, a, occupiedSquares); // TODO choose winner randomly? a and b can have idential backoff, a has an advantage currently ActorData bActor = Utils.GetActorByIndex(pathInfos[j].Key); b.next = BackOff(bActor, b, occupiedSquares); } else { if (b.prev != null) { b.prev.next = null; b.prev.m_moverBumpedFromClash = true; return(false); } else { Log.Error($"Failed to resolve movement for player {pathInfos[i].Key} -- but they did not move!"); } } } } } } } return(true); }
public static BoardSquarePathInfo DeSerializePath(Component context, NetworkReader reader) { var boardSquarePathInfo1 = new BoardSquarePathInfo(); var boardSquarePathInfo2 = boardSquarePathInfo1; BoardSquarePathInfo boardSquarePathInfo3 = null; float num1 = 0.0f; sbyte num2 = 0; sbyte num3 = 0; float num4 = 0.0f; float num5 = 0.0f; float num6 = 0.0f; bool out0_1 = false; bool out1_1 = false; bool flag; if (flag = reader.ReadBoolean()) { num4 = reader.ReadSingle(); num5 = reader.ReadSingle(); num6 = reader.ReadSingle(); } bool out2 = !flag; bool out3 = false; bool out4 = false; bool out5 = false; bool out0_2 = false; bool out1_2 = false; while (!out2) { byte num7 = reader.ReadByte(); byte num8 = reader.ReadByte(); sbyte num9 = reader.ReadSByte(); int num10; switch (num9) { case 0: case 3: num10 = 1; break; default: num10 = num9 == (sbyte)1 ? 1 : 0; break; } if (num10 == 0) { num2 = reader.ReadSByte(); num3 = reader.ReadSByte(); } var bitField1 = reader.ReadByte(); var bitField2 = reader.ReadByte(); var out6 = false; var out7 = false; ServerClientUtils.GetBoolsFromBitfield(bitField1, out out0_1, out out1_1, out out2, out out3, out out4, out out5, out out6, out out7); ServerClientUtils.GetBoolsFromBitfield(bitField2, out out0_2, out out1_2); var num11 = num4; var num12 = num5; if (out6) { num11 = reader.ReadSingle(); } if (out7) { num12 = reader.ReadSingle(); } var boardSquare = context.Board.method_10(num7, num8); if (boardSquare == null) { Log.Print(LogType.Error, "Failed to find square from index [" + num7 + ", " + num8 + "] during serialization of path"); } boardSquarePathInfo2.square = boardSquare; boardSquarePathInfo2.moveCost = num1; boardSquarePathInfo2.heuristicCost = 0.0f; boardSquarePathInfo2.connectionType = (BoardSquarePathInfo.ConnectionType)num9; boardSquarePathInfo2.chargeCycleType = (BoardSquarePathInfo.ChargeCycleType)num2; boardSquarePathInfo2.chargeEndType = (BoardSquarePathInfo.ChargeEndType)num3; boardSquarePathInfo2.segmentMovementSpeed = num11; boardSquarePathInfo2.segmentMovementDuration = num12; boardSquarePathInfo2.m_reverse = out0_1; boardSquarePathInfo2.m_unskippable = out1_1; boardSquarePathInfo2.m_visibleToEnemies = out3; boardSquarePathInfo2.m_updateLastKnownPos = out4; boardSquarePathInfo2.m_moverDiesHere = out5; boardSquarePathInfo2.m_moverClashesHere = out0_2; boardSquarePathInfo2.m_moverBumpedFromClash = out1_2; boardSquarePathInfo2.prev = boardSquarePathInfo3; if (boardSquarePathInfo3 != null) { boardSquarePathInfo3.next = boardSquarePathInfo2; } if (!out2) { boardSquarePathInfo3 = boardSquarePathInfo2; boardSquarePathInfo2 = new BoardSquarePathInfo(); } } boardSquarePathInfo1.moveCost = num6; boardSquarePathInfo1.CalcAndSetMoveCostToEnd(context); return(boardSquarePathInfo1); }
public override void UpdateTargetingMultiTargets(AbilityTarget currentTarget, ActorData targetingActor, int currentTargetIndex, List <AbilityTarget> targets) { ClearActorsInRange(); m_hitActorContext.Clear(); Vector3 travelBoardSquareWorldPositionForLos = targetingActor.GetTravelBoardSquareWorldPositionForLos(); Vector3 aimDirection = currentTarget?.AimDirection ?? targetingActor.transform.forward; float maxDistancePerBounce = m_maxDistancePerBounce + (m_extraDistancePerBounceDelegate != null ? m_extraDistancePerBounceDelegate() : 0f); float maxTotalDistance = m_maxTotalDistance + (m_extraTotalDistanceDelegate != null ? m_extraTotalDistanceDelegate() : 0f); int maxBounces = m_maxBounces + (m_extraBouncesDelegate != null ? Mathf.RoundToInt(m_extraBouncesDelegate()) : 0); int maxTargetsHit = m_maxTargetsHit; if (m_ability is ScoundrelBouncingLaser && CollectTheCoins.Get() != null) { maxTotalDistance += CollectTheCoins.Get().m_bouncingLaserTotalDistance.GetBonus_Client(targetingActor); maxDistancePerBounce += CollectTheCoins.Get().m_bouncingLaserBounceDistance.GetBonus_Client(targetingActor); maxBounces += Mathf.RoundToInt(CollectTheCoins.Get().m_bouncingLaserBounces.GetBonus_Client(targetingActor)); maxTargetsHit += Mathf.RoundToInt(CollectTheCoins.Get().m_bouncingLaserPierces.GetBonus_Client(targetingActor)); } bool penetrateTargetsAndHitCaster = m_penetrateTargetsAndHitCaster; List <Vector3> endpoints = VectorUtils.CalculateBouncingLaserEndpoints( travelBoardSquareWorldPositionForLos, aimDirection, maxDistancePerBounce, maxTotalDistance, maxBounces, targetingActor, m_width, maxTargetsHit, m_includeInvisibles, // was false GetAffectedTeams(), m_bounceOnActors, out Dictionary <ActorData, AreaEffectUtils.BouncingLaserInfo> bounceHitActors, out List <ActorData> orderedHitActors, null, penetrateTargetsAndHitCaster); if (penetrateTargetsAndHitCaster && endpoints.Count > 1) { float totalMaxDistanceInSquares = maxTotalDistance - (endpoints[0] - travelBoardSquareWorldPositionForLos).magnitude / Board.Get().squareSize; Vector3 normalized = (endpoints[1] - endpoints[0]).normalized; VectorUtils.CalculateBouncingLaserEndpoints( endpoints[0], normalized, maxDistancePerBounce, totalMaxDistanceInSquares, maxBounces, targetingActor, m_width, 0, m_includeInvisibles, // was false targetingActor.GetTeams(), m_bounceOnActors, out Dictionary <ActorData, AreaEffectUtils.BouncingLaserInfo> _, out List <ActorData> orderedHitActors2, null, false, false); if (orderedHitActors2.Contains(targetingActor)) { AddActorInRange(targetingActor, targetingActor.GetTravelBoardSquareWorldPositionForLos(), targetingActor, AbilityTooltipSubject.Self); } } foreach (var hitActor in bounceHitActors) { AddActorInRange(hitActor.Key, hitActor.Value.m_segmentOrigin, targetingActor); if (hitActor.Value.m_endpointIndex > 0) { SetIgnoreCoverMinDist(hitActor.Key, true); } } HitActorContext item = default(HitActorContext); for (int i = 0; i < orderedHitActors.Count; i++) { ActorData hitActor = orderedHitActors[i]; AreaEffectUtils.BouncingLaserInfo bouncingLaserInfo = bounceHitActors[hitActor]; item.actor = hitActor; item.segmentIndex = bouncingLaserInfo.m_endpointIndex; m_hitActorContext.Add(item); ActorHitContext actorHitContext = m_actorContextVars[hitActor]; actorHitContext.source = targetingActor.GetTravelBoardSquareWorldPositionForLos(); actorHitContext.context.SetInt(TargetSelect_BouncingLaser.s_cvarEndpointIndex.GetKey(), bouncingLaserInfo.m_endpointIndex); actorHitContext.context.SetInt(TargetSelect_BouncingLaser.s_cvarHitOrder.GetKey(), i); } m_laserEndpoints = endpoints; //CreateLaserHighlights(travelBoardSquareWorldPositionForLos, endpoints); //if (targetingActor == GameFlowData.Get().activeOwnedActorData) //{ // ResetSquareIndicatorIndexToUse(); // AreaEffectUtils.OperateOnSquaresInBounceLaser(m_indicatorHandler, travelBoardSquareWorldPositionForLos, endpoints, m_width, targetingActor, false); // HideUnusedSquareIndicators(); //} if (m_knockbackDistance > 0f) { int movementArrowIndex = 0; EnableAllMovementArrows(); for (int i = 0; i < orderedHitActors.Count; i++) { ActorData hitActor = orderedHitActors[i]; if (hitActor.GetTeam() == targetingActor.GetTeam() || m_maxKnockbackTargets > 0 && i >= m_maxKnockbackTargets) { continue; } float knockbackDistance = m_knockbackDistance + (m_extraKnockdownDelegate != null ? m_extraKnockdownDelegate(hitActor) : 0f); AreaEffectUtils.BouncingLaserInfo bouncingLaserInfo = bounceHitActors[hitActor]; Vector3 aimDir = endpoints[bouncingLaserInfo.m_endpointIndex] - bouncingLaserInfo.m_segmentOrigin; BoardSquarePathInfo path = KnockbackUtils.BuildKnockbackPath(hitActor, m_knockbackType, aimDir, bouncingLaserInfo.m_segmentOrigin, knockbackDistance); movementArrowIndex = AddMovementArrowWithPrevious(hitActor, path, TargeterMovementType.Knockback, movementArrowIndex); } SetMovementArrowEnabledFromIndex(movementArrowIndex, false); } }
internal static BoardSquarePathInfo DeSerializeLightweightPath(Component context, IBitStream stream) { if (stream == null) { Log.Print(LogType.Error, "Calling DeSerializeLightweightPath with a null stream"); return(null); } BoardSquarePathInfo boardSquarePathInfo1; if (stream.isWriting) { Log.Print(LogType.Error, "Trying to deserialize a (lightweight) path while writing."); boardSquarePathInfo1 = null; } else { sbyte num1 = 0; stream.Serialize(ref num1); if (num1 <= 0) { boardSquarePathInfo1 = null; } else { sbyte num2 = 0; stream.Serialize(ref num2); boardSquarePathInfo1 = null; BoardSquarePathInfo boardSquarePathInfo2 = null; for (int index = 0; index < (int)num1; ++index) { short num3 = -1; short num4 = -1; stream.Serialize(ref num3); stream.Serialize(ref num4); var boardSquare = num3 != (short)-1 || num4 != (short)-1 ? context.Board.method_10(num3, num4) : null; var boardSquarePathInfo3 = new BoardSquarePathInfo(); boardSquarePathInfo3.square = boardSquare; boardSquarePathInfo3.prev = boardSquarePathInfo2; if (boardSquarePathInfo2 != null) { boardSquarePathInfo2.next = boardSquarePathInfo3; } boardSquarePathInfo2 = boardSquarePathInfo3; if (index == 0) { boardSquarePathInfo1 = boardSquarePathInfo3; } } BoardSquarePathInfo boardSquarePathInfo4 = boardSquarePathInfo1; for (int index = 0; index < (int)num2; ++index) { short num3 = -1; short num4 = -1; stream.Serialize(ref num3); stream.Serialize(ref num4); var boardSquare = num3 != (short)-1 || num4 != (short)-1 ? context.Board.method_10(num3, num4) : null; var boardSquarePathInfo3 = new BoardSquarePathInfo(); boardSquarePathInfo3.square = boardSquare; boardSquarePathInfo3.next = boardSquarePathInfo4; boardSquarePathInfo4.prev = boardSquarePathInfo3; boardSquarePathInfo4 = boardSquarePathInfo3; } } } return(boardSquarePathInfo1); }