private void MoveMissile(MissileInfo missile, float timelapseSeconds) { bool collision; Move( missile.X, missile.Y, missile.Distance, missile.Speed, missile.Heading, missile.Range, timelapseSeconds, out var missileX, out var missileY, out var missileDistance, out collision ); missile.X = missileX; missile.Y = missileY; missile.Distance = missileDistance; if (collision) { missile.Status = MissileStatus.ExplodingDirect; missile.Speed = 0.0f; } }
private void ApplyBotAction(BotInfo bot, GetActionResponse action) { var now = _provider.UtcNow; var secondsSinceUpdate = (float)(now - bot.LastStatusUpdate).TotalSeconds; bot.LastStatusUpdate = now; // reduce reload time if any is active if (bot.ReloadCoolDown > 0) { bot.ReloadCoolDown = MathF.Max(0.0f, bot.ReloadCoolDown - secondsSinceUpdate); } // check if any actions need to be applied if (action is null) { // bot didn't respond with an action; consider it dead bot.Status = BotStatus.Dead; bot.TimeOfDeathGameTurn = GameSession.CurrentGameTurn; AddMessage($"{bot.Name} (R{bot.Index}) was disqualified by lack of action"); return; } // update bot state bot.InternalState = action.BotState; // update speed and heading bot.TargetSpeed = GameMath.MinMax(0.0f, action.Speed ?? bot.TargetSpeed, bot.MaxSpeed); bot.TargetHeading = GameMath.NormalizeAngle(action.Heading ?? bot.TargetHeading); // fire missile if requested and possible if ((action.FireMissileHeading.HasValue || action.FireMissileDistance.HasValue) && (bot.ReloadCoolDown == 0.0f)) { // update bot state ++bot.TotalMissileFiredCount; bot.ReloadCoolDown = bot.MissileReloadCooldown; // add missile var missile = new MissileInfo { Id = $"{bot.Id}:M{bot.TotalMissileFiredCount}", BotId = bot.Id, Status = MissileStatus.Flying, X = bot.X, Y = bot.Y, Speed = bot.MissileVelocity, Heading = GameMath.NormalizeAngle(action.FireMissileHeading ?? bot.Heading), Range = GameMath.MinMax(0.0f, action.FireMissileDistance ?? bot.MissileRange, bot.MissileRange), DirectHitDamageBonus = bot.MissileDirectHitDamageBonus, NearHitDamageBonus = bot.MissileNearHitDamageBonus, FarHitDamageBonus = bot.MissileFarHitDamageBonus }; GameSession.Missiles.Add(missile); } }
private void AssessMissileDamage(MissileInfo missile) { FindBotsByDistance(missile.X, missile.Y, (bot, distance) => { // compute damage dealt by missile float damage = 0.0f; string damageType = null; switch (missile.Status) { case MissileStatus.ExplodingDirect: if (distance <= GameSession.DirectHitRange) { damage = bot.DirectHitDamage + missile.DirectHitDamageBonus; damageType = "direct"; } break; case MissileStatus.ExplodingNear: if (distance <= GameSession.NearHitRange) { damage = bot.NearHitDamage + missile.NearHitDamageBonus; damageType = "near"; } break; case MissileStatus.ExplodingFar: if (distance <= GameSession.FarHitRange) { damage = bot.FarHitDamage + missile.FarHitDamageBonus; damageType = "far"; } break; } // check if any damage was dealt if (damage == 0.0f) { // stop enumerating more bots since they will be further away return(false); } // record damage dealt var from = GameSession.Bots.FirstOrDefault(fromBot => fromBot.Id == missile.BotId); if (from != null) { from.TotalDamageDealt += damage; ++from.TotalMissileHitCount; // check if bot was killed if (Damage(bot, damage)) { ++from.TotalKills; // check if bot inflicted damage to itself if (bot.Id == from.Id) { AddMessage($"{bot.Name} (R{bot.Index}) killed itself"); } else { AddMessage($"{bot.Name} (R{bot.Index}) was killed by {from.Name} (R{from.Index})"); } } else { // check if bot inflicted damage to itself if (bot.Id == from.Id) { AddMessage($"{bot.Name} (R{bot.Index}) caused {damage:N0} {damageType} damage to itself"); } else { AddMessage($"{bot.Name} (R{bot.Index}) received {damage:N0} {damageType} damage from {from.Name} (R{from.Index})"); } } } return(true); }); }