Skip to content

Commit

Permalink
Add "Sabotage" skill.
Browse files Browse the repository at this point in the history
GitOrigin-RevId: 5c978a7dec6a57138a46f75d94a60289c8669b2e
  • Loading branch information
cpojer committed Aug 2, 2024
1 parent ecbafcf commit 13aace6
Show file tree
Hide file tree
Showing 10 changed files with 56 additions and 9 deletions.
18 changes: 16 additions & 2 deletions athena/info/Skill.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ export enum Skill {
BuyUnitSuperTank = 27,
BuyUnitAcidBomber = 28,
BuyUnitDinosaur = 29,
Sabotage = 30,
}

export const Skills = new Set<Skill>([
Expand All @@ -57,6 +58,7 @@ export const Skills = new Set<Skill>([
Skill.UnitAbilitySniperImmediateAction,
Skill.UnitInfantryForestDefenseIncrease,
Skill.UnitRailDefenseIncreasePowerAttackIncrease,
Skill.Sabotage,
Skill.RecoverAirUnits,
Skill.BuyUnitBrute,
Skill.BuyUnitSuperAPU,
Expand Down Expand Up @@ -114,6 +116,7 @@ const skillConfig: Record<
[Skill.BuyUnitSuperTank]: { cost: 1500 },
[Skill.BuyUnitAcidBomber]: { cost: 1500 },
[Skill.BuyUnitDinosaur]: { cost: 1500 },
[Skill.Sabotage]: { charges: 5, cost: 1500 },
};

export const AIOnlySkills: ReadonlySet<Skill> = new Set(
Expand All @@ -124,7 +127,8 @@ type ID = number;
type Modifier = number;

type SkillMap = ReadonlyMap<Skill, Modifier>;
type UnitSkillMap = ReadonlyMap<Skill, ReadonlyMap<ID, Modifier>>;
type UnitModifierMap = ReadonlyMap<ID, Modifier>;
type UnitSkillMap = ReadonlyMap<Skill, UnitModifierMap>;
type MovementSkillMap = ReadonlyMap<Skill, ReadonlyMap<MovementType, Modifier>>;

type TileMovementSkillMap = ReadonlyMap<
Expand Down Expand Up @@ -154,7 +158,7 @@ const attackStatusEffects: SkillMap = new Map([
[Skill.AttackAndDefenseDecreaseEasy, -0.1],
]);

const attackUnitStatusEffects: UnitSkillMap = new Map([
const attackUnitStatusEffects = new Map<Skill, UnitModifierMap>([
[
Skill.ArtilleryRangeIncrease,
new Map([
Expand All @@ -163,6 +167,7 @@ const attackUnitStatusEffects: UnitSkillMap = new Map([
[UnitID.Cannon, 0.1],
]),
],
[Skill.Sabotage, new Map([[UnitID.Saboteur, 0.2]])],
]);

const attackPowerStatusEffects: SkillMap = new Map([
Expand Down Expand Up @@ -866,6 +871,15 @@ const getSkillActiveUnitTypes = (
}
}

if (skill === Skill.Sabotage) {
for (const [vector, unit] of map.units) {
if (unit.id === UnitID.Saboteur && map.matchesPlayer(unit, player)) {
list.push(vector);
}
}
return list;
}

if (skill === Skill.BuyUnitCommander) {
for (const [vector, unit] of map.units) {
if (unit.isLeader() && map.matchesPlayer(unit, player)) {
Expand Down
2 changes: 1 addition & 1 deletion athena/info/Unit.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2295,7 +2295,7 @@ export const Flamethrower = new UnitInfo(
);

export const Saboteur = new UnitInfo(
16,
UnitID.Saboteur,
'Saboteur',
'Arvid',
'male',
Expand Down
1 change: 1 addition & 0 deletions athena/info/UnitID.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ export default {
Artillery: 7,
HeavyArtillery: 12,
Sniper: 14,
Saboteur: 16,
AcidBomber: 22,
Medic: 26,
Dinosaur: 36,
Expand Down
3 changes: 1 addition & 2 deletions athena/lib/maybeConvertPlayer.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import ImmutableMap from '@nkzw/immutable-map';
import { Ability } from '../info/Unit.tsx';
import Unit from '../map/Unit.tsx';
import Vector from '../map/Vector.tsx';
import MapData from '../MapData.tsx';
Expand All @@ -12,7 +11,7 @@ export default function maybeConvertPlayer(
attackingUnit: Unit | null | undefined,
state: 'recover' | 'complete',
) {
if (!attackingUnit?.info.hasAbility(Ability.Convert)) {
if (!attackingUnit?.canConvert(map.getPlayer(attackingUnit.player))) {
return unit;
}

Expand Down
8 changes: 8 additions & 0 deletions athena/map/Unit.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { Skill } from '../info/Skill.tsx';
import {
Ability,
getUnitInfo,
Saboteur,
Sniper,
Supply,
UnitInfo,
Expand Down Expand Up @@ -475,6 +476,13 @@ export default class Unit extends Entity {
);
}

canConvert(player: Player) {
return (
this.info.hasAbility(Ability.Convert) ||
(this.info === Saboteur && player.activeSkills.has(Skill.Sabotage))
);
}

getAttackWeapon(entity: Entity) {
const { primaryWeapon, weapons } = this.info.attack;
if (weapons) {
Expand Down
2 changes: 1 addition & 1 deletion dionysus/lib/getPossibleAttacks.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ export default function getPossibleAttacks(
counterDamage &&
counterDamage > 0 &&
(counterDamage * 0.75 > damage || counterDamage > unitA.health) &&
!unitA.info.hasAbility(Ability.Convert)
!unitA.canConvert(map.getPlayer(unitA))
) {
return;
}
Expand Down
1 change: 1 addition & 0 deletions dionysus/lib/shouldActivatePower.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ const shouldConsiderUnitRatio = (skill: Skill) => {
case Skill.MovementIncreaseGroundUnitDefenseDecrease:
case Skill.NoUnitRestrictions:
case Skill.RecoverAirUnits:
case Skill.Sabotage:
case Skill.UnitAbilitySniperImmediateAction:
case Skill.UnitBattleShipMoveAndAct:
case Skill.UnitInfantryForestDefenseIncrease:
Expand Down
11 changes: 9 additions & 2 deletions hera/lib/getSkillBasedPortrait.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,15 @@ import {
AcidBomber,
AIU,
Alien,
Battleship,
BazookaBear,
Brute,
Cannon,
Commander,
Dinosaur,
Octopus,
Saboteur,
Sniper,
SuperAPU,
SuperTank,
Zombie,
Expand Down Expand Up @@ -41,6 +44,12 @@ export default function getSkillBasedPortrait(skill: Skill) {
return SuperAPU;
case Skill.BuyUnitZombieDefenseDecreaseMajor:
return Zombie;
case Skill.Sabotage:
return Saboteur;
case Skill.UnitAbilitySniperImmediateAction:
return Sniper;
case Skill.UnitBattleShipMoveAndAct:
return Battleship;

case Skill.DecreaseUnitCostAttackAndDefenseDecreaseMinor:
case Skill.ArtilleryRangeIncrease:
Expand All @@ -55,8 +64,6 @@ export default function getSkillBasedPortrait(skill: Skill) {
case Skill.MovementIncreaseGroundUnitDefenseDecrease:
case Skill.NoUnitRestrictions:
case Skill.RecoverAirUnits:
case Skill.UnitAbilitySniperImmediateAction:
case Skill.UnitBattleShipMoveAndAct:
case Skill.UnitInfantryForestDefenseIncrease:
case Skill.UnitRailDefenseIncreasePowerAttackIncrease:
return null;
Expand Down
8 changes: 8 additions & 0 deletions hera/lib/getSkillConfigForDisplay.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,14 @@ export default function getSkillConfigForDisplay(skill: Skill): SkillConfig {
icon: Dinosaur,
name: fbt('Dino Rampage', 'Skill name'),
};
case Skill.Sabotage:
return {
alpha: 0.3,
borderStyle: 'coin',
colors: 'purple',
icon: Repeat,
name: fbt('Sneaky Sabotage', 'Skill name'),
};
default: {
skill satisfies never;
throw new UnknownTypeError('getSkillConfig', skill);
Expand Down
11 changes: 10 additions & 1 deletion hera/ui/SkillDescription.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import {
Battleship,
BazookaBear,
getUnitInfoOrThrow,
Saboteur,
Sniper,
SpecialUnits,
UnitInfo,
Expand Down Expand Up @@ -670,7 +671,6 @@ const getExtraPowerDescription = (skill: Skill, color: BaseColor) => {
</fbt:param>.
</fbt>
);

case Skill.BuyUnitOctopus:
return (
<fbt desc="Additional skill description">
Expand All @@ -679,6 +679,15 @@ const getExtraPowerDescription = (skill: Skill, color: BaseColor) => {
points.
</fbt>
);
case Skill.Sabotage:
return (
<fbt desc="Additional skill description">
<fbt:param name="unitName">
<UnitName color={color} unit={Saboteur} />
</fbt:param>{' '}
convert opponents after attacking.
</fbt>
);
}

return null;
Expand Down

0 comments on commit 13aace6

Please sign in to comment.