Repository: Monash-FIT3170/2025W2-Beastly-Brawl-Showdown
Pull request #38: Feature/1001.5 abilities monsters consolidation
Author: login: OmarySalem248
Created: 2025-05-29T12:31:49Z | Merged: 2025-05-30T13:26:52Z

# Description

Added abilities into the game to be used by players while battling monsters: now compatibale with main and more streamlined less hardcoded code. 
## Type of change

- [ ] Bug fix (non-breaking change which fixes an issue)
- [x] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
- [ ] This change requires a documentation update

# How Has This Been Tested?

Please describe the tests that you ran to verify your changes. Provide instructions so we can reproduce. Please also list any relevant details for your test configuration

- [ ] End-to-end tests w/ Playwright
- [ ] Unit Tests
- [ ] Integration Tests
- [ ] CI Pipeline
- [x] Manual Testing (please describe if checked):
- [ ] N/A

# Checklist (only check off the applicable):

- [x] My code follows the style guidelines of this project
- [x] I have performed a self-review of my code
- [ ] I have commented my code, particularly in hard-to-understand areas
- [ ] I have made corresponding changes to the documentation
- [ ] My changes generate no new warnings
- [ ] I have added tests that prove my fix is effective or that my feature works
- [ ] New and existing unit tests pass locally with my changes
- [ ] Any dependent changes have been merged and published in downstream modules



Diff:
diff --git a/package-lock.json b/package-lock.json
index f0f73a7b..c770c3d7 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -11,6 +11,7 @@
         "@tailwindcss/vite": "^4.1.6",
         "@types/socket.io": "^3.0.1",
         "@types/socket.io-client": "^1.4.36",
+        "babel-runtime": "^6.26.0",
         "meteor-node-stubs": "^1.2.5",
         "postcss": "^8.5.3",
         "postcss-load-config": "^6.0.1",
@@ -1198,6 +1199,16 @@
         "node": ">= 0.6"
       }
     },
+    "node_modules/babel-runtime": {
+      "version": "6.26.0",
+      "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz",
+      "integrity": "sha512-ITKNuq2wKlW1fJg9sSW52eepoYgZBggvOAHC0u/CYu/qxQ9EVzThCgR69BnSXLHjy2f7SY5zaQ4yt7H9ZVxY2g==",
+      "license": "MIT",
+      "dependencies": {
+        "core-js": "^2.4.0",
+        "regenerator-runtime": "^0.11.0"
+      }
+    },
     "node_modules/base64id": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz",
@@ -1225,6 +1236,14 @@
         "node": ">= 0.6"
       }
     },
+    "node_modules/core-js": {
+      "version": "2.6.12",
+      "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz",
+      "integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==",
+      "deprecated": "core-js@<3.23.3 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Some versions have web compatibility issues. Please, upgrade your dependencies to the actual version of core-js.",
+      "hasInstallScript": true,
+      "license": "MIT"
+    },
     "node_modules/cors": {
       "version": "2.8.5",
       "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz",
@@ -3070,6 +3089,12 @@
         "react": "^18.3.1"
       }
     },
+    "node_modules/regenerator-runtime": {
+      "version": "0.11.1",
+      "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz",
+      "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==",
+      "license": "MIT"
+    },
     "node_modules/rollup": {
       "version": "4.41.1",
       "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.41.1.tgz",
diff --git a/package.json b/package.json
index 82c35e28..510d8a95 100644
--- a/package.json
+++ b/package.json
@@ -13,6 +13,7 @@
     "@tailwindcss/vite": "^4.1.6",
     "@types/socket.io": "^3.0.1",
     "@types/socket.io-client": "^1.4.36",
+    "babel-runtime": "^6.26.0",
     "meteor-node-stubs": "^1.2.5",
     "postcss": "^8.5.3",
     "postcss-load-config": "^6.0.1",
diff --git a/server/src/model/game/action/ability/arcaneShield.ts b/server/src/model/game/action/ability/arcaneShield.ts
index 42428b99..98c92160 100644
--- a/server/src/model/game/action/ability/arcaneShield.ts
+++ b/server/src/model/game/action/ability/arcaneShield.ts
@@ -1,25 +1,39 @@
 import { Action } from "../action";
 import { Player } from "../../player";
 import { ActionIdentifier } from "/types/single/actionState";
+import { AttackAction } from "../attack";
 
 export class ArcaneShieldAbilityAction extends Action {
+  private strike: AttackAction | null = null;
+
   constructor() {
     super(
       ActionIdentifier.ARCANE_SHIELD,
       "Arcane Shield",
-      "Can reroll the d20 once per battle.",
-      Infinity
+      "Use a biased d20, increasing the minimum roll to 10 for your next attack.",
+      1
     );
   }
 
-  public prepare(actingPlayer: Player, affectedPlayer: Player): void {}
+  public prepare(actingPlayer: Player, affectedPlayer: Player): void {
+    this.strike = new AttackAction(actingPlayer.getAttackStat(), 10);
+    this.strike.prepare(actingPlayer,affectedPlayer);
+  }
+
 
   public execute(actingPlayer: Player, affectedPlayer: Player): void {
+    this.incCurrentUse(-1);
+    this.strike?.execute(actingPlayer,affectedPlayer)
+
+    // Log actions
     actingPlayer.addLog(
-      `You did nothing. Unimplemented action ${this.getName()}`
+      `You used ${this.getName()}, increasing the minimum roll to 10 for your next attack.`
     );
     affectedPlayer.addLog(
-      `${actingPlayer.getName()} did nothing. Unimplemented action ${this.getName()}`
+      `${actingPlayer.getName()} used ${this.getName()}, increasing the minimum roll to 10 for their next attack.`
+    );
+    affectedPlayer.addBattleLog(
+      `${actingPlayer.getName()} used ${this.getName()}, increasing the minimum roll to 10 for their next attack.`
     );
   }
 }
diff --git a/server/src/model/game/action/ability/elementalBreath.ts b/server/src/model/game/action/ability/elementalBreath.ts
index 2133925b..b9d5223d 100644
--- a/server/src/model/game/action/ability/elementalBreath.ts
+++ b/server/src/model/game/action/ability/elementalBreath.ts
@@ -3,23 +3,38 @@ import { Player } from "../../player";
 import { ActionIdentifier } from "/types/single/actionState";
 
 export class ElementalBreathAbilityAction extends Action {
+  // Attack that always lands on your opponent, even if they attempt to dodge the attack.
   constructor() {
     super(
       ActionIdentifier.ELEMENTAL_BREATH,
       "Elemental Breath",
-      "Deals damage to opponents in a cone.",
-      Infinity
+      "Deal 5 damage to your opponent. If the opponent tries to dodge in the same turn, deal an additional 5 damage.",
+      1
     );
+    this.setDodgeable(false);
   }
 
   public prepare(actingPlayer: Player, affectedPlayer: Player): void {}
 
   public execute(actingPlayer: Player, affectedPlayer: Player): void {
+    this.incCurrentUse(-1);
+
+    // Deal 10 damage if the opponent is dodging, 5 damage otherwise
+    if (affectedPlayer.getDodgingPosition()){
+      affectedPlayer.incHealth(-10);
+    } else {
+      affectedPlayer.incHealth(-5);
+    }
+
+    // Log the action
     actingPlayer.addLog(
-      `You did nothing. Unimplemented action ${this.getName()}`
+      `You used ${this.getName()}, dealing ${affectedPlayer.getDodgingPosition() ? 10 : 5} damage to ${affectedPlayer.getName()}.`
     );
     affectedPlayer.addLog(
-      `${actingPlayer.getName()} did nothing. Unimplemented action ${this.getName()}`
+      `${actingPlayer.getName()} used ${this.getName()}, dealing ${affectedPlayer.getDodgingPosition() ? 10 : 5} damage to you.`
+    );
+    affectedPlayer.addBattleLog(
+      `${actingPlayer.getName()} used ${this.getName()}, dealing ${affectedPlayer.getDodgingPosition() ? 10 : 5} damage to ${affectedPlayer.getName()}.`
     );
   }
-}
+}
\ No newline at end of file
diff --git a/server/src/model/game/action/ability/feralStrike.ts b/server/src/model/game/action/ability/feralStrike.ts
index 9607cda9..e4c615e3 100644
--- a/server/src/model/game/action/ability/feralStrike.ts
+++ b/server/src/model/game/action/ability/feralStrike.ts
@@ -2,12 +2,13 @@ import { Action } from "../action";
 import { Player } from "../../player";
 import { ActionIdentifier } from "/types/single/actionState";
 
