isaacscript-common 6.16.2 → 6.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/features/persistentEntities.d.ts.map +1 -1
- package/dist/features/persistentEntities.lua +15 -5
- package/dist/features/pickupIndex.d.ts.map +1 -1
- package/dist/features/pickupIndex.lua +2 -4
- package/dist/features/roomHistory.d.ts +11 -4
- package/dist/features/roomHistory.d.ts.map +1 -1
- package/dist/features/roomHistory.lua +18 -5
- package/dist/functions/log.d.ts.map +1 -1
- package/dist/functions/log.lua +6 -1
- package/dist/functions/npcs.d.ts +9 -0
- package/dist/functions/npcs.d.ts.map +1 -1
- package/dist/functions/npcs.lua +16 -3
- package/dist/functions/playerHealth.d.ts.map +1 -1
- package/dist/functions/playerHealth.lua +29 -12
- package/dist/functions/rockAlt.lua +18 -18
- package/dist/interfaces/PlayerHealth.d.ts +4 -1
- package/dist/interfaces/PlayerHealth.d.ts.map +1 -1
- package/dist/interfaces/RoomDescription.d.ts +1 -0
- package/dist/interfaces/RoomDescription.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/features/persistentEntities.ts +19 -5
- package/src/features/pickupIndex.ts +5 -11
- package/src/features/roomHistory.ts +24 -4
- package/src/functions/log.ts +6 -1
- package/src/functions/npcs.ts +27 -2
- package/src/functions/playerHealth.ts +25 -12
- package/src/functions/rockAlt.ts +21 -21
- package/src/interfaces/PlayerHealth.ts +12 -1
- package/src/interfaces/RoomDescription.ts +1 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"persistentEntities.d.ts","sourceRoot":"","sources":["../../src/features/persistentEntities.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,UAAU,EAEX,MAAM,8BAA8B,CAAC;
|
|
1
|
+
{"version":3,"file":"persistentEntities.d.ts","sourceRoot":"","sources":["../../src/features/persistentEntities.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,UAAU,EAEX,MAAM,8BAA8B,CAAC;AAgHtC;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,qBAAqB,CACnC,UAAU,EAAE,UAAU,EACtB,OAAO,EAAE,GAAG,EACZ,OAAO,EAAE,GAAG,EACZ,QAAQ,EAAE,MAAM,GACf,CAAC,MAAM,EAAE,GAAG,CAAC,CAcf;AAwBD;;;;;;;;GAQG;AACH,wBAAgB,sBAAsB,CACpC,qBAAqB,EAAE,GAAG,EAC1B,YAAY,UAAO,GAClB,IAAI,CAiBN"}
|
|
@@ -3,7 +3,7 @@ local Map = ____lualib.Map
|
|
|
3
3
|
local __TS__New = ____lualib.__TS__New
|
|
4
4
|
local __TS__Iterator = ____lualib.__TS__Iterator
|
|
5
5
|
local ____exports = {}
|
|
6
|
-
local postEntityRemove, postNewRoomReordered, spawnAndTrack, v
|
|
6
|
+
local postEntityRemove, checkDespawningFromPlayerLeavingRoom, trackDespawningPickupPosition, postNewRoomReordered, spawnAndTrack, v
|
|
7
7
|
local ____isaac_2Dtypescript_2Ddefinitions = require("isaac-typescript-definitions")
|
|
8
8
|
local EntityFlag = ____isaac_2Dtypescript_2Ddefinitions.EntityFlag
|
|
9
9
|
local ModCallback = ____isaac_2Dtypescript_2Ddefinitions.ModCallback
|
|
@@ -17,15 +17,25 @@ local ____roomData = require("functions.roomData")
|
|
|
17
17
|
local getRoomListIndex = ____roomData.getRoomListIndex
|
|
18
18
|
local ____roomHistory = require("features.roomHistory")
|
|
19
19
|
local getLatestRoomDescription = ____roomHistory.getLatestRoomDescription
|
|
20
|
+
local isLeavingRoom = ____roomHistory.isLeavingRoom
|
|
20
21
|
local ____exports = require("features.saveDataManager.exports")
|
|
21
22
|
local saveDataManager = ____exports.saveDataManager
|
|
22
23
|
function postEntityRemove(self, entity)
|
|
24
|
+
checkDespawningFromPlayerLeavingRoom(nil, entity)
|
|
25
|
+
end
|
|
26
|
+
function checkDespawningFromPlayerLeavingRoom(self, entity)
|
|
23
27
|
local ptrHash = GetPtrHash(entity)
|
|
24
28
|
local tuple = v.room.spawnedPersistentEntities:get(ptrHash)
|
|
25
29
|
if tuple == nil then
|
|
26
30
|
return
|
|
27
31
|
end
|
|
28
32
|
local index = tuple[1]
|
|
33
|
+
if not isLeavingRoom(nil) then
|
|
34
|
+
return
|
|
35
|
+
end
|
|
36
|
+
trackDespawningPickupPosition(nil, entity, index)
|
|
37
|
+
end
|
|
38
|
+
function trackDespawningPickupPosition(self, entity, index)
|
|
29
39
|
local previousRoomDescription = getLatestRoomDescription(nil)
|
|
30
40
|
local previousRoomListIndex = previousRoomDescription.roomListIndex
|
|
31
41
|
local persistentEntityDescription = {
|
|
@@ -44,7 +54,7 @@ function postNewRoomReordered(self)
|
|
|
44
54
|
local description = ____value[2]
|
|
45
55
|
do
|
|
46
56
|
if roomListIndex ~= description.roomListIndex then
|
|
47
|
-
goto
|
|
57
|
+
goto __continue9
|
|
48
58
|
end
|
|
49
59
|
v.level.persistentEntities:delete(index)
|
|
50
60
|
spawnAndTrack(
|
|
@@ -57,7 +67,7 @@ function postNewRoomReordered(self)
|
|
|
57
67
|
true
|
|
58
68
|
)
|
|
59
69
|
end
|
|
60
|
-
::
|
|
70
|
+
::__continue9::
|
|
61
71
|
end
|
|
62
72
|
end
|
|
63
73
|
function spawnAndTrack(self, entityType, variant, subType, position, index, respawning)
|
|
@@ -142,14 +152,14 @@ function ____exports.removePersistentEntity(self, persistentEntityIndex, removeE
|
|
|
142
152
|
do
|
|
143
153
|
local index, entityPtr = table.unpack(tuple)
|
|
144
154
|
if index ~= persistentEntityIndex then
|
|
145
|
-
goto
|
|
155
|
+
goto __continue16
|
|
146
156
|
end
|
|
147
157
|
v.room.spawnedPersistentEntities:delete(ptrHash)
|
|
148
158
|
if removeEntity and entityPtr.Ref ~= nil then
|
|
149
159
|
entityPtr.Ref:Remove()
|
|
150
160
|
end
|
|
151
161
|
end
|
|
152
|
-
::
|
|
162
|
+
::__continue16::
|
|
153
163
|
end
|
|
154
164
|
end
|
|
155
165
|
return ____exports
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pickupIndex.d.ts","sourceRoot":"","sources":["../../src/features/pickupIndex.ts"],"names":[],"mappings":";AAOA,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAQrD,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"pickupIndex.d.ts","sourceRoot":"","sources":["../../src/features/pickupIndex.ts"],"names":[],"mappings":";AAOA,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAQrD,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AA+BnD,wBAAgB,eAAe,CAAC,GAAG,EAAE,WAAW,GAAG,IAAI,CAatD;AAqKD;;;;;;;;;;;;GAYG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,YAAY,GAAG,WAAW,CAahE"}
|
|
@@ -28,6 +28,7 @@ local ____vector = require("functions.vector")
|
|
|
28
28
|
local vectorEquals = ____vector.vectorEquals
|
|
29
29
|
local ____roomHistory = require("features.roomHistory")
|
|
30
30
|
local getLatestRoomDescription = ____roomHistory.getLatestRoomDescription
|
|
31
|
+
local isLeavingRoom = ____roomHistory.isLeavingRoom
|
|
31
32
|
local ____exports = require("features.saveDataManager.exports")
|
|
32
33
|
local saveDataManager = ____exports.saveDataManager
|
|
33
34
|
function postPickupInit(self, pickup)
|
|
@@ -44,7 +45,6 @@ function postPickupInit(self, pickup)
|
|
|
44
45
|
local ____v_run_0, ____pickupCounter_1 = v.run, "pickupCounter"
|
|
45
46
|
____v_run_0[____pickupCounter_1] = ____v_run_0[____pickupCounter_1] + 1
|
|
46
47
|
v.room.pickupIndexes:set(ptrHash, v.run.pickupCounter)
|
|
47
|
-
v.run.currentRoomListIndex = getRoomListIndex(nil)
|
|
48
48
|
end
|
|
49
49
|
function postEntityRemovePickup(self, entity)
|
|
50
50
|
checkDespawningFromPlayerLeavingRoom(nil, entity)
|
|
@@ -55,8 +55,7 @@ function checkDespawningFromPlayerLeavingRoom(self, entity)
|
|
|
55
55
|
if pickupIndex == nil then
|
|
56
56
|
return
|
|
57
57
|
end
|
|
58
|
-
|
|
59
|
-
if roomListIndex == v.run.currentRoomListIndex then
|
|
58
|
+
if not isLeavingRoom(nil) then
|
|
60
59
|
return
|
|
61
60
|
end
|
|
62
61
|
trackDespawningPickupMetadata(nil, entity, pickupIndex)
|
|
@@ -157,7 +156,6 @@ local FEATURE_NAME = "pickupIndex"
|
|
|
157
156
|
v = {
|
|
158
157
|
run = {
|
|
159
158
|
pickupCounter = 0,
|
|
160
|
-
currentRoomListIndex = 0,
|
|
161
159
|
pickupDataTreasureRooms = __TS__New(Map),
|
|
162
160
|
pickupDataBossRooms = __TS__New(Map)
|
|
163
161
|
},
|
|
@@ -15,10 +15,17 @@ export declare function getPreviousRoomDescription(): RoomDescription;
|
|
|
15
15
|
* Helper function to get information about the most recent room that is stored in the room history
|
|
16
16
|
* array.
|
|
17
17
|
*
|
|
18
|
-
* This is useful in the `POST_ENTITY_REMOVE` callback
|
|
19
|
-
* player having left the room, the current room will have changed already, but the `POST_NEW_ROOM`
|
|
20
|
-
* callback will not have fired yet, and there will not be an entry in the room history array for
|
|
21
|
-
* the current room.
|
|
18
|
+
* This is useful in the `POST_ENTITY_REMOVE` callback; see the `isLeavingRoom` function.
|
|
22
19
|
*/
|
|
23
20
|
export declare function getLatestRoomDescription(): RoomDescription;
|
|
21
|
+
/**
|
|
22
|
+
* Helper function to detect if the game is in the state where the room index has changed to a new
|
|
23
|
+
* room, but the entities from the previous room are currently in the process of despawning. (At
|
|
24
|
+
* this point, the `POST_NEW_ROOM` callback will not have fired yet, and there will not be an entry
|
|
25
|
+
* in the room history array for the current room.)
|
|
26
|
+
*
|
|
27
|
+
* This function is intended to be used in the `POST_ENTITY_REMOVE` callback to detect when an
|
|
28
|
+
* entity is pseudo-persistent entity such as a pickup is despawning.
|
|
29
|
+
*/
|
|
30
|
+
export declare function isLeavingRoom(): boolean;
|
|
24
31
|
//# sourceMappingURL=roomHistory.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"roomHistory.d.ts","sourceRoot":"","sources":["../../src/features/roomHistory.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"roomHistory.d.ts","sourceRoot":"","sources":["../../src/features/roomHistory.ts"],"names":[],"mappings":"AAcA,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAmDhE;;;GAGG;AACH,wBAAgB,cAAc,IAAI,SAAS,eAAe,EAAE,CAG3D;AAED;;;;;GAKG;AACH,wBAAgB,0BAA0B,IAAI,eAAe,CAe5D;AAED;;;;;GAKG;AACH,wBAAgB,wBAAwB,IAAI,eAAe,CAS1D;AAED;;;;;;;;GAQG;AACH,wBAAgB,aAAa,IAAI,OAAO,CASvC"}
|
|
@@ -15,6 +15,7 @@ local getRoomName = ____roomData.getRoomName
|
|
|
15
15
|
local getRoomStageID = ____roomData.getRoomStageID
|
|
16
16
|
local getRoomSubType = ____roomData.getRoomSubType
|
|
17
17
|
local getRoomVariant = ____roomData.getRoomVariant
|
|
18
|
+
local getRoomVisitedCount = ____roomData.getRoomVisitedCount
|
|
18
19
|
local ____exports = require("features.saveDataManager.exports")
|
|
19
20
|
local saveDataManager = ____exports.saveDataManager
|
|
20
21
|
function postNewRoomEarly(self)
|
|
@@ -29,6 +30,7 @@ function postNewRoomEarly(self)
|
|
|
29
30
|
local roomName = getRoomName(nil)
|
|
30
31
|
local roomGridIndex = getRoomGridIndex(nil)
|
|
31
32
|
local roomListIndex = getRoomListIndex(nil)
|
|
33
|
+
local roomVisitedCount = getRoomVisitedCount(nil)
|
|
32
34
|
local roomDescription = {
|
|
33
35
|
stage = stage,
|
|
34
36
|
stageType = stageType,
|
|
@@ -38,7 +40,8 @@ function postNewRoomEarly(self)
|
|
|
38
40
|
roomSubType = roomSubType,
|
|
39
41
|
roomName = roomName,
|
|
40
42
|
roomGridIndex = roomGridIndex,
|
|
41
|
-
roomListIndex = roomListIndex
|
|
43
|
+
roomListIndex = roomListIndex,
|
|
44
|
+
roomVisitedCount = roomVisitedCount
|
|
42
45
|
}
|
|
43
46
|
local ____v_run_roomHistory_0 = v.run.roomHistory
|
|
44
47
|
____v_run_roomHistory_0[#____v_run_roomHistory_0 + 1] = roomDescription
|
|
@@ -75,10 +78,7 @@ end
|
|
|
75
78
|
--- Helper function to get information about the most recent room that is stored in the room history
|
|
76
79
|
-- array.
|
|
77
80
|
--
|
|
78
|
-
-- This is useful in the `POST_ENTITY_REMOVE` callback
|
|
79
|
-
-- player having left the room, the current room will have changed already, but the `POST_NEW_ROOM`
|
|
80
|
-
-- callback will not have fired yet, and there will not be an entry in the room history array for
|
|
81
|
-
-- the current room.
|
|
81
|
+
-- This is useful in the `POST_ENTITY_REMOVE` callback; see the `isLeavingRoom` function.
|
|
82
82
|
function ____exports.getLatestRoomDescription(self)
|
|
83
83
|
local latestRoomDescription = getLastElement(nil, v.run.roomHistory)
|
|
84
84
|
if latestRoomDescription == nil then
|
|
@@ -86,4 +86,17 @@ function ____exports.getLatestRoomDescription(self)
|
|
|
86
86
|
end
|
|
87
87
|
return latestRoomDescription
|
|
88
88
|
end
|
|
89
|
+
--- Helper function to detect if the game is in the state where the room index has changed to a new
|
|
90
|
+
-- room, but the entities from the previous room are currently in the process of despawning. (At
|
|
91
|
+
-- this point, the `POST_NEW_ROOM` callback will not have fired yet, and there will not be an entry
|
|
92
|
+
-- in the room history array for the current room.)
|
|
93
|
+
--
|
|
94
|
+
-- This function is intended to be used in the `POST_ENTITY_REMOVE` callback to detect when an
|
|
95
|
+
-- entity is pseudo-persistent entity such as a pickup is despawning.
|
|
96
|
+
function ____exports.isLeavingRoom(self)
|
|
97
|
+
local roomListIndex = getRoomListIndex(nil)
|
|
98
|
+
local roomVisitedCount = getRoomVisitedCount(nil)
|
|
99
|
+
local latestRoomDescription = ____exports.getLatestRoomDescription(nil)
|
|
100
|
+
return roomListIndex ~= latestRoomDescription.roomListIndex or roomVisitedCount ~= latestRoomDescription.roomVisitedCount
|
|
101
|
+
end
|
|
89
102
|
return ____exports
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"log.d.ts","sourceRoot":"","sources":["../../src/functions/log.ts"],"names":[],"mappings":";AAAA,OAAO,EACL,UAAU,EAEV,UAAU,EACV,UAAU,EAEV,cAAc,
|
|
1
|
+
{"version":3,"file":"log.d.ts","sourceRoot":"","sources":["../../src/functions/log.ts"],"names":[],"mappings":"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"}
|
package/dist/functions/log.lua
CHANGED
|
@@ -16,6 +16,7 @@ local EntityFlag = ____isaac_2Dtypescript_2Ddefinitions.EntityFlag
|
|
|
16
16
|
local GameStateFlag = ____isaac_2Dtypescript_2Ddefinitions.GameStateFlag
|
|
17
17
|
local GridEntityType = ____isaac_2Dtypescript_2Ddefinitions.GridEntityType
|
|
18
18
|
local GridRoom = ____isaac_2Dtypescript_2Ddefinitions.GridRoom
|
|
19
|
+
local HeartSubType = ____isaac_2Dtypescript_2Ddefinitions.HeartSubType
|
|
19
20
|
local LevelStateFlag = ____isaac_2Dtypescript_2Ddefinitions.LevelStateFlag
|
|
20
21
|
local ProjectileFlag = ____isaac_2Dtypescript_2Ddefinitions.ProjectileFlag
|
|
21
22
|
local SeedEffect = ____isaac_2Dtypescript_2Ddefinitions.SeedEffect
|
|
@@ -430,7 +431,11 @@ function ____exports.logPlayerHealth(player)
|
|
|
430
431
|
____exports.log(" Broken hearts: " .. tostring(playerHealth.brokenHearts))
|
|
431
432
|
____exports.log(" Soul charges: " .. tostring(playerHealth.soulCharges))
|
|
432
433
|
____exports.log(" Blood charges: " .. tostring(playerHealth.bloodCharges))
|
|
433
|
-
____exports.log(
|
|
434
|
+
____exports.log(" Soul heart types: [")
|
|
435
|
+
for ____, soulHeartType in ipairs(playerHealth.soulHeartTypes) do
|
|
436
|
+
____exports.log(" HeartSubType." .. tostring(HeartSubType[soulHeartType]))
|
|
437
|
+
end
|
|
438
|
+
____exports.log(" ]")
|
|
434
439
|
end
|
|
435
440
|
--- Helper function for printing out every projectile flag that is turned on. Useful when debugging.
|
|
436
441
|
function ____exports.logProjectileFlags(flags)
|
package/dist/functions/npcs.d.ts
CHANGED
|
@@ -19,6 +19,15 @@ export declare function getAliveNPCs(entityType?: EntityType, variant?: number,
|
|
|
19
19
|
* not actually keep the doors closed (like Death's scythes).
|
|
20
20
|
*/
|
|
21
21
|
export declare function isAliveExceptionNPC(npc: EntityNPC): boolean;
|
|
22
|
+
/**
|
|
23
|
+
* Helper function to distinguish between a normal Daddy Long Legs / Triachnid and the child entity
|
|
24
|
+
* that is spawned when the boss does the multi-stomp attack.
|
|
25
|
+
*
|
|
26
|
+
* When this attack occurs, four extra copies of Daddy Long Legs will be spawned with the same
|
|
27
|
+
* entity type, variant, and sub-type. The `Entity.Parent` property will be undefined in this case,
|
|
28
|
+
* so the way to tell them apart is to check for a non-undefined `Entity.SpawnerEntity` property.
|
|
29
|
+
*/
|
|
30
|
+
export declare function isDaddyLongLegsChildStompEntity(npc: EntityNPC): boolean;
|
|
22
31
|
/**
|
|
23
32
|
* Helper function to detect the custom death state of an Eggy. Eggies are never actually marked
|
|
24
33
|
* dead by the game. Instead, when Eggies take fatal damage, they go into NpcState.STATE_SUICIDE and
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"npcs.d.ts","sourceRoot":"","sources":["../../src/functions/npcs.ts"],"names":[],"mappings":"AAAA,OAAO,EAOL,UAAU,
|
|
1
|
+
{"version":3,"file":"npcs.d.ts","sourceRoot":"","sources":["../../src/functions/npcs.ts"],"names":[],"mappings":"AAAA,OAAO,EAOL,UAAU,EASX,MAAM,8BAA8B,CAAC;AA+BtC;;;;;;;;;;;;;GAaG;AACH,wBAAgB,YAAY,CAC1B,UAAU,GAAE,UAAe,EAC3B,OAAO,SAAK,EACZ,OAAO,SAAK,EACZ,cAAc,UAAQ,GACrB,SAAS,EAAE,CAGb;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,SAAS,GAAG,OAAO,CA4B3D;AAED;;;;;;;GAOG;AACH,wBAAgB,+BAA+B,CAAC,GAAG,EAAE,SAAS,GAAG,OAAO,CAIvE;AAED;;;;GAIG;AACH,wBAAgB,4BAA4B,CAAC,GAAG,EAAE,SAAS,GAAG,OAAO,CAOpE;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,SAAS,GAAG,OAAO,CAO3D"}
|
package/dist/functions/npcs.lua
CHANGED
|
@@ -12,6 +12,7 @@ local ChargerVariant = ____isaac_2Dtypescript_2Ddefinitions.ChargerVariant
|
|
|
12
12
|
local DarkEsauVariant = ____isaac_2Dtypescript_2Ddefinitions.DarkEsauVariant
|
|
13
13
|
local DeathVariant = ____isaac_2Dtypescript_2Ddefinitions.DeathVariant
|
|
14
14
|
local EntityType = ____isaac_2Dtypescript_2Ddefinitions.EntityType
|
|
15
|
+
local HopperVariant = ____isaac_2Dtypescript_2Ddefinitions.HopperVariant
|
|
15
16
|
local MamaGurdyVariant = ____isaac_2Dtypescript_2Ddefinitions.MamaGurdyVariant
|
|
16
17
|
local MotherSubType = ____isaac_2Dtypescript_2Ddefinitions.MotherSubType
|
|
17
18
|
local MotherVariant = ____isaac_2Dtypescript_2Ddefinitions.MotherVariant
|
|
@@ -34,19 +35,31 @@ function ____exports.isAliveExceptionNPC(self, npc)
|
|
|
34
35
|
if NON_ALIVE_NPCS_TYPE_VARIANT_SUBTYPE:has(entityTypeVariantSubType) then
|
|
35
36
|
return true
|
|
36
37
|
end
|
|
37
|
-
if ____exports.
|
|
38
|
+
if ____exports.isDyingEggyWithNoSpidersLeft(nil, npc) then
|
|
38
39
|
return true
|
|
39
40
|
end
|
|
40
|
-
if ____exports.
|
|
41
|
+
if ____exports.isDaddyLongLegsChildStompEntity(nil, npc) then
|
|
42
|
+
return true
|
|
43
|
+
end
|
|
44
|
+
if ____exports.isRaglingDeathPatch(nil, npc) then
|
|
41
45
|
return true
|
|
42
46
|
end
|
|
43
47
|
return false
|
|
44
48
|
end
|
|
49
|
+
--- Helper function to distinguish between a normal Daddy Long Legs / Triachnid and the child entity
|
|
50
|
+
-- that is spawned when the boss does the multi-stomp attack.
|
|
51
|
+
--
|
|
52
|
+
-- When this attack occurs, four extra copies of Daddy Long Legs will be spawned with the same
|
|
53
|
+
-- entity type, variant, and sub-type. The `Entity.Parent` property will be undefined in this case,
|
|
54
|
+
-- so the way to tell them apart is to check for a non-undefined `Entity.SpawnerEntity` property.
|
|
55
|
+
function ____exports.isDaddyLongLegsChildStompEntity(self, npc)
|
|
56
|
+
return npc.Type == EntityType.DADDY_LONG_LEGS and npc.SpawnerEntity ~= nil
|
|
57
|
+
end
|
|
45
58
|
--- Helper function to detect the custom death state of an Eggy. Eggies are never actually marked
|
|
46
59
|
-- dead by the game. Instead, when Eggies take fatal damage, they go into NpcState.STATE_SUICIDE and
|
|
47
60
|
-- spawn 14 Swarm Spiders while their StateFrame ticks upwards.
|
|
48
61
|
function ____exports.isDyingEggyWithNoSpidersLeft(self, npc)
|
|
49
|
-
return npc.State == NpcState.SUICIDE and npc.StateFrame >= EGGY_STATE_FRAME_OF_FINAL_SPIDER
|
|
62
|
+
return npc.Type == EntityType.HOPPER and npc.Variant == HopperVariant.EGGY and npc.State == NpcState.SUICIDE and npc.StateFrame >= EGGY_STATE_FRAME_OF_FINAL_SPIDER
|
|
50
63
|
end
|
|
51
64
|
--- Helper function to detect the custom death state of a Rag Man Ragling. When Rag Man Raglings die,
|
|
52
65
|
-- they turn into a patch on the ground and can be revived by Rag Man at a later time. This causes
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"playerHealth.d.ts","sourceRoot":"","sources":["../../src/functions/playerHealth.ts"],"names":[],"mappings":";;AAOA,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACjD,OAAO,EAAE,YAAY,
|
|
1
|
+
{"version":3,"file":"playerHealth.d.ts","sourceRoot":"","sources":["../../src/functions/playerHealth.ts"],"names":[],"mappings":";;AAOA,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACjD,OAAO,EAAE,YAAY,EAAiB,MAAM,4BAA4B,CAAC;AAWzE,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,YAAY,EACpB,UAAU,EAAE,UAAU,EACtB,SAAS,EAAE,GAAG,GACb,IAAI,CA+CN;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,YAAY,GAAG,YAAY,CA2ElE;AAED,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,YAAY,EACpB,UAAU,EAAE,UAAU,GACrB,GAAG,CAmDL;AAED,mDAAmD;AACnD,wBAAgB,eAAe,IAAI,YAAY,CAc9C;AAED,wBAAgB,oCAAoC,CAClD,MAAM,EAAE,YAAY,GACnB,IAAI,CAQN;AAED,wBAAgB,oCAAoC,CAClD,MAAM,EAAE,YAAY,GACnB,IAAI,CAQN;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAMjE;AAED,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,YAAY,GAAG,IAAI,CAwBhE;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAC7B,MAAM,EAAE,YAAY,EACpB,YAAY,EAAE,YAAY,GACzB,IAAI,CAyGN"}
|
|
@@ -69,21 +69,38 @@ function ____exports.setPlayerHealth(self, player, playerHealth)
|
|
|
69
69
|
local soulHeartsRemaining = playerHealth.soulHearts
|
|
70
70
|
__TS__ArrayForEach(
|
|
71
71
|
playerHealth.soulHeartTypes,
|
|
72
|
-
function(____,
|
|
72
|
+
function(____, soulHeartType, i)
|
|
73
73
|
local isHalf = playerHealth.soulHearts + playerHealth.boneHearts * 2 < (i + 1) * 2
|
|
74
74
|
local addAmount = 2
|
|
75
|
-
if isHalf or
|
|
75
|
+
if isHalf or soulHeartType == HeartSubType.BONE or soulHeartsRemaining < 2 then
|
|
76
76
|
addAmount = 1
|
|
77
77
|
end
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
78
|
+
repeat
|
|
79
|
+
local ____switch52 = soulHeartType
|
|
80
|
+
local ____cond52 = ____switch52 == HeartSubType.SOUL
|
|
81
|
+
if ____cond52 then
|
|
82
|
+
do
|
|
83
|
+
player:AddSoulHearts(addAmount)
|
|
84
|
+
soulHeartsRemaining = soulHeartsRemaining - addAmount
|
|
85
|
+
break
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
____cond52 = ____cond52 or ____switch52 == HeartSubType.BLACK
|
|
89
|
+
if ____cond52 then
|
|
90
|
+
do
|
|
91
|
+
player:AddBlackHearts(addAmount)
|
|
92
|
+
soulHeartsRemaining = soulHeartsRemaining - addAmount
|
|
93
|
+
break
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
____cond52 = ____cond52 or ____switch52 == HeartSubType.BONE
|
|
97
|
+
if ____cond52 then
|
|
98
|
+
do
|
|
99
|
+
player:AddBoneHearts(addAmount)
|
|
100
|
+
break
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
until true
|
|
87
104
|
end
|
|
88
105
|
)
|
|
89
106
|
player:AddRottenHearts(playerHealth.rottenHearts)
|
|
@@ -187,7 +204,6 @@ end
|
|
|
187
204
|
-- This is based on the `REVEL.StoreHealth` function in the Revelations mod.
|
|
188
205
|
function ____exports.getPlayerHealth(self, player)
|
|
189
206
|
local character = player:GetPlayerType()
|
|
190
|
-
local soulHeartTypes = {}
|
|
191
207
|
local maxHearts = player:GetMaxHearts()
|
|
192
208
|
local hearts = getPlayerHearts(nil, player)
|
|
193
209
|
local soulHearts = player:GetSoulHearts()
|
|
@@ -209,6 +225,7 @@ function ____exports.getPlayerHealth(self, player)
|
|
|
209
225
|
end
|
|
210
226
|
local extraHearts = math.ceil(soulHearts / 2) + boneHearts
|
|
211
227
|
local currentSoulHeart = 0
|
|
228
|
+
local soulHeartTypes = {}
|
|
212
229
|
do
|
|
213
230
|
local i = 0
|
|
214
231
|
while i < extraHearts do
|
|
@@ -47,11 +47,11 @@ local getRandomVector = ____vector.getRandomVector
|
|
|
47
47
|
function spawnRockAltRewardUrn(self, position, rng)
|
|
48
48
|
local chance = getRandom(nil, rng)
|
|
49
49
|
local totalChance = 0
|
|
50
|
-
totalChance = totalChance + ROCK_ALT_CHANCES.
|
|
50
|
+
totalChance = totalChance + ROCK_ALT_CHANCES.NOTHING
|
|
51
51
|
if chance < totalChance then
|
|
52
52
|
return false
|
|
53
53
|
end
|
|
54
|
-
totalChance = totalChance + ROCK_ALT_CHANCES.
|
|
54
|
+
totalChance = totalChance + ROCK_ALT_CHANCES.BASIC_DROP
|
|
55
55
|
if chance < totalChance then
|
|
56
56
|
local numCoinsChance = getRandom(nil, rng)
|
|
57
57
|
local numCoins = numCoinsChance < 0.5 and 1 or 2
|
|
@@ -73,12 +73,12 @@ function spawnRockAltRewardUrn(self, position, rng)
|
|
|
73
73
|
)
|
|
74
74
|
return true
|
|
75
75
|
end
|
|
76
|
-
totalChance = totalChance + ROCK_ALT_CHANCES.
|
|
76
|
+
totalChance = totalChance + ROCK_ALT_CHANCES.TRINKET
|
|
77
77
|
if chance < totalChance then
|
|
78
78
|
spawnTrinketWithSeed(nil, TrinketType.SWALLOWED_PENNY, position, rng)
|
|
79
79
|
return true
|
|
80
80
|
end
|
|
81
|
-
totalChance = totalChance + ROCK_ALT_CHANCES.
|
|
81
|
+
totalChance = totalChance + ROCK_ALT_CHANCES.COLLECTIBLE
|
|
82
82
|
if chance < totalChance then
|
|
83
83
|
local stillInPools = isCollectibleInItemPool(nil, CollectibleType.QUARTER, ItemPoolType.DEVIL)
|
|
84
84
|
if stillInPools then
|
|
@@ -113,21 +113,21 @@ function spawnRockAltRewardMushroom(self, position, rng)
|
|
|
113
113
|
local roomType = room:GetType()
|
|
114
114
|
local chance = getRandom(nil, rng)
|
|
115
115
|
local totalChance = 0
|
|
116
|
-
totalChance = totalChance + ROCK_ALT_CHANCES.
|
|
116
|
+
totalChance = totalChance + ROCK_ALT_CHANCES.NOTHING
|
|
117
117
|
if chance < totalChance then
|
|
118
118
|
return false
|
|
119
119
|
end
|
|
120
|
-
totalChance = totalChance + ROCK_ALT_CHANCES.
|
|
120
|
+
totalChance = totalChance + ROCK_ALT_CHANCES.BASIC_DROP
|
|
121
121
|
if chance < totalChance then
|
|
122
122
|
spawnPillWithSeed(nil, PillColor.NULL, position, rng)
|
|
123
123
|
return true
|
|
124
124
|
end
|
|
125
|
-
totalChance = totalChance + ROCK_ALT_CHANCES.
|
|
125
|
+
totalChance = totalChance + ROCK_ALT_CHANCES.TRINKET
|
|
126
126
|
if chance < totalChance then
|
|
127
127
|
spawnTrinketWithSeed(nil, TrinketType.LIBERTY_CAP, position, rng)
|
|
128
128
|
return true
|
|
129
129
|
end
|
|
130
|
-
totalChance = totalChance + ROCK_ALT_CHANCES.
|
|
130
|
+
totalChance = totalChance + ROCK_ALT_CHANCES.COLLECTIBLE
|
|
131
131
|
if chance < totalChance then
|
|
132
132
|
if roomType == RoomType.SECRET then
|
|
133
133
|
local wavyCapChance = getRandom(nil, rng)
|
|
@@ -169,21 +169,21 @@ end
|
|
|
169
169
|
function spawnRockAltRewardSkull(self, position, rng)
|
|
170
170
|
local chance = getRandom(nil, rng)
|
|
171
171
|
local totalChance = 0
|
|
172
|
-
totalChance = totalChance + ROCK_ALT_CHANCES.
|
|
172
|
+
totalChance = totalChance + ROCK_ALT_CHANCES.NOTHING
|
|
173
173
|
if chance < totalChance then
|
|
174
174
|
return false
|
|
175
175
|
end
|
|
176
|
-
totalChance = totalChance + ROCK_ALT_CHANCES.
|
|
176
|
+
totalChance = totalChance + ROCK_ALT_CHANCES.BASIC_DROP
|
|
177
177
|
if chance < totalChance then
|
|
178
178
|
spawnCardWithSeed(nil, Card.NULL, position, rng)
|
|
179
179
|
return true
|
|
180
180
|
end
|
|
181
|
-
totalChance = totalChance + ROCK_ALT_CHANCES.
|
|
181
|
+
totalChance = totalChance + ROCK_ALT_CHANCES.TRINKET
|
|
182
182
|
if chance < totalChance then
|
|
183
183
|
spawnHeartWithSeed(nil, HeartSubType.BLACK, position, rng)
|
|
184
184
|
return true
|
|
185
185
|
end
|
|
186
|
-
totalChance = totalChance + ROCK_ALT_CHANCES.
|
|
186
|
+
totalChance = totalChance + ROCK_ALT_CHANCES.COLLECTIBLE
|
|
187
187
|
if chance < totalChance then
|
|
188
188
|
local ghostBabyStillInPools = isCollectibleInItemPool(nil, CollectibleType.GHOST_BABY, ItemPoolType.TREASURE)
|
|
189
189
|
local dryBabyStillInPools = isCollectibleInItemPool(nil, CollectibleType.DRY_BABY, ItemPoolType.TREASURE)
|
|
@@ -216,21 +216,21 @@ end
|
|
|
216
216
|
function spawnRockAltRewardPolyp(self, position, rng)
|
|
217
217
|
local chance = getRandom(nil, rng)
|
|
218
218
|
local totalChance = 0
|
|
219
|
-
totalChance = totalChance + ROCK_ALT_CHANCES.
|
|
219
|
+
totalChance = totalChance + ROCK_ALT_CHANCES.NOTHING
|
|
220
220
|
if chance < totalChance then
|
|
221
221
|
return false
|
|
222
222
|
end
|
|
223
|
-
totalChance = totalChance + ROCK_ALT_CHANCES.
|
|
223
|
+
totalChance = totalChance + ROCK_ALT_CHANCES.BASIC_DROP
|
|
224
224
|
if chance < totalChance then
|
|
225
225
|
spawnHeartWithSeed(nil, HeartSubType.NULL, position, rng)
|
|
226
226
|
return true
|
|
227
227
|
end
|
|
228
|
-
totalChance = totalChance + ROCK_ALT_CHANCES.
|
|
228
|
+
totalChance = totalChance + ROCK_ALT_CHANCES.TRINKET
|
|
229
229
|
if chance < totalChance then
|
|
230
230
|
spawnTrinketWithSeed(nil, TrinketType.UMBILICAL_CORD, position, rng)
|
|
231
231
|
return true
|
|
232
232
|
end
|
|
233
|
-
totalChance = totalChance + ROCK_ALT_CHANCES.
|
|
233
|
+
totalChance = totalChance + ROCK_ALT_CHANCES.COLLECTIBLE
|
|
234
234
|
if chance < totalChance then
|
|
235
235
|
local placentaStillInPools = isCollectibleInItemPool(nil, CollectibleType.PLACENTA, ItemPoolType.BOSS)
|
|
236
236
|
local bloodClotStillInPools = isCollectibleInItemPool(nil, CollectibleType.BLOOD_CLOT, ItemPoolType.BOSS)
|
|
@@ -269,13 +269,13 @@ end
|
|
|
269
269
|
function spawnRockAltRewardBucket(self, _position, rng, _variant)
|
|
270
270
|
local chance = getRandom(nil, rng)
|
|
271
271
|
local totalChance = 0
|
|
272
|
-
totalChance = totalChance + ROCK_ALT_CHANCES.
|
|
272
|
+
totalChance = totalChance + ROCK_ALT_CHANCES.NOTHING
|
|
273
273
|
if chance < totalChance then
|
|
274
274
|
return false
|
|
275
275
|
end
|
|
276
276
|
return false
|
|
277
277
|
end
|
|
278
|
-
ROCK_ALT_CHANCES = {
|
|
278
|
+
ROCK_ALT_CHANCES = {NOTHING = 0.68, BASIC_DROP = 0.0967, TRINKET = 0.025, COLLECTIBLE = 0.005}
|
|
279
279
|
POLYP_PROJECTILE_SPEED = 10
|
|
280
280
|
POLYP_NUM_PROJECTILES = 6
|
|
281
281
|
--- Helper function to get the alternate rock type (i.e. urn, mushroom, etc.) that the current room
|
|
@@ -4,13 +4,16 @@ export interface PlayerHealth {
|
|
|
4
4
|
maxHearts: int;
|
|
5
5
|
hearts: int;
|
|
6
6
|
eternalHearts: int;
|
|
7
|
+
/** For soul hearts to apply, they also have to be specified in the `soulHeartTypes` array. */
|
|
7
8
|
soulHearts: int;
|
|
9
|
+
/** For bone hearts to apply, they also have to be specified in the `soulHeartTypes` array. */
|
|
8
10
|
boneHearts: int;
|
|
9
11
|
goldenHearts: int;
|
|
10
12
|
rottenHearts: int;
|
|
11
13
|
brokenHearts: int;
|
|
12
14
|
soulCharges: int;
|
|
13
15
|
bloodCharges: int;
|
|
14
|
-
soulHeartTypes:
|
|
16
|
+
soulHeartTypes: SoulHeartType[];
|
|
15
17
|
}
|
|
18
|
+
export declare type SoulHeartType = HeartSubType.SOUL | HeartSubType.BLACK | HeartSubType.BONE;
|
|
16
19
|
//# sourceMappingURL=PlayerHealth.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PlayerHealth.d.ts","sourceRoot":"","sources":["../../src/interfaces/PlayerHealth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAE5D,4EAA4E;AAC5E,MAAM,WAAW,YAAY;IAC3B,SAAS,EAAE,GAAG,CAAC;IACf,MAAM,EAAE,GAAG,CAAC;IACZ,aAAa,EAAE,GAAG,CAAC;
|
|
1
|
+
{"version":3,"file":"PlayerHealth.d.ts","sourceRoot":"","sources":["../../src/interfaces/PlayerHealth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAE5D,4EAA4E;AAC5E,MAAM,WAAW,YAAY;IAC3B,SAAS,EAAE,GAAG,CAAC;IACf,MAAM,EAAE,GAAG,CAAC;IACZ,aAAa,EAAE,GAAG,CAAC;IAEnB,8FAA8F;IAC9F,UAAU,EAAE,GAAG,CAAC;IAEhB,8FAA8F;IAC9F,UAAU,EAAE,GAAG,CAAC;IAEhB,YAAY,EAAE,GAAG,CAAC;IAClB,YAAY,EAAE,GAAG,CAAC;IAClB,YAAY,EAAE,GAAG,CAAC;IAClB,WAAW,EAAE,GAAG,CAAC;IACjB,YAAY,EAAE,GAAG,CAAC;IAElB,cAAc,EAAE,aAAa,EAAE,CAAC;CACjC;AAED,oBAAY,aAAa,GACrB,YAAY,CAAC,IAAI,GACjB,YAAY,CAAC,KAAK,GAClB,YAAY,CAAC,IAAI,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RoomDescription.d.ts","sourceRoot":"","sources":["../../src/interfaces/RoomDescription.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,UAAU,EACV,QAAQ,EACR,OAAO,EACP,SAAS,EACV,MAAM,8BAA8B,CAAC;AAEtC,wCAAwC;AACxC,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,UAAU,CAAC;IAClB,SAAS,EAAE,SAAS,CAAC;IACrB,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,QAAQ,CAAC;IACnB,WAAW,EAAE,GAAG,CAAC;IACjB,WAAW,EAAE,GAAG,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,GAAG,CAAC;IACnB,aAAa,EAAE,GAAG,CAAC;
|
|
1
|
+
{"version":3,"file":"RoomDescription.d.ts","sourceRoot":"","sources":["../../src/interfaces/RoomDescription.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,UAAU,EACV,QAAQ,EACR,OAAO,EACP,SAAS,EACV,MAAM,8BAA8B,CAAC;AAEtC,wCAAwC;AACxC,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,UAAU,CAAC;IAClB,SAAS,EAAE,SAAS,CAAC;IACrB,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,QAAQ,CAAC;IACnB,WAAW,EAAE,GAAG,CAAC;IACjB,WAAW,EAAE,GAAG,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,GAAG,CAAC;IACnB,aAAa,EAAE,GAAG,CAAC;IACnB,gBAAgB,EAAE,GAAG,CAAC;CACvB"}
|
package/package.json
CHANGED
|
@@ -8,7 +8,7 @@ import { ModCallbackCustom } from "../enums/ModCallbackCustom";
|
|
|
8
8
|
import { errorIfFeaturesNotInitialized } from "../featuresInitialized";
|
|
9
9
|
import { spawn } from "../functions/entities";
|
|
10
10
|
import { getRoomListIndex } from "../functions/roomData";
|
|
11
|
-
import { getLatestRoomDescription } from "./roomHistory";
|
|
11
|
+
import { getLatestRoomDescription, isLeavingRoom } from "./roomHistory";
|
|
12
12
|
import { saveDataManager } from "./saveDataManager/exports";
|
|
13
13
|
|
|
14
14
|
interface PersistentEntityDescription {
|
|
@@ -56,6 +56,10 @@ export function persistentEntitiesInit(mod: ModUpgraded): void {
|
|
|
56
56
|
|
|
57
57
|
// ModCallback.POST_ENTITY_REMOVE (67)
|
|
58
58
|
function postEntityRemove(entity: Entity) {
|
|
59
|
+
checkDespawningFromPlayerLeavingRoom(entity);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function checkDespawningFromPlayerLeavingRoom(entity: Entity) {
|
|
59
63
|
const ptrHash = GetPtrHash(entity);
|
|
60
64
|
const tuple = v.room.spawnedPersistentEntities.get(ptrHash);
|
|
61
65
|
if (tuple === undefined) {
|
|
@@ -63,10 +67,20 @@ function postEntityRemove(entity: Entity) {
|
|
|
63
67
|
}
|
|
64
68
|
const index = tuple[0];
|
|
65
69
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
+
if (!isLeavingRoom()) {
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
trackDespawningPickupPosition(entity, index);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* The persistent entity is despawning because the player is in the process of leaving the room.
|
|
79
|
+
* Keep track of the position for later.
|
|
80
|
+
*/
|
|
81
|
+
function trackDespawningPickupPosition(entity: Entity, index: int) {
|
|
82
|
+
// (The "latest" room description is really the previous room, because the `POST_NEW_ROOM`
|
|
83
|
+
// callback was not fired yet.)
|
|
70
84
|
const previousRoomDescription = getLatestRoomDescription();
|
|
71
85
|
const previousRoomListIndex = previousRoomDescription.roomListIndex;
|
|
72
86
|
const persistentEntityDescription: PersistentEntityDescription = {
|
|
@@ -14,7 +14,7 @@ import { getRoomListIndex } from "../functions/roomData";
|
|
|
14
14
|
import { onAscent } from "../functions/stage";
|
|
15
15
|
import { vectorEquals } from "../functions/vector";
|
|
16
16
|
import { PickupIndex } from "../types/PickupIndex";
|
|
17
|
-
import { getLatestRoomDescription } from "./roomHistory";
|
|
17
|
+
import { getLatestRoomDescription, isLeavingRoom } from "./roomHistory";
|
|
18
18
|
import { saveDataManager } from "./saveDataManager/exports";
|
|
19
19
|
|
|
20
20
|
interface PickupDescription {
|
|
@@ -27,7 +27,6 @@ const FEATURE_NAME = "pickupIndex";
|
|
|
27
27
|
const v = {
|
|
28
28
|
run: {
|
|
29
29
|
pickupCounter: 0 as PickupIndex,
|
|
30
|
-
currentRoomListIndex: 0,
|
|
31
30
|
|
|
32
31
|
pickupDataTreasureRooms: new Map<PickupIndex, PickupDescription>(),
|
|
33
32
|
pickupDataBossRooms: new Map<PickupIndex, PickupDescription>(),
|
|
@@ -81,9 +80,6 @@ function postPickupInit(pickup: EntityPickup) {
|
|
|
81
80
|
|
|
82
81
|
v.run.pickupCounter++;
|
|
83
82
|
v.room.pickupIndexes.set(ptrHash, v.run.pickupCounter);
|
|
84
|
-
|
|
85
|
-
// Additionally, keep track of which room we are storing the pointer hashes for.
|
|
86
|
-
v.run.currentRoomListIndex = getRoomListIndex();
|
|
87
83
|
}
|
|
88
84
|
|
|
89
85
|
// ModCallback.POST_ENTITY_REMOVE (67)
|
|
@@ -99,10 +95,7 @@ function checkDespawningFromPlayerLeavingRoom(entity: Entity) {
|
|
|
99
95
|
return;
|
|
100
96
|
}
|
|
101
97
|
|
|
102
|
-
|
|
103
|
-
if (roomListIndex === v.run.currentRoomListIndex) {
|
|
104
|
-
// This is a pickup that is despawning in the current room. For example, it could be a heart
|
|
105
|
-
// pickup that the player picked up. Thus, we do not need to keep track of it's metadata.
|
|
98
|
+
if (!isLeavingRoom()) {
|
|
106
99
|
return;
|
|
107
100
|
}
|
|
108
101
|
|
|
@@ -111,13 +104,14 @@ function checkDespawningFromPlayerLeavingRoom(entity: Entity) {
|
|
|
111
104
|
|
|
112
105
|
/**
|
|
113
106
|
* This is a pickup that is despawning because the player is in the process of leaving the room.
|
|
114
|
-
* Keep track of the metadata for later.
|
|
115
|
-
* though the `POST_NEW_ROOM` callback was not fired yet, we have already traveled to the next room.
|
|
107
|
+
* Keep track of the metadata for later.
|
|
116
108
|
*/
|
|
117
109
|
function trackDespawningPickupMetadata(
|
|
118
110
|
entity: Entity,
|
|
119
111
|
pickupIndex: PickupIndex,
|
|
120
112
|
) {
|
|
113
|
+
// The "latest" room description is really the previous room, because the `POST_NEW_ROOM` callback
|
|
114
|
+
// was not fired yet.
|
|
121
115
|
const previousRoomDescription = getLatestRoomDescription();
|
|
122
116
|
const previousRoomListIndex = previousRoomDescription.roomListIndex;
|
|
123
117
|
const pickupDescriptions = v.level.pickupData.getAndSetDefault(
|
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
getRoomStageID,
|
|
11
11
|
getRoomSubType,
|
|
12
12
|
getRoomVariant,
|
|
13
|
+
getRoomVisitedCount,
|
|
13
14
|
} from "../functions/roomData";
|
|
14
15
|
import { RoomDescription } from "../interfaces/RoomDescription";
|
|
15
16
|
import { saveDataManager } from "./saveDataManager/exports";
|
|
@@ -45,6 +46,7 @@ function postNewRoomEarly() {
|
|
|
45
46
|
const roomName = getRoomName();
|
|
46
47
|
const roomGridIndex = getRoomGridIndex();
|
|
47
48
|
const roomListIndex = getRoomListIndex();
|
|
49
|
+
const roomVisitedCount = getRoomVisitedCount();
|
|
48
50
|
|
|
49
51
|
const roomDescription: RoomDescription = {
|
|
50
52
|
stage,
|
|
@@ -56,6 +58,7 @@ function postNewRoomEarly() {
|
|
|
56
58
|
roomName,
|
|
57
59
|
roomGridIndex,
|
|
58
60
|
roomListIndex,
|
|
61
|
+
roomVisitedCount,
|
|
59
62
|
};
|
|
60
63
|
v.run.roomHistory.push(roomDescription);
|
|
61
64
|
}
|
|
@@ -96,10 +99,7 @@ export function getPreviousRoomDescription(): RoomDescription {
|
|
|
96
99
|
* Helper function to get information about the most recent room that is stored in the room history
|
|
97
100
|
* array.
|
|
98
101
|
*
|
|
99
|
-
* This is useful in the `POST_ENTITY_REMOVE` callback
|
|
100
|
-
* player having left the room, the current room will have changed already, but the `POST_NEW_ROOM`
|
|
101
|
-
* callback will not have fired yet, and there will not be an entry in the room history array for
|
|
102
|
-
* the current room.
|
|
102
|
+
* This is useful in the `POST_ENTITY_REMOVE` callback; see the `isLeavingRoom` function.
|
|
103
103
|
*/
|
|
104
104
|
export function getLatestRoomDescription(): RoomDescription {
|
|
105
105
|
const latestRoomDescription = getLastElement(v.run.roomHistory);
|
|
@@ -111,3 +111,23 @@ export function getLatestRoomDescription(): RoomDescription {
|
|
|
111
111
|
|
|
112
112
|
return latestRoomDescription;
|
|
113
113
|
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Helper function to detect if the game is in the state where the room index has changed to a new
|
|
117
|
+
* room, but the entities from the previous room are currently in the process of despawning. (At
|
|
118
|
+
* this point, the `POST_NEW_ROOM` callback will not have fired yet, and there will not be an entry
|
|
119
|
+
* in the room history array for the current room.)
|
|
120
|
+
*
|
|
121
|
+
* This function is intended to be used in the `POST_ENTITY_REMOVE` callback to detect when an
|
|
122
|
+
* entity is pseudo-persistent entity such as a pickup is despawning.
|
|
123
|
+
*/
|
|
124
|
+
export function isLeavingRoom(): boolean {
|
|
125
|
+
const roomListIndex = getRoomListIndex();
|
|
126
|
+
const roomVisitedCount = getRoomVisitedCount();
|
|
127
|
+
const latestRoomDescription = getLatestRoomDescription();
|
|
128
|
+
|
|
129
|
+
return (
|
|
130
|
+
roomListIndex !== latestRoomDescription.roomListIndex ||
|
|
131
|
+
roomVisitedCount !== latestRoomDescription.roomVisitedCount
|
|
132
|
+
);
|
|
133
|
+
}
|
package/src/functions/log.ts
CHANGED
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
GameStateFlag,
|
|
7
7
|
GridEntityType,
|
|
8
8
|
GridRoom,
|
|
9
|
+
HeartSubType,
|
|
9
10
|
LevelStateFlag,
|
|
10
11
|
ProjectileFlag,
|
|
11
12
|
SeedEffect,
|
|
@@ -519,7 +520,11 @@ export function logPlayerHealth(this: void, player: EntityPlayer): void {
|
|
|
519
520
|
log(` Broken hearts: ${playerHealth.brokenHearts}`);
|
|
520
521
|
log(` Soul charges: ${playerHealth.soulCharges}`);
|
|
521
522
|
log(` Blood charges: ${playerHealth.bloodCharges}`);
|
|
522
|
-
log(
|
|
523
|
+
log(" Soul heart types: [");
|
|
524
|
+
for (const soulHeartType of playerHealth.soulHeartTypes) {
|
|
525
|
+
log(` HeartSubType.${HeartSubType[soulHeartType]}`);
|
|
526
|
+
}
|
|
527
|
+
log(" ]");
|
|
523
528
|
}
|
|
524
529
|
|
|
525
530
|
/**
|
package/src/functions/npcs.ts
CHANGED
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
DarkEsauVariant,
|
|
7
7
|
DeathVariant,
|
|
8
8
|
EntityType,
|
|
9
|
+
HopperVariant,
|
|
9
10
|
MamaGurdyVariant,
|
|
10
11
|
MotherSubType,
|
|
11
12
|
MotherVariant,
|
|
@@ -83,17 +84,39 @@ export function isAliveExceptionNPC(npc: EntityNPC): boolean {
|
|
|
83
84
|
return true;
|
|
84
85
|
}
|
|
85
86
|
|
|
86
|
-
|
|
87
|
+
// EntityType.HOPPER (29)
|
|
88
|
+
// HopperVariant.EGGY (2)
|
|
89
|
+
if (isDyingEggyWithNoSpidersLeft(npc)) {
|
|
87
90
|
return true;
|
|
88
91
|
}
|
|
89
92
|
|
|
90
|
-
|
|
93
|
+
// EntityType.DADDY_LONG_LEGS (101)
|
|
94
|
+
if (isDaddyLongLegsChildStompEntity(npc)) {
|
|
95
|
+
return true;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// EntityType.RAGLING (256)
|
|
99
|
+
if (isRaglingDeathPatch(npc)) {
|
|
91
100
|
return true;
|
|
92
101
|
}
|
|
93
102
|
|
|
94
103
|
return false;
|
|
95
104
|
}
|
|
96
105
|
|
|
106
|
+
/**
|
|
107
|
+
* Helper function to distinguish between a normal Daddy Long Legs / Triachnid and the child entity
|
|
108
|
+
* that is spawned when the boss does the multi-stomp attack.
|
|
109
|
+
*
|
|
110
|
+
* When this attack occurs, four extra copies of Daddy Long Legs will be spawned with the same
|
|
111
|
+
* entity type, variant, and sub-type. The `Entity.Parent` property will be undefined in this case,
|
|
112
|
+
* so the way to tell them apart is to check for a non-undefined `Entity.SpawnerEntity` property.
|
|
113
|
+
*/
|
|
114
|
+
export function isDaddyLongLegsChildStompEntity(npc: EntityNPC): boolean {
|
|
115
|
+
return (
|
|
116
|
+
npc.Type === EntityType.DADDY_LONG_LEGS && npc.SpawnerEntity !== undefined
|
|
117
|
+
);
|
|
118
|
+
}
|
|
119
|
+
|
|
97
120
|
/**
|
|
98
121
|
* Helper function to detect the custom death state of an Eggy. Eggies are never actually marked
|
|
99
122
|
* dead by the game. Instead, when Eggies take fatal damage, they go into NpcState.STATE_SUICIDE and
|
|
@@ -101,6 +124,8 @@ export function isAliveExceptionNPC(npc: EntityNPC): boolean {
|
|
|
101
124
|
*/
|
|
102
125
|
export function isDyingEggyWithNoSpidersLeft(npc: EntityNPC): boolean {
|
|
103
126
|
return (
|
|
127
|
+
npc.Type === EntityType.HOPPER &&
|
|
128
|
+
npc.Variant === (HopperVariant.EGGY as int) &&
|
|
104
129
|
npc.State === NpcState.SUICIDE &&
|
|
105
130
|
npc.StateFrame >= EGGY_STATE_FRAME_OF_FINAL_SPIDER
|
|
106
131
|
);
|
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
} from "isaac-typescript-definitions";
|
|
7
7
|
import { MAX_PLAYER_HEART_CONTAINERS } from "../constants";
|
|
8
8
|
import { HealthType } from "../enums/HealthType";
|
|
9
|
-
import { PlayerHealth } from "../interfaces/PlayerHealth";
|
|
9
|
+
import { PlayerHealth, SoulHeartType } from "../interfaces/PlayerHealth";
|
|
10
10
|
import { getTotalCharge } from "./charge";
|
|
11
11
|
import { getEnumValues } from "./enums";
|
|
12
12
|
import {
|
|
@@ -79,7 +79,6 @@ export function addPlayerHealthType(
|
|
|
79
79
|
*/
|
|
80
80
|
export function getPlayerHealth(player: EntityPlayer): PlayerHealth {
|
|
81
81
|
const character = player.GetPlayerType();
|
|
82
|
-
const soulHeartTypes: HeartSubType[] = [];
|
|
83
82
|
let maxHearts = player.GetMaxHearts();
|
|
84
83
|
let hearts = getPlayerHearts(player); // We use the helper function to remove rotten hearts
|
|
85
84
|
let soulHearts = player.GetSoulHearts();
|
|
@@ -115,6 +114,7 @@ export function getPlayerHealth(player: EntityPlayer): PlayerHealth {
|
|
|
115
114
|
// track which soul heart we're currently at.
|
|
116
115
|
let currentSoulHeart = 0;
|
|
117
116
|
|
|
117
|
+
const soulHeartTypes: SoulHeartType[] = [];
|
|
118
118
|
for (let i = 0; i < extraHearts; i++) {
|
|
119
119
|
let isBoneHeart = player.IsBoneHeart(i);
|
|
120
120
|
if (character === PlayerType.THE_FORGOTTEN && subPlayer !== undefined) {
|
|
@@ -333,24 +333,37 @@ export function setPlayerHealth(
|
|
|
333
333
|
|
|
334
334
|
// Add the soul / black / bone hearts.
|
|
335
335
|
let soulHeartsRemaining = playerHealth.soulHearts;
|
|
336
|
-
playerHealth.soulHeartTypes.forEach((
|
|
336
|
+
playerHealth.soulHeartTypes.forEach((soulHeartType, i) => {
|
|
337
337
|
const isHalf =
|
|
338
338
|
playerHealth.soulHearts + playerHealth.boneHearts * 2 < (i + 1) * 2;
|
|
339
339
|
let addAmount = 2;
|
|
340
|
-
if (
|
|
340
|
+
if (
|
|
341
|
+
isHalf ||
|
|
342
|
+
soulHeartType === HeartSubType.BONE ||
|
|
343
|
+
soulHeartsRemaining < 2
|
|
344
|
+
) {
|
|
341
345
|
// Fix the bug where a half soul heart to the left of a bone heart will be treated as a full
|
|
342
346
|
// soul heart.
|
|
343
347
|
addAmount = 1;
|
|
344
348
|
}
|
|
345
349
|
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
350
|
+
switch (soulHeartType) {
|
|
351
|
+
case HeartSubType.SOUL: {
|
|
352
|
+
player.AddSoulHearts(addAmount);
|
|
353
|
+
soulHeartsRemaining -= addAmount;
|
|
354
|
+
break;
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
case HeartSubType.BLACK: {
|
|
358
|
+
player.AddBlackHearts(addAmount);
|
|
359
|
+
soulHeartsRemaining -= addAmount;
|
|
360
|
+
break;
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
case HeartSubType.BONE: {
|
|
364
|
+
player.AddBoneHearts(addAmount);
|
|
365
|
+
break;
|
|
366
|
+
}
|
|
354
367
|
}
|
|
355
368
|
});
|
|
356
369
|
|
package/src/functions/rockAlt.ts
CHANGED
|
@@ -31,13 +31,13 @@ import { repeat } from "./utils";
|
|
|
31
31
|
import { getRandomVector } from "./vector";
|
|
32
32
|
|
|
33
33
|
const ROCK_ALT_CHANCES = {
|
|
34
|
-
|
|
35
|
-
|
|
34
|
+
NOTHING: 0.68,
|
|
35
|
+
BASIC_DROP: 0.0967,
|
|
36
36
|
|
|
37
37
|
/** Also used for e.g. black hearts from skulls. */
|
|
38
|
-
|
|
38
|
+
TRINKET: 0.025,
|
|
39
39
|
|
|
40
|
-
|
|
40
|
+
COLLECTIBLE: 0.005,
|
|
41
41
|
} as const;
|
|
42
42
|
|
|
43
43
|
const POLYP_PROJECTILE_SPEED = 10;
|
|
@@ -126,12 +126,12 @@ function spawnRockAltRewardUrn(position: Vector, rng: RNG): boolean {
|
|
|
126
126
|
const chance = getRandom(rng);
|
|
127
127
|
let totalChance = 0;
|
|
128
128
|
|
|
129
|
-
totalChance += ROCK_ALT_CHANCES.
|
|
129
|
+
totalChance += ROCK_ALT_CHANCES.NOTHING;
|
|
130
130
|
if (chance < totalChance) {
|
|
131
131
|
return false;
|
|
132
132
|
}
|
|
133
133
|
|
|
134
|
-
totalChance += ROCK_ALT_CHANCES.
|
|
134
|
+
totalChance += ROCK_ALT_CHANCES.BASIC_DROP;
|
|
135
135
|
if (chance < totalChance) {
|
|
136
136
|
const numCoinsChance = getRandom(rng);
|
|
137
137
|
const numCoins = numCoinsChance < 0.5 ? 1 : 2;
|
|
@@ -144,13 +144,13 @@ function spawnRockAltRewardUrn(position: Vector, rng: RNG): boolean {
|
|
|
144
144
|
return true;
|
|
145
145
|
}
|
|
146
146
|
|
|
147
|
-
totalChance += ROCK_ALT_CHANCES.
|
|
147
|
+
totalChance += ROCK_ALT_CHANCES.TRINKET;
|
|
148
148
|
if (chance < totalChance) {
|
|
149
149
|
spawnTrinketWithSeed(TrinketType.SWALLOWED_PENNY, position, rng);
|
|
150
150
|
return true;
|
|
151
151
|
}
|
|
152
152
|
|
|
153
|
-
totalChance += ROCK_ALT_CHANCES.
|
|
153
|
+
totalChance += ROCK_ALT_CHANCES.COLLECTIBLE;
|
|
154
154
|
if (chance < totalChance) {
|
|
155
155
|
const stillInPools = isCollectibleInItemPool(
|
|
156
156
|
CollectibleType.QUARTER,
|
|
@@ -184,24 +184,24 @@ function spawnRockAltRewardMushroom(position: Vector, rng: RNG): boolean {
|
|
|
184
184
|
const chance = getRandom(rng);
|
|
185
185
|
let totalChance = 0;
|
|
186
186
|
|
|
187
|
-
totalChance += ROCK_ALT_CHANCES.
|
|
187
|
+
totalChance += ROCK_ALT_CHANCES.NOTHING;
|
|
188
188
|
if (chance < totalChance) {
|
|
189
189
|
return false;
|
|
190
190
|
}
|
|
191
191
|
|
|
192
|
-
totalChance += ROCK_ALT_CHANCES.
|
|
192
|
+
totalChance += ROCK_ALT_CHANCES.BASIC_DROP;
|
|
193
193
|
if (chance < totalChance) {
|
|
194
194
|
spawnPillWithSeed(PillColor.NULL, position, rng);
|
|
195
195
|
return true;
|
|
196
196
|
}
|
|
197
197
|
|
|
198
|
-
totalChance += ROCK_ALT_CHANCES.
|
|
198
|
+
totalChance += ROCK_ALT_CHANCES.TRINKET;
|
|
199
199
|
if (chance < totalChance) {
|
|
200
200
|
spawnTrinketWithSeed(TrinketType.LIBERTY_CAP, position, rng);
|
|
201
201
|
return true;
|
|
202
202
|
}
|
|
203
203
|
|
|
204
|
-
totalChance += ROCK_ALT_CHANCES.
|
|
204
|
+
totalChance += ROCK_ALT_CHANCES.COLLECTIBLE;
|
|
205
205
|
if (chance < totalChance) {
|
|
206
206
|
if (roomType === RoomType.SECRET) {
|
|
207
207
|
const wavyCapChance = getRandom(rng);
|
|
@@ -257,24 +257,24 @@ function spawnRockAltRewardSkull(position: Vector, rng: RNG): boolean {
|
|
|
257
257
|
const chance = getRandom(rng);
|
|
258
258
|
let totalChance = 0;
|
|
259
259
|
|
|
260
|
-
totalChance += ROCK_ALT_CHANCES.
|
|
260
|
+
totalChance += ROCK_ALT_CHANCES.NOTHING;
|
|
261
261
|
if (chance < totalChance) {
|
|
262
262
|
return false;
|
|
263
263
|
}
|
|
264
264
|
|
|
265
|
-
totalChance += ROCK_ALT_CHANCES.
|
|
265
|
+
totalChance += ROCK_ALT_CHANCES.BASIC_DROP;
|
|
266
266
|
if (chance < totalChance) {
|
|
267
267
|
spawnCardWithSeed(Card.NULL, position, rng);
|
|
268
268
|
return true;
|
|
269
269
|
}
|
|
270
270
|
|
|
271
|
-
totalChance += ROCK_ALT_CHANCES.
|
|
271
|
+
totalChance += ROCK_ALT_CHANCES.TRINKET;
|
|
272
272
|
if (chance < totalChance) {
|
|
273
273
|
spawnHeartWithSeed(HeartSubType.BLACK, position, rng);
|
|
274
274
|
return true;
|
|
275
275
|
}
|
|
276
276
|
|
|
277
|
-
totalChance += ROCK_ALT_CHANCES.
|
|
277
|
+
totalChance += ROCK_ALT_CHANCES.COLLECTIBLE;
|
|
278
278
|
if (chance < totalChance) {
|
|
279
279
|
const ghostBabyStillInPools = isCollectibleInItemPool(
|
|
280
280
|
CollectibleType.GHOST_BABY,
|
|
@@ -316,24 +316,24 @@ function spawnRockAltRewardPolyp(position: Vector, rng: RNG): boolean {
|
|
|
316
316
|
const chance = getRandom(rng);
|
|
317
317
|
let totalChance = 0;
|
|
318
318
|
|
|
319
|
-
totalChance += ROCK_ALT_CHANCES.
|
|
319
|
+
totalChance += ROCK_ALT_CHANCES.NOTHING;
|
|
320
320
|
if (chance < totalChance) {
|
|
321
321
|
return false;
|
|
322
322
|
}
|
|
323
323
|
|
|
324
|
-
totalChance += ROCK_ALT_CHANCES.
|
|
324
|
+
totalChance += ROCK_ALT_CHANCES.BASIC_DROP;
|
|
325
325
|
if (chance < totalChance) {
|
|
326
326
|
spawnHeartWithSeed(HeartSubType.NULL, position, rng);
|
|
327
327
|
return true;
|
|
328
328
|
}
|
|
329
329
|
|
|
330
|
-
totalChance += ROCK_ALT_CHANCES.
|
|
330
|
+
totalChance += ROCK_ALT_CHANCES.TRINKET;
|
|
331
331
|
if (chance < totalChance) {
|
|
332
332
|
spawnTrinketWithSeed(TrinketType.UMBILICAL_CORD, position, rng);
|
|
333
333
|
return true;
|
|
334
334
|
}
|
|
335
335
|
|
|
336
|
-
totalChance += ROCK_ALT_CHANCES.
|
|
336
|
+
totalChance += ROCK_ALT_CHANCES.COLLECTIBLE;
|
|
337
337
|
if (chance < totalChance) {
|
|
338
338
|
const placentaStillInPools = isCollectibleInItemPool(
|
|
339
339
|
CollectibleType.PLACENTA,
|
|
@@ -386,7 +386,7 @@ function spawnRockAltRewardBucket(
|
|
|
386
386
|
const chance = getRandom(rng);
|
|
387
387
|
let totalChance = 0;
|
|
388
388
|
|
|
389
|
-
totalChance += ROCK_ALT_CHANCES.
|
|
389
|
+
totalChance += ROCK_ALT_CHANCES.NOTHING;
|
|
390
390
|
if (chance < totalChance) {
|
|
391
391
|
return false;
|
|
392
392
|
}
|
|
@@ -5,12 +5,23 @@ export interface PlayerHealth {
|
|
|
5
5
|
maxHearts: int;
|
|
6
6
|
hearts: int;
|
|
7
7
|
eternalHearts: int;
|
|
8
|
+
|
|
9
|
+
/** For soul hearts to apply, they also have to be specified in the `soulHeartTypes` array. */
|
|
8
10
|
soulHearts: int;
|
|
11
|
+
|
|
12
|
+
/** For bone hearts to apply, they also have to be specified in the `soulHeartTypes` array. */
|
|
9
13
|
boneHearts: int;
|
|
14
|
+
|
|
10
15
|
goldenHearts: int;
|
|
11
16
|
rottenHearts: int;
|
|
12
17
|
brokenHearts: int;
|
|
13
18
|
soulCharges: int;
|
|
14
19
|
bloodCharges: int;
|
|
15
|
-
|
|
20
|
+
|
|
21
|
+
soulHeartTypes: SoulHeartType[];
|
|
16
22
|
}
|
|
23
|
+
|
|
24
|
+
export type SoulHeartType =
|
|
25
|
+
| HeartSubType.SOUL // 3
|
|
26
|
+
| HeartSubType.BLACK // 6
|
|
27
|
+
| HeartSubType.BONE; // 11
|