Skip to content

PalEdit 1.0 - Updates for Palworld 1.0 - Addition of some Requested Community Features#211

Open
TheMysticTurtle wants to merge 82 commits into
EternalWraith:mainfrom
TheMysticTurtle:main
Open

PalEdit 1.0 - Updates for Palworld 1.0 - Addition of some Requested Community Features#211
TheMysticTurtle wants to merge 82 commits into
EternalWraith:mainfrom
TheMysticTurtle:main

Conversation

@TheMysticTurtle

Copy link
Copy Markdown

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-picked
individually.

Palworld 1.0 support

  • Read and write the 1.0 save format (Oodle-compressed PlM, save type
    0x31), preserving the original compression on save.
  • Load GlobalPalStorage.sav (the 1.0 Global Palbox), not just Level.sav.
  • Fix every pal failing to load in 1.0 saves (1.0 writes IsPlayer: false on
    each pal; detection now checks the value instead of key presence).
  • Refresh all game data for 1.0: new species, movesets, stat scaling, work
    suitabilities, attacks, and passive skills, plus new-pal icons.
  • Raise the level cap to 80 and add the rank-5 passive tier.

Editor features

  • Add, clone, and delete pals in the Global Palbox. Newly added pals start as a
    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)
  • Edit pal nicknames (updates both NickName and the 1.0 FilteredNickName).
  • Searchable attack picker with a tier toggle (learnset / fruit-teachable /
    all), element filter, and damage sort.
  • Searchable passive picker grouped by effect (Attack, Defense, Work, etc.),
    with a per-passive effect description and a natural-only / all toggle.
  • Automatic save backup: the loaded save is copied to a PalEdit-backups
    folder before the first write of each editing session.
  • Hide the stale-player warning when editing the Global Palbox, where it does
    not apply.