-export class FeralStrikeAbilityPassive extends Action {
+export class FeralStrikeAbilityAction extends Action {
+  // Passive ability that increases critical hit rate by 15%
   constructor() {
     super(
       ActionIdentifier.FERAL_STRIKE,
       "Feral Strike",
-      "Increases your critical hit rate by 15%.",
+      "Increase your critical hit rate by 15%.",
       0 // Passive abilities do not have uses
     );
   }
diff --git a/server/src/model/game/action/ability/fortressStance.ts b/server/src/model/game/action/ability/fortressStance.ts
index edf3a820..7a0b25cb 100644
--- a/server/src/model/game/action/ability/fortressStance.ts
+++ b/server/src/model/game/action/ability/fortressStance.ts
@@ -3,23 +3,35 @@ import { Player } from "../../player";
 import { ActionIdentifier } from "/types/single/actionState";
 
 export class FortressStanceAbilityAction extends Action {
+  // Grants the user bonus AC for 1 round
+  private armourBonus = 10;
+
   constructor() {
     super(
       ActionIdentifier.FORTRESS_STANCE,
       "Fortress Stance",
-      "Increases AC for one round.",
-      Infinity
+      "Increase your AC by 10 for 1 turn.",
+      1
     );
   }
 
   public prepare(actingPlayer: Player, affectedPlayer: Player): void {}
-
+  
   public execute(actingPlayer: Player, affectedPlayer: Player): void {
+    this.incCurrentUse(-1);
+
+    // Increase the AC of the player
+    actingPlayer.incArmourClassStat(this.armourBonus);
+
+    // Add logs
     actingPlayer.addLog(
-      `You did nothing. Unimplemented action ${this.getName()}`
+      `You used ${this.getName()}, gaining ${this.armourBonus} AC for 1 turn.`
     );
     affectedPlayer.addLog(
-      `${actingPlayer.getName()} did nothing. Unimplemented action ${this.getName()}`
+      `${actingPlayer.getName()} used ${this.getName()}, gaining ${this.armourBonus} AC for 1 turn.`
+    );
+    affectedPlayer.addBattleLog(
+      `${actingPlayer.getName()} used ${this.getName()}, gaining ${this.armourBonus} AC for 1 turn.`
     );
   }
-}
+}
\ No newline at end of file
diff --git a/server/src/model/game/action/ability/groundSlam.ts b/server/src/model/game/action/ability/groundSlam.ts
index 14c8eeb1..0c063c87 100644
--- a/server/src/model/game/action/ability/groundSlam.ts
+++ b/server/src/model/game/action/ability/groundSlam.ts
@@ -7,19 +7,31 @@ export class GroundSlamAbilityAction extends Action {
     super(
       ActionIdentifier.GROUND_SLAM,
       "Ground Slam",
-      "Can stun opponents with a powerful stomp.",
-      Infinity
+      "Deal 3 damage and stun your opponent, preventing them from acting for 1 turn.",
+      1
     );
   }
 
-  public prepare(actingPlayer: Player, affectedPlayer: Player): void {}
+  // Clear the opponent's actions
+  public prepare(actingPlayer: Player, affectedPlayer: Player): void {
+    affectedPlayer.clearActions();
+  }
 
   public execute(actingPlayer: Player, affectedPlayer: Player): void {
+    this.incCurrentUse(-1);
+
+    // Deal 3 damage
+    affectedPlayer.incHealth(-3);
+
+    // Add logs
     actingPlayer.addLog(
-      `You did nothing. Unimplemented action ${this.getName()}`
+      `You used ${this.getName()}, dealing 3 damage and stunning ${affectedPlayer.getName()} for 1 turn.`
     );
     affectedPlayer.addLog(
-      `${actingPlayer.getName()} did nothing. Unimplemented action ${this.getName()}`
+      `${actingPlayer.getName()} used ${this.getName()}, dealing 3 damage and stunning you for 1 turn.`
+    );
+    affectedPlayer.addBattleLog(
+      `${actingPlayer.getName()} used ${this.getName()}, dealing 3 damage and stunning ${affectedPlayer.getName()} for 1 turn.`
     );
   }
-}
+}
\ No newline at end of file
diff --git a/server/src/model/game/action/ability/shadowLeap.ts b/server/src/model/game/action/ability/shadowLeap.ts
index ec859fcf..5802c61a 100644
--- a/server/src/model/game/action/ability/shadowLeap.ts
+++ b/server/src/model/game/action/ability/shadowLeap.ts
@@ -1,25 +1,50 @@
 import { Action } from "../action";
 import { Player } from "../../player";
 import { ActionIdentifier } from "/types/single/actionState";
