Difference between revisions of "Room Clear Awards"

From Binding of Isaac: Rebirth Wiki
Jump to: navigation, search
Tag: Visual edit
(Translating the code into someting easier to read)
Line 125: Line 125:
 
</nowiki>
 
</nowiki>
   
  +
==Translation==
  +
First, the game generates a random number using this formula:
  +
  +
''(RandomFloat * Luck * 0.1) + pickupPercent''
  +
*RandomFloat and pickupPercent are random numbers between 0 and 1
  +
*Luck is clamped to 0 if Isaac’s luck is less than 0 and 10 if Isaac’s luck is greater than 10
  +
*This chance is modified by the following items/trinkets:
  +
**{{i|Lucky Foot}} multiplies RandomFloat and pickupPercent by 0.9, then adds 0.1.
  +
**{{t|Lucky Toe}} multiplies pickupPercent by 0.98, then adds 0.02.
  +
That number is then used to determine the reward given after clearing the room. At zero luck and with no other modifiers, the chances are as follows:
  +
*Nothing (22%)
  +
*A [[tarot card]] (2.66%)
  +
*A [[pill]] (2.66%)
  +
*A [[trinket]] (2.66%)
  +
*A [[coin]] (15%, or 20% if Isaac has {{t|Rib of Greed}})
  +
*A [[heart]] (15%, or 10% if Isaac has Rib of Greed)
  +
