From 02fd39cc492227ffde2684606d4730849a0bd306 Mon Sep 17 00:00:00 2001 From: cpojer Date: Fri, 1 Nov 2024 09:49:59 +0900 Subject: [PATCH] Status effects cannot go negative. GitOrigin-RevId: 791f721e6363322666b42c5a32968b3b8f506b15 --- apollo/__tests__/Skill.test.tsx | 20 ++++++++++++++++++++ athena/lib/getAttackStatusEffect.tsx | 13 +++++++------ athena/lib/getDefenseStatusEffect.tsx | 17 +++++++++-------- 3 files changed, 36 insertions(+), 14 deletions(-) diff --git a/apollo/__tests__/Skill.test.tsx b/apollo/__tests__/Skill.test.tsx index b46528b0..cbc9d37f 100644 --- a/apollo/__tests__/Skill.test.tsx +++ b/apollo/__tests__/Skill.test.tsx @@ -10,9 +10,11 @@ import { Saboteur, SmallTank, Sniper, + SuperTank, Zombie, } from '@deities/athena/info/Unit.tsx'; import { generateUnitName } from '@deities/athena/info/UnitNames.tsx'; +import getDefenseStatusEffect from '@deities/athena/lib/getDefenseStatusEffect.tsx'; import updatePlayer from '@deities/athena/lib/updatePlayer.tsx'; import withModifiers from '@deities/athena/lib/withModifiers.tsx'; import { Charge, MaxCharges } from '@deities/athena/map/Configuration.tsx'; @@ -682,3 +684,21 @@ test('the Charge skill increases charge accumulation', async () => { state1.getPlayer(1).charge, ); }); + +test('defense cannot go negative', async () => { + const skills = new Set([ + Skill.DecreaseUnitCostAttackAndDefenseDecreaseMinor, + Skill.BuyUnitZombieDefenseDecreaseMajor, + Skill.UnlockZombie, + ]); + const mapA = map.copy({ + teams: updatePlayer(map.teams, map.getPlayer(1).copy({ skills })), + units: map.units + .set(fromA, SuperTank.create(1)) + .set(toA, SmallTank.create(2)), + }); + + expect( + getDefenseStatusEffect(mapA, mapA.units.get(fromA)!, null), + ).toBeGreaterThanOrEqual(0); +}); diff --git a/athena/lib/getAttackStatusEffect.tsx b/athena/lib/getAttackStatusEffect.tsx index 51e5c509..c21f3fd9 100644 --- a/athena/lib/getAttackStatusEffect.tsx +++ b/athena/lib/getAttackStatusEffect.tsx @@ -43,12 +43,13 @@ export default function getAttackStatusEffect( ? CrystalAttackEffect : 0; - return ( + return Math.max( + 0, 1 + - crystalEffect + - buildingEffect + - unitEffect + - (unit.isLeader() ? LeaderStatusEffect : 0) + - getSkillAttackStatusEffects(unit, tile, player) + crystalEffect + + buildingEffect + + unitEffect + + (unit.isLeader() ? LeaderStatusEffect : 0) + + getSkillAttackStatusEffects(unit, tile, player), ); } diff --git a/athena/lib/getDefenseStatusEffect.tsx b/athena/lib/getDefenseStatusEffect.tsx index a2c8459c..382018c7 100644 --- a/athena/lib/getDefenseStatusEffect.tsx +++ b/athena/lib/getDefenseStatusEffect.tsx @@ -10,14 +10,15 @@ export default function getDefenseStatusEffect( tile: TileInfo | null, ) { const player = map.getPlayer(entity); - return ( + return Math.max( + 0, 1 + - (isUnit(entity) && entity.isLeader() ? LeaderStatusEffect : 0) + - getSkillDefenseStatusEffects( - entity, - tile, - player.skills, - player.activeSkills, - ) + (isUnit(entity) && entity.isLeader() ? LeaderStatusEffect : 0) + + getSkillDefenseStatusEffects( + entity, + tile, + player.skills, + player.activeSkills, + ), ); }