diff --git a/src/battle-animations-moves.ts b/src/battle-animations-moves.ts
index ec39628e9..81c8a0681 100644
--- a/src/battle-animations-moves.ts
+++ b/src/battle-animations-moves.ts
@@ -9,7 +9,9 @@
* @license CC0-1.0
*/
-const BattleMoveAnims: AnimTable = {
+import {AnimTable, BattleOtherAnims} from './battle-animations';
+
+export const BattleMoveAnims: AnimTable = {
taunt: {
anim(scene, [attacker, defender]) {
BattleOtherAnims.dance.anim(scene, [attacker, defender]);
diff --git a/src/battle-animations.ts b/src/battle-animations.ts
index 396eb1934..b86378367 100644
--- a/src/battle-animations.ts
+++ b/src/battle-animations.ts
@@ -11,6 +11,12 @@
* @license MIT
*/
+import type {Battle, Pokemon, Side, WeatherState} from './battle';
+import type {BattleSceneStub} from './battle-scene-stub';
+import {BattleMoveAnims} from './battle-animations-moves';
+import {BattleLog} from './battle-log';
+import {BattleBGM, BattleSound} from './battle-sound';
+
/*
Most of this file is: CC0 (public domain)
@@ -30,7 +36,7 @@ This license DOES NOT extend to any other files in this repository.
*/
-class BattleScene {
+export class BattleScene implements BattleSceneStub {
battle: Battle;
animating = true;
acceleration = 1;
@@ -234,7 +240,7 @@ class BattleScene {
} else {
this.$frame.append('
');
this.$frame.find('div.playbutton button[name=play-muted]').click(() => {
- this.battle.setMute(true);
+ this.setMute(true);
this.battle.play();
});
}
@@ -244,6 +250,9 @@ class BattleScene {
this.$frame.find('div.playbutton').remove();
this.updateBgm();
}
+ setMute(muted: boolean) {
+ BattleSound.setMute(muted);
+ }
wait(time: number) {
if (!this.animating) return;
this.timeOffset += time;
@@ -589,7 +598,7 @@ class BattleScene {
} else {
let statustext = '';
if (pokemon.hp !== pokemon.maxhp) {
- statustext += Pokemon.getHPText(pokemon);
+ statustext += pokemon.getHPText();
}
if (pokemon.status) {
if (statustext) statustext += '|';
@@ -1643,7 +1652,7 @@ class BattleScene {
}
}
-interface ScenePos {
+export interface ScenePos {
/** - left, + right */
x?: number;
/** - down, + up */
@@ -1669,7 +1678,7 @@ interface InitScenePos {
display?: string;
}
-class Sprite {
+export class Sprite {
scene: BattleScene;
$el: JQuery = null!;
sp: SpriteData;
@@ -1732,7 +1741,7 @@ class Sprite {
}
}
-class PokemonSprite extends Sprite {
+export class PokemonSprite extends Sprite {
// HTML strings are constructed from this table and stored back in it to cache them
protected static statusTable: {[id: string]: [string, 'good' | 'bad' | 'neutral'] | null | string} = {
formechange: null,
@@ -2795,7 +2804,7 @@ interface AnimData {
prepareAnim?(scene: BattleScene, args: PokemonSprite[]): void;
residualAnim?(scene: BattleScene, args: PokemonSprite[]): void;
}
-type AnimTable = {[k: string]: AnimData};
+export type AnimTable = {[k: string]: AnimData};
const BattleEffects: {[k: string]: SpriteData} = {
wisp: {
@@ -3112,7 +3121,7 @@ const BattleBackdrops = [
'bg-skypillar.jpg',
];
-const BattleOtherAnims: AnimTable = {
+export const BattleOtherAnims: AnimTable = {
hitmark: {
anim(scene, [attacker]) {
scene.showEffect('hitmark', {
@@ -5698,7 +5707,7 @@ const BattleOtherAnims: AnimTable = {
},
},
};
-const BattleStatusAnims: AnimTable = {
+export const BattleStatusAnims: AnimTable = {
brn: {
anim(scene, [attacker]) {
scene.showEffect('fireball', {
diff --git a/src/battle-log.ts b/src/battle-log.ts
index ece0bad60..a45b6c9c1 100644
--- a/src/battle-log.ts
+++ b/src/battle-log.ts
@@ -13,7 +13,17 @@
* @license MIT
*/
-class BattleLog {
+import type {BattleScene} from './battle-animations';
+
+// Caja
+declare const html4: any;
+declare const html: any;
+
+// defined in battle-log-misc
+declare function MD5(input: string): string;
+declare function formatText(input: string, isTrusted?: boolean): string;
+
+export class BattleLog {
elem: HTMLDivElement;
innerElem: HTMLDivElement;
scene: BattleScene | null = null;
@@ -358,7 +368,7 @@ class BattleLog {
addSpacer() {
this.addDiv('spacer battle-history', '
');
}
- changeUhtml(id: string, html: string, forceAdd?: boolean) {
+ changeUhtml(id: string, htmlSrc: string, forceAdd?: boolean) {
id = toID(id);
const classContains = ' uhtml-' + id + ' ';
let elements = [] as HTMLDivElement[];
@@ -374,9 +384,9 @@ class BattleLog {
}
}
}
- if (html && elements.length && !forceAdd) {
+ if (htmlSrc && elements.length && !forceAdd) {
for (const element of elements) {
- element.innerHTML = BattleLog.sanitizeHTML(html);
+ element.innerHTML = BattleLog.sanitizeHTML(htmlSrc);
}
this.updateScroll();
return;
@@ -384,11 +394,11 @@ class BattleLog {
for (const element of elements) {
element.parentElement!.removeChild(element);
}
- if (!html) return;
+ if (!htmlSrc) return;
if (forceAdd) {
- this.addDiv('notice uhtml-' + id, BattleLog.sanitizeHTML(html));
+ this.addDiv('notice uhtml-' + id, BattleLog.sanitizeHTML(htmlSrc));
} else {
- this.prependDiv('notice uhtml-' + id, BattleLog.sanitizeHTML(html));
+ this.prependDiv('notice uhtml-' + id, BattleLog.sanitizeHTML(htmlSrc));
}
}
hideChatFrom(userid: ID, showRevealButton = true, lineCount = 0) {
@@ -634,8 +644,8 @@ class BattleLog {
case 'uhtml':
case 'uhtmlchange':
let parts = target.split(',');
- let html = parts.slice(1).join(',').trim();
- this.changeUhtml(parts[0], html, cmd === 'uhtml');
+ let htmlSrc = parts.slice(1).join(',').trim();
+ this.changeUhtml(parts[0], htmlSrc, cmd === 'uhtml');
return ['', ''];
case 'raw':
return ['chat', BattleLog.sanitizeHTML(target)];
diff --git a/src/battle-scene-stub.ts b/src/battle-scene-stub.ts
index b27b7a74f..99a8dde09 100644
--- a/src/battle-scene-stub.ts
+++ b/src/battle-scene-stub.ts
@@ -1,4 +1,8 @@
-class BattleSceneStub {
+import type {Pokemon, Side} from './battle';
+import type {ScenePos, PokemonSprite} from './battle-animations';
+import type {BattleLog} from './battle-log';
+
+export class BattleSceneStub {
animating: boolean = false;
acceleration: number = NaN;
gen: number = NaN;
@@ -10,12 +14,12 @@ class BattleSceneStub {
log: BattleLog = {add: (args: Args, kwargs?: KWArgs) => {}} as any;
abilityActivateAnim(pokemon: Pokemon, result: string): void { }
- addPokemonSprite(pokemon: Pokemon) { return null!; }
+ addPokemonSprite(pokemon: Pokemon): PokemonSprite { return null!; }
addSideCondition(siden: number, id: ID, instant?: boolean | undefined): void { }
animationOff(): void { }
animationOn(): void { }
maybeCloseMessagebar(args: Args, kwArgs: KWArgs): boolean { return false; }
- closeMessagebar(): void { }
+ closeMessagebar(): boolean { return false; }
damageAnim(pokemon: Pokemon, damage: string | number): void { }
destroy(): void { }
finishAnimations(): JQuery.Promise, any, any> | undefined { return void(0); }
@@ -25,6 +29,7 @@ class BattleSceneStub {
updateAcceleration(): void { }
message(message: string, hiddenMessage?: string | undefined): void { }
pause(): void { }
+ setMute(muted: boolean): void { }
preemptCatchup(): void { }
removeSideCondition(siden: number, id: ID): void { }
reset(): void { }
@@ -68,7 +73,6 @@ class BattleSceneStub {
anim(pokemon: Pokemon, end: ScenePos, transition?: string) { }
beforeMove(pokemon: Pokemon) { }
afterMove(pokemon: Pokemon) { }
- unlink(userid: string, showRevealButton = false) { }
}
if (typeof require === 'function') {
diff --git a/src/battle-sound.ts b/src/battle-sound.ts
index ae1bac2c2..5307e73f9 100644
--- a/src/battle-sound.ts
+++ b/src/battle-sound.ts
@@ -1,5 +1,5 @@
-class BattleBGM {
+export class BattleBGM {
/**
* May be shared with other BGM objects: every battle has its own BattleBGM
* object, but two battles with the same music will have the same HTMLAudioElement
@@ -100,7 +100,7 @@ class BattleBGM {
}
}
-const BattleSound = new class {
+export const BattleSound = new class {
soundCache: {[url: string]: HTMLAudioElement | undefined} = {};
bgm: BattleBGM[] = [];
diff --git a/src/battle.ts b/src/battle.ts
index 7e51d7a82..ceb23d287 100644
--- a/src/battle.ts
+++ b/src/battle.ts
@@ -27,13 +27,17 @@
* @license MIT
*/
-/** [id, element?, ...misc] */
-type EffectState = any[] & {0: ID};
-/** [name, minTimeLeft, maxTimeLeft] */
-type WeatherState = [string, number, number];
-type HPColor = 'r' | 'y' | 'g';
+import {BattleSceneStub} from './battle-scene-stub';
+import {BattleLog} from './battle-log';
+import {BattleScene, PokemonSprite, BattleStatusAnims} from './battle-animations';
-class Pokemon implements PokemonDetails, PokemonHealth {
+/** [id, element?, ...misc] */
+export type EffectState = any[] & {0: ID};
+/** [name, minTimeLeft, maxTimeLeft] */
+export type WeatherState = [string, number, number];
+export type HPColor = 'r' | 'y' | 'g';
+
+export class Pokemon implements PokemonDetails, PokemonHealth {
name = '';
speciesForme = '';
@@ -570,6 +574,9 @@ class Pokemon implements PokemonDetails, PokemonHealth {
}
return percentage * maxWidth / 100;
}
+ getHPText(precision = 1) {
+ return Pokemon.getHPText(this, precision);
+ }
static getHPText(pokemon: PokemonHealth, precision = 1) {
if (pokemon.maxhp === 100) return pokemon.hp + '%';
if (pokemon.maxhp !== 48) return (100 * pokemon.hp / pokemon.maxhp).toFixed(precision) + '%';
@@ -583,7 +590,7 @@ class Pokemon implements PokemonDetails, PokemonHealth {
}
}
-class Side {
+export class Side {
battle: Battle;
name = '';
id = '';
@@ -932,7 +939,7 @@ class Side {
}
}
-interface PokemonDetails {
+export interface PokemonDetails {
details: string;
name: string;
speciesForme: string;
@@ -942,14 +949,14 @@ interface PokemonDetails {
ident: string;
searchid: string;
}
-interface PokemonHealth {
+export interface PokemonHealth {
hp: number;
maxhp: number;
hpcolor: HPColor | '';
status: StatusName | 'tox' | '' | '???';
fainted?: boolean;
}
-interface ServerPokemon extends PokemonDetails, PokemonHealth {
+export interface ServerPokemon extends PokemonDetails, PokemonHealth {
ident: string;
details: string;
condition: string;
@@ -976,8 +983,8 @@ interface ServerPokemon extends PokemonDetails, PokemonHealth {
gigantamax: string | false;
}
-class Battle {
- scene: BattleScene | BattleSceneStub;
+export class Battle {
+ scene: BattleSceneStub;
sidesSwitched = false;
@@ -3669,7 +3676,7 @@ class Battle {
}
setMute(mute: boolean) {
- BattleSound.setMute(mute);
+ this.scene.setMute(mute);
}
}
diff --git a/src/globals.d.ts b/src/globals.d.ts
index 67c82497e..b81224f6b 100644
--- a/src/globals.d.ts
+++ b/src/globals.d.ts
@@ -1,14 +1,5 @@
-
-
-// dependencies
-///////////////
-
-// Caja
-declare var html4: any;
-declare var html: any;
-
-// data
-///////
+// dex data
+///////////
declare var BattlePokedex: any;
declare var BattleMovedex: any;
@@ -16,21 +7,9 @@ declare var BattleAbilities: any;
declare var BattleItems: any;
declare var BattleAliases: any;
declare var BattleStatuses: any;
-// declare var BattleMoveAnims: any;
-// declare var BattleStatusAnims: any;
-// declare var BattleOtherAnims: any;
-// declare var BattleBackdrops: any;
-// declare var BattleBackdropsThree: any;
-// declare var BattleBackdropsFour: any;
-// declare var BattleBackdropsFive: any;
-// declare var BattleEffects: any;
declare var BattlePokemonSprites: any;
declare var BattlePokemonSpritesBW: any;
-// defined in battle-log-misc
-declare function MD5(input: string): string;
-declare function formatText(input: string, isTrusted?: boolean): string;
-
// PS globals
/////////////
@@ -43,3 +22,18 @@ declare var app: {user: AnyObject, rooms: AnyObject, ignore?: AnyObject};
interface Window {
[k: string]: any;
}
+
+// Temporary globals (exported from modules, used by non-module files)
+
+// When creating now module files, these should all be commented out
+// to make sure they're not being used globally in modules.
+
+declare var Battle: typeof import('./battle').Battle;
+type Battle = import('./battle').Battle;
+declare var BattleScene: typeof import('./battle-animations').BattleScene;
+type BattleScene = import('./battle-animations').BattleScene;
+declare var Pokemon: typeof import('./battle').Pokemon;
+type Pokemon = import('./battle').Pokemon;
+type ServerPokemon = import('./battle').ServerPokemon;
+declare var BattleLog: typeof import('./battle-log').BattleLog;
+type BattleLog = import('./battle-log').BattleLog;
diff --git a/tslint.json b/tslint.json
index 302df6498..280ac9e9a 100644
--- a/tslint.json
+++ b/tslint.json
@@ -36,6 +36,7 @@
"no-unnecessary-initializer": false,
"object-literal-sort-keys": false,
"object-literal-key-quotes": false,
+ "ordered-imports": false,
"trailing-comma": [
true,
{