PalEdit 1.0 - Updates for Palworld 1.0 - Addition of some Requested Community Features#211
PalEdit 1.0 - Updates for Palworld 1.0 - Addition of some Requested Community Features#211TheMysticTurtle wants to merge 82 commits into
Conversation
Save format: - Read/write 1.0 Oodle-compressed (PlM, 0x31) saves; preserve the load-time save_type on save so round-trips keep the original format - Support GlobalPalStorage.sav (1.0 Global Palbox): occupied slots of SaveParameterArray are wrapped into the Level.sav entry shape and edited by reference under a "Global Palbox" pseudo-player - Fix pals misdetected as player characters (1.0 writes IsPlayer=False on every pal; check the value, not key presence) - Survive missing/unreadable Players/*.sav when loading world saves Game data (regenerated from oMaN-Rod/palworld-save-pal dumps via the new update_data.py; psp sources cached in gitignored psp_data_cache/): - 155 new species entries incl. all 1.0 pals; rebalanced movesets, scaling and work suitabilities for existing pals - 82 new attacks, 320 new passives (incl. new rank-5 tier), localized names for en-GB/it-IT/zh-CN - Icons for new pals from the paldb CDN; variant entities aliased to their base pal's icon - Level cap 65 -> 80; 9th skill_col entry so rank-5 passives don't crash the rating colors; vendor palworld_save_tools extracted (tracked) instead of zip-only Verified end-to-end against a copy of a real 1.0 Global Palbox: unmodified GVAS write is byte-identical; level/IV edits persist through save and re-parse. See CLAUDE.md for working notes. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Passive and equipped-attack slots open a searchable picker (type to filter, arrows/Enter/double-click); rows show passive rating and attack power. The picker applies exact codes, so two passives that share a localized name (e.g. "Swift") stay distinct. Add a Tools > "Legal abilities only" toggle (on by default): passives are limited to wild-rollable plus species innates, attacks to a pal's own moves, and equipped abilities are always shown. update_data.py now emits Rollable, InnatePassives and per-attack Exclusive species lists. Verified on Global Palbox copies: the legality toggle works both ways and edits survive a save/reload round-trip. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…pecies list cleanup Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
One-time hygiene commit: stops Windows checkouts from flagging phantom modifications (e.g. the egg-info files) on every session. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Plumbing shared by the upcoming browser/filter features: - DeckIndex (psp pal_deck_index): >= 0 means the species is catchable and appears in the Paldeck; bosses/NPC variants carry -1/-2 - TowerBoss (psp is_tower_boss) marks tower-boss entries - PalInfo attaches both to PalObject (_deck_index, _tower_boss) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Before the first write to a given save file in a session, copy the current on-disk file into a PalEdit-backups/ folder beside it, named <save>.<timestamp>.bak. Subsequent saves of the same file in the same session skip re-backup (the tracked set in self._session_backups), so the backup always reflects the pre-edit state, not an intermediate one. If the backup cannot be written (disk full, permissions), the save is aborted with an error dialog rather than risking the only good copy. Verified on scratchpad copies: exactly one backup per file per session, backup bytes equal the original save, and a simulated backup failure leaves the save untouched. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Double-clicking the name label above the portrait opens a rename prompt for the selected pal. PalInfo.SetNickname writes both NickName and, on Palworld 1.0 saves, FilteredNickName (the copy the game displays) so they stay in sync; either key is created if absent for older/world saves. Blank clears the nickname back to the species name. Verified on a scratchpad palbox copy: set and cleared names round-trip to disk with both fields consistent. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Upstream's clone/delete only worked on world saves (they go through the container/group bookkeeping that GlobalPalStorage.sav does not have), so all three were no-ops in storage mode. Implement them directly against the flat 960-slot array: - Clone: deep-copy the selected pal into a free slot with a fresh InstanceId and its own slot index in the palbox container. - Add New Pal (new button): claim a free slot as a level-1 default, defaulting to CubeTurtle/Tetroise (a nod to the Mystic Testudine), with its natural moveset filled in; edit from there. - Delete: confirm, then return the slot to a pristine null placeholder. The array length stays fixed at 960 and identities stay unique. Note the global box legitimately allows duplicate slot indices (the source save already has them), so slot-index assignment only avoids colliding where it can rather than enforcing uniqueness. Verified on scratchpad palbox copies: clone/add/delete round-trip through save and reload, InstanceIds stay unique, and deletes free the slot without disturbing the other pals. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The 'players who have not logged in can break your save' warning is specific to world saves (Level.sav plus the Players/ folder). The Global Palbox has no player data, so the warning is inapplicable and confusing there. loaddata now hides it in storage mode and restores it for world saves. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The equipped-attack search gains a small toolbar: - Tier: Standard (the species' natural learnset) / Fruit-teachable (non-unique moves plus the pal's own unique) / All attacks. Defaults to the tier implied by the global legal-only toggle. - Element filter: All or a single element. - Sort: by Power (default, strongest first) or Name. Rows now show power and element (e.g. 'Flame Cutter (700) Fire'). availableAttacks(pal, tier) centralises the tier logic and strips the empty/None sentinels so the picker's own clear-row is not duplicated. Verified on a palbox copy: tier switches 9/147/359 rows for Foxparks, element filter and power sort update the list live. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The passive search gains a toolbar and a description pane: - Group filter (Attack / Defense / Work / Movement / Utility / Other), derived from each passive's psp effect type and emitted into passives.json as Group; rows are clustered and tagged by group. - 'Natural only' toggle: limit to what the pal can obtain naturally (wild-rollable + species innates) or show every passive. - A blurb pane under the list shows the highlighted entry's effect description (attacks show element / power / category). Verified on a palbox copy: natural 86 vs all 420, group filter and natural toggle update the list live, and the blurb tracks selection. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Opening and saving added a zero-rank entry to GotWorkSuitabilityAddRankList for every suitability (13 per pal), which the game normally leaves empty and which could interfere with in-game work assignment (farming/grazing pals doing nothing). Zero-rank entries are now pruned on load and never written; an entry is created only for a real, non-zero bonus. Also fixes the suitability spinbox receiving its value before its range, which could clamp and later write the wrong value when switching between pals. Verified on save copies: a clean open+save adds no entries, a real bonus round-trips, clearing it removes the entry, and values stay correct across switching. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…itor plan Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Palworld 1.0 derives work suitability from species data plus GotWorkSuitabilityAddRankList and has no CraftSpeeds field (confirmed against palworld-save-pal). SetType no longer writes it, and any existing CraftSpeeds is dropped on load so re-saving matches the 1.0 format. Verified on a save copy: a species change no longer writes CraftSpeeds and still applies correctly. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
MasteredWaza holds moves taught beyond a species' natural learnset; the game grants the natural learnset itself. The move list was being filled with the whole learnset on load, so open+save added extra "mastered" moves to every pal. The displayed move pool is now derived (learnset + taught + equipped) and never written; MasteredWaza keeps only genuine taught moves, and any learnset entries left in it are cleaned on load. Verified on save copies: open+save keeps MasteredWaza empty for pals with only natural moves and preserves a genuinely taught move; teaching or equipping a non-learnset move records it, and stripping removes it. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Replace the ad-hoc grey look with a centralised palette in PalEditConfig (window/surface/input/fg/accent/danger) and apply it globally: a tk_setPalette call recolours all classic tk widgets (so unstyled labels and buttons stay readable on the dark surfaces), plus a ttk 'clam' style for comboboxes and buttons. The ~50 scattered darkgrey/lightgrey/#D3D3D3 literals now reference the palette constants, and list/picker item colours were adjusted for contrast on the dark background. Purely presentational — no logic or widget structure changed. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Beyond the fixed preset buttons, add a preset box: a dropdown of your own named passive presets with an Apply button, plus a Manage… popup to create/update/delete them (name + four passive slots). Presets are stored in ~/.paledit_passive_presets.json so they persist across sessions. Apply stamps the preset's passives onto the selected pal. Verified: save/list/apply round-trips (a 'Workhorse' preset applied its four passives to a pal and persisted), and the manager popup opens with the four slot pickers, existing-preset list and name field. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Update — Palworld 1.0 support, Global Palbox management, and save-safety fixesThis brings PalEdit from v0.12.1 (pre-1.0) up to the Palworld 1.0 save format, Palworld 1.0 support
New features
FixesA no-edit open→save is now a semantic no-op, verified by a field-by-field diff
Loading a previously-affected save and re-saving cleans out the obsolete/phantom Bugs encountered, and the fixes above that address them
The 1.0 field model and save behavior were cross-checked against |
Reword some code comments and the changelog to describe behaviour changes plainly. No functional changes. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Hello! After extensive in-game testing and edge-case checks, I was able to resolve all bugs encountered and confirm the updated editor is functioning cleanly with Palworld 1.0. I also updated the README and revised the commit documentation to make the full change set easier to review. I force-pushed the branch so the earlier commit entries could be replaced with clearer, more detailed descriptions. A release has also been published on my fork for easy download, testing, and general use. Please let me know if you have any questions or concerns, or identify any additional failure cases. |
… element
The searchable picker that backs the equipped-attack and passive slots now
also drives:
- the "add a move" box under the moveset (click to open the full tier /
element / sort picker; the ➕ button still commits the staged move), and
- the four slots in the passive-preset editor (pal-agnostic, so any passive
can go into a preset).
To share it, open_ability_search takes an anchor, an on_choose callback, an
include_none flag, and an optional pal (passives allow pal=None to offer every
passive). Attack rows are now tinted by element — Fire red, Water blue, and so
on — darkened for contrast on the light list, mirroring how passives are
already tinted by rating.
Verified headless on a Global Palbox copy: every picker variant builds, the
add-a-move flow adds a move that survives a save + reload, and the element
colour lookup is total over every attack.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The stats breakdown was read-only; it now lets you edit right where you're reading the numbers. IVs / Talents (0-100), the four souls (0-20) and condensation (shown as the in-game 0-4 stars) each become a spinbox that commits on arrow, Enter or focus-out. An edit writes straight through the pal's setters, keeps the HP ceiling and the main window in step, and refreshes the popup's own "current vs standard" column so you can watch a stat move as you tune it. Verified headless on a Global Palbox copy: each field lands on the pal and on the control it mirrors in the main window, the HP stat tracks its IV, condensation stars map to the internal rank, and every value survives a save + reload. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The level at the top of the pal panel is now a small text field as well as a stepper. You can type a level and press Enter (or click away) to jump straight there, which is much quicker than holding the arrows when you want, say, level 1 to 50 in one go. The ➖ / ➕ buttons are unchanged and still step one level at a time; the field simply follows along so the two always agree. Typed input is clamped to 1..level cap, and anything that isn't a number (a blank, a stray letter) is ignored and the field snaps back to the pal's real level, so a mistype can't put a pal into a bad state. The old hover readout that showed the pal's owner is preserved on the new field. Verified headless on a Global Palbox copy: the field tracks the selected pal, a typed value sets the level, over-cap input clamps, non-numbers revert, the +/- buttons keep the field in sync, and a set level survives a save + reload. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Record this round of editor conveniences in CONTRIBUTIONS.md: the shared searchable picker now backs the add-a-move box and the preset slots and tints attacks by element, the stats popup edits IVs / souls / condensation in place, and the level can be typed as well as stepped.
…Ball) Six of a real box's pals — all SheepBall (Lamball) — were dropping out of the list with `KeyError: 'SheepBall'`. The species lookup keys on the exact CharacterID, but our generated data can store a slightly different casing than the save (here the game's "SheepBall" vs a data key "Sheepball"), so the pal couldn't be matched and landed in the Unknown list. Unreal treats these names case-insensitively, so match them the same way: LoadPals now builds a lowercased-CodeName index (PalSpeciesLower) and PalEntity falls back to it when an exact match isn't found. This replaces the old one-off SheepBall fix-up with a general rule that also covers any other pal whose data casing drifts from the save, for every user — not just this box. Verified headless on the affected Global Palbox copy: all six SheepBall pals now load and resolve to "Lamball", the Unknown list goes from 6 to 0, the box count is stable across a no-edit save + reload, and the full picker regression still passes. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Note the SheepBall/Lamball load fix in CONTRIBUTIONS.md: a pal whose data casing differs from the save now matches case-insensitively instead of being dropped into the Unknown list.
Rewrite the usage sections around how the fork is actually used on Palworld 1.0: load GlobalPalStorage.sav, edit / add / clone / delete Pals, then move them into a local box in-game. Documents the two in-game behaviours players will see — edits to existing Pals apply immediately, while a freshly reconstructed Pal sits on a short (~10 minute) cooldown before it's usable. Also refresh the backup section to describe the automatic per-session backup (the old text said it wasn't implemented yet), and use a generic save path placeholder rather than a specific account id.
pals/error_0.json is written at runtime when a Pal fails to load, so it holds data copied from whatever save was open. It was committed before the matching .gitignore rule (pals/error_*.json) existed, so git kept tracking it. Untrack it (the file stays locally and is regenerated as needed) so real save data isn't published and the working tree stops showing it as modified.
A technical write-up for contributors: the 1.0 save/compression formats, the skip-decode strategy for GVAS parsing, how the supported Global Palbox path works, the per-pal 1.0 field model, and a full analysis of world-save (Level.sav) support — including the one decoder blocker (GroupSaveDataMap's 1.0 trailing bytes), the proven minimal fix, and the trade-offs still to resolve before enabling it.
…hots Call out clearly that GlobalPalStorage.sav is the only save file tested and working today (with a pointer to the save-editing analysis for the Level.sav groundwork), and illustrate the walkthrough with screenshots: the editor window, transferring an edited Pal (new vs overwritten genetic data), and a newly added Pal reconstructing on its cooldown. The editor screenshot is cropped to drop the window title bar so no personal save path is shown.
Advise closing the game before editing and relaunching after saving. While Palworld is running it keeps the palbox in memory and can overwrite disk edits on its next autosave, so editing with the game shut is the safe default.
Update the in-app version label so the title bar and About match the v0.13.1 release.
A few minor changes
Fixed bullet point title.
Fixed a few links
Hey man, i loved your mod and wanted to see it working in palworld 1.0 with some of your requested community changes.
I hope you like it! I've been testing it out on my saves (only global palbox so far) and it's been working great.
Contributions summary below:
Changes in this fork
Fork of EternalWraith/PalEdit, updated for the Palworld 1.0 release and
extended with editor features and save-safety fixes. Each item below is a
self-contained branch merged into
main, so changes can be cherry-pickedindividually.
Palworld 1.0 support
PlM, save type0x31), preserving the original compression on save.
GlobalPalStorage.sav(the 1.0 Global Palbox), not justLevel.sav.IsPlayer: falseoneach pal; detection now checks the value instead of key presence).
suitabilities, attacks, and passive skills, plus new-pal icons.
Editor features
default species and can be re-typed from there. (I picked a turtle for this because I am the mystic turtle, you can change this as you see fit but it'd tickle me to death if you left it in. :D)
NickNameand the 1.0FilteredNickName).all), element filter, and damage sort.
with a per-passive effect description and a natural-only / all toggle.
PalEdit-backupsfolder before the first write of each editing session.
not apply.
Fixes
behaviour because opening and saving injected a zero-rank entry into
GotWorkSuitabilityAddRankListfor every suitability (13 phantom entriesper pal). Zero-rank entries are now pruned on load and never written; a
suitability entry is created only for a real, non-zero bonus. Loading a
previously affected save and re-saving removes the phantom entries.
suitability controls set their value before their minimum, so a stale
minimum from the previous pal could clamp and later write a wrong value. The
range is now set before the value, and the write-back is skipped during
selection refresh.