**If Isaac has {{t|Daemon's Tail}}, the heart has an 80% chance of being replaced by a key.
  +
*A [[key]] (20%)
  +
*A [[bomb]] (15%)
  +
*A [[chest]] (5%)
  +
**If Isaac has positive luck, the chance for a chest increases and all other chances decrease.
  +
*** Lucky Foot/Toe decrease the chance of getting nothing, but do not themselves increase the chance for chests to spawn.
  +
The reward then has a chance to be modified/replaced by the following, in order:
  +
*{{t|Watch Battery}} (3.33% chance to replace with a lil’ battery)
  +
*A [[sack]] (2% chance, always in effect)
  +
*{{t|Ace of Spades}} (10% chance to replace with a tarot card)
  +
*{{t|Safety Cap}} (10% chance to replace with a pill)
  +
*{{t|Match Stick}} (10% chance to replace with a bomb)
  +
*{{t|Child's Heart}} (10% chance to replace with a heart)
  +
*{{t|Rusted Key}} (10% chance to replace with a key)
  +
*{{i|Smelter}} (2% chance to replace with a trinket)
  +
**If Isaac has multiple of these, the first one to activate is the one that replaces the room reward
  +
*{{i|Guppy's Tail}} has a 33% chance to replace the reward with a (locked) chest and a 33% chance to prevent it from spawning.
  +
*{{i|Contract from Below}} gives an extra copy of the reward, but has a 33% chance to prevent it from spawning.
  +
**Each extra contract Isaac has causes another copy of the reward to spawn and halves the chance the reward doesn’t spawn.
  +
*If playing on [[Hard Mode]], heart rewards have a 66% chance to not spawn.
  +
*{{i|Broken Modem}} has a 25% chance to create an additional copy of the reward if it’s a key, coin, heart, bomb, or sack.
  +
  +
==Notes==
 
This is taken from [https://gist.github.com/bladecoding/e2822580734366633347ac98dfe4a8d9 Blade's GitHub Gist]. (Blade is also known as blcd / Will.) He reverse engineered the game using a disassembler in order to create this pseudo-code.
 
This is taken from [https://gist.github.com/bladecoding/e2822580734366633347ac98dfe4a8d9 Blade's GitHub Gist]. (Blade is also known as blcd / Will.) He reverse engineered the game using a disassembler in order to create this pseudo-code.
   

Revision as of 06:17, 26 September 2020

When clearing a room, the game has a chance of rewarding a pickup or trinket. This based on many things, including your current luck and whether you have some particular items. The full logic is contained within the following pseudo-code:

local room = Game():GetLevel():GetCurrentRoom()
local awardSeed = room.AwardSeed
local player = Game():GetPlayer(0)
local difficulty = Game().Difficulty

local rng = RNG()
rng:SetSeed(awardSeed, 35) --5, 9, 7

local pickupPercent = rng:RandomFloat()
if (player:HasCollectible(COLLECTIBLE_LUCKYFOOT)) then
	pickupPercent = (pickupPercent * 0.9) + 0.1
end

local luck = math.max(math.min(player.Luck, 10), 0) --Clamp to 0-10

--Max luck increases the pickupPercent range from 0-1 to 0-2
--That means the more luck you have, the more likely you are to get chests.
pickupPercent = rng:RandomFloat() * luck * 0.1 + pickupPercent

if (player:HasTrinket(TRINKET_LUCKY_TOE)) then
	if (player:HasCollectible(COLLECTIBLE_LUCKYFOOT) and luck > 0) then
		pickupPercent = (pickupPercent * 0.98) + 0.02
	else
		pickupPercent = (pickupPercent * 0.9) + 0.1
	end
end

local pickupAward = COLLECTIBLE_NULL
local pickupCount = 1

if (pickupPercent > 0.22) then
	if (pickupPercent < 0.3) then
		if (rng:RandomInt(3) == 0) then
			pickupAward = PICKUP_TAROTCARD
		elseif (rng:RandomInt(2) == 0) then
			pickupAward = PICKUP_TRINKET
		else
			pickupAward = PICKUP_PILL
		end
	elseif (pickupPercent < 0.45) then
		pickupAward = PICKUP_COIN
	elseif (pickupPercent < 0.5 and player:HasTrinket(TRINKET_RIB_OF_GREED)) then
		pickupAward = PICKUP_COIN
	elseif (pickupPercent < 0.6 and (not player:HasTrinket(TRINKET_DAEMONS_TAIL) or rng:RandomInt(5) == 0)) then
		pickupAward = PICKUP_HEART
	elseif (pickupPercent < 0.8) then
		pickupAward = PICKUP_KEY
	elseif (pickupPercent < 0.95) then
		pickupAward = PICKUP_BOMB
	else
		pickupAward = PICKUP_CHEST
	end
	
	if (rng:RandomInt(20) == 0 or (rng:RandomInt(15) == 0 and player:HasTrinket(TRINKET_WATCH_BATTERY))) then
		pickupAward = PICKUP_LIL_BATTERY
	end
	
	if (rng:RandomInt(50) == 0) then
		pickupAward = PICKUP_GRAB_BAG
	end
	
	if (player:HasTrinket(TRINKET_ACE_SPADES) and rng:RandomInt(10) == 0) then
		pickupAward = PICKUP_TAROTCARD
	elseif (player:HasTrinket(TRINKET_SAFETY_CAP) and rng:RandomInt(10) == 0) then
		pickupAward = PICKUP_PILL
	elseif (player:HasTrinket(TRINKET_MATCH_STICK) and rng:RandomInt(10) == 0) then
		pickupAward = PICKUP_BOMB
	elseif (player:HasTrinket(TRINKET_CHILDS_HEART) and rng:RandomInt(10) == 0 and (not player:HasTrinket(TRINKET_DAEMONS_TAIL) or rng:RandomInt(5) == 0)) then
		pickupAward = PICKUP_HEART
	elseif (player:HasTrinket(TRINKET_RUSTED_KEY) and rng:RandomInt(10) == 0) then
		pickupAward = PICKUP_KEY
	end
	
		
	if (player:HasCollectible(COLLECTIBLE_SMELTER) and rng:RandomInt(50) == 0) then
		pickupAward = PICKUP_TRINKET
	end
end


if (player:HasCollectible(COLLECTIBLE_GUPPYS_TAIL)) then
	if (rng:RandomInt(3) != 0) then
		if (rng:RandomInt(3) == 0) then
			pickupAward = PICKUP_NULL
		end
	else
		if (rng:RandomInt(2) != 0) then
			pickupAward = PICKUP_LOCKEDCHEST
		else
			pickupAward = PICKUP_CHEST
		end
	end
end

if (player:HasCollectible(COLLECTIBLE_CONTRACT_FROM_BELOW) and pickupAward != PICKUP_TRINKET) then
	pickupCount = player:GetCollectibleNum(COLLECTIBLE_CONTRACT_FROM_BELOW) + 1
	--The chance of getting nothing goes down with each contract exponentially
	local nothingChance = math.pow(0.666, pickupCount - 1)
	if (nothingChance * 0.5 > rng:NextFloat()) then
		pickupCount = 0
	end
end

if (difficulty == 1 and pickupAward == PICKUP_HEART) then
	if rng:RandomInt(100) >= 35 then
		pickupAward = PICKUP_NULL
	end
end

if (player:HasCollectible(COLLECTIBLE_BROKEN_MODEM) and rng:RandomInt(4) == 0 and pickupCount >= 1 and
		(pickupAward == PICKUP_COIN or pickupAward == PICKUP_HEART or pickupAward == PICKUP_KEY or pickupAward == PICKUP_GRAB_BAG or pickupAward == PICKUP_BOMB) then
	pickupCount = pickupCount + 1
end

if (pickupCount > 0 and pickupAward != PICKUP_NULL) then
	local subType = 0
	for i=1, pickupCount do
		local ent = Game():Spawn(ENTITY_PICKUP, pickupAward, nearCenter, Vector(0, 0), 0, subtype, rng:Next())
		subType = ent.SubType
	end
end

Translation

First, the game generates a random number using this formula:

(RandomFloat * Luck * 0.1) + pickupPercent

  • RandomFloat and pickupPercent are random numbers between 0 and 1
  • Luck is clamped to 0 if Isaac’s luck is less than 0 and 10 if Isaac’s luck is greater than 10
  • This chance is modified by the following items/trinkets:
    • Lucky Foot Lucky Foot multiplies RandomFloat and pickupPercent by 0.9, then adds 0.1.
    • Lucky Toe Lucky Toe multiplies pickupPercent by 0.98, then adds 0.02.

That number is then used to determine the reward given after clearing the room. At zero luck and with no other modifiers, the chances are as follows:

  • Nothing (22%)
  • A tarot card (2.66%)
  • A pill (2.66%)
  • A trinket (2.66%)
  • A coin (15%, or 20% if Isaac has Added in AfterbirthRib of Greed Rib of Greed)
  • A heart (15%, or 10% if Isaac has Rib of Greed)
    • If Isaac has Daemon's Tail Daemon's Tail, the heart has an 80% chance of being replaced by a key.
  • A key (20%)
  • A bomb (15%)
  • A chest (5%)
    • If Isaac has positive luck, the chance for a chest increases and all other chances decrease.
      • Lucky Foot/Toe decrease the chance of getting nothing, but do not themselves increase the chance for chests to spawn.

The reward then has a chance to be modified/replaced by the following, in order:

  • Added in AfterbirthWatch Battery Watch Battery (3.33% chance to replace with a lil’ battery)
  • A sack (2% chance, always in effect)
  • Ace of Spades Ace of Spades (10% chance to replace with a tarot card)
  • Safety Cap Safety Cap (10% chance to replace with a pill)
  • Match Stick Match Stick (10% chance to replace with a bomb)
  • Child's Heart Child's Heart (10% chance to replace with a heart)
  • Rusted Key Rusted Key (10% chance to replace with a key)
  • Added in Afterbirth †Smelter Smelter (2% chance to replace with a trinket)
    • If Isaac has multiple of these, the first one to activate is the one that replaces the room reward
  • Guppy's Tail Guppy's Tail has a 33% chance to replace the reward with a (locked) chest and a 33% chance to prevent it from spawning.
  • Contract From Below Contract From Below gives an extra copy of the reward, but has a 33% chance to prevent it from spawning.
    • Each extra contract Isaac has causes another copy of the reward to spawn and halves the chance the reward doesn’t spawn.
  • If playing on Hard Mode, heart rewards have a 66% chance to not spawn.
  • Added in Afterbirth †Broken Modem Broken Modem has a 25% chance to create an additional copy of the reward if it’s a key, coin, heart, bomb, or sack.

Notes

This is taken from Blade's GitHub Gist. (Blade is also known as blcd / Will.) He reverse engineered the game using a disassembler in order to create this pseudo-code.