Skip to content

Commit 4e188ad

Browse files
committed
Enhance transformation progress tracking logic
1 parent 695a6e0 commit 4e188ad

5 files changed

Lines changed: 46 additions & 7 deletions

File tree

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
# Changelog
22

3+
## 0.6.1 - 2026-08-21
4+
5+
- Made transformation progress refresh immediately when one of multiple identical
6+
transformation pedestals is collected in the same room. The displayed count now
7+
combines the live inventory with Isaac's persisted PlayerForm state.
8+
39
## 0.6.0 - 2026-08-20
410

511
- Added a top-left pause-only inventory browser for collectibles, active items,

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,8 @@ The overlay tracks the player's position and displays the nearest eligible objec
3838
- Untouched floor cards and runes remain hidden until the game marks them touched or a player holds them in a native pocket slot.
3939
- Pills remain hidden until Isaac's native ItemPool state identifies their effect.
4040
- Curse of the Blind suppresses every collectible description using the native level curse mask. The forced-blind field and question-mark sprite are retained as additional guards.
41-
- Transformation progress is read from the player's native persisted transformation state instead of nearby-item observations.
42-
- The 14 normal transformations use Isaac's persisted native PlayerForm counters, so replaced active items and saved/reloaded runs keep their real progress. Super Bum completion is read from its native merged familiar.
41+
- Transformation progress combines Isaac's persisted PlayerForm counters with the live owned-item table. It updates immediately after a pickup while still preserving progress across active-item replacement and save reloads.
42+
- The 14 normal transformations use the native counters and inventory state. Super Bum completion is read from its native merged familiar.
4343
- Native run identity and seed tracking reset learned cards and run-only knowledge when a new run begins.
4444

4545
### Artwork and presentation

include/EIDTransformationProgress.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ NS_ASSUME_NONNULL_BEGIN
1111
- (NSArray<NSNumber *> *)allTransformationIdentifiers;
1212
- (NSArray<NSNumber *> *)transformationsForCollectible:(NSInteger)collectible;
1313
- (NSInteger)progressForTransformation:(NSInteger)transformation;
14+
- (NSString *)progressSignatureForPickups:(NSArray *)pickups;
1415
- (NSString *)localizedNameForTransformation:(NSInteger)transformation;
1516
- (NSString *)englishNameForTransformation:(NSInteger)transformation;
1617
@end

src/EIDOverlayController.m

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,7 @@ @interface EIDOverlayController ()
129129
@property(nonatomic) NSUInteger consecutiveMenuScans;
130130
@property(nonatomic, strong) EIDPickupIdentity *selectedInventoryItem;
131131
@property(nonatomic, copy) NSString *inventorySignature;
132+
@property(nonatomic, copy) NSString *transformationProgressSignature;
132133
@property(nonatomic) BOOL pauseUIActive;
133134
@end
134135

@@ -454,7 +455,12 @@ - (void)tick:(NSTimer *)timer {
454455
BOOL paused = self.probe.gameplayActive && self.probe.pauseStateAvailable &&
455456
self.probe.paused;
456457
[self updatePauseInventoryForPaused:paused];
457-
if (![pickups isEqualToArray:self.lastPickups]) {
458+
NSString *progressSignature = [[EIDTransformationProgress shared]
459+
progressSignatureForPickups:pickups];
460+
BOOL progressChanged = ![progressSignature
461+
isEqualToString:self.transformationProgressSignature ?: @""];
462+
self.transformationProgressSignature = progressSignature;
463+
if (![pickups isEqualToArray:self.lastPickups] || progressChanged) {
458464
self.lastPickups = pickups;
459465
if (!self.menuMode && !paused && !self.selectedInventoryItem) {
460466
[self renderPickups:pickups];

src/EIDTransformationProgress.m

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -162,9 +162,20 @@ - (NSInteger)progressForTransformation:(NSInteger)transformation {
162162
if (transformation <= 0) return 0;
163163
NSInteger nativeForm = EIDNativeFormIDForTransformation(transformation);
164164
if (nativeForm != NSNotFound) {
165-
if (!self.probe.transformationStateAvailable) return 0;
166-
NSInteger count = [self.probe nativeTransformationCounterForFormID:nativeForm];
167-
return MIN(self.required, MAX(0, count));
165+
NSInteger nativeCount = self.probe.transformationStateAvailable
166+
? [self.probe nativeTransformationCounterForFormID:nativeForm] : 0;
167+
NSInteger liveCount = 0;
168+
if (self.probe.ownedCollectibleStateAvailable) {
169+
for (NSNumber *collectible in self.collectiblesByTransformation[@(transformation)]) {
170+
liveCount += [self.probe
171+
transformationCollectibleCountForID:collectible.integerValue];
172+
}
173+
}
174+
// PlayerForm is authoritative across reloads and after an active item is
175+
// replaced, but Isaac can update it a few frames after the live inventory.
176+
// Taking the maximum gives an immediate in-room update without losing the
177+
// persisted history that the inventory alone cannot reconstruct.
178+
return MIN(self.required, MAX(0, MAX(nativeCount, liveCount)));
168179
}
169180

170181
// Super Bum (EID 11) is a familiar merge, not an entry in the native
@@ -179,6 +190,21 @@ - (NSInteger)progressForTransformation:(NSInteger)transformation {
179190
return MIN(self.required, MAX(0, count));
180191
}
181192

193+
- (NSString *)progressSignatureForPickups:(NSArray<EIDPickupIdentity *> *)pickups {
194+
EIDPickupIdentity *pickup = pickups.firstObject;
195+
if (!pickup || pickup.variant != EIDPickupVariantCollectible) return @"";
196+
NSArray<NSNumber *> *transformations = [self transformationsForCollectible:pickup.subtype];
197+
if (!transformations.count) return @"";
198+
199+
NSMutableArray<NSString *> *parts = [NSMutableArray arrayWithCapacity:transformations.count];
200+
for (NSNumber *transformation in transformations) {
201+
[parts addObject:[NSString stringWithFormat:@"%@=%ld", transformation,
202+
(long)[self progressForTransformation:transformation.integerValue]]];
203+
}
204+
return [NSString stringWithFormat:@"%lu:%ld:%@", (unsigned long)self.probe.runCounter,
205+
(long)pickup.subtype, [parts componentsJoinedByString:@","]];
206+
}
207+
182208
- (void)logProgressForCollectible:(NSInteger)collectible
183209
transformations:(NSArray<NSNumber *> *)transformations {
184210
if (!transformations.count) return;
@@ -194,7 +220,7 @@ - (void)logProgressForCollectible:(NSInteger)collectible
194220
static NSString *lastLoggedState;
195221
if ([lastLoggedState isEqualToString:state]) return;
196222
lastLoggedState = state;
197-
EIDLog(@"transformation progress for collectible %ld: %@ (persisted native counters %@)",
223+
EIDLog(@"transformation progress for collectible %ld: %@ (native/live counters %@)",
198224
(long)collectible, [parts componentsJoinedByString:@", "],
199225
self.probe.transformationStateAvailable ? @"ready" : @"unavailable");
200226
}

0 commit comments

Comments
 (0)