Add character sprite system with female rival

pull/16/head
Flashfyre 2024-02-22 18:03:36 -05:00
parent 3ed80de330
commit 9005e32883
9 changed files with 398 additions and 51 deletions

1
.gitignore vendored
View File

@ -29,5 +29,6 @@ public/images/pokemon/input/*.png
public/images/pokemon/input/output/* public/images/pokemon/input/output/*
public/images/pokemon/icons/input/*.png public/images/pokemon/icons/input/*.png
public/images/pokemon/icons/input/output/* public/images/pokemon/icons/input/output/*
public/images/character/*/
src/data/battle-anim-raw-data*.ts src/data/battle-anim-raw-data*.ts
src/data/battle-anim-data.ts src/data/battle-anim-data.ts

View File

@ -0,0 +1,209 @@
{
"textures": [
{
"image": "rival_f.png",
"format": "RGBA8888",
"size": {
"w": 184,
"h": 675
},
"scale": 1,
"frames": [
{
"filename": "angry",
"rotated": false,
"trimmed": true,
"sourceSize": {
"w": 108,
"h": 135
},
"spriteSourceSize": {
"x": 9,
"y": 0,
"w": 92,
"h": 135
},
"frame": {
"x": 0,
"y": 0,
"w": 92,
"h": 135
}
},
{
"filename": "angry_mopen",
"rotated": false,
"trimmed": true,
"sourceSize": {
"w": 108,
"h": 135
},
"spriteSourceSize": {
"x": 9,
"y": 0,
"w": 92,
"h": 135
},
"frame": {
"x": 92,
"y": 0,
"w": 92,
"h": 135
}
},
{
"filename": "neutral",
"rotated": false,
"trimmed": true,
"sourceSize": {
"w": 108,
"h": 135
},
"spriteSourceSize": {
"x": 9,
"y": 0,
"w": 92,
"h": 135
},
"frame": {
"x": 0,
"y": 135,
"w": 92,
"h": 135
}
},
{
"filename": "shock",
"rotated": false,
"trimmed": true,
"sourceSize": {
"w": 108,
"h": 135
},
"spriteSourceSize": {
"x": 9,
"y": 0,
"w": 92,
"h": 135
},
"frame": {
"x": 92,
"y": 135,
"w": 92,
"h": 135
}
},
{
"filename": "smile",
"rotated": false,
"trimmed": true,
"sourceSize": {
"w": 108,
"h": 135
},
"spriteSourceSize": {
"x": 9,
"y": 0,
"w": 92,
"h": 135
},
"frame": {
"x": 0,
"y": 270,
"w": 92,
"h": 135
}
},
{
"filename": "smile_eclosed",
"rotated": false,
"trimmed": true,
"sourceSize": {
"w": 108,
"h": 135
},
"spriteSourceSize": {
"x": 9,
"y": 0,
"w": 92,
"h": 135
},
"frame": {
"x": 92,
"y": 270,
"w": 92,
"h": 135
}
},
{
"filename": "smile_ehalf",
"rotated": false,
"trimmed": true,
"sourceSize": {
"w": 108,
"h": 135
},
"spriteSourceSize": {
"x": 9,
"y": 0,
"w": 92,
"h": 135
},
"frame": {
"x": 0,
"y": 405,
"w": 92,
"h": 135
}
},
{
"filename": "smile_wave",
"rotated": false,
"trimmed": true,
"sourceSize": {
"w": 108,
"h": 135
},
"spriteSourceSize": {
"x": 18,
"y": 0,
"w": 83,
"h": 135
},
"frame": {
"x": 0,
"y": 540,
"w": 83,
"h": 135
}
},
{
"filename": "smile_wave_wink",
"rotated": false,
"trimmed": true,
"sourceSize": {
"w": 108,
"h": 135
},
"spriteSourceSize": {
"x": 18,
"y": 0,
"w": 83,
"h": 135
},
"frame": {
"x": 83,
"y": 540,
"w": 83,
"h": 135
}
}
]
}
],
"meta": {
"app": "https://www.codeandweb.com/texturepacker",
"version": "3.0",
"smartupdate": "$TexturePacker:SmartUpdate:1be996f9906a409496e360d67e49ccd0:db1900b6808dc32ed4746255b60aa557:0aaa288a75ecf87b6647cbb7fd0d2ecc$"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

View File

@ -51,6 +51,7 @@ import { FormChangePhase, QuietFormChangePhase } from './form-change-phase';
import { BattleSpec } from './enums/battle-spec'; import { BattleSpec } from './enums/battle-spec';
import { getTypeRgb } from './data/type'; import { getTypeRgb } from './data/type';
import PokemonSpriteSparkleHandler from './sprite/pokemon-sprite-sparkle-handler'; import PokemonSpriteSparkleHandler from './sprite/pokemon-sprite-sparkle-handler';
import CharSprite from './ui/char-sprite';
const enableAuto = true; const enableAuto = true;
const quickStart = false; const quickStart = false;
@ -112,6 +113,7 @@ export default class BattleScene extends Phaser.Scene {
private standbyPhase: Phase; private standbyPhase: Phase;
public field: Phaser.GameObjects.Container; public field: Phaser.GameObjects.Container;
public fieldUI: Phaser.GameObjects.Container; public fieldUI: Phaser.GameObjects.Container;
public charSprite: CharSprite;
public pbTray: PokeballTray; public pbTray: PokeballTray;
public pbTrayEnemy: PokeballTray; public pbTrayEnemy: PokeballTray;
public abilityBar: AbilityBar; public abilityBar: AbilityBar;
@ -320,6 +322,9 @@ export default class BattleScene extends Phaser.Scene {
this.loadAtlas(config.getKey(true), 'trainer'); this.loadAtlas(config.getKey(true), 'trainer');
}); });
// Load character sprites
this.loadAtlas('c_rival_f', 'character', 'rival_f');
// Load pokemon-related images // Load pokemon-related images
this.loadImage(`pkmn__back__sub`, 'pokemon/back', 'sub.png'); this.loadImage(`pkmn__back__sub`, 'pokemon/back', 'sub.png');
this.loadImage(`pkmn__sub`, 'pokemon', 'sub.png'); this.loadImage(`pkmn__sub`, 'pokemon', 'sub.png');
@ -483,6 +488,11 @@ export default class BattleScene extends Phaser.Scene {
this.add.existing(this.enemyModifierBar); this.add.existing(this.enemyModifierBar);
uiContainer.add(this.enemyModifierBar); uiContainer.add(this.enemyModifierBar);
this.charSprite = new CharSprite(this);
this.charSprite.setup();
this.fieldUI.add(this.charSprite);
this.pbTray = new PokeballTray(this, true); this.pbTray = new PokeballTray(this, true);
this.pbTray.setup(); this.pbTray.setup();
@ -850,7 +860,7 @@ export default class BattleScene extends Phaser.Scene {
this.currentBattle = new Battle(this.gameMode, newWaveIndex, newBattleType, newTrainer, newDouble); this.currentBattle = new Battle(this.gameMode, newWaveIndex, newBattleType, newTrainer, newDouble);
this.currentBattle.incrementTurn(this); this.currentBattle.incrementTurn(this);
//this.pushPhase(new TrainerMessageTestPhase(this)); //this.pushPhase(new TrainerMessageTestPhase(this, TrainerType.RIVAL, TrainerType.RIVAL_2, TrainerType.RIVAL_3, TrainerType.RIVAL_4, TrainerType.RIVAL_5, TrainerType.RIVAL_6));
if (!waveIndex && lastBattle) { if (!waveIndex && lastBattle) {
const isNewBiome = !(lastBattle.waveIndex % 10); const isNewBiome = !(lastBattle.waveIndex % 10);

View File

@ -334,7 +334,7 @@ export const trainerTypeDialogue = {
`Hey, I was looking for you! I knew you were eager to get going but I expected at least a goodbye… `Hey, I was looking for you! I knew you were eager to get going but I expected at least a goodbye…
$So you're really pursuing your dream after all?\n I almost can't believe it. $So you're really pursuing your dream after all?\n I almost can't believe it.
$Since we're here, how about a battle?\nAfter all, I want to make sure you're ready. $Since we're here, how about a battle?\nAfter all, I want to make sure you're ready.
$Don't hold back, I want you to give me everything you've got!` $@c{angry_mopen}Don't hold back, I want you to give me everything you've got!`
], ],
victory: [ victory: [
`Wow… You actually cleaned me out.\nAre you actually a beginner? `Wow… You actually cleaned me out.\nAre you actually a beginner?
@ -345,16 +345,16 @@ export const trainerTypeDialogue = {
}, },
{ {
encounter: [ encounter: [
`There you are! I've been looking everywhere for you!\nDid you forget to say goodbye to your best friend? `@c{smile_wave}There you are! I've been looking everywhere for you!\n@c{angry_mopen}Did you forget to say goodbye to your best friend?
$You're going after your dream, huh?\nThat day is really today isn't it $@c{smile_ehalf}You're going after your dream, huh?\nThat day is really today isn't it
$Anyway, I'll forgive you for forgetting me, but on one condition. You have to battle me! $@c{smile}Anyway, I'll forgive you for forgetting me, but on one condition. @c{smile_wave_wink}You have to battle me!
$Give it your all! Wouldn't want your adventure to be over before it started, right?` $@c{angry_mopen}Give it your all! Wouldn't want your adventure to be over before it started, right?`
], ],
victory: [ victory: [
`You just started and you're already this strong?!\nYou totally cheated, didn't you? `@c{shock}You just started and you're already this strong?!\n@c{angry}@d{96}You totally cheated, didn't you?
$Just kidding! I lost fair and square I have a feeling you're going to do really well out there. $@c{smile_wave_wink}Just kidding! @d{64}@c{smile_eclosed}I lost fair and square I have a feeling you're going to do really well out there.
$By the way, the professor wanted me to give you some items. Hopefully they're helpful! $@c{smile}By the way, the professor wanted me to give you some items. Hopefully they're helpful!
$Do your best like always! I believe in you!` $@c{smile_wave}Do your best like always! I believe in you!`
] ]
} }
], ],
@ -373,14 +373,14 @@ export const trainerTypeDialogue = {
}, },
{ {
encounter: [ encounter: [
`Oh, fancy meeting you here. Looks like you're still undefeated. Huh… Not bad! `@c{smile_wave}Oh, fancy meeting you here. Looks like you're still undefeated. @c{angry_mopen}Huh… Not bad!
$I know what you're thinking, and no, I wasn't creeping on you. I just happened to be in the area. $@c{angry_mopen}I know what you're thinking, and no, I wasn't creeping on you. @c{smile_eclosed}I just happened to be in the area.
$I'm happy for you but I just want to let you know that it's OK to lose sometimes. $@c{smile_ehalf}I'm happy for you but I just want to let you know that it's OK to lose sometimes.
$We learn from our mistakes, often more than we would if we kept succeeding. $@c{smile}We learn from our mistakes, often more than we would if we kept succeeding.
$In any case, I've been training hard for our rematch, so you'd better give it your all!` $@c{angry_mopen}In any case, I've been training hard for our rematch, so you'd better give it your all!`
], ],
victory: [ victory: [
`I… wasn't supposed to lose that time…` `@c{neutral}I… wasn't supposed to lose that time…`
] ]
} }
], ],
@ -400,13 +400,13 @@ export const trainerTypeDialogue = {
}, },
{ {
encounter: [ encounter: [
`Long time no see! Still haven't lost, huh.\nYou're starting to get on my nerves. Just kidding! `@c{smile_wave}Long time no see! Still haven't lost, huh.\n@c{angry}You're starting to get on my nerves. @c{smile_wave_wink}Just kidding!
$But really, don't you miss home by now? Or… me?\nI… I mean, we've really missed you. $@c{smile_ehalf}But really, don't you miss home by now? Or… me?\nI… I mean, we've really missed you.
$I support you in your dream and everything, but the reality is you're going to lose sooner or later. $@c{smile_eclosed}I support you in your dream and everything, but the reality is you're going to lose sooner or later.
$And when you do, I'll be there for you like always.\nNow, let me show you how strong I've become!` $@c{smile}And when you do, I'll be there for you like always.\n@c{angry_mopen}Now, let me show you how strong I've become!`
], ],
victory: [ victory: [
`After all that… it wasn't enough…?\nYou'll never come back at this rate…` `@c{shock}After all that… it wasn't enough…?\nYou'll never come back at this rate…`
] ]
} }
], ],
@ -428,17 +428,17 @@ export const trainerTypeDialogue = {
}, },
{ {
encounter: [ encounter: [
`It's me! You didn't forget about me again… did you? `@c{neutral}It's me! You didn't forget about me again… did you?
$You should be proud of how far you made it. Congrats!\nBut it looks like it's the end of your journey. $@c{smile}You should be proud of how far you made it. Congrats!\nBut it looks like it's the end of your journey.
$You've awoken something in me I never knew was there.\nIt seems like all I do now is train. $@c{smile_eclosed}You've awoken something in me I never knew was there.\nIt seems like all I do now is train.
$I hardly even eat or sleep now, I just train my Pokémon all day, getting stronger every time. $@c{smile_ehalf}I hardly even eat or sleep now, I just train my Pokémon all day, getting stronger every time.
$In fact, I hardly recognize myself. $@c{neutral}In fact, I hardly recognize myself.
$And now, I've finally reached peak performance.\nI don't think anyone could beat me now. $And now, I've finally reached peak performance.\nI don't think anyone could beat me now.
$And you know what? It's all because of you.\nI don't know whether to thank you or hate you. $And you know what? It's all because of you.\n@c{smile_ehalf}I don't know whether to thank you or hate you.
$Prepare yourself.` $@c{angry_mopen}Prepare yourself.`
], ],
victory: [ victory: [
`What…@d{64} What are you?` `@c{neutral}What…@d{64} What are you?`
] ]
} }
], ],
@ -470,25 +470,25 @@ export const trainerTypeDialogue = {
}, },
{ {
encounter: [ encounter: [
`So it's just us again. `@c{smile_ehalf}So it's just us again.
$You know, I keep going around and around in my head $@c{smile_eclosed}You know, I keep going around and around in my head
$There's something to all this, why everything seems so strange now $@c{smile_ehalf}There's something to all this, why everything seems so strange now
$You have your dream, and I have this ambition in me $@c{smile}You have your dream, and I have this ambition in me
$I just can't help but feel there's a greater purpose to all this, to what we're doing, you and I. $I just can't help but feel there's a greater purpose to all this, to what we're doing, you and I.
$I think I'm supposed to push you to your limits. $@c{smile_eclosed}I think I'm supposed to push you to your limits.
$I'm not sure if I've been doing a good job at that, but I've tried my best up to now. $@c{smile_ehalf}I'm not sure if I've been doing a good job at that, but I've tried my best up to now.
$It's something about this strange and dreadful place Everything seems so clear $It's something about this strange and dreadful place Everything seems so clear
$This is all the world's known for a long time now. $This is all the world's known for a long time now.
$It's like I can barely remember the memories we cherished together. $@c{smile_eclosed}It's like I can barely remember the memories we cherished together.
$Were they even real? They seem so far away now $@c{smile_ehalf}Were they even real? They seem so far away now
$You need to keep pushing, because if you don't, it will never end. You're the only one who can do this. $@c{angry_mopen}You need to keep pushing, because if you don't, it will never end. You're the only one who can do this.
$I don't know what all this means… but I feel it's true. $I don't know what all this means… but I feel it's true.
$If you can't defeat me here and now, you won't stand a chance.` $If you can't defeat me here and now, you won't stand a chance.`
], ],
victory: [ victory: [
`I… I think I fulfilled my purpose… `@c{smile_ehalf}I… I think I fulfilled my purpose…
$Promise me After you heal the world Please come home safe. $@c{smile_eclosed}Promise me After you heal the world Please come home safe.
$Thank you.` $@c{smile_ehalf}Thank you.`
] ]
} }
] ]

