Skip to content

Commit

Permalink
Merge pull request #62 from samsmithnz/feature/reload
Browse files Browse the repository at this point in the history
Added reload functionality
  • Loading branch information
samsmithnz committed May 25, 2021
2 parents 8e3e666 + fe03249 commit 9656939
Show file tree
Hide file tree
Showing 5 changed files with 106 additions and 32 deletions.
1 change: 1 addition & 0 deletions src/Battle.Logic/Characters/Character.cs
Original file line number Diff line number Diff line change
Expand Up @@ -157,5 +157,6 @@ private static bool LocationIsAdjacentToList(Vector3 location, List<Vector3> lis
}
return false;
}

}
}
71 changes: 41 additions & 30 deletions src/Battle.Logic/Encounters/Encounter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -77,48 +77,59 @@ public static EncounterResult AttackCharacterWithAreaOfEffect(Character sourceCh

public static EncounterResult AttackCharacter(Character sourceCharacter, Weapon weapon, Character targetCharacter, string[,] map, Queue<int> diceRolls)
{
int damageDealt = 0;
bool isCriticalHit = false;
List<string> log = new();
log.Add(sourceCharacter.Name + " is attacking with " + weapon.Name + ", targeted on " + targetCharacter.Name.ToString());

if (diceRolls == null || diceRolls.Count == 0)
{
return null;
}
int toHitPercent = EncounterCore.GetChanceToHit(sourceCharacter, weapon, targetCharacter);

//If the number rolled is higher than the chance to hit, the attack was successful!
int randomToHit = diceRolls.Dequeue();
int damageDealt = 0;
bool isCriticalHit = false;
List<string> log = new();
log.Add(sourceCharacter.Name + " is attacking with " + weapon.Name + ", targeted on " + targetCharacter.Name.ToString());

if ((100 - toHitPercent) <= randomToHit)
//Don't attack if the clip is empty
if (weapon.ClipRemaining > 0)
{
log.Add("Hit: Chance to hit: " + toHitPercent.ToString() + ", (dice roll: " + randomToHit.ToString() + ")");
int toHitPercent = EncounterCore.GetChanceToHit(sourceCharacter, weapon, targetCharacter);

EncounterResult tempResult = ProcessCharacterDamageAndExperience(sourceCharacter, weapon, targetCharacter, map, diceRolls, log, false);
sourceCharacter = tempResult.SourceCharacter;
targetCharacter = tempResult.TargetCharacter;
damageDealt = tempResult.DamageDealt;
isCriticalHit = tempResult.IsCriticalHit;
log = tempResult.Log;
}
else
{
log.Add("Missed: Chance to hit: " + toHitPercent.ToString() + ", (dice roll: " + randomToHit.ToString() + ")");
//If the number rolled is higher than the chance to hit, the attack was successful!
int randomToHit = diceRolls.Dequeue();

int xp = Experience.GetExperience(false);
sourceCharacter.Experience += xp;
log.Add(xp.ToString() + " XP added to character " + sourceCharacter.Name + ", for a total of " + sourceCharacter.Experience + " XP");
}
if ((100 - toHitPercent) <= randomToHit)
{
log.Add("Hit: Chance to hit: " + toHitPercent.ToString() + ", (dice roll: " + randomToHit.ToString() + ")");

EncounterResult tempResult = ProcessCharacterDamageAndExperience(sourceCharacter, weapon, targetCharacter, map, diceRolls, log, false);
sourceCharacter = tempResult.SourceCharacter;
targetCharacter = tempResult.TargetCharacter;
damageDealt = tempResult.DamageDealt;
isCriticalHit = tempResult.IsCriticalHit;
log = tempResult.Log;
}
else
{
log.Add("Missed: Chance to hit: " + toHitPercent.ToString() + ", (dice roll: " + randomToHit.ToString() + ")");

//Consume source characters action points
sourceCharacter.ActionPoints = 0;
int xp = Experience.GetExperience(false);
sourceCharacter.Experience += xp;
log.Add(xp.ToString() + " XP added to character " + sourceCharacter.Name + ", for a total of " + sourceCharacter.Experience + " XP");
}

//Check if the character has enough experience to level up
sourceCharacter.LevelUpIsReady = Experience.CheckIfReadyToLevelUp(sourceCharacter.Level, sourceCharacter.Experience);
if (sourceCharacter.LevelUpIsReady == true)
//Consume source characters action points
sourceCharacter.ActionPoints = 0;
//Consume weapon ammo
weapon.ClipRemaining--;

//Check if the character has enough experience to level up
sourceCharacter.LevelUpIsReady = Experience.CheckIfReadyToLevelUp(sourceCharacter.Level, sourceCharacter.Experience);
if (sourceCharacter.LevelUpIsReady == true)
{
log.Add(sourceCharacter.Name + " is ready to level up");
}
}
else
{
log.Add(sourceCharacter.Name + " is ready to level up");
log.Add(weapon.Name + " has no ammo remaining and the attack cannot be completed");
}

EncounterResult result = new()
Expand Down
5 changes: 5 additions & 0 deletions src/Battle.Logic/Items/Weapon.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@ public class Weapon
public int ClipRemaining { get; set; }
public int ActionPointsRequired { get; set; }
public WeaponType Type { get; set; }

public void Reload()
{
ClipRemaining = ClipSize;
}
}

