Skip to content

Commit 8d527cb

Browse files
authored
Added Power Spot, Fixed Dauntless Shield, Made Competitive activate from Intimidate, Cleaned up EV and IV exporting (#435)
* Added Power Spot * Fixed a minor typo * fixed Dauntless Shield Bug (#436) * added a trigger for Competitive when opposing Pokemon has Intimidate * cleaned up IV and EV exporting * added iron ball check to immunity checks * added iron ball check to immunity checks, made terrain pulse only take terrain type for grounded pokemon * made max move names change based on ability * added Iron Ball to isGrounded check * Dynamic Max Moves get the right type, name and desc still wrong (#437)
1 parent 0cc3c16 commit 8d527cb

13 files changed

+96
-23
lines changed

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ $ cd calc && npm install
135135
```
136136

137137
Next, run `node build` from the root directory of your clone of this repository. This should
138-
run `npm run compile` in the `calc/` subdirectory to compile the `@smoogon/calc` package from
138+
run `npm run compile` in the `calc/` subdirectory to compile the `@smogon/calc` package from
139139
TypeScript to JavaScript that can be run in the browser, and then compile the 'templated' HTML
140140
and copy everything into the top-level `dist/` folder. To then view the UI, open `dist/index.html` -
141141
simply double-clicking on the file from your operating system's file manager UI should open it in

calc/src/desc.ts

+4
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ export interface RawDesc {
2929
isProtected?: boolean;
3030
isReflect?: boolean;
3131
isBattery?: boolean;
32+
isPowerSpot?: boolean;
3233
isSwitching?: 'out' | 'in';
3334
moveBP?: number;
3435
moveName: string;
@@ -825,6 +826,9 @@ function buildDescription(description: RawDesc, attacker: Pokemon, defender: Pok
825826
if (description.isBattery) {
826827
output += ' Battery boosted ';
827828
}
829+
if (description.isPowerSpot) {
830+
output += ' Power Spot boosted ';
831+
}
828832
if (description.isSwitching) {
829833
output += ' switching boosted ';
830834
}

calc/src/field.ts

+2
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ export class Side implements State.Side {
7171
isFriendGuard: boolean;
7272
isAuroraVeil: boolean;
7373
isBattery: boolean;
74+
isPowerSpot: boolean;
7475
isSwitching?: 'out' | 'in';
7576

7677
constructor(side: State.Side = {}) {
@@ -91,6 +92,7 @@ export class Side implements State.Side {
9192
this.isFriendGuard = !!side.isFriendGuard;
9293
this.isAuroraVeil = !!side.isAuroraVeil;
9394
this.isBattery = !!side.isBattery;
95+
this.isPowerSpot = !!side.isPowerSpot;
9496
this.isSwitching = side.isSwitching;
9597
}
9698

calc/src/mechanics/gen56.ts

+9-1
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,8 @@ export function calculateBWXY(
180180
} else if (defender.types[1] && effectiveness[defender.types[1]]! === 0) {
181181
typeEffectiveness = type1Effectiveness;
182182
}
183+
} else if (typeEffectiveness === 0 && move.hasType('Ground') && defender.hasItem('Iron Ball')) {
184+
typeEffectiveness = 1;
183185
}
184186

185187
if (typeEffectiveness === 0) {
@@ -202,7 +204,8 @@ export function calculateBWXY(
202204
(move.hasType('Electric') &&
203205
defender.hasAbility('Lightning Rod', 'Motor Drive', 'Volt Absorb')) ||
204206
(move.hasType('Ground') &&
205-
!field.isGravity && !move.named('Thousand Arrows') && defender.hasAbility('Levitate')) ||
207+
!field.isGravity && !defender.hasItem('Iron Ball') &&
208+
!move.named('Thousand Arrows') && defender.hasAbility('Levitate')) ||
206209
(move.flags.bullet && defender.hasAbility('Bulletproof')) ||
207210
(move.flags.sound && defender.hasAbility('Soundproof'))
208211
) {
@@ -456,6 +459,11 @@ export function calculateBWXY(
456459
desc.isBattery = true;
457460
}
458461

462+
if (field.attackerSide.isPowerSpot) {
463+
bpMods.push(0x14cc);
464+
desc.isPowerSpot = true;
465+
}
466+
459467
if (isAerilate || isPixilate || isRefrigerate || isNormalize) {
460468
bpMods.push(0x14cd);
461469
desc.attackerAbility = attacker.ability;

calc/src/mechanics/gen78.ts

+15-7
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,8 @@ export function calculateSMSS(
5858
checkKlutz(defender);
5959
checkSeedBoost(attacker, field);
6060
checkSeedBoost(defender, field);
61+
checkDauntlessShield(attacker);
62+
checkDauntlessShield(defender);
6163

6264
computeFinalStats(gen, attacker, defender, field, 'def', 'spd', 'spe');
6365

@@ -67,8 +69,6 @@ export function calculateSMSS(
6769
checkDownload(defender, attacker);
6870
checkIntrepidSword(attacker);
6971
checkIntrepidSword(defender);
70-
checkDauntlessShield(attacker);
71-
checkDauntlessShield(defender);
7272

7373
computeFinalStats(gen, attacker, defender, field, 'atk', 'spa');
7474

@@ -130,8 +130,7 @@ export function calculateSMSS(
130130
const isCritical = !defender.hasAbility('Battle Armor', 'Shell Armor') &&
131131
(move.isCrit || (attacker.hasAbility('Merciless') && defender.hasStatus('psn', 'tox'))) &&
132132
move.timesUsed === 1;
133-
134-
if (move.named('Weather Ball')) {
133+
if (move.named('Weather Ball') || move.originalName === 'Weather Ball') {
135134
const holdingUmbrella = attacker.hasItem('Utility Umbrella');
136135
move.type =
137136
field.hasWeather('Sun', 'Harsh Sunshine') && !holdingUmbrella ? 'Fire'
@@ -154,7 +153,8 @@ export function calculateSMSS(
154153
desc.attackerItem = attacker.item;
155154
desc.moveBP = move.bp;
156155
desc.moveType = move.type;
157-
} else if (move.named('Nature Power', 'Terrain Pulse')) {
156+
} else if (move.named('Nature Power') || move.originalName === 'Nature Power' ||
157+
((move.named('Terrain Pulse') || move.originalName === 'Terrain Pulse') && isGrounded(attacker, field))) {
158158
move.type =
159159
field.hasTerrain('Electric') ? 'Electric'
160160
: field.hasTerrain('Grassy') ? 'Grass'
@@ -234,6 +234,8 @@ export function calculateSMSS(
234234
} else if (defender.types[1] && effectiveness[defender.types[1]]! === 0) {
235235
typeEffectiveness = type1Effectiveness;
236236
}
237+
} else if (typeEffectiveness === 0 && move.hasType('Ground') && defender.hasItem('Iron Ball')) {
238+
typeEffectiveness = 1;
237239
}
238240

239241
if (typeEffectiveness === 0) {
@@ -256,7 +258,8 @@ export function calculateSMSS(
256258
(move.hasType('Electric') &&
257259
defender.hasAbility('Lightning Rod', 'Motor Drive', 'Volt Absorb')) ||
258260
(move.hasType('Ground') &&
259-
!field.isGravity && !move.named('Thousand Arrows') && defender.hasAbility('Levitate')) ||
261+
!field.isGravity && !defender.hasItem('Iron Ball') &&
262+
!move.named('Thousand Arrows') && defender.hasAbility('Levitate')) ||
260263
(move.flags.bullet && defender.hasAbility('Bulletproof')) ||
261264
(move.flags.sound && !move.named('Clangorous Soul') && defender.hasAbility('Soundproof')) ||
262265
(move.priority > 0 && defender.hasAbility('Queenly Majesty', 'Dazzling'))
@@ -648,7 +651,7 @@ export function calculateBasePowerSMSS(
648651
desc.moveBP = basePower;
649652
break;
650653
case 'Terrain Pulse':
651-
basePower = move.bp * (field.terrain ? 2 : 1);
654+
basePower = move.bp * (field.terrain && isGrounded(attacker, field) ? 2 : 1);
652655
desc.moveBP = basePower;
653656
break;
654657
case 'Fling':
@@ -812,6 +815,11 @@ export function calculateBPModsSMSS(
812815
desc.isBattery = true;
813816
}
814817

818+
if (field.attackerSide.isPowerSpot) {
819+
bpMods.push(0x14CD);
820+
desc.isPowerSpot = true;
821+
}
822+
815823
// Sheer Force does not power up max moves or remove the effects (SadisticMystic)
816824
const analyticBoost = attacker.hasAbility('Analytic') &&
817825
(turnOrder !== 'first' || field.defenderSide.isSwitching === 'out');

calc/src/mechanics/util.ts

+4-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ const EV_ITEMS = [
2828
];
2929

3030
export function isGrounded(pokemon: Pokemon, field: Field) {
31-
return (field.isGravity ||
31+
return (field.isGravity || pokemon.hasItem('Iron Ball') ||
3232
(!pokemon.hasType('Flying') &&
3333
!pokemon.hasAbility('Levitate') &&
3434
!pokemon.hasItem('Air Balloon')));
@@ -181,6 +181,9 @@ export function checkIntimidate(gen: Generation, source: Pokemon, target: Pokemo
181181
} else {
182182
target.boosts.atk = Math.max(-6, target.boosts.atk - 1);
183183
}
184+
if(target.hasAbility('Competitive')) {
185+
target.boosts.spa = Math.min(6, target.boosts.spa + 2);
186+
}
184187
}
185188
}
186189

calc/src/move.ts

+8-2
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,8 @@ export class Move implements State.Move {
5858
const maxMoveName: string = getMaxMoveName(
5959
data.type,
6060
options.species,
61-
!!(data.category === 'Status')
61+
!!(data.category === 'Status'),
62+
options.ability
6263
);
6364
const maxMove = gen.moves.get(toID(maxMoveName));
6465
const maxPower = () => {
@@ -232,8 +233,9 @@ const ZMOVES_TYPING: {
232233
Water: 'Hydro Vortex',
233234
};
234235

235-
export function getMaxMoveName(moveType: I.TypeName, pokemonSpecies?: string, isStatus?: boolean) {
236+
export function getMaxMoveName(moveType: I.TypeName, pokemonSpecies?: string, isStatus?: boolean, pokemonAbility?: string) {
236237
if (isStatus) return 'Max Guard';
238+
if (pokemonAbility === 'Normalize') return 'Max Strike';
237239
if (moveType === 'Fire') {
238240
if (pokemonSpecies === 'Charizard-Gmax') return 'G-Max Wildfire';
239241
if (pokemonSpecies === 'Centiskorch-Gmax') return 'G-Max Centiferno';
@@ -243,6 +245,10 @@ export function getMaxMoveName(moveType: I.TypeName, pokemonSpecies?: string, is
243245
if (pokemonSpecies === 'Eevee-Gmax') return 'G-Max Cuddle';
244246
if (pokemonSpecies === 'Meowth-Gmax') return 'G-Max Gold Rush';
245247
if (pokemonSpecies === 'Snorlax-Gmax') return 'G-Max Replenish';
248+
if (pokemonAbility === 'Pixilate') return 'Max Starfall';
249+
if (pokemonAbility === 'Aerilate') return 'Max Airstream';
250+
if (pokemonAbility === 'Refrigerate') return 'Max Hailstorm';
251+
if (pokemonAbility === 'Galvanize') return 'Max Lightning';
246252
}
247253
if (moveType === 'Fairy') {
248254
if (pokemonSpecies === 'Alcremie-Gmax') return 'G-Max Finale';

calc/src/state.ts

+1
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ export namespace State {
6161
isFriendGuard?: boolean;
6262
isAuroraVeil?: boolean;
6363
isBattery?: boolean;
64+
isPowerSpot?: boolean;
6465
isSwitching?: 'out' | 'in';
6566
}
6667
}

src/honkalculate.template.html

+10
Original file line numberDiff line numberDiff line change
@@ -774,6 +774,16 @@
774774
<input class="visually-hidden" type="checkbox" id="batteryR" />
775775
<label class="btn btn-xxwide" for="batteryR">Battery</label>
776776
</div>
777+
<div class="btn-group gen-specific g8">
778+
<div class="left" title="Has this Pok&eacute;mon's power been boosted by an ally's Power Spot ability?">
779+
<input class="visually-hidden" type="checkbox" id="powerSpotL" />
780+
<label class="btn btn-xxwide" for="powerSpotL">Power Spot</label>
781+
</div>
782+
<div class="right" title="Has this Pok&eacute;mon's power been boosted by an ally's Power Spot ability?">
783+
<input class="visually-hidden" type="checkbox" id="powerSpotR" />
784+
<label class="btn btn-xxwide" for="powerSpotR">Power Spot</label>
785+
</div>
786+
</div>
777787
<div class="btn-group gen-specific g2 g3 g4 g5 g6 g7 g8">
778788
<div class="left" title="Is the defending Pok&eacute;mon switching out?">
779789
<input class="visually-hidden" type="checkbox" id="switchingL" />

src/index.template.html

+11
Original file line numberDiff line numberDiff line change
@@ -893,6 +893,17 @@
893893
<label class="btn btn-xxwide" for="batteryR">Battery</label>
894894
</div></td>
895895
</tr>
896+
<tr class="gen-specific g8">
897+
<td><div class="left" title="Is the Pok&eacute;mon boosted by an ally's Power Spot ability?">
898+
<div hidden id="selectPowerSpotInstruction">Is the Pok&eacute;mon boosted by an ally's Power Spot ability?</div>
899+
<input aria-describedby="selectPowerSpotInstruction" class="visually-hidden calc-trigger" type="checkbox" id="powerSpotL" />
900+
<label class="btn btn-xxwide" for="powerSpotL">Power Spot</label>
901+
</div></td>
902+
<td><div class="right" title="Is the Pok&eacute;mon boosted by an ally's Power Spot ability?">
903+
<input aria-describedby="selectPowerSpotInstruction" class="visually-hidden calc-trigger" type="checkbox" id="powerSpotR" />
904+
<label class="btn btn-xxwide" for="powerSpotR">Power Spot</label>
905+
</div></td>
906+
</tr>
896907
<tr class="gen-specific g2 g3 g4 g5 g6 g7 g8">
897908
<td><div class="left" title="Is the defending Pok&eacute;mon switching out?">
898909
<div hidden id="selectSwitchingInstruction">Is the defending Pok&eacute;mon switching out?</div>

src/js/moveset_import.js

+18-10
Original file line numberDiff line numberDiff line change
@@ -17,27 +17,35 @@ function ExportPokemon(pokeInfo) {
1717
finalText += "Level: " + pokemon.level + "\n";
1818
finalText += pokemon.nature && gen > 2 ? pokemon.nature + " Nature" + "\n" : "";
1919
finalText += pokemon.ability ? "Ability: " + pokemon.ability + "\n" : "";
20-
if (gen > 2) {
21-
finalText += "EVs: ";
20+
if (gen > 2) {
2221
var EVs_Array = [];
2322
for (var stat in pokemon.evs) {
2423
var ev = pokemon.evs[stat] ? pokemon.evs[stat] : 0;
25-
EVs_Array.push(ev + " " + calc.Stats.displayStat(stat));
24+
if(ev > 0) {
25+
EVs_Array.push(ev + " " + calc.Stats.displayStat(stat));
26+
}
2627
EV_counter += ev;
2728
if (EV_counter > 510) break;
2829
}
29-
finalText += serialize(EVs_Array, " / ");
30-
finalText += "\n";
30+
if(EVs_Array.length > 0){
31+
finalText += "EVs: ";
32+
finalText += serialize(EVs_Array, " / ");
33+
finalText += "\n";
34+
}
3135
}
32-
33-
finalText += "IVs: ";
36+
3437
var IVs_Array = [];
3538
for (var stat in pokemon.ivs) {
3639
var iv = pokemon.ivs[stat] ? pokemon.ivs[stat] : 0;
37-
IVs_Array.push(iv + " " + calc.Stats.displayStat(stat));
40+
if(iv < 31) {
41+
IVs_Array.push(iv + " " + calc.Stats.displayStat(stat));
42+
}
43+
}
44+
if(IVs_Array.length > 0) {
45+
finalText += "IVs: ";
46+
finalText += serialize(IVs_Array, " / ");
47+
finalText += "\n";
3848
}
39-
finalText += serialize(IVs_Array, " / ");
40-
finalText += "\n";
4149

4250
for (var i = 0; i < 4; i++) {
4351
var moveName = pokemon.moves[i].name;

src/js/shared_controls.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -846,6 +846,7 @@ function createField() {
846846
var isFriendGuard = [$("#friendGuardL").prop("checked"), $("#friendGuardR").prop("checked")];
847847
var isAuroraVeil = [$("#auroraVeilL").prop("checked"), $("#auroraVeilR").prop("checked")];
848848
var isBattery = [$("#batteryL").prop("checked"), $("#batteryR").prop("checked")];
849+
var isPowerSpot = [$("#powerSpotL").prop("checked"), $("#powerSpotR").prop("checked")];
849850
// TODO: support switching in as well!
850851
var isSwitchingOut = [$("#switchingL").prop("checked"), $("#switchingR").prop("checked")];
851852

@@ -856,7 +857,7 @@ function createField() {
856857
isReflect: isReflect[i], isLightScreen: isLightScreen[i],
857858
isProtected: isProtected[i], isSeeded: isSeeded[i], isForesight: isForesight[i],
858859
isTailwind: isTailwind[i], isHelpingHand: isHelpingHand[i], isFriendGuard: isFriendGuard[i],
859-
isAuroraVeil: isAuroraVeil[i], isBattery: isBattery[i], isSwitching: isSwitchingOut[i] ? 'out' : undefined
860+
isAuroraVeil: isAuroraVeil[i], isBattery: isBattery[i], isPowerSpot: isPowerSpot[i], isSwitching: isSwitchingOut[i] ? 'out' : undefined
860861
});
861862
};
862863
return new calc.Field({

src/randoms.template.html

+11
Original file line numberDiff line numberDiff line change
@@ -877,6 +877,17 @@
877877
<label class="btn btn-xxwide" for="batteryR">Battery</label>
878878
</div></td>
879879
</tr>
880+
<tr class="gen-specific g8">
881+
<td><div class="left" title="Is the Pok&eacute;mon boosted by an ally's Power Spot ability?">
882+
<div hidden id="selectPowerSpotInstruction">Is the Pok&eacute;mon boosted by an ally's Power Spot ability?</div>
883+
<input aria-describedby="selectPowerSpotInstruction" class="visually-hidden calc-trigger" type="checkbox" id="powerSpotL" />
884+
<label class="btn btn-xxwide" for="powerSpotR">Power Spot</label>
885+
</div></td>
886+
<td><div class="right" title="Is the Pok&eacute;mon boosted by an ally's Power Spot ability?">
887+
<input aria-describedby="selectPowerSpotInstruction" class="visually-hidden calc-trigger" type="checkbox" id="powerSpotR" />
888+
<label class="btn btn-xxwide" for="powerSpotR">Power Spot</label>
889+
</div></td>
890+
</tr>
880891
<tr class="gen-specific g2 g3 g4 g5 g6 g7 g8">
881892
<td><div class="left" title="Is the defending Pok&eacute;mon switching out?">
882893
<div hidden id="selectSwitchingInstruction">Is the defending Pok&eacute;mon switching out?</div>

0 commit comments

Comments
 (0)