View File

@ -176,6 +176,7 @@ export class TrainerConfig {
public nameFemale: string; public nameFemale: string;
public title: string; public title: string;
public hasGenders: boolean = false; public hasGenders: boolean = false;
public hasCharSprite: boolean = false;
public isDouble: boolean = false; public isDouble: boolean = false;
public moneyMultiplier: number = 1; public moneyMultiplier: number = 1;
public isBoss: boolean = false; public isBoss: boolean = false;
@ -257,6 +258,11 @@ export class TrainerConfig {
return this; return this;
} }
setHasCharSprite(): TrainerConfig {
this.hasCharSprite = true;
return this;
}
setDouble(): TrainerConfig { setDouble(): TrainerConfig {
this.isDouble = true; this.isDouble = true;
return this; return this;
@ -763,19 +769,19 @@ export const trainerConfigs: TrainerConfigs = {
[TrainerType.NEMONA]: new TrainerConfig(++t).initForChampion([ Species.LYCANROC, Species.KORAIDON, Species.KOMMO_O, Species.PAWMOT, Species.DUSKNOIR ]), [TrainerType.NEMONA]: new TrainerConfig(++t).initForChampion([ Species.LYCANROC, Species.KORAIDON, Species.KOMMO_O, Species.PAWMOT, Species.DUSKNOIR ]),
[TrainerType.KIERAN]: new TrainerConfig(++t).initForChampion([ Species.POLITOED, Species.TERAPAGOS, Species.HYDRAPPLE, Species.PORYGON_Z, Species.GRIMMSNARL ]), [TrainerType.KIERAN]: new TrainerConfig(++t).initForChampion([ Species.POLITOED, Species.TERAPAGOS, Species.HYDRAPPLE, Species.PORYGON_Z, Species.GRIMMSNARL ]),
[TrainerType.RIVAL]: new TrainerConfig((t = TrainerType.RIVAL)).setName('Finn').setHasGenders('Ivy').setTitle('Rival').setStaticParty().setEncounterBgm(TrainerType.RIVAL).setBattleBgm('battle_rival').setPartyTemplates(trainerPartyTemplates.RIVAL) [TrainerType.RIVAL]: new TrainerConfig((t = TrainerType.RIVAL)).setName('Finn').setHasGenders('Ivy').setHasCharSprite().setTitle('Rival').setStaticParty().setEncounterBgm(TrainerType.RIVAL).setBattleBgm('battle_rival').setPartyTemplates(trainerPartyTemplates.RIVAL)
.setModifierRewardFuncs(() => modifierTypes.SUPER_EXP_CHARM, () => modifierTypes.EXP_SHARE).setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.BULBASAUR, Species.CHARMANDER, Species.SQUIRTLE, Species.CHIKORITA, Species.CYNDAQUIL, Species.TOTODILE, Species.TREECKO, Species.TORCHIC, Species.MUDKIP, Species.TURTWIG, Species.CHIMCHAR, Species.PIPLUP, Species.SNIVY, Species.TEPIG, Species.OSHAWOTT, Species.CHESPIN, Species.FENNEKIN, Species.FROAKIE, Species.ROWLET, Species.LITTEN, Species.POPPLIO, Species.GROOKEY, Species.SCORBUNNY, Species.SOBBLE, Species.SPRIGATITO, Species.FUECOCO, Species.QUAXLY ])) .setModifierRewardFuncs(() => modifierTypes.SUPER_EXP_CHARM, () => modifierTypes.EXP_SHARE).setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.BULBASAUR, Species.CHARMANDER, Species.SQUIRTLE, Species.CHIKORITA, Species.CYNDAQUIL, Species.TOTODILE, Species.TREECKO, Species.TORCHIC, Species.MUDKIP, Species.TURTWIG, Species.CHIMCHAR, Species.PIPLUP, Species.SNIVY, Species.TEPIG, Species.OSHAWOTT, Species.CHESPIN, Species.FENNEKIN, Species.FROAKIE, Species.ROWLET, Species.LITTEN, Species.POPPLIO, Species.GROOKEY, Species.SCORBUNNY, Species.SOBBLE, Species.SPRIGATITO, Species.FUECOCO, Species.QUAXLY ]))
.setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.PIDGEY, Species.HOOTHOOT, Species.TAILLOW, Species.STARLY, Species.PIDOVE, Species.FLETCHLING, Species.PIKIPEK, Species.ROOKIDEE, Species.WATTREL ])), .setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.PIDGEY, Species.HOOTHOOT, Species.TAILLOW, Species.STARLY, Species.PIDOVE, Species.FLETCHLING, Species.PIKIPEK, Species.ROOKIDEE, Species.WATTREL ])),
[TrainerType.RIVAL_2]: new TrainerConfig(++t).setName('Finn').setHasGenders('Ivy').setTitle('Rival').setStaticParty().setMoneyMultiplier(1.25).setEncounterBgm(TrainerType.RIVAL).setBattleBgm('battle_rival').setPartyTemplates(trainerPartyTemplates.RIVAL_2) [TrainerType.RIVAL_2]: new TrainerConfig(++t).setName('Finn').setHasGenders('Ivy').setHasCharSprite().setTitle('Rival').setStaticParty().setMoneyMultiplier(1.25).setEncounterBgm(TrainerType.RIVAL).setBattleBgm('battle_rival').setPartyTemplates(trainerPartyTemplates.RIVAL_2)
.setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.IVYSAUR, Species.CHARMELEON, Species.WARTORTLE, Species.BAYLEEF, Species.QUILAVA, Species.CROCONAW, Species.GROVYLE, Species.COMBUSKEN, Species.MARSHTOMP, Species.GROTLE, Species.MONFERNO, Species.PRINPLUP, Species.SERVINE, Species.PIGNITE, Species.DEWOTT, Species.QUILLADIN, Species.BRAIXEN, Species.FROGADIER, Species.DARTRIX, Species.TORRACAT, Species.BRIONNE, Species.THWACKEY, Species.RABOOT, Species.DRIZZILE, Species.FLORAGATO, Species.CROCALOR, Species.QUAXWELL ])) .setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.IVYSAUR, Species.CHARMELEON, Species.WARTORTLE, Species.BAYLEEF, Species.QUILAVA, Species.CROCONAW, Species.GROVYLE, Species.COMBUSKEN, Species.MARSHTOMP, Species.GROTLE, Species.MONFERNO, Species.PRINPLUP, Species.SERVINE, Species.PIGNITE, Species.DEWOTT, Species.QUILLADIN, Species.BRAIXEN, Species.FROGADIER, Species.DARTRIX, Species.TORRACAT, Species.BRIONNE, Species.THWACKEY, Species.RABOOT, Species.DRIZZILE, Species.FLORAGATO, Species.CROCALOR, Species.QUAXWELL ]))
.setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.PIDGEOTTO, Species.HOOTHOOT, Species.TAILLOW, Species.STARAVIA, Species.TRANQUILL, Species.FLETCHINDER, Species.TRUMBEAK, Species.CORVISQUIRE, Species.WATTREL ])) .setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.PIDGEOTTO, Species.HOOTHOOT, Species.TAILLOW, Species.STARAVIA, Species.TRANQUILL, Species.FLETCHINDER, Species.TRUMBEAK, Species.CORVISQUIRE, Species.WATTREL ]))
.setPartyMemberFunc(2, getSpeciesFilterRandomPartyMemberFunc((species: PokemonSpecies) => !pokemonEvolutions.hasOwnProperty(species.speciesId) && !pokemonPrevolutions.hasOwnProperty(species.speciesId) && species.baseTotal >= 450)), .setPartyMemberFunc(2, getSpeciesFilterRandomPartyMemberFunc((species: PokemonSpecies) => !pokemonEvolutions.hasOwnProperty(species.speciesId) && !pokemonPrevolutions.hasOwnProperty(species.speciesId) && species.baseTotal >= 450)),
[TrainerType.RIVAL_3]: new TrainerConfig(++t).setName('Finn').setHasGenders('Ivy').setTitle('Rival').setStaticParty().setMoneyMultiplier(1.5).setEncounterBgm(TrainerType.RIVAL).setBattleBgm('battle_rival').setPartyTemplates(trainerPartyTemplates.RIVAL_3) [TrainerType.RIVAL_3]: new TrainerConfig(++t).setName('Finn').setHasGenders('Ivy').setHasCharSprite().setTitle('Rival').setStaticParty().setMoneyMultiplier(1.5).setEncounterBgm(TrainerType.RIVAL).setBattleBgm('battle_rival').setPartyTemplates(trainerPartyTemplates.RIVAL_3)
.setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.VENUSAUR, Species.CHARIZARD, Species.BLASTOISE, Species.MEGANIUM, Species.TYPHLOSION, Species.FERALIGATR, Species.SCEPTILE, Species.BLAZIKEN, Species.SWAMPERT, Species.TORTERRA, Species.INFERNAPE, Species.EMPOLEON, Species.SERPERIOR, Species.EMBOAR, Species.SAMUROTT, Species.CHESNAUGHT, Species.DELPHOX, Species.GRENINJA, Species.DECIDUEYE, Species.INCINEROAR, Species.PRIMARINA, Species.RILLABOOM, Species.CINDERACE, Species.INTELEON, Species.MEOWSCARADA, Species.SKELEDIRGE, Species.QUAQUAVAL ])) .setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.VENUSAUR, Species.CHARIZARD, Species.BLASTOISE, Species.MEGANIUM, Species.TYPHLOSION, Species.FERALIGATR, Species.SCEPTILE, Species.BLAZIKEN, Species.SWAMPERT, Species.TORTERRA, Species.INFERNAPE, Species.EMPOLEON, Species.SERPERIOR, Species.EMBOAR, Species.SAMUROTT, Species.CHESNAUGHT, Species.DELPHOX, Species.GRENINJA, Species.DECIDUEYE, Species.INCINEROAR, Species.PRIMARINA, Species.RILLABOOM, Species.CINDERACE, Species.INTELEON, Species.MEOWSCARADA, Species.SKELEDIRGE, Species.QUAQUAVAL ]))
.setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.PIDGEOT, Species.NOCTOWL, Species.SWELLOW, Species.STARAPTOR, Species.UNFEZANT, Species.TALONFLAME, Species.TOUCANNON, Species.CORVIKNIGHT, Species.KILOWATTREL ])) .setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.PIDGEOT, Species.NOCTOWL, Species.SWELLOW, Species.STARAPTOR, Species.UNFEZANT, Species.TALONFLAME, Species.TOUCANNON, Species.CORVIKNIGHT, Species.KILOWATTREL ]))
.setPartyMemberFunc(2, getSpeciesFilterRandomPartyMemberFunc((species: PokemonSpecies) => !pokemonEvolutions.hasOwnProperty(species.speciesId) && !pokemonPrevolutions.hasOwnProperty(species.speciesId) && species.baseTotal >= 450)) .setPartyMemberFunc(2, getSpeciesFilterRandomPartyMemberFunc((species: PokemonSpecies) => !pokemonEvolutions.hasOwnProperty(species.speciesId) && !pokemonPrevolutions.hasOwnProperty(species.speciesId) && species.baseTotal >= 450))
.setSpeciesFilter(species => species.baseTotal >= 540), .setSpeciesFilter(species => species.baseTotal >= 540),
[TrainerType.RIVAL_4]: new TrainerConfig(++t).setName('Finn').setHasGenders('Ivy').setTitle('Rival').setBoss().setStaticParty().setMoneyMultiplier(1.75).setEncounterBgm(TrainerType.RIVAL).setBattleBgm('battle_rival_2').setPartyTemplates(trainerPartyTemplates.RIVAL_4) [TrainerType.RIVAL_4]: new TrainerConfig(++t).setName('Finn').setHasGenders('Ivy').setHasCharSprite().setTitle('Rival').setBoss().setStaticParty().setMoneyMultiplier(1.75).setEncounterBgm(TrainerType.RIVAL).setBattleBgm('battle_rival_2').setPartyTemplates(trainerPartyTemplates.RIVAL_4)
.setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.VENUSAUR, Species.CHARIZARD, Species.BLASTOISE, Species.MEGANIUM, Species.TYPHLOSION, Species.FERALIGATR, Species.SCEPTILE, Species.BLAZIKEN, Species.SWAMPERT, Species.TORTERRA, Species.INFERNAPE, Species.EMPOLEON, Species.SERPERIOR, Species.EMBOAR, Species.SAMUROTT, Species.CHESNAUGHT, Species.DELPHOX, Species.GRENINJA, Species.DECIDUEYE, Species.INCINEROAR, Species.PRIMARINA, Species.RILLABOOM, Species.CINDERACE, Species.INTELEON, Species.MEOWSCARADA, Species.SKELEDIRGE, Species.QUAQUAVAL ])) .setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.VENUSAUR, Species.CHARIZARD, Species.BLASTOISE, Species.MEGANIUM, Species.TYPHLOSION, Species.FERALIGATR, Species.SCEPTILE, Species.BLAZIKEN, Species.SWAMPERT, Species.TORTERRA, Species.INFERNAPE, Species.EMPOLEON, Species.SERPERIOR, Species.EMBOAR, Species.SAMUROTT, Species.CHESNAUGHT, Species.DELPHOX, Species.GRENINJA, Species.DECIDUEYE, Species.INCINEROAR, Species.PRIMARINA, Species.RILLABOOM, Species.CINDERACE, Species.INTELEON, Species.MEOWSCARADA, Species.SKELEDIRGE, Species.QUAQUAVAL ]))
.setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.PIDGEOT, Species.NOCTOWL, Species.SWELLOW, Species.STARAPTOR, Species.UNFEZANT, Species.TALONFLAME, Species.TOUCANNON, Species.CORVIKNIGHT, Species.KILOWATTREL ])) .setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.PIDGEOT, Species.NOCTOWL, Species.SWELLOW, Species.STARAPTOR, Species.UNFEZANT, Species.TALONFLAME, Species.TOUCANNON, Species.CORVIKNIGHT, Species.KILOWATTREL ]))
.setPartyMemberFunc(2, getSpeciesFilterRandomPartyMemberFunc((species: PokemonSpecies) => !pokemonEvolutions.hasOwnProperty(species.speciesId) && !pokemonPrevolutions.hasOwnProperty(species.speciesId) && species.baseTotal >= 450)) .setPartyMemberFunc(2, getSpeciesFilterRandomPartyMemberFunc((species: PokemonSpecies) => !pokemonEvolutions.hasOwnProperty(species.speciesId) && !pokemonPrevolutions.hasOwnProperty(species.speciesId) && species.baseTotal >= 450))
@ -784,7 +790,7 @@ export const trainerConfigs: TrainerConfigs = {
const starter = party[0]; const starter = party[0];
return [ modifierTypes.TERA_SHARD().generateType(null, [ starter.species.type1 ]).withIdFromFunc(modifierTypes.TERA_SHARD).newModifier(starter) as PersistentModifier ]; return [ modifierTypes.TERA_SHARD().generateType(null, [ starter.species.type1 ]).withIdFromFunc(modifierTypes.TERA_SHARD).newModifier(starter) as PersistentModifier ];
}), }),
[TrainerType.RIVAL_5]: new TrainerConfig(++t).setName('Finn').setHasGenders('Ivy').setTitle('Rival').setBoss().setStaticParty().setMoneyMultiplier(2.25).setEncounterBgm(TrainerType.RIVAL).setBattleBgm('battle_rival_3').setPartyTemplates(trainerPartyTemplates.RIVAL_5) [TrainerType.RIVAL_5]: new TrainerConfig(++t).setName('Finn').setHasGenders('Ivy').setHasCharSprite().setTitle('Rival').setBoss().setStaticParty().setMoneyMultiplier(2.25).setEncounterBgm(TrainerType.RIVAL).setBattleBgm('battle_rival_3').setPartyTemplates(trainerPartyTemplates.RIVAL_5)
.setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.VENUSAUR, Species.CHARIZARD, Species.BLASTOISE, Species.MEGANIUM, Species.TYPHLOSION, Species.FERALIGATR, Species.SCEPTILE, Species.BLAZIKEN, Species.SWAMPERT, Species.TORTERRA, Species.INFERNAPE, Species.EMPOLEON, Species.SERPERIOR, Species.EMBOAR, Species.SAMUROTT, Species.CHESNAUGHT, Species.DELPHOX, Species.GRENINJA, Species.DECIDUEYE, Species.INCINEROAR, Species.PRIMARINA, Species.RILLABOOM, Species.CINDERACE, Species.INTELEON, Species.MEOWSCARADA, Species.SKELEDIRGE, Species.QUAQUAVAL ])) .setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.VENUSAUR, Species.CHARIZARD, Species.BLASTOISE, Species.MEGANIUM, Species.TYPHLOSION, Species.FERALIGATR, Species.SCEPTILE, Species.BLAZIKEN, Species.SWAMPERT, Species.TORTERRA, Species.INFERNAPE, Species.EMPOLEON, Species.SERPERIOR, Species.EMBOAR, Species.SAMUROTT, Species.CHESNAUGHT, Species.DELPHOX, Species.GRENINJA, Species.DECIDUEYE, Species.INCINEROAR, Species.PRIMARINA, Species.RILLABOOM, Species.CINDERACE, Species.INTELEON, Species.MEOWSCARADA, Species.SKELEDIRGE, Species.QUAQUAVAL ]))
.setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.PIDGEOT, Species.NOCTOWL, Species.SWELLOW, Species.STARAPTOR, Species.UNFEZANT, Species.TALONFLAME, Species.TOUCANNON, Species.CORVIKNIGHT, Species.KILOWATTREL ])) .setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.PIDGEOT, Species.NOCTOWL, Species.SWELLOW, Species.STARAPTOR, Species.UNFEZANT, Species.TALONFLAME, Species.TOUCANNON, Species.CORVIKNIGHT, Species.KILOWATTREL ]))
.setPartyMemberFunc(2, getSpeciesFilterRandomPartyMemberFunc((species: PokemonSpecies) => !pokemonEvolutions.hasOwnProperty(species.speciesId) && !pokemonPrevolutions.hasOwnProperty(species.speciesId) && species.baseTotal >= 450)) .setPartyMemberFunc(2, getSpeciesFilterRandomPartyMemberFunc((species: PokemonSpecies) => !pokemonEvolutions.hasOwnProperty(species.speciesId) && !pokemonPrevolutions.hasOwnProperty(species.speciesId) && species.baseTotal >= 450))
@ -797,7 +803,7 @@ export const trainerConfigs: TrainerConfigs = {
const starter = party[0]; const starter = party[0];
return [ modifierTypes.TERA_SHARD().generateType(null, [ starter.species.type1 ]).withIdFromFunc(modifierTypes.TERA_SHARD).newModifier(starter) as PersistentModifier ]; return [ modifierTypes.TERA_SHARD().generateType(null, [ starter.species.type1 ]).withIdFromFunc(modifierTypes.TERA_SHARD).newModifier(starter) as PersistentModifier ];
}), }),
[TrainerType.RIVAL_6]: new TrainerConfig(++t).setName('Finn').setHasGenders('Ivy').setTitle('Rival').setBoss().setStaticParty().setMoneyMultiplier(3).setEncounterBgm('final').setBattleBgm('battle_rival_3').setPartyTemplates(trainerPartyTemplates.RIVAL_6) [TrainerType.RIVAL_6]: new TrainerConfig(++t).setName('Finn').setHasGenders('Ivy').setHasCharSprite().setTitle('Rival').setBoss().setStaticParty().setMoneyMultiplier(3).setEncounterBgm('final').setBattleBgm('battle_rival_3').setPartyTemplates(trainerPartyTemplates.RIVAL_6)
.setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.VENUSAUR, Species.CHARIZARD, Species.BLASTOISE, Species.MEGANIUM, Species.TYPHLOSION, Species.FERALIGATR, Species.SCEPTILE, Species.BLAZIKEN, Species.SWAMPERT, Species.TORTERRA, Species.INFERNAPE, Species.EMPOLEON, Species.SERPERIOR, Species.EMBOAR, Species.SAMUROTT, Species.CHESNAUGHT, Species.DELPHOX, Species.GRENINJA, Species.DECIDUEYE, Species.INCINEROAR, Species.PRIMARINA, Species.RILLABOOM, Species.CINDERACE, Species.INTELEON ])) .setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.VENUSAUR, Species.CHARIZARD, Species.BLASTOISE, Species.MEGANIUM, Species.TYPHLOSION, Species.FERALIGATR, Species.SCEPTILE, Species.BLAZIKEN, Species.SWAMPERT, Species.TORTERRA, Species.INFERNAPE, Species.EMPOLEON, Species.SERPERIOR, Species.EMBOAR, Species.SAMUROTT, Species.CHESNAUGHT, Species.DELPHOX, Species.GRENINJA, Species.DECIDUEYE, Species.INCINEROAR, Species.PRIMARINA, Species.RILLABOOM, Species.CINDERACE, Species.INTELEON ]))
.setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.PIDGEOT, Species.NOCTOWL, Species.SWELLOW, Species.STARAPTOR, Species.UNFEZANT, Species.TALONFLAME, Species.TOUCANNON, Species.CORVIKNIGHT ])) .setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.PIDGEOT, Species.NOCTOWL, Species.SWELLOW, Species.STARAPTOR, Species.UNFEZANT, Species.TALONFLAME, Species.TOUCANNON, Species.CORVIKNIGHT ]))
.setPartyMemberFunc(2, getSpeciesFilterRandomPartyMemberFunc((species: PokemonSpecies) => !pokemonEvolutions.hasOwnProperty(species.speciesId) && !pokemonPrevolutions.hasOwnProperty(species.speciesId) && species.baseTotal >= 450)) .setPartyMemberFunc(2, getSpeciesFilterRandomPartyMemberFunc((species: PokemonSpecies) => !pokemonEvolutions.hasOwnProperty(species.speciesId) && !pokemonPrevolutions.hasOwnProperty(species.speciesId) && species.baseTotal >= 450))