public enum WeaponType
Expand Down
4 changes: 2 additions & 2 deletions src/Battle.Logic/Map/FieldOfView.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@ public static List<Vector3> GetFieldOfView(string[,] map, Vector3 location, int
return MapCore.GetMapArea(map, location, range, true);
}

public static List<Character> GetCharactersInArea(List<Character> characters, string[,] map, Vector3 location, int radius)
public static List<Character> GetCharactersInArea(List<Character> characters, string[,] map, Vector3 location, int range)
{
List<Character> results = new();
List<Vector3> area = MapCore.GetMapArea(map, location, radius, false, true);
List<Vector3> area = MapCore.GetMapArea(map, location, range, false, true);
foreach (Character character in characters)
{
foreach (Vector3 item in area)
Expand Down
57 changes: 57 additions & 0 deletions src/Battle.Tests/Encounters/RegularAttackTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -743,5 +743,62 @@ public void FredAttacksWithRifleJeffBehindHalfCoverAndHunkeredDownInjuriesHimTes
Assert.AreEqual(log, result.LogString);
}


[TestMethod]
public void FredAttacksJeffWithRifleWithNoAmmoTest()
{
//Arrange
Character fred = CharacterPool.CreateFredHero();
Weapon rifle = fred.WeaponEquipped;
rifle.ClipRemaining = 0;
Character jeff = CharacterPool.CreateJeffBaddie();
string[,] map = MapUtility.InitializeMap(10, 10);
Queue<int> diceRolls = new(new List<int> { 80, 100, 0 }); //Chance to hit roll, damage roll, critical chance roll

//Act
EncounterResult result = Encounter.AttackCharacter(fred, rifle, jeff, map, diceRolls);

//Assert
Assert.IsTrue(result != null);
//Assert.AreEqual(7, result.TargetCharacter.Hitpoints);
//Assert.AreEqual(10, result.SourceCharacter.Experience);
string log = @"
Fred is attacking with Rifle, targeted on Jeff
Rifle has no ammo remaining and the attack cannot be completed
";
Assert.AreEqual(log, result.LogString);
}

[TestMethod]
public void FredAttacksJeffWithRifleWithNoAmmoAndReloadsFirstTest()
{
//Arrange
Character fred = CharacterPool.CreateFredHero();
Weapon rifle = fred.WeaponEquipped;
rifle.ClipRemaining = 0;
Character jeff = CharacterPool.CreateJeffBaddie();
string[,] map = MapUtility.InitializeMap(10, 10);
Queue<int> diceRolls = new(new List<int> { 80, 100, 0 }); //Chance to hit roll, damage roll, critical chance roll

//Act
fred.WeaponEquipped.Reload();
EncounterResult result = Encounter.AttackCharacter(fred, rifle, jeff, map, diceRolls);

//Assert
Assert.IsTrue(result != null);
Assert.AreEqual(7, result.TargetCharacter.Hitpoints);
Assert.AreEqual(10, result.SourceCharacter.Experience);
Assert.AreEqual(3, result.SourceCharacter.WeaponEquipped.ClipRemaining);
string log = @"
Fred is attacking with Rifle, targeted on Jeff
Hit: Chance to hit: 80, (dice roll: 80)
Damage range: 3-5, (dice roll: 100)
Critical chance: 70, (dice roll: 0)
5 damage dealt to character Jeff, HP is now 7
10 XP added to character Fred, for a total of 10 XP
";
Assert.AreEqual(log, result.LogString);
}

}
}

0 comments on commit 9656939

Please sign in to comment.