PiP: unlockables and achievements
Panic in Paradise. What you have to do to unlock a weapon, an attack or a costume, and what earns an achievement, is a list of rules in three scripts. Each rule is one line: a name, a condition, and a number or an item. That makes them some of the easiest things in the game to change.
Where it lives
All in global.lu:
unlockablerules: the rules for unlocking things.rules_achievements: the rules for achievements.libraryunlockable: the functions both call (UnlockablesRegisterLevelRulesand the like). You rarely edit it, but its comments say what each kind of rule expects, for example “minCount = minimum number of levels to be completed”.
How a rule reads
The name is a hash, then a table. The same unlockCondTxtID is the text
shown for the condition, shared by many rules:
[--[[HASH:"rank_names_rank02":0x53d83b54]]1406679892] = {canForceUnlock=false, unlockCondTxtID = --[[HASH:"unlockable_condition_reach_level":0x974f744b]]2538566731, lvl = 2 },
InitializeAllRules then runs the groups in this order (the last four only
outside the demo):
| Function | What it unlocks |
|---|---|
InitializePlayerLevelRules |
The player ranks, rank01 to rank100, each at lvl = 1 to 100 |
InitializePlayerUpgradeAttack |
Attack moves, by rank |
InitializeMultiTokenRules |
An unlock that needs other unlocks first, such as the Baseball bat and Machete masteries together |
InitializeObjectOwnershipRules |
Items that unlock when you own two others |
InitializeAcquireItemRules |
Weapons from ultra-kills, and costumes stolen from bears |
InitializeItemMasteryRules |
Mastery of a weapon |
InitializeLevelCompletedRules |
Number of levels finished |
InitializeKillCompletedRules |
Killing a particular bear |
InitializeLevelTrophyRules, InitializeTrophyCountRules |
A grade on one level (lvl1_story_bronze), and a total number of one kind of cup (gold_allcup needs minCount=36) |
Attacks by rank
The three moves Naughty gains by ranking up are one small table:
[--[[HASH:"uppercut_attack":0x2f4deb6e]]793635694] = {canForceUnlock=false, unlockCondTxtID = --[[HASH:"unlockable_unlock_uppercut_attack":0x727b6376]]1920689014, lvl = 5 }, --this is link to the kick
[--[[HASH:"special_attack":0x46b76293]]1186423443] = {canForceUnlock=false, unlockCondTxtID = --[[HASH:"unlockable_unlock_special_attack":0x18247869]]405043305, lvl = 10 },
[--[[HASH:"big_terrorize_attack":0x718468e7]]1904503015] = {canForceUnlock=false, unlockCondTxtID = --[[HASH:"unlockable_unlock_big_terrorize":0xd530f849]]3576756297, lvl = 20 },
Interpretation: lvl is the rank at which the move unlocks. Set the three
numbers to 1 to have them from the start.
Weapons from ultra-kills
A comment in the script says the token “must absolutely be the name of the item for ultra kills and stolen costumes”. An ultra-kill rule looks like this:
[--[[HASH:"Animesword":0x68356540]]1748329792] = {unlockCondTxtID = --[[HASH:"unlockable_condition_ultrakill_knight":0x2c94dd37]]747953463, itemID = --[[HASH:"Animesword":0x68356540]]1748329792 },
Interpretation: the condition text name (..._ultrakill_knight) says which bear’s ultra-kill
earns the Anime sword.
Achievements
rules_achievements has the same shape. Trophies are counted by grade, and the
number of items bought or mastered is counted too. For the first trophy and the
purchase counts:
[--[[HASH:"achievement_First_Trophy":0x91266097]]2435211415] = {canForceUnlock=false, unlockCondTxtID = --[[HASH:"unlockable_condition_missing":0xef3cfe39]]4013751865, minCountBronze = 1, minCountSilver = 1, minCountGold = 1, minCountPlatine = 1},
[--[[HASH:"achievement_PurchasedItems_1":0xd9a91b24]]3651738404] = {canForceUnlock=false, unlockCondTxtID = --[[HASH:"unlockable_condition_missing":0xef3cfe39]]4013751865, minPurchasedItemsCount = 25},
The purchase counts are 25, 50, 100 and 200 items. One gold-count rule needs
goldCount = 1000000. The script also prints a line when one is earned:
print("Achievement earned : " .. engine.GetAchievementHashName(aAchievementID))
SetAchievementComplete hands the achievement to the engine. Interpretation:
the engine passes it on to the console, which this page cannot test.
How to change it
Change the number in a rule and Ship. Whole numbers only, no decimal point. Keep to the kind of value the game already uses: PiP scripts hang when a value is far outside its normal range (see PiP internals).
Confirmed and not
- Confirmed in the scripts: the rule groups, their order, and the shape of each rule.
- Interpretation: that
lvlis a rank, whatcanForceUnlockdoes (every rule here sets it tofalse), and which bear each ultra-kill name means. - Checked in Seam Ripper: setting the uppercut to
lvl = 1ships, the file reads back with only that line changed, and every record keeps its retail size. Not tested in the game; try that one first.