View File

@ -620,9 +620,17 @@ export class EncounterPhase extends BattlePhase {
if (!encounterMessages?.length) if (!encounterMessages?.length)
doSummon(); doSummon();
else { else {
const showDialogueAndSummon = () => {
let message: string; let message: string;
this.scene.executeWithSeedOffset(() => message = Utils.randSeedItem(encounterMessages), this.scene.currentBattle.waveIndex); this.scene.executeWithSeedOffset(() => message = Utils.randSeedItem(encounterMessages), this.scene.currentBattle.waveIndex);
this.scene.ui.showDialogue(message, trainer.getName(), null, doSummon); this.scene.ui.showDialogue(message, trainer.getName(), null, () => {
this.scene.charSprite.hide().then(() => this.scene.hideFieldOverlay(250).then(() => doSummon()));
});
};
if (this.scene.currentBattle.trainer.config.hasCharSprite)
this.scene.showFieldOverlay(500).then(() => this.scene.charSprite.showCharacter(trainer.getKey(), 'smile').then(() => showDialogueAndSummon()));
else
showDialogueAndSummon();
} }
} }
} }

106
src/ui/char-sprite.ts Normal file
View File

@ -0,0 +1,106 @@
import BattleScene from "../battle-scene";
export default class CharSprite extends Phaser.GameObjects.Container {
private sprite: Phaser.GameObjects.Sprite;
private transitionSprite: Phaser.GameObjects.Sprite;
public key: string;
public variant: string;
public shown: boolean;
constructor(scene: BattleScene) {
super(scene, (scene.game.canvas.width / 6) + 32, -42);
}
setup(): void {
[ this.sprite, this.transitionSprite ] = new Array(2).fill(null).map(() => {
const ret = this.scene.add.sprite(0, 0, '', '');
ret.setOrigin(0.5, 1);
this.add(ret);
return ret;
});
this.transitionSprite.setVisible(false);
this.setVisible(false);
this.shown = false;
}
showCharacter(key: string, variant: string): Promise<void> {
return new Promise(resolve => {
if (!key.startsWith('c_'))
key = `c_${key}`;
if (this.shown) {
if (key === this.key && variant === this.variant)
return resolve();
if (key !== this.key)
return this.hide().then(() => this.showCharacter(key, variant));
this.setVariant(variant).then(() => resolve());
return;
}
this.sprite.setTexture(key, variant);
(this.scene as BattleScene).fieldUI.bringToTop(this);
this.scene.tweens.add({
targets: this,
x: (this.scene.game.canvas.width / 6) - 102,
duration: 750,
ease: 'Cubic.easeOut',
onComplete: () => {
resolve();
}
});
this.setVisible(this.scene.textures.get(key).key !== '__MISSING');
this.shown = true;
this.key = key;
this.variant = variant;
});
}
setVariant(variant: string): Promise<void> {
return new Promise(resolve => {
(this.scene as BattleScene).fieldUI.bringToTop(this);
this.transitionSprite.setTexture(this.key, variant);
this.transitionSprite.setAlpha(0);
this.transitionSprite.setVisible(true);
this.scene.tweens.add({
targets: this.transitionSprite,
alpha: 1,
duration: 250,
ease: 'Sine.easeIn',
onComplete: () => {
this.sprite.setTexture(this.key, variant);
this.transitionSprite.setVisible(false);
resolve();
}
});
this.variant = variant;
});
}
hide(): Promise<void> {
return new Promise(resolve => {
if (!this.shown)
return resolve();
this.scene.tweens.add({
targets: this,
x: (this.scene.game.canvas.width / 6) + 32,
duration: 750,
ease: 'Cubic.easeIn',
onComplete: () => {
if (!this.shown)
this.setVisible(false);
resolve();
}
});
this.shown = false;
});
};
}

