public static bool DoesQuadIntersectCircleSector(Quad quad, Messages.ScanShoot msg) { Vector2 quadCentre = new Vector2(quad.CentreX, quad.CentreY); double maximumQuadRadius = 1.41421356237 * quad.Radius; Vector2 leftPoint = new Vector2(msg.Radius * Math.Cos(msg.Direction + msg.Width), msg.Radius * Math.Sin(msg.Direction + msg.Width)); Vector2 rightPoint = new Vector2(msg.Radius * Math.Cos(msg.Direction - msg.Width), msg.Radius * Math.Sin(msg.Direction - msg.Width)); return(CircleTriangleIntersection(quadCentre, maximumQuadRadius, msg.Origin, leftPoint, rightPoint) || CircleSegmentIntersection(quadCentre, maximumQuadRadius, msg.Origin, msg.Radius, msg.Direction, msg.Width)); }
/// <summary> /// Handle scanning/shooting on this node: /// - Broadcasts the Struck response for the local node /// - Moves ships to the graveyard as needed /// </summary> private Messages.Struck HandleLocalScanShoot(Messages.ScanShoot msg) { Messages.Struck results = QuadTreeNode.ScanShootLocal(msg); Bus.BroadcastMessage(results); foreach (var ourStruck in results.ShipsInfo) { if (ourStruck.Damage < 0.0) // ship ded { var ourDeadShip = ourStruck.Ship; QuadTreeNode.ShipsByToken.Remove(ourDeadShip.Token); DeadShips.Add(ourDeadShip.Token, ourDeadShip); } } return(results); }
public override Messages.Struck ScanShootLocal(Messages.ScanShoot msg) { bool affected = MathUtils.DoesQuadIntersectCircleSector(this.Bounds, msg); if (affected) { Bus.SendMessage(msg, NodePeer); var struckTask = new MessageWaiter <Messages.Struck>(Bus, NodePeer, (struck) => struck.Originator == msg.Originator).Wait; Messages.Struck results = new Messages.Struck(); if (Task.WaitAll(new Task[] { struckTask }, REPLYTIMEOUT)) { results.OriginatorAreaGain += struckTask.Result.OriginatorAreaGain; results.ShipsInfo.AddRange(struckTask.Result.ShipsInfo); } return(results); } else { return(null); } }
public override Messages.Struck ScanShootLocal(Messages.ScanShoot msg) { Messages.Struck results = new Messages.Struck(); // 1) Search ships locally (but only if affected by the scan) //bool affected = MathUtils.DoesQuadIntersectCircleSector(this.Bounds, msg); bool affected = true; // FIXME - This is here to make sure scans always go through; ideally, though, ships would always be in the SGame node that manages them... if (affected) { Vector2 leftPoint = MathUtils.DirVec(msg.Direction + msg.Width) * msg.Radius; Vector2 rightPoint = MathUtils.DirVec(msg.Direction - msg.Width) * msg.Radius; Console.WriteLine($"Scanning with radius {msg.Radius}, in triangle <{msg.Origin}, {leftPoint}, {rightPoint}>"); var iscanned = ShipsByToken.Values .Where((ship) => ship.Token != msg.Originator && (MathUtils.CircleTriangleIntersection(ship.Pos, ship.Radius(), msg.Origin, leftPoint, rightPoint) || MathUtils.CircleSegmentIntersection(ship.Pos, ship.Radius(), msg.Origin, msg.Radius, msg.Direction, msg.Width)) ) .Select((ship) => new Messages.Struck.ShipInfo() { Ship = ship }); results.ShipsInfo.AddRange(iscanned); if (msg.ScaledShotEnergy > 0.0) { foreach (var struck in results.ShipsInfo) { var ourShip = (LocalSpaceship)struck.Ship; double shipDistance = (ourShip.Pos - msg.Origin).Length(); double damage = MathUtils.ShotDamage(msg.ScaledShotEnergy, msg.Width, shipDistance); double shielding = MathUtils.ShieldingAmount(ourShip, msg.Origin, msg.Direction, msg.Width, msg.Radius); if (shielding > 0.0) { Console.WriteLine($"{ourShip.PublicId} shielded itself for {shielding * 100.0}% of {msg.Originator}'s shot (= {damage * shielding} damage)"); } damage *= (1.0 - shielding); // We have killed a ship, gain it's kill reward, and move struck ship to the graveyard if (ourShip.Area - damage < MINIMUM_AREA) { results.OriginatorAreaGain += ourShip.KillReward; struck.Damage = -damage; } else // Struck ship survived - note that it's in combat { if (ourShip.LastUpdate - ourShip.LastCombat > LocalSpaceship.COMBAT_COOLDOWN) { // Reset kill reward when hit ship was not in combat ourShip.KillReward = ourShip.Area; } ourShip.LastCombat = ourShip.LastUpdate; ourShip.Area -= damage; struck.Damage = damage; } } } } return(results); }
/// <summary> /// Returns a (area gain for shooter, list of struck ships) pair. /// </summary> public abstract Messages.Struck ScanShootLocal(Messages.ScanShoot msg);
public override Messages.Struck ScanShootLocal(Messages.ScanShoot msg) { return(new Messages.Struck()); }
/// <summary> /// Called when a node sends a ScanShoot request; broadcasts the response from this node. /// </summary> private void OnScanShootReceived(NetPeer arbiterPeer, Messages.ScanShoot msg) { HandleLocalScanShoot(msg); }