Commit Graph

601 Commits

Author SHA1 Message Date
bryanthaboi 580449b8df Merge pull request #1538 from castdrian/ios-audio-stuff
fix(ios): recover audio after route changes
2026-08-18 17:02:10 -04:00
bryanthaboi 794a5fc6cb Merge pull request #1540 from 1Jamie/fix/grass-standing-overdraw
fixes #1537 #1528  also fixes feet layering of gold with grass. Unifies gen1/gen2 grass layering into a single system
2026-08-18 16:55:39 -04:00
1jamie 286988a1e3 fixes #1537 #1528
also fixes feet layering of gold with grass. Unifies gen1/gen2 grass layering into a single system
2026-08-18 15:37:27 -05:00
Adrian Castro 48a3140a28 fix(ios): recover audio after route changes 2026-08-18 22:36:11 +02:00
bryanthaboi f7bdaa81f8 true color sprites shouldnt show in non color modes 2026-08-18 16:06:15 -04:00
bryanthaboi a1ab5e2cff title screen on gold going the wrong dir 2026-08-18 15:54:48 -04:00
bryanthaboi 99806ead25 Potentially CLOSES #1310, CLOSES #1005, CLOSES #1291 2026-08-18 15:49:47 -04:00
1jamie def967a8f8 fix(render): replace per-entity grass overdraw with full-screen cell pass
The previous drawCellBottom calls fired only for cells containing a
tracked entity.  While walking this worked acceptably because the
sprite's sub-pixel tween kept the visual overlap plausible, but while
standing still the sprite is pixel-aligned with the cell and the opaque
leaf-edge pixels in the grass bottom row paint over the player's feet.

This change removes the per-entity isGrassCell checks and replaces them
with a single post-sprite pass that overdraws every visible grass cell.

TileRenderer:
- ensureWindow now builds grassCells (all paths) and grassBatch (DMG/SGB
  shader path) alongside winBatch during the existing tile scan loop.
  A grassSeen table deduplicates cells so each cx/cy pair is only
  recorded once despite having two bottom-row tiles.