View File

@ -28,12 +28,16 @@ export default abstract class MessageUiHandler extends AwaitableUiHandler {
private showTextInternal(text: string, delay: integer, callback: Function, callbackDelay: integer, prompt: boolean, promptDelay: integer) { private showTextInternal(text: string, delay: integer, callback: Function, callbackDelay: integer, prompt: boolean, promptDelay: integer) {
if (delay === null || delay === undefined) if (delay === null || delay === undefined)
delay = 20; delay = 20;
let charVarMap = new Map<integer, string>();
let delayMap = new Map<integer, integer>(); let delayMap = new Map<integer, integer>();
let soundMap = new Map<integer, string>(); let soundMap = new Map<integer, string>();
const actionPattern = /@(d|s)\{(.*?)\}/; const actionPattern = /@(c|d|s)\{(.*?)\}/;
let actionMatch: RegExpExecArray; let actionMatch: RegExpExecArray;
while ((actionMatch = actionPattern.exec(text))) { while ((actionMatch = actionPattern.exec(text))) {
switch (actionMatch[1]) { switch (actionMatch[1]) {
case 'c':
charVarMap.set(actionMatch.index, actionMatch[2]);
break;
case 'd': case 'd':
delayMap.set(actionMatch.index, parseInt(actionMatch[2])); delayMap.set(actionMatch.index, parseInt(actionMatch[2]));
break; break;
@ -67,10 +71,13 @@ export default abstract class MessageUiHandler extends AwaitableUiHandler {
delay: delay, delay: delay,
callback: () => { callback: () => {
const charIndex = text.length - this.textTimer.repeatCount; const charIndex = text.length - this.textTimer.repeatCount;
const charVar = charVarMap.get(charIndex);
const charSound = soundMap.get(charIndex); const charSound = soundMap.get(charIndex);
const charDelay = delayMap.get(charIndex); const charDelay = delayMap.get(charIndex);
this.message.setText(text.slice(0, charIndex)); this.message.setText(text.slice(0, charIndex));
const advance = () => { const advance = () => {
if (charVar)
this.scene.charSprite.setVariant(charVar);
if (charSound) if (charSound)
this.scene.playSound(charSound); this.scene.playSound(charSound);
if (callback && !this.textTimer.repeatCount) { if (callback && !this.textTimer.repeatCount) {