+import { AttackAction } from "../attack";
+import { NullAction } from "../null";
 
 export class ShadowLeapAbilityAction extends Action {
+  // Puts you in an evasive stance, allowing you to dodge an attack once per battle.
   constructor() {
     super(
       ActionIdentifier.SHADOW_LEAP,
       "Shadow Leap",
-      "Can evade an attack once per battle.",
-      Infinity
-    );
+      "Enter an evasive stance, allowing you to dodge an attack in the current turn.",
+      1
+        );
   }
 
-  public prepare(actingPlayer: Player, affectedPlayer: Player): void {}
+  public prepare(actingPlayer: Player, affectedPlayer: Player): void {
+    // Set dodge to true
+    actingPlayer.dodge();
+
+    // Remove 1 use from each of the opponent's actions and remove the action if they can be dodged.
+    affectedPlayer.getActions().forEach((action) => {
+      if (action.getDodgeable()==true){
+        action.incCurrentUse(-1);
+        affectedPlayer.removeAction(action);
+        const actingMessage = `${actingPlayer.getName()} dodged your attack!`;
+        const affectedMessage = `You dodged ${affectedPlayer.getName()}'s attack!`;
+        const battleLogMessage = `${actingPlayer.getName()} dodged ${affectedPlayer.getName()}'s attack!`;
+        affectedPlayer.addAction(new NullAction(actingMessage, affectedMessage, battleLogMessage));
+      }
+    });
+
+  }
 
   public execute(actingPlayer: Player, affectedPlayer: Player): void {
+    this.incCurrentUse(-1);
+
+    // Log the action
     actingPlayer.addLog(
-      `You did nothing. Unimplemented action ${this.getName()}`
+      `You used ${this.getName()}, preparing to dodge an attack.`
     );
     affectedPlayer.addLog(
-      `${actingPlayer.getName()} did nothing. Unimplemented action ${this.getName()}`
+      `${actingPlayer.getName()} uses ${this.getName()}, preparing to dodge an attack.`
+    );
+    affectedPlayer.addBattleLog(
+      `${actingPlayer.getName()} uses ${this.getName()}, preparing to dodge an attack.`
     );
   }
 }
