mirror of
https://github.com/bryanthaboi/gen1recomp.git
synced 2026-08-20 20:50:21 +02:00
i did it for greg
This commit is contained in:
@@ -929,6 +929,10 @@ mod.content.sfx:register("SFX_MOD_CHIME", { file = "chime.ogg" })
|
|||||||
|
|
||||||
| field | type | required |
|
| field | type | required |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
|
| `anchorX` | number | no |
|
||||||
|
| `anchorY` | number | no |
|
||||||
|
| `frameHeight` | integer >= 1 | no |
|
||||||
|
| `frameWidth` | integer >= 1 | no |
|
||||||
| `frames` | integer >= 1 | yes |
|
| `frames` | integer >= 1 | yes |
|
||||||
| `id` | string | no |
|
| `id` | string | no |
|
||||||
| `image` | file path | yes |
|
| `image` | file path | yes |
|
||||||
@@ -1100,6 +1104,7 @@ mod.content.tokens:register("CLOCK", function(game) return "12" end)
|
|||||||
| `paletteSource` | string | no |
|
| `paletteSource` | string | no |
|
||||||
| `parties` | list of list of {level, species} | yes |
|
| `parties` | list of list of {level, species} | yes |
|
||||||
| `pic` | file path | no |
|
| `pic` | file path | no |
|
||||||
|
| `trueColor` | boolean | no |
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
mod.content.trainers:patch("OPP_BROCK", { baseMoney = 99 })
|
mod.content.trainers:patch("OPP_BROCK", { baseMoney = 99 })
|
||||||
@@ -1122,7 +1127,9 @@ do not.
|
|||||||
| `index` | integer 0..255 | no |
|
| `index` | integer 0..255 | no |
|
||||||
| `items` | list of items id | no |
|
| `items` | list of items id | no |
|
||||||
| `name` | string | yes |
|
| `name` | string | yes |
|
||||||
|
| `pic` | file path | no |
|
||||||
| `trainers` | list of {id?, index?, name, party, trainerType?} | yes |
|
| `trainers` | list of {id?, index?, name, party, trainerType?} | yes |
|
||||||
|
| `trueColor` | boolean | no |
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
mod.content.trainers:patch("BEAUTY", { baseMoney = 99 })
|
mod.content.trainers:patch("BEAUTY", { baseMoney = 99 })
|
||||||
|
|||||||
@@ -316,6 +316,27 @@ function BattleState.trainerPicPath(data, trainer, oppClass, partyIndex)
|
|||||||
return base and base.pic or nil
|
return base and base.pic or nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- trueColor on the trainer record, or on the basePic it reuses when the
|
||||||
|
-- subclass does not set the flag itself. Explicit false stays false.
|
||||||
|
function BattleState.trainerTrueColor(data, trainer)
|
||||||
|
if not trainer then return false end
|
||||||
|
if trainer.trueColor ~= nil then
|
||||||
|
return trainer.trueColor and true or false
|
||||||
|
end
|
||||||
|
local base = trainer.basePic and data and data.trainers
|
||||||
|
and data.trainers[trainer.basePic]
|
||||||
|
return (base and base.trueColor) and true or false
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Load a trainer frontpic through getImage so a trueColor portrait skips
|
||||||
|
-- the 4-shade quantize the same way a species pic does.
|
||||||
|
function BattleState.trainerSprite(data, trainer, oppClass, partyIndex)
|
||||||
|
return getImage(
|
||||||
|
BattleState.trainerPicPath(data, trainer, oppClass, partyIndex),
|
||||||
|
BattleState.trainerPalette(data, trainer),
|
||||||
|
BattleState.trainerTrueColor(data, trainer))
|
||||||
|
end
|
||||||
|
|
||||||
-- The battle-BGP fade variant of a pic (AnimationFlashScreen and the
|
-- The battle-BGP fade variant of a pic (AnimationFlashScreen and the
|
||||||
-- SetAnimationBGPalette effects remap the four BG shades; on the SGB
|
-- SetAnimationBGPalette effects remap the four BG shades; on the SGB
|
||||||
-- the colorizer then colors the REMAPPED shade, so a faded pic shows
|
-- the colorizer then colors the REMAPPED shade, so a faded pic shows
|
||||||
@@ -756,9 +777,8 @@ function BattleState.newTrainer(game, oppClass, partyIndex)
|
|||||||
-- MonsterPalettes[0] = PAL_MEWMON -- InitBattleCommon zeroes
|
-- MonsterPalettes[0] = PAL_MEWMON -- InitBattleCommon zeroes
|
||||||
-- wEnemyMonSpecies2 before the intro's SET_PAL_BATTLE
|
-- wEnemyMonSpecies2 before the intro's SET_PAL_BATTLE
|
||||||
-- (engine/battle/core.asm:6682, engine/gfx/palettes.asm SetPal_Battle)
|
-- (engine/battle/core.asm:6682, engine/gfx/palettes.asm SetPal_Battle)
|
||||||
self.trainerPic = getImage(
|
self.trainerPic = BattleState.trainerSprite(
|
||||||
BattleState.trainerPicPath(game.data, self.trainer, oppClass, partyIndex),
|
game.data, self.trainer, oppClass, partyIndex)
|
||||||
BattleState.trainerPalette(game.data, self.trainer))
|
|
||||||
self.introText = Strings("%s wants\nto fight!", self.trainer.name)
|
self.introText = Strings("%s wants\nto fight!", self.trainer.name)
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1797,7 +1797,8 @@ local function buildBattleState()
|
|||||||
"throwBall", "ballChain", "tossAnimFor", "ballFlicker", "ballMissMessage",
|
"throwBall", "ballChain", "tossAnimFor", "ballFlicker", "ballMissMessage",
|
||||||
"storeCaughtMon", "safariAction", "safariEnemyTurn", "drawBallRow",
|
"storeCaughtMon", "safariAction", "safariEnemyTurn", "drawBallRow",
|
||||||
"drawClassic", "isWideBattleLayout", "wideLayout", "bgMode", "uiSize",
|
"drawClassic", "isWideBattleLayout", "wideLayout", "bgMode", "uiSize",
|
||||||
"sgbPalettes", "trainerPalette", "trainerPicPath", "invalidate",
|
"sgbPalettes", "trainerPalette", "trainerPicPath", "trainerTrueColor",
|
||||||
|
"trainerSprite", "invalidate",
|
||||||
"imageBattleScale", "resolveBattleScale", "backPlacement",
|
"imageBattleScale", "resolveBattleScale", "backPlacement",
|
||||||
"frontPlacement", "StatBox", "enter", "exit",
|
"frontPlacement", "StatBox", "enter", "exit",
|
||||||
}) do
|
}) do
|
||||||
@@ -1884,7 +1885,8 @@ COVERAGE["src.battle.BattleState"] = {
|
|||||||
absent = "newWild newTrainer makeSafari makeGhost makeBattler resolveTurn "
|
absent = "newWild newTrainer makeSafari makeGhost makeBattler resolveTurn "
|
||||||
.. "computeDamage catchAttempt runRoll enter exit sgbPalettes "
|
.. "computeDamage catchAttempt runRoll enter exit sgbPalettes "
|
||||||
.. "isWideBattleLayout wideLayout bgMode uiSize letterboxWhite "
|
.. "isWideBattleLayout wideLayout bgMode uiSize letterboxWhite "
|
||||||
.. "holdsUIAnchors BG_WORLD_DIM trainerPalette trainerPicPath invalidate "
|
.. "holdsUIAnchors BG_WORLD_DIM trainerPalette trainerPicPath "
|
||||||
|
.. "trainerTrueColor trainerSprite invalidate "
|
||||||
.. "backPlacement frontPlacement StatBox drawClassic drawBallRow "
|
.. "backPlacement frontPlacement StatBox drawClassic drawBallRow "
|
||||||
.. "safariAction safariEnemyTurn throwBall storeCaughtMon field ruleset "
|
.. "safariAction safariEnemyTurn throwBall storeCaughtMon field ruleset "
|
||||||
.. "rng oppClass partyIndex aiUses introText dead",
|
.. "rng oppClass partyIndex aiUses introText dead",
|
||||||
|
|||||||
@@ -1017,6 +1017,9 @@ R.trainers = {
|
|||||||
index = f.opt(f.int(0, 255)),
|
index = f.opt(f.int(0, 255)),
|
||||||
-- unused vanilla classes ship without a pic, so it cannot be required
|
-- unused vanilla classes ship without a pic, so it cannot be required
|
||||||
pic = f.opt(f.path),
|
pic = f.opt(f.path),
|
||||||
|
-- Full-color portrait: skip the 4-shade SGB/GBC remap, same flag pokemon
|
||||||
|
-- and sprites already carry.
|
||||||
|
trueColor = f.opt(f.bool),
|
||||||
-- Optional Advanced-mode OBJ palette source for a custom trainer portrait.
|
-- Optional Advanced-mode OBJ palette source for a custom trainer portrait.
|
||||||
-- It follows the same ROM crosswalk form as sprites.paletteSource.
|
-- It follows the same ROM crosswalk form as sprites.paletteSource.
|
||||||
paletteSource = f.opt(f.str),
|
paletteSource = f.opt(f.str),
|
||||||
@@ -1068,6 +1071,11 @@ R.trainers = {
|
|||||||
gen2Fields = {
|
gen2Fields = {
|
||||||
id = f.opt(f.str), name = f.str,
|
id = f.opt(f.str), name = f.str,
|
||||||
index = f.opt(f.int(0, 255)),
|
index = f.opt(f.int(0, 255)),
|
||||||
|
-- class frontpic; when set, this wins over menu_gfx.battleHud.trainerPics
|
||||||
|
pic = f.opt(f.path),
|
||||||
|
-- Full-color portrait: skip the GBC 4-shade remap, same flag Gen 1
|
||||||
|
-- trainers and pokemon already carry.
|
||||||
|
trueColor = f.opt(f.bool),
|
||||||
baseMoney = f.opt(f.int(0)),
|
baseMoney = f.opt(f.int(0)),
|
||||||
-- the class's battle theme; Gen 1 spells the same idea `battleTheme`,
|
-- the class's battle theme; Gen 1 spells the same idea `battleTheme`,
|
||||||
-- but this is the extractor's own key and a strict rename would reject
|
-- but this is the extractor's own key and a strict rename would reject
|
||||||
|
|||||||
@@ -98,14 +98,14 @@ function OakSpeech.resolvePic(game, desc, speech)
|
|||||||
local t = desc.type
|
local t = desc.type
|
||||||
if t == "trainer" then
|
if t == "trainer" then
|
||||||
if speech and desc.id == "OPP_PROF_OAK" and speech.oakPic then
|
if speech and desc.id == "OPP_PROF_OAK" and speech.oakPic then
|
||||||
return speech.oakPic, false, false
|
return speech.oakPic, false, speech.oakTrueColor or false
|
||||||
end
|
end
|
||||||
if speech and desc.id == "OPP_RIVAL1" and speech.rivalPic then
|
if speech and desc.id == "OPP_RIVAL1" and speech.rivalPic then
|
||||||
return speech.rivalPic, false, false
|
return speech.rivalPic, false, speech.rivalTrueColor or false
|
||||||
end
|
end
|
||||||
local trainers = game.data.trainers or {}
|
local trainers = game.data.trainers or {}
|
||||||
local tr = trainers[desc.id]
|
local tr = trainers[desc.id]
|
||||||
return tryImage(tr and tr.pic), false, false
|
return tryImage(tr and tr.pic), false, tr and tr.trueColor or false
|
||||||
elseif t == "pokemon" then
|
elseif t == "pokemon" then
|
||||||
if speech and desc.id == speech.demoSpecies and speech.demoPic then
|
if speech and desc.id == speech.demoSpecies and speech.demoPic then
|
||||||
return speech.demoPic, desc.flip and true or false, speech.demoTrueColor
|
return speech.demoPic, desc.flip and true or false, speech.demoTrueColor
|
||||||
@@ -241,7 +241,11 @@ function OakSpeech.new(game, onDone)
|
|||||||
self.answers = {}
|
self.answers = {}
|
||||||
local trainers = game.data.trainers or {}
|
local trainers = game.data.trainers or {}
|
||||||
self.oakPic = tryImage(trainers.OPP_PROF_OAK and trainers.OPP_PROF_OAK.pic)
|
self.oakPic = tryImage(trainers.OPP_PROF_OAK and trainers.OPP_PROF_OAK.pic)
|
||||||
|
self.oakTrueColor = self.oakPic
|
||||||
|
and trainers.OPP_PROF_OAK and trainers.OPP_PROF_OAK.trueColor or false
|
||||||
self.rivalPic = tryImage(trainers.OPP_RIVAL1 and trainers.OPP_RIVAL1.pic)
|
self.rivalPic = tryImage(trainers.OPP_RIVAL1 and trainers.OPP_RIVAL1.pic)
|
||||||
|
self.rivalTrueColor = self.rivalPic
|
||||||
|
and trainers.OPP_RIVAL1 and trainers.OPP_RIVAL1.trueColor or false
|
||||||
local oakGfx = (game.data.field and game.data.field.oakSpeech) or {}
|
local oakGfx = (game.data.field and game.data.field.oakSpeech) or {}
|
||||||
self.cfg = oakGfx
|
self.cfg = oakGfx
|
||||||
-- the show-off mon and the name length cap come from data; the vanilla
|
-- the show-off mon and the name length cap come from data; the vanilla
|
||||||
|
|||||||
@@ -185,6 +185,19 @@ function BattleState:statusHUDVisible()
|
|||||||
self) ~= false
|
self) ~= false
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Class frontpic for the battle intro. A trainers-registry `pic` wins over
|
||||||
|
-- the extracted menu_gfx sheet; `trueColor` skips the GBC 4-shade remap.
|
||||||
|
-- Returns path, trueColor.
|
||||||
|
function BattleState.trainerArt(data, classId)
|
||||||
|
if not classId then return nil, false end
|
||||||
|
local classes = data and data.gen2Trainers and data.gen2Trainers.classes
|
||||||
|
local classDef = classes and classes[classId]
|
||||||
|
local hud = data and data.gen2MenuGfx and data.gen2MenuGfx.battleHud
|
||||||
|
local path = (classDef and classDef.pic)
|
||||||
|
or (hud and hud.trainerPics and hud.trainerPics[classId])
|
||||||
|
return path, (classDef and classDef.trueColor) and true or false
|
||||||
|
end
|
||||||
|
|
||||||
-- opts: battle (a Battle), onDone(outcome), save
|
-- opts: battle (a Battle), onDone(outcome), save
|
||||||
function BattleState.new(game, opts)
|
function BattleState.new(game, opts)
|
||||||
opts = opts or {}
|
opts = opts or {}
|
||||||
@@ -308,6 +321,7 @@ function BattleState.new(game, opts)
|
|||||||
-- pic is a cache asset, so an import made before the extractor grew that
|
-- pic is a cache asset, so an import made before the extractor grew that
|
||||||
-- stage has none and the mon stands in for the whole intro.
|
-- stage has none and the mon stands in for the whole intro.
|
||||||
self.showEnemyTrainer = false
|
self.showEnemyTrainer = false
|
||||||
|
self.enemyTrainerTrueColor = false
|
||||||
-- The CLASS CONSTANT (BUG_CATCHER), which is what both tables this looks the
|
-- The CLASS CONSTANT (BUG_CATCHER), which is what both tables this looks the
|
||||||
-- pic up in are keyed by: menu_gfx's trainerPics is written out of
|
-- pic up in are keyed by: menu_gfx's trainerPics is written out of
|
||||||
-- constants.trainerClassOrder, and palettes.trainers out of the same names.
|
-- constants.trainerClassOrder, and palettes.trainers out of the same names.
|
||||||
@@ -317,17 +331,19 @@ function BattleState.new(game, opts)
|
|||||||
-- no palette for every trainer the world starts, which is all of them.
|
-- no palette for every trainer the world starts, which is all of them.
|
||||||
-- `classId` is the trainers.lua key, i.e. the constant; `className` is the
|
-- `classId` is the trainers.lua key, i.e. the constant; `className` is the
|
||||||
-- DISPLAY name ("BUG CATCHER", with the space) and is not a key at all.
|
-- DISPLAY name ("BUG CATCHER", with the space) and is not a key at all.
|
||||||
|
-- A class record's own `pic` / `trueColor` (the trainers registry) wins
|
||||||
|
-- over the extracted sheet, so a mod can drop in full-color art.
|
||||||
local enemyTrainer = self.battle and self.battle.trainer
|
local enemyTrainer = self.battle and self.battle.trainer
|
||||||
self.enemyTrainerClass = enemyTrainer
|
self.enemyTrainerClass = enemyTrainer
|
||||||
and (enemyTrainer.classId or enemyTrainer.class)
|
and (enemyTrainer.classId or enemyTrainer.class)
|
||||||
local trainerPics = hudGfx and hudGfx.trainerPics
|
local trainerPath, trainerTrueColor =
|
||||||
local trainerPath = self.enemyTrainerClass and trainerPics
|
BattleState.trainerArt(data, self.enemyTrainerClass)
|
||||||
and trainerPics[self.enemyTrainerClass]
|
|
||||||
if trainerPath then
|
if trainerPath then
|
||||||
local ok, image = pcall(Assets.image, trainerPath)
|
local ok, image = pcall(Assets.image, trainerPath)
|
||||||
if ok and image then
|
if ok and image then
|
||||||
self.enemyTrainerImage = image
|
self.enemyTrainerImage = image
|
||||||
self.enemyTrainerPath = trainerPath
|
self.enemyTrainerPath = trainerPath
|
||||||
|
self.enemyTrainerTrueColor = trainerTrueColor and true or false
|
||||||
self.showEnemyTrainer = true
|
self.showEnemyTrainer = true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -588,7 +604,10 @@ function BattleState:drawPic(mon, back)
|
|||||||
-- slides it out (InitEnemyTrainer, engine/battle/core.asm:7848).
|
-- slides it out (InitEnemyTrainer, engine/battle/core.asm:7848).
|
||||||
local enemyTrainer = (not back) and self.showEnemyTrainer
|
local enemyTrainer = (not back) and self.showEnemyTrainer
|
||||||
and self.enemyTrainerImage
|
and self.enemyTrainerImage
|
||||||
if enemyTrainer then image, path = enemyTrainer, self.enemyTrainerPath end
|
if enemyTrainer then
|
||||||
|
image, path = enemyTrainer, self.enemyTrainerPath
|
||||||
|
trueColor = self.enemyTrainerTrueColor
|
||||||
|
end
|
||||||
if not image then return end
|
if not image then return end
|
||||||
local side = back and "player" or "enemy"
|
local side = back and "player" or "enemy"
|
||||||
local anim = self:animPicState(side)
|
local anim = self:animPicState(side)
|
||||||
|
|||||||
@@ -0,0 +1,92 @@
|
|||||||
|
-- trainers.trueColor: the same 4-shade opt-out pokemon and sprites already
|
||||||
|
-- carry, now on the trainers registry. ROM-free.
|
||||||
|
-- luajit tests/engine/trainer_true_color.lua
|
||||||
|
package.path = "./?.lua;./?/init.lua;" .. package.path
|
||||||
|
|
||||||
|
local T = require("tests.modkit")
|
||||||
|
local BattleState = require("src.battle.BattleState")
|
||||||
|
local Gen2Battle = require("src.ui.gen2.BattleState")
|
||||||
|
local Schemas = require("src.mods.Schemas")
|
||||||
|
local OakSpeech = require("src.ui.OakSpeech")
|
||||||
|
|
||||||
|
local spec = Schemas.REGISTRIES.trainers
|
||||||
|
T.check(spec.fields.trueColor ~= nil,
|
||||||
|
"Gen 1 trainers schema lists trueColor")
|
||||||
|
T.check(Schemas.check(spec, "trainers", "OPP_BROCK",
|
||||||
|
{ trueColor = true }, "patch"),
|
||||||
|
"a trueColor patch validates")
|
||||||
|
T.check(not Schemas.check(spec, "trainers", "OPP_BROCK",
|
||||||
|
{ trueColor = "yes" }, "patch"),
|
||||||
|
"trueColor rejects a non-boolean")
|
||||||
|
|
||||||
|
local gen2 = Schemas.shapeFor("trainers", spec, 2)
|
||||||
|
T.check(gen2.fields.trueColor ~= nil and gen2.fields.pic ~= nil,
|
||||||
|
"Gold trainers schema lists pic and trueColor")
|
||||||
|
T.check(Schemas.check(spec, "trainers", "BEAUTY",
|
||||||
|
{ pic = "mods/x/beauty.png", trueColor = true },
|
||||||
|
"patch", 2),
|
||||||
|
"a Gold pic+trueColor patch validates")
|
||||||
|
|
||||||
|
T.eq(BattleState.trainerTrueColor(nil, nil), false,
|
||||||
|
"no trainer is not trueColor")
|
||||||
|
T.eq(BattleState.trainerTrueColor(nil, { pic = "a.png" }), false,
|
||||||
|
"a vanilla portrait is not trueColor")
|
||||||
|
T.eq(BattleState.trainerTrueColor(nil, { trueColor = true }), true,
|
||||||
|
"the record's own flag wins")
|
||||||
|
T.eq(BattleState.trainerTrueColor(nil, { trueColor = false }), false,
|
||||||
|
"explicit false stays false")
|
||||||
|
|
||||||
|
local data = {
|
||||||
|
trainers = {
|
||||||
|
BASE = { pic = "base.png", trueColor = true },
|
||||||
|
VANILLA = { pic = "vanilla.png" },
|
||||||
|
},
|
||||||
|
}
|
||||||
|
T.eq(BattleState.trainerTrueColor(data, { basePic = "BASE" }), true,
|
||||||
|
"a basePic reuse inherits the base flag")
|
||||||
|
T.eq(BattleState.trainerTrueColor(data,
|
||||||
|
{ basePic = "BASE", trueColor = false }), false,
|
||||||
|
"an explicit false on the subclass beats the base")
|
||||||
|
T.eq(BattleState.trainerTrueColor(data, { basePic = "VANILLA" }), false,
|
||||||
|
"reusing a vanilla base stays unshaded-off")
|
||||||
|
|
||||||
|
local goldData = {
|
||||||
|
gen2Trainers = {
|
||||||
|
classes = {
|
||||||
|
BEAUTY = { pic = "mods/x/beauty.png", trueColor = true },
|
||||||
|
BUG_CATCHER = {},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
gen2MenuGfx = {
|
||||||
|
battleHud = {
|
||||||
|
trainerPics = {
|
||||||
|
BEAUTY = "assets/generated/trainers/beauty.png",
|
||||||
|
BUG_CATCHER = "assets/generated/trainers/bug_catcher.png",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
local beautyPath, beautyTc = Gen2Battle.trainerArt(goldData, "BEAUTY")
|
||||||
|
T.eq(beautyPath, "mods/x/beauty.png",
|
||||||
|
"a class pic wins over the extracted sheet")
|
||||||
|
T.eq(beautyTc, true, "and keeps trueColor")
|
||||||
|
local bugPath, bugTc = Gen2Battle.trainerArt(goldData, "BUG_CATCHER")
|
||||||
|
T.eq(bugPath, "assets/generated/trainers/bug_catcher.png",
|
||||||
|
"a class without pic keeps the extracted sheet")
|
||||||
|
T.eq(bugTc, false, "and is not trueColor")
|
||||||
|
T.eq(select(1, Gen2Battle.trainerArt(goldData, nil)), nil,
|
||||||
|
"no class is no pic")
|
||||||
|
|
||||||
|
local game = {
|
||||||
|
data = {
|
||||||
|
trainers = {
|
||||||
|
OPP_BROCK = { pic = "brock.png", trueColor = true },
|
||||||
|
OPP_PROF_OAK = { pic = "oak.png", trueColor = true },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
local _, _, oakTc = OakSpeech.resolvePic(game,
|
||||||
|
{ type = "trainer", id = "OPP_BROCK" })
|
||||||
|
T.eq(oakTc, true, "OakSpeech reports a trainer record's trueColor")
|
||||||
|
|
||||||
|
T.finish("trainer true color")
|
||||||
@@ -23,6 +23,7 @@ local MoveEffects = require("src.battle.MoveEffects")
|
|||||||
local Pokemon = require("src.pokemon.Pokemon")
|
local Pokemon = require("src.pokemon.Pokemon")
|
||||||
local Runtime = require("src.mods.Runtime")
|
local Runtime = require("src.mods.Runtime")
|
||||||
local SaveData = require("src.core.SaveData")
|
local SaveData = require("src.core.SaveData")
|
||||||
|
local Schemas = require("src.mods.Schemas")
|
||||||
local Status = require("src.battle.Status")
|
local Status = require("src.battle.Status")
|
||||||
local TrainerAI = require("src.battle.TrainerAI")
|
local TrainerAI = require("src.battle.TrainerAI")
|
||||||
local TurnOrder = require("src.battle.TurnOrder")
|
local TurnOrder = require("src.battle.TurnOrder")
|
||||||
@@ -346,6 +347,20 @@ do
|
|||||||
check(BattleState.trainerPicPath(Data, { basePic = "OPP_ENGINEER" })
|
check(BattleState.trainerPicPath(Data, { basePic = "OPP_ENGINEER" })
|
||||||
== Data.trainers.OPP_ENGINEER.pic,
|
== Data.trainers.OPP_ENGINEER.pic,
|
||||||
"a custom trainer can reuse a base trainer portrait by id")
|
"a custom trainer can reuse a base trainer portrait by id")
|
||||||
|
check(BattleState.trainerTrueColor(Data, { trueColor = true }) == true,
|
||||||
|
"a trainer record's trueColor flag is readable")
|
||||||
|
check(BattleState.trainerTrueColor(Data, { trueColor = false }) == false,
|
||||||
|
"explicit false stays false")
|
||||||
|
check(BattleState.trainerTrueColor(Data, { basePic = "OPP_ENGINEER" })
|
||||||
|
== false,
|
||||||
|
"a vanilla base portrait is not trueColor")
|
||||||
|
check(Schemas.check(Schemas.REGISTRIES.trainers, "trainers", "OPP_BROCK",
|
||||||
|
{ trueColor = true }, "patch"),
|
||||||
|
"a trueColor trainers patch validates against the catalog schema")
|
||||||
|
check(Schemas.check(Schemas.REGISTRIES.trainers, "trainers", "BEAUTY",
|
||||||
|
{ pic = "mods/x/beauty.png", trueColor = true },
|
||||||
|
"patch", 2),
|
||||||
|
"a Gold trainers patch can carry pic and trueColor")
|
||||||
end
|
end
|
||||||
|
|
||||||
do
|
do
|
||||||
|
|||||||
@@ -370,6 +370,32 @@ check(math.abs(r - 0.4) < 1e-6 and math.abs(g - 0.7) < 1e-6
|
|||||||
and math.abs(b - 0.9) < 1e-6,
|
and math.abs(b - 0.9) < 1e-6,
|
||||||
"a trueColor pic keeps a pixel no 4-shade palette contains")
|
"a trueColor pic keeps a pixel no 4-shade palette contains")
|
||||||
|
|
||||||
|
-- trainers.trueColor is the same opt-out on a class portrait
|
||||||
|
BattleState.invalidate()
|
||||||
|
local trainerPicData = {
|
||||||
|
trainers = {
|
||||||
|
SHADED = { pic = "assets/generated/battle/front/shaded.png" },
|
||||||
|
FULLCOLOR = { pic = "assets/generated/battle/front/full.png",
|
||||||
|
trueColor = true },
|
||||||
|
REUSED = { basePic = "FULLCOLOR" },
|
||||||
|
},
|
||||||
|
palettes = { palettes = { MEWMON = monPalette }, pokemon = {} },
|
||||||
|
}
|
||||||
|
local shadedTrainer = BattleState.trainerSprite(trainerPicData,
|
||||||
|
trainerPicData.trainers.SHADED)
|
||||||
|
r, g, b = shadedTrainer.data:getPixel(0, 0)
|
||||||
|
check(r == 0 and g == 0 and b == 1,
|
||||||
|
"a 4-shade trainer pic is palette-quantized onto its shade bucket")
|
||||||
|
local fullTrainer = BattleState.trainerSprite(trainerPicData,
|
||||||
|
trainerPicData.trainers.FULLCOLOR)
|
||||||
|
r, g, b = fullTrainer.data:getPixel(0, 0)
|
||||||
|
check(math.abs(r - 0.4) < 1e-6 and math.abs(g - 0.7) < 1e-6
|
||||||
|
and math.abs(b - 0.9) < 1e-6,
|
||||||
|
"a trueColor trainer pic keeps a pixel no 4-shade palette contains")
|
||||||
|
check(BattleState.trainerTrueColor(trainerPicData,
|
||||||
|
trainerPicData.trainers.REUSED) == true,
|
||||||
|
"a basePic reuse inherits the base portrait's trueColor flag")
|
||||||
|
|
||||||
-- ------- trueColor: the colors == false zone sentinel
|
-- ------- trueColor: the colors == false zone sentinel
|
||||||
|
|
||||||
check(PaletteFX.zone(nil, 0, 0, 1, 1) == nil, "nil colors is still no zone")
|
check(PaletteFX.zone(nil, 0, 0, 1, 1) == nil, "nil colors is still no zone")
|
||||||
|
|||||||
Reference in New Issue
Block a user