private void UseWeapon(FireableWeapon weapon, IFireableWeaponModel model) { _player.Inventory.ForceSnapshot(); var result = _weaponController.FireWeapon(_player, weapon); bool wasFired = false; switch (result) { case FireableWeaponController.FireResult.OutOfAmmo: Log.Info("Out of Ammo"); _weaponController.Reload(_player.Inventory, weapon); Log.Info("Reloaded"); break; case FireableWeaponController.FireResult.Missed: Log.Info("Fired, but missed"); wasFired = true; break; case FireableWeaponController.FireResult.Hit: Log.Info("Fired and hit"); wasFired = true; break; default: throw new ArgumentOutOfRangeException(); } if (wasFired && model != null) { model.TransitionToState(FireableWeaponState.Fired); } }
/// <summary> Have the actor fire their primary weapon. </summary> /// <param name="player"> The actor who should fire their weapon. </param> /// <param name="weapon"> The weapon that should be fired. </param> /// <returns> The result of firing the weapon </returns> public FireResult FireWeapon(IPlayer player, FireableWeapon weapon) { if (weapon.ShotsRemaining == 0) { return(FireResult.OutOfAmmo); } var result = FireResult.Missed; var stats = weapon.Stats; var right = player.Transform.right; var up = player.Transform.up; for (int i = 0; i < stats.NumberOfPellets; i++) { var ray = player.Transform.ToRay(); if (stats.Spread > 0) { var offset = right * _randomNumberGenerator.NextFloat(-stats.Spread, stats.Spread) + up * _randomNumberGenerator.NextFloat(-stats.Spread, stats.Spread); ray.direction += offset; } float distance; var hitObject = _raycastService.Raycast <IDestroyable>(ray, stats.MaxDistance, out distance); Debugging.Drawing.Draw(ray, distance); if (hitObject != null) { float damage = weapon.Stats.CalculateDamage(distance); Log.InfoFormat("Hit {0} with {1}. Damage: {2}", hitObject, weapon, damage); Damage(hitObject, (int)damage); result = FireResult.Hit; } } weapon.ShotsRemaining--; return(result); }
/// <summary> Reloads a weapon from inventory. </summary> /// <param name="inventory"> The inventory to reload the weapon with. </param> /// <param name="weapon"> The weapon that should be reloaded. </param> /// <returns> true if it succeeds, false if it fails. </returns> public ReloadResult Reload(StorageContainer inventory, FireableWeapon weapon) { var countController = new InventoryCountController(inventory); if (weapon.ShotsRemaining == weapon.Stats.ClipSize) { return(ReloadResult.ClipIsAlreadyFilled); } int initialCount = weapon.ShotsRemaining; while (weapon.ShotsRemaining < weapon.Stats.ClipSize) { var ammoCursor = countController.GetAmmoCursor(weapon.Stats.AmmoType); var ammoStack = ammoCursor.Stack; if (ammoStack.IsEmpty) { break; } inventory.Decrement(ammoCursor); weapon.ShotsRemaining++; } // we didn't add any if (weapon.ShotsRemaining == initialCount) { return(ReloadResult.OutOfAmmo); } else if (weapon.ShotsRemaining == weapon.Stats.ClipSize) { return(ReloadResult.ClipHasBeenFilled); } else { return(ReloadResult.AddedSomeAndNowOutOfAmmo); } }
/// <summary> Gets the display count for fireable weapons. </summary> private int GetDisplayFor(FireableWeapon weapon) { return(weapon.ShotsRemaining); }