mirror of
https://github.com/bryanthaboi/gen1recomp.git
synced 2026-08-18 03:35:56 +02:00
CLOSES #1181, CLOSES #1212, CLOSES #1214, CLOSES #1224, CLOSES #1230, CLOSES #1249, CLOSES #1271, CLOSES #1272, CLOSES #1273, CLOSES #1298, CLOSES #1305, CLOSES #1307, CLOSES #1318, CLOSES #1328, CLOSES #1330, CLOSES #1331, CLOSES #1333, CLOSES #1334, CLOSES #1335, CLOSES #1340, CLOSES #1345, CLOSES #1346, CLOSES #1360, CLOSES #1362
This commit is contained in:
+9
-2
@@ -730,7 +730,7 @@ function Game2:usePartyItem(itemId)
|
||||
local row = ItemEffects.RESTORE_PP[itemId] or {}
|
||||
if row.each or mon.isEgg then
|
||||
self.stack:pop()
|
||||
finish(ItemEffects.usePpItem(itemId, mon), mon)
|
||||
finish(ItemEffects.usePpItem(itemId, mon, nil, self.data), mon)
|
||||
return
|
||||
end
|
||||
Screens.push(self, "Gen2MoveDeleter", {
|
||||
@@ -740,7 +740,7 @@ function Game2:usePartyItem(itemId)
|
||||
onChoose = function(slot)
|
||||
self.stack:pop() -- the move list
|
||||
self.stack:pop() -- the party list
|
||||
finish(ItemEffects.usePpItem(itemId, mon, slot), mon)
|
||||
finish(ItemEffects.usePpItem(itemId, mon, slot, self.data), mon)
|
||||
end,
|
||||
})
|
||||
end,
|
||||
@@ -888,6 +888,12 @@ function Game2:load()
|
||||
self.data.items = loadGenerated("data/generated/items.lua") or {}
|
||||
self.data.moves = loadGenerated("data/generated/moves.lua") or {}
|
||||
self.data.type_chart = loadGenerated("data/generated/type_chart.lua") or {}
|
||||
-- data/types/type_matchups.asm:112-116: the rows after the `db -2` marker
|
||||
-- apply by default; Foresight is what cuts the table short at it.
|
||||
local chart = self.data.type_chart
|
||||
for _, row in ipairs(chart.foresightMatchups or {}) do
|
||||
chart.matchups[#chart.matchups + 1] = row
|
||||
end
|
||||
-- The `held_items` registry's merge target: ItemAttributes' last two columns
|
||||
-- as their own table, so a mod can give an item a held behaviour without
|
||||
-- owning the whole item record. Built BEFORE mods:load so the registry
|
||||
@@ -1949,6 +1955,7 @@ function Game2:applyOptions()
|
||||
touchControls = options.touchControls,
|
||||
haptics = options.haptics,
|
||||
})
|
||||
require("src.core.VideoMode").applyOptions(options)
|
||||
local GBCFX = require("src.render.GBCFX")
|
||||
if GBCFX.applyOptions(options) and self.save then
|
||||
-- applyOptions returns true when it had to clear an unsupported level.
|
||||
|
||||
+38
-7
@@ -130,12 +130,23 @@ local SPECIAL = {
|
||||
evolution = "Music_SafariZone",
|
||||
}
|
||||
|
||||
-- SpecialMapMusic (pokegold home/audio.asm:397)
|
||||
local SPECIAL_GEN2 = {
|
||||
surf = "Music_Surf",
|
||||
bike = "Music_Bicycle",
|
||||
evolution = "Music_Evolution",
|
||||
}
|
||||
|
||||
-- the label a scene role resolves to; call sites keep their own presence
|
||||
-- guard on the resolved label
|
||||
function Music.special(data, key)
|
||||
local special = data and data.audio and data.audio.special
|
||||
local label = special and special[key]
|
||||
if label ~= nil then return label end
|
||||
if data and data.audio and data.audio.generation == 2
|
||||
and SPECIAL_GEN2[key] ~= nil then
|
||||
return SPECIAL_GEN2[key]
|
||||
end
|
||||
return SPECIAL[key]
|
||||
end
|
||||
|
||||
@@ -192,6 +203,12 @@ local function startSong(data, def, wantLoop)
|
||||
return nil, nil, nil, "no chip program and no file"
|
||||
end
|
||||
|
||||
-- Music_MeetRival_Ch{1,2,3}_AlternateStart (audio/alternate_tempo.asm:7)
|
||||
local RIVAL_ALT_START = {
|
||||
redblue = { 0x71a2, 0x721d, 0x72b5 },
|
||||
yellow = { 0x7075, 0x70f0, 0x7188 },
|
||||
}
|
||||
|
||||
-- the single choke point every song choice passes through, so one hook
|
||||
-- covers map themes, battle themes, jingles and scene music
|
||||
local function selectSong(song, ctx)
|
||||
@@ -219,8 +236,17 @@ function Music.play(data, song, loop, ctx)
|
||||
local start = ctx and ctx.start or nil
|
||||
-- a hook may silence the cue outright, or swap in a label the dedupe
|
||||
-- below has to compare against
|
||||
if not song or (song == state.current and tempo == state.tempo
|
||||
and start == state.start) then return end
|
||||
if not song then return end
|
||||
if song == state.current and tempo == state.tempo
|
||||
and start == state.start then
|
||||
-- ..(home/audio.asm ln 65)
|
||||
if state.fade and state.fade.pending then
|
||||
state.fade = nil
|
||||
applyVolume(state.source)
|
||||
applyVolume(state.loopSource)
|
||||
end
|
||||
return
|
||||
end
|
||||
local def = songDef(data, song)
|
||||
if not def or state.failed[song] then return end
|
||||
|
||||
@@ -247,10 +273,12 @@ function Music.play(data, song, loop, ctx)
|
||||
and def.bank == 2 and def.address == 17050 then
|
||||
local started = {}
|
||||
for key, value in pairs(def) do started[key] = value end
|
||||
local alt = require("src.core.GameVersion").isYellow()
|
||||
and RIVAL_ALT_START.yellow or RIVAL_ALT_START.redblue
|
||||
started.startChannels = {
|
||||
{ number = 1, address = 0x71a2 },
|
||||
{ number = 2, address = 0x721d },
|
||||
{ number = 3, address = 0x72b5 },
|
||||
{ number = 1, address = alt[1] },
|
||||
{ number = 2, address = alt[2] },
|
||||
{ number = 3, address = alt[3] },
|
||||
}
|
||||
def = started
|
||||
end
|
||||
@@ -340,9 +368,12 @@ end
|
||||
|
||||
Music.MAP_FADE = 10
|
||||
|
||||
-- the song a map should currently play, honoring the bike/surf overrides
|
||||
-- the song a map should currently play, honoring the bike/surf overrides;
|
||||
-- Gen 2 has no outdoor gate (pokegold home/audio.asm:437)
|
||||
local function effectiveMapSong(data, song)
|
||||
if not song or not outdoorSongs(data)[song] then return song end
|
||||
if not song then return song end
|
||||
local gen2 = data and data.audio and data.audio.generation == 2
|
||||
if not gen2 and not outdoorSongs(data)[song] then return song end
|
||||
if state.onBike then
|
||||
local bike = Music.special(data, "bike")
|
||||
if bike and songDef(data, bike) then return bike end
|
||||
|
||||
@@ -58,6 +58,12 @@ ItemEffects.RESTORE_PP = {
|
||||
MAX_ELIXER = { amount = "all", each = true },
|
||||
}
|
||||
|
||||
-- engine/items/item_effects.asm:1245 StatExpItemPointerOffsets.
|
||||
ItemEffects.VITAMIN = {
|
||||
HP_UP = "hp", PROTEIN = "attack", IRON = "defense",
|
||||
CARBOS = "speed", CALCIUM = "special",
|
||||
}
|
||||
|
||||
-- EnergypowderEnergyRootCommon / HealPowderEffect: the herb items charge
|
||||
-- happiness for tasting bitter on top of their heal.
|
||||
local BITTER = {
|
||||
@@ -70,6 +76,9 @@ ItemEffects.TEXT_NO_EFFECT = "It won't have any\neffect."
|
||||
ItemEffects.TEXT_CANT_USE_ON_EGG = "That can't be used\non an EGG."
|
||||
-- _PPRestoredText (data/text/common_3.asm).
|
||||
ItemEffects.TEXT_PP_RESTORED = "PP was restored."
|
||||
-- _PPIsMaxedOutText / _PPsIncreasedText (data/text/common_3.asm).
|
||||
ItemEffects.TEXT_PP_MAXED = "%s's PP\nis maxed out."
|
||||
ItemEffects.TEXT_PP_INCREASED = "%s's PP\nincreased."
|
||||
|
||||
-- PrintPartyMenuActionText's .MenuActionTexts (engine/pokemon/party_menu.asm),
|
||||
-- keyed by the class GetItemHealingAction resolves. Each is the two rows the
|
||||
@@ -235,6 +244,33 @@ local function rareCandy(mon, data)
|
||||
}
|
||||
end
|
||||
|
||||
-- engine/items/item_effects.asm:1216 StatStrings.
|
||||
local VITAMIN_LABEL = {
|
||||
hp = "HEALTH", attack = "ATTACK", defense = "DEFENSE",
|
||||
speed = "SPEED", special = "SPECIAL",
|
||||
}
|
||||
|
||||
-- engine/items/item_effects.asm:1149 VitaminEffect.
|
||||
local function vitamin(itemId, mon, data)
|
||||
local stat = ItemEffects.VITAMIN[itemId]
|
||||
mon.statExp = mon.statExp or Mon.newStatExp()
|
||||
local cur = mon.statExp[stat] or 0
|
||||
if cur >= 25600 then
|
||||
return { used = false, text = ItemEffects.TEXT_NO_EFFECT }
|
||||
end
|
||||
mon.statExp[stat] = math.min(Mon.MAX_STAT_EXP, cur + 2560)
|
||||
local def = data and data.pokemon and data.pokemon[mon.species]
|
||||
if def and def.baseStats then
|
||||
mon.stats = Mon.stats(def.baseStats, mon.dvs, mon.level, mon.statExp)
|
||||
mon.maxHp = mon.stats.hp
|
||||
end
|
||||
Happiness.change(mon, "USEDITEM")
|
||||
return {
|
||||
used = true,
|
||||
text = ("%s's\n%s rose."):format(monName(mon), VITAMIN_LABEL[stat]),
|
||||
}
|
||||
end
|
||||
|
||||
-- --------------------------------------------------------- held attributes
|
||||
--
|
||||
-- The `held_items` registry (src/mods/Schemas.lua), which is the last two
|
||||
@@ -341,11 +377,8 @@ function ItemEffects.recordFor(itemId, data)
|
||||
return (merged and merged[itemId]) or ItemEffects.RECORDS[itemId]
|
||||
end
|
||||
|
||||
-- Which family a PACK item runs on a party mon, or nil for anything whose
|
||||
-- ITEMMENU_PARTY behaviour is not ported (vitamins, PP UP, evolution stones).
|
||||
-- FULL_RESTORE classifies as "heal"; its full-HP status arm lives inside the
|
||||
-- record's own `use` the way FullRestoreEffect keeps both halves in one
|
||||
-- routine.
|
||||
-- Which family a PACK item runs on a party mon, or nil for an id with no
|
||||
-- item_effects record (engine/items/pack.asm UseItem, ITEMMENU_PARTY arm).
|
||||
function ItemEffects.partyAction(itemId, data)
|
||||
local record = ItemEffects.recordFor(itemId, data)
|
||||
return record and record.action or nil
|
||||
@@ -446,6 +479,36 @@ for itemId, row in pairs(ItemEffects.RESTORE_PP) do
|
||||
end)
|
||||
end
|
||||
|
||||
-- engine/items/item_effects.asm:2320 RestorePPEffect's PP_UP arm.
|
||||
record("PP_UP", "pp", function(ctx)
|
||||
local move = (ctx.mon.moves or {})[ctx.slot]
|
||||
if type(move) ~= "table" or not move.id then
|
||||
return { used = false, text = ItemEffects.TEXT_NO_EFFECT }
|
||||
end
|
||||
local row = ((ctx.data and ctx.data.moves) or {})[move.id]
|
||||
local name = (row and row.name) or move.id
|
||||
-- constants/pokemon_data_constants.asm:216 PP_UP_MASK.
|
||||
if move.id == "SKETCH" or (move.ppUps or 0) >= 3 then
|
||||
return { used = false, text = ItemEffects.TEXT_PP_MAXED:format(name) }
|
||||
end
|
||||
local base = (row and row.pp) or move.maxPp
|
||||
if not base then
|
||||
return { used = false, text = ItemEffects.TEXT_PP_MAXED:format(name) }
|
||||
end
|
||||
-- engine/items/item_effects.asm:2736 ComputeMaxPP.
|
||||
local bonus = math.min(math.floor(base / 5), 7)
|
||||
move.ppUps = (move.ppUps or 0) + 1
|
||||
move.maxPp = base + move.ppUps * bonus
|
||||
move.pp = (move.pp or 0) + bonus
|
||||
return { used = true, text = ItemEffects.TEXT_PP_INCREASED:format(name) }
|
||||
end)
|
||||
|
||||
for itemId in pairs(ItemEffects.VITAMIN) do
|
||||
record(itemId, "vitamin", function(ctx)
|
||||
return vitamin(ctx.item, ctx.mon, ctx.data)
|
||||
end)
|
||||
end
|
||||
|
||||
record("RARE_CANDY", "candy", function(ctx)
|
||||
return rareCandy(ctx.mon, ctx.data)
|
||||
end)
|
||||
|
||||
@@ -272,6 +272,7 @@ Save.DEFAULT_OPTIONS = {
|
||||
-- Game Boy. The Gen 1 save's equivalent key is `colors` (SGB packs), which
|
||||
-- means something different, hence the different name.
|
||||
color = "gbc",
|
||||
videoMode = "windowed",
|
||||
musicVol = 7, -- 0-7, like the GB's NR50 master volume
|
||||
sfxVol = 7, -- 0-7
|
||||
musicFilter = 0, -- low-pass steps, 0 = off
|
||||
|
||||
Reference in New Issue
Block a user