Compare commits

...
12 Commits
Author SHA1 Message Date
Wofsauge b7b5da2e6a chore: release 4.78 2024-07-15 00:04:46 +02:00
Wofsauge 2b3c48d1ea Added shortcut function for adding general conditions 2024-07-14 23:39:12 +02:00
Buurazu 9703626b71 Misc item reminder updates (#695)
* Change wisp checking

* Change selected item var

* Trinket and wisp checks

* add a simple room counter

* various changes

* update my todo list

* Gulped trinket support

* Reset selected items better

* update todo list

* add poop nuggets to pickup names

* add glyph of balance

* add a helper function for xml names

* overhaul special description modifiers

* Pandora's Box greed

* Pandora's Box tweak

* Pandora's Box overview desc

* let Card Reading Boss portal get modified

* move Strange Key to conditionals

* Update eid_conditionals.lua

* misc helper functions

* whitelists

* small text pos modifier tweaks

* wild card + glowing hourglass + void ab+

* move vurp, add wild card

* move SimpleRound

* add wild card, move simpleround, fix pill icon stuff

* Echo Chamber color

* update todo list

* starting work on The Stars? preview

* remove collectible count check; bad for tainted eden

* Tainted Laz overhaul

* fix 4.5 volt with timed pocket actives

* fix pocket active check functions

* Tainted Laz overhaul + The Stars?

* more conditionals

* Battery and bean synergies
2024-07-14 22:07:10 +02:00
Buurazu 24a6a808ba misc char tweaks 2024-07-02 07:34:43 -04:00
Buurazu 9f83af5628 small char tweaks 2024-07-02 07:31:13 -04:00
Buurazu c877530540 Fix car battery pedestal showing no effect erroneously 2024-07-01 22:45:59 -04:00
Buurazu f2aab787a7 Add addHorsePill
The descriptions are added to pills[] instead of custom[] now because custom receives adjusted subtypes, and was overriding horsepill descriptions
2024-07-01 22:32:41 -04:00
Buurazu cd9bd800ab Fix en_us_detailed causing errors 2024-07-01 21:50:33 -04:00
Wofsauge 000893987b chore: release 4.77 2024-06-28 21:11:12 +02:00
Buurazu 8ff9f7a262 More override/overridden conditionals (#692)
* Add layers and unique ID checks

* a bunch more overrides

* some overridey conditions

* shorten spirit sword, some conditions

* brimstone mom's knife

* reorganize + mom's knife brimstone
2024-06-28 19:30:33 +02:00
Buurazu 3b0c1165c0 API functions for adding conditionals + override/overridden part 1 (#690)
* some more conditionals

* brimstoney conditions

* add an empty table...

* overrides wip

* Add functions for modders

* more overriding

* Update en_us.lua

* Update en_us.lua

* fix typo
2024-06-27 18:23:50 +02:00
Buurazu 2b78661002 remove a leftover debug print 2024-06-26 21:46:54 -04:00
13 changed files with 1349 additions and 503 deletions

No files matched your search

+42 -15
View File
@@ -319,7 +319,7 @@ EID.descriptions[languageCode].collectibles={
{"296", "Converter", "{{Heart}} Converts 2 Soul/Black Hearts into 1 heart container"}, -- Converter
-- NOTE FOR LOCALIZERS: There is code to highlight the text of your current floor
-- For it to work, only use line breaks or semicolons to separate floor details, and use the same order as English
{"297", "Pandora's Box", "{{Warning}} SINGLE USE {{Warning}} Spawns rewards based on floor:#B1: 2{{SoulHeart}}; B2: 2{{Bomb}} + 2{{Key}}#C1: Boss item; C2: B1+C1#D1: 4{{SoulHeart}}; D2: 20{{Coin}}#W1: 2 Boss items#W2: {{Collectible33}} The Bible#???/Void: Nothing#Sheol: Devil item + 1{{BlackHeart}}#Cathe: Angel item + 1{{EternalHeart}}#{{NoLB}}Dark Room: Unlocks {{Collectible523}} Moving Box#Chest: 1{{Coin}}"}, -- Pandora's Box
{"297", "Pandora's Box", "{{Warning}} SINGLE USE {{Warning}} Spawns rewards based on floor:#B1: 2{{SoulHeart}}; B2: 2{{Bomb}} + 2{{Key}}#{{NoLB}}C1: Boss item; C2: C1 + 2{{SoulHeart}}#D1: 4{{SoulHeart}}; D2: 20{{Coin}}#W1: 2 Boss items#W2: {{Collectible33}} The Bible#???/Void: Nothing#Sheol: Devil item + 1{{BlackHeart}}#Cathe: Angel item + 1{{EternalHeart}}#{{NoLB}}Dark Room: Unlocks {{Collectible523}} Moving Box#Chest: 1{{Coin}}"}, -- Pandora's Box
{"298", "Unicorn Stump", "{{Timer}} Receive for 6 seconds:#↑ {{Speed}} +0.28 Speed#Invincibility#Isaac can't shoot (No contact damage)"}, -- Unicorn Stump
{"299", "Taurus", "↓ {{Speed}} -0.3 Speed#↑ {{Speed}} Slowly gain speed while in hostile rooms#At 2 speed, Isaac becomes invincible and deals contact damage#Afterwards, lose the Taurus speed boost for the room"}, -- Taurus
{"300", "Aries", "↑ {{Speed}} +0.25 Speed#Touching enemies deals contact damage"}, -- Aries
@@ -633,7 +633,7 @@ EID.descriptions[languageCode].carBattery = {
[485] = "25% chance to quadruple, 25% chance to double and remove the originals, 50% chance to remove", -- Crooked Penny
[486] = {"effects", "{{CR}}effects {{BlinkYellowGreen}}twice"}, -- Dull Razor
[488] = "Activates twice, but only the second effect stays", -- Metronome
[489] = {" a ", " 2 ", "effect", "{{CR}}effects"}, -- D Infinity (TODO: d infinity's desc addon is not visible in item reminder)
[489] = {" a ", " 2 ", "effect", "{{CR}}effects"}, -- D Infinity
[504] = {" a ", " 2 ", "turret", "{{CR}}turrets"}, -- Brown Nugget
[507] = "Triggers twice", -- Sharp Straw
[510] = {" a ", " 2 ", "version", "{{CR}}versions"}, -- Delirious
@@ -731,6 +731,7 @@ EID.descriptions[languageCode].BFFSSynergies = {
["5.350.54"] = {3.5, 7}, --- Isaac's Head
["5.350.57"] = {3.5, 7}, --- ???'s Soul
["Lilith"] = "Incubus damage is doubled", -- Incubus (for BFFS pedestal)
}
---------- Trinkets ----------
@@ -1023,19 +1024,19 @@ EID.descriptions[languageCode].CharacterInfo = {
[2] = {"Cain", ""},
[3] = {"Judas", ""},
[4] = {"???", "Can't have Red Hearts"},
[5] = {"Eve", "Eve's Whore of Babylon triggers at 1 Red Heart or less"}, --this could just be desc modifier?
[5] = {"Eve", ""},
[6] = {"Samson", ""},
[7] = {"Azazel", "Flight#Short range Brimstone instead of tears"},
[7] = {"Azazel", "Flight#Short range Brimstone instead of tears#Can gain Red Hearts"},
[8] = {"Lazarus", "When you die, resurrect as Lazarus Risen with 1 Red Heart container"},
[9] = {"Eden", "Start with random stats and items each run"},
[10] = {"The Lost", "Flight#Spectral tears#No health#One devil deal per room can be taken for free"},
[11] = {"Lazarus Risen", "Increased stats and x1.2 damage multiplier"},
[12] = {"Dark Judas", "x2 Damage multiplier"},
[13] = {"Lilith", "Cannot shoot tears"},
[12] = {"Dark Judas", "x2 Damage multiplier#Can gain Red Hearts#Counts as Judas for completion marks"},
[13] = {"Lilith", "Cannot shoot tears#Her Incubus shoots for her"},
[14] = {"Keeper", "Heal by picking up coins#Heart pickups are turned into Blue Flies"},
[15] = {"Apollyon", ""},
[16] = {"The Forgotten", "You have a melee attack#Can have up to 6 Bone Hearts#Press {{ButtonRT}} to switch to The Soul#The Soul can have up to 6 Soul/Black Hearts and has flight and spectral tears#The Soul is chained to The Forgotten, and can only move in a small radius around him"},
[17] = {"The Forgotten Soul", "You have a melee attack#Can have up to 6 Bone Hearts#Press {{ButtonRT}} to switch to The Soul#The Soul can have up to 6 Soul/Black Hearts and has flight and spectral tears#The Soul is chained to The Forgotten, and can only move in a small radius around him"},
[16] = {"The Forgotten", "You have a melee attack which can be charged and thrown#Can have up to 6 Bone Hearts#Press {{ButtonRT}} to switch to The Soul#The Soul can have up to 6 Soul/Black Hearts and has flight and spectral tears#The Soul is chained to The Forgotten, and can only move in a small radius around him"},
[17] = {"The Forgotten Soul", "You have a melee attack which can be charged and thrown#Can have up to 6 Bone Hearts#Press {{ButtonRT}} to switch to The Soul#The Soul can have up to 6 Soul/Black Hearts and has flight and spectral tears#The Soul is chained to The Forgotten, and can only move in a small radius around him"},
}
---------- Sacrifice Room ----------
@@ -1113,12 +1114,13 @@ EID.descriptions[languageCode].ItemReminder = {
InventoryEmpty = "(Player has no items)",
CategoryNames = {
Overview = "Inventory Overview",
Wisps = "Lemegeton Wisps",
Special = "Special",
Actives = "Held active items",
Pockets = "Held pocket items",
Actives = "Held Active Items",
Pockets = "Held Pocket Items",
Trinkets = "Held Trinkets",
Passives = "Held passive items",
Character = "Character Info"
Passives = "Held Passive Items",
Character = "Character Info",
}
}
@@ -1128,7 +1130,7 @@ EID.descriptions[languageCode].RoomTypeNames = { "Normal Room", "Shop", "I AM ER
-- Not technically room types but still potentially useful to have localized
[666] = "Devil/Angel Room", [1024] = "Red Room", [1025] = "Special Red Room" }
-- currently used for D1
-- currently used for D1 and Glyph of Balance; contains Rep pickups for ease of localization
EID.descriptions[languageCode].PickupNames = {
["5.0"] = "None",
@@ -1143,6 +1145,8 @@ EID.descriptions[languageCode].PickupNames = {
["5.40"] = "{{Bomb}} Bomb",
["5.40.1"] = "{{Crafting15}} Bomb", ["5.40.2"] = "{{Crafting15}} Double Bomb", ["5.40.3"] = "{{Crafting15}} Troll Bomb", ["5.40.4"] = "{{Crafting16}} Golden Bomb", ["5.40.5"] = "{{Crafting15}} Mega Troll Bomb", ["5.40.7"] = "{{Crafting17}} Giga Bomb",
["5.42"] = "{{Crafting29}} Poop Nugget", ["5.42.1"] = "{{Crafting29}} Big Poop Nugget",
["5.90"] = "{{Battery}} Battery",
["5.90.0"] = "{{Crafting19}} Lil' Battery", --AB+ didn't have subtypes for batteries
@@ -1162,7 +1166,7 @@ EID.descriptions[languageCode].PickupNames = {
-- Conditional descriptions - DO NOT TRANSLATE THE FIRST PART IN ["BRACKETS"]
-- Strings will be appended to the original description
-- Tables with one entry will completely replace the original description
-- Tables with two or more entries are find-replace pairs
-- Tables with two or more entries are find-replace pairs (if there's an odd number of entries, the last entry is appended)
-- For collectible/player conditionals, lines will automatically have their bulletpoint, and {1} is replaced with their name
EID.descriptions[languageCode].ConditionalDescs = {
------ GENERAL STRINGS ------
@@ -1170,6 +1174,7 @@ EID.descriptions[languageCode].ConditionalDescs = {
["Overrides"] = "Overrides {1}",
["Almost No Effect"] = "Little to no effect for {1}",
["No Effect"] = "No effect for {1}",
["No Effect From"] = "No effect from {1}",
["Can't Charge"] = "Can't charge {1}",
["Can't Be Charged"] = "Can't be charged by {1}",
["Can't Be Duplicated"] = "Can't be duplicated",
@@ -1197,6 +1202,7 @@ EID.descriptions[languageCode].ConditionalDescs = {
["5.350.44"] = {"{{Pill}} Chance for a bonus pill from chests, tinted rocks and destroyed machines"}, -- Safety Cap
["5.350.45"] = {"{{Card}} Chance for a bonus card from chests, tinted rocks and destroyed machines"}, -- Ace of Spades
["5.350.72"] = {"{{Battery}} +10% chance for random pickups to be a battery#{{Battery}} 5% chance to add 1 charge to held active item when clearing a wave"}, -- Watch Battery
["5.100.297 (Greed)"] = {"{{Warning}} SINGLE USE {{Warning}} Spawns rewards based on floor:#Basement: 2{{Bomb}} + 2{{Key}}#Caves: Boss item + 2{{SoulHeart}}#Depths: 20{{Coin}}#Womb: 2 Boss items#Sheol: Devil item + 1{{BlackHeart}}#The Shop/Ultra Greed: 1{{Coin}}"}, -- Pandora's Box
------ ACHIEVEMENT CHECKS ------
@@ -1253,11 +1259,32 @@ EID.descriptions[languageCode].ConditionalDescs = {
["Bulb Multiple"] = "Only checks the primary active item", -- Vibrant/Dim Bulb + Schoolbag/Pocket Actives
["Bulb Zero"] = "Actives with 0 max charges trigger the bulb", -- Vibrant/Dim Bulb + zero charge actives
["5.350.101 (Timed)"] = "Basically useless with timed recharges", -- Dim Bulb + Timed Recharges
["5.100.122"] = "Triggers at 1 Red Heart as {1}", -- Whore of Babylon + Eve
["5.70.28"] = "Isaac shoots forward and to the sides instead", -- R U A Wizard + The Wiz
["5.100.523"] = "Counts as a passive item to {1}", -- Moving Box + Void
["Mongo Babies"] = "Can be copied by {1}", -- Mongo Baby + Baby Familiars
["Technology 2 One Eye"] = "With {1}, the laser replaces your tears entirely", -- Technology 2 + one eye
["Technology 2 One Eye"] = "With {1}, the laser replaces your tears entirely",
["Brimstone Proptosis"] = "Beams deal additional 2x damage at point blank range, decreasing with distance",
["Brimstone Ipecac"] = "Ipecac tears are fired while charging#The +40 damage applies to the laser",
["Proptosis Anti-Gravity"] = "Tears don't lose damage until they start moving",
["Epic Fetus Soy Milk"] = "Crosshair time is not shortened, but missile damage is drastically reduced",
["Eye of Belial Dr. Fetus"] = "Bombs pierce, but don't home or do additional damage",
["Epic Fetus Brimstone"] = "{1} has priority#Rockets shoot out 10 beams",
["Epic Fetus Mom's Knife"] = "{1} has priority#Rockets shoot out 10 knives",
["Brimstone Mom's Knife"] = "{1} has priority#A barrage of knives shoot out based on charge amount",
["Ludovico Ipecac"] = "The tear gets +4 damage but doesn't explode or poison",
["Technology Ipecac"] = "The laser gets +4 damage and poisons targets",
["Chocolate Milk Overrides"] = "↑ {{Tears}} x1.25 Tears multiplier",
["Chocolate Milk Marked"] = "Isaac automatically charges based on distance from the crosshair",
["Ghost Pepper Fart"] = "Farting causes a flame to shoot out behind Isaac",
["5.300.5"] = {"{{BossRoom}} Teleports Isaac to a random Boss Room"}, -- IV - The Emperor (in The Void)
["5.300.18"] = "Teleports Isaac to a random room if there's no Treasure Room", -- XVII - The Stars (Womb and below)
["5.300.18 (Greed)"] = {"{{TreasureRoom}} Teleports Isaac to a random Treasure Room"}, -- XVII - The Stars (Greed)
["5.300.18 (Late Greed)"] = {"Teleports Isaac to the first room of the floor"}, -- XVII - The Stars (Greed Last Floors)
["5.300.10"] = "Teleports Isaac to a random room if there's no Shop", -- IX - The Hermit (Womb and below)
}
+47 -23
View File
@@ -135,7 +135,7 @@ local repCollectibles={
[296] = {"296", "Converter", "{{Heart}} Converts 1 Soul or Black Heart into 1 heart container"}, -- Converter
-- NOTE FOR LOCALIZERS: There is code to highlight the text of your current floor
-- For it to work, only use line breaks or semicolons to separate floor details, and use the same order as English
[297] = {"297", "Pandora's Box", "{{Warning}} SINGLE USE {{Warning}} Spawns rewards based on floor:#B1: 2{{SoulHeart}}; B2: 2{{Bomb}} + 2{{Key}}#C1: Boss item; C2: B1+C1#D1: 4{{SoulHeart}}; D2: 20{{Coin}}#W1: 2 Boss items#W2: {{Collectible33}} The Bible#???/Void: Nothing#Sheol: Devil item + 1{{BlackHeart}}#Cathe: Angel item + 1{{EternalHeart}}#{{NoLB}}Dark Room: Unlocks {{Collectible523}} Moving Box#Chest: 1{{Coin}}#Home: {{Collectible580}} Red Key"}, -- Pandora's Box
[297] = {"297", "Pandora's Box", "{{Warning}} SINGLE USE {{Warning}} Spawns rewards based on floor:#B1: 2{{SoulHeart}}; B2: 2{{Bomb}} + 2{{Key}}#{{NoLB}}C1: Boss item; C2: C1 + 2{{SoulHeart}}#D1: 4{{SoulHeart}}; D2: 20{{Coin}}#W1: 2 Boss items#W2: {{Collectible33}} The Bible#???/Void: Nothing#Sheol: Devil item + 1{{BlackHeart}}#Cathe: Angel item + 1{{EternalHeart}}#{{NoLB}}Dark Room: Unlocks {{Collectible523}} Moving Box#Chest: 1{{Coin}}#Home: {{Collectible580}} Red Key"}, -- Pandora's Box
[300] = {"300", "Aries", "↑ {{Speed}} +0.25 Speed#Moving above 0.85 Speed makes Isaac immune to contact damage and deals 25 damage to enemies"}, -- Aries
[307] = {"307", "Capricorn", "↑ {{Heart}} +1 Health#↑ {{Speed}} +0.1 Speed#↑ {{Tears}} +0.5 Fire rate#↑ {{Damage}} +0.5 Damage#↑ {{Range}} +0.75 Range#+1 {{Coin}} coin, {{Bomb}} bomb and {{Key}} key"}, -- Capricorn
[308] = {"308", "Aquarius", "Isaac leaves a trail of creep#{{Damage}} The creep deals 66% of Isaac's damage per second and inherits his tear effects"}, -- Aquarius
@@ -221,7 +221,7 @@ local repCollectibles={
[489] = {"489", "D Infinity", "Can be made to act as any die item (except {{Collectible723}} Spindown Dice) with the drop button ({{ButtonRT}})#Charge time varies based on the last die used and updates with every use"}, -- D Infinity
[491] = {"491", "Acid Baby", "{{Pill}} Spawns a random pill every 7 rooms#{{Poison}} Using a pill poisons all enemies in the room"}, -- Acid Baby
[493] = {"493", "Adrenaline", "↑ {{Damage}} Damage up for every empty heart container#The more empty heart containers, the bigger the bonus for each new one"}, -- Adrenaline
[494] = {"494", "Jacob's Ladder", "Tears spawn a spark of electricity on impact#Sparks deal half of Isaac's damage#Sparks can spread to other enemies"}, -- Jacob's Ladder
[494] = {"494", "Jacob's Ladder", "Tears spawn a spark of electricity on impact#Sparks deal half of Isaac's damage#Sparks can arc to up to 4 other enemies"}, -- Jacob's Ladder
[495] = {"495", "Ghost Pepper", "8% chance to shoot a blue fire that blocks enemy shots and deals contact damage#{{Luck}} 50% chance at 10 luck#Fires shrink and disappear after 2 seconds"}, -- Ghost Pepper
[496] = {"496", "Euthanasia", "3.33% chance to shoot a needle#{{Luck}} 25% chance at 13 luck#Needles kill normal enemies instantly, bursting them into 10 tears#{{Damage}} Needles deal 3x Isaac's damage against bosses"}, -- Euthanasia
[497] = {"497", "Camo Undies", "{{Confusion}} Entering a room camouflages Isaac and confuses all enemies until a tear is shot#↑ {{Speed}} +0.5 Speed while cloaked#Uncloaking deals damage around Isaac and grants a very brief fire rate and damage up"}, -- Camo Undies
@@ -248,7 +248,7 @@ local repCollectibles={
[556] = {"556", "Sulfur", "{{Timer}} {{Collectible118}} Brimstone for the room#Using it multiple times in one room grants increased damage and a larger beam"}, -- Sulfur
[557] = {"557", "Fortune Cookie", "Grants one of the following rewards:#A fortune#{{SoulHeart}} A Soul Heart#{{Rune}} A Rune or Soul Stone#{{Card}} A Tarot card#{{Trinket}} A Trinket"}, -- Fortune Cookie
[558] = {"558", "Eye Sore", "Chance to shoot 1-3 extra tears in random directions#{{Luck}} Not affected by luck"}, -- Eye Sore
[559] = {"559", "120 Volt", "Repeatedly zaps nearby enemies#{{Damage}} Electricity deals up to 3.75x Isaac's damage per second"}, -- 120 Volt
[559] = {"559", "120 Volt", "Repeatedly zaps nearby enemies#{{Damage}} Electricity deals up to 3.75x Isaac's damage per second#Sparks can arc to up to 4 other enemies"}, -- 120 Volt
[560] = {"560", "It Hurts", "{{Timer}} When taking damage, receive for the room:#↑ {{Tears}} +1.2 Fire rate on the first hit#↑ {{Tears}} +0.4 Fire rate for each additional hit#Releases a ring of 10 tears around Isaac"}, -- It Hurts
[561] = {"561", "Almond Milk", "↑ {{Tears}} x4 Fire rate multiplier#↓ {{Damage}} x0.3 Damage multiplier#↓ {{Tearsize}} -0.16 Tear size#Tears gain random worm trinket effects and some item effects"}, -- Almond Milk
[562] = {"562", "Rock Bottom", "↑ Prevents stats from being lowered for the rest of the run"}, -- Rock Bottom
@@ -268,7 +268,7 @@ local repCollectibles={
[576] = {"576", "Dirty Mind", "All Dip (small poop) enemies are friendly#Destroying poop spawns 1-4 Dips#Dip type depends on the poop type#Rocks may be replaced with poop"}, -- Dirty Mind
[577] = {"577", "Damocles", "{{Warning}} SINGLE USE {{Warning}}#Hangs a sword above Isaac's head, which doubles all pedestal items#Does not double items that have a price or come from chests#{{Warning}} After taking any damage, the sword has an extremely low chance to instantly kill Isaac every frame#Invincibility effects can prevent the death"}, -- Damocles
[578] = {"578", "Free Lemonade", "Creates a large pool of yellow creep#The creep deals 24 damage per second"}, -- Free Lemonade
[579] = {"579", "Spirit Sword", "Instead of shooting tears, Isaac swings a sword#{{Damage}} The sword deals 3x Isaac's damage +3.5 and swings as fast as the fire button is tapped#{{Chargeable}} Charging does a spin attack + projectile shot#Shoots projectiles with normal swings at full health#{{Tears}} Tears effect the charge time and how often a projectile is shot at full health"}, -- Spirit Sword
[579] = {"579", "Spirit Sword", "Instead of shooting tears, swing a sword#{{Damage}} The sword deals 3x Isaac's damage +3.5 and swings as fast as the fire button is tapped#{{Chargeable}} Charging does a spin attack + projectile shot#Shoots projectiles with swings at full health"}, -- Spirit Sword
[580] = {"580", "Red Key", "Creates a red room adjacent to a regular room, indicated by a door outline#Red Rooms can be special rooms#{{ErrorRoom}} Entering a room outside the 13x13 floor map teleports Isaac to the I AM ERROR room"}, -- Red Key
[581] = {"581", "Psy Fly", "Chases and deflects enemy projectiles#Deals 15 contact damage per second"}, -- Psy Fly
[582] = {"582", "Wavy Cap", "↑ {{Tears}} +0.75 Fire rate#↓ {{Speed}} -0.03 Speed#Distorts the screen#Takes longer to recharge each use#Leaving or clearing rooms reduces the effects"}, -- Wavy Cap
@@ -669,11 +669,11 @@ EID.descriptions[languageCode].abyssSynergies = {
-- Effect of Car battery on Active Items
local repCarBattery = {
[34] = {2, 4}, -- The Book of Belial -- TODO: Is this +1 damage or another +2 from additional uses?
[59] = {2, 4}, -- The Book of Belial (Birthright)
[34] = {2, 3}, -- The Book of Belial
[59] = {2, 3}, -- The Book of Belial (Birthright)
[83] = {" Half", "1"}, -- The Nail
[263] = "Triggers it twice", -- Clear Rune
[283] = {1, 2, "pickup", "{{CR}}pickups"}, -- D100 TODO: TEST THIS is this really the only change
[283] = {1, 2, "pickup", "{{CR}}pickups"}, -- D100
[285] = "Devolves enemies twice", -- D10
[288] = {"4-8", "8-16"}, -- Box of Spiders
[293] = {200, 400}, -- Head of Krampus
@@ -703,7 +703,7 @@ local repCarBattery = {
[713] = {"half a heart", "a heart", "a clot", "2 {{CR}}clots"}, -- Sumptorium
[719] = {" a ", " 2 ", "item/pickup", "{{CR}}items/pickups"}, -- Keeper's Box
[720] = "Spawns a poop alongside the pickup", -- Everything Jar
[722] = "Chains 2 enemies down#If there's only one enemy, chains it for 10 seconds", -- Anima Sola
[722] = "Chains 2 enemies down#If there's only one enemy, chains it for 10 seconds#Using Anima Sola again unchains the closest enemy", -- Anima Sola
[723] = {"one", "two"}, -- Spindown Dice
}
EID:updateDescriptionsViaTable(repCarBattery, EID.descriptions[languageCode].carBattery)
@@ -764,13 +764,14 @@ local repBFFSSynergies = {
["5.100.706"] = "Locust damage is increased by 25%", -- Abyss
["5.100.712"] = "Doubles orbital contact damage", -- Lemegeton
["5.100.713"] = "Clot damage is doubled", -- Sumptorium
["5.100.728"] = {75, 150, 100, 200}, -- Incubus (+ Lilith exception)
["5.100.728"] = {75, 150, 100, 200}, -- Gello (+ Lilith exception)
["5.300.96"] = "Doubles wisp tear and contact damage", -- Soul of Bethany
["5.350.142"] = "Doubles wisp tear and contact damage", -- Beth's Faith
["5.350.182"] = "Doubles wisp tear and contact damage", -- Beth's Essence
["5.350.176"] = "Clot damage is doubled", -- Lil Clot
["5.350.186"] = "Locust damage is increased by 25%", -- Apollyon's Best Friend
["Tainted Lilith"] = "Gello's tear damage is doubled", -- Gello (for BFFS pedestal)
}
EID:updateDescriptionsViaTable(repBFFSSynergies, EID.descriptions[languageCode].BFFSSynergies)
@@ -817,7 +818,7 @@ local repTrinkets={
[138] = {"138", "'M", "Using an active item rerolls it"}, -- 'M
[139] = {"139", "Teardrop Charm", "{{Luck}} +4 Luck towards luck-based tear effects"}, -- Teardrop Charm
[140] = {"140", "Apple of Sodom", "Picking up Red Hearts can convert them into blue spiders#Works even while at full health#Effect may consume hearts needed for healing"}, -- Apple of Sodom
[141] = {"141", "Forgotten Lullaby", "Increases the fire rate of familiars"}, -- Forgotten Lullaby
[141] = {"141", "Forgotten Lullaby", "Doubles the fire rate of familiars"}, -- Forgotten Lullaby
[142] = {"142", "Beth's Faith", "{{Collectible584}} Entering a new floor spawns 4 Book of Virtues wisps"}, -- Beth's Faith
[143] = {"143", "Old Capacitor", "{{Battery}} Prevents active item from charging by clearing a room#{{Battery}} Clearing a room has a 20% chance to spawn a battery#{{Luck}} 33% chance at 5 luck"}, -- Old Capacitor
[144] = {"144", "Brain Worm", "Tears turn 90 degrees to target enemies that they may have missed"}, -- Brain Worm
@@ -1100,7 +1101,7 @@ EID.descriptions[languageCode].horsepills={
{"41", "I'm Drowsy...", "{{Slow}} Slows Isaac and all enemies in the room"}, -- I'm Drowsy...
{"42", "I'm Excited!!", "Speeds up Isaac and all enemies in the room#Triggers again after 30 and 60 seconds"}, --I'm Excited!!
{"43", "Gulp!", "Consumes Isaac's trinket and grants its effects permanently"}, -- Gulp!
{"44", "Horf!", "{{Collectible149}} Shoots a cluster of ipecac tears"}, -- Horf!
{"44", "Horf!", "{{Collectible149}} Shoots a cluster of Ipecac tears"}, -- Horf!
{"45", "Feels like I'm walking on sunshine!", "{{Timer}} Receive for 6.5 seconds:#Invincibility#Isaac can't shoot but deals 40 contact damage per second#{{HalfHeart}} Eating 2 enemies heals half a heart#{{Fear}} Fears all enemies in the room"}, -- Feels like I'm walking on sunshine!
{"46", "Vurp!", "Spawns the last pill Isaac used as a horse pill"}, -- Vurp!
{"47", "Shot speed Down", "↓ {{Shotspeed}} -0.3 Shot speed"}, -- Shot speed Down
@@ -1114,29 +1115,29 @@ EID.descriptions[languageCode].horsepills={
local repCharacterInfo = {
[4] = {"???", "Can't have Red Hearts#Devil deals that would cost 1 or 2 Red Hearts will cost 1 or 2 Soul Hearts instead#Destroying poop spawns 1 blue fly"},
[8] = {"Lazarus", "Once per floor, when you die:#Resurrect as Lazarus Risen#Lose 1 Red Heart container#↑ {{Damage}} 0.5 Damage up"},
[11] = {"Lazarus Risen", "Increased stats and 1.4x damage multiplier#When entering a new floor, turn back into Lazarus"},
[12] = {"Dark Judas", "Can't have Red Hearts#Health ups grant Black Hearts#2x Damage multiplier"},
[11] = {"Lazarus Risen", "Increased stats and x1.4 damage multiplier#When entering a new floor, turn back into Lazarus"},
[12] = {"Dark Judas", "x2 Damage multiplier#Can't have Red Hearts#Health ups grant Black Hearts#Counts as Judas for completion marks"},
[14] = {"Keeper", "Heal by picking up coins#Heart pickups are turned into Blue Flies#Devil deals cost 15 or 30 coins"},
[18] = {"Bethany", "Use Soul Hearts to charge your active item#Can't use Soul Hearts as health#The first Devil room is guaranteed to be an Angel room instead"},
[19] = {"Jacob", "Control Jacob and Esau at the same time#Both characters drop a bomb when one is used#Esau stays in place while holding {{ButtonRT}}#When there's a choice between items, Jacob and Esau can grab two simultaneously"},
[20] = {"Esau", ""},
[18] = {"Bethany", "Use Soul Hearts to charge your active item#Can't use Soul Hearts as health"},
[19] = {"Jacob", "Control Jacob and Esau at the same time#Both characters drop a bomb when one is used#Esau stays in place while holding {{ButtonRT}}#{{ButtonLT}} uses Jacob's active, {{ButtonRB}} uses Esau's active, hold {{ButtonRT}} to use their card/pill#When there's a choice between items, Jacob and Esau can grab two simultaneously"},
[20] = {"Esau", "Control Jacob and Esau at the same time#Both characters drop a bomb when one is used#Esau stays in place while holding {{ButtonRT}}#{{ButtonLT}} uses Jacob's active, {{ButtonRB}} uses Esau's active, hold {{ButtonRT}} to use their card/pill#When there's a choice between items, Jacob and Esau can grab two simultaneously"},
[21] = {"Tainted Isaac", "Item pedestals cycle between 2 options#You can only carry 8 passive items#Cycle which item will be dropped for a 9th item with {{ButtonRT}}"},
[22] = {"Tainted Magdalene", "Health above 2 Red Hearts will slowly drain#On contact, do a melee swing#Chance for enemies to drop Half Red Hearts that disappear in 2 seconds#Drop is guaranteed on melee kill#Heal twice as much from non-pickup sources#Damage taken to draining hearts doesn't affect Devil Deal chance"},
[23] = {"Tainted Cain", "Touching an item pedestal turns it into a variety of pickups#Gain collectibles by crafting 8 pickups together in the Bag of Crafting#The Bag's contents can be shifted with {{ButtonRT}} to replace specific pickups when full"},
[22] = {"Tainted Magdalene", "Health above 2 Red Hearts will slowly drain#On contact, do a melee swing for 6x damage#Chance for enemies to drop Half Red Hearts that disappear in 2 seconds#Drop is guaranteed on melee kill#Heal twice as much from non-pickup sources#Damage taken to draining hearts doesn't affect Devil Deal chance"},
[23] = {"Tainted Cain", "Touching an item pedestal turns it into a variety of pickups#Gain items by crafting 8 pickups together in the Bag of Crafting#The Bag's contents can be shifted with {{ButtonRT}} to replace specific pickups when full"},
[24] = {"Tainted Judas", "Can't have Red Hearts#Health ups grant Black Hearts"},
[25] = {"Tainted ???", "Bombs are replaced with Poop Spells#Doing damage spawns poop pickups#The HUD has a preview of your upcoming poop spells#You can store the next spell for later by using Hold#Can't have Red Hearts"},
[26] = {"Tainted Eve", "Holding Fire will convert your hearts into Clot familiars#Different Heart types spawn Clots with more health and tear effects#Clots lose health over time#Using Sumptorium will absorb the Clots back into your health, if possible#Clots stay in place while holding {{ButtonRT}}"},
[25] = {"Tainted ???", "Can't have Red Hearts#Bombs are replaced with Poop Spells#Doing damage spawns poop pickups#The HUD has a preview of your upcoming poop spells#You can store the next spell for later by using Hold"},
[26] = {"Tainted Eve", "Holding Fire converts your hearts into Clot familiars#Different Heart types spawn Clots with more health and tear effects#Clots lose health over time#Using Sumptorium will absorb the Clots back into your health, if possible#Clots stay in place while holding {{ButtonRT}}#At half a heart left with no Clots, you gain a Mom's Knife-like attack until you heal and leave the room"},
[27] = {"Tainted Samson", "Dealing or taking damage builds up Berserk mode#{{Timer}} When you go berserk, receive for 5 seconds:#↑ {{Speed}} +0.4 Speed#↓ {{Tears}} x0.5 Fire rate multiplier#↑ {{Tears}} +2 Fire rate#↑ {{Damage}} +3 Damage#Restricts attacks to a melee that reflects shots#{{Timer}} Each kill increases the duration by 1 second and grants brief invincibility"},
[28] = {"Tainted Azazel", "When you start charging, you sneeze blood#Hitting an enemy with the sneeze halves your charge time#The sneeze deals 1.5x Azazel's damage#{{BrimstoneCurse}} Affected enemies take extra damage from Brimstone beams#On death, cursed enemies explode and pass on the curse to nearby enemies"},
[29] = {"Tainted Lazarus", "Lazarus has two states, each with their own items and health#Whenever you clear a room/wave or use Flip, you're switched to the other state"},
[30] = {"Tainted Eden", "When you take damage, reroll your stats, items, trinket, and consumables#Items reroll into an item from the same item pool#Self-damage doesn't reroll"},
[31] = {"Tainted Lost", "Cards that spawn have a 10% chance to be Holy Card#Quality {{Quality2}} or less items have a 20% chance to be rerolled#Only \"offensive\" items can spawn"},
[32] = {"Tainted Lilith", "Pressing Fire launches a short-range fetus melee attack that does 3x damage#Holding Fire keeps the fetus out shooting tears"},
[32] = {"Tainted Lilith", "Pressing Fire launches a short-range fetus melee attack that does 3x damage#Holding Fire keeps the fetus out shooting tears towards the nearest enemy"},
[33] = {"Tainted Keeper", "Enemies drop coins that disappear in 2 seconds#Most item pedestals cost 15 coins#Devil deals and Angel items cost 15 or 30 coins#Shops don't require a key and have increased stock"},
[34] = {"Tainted Apollyon", ""},
[35] = {"Tainted Forgotten", "The Forgotten is an immobile bone pile that is picked up and thrown by The Soul for 3x damage#Only The Soul can take damage#Bombs are placed at Forgotten's location#Can't have Red Hearts"},
[36] = {"Tainted Bethany", "Use Red Hearts to charge your active item#Can't have Red Hearts"},
[36] = {"Tainted Bethany", "Use Red Hearts to charge your active item#Can't have Red Hearts#Stat increases are only 75% effective"},
[37] = {"Tainted Jacob", "Dark Esau chases you, charging towards you when close#Anima Sola will chain Dark Esau down briefly, charging at you after 5 seconds or on using Anima Sola again#Dark Esau's charge does a lot of damage to enemies and ignores Boss Armor#If he hits you, you turn into a ghost that dies in one hit for the rest of the floor#While a ghost, one devil deal per room can be taken for free"},
[38] = {"Dead Tainted Lazarus", "Lazarus has two states, each with their own items and health#Whenever you clear a room/wave or use Flip, you're switched to the other state"},
[39] = {"Tainted Jacob 2", ""},
@@ -1319,7 +1320,8 @@ EID.descriptions[languageCode].ModdedRecipesWarningText = "Modded items could ma
-- Conditional descriptions - DO NOT TRANSLATE THE FIRST PART IN ["BRACKETS"]
-- Strings will be appended to the original description
-- Tables with one entry will completely replace the original description
-- Tables with two or more entries are find-replace pairs
-- Tables with two or more entries are find-replace pairs (if there's an odd number of entries, the last entry is appended)
-- For collectible/player conditionals, lines will automatically have their bulletpoint, and {1} is replaced with their name
local repConditions = {
------ GENERAL STRINGS ------
["Tainted Revive"] = "{1} simply revives",
@@ -1403,11 +1405,33 @@ local repConditions = {
["Black Feather"] = "↑ {{Damage}} +0.5 Damage", -- Black Feather items
["Hemoptysis"] = "Works with {1}", -- Hemoptysis + Brimstone items
["5.100.600"] = "x1.2 Fire rate multiplier for {1}", -- Eye Drops (items and some players)
["5.100.482"] = "Tainted characters change into other tainted characters", -- Clicker
["4.5 Volt Timed"] = "No effect on timed recharges", -- 4.5 Volt + Timed Recharges
["4.5 Volt Multiple"] = "Secondary active items only gain charge if the primary active is fully charged", -- 4.5 Volt + Schoolbag/Pocket Actives
["Bulb Zero"] = "Actives with 0 max charges don't count", -- Vibrant/Dim Bulb + zero charge actives
["Brimstone Proptosis"] = "Beams deal 6x damage at point blank range, decreasing with distance",
["Brimstone Ipecac"] = "The laser gets +2 damage and explodes on enemies and obstacles",
["Brimstone Pop!"] = "Shorter beam that shoots {1} tears at the end",
["Eye of Belial Dr. Fetus"] = "Bombs pierce, doing 2.5x damage, but don't home or do additional blast damage",
["Spirit Sword C Section"] = "{1} has priority#Fetuses hold swords and do spin attacks",
["Spirit Sword Mom's Knife"] = "{1} has priority#The spin attack throws the sword forward",
["Spirit Sword Technology"] = "The sword becomes a lightsaber that can reflect enemy shots",
["Spirit Sword Ipecac"] = "The sword gets +6 damage and poisons but doesn't explode#Sword beams do explode",
["Ludovico Ipecac"] = "The tear gets +2 damage but doesn't explode or poison",
["Technology Ipecac"] = "The laser gets +2 damage and explodes on targets",
["Eye of the Occult Beam"] = "Isaac automatically shoots with a crosshair that alters the beam's path",
["Lullaby Tainted Eve"] = "Clot fire rate is doubled",
["Lullaby Lilith"] = "Incubus fire rate is doubled",
-- Jacob's Ladder / 120 Volt battery synergies
["Sparks Damage"] = "Sparks deal 50% more damage",
["Sparks Arc Length"] = "Sparks have longer arc distance",
["Sparks Arc Count"] = "Sparks can arc to 2 more enemies",
["Sparks Arc Back"] = "Sparks can arc back to the same enemy",
}
EID:updateDescriptionsViaTable(repConditions, EID.descriptions[languageCode].ConditionalDescs)
+213 -81
View File
@@ -113,7 +113,17 @@ end
function EID:addPill(id, description, itemName, language)
itemName = itemName or nil
language = language or "en_us"
EID.descriptions[language].custom["5.70." .. id+1] = {id+1, itemName, description, EID._currentMod}
EID.descriptions[language].pills[id+1] = {id, itemName, description, EID._currentMod}
-- Default the horsepill to the same description as the base pill, for mods that only define the base pill
if EID.isRepentance and EID.descriptions[language].horsepills[id+1] == nil then
EID.descriptions[language].horsepills[id+1] = {id, itemName, description, EID._currentMod}
end
end
function EID:addHorsePill(id, description, itemName, language)
if not EID.isRepentance then return end
itemName = itemName or nil
language = language or "en_us"
EID.descriptions[language].horsepills[id+1] = {id, itemName, description, EID._currentMod}
end
-- Adds a metadata for a pilleffect. Used for Placebo/False PHD. Optional parameters: class
@@ -746,7 +756,8 @@ function EID:replaceNameMarkupStrings(text)
if showIcon then iconText = "{{" .. EID:GetIconNameByVariant(entityID[2]) .. entityID[3] .. "}} " end
colorText = VariantToColorText[entityID[2]] or ""
end
name = iconText .. colorText .. EID:getObjectName(entityID[1], entityID[2], entityID[3]) .. "{{CR}}"
if entityID[2] == 70 then name = iconText .. colorText .. EID:getPillName(entityID[3], false) .. "{{CR}}"
else name = iconText .. colorText .. EID:getObjectName(entityID[1], entityID[2], entityID[3]) .. "{{CR}}" end
elseif indicator == "C" then -- Collectible
name = (showIcon and "{{Collectible"..id.."}} " or "") .. "{{ColorYellow}}" .. EID:getObjectName(5, 100, id) .. "{{CR}}"
elseif indicator == "T" then -- Trinket
@@ -827,8 +838,8 @@ function EID:createItemIconObject(str)
end
local pillID,numReplace4 = string.gsub(str, "Pill", "")
if numReplace4 > 0 and pillID ~= "" and tonumber(pillID) ~= nil then
if tonumber(pillID) > maxPillID then return EID.InlineIcons[str] or EID.InlineIcons["Pill"] end
return {"Pills", tonumber(pillID)-1, 9, 8, 0, 1, EID.CardPillSprite}
if tonumber(pillID % 2048) > maxPillID then return EID.InlineIcons[str] or EID.InlineIcons["Pill"] end
return {"Pills", tonumber(pillID % 2048)-1, 9, 8, 0, 1, EID.CardPillSprite}
end
if item == nil then
return nil
@@ -1256,14 +1267,15 @@ end
function EID:PlayersVoidedCollectible(collectibleID)
for i = 0, game:GetNumPlayers() - 1 do
local player = Isaac.GetPlayer(i)
if player:HasCollectible(477) and EID.absorbedItems[tostring(i)] and EID.absorbedItems[tostring(i)][tostring(collectibleID)] then
local playerNum = EID:getPlayerID(player, true)
if player:HasCollectible(477) and EID.absorbedItems[tostring(playerNum)] and EID.absorbedItems[tostring(playerNum)][tostring(collectibleID)] then
return true, player, i
end
end
return false
end
function EID:PlayerVoidedCollectible(player, collectibleID)
local i = EID:getPlayerID(player)
local i = EID:getPlayerID(player, true)
if player:HasCollectible(477) and EID.absorbedItems[tostring(i)] and EID.absorbedItems[tostring(i)][tostring(collectibleID)] then
return true
end
@@ -1365,6 +1377,24 @@ function EID:GetMaxCollectibleID()
return id
end
local maxTrinketID = nil
function EID:GetMaxTrinketID()
if maxTrinketID then
return maxTrinketID
end
local id = TrinketType.NUM_TRINKETS-1
local step = 16
while step > 0 do
if EID.itemConfig:GetTrinket(id+step) ~= nil then
id = id + step
else
step = step // 2
end
end
maxTrinketID = id
return id
end
function EID:DetectModdedItems()
if EID:GetMaxCollectibleID() > EID.XMLMaxItemID then
return true
@@ -1712,11 +1742,22 @@ function EID:checkPlayersForMissingItems()
end
end
function EID:getPlayerID(entityPlayer)
function EID:getPlayerID(entityPlayer, lazarusAdjust)
if not entityPlayer then return 0 end
for i = 0, game:GetNumPlayers() - 1 do
local player = Isaac.GetPlayer(i)
if GetPtrHash(player) == GetPtrHash(entityPlayer) then
-- Dead Tainted Lazarus exceptions
if lazarusAdjust and EID.isRepentance then
-- Check for Birthright to make the ghostly form use the same base ID as the main form
if player:GetMainTwin() then
if GetPtrHash(player:GetMainTwin()) ~= GetPtrHash(player) then
i = EID:getPlayerID(player:GetMainTwin())
end
end
-- Increase the ID by 666 if Dead Tainted Lazarus
if player:GetPlayerType() == 38 then i = i + 666 end
end
return i
end
end
@@ -1726,6 +1767,11 @@ end
-- Get the current Language. Defaults to english if none is set.
function EID:getLanguage()
local lang = EID.Config["Language"]
-- Reset invalid languages (like en_us_detailed)
if EID.descriptions[lang] == nil then
EID.Config["Language"] = "auto"
lang = "auto"
end
if lang == "auto" then
return Options and EID.LanguageMap[Options.Language] or "en_us"
end
@@ -1827,24 +1873,21 @@ EID.TransformationProgress = {}
function EID:evaluateTransformationProgress(transformation)
for i = 0, game:GetNumPlayers() - 1 do
local player = Isaac.GetPlayer(i)
EID.TransformationProgress[i] = {}
EID.TransformationProgress[i][transformation] = 0
local id = EID:getPlayerID(player, true) -- Dead Tainted Lazarus exception
EID.TransformationProgress[id] = {}
EID.TransformationProgress[id][transformation] = 0
local transformData = EID.TransformationData[transformation]
if not EID.TransformationLookup[transformation] then return end
if REPENTOGON and transformData and transformData.VanillaForm then
-- REPENTOGON lets us ignore everything else for vanilla transformation progress
EID.TransformationProgress[i][transformation] = player:GetPlayerFormCounter(transformData.VanillaForm)
EID.TransformationProgress[id][transformation] = player:GetPlayerFormCounter(transformData.VanillaForm)
elseif transformData and transformData.VanillaForm and player:HasPlayerForm(transformData.VanillaForm) then
EID.TransformationProgress[i][transformation] = transformData.NumNeeded or 3
EID.TransformationProgress[id][transformation] = transformData.NumNeeded or 3
else
local pickupHistory = EID.PlayerItemInteractions[i].pickupHistory
local pickupHistory = EID.PlayerItemInteractions[id].pickupHistory
local pillsTable = {}
-- Dead Tainted Lazarus exception
if player:GetPlayerType() == 38 then
pickupHistory = EID.PlayerItemInteractions[i].altPickupHistory or pickupHistory
end
if pickupHistory then
for j = 1, #pickupHistory do
if pickupHistory[j][1] == "pill" then
@@ -1857,38 +1900,35 @@ function EID:evaluateTransformationProgress(transformation)
end
end
local activesTable = EID.PlayerItemInteractions[i].actives
if player:GetPlayerType() == 38 then
activesTable = EID.PlayerItemInteractions[i].altActives or activesTable
end
local activesTable = EID.PlayerItemInteractions[id].actives
for entityString, _ in pairs(EID.TransformationLookup[transformation]) do
local eType, eVariant, eSubType = entityString:match("([^.]+).([^.]+).([^.]+)")
if tonumber(eType) == EntityType.ENTITY_PICKUP then
if tonumber(eVariant) == PickupVariant.PICKUP_COLLECTIBLE then
local currentCount = EID.TransformationProgress[i][transformation]
local currentCount = EID.TransformationProgress[id][transformation]
if activesTable[tostring(eSubType)] then
EID.TransformationProgress[i][transformation] = EID.TransformationProgress[i][transformation] + activesTable[tostring(eSubType)]
EID.TransformationProgress[id][transformation] = EID.TransformationProgress[id][transformation] + activesTable[tostring(eSubType)]
else
local collCount = player:GetCollectibleNum(eSubType, true)
if EID.PlayerItemInteractions[i].rerollItems then
collCount = collCount - (EID.PlayerItemInteractions[i].rerollItems[tostring(eSubType)] or 0)
if EID.PlayerItemInteractions[id].rerollItems then
collCount = collCount - (EID.PlayerItemInteractions[id].rerollItems[tostring(eSubType)] or 0)
end
EID.TransformationProgress[i][transformation] = EID.TransformationProgress[i][transformation] + collCount
EID.TransformationProgress[id][transformation] = EID.TransformationProgress[id][transformation] + collCount
-- Undo the Book of Virtues active item getting counted here
if tonumber(eSubType) == 584 and player:GetActiveItem() == 584 then
EID.TransformationProgress[i][transformation] = EID.TransformationProgress[i][transformation] - 1
EID.TransformationProgress[id][transformation] = EID.TransformationProgress[id][transformation] - 1
end
end
-- In AB+, only one copy of a given collectible is counted for trans
if not EID.isRepentance and EID.TransformationProgress[i][transformation] > currentCount + 1 then
EID.TransformationProgress[i][transformation] = currentCount + 1
if not EID.isRepentance and EID.TransformationProgress[id][transformation] > currentCount + 1 then
EID.TransformationProgress[id][transformation] = currentCount + 1
end
elseif tonumber(eVariant) == PickupVariant.PICKUP_TRINKET and player:HasTrinket(eSubType) then
EID.TransformationProgress[i][transformation] = EID.TransformationProgress[i][transformation] + player:GetTrinketMultiplier(eSubType)
EID.TransformationProgress[id][transformation] = EID.TransformationProgress[id][transformation] + player:GetTrinketMultiplier(eSubType)
elseif tonumber(eVariant) == PickupVariant.PICKUP_PILL then
if pillsTable[tostring(eSubType)] then
EID.TransformationProgress[i][transformation] = EID.TransformationProgress[i][transformation] + pillsTable[tostring(eSubType)]
EID.TransformationProgress[id][transformation] = EID.TransformationProgress[id][transformation] + pillsTable[tostring(eSubType)]
end
end
end
@@ -1926,23 +1966,25 @@ EID.RecentlyTouchedItems = {}
local hadQueuedItem = {}
function EID:evaluateQueuedItems()
for i = 0, game:GetNumPlayers() - 1 do
EID:InitItemInteractionIfAbsent(i)
local player = Isaac.GetPlayer(i)
local id = EID:getPlayerID(player, true)
EID:InitItemInteractionIfAbsent(id)
if player.QueuedItem then
-- Refresh our descriptions and grid entity list upon a queued passive item being added to a player
if not player.QueuedItem.Item and hadQueuedItem[i] then
if not player.QueuedItem.Item and hadQueuedItem[id] then
EID.ForceRefreshCache = true
EID:CheckCurrentRoomGridEntities()
end
hadQueuedItem[i] = player.QueuedItem.Item ~= nil
if EID.PlayerItemInteractions[i].LastTouch + 45 >= game:GetFrameCount() and player.QueuedItem.Item then
hadQueuedItem[id] = player.QueuedItem.Item ~= nil
if EID.PlayerItemInteractions[id].LastTouch + 45 >= game:GetFrameCount() and player.QueuedItem.Item then
return
else
EID.PlayerItemInteractions[i].LastTouch = 0
EID.PlayerItemInteractions[id].LastTouch = 0
end
if not player.QueuedItem.Touched and player.QueuedItem.Item then
EID.PlayerItemInteractions[i].LastTouch = game:GetFrameCount()
EID.PlayerItemInteractions[id].LastTouch = game:GetFrameCount()
local itemIDStr = tostring(player.QueuedItem.Item.ID)
-- Add touched active items to our transformation progress table
if player.QueuedItem.Item.Type == ItemType.ITEM_ACTIVE then
@@ -1950,24 +1992,23 @@ function EID:evaluateQueuedItems()
-- (Fixes co-op bugs, compared to only initiating it for the toucher)
for j = 0, game:GetNumPlayers() - 1 do
EID.PlayerItemInteractions[j].actives[itemIDStr] = EID.PlayerItemInteractions[j].actives[itemIDStr] or 0
EID.PlayerItemInteractions[j].altActives[itemIDStr] = EID.PlayerItemInteractions[j].altActives[itemIDStr] or 0
end
-- Dead Tainted Lazarus exceptions
local activesTable = EID.PlayerItemInteractions[i].actives
if player:GetPlayerType() == 38 then
activesTable = EID.PlayerItemInteractions[i].altActives or activesTable
EID.PlayerItemInteractions[j+666].actives[itemIDStr] = EID.PlayerItemInteractions[j+666].actives[itemIDStr] or 0
end
local activesTable = EID.PlayerItemInteractions[id].actives
EID.ForceRefreshCache = true
activesTable[itemIDStr] = activesTable[itemIDStr] + 1
elseif player.QueuedItem.Item.Type ~= ItemType.ITEM_TRINKET then
-- In AB+, Halo of Flies is counted as an active item due to inaccuracy with GetCollectibleNum
if (not EID.isRepentance and itemIDStr == "10") then
EID.PlayerItemInteractions[i].actives[itemIDStr] = EID.PlayerItemInteractions[i].actives[itemIDStr] + 1
EID.PlayerItemInteractions[id].actives[itemIDStr] = EID.PlayerItemInteractions[id].actives[itemIDStr] + 1
end
-- Put non-active item pickups into the recent item list, for printing in the Item Reminder
table.insert(EID.RecentlyTouchedItems[i], player.QueuedItem.Item.ID)
EID.ItemReminderSelectedItem = 0
local playerID = i
if EID.isRepentance and player:GetPlayerType() == 38 then playerID = playerID + 666 end
table.insert(EID.RecentlyTouchedItems[playerID], player.QueuedItem.Item.ID)
EID:ResetItemReminderSelectedItems("Passives")
EID.ItemReminderSelectedItems[#EID.ItemReminderCategories - 1] = 0
end
end
end
@@ -1976,15 +2017,17 @@ end
-- if the player ItemInteraction table doesnt exist, create it with its init values
function EID:InitItemInteractionIfAbsent(playerID)
playerID = playerID % 666 -- dead tainted lazarus exception
if not EID.PlayerItemInteractions[playerID] then
EID.PlayerItemInteractions[playerID] = { LastTouch = 0, actives = {}, altActives = {},
pickupHistory = {}, altPickupHistory = {}, rerollItems = {} }
EID.PlayerItemInteractions[playerID] = { LastTouch = 0, actives = {}, pickupHistory = {}, rerollItems = {} }
EID.PlayerItemInteractions[playerID+666] = { LastTouch = 0, actives = {}, pickupHistory = {}, rerollItems = {} }
-- in AB+, initiate Halo of Flies as an active item (collectible ID 10 is used for ALL Pretty Flies)
if not EID.isRepentance then
EID.PlayerItemInteractions[playerID].actives["10"] = 0
end
end
EID.RecentlyTouchedItems[playerID] = EID.RecentlyTouchedItems[playerID] or {}
EID.RecentlyTouchedItems[playerID+666] = EID.RecentlyTouchedItems[playerID+666] or {}
end
@@ -2036,19 +2079,33 @@ function EID:AddPickupToHistory(pickupType, effectID, player, useFlags, pillColo
if EID.isRepentance and (useFlags & UseFlag.USE_MIMIC == UseFlag.USE_MIMIC or useFlags & UseFlag.USE_NOANNOUNCER == UseFlag.USE_NOANNOUNCER) then
allowEchoChamber = false
end
local playerID = EID:getPlayerID(player)
local playerID = EID:getPlayerID(player, true)
EID:InitItemInteractionIfAbsent(playerID)
local historyTable = EID.PlayerItemInteractions[playerID].pickupHistory
-- Dead Tainted Lazarus exception
if player:GetPlayerType() == 38 then
historyTable = EID.PlayerItemInteractions[playerID].altPickupHistory or historyTable
end
-- pickupType = ["pill","card"], pillColorID, effectID, hadEchoChamberWhenUsed
table.insert(historyTable, 1, {pickupType, pillColorID, effectID, EID.isRepentance and player:HasCollectible(700) and allowEchoChamber})
end
EID.WildCardEffects = {}
EID.WildCardPillColor = {}
EID.TemporaryWildCardEffects = {} -- resets every frame
function EID:TrackWildCardEffects(effectID, player, pillColor)
local playerID = EID:getPlayerID(player, true)
-- ? Card exception; both it and the active it used are ignored by Wild Card
if effectID == "5.300.48" then
-- Blank Card using ? Card exception; Blank Card being used is still seen
if EID.TemporaryWildCardEffects[playerID] ~= "5.100.286" then EID.TemporaryWildCardEffects[playerID] = nil end
else
EID.TemporaryWildCardEffects[playerID] = effectID
EID.WildCardPillColor[playerID] = pillColor -- doesn't matter that much so just set it here
end
end
function EID:UpdateWildCardEffects()
for k,v in pairs(EID.TemporaryWildCardEffects) do EID.WildCardEffects[k] = v end
EID.TemporaryWildCardEffects = {}
end
-- Render a sprite of an entity
function EID:RenderEntity(entity, sprite, position)
if entity.Type == 5 and entity.Variant == 100 then
@@ -2072,7 +2129,7 @@ end
-- Collects items that the player got after using D4 item
function EID:CollectRerolledItemsOfPlayer(player)
if maxCollectibleID == nil then maxCollectibleID = EID:GetMaxCollectibleID() end
local playerID = EID:getPlayerID(player)
local playerID = EID:getPlayerID(player, true)
EID.PlayerItemInteractions[playerID].rerollItems = {}
for i = 1, maxCollectibleID do
local count = player:GetCollectibleNum(i, true)
@@ -2104,6 +2161,12 @@ function EID:GetEntityXMLName(Type, Variant, SubType)
return EID.XMLEntityNames[Type.."."..Variant] or EID.XMLEntityNames[Type.."."..Variant.."."..SubType]
end
---@diagnostic disable-next-line: duplicate-set-field
function EID:GetEntityXMLNameByString(tvsString)
local Type, Var, Sub = EID:SplitTVS(tvsString)
return EID:GetEntityXMLName(Type, Var, Sub)
end
-- Get an item's RNG seed. We have no use for the RNG object itself because every other function it can do will advance the item's RNG, altering the game state
function EID:GetItemSeed(player, id, variant)
if player == nil then return game:GetSeeds():GetStartSeed()
@@ -2162,44 +2225,90 @@ function EID:UpdateAllPlayerPassiveItems()
local listUpdatedForPlayers = {}
for i = 1, #EID.coopAllPlayers do
local player = EID.coopAllPlayers[i]
local playerNum = EID:getPlayerID(player)
if player == nil then
return listUpdatedForPlayers -- dont evaluate when bad data is present
end
-- only update if collectible number changed
local currentCollectibleCount = player:GetCollectibleCount()
if #EID.RecentlyTouchedItems[playerNum] ~= currentCollectibleCount then
-- remove items the player no longer has. reverse itteration to make deletion easier
for index = #EID.RecentlyTouchedItems[playerNum], 1, -1 do
if not player:HasCollectible(EID.RecentlyTouchedItems[playerNum][index], true) then
table.remove(EID.RecentlyTouchedItems[playerNum], index)
listUpdatedForPlayers[i] = true
end
local playerNum = EID:getPlayerID(player, true)
-- remove items the player no longer has. reverse iteration to make deletion easier
for index = #EID.RecentlyTouchedItems[playerNum], 1, -1 do
if not player:HasCollectible(EID.RecentlyTouchedItems[playerNum][index], true) then
table.remove(EID.RecentlyTouchedItems[playerNum], index)
listUpdatedForPlayers[i] = true
-- If an item earlier than our oldest item is removed (e.g. Eve sacrificial altaring her Dead Bird), reduce it
if index < EID.OldestItemIndex[playerNum] then EID.OldestItemIndex[playerNum] = EID.OldestItemIndex[playerNum] - 1 end
end
end
-- add items the player did get with non-standard methods (console command, item effects, etc...)
for _, itemID in ipairs(passives) do
if player:HasCollectible(itemID, true) then
local alreadyInList = false
for _, heldItemID in ipairs(EID.RecentlyTouchedItems[playerNum]) do
if itemID == heldItemID then
alreadyInList = true
break
end
end
if not alreadyInList then
table.insert(EID.RecentlyTouchedItems[playerNum], itemID)
listUpdatedForPlayers[i] = true
-- add items the player did get with non-standard methods (console command, item effects, etc...)
for _, itemID in ipairs(passives) do
if player:HasCollectible(itemID, true) then
local alreadyInList = false
for _, heldItemID in ipairs(EID.RecentlyTouchedItems[playerNum]) do
if itemID == heldItemID then
alreadyInList = true
break
end
end
if not alreadyInList then
table.insert(EID.RecentlyTouchedItems[playerNum], itemID)
listUpdatedForPlayers[i] = true
end
end
end
end
return listUpdatedForPlayers
end
EID.OldestItemIndex = {}
function EID:SetOldestItemIndex()
for i = 0, game:GetNumPlayers() - 1 do
EID.RecentlyTouchedItems[i] = EID.RecentlyTouchedItems[i] or {}
if EID.OldestItemIndex[i] == nil then EID.OldestItemIndex[i] = #EID.RecentlyTouchedItems[i] + 1 end
-- set up Dead Tainted Lazarus to be oldest slot 1
if EID.OldestItemIndex[i+666] == nil then EID.OldestItemIndex[i+666] = 1 end
end
end
EID.GulpedTrinkets = {}
-- Check for gulped trinkets that have been removed (e.g. perfection, walnut)
function EID:UpdateAllPlayerTrinkets()
for i = 1, #EID.coopAllPlayers do
local player = EID.coopAllPlayers[i]
if player == nil then return end
local playerNum = EID:getPlayerID(player, true)
if EID.GulpedTrinkets[playerNum] == nil then return end
-- remove items the player no longer has. reverse iteration to make deletion easier
for index = #EID.GulpedTrinkets[playerNum], 1, -1 do
if not player:HasTrinket(EID.GulpedTrinkets[playerNum][index]) then
table.remove(EID.GulpedTrinkets[playerNum], index)
end
end
end
end
EID.WispsPerPlayer = {}
-- This is automatically called shortly after main.lua sees a Lemegeton get used, and when the Item Reminder is opened
function EID:UpdateAllPlayerLemegetonWisps()
EID.WispsPerPlayer = {}
for _, wisp in ipairs(Isaac.FindByType(3, 237, -1, true, false)) do
local wispPlayer = wisp:ToFamiliar() and wisp:ToFamiliar().Player
if wispPlayer then
local playerNum = EID:getPlayerID(wispPlayer, true)
EID.WispsPerPlayer[playerNum] = EID.WispsPerPlayer[playerNum] or {}
table.insert(EID.WispsPerPlayer[playerNum], wisp)
end
end
-- Sort wisps by age (newest first), and leave just the IDs
for playerNum,wisps in pairs(EID.WispsPerPlayer) do
table.sort(wisps, function(a, b) return a.FrameCount < b.FrameCount end)
for i,v in ipairs(wisps) do wisps[i] = v.SubType end
end
end
-- Replaces Variable placeholders in string with a given value
-- Example: "My {1} message" --> "My test message"
@@ -2207,3 +2316,26 @@ function EID:ReplaceVariableStr(str, varID, newString)
if type(str) ~= "string" or newString == nil then return str end
return str:gsub("{"..varID.."}", newString)
end
-- deep table copy, copied from http://lua-users.org/wiki/CopyTable
function EID:CopyTable(orig)
local orig_type = type(orig)
local copy
if orig_type == 'table' then
copy = {}
for orig_key, orig_value in next, orig, nil do
copy[EID:CopyTable(orig_key)] = EID:CopyTable(orig_value)
end
setmetatable(copy, EID:CopyTable(getmetatable(orig)))
else -- number, string, boolean, etc
copy = orig
end
return copy
end
-- simple decimal rounding, instead of just floor or ceil
function EID:SimpleRound(num, dp)
dp = dp or 2
local mult = 10^dp
return math.floor(num * mult + 0.5)/mult
end
+112 -30
View File
@@ -24,15 +24,26 @@ else EID:AddItemConditional("5.300", 451, nil, {locTable = "tarotClothBuffs", re
-- Car Battery
EID:AddItemConditional("5.100", 356, EID.CheckForCarBattery, {locTable = "carBattery", replaceColor = "BlinkYellowGreen", noFallback = false})
EID:AddConditional(356, EID.CheckActivesForCarBattery, "No Effect") -- "No effect" text for Car Battery pedestal
EID:AddConditional(356, EID.CheckActivesForCarBattery, nil, {locTable = "carBattery", useResult = true, layer = 2}) -- Effect text for Car Battery pedestal
EID:AddConditional(356, EID.CheckActivesForNoCarBattery, "No Effect", {layer = 1}) -- "No effect" text for Car Battery pedestal
-- BFFS! / Hive Mind
EID:AddItemConditional({"5.100","5.350.54","5.350.57"}, 247, EID.CheckForBFFS, {locTable = "BFFSSynergies", replaceColor = "BlinkPink", noFallback = false})
EID:AddConditional(247, EID.CheckFamiliarsForBFFS, "No Effect") -- "No effect" text for BFFS pedestal
-- BFFS! / Hive Mind / Forgotten Lullaby
EID:AddItemConditional({"5.100","5.350.54","5.350.57"}, 247, EID.CheckForBFFS, {locTable = "BFFSSynergies", replaceColor = "BlinkPink", noFallback = false, uniqueID = "BFFS"})
EID:AddConditional(247, EID.CheckFamiliarsForBFFS, nil, {locTable = "BFFSSynergies", useResult = true, layer = 2}) -- Effect text for BFFS pedestal
EID:AddPlayerConditional(247, 13, "Lilith", {locTable = "BFFSSynergies", layer = 3}, false) -- Lilith's Incubus
EID:AddConditional(247, EID.CheckFamiliarsForNoBFFS, "No Effect", {layer = 1}) -- No effect text for BFFS pedestal
if EID.isRepentance then
EID:AddItemConditional({"5.300.96", "5.350.142", "5.350.176", "5.350.182", "5.350.186"}, 247, EID.CheckForBFFS, {locTable = "BFFSSynergies", replaceColor = "BlinkPink", noFallback = false}) -- BFFS! Repentance soulstone/trinkets
EID:AddItemConditional("5.100", 248, EID.CheckForHiveMind, {locTable = "BFFSSynergies", replaceColor = "BlinkBlue", noFallback = false}) -- Hive Mind
EID:AddSynergyConditional(247, 248, "No Effect (Familiars)") -- Already having Hive Mind / BFFS!
EID:AddPlayerConditional(247, 32, "Tainted Lilith", {locTable = "BFFSSynergies", layer = 3}) -- Tainted Lilith's Gello
EID:AddItemConditional("5.100", 248, EID.CheckForHiveMind, {locTable = "BFFSSynergies", replaceColor = "BlinkBlue", noFallback = false, uniqueID = "BFFS"}) -- Hive Mind
EID:AddSynergyConditional(247, 248, "No Effect (Familiars)", {layer = 5}) -- Already having Hive Mind / BFFS!
EID:AddConditional(248, EID.CheckFamiliarsForHiveMind, nil, {locTable = "BFFSSynergies", useResult = true, layer = 2}) -- Effect text for Hive Mind pedestal
EID:AddSynergyConditional({584, 685, 702, 728}, "5.350.141", "No Effect From", "No Effect") -- Forgotten Lullaby no effect familiars (wisps, Gello)
EID:AddPlayerConditional("5.350.141", 32, "No Effect", {bulletpoint = "Collectible728", variableText = "{{NameOnlyC728}}"}) -- Forgotten Lullaby no effect on Tainted Lilith's Gello
EID:AddPlayerConditional("5.350.141", 13, "Lullaby Lilith", nil, false)
EID:AddPlayerConditional("5.350.141", 26, "Lullaby Tainted Eve")
end
-- Abyss, Birthright Book of Belial, Binge Eater
@@ -53,7 +64,8 @@ EID:AddConditional({266, "5.350.46", 385}, EID.IsGreedMode, "Room to Wave")
-- append/overwrite some descriptions
EID:AddConditional({483, 535, "5.300.15", "5.300.19", "5.300.20", 246, 333, "5.350.120", "5.350.34", "5.350.36", "5.350.41", "5.350.44", "5.350.45", "5.350.72", 514 }, EID.IsGreedMode) -- Mama Mega, Blanket, Temperance, The Moon, The Sun, Blue Map, The Mind, Hairpin, some nogreed trinkets, Broken Modem
EID:AddConditional({"5.350.5", 208}, EID.IsGreedMode, "No Champion Drops")
EID:AddConditional({"5.350.5", 208}, EID.IsGreedMode, "No Champion Drops") -- Champion Belt, Purple Heart
EID:AddConditional(297, EID.IsGreedMode, "Greed") -- Pandora's Box
if EID.isRepentance then
EID:AddConditional({567, 693, "5.350.163", "5.350.167", }, EID.IsGreedMode, "Room to Wave")
@@ -85,6 +97,7 @@ EID:AddPlayerConditional(227, 14, "Keeper 0-1") -- Keeper + Piggy Bank
EID:AddPlayerConditional(501, 14) -- Keeper + Greed's Gullet
EID:AddPlayerConditional(230, 14, "Keeper") -- Keeper + Abaddon
EID:AddPlayerConditional(152, 2, "Technology 2 One Eye") -- Cain + Technology 2
EID:AddPlayerConditional(122, 5, nil, nil, false) -- Eve + Whore of Babylon
if EID.isRepentance then
-- Tainted characters reviving as themselves
EID:AddPlayerConditional({ 161, "5.350.28" }, 25, "Tainted Revive") -- Ankh, Broken Ankh
@@ -112,12 +125,12 @@ end
------ DUPLICATE COPIES OF ITEMS ------
-- Items that have no effect from multiple copies (AddSelfConditional adds it when holding Diplopia automatically)
-- Items that have no effect from multiple copies (AddSelfConditional adds it when holding Diplopia / Crooked Penny automatically)
-- This list is mostly taken from Diplopia's wiki page, there's a lot more with no effect out there I'm sure
EID:AddSelfConditional({7, 55, 63, 69, 87, 104, 106, 108, 109, 116, 122, 132, 139, 149, 152, 156, 162, 169, 191, 200, 203, 214, 221, 225, 231, 233, 238, 239, 243, 244, 247, 248, 249, 261, 276, 299, 300, 313, 316, 330, 350, 356, 366, 368, 371, 374, 379, 400, 401, 408, 411, 412, 414, 416, 423, 429, 444, 446, 447, 450, 451, 458, 494, 495, 496, 501, 524, 525, 529, 532, 533, 534, 540, 546, }, "No Effect (Copies)")
-- Items that have an interesting effect from multiple copies
EID:AddSelfConditional({2, 64, 118, 153, 245, 358}, "Copies")
-- Items that can't be duplicated
-- Items that can't be duplicated by Diplopia
EID:AddItemConditional(347, 347, "Can't Be Duplicated", nil, false) -- Diplopia
if not EID.isRepentance then
EID:AddSelfConditional({115, 222, 224, 228, 531}, "No Effect (Copies)")
@@ -131,19 +144,71 @@ end
------ OVERRIDES / OVERRIDDEN BY -----
-- huge TODO here, a lot of AB+ only ones too
-- TODO: Check Azazel and Forgotten's effects with these items, especially Brimstone overrides
-- Monstro's Lung might be worthy of this list too?
-- Is the layer order correct here? Would I be better off making a new function for adding these overrides that has its own pre-defined layer numbers for the problematic items, to clean up this mess some?
EID:AddSynergyConditional({52, 69, 104, 132, 222, 224, 233, 316, 329, 369, 379, 397, 401, 410, 440, 444, 453, 459, 461, 462, 494, 524, 532, 533, 540, }, 168, "Overridden", "Overrides", {layer = 900, checkLayers = true}) -- Epic Fetus
EID:AddOneSidedSynergyConditional(168, 118, "Epic Fetus Brimstone", {layer = 900, checkLayers = true})
EID:AddOneSidedSynergyConditional(168, 114, "Epic Fetus Mom's Knife", {layer = 900, checkLayers = true})
EID:AddOneSidedSynergyConditional(168, 330, "Epic Fetus Soy Milk", {layer = 900, checkLayers = true})
EID:AddSynergyConditional({69, 132, 222, 316, 369, 379, 410, 440, 453, 459, 461, 494, 524, 532, 533, }, 52, "Overridden", "Overrides", {layer = 800, checkLayers = true}) -- Dr. Fetus
EID:AddSynergyConditional(462, 52, "Eye of Belial Dr. Fetus", nil, {layer = 800, checkLayers = true})
EID:AddSynergyConditional({5, 69, 132, 221, 224, 316, 379, 401, 410, 459, 461, 462, 529, 532, 533, }, 114, "Overridden", "Overrides", {layer = 700, checkLayers = true}) -- Mom's Knife
EID:AddOneSidedSynergyConditional(114, 118, "Brimstone Mom's Knife", {layer = 700, checkLayers = true})
EID:AddSynergyConditional({316, 379, 410, 440, 453, 461, 462, 524, 533, 540, }, 118, "Overridden", "Overrides", {layer = 666, checkLayers = true}) -- Brimstone
EID:AddSynergyConditional(118, 149, "Brimstone Ipecac", nil, {layer = 666, checkLayers = true})
EID:AddSynergyConditional({5, 69, 104, 233, 316, 329, 379, 397, 410, 453, 461, 524, 529, 532, 533, 540, "5.350.26"}, 395, "Overridden", "Overrides", {layer = 600, checkLayers = true}) -- Tech X
EID:AddSynergyConditional(149, 395, "Technology Ipecac", nil, {layer = 600, checkLayers = true}) -- Tech X + Ipecac
EID:AddSynergyConditional({410, 462, 524, 533, 540}, 68, "Overridden", "Overrides", {layer = 400, checkLayers = true}) -- Technology
EID:AddSynergyConditional(149, 68, "Technology Ipecac", nil, {layer = 400, checkLayers = true}) -- Technology + Ipecac
EID:AddSynergyConditional({69, 222, 224, 316, 394, 397, 410, 532}, 329, "Overridden", "Overrides", {layer = 300, checkLayers = true}) -- Ludovico
EID:AddSynergyConditional(149, 329, "Ludovico Ipecac", nil, {layer = 300, checkLayers = true}) -- Ludovico + Ipecac
if not EID.isRepentance then
EID:AddSynergyConditional({374, 429, }, 168, "Overridden", "Overrides", {layer = 900, checkLayers = true}) -- Epic Fetus
EID:AddSynergyConditional({374, 401, 429, 444, 461}, 52, "Overridden", "Overrides", {layer = 800, checkLayers = true}) -- Dr. Fetus
EID:AddSynergyConditional({104, 150, 374, 394, 443, 453, 463, 494, 496, 503, }, 114, "Overridden", "Overrides", {layer = 700, checkLayers = true}) -- Mom's Knife
EID:AddSynergyConditional({104, 224, 369, 374, 394, 401, 429, 444, 459, 463, 494, 532, }, 118, "Overridden", "Overrides", {layer = 666, checkLayers = true}) -- Brimstone
EID:AddSynergyConditional({55, 87, 150, 221, 374, 394, 401, 429, 443, 444, 463, 494, 496, 503, "5.350.96"}, 395, "Overridden", "Overrides", {layer = 600, checkLayers = true}) -- Tech X
EID:AddSynergyConditional({69, 104, 222, 224, 245, 316, 369, 374, 394, 429, 494, }, 68, "Overridden", "Overrides", {layer = 400, checkLayers = true}) -- Technology
EID:AddSynergyConditional({52, 68, 114, 118, 168, 329, 395}, 69, "Chocolate Milk Overrides", nil, {uniqueID = "choccy"}) -- Chocolate Milk providing fire rate (the override/overridden line happens too)
end
if EID.isRepentance then
EID:AddOneSidedSynergyConditional(678, 579, "Spirit Sword C Section", {layer = 1001, checkLayers = true}) -- C Section + Spirit Sword
EID:AddSynergyConditional({52, 69, 118, 168, 229, 316, 329, 379, 394, 395, 397, 440, 556, 597, }, 579, "Overridden", "Overrides", {layer = 1000, checkLayers = true}) -- Spirit Sword
EID:AddOneSidedSynergyConditional(579, 114, "Spirit Sword Mom's Knife", {layer = 1000, checkLayers = true}) -- Spirit Sword + Mom's Knife
EID:AddOneSidedSynergyConditional(579, 68, "Spirit Sword Technology", {layer = 1000, checkLayers = true}) -- Spirit Sword + Technology
EID:AddOneSidedSynergyConditional(579, 149, "Spirit Sword Ipecac", {layer = 1000, checkLayers = true}) -- Spirit Sword + Ipecac
EID:AddSynergyConditional({553, 572, 678, "5.350.144"}, 168, "Overridden", "Overrides", {layer = 900, checkLayers = true}) -- Epic Fetus
EID:AddOneSidedSynergyConditional(561, 168, "Epic Fetus Soy Milk", {layer = 900, checkLayers = true}) -- Epic Fetus + Almond Milk
EID:AddSynergyConditional({69, 229, 316, 329, 397, 410, 533, 572, 597, }, 678, "Overridden", "Overrides", {layer = 850, checkLayers = true}) -- C Section
EID:AddSynergyConditional({68, 118, 572, 597, 637, "5.350.144"}, 52, "Overridden", "Overrides", {layer = 800, checkLayers = true}) -- Dr. Fetus
EID:AddSynergyConditional({52, 572, 597}, 114, "Overridden", "Overrides", {layer = 700, checkLayers = true}) -- Mom's Knife
EID:AddSynergyConditional({597}, 118, "Overridden", "Overrides", {layer = 666, checkLayers = true}) -- Brimstone
EID:AddOneSidedSynergyConditional({529, 532}, 118, "Brimstone Pop!", {layer = 666, checkLayers = true}) -- Brimstone + Pop!/Lachryphagy
EID:AddSynergyConditional(572, 118, "Eye of the Occult Beam", nil, {layer = 666}) -- Brimstone + Eye of the Occult
EID:AddSynergyConditional({572, 597, "5.350.144"}, 395, "Overridden", "Overrides", {layer = 600, checkLayers = true}) -- Tech X
EID:AddSynergyConditional({597}, 68, "Overridden", "Overrides", {layer = 400, checkLayers = true}) -- Technology
EID:AddSynergyConditional(572, 68, "Eye of the Occult Beam", nil, {layer = 400}) -- Technology + Eye of the Occult
EID:AddSynergyConditional(330, 561, "Overridden", "Overrides") -- Soy Milk + Almond Milk
end
----- MISC. ITEM CONDITIONS ------
-- IV Bag conditions (need to be applied in a specific order)
EID:AddItemConditional(135, 75, "PHD") -- PHD improves IV Bag
EID:AddPlayerConditional(135, 14, "Keeper 0-1") -- Keeper gets 0-1 coins
if EID.isRepentance then EID:AddConditional(135, EID.IsHardMode, "Hard Mode") end -- Hard Mode pays out less
EID:AddItemConditional(135, 75, "PHD", {layer = 3}) -- PHD improves IV Bag
EID:AddPlayerConditional(135, 14, "Keeper 0-1", {layer = 2}) -- Keeper gets 0-1 coins
if EID.isRepentance then EID:AddConditional(135, EID.IsHardMode, "Hard Mode", {layer = 1}) end -- Hard Mode pays out less
-- Suicide item interactions
EID:AddSynergyConditional({475, "5.300.46"}, {210, 276, 313}, "Suicide 1", "Suicide 2") -- Plan C, Suicide King + Isaac's Heart, Holy Mantle, Gnawed Leaf
@@ -177,7 +242,7 @@ if EID.isRepentance then
EID:AddConditional(647, function() return EID:CheckPlayersForActiveChargeType(nil, 1) end, "4.5 Volt Timed") -- 4.5 Volt + Having a timed active
EID:AddConditional("5.100", function(EID, descObj) return EID:CheckActiveChargeType(descObj.ObjSubType, nil, 1, 647) end, "4.5 Volt Timed", { bulletpoint = "Collectible647"})
EID:AddItemConditional(534, 647, "4.5 Volt Multiple") -- Schoolbag + 4.5 Volt
EID:AddConditional(647, EID.CheckForMultipleActives, "4.5 Volt Multiple")-- 4.5 Volt + Schoolbag/Pocket Actives
EID:AddConditional(647, EID.CheckForMultipleChargeableActives, "4.5 Volt Multiple")-- 4.5 Volt + Schoolbag/Pocket Actives
end
-- Sacrificial Altar interactions
@@ -212,6 +277,13 @@ EID:AddItemConditional("5.70.28", 358) -- Wizard pill + The Wiz
EID:AddItemConditional(523, 477) -- Moving Box is a passive to Void
EID:AddItemConditional({8, 113, 163, 167, 99, 100, 174, 95, 268, 67}, 322, "Mongo Babies") -- Mongo Baby + Copiable familiars
if EID.isRepentance then EID:AddItemConditional(608, 322, "Mongo Babies") end
EID:AddSynergyConditional(261, 222, "Proptosis Anti-Gravity")
EID:AddSynergyConditional(394, 69, "Chocolate Milk Marked")
EID:AddConditional("5.300.5", EID.InStageVoid) -- The Emperor random boss room
EID:AddConditional("5.300.10", EID.InStageNoTreasureRoom) -- The Hermit possibly no shop
EID:AddConditional("5.300.18", EID.InStageNoTreasureRoom, nil, {layer = 3}) -- The Stars possibly no treasure room
EID:AddConditional("5.300.18", EID.IsGreedMode, "Greed", {layer = 2}) -- The Stars random treasure room
EID:AddConditional("5.300.18", EID.InStageTheShop, "Late Greed", {layer = 1}) -- The Stars no treasure room (I probably went too high detail on this)
-- AB+ only misc conditionals
if not EID.isRepentance then
@@ -222,7 +294,6 @@ end
-- Rep only misc conditionals
if EID.isRepentance then
-- Co-op friendly items
-- todo: what items have a cool co-op synergy?
EID:AddConditional({45, "5.350.125"}, EID.MultiplePlayerCharacters) -- Yum Heart, Extension Cord
EID:AddConditional({"1000.76.0", "1000.76.5"}, EID.MultiplePlayerCharacters) -- Dice Room 1 and 6
@@ -231,46 +302,57 @@ if EID.isRepentance then
EID:AddItemConditional("5.350.172", 260) -- Black Candle + Cursed Penny
EID:AddItemConditional(501, 416) -- Greed's Gullet + Deep Pockets
EID:AddSynergyConditional(245, { 2, 153, 169 }, nil, "20/20") -- 20/20 + The Inner Eye, Mutant Spider, Polyphemus
EID:AddSynergyConditional(596, {"5.350.118", 704, 62, "5.350.60", 520, 411, 621, "5.350.58", "5.350.189", 657}, "Ice Tears") -- Uranus + On Kill Effects
EID:AddPlayerConditional(596, 27, "Ice Tears") -- Uranus + Tainted Samson
EID:AddSynergyConditional(495, 616, "Both Peppers") -- Ghost Pepper + Bird's Eye
EID:AddSynergyConditional(726, {408, 646, 293, 679, 275, 399, 680, 441, 49, 533}, "Hemoptysis") -- Hemoptysis + Brimstone effects
-- eye drops + passives like brimstone go here but there's a lot of them
-- eye drops + chargeable passives like brimstone could go here but there's a lot of them
EID:AddPlayerConditional(600, {2, 7, 13, 16}) -- Eye Drops + Cain, Azazel, Lilith, Forgotten
EID:AddSynergyConditional(152, {708, 444}, "Technology 2 One Eye") -- Technology 2 + Stapler, Lead Pencil
EID:AddConditional(482, EID.CheckForTaintedPlayer)
EID:AddItemConditional(297, "5.350.175", "PandorasBoxStrangeKeyEffect", {noTable = true})
-- Jacob's Ladder / 120 Volt battery synergies
EID:AddSynergyConditional({494, 559}, {205, 356}, "Sparks Damage")
EID:AddSynergyConditional({494, 559}, {116, "5.350.72", "5.350.120"}, "Sparks Arc Length")
EID:AddSynergyConditional({494, 559}, {63, 520, "5.350.3"}, "Sparks Arc Count")
EID:AddSynergyConditional({494, 559}, {"5.350.143"}, "Sparks Arc Back")
-- Ghost Pepper / Bird's Eye + farting (The Poop, Kidney Bean, The Bean, The Black Bean, Butter Bean, Wait What?, Mega Bean, No. 2, IBS)
EID:AddSynergyConditional(495, {36, 421, 111, 180, 294, 484, 351, 378}, "Ghost Pepper Fart", nil, {uniqueID = "pepperfart"})
if EID.isRepentance then
EID:AddSynergyConditional(495, 725, "Ghost Pepper Fart", nil, {uniqueID = "pepperfart"})
EID:AddSynergyConditional(616, {36, 421, 111, 180, 294, 484, 351, 378, 725}, "Ghost Pepper Fart", nil, {uniqueID = "pepperfart"})
end
end
--[[
BUURAZU'S TODO STUFF:
Overridden / Overrides (Brimstone, Mom's Knife, Epic Fetus stuff)
Co-op benefit items (not sure what they are tbh)
Overridden / Overrides (Brimstone, Mom's Knife, Epic Fetus stuff) (still need some probably)
Spoiler achievement descriptions (plus a config setting possibly, to always show the spoilers) (Chaos Card and Plan C?)
BFFs / Hive Mind + Tainted Apollyon, Tainted Eve, Tainted Lilith; melody trinket + Tainted Eve/Lilith; these are insane synergies that deserve attention
Maybe a find/replace pair for some Keeper descriptions that talk about Red hearts but work for him, Red -> Coin or Red/Coin; Could be good for Dead Cat. or just leave it be
Crystal Key + Pandora's Box should be moved here? Or leave it in modifiers
Are Blank Card + Placebo + Clear Rune ready to get moved to here now that I have good ways to return values?
Jacob's Ladder synergies with other battery items (I didn't even know about this)
Bean synergies with ghost pepper/bird's eye
Car Battery / BFFS whitelist for showing certain lines on the car/bffs pedestal, not just "No effect"
Implement a system where similar texts don't get shown multiple times in one apply conditionals function (hive minds/bffs)
hallowed ground / midas touch + the poop / card against humanity / everything jar synergies
Add Void synergy information for some active items (which?) (warn on things like mom's box you don't get double trinket power?)
Damage multipliers that don't stack
TODOS I'VE DECIDED NOT TODO RIGHT NOW:
Incubus effects; a lot are AB+ only; annoying to test; plus Lilith has to be added for all of them too
TODOs unrelated to conditionals:
Luck modifier that prints out a percentage for the effect based on your current luck stat
Glyph of Balance prediction in Item Reminder?
Purity's current stat boost, if possible
What item is Liberty Cap, Broken Syringe, etc. currently giving?
RNG cheat for Crooked Penny
Implement the standardized colors for characters, items, map names, etc
Character info tab in item reminder
Make Glitched Crown type pedestals work better in EID (pause on one item and press tab to switch to the next item)
Don't show Void stat ups depending on what Void has absorbed (abyss absorbed = no void stat ups etc, reroll item = might become actives)
Wild Card vurp-like desc modifier
REPENTOGON TODOS:
Glyph of balance (test with bethany but repentogon's is probably always right)
Item reminder previews of immaculate/cambion progress (cambion's increases after two familiars; vardata like glowing hourglass?)
Purity's current stat boost
Attack formula simulator? (yeah right)
MAYBE SOME DAYS:
Bag of Crafting "sort by recipe nearest completion in bag" option
+310 -101
View File
@@ -1,4 +1,141 @@
local game = Game()
local modTextsAdded = 0
local function newModdedCondition(text, language)
if text == nil then return nil end
modTextsAdded = modTextsAdded + 1
EID.descriptions[language].ConditionalDescs["Modded Conditional " .. modTextsAdded] = text
return "Modded Conditional " .. modTextsAdded
end
------ FUNCTIONS FOR MODDERS TO ADD CONDITIONALS ------
-- You provide your own strings into these functions
-- Add text to a pedestal's description when you own a different item
-- ID and ownedID can be a collectible ID or a full item string (like "5.350.54")
-- ownedID can also be a function rather than just an ID; if it returns true, the text will be displayed
-- The text will be added as a new line, with the owned item's icon at the start
-- If you pass in replaceText, instead the text is found in the description and replaced with replaceText
-- For convenience, ID can be a table of IDs that will all get the condition applied
-- Optional parameters: replaceText, language, extraTable
-- Example usage: EID:addCondition(myDevilishItemID, EID.IsGreedMode, "{{GreedMode}} Reduces shop prices by 1 for each optional Nightmare wave completed")
function EID:addCondition(ID, ownedID, text, replaceText, language, extraTable)
language = language or "en_us"
if replaceText then text = {text, replaceText} end
local modifierText = newModdedCondition(text, language)
if type(ownedID) ~= "function" then
EID:AddItemConditional(ID, ownedID, modifierText, extraTable)
else
EID:AddConditional(ID, ownedID, modifierText, extraTable)
end
end
-- Shortcut function for when you have two items that have a synergy with each other
-- ID1 will have text1 added to its description if you own ID2
-- ID2 will have text2 (or text1, if text2 isn't given) added to its description if you own ID1
-- ID1 and ID2 can both be tables of IDs that will get the condition applied to each other
-- Optional parameters: text2, language, extraTable
-- Example usage: EID:addSynergyCondition(myHappyLittleItemID, {CollectibleType.COLLECTIBLE_BRIMSTONE, CollectibleType.COLLECTIBLE_SULFUR}, "Turns your laser into a smiley face that charms enemies")
function EID:addSynergyCondition(ID1, ID2, text1, text2, language, extraTable)
language = language or "en_us"
local modifierText1 = newModdedCondition(text1, language)
local modifierText2 = newModdedCondition(text2, language)
EID:AddSynergyConditional(ID1, ID2, modifierText1, modifierText2, extraTable)
end
-- Function for adding text to a pedestal's description when you're playing a specific character
-- The character's head icon will be at the start of appended lines
-- Optional parameters: replaceText, language, extraTable
-- Example usage: EID:addPlayerCondition(myAngstyItemID, PlayerType.PLAYER_EVE, "Gives Eve extra mascara (2x Damage multiplier)")
function EID:addPlayerCondition(ID, playerID, text, replaceText, language, extraTable)
language = language or "en_us"
if replaceText then text = {text, replaceText} end
local modifierText = newModdedCondition(text, language)
EID:AddPlayerConditional(ID, playerID, modifierText, extraTable)
end
-- Shortcut function for tarotClothBuffs, tarotClothBuffsAB, carBattery, abyssSynergies, bookOfBelialBuffs, bingeEaterBuffs
-- Because these are general conditions that only match one item type, it's super easy to add to them
-- The text will be appended; numberToDouble will be found in the description and doubled, as that's the most frequent use case
-- or, if you provide newNumber, it changes numberToDouble to that (technically, it's just a find/replace pair, any strings work)
-- Example usage: EID:addToGeneralCondition(myVeryHealthyItemID, "bingeEaterBuffs", "↑ {{Speed}} +0.15 Speed#↓ {{Tears}} -0.5 Tears#↓ {{Damage}} -0.5 Damage")
function EID:addToGeneralCondition(ID, locTable, text, numberToDouble, newNumber, language)
language = language or "en_us"
if numberToDouble then
newNumber = newNumber or numberToDouble * 2
text = { numberToDouble, newNumber, text }
end
EID.descriptions[language][locTable][ID] = text
end
-- Shortcut function for adding Repentance Tarot Cloth conditions
function EID:addTarotClothBuffsCondition(ID, text, numberToDouble, newNumber, language)
EID:addToGeneralCondition(ID, "tarotClothBuffs", text, numberToDouble, newNumber, language)
end
-- Shortcut function for adding Ab+ Tarot Cloth conditions
function EID:addTarotClothBuffsABCondition(ID, text, numberToDouble, newNumber, language)
EID:addToGeneralCondition(ID, "tarotClothBuffsAB", text, numberToDouble, newNumber, language)
end
-- Shortcut function for adding car battery conditions
function EID:addCarBatteryCondition(ID, text, numberToDouble, newNumber, language)
EID:addToGeneralCondition(ID, "carBattery", text, numberToDouble, newNumber, language)
end
-- Shortcut function for adding abyss synergies conditions
function EID:addAbyssSynergiesCondition(ID, text, numberToDouble, newNumber, language)
EID:addToGeneralCondition(ID, "abyssSynergies", text, numberToDouble, newNumber, language)
end
-- Shortcut function for adding book of belial conditions
function EID:addBookOfBelialBuffsCondition(ID, text, numberToDouble, newNumber, language)
EID:addToGeneralCondition(ID, "bookOfBelialBuffs", text, numberToDouble, newNumber, language)
end
-- Shortcut function for adding binge eater conditions
function EID:addBingeEaterBuffsCondition(ID, text, numberToDouble, newNumber, language)
EID:addToGeneralCondition(ID, "bingeEaterBuffs", text, numberToDouble, newNumber, language)
end
-- Shortcut function for adding BFFS conditions; this is slightly more complex since it supports trinkets
-- Example usage: EID:addBFFSCondition(myBasicFamiliarID, nil, 3.5)
function EID:addBFFSCondition(ID, text, numberToDouble, newNumber, language)
language = language or "en_us"
if numberToDouble then
newNumber = newNumber or numberToDouble * 2
text = { numberToDouble, newNumber, text }
end
if type(ID) ~= "string" then ID = "5.100." .. ID
else
-- We don't have to add a new condition for collectibles, because they're checked with a "5.100" condition
EID:AddItemConditional(ID, 247, EID.CheckForBFFS, {locTable = "BFFSSynergies", replaceColor = "BlinkPink", noFallback = false, uniqueID = "BFFS"})
end
EID.descriptions[language].BFFSSynergies[ID] = text
end
-- Shortcut function for adding Hive Mind conditions; by default, it will show with BFFS too, unless you pass in allowBFFS as false
function EID:addHiveMindCondition(ID, text, numberToDouble, newNumber, language, allowBFFS)
language = language or "en_us"
if allowBFFS == nil then allowBFFS = true end
EID.HiveMindFamiliars[ID] = true
if not allowBFFS then EID.BFFSIgnore[ID] = true end
if numberToDouble then
newNumber = newNumber or numberToDouble * 2
text = {numberToDouble, newNumber, text}
end
if type(ID) ~= "string" then ID = "5.100." .. ID
else
-- We don't have to add a new condition for collectibles, because they're checked with a "5.100" condition
EID:AddItemConditional(ID, 248, EID.CheckForHiveMind, {locTable = "BFFSSynergies", replaceColor = "BlinkBlue", noFallback = false, uniqueID = "BFFS"})
end
EID.descriptions[language].BFFSSynergies[ID] = text
end
------ FUNCTIONS FOR INTERNAL USE ------
-- These need to look up strings from the localization table, and are designed to reduce work needed by localizers. Of course, you can use these in mods if you want
-- They're simple to use in the simplest use case, while powerful enough to handle complicated needs
--[[
Argument 1: The item ID
@@ -16,24 +153,28 @@ local game = Game()
Argument 4 (optional): Table with any additional options, usually not needed:
variableText: If there's a {1} in the desc, it will be replaced with this; can be a function for more dynamic text results, it will get descObj passed into it
locTable: Specify a different table to look for the localization string in, rather than ConditionalDescs
noTable: Set to true to look in the base localizations only (requires modText) (not used yet...)
noTable: Set to true to look in the base localizations only (requires modText)
lineColor: Appended lines will be highlighted with this color
replaceColor: Find/replace text will be highlighted with this color
bulletpoint: Appended lines will begin with this bulletpoint
noFallback: Don't fallback to English if this isn't localized; by default, conditionals don't fallback, to avoid printing English text in unupdated languages
usePedestalName: If true, display the pedestal item's name in place of {1}
Argument 5 (very optional): The position in the table to insert this new condition, in case mods want to insert modifiers before our base ones
useResult: If true, use the result from the conditional function to find the localization string
layer: A number used in determining the order that conditionals should be checked in, default -1
checkLayers: If true, don't print this condition if a higher layer condition was applied already
uniqueID: Only one conditional with the given unique ID will be printed
]]
local function CopyTable(t1)
local newTable = {}; for k, v in pairs(t1) do newTable[k] = v end
return newTable
end
function EID:AddConditional(IDs, funcText, modText, extraTable, insertPoint)
-- Every single add conditional function ends up calling this function eventually. This is THE place to define variables every condition MUST have.
function EID:AddConditional(IDs, funcText, modText, extraTable)
if type(IDs) ~= "table" then IDs = { IDs } end
if modText == "" then modText = nil end
extraTable = extraTable or {}
if extraTable.noFallback == nil then extraTable.noFallback = true end
extraTable.layer = extraTable.layer or -1
for _, id in ipairs(IDs) do
if type(id) ~= "string" then id = "5.100." .. id end
EID.DescriptionConditions[id] = EID.DescriptionConditions[id] or {}
@@ -44,20 +185,13 @@ function EID:AddConditional(IDs, funcText, modText, extraTable, insertPoint)
if newTable.usePedestalName then
newTable.variableText = "{{NameOnly" .. id .. "}}"
end
if insertPoint then
table.insert(EID.DescriptionConditions[id], insertPoint, newTable)
else
table.insert(EID.DescriptionConditions[id], newTable)
end
table.insert(EID.DescriptionConditions[id], newTable)
end
end
-- Easy to use functions for conditionals that rely on having a specific item/character
-- By default, they'll have a bulletpoint for the item/char, and {1} becomes the item/char's name
-- checkInReminder is for if a synergy is no longer relevant once the item isn't obtainable (e.g. Abyss locusts) (true by default)
function EID:AddItemConditional(IDs, ownedIDs, modText, extraTable, checkInReminder)
if type(ownedIDs) ~= "table" then ownedIDs = { ownedIDs } end
if checkInReminder == nil then checkInReminder = true end
@@ -100,6 +234,7 @@ function EID:AddSelfConditional(ownedIDs, modText, extraTable, includeDiplopia)
end
end
-- For adding a conditional based on if a specific character is present
-- includeTainted is for if you want to check the normal and tainted version of a character (true by default)
function EID:AddPlayerConditional(IDs, charIDs, modText, extraTable, includeTainted)
if type(charIDs) ~= "table" then charIDs = { charIDs } end
@@ -114,7 +249,7 @@ function EID:AddPlayerConditional(IDs, charIDs, modText, extraTable, includeTain
end
----- Evaluation Functions -----
------ Evaluation Functions ------
function EID:ConditionalItemCheck(itemID, checkInReminder)
if EID.InsideItemReminder then
@@ -156,6 +291,19 @@ function EID:IsHardMode()
return game.Difficulty == 1 or game.Difficulty == 3
end
function EID:InStageNum(stageNum)
return game:GetLevel():GetAbsoluteStage() == stageNum
end
function EID:InStageVoid()
return EID:InStageNum(12)
end
function EID:InStageNoTreasureRoom()
return game:GetLevel():GetAbsoluteStage() > 6
end
function EID:InStageTheShop()
return EID:IsGreedMode() and EID:InStageNum(0)
end
-- Check if we have any characters that can't have Red Health, to print additions to descs like Dead Cat
function EID:CheckForNoRedHealthPlayer()
if EID.InsideItemReminder then
@@ -172,26 +320,54 @@ function EID:CheckForNoRedHealthPlayer()
return false
end
-- Check if we have characters with Schoolbag or a pocket active item
function EID:CheckForMultipleActives(onlyChargeablePockets)
function EID:CheckForTaintedPlayer()
if EID.InsideItemReminder then
local player = EID.ItemReminderPlayerEntity
if player:HasCollectible(534) then return true end
local id = player:GetPlayerType()
if EID.isRepentance and (EID.PocketActivePlayerIDs[id] == 0 or (not onlyChargeablePockets and EID.PocketActivePlayerIDs[id])) then return true end
return EID.TaintedIDs[player:GetPlayerType()]
else
for i = 0, game:GetNumPlayers() - 1 do
local player = Isaac.GetPlayer(i)
if player:HasCollectible(534) then return true end
if EID.TaintedIDs[player:GetPlayerType()] then
return true
end
end
end
return false
end
-- Check if we have characters with Schoolbag or a pocket active item
function EID:CheckForMultipleActives(descObj, onlyChargeablePockets)
if EID.InsideItemReminder then
local player = EID.ItemReminderPlayerEntity
if player:HasCollectible(534) then return 534 end
local id = player:GetPlayerType()
if EID.isRepentance and (EID.PocketActivePlayerIDs[id] == 0 or (not onlyChargeablePockets and EID.PocketActivePlayerIDs[id])) then return player:GetActiveItem(2) end
else
for i = 0, game:GetNumPlayers() - 1 do
local player = Isaac.GetPlayer(i)
if player:HasCollectible(534) then return 534 end
local id = player:GetPlayerType()
if EID.isRepentance and (EID.PocketActivePlayerIDs[id] == 0 or (not onlyChargeablePockets and EID.PocketActivePlayerIDs[id])) then return true end
if EID.isRepentance and (EID.PocketActivePlayerIDs[id] == 0 or (not onlyChargeablePockets and EID.PocketActivePlayerIDs[id])) then return player:GetActiveItem(2) end
end
end
return false
end
-- Check if we have characters with Schoolbag or a chargeable pocket active item (for 4.5 Volt)
function EID:CheckForMultipleChargeableActives()
return EID:CheckForMultipleActives(true)
function EID:CheckForMultipleChargeableActives(descObj)
return EID:CheckForMultipleActives(descObj, true)
end
-- Check if we have a character with a pocket active
function EID:CheckForPocketActives()
if EID.InsideItemReminder then
local player = EID.ItemReminderPlayerEntity
return EID.PocketActivePlayerIDs[player:GetPlayerType()]
else
for i = 0, game:GetNumPlayers() - 1 do
local player = Isaac.GetPlayer(i)
if EID.PocketActivePlayerIDs[player:GetPlayerType()] then return true end
end
end
return false
end
-- When we have Car Battery, change active pedestal descriptions
@@ -199,30 +375,53 @@ function EID:CheckForCarBattery(descObj)
if EID.CarBatteryNoSynergy[descObj.ObjSubType] then return "No Effect" end
return descObj.ObjSubType
end
-- When we're looking at a Car Battery pedestal, check our actives for having no effect
-- When we're looking at a Car Battery pedestal, check our actives for having an effect or no effect
function EID:CheckActivesForCarBattery(descObj)
if EID.InsideItemReminder then return false end
for k,_ in pairs(EID.CarBatteryNoSynergy) do
if EID:PlayersHaveCollectible(k) then return k end
for k,v in pairs(EID.CarBatteryPedestalWhitelist) do
if v and EID:PlayersHaveCollectible(k) then return k end
end
return false
end
function EID:CheckActivesForNoCarBattery(descObj)
if EID.InsideItemReminder then return false end
for k,v in pairs(EID.CarBatteryNoSynergy) do
if v and EID:PlayersHaveCollectible(k) then return k end
end
return false
end
-- When we have BFFS/Hive Mind, change familiar pedestal descriptions
function EID:CheckForBFFS(descObj)
function EID:CheckForBFFS(descObj, hiveMind)
if EID.BFFSIgnore[descObj.ObjSubType] and not hiveMind then return "N/A" end
if descObj.ObjVariant == 100 and EID.BFFSNoSynergy[descObj.ObjSubType] then return "No Effect" end
return descObj.fullItemString
local adjustedSubtype = EID:getAdjustedSubtype(descObj.ObjType, descObj.ObjVariant, descObj.ObjSubType)
return descObj.ObjType.."."..descObj.ObjVariant.."."..adjustedSubtype
end
function EID:CheckForHiveMind(descObj)
if EID.HiveMindFamiliars[descObj.ObjSubType] then return EID:CheckForBFFS(descObj) end
if EID.HiveMindFamiliars[descObj.ObjSubType] then return EID:CheckForBFFS(descObj, true) end
return "N/A"
end
-- When we're looking at a BFFS pedestal, check our familiars for having no effect (only finds the earliest one, but whatever)
-- When we're looking at a BFFS pedestal, check our familiars for having an effect (only finds the earliest one)
function EID:CheckFamiliarsForBFFS(descObj)
if EID.InsideItemReminder then return false end
for k,_ in pairs(EID.BFFSNoSynergy) do
if EID:PlayersHaveCollectible(k) then return k end
for k,v in pairs(EID.BFFSPedestalWhitelist) do
if v and EID:PlayersHaveCollectible(k) then return "5.100." .. k end
end
return false
end
function EID:CheckFamiliarsForHiveMind(descObj)
if EID.InsideItemReminder then return false end
for k,v in pairs(EID.BFFSPedestalWhitelist) do
if EID.HiveMindFamiliars[k] and v and EID:PlayersHaveCollectible(k) then return "5.100." .. k end
end
return false
end
function EID:CheckFamiliarsForNoBFFS(descObj)
if EID.InsideItemReminder then return false end
for k,v in pairs(EID.BFFSNoSynergy) do
if v and EID:PlayersHaveCollectible(k) then return k end
end
return false
end
@@ -230,7 +429,7 @@ end
-- Check for a player having an active item with a specific quantity of charges, or charge type
-- 0 = normal, 1 = timed, 2 = special
function EID:CheckPlayersForActiveChargeType(maxCharge, chargeType, checkPockets)
checkPockets = checkPockets or true
if checkPockets == nil then checkPockets = true end
local players = {}
if EID.InsideItemReminder then
players[1] = EID:ItemReminderGetAllPlayers()[EID.ItemReminderSelectedPlayer + 1] or EID.player
@@ -317,88 +516,98 @@ function EID:applyConditionals(descObj)
local adjustedSubtype = EID:getAdjustedSubtype(descObj.ObjType, descObj.ObjVariant, descObj.ObjSubType)
local typeVar = descObj.ObjType.."."..descObj.ObjVariant -- for general conditions (Tarot Cloth, Book of Virtues)
local typeVarSub = descObj.ObjType.."."..descObj.ObjVariant.."."..adjustedSubtype -- for specific conditions
local highestLayer = -999
local printedDescs = {}
-- Combine specific+generic conditions into one table (in that order)
local conds = {}
if EID.DescriptionConditions[typeVarSub] then TableConcat(conds, EID.DescriptionConditions[typeVarSub]) end
if EID.DescriptionConditions[typeVar] then TableConcat(conds, EID.DescriptionConditions[typeVar]) end
table.sort(conds, function(a, b) return a.layer > b.layer end)
-- Check every condition we need to check for this item
for _, cond in ipairs(conds) do
-- Search for the localization string; "S" (for generals) or "T.V.S" or "T.V.S (Modifier)" or "Modifier"
local locTable = cond.locTable or "ConditionalDescs"
local text = nil
local modifierText = type(cond.modifierText) == "function" and cond.modifierText(EID, descObj) or cond.modifierText
-- Find our string in the base localization table
if cond.noTable then
text = EID:getDescriptionEntry(modifierText, nil, cond.noFallback)
-- Find our string as either "Type.Var.Sub (Mod Text)" or "Mod Text"
elseif modifierText then
text = EID:getDescriptionEntry(locTable, typeVarSub .. " (" .. modifierText .. ")", cond.noFallback)
if text == nil then text = EID:getDescriptionEntry(locTable, modifierText, cond.noFallback) end
-- Find our string as either "Type.Var.Sub" or just the Subtype
else
text = EID:getDescriptionEntry(locTable, typeVarSub, cond.noFallback)
if text == nil then text = EID:getDescriptionEntry(locTable, descObj.ObjSubType, cond.noFallback) end
end
if not cond.checkLayers or highestLayer <= cond.layer then
local result = cond.func(EID, descObj)
if result then
-- Search for the localization string; "S" (for generals) or "T.V.S" or "T.V.S (Modifier)" or "Modifier"
local locTable = cond.locTable or "ConditionalDescs"
local text = nil
local modifierText = type(cond.modifierText) == "function" and cond.modifierText(EID, descObj) or cond.modifierText
if cond.useResult then modifierText = result end
-- Find our string in the base localization table
if cond.noTable then
text = EID:getDescriptionEntry(modifierText, nil, cond.noFallback)
-- Find our string as either "Type.Var.Sub (Mod Text)" or "Mod Text"
elseif modifierText then
text = EID:getDescriptionEntry(locTable, typeVarSub .. " (" .. modifierText .. ")", cond.noFallback)
if text == nil then text = EID:getDescriptionEntry(locTable, modifierText, cond.noFallback) end
-- Find our string as either "Type.Var.Sub" or just the Subtype
else
text = EID:getDescriptionEntry(locTable, typeVarSub, cond.noFallback)
if text == nil then text = EID:getDescriptionEntry(locTable, descObj.ObjSubType, cond.noFallback) end
end
-- If we find the localization string for this condition, and it passes the test, modify the description text
local result = cond.func(EID, descObj)
if text ~= nil and result then
local variableText, bulletpoint
-- If the condition returned a value, use that value
if result ~= true then
-- For the time being, we assume the result was a collectible number (will support more soon)
variableText = "{{NameOnlyC"..result.."}}"
bulletpoint = "Collectible"..result
else
variableText = type(cond.variableText) == "function" and cond.variableText(EID, descObj) or cond.variableText
bulletpoint = cond.bulletpoint
end
-- String = append
if type(text) == "string" then
text = EID:ReplaceVariableStr(text, 1, variableText)
local iconStr = "#"
if bulletpoint then iconStr = iconStr .. "{{" .. bulletpoint .. "}} " end
if cond.lineColor then iconStr = iconStr .. "{{" .. cond.lineColor .. "}}" end
EID:appendToDescription(descObj, iconStr .. text:gsub("#", iconStr))
-- Table with 1 entry = replace
elseif #text == 1 then
descObj.Description = EID:ReplaceVariableStr(text[1], 1, variableText)
-- Table with 2+ entries = find and replace pairs
-- Entry 1 is replaced with entry 2, entry 3 is replaced with entry 4, etc.
-- If there's an odd number of entries, the last one is appended
else
local pos = 1
while pos < #text do
local toFind = text[pos]
if text[pos + 1] then
local replaceWith = EID:ReplaceVariableStr(text[pos + 1], 1, variableText)
if cond.replaceColor then replaceWith = "{{" .. cond.replaceColor .. "}}" .. replaceWith .. "{{CR}}" end
--"%d*%.?%d+" will grab every number group (1, 10, 0.5), this will allow us to not replace the "1" in "10" erroneously
if (type(toFind) == "number") then
local count = 0
descObj.Description = string.gsub(descObj.Description, "%d*%.?%d+", function(s)
if (s == tostring(toFind) and count == 0) then
count = count + 1
return replaceWith
end
end)
-- Basic find+replace for non-numbers
else
descObj.Description = replace(descObj.Description, tostring(toFind), replaceWith, 1)
end
-- If we find the localization string for this condition, it passed the condition's test, and the layer is ok, modify the description text
if text ~= nil and (not cond.uniqueID or printedDescs[cond.uniqueID] == nil) then
if cond.layer > highestLayer then highestLayer = cond.layer end
if cond.uniqueID then printedDescs[cond.uniqueID] = true end
local variableText, bulletpoint
-- If the condition returned a value, use that value as an item ID for the bulletpoint/{1} replacement
if result ~= true then
if type(result) == "number" then result = "5.100." .. result end
variableText = "{{NameOnly"..result.."}}"
bulletpoint = "Item"..result
else
toFind = EID:ReplaceVariableStr(toFind, 1, variableText)
variableText = type(cond.variableText) == "function" and cond.variableText(EID, descObj) or cond.variableText
bulletpoint = cond.bulletpoint
end
-- String = append
if type(text) == "string" then
text = EID:ReplaceVariableStr(text, 1, variableText)
local iconStr = "#"
if bulletpoint then iconStr = iconStr .. "{{" .. bulletpoint .. "}} " end
if cond.lineColor then iconStr = iconStr .. "{{" .. cond.lineColor .. "}}" end
EID:appendToDescription(descObj, iconStr .. toFind:gsub("#", iconStr))
EID:appendToDescription(descObj, iconStr .. text:gsub("#", iconStr))
-- Table with 1 entry = replace
elseif #text == 1 then
descObj.Description = EID:ReplaceVariableStr(text[1], 1, variableText)
-- Table with 2+ entries = find and replace pairs
-- Entry 1 is replaced with entry 2, entry 3 is replaced with entry 4, etc.
-- If there's an odd number of entries, the last one is appended
else
local pos = 1
while pos <= #text do
local toFind = text[pos]
if text[pos + 1] then
local replaceWith = EID:ReplaceVariableStr(text[pos + 1], 1, variableText)
if cond.replaceColor then replaceWith = "{{" .. cond.replaceColor .. "}}" .. replaceWith .. "{{CR}}" end
--"%d*%.?%d+" will grab every number group (1, 10, 0.5), this will allow us to not replace the "1" in "10" erroneously
if (type(toFind) == "number") then
local count = 0
descObj.Description = string.gsub(descObj.Description, "%d*%.?%d+", function(s)
if (s == tostring(toFind) and count == 0) then
count = count + 1
return replaceWith
end
end)
-- Basic find+replace for non-numbers
else
descObj.Description = replace(descObj.Description, tostring(toFind), replaceWith, 1)
end
else
toFind = EID:ReplaceVariableStr(toFind, 1, variableText)
local iconStr = "#"
if bulletpoint then iconStr = iconStr .. "{{" .. bulletpoint .. "}} " end
if cond.lineColor then iconStr = iconStr .. "{{" .. cond.lineColor .. "}}" end
EID:appendToDescription(descObj, iconStr .. toFind:gsub("#", iconStr))
end
pos = pos + 2
end
end
pos = pos + 2
end
end
end
+31 -1
View File
@@ -952,6 +952,18 @@ if EID.isRepentance then
EID.CarBatteryNoSynergy[709] = true; EID.CarBatteryNoSynergy[710] = true; EID.CarBatteryNoSynergy[711] = true; EID.CarBatteryNoSynergy[714] = true;
EID.CarBatteryNoSynergy[715] = true; EID.CarBatteryNoSynergy[728] = true; EID.CarBatteryNoSynergy[729] = true;
end
-- Items that should show their Car Battery synergy while looking at a Car Battery pedestal
-- Void, Crooked Penny, Metronome, Moving Box, Broken Shovel
EID.CarBatteryPedestalWhitelist = { [477] = true, [485] = true, [488] = true, [523] = true, [550] = true }
if EID.isRepentance then
EID.CarBatteryPedestalWhitelist[523] = nil -- Moving Box
EID.CarBatteryPedestalWhitelist[386] = true -- D12
EID.CarBatteryPedestalWhitelist[611] = true -- Larynx
EID.CarBatteryPedestalWhitelist[635] = true -- Stitches
EID.CarBatteryPedestalWhitelist[685] = true -- Jar of Wisps
EID.CarBatteryPedestalWhitelist[720] = true -- Everything Jar
EID.CarBatteryPedestalWhitelist[722] = true -- Anima Sola
end
-- Familiars that have no effect from BFFS!
EID.BFFSNoSynergy = { [10] = true, [11] = true, [81] = true, [178] = true, [238] = true, [239] = true, [243] = true, [265] = true, [268] = true, [269] = true, [276] = true, [278] = true, [280] = true, [281] = true, [387] = true, [404] = true, [431] = true, [433] = true, [436] = true, [467] = true, [469] = true, [472] = true, [492] = true, [504] = true, [516] = true, [528] = true, [542] = true, [543] = true }
@@ -967,15 +979,33 @@ if EID.isRepentance then
EID.BFFSNoSynergy[651] = true -- Star of Bethlehem
EID.BFFSNoSynergy[697] = true -- Vanishing Twin
end
-- Items that should show their BFFS / Hive Mind synergy while looking at a BFFS / Hive Mind pedestal
-- Charged Baby, Key Bum, Spider Mod, Succubus, Lil Spewer, Mystery Egg
EID.BFFSPedestalWhitelist = { [372] = true, [388] = true, [403] = true, [417] = true, [537] = true, [539] = true }
if EID.isRepentance then
EID.BFFSPedestalWhitelist[276] = true -- Isaac's Heart
EID.BFFSPedestalWhitelist[569] = true -- Blood Oath
EID.BFFSPedestalWhitelist[584] = true -- Book of Virtues
EID.BFFSPedestalWhitelist[612] = true -- Lost Soul
EID.BFFSPedestalWhitelist[635] = true -- Stitches
EID.BFFSPedestalWhitelist[685] = true -- Jar of Wisps
EID.BFFSPedestalWhitelist[702] = true -- Vengeful Spirit
EID.BFFSPedestalWhitelist[706] = true -- Abyss
EID.BFFSPedestalWhitelist[712] = true -- Lemegeton
EID.BFFSPedestalWhitelist[713] = true -- Sumptorium
end
-- Familiars that count for Hive Mind in Repentance (although it could give them No Effect if it just increases size)
EID.HiveMindFamiliars = { [10] = true, [57] = true, [128] = true, [170] = true, [264] = true, [272] = true, [274] = true, [279] = true, [320] = true, [364] = true, [365] = true, [403] = true, [426] = true, [430] = true, [504] = true, [511] = true, [575] = true, [581] = true, [629] = true, [649] = true, [650] = true, [706] = true, }
-- Familiars that count for Hive Mind but should be ignored by BFFS (not used yet, maybe used by modded item conditionals)
EID.BFFSIgnore = {}
-- Tainted character's respective normal version ID, for conditionals that apply to both versions of the character
-- To help with other character pairs, Esau = Jacob, Dead Tainted Lazarus = Tainted Lazarus, Tainted Soul = Tainted Forgotten
EID.TaintedToRegularID = { [20] = 19, [21] = 0, [22] = 1, [23] = 2, [24] = 3, [25] = 4, [26] = 5, [27] = 6, [28] = 7, [29] = 8, [30] = 9, [31] = 10, [32] = 13,
[33] = 14, [34] = 15, [35] = 16, [36] = 18, [37] = 19, [38] = 29, [39] = 37, [40] = 35 }
-- Player IDs of Tainted characters, might be useful for something
-- Player IDs of Tainted characters
EID.TaintedIDs = {}; for i = 21, 40 do EID.TaintedIDs[i] = true end
-- Character IDs that are Soul/Black Hearts only: ???, The Lost, The Soul
+290 -113
View File
@@ -10,14 +10,11 @@ EID.ItemReminderBlacklist = { ["5.100.714"] = true, ["5.100.715"] = true } -- Do
EID.ItemReminderTempDescriptions = {} -- Temporary stores descriptions that will be displayed after everythng got evaluated
EID.ItemReminderSelectedCategory = 0 -- Currently selected category
EID.ItemReminderSelectedPlayer = 0 -- Currently selected player
EID.ItemReminderSelectedItem = 0 -- Currently selected Item
EID.ItemReminderSelectedItems = {} -- Currently selected Item per category
EID.ItemReminderDisplayingScrollbar = false -- For if the scrollbar is currently being drawn
EID.InsideItemReminder = false -- Disable some modifiers, when building the Item Reminder description
EID.ItemReminderPlayerEntity = nil -- for description modifiers to reference
-- TODO:
-- crooked penny cheats. 404/liberty cap/broken syringe/etc. "what item is it"
-- pandora's box? it shows the whole desc which is kinda useful but too big
-- Data Tables --
@@ -25,50 +22,61 @@ EID.ItemReminderPlayerEntity = nil -- for description modifiers to reference
-- Execution order is handles by the order of the table entries.
-- Category name is interpreted as a lookup for the "EID.descriptions.ItemReminder.CategoryNames" table. If no translation is found, use english or the lookup value
EID.ItemReminderCategories = {
{ id = "Overview", entryGenerators = {} }, -- special handling for Overview category
{ id = "Special", entryGenerators = { function(player) EID:ItemReminderHandlePoopSpells(player) end, } },
{ id = "Overview", entryGenerators = { } }, -- special handling for Overview category
{ id = "Character", entryGenerators = { function(player) EID:ItemReminderHandleCharacterInfo(player) end, } },
{ id = "Special", entryGenerators = { function(player) EID:ItemReminderHandlePoopSpells(player) end, } },
{ id = "Wisps",
isScrollable = true,
entryGenerators = { function(player) EID:ItemReminderHandleLemegetonWisps(player) end, },
scrollbarGenerator = function(player)
local playerNum = EID:getPlayerID(player, true)
return EID:ItemReminderHandleItemScrollbarFeature(EID.WispsPerPlayer[playerNum], 100, false)
end
},
{ id = "Actives", entryGenerators = { function(player) EID:ItemReminderHandleActiveItems(player) end, } },
{
id = "Pockets",
{ id = "Pockets",
entryGenerators = {
function(player) EID:ItemReminderHandleDiceBag(player) end,
function(player) EID:ItemReminderHandlePocketActive(player) end,
function(player) EID:ItemReminderHandlePocketItems(player) end }
},
{
id = "Trinkets",
entryGenerators = {
function(player) EID:ItemReminderHandleTrinkets(player) end,
function(player) EID:ItemReminderHandleGulpedModelingClay(player) end }
},
{
id = "Passives",
{ id = "Trinkets",
isScrollable = true,
entryGenerators = {
function(player) -- Passive item: Zodiac
if EID.isRepentance and player:HasCollectible(392) and not EID:IsCategorySelected("Passives") then
EID:ItemReminderAddDescription(player, 5, 100, 392)
end
end,
function(player) -- Passive item: Echo Chamber
if EID.isRepentance and player:HasCollectible(700) and not EID:IsCategorySelected("Passives") then
EID:ItemReminderAddDescription(player, 5, 100, 700)
end
end,
function(player) EID:ItemReminderHandleSelectedPassiveItem(player) end },
entryGenerators = { function(player) EID:ItemReminderHandleTrinkets(player) end },
scrollbarGenerator = function(player)
local playerNum = EID:getPlayerID(player)
local numPassives = EID.RecentlyTouchedItems[playerNum] and #EID.RecentlyTouchedItems[playerNum] or 0
if numPassives < 2 then return nil end -- dont display scrollbar if less than 2 items are in the table
return EID:ItemReminderHandleItemScrollbarFeature(EID:ItemReminderHeldPlusGulped(player), 350, true)
end
},
{ id = "Passives",
isScrollable = true,
entryGenerators = { function(player) EID:ItemReminderHandleSelectedPassiveItem(player) end },
scrollbarGenerator = function(player)
local playerNum = EID:getPlayerID(player, true)
return EID:ItemReminderHandleItemScrollbarFeature(EID.RecentlyTouchedItems[playerNum], 100, true)
end
},
}
-- simple function to reset the selected items in the scrollbars. can specify a category name like "Passives"
function EID:ResetItemReminderSelectedItems(categoryName)
if not categoryName then
for i=0,#EID.ItemReminderCategories-1 do EID.ItemReminderSelectedItems[i] = 0 end
else
for i,category in ipairs(EID.ItemReminderCategories) do
if category.id == categoryName then EID.ItemReminderSelectedItems[i-1] = 0 return end
end
end
end
EID:ResetItemReminderSelectedItems()
-- This table is for items that should have a special modifier applied to them when viewed in the item reminder
-- Format: ItemID = table
-- modifierFunction = function that modifies the original description object of the item
-- isCheat = Only evaluate, if the "ItemReminderShowRNGCheats" config option is enabled
-- isHiddenInfo = Only evaluate, if the "ItemReminderShowHiddenInfo" config option is enabled
-- isRepentance = Only evaluate, if Repentance is installed
-- noOverview = If true, this modifier doesn't have special priority in the Overview category (most do)
-- Make sure to return true if the description was modified, so the overview knows
EID.ItemReminderDescriptionModifier = {
---------------- Passive Items ----------------
["5.100.392"] = { -- Zodiac
@@ -80,18 +88,15 @@ EID.ItemReminderDescriptionModifier = {
EID:ItemReminderAddResultHeaderSuffix(descObj, demoDescObj.Name)
descObj.Icon = demoDescObj.Icon
descObj.Description = demoDescObj.Description
return true
end
end
},
["5.100.700"] = { -- Echo Chamber
isRepentance = true,
modifierFunction = function(descObj, player)
local playerID = EID:getPlayerID(player)
modifierFunction = function(descObj, player, inOverview)
local playerID = EID:getPlayerID(player, true)
local pickupHistory = EID.PlayerItemInteractions[playerID].pickupHistory
-- Dead Tainted Lazarus exception
if player:GetPlayerType() == 38 then
pickupHistory = EID.PlayerItemInteractions[playerID].altPickupHistory or pickupHistory
end
if not pickupHistory then return end
local pickupNames = ""
local pickupsToPrint = 3
@@ -99,53 +104,131 @@ EID.ItemReminderDescriptionModifier = {
if pickupHistory[i][4] then -- Echo chamber was owned before this card/pill was used and it's not a mimic usage
if pickupHistory[i][1] == "pill" then
local name = EID:getPillName(pickupHistory[i][3], false)
if (pickupHistory[i][2] == 14) then name = EID:getPillName(9999, false) end
pickupNames = pickupNames .. "{{Pill" .. pickupHistory[i][2] .. "}} " .. name .. "#"
pickupsToPrint = pickupsToPrint - 1
if (pickupHistory[i][2] % 2048 == 14) then name = EID:getPillName(9999, false) end
pickupNames = pickupNames .. "{{Pill" .. pickupHistory[i][2] .. "}} {{ColorPill}}" .. name .. "#"
else
local name = EID:getObjectName(5, 300, pickupHistory[i][3])
pickupNames = pickupNames .. "{{Card" .. pickupHistory[i][3] .. "}} " .. name .. "#"
pickupsToPrint = pickupsToPrint - 1
pickupNames = pickupNames .. "{{Card" .. pickupHistory[i][3] .. "}} {{ColorCard}}" .. name .. "#"
end
pickupsToPrint = pickupsToPrint - 1
if (pickupsToPrint == 0) then break end
end
end
if pickupNames ~= "" then
EID:ItemReminderAddResultHeaderSuffix(descObj)
descObj.Description = pickupNames
EID:ItemReminderAddResult(descObj, pickupNames, inOverview)
return true
end
end
},
["5.100.464"] = { -- Glyph of Balance
modifierFunction = function(descObj, player, inOverview)
local result = EID:GlyphOfBalancePrediction(player)
EID:ItemReminderAddResult(descObj, result, inOverview)
return true
end
},
---------------- Active Items ----------------
["5.100.44"] = { -- Teleport! location
isCheat = true,
modifierFunction = function(descObj, player)
modifierFunction = function(descObj, player, inOverview)
-- The result preview changes as soon as we activate Teleport, which looks awkward, so try to not display the result while mid-teleport.
-- Doesn't work perfectly and only in Rep
if not EID.isRepentance or player:GetSprite():GetAnimation() ~= "TeleportUp" then
EID:ItemReminderAddResultHeaderSuffix(descObj)
descObj.Description = EID:Teleport1Prediction(EID:GetItemSeed(player, 44))
EID:ItemReminderAddResult(descObj, EID:Teleport1Prediction(EID:GetItemSeed(player, 44)), inOverview)
return true
end
end,
},
["5.100.297"] = { -- Pandora's Box shortened description for overview
modifierFunction = function(descObj, player, inOverview)
if inOverview then
-- Crystal Key interaction takes priority
if EID.isRepentance and player:HasTrinket(175) then
local result = "{{Trinket175}} " .. EID:getDescriptionEntry("PandorasBoxStrangeKeyEffect")
EID:ItemReminderAddResult(descObj, result, inOverview)
return true
end
-- remove spaces after semicolons
descObj.Description = string.gsub(descObj.Description, "; ", ";")
descObj.Description = string.gsub(descObj.Description, "{{ColorBagComplete}} ", "{{ColorBagComplete}}")
-- find the highlighted text
local startLoc = string.find(descObj.Description, "{{ColorBagComplete}}")
if startLoc then
-- display the current result and the next floor's result; this is a bit complicated if you want to be truly accurate
local count = 2
local skip = 0
local level = game:GetLevel()
local stageNum = level:GetAbsoluteStage()
local inAscent = EID.isRepentance and (level:IsAscent() or level:IsPreAscent())
local final = not level:IsNextStageAvailable()
if EID:IsGreedMode() and not EID.PandorasGreedConditional then
skip = 1
if stageNum == 5 then skip = 0 -- Depths 2 -> Womb 1
elseif stageNum == 7 or stageNum == 10 then skip = 2
elseif stageNum == 0 then count = 1 end -- Womb 1 -> Sheol, Sheol -> Chest
else
if final or stageNum == 12 then count = 1 -- Dark Room/Chest/The Void/Home/Corpse 2 doesn't display any more
elseif EID:IsGreedMode() then count = 2 -- prevent Greed Mode Sheol from behaving weird
elseif stageNum == 8 then count = 3; skip = 1 -- Womb 2 displays Sheol and Cathe
elseif stageNum == 9 then count = 3 -- ??? displays Sheol and Cathe
elseif stageNum == 10 then skip = 1 end -- Sheol/Cathe skip one to display Dark Room/Chest
end
local newDesc = ""
if inAscent then
-- Go through the description, copying the current line, until we find the highlighted line, appending the previous line to it
-- Exception: Basement 1 wants to append the final line (Home) so just keep iterating
local highlightLine = ""
local secondLine = ""
for w in string.gmatch(descObj.Description, "([^#;]+)") do
if string.find(w, "{{ColorBagComplete}}") then
highlightLine = w
if stageNum ~= 1 then break end
else
secondLine = w
end
end
newDesc = highlightLine .. "#" .. secondLine
else
local truncated = string.sub(descObj.Description, startLoc)
for w in string.gmatch(truncated, "([^#;]+)") do
-- skip lines after adding the highlighted line
if newDesc ~= "" and skip > 0 then
skip = skip - 1
else
newDesc = newDesc .. w
count = count - 1
if count == 0 then break
else newDesc = newDesc .. "#" end
end
end
end
EID:ItemReminderAddResult(descObj, newDesc, inOverview)
return true
end
end
end
},
["5.100.419"] = { -- Teleport 2.0 location
modifierFunction = function(descObj, _)
EID:ItemReminderAddResultHeaderSuffix(descObj)
descObj.Description = EID:Teleport2Prediction()
modifierFunction = function(descObj, _, inOverview)
EID:ItemReminderAddResult(descObj, EID:Teleport2Prediction(), inOverview)
return true
end
},
["5.100.476"] = { -- D1
isCheat = true,
modifierFunction = function(descObj, player)
EID:ItemReminderAddResultHeaderSuffix(descObj)
descObj.Description = EID:D1Prediction(EID:GetItemSeed(player, 476))
modifierFunction = function(descObj, player, inOverview)
EID:ItemReminderAddResult(descObj, EID:D1Prediction(EID:GetItemSeed(player, 476)), inOverview)
return true
end
},
["5.100.477"] = { -- Void
modifierFunction = function(descObj, player)
local absorbedItems = EID.absorbedItems[tostring(EID:getPlayerID(player))]
modifierFunction = function(descObj, player, inOverview)
local absorbedItems = EID.absorbedItems[tostring(EID:getPlayerID(player, true))]
if absorbedItems then
local descriptionText = ""
local countItems = 0
@@ -162,8 +245,8 @@ EID.ItemReminderDescriptionModifier = {
descriptionText = descriptionText .. EID:getObjectName(5, 100, tonumber(k)) .. "#"
end
end
EID:ItemReminderAddResultHeaderSuffix(descObj)
descObj.Description = descriptionText
EID:ItemReminderAddResult(descObj, descriptionText, inOverview)
return true
end
end
end
@@ -176,6 +259,7 @@ EID.ItemReminderDescriptionModifier = {
EID:ItemReminderAddResultHeaderSuffix(descObj, demoDescObj.Name)
descObj.Icon = demoDescObj.Icon
descObj.Description = demoDescObj.Description
return true
end
},
["5.100.489"] = { -- D Infinity
@@ -185,11 +269,12 @@ EID.ItemReminderDescriptionModifier = {
EID:ItemReminderAddResultHeaderSuffix(descObj, demoDescObj.Name)
descObj.Icon = demoDescObj.Icon
descObj.Description = demoDescObj.Description
return true
end
},
["5.100.710"] = { -- Bag of Crafting
isRepentance = true,
modifierFunction = function(descObj, _)
modifierFunction = function(descObj, _, inOverview)
local floorQuery = EID.BoC.FloorOverride or EID.BoC.FloorQuery
local inventoryQuery = EID.BoC.InventoryOverride or EID.BoC.InventoryQuery
local bagItems = EID.BoC.BagItemsOverride or EID.BoC.BagItems
@@ -203,27 +288,34 @@ EID.ItemReminderDescriptionModifier = {
local hideButton = controllerEnabled and EID.ButtonToIconMap[EID.Config["CraftingHideButton"]]
text = text .. "#!!! ".. EID:ReplaceVariableStr(EID:getDescriptionEntry("CraftingIsHidden"), 1, (hideKey or hideButton))
end
descObj.Description = text
if inOverview then
descObj.Description = text
else
descObj.Description = descObj.Description .. "#" .. text
end
return true
end
},
---------------- TRINKETS ----------------
["5.350.4"] = { -- Broken Remote has two possible effects depending on if its doubled
modifierFunction = function(descObj, player)
modifierFunction = function(descObj, player, inOverview)
local originalName = descObj.Name
if player:GetTrinketMultiplier(4) > 1 then
-- Teleport 2.0
local demoDescObj = EID:getDescriptionObj(5, 100, 419)
EID.ItemReminderDescriptionModifier["5.100.419"].modifierFunction(descObj, player)
EID.ItemReminderDescriptionModifier["5.100.419"].modifierFunction(descObj, player, inOverview)
descObj.Name = originalName
EID:ItemReminderAddResultHeaderSuffix(descObj, demoDescObj.Name)
if inOverview then EID:ItemReminderAddResultHeaderSuffix(descObj, demoDescObj.Name) end
return true
elseif EID.Config["ItemReminderShowRNGCheats"] then
-- Teleport
local demoDescObj = EID:getDescriptionObj(5, 100, 44)
EID.ItemReminderDescriptionModifier["5.100.44"].modifierFunction(descObj, player)
EID.ItemReminderDescriptionModifier["5.100.44"].modifierFunction(descObj, player, inOverview)
descObj.Name = originalName
EID:ItemReminderAddResultHeaderSuffix(descObj, demoDescObj.Name)
if inOverview then EID:ItemReminderAddResultHeaderSuffix(descObj, demoDescObj.Name) end
return true
end
end
},
@@ -237,6 +329,7 @@ EID.ItemReminderDescriptionModifier = {
EID:ItemReminderAddResultHeaderSuffix(descObj, demoDescObj.Name)
descObj.Icon = demoDescObj.Icon
descObj.Description = demoDescObj.Description
return true
end
},
["5.350.75"] = { -- 404 Error
@@ -249,17 +342,22 @@ EID.ItemReminderDescriptionModifier = {
EID:ItemReminderAddResultHeaderSuffix(descObj, demoDescObj.Name)
descObj.Icon = demoDescObj.Icon
descObj.Description = demoDescObj.Description
return true
end
},
["5.350.166"] = { -- Modeling Clay
isRepentance = true,
modifierFunction = function(descObj, player)
local modelingClayItem = player:GetModelingClayEffect()
if modelingClayItem > 0 then
local demoDescObj = EID:getDescriptionObj(5, 100, modelingClayItem)
EID:ItemReminderAddResultHeaderSuffix(descObj, demoDescObj.Name)
descObj.Icon = "{{Collectible" .. modelingClayItem .. "}}"
descObj.Description = demoDescObj.Description
-- When gulped, Modeling Clay's current item becomes Hidden Information
if EID.Config["ItemReminderShowHiddenInfo"] or player:GetTrinket(0) == 166 or player:GetTrinket(1) == 166 then
local modelingClayItem = player:GetModelingClayEffect()
if modelingClayItem > 0 then
local demoDescObj = EID:getDescriptionObj(5, 100, modelingClayItem)
EID:ItemReminderAddResultHeaderSuffix(descObj, demoDescObj.Name)
descObj.Icon = "{{Collectible" .. modelingClayItem .. "}}"
descObj.Description = demoDescObj.Description
return true
end
end
end
},
@@ -290,9 +388,25 @@ function EID:ItemReminderAddResultHeaderSuffix(descObj, newName)
descObj.Name = descObj.Name .. EID:getDescriptionEntry("ItemReminder", "ResultHeader")
end
end
-- Adds a formatted "Result" text appended to the item description
function EID:ItemReminderAddResultAppend(descObj, newText)
local iconString = EID:GetIconStringByDescriptionObject(descObj)
descObj.Description = descObj.Description .. "#" .. iconString .. " {{ColorObjName}}" .. descObj.Name .. EID:getDescriptionEntry("ItemReminder", "ResultHeader") .. "#" .. newText
end
-- Helper function for modifiers that want to replace the description in the overview, but append to the description otherwise
function EID:ItemReminderAddResult(descObj, newText, inOverview)
if inOverview then
EID:ItemReminderAddResultHeaderSuffix(descObj)
descObj.Description = newText
else
EID:ItemReminderAddResultAppend(descObj, newText)
end
end
-- Add item description for a given entity to the reminder. Also tries to apply special modifiers if present
function EID:ItemReminderAddDescription(player, entityType, variant, subType, extraIcon)
-- If given an item ID string, split it into type/variant/subtype
if type(entityType) == "string" then entityType, variant, subType = EID:SplitTVS(entityType) end
local objectID = entityType .. "." .. variant .. "." .. subType
if currentBlacklist[objectID] then return true end
@@ -315,13 +429,41 @@ function EID:ItemReminderAddDescription(player, entityType, variant, subType, ex
return EID:ItemReminderAddTempDescriptionEntry(iconString, descObj.Name, descObj.Description)
end
-- Recently Acquired Item Descriptions
-- In the overview category, check for special descriptions
function EID:ItemReminderAddSpecialDescriptions(player)
for objectID,specialDesc in pairs(EID.ItemReminderDescriptionModifier) do
local evaluateFunction = true
if (not EID:PlayerHasItem(player, objectID)) then evaluateFunction = false end
if (specialDesc.isCheat and not EID.Config["ItemReminderShowRNGCheats"]) then evaluateFunction = false end
if (specialDesc.isHiddenInfo and not EID.Config["ItemReminderShowHiddenInfo"]) then evaluateFunction = false end
if (specialDesc.isRepentance and not EID.isRepentance) then evaluateFunction = false end
if evaluateFunction then
local Type, Var, Sub = EID:SplitTVS(objectID)
local descObj = EID:getDescriptionObj(Type, Var, Sub)
if specialDesc.modifierFunction(descObj, player, true) then
currentBlacklist[objectID] = true
local iconString = EID:GetIconStringByDescriptionObject(descObj)
EID:ItemReminderAddTempDescriptionEntry(iconString, descObj.Name, descObj.Description)
end
end
if not EID:ItemReminderCanAddMoreToView() then return end
end
end
-- Information about the player character's traits
function EID:ItemReminderHandleCharacterInfo(player)
local playerType = player:GetPlayerType()
local playerDesc = EID:getDescriptionEntry("CharacterInfo")[playerType]
if playerDesc[2] ~= "" then
EID:ItemReminderAddTempDescriptionEntry("{{Player" .. playerType .. "}}", playerDesc[1], playerDesc[2])
end
end
-- Passive Item Descriptions
function EID:ItemReminderHandleSelectedPassiveItem(player)
local playerNum = EID:getPlayerID(player)
local playerNum = EID:getPlayerID(player, true)
if EID.RecentlyTouchedItems[playerNum] and #EID.RecentlyTouchedItems[playerNum] > 0 then
local index = EID:IsCategorySelected("Passives") and EID.ItemReminderSelectedItem % #EID.RecentlyTouchedItems[playerNum] or 0
local recentID = EID.RecentlyTouchedItems[playerNum][#EID.RecentlyTouchedItems[playerNum] - index] % GLITCH_ITEM_FLAG
EID:ItemReminderAddDescription(player, 5, 100, recentID)
EID:ItemReminderHandleItemPrinting(player, EID.RecentlyTouchedItems[playerNum], 100, true)
end
end
@@ -378,33 +520,27 @@ function EID:ItemReminderHandlePocketItems(player)
end
end
-- Held trinkets are added at the end of the table; use this table in descending order
function EID:ItemReminderHeldPlusGulped(player)
local playerNum = EID:getPlayerID(player, true)
local newTable = {}
if EID.GulpedTrinkets[playerNum] then newTable = {table.unpack(EID.GulpedTrinkets[playerNum])} end
for i=0, 1 do
local trinket = player:GetTrinket(i)
if trinket > 0 then table.insert(newTable, trinket) end
end
return newTable
end
-- Trinket Descriptions
function EID:ItemReminderHandleTrinkets(player)
for t = 0, 1 do
if not EID:ItemReminderCanAddMoreToView() then return end
-- account for Golden Trinket IDs
local heldTrinketTrue = player:GetTrinket(t)
local heldTrinket = heldTrinketTrue
if EID.isRepentance then heldTrinket = heldTrinketTrue & TrinketType.TRINKET_ID_MASK end
if heldTrinket > 0 then
EID:ItemReminderAddDescription(player, 5, 350, heldTrinketTrue)
end
end
end
-- Gulped/unslotted Modeling Clay
-- (Hidden information, because Modeling Clay does not visually show its item when gulped)
function EID:ItemReminderHandleGulpedModelingClay(player)
if EID.isRepentance and EID.Config["ItemReminderShowHiddenInfo"] and player:GetModelingClayEffect() > 0 and EID:ItemReminderCanAddMoreToView() then
EID:ItemReminderAddDescription(player, 5, 350, 166)
end
EID:ItemReminderHandleItemPrinting(player, EID:ItemReminderHeldPlusGulped(player), 350, true)
end
-- Tainted ??? Poop Descriptions
function EID:ItemReminderHandlePoopSpells(player)
if EID.isRepentance and player:GetPlayerType() == 25 and EID:ItemReminderCanAddMoreToView() then
local poopInfo = EID:getDescriptionEntry("poopSpells")
for i = 0, 3 do
for i = 0, numAvailableDescriptionSlots - 1 do
local nextPoop = player:GetPoopSpell(i)
EID:ItemReminderAddTempDescriptionEntry("{{PoopSpell" .. nextPoop .. "}}", poopInfo[nextPoop][1],
poopInfo[nextPoop][2])
@@ -412,6 +548,12 @@ function EID:ItemReminderHandlePoopSpells(player)
end
end
-- Lemegeton wisp descriptions
function EID:ItemReminderHandleLemegetonWisps(player)
local playerNum = EID:getPlayerID(player, true)
EID:ItemReminderHandleItemPrinting(player, EID.WispsPerPlayer[playerNum], 100, false)
end
-- Handle scroll inputs
function EID:ItemReminderHandleInputs()
if EID.Config["ItemReminderEnabled"] and EID.Config["ItemReminderDisplayMode"] ~= "Classic" and EID.holdTabCounter >= 30 and EID.TabDescThisFrame == false and EID.holdTabPlayer ~= nil then
@@ -434,19 +576,19 @@ function EID:ItemReminderHandleInputs()
lastInputTime = Isaac.GetTime()
lastScrollDirection = 1
elseif Input.IsActionTriggered(EID.Config["ItemReminderNavigateUpButton"], EID.holdTabPlayer.ControllerIndex) and Isaac.GetTime() - lastInputTime > 50 then
if not EID:IsScrollableCategorySelected() then
if not EID.ItemReminderDisplayingScrollbar then
EID.ItemReminderSelectedPlayer = (EID.ItemReminderSelectedPlayer - 1) % #EID:ItemReminderGetAllPlayers()
else
EID.ItemReminderSelectedItem = EID.ItemReminderSelectedItem - 1 -- clamp later
EID.ItemReminderSelectedItems[EID.ItemReminderSelectedCategory] = EID.ItemReminderSelectedItems[EID.ItemReminderSelectedCategory] - 1 -- clamp later
end
EID.ForceRefreshCache = true
lastInputTime = Isaac.GetTime()
elseif Input.IsActionTriggered(EID.Config["ItemReminderNavigateDownButton"], EID.holdTabPlayer.ControllerIndex) and Isaac.GetTime() - lastInputTime > 50 then
if not EID:IsScrollableCategorySelected() then
if not EID.ItemReminderDisplayingScrollbar then
EID.ItemReminderSelectedPlayer = (EID.ItemReminderSelectedPlayer + 1) % #EID:ItemReminderGetAllPlayers()
else
EID.ItemReminderSelectedItem = EID.ItemReminderSelectedItem + 1 -- clamp later
EID.ItemReminderSelectedItems[EID.ItemReminderSelectedCategory] = EID.ItemReminderSelectedItems[EID.ItemReminderSelectedCategory] + 1 -- clamp later
end
EID.ForceRefreshCache = true
@@ -485,10 +627,12 @@ function EID:ItemReminderHandleInitHoldTab()
break
end
end
EID:UpdateAllPlayerLemegetonWisps()
EID:UpdateAllPlayerTrinkets()
local updatedPlayers = EID:UpdateAllPlayerPassiveItems()
if updatedPlayers[EID.ItemReminderSelectedPlayer + 1] or oldDisplayPlayer ~= EID.ItemReminderSelectedPlayer then
EID.ItemReminderSelectedItem = 0
EID:ResetItemReminderSelectedItems("Passives")
end
end
@@ -516,7 +660,7 @@ function EID:ItemReminderGetTitle()
local playerIcon = EID:GetPlayerIcon(currentPlayer:GetPlayerType(), "P" .. curPlayerID )
local playerSelectWidget = playerIcon .. " "
if not EID:IsScrollableCategorySelected() and EID.Config["ItemReminderDisplayMode"] ~= "Classic" then
if not EID.ItemReminderDisplayingScrollbar and EID.Config["ItemReminderDisplayMode"] ~= "Classic" then
playerSelectWidget = EID.ButtonToIconMap[EID.Config["ItemReminderNavigateUpButton"]] ..
playerIcon .. EID.ButtonToIconMap[EID.Config["ItemReminderNavigateDownButton"]] .. "|"
end
@@ -542,15 +686,18 @@ end
-- takes a list of item ids and an item variant to automatically generate a scrollable list of item icons.
function EID:ItemReminderHandleItemScrollbarFeature(entryTable, itemVariant, descending)
if entryTable == nil or #entryTable <= EID.Config["ItemReminderMaxEntriesCount"] then return nil end
-- handle Scrollable passives list
local newDescription = "{{Blank}} " .. EID.ButtonToIconMap[EID.Config["ItemReminderNavigateUpButton"]]
local newDescription = "{{Blank}} {{NoLB}}" .. EID.ButtonToIconMap[EID.Config["ItemReminderNavigateUpButton"]]
local selectedItem = EID.ItemReminderSelectedItems[EID.ItemReminderSelectedCategory]
EID.ItemReminderSelectedItem = EID.ItemReminderSelectedItem % #entryTable -- clamp selection
selectedItem = selectedItem % #entryTable -- clamp selection
-- render icons
if descending then
local startIndex = #entryTable - EID.ItemReminderSelectedItem -- start from end of list
local stopIndex = startIndex - 3
local startIndex = #entryTable - selectedItem -- start from end of list
local stopIndex = startIndex - (EID.Config["ItemReminderMaxEntriesCount"] + 1)
for i = startIndex, stopIndex, -1 do
local index = ((i - 1) % #entryTable) + 1
@@ -563,8 +710,8 @@ function EID:ItemReminderHandleItemScrollbarFeature(entryTable, itemVariant, des
newDescription = newDescription .. "{{" .. EID:GetIconNameByVariant(itemVariant) .. recentID .. "}} "
end
else
local startIndex = EID.ItemReminderSelectedItem -- start from end of list
local stopIndex = startIndex + 3
local startIndex = selectedItem -- start from end of list
local stopIndex = startIndex + (EID.Config["ItemReminderMaxEntriesCount"] + 1)
for i = startIndex, stopIndex do
local index = (i % #entryTable) + 1
local recentID = entryTable[index] % GLITCH_ITEM_FLAG
@@ -577,11 +724,33 @@ function EID:ItemReminderHandleItemScrollbarFeature(entryTable, itemVariant, des
end
end
-- add counter
newDescription = newDescription .. "(" .. (EID.ItemReminderSelectedItem + 1) .. "/" .. #entryTable .. ") "
newDescription = newDescription .. "(" .. (selectedItem + 1) .. "/" .. #entryTable .. ")"
return newDescription .. EID.ButtonToIconMap[EID.Config["ItemReminderNavigateDownButton"]] .. "#"
end
-- takes a list of item ids and an item variant to automatically print the correct amount of descriptions
function EID:ItemReminderHandleItemPrinting(player, entryTable, itemVariant, descending)
if not EID:ItemReminderCanAddMoreToView() or entryTable == nil or #entryTable == 0 then return end
local descsToDisplay = numAvailableDescriptionSlots
if #entryTable < descsToDisplay then descsToDisplay = #entryTable end
if descending then
local startIndex = (#entryTable - EID.ItemReminderSelectedItems[EID.ItemReminderSelectedCategory] - 1) % #entryTable
for i = 1, descsToDisplay do
EID:ItemReminderAddDescription(player, 5, itemVariant, entryTable[startIndex+1] % GLITCH_ITEM_FLAG)
startIndex = (startIndex - 1) % #entryTable
end
else
local startIndex = EID.ItemReminderSelectedItems[EID.ItemReminderSelectedCategory] % #entryTable
for i = 1, descsToDisplay do
EID:ItemReminderAddDescription(player, 5, itemVariant, entryTable[startIndex+1] % GLITCH_ITEM_FLAG)
startIndex = (startIndex + 1) % #entryTable
end
end
end
function EID:ItemReminderGetDescription()
EID.InsideItemReminder = true
EID.ItemReminderTempDescriptions = {}
@@ -593,11 +762,17 @@ function EID:ItemReminderGetDescription()
EID.ItemReminderPlayerEntity = player -- for description modifiers to reference
if EID.ItemReminderSelectedCategory == 0 or EID.Config["ItemReminderDisplayMode"] == "Classic" then
-- execute special previews / item results while in the overview
numAvailableDescriptionSlots = EID.Config["ItemReminderMaxEntriesCount"]
EID:ItemReminderAddSpecialDescriptions(player)
-- execute all functions defined per category
for _, category in ipairs(EID.ItemReminderCategories) do
numAvailableDescriptionSlots = 1 -- limit to one description per category in overview mode
for _, func in ipairs(category.entryGenerators) do
func(player)
-- don't display character info in the overview after a few rooms
if category.id ~= "Character" or EID.roomCount < 5 then
numAvailableDescriptionSlots = 1 -- limit to one description per category in overview mode
for _, func in ipairs(category.entryGenerators) do
func(player)
end
end
end
else
@@ -638,13 +813,15 @@ function EID:ItemReminderGetDescription()
end
autoScrollTriesLeft = -999
local finalHoldMapDesc = "{{Blank}}#"
local finalHoldMapDesc = ""
EID.ItemReminderDisplayingScrollbar = false
local category = EID.ItemReminderCategories[EID.ItemReminderSelectedCategory + 1]
if EID:IsScrollableCategorySelected() then
local scrollbar = category.scrollbarGenerator(player)
if scrollbar then
finalHoldMapDesc = scrollbar
EID.ItemReminderDisplayingScrollbar = true
end
end
-- roughly estimate space the descriptions would occupy. trim descriptions if nessesary
+69 -2
View File
@@ -28,7 +28,7 @@ function EID:CurrentDInfinity(rng, player)
rng = EID:RNGNext(rng, 0x1, 0x9, 0x1D) -- magic disassembled numbers!
return dinfinityList[rng % 7]
else
local playerID = EID:getPlayerID(player)
local playerID = EID:getPlayerID(player, true)
return dinfinityList[EID.DInfinityState[playerID]] or 476
end
end
@@ -42,7 +42,7 @@ if EID.isRepentance then
function EID:WatchForDice(collectibleType, _, player)
if not justDidD or collectibleType == 489 then return end
justDidD = false
local playerID = EID:getPlayerID(player)
local playerID = EID:getPlayerID(player, true)
for i,v in ipairs(dinfinityList) do
if v == collectibleType then EID.DInfinityState[playerID] = i end
end
@@ -329,3 +329,70 @@ function EID:D1Prediction(rng)
local pickupNames = EID:getDescriptionEntry("PickupNames") or {}
return pickupNames[fullID] or EID:GetEntityXMLNameByString(fullID) or fullID
end
-- Glyph of Balance --
function EID:GlyphOfBalancePrediction(player)
local fullID = "5.0"
local playerID = player:GetPlayerType()
local skipHearts = EID.isRepentance and EID.NoRedHeartsPlayerIDs[playerID] -- Soul Heart characters can't get hearts in Repentance
local skipSoulHearts = EID.isRepentance and (playerID == 18 or playerID == 14 or playerID == 33) -- Bethany and Keepers can't get Soul Hearts with 6 or less containers in Repentance
local skipBombs = EID.isRepentance and playerID == 25 -- Tainted ??? (the only character that can't have Bombs)
-- Soul Hearts: When Isaac has no Red Heart containers and less than 2 Soul Hearts.
if not skipHearts and player:GetEffectiveMaxHearts() == 0 and player:GetSoulHearts() < 4 then
fullID = "5.10.3"
-- Full Red Hearts: While at 0.5 Red Hearts.
-- In AB+, you seem to have to have at least one non-Bone container to trigger this condition
elseif not skipHearts and player:CanPickRedHearts() and player:GetHearts() <= 1 and (EID.isRepentance or player:GetMaxHearts() > 0) then
fullID = "5.10.1"
-- Keys: When Isaac has no keys.
elseif player:GetNumKeys() == 0 then
fullID = "5.30.1"
-- Bombs: When Isaac has no bombs.
elseif not skipBombs and player:GetNumBombs() == 0 then
fullID = "5.40.1"
-- Big Poop Nugget: When Tainted ??? has no poops
elseif skipBombs and player:GetPoopMana() == 0 then
fullID = "5.42.1"
-- Soul Hearts: When Bethany has no soul charges
elseif EID.isRepentance and playerID == 18 and player:GetSoulCharge() == 0 then
fullID = "5.10.3"
-- Red Hearts: When Tainted Bethany has no blood charges
elseif EID.isRepentance and playerID == 36 and player:GetBloodCharge() == 0 then
fullID = "5.10.1"
-- Full Red Hearts: When Isaac has at least half a Red Heart container empty.
elseif not skipHearts and player:CanPickRedHearts() then
fullID = "5.10.1"
-- Pennies: While Isaac has less than 15 pennies.
elseif player:GetNumCoins() < 15 then
fullID = "5.20.1"
-- Keys: When Isaac has less than 5 keys.
elseif player:GetNumKeys() < 5 then
fullID = "5.30.1"
-- Bombs: When Isaac has less than 5 bombs.
elseif not skipBombs and player:GetNumBombs() < 5 then
fullID = "5.40.1"
-- Trinkets: If Isaac has no trinkets and there are no trinkets on the ground in the room.
elseif player:GetTrinket(0) == 0 and #Isaac.FindByType(5, 350) == 0 then
fullID = "5.350"
-- Big Poop Nugget: When Tainted ??? has less than 5 poops
elseif skipBombs and player:GetPoopMana() < 5 then
fullID = "5.42.1"
-- Soul Hearts: When Bethany has less than 12 soul charges
elseif EID.isRepentance and playerID == 18 and player:GetSoulCharge() < 12 then
fullID = "5.10.3"
-- Red Hearts: When Tainted Bethany has less than 12 blood charges
elseif EID.isRepentance and playerID == 36 and player:GetBloodCharge() < 12 then
fullID = "5.10.1"
-- Soul Hearts: When Isaac has less than 6 total Heart containers of any kind.
elseif not skipHearts and not skipSoulHearts and player:GetHearts() + player:GetSoulHearts() < 12 then
fullID = "5.10.3"
end
--todo: in REPENTOGON, replace this whole function (in the eid_repentogon lua style)
local pickupNames = EID:getDescriptionEntry("PickupNames") or {}
return pickupNames[fullID] or EID:GetEntityXMLNameByString(fullID) or fullID
end
+1 -1
View File
@@ -583,7 +583,7 @@ if MCMLoaded then
EID:AddNumberSetting("Reminder", "ItemReminderDisplayMode", "Display Mode", 1, #itemReminderModes, {indexOf = itemReminderModes, infoText = "Changes the display mode. All = overview + categories. NoOverview = categories. Classic = Overview only", onChangeFunc =
function(currentNum)
EID.MCM_OptionChanged = true
EID.ItemReminderSelectedItem = 0
EID:ResetItemReminderSelectedItems()
EID.ItemReminderSelectedCategory = currentNum ~= 2 and 0 or 1 -- reset category
EID.Config["ItemReminderDisplayMode"] = itemReminderModes[currentNum]
end})
+85 -54
View File
@@ -137,9 +137,9 @@ local pandorasStages = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 11, 11, 13 }
local altStages = { [10] = false, [11] = true, [12] = false, [13] = true }
-- Greed Mode Absolute Stage / Pandora's Box Behavior: 1: B2, 3: C2, 5: D2, 7: W1, 10: Sheol, 0: Chest
local greedStages = { -1, 1, -1, 3, -1, 5, 7, -1, -1, 10, -1, -1, 0, -1 }
EID.PandorasGreedConditional = false -- helper variable to let item reminder know that we have the 6-entry greed pandora desc
local function PandorasBoxCallback(descObj)
local strangeKeyOwned = EID.isRepentance and EID:PlayersHaveTrinket(175)
local pandoraCount = 0
local level = game:GetLevel()
local stageNum = level:GetAbsoluteStage()
@@ -157,10 +157,15 @@ local function PandorasBoxCallback(descObj)
end
end
local skip9and12 = false
EID.PandorasGreedConditional = false
-- many localizations do not have the ???/Void entry and the Dark Room entry
-- this seemed better than forcing them to have it
if totalCount == (EID.isRepentance and 12 or 11) then
skip9and12 = true
-- If the localization has a simplified Greed Mode desc, it will only have 6 entries
elseif totalCount == 6 then
EID.PandorasGreedConditional = true
greedStages = { 1, 3, 5, 7, 10, 0 }
end
for w in string.gmatch(descObj.Description, "([^#;]+)") do
@@ -185,9 +190,6 @@ local function PandorasBoxCallback(descObj)
if pandoraCount == (EID.isRepentance and 14 or 13) then break end
end
end
if strangeKeyOwned then
descObj.Description = descObj.Description .. "#{{Trinket175}} " .. EID:getDescriptionEntry("PandorasBoxStrangeKeyEffect")
end
return descObj
end
@@ -242,6 +244,40 @@ local function BlackFeatherCallback(descObj)
return descObj
end
-- Handle VURP description addition
local function VurpCallback(descObj)
local adjustedID = EID:getAdjustedSubtype(descObj.ObjType, descObj.ObjVariant, descObj.ObjSubType)
if adjustedID - 1 ~= PillEffect.PILLEFFECT_VURP then return descObj end
for i = 1,#EID.coopAllPlayers do
local player = EID.coopAllPlayers[i]
local playerID = EID:getPlayerID(player, true)
local playerType = player:GetPlayerType()
local pickupHistory = EID.PlayerItemInteractions[playerID].pickupHistory
if pickupHistory then
local lastUsedPill = PillEffect.PILLEFFECT_VURP + 1
local lastUsedPillColor = 1
local j = 1
while (j <= #pickupHistory) do
local entry = pickupHistory[j]
-- ignore the pill if the pill color is Golden
if entry[1] == "pill" and entry[2] % 2048 ~= 14 then
lastUsedPill = entry[3]
lastUsedPillColor = entry[2]
break
end
j = j + 1
end
local tableName = EID:getTableName(descObj.ObjType, descObj.ObjVariant, descObj.ObjSubType)
local name = EID:getPillName(lastUsedPill, tableName == "horsepills")
if #EID.coopAllPlayers == 1 then EID:appendToDescription(descObj, "#{{Pill" .. lastUsedPillColor .. "}}")
else EID:appendToDescription(descObj, "#" .. EID:GetPlayerIcon(playerType, "P" .. i .. ":")) end
EID:appendToDescription(descObj, " {{ColorPill}}" .. name)
end
end
return descObj
end
if EID.isRepentance then
-- Handle Birthright
local function BirthrightCallback(descObj)
@@ -262,7 +298,7 @@ if EID.isRepentance then
return descObj
end
-- Handle Glowing Hourglass description
-- Handle Glowing Hourglass changed back into Hourglass description
local function GlowingHourglassCallback(descObj)
if REPENTOGON and EID.collectiblesOwned[422] then
local transformedText = EID:getDescriptionEntry("GlowingHourglassTransformed")
@@ -302,13 +338,6 @@ if EID.isRepentance then
return descObj
end
--simple decimal rounding
local function SimpleRound(num, dp)
dp = dp or 2
local mult = 10^dp
return math.floor(num * mult + 0.5)/mult
end
-- 3 coins, 1 bomb, 1 key, 1 soul heart, 2 red hearts
local consolationPickups = { "5.20", "5.40", "5.30", "5.10.3", "5.10" }
local consolationQuantity = { "3", "1", "1", "1", "2" }
@@ -321,10 +350,10 @@ if EID.isRepentance then
local playerName = player:GetName()
local playerStats = {}
playerStats[1] = SimpleRound((player.MoveSpeed * 4.5) - 2)
playerStats[2] = SimpleRound((((30/(player.MaxFireDelay + 1))^0.75) * 2.120391) - 2)
playerStats[3] = SimpleRound(((player.Damage^0.56)*2.231179) - 2)
playerStats[4] = SimpleRound(((player.TearRange - 230) / 60) + 2)
playerStats[1] = EID:SimpleRound((player.MoveSpeed * 4.5) - 2)
playerStats[2] = EID:SimpleRound((((30/(player.MaxFireDelay + 1))^0.75) * 2.120391) - 2)
playerStats[3] = EID:SimpleRound(((player.Damage^0.56)*2.231179) - 2)
playerStats[4] = EID:SimpleRound(((player.TearRange - 230) / 60) + 2)
local playerPickups = {}
playerPickups[1] = player:GetNumCoins()
@@ -517,8 +546,42 @@ if EID.isRepentance then
return descObj
end
local hasTarot = false
-- Handle Wild Card description addition
local function WildCardCallback(descObj)
for i = 1,#EID.coopAllPlayers do
local player = EID.coopAllPlayers[i]
local playerID = EID:getPlayerID(player, true)
local playerType = player:GetPlayerType()
if EID.WildCardEffects[playerID] then
EID:appendToDescription(descObj, "#")
if #EID.coopAllPlayers > 1 then EID:appendToDescription(descObj, EID:GetPlayerIcon(playerType, "P" .. i .. ":") .. " ") end
if EID.WildCardPillColor[playerID] then -- show the correct pill color; unnecessary attention to detail but why not
EID:appendToDescription(descObj, "{{Pill" .. EID.WildCardPillColor[playerID] .. "}} {{NameOnly" .. EID.WildCardEffects[playerID] .. "}}")
else EID:appendToDescription(descObj, "{{Name" .. EID.WildCardEffects[playerID] .. "}}") end
end
end
return descObj
end
-- Handle The Stars? description addition
local function TheStarsCallback(descObj)
EID:UpdateAllPlayerPassiveItems()
for i = 1,#EID.coopAllPlayers do
local player = EID.coopAllPlayers[i]
local playerID = EID:getPlayerID(player, true)
local playerType = player:GetPlayerType()
if EID.OldestItemIndex[playerID] and EID.RecentlyTouchedItems[playerID] then
local oldestItem = EID.RecentlyTouchedItems[playerID][EID.OldestItemIndex[playerID]]
if oldestItem then
EID:appendToDescription(descObj, "#")
if #EID.coopAllPlayers > 1 then EID:appendToDescription(descObj, EID:GetPlayerIcon(playerType, "P" .. i .. ":") .. " ") end
EID:appendToDescription(descObj, "{{NameC" .. oldestItem .. "}}")
end
end
end
return descObj
end
local function VariableCharge(descObj, metadata, collID, chargeText)
local text = EID:getDescriptionEntry(chargeText or "VariableCharge")
@@ -528,6 +591,7 @@ if EID.isRepentance then
end
end
local hasTarot = false
-- Handle Blank Card description addition
local function BlankCardCallback(descObj)
VariableCharge(descObj, EID.cardMetadata[descObj.ObjSubType], 286, "BlankCardCharge")
@@ -552,42 +616,6 @@ if EID.isRepentance then
VariableCharge(descObj, EID.pillMetadata[adjustedID-1], 348, "PlaceboCharge")
return descObj
end
-- Handle VURP description addition
local function VurpCallback(descObj)
local adjustedID = EID:getAdjustedSubtype(descObj.ObjType, descObj.ObjVariant, descObj.ObjSubType)
if adjustedID - 1 ~= PillEffect.PILLEFFECT_VURP then return descObj end
for i = 1,#EID.coopAllPlayers do
local player = EID.coopAllPlayers[i]
local playerID = EID:getPlayerID(player)
local playerType = player:GetPlayerType()
local pickupHistory = EID.PlayerItemInteractions[playerID].pickupHistory
-- Dead Tainted Lazarus exception
if playerType == 38 then
pickupHistory = EID.PlayerItemInteractions[playerID].altPickupHistory or pickupHistory
end
if pickupHistory then
local lastUsedPill = PillEffect.PILLEFFECT_VURP + 1
local j = 1
while (j <= #pickupHistory) do
local entry = pickupHistory[j]
-- ignore the pill if the pill color is Golden
if entry[1] == "pill" and entry[2] ~= 14 then
lastUsedPill = entry[3]
break
end
j = j + 1
end
local tableName = EID:getTableName(descObj.ObjType, descObj.ObjVariant, descObj.ObjSubType)
local name = EID:getPillName(lastUsedPill, tableName == "horsepills")
if #EID.coopAllPlayers == 1 then EID:appendToDescription(descObj, "#{{Pill}}")
else EID:appendToDescription(descObj, "#" .. EID:GetPlayerIcon(playerType, "P" .. i .. ":")) end
EID:appendToDescription(descObj, " {{ColorSilver}}" .. name)
end
end
return descObj
end
-- Handle Experimental Pill description addition
local function ExperimentalPillCallback(descObj)
@@ -734,11 +762,12 @@ if EID.isRepentance then
if EID.collectiblesOwned[286] and not EID.blankCardHidden[descObj.ObjSubType] and EID.cardMetadata[descObj.ObjSubType] then table.insert(callbacks, BlankCardCallback) end
if EID.collectiblesOwned[263] and EID.runeIDs[descObj.ObjSubType] and EID.cardMetadata[descObj.ObjSubType] then table.insert(callbacks, ClearRuneCallback) end
if descObj.ObjSubType == 80 then table.insert(callbacks, WildCardCallback) end
if descObj.ObjSubType == 73 then table.insert(callbacks, TheStarsCallback) end
-- Pill Callbacks
elseif descObj.ObjVariant == PickupVariant.PICKUP_PILL then
if EID.collectiblesOwned[654] then table.insert(callbacks, FalsePHDCallback) end
if EID.collectiblesOwned[348] then table.insert(callbacks, PlaceboCallback) end
table.insert(callbacks, VurpCallback)
table.insert(callbacks, ExperimentalPillCallback)
if EID.pillPlayer == nil and #EID.coopAllPlayers > 1 then
@@ -782,6 +811,8 @@ local function EIDConditionsAB(descObj)
elseif descObj.ObjVariant == PickupVariant.PICKUP_TRINKET then
if descObj.ObjSubType == 80 then table.insert(callbacks, BlackFeatherCallback) end
elseif descObj.ObjVariant == PickupVariant.PICKUP_PILL then
table.insert(callbacks, VurpCallback)
end
return callbacks
end
+5 -13
View File
@@ -22,13 +22,6 @@ local triggerColors = {
local actions = { [0] = "use_active_item", "add_temporary_effect", "convert_entities", "area_damage", "spawn_entity", "fart" }
local triggers = { [0] = "active", "tear_fire", "enemy_hit", "enemy_kill", "damage_taken", "room_clear", "entity_spawned", "pickup_collected", "chain" }
--simple decimal rounding
local function SimpleRound(num, dp)
dp = dp or 2
local mult = 10^dp
return math.floor(num * mult + 0.5)/mult
end
local function entityToName(Type, Variant, plural)
plural = plural or false
-- -1 is often used as an "any of this type", even if there's only one of that type, so converting it to 0 can help find names
@@ -122,8 +115,7 @@ function EID:CheckGlitchedItemConfig(id)
for i,func in ipairs(getFunctions) do
local val = item[func](item) * statMult[i]
if val ~= 0 then
if (i == 4) then print("range!") end
local s = string.format("%.2g",SimpleRound(val))
local s = string.format("%.2g",EID:SimpleRound(val))
local prefix = "↑ "
if val > 0 then s = "+" .. s else prefix = "↓ " end
attributes = attributes .. prefix .. EID:ReplaceVariableStr(voidNames[i], 1, s) .. "#"
@@ -156,13 +148,13 @@ function EID:CheckGlitchedItemConfig(id)
replacements[1] = "{{ColorGray}}" .. entityToName(effectProp.type, effectProp.variant) .. "{{CR}}"
elseif effectType == "fart" then
--I think the fart scale is strictly visual and therefore useless
--replacements[1] = SimpleRound(effectProp.scale)
replacements[1] = string.format("%.4g",SimpleRound(effectProp.radius))
--replacements[1] = EID:SimpleRound(effectProp.scale)
replacements[1] = string.format("%.4g",EID:SimpleRound(effectProp.radius))
elseif effectType == "area_damage" then
replacements[1] = string.format("%.4g",SimpleRound(effectProp.damage))
replacements[1] = string.format("%.4g",EID:SimpleRound(effectProp.damage))
--Fart scales are all small numbers and seem to be tiles; area damage is huge numbers, but still tiles?
--so area damage is almost always the entire room
replacements[2] = string.format("%.4g",SimpleRound(effectProp.radius))
replacements[2] = string.format("%.4g",EID:SimpleRound(effectProp.radius))
end
if effectTrigger ~= lastEffectTrigger then
+143 -68
View File
@@ -10,8 +10,8 @@ EID.isRepentance = REPENTANCE -- REPENTANCE variable can be altered by any mod,
require("eid_config")
EID.Config = EID.UserConfig
EID.Config.Version = "3.2" -- note: changing this will reset everyone's settings to default!
EID.ModVersion = 4.76
EID.ModVersionCommit = "2ae651d"
EID.ModVersion = 4.78
EID.ModVersionCommit = "2b3c48d"
EID.DefaultConfig.Version = EID.Config.Version
EID.isHidden = false
EID.player = nil -- The primary Player Entity of Player 1
@@ -51,6 +51,8 @@ EID.holdTabPlayer = 0
EID.holdTabCounter = 0
EID.DInfinityState = {}
local forgottenDropTimer = 0
EID.roomCount = 0
local preHourglassStatus = {}
EID.GameUpdateCount = 0
EID.GameRenderCount = 0
@@ -375,7 +377,8 @@ end
-- Watch for a Void absorbing active items
function EID:CheckVoidAbsorbs(_, _, player)
local playerID = EID:getPlayerID(player)
player = player or EID.player
local playerID = EID:getPlayerID(player, true)
EID.absorbedItems[tostring(playerID)] = EID.absorbedItems[tostring(playerID)] or {}
for _,v in ipairs(EID:VoidRoomCheck()) do
EID.absorbedItems[tostring(playerID)][tostring(v)] = true
@@ -672,7 +675,7 @@ function EID:printDescription(desc, cachedID)
if #EID.coopAllPlayers > 1 then
transformationName = transformationName .. EID:GetPlayerIcon(playerType)
end
local numCollected = EID.TransformationProgress[EID:getPlayerID(player)] and EID.TransformationProgress[EID:getPlayerID(player)][transform] or 0
local numCollected = EID.TransformationProgress[EID:getPlayerID(player, true)] and EID.TransformationProgress[EID:getPlayerID(player, true)][transform] or 0
local numMax = EID.TransformationData[transform] and EID.TransformationData[transform].NumNeeded or 3
transformationName = transformationName.."("..numCollected.."/"..numMax..") "
end
@@ -776,6 +779,18 @@ end
function EID:onNewRoom()
EID:CheckCurrentRoomGridEntities()
EID.roomCount = EID.roomCount + 1
-- Store values here to be rewound after using Glowing Hour Glass
preHourglassStatus = {}
preHourglassStatus.absorbedItems = EID:CopyTable(EID.absorbedItems)
preHourglassStatus.PlayerItemInteractions = EID:CopyTable(EID.PlayerItemInteractions)
if EID.isRepentance then
preHourglassStatus.WildCardEffects = EID:CopyTable(EID.WildCardEffects)
preHourglassStatus.WildCardPillColor = EID:CopyTable(EID.WildCardPillColor)
preHourglassStatus.DInfinityState = EID:CopyTable(EID.DInfinityState)
preHourglassStatus.BagItems = EID:CopyTable(EID.BoC.BagItems)
preHourglassStatus.RoomQueries = EID:CopyTable(EID.BoC.RoomQueries)
end
end
EID:AddCallback(ModCallbacks.MC_POST_NEW_ROOM, EID.onNewRoom)
@@ -1063,31 +1078,32 @@ function EID:onGameUpdate()
EID.RecheckVoid = true
end
if EID.isRepentance and EID.GameUpdateCount % 10 == 0 then
-- Check wisp for adding reminder when using lemegeton
if EID.ShouldCheckWisp then
for _, wisp in ipairs(Isaac.FindByType(3, 237, -1, true, false)) do
if wisp.FrameCount < 10 then
local player = wisp:ToFamiliar() and wisp:ToFamiliar().Player
if player then
local playerID = EID:getPlayerID(player)
EID:InitItemInteractionIfAbsent(playerID)
table.insert(EID.RecentlyTouchedItems[playerID], wisp.SubType)
end
end
-- Check player items for starting items
if EID.ShouldCheckStartingItems then
EID:UpdateAllPlayerPassiveItems()
EID:SetOldestItemIndex()
EID.ShouldCheckStartingItems = false
end
if EID.isRepentance then
EID:UpdateWildCardEffects()
if EID.GameUpdateCount % 10 == 0 then
-- Check wisp for adding reminder when using lemegeton
if EID.ShouldCheckWisp then
EID:UpdateAllPlayerLemegetonWisps()
EID.ShouldCheckWisp = false
end
EID.ShouldCheckWisp = false
end
-- Remove Crane Game item data if it's giving the prize out
for _, crane in ipairs(Isaac.FindByType(6, 16, -1, true, false)) do
if EID.CraneItemType[tostring(crane.InitSeed)] then
if crane:GetSprite():IsPlaying("Prize") then
EID.CraneItemType[tostring(crane.InitSeed)] = nil
-- Pair the Crane Game's new drop seed with the latest collectible ID it's gotten
-- (fixes Glowing Hour Glass rewinds)
elseif EID.CraneItemType[crane.InitSeed.."Drop"..crane.DropSeed] == nil then
EID.CraneItemType[crane.InitSeed.."Drop"..crane.DropSeed] = EID.CraneItemType[tostring(crane.InitSeed)]
-- Remove Crane Game item data if it's giving the prize out
for _, crane in ipairs(Isaac.FindByType(6, 16, -1, true, false)) do
if EID.CraneItemType[tostring(crane.InitSeed)] then
if crane:GetSprite():IsPlaying("Prize") then
EID.CraneItemType[tostring(crane.InitSeed)] = nil
-- Pair the Crane Game's new drop seed with the latest collectible ID it's gotten
-- (fixes Glowing Hour Glass rewinds)
elseif EID.CraneItemType[crane.InitSeed.."Drop"..crane.DropSeed] == nil then
EID.CraneItemType[crane.InitSeed.."Drop"..crane.DropSeed] = EID.CraneItemType[tostring(crane.InitSeed)]
end
end
end
end
@@ -1185,20 +1201,20 @@ function EID:CheckPosModifiers()
else
-- Tainted Isaac and Tainted ??? unique HUD adjustment
if EID.player:GetPlayerType() == 21 or EID.player:GetPlayerType() == 25 then
EID:addTextPosModifier("Tainted HUD", Vector(0,30))
EID:addTextPosModifier("Tainted HUD", Vector(0,26))
else
EID:removeTextPosModifier("Tainted HUD")
end
-- Jacob and Esau card/pill adjustment
if EID.player:GetPlayerType() == 19 then
EID:addTextPosModifier("J&E HUD", Vector(0,15))
EID:addTextPosModifier("J&E HUD", Vector(0,16))
else
EID:removeTextPosModifier("J&E HUD")
end
-- Magdalene Birthright, Keeper & Tainted Keeper third/fourth row of hearts adjustment
if EID.player:GetEffectiveMaxHearts() + EID.player:GetSoulHearts() + (EID.player:GetBrokenHearts() * 2) >= 37 then
EID:removeTextPosModifier("18 Heart HUD")
EID:addTextPosModifier("24 Heart HUD", Vector(0,22))
EID:addTextPosModifier("24 Heart HUD", Vector(0,20))
elseif EID.player:GetEffectiveMaxHearts() + EID.player:GetSoulHearts() + (EID.player:GetBrokenHearts() * 2) >= 25 then
EID:removeTextPosModifier("24 Heart HUD")
EID:addTextPosModifier("18 Heart HUD", Vector(0,10))
@@ -1298,7 +1314,7 @@ function EID:OnRender()
local dropTriggered, playerNumPressingDrop = EID:PlayersActionPressed(ButtonAction.ACTION_DROP, Input.IsActionTriggered)
if dropTriggered then
local playerPressingDrop = EID.coopMainPlayers[playerNumPressingDrop]
local playerID = EID:getPlayerID(playerPressingDrop)
local playerID = EID:getPlayerID(playerPressingDrop, true)
local playerType = playerPressingDrop:GetPlayerType()
-- Forgotten's drop requires a double tap to actually count for this
if (playerType == 16 or playerType == 17) then
@@ -1465,10 +1481,10 @@ function EID:OnRender()
elseif closest.Type == 1000 and closest.Variant == 161 and closest.SubType <= 2 then
local subtypeToCard = {18, 5, 19}
-- Reuse the descriptions of The Emperor/Stars/Moon, so no localization needed
local descriptionObj = EID:getDescriptionObj(5, 300, subtypeToCard[closest.SubType+1], closest, false)
local descriptionObj = EID:getDescriptionObj(5, 300, subtypeToCard[closest.SubType+1], closest)
-- Card Reading's name
descriptionObj.Name = EID:getObjectName(5, 100, 660)
-- Only keep the first line of the description
-- Only keep the first line of the description (to avoid Tarot Cloth effects or Planetarium mention on The Stars)
descriptionObj.Description = string.sub(descriptionObj.Description, 1, string.find(descriptionObj.Description, "#"))
EID:addDescriptionToPrint(descriptionObj)
-- Handle Crane Game
@@ -1596,13 +1612,9 @@ EID:AddCallback(ModCallbacks.MC_POST_RENDER, EID.OnRender)
local function AddActiveItemProgress(player, isD4)
EID.ForceRefreshCache = true
local playerID = EID:getPlayerID(player)
local playerID = EID:getPlayerID(player, true)
EID:InitItemInteractionIfAbsent(playerID)
-- Dead Tainted Lazarus exceptions
local activesTable = EID.PlayerItemInteractions[playerID].actives
if player:GetPlayerType() == 38 then
activesTable = EID.PlayerItemInteractions[playerID].altActives or activesTable
end
-- don't check pocket items after D4, they don't reroll and would get counted twice
local maxSlot = 3
if isD4 then maxSlot = 1 end
@@ -1629,22 +1641,61 @@ local function OnGameStartGeneral(_,isSave)
EID:GetTransformationsOfModdedItems()
EID:buildTransformationTables()
EID.RecentlyTouchedItems = {}
EID.GulpedTrinkets = {}
EID.OldestItemIndex = {}
if not isSave then
EID.PlayerItemInteractions = {}
EID.DInfinityState = {}
end
EID.ShouldCheckWisp = true
EID.WildCardEffects = {}
EID.roomCount = 0
end
EID:AddCallback(ModCallbacks.MC_POST_GAME_STARTED, OnGameStartGeneral)
local function OnPostPlayerInit()
EID.ShouldCheckStartingItems = true -- for The Stars? tracking
end
EID:AddCallback(ModCallbacks.MC_POST_PLAYER_INIT, OnPostPlayerInit)
-- Add currently held active items after D4 was used. Used for Transformation Progress
local function OnUseD4(_, _, _, player)
-- in AB+, USE_ITEM doesn't provide a player
AddActiveItemProgress(player or EID.player, true)
-- repentance fixed needing to blacklist your new items from counting (and AB+ counts everything)
--EID:CollectRerolledItemsOfPlayer(player or EID.player)
if EID.isRepentance then
local playerNum = EID:getPlayerID(player, true)
EID.OldestItemIndex[playerNum] = -1 -- D4 makes it impossible for us to know what the oldest item is for The Stars?
end
end
EID:AddCallback(ModCallbacks.MC_USE_ITEM, OnUseD4, CollectibleType.COLLECTIBLE_D4)
-- Watch for smelting trinkets; includes Gulp and Marbles
local function OnUseSmelter(_, _, _, player)
player = player or EID.player
local playerNum = EID:getPlayerID(player, true)
EID.GulpedTrinkets[playerNum] = EID.GulpedTrinkets[playerNum] or {}
for i=0,1 do
local trinket = player:GetTrinket(i)
if trinket > 0 then table.insert(EID.GulpedTrinkets[playerNum], trinket) end
end
end
EID:AddCallback(ModCallbacks.MC_PRE_USE_ITEM, OnUseSmelter, CollectibleType.COLLECTIBLE_SMELTER)
-- Watch for Glowing Hourglass to revert certain variables
local function OnUseGlowingHourglass(_, _, _, _)
EID.absorbedItems = EID:CopyTable(preHourglassStatus.absorbedItems)
EID.PlayerItemInteractions = EID:CopyTable(preHourglassStatus.PlayerItemInteractions)
if EID.isRepentance then
EID.WildCardEffects = EID:CopyTable(preHourglassStatus.WildCardEffects)
EID.WildCardPillColor = EID:CopyTable(preHourglassStatus.WildCardPillColor)
EID.DInfinityState = EID:CopyTable(preHourglassStatus.DInfinityState)
EID.BoC.BagItems = EID:CopyTable(preHourglassStatus.BagItems)
EID.BoC.RoomQueries = EID:CopyTable(preHourglassStatus.RoomQueries)
end
end
EID:AddCallback(ModCallbacks.MC_PRE_USE_ITEM, OnUseGlowingHourglass, CollectibleType.COLLECTIBLE_GLOWING_HOUR_GLASS)
-- Re-init transformation progress and item interactions after using Genesis
if EID.isRepentance then
local function OnUseGenesis(_, _, _, _)
@@ -1658,6 +1709,14 @@ if EID.isRepentance then
end
EID:AddCallback(ModCallbacks.MC_PRE_USE_ITEM, OnUseLemegeton, CollectibleType.COLLECTIBLE_LEMEGETON)
-- Watch for any active item usage for Wild Card
local function OnUseGeneral(_, collectibleType, _, player, useFlags, activeSlot)
-- add the active to Wild Card tracking if it was a real active usage
if useFlags & UseFlag.USE_OWNED > 0 and activeSlot >= 0 then
EID:TrackWildCardEffects("5.100." .. collectibleType, player)
end
end
EID:AddCallback(ModCallbacks.MC_PRE_USE_ITEM, OnUseGeneral)
end
function EID:OnUsePill(pillEffectID, player, useFlags)
@@ -1666,9 +1725,11 @@ function EID:OnUsePill(pillEffectID, player, useFlags)
local pillColor = EID.PlayerHeldPill[EID:getPlayerID(player)]
-- add the pill used to our history for Echo Chamber / Vurp! / transformation progress
EID:AddPickupToHistory("pill", pillEffectID+1, player, useFlags, pillColor)
-- add the pill to Wild Card tracking, unless it's a Temperance? pill
if EID.isRepentance and useFlags ~= UseFlag.USE_NOANNOUNCER then EID:TrackWildCardEffects("5.70." .. (pillEffectID+1), player, pillColor) end
EID.ForceRefreshCache = true -- for transformation progress update
-- for tracking used pills, ignore gold pills and noannouncer flag pills
-- for tracking used pills, ignore gold pills and noannouncer flag pills (Temperance?)
-- (not using a bitmask, because Placebo is mimic+noannouncer, and we want to count those)
if EID.isRepentance and (pillColor % PillColor.PILL_GIANT_FLAG == PillColor.PILL_GOLD or useFlags == UseFlag.USE_NOANNOUNCER) then return end
EID.UsedPillColors[tostring(pillColor)] = true
@@ -1678,6 +1739,8 @@ EID:AddCallback(ModCallbacks.MC_USE_PILL, EID.OnUsePill)
function EID:OnUseCard(cardID, player, useFlags)
player = player or EID.player --AB+ doesn't receive player in callback arguments!
EID:AddPickupToHistory("card", cardID, player, useFlags)
-- add the card to Wild Card tracking unless it's Wild Card
if EID.isRepentance and cardID ~= 80 then EID:TrackWildCardEffects("5.300." .. cardID, player) end
end
EID:AddCallback(ModCallbacks.MC_USE_CARD, EID.OnUseCard)
@@ -1693,16 +1756,34 @@ local configIgnoreList = {
["PlayerItemInteractions"] = true,
["UsedPillColors"] = true,
["RecentlyTouchedItems"] = true,
["GulpedTrinkets"] = true,
["WildCardEffects"] = true,
["DInfinityState"] = true,
["OldestItemIndex"] = true,
}
--------------------------------
--------Handle Savadata---------
--------Handle Savedata---------
--------------------------------
function EID:OnGameStart(isSave)
--Loading Moddata--
if EID:HasData() then
local savedEIDConfig = json.decode(Isaac.LoadModData(EID))
-- JSON saves integer table keys as strings. we need to transform them back... used in OnGameStart
local function ConvertSavedTable(tableName)
for playerID, data in pairs(savedEIDConfig[tableName] or {}) do
local convertedData = {}
if type(data) == "table" then
for key, value in pairs(data) do
convertedData[tonumber(key) or key] = value
end
else
convertedData = data
end
EID[tableName][tonumber(playerID)] = convertedData
end
end
-- collection progress
EID.CollectedItems = savedEIDConfig["CollectedItems"] or {}
if EID.SaveGame and savedEIDConfig["SaveGameNumber"] > 0 then
@@ -1713,44 +1794,35 @@ function EID:OnGameStart(isSave)
EID.PlayerItemInteractions = {}
if isSave then
-- JSON saves integer table keys as strings. we need to transform them back...
for playerID, data in pairs(savedEIDConfig["PlayerItemInteractions"] or {}) do
local convertedData = {}
for key, value in pairs(data) do
convertedData[tonumber(key) or key] = value
end
EID.PlayerItemInteractions[tonumber(playerID)] = convertedData
end
for playerID, data in pairs(savedEIDConfig["RecentlyTouchedItems"] or {}) do
local convertedData = {}
for key, value in pairs(data) do
convertedData[tonumber(key) or key] = value
end
EID.RecentlyTouchedItems[tonumber(playerID)] = convertedData
end
ConvertSavedTable("PlayerItemInteractions")
ConvertSavedTable("RecentlyTouchedItems")
ConvertSavedTable("GulpedTrinkets")
ConvertSavedTable("WildCardEffects")
ConvertSavedTable("DInfinityState")
ConvertSavedTable("OldestItemIndex")
else
-- check for the players' starting active items
CheckAllActiveItemProgress()
end
EID.UsedPillColors = {}
EID.absorbedItems = {}
if isSave then
EID.UsedPillColors = savedEIDConfig["UsedPillColors"] or {}
EID.absorbedItems = savedEIDConfig["AbsorbedItems"] or {}
end
if EID.isRepentance then
EID.BoC.BagItems = {}
EID.BoC.LearnedRecipes = {}
EID.CraneItemType = {}
EID.flipItemPositions = {}
EID.absorbedItems = {}
if isSave then
EID.BoC.BagItems = savedEIDConfig["BagContent"] or {}
EID.BoC.LearnedRecipes = savedEIDConfig["BagLearnedRecipes"] or {}
EID.BoC.RoomQueries = savedEIDConfig["BagFloorContent"] or {}
EID.CraneItemType = savedEIDConfig["CraneItemType"] or {}
EID.absorbedItems = savedEIDConfig["AbsorbedItems"] or {}
-- turn list back into dict because json cant save dict indices.
local flipItemTable = {}
for _, v in ipairs(savedEIDConfig["FlipItemPositions"]) do
@@ -1794,7 +1866,7 @@ function EID:OnGameStart(isSave)
EID.UsedPosition = Vector(EID.Config["XPosition"], EID.Config["YPosition"])
EID.Scale = EID.Config["Size"]
EID.ItemReminderSelectedCategory = EID.Config["ItemReminderDisplayMode"] == "NoOverview" and 1 or 0
EID:fixDefinedFont()
EID:loadFont(EID.modPath .. "resources/font/eid_"..EID.Config["FontType"]..".fnt")
end
@@ -1808,8 +1880,8 @@ function EID:OnGameExit()
EID.Config["BagLearnedRecipes"] = EID.BoC.LearnedRecipes or {}
EID.Config["BagFloorContent"] = EID.BoC.RoomQueries or {}
EID.Config["CraneItemType"] = EID.CraneItemType or {}
EID.Config["AbsorbedItems"] = EID.absorbedItems or {}
EID.Config["WildCardEffects"] = EID.WildCardEffects or {}
EID.Config["DInfinityState"] = EID.DInfinityState or {}
-- turn dictionary into list because json cant save dict indices.
local flipItemTable = {}
for k, v in pairs(EID.flipItemPositions) do
@@ -1824,7 +1896,10 @@ function EID:OnGameExit()
EID.Config["CollectedItems"] = EID.CollectedItems
EID.Config["PlayerItemInteractions"] = EID.PlayerItemInteractions or {}
EID.Config["RecentlyTouchedItems"] = EID.RecentlyTouchedItems or {}
EID.Config["GulpedTrinkets"] = EID.GulpedTrinkets or {}
EID.Config["UsedPillColors"] = EID.UsedPillColors
EID.Config["AbsorbedItems"] = EID.absorbedItems or {}
EID.Config["OldestItemIndex"] = EID.OldestItemIndex or {}
EID.SaveData(EID, json.encode(EID.Config))
EID:hidePermanentText()
+1 -1
View File
@@ -51,7 +51,7 @@ You are currently looking at the version for Afterbirth+ and Repentance.
[img]https://i.imgur.com/jrdGbna.png[/img]
[url=https://github.com/wofsauge/External-Item-Descriptions/blob/master/CREDITS.md]Check out the credits here[/url]
</description>
<version>4.76</version>
<version>4.78</version>
<visibility>Public</visibility>
<tag id="Lua"/>
<tag id="Items"/>