- drawGrassOverdraw: DMG/SGB draws the grassBatch under color0KeyShader
  in one call; GBC iterates grassCells and calls drawCellBottomRaw per
  cell (pre-keyed images can't share a SpriteBatch).
- markGrassOverdrawRedraw: iterates grassCells and calls
  markCellBottomRedraw for the post-zone OBP-replay pass (GBC only).
- releaseBatches cleans up grassBatch and grassCells.

OverworldController (flat path):
- Entity loop draws sprites only; grass overdraw fires once after the
  loop via drawGrassOverdraw + markGrassOverdrawRedraw.

OverworldController (tilt path):
- Grass cells are injected into the billboard sort queue keyed on the
  world-pixel foot of each cell's bottom tile row (cy*16+16), so they
  depth-sort correctly against entities at different y positions.  Each
  grass cell billboards via drawCellBottomRaw inside the upright pass.

Fixes: standing-in-tall-grass feet overdraw (Gen 2 confirmed, Gen 1
improved); NPCs and Pikachu follower in grass benefit automatically.
Parity test: tests/parity_grass_seam.lua 10/10, engine 228/228.
2026-08-18 13:23:10 -05:00
bryanthaboi 7583ba8729 CLOSES #1471 2026-08-18 14:19:42 -04:00
bryanthaboi abf95ce1c4 CLOSES #1519 2026-08-18 11:43:23 -04:00
bryanthaboi bd1046f398 CLOSES #1393 2026-08-18 11:29:50 -04:00
bryanthaboi d5ad830fb8 CLOSES #1418 2026-08-18 10:49:04 -04:00
bryanthaboi c2c7fdafcf CLOSES #1430 2026-08-18 10:36:44 -04:00
bryanthaboi 25ec896545 fix(audio): do not stop the move sfx source the replay just restarted
The takeover stop in Sound.playMove moved after the new source starts in
cfa84063, but an equal-id replay reuses the cached source, so the stop
killed the sound it had just restarted.
2026-08-18 10:14:44 -04:00
bryanthaboi 8240205254 ingested 2026-08-18 09:51:22 -04:00
bryanthaboi 55616fc03d CLOSES #1390 2026-08-18 09:20:07 -04:00
bryanthaboi 675971068e CLOSES #1503 2026-08-18 09:16:04 -04:00
bryanthaboi cfa8406306 CLOSES #1508 2026-08-18 04:52:00 -04:00
bryanthaboi 7b1e796c48 CLOSES #1496 2026-08-17 22:52:33 -04:00
bryanthaboi 4e1ab1879b updated skin studio 2026-08-17 20:39:53 -04:00
bryanthaboi 917735a41c Merge branch 'dev' of https://github.com/bryanthaboi/gen1recomp into dev 2026-08-17 20:15:40 -04:00
bryanthaboi c877ea80a7 importer for skins now w file picker 2026-08-17 20:15:39 -04:00
bryanthaboi 5bc6036735 Merge pull request #1420 from anxiousintrovert/fix/required-import-platform-pickers
Fix required imports on Android legacy picker bridges
2026-08-17 19:58:13 -04:00
anxiousintrovert 4f8739c029 Fix required imports on legacy Android picker bridges 2026-08-17 18:35:25 -05:00
AverageConsumer c655217120 feat(gen2): expose stock ball catch previews 2026-08-17 23:00:38 +02:00
bryanthaboi 22bcd95da1 Update LauncherView.lua 2026-08-17 14:03:07 -04:00
bryanthaboi 8c9af95598 CLOSES #1396, CLOSES #1398, CLOSES #1400, CLOSES #1401, CLOSES #1406, CLOSES #1407, CLOSES #1411, CLOSES #1413, CLOSES #1415, CLOSES #1416, CLOSES #1417, CLOSES #1419, CLOSES #1421, CLOSES #1422, CLOSES #1423, CLOSES #1424, CLOSES #1425, CLOSES #1427, CLOSES #1428, CLOSES #1429, CLOSES #1431, CLOSES #1432, CLOSES #1433, CLOSES #1435, CLOSES #1437, CLOSES #1440, CLOSES #1441, CLOSES #1442, CLOSES #1443, CLOSES #1444, CLOSES #1447, CLOSES #1449, CLOSES #1456, CLOSES #1461, CLOSES #1464, CLOSES #1465, CLOSES #1466, CLOSES #1468, CLOSES #1469, CLOSES #1470 2026-08-17 10:27:14 -04:00
bryanthaboi 45519ad550 CLOSES #1396, CLOSES #1398, CLOSES #1400, CLOSES #1401, CLOSES #1406, CLOSES #1407, CLOSES #1411, CLOSES #1413, CLOSES #1415, CLOSES #1416, CLOSES #1417, CLOSES #1419, CLOSES #1421, CLOSES #1422, CLOSES #1423, CLOSES #1424, CLOSES #1425, CLOSES #1427, CLOSES #1428, CLOSES #1429, CLOSES #1431, CLOSES #1432, CLOSES #1433, CLOSES #1435, CLOSES #1437, CLOSES #1440, CLOSES #1441, CLOSES #1442, CLOSES #1443, CLOSES #1447, CLOSES #1449, CLOSES #1456, CLOSES #1464, CLOSES #1465, CLOSES #1468, CLOSES #1469, CLOSES #1470 2026-08-17 10:15:06 -04:00
bryanthaboi 3cca70608f skins and skin studio 2026-08-17 06:47:33 -04:00
bryanthaboi a5b674f9da Merge pull request #1454 from ShaneMcGovernIE/feat/mod-compute-permission 2026-08-16 22:05:10 -04:00
bryanthaboi c8bd205d0c Merge pull request #1378 from syybott/experiment/fixed-extended-world-alignment 2026-08-16 22:04:28 -04:00
AverageConsumer 360b692963 android: route asymmetric companion displays 2026-08-17 03:00:05 +02:00
bryanthaboi 051040371f Merge pull request #1439 from thibautbus/fix/stat-rise-message-translation 2026-08-16 20:43:54 -04:00
bryanthaboi c5ff95edcf Merge pull request #1450 from thibautbus/fix/translate-clock-and-day-of-week 2026-08-16 20:43:36 -04:00
bryanthaboi d6627eda4c Merge pull request #1426 from thibautbus/fix/manager-state-draw-color 2026-08-16 20:36:13 -04:00
bryanthaboi 6e28cd5dca Merge pull request #1434 from sanjinpepic/upstream-fixes 2026-08-16 20:34:55 -04:00
bryanthaboi 08ddb882af Merge pull request #1448 from AverageConsumer/codex/android-companion-contract 2026-08-16 20:33:22 -04:00
bryanthaboi 2f6f094559 Merge pull request #1446 from 1Jamie/feat/launcher-fixes-and-patch-notes 2026-08-16 20:33:11 -04:00
James Hall 73f561e256 Merge branch 'bryanthaboi:dev' into experiment/fixed-extended-world-alignment 2026-08-16 19:30:19 -05:00
Shane McGovern b739fa76c0 mods: gate love.thread behind a compute permission
Threads open a fresh Lua state with a full standard library, so they
stayed blocked wholesale. PotatoVoxel's prebuilder wants to run its
pure geometry phase on worker threads; the mod declares the new
"compute" permission and the sandbox hands out love.thread only
then. The worker runs the mod's own source (source-only, like every
mod file) and receives data only through channels.
2026-08-16 23:45:09 +01:00
Shane McGovern 0b00faf38e feat(android): add httpPost bridge for mod.postLog log sends
Android ships no curl and the JNI bridge was GET-only, so mod.postLog
failed there with 'no POST transport on this platform' (HostShell.lua).
Add the mirror of httpDownload: GameActivity.httpPost (https-only,
hand-followed redirects re-POSTing the body, one-way), the JNI bridge
with the same old-APK-skew tolerance, the love.system.httpPost binding,
and the HostShell arm that rides it when curl is absent. The body
crosses the JNI as raw bytes (jbyteArray) so a log ring with arbitrary
UTF-8 cannot corrupt through modified-UTF-8 jstring conversion.
2026-08-16 22:22:38 +01:00
thibautbus b20b1370ab Reset ManagerState's draw color after Font.drawBox
Font.drawBox leaves the caller's color at white; every other screen
resets to black right after calling it, but ManagerState.lua's draw()
and drawOverlay() never did. That's invisible on the vanilla tile font
(tile glyphs are black-on-transparent regardless of color) but renders
fully invisible white-on-white text once a mod's TTF font is active.
2026-08-16 23:15:59 +02:00
thibautbus 9423337bcc Make the rose! messages' stat name harvestable by the mod catalog tool
Strings(stat:upper()) is a dynamic argument -- tools/modkit.py's
STRINGS_CALL harvester only matches a literal string right after
Strings(/Strings.source(, so it can't discover "ATTACK"/"DEFENSE"/etc.
from these call sites. Translation coverage happened to still work
only because the same literals are independently harvested from
unrelated call sites (MoveEffects.lua's STAT_LABEL, BattleState.lua's
literal Strings("ATTACK") calls) -- real but fragile, found in review.

Reuse the codebase's existing pattern for exactly this situation
(MoveEffects.lua's STAT_LABEL): a local table built at require time
with Strings.source(...), which the harvester can see, resolved to a
translated label at use time with Strings(TABLE[key]). Adds one such
table to ItemEffects.lua (covering its X-item and vitamin call sites,
including "hp") and one to TrainerAI.lua.
2026-08-16 23:15:18 +02:00
thibautbus c280119d03 Translate Gold's Light Screen / Reflect rose! messages
Same theme as the RBY fix, found while checking whether Gold had the
same gap: EFFECT_LIGHT_SCREEN and EFFECT_REFLECT built their "'s
SPCL.DEF/DEFENSE rose!" message by raw string concatenation, bypassing
Strings() entirely -- unlike most other messages in this file (e.g.
"%s\nused %s!" a few lines up), which already go through it.

Wrap the whole message template in Strings(), matching that existing
pattern; the substituted name still comes from monName() as before.

Gold's gen2/Battle.lua has many more messages built the same
unwrapped way (fainted!, learned..., missed!, and so on) -- that is
the much larger "Battle messages" gap already tracked separately and
deliberately left out of this change.
2026-08-16 23:15:18 +02:00
thibautbus 24d0c6528d Translate the stat name in RBY's X-item and vitamin rose! messages
Both the player-side and AI-trainer stat-rise messages (X ATTACK/
DEFENSE/etc. and the vitamins) passed the raised stat's name as a raw
uppercase Lua string (stat:upper()), bypassing Strings() entirely, so
it always rendered in English regardless of the active language even
though the surrounding sentence template was already translated.

Wrap the substituted stat name in Strings() at every call site
(src/inventory/ItemEffects.lua's two player-side messages and
src/battle/TrainerAI.lua's AI-trainer X-item message, found in
review), reusing the same "ATTACK"/"DEFENSE"/"SPEED"/"SPECIAL"/"HP"
keys SummaryMenu.lua's stat labels already look up the same way.
2026-08-16 23:15:18 +02:00
AverageConsumer 1fc34da2a9 android: extend secondary display presentation 2026-08-16 22:57:10 +02:00
sanjinpepic 70b9def0b0 Make Mon.syncIdentity's shiny recompute monotonic
syncIdentity unconditionally recomputed mon.shiny from the mon's DVs,
overwriting whatever was there. It is wired into refreshStats, which
SummaryMenu.new calls on every menu open, so a forced shiny -- Mon.new's
opts.shiny path, DVs that do not themselves read as shiny -- got
un-shinied the moment the summary screen opened, even though opts.shiny
already wins over shiny.roll at construction for exactly this case (a
scripted shiny is the cart overriding the roll, not a roll to be
hooked).

mon.shiny now only ever gets PROMOTED by the DV check, never demoted:
`mon.shiny or Mon.isShiny(...)`. A naturally shiny mon and a plain one
are unaffected -- the DV check still runs and still decides the first
time -- and a mon whose DVs are edited to justify shininess later still
promotes normally; only an already-true shiny stops being able to flip
back to false on a later refresh.
2026-08-16 22:48:34 +02:00
sanjinpepic d03d2af5f8 Pass data through to ItemEffects.partyAction for Gen 2 pack items
Both call sites -- Game2:usePartyItem (the field pack) and
BattleState:useItem (the battle pack) -- asked ItemEffects.partyAction
for an item's family with no `data` argument, even though every other
call in the same functions (useOnMon, usePpItem, applyPartyItem) passed
it through correctly. partyAction resolves through recordFor, which
reads data.gen2ItemEffects when given a dataset and falls back to the
module's own built-in RECORDS table when not -- so with no data, a
mod's own item_effects record was invisible and every mod-defined Gen 2
field or battle item resolved to a nil action, falling straight through
to "isn't going to help here" / "isn't going to help here" without ever
opening the party picker.

Both now pass the live dataset (self.data on Game2, self.game.data on
the battle screen) the same way their sibling calls already did.
2026-08-16 22:48:34 +02:00
sanjinpepic 455ff21aff Validate a map object's pokemon field against the pokemon registry
R.maps.objects was f.opt(f.list(f.any)): a static wild encounter's
species (OverworldController.lua's d.pokemon, handed straight to
BattleState.newWild) went completely unchecked at load time, unlike an
encounter slot's species. A typo'd or removed id sat in a loaded mod
and only surfaced as a crash the moment a player reached that object.

Objects share one array across every kind -- NPCs, signs, warps and
static encounters all coexist with no field the loader could use to
tell them apart ahead of time -- so a strict f.rec covering the whole
shape would reject every kind this schema does not enumerate. Added
f.partial, an open counterpart to f.rec: it type-checks (and, through
collectRefs, cross-reference-checks) only the fields it is given and
leaves everything else on the value alone, the same extensibility
f.rec already grants at a record's top level but nowhere further in.
R.maps.objects now types just `pokemon` through it, so a bad species
id is a load-time "unresolved reference" error instead of a runtime
crash, while an NPC object's sprite/movement/range/... fields -- never
named in this schema -- still pass through untouched.
2026-08-16 22:48:33 +02:00
sanjinpepic 2da2168dac Refuse a TM/HM on a species with no tmhm list instead of crashing
ItemEffects.use walked speciesDef.tmhm with a bare ipairs() to check
whether the species could learn the machine's move. A record with no
tmhm field at all -- a mod species that never set one, or any record
missing it for whatever reason -- hit ipairs(nil) and took the whole
game down on the first TM/HM use, rather than reaching the ordinary
"can't learn that move" refusal a species whose list simply omits the
move already gets.

An absent list now reads the same as an empty one: nothing to learn,
same refusal, same sound, same text.
2026-08-16 22:48:33 +02:00