diff --git a/server/src/model/game/action/action.ts b/server/src/model/game/action/action.ts
index efe038f0..f0525356 100644
--- a/server/src/model/game/action/action.ts
+++ b/server/src/model/game/action/action.ts
@@ -8,6 +8,7 @@ export abstract class Action {
 
   private currentUse: number;
   private maxUse: number;
+  private dodgeable: boolean = true;
 
   constructor(
     id: ActionIdentifier,
@@ -22,14 +23,21 @@ export abstract class Action {
     this.maxUse = maxUse;
   }
 
-  protected incCurrentUse(value: number): void {
+  public incCurrentUse(value: number): void {
     this.currentUse += value;
   }
 
   public getCurrentUse(): number {
     return this.currentUse;
   }
-
+  //returns if an action can be dodged 
+  public getDodgeable(): boolean {
+    return this.dodgeable;
+  }
+  //if an action cant be dodged, this function is used to set it apart from the default 
+  protected setDodgeable(value: boolean): void {
+    this.dodgeable = value;
+  }
   public getMaxUse(): number {
     return this.maxUse;
   }
diff --git a/server/src/model/game/action/attack.ts b/server/src/model/game/action/attack.ts
index e48b5a7d..16f240ca 100644
--- a/server/src/model/game/action/attack.ts
+++ b/server/src/model/game/action/attack.ts
@@ -63,15 +63,15 @@ export class AttackAction extends Action {
 
       // Log successful attack
       actingPlayer.addLog(
-        `${isCrit ? "Critical hit! " : ""}You attacked ${affectedPlayer.getName()} and dealt ${this.damageDealt} damage.`
+        `${isCrit ? "Critical hit! " : ""}You attacked ${affectedPlayer.getName()}, dealing ${this.damageDealt} damage.`
       );
 
       affectedPlayer.addLog(
-        `${isCrit ? "Critical hit! " : ""}${actingPlayer.getName()} attacked you and dealt ${this.damageDealt} damage.`
+        `${isCrit ? "Critical hit! " : ""}${actingPlayer.getName()} attacked you, dealing ${this.damageDealt} damage.`
       );
 
       actingPlayer.addBattleLog(
-        `${isCrit ? "Critical hit! " : ""}${actingPlayer.getName()} attacked ${affectedPlayer.getName()} and dealt ${this.damageDealt} damage.`
+        `${isCrit ? "Critical hit! " : ""}${actingPlayer.getName()} attacked ${affectedPlayer.getName()}, dealing ${this.damageDealt} damage.`
       );
       // Increment successful hit for front end
       actingPlayer.incSuccessfulHit(1);
diff --git a/server/src/model/game/action/null.ts b/server/src/model/game/action/null.ts
index e61c16f3..269cdca7 100644
--- a/server/src/model/game/action/null.ts
+++ b/server/src/model/game/action/null.ts
@@ -3,15 +3,22 @@ import { Player } from "../player";
 import { ActionIdentifier } from "/types/single/actionState";
 
 export class NullAction extends Action {
-  constructor() {
+  private actingMessage: string | null;
+  private affectedMessage: string | null;
+  private battleLogMessage: string | null;
+
+  constructor(actingMessage: string | null = null, affectedMessage: string | null = null, battleLogMessage: string | null = null) {
     super(ActionIdentifier.NULL, "Null", "No action", Infinity);
+    this.actingMessage = actingMessage;
+    this.affectedMessage = affectedMessage;
+    this.battleLogMessage = battleLogMessage;
   }
 
   public prepare(actingPlayer: Player, affectedPlayer: Player): void {}
 
   public execute(actingPlayer: Player, affectedPlayer: Player): void {
-    actingPlayer.addLog("You did nothing.");
-    affectedPlayer.addLog(`${actingPlayer.getName()} did nothing.`);
-    actingPlayer.addBattleLog(`${actingPlayer.getName()} did nothing.`);
+    actingPlayer.addLog(`${this.actingMessage ? this.actingMessage + " " : ""}You did nothing.`);
+    affectedPlayer.addLog(`${this.affectedMessage ? this.affectedMessage + " " : ""}${actingPlayer.getName()} did nothing.`);
+    actingPlayer.addBattleLog(`${this.battleLogMessage ? this.battleLogMessage + " " : ""}${actingPlayer.getName()} did nothing.`);
   }
 }
diff --git a/server/src/model/game/archetype/warrior.ts b/server/src/model/game/archetype/warrior.ts
index 926bdd2b..5ab78bdd 100644
--- a/server/src/model/game/archetype/warrior.ts
+++ b/server/src/model/game/archetype/warrior.ts
@@ -1,8 +1,8 @@
 import { Archetype } from "./archetype";
-import { FeralStrikeAbilityPassive } from "../action/ability/feralStrike";
+import { FeralStrikeAbilityAction } from "../action/ability/feralStrike";
 
 export class Warrior extends Archetype {
   constructor() {
-    super("Warrior", new FeralStrikeAbilityPassive(), 25); // Warrior-type monsters have an enhanced crit rate of 25%
+    super("Warrior", new FeralStrikeAbilityAction(), 25); // Warrior-type monsters have an enhanced crit rate of 25%
   }
 }
diff --git a/server/src/model/game/player.ts b/server/src/model/game/player.ts
index 4b2e6547..636575d8 100644
--- a/server/src/model/game/player.ts
+++ b/server/src/model/game/player.ts
@@ -8,7 +8,7 @@ export class Player {
   private monster: Monster | null;
   public currentGameCode: number;
   private score: number = 0;
-
+  private currentlyDodging = false
   private currentHealth: number;
   private currentAttackStat: number;
   private currentArmourClassStat: number;
@@ -33,6 +33,14 @@ export class Player {
   public getSuccessfulHit() {
     return this.successfulHit;
   }
+  //sets the player in a dodging position
+  public dodge(): void{
+    this.currentlyDodging= true
+  }
+  //returns wheather or not the player was dodging 
+  public getDodgingPosition():boolean{
+    return this.currentlyDodging
+  }  
 
   public getSuccessfulBlock() {
     return this.successfulBlock;
@@ -74,6 +82,7 @@ export class Player {
     if (this.monster) {
       this.currentAttackStat = this.monster.getAttackBonus();
       this.currentArmourClassStat = this.monster.getArmourClass();
+      this.dodging = false;
     }
   }
 


Reviews:
user: login: kamlesa
body: Can you add comments to all your code - I want to know your intentions with what you're implementing so I can actually tell it's done right - Abilities can be interpreted differently in the brief so need to know your plan.

Also I think all (?) abilities should be one-time use rather than infinity, can confirm with someone else but they should definitely be limited.

With "dodge" - need to make a distinction between a player "dodging" and an attack being "dodgeable". It's a bit confusing cos the words are basically the same.
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-29T16:59:53Z
user: login: mycapyplace
state: CHANGES_REQUESTED
author_association: COLLABORATOR
submitted_at: 2025-05-29T17:14:45Z
user: login: mycapyplace
body: Please make changes on what Anika and I mentioned, thanks!
state: CHANGES_REQUESTED
author_association: COLLABORATOR
submitted_at: 2025-05-29T17:16:43Z
user: login: dyou0009
body: I've did some testing of the individual abilities and used to logs to verify (as best as I can).

Most of these seem to work on their own in simple situations, but as these others have said, you should document what some of these abilities specifically do. For example, Elemental Breath dealing different damage values (and what these values are) depending on whether the opponent is dodging or not.

I can't tell if Arcane Shield is done or not, but with the way that you are implementing it right now, you might need to structure it differently. Since this is a reroll ability, this should be something that can be activated after an attack (or attacking ability) is selected. So, it doesn't really make sense for it to be its own selectable action among the other three. Ideally, it should be so that after a roll is performed (e.g., by choosing Attack), the user can then perform Arcane Shield to reroll again.

Also, I don't think Feral Strike is working properly, but this might be because critical attacks have not been implemented yet, maybe? (Sorry, I couldn't fully tell from the code, so I might be wrong here.) Either way, when Feral Strike lands, it's still doing only 5 damage.

But overall, great job! Just remember to double check that your abilities are doing what they're supposed to do, but also in different situations as well.
state: DISMISSED
author_association: COLLABORATOR
submitted_at: 2025-05-29T19:21:31Z
user: login: OmarySalem248
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-30T00:09:12Z
user: login: OmarySalem248
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-30T00:09:57Z
user: login: mycapyplace
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-30T07:38:52Z
user: login: OmarySalem248
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-30T07:41:17Z
user: login: OmarySalem248
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-30T07:41:45Z
user: login: mycapyplace
body: Check my comments and make changes please 
state: DISMISSED
author_association: COLLABORATOR
submitted_at: 2025-05-30T07:55:04Z
user: login: OmarySalem248
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-30T07:59:31Z
user: login: kamlesa
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-30T08:01:32Z
user: login: kamlesa
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-30T08:02:37Z
user: login: OmarySalem248
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-30T08:10:20Z
user: login: OmarySalem248
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-30T08:12:04Z
user: login: mycapyplace
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-30T08:26:32Z
user: login: OmarySalem248
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-30T08:30:29Z
user: login: kamlesa
body: thanks for adding the comments 😄 

state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-30T08:33:21Z
user: login: mycapyplace
body: Might merge Tinesia's PR before this one
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-30T13:09:29Z
user: login: devanfedhi
body: I tested on my end, abilities seem to work. Great job @OmarSalem248 and @stonefacedcapy 
state: APPROVED
author_association: COLLABORATOR
submitted_at: 2025-05-30T13:18:12Z
user: login: WillMGRichter
state: APPROVED
author_association: COLLABORATOR
submitted_at: 2025-05-30T13:26:16Z

Review comments:
diff_hunk: @@ -1,25 +1,32 @@
 import { Action } from "../action";
 import { Player } from "../../player";
 import { ActionIdentifier } from "/types/single/actionState";
+import { AttackAction } from "../attack";
 
 export class ArcaneShieldAbilityAction extends Action {
+  private strike = new AttackAction(7,10);
+  private armourBonus = 0
   constructor() {
     super(
       ActionIdentifier.ARCANE_SHIELD,
       "Arcane Shield",
-      "Can reroll the d20 once per battle.",
-      Infinity
+      "Can reroll one d20 roll once per battle",
+      1
     );
   }
 
-  public prepare(actingPlayer: Player, affectedPlayer: Player): void {}
+
+  public prepare(actingPlayer: Player, affectedPlayer: Player): void {
+    this.strike.prepare(actingPlayer,affectedPlayer)
path: server/src/model/game/action/ability/arcaneShield.ts
user: login: kamlesa
body: is this implemented?
created_at: 2025-05-29T16:49:01Z
author_association: COLLABORATOR
diff_hunk: @@ -22,14 +23,19 @@ export abstract class Action {
     this.maxUse = maxUse;
   }
 
-  protected incCurrentUse(value: number): void {
+  public incCurrentUse(value: number): void {
     this.currentUse += value;
   }
 
   public getCurrentUse(): number {
     return this.currentUse;
   }
-
+  public getDodgeable(): boolean {
+    return this.dodgable;
path: server/src/model/game/action/action.ts
user: login: mycapyplace
body: Keep spelling consistent "return this.dodgeable"
created_at: 2025-05-29T16:59:20Z
author_association: COLLABORATOR
path: server/src/model/game/action/ability/feralStrike.ts
user: login: mycapyplace
body: Feral Strike should be a passive. I reckon leave these for now and we can figure it out at a later date.
created_at: 2025-05-29T17:04:36Z
author_association: COLLABORATOR
path: server/src/model/game/action/ability/fortressStance.ts
user: login: mycapyplace
body: Fortress Stance is also a passive. Let's work it out another time
created_at: 2025-05-29T17:04:49Z
author_association: COLLABORATOR
diff_hunk: @@ -1,25 +1,30 @@
 import { Action } from "../action";
 import { Player } from "../../player";
 import { ActionIdentifier } from "/types/single/actionState";
+import { AttackAction } from "../attack";
 
 export class FeralStrikeAbilityAction extends Action {
+  private strike = new AttackAction(7);
path: server/src/model/game/action/ability/feralStrike.ts
user: login: dyou0009
body: Isn't Feral Strike supposed to be dealing addition damage on crits? This is increasing attack bonus by 7 instead, which I don't think should be happening. Attack bonus effectively adds to the dice roll, not increase your actual attack stat. Thus, in the logs, crits are still only dealing 5 damage.
created_at: 2025-05-29T18:59:39Z
author_association: COLLABORATOR
diff_hunk: @@ -1,25 +1,30 @@
 import { Action } from "../action";
 import { Player } from "../../player";
 import { ActionIdentifier } from "/types/single/actionState";
+import { AttackAction } from "../attack";
 
 export class FeralStrikeAbilityAction extends Action {
+  private strike = new AttackAction(7);
path: server/src/model/game/action/ability/feralStrike.ts
user: login: OmarySalem248
body: yea i may be a bit confused on how critical damage works in preexisiting code
created_at: 2025-05-30T00:09:12Z
author_association: COLLABORATOR
path: server/src/model/game/action/ability/fortressStance.ts
user: login: OmarySalem248
body: I dont think it is ?
created_at: 2025-05-30T00:09:57Z
author_association: COLLABORATOR
diff_hunk: @@ -1,25 +1,30 @@
 import { Action } from "../action";
 import { Player } from "../../player";
 import { ActionIdentifier } from "/types/single/actionState";
+import { AttackAction } from "../attack";
 
 export class FeralStrikeAbilityAction extends Action {
+  private strike = new AttackAction(7);
path: server/src/model/game/action/ability/feralStrike.ts
user: login: mycapyplace
body: There is no "critical hit" in the game currently. I think Feral Strike is meant to be a passive that **allows** for the existence of critical hits, only for the Shadowfang Predator (now Pouncing Bandit). In my mind it should just be a 20% chance to add on some additional damage to the enemy
created_at: 2025-05-30T07:38:52Z
author_association: COLLABORATOR
diff_hunk: @@ -1,25 +1,30 @@
 import { Action } from "../action";
 import { Player } from "../../player";
 import { ActionIdentifier } from "/types/single/actionState";
+import { AttackAction } from "../attack";
 
 export class FeralStrikeAbilityAction extends Action {
+  private strike = new AttackAction(7);
path: server/src/model/game/action/ability/feralStrike.ts
user: login: OmarySalem248
body: i understood that but i think critical damge will be incorporated in the future, all the monsters have attack bonuses, so in my code i just increases said bonus
created_at: 2025-05-30T07:41:17Z
author_association: COLLABORATOR
diff_hunk: @@ -1,25 +1,30 @@
 import { Action } from "../action";
 import { Player } from "../../player";
 import { ActionIdentifier } from "/types/single/actionState";
+import { AttackAction } from "../attack";
 
 export class FeralStrikeAbilityAction extends Action {
+  private strike = new AttackAction(7);
path: server/src/model/game/action/ability/feralStrike.ts
user: login: OmarySalem248
body: i committed a modifed version of the ability recently
created_at: 2025-05-30T07:41:45Z
author_association: COLLABORATOR
diff_hunk: @@ -1,25 +1,32 @@
 import { Action } from "../action";
 import { Player } from "../../player";
 import { ActionIdentifier } from "/types/single/actionState";
+import { AttackAction } from "../attack";
 
 export class ArcaneShieldAbilityAction extends Action {
+  private strike = new AttackAction(7,10);
+  private armourBonus = 0
   constructor() {
     super(
       ActionIdentifier.ARCANE_SHIELD,
       "Arcane Shield",
-      "Can reroll the d20 once per battle.",
-      Infinity
+      "Can reroll one d20 roll once per battle",
+      1
     );
   }
 
-  public prepare(actingPlayer: Player, affectedPlayer: Player): void {}
+
+  public prepare(actingPlayer: Player, affectedPlayer: Player): void {
+    this.strike.prepare(actingPlayer,affectedPlayer)
path: server/src/model/game/action/ability/arcaneShield.ts
user: login: mycapyplace
body: Bump on this, what does this do??
created_at: 2025-05-30T07:43:01Z
author_association: COLLABORATOR
diff_hunk: @@ -1,25 +1,33 @@
 import { Action } from "../action";
 import { Player } from "../../player";
 import { ActionIdentifier } from "/types/single/actionState";
+import { AttackAction } from "../attack";
 
 export class ArcaneShieldAbilityAction extends Action {
+  //sets us a biased dice for better chances by preparing and excecuting an attack with a higher minimum dice roll
+  private strike = new AttackAction(7,10);
+
   constructor() {
     super(
       ActionIdentifier.ARCANE_SHIELD,
       "Arcane Shield",
-      "Can reroll the d20 once per battle.",
-      Infinity
+      "Can reroll one d20 roll once per battle",
path: server/src/model/game/action/ability/arcaneShield.ts
user: login: mycapyplace
body: Remember that we changed the implementation, so this description isn't accurate anymore
created_at: 2025-05-30T07:43:40Z
author_association: COLLABORATOR
diff_hunk: @@ -1,25 +1,33 @@
 import { Action } from "../action";
 import { Player } from "../../player";
 import { ActionIdentifier } from "/types/single/actionState";
+import { AttackAction } from "../attack";
 
 export class ArcaneShieldAbilityAction extends Action {
+  //sets us a biased dice for better chances by preparing and excecuting an attack with a higher minimum dice roll
+  private strike = new AttackAction(7,10);
+
   constructor() {
     super(
       ActionIdentifier.ARCANE_SHIELD,
       "Arcane Shield",
-      "Can reroll the d20 once per battle.",
-      Infinity
+      "Can reroll one d20 roll once per battle",
+      1
     );
   }
 
-  public prepare(actingPlayer: Player, affectedPlayer: Player): void {}
+
+  public prepare(actingPlayer: Player, affectedPlayer: Player): void {
+    this.strike.prepare(actingPlayer,affectedPlayer)
+  }
 
   public execute(actingPlayer: Player, affectedPlayer: Player): void {
+    this.strike.execute(actingPlayer,affectedPlayer)
     actingPlayer.addLog(
-      `You did nothing. Unimplemented action ${this.getName()}`
+      `Biased dice has been rerolled for an attack using ${this.getName()}`
     );
     affectedPlayer.addLog(
-      `${actingPlayer.getName()} did nothing. Unimplemented action ${this.getName()}`
+      `${actingPlayer.getName()} rerolled their dice, implemented action ${this.getName()} and obtaining a biased attack`
path: server/src/model/game/action/ability/arcaneShield.ts
user: login: mycapyplace
body: The wording of this is really strange
created_at: 2025-05-30T07:43:54Z
author_association: COLLABORATOR
path: server/src/model/game/action/ability/fortressStance.ts
user: login: mycapyplace
body: I personally think it should be a passive, cause otherwise this ability seems completely garbage to use in battle. Just a glorified defend action
created_at: 2025-05-30T07:46:19Z
author_association: COLLABORATOR
path: server/src/model/game/action/ability/fortressStance.ts
user: login: mycapyplace
body: But for now, it's fine to leave as is. Just thought I'd mention that we should probably discuss and change another time
created_at: 2025-05-30T07:46:45Z
author_association: COLLABORATOR
diff_hunk: @@ -3,23 +3,25 @@ import { Player } from "../../player";
 import { ActionIdentifier } from "/types/single/actionState";
 
 export class FortressStanceAbilityAction extends Action {
+  private armourBonus = 6
   constructor() {
     super(
       ActionIdentifier.FORTRESS_STANCE,
       "Fortress Stance",
       "Increases AC for one round.",
-      Infinity
+      1
     );
   }
 
   public prepare(actingPlayer: Player, affectedPlayer: Player): void {}
-
+  //gives player an armour bomus for the round
path: server/src/model/game/action/ability/fortressStance.ts
user: login: mycapyplace
body: Spelling
created_at: 2025-05-30T07:47:12Z
author_association: COLLABORATOR
diff_hunk: @@ -7,19 +7,23 @@ export class GroundSlamAbilityAction extends Action {
     super(
       ActionIdentifier.GROUND_SLAM,
       "Ground Slam",
-      "Can stun opponents with a powerful stomp.",
-      Infinity
+      "Can stun opponents with a powerful stomp canceling out all abilities and even dealing 3 damage.",
path: server/src/model/game/action/ability/groundSlam.ts
user: login: mycapyplace
body: Spelling and wording. This might be a better description:
"Deals 3 damage and stuns the opponent, preventing them from acting this turn."
created_at: 2025-05-30T07:48:48Z
author_association: COLLABORATOR
diff_hunk: @@ -8,18 +8,27 @@ export class ShadowLeapAbilityAction extends Action {
       ActionIdentifier.SHADOW_LEAP,
       "Shadow Leap",
       "Can evade an attack once per battle.",
-      Infinity
-    );
+      1
+        );
   }
+  //puts the player ina state of "dodgeing" and removes all enemy actions that can be dodged 
path: server/src/model/game/action/ability/shadowLeap.ts
user: login: mycapyplace
body: Spelling
created_at: 2025-05-30T07:49:07Z
author_association: COLLABORATOR
diff_hunk: @@ -8,18 +8,27 @@ export class ShadowLeapAbilityAction extends Action {
       ActionIdentifier.SHADOW_LEAP,
       "Shadow Leap",
       "Can evade an attack once per battle.",
-      Infinity
-    );
+      1
+        );
   }
+  //puts the player ina state of "dodgeing" and removes all enemy actions that can be dodged 
+  public prepare(actingPlayer: Player, affectedPlayer: Player): void {
+    actingPlayer.dodge()
+    affectedPlayer.getActions().forEach((action) => {
+      action.incCurrentUse(-1);
+      if (action.getDodgeable()==true){
+        affectedPlayer. removeAction(action)
+      }
+    });
 
-  public prepare(actingPlayer: Player, affectedPlayer: Player): void {}
+  }
 
   public execute(actingPlayer: Player, affectedPlayer: Player): void {
     actingPlayer.addLog(
-      `You did nothing. Unimplemented action ${this.getName()}`
+      `You dodge using ${this.getName()} hopefully they dont get you`
path: server/src/model/game/action/ability/shadowLeap.ts
user: login: mycapyplace
body: This sentence feels so casual. In games the console/logs should maintain some professionalism/seriousness? in my opinion. Maybe this could be better:
"You anticipate the opponent's action and prepare to dodge."
created_at: 2025-05-30T07:50:56Z
author_association: COLLABORATOR
diff_hunk: @@ -3,23 +3,25 @@ import { Player } from "../../player";
 import { ActionIdentifier } from "/types/single/actionState";
 
 export class FortressStanceAbilityAction extends Action {
+  private armourBonus = 6
   constructor() {
     super(
       ActionIdentifier.FORTRESS_STANCE,
       "Fortress Stance",
       "Increases AC for one round.",
-      Infinity
+      1
     );
   }
 
   public prepare(actingPlayer: Player, affectedPlayer: Player): void {}
-
+  //gives player an armour bomus for the round
   public execute(actingPlayer: Player, affectedPlayer: Player): void {
+    actingPlayer.incArmourClassStat(this.armourBonus)
     actingPlayer.addLog(
-      `You did nothing. Unimplemented action ${this.getName()}`
+      `You have activated ${this.getName()} + 5 AC!!!!`
path: server/src/model/game/action/ability/fortressStance.ts
user: login: mycapyplace
body: Above says armorBonus = 6 though?
created_at: 2025-05-30T07:51:57Z
author_association: COLLABORATOR
diff_hunk: @@ -8,6 +8,7 @@ export abstract class Action {
 
   private currentUse: number;
   private maxUse: number;
+  protected dodgeable: boolean = true;
path: server/src/model/game/action/action.ts
user: login: mycapyplace
body: Can this be made private?
created_at: 2025-05-30T07:53:05Z
author_association: COLLABORATOR
diff_hunk: @@ -22,14 +23,19 @@ export abstract class Action {
     this.maxUse = maxUse;
   }
 
-  protected incCurrentUse(value: number): void {
+  public incCurrentUse(value: number): void {
     this.currentUse += value;
   }
 
   public getCurrentUse(): number {
     return this.currentUse;
   }
-
+  public getDodgeable(): boolean {
path: server/src/model/game/action/action.ts
user: login: mycapyplace
body: Needs comments!
created_at: 2025-05-30T07:53:43Z
author_association: COLLABORATOR
diff_hunk: @@ -8,18 +8,27 @@ export class ShadowLeapAbilityAction extends Action {
       ActionIdentifier.SHADOW_LEAP,
       "Shadow Leap",
       "Can evade an attack once per battle.",
-      Infinity
-    );
+      1
+        );
   }
+  //puts the player ina state of "dodgeing" and removes all enemy actions that can be dodged 
+  public prepare(actingPlayer: Player, affectedPlayer: Player): void {
path: server/src/model/game/action/ability/shadowLeap.ts
user: login: mycapyplace
body: Please explain in more detail
created_at: 2025-05-30T07:54:05Z
author_association: COLLABORATOR
diff_hunk: @@ -32,6 +32,12 @@ export class Player {
   public getSuccessfulHit(){
     return this.successfulHit
   }
+  public dodge(): void{
+    this.currentlydodging= true
path: server/src/model/game/player.ts
user: login: mycapyplace
body: Should have a capital D
created_at: 2025-05-30T07:54:25Z
author_association: COLLABORATOR
path: server/src/model/game/action/ability/fortressStance.ts
user: login: OmarySalem248
body: thats why i made it give more shield i just forgot to update it in the logs lol

created_at: 2025-05-30T07:59:31Z
author_association: COLLABORATOR
diff_hunk: @@ -1,25 +1,30 @@
 import { Action } from "../action";
 import { Player } from "../../player";
 import { ActionIdentifier } from "/types/single/actionState";
+import { AttackAction } from "../attack";
 
 export class FeralStrikeAbilityAction extends Action {
+  private strike = new AttackAction(7);
path: server/src/model/game/action/ability/feralStrike.ts
user: login: kamlesa
body: rather than a chance % - it's if you roll an 18+ on the die
so rolling an 18-20 = 10 (double) damage, rolling anything lower would be normal damage
not sure why it would be done in the future if its a current ability
created_at: 2025-05-30T08:01:32Z
author_association: COLLABORATOR
path: server/src/model/game/action/ability/fortressStance.ts
user: login: kamlesa
body: i think we had some discussion about passives of how we should display the button differently to represent its not clickable but active. so potentially something to properly implement in m3 along with the additional abilities
created_at: 2025-05-30T08:02:37Z
author_association: COLLABORATOR
diff_hunk: @@ -1,25 +1,30 @@
 import { Action } from "../action";
 import { Player } from "../../player";
 import { ActionIdentifier } from "/types/single/actionState";
+import { AttackAction } from "../attack";
 
 export class FeralStrikeAbilityAction extends Action {
+  private strike = new AttackAction(7);
path: server/src/model/game/action/ability/feralStrike.ts
user: login: OmarySalem248
body: where is this incorporated i dont see it in the action class?
created_at: 2025-05-30T08:10:20Z
author_association: COLLABORATOR
path: server/src/model/game/action/ability/fortressStance.ts
user: login: OmarySalem248
body: the abilities i did are not passives, I intentionally left the passives to next milestone. The abilities are all active skills, check the google doc 
created_at: 2025-05-30T08:12:03Z
author_association: COLLABORATOR
diff_hunk: @@ -1,25 +1,33 @@
 import { Action } from "../action";
 import { Player } from "../../player";
 import { ActionIdentifier } from "/types/single/actionState";
+import { AttackAction } from "../attack";
 
 export class ArcaneShieldAbilityAction extends Action {
+  //sets us a biased dice for better chances by preparing and excecuting an attack with a higher minimum dice roll
+  private strike = new AttackAction(7,10);
+
   constructor() {
     super(
       ActionIdentifier.ARCANE_SHIELD,
       "Arcane Shield",
-      "Can reroll the d20 once per battle.",
-      Infinity
+      "Can reroll one d20 roll once per battle",
+      1
     );
   }
 
-  public prepare(actingPlayer: Player, affectedPlayer: Player): void {}
+
+  public prepare(actingPlayer: Player, affectedPlayer: Player): void {
+    this.strike.prepare(actingPlayer,affectedPlayer)
+  }
 
   public execute(actingPlayer: Player, affectedPlayer: Player): void {
+    this.strike.execute(actingPlayer,affectedPlayer)
     actingPlayer.addLog(
-      `You did nothing. Unimplemented action ${this.getName()}`
+      `Biased dice has been rerolled for an attack using ${this.getName()}`
     );
     affectedPlayer.addLog(
-      `${actingPlayer.getName()} did nothing. Unimplemented action ${this.getName()}`
+      `${actingPlayer.getName()} rerolled their dice, implemented action ${this.getName()} and obtaining a biased attack`
path: server/src/model/game/action/ability/arcaneShield.ts
user: login: kamlesa
body: makes more sense to ditch the "reroll" in the sentence, instead consider it an attack with a higher chance of hitting (because the dice is biased). i'm not sure if the log needs to say its a biased attack - could be something just in the descriptor.
created_at: 2025-05-30T08:14:16Z
author_association: COLLABORATOR
diff_hunk: @@ -1,25 +1,30 @@
 import { Action } from "../action";
 import { Player } from "../../player";
 import { ActionIdentifier } from "/types/single/actionState";
+import { AttackAction } from "../attack";
 
 export class FeralStrikeAbilityAction extends Action {
+
   constructor() {
     super(
       ActionIdentifier.FERAL_STRIKE,
       "Feral Strike",
       "Deals extra damage on critical hits.",
-      Infinity
+      1
     );
   }
-
-  public prepare(actingPlayer: Player, affectedPlayer: Player): void {}
+  //just increasing attack bonus of player for the turn
+  public prepare(actingPlayer: Player, affectedPlayer: Player): void {
+    var bonus = actingPlayer.getAttackStat();
+    bonus += 3
+  }
 
   public execute(actingPlayer: Player, affectedPlayer: Player): void {
     actingPlayer.addLog(
-      `You did nothing. Unimplemented action ${this.getName()}`
+      `Critcal damage increase due to ${this.getName()}`
     );
     affectedPlayer.addLog(
-      `${actingPlayer.getName()} did nothing. Unimplemented action ${this.getName()}`
+      `${actingPlayer.getName()} has used ${this.getName()} increasing their critical damage`
path: server/src/model/game/action/ability/feralStrike.ts
user: login: kamlesa
body: since you're implementing an attack boost rather than "critical damage" maybe update the wording
also in the action description
created_at: 2025-05-30T08:16:31Z
author_association: COLLABORATOR
diff_hunk: @@ -3,23 +3,25 @@ import { Player } from "../../player";
 import { ActionIdentifier } from "/types/single/actionState";
 
 export class FortressStanceAbilityAction extends Action {
+  private armourBonus = 6
   constructor() {
     super(
       ActionIdentifier.FORTRESS_STANCE,
       "Fortress Stance",
       "Increases AC for one round.",
-      Infinity
+      1
     );
   }
 
   public prepare(actingPlayer: Player, affectedPlayer: Player): void {}
-
+  //gives player an armour bomus for the round
   public execute(actingPlayer: Player, affectedPlayer: Player): void {
+    actingPlayer.incArmourClassStat(this.armourBonus)
     actingPlayer.addLog(
-      `You did nothing. Unimplemented action ${this.getName()}`
+      `You have activated ${this.getName()} + 5 AC!!!!`
path: server/src/model/game/action/ability/fortressStance.ts
user: login: kamlesa
body: to avoid this problem just write "+ ${this.armourBonus} AC!!!"
created_at: 2025-05-30T08:17:33Z
author_association: COLLABORATOR
diff_hunk: @@ -3,23 +3,25 @@ import { Player } from "../../player";
 import { ActionIdentifier } from "/types/single/actionState";
 
 export class FortressStanceAbilityAction extends Action {
+  private armourBonus = 6
   constructor() {
     super(
       ActionIdentifier.FORTRESS_STANCE,
       "Fortress Stance",
       "Increases AC for one round.",
-      Infinity
+      1
     );
   }
 
   public prepare(actingPlayer: Player, affectedPlayer: Player): void {}
-
+  //gives player an armour bomus for the round
   public execute(actingPlayer: Player, affectedPlayer: Player): void {
+    actingPlayer.incArmourClassStat(this.armourBonus)
     actingPlayer.addLog(
-      `You did nothing. Unimplemented action ${this.getName()}`
+      `You have activated ${this.getName()} + 5 AC!!!!`
     );
     affectedPlayer.addLog(
-      `${actingPlayer.getName()} did nothing. Unimplemented action ${this.getName()}`
+      `${actingPlayer.getName()} has temporarly increased his AC by using ${this.getName()}`
path: server/src/model/game/action/ability/fortressStance.ts
user: login: kamlesa
body: typo 😛 
created_at: 2025-05-30T08:17:53Z
author_association: COLLABORATOR
diff_hunk: @@ -8,7 +8,7 @@ export class Player {
   private monster: Monster | null;
   public currentGameCode?: number;
   private score: number = 0;
-
+  private currentlydodging = false
path: server/src/model/game/player.ts
user: login: kamlesa
body: should this be camel case
created_at: 2025-05-30T08:20:51Z
author_association: COLLABORATOR
diff_hunk: @@ -1,25 +1,33 @@
 import { Action } from "../action";
 import { Player } from "../../player";
 import { ActionIdentifier } from "/types/single/actionState";
+import { AttackAction } from "../attack";
 
 export class ArcaneShieldAbilityAction extends Action {
+  //sets us a biased dice for better chances by preparing and excecuting an attack with a higher minimum dice roll
+  private strike = new AttackAction(7,10);
path: server/src/model/game/action/ability/arcaneShield.ts
user: login: mycapyplace
body: I think 10 should be 20 by the way. Isn't this worse than just attacking normally? Why would you want to only roll up to 10?
created_at: 2025-05-30T08:26:32Z
author_association: COLLABORATOR
diff_hunk: @@ -1,25 +1,33 @@
 import { Action } from "../action";
 import { Player } from "../../player";
 import { ActionIdentifier } from "/types/single/actionState";
+import { AttackAction } from "../attack";
 
 export class ArcaneShieldAbilityAction extends Action {
+  //sets us a biased dice for better chances by preparing and excecuting an attack with a higher minimum dice roll
+  private strike = new AttackAction(7,10);
path: server/src/model/game/action/ability/arcaneShield.ts
user: login: OmarySalem248
body: in an attack action the first parameter is the attack bonus and the second is the minimum dice roll, the rest including maximum are set to defaults
created_at: 2025-05-30T08:30:29Z
author_association: COLLABORATOR

PR comments:
user: login: mycapyplace
created_at: 2025-05-29T17:14:31Z
body: General comments:
- Good work
- Please make sure your spelling is consistent across the files you've changed
- We need comments for us to understand what you're trying to implement
- The ability descriptions could be more specific. If it deals 3 damage and prevents the opponent from acting in the current turn, just mention that. Same goes with things like "deals damage in a cone", it doesn't actually do that so the descriptions should reflect what it really does
author_association: COLLABORATOR
user: login: kamlesa
created_at: 2025-05-30T08:31:58Z
body: ![image](https://github.com/user-attachments/assets/334af77e-fda3-487a-b76a-d32a5e620919)
i think you forgot a part! the host side logs are not set up or something - it logs when i do an attack, or another move unrelated(?) to the abilities, but nothing about the abilities shows up
author_association: COLLABORATOR
user: login: kamlesa
created_at: 2025-05-30T08:33:13Z
body: while testing i notice sometimes the ability usage increments and you can't use it - and sometimes it doesn't and i can use it again. not sure why, i'm guessing might relate to whether its successful or not? which i'm not sure about.. idk if you should be able to keep doing the move till you succeed, depends on general concensus.
not guaranteed that's the source of the bug though, so please check it out.
author_association: COLLABORATOR
user: login: mycapyplace
created_at: 2025-05-30T13:08:19Z
body: ### UPDATE
I have cleaned and fixed up the abilities so they all work as intended. Comments have been added for all abilities, and have logs that reflect on both players' sides and the battle log. Relevant back-end and front-end changes have been made to accommodate for the inclusion of abilities that were not made prior to my update.

Concerns:
- The game on-screen logs always show player 1 first. So it'll say they dodged the attack before preparing to dodge the attack sometimes
- The dice roll stuff is hard coded. So that means using Arcane Shield to give yourself a better d20 doesn't show the dice roll on screen (it works in back-end though)

I don't have time or energy to fix these issues, sorry.

**Please have a look and approve if you are all good with it. Thanks!**
author_association: COLLABORATOR
user: login: WillMGRichter
created_at: 2025-05-30T13:23:16Z
body: Tested and all works on my end
author_association: COLLABORATOR
user: login: WillMGRichter
created_at: 2025-05-30T13:24:25Z
body: i didnt mean to close whoops
author_association: COLLABORATOR