Fixes

  • Fix work-suitability corruption. Pals lost their farming/grazing/kindling
    behaviour because opening and saving injected a zero-rank entry into
    GotWorkSuitabilityAddRankList for every suitability (13 phantom entries
    per 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.
  • Fix work suitabilities "flip-flopping" between pals: on selecting a pal, the
    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.

TheMysticTurtle and others added 30 commits July 20, 2026 00:35
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>
TheMysticTurtle and others added 5 commits July 21, 2026 21:45
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>
@TheMysticTurtle

Copy link
Copy Markdown
Author

Update — Palworld 1.0 support, Global Palbox management, and save-safety fixes

This brings PalEdit from v0.12.1 (pre-1.0) up to the Palworld 1.0 save format,
adds Global Palbox editing and a batch of editor features, and fixes several
sources of save corruption. Each item was built as its own branch and merged to
main, so anything here can be reviewed or cherry-picked individually.

Palworld 1.0 support

  • Read/write the 1.0 save format (Oodle-compressed PlM, save type 0x31),
    preserving the original compression on save.
  • Load GlobalPalStorage.sav (the 1.0 Global Palbox) in addition to Level.sav.
  • Fix all pals failing to load from 1.0 saves (see bugs below).
  • Regenerate bundled game data for 1.0: species, movesets, stat scaling, work
    suitabilities, attacks, passives, and icons. Level cap raised to 80; rank-5
    passive tier supported.

New features

  • Global Palbox management — add, clone, and delete pals; edit nicknames
    (writes both NickName and the 1.0 FilteredNickName).
  • Attack picker — search by name, filter by element, sort by damage, and
    toggle between natural learnset / fruit-teachable / all attacks.
  • Passive picker — search, group by effect (Attack, Defense, Work,
    Movement, Utility, Other), toggle natural-only vs all, with accurate
    descriptions generated from each passive's effects, shown on hover.
  • Pal-list filter bar — name/species search, element, and category.
  • Species browser — searchable, with element / category / work-suitability /
    NPC-type filters; rows show the internal code so catchable NPCs and merchants
    are identifiable by name. (Editing NPCs/merchants works within PalEdit; using
    them in-game is experimental — see bugs below.)
  • Work-suitability editing 0–10 — with grey/green/red feedback: grey at the
    species base, green when raised within the normal cap, red in the excessive
    6–10 range.
  • Stats/potential popup — current stats vs the level standard, plus IV, soul
    and condensation contributions.
  • Custom named passive presets — build and save passive sets, then stamp
    them onto pals.
  • Automatic per-session save backup — the loaded save is copied into a
    PalEdit-backups folder before the first write of each session (one backup
    per loaded save per session).

Fixes

A no-edit open→save is now a semantic no-op, verified by a field-by-field diff
of every pal. The following remove data the older behavior wrote that either
doesn't belong in 1.0 or actively broke things:

  • Stop writing the obsolete CraftSpeeds field.
  • Stop writing zero-rank GotWorkSuitabilityAddRankList entries; prune existing
    ones on load; only create an entry for a real, non-zero suitability bonus.
  • Fix work-suitability "flip-flopping" between pals on selection.
  • Stop dumping the full learnset into MasteredWaza; preserve actual mastered
    attacks.
  • Stop writing the pre-1.0 Talent_Melee IV (1.0 uses a single attack IV).
  • Fix list selection landing on the wrong pal after a species change.

Loading a previously-affected save and re-saving cleans out the obsolete/phantom
data automatically.

Bugs encountered, and the fixes above that address them

  • Every pal failed to load from 1.0 saves. 1.0 writes IsPlayer: false on
    every pal, and the old code treated the presence of the IsPlayer key as
    "this is a player," so all pals were skipped. Now it checks the value.
  • Pals were grazing that shouldn't be. In-game, pals with no ranch/grazing
    work suitability were still being sent to graze (idling on a ranch, producing
    nothing). A field-by-field diff of a no-edit open→save showed the cause:
    simply opening and saving a box injected phantom data into every pal —
    CraftSpeeds, ~13 zero-rank suitability entries per pal (286 across a 22-pal
    box), the full learnset into MasteredWaza, and Talent_Melee. The extra
    suitability entries in particular interfered with in-game work assignment.
    This is addressed by the four "stop writing / prune on load" fixes above.
    Confirmed resolved in practice: after the corrections, re-saving the box
    cleaned out the phantom data, and reloading all the pals back into the world
    from the Global Palbox stopped the erroneous grazing.
  • Work suitabilities copying between pals. On selection, the suitability
    spinbox received its new value before its minimum range was updated, so a
    stale minimum from the previously selected pal clamped the value and a later
    click wrote the wrong rank back. Fixed by updating each control's range before
    its value and skipping write-back during selection refresh.
  • Selection jumping to the wrong pal after a species change. The list
    refresh set the new selection without clearing the old one, leaving two rows
    selected. Fixed so a refresh selects exactly one row (this also keeps a clone
    on the pal it was cloned from).
  • Rank-5 passives could crash the passive color lookup. 1.0 added a rank-5
    tier the color table didn't account for; the missing tier was added.
  • Caught merchants/NPCs. This was an incomplete-data issue in the editor:
    the refreshed 1.0 data now includes all NPC and merchant character types, so
    they load, display, edit, and save correctly in PalEdit. However, actually
    using an edited merchant in-game is not fully working — dragging one out of
    the box into the world still errors on a multiplayer server. It may behave
    differently in single-player, but that's untested. Treat NPC/merchant editing
    as experimental for now.

The 1.0 field model and save behavior were cross-checked against
oMaN-Rod/palworld-save-pal throughout. Testing so far has focused on the
Global Palbox workflow (load, edit, add/clone/delete, save, reload in-game, and
no-edit round-trip comparisons); as with any save editor I'd still recommend
keeping normal backups while reviewing.

@TheMysticTurtle
TheMysticTurtle marked this pull request as ready for review July 22, 2026 03:54
TheMysticTurtle and others added 2 commits July 22, 2026 01:13
Reword some code comments and the changelog to describe behaviour changes
plainly. No functional changes.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@TheMysticTurtle

Copy link
Copy Markdown
Author

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.

TheMysticTurtle and others added 19 commits July 22, 2026 20:01
… 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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant