diff --git a/data/palettes_gbc.lua b/data/palettes_gbc.lua new file mode 100644 index 00000000..452c4c48 --- /dev/null +++ b/data/palettes_gbc.lua @@ -0,0 +1,1837 @@ +-- Generated by tools/build_data.py. DO NOT EDIT. +-- Red++ / pokered-gbc SuperPalettes (COLORS=RED++): 4 8-bit RGB +-- colors per palette (color 0 first), including per-species +-- pals and the GEN_2 MonsterPalettes assignment. +return { + order = { + "TOWNMAP2", + "SLOTS5", + "VIRIDIAN", + "PEWTER", + "CERULEAN", + "LAVENDER", + "VERMILION", + "CELADON", + "FUCHSIA", + "CINNABAR", + "INDIGO", + "SAFFRON", + "TOWNMAP", + "LOGO1", + "LOGO2", + "EXP", + "MEWMON", + "BLUEMON", + "REDMON", + "CYANMON", + "PURPLEMON", + "BROWNMON", + "GREENMON", + "PINKMON", + "YELLOWMON", + "GREYMON", + "SLOTS1", + "SLOTS2", + "SLOTS3", + "SLOTS4", + "BLACK", + "GREENBAR", + "YELLOWBAR", + "REDBAR", + "BADGE", + "CAVE", + "GAMEFREAK", + "BULBASAUR", + "IVYSAUR", + "VENUSAUR", + "CHARMANDER", + "CHARMELEON", + "CHARIZARD", + "SQUIRTLE", + "WARTORTLE", + "BLASTOISE", + "CATERPIE", + "METAPOD", + "BUTTERFREE", + "WEEDLE", + "KAKUNA", + "BEEDRILL", + "PIDGEY", + "PIDGEOTTO", + "PIDGEOT", + "RATTATA", + "RATICATE", + "SPEAROW", + "FEAROW", + "EKANS", + "ARBOK", + "PIKACHU", + "RAICHU", + "SANDSHREW", + "SANDSLASH", + "NIDORAN_F", + "NIDORINA", + "NIDOQUEEN", + "NIDORAN_M", + "NIDORINO", + "NIDOKING", + "CLEFAIRY", + "CLEFABLE", + "VULPIX", + "NINETALES", + "JIGGLYPUFF", + "WIGGLYTUFF", + "ZUBAT", + "GOLBAT", + "ODDISH", + "GLOOM", + "VILEPLUME", + "PARAS", + "PARASECT", + "VENONAT", + "VENOMOTH", + "DIGLETT", + "DUGTRIO", + "MEOWTH", + "PERSIAN", + "PSYDUCK", + "GOLDUCK", + "MANKEY", + "PRIMEAPE", + "GROWLITHE", + "ARCANINE", + "POLIWAG", + "POLIWHIRL", + "POLIWRATH", + "ABRA", + "KADABRA", + "ALAKAZAM", + "MACHOP", + "MACHOKE", + "MACHAMP", + "BELLSPROUT", + "WEEPINBELL", + "VICTREEBEL", + "TENTACOOL", + "TENTACRUEL", + "GEODUDE", + "GRAVELER", + "GOLEM", + "PONYTA", + "RAPIDASH", + "SLOWPOKE", + "SLOWBRO", + "MAGNEMITE", + "MAGNETON", + "FARFETCH_D", + "DODUO", + "DODRIO", + "SEEL", + "DEWGONG", + "GRIMER", + "MUK", + "SHELLDER", + "CLOYSTER", + "GASTLY", + "HAUNTER", + "GENGAR", + "ONIX", + "DROWZEE", + "HYPNO", + "KRABBY", + "KINGLER", + "VOLTORB", + "ELECTRODE", + "EXEGGCUTE", + "EXEGGUTOR", + "CUBONE", + "MAROWAK", + "HITMONLEE", + "HITMONCHAN", + "LICKITUNG", + "KOFFING", + "WEEZING", + "RHYHORN", + "RHYDON", + "CHANSEY", + "TANGELA", + "KANGASKHAN", + "HORSEA", + "SEADRA", + "GOLDEEN", + "SEAKING", + "STARYU", + "STARMIE", + "MR_MIME", + "SCYTHER", + "JYNX", + "ELECTABUZZ", + "MAGMAR", + "PINSIR", + "TAUROS", + "MAGIKARP", + "GYARADOS", + "LAPRAS", + "DITTO", + "EEVEE", + "VAPOREON", + "JOLTEON", + "FLAREON", + "PORYGON", + "OMANYTE", + "OMASTAR", + "KABUTO", + "KABUTOPS", + "AERODACTYL", + "SNORLAX", + "ARTICUNO", + "ZAPDOS", + "MOLTRES", + "DRATINI", + "DRAGONAIR", + "DRAGONITE", + "MEWTWO", + "MEW", + "YOUNGSTER", + "BUGCATCHER", + "LASS", + "SAILOR", + "JR_TRAINER_M", + "JR_TRAINER_F", + "POKEMANIAC", + "SUPERNERD", + "HIKER", + "BIKER", + "BURGLAR", + "ENGINEER", + "JUGGLER", + "FISHERMAN", + "SWIMMER", + "CUEBALL", + "GAMBLER", + "BEAUTY", + "PSYCHIC", + "ROCKER", + "JUGGLER2", + "TAMER", + "BIRDKEEPER", + "BLACKBELT", + "GARY1", + "OAK", + "CHIEF", + "SCIENTIST", + "GIOVANNI", + "ROCKET", + "COOLTRAINER_M", + "COOLTRAINER_F", + "BRUNO", + "BROCK", + "MISTY", + "LT_SURGE", + "ERIKA", + "KOGA", + "BLAINE", + "SABRINA", + "GENTLEMAN", + "GARY2", + "GARY3", + "LORELEI", + "CHANNELER", + "AGATHA", + "LANCE", + "HERO", + "GRAYMON", + "ROUTE", + "PALLET", + }, + palettes = { + ABRA = { + { 255, 255, 255 }, + { 230, 156, 25 }, + { 99, 66, 82 }, + { 0, 0, 0 }, + }, + AERODACTYL = { + { 255, 255, 255 }, + { 173, 123, 148 }, + { 107, 90, 66 }, + { 0, 0, 0 }, + }, + AGATHA = { + { 255, 255, 255 }, + { 222, 181, 140 }, + { 132, 90, 165 }, + { 0, 0, 0 }, + }, + ALAKAZAM = { + { 255, 255, 255 }, + { 230, 156, 25 }, + { 99, 66, 82 }, + { 0, 0, 0 }, + }, + ARBOK = { + { 255, 255, 255 }, + { 148, 66, 156 }, + { 181, 33, 74 }, + { 0, 0, 0 }, + }, + ARCANINE = { + { 255, 255, 255 }, + { 255, 189, 58 }, + { 255, 74, 33 }, + { 0, 0, 0 }, + }, + ARTICUNO = { + { 255, 255, 255 }, + { 90, 173, 255 }, + { 66, 90, 132 }, + { 0, 0, 0 }, + }, + BADGE = { + { 255, 255, 255 }, + { 90, 123, 189 }, + { 33, 33, 165 }, + { 0, 0, 0 }, + }, + BEAUTY = { + { 255, 255, 255 }, + { 197, 140, 90 }, + { 66, 74, 140 }, + { 0, 0, 0 }, + }, + BEEDRILL = { + { 255, 255, 255 }, + { 255, 156, 33 }, + { 247, 33, 8 }, + { 0, 0, 0 }, + }, + BELLSPROUT = { + { 255, 255, 255 }, + { 165, 255, 58 }, + { 222, 82, 74 }, + { 0, 0, 0 }, + }, + BIKER = { + { 255, 255, 255 }, + { 165, 140, 74 }, + { 33, 25, 82 }, + { 0, 0, 0 }, + }, + BIRDKEEPER = { + { 255, 255, 255 }, + { 247, 181, 140 }, + { 49, 99, 214 }, + { 0, 0, 0 }, + }, + BLACK = { + { 255, 255, 255 }, + { 58, 58, 58 }, + { 16, 25, 25 }, + { 0, 0, 0 }, + }, + BLACKBELT = { + { 255, 255, 255 }, + { 214, 123, 66 }, + { 107, 82, 99 }, + { 0, 0, 0 }, + }, + BLAINE = { + { 255, 255, 255 }, + { 247, 165, 132 }, + { 58, 90, 99 }, + { 0, 0, 0 }, + }, + BLASTOISE = { + { 255, 255, 255 }, + { 197, 165, 25 }, + { 66, 90, 255 }, + { 0, 0, 0 }, + }, + BLUEMON = { + { 255, 255, 255 }, + { 132, 148, 255 }, + { 0, 8, 206 }, + { 0, 0, 0 }, + }, + BROCK = { + { 255, 255, 255 }, + { 247, 148, 115 }, + { 115, 58, 82 }, + { 0, 0, 0 }, + }, + BROWNMON = { + { 255, 255, 255 }, + { 239, 148, 82 }, + { 140, 74, 41 }, + { 0, 0, 0 }, + }, + BRUNO = { + { 255, 255, 255 }, + { 206, 140, 99 }, + { 66, 82, 99 }, + { 0, 0, 0 }, + }, + BUGCATCHER = { + { 255, 255, 255 }, + { 222, 140, 82 }, + { 49, 82, 148 }, + { 0, 0, 0 }, + }, + BULBASAUR = { + { 255, 255, 255 }, + { 99, 255, 90 }, + { 255, 82, 49 }, + { 0, 0, 0 }, + }, + BURGLAR = { + { 255, 255, 255 }, + { 230, 132, 74 }, + { 99, 33, 189 }, + { 0, 0, 0 }, + }, + BUTTERFREE = { + { 255, 255, 255 }, + { 148, 206, 255 }, + { 214, 41, 107 }, + { 0, 0, 0 }, + }, + CATERPIE = { + { 255, 255, 255 }, + { 99, 181, 49 }, + { 255, 74, 123 }, + { 0, 0, 0 }, + }, + CAVE = { + { 255, 255, 255 }, + { 189, 66, 0 }, + { 140, 115, 90 }, + { 0, 0, 0 }, + }, + CELADON = { + { 255, 255, 255 }, + { 41, 255, 41 }, + { 90, 189, 255 }, + { 0, 0, 0 }, + }, + CERULEAN = { + { 255, 255, 255 }, + { 41, 66, 255 }, + { 90, 189, 255 }, + { 0, 0, 0 }, + }, + CHANNELER = { + { 255, 255, 255 }, + { 247, 181, 140 }, + { 66, 66, 165 }, + { 0, 0, 0 }, + }, + CHANSEY = { + { 255, 255, 255 }, + { 230, 132, 173 }, + { 255, 74, 156 }, + { 0, 0, 0 }, + }, + CHARIZARD = { + { 255, 255, 255 }, + { 255, 90, 0 }, + { 49, 74, 123 }, + { 0, 0, 0 }, + }, + CHARMANDER = { + { 255, 255, 255 }, + { 255, 107, 33 }, + { 181, 41, 41 }, + { 0, 0, 0 }, + }, + CHARMELEON = { + { 255, 255, 255 }, + { 255, 115, 41 }, + { 189, 74, 82 }, + { 0, 0, 0 }, + }, + CHIEF = { + { 255, 255, 255 }, + { 197, 156, 90 }, + { 82, 107, 140 }, + { 0, 0, 0 }, + }, + CINNABAR = { + { 255, 255, 255 }, + { 255, 66, 66 }, + { 90, 189, 255 }, + { 0, 0, 0 }, + }, + CLEFABLE = { + { 255, 255, 255 }, + { 255, 115, 148 }, + { 107, 58, 0 }, + { 0, 0, 0 }, + }, + CLEFAIRY = { + { 255, 255, 255 }, + { 255, 115, 148 }, + { 107, 58, 0 }, + { 0, 0, 0 }, + }, + CLOYSTER = { + { 255, 255, 255 }, + { 173, 82, 181 }, + { 99, 33, 107 }, + { 0, 0, 0 }, + }, + COOLTRAINER_F = { + { 255, 255, 255 }, + { 214, 148, 123 }, + { 181, 74, 25 }, + { 0, 0, 0 }, + }, + COOLTRAINER_M = { + { 255, 255, 255 }, + { 214, 148, 123 }, + { 181, 74, 25 }, + { 0, 0, 0 }, + }, + CUBONE = { + { 255, 255, 255 }, + { 165, 156, 99 }, + { 132, 82, 33 }, + { 0, 0, 0 }, + }, + CUEBALL = { + { 255, 255, 255 }, + { 230, 181, 148 }, + { 74, 107, 148 }, + { 0, 0, 0 }, + }, + CYANMON = { + { 255, 255, 255 }, + { 99, 197, 181 }, + { 41, 107, 239 }, + { 0, 0, 0 }, + }, + DEWGONG = { + { 255, 255, 255 }, + { 156, 173, 255 }, + { 66, 90, 148 }, + { 0, 0, 0 }, + }, + DIGLETT = { + { 255, 255, 255 }, + { 156, 90, 33 }, + { 197, 49, 33 }, + { 0, 0, 0 }, + }, + DITTO = { + { 255, 255, 255 }, + { 189, 99, 230 }, + { 107, 58, 132 }, + { 0, 0, 0 }, + }, + DODRIO = { + { 255, 255, 255 }, + { 214, 132, 66 }, + { 148, 66, 49 }, + { 0, 0, 0 }, + }, + DODUO = { + { 255, 255, 255 }, + { 173, 107, 74 }, + { 99, 66, 49 }, + { 0, 0, 0 }, + }, + DRAGONAIR = { + { 255, 255, 255 }, + { 115, 156, 255 }, + { 41, 90, 255 }, + { 0, 0, 0 }, + }, + DRAGONITE = { + { 255, 255, 255 }, + { 197, 140, 33 }, + { 90, 82, 140 }, + { 0, 0, 0 }, + }, + DRATINI = { + { 255, 255, 255 }, + { 230, 214, 58 }, + { 41, 90, 197 }, + { 0, 0, 0 }, + }, + DROWZEE = { + { 255, 255, 255 }, + { 255, 189, 33 }, + { 148, 82, 99 }, + { 0, 0, 0 }, + }, + DUGTRIO = { + { 255, 255, 255 }, + { 156, 90, 33 }, + { 197, 49, 33 }, + { 0, 0, 0 }, + }, + EEVEE = { + { 255, 255, 255 }, + { 197, 132, 90 }, + { 140, 82, 66 }, + { 0, 0, 0 }, + }, + EKANS = { + { 255, 255, 255 }, + { 165, 66, 173 }, + { 173, 0, 58 }, + { 0, 0, 0 }, + }, + ELECTABUZZ = { + { 255, 255, 255 }, + { 255, 255, 41 }, + { 197, 132, 41 }, + { 0, 0, 0 }, + }, + ELECTRODE = { + { 255, 255, 255 }, + { 206, 189, 140 }, + { 255, 74, 66 }, + { 0, 0, 0 }, + }, + ENGINEER = { + { 255, 255, 255 }, + { 214, 156, 123 }, + { 239, 197, 74 }, + { 0, 0, 0 }, + }, + ERIKA = { + { 255, 255, 255 }, + { 255, 148, 107 }, + { 58, 123, 66 }, + { 0, 0, 0 }, + }, + EXEGGCUTE = { + { 255, 255, 255 }, + { 255, 123, 140 }, + { 156, 41, 74 }, + { 0, 0, 0 }, + }, + EXEGGUTOR = { + { 255, 255, 255 }, + { 165, 107, 49 }, + { 41, 132, 58 }, + { 0, 0, 0 }, + }, + EXP = { + { 255, 255, 255 }, + { 239, 206, 123 }, + { 33, 140, 255 }, + { 0, 0, 0 }, + }, + FARFETCH_D = { + { 255, 255, 255 }, + { 189, 99, 25 }, + { 49, 214, 8 }, + { 0, 0, 0 }, + }, + FEAROW = { + { 255, 255, 255 }, + { 181, 140, 58 }, + { 255, 90, 0 }, + { 0, 0, 0 }, + }, + FISHERMAN = { + { 255, 255, 255 }, + { 247, 140, 107 }, + { 58, 99, 123 }, + { 0, 0, 0 }, + }, + FLAREON = { + { 255, 255, 255 }, + { 255, 82, 8 }, + { 173, 41, 16 }, + { 0, 0, 0 }, + }, + FUCHSIA = { + { 255, 255, 255 }, + { 255, 123, 123 }, + { 90, 189, 255 }, + { 0, 0, 0 }, + }, + GAMBLER = { + { 255, 255, 255 }, + { 230, 148, 99 }, + { 82, 25, 181 }, + { 0, 0, 0 }, + }, + GAMEFREAK = { + { 255, 255, 255 }, + { 255, 230, 115 }, + { 197, 165, 82 }, + { 0, 0, 0 }, + }, + GARY1 = { + { 255, 255, 255 }, + { 255, 197, 66 }, + { 99, 74, 156 }, + { 0, 0, 0 }, + }, + GARY2 = { + { 255, 255, 255 }, + { 255, 197, 66 }, + { 99, 74, 156 }, + { 0, 0, 0 }, + }, + GARY3 = { + { 255, 255, 255 }, + { 255, 197, 66 }, + { 99, 74, 156 }, + { 0, 0, 0 }, + }, + GASTLY = { + { 255, 255, 255 }, + { 247, 66, 247 }, + { 140, 0, 189 }, + { 0, 0, 0 }, + }, + GENGAR = { + { 255, 255, 255 }, + { 255, 41, 16 }, + { 74, 0, 132 }, + { 0, 0, 0 }, + }, + GENTLEMAN = { + { 255, 255, 255 }, + { 206, 132, 99 }, + { 74, 74, 123 }, + { 0, 0, 0 }, + }, + GEODUDE = { + { 255, 255, 255 }, + { 148, 140, 123 }, + { 66, 90, 58 }, + { 0, 0, 0 }, + }, + GIOVANNI = { + { 255, 255, 255 }, + { 206, 140, 99 }, + { 66, 82, 99 }, + { 0, 0, 0 }, + }, + GLOOM = { + { 255, 255, 255 }, + { 255, 115, 58 }, + { 66, 74, 107 }, + { 0, 0, 0 }, + }, + GOLBAT = { + { 255, 255, 255 }, + { 99, 123, 156 }, + { 41, 66, 140 }, + { 0, 0, 0 }, + }, + GOLDEEN = { + { 255, 255, 255 }, + { 255, 99, 156 }, + { 255, 82, 16 }, + { 0, 0, 0 }, + }, + GOLDUCK = { + { 255, 255, 255 }, + { 181, 173, 214 }, + { 66, 90, 197 }, + { 0, 0, 0 }, + }, + GOLEM = { + { 255, 255, 255 }, + { 148, 140, 123 }, + { 66, 90, 58 }, + { 0, 0, 0 }, + }, + GRAVELER = { + { 255, 255, 255 }, + { 140, 140, 148 }, + { 66, 90, 58 }, + { 0, 0, 0 }, + }, + GRAYMON = { + { 255, 255, 255 }, + { 214, 132, 181 }, + { 123, 107, 148 }, + { 0, 0, 0 }, + }, + GREENBAR = { + { 255, 255, 255 }, + { 239, 206, 123 }, + { 0, 189, 0 }, + { 0, 0, 0 }, + }, + GREENMON = { + { 255, 255, 255 }, + { 140, 255, 90 }, + { 8, 181, 49 }, + { 0, 0, 0 }, + }, + GREYMON = { + { 255, 255, 255 }, + { 214, 132, 181 }, + { 123, 107, 148 }, + { 0, 0, 0 }, + }, + GRIMER = { + { 255, 255, 255 }, + { 239, 16, 165 }, + { 99, 8, 99 }, + { 0, 0, 0 }, + }, + GROWLITHE = { + { 255, 255, 255 }, + { 255, 189, 58 }, + { 255, 74, 33 }, + { 0, 0, 0 }, + }, + GYARADOS = { + { 255, 255, 255 }, + { 222, 206, 58 }, + { 74, 115, 214 }, + { 0, 0, 0 }, + }, + HAUNTER = { + { 255, 255, 255 }, + { 206, 58, 49 }, + { 115, 0, 156 }, + { 0, 0, 0 }, + }, + HERO = { + { 255, 255, 255 }, + { 230, 148, 140 }, + { 181, 58, 66 }, + { 0, 0, 0 }, + }, + HIKER = { + { 255, 255, 255 }, + { 189, 123, 74 }, + { 107, 66, 189 }, + { 0, 0, 0 }, + }, + HITMONCHAN = { + { 255, 255, 255 }, + { 173, 123, 99 }, + { 222, 25, 148 }, + { 0, 0, 0 }, + }, + HITMONLEE = { + { 255, 255, 255 }, + { 181, 115, 41 }, + { 123, 132, 123 }, + { 0, 0, 0 }, + }, + HORSEA = { + { 255, 255, 255 }, + { 230, 222, 99 }, + { 90, 140, 255 }, + { 0, 0, 0 }, + }, + HYPNO = { + { 255, 255, 255 }, + { 255, 206, 0 }, + { 173, 99, 0 }, + { 0, 0, 0 }, + }, + INDIGO = { + { 255, 255, 255 }, + { 90, 66, 255 }, + { 90, 189, 255 }, + { 0, 0, 0 }, + }, + IVYSAUR = { + { 255, 255, 255 }, + { 99, 255, 90 }, + { 255, 99, 140 }, + { 0, 0, 0 }, + }, + JIGGLYPUFF = { + { 255, 255, 255 }, + { 255, 132, 255 }, + { 49, 132, 255 }, + { 0, 0, 0 }, + }, + JOLTEON = { + { 255, 255, 255 }, + { 255, 255, 25 }, + { 230, 90, 8 }, + { 0, 0, 0 }, + }, + JR_TRAINER_F = { + { 255, 255, 255 }, + { 255, 156, 66 }, + { 82, 165, 16 }, + { 0, 0, 0 }, + }, + JR_TRAINER_M = { + { 255, 255, 255 }, + { 255, 156, 66 }, + { 123, 206, 16 }, + { 0, 0, 0 }, + }, + JUGGLER = { + { 255, 255, 255 }, + { 214, 123, 82 }, + { 74, 49, 255 }, + { 0, 0, 0 }, + }, + JUGGLER2 = { + { 255, 255, 255 }, + { 214, 123, 82 }, + { 74, 49, 255 }, + { 0, 0, 0 }, + }, + JYNX = { + { 255, 255, 255 }, + { 255, 222, 33 }, + { 239, 49, 156 }, + { 0, 0, 0 }, + }, + KABUTO = { + { 255, 255, 255 }, + { 189, 123, 90 }, + { 115, 90, 66 }, + { 0, 0, 0 }, + }, + KABUTOPS = { + { 255, 255, 255 }, + { 189, 123, 90 }, + { 115, 90, 66 }, + { 0, 0, 0 }, + }, + KADABRA = { + { 255, 255, 255 }, + { 230, 156, 25 }, + { 99, 66, 82 }, + { 0, 0, 0 }, + }, + KAKUNA = { + { 255, 255, 255 }, + { 214, 206, 25 }, + { 165, 115, 66 }, + { 0, 0, 0 }, + }, + KANGASKHAN = { + { 255, 255, 255 }, + { 156, 115, 33 }, + { 66, 66, 16 }, + { 0, 0, 0 }, + }, + KINGLER = { + { 255, 255, 255 }, + { 239, 140, 74 }, + { 239, 41, 33 }, + { 0, 0, 0 }, + }, + KOFFING = { + { 255, 255, 255 }, + { 206, 82, 206 }, + { 148, 49, 148 }, + { 0, 0, 0 }, + }, + KOGA = { + { 255, 255, 255 }, + { 222, 148, 115 }, + { 99, 58, 107 }, + { 0, 0, 0 }, + }, + KRABBY = { + { 255, 255, 255 }, + { 239, 140, 74 }, + { 239, 41, 33 }, + { 0, 0, 0 }, + }, + LANCE = { + { 255, 255, 255 }, + { 239, 156, 123 }, + { 173, 74, 41 }, + { 0, 0, 0 }, + }, + LAPRAS = { + { 255, 255, 255 }, + { 230, 173, 107 }, + { 66, 132, 230 }, + { 0, 0, 0 }, + }, + LASS = { + { 255, 255, 255 }, + { 206, 140, 49 }, + { 107, 66, 206 }, + { 0, 0, 0 }, + }, + LAVENDER = { + { 255, 255, 255 }, + { 206, 33, 255 }, + { 90, 189, 255 }, + { 0, 0, 0 }, + }, + LICKITUNG = { + { 255, 255, 255 }, + { 255, 82, 148 }, + { 214, 49, 41 }, + { 0, 0, 0 }, + }, + LOGO1 = { + { 255, 255, 255 }, + { 247, 247, 140 }, + { 140, 189, 82 }, + { 173, 0, 33 }, + }, + LOGO2 = { + { 255, 255, 255 }, + { 230, 197, 0 }, + { 148, 156, 148 }, + { 41, 99, 181 }, + }, + LORELEI = { + { 255, 255, 255 }, + { 230, 165, 132 }, + { 206, 49, 49 }, + { 0, 0, 0 }, + }, + LT_SURGE = { + { 255, 255, 255 }, + { 206, 140, 115 }, + { 74, 115, 82 }, + { 0, 0, 0 }, + }, + MACHAMP = { + { 255, 255, 255 }, + { 173, 148, 90 }, + { 74, 90, 33 }, + { 0, 0, 0 }, + }, + MACHOKE = { + { 255, 255, 255 }, + { 132, 140, 90 }, + { 181, 33, 33 }, + { 0, 0, 0 }, + }, + MACHOP = { + { 255, 255, 255 }, + { 165, 140, 90 }, + { 74, 90, 33 }, + { 0, 0, 0 }, + }, + MAGIKARP = { + { 255, 255, 255 }, + { 239, 82, 49 }, + { 148, 25, 74 }, + { 0, 0, 0 }, + }, + MAGMAR = { + { 255, 255, 255 }, + { 255, 165, 0 }, + { 189, 58, 49 }, + { 0, 0, 0 }, + }, + MAGNEMITE = { + { 255, 255, 255 }, + { 90, 165, 255 }, + { 255, 49, 16 }, + { 0, 0, 0 }, + }, + MAGNETON = { + { 255, 255, 255 }, + { 90, 165, 255 }, + { 255, 49, 16 }, + { 0, 0, 0 }, + }, + MANKEY = { + { 255, 255, 255 }, + { 239, 165, 90 }, + { 156, 74, 58 }, + { 0, 0, 0 }, + }, + MAROWAK = { + { 255, 255, 255 }, + { 165, 156, 99 }, + { 132, 82, 33 }, + { 0, 0, 0 }, + }, + MEOWTH = { + { 255, 255, 255 }, + { 255, 222, 107 }, + { 165, 66, 25 }, + { 0, 0, 0 }, + }, + METAPOD = { + { 255, 255, 255 }, + { 123, 255, 0 }, + { 74, 115, 8 }, + { 0, 0, 0 }, + }, + MEW = { + { 255, 255, 255 }, + { 255, 123, 255 }, + { 58, 90, 214 }, + { 0, 0, 0 }, + }, + MEWMON = { + { 255, 255, 255 }, + { 239, 156, 107 }, + { 115, 33, 165 }, + { 0, 0, 0 }, + }, + MEWTWO = { + { 255, 255, 255 }, + { 181, 165, 206 }, + { 132, 41, 165 }, + { 0, 0, 0 }, + }, + MISTY = { + { 255, 255, 255 }, + { 239, 156, 132 }, + { 165, 82, 41 }, + { 0, 0, 0 }, + }, + MOLTRES = { + { 255, 255, 255 }, + { 255, 181, 0 }, + { 255, 99, 25 }, + { 0, 0, 0 }, + }, + MR_MIME = { + { 255, 255, 255 }, + { 255, 90, 255 }, + { 230, 58, 107 }, + { 0, 0, 0 }, + }, + MUK = { + { 255, 255, 255 }, + { 239, 16, 165 }, + { 99, 8, 99 }, + { 0, 0, 0 }, + }, + NIDOKING = { + { 255, 255, 255 }, + { 197, 82, 156 }, + { 107, 25, 123 }, + { 0, 0, 0 }, + }, + NIDOQUEEN = { + { 255, 255, 255 }, + { 222, 156, 58 }, + { 74, 132, 222 }, + { 0, 0, 0 }, + }, + NIDORAN_F = { + { 255, 255, 255 }, + { 148, 173, 247 }, + { 99, 49, 115 }, + { 0, 0, 0 }, + }, + NIDORAN_M = { + { 255, 255, 255 }, + { 222, 140, 181 }, + { 173, 16, 66 }, + { 0, 0, 0 }, + }, + NIDORINA = { + { 255, 255, 255 }, + { 107, 165, 255 }, + { 58, 99, 115 }, + { 0, 0, 0 }, + }, + NIDORINO = { + { 255, 255, 255 }, + { 214, 140, 181 }, + { 173, 16, 66 }, + { 0, 0, 0 }, + }, + NINETALES = { + { 255, 255, 255 }, + { 255, 206, 74 }, + { 148, 123, 0 }, + { 0, 0, 0 }, + }, + OAK = { + { 255, 255, 255 }, + { 197, 156, 90 }, + { 107, 132, 0 }, + { 0, 0, 0 }, + }, + ODDISH = { + { 255, 255, 255 }, + { 90, 189, 25 }, + { 49, 74, 74 }, + { 0, 0, 0 }, + }, + OMANYTE = { + { 255, 255, 255 }, + { 165, 140, 90 }, + { 58, 115, 173 }, + { 0, 0, 0 }, + }, + OMASTAR = { + { 255, 255, 255 }, + { 165, 140, 90 }, + { 58, 115, 173 }, + { 0, 0, 0 }, + }, + ONIX = { + { 255, 255, 255 }, + { 140, 123, 165 }, + { 74, 49, 90 }, + { 0, 0, 0 }, + }, + PALLET = { + { 255, 255, 255 }, + { 148, 148, 123 }, + { 90, 189, 255 }, + { 0, 0, 0 }, + }, + PARAS = { + { 255, 255, 255 }, + { 255, 99, 25 }, + { 189, 25, 0 }, + { 0, 0, 0 }, + }, + PARASECT = { + { 255, 255, 255 }, + { 255, 74, 33 }, + { 115, 41, 8 }, + { 0, 0, 0 }, + }, + PERSIAN = { + { 255, 255, 255 }, + { 255, 230, 82 }, + { 99, 74, 33 }, + { 0, 0, 0 }, + }, + PEWTER = { + { 255, 255, 255 }, + { 148, 148, 123 }, + { 90, 189, 255 }, + { 0, 0, 0 }, + }, + PIDGEOT = { + { 255, 255, 255 }, + { 255, 82, 99 }, + { 156, 66, 16 }, + { 0, 0, 0 }, + }, + PIDGEOTTO = { + { 255, 255, 255 }, + { 255, 82, 99 }, + { 156, 66, 16 }, + { 0, 0, 0 }, + }, + PIDGEY = { + { 255, 255, 255 }, + { 255, 173, 255 }, + { 156, 66, 16 }, + { 0, 0, 0 }, + }, + PIKACHU = { + { 255, 255, 255 }, + { 239, 214, 41 }, + { 214, 49, 0 }, + { 0, 0, 0 }, + }, + PINKMON = { + { 255, 255, 255 }, + { 255, 123, 148 }, + { 255, 0, 49 }, + { 0, 0, 0 }, + }, + PINSIR = { + { 255, 255, 255 }, + { 165, 165, 115 }, + { 140, 82, 58 }, + { 0, 0, 0 }, + }, + POKEMANIAC = { + { 255, 255, 255 }, + { 230, 165, 107 }, + { 107, 41, 148 }, + { 0, 0, 0 }, + }, + POLIWAG = { + { 255, 255, 255 }, + { 214, 66, 41 }, + { 58, 66, 82 }, + { 0, 0, 0 }, + }, + POLIWHIRL = { + { 255, 255, 255 }, + { 132, 132, 214 }, + { 66, 41, 123 }, + { 0, 0, 0 }, + }, + POLIWRATH = { + { 255, 255, 255 }, + { 132, 132, 214 }, + { 49, 49, 123 }, + { 0, 0, 0 }, + }, + PONYTA = { + { 255, 255, 255 }, + { 214, 222, 33 }, + { 255, 41, 25 }, + { 0, 0, 0 }, + }, + PORYGON = { + { 255, 255, 255 }, + { 197, 74, 33 }, + { 99, 90, 206 }, + { 0, 0, 0 }, + }, + PRIMEAPE = { + { 255, 255, 255 }, + { 255, 148, 99 }, + { 132, 66, 41 }, + { 0, 0, 0 }, + }, + PSYCHIC = { + { 255, 255, 255 }, + { 247, 181, 140 }, + { 82, 99, 156 }, + { 0, 0, 0 }, + }, + PSYDUCK = { + { 255, 255, 255 }, + { 255, 222, 33 }, + { 140, 123, 0 }, + { 0, 0, 0 }, + }, + PURPLEMON = { + { 255, 255, 255 }, + { 206, 123, 255 }, + { 156, 0, 181 }, + { 0, 0, 0 }, + }, + RAICHU = { + { 255, 255, 255 }, + { 255, 214, 58 }, + { 255, 99, 0 }, + { 0, 0, 0 }, + }, + RAPIDASH = { + { 255, 255, 255 }, + { 214, 222, 33 }, + { 255, 41, 25 }, + { 0, 0, 0 }, + }, + RATICATE = { + { 255, 255, 255 }, + { 239, 189, 82 }, + { 140, 82, 0 }, + { 0, 0, 0 }, + }, + RATTATA = { + { 255, 255, 255 }, + { 181, 66, 247 }, + { 132, 25, 140 }, + { 0, 0, 0 }, + }, + REDBAR = { + { 255, 255, 255 }, + { 239, 206, 123 }, + { 247, 0, 0 }, + { 0, 0, 0 }, + }, + REDMON = { + { 255, 255, 255 }, + { 255, 140, 0 }, + { 255, 0, 0 }, + { 0, 0, 0 }, + }, + RHYDON = { + { 255, 255, 255 }, + { 123, 90, 140 }, + { 58, 74, 33 }, + { 0, 0, 0 }, + }, + RHYHORN = { + { 255, 255, 255 }, + { 123, 90, 140 }, + { 58, 74, 33 }, + { 0, 0, 0 }, + }, + ROCKER = { + { 255, 255, 255 }, + { 255, 181, 156 }, + { 255, 66, 41 }, + { 0, 0, 0 }, + }, + ROCKET = { + { 255, 255, 255 }, + { 239, 140, 123 }, + { 165, 66, 41 }, + { 0, 0, 0 }, + }, + ROUTE = { + { 255, 255, 255 }, + { 156, 255, 0 }, + { 90, 189, 255 }, + { 0, 0, 0 }, + }, + SABRINA = { + { 255, 255, 255 }, + { 247, 181, 140 }, + { 197, 58, 74 }, + { 0, 0, 0 }, + }, + SAFFRON = { + { 255, 255, 255 }, + { 255, 255, 0 }, + { 90, 189, 255 }, + { 0, 0, 0 }, + }, + SAILOR = { + { 255, 255, 255 }, + { 197, 115, 58 }, + { 25, 58, 107 }, + { 0, 0, 0 }, + }, + SANDSHREW = { + { 255, 255, 255 }, + { 181, 148, 49 }, + { 99, 58, 8 }, + { 0, 0, 0 }, + }, + SANDSLASH = { + { 255, 255, 255 }, + { 189, 115, 33 }, + { 107, 58, 0 }, + { 0, 0, 0 }, + }, + SCIENTIST = { + { 255, 255, 255 }, + { 197, 156, 90 }, + { 82, 107, 140 }, + { 0, 0, 0 }, + }, + SCYTHER = { + { 255, 255, 255 }, + { 123, 214, 0 }, + { 189, 206, 0 }, + { 0, 0, 0 }, + }, + SEADRA = { + { 255, 255, 255 }, + { 230, 181, 132 }, + { 74, 132, 255 }, + { 0, 0, 0 }, + }, + SEAKING = { + { 255, 255, 255 }, + { 156, 181, 247 }, + { 255, 82, 16 }, + { 0, 0, 0 }, + }, + SEEL = { + { 255, 255, 255 }, + { 156, 173, 255 }, + { 239, 74, 107 }, + { 0, 0, 0 }, + }, + SHELLDER = { + { 255, 255, 255 }, + { 132, 66, 107 }, + { 173, 58, 8 }, + { 0, 0, 0 }, + }, + SLOTS1 = { + { 255, 255, 255 }, + { 0, 115, 0 }, + { 16, 165, 25 }, + { 0, 0, 0 }, + }, + SLOTS2 = { + { 255, 255, 255 }, + { 214, 0, 0 }, + { 16, 165, 25 }, + { 0, 0, 0 }, + }, + SLOTS3 = { + { 255, 255, 255 }, + { 66, 33, 181 }, + { 16, 165, 25 }, + { 0, 0, 0 }, + }, + SLOTS4 = { + { 255, 255, 255 }, + { 239, 247, 8 }, + { 16, 165, 25 }, + { 0, 0, 0 }, + }, + SLOTS5 = { + { 255, 255, 255 }, + { 140, 8, 16 }, + { 214, 0, 0 }, + { 0, 0, 0 }, + }, + SLOWBRO = { + { 255, 255, 255 }, + { 255, 82, 140 }, + { 99, 140, 90 }, + { 0, 0, 0 }, + }, + SLOWPOKE = { + { 255, 255, 255 }, + { 255, 82, 140 }, + { 173, 41, 66 }, + { 0, 0, 0 }, + }, + SNORLAX = { + { 255, 255, 255 }, + { 222, 148, 115 }, + { 107, 74, 74 }, + { 0, 0, 0 }, + }, + SPEAROW = { + { 255, 255, 255 }, + { 239, 189, 107 }, + { 173, 66, 90 }, + { 0, 0, 0 }, + }, + SQUIRTLE = { + { 255, 255, 255 }, + { 181, 148, 66 }, + { 99, 156, 255 }, + { 0, 0, 0 }, + }, + STARMIE = { + { 255, 255, 255 }, + { 214, 181, 0 }, + { 156, 58, 148 }, + { 0, 0, 0 }, + }, + STARYU = { + { 255, 255, 255 }, + { 189, 140, 90 }, + { 255, 41, 25 }, + { 0, 0, 0 }, + }, + SUPERNERD = { + { 255, 255, 255 }, + { 247, 181, 140 }, + { 90, 74, 82 }, + { 0, 0, 0 }, + }, + SWIMMER = { + { 255, 255, 255 }, + { 173, 107, 8 }, + { 25, 33, 74 }, + { 0, 0, 0 }, + }, + TAMER = { + { 255, 255, 255 }, + { 230, 165, 123 }, + { 99, 107, 148 }, + { 0, 0, 0 }, + }, + TANGELA = { + { 255, 255, 255 }, + { 74, 107, 189 }, + { 140, 49, 49 }, + { 0, 0, 0 }, + }, + TAUROS = { + { 255, 255, 255 }, + { 206, 123, 41 }, + { 82, 58, 33 }, + { 0, 0, 0 }, + }, + TENTACOOL = { + { 255, 255, 255 }, + { 90, 165, 255 }, + { 247, 41, 82 }, + { 0, 0, 0 }, + }, + TENTACRUEL = { + { 255, 255, 255 }, + { 90, 165, 255 }, + { 214, 16, 16 }, + { 0, 0, 0 }, + }, + TOWNMAP = { + { 255, 255, 255 }, + { 0, 173, 255 }, + { 82, 230, 0 }, + { 0, 0, 0 }, + }, + TOWNMAP2 = { + { 206, 148, 0 }, + { 123, 66, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + }, + VAPOREON = { + { 255, 255, 255 }, + { 132, 181, 255 }, + { 74, 90, 255 }, + { 0, 0, 0 }, + }, + VENOMOTH = { + { 255, 255, 255 }, + { 222, 82, 197 }, + { 99, 41, 115 }, + { 0, 0, 0 }, + }, + VENONAT = { + { 255, 255, 255 }, + { 230, 41, 16 }, + { 90, 0, 115 }, + { 0, 0, 0 }, + }, + VENUSAUR = { + { 255, 255, 255 }, + { 99, 255, 156 }, + { 255, 74, 156 }, + { 0, 0, 0 }, + }, + VERMILION = { + { 255, 255, 255 }, + { 255, 156, 0 }, + { 90, 189, 255 }, + { 0, 0, 0 }, + }, + VICTREEBEL = { + { 255, 255, 255 }, + { 123, 214, 25 }, + { 255, 82, 107 }, + { 0, 0, 0 }, + }, + VILEPLUME = { + { 255, 255, 255 }, + { 255, 49, 25 }, + { 66, 74, 107 }, + { 0, 0, 0 }, + }, + VIRIDIAN = { + { 255, 255, 255 }, + { 156, 255, 0 }, + { 90, 189, 255 }, + { 0, 0, 0 }, + }, + VOLTORB = { + { 255, 255, 255 }, + { 206, 189, 140 }, + { 255, 74, 66 }, + { 0, 0, 0 }, + }, + VULPIX = { + { 255, 255, 255 }, + { 255, 148, 74 }, + { 189, 74, 82 }, + { 0, 0, 0 }, + }, + WARTORTLE = { + { 255, 255, 255 }, + { 181, 148, 66 }, + { 99, 156, 255 }, + { 0, 0, 0 }, + }, + WEEDLE = { + { 255, 255, 255 }, + { 214, 140, 41 }, + { 206, 41, 25 }, + { 0, 0, 0 }, + }, + WEEPINBELL = { + { 255, 255, 255 }, + { 107, 255, 58 }, + { 239, 74, 74 }, + { 0, 0, 0 }, + }, + WEEZING = { + { 255, 255, 255 }, + { 206, 82, 206 }, + { 148, 49, 148 }, + { 0, 0, 0 }, + }, + WIGGLYTUFF = { + { 255, 255, 255 }, + { 255, 132, 255 }, + { 49, 132, 255 }, + { 0, 0, 0 }, + }, + YELLOWBAR = { + { 255, 255, 255 }, + { 239, 206, 123 }, + { 247, 165, 0 }, + { 0, 0, 0 }, + }, + YELLOWMON = { + { 255, 255, 255 }, + { 255, 255, 0 }, + { 230, 115, 0 }, + { 0, 0, 0 }, + }, + YOUNGSTER = { + { 255, 255, 255 }, + { 222, 165, 74 }, + { 74, 99, 189 }, + { 0, 0, 0 }, + }, + ZAPDOS = { + { 255, 255, 255 }, + { 255, 230, 0 }, + { 189, 132, 0 }, + { 0, 0, 0 }, + }, + ZUBAT = { + { 255, 255, 255 }, + { 99, 123, 156 }, + { 41, 66, 140 }, + { 0, 0, 0 }, + }, + }, + pokemon = { + ABRA = "ABRA", + AERODACTYL = "AERODACTYL", + ALAKAZAM = "ALAKAZAM", + ARBOK = "ARBOK", + ARCANINE = "ARCANINE", + ARTICUNO = "ARTICUNO", + BEEDRILL = "BEEDRILL", + BELLSPROUT = "BELLSPROUT", + BLASTOISE = "BLASTOISE", + BULBASAUR = "BULBASAUR", + BUTTERFREE = "BUTTERFREE", + CATERPIE = "CATERPIE", + CHANSEY = "CHANSEY", + CHARIZARD = "CHARIZARD", + CHARMANDER = "CHARMANDER", + CHARMELEON = "CHARMELEON", + CLEFABLE = "CLEFABLE", + CLEFAIRY = "CLEFAIRY", + CLOYSTER = "CLOYSTER", + CUBONE = "CUBONE", + DEWGONG = "DEWGONG", + DIGLETT = "DIGLETT", + DITTO = "DITTO", + DODRIO = "DODRIO", + DODUO = "DODUO", + DRAGONAIR = "DRAGONAIR", + DRAGONITE = "DRAGONITE", + DRATINI = "DRATINI", + DROWZEE = "DROWZEE", + DUGTRIO = "DUGTRIO", + EEVEE = "EEVEE", + EKANS = "EKANS", + ELECTABUZZ = "ELECTABUZZ", + ELECTRODE = "ELECTRODE", + EXEGGCUTE = "EXEGGCUTE", + EXEGGUTOR = "EXEGGUTOR", + FARFETCHD = "FARFETCH_D", + FEAROW = "FEAROW", + FLAREON = "FLAREON", + GASTLY = "GASTLY", + GENGAR = "GENGAR", + GEODUDE = "GEODUDE", + GLOOM = "GLOOM", + GOLBAT = "GOLBAT", + GOLDEEN = "GOLDEEN", + GOLDUCK = "GOLDUCK", + GOLEM = "GOLEM", + GRAVELER = "GRAVELER", + GRIMER = "GRIMER", + GROWLITHE = "GROWLITHE", + GYARADOS = "GYARADOS", + HAUNTER = "HAUNTER", + HITMONCHAN = "HITMONCHAN", + HITMONLEE = "HITMONLEE", + HORSEA = "HORSEA", + HYPNO = "HYPNO", + IVYSAUR = "IVYSAUR", + JIGGLYPUFF = "JIGGLYPUFF", + JOLTEON = "JOLTEON", + JYNX = "JYNX", + KABUTO = "KABUTO", + KABUTOPS = "KABUTOPS", + KADABRA = "KADABRA", + KAKUNA = "KAKUNA", + KANGASKHAN = "KANGASKHAN", + KINGLER = "KINGLER", + KOFFING = "KOFFING", + KRABBY = "KRABBY", + LAPRAS = "LAPRAS", + LICKITUNG = "LICKITUNG", + MACHAMP = "MACHAMP", + MACHOKE = "MACHOKE", + MACHOP = "MACHOP", + MAGIKARP = "MAGIKARP", + MAGMAR = "MAGMAR", + MAGNEMITE = "MAGNEMITE", + MAGNETON = "MAGNETON", + MANKEY = "MANKEY", + MAROWAK = "MAROWAK", + MEOWTH = "MEOWTH", + METAPOD = "METAPOD", + MEW = "MEW", + MEWTWO = "MEWTWO", + MOLTRES = "MOLTRES", + MR_MIME = "MR_MIME", + MUK = "MUK", + NIDOKING = "NIDOKING", + NIDOQUEEN = "NIDOQUEEN", + NIDORAN_F = "NIDORAN_F", + NIDORAN_M = "NIDORAN_M", + NIDORINA = "NIDORINA", + NIDORINO = "NIDORINO", + NINETALES = "NINETALES", + ODDISH = "ODDISH", + OMANYTE = "OMANYTE", + OMASTAR = "OMASTAR", + ONIX = "ONIX", + PARAS = "PARAS", + PARASECT = "PARASECT", + PERSIAN = "PERSIAN", + PIDGEOT = "PIDGEOT", + PIDGEOTTO = "PIDGEOTTO", + PIDGEY = "PIDGEY", + PIKACHU = "PIKACHU", + PINSIR = "PINSIR", + POLIWAG = "POLIWAG", + POLIWHIRL = "POLIWHIRL", + POLIWRATH = "POLIWRATH", + PONYTA = "PONYTA", + PORYGON = "PORYGON", + PRIMEAPE = "PRIMEAPE", + PSYDUCK = "PSYDUCK", + RAICHU = "RAICHU", + RAPIDASH = "RAPIDASH", + RATICATE = "RATICATE", + RATTATA = "RATTATA", + RHYDON = "RHYDON", + RHYHORN = "RHYHORN", + SANDSHREW = "SANDSHREW", + SANDSLASH = "SANDSLASH", + SCYTHER = "SCYTHER", + SEADRA = "SEADRA", + SEAKING = "SEAKING", + SEEL = "SEEL", + SHELLDER = "SHELLDER", + SLOWBRO = "SLOWBRO", + SLOWPOKE = "SLOWPOKE", + SNORLAX = "SNORLAX", + SPEAROW = "SPEAROW", + SQUIRTLE = "SQUIRTLE", + STARMIE = "STARMIE", + STARYU = "STARYU", + TANGELA = "TANGELA", + TAUROS = "TAUROS", + TENTACOOL = "TENTACOOL", + TENTACRUEL = "TENTACRUEL", + VAPOREON = "VAPOREON", + VENOMOTH = "VENOMOTH", + VENONAT = "VENONAT", + VENUSAUR = "VENUSAUR", + VICTREEBEL = "VICTREEBEL", + VILEPLUME = "VILEPLUME", + VOLTORB = "VOLTORB", + VULPIX = "VULPIX", + WARTORTLE = "WARTORTLE", + WEEDLE = "WEEDLE", + WEEPINBELL = "WEEPINBELL", + WEEZING = "WEEZING", + WIGGLYTUFF = "WIGGLYTUFF", + ZAPDOS = "ZAPDOS", + ZUBAT = "ZUBAT", + }, + source = "pokered-gbc data/super_palettes.asm + data/mon_palettes.asm", +} diff --git a/data/scripts/oaks_lab.lua b/data/scripts/oaks_lab.lua index dcce5fef..fb8b0e81 100644 --- a/data/scripts/oaks_lab.lua +++ b/data/scripts/oaks_lab.lua @@ -10,8 +10,8 @@ -- starter -> taunt + battle OPP_RIVAL1 with the counter-pick party -- (player Bulbasaur -> rival Charmander etc., parties 1/2/3 = -- Squirtle/Bulbasaur/Charmander in data/trainers/parties.asm); --- afterwards he gloats or sulks and marches out of the lab --- (OaksLabRivalBattleEndScript). +-- afterwards HealParty + flag always, then he gloats or sulks and +-- marches out (OaksLabRivalEndBattleScript). A loss does not black out. -- ball objects: CHARMANDER (6,3), SQUIRTLE (7,3), BULBASAUR (8,3); -- rival = object 1 at (4,3). rivalBallX is the counter-pick's column. @@ -107,9 +107,9 @@ return { TEXT_OAKSLAB_RIVAL = { { "face_player" }, -- 1 { "check_flag", "EVENT_GOT_STARTER" }, -- 2 - { "jump_if_false", 20 }, -- 3 + { "jump_if_false", 21 }, -- 3 { "check_flag", "EVENT_BATTLED_RIVAL_IN_OAKS_LAB" }, -- 4 - { "jump_if_true", 18 }, -- 5 + { "jump_if_true", 19 }, -- 5 { "show_text", "_OaksLabRivalMyPokemonLooksStrongerText" }, -- 6 { "check_flag", "EVENT_CHOSE_BULBASAUR" }, -- 7 { "jump_if_false", 11 }, -- 8 @@ -120,18 +120,20 @@ return { { "start_battle", "trainer", "OPP_RIVAL1", 2 }, -- 13 Bulbasaur { "jump", 16 }, -- 14 { "start_battle", "trainer", "OPP_RIVAL1", 1 }, -- 15 Squirtle - { "set_flag", "EVENT_BATTLED_RIVAL_IN_OAKS_LAB" }, -- 16 - { "jump", 21 }, -- 17 - { "show_text", "_OaksLabRivalFedUpWithWaitingText" }, -- 18 - { "jump", 25 }, -- 19 - { "show_text", "_OaksLabRivalGrampsIsntAroundText" }, -- 20 - -- battle aftermath: on a win the rival sulks and marches out - -- (OaksLabRivalBattleEnd); on a loss the blackout already warped - -- us away, so the script just ends - { "jump_if_false", 25 }, -- 21 - { "show_text", "_OaksLabRivalIPickedTheWrongPokemonText" }, -- 22 - { "move_npc_to", 1, 4, 11 }, -- 23 - { "hide_object", "OAKS_LAB", "OAKSLAB_RIVAL" }, -- 24 (25 = end) + -- OaksLabRivalEndBattleScript: HealParty + flag, then exit either way + { "heal_party" }, -- 16 + { "set_flag", "EVENT_BATTLED_RIVAL_IN_OAKS_LAB" }, -- 17 + { "jump", 23 }, -- 18 + { "show_text", "_OaksLabRivalFedUpWithWaitingText" }, -- 19 + { "jump", "end" }, -- 20 + { "show_text", "_OaksLabRivalGrampsIsntAroundText" }, -- 21 + { "jump", "end" }, -- 22 + -- win: sulk text then exit; loss: Rival1WinText already played in + -- battle (HandlePlayerBlackOut), so skip straight to the walk-out + { "jump_if_false", 25 }, -- 23 + { "show_text", "_OaksLabRivalIPickedTheWrongPokemonText" }, -- 24 + { "move_npc_to", 1, 4, 11 }, -- 25 + { "hide_object", "OAKS_LAB", "OAKSLAB_RIVAL" }, -- 26 }, }, @@ -178,9 +180,12 @@ return { local party = flags.EVENT_CHOSE_BULBASAUR and 3 or flags.EVENT_CHOSE_SQUIRTLE and 2 or 1 table.insert(rows, { "start_battle", "trainer", "OPP_RIVAL1", party }) + -- OaksLabRivalEndBattleScript: heal + flag on win or loss; no blackout + table.insert(rows, { "heal_party" }) table.insert(rows, { "set_flag", "EVENT_BATTLED_RIVAL_IN_OAKS_LAB" }) - -- a loss blacks out to another map: end the script there - table.insert(rows, { "jump_if_false", base + 7 }) + -- win: sulk text then exit; loss jumps to the walk-out (taunt was + -- already shown in-battle via Rival1WinText) + table.insert(rows, { "jump_if_false", base + 6 }) table.insert(rows, { "show_text", "_OaksLabRivalIPickedTheWrongPokemonText" }) table.insert(rows, { "move_npc_to", 1, 4, 11 }) table.insert(rows, { "hide_object", "OAKS_LAB", "OAKSLAB_RIVAL" }) diff --git a/data/scripts/story2.lua b/data/scripts/story2.lua index 6823908d..963b8d9a 100644 --- a/data/scripts/story2.lua +++ b/data/scripts/story2.lua @@ -417,6 +417,26 @@ M.BIKE_SHOP = { -- the Cinnabar lab (the wait is skipped). -- ------------------------------------------------------------------- +-- The Super Nerd (object index 1) claims both fossils and blocks the way +-- to them. In scripts/MtMoonB2F.asm he isn't a sight-line trainer: his +-- header carries no range, so MtMoonB2FDefaultScript force-triggers the +-- battle the instant the player steps onto (13,8) -- the chokepoint tile +-- to his right -- and reaching for a fossil intercepts you too. +local function superNerdBeaten(ow) + local nerd = ow:npcByIndex(1) + return not nerd or ow:trainerDefeated(nerd) +end + +local function engageSuperNerd(game, ow, onDone) + local nerd = ow:npcByIndex(1) + if not nerd or ow:trainerDefeated(nerd) then + if onDone then onDone() end + return + end + nerd:facePlayer(ow.player) + ow:engageTrainer(nerd, onDone) +end + local function mtMoonFossil(itemId, otherName) return function(game, ow, npc, done) local TextBox = require("src.render.TextBox") @@ -425,7 +445,13 @@ local function mtMoonFossil(itemId, otherName) game.stack:push(TextBox.new(game, "You already took\na fossil.", done)) return end - game.stack:push(TextBox.new(game, "You found a\nfossil! Take it?", function() + -- can't grab a fossil until the Super Nerd is beaten -- he intercepts + if not superNerdBeaten(ow) then + engageSuperNerd(game, ow, done) + return + end + local name = game.data.items[itemId].name + game.stack:push(TextBox.new(game, ("You want the\n%s?"):format(name), function() game.stack:push(ChoiceBox.new(game, function(yes) if not yes then done() return end game.save.inventory[itemId] = 1 @@ -434,7 +460,6 @@ local function mtMoonFossil(itemId, otherName) local ctx = { save = game.save, overworld = ow, game = game } Commands.hide_object(ctx, "MT_MOON_B2F", npc.def.name) Commands.hide_object(ctx, "MT_MOON_B2F", otherName) - local name = game.data.items[itemId].name game.stack:push(TextBox.new(game, ("%s got the\n%s!"):format(game.save.player.name, name), done)) end)) @@ -443,6 +468,15 @@ local function mtMoonFossil(itemId, otherName) end M.MT_MOON_B2F = { + -- MtMoonB2FDefaultScript forces the Super Nerd battle when the player + -- steps onto (13,8), the tile beside him guarding the fossils. + onStep = function(game, ow, x, y) + if x == 13 and y == 8 and not superNerdBeaten(ow) then + engageSuperNerd(game, ow, nil) + return true + end + return false + end, talk = { TEXT_MTMOONB2F_DOME_FOSSIL = mtMoonFossil("DOME_FOSSIL", "MTMOONB2F_HELIX_FOSSIL"), TEXT_MTMOONB2F_HELIX_FOSSIL = mtMoonFossil("HELIX_FOSSIL", "MTMOONB2F_DOME_FOSSIL"), diff --git a/data/scripts/story3.lua b/data/scripts/story3.lua index 16e81404..3bd12027 100644 --- a/data/scripts/story3.lua +++ b/data/scripts/story3.lua @@ -104,7 +104,7 @@ M.POKEMON_TOWER_6F = { -- immediately re-fires. ow:scriptMove(ow.player, "right", 1) end - ow:afterBattle(result) + ow:afterBattle(result, battle) end game.stack:push(battle) end)) diff --git a/docs/new-features.md b/docs/new-features.md index 6f6f5436..6155d80f 100644 --- a/docs/new-features.md +++ b/docs/new-features.md @@ -132,6 +132,7 @@ migrated once into `options.lua` on load. - Music / SFX volume - Music Filter - OG GLITCHES on / off (Gen 1 quirks vs. modern-clean battle rules) -- COLORS (GBC / OG / OG INV / GBC INV / CLASSIC), also hotkey `2` +- COLORS (GBC / RED++ / OG / OG INV / GBC INV / CLASSIC), also hotkey `2` + (RED++ uses pokered-gbc SuperPalettes + per-species mon colors) - TILT (OFF / 15 / 35 / 50), also hotkey `3` while free-roaming - GBC FX (OFF / 1 / 2 / 3 / 4), also hotkey `5` \ No newline at end of file diff --git a/src/battle/BattleState.lua b/src/battle/BattleState.lua index 3268a5b8..34658437 100644 --- a/src/battle/BattleState.lua +++ b/src/battle/BattleState.lua @@ -106,19 +106,25 @@ end Assets.register(BattleState.invalidate) --- the species' SGB palette (data/pokemon/palettes.asm), or nil +-- the species' SGB palette (active COLORS pack), or nil local function monPalette(data, species) - local p = data.palettes - local name = p and p.pokemon[species] - local colors = name and p.palettes[name] - return colors and { name = name, colors = colors } or nil + local PaletteFX = require("src.render.PaletteFX") + local colors = PaletteFX.monPal(data, species) + if not colors then return nil end + local name = PaletteFX.monPalName(data, species) + -- prefix so GBC vs RED++ cache keys don't collide on shared names + if PaletteFX.usesGbcPack() then name = "redpp:" .. name end + return { name = name, colors = colors } end --- a named palette from data/generated/palettes.lua as a getImage pal +-- a named palette from the active COLORS pack as a getImage pal local function namedPalette(data, name) - local p = data.palettes - local colors = p and p.palettes[name] - return colors and { name = name, colors = colors } or nil + local PaletteFX = require("src.render.PaletteFX") + local colors = PaletteFX.pal(data, name) + if not colors then return nil end + local key = name + if PaletteFX.usesGbcPack() then key = "redpp:" .. name end + return { name = key, colors = colors } end -- The battle-BGP fade variant of a pic (AnimationFlashScreen and the @@ -264,8 +270,10 @@ function BattleState:speciesSprite(species, isPlayerSide) if not def then return nil end local PaletteFX = require("src.render.PaletteFX") local colors = PaletteFX.monPal(self.data, species, true) + local name = "GRAYMON" + if PaletteFX.usesGbcPack() then name = "redpp:GRAYMON" end return getImage(isPlayerSide and def.spriteBack or def.spriteFront, - colors and { name = "GRAYMON", colors = colors } or nil, + colors and { name = name, colors = colors } or nil, def.trueColor) end @@ -414,6 +422,7 @@ end function BattleState.newTrainer(game, oppClass, partyIndex) local self = newBattle(game) self.kind = "trainer" + self.oppClass = oppClass self.trainer = game.data.trainers[oppClass] assert(self.trainer, "unknown trainer class " .. tostring(oppClass)) self.enemyAIMods = self.trainer.aiMods @@ -2558,6 +2567,22 @@ function BattleState:learnMove(mon, moveId) end) end +-- Map the battle was fought on (overworld wins; save.player.map is fallback). +function BattleState.currentMapId(self) + local game = self.game + local ow = game and game.overworld + if ow and ow.map then return ow.map.id end + local player = game and game.save and game.save.player + return player and player.map +end + +-- pret HandlePlayerBlackOut: OPP_RIVAL1 in OAKS_LAB prints Rival1WinText +-- and returns without blacking out. OaksLabRivalEndBattleScript then heals. +function BattleState.isOaksLabStarterRival(self) + return self.oppClass == "OPP_RIVAL1" + and BattleState.currentMapId(self) == "OAKS_LAB" +end + function BattleState:playerMonFainted() local nextMon = Party.firstHealthy(self.game.save.party) -- Being out of useable POKéMON blacks you out even when the battle was @@ -2570,9 +2595,20 @@ function BattleState:playerMonFainted() -- aborts with "no healthy party"), and it is not reachable in pokered: -- HandlePlayerMonFainted runs the player-side check on its own, so -- losing your last mon always blacks you out whatever the enemy did. + -- Exception: the Oak's Lab starter rival (HandlePlayerBlackOut). if not nextMon and self.result ~= "lose" then - self:sayNext(("%s is out of\nuseable POKéMON!"):format(self.game.save.player.name)) - self:sayNext(("%s blacked\nout!"):format(self.game.save.player.name)) + if self.oppClass == "OPP_RIVAL1" then + local TextBox = require("src.render.TextBox") + local raw = (self.data.text and self.data.text._Rival1WinText) + or "{RIVAL}: Yeah! Am\nI great or what?" + self:sayNext(TextBox.substitute(self.game, raw)) + end + -- Oak's Lab starter rival: Rival1WinText only (no blackout lines). + -- Any other wipe, including Route 22 RIVAL1, still blacks out. + if not BattleState.isOaksLabStarterRival(self) then + self:sayNext(("%s is out of\nuseable POKéMON!"):format(self.game.save.player.name)) + self:sayNext(("%s blacked\nout!"):format(self.game.save.player.name)) + end self.result = "lose" self.afterQueue = "finish" return @@ -3037,11 +3073,13 @@ function BattleState:finish() return end -- Invariant: a battle can never hand the overworld a party with nothing - -- healthy in it. afterBattle only revives and warps to the heal point on - -- "lose", so any other result here strands the player at 0 HP with no way - -- back -- an unrecoverable state, not merely a wrong one. playerMonFainted - -- is the path that should have caught this; if we land here it did not, so - -- say so rather than silently papering over it. + -- healthy in it -- except the Oak's Lab starter rival, where pret skips + -- the blackout and OaksLabRivalEndBattleScript HealParty's immediately. + -- afterBattle only revives and warps to the heal point on a normal + -- "lose", so any other result here strands the player at 0 HP with no + -- way back -- an unrecoverable state, not merely a wrong one. + -- playerMonFainted is the path that should have caught this; if we land + -- here it did not, so say so rather than silently papering over it. if self.result ~= "lose" and not Party.firstHealthy(self.game.save.party) then Logger.warn("battle finished %s with no healthy party; forcing blackout", tostring(self.result)) @@ -3364,9 +3402,10 @@ function BattleState:colorMode() if self.colorFxReady == nil then local ready = false local g = love and love.graphics + local PaletteFX = require("src.render.PaletteFX") if g and g.newCanvas and g.setScissor and g.setShader and g.getCanvas - and love.image and self.data.palettes - and require("src.render.PaletteFX").shader() then + and love.image and PaletteFX.pack(self.data) + and PaletteFX.shader() then local ok1, bg = pcall(g.newCanvas, 160, 144) local ok2, wv = pcall(g.newCanvas, 160, 144) if ok1 and ok2 and bg and wv then @@ -3385,9 +3424,10 @@ end -- PAL_MEWMON (= MonsterPalettes[0]) while a side still shows its -- trainer/back pic (the species bytes are 0 then). function BattleState:sgbBattlePals() - local pals = self.data.palettes and self.data.palettes.palettes - if not pals then return nil end local PaletteFX = require("src.render.PaletteFX") + local pack = PaletteFX.pack(self.data) + local pals = pack and pack.palettes + if not pals then return nil end local function bar(b) if not b then return pals.GREENBAR end local hp = b.shownHP or b.mon.hp @@ -3395,8 +3435,7 @@ function BattleState:sgbBattlePals() end local function mon(b, placeholder) if placeholder or not b then return pals.MEWMON or pals.GREENBAR end - local name = self.data.palettes.pokemon[b.mon.species] - return pals[name] or pals.MEWMON + return PaletteFX.monPal(self.data, b.mon.species) or pals.MEWMON end return { [0] = bar(self.player), diff --git a/src/render/HudTiles.lua b/src/render/HudTiles.lua index 6c3299c8..c10fad8f 100644 --- a/src/render/HudTiles.lua +++ b/src/render/HudTiles.lua @@ -86,10 +86,11 @@ function HudTiles.drawHPBar(data, tx, ty, mon, barType) px = math.max(1, math.floor(mon.hp * 48 / mon.stats.hp)) end local tint - local pals = data.palettes - if pals then - local name = px >= 27 and "GREENBAR" or px >= 10 and "YELLOWBAR" or "REDBAR" - local c = pals.palettes[name][3] -- GB color 2 is the fill shade + local PaletteFX = require("src.render.PaletteFX") + local name = px >= 27 and "GREENBAR" or px >= 10 and "YELLOWBAR" or "REDBAR" + local colors = PaletteFX.pal(data, name) + if colors then + local c = colors[3] -- GB color 2 is the fill shade -- the fill pixels are the 2/3-gray shade; divide so they land on -- the palette color exactly (the black outline stays black) tint = { math.min(1, c[1] / 170), math.min(1, c[2] / 170), diff --git a/src/render/PaletteFX.lua b/src/render/PaletteFX.lua index 54a1575a..445eec20 100644 --- a/src/render/PaletteFX.lua +++ b/src/render/PaletteFX.lua @@ -5,17 +5,20 @@ -- then drawn once per zone through a shader that remaps the four DMG -- shades to that zone's palette. -- --- Port display option: COLORS (GBC / OG / OG INV / GBC INV / CLASSIC) +-- Port display option: COLORS (GBC / RED++ / OG / OG INV / GBC INV / CLASSIC) -- transforms every zone's palette at send time via effectiveColors. +-- RED++ swaps the named-palette pack for pokered-gbc SuperPalettes +-- (data/palettes_gbc.lua), including per-species mon colors. local PaletteFX = {} local shader -- false = unavailable (headless / no shader support) +local gbcPack -- false = missing; nil = not loaded yet -- Cycle order matches OptionsMenu / hotkey 2 -PaletteFX.MODES = { "gbc", "og", "og_inv", "gbc_inv", "classic" } +PaletteFX.MODES = { "gbc", "redpp", "og", "og_inv", "gbc_inv", "classic" } PaletteFX.MODE_LABELS = { - gbc = "GBC", og = "OG", og_inv = "OG INV", + gbc = "GBC", redpp = "RED++", og = "OG", og_inv = "OG INV", gbc_inv = "GBC INV", classic = "CLASSIC", } PaletteFX.mode = "gbc" @@ -124,22 +127,73 @@ function PaletteFX.whole(colors) return PaletteFX.zone(colors, 0, 0, 19, 17) end --- named palette from data/generated/palettes.lua (nil on stale builds) +-- Red++ / pokered-gbc SuperPalette pack (committed; optional if absent). +function PaletteFX.gbcPack() + if gbcPack == nil then + local ok, pack = pcall(require, "data.palettes_gbc") + gbcPack = ok and pack or false + end + return gbcPack or nil +end + +function PaletteFX.usesGbcPack(mode) + mode = mode or PaletteFX.mode + return mode == "redpp" +end + +-- Active named-palette table for COLORS: RED++ uses data/palettes_gbc.lua, +-- everything else uses the ROM-imported data.palettes. +function PaletteFX.pack(data) + if PaletteFX.usesGbcPack() then + local g = PaletteFX.gbcPack() + if g then return g end + end + return data and data.palettes or nil +end + +-- named palette from the active pack (nil on stale builds / missing name). +-- RED++ falls back to the ROM pack for names the gbc table omits (rare). function PaletteFX.pal(data, name) - local p = data.palettes - return p and p.palettes[name] or nil + local p = PaletteFX.pack(data) + local c = p and p.palettes[name] + if c then return c end + if PaletteFX.usesGbcPack() and data and data.palettes then + return data.palettes.palettes[name] + end + return nil end -- the species' palette (data/pokemon/palettes.asm), MEWMON for unknowns. -- transformed forces PAL_GRAYMON (Ditto's palette) regardless of species -- (engine/gfx/palettes.asm DeterminePaletteID: bit TRANSFORMED, a; a -- Transformed mon's pic is tinted gray, not the copied species' own --- SGB color). +-- SGB color). RED++ uses per-species pals from mon_palettes.asm. function PaletteFX.monPal(data, species, transformed) - local p = data.palettes + local p = PaletteFX.pack(data) if not p then return nil end - if transformed then return p.palettes.GRAYMON end - return p.palettes[p.pokemon[species] or "MEWMON"] + if transformed then + return p.palettes.GRAYMON + or (data and data.palettes and data.palettes.palettes.GRAYMON) + end + local name = p.pokemon[species] or "MEWMON" + local c = p.palettes[name] + if c then return c end + if PaletteFX.usesGbcPack() and data and data.palettes then + name = data.palettes.pokemon[species] or "MEWMON" + return data.palettes.palettes[name] + end + return nil +end + +-- palette name a species currently resolves to (for image-cache keys) +function PaletteFX.monPalName(data, species, transformed) + if transformed then return "GRAYMON" end + local p = PaletteFX.pack(data) + if p and p.pokemon[species] then return p.pokemon[species] end + if data and data.palettes and data.palettes.pokemon[species] then + return data.palettes.pokemon[species] + end + return "MEWMON" end -- GetHealthBarColor (home/palettes.asm) on the standard 48px bar @@ -173,13 +227,21 @@ function PaletteFX.permute(colors, map) end function PaletteFX.setMode(mode) + local prev = PaletteFX.mode + local ok = false for _, m in ipairs(PaletteFX.MODES) do if m == mode then PaletteFX.mode = mode - return + ok = true + break end end - PaletteFX.mode = "gbc" + if not ok then PaletteFX.mode = "gbc" end + -- battle pics bake the active pack into ImageData; drop the cache when + -- the pack (or any COLORS mode) changes so the next draw re-tints + if prev ~= PaletteFX.mode then + pcall(function() require("src.battle.BattleState").invalidate() end) + end end function PaletteFX.cycleMode() @@ -188,7 +250,7 @@ function PaletteFX.cycleMode() for i, m in ipairs(PaletteFX.MODES) do if m == cur then idx = i; break end end - PaletteFX.mode = PaletteFX.MODES[idx % #PaletteFX.MODES + 1] + PaletteFX.setMode(PaletteFX.MODES[idx % #PaletteFX.MODES + 1]) return PaletteFX.mode end @@ -202,7 +264,7 @@ end -- When a state exposes no SGB zones but COLORS needs a forced palette -- (OG / OG INV / CLASSIC), invent a whole-screen zone so the shade-remap --- shader still runs. GBC / GBC INV leave nil alone (raw DMG canvas). +-- shader still runs. GBC / RED++ / GBC INV leave nil alone (raw DMG canvas). function PaletteFX.ensureZones(zones) if zones and zones[1] then return zones end local mode = PaletteFX.mode or "gbc" @@ -213,6 +275,8 @@ function PaletteFX.ensureZones(zones) end -- Transform a 4-color palette for the active COLORS display mode. +-- GBC and RED++ pass the zone colors through (RED++ already swapped the +-- pack in pal/monPal); OG* / CLASSIC replace; GBC INV permutes shades. function PaletteFX.effectiveColors(c) if not c then return nil end local mode = PaletteFX.mode or "gbc" diff --git a/src/script/Commands.lua b/src/script/Commands.lua index 3918edff..e12cadc1 100644 --- a/src/script/Commands.lua +++ b/src/script/Commands.lua @@ -225,7 +225,7 @@ function Commands.start_battle(ctx, kind, a, b) ctx.lastBattleResult = result ctx.lastCheck = result == "win" if ctx.overworld then - ctx.overworld:afterBattle(result) + ctx.overworld:afterBattle(result, battle) end runner:resume() end diff --git a/src/world/OverworldController.lua b/src/world/OverworldController.lua index 6e840b25..fb7de260 100644 --- a/src/world/OverworldController.lua +++ b/src/world/OverworldController.lua @@ -1031,7 +1031,7 @@ function OverworldState:goFishing(rod) if Game.save.safari and Map.inRegion(self.map.def, "SAFARI", "SAFARI_ZONE") then battle:makeSafari(Game.save.safari) end - battle.onFinish = function(result) self:afterBattle(result) end + battle.onFinish = function(result) self:afterBattle(result, battle) end self:pushBattle(battle) end)) end)) @@ -1687,7 +1687,7 @@ function OverworldState:talkTo(npc) if e == npc then table.remove(self.entities, i) break end end end - self:afterBattle(result) + self:afterBattle(result, battle) unfreeze() end self:pushBattle(battle) @@ -2005,7 +2005,7 @@ function OverworldState:engageTrainer(npc, onDone) end self:checkVictoryRewards(d.trainerClass, d.trainerParty) local after = function() - self:afterBattle(result) + self:afterBattle(result, battle) if onDone then onDone() end end if wonText then @@ -2014,7 +2014,7 @@ function OverworldState:engageTrainer(npc, onDone) after() end else - self:afterBattle(result) + self:afterBattle(result, battle) if onDone then onDone() end end end @@ -2381,7 +2381,7 @@ function OverworldState:onStepComplete() if Game.save.safari and Map.inRegion(self.map.def, "SAFARI", "SAFARI_ZONE") then battle:makeSafari(Game.save.safari) end - battle.onFinish = function(result) self:afterBattle(result) end + battle.onFinish = function(result) self:afterBattle(result, battle) end self:pushBattle(battle) return end @@ -2714,7 +2714,9 @@ function OverworldState:safariGameOver(text) end -- Blackouts return to the last heal point; evolutions run after battles. -function OverworldState:afterBattle(result) +-- battle is optional; when given, Oak's Lab OPP_RIVAL1 losses skip the +-- blackout (pret HandlePlayerBlackOut) so the map script can HealParty. +function OverworldState:afterBattle(result, battle) local lead = Game.save.party[1] Logger.info("battle over: %s (lead %s %d/%d)", tostring(result), lead and lead.species or "-", lead and lead.hp or 0, @@ -2724,6 +2726,13 @@ function OverworldState:afterBattle(result) Evolution.checkParty(Game) end if result == "lose" then + local oaksLabRival = battle and battle.oppClass == "OPP_RIVAL1" + and self.map and self.map.id == "OAKS_LAB" + if oaksLabRival then + -- stay in the lab; OaksLabRivalEndBattleScript heals and continues + evolutions() + return + end -- blackout: revive the party at the last heal point; half the -- money is lost (like the original) local Pokemon = require("src.pokemon.Pokemon") diff --git a/tests/mod_graphics_tests.lua b/tests/mod_graphics_tests.lua index 4a119255..f672469e 100644 --- a/tests/mod_graphics_tests.lua +++ b/tests/mod_graphics_tests.lua @@ -598,6 +598,23 @@ check(PaletteFX.monPal(palData, "TESTMON") == monPalette, check(PaletteFX.monPal(palData, "UNKNOWN") == nil, "an unmapped species falls through to MEWMON (absent here)") +-- RED++ pack: per-species SuperPalettes from data/palettes_gbc.lua +local prevMode = PaletteFX.mode +PaletteFX.setMode("redpp") +check(PaletteFX.usesGbcPack(), "redpp mode selects the gbc pack") +local gbc = PaletteFX.gbcPack() +check(gbc ~= nil and gbc.palettes.BULBASAUR ~= nil, + "data/palettes_gbc.lua ships per-species pals") +check(PaletteFX.monPalName({ palettes = nil }, "BULBASAUR") == "BULBASAUR", + "RED++ monPalName resolves to the species palette id") +check(PaletteFX.monPal({ palettes = nil }, "BULBASAUR") == gbc.palettes.BULBASAUR, + "RED++ monPal reads the species colors without a ROM pack") +check(PaletteFX.pal({ palettes = nil }, "ROUTE") == gbc.palettes.ROUTE, + "RED++ still has ROUTE (aliased from VIRIDIAN)") +check(PaletteFX.effectiveColors(gbc.palettes.MEWMON) == gbc.palettes.MEWMON, + "RED++ passes zone colors through like GBC") +PaletteFX.setMode(prevMode) + -- ------- the transitions registry local transitions = Registry.new("transitions", Schemas.REGISTRIES.transitions) diff --git a/tests/parity_oaks_lab_rival_loss.lua b/tests/parity_oaks_lab_rival_loss.lua new file mode 100644 index 00000000..d05c69a9 --- /dev/null +++ b/tests/parity_oaks_lab_rival_loss.lua @@ -0,0 +1,67 @@ +-- Parity: losing the Oak's Lab starter rival must not black out. +-- pret HandlePlayerBlackOut special-cases OPP_RIVAL1 on OAKS_LAB: +-- Rival1WinText only, no PlayerBlackedOutText, no warp / half-money. +-- OaksLabRivalEndBattleScript then HealParty and continues either way. +-- Self-contained; run via `luajit tests/parity_oaks_lab_rival_loss.lua`. +package.path = "./?.lua;./?/init.lua;" .. package.path +if not _G.love then _G.love = require("tests.love_stub") end +local BattleState = require("src.battle.BattleState") +local S = require("tests.harness").suite("parity oaks lab rival loss") +local check, eq = S.check, S.eq + +local function saidBlackout(b) + for _, m in ipairs(b.said) do + if tostring(m):find("blacked") then return true end + end + return false +end + +local function saidRivalTaunt(b) + for _, m in ipairs(b.said) do + if tostring(m):find("great or what") then return true end + end + return false +end + +local function rivalBattle(mapId) + return { + kind = "trainer", + oppClass = "OPP_RIVAL1", + result = nil, + afterQueue = nil, + said = {}, + data = { + text = { _Rival1WinText = "{RIVAL}: Yeah! Am\nI great or what?" }, + }, + game = { + save = { + party = { { species = "SQUIRTLE", hp = 0, stats = { hp = 20 } } }, + player = { name = "RED", rival = "BLUE", map = mapId }, + }, + overworld = { map = { id = mapId } }, + }, + sayNext = function(self, m) self.said[#self.said + 1] = m end, + say = function(self, m) self.said[#self.said + 1] = m end, + } +end + +do + local b = rivalBattle("OAKS_LAB") + BattleState.playerMonFainted(b) + eq(b.result, "lose", "lab rival wipe is still a loss") + check(saidRivalTaunt(b), "lab rival wipe shows Rival1WinText") + check(not saidBlackout(b), "lab rival wipe does not say blacked out") + check(BattleState.isOaksLabStarterRival(b), "oaks-lab starter-rival detector") +end + +do + local b = rivalBattle("ROUTE_22") + BattleState.playerMonFainted(b) + eq(b.result, "lose", "route-22 rival wipe is a loss") + check(saidRivalTaunt(b), "route-22 rival still shows Rival1WinText") + check(saidBlackout(b), "route-22 rival still blacks out") + check(not BattleState.isOaksLabStarterRival(b), + "route-22 is not the oaks-lab special case") +end + +S.finish() diff --git a/tools/extract/palettes.py b/tools/extract/palettes.py index 385a3209..9be7d694 100644 --- a/tools/extract/palettes.py +++ b/tools/extract/palettes.py @@ -1,6 +1,6 @@ """Extract the Super Game Boy colorization palettes. -Sources: +Sources (vanilla pokered): data/sgb/sgb_palettes.asm SuperPalettes: 4 colors per PAL_* entry, 5-bit RGB (IF DEF(_RED) variants are used; this is a Red port) @@ -8,17 +8,27 @@ Sources: in Pokédex order with species names in the line comments +Sources (pokered-gbc / Red++ SuperPalettes, optional COLORS mode): + data/super_palettes.asm multi-line RGB + ; 0xNN: PAL_NAME comments; + includes per-species pals under GEN_2_GRAPHICS + data/mon_palettes.asm MonsterPalettes: GEN_2 per-species PAL_* ids + Output: data/generated/palettes.lua palettes[NAME] = { {r,g,b} x4 } with 8-bit components, color 0 first pokemon[SPECIES] = NAME (PAL_ prefix stripped) +Output: data/palettes_gbc.lua (committed; not wiped by ROM import) + same shape, plus per-species palette entries (BULBASAUR, …) + The HP bar fill is GB color 2 of PAL_GREENBAR / PAL_YELLOWBAR / PAL_REDBAR; the thresholds live in home/palettes.asm GetHealthBarColor (>= 27 pixels green, >= 10 yellow, else red). """ +import argparse import os import re +import sys from . import util @@ -28,6 +38,11 @@ def _scale5(v): return round(int(v) * 255 / 31) +def _rgb8(nums12): + return [[_scale5(nums12[i]), _scale5(nums12[i + 1]), _scale5(nums12[i + 2])] + for i in range(0, 12, 3)] + + def _read_raw(path): """Raw lines WITH comments (palette / species names live in them).""" with open(path, encoding="utf-8") as f: @@ -54,8 +69,7 @@ def extract(pokered, out_dir): if len(nums) != 12: util.die(f"sgb_palettes.asm:{lineno}: expected 12 components, got {len(nums)}") name = m.group(2) - palettes[name] = [[_scale5(nums[i]), _scale5(nums[i + 1]), _scale5(nums[i + 2])] - for i in range(0, 12, 3)] + palettes[name] = _rgb8(nums) order.append(name) # ---- MonsterPalettes ------------------------------------------------- @@ -91,3 +105,157 @@ def extract(pokered, out_dir): header="SGB colorization: 4 8-bit RGB colors per palette (color 0\n" "first) and the per-species palette assignment.") return palettes, mon_pals + + +def _parse_gbc_super_palettes(path): + """pokered-gbc data/super_palettes.asm: ; 0xNN: PAL_NAME then 4x RGB lines.""" + palettes = {} + order = [] + pending = None + buf = [] + for lineno, line in _read_raw(path): + s = line.strip() + m = re.match(r";\s*0x[0-9a-fA-F]+:\s*PAL_(\w+)", s) + if m: + pending = m.group(1) + buf = [] + continue + m = re.match(r"RGB\s+([\d,\s]+)", s) + if not m or not pending: + continue + nums = [n for n in re.split(r"[,\s]+", m.group(1).strip()) if n] + buf.extend(nums) + if len(buf) < 12: + continue + if len(buf) != 12: + util.die(f"{path}:{lineno}: expected 12 components for PAL_{pending}, " + f"got {len(buf)}") + palettes[pending] = _rgb8(buf) + order.append(pending) + pending = None + buf = [] + if pending: + util.die(f"{path}: incomplete palette PAL_{pending}") + return palettes, order + + +def _parse_gbc_monster_palettes(path): + """GEN_2_GRAPHICS MonsterPalettes paired with ELSE-branch species comments.""" + lines = _read_raw(path) + # species order from the vanilla ELSE comments (dex order + MISSINGNO) + species_order = [] + in_else = False + for _, line in lines: + s = line.strip() + if s.startswith("ELSE"): + in_else = True + continue + if s.startswith("ENDC"): + break + if not in_else: + continue + m = re.match(r"db\s+PAL_\w+\s*;\s*(\w+)", s) + if m: + species_order.append(m.group(1)) + + gen2_pals = [] + in_gen2 = False + for lineno, line in lines: + s = line.strip() + if s.startswith("MonsterPalettes:"): + continue + if s.startswith("IF GEN_2_GRAPHICS"): + in_gen2 = True + continue + if s.startswith("ELSE") or s.startswith("TrainerPalettes:"): + break + if not in_gen2: + continue + m = re.match(r"db\s+PAL_(\w+)", s) + if m: + gen2_pals.append(m.group(1)) + + if len(species_order) != len(gen2_pals): + util.die(f"{path}: GEN_2 MonsterPalettes ({len(gen2_pals)}) != " + f"ELSE species comments ({len(species_order)})") + mon_pals = {} + for species, pal in zip(species_order, gen2_pals): + if species != "MISSINGNO": + mon_pals[species] = pal + return mon_pals + + +def extract_gbc(pokered_gbc, out_path): + """Build the Red++ / pokered-gbc SuperPalette pack used by COLORS=RED++.""" + super_path = os.path.join(pokered_gbc, "data/super_palettes.asm") + mon_path = os.path.join(pokered_gbc, "data/mon_palettes.asm") + if not os.path.isfile(super_path): + util.die(f"missing {super_path}") + if not os.path.isfile(mon_path): + util.die(f"missing {mon_path}") + + palettes, order = _parse_gbc_super_palettes(super_path) + # pret spelling vs Red++ British spelling + if "GREYMON" in palettes and "GRAYMON" not in palettes: + palettes["GRAYMON"] = palettes["GREYMON"] + order.append("GRAYMON") + # Overworld still asks for ROUTE / PALLET; Red++ dropped those SGB + # entries (color/data handles overworld). Alias to closest town pals. + if "ROUTE" not in palettes and "VIRIDIAN" in palettes: + palettes["ROUTE"] = palettes["VIRIDIAN"] + order.append("ROUTE") + if "PALLET" not in palettes and "PEWTER" in palettes: + palettes["PALLET"] = palettes["PEWTER"] + order.append("PALLET") + + mon_pals = _parse_gbc_monster_palettes(mon_path) + if len(mon_pals) != 151: + util.die(f"mon_palettes.asm: parsed {len(mon_pals)} species (want 151)") + for species, pal in mon_pals.items(): + if pal not in palettes: + util.die(f"mon_palettes.asm: unknown palette PAL_{pal} for {species}") + for name in ("MEWMON", "GREENBAR", "YELLOWBAR", "REDBAR", "GRAYMON"): + if name not in palettes: + util.die(f"super_palettes.asm: PAL_{name} missing") + + # write_lua stamps "Generated by tools/build_data.py"; keep that header + # but point the source field at the gbc tree. + util.write_lua( + out_path, + {"source": "pokered-gbc data/super_palettes.asm + data/mon_palettes.asm", + "palettes": palettes, + "order": order, + "pokemon": mon_pals}, + header="Red++ / pokered-gbc SuperPalettes (COLORS=RED++): 4 8-bit RGB\n" + "colors per palette (color 0 first), including per-species\n" + "pals and the GEN_2 MonsterPalettes assignment.") + return palettes, mon_pals + + +def main(argv=None): + parser = argparse.ArgumentParser(description=__doc__.split("\n\n")[0]) + sub = parser.add_subparsers(dest="cmd", required=True) + + p_van = sub.add_parser("vanilla", help="extract pret/pokered SGB palettes") + p_van.add_argument("--pokered", required=True) + p_van.add_argument("--out-dir", default="data/generated") + + p_gbc = sub.add_parser("gbc", help="extract pokered-gbc SuperPalettes") + p_gbc.add_argument("--pokered-gbc", required=True) + p_gbc.add_argument("--out", default="data/palettes_gbc.lua") + + args = parser.parse_args(argv) + if args.cmd == "vanilla": + extract(args.pokered, args.out_dir) + else: + extract_gbc(args.pokered_gbc, args.out) + return 0 + + +if __name__ == "__main__": + # python3 -m extract.palettes (from tools/) or python3 tools/extract/palettes.py + if __package__ is None: + sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..")) + __package__ = "extract" + from extract import util as util # noqa: F811 + raise SystemExit(main()) diff --git a/tools/rom_manifest.json b/tools/rom_manifest.json index bde4501c..b64064dc 100644 --- a/tools/rom_manifest.json +++ b/tools/rom_manifest.json @@ -42219,6 +42219,12 @@ } }, "MtMoonB2F": { + "1": { + "after": "_MtMoonB2FSuperNerdTheresAPokemonLabText", + "battle": "_MtMoonB2FSuperNerdTheyreBothMineText", + "event": "EVENT_BEAT_MT_MOON_3_SUPER_NERD", + "won": "_MtMoonB2fSuperNerdEachTakeOneText" + }, "2": { "after": "_MtMoonB2FRocket1AfterBattleText", "battle": "_MtMoonB2FRocket1BattleText",