From 7c8aed50cd3b0ab22f5ef57167db95b09288888d Mon Sep 17 00:00:00 2001 From: ARSOD-Z <75585461+ARSOD-Z@users.noreply.github.com> Date: Wed, 10 Apr 2024 23:39:42 -0300 Subject: [PATCH 01/10] trainer dialogue (#81) --- src/data/dialogue.ts | 1670 +++++++++++++++++++++++++++++++++++- src/data/trainer-config.ts | 2 +- 2 files changed, 1663 insertions(+), 9 deletions(-) diff --git a/src/data/dialogue.ts b/src/data/dialogue.ts index 3e7be0dbc61..dc1b346d513 100644 --- a/src/data/dialogue.ts +++ b/src/data/dialogue.ts @@ -18,24 +18,323 @@ export const trainerTypeDialogue = { encounter: [ `Hey, wanna battle?`, `Are you a new trainer too?`, - `Hey, I haven't seen you before. Let's battle!` + `Hey, I haven't seen you before. Let's battle!`, + `I just lost, so I'm trying to find more Pokémon.\nWait! You look weak! Come on, let's battle!`, + `Have we met or not? I don't really remember. Well, I guess it's nice to meet you anyway!`, + `All right! Let's go!`, + `All right! Here I come! I'll show you my power!`, + `Haw haw haw... I'll show you how hawesome my Pokémon are!`, + `No need to waste time saying hello. Bring it on whenever you're ready!`, + `Don't let your guard down, or you may be crying when a kid beats you.`, + `I've raised my Pokémon with great care. You're not allowed to hurt them!`, + `Glad you made it! It won't be an easy job from here.`, + `The battles continue forever! Welcome to the world with no end!` ], victory: [ `Wow! You're strong!`, - `I didn't stand a chance, huh.`, - `I'll find you again when I'm older and beat you!` + `I didn't stand a chance, huh?`, + `I'll find you again when I'm older and beat you!`, + `Ugh. I don't have any more Pokémon.`, + `No way… NO WAY! How could I lose again…`, + `No! I lost!`, + `Whoa! You are incredible! I'm amazed and surprised!`, + `Could it be… How… My Pokémon and I are the strongest, though…`, + `I won't lose next time! Let's battle again sometime!`, + `Sheesh! Can't you see that I'm just a kid! It wasn't fair of you to go all out like that!`, + `Your Pokémon are more amazing! Trade with me!`, + `I got a little carried away earlier, but what job was I talking about?`, + `Ahaha! There it is! That's right! You're already right at home in this world!` ] }, + //LASS { encounter: [ `Let's have a battle, shall we?`, `You look like a new trainer. Let's have a battle!`, - `I don't recognize you. How about a battle?` + `I don't recognize you. How about a battle?`, + `Let's have a fun Pokémon battle!`, + `I'll show you the ropes of how to really use Pokémon!`, + `A serious battle starts from a serious beginning! Are you sure you're ready?`, + `You're only young once. And you only get one shot at a given battle. Soon, you'll be nothing but a memory.`, + `You'd better go easy on me, OK? Though I'll be seriously fighting!` ], victory: [ `That was impressive! I've got a lot to learn.`, `I didn't think you'd beat me that bad…`, - `I hope we get to have a rematch some day.` + `I hope we get to have a rematch some day.`, + `That was pretty amazingly fun! You've totally exhausted me…`, + `You actually taught me a lesson! You're pretty amazing!`, + `Seriously, I lost. That is, like, seriously depressing, but you were seriously cool.`, + `I don't need memories like this. Deleting memory…`, + `Hey! I told you to go easy on me! Still, you're pretty cool when you're serious.` + ] + } + ], + [TrainerType.BREEDER]: [ + { + encounter: [ + `Obedient Pokémon, selfish Pokémon… Pokémon have unique characteristics.`, + `Even though my upbringing and behavior are poor, I've raised my Pokémon well.`, + `Hmm, do you discipline your Pokémon? Pampering them too much is no good.`, + ], + victory: [ + `I am happy! Happy, I tell you! Don't look at me like that!`, + `You don't seem to need any tips for training good Pokémon.`, + `The hardest part of this job is saying farewell to Pokémon.`, + ] + }, + { + encounter: [ + `Pokémon never betray you. They return all the love you give them.`, + `Shall I give you a tip for training good Pokémon?`, + `I have raised these very special Pokémon using a special method.` + ], + victory: [ + `Ugh… It wasn't supposed to be like this. Did I administer the wrong blend?`, + `How could that happen to my Pokémon… What are you feeding your Pokémon?`, + `If I lose, that tells you I was just killing time. It doesn't damage my ego at all.` + ] + } + ], + [TrainerType.FISHERMAN]: [ + { + encounter: [ + `Aack! You made me lose a bite!\nWhat are you going to do about it?`, + `Go away! You're scaring the Pokémon!`, + `Let's see if you can reel in a victory!`, + ], + victory: [ + `Just forget about it.`, + `Next time, I'll be reelin' in the triumph!`, + `Guess I underestimated the currents this time.`, + ] + }, + { + encounter: [ + `Woah! I've hooked a big one!`, + `Line's in, ready to reel in success!`, + `Ready to make waves!` + ], + victory: [ + `I'll be back with a stronger hook.`, + `I'll reel in victory next time.`, + `I'm just sharpening my hooks for the comeback!` + ] + } + ], + [TrainerType.SWIMMER]: [ + { + encounter: [ + `Time to dive in!`, + `Let's ride the waves of victory!`, + `Ready to make a splash!`, + ], + victory: [ + `Drenched in defeat!`, + `A wave of defeat!`, + `Back to shore, I guess.`, + ] + } + ], + [TrainerType.BACKPACKER]: [ + { + encounter: [ + `Pack up, game on!`, + `Let's see if you can keep pace!`, + `Gear up, challenger!`, + `I've spent 20 years trying to find myself… But where am I?` + ], + victory: [ + `Tripped up this time!`, + `Oh, I think I'm lost.`, + `Dead end!`, + `Wait up a second! Hey! Don't you know who I am?` + ] + } + ], + [TrainerType.ACE_TRAINER]: [ + { + encounter: [ + `You seem quite confident.`, + `Your Pokémon… Show them to me…`, + `Because I'm an Ace Trainer, people think I'm strong.`, + `Are you aware of what it takes to be an Ace Trainer?` + ], + victory: [ + `Yes… You have good Pokémon…`, + `What?! But I'm a battling genius!`, + `Of course, you are the main character!`, + `OK! OK! You could be an Ace Trainer!` + ] + } + ], + [TrainerType.PARASOL_LADY]: [ + { + encounter: [ + `Time to grace the battlefield with elegance and poise!`, + ], + victory: [ + `My elegance remains unbroken!`, + ] + } + ], + [TrainerType.TWINS]: [ + { + encounter: [ + `Get ready, because when we team up, it's double the trouble!`, + `Two hearts, one strategy – let's see if you can keep up with our twin power!`, + `Hope you're ready for double trouble, because we're about to bring the heat!` + ], + victory: [ + `We may have lost this round, but our bond remains unbreakable!`, + `Our twin spirit won't be dimmed for long.`, + `We'll come back stronger as a dynamic duo!` + ] + } + ], + [TrainerType.CYCLIST]: [ + { + encounter: [ + `Get ready to eat my dust!`, + `Gear up, challenger! I'm about to leave you in the dust!`, + `Pedal to the metal, let's see if you can keep pace!` + ], + victory: [ + `Spokes may be still, but determination pedals on.`, + `Outpaced!`, + `The road to victory has many twists and turns yet to explore.` + ] + } + ], + [TrainerType.BLACK_BELT]: [ + { + encounter: [ + `I praise your courage in challenging me! For I am the one with the strongest kick!`, + `Oh, I see. Would you like to be cut to pieces? Or do you prefer the role of punching bag?` + ], + victory: [ + `Oh. The Pokémon did the fighting. My strong kick didn't help a bit.`, + `Hmmm… If I was going to lose anyway, I was hoping to get totally messed up in the process.` + ] + }, + //BATTLE GIRL + { + encounter: [ + `You don't have to try to impress me. You can lose against me.`, + ], + victory: [ + `It's hard to say good-bye, but we are running out of time…`, + ] + } + ], + [TrainerType.HIKER]: [ + { + encounter: [ + `My middle-age spread has given me as much gravitas as the mountains I hike!`, + `I inherited this big-boned body from my parents… I'm like a living mountain range…`, + ], + victory: [ + `At least I cannot lose when it comes to BMI!`, + `It's not enough… It's never enough. My bad cholesterol isn't high enough…` + ] + } + ], + [TrainerType.RANGER]: [ + { + encounter: [ + `When I am surrounded by nature, most other things cease to matter.`, + `When I'm living without nature in my life, sometimes I'll suddenly feel an anxiety attack coming on.` + ], + victory: [ + `It doesn't matter to the vastness of nature whether I win or lose…`, + `Something like this is pretty trivial compared to the stifling feelings of city life.` + ] + } + ], + [TrainerType.SCIENTIST]: [ + { + encounter: [ + `My research will lead this world to peace and joy.`, + ], + victory: [ + `I am a genius… I am not supposed to lose against someone like you…`, + ] + } + ], + [TrainerType.STUDENT]: [ + { + encounter: [ + `…Heehee. I'm confident in my calculations and analysis.`, + `I'm gaining as much experience as I can because I want to be a Gym Leader someday.` + ], + victory: [ + `Ohhhh… Calculation and analysis are perhaps no match for chance…`, + `Even difficult, trying experiences have their purpose, I suppose.` + ] + } + ], + [TrainerType.ARTIST]: [ + { + encounter: [ + `I used to be popular, but now I am all washed up.`, + ], + victory: [ + `As times change, values also change. I realized that too late.`, + ] + } + ], + [TrainerType.GUITARIST]: [ + { + encounter: [ + `Get ready to feel the rhythm of defeat as I strum my way to victory!`, + ], + victory: [ + `Silenced for now, but my melody of resilience will play on.`, + ] + } + ], + [TrainerType.WORKER]: [ + { + encounter: [ + `I'll show you we can break you. We've been training in the field!`, + `It bothers me that people always misunderstand me. + $I'm a lot more pure than everyone thinks.` + ], + victory: [ + `How strange… How could this be… I shouldn't have been outmuscled.`, + `I really don't want my skin to burn, so I want to stay in the shade while I work.` + ] + } + ], + [TrainerType.HEX_MANIAC]: [ + { + encounter: [ + `I normally only ever listen to classical music, but if I lose, I think I shall try a bit of new age!`, + ], + victory: [ + `Is this the dawning of the age of Aquarius?`, + ] + } + ], + [TrainerType.PSYCHIC]: [ + { + encounter: [ + `Hi! Focus!`, + ], + victory: [ + `Eeeeek!`, + ] + } + ], + [TrainerType.OFFICER]: [ + { + encounter: [ + `Brace yourself, because justice is about to be served!`, + `Ready to uphold the law and serve justice on the battlefield!` + ], + victory: [ + `The weight of justice feels heavier than ever…`, + `The shadows of defeat linger in the precinct.` ] } ], @@ -315,19 +614,1374 @@ export const trainerTypeDialogue = { encounter: [ `Now's not the time to act coy.\nLet's battle!`, `Ahahaha, You'll be witness to my artistry with Water Pokémon!`, - `A typhoon approaches!\nWill you be able to test me?` + `A typhoon approaches!\nWill you be able to test me?`, + `Please, you shall bear witness to our artistry.\nA grand illusion of water sculpted by my Pokémon and myself!` ], victory: [ `You may be a genius who can take on Wallace!`, `I focused on elegance while you trained.\nIt's only natural that you defeated me.`, - `Ahahaha!\nVery well, You have won this time.` + `Ahahaha!\nVery well, You have won this time.`, + `From you, I sense the brilliant shine of skill that will overcome all.` ], defeat: [ `My Pokémon and I have sculpted an illusion of Water and come out victorious.`, `Ahahaha, I have won, and you have lost.`, - `Shall I loan you my outfit? It may help you battle!\nAhahaha, I jest!` + `Shall I loan you my outfit? It may help you battle!\nAhahaha, I jest!`, + `I'm the winner! Which is to say, you lost.` ] }, + [TrainerType.CRASHER_WAKE]: { + encounter: [ + `Crash! Crash! Watch out!\nCrasher Wake…is…heeere!`, + `Crash! Crash! Crasher Wake!`, + `I'm the tidal wave of power to wash you away!` + ], + victory: [ + `That puts a grin on my face!\nGuhahaha! That was a blast!`, + `Hunwah! It's gone and ended!\nHow will I say this…\nI want more! I wanted to battle a lot more!`, + `WHAAAAT!?` + ], + defeat: [ + `Yeeeeah! That's right!`, + `I won, but I want more! I wanted to battle a lot more!`, + `So long!` + ] + }, + [TrainerType.FALKNER]: { + encounter: [ + `I'll show you the real power of the magnificent bird Pokémon!`, + `Winds, stay with me!`, + `Dad! I hope you're watching me battle from above!` + ], + victory: [ + `I understand… I'll bow out gracefully.`, + `A defeat is a defeat. You are strong indeed.`, + `…Shoot! Yeah, I lost.` + ], + defeat: [ + `Dad! I won with your cherished bird Pokémon…`, + `Bird Pokémon are the best after all!`, + `Feels like I'm catching up to my dad!` + ] + }, + [TrainerType.NESSA]: { + encounter: [ + `No matter what kind of plan your refined mind may be plotting, my partner and I will be sure to sink it.`, + `I'm not here to chat. I'm here to win!`, + `This is a little gift from my Pokémon… I hope you can take it!` + ], + victory: [ + `You and your Pokémon are just too much…`, + `How…? How can this be?!`, + `I was totally washed away!` + ], + defeat: [ + `The raging wave crashes again!`, + `Time to ride the wave of victory!`, + `Ehehe!` + ] + }, + [TrainerType.MELONY]: { + encounter: [ + `I'm not going to hold back!`, + `All righty, I suppose we should get started.`, + `I'll freeze you solid!` + ], + victory: [ + `You… You're pretty good, huh?`, + `If you find Gordie around, be sure to give him a right trashing, would you?`, + `I think you took breaking the ice a little too literally…` + ], + defeat: [ + `Now do you see how severe battles can be?`, + `Hee! Looks like I went and won again!`, + `Are you holding back?` + ] + }, + [TrainerType.MARLON]: { + encounter: [ + `You look strong! Shoots! Let's start!`, + `I'm strong like the ocean's wide. You're gonna get swept away, fo' sho'.`, + `Oh ho, so I'm facing you! That's off the wall.` + ], + victory: [ + `You totally rocked that! You're raising some wicked Pokémon. You got this Trainer thing down!`, + `You don't just look strong, you're strong fo' reals! Eh, I was swept away, too!`, + `You're strong as a gnarly wave!` + ], + defeat: [ + `You're tough, but it's not enough to sway the sea, 'K!`, + `Hee! Looks like I went and won again!`, + `Sweet, sweet victory!` + ] + }, + [TrainerType.SHAUNTAL]: { + encounter: [ + `Excuse me. You're a challenger, right?\nI'm the Elite Four's Ghost-type Pokémon user, Shauntal, and I shall be your opponent.`, + `I absolutely love writing about Trainers who come here and the Pokémon they train.\nCould I use you and your Pokémon as a subject?`, + `Every person who works with Pokémon has a story to tell.\nWhat story is about to be told?` + ], + victory: [ + `Wow. I'm dumbstruck!`, + `S-sorry! First, I must apologize to my Pokémon…\n\nI'm really sorry you had a bad experience because of me!`, + `Even in light of that, I'm still one of the Elite Four!` + ], + defeat: [ + `Eheh.`, + `That gave me excellent material for my next novel!`, + `And so, another tale ends…` + ] + }, + [TrainerType.MARSHAL]: { + encounter: [ + `My mentor, Alder, sees your potential as a Trainer and is taking an interest in you.\nIt is my intention to test you--to take you to the limits of your strength. Kiai!`, + `Victory, decisive victory, is my intention! Challenger, here I come!`, + `In myself, I seek to develop the strength of a fighter and shatter any weakness in myself!\nPrevailing with the force of my convictions!` + ], + victory: [ + `Whew! Well done!`, + `As your battles continue, aim for even greater heights!`, + `The strength shown by you and your Pokémon has deeply impressed me…` + ], + defeat: [ + `Hmm.`, + `That was good battle.`, + `Haaah! Haaah! Haiyaaaah!` + ] + }, + [TrainerType.CHEREN]: { + encounter: [ + `You remind me of an old friend. That makes me excited about this Pokémon battle!`, + `Pokémon battles have no meaning if you don't think why you battle. + $Or better said, it makes battling together with Pokémon meaningless.`, + `My name's Cheren! I'm a Gym Leader and a teacher! Pleasure to meet you.` + ], + victory: [ + `Thank you! I saw what was missing in me.`, + `Thank you! I feel like I saw a little of the way toward my ideals.`, + `Hmm… This is problematic.` + ], + defeat: [ + `As a Gym Leader, I aim to be a wall for you to overcome.`, + `All right!`, + `I made it where I am because Pokémon were by my side.\nPerhaps we need to think about why Pokémon help us not in terms of Pokémon and Trainers but as a relationship between living beings.` + ] + }, + [TrainerType.CHILI]: { + encounter: [ + `Yeeeeooow! Time to play with FIRE!! I'm the strongest of us brothers!`, + `Ta-da! The Fire-type scorcher Chili--that's me--will be your opponent!`, + `I'm going to show you what me and my blazing Fire types can do!` + ], + victory: [ + `You got me. I am… burned… out…`, + `Whoa ho! You're on fire!`, + `Augh! You got me!` + ], + defeat: [ + `I'm on fire! Play with me, and you'll get burned!`, + `When you play with fire, you get burned!`, + `I mean, c'mon, your opponent was me! You didn't have a chance!` + ] + }, + [TrainerType.CILAN]: { + encounter: [ + `Nothing personal... No hard feelings... Me and my Grass-type Pokémon will... + $Um... We're gonna battle come what may.`, + `So, um, if you're OK with me, I'll, um, put everything I've got into being, er, you know, your opponent.`, + `OK… So, um, I'm Cilan, I like Grass-type Pokémon.` + ], + victory: [ + `Er… Is it over now?`, + `…What a surprise. You are very strong, aren't you? + $I guess my brothers wouldn't have been able to defeat you either…`, + `…Huh. Looks like my timing was, um, off?` + ], + defeat: [ + `Huh? Did I win?`, + `I guess… + $I suppose I won, because I've been competing with my brothers Chili and Cress, and we all were able to get tougher.`, + `It…it was quite a thrilling experience…` + ] + }, + [TrainerType.ROARK]: { + encounter: [ + `I need to see your potential as a Trainer. And, I'll need to see the toughness of the Pokémon that battle with you!`, + `Here goes! These are my rocking Pokémon, my pride and joy!`, + `Rock-type Pokémon are simply the best!`, + `I need to see your potential as a Trainer. And, I'll need to see the toughness of the Pokémon that battle with you!` + ], + victory: [ + `W-what? That can't be! My buffed-up Pokémon!`, + `…We lost control there. Next time I'd like to challenge you to a Fossil-digging race underground.`, + `With skill like yours, it's natural for you to win.`, + `Wh-what?! It can't be! Even that wasn't enough?`, + `I blew it.` + ], + defeat: [ + `See? I'm proud of my rocking battle style!`, + `Thanks! The battle gave me confidence that I may be able to beat my dad!`, + `I feel like I just smashed through a really stubborn boulder!` + ] + }, + [TrainerType.MORTY]: { + encounter: [ + `With a little more, I could see a future in which I meet the legendary Pokémon. You're going to help me reach that level!`, + `It's said that a rainbow-hued Pokémon will come down to appear before a truly powerful Trainer. + $I believed that tale, so I have secretly trained here all my life. As a result, I can now see what others cannot. + $I see a shadow of the person who will make the Pokémon appear. + $I believe that person is me! You're going to help me reach that level!`, + `Whether you choose to believe or not, mystic power does exist.`, + `You can bear witness to the fruits of my training.`, + `You must make your soul one with that of Pokémon. Can you do this?`, + `Say, do you want to be part of my training?` + ], + victory: [ + `I'm not good enough yet…`, + `I see… Your journey has taken you to far-away places and you have witnessed much more than I. + $I envy you for that…`, + `How is this possible…`, + `I don't think our potentials are so different. But you seem to have something more than that… So be it.`, + `Guess I need more training.`, + `That's a shame.` + ], + defeat: [ + `I moved… one step ahead again.`, + `Fufufu…`, + `Wh-what?! It can't be! Even that wasn't enough?`, + `I feel like I just smashed through a really stubborn boulder!`, + `Ahahahah!`, + `I knew I would win!` + ] + }, + [TrainerType.CRISPIN]: { + encounter: [ + `I wanna win, so that's exactly what I'll do!`, + `I battle because I wanna battle! And you know what? That's how it should be!` + ], + victory: [ + `I wanted to win…but I lost!`, + `I lost…'cause I couldn't win!` + ], + defeat: [ + `Hey, wait a sec. Did I just win? I think I just won! Talk about satisfying!`, + `Wooo! That was amazing!` + ] + }, + [TrainerType.AMARYS]: { + encounter: [ + `I want to be the one to help a certain person. That being the case, I cannot afford to lose. + $… Our battle starts now.`, + + ], + victory: [ + `I am… not enough, I see.`, + ], + defeat: [ + `Victory belongs to me. Well fought.`, + ] + }, + [TrainerType.LACEY]: { + encounter: [ + `I'll be facing you with my usual party as a member of the Elite Four.`, + ], + victory: [ + `That was a great battle!`, + ], + defeat: [ + `Let's give your Pokémon a nice round of applause for their efforts!`, + ] + }, + [TrainerType.DRAYTON]: { + encounter: [ + `Man, I love chairs. Don't you love chairs? What lifesavers. + $I don't get why everyone doesn't just sit all the time. Standing up's tiring work!`, + ], + victory: [ + `Guess I should've expected that!`, + ], + defeat: [ + `Heh heh! Don't mind me, just scooping up a W over here. I get it if you're upset, but don't go full Kieran on me, OK?`, + ] + }, + [TrainerType.RAMOS]: { + encounter: [ + `Did yeh enjoy the garden playground I made with all these sturdy plants o' mine? + $Their strength is a sign o' my strength as a gardener and a Gym Leader! Yeh sure yer up to facing all that?`, + ], + victory: [ + `Yeh believe in yer Pokémon… And they believe in yeh, too… It was a fine battle, sprout.`, + ], + defeat: [ + `Hohoho… Indeed. Frail little blades o' grass'll break through even concrete.`, + ] + }, + [TrainerType.VIOLA]: { + encounter: [ + `Whether it's the tears of frustration that follow a loss or the blossoming of joy that comes with victory… + $They're both great subjects for my camera! Fantastic! This'll be just fantastic! + $Now come at me!`, + `My lens is always focused on victory--I won't let anything ruin this shot!` + ], + victory: [ + `You and your Pokémon have shown me a whole new depth of field! Fantastic! Just fantastic!`, + `The world you see through a lens, and the world you see with a Pokémon by your side… + $The same world can look entirely different depending on your view.` + ], + defeat: [ + `The photo from the moment of my victory will be a really winner, all right!`, + `Yes! I took some great photos!` + ] + }, + [TrainerType.CANDICE]: { + encounter: [ + `You want to challenge Candice? Sure thing! I was waiting for someone tough! + $But I should tell you, I'm tough because I know how to focus.`, + `Pokémon, fashion, romance… It's all about focus! + $I'll show you just what I mean. Get ready to lose!` + ], + victory: [ + `I must say, I'm warmed up to you! I might even admire you a little.`, + `Wow! You're great! You've earned my respect! + $I think your focus and will bowled us over totally. ` + ], + defeat: [ + `I sensed your will to win, but I don't lose!`, + `See? Candice's focus! My Pokémon's focus is great, too!` + ] + }, + [TrainerType.GARDENIA]: { + encounter: [ + `You have a winning aura about you. So, anyway, this will be fun. Let's have our battle!`, + ], + victory: [ + `Amazing! You're very good, aren't you?`, + ], + defeat: [ + `Yes! My Pokémon and I are perfectly good!`, + ] + }, + [TrainerType.AARON]: { + encounter: [ + `Ok! Let me take you on!`, + ], + victory: [ + `Battling is a deep and complex affair…`, + ], + defeat: [ + `Victory over an Elite Four member doesn't come easily.`, + ] + }, + [TrainerType.CRESS]: { + encounter: [ + `That is correct! It shall be I and my esteemed Water types that you must face in battle!`, + ], + victory: [ + `Lose? Me? I don't believe this.`, + ], + defeat: [ + `This is the appropriate result when I'm your opponent.`, + ] + }, + [TrainerType.ALLISTER]: { + encounter: [ + `'M Allister.\nH-here… I go…`, + ], + victory: [ + `I nearly lost my mask from the shock… That was… + $Wow. I can see your skill for what it is.`, + ], + defeat: [ + `Th-that was ace!`, + ] + }, + [TrainerType.CLAY]: { + encounter: [ + `Harrumph! Kept me waitin', didn't ya, kid? All right, time to see what ya can do!`, + ], + victory: [ + `Man oh man… It feels good to go all out and still be defeated!`, + ], + defeat: [ + `What's important is how ya react to losin'. + $That's why folks who use losin' as fuel to get better are tough.`, + ] + }, + [TrainerType.KOFU]: { + encounter: [ + `I'mma serve you a full course o' Water-type Pokémon! Don't try to eat 'em, though!`, + ], + victory: [ + `Vaultin' Veluza! Yer a lively one, aren't ya! A little TOO lively, if I do say so myself!`, + ], + defeat: [ + `You come back to see me again now, ya hear?`, + ] + }, + [TrainerType.TULIP]: { + encounter: [ + `Allow me to put my skills to use to make your cute little Pokémon even more beautiful!`, + ], + victory: [ + `Your strength has a magic to it that cannot be washed away.`, + ], + defeat: [ + `You know, in my line of work, people who lack talent in one area or the other often fade away quickly—never to be heard of again.`, + ] + }, + [TrainerType.SIDNEY]: { + encounter: [ + `I like that look you're giving me. I guess you'll give me a good match. + $That's good! Looking real good! All right! + $You and me, let's enjoy a battle that can only be staged here!`, + ], + victory: [ + `Well, how do you like that? I lost! Eh, it was fun, so it doesn't matter.`, + ], + defeat: [ + `No hard feelings, alright?`, + ] + }, + [TrainerType.PHOEBE]: { + encounter: [ + `While I trained, I gained the ability to commune with Ghost-type Pokémon. + $Yes, the bond I developed with Pokémon is extremely tight. + $So, come on, just try and see if you can even inflict damage on my Pokémon!`, + ], + victory: [ + `Oh, darn. I've gone and lost.`, + ], + defeat: [ + `I look forward to battling you again sometime!`, + ] + }, + [TrainerType.GLACIA]: { + encounter: [ + `All I have seen are challenges by weak Trainers and their Pokémon. + $What about you? It would please me to no end if I could go all out against you!`, + ], + victory: [ + `You and your Pokémon… How hot your spirits burn! + $The all-consuming heat overwhelms. + $It's no surprise that my icy skills failed to harm you.`, + ], + defeat: [ + `A fiercely passionate battle, indeed.`, + ] + }, + [TrainerType.DRAKE]: { + encounter: [ + `For us to battle with Pokémon as partners, do you know what it takes? Do you know what is needed? + $If you don't, then you will never prevail over me!`, + ], + victory: [ + `Superb, it should be said.`, + ], + defeat: [ + `I gave my all for that battle!`, + ] + }, + [TrainerType.WALLACE]: { + encounter: [ + `There's something about you… A difference in your demeanor. + $I think I sense that in you. Now, show me. Show me the power you wield with your Pokémon. + $And I, in turn, shall present you with a performance of illusions in water by me and my Pokémon!`, + ], + victory: [ + `Bravo. I realize now your authenticity and magnificence as a Pokémon Trainer. + $I find much joy in having met you and your Pokémon. You have proven yourself worthy.`, + ], + defeat: [ + `A grand illusion!`, + ] + }, + [TrainerType.LORELEI]: { + encounter: [ + `No one can best me when it comes to icy Pokémon! Freezing moves are powerful! + $Your Pokémon will be at my mercy when they are frozen solid! Hahaha! Are you ready?`, + ], + victory: [ + `How dare you!`, + ], + defeat: [ + `There's nothing you can do once you're frozen.`, + ] + }, + [TrainerType.WILL]: { + encounter: [ + `I have trained all around the world, making my psychic Pokémon powerful. + $I can only keep getting better! Losing is not an option!`, + ], + victory: [ + `I… I can't… believe it…`, + ], + defeat: [ + `That was close. I wonder what it is that you lack.`, + ] + }, + [TrainerType.MALVA]: { + encounter: [ + `I feel like my heart might just burst into flames. + $I'm burning up with my hatred for you, runt!`, + ], + victory: [ + `What news… So a new challenger has defeated Malva!`, + ], + defeat: [ + `I am delighted! Yes, delighted that I could squash you beneath my heel.`, + ] + }, + [TrainerType.HALA]: { + encounter: [ + `Old Hala is here to make you holler!`, + ], + victory: [ + `I could feel the power you gained on your journey.`, + ], + defeat: [ + `Haha! What a delightful battle!`, + ] + }, + [TrainerType.MOLAYNE]: { + encounter: [ + `I gave the captain position to my cousin Sophocles, but I'm confident in my ability. + $My strength is like that of a supernova!`, + ], + victory: [ + `I certainly found an interesting Trainer to face!`, + ], + defeat: [ + `Ahaha. What an interesting battle.`, + ] + }, + [TrainerType.RIKA]: { + encounter: [ + `I'd say I'll go easy on you, but… I'd be lying! Think fast!`, + ], + victory: [ + `Not bad, kiddo.`, + ], + defeat: [ + `Nahahaha! You really are something else, kiddo!`, + ] + }, + [TrainerType.BRUNO]: { + encounter: [ + `We will grind you down with our superior power! Hoo hah!`, + ], + victory: [ + `Why? How could I lose?`, + ], + defeat: [ + `You can challenge me all you like, but the results will never change!`, + ] + }, + [TrainerType.BUGSY]: { + encounter: [ + `Let me demonstrate what I've learned from my studies.`, + ], + victory: [ + `Whoa, amazing! You're an expert on Pokémon! + $My research isn't complete yet. OK, you win.`, + ], + defeat: [ + `Thanks! Thanks to our battle, I was also able to make progress in my research!`, + ] + }, + [TrainerType.KOGA]: { + encounter: [ + `Fwahahahaha! Pokémon are not merely about brute force--you shall see soon enough!`, + ], + victory: [ + `Ah! You've proven your worth!`, + ], + defeat: [ + `Have you learned to fear the techniques of the ninja?`, + ] + }, + [TrainerType.BERTHA]: { + encounter: [ + `Well, would you show this old lady how much you've learned?`, + ], + victory: [ + `Well! Dear child, I must say, that was most impressive. + $Your Pokémon believed in you and did their best to earn you the win. + $Even though I've lost, I find myself with this silly grin!`, + ], + defeat: [ + `Hahahahah! Looks like this old lady won!`, + ] + }, + [TrainerType.LENORA]: { + encounter: [ + `Well then, challenger, I'm going to research how you battle with the Pokémon you've so lovingly raised!`, + ], + victory: [ + `My theory about you was correct. You're more than just talented… You're motivated! I salute you!`, + ], + defeat: [ + `Ah ha ha! If you lose, make sure to analyze why, and use that knowledge in your next battle!`, + ] + }, + [TrainerType.SIEBOLD]: { + encounter: [ + `As long as I am alive, I shall strive onward to seek the ultimate cuisine... and the strongest opponents in battle!`, + ], + victory: [ + `I shall store my memory of you and your Pokémon forever away within my heart.`, + ], + defeat: [ + `Our Pokémon battle was like food for my soul. It shall keep me going. + $That is how I will pay my respects to you for giving your all in battle!`, + ] + }, + [TrainerType.ROXIE]: { + encounter: [ + `Get ready! I'm gonna knock some sense outta ya!`, + ], + victory: [ + `Wild! Your reason's already more toxic than mine!`, + ], + defeat: [ + `Hey, c'mon! Get serious! You gotta put more out there!`, + ] + }, + [TrainerType.OLIVIA]: { + encounter: [ + `No introduction needed here. Time to battle me, Olivia!`, + ], + victory: [ + `Really lovely… Both you and your Pokémon…`, + ], + defeat: [ + `Mmm-hmm.`, + ] + }, + [TrainerType.POPPY]: { + encounter: [ + `Oooh! Do you wanna have a Pokémon battle with me?`, + ], + victory: [ + `Uagh?! Mmmuuuggghhh…`, + ], + defeat: [ + `Yaaay! I did it! I de-feet-ed you! You can come for… For… An avenge match? + $Come for an avenge match anytime you want!`, + ] + }, + [TrainerType.AGATHA]: { + encounter: [ + `Pokémon are for battling! I'll show you how a real Trainer battles!`, + ], + victory: [ + `Oh my! You're something special, child!`, + ], + defeat: [ + `Bahaha. That's how a proper battle's done!`, + ] + }, + [TrainerType.FLINT]: { + encounter: [ + `Hope you're warmed up, cause here comes the Big Bang!`, + ], + victory: [ + `Incredible! Your moves are so hot, they make mine look lukewarm!`, + ], + defeat: [ + `Huh? Is that it? I think you need a bit more passion.`, + ] + }, + [TrainerType.GRIMSLEY]: { + encounter: [ + `The winner takes everything, and there's nothing left for the loser.`, + ], + victory: [ + `When one loses, they lose everything… The next thing I'll look for will be victory, too!`, + ], + defeat: [ + `If somebody wins, the person who fought against that person will lose.`, + ] + }, + [TrainerType.CAITLIN]: { + encounter: [ + `It's me who appeared when the flower opened up. You who have been waiting… + $You look like a Pokémon Trainer with refined strength and deepened kindness. + $What I look for in my opponent is superb strength… + $Please unleash your power to the fullest!`, + ], + victory: [ + `My Pokémon and I learned so much! I offer you my thanks.`, + ], + defeat: [ + `I aspire to claim victory with elegance and grace.`, + ] + }, + [TrainerType.DIANTHA]: { + encounter: [ + `Battling against you and your Pokémon, all of you brimming with hope for the future… + $Honestly, it just fills me up with energy I need to keep facing each new day! It does!`, + ], + victory: [ + `Witnessing the noble spirits of you and your Pokémon in battle has really touched my heart…`, + ], + defeat: [ + `Oh, fantastic! What did you think? My team was pretty cool, right?`, + ] + }, + [TrainerType.WIKSTROM]: { + encounter: [ + `Well met, young challenger! Verily am I the famed blade of hardened steel, Duke Wikstrom! + $Let the battle begin! En garde!`, + ], + victory: [ + `Glorious! The trust that you share with your honorable Pokémon surpasses even mine!`, + ], + defeat: [ + `What manner of magic is this? My heart, it doth hammer ceaselessly in my breast! + $Winning against such a worthy opponent doth give my soul wings--thus do I soar!`, + ] + }, + [TrainerType.ACEROLA]: { + encounter: [ + `Battling is just plain fun! Come on, I can take you!`, + ], + victory: [ + `I'm… I'm speechless! How did you do it?!`, + ], + defeat: [ + `Ehaha! What an amazing victory!`, + ] + }, + [TrainerType.LARRY_ELITE]: { + encounter: [ + `Hello there… It's me, Larry. + $I serve as a member of the Elite Four too, yes… Unfortunately for me.`, + ], + victory: [ + `Well, that took the wind from under our wings…`, + ], + defeat: [ + `It's time for a meeting with the boss.`, + ] + }, + [TrainerType.LANCE]: { + encounter: [ + `I've been waiting for you. Allow me to test your skill.`, + `I thought that you would be able to get this far. Let's get this started.` + ], + victory: [ + `You got me. You are magneficent!`, + `I never expected another trainer to beat me… I'm surprised.` + ], + defeat: [ + `That was close. Want to try again?`, + `It's not that you are weak. Don't let it bother you.` + ] + }, + [TrainerType.KAREN]: { + encounter: [ + `I am Karen. Would you care for a showdown with my Dark-type Pokémon?`, + `I am unlike those you've already met.`, + `You've assembled a charming team. Our battle should be a good one.` + ], + victory: [ + `No! I can't win. How did you become so strong?`, + `I will not stray from my chosen path.`, + `The Champion is looking forward to meeting you.` + ], + defeat: [ + `That's about what I expected.`, + `Well, that was relatively entertaining.`, + `Come visit me anytime.` + ] + }, + [TrainerType.MILO]: { + encounter: [ + `Sure seems like you understand Pokémon real well. + $This is gonna be a doozy of a battle! + $I'll have to Dynamax my Pokémon if I want to win!`, + ], + victory: [ + `The power of Grass has wilted… What an incredible Challenger!`, + ], + defeat: [ + `This'll really leave you in shock and awe.`, + ] + }, + [TrainerType.LUCIAN]: { + encounter: [ + `Just a moment, please. The book I'm reading has nearly reached its thrilling climax… + $The hero has obtained a mystic sword and is about to face their final trial… Ah, never mind. + $Since you've made it this far, I'll put that aside and battle you. + $Let me see if you'll achieve as much glory as the hero of my book!,` + ], + victory: [ + `I see… It appears you've put me in checkmate.`, + ], + defeat: [ + `I have a reputation to uphold.`, + ] + }, + [TrainerType.DRASNA]: { + encounter: [ + `You must be a strong Trainer. Yes, quite strong indeed… + $That's just wonderful news! Facing opponents like you and your team will make my Pokémon grow like weeds!` + ], + victory: [ + `Oh, dear me. That sure was a quick battle… I do hope you'll come back again sometime!`, + ], + defeat: [ + `How can this be?`, + ] + }, + [TrainerType.KAHILI]: { + encounter: [ + `So, here you are… Why don't we see who the winds favor today, you… Or me?` + ], + victory: [ + `It's frustrating to me as a member of the Elite Four, but it seems your strength is the real deal.`, + ], + defeat: [ + `That was an ace!`, + ] + }, + [TrainerType.HASSEL]: { + encounter: [ + `Prepare to learn firsthand how the fiery breath of ferocious battle feels!` + ], + victory: [ + `Fortune smiled on me this time, but… + $Judging from how the match went, who knows if I will be so lucky next time.`, + ], + defeat: [ + `That was an ace!`, + ] + }, + [TrainerType.BLUE]: { + encounter: [ + `You must be pretty good to get this far.` + ], + victory: [ + `I've only lost to him and now to you… Him? Hee, hee…`, + ], + defeat: [ + `See? My power is what got me here.`, + ] + }, + [TrainerType.PIERS]: { + encounter: [ + `Get ready for a mosh pit with me and my party! Spikemuth, it's time to rock!` + ], + victory: [ + `Me an' my team gave it our best. Let's meet up again for a battle some time…`, + ], + defeat: [ + `My throat's ragged from shoutin'… But 'at was an excitin' battle!`, + ] + }, + [TrainerType.RED]: { + encounter: [ + `…!` + ], + victory: [ + `…?`, + ], + defeat: [ + `…!`, + ] + }, + [TrainerType.JASMINE]: { + encounter: [ + `Oh… Your Pokémon are impressive. I think I will enjoy this.` + ], + victory: [ + `You are truly strong. I'll have to try much harder, too.`, + ], + defeat: [ + `I never expected to win.`, + ] + }, + [TrainerType.LANCE_CHAMPION]: { + encounter: [ + `I am still the Champion. I won't hold anything back.`, + ], + victory: [ + `This is the emergence of a new Champion.`, + ], + defeat: [ + `I successfully defended my Championship.`, + ] + }, + [TrainerType.STEVEN]: { + encounter: [ + `Tell me… What have you seen on your journey with your Pokémon? + $What have you felt, meeting so many other Trainers out there? + $Traveling this rich land… Has it awoken something inside you? + $I want you to come at me with all that you've learned. + $My Pokémon and I will respond in turn with all that we know!`, + ], + victory: [ + `So I, the Champion, fall in defeat…`, + ], + defeat: [ + `That was time well spent! Thank you!`, + ] + }, + [TrainerType.CYNTHIA]: { + encounter: [ + `I, Cynthia, accept your challenge! There won't be any letup from me!`, + ], + victory: [ + `No matter how fun the battle is, it will always end sometime…`, + ], + defeat: [ + `Even if you lose, never lose your love of Pokémon.`, + ] + }, + [TrainerType.IRIS]: { + encounter: [ + `Know what? I really look forward to having serious battles with strong Trainers! + $I mean, come on! The Trainers who make it here are Trainers who desire victory with every fiber of their being! + #And they are battling alongside Pokémon that have been through countless difficult battles! + $If I battle with people like that, not only will I get stronger, my Pokémon will, too! + $And we'll get to know each other even better! OK! Brace yourself! + $I'm Iris, the Pokémon League Champion, and I'm going to defeat you!`, + ], + victory: [ + `Aghhhh… I did my best, but we lost…`, + ], + defeat: [ + `Yay! We won!`, + ] + }, + [TrainerType.HAU]: { + encounter: [ + `I wonder if a Trainer battles differently depending on whether they're from a warm region or a cold region. Let's test it out!`, + ], + victory: [ + `That was awesome! I think I kinda understand your vibe a little better now!`, + ], + defeat: [ + `Ma-an, that was some kinda battle!`, + ] + }, + [TrainerType.GEETA]: { + encounter: [ + `I decided to throw my hat in the ring once more. + $Come now… Show me the fruits of your training.`, + ], + victory: [ + `I eagerly await news of all your achievements!`, + ], + defeat: [ + `What's the matter? This isn't all, is it?`, + ] + }, + [TrainerType.NEMONA]: { + encounter: [ + `Yesss! I'm so psyched! Time for us to let loose!`, + ], + victory: [ + `Well, that stinks, but I still had fun! I'll getcha next time!`, + ], + defeat: [ + `Well, that was a great battle! Fruitful for sure.`, + ] + }, + [TrainerType.LEON]: { + encounter: [ + `We're gonna have an absolutely champion time!`, + ], + victory: [ + `My time as Champion is over… + $But what a champion time it's been! + $Thank you for the greatest battle I've ever had!`, + ], + defeat: [ + `An absolute champion time, that was!`, + ] + }, + [TrainerType.WHITNEY]: { + encounter: [ + `Hey! Don't you think Pokémon are, like, super cute?`, + ], + victory: [ + `Waaah! Waaah! You're so mean!`, + ], + defeat: [ + `And that's that!`, + ] + }, + [TrainerType.CHUCK]: { + encounter: [ + `Hah! You want to challenge me? Are you brave or just ignorant?`, + ], + victory: [ + `You're strong! Would you please make me your apprentice?`, + ], + defeat: [ + `There. Do you realize how much more powerful I am than you?`, + ] + }, + [TrainerType.KATY]: { + encounter: [ + `Don't let your guard down unless you would like to find yourself knocked off your feet!`, + ], + victory: [ + `All of my sweet little Pokémon dropped like flies!`, + ], + defeat: [ + `Eat up, my cute little Vivillon!`, + ] + }, + [TrainerType.PRYCE]: { + encounter: [ + `Youth alone does not ensure victory! Experience is what counts.`, + ], + victory: [ + `Outstanding! That was perfect. Try not to forget what you feel now.`, + ], + defeat: [ + `Just as I envisioned.`, + ] + }, + [TrainerType.CLAIR]: { + encounter: [ + `Do you know who I am? And you still dare to challenge me?`, + ], + victory: [ + `I wonder how far you can get with your skill level. This should be fascinating.`, + ], + defeat: [ + `That's that.`, + ] + }, + [TrainerType.MAYLENE]: { + encounter: [ + `I've come to challenge you now, and I won't hold anything back. + $Please prepare yourself for battle!`, + ], + victory: [ + `I admit defeat…`, + ], + defeat: [ + `That was awesome.`, + ] + }, + [TrainerType.FANTINA]: { + encounter: [ + `You shall challenge me, yes? But I shall win. + $That is what the Gym Leader of Hearthome does, non?`, + ], + victory: [ + `You are so fantastically strong. I know why I have lost.`, + ], + defeat: [ + `I am so, so, very happy!`, + ] + }, + [TrainerType.BYRON]: { + encounter: [ + `Trainer! You're young, just like my son, Roark. + $With more young Trainers taking charge, the future of Pokémon is bright! + $So, as a wall for young people, I'll take your challenge!`, + ], + victory: [ + `Hmm! My sturdy Pokémon--defeated!`, + ], + defeat: [ + `Gwahahaha! How were my sturdy Pokémon?!`, + ] + }, + [TrainerType.OLYMPIA]: { + encounter: [ + `An ancient custom deciding one's destiny. The battle begins!`, + ], + victory: [ + `Create your own path. Let nothing get in your way. Your fate, your future.`, + ], + defeat: [ + `Our path is clear now.`, + ] + }, + [TrainerType.VOLKNER]: { + encounter: [ + `Since you've come this far, you must be quite strong… + $I hope you're the Trainer who'll make me remember how fun it is to battle!`, + ], + victory: [ + `You've got me beat… + $Your desire and the noble way your Pokémon battled for you… + $I even felt thrilled during our match. That was a very good battle.`, + ], + defeat: [ + `It was not shocking at all… + $That is not what I wanted!`, + ] + }, + [TrainerType.BURGH]: { + encounter: [ + `M'hm… If I win this battle, I feel like I can draw a picture unlike any before it. + $OK! I can hear my battle muse loud and clear. Let's get straight to it!`, + ], + victory: [ + `Is it over? Has my muse abandoned me?`, + ], + defeat: [ + `Wow… It's beautiful somehow, isn't it…`, + ] + }, + [TrainerType.ELESA]: { + encounter: [ + `C'est fini! When I'm certain of that, I feel an electric jolt run through my body! + $I want to feel the sensation, so now my beloved Pokémon are going to make your head spin!`, + ], + victory: [ + `I meant to make your head spin, but you shocked me instead.`, + ], + defeat: [ + `That was unsatisfying somehow… Will you give it your all next time?`, + ] + }, + [TrainerType.SKYLA]: { + encounter: [ + `It's finally time for a showdown! That means the Pokémon battle that decides who's at the top, right? + $I love being on the summit! 'Cause you can see forever and ever from high places! + $So, how about you and I have some fun?`, + ], + victory: [ + `Being your opponent in battle is a new source of strength to me. Thank you!`, + ], + defeat: [ + `Win or lose, you always gain something from a battle, right?`, + ] + }, + [TrainerType.BRYCEN]: { + encounter: [ + `There is also strength in being with other people and Pokémon. + $Receiving their support makes you stronger. I'll show you this power!`, + ], + victory: [ + `The wonderful combination of you and your Pokémon! What a beautiful friendship!`, + ], + defeat: [ + `Extreme conditions really test you and train you!`, + ] + }, + [TrainerType.DRAYDEN]: { + encounter: [ + `What I want to find is a young Trainer who can show me a bright future. + $Let's battle with everything we have: your skill, my experience, and the love we've raised our Pokémon with!`, + ], + victory: [ + `This intense feeling that floods me after a defeat… I don't know how to describe it.`, + ], + defeat: [ + `Harrumph! I know your ability is greater than that!`, + ] + }, + [TrainerType.GRANT]: { + encounter: [ + `There is only one thing I wish for. + $That by surpassing one another, we find a way to even greater heights.`, + ], + victory: [ + `You are a wall that I am unable to surmount!`, + ], + defeat: [ + `Do not give up. + $That is all there really is to it. + $The most important lessons in life are simple.`, + ] + }, + [TrainerType.KORRINA]: { + encounter: [ + `Time for Lady Korrina's big appearance!`, + ], + victory: [ + `It's your very being that allows your Pokémon to evolve!`, + ], + defeat: [ + `What an explosive battle!`, + ] + }, + [TrainerType.CLEMONT]: { + encounter: [ + `Oh! I'm glad that we got to meet!`, + ], + victory: [ + `Your passion for battle inspires me!`, + ], + defeat: [ + `Looks like my Trainer-Grow-Stronger Machine, Mach 2 is really working!`, + ] + }, + [TrainerType.VALERIE]: { + encounter: [ + `Oh, if it isn't a young Trainer… It is lovely to get to meet you like this. + $Then I suppose you have earned yourself the right to a battle, as a reward for your efforts. + $The elusive Fairy may appear frail as the breeze and delicate as a bloom, but it is strong.`, + ], + victory: [ + `I hope that you will find things worth smiling about tomorrow…`, + ], + defeat: [ + `Oh goodness, what a pity…`, + ] + }, + [TrainerType.WULFRIC]: { + encounter: [ + `You know what? We all talk big about what you learn from battling and bonds and all that, but really, I just do it 'cause it's fun. + $Who cares about the grandstanding? Let's get to battling!`, + ], + victory: [ + `Outstanding! I'm tough as an iceberg, but you smashed me through and through!`, + ], + defeat: [ + `Tussle with me and this is what happens!`, + ] + }, + [TrainerType.KABU]: { + encounter: [ + `Every Trainer and Pokémon trains hard in pursuit of victory. + $But that means your opponent is also working hard to win. + $In the end, the match is decided by which side is able to unleash their true potential.`, + ], + victory: [ + `I'm glad I could battle you today!`, + ], + defeat: [ + `That's a great way for me to feel my own growth!`, + ] + }, + [TrainerType.BEA]: { + encounter: [ + `Do you have an unshakable spirit that won't be moved, no matter how you are attacked? + $I think I'll just test that out, shall I?`, + ], + victory: [ + `I felt the fighting spirit of your Pokémon as you led them in battle.`, + ], + defeat: [ + `That was the best sort of match anyone could ever hope for.`, + ] + }, + [TrainerType.OPAL]: { + encounter: [ + `Let me have a look at how you and your partner Pokémon behave!`, + ], + victory: [ + `Your pink is still lacking, but you're an excellent Trainer with excellent Pokémon.`, + ], + defeat: [ + `Too bad for you, I guess.`, + ] + }, + [TrainerType.BEDE]: { + encounter: [ + `I suppose I should prove beyond doubt just how pathetic you are and how strong I am.`, + ], + victory: [ + `I see… Well, that's fine. I wasn't really trying all that hard anyway.`, + ], + defeat: [ + `Not a bad job, I suppose.`, + ] + }, + [TrainerType.GORDIE]: { + encounter: [ + `So, let's get this over with.`, + ], + victory: [ + `I just want to climb into a hole… Well, I guess it'd be more like falling from here.`, + ], + defeat: [ + `Battle like you always do, victory will follow!`, + ] + }, + [TrainerType.MARNIE]: { + encounter: [ + `The truth is, when all's said and done… I really just wanna become Champion for myself! + $So don't take it personal when I kick your butt!`, + ], + victory: [ + `OK, so I lost… But I got to see a lot of the good points of you and your Pokémon!`, + ], + defeat: [ + `Hope you enjoyed our battle tactics.`, + ] + }, + [TrainerType.RAIHAN]: { + encounter: [ + `I'm going to defeat the Champion, win the whole tournament, and prove to the world just how strong the great Raihan really is!`, + ], + victory: [ + `I look this good even when I lose. + $It's a real curse. + $Guess it's time for another selfie!`, + ], + defeat: [ + `Let's take a selfie to remember this.`, + ] + }, + [TrainerType.BRASSIUS]: { + encounter: [ + `I assume you are ready? Let our collaborative work of art begin!`, + ], + victory: [ + `Ahhh…vant-garde!`, + ], + defeat: [ + `I will begin on a new piece at once!`, + ] + }, + [TrainerType.IONO]: { + encounter: [ + `How're ya feelin' about this battle? + $... + $Let's get this show on the road! How strong is our challenger? + $I 'unno! Let's find out together!`, + ], + victory: [ + `You're as flashy and bright as a 10,000,000-volt Thunderbolt, friendo!`, + ], + defeat: [ + `Your eyeballs are MINE!`, + ] + }, + [TrainerType.LARRY]: { + encounter: [ + `When all's said and done, simplicity is strongest.`, + ], + victory: [ + `A serving of defeat, huh?`, + ], + defeat: [ + `I'll call it a day.`, + ] + }, + [TrainerType.RYME]: { + encounter: [ + `Come on, baby! Rattle me down to the bone!`, + ], + victory: [ + `You're cool, my friend—you move my SOUL!`, + ], + defeat: [ + `Later, baby!`, + ] + }, + [TrainerType.GRUSHA]: { + encounter: [ + `All I need to do is make sure the power of my Pokémon chills you to the bone!`, + ], + victory: [ + `Your burning passion… I kinda like it, to be honest.`, + ], + defeat: [ + `Things didn't heat up for you.`, + ] + }, [TrainerType.RIVAL]: [ { encounter: [ diff --git a/src/data/trainer-config.ts b/src/data/trainer-config.ts index 5cde2e7b370..c13ea820e03 100644 --- a/src/data/trainer-config.ts +++ b/src/data/trainer-config.ts @@ -309,7 +309,7 @@ export class TrainerConfig { } setEncounterBgm(encounterBgm: TrainerType | string): TrainerConfig { - this.encounterBgm = typeof encounterBgm === 'number' ? TrainerType[encounterBgm].toString().replace(/\_/g, ' ').toLowerCase() : encounterBgm; + this.encounterBgm = typeof encounterBgm === 'number' ? TrainerType[encounterBgm].toString().toLowerCase() : encounterBgm; return this; } From 4f63b83bd9bc3f04c7f17f753b0faab414b921f8 Mon Sep 17 00:00:00 2001 From: Xavion3 Date: Thu, 11 Apr 2024 07:49:35 +1000 Subject: [PATCH 02/10] Add support for variable category moves Also lets shell side arm poison --- src/data/move.ts | 67 ++++++++++++++++++++++++++++++++++++++++---- src/field/pokemon.ts | 7 +++-- 2 files changed, 67 insertions(+), 7 deletions(-) diff --git a/src/data/move.ts b/src/data/move.ts index a296e3b4884..06f6a2c2de2 100644 --- a/src/data/move.ts +++ b/src/data/move.ts @@ -1898,6 +1898,57 @@ export class BlizzardAccuracyAttr extends VariableAccuracyAttr { } } +export class VariableMoveCategoryAttr extends MoveAttr { + apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { + return false; + } +} + +export class PhotonGeyserCategoryAttr extends VariableMoveCategoryAttr { + apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { + const category = (args[0] as Utils.IntegerHolder); + + if (user.getBattleStat(Stat.ATK, target, move) > user.getBattleStat(Stat.SPATK, target, move)) { + category.value = MoveCategory.PHYSICAL; + return true; + } + + return false; + } +} + +export class TeraBlastCategoryAttr extends VariableMoveCategoryAttr { + apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { + const category = (args[0] as Utils.IntegerHolder); + + if (user.isTerastallized() && user.getBattleStat(Stat.ATK, target, move) > user.getBattleStat(Stat.SPATK, target, move)) { + category.value = MoveCategory.PHYSICAL; + return true; + } + + return false; + } +} + +export class ShellSideArmCategoryAttr extends VariableMoveCategoryAttr { + apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { + const category = (args[0] as Utils.IntegerHolder); + const atkRatio = user.getBattleStat(Stat.ATK, target, move) / target.getBattleStat(Stat.DEF, user, move); + const defRatio = user.getBattleStat(Stat.SPATK, target, move) / target.getBattleStat(Stat.SPDEF, user, move); + + // Shell Side Arm is much more complicated than it looks, this is a partial implementation to try to achieve something similar to the games + if (atkRatio > defRatio) { + category.value = MoveCategory.PHYSICAL; + return true; + } else if (atkRatio === defRatio && user.randSeedInt(1) === 0) { + category.value = MoveCategory.PHYSICAL; + return true; + } + + return false; + } +} + export class VariableMoveTypeAttr extends MoveAttr { apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { return false; @@ -4672,9 +4723,11 @@ export function initMoves() { .target(MoveTarget.ALL_NEAR_OTHERS), new AttackMove(Moves.PLASMA_FISTS, "Plasma Fists (P)", Type.ELECTRIC, MoveCategory.PHYSICAL, 100, 100, 15, "The user attacks with electrically charged fists. This move changes Normal-type moves to Electric-type moves.", -1, 0, 7) .punchingMove(), - new AttackMove(Moves.PHOTON_GEYSER, "Photon Geyser (P)", Type.PSYCHIC, MoveCategory.SPECIAL, 100, 100, 5, "The user attacks a target with a pillar of light. This move inflicts Attack or Sp. Atk damage—whichever stat is higher for the user.", -1, 0, 7), + new AttackMove(Moves.PHOTON_GEYSER, "Photon Geyser (P)", Type.PSYCHIC, MoveCategory.SPECIAL, 100, 100, 5, "The user attacks a target with a pillar of light. This move inflicts Attack or Sp. Atk damage—whichever stat is higher for the user.", -1, 0, 7) + .attr(PhotonGeyserCategoryAttr), /* Unused */ - new AttackMove(Moves.LIGHT_THAT_BURNS_THE_SKY, "Light That Burns the Sky (P)", Type.PSYCHIC, MoveCategory.SPECIAL, 200, -1, 1, "This attack inflicts Attack or Sp. Atk damage—whichever stat is higher for the user, Necrozma. This move ignores the target's Ability.", -1, 0, 7), + new AttackMove(Moves.LIGHT_THAT_BURNS_THE_SKY, "Light That Burns the Sky (P)", Type.PSYCHIC, MoveCategory.SPECIAL, 200, -1, 1, "This attack inflicts Attack or Sp. Atk damage—whichever stat is higher for the user, Necrozma. This move ignores the target's Ability.", -1, 0, 7) + .attr(PhotonGeyserCategoryAttr), new AttackMove(Moves.SEARING_SUNRAZE_SMASH, "Searing Sunraze Smash (P)", Type.STEEL, MoveCategory.PHYSICAL, 200, -1, 1, "After obtaining Z-Power, the user, Solgaleo, attacks the target with full force. This move can ignore the effect of the target's Ability.", -1, 0, 7), new AttackMove(Moves.MENACING_MOONRAZE_MAELSTROM, "Menacing Moonraze Maelstrom (P)", Type.GHOST, MoveCategory.SPECIAL, 200, -1, 1, "After obtaining Z-Power, the user, Lunala, attacks the target with full force. This move can ignore the effect of the target's Ability.", -1, 0, 7), new AttackMove(Moves.LETS_SNUGGLE_FOREVER, "Let's Snuggle Forever (P)", Type.FAIRY, MoveCategory.PHYSICAL, 190, -1, 1, "After obtaining Z-Power, the user, Mimikyu, punches the target with full force.", -1, 0, 7), @@ -4855,7 +4908,9 @@ export function initMoves() { .attr(ChargeAttr, ChargeAnim.METEOR_BEAM_CHARGING, 'is overflowing\nwith space power!', null, true) .attr(StatChangeAttr, BattleStat.SPATK, 1, true) .ignoresVirtual(), - new AttackMove(Moves.SHELL_SIDE_ARM, "Shell Side Arm (P)", Type.POISON, MoveCategory.SPECIAL, 90, 100, 10, "This move inflicts physical or special damage, whichever will be more effective. This may also poison the target.", 20, 0, 8), + new AttackMove(Moves.SHELL_SIDE_ARM, "Shell Side Arm (P)", Type.POISON, MoveCategory.SPECIAL, 90, 100, 10, "This move inflicts physical or special damage, whichever will be more effective. This may also poison the target.", 20, 0, 8) + .attr(ShellSideArmCategoryAttr) + .attr(StatusEffectAttr, StatusEffect.POISON), new AttackMove(Moves.MISTY_EXPLOSION, "Misty Explosion (P)", Type.FAIRY, MoveCategory.SPECIAL, 100, 100, 5, "The user attacks everything around it and faints upon using this move. This move's power is increased on Misty Terrain.", -1, 0, 8) .target(MoveTarget.ALL_NEAR_OTHERS), new AttackMove(Moves.GRASSY_GLIDE, "Grassy Glide (P)", Type.GRASS, MoveCategory.PHYSICAL, 55, 100, 20, "Gliding on the ground, the user attacks the target. This move always goes first on Grassy Terrain.", -1, 0, 8), @@ -5057,7 +5112,8 @@ export function initMoves() { new AttackMove(Moves.G_MAX_RAPID_FLOW, "G-Max Rapid Flow (N)", Type.WATER, MoveCategory.PHYSICAL, 10, -1, 10, "A Water-type attack that Gigantamax Urshifu use. This rapid-strike move can ignore Max Guard.", -1, 0, 8) .target(MoveTarget.ALL_NEAR_ENEMIES), End Unused */ - new AttackMove(Moves.TERA_BLAST, "Tera Blast (P)", Type.NORMAL, MoveCategory.SPECIAL, 80, 100, 10, "If the user has Terastallized, it unleashes energy of its Tera Type. This move inflicts damage using the Attack or Sp. Atk stat-whichever is higher for the user.", -1, 0, 9), + new AttackMove(Moves.TERA_BLAST, "Tera Blast (P)", Type.NORMAL, MoveCategory.SPECIAL, 80, 100, 10, "If the user has Terastallized, it unleashes energy of its Tera Type. This move inflicts damage using the Attack or Sp. Atk stat-whichever is higher for the user.", -1, 0, 9) + .attr(TeraBlastCategoryAttr), new SelfStatusMove(Moves.SILK_TRAP, "Silk Trap", Type.BUG, -1, 10, "The user spins a silken trap, protecting itself from damage while lowering the Speed stat of any attacker that makes direct contact.", -1, 4, 9) .attr(ProtectAttr, BattlerTagType.SILK_TRAP), new AttackMove(Moves.AXE_KICK, "Axe Kick", Type.FIGHTING, MoveCategory.PHYSICAL, 120, 90, 10, "The user attacks by kicking up into the air and slamming its heel down upon the target. This may also confuse the target. If it misses, the user takes damage instead.", 30, 0, 9) @@ -5193,7 +5249,8 @@ export function initMoves() { .attr(ElectroShotChargeAttr) .attr(StatChangeAttr, BattleStat.SPATK, 1, true) .ignoresVirtual(), - new AttackMove(Moves.TERA_STARSTORM, "Tera Starstorm (P)", Type.NORMAL, MoveCategory.SPECIAL, 120, 100, 5, "With the power of its crystals, the user bombards and eliminates the target. When used by Terapagos in its Stellar Form, this move damages all opposing Pokémon.", -1, 0, 9), + new AttackMove(Moves.TERA_STARSTORM, "Tera Starstorm (P)", Type.NORMAL, MoveCategory.SPECIAL, 120, 100, 5, "With the power of its crystals, the user bombards and eliminates the target. When used by Terapagos in its Stellar Form, this move damages all opposing Pokémon.", -1, 0, 9) + .attr(TeraBlastCategoryAttr), new AttackMove(Moves.FICKLE_BEAM, "Fickle Beam", Type.DRAGON, MoveCategory.SPECIAL, 80, 100, 5, "The user shoots a beam of light to inflict damage. Sometimes all the user's heads shoot beams in unison, doubling the move's power.", 30, 0, 9) .attr(PreMoveMessageAttr, doublePowerChanceMessageFunc) .attr(DoublePowerChanceAttr), diff --git a/src/field/pokemon.ts b/src/field/pokemon.ts index 6f4d09ea7a2..e5b7f75186b 100644 --- a/src/field/pokemon.ts +++ b/src/field/pokemon.ts @@ -2,7 +2,7 @@ import Phaser from 'phaser'; import BattleScene, { ABILITY_OVERRIDE, AnySound, MOVE_OVERRIDE, OPP_ABILITY_OVERRIDE, OPP_MOVE_OVERRIDE } from '../battle-scene'; import BattleInfo, { PlayerBattleInfo, EnemyBattleInfo } from '../ui/battle-info'; import { Moves } from "../data/enums/moves"; -import Move, { HighCritAttr, HitsTagAttr, applyMoveAttrs, FixedDamageAttr, VariableAtkAttr, VariablePowerAttr, allMoves, MoveCategory, TypelessAttr, CritOnlyAttr, getMoveTargets, OneHitKOAttr, MultiHitAttr, StatusMoveTypeImmunityAttr, MoveTarget, VariableDefAttr, AttackMove, ModifiedDamageAttr, VariableMoveTypeMultiplierAttr, IgnoreOpponentStatChangesAttr, SacrificialAttr, VariableMoveTypeAttr } from "../data/move"; +import Move, { HighCritAttr, HitsTagAttr, applyMoveAttrs, FixedDamageAttr, VariableAtkAttr, VariablePowerAttr, allMoves, MoveCategory, TypelessAttr, CritOnlyAttr, getMoveTargets, OneHitKOAttr, MultiHitAttr, StatusMoveTypeImmunityAttr, MoveTarget, VariableDefAttr, AttackMove, ModifiedDamageAttr, VariableMoveTypeMultiplierAttr, IgnoreOpponentStatChangesAttr, SacrificialAttr, VariableMoveTypeAttr, VariableMoveCategoryAttr } from "../data/move"; import { default as PokemonSpecies, PokemonSpeciesForm, SpeciesFormKey, getFusedSpeciesName, getPokemonSpecies, getPokemonSpeciesForm } from '../data/pokemon-species'; import * as Utils from '../utils'; import { Type, TypeDamageMultiplier, getTypeDamageMultiplier, getTypeRgb } from '../data/type'; @@ -1093,9 +1093,12 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { apply(source: Pokemon, battlerMove: PokemonMove): HitResult { let result: HitResult; const move = battlerMove.getMove(); - const moveCategory = move.category; let damage = new Utils.NumberHolder(0); + const variableCategory = new Utils.IntegerHolder(move.category); + applyMoveAttrs(VariableMoveCategoryAttr, source, this, move, variableCategory); + const moveCategory = variableCategory.value as MoveCategory; + const variableType = new Utils.IntegerHolder(move.type); const typeChangeMovePowerMultiplier = new Utils.NumberHolder(1); applyMoveAttrs(VariableMoveTypeAttr, source, this, move, variableType); From 4f1fa4e19223888a8c2a23d1602129148d29ec75 Mon Sep 17 00:00:00 2001 From: Xavion3 Date: Thu, 11 Apr 2024 10:45:33 +1000 Subject: [PATCH 03/10] Fix random category Also fix the variable name --- src/data/move.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/data/move.ts b/src/data/move.ts index 06f6a2c2de2..c8ead786b33 100644 --- a/src/data/move.ts +++ b/src/data/move.ts @@ -1934,13 +1934,13 @@ export class ShellSideArmCategoryAttr extends VariableMoveCategoryAttr { apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { const category = (args[0] as Utils.IntegerHolder); const atkRatio = user.getBattleStat(Stat.ATK, target, move) / target.getBattleStat(Stat.DEF, user, move); - const defRatio = user.getBattleStat(Stat.SPATK, target, move) / target.getBattleStat(Stat.SPDEF, user, move); + const specialRatio = user.getBattleStat(Stat.SPATK, target, move) / target.getBattleStat(Stat.SPDEF, user, move); // Shell Side Arm is much more complicated than it looks, this is a partial implementation to try to achieve something similar to the games - if (atkRatio > defRatio) { + if (atkRatio > specialRatio) { category.value = MoveCategory.PHYSICAL; return true; - } else if (atkRatio === defRatio && user.randSeedInt(1) === 0) { + } else if (atkRatio === specialRatio && user.randSeedInt(2) === 0) { category.value = MoveCategory.PHYSICAL; return true; } From a337e9499a5ab592e4f6d4a240b8be8608837d1e Mon Sep 17 00:00:00 2001 From: Jason Halvorson <47071224+JasonHalvorson@users.noreply.github.com> Date: Tue, 9 Apr 2024 12:55:06 -0700 Subject: [PATCH 04/10] Fix Diancie's gender Diancie is genderless, so I've removed it's gender --- src/data/pokemon-species.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/data/pokemon-species.ts b/src/data/pokemon-species.ts index 02c259d5075..e0ef53d9628 100644 --- a/src/data/pokemon-species.ts +++ b/src/data/pokemon-species.ts @@ -1835,7 +1835,7 @@ export function initSpecies() { new PokemonForm("10% Forme Power Construct", "10-pc", Type.DRAGON, Type.GROUND, 1.2, 33.5, Abilities.POWER_CONSTRUCT, Abilities.NONE, Abilities.NONE, 486, 54, 100, 71, 61, 85, 115, 3, 0, 300, false, "10"), new PokemonForm("Complete Forme", "complete", Type.DRAGON, Type.GROUND, 4.5, 610, Abilities.POWER_CONSTRUCT, Abilities.NONE, Abilities.NONE, 708, 216, 100, 121, 91, 95, 85, 3, 0, 300), ), - new PokemonSpecies(Species.DIANCIE, "Diancie", 6, false, false, true, "Jewel Pokémon", Type.ROCK, Type.FAIRY, 0.7, 8.8, Abilities.CLEAR_BODY, Abilities.NONE, Abilities.NONE, 600, 50, 100, 150, 100, 150, 50, 3, 50, 300, GrowthRate.SLOW, 0, false, true, + new PokemonSpecies(Species.DIANCIE, "Diancie", 6, false, false, true, "Jewel Pokémon", Type.ROCK, Type.FAIRY, 0.7, 8.8, Abilities.CLEAR_BODY, Abilities.NONE, Abilities.NONE, 600, 50, 100, 150, 100, 150, 50, 3, 50, 300, GrowthRate.SLOW, null, false, true, new PokemonForm("Normal", "", Type.ROCK, Type.FAIRY, 0.7, 8.8, Abilities.CLEAR_BODY, Abilities.NONE, Abilities.NONE, 600, 50, 100, 150, 100, 150, 50, 3, 50, 300), new PokemonForm("Mega", SpeciesFormKey.MEGA, Type.ROCK, Type.FAIRY, 1.1, 27.8, Abilities.MAGIC_BOUNCE, Abilities.NONE, Abilities.NONE, 700, 50, 160, 110, 160, 110, 110, 3, 50, 300), ), @@ -3071,4 +3071,4 @@ export const noStarterFormKeys: string[] = [ return s; }))].map(s => s.name));*/ //}, 1000); -} \ No newline at end of file +} From b2beb8e0c8bcfb56bef15b3203f41a88c1459977 Mon Sep 17 00:00:00 2001 From: Madmadness65 Date: Wed, 10 Apr 2024 21:59:08 -0500 Subject: [PATCH 05/10] Chespin now has Tackle at level 1 Minor change to give the only starter without a normal attack one. Chesnaught *does* have it at level 1 oddly enough. --- src/data/pokemon-level-moves.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/data/pokemon-level-moves.ts b/src/data/pokemon-level-moves.ts index bc72a3bd0f5..81fb79660fe 100644 --- a/src/data/pokemon-level-moves.ts +++ b/src/data/pokemon-level-moves.ts @@ -10888,6 +10888,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 91, Moves.SELF_DESTRUCT ], ], [Species.CHESPIN]: [ + [ 1, Moves.TACKLE ], [ 1, Moves.VINE_WHIP ], [ 1, Moves.GROWL ], [ 8, Moves.ROLLOUT ], @@ -10902,6 +10903,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 48, Moves.WOOD_HAMMER ], ], [Species.QUILLADIN]: [ + [ 1, Moves.TACKLE ], [ 1, Moves.VINE_WHIP ], [ 1, Moves.GROWL ], [ 8, Moves.ROLLOUT ], From b9a068e3b7d749f3370d123961ecf6d05ea804fd Mon Sep 17 00:00:00 2001 From: AppleOfTheDark <72869654+AppleOfTheDark@users.noreply.github.com> Date: Thu, 11 Apr 2024 05:16:09 +0100 Subject: [PATCH 06/10] Implement Shed Skin (and Hydration!) (#84) * Implement Shed Skin (and Hydration!) Implemented Shed Skin, with a 1/3 chance to remove a non-volatile status condition if inflicted with it at the end of each turn. While doing this I noticed Hydration is the same effect but in Rain/Heavy Rain, so I implemented that too. * Update to ability.ts based on changes. Formatting errors should be largely fixed, and we've switched from Math.rand to Utils. * Update src/data/ability.ts --------- Co-authored-by: Samuel H --- src/data/ability.ts | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/src/data/ability.ts b/src/data/ability.ts index 6c00f86d5ad..713a28d10d9 100644 --- a/src/data/ability.ts +++ b/src/data/ability.ts @@ -7,7 +7,7 @@ import { getPokemonMessage } from "../messages"; import { Weather, WeatherType } from "./weather"; import { BattlerTag } from "./battler-tags"; import { BattlerTagType } from "./enums/battler-tag-type"; -import { StatusEffect, getStatusEffectDescriptor } from "./status-effect"; +import { StatusEffect, getStatusEffectDescriptor, getStatusEffectHealText } from "./status-effect"; import Move, { AttackMove, MoveCategory, MoveFlags, MoveTarget, RecoilAttr, StatusMoveTypeImmunityAttr, allMoves } from "./move"; import { ArenaTagType } from "./enums/arena-tag-type"; import { Stat } from "./pokemon-stat"; @@ -1366,6 +1366,20 @@ export class PostTurnAbAttr extends AbAttr { } } +export class PostTurnResetStatusAbAttr extends PostTurnAbAttr { + applyPostTurn(pokemon: Pokemon, args: any[]): boolean { + if (pokemon.status) { + + pokemon.scene.queueMessage(getPokemonMessage(pokemon, getStatusEffectHealText(pokemon.status?.effect))); + pokemon.resetStatus(); + pokemon.updateInfo(); + return true; + } + + return false; + } +} + export class PostTurnStatChangeAbAttr extends PostTurnAbAttr { private stats: BattleStat[]; private levels: integer; @@ -2376,7 +2390,8 @@ export function initAbilities() { .attr(BlockItemTheftAbAttr) .passive() .ignorable(), - new Ability(Abilities.SHED_SKIN, "Shed Skin (N)", "The Pokémon may heal its own status conditions by shedding its skin.", 3), + new Ability(Abilities.SHED_SKIN, "Shed Skin", "The Pokémon may heal its own status conditions by shedding its skin.", 3) + .conditionalAttr(pokemon => !Utils.randSeedInt(3), PostTurnResetStatusAbAttr), new Ability(Abilities.GUTS, "Guts", "It's so gutsy that having a status condition boosts the Pokémon's Attack stat.", 3) .attr(BypassBurnDamageReductionAbAttr) .conditionalAttr(pokemon => !!pokemon.status, BattleStatMultiplierAbAttr, BattleStat.ATK, 1.5), @@ -2451,7 +2466,9 @@ export function initAbilities() { .attr(StabBoostAbAttr), new Ability(Abilities.SKILL_LINK, "Skill Link", "Maximizes the number of times multistrike moves hit.", 4) .attr(MaxMultiHitAbAttr), - new Ability(Abilities.HYDRATION, "Hydration (N)", "Heals status conditions if it's raining.", 4), + new Ability(Abilities.HYDRATION, "Hydration", "Heals status conditions if it's raining.", 4) + .attr(PostTurnResetStatusAbAttr) + .condition(getWeatherCondition(WeatherType.RAIN, WeatherType.HEAVY_RAIN)), new Ability(Abilities.SOLAR_POWER, "Solar Power", "Boosts the Sp. Atk stat in harsh sunlight, but HP decreases every turn.", 4) .attr(PostWeatherLapseDamageAbAttr, 2, WeatherType.SUNNY, WeatherType.HARSH_SUN) .attr(BattleStatMultiplierAbAttr, BattleStat.SPATK, 1.5) From 75075c6fabe3804a6c80abd7364232355ac3e7ed Mon Sep 17 00:00:00 2001 From: Flashfyre Date: Thu, 11 Apr 2024 00:18:16 -0400 Subject: [PATCH 07/10] Update missing save data handling --- src/account.ts | 1 - src/system/game-data.ts | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/account.ts b/src/account.ts index 104ad15704c..a2ff71a6ed3 100644 --- a/src/account.ts +++ b/src/account.ts @@ -22,7 +22,6 @@ export function updateUserInfo(): Promise<[boolean, integer]> { return resolve([ true, 200 ]); } Utils.apiFetch('account/info').then(response => { - console.log(response.status); if (!response.ok) { resolve([ false, response.status ]); return; diff --git a/src/system/game-data.ts b/src/system/game-data.ts index 248a3705122..1bf3852740a 100644 --- a/src/system/game-data.ts +++ b/src/system/game-data.ts @@ -360,7 +360,7 @@ export class GameData { .then(response => response.text()) .then(response => { if (!response.length || response[0] !== '{') { - if (response.startsWith('failed to read save file')) { + if (response.startsWith('failed to open save file')) { this.scene.queueMessage('Save data could not be found. If this is a new account, you can safely ignore this message.', null, true); return resolve(true); } From 31050a5181e89c6db423a60cbd60579f4533e886 Mon Sep 17 00:00:00 2001 From: Flashfyre Date: Thu, 11 Apr 2024 09:24:03 -0400 Subject: [PATCH 08/10] Add passive secondary abilities for bosses --- src/battle-scene.ts | 3 +- src/data/ability.ts | 672 ++++++++++-------------------------- src/data/api.ts | 3 +- src/data/battler-tags.ts | 13 +- src/data/enums/abilities.ts | 313 +++++++++++++++++ src/data/move.ts | 13 +- src/data/pokemon-forms.ts | 2 +- src/data/pokemon-species.ts | 574 +++++++++++++++++++++++++++++- src/data/weather.ts | 4 +- src/field/pokemon.ts | 22 +- src/phases.ts | 23 +- src/ui/ability-bar.ts | 6 +- 12 files changed, 1127 insertions(+), 521 deletions(-) create mode 100644 src/data/enums/abilities.ts diff --git a/src/battle-scene.ts b/src/battle-scene.ts index 3090bbe1c8b..27166347039 100644 --- a/src/battle-scene.ts +++ b/src/battle-scene.ts @@ -19,7 +19,8 @@ import { } from "./data/move"; import { initMoves } from './data/move'; import { ModifierPoolType, getDefaultModifierTypeForTier, getEnemyModifierTypesForWave } from './modifier/modifier-type'; import AbilityBar from './ui/ability-bar'; -import { Abilities, BlockItemTheftAbAttr, DoubleBattleChanceAbAttr, IncrementMovePriorityAbAttr, applyAbAttrs, initAbilities } from './data/ability'; +import { BlockItemTheftAbAttr, DoubleBattleChanceAbAttr, IncrementMovePriorityAbAttr, applyAbAttrs, initAbilities } from './data/ability'; +import { Abilities } from "./data/enums/abilities"; import Battle, { BattleType, FixedBattleConfig, fixedBattles } from './battle'; import { GameMode, GameModes, gameModes } from './game-mode'; import FieldSpritePipeline from './pipelines/field-sprite'; diff --git a/src/data/ability.ts b/src/data/ability.ts index 713a28d10d9..1d5dcb7581f 100644 --- a/src/data/ability.ts +++ b/src/data/ability.ts @@ -15,13 +15,14 @@ import { PokemonHeldItemModifier } from "../modifier/modifier"; import { Moves } from "./enums/moves"; import { TerrainType } from "./terrain"; import { SpeciesFormChangeManualTrigger } from "./pokemon-forms"; +import { Abilities } from "./enums/abilities"; export class Ability { public id: Abilities; public name: string; public description: string; public generation: integer; - public isPassive: boolean; + public isBypassFaint: boolean; public isIgnorable: boolean; public attrs: AbAttr[]; public conditions: AbAttrCondition[]; @@ -58,8 +59,8 @@ export class Ability { return !!this.getAttrs(attrType).length; } - passive(): Ability { - this.isPassive = true; + bypassFaint(): Ability { + this.isBypassFaint = true; return this; } @@ -75,7 +76,7 @@ export class Ability { } } -type AbAttrApplyFunc = (attr: TAttr) => boolean | Promise; +type AbAttrApplyFunc = (attr: TAttr, passive: boolean) => boolean | Promise; type AbAttrCondition = (pokemon: Pokemon) => boolean; type PokemonAttackCondition = (user: Pokemon, target: Pokemon, move: Move) => boolean; @@ -89,11 +90,11 @@ export abstract class AbAttr { this.showAbility = showAbility; } - apply(pokemon: Pokemon, cancelled: Utils.BooleanHolder, args: any[]): boolean | Promise { + apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean | Promise { return false; } - getTriggerMessage(pokemon: Pokemon, ...args: any[]): string { + getTriggerMessage(pokemon: Pokemon, abilityName: string, ...args: any[]): string { return null; } @@ -108,14 +109,14 @@ export abstract class AbAttr { } export class BlockRecoilDamageAttr extends AbAttr { - apply(pokemon: Pokemon, cancelled: Utils.BooleanHolder, args: any[]): boolean { + apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { cancelled.value = true; return true; } - getTriggerMessage(pokemon: Pokemon, ...args: any[]) { - return getPokemonMessage(pokemon, `'s ${pokemon.getAbility().name}\nprotected it from recoil!`); + getTriggerMessage(pokemon: Pokemon, abilityName: string, ...args: any[]) { + return getPokemonMessage(pokemon, `'s ${abilityName}\nprotected it from recoil!`); } } @@ -124,7 +125,7 @@ export class DoubleBattleChanceAbAttr extends AbAttr { super(false); } - apply(pokemon: Pokemon, cancelled: Utils.BooleanHolder, args: any[]): boolean { + apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { const doubleChance = (args[0] as Utils.IntegerHolder); doubleChance.value = Math.max(doubleChance.value / 2, 1); return true; @@ -132,7 +133,7 @@ export class DoubleBattleChanceAbAttr extends AbAttr { } export class PostBattleInitAbAttr extends AbAttr { - applyPostBattleInit(pokemon: Pokemon, args: any[]): boolean | Promise { + applyPostBattleInit(pokemon: Pokemon, passive: boolean, args: any[]): boolean | Promise { return false; } } @@ -146,7 +147,7 @@ export class PostBattleInitFormChangeAbAttr extends PostBattleInitAbAttr { this.formFunc = formFunc; } - applyPostBattleInit(pokemon: Pokemon, args: any[]): boolean { + applyPostBattleInit(pokemon: Pokemon, passive: boolean, args: any[]): boolean { const formIndex = this.formFunc(pokemon); if (formIndex !== pokemon.formIndex) return pokemon.scene.triggerPokemonFormChange(pokemon, SpeciesFormChangeManualTrigger, false); @@ -170,7 +171,7 @@ export class PostBattleInitStatChangeAbAttr extends PostBattleInitAbAttr { this.selfTarget = !!selfTarget; } - applyPostBattleInit(pokemon: Pokemon, args: any[]): boolean { + applyPostBattleInit(pokemon: Pokemon, passive: boolean, args: any[]): boolean { const statChangePhases: StatChangePhase[] = []; if (this.selfTarget) @@ -194,13 +195,13 @@ export class PostBattleInitStatChangeAbAttr extends PostBattleInitAbAttr { type PreDefendAbAttrCondition = (pokemon: Pokemon, attacker: Pokemon, move: PokemonMove) => boolean; export class PreDefendAbAttr extends AbAttr { - applyPreDefend(pokemon: Pokemon, attacker: Pokemon, move: PokemonMove, cancelled: Utils.BooleanHolder, args: any[]): boolean | Promise { + applyPreDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, cancelled: Utils.BooleanHolder, args: any[]): boolean | Promise { return false; } } export class PreDefendFullHpEndureAbAttr extends PreDefendAbAttr { - applyPreDefend(pokemon: Pokemon, attacker: Pokemon, move: PokemonMove, cancelled: Utils.BooleanHolder, args: any[]): boolean { + applyPreDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, cancelled: Utils.BooleanHolder, args: any[]): boolean { if (pokemon.getHpRatio() < 1 || (args[0] as Utils.NumberHolder).value < pokemon.hp) return false; @@ -209,19 +210,19 @@ export class PreDefendFullHpEndureAbAttr extends PreDefendAbAttr { } export class BlockItemTheftAbAttr extends AbAttr { - apply(pokemon: Pokemon, cancelled: Utils.BooleanHolder, args: any[]): boolean { + apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { cancelled.value = true; return true; } - getTriggerMessage(pokemon: Pokemon, ...args: any[]) { - return getPokemonMessage(pokemon, `'s ${pokemon.getAbility().name}\nprevents item theft!`); + getTriggerMessage(pokemon: Pokemon, abilityName: string, ...args: any[]) { + return getPokemonMessage(pokemon, `'s ${abilityName}\nprevents item theft!`); } } export class StabBoostAbAttr extends AbAttr { - apply(pokemon: Pokemon, cancelled: Utils.BooleanHolder, args: any[]): boolean { + apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { if ((args[0] as Utils.NumberHolder).value > 1) { (args[0] as Utils.NumberHolder).value += 0.5; return true; @@ -242,7 +243,7 @@ export class ReceivedMoveDamageMultiplierAbAttr extends PreDefendAbAttr { this.powerMultiplier = powerMultiplier; } - applyPreDefend(pokemon: Pokemon, attacker: Pokemon, move: PokemonMove, cancelled: Utils.BooleanHolder, args: any[]): boolean { + applyPreDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, cancelled: Utils.BooleanHolder, args: any[]): boolean { if (this.condition(pokemon, attacker, move.getMove())) { (args[0] as Utils.NumberHolder).value *= this.powerMultiplier; return true; @@ -269,7 +270,7 @@ export class TypeImmunityAbAttr extends PreDefendAbAttr { this.condition = condition; } - applyPreDefend(pokemon: Pokemon, attacker: Pokemon, move: PokemonMove, cancelled: Utils.BooleanHolder, args: any[]): boolean { + applyPreDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, cancelled: Utils.BooleanHolder, args: any[]): boolean { if ((move.getMove() instanceof AttackMove || move.getMove().getAttrs(StatusMoveTypeImmunityAttr).find(attr => (attr as StatusMoveTypeImmunityAttr).immuneType === this.immuneType)) && move.getMove().type === this.immuneType) { (args[0] as Utils.NumberHolder).value = 0; return true; @@ -288,15 +289,16 @@ export class TypeImmunityHealAbAttr extends TypeImmunityAbAttr { super(immuneType); } - applyPreDefend(pokemon: Pokemon, attacker: Pokemon, move: PokemonMove, cancelled: Utils.BooleanHolder, args: any[]): boolean { - const ret = super.applyPreDefend(pokemon, attacker, move, cancelled, args); + applyPreDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, cancelled: Utils.BooleanHolder, args: any[]): boolean { + const ret = super.applyPreDefend(pokemon, passive, attacker, move, cancelled, args); if (ret) { if (pokemon.getHpRatio() < 1) { const simulated = args.length > 1 && args[1]; if (!simulated) { + const abilityName = (!passive ? pokemon.getAbility() : pokemon.getPassiveAbility()).name; pokemon.scene.unshiftPhase(new PokemonHealPhase(pokemon.scene, pokemon.getBattlerIndex(), - Math.max(Math.floor(pokemon.getMaxHp() / 4), 1), getPokemonMessage(pokemon, `'s ${pokemon.getAbility().name}\nrestored its HP a little!`), true)); + Math.max(Math.floor(pokemon.getMaxHp() / 4), 1), getPokemonMessage(pokemon, `'s ${abilityName}\nrestored its HP a little!`), true)); } } return true; @@ -317,8 +319,8 @@ class TypeImmunityStatChangeAbAttr extends TypeImmunityAbAttr { this.levels = levels; } - applyPreDefend(pokemon: Pokemon, attacker: Pokemon, move: PokemonMove, cancelled: Utils.BooleanHolder, args: any[]): boolean { - const ret = super.applyPreDefend(pokemon, attacker, move, cancelled, args); + applyPreDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, cancelled: Utils.BooleanHolder, args: any[]): boolean { + const ret = super.applyPreDefend(pokemon, passive, attacker, move, cancelled, args); if (ret) { cancelled.value = true; @@ -342,8 +344,8 @@ class TypeImmunityAddBattlerTagAbAttr extends TypeImmunityAbAttr { this.turnCount = turnCount; } - applyPreDefend(pokemon: Pokemon, attacker: Pokemon, move: PokemonMove, cancelled: Utils.BooleanHolder, args: any[]): boolean { - const ret = super.applyPreDefend(pokemon, attacker, move, cancelled, args); + applyPreDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, cancelled: Utils.BooleanHolder, args: any[]): boolean { + const ret = super.applyPreDefend(pokemon, passive, attacker, move, cancelled, args); if (ret) { cancelled.value = true; @@ -361,7 +363,7 @@ export class NonSuperEffectiveImmunityAbAttr extends TypeImmunityAbAttr { super(null, condition); } - applyPreDefend(pokemon: Pokemon, attacker: Pokemon, move: PokemonMove, cancelled: Utils.BooleanHolder, args: any[]): boolean { + applyPreDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, cancelled: Utils.BooleanHolder, args: any[]): boolean { if (move.getMove() instanceof AttackMove && pokemon.getAttackTypeEffectiveness(move.getMove().type) < 2) { cancelled.value = true; (args[0] as Utils.NumberHolder).value = 0; @@ -371,13 +373,13 @@ export class NonSuperEffectiveImmunityAbAttr extends TypeImmunityAbAttr { return false; } - getTriggerMessage(pokemon: Pokemon, ...args: any[]): string { - return getPokemonMessage(pokemon, ` avoided damage\nwith ${pokemon.getAbility().name}!`); + getTriggerMessage(pokemon: Pokemon, abilityName: string, ...args: any[]): string { + return getPokemonMessage(pokemon, ` avoided damage\nwith ${abilityName}!`); } } export class PostDefendAbAttr extends AbAttr { - applyPostDefend(pokemon: Pokemon, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean | Promise { + applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean | Promise { return false; } } @@ -391,7 +393,7 @@ export class MoveImmunityAbAttr extends PreDefendAbAttr { this.immuneCondition = immuneCondition; } - applyPreDefend(pokemon: Pokemon, attacker: Pokemon, move: PokemonMove, cancelled: Utils.BooleanHolder, args: any[]): boolean { + applyPreDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, cancelled: Utils.BooleanHolder, args: any[]): boolean { if (this.immuneCondition(pokemon, attacker, move)) { cancelled.value = true; return true; @@ -400,7 +402,7 @@ export class MoveImmunityAbAttr extends PreDefendAbAttr { return false; } - getTriggerMessage(pokemon: Pokemon, ...args: any[]): string { + getTriggerMessage(pokemon: Pokemon, abilityName: string, ...args: any[]): string { return `It doesn\'t affect ${pokemon.name}!`; } } @@ -420,7 +422,7 @@ export class PostDefendStatChangeAbAttr extends PostDefendAbAttr { this.selfTarget = selfTarget; } - applyPostDefend(pokemon: Pokemon, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean { + applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean { if (this.condition(pokemon, attacker, move.getMove())) { pokemon.scene.unshiftPhase(new StatChangePhase(pokemon.scene, (this.selfTarget ? pokemon : attacker).getBattlerIndex(), true, [ this.stat ], this.levels)); return true; @@ -431,7 +433,7 @@ export class PostDefendStatChangeAbAttr extends PostDefendAbAttr { } export class PostDefendTypeChangeAbAttr extends PostDefendAbAttr { - applyPostDefend(pokemon: Pokemon, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean { + applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean { if (hitResult < HitResult.NO_EFFECT) { const type = move.getMove().type; const pokemonTypes = pokemon.getTypes(true); @@ -444,8 +446,8 @@ export class PostDefendTypeChangeAbAttr extends PostDefendAbAttr { return false; } - getTriggerMessage(pokemon: Pokemon, ...args: any[]): string { - return getPokemonMessage(pokemon, `'s ${pokemon.getAbility().name}\nmade it the ${Utils.toReadableString(Type[pokemon.getTypes(true)[0]])} type!`); + getTriggerMessage(pokemon: Pokemon, abilityName: string, ...args: any[]): string { + return getPokemonMessage(pokemon, `'s ${abilityName}\nmade it the ${Utils.toReadableString(Type[pokemon.getTypes(true)[0]])} type!`); } } @@ -458,7 +460,7 @@ export class PostDefendTerrainChangeAbAttr extends PostDefendAbAttr { this.terrainType = terrainType; } - applyPostDefend(pokemon: Pokemon, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean { + applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean { if (hitResult < HitResult.NO_EFFECT) return pokemon.scene.arena.trySetTerrain(this.terrainType, true); @@ -477,7 +479,7 @@ export class PostDefendContactApplyStatusEffectAbAttr extends PostDefendAbAttr { this.effects = effects; } - applyPostDefend(pokemon: Pokemon, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean { + applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean { if (move.getMove().checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon) && !attacker.status && (this.chance === -1 || pokemon.randSeedInt(100) < this.chance)) { const effect = this.effects.length === 1 ? this.effects[0] : this.effects[pokemon.randSeedInt(this.effects.length)]; return attacker.trySetStatus(effect, true); @@ -500,7 +502,7 @@ export class PostDefendContactApplyTagChanceAbAttr extends PostDefendAbAttr { this.turnCount = turnCount; } - applyPostDefend(pokemon: Pokemon, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean { + applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean { if (move.getMove().checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon) && pokemon.randSeedInt(100) < this.chance) return attacker.addTag(this.tagType, this.turnCount, move.moveId, attacker.id); @@ -519,7 +521,7 @@ export class PostDefendCritStatChangeAbAttr extends PostDefendAbAttr { this.levels = levels; } - applyPostDefend(pokemon: Pokemon, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean { + applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean { pokemon.scene.unshiftPhase(new StatChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, [ this.stat ], this.levels)); return true; @@ -539,7 +541,7 @@ export class PostDefendContactDamageAbAttr extends PostDefendAbAttr { this.damageRatio = damageRatio; } - applyPostDefend(pokemon: Pokemon, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean { + applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean { if (move.getMove().checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon)) { attacker.damageAndUpdate(Math.ceil(attacker.getMaxHp() * (1 / this.damageRatio)), HitResult.OTHER); return true; @@ -548,8 +550,8 @@ export class PostDefendContactDamageAbAttr extends PostDefendAbAttr { return false; } - getTriggerMessage(pokemon: Pokemon, ...args: any[]): string { - return getPokemonMessage(pokemon, `'s ${pokemon.getAbility().name}\nhurt its attacker!`); + getTriggerMessage(pokemon: Pokemon, abilityName: string, ...args: any[]): string { + return getPokemonMessage(pokemon, `'s ${abilityName}\nhurt its attacker!`); } } @@ -562,7 +564,7 @@ export class PostDefendWeatherChangeAbAttr extends PostDefendAbAttr { this.weatherType = weatherType; } - applyPostDefend(pokemon: Pokemon, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean { + applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean { if (!pokemon.scene.arena.weather?.isImmutable()) return pokemon.scene.arena.trySetWeather(this.weatherType, true); @@ -571,20 +573,20 @@ export class PostDefendWeatherChangeAbAttr extends PostDefendAbAttr { } export class PreAttackAbAttr extends AbAttr { - applyPreAttack(pokemon: Pokemon, defender: Pokemon, move: PokemonMove, args: any[]): boolean | Promise { + applyPreAttack(pokemon: Pokemon, passive: boolean, defender: Pokemon, move: PokemonMove, args: any[]): boolean | Promise { return false; } } export class VariableMovePowerAbAttr extends PreAttackAbAttr { - applyPreAttack(pokemon: Pokemon, defender: Pokemon, move: PokemonMove, args: any[]): boolean { + applyPreAttack(pokemon: Pokemon, passive: boolean, defender: Pokemon, move: PokemonMove, args: any[]): boolean { //const power = args[0] as Utils.NumberHolder; return false; } } export class VariableMoveTypeAbAttr extends AbAttr { - apply(pokemon: Pokemon, cancelled: Utils.BooleanHolder, args: any[]): boolean { + apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { //const power = args[0] as Utils.IntegerHolder; return false; } @@ -602,7 +604,7 @@ export class MoveTypeChangePowerMultiplierAbAttr extends VariableMoveTypeAbAttr this.powerMultiplier = powerMultiplier; } - apply(pokemon: Pokemon, cancelled: Utils.BooleanHolder, args: any[]): boolean { + apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { const type = (args[0] as Utils.IntegerHolder); if (type.value == this.matchType) { type.value = this.newType; @@ -624,7 +626,7 @@ export class MovePowerBoostAbAttr extends VariableMovePowerAbAttr { this.powerMultiplier = powerMultiplier; } - applyPreAttack(pokemon: Pokemon, defender: Pokemon, move: PokemonMove, args: any[]): boolean { + applyPreAttack(pokemon: Pokemon, passive: boolean, defender: Pokemon, move: PokemonMove, args: any[]): boolean { if (this.condition(pokemon, defender, move.getMove())) { (args[0] as Utils.NumberHolder).value *= this.powerMultiplier; @@ -652,7 +654,7 @@ export class LowHpMoveTypePowerBoostAbAttr extends MoveTypePowerBoostAbAttr { } export class FieldVariableMovePowerAbAttr extends AbAttr { - applyPreAttack(pokemon: Pokemon, defender: Pokemon, move: PokemonMove, args: any[]): boolean { + applyPreAttack(pokemon: Pokemon, passive: boolean, defender: Pokemon, move: PokemonMove, args: any[]): boolean { //const power = args[0] as Utils.NumberHolder; return false; } @@ -668,7 +670,7 @@ export class FieldMovePowerBoostAbAttr extends FieldVariableMovePowerAbAttr { this.powerMultiplier = powerMultiplier; } - applyPreAttack(pokemon: Pokemon, defender: Pokemon, move: PokemonMove, args: any[]): boolean { + applyPreAttack(pokemon: Pokemon, passive: boolean, defender: Pokemon, move: PokemonMove, args: any[]): boolean { if (this.condition(pokemon, defender, move.getMove())) { (args[0] as Utils.NumberHolder).value *= this.powerMultiplier; @@ -696,7 +698,7 @@ export class BattleStatMultiplierAbAttr extends AbAttr { this.multiplier = multiplier; } - applyBattleStat(pokemon: Pokemon, battleStat: BattleStat, statValue: Utils.NumberHolder, args: any[]): boolean | Promise { + applyBattleStat(pokemon: Pokemon, passive: boolean, battleStat: BattleStat, statValue: Utils.NumberHolder, args: any[]): boolean | Promise { if (battleStat === this.battleStat) { statValue.value *= this.multiplier; return true; @@ -707,7 +709,7 @@ export class BattleStatMultiplierAbAttr extends AbAttr { } export class PostAttackAbAttr extends AbAttr { - applyPostAttack(pokemon: Pokemon, defender: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean | Promise { + applyPostAttack(pokemon: Pokemon, passive: boolean, defender: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean | Promise { return false; } } @@ -721,7 +723,7 @@ export class PostAttackStealHeldItemAbAttr extends PostAttackAbAttr { this.condition = condition; } - applyPostAttack(pokemon: Pokemon, defender: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): Promise { + applyPostAttack(pokemon: Pokemon, passive: boolean, defender: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): Promise { return new Promise(resolve => { if (hitResult < HitResult.NO_EFFECT && (!this.condition || this.condition(pokemon, defender, move.getMove()))) { const heldItems = this.getTargetHeldItems(defender).filter(i => i.getTransferrable(false)); @@ -756,7 +758,7 @@ export class PostAttackContactApplyStatusEffectAbAttr extends PostAttackAbAttr { this.effects = effects; } - applyPostAttack(pokemon: Pokemon, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean { + applyPostAttack(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean { if (move.getMove().checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon) && pokemon.randSeedInt(100) < this.chance && !pokemon.status) { const effect = this.effects.length === 1 ? this.effects[0] : this.effects[pokemon.randSeedInt(this.effects.length)]; return attacker.trySetStatus(effect, true); @@ -775,7 +777,7 @@ export class PostDefendStealHeldItemAbAttr extends PostDefendAbAttr { this.condition = condition; } - applyPostDefend(pokemon: Pokemon, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): Promise { + applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): Promise { return new Promise(resolve => { if (hitResult < HitResult.NO_EFFECT && (!this.condition || this.condition(pokemon, attacker, move.getMove()))) { const heldItems = this.getTargetHeldItems(attacker).filter(i => i.getTransferrable(false)); @@ -800,7 +802,7 @@ export class PostDefendStealHeldItemAbAttr extends PostDefendAbAttr { } export class PostVictoryAbAttr extends AbAttr { - applyPostVictory(pokemon: Pokemon, args: any[]): boolean | Promise { + applyPostVictory(pokemon: Pokemon, passive: boolean, args: any[]): boolean | Promise { return false; } } @@ -816,7 +818,7 @@ class PostVictoryStatChangeAbAttr extends PostVictoryAbAttr { this.levels = levels; } - applyPostVictory(pokemon: Pokemon, args: any[]): boolean | Promise { + applyPostVictory(pokemon: Pokemon, passive: boolean, args: any[]): boolean | Promise { const stat = typeof this.stat === 'function' ? this.stat(pokemon) : this.stat; @@ -827,7 +829,7 @@ class PostVictoryStatChangeAbAttr extends PostVictoryAbAttr { } export class PostKnockOutAbAttr extends AbAttr { - applyPostKnockOut(pokemon: Pokemon, args: any[]): boolean | Promise { + applyPostKnockOut(pokemon: Pokemon, passive: boolean, args: any[]): boolean | Promise { return false; } } @@ -843,7 +845,7 @@ export class PostKnockOutStatChangeAbAttr extends PostKnockOutAbAttr { this.levels = levels; } - applyPostKnockOut(pokemon: Pokemon, args: any[]): boolean | Promise { + applyPostKnockOut(pokemon: Pokemon, passive: boolean, args: any[]): boolean | Promise { const stat = typeof this.stat === 'function' ? this.stat(pokemon) : this.stat; @@ -858,7 +860,7 @@ export class IgnoreOpponentStatChangesAbAttr extends AbAttr { super(false); } - apply(pokemon: Pokemon, cancelled: Utils.BooleanHolder, args: any[]) { + apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]) { (args[0] as Utils.IntegerHolder).value = 0; return true; @@ -866,7 +868,7 @@ export class IgnoreOpponentStatChangesAbAttr extends AbAttr { } export class PostSummonAbAttr extends AbAttr { - applyPostSummon(pokemon: Pokemon, args: any[]): boolean | Promise { + applyPostSummon(pokemon: Pokemon, passive: boolean, args: any[]): boolean | Promise { return false; } } @@ -880,7 +882,7 @@ export class PostSummonMessageAbAttr extends PostSummonAbAttr { this.messageFunc = messageFunc; } - applyPostSummon(pokemon: Pokemon, args: any[]): boolean { + applyPostSummon(pokemon: Pokemon, passive: boolean, args: any[]): boolean { pokemon.scene.queueMessage(this.messageFunc(pokemon)); return true; @@ -898,7 +900,7 @@ export class PostSummonAddBattlerTagAbAttr extends PostSummonAbAttr { this.turnCount = turnCount; } - applyPostSummon(pokemon: Pokemon, args: any[]): boolean { + applyPostSummon(pokemon: Pokemon, passive: boolean, args: any[]): boolean { return pokemon.addTag(this.tagType, this.turnCount); } } @@ -918,7 +920,7 @@ export class PostSummonStatChangeAbAttr extends PostSummonAbAttr { this.selfTarget = !!selfTarget; } - applyPostSummon(pokemon: Pokemon, args: any[]): boolean { + applyPostSummon(pokemon: Pokemon, passive: boolean, args: any[]): boolean { const statChangePhases: StatChangePhase[] = []; if (this.selfTarget) @@ -948,7 +950,7 @@ export class PostSummonWeatherChangeAbAttr extends PostSummonAbAttr { this.weatherType = weatherType; } - applyPostSummon(pokemon: Pokemon, args: any[]): boolean { + applyPostSummon(pokemon: Pokemon, passive: boolean, args: any[]): boolean { if (!pokemon.scene.arena.weather?.isImmutable()) return pokemon.scene.arena.trySetWeather(this.weatherType, true); @@ -965,7 +967,7 @@ export class PostSummonTerrainChangeAbAttr extends PostSummonAbAttr { this.terrainType = terrainType; } - applyPostSummon(pokemon: Pokemon, args: any[]): boolean { + applyPostSummon(pokemon: Pokemon, passive: boolean, args: any[]): boolean { return pokemon.scene.arena.trySetTerrain(this.terrainType, true); } } @@ -979,7 +981,7 @@ export class PostSummonFormChangeAbAttr extends PostSummonAbAttr { this.formFunc = formFunc; } - applyPostSummon(pokemon: Pokemon, args: any[]): boolean { + applyPostSummon(pokemon: Pokemon, passive: boolean, args: any[]): boolean { const formIndex = this.formFunc(pokemon); if (formIndex !== pokemon.formIndex) return pokemon.scene.triggerPokemonFormChange(pokemon, SpeciesFormChangeManualTrigger, false); @@ -993,7 +995,7 @@ export class PostSummonTransformAbAttr extends PostSummonAbAttr { super(true); } - applyPostSummon(pokemon: Pokemon, args: any[]): boolean { + applyPostSummon(pokemon: Pokemon, passive: boolean, args: any[]): boolean { const targets = pokemon.getOpponents(); let target: Pokemon; if (targets.length > 1) @@ -1025,13 +1027,13 @@ export class PreSwitchOutAbAttr extends AbAttr { super(true); } - applyPreSwitchOut(pokemon: Pokemon, args: any[]): boolean | Promise { + applyPreSwitchOut(pokemon: Pokemon, passive: boolean, args: any[]): boolean | Promise { return false; } } export class PreSwitchOutResetStatusAbAttr extends PreSwitchOutAbAttr { - applyPreSwitchOut(pokemon: Pokemon, args: any[]): boolean | Promise { + applyPreSwitchOut(pokemon: Pokemon, passive: boolean, args: any[]): boolean | Promise { if (pokemon.status) { pokemon.resetStatus(); pokemon.updateInfo(); @@ -1043,7 +1045,7 @@ export class PreSwitchOutResetStatusAbAttr extends PreSwitchOutAbAttr { } export class PreSwitchOutHealAbAttr extends PreSwitchOutAbAttr { - applyPreSwitchOut(pokemon: Pokemon, args: any[]): boolean | Promise { + applyPreSwitchOut(pokemon: Pokemon, passive: boolean, args: any[]): boolean | Promise { if (pokemon.getHpRatio() < 1 ) { const healAmount = Math.floor(pokemon.getMaxHp() * 0.33); pokemon.heal(healAmount); @@ -1056,7 +1058,7 @@ export class PreSwitchOutHealAbAttr extends PreSwitchOutAbAttr { } export class PreStatChangeAbAttr extends AbAttr { - applyPreStatChange(pokemon: Pokemon, stat: BattleStat, cancelled: Utils.BooleanHolder, args: any[]): boolean | Promise { + applyPreStatChange(pokemon: Pokemon, passive: boolean, stat: BattleStat, cancelled: Utils.BooleanHolder, args: any[]): boolean | Promise { return false; } } @@ -1070,7 +1072,7 @@ export class ProtectStatAbAttr extends PreStatChangeAbAttr { this.protectedStat = protectedStat; } - applyPreStatChange(pokemon: Pokemon, stat: BattleStat, cancelled: Utils.BooleanHolder, args: any[]): boolean { + applyPreStatChange(pokemon: Pokemon, passive: boolean, stat: BattleStat, cancelled: Utils.BooleanHolder, args: any[]): boolean { if (this.protectedStat === undefined || stat === this.protectedStat) { cancelled.value = true; return true; @@ -1079,13 +1081,13 @@ export class ProtectStatAbAttr extends PreStatChangeAbAttr { return false; } - getTriggerMessage(pokemon: Pokemon, ...args: any[]): string { - return getPokemonMessage(pokemon, `'s ${pokemon.getAbility().name}\nprevents lowering its ${this.protectedStat !== undefined ? getBattleStatName(this.protectedStat) : 'stats'}!`); + getTriggerMessage(pokemon: Pokemon, abilityName: string, ...args: any[]): string { + return getPokemonMessage(pokemon, `'s ${abilityName}\nprevents lowering its ${this.protectedStat !== undefined ? getBattleStatName(this.protectedStat) : 'stats'}!`); } } export class PreSetStatusAbAttr extends AbAttr { - applyPreSetStatus(pokemon: Pokemon, effect: StatusEffect, cancelled: Utils.BooleanHolder, args: any[]): boolean | Promise { + applyPreSetStatus(pokemon: Pokemon, passive: boolean, effect: StatusEffect, cancelled: Utils.BooleanHolder, args: any[]): boolean | Promise { return false; } } @@ -1099,7 +1101,7 @@ export class StatusEffectImmunityAbAttr extends PreSetStatusAbAttr { this.immuneEffects = immuneEffects; } - applyPreSetStatus(pokemon: Pokemon, effect: StatusEffect, cancelled: Utils.BooleanHolder, args: any[]): boolean { + applyPreSetStatus(pokemon: Pokemon, passive: boolean, effect: StatusEffect, cancelled: Utils.BooleanHolder, args: any[]): boolean { if (!this.immuneEffects.length || this.immuneEffects.indexOf(effect) > -1) { cancelled.value = true; return true; @@ -1108,13 +1110,13 @@ export class StatusEffectImmunityAbAttr extends PreSetStatusAbAttr { return false; } - getTriggerMessage(pokemon: Pokemon, ...args: any[]): string { - return getPokemonMessage(pokemon, `'s ${pokemon.getAbility().name}\nprevents ${this.immuneEffects.length ? getStatusEffectDescriptor(args[0] as StatusEffect) : 'status problems'}!`); + getTriggerMessage(pokemon: Pokemon, abilityName: string, ...args: any[]): string { + return getPokemonMessage(pokemon, `'s ${abilityName}\nprevents ${this.immuneEffects.length ? getStatusEffectDescriptor(args[0] as StatusEffect) : 'status problems'}!`); } } export class PreApplyBattlerTagAbAttr extends AbAttr { - applyPreApplyBattlerTag(pokemon: Pokemon, tag: BattlerTag, cancelled: Utils.BooleanHolder, args: any[]): boolean | Promise { + applyPreApplyBattlerTag(pokemon: Pokemon, passive: boolean, tag: BattlerTag, cancelled: Utils.BooleanHolder, args: any[]): boolean | Promise { return false; } } @@ -1128,7 +1130,7 @@ export class BattlerTagImmunityAbAttr extends PreApplyBattlerTagAbAttr { this.immuneTagType = immuneTagType; } - applyPreApplyBattlerTag(pokemon: Pokemon, tag: BattlerTag, cancelled: Utils.BooleanHolder, args: any[]): boolean { + applyPreApplyBattlerTag(pokemon: Pokemon, passive: boolean, tag: BattlerTag, cancelled: Utils.BooleanHolder, args: any[]): boolean { if (tag.tagType === this.immuneTagType) { cancelled.value = true; return true; @@ -1137,27 +1139,27 @@ export class BattlerTagImmunityAbAttr extends PreApplyBattlerTagAbAttr { return false; } - getTriggerMessage(pokemon: Pokemon, ...args: any[]): string { - return getPokemonMessage(pokemon, `'s ${pokemon.getAbility().name}\nprevents ${(args[0] as BattlerTag).getDescriptor()}!`); + getTriggerMessage(pokemon: Pokemon, abilityName: string, ...args: any[]): string { + return getPokemonMessage(pokemon, `'s ${abilityName}\nprevents ${(args[0] as BattlerTag).getDescriptor()}!`); } } export class BlockCritAbAttr extends AbAttr { - apply(pokemon: Pokemon, cancelled: Utils.BooleanHolder, args: any[]): boolean { + apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { (args[0] as Utils.BooleanHolder).value = true; return true; } } export class BlockNonDirectDamageAbAttr extends AbAttr { - apply(pokemon: Pokemon, cancelled: Utils.BooleanHolder, args: any[]): boolean { + apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { cancelled.value = true; return true; } } export class BlockOneHitKOAbAttr extends AbAttr { - apply(pokemon: Pokemon, cancelled: Utils.BooleanHolder, args: any[]): boolean { + apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { cancelled.value = true; return true; } @@ -1174,7 +1176,7 @@ export class IncrementMovePriorityAbAttr extends AbAttr { this.increaseAmount = increaseAmount; } - apply(pokemon: Pokemon, cancelled: Utils.BooleanHolder, args: any[]): boolean { + apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { if (!this.moveIncrementFunc(pokemon, args[0] as Move)) return false; @@ -1186,7 +1188,7 @@ export class IncrementMovePriorityAbAttr extends AbAttr { export class IgnoreContactAbAttr extends AbAttr { } export class PreWeatherEffectAbAttr extends AbAttr { - applyPreWeatherEffect(pokemon: Pokemon, weather: Weather, cancelled: Utils.BooleanHolder, args: any[]): boolean | Promise { + applyPreWeatherEffect(pokemon: Pokemon, passive: boolean, weather: Weather, cancelled: Utils.BooleanHolder, args: any[]): boolean | Promise { return false; } } @@ -1202,7 +1204,7 @@ export class BlockWeatherDamageAttr extends PreWeatherDamageAbAttr { this.weatherTypes = weatherTypes; } - applyPreWeatherEffect(pokemon: Pokemon, weather: Weather, cancelled: Utils.BooleanHolder, args: any[]): boolean { + applyPreWeatherEffect(pokemon: Pokemon, passive: boolean, weather: Weather, cancelled: Utils.BooleanHolder, args: any[]): boolean { if (!this.weatherTypes.length || this.weatherTypes.indexOf(weather?.weatherType) > -1) cancelled.value = true; @@ -1219,7 +1221,7 @@ export class SuppressWeatherEffectAbAttr extends PreWeatherEffectAbAttr { this.affectsImmutable = affectsImmutable; } - applyPreWeatherEffect(pokemon: Pokemon, weather: Weather, cancelled: Utils.BooleanHolder, args: any[]): boolean { + applyPreWeatherEffect(pokemon: Pokemon, passive: boolean, weather: Weather, cancelled: Utils.BooleanHolder, args: any[]): boolean { if (this.affectsImmutable || weather.isImmutable()) { cancelled.value = true; return true; @@ -1239,7 +1241,7 @@ function getWeatherCondition(...weatherTypes: WeatherType[]): AbAttrCondition { } export class PostWeatherChangeAbAttr extends AbAttr { - applyPostWeatherChange(pokemon: Pokemon, weather: WeatherType, args: any[]): boolean { + applyPostWeatherChange(pokemon: Pokemon, passive: boolean, weather: WeatherType, args: any[]): boolean { return false; } } @@ -1257,7 +1259,7 @@ export class PostWeatherChangeAddBattlerTagAttr extends PostWeatherChangeAbAttr this.weatherTypes = weatherTypes; } - applyPostWeatherChange(pokemon: Pokemon, weather: WeatherType, args: any[]): boolean { + applyPostWeatherChange(pokemon: Pokemon, passive: boolean, weather: WeatherType, args: any[]): boolean { console.log(this.weatherTypes.find(w => weather === w), WeatherType[weather]); if (!this.weatherTypes.find(w => weather === w)) return false; @@ -1275,7 +1277,7 @@ export class PostWeatherLapseAbAttr extends AbAttr { this.weatherTypes = weatherTypes; } - applyPostWeatherLapse(pokemon: Pokemon, weather: Weather, args: any[]): boolean | Promise { + applyPostWeatherLapse(pokemon: Pokemon, passive: boolean, weather: Weather, args: any[]): boolean | Promise { return false; } @@ -1293,11 +1295,12 @@ export class PostWeatherLapseHealAbAttr extends PostWeatherLapseAbAttr { this.healFactor = healFactor; } - applyPostWeatherLapse(pokemon: Pokemon, weather: Weather, args: any[]): boolean { + applyPostWeatherLapse(pokemon: Pokemon, passive: boolean, weather: Weather, args: any[]): boolean { if (pokemon.getHpRatio() < 1) { const scene = pokemon.scene; + const abilityName = (!passive ? pokemon.getAbility() : pokemon.getPassiveAbility()).name; scene.unshiftPhase(new PokemonHealPhase(scene, pokemon.getBattlerIndex(), - Math.max(Math.floor(pokemon.getMaxHp() / (16 / this.healFactor)), 1), getPokemonMessage(pokemon, `'s ${pokemon.getAbility().name}\nrestored its HP a little!`), true)); + Math.max(Math.floor(pokemon.getMaxHp() / (16 / this.healFactor)), 1), getPokemonMessage(pokemon, `'s ${abilityName}\nrestored its HP a little!`), true)); return true; } @@ -1314,10 +1317,11 @@ export class PostWeatherLapseDamageAbAttr extends PostWeatherLapseAbAttr { this.damageFactor = damageFactor; } - applyPostWeatherLapse(pokemon: Pokemon, weather: Weather, args: any[]): boolean { + applyPostWeatherLapse(pokemon: Pokemon, passive: boolean, weather: Weather, args: any[]): boolean { if (pokemon.getHpRatio() < 1) { const scene = pokemon.scene; - scene.queueMessage(getPokemonMessage(pokemon, ` is hurt\nby its ${pokemon.getAbility().name}!`)); + const abilityName = (!passive ? pokemon.getAbility() : pokemon.getPassiveAbility()).name; + scene.queueMessage(getPokemonMessage(pokemon, ` is hurt\nby its ${abilityName}!`)); pokemon.damageAndUpdate(Math.ceil(pokemon.getMaxHp() / (16 / this.damageFactor)), HitResult.OTHER); return true; } @@ -1327,7 +1331,7 @@ export class PostWeatherLapseDamageAbAttr extends PostWeatherLapseAbAttr { } export class PostTerrainChangeAbAttr extends AbAttr { - applyPostTerrainChange(pokemon: Pokemon, terrain: TerrainType, args: any[]): boolean { + applyPostTerrainChange(pokemon: Pokemon, passive: boolean, terrain: TerrainType, args: any[]): boolean { return false; } } @@ -1345,7 +1349,7 @@ export class PostTerrainChangeAddBattlerTagAttr extends PostTerrainChangeAbAttr this.terrainTypes = terrainTypes; } - applyPostTerrainChange(pokemon: Pokemon, terrain: TerrainType, args: any[]): boolean { + applyPostTerrainChange(pokemon: Pokemon, passive: boolean, terrain: TerrainType, args: any[]): boolean { if (!this.terrainTypes.find(t => terrain === terrain)) return false; @@ -1361,13 +1365,13 @@ function getTerrainCondition(...terrainTypes: TerrainType[]): AbAttrCondition { } export class PostTurnAbAttr extends AbAttr { - applyPostTurn(pokemon: Pokemon, args: any[]): boolean | Promise { + applyPostTurn(pokemon: Pokemon, passive: boolean, args: any[]): boolean | Promise { return false; } } export class PostTurnResetStatusAbAttr extends PostTurnAbAttr { - applyPostTurn(pokemon: Pokemon, args: any[]): boolean { + applyPostTurn(pokemon: Pokemon, passive: boolean, args: any[]): boolean { if (pokemon.status) { pokemon.scene.queueMessage(getPokemonMessage(pokemon, getStatusEffectHealText(pokemon.status?.effect))); @@ -1393,18 +1397,19 @@ export class PostTurnStatChangeAbAttr extends PostTurnAbAttr { this.levels = levels; } - applyPostTurn(pokemon: Pokemon, args: any[]): boolean { + applyPostTurn(pokemon: Pokemon, passive: boolean, args: any[]): boolean { pokemon.scene.unshiftPhase(new StatChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, this.stats, this.levels)); return true; } } export class PostTurnHealAbAttr extends PostTurnAbAttr { - applyPostTurn(pokemon: Pokemon, args: any[]): boolean { + applyPostTurn(pokemon: Pokemon, passive: boolean, args: any[]): boolean { if (pokemon.getHpRatio() < 1) { const scene = pokemon.scene; + const abilityName = (!passive ? pokemon.getAbility() : pokemon.getPassiveAbility()).name; scene.unshiftPhase(new PokemonHealPhase(scene, pokemon.getBattlerIndex(), - Math.max(Math.floor(pokemon.getMaxHp() / 16), 1), getPokemonMessage(pokemon, `'s ${pokemon.getAbility().name}\nrestored its HP a little!`), true)); + Math.max(Math.floor(pokemon.getMaxHp() / 16), 1), getPokemonMessage(pokemon, `'s ${abilityName}\nrestored its HP a little!`), true)); return true; } @@ -1421,7 +1426,7 @@ export class PostTurnFormChangeAbAttr extends PostTurnAbAttr { this.formFunc = formFunc; } - applyPostTurn(pokemon: Pokemon, args: any[]): boolean { + applyPostTurn(pokemon: Pokemon, passive: boolean, args: any[]): boolean { const formIndex = this.formFunc(pokemon); if (formIndex !== pokemon.formIndex) { pokemon.scene.triggerPokemonFormChange(pokemon, SpeciesFormChangeManualTrigger, false); @@ -1443,7 +1448,7 @@ export class PostBiomeChangeWeatherChangeAbAttr extends PostBiomeChangeAbAttr { this.weatherType = weatherType; } - apply(pokemon: Pokemon, cancelled: Utils.BooleanHolder, args: any[]): boolean { + apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { if (!pokemon.scene.arena.weather?.isImmutable()) return pokemon.scene.arena.trySetWeather(this.weatherType, true); @@ -1460,7 +1465,7 @@ export class PostBiomeChangeTerrainChangeAbAttr extends PostBiomeChangeAbAttr { this.terrainType = terrainType; } - apply(pokemon: Pokemon, cancelled: Utils.BooleanHolder, args: any[]): boolean { + apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { return pokemon.scene.arena.trySetTerrain(this.terrainType, true); } } @@ -1474,7 +1479,7 @@ export class StatChangeMultiplierAbAttr extends AbAttr { this.multiplier = multiplier; } - apply(pokemon: Pokemon, cancelled: Utils.BooleanHolder, args: any[]): boolean { + apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { (args[0] as Utils.IntegerHolder).value *= this.multiplier; return true; @@ -1486,7 +1491,7 @@ export class BypassBurnDamageReductionAbAttr extends AbAttr { super(false); } - apply(pokemon: Pokemon, cancelled: Utils.BooleanHolder, args: any[]): boolean { + apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { cancelled.value = true; return true; @@ -1494,7 +1499,7 @@ export class BypassBurnDamageReductionAbAttr extends AbAttr { } export class DoubleBerryEffectAbAttr extends AbAttr { - apply(pokemon: Pokemon, cancelled: Utils.BooleanHolder, args: any[]): boolean { + apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { (args[0] as Utils.NumberHolder).value *= 2; return true; @@ -1502,7 +1507,7 @@ export class DoubleBerryEffectAbAttr extends AbAttr { } export class PreventBerryUseAbAttr extends AbAttr { - apply(pokemon: Pokemon, cancelled: Utils.BooleanHolder, args: any[]): boolean { + apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { cancelled.value = true; return true; @@ -1510,7 +1515,7 @@ export class PreventBerryUseAbAttr extends AbAttr { } export class RunSuccessAbAttr extends AbAttr { - apply(pokemon: Pokemon, cancelled: Utils.BooleanHolder, args: any[]): boolean { + apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { (args[0] as Utils.IntegerHolder).value = 256; return true; @@ -1522,24 +1527,24 @@ export class CheckTrappedAbAttr extends AbAttr { super(false); } - applyCheckTrapped(pokemon: Pokemon, trapped: Utils.BooleanHolder, args: any[]): boolean | Promise { + applyCheckTrapped(pokemon: Pokemon, passive: boolean, trapped: Utils.BooleanHolder, args: any[]): boolean | Promise { return false; } } export class ArenaTrapAbAttr extends CheckTrappedAbAttr { - applyCheckTrapped(pokemon: Pokemon, trapped: Utils.BooleanHolder, args: any[]): boolean { + applyCheckTrapped(pokemon: Pokemon, passive: boolean, trapped: Utils.BooleanHolder, args: any[]): boolean { trapped.value = true; return true; } - getTriggerMessage(pokemon: Pokemon, ...args: any[]): string { - return getPokemonMessage(pokemon, `\'s ${pokemon.getAbility().name}\nprevents switching!`); + getTriggerMessage(pokemon: Pokemon, abilityName: string, ...args: any[]): string { + return getPokemonMessage(pokemon, `\'s ${abilityName}\nprevents switching!`); } } export class MaxMultiHitAbAttr extends AbAttr { - apply(pokemon: Pokemon, cancelled: Utils.BooleanHolder, args: any[]): boolean { + apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { (args[0] as Utils.IntegerHolder).value = 0; return true; @@ -1551,13 +1556,13 @@ export class PostBattleAbAttr extends AbAttr { super(true); } - applyPostBattle(pokemon: Pokemon, args: any[]): boolean { + applyPostBattle(pokemon: Pokemon, passive: boolean, args: any[]): boolean { return false; } } export class PostBattleLootAbAttr extends PostBattleAbAttr { - applyPostBattle(pokemon: Pokemon, args: any[]): boolean { + applyPostBattle(pokemon: Pokemon, passive: boolean, args: any[]): boolean { const postBattleLoot = pokemon.scene.currentBattle.postBattleLoot; if (postBattleLoot.length) { const randItem = Utils.randSeedItem(postBattleLoot); @@ -1573,7 +1578,7 @@ export class PostBattleLootAbAttr extends PostBattleAbAttr { } export class PostFaintAbAttr extends AbAttr { - applyPostFaint(pokemon: Pokemon, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean { + applyPostFaint(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean { return false; } } @@ -1587,7 +1592,7 @@ export class PostFaintContactDamageAbAttr extends PostFaintAbAttr { this.damageRatio = damageRatio; } - applyPostFaint(pokemon: Pokemon, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean { + applyPostFaint(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean { if (move.getMove().checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon)) { attacker.damageAndUpdate(Math.ceil(attacker.getMaxHp() * (1 / this.damageRatio)), HitResult.OTHER); return true; @@ -1596,13 +1601,13 @@ export class PostFaintContactDamageAbAttr extends PostFaintAbAttr { return false; } - getTriggerMessage(pokemon: Pokemon, ...args: any[]): string { - return getPokemonMessage(pokemon, `'s ${pokemon.getAbility().name} hurt\nits attacker!`); + getTriggerMessage(pokemon: Pokemon, abilityName: string, ...args: any[]): string { + return getPokemonMessage(pokemon, `'s ${abilityName} hurt\nits attacker!`); } } export class RedirectMoveAbAttr extends AbAttr { - apply(pokemon: Pokemon, cancelled: Utils.BooleanHolder, args: any[]): boolean { + apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { if (this.canRedirect(args[0] as Moves)) { const target = args[1] as Utils.IntegerHolder; const newTarget = pokemon.getBattlerIndex(); @@ -1643,7 +1648,7 @@ export class ReduceStatusEffectDurationAbAttr extends AbAttr { this.statusEffect = statusEffect; } - apply(pokemon: Pokemon, cancelled: Utils.BooleanHolder, args: any[]): boolean { + apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { if (args[0] === this.statusEffect) { (args[1] as Utils.IntegerHolder).value = Math.floor((args[1] as Utils.IntegerHolder).value / 2); return true; @@ -1672,18 +1677,20 @@ export class FlinchStatChangeAbAttr extends FlinchEffectAbAttr { this.levels = levels; } - apply(pokemon: Pokemon, cancelled: Utils.BooleanHolder, args: any[]): boolean { + apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { pokemon.scene.unshiftPhase(new StatChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, this.stats, this.levels)); return true; } } +export class IncreasePpAbAttr extends AbAttr { } + export class ReduceBerryUseThresholdAbAttr extends AbAttr { constructor() { - super(true); + super(); } - apply(pokemon: Pokemon, cancelled: Utils.BooleanHolder, args: any[]): boolean { + apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { const hpRatio = pokemon.getHpRatio(); if (args[0].value < hpRatio) { @@ -1699,12 +1706,12 @@ export class WeightMultiplierAbAttr extends AbAttr { private multiplier: integer; constructor(multiplier: integer) { - super(true); + super(); this.multiplier = multiplier; } - apply(pokemon: Pokemon, cancelled: Utils.BooleanHolder, args: any[]): boolean { + apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { (args[0] as Utils.NumberHolder).value *= this.multiplier; return true; @@ -1716,7 +1723,7 @@ export class SyncEncounterNatureAbAttr extends AbAttr { super(false); } - apply(pokemon: Pokemon, cancelled: Utils.BooleanHolder, args: any[]): boolean { + apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { (args[0] as Pokemon).setNature(pokemon.getNature()); return true; @@ -1728,7 +1735,7 @@ export class MoveAbilityBypassAbAttr extends AbAttr { super(false); } - apply(pokemon: Pokemon, cancelled: Utils.BooleanHolder, args: any[]): boolean { + apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { cancelled.value = true; return true; } @@ -1741,17 +1748,24 @@ export class ProtectAbilityAbAttr extends AbAttr { } function applyAbAttrsInternal(attrType: { new(...args: any[]): TAttr }, - pokemon: Pokemon, applyFunc: AbAttrApplyFunc, args: any[], isAsync: boolean = false, showAbilityInstant: boolean = false, quiet: boolean = false): Promise { + pokemon: Pokemon, applyFunc: AbAttrApplyFunc, args: any[], isAsync: boolean = false, showAbilityInstant: boolean = false, quiet: boolean = false, passive: boolean = false): Promise { return new Promise(resolve => { - if (!pokemon.canApplyAbility()) - return resolve(); + if (!pokemon.canApplyAbility(passive)) { + if (!passive) + return applyAbAttrsInternal(attrType, pokemon, applyFunc, args, isAsync, showAbilityInstant, quiet, true).then(() => resolve()); + else + return resolve(); + } - const ability = pokemon.getAbility(); + const ability = (!passive ? pokemon.getAbility() : pokemon.getPassiveAbility()); const attrs = ability.getAttrs(attrType) as TAttr[]; const clearSpliceQueueAndResolve = () => { pokemon.scene.clearPhaseQueueSplice(); - resolve(); + if (!passive) + return applyAbAttrsInternal(attrType, pokemon, applyFunc, args, isAsync, showAbilityInstant, quiet, true).then(() => resolve()); + else + return resolve(); }; const applyNextAbAttr = () => { if (attrs.length) @@ -1766,12 +1780,12 @@ function applyAbAttrsInternal(attrType: { new(...args: any const onApplySuccess = () => { if (attr.showAbility && !quiet) { if (showAbilityInstant) - pokemon.scene.abilityBar.showAbility(pokemon); + pokemon.scene.abilityBar.showAbility(pokemon, passive); else - queueShowAbility(pokemon); + queueShowAbility(pokemon, passive); } if (!quiet) { - const message = attr.getTriggerMessage(pokemon, args); + const message = attr.getTriggerMessage(pokemon, (!passive ? pokemon.getAbility() : pokemon.getPassiveAbility()).name, args); if (message) { if (isAsync) pokemon.scene.ui.showText(message, null, () => pokemon.scene.ui.showText(null, 0), null, true); @@ -1780,7 +1794,7 @@ function applyAbAttrsInternal(attrType: { new(...args: any } } }; - const result = applyFunc(attr); + const result = applyFunc(attr, passive); if (result instanceof Promise) { result.then(success => { if (success) @@ -1798,114 +1812,114 @@ function applyAbAttrsInternal(attrType: { new(...args: any } export function applyAbAttrs(attrType: { new(...args: any[]): AbAttr }, pokemon: Pokemon, cancelled: Utils.BooleanHolder, ...args: any[]): Promise { - return applyAbAttrsInternal(attrType, pokemon, attr => attr.apply(pokemon, cancelled, args), args); + return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.apply(pokemon, passive, cancelled, args), args); } export function applyPostBattleInitAbAttrs(attrType: { new(...args: any[]): PostBattleInitAbAttr }, pokemon: Pokemon, ...args: any[]): Promise { - return applyAbAttrsInternal(attrType, pokemon, attr => attr.applyPostBattleInit(pokemon, args), args); + return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.applyPostBattleInit(pokemon, passive, args), args); } export function applyPreDefendAbAttrs(attrType: { new(...args: any[]): PreDefendAbAttr }, pokemon: Pokemon, attacker: Pokemon, move: PokemonMove, cancelled: Utils.BooleanHolder, ...args: any[]): Promise { const simulated = args.length > 1 && args[1]; - return applyAbAttrsInternal(attrType, pokemon, attr => attr.applyPreDefend(pokemon, attacker, move, cancelled, args), args, false, false, simulated); + return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.applyPreDefend(pokemon, passive, attacker, move, cancelled, args), args, false, false, simulated); } export function applyPostDefendAbAttrs(attrType: { new(...args: any[]): PostDefendAbAttr }, pokemon: Pokemon, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, ...args: any[]): Promise { - return applyAbAttrsInternal(attrType, pokemon, attr => attr.applyPostDefend(pokemon, attacker, move, hitResult, args), args); + return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.applyPostDefend(pokemon, passive, attacker, move, hitResult, args), args); } export function applyBattleStatMultiplierAbAttrs(attrType: { new(...args: any[]): BattleStatMultiplierAbAttr }, pokemon: Pokemon, battleStat: BattleStat, statValue: Utils.NumberHolder, ...args: any[]): Promise { - return applyAbAttrsInternal(attrType, pokemon, attr => attr.applyBattleStat(pokemon, battleStat, statValue, args), args); + return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.applyBattleStat(pokemon, passive, battleStat, statValue, args), args); } export function applyPreAttackAbAttrs(attrType: { new(...args: any[]): PreAttackAbAttr }, pokemon: Pokemon, defender: Pokemon, move: PokemonMove, ...args: any[]): Promise { - return applyAbAttrsInternal(attrType, pokemon, attr => attr.applyPreAttack(pokemon, defender, move, args), args); + return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.applyPreAttack(pokemon, passive, defender, move, args), args); } export function applyPostAttackAbAttrs(attrType: { new(...args: any[]): PostAttackAbAttr }, pokemon: Pokemon, defender: Pokemon, move: PokemonMove, hitResult: HitResult, ...args: any[]): Promise { - return applyAbAttrsInternal(attrType, pokemon, attr => attr.applyPostAttack(pokemon, defender, move, hitResult, args), args); + return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.applyPostAttack(pokemon, passive, defender, move, hitResult, args), args); } export function applyPostKnockOutAbAttrs(attrType: { new(...args: any[]): PostKnockOutAbAttr }, pokemon: Pokemon, ...args: any[]): Promise { - return applyAbAttrsInternal(attrType, pokemon, attr => attr.applyPostKnockOut(pokemon, args), args); + return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.applyPostKnockOut(pokemon, passive, args), args); } export function applyPostVictoryAbAttrs(attrType: { new(...args: any[]): PostVictoryAbAttr }, pokemon: Pokemon, ...args: any[]): Promise { - return applyAbAttrsInternal(attrType, pokemon, attr => attr.applyPostVictory(pokemon, args), args); + return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.applyPostVictory(pokemon, passive, args), args); } export function applyPostSummonAbAttrs(attrType: { new(...args: any[]): PostSummonAbAttr }, pokemon: Pokemon, ...args: any[]): Promise { - return applyAbAttrsInternal(attrType, pokemon, attr => attr.applyPostSummon(pokemon, args), args); + return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.applyPostSummon(pokemon, passive, args), args); } export function applyPreSwitchOutAbAttrs(attrType: { new(...args: any[]): PreSwitchOutAbAttr }, pokemon: Pokemon, ...args: any[]): Promise { - return applyAbAttrsInternal(attrType, pokemon, attr => attr.applyPreSwitchOut(pokemon, args), args, false, true); + return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.applyPreSwitchOut(pokemon, passive, args), args, false, true); } export function applyPreStatChangeAbAttrs(attrType: { new(...args: any[]): PreStatChangeAbAttr }, pokemon: Pokemon, stat: BattleStat, cancelled: Utils.BooleanHolder, ...args: any[]): Promise { - return applyAbAttrsInternal(attrType, pokemon, attr => attr.applyPreStatChange(pokemon, stat, cancelled, args), args); + return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.applyPreStatChange(pokemon, passive, stat, cancelled, args), args); } export function applyPreSetStatusAbAttrs(attrType: { new(...args: any[]): PreSetStatusAbAttr }, pokemon: Pokemon, effect: StatusEffect, cancelled: Utils.BooleanHolder, ...args: any[]): Promise { const simulated = args.length > 1 && args[1]; - return applyAbAttrsInternal(attrType, pokemon, attr => attr.applyPreSetStatus(pokemon, effect, cancelled, args), args, false, false, !simulated); + return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.applyPreSetStatus(pokemon, passive, effect, cancelled, args), args, false, false, !simulated); } export function applyPreApplyBattlerTagAbAttrs(attrType: { new(...args: any[]): PreApplyBattlerTagAbAttr }, pokemon: Pokemon, tag: BattlerTag, cancelled: Utils.BooleanHolder, ...args: any[]): Promise { - return applyAbAttrsInternal(attrType, pokemon, attr => attr.applyPreApplyBattlerTag(pokemon, tag, cancelled, args), args); + return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.applyPreApplyBattlerTag(pokemon, passive, tag, cancelled, args), args); } export function applyPreWeatherEffectAbAttrs(attrType: { new(...args: any[]): PreWeatherEffectAbAttr }, pokemon: Pokemon, weather: Weather, cancelled: Utils.BooleanHolder, ...args: any[]): Promise { - return applyAbAttrsInternal(attrType, pokemon, attr => attr.applyPreWeatherEffect(pokemon, weather, cancelled, args), args, false, true); + return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.applyPreWeatherEffect(pokemon, passive, weather, cancelled, args), args, false, true); } export function applyPostTurnAbAttrs(attrType: { new(...args: any[]): PostTurnAbAttr }, pokemon: Pokemon, ...args: any[]): Promise { - return applyAbAttrsInternal(attrType, pokemon, attr => attr.applyPostTurn(pokemon, args), args); + return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.applyPostTurn(pokemon, passive, args), args); } export function applyPostWeatherChangeAbAttrs(attrType: { new(...args: any[]): PostWeatherChangeAbAttr }, pokemon: Pokemon, weather: WeatherType, ...args: any[]): Promise { - return applyAbAttrsInternal(attrType, pokemon, attr => attr.applyPostWeatherChange(pokemon, weather, args), args); + return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.applyPostWeatherChange(pokemon, passive, weather, args), args); } export function applyPostWeatherLapseAbAttrs(attrType: { new(...args: any[]): PostWeatherLapseAbAttr }, pokemon: Pokemon, weather: Weather, ...args: any[]): Promise { - return applyAbAttrsInternal(attrType, pokemon, attr => attr.applyPostWeatherLapse(pokemon, weather, args), args); + return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.applyPostWeatherLapse(pokemon, passive, weather, args), args); } export function applyPostTerrainChangeAbAttrs(attrType: { new(...args: any[]): PostTerrainChangeAbAttr }, pokemon: Pokemon, terrain: TerrainType, ...args: any[]): Promise { - return applyAbAttrsInternal(attrType, pokemon, attr => attr.applyPostTerrainChange(pokemon, terrain, args), args); + return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.applyPostTerrainChange(pokemon, passive, terrain, args), args); } export function applyCheckTrappedAbAttrs(attrType: { new(...args: any[]): CheckTrappedAbAttr }, pokemon: Pokemon, trapped: Utils.BooleanHolder, ...args: any[]): Promise { - return applyAbAttrsInternal(attrType, pokemon, attr => attr.applyCheckTrapped(pokemon, trapped, args), args, true); + return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.applyCheckTrapped(pokemon, passive, trapped, args), args, true); } export function applyPostBattleAbAttrs(attrType: { new(...args: any[]): PostBattleAbAttr }, pokemon: Pokemon, ...args: any[]): Promise { - return applyAbAttrsInternal(attrType, pokemon, attr => attr.applyPostBattle(pokemon, args), args); + return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.applyPostBattle(pokemon, passive, args), args); } export function applyPostFaintAbAttrs(attrType: { new(...args: any[]): PostFaintAbAttr }, pokemon: Pokemon, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, ...args: any[]): Promise { - return applyAbAttrsInternal(attrType, pokemon, attr => attr.applyPostFaint(pokemon, attacker, move, hitResult, args), args); + return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.applyPostFaint(pokemon, passive, attacker, move, hitResult, args), args); } function canApplyAttr(pokemon: Pokemon, attr: AbAttr): boolean { @@ -1913,325 +1927,11 @@ function canApplyAttr(pokemon: Pokemon, attr: AbAttr): boolean { return !condition || condition(pokemon); } -function queueShowAbility(pokemon: Pokemon): void { - pokemon.scene.unshiftPhase(new ShowAbilityPhase(pokemon.scene, pokemon.id)); +function queueShowAbility(pokemon: Pokemon, passive: boolean): void { + pokemon.scene.unshiftPhase(new ShowAbilityPhase(pokemon.scene, pokemon.id, passive)); pokemon.scene.clearPhaseQueueSplice(); } -export enum Abilities { - NONE, - STENCH, - DRIZZLE, - SPEED_BOOST, - BATTLE_ARMOR, - STURDY, - DAMP, - LIMBER, - SAND_VEIL, - STATIC, - VOLT_ABSORB, - WATER_ABSORB, - OBLIVIOUS, - CLOUD_NINE, - COMPOUND_EYES, - INSOMNIA, - COLOR_CHANGE, - IMMUNITY, - FLASH_FIRE, - SHIELD_DUST, - OWN_TEMPO, - SUCTION_CUPS, - INTIMIDATE, - SHADOW_TAG, - ROUGH_SKIN, - WONDER_GUARD, - LEVITATE, - EFFECT_SPORE, - SYNCHRONIZE, - CLEAR_BODY, - NATURAL_CURE, - LIGHTNING_ROD, - SERENE_GRACE, - SWIFT_SWIM, - CHLOROPHYLL, - ILLUMINATE, - TRACE, - HUGE_POWER, - POISON_POINT, - INNER_FOCUS, - MAGMA_ARMOR, - WATER_VEIL, - MAGNET_PULL, - SOUNDPROOF, - RAIN_DISH, - SAND_STREAM, - PRESSURE, - THICK_FAT, - EARLY_BIRD, - FLAME_BODY, - RUN_AWAY, - KEEN_EYE, - HYPER_CUTTER, - PICKUP, - TRUANT, - HUSTLE, - CUTE_CHARM, - PLUS, - MINUS, - FORECAST, - STICKY_HOLD, - SHED_SKIN, - GUTS, - MARVEL_SCALE, - LIQUID_OOZE, - OVERGROW, - BLAZE, - TORRENT, - SWARM, - ROCK_HEAD, - DROUGHT, - ARENA_TRAP, - VITAL_SPIRIT, - WHITE_SMOKE, - PURE_POWER, - SHELL_ARMOR, - AIR_LOCK, - TANGLED_FEET, - MOTOR_DRIVE, - RIVALRY, - STEADFAST, - SNOW_CLOAK, - GLUTTONY, - ANGER_POINT, - UNBURDEN, - HEATPROOF, - SIMPLE, - DRY_SKIN, - DOWNLOAD, - IRON_FIST, - POISON_HEAL, - ADAPTABILITY, - SKILL_LINK, - HYDRATION, - SOLAR_POWER, - QUICK_FEET, - NORMALIZE, - SNIPER, - MAGIC_GUARD, - NO_GUARD, - STALL, - TECHNICIAN, - LEAF_GUARD, - KLUTZ, - MOLD_BREAKER, - SUPER_LUCK, - AFTERMATH, - ANTICIPATION, - FOREWARN, - UNAWARE, - TINTED_LENS, - FILTER, - SLOW_START, - SCRAPPY, - STORM_DRAIN, - ICE_BODY, - SOLID_ROCK, - SNOW_WARNING, - HONEY_GATHER, - FRISK, - RECKLESS, - MULTITYPE, - FLOWER_GIFT, - BAD_DREAMS, - PICKPOCKET, - SHEER_FORCE, - CONTRARY, - UNNERVE, - DEFIANT, - DEFEATIST, - CURSED_BODY, - HEALER, - FRIEND_GUARD, - WEAK_ARMOR, - HEAVY_METAL, - LIGHT_METAL, - MULTISCALE, - TOXIC_BOOST, - FLARE_BOOST, - HARVEST, - TELEPATHY, - MOODY, - OVERCOAT, - POISON_TOUCH, - REGENERATOR, - BIG_PECKS, - SAND_RUSH, - WONDER_SKIN, - ANALYTIC, - ILLUSION, - IMPOSTER, - INFILTRATOR, - MUMMY, - MOXIE, - JUSTIFIED, - RATTLED, - MAGIC_BOUNCE, - SAP_SIPPER, - PRANKSTER, - SAND_FORCE, - IRON_BARBS, - ZEN_MODE, - VICTORY_STAR, - TURBOBLAZE, - TERAVOLT, - AROMA_VEIL, - FLOWER_VEIL, - CHEEK_POUCH, - PROTEAN, - FUR_COAT, - MAGICIAN, - BULLETPROOF, - COMPETITIVE, - STRONG_JAW, - REFRIGERATE, - SWEET_VEIL, - STANCE_CHANGE, - GALE_WINGS, - MEGA_LAUNCHER, - GRASS_PELT, - SYMBIOSIS, - TOUGH_CLAWS, - PIXILATE, - GOOEY, - AERILATE, - PARENTAL_BOND, - DARK_AURA, - FAIRY_AURA, - AURA_BREAK, - PRIMORDIAL_SEA, - DESOLATE_LAND, - DELTA_STREAM, - STAMINA, - WIMP_OUT, - EMERGENCY_EXIT, - WATER_COMPACTION, - MERCILESS, - SHIELDS_DOWN, - STAKEOUT, - WATER_BUBBLE, - STEELWORKER, - BERSERK, - SLUSH_RUSH, - LONG_REACH, - LIQUID_VOICE, - TRIAGE, - GALVANIZE, - SURGE_SURFER, - SCHOOLING, - DISGUISE, - BATTLE_BOND, - POWER_CONSTRUCT, - CORROSION, - COMATOSE, - QUEENLY_MAJESTY, - INNARDS_OUT, - DANCER, - BATTERY, - FLUFFY, - DAZZLING, - SOUL_HEART, - TANGLING_HAIR, - RECEIVER, - POWER_OF_ALCHEMY, - BEAST_BOOST, - RKS_SYSTEM, - ELECTRIC_SURGE, - PSYCHIC_SURGE, - MISTY_SURGE, - GRASSY_SURGE, - FULL_METAL_BODY, - SHADOW_SHIELD, - PRISM_ARMOR, - NEUROFORCE, - INTREPID_SWORD, - DAUNTLESS_SHIELD, - LIBERO, - BALL_FETCH, - COTTON_DOWN, - PROPELLER_TAIL, - MIRROR_ARMOR, - GULP_MISSILE, - STALWART, - STEAM_ENGINE, - PUNK_ROCK, - SAND_SPIT, - ICE_SCALES, - RIPEN, - ICE_FACE, - POWER_SPOT, - MIMICRY, - SCREEN_CLEANER, - STEELY_SPIRIT, - PERISH_BODY, - WANDERING_SPIRIT, - GORILLA_TACTICS, - NEUTRALIZING_GAS, - PASTEL_VEIL, - HUNGER_SWITCH, - QUICK_DRAW, - UNSEEN_FIST, - CURIOUS_MEDICINE, - TRANSISTOR, - DRAGONS_MAW, - CHILLING_NEIGH, - GRIM_NEIGH, - AS_ONE_GLASTRIER, - AS_ONE_SPECTRIER, - LINGERING_AROMA, - SEED_SOWER, - THERMAL_EXCHANGE, - ANGER_SHELL, - PURIFYING_SALT, - WELL_BAKED_BODY, - WIND_RIDER, - GUARD_DOG, - ROCKY_PAYLOAD, - WIND_POWER, - ZERO_TO_HERO, - COMMANDER, - ELECTROMORPHOSIS, - PROTOSYNTHESIS, - QUARK_DRIVE, - GOOD_AS_GOLD, - VESSEL_OF_RUIN, - SWORD_OF_RUIN, - TABLETS_OF_RUIN, - BEADS_OF_RUIN, - ORICHALCUM_PULSE, - HADRON_ENGINE, - OPPORTUNIST, - CUD_CHEW, - SHARPNESS, - SUPREME_OVERLORD, - COSTAR, - TOXIC_DEBRIS, - ARMOR_TAIL, - EARTH_EATER, - MYCELIUM_MIGHT, - MINDS_EYE, - SUPERSWEET_SYRUP, - HOSPITALITY, - TOXIC_CHAIN, - EMBODY_ASPECT_TEAL, - EMBODY_ASPECT_WELLSPRING, - EMBODY_ASPECT_HEARTHFLAME, - EMBODY_ASPECT_CORNERSTONE, - TERA_SHIFT, - TERA_SHELL, - TERAFORM_ZERO, - POISON_PUPPETEER -}; - export const allAbilities = [ new Ability(Abilities.NONE, "-", "", 3) ]; export function initAbilities() { @@ -2299,7 +1999,7 @@ export function initAbilities() { new Ability(Abilities.ROUGH_SKIN, "Rough Skin", "This Pokémon inflicts damage with its rough skin to the attacker on contact.", 3) .attr(PostDefendContactDamageAbAttr, 8) .ignorable() - .passive(), + .bypassFaint(), new Ability(Abilities.WONDER_GUARD, "Wonder Guard", "Its mysterious power only lets supereffective moves hit the Pokémon.", 3) .attr(NonSuperEffectiveImmunityAbAttr) .attr(ProtectAbilityAbAttr) @@ -2388,7 +2088,7 @@ export function initAbilities() { new Ability(Abilities.FORECAST, "Forecast (N)", "The Pokémon transforms with the weather to change its type to Water, Fire, or Ice.", 3), new Ability(Abilities.STICKY_HOLD, "Sticky Hold", "Items held by the Pokémon are stuck fast and cannot be removed by other Pokémon.", 3) .attr(BlockItemTheftAbAttr) - .passive() + .bypassFaint() .ignorable(), new Ability(Abilities.SHED_SKIN, "Shed Skin", "The Pokémon may heal its own status conditions by shedding its skin.", 3) .conditionalAttr(pokemon => !Utils.randSeedInt(3), PostTurnResetStatusAbAttr), @@ -2493,7 +2193,7 @@ export function initAbilities() { new Ability(Abilities.SUPER_LUCK, "Super Luck (N)", "The Pokémon is so lucky that the critical-hit ratios of its moves are boosted.", 4), new Ability(Abilities.AFTERMATH, "Aftermath", "Damages the attacker if it contacts the Pokémon with a finishing hit.", 4) .attr(PostFaintContactDamageAbAttr,4) - .passive(), + .bypassFaint(), new Ability(Abilities.ANTICIPATION, "Anticipation (N)", "The Pokémon can sense an opposing Pokémon's dangerous moves.", 4), new Ability(Abilities.FOREWARN, "Forewarn (N)", "When it enters a battle, the Pokémon can tell one of the moves an opposing Pokémon has.", 4), new Ability(Abilities.UNAWARE, "Unaware", "When attacking, the Pokémon ignores the target Pokémon's stat changes.", 4) @@ -2613,7 +2313,7 @@ export function initAbilities() { .condition(getWeatherCondition(WeatherType.SANDSTORM)), new Ability(Abilities.IRON_BARBS, "Iron Barbs", "Inflicts damage on the attacker upon contact with iron barbs.", 5) .attr(PostDefendContactDamageAbAttr, 8) - .passive(), + .bypassFaint(), new Ability(Abilities.ZEN_MODE, "Zen Mode", "Changes the Pokémon's shape when HP is half or less.", 5) .attr(PostBattleInitFormChangeAbAttr, p => p.getHpRatio() >= 0.5 ? 0 : 1) .attr(PostSummonFormChangeAbAttr, p => p.getHpRatio() >= 0.5 ? 0 : 1) diff --git a/src/data/api.ts b/src/data/api.ts index aee0ece9581..9d342dab288 100644 --- a/src/data/api.ts +++ b/src/data/api.ts @@ -5,7 +5,8 @@ import fs from 'vite-plugin-fs/browser'; import PokemonSpecies, { PokemonForm, SpeciesFormKey, allSpecies } from './pokemon-species'; import { GrowthRate } from './exp'; import { Type } from './type'; -import { Abilities, allAbilities } from './ability'; +import { allAbilities } from './ability'; +import { Abilities } from "./enums/abilities"; import { Species } from './enums/species'; import { pokemonFormLevelMoves } from './pokemon-level-moves'; import { tmSpecies } from './tms'; diff --git a/src/data/battler-tags.ts b/src/data/battler-tags.ts index f50ad87d61b..25567b83c27 100644 --- a/src/data/battler-tags.ts +++ b/src/data/battler-tags.ts @@ -8,11 +8,13 @@ import * as Utils from "../utils"; import { Moves } from "./enums/moves"; import { ChargeAttr, MoveFlags, allMoves } from "./move"; import { Type } from "./type"; -import { Abilities, BlockNonDirectDamageAbAttr, FlinchEffectAbAttr, applyAbAttrs } from "./ability"; +import { BlockNonDirectDamageAbAttr, FlinchEffectAbAttr, applyAbAttrs } from "./ability"; +import { Abilities } from "./enums/abilities"; import { BattlerTagType } from "./enums/battler-tag-type"; import { TerrainType } from "./terrain"; import { WeatherType } from "./weather"; import { BattleStat } from "./battle-stat"; +import { allAbilities } from "./ability" export enum BattlerTagLapseType { FAINT, @@ -797,14 +799,15 @@ export class TruantTag extends AbilityBattlerTag { } lapse(pokemon: Pokemon, lapseType: BattlerTagLapseType): boolean { - if (pokemon.getAbility().id !== Abilities.TRUANT) + if ((!pokemon.canApplyAbility() || pokemon.getAbility().id !== Abilities.TRUANT) && (!pokemon.canApplyAbility(true) || pokemon.getPassiveAbility().id !== Abilities.TRUANT)) return super.lapse(pokemon, lapseType); + const passive = pokemon.getAbility().id !== Abilities.TRUANT; const lastMove = pokemon.getLastXMoves().find(() => true); if (lastMove && lastMove.move !== Moves.NONE) { (pokemon.scene.getCurrentPhase() as MovePhase).cancel(); - pokemon.scene.unshiftPhase(new ShowAbilityPhase(pokemon.scene, pokemon.id)); + pokemon.scene.unshiftPhase(new ShowAbilityPhase(pokemon.scene, pokemon.id, passive)); pokemon.scene.queueMessage(getPokemonMessage(pokemon, ' is\nloafing around!')); } @@ -824,7 +827,7 @@ export class SlowStartTag extends AbilityBattlerTag { } lapse(pokemon: Pokemon, lapseType: BattlerTagLapseType): boolean { - if (pokemon.getAbility().id !== this.ability) + if (pokemon.getAbility().id !== this.ability && (pokemon.canApplyAbility(true) && pokemon.getPassiveAbility().id !== this.ability)) this.turnCount = 1; return super.lapse(pokemon, lapseType); @@ -875,7 +878,7 @@ export class HighestStatBoostTag extends AbilityBattlerTag { onRemove(pokemon: Pokemon): void { super.onRemove(pokemon); - pokemon.scene.queueMessage(`The effects of ${getPokemonMessage(pokemon, `'s\n${pokemon.getAbility().name} wore off!`)}`); + pokemon.scene.queueMessage(`The effects of ${getPokemonMessage(pokemon, `'s\n${allAbilities[this.ability].name} wore off!`)}`); } } diff --git a/src/data/enums/abilities.ts b/src/data/enums/abilities.ts new file mode 100644 index 00000000000..4be87d8181b --- /dev/null +++ b/src/data/enums/abilities.ts @@ -0,0 +1,313 @@ +export enum Abilities { + NONE, + STENCH, + DRIZZLE, + SPEED_BOOST, + BATTLE_ARMOR, + STURDY, + DAMP, + LIMBER, + SAND_VEIL, + STATIC, + VOLT_ABSORB, + WATER_ABSORB, + OBLIVIOUS, + CLOUD_NINE, + COMPOUND_EYES, + INSOMNIA, + COLOR_CHANGE, + IMMUNITY, + FLASH_FIRE, + SHIELD_DUST, + OWN_TEMPO, + SUCTION_CUPS, + INTIMIDATE, + SHADOW_TAG, + ROUGH_SKIN, + WONDER_GUARD, + LEVITATE, + EFFECT_SPORE, + SYNCHRONIZE, + CLEAR_BODY, + NATURAL_CURE, + LIGHTNING_ROD, + SERENE_GRACE, + SWIFT_SWIM, + CHLOROPHYLL, + ILLUMINATE, + TRACE, + HUGE_POWER, + POISON_POINT, + INNER_FOCUS, + MAGMA_ARMOR, + WATER_VEIL, + MAGNET_PULL, + SOUNDPROOF, + RAIN_DISH, + SAND_STREAM, + PRESSURE, + THICK_FAT, + EARLY_BIRD, + FLAME_BODY, + RUN_AWAY, + KEEN_EYE, + HYPER_CUTTER, + PICKUP, + TRUANT, + HUSTLE, + CUTE_CHARM, + PLUS, + MINUS, + FORECAST, + STICKY_HOLD, + SHED_SKIN, + GUTS, + MARVEL_SCALE, + LIQUID_OOZE, + OVERGROW, + BLAZE, + TORRENT, + SWARM, + ROCK_HEAD, + DROUGHT, + ARENA_TRAP, + VITAL_SPIRIT, + WHITE_SMOKE, + PURE_POWER, + SHELL_ARMOR, + AIR_LOCK, + TANGLED_FEET, + MOTOR_DRIVE, + RIVALRY, + STEADFAST, + SNOW_CLOAK, + GLUTTONY, + ANGER_POINT, + UNBURDEN, + HEATPROOF, + SIMPLE, + DRY_SKIN, + DOWNLOAD, + IRON_FIST, + POISON_HEAL, + ADAPTABILITY, + SKILL_LINK, + HYDRATION, + SOLAR_POWER, + QUICK_FEET, + NORMALIZE, + SNIPER, + MAGIC_GUARD, + NO_GUARD, + STALL, + TECHNICIAN, + LEAF_GUARD, + KLUTZ, + MOLD_BREAKER, + SUPER_LUCK, + AFTERMATH, + ANTICIPATION, + FOREWARN, + UNAWARE, + TINTED_LENS, + FILTER, + SLOW_START, + SCRAPPY, + STORM_DRAIN, + ICE_BODY, + SOLID_ROCK, + SNOW_WARNING, + HONEY_GATHER, + FRISK, + RECKLESS, + MULTITYPE, + FLOWER_GIFT, + BAD_DREAMS, + PICKPOCKET, + SHEER_FORCE, + CONTRARY, + UNNERVE, + DEFIANT, + DEFEATIST, + CURSED_BODY, + HEALER, + FRIEND_GUARD, + WEAK_ARMOR, + HEAVY_METAL, + LIGHT_METAL, + MULTISCALE, + TOXIC_BOOST, + FLARE_BOOST, + HARVEST, + TELEPATHY, + MOODY, + OVERCOAT, + POISON_TOUCH, + REGENERATOR, + BIG_PECKS, + SAND_RUSH, + WONDER_SKIN, + ANALYTIC, + ILLUSION, + IMPOSTER, + INFILTRATOR, + MUMMY, + MOXIE, + JUSTIFIED, + RATTLED, + MAGIC_BOUNCE, + SAP_SIPPER, + PRANKSTER, + SAND_FORCE, + IRON_BARBS, + ZEN_MODE, + VICTORY_STAR, + TURBOBLAZE, + TERAVOLT, + AROMA_VEIL, + FLOWER_VEIL, + CHEEK_POUCH, + PROTEAN, + FUR_COAT, + MAGICIAN, + BULLETPROOF, + COMPETITIVE, + STRONG_JAW, + REFRIGERATE, + SWEET_VEIL, + STANCE_CHANGE, + GALE_WINGS, + MEGA_LAUNCHER, + GRASS_PELT, + SYMBIOSIS, + TOUGH_CLAWS, + PIXILATE, + GOOEY, + AERILATE, + PARENTAL_BOND, + DARK_AURA, + FAIRY_AURA, + AURA_BREAK, + PRIMORDIAL_SEA, + DESOLATE_LAND, + DELTA_STREAM, + STAMINA, + WIMP_OUT, + EMERGENCY_EXIT, + WATER_COMPACTION, + MERCILESS, + SHIELDS_DOWN, + STAKEOUT, + WATER_BUBBLE, + STEELWORKER, + BERSERK, + SLUSH_RUSH, + LONG_REACH, + LIQUID_VOICE, + TRIAGE, + GALVANIZE, + SURGE_SURFER, + SCHOOLING, + DISGUISE, + BATTLE_BOND, + POWER_CONSTRUCT, + CORROSION, + COMATOSE, + QUEENLY_MAJESTY, + INNARDS_OUT, + DANCER, + BATTERY, + FLUFFY, + DAZZLING, + SOUL_HEART, + TANGLING_HAIR, + RECEIVER, + POWER_OF_ALCHEMY, + BEAST_BOOST, + RKS_SYSTEM, + ELECTRIC_SURGE, + PSYCHIC_SURGE, + MISTY_SURGE, + GRASSY_SURGE, + FULL_METAL_BODY, + SHADOW_SHIELD, + PRISM_ARMOR, + NEUROFORCE, + INTREPID_SWORD, + DAUNTLESS_SHIELD, + LIBERO, + BALL_FETCH, + COTTON_DOWN, + PROPELLER_TAIL, + MIRROR_ARMOR, + GULP_MISSILE, + STALWART, + STEAM_ENGINE, + PUNK_ROCK, + SAND_SPIT, + ICE_SCALES, + RIPEN, + ICE_FACE, + POWER_SPOT, + MIMICRY, + SCREEN_CLEANER, + STEELY_SPIRIT, + PERISH_BODY, + WANDERING_SPIRIT, + GORILLA_TACTICS, + NEUTRALIZING_GAS, + PASTEL_VEIL, + HUNGER_SWITCH, + QUICK_DRAW, + UNSEEN_FIST, + CURIOUS_MEDICINE, + TRANSISTOR, + DRAGONS_MAW, + CHILLING_NEIGH, + GRIM_NEIGH, + AS_ONE_GLASTRIER, + AS_ONE_SPECTRIER, + LINGERING_AROMA, + SEED_SOWER, + THERMAL_EXCHANGE, + ANGER_SHELL, + PURIFYING_SALT, + WELL_BAKED_BODY, + WIND_RIDER, + GUARD_DOG, + ROCKY_PAYLOAD, + WIND_POWER, + ZERO_TO_HERO, + COMMANDER, + ELECTROMORPHOSIS, + PROTOSYNTHESIS, + QUARK_DRIVE, + GOOD_AS_GOLD, + VESSEL_OF_RUIN, + SWORD_OF_RUIN, + TABLETS_OF_RUIN, + BEADS_OF_RUIN, + ORICHALCUM_PULSE, + HADRON_ENGINE, + OPPORTUNIST, + CUD_CHEW, + SHARPNESS, + SUPREME_OVERLORD, + COSTAR, + TOXIC_DEBRIS, + ARMOR_TAIL, + EARTH_EATER, + MYCELIUM_MIGHT, + MINDS_EYE, + SUPERSWEET_SYRUP, + HOSPITALITY, + TOXIC_CHAIN, + EMBODY_ASPECT_TEAL, + EMBODY_ASPECT_WELLSPRING, + EMBODY_ASPECT_HEARTHFLAME, + EMBODY_ASPECT_CORNERSTONE, + TERA_SHIFT, + TERA_SHELL, + TERAFORM_ZERO, + POISON_PUPPETEER +} diff --git a/src/data/move.ts b/src/data/move.ts index c8ead786b33..2ea99430211 100644 --- a/src/data/move.ts +++ b/src/data/move.ts @@ -12,7 +12,8 @@ import * as Utils from "../utils"; import { WeatherType } from "./weather"; import { ArenaTagSide, ArenaTrapTag } from "./arena-tag"; import { ArenaTagType } from "./enums/arena-tag-type"; -import { Abilities, ProtectAbilityAbAttr, BlockRecoilDamageAttr, BlockOneHitKOAbAttr, IgnoreContactAbAttr, MaxMultiHitAbAttr, applyAbAttrs, BlockNonDirectDamageAbAttr, applyPreSwitchOutAbAttrs, PreSwitchOutAbAttr } from "./ability"; +import { ProtectAbilityAbAttr, BlockRecoilDamageAttr, BlockOneHitKOAbAttr, IgnoreContactAbAttr, MaxMultiHitAbAttr, applyAbAttrs, BlockNonDirectDamageAbAttr, applyPreSwitchOutAbAttrs, PreSwitchOutAbAttr } from "./ability"; +import { Abilities } from "./enums/abilities"; import { PokemonHeldItemModifier } from "../modifier/modifier"; import { BattlerIndex } from "../battle"; import { Stat } from "./pokemon-stat"; @@ -271,7 +272,7 @@ export default class Move { checkFlag(flag: MoveFlags, user: Pokemon, target: Pokemon): boolean { switch (flag) { case MoveFlags.MAKES_CONTACT: - if (user.getAbility().hasAttr(IgnoreContactAbAttr)) + if ((user.canApplyAbility() && user.getAbility().hasAttr(IgnoreContactAbAttr)) || (user.canApplyAbility(true) && user.getPassiveAbility().hasAttr(IgnoreContactAbAttr))) return false; break; } @@ -4504,9 +4505,9 @@ export function initMoves() { .attr(StatChangeAttr, [ BattleStat.SPATK, BattleStat.SPDEF, BattleStat.SPD ], 2, true) .ignoresVirtual(), new StatusMove(Moves.MAGNETIC_FLUX, "Magnetic Flux", Type.ELECTRIC, -1, 20, "The user manipulates magnetic fields, which raises the Defense and Sp. Def stats of ally Pokémon with the Plus or Minus Ability.", -1, 0, 6) - .attr(StatChangeAttr, [ BattleStat.DEF, BattleStat.SPDEF ], 1, false, (user, target, move) => !![ Abilities.PLUS, Abilities.MINUS].find(a => a === user.getAbility().id)) + .attr(StatChangeAttr, [ BattleStat.DEF, BattleStat.SPDEF ], 1, false, (user, target, move) => !![ Abilities.PLUS, Abilities.MINUS].find(a => a === user.getAbility().id || (user.canApplyAbility(true) && a === user.getPassiveAbility().id))) .target(MoveTarget.USER_AND_ALLIES) - .condition((user, target, move) => !![ user, user.getAlly() ].filter(p => p?.isActive()).find(p => !![ Abilities.PLUS, Abilities.MINUS].find(a => a === p.getAbility().id))), + .condition((user, target, move) => !![ user, user.getAlly() ].filter(p => p?.isActive()).find(p => !![ Abilities.PLUS, Abilities.MINUS].find(a => a === p.getAbility().id || (user.canApplyAbility(true) && a === user.getPassiveAbility().id)))), new StatusMove(Moves.HAPPY_HOUR, "Happy Hour (N)", Type.NORMAL, -1, 30, "Using Happy Hour doubles the amount of prize money received after battle.", -1, 0, 6) // No animation .target(MoveTarget.USER_SIDE), new StatusMove(Moves.ELECTRIC_TERRAIN, "Electric Terrain", Type.ELECTRIC, -1, 10, "The user electrifies the ground for five turns, powering up Electric-type moves. Pokémon on the ground no longer fall asleep.", -1, 0, 6) @@ -4631,9 +4632,9 @@ export function initMoves() { .attr(StatChangeAttr, BattleStat.SPD, -1), new SelfStatusMove(Moves.LASER_FOCUS, "Laser Focus (N)", Type.NORMAL, -1, 30, "The user concentrates intensely. The attack on the next turn always results in a critical hit.", -1, 0, 7), new StatusMove(Moves.GEAR_UP, "Gear Up", Type.STEEL, -1, 20, "The user engages its gears to raise the Attack and Sp. Atk stats of ally Pokémon with the Plus or Minus Ability.", -1, 0, 7) - .attr(StatChangeAttr, [ BattleStat.ATK, BattleStat.SPATK ], 1, false, (user, target, move) => [ Abilities.PLUS, Abilities.MINUS ].indexOf(target.getAbility().id) > -1) + .attr(StatChangeAttr, [ BattleStat.ATK, BattleStat.SPATK ], 1, false, (user, target, move) => [ Abilities.PLUS, Abilities.MINUS ].includes(target.getAbility().id) || (target.canApplyAbility(true) && [ Abilities.PLUS, Abilities.MINUS ].includes(target.getPassiveAbility().id))) .target(MoveTarget.USER_AND_ALLIES) - .condition((user, target, move) => !![ user, user.getAlly() ].find(p => p && [ Abilities.PLUS, Abilities.MINUS ].indexOf(p.getAbility().id) > -1)), + .condition((user, target, move) => !![ user, user.getAlly() ].find(p => p && [ Abilities.PLUS, Abilities.MINUS ].includes(p.getAbility().id) || (target.canApplyAbility(true) && [ Abilities.PLUS, Abilities.MINUS ].includes(target.getPassiveAbility().id)))), new AttackMove(Moves.THROAT_CHOP, "Throat Chop (P)", Type.DARK, MoveCategory.PHYSICAL, 80, 100, 15, "The user attacks the target's throat, and the resultant suffering prevents the target from using moves that emit sound for two turns.", 100, 0, 7), new AttackMove(Moves.POLLEN_PUFF, "Pollen Puff (P)", Type.BUG, MoveCategory.SPECIAL, 90, 100, 15, "The user attacks the enemy with a pollen puff that explodes. If the target is an ally, it gives the ally a pollen puff that restores its HP instead.", -1, 0, 7) .ballBombMove(), diff --git a/src/data/pokemon-forms.ts b/src/data/pokemon-forms.ts index 63f85ae42d8..e5bcf25a4fe 100644 --- a/src/data/pokemon-forms.ts +++ b/src/data/pokemon-forms.ts @@ -6,7 +6,7 @@ import { SpeciesFormKey } from "./pokemon-species"; import { Species } from "./enums/species"; import { StatusEffect } from "./status-effect"; import { MoveCategory, allMoves } from "./move"; -import { Abilities } from "./ability"; +import { Abilities } from "./enums/abilities"; export enum FormChangeItem { NONE, diff --git a/src/data/pokemon-species.ts b/src/data/pokemon-species.ts index e0ef53d9628..7f52315cfa7 100644 --- a/src/data/pokemon-species.ts +++ b/src/data/pokemon-species.ts @@ -1,4 +1,4 @@ -import { Abilities } from './ability'; +import { Abilities } from "./enums/abilities"; import BattleScene, { AnySound } from '../battle-scene'; import { GrowthRate } from './exp'; import { SpeciesWildEvolutionDelay, pokemonEvolutions, pokemonPrevolutions } from './pokemon-evolutions'; @@ -3053,6 +3053,578 @@ export const noStarterFormKeys: string[] = [ SpeciesFormKey.ETERNAMAX ].map(k => k.toString()); +export const starterPassiveAbilities = { + [Species.BULBASAUR]: Abilities.SOLAR_POWER, + [Species.CHARMANDER]: Abilities.INTIMIDATE, + [Species.SQUIRTLE]: Abilities.DAUNTLESS_SHIELD, + [Species.CATERPIE]: Abilities.MAGICIAN, + [Species.WEEDLE]: Abilities.POISON_TOUCH, + [Species.PIDGEY]: Abilities.TECHNICIAN, + [Species.RATTATA]: Abilities.STRONG_JAW, + [Species.SPEAROW]: Abilities.MOXIE, + [Species.EKANS]: Abilities.ROUGH_SKIN, + [Species.SANDSHREW]: Abilities.IRON_BARBS, + [Species.NIDORAN_F]: Abilities.QUEENLY_MAJESTY, + [Species.NIDORAN_M]: Abilities.SUPREME_OVERLORD, + [Species.VULPIX]: Abilities.CURSED_BODY, + [Species.ZUBAT]: Abilities.WIND_RIDER, + [Species.ODDISH]: Abilities.LINGERING_AROMA, + [Species.PARAS]: Abilities.POISON_HEAL, + [Species.VENONAT]: Abilities.TECHNICIAN, + [Species.DIGLETT]: Abilities.STURDY, + [Species.MEOWTH]: Abilities.NORMALIZE, + [Species.PSYDUCK]: Abilities.SIMPLE, + [Species.MANKEY]: Abilities.STAMINA, + [Species.GROWLITHE]: Abilities.BALL_FETCH, + [Species.POLIWAG]: Abilities.WATER_BUBBLE, + [Species.ABRA]: Abilities.TECHNICIAN, + [Species.MACHOP]: Abilities.IRON_FIST, + [Species.BELLSPROUT]: Abilities.CORROSION, + [Species.TENTACOOL]: Abilities.INNARDS_OUT, + [Species.GEODUDE]: Abilities.ROCKY_PAYLOAD, + [Species.PONYTA]: Abilities.PIXILATE, + [Species.SLOWPOKE]: Abilities.UNAWARE, + [Species.MAGNEMITE]: Abilities.MOTOR_DRIVE, + [Species.FARFETCHD]: Abilities.PURE_POWER, + [Species.DODUO]: Abilities.RECKLESS, + [Species.SEEL]: Abilities.REGENERATOR, + [Species.GRIMER]: Abilities.GOOEY, + [Species.SHELLDER]: Abilities.MOXIE, + [Species.GASTLY]: Abilities.PERISH_BODY, + [Species.ONIX]: Abilities.ROCKY_PAYLOAD, + [Species.DROWZEE]: Abilities.BAD_DREAMS, + [Species.KRABBY]: Abilities.ANGER_SHELL, + [Species.VOLTORB]: Abilities.GALVANIZE, + [Species.EXEGGCUTE]: Abilities.PARENTAL_BOND, + [Species.CUBONE]: Abilities.MOODY, + [Species.LICKITUNG]: Abilities.EARTH_EATER, + [Species.KOFFING]: Abilities.FLARE_BOOST, + [Species.RHYHORN]: Abilities.FILTER, + [Species.TANGELA]: Abilities.TANGLING_HAIR, + [Species.KANGASKHAN]: Abilities.IRON_FIST, + [Species.HORSEA]: Abilities.DRIZZLE, + [Species.GOLDEEN]: Abilities.VOLT_ABSORB, + [Species.STARYU]: Abilities.REGENERATOR, + [Species.SCYTHER]: Abilities.SPEED_BOOST, + [Species.PINSIR]: Abilities.SAP_SIPPER, + [Species.TAUROS]: Abilities.ROCK_HEAD, + [Species.MAGIKARP]: Abilities.BERSERK, + [Species.LAPRAS]: Abilities.LIQUID_VOICE, + [Species.DITTO]: Abilities.GOOEY, + [Species.EEVEE]: Abilities.PROTEAN, + [Species.PORYGON]: Abilities.QUARK_DRIVE, + [Species.OMANYTE]: Abilities.ANGER_SHELL, + [Species.KABUTO]: Abilities.SHARPNESS, + [Species.AERODACTYL]: Abilities.PROTOSYNTHESIS, + [Species.ARTICUNO]: Abilities.SNOW_WARNING, + [Species.ZAPDOS]: Abilities.DRIZZLE, + [Species.MOLTRES]: Abilities.DROUGHT, + [Species.DRATINI]: Abilities.DELTA_STREAM, + [Species.MEWTWO]: Abilities.BERSERK, + [Species.MEW]: Abilities.PROTEAN, + [Species.CHIKORITA]: Abilities.TRIAGE, + [Species.CYNDAQUIL]: Abilities.TURBOBLAZE, + [Species.TOTODILE]: Abilities.STRONG_JAW, + [Species.SENTRET]: Abilities.FLUFFY, + [Species.HOOTHOOT]: Abilities.CURSED_BODY, + [Species.LEDYBA]: Abilities.SCREEN_CLEANER, + [Species.SPINARAK]: Abilities.PRANKSTER, + [Species.CHINCHOU]: Abilities.REGENERATOR, + [Species.PICHU]: Abilities.TRANSISTOR, + [Species.CLEFFA]: Abilities.TRIAGE, + [Species.IGGLYBUFF]: Abilities.SERENE_GRACE, + [Species.TOGEPI]: Abilities.OPPORTUNIST, + [Species.NATU]: Abilities.TINTED_LENS, + [Species.MAREEP]: Abilities.FLUFFY, + [Species.HOPPIP]: Abilities.PRANKSTER, + [Species.AIPOM]: Abilities.SCRAPPY, + [Species.SUNKERN]: Abilities.DROUGHT, + [Species.YANMA]: Abilities.TECHNICIAN, + [Species.WOOPER]: Abilities.SIMPLE, + [Species.MURKROW]: Abilities.DEFIANT, + [Species.MISDREAVUS]: Abilities.DAZZLING, + [Species.UNOWN]: Abilities.PICKUP, + [Species.GIRAFARIG]: Abilities.PARENTAL_BOND, + [Species.PINECO]: Abilities.IRON_BARBS, + [Species.DUNSPARCE]: Abilities.MARVEL_SCALE, + [Species.GLIGAR]: Abilities.MERCILESS, + [Species.SNUBBULL]: Abilities.BALL_FETCH, + [Species.QWILFISH]: Abilities.LIQUID_OOZE, + [Species.SHUCKLE]: Abilities.WELL_BAKED_BODY, + [Species.HERACROSS]: Abilities.QUICK_FEET, + [Species.SNEASEL]: Abilities.MOXIE, + [Species.TEDDIURSA]: Abilities.GLUTTONY, + [Species.SLUGMA]: Abilities.DESOLATE_LAND, + [Species.SWINUB]: Abilities.SLUSH_RUSH, + [Species.CORSOLA]: Abilities.STORM_DRAIN, + [Species.REMORAID]: Abilities.SKILL_LINK, + [Species.DELIBIRD]: Abilities.PRANKSTER, + [Species.SKARMORY]: Abilities.OBLIVIOUS, + [Species.HOUNDOUR]: Abilities.INTIMIDATE, + [Species.PHANPY]: Abilities.ROCK_HEAD, + [Species.STANTLER]: Abilities.MAGIC_GUARD, + [Species.SMEARGLE]: Abilities.TRACE, + [Species.TYROGUE]: Abilities.STAMINA, + [Species.SMOOCHUM]: Abilities.CUTE_CHARM, + [Species.ELEKID]: Abilities.ADAPTABILITY, + [Species.MAGBY]: Abilities.CONTRARY, + [Species.MILTANK]: Abilities.GLUTTONY, + [Species.RAIKOU]: Abilities.FLARE_BOOST, + [Species.ENTEI]: Abilities.TOXIC_BOOST, + [Species.SUICUNE]: Abilities.SPEED_BOOST, + [Species.LARVITAR]: Abilities.SAND_FORCE, + [Species.LUGIA]: Abilities.STORM_DRAIN, + [Species.HO_OH]: Abilities.FLASH_FIRE, + [Species.CELEBI]: Abilities.TRIAGE, + [Species.TREECKO]: Abilities.GRASSY_SURGE, + [Species.TORCHIC]: Abilities.RECKLESS, + [Species.MUDKIP]: Abilities.REGENERATOR, + [Species.POOCHYENA]: Abilities.STRONG_JAW, + [Species.ZIGZAGOON]: Abilities.PICKPOCKET, + [Species.WURMPLE]: Abilities.TINTED_LENS, + [Species.LOTAD]: Abilities.DRIZZLE, + [Species.SEEDOT]: Abilities.DISGUISE, + [Species.TAILLOW]: Abilities.KEEN_EYE, + [Species.WINGULL]: Abilities.HYDRATION, + [Species.RALTS]: Abilities.PSYCHIC_SURGE, + [Species.SURSKIT]: Abilities.WATER_ABSORB, + [Species.SHROOMISH]: Abilities.GUTS, + [Species.SLAKOTH]: Abilities.GUTS, + [Species.NINCADA]: Abilities.OVERCOAT, + [Species.WHISMUR]: Abilities.PUNK_ROCK, + [Species.MAKUHITA]: Abilities.CONTRARY, + [Species.AZURILL]: Abilities.UNNERVE, + [Species.NOSEPASS]: Abilities.LEVITATE, + [Species.SKITTY]: Abilities.SCRAPPY, + [Species.SABLEYE]: Abilities.UNNERVE, + [Species.MAWILE]: Abilities.MOLD_BREAKER, + [Species.ARON]: Abilities.SOLID_ROCK, + [Species.MEDITITE]: Abilities.OWN_TEMPO, + [Species.ELECTRIKE]: Abilities.SPEED_BOOST, + [Species.PLUSLE]: Abilities.MINUS, + [Species.MINUN]: Abilities.PLUS, + [Species.VOLBEAT]: Abilities.TINTED_LENS, + [Species.ILLUMISE]: Abilities.SWARM, + [Species.GULPIN]: Abilities.POISON_TOUCH, + [Species.CARVANHA]: Abilities.STAKEOUT, + [Species.WAILMER]: Abilities.LEVITATE, + [Species.NUMEL]: Abilities.TURBOBLAZE, + [Species.TORKOAL]: Abilities.PROTOSYNTHESIS, + [Species.SPOINK]: Abilities.PSYCHIC_SURGE, + [Species.SPINDA]: Abilities.SIMPLE, + [Species.TRAPINCH]: Abilities.ADAPTABILITY, + [Species.CACNEA]: Abilities.SAND_RUSH, + [Species.SWABLU]: Abilities.WHITE_SMOKE, + [Species.ZANGOOSE]: Abilities.SUPER_LUCK, + [Species.SEVIPER]: Abilities.MOLD_BREAKER, + [Species.LUNATONE]: Abilities.SHADOW_SHIELD, + [Species.SOLROCK]: Abilities.FULL_METAL_BODY, + [Species.BARBOACH]: Abilities.BALL_FETCH, + [Species.CORPHISH]: Abilities.WATER_BUBBLE, + [Species.BALTOY]: Abilities.OWN_TEMPO, + [Species.LILEEP]: Abilities.WATER_ABSORB, + [Species.ANORITH]: Abilities.WATER_ABSORB, + [Species.FEEBAS]: Abilities.PASTEL_VEIL, + [Species.CASTFORM]: Abilities.ADAPTABILITY, + [Species.KECLEON]: Abilities.ADAPTABILITY, + [Species.SHUPPET]: Abilities.MUMMY, + [Species.DUSKULL]: Abilities.UNNERVE, + [Species.TROPIUS]: Abilities.CUD_CHEW, + [Species.ABSOL]: Abilities.DARK_AURA, + [Species.WYNAUT]: Abilities.STAMINA, + [Species.SNORUNT]: Abilities.SNOW_WARNING, + [Species.SPHEAL]: Abilities.SLUSH_RUSH, + [Species.CLAMPERL]: Abilities.SIMPLE, + [Species.RELICANTH]: Abilities.SOLID_ROCK, + [Species.LUVDISC]: Abilities.PICKUP, + [Species.BAGON]: Abilities.GALE_WINGS, + [Species.BELDUM]: Abilities.IRON_FIST, + [Species.REGIROCK]: Abilities.REGENERATOR, + [Species.REGICE]: Abilities.ICE_SCALES, + [Species.REGISTEEL]: Abilities.STEELY_SPIRIT, + [Species.LATIAS]: Abilities.SERENE_GRACE, + [Species.LATIOS]: Abilities.SERENE_GRACE, + [Species.KYOGRE]: Abilities.HYDRATION, + [Species.GROUDON]: Abilities.LEAF_GUARD, + [Species.RAYQUAZA]: Abilities.STEADFAST, + [Species.JIRACHI]: Abilities.COMATOSE, + [Species.DEOXYS]: Abilities.STICKY_HOLD, + [Species.TURTWIG]: Abilities.HARVEST, + [Species.CHIMCHAR]: Abilities.DEFIANT, + [Species.PIPLUP]: Abilities.BATTLE_ARMOR, + [Species.STARLY]: Abilities.ROCK_HEAD, + [Species.BIDOOF]: Abilities.NEUROFORCE, + [Species.KRICKETOT]: Abilities.SOUNDPROOF, + [Species.SHINX]: Abilities.VOLT_ABSORB, + [Species.BUDEW]: Abilities.CUTE_CHARM, + [Species.CRANIDOS]: Abilities.ROCK_HEAD, + [Species.SHIELDON]: Abilities.SOLID_ROCK, + [Species.BURMY]: Abilities.STURDY, + [Species.COMBEE]: Abilities.QUEENLY_MAJESTY, + [Species.PACHIRISU]: Abilities.BALL_FETCH, + [Species.BUIZEL]: Abilities.HYDRATION, + [Species.CHERUBI]: Abilities.DROUGHT, + [Species.SHELLOS]: Abilities.SHELL_ARMOR, + [Species.DRIFLOON]: Abilities.PICKPOCKET, + [Species.BUNEARY]: Abilities.OBLIVIOUS, + [Species.GLAMEOW]: Abilities.PICKUP, + [Species.CHINGLING]: Abilities.VICTORY_STAR, + [Species.STUNKY]: Abilities.MERCILESS, + [Species.BRONZOR]: Abilities.SOUNDPROOF, + [Species.BONSLY]: Abilities.SAP_SIPPER, + [Species.MIME_JR]: Abilities.MAGIC_BOUNCE, + [Species.HAPPINY]: Abilities.TRIAGE, + [Species.CHATOT]: Abilities.PUNK_ROCK, + [Species.SPIRITOMB]: Abilities.REGENERATOR, + [Species.GIBLE]: Abilities.SAND_STREAM, + [Species.MUNCHLAX]: Abilities.CUD_CHEW, + [Species.RIOLU]: Abilities.MEGA_LAUNCHER, + [Species.HIPPOPOTAS]: Abilities.SAND_VEIL, + [Species.SKORUPI]: Abilities.SUPER_LUCK, + [Species.CROAGUNK]: Abilities.PICKPOCKET, + [Species.CARNIVINE]: Abilities.EFFECT_SPORE, + [Species.FINNEON]: Abilities.DRIZZLE, + [Species.MANTYKE]: Abilities.STORM_DRAIN, + [Species.SNOVER]: Abilities.SNOW_CLOAK, + [Species.ROTOM]: Abilities.ELECTRIC_SURGE, + [Species.UXIE]: Abilities.ILLUSION, + [Species.MESPRIT]: Abilities.MOODY, + [Species.AZELF]: Abilities.NEUROFORCE, + [Species.DIALGA]: Abilities.SPEED_BOOST, + [Species.PALKIA]: Abilities.MAGIC_BOUNCE, + [Species.HEATRAN]: Abilities.ROUGH_SKIN, + [Species.REGIGIGAS]: Abilities.IRON_FIST, + [Species.GIRATINA]: Abilities.SHADOW_TAG, + [Species.CRESSELIA]: Abilities.MAGIC_BOUNCE, + [Species.PHIONE]: Abilities.SWIFT_SWIM, + [Species.MANAPHY]: Abilities.SIMPLE, + [Species.DARKRAI]: Abilities.UNNERVE, + [Species.SHAYMIN]: Abilities.FLOWER_VEIL, + [Species.ARCEUS]: Abilities.ADAPTABILITY, + [Species.VICTINI]: Abilities.SUPER_LUCK, + [Species.SNIVY]: Abilities.MULTISCALE, + [Species.TEPIG]: Abilities.SAND_RUSH, + [Species.OSHAWOTT]: Abilities.LIGHTNING_ROD, + [Species.PATRAT]: Abilities.STAKEOUT, + [Species.LILLIPUP]: Abilities.BALL_FETCH, + [Species.PURRLOIN]: Abilities.DEFIANT, + [Species.PANSAGE]: Abilities.SAP_SIPPER, + [Species.PANSEAR]: Abilities.FLASH_FIRE, + [Species.PANPOUR]: Abilities.STORM_DRAIN, + [Species.MUNNA]: Abilities.NEUTRALIZING_GAS, + [Species.PIDOVE]: Abilities.OPPORTUNIST, + [Species.BLITZLE]: Abilities.FLARE_BOOST, + [Species.ROGGENROLA]: Abilities.SOLID_ROCK, + [Species.WOOBAT]: Abilities.SOUL_HEART, + [Species.DRILBUR]: Abilities.SAND_STREAM, + [Species.AUDINO]: Abilities.SERENE_GRACE, + [Species.TIMBURR]: Abilities.STAMINA, + [Species.TYMPOLE]: Abilities.MOODY, + [Species.THROH]: Abilities.SIMPLE, + [Species.SAWK]: Abilities.DEFIANT, + [Species.SEWADDLE]: Abilities.SHARPNESS, + [Species.VENIPEDE]: Abilities.INTIMIDATE, + [Species.COTTONEE]: Abilities.MISTY_SURGE, + [Species.PETILIL]: Abilities.ORICHALCUM_PULSE, + [Species.BASCULIN]: Abilities.ROCK_HEAD, + [Species.SANDILE]: Abilities.STRONG_JAW, + [Species.DARUMAKA]: Abilities.IRON_FIST, + [Species.MARACTUS]: Abilities.IRON_BARBS, + [Species.DWEBBLE]: Abilities.STAMINA, + [Species.SCRAGGY]: Abilities.ROCK_HEAD, + [Species.SIGILYPH]: Abilities.MAGICIAN, + [Species.YAMASK]: Abilities.GOOD_AS_GOLD, + [Species.TIRTOUGA]: Abilities.SHELL_ARMOR, + [Species.ARCHEN]: Abilities.ROCKY_PAYLOAD, + [Species.TRUBBISH]: Abilities.GOOEY, + [Species.ZORUA]: Abilities.ADAPTABILITY, + [Species.MINCCINO]: Abilities.SCRAPPY, + [Species.GOTHITA]: Abilities.PRESSURE, + [Species.SOLOSIS]: Abilities.GOOEY, + [Species.DUCKLETT]: Abilities.GALE_WINGS, + [Species.VANILLITE]: Abilities.REFRIGERATE, + [Species.DEERLING]: Abilities.JUSTIFIED, + [Species.EMOLGA]: Abilities.WIND_POWER, + [Species.KARRABLAST]: Abilities.NO_GUARD, + [Species.FOONGUS]: Abilities.ADAPTABILITY, + [Species.FRILLISH]: Abilities.MUMMY, + [Species.ALOMOMOLA]: Abilities.MULTISCALE, + [Species.JOLTIK]: Abilities.VOLT_ABSORB, + [Species.FERROSEED]: Abilities.SKILL_LINK, + [Species.KLINK]: Abilities.STEELWORKER, + [Species.TYNAMO]: Abilities.SWIFT_SWIM, + [Species.ELGYEM]: Abilities.COMMANDER, + [Species.LITWICK]: Abilities.SOUL_HEART, + [Species.AXEW]: Abilities.SHEER_FORCE, + [Species.CUBCHOO]: Abilities.INTIMIDATE, + [Species.CRYOGONAL]: Abilities.DAZZLING, + [Species.SHELMET]: Abilities.DISGUISE, + [Species.STUNFISK]: Abilities.STORM_DRAIN, + [Species.MIENFOO]: Abilities.NO_GUARD, + [Species.DRUDDIGON]: Abilities.INTIMIDATE, + [Species.GOLETT]: Abilities.JUSTIFIED, + [Species.PAWNIARD]: Abilities.SHARPNESS, + [Species.BOUFFALANT]: Abilities.THICK_FAT, + [Species.RUFFLET]: Abilities.RECKLESS, + [Species.VULLABY]: Abilities.THICK_FAT, + [Species.HEATMOR]: Abilities.CONTRARY, + [Species.DURANT]: Abilities.TOUGH_CLAWS, + [Species.DEINO]: Abilities.BERSERK, + [Species.LARVESTA]: Abilities.DROUGHT, + [Species.COBALION]: Abilities.INTREPID_SWORD, + [Species.TERRAKION]: Abilities.ROCKY_PAYLOAD, + [Species.VIRIZION]: Abilities.SYMBIOSIS, + [Species.TORNADUS]: Abilities.DELTA_STREAM, + [Species.THUNDURUS]: Abilities.DRIZZLE, + [Species.RESHIRAM]: Abilities.ORICHALCUM_PULSE, + [Species.ZEKROM]: Abilities.HADRON_ENGINE, + [Species.LANDORUS]: Abilities.PRANKSTER, + [Species.KYUREM]: Abilities.SNOW_WARNING, + [Species.KELDEO]: Abilities.HUGE_POWER, + [Species.MELOETTA]: Abilities.PUNK_ROCK, + [Species.GENESECT]: Abilities.MEGA_LAUNCHER, + [Species.CHESPIN]: Abilities.IRON_BARBS, + [Species.FENNEKIN]: Abilities.MAGIC_GUARD, + [Species.FROAKIE]: Abilities.MERCILESS, + [Species.BUNNELBY]: Abilities.GUTS, + [Species.FLETCHLING]: Abilities.RECKLESS, + [Species.SCATTERBUG]: Abilities.PRANKSTER, + [Species.LITLEO]: Abilities.INTIMIDATE, + [Species.FLABEBE]: Abilities.GRASSY_SURGE, + [Species.SKIDDO]: Abilities.FUR_COAT, + [Species.PANCHAM]: Abilities.FLUFFY, + [Species.FURFROU]: Abilities.BALL_FETCH, + [Species.ESPURR]: Abilities.PSYCHIC_SURGE, + [Species.HONEDGE]: Abilities.SHARPNESS, + [Species.SPRITZEE]: Abilities.UNAWARE, + [Species.SWIRLIX]: Abilities.PIXILATE, + [Species.INKAY]: Abilities.SUPREME_OVERLORD, + [Species.BINACLE]: Abilities.SOLID_ROCK, + [Species.SKRELP]: Abilities.CORROSION, + [Species.CLAUNCHER]: Abilities.SWIFT_SWIM, + [Species.HELIOPTILE]: Abilities.NO_GUARD, + [Species.TYRUNT]: Abilities.SHEER_FORCE, + [Species.AMAURA]: Abilities.SERENE_GRACE, + [Species.HAWLUCHA]: Abilities.RECKLESS, + [Species.DEDENNE]: Abilities.SIMPLE, + [Species.CARBINK]: Abilities.OBLIVIOUS, + [Species.GOOMY]: Abilities.POISON_HEAL, + [Species.KLEFKI]: Abilities.TRIAGE, + [Species.PHANTUMP]: Abilities.UNNERVE, + [Species.PUMPKABOO]: Abilities.FLARE_BOOST, + [Species.BERGMITE]: Abilities.MIRROR_ARMOR, + [Species.NOIBAT]: Abilities.PUNK_ROCK, + [Species.XERNEAS]: Abilities.COMPETITIVE, + [Species.YVELTAL]: Abilities.DEFIANT, + [Species.ZYGARDE]: Abilities.REGENERATOR, + [Species.DIANCIE]: Abilities.QUEENLY_MAJESTY, + [Species.HOOPA]: Abilities.TRACE, + [Species.VOLCANION]: Abilities.FILTER, + [Species.ROWLET]: Abilities.SNIPER, + [Species.LITTEN]: Abilities.PRANKSTER, + [Species.POPPLIO]: Abilities.PUNK_ROCK, + [Species.PIKIPEK]: Abilities.ANGER_POINT, + [Species.YUNGOOS]: Abilities.HUGE_POWER, + [Species.GRUBBIN]: Abilities.GALVANIZE, + [Species.CRABRAWLER]: Abilities.REFRIGERATE, + [Species.ORICORIO]: Abilities.ADAPTABILITY, + [Species.CUTIEFLY]: Abilities.FRIEND_GUARD, + [Species.ROCKRUFF]: Abilities.ROCKY_PAYLOAD, + [Species.WISHIWASHI]: Abilities.PARENTAL_BOND, + [Species.MAREANIE]: Abilities.TOXIC_DEBRIS, + [Species.MUDBRAY]: Abilities.CUD_CHEW, + [Species.DEWPIDER]: Abilities.STRONG_JAW, + [Species.FOMANTIS]: Abilities.MIMICRY, + [Species.MORELULL]: Abilities.PERISH_BODY, + [Species.SALANDIT]: Abilities.DAZZLING, + [Species.STUFFUL]: Abilities.HOSPITALITY, + [Species.BOUNSWEET]: Abilities.RIPEN, + [Species.COMFEY]: Abilities.FRIEND_GUARD, + [Species.ORANGURU]: Abilities.HOSPITALITY, + [Species.PASSIMIAN]: Abilities.COSTAR, + [Species.WIMPOD]: Abilities.BATTLE_ARMOR, + [Species.SANDYGAST]: Abilities.DAUNTLESS_SHIELD, + [Species.PYUKUMUKU]: Abilities.IRON_BARBS, + [Species.TYPE_NULL]: Abilities.ADAPTABILITY, + [Species.MINIOR]: Abilities.ANGER_SHELL, + [Species.KOMALA]: Abilities.GUTS, + [Species.TURTONATOR]: Abilities.ANGER_SHELL, + [Species.TOGEDEMARU]: Abilities.STATIC, + [Species.MIMIKYU]: Abilities.MIMICRY, + [Species.BRUXISH]: Abilities.MULTISCALE, + [Species.DRAMPA]: Abilities.FLASH_FIRE, + [Species.DHELMISE]: Abilities.INFILTRATOR, + [Species.JANGMO_O]: Abilities.DANCER, + [Species.TAPU_KOKO]: Abilities.GALVANIZE, + [Species.TAPU_LELE]: Abilities.BERSERK, + [Species.TAPU_BULU]: Abilities.FLOWER_VEIL, + [Species.TAPU_FINI]: Abilities.FAIRY_AURA, + [Species.COSMOG]: Abilities.BEAST_BOOST, + [Species.NIHILEGO]: Abilities.POISON_PUPPETEER, + [Species.BUZZWOLE]: Abilities.MOXIE, + [Species.PHEROMOSA]: Abilities.MOXIE, + [Species.XURKITREE]: Abilities.LIGHTNING_ROD, + [Species.CELESTEELA]: Abilities.CHLOROPHYLL, + [Species.KARTANA]: Abilities.INTREPID_SWORD, + [Species.GUZZLORD]: Abilities.GLUTTONY, + [Species.NECROZMA]: Abilities.BEAST_BOOST, + [Species.MAGEARNA]: Abilities.STEELY_SPIRIT, + [Species.MARSHADOW]: Abilities.IRON_FIST, + [Species.POIPOLE]: Abilities.MERCILESS, + [Species.STAKATAKA]: Abilities.DAUNTLESS_SHIELD, + [Species.BLACEPHALON]: Abilities.REGENERATOR, + [Species.ZERAORA]: Abilities.MOTOR_DRIVE, + [Species.MELTAN]: Abilities.FULL_METAL_BODY, + [Species.GROOKEY]: Abilities.SOLID_ROCK, + [Species.SCORBUNNY]: Abilities.RECKLESS, + [Species.SOBBLE]: Abilities.MIMICRY, + [Species.SKWOVET]: Abilities.HONEY_GATHER, + [Species.ROOKIDEE]: Abilities.JUSTIFIED, + [Species.BLIPBUG]: Abilities.TINTED_LENS, + [Species.NICKIT]: Abilities.INTIMIDATE, + [Species.GOSSIFLEUR]: Abilities.STORM_DRAIN, + [Species.WOOLOO]: Abilities.ROCK_HEAD, + [Species.CHEWTLE]: Abilities.ROCK_HEAD, + [Species.YAMPER]: Abilities.SPEED_BOOST, + [Species.ROLYCOLY]: Abilities.EARTH_EATER, + [Species.APPLIN]: Abilities.DRAGONS_MAW, + [Species.SILICOBRA]: Abilities.SAND_RUSH, + [Species.CRAMORANT]: Abilities.STORM_DRAIN, + [Species.ARROKUDA]: Abilities.STRONG_JAW, + [Species.TOXEL]: Abilities.GALVANIZE, + [Species.SIZZLIPEDE]: Abilities.DEFIANT, + [Species.CLOBBOPUS]: Abilities.SWIFT_SWIM, + [Species.SINISTEA]: Abilities.WATER_ABSORB, + [Species.HATENNA]: Abilities.MAGIC_GUARD, + [Species.IMPIDIMP]: Abilities.TANGLING_HAIR, + [Species.MILCERY]: Abilities.WELL_BAKED_BODY, + [Species.FALINKS]: Abilities.MOXIE, + [Species.PINCURCHIN]: Abilities.IRON_BARBS, + [Species.SNOM]: Abilities.SNOW_WARNING, + [Species.STONJOURNER]: Abilities.SOLID_ROCK, + [Species.EISCUE]: Abilities.SLUSH_RUSH, + [Species.INDEEDEE]: Abilities.MAGIC_BOUNCE, + [Species.MORPEKO]: Abilities.GLUTTONY, + [Species.CUFANT]: Abilities.HEATPROOF, + [Species.DRACOZOLT]: Abilities.SLUSH_RUSH, + [Species.ARCTOZOLT]: Abilities.SAND_RUSH, + [Species.DRACOVISH]: Abilities.HUSTLE, + [Species.ARCTOVISH]: Abilities.STRONG_JAW, + [Species.DURALUDON]: Abilities.MEGA_LAUNCHER, + [Species.DREEPY]: Abilities.PARENTAL_BOND, + [Species.ZACIAN]: Abilities.SHARPNESS, + [Species.ZAMAZENTA]: Abilities.GUARD_DOG, + [Species.ETERNATUS]: Abilities.SUPREME_OVERLORD, + [Species.KUBFU]: Abilities.IRON_FIST, + [Species.ZARUDE]: Abilities.PRANKSTER, + [Species.REGIELEKI]: Abilities.LEVITATE, + [Species.REGIDRAGO]: Abilities.INTIMIDATE, + [Species.GLASTRIER]: Abilities.FILTER, + [Species.SPECTRIER]: Abilities.PERISH_BODY, + [Species.CALYREX]: Abilities.HARVEST, + [Species.ENAMORUS]: Abilities.MISTY_SURGE, + [Species.SPRIGATITO]: Abilities.MAGICIAN, + [Species.FUECOCO]: Abilities.EARTH_EATER, + [Species.QUAXLY]: Abilities.DANCER, + [Species.LECHONK]: Abilities.SIMPLE, + [Species.TAROUNTULA]: Abilities.PICKUP, + [Species.NYMBLE]: Abilities.TECHNICIAN, + [Species.PAWMI]: Abilities.FLUFFY, + [Species.TANDEMAUS]: Abilities.PARENTAL_BOND, + [Species.FIDOUGH]: Abilities.WATER_ABSORB, + [Species.SMOLIV]: Abilities.RIPEN, + [Species.SQUAWKABILLY]: Abilities.GALE_WINGS, + [Species.NACLI]: Abilities.EARTH_EATER, + [Species.CHARCADET]: Abilities.CONTRARY, + [Species.TADBULB]: Abilities.TRANSISTOR, + [Species.WATTREL]: Abilities.GALE_WINGS, + [Species.MASCHIFF]: Abilities.STRONG_JAW, + [Species.SHROODLE]: Abilities.CORROSION, + [Species.BRAMBLIN]: Abilities.WANDERING_SPIRIT, + [Species.TOEDSCOOL]: Abilities.PRANKSTER, + [Species.KLAWF]: Abilities.WATER_ABSORB, + [Species.CAPSAKID]: Abilities.PARENTAL_BOND, + [Species.RELLOR]: Abilities.MAGIC_GUARD, + [Species.FLITTLE]: Abilities.COMPETITIVE, + [Species.TINKATINK]: Abilities.HUGE_POWER, + [Species.WIGLETT]: Abilities.STORM_DRAIN, + [Species.BOMBIRDIER]: Abilities.UNAWARE, + [Species.FINIZEN]: Abilities.LIQUID_VOICE, + [Species.VAROOM]: Abilities.SPEED_BOOST, + [Species.CYCLIZAR]: Abilities.PROTEAN, + [Species.ORTHWORM]: Abilities.HEATPROOF, + [Species.GLIMMET]: Abilities.SYMBIOSIS, + [Species.GREAVARD]: Abilities.FUR_COAT, + [Species.FLAMIGO]: Abilities.MOXIE, + [Species.CETODDLE]: Abilities.GLUTTONY, + [Species.VELUZA]: Abilities.SIMPLE, + [Species.DONDOZO]: Abilities.GLUTTONY, + [Species.TATSUGIRI]: Abilities.WATER_BUBBLE, + [Species.GREAT_TUSK]: Abilities.INTIMIDATE, + [Species.SCREAM_TAIL]: Abilities.PIXILATE, + [Species.BRUTE_BONNET]: Abilities.ADAPTABILITY, + [Species.FLUTTER_MANE]: Abilities.DAZZLING, + [Species.SLITHER_WING]: Abilities.SCRAPPY, + [Species.SANDY_SHOCKS]: Abilities.EARTH_EATER, + [Species.IRON_TREADS]: Abilities.STEAM_ENGINE, + [Species.IRON_BUNDLE]: Abilities.SNOW_WARNING, + [Species.IRON_HANDS]: Abilities.IRON_FIST, + [Species.IRON_JUGULIS]: Abilities.NO_GUARD, + [Species.IRON_MOTH]: Abilities.TINTED_LENS, + [Species.IRON_THORNS]: Abilities.SAND_STREAM, + [Species.FRIGIBAX]: Abilities.THICK_FAT, + [Species.GIMMIGHOUL]: Abilities.SUPER_LUCK, + [Species.WO_CHIEN]: Abilities.TRIAGE, + [Species.CHIEN_PAO]: Abilities.REFRIGERATE, + [Species.TING_LU]: Abilities.STAMINA, + [Species.CHI_YU]: Abilities.BLAZE, + [Species.ROARING_MOON]: Abilities.AERILATE, + [Species.IRON_VALIANT]: Abilities.DOWNLOAD, + [Species.KORAIDON]: Abilities.PROTOSYNTHESIS, + [Species.MIRAIDON]: Abilities.QUARK_DRIVE, + [Species.WALKING_WAKE]: Abilities.BEAST_BOOST, + [Species.IRON_LEAVES]: Abilities.SHARPNESS, + [Species.POLTCHAGEIST]: Abilities.FLAME_BODY, + [Species.OKIDOGI]: Abilities.STICKY_HOLD, + [Species.MUNKIDORI]: Abilities.PRANKSTER, + [Species.FEZANDIPITI]: Abilities.DAZZLING, + [Species.OGERPON]: Abilities.DISGUISE, + [Species.GOUGING_FIRE]: Abilities.BEAST_BOOST, + [Species.RAGING_BOLT]: Abilities.BEAST_BOOST, + [Species.IRON_BOULDER]: Abilities.SHARPNESS, + [Species.IRON_CROWN]: Abilities.SHARPNESS, + [Species.TERAPAGOS]: Abilities.PROTEAN, + [Species.PECHARUNT]: Abilities.CORROSION, + [Species.ALOLA_RATTATA]: Abilities.CHEEK_POUCH, + [Species.ALOLA_SANDSHREW]: Abilities.ICE_BODY, + [Species.ALOLA_VULPIX]: Abilities.ICE_BODY, + [Species.ALOLA_DIGLETT]: Abilities.CUTE_CHARM, + [Species.ALOLA_MEOWTH]: Abilities.UNNERVE, + [Species.ALOLA_GEODUDE]: Abilities.ELECTROMORPHOSIS, + [Species.ALOLA_GRIMER]: Abilities.MERCILESS, + [Species.ETERNAL_FLOETTE]: Abilities.MAGIC_GUARD, + [Species.GALAR_MEOWTH]: Abilities.SUPER_LUCK, + [Species.GALAR_PONYTA]: Abilities.MAGIC_GUARD, + [Species.GALAR_SLOWPOKE]: Abilities.POISON_TOUCH, + [Species.GALAR_FARFETCHD]: Abilities.SUPER_LUCK, + [Species.GALAR_ARTICUNO]: Abilities.SERENE_GRACE, + [Species.GALAR_ZAPDOS]: Abilities.TOUGH_CLAWS, + [Species.GALAR_MOLTRES]: Abilities.REGENERATOR, + [Species.GALAR_CORSOLA]: Abilities.SHADOW_TAG, + [Species.GALAR_ZIGZAGOON]: Abilities.PICKPOCKET, + [Species.GALAR_DARUMAKA]: Abilities.FLASH_FIRE, + [Species.GALAR_YAMASK]: Abilities.SOLID_ROCK, + [Species.GALAR_STUNFISK]: Abilities.IRON_BARBS, + [Species.HISUI_GROWLITHE]: Abilities.STRONG_JAW, + [Species.HISUI_VOLTORB]: Abilities.HADRON_ENGINE, + [Species.HISUI_QWILFISH]: Abilities.MERCILESS, + [Species.HISUI_SNEASEL]: Abilities.SCRAPPY, + [Species.HISUI_ZORUA]: Abilities.DARK_AURA, + [Species.PALDEA_TAUROS]: Abilities.RATTLED, + [Species.PALDEA_WOOPER]: Abilities.THICK_FAT, + [Species.BLOODMOON_URSALUNA]: Abilities.BERSERK +}; + // TODO: Remove { //setTimeout(() => { diff --git a/src/data/weather.ts b/src/data/weather.ts index a198990fd61..cf3cf3434ea 100644 --- a/src/data/weather.ts +++ b/src/data/weather.ts @@ -106,7 +106,9 @@ export class Weather { const field = scene.getField(true); for (let pokemon of field) { - const suppressWeatherEffectAbAttr = pokemon.getAbility().getAttrs(SuppressWeatherEffectAbAttr).find(() => true) as SuppressWeatherEffectAbAttr; + let suppressWeatherEffectAbAttr = pokemon.canApplyAbility(false) ? pokemon.getAbility().getAttrs(SuppressWeatherEffectAbAttr).find(() => true) as SuppressWeatherEffectAbAttr : null; + if (!suppressWeatherEffectAbAttr) + suppressWeatherEffectAbAttr = pokemon.canApplyAbility(true) ? pokemon.getPassiveAbility().getAttrs(SuppressWeatherEffectAbAttr).find(() => true) as SuppressWeatherEffectAbAttr : null; if (suppressWeatherEffectAbAttr && (!this.isImmutable() || suppressWeatherEffectAbAttr.affectsImmutable)) return true; } diff --git a/src/field/pokemon.ts b/src/field/pokemon.ts index e5b7f75186b..d8f1ed934e0 100644 --- a/src/field/pokemon.ts +++ b/src/field/pokemon.ts @@ -3,7 +3,7 @@ import BattleScene, { ABILITY_OVERRIDE, AnySound, MOVE_OVERRIDE, OPP_ABILITY_OVE import BattleInfo, { PlayerBattleInfo, EnemyBattleInfo } from '../ui/battle-info'; import { Moves } from "../data/enums/moves"; import Move, { HighCritAttr, HitsTagAttr, applyMoveAttrs, FixedDamageAttr, VariableAtkAttr, VariablePowerAttr, allMoves, MoveCategory, TypelessAttr, CritOnlyAttr, getMoveTargets, OneHitKOAttr, MultiHitAttr, StatusMoveTypeImmunityAttr, MoveTarget, VariableDefAttr, AttackMove, ModifiedDamageAttr, VariableMoveTypeMultiplierAttr, IgnoreOpponentStatChangesAttr, SacrificialAttr, VariableMoveTypeAttr, VariableMoveCategoryAttr } from "../data/move"; -import { default as PokemonSpecies, PokemonSpeciesForm, SpeciesFormKey, getFusedSpeciesName, getPokemonSpecies, getPokemonSpeciesForm } from '../data/pokemon-species'; +import { default as PokemonSpecies, PokemonSpeciesForm, SpeciesFormKey, getFusedSpeciesName, getPokemonSpecies, getPokemonSpeciesForm, starterPassiveAbilities } from '../data/pokemon-species'; import * as Utils from '../utils'; import { Type, TypeDamageMultiplier, getTypeDamageMultiplier, getTypeRgb } from '../data/type'; import { getLevelTotalExp } from '../data/exp'; @@ -25,7 +25,8 @@ import { TempBattleStat } from '../data/temp-battle-stat'; import { ArenaTagSide, WeakenMoveScreenTag, WeakenMoveTypeTag } from '../data/arena-tag'; import { ArenaTagType } from "../data/enums/arena-tag-type"; import { Biome } from "../data/enums/biome"; -import { Abilities, Ability, BattleStatMultiplierAbAttr, BlockCritAbAttr, BypassBurnDamageReductionAbAttr, FieldVariableMovePowerAbAttr, IgnoreOpponentStatChangesAbAttr, MoveImmunityAbAttr, NonSuperEffectiveImmunityAbAttr, PreApplyBattlerTagAbAttr, PreDefendFullHpEndureAbAttr, ReceivedMoveDamageMultiplierAbAttr, ReduceStatusEffectDurationAbAttr, StabBoostAbAttr, StatusEffectImmunityAbAttr, TypeImmunityAbAttr, VariableMovePowerAbAttr, VariableMoveTypeAbAttr, WeightMultiplierAbAttr, allAbilities, applyAbAttrs, applyBattleStatMultiplierAbAttrs, applyPostDefendAbAttrs, applyPreApplyBattlerTagAbAttrs, applyPreAttackAbAttrs, applyPreDefendAbAttrs, applyPreSetStatusAbAttrs } from '../data/ability'; +import { Ability, BattleStatMultiplierAbAttr, BlockCritAbAttr, BypassBurnDamageReductionAbAttr, FieldVariableMovePowerAbAttr, IgnoreOpponentStatChangesAbAttr, MoveImmunityAbAttr, NonSuperEffectiveImmunityAbAttr, PreApplyBattlerTagAbAttr, PreDefendFullHpEndureAbAttr, ReceivedMoveDamageMultiplierAbAttr, ReduceStatusEffectDurationAbAttr, StabBoostAbAttr, StatusEffectImmunityAbAttr, TypeImmunityAbAttr, VariableMovePowerAbAttr, VariableMoveTypeAbAttr, WeightMultiplierAbAttr, allAbilities, applyAbAttrs, applyBattleStatMultiplierAbAttrs, applyPostDefendAbAttrs, applyPreApplyBattlerTagAbAttrs, applyPreAttackAbAttrs, applyPreDefendAbAttrs, applyPreSetStatusAbAttrs } from '../data/ability'; +import { Abilities } from "#app/data/enums/abilities"; import PokemonData from '../system/pokemon-data'; import { BattlerIndex } from '../battle'; import { BattleSpec } from "../enums/battle-spec"; @@ -556,7 +557,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { let value = Math.floor(((2 * baseStat + this.ivs[s]) * this.level) * 0.01); if (isHp) { value = value + this.level + 10; - if (this.getAbility().hasAttr(NonSuperEffectiveImmunityAbAttr)) + if ((this.canApplyAbility() && this.getAbility().hasAttr(NonSuperEffectiveImmunityAbAttr)) || (this.canApplyAbility(true) && this.getPassiveAbility().hasAttr(NonSuperEffectiveImmunityAbAttr))) value = 1; if (this.hp > value || this.hp === undefined) this.hp = value; @@ -716,11 +717,20 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { return allAbilities[abilityId]; } - canApplyAbility(): boolean { - const ability = this.getAbility(); + getPassiveAbility(): Ability { + let starterSpeciesId = this.species.speciesId; + while (pokemonPrevolutions.hasOwnProperty(starterSpeciesId)) + starterSpeciesId = pokemonPrevolutions[starterSpeciesId]; + return allAbilities[starterPassiveAbilities[starterSpeciesId]]; + } + + canApplyAbility(passive: boolean = false): boolean { + if (passive && !this.isBoss()) + return false; + const ability = (!passive ? this.getAbility() : this.getPassiveAbility()); if (ability.isIgnorable && this.scene.arena.ignoreAbilities) return false; - return (this.hp || ability.isPassive) && !this.getAbility().conditions.find(condition => !condition(this)); + return (this.hp || ability.isBypassFaint) && !ability.conditions.find(condition => !condition(this)); } getWeight(): number { diff --git a/src/phases.ts b/src/phases.ts index 8c983317239..26a0651d647 100644 --- a/src/phases.ts +++ b/src/phases.ts @@ -30,7 +30,8 @@ import { Weather, WeatherType, getRandomWeatherType, getTerrainBlockMessage, get import { TempBattleStat } from "./data/temp-battle-stat"; import { ArenaTagSide, ArenaTrapTag, MistTag, TrickRoomTag } from "./data/arena-tag"; import { ArenaTagType } from "./data/enums/arena-tag-type"; -import { Abilities, CheckTrappedAbAttr, MoveAbilityBypassAbAttr, IgnoreOpponentStatChangesAbAttr, PostAttackAbAttr, PostBattleAbAttr, PostDefendAbAttr, PostSummonAbAttr, PostTurnAbAttr, PostWeatherLapseAbAttr, PreSwitchOutAbAttr, PreWeatherDamageAbAttr, ProtectStatAbAttr, RedirectMoveAbAttr, RunSuccessAbAttr, StatChangeMultiplierAbAttr, SuppressWeatherEffectAbAttr, SyncEncounterNatureAbAttr, applyAbAttrs, applyCheckTrappedAbAttrs, applyPostAttackAbAttrs, applyPostBattleAbAttrs, applyPostDefendAbAttrs, applyPostSummonAbAttrs, applyPostTurnAbAttrs, applyPostWeatherLapseAbAttrs, applyPreStatChangeAbAttrs, applyPreSwitchOutAbAttrs, applyPreWeatherEffectAbAttrs, BattleStatMultiplierAbAttr, applyBattleStatMultiplierAbAttrs, IncrementMovePriorityAbAttr, applyPostVictoryAbAttrs, PostVictoryAbAttr, applyPostBattleInitAbAttrs, PostBattleInitAbAttr, BlockNonDirectDamageAbAttr as BlockNonDirectDamageAbAttr, applyPostKnockOutAbAttrs, PostKnockOutAbAttr, PostBiomeChangeAbAttr, applyPostFaintAbAttrs, PostFaintAbAttr } from "./data/ability"; +import { CheckTrappedAbAttr, MoveAbilityBypassAbAttr, IgnoreOpponentStatChangesAbAttr, PostAttackAbAttr, PostBattleAbAttr, PostDefendAbAttr, PostSummonAbAttr, PostTurnAbAttr, PostWeatherLapseAbAttr, PreSwitchOutAbAttr, PreWeatherDamageAbAttr, ProtectStatAbAttr, RedirectMoveAbAttr, RunSuccessAbAttr, StatChangeMultiplierAbAttr, SuppressWeatherEffectAbAttr, SyncEncounterNatureAbAttr, applyAbAttrs, applyCheckTrappedAbAttrs, applyPostAttackAbAttrs, applyPostBattleAbAttrs, applyPostDefendAbAttrs, applyPostSummonAbAttrs, applyPostTurnAbAttrs, applyPostWeatherLapseAbAttrs, applyPreStatChangeAbAttrs, applyPreSwitchOutAbAttrs, applyPreWeatherEffectAbAttrs, BattleStatMultiplierAbAttr, applyBattleStatMultiplierAbAttrs, IncrementMovePriorityAbAttr, applyPostVictoryAbAttrs, PostVictoryAbAttr, applyPostBattleInitAbAttrs, PostBattleInitAbAttr, BlockNonDirectDamageAbAttr as BlockNonDirectDamageAbAttr, applyPostKnockOutAbAttrs, PostKnockOutAbAttr, PostBiomeChangeAbAttr, applyPostFaintAbAttrs, PostFaintAbAttr, IncreasePpAbAttr } from "./data/ability"; +import { Abilities } from "./data/enums/abilities"; import { Unlockables, getUnlockableName } from "./system/unlockables"; import { getBiomeKey } from "./field/arena"; import { BattleType, BattlerIndex, TurnCommand } from "./battle"; @@ -1207,7 +1208,7 @@ export class SummonPhase extends PartyMemberPokemonPhase { pokemon.resetTurnData(); - if (!this.loaded) { + if (!this.loaded || this.scene.currentBattle.battleType === BattleType.TRAINER || (this.scene.currentBattle.waveIndex % 10) === 1) { this.scene.triggerPokemonFormChange(pokemon, SpeciesFormChangeActiveTrigger, true); this.queuePostSummon(); @@ -2131,7 +2132,7 @@ export class MovePhase extends BattlePhase { for (let opponent of targetedOpponents) { if (this.move.ppUsed === this.move.getMove().pp) break; - if (opponent.getAbility().id === Abilities.PRESSURE) + if ((opponent.canApplyAbility() && opponent.getAbility().hasAttr(IncreasePpAbAttr)) || (opponent.canApplyAbility(true) && opponent.getPassiveAbility().hasAttr(IncreasePpAbAttr))) this.move.ppUsed = Math.min(this.move.ppUsed + 1, this.move.getMovePp()); } } @@ -2502,14 +2503,18 @@ export class MoveAnimTestPhase extends BattlePhase { } export class ShowAbilityPhase extends PokemonPhase { - constructor(scene: BattleScene, battlerIndex: BattlerIndex) { + private passive: boolean; + + constructor(scene: BattleScene, battlerIndex: BattlerIndex, passive: boolean = false) { super(scene, battlerIndex); + + this.passive = passive; } start() { super.start(); - this.scene.abilityBar.showAbility(this.getPokemon()); + this.scene.abilityBar.showAbility(this.getPokemon(), this.passive); this.end(); } @@ -2904,11 +2909,9 @@ export class FaintPhase extends PokemonPhase { this.scene.queueMessage(getPokemonMessage(pokemon, ' fainted!'), null, true); - if (pokemon.getAbility().hasAttr(PostFaintAbAttr)) { - if (pokemon.turnData?.attacksReceived?.length) { - const lastAttack = pokemon.turnData.attacksReceived[0]; - applyPostFaintAbAttrs(PostFaintAbAttr,pokemon, this.scene.getPokemonById(lastAttack.sourceId), new PokemonMove(lastAttack.move), lastAttack.result); - } + if (pokemon.turnData?.attacksReceived?.length) { + const lastAttack = pokemon.turnData.attacksReceived[0]; + applyPostFaintAbAttrs(PostFaintAbAttr, pokemon, this.scene.getPokemonById(lastAttack.sourceId), new PokemonMove(lastAttack.move), lastAttack.result); } const alivePlayField = this.scene.getField(true); diff --git a/src/ui/ability-bar.ts b/src/ui/ability-bar.ts index 1985844e919..155123b8553 100644 --- a/src/ui/ability-bar.ts +++ b/src/ui/ability-bar.ts @@ -38,9 +38,9 @@ export default class AbilityBar extends Phaser.GameObjects.Container { this.shown = false; } - showAbility(pokemon: Pokemon): void { - this.pokemonNameText.setText(`${pokemon.name}'s`); - this.abilityNameText.setText(pokemon.getAbility().name); + showAbility(pokemon: Pokemon, passive: boolean = false): void { + this.pokemonNameText.setText(`${pokemon.name}'s${passive ? ' Passive' : ''}`); + this.abilityNameText.setText((!passive ? pokemon.getAbility() : pokemon.getPassiveAbility()).name); if (this.shown) return; From fbb901e591cc9a35443e8f81141dbaa5fb13ac55 Mon Sep 17 00:00:00 2001 From: Flashfyre Date: Thu, 11 Apr 2024 09:30:40 -0400 Subject: [PATCH 09/10] Temporarily disable passive abilities --- src/field/pokemon.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/field/pokemon.ts b/src/field/pokemon.ts index d8f1ed934e0..8b18edeabf9 100644 --- a/src/field/pokemon.ts +++ b/src/field/pokemon.ts @@ -725,7 +725,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { } canApplyAbility(passive: boolean = false): boolean { - if (passive && !this.isBoss()) + if (passive) return false; const ability = (!passive ? this.getAbility() : this.getPassiveAbility()); if (ability.isIgnorable && this.scene.arena.ignoreAbilities) From 43bf8e13eaeb2dd59ae70b30b07b187b256355b6 Mon Sep 17 00:00:00 2001 From: Flashfyre Date: Thu, 11 Apr 2024 09:39:15 -0400 Subject: [PATCH 10/10] Fix stack overflow with weather abilities --- src/data/battler-tags.ts | 2 +- src/data/move.ts | 8 ++++---- src/data/weather.ts | 4 ++-- src/field/pokemon.ts | 6 +++++- 4 files changed, 12 insertions(+), 8 deletions(-) diff --git a/src/data/battler-tags.ts b/src/data/battler-tags.ts index 25567b83c27..1244d8697e6 100644 --- a/src/data/battler-tags.ts +++ b/src/data/battler-tags.ts @@ -827,7 +827,7 @@ export class SlowStartTag extends AbilityBattlerTag { } lapse(pokemon: Pokemon, lapseType: BattlerTagLapseType): boolean { - if (pokemon.getAbility().id !== this.ability && (pokemon.canApplyAbility(true) && pokemon.getPassiveAbility().id !== this.ability)) + if ((!pokemon.canApplyAbility() || pokemon.getAbility().id !== this.ability) && (!pokemon.canApplyAbility(true) || pokemon.getPassiveAbility().id !== this.ability)) this.turnCount = 1; return super.lapse(pokemon, lapseType); diff --git a/src/data/move.ts b/src/data/move.ts index 2ea99430211..2ba34d488fd 100644 --- a/src/data/move.ts +++ b/src/data/move.ts @@ -4505,9 +4505,9 @@ export function initMoves() { .attr(StatChangeAttr, [ BattleStat.SPATK, BattleStat.SPDEF, BattleStat.SPD ], 2, true) .ignoresVirtual(), new StatusMove(Moves.MAGNETIC_FLUX, "Magnetic Flux", Type.ELECTRIC, -1, 20, "The user manipulates magnetic fields, which raises the Defense and Sp. Def stats of ally Pokémon with the Plus or Minus Ability.", -1, 0, 6) - .attr(StatChangeAttr, [ BattleStat.DEF, BattleStat.SPDEF ], 1, false, (user, target, move) => !![ Abilities.PLUS, Abilities.MINUS].find(a => a === user.getAbility().id || (user.canApplyAbility(true) && a === user.getPassiveAbility().id))) + .attr(StatChangeAttr, [ BattleStat.DEF, BattleStat.SPDEF ], 1, false, (user, target, move) => !![ Abilities.PLUS, Abilities.MINUS].find(a => a === user.getAbility().id || (user.canApplyPassive() && a === user.getPassiveAbility().id))) .target(MoveTarget.USER_AND_ALLIES) - .condition((user, target, move) => !![ user, user.getAlly() ].filter(p => p?.isActive()).find(p => !![ Abilities.PLUS, Abilities.MINUS].find(a => a === p.getAbility().id || (user.canApplyAbility(true) && a === user.getPassiveAbility().id)))), + .condition((user, target, move) => !![ user, user.getAlly() ].filter(p => p?.isActive()).find(p => !![ Abilities.PLUS, Abilities.MINUS].find(a => a === p.getAbility().id || (user.canApplyPassive() && a === user.getPassiveAbility().id)))), new StatusMove(Moves.HAPPY_HOUR, "Happy Hour (N)", Type.NORMAL, -1, 30, "Using Happy Hour doubles the amount of prize money received after battle.", -1, 0, 6) // No animation .target(MoveTarget.USER_SIDE), new StatusMove(Moves.ELECTRIC_TERRAIN, "Electric Terrain", Type.ELECTRIC, -1, 10, "The user electrifies the ground for five turns, powering up Electric-type moves. Pokémon on the ground no longer fall asleep.", -1, 0, 6) @@ -4632,9 +4632,9 @@ export function initMoves() { .attr(StatChangeAttr, BattleStat.SPD, -1), new SelfStatusMove(Moves.LASER_FOCUS, "Laser Focus (N)", Type.NORMAL, -1, 30, "The user concentrates intensely. The attack on the next turn always results in a critical hit.", -1, 0, 7), new StatusMove(Moves.GEAR_UP, "Gear Up", Type.STEEL, -1, 20, "The user engages its gears to raise the Attack and Sp. Atk stats of ally Pokémon with the Plus or Minus Ability.", -1, 0, 7) - .attr(StatChangeAttr, [ BattleStat.ATK, BattleStat.SPATK ], 1, false, (user, target, move) => [ Abilities.PLUS, Abilities.MINUS ].includes(target.getAbility().id) || (target.canApplyAbility(true) && [ Abilities.PLUS, Abilities.MINUS ].includes(target.getPassiveAbility().id))) + .attr(StatChangeAttr, [ BattleStat.ATK, BattleStat.SPATK ], 1, false, (user, target, move) => [ Abilities.PLUS, Abilities.MINUS ].includes(target.getAbility().id) || (target.canApplyPassive() && [ Abilities.PLUS, Abilities.MINUS ].includes(target.getPassiveAbility().id))) .target(MoveTarget.USER_AND_ALLIES) - .condition((user, target, move) => !![ user, user.getAlly() ].find(p => p && [ Abilities.PLUS, Abilities.MINUS ].includes(p.getAbility().id) || (target.canApplyAbility(true) && [ Abilities.PLUS, Abilities.MINUS ].includes(target.getPassiveAbility().id)))), + .condition((user, target, move) => !![ user, user.getAlly() ].find(p => p && [ Abilities.PLUS, Abilities.MINUS ].includes(p.getAbility().id) || (target.canApplyPassive() && [ Abilities.PLUS, Abilities.MINUS ].includes(target.getPassiveAbility().id)))), new AttackMove(Moves.THROAT_CHOP, "Throat Chop (P)", Type.DARK, MoveCategory.PHYSICAL, 80, 100, 15, "The user attacks the target's throat, and the resultant suffering prevents the target from using moves that emit sound for two turns.", 100, 0, 7), new AttackMove(Moves.POLLEN_PUFF, "Pollen Puff (P)", Type.BUG, MoveCategory.SPECIAL, 90, 100, 15, "The user attacks the enemy with a pollen puff that explodes. If the target is an ally, it gives the ally a pollen puff that restores its HP instead.", -1, 0, 7) .ballBombMove(), diff --git a/src/data/weather.ts b/src/data/weather.ts index cf3cf3434ea..b3a59f34b98 100644 --- a/src/data/weather.ts +++ b/src/data/weather.ts @@ -106,9 +106,9 @@ export class Weather { const field = scene.getField(true); for (let pokemon of field) { - let suppressWeatherEffectAbAttr = pokemon.canApplyAbility(false) ? pokemon.getAbility().getAttrs(SuppressWeatherEffectAbAttr).find(() => true) as SuppressWeatherEffectAbAttr : null; + let suppressWeatherEffectAbAttr = pokemon.getAbility().getAttrs(SuppressWeatherEffectAbAttr).find(() => true) as SuppressWeatherEffectAbAttr; if (!suppressWeatherEffectAbAttr) - suppressWeatherEffectAbAttr = pokemon.canApplyAbility(true) ? pokemon.getPassiveAbility().getAttrs(SuppressWeatherEffectAbAttr).find(() => true) as SuppressWeatherEffectAbAttr : null; + suppressWeatherEffectAbAttr = pokemon.canApplyPassive() ? pokemon.getPassiveAbility().getAttrs(SuppressWeatherEffectAbAttr).find(() => true) as SuppressWeatherEffectAbAttr : null; if (suppressWeatherEffectAbAttr && (!this.isImmutable() || suppressWeatherEffectAbAttr.affectsImmutable)) return true; } diff --git a/src/field/pokemon.ts b/src/field/pokemon.ts index 8b18edeabf9..1cc4378ead5 100644 --- a/src/field/pokemon.ts +++ b/src/field/pokemon.ts @@ -724,8 +724,12 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { return allAbilities[starterPassiveAbilities[starterSpeciesId]]; } + canApplyPassive(): boolean { + return this.isBoss(); + } + canApplyAbility(passive: boolean = false): boolean { - if (passive) + if (passive && !this.canApplyPassive()) return false; const ability = (!passive ? this.getAbility() : this.getPassiveAbility()); if (ability.isIgnorable && this.scene.arena.ignoreAbilities)