void BuildChangedValues() { if (PositionChanged || RotationChanged) { BuildPoints(); BuildBounds(); //Reset this value so we're not permanently considered colliding against wall this.ImmovableCollisionDirection = Vector2d.zero; } if (PositionChanged || this.HeightPosChanged) { PositionChangedBuffer = true; PositionChanged = false; this._settingVisualsCounter = SETTING_VISUALS_COUNT; this.HeightPosChanged = false; } else { PositionChangedBuffer = false; } if (RotationChanged) { _rotation.Normalize(); RotationChangedBuffer = true; RotationChanged = false; this._settingVisualsCounter = SETTING_VISUALS_COUNT; } else { RotationChangedBuffer = false; } }
private void ApplyCone(Vector3d center3d, Vector2d forward, long radius, long angle) { Vector2d center = center3d.ToVector2d(); long fastRange = radius * radius; Scan(center, radius); for (int i = 0; i < ScanOutput.Count; i++) { RTSAgent agent = ScanOutput [i]; Vector2d agentPos = agent.Body._position; Vector2d difference = agentPos - center; if (difference.FastMagnitude() > fastRange) { continue; } if (forward.Dot(difference) < 0) { continue; } difference.Normalize(); long cross = forward.Cross(difference).Abs(); if (cross > angle) { continue; } HitAgent(agent); } }
public static void PrepareAxisCheck(Vector2d p1, Vector2d p2, bool calculateIntersectionPoints = true) { cacheP1 = p1; cacheP2 = p2; cacheAxis = p2 - p1; cacheAxis.Normalize(); cacheAxisNormal = cacheAxis.rotatedLeft; axisMin = p1.Dot(cacheAxis.x, cacheAxis.y); axisMax = p2.Dot(cacheAxis.x, cacheAxis.y); cacheProj = cacheP1.Dot(cacheAxis.x, cacheAxis.y); cacheProjPerp = cacheP1.Dot(cacheAxisNormal.x, cacheAxisNormal.y); perpVector = cacheAxisNormal * cacheProjPerp; calculateIntersections = calculateIntersectionPoints; }
void CheckAutoturn() { if (isColliding) { isColliding = false; //autoturn direction will be culmination of positional changes if (targetReached == true && Agent.IsCasting == false && !(Agent.Body.Immovable || Agent.Body.IsTrigger)) { Vector2d delta = this.Agent.Body._position - this.Agent.Body.LastPosition; if (delta.FastMagnitude() > collisionTurnThreshold) { delta.Normalize(); this.StartTurnDirection(delta); } } } }
public void BuildPoints() { if (Shape == ColliderType.Polygon) { int VertLength = Vertices.Length; if (RotationChanged) { for (int i = 0; i < VertLength; i++) { RotatedPoints[i] = Vertices[i]; RotatedPoints[i].Rotate(_rotation.x, _rotation.y); } for (int i = VertLength - 1; i >= 0; i--) { int nextIndex = i + 1 < VertLength ? i + 1 : 0; Vector2d point = RotatedPoints[nextIndex]; point.Subtract(ref RotatedPoints[i]); point.Normalize(); Edges[i] = point; point.RotateRight(); EdgeNorms[i] = point; } if (!OutMoreThanSet) { OutMoreThanSet = true; long dot = Edges[0].Cross(Edges[1]); this.OutMoreThan = dot < 0; } } for (int i = 0; i < VertLength; i++) { RealPoints[i].x = RotatedPoints[i].x + _position.x; RealPoints[i].y = RotatedPoints[i].y + _position.y; } } }
public void StartTurnVector(Vector2d targetVector) { targetVector.Normalize(); StartTurnDirection(targetVector); }
void BehaveWithTarget() { if (Target.IsActive == false || Target.SpawnVersion != targetVersion || (this.TargetAllegiance & Agent.GetAllegiance(Target)) == 0) { //Target's lifecycle has ended StopEngage(); BehaveWithNoTarget(); return; } if (!IsWindingUp) { Vector2d targetDirection = Target.Body._position - cachedBody._position; long fastMag = targetDirection.FastMagnitude(); //TODO: Optimize this instead of recalculating magnitude multiple times if (CheckRange()) { if (!inRange) { if (CanMove) { cachedMove.StopMove(); } inRange = true; } Agent.SetState(EngagingAnimState); long mag; targetDirection.Normalize(out mag); bool withinTurn = TrackAttackAngle == false || (fastMag != 0 && cachedBody.Forward.Dot(targetDirection.x, targetDirection.y) > 0 && cachedBody.Forward.Cross(targetDirection.x, targetDirection.y).Abs() <= AttackAngle); bool needTurn = mag != 0 && !withinTurn; if (needTurn) { if (CanTurn) { cachedTurn.StartTurnDirection(targetDirection); } } else { if (attackCount >= AttackInterval) { StartWindup(); } } } else { if (CanMove) { cachedMove.PauseAutoStop(); cachedMove.PauseCollisionStop(); if (cachedMove.IsMoving == false) { cachedMove.StartMove(Target.Body._position); cachedBody.Priority = basePriority; } else { if (inRange) { cachedMove.Destination = Target.Body.Position; } else { if (repathTimer.AdvanceFrame()) { if (Target.Body.PositionChangedBuffer && Target.Body.Position.FastDistance(cachedMove.Destination.x, cachedMove.Destination.y) >= (repathDistance * repathDistance)) { cachedMove.StartMove(Target.Body._position); //So units don't sync up and path on the same frame repathTimer.AdvanceFrames(repathRandom); } } } } } if (IsAttackMoving || isFocused == false) { searchCount -= 1; if (searchCount <= 0) { searchCount = SearchRate; if (ScanAndEngage()) { } else { } } } if (inRange == true) { inRange = false; } } } if (IsWindingUp) { //TODO: Do we need AgentConditional checks here? windupCount += LockstepManager.DeltaTime; if (CanTurn) { Vector2d targetVector = Target.Body._position - cachedBody._position; cachedTurn.StartTurnVector(targetVector); } if (windupCount >= Windup) { windupCount = 0; Fire(); while (this.attackCount >= AttackInterval) { //resetting back down after attack is fired this.attackCount -= (this.AttackInterval); } this.attackCount += Windup; IsWindingUp = false; } } else { windupCount = 0; } if (CanMove && inRange) { cachedMove.PauseAutoStop(); cachedMove.PauseCollisionStop(); } }
private void BehaveWithTarget() { if (CurrentProject && (CurrentProject.IsActive == false || !CurrentProject.GetAbility <Structure>().NeedsConstruction)) { //Target's lifecycle has ended StopConstruction(); } else { Vector2d targetDirection = CurrentProject.Body._position - CachedBody._position; long fastMag = targetDirection.FastMagnitude(); if (!IsWindingUp) { if (CheckRange()) { IsBuildMoving = false; if (!inRange) { cachedMove.StopMove(); inRange = true; } Agent.Animator.SetState(ConstructingAnimState); if (!CurrentProject.GetAbility <Structure>().ConstructionStarted) { CurrentProject.GetAbility <Structure>().ConstructionStarted = true; // Restore material ConstructionHandler.RestoreMaterial(CurrentProject.gameObject); } long mag; targetDirection.Normalize(out mag); bool withinTurn = cachedAttack.TrackAttackAngle == false || (fastMag != 0 && CachedBody.Forward.Dot(targetDirection.x, targetDirection.y) > 0 && CachedBody.Forward.Cross(targetDirection.x, targetDirection.y).Abs() <= cachedAttack.AttackAngle); bool needTurn = mag != 0 && !withinTurn; if (needTurn) { cachedTurn.StartTurnDirection(targetDirection); } else { if (constructCount >= _constructInterval) { StartWindup(); } } } else { cachedMove.PauseAutoStop(); cachedMove.PauseCollisionStop(); if (cachedMove.IsMoving == false) { cachedMove.StartMove(CurrentProject.Body._position); CachedBody.Priority = basePriority; } else { if (inRange) { cachedMove.Destination = CurrentProject.Body.Position; } else { if (repathTimer.AdvanceFrame()) { if (CurrentProject.Body.PositionChangedBuffer && CurrentProject.Body.Position.FastDistance(cachedMove.Destination.x, cachedMove.Destination.y) >= (repathDistance * repathDistance)) { cachedMove.StartMove(CurrentProject.Body._position); //So units don't sync up and path on the same frame repathTimer.AdvanceFrames(repathRandom); } } } } if (inRange == true) { inRange = false; } } } if (IsWindingUp) { //TODO: Do we need AgentConditional checks here? windupCount += LockstepManager.DeltaTime; if (windupCount >= Windup) { windupCount = 0; Build(); while (this.constructCount >= _constructInterval) { //resetting back down after attack is fired this.constructCount -= (this._constructInterval); } this.constructCount += Windup; IsWindingUp = false; } } else { windupCount = 0; } if (inRange) { cachedMove.PauseAutoStop(); cachedMove.PauseCollisionStop(); } } }
private void DistributeCircle_Box(LSBody box, LSBody circle) { xMore = circle._position.x > box._position.x; yMore = circle._position.y > box._position.y; if (xMore) { PenetrationX = (circle.XMin - box.XMax); } else { PenetrationX = (circle.XMax - box.XMin); } if (yMore) { PenetrationY = (circle.YMin - box.YMax); } else { PenetrationY = (circle.YMax - box.YMin); } //PenetrationX = PenetrationX + circle.Velocity.x; //PenetrationY = PenetrationY + circle.Velocity.y; xAbs = PenetrationX < 0 ? -PenetrationX : PenetrationX; yAbs = PenetrationY < 0 ? -PenetrationY : PenetrationY; if ((xAbs <= circle.Radius && yAbs <= circle.Radius)) { Vector2d corner; corner.x = xMore ? box.Position.x + box.HalfWidth : box.Position.x - box.HalfWidth; corner.y = yMore ? box.Position.y + box.HalfLength : box.Position.y - box.HalfLength; Vector2d dir = circle.Position - corner; dir.Normalize(); circle.Position = corner + dir * circle.Radius; } else { if (xAbs > yAbs) { PenetrationX = 0; //if (yAbs < circle.Radius) PenetrationY = PenetrationY * yAbs / circle.Radius; if (PenetrationY > 0 == yMore) { PenetrationY = -PenetrationY; } } else { PenetrationY = 0; //if (xAbs < circle.Radius) PenetrationX = PenetrationX * xAbs / circle.Radius; if (PenetrationX > 0 == xMore) { PenetrationX = -PenetrationX; } } //Resolving circle._position.x -= PenetrationX; circle._position.y -= PenetrationY; } circle.PositionChanged = true; circle.BuildBounds(); }
protected override void OnSimulate() { if (!CanMove) { return; } //TODO: Organize/split this function if (IsMoving) { if (CanPathfind) { if (DoPathfind) { DoPathfind = false; if (viableDestination) { if (Pathfinder.GetStartNode(cachedBody.Position, out currentNode)) { if (currentNode.DoesEqual(this.destinationNode)) { if (this.RepathTries >= 1) { this.Arrive(); } } else { if (straightPath) { if (Pathfinder.NeedsPath(currentNode, destinationNode, this.GridSize)) { if (Pathfinder.FindPath(Destination, currentNode, destinationNode, myPath, GridSize, GetNodeHash(destinationNode))) { hasPath = true; pathIndex = 0; } else { if (IsFormationMoving) { StartMove(MyMovementGroup.Destination); IsFormationMoving = false; } } straightPath = false; } else { } } else { if (Pathfinder.NeedsPath(currentNode, destinationNode, this.GridSize)) { if (Pathfinder.FindPath(Destination, currentNode, destinationNode, myPath, GridSize, GetNodeHash(destinationNode))) { hasPath = true; pathIndex = 0; } else { if (IsFormationMoving) { StartMove(MyMovementGroup.Destination); IsFormationMoving = false; } } } else { straightPath = true; } } } } else { } } else { hasPath = false; if (IsFormationMoving) { StartMove(MyMovementGroup.Destination); IsFormationMoving = false; } } } else { } if (straightPath) { targetPos = Destination; } else if (hasPath) { if (pathIndex >= myPath.Count) { targetPos = this.Destination; } else { targetPos = myPath[pathIndex]; } } else { targetPos = Destination; } } else { targetPos = Destination; } movementDirection = targetPos - cachedBody._position; movementDirection.Normalize(out distance); if (targetPos.x != lastTargetPos.x || targetPos.y != lastTargetPos.y) { lastTargetPos = targetPos; targetDirection = movementDirection; } bool movingToWaypoint = (this.hasPath && this.pathIndex < myPath.Count - 1); long stuckThreshold = timescaledAcceleration / LockstepManager.FrameRate; long slowDistance = cachedBody.VelocityMagnitude.Div(timescaledDecceleration); if (distance > slowDistance || movingToWaypoint) { desiredVelocity = (movementDirection); if (CanTurn) { cachedTurn.StartTurnDirection(movementDirection); } } else { if (distance < FixedMath.Mul(closingDistance, StopMultiplier)) { Arrive(); //TODO: Don't skip this frame of slowing down return; } if (distance > closingDistance) { if (CanTurn) { cachedTurn.StartTurnDirection(movementDirection); } } if (distance <= slowDistance) { long closingSpeed = distance.Div(slowDistance); if (CanTurn) { cachedTurn.StartTurnDirection(movementDirection); } desiredVelocity = movementDirection * closingSpeed; decellerating = true; //Reduce occurence of units preventing other units from reaching destination stuckThreshold *= 4; } } //If unit has not moved stuckThreshold in a frame, it's stuck StuckTime++; if (GetCanAutoStop()) { if (Agent.Body.Position.FastDistance(AveragePosition) <= (stuckThreshold * stuckThreshold)) { if (StuckTime > StuckTimeThreshold) { if (movingToWaypoint) { this.pathIndex++; } else { if (RepathTries < StuckRepathTries) { DoPathfind = true; RepathTries++; } else { RepathTries = 0; this.Arrive(); } } StuckTime = 0; } } else { if (StuckTime > 0) { StuckTime -= 1; } RepathTries = 0; } } if (movingToWaypoint) { if ( ( this.pathIndex >= 0 && distance < closingDistance && (movementDirection).Dot(waypointDirection) < 0 ) || distance < FixedMath.Mul(closingDistance, FixedMath.Half)) { this.pathIndex++; } } desiredVelocity *= Speed; cachedBody._velocity += GetAdjustVector(desiredVelocity); cachedBody.VelocityChanged = true; } else { decellerating = true; //Slowin' down if (cachedBody.VelocityMagnitude > 0) { cachedBody.Velocity += GetAdjustVector(Vector2d.zero); } StoppedTime++; } decellerating = false; AutoStopPauser--; CollisionStopPauser--; StopPauseLooker--; AveragePosition = AveragePosition.Lerped(Agent.Body.Position, FixedMath.One / 2); }
void BehaveWithStorage() { resourceStorage = ClosestResourceStore(); if (!resourceStorage) { // can't find clostest resource store // send command to stop harvesting... StopHarvesting(true); } else { if (!IsWindingUp) { Vector2d targetDirection = resourceStorage.Body._position - CachedBody._position; long fastMag = targetDirection.FastMagnitude(); if (CheckRange(resourceStorage.Body)) { if (!inRange) { cachedMove.StopMove(); inRange = true; } Agent.Animator.SetIdleState(IdlingAnimState); //if (audioElement != null && Time.timeScale > 0) //{ // audioElement.Play(emptyHarvestSound); //} long mag; targetDirection.Normalize(out mag); bool withinTurn = cachedAttack.TrackAttackAngle == false || (fastMag != 0 && CachedBody.Forward.Dot(targetDirection.x, targetDirection.y) > 0 && CachedBody.Forward.Cross(targetDirection.x, targetDirection.y).Abs() <= cachedAttack.AttackAngle); bool needTurn = mag != 0 && !withinTurn; if (needTurn) { cachedTurn.StartTurnDirection(targetDirection); } else { if (harvestCount >= _harvestInterval) { StartWindup(); } } } else { cachedMove.PauseAutoStop(); cachedMove.PauseCollisionStop(); if (cachedMove.IsMoving == false) { cachedMove.StartMove(resourceStorage.Body._position); CachedBody.Priority = basePriority; } else { if (inRange) { cachedMove.Destination = resourceStorage.Body.Position; } else { if (repathTimer.AdvanceFrame()) { if (resourceStorage.Body.PositionChangedBuffer && resourceStorage.Body.Position.FastDistance(cachedMove.Destination.x, cachedMove.Destination.y) >= (repathDistance * repathDistance)) { cachedMove.StartMove(resourceStorage.Body._position); //So units don't sync up and path on the same frame repathTimer.AdvanceFrames(repathRandom); } } } } if (inRange == true) { inRange = false; } } } if (IsWindingUp) { //TODO: Do we need AgentConditional checks here? windupCount += LockstepManager.DeltaTime; if (windupCount >= Windup) { windupCount = 0; Deposit(); while (this.harvestCount >= _harvestInterval) { //resetting back down after attack is fired this.harvestCount -= (this._harvestInterval); } this.harvestCount += Windup; IsWindingUp = false; } } else { windupCount = 0; } if (inRange) { cachedMove.PauseAutoStop(); cachedMove.PauseCollisionStop(); } } }
void BehaveWithResource() { if (!resourceTarget || resourceTarget.IsActive == false || resourceTarget.GetAbility <ResourceDeposit>().IsEmpty()) { //Target's lifecycle has ended StopHarvesting(); } else { SetAnimState(); if (!IsWindingUp) { Vector2d targetDirection = resourceTarget.Body._position - CachedBody._position; long fastMag = targetDirection.FastMagnitude(); if (CheckRange(resourceTarget.Body)) { IsHarvestMoving = false; if (!inRange) { cachedMove.StopMove(); inRange = true; } Agent.Animator.SetState(HarvestingAnimState); long mag; targetDirection.Normalize(out mag); bool withinTurn = cachedAttack.TrackAttackAngle == false || (fastMag != 0 && CachedBody.Forward.Dot(targetDirection.x, targetDirection.y) > 0 && CachedBody.Forward.Cross(targetDirection.x, targetDirection.y).Abs() <= cachedAttack.AttackAngle); bool needTurn = mag != 0 && !withinTurn; if (needTurn) { cachedTurn.StartTurnDirection(targetDirection); } else { if (harvestCount >= _harvestInterval) { StartWindup(); } } } else { cachedMove.PauseAutoStop(); cachedMove.PauseCollisionStop(); if (cachedMove.IsMoving == false) { cachedMove.StartMove(resourceTarget.Body._position); CachedBody.Priority = basePriority; } else { if (inRange) { cachedMove.Destination = resourceTarget.Body.Position; } else { if (repathTimer.AdvanceFrame()) { if (resourceTarget.Body.PositionChangedBuffer && resourceTarget.Body.Position.FastDistance(cachedMove.Destination.x, cachedMove.Destination.y) >= (repathDistance * repathDistance)) { cachedMove.StartMove(resourceTarget.Body._position); //So units don't sync up and path on the same frame repathTimer.AdvanceFrames(repathRandom); } } } } if (inRange == true) { inRange = false; } } } if (IsWindingUp) { //TODO: Do we need AgentConditional checks here? windupCount += LockstepManager.DeltaTime; if (windupCount >= Windup) { windupCount = 0; // begin collecting resources Collect(); while (this.harvestCount >= _harvestInterval) { //resetting back down after attack is fired this.harvestCount -= (this._harvestInterval); } this.harvestCount += Windup; IsWindingUp = false; } } else { windupCount = 0; } if (inRange) { cachedMove.PauseAutoStop(); cachedMove.PauseCollisionStop(); } } }