Merged in DR v1.4.1.6
This commit is contained in:
@@ -110,7 +110,8 @@ class CustomSettings(object):
|
||||
args.pottery[p] = get_setting(settings['pottery'], args.pottery[p])
|
||||
|
||||
if get_setting(settings['keydropshuffle'], args.keydropshuffle[p]):
|
||||
args.dropshuffle[p] = True
|
||||
if args.dropshuffle[p] == 'none':
|
||||
args.dropshuffle[p] = 'keys'
|
||||
if args.pottery[p] == 'none':
|
||||
args.pottery[p] = 'keys'
|
||||
|
||||
@@ -153,6 +154,7 @@ class CustomSettings(object):
|
||||
args.shuffleenemies[p] = get_setting(settings['enemy_shuffle'], get_setting(settings['shuffleenemies'], args.shuffleenemies[p]))
|
||||
args.enemy_health[p] = get_setting(settings['enemy_health'], args.enemy_health[p])
|
||||
args.enemy_damage[p] = get_setting(settings['enemy_damage'], args.enemy_damage[p])
|
||||
args.any_enemy_logic[p] = get_setting(settings['any_enemy_logic'], args.any_enemy_logic[p])
|
||||
args.shufflepots[p] = get_setting(settings['shufflepots'], args.shufflepots[p])
|
||||
args.bombbag[p] = get_setting(settings['bombbag'], args.bombbag[p])
|
||||
args.shufflelinks[p] = get_setting(settings['shufflelinks'], args.shufflelinks[p])
|
||||
@@ -260,6 +262,11 @@ class CustomSettings(object):
|
||||
return self.file_source['drops']
|
||||
return None
|
||||
|
||||
def get_enemies(self):
|
||||
if 'enemies' in self.file_source:
|
||||
return self.file_source['enemies']
|
||||
return None
|
||||
|
||||
def create_from_world(self, world, settings):
|
||||
self.player_range = range(1, world.players + 1)
|
||||
settings_dict, meta_dict = {}, {}
|
||||
@@ -319,6 +326,7 @@ class CustomSettings(object):
|
||||
settings_dict[p]['enemy_shuffle'] = world.enemy_shuffle[p]
|
||||
settings_dict[p]['enemy_health'] = world.enemy_health[p]
|
||||
settings_dict[p]['enemy_damage'] = world.enemy_damage[p]
|
||||
settings_dict[p]['any_enemy_logic'] = world.any_enemy_logic[p]
|
||||
settings_dict[p]['shufflepots'] = world.potshuffle[p]
|
||||
settings_dict[p]['bombbag'] = world.bombbag[p]
|
||||
settings_dict[p]['shufflelinks'] = world.shufflelinks[p]
|
||||
|
||||
@@ -127,7 +127,8 @@ SETTINGSTOPROCESS = {
|
||||
"enemyshuffle": "shuffleenemies",
|
||||
"bossshuffle": "shufflebosses",
|
||||
"enemydamage": "enemy_damage",
|
||||
"enemyhealth": "enemy_health"
|
||||
"enemyhealth": "enemy_health",
|
||||
"enemylogic": "any_enemy_logic"
|
||||
},
|
||||
"gameoptions": {
|
||||
"nobgm": "disablemusic",
|
||||
|
||||
2676
source/dungeon/EnemyList.py
Normal file
2676
source/dungeon/EnemyList.py
Normal file
File diff suppressed because it is too large
Load Diff
266
source/dungeon/RoomConstants.py
Normal file
266
source/dungeon/RoomConstants.py
Normal file
@@ -0,0 +1,266 @@
|
||||
Ganon = 0x0
|
||||
HC_NorthCorridor = 0x1
|
||||
HC_SwitchRoom = 0x2
|
||||
HoulihanRoom = 0x3
|
||||
TR_CrystalRollerRoom = 0x4
|
||||
Swamp_Arrghus = 0x6
|
||||
Hera_Moldorm = 0x7
|
||||
Cave_HealingFairy = 0x8
|
||||
PalaceofDarkness0x09 = 0x9
|
||||
PoD_StalfosTrapRoom = 0xa
|
||||
PoD_TurtleRoom = 0xb
|
||||
GT_EntranceRoom = 0xc
|
||||
GT_Agahnim2 = 0xd
|
||||
Ice_EntranceRoom = 0xe
|
||||
GanonEvacuationRoute = 0x10
|
||||
HC_BombableStockRoom = 0x11
|
||||
Sanctuary = 0x12
|
||||
TR_Hokku_BokkuKeyRoom2 = 0x13
|
||||
TR_BigKeyRoom = 0x14
|
||||
TurtleRock0x15 = 0x15
|
||||
Swamp_SwimmingTreadmill = 0x16
|
||||
Hera_MoldormFallRoom = 0x17
|
||||
Cave0x18_BigFairyDropEntrance = 0x18
|
||||
PoD_DarkMaze = 0x19
|
||||
PoD_BigChestRoom = 0x1a
|
||||
PoD_Mimics_MovingWallRoom = 0x1b
|
||||
GT_IceArmos = 0x1c
|
||||
GT_FinalHallway = 0x1d
|
||||
Ice_BombFloor_BariRoom = 0x1e
|
||||
Ice_Pengator_BigKeyRoom = 0x1f
|
||||
Tower_Agahnim = 0x20
|
||||
HC_KeyRatRoom = 0x21
|
||||
HC_SewerTextTriggerRoom = 0x22
|
||||
TR_WestExittoBalcony = 0x23
|
||||
TR_DoubleHokku_Bokku_BigchestRoom = 0x24
|
||||
Swamp_StatueRoom = 0x26
|
||||
Hera_BigChest = 0x27
|
||||
Swamp_EntranceRoom = 0x28
|
||||
Skull_Mothula = 0x29
|
||||
PoD_BigHubRoom = 0x2a
|
||||
PoD_MapChest_FairyRoom = 0x2b
|
||||
Cave0x2C_HookshotCaveBackdoor = 0x2c
|
||||
Ice_CompassRoom = 0x2e
|
||||
Cave_KakarikoWellHP = 0x2f
|
||||
Tower_MaidenSacrificeChamber = 0x30
|
||||
Hera_HardhatBeetlesRoom = 0x31
|
||||
HC_SewerKeyChestRoom = 0x32
|
||||
Desert_Lanmolas = 0x33
|
||||
Swamp_PushBlockPuzzle_Pre_BigKeyRoom = 0x34
|
||||
Swamp_BigKey_BSRoom = 0x35
|
||||
Swamp_BigChestRoom = 0x36
|
||||
Swamp_MapChest_WaterFillRoom = 0x37
|
||||
Swamp_KeyPotRoom = 0x38
|
||||
Skull_GibdoKey_MothulaHoleRoom = 0x39
|
||||
PoD_BombableFloorRoom = 0x3a
|
||||
PoD_SpikeBlock_ConveyorRoom = 0x3b
|
||||
Cave0x3C_HookshotCave = 0x3c
|
||||
GT_TorchRoom2 = 0x3d
|
||||
Ice_StalfosKnights_ConveyorHellway = 0x3e
|
||||
Ice_MapChestRoom = 0x3f
|
||||
Tower_FinalBridgeRoom = 0x40
|
||||
HC_FirstDarkRoom = 0x41
|
||||
HC_6RopesRoom = 0x42
|
||||
Desert_TorchPuzzle_MovingWallRoom = 0x43
|
||||
TT_BigChestRoom = 0x44
|
||||
TT_JailCellsRoom = 0x45
|
||||
Swamp_CompassChestRoom = 0x46
|
||||
Skull_GibdoTorchPuzzleRoom = 0x49
|
||||
PoD_EntranceRoom = 0x4a
|
||||
PoD_Warps_SouthMimicsRoom = 0x4b
|
||||
GT_Mini_HelmasaurConveyorRoom = 0x4c
|
||||
GT_MoldormRoom = 0x4d
|
||||
Ice_Bomb_JumpRoom = 0x4e
|
||||
IcePalaceCloneRoom_FairyRoom = 0x4f
|
||||
HC_WestCorridor = 0x50
|
||||
HC_ThroneRoom = 0x51
|
||||
HC_EastCorridor = 0x52
|
||||
Desert_Popos2_BeamosHellwayRoom = 0x53
|
||||
Swamp_UpstairsPitsRoom = 0x54
|
||||
CastleSecretEntrance_UncleDeathRoom = 0x55
|
||||
Skull_KeyPot_TrapRoom = 0x56
|
||||
Skull_BigKeyRoom = 0x57
|
||||
Skull_BigChestRoom = 0x58
|
||||
Skull_FinalSectionEntranceRoom = 0x59
|
||||
PoD_HelmasaurKing = 0x5a
|
||||
GT_SpikePitRoom = 0x5b
|
||||
GT_Ganon_BallZ = 0x5c
|
||||
GT_Gauntlet1_2_3 = 0x5d
|
||||
Ice_LonelyFirebar = 0x5e
|
||||
Ice_HiddenChest_SpikeFloorRoom = 0x5f
|
||||
HC_WestEntranceRoom = 0x60
|
||||
HC_MainEntranceRoom = 0x61
|
||||
HC_EastEntranceRoom = 0x62
|
||||
Desert_FinalSectionEntranceRoom = 0x63
|
||||
TT_WestAtticRoom = 0x64
|
||||
TT_EastAtticRoom = 0x65
|
||||
Swamp_HiddenChest_HiddenDoorRoom = 0x66
|
||||
Skull_CompassChestRoom = 0x67
|
||||
Skull_KeyChest_TrapRoom = 0x68
|
||||
PoD_RupeeRoom = 0x6a
|
||||
GT_MimicsRooms = 0x6b
|
||||
GT_LanmolasRoom = 0x6c
|
||||
GT_Gauntlet4_5 = 0x6d
|
||||
Ice_PengatorsRoom = 0x6e
|
||||
HC_SmallCorridortoJailCells = 0x70
|
||||
HC_BoomerangChestRoom = 0x71
|
||||
HC_MapChestRoom = 0x72
|
||||
Desert_BigChestRoom = 0x73
|
||||
Desert_MapChestRoom = 0x74
|
||||
Desert_BigKeyChestRoom = 0x75
|
||||
Swamp_WaterDrainRoom = 0x76
|
||||
Hera_EntranceRoom = 0x77
|
||||
GanonsTower = 0x7b
|
||||
GT_EastSideCollapsingBridge_ExplodingWallRoom = 0x7c
|
||||
GT_Winder_WarpMazeRoom = 0x7d
|
||||
Ice_HiddenChest_BombableFloorRoom = 0x7e
|
||||
Ice_BigSpikeTrapsRoom = 0x7f
|
||||
HC_JailCellRoom = 0x80
|
||||
HC_NextToChasmRoom = 0x81
|
||||
HC_BasementChasmRoom = 0x82
|
||||
Desert_WestEntranceRoom = 0x83
|
||||
Desert_MainEntranceRoom = 0x84
|
||||
Desert_EastEntranceRoom = 0x85
|
||||
Hera_TileRoom = 0x87
|
||||
Eastern_FairyRoom = 0x89
|
||||
GT_BlockPuzzle_SpikeSkip_MapChestRoom = 0x8b
|
||||
GT_EastandWestDownstairs_BigChestRoom = 0x8c
|
||||
GT_Tile_TorchPuzzleRoom = 0x8d
|
||||
IcePalace0x8E = 0x8e
|
||||
Mire_Vitreous = 0x90
|
||||
Mire_FinalSwitchRoom = 0x91
|
||||
Mire_DarkBombWall_SwitchesRoom = 0x92
|
||||
Mire_DarkCaneFloorSwitchPuzzleRoom = 0x93
|
||||
GT_FinalCollapsingBridgeRoom = 0x95
|
||||
GT_Torches1Room = 0x96
|
||||
Mire_TorchPuzzle_MovingWallRoom = 0x97
|
||||
Mire_EntranceRoom = 0x98
|
||||
Eastern_EyegoreKeyRoom = 0x99
|
||||
GT_ManySpikes_WarpMazeRoom = 0x9b
|
||||
GT_InvisibleFloorMazeRoom = 0x9c
|
||||
GT_CompassChest_InvisibleFloorRoom = 0x9d
|
||||
Ice_BigChestRoom = 0x9e
|
||||
IcePalace0x9F = 0x9f
|
||||
Mire_Pre_VitreousRoom = 0xa0
|
||||
Mire_FishRoom = 0xa1
|
||||
Mire_BridgeKeyChestRoom = 0xa2
|
||||
MiseryMire0xA3 = 0xa3
|
||||
TR_Trinexx = 0xa4
|
||||
GT_WizzrobesRooms = 0xa5
|
||||
GT_MoldormFallRoom = 0xa6
|
||||
Hera_FairyRoom = 0xa7
|
||||
Eastern_StalfosSpawnRoom = 0xa8
|
||||
Eastern_BigChestRoom = 0xa9
|
||||
Eastern_MapChestRoom = 0xaa
|
||||
TT_MovingSpikes_KeyPotRoom = 0xab
|
||||
TT_BlindTheThief = 0xac
|
||||
IcePalace0xAE = 0xae
|
||||
Ice_IceBridgeRoom = 0xaf
|
||||
Tower_CircleofPots = 0xb0
|
||||
Mire_HourglassRoom = 0xb1
|
||||
Mire_SlugRoom = 0xb2
|
||||
Mire_SpikeKeyChestRoom = 0xb3
|
||||
TR_Pre_TrinexxRoom = 0xb4
|
||||
TR_DarkMaze = 0xb5
|
||||
TR_ChainChompsRoom = 0xb6
|
||||
TR_MapChest_KeyChest_RollerRoom = 0xb7
|
||||
Eastern_BigKeyRoom = 0xb8
|
||||
Eastern_LobbyCannonballsRoom = 0xb9
|
||||
Eastern_DarkAntifairy_KeyPotRoom = 0xba
|
||||
TT_Hellway = 0xbb
|
||||
TT_ConveyorToilet = 0xbc
|
||||
Ice_BlockPuzzleRoom = 0xbe
|
||||
IcePalaceCloneRoom_SwitchRoom = 0xbf
|
||||
Tower_DarkBridgeRoom = 0xc0
|
||||
Mire_CompassChest_TileRoom = 0xc1
|
||||
Mire_BigHubRoom = 0xc2
|
||||
Mire_BigChestRoom = 0xc3
|
||||
TR_FinalCrystalSwitchPuzzleRoom = 0xc4
|
||||
TR_LaserBridge = 0xc5
|
||||
TurtleRock0xC6 = 0xc6
|
||||
TR_TorchPuzzle = 0xc7
|
||||
Eastern_ArmosKnights = 0xc8
|
||||
Eastern_EntranceRoom = 0xc9
|
||||
UnknownRoom = 0xca
|
||||
TT_NorthWestEntranceRoom = 0xcb
|
||||
TT_NorthEastEntranceRoom = 0xcc
|
||||
Ice_HoletoKholdstareRoom = 0xce
|
||||
Tower_DarkMaze = 0xd0
|
||||
Mire_ConveyorSlug_BigKeyRoom = 0xd1
|
||||
Mire_Mire02_WizzrobesRoom = 0xd2
|
||||
TR_LaserKeyRoom = 0xd5
|
||||
TR_EntranceRoom = 0xd6
|
||||
Eastern_PreArmosKnightsRoom = 0xd8
|
||||
Eastern_CanonballRoom = 0xd9
|
||||
EasternPalace = 0xda
|
||||
TT_Main_SouthWestEntranceRoom = 0xdb
|
||||
TT_SouthEastEntranceRoom = 0xdc
|
||||
Ice_Kholdstare = 0xde
|
||||
Cave_BackwardsDeathMountainTopFloor = 0xdf
|
||||
Tower_EntranceRoom = 0xe0
|
||||
Cave_LostWoodsHP = 0xe1
|
||||
Cave_LumberjacksTreeHP = 0xe2
|
||||
Cave_HalfMagic = 0xe3
|
||||
Cave_LostOldManFinalCave = 0xe4
|
||||
Cave_LostOldManFinalCave2 = 0xe5
|
||||
Cave0xE6 = 0xe6
|
||||
Cave0xE7 = 0xe7
|
||||
Cave0xE8 = 0xe8
|
||||
Cave_SpectacleRockHP = 0xea
|
||||
Cave0xEB = 0xeb
|
||||
Cave0xED = 0xed
|
||||
Cave_SpiralCave = 0xee
|
||||
Cave_CrystalSwitch_5ChestsRoom = 0xef
|
||||
Cave_LostOldManStartingCave = 0xf0
|
||||
Cave_LostOldManStartingCave2 = 0xf1
|
||||
House = 0xf2
|
||||
House_OldWoman = 0xf3
|
||||
House_AngryBrothers = 0xf4
|
||||
House_AngryBrothers2 = 0xf5
|
||||
Cave0xF8 = 0xf8
|
||||
Cave0xF9 = 0xf9
|
||||
Cave0xFA = 0xfa
|
||||
Cave0xFB = 0xfb
|
||||
Cave0xFD = 0xfd
|
||||
Cave0xFE = 0xfe
|
||||
Cave0xFF = 0xff
|
||||
ShopInLostWoods0x100 = 0x100
|
||||
ScaredLadyHouses = 0x101
|
||||
SickKid = 0x102
|
||||
Inn_BushHouse = 0x103
|
||||
LinksHouse = 0x104
|
||||
ShabadooHouse = 0x105
|
||||
ChestGame_BombHouse = 0x106
|
||||
Library_BombFarmRoom = 0x107
|
||||
ChickenHouse = 0x108
|
||||
WitchHut = 0x109
|
||||
Aginah = 0x10a
|
||||
SwampFloodwayRoom = 0x10b
|
||||
MimicCave = 0x10c
|
||||
CaveOutsideMiseryMire = 0x10d
|
||||
Cave0x10E = 0x10e
|
||||
Shop0x10F = 0x10f
|
||||
Shop0x110 = 0x110
|
||||
ArcherGame = 0x111
|
||||
CaveShop0x112 = 0x112
|
||||
KingsTomb = 0x113
|
||||
WishingWell_Cave0x114 = 0x114
|
||||
WishingWell_BigFairy = 0x115
|
||||
FatFairy = 0x116
|
||||
SpikeCave = 0x117
|
||||
Shop0x118 = 0x118
|
||||
BlindsHouse = 0x119
|
||||
Mutant = 0x11a
|
||||
MirrorCaveGroveAndTomb = 0x11b
|
||||
BombShop = 0x11c
|
||||
BlindsBasement = 0x11d
|
||||
HypeCave = 0x11e
|
||||
Shop0x11F = 0x11f
|
||||
IceRodCave = 0x120
|
||||
SmithHouse = 0x121
|
||||
FortuneTellers = 0x122
|
||||
MiniMoldormCave = 0x123
|
||||
UnknownCave_BonkCave = 0x124
|
||||
Cave0x125 = 0x125
|
||||
CheckerBoardCave = 0x126
|
||||
HammerPegCave = 0x127
|
||||
331
source/dungeon/RoomHeader.py
Normal file
331
source/dungeon/RoomHeader.py
Normal file
@@ -0,0 +1,331 @@
|
||||
|
||||
|
||||
vanilla_headers = {
|
||||
0x0000: [0x41, 0x21, 0x13, 0x22, 0x07, 0x3D, 0x00, 0x00, 0x00, 0x10, 0xC0, 0x00, 0x00, 0x04],
|
||||
0x0001: [0xC0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x72, 0x00, 0x50, 0x52],
|
||||
0x0002: [0xC0, 0x1D, 0x04, 0x06, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x18, 0x0D],
|
||||
0x0003: [0xC0, 0x07, 0x06, 0x19, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x02, 0x12, 0x00, 0x00, 0x00],
|
||||
0x0004: [0x00, 0x18, 0x0D, 0x26, 0x00, 0x26, 0x14, 0x00, 0x00, 0x00, 0xB5, 0x00, 0x08, 0x08],
|
||||
0x0005: [0x00, 0x08, 0x08, 0x14, 0x00, 0x25, 0x00, 0x20, 0x06, 0x05, 0x0C, 0x00, 0x25, 0x00],
|
||||
0x0006: [0x00, 0x08, 0x08, 0x14, 0x00, 0x25, 0x00, 0x20, 0x06, 0x05, 0x0C, 0x00, 0x25, 0x00],
|
||||
0x0007: [0x20, 0x06, 0x05, 0x0C, 0x00, 0x25, 0x00, 0x00, 0x00, 0x17, 0x17, 0xC0, 0x07, 0x06],
|
||||
0x0008: [0xC0, 0x07, 0x06, 0x07, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x07, 0x19, 0x00, 0x27, 0x00],
|
||||
0x0009: [0x00, 0x0F, 0x07, 0x19, 0x00, 0x27, 0x00, 0x00, 0x00, 0x4B, 0x4A, 0x4A, 0x00, 0x0F],
|
||||
0x000A: [0x00, 0x0F, 0x07, 0x19, 0x00, 0x27, 0x00, 0x00, 0x00, 0x09, 0x3A, 0x01, 0x0F, 0x07],
|
||||
0x000B: [0x01, 0x0F, 0x07, 0x19, 0x00, 0x03, 0x00, 0x00, 0x00, 0x6A, 0x1B, 0xC0, 0x28, 0x0E],
|
||||
0x000C: [0xC0, 0x28, 0x0E, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6B, 0x8C, 0x8C, 0x40],
|
||||
0x000D: [0x40, 0x1B, 0x0E, 0x18, 0x05, 0x38, 0x00, 0x00, 0x13, 0x0B, 0x1C, 0x00, 0x08, 0x00],
|
||||
0x000E: [0x00, 0x13, 0x0B, 0x1C, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x21, 0x13],
|
||||
0x000F: [0x00, 0x21, 0x13, 0x22, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00],
|
||||
0x0010: [0x00, 0x21, 0x13, 0x22, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00],
|
||||
0x0011: [0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x02, 0xC0, 0x1D, 0x04],
|
||||
0x0012: [0xC0, 0x1D, 0x04, 0x06, 0x00, 0x00, 0x00, 0x00, 0x18, 0x0D, 0x26, 0x00, 0x00, 0x00],
|
||||
0x0013: [0x00, 0x18, 0x0D, 0x26, 0x00, 0x00, 0x00, 0x00, 0x18, 0x0D, 0x1E, 0x00, 0x00, 0x00],
|
||||
0x0014: [0x20, 0x18, 0x0D, 0x26, 0x00, 0x00, 0x00, 0xC0, 0x18, 0x0D, 0x26, 0x00, 0x00, 0x00],
|
||||
0x0015: [0xC0, 0x18, 0x0D, 0x26, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB6, 0x90, 0x08, 0x08],
|
||||
0x0016: [0x90, 0x08, 0x08, 0x11, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x20, 0x06, 0x05],
|
||||
0x0017: [0x20, 0x06, 0x05, 0x19, 0x00, 0x35, 0x00, 0x00, 0x00, 0x27, 0x07, 0x27, 0x01, 0x0F],
|
||||
0x0018: [0x00, 0x07, 0x06, 0x07, 0x00, 0x00, 0x00, 0x00, 0x22, 0x12, 0x07, 0x00, 0x00, 0x00],
|
||||
0x0019: [0x01, 0x0F, 0x07, 0x19, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x07, 0x19, 0x00, 0x16, 0x00],
|
||||
0x001A: [0x00, 0x0F, 0x07, 0x19, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x6A, 0x6A, 0x68, 0x0F],
|
||||
0x001B: [0x68, 0x0F, 0x07, 0x08, 0x00, 0x03, 0x1C, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x1A, 0x0E],
|
||||
0x001C: [0x00, 0x1A, 0x0E, 0x09, 0x00, 0x04, 0x3F, 0x00, 0x00, 0x00, 0x8C, 0x00, 0x1B, 0x0E],
|
||||
0x001D: [0x00, 0x1B, 0x0E, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4C, 0x20, 0x13, 0x0B],
|
||||
0x001E: [0x20, 0x13, 0x0B, 0x1C, 0x00, 0x17, 0x00, 0x00, 0x00, 0x3E, 0x0E, 0x00, 0x13, 0x0B],
|
||||
0x001F: [0x00, 0x13, 0x0B, 0x29, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x20, 0x0C, 0x02],
|
||||
0x0020: [0x20, 0x0C, 0x02, 0x12, 0x00, 0x15, 0x25, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00],
|
||||
0x0021: [0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x18, 0x0D, 0x26, 0x00, 0x01, 0x00],
|
||||
0x0022: [0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x18, 0x0D, 0x26, 0x00, 0x01, 0x00],
|
||||
0x0023: [0x00, 0x18, 0x0D, 0x26, 0x00, 0x00, 0x00, 0x00, 0x18, 0x0D, 0x1E, 0x00, 0x00, 0x00],
|
||||
0x0024: [0x00, 0x18, 0x0D, 0x26, 0x00, 0x01, 0x00, 0x00, 0x0A, 0x08, 0x11, 0x00, 0x16, 0x00],
|
||||
0x0025: [0x00, 0x0A, 0x08, 0x11, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x76, 0x76, 0x76, 0x20],
|
||||
0x0026: [0x00, 0x0A, 0x08, 0x11, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x76, 0x76, 0x76, 0x20],
|
||||
0x0027: [0x20, 0x06, 0x05, 0x19, 0x00, 0x36, 0x00, 0x00, 0x00, 0x31, 0x17, 0x31, 0x80, 0x0A],
|
||||
0x0028: [0x80, 0x0A, 0x08, 0x11, 0x00, 0x32, 0x1B, 0x00, 0x00, 0x00, 0x38, 0xCC, 0x0E, 0x09],
|
||||
0x0029: [0xCC, 0x0E, 0x09, 0x1A, 0x02, 0x25, 0x00, 0x00, 0x0F, 0x07, 0x19, 0x00, 0x00, 0x00],
|
||||
0x002A: [0x00, 0x0F, 0x07, 0x19, 0x00, 0x00, 0x00, 0xC0, 0x0F, 0x07, 0x2B, 0x00, 0x16, 0x00],
|
||||
0x002B: [0xC0, 0x0F, 0x07, 0x2B, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x13, 0x0B],
|
||||
0x002C: [0x00, 0x07, 0x06, 0x07, 0x00, 0x00, 0x00, 0x00, 0x22, 0x12, 0x07, 0x00, 0x00, 0x00],
|
||||
0x002D: [0x00, 0x13, 0x0B, 0x1C, 0x00, 0x2A, 0x00, 0xC0, 0x07, 0x06, 0x19, 0x00, 0x00, 0x00],
|
||||
0x002E: [0x00, 0x13, 0x0B, 0x1C, 0x00, 0x2A, 0x00, 0xC0, 0x07, 0x06, 0x19, 0x00, 0x00, 0x00],
|
||||
0x002F: [0xC0, 0x07, 0x06, 0x19, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x02, 0x12, 0x00, 0x00, 0x00],
|
||||
0x0030: [0x00, 0x0C, 0x02, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x20, 0x06, 0x05],
|
||||
0x0031: [0x20, 0x06, 0x05, 0x19, 0x00, 0x37, 0x04, 0x22, 0x00, 0x77, 0x27, 0x77, 0x01, 0x01],
|
||||
0x0032: [0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x00, 0x04, 0x05],
|
||||
0x0033: [0x00, 0x04, 0x05, 0x0B, 0x00, 0x15, 0x25, 0x80, 0x0A, 0x08, 0x11, 0x00, 0x00, 0x00],
|
||||
0x0034: [0x80, 0x0A, 0x08, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x80, 0x0A, 0x08],
|
||||
0x0035: [0x80, 0x0A, 0x08, 0x11, 0x00, 0x00, 0x19, 0x80, 0x0A, 0x08, 0x11, 0x00, 0x00, 0x00],
|
||||
0x0036: [0x80, 0x0A, 0x08, 0x11, 0x00, 0x00, 0x00, 0x80, 0x0A, 0x08, 0x11, 0x00, 0x00, 0x00],
|
||||
0x0037: [0x80, 0x0A, 0x08, 0x11, 0x00, 0x00, 0x19, 0x80, 0x0A, 0x08, 0x11, 0x00, 0x00, 0x00],
|
||||
0x0038: [0x80, 0x0A, 0x08, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x20, 0x0D, 0x09],
|
||||
0x0039: [0x20, 0x0D, 0x09, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0x20, 0x0F, 0x07, 0x19],
|
||||
0x003A: [0x20, 0x0F, 0x07, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x0A, 0x00, 0x0F, 0x07],
|
||||
0x003B: [0x00, 0x0F, 0x07, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x07, 0x06],
|
||||
0x003C: [0x00, 0x07, 0x06, 0x13, 0x00, 0x00, 0x00, 0x20, 0x1A, 0x0E, 0x0C, 0x00, 0x33, 0x00],
|
||||
0x003D: [0x20, 0x1A, 0x0E, 0x0C, 0x00, 0x33, 0x00, 0x00, 0x00, 0x96, 0x96, 0xCC, 0x13, 0x0B],
|
||||
0x003E: [0xCC, 0x13, 0x0B, 0x29, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x13, 0x0B],
|
||||
0x003F: [0x00, 0x13, 0x0B, 0x29, 0x00, 0x27, 0x14, 0x00, 0x00, 0x00, 0x1F, 0x5F, 0xC0, 0x00],
|
||||
0x0040: [0xC0, 0x00, 0x02, 0x27, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0xB0, 0x01, 0x00],
|
||||
0x0041: [0x01, 0x00, 0x00, 0x02, 0x00, 0x13, 0x00, 0x00, 0x00, 0x00, 0x42, 0x01, 0x01, 0x01],
|
||||
0x0042: [0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x32, 0x68, 0x04],
|
||||
0x0043: [0x68, 0x04, 0x05, 0x0A, 0x00, 0x00, 0x1D, 0x00, 0x17, 0x0A, 0x1B, 0x00, 0x01, 0x00],
|
||||
0x0044: [0x00, 0x17, 0x0A, 0x1B, 0x00, 0x01, 0x00, 0x60, 0x17, 0x0A, 0x1B, 0x00, 0x01, 0x00],
|
||||
0x0045: [0x60, 0x17, 0x0A, 0x1B, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0xBC, 0x00, 0x0A, 0x08],
|
||||
0x0046: [0x00, 0x0A, 0x08, 0x11, 0x00, 0x3C, 0x00, 0x00, 0x0D, 0x09, 0x13, 0x00, 0x33, 0x34],
|
||||
0x0047: [0x00, 0x0D, 0x09, 0x13, 0x00, 0x33, 0x34, 0x00, 0x0F, 0x07, 0x19, 0x00, 0x17, 0x00],
|
||||
0x0048: [0x00, 0x0D, 0x09, 0x13, 0x00, 0x33, 0x34, 0x00, 0x0F, 0x07, 0x19, 0x00, 0x17, 0x00],
|
||||
0x0049: [0x00, 0x0D, 0x09, 0x13, 0x00, 0x33, 0x34, 0x00, 0x0F, 0x07, 0x19, 0x00, 0x17, 0x00],
|
||||
0x004A: [0x00, 0x0F, 0x07, 0x19, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x09, 0x09, 0x00, 0x0F],
|
||||
0x004B: [0x00, 0x0F, 0x07, 0x08, 0x00, 0x01, 0x00, 0x00, 0x00, 0x09, 0x00, 0x1A, 0x0E, 0x0C],
|
||||
0x004C: [0x00, 0x1A, 0x0E, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1D, 0x20, 0x1A, 0x0E],
|
||||
0x004D: [0x20, 0x1A, 0x0E, 0x0C, 0x00, 0x32, 0x3F, 0x00, 0x00, 0xA6, 0xA6, 0x00, 0x13, 0x0B],
|
||||
0x004E: [0x00, 0x13, 0x0B, 0x29, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x6E, 0x00, 0x13, 0x0B],
|
||||
0x004F: [0x00, 0x13, 0x0B, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBE, 0xC0, 0x00, 0x00, 0x04],
|
||||
0x0050: [0xC0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01],
|
||||
0x0051: [0xC0, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x61, 0xC0, 0x00, 0x00],
|
||||
0x0052: [0xC0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01],
|
||||
0x0053: [0xC0, 0x04, 0x05, 0x0A, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x63, 0x20, 0x0A, 0x08],
|
||||
0x0054: [0x20, 0x0A, 0x08, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x34, 0x01, 0x01, 0x10],
|
||||
0x0055: [0x01, 0x01, 0x10, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x09, 0x13, 0x00, 0x23, 0x00],
|
||||
0x0056: [0x00, 0x0D, 0x09, 0x13, 0x00, 0x23, 0x00, 0x00, 0x0D, 0x09, 0x13, 0x00, 0x16, 0x00],
|
||||
0x0057: [0x00, 0x0D, 0x09, 0x13, 0x00, 0x16, 0x00, 0x00, 0x0D, 0x09, 0x13, 0x00, 0x21, 0x28],
|
||||
0x0058: [0x00, 0x0D, 0x09, 0x13, 0x00, 0x21, 0x28, 0xC0, 0x0D, 0x09, 0x13, 0x00, 0x00, 0x00],
|
||||
0x0059: [0xC0, 0x0D, 0x09, 0x13, 0x00, 0x00, 0x00, 0x00, 0x10, 0x07, 0x15, 0x00, 0x25, 0x00],
|
||||
0x005A: [0x00, 0x10, 0x07, 0x15, 0x00, 0x25, 0x00, 0xC0, 0x1B, 0x0E, 0x0A, 0x00, 0x17, 0x00],
|
||||
0x005B: [0xC0, 0x1B, 0x0E, 0x0A, 0x00, 0x17, 0x00, 0x00, 0x1B, 0x0E, 0x0A, 0x00, 0x00, 0x00],
|
||||
0x005C: [0x00, 0x1B, 0x0E, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5D, 0x00, 0x24, 0x0E],
|
||||
0x005D: [0x00, 0x24, 0x0E, 0x23, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x5C, 0x20, 0x13, 0x0B],
|
||||
0x005E: [0x20, 0x13, 0x0B, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x7E, 0x00, 0x13, 0x0B],
|
||||
0x005F: [0x00, 0x13, 0x0B, 0x1C, 0x00, 0x27, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x7F, 0xC0, 0x00],
|
||||
0x0060: [0xC0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00],
|
||||
0x0061: [0xC0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x51, 0x00, 0x09, 0x05],
|
||||
0x0062: [0xC0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00],
|
||||
0x0063: [0x00, 0x09, 0x05, 0x0A, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x53, 0xE0, 0x23, 0x0A],
|
||||
0x0064: [0xE0, 0x23, 0x0A, 0x21, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0xAB, 0xE0, 0x23, 0x0A],
|
||||
0x0065: [0xE0, 0x23, 0x0A, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0xAC, 0xC0, 0x0A, 0x08, 0x11],
|
||||
0x0066: [0xC0, 0x0A, 0x08, 0x11, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x16, 0x00, 0x0D, 0x09],
|
||||
0x0067: [0x00, 0x0D, 0x09, 0x13, 0x00, 0x22, 0x00, 0x00, 0x0D, 0x09, 0x13, 0x00, 0x00, 0x00],
|
||||
0x0068: [0x00, 0x0D, 0x09, 0x13, 0x00, 0x00, 0x00, 0x01, 0x0F, 0x07, 0x19, 0x00, 0x00, 0x00],
|
||||
0x0069: [0x01, 0x0F, 0x07, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1A, 0x1A, 0x00, 0x1B],
|
||||
0x006A: [0x01, 0x0F, 0x07, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1A, 0x1A, 0x00, 0x1B],
|
||||
0x006B: [0x00, 0x1B, 0x0E, 0x0A, 0x00, 0x08, 0x0B, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x24, 0x0E],
|
||||
0x006C: [0x00, 0x24, 0x0E, 0x23, 0x00, 0x03, 0x3F, 0x00, 0x00, 0x00, 0xA5, 0x00, 0x24, 0x0E],
|
||||
0x006D: [0x00, 0x24, 0x0E, 0x23, 0x00, 0x05, 0x00, 0x00, 0x13, 0x0B, 0x1C, 0x00, 0x02, 0x00],
|
||||
0x006E: [0x00, 0x13, 0x0B, 0x1C, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x4E, 0x00, 0x01, 0x01],
|
||||
0x006F: [0x00, 0x01, 0x01, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x71, 0x80, 0xC0, 0x01],
|
||||
0x0070: [0x00, 0x01, 0x01, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x71, 0x80, 0xC0, 0x01],
|
||||
0x0071: [0xC0, 0x01, 0x01, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x70, 0xC0, 0x01, 0x01],
|
||||
0x0072: [0xC0, 0x01, 0x01, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x01, 0x00, 0x09, 0x05],
|
||||
0x0073: [0x00, 0x09, 0x05, 0x0A, 0x00, 0x17, 0x00, 0x00, 0x09, 0x05, 0x0A, 0x00, 0x27, 0x00],
|
||||
0x0074: [0x00, 0x09, 0x05, 0x0A, 0x00, 0x27, 0x00, 0x00, 0x09, 0x05, 0x0A, 0x00, 0x01, 0x00],
|
||||
0x0075: [0x00, 0x09, 0x05, 0x0A, 0x00, 0x01, 0x00, 0x80, 0x0A, 0x08, 0x11, 0x00, 0x00, 0x18],
|
||||
0x0076: [0x80, 0x0A, 0x08, 0x11, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x26, 0x26, 0x26, 0xC0],
|
||||
0x0077: [0xC0, 0x06, 0x05, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA7, 0x31, 0x87, 0x87, 0x00],
|
||||
0x0078: [0x00, 0x28, 0x0E, 0x13, 0x00, 0x03, 0x39, 0x00, 0x00, 0x9D, 0x00, 0x28, 0x0E, 0x13],
|
||||
0x0079: [0x00, 0x28, 0x0E, 0x13, 0x00, 0x03, 0x39, 0x00, 0x00, 0x9D, 0x00, 0x28, 0x0E, 0x13],
|
||||
0x007A: [0x00, 0x28, 0x0E, 0x13, 0x00, 0x03, 0x39, 0x00, 0x00, 0x9D, 0x00, 0x28, 0x0E, 0x13],
|
||||
0x007B: [0x00, 0x28, 0x0E, 0x13, 0x00, 0x03, 0x39, 0x00, 0x00, 0x9D, 0x00, 0x28, 0x0E, 0x13],
|
||||
0x007C: [0x00, 0x28, 0x0E, 0x13, 0x00, 0x20, 0x00, 0x00, 0x28, 0x0E, 0x13, 0x00, 0x04, 0x3C],
|
||||
0x007D: [0x00, 0x28, 0x0E, 0x13, 0x00, 0x04, 0x3C, 0x00, 0x00, 0x9B, 0x20, 0x13, 0x0B, 0x1C],
|
||||
0x007E: [0x20, 0x13, 0x0B, 0x1C, 0x00, 0x2B, 0x17, 0x00, 0x00, 0x9E, 0x5E, 0x00, 0x13, 0x0B],
|
||||
0x007F: [0x00, 0x13, 0x0B, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5F, 0x60, 0x01, 0x01],
|
||||
0x0080: [0x60, 0x01, 0x01, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0xC0, 0x01, 0x01],
|
||||
0x0081: [0xC0, 0x01, 0x01, 0x04, 0x00, 0x00, 0x00, 0x00, 0x09, 0x05, 0x0A, 0x00, 0x0D, 0x00],
|
||||
0x0082: [0xC0, 0x01, 0x01, 0x04, 0x00, 0x00, 0x00, 0x00, 0x09, 0x05, 0x0A, 0x00, 0x0D, 0x00],
|
||||
0x0083: [0x00, 0x09, 0x05, 0x0A, 0x00, 0x0D, 0x00, 0x00, 0x09, 0x05, 0x0A, 0x00, 0x00, 0x00],
|
||||
0x0084: [0x00, 0x09, 0x05, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x09, 0x05, 0x0A, 0x00, 0x02, 0x00],
|
||||
0x0085: [0x00, 0x09, 0x05, 0x0A, 0x00, 0x02, 0x00, 0x00, 0x06, 0x05, 0x19, 0x00, 0x3E, 0x01],
|
||||
0x0086: [0x00, 0x06, 0x05, 0x19, 0x00, 0x3E, 0x01, 0x28, 0x00, 0x00, 0x77, 0x77, 0x00, 0x0B],
|
||||
0x0087: [0x00, 0x06, 0x05, 0x19, 0x00, 0x3E, 0x01, 0x28, 0x00, 0x00, 0x77, 0x77, 0x00, 0x0B],
|
||||
0x0088: [0x00, 0x0B, 0x05, 0x08, 0x00, 0x00, 0x00, 0x02, 0x00, 0xA9, 0x00, 0x28, 0x0E, 0x13],
|
||||
0x0089: [0x00, 0x0B, 0x05, 0x08, 0x00, 0x00, 0x00, 0x02, 0x00, 0xA9, 0x00, 0x28, 0x0E, 0x13],
|
||||
0x008A: [0x00, 0x28, 0x0E, 0x13, 0x00, 0x3A, 0x0C, 0x20, 0x28, 0x0E, 0x13, 0x00, 0x16, 0x00],
|
||||
0x008B: [0x00, 0x28, 0x0E, 0x13, 0x00, 0x3A, 0x0C, 0x20, 0x28, 0x0E, 0x13, 0x00, 0x16, 0x00],
|
||||
0x008C: [0x20, 0x28, 0x0E, 0x13, 0x00, 0x16, 0x00, 0x28, 0x00, 0x1C, 0x0C, 0x0C, 0x1C, 0x00],
|
||||
0x008D: [0x00, 0x28, 0x0E, 0x13, 0x00, 0x33, 0x29, 0x00, 0x13, 0x0B, 0x1C, 0x00, 0x00, 0x00],
|
||||
0x008E: [0x00, 0x13, 0x0B, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xAE, 0x80, 0x12, 0x0C],
|
||||
0x008F: [0x80, 0x12, 0x0C, 0x16, 0x00, 0x25, 0x00, 0x00, 0x11, 0x0C, 0x1C, 0x00, 0x00, 0x00],
|
||||
0x0090: [0x80, 0x12, 0x0C, 0x16, 0x00, 0x25, 0x00, 0x00, 0x11, 0x0C, 0x1C, 0x00, 0x00, 0x00],
|
||||
0x0091: [0x00, 0x11, 0x0C, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA0, 0x01, 0x11, 0x0C],
|
||||
0x0092: [0x01, 0x11, 0x0C, 0x1C, 0x00, 0x00, 0x00, 0x01, 0x11, 0x0C, 0x1C, 0x00, 0x16, 0x00],
|
||||
0x0093: [0x01, 0x11, 0x0C, 0x1C, 0x00, 0x16, 0x00, 0x08, 0x00, 0x00, 0xA2, 0x00, 0x25, 0x0E],
|
||||
0x0094: [0x00, 0x25, 0x0E, 0x24, 0x00, 0x00, 0x00, 0x00, 0x25, 0x0E, 0x24, 0x00, 0x33, 0x00],
|
||||
0x0095: [0x00, 0x25, 0x0E, 0x24, 0x00, 0x00, 0x00, 0x00, 0x25, 0x0E, 0x24, 0x00, 0x33, 0x00],
|
||||
0x0096: [0x00, 0x25, 0x0E, 0x24, 0x00, 0x33, 0x00, 0x00, 0x00, 0x00, 0x3D, 0x68, 0x11, 0x0C],
|
||||
0x0097: [0x68, 0x11, 0x0C, 0x1D, 0x00, 0x1C, 0x00, 0x00, 0x00, 0xD1, 0xD1, 0x00, 0x11, 0x0C],
|
||||
0x0098: [0x00, 0x11, 0x0C, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD2, 0x01, 0x0B, 0x05],
|
||||
0x0099: [0x01, 0x0B, 0x05, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xDA, 0x00, 0x28, 0x0E],
|
||||
0x009A: [0x00, 0x28, 0x0E, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7D, 0x00, 0x28, 0x0E, 0x13],
|
||||
0x009B: [0x00, 0x28, 0x0E, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7D, 0x00, 0x28, 0x0E, 0x13],
|
||||
0x009C: [0x00, 0x28, 0x0E, 0x13, 0x06, 0x00, 0x00, 0x00, 0x28, 0x0E, 0x13, 0x06, 0x00, 0x3B],
|
||||
0x009D: [0x00, 0x28, 0x0E, 0x13, 0x06, 0x00, 0x3B, 0x00, 0x00, 0x7B, 0x20, 0x13, 0x0B, 0x1C],
|
||||
0x009E: [0x20, 0x13, 0x0B, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBE, 0xBE, 0x00, 0x13, 0x0B],
|
||||
0x009F: [0x00, 0x13, 0x0B, 0x1C, 0x00, 0x17, 0x00, 0x00, 0x12, 0x0C, 0x1D, 0x00, 0x00, 0x00],
|
||||
0x00A0: [0x00, 0x12, 0x0C, 0x1D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x91, 0x00, 0x11, 0x0C],
|
||||
0x00A1: [0x00, 0x11, 0x0C, 0x1D, 0x00, 0x00, 0x00, 0xC0, 0x11, 0x0C, 0x1D, 0x00, 0x00, 0x00],
|
||||
0x00A2: [0xC0, 0x11, 0x0C, 0x1D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x93, 0x60, 0x19, 0x0D],
|
||||
0x00A3: [0x00, 0x11, 0x0C, 0x1D, 0x00, 0x00, 0x00, 0xC0, 0x11, 0x0C, 0x1D, 0x00, 0x00, 0x00],
|
||||
0x00A4: [0x60, 0x19, 0x0D, 0x17, 0x04, 0x25, 0x00, 0x00, 0x25, 0x0E, 0x24, 0x00, 0x07, 0x00],
|
||||
0x00A5: [0x00, 0x25, 0x0E, 0x24, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x6C, 0x00, 0x25, 0x0E],
|
||||
0x00A6: [0x00, 0x25, 0x0E, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4D, 0x00, 0x06, 0x05],
|
||||
0x00A7: [0x00, 0x06, 0x05, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0xC0, 0x0B, 0x05, 0x08],
|
||||
0x00A8: [0xC0, 0x0B, 0x05, 0x08, 0x00, 0x03, 0x00, 0xC0, 0x0B, 0x05, 0x08, 0x00, 0x17, 0x00],
|
||||
0x00A9: [0xC0, 0x0B, 0x05, 0x08, 0x00, 0x17, 0x00, 0x00, 0x00, 0x89, 0xC0, 0x0B, 0x05, 0x08],
|
||||
0x00AA: [0xC0, 0x0B, 0x05, 0x08, 0x00, 0x17, 0x00, 0x00, 0x17, 0x0A, 0x1B, 0x00, 0x00, 0x00],
|
||||
0x00AB: [0x00, 0x17, 0x0A, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0xE0, 0x17, 0x0A],
|
||||
0x00AC: [0xE0, 0x17, 0x0A, 0x20, 0x00, 0x25, 0x00, 0x00, 0x13, 0x0B, 0x1C, 0x00, 0x27, 0x00],
|
||||
0x00AD: [0x00, 0x13, 0x0B, 0x1C, 0x00, 0x27, 0x00, 0x00, 0x00, 0x00, 0x8E, 0x00, 0x13, 0x0B],
|
||||
0x00AE: [0x00, 0x13, 0x0B, 0x1C, 0x00, 0x27, 0x00, 0x00, 0x00, 0x00, 0x8E, 0x00, 0x13, 0x0B],
|
||||
0x00AF: [0x00, 0x13, 0x0B, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x26, 0x02, 0x21, 0x00, 0x05, 0x02],
|
||||
0x00B0: [0x00, 0x26, 0x02, 0x21, 0x00, 0x05, 0x02, 0x08, 0x00, 0x00, 0x40, 0xC0, 0x00, 0x11],
|
||||
0x00B1: [0x00, 0x11, 0x0C, 0x1D, 0x00, 0x00, 0x00, 0x02, 0x00, 0xB2, 0xC0, 0x11, 0x0C, 0x1D],
|
||||
0x00B2: [0xC0, 0x11, 0x0C, 0x1D, 0x00, 0x03, 0x0E, 0xC0, 0x11, 0x0C, 0x1D, 0x00, 0x27, 0x00],
|
||||
0x00B3: [0xC0, 0x11, 0x0C, 0x1D, 0x00, 0x27, 0x00, 0x00, 0x19, 0x0D, 0x17, 0x00, 0x00, 0x00],
|
||||
0x00B4: [0x00, 0x19, 0x0D, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC4, 0x01, 0x18, 0x0D],
|
||||
0x00B5: [0x01, 0x18, 0x0D, 0x25, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x18, 0x0D],
|
||||
0x00B6: [0x00, 0x18, 0x0D, 0x1E, 0x00, 0x04, 0x3C, 0x00, 0x00, 0x00, 0x15, 0x00, 0x0B, 0x05],
|
||||
0x00B7: [0x00, 0x18, 0x0D, 0x1E, 0x00, 0x00, 0x00, 0x20, 0x18, 0x0D, 0x26, 0x00, 0x00, 0x00],
|
||||
0x00B8: [0x00, 0x0B, 0x05, 0x08, 0x00, 0x27, 0x00, 0xC0, 0x0B, 0x05, 0x08, 0x00, 0x00, 0x00],
|
||||
0x00B9: [0xC0, 0x0B, 0x05, 0x08, 0x00, 0x00, 0x00, 0x01, 0x0B, 0x05, 0x08, 0x00, 0x17, 0x00],
|
||||
0x00BA: [0x01, 0x0B, 0x05, 0x08, 0x00, 0x17, 0x00, 0x40, 0x17, 0x0A, 0x1B, 0x00, 0x00, 0x00],
|
||||
0x00BB: [0x40, 0x17, 0x0A, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x17, 0x0A, 0x1B, 0x00, 0x17, 0x00],
|
||||
0x00BC: [0x00, 0x17, 0x0A, 0x1B, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x45, 0x00, 0x13, 0x0B],
|
||||
0x00BD: [0x00, 0x13, 0x0B, 0x29, 0x00, 0x16, 0x00, 0x00, 0x00, 0x4F, 0x9E, 0x00, 0x13, 0x0B],
|
||||
0x00BE: [0x00, 0x13, 0x0B, 0x29, 0x00, 0x16, 0x00, 0x00, 0x00, 0x4F, 0x9E, 0x00, 0x13, 0x0B],
|
||||
0x00BF: [0x00, 0x13, 0x0B, 0x29, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x27, 0x00, 0x02, 0x0F],
|
||||
0x00C0: [0x01, 0x00, 0x02, 0x27, 0x00, 0x02, 0x0F, 0x00, 0x00, 0x00, 0xB0, 0xD0, 0x00, 0x11],
|
||||
0x00C1: [0x00, 0x11, 0x0C, 0x1D, 0x00, 0x33, 0x00, 0xC0, 0x11, 0x0C, 0x1D, 0x00, 0x27, 0x00],
|
||||
0x00C2: [0xC0, 0x11, 0x0C, 0x1D, 0x00, 0x27, 0x00, 0xC0, 0x11, 0x0C, 0x1D, 0x00, 0x00, 0x00],
|
||||
0x00C3: [0xC0, 0x11, 0x0C, 0x1D, 0x00, 0x00, 0x00, 0x00, 0x18, 0x0D, 0x25, 0x00, 0x00, 0x00],
|
||||
0x00C4: [0x00, 0x18, 0x0D, 0x25, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB4, 0x00, 0x18, 0x0D],
|
||||
0x00C5: [0x00, 0x18, 0x0D, 0x25, 0x00, 0x00, 0x00, 0x00, 0x18, 0x0D, 0x1E, 0x00, 0x33, 0x00],
|
||||
0x00C6: [0x00, 0x18, 0x0D, 0x1E, 0x00, 0x00, 0x00, 0x20, 0x18, 0x0D, 0x26, 0x00, 0x00, 0x00],
|
||||
0x00C7: [0x00, 0x18, 0x0D, 0x1E, 0x00, 0x33, 0x00, 0x00, 0x0B, 0x05, 0x09, 0x00, 0x15, 0x25],
|
||||
0x00C8: [0x00, 0x0B, 0x05, 0x09, 0x00, 0x15, 0x25, 0x00, 0x0B, 0x05, 0x08, 0x00, 0x17, 0x00],
|
||||
0x00C9: [0x00, 0x0B, 0x05, 0x08, 0x00, 0x17, 0x00, 0xC0, 0x17, 0x0A, 0x1B, 0x00, 0x00, 0x00],
|
||||
0x00CA: [0xC0, 0x17, 0x0A, 0x1B, 0x00, 0x00, 0x00, 0x20, 0x13, 0x0B, 0x29, 0x00, 0x14, 0x00],
|
||||
0x00CB: [0xC0, 0x17, 0x0A, 0x1B, 0x00, 0x00, 0x00, 0x20, 0x13, 0x0B, 0x29, 0x00, 0x14, 0x00],
|
||||
0x00CC: [0xC0, 0x17, 0x0A, 0x1B, 0x00, 0x00, 0x00, 0x20, 0x13, 0x0B, 0x29, 0x00, 0x14, 0x00],
|
||||
0x00CD: [0x20, 0x13, 0x0B, 0x29, 0x00, 0x14, 0x00, 0x00, 0x00, 0xDE, 0x01, 0x00, 0x02, 0x21],
|
||||
0x00CE: [0x20, 0x13, 0x0B, 0x29, 0x00, 0x14, 0x00, 0x00, 0x00, 0xDE, 0x01, 0x00, 0x02, 0x21],
|
||||
0x00CF: [0x01, 0x00, 0x02, 0x21, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xE0, 0x00, 0x11],
|
||||
0x00D0: [0x01, 0x00, 0x02, 0x21, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xE0, 0x00, 0x11],
|
||||
0x00D1: [0x00, 0x11, 0x0C, 0x1D, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB1, 0x97, 0x00, 0x11, 0x0C],
|
||||
0x00D2: [0x00, 0x11, 0x0C, 0x1D, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x98, 0x00, 0x0B, 0x05],
|
||||
0x00D3: [0x00, 0x0B, 0x05, 0x08, 0x00, 0x06, 0x00, 0x00, 0x0B, 0x05, 0x08, 0x00, 0x17, 0x00],
|
||||
0x00D4: [0x00, 0x0B, 0x05, 0x08, 0x00, 0x06, 0x00, 0x00, 0x0B, 0x05, 0x08, 0x00, 0x17, 0x00],
|
||||
0x00D5: [0x00, 0x18, 0x0D, 0x25, 0x00, 0x00, 0x00, 0x00, 0x18, 0x0D, 0x1E, 0x00, 0x33, 0x00],
|
||||
0x00D6: [0x00, 0x18, 0x0D, 0x1E, 0x00, 0x00, 0x00, 0x20, 0x18, 0x0D, 0x26, 0x00, 0x00, 0x00],
|
||||
0x00D7: [0x00, 0x0B, 0x05, 0x08, 0x00, 0x06, 0x00, 0x00, 0x0B, 0x05, 0x08, 0x00, 0x17, 0x00],
|
||||
0x00D8: [0x00, 0x0B, 0x05, 0x08, 0x00, 0x06, 0x00, 0x00, 0x0B, 0x05, 0x08, 0x00, 0x17, 0x00],
|
||||
0x00D9: [0x00, 0x0B, 0x05, 0x08, 0x00, 0x17, 0x00, 0x00, 0x0B, 0x05, 0x08, 0x00, 0x17, 0x00],
|
||||
0x00DA: [0x00, 0x0B, 0x05, 0x08, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x99, 0xE0, 0x14, 0x0B],
|
||||
0x00DB: [0xC0, 0x17, 0x0A, 0x1B, 0x00, 0x00, 0x00, 0x20, 0x13, 0x0B, 0x29, 0x00, 0x14, 0x00],
|
||||
0x00DC: [0xC0, 0x17, 0x0A, 0x1B, 0x00, 0x00, 0x00, 0x20, 0x13, 0x0B, 0x29, 0x00, 0x14, 0x00],
|
||||
0x00DD: [0xE0, 0x14, 0x0B, 0x16, 0x00, 0x25, 0x00, 0xC0, 0x20, 0x06, 0x13, 0x00, 0x00, 0x00],
|
||||
0x00DE: [0xE0, 0x14, 0x0B, 0x16, 0x00, 0x25, 0x00, 0xC0, 0x20, 0x06, 0x13, 0x00, 0x00, 0x00],
|
||||
0x00DF: [0xC0, 0x20, 0x06, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xEF, 0x00, 0x26, 0x02],
|
||||
0x00E0: [0x00, 0x26, 0x02, 0x21, 0x00, 0x01, 0x2A, 0x00, 0x00, 0x00, 0xD0, 0xC0, 0x07, 0x06],
|
||||
0x00E1: [0xC0, 0x07, 0x06, 0x28, 0x00, 0x00, 0x00, 0x00, 0x20, 0x06, 0x13, 0x00, 0x00, 0x00],
|
||||
0x00E2: [0x00, 0x20, 0x06, 0x13, 0x00, 0x00, 0x00, 0xC0, 0x20, 0x06, 0x09, 0x00, 0x00, 0x00],
|
||||
0x00E3: [0xC0, 0x20, 0x06, 0x09, 0x00, 0x00, 0x00, 0x01, 0x07, 0x14, 0x01, 0x00, 0x00, 0x00],
|
||||
0x00E4: [0x01, 0x07, 0x14, 0x01, 0x00, 0x00, 0x00, 0x01, 0x07, 0x06, 0x01, 0x00, 0x00, 0x00],
|
||||
0x00E5: [0x01, 0x07, 0x14, 0x01, 0x00, 0x00, 0x00, 0x01, 0x07, 0x06, 0x01, 0x00, 0x00, 0x00],
|
||||
0x00E6: [0x01, 0x07, 0x06, 0x01, 0x00, 0x00, 0x00, 0x20, 0x07, 0x06, 0x13, 0x00, 0x00, 0x00],
|
||||
0x00E7: [0x01, 0x07, 0x06, 0x01, 0x00, 0x00, 0x00, 0x20, 0x07, 0x06, 0x13, 0x00, 0x00, 0x00],
|
||||
0x00E8: [0x20, 0x07, 0x06, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8],
|
||||
0x00E9: [0x20, 0x20, 0x06, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFA, 0xFA, 0x20, 0x07, 0x06],
|
||||
0x00EA: [0x20, 0x20, 0x06, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFA, 0xFA, 0x20, 0x07, 0x06],
|
||||
0x00EB: [0x20, 0x07, 0x06, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFB, 0xFB, 0x20, 0x20, 0x06],
|
||||
0x00EC: [0x20, 0x20, 0x06, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0xFD, 0xFD, 0x20, 0x20],
|
||||
0x00ED: [0x20, 0x20, 0x06, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0xFD, 0xFD, 0x20, 0x20],
|
||||
0x00EE: [0x20, 0x20, 0x06, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x20, 0x20, 0x06, 0x13],
|
||||
0x00EF: [0x20, 0x20, 0x06, 0x13, 0x00, 0x02, 0x00, 0x08, 0x00, 0xFF, 0xDF, 0xFF, 0x00, 0x02],
|
||||
0x00F0: [0x01, 0x07, 0x06, 0x01, 0x00, 0x00, 0x00, 0x20, 0x07, 0x06, 0x13, 0x00, 0x00, 0x00],
|
||||
0x00F1: [0x01, 0x07, 0x06, 0x01, 0x00, 0x00, 0x00, 0x20, 0x07, 0x06, 0x13, 0x00, 0x00, 0x00],
|
||||
0x00F2: [0x00, 0x02, 0x03, 0x05, 0x00, 0x00, 0x02, 0x03, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x07],
|
||||
0x00F3: [0x00, 0x02, 0x03, 0x05, 0x00, 0x00, 0x02, 0x03, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x07],
|
||||
0x00F4: [0x00, 0x02, 0x03, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x07, 0x06, 0x13, 0x00, 0x00, 0x00],
|
||||
0x00F5: [0x00, 0x02, 0x03, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x07, 0x06, 0x13, 0x00, 0x00, 0x00],
|
||||
0x00F6: [0x00, 0x07, 0x06, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE8, 0xE8, 0xE8, 0xE8],
|
||||
0x00F7: [0x00, 0x07, 0x06, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE8, 0xE8, 0xE8, 0xE8],
|
||||
0x00F8: [0x00, 0x07, 0x06, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE8, 0xE8, 0xE8, 0xE8],
|
||||
0x00F9: [0x00, 0x20, 0x06, 0x13, 0x00, 0x00, 0x00, 0xC0, 0x20, 0x06, 0x13, 0x00, 0x00, 0x00],
|
||||
0x00FA: [0xC0, 0x20, 0x06, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xEA, 0x00, 0x07, 0x06],
|
||||
0x00FB: [0x00, 0x07, 0x06, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xEB, 0x00, 0x20, 0x06],
|
||||
0x00FC: [0x00, 0x20, 0x06, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xED, 0xED, 0x00, 0x07],
|
||||
0x00FD: [0x00, 0x20, 0x06, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xED, 0xED, 0x00, 0x07],
|
||||
0x00FE: [0x00, 0x20, 0x06, 0x13, 0x00, 0x00, 0x00, 0xC0, 0x20, 0x06, 0x13, 0x00, 0x00, 0x00],
|
||||
0x00FF: [0x00, 0x07, 0x06, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xEF, 0x00, 0x05, 0x03],
|
||||
0x0100: [0x00, 0x05, 0x03, 0x28, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x03, 0x05, 0x00, 0x00, 0x00],
|
||||
0x0101: [0x00, 0x02, 0x03, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x15, 0x03, 0x0D, 0x00, 0x00, 0x00],
|
||||
0x0102: [0x00, 0x15, 0x03, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x05, 0x03, 0x0F, 0x00, 0x00, 0x00],
|
||||
0x0103: [0x00, 0x05, 0x03, 0x0F, 0x00, 0x00, 0x00, 0x01, 0x15, 0x03, 0x0D, 0x00, 0x00, 0x00],
|
||||
0x0104: [0x01, 0x15, 0x03, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x0F, 0x10, 0x00, 0x00, 0x00],
|
||||
0x0105: [0x00, 0x1C, 0x0F, 0x10, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x03, 0x0F, 0x00, 0x00, 0x00],
|
||||
0x0106: [0x00, 0x1F, 0x03, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x02, 0x03, 0x01, 0x00, 0x00, 0x00],
|
||||
0x0107: [0x00, 0x02, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x02, 0x03, 0x0E, 0x00, 0x00, 0x00],
|
||||
0x0108: [0x00, 0x02, 0x03, 0x0E, 0x00, 0x00, 0x00, 0x01, 0x05, 0x03, 0x05, 0x00, 0x00, 0x00],
|
||||
0x0109: [0x01, 0x05, 0x03, 0x05, 0x00, 0x00, 0x00, 0x01, 0x07, 0x06, 0x10, 0x00, 0x00, 0x00],
|
||||
0x010A: [0x01, 0x07, 0x06, 0x10, 0x00, 0x00, 0x00, 0x80, 0x0A, 0x08, 0x08, 0x00, 0x00, 0x1A],
|
||||
0x010B: [0x80, 0x0A, 0x08, 0x08, 0x00, 0x00, 0x1A, 0x00, 0x27, 0x06, 0x08, 0x00, 0x03, 0x00],
|
||||
0x010C: [0x00, 0x27, 0x06, 0x08, 0x00, 0x03, 0x00, 0x00, 0x0A, 0x08, 0x11, 0x00, 0x00, 0x00],
|
||||
0x010D: [0x00, 0x0A, 0x08, 0x11, 0x00, 0x00, 0x00, 0x00, 0x07, 0x14, 0x05, 0x00, 0x00, 0x00],
|
||||
0x010E: [0x00, 0x07, 0x14, 0x05, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x11, 0x05, 0x00, 0x00, 0x00],
|
||||
0x010F: [0x00, 0x1F, 0x03, 0x05, 0x00, 0x00, 0x00, 0x00, 0x02, 0x03, 0x0F, 0x00, 0x00, 0x00],
|
||||
0x0110: [0x00, 0x1F, 0x03, 0x05, 0x00, 0x00, 0x00, 0x00, 0x02, 0x03, 0x0F, 0x00, 0x00, 0x00],
|
||||
0x0111: [0x00, 0x1E, 0x11, 0x05, 0x00, 0x00, 0x00, 0x00, 0x07, 0x14, 0x05, 0x00, 0x00, 0x00],
|
||||
0x0112: [0x00, 0x07, 0x14, 0x05, 0x00, 0x00, 0x00, 0x00, 0x03, 0x10, 0x08, 0x00, 0x00, 0x00],
|
||||
0x0113: [0x00, 0x03, 0x10, 0x08, 0x00, 0x00, 0x00, 0x00, 0x07, 0x06, 0x07, 0x00, 0x00, 0x00],
|
||||
0x0114: [0x00, 0x07, 0x06, 0x07, 0x00, 0x00, 0x00, 0x00, 0x22, 0x12, 0x07, 0x00, 0x00, 0x00],
|
||||
0x0115: [0x00, 0x07, 0x06, 0x07, 0x00, 0x00, 0x00, 0x00, 0x22, 0x12, 0x07, 0x00, 0x00, 0x00],
|
||||
0x0116: [0x00, 0x22, 0x12, 0x07, 0x00, 0x00, 0x00, 0x00, 0x20, 0x14, 0x05, 0x00, 0x00, 0x00],
|
||||
0x0117: [0x00, 0x20, 0x14, 0x05, 0x00, 0x00, 0x00, 0xE0, 0x23, 0x0A, 0x0F, 0x00, 0x00, 0x00],
|
||||
0x0118: [0x00, 0x05, 0x03, 0x0F, 0x00, 0x00, 0x00, 0x01, 0x15, 0x03, 0x0D, 0x00, 0x00, 0x00],
|
||||
0x0119: [0xE0, 0x23, 0x0A, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1D, 0x00, 0x1C, 0x0F],
|
||||
0x011A: [0x00, 0x1C, 0x0F, 0x05, 0x00, 0x00, 0x00, 0xC0, 0x07, 0x06, 0x08, 0x00, 0x00, 0x00],
|
||||
0x011B: [0xC0, 0x07, 0x06, 0x08, 0x00, 0x00, 0x00, 0x00, 0x23, 0x0A, 0x0F, 0x00, 0x00, 0x00],
|
||||
0x011C: [0x00, 0x1F, 0x03, 0x05, 0x00, 0x00, 0x00, 0x00, 0x02, 0x03, 0x0F, 0x00, 0x00, 0x00],
|
||||
0x011D: [0x00, 0x23, 0x0A, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0x00, 0x20, 0x06],
|
||||
0x011E: [0x00, 0x20, 0x06, 0x2A, 0x00, 0x00, 0x00, 0x00, 0x05, 0x03, 0x05, 0x00, 0x00, 0x00],
|
||||
0x011F: [0x00, 0x05, 0x03, 0x05, 0x00, 0x00, 0x00, 0x00, 0x13, 0x06, 0x13, 0x00, 0x00, 0x00],
|
||||
0x0120: [0x00, 0x13, 0x06, 0x13, 0x00, 0x00, 0x00, 0x00, 0x07, 0x06, 0x28, 0x00, 0x03, 0x00],
|
||||
0x0121: [0x00, 0x1E, 0x11, 0x05, 0x00, 0x00, 0x00, 0x00, 0x07, 0x14, 0x05, 0x00, 0x00, 0x00],
|
||||
0x0122: [0x00, 0x1E, 0x11, 0x05, 0x00, 0x00, 0x00, 0x00, 0x07, 0x14, 0x05, 0x00, 0x00, 0x00],
|
||||
0x0123: [0x00, 0x07, 0x06, 0x28, 0x00, 0x03, 0x00, 0x00, 0x07, 0x06, 0x28, 0x00, 0x00, 0x00],
|
||||
0x0124: [0x00, 0x07, 0x06, 0x28, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF],
|
||||
0x0125: [0x00, 0x07, 0x06, 0x28, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF],
|
||||
0x0126: [0x00, 0x07, 0x06, 0x28, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF],
|
||||
0x0127: [0x00, 0x20, 0x06, 0x2A, 0x00, 0x00, 0x00, 0x00, 0x05, 0x03, 0x05, 0x00, 0x00, 0x00],
|
||||
0x0128: [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF],
|
||||
0x0129: [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF],
|
||||
0x012A: [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF],
|
||||
0x012B: [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF],
|
||||
0x012C: [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF],
|
||||
0x012D: [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF],
|
||||
0x012E: [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF]
|
||||
}
|
||||
|
||||
|
||||
class RoomHeader:
|
||||
def __init__(self, room_id, byte_array):
|
||||
self.room_id = room_id
|
||||
|
||||
# todo: the rest of the header
|
||||
self.byte_0 = byte_array[0] # bg2, collision, lights out
|
||||
self.sprite_sheet = byte_array[3] # sprite gfx #
|
||||
self.effect = byte_array[4]
|
||||
|
||||
def write_to_rom(self, rom, base_address):
|
||||
room_offest = self.room_id*14
|
||||
rom.write_byte(base_address + room_offest + 0, self.byte_0)
|
||||
rom.write_byte(base_address + room_offest + 3, self.sprite_sheet)
|
||||
rom.write_byte(base_address + room_offest + 4, self.effect)
|
||||
|
||||
|
||||
def init_room_headers():
|
||||
header_table = {}
|
||||
for room_id, header_bytes in vanilla_headers.items():
|
||||
header_table[room_id] = RoomHeader(room_id, header_bytes)
|
||||
return header_table
|
||||
|
||||
@@ -1,34 +1,505 @@
|
||||
try:
|
||||
from fast_enum import FastEnum
|
||||
except ImportError:
|
||||
from enum import IntFlag as FastEnum
|
||||
|
||||
|
||||
from RoomData import DoorKind, Position
|
||||
from source.dungeon.RoomObject import RoomObject, DoorObject
|
||||
|
||||
|
||||
class Room:
|
||||
|
||||
def __init__(self, layout, layer1, layer2, doors):
|
||||
def __init__(self, layout, layer1, layer2, doors, layer3=None):
|
||||
self.layout = layout
|
||||
self.layer1 = layer1
|
||||
self.layer2 = layer2
|
||||
self.layer3 = layer3
|
||||
self.doors = doors
|
||||
|
||||
def write_to_rom(self, address, rom):
|
||||
offset = 0
|
||||
rom.write_bytes(address, self.layout)
|
||||
address += 2
|
||||
offset += 2
|
||||
for obj in self.layer1:
|
||||
rom.write_bytes(address, obj.data)
|
||||
address += 3
|
||||
rom.write_bytes(address, [0xFF, 0xFF])
|
||||
address += 2
|
||||
rom.write_bytes(address + offset, obj.data)
|
||||
offset += 3
|
||||
rom.write_bytes(address + offset, [0xFF, 0xFF])
|
||||
offset += 2
|
||||
for obj in self.layer2:
|
||||
rom.write_bytes(address, obj.data)
|
||||
address += 3
|
||||
rom.write_bytes(address, [0xFF, 0xFF, 0xF0, 0xFF])
|
||||
address += 4
|
||||
rom.write_bytes(address + offset, obj.data)
|
||||
offset += 3
|
||||
rom.write_bytes(address + offset, [0xFF, 0xFF])
|
||||
offset += 2
|
||||
if self.layer3:
|
||||
for obj in self.layer3:
|
||||
rom.write_bytes(address + offset, obj.data)
|
||||
offset += 3
|
||||
rom.write_bytes(address + offset, [0xF0, 0xFF])
|
||||
offset += 2
|
||||
door_start = offset
|
||||
for door in self.doors:
|
||||
rom.write_bytes(address, door.get_bytes())
|
||||
address += 2
|
||||
rom.write_bytes(address, [0xFF, 0xFF])
|
||||
return address + 2 # where the data ended
|
||||
rom.write_bytes(address + offset, door.get_bytes())
|
||||
offset += 2
|
||||
rom.write_bytes(address + offset, [0xFF, 0xFF])
|
||||
return door_start, offset + 2 # how many bytes were written
|
||||
|
||||
def find_all_pots(self):
|
||||
pots = []
|
||||
pots.extend([x for x in self.layer1 if x.data[2] in {0xFA, 0xFB} and not x.dummy])
|
||||
pots.extend([x for x in self.layer2 if x.data[2] in {0xFA, 0xFB} and not x.dummy])
|
||||
if self.layer3:
|
||||
pots.extend([x for x in self.layer3 if x.data[2] in {0xFA, 0xFB} and not x.dummy])
|
||||
return pots
|
||||
|
||||
|
||||
|
||||
Room0006 = Room([0xE1, 0x00],
|
||||
[RoomObject(0x1FA15C, [0x1B, 0xA3, 0xC8]),
|
||||
RoomObject(0x1FA15F, [0x58, 0xA3, 0xC8]),
|
||||
RoomObject(0x1FA162, [0x1B, 0xD8, 0xC8]),
|
||||
RoomObject(0x1FA165, [0x58, 0xD8, 0xC8]),
|
||||
RoomObject(0x1FA168, [0x17, 0x9F, 0x3F]),
|
||||
RoomObject(0x1FA16B, [0x54, 0x9F, 0x3F]),
|
||||
RoomObject(0x1FA16E, [0x17, 0xA3, 0x79]),
|
||||
RoomObject(0x1FA171, [0x14, 0xE1, 0x79]),
|
||||
RoomObject(0x1FA174, [0x17, 0xEB, 0x40]),
|
||||
RoomObject(0x1FA177, [0x54, 0xEB, 0x40]),
|
||||
RoomObject(0x1FA17A, [0x6B, 0xA3, 0x7A]),
|
||||
RoomObject(0x1FA17D, [0x68, 0xE1, 0x7A]),
|
||||
RoomObject(0x1FA180, [0x21, 0x90, 0xF8]),
|
||||
RoomObject(0x1FA183, [0x51, 0x90, 0xF8]),
|
||||
RoomObject(0x1FA186, [0x0C, 0xA5, 0x7F]),
|
||||
RoomObject(0x1FA189, [0x6C, 0xA5, 0x80])],
|
||||
[], [DoorObject(Position.SouthW, DoorKind.Trap)])
|
||||
|
||||
|
||||
Room0007 = Room([0x81, 0x1C],
|
||||
[RoomObject(0x1FCAF0, [0x0A, 0x4E, 0x0D]),
|
||||
RoomObject(0x1FCAF3, [0x0A, 0xAA, 0x0E]),
|
||||
RoomObject(0x1FCAF6, [0x0B, 0x51, 0x61]),
|
||||
RoomObject(0x1FCAF9, [0xC0, 0x2C, 0xA2]),
|
||||
RoomObject(0x1FCAFC, [0xB0, 0x20, 0x0F]),
|
||||
RoomObject(0x1FCAFF, [0xB0, 0x22, 0x62]),
|
||||
RoomObject(0x1FCB02, [0xFE, 0xC1, 0x02]),
|
||||
RoomObject(0x1FCB05, [0xC9, 0x38, 0x01]),
|
||||
RoomObject(0x1FCB08, [0xFF, 0xA3, 0x82]),
|
||||
RoomObject(0x1FCB0B, [0xBA, 0xE6, 0x10]),
|
||||
RoomObject(0x1FCB0E, [0xE8, 0xAA, 0x62]),
|
||||
RoomObject(0x1FCB11, [0xFF, 0x43, 0xB9]),
|
||||
RoomObject(0x1FCB14, [0x53, 0x53, 0xE0]),
|
||||
RoomObject(0x1FCB17, [0x91, 0x53, 0xE0]),
|
||||
RoomObject(0x1FCB1A, [0x53, 0x91, 0xE0]),
|
||||
RoomObject(0x1FCB1D, [0x91, 0x91, 0xE0]),
|
||||
RoomObject(0x1FCB20, [0x3C, 0x6B, 0xC2]),
|
||||
RoomObject(0x1FCB23, [0x3D, 0x9B, 0xC3]),
|
||||
RoomObject(0x1FCB26, [0x54, 0xA6, 0xC3]),
|
||||
RoomObject(0x1FCB29, [0x5C, 0xAA, 0xC3]),
|
||||
RoomObject(0x1FCB2C, [0x68, 0xB1, 0xC3]),
|
||||
RoomObject(0x1FCB2F, [0x75, 0xB0, 0xC3]),
|
||||
RoomObject(0x1FCB32, [0x8F, 0xB1, 0xC3]),
|
||||
RoomObject(0x1FCB35, [0x9B, 0xAA, 0xC3]),
|
||||
RoomObject(0x1FCB38, [0xA6, 0xA0, 0xC3]),
|
||||
RoomObject(0x1FCB3B, [0xAD, 0x98, 0xC3]),
|
||||
RoomObject(0x1FCB3E, [0xB4, 0x6A, 0xC2]),
|
||||
RoomObject(0x1FCB41, [0x51, 0x3D, 0xC3]),
|
||||
RoomObject(0x1FCB44, [0x45, 0x49, 0xC3]),
|
||||
RoomObject(0x1FCB47, [0x3D, 0x51, 0xC3]),
|
||||
RoomObject(0x1FCB4A, [0x9C, 0x39, 0xC2]),
|
||||
RoomObject(0x1FCB4D, [0xA1, 0x49, 0xC3]),
|
||||
RoomObject(0x1FCB50, [0xAD, 0x51, 0xC3]),
|
||||
RoomObject(0x1FCB53, [0x3A, 0x50, 0x8A]),
|
||||
RoomObject(0x1FCB56, [0x38, 0x50, 0x22]),
|
||||
RoomObject(0x1FCB59, [0x44, 0x44, 0x69]),
|
||||
RoomObject(0x1FCB5C, [0x44, 0x44, 0x22]),
|
||||
RoomObject(0x1FCB5F, [0x58, 0x13, 0x05]),
|
||||
RoomObject(0x1FCB62, [0x60, 0x15, 0x55]),
|
||||
RoomObject(0x1FCB65, [0x78, 0x10, 0x3A]),
|
||||
RoomObject(0x1FCB68, [0x08, 0x5B, 0x65]),
|
||||
RoomObject(0x1FCB6B, [0x0C, 0x61, 0x7F]),
|
||||
RoomObject(0x1FCB6E, [0xC8, 0x39, 0x05]),
|
||||
RoomObject(0x1FCB71, [0xE8, 0x5B, 0x66]),
|
||||
RoomObject(0x1FCB74, [0xEC, 0x4A, 0x80]),
|
||||
RoomObject(0x1FCB77, [0x58, 0xEB, 0x06]),
|
||||
RoomObject(0x1FCB7A, [0x60, 0xED, 0x56]),
|
||||
RoomObject(0x1FCB7D, [0x78, 0xEC, 0x3B]),
|
||||
RoomObject(0x1FCB80, [0x50, 0x38, 0x69]),
|
||||
RoomObject(0x1FCB83, [0x50, 0x38, 0x5F]),
|
||||
RoomObject(0x1FCB86, [0xA8, 0x38, 0x69]),
|
||||
RoomObject(0x1FCB89, [0xA8, 0x44, 0x22]),
|
||||
RoomObject(0x1FCB8C, [0xB4, 0x44, 0x69]),
|
||||
RoomObject(0x1FCB8F, [0xB4, 0x51, 0x22]),
|
||||
RoomObject(0x1FCB92, [0xC6, 0x50, 0x8A]),
|
||||
RoomObject(0x1FCB95, [0x3B, 0xC8, 0x22]),
|
||||
RoomObject(0x1FCB98, [0x8B, 0xC8, 0x22]),
|
||||
RoomObject(0x1FCB9B, [0x74, 0xBC, 0x69]),
|
||||
RoomObject(0x1FCB9E, [0x88, 0xBC, 0x69]),
|
||||
RoomObject(0x1FCBA1, [0x63, 0x3C, 0xC2]),
|
||||
RoomObject(0x1FCBA4, [0x66, 0x4F, 0x29]),
|
||||
RoomObject(0x1FCBA7, [0x64, 0x50, 0x6B]),
|
||||
RoomObject(0x1FCBAA, [0x5C, 0x54, 0x2B]),
|
||||
RoomObject(0x1FCBAD, [0x5C, 0x58, 0x6B]),
|
||||
RoomObject(0x1FCBB0, [0x54, 0x5C, 0x2B]),
|
||||
RoomObject(0x1FCBB3, [0x54, 0x60, 0x6B]),
|
||||
RoomObject(0x1FCBB6, [0x4C, 0x64, 0x2B]),
|
||||
RoomObject(0x1FCBB9, [0x4E, 0x6B, 0x6B]),
|
||||
RoomObject(0x1FCBBC, [0x4C, 0x98, 0x2D]),
|
||||
RoomObject(0x1FCBBF, [0x54, 0x9C, 0x6B]),
|
||||
RoomObject(0x1FCBC2, [0x54, 0xA0, 0x2D]),
|
||||
RoomObject(0x1FCBC5, [0x5C, 0xA4, 0x6B]),
|
||||
RoomObject(0x1FCBC8, [0x5C, 0xA8, 0x2D]),
|
||||
RoomObject(0x1FCBCB, [0x64, 0xAC, 0x6B]),
|
||||
RoomObject(0x1FCBCE, [0x66, 0xB3, 0x2A]),
|
||||
RoomObject(0x1FCBD1, [0x98, 0xAC, 0x6A]),
|
||||
RoomObject(0x1FCBD4, [0x98, 0xA8, 0x2E]),
|
||||
RoomObject(0x1FCBD7, [0xA0, 0xA4, 0x6A]),
|
||||
RoomObject(0x1FCBDA, [0xA0, 0xA0, 0x2E]),
|
||||
RoomObject(0x1FCBDD, [0xA8, 0x9C, 0x6A]),
|
||||
RoomObject(0x1FCBE0, [0xA8, 0x98, 0x2E]),
|
||||
RoomObject(0x1FCBE3, [0xB2, 0x6B, 0x6A]),
|
||||
RoomObject(0x1FCBE6, [0xA8, 0x64, 0x2C]),
|
||||
RoomObject(0x1FCBE9, [0xA8, 0x60, 0x6A]),
|
||||
RoomObject(0x1FCBEC, [0xA0, 0x5C, 0x2C]),
|
||||
RoomObject(0x1FCBEF, [0xA0, 0x58, 0x6A]),
|
||||
RoomObject(0x1FCBF2, [0x98, 0x54, 0x2C]),
|
||||
RoomObject(0x1FCBF5, [0x98, 0x50, 0x6A]),
|
||||
RoomObject(0x1FCBF8, [0x68, 0x74, 0xC2]),
|
||||
RoomObject(0x1FCBFB, [0x68, 0x71, 0x27]),
|
||||
RoomObject(0x1FCBFE, [0x68, 0x77, 0x6A]),
|
||||
RoomObject(0x1FCC01, [0x74, 0x77, 0x6B]),
|
||||
RoomObject(0x1FCC04, [0x68, 0x85, 0x28]),
|
||||
RoomObject(0x1FCC07, [0xFC, 0x31, 0x72]),
|
||||
RoomObject(0x1FCC0A, [0x74, 0xAE, 0x04]),
|
||||
RoomObject(0x1FCC0D, [0x71, 0xA0, 0xE0]),
|
||||
RoomObject(0x1FCC10, [0x0A, 0x13, 0xA0]),
|
||||
RoomObject(0x1FCC13, [0x0A, 0xBF, 0xA1]),
|
||||
RoomObject(0x1FCC16, [0xBE, 0xF7, 0xA3]),
|
||||
RoomObject(0x1FCC19, [0xC3, 0x11, 0xC0]),
|
||||
RoomObject(0x1FCC1C, [0xD1, 0x31, 0x00])],
|
||||
[], [])
|
||||
|
||||
Room001C = Room([0xE1, 0x00],
|
||||
[RoomObject(0x1FF74B, [0x2D, 0x32, 0xA4]),
|
||||
RoomObject(0x1FF74E, [0xA9, 0x1E, 0xDC]),
|
||||
RoomObject(0x1FF751, [0xA8, 0x91, 0x3A]),
|
||||
RoomObject(0x1FF754, [0x88, 0xAD, 0x76]),
|
||||
RoomObject(0x1FF757, [0xEC, 0xAD, 0x77]),
|
||||
RoomObject(0x1FF75A, [0xA8, 0x50, 0x3D]),
|
||||
RoomObject(0x1FF75D, [0xD0, 0x50, 0x3D]),
|
||||
RoomObject(0x1FF760, [0x30, 0xA9, 0x3D]),
|
||||
RoomObject(0x1FF763, [0x30, 0xC1, 0x3D]),
|
||||
RoomObject(0x1FF766, [0xFC, 0x69, 0x38]),
|
||||
RoomObject(0x1FF769, [0x97, 0x9F, 0xD1]),
|
||||
RoomObject(0x1FF76C, [0xCD, 0x9F, 0xD1]),
|
||||
RoomObject(0x1FF76F, [0x97, 0xDC, 0xD1]),
|
||||
RoomObject(0x1FF772, [0xCD, 0xDC, 0xD1]),
|
||||
RoomObject(0x1FF775, [0xBD, 0x32, 0xF9]),
|
||||
RoomObject(0x1FF778, [0xB1, 0x22, 0xF9]),
|
||||
RoomObject(0x1FF77B, [0xC9, 0x22, 0xF9]),], [],
|
||||
[DoorObject(Position.InteriorE, DoorKind.TrapTriggerable),
|
||||
DoorObject(Position.InteriorS, DoorKind.Trap), DoorObject(Position.InteriorW, DoorKind.Dashable)])
|
||||
|
||||
|
||||
Room0029 = Room([0xE5, 0x00],
|
||||
[RoomObject(0x1FC188, [0x97, 0x9C, 0xDE]),
|
||||
RoomObject(0x1FC18B, [0xB7, 0x9C, 0xDE]),
|
||||
RoomObject(0x1FC18E, [0xD6, 0x9C, 0xDE]),
|
||||
RoomObject(0x1FC191, [0x97, 0xE4, 0xDE]),
|
||||
RoomObject(0x1FC194, [0xB7, 0xE4, 0xDE]),
|
||||
RoomObject(0x1FC197, [0xD6, 0xE4, 0xDE]),
|
||||
RoomObject(0x1FC19A, [0x94, 0xA7, 0xDE]),
|
||||
RoomObject(0x1FC19D, [0x94, 0xC7, 0xDE]),
|
||||
RoomObject(0x1FC1A0, [0xE4, 0xA7, 0xDE]),
|
||||
RoomObject(0x1FC1A3, [0xE4, 0xC7, 0xDE])],
|
||||
[RoomObject(0x1FC1A8, [0x03, 0x03, 0xCA]),
|
||||
RoomObject(0x1FC1AB, [0x43, 0x03, 0xCA]),
|
||||
RoomObject(0x1FC1AE, [0x83, 0x03, 0xCA]),
|
||||
RoomObject(0x1FC1B1, [0xC3, 0x03, 0xCA]),
|
||||
RoomObject(0x1FC1B4, [0x03, 0x43, 0xCA]),
|
||||
RoomObject(0x1FC1B7, [0x43, 0x43, 0xCA]),
|
||||
RoomObject(0x1FC1BA, [0x83, 0x43, 0xCA]),
|
||||
RoomObject(0x1FC1BD, [0xC3, 0x43, 0xCA]),
|
||||
RoomObject(0x1FC1C0, [0x03, 0x83, 0xCA]),
|
||||
RoomObject(0x1FC1C3, [0x43, 0x83, 0xCA]),
|
||||
RoomObject(0x1FC1C6, [0x83, 0x83, 0xCA]),
|
||||
RoomObject(0x1FC1C9, [0xC3, 0x83, 0xCA]),
|
||||
RoomObject(0x1FC1CC, [0x03, 0xC3, 0xCA]),
|
||||
RoomObject(0x1FC1CF, [0x43, 0xC3, 0xCA]),
|
||||
RoomObject(0x1FC1D2, [0x83, 0xC3, 0xCA]),
|
||||
RoomObject(0x1FC1D5, [0xC3, 0xC3, 0xCA])],
|
||||
[], layer3=[RoomObject(0x1FC1DA, [0x9F, 0xA7, 0xC6]),
|
||||
RoomObject(0x1FC1DD, [0xD4, 0xA7, 0xC6]),
|
||||
RoomObject(0x1FC1E0, [0xFE, 0xF9, 0xF4]),
|
||||
RoomObject(0x1FC1E3, [0xFF, 0x1E, 0x74]),
|
||||
RoomObject(0x1FC1E6, [0xFE, 0x5C, 0x74]),
|
||||
RoomObject(0x1FC1E9, [0xFF, 0x9C, 0x74])])
|
||||
|
||||
|
||||
Room0033 = Room([0xE9, 0x00], [], [], [DoorObject(Position.SouthW, DoorKind.Trap)])
|
||||
|
||||
|
||||
Room004D = Room([0x82, 0x1C],
|
||||
[RoomObject(0x1FFD43, [0x09, 0x34, 0x0D]),
|
||||
RoomObject(0x1FFD46, [0x08, 0x3A, 0x61]),
|
||||
RoomObject(0x1FFD49, [0x09, 0xC0, 0x0E]),
|
||||
RoomObject(0x1FFD4C, [0x08, 0xC2, 0x61]),
|
||||
RoomObject(0x1FFD4F, [0xD1, 0x10, 0x0F]),
|
||||
RoomObject(0x1FFD52, [0xE8, 0x3A, 0x62]),
|
||||
RoomObject(0x1FFD55, [0x5E, 0x1C, 0x03]),
|
||||
RoomObject(0x1FFD58, [0x17, 0x49, 0x63]),
|
||||
RoomObject(0x1FFD5B, [0xDF, 0x4B, 0x64]),
|
||||
RoomObject(0x1FFD5E, [0xDC, 0xCA, 0x64]),
|
||||
RoomObject(0x1FFD61, [0xFF, 0x7D, 0xCB]),
|
||||
RoomObject(0x1FFD64, [0x9D, 0xDF, 0x04]),
|
||||
RoomObject(0x1FFD67, [0x3B, 0x5B, 0xE0]),
|
||||
RoomObject(0x1FFD6A, [0x7B, 0x5B, 0xE0]),
|
||||
RoomObject(0x1FFD6D, [0xB8, 0x5B, 0xE0]),
|
||||
RoomObject(0x1FFD70, [0x6A, 0xB1, 0xE0]),
|
||||
RoomObject(0x1FFD73, [0x78, 0x54, 0xC2]),
|
||||
RoomObject(0x1FFD76, [0x5B, 0x2A, 0xC2]),
|
||||
RoomObject(0x1FFD79, [0x98, 0x2A, 0xC2]),
|
||||
RoomObject(0x1FFD7C, [0x21, 0x4B, 0xC3]),
|
||||
RoomObject(0x1FFD7F, [0x21, 0x7B, 0xC3]),
|
||||
RoomObject(0x1FFD82, [0x21, 0xA1, 0xC3]),
|
||||
RoomObject(0x1FFD85, [0x38, 0x7B, 0xC2]),
|
||||
RoomObject(0x1FFD88, [0x48, 0x8A, 0xC2]),
|
||||
RoomObject(0x1FFD8B, [0x3A, 0xAA, 0xC2]),
|
||||
RoomObject(0x1FFD8E, [0x5B, 0x9C, 0xC2]),
|
||||
RoomObject(0x1FFD91, [0xC9, 0x4B, 0xC3]),
|
||||
RoomObject(0x1FFD94, [0xC9, 0x7B, 0xC3]),
|
||||
RoomObject(0x1FFD97, [0xB8, 0x79, 0xC2]),
|
||||
RoomObject(0x1FFD9A, [0xA8, 0x88, 0xC2]),
|
||||
RoomObject(0x1FFD9D, [0x9B, 0x9B, 0xC2]),
|
||||
RoomObject(0x1FFDA0, [0x9B, 0xD0, 0xC2]),
|
||||
RoomObject(0x1FFDA3, [0xD0, 0xA3, 0xC2]),
|
||||
RoomObject(0x1FFDA6, [0x78, 0x8C, 0xC2]),
|
||||
RoomObject(0x1FFDA9, [0x15, 0x45, 0x22]),
|
||||
RoomObject(0x1FFDAC, [0x59, 0x1F, 0x69]),
|
||||
RoomObject(0x1FFDAF, [0xA5, 0x1F, 0x69]),
|
||||
RoomObject(0x1FFDB2, [0xC9, 0x45, 0x22]),
|
||||
RoomObject(0x1FFDB5, [0x68, 0xE4, 0x5E]),
|
||||
RoomObject(0x1FFDB8, [0x15, 0xB9, 0x22]),
|
||||
RoomObject(0x1FFDBB, [0x35, 0xB9, 0x69]),
|
||||
RoomObject(0x1FFDBE, [0x37, 0xD9, 0x22]),
|
||||
RoomObject(0x1FFDC1, [0x88, 0xD9, 0x22]),
|
||||
RoomObject(0x1FFDC4, [0x98, 0xD9, 0x69]),
|
||||
RoomObject(0x1FFDC7, [0x66, 0xCB, 0x2A]),
|
||||
RoomObject(0x1FFDCA, [0x69, 0xC9, 0x04]),
|
||||
RoomObject(0x1FFDCD, [0x79, 0xCB, 0xF9]),
|
||||
RoomObject(0x1FFDD0, [0x8D, 0xBA, 0xF9]),
|
||||
RoomObject(0x1FFDD3, [0x37, 0x57, 0x29]),
|
||||
RoomObject(0x1FFDD6, [0x87, 0x57, 0x29]),
|
||||
RoomObject(0x1FFDD9, [0x78, 0x5A, 0x6A]),
|
||||
RoomObject(0x1FFDDC, [0x84, 0x5A, 0x6B]),
|
||||
RoomObject(0x1FFDDF, [0x78, 0x65, 0x28]),
|
||||
RoomObject(0x1FFDE2, [0x35, 0x5B, 0x6B]),
|
||||
RoomObject(0x1FFDE5, [0x34, 0x7A, 0x2D]),
|
||||
RoomObject(0x1FFDE8, [0x44, 0x7E, 0x6B]),
|
||||
RoomObject(0x1FFDEB, [0x44, 0x8A, 0x2D]),
|
||||
RoomObject(0x1FFDEE, [0x54, 0x8E, 0x6B]),
|
||||
RoomObject(0x1FFDF1, [0x55, 0x9B, 0x2A]),
|
||||
RoomObject(0x1FFDF4, [0x78, 0x8E, 0x6A]),
|
||||
RoomObject(0x1FFDF7, [0x78, 0x89, 0x27]),
|
||||
RoomObject(0x1FFDFA, [0x84, 0x8E, 0x6B]),
|
||||
RoomObject(0x1FFDFD, [0x85, 0x9B, 0x2A]),
|
||||
RoomObject(0x1FFE00, [0xA8, 0x8E, 0x6A]),
|
||||
RoomObject(0x1FFE03, [0xA8, 0x8A, 0x2E]),
|
||||
RoomObject(0x1FFE06, [0xB8, 0x7E, 0x6A]),
|
||||
RoomObject(0x1FFE09, [0xB8, 0x7A, 0x2E]),
|
||||
RoomObject(0x1FFE0C, [0xC9, 0x5B, 0x6A]),
|
||||
RoomObject(0x1FFE0F, [0x66, 0xAF, 0x29]),
|
||||
RoomObject(0x1FFE12, [0x65, 0xB1, 0x6B]),
|
||||
RoomObject(0x1FFE15, [0x99, 0xB1, 0x6A]),
|
||||
RoomObject(0x1FFE18, [0x38, 0x4B, 0x03]),
|
||||
RoomObject(0x1FFE1B, [0xA8, 0x4B, 0x03]),
|
||||
RoomObject(0x1FFE1E, [0x48, 0x13, 0x3A]),
|
||||
RoomObject(0x1FFE21, [0x0C, 0x4A, 0x7F]),
|
||||
RoomObject(0x1FFE24, [0xEC, 0x4A, 0x80]),
|
||||
RoomObject(0x1FFE27, [0xFE, 0xE1, 0x39]),
|
||||
RoomObject(0x1FFE2A, [0x09, 0x11, 0xA0]),
|
||||
RoomObject(0x1FFE2D, [0xD5, 0x11, 0xA2]),
|
||||
RoomObject(0x1FFE30, [0x09, 0xD5, 0xA1])],
|
||||
[RoomObject(0x1FFE35, [0x5B, 0x19, 0xDB]),
|
||||
RoomObject(0x1FFE38, [0x98, 0x19, 0xDB]),
|
||||
RoomObject(0x1FFE3B, [0x11, 0x4B, 0xDB]),
|
||||
RoomObject(0x1FFE3E, [0x11, 0x8A, 0xDB]),
|
||||
RoomObject(0x1FFE41, [0x39, 0x48, 0xDB]),
|
||||
RoomObject(0x1FFE44, [0xA9, 0x48, 0xDB]),
|
||||
RoomObject(0x1FFE47, [0xD9, 0x4B, 0xDB]),
|
||||
RoomObject(0x1FFE4A, [0xD9, 0x8B, 0xDB]),
|
||||
RoomObject(0x1FFE4D, [0x6A, 0xC8, 0xDB]),
|
||||
RoomObject(0x1FFE50, [0x9B, 0xCA, 0xDB]),
|
||||
RoomObject(0x1FFE53, [0xD9, 0xCA, 0xDB])],
|
||||
[DoorObject(Position.NorthW, DoorKind.SmallKey), DoorObject(Position.WestS, DoorKind.Normal)])
|
||||
|
||||
Room005A = Room([0xE9, 0x00],
|
||||
[RoomObject(0x1FA7CD, [0xA8, 0xA8, 0xDE]),
|
||||
RoomObject(0x1FA7D0, [0xB0, 0xA0, 0xDE]),
|
||||
RoomObject(0x1FA7D3, [0xB8, 0xA8, 0xDE]),
|
||||
RoomObject(0x1FA7D6, [0xC0, 0xA0, 0xDE]),
|
||||
RoomObject(0x1FA7D9, [0xC8, 0xA8, 0xDE]),
|
||||
RoomObject(0x1FA7DC, [0xD0, 0xA0, 0xDE])],
|
||||
[], [DoorObject(Position.SouthE, DoorKind.Trap)])
|
||||
|
||||
Room006C = Room([0xE2, 0x00],
|
||||
[RoomObject(0x1FFA58, [0x17, 0x9F, 0xE8]),
|
||||
RoomObject(0x1FFA5B, [0x4D, 0x9F, 0xE8]),
|
||||
RoomObject(0x1FFA5E, [0x17, 0xDC, 0xE8]),
|
||||
RoomObject(0x1FFA61, [0x4D, 0xDC, 0xE8]),
|
||||
RoomObject(0x1FFA64, [0x18, 0xE1, 0xFE]),
|
||||
RoomObject(0x1FFA67, [0x88, 0xAD, 0x76]),
|
||||
RoomObject(0x1FFA6A, [0x99, 0xBC, 0x33]),
|
||||
RoomObject(0x1FFA6D, [0x9B, 0xBB, 0x34]),
|
||||
RoomObject(0x1FFA70, [0x9B, 0xCF, 0x34]),
|
||||
RoomObject(0x1FFA73, [0xD8, 0xB8, 0x34]),
|
||||
RoomObject(0x1FFA76, [0xD8, 0xCC, 0x34]),
|
||||
RoomObject(0x1FFA79, [0xAF, 0xAA, 0xFE]),
|
||||
RoomObject(0x1FFA7C, [0xC7, 0xAA, 0xFE]),
|
||||
RoomObject(0x1FFA7F, [0xAF, 0xD2, 0xFE]),
|
||||
RoomObject(0x1FFA82, [0xC7, 0xD2, 0xFE]),
|
||||
RoomObject(0x1FFA85, [0x28, 0x11, 0x3A]),
|
||||
RoomObject(0x1FFA88, [0x28, 0x91, 0x3A]),
|
||||
RoomObject(0x1FFA8B, [0xFC, 0xE1, 0x38]),
|
||||
RoomObject(0x1FFA8E, [0x2B, 0x33, 0xFA]),
|
||||
RoomObject(0x1FFA91, [0x53, 0x33, 0xFA]),
|
||||
RoomObject(0x1FFA94, [0x2B, 0x53, 0xFA]),
|
||||
RoomObject(0x1FFA97, [0x53, 0x53, 0xFA])], [],
|
||||
[DoorObject(Position.InteriorS, DoorKind.Trap2), DoorObject(Position.InteriorW, DoorKind.Trap),
|
||||
DoorObject(Position.EastS, DoorKind.Normal)])
|
||||
|
||||
Room0090 = Room([0xE1, 0x00],
|
||||
[RoomObject(0x1FBAA0, [0x28, 0xEC, 0x56]),
|
||||
RoomObject(0x1FBAA3, [0x48, 0xEC, 0x56]),
|
||||
RoomObject(0x1FBAA6, [0x1B, 0xA2, 0xFF])],
|
||||
[RoomObject(0x1FBAAB, [0x16, 0x9C, 0xFE])], [DoorObject(Position.SouthW, DoorKind.Trap)])
|
||||
|
||||
Room00A4 = Room([0xE1, 0x00],
|
||||
[RoomObject(0x1FE702, [0xFC, 0x08, 0x00]),
|
||||
RoomObject(0x1FE705, [0x13, 0x80, 0x01]),
|
||||
RoomObject(0x1FE708, [0xFD, 0xC8, 0x02]),
|
||||
RoomObject(0x1FE70B, [0x02, 0x93, 0x61]),
|
||||
RoomObject(0x1FE70E, [0xFC, 0x0E, 0x81]),
|
||||
RoomObject(0x1FE711, [0x13, 0xE8, 0x02]),
|
||||
RoomObject(0x1FE714, [0xFD, 0xCE, 0x83]),
|
||||
RoomObject(0x1FE717, [0x72, 0x93, 0x62]),
|
||||
RoomObject(0x1FE71A, [0x13, 0x93, 0xC4]),
|
||||
RoomObject(0x1FE71D, [0x51, 0x93, 0xC4]),
|
||||
RoomObject(0x1FE720, [0x51, 0xC9, 0xC4]),
|
||||
RoomObject(0x1FE723, [0x10, 0xC9, 0xC4]),
|
||||
RoomObject(0x1FE726, [0x0E, 0x8D, 0xDE]),
|
||||
RoomObject(0x1FE729, [0x0D, 0x9C, 0xDE]),
|
||||
RoomObject(0x1FE72C, [0x0C, 0xA5, 0xDE]),
|
||||
RoomObject(0x1FE72F, [0x5E, 0x8C, 0xDE]),
|
||||
RoomObject(0x1FE732, [0x65, 0x94, 0xDE]),
|
||||
RoomObject(0x1FE735, [0x6C, 0x9C, 0xDE])],
|
||||
[RoomObject(0x1FE73A, [0x2E, 0x98, 0xFF])], [DoorObject(Position.SouthW, DoorKind.Trap)])
|
||||
|
||||
Room00AC = Room([0xE9, 0x00],
|
||||
[RoomObject(0x1FD9B1, [0x88, 0xA4, 0x0D]),
|
||||
RoomObject(0x1FD9B4, [0x88, 0xD0, 0x0E]),
|
||||
RoomObject(0x1FD9B7, [0xE0, 0x90, 0x0F]),
|
||||
RoomObject(0x1FD9BA, [0xE0, 0xE4, 0x10]),
|
||||
RoomObject(0x1FD9BD, [0x89, 0xAB, 0x61]),
|
||||
RoomObject(0x1FD9C0, [0xE9, 0xAB, 0x62]),
|
||||
RoomObject(0x1FD9C3, [0x88, 0x91, 0xA0]),
|
||||
RoomObject(0x1FD9C6, [0x88, 0xE5, 0xA1]),
|
||||
RoomObject(0x1FD9C9, [0xE4, 0x91, 0xA2]),
|
||||
RoomObject(0x1FD9CC, [0xE4, 0xF5, 0xA3])],
|
||||
[RoomObject(0x1FD9D1, [0xB1, 0xA8, 0xFF])], [DoorObject(Position.SouthE, DoorKind.Trap)])
|
||||
|
||||
Room00C8 = Room([0xE1, 0x00],
|
||||
[RoomObject(0x0A9587, [0x98, 0x92, 0x3A]),
|
||||
RoomObject(0x0A958A, [0x88, 0xAA, 0x65]),
|
||||
RoomObject(0x0A958D, [0xE8, 0xAA, 0x66])], [], [DoorObject(Position.SouthE, DoorKind.Trap)])
|
||||
|
||||
Room00DE = Room([0xE4, 0x00], [], [RoomObject(0x1FCAE5, [0xAD, 0x21, 0xF9])], [])
|
||||
|
||||
Room010C = Room([0xE0, 0x08],
|
||||
[RoomObject(0x03F25D, [0xFC, 0x62, 0x00]),
|
||||
RoomObject(0x03F260, [0x19, 0x33, 0x61]),
|
||||
RoomObject(0x03F263, [0xFC, 0x66, 0x81]),
|
||||
RoomObject(0x03F266, [0x29, 0x22, 0x01]),
|
||||
RoomObject(0x03F269, [0xFD, 0x62, 0x02]),
|
||||
RoomObject(0x03F26C, [0x59, 0x33, 0x62]),
|
||||
RoomObject(0x03F26F, [0xFD, 0x66, 0x83]),
|
||||
RoomObject(0x03F272, [0xFC, 0x89, 0x00]),
|
||||
RoomObject(0x03F275, [0x22, 0xA1, 0x61]),
|
||||
RoomObject(0x03F278, [0xFC, 0x8E, 0x81]),
|
||||
RoomObject(0x03F27B, [0x90, 0xCA, 0x0E]),
|
||||
RoomObject(0x03F27E, [0xD0, 0xE6, 0x10]),
|
||||
RoomObject(0x03F281, [0xFE, 0x41, 0x00]),
|
||||
RoomObject(0x03F284, [0x93, 0x23, 0x61]),
|
||||
RoomObject(0x03F287, [0x92, 0x98, 0x61]),
|
||||
RoomObject(0x03F28A, [0xFF, 0x81, 0x02]),
|
||||
RoomObject(0x03F28D, [0xE3, 0x23, 0x62]),
|
||||
RoomObject(0x03F290, [0xE2, 0x98, 0x62]),
|
||||
RoomObject(0x03F293, [0xFE, 0x71, 0xC8]),
|
||||
RoomObject(0x03F296, [0xAD, 0x1C, 0x03]),
|
||||
RoomObject(0x03F299, [0xFF, 0x51, 0xCA]),
|
||||
RoomObject(0x03F29C, [0x9D, 0x2D, 0x63]),
|
||||
RoomObject(0x03F29F, [0xFE, 0x75, 0x89]),
|
||||
RoomObject(0x03F2A2, [0xAD, 0x58, 0x04]),
|
||||
RoomObject(0x03F2A5, [0xD5, 0x2D, 0x64]),
|
||||
RoomObject(0x03F2A8, [0xFF, 0x55, 0x8B]),
|
||||
RoomObject(0x03F2AB, [0xFE, 0x78, 0x08]),
|
||||
RoomObject(0x03F2AE, [0xAD, 0x80, 0x03]),
|
||||
RoomObject(0x03F2B1, [0xFF, 0x58, 0x0A]),
|
||||
RoomObject(0x03F2B4, [0x9C, 0x91, 0x63]),
|
||||
RoomObject(0x03F2B7, [0xFE, 0x7A, 0x09]),
|
||||
RoomObject(0x03F2BA, [0xAD, 0xA0, 0x04]),
|
||||
RoomObject(0x03F2BD, [0xFF, 0x5A, 0x0B]),
|
||||
RoomObject(0x03F2C0, [0xD4, 0x91, 0x64]),
|
||||
RoomObject(0x03F2C3, [0x2C, 0x2E, 0xDC]),
|
||||
RoomObject(0x03F2C6, [0x3D, 0x3E, 0xF9]),
|
||||
RoomObject(0x03F2C9, [0x32, 0xA9, 0xF9]),
|
||||
RoomObject(0x03F2CC, [0x3A, 0xA9, 0xF9]),
|
||||
RoomObject(0x03F2CF, [0x42, 0xA9, 0xF9]),
|
||||
RoomObject(0x03F2D2, [0x4A, 0xA9, 0xF9]),
|
||||
RoomObject(0x03F2D5, [0x57, 0x9E, 0x69]),
|
||||
RoomObject(0x03F2D8, [0x54, 0xDC, 0x69]),
|
||||
RoomObject(0x03F2DB, [0x38, 0xC8, 0x89]),
|
||||
RoomObject(0x03F2DE, [0x58, 0x9C, 0x89]),
|
||||
RoomObject(0x03F2E1, [0x58, 0xA8, 0x89]),
|
||||
RoomObject(0x03F2E4, [0x58, 0xB4, 0x89]),
|
||||
RoomObject(0x03F2E7, [0x58, 0xC0, 0x89]),
|
||||
RoomObject(0x03F2EA, [0x58, 0xCC, 0x89]),
|
||||
RoomObject(0x03F2ED, [0x58, 0xD8, 0x89]),
|
||||
RoomObject(0x03F2F0, [0x58, 0xE4, 0x89]),
|
||||
RoomObject(0x03F2F3, [0xAA, 0x2E, 0xC8]),
|
||||
RoomObject(0x03F2F6, [0xAA, 0x29, 0x3F]),
|
||||
RoomObject(0x03F2F9, [0xAA, 0x2E, 0x79]),
|
||||
RoomObject(0x03F2FC, [0xAA, 0x59, 0x40]),
|
||||
RoomObject(0x03F2FF, [0xD6, 0x2E, 0x7A]),
|
||||
RoomObject(0x03F302, [0xAA, 0x90, 0xC8]),
|
||||
RoomObject(0x03F305, [0xAA, 0x8D, 0x3F]),
|
||||
RoomObject(0x03F308, [0xA8, 0x93, 0x79]),
|
||||
RoomObject(0x03F30B, [0xAA, 0xA1, 0x40]),
|
||||
RoomObject(0x03F30E, [0xD4, 0x93, 0x7A]),
|
||||
RoomObject(0x03F311, [0xB9, 0x5B, 0xF9]),
|
||||
RoomObject(0x03F314, [0xB9, 0xA3, 0xF9]),
|
||||
RoomObject(0x03F317, [0x9C, 0x68, 0x22]),
|
||||
RoomObject(0x03F31A, [0x9C, 0x6A, 0x69]),
|
||||
RoomObject(0x03F31D, [0x9C, 0x7C, 0x22]),
|
||||
RoomObject(0x03F320, [0xD4, 0x7C, 0x22]),
|
||||
RoomObject(0x03F323, [0x9C, 0xB0, 0x22]),
|
||||
RoomObject(0x03F326, [0xD4, 0xB0, 0x22]),
|
||||
RoomObject(0x03F329, [0xB3, 0x73, 0xFA]),
|
||||
RoomObject(0x03F32C, [0xCD, 0x68, 0xDD]),
|
||||
RoomObject(0x03F32F, [0xB8, 0xC0, 0xDD]),
|
||||
RoomObject(0x03F332, [0x08, 0x00, 0x60]),
|
||||
RoomObject(0x03F335, [0x10, 0x00, 0x60]),
|
||||
RoomObject(0x03F338, [0x1B, 0x10, 0xC0]),
|
||||
RoomObject(0x03F33B, [0x59, 0x10, 0xC0]),
|
||||
RoomObject(0x03F33E, [0x68, 0x23, 0xC0]),
|
||||
RoomObject(0x03F341, [0x68, 0x61, 0xC0]),
|
||||
RoomObject(0x03F344, [0x1B, 0x91, 0x60]),
|
||||
RoomObject(0x03F347, [0x88, 0x10, 0x60]),
|
||||
RoomObject(0x03F34A, [0xF0, 0x10, 0x60]),
|
||||
RoomObject(0x03F34D, [0x90, 0xDF, 0xA1]),
|
||||
RoomObject(0x03F350, [0xD4, 0xF7, 0xA3])], [],
|
||||
[DoorObject(Position.InteriorW, DoorKind.TrapTriggerable),
|
||||
DoorObject(Position.SouthW, DoorKind.CaveEntrance), DoorObject(Position.SouthE, DoorKind.CaveEntrance)]
|
||||
)
|
||||
|
||||
Room0127 = Room([0xE1, 0x00],
|
||||
[RoomObject(0x0AB600, [0xFE, 0x89, 0x00]),
|
||||
@@ -44,15 +515,35 @@ Room0127 = Room([0xE1, 0x00],
|
||||
RoomObject(0x0AB61E, [0x43, 0xCB, 0xFA]),
|
||||
RoomObject(0x0AB621, [0x4B, 0xCB, 0xFA]),
|
||||
RoomObject(0x0AB624, [0xBF, 0x94, 0xF9]),
|
||||
RoomObject(0x0AB627, [0xB3, 0xB3, 0xFA]),
|
||||
RoomObject(0x0AB62A, [0xCB, 0xB3, 0xFA]),
|
||||
RoomObject(0x0AB627, [0xB3, 0xB3, 0xFA], True),
|
||||
RoomObject(0x0AB62A, [0xCB, 0xB3, 0xFA], True),
|
||||
RoomObject(0x0AB62D, [0xAD, 0xC8, 0xDF]),
|
||||
RoomObject(0x0AB630, [0xC4, 0xC8, 0xDF]),
|
||||
RoomObject(0x0AB633, [0xB3, 0xE3, 0xFA]),
|
||||
RoomObject(0x0AB636, [0xCB, 0xE3, 0xFA]),
|
||||
RoomObject(0x0AB633, [0xB3, 0xE3, 0xFA], True),
|
||||
RoomObject(0x0AB636, [0xCB, 0xE3, 0xFA], True),
|
||||
RoomObject(0x0AB639, [0x81, 0x93, 0xC0]),
|
||||
RoomObject(0x0AB63C, [0x81, 0xD2, 0xC0]),
|
||||
RoomObject(0x0AB63F, [0xE1, 0x93, 0xC0]),
|
||||
RoomObject(0x0AB642, [0xE1, 0xD2, 0xC0])],
|
||||
[], [DoorObject(Position.SouthW, DoorKind.CaveEntrance),
|
||||
DoorObject(Position.SouthE, DoorKind.CaveEntrance)])
|
||||
|
||||
# boss room id, room data, shell x, shell y, clear layer 2
|
||||
boss_rooms = {
|
||||
'Eastern Palace': (0xc8, Room00C8, 0x2B, 0x28, False),
|
||||
'Desert Palace': (0x33, Room0033, 0x0B, 0x28, False),
|
||||
'Tower of Hera': (7, Room0007, 0x18, 0x16, False),
|
||||
'Palace of Darkness': (0x5A, Room005A, 0x2B, 0x28, False),
|
||||
'Swamp Palace': (6, Room0006, 0x0B, 0x28, False),
|
||||
'Skull Woods': (0x29, Room0029, 0x2B, 0x28, False),
|
||||
'Thieves Town': (0xac, Room00AC, 0x2B, 0x28, True),
|
||||
'Ice Palace': (0xde, Room00DE, 0x2B, 0x08, True),
|
||||
'Misery Mire': (0x90, Room0090, 0x0B, 0x28, True),
|
||||
'Turtle Rock': (0xa4, Room00A4, 0x0B, 0x28, True),
|
||||
}
|
||||
|
||||
gt_boss_room = {
|
||||
'bottom': (0x1C, Room001C, 0x2B, 0x28, False),
|
||||
'middle': (0x6C, Room006C, 0x0B, 0x28, False),
|
||||
'top': (0x4D, Room004D, 0x18, 0x16, False),
|
||||
}
|
||||
|
||||
@@ -8,9 +8,10 @@ Shuffled_Pot = (0xFB, 0, 0) # formerly weird pot, or black diagonal thing
|
||||
|
||||
class RoomObject:
|
||||
|
||||
def __init__(self, address, data):
|
||||
def __init__(self, address, data, dummy=False):
|
||||
self.address = address
|
||||
self.data = data
|
||||
self.dummy = dummy # some room objects are dummies, unreachable
|
||||
|
||||
def change_type(self, new_type):
|
||||
type_id, datum_a, datum_b = new_type
|
||||
@@ -22,6 +23,17 @@ class RoomObject:
|
||||
def write_to_rom(self, rom):
|
||||
rom.write_bytes(snes_to_pc(self.address), self.data)
|
||||
|
||||
# subtype 3 only?
|
||||
def matches_oid(self, oid):
|
||||
my_oid = (self.data[2] << 4) | ((self.data[1] & 3) << 2) | (self.data[0] & 3)
|
||||
return my_oid == oid
|
||||
|
||||
@staticmethod
|
||||
def subtype3_factory(x, y, type_id):
|
||||
return RoomObject(None, [((x << 2) & 0xFC) | (type_id & 0x3),
|
||||
((y << 2) & 0xFC) | ((type_id >> 2) & 0x3),
|
||||
0xF0 | ((type_id >> 4) & 0xF)])
|
||||
|
||||
|
||||
class DoorObject:
|
||||
|
||||
|
||||
1
source/dungeon/__init__.py
Normal file
1
source/dungeon/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
# do nothing, just exist to make "source" package
|
||||
222
source/enemizer/Bossmizer.py
Normal file
222
source/enemizer/Bossmizer.py
Normal file
@@ -0,0 +1,222 @@
|
||||
import RaceRandom as random
|
||||
from Utils import snes_to_pc
|
||||
|
||||
from source.dungeon.EnemyList import EnemySprite, SpriteType, Sprite
|
||||
from source.dungeon.RoomList import boss_rooms, gt_boss_room, Room0006
|
||||
from source.dungeon.RoomObject import RoomObject
|
||||
from source.enemizer.SpriteSheets import required_boss_sheets
|
||||
|
||||
|
||||
def get_dungeon_boss_room(dungeon_name, level):
|
||||
if level is None:
|
||||
return boss_rooms[dungeon_name]
|
||||
return gt_boss_room[level]
|
||||
|
||||
|
||||
def get_dungeon_boss_default(dungeon_name, level):
|
||||
if level is None:
|
||||
return boss_defaults[dungeon_name]
|
||||
return gt_boss_defaults[level]
|
||||
|
||||
|
||||
def add_shell_to_boss_room(data_tables, dungeon_name, level, shell_id):
|
||||
room_id, room, shell_x, shell_y, clear_layer_2 = get_dungeon_boss_room(dungeon_name, level)
|
||||
if room_id in data_tables.room_list:
|
||||
room = data_tables.room_list[room_id]
|
||||
else:
|
||||
data_tables.room_list[room_id] = room
|
||||
room.layout[0] = 0xF0
|
||||
if clear_layer_2:
|
||||
room.layer2.clear()
|
||||
y_offset = 0 if shell_id == 0xF95 else -2
|
||||
room.layer2.append(RoomObject.subtype3_factory(shell_x, shell_y + y_offset, shell_id))
|
||||
|
||||
|
||||
def remove_shell_from_boss_room(data_tables, dungeon_name, level, shell_id):
|
||||
room_id, room, shell_x, shell_y, clear_layer_2 = get_dungeon_boss_room(dungeon_name, level)
|
||||
if room_id in data_tables.room_list:
|
||||
room = data_tables.room_list[room_id]
|
||||
else:
|
||||
data_tables.room_list[room_id] = room
|
||||
room.layer2[:] = [obj for obj in room.layer2 if not obj.matches_oid(shell_id)]
|
||||
|
||||
|
||||
def remove_water_tiles(data_tables):
|
||||
room = Room0006
|
||||
if 0x6 in data_tables.room_list:
|
||||
room = data_tables.room_list[0x6]
|
||||
else:
|
||||
data_tables.room_list[0x6] = room
|
||||
room.layer1.clear()
|
||||
|
||||
|
||||
def create_sprite(super_tile, kind, sub_type, layer, tile_x, tile_y):
|
||||
return Sprite(super_tile, kind, sub_type, layer, tile_x, tile_y, None, False, None)
|
||||
|
||||
|
||||
def add_armos_to_list(sprite_list, room_id):
|
||||
sprite_list.insert(0, create_sprite(room_id, EnemySprite.ArmosKnight, 0x00, 0, 0x04, 0x05))
|
||||
sprite_list.insert(1, create_sprite(room_id, EnemySprite.ArmosKnight, 0x00, 0, 0x07, 0x05))
|
||||
sprite_list.insert(2, create_sprite(room_id, EnemySprite.ArmosKnight, 0x00, 0, 0x0a, 0x05))
|
||||
sprite_list.insert(3, create_sprite(room_id, EnemySprite.ArmosKnight, 0x00, 0, 0x0a, 0x08))
|
||||
sprite_list.insert(4, create_sprite(room_id, EnemySprite.ArmosKnight, 0x00, 0, 0x07, 0x08))
|
||||
sprite_list.insert(5, create_sprite(room_id, EnemySprite.ArmosKnight, 0x00, 0, 0x04, 0x08))
|
||||
sprite_list.insert(6, create_sprite(room_id, 0x19, SpriteType.Overlord, 0, 0x07, 0x08))
|
||||
|
||||
|
||||
def add_lanmolas_to_list(sprite_list, room_id):
|
||||
sprite_list.insert(0, create_sprite(room_id, EnemySprite.Lanmolas, 0x00, 0, 0x06, 0x07))
|
||||
sprite_list.insert(1, create_sprite(room_id, EnemySprite.Lanmolas, 0x00, 0, 0x09, 0x07))
|
||||
sprite_list.insert(2, create_sprite(room_id, EnemySprite.Lanmolas, 0x00, 0, 0x07, 0x09))
|
||||
|
||||
|
||||
def add_moldorm_to_list(sprite_list, room_id):
|
||||
sprite_list.insert(0, create_sprite(room_id, EnemySprite.Moldorm, 0x00, 0, 0x09, 0x09))
|
||||
|
||||
|
||||
def add_helmasaur_king_to_list(sprite_list, room_id):
|
||||
sprite_list.insert(0, create_sprite(room_id, EnemySprite.HelmasaurKing, 0x00, 0, 0x07, 0x06))
|
||||
|
||||
|
||||
def add_arrghus_to_list(sprite_list, room_id):
|
||||
sprite_list.insert(0, create_sprite(room_id, EnemySprite.Arrghus, 0x00, 0, 0x07, 0x07))
|
||||
sprite_list.insert(1, create_sprite(room_id, EnemySprite.Arrghi, 0x00, 0, 0x07, 0x07))
|
||||
sprite_list.insert(2, create_sprite(room_id, EnemySprite.Arrghi, 0x00, 0, 0x07, 0x07))
|
||||
sprite_list.insert(3, create_sprite(room_id, EnemySprite.Arrghi, 0x00, 0, 0x07, 0x07))
|
||||
sprite_list.insert(4, create_sprite(room_id, EnemySprite.Arrghi, 0x00, 0, 0x07, 0x07))
|
||||
sprite_list.insert(5, create_sprite(room_id, EnemySprite.Arrghi, 0x00, 0, 0x07, 0x07))
|
||||
sprite_list.insert(6, create_sprite(room_id, EnemySprite.Arrghi, 0x00, 0, 0x07, 0x07))
|
||||
sprite_list.insert(7, create_sprite(room_id, EnemySprite.Arrghi, 0x00, 0, 0x07, 0x07))
|
||||
sprite_list.insert(8, create_sprite(room_id, EnemySprite.Arrghi, 0x00, 0, 0x07, 0x07))
|
||||
sprite_list.insert(9, create_sprite(room_id, EnemySprite.Arrghi, 0x00, 0, 0x07, 0x07))
|
||||
sprite_list.insert(10, create_sprite(room_id, EnemySprite.Arrghi, 0x00, 0, 0x07, 0x07))
|
||||
sprite_list.insert(11, create_sprite(room_id, EnemySprite.Arrghi, 0x00, 0, 0x07, 0x07))
|
||||
sprite_list.insert(12, create_sprite(room_id, EnemySprite.Arrghi, 0x00, 0, 0x07, 0x07))
|
||||
sprite_list.insert(13, create_sprite(room_id, EnemySprite.Arrghi, 0x00, 0, 0x07, 0x07))
|
||||
|
||||
|
||||
def add_mothula_to_list(sprite_list, room_id):
|
||||
sprite_list.insert(0, create_sprite(room_id, EnemySprite.Mothula, 0x00, 0, 0x08, 0x06))
|
||||
|
||||
|
||||
def add_blind_to_list(sprite_list, room_id):
|
||||
sprite_list.insert(0, create_sprite(room_id, EnemySprite.Blind, 0x00, 0, 0x09, 0x05))
|
||||
|
||||
|
||||
def add_kholdstare_to_list(sprite_list, room_id):
|
||||
sprite_list.insert(0, create_sprite(room_id, EnemySprite.KholdstareShell, 0x00, 0, 0x07, 0x05))
|
||||
sprite_list.insert(1, create_sprite(room_id, EnemySprite.FallingIce, 0x00, 0, 0x07, 0x05))
|
||||
sprite_list.insert(2, create_sprite(room_id, EnemySprite.Kholdstare, 0x00, 0, 0x07, 0x05))
|
||||
|
||||
|
||||
def add_vitreous_to_list(sprite_list, room_id):
|
||||
sprite_list.clear() # vitreous does not play nice which other sprites on the tile, just kill them
|
||||
sprite_list.append(create_sprite(room_id, EnemySprite.Vitreous, 0x00, 0, 0x07, 0x05))
|
||||
|
||||
|
||||
def add_trinexx_to_list(sprite_list, room_id):
|
||||
sprite_list.insert(0, create_sprite(room_id, EnemySprite.TrinexxRockHead, 0x00, 0, 0x07, 0x05))
|
||||
sprite_list.insert(1, create_sprite(room_id, EnemySprite.TrinexxFireHead, 0x00, 0, 0x07, 0x05))
|
||||
sprite_list.insert(2, create_sprite(room_id, EnemySprite.TrinexxIceHead, 0x00, 0, 0x07, 0x05))
|
||||
|
||||
|
||||
def boss_adjust(world, player):
|
||||
data_tables = world.data_tables[player]
|
||||
for dungeon in world.get_dungeons(player):
|
||||
for level, boss in dungeon.bosses.items():
|
||||
if not boss or boss.name in ['Agahnim', 'Agahnim2']:
|
||||
continue
|
||||
default_boss = get_dungeon_boss_default(dungeon.name, level)
|
||||
room_data = get_dungeon_boss_room(dungeon.name, level)
|
||||
room_id = room_data[0]
|
||||
if default_boss != boss.name:
|
||||
sprite_list = data_tables.uw_enemy_table.room_map[room_id]
|
||||
data = boss_room_remove_data[room_id]
|
||||
del sprite_list[:data]
|
||||
add_func, sprite_type = boss_addition_table[boss.name]
|
||||
add_func(sprite_list, room_id)
|
||||
if len(sprite_list) > 15:
|
||||
del sprite_list[15:]
|
||||
data_tables.room_headers[room_id].sprite_sheet = required_boss_sheets[sprite_type]
|
||||
|
||||
|
||||
def boss_writes(world, player, rom):
|
||||
rom.write_byte(snes_to_pc(0x368107), 1) # centralize drops
|
||||
eye_number = random.randint(0, 8) # randomize moldorm eyes (var + 1)
|
||||
rom.write_byte(snes_to_pc(0x368102), eye_number) # enemizer flag
|
||||
rom.write_byte(snes_to_pc(0x1DDBB3), eye_number) # loop variable
|
||||
data_tables = world.data_tables[player]
|
||||
arrghus_can_swim = True
|
||||
water_tiles_on = True
|
||||
for dungeon in world.get_dungeons(player):
|
||||
for level, boss in dungeon.bosses.items():
|
||||
if not boss or boss.name in ['Agahnim', 'Agahnim2']:
|
||||
continue
|
||||
room_data = get_dungeon_boss_room(dungeon.name, level)
|
||||
room_id = room_data[0]
|
||||
# room changes
|
||||
if boss.name == 'Arrghus' and (dungeon.name != 'Swamp Palace' or level is not None):
|
||||
rom.write_byte(snes_to_pc(0x0DB6BE), 0) # arrghus can stand on ground
|
||||
arrghus_can_swim = False
|
||||
if boss.name != 'Arrghus' and dungeon.name == 'Swamp Palace' and level is None:
|
||||
remove_water_tiles(data_tables)
|
||||
water_tiles_on = False
|
||||
if boss.name == 'Trinexx' and (dungeon.name != 'Turtle Rock' or level is not None):
|
||||
add_shell_to_boss_room(data_tables, dungeon.name, level, 0xFF2)
|
||||
data_tables.room_headers[room_id].byte_0 = 0x60
|
||||
data_tables.room_headers[room_id].effect = 4
|
||||
# $2E, $98, $FF (original shell)
|
||||
if boss.name == 'Kholdstare' and (dungeon.name != 'Ice Palace' or level is not None):
|
||||
add_shell_to_boss_room(data_tables, dungeon.name, level, 0xF95)
|
||||
data_tables.room_headers[room_id].byte_0 = 0xE0
|
||||
data_tables.room_headers[room_id].effect = 1
|
||||
if boss.name != 'Trinexx' and dungeon.name == 'Turtle Rock' and level is None:
|
||||
remove_shell_from_boss_room(data_tables, dungeon.name, level, 0xFF2)
|
||||
# disable trinexx ice breath with No-ops
|
||||
rom.write_bytes(snes_to_pc(0x09B37E), [0xEA, 0xEA, 0xEA, 0xEA])
|
||||
if boss.name != 'Kholdstare' and dungeon.name == 'Ice Palace' and level is None:
|
||||
remove_shell_from_boss_room(data_tables, dungeon.name, level, 0xF95)
|
||||
if boss.name != 'Blind' and dungeon.name == 'Thieves Town' and level is None:
|
||||
rom.write_byte(snes_to_pc(0x368101), 1) # set blind boss door flag
|
||||
# maiden is deleted
|
||||
del data_tables.uw_enemy_table.room_map[0x45][0]
|
||||
if not arrghus_can_swim and water_tiles_on:
|
||||
remove_water_tiles(data_tables)
|
||||
|
||||
|
||||
boss_defaults = {
|
||||
'Eastern Palace': 'Armos Knights',
|
||||
'Desert Palace': 'Lanmolas',
|
||||
'Tower of Hera': 'Moldorm',
|
||||
'Palace of Darkness': 'Helmasaur King',
|
||||
'Swamp Palace': 'Arrghus',
|
||||
'Skull Woods': 'Mothula',
|
||||
'Thieves Town': 'Blind',
|
||||
'Ice Palace': 'Kholdstare',
|
||||
'Misery Mire': 'Vitreous',
|
||||
'Turtle Rock': 'Trinexx',
|
||||
}
|
||||
|
||||
gt_boss_defaults = {
|
||||
'bottom': 'Armos Knights',
|
||||
'middle': 'Lanmolas',
|
||||
'top': 'Moldorm',
|
||||
}
|
||||
|
||||
boss_room_remove_data = {
|
||||
6: 14, 7: 1, 0x1c: 7, 0x29: 1, 0x33: 3, 0x4d: 1, 0x5a: 1,
|
||||
0x6c: 3, 0x90: 1, 0xa4: 2, 0xac: 1, 0xc8: 7, 0xde: 3
|
||||
}
|
||||
|
||||
boss_addition_table = {
|
||||
'Armos Knights': (add_armos_to_list, EnemySprite.ArmosKnight),
|
||||
'Lanmolas': (add_lanmolas_to_list, EnemySprite.Lanmolas),
|
||||
'Moldorm': (add_moldorm_to_list, EnemySprite.Moldorm),
|
||||
'Helmasaur King': (add_helmasaur_king_to_list, EnemySprite.HelmasaurKing),
|
||||
'Arrghus': (add_arrghus_to_list, EnemySprite.Arrghus),
|
||||
'Mothula': (add_mothula_to_list, EnemySprite.Mothula),
|
||||
'Blind': (add_blind_to_list, EnemySprite.Blind),
|
||||
'Kholdstare': (add_kholdstare_to_list, EnemySprite.Kholdstare),
|
||||
'Vitreous': (add_vitreous_to_list, EnemySprite.Vitreous),
|
||||
'Trinexx': (add_trinexx_to_list, EnemySprite.TrinexxRockHead)
|
||||
}
|
||||
8
source/enemizer/DamageTables.py
Normal file
8
source/enemizer/DamageTables.py
Normal file
@@ -0,0 +1,8 @@
|
||||
from Utils import load_cached_yaml
|
||||
|
||||
|
||||
class DamageTable:
|
||||
def __init__(self):
|
||||
self.damage_table = load_cached_yaml(['source', 'enemizer', 'damage_table.yaml'])
|
||||
self.enemy_damage = load_cached_yaml(['source', 'enemizer', 'enemy_damage_table.yaml'])
|
||||
|
||||
539
source/enemizer/Enemizer.py
Normal file
539
source/enemizer/Enemizer.py
Normal file
@@ -0,0 +1,539 @@
|
||||
import RaceRandom as random
|
||||
from Utils import snes_to_pc
|
||||
|
||||
from source.dungeon.EnemyList import SpriteType, EnemySprite, sprite_translation
|
||||
from source.dungeon.RoomList import Room010C
|
||||
from source.enemizer.SpriteSheets import sub_group_choices
|
||||
from source.enemizer.SpriteSheets import randomize_underworld_sprite_sheets, randomize_overworld_sprite_sheets
|
||||
from source.enemizer.TilePattern import tile_patterns
|
||||
|
||||
shutter_sprites = {
|
||||
0xb8: {0, 1, 2, 3, 4, 5}, 0xb: {4, 5, 6, 7, 8, 9}, 0x1b: {3, 4, 5}, 0x4b: {0, 3, 4}, 0x4: {9, 13, 14},
|
||||
0x24: {3, 4, 5, 6}, # not sure about 6 - bunny beam under pot
|
||||
0x28: {0, 1, 2, 3, 4}, 0xe: {0, 1, 2, 3}, 0x2e: {0, 1, 2, 3, 4, 5}, 0x3e: {1, 2}, 0x6e: {0, 1, 2, 3, 4},
|
||||
0x31: {7, 8, 10}, 0x44: {2, 3, 5}, 0x45: {1, 2, 3}, 0x53: {5, 6, 8, 9, 10}, 0x75: {0, 2, 3, 4, 5},
|
||||
0x85: {2, 3, 4, 5}, 0x5d: {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}, 0x6b: {5, 6, 7, 8, 9, 10, 11, 12, 13},
|
||||
0x6d: {0, 1, 2, 3, 4, 5, 6, 7, 8}, 0x7b: {2, 3, 4, 5, 8, 9, 10}, 0x7d: {4, 5, 6, 7, 8, 10}, 0x8d: {0, 1, 2, 3, 4},
|
||||
0xa5: {0, 1, 2, 3, 4, 5, 6, 7}, 0x71: {0, 1}, 0xd8: {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10},
|
||||
0xb0: {0, 1, 2, 3, 4, 5, 7, 8, 9, 10}, 0xc0: {0, 1, 2}, 0xe0: {0, 1, 2, 3}, 0xb2: {5, 6, 7, 10, 11},
|
||||
0xd2: {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}, 0xef: {0, 1, 2}, 0x10c: {4, 5, 6, 7}, 0x123: {0, 1, 2, 3},
|
||||
0xee: {0, 1, 2, 3, 4} # low health traversal
|
||||
}
|
||||
|
||||
|
||||
def setup_specific_requirements(data_tables):
|
||||
requirements = data_tables.sprite_requirements
|
||||
water_groups = set()
|
||||
water_sub_groups = {0: set(), 1: set(), 2: set(), 3: set()}
|
||||
killable_groups = set()
|
||||
killable_sub_groups = {0: set(), 1: set(), 2: set(), 3: set()}
|
||||
key_groups = set()
|
||||
key_sub_groups = {0: set(), 1: set(), 2: set(), 3: set()}
|
||||
|
||||
for sid, requirement in requirements.items():
|
||||
if isinstance(requirement, dict):
|
||||
continue
|
||||
if requirement.good_for_uw_water():
|
||||
water_groups.update(requirement.groups)
|
||||
for i in range(0, 4):
|
||||
limited = [x for x in requirement.sub_groups[i] if x in sub_group_choices[i]]
|
||||
water_sub_groups[i].update(limited)
|
||||
if requirement.good_for_shutter([]):
|
||||
killable_groups.update(requirement.groups)
|
||||
for i in range(0, 4):
|
||||
killable_sub_groups[i].update(requirement.sub_groups[i])
|
||||
if requirement.can_drop:
|
||||
key_groups.update(requirement.groups)
|
||||
for i in range(0, 4):
|
||||
key_sub_groups[i].update(requirement.sub_groups[i])
|
||||
return water_groups, water_sub_groups, killable_groups, killable_sub_groups, key_groups, key_sub_groups
|
||||
|
||||
|
||||
def get_possible_sheets(room_id, data_tables, specific, all_sheets, uw_sheets):
|
||||
# forced sprites for room
|
||||
requirements = data_tables.sprite_requirements
|
||||
|
||||
water_groups, water_sub_groups, killable_groups, killable_sub_groups, key_groups, key_sub_groups = specific
|
||||
|
||||
# forced_req = set()
|
||||
key_needed = False
|
||||
killable_needed = room_id in shutter_sprites
|
||||
|
||||
for sheet in all_sheets:
|
||||
if room_id in sheet.room_set:
|
||||
return [sheet]
|
||||
|
||||
match_all_room_groups = set()
|
||||
match_all_sub_groups = {0: set(), 1: set(), 2: set(), 3: set()}
|
||||
# match_all_sub_groups = {0: set(uw_sub_group_choices[0] + [70, 72]), 1: set(uw_sub_group_choices[1] + [13, 73]),
|
||||
# 2: set(uw_sub_group_choices[2] + [19]), 3: set(uw_sub_group_choices[3] + [25, 68])}
|
||||
|
||||
for sprite in data_tables.uw_enemy_table.room_map[room_id]:
|
||||
sprite_secondary = 0 if sprite.sub_type != SpriteType.Overlord else sprite.sub_type
|
||||
key = (sprite.kind, sprite_secondary)
|
||||
if key not in requirements:
|
||||
continue
|
||||
req = requirements[key]
|
||||
if isinstance(req, dict):
|
||||
req = req[room_id]
|
||||
if req.static or not req.can_randomize or sprite.static:
|
||||
if req.groups:
|
||||
match_all_room_groups.intersection_update(req.groups)
|
||||
if not match_all_room_groups:
|
||||
match_all_room_groups = set(req.groups)
|
||||
for i in range(0, 4):
|
||||
if req.sub_groups[i]:
|
||||
match_all_sub_groups[i].intersection_update(req.sub_groups[i])
|
||||
if not match_all_sub_groups[i]:
|
||||
match_all_sub_groups[i] = set(req.sub_groups[i])
|
||||
# forced_req.add(req)
|
||||
if sprite.drops_item:
|
||||
key_needed = True
|
||||
|
||||
match_any_room_groups = set()
|
||||
match_any_sub_groups = {0: set(), 1: set(), 2: set(), 3: set()}
|
||||
exclude_all_groups = set()
|
||||
exclude_all_sub_groups = {0: set(), 1: set(), 2: set(), 3: set()}
|
||||
|
||||
if room_id in data_tables.room_requirements:
|
||||
required_groups = data_tables.room_requirements[room_id]
|
||||
for idx, grp in enumerate(required_groups):
|
||||
if grp is not None:
|
||||
if isinstance(grp, tuple):
|
||||
match_any_sub_groups[idx].update(grp)
|
||||
else:
|
||||
match_all_sub_groups[idx] = {grp}
|
||||
|
||||
if key_needed:
|
||||
if key_groups:
|
||||
match_any_room_groups.update(key_groups)
|
||||
for i in range(0, 4):
|
||||
if key_sub_groups[i]:
|
||||
match_any_sub_groups[i].update(key_sub_groups[i])
|
||||
elif killable_needed:
|
||||
if killable_groups:
|
||||
match_any_room_groups.update(killable_groups)
|
||||
for i in range(0, 4):
|
||||
if killable_sub_groups[i]:
|
||||
match_any_sub_groups[i].update(killable_sub_groups[i])
|
||||
|
||||
possible_sheets = []
|
||||
for sheet in uw_sheets:
|
||||
if match_all_room_groups and sheet.id not in match_all_room_groups:
|
||||
continue
|
||||
if any(match_all_sub_groups[i] and sheet.sub_groups[i] not in match_all_sub_groups[i] for i in range(0, 4)):
|
||||
continue
|
||||
if exclude_all_groups and sheet.id in exclude_all_groups:
|
||||
continue
|
||||
if any(exclude_all_sub_groups[i] and sheet.sub_groups[i] in exclude_all_sub_groups[i] for i in range(0, 4)):
|
||||
continue
|
||||
if match_any_room_groups and sheet.id not in match_any_sub_groups:
|
||||
continue
|
||||
test_subs = [i for i in range(0, 4) if match_any_sub_groups[i]]
|
||||
if test_subs and all(sheet.sub_groups[i] not in match_any_sub_groups[i] for i in test_subs):
|
||||
continue
|
||||
possible_sheets.append(sheet)
|
||||
return possible_sheets
|
||||
|
||||
|
||||
def get_possible_ow_sheets(area_id, all_sheets, ow_sheets, data_tables):
|
||||
requirements = data_tables.sprite_requirements
|
||||
|
||||
for sheet in all_sheets:
|
||||
if area_id in sheet.room_set:
|
||||
return [sheet]
|
||||
|
||||
match_all_room_groups = set()
|
||||
match_all_sub_groups = {0: set(), 1: set(), 2: set(), 3: set()}
|
||||
|
||||
for sprite in data_tables.ow_enemy_table[area_id]:
|
||||
sprite_secondary = 0 if sprite.sub_type != SpriteType.Overlord else sprite.sub_type
|
||||
key = (sprite.kind, sprite_secondary)
|
||||
if key not in requirements:
|
||||
continue
|
||||
req = requirements[key]
|
||||
if isinstance(req, dict):
|
||||
req = req[area_id]
|
||||
if req.static or not req.can_randomize:
|
||||
if req.groups:
|
||||
match_all_room_groups.intersection_update(req.groups)
|
||||
if not match_all_room_groups:
|
||||
match_all_room_groups = set(req.groups)
|
||||
for i in range(0, 4):
|
||||
if req.sub_groups[i]:
|
||||
match_all_sub_groups[i].intersection_update(req.sub_groups[i])
|
||||
if not match_all_sub_groups[i]:
|
||||
match_all_sub_groups[i] = set(req.sub_groups[i])
|
||||
|
||||
possible_sheets = []
|
||||
for sheet in ow_sheets:
|
||||
if match_all_room_groups and sheet.id not in match_all_room_groups:
|
||||
continue
|
||||
if any(match_all_sub_groups[i] and sheet.sub_groups[i] not in match_all_sub_groups[i] for i in range(0, 4)):
|
||||
continue
|
||||
possible_sheets.append(sheet)
|
||||
return possible_sheets
|
||||
|
||||
|
||||
ignore_sheets_uw = {65, 69, 71, 78, 79, 82, 88, 98}
|
||||
ignore_sheets_ow = {6}
|
||||
|
||||
|
||||
def find_candidate_sprites(data_tables, sheet_range, uw=True):
|
||||
requirements = data_tables.sprite_requirements
|
||||
sprite_candidates = []
|
||||
sheet_candidates = []
|
||||
all_sheets = []
|
||||
|
||||
candidate_groups = set()
|
||||
candidate_sub_groups = {0: set(), 1: set(), 2: set(), 3: set()}
|
||||
|
||||
for k, r in requirements.items():
|
||||
if isinstance(r, dict):
|
||||
continue
|
||||
valid_flag = (uw and r.uw_valid) or (not uw and r.ow_valid)
|
||||
if not r.static and valid_flag and not r.dont_use:
|
||||
candidate_groups.update(r.groups)
|
||||
for i in range(0, 4):
|
||||
candidate_sub_groups[i].update(r.sub_groups[i])
|
||||
sprite_candidates.append(k)
|
||||
|
||||
for num in sheet_range:
|
||||
sheet = data_tables.sprite_sheets[num]
|
||||
all_sheets.append(sheet)
|
||||
if (uw and num in ignore_sheets_uw) or (not uw and num in ignore_sheets_ow):
|
||||
continue
|
||||
if candidate_groups and sheet not in candidate_groups:
|
||||
continue
|
||||
test_subs = [i for i in range(0, 4) if candidate_sub_groups[i]]
|
||||
if test_subs and all(sheet.sub_groups[i] not in candidate_sub_groups[i] for i in test_subs):
|
||||
continue
|
||||
sheet_candidates.append(sheet)
|
||||
|
||||
return sprite_candidates, sheet_candidates, all_sheets
|
||||
|
||||
|
||||
def get_possible_enemy_sprites(room_id, sheet, uw_sprites, data_tables):
|
||||
ret = []
|
||||
for sprite in uw_sprites:
|
||||
requirement = data_tables.sprite_requirements[sprite]
|
||||
if isinstance(requirement, dict):
|
||||
requirement = requirement[room_id]
|
||||
if sheet.valid_sprite(requirement) and requirement.can_spawn_in_room(room_id):
|
||||
ret.append(requirement)
|
||||
return ret
|
||||
|
||||
|
||||
def get_possible_enemy_sprites_ow(sheet, sprites, data_tables):
|
||||
ret = []
|
||||
for sprite in sprites:
|
||||
requirement = data_tables.sprite_requirements[sprite]
|
||||
if isinstance(requirement, dict):
|
||||
continue
|
||||
if sheet.valid_sprite(requirement) and requirement.ow_valid:
|
||||
ret.append(requirement)
|
||||
return ret
|
||||
|
||||
|
||||
def get_randomize_able_sprites(room_id, data_tables):
|
||||
sprite_table = {}
|
||||
for idx, sprite in enumerate(data_tables.uw_enemy_table.room_map[room_id]):
|
||||
sprite_secondary = 0 if sprite.sub_type != SpriteType.Overlord else sprite.sub_type
|
||||
key = (sprite.kind, sprite_secondary)
|
||||
if key not in data_tables.sprite_requirements:
|
||||
continue
|
||||
req = data_tables.sprite_requirements[key]
|
||||
if isinstance(req, dict):
|
||||
continue
|
||||
if not req.static and req.can_randomize and not sprite.static:
|
||||
sprite_table[idx] = sprite
|
||||
return sprite_table
|
||||
|
||||
|
||||
def get_randomize_able_sprites_ow(area_id, data_tables):
|
||||
sprite_table = {}
|
||||
for idx, sprite in enumerate(data_tables.ow_enemy_table[area_id]):
|
||||
sprite_secondary = 0 if sprite.sub_type != SpriteType.Overlord else sprite.sub_type
|
||||
key = (sprite.kind, sprite_secondary)
|
||||
if key not in data_tables.sprite_requirements:
|
||||
continue
|
||||
req = data_tables.sprite_requirements[key]
|
||||
if isinstance(req, dict):
|
||||
continue
|
||||
if not req.static and req.can_randomize:
|
||||
sprite_table[idx] = sprite
|
||||
return sprite_table
|
||||
|
||||
|
||||
sprite_limiter = {
|
||||
EnemySprite.Debirando: 2,
|
||||
EnemySprite.DebirandoPit: 2,
|
||||
EnemySprite.Hinox: 2,
|
||||
EnemySprite.Sluggula: 2,
|
||||
EnemySprite.BombGuard: 2,
|
||||
EnemySprite.Beamos: 2,
|
||||
EnemySprite.Gibo: 2,
|
||||
# EnemySprite.CannonTrooper: 2, ??
|
||||
EnemySprite.WallCannonHorzTop: 2,
|
||||
EnemySprite.WallCannonHorzBottom: 2,
|
||||
EnemySprite.WallCannonVertLeft: 2,
|
||||
EnemySprite.WallCannonVertRight: 2,
|
||||
EnemySprite.BlueArcher: 2,
|
||||
EnemySprite.BlueGuard: 2,
|
||||
EnemySprite.GreenGuard: 2,
|
||||
EnemySprite.RedSpearGuard: 2,
|
||||
EnemySprite.RedJavelinGuard: 2,
|
||||
EnemySprite.AntiFairyCircle: 4
|
||||
}
|
||||
|
||||
|
||||
def exceeds_sprite_limit(limit, sprite):
|
||||
return sprite_limiter[sprite.sprite]-1+limit > 15 if sprite.sprite in sprite_limiter else False
|
||||
|
||||
|
||||
def randomize_underworld_rooms(data_tables, world, player, custom_uw):
|
||||
any_enemy_logic = world.any_enemy_logic[player]
|
||||
enemy_drops_active = world.dropshuffle[player] in ['underworld']
|
||||
specific = setup_specific_requirements(data_tables)
|
||||
uw_candidates, uw_sheets, all_sheets = find_candidate_sprites(data_tables, range(65, 124))
|
||||
for room_id in range(0, 0x128):
|
||||
if room_id in {0, 1, 3, 6, 7, 0xd, 0x14, 0x20, 0x29, 0x30, 0x33,
|
||||
0x4d, 0x5a, 0x90, 0xa4, 0xac, 0xc8, 0xde}:
|
||||
continue
|
||||
current_sprites = data_tables.uw_enemy_table.room_map[room_id]
|
||||
sprite_limit = sum(sprite_limiter[x.kind] if x.kind in sprite_limiter else 1 for x in current_sprites)
|
||||
if room_id in {0x3f, 0x44, 0x45, 0x93, 0xce, 0x117}:
|
||||
sprite_limit += 1 # for liftable blocks see PotFlags.Block in PotShuffle
|
||||
randomizeable_sprites = get_randomize_able_sprites(room_id, data_tables)
|
||||
if not randomizeable_sprites:
|
||||
candidate_sheets = get_possible_sheets(room_id, data_tables, specific, all_sheets, uw_sheets)
|
||||
chosen_sheet = random.choice(candidate_sheets)
|
||||
data_tables.room_headers[room_id].sprite_sheet = chosen_sheet.id - 0x40
|
||||
if randomizeable_sprites:
|
||||
candidate_sheets = get_possible_sheets(room_id, data_tables, specific, all_sheets, uw_sheets)
|
||||
done = False
|
||||
while not done:
|
||||
chosen_sheet = random.choice(candidate_sheets)
|
||||
data_tables.room_headers[room_id].sprite_sheet = chosen_sheet.id - 0x40
|
||||
candidate_sprites = get_possible_enemy_sprites(room_id, chosen_sheet, uw_candidates, data_tables)
|
||||
randomized = True
|
||||
# wallmaster in hera basement throws off hera basement key code
|
||||
wallmaster_chosen = room_id in {0x0039, 0x0049, 0x0056, 0x0057, 0x0068, 0x0087, 0x008d}
|
||||
for i, sprite in randomizeable_sprites.items():
|
||||
if room_id in custom_uw and i in custom_uw[room_id]:
|
||||
sprite.kind = sprite_translation[custom_uw[room_id][i]]
|
||||
else:
|
||||
# filter out water if necessary
|
||||
candidate_sprites = [x for x in candidate_sprites if not x.water_only or sprite.water]
|
||||
# filter out wallmaster if already on tile
|
||||
if wallmaster_chosen:
|
||||
candidate_sprites = [x for x in candidate_sprites if x.sprite != EnemySprite.Wallmaster]
|
||||
candidate_sprites = [x for x in candidate_sprites if not exceeds_sprite_limit(sprite_limit, x)]
|
||||
if sprite.drops_item:
|
||||
forbidden = determine_forbidden(any_enemy_logic == 'none', room_id, True)
|
||||
choice_list = [x for x in candidate_sprites if x.good_for_key_drop(forbidden)]
|
||||
# terrorpin, deadrock, buzzblob, lynel, redmimic/eyegore
|
||||
elif room_id in shutter_sprites and i in shutter_sprites[room_id]:
|
||||
forbidden = determine_forbidden(any_enemy_logic != 'allow_all', room_id)
|
||||
choice_list = [x for x in candidate_sprites if x.good_for_shutter(forbidden)]
|
||||
else:
|
||||
choice_list = [x for x in candidate_sprites if not x.water_only]
|
||||
choice_list = filter_choices(choice_list, room_id, i, data_tables.uw_enemy_denials)
|
||||
if enemy_drops_active:
|
||||
choice_list = filter_choices(choice_list, room_id, i, data_tables.uw_enemy_drop_denials)
|
||||
if len(choice_list) == 0:
|
||||
randomized = False
|
||||
break
|
||||
weight = [data_tables.uw_weights[r.sprite] for r in choice_list]
|
||||
chosen = random.choices(choice_list, weight, k=1)[0]
|
||||
sprite.kind = chosen.sprite
|
||||
if sprite.kind in sprite_limiter:
|
||||
sprite_limit += sprite_limiter[sprite.kind]-1
|
||||
if sprite.kind == EnemySprite.Wallmaster:
|
||||
wallmaster_chosen = True
|
||||
sprite.kind = 0x09
|
||||
sprite.sub_type = SpriteType.Overlord
|
||||
done = randomized
|
||||
# done with sprites
|
||||
# done with rooms
|
||||
|
||||
|
||||
def determine_forbidden(forbid, room_id, drop_flag=False):
|
||||
forbidden_set = set()
|
||||
if forbid:
|
||||
forbidden_set.update({EnemySprite.Terrorpin, EnemySprite.Deadrock, EnemySprite.Buzzblob,
|
||||
EnemySprite.Lynel})
|
||||
if drop_flag:
|
||||
forbidden_set.add(EnemySprite.RedBari) # requires FireRod to Drop
|
||||
# else: Not yet able to protect triggers, would change default GT tile room behavior
|
||||
# forbidden_set.add(EnemySprite.AntiFairy) # can't drop anyway
|
||||
if room_id not in {0x6b, 0x4b, 0x1b, 0xd8}: # mimics/eyegore are allowed in vanilla rooms
|
||||
forbidden_set.add(EnemySprite.RedEyegoreMimic)
|
||||
forbidden_set.add(EnemySprite.RedMimic)
|
||||
return forbidden_set
|
||||
|
||||
|
||||
def filter_choices(options, room_id, sprite_idx, denials):
|
||||
key = room_id, sprite_idx
|
||||
return [x for x in options if key not in denials or x.sprite not in denials[key]]
|
||||
|
||||
|
||||
def filter_water_phobic(options, sprite):
|
||||
return [x for x in options if not x.water_phobic or not sprite.water]
|
||||
|
||||
|
||||
def randomize_overworld_enemies(data_tables, custom_ow):
|
||||
ow_candidates, ow_sheets, all_sheets = find_candidate_sprites(data_tables, range(1, 64), False)
|
||||
areas_to_randomize = [0, 2, 3, 5, 7, 0xA, 0xF, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
|
||||
0x1a, 0x1b, 0x1d, 0x1e, 0x22, 0x25, 0x28, 0x29, 0x2A, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
|
||||
0x30, 0x32, 0x33, 0x34, 0x35, 0x37, 0x3a, 0x3b, 0x3c, 0x3f]
|
||||
area_list = areas_to_randomize + [x + 0x40 for x in areas_to_randomize] # light world + dark world
|
||||
area_list += [0x80, 0x81] + [x + 0x90 for x in areas_to_randomize] # specials + post aga LW
|
||||
for area_id in area_list:
|
||||
randomizeable_sprites = get_randomize_able_sprites_ow(area_id, data_tables)
|
||||
if not randomizeable_sprites:
|
||||
candidate_sheets = get_possible_ow_sheets(area_id, all_sheets, ow_sheets, data_tables)
|
||||
chosen_sheet = random.choice(candidate_sheets)
|
||||
data_tables.overworld_sprite_sheets[area_id] = chosen_sheet
|
||||
candidate_sprites = get_possible_enemy_sprites_ow(chosen_sheet, ow_candidates, data_tables)
|
||||
else:
|
||||
candidate_sheets = get_possible_ow_sheets(area_id, all_sheets, ow_sheets, data_tables)
|
||||
chosen_sheet = random.choice(candidate_sheets)
|
||||
data_tables.overworld_sprite_sheets[area_id] = chosen_sheet
|
||||
candidate_sprites = get_possible_enemy_sprites_ow(chosen_sheet, ow_candidates, data_tables)
|
||||
for i, sprite in randomizeable_sprites.items():
|
||||
if area_id in custom_ow and i in custom_ow[area_id]:
|
||||
sprite.kind = sprite_translation[custom_ow[area_id][i]]
|
||||
else:
|
||||
candidate_sprites = filter_choices(candidate_sprites, area_id, i, data_tables.ow_enemy_denials)
|
||||
candidate_sprites = filter_water_phobic(candidate_sprites, sprite)
|
||||
weight = [data_tables.ow_weights[r.sprite] for r in candidate_sprites]
|
||||
chosen = random.choices(candidate_sprites, weight, k=1)[0]
|
||||
sprite.kind = chosen.sprite
|
||||
# randomize the bush sprite per area
|
||||
weight = [data_tables.ow_weights[r.sprite] for r in candidate_sprites]
|
||||
bush_sprite_choice = random.choices(candidate_sprites, weight, k=1)[0]
|
||||
data_tables.bush_sprite_table[area_id] = bush_sprite_choice
|
||||
|
||||
|
||||
# damage and health tables only go to F2
|
||||
skip_sprites = {
|
||||
EnemySprite.ArmosKnight, EnemySprite.Lanmolas, EnemySprite.Moldorm, EnemySprite.Mothula, EnemySprite.Arrghus,
|
||||
EnemySprite.HelmasaurKing, EnemySprite.Vitreous, EnemySprite.TrinexxRockHead, EnemySprite.TrinexxFireHead,
|
||||
EnemySprite.TrinexxIceHead, EnemySprite.Blind, EnemySprite.Kholdstare, EnemySprite.KholdstareShell,
|
||||
EnemySprite.FallingIce, EnemySprite.Arrghi, EnemySprite.Agahnim, EnemySprite.Ganon,
|
||||
EnemySprite.PositionTarget, EnemySprite.Boulders
|
||||
}
|
||||
|
||||
|
||||
def randomize_enemies(world, player):
|
||||
if world.enemy_shuffle[player] != 'none':
|
||||
data_tables = world.data_tables[player]
|
||||
custom_uw, custom_ow = {}, {}
|
||||
enemy_map = world.customizer.get_enemies() if world.customizer else None
|
||||
if enemy_map and player in enemy_map:
|
||||
if 'Underworld' in enemy_map[player]:
|
||||
custom_uw = enemy_map[player]['Underworld']
|
||||
if 'Overworld' in enemy_map[player]:
|
||||
custom_ow = enemy_map[player]['Overworld']
|
||||
randomize_underworld_sprite_sheets(data_tables.sprite_sheets, data_tables, custom_uw)
|
||||
randomize_underworld_rooms(data_tables, world, player, custom_uw)
|
||||
randomize_overworld_sprite_sheets(data_tables.sprite_sheets, data_tables, custom_ow)
|
||||
randomize_overworld_enemies(data_tables, custom_ow)
|
||||
# fix thief stats
|
||||
# subclass_table = world.damage_table[player].damage_table['SubClassTable']
|
||||
# subclass_table[EnemySprite.Thief] = subclass_table[EnemySprite.GreenEyegoreMimic]
|
||||
# data_tables.enemy_stats[EnemySprite.Thief].health = 4
|
||||
# could turn droppable on here if we wanted for killable theives
|
||||
# health shuffle
|
||||
if world.enemy_health[player] != 'default':
|
||||
stats = world.data_tables[player].enemy_stats
|
||||
min_health = {'easy': 1, 'normal': 2, 'hard': 2, 'expert': 4}
|
||||
max_health = {'easy': 4, 'normal': 15, 'hard': 25, 'expert': 50}
|
||||
min_h = min_health[world.enemy_health[player]]
|
||||
max_h = max_health[world.enemy_health[player]]
|
||||
for sprite, stat in stats.items():
|
||||
if sprite == EnemySprite.Octorok4Way:
|
||||
stat.health = stats[EnemySprite.Octorok].health # these guys share data
|
||||
elif sprite == EnemySprite.GreenMimic:
|
||||
stat.health = stats[EnemySprite.GreenEyegoreMimic].health # these share data
|
||||
elif sprite == EnemySprite.RedMimic:
|
||||
stat.health = stats[EnemySprite.RedEyegoreMimic].health # these share data
|
||||
elif sprite not in skip_sprites:
|
||||
if isinstance(stat.health, tuple):
|
||||
stat.health = random.randint(min_h, max_h), random.randint(min_h, max_h)
|
||||
else:
|
||||
stat.health = random.randint(min_h, max_h)
|
||||
if world.enemy_damage[player] != 'default':
|
||||
stats = world.data_tables[player].enemy_stats
|
||||
# randomize damage groupings
|
||||
for sprite, stat in stats.items():
|
||||
if sprite == EnemySprite.Octorok4Way:
|
||||
stat.damage = stats[EnemySprite.Octorok].damage # these guys share data
|
||||
elif sprite == EnemySprite.GreenMimic:
|
||||
stat.damage = stats[EnemySprite.GreenEyegoreMimic].damage # these share data
|
||||
elif sprite == EnemySprite.RedMimic:
|
||||
stat.damage = stats[EnemySprite.RedEyegoreMimic].damage # these share data
|
||||
elif sprite == EnemySprite.Thief: # always group 0 for 0 damage
|
||||
stat.damage = 0
|
||||
elif sprite not in skip_sprites:
|
||||
if isinstance(stat.damage, tuple):
|
||||
stat.damage = random.randint(0, 8), random.randint(0, 8)
|
||||
else:
|
||||
stat.damage = random.randint(0, 8)
|
||||
# randomize bump table
|
||||
original_table = [
|
||||
(0x02, 0x01, 0x01),
|
||||
(0x04, 0x04, 0x04),
|
||||
(0x00, 0x00, 0x00),
|
||||
(0x08, 0x04, 0x02),
|
||||
(0x08, 0x08, 0x08),
|
||||
(0x10, 0x08, 0x04),
|
||||
(0x20, 0x10, 0x08),
|
||||
(0x20, 0x18, 0x10),
|
||||
(0x18, 0x10, 0x08),
|
||||
(0x40, 0x30, 0x18)]
|
||||
for i in range(0, 10):
|
||||
if i == 0: # group 0 will always be 0 for thieves
|
||||
green_mail, blue_mail, red_mail = 0, 0, 0
|
||||
del original_table[2]
|
||||
else:
|
||||
if world.enemy_damage[player] == 'random':
|
||||
green_mail = random.randint(0, 64)
|
||||
if world.enemy_damage[player] == 'random':
|
||||
blue_mail = random.randint(0, 64)
|
||||
red_mail = random.randint(0, 64)
|
||||
else:
|
||||
idx = random.randint(0, len(original_table)-1)
|
||||
green_mail, blue_mail, red_mail = original_table[idx]
|
||||
del original_table[idx]
|
||||
world.data_tables[player].enemy_damage[i] = [green_mail, blue_mail, red_mail]
|
||||
|
||||
|
||||
def write_enemy_shuffle_settings(world, player, rom):
|
||||
if world.dropshuffle[player] in ['underworld']:
|
||||
rom.write_byte(snes_to_pc(0x368109), 0x01)
|
||||
if world.enemy_shuffle[player] != 'none':
|
||||
# enable new mimics
|
||||
rom.write_byte(snes_to_pc(0x368105), 0x01)
|
||||
|
||||
# killable thief
|
||||
# rom.write_byte(snes_to_pc(0x368108), 0xc4)
|
||||
# rom.write_byte(snes_to_pc(0x0DB237), 4) # health value - randomize it if killable, maybe
|
||||
|
||||
# mimic room barriers
|
||||
data_tables = world.data_tables[player]
|
||||
mimic_room = data_tables.room_list[0x10c] = Room010C
|
||||
mimic_room.layer1[40].data[0] = 0x54 # rail adjust
|
||||
mimic_room.layer1[40].data[1] = 0x9C
|
||||
mimic_room.layer1[45].data[1] = 0xB0 # block adjust 1
|
||||
mimic_room.layer1[47].data[1] = 0xD0 # block adjust 2
|
||||
|
||||
# random tile pattern
|
||||
pattern_name, tile_pattern = random.choice(tile_patterns)
|
||||
rom.write_byte(snes_to_pc(0x9BA1D), len(tile_pattern))
|
||||
for idx, pair in enumerate(tile_pattern):
|
||||
rom.write_byte(snes_to_pc(0x09BA2A + idx), (pair[0] + 3) * 16)
|
||||
rom.write_byte(snes_to_pc(0x09BA40 + idx), (pair[1] + 4) * 16)
|
||||
if world.enemy_shuffle[player] == 'random':
|
||||
rom.write_byte(snes_to_pc(0x368100), 1) # randomize bushes
|
||||
185
source/enemizer/EnemizerTestHarness.py
Normal file
185
source/enemizer/EnemizerTestHarness.py
Normal file
@@ -0,0 +1,185 @@
|
||||
from types import SimpleNamespace
|
||||
from collections import Counter, defaultdict
|
||||
|
||||
from source.dungeon.EnemyList import enemy_names, SpriteType
|
||||
from source.enemizer.Enemizer import randomize_underworld_rooms, randomize_overworld_enemies
|
||||
from source.enemizer.SpriteSheets import randomize_underworld_sprite_sheets, randomize_overworld_sprite_sheets
|
||||
from source.rom.DataTables import init_data_tables
|
||||
from source.enemizer.DamageTables import DamageTable
|
||||
import RaceRandom as random
|
||||
|
||||
|
||||
def calculate_odds():
|
||||
ctr_uw = Counter()
|
||||
ctr_ow = Counter()
|
||||
for trial in range(0, 100):
|
||||
world = SimpleNamespace(pottery={1: 'none'}, damage_table={1: DamageTable()})
|
||||
data_tables = init_data_tables(world, 1)
|
||||
|
||||
randomize_underworld_sprite_sheets(data_tables.sprite_sheets, data_tables)
|
||||
randomize_overworld_sprite_sheets(data_tables.sprite_sheets)
|
||||
|
||||
for num in range(65, 124):
|
||||
sheet = data_tables.sprite_sheets[num]
|
||||
ret = []
|
||||
for req in data_tables.sprite_requirements.values():
|
||||
if not isinstance(req, dict) and sheet.valid_sprite(req) and not req.overlord and not req.static:
|
||||
ret.append(enemy_names[req.sprite])
|
||||
for x in ret:
|
||||
ctr_uw[x] += 1
|
||||
|
||||
for num in range(1, 64):
|
||||
sheet = data_tables.sprite_sheets[num]
|
||||
ret = []
|
||||
for req in data_tables.sprite_requirements.values():
|
||||
if not isinstance(req, dict) and sheet.valid_sprite(req) and not req.overlord and not req.static:
|
||||
ret.append(enemy_names[req.sprite])
|
||||
for x in ret:
|
||||
ctr_ow[x] += 1
|
||||
ttl = sum(ctr_uw.values())
|
||||
print(f'UW: # Total {ttl}')
|
||||
for k, v in ctr_uw.items():
|
||||
weight = round(.01 * ttl * 100 / v)
|
||||
print(f' {k}: {weight} # {v*100/ttl:.5f}% raw:{v}')
|
||||
ttl = sum(ctr_ow.values())
|
||||
print(f'OW: # Total {ttl}')
|
||||
for k, v in ctr_ow.items():
|
||||
weight = round(.01 * ttl * 100 / v)
|
||||
print(f' {k}: {weight} # {v*100/ttl:.5f}% raw:{v}')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
# calculate_odds()
|
||||
random.seed(42)
|
||||
#
|
||||
frequency = Counter()
|
||||
sheet_ctr = Counter()
|
||||
ctr_uw = Counter()
|
||||
ctr_ow = Counter()
|
||||
sheet_thing = Counter()
|
||||
sheet_sub_groups = defaultdict(set)
|
||||
|
||||
for trial in range(0, 100):
|
||||
world = SimpleNamespace(pottery={1: 'none'}, damage_table={1: DamageTable()}, any_enemy_logic={1: 'allow_all'},
|
||||
dropshuffle={1: 'none'})
|
||||
data_tables = init_data_tables(world, 1)
|
||||
stats = data_tables.enemy_stats
|
||||
|
||||
def randomize_able_sprite(sprite, stats):
|
||||
if sprite.static:
|
||||
return False
|
||||
if sprite.sub_type == 0x7 and sprite.kind != 0x9:
|
||||
return False
|
||||
if sprite.sub_type == 0x7 and sprite.kind == 0x9:
|
||||
return True
|
||||
return sprite.kind not in stats or not stats[sprite.kind].static
|
||||
|
||||
if trial == 0:
|
||||
print(f' Underworld:')
|
||||
for room_id, enemy_list in data_tables.uw_enemy_table.room_map.items():
|
||||
print(f' {hex(room_id)}:')
|
||||
for i, sprite in enumerate(enemy_list):
|
||||
if randomize_able_sprite(sprite, stats):
|
||||
print(f' {i}: {str(sprite)}')
|
||||
print(f' Overworld:')
|
||||
for area, enemy_list in data_tables.ow_enemy_table.items():
|
||||
print(f' {hex(area)}:')
|
||||
for i, sprite in enumerate(enemy_list):
|
||||
if randomize_able_sprite(sprite, stats):
|
||||
print(f' {i}: {str(sprite)}')
|
||||
|
||||
randomize_underworld_sprite_sheets(data_tables.sprite_sheets, data_tables, {})
|
||||
randomize_underworld_rooms(data_tables, world, 1)
|
||||
randomize_overworld_sprite_sheets(data_tables.sprite_sheets, data_tables, {})
|
||||
randomize_overworld_enemies(data_tables)
|
||||
|
||||
for room_id, enemy_list in data_tables.uw_enemy_table.room_map.items():
|
||||
# print(f'Room {hex(room_id)}:')
|
||||
for i, sprite in enumerate(enemy_list):
|
||||
if randomize_able_sprite(sprite, stats):
|
||||
result = str(sprite)
|
||||
frequency[result] += 1
|
||||
for area, enemy_list in data_tables.ow_enemy_table.items():
|
||||
for i, sprite in enumerate(enemy_list):
|
||||
if randomize_able_sprite(sprite, stats):
|
||||
result = str(sprite)
|
||||
frequency[result] += 1
|
||||
|
||||
for num in range(65, 124):
|
||||
if num in {65, 69, 71, 78, 79, 82, 88, 98}:
|
||||
continue
|
||||
sheet = data_tables.sprite_sheets[num]
|
||||
ret = []
|
||||
for req in data_tables.sprite_requirements.values():
|
||||
if not isinstance(req, dict) and sheet.valid_sprite(req) and not req.overlord and not req.static:
|
||||
ret.append(enemy_names[req.sprite])
|
||||
for x in ret:
|
||||
ctr_uw[x] += 1
|
||||
sheet_ctr[x] += 1
|
||||
key = tuple(sorted(ret))
|
||||
sheet_thing[key] += 1
|
||||
sheet_sub_groups[key].add(tuple(sheet.sub_groups))
|
||||
|
||||
for num in range(1, 64):
|
||||
if num == 6:
|
||||
continue
|
||||
sheet = data_tables.sprite_sheets[num]
|
||||
ret = []
|
||||
for req in data_tables.sprite_requirements.values():
|
||||
if not isinstance(req, dict) and sheet.valid_sprite(req) and not req.overlord and not req.static:
|
||||
ret.append(enemy_names[req.sprite])
|
||||
for x in ret:
|
||||
ctr_ow[x] += 1
|
||||
sheet_ctr[x] += 1
|
||||
key = tuple(sorted(ret))
|
||||
sheet_thing[key] += 1
|
||||
sheet_sub_groups[key].add(tuple(sheet.sub_groups))
|
||||
|
||||
total_sheets = sum(sheet_thing.values())
|
||||
ttl = sum(ctr_uw.values())
|
||||
print(f'UW: # Total {ttl}')
|
||||
for k in sorted(list(ctr_uw.keys())):
|
||||
v = ctr_uw[k]
|
||||
weight = round(.01 * ttl * 100 / v)
|
||||
print(f' {k}: {weight} # {v*100/ttl:.5f}% raw:{v} {v*100/total_sheets:.5f}%')
|
||||
ttl = sum(ctr_ow.values())
|
||||
print(f'OW: # Total {ttl}')
|
||||
for k in sorted(list(ctr_ow.keys())):
|
||||
v = ctr_ow[k]
|
||||
weight = round(.01 * ttl * 100 / v)
|
||||
print(f' {k}: {weight} # {v*100/ttl:.5f}% raw:{v} {v*100/total_sheets:.5f}%')
|
||||
|
||||
ttl = sum(sheet_ctr.values())
|
||||
print(f'Sheet: # Total {ttl}')
|
||||
for k, v in sheet_ctr.items():
|
||||
print(f' {k} {v*100/ttl:.5f}% raw:{v} {v*100/total_sheets:.5f}%')
|
||||
|
||||
ttl = sum(frequency.values())
|
||||
print(f'Total: {ttl}')
|
||||
for enemy, freq in frequency.items():
|
||||
print(f'{enemy} {freq*100/ttl:.5f}% raw:{freq}')
|
||||
|
||||
ttl = sum(sheet_thing.values())
|
||||
print(f'Total Sheets?: {ttl}')
|
||||
|
||||
def rejoin(list_of_things):
|
||||
return f'[{",".join([str(i) for i in list_of_things])}]'
|
||||
|
||||
for items, cnt in sheet_thing.items():
|
||||
print(f'{",".join(items)} {cnt} {cnt*100/ttl:.5f}% {",".join([rejoin(x) for x in sheet_sub_groups[items]])}')
|
||||
|
||||
# if result not in column_headers:
|
||||
# column_headers[result] = None
|
||||
# stats[(room_id, i)][result] += 1
|
||||
# with open('result.csv', 'w') as result_file:
|
||||
# result_file.write('room_id,slot,')
|
||||
# result_file.write(','.join(column_headers.keys()))
|
||||
# result_file.write('\n')
|
||||
#
|
||||
# for key, counter in stats.items():
|
||||
# rid, slot = key
|
||||
# result_file.write(f'{rid},{slot}')
|
||||
# for result_item in column_headers.keys():
|
||||
# result_file.write(f',{counter[result_item]}')
|
||||
# result_file.write('\n')
|
||||
|
||||
525
source/enemizer/EnemyLogic.py
Normal file
525
source/enemizer/EnemyLogic.py
Normal file
@@ -0,0 +1,525 @@
|
||||
import math
|
||||
from collections import defaultdict
|
||||
|
||||
import RaceRandom as random
|
||||
|
||||
from source.logic.Rule import RuleFactory
|
||||
from source.dungeon.EnemyList import EnemySprite
|
||||
|
||||
|
||||
# these are for drops only
|
||||
def defeat_rule_single(world, player, enemy_sprite, region):
|
||||
if enemy_sprite.kind == EnemySprite.Terrorpin:
|
||||
# must be flipped
|
||||
return has('Hammer', player)
|
||||
elif enemy_sprite.kind == EnemySprite.RedBari:
|
||||
# must be burned to drop
|
||||
return or_rule(has('Fire Rod', player), and_rule(has_sword(player), has('Bombos', player)))
|
||||
vln = enemy_vulnerability(world, player, enemy_sprite, region)
|
||||
rules = []
|
||||
if vln['Blunt'] != 0:
|
||||
rules.append(has_blunt_weapon(player))
|
||||
if vln['Stun'] != 0:
|
||||
rules.append(buzzblob_rule(player))
|
||||
if vln['Somaria'] != 0:
|
||||
rules.append(somaria_rule(world, player, vln['Somaria']))
|
||||
if vln['Byrna'] != 0:
|
||||
rules.append(byrna_rule(world, player, vln['Byrna']))
|
||||
if vln['Master'] != 0:
|
||||
rules.append(has_class_2_weapon(player))
|
||||
if vln['Bow'] != 0:
|
||||
rules.append(bow_rule(world, player, vln['Bow']))
|
||||
if vln['Silvers'] != 0:
|
||||
rules.append(silvers_rule(world, player, vln['Silvers']))
|
||||
if vln['Bomb'] != 0:
|
||||
rules.append(bombs_rule(world, player, vln['Bomb']))
|
||||
if vln['Hookshot'] != 0:
|
||||
rules.append(has('Hookshot', player))
|
||||
if vln['IceRod'] != 0:
|
||||
rules.append(ice_rod_rule(world, player, vln['IceRod']))
|
||||
if vln['FireRod'] != 0:
|
||||
rules.append(fire_rod_rule(world, player, vln['FireRod']))
|
||||
if vln['Boomerang'] != 0:
|
||||
rules.append(has_boomerang(player))
|
||||
if vln['Powder'] not in [0, -3]: # fairy doesn't make it drop
|
||||
rules.append(magic_powder_rule(world, player, vln['Powder']))
|
||||
# skip medallions if vln to Blunt?
|
||||
if vln['Bombos'] != 0 and vln['Blunt'] == 0:
|
||||
rules.append(medallion_rule(world, player, 'Bombos', vln['Bombos']))
|
||||
if vln['Ether'] != 0 and vln['Blunt'] == 0:
|
||||
rules.append(medallion_rule(world, player, 'Ether', vln['Ether']))
|
||||
if vln['Quake'] != 0 and vln['Blunt'] == 0:
|
||||
rules.append(medallion_rule(world, player, 'Quake', vln['Quake']))
|
||||
if enemy_sprite.kind == EnemySprite.StalfosKnight:
|
||||
# must be bombed once made vulnerable
|
||||
return and_rule(can_use_bombs(world, player), or_rule(*rules))
|
||||
return or_rule(*rules)
|
||||
|
||||
|
||||
damage_cost = {
|
||||
'Bomb': 1, 'Bow': 1, 'Silvers': 1,
|
||||
'Powder': .5, 'Somaria': .5, 'Byrna': 1.125,
|
||||
'FireRod': 1, 'IceRod': 1,
|
||||
'Bombos': 2, 'Ether': 2, 'Quake': 2
|
||||
}
|
||||
|
||||
# damage_set = ['Blunt', 'Stun', 'Master', 'Tempered', 'Boomerang', 'Hookshot', 'Bomb', 'Silvers', 'Bow',
|
||||
# 'Somaria', 'Powder', 'FireRod', 'IceRod', 'Byrna', 'Bombos', 'Ether', 'Quake']
|
||||
|
||||
|
||||
# these are for "challenge" rooms
|
||||
def defeat_rule_multiple(world, player, enemy_sprite_region_pairs):
|
||||
vln_list = {}
|
||||
for sprite, region in enemy_sprite_region_pairs:
|
||||
vln_list[(sprite, region)] = enemy_vulnerability(world, player, sprite, region)
|
||||
|
||||
# damage_accounting = {x: list(y) for x, y in damage_types.items()}
|
||||
used_resources = {'Bomb': 0, 'Arrow': 0, 'Magic': 0}
|
||||
required_rules = []
|
||||
picky_enemies = []
|
||||
hammer_required = False
|
||||
bombs_required = False
|
||||
|
||||
for key, vln in vln_list.items():
|
||||
if key[0].kind == EnemySprite.Terrorpin:
|
||||
if not hammer_required:
|
||||
required_rules.append(has('Hammer', player))
|
||||
hammer_required = True
|
||||
picky_enemies.append(key)
|
||||
continue
|
||||
if key[0].kind == EnemySprite.StalfosKnight:
|
||||
if not bombs_required:
|
||||
required_rules.append(bombs_rule(world, player, 1))
|
||||
bombs_required = True
|
||||
used_resources['Bomb'] += 1
|
||||
picky_enemies.append(key)
|
||||
continue
|
||||
vln_types = [k for k in vln.keys() if vln[k] != 0]
|
||||
if len(vln_types) == 1:
|
||||
d_type = vln_types[0]
|
||||
required_rules.append(defeat_rule_single(world, player, key[0], key[1]))
|
||||
picky_enemies.append(key)
|
||||
if d_type in damage_cost:
|
||||
cost = damage_cost[d_type]
|
||||
if d_type == 'Bomb':
|
||||
used_resources['Bomb'] += cost
|
||||
elif d_type in ['Bow', 'Silvers']:
|
||||
used_resources['Arrow'] += cost
|
||||
else:
|
||||
used_resources['Magic'] += cost
|
||||
vln_list = {k: v for k, v in vln_list.items() if k not in picky_enemies}
|
||||
|
||||
while len(vln_list) > 0:
|
||||
|
||||
optional_clears = find_possible_rules(vln_list, used_resources, world, player)
|
||||
if len(optional_clears) == 0:
|
||||
raise Exception('Kill rules seems to be insufficient for this enemy set, please report:'
|
||||
+ ', '.join([str(x) for x, y in enemy_sprite_region_pairs]))
|
||||
|
||||
# find rules which kill the most
|
||||
# idea: this could be multiple criteria: most-constrained then which method kills the most
|
||||
best_rules = {}
|
||||
best_size = 0
|
||||
for vln_option in optional_clears.keys():
|
||||
if len(vln_option) > best_size:
|
||||
best_size = len(vln_option)
|
||||
best_rules.clear()
|
||||
best_rules[vln_option] = optional_clears[vln_option]
|
||||
elif len(vln_option) == best_size: # assumes vln_option is different from prior options
|
||||
best_rules[vln_option] = optional_clears[vln_option]
|
||||
if len(best_rules) == 1:
|
||||
vln_option, rule_pair_list = next(iter(best_rules.items()))
|
||||
else:
|
||||
vln_option, rule_pair_list = random.choice(list(best_rules.items()))
|
||||
if best_size == 0:
|
||||
raise Exception('Invulnerable enemy? rules seems to be insufficient for this enemy set, please report:'
|
||||
+ ', '.join([str(x) for x, y in enemy_sprite_region_pairs]))
|
||||
|
||||
new_vln_list = {vln_kv[0]: vln_kv[1] for idx, vln_kv in enumerate(vln_list.items()) if idx not in vln_option}
|
||||
rules_to_add = [rule for rule, resources in rule_pair_list]
|
||||
resources_to_use = [resources for rule, resources in rule_pair_list]
|
||||
required_rules.append(or_rule(*rules_to_add))
|
||||
for r in resources_to_use:
|
||||
for k, v in r.items():
|
||||
used_resources[k] += v
|
||||
vln_list = new_vln_list
|
||||
|
||||
return and_rule(*required_rules)
|
||||
|
||||
|
||||
def find_possible_rules(vln_list, used_resources, world, player):
|
||||
optional_clears = defaultdict(list)
|
||||
blunt_marker = defaultdict(bool)
|
||||
for damage_type in ['Blunt', 'Stun', 'Master', 'Boomerang', 'Hookshot']:
|
||||
# all_vln = all(vln[damage_type] != 0 for vln in vln_list.values())
|
||||
vln_sub_list = frozenset({idx for idx, vln in enumerate(vln_list.values()) if vln[damage_type] != 0})
|
||||
if vln_sub_list:
|
||||
if damage_type == 'Blunt':
|
||||
optional_clears[vln_sub_list].append((has_blunt_weapon(player), {}))
|
||||
blunt_marker[vln_sub_list] = True
|
||||
if damage_type == 'Stun':
|
||||
optional_clears[vln_sub_list].append((buzzblob_rule(player), {}))
|
||||
if damage_type == 'Master' and not blunt_marker[vln_sub_list]:
|
||||
optional_clears[vln_sub_list].append((has_class_2_weapon(player), {}))
|
||||
if damage_type == 'Boomerang':
|
||||
optional_clears[vln_sub_list].append((has('Hookshot', player), {}))
|
||||
elif damage_type == 'Hookshot':
|
||||
optional_clears[vln_sub_list].append((has_boomerang(player), {}))
|
||||
damage_type = 'Bomb'
|
||||
vln_sub_list = frozenset({idx for idx, vln in enumerate(vln_list.values()) if vln[damage_type] != 0})
|
||||
if vln_sub_list:
|
||||
hits = needed_resources(damage_type, vln_list)
|
||||
if hits + used_resources['Bomb'] <= 8:
|
||||
optional_clears[vln_sub_list].append(
|
||||
(bombs_rule(world, player, hits + used_resources['Bomb']), {'Bomb': hits}))
|
||||
for damage_type in ['Bow', 'Silvers']:
|
||||
vln_sub_list = frozenset({idx for idx, vln in enumerate(vln_list.values()) if vln[damage_type] != 0})
|
||||
if vln_sub_list:
|
||||
hits = needed_resources(damage_type, vln_list)
|
||||
resources = {'Arrow': hits}
|
||||
if damage_type == 'Bow' and hits + used_resources['Arrow'] <= 25:
|
||||
optional_clears[vln_sub_list].append(
|
||||
(bow_rule(world, player, hits + used_resources['Arrow']), resources))
|
||||
if damage_type == 'Silvers' and hits + used_resources['Arrow'] <= 25:
|
||||
optional_clears[vln_sub_list].append(
|
||||
(silvers_rule(world, player, hits + used_resources['Arrow']), resources))
|
||||
for damage_type in ['Powder', 'Somaria', 'Byrna', 'FireRod', 'IceRod', 'Bombos', 'Ether', 'Quake']:
|
||||
vln_sub_list = frozenset({idx for idx, vln in enumerate(vln_list.values()) if vln[damage_type] != 0})
|
||||
if vln_sub_list:
|
||||
hits = needed_resources(damage_type, vln_list)
|
||||
resources = {'Magic': damage_cost[damage_type] * hits}
|
||||
if damage_type == 'Powder' and math.ceil(hits / 16) * 8 + used_resources['Magic'] <= 160:
|
||||
flag = min(vln[damage_type] for vln in vln_list.values())
|
||||
flag = flag if flag < 0 else (hits + used_resources['Magic'] * 2)
|
||||
optional_clears[vln_sub_list].append((magic_powder_rule(world, player, flag), resources))
|
||||
elif damage_type == 'Somaria' and math.ceil(hits / 64) * 8 + used_resources['Magic'] <= 160:
|
||||
flag = min(vln[damage_type] for vln in vln_list.values())
|
||||
flag = flag if flag < 0 else (hits + used_resources['Magic'] * 8)
|
||||
optional_clears[vln_sub_list].append((somaria_rule(world, player, flag), resources))
|
||||
elif damage_type == 'Byrna' and math.ceil(hits / 7) * 8 + used_resources['Magic'] <= 160:
|
||||
flag = min(vln[damage_type] for vln in vln_list.values())
|
||||
flag = flag if flag < 0 else (hits + used_resources['Magic'] * 7 / 8)
|
||||
optional_clears[vln_sub_list].append((byrna_rule(world, player, flag), resources))
|
||||
elif damage_type == 'FireRod' and hits + used_resources['Magic'] <= 160:
|
||||
flag = min(vln[damage_type] for vln in vln_list.values())
|
||||
flag = flag if flag < 0 else (hits + used_resources['Magic'])
|
||||
optional_clears[vln_sub_list].append((fire_rod_rule(world, player, flag), resources))
|
||||
elif damage_type == 'IceRod' and hits + used_resources['Magic'] <= 160:
|
||||
flag = min(vln[damage_type] for vln in vln_list.values())
|
||||
flag = flag if flag < 0 else (hits + used_resources['Magic'])
|
||||
optional_clears[vln_sub_list].append((ice_rod_rule(world, player, flag), resources))
|
||||
elif hits * 2 + used_resources['Magic'] <= 160 and not blunt_marker[vln_sub_list]:
|
||||
flag = min(vln[damage_type] for vln in vln_list.values())
|
||||
flag = flag if flag < 0 else (hits + used_resources['Magic'] / 2)
|
||||
optional_clears[vln_sub_list].append((medallion_rule(world, player, damage_type, flag), resources))
|
||||
return optional_clears
|
||||
|
||||
|
||||
def needed_resources(damage_type, vln_list):
|
||||
return sum(vln[damage_type] if vln[damage_type] >= 0 else 1 for vln in vln_list.values() if vln[damage_type] != 0)
|
||||
|
||||
|
||||
special_rules_check = {
|
||||
'Swamp Waterway': None,
|
||||
'Hera Back': [5, 6],
|
||||
'GT Petting Zoo': [5, 8, 9, 11],
|
||||
'Mimic Cave': [4, 5, 6, 7],
|
||||
'Ice Hookshot Ledge': None,
|
||||
'TR Hub Ledges': [3, 4, 5, 6, 7],
|
||||
'TR Dark Ride': [1, 2, 3],
|
||||
'GT Speed Torch': [11, 13],
|
||||
'Old Man Cave (West)': None,
|
||||
'Old Man Cave (East)': None,
|
||||
'Old Man House': [1, 3],
|
||||
'Old Man House Back': [4, 5, 6],
|
||||
'Death Mountain Return Cave (left)': None,
|
||||
'Death Mountain Return Cave (right)': [1, 2, 3, 6, 7], # 2, 5, 6 are considered embedded
|
||||
'Hookshot Fairy': [0, 1, 2, 3]
|
||||
}
|
||||
|
||||
|
||||
def special_rules_for_region(world, player, region_name, location, original_rule):
|
||||
if region_name == 'Swamp Waterway':
|
||||
return or_rule(medallion_rule(world, player, 'Quake', 1),
|
||||
medallion_rule(world, player, 'Ether', 1),
|
||||
medallion_rule(world, player, 'Bombos', 1))
|
||||
elif region_name in ['Hera Back', 'GT Petting Zoo', 'Mimic Cave']:
|
||||
enemy_number = int(location.name.split('#')[1])
|
||||
if region_name == 'Mimic Cave':
|
||||
if enemy_number in [4, 5]: # these are behind hammer blocks potentially
|
||||
return and_rule(original_rule, has('Hammer', player))
|
||||
elif enemy_number in special_rules_check[region_name]: # these are behind rails
|
||||
return and_rule(original_rule, has_boomerang(player))
|
||||
if enemy_number in special_rules_check[region_name]:
|
||||
return and_rule(original_rule, has_boomerang(player))
|
||||
else:
|
||||
return original_rule
|
||||
elif region_name in ['TR Hub Ledges', 'Ice Hookshot Ledge', 'TR Dark Ride']:
|
||||
enemy_number = int(location.name.split('#')[1])
|
||||
if special_rules_check[region_name] is None or enemy_number in special_rules_check[region_name]:
|
||||
return and_rule(original_rule, or_rule(has_boomerang(player), has('Hookshot', player)))
|
||||
else:
|
||||
return original_rule
|
||||
elif region_name in ['Old Man Cave (West)', 'Old Man Cave (East)', 'Old Man House Back', 'Old Man House',
|
||||
'Death Mountain Return Cave (left)', 'Death Mountain Return Cave (right)',
|
||||
'Hookshot Fairy']:
|
||||
enemy_number = int(location.name.split('#')[1])
|
||||
if region_name == 'Death Mountain Return Cave (left)':
|
||||
if enemy_number in [1, 5]:
|
||||
return and_rule(original_rule, or_rule(has_boomerang(player), has('Hookshot', player)))
|
||||
else:
|
||||
return and_rule(original_rule, has('Hookshot', player))
|
||||
if special_rules_check[region_name] is None or enemy_number in special_rules_check[region_name]:
|
||||
return and_rule(original_rule, has('Hookshot', player))
|
||||
else:
|
||||
return original_rule
|
||||
return original_rule
|
||||
|
||||
|
||||
def has_blunt_weapon(player):
|
||||
return or_rule(has_sword(player), has('Hammer', player))
|
||||
|
||||
|
||||
# Bombs, Arrows, Bombos, FireRod, Somaria, Byrna should be handled by the damage table logic
|
||||
# Powder doesn't work (also handled by damage table)
|
||||
def buzzblob_rule(player):
|
||||
return or_rule(has('Golden Sword', player),
|
||||
and_rule(has_blunt_weapon(player),
|
||||
or_rule(has_boomerang(player), has('Hookshot', player), has('Ice Rod', player))),
|
||||
and_rule(has('Ether', player), has_sword(player)),
|
||||
and_rule(has('Quake', player), has_sword(player)))
|
||||
|
||||
|
||||
def has_class_2_weapon(player):
|
||||
return or_rule(has_beam_sword(player), has('Hammer', player))
|
||||
|
||||
|
||||
def somaria_rule(world, player, somaria_hits):
|
||||
if somaria_hits == -1:
|
||||
return has('Cane of Somaria', player) # insta-kill somaria? - not in vanilla
|
||||
else:
|
||||
magic_needed = math.ceil(somaria_hits / 64) * 8 # 64 hits per magic bar - 80 max?
|
||||
if magic_needed > 8:
|
||||
return and_rule(has('Cane of Somaria', player), can_extend_magic(world, player, magic_needed))
|
||||
else:
|
||||
return has('Cane of Somaria', player)
|
||||
|
||||
|
||||
def byrna_rule(world, player, byrna_hits):
|
||||
if byrna_hits == -1:
|
||||
return has('Cane of Byrna', player) # insta-kill byrna? - not in vanilla
|
||||
else:
|
||||
magic_needed = math.ceil(byrna_hits / 7) * 8 # 7 hits per magic bar - generous?
|
||||
if magic_needed > 8:
|
||||
return and_rule(has('Cane of Byrna', player), can_extend_magic(world, player, magic_needed))
|
||||
else:
|
||||
return has('Cane of Byrna', player)
|
||||
|
||||
|
||||
def bow_rule(world, player, arrows):
|
||||
if arrows == -1 or 0 < arrows <= 25:
|
||||
return can_shoot_normal_arrows(world, player)
|
||||
return RuleFactory.static_rule(False)
|
||||
|
||||
|
||||
def silvers_rule(world, player, arrows):
|
||||
if arrows == -1 or 0 < arrows <= 25:
|
||||
return can_shoot_silver_arrows(world, player)
|
||||
return RuleFactory.static_rule(False)
|
||||
|
||||
|
||||
def bombs_rule(world, player, bombs):
|
||||
if bombs == -1 or 0 < bombs <= 8:
|
||||
return can_use_bombs(world, player)
|
||||
return RuleFactory.static_rule(False)
|
||||
|
||||
|
||||
def ice_rod_rule(world, player, shots):
|
||||
if shots == -1:
|
||||
return has('Ice Rod', player)
|
||||
if shots > 8:
|
||||
return and_rule(has('Ice Rod', player), can_extend_magic(world, player, shots))
|
||||
else:
|
||||
return has('Ice Rod', player)
|
||||
|
||||
|
||||
def fire_rod_rule(world, player, shots):
|
||||
if shots == -1:
|
||||
return has('Fire Rod', player)
|
||||
if shots > 8:
|
||||
return and_rule(has('Fire Rod', player), can_extend_magic(world, player, shots))
|
||||
else:
|
||||
return has('Fire Rod', player)
|
||||
|
||||
|
||||
def magic_powder_rule(world, player, shots):
|
||||
if shots == -1:
|
||||
return has('Magic Powder', player)
|
||||
if shots == -2:
|
||||
# todo: other resources possible I guess - harder to keep track of though
|
||||
return and_rule(has('Magic Powder', player), or_rule(has_blunt_weapon(player), has('Hookshot', player)))
|
||||
magic_needed = math.ceil(shots / 16) * 8 # 16 tries per magic bar, that could be tight...
|
||||
if magic_needed > 8:
|
||||
return and_rule(has('Magic Powder', player), can_extend_magic(world, player, shots))
|
||||
else:
|
||||
return has('Magic Powder', player)
|
||||
|
||||
|
||||
def medallion_rule(world, player, medallion, shots):
|
||||
if shots == -1:
|
||||
return and_rule(has(medallion, player), has_sword(player))
|
||||
if shots == -2:
|
||||
return and_rule(has(medallion, player), has_sword(player))
|
||||
magic_needed = shots * 2
|
||||
if magic_needed > 8:
|
||||
return and_rule(has(medallion, player), has_sword(player), can_extend_magic(world, player, shots))
|
||||
else:
|
||||
return and_rule(has(medallion, player), has_sword(player))
|
||||
|
||||
|
||||
def or_rule(*rules):
|
||||
return RuleFactory.disj(rules)
|
||||
|
||||
|
||||
def and_rule(*rules):
|
||||
return RuleFactory.conj(rules)
|
||||
|
||||
|
||||
def has(item, player, count=1):
|
||||
return RuleFactory.item(item, player, count)
|
||||
|
||||
|
||||
def has_sword(player):
|
||||
return or_rule(
|
||||
has('Fighter Sword', player), has('Master Sword', player),
|
||||
has('Tempered Sword', player), has('Golden Sword', player)
|
||||
)
|
||||
|
||||
|
||||
def has_beam_sword(player):
|
||||
return or_rule(
|
||||
has('Master Sword', player), has('Tempered Sword', player), has('Golden Sword', player)
|
||||
)
|
||||
|
||||
|
||||
def has_class_3_sword(player):
|
||||
return or_rule(
|
||||
has('Tempered Sword', player), has('Golden Sword', player)
|
||||
)
|
||||
|
||||
|
||||
def can_extend_magic(world, player, magic, flag_t=False):
|
||||
potion_shops = (find_shops_that_sell('Blue Potion', world, player) |
|
||||
find_shops_that_sell('Green Potion', world, player))
|
||||
return RuleFactory.extend_magic(player, magic, world.difficulty_adjustments[player], potion_shops, flag_t)
|
||||
|
||||
|
||||
# class 0 damage (subtypes 1 and 2)
|
||||
def has_boomerang(player):
|
||||
return or_rule(has('Blue Boomerang', player), has('Red_Boomerang', player))
|
||||
|
||||
|
||||
def find_shops_that_sell(item, world, player):
|
||||
return {shop.region for shop in world.shops[player] if shop.has_unlimited(item) and shop.region.player == player}
|
||||
|
||||
|
||||
def can_shoot_normal_arrows(world, player):
|
||||
if world.bow_mode[player].startswith('retro'):
|
||||
shops = find_shops_that_sell('Single Arrow', world, player)
|
||||
# retro+shopsanity, shops may not sell the Single Arrow at all
|
||||
if world.bow_mode[player] == 'retro_silvers':
|
||||
# non-progressive silvers grant wooden arrows, so shop may not be needed
|
||||
return and_rule(has('Bow', player), or_rule(RuleFactory.unlimited('Single Arrow', player, shops),
|
||||
has('Single Arrow', player), has('Silver Arrows', player)))
|
||||
else:
|
||||
return and_rule(has('Bow', player), or_rule(RuleFactory.unlimited('Single Arrow', player, shops),
|
||||
has('Single Arrow', player)))
|
||||
return has('Bow', player)
|
||||
|
||||
|
||||
def can_shoot_silver_arrows(world, player):
|
||||
# retro_silver requires the silver arrows item which is sufficient for the quiver
|
||||
if world.bow_mode[player] == 'retro':
|
||||
shops = find_shops_that_sell('Single Arrow', world, player)
|
||||
# retro+shopsanity, shops may not sell the Single Arrow at all
|
||||
return and_rule(has('Silver Arrows', player), or_rule(RuleFactory.unlimited('Single Arrow', player, shops),
|
||||
has('Single Arrow', player)))
|
||||
return and_rule(has('Bow', player), has('Silver Arrows', player))
|
||||
|
||||
|
||||
def can_use_bombs(world, player):
|
||||
return or_rule(RuleFactory.static_rule(not world.bombbag[player]), has('Bomb Upgrade (+10)', player))
|
||||
|
||||
|
||||
def enemy_vulnerability(world, player, enemy_sprite, region):
|
||||
damage_table = world.damage_table[player].damage_table
|
||||
stats = world.data_tables[player].enemy_stats
|
||||
damage_src = damage_table['DamageSource']
|
||||
sub_class_table = damage_table['SubClassTable']
|
||||
|
||||
enemy_sub_class = sub_class_table[enemy_sprite.kind]
|
||||
|
||||
vulnerability = defaultdict(int)
|
||||
|
||||
c1 = number_of_hits('Sword1', damage_src, enemy_sub_class, stats, enemy_sprite, region)
|
||||
if c1 != 0:
|
||||
if enemy_sprite.kind == EnemySprite.Buzzblob:
|
||||
vulnerability['Stun'] = -1
|
||||
else:
|
||||
vulnerability['Blunt'] = -1
|
||||
vulnerability['Master'] = -1
|
||||
vulnerability['Somaria'] = c1
|
||||
vulnerability['Byrna'] = c1
|
||||
else:
|
||||
c2 = number_of_hits('Sword3', damage_src, enemy_sub_class, stats, enemy_sprite, region)
|
||||
if c2 != 0:
|
||||
vulnerability['Master'] = -1 # currently Lynels are only vulnerable to only master spins or above
|
||||
hits = number_of_hits('Arrow', damage_src, enemy_sub_class, stats, enemy_sprite, region)
|
||||
if hits != 0:
|
||||
vulnerability['Bow'] = hits
|
||||
hits = number_of_hits('SilverArrow', damage_src, enemy_sub_class, stats, enemy_sprite, region)
|
||||
if hits != 0:
|
||||
vulnerability['Silvers'] = hits
|
||||
for method in ['Bomb', 'Hookshot', 'FireRod', 'IceRod', 'Boomerang', 'Powder', 'Bombos', 'Ether', 'Quake']:
|
||||
hits = number_of_hits(method, damage_src, enemy_sub_class, stats, enemy_sprite, region)
|
||||
if hits == -3:
|
||||
if enemy_sprite.kind != EnemySprite.Buzzblob: # buzzblobs are special and don't die
|
||||
vulnerability[method] = -1
|
||||
elif hits != 0:
|
||||
vulnerability[method] = hits
|
||||
return vulnerability
|
||||
|
||||
|
||||
def number_of_hits(source_name, damage_src, enemy_sub_class, stats, enemy_sprite, region):
|
||||
damage_class = damage_src[source_name]['class']
|
||||
sub_class = enemy_sub_class[damage_class]
|
||||
damage_amount = damage_src[source_name]['subclass'][sub_class]
|
||||
if damage_amount == 0:
|
||||
return 0
|
||||
elif damage_amount <= 0x64:
|
||||
health = stats[enemy_sprite.kind].health
|
||||
if isinstance(health, tuple):
|
||||
if enemy_sprite.kind in [EnemySprite.Tektite, EnemySprite.HardhatBeetle]:
|
||||
idx = enemy_sprite.tile_x & 0x1
|
||||
health = health[idx]
|
||||
elif region.is_light_world and region.is_dark_world:
|
||||
health = min(health)
|
||||
elif region.is_light_world:
|
||||
health = health[0]
|
||||
elif region.is_dark_world:
|
||||
health = health[1]
|
||||
else:
|
||||
health = max(health)
|
||||
return math.ceil(health / damage_amount)
|
||||
elif damage_amount in [0xF9, 0xFA, 0xFD]:
|
||||
# -1 incinerated; -2 blobbed, -3 fairy-ed (depends on enemy if "killed" or not)
|
||||
# F9: fairy, defeated, but doesn't drop anything: -3
|
||||
# FA: blobbed - can you kill a blob? = -2
|
||||
# FD: incinerated
|
||||
return special_classes[damage_amount]
|
||||
else:
|
||||
return 0
|
||||
|
||||
|
||||
special_classes = {0xF9: -3, 0xFA: -2, 0xFD: -1}
|
||||
|
||||
1038
source/enemizer/OwEnemyList.py
Normal file
1038
source/enemizer/OwEnemyList.py
Normal file
File diff suppressed because it is too large
Load Diff
788
source/enemizer/SpriteSheets.py
Normal file
788
source/enemizer/SpriteSheets.py
Normal file
@@ -0,0 +1,788 @@
|
||||
import logging
|
||||
from collections import defaultdict
|
||||
import RaceRandom as random
|
||||
|
||||
from source.dungeon.EnemyList import EnemySprite, SpriteType, enemy_names, sprite_translation, overlord_names
|
||||
from source.dungeon.RoomConstants import *
|
||||
|
||||
|
||||
class SpriteRequirement:
|
||||
def __init__(self, sprite, overlord=0):
|
||||
self.sprite = sprite
|
||||
self.overlord = overlord
|
||||
|
||||
self.boss = False
|
||||
self.static = False # npcs and do not randomize
|
||||
self.killable = True
|
||||
self.can_drop = True
|
||||
self.water_only = False
|
||||
self.dont_use = False
|
||||
self.ow_valid = True
|
||||
self.uw_valid = True
|
||||
self.can_randomize = True
|
||||
self.water_phobic = False
|
||||
|
||||
self.groups = []
|
||||
self.sub_groups = defaultdict(list)
|
||||
|
||||
self.excluded_rooms = set()
|
||||
self.allowed_rooms = set()
|
||||
|
||||
def can_spawn_in_room(self, room_id):
|
||||
return room_id not in self.excluded_rooms and (self.sprite != EnemySprite.Wallmaster or room_id < 0x100)
|
||||
|
||||
def no_drop(self):
|
||||
self.can_drop = False
|
||||
return self
|
||||
|
||||
def sub_group(self, key, subs):
|
||||
if isinstance(subs, list):
|
||||
self.sub_groups[key].extend(subs)
|
||||
else:
|
||||
self.sub_groups[key].append(subs)
|
||||
return self
|
||||
|
||||
def group(self, group_id):
|
||||
self.groups.append(group_id)
|
||||
return self
|
||||
|
||||
def exclude(self, exclusions):
|
||||
self.excluded_rooms.update(exclusions)
|
||||
return self
|
||||
|
||||
def allow(self, allowed):
|
||||
self.allowed_rooms.update(allowed)
|
||||
return self
|
||||
|
||||
def affix(self):
|
||||
self.static = True
|
||||
self.killable = False
|
||||
self.can_drop = False
|
||||
return self
|
||||
|
||||
def stasis(self):
|
||||
self.can_randomize = False
|
||||
return self
|
||||
|
||||
def exalt(self):
|
||||
self.boss = True
|
||||
self.static = True # not randomized by sprite sheet
|
||||
return self
|
||||
|
||||
def immune(self):
|
||||
self.killable = False
|
||||
self.can_drop = False
|
||||
return self
|
||||
|
||||
def immerse(self):
|
||||
self.water_only = True
|
||||
return self
|
||||
|
||||
def aquaphobia(self):
|
||||
self.water_phobic = True
|
||||
return self
|
||||
|
||||
def skip(self):
|
||||
self.dont_use = True
|
||||
return self
|
||||
|
||||
def ow_skip(self):
|
||||
self.ow_valid = False
|
||||
return self
|
||||
|
||||
def uw_skip(self):
|
||||
self.uw_valid = False
|
||||
return self
|
||||
|
||||
def good_for_uw_water(self):
|
||||
return self.water_only and not self.static and not self.dont_use and self.uw_valid
|
||||
|
||||
def good_for_shutter(self, forbidden):
|
||||
if self.sprite in forbidden:
|
||||
return False
|
||||
return self.killable and not self.static and not self.dont_use and self.uw_valid
|
||||
|
||||
def good_for_key_drop(self, forbidden):
|
||||
return self.good_for_shutter(forbidden) and self.can_drop
|
||||
|
||||
def __str__(self):
|
||||
return f'Req for {enemy_names[self.sprite] if self.overlord != 0x7 else overlord_names[self.sprite]}'
|
||||
|
||||
|
||||
NoFlyingRooms = {0xd2, 0x10c} # Mire 2, Mimic Cave
|
||||
NoBeamosOrTrapRooms = {0xb, 0x16, 0x19, 0x1e, 0x26, 0x27, 0x36, 0x3f, 0x40, 0x42, 0x46, 0x49, 0x4b, 0x4e, 0x55, 0x57,
|
||||
0x5f, 0x65, 0x6a, 0x74, 0x76, 0x7d, 0x7f, 0x83, 0x84, 0x85, 0x8c, 0x8d, 0x92, 0x95, 0x98, 0x9b,
|
||||
0x9c, 0x9d, 0x9e, 0xa0, 0xaa, 0xaf, 0xb3, 0xba, 0xbb, 0xbc, 0xc6, 0xcb, 0xce, 0xd0, 0xd2, 0xd5,
|
||||
0xd8, 0xdc, 0xdf, 0xe4, 0xe7, 0xee, 0xf9, 0xfd, 0x10c}
|
||||
LenientTrapsForTesting = {0x16, 0x26, 0x3f, 0x40, 0x42, 0x46, 0x49, 0x4e, 0x57,
|
||||
0x65, 0x6a, 0x74, 0x76, 0x7d, 0x98,
|
||||
0x9e, 0xaf, 0xba, 0xc6, 0xcb, 0xce, 0xd2, 0xd5,
|
||||
0xd8, 0xdf, 0xe4, 0xe7, 0xee, 0xfd, 0x10c}
|
||||
# this will have to be dynamic if cave rooms are allowed in dungeons
|
||||
WallmasterValidRooms = {
|
||||
HC_NorthCorridor, HC_SwitchRoom, HoulihanRoom, TR_CrystalRollerRoom,
|
||||
PalaceofDarkness0x09, PoD_StalfosTrapRoom, PoD_TurtleRoom, GT_EntranceRoom, Ice_EntranceRoom,
|
||||
GanonEvacuationRoute, HC_BombableStockRoom, Sanctuary, TR_Hokku_BokkuKeyRoom2, TR_BigKeyRoom, TurtleRock0x15,
|
||||
Swamp_SwimmingTreadmill, Hera_MoldormFallRoom, PoD_DarkMaze, PoD_BigChestRoom, PoD_Mimics_MovingWallRoom,
|
||||
GT_IceArmos, GT_FinalHallway, Ice_BombFloor_BariRoom, Ice_Pengator_BigKeyRoom, Tower_Agahnim, HC_KeyRatRoom,
|
||||
HC_SewerTextTriggerRoom, TR_WestExittoBalcony, TR_DoubleHokku_Bokku_BigchestRoom, Swamp_StatueRoom, Hera_BigChest,
|
||||
Swamp_EntranceRoom, Skull_Mothula, PoD_BigHubRoom, PoD_MapChest_FairyRoom, Ice_CompassRoom, Hera_HardhatBeetlesRoom,
|
||||
HC_SewerKeyChestRoom, Desert_Lanmolas, Swamp_PushBlockPuzzle_Pre_BigKeyRoom, Swamp_BigKey_BSRoom,
|
||||
Swamp_BigChestRoom, Swamp_MapChest_WaterFillRoom, Swamp_KeyPotRoom, Skull_GibdoKey_MothulaHoleRoom,
|
||||
PoD_BombableFloorRoom, PoD_SpikeBlock_ConveyorRoom, GT_TorchRoom2, Ice_StalfosKnights_ConveyorHellway,
|
||||
Ice_MapChestRoom, Tower_FinalBridgeRoom, HC_FirstDarkRoom, HC_6RopesRoom, Desert_TorchPuzzle_MovingWallRoom,
|
||||
TT_BigChestRoom, TT_JailCellsRoom, Swamp_CompassChestRoom, Skull_GibdoTorchPuzzleRoom, PoD_EntranceRoom,
|
||||
PoD_Warps_SouthMimicsRoom, GT_Mini_HelmasaurConveyorRoom, GT_MoldormRoom, Ice_Bomb_JumpRoom,
|
||||
IcePalaceCloneRoom_FairyRoom, HC_WestCorridor, HC_ThroneRoom, HC_EastCorridor, Desert_Popos2_BeamosHellwayRoom,
|
||||
Swamp_UpstairsPitsRoom, CastleSecretEntrance_UncleDeathRoom, Skull_KeyPot_TrapRoom, Skull_BigKeyRoom,
|
||||
Skull_BigChestRoom, Skull_FinalSectionEntranceRoom, PoD_HelmasaurKing, GT_SpikePitRoom, GT_Ganon_BallZ,
|
||||
GT_Gauntlet1_2_3, Ice_LonelyFirebar, Ice_HiddenChest_SpikeFloorRoom, HC_WestEntranceRoom, HC_MainEntranceRoom,
|
||||
HC_EastEntranceRoom, Desert_FinalSectionEntranceRoom, TT_WestAtticRoom, TT_EastAtticRoom,
|
||||
Swamp_HiddenChest_HiddenDoorRoom, Skull_CompassChestRoom, Skull_KeyChest_TrapRoom, PoD_RupeeRoom, GT_MimicsRooms,
|
||||
GT_LanmolasRoom, GT_Gauntlet4_5, Ice_PengatorsRoom, HC_SmallCorridortoJailCells, HC_BoomerangChestRoom,
|
||||
HC_MapChestRoom, Desert_BigChestRoom, Desert_MapChestRoom, Desert_BigKeyChestRoom, Swamp_WaterDrainRoom,
|
||||
Hera_EntranceRoom, GanonsTower, GT_EastSideCollapsingBridge_ExplodingWallRoom, GT_Winder_WarpMazeRoom,
|
||||
Ice_HiddenChest_BombableFloorRoom, Ice_BigSpikeTrapsRoom, HC_JailCellRoom, HC_NextToChasmRoom, HC_BasementChasmRoom,
|
||||
Desert_WestEntranceRoom, Desert_MainEntranceRoom, Desert_EastEntranceRoom, Hera_TileRoom, Eastern_FairyRoom,
|
||||
GT_BlockPuzzle_SpikeSkip_MapChestRoom, GT_EastandWestDownstairs_BigChestRoom, GT_Tile_TorchPuzzleRoom,
|
||||
IcePalace0x8E, Mire_Vitreous, Mire_FinalSwitchRoom, Mire_DarkBombWall_SwitchesRoom,
|
||||
Mire_DarkCaneFloorSwitchPuzzleRoom, GT_FinalCollapsingBridgeRoom, GT_Torches1Room, Mire_TorchPuzzle_MovingWallRoom,
|
||||
Mire_EntranceRoom, Eastern_EyegoreKeyRoom, GT_ManySpikes_WarpMazeRoom, GT_InvisibleFloorMazeRoom,
|
||||
GT_CompassChest_InvisibleFloorRoom, Ice_BigChestRoom, IcePalace0x9F, Mire_Pre_VitreousRoom, Mire_FishRoom,
|
||||
Mire_BridgeKeyChestRoom, MiseryMire0xA3, TR_Trinexx, GT_WizzrobesRooms, GT_MoldormFallRoom, Hera_FairyRoom,
|
||||
Eastern_StalfosSpawnRoom, Eastern_BigChestRoom, Eastern_MapChestRoom, TT_MovingSpikes_KeyPotRoom, TT_BlindTheThief,
|
||||
IcePalace0xAE, Ice_IceBridgeRoom, Tower_CircleofPots, Mire_HourglassRoom, Mire_SlugRoom, Mire_SpikeKeyChestRoom,
|
||||
TR_Pre_TrinexxRoom, TR_DarkMaze, TR_ChainChompsRoom, TR_MapChest_KeyChest_RollerRoom, Eastern_BigKeyRoom,
|
||||
Eastern_LobbyCannonballsRoom, Eastern_DarkAntifairy_KeyPotRoom, TT_Hellway, TT_ConveyorToilet, Ice_BlockPuzzleRoom,
|
||||
IcePalaceCloneRoom_SwitchRoom, Tower_DarkBridgeRoom, Mire_CompassChest_TileRoom, Mire_BigHubRoom, Mire_BigChestRoom,
|
||||
TR_FinalCrystalSwitchPuzzleRoom, TR_LaserBridge, TurtleRock0xC6, TR_TorchPuzzle,
|
||||
Eastern_EntranceRoom, UnknownRoom, TT_NorthWestEntranceRoom, TT_NorthEastEntranceRoom, Ice_HoletoKholdstareRoom,
|
||||
Tower_DarkMaze, Mire_ConveyorSlug_BigKeyRoom, Mire_Mire02_WizzrobesRoom, TR_LaserKeyRoom, TR_EntranceRoom,
|
||||
Eastern_PreArmosKnightsRoom, Eastern_CanonballRoom, EasternPalace, TT_Main_SouthWestEntranceRoom,
|
||||
TT_SouthEastEntranceRoom, Tower_EntranceRoom
|
||||
}
|
||||
|
||||
|
||||
def init_sprite_requirements():
|
||||
reqs = [
|
||||
SpriteRequirement(EnemySprite.Raven).no_drop().sub_group(3, [0x11, 0x19]).exclude(NoFlyingRooms),
|
||||
SpriteRequirement(EnemySprite.Vulture).no_drop().sub_group(2, 0x12).exclude(NoFlyingRooms),
|
||||
SpriteRequirement(EnemySprite.CorrectPullSwitch).affix().sub_group(3, [0x52, 0x53]),
|
||||
SpriteRequirement(EnemySprite.WrongPullSwitch).affix().sub_group(3, [0x52, 0x53]),
|
||||
SpriteRequirement(EnemySprite.Octorok).sub_group(2, [0xc, 0x18]),
|
||||
SpriteRequirement(EnemySprite.Moldorm).exalt().sub_group(2, 0x30),
|
||||
SpriteRequirement(EnemySprite.Octorok4Way).sub_group(2, 0xc),
|
||||
SpriteRequirement(EnemySprite.Cucco).immune().sub_group(3, [0x15, 0x50]).exclude(NoFlyingRooms),
|
||||
SpriteRequirement(EnemySprite.Buzzblob).sub_group(3, 0x11),
|
||||
SpriteRequirement(EnemySprite.Snapdragon).sub_group(0, 0x16).sub_group(2, 0x17),
|
||||
SpriteRequirement(EnemySprite.Octoballoon).no_drop().sub_group(2, 0xc).exclude(NoFlyingRooms),
|
||||
SpriteRequirement(EnemySprite.Hinox).sub_group(0, 0x16),
|
||||
SpriteRequirement(EnemySprite.Moblin).sub_group(2, 0x17),
|
||||
SpriteRequirement(EnemySprite.MiniHelmasaur).sub_group(1, 0x1e),
|
||||
SpriteRequirement(EnemySprite.AntiFairy).no_drop().sub_group(3, [0x52, 0x53])
|
||||
.exclude(NoFlyingRooms).exclude({0x40}), # no anti-fairies in aga tower bridge room
|
||||
SpriteRequirement(EnemySprite.Wiseman).affix().sub_group(2, 0x4c),
|
||||
SpriteRequirement(EnemySprite.Hoarder).sub_group(3, 0x11).exclude({0x10c}),
|
||||
SpriteRequirement(EnemySprite.MiniMoldorm).sub_group(1, 0x1e),
|
||||
SpriteRequirement(EnemySprite.Poe).no_drop().sub_group(3, 0x15).exclude(NoFlyingRooms),
|
||||
SpriteRequirement(EnemySprite.Smithy).affix().sub_group(1, 0x1d).sub_group(3, 0x15),
|
||||
SpriteRequirement(EnemySprite.Statue).stasis().immune().sub_group(3, [0x52, 0x53]),
|
||||
SpriteRequirement(EnemySprite.CrystalSwitch).affix().sub_group(3, [0x52, 0x53]),
|
||||
SpriteRequirement(EnemySprite.SickKid).affix().sub_group(0, 0x51),
|
||||
SpriteRequirement(EnemySprite.Sluggula).sub_group(2, 0x25),
|
||||
SpriteRequirement(EnemySprite.WaterSwitch).affix().sub_group(3, 0x53),
|
||||
SpriteRequirement(EnemySprite.Ropa).sub_group(0, 0x16),
|
||||
SpriteRequirement(EnemySprite.RedBari).sub_group(0, 0x1f),
|
||||
SpriteRequirement(EnemySprite.BlueBari).sub_group(0, 0x1f),
|
||||
SpriteRequirement(EnemySprite.TalkingTree).affix().sub_group(3, [0x15, 0x1B]),
|
||||
SpriteRequirement(EnemySprite.HardhatBeetle).sub_group(1, 0x1e),
|
||||
SpriteRequirement(EnemySprite.Deadrock).sub_group(3, 0x10).exclude({0x7f, 0x10c}),
|
||||
SpriteRequirement(EnemySprite.DarkWorldHintNpc).affix(), # no groups?
|
||||
SpriteRequirement(EnemySprite.AdultNpc).affix().sub_group(0, [0xe, 0x4f]),
|
||||
SpriteRequirement(EnemySprite.SweepingLady).affix().group(6), # no sub groups?
|
||||
SpriteRequirement(EnemySprite.Lumberjacks).affix().sub_group(2, 0x4a),
|
||||
SpriteRequirement(EnemySprite.RaceGameLady).affix().group(6),
|
||||
SpriteRequirement(EnemySprite.FortuneTeller).affix().sub_group(0, 0x4b),
|
||||
SpriteRequirement(EnemySprite.ArgueBros).affix().sub_group(0, 0x4f),
|
||||
SpriteRequirement(EnemySprite.RupeePull).affix(),
|
||||
SpriteRequirement(EnemySprite.YoungSnitch).affix().group(6),
|
||||
SpriteRequirement(EnemySprite.Innkeeper).affix(), # no groups?
|
||||
SpriteRequirement(EnemySprite.Witch).affix().sub_group(2, 0x7c),
|
||||
SpriteRequirement(EnemySprite.Waterfall).affix(),
|
||||
SpriteRequirement(EnemySprite.EyeStatue).affix(),
|
||||
SpriteRequirement(EnemySprite.Locksmith).affix().sub_group(3, 0x11),
|
||||
SpriteRequirement(EnemySprite.MagicBat).affix().sub_group(3, 0x1d),
|
||||
SpriteRequirement(EnemySprite.KidInKak).affix().group(6),
|
||||
SpriteRequirement(EnemySprite.OldSnitch).affix().group(6),
|
||||
SpriteRequirement(EnemySprite.Hoarder2).sub_group(3, 0x11).exclude({0x10c}),
|
||||
SpriteRequirement(EnemySprite.TutorialGuard).affix(),
|
||||
SpriteRequirement(EnemySprite.LightningGate).affix().sub_group(3, 0x3f),
|
||||
SpriteRequirement(EnemySprite.BlueGuard).sub_group(1, [0xd, 0x49]),
|
||||
SpriteRequirement(EnemySprite.GreenGuard).sub_group(1, 0x49),
|
||||
SpriteRequirement(EnemySprite.RedSpearGuard).sub_group(1, [0xd, 0x49]),
|
||||
SpriteRequirement(EnemySprite.BluesainBolt).sub_group(0, 0x46).sub_group(1, [0xd, 0x49]),
|
||||
SpriteRequirement(EnemySprite.UsainBolt).sub_group(1, [0xd, 0x49]),
|
||||
SpriteRequirement(EnemySprite.BlueArcher).sub_group(0, 0x48).sub_group(1, 0x49),
|
||||
SpriteRequirement(EnemySprite.GreenBushGuard).sub_group(0, 0x48).sub_group(1, 0x49),
|
||||
SpriteRequirement(EnemySprite.RedJavelinGuard).sub_group(0, 0x46).sub_group(1, 0x49),
|
||||
SpriteRequirement(EnemySprite.RedBushGuard).sub_group(0, 0x46).sub_group(1, 0x49),
|
||||
SpriteRequirement(EnemySprite.BombGuard).sub_group(0, 0x46).sub_group(1, 0x49),
|
||||
SpriteRequirement(EnemySprite.GreenKnifeGuard).sub_group(1, 0x49).sub_group(2, 0x13),
|
||||
SpriteRequirement(EnemySprite.Geldman).sub_group(2, 0x12).exclude({0x10c}),
|
||||
SpriteRequirement(EnemySprite.Toppo).immune().sub_group(3, 0x11),
|
||||
SpriteRequirement(EnemySprite.Popo).sub_group(1, 0x2c),
|
||||
SpriteRequirement(EnemySprite.Popo2).sub_group(1, 0x2c),
|
||||
SpriteRequirement(EnemySprite.ArmosStatue).sub_group(3, 0x10).exclude({0x10c}),
|
||||
SpriteRequirement(EnemySprite.KingZora).affix().sub_group(3, 0x44),
|
||||
SpriteRequirement(EnemySprite.ArmosKnight).exalt().sub_group(3, 0x1d),
|
||||
SpriteRequirement(EnemySprite.Lanmolas).exalt().sub_group(3, 0x31),
|
||||
SpriteRequirement(EnemySprite.FireballZora).immerse().no_drop().sub_group(2, [0xc, 0x18]), # .uw_skip() test
|
||||
SpriteRequirement(EnemySprite.Zora).sub_group(2, 0xc).sub_group(3, 0x44), # .uw_skip() test
|
||||
SpriteRequirement(EnemySprite.DesertStatue).affix().sub_group(2, 0x12),
|
||||
SpriteRequirement(EnemySprite.Crab).sub_group(2, 0xc),
|
||||
SpriteRequirement(EnemySprite.LostWoodsBird).affix().sub_group(2, 0x37).sub_group(3, 0x36),
|
||||
SpriteRequirement(EnemySprite.LostWoodsSquirrel).affix().sub_group(2, 0x37).sub_group(3, 0x36),
|
||||
SpriteRequirement(EnemySprite.SparkCW).immune().sub_group(0, 0x1f),
|
||||
SpriteRequirement(EnemySprite.SparkCCW).immune().sub_group(0, 0x1f),
|
||||
SpriteRequirement(EnemySprite.RollerVerticalUp).immune().sub_group(2, 0x27).exclude(NoBeamosOrTrapRooms),
|
||||
SpriteRequirement(EnemySprite.RollerVerticalDown).immune().sub_group(2, 0x27).exclude(NoBeamosOrTrapRooms),
|
||||
SpriteRequirement(EnemySprite.RollerHorizontalLeft).immune().sub_group(2, 0x27).exclude(NoBeamosOrTrapRooms),
|
||||
SpriteRequirement(EnemySprite.RollerHorizontalRight).immune().sub_group(2, 0x27).exclude(NoBeamosOrTrapRooms),
|
||||
SpriteRequirement(EnemySprite.Beamos).no_drop().sub_group(1, 0x2c).exclude(NoBeamosOrTrapRooms),
|
||||
SpriteRequirement(EnemySprite.MasterSword).affix().sub_group(2, 0x37).sub_group(3, 0x36),
|
||||
|
||||
SpriteRequirement(EnemySprite.DebirandoPit).sub_group(0, 0x2f), # skip
|
||||
SpriteRequirement(EnemySprite.Debirando).sub_group(0, 0x2f), # skip
|
||||
SpriteRequirement(EnemySprite.ArcheryNpc).affix().sub_group(0, 0x4b),
|
||||
SpriteRequirement(EnemySprite.WallCannonVertLeft).affix().sub_group(0, 0x2f),
|
||||
SpriteRequirement(EnemySprite.WallCannonVertRight).affix().sub_group(0, 0x2f),
|
||||
SpriteRequirement(EnemySprite.WallCannonHorzTop).affix().sub_group(0, 0x2f),
|
||||
SpriteRequirement(EnemySprite.WallCannonHorzBottom).affix().sub_group(0, 0x2f),
|
||||
SpriteRequirement(EnemySprite.BallNChain).sub_group(0, 0x46).sub_group(1, 0x49),
|
||||
SpriteRequirement(EnemySprite.CannonTrooper).sub_group(0, 0x46).sub_group(1, 0x49),
|
||||
SpriteRequirement(EnemySprite.CricketRat).sub_group(2, [0x1c, 0x24]),
|
||||
SpriteRequirement(EnemySprite.Snake).sub_group(2, [0x1c, 0x24]),
|
||||
SpriteRequirement(EnemySprite.Keese).no_drop().sub_group(2, [0x1c, 0x24]),
|
||||
SpriteRequirement(EnemySprite.Leever).sub_group(0, 0x2f),
|
||||
SpriteRequirement(EnemySprite.FairyPondTrigger).affix().sub_group(3, 0x36),
|
||||
SpriteRequirement(EnemySprite.UnclePriest).affix().sub_group(0, [0x47, 0x51]),
|
||||
SpriteRequirement(EnemySprite.RunningNpc).affix().group(6),
|
||||
SpriteRequirement(EnemySprite.BottleMerchant).affix().group(6),
|
||||
SpriteRequirement(EnemySprite.Zelda).affix(),
|
||||
SpriteRequirement(EnemySprite.Grandma).affix().sub_group(0, 0x4b).sub_group(1, 0x4d).sub_group(2, 0x4a),
|
||||
SpriteRequirement(EnemySprite.Agahnim).exalt().sub_group(0, 0x55).sub_group(1, [0x1a, 0x3d]).sub_group(2, 0x42)
|
||||
.sub_group(3, 0x43),
|
||||
SpriteRequirement(EnemySprite.FloatingSkull).sub_group(0, 0x1f).exclude(NoFlyingRooms),
|
||||
SpriteRequirement(EnemySprite.BigSpike).sub_group(3, [0x52, 0x53]).no_drop(),
|
||||
SpriteRequirement(EnemySprite.FirebarCW).immune().sub_group(0, 0x1f),
|
||||
SpriteRequirement(EnemySprite.FirebarCCW).immune().sub_group(0, 0x1f),
|
||||
SpriteRequirement(EnemySprite.Firesnake).no_drop().sub_group(0, 0x1f),
|
||||
SpriteRequirement(EnemySprite.Hover).sub_group(2, 0x22), # .exclude(NoFlyingRooms), might be okay now
|
||||
SpriteRequirement(EnemySprite.AntiFairyCircle).no_drop().sub_group(3, [0x52, 0x53]),
|
||||
SpriteRequirement(EnemySprite.GreenEyegoreMimic).sub_group(2, 0x2e),
|
||||
SpriteRequirement(EnemySprite.RedEyegoreMimic).sub_group(2, 0x2e),
|
||||
|
||||
SpriteRequirement(EnemySprite.Kodongo).sub_group(2, 0x2a),
|
||||
# SpriteRequirement(EnemySprite.YellowStalfos).sub_group(0, 0x1f), # doesn't spawn
|
||||
SpriteRequirement(EnemySprite.Mothula).exalt().sub_group(2, 0x38).sub_group(3, 0x52),
|
||||
SpriteRequirement(EnemySprite.SpikeBlock).immune().sub_group(3, [0x52, 0x53]).exclude(NoBeamosOrTrapRooms)
|
||||
.exclude({0x28}), # why exclude sp entrance?
|
||||
SpriteRequirement(EnemySprite.Gibdo).sub_group(2, 0x23),
|
||||
SpriteRequirement(EnemySprite.Arrghus).exalt().sub_group(2, 0x39),
|
||||
SpriteRequirement(EnemySprite.Arrghi).exalt().sub_group(2, 0x39),
|
||||
SpriteRequirement(EnemySprite.Terrorpin).sub_group(2, 0x2a).exclude({0x10c}), # probably fine in mimic now
|
||||
SpriteRequirement(EnemySprite.Blob).sub_group(1, 0x20),
|
||||
SpriteRequirement(EnemySprite.Wallmaster).immune().ow_skip().sub_group(2, 0x23)
|
||||
.allow(WallmasterValidRooms),
|
||||
SpriteRequirement(EnemySprite.StalfosKnight).sub_group(1, 0x20).exclude({0x10c}),
|
||||
SpriteRequirement(EnemySprite.HelmasaurKing).exalt().sub_group(2, 0x3a).sub_group(3, 0x3e),
|
||||
SpriteRequirement(EnemySprite.Bumper).immune().aquaphobia().sub_group(3, [0x52, 0x53]),
|
||||
SpriteRequirement(EnemySprite.LaserEyeLeft).affix().sub_group(3, [0x52, 0x53]),
|
||||
SpriteRequirement(EnemySprite.LaserEyeRight).affix().sub_group(3, [0x52, 0x53]),
|
||||
SpriteRequirement(EnemySprite.LaserEyeTop).affix().sub_group(3, [0x52, 0x53]),
|
||||
SpriteRequirement(EnemySprite.LaserEyeBottom).affix().sub_group(3, [0x52, 0x53]),
|
||||
SpriteRequirement(EnemySprite.Pengator).sub_group(2, 0x26),
|
||||
SpriteRequirement(EnemySprite.Kyameron).no_drop().immerse().sub_group(2, 0x22),
|
||||
SpriteRequirement(EnemySprite.Wizzrobe).sub_group(2, [0x25, 0x29]),
|
||||
SpriteRequirement(EnemySprite.Zoro).sub_group(1, 0x20),
|
||||
SpriteRequirement(EnemySprite.Babasu).sub_group(1, 0x20),
|
||||
SpriteRequirement(EnemySprite.GroveOstritch).affix().sub_group(2, 0x4e),
|
||||
SpriteRequirement(EnemySprite.GroveRabbit).affix(),
|
||||
SpriteRequirement(EnemySprite.GroveBird).affix().sub_group(2, 0x4e),
|
||||
SpriteRequirement(EnemySprite.Freezor).stasis().skip().sub_group(2, 0x26),
|
||||
SpriteRequirement(EnemySprite.Kholdstare).exalt().sub_group(2, 0x3c),
|
||||
SpriteRequirement(EnemySprite.KholdstareShell).exalt(),
|
||||
SpriteRequirement(EnemySprite.FallingIce).exalt().sub_group(2, 0x3c),
|
||||
SpriteRequirement(EnemySprite.BlueZazak).sub_group(2, 0x28),
|
||||
SpriteRequirement(EnemySprite.RedZazak).sub_group(2, 0x28),
|
||||
SpriteRequirement(EnemySprite.Stalfos).sub_group(0, 0x1f),
|
||||
SpriteRequirement(EnemySprite.GreenZirro).no_drop().sub_group(3, 0x1b).exclude(NoFlyingRooms),
|
||||
SpriteRequirement(EnemySprite.BlueZirro).no_drop().sub_group(3, 0x1b).exclude(NoFlyingRooms),
|
||||
SpriteRequirement(EnemySprite.Pikit).sub_group(3, 0x1b),
|
||||
SpriteRequirement(EnemySprite.CrystalMaiden).affix(),
|
||||
SpriteRequirement(EnemySprite.OldMan).affix().sub_group(0, 0x46).sub_group(1, 0x49).sub_group(2, 0x1c),
|
||||
SpriteRequirement(EnemySprite.PipeDown).affix(),
|
||||
SpriteRequirement(EnemySprite.PipeUp).affix(),
|
||||
SpriteRequirement(EnemySprite.PipeRight).affix(),
|
||||
SpriteRequirement(EnemySprite.PipeLeft).affix(),
|
||||
SpriteRequirement(EnemySprite.GoodBee).affix().sub_group(0, 0x1f),
|
||||
SpriteRequirement(EnemySprite.PurpleChest).affix().sub_group(3, 0x15),
|
||||
SpriteRequirement(EnemySprite.BombShopGuy).affix().sub_group(1, 0x4d),
|
||||
SpriteRequirement(EnemySprite.Kiki).affix().sub_group(3, 0x19),
|
||||
SpriteRequirement(EnemySprite.BlindMaiden).affix(),
|
||||
# dialog tester.sub_group(1, 0x2c)
|
||||
SpriteRequirement(EnemySprite.BullyPinkBall).affix().sub_group(3, 0x14),
|
||||
# shop keepers in complex thing below
|
||||
SpriteRequirement(EnemySprite.Drunkard).affix().sub_group(0, 0x4f).sub_group(1, 0x4d).sub_group(2, 0x4a).
|
||||
sub_group(3, 0x50),
|
||||
SpriteRequirement(EnemySprite.Vitreous).exalt().sub_group(3, 0x3d),
|
||||
SpriteRequirement(EnemySprite.Catfish).affix().sub_group(2, 0x18),
|
||||
SpriteRequirement(EnemySprite.CutsceneAgahnim).affix().sub_group(0, 0x55).sub_group(1, 0x3d)
|
||||
.sub_group(2, 0x42).sub_group(3, 0x43),
|
||||
SpriteRequirement(EnemySprite.Boulder).affix().sub_group(3, 0x10),
|
||||
SpriteRequirement(EnemySprite.Gibo).sub_group(2, 0x28),
|
||||
SpriteRequirement(EnemySprite.Thief).immune().uw_skip().sub_group(0, [0xe, 0x15]),
|
||||
SpriteRequirement(EnemySprite.Medusa).affix(),
|
||||
SpriteRequirement(EnemySprite.FourWayShooter).affix(),
|
||||
SpriteRequirement(EnemySprite.Pokey).sub_group(2, 0x27),
|
||||
SpriteRequirement(EnemySprite.BigFairy).affix().sub_group(2, 0x39).sub_group(3, 0x36),
|
||||
SpriteRequirement(EnemySprite.Tektite).sub_group(3, 0x10),
|
||||
SpriteRequirement(EnemySprite.Chainchomp).immune().sub_group(2, 0x27),
|
||||
SpriteRequirement(EnemySprite.TrinexxRockHead).exalt().sub_group(0, 0x40).sub_group(3, 0x3f),
|
||||
SpriteRequirement(EnemySprite.TrinexxFireHead).exalt().sub_group(0, 0x40).sub_group(3, 0x3f),
|
||||
SpriteRequirement(EnemySprite.TrinexxIceHead).exalt().sub_group(0, 0x40).sub_group(3, 0x3f),
|
||||
SpriteRequirement(EnemySprite.Blind).exalt().sub_group(1, 0x2c).sub_group(2, 0x3b),
|
||||
SpriteRequirement(EnemySprite.Swamola).no_drop().sub_group(3, 0x19),
|
||||
SpriteRequirement(EnemySprite.Lynel).sub_group(3, 0x14),
|
||||
SpriteRequirement(EnemySprite.BunnyBeam).no_drop().ow_skip(),
|
||||
SpriteRequirement(EnemySprite.FloppingFish).uw_skip().immune(),
|
||||
SpriteRequirement(EnemySprite.Stal),
|
||||
SpriteRequirement(EnemySprite.Landmine).skip(),
|
||||
SpriteRequirement(EnemySprite.DiggingGameNPC).affix().sub_group(1, 0x2a),
|
||||
SpriteRequirement(EnemySprite.Ganon).exalt().sub_group(0, 0x21).sub_group(1, 0x41)
|
||||
.sub_group(2, 0x45).sub_group(3, 0x33),
|
||||
SpriteRequirement(EnemySprite.Faerie).immune(),
|
||||
SpriteRequirement(EnemySprite.FakeMasterSword).immune().sub_group(3, 0x11),
|
||||
SpriteRequirement(EnemySprite.MagicShopAssistant).affix().sub_group(0, 0x4b).sub_group(3, 0x5a),
|
||||
SpriteRequirement(EnemySprite.SomariaPlatform).affix().sub_group(2, 0x27),
|
||||
SpriteRequirement(EnemySprite.CastleMantle).affix().sub_group(0, 0x5d),
|
||||
SpriteRequirement(EnemySprite.GreenMimic).sub_group(1, 0x2c),
|
||||
SpriteRequirement(EnemySprite.RedMimic).sub_group(1, 0x2c),
|
||||
SpriteRequirement(EnemySprite.MedallionTablet).affix().sub_group(2, 0x12),
|
||||
|
||||
# overlord requirements - encapsulated mostly in the required sheets
|
||||
SpriteRequirement(2, 7).affix().sub_group(2, 46),
|
||||
SpriteRequirement(3, 7).affix().sub_group(2, 46),
|
||||
SpriteRequirement(5, 7).affix().sub_group(0, 31),
|
||||
SpriteRequirement(6, 7).affix().sub_group(2, [28, 36]),
|
||||
SpriteRequirement(7, 7).affix(),
|
||||
SpriteRequirement(8, 7).affix().sub_group(1, 32),
|
||||
SpriteRequirement(9, 7).affix().sub_group(2, 35),
|
||||
SpriteRequirement(0xa, 7).affix().sub_group(3, 82),
|
||||
SpriteRequirement(0xb, 7).affix().sub_group(3, 82),
|
||||
SpriteRequirement(0x10, 7).affix().sub_group(2, 34),
|
||||
SpriteRequirement(0x11, 7).affix().sub_group(2, 34),
|
||||
SpriteRequirement(0x12, 7).affix().sub_group(2, 34),
|
||||
SpriteRequirement(0x13, 7).affix().sub_group(2, 34),
|
||||
SpriteRequirement(0x14, 7).affix(),
|
||||
SpriteRequirement(0x15, 7).affix().sub_group(2, [37, 41]),
|
||||
SpriteRequirement(0x16, 7).affix().sub_group(1, 32),
|
||||
SpriteRequirement(0x17, 7).affix().sub_group(0, 31),
|
||||
SpriteRequirement(0x18, 7).affix().sub_group(0, 31),
|
||||
SpriteRequirement(0x19, 7).affix(),
|
||||
SpriteRequirement(0x1a, 7).affix(),
|
||||
]
|
||||
simple = {(r.sprite, r.overlord): r for r in reqs}
|
||||
shopkeeper = [
|
||||
SpriteRequirement(EnemySprite.Shopkeeper).affix().sub_group(0, 75).sub_group(2, 74).sub_group(3, 90)
|
||||
.allow({0xff, 0x112, 0x11f}),
|
||||
SpriteRequirement(EnemySprite.Shopkeeper).affix().sub_group(0, 75).sub_group(1, 77).sub_group(2, 74)
|
||||
.sub_group(3, 90).allow({0x10f, 0x110, 0x11f}),
|
||||
SpriteRequirement(EnemySprite.Shopkeeper).affix().sub_group(0, 79).sub_group(2, 74).sub_group(3, 90)
|
||||
.allow({0x118}),
|
||||
SpriteRequirement(EnemySprite.Shopkeeper).affix().sub_group(0, 14).sub_group(2, 74).sub_group(3, 90)
|
||||
.allow({0x123, 0x124}),
|
||||
SpriteRequirement(EnemySprite.Shopkeeper).affix().sub_group(0, 14).sub_group(2, 74).sub_group(3, 80)
|
||||
.allow({0x125, 0x100}),
|
||||
SpriteRequirement(EnemySprite.Shopkeeper).affix().sub_group(0, 21).allow({0x11e}),
|
||||
]
|
||||
complex_r = {}
|
||||
for req in shopkeeper:
|
||||
for r in req.allowed_rooms:
|
||||
complex_r[r] = req
|
||||
simple[(EnemySprite.Shopkeeper, 0)] = complex_r
|
||||
return simple
|
||||
|
||||
|
||||
# sheet 1 and 1c have group 4 modified from vanilla for murahdahla
|
||||
vanilla_sheets = [
|
||||
(0x00, 0x49, 0x00, 0x00), (0x46, 0x49, 0x0C, 0x3F), (0x48, 0x49, 0x13, 0x3F), (0x46, 0x49, 0x13, 0x0E),
|
||||
(0x48, 0x49, 0x0C, 0x11), (0x48, 0x49, 0x0C, 0x10), (0x4F, 0x49, 0x4A, 0x50), (0x0E, 0x49, 0x4A, 0x11),
|
||||
(0x46, 0x49, 0x12, 0x00), (0x00, 0x49, 0x00, 0x50), (0x00, 0x49, 0x00, 0x11), (0x48, 0x49, 0x0C, 0x00),
|
||||
(0x00, 0x00, 0x37, 0x36), (0x48, 0x49, 0x4C, 0x11), (0x5D, 0x2C, 0x0C, 0x44), (0x00, 0x00, 0x4E, 0x00),
|
||||
|
||||
(0x0F, 0x00, 0x12, 0x10), (0x00, 0x00, 0x00, 0x4C), (0x00, 0x0D, 0x17, 0x00), (0x16, 0x0D, 0x17, 0x1B),
|
||||
(0x16, 0x0D, 0x17, 0x14), (0x15, 0x0D, 0x17, 0x15), (0x16, 0x0D, 0x18, 0x19), (0x16, 0x0D, 0x17, 0x19),
|
||||
(0x16, 0x0D, 0x00, 0x00), (0x16, 0x0D, 0x18, 0x1B), (0x0F, 0x49, 0x4A, 0x11), (0x4B, 0x2A, 0x5C, 0x15),
|
||||
(0x16, 0x49, 0x17, 0x3F), (0x00, 0x00, 0x00, 0x15), (0x16, 0x0D, 0x17, 0x10), (0x16, 0x49, 0x12, 0x00),
|
||||
|
||||
(0x16, 0x49, 0x0C, 0x11), (0x00, 0x00, 0x12, 0x10), (0x16, 0x0D, 0x00, 0x11), (0x16, 0x49, 0x0C, 0x00),
|
||||
(0x16, 0x0D, 0x4C, 0x11), (0x0E, 0x0D, 0x4A, 0x11), (0x16, 0x1A, 0x17, 0x1B), (0x4F, 0x34, 0x4A, 0x50),
|
||||
(0x35, 0x4D, 0x65, 0x36), (0x4A, 0x34, 0x4E, 0x00), (0x0E, 0x34, 0x4A, 0x11), (0x51, 0x34, 0x5D, 0x59),
|
||||
(0x4B, 0x49, 0x4C, 0x11), (0x2D, 0x00, 0x00, 0x00), (0x5D, 0x00, 0x12, 0x59), (0x00, 0x00, 0x00, 0x00),
|
||||
|
||||
(0x00, 0x00, 0x00, 0x00), (0x00, 0x00, 0x00, 0x00), (0x00, 0x00, 0x00, 0x00), (0x00, 0x00, 0x00, 0x00),
|
||||
(0x00, 0x00, 0x00, 0x00), (0x00, 0x00, 0x00, 0x00), (0x00, 0x00, 0x00, 0x00), (0x00, 0x00, 0x00, 0x00),
|
||||
(0x00, 0x00, 0x00, 0x00), (0x00, 0x00, 0x00, 0x00), (0x00, 0x00, 0x00, 0x00), (0x00, 0x00, 0x00, 0x00),
|
||||
(0x00, 0x00, 0x00, 0x00), (0x00, 0x00, 0x00, 0x00), (0x00, 0x00, 0x00, 0x00), (0x00, 0x00, 0x00, 0x00),
|
||||
|
||||
(0x47, 0x49, 0x2B, 0x2D), (0x46, 0x49, 0x1C, 0x52), (0x00, 0x49, 0x1C, 0x52), (0x5D, 0x49, 0x00, 0x52),
|
||||
(0x46, 0x49, 0x13, 0x52), (0x4B, 0x4D, 0x4A, 0x5A), (0x47, 0x49, 0x1C, 0x52), (0x4B, 0x4D, 0x39, 0x36),
|
||||
(0x1F, 0x2C, 0x2E, 0x52), (0x1F, 0x2C, 0x2E, 0x1D), (0x2F, 0x2C, 0x2E, 0x52), (0x2F, 0x2C, 0x2E, 0x31),
|
||||
(0x1F, 0x1E, 0x30, 0x52), (0x51, 0x49, 0x13, 0x00), (0x4F, 0x49, 0x13, 0x50), (0x4F, 0x4D, 0x4A, 0x50),
|
||||
|
||||
(0x4B, 0x49, 0x4C, 0x2B), (0x1F, 0x20, 0x22, 0x53), (0x55, 0x3D, 0x42, 0x43), (0x1F, 0x1E, 0x23, 0x52),
|
||||
(0x1F, 0x1E, 0x39, 0x3A), (0x1F, 0x1E, 0x3A, 0x3E), (0x1F, 0x1E, 0x3C, 0x3D), (0x40, 0x1E, 0x27, 0x3F),
|
||||
(0x55, 0x1A, 0x42, 0x43), (0x1F, 0x1E, 0x2A, 0x52), (0x1F, 0x1E, 0x38, 0x52), (0x1F, 0x20, 0x28, 0x52),
|
||||
(0x1F, 0x20, 0x26, 0x52), (0x1F, 0x2C, 0x25, 0x52), (0x1F, 0x20, 0x27, 0x52), (0x1F, 0x1E, 0x29, 0x52),
|
||||
|
||||
(0x1F, 0x2C, 0x3B, 0x52), (0x46, 0x49, 0x24, 0x52), (0x21, 0x41, 0x45, 0x33), (0x1F, 0x2C, 0x28, 0x31),
|
||||
(0x1F, 0x0D, 0x29, 0x52), (0x1F, 0x1E, 0x27, 0x52), (0x1F, 0x20, 0x27, 0x53), (0x48, 0x49, 0x13, 0x52),
|
||||
(0x0E, 0x1E, 0x4A, 0x50), (0x1F, 0x20, 0x26, 0x53), (0x15, 0x00, 0x00, 0x00), (0x1F, 0x00, 0x2A, 0x52),
|
||||
(0x00, 0x00, 0x00, 0x00), (0x00, 0x00, 0x00, 0x00), (0x00, 0x00, 0x00, 0x00), (0x00, 0x00, 0x00, 0x00),
|
||||
(0x00, 0x00, 0x00, 0x00), (0x00, 0x00, 0x00, 0x00), (0x00, 0x00, 0x00, 0x00), (0x00, 0x00, 0x00, 0x00),
|
||||
(0x00, 0x00, 0x00, 0x00), (0x00, 0x00, 0x00, 0x00), (0x00, 0x00, 0x00, 0x00), (0x00, 0x00, 0x00, 0x00),
|
||||
(0x00, 0x00, 0x00, 0x00), (0x00, 0x00, 0x00, 0x00), (0x00, 0x00, 0x00, 0x00), (0x00, 0x00, 0x00, 0x00),
|
||||
(0x00, 0x00, 0x00, 0x00), (0x00, 0x00, 0x00, 0x08), (0x5D, 0x49, 0x00, 0x52), (0x55, 0x49, 0x42, 0x43),
|
||||
(0x61, 0x62, 0x63, 0x50), (0x61, 0x62, 0x63, 0x50), (0x61, 0x62, 0x63, 0x50), (0x61, 0x62, 0x63, 0x50),
|
||||
(0x61, 0x62, 0x63, 0x50), (0x61, 0x62, 0x63, 0x50), (0x61, 0x56, 0x57, 0x50), (0x61, 0x62, 0x63, 0x50),
|
||||
(0x61, 0x62, 0x63, 0x50), (0x61, 0x56, 0x57, 0x50), (0x61, 0x56, 0x63, 0x50), (0x61, 0x56, 0x57, 0x50),
|
||||
(0x61, 0x56, 0x33, 0x50), (0x61, 0x56, 0x57, 0x50), (0x61, 0x62, 0x63, 0x50), (0x61, 0x62, 0x63, 0x50)
|
||||
]
|
||||
|
||||
required_boss_sheets = {EnemySprite.ArmosKnight: 9, EnemySprite.Lanmolas: 11, EnemySprite.Moldorm: 12,
|
||||
EnemySprite.HelmasaurKing: 21, EnemySprite.Arrghus: 20, EnemySprite.Mothula: 26,
|
||||
EnemySprite.Blind: 32, EnemySprite.Kholdstare: 22, EnemySprite.Vitreous: 22,
|
||||
EnemySprite.TrinexxRockHead: 23}
|
||||
|
||||
|
||||
class SpriteSheet:
|
||||
def __init__(self, id, default_sub_groups):
|
||||
self.id = id
|
||||
self.sub_groups = list(default_sub_groups)
|
||||
self.locked = [False] * 4
|
||||
self.room_set = set()
|
||||
|
||||
def dungeon_id(self):
|
||||
return self.id + 0x40
|
||||
|
||||
def valid_sprite(self, requirement):
|
||||
if requirement.groups and self.id not in requirement.groups:
|
||||
return False
|
||||
for idx, sub in enumerate(self.sub_groups):
|
||||
if requirement.sub_groups[idx] and sub not in requirement.sub_groups[idx]:
|
||||
return False
|
||||
return True
|
||||
|
||||
def lock_sprite_in(self, sprite):
|
||||
for i, options in sprite.sub_groups.items():
|
||||
self.locked[i] = len(options) > 0
|
||||
|
||||
def add_sprite_to_sheet(self, groups, rooms=None):
|
||||
for idx, g in enumerate(groups):
|
||||
if g is not None:
|
||||
self.sub_groups[idx] = g
|
||||
self.locked[idx] = True
|
||||
if rooms is not None:
|
||||
self.room_set.update(rooms)
|
||||
|
||||
def write_to_rom(self, rom, base_address):
|
||||
rom.write_bytes(base_address + self.id * 4, self.sub_groups)
|
||||
|
||||
def __str__(self):
|
||||
return f'{self.id} => [{", ".join([str(x) for x in self.sub_groups])}]'
|
||||
|
||||
|
||||
# convert to dungeon id
|
||||
def did(n):
|
||||
return n + 0x40
|
||||
|
||||
|
||||
def init_sprite_sheets(requirements):
|
||||
sheets = {id: SpriteSheet(id, def_sheet) for id, def_sheet in enumerate(vanilla_sheets)}
|
||||
# wait until bosses are randomized to determine which are randomized
|
||||
for sprite, sheet_num in required_boss_sheets.items():
|
||||
sheet = sheets[did(sheet_num)] # convert to dungeon sheet id
|
||||
boss_sprite = requirements[(sprite, 0)]
|
||||
sheet.lock_sprite_in(boss_sprite)
|
||||
return sheets
|
||||
|
||||
|
||||
def setup_required_dungeon_groups(sheets, data_tables):
|
||||
|
||||
sheets[did(1)].add_sprite_to_sheet([70, 73, 28, 82], {0xe4, 0xf0}) # old man
|
||||
# various npcs
|
||||
sheets[did(5)].add_sprite_to_sheet([75, 77, 74, 90], {0xf3, 0x109, 0x10e, 0x10f, 0x110, 0x111, 0x112,
|
||||
0x11a, 0x11c, 0x11f, 0x122})
|
||||
sheets[did(7)].add_sprite_to_sheet([75, 77, 57, 54], {0x8, 0x2c, 0x114, 0x115, 0x116}) # big fairies
|
||||
sheets[did(13)].add_sprite_to_sheet([81, None, None, None], {0x55, 0x102, 0x104}) # uncle, sick kid
|
||||
sheets[did(14)].add_sprite_to_sheet([71, 73, 76, 80], {0x12, 0x105, 0x10a}) # wisemen
|
||||
sheets[did(15)].add_sprite_to_sheet([79, 77, 74, 80], {0xf4, 0xf5, 0x101, 0x103, 0x106, 0x118, 0x119}) # more npcs
|
||||
sheets[did(18)].add_sprite_to_sheet([85, 61, 66, 67], {0x20, 0x30}) # aga alter, aga1
|
||||
sheets[did(24)].add_sprite_to_sheet([85, 26, 66, 67], {0xd}) # aga2
|
||||
sheets[did(34)].add_sprite_to_sheet([33, 65, 69, 51], {0}) # ganon
|
||||
sheets[did(40)].add_sprite_to_sheet([14, None, 74, 80], {0x124, 0x125, 0x126}) # fairy + rupee npcs
|
||||
sheets[did(9)].add_sprite_to_sheet([None, None, None, 29], {0xe3}) # magic bat
|
||||
sheets[did(28)].add_sprite_to_sheet([None, None, 38, 82], {0xe, 0x7e, 0x8e, 0x9e}) # freezors
|
||||
sheets[did(3)].add_sprite_to_sheet([93, None, None, None], {0x51}) # mantle
|
||||
sheets[did(42)].add_sprite_to_sheet([21, None, None, None], {0x11e}) # hype cave
|
||||
sheets[did(10)].add_sprite_to_sheet([47, None, 46, None], {0x5c, 0x75, 0xb9, 0xd9}) # cannonballs
|
||||
sheets[did(37)].add_sprite_to_sheet([31, None, 39, 82], {0x24, 0xb4, 0xb5, 0xc6, 0xc7, 0xd6}) # somaria platforms
|
||||
# not sure 31 is needed above
|
||||
|
||||
free_sheet_reqs = [
|
||||
([75, None, None, None], [0xff, 0x11f]), # shopkeepers
|
||||
([None, 77, None, 21], [0x121]), # smithy
|
||||
([None, None, None, 80], [0x108]), # chicken house
|
||||
([14, 30, None, None], [0x123]), # mini moldorm (shutter door)
|
||||
([None, None, 34, None], [0x36, 0x46, 0x66, 0x76]), # pirogusu spawners
|
||||
([None, 32, None, None], [0x9f]), # babasu spawners
|
||||
([31, None, None, None], [0x7f]), # force baris
|
||||
([None, None, 35, None], [0x39, 0x49]), # wallmasters
|
||||
# bumpers - why the split - because of other requirements -
|
||||
([None, None, None, (82, 83)], [0x17, 0x2a, 0x4c, 0x59, 0x67, 0x7e, 0x8b, 0xeb, 0xfb]),
|
||||
# crystal switches - split for some reason
|
||||
([None, None, None, (82, 83)], [0xb, 0x13, 0x1b, 0x1e, 0x2a, 0x2b, 0x31, 0x5b, 0x6b, 0x77, 0x8b,
|
||||
0x91, 0x92, 0x9b, 0x9d, 0xa1, 0xab, 0xbf, 0xc4, 0xef]),
|
||||
# laser eyes - split for some reason
|
||||
([None, None, None, (82, 83)], [0x13, 0x23, 0x96, 0xa5, 0xc5, 0xd5]),
|
||||
# statues - split for some reason
|
||||
([None, None, None, (82, 83)], [0x26, 0x2b, 0x40, 0x4a, 0x6b, 0x7b]),
|
||||
([None, None, None, 83], [0x43, 0x63, 0x87]), # tile rooms
|
||||
|
||||
# non-optional
|
||||
([None, None, None, 82], [0x58, 0x8c, 0x10b]), # pull switches
|
||||
([None, None, (28, 36), 82], [0x2, 0x64]), # pull switches (snakes)
|
||||
([None, None, None, 82], [0x1a, 0x3d, 0x44, 0x5e, 0x7c, 0x95, 0xc3]), # collapsing bridges
|
||||
([None, None, None, 83], [0x3f, 0xce]), # pull tongue
|
||||
([None, None, None, 83], [0x35, 0x37, 0x76]), # swamp drains
|
||||
([None, None, 34, None], [0x28]), # tektike forced? - spawn chest
|
||||
([None, None, 37, None], [0x97]), # wizzrobe spawner - in middle of room...
|
||||
|
||||
# combined
|
||||
([None, 32, None, (82, 83)], [0x3e]), # babasu spawners + crystal switch
|
||||
([None, 32, None, 83], [0x4]), # zoro spawners + crystal switch + pull switch
|
||||
([None, None, 35, 82], [0x56]), # wallmaster + collasping bridge
|
||||
([None, None, 35, (82, 83)], [0x57, 0x68]), # wallmaster + statue and wallmaster + bumpers
|
||||
([None, None, 34, 83], [0x76]), # swamp drain + pirogusu spawners
|
||||
([None, None, 35, 83], [0x8d]), # wallmaster + tile room
|
||||
([None, None, None, 83], [0xb6, 0xc1]), # tile room + crystal switch
|
||||
|
||||
# allow some sprites / increase odds:
|
||||
([72, 73, None, None], []), # allow for blue archer + greenbush
|
||||
([None, 73, 19, None], []), # allow for green knife guard
|
||||
([None, None, 12, 68], []), # increase odds for zora
|
||||
([22, None, 23, None], []), # increase odds for snapdragon
|
||||
]
|
||||
|
||||
data_tables.room_requirements = {}
|
||||
# find home for the free_sheet_reqs
|
||||
for pair in free_sheet_reqs:
|
||||
groups, room_list = pair
|
||||
for room in room_list:
|
||||
data_tables.room_requirements[room] = groups
|
||||
find_matching_sheet(groups, sheets, range(65, 124), room_list)
|
||||
|
||||
|
||||
# RandomizeRooms(optionFlags);
|
||||
# roomCollection.LoadRooms()
|
||||
# roomCollection.RandomizeRoomSpriteGroups(spriteGroupCollection, optionFlags);
|
||||
# more stuff
|
||||
sub_group_choices = {
|
||||
0: [22, 31, 47, 14],
|
||||
1: [44, 30, 32], # 73, 13
|
||||
2: [12, 18, 23, 24, 28, 46, 34, 35, 39, 40, 38, 41, 36, 37, 42],
|
||||
3: [17, 16, 27, 20, 82, 83, 25] # 25 for Swamola
|
||||
}
|
||||
# 70, 72 for guards
|
||||
# 0: 72 specifically for BlueArcher/GreenBush (but needs combination)
|
||||
# 0: 70 for guards but needs combination
|
||||
# 2: 19 for green knife guard, but needs combination
|
||||
# 3: 68 for Zora, but needs combination
|
||||
|
||||
|
||||
def combine_req(sub_groups, requirement):
|
||||
for i in range(0, 4):
|
||||
if requirement.sub_groups[i]:
|
||||
if len(sub_groups[i]) == 0:
|
||||
sub_groups[i].update(requirement.sub_groups[i])
|
||||
else:
|
||||
if len(sub_groups[i].intersection(requirement.sub_groups[i])) == 0:
|
||||
raise IncompatibleEnemyException
|
||||
sub_groups[i].intersection_update(requirement.sub_groups[i])
|
||||
|
||||
|
||||
def setup_custom_enemy_sheets(custom_enemies, sheets, data_tables, sheet_range, uw=True):
|
||||
requirements = data_tables.sprite_requirements
|
||||
for room_id, enemy_map in custom_enemies.items():
|
||||
if uw:
|
||||
original_list = data_tables.uw_enemy_table.room_map[room_id]
|
||||
else:
|
||||
original_list = data_tables.ow_enemy_table[room_id]
|
||||
sub_groups_choices = [set(), set(), set(), set()]
|
||||
for idx, sprite in enumerate(original_list):
|
||||
if idx in enemy_map:
|
||||
key = (sprite_translation[enemy_map[idx]], 0)
|
||||
if key not in requirements:
|
||||
continue
|
||||
req = requirements[key]
|
||||
try:
|
||||
combine_req(sub_groups_choices, req)
|
||||
except IncompatibleEnemyException:
|
||||
logging.getLogger('').warning(f'Incompatible enemy: {hex(room_id)}:{idx} {enemy_map[idx]}')
|
||||
else:
|
||||
sprite_secondary = 0 if sprite.sub_type != SpriteType.Overlord else sprite.sub_type
|
||||
key = (sprite.kind, sprite_secondary)
|
||||
if key not in requirements:
|
||||
continue
|
||||
req = requirements[key]
|
||||
if isinstance(req, dict):
|
||||
req = req[room_id]
|
||||
if req.static or not req.can_randomize:
|
||||
try:
|
||||
combine_req(sub_groups_choices, req)
|
||||
except IncompatibleEnemyException:
|
||||
raise IncompatibleEnemyException(f'Incompatible enemy: {hex(room_id)}:{idx} {str(req)}')
|
||||
sheet_req = [None if not x else tuple(x) for x in sub_groups_choices]
|
||||
find_matching_sheet(sheet_req, sheets, sheet_range, [room_id], True)
|
||||
|
||||
|
||||
def randomize_underworld_sprite_sheets(sheets, data_tables, custom_enemies):
|
||||
setup_required_dungeon_groups(sheets, data_tables)
|
||||
|
||||
setup_custom_enemy_sheets(custom_enemies, sheets, data_tables, range(65, 124), True)
|
||||
|
||||
for num in range(65, 124): # sheets 0x41 to 0x7B inclusive
|
||||
sheet = sheets[num]
|
||||
# if not sheet.locked[1] and num in [65, 66, 67, 68]: # guard stuff, kind of
|
||||
# sheet.locked[1] = True
|
||||
# sheet.sub_groups[1] = random.choice([13, 73])
|
||||
|
||||
free_slots = [idx for idx in range(0, 4) if not sheet.locked[idx]]
|
||||
while free_slots:
|
||||
choices = [c for c in data_tables.sheet_choices if all(slot in free_slots for slot in c.slots)]
|
||||
weights = [c.weight for c in choices]
|
||||
choice = random.choices(choices, weights, k=1)[0]
|
||||
for idx, val in choice.assignments.items():
|
||||
v = random.choice(val) if isinstance(val, list) else val
|
||||
sheet.sub_groups[idx] = v
|
||||
sheet.locked[idx] = True
|
||||
free_slots = [idx for idx in range(0, 4) if not sheet.locked[idx]]
|
||||
|
||||
|
||||
def setup_required_overworld_groups(sheets):
|
||||
sheets[7].add_sprite_to_sheet([None, None, 74, None], {0x2}) # lumberjacks
|
||||
sheets[16].add_sprite_to_sheet([None, None, 18, 16], {0x3, 0x93}) # WDM (pre/post-Aga)
|
||||
sheets[7].add_sprite_to_sheet([None, None, None, 17], {0xA, 0x9A}) # DM Foothills? (pre/post-Aga)
|
||||
sheets[4].add_sprite_to_sheet([None, None, None, None], {0xF, 0x9F}) # Waterfall of wishing (pre/post-Aga)
|
||||
sheets[3].add_sprite_to_sheet([None, None, None, 14], {0x14, 0xA4}) # Graveyard (pre/post-Aga)
|
||||
sheets[1].add_sprite_to_sheet([None, None, 76, 0x3F], {0x1B, 0xAB}) # Hyrule Castle (pre/post-Aga)
|
||||
sheets[2].add_sprite_to_sheet([None, None, None, 0x3F], {}) # Hyrule Castle - rain state
|
||||
# Smithy/Race/Kak (pre/post-Aga)
|
||||
sheets[6].add_sprite_to_sheet([0x4F, 0x49, 0x4A, 0x50], {0x18, 0x22, 0x28, 0xA8, 0xB2, 0xB8})
|
||||
sheets[8].add_sprite_to_sheet([None, None, 18, None], {0x30, 0xC0}) # Desert (pre/post-Aga)
|
||||
sheets[10].add_sprite_to_sheet([None, None, None, 17], {0x3A, 0xCA}) # M-rock (pre/post-Aga)
|
||||
sheets[22].add_sprite_to_sheet([None, None, 24, None], {0x4F, 0xDF}) # Catfish (pre/post-Aga)
|
||||
sheets[21].add_sprite_to_sheet([21, None, None, 21], {0x62, 0xF2}) # Smith DW (pre/post-Aga)
|
||||
sheets[27].add_sprite_to_sheet([None, 42, None, None], {0x68, 0xF8}) # Dig Game (pre/post-Aga)
|
||||
sheets[13].add_sprite_to_sheet([None, None, 76, None], {0x16, 0xA6}) # Witch hut (pre/post-Aga)
|
||||
sheets[29].add_sprite_to_sheet([None, 77, None, 21], {0x69, 0xF9}) # VoO South (pre/post-Aga)
|
||||
sheets[15].add_sprite_to_sheet([None, None, 78, None], {0x2A, 0xBA}) # Haunted Grove (pre/post-Aga)
|
||||
sheets[17].add_sprite_to_sheet([None, None, None, 76], {0x6A, 0xFA}) # Stumpy (pre/post-Aga)
|
||||
sheets[12].add_sprite_to_sheet([None, None, 55, 54], {0x80, 0x110}) # Specials (pre/post-Aga)
|
||||
sheets[14].add_sprite_to_sheet([None, None, 12, 68], {0x81, 0x111}) # Zora's Domain (pre/post-Aga)
|
||||
sheets[26].add_sprite_to_sheet([15, None, None, None], {0x92}) # Lumberjacks post-Aga
|
||||
sheets[23].add_sprite_to_sheet([None, None, None, 25], {0x5E, 0xEE}) # PoD pre/post-Aga
|
||||
|
||||
free_sheet_reqs = [
|
||||
[None, None, None, 0x14], # bully+pink ball needs this
|
||||
[72, 73, None, None], # allow for blue archer + green bush
|
||||
[None, 73, 19, None], # allow for green knife guard
|
||||
[22, None, 23, None], # increase odds for snapdragon
|
||||
[70, 73, None, None], # guards group (ballnchain, redbush, redjav, cannon, bomb, bluesain
|
||||
[None, None, None, 0x15], # an option for talking trees
|
||||
[None, None, None, 0x1B], # an option for talking trees
|
||||
]
|
||||
|
||||
for group in free_sheet_reqs:
|
||||
find_matching_sheet(group, sheets, range(1, 64))
|
||||
|
||||
|
||||
class NoMatchingSheetException(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class IncompatibleEnemyException(Exception):
|
||||
pass
|
||||
|
||||
|
||||
def find_matching_sheet(groups, sheets, search_sheets, room_list=None, lock_match=False):
|
||||
possible_sheets = []
|
||||
found_match = False
|
||||
for num in search_sheets:
|
||||
if num in {6, 65, 69, 71, 78, 79, 82, 88, 98}: # these are not useful sheets for randomization
|
||||
continue
|
||||
sheet = sheets[num]
|
||||
valid = True
|
||||
match = True
|
||||
for idx, value in enumerate(groups):
|
||||
if value is not None and sheet.locked[idx]:
|
||||
valid = False
|
||||
if (sheet.sub_groups[idx] not in value if isinstance(value, tuple)
|
||||
else value != sheet.sub_groups[idx]):
|
||||
match = False
|
||||
elif value is not None:
|
||||
match = False
|
||||
if match:
|
||||
found_match = True
|
||||
if lock_match and room_list is not None:
|
||||
sheet.room_set.update(room_list)
|
||||
break
|
||||
if valid:
|
||||
possible_sheets.append(sheet)
|
||||
if not found_match:
|
||||
if len(possible_sheets) == 0:
|
||||
raise NoMatchingSheetException
|
||||
chosen_sheet = random.choice(possible_sheets)
|
||||
chosen_groups = [(random.choice(g) if isinstance(g, tuple) else g) for g in groups]
|
||||
chosen_sheet.add_sprite_to_sheet(chosen_groups, room_list)
|
||||
|
||||
|
||||
def randomize_overworld_sprite_sheets(sheets, data_tables, custom_enemies):
|
||||
setup_required_overworld_groups(sheets)
|
||||
|
||||
setup_custom_enemy_sheets(custom_enemies, sheets, data_tables, range(1, 64), False)
|
||||
|
||||
for num in range(1, 64): # sheets 0x1 to 0x3F inclusive
|
||||
sheet = sheets[num]
|
||||
if num == 6: # skip this group - it is locked for kakariko
|
||||
continue
|
||||
|
||||
free_slots = [idx for idx in range(0, 4) if not sheet.locked[idx]]
|
||||
while free_slots:
|
||||
choices = [c for c in data_tables.sheet_choices if all(slot in free_slots for slot in c.slots)]
|
||||
weights = [c.weight for c in choices]
|
||||
choice = random.choices(choices, weights, k=1)[0]
|
||||
for idx, val in choice.assignments.items():
|
||||
v = random.choice(val) if isinstance(val, list) else val
|
||||
sheet.sub_groups[idx] = v
|
||||
sheet.locked[idx] = True
|
||||
free_slots = [idx for idx in range(0, 4) if not sheet.locked[idx]]
|
||||
|
||||
|
||||
class SheetChoice:
|
||||
|
||||
def __init__(self, slots, assignments, weight):
|
||||
self.slots = slots
|
||||
self.assignments = assignments
|
||||
self.weight = weight
|
||||
102
source/enemizer/TilePattern.py
Normal file
102
source/enemizer/TilePattern.py
Normal file
@@ -0,0 +1,102 @@
|
||||
import os
|
||||
import json
|
||||
import codecs
|
||||
|
||||
if __name__ == '__main__':
|
||||
directory = './EnemizerCLI.Core/tiles'
|
||||
for filename in os.listdir(directory):
|
||||
with codecs.open(directory+'/'+filename, 'r', 'utf-8-sig') as fin:
|
||||
pattern = json.load(fin)
|
||||
pairs = [f'({x["x"]}, {x["y"]})' for x in pattern["Items"]]
|
||||
print(f'(\'{filename}\', [{", ".join(pairs)}]),')
|
||||
|
||||
tile_patterns = [
|
||||
('heart soft', [(3, 1), (5, 2), (4, 7), (2, 5), (7, 1), (7, 5), (8, 4), (1, 2), (2, 1), (1, 4), (5, 7), (6, 1),
|
||||
(6, 6), (4, 2), (8, 3), (1, 3), (3, 6), (8, 2)]),
|
||||
('metroid', [(2, 7), (7, 7), (1, 3), (3, 1), (8, 3), (1, 6), (4, 5), (5, 3), (1, 4), (6, 1), (6, 4), (8, 6), (3, 4),
|
||||
(7, 5), (4, 1), (5, 5), (2, 2), (2, 5), (7, 2), (5, 1), (4, 3), (8, 4)]),
|
||||
# ('moldorm vertical', [(5, 1), (6, 0), (7, 2), (5, 4), (4, 4), (4, 1), (3, 5), (5, 6), (3, 2), (6, 6), (7, 5),
|
||||
# (6, 1), (4, 8), (3, 3), (5, 7), (3, 8), (2, 7), (6, 4), (4, 0), (3, 6), (7, 3), (4, 6)]),
|
||||
# ('scream emoji', [(2, 2), (7, 2), (2, 3), (7, 3), (1, 7), (8, 7), (3, 2), (6, 2), (2, 6), (7, 6), (3, 3), (6, 3),
|
||||
# (2, 7), (7, 7), (4, 5), (5, 7), (5, 5), (4, 7), (4, 6), (5, 6), (2, 5), (7, 5)]),
|
||||
('mario mushroom', [(3, 7), (4, 7), (5, 7), (3, 4), (4, 4), (5, 4), (3, 1), (4, 1), (5, 1), (2, 2), (6, 6), (6, 2),
|
||||
(2, 6), (1, 3), (7, 5), (7, 3), (1, 5), (1, 4), (6, 5), (7, 4), (2, 5)]),
|
||||
('moldorm', [(1, 3), (2, 5), (3, 6), (5, 5), (7, 5), (7, 2), (5, 3), (3, 2), (2, 4), (1, 5), (5, 4), (6, 2), (7, 4),
|
||||
(8, 1), (8, 4), (4, 2), (9, 2), (2, 3), (4, 6), (9, 3), (7, 3), (6, 6)]),
|
||||
# ('thinking emoji', [(5, 6), (6, 4), (4, 3), (3, 1), (2, 6), (5, 3), (6, 6), (6, 1), (3, 0), (4, 7), (2, 4),
|
||||
# (3, 8), (6, 0), (3, 7), (3, 3)]),
|
||||
('triangle', [(1, 5), (7, 5), (4, 2), (3, 5), (5, 5), (4, 3), (2, 4), (6, 4), (5, 3), (2, 5), (6, 5), (3, 3),
|
||||
(4, 5), (5, 4), (3, 4), (4, 4)]),
|
||||
('heart', [(8, 3), (2, 3), (5, 7), (2, 4), (8, 4), (4, 6), (6, 6), (8, 2), (2, 2), (5, 2), (7, 1), (3, 1), (3, 5),
|
||||
(6, 1), (7, 5), (4, 1)]),
|
||||
('arrghus', [(4, 1), (6, 2), (2, 3), (4, 3), (3, 4), (4, 5), (5, 6), (3, 7), (1, 4), (2, 5), (5, 1), (6, 3), (2, 2),
|
||||
(7, 4), (5, 4), (4, 4), (6, 5), (3, 6), (5, 7), (3, 1), (3, 5), (5, 5)]),
|
||||
# ('cowboy smile', [(1, 2), (3, 3), (4, 1), (3, 5), (5, 8), (6, 7), (5, 2), (7, 2), (1, 3), (2, 7), (5, 5), (5, 3),
|
||||
# (3, 2), (4, 3), (7, 3), (2, 3), (4, 2), (3, 8), (4, 8), (6, 3)]),
|
||||
('clown face happy', [(2, 2), (7, 6), (7, 2), (2, 6), (3, 3), (6, 7), (6, 3), (3, 7), (2, 3), (5, 6), (7, 3),
|
||||
(4, 6), (2, 5), (6, 6), (7, 5), (3, 6), (4, 5), (5, 7), (5, 5), (4, 7), (3, 2), (6, 2)]),
|
||||
('generic happy face', [(2, 1), (6, 3), (6, 5), (4, 6), (2, 2), (6, 6), (2, 3), (3, 5), (3, 2), (3, 3), (6, 2),
|
||||
(5, 5), (1, 2), (3, 6), (7, 5), (7, 1), (4, 5), (8, 2), (5, 6), (2, 5), (7, 3), (7, 2)]),
|
||||
# ('YMCA', [(1, 2), (2, 3), (5, 2), (7, 2), (6, 3), (7, 4), (2, 4), (5, 4), (6, 2), (3, 2), (5, 3), (7, 3), (7, 6),
|
||||
# (4, 8), (2, 7), (6, 7), (4, 6), (8, 8), (8, 7), (3, 8), (3, 6), (6, 8)]),
|
||||
# ('ze', [(5, 7), (6, 7), (7, 7), (1, 3), (2, 3), (3, 3), (5, 5), (6, 5), (7, 5), (1, 7), (2, 7), (3, 7), (5, 3),
|
||||
# (6, 3), (7, 3), (3, 4), (2, 5), (1, 6), (5, 4), (5, 6)]),
|
||||
# ('space invader metroid', [(4, 1), (2, 3), (3, 5), (5, 6), (7, 6), (7, 3), (2, 8), (3, 2), (1, 7), (1, 4), (6, 2),
|
||||
# (8, 5), (7, 8), (4, 6), (8, 7), (5, 1), (2, 6), (8, 4), (1, 5), (6, 5)]),
|
||||
('screw attack', [(2, 7), (7, 4), (6, 1), (3, 7), (2, 4), (5, 6), (4, 2), (5, 4), (3, 6), (7, 1), (3, 3), (6, 4),
|
||||
(4, 6), (4, 3), (6, 2), (3, 4), (6, 5), (5, 2), (4, 5), (4, 4), (5, 3), (5, 5)]),
|
||||
('vanilla wrong order', [(7, 2), (7, 4), (7, 5), (7, 7), (6, 3), (6, 5), (5, 2), (5, 3), (5, 4), (5, 5), (5, 6),
|
||||
(4, 2), (4, 3), (4, 4), (4, 5), (4, 6), (3, 3), (3, 5), (2, 2), (2, 4), (2, 5), (2, 7)]),
|
||||
('tile shaped tiles', [(2, 7), (2, 6), (2, 5), (2, 4), (2, 3), (2, 2), (3, 2), (4, 2), (5, 2), (6, 2), (7, 2),
|
||||
(7, 3), (7, 4), (7, 5), (7, 6), (7, 7), (6, 7), (5, 7), (4, 7), (3, 7), (4, 5), (5, 4)]),
|
||||
# ('panda shocked emoji', [(7, 3), (7, 4), (3, 3), (3, 4), (5, 5), (5, 6), (5, 7), (4, 6), (4, 7), (6, 7), (6, 6),
|
||||
# (8, 6), (8, 7), (8, 8), (2, 8), (2, 7), (2, 6), (2, 1), (3, 1), (7, 1), (8, 1), (5, 8)]),
|
||||
('JK', [(1, 5), (3, 4), (5, 3), (7, 3), (3, 2), (7, 5), (6, 4), (2, 6), (5, 6), (5, 5), (8, 2), (3, 5), (8, 6),
|
||||
(5, 2), (3, 3), (5, 4)]),
|
||||
('dollar sign', [(6, 2), (5, 1), (4, 1), (3, 1), (2, 2), (2, 6), (3, 7), (4, 7), (5, 7), (6, 6), (2, 3), (6, 5),
|
||||
(3, 4), (5, 4), (4, 4), (4, 0), (4, 2), (4, 3), (4, 5), (4, 6), (4, 8)]),
|
||||
# ('rupee diagonal', [(1, 4), (1, 5), (1, 6), (1, 7), (2, 7), (3, 7), (4, 7), (5, 6), (6, 5), (7, 4), (7, 3),
|
||||
# (7, 2), (7, 1), (6, 1), (5, 1), (4, 1), (3, 2), (2, 3), (3, 5), (4, 4), (5, 3)]),
|
||||
# ('sword', [(1, 8), (8, 1), (8, 2), (1, 4), (7, 1), (5, 8), (7, 3), (2, 4), (6, 2), (5, 7), (6, 4), (2, 5), (5, 3),
|
||||
# (4, 7), (5, 5), (3, 6), (4, 4), (2, 7), (4, 6), (3, 5)]),
|
||||
('z1 dungeon1', [(4, 6), (6, 4), (2, 4), (3, 7), (4, 3), (5, 7), (3, 2), (5, 4), (3, 5), (5, 5), (4, 2), (6, 3),
|
||||
(4, 7), (3, 4), (7, 3), (4, 5), (4, 4)]),
|
||||
# ('z1 dungeon 4', [(4, 8), (3, 6), (4, 4), (5, 2), (3, 1), (4, 3), (6, 2), (4, 1), (3, 3), (5, 4), (3, 5), (4, 7),
|
||||
# (6, 1), (3, 8), (5, 7), (3, 2), (4, 6), (3, 4), (5, 1)]),
|
||||
# ('LTTP', [(3, 4), (2, 3), (6, 2), (6, 4), (2, 2), (5, 2), (6, 3), (2, 4), (7, 2), (3, 6), (4, 8), (8, 7), (7, 6),
|
||||
# (7, 8), (5, 6), (7, 7), (4, 6), (4, 7), (8, 6)]),
|
||||
('triple triforce', [(4, 2), (3, 3), (4, 3), (5, 3), (6, 5), (5, 6), (6, 6), (7, 6), (3, 6), (2, 6), (2, 5),
|
||||
(1, 6)]),
|
||||
# ('TILE', [(2, 2), (5, 4), (3, 2), (2, 4), (5, 2), (2, 3), (1, 2), (5, 3), (3, 6), (6, 6), (7, 8), (8, 6), (6, 7),
|
||||
# (3, 8), (4, 8), (3, 7), (6, 8), (7, 6), (7, 7), (8, 8)]),
|
||||
# ('panda thinking emoji', [(2, 1), (3, 1), (6, 2), (7, 2), (6, 3), (3, 2), (3, 3), (3, 5), (4, 5), (5, 5), (2, 6),
|
||||
# (2, 7), (1, 7), (2, 8), (1, 8), (3, 7), (4, 7), (3, 8)]),
|
||||
# ('pokata key', [(3, 1), (4, 2), (5, 3), (4, 4), (4, 6), (5, 7), (6, 8), (4, 8), (6, 6), (3, 3), (5, 1), (4, 5),
|
||||
# (3, 2), (4, 3), (5, 4), (5, 6), (4, 7), (5, 8), (3, 4), (5, 2), (4, 1)]),
|
||||
('tile shaped tiles randomish', [(4, 2), (2, 2), (7, 5), (5, 4), (3, 2), (4, 5), (4, 7), (7, 7), (2, 7), (2, 4),
|
||||
(7, 2), (2, 5), (5, 7), (7, 4), (5, 2), (6, 2), (3, 7), (2, 3), (7, 6), (6, 7),
|
||||
(7, 3), (2, 6)]),
|
||||
('NO', [(1, 5), (4, 4), (3, 4), (6, 2), (8, 4), (1, 2), (8, 5), (7, 5), (1, 3), (6, 5), (6, 4), (1, 4), (4, 5),
|
||||
(4, 2), (2, 3), (7, 2), (8, 2), (8, 3), (4, 3), (6, 3)]),
|
||||
('bomb', [(3, 3), (5, 7), (6, 4), (2, 6), (5, 3), (3, 7), (6, 6), (2, 4), (7, 2), (2, 5), (4, 7), (5, 1), (4, 2),
|
||||
(6, 5), (6, 1), (4, 3), (8, 2)]),
|
||||
# ('boot', [(6, 7), (8, 6), (5, 5), (5, 3), (8, 2), (3, 6), (4, 8), (7, 8), (8, 4), (6, 2), (2, 7), (3, 8), (4, 5),
|
||||
# (5, 4), (7, 2), (8, 7), (8, 8), (8, 3), (5, 8), (2, 8), (5, 2), (8, 5)]),
|
||||
# ('javalogo', [(5, 8), (4, 8), (3, 8), (2, 8), (1, 7), (5, 6), (4, 6), (3, 6), (2, 6), (1, 5), (7, 7), (8, 6),
|
||||
# (7, 5), (3, 4), (3, 3), (2, 2), (3, 1), (5, 4), (5, 3), (6, 2)]),
|
||||
# ('pokata and ender key', [(3, 1), (5, 3), (4, 4), (4, 6), (5, 7), (6, 8), (4, 8), (6, 6), (3, 3), (5, 1), (4, 5),
|
||||
# (3, 2), (4, 7), (4, 1), (5, 8), (5, 2), (3, 4), (5, 6), (5, 4)]),
|
||||
('kitty', [(3, 1), (6, 4), (7, 6), (8, 3), (1, 4), (3, 7), (3, 4), (2, 2), (5, 2), (6, 1), (6, 5), (6, 7), (2, 6),
|
||||
(7, 2), (8, 5), (1, 3), (1, 5), (4, 2), (3, 5), (4, 6), (8, 4), (5, 6)]),
|
||||
('creeper face', [(3, 7), (4, 5), (5, 4), (5, 6), (3, 3), (2, 2), (3, 2), (7, 3), (6, 7), (4, 6), (6, 3), (7, 2),
|
||||
(2, 3), (4, 4), (3, 6), (6, 2), (6, 6), (5, 5)]),
|
||||
('fast', [(7, 7)])
|
||||
]
|
||||
|
||||
|
||||
banned_tiles = {
|
||||
# these are pots in tower of hera, only ban if pottery is on?
|
||||
(1, 8), (1, 7), (3, 8), (5, 8), (7, 8),
|
||||
# these are crystal barrier tiles
|
||||
# (8, 3), (8, 4), (8, 5) # should I ban these too? bypasses barrier logic? regex \(8, [345]\)
|
||||
}
|
||||
1
source/enemizer/__init__.py
Normal file
1
source/enemizer/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
# do nothing, just exist to make "source" package
|
||||
304
source/enemizer/damage_table.yaml
Normal file
304
source/enemizer/damage_table.yaml
Normal file
@@ -0,0 +1,304 @@
|
||||
# From: https://spannerisms.github.io/damage
|
||||
# There are 16 damage classes, each with 8 subclasses.
|
||||
# These subclasses determine the damage or effect inflicted on a sprite.
|
||||
# Subclass data is stored as a table in ROM at $0D:B8F1
|
||||
|
||||
# DamageSource and SubClassTable
|
||||
|
||||
#_0DB8F1: db $00, $01, $20, $FF, $FC, $FB, $00, $00 ; 0x00 - Boomerang
|
||||
#_0DB8F9: db $00, $02, $40, $04, $00, $00, $00, $00 ; 0x01 - Sword 1
|
||||
#_0DB901: db $00, $04, $40, $02, $03, $00, $00, $00 ; 0x02 - Sword 2
|
||||
#_0DB909: db $00, $08, $40, $04, $00, $00, $00, $00 ; 0x03 - Sword 3
|
||||
#_0DB911: db $00, $10, $40, $08, $00, $00, $00, $00 ; 0x04 - Sword 4
|
||||
#_0DB919: db $00, $10, $40, $08, $00, $00, $00, $00 ; 0x05 - Sword 5
|
||||
#_0DB921: db $00, $04, $40, $10, $00, $00, $00, $00 ; 0x06 - Arrow
|
||||
#_0DB929: db $00, $FF, $40, $FF, $FC, $FB, $00, $00 ; 0x07 - Hookshot
|
||||
#_0DB931: db $00, $04, $40, $FF, $FC, $FB, $20, $00 ; 0x08 - Bomb
|
||||
#_0DB939: db $00, $64, $18, $64, $00, $00, $00, $00 ; 0x09 - Silver arrow
|
||||
#_0DB941: db $00, $F9, $FA, $FF, $64, $00, $00, $00 ; 0x0A - Powder
|
||||
#_0DB949: db $00, $08, $40, $FD, $04, $10, $00, $00 ; 0x0B - Fire rod
|
||||
#_0DB951: db $00, $08, $40, $FE, $04, $00, $00, $00 ; 0x0C - Ice rod
|
||||
#_0DB959: db $00, $10, $40, $FD, $00, $00, $00, $00 ; 0x0D - Bombos
|
||||
#_0DB961: db $00, $FE, $40, $10, $00, $00, $00, $00 ; 0x0E - Ether
|
||||
#_0DB969: db $00, $20, $40, $FF, $00, $00, $00, $FA ; 0x0F - Quake
|
||||
|
||||
# Special Values:
|
||||
# $F9 Target becomes a faerie
|
||||
# $FA Target becomes a blob
|
||||
# $FB Target stunned for 32 frames
|
||||
# $FC Target stunned for 128 frames
|
||||
# $FD Target incinerated
|
||||
# $FE Target becomes frozen
|
||||
# $FF Target stunned for 255 frames
|
||||
|
||||
DamageSource:
|
||||
Boomerang:
|
||||
class: 0x00
|
||||
subclass: [0x00, 0x01, 0x20, 0xFF, 0xFC, 0xFB, 0x00, 0x00]
|
||||
Sword1:
|
||||
class: 0x01
|
||||
subclass: [0x00, 0x02, 0x40, 0x04, 0x00, 0x00, 0x00, 0x00]
|
||||
Sword2:
|
||||
class: 0x02
|
||||
subclass: [0x00, 0x04, 0x40, 0x02, 0x03, 0x00, 0x00, 0x00]
|
||||
Sword3:
|
||||
class: 0x03
|
||||
subclass: [0x00, 0x08, 0x40, 0x04, 0x00, 0x00, 0x00, 0x00]
|
||||
Sword4:
|
||||
class: 0x04
|
||||
subclass: [0x00, 0x10, 0x40, 0x08, 0x00, 0x00, 0x00, 0x00]
|
||||
Sword5:
|
||||
class: 0x05
|
||||
subclass: [0x00, 0x10, 0x40, 0x08, 0x00, 0x00, 0x00, 0x00]
|
||||
Arrow:
|
||||
class: 0x06
|
||||
subclass: [0x00, 0x04, 0x40, 0x10, 0x00, 0x00, 0x00, 0x00]
|
||||
Hookshot:
|
||||
class: 0x07
|
||||
subclass: [0x00, 0xFF, 0x40, 0xFF, 0xFC, 0xFB, 0x00, 0x00]
|
||||
Bomb:
|
||||
class: 0x08
|
||||
subclass: [0x00, 0x04, 0x40, 0xFF, 0xFC, 0xFB, 0x20, 0x00]
|
||||
SilverArrow:
|
||||
class: 0x09
|
||||
subclass: [0x00, 0x64, 0x18, 0x64, 0x00, 0x00, 0x00, 0x00]
|
||||
Powder:
|
||||
class: 0x0A
|
||||
subclass: [0x00, 0xF9, 0xFA, 0xFF, 0x64, 0x00, 0x00, 0x00]
|
||||
FireRod:
|
||||
class: 0x0B
|
||||
subclass: [0x00, 0x08, 0x40, 0xFD, 0x04, 0x10, 0x00, 0x00]
|
||||
IceRod:
|
||||
class: 0x0C
|
||||
subclass: [0x00, 0x08, 0x40, 0xFE, 0x04, 0x00, 0x00, 0x00]
|
||||
Bombos:
|
||||
class: 0x0D
|
||||
subclass: [0x00, 0x10, 0x40, 0xFD, 0x00, 0x00, 0x00, 0x00]
|
||||
Ether:
|
||||
class: 0x0E
|
||||
subclass: [0x00, 0xFE, 0x40, 0x10, 0x00, 0x00, 0x00, 0x00]
|
||||
Quake:
|
||||
class: 0x0F
|
||||
subclass: [0x00, 0x20, 0x40, 0xFF, 0x00, 0x00, 0x00, 0xFA]
|
||||
|
||||
# The subclass that each sprite should look for in each damage class is in a table in WRAM at $7F:6000
|
||||
# Rando migrated it to $31:C800
|
||||
SubClassTable:
|
||||
0x0: [1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 0, 3, 1, 3, 1, 1]
|
||||
0x1: [1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 0, 3, 1, 3, 1, 1]
|
||||
0x2: [1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
0x3: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
0x4: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
0x5: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
0x6: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
0x7: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
0x8: [3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 3, 3, 1, 7]
|
||||
0x9: [0, 1, 3, 3, 3, 3, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0]
|
||||
0xA: [3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 3, 3, 1, 7]
|
||||
0xB: [1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 0, 1, 1, 0, 0, 0]
|
||||
0xC: [1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 0, 1, 1, 1, 3, 1]
|
||||
0xD: [3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 1, 3]
|
||||
0xE: [3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 3, 3, 2, 7]
|
||||
0xF: [1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 0, 3, 1, 3, 3, 2]
|
||||
0x10: [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 3, 1]
|
||||
0x11: [4, 1, 1, 1, 1, 2, 1, 0, 2, 1, 0, 1, 3, 3, 1, 7]
|
||||
0x12: [3, 1, 1, 1, 1, 1, 1, 1, 2, 1, 2, 3, 3, 3, 1, 7]
|
||||
0x13: [0, 1, 1, 1, 1, 1, 1, 3, 2, 3, 2, 0, 0, 3, 2, 7]
|
||||
0x14: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
0x15: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0]
|
||||
0x16: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
0x17: [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 7]
|
||||
0x18: [0, 1, 1, 1, 1, 1, 1, 2, 1, 1, 2, 3, 1, 3, 3, 7]
|
||||
0x19: [1, 1, 1, 2, 1, 1, 1, 2, 1, 1, 0, 1, 1, 3, 2, 3]
|
||||
0x1A: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
0x1B: [2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 3, 2]
|
||||
0x1C: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
0x1D: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
0x1E: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
0x1F: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
0x20: [3, 1, 1, 1, 1, 1, 1, 1, 0, 1, 2, 3, 3, 3, 1, 7]
|
||||
0x21: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
0x22: [3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 3, 3, 2, 7]
|
||||
0x23: [0, 1, 1, 1, 1, 1, 1, 2, 1, 1, 0, 3, 2, 3, 2, 3]
|
||||
0x24: [0, 1, 1, 1, 1, 1, 1, 2, 1, 1, 0, 3, 2, 3, 2, 3]
|
||||
0x25: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
0x26: [0, 1, 1, 1, 1, 1, 0, 3, 3, 1, 0, 0, 0, 3, 1, 3]
|
||||
0x27: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 7]
|
||||
0x28: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
0x29: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
0x2A: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0]
|
||||
0x2B: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
0x2C: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
0x2D: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
0x2E: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
0x2F: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
0x30: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
0x31: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
0x32: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
0x33: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
0x34: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
0x35: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
0x36: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
0x37: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
0x38: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
0x39: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
0x3A: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
0x3B: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
0x3C: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
0x3D: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
0x3E: [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 2, 2, 2, 7]
|
||||
0x3F: [0, 0, 2, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1]
|
||||
0x40: [0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
0x41: [3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 3, 1, 3, 1, 7]
|
||||
0x42: [3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 3, 3, 1, 7]
|
||||
0x43: [3, 1, 4, 3, 1, 1, 1, 1, 1, 1, 0, 3, 0, 3, 1, 7]
|
||||
0x44: [3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 3, 0, 3, 1, 7]
|
||||
0x45: [3, 1, 4, 3, 1, 1, 1, 1, 1, 1, 0, 3, 0, 3, 1, 7]
|
||||
0x46: [3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 3, 3, 3, 1, 7]
|
||||
0x47: [3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 3, 1, 3, 2, 7]
|
||||
0x48: [3, 1, 4, 3, 1, 1, 1, 1, 1, 1, 0, 3, 0, 3, 1, 7]
|
||||
0x49: [3, 1, 4, 3, 1, 1, 1, 1, 1, 1, 0, 3, 0, 3, 2, 7]
|
||||
0x4A: [3, 1, 4, 3, 1, 1, 1, 1, 1, 1, 0, 3, 3, 3, 1, 7]
|
||||
0x4B: [3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 3, 3, 1, 7]
|
||||
0x4C: [1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 0, 1, 1, 3, 3, 3]
|
||||
0x4D: [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 3, 2, 3, 2, 3]
|
||||
0x4E: [3, 1, 1, 1, 1, 1, 1, 2, 1, 1, 2, 3, 3, 3, 1, 7]
|
||||
0x4F: [3, 1, 1, 1, 1, 1, 1, 2, 1, 1, 2, 3, 3, 3, 1, 7]
|
||||
0x50: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
0x51: [3, 1, 1, 1, 1, 1, 2, 1, 1, 1, 0, 1, 3, 3, 3, 3]
|
||||
0x52: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
0x53: [1, 3, 3, 3, 3, 3, 3, 0, 1, 1, 0, 1, 1, 0, 0, 0]
|
||||
0x54: [0, 1, 3, 3, 3, 3, 1, 0, 1, 1, 0, 1, 1, 0, 0, 0]
|
||||
0x55: [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 3, 1, 3, 2, 1]
|
||||
0x56: [3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 3, 1, 3, 2, 1]
|
||||
0x57: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
0x58: [3, 1, 1, 1, 1, 1, 1, 3, 1, 1, 2, 1, 3, 3, 1, 7]
|
||||
0x59: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
0x5A: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
0x5B: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 3]
|
||||
0x5C: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 3]
|
||||
0x5D: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
0x5E: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
0x5F: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
0x60: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
0x61: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
0x62: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
0x63: [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 3, 3, 3] # the pit spawns the 0x64
|
||||
0x64: [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 3, 3, 3]
|
||||
0x65: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
0x66: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
0x67: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
0x68: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
0x69: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
0x6A: [5, 1, 3, 1, 1, 1, 1, 1, 1, 1, 0, 3, 0, 3, 1, 7]
|
||||
0x6B: [3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1]
|
||||
0x6C: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
0x6D: [3, 1, 1, 1, 1, 1, 1, 2, 1, 1, 2, 3, 3, 3, 1, 7]
|
||||
0x6E: [3, 1, 1, 1, 1, 1, 1, 2, 1, 1, 2, 3, 3, 3, 1, 7]
|
||||
0x6F: [1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 0, 3, 3, 3, 1, 3]
|
||||
0x70: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
0x71: [3, 1, 1, 1, 1, 1, 1, 3, 1, 1, 0, 3, 3, 3, 1, 3]
|
||||
0x72: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
0x73: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
0x74: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
0x75: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
0x76: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
0x77: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
0x78: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
0x79: [1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 3, 1]
|
||||
0x7A: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
0x7B: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
0x7C: [0, 1, 1, 1, 1, 1, 1, 0, 2, 1, 0, 3, 3, 3, 3, 3]
|
||||
0x7D: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
0x7E: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
0x7F: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
0x80: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
0x81: [0, 1, 1, 1, 1, 1, 1, 2, 1, 1, 0, 3, 3, 2, 3, 2]
|
||||
0x82: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
0x83: [0, 1, 1, 2, 2, 1, 2, 0, 1, 2, 0, 0, 0, 0, 0, 0]
|
||||
0x84: [0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0]
|
||||
0x85: [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 2, 3, 2, 3]
|
||||
0x86: [0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 1, 3, 3, 1, 7]
|
||||
0x87: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
0x88: [0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0] # mothula
|
||||
0x89: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
0x8A: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
0x8B: [3, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 3, 3, 3, 2, 3]
|
||||
0x8C: [0, 0, 1, 1, 1, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 0]
|
||||
0x8D: [0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0]
|
||||
0x8E: [1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 0, 1, 3, 2, 2, 3]
|
||||
0x8F: [3, 1, 1, 1, 1, 1, 1, 2, 2, 1, 0, 3, 3, 3, 1, 2]
|
||||
0x90: [1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 3, 3, 2]
|
||||
0x91: [1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
0x92: [0, 0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0]
|
||||
0x93: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
0x94: [1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 0, 3, 1, 3, 2, 3]
|
||||
0x95: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
0x96: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
0x97: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
0x98: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
0x99: [1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 0, 1, 0, 3, 1, 2]
|
||||
0x9A: [1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 0, 2, 3, 2, 1, 1]
|
||||
0x9B: [0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 1, 1, 2, 3, 2]
|
||||
0x9C: [0, 1, 1, 1, 1, 1, 1, 2, 1, 1, 0, 3, 2, 3, 2, 2]
|
||||
0x9D: [0, 1, 1, 1, 1, 1, 1, 2, 1, 1, 0, 3, 2, 3, 2, 2]
|
||||
0x9E: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
0x9F: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
0xA0: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
0xA1: [0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 2, 0, 2, 0, 0]
|
||||
0xA2: [0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0]
|
||||
0xA3: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 2, 0, 0]
|
||||
0xA4: [0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 3, 0, 1, 3, 1]
|
||||
0xA5: [3, 1, 1, 1, 1, 1, 1, 1, 2, 1, 0, 3, 3, 3, 1, 3]
|
||||
0xA6: [3, 1, 1, 1, 1, 1, 1, 1, 2, 1, 0, 3, 3, 3, 1, 3]
|
||||
0xA7: [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 2, 3, 2, 7]
|
||||
0xA8: [0, 1, 1, 1, 1, 1, 1, 2, 1, 1, 0, 3, 3, 3, 1, 1]
|
||||
0xA9: [0, 1, 1, 1, 1, 1, 1, 2, 1, 1, 0, 3, 3, 3, 1, 1]
|
||||
0xAA: [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 3, 1, 3, 1, 3]
|
||||
0xAB: [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0]
|
||||
0xAC: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
0xAD: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
0xAE: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
0xAF: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
0xB0: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
0xB1: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
0xB2: [1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 0, 1, 1, 1, 3, 1]
|
||||
0xB3: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
0xB4: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
0xB5: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
0xB6: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
0xB7: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
0xB8: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
0xB9: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
0xBA: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
0xBB: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
0xBC: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
0xBD: [0, 0, 1, 1, 1, 1, 3, 0, 1, 1, 0, 0, 0, 0, 0, 0]
|
||||
0xBE: [0, 0, 1, 1, 1, 1, 3, 0, 1, 1, 0, 0, 0, 0, 0, 0]
|
||||
0xBF: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
0xC0: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
0xC1: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
0xC2: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
0xC3: [0, 1, 1, 1, 1, 1, 3, 0, 1, 1, 0, 0, 0, 0, 0, 0]
|
||||
0xC4: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
0xC5: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 3, 1]
|
||||
0xC6: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 3, 1]
|
||||
0xC7: [0, 1, 1, 1, 1, 1, 1, 0, 1, 2, 0, 3, 1, 3, 1, 3]
|
||||
0xC8: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
0xC9: [5, 1, 1, 1, 1, 1, 3, 0, 2, 1, 0, 3, 3, 1, 3, 1]
|
||||
0xCA: [5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
0xCB: [0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
0xCC: [0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0]
|
||||
0xCD: [0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0]
|
||||
0xCE: [0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
0xCF: [1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 0, 1, 1, 1, 2, 1]
|
||||
0xD0: [0, 0, 0, 1, 1, 1, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0]
|
||||
0xD1: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 2, 2, 2]
|
||||
0xD2: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 7]
|
||||
0xD3: [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 2, 7]
|
||||
0xD4: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
0xD5: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
0xD6: [0, 0, 0, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
0xD7: [0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0]
|
||||
0xEF: [0, 1, 1, 2, 2, 1, 2, 0, 1, 2, 0, 0, 0, 0, 0, 0]
|
||||
0xF0: [0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0]
|
||||
10
source/enemizer/enemy_damage_table.yaml
Normal file
10
source/enemizer/enemy_damage_table.yaml
Normal file
@@ -0,0 +1,10 @@
|
||||
0x00: [0x02, 0x01, 0x01]
|
||||
0x01: [0x04, 0x04, 0x04]
|
||||
0x02: [0x00, 0x00, 0x00]
|
||||
0x03: [0x08, 0x04, 0x02]
|
||||
0x04: [0x08, 0x08, 0x08]
|
||||
0x05: [0x10, 0x08, 0x04]
|
||||
0x06: [0x20, 0x10, 0x08]
|
||||
0x07: [0x20, 0x18, 0x10]
|
||||
0x08: [0x18, 0x10, 0x08] # Roller class damage
|
||||
0x09: [0x40, 0x30, 0x18] # Ganon class damage - max 8 hearts
|
||||
@@ -17,9 +17,9 @@ UwGeneralDeny:
|
||||
- [ 0x000e, 0, [ "RollerVerticalDown", "RollerVerticalUp", "RollerHorizontalRight", "RollerHorizontalLeft" ] ] #"Ice Palace - Entrance - Freezor"
|
||||
- [ 0x000e, 1, [ "RollerVerticalDown", "RollerVerticalUp", "RollerHorizontalRight", "RollerHorizontalLeft" ] ] #"Ice Palace - Bari Key - Top Bari"
|
||||
- [ 0x000e, 2, [ "RollerVerticalDown", "RollerVerticalUp", "RollerHorizontalRight", "RollerHorizontalLeft" ] ] #"Ice Palace - Bari Key - Middle Bari"
|
||||
- [ 0x0016, 0, [ "RollerVerticalDown", "RollerVerticalUp", "Beamos", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper" ] ] #"Swamp Palace - Pool - Zol 1"
|
||||
- [ 0x0016, 1, [ "RollerVerticalDown", "RollerVerticalUp", "RollerHorizontalRight", "RollerHorizontalLeft", "Beamos", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper" ] ] #"Swamp Palace - Pool - Zol 2"
|
||||
- [ 0x0016, 2, [ "SparkCW", "SparkCCW", "RollerVerticalDown", "RollerVerticalUp", "RollerHorizontalRight", "RollerHorizontalLeft", "Beamos", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper" ] ] #"Swamp Palace - Pool - Blue Bari"
|
||||
- [ 0x0016, 0, [ "RollerVerticalDown", "RollerVerticalUp", "Beamos", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper", "GreenMimic", "RedMimic", "Pikit"] ] #"Swamp Palace - Pool - Zol 1"
|
||||
- [ 0x0016, 1, [ "RollerVerticalDown", "RollerVerticalUp", "RollerHorizontalRight", "RollerHorizontalLeft", "Beamos", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper", "GreenMimic", "RedMimic", "Pikit" ] ] #"Swamp Palace - Pool - Zol 2"
|
||||
- [ 0x0016, 2, [ "SparkCW", "SparkCCW", "RollerVerticalDown", "RollerVerticalUp", "RollerHorizontalRight", "RollerHorizontalLeft", "Beamos", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper", "GreenMimic", "RedMimic", "Pikit" ] ] #"Swamp Palace - Pool - Blue Bari"
|
||||
- [ 0x0016, 3, [ "RollerVerticalDown", "RollerVerticalUp", "RollerHorizontalRight", "RollerHorizontalLeft", "Beamos", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper" ] ] #"Swamp Palace - Pool - Zol 3"
|
||||
- [ 0x0017, 5, [ "Beamos", "AntiFairyCircle", "SpikeBlock", "Bumper" ] ] #"Tower Of Hera - Bumper Room - Fire Bar (Clockwise)"
|
||||
- [ 0x0019, 0, [ "SparkCW", "SparkCCW", "RollerVerticalDown", "Beamos", "AntiFairyCircle", "BigSpike", "Bumper" ] ] #"Palace of Darkness - Dark Maze - Kodongo 1"
|
||||
@@ -52,7 +52,7 @@ UwGeneralDeny:
|
||||
- [ 0x0028, 4, [ "RollerVerticalUp" ] ] #"Swamp Palace - Entrance Ledge - Spike Trap"
|
||||
- [ 0x002a, 2, [ "SparkCW", "SparkCCW", "RollerHorizontalRight", "RollerHorizontalLeft", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper"]] #"Palace of Darkness - Arena Main - Hardhat Beetle 1"
|
||||
- [ 0x002a, 3, [ "Statue", "SparkCW", "SparkCCW", "RollerVerticalDown", "RollerVerticalUp", "RollerHorizontalRight", "RollerHorizontalLeft", "Beamos", "AntiFairyCircle", "BigSpike", "FirebarCW", "FirebarCCW", "SpikeBlock", "Bumper" ] ] #"Palace of Darkness - Arena Main - Hardhat Beetle 2"
|
||||
- [ 0x002a, 4, [ "Statue", "Beamos", "AntiFairyCircle", "BigSpike", "Bumper" ]]
|
||||
- [ 0x002a, 4, [ "Statue", "Beamos", "AntiFairyCircle", "BigSpike", "Bumper", "RollerHorizontalRight", "RollerHorizontalLeft"]]
|
||||
- [ 0x002a, 6, [ "RollerVerticalUp", "RollerHorizontalRight", "RollerHorizontalLeft", "Beamos", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper" ] ] #"Palace of Darkness - Arena Main - Hardhat Beetle 5"
|
||||
- [ 0x002b, 5, [ "RollerHorizontalRight" ] ] #"Palace of Darkness - Fairies - Red Bari 2"
|
||||
- [ 0x002e, 0, [ "RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalLeft", "RollerHorizontalRight", "BigSpike", "FirebarCW", "FirebarCCW" ] ] #"Ice Palace - Penguin Chest - Pengator 1"
|
||||
@@ -67,6 +67,7 @@ UwGeneralDeny:
|
||||
- [ 0x0034, 4, [ "Statue", "SparkCW", "SparkCCW", "RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalLeft", "RollerHorizontalRight", "Beamos", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper" ] ] #"Swamp Palace - West Wing - Zol"
|
||||
- [ 0x0035, 6, [ "RollerHorizontalRight" ] ] #"Swamp Palace - West Lever - Stalfos 2"
|
||||
- [ 0x0035, 9, [ "RollerHorizontalRight", "Beamos", "AntiFairyCircle", "Bumper" ] ] #"Swamp Palace - West Lever - Blue Bari"
|
||||
- [0x0036, 5, ["AntiFairyCircle", "Bumper"]]
|
||||
- [ 0x0036, 7, [ "RollerHorizontalRight", "Beamos", "AntiFairyCircle", "BigSpike", "FirebarCW", "FirebarCCW", "SpikeBlock", "Bumper" ] ] #"Swamp Palace - Lobby - Hover 3"
|
||||
- [ 0x0037, 7, [ "RollerHorizontalRight" ] ] #"Swamp Palace - Water 1 - Blue Bari"
|
||||
- [ 0x0038, 4, [ "RollerHorizontalRight" ] ] #"Swamp Palace - Long Hall - Kyameron 2"
|
||||
@@ -90,12 +91,12 @@ UwGeneralDeny:
|
||||
- [ 0x0041, 0, [ "RollerHorizontalLeft" ] ] #"Sewers - Dark Cactus - Rat 1"
|
||||
- [ 0x0041, 1, [ "RollerVerticalDown", "RollerHorizontalRight" ] ] #"Sewers - Dark Cactus - Rat 2"
|
||||
- [ 0x0041, 2, [ "RollerVerticalUp" ] ] #"Sewers - Dark Cactus - Rat 3"
|
||||
- [ 0x0042, 0, [ "SparkCW", "SparkCCW", "RollerHorizontalLeft", "Beamos", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper" ] ] #"Sewers - Dark Rope Corridor - Rope 1"
|
||||
- [ 0x0042, 1, [ "SparkCW", "SparkCCW", "RollerHorizontalLeft", "Beamos", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper" ] ] #"Sewers - Dark Rope Corridor - Rope 2"
|
||||
- [ 0x0042, 2, [ "SparkCW", "SparkCCW", "RollerHorizontalLeft", "Beamos", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper" ] ] #"Sewers - Dark Rope Corridor - Rope 3"
|
||||
- [ 0x0042, 3, [ "SparkCW", "SparkCCW", "RollerHorizontalLeft", "Beamos", "AntiFairyCircle", "BigSpike", "Bumper" ] ] #"Sewers - Dark Rope Corridor - Rope 4"
|
||||
- [ 0x0042, 4, [ "SparkCW", "SparkCCW", "RollerHorizontalLeft", "Beamos", "AntiFairyCircle", "BigSpike", "Bumper" ] ] #"Sewers - Dark Rope Corridor - Rope 5"
|
||||
- [ 0x0042, 5, [ "SparkCW", "SparkCCW", "RollerHorizontalLeft", "Beamos", "AntiFairyCircle", "BigSpike", "Bumper" ] ] #"Sewers - Dark Rope Corridor - Rope 6"
|
||||
- [ 0x0042, 0, [ "SparkCW", "SparkCCW", "RollerHorizontalLeft", "Beamos", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper", "Chainchomp" ] ] #"Sewers - Dark Rope Corridor - Rope 1"
|
||||
- [ 0x0042, 1, [ "SparkCW", "SparkCCW", "RollerHorizontalLeft", "Beamos", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper", "Chainchomp" ] ] #"Sewers - Dark Rope Corridor - Rope 2"
|
||||
- [ 0x0042, 2, [ "SparkCW", "SparkCCW", "RollerHorizontalLeft", "Beamos", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper", "Chainchomp" ] ] #"Sewers - Dark Rope Corridor - Rope 3"
|
||||
- [ 0x0042, 3, [ "SparkCW", "SparkCCW", "RollerHorizontalLeft", "Beamos", "AntiFairyCircle", "BigSpike", "Bumper", "Chainchomp" ] ] #"Sewers - Dark Rope Corridor - Rope 4"
|
||||
- [ 0x0042, 4, [ "SparkCW", "SparkCCW", "RollerHorizontalLeft", "Beamos", "AntiFairyCircle", "BigSpike", "Bumper", "Chainchomp" ] ] #"Sewers - Dark Rope Corridor - Rope 5"
|
||||
- [ 0x0042, 5, [ "SparkCW", "SparkCCW", "RollerHorizontalLeft", "Beamos", "AntiFairyCircle", "BigSpike", "Bumper", "Chainchomp" ] ] #"Sewers - Dark Rope Corridor - Rope 6"
|
||||
- [ 0x0044, 4, [ "RollerVerticalUp", "RollerHorizontalLeft", "RollerHorizontalRight", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper" ] ] #"Thieves' Town - Joke Room - Zol"
|
||||
- [ 0x0044, 6, [ "RollerVerticalUp", "RollerVerticalDown", "Beamos", "BigSpike" ] ] #"Thieves' Town - Joke Room - Red Bari"
|
||||
- [ 0x0044, 8, [ "Statue", "RollerVerticalDown", "RollerHorizontalLeft", "RollerHorizontalRight", "AntiFairyCircle", "SpikeBlock", "Bumper" ] ] #"Thieves' Town - Joke Room - Blue Bari 4"
|
||||
@@ -125,7 +126,7 @@ UwGeneralDeny:
|
||||
- [ 0x0052, 2, [ "RollerVerticalUp", "RollerVerticalDown", "AntiFairyCircle", "Bumper" ] ] #"Hyrule Castle - North East Passage - Green Knife Guard 2"
|
||||
- [ 0x0053, 1, [ "AntiFairyCircle", "Bumper" ] ] #"Desert Palace - Bridge - Beamos 1"
|
||||
- [ 0x0053, 5, [ "RollerVerticalDown" ] ] #"Desert Palace - Popo Genocide - Popo TL"
|
||||
- [ 0x0053, 7, [ "Beamos", "AntiFairyCircle", "Bumper" ] ] #"Desert Palace - Bridge - Popo 5"
|
||||
- [ 0x0053, 7, ["Beamos", "AntiFairyCircle", "Bumper", "RollerVerticalUp", "RollerVerticalDown"]] #"Desert Palace - Bridge - Popo 5"
|
||||
- [ 0x0055, 1, [ "RollerVerticalUp", "RollerHorizontalRight", "AntiFairyCircle", "BigSpike", "Bumper" ] ] #"Secret Passage Exit - Green Knife Guard 1"
|
||||
- [ 0x0057, 0, [ "Wizzrobe", "Statue" ] ] # Wizzrobes can't spawn on pots
|
||||
- [ 0x0057, 1, ["Statue"]] # Statue switch issues
|
||||
@@ -139,8 +140,8 @@ UwGeneralDeny:
|
||||
- [ 0x0057, 10, ["Statue"]] # Statue switch issues
|
||||
- [ 0x0057, 11, ["Statue"]] # Statue switch issues
|
||||
- [ 0x0057, 12, [ "RollerVerticalUp", "RollerVerticalDown", "Beamos", "AntiFairyCircle", "Bumper", "BigSpike", "SpikeBlock", "Statue"]] #"Skull Woods - Big Key Room - Gibdo 6"
|
||||
- [ 0x0057, 13, [ "RollerVerticalDown", "Beamos", "AntiFairyCircle", "Bumper", "Statue" ] ] #"Skull Woods - Big Key Room - Blue Bari 1"
|
||||
- [ 0x0057, 14, [ "RollerVerticalDown", "Beamos", "AntiFairyCircle", "Bumper", "Statue" ] ] #"Skull Woods - Big Key Room - Blue Bari 2"
|
||||
- [ 0x0057, 13, [ "RollerVerticalDown", "Beamos", "AntiFairyCircle", "Bumper", "Statue", "BigSpike"]] #"Skull Woods - Big Key Room - Blue Bari 1"
|
||||
- [ 0x0057, 14, [ "RollerVerticalDown", "Beamos", "AntiFairyCircle", "Bumper", "Statue", "BigSpike"]] #"Skull Woods - Big Key Room - Blue Bari 2"
|
||||
- [ 0x0058, 0, ["Statue"]]
|
||||
- [ 0x0058, 1, ["Statue"]]
|
||||
- [ 0x0058, 2, ["Statue"]]
|
||||
@@ -156,7 +157,7 @@ UwGeneralDeny:
|
||||
- [ 0x005e, 4, [ "RollerVerticalUp", "RollerVerticalDown" ] ] #"Ice Palace - Pit Trap - Fire Bar (Clockwise)"
|
||||
- [ 0x005f, 0, [ "RollerVerticalDown", "RollerHorizontalLeft" ] ] #"Ice Palace - Bari University - Blue Bari 1"
|
||||
- [ 0x005f, 1, [ "RollerVerticalDown", "RollerHorizontalRight" ] ] #"Ice Palace - Bari University - Blue Bari 2"
|
||||
- [ 0x0060, 0, [ "RollerVerticalUp", "RollerHorizontalLeft", "AntiFairyCircle", "BigSpike", "Bumper" ] ] #"Hyrule Castle - West - Blue Guard"
|
||||
- [ 0x0060, 0, [ "RollerVerticalUp", "RollerHorizontalLeft", "AntiFairyCircle", "BigSpike", "Bumper", "Beamos" ] ] #"Hyrule Castle - West - Blue Guard"
|
||||
- [ 0x0062, 0, [ "RollerVerticalUp", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper" ] ] #"Hyrule Castle - East - Blue Guard"
|
||||
- [ 0x0064, 2, [ "Bumper" , "Beamos" ] ] #"Thieves' Town - Attic Hall Left - Keese 2"
|
||||
- [ 0x0064, 3, [ "Wizzrobe", "Statue" ] ] # Wizzrobes can't spawn on pots
|
||||
@@ -170,7 +171,7 @@ UwGeneralDeny:
|
||||
- [ 0x0067, 2, ["Bumper"]] #"Skull Woods - Firebar Pits - Blue Bari 2"
|
||||
- [ 0x0067, 3, [ "RollerVerticalUp", "RollerVerticalDown" ] ] #"Skull Woods - Firebar Pits - Hardhat Beetle 1"
|
||||
- [ 0x0067, 4, [ "AntiFairyCircle", "Bumper" ]]
|
||||
- [ 0x0067, 5, [ "RollerVerticalDown" ] ] #"Skull Woods - Firebar Pits - Hardhat Beetle 3"
|
||||
- [ 0x0067, 5, ["RollerVerticalDown", "Beamos"]] #"Skull Woods - Firebar Pits - Hardhat Beetle 3"
|
||||
- [ 0x0067, 6, [ "RollerVerticalDown" ] ] #"Skull Woods - Firebar Pits - Hardhat Beetle 4"
|
||||
- [ 0x0067, 7, [ "Beamos", "AntiFairyCircle", "Bumper", "BunnyBeam" ] ] #"Skull Woods - Firebar Pits - Fire Bar (Clockwise)"
|
||||
- [ 0x006a, 0, [ "RollerVerticalUp", "RollerVerticalDown", "Beamos", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper" ] ] #"Palace of Darkness - Dark Alley - Terrorpin 1"
|
||||
@@ -195,7 +196,7 @@ UwGeneralDeny:
|
||||
- [ 0x007b, 7, [ "Beamos", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper" ] ] #"Ganon's Tower - DMs Room - Hardhat Beetle"
|
||||
- [ 0x007c, 1, [ "RollerVerticalUp", "RollerVerticalDown", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper" ] ] #"Ganon's Tower - Randomizer Room - Fire Bar (Counterclockwise)"
|
||||
- [ 0x007c, 2, [ "RollerVerticalUp", "RollerVerticalDown", "AntiFairyCircle", "BigSpike", "Bumper" ] ] #"Ganon's Tower - Randomizer Room - Spike Trap"
|
||||
- [ 0x007c, 3, [ "RollerVerticalUp", "RollerVerticalDown", "AntiFairyCircle", "BigSpike", "Bumper" ] ] #"Ganon's Tower - Randomizer Room - Fire Bar (Clockwise)"
|
||||
- [ 0x007c, 3, [ "RollerVerticalUp", "RollerVerticalDown", "AntiFairyCircle", "BigSpike", "Bumper", "Statue"]] #"Ganon's Tower - Randomizer Room - Fire Bar (Clockwise)"
|
||||
- [ 0x007c, 4, [ "RollerVerticalUp", "RollerVerticalDown", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper" ] ] #"Ganon's Tower - Randomizer Room - Hardhat Beetle"
|
||||
- [ 0x007d, 0, [ "RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalLeft", "RollerHorizontalRight", "AntiFairyCircle", "BigSpike", "Bumper" ] ] #"Ganon's Tower - The Zoo - Fire Snake 1"
|
||||
- [ 0x007d, 1, [ "RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalLeft", "RollerHorizontalRight", "AntiFairyCircle", "BigSpike", "Bumper" ] ] #"Ganon's Tower - The Zoo - Fire Snake 2"
|
||||
@@ -244,6 +245,7 @@ UwGeneralDeny:
|
||||
- [ 0x0098, 2, [ "RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalLeft", "RollerHorizontalRight", "Beamos", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper" ] ] #"Misery Mire - Entrance - Zol 3"
|
||||
- [ 0x0098, 3, [ "RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalLeft", "RollerHorizontalRight", "Beamos", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper" ] ] #"Misery Mire - Entrance - Zol 4"
|
||||
- [ 0x0098, 4, [ "RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalLeft", "RollerHorizontalRight", "Beamos", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper" ] ] #"Misery Mire - Entrance - Zol 5"
|
||||
- [0x0099, 8, ["RollerHorizontalLeft", "RollerHorizontalRight"]]
|
||||
- [ 0x009b, 3, [ "RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalLeft", "RollerHorizontalRight", "Beamos", "AntiFairyCircle", "BigSpike", "Bumper" ] ] #"Ganon's Tower - Spike Switch - Spike Trap 1"
|
||||
- [ 0x009b, 4, [ "RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalLeft", "RollerHorizontalRight", "Beamos", "AntiFairyCircle", "BigSpike", "Bumper" ] ] #"Ganon's Tower - Spike Switch - Spike Trap 2"
|
||||
- [ 0x009b, 5, [ "RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalLeft", "RollerHorizontalRight", "Beamos", "AntiFairyCircle", "BigSpike", "Bumper" ] ]
|
||||
@@ -288,7 +290,8 @@ UwGeneralDeny:
|
||||
- [ 0x00b2, 9, [ "RollerVerticalUp" ] ] #"Misery Mire - Sluggula Cross - Sluggula BL"
|
||||
- [ 0x00b3, 0, [ "RollerVerticalUp", "RollerHorizontalRight", "BigSpike", "SpikeBlock" ] ] #"Misery Mire - Spike Room - Stalfos 1"
|
||||
- [ 0x00b3, 2, [ "Statue", "RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalLeft", "RollerHorizontalRight", "Beamos", "AntiFairyCircle", "BigSpike", "FirebarCW", "Bumper" ] ] #"Misery Mire - Spike Room - Beamos"
|
||||
- [ 0x00b3, 3, [ "AntiFairyCircle", "Bumper" ] ] #"Misery Mire - Spike Room - Yomo Medusa"
|
||||
- [ 0x00b3, 3, ["AntiFairyCircle", "Bumper" ]] #"Misery Mire - Spike Room - Yomo Medusa"
|
||||
- [ 0x00b3, 4, ["AntiFairyCircle", "Bumper"]]
|
||||
- [ 0x00b6, 7, [ "RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalLeft", "RollerHorizontalRight", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper" ] ] #"Turtle Rock - Tile Room - Zol 1"
|
||||
- [ 0x00b6, 8, [ "RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalLeft", "RollerHorizontalRight", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper" ] ] #"Turtle Rock - Tile Room - Zol 2"
|
||||
- [ 0x00ba, 1, [ "RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalLeft", "RollerHorizontalRight", "Beamos", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper" ] ] #"Eastern Palace - Dark Stalfos - Antifairy 1"
|
||||
@@ -347,6 +350,7 @@ UwGeneralDeny:
|
||||
- [ 0x00d8, 8, [ "Beamos", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper" ] ] #"Eastern Palace - Kill Room 1 - Red Eyegore"
|
||||
- [ 0x00d9, 1, [ "RollerHorizontalRight" ] ] #"Eastern Palace - Dodgeball - Green Eyegore 1"
|
||||
- [ 0x00db, 0, [ "Wizzrobe", "Statue" ] ] # Wizzrobes can't spawn on pots
|
||||
- [ 0x00db, 3, [ "Bumper" ] ] # Okay in vanilla
|
||||
- [ 0x00dc, 2, [ "AntiFairyCircle", "BigSpike", "Bumper" ] ]
|
||||
- [ 0x00dc, 9, [ "RollerVerticalDown", "RollerHorizontalLeft", "RollerHorizontalRight", "Beamos", "AntiFairyCircle", "BigSpike", "Bumper" ] ] #"Thieves' Town - Grand Room SE - Fire Snake 2"
|
||||
- [ 0x00df, 0, [ "RollerVerticalDown", "RollerHorizontalRight", "Beamos", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper" ] ] #"Paradox Cave - Top - Mini Moldorm 1"
|
||||
@@ -398,10 +402,10 @@ OwGeneralDeny:
|
||||
- [0x40, 13, ["Beamos", "Bumper", "BigSpike", "AntiFairyCircle", "Thief"]]
|
||||
- [0x40, 14, ["Beamos", "Bumper", "BigSpike", "AntiFairyCircle", "Thief"]]
|
||||
- [0x5e, 0, ["Gibo"]] # kiki eating Gibo
|
||||
- [0x5e, 1, ["Gibo"]] # kiki eating Gibo
|
||||
- [0x5e, 1, ["Gibo", "RollerVerticalUp", "RollerVerticalDown"]] # kiki eating Gibo
|
||||
- [0x5e, 2, ["Gibo"]] # kiki eating Gibo
|
||||
- [0x5e, 3, ["Gibo"]] # kiki eating Gibo
|
||||
- [0x5e, 4, ["RollerVerticalUp", "Gibo"]] # forbid that one roller for kiki pod, and the kiki eating Gibo
|
||||
- [0x5e, 4, ["RollerVerticalUp", "RollerVerticalDown", "Gibo"]] # forbid that one roller for kiki pod, and the kiki eating Gibo
|
||||
- [0x5e, 5, ["Gibo"]] # kiki eating Gibo
|
||||
- [0x5e, 6, ["Gibo"]] # kiki eating Gibo
|
||||
- [0x5e, 7, ["Gibo"]] # kiki eating Gibo
|
||||
@@ -435,94 +439,97 @@ UwEnemyDrop:
|
||||
- [0x00b0, 8, ["StalfosKnight", "Blob", "Stal", "Wizzrobe"]] # blocked, but Geldmen are probably okay
|
||||
# the following are not allowed at certain pits (or on conveyors near pits)
|
||||
# because they despawned or clipped away or immediately fell, etc
|
||||
- [0x003d, 9, ["HardhatBeetle", "Wizzrobe", "MiniHelmasaur", "BlueGuard", "GreenGuard", "RedSpearGuard",
|
||||
- [0x003d, 9, ["HardhatBeetle", "Wizzrobe", "MiniHelmasaur", "BlueGuard", "GreenGuard", "RedSpearGuard", "Hover",
|
||||
"BluesainBolt", "UsainBolt", "BlueArcher", "GreenBushGuard", "RedJavelinGuard", "RedBushGuard",
|
||||
"BombGuard", "GreenKnifeGuard", "Stal", "GreenMimic", "RedMimic", "StalfosKnight", "Geldman", "Blob"]]
|
||||
- [0x003d, 10, ["HardhatBeetle", "Wizzrobe", "MiniHelmasaur", "BlueGuard", "GreenGuard", "RedSpearGuard",
|
||||
- [0x003d, 10, ["HardhatBeetle", "Wizzrobe", "MiniHelmasaur", "BlueGuard", "GreenGuard", "RedSpearGuard", "Hover",
|
||||
"BluesainBolt", "UsainBolt", "BlueArcher", "GreenBushGuard", "RedJavelinGuard", "RedBushGuard",
|
||||
"BombGuard", "GreenKnifeGuard", "Stal", "GreenMimic", "RedMimic", "StalfosKnight", "Geldman", "Blob"]]
|
||||
- [0x0044, 0, ["HardhatBeetle", "Wizzrobe", "MiniHelmasaur", "BlueGuard", "GreenGuard", "RedSpearGuard",
|
||||
"BluesainBolt", "UsainBolt", "BlueArcher", "GreenBushGuard", "RedJavelinGuard", "RedBushGuard",
|
||||
"BombGuard", "GreenKnifeGuard", "Stal", "GreenMimic", "RedMimic"]]
|
||||
"BombGuard", "GreenKnifeGuard", "Stal", "GreenMimic", "RedMimic", "Hover"]]
|
||||
- [0x0044, 1, ["HardhatBeetle", "Wizzrobe", "MiniHelmasaur", "BlueGuard", "GreenGuard", "RedSpearGuard",
|
||||
"BluesainBolt", "UsainBolt", "BlueArcher", "GreenBushGuard", "RedJavelinGuard", "RedBushGuard",
|
||||
"BombGuard", "GreenKnifeGuard", "Stal", "GreenMimic", "RedMimic"]]
|
||||
"BombGuard", "GreenKnifeGuard", "Stal", "GreenMimic", "RedMimic", "Hover"]]
|
||||
- [0x0044, 2, ["HardhatBeetle", "Wizzrobe", "MiniHelmasaur", "BlueGuard", "GreenGuard", "RedSpearGuard",
|
||||
"BluesainBolt", "UsainBolt", "BlueArcher", "GreenBushGuard", "RedJavelinGuard", "RedBushGuard",
|
||||
"BombGuard", "GreenKnifeGuard", "Stal", "GreenMimic", "RedMimic"]]
|
||||
"BombGuard", "GreenKnifeGuard", "Stal", "GreenMimic", "RedMimic", "Hover"]]
|
||||
- [0x0044, 3, ["HardhatBeetle", "Wizzrobe", "MiniHelmasaur", "BlueGuard", "GreenGuard", "RedSpearGuard",
|
||||
"BluesainBolt", "UsainBolt", "BlueArcher", "GreenBushGuard", "RedJavelinGuard", "RedBushGuard",
|
||||
"BombGuard", "GreenKnifeGuard", "Stal", "GreenMimic", "RedMimic"]]
|
||||
"BombGuard", "GreenKnifeGuard", "Stal", "GreenMimic", "RedMimic", "Hover"]]
|
||||
- [0x0044, 4, ["HardhatBeetle", "Wizzrobe", "MiniHelmasaur", "BlueGuard", "GreenGuard", "RedSpearGuard",
|
||||
"BluesainBolt", "UsainBolt", "BlueArcher", "GreenBushGuard", "RedJavelinGuard", "RedBushGuard",
|
||||
"BombGuard", "GreenKnifeGuard", "Stal", "GreenMimic", "RedMimic"]]
|
||||
"BombGuard", "GreenKnifeGuard", "Stal", "GreenMimic", "RedMimic", "Hover"]]
|
||||
- [0x0044, 5, ["HardhatBeetle", "Wizzrobe", "MiniHelmasaur", "BlueGuard", "GreenGuard", "RedSpearGuard",
|
||||
"BluesainBolt", "UsainBolt", "BlueArcher", "GreenBushGuard", "RedJavelinGuard", "RedBushGuard",
|
||||
"BombGuard", "GreenKnifeGuard", "Stal", "GreenMimic", "RedMimic"]]
|
||||
"BombGuard", "GreenKnifeGuard", "Stal", "GreenMimic", "RedMimic", "Hover"]]
|
||||
- [0x0044, 6, ["HardhatBeetle", "Wizzrobe", "MiniHelmasaur", "BlueGuard", "GreenGuard", "RedSpearGuard",
|
||||
"BluesainBolt", "UsainBolt", "BlueArcher", "GreenBushGuard", "RedJavelinGuard", "RedBushGuard",
|
||||
"BombGuard", "GreenKnifeGuard", "Stal", "GreenMimic", "RedMimic"]]
|
||||
"BombGuard", "GreenKnifeGuard", "Stal", "GreenMimic", "RedMimic", "Hover"]]
|
||||
- [0x0044, 8, ["HardhatBeetle", "Wizzrobe", "MiniHelmasaur", "BlueGuard", "GreenGuard", "RedSpearGuard",
|
||||
"BluesainBolt", "UsainBolt", "BlueArcher", "GreenBushGuard", "RedJavelinGuard", "RedBushGuard",
|
||||
"BombGuard", "GreenKnifeGuard", "Stal", "GreenMimic", "RedMimic"]]
|
||||
"BombGuard", "GreenKnifeGuard", "Stal", "GreenMimic", "RedMimic", "Hover"]]
|
||||
- [0x0049, 10, ["HardhatBeetle", "Wizzrobe", "MiniHelmasaur", "BlueGuard", "GreenGuard", "RedSpearGuard",
|
||||
"BluesainBolt", "UsainBolt", "BlueArcher", "GreenBushGuard", "RedJavelinGuard", "RedBushGuard",
|
||||
"BombGuard", "GreenKnifeGuard", "Stal", "GreenMimic", "RedMimic"]]
|
||||
"BombGuard", "GreenKnifeGuard", "Stal", "GreenMimic", "RedMimic", "Hover"]]
|
||||
- [0x007b, 0, ["HardhatBeetle", "Wizzrobe", "MiniHelmasaur", "BlueGuard", "GreenGuard", "RedSpearGuard",
|
||||
"BluesainBolt", "UsainBolt", "BlueArcher", "GreenBushGuard", "RedJavelinGuard", "RedBushGuard",
|
||||
"BombGuard", "GreenKnifeGuard", "Stal", "GreenMimic", "RedMimic"]]
|
||||
"BombGuard", "GreenKnifeGuard", "Stal", "GreenMimic", "RedMimic", "Hover"]]
|
||||
- [0x007b, 1, ["HardhatBeetle", "Wizzrobe", "MiniHelmasaur", "BlueGuard", "GreenGuard", "RedSpearGuard",
|
||||
"BluesainBolt", "UsainBolt", "BlueArcher", "GreenBushGuard", "RedJavelinGuard", "RedBushGuard",
|
||||
"BombGuard", "GreenKnifeGuard", "Stal", "GreenMimic", "RedMimic"]]
|
||||
- [0x007f, 0, ["HardhatBeetle", "Wizzrobe", "MiniHelmasaur", "BlueGuard", "GreenGuard", "RedSpearGuard",
|
||||
"BombGuard", "GreenKnifeGuard", "Stal", "GreenMimic", "RedMimic", "Hover"]]
|
||||
- [0x007f, 0, ["HardhatBeetle", "Wizzrobe", "MiniHelmasaur", "BlueGuard", "GreenGuard", "RedSpearGuard", "Hover",
|
||||
"BluesainBolt", "UsainBolt", "BlueArcher", "GreenBushGuard", "RedJavelinGuard", "RedBushGuard",
|
||||
"BombGuard", "GreenKnifeGuard", "Stal", "GreenMimic", "RedMimic", "StalfosKnight", "Geldman", "Blob"]]
|
||||
- [0x007f, 1, ["HardhatBeetle", "Wizzrobe", "MiniHelmasaur", "BlueGuard", "GreenGuard", "RedSpearGuard",
|
||||
- [0x007f, 1, ["HardhatBeetle", "Wizzrobe", "MiniHelmasaur", "BlueGuard", "GreenGuard", "RedSpearGuard", "Hover",
|
||||
"BluesainBolt", "UsainBolt", "BlueArcher", "GreenBushGuard", "RedJavelinGuard", "RedBushGuard",
|
||||
"BombGuard", "GreenKnifeGuard", "Stal", "GreenMimic", "RedMimic", "StalfosKnight", "Geldman", "Blob"]]
|
||||
- [0x007f, 2, ["HardhatBeetle", "Wizzrobe", "MiniHelmasaur", "BlueGuard", "GreenGuard", "RedSpearGuard",
|
||||
- [0x007f, 2, ["HardhatBeetle", "Wizzrobe", "MiniHelmasaur", "BlueGuard", "GreenGuard", "RedSpearGuard", "Hover",
|
||||
"BluesainBolt", "UsainBolt", "BlueArcher", "GreenBushGuard", "RedJavelinGuard", "RedBushGuard",
|
||||
"BombGuard", "GreenKnifeGuard", "Stal", "GreenMimic", "RedMimic", "StalfosKnight", "Geldman", "Blob"]]
|
||||
- [0x007f, 3, ["HardhatBeetle", "Wizzrobe", "MiniHelmasaur", "BlueGuard", "GreenGuard", "RedSpearGuard",
|
||||
- [0x007f, 3, ["HardhatBeetle", "Wizzrobe", "MiniHelmasaur", "BlueGuard", "GreenGuard", "RedSpearGuard", "Hover",
|
||||
"BluesainBolt", "UsainBolt", "BlueArcher", "GreenBushGuard", "RedJavelinGuard", "RedBushGuard",
|
||||
"BombGuard", "GreenKnifeGuard", "Stal", "GreenMimic", "RedMimic", "StalfosKnight", "Geldman", "Blob"]]
|
||||
- [0x0095, 0, ["HardhatBeetle", "Wizzrobe", "MiniHelmasaur", "BlueGuard", "GreenGuard", "RedSpearGuard",
|
||||
"BluesainBolt", "UsainBolt", "BlueArcher", "GreenBushGuard", "RedJavelinGuard", "RedBushGuard",
|
||||
"BombGuard", "GreenKnifeGuard", "Stal", "GreenMimic", "RedMimic"]]
|
||||
- [0x0095, 1, ["HardhatBeetle", "Wizzrobe", "MiniHelmasaur", "BlueGuard", "GreenGuard", "RedSpearGuard",
|
||||
"BombGuard", "GreenKnifeGuard", "Stal", "GreenMimic", "RedMimic", "Hover"]]
|
||||
- [0x0095, 1, ["HardhatBeetle", "Wizzrobe", "MiniHelmasaur", "BlueGuard", "GreenGuard", "RedSpearGuard", "Hover",
|
||||
"BluesainBolt", "UsainBolt", "BlueArcher", "GreenBushGuard", "RedJavelinGuard", "RedBushGuard",
|
||||
"BombGuard", "GreenKnifeGuard", "Stal", "GreenMimic", "RedMimic", "StalfosKnight", "Geldman", "Blob"]]
|
||||
- [0x0095, 2, ["HardhatBeetle", "Wizzrobe", "MiniHelmasaur", "BlueGuard", "GreenGuard", "RedSpearGuard",
|
||||
- [0x0095, 2, ["HardhatBeetle", "Wizzrobe", "MiniHelmasaur", "BlueGuard", "GreenGuard", "RedSpearGuard", "Hover",
|
||||
"BluesainBolt", "UsainBolt", "BlueArcher", "GreenBushGuard", "RedJavelinGuard", "RedBushGuard",
|
||||
"BombGuard", "GreenKnifeGuard", "Stal", "GreenMimic", "RedMimic", "StalfosKnight", "Geldman", "Blob"]]
|
||||
- [0x0095, 3, ["HardhatBeetle", "Wizzrobe", "MiniHelmasaur", "BlueGuard", "GreenGuard", "RedSpearGuard",
|
||||
"BluesainBolt", "UsainBolt", "BlueArcher", "GreenBushGuard", "RedJavelinGuard", "RedBushGuard",
|
||||
"BombGuard", "GreenKnifeGuard", "Stal", "GreenMimic", "RedMimic"]]
|
||||
- [0x00b5, 0, ["HardhatBeetle", "Wizzrobe", "MiniHelmasaur", "BlueGuard", "GreenGuard", "RedSpearGuard",
|
||||
"BombGuard", "GreenKnifeGuard", "Stal", "GreenMimic", "RedMimic", "Hover"]]
|
||||
- [0x00af, 0, ["HardhatBeetle", "Wizzrobe", "MiniHelmasaur", "BlueGuard", "GreenGuard", "RedSpearGuard",
|
||||
"BluesainBolt", "UsainBolt", "BlueArcher", "GreenBushGuard", "RedJavelinGuard", "RedBushGuard",
|
||||
"BombGuard", "GreenKnifeGuard", "Stal", "GreenMimic", "RedMimic", "Hover"]]
|
||||
- [0x00b5, 0, ["HardhatBeetle", "Wizzrobe", "MiniHelmasaur", "BlueGuard", "GreenGuard", "RedSpearGuard", "Hover",
|
||||
"BluesainBolt", "UsainBolt", "BlueArcher", "GreenBushGuard", "RedJavelinGuard", "RedBushGuard",
|
||||
"BombGuard", "GreenKnifeGuard", "Stal", "GreenMimic", "RedMimic", "StalfosKnight", "Geldman", "Blob"]]
|
||||
- [0x00b5, 1, ["HardhatBeetle", "Wizzrobe", "MiniHelmasaur", "BlueGuard", "GreenGuard", "RedSpearGuard",
|
||||
- [0x00b5, 1, ["HardhatBeetle", "Wizzrobe", "MiniHelmasaur", "BlueGuard", "GreenGuard", "RedSpearGuard", "Hover",
|
||||
"BluesainBolt", "UsainBolt", "BlueArcher", "GreenBushGuard", "RedJavelinGuard", "RedBushGuard",
|
||||
"BombGuard", "GreenKnifeGuard", "Stal", "GreenMimic", "RedMimic", "StalfosKnight", "Geldman", "Blob"]]
|
||||
- [0x00b5, 2, ["HardhatBeetle", "Wizzrobe", "MiniHelmasaur", "BlueGuard", "GreenGuard", "RedSpearGuard",
|
||||
- [0x00b5, 2, ["HardhatBeetle", "Wizzrobe", "MiniHelmasaur", "BlueGuard", "GreenGuard", "RedSpearGuard", "Hover",
|
||||
"BluesainBolt", "UsainBolt", "BlueArcher", "GreenBushGuard", "RedJavelinGuard", "RedBushGuard",
|
||||
"BombGuard", "GreenKnifeGuard", "Stal", "GreenMimic", "RedMimic", "StalfosKnight", "Geldman", "Blob"]]
|
||||
- [0x00c6, 2, ["HardhatBeetle", "Wizzrobe", "MiniHelmasaur", "BlueGuard", "GreenGuard", "RedSpearGuard",
|
||||
- [0x00c6, 2, ["HardhatBeetle", "Wizzrobe", "MiniHelmasaur", "BlueGuard", "GreenGuard", "RedSpearGuard", "Hover",
|
||||
"BluesainBolt", "UsainBolt", "BlueArcher", "GreenBushGuard", "RedJavelinGuard", "RedBushGuard",
|
||||
"BombGuard", "GreenKnifeGuard", "Stal", "GreenMimic", "RedMimic", "StalfosKnight", "Geldman", "Blob"]]
|
||||
- [0x00c6, 3, ["HardhatBeetle", "Wizzrobe", "MiniHelmasaur", "BlueGuard", "GreenGuard", "RedSpearGuard",
|
||||
- [0x00c6, 3, ["HardhatBeetle", "Wizzrobe", "MiniHelmasaur", "BlueGuard", "GreenGuard", "RedSpearGuard", "Hover",
|
||||
"BluesainBolt", "UsainBolt", "BlueArcher", "GreenBushGuard", "RedJavelinGuard", "RedBushGuard",
|
||||
"BombGuard", "GreenKnifeGuard", "Stal", "GreenMimic", "RedMimic", "StalfosKnight", "Geldman", "Blob"]]
|
||||
- [0x00c6, 4, ["HardhatBeetle", "Wizzrobe", "MiniHelmasaur", "BlueGuard", "GreenGuard", "RedSpearGuard",
|
||||
- [0x00c6, 4, ["HardhatBeetle", "Wizzrobe", "MiniHelmasaur", "BlueGuard", "GreenGuard", "RedSpearGuard", "Hover",
|
||||
"BluesainBolt", "UsainBolt", "BlueArcher", "GreenBushGuard", "RedJavelinGuard", "RedBushGuard",
|
||||
"BombGuard", "GreenKnifeGuard", "Stal", "GreenMimic", "RedMimic", "StalfosKnight", "Geldman", "Blob"]]
|
||||
- [0x00c6, 5, ["HardhatBeetle", "Wizzrobe", "MiniHelmasaur", "BlueGuard", "GreenGuard", "RedSpearGuard",
|
||||
- [0x00c6, 5, ["HardhatBeetle", "Wizzrobe", "MiniHelmasaur", "BlueGuard", "GreenGuard", "RedSpearGuard", "Hover",
|
||||
"BluesainBolt", "UsainBolt", "BlueArcher", "GreenBushGuard", "RedJavelinGuard", "RedBushGuard",
|
||||
"BombGuard", "GreenKnifeGuard", "Bumper", "Stal", "GreenMimic", "RedMimic", "StalfosKnight", "Geldman", "Blob"]]
|
||||
- [0x00c6, 6, ["HardhatBeetle", "Wizzrobe", "MiniHelmasaur", "BlueGuard", "GreenGuard", "RedSpearGuard",
|
||||
- [0x00c6, 6, ["HardhatBeetle", "Wizzrobe", "MiniHelmasaur", "BlueGuard", "GreenGuard", "RedSpearGuard", "Hover",
|
||||
"BluesainBolt", "UsainBolt", "BlueArcher", "GreenBushGuard", "RedJavelinGuard", "RedBushGuard",
|
||||
"BombGuard", "GreenKnifeGuard", "Stal", "GreenMimic", "RedMimic", "StalfosKnight", "Geldman", "Blob"]]
|
||||
- [0x00e6, 0, ["HardhatBeetle", "Wizzrobe", "MiniHelmasaur", "BlueGuard", "GreenGuard", "RedSpearGuard",
|
||||
- [0x00e6, 0, ["HardhatBeetle", "Wizzrobe", "MiniHelmasaur", "BlueGuard", "GreenGuard", "RedSpearGuard", "Hover",
|
||||
"BluesainBolt", "UsainBolt", "BlueArcher", "GreenBushGuard", "RedJavelinGuard", "RedBushGuard",
|
||||
"BombGuard", "GreenKnifeGuard", "Stal", "GreenMimic", "RedMimic", "StalfosKnight", "Geldman", "Blob"]]
|
||||
# wizzrobe despawn issues - on pots/blocks - too close to some object
|
||||
@@ -577,7 +584,6 @@ UwEnemyDrop:
|
||||
- [0x009f, 5, ["Wizzrobe", "Stal"]]
|
||||
- [0x00a1, 1, ["Wizzrobe"]]
|
||||
- [0x00aa, 5, ["Wizzrobe"]]
|
||||
- [0x00af, 0, ["Wizzrobe", "Stal"]]
|
||||
- [0x00b0, 1, ["Wizzrobe"]]
|
||||
- [0x00b0, 2, ["Wizzrobe"]]
|
||||
- [0x00b2, 4, ["Wizzrobe"]]
|
||||
|
||||
206
source/enemizer/enemy_weight.yaml
Normal file
206
source/enemizer/enemy_weight.yaml
Normal file
@@ -0,0 +1,206 @@
|
||||
UW: # Total 94431
|
||||
AntiFairy: 40 # 1.82885% raw:1727 15.28319%
|
||||
AntiFairyCircle: 40 # 1.82885% raw:1727 15.28319%
|
||||
ArmosStatue: 186 # 0.53796% raw:508 4.49558%
|
||||
Babasu: 80 # 1.15428% raw:1090 9.64602%
|
||||
BallNChain: 163 # 0.61526% raw:581 5.14159%
|
||||
Beamos: 155 # 0.64703% raw:611 5.40708%
|
||||
BigSpike: 40 # 1.82885% raw:1727 15.28319%
|
||||
Blob: 87 # 1.15428% raw:1090 9.64602%
|
||||
BlueArcher: 325 # 0.30816% raw:291 2.57522%
|
||||
BlueBari: 49 # 2.02688% raw:1914 16.93805%
|
||||
BlueGuard: 44 # 2.28527% raw:2158 19.09735%
|
||||
BlueZazak: 294 # 0.33993% raw:321 2.84071%
|
||||
BlueZirro: 180 # 0.55702% raw:526 4.65487%
|
||||
BluesainBolt: 150 # 0.66821% raw:631 5.58407%
|
||||
BombGuard: 163 # 0.61526% raw:581 5.14159%
|
||||
Bumper: 55 # 1.82885% raw:1727 15.28319%
|
||||
BunnyBeam: 19 # 5.40077% raw:5100 45.13274%
|
||||
Buzzblob: 123 # 0.81223% raw:767 6.78761%
|
||||
CannonTrooper: 163 # 0.61526% raw:581 5.14159%
|
||||
Chainchomp: 238 # 0.42041% raw:397 3.51327%
|
||||
Crab: 204 # 0.48925% raw:462 4.08850%
|
||||
CricketRat: 212 # 0.47230% raw:446 3.94690%
|
||||
Cucco: 120 # 0.54325% raw:513 4.53982%
|
||||
Deadrock: 186 # 0.53796% raw:508 4.49558%
|
||||
Debirando: 154 # 0.65127% raw:615 5.44248%
|
||||
DebirandoPit: 154 # 0.65127% raw:615 5.44248%
|
||||
Faerie: 19
|
||||
FakeMasterSword: 120 # 0.81223% raw:767 6.78761%
|
||||
FireballZora: 165 # 0.60679% raw:573 5.07080%
|
||||
FirebarCCW: 49 # 2.02688% raw:1914 16.93805%
|
||||
FirebarCW: 49 # 2.02688% raw:1914 16.93805%
|
||||
Firesnake: 49 # 2.02688% raw:1914 16.93805%
|
||||
FloatingSkull: 49 # 2.02688% raw:1914 16.93805%
|
||||
FloppingFish: 30 # 5.40077% raw:5100 45.13274%
|
||||
Freezor: 454 # 0.22027% raw:208 1.84071%
|
||||
Geldman: 445 # 0.22450% raw:212 1.87611%
|
||||
Gibdo: 150 # 0.40453% raw:382 3.38053%
|
||||
Gibo: 294 # 0.33993% raw:321 2.84071%
|
||||
GreenBushGuard: 325 # 0.30816% raw:291 2.57522%
|
||||
GreenEyegoreMimic: 175 # 0.57291% raw:541 4.78761%
|
||||
GreenMimic: 175 # 0.57291% raw:541 4.78761%
|
||||
GreenGuard: 55 # 1.80237% raw:1702 15.06195%
|
||||
GreenKnifeGuard: 621 # 0.16096% raw:152 1.34513%
|
||||
GreenZirro: 180 # 0.55702% raw:526 4.65487%
|
||||
HardhatBeetle: 109 # 0.91495% raw:864 7.64602%
|
||||
Hinox: 140 # 0.71269% raw:673 5.95575%
|
||||
Hoarder: 123 # 0.81223% raw:767 6.78761%
|
||||
Hoarder2: 123 # 0.81223% raw:767 6.78761%
|
||||
Hover: 150 # 0.42147% raw:398 3.52212%
|
||||
Keese: 212 # 0.47230% raw:446 3.94690%
|
||||
Kodongo: 463 # 0.21603% raw:204 1.80531%
|
||||
Kyameron: 237 # 0.42147% raw:398 3.52212%
|
||||
Landmine: 19 # 5.40077% raw:5100 45.13274%
|
||||
Leever: 154 # 0.65127% raw:615 5.44248%
|
||||
Lynel: 400 # 0.17897% raw:169 1.49558%
|
||||
MiniHelmasaur: 109 # 0.91495% raw:864 7.64602%
|
||||
MiniMoldorm: 109 # 0.91495% raw:864 7.64602%
|
||||
Moblin: 367 # 0.27216% raw:257 2.27434%
|
||||
Octoballoon: 204 # 0.48925% raw:462 4.08850%
|
||||
Octorok: 165 # 0.60679% raw:573 5.07080%
|
||||
Octorok4Way: 204 # 0.48925% raw:462 4.08850%
|
||||
Pengator: 300 # 0.22027% raw:208 1.84071%
|
||||
Pikit: 180 # 0.55702% raw:526 4.65487%
|
||||
Poe: 284 # 0.35264% raw:333 2.94690%
|
||||
Pokey: 238 # 0.42041% raw:397 3.51327%
|
||||
Popo: 155 # 0.64703% raw:611 5.40708%
|
||||
Popo2: 155 # 0.64703% raw:611 5.40708%
|
||||
Raven: 94 # 1.06109% raw:1002 8.86726%
|
||||
RedBari: 49 # 2.02688% raw:1914 16.93805%
|
||||
RedBushGuard: 163 # 0.61526% raw:581 5.14159%
|
||||
RedEyegoreMimic: 175 # 0.57291% raw:541 4.78761%
|
||||
RedMimic: 175 # 0.57291% raw:541 4.78761%
|
||||
RedJavelinGuard: 163 # 0.61526% raw:581 5.14159%
|
||||
RedSpearGuard: 44 # 2.28527% raw:2158 19.09735%
|
||||
RedZazak: 294 # 0.33993% raw:321 2.84071%
|
||||
RollerHorizontalLeft: 238 # 0.42041% raw:397 3.51327%
|
||||
RollerHorizontalRight: 238 # 0.42041% raw:397 3.51327%
|
||||
RollerVerticalDown: 238 # 0.42041% raw:397 3.51327%
|
||||
RollerVerticalUp: 238 # 0.42041% raw:397 3.51327%
|
||||
Ropa: 140 # 0.71269% raw:673 5.95575%
|
||||
Sluggula: 360 # 0.27745% raw:262 2.31858%
|
||||
Snake: 212 # 0.47230% raw:446 3.94690%
|
||||
Snapdragon: 562 # 0.17791% raw:168 1.48673%
|
||||
SparkCCW: 49 # 2.02688% raw:1914 16.93805%
|
||||
SparkCW: 49 # 2.02688% raw:1914 16.93805%
|
||||
SpikeBlock: 55 # 1.82885% raw:1727 15.28319%
|
||||
Stal: 19 # 5.40077% raw:5100 45.13274%
|
||||
Stalfos: 49 # 2.02688% raw:1914 16.93805%
|
||||
StalfosKnight: 87 # 1.15428% raw:1090 9.64602%
|
||||
Statue: 30 # 1.82885% raw:1727 15.28319%
|
||||
Swamola: 402 # 0.24886% raw:235 2.07965%
|
||||
Tektite: 186 # 0.53796% raw:508 4.49558%
|
||||
Terrorpin: 463 # 0.21603% raw:204 1.80531%
|
||||
Thief: 100 # 0.60997% raw:576 5.09735%
|
||||
Toppo: 123 # 0.81223% raw:767 6.78761%
|
||||
UsainBolt: 44 # 2.28527% raw:2158 19.09735%
|
||||
Vulture: 445 # 0.22450% raw:212 1.87611%
|
||||
Wallmaster: 247 # 0.40453% raw:382 3.38053%
|
||||
Wizzrobe: 306 # 0.32722% raw:309 2.73451%
|
||||
# YellowStalfos: 49
|
||||
Zora: 609 # 0.16414% raw:155 1.37168%
|
||||
Zoro: 80 # 1.15428% raw:1090 9.64602%
|
||||
OW: # Total 117724
|
||||
AntiFairy: 60 # 0.97346% raw:1146 10.14159%
|
||||
AntiFairyCircle: 60 # 0.97346% raw:1146 10.14159%
|
||||
ArmosStatue: 144 # 0.69570% raw:819 7.24779%
|
||||
Babasu: 100 # 0.84605% raw:996 8.81416%
|
||||
BallNChain: 121 # 0.82651% raw:973 8.61062%
|
||||
Beamos: 184 # 0.54364% raw:640 5.66372%
|
||||
BigSpike: 70 # 0.97346% raw:1146 10.14159%
|
||||
Blob: 118 # 0.84605% raw:996 8.81416%
|
||||
BlueArcher: 291 # 0.34403% raw:405 3.58407%
|
||||
BlueBari: 47 # 2.11767% raw:2493 22.06195%
|
||||
BlueGuard: 39 # 2.56617% raw:3021 26.73451%
|
||||
BlueZazak: 247 # 0.40519% raw:477 4.22124%
|
||||
BlueZirro: 158 # 0.63369% raw:746 6.60177%
|
||||
BluesainBolt: 111 # 0.90381% raw:1064 9.41593%
|
||||
BombGuard: 121 # 0.82651% raw:973 8.61062%
|
||||
Bumper: 103 # 0.97346% raw:1146 10.14159%
|
||||
BunnyBeam: 19 # 5.26656% raw:6200 54.86726%
|
||||
Buzzblob: 86 # 1.15609% raw:1361 12.04425%
|
||||
CannonTrooper: 121 # 0.82651% raw:973 8.61062%
|
||||
Chainchomp: 226 # 0.44341% raw:522 4.61947%
|
||||
Crab: 163 # 0.61500% raw:724 6.40708%
|
||||
CricketRat: 236 # 0.42387% raw:499 4.41593%
|
||||
Cucco: 140 # 0.60396% raw:711 6.29204%
|
||||
Deadrock: 144 # 0.69570% raw:819 7.24779%
|
||||
Debirando: 164 # 0.60905% raw:717 6.34513%
|
||||
DebirandoPit: 164 # 0.60905% raw:717 6.34513%
|
||||
Faerie: 19
|
||||
FakeMasterSword: 120 # 1.15609% raw:1361 12.04425%
|
||||
FireballZora: 119 # 0.84350% raw:993 8.78761%
|
||||
FirebarCCW: 47 # 2.11767% raw:2493 22.06195%
|
||||
FirebarCW: 47 # 2.11767% raw:2493 22.06195%
|
||||
Firesnake: 47 # 2.11767% raw:2493 22.06195%
|
||||
FloatingSkull: 47 # 2.11767% raw:2493 22.06195%
|
||||
FloppingFish: 30 # 5.26656% raw:6200 54.86726%
|
||||
Freezor: 692 # 0.14441% raw:170 1.50442%
|
||||
Geldman: 229 # 0.43746% raw:515 4.55752%
|
||||
Gibdo: 300 # 0.15545% raw:183 1.61947%
|
||||
Gibo: 247 # 0.40519% raw:477 4.22124%
|
||||
GreenBushGuard: 291 # 0.34403% raw:405 3.58407%
|
||||
GreenEyegoreMimic: 171 # 0.58527% raw:689 6.09735%
|
||||
GreenMimic: 171 # 0.58527% raw:689 6.09735%
|
||||
GreenGuard: 48 # 2.06330% raw:2429 21.49558%
|
||||
GreenKnifeGuard: 589 # 0.16989% raw:200 1.76991%
|
||||
GreenZirro: 158 # 0.63369% raw:746 6.60177%
|
||||
HardhatBeetle: 113 # 0.88682% raw:1044 9.23894%
|
||||
Hinox: 123 # 0.81462% raw:959 8.48673%
|
||||
Hoarder: 86 # 1.15609% raw:1361 12.04425%
|
||||
Hoarder2: 86 # 1.15609% raw:1361 12.04425%
|
||||
Hover: 200 # 0.32449% raw:382 3.38053%
|
||||
Keese: 236 # 0.42387% raw:499 4.41593%
|
||||
Kodongo: 346 # 0.28881% raw:340 3.00885%
|
||||
Kyameron: 308 # 0.32449% raw:382 3.38053%
|
||||
Landmine: 19 # 5.26656% raw:6200 54.86726%
|
||||
Leever: 164 # 0.60905% raw:717 6.34513%
|
||||
Lynel: 325 # 0.30750% raw:362 3.20354%
|
||||
MiniHelmasaur: 113 # 0.88682% raw:1044 9.23894%
|
||||
MiniMoldorm: 113 # 0.88682% raw:1044 9.23894%
|
||||
Moblin: 303 # 0.33043% raw:389 3.44248%
|
||||
Octoballoon: 163 # 0.61500% raw:724 6.40708%
|
||||
Octorok: 119 # 0.84350% raw:993 8.78761%
|
||||
Octorok4Way: 163 # 0.61500% raw:724 6.40708%
|
||||
Pengator: 400 # 0.14441% raw:170 1.50442%
|
||||
Pikit: 158 # 0.63369% raw:746 6.60177%
|
||||
Poe: 202 # 0.49608% raw:584 5.16814%
|
||||
Pokey: 226 # 0.44341% raw:522 4.61947%
|
||||
Popo: 184 # 0.54364% raw:640 5.66372%
|
||||
Popo2: 184 # 0.54364% raw:640 5.66372%
|
||||
Raven: 65 # 1.53325% raw:1805 15.97345%
|
||||
RedBari: 47 # 2.11767% raw:2493 22.06195%
|
||||
RedBushGuard: 121 # 0.82651% raw:973 8.61062%
|
||||
RedEyegoreMimic: 171 # 0.58527% raw:689 6.09735%
|
||||
RedMimic: 171 # 0.58527% raw:689 6.09735%
|
||||
RedJavelinGuard: 121 # 0.82651% raw:973 8.61062%
|
||||
RedSpearGuard: 39 # 2.56617% raw:3021 26.73451%
|
||||
RedZazak: 247 # 0.40519% raw:477 4.22124%
|
||||
RollerHorizontalLeft: 226 # 0.44341% raw:522 4.61947%
|
||||
RollerHorizontalRight: 226 # 0.44341% raw:522 4.61947%
|
||||
RollerVerticalDown: 226 # 0.44341% raw:522 4.61947%
|
||||
RollerVerticalUp: 226 # 0.44341% raw:522 4.61947%
|
||||
Ropa: 123 # 0.81462% raw:959 8.48673%
|
||||
Sluggula: 443 # 0.22595% raw:266 2.35398%
|
||||
Snake: 236 # 0.42387% raw:499 4.41593%
|
||||
Snapdragon: 526 # 0.19028% raw:224 1.98230%
|
||||
SparkCCW: 47 # 2.11767% raw:2493 22.06195%
|
||||
SparkCW: 47 # 2.11767% raw:2493 22.06195%
|
||||
SpikeBlock: 103 # 0.97346% raw:1146 10.14159%
|
||||
Stal: 19 # 5.26656% raw:6200 54.86726%
|
||||
Stalfos: 47 # 2.11767% raw:2493 22.06195%
|
||||
StalfosKnight: 118 # 0.84605% raw:996 8.81416%
|
||||
Statue: 60 # 0.97346% raw:1146 10.14159%
|
||||
Swamola: 265 # 0.37715% raw:444 3.92920%
|
||||
Tektite: 144 # 0.69570% raw:819 7.24779%
|
||||
Terrorpin: 346 # 0.28881% raw:340 3.00885%
|
||||
Thief: 100 # 0.39244% raw:462 4.08850%
|
||||
Toppo: 86 # 1.15609% raw:1361 12.04425%
|
||||
UsainBolt: 39 # 2.56617% raw:3021 26.73451%
|
||||
Vulture: 229 # 0.43746% raw:515 4.55752%
|
||||
Wallmaster: 643 # 0.15545% raw:183 1.61947%
|
||||
Wizzrobe: 345 # 0.28966% raw:341 3.01770%
|
||||
# YellowStalfos: 47
|
||||
Zora: 558 # 0.17923% raw:211 1.86726%
|
||||
Zoro: 100 # 0.84605% raw:996 8.81416%
|
||||
168
source/enemizer/sheet_weight.yaml
Normal file
168
source/enemizer/sheet_weight.yaml
Normal file
@@ -0,0 +1,168 @@
|
||||
SheetChoices:
|
||||
# Complex
|
||||
- slots: [0, 1]
|
||||
assignments:
|
||||
0: 0x46
|
||||
1: 0xd
|
||||
weight: .5 # BluesainBolt(1/2) - 2 types
|
||||
- slots: [0, 1]
|
||||
assignments:
|
||||
0: 0x46
|
||||
1: 0x49
|
||||
weight: 5.5 # CannonTrooper, BallNChain, RedBushGuard, RedJavelinGuard, BombGuard, BluesainBolt(1/2)
|
||||
- slots: [0, 1]
|
||||
assignments:
|
||||
0: 0x48
|
||||
1: 0x49
|
||||
weight: 2 # GreenBushGuard, BlueArcher
|
||||
- slots: [1, 2]
|
||||
assignments:
|
||||
1: 0x49
|
||||
2: 0x13
|
||||
weight: 1 # GreenKnifeGuard
|
||||
- slots: [0, 2]
|
||||
assignments:
|
||||
0: 0x16
|
||||
2: 0x17
|
||||
weight: 1 # Snapdragon
|
||||
- slots: [2, 3]
|
||||
assignments:
|
||||
2: 0xc
|
||||
3: 0x44
|
||||
weight: 1 # Zora (walking)
|
||||
|
||||
# Slot 0 (21 enemy types require slot 0)
|
||||
- slots: [0]
|
||||
assignments:
|
||||
0: [0xe, 0x15]
|
||||
weight: 1 # Thief
|
||||
- slots: [0]
|
||||
assignments:
|
||||
0: 0x16
|
||||
weight: 2 # Ropa, Hinox
|
||||
- slots: [0]
|
||||
assignments:
|
||||
0: 0x1f
|
||||
weight: 7 # Sparks, Firebars, FloatingSkull, RedBari, BlueBari, Firesnake, Stalfos, ~~YellowStalfos~~
|
||||
- slots: [0]
|
||||
assignments:
|
||||
0: 0x2f
|
||||
weight: 2 # Debirandos, Leever
|
||||
|
||||
# Slot 1 (24 enemy types require slot 1)
|
||||
- slots: [1]
|
||||
assignments:
|
||||
1: 0x1e
|
||||
weight: 3 # MiniMoldorm, MiniHelmasaur, Hardhat
|
||||
- slots: [1]
|
||||
assignments:
|
||||
1: 0x20
|
||||
weight: 3 # StalfosKnight, Blob, Babasus
|
||||
- slots: [1]
|
||||
assignments:
|
||||
1: 0x23
|
||||
weight: 1 # Wallmaster
|
||||
- slots: [1]
|
||||
assignments:
|
||||
1: 0x2c
|
||||
weight: 4 # Beamos, Popos, Mimics (2)
|
||||
- slots: [1]
|
||||
assignments:
|
||||
1: 0x49
|
||||
weight: 2.5 # GreenGuard, RedSpearGuard, BlueGuard, UsainBolt (1/2)
|
||||
- slots: [1]
|
||||
assignments:
|
||||
1: 0xd
|
||||
weight: 1.5 # RedSpearGuard, BlueGuard, UsainBolt (1/2)
|
||||
|
||||
# Slot 2 (29 enemy types require slot 2)
|
||||
- slots: [2]
|
||||
assignments:
|
||||
2: 0xc
|
||||
weight: 3 # Crab, Octoballon, FireballZora(1/2), Octorocks(1/2) (4Way is 0xC only?)
|
||||
- slots: [2]
|
||||
assignments:
|
||||
2: 0x12
|
||||
weight: 2 # Vulture, Geldman
|
||||
- slots: [2]
|
||||
assignments:
|
||||
2: 0x17
|
||||
weight: 1 # Moblin
|
||||
- slots: [2]
|
||||
assignments:
|
||||
2: 0x18
|
||||
weight: 1 # FireballZora(1/2) (note: immersible only), Octoroks(1/2)
|
||||
- slots: [2]
|
||||
assignments:
|
||||
2: [0x1c, 0x24]
|
||||
weight: 3 # Keese, CricketRat, Snake
|
||||
- slots: [2]
|
||||
assignments:
|
||||
2: 0x22
|
||||
weight: 2 # Kyameron (note: immersible only), Hover
|
||||
- slots: [2]
|
||||
assignments:
|
||||
2: 0x23
|
||||
weight: 1 # Gibdo
|
||||
- slots: [2]
|
||||
assignments:
|
||||
2: 0x25
|
||||
weight: 1.5 # Sluggula, Wizzrobe (half)
|
||||
- slots: [2]
|
||||
assignments:
|
||||
2: 0x26
|
||||
weight: 1 # Pengator
|
||||
- slots: [2]
|
||||
assignments:
|
||||
2: 0x27
|
||||
weight: 3 # Rollers4, Chainchomp, Pokey
|
||||
- slots: [2]
|
||||
assignments:
|
||||
2: 0x28
|
||||
weight: 3 # Gibo, BlueZazak, RedZazak
|
||||
- slots: [2]
|
||||
assignments:
|
||||
2: 0x29
|
||||
weight: .5 # Wizzrobe (half)
|
||||
- slots: [2]
|
||||
assignments:
|
||||
2: 0x2a
|
||||
weight: 2 # Kodongo, Terrorpin
|
||||
- slots: [2]
|
||||
assignments:
|
||||
2: 0x2e
|
||||
weight: 2 # GreenEyeGoreMimic, RedEyeGoreMimic (Eyegores only)
|
||||
|
||||
# Slot 3 (21 enemy types require slot 3)
|
||||
- slots: [3]
|
||||
assignments:
|
||||
3: 0x10
|
||||
weight: 3 # Deadrock, Tektite, ArmosStatue
|
||||
- slots: [3]
|
||||
assignments:
|
||||
3: 0x11
|
||||
weight: 4.5 # FakeMasterSword, Hoarder, Buzzblob, Toppo, Raven(1/2)
|
||||
- slots: [3]
|
||||
assignments:
|
||||
3: 0x14
|
||||
weight: 1 # Lynel
|
||||
- slots: [3]
|
||||
assignments:
|
||||
3: 0x15
|
||||
weight: 1.5 # Poe, Cucco(1/2)
|
||||
- slots: [3]
|
||||
assignments:
|
||||
3: 0x19
|
||||
weight: 1.5 # Swamola, Raven(1/2)
|
||||
- slots: [3]
|
||||
assignments:
|
||||
3: 0x1b
|
||||
weight: 3 # GreenZirro, BlueZirro, Pikit
|
||||
- slots: [3]
|
||||
assignments:
|
||||
3: [0x50]
|
||||
weight: .5 # Cucco(1/2)
|
||||
- slots: [3]
|
||||
assignments:
|
||||
3: [0x52, 0x53]
|
||||
weight: 5 # SpikeBlock, Bumper, BigSpike, AntiFairy, Statue (AntiFairyCircle?)
|
||||
@@ -1,4 +1,4 @@
|
||||
from tkinter import ttk, messagebox, StringVar, Button, Entry, Frame, Label, E, W, LEFT, RIGHT, X
|
||||
from tkinter import ttk, messagebox, StringVar, Button, Entry, Frame, Label, LEFT, RIGHT, X
|
||||
from argparse import Namespace
|
||||
import logging
|
||||
import os
|
||||
@@ -79,65 +79,67 @@ def bottom_frame(self, parent, args=None):
|
||||
|
||||
guiargs = create_guiargs(parent)
|
||||
# get default values for missing parameters
|
||||
for k,v in vars(parse_cli(['--multi', str(guiargs.multi)])).items():
|
||||
cliargs = ['--multi', str(guiargs.multi)]
|
||||
if hasattr(guiargs, 'customizer'):
|
||||
cliargs.extend(['--customizer', str(guiargs.customizer)])
|
||||
for k,v in vars(parse_cli(cliargs)).items():
|
||||
if k not in vars(guiargs):
|
||||
setattr(guiargs, k, v)
|
||||
elif type(v) is dict: # use same settings for every player
|
||||
setattr(guiargs, k, {player: getattr(guiargs, k) for player in range(1, guiargs.multi + 1)})
|
||||
setattr(guiargs, k, {player: getattr(guiargs, k) for player in range(1, len(v) + 1)})
|
||||
argsDump = vars(guiargs)
|
||||
hasEnemizer = "enemizercli" in argsDump and os.path.isfile(argsDump["enemizercli"])
|
||||
needEnemizer = False
|
||||
if hasEnemizer:
|
||||
falsey = ["none", "default", False, 0]
|
||||
for enemizerOption in ["shuffleenemies", "enemy_damage", "shufflebosses", "enemy_health"]:
|
||||
if enemizerOption in argsDump:
|
||||
if isinstance(argsDump[enemizerOption], dict):
|
||||
for playerID,playerSetting in argsDump[enemizerOption].items():
|
||||
if not playerSetting in falsey:
|
||||
needEnemizer = True
|
||||
elif not argsDump[enemizerOption] in falsey:
|
||||
needEnemizer = True
|
||||
seeds = []
|
||||
if not needEnemizer or (needEnemizer and hasEnemizer):
|
||||
try:
|
||||
if guiargs.count is not None and guiargs.seed:
|
||||
seed = guiargs.seed
|
||||
for _ in range(guiargs.count):
|
||||
seeds.append(seed)
|
||||
main(seed=seed, args=guiargs, fish=parent.fish)
|
||||
seed = random.randint(0, 999999999)
|
||||
else:
|
||||
if guiargs.seed:
|
||||
seeds.append(guiargs.seed)
|
||||
else:
|
||||
random.seed(None)
|
||||
guiargs.seed = random.randint(0, 999999999)
|
||||
seeds.append(guiargs.seed)
|
||||
main(seed=guiargs.seed, args=guiargs, fish=parent.fish)
|
||||
except (FillError, EnemizerError, Exception, RuntimeError) as e:
|
||||
logging.exception(e)
|
||||
messagebox.showerror(title="Error while creating seed", message=str(e))
|
||||
else:
|
||||
YES = parent.fish.translate("cli","cli","yes")
|
||||
NO = parent.fish.translate("cli","cli","no")
|
||||
successMsg = ""
|
||||
made = {}
|
||||
for k in [ "rom", "playthrough", "spoiler" ]:
|
||||
made[k] = parent.fish.translate("cli","cli","made." + k)
|
||||
made["enemizer"] = parent.fish.translate("cli","cli","used.enemizer")
|
||||
for k in made:
|
||||
v = made[k]
|
||||
pattern = "([\w]+)(:)([\s]+)(.*)"
|
||||
m = re.search(pattern,made[k])
|
||||
made[k] = m.group(1) + m.group(2) + ' ' + m.group(4)
|
||||
successMsg += (made["rom"] % (YES if (guiargs.create_rom) else NO)) + "\n"
|
||||
successMsg += (made["playthrough"] % (YES if (guiargs.calc_playthrough) else NO)) + "\n"
|
||||
successMsg += (made["spoiler"] % (YES if (not guiargs.jsonout and guiargs.create_spoiler) else NO)) + "\n"
|
||||
successMsg += (made["enemizer"] % (YES if needEnemizer else NO)) + "\n"
|
||||
# FIXME: English
|
||||
successMsg += ("Seed%s: %s" % ('s' if len(seeds) > 1 else "", ','.join(str(x) for x in seeds)))
|
||||
|
||||
messagebox.showinfo(title="Success", message=successMsg)
|
||||
needEnemizer = False
|
||||
falsey = ["none", "default", False, 0]
|
||||
for enemizerOption in ["shuffleenemies", "enemy_damage", "shufflebosses", "enemy_health"]:
|
||||
if enemizerOption in argsDump:
|
||||
if isinstance(argsDump[enemizerOption], dict):
|
||||
for playerID,playerSetting in argsDump[enemizerOption].items():
|
||||
if not playerSetting in falsey:
|
||||
needEnemizer = True
|
||||
elif not argsDump[enemizerOption] in falsey:
|
||||
needEnemizer = True
|
||||
seeds = []
|
||||
|
||||
try:
|
||||
if guiargs.count is not None and guiargs.seed:
|
||||
seed = guiargs.seed
|
||||
for _ in range(guiargs.count):
|
||||
seeds.append(seed)
|
||||
main(seed=seed, args=guiargs, fish=parent.fish)
|
||||
seed = random.randint(0, 999999999)
|
||||
else:
|
||||
if guiargs.seed:
|
||||
seeds.append(guiargs.seed)
|
||||
else:
|
||||
random.seed(None)
|
||||
guiargs.seed = random.randint(0, 999999999)
|
||||
seeds.append(guiargs.seed)
|
||||
main(seed=guiargs.seed, args=guiargs, fish=parent.fish)
|
||||
except (FillError, EnemizerError, Exception, RuntimeError) as e:
|
||||
logging.exception(e)
|
||||
messagebox.showerror(title="Error while creating seed", message=str(e))
|
||||
else:
|
||||
YES = parent.fish.translate("cli","cli","yes")
|
||||
NO = parent.fish.translate("cli","cli","no")
|
||||
successMsg = ""
|
||||
made = {}
|
||||
for k in [ "rom", "playthrough", "spoiler" ]:
|
||||
made[k] = parent.fish.translate("cli","cli","made." + k)
|
||||
made["enemizer"] = parent.fish.translate("cli","cli","used.enemizer")
|
||||
for k in made:
|
||||
v = made[k]
|
||||
pattern = "([\w]+)(:)([\s]+)(.*)"
|
||||
m = re.search(pattern,made[k])
|
||||
made[k] = m.group(1) + m.group(2) + ' ' + m.group(4)
|
||||
successMsg += (made["rom"] % (YES if (guiargs.create_rom) else NO)) + "\n"
|
||||
successMsg += (made["playthrough"] % (YES if (guiargs.calc_playthrough) else NO)) + "\n"
|
||||
successMsg += (made["spoiler"] % (YES if (not guiargs.jsonout and guiargs.create_spoiler) else NO)) + "\n"
|
||||
successMsg += (made["enemizer"] % (YES if needEnemizer else NO)) + "\n"
|
||||
# FIXME: English
|
||||
successMsg += ("Seed%s: %s" % ('s' if len(seeds) > 1 else "", ','.join(str(x) for x in seeds)))
|
||||
|
||||
messagebox.showinfo(title="Success", message=successMsg)
|
||||
|
||||
## Generate Button
|
||||
# widget ID
|
||||
@@ -273,9 +275,6 @@ def create_guiargs(parent):
|
||||
if hasattr(pagewidgets[widget], 'storageVar'):
|
||||
setattr(guiargs, arg, pagewidgets[widget].storageVar.get())
|
||||
|
||||
# Get EnemizerCLI setting
|
||||
guiargs.enemizercli = parent.pages["randomizer"].pages["enemizer"].widgets["enemizercli"].storageVar.get()
|
||||
|
||||
# Get Multiworld Worlds count
|
||||
guiargs.multi = int(parent.pages["bottom"].pages["content"].widgets["worlds"].storageVar.get())
|
||||
|
||||
|
||||
@@ -80,20 +80,6 @@ def loadcliargs(gui, args, settings=None):
|
||||
# If we've got a Game Options val and we don't have an Adjust val, use the Game Options val
|
||||
gui.pages["adjust"].content.widgets[widget].storageVar.set(args[arg])
|
||||
|
||||
# Get EnemizerCLI setting
|
||||
mainpage = "randomizer"
|
||||
subpage = "enemizer"
|
||||
widget = "enemizercli"
|
||||
setting = "enemizercli"
|
||||
# set storagevar
|
||||
gui.pages[mainpage].pages[subpage].widgets[widget].storageVar.set(args[setting])
|
||||
# set textbox/frame label
|
||||
label = fish.translate("gui","gui",mainpage + '.' + subpage + '.' + widget)
|
||||
gui.pages[mainpage].pages[subpage].widgets[widget].pieces["frame"].label.configure(text=label)
|
||||
# set get from web label
|
||||
label = fish.translate("gui","gui",mainpage + '.' + subpage + '.' + widget + ".online")
|
||||
gui.pages[mainpage].pages[subpage].widgets[widget].pieces["online"].label.configure(text=label)
|
||||
|
||||
# Get baserom path
|
||||
mainpage = "randomizer"
|
||||
subpage = "generation"
|
||||
|
||||
@@ -6,10 +6,7 @@ import webbrowser
|
||||
from source.classes.Empty import Empty
|
||||
|
||||
def enemizer_page(parent,settings):
|
||||
def open_enemizer_download(_evt):
|
||||
webbrowser.open("https://github.com/Bonta0/Enemizer/releases")
|
||||
|
||||
# Enemizer
|
||||
# Enemizer
|
||||
self = ttk.Frame(parent)
|
||||
|
||||
# Enemizer options
|
||||
@@ -29,7 +26,7 @@ def enemizer_page(parent,settings):
|
||||
self.frames["selectOptionsFrame"].pack(fill=X)
|
||||
self.frames["leftEnemizerFrame"].pack(side=LEFT)
|
||||
self.frames["rightEnemizerFrame"].pack(side=RIGHT)
|
||||
self.frames["bottomEnemizerFrame"].pack(fill=X)
|
||||
self.frames["bottomEnemizerFrame"].pack(fill=X, padx=(12, 0))
|
||||
|
||||
# Load Enemizer option widgets as defined by JSON file
|
||||
# Defns include frame name, widget type, widget options, widget placement attributes
|
||||
@@ -43,47 +40,8 @@ def enemizer_page(parent,settings):
|
||||
packAttrs = {"anchor":E}
|
||||
if self.widgets[key].type == "checkbox":
|
||||
packAttrs["anchor"] = W
|
||||
if framename == 'bottomEnemizerFrame':
|
||||
packAttrs["anchor"] = W
|
||||
self.widgets[key].pack(packAttrs)
|
||||
|
||||
## Enemizer CLI Path
|
||||
# This one's more-complicated, build it and stuff it
|
||||
# widget ID
|
||||
widget = "enemizercli"
|
||||
|
||||
# Empty object
|
||||
self.widgets[widget] = Empty()
|
||||
# pieces
|
||||
self.widgets[widget].pieces = {}
|
||||
|
||||
# frame
|
||||
self.widgets[widget].pieces["frame"] = Frame(self.frames["bottomEnemizerFrame"])
|
||||
# frame: label
|
||||
self.widgets[widget].pieces["frame"].label = Label(self.widgets[widget].pieces["frame"], text="EnemizerCLI path: ")
|
||||
self.widgets[widget].pieces["frame"].label.pack(side=LEFT)
|
||||
|
||||
# get app online
|
||||
self.widgets[widget].pieces["online"] = Empty()
|
||||
# get app online: label
|
||||
self.widgets[widget].pieces["online"].label = Label(self.widgets[widget].pieces["frame"], text="(get online)", fg="blue", cursor="hand2")
|
||||
self.widgets[widget].pieces["online"].label.pack(side=LEFT)
|
||||
# get app online: open browser
|
||||
self.widgets[widget].pieces["online"].label.bind("<Button-1>", open_enemizer_download)
|
||||
# storage var
|
||||
self.widgets[widget].storageVar = StringVar(value=settings["enemizercli"])
|
||||
# textbox
|
||||
self.widgets[widget].pieces["textbox"] = Entry(self.widgets[widget].pieces["frame"], textvariable=self.widgets[widget].storageVar)
|
||||
self.widgets[widget].pieces["textbox"].pack(side=LEFT, fill=X, expand=True)
|
||||
|
||||
def EnemizerSelectPath():
|
||||
path = filedialog.askopenfilename(filetypes=[("EnemizerCLI executable", "*EnemizerCLI*")], initialdir=os.path.join("."))
|
||||
if path:
|
||||
self.widgets[widget].storageVar.set(path)
|
||||
settings["enemizercli"] = path
|
||||
# dialog button
|
||||
self.widgets[widget].pieces["opendialog"] = Button(self.widgets[widget].pieces["frame"], text='...', command=EnemizerSelectPath)
|
||||
self.widgets[widget].pieces["opendialog"].pack(side=LEFT)
|
||||
|
||||
# frame: pack
|
||||
self.widgets[widget].pieces["frame"].pack(fill=X)
|
||||
|
||||
return self,settings
|
||||
return self, settings
|
||||
|
||||
@@ -287,9 +287,9 @@ def widget_command(widget, command=""):
|
||||
temp_widget.storageVar.set('keys')
|
||||
|
||||
temp_widget = root.pages["randomizer"].pages["item"].widgets["dropshuffle"]
|
||||
text_output += f'\n {temp_widget.checkbox.cget("text")}'
|
||||
if temp_widget.storageVar.get() == 0:
|
||||
temp_widget.storageVar.set(1)
|
||||
text_output += f'\n {temp_widget.label.cget("text")}'
|
||||
if temp_widget.storageVar.get() == 'none':
|
||||
temp_widget.storageVar.set('keys')
|
||||
|
||||
if text_output:
|
||||
messagebox.showinfo('', f'The following settings were changed:{text_output}')
|
||||
|
||||
@@ -70,7 +70,7 @@ def create_item_pool_config(world):
|
||||
for player in range(1, world.players + 1):
|
||||
config.static_placement[player] = defaultdict(list)
|
||||
config.static_placement[player].update(vanilla_mapping)
|
||||
if world.dropshuffle[player]:
|
||||
if world.dropshuffle[player] != 'none':
|
||||
for item, locs in keydrop_vanilla_mapping.items():
|
||||
config.static_placement[player][item].extend(locs)
|
||||
if world.pottery[player] not in ['none', 'cave']:
|
||||
@@ -96,7 +96,7 @@ def create_item_pool_config(world):
|
||||
for item, locs in vanilla_mapping.items():
|
||||
if 'Small Key' in item:
|
||||
universal_key_locations.extend(locs)
|
||||
if world.dropshuffle[player]:
|
||||
if world.dropshuffle[player] != 'none':
|
||||
for item, locs in keydrop_vanilla_mapping.items():
|
||||
if 'Small Key' in item:
|
||||
universal_key_locations.extend(locs)
|
||||
@@ -129,11 +129,11 @@ def create_item_pool_config(world):
|
||||
groups = LocationGroup('Major').locs(init_set)
|
||||
if world.bigkeyshuffle[player]:
|
||||
groups.locations.extend(mode_grouping['Big Keys'])
|
||||
if world.dropshuffle[player]:
|
||||
if world.dropshuffle[player] != 'none':
|
||||
groups.locations.extend(mode_grouping['Big Key Drops'])
|
||||
if world.keyshuffle[player] != 'none':
|
||||
groups.locations.extend(mode_grouping['Small Keys'])
|
||||
if world.dropshuffle[player]:
|
||||
if world.dropshuffle[player] != 'none':
|
||||
groups.locations.extend(mode_grouping['Key Drops'])
|
||||
if world.pottery[player] not in ['none', 'cave']:
|
||||
groups.locations.extend(mode_grouping['Pot Keys'])
|
||||
@@ -357,7 +357,7 @@ def determine_major_items(world, player):
|
||||
major_item_set.add('Single Arrow')
|
||||
if world.keyshuffle[player] == 'universal':
|
||||
major_item_set.add('Small Key (Universal)')
|
||||
if world.goal[player] in ['triforcehunt', 'trinity', 'ganonhunt']:
|
||||
if world.goal[player] in {'triforcehunt', 'ganonhunt', 'trinity'}:
|
||||
major_item_set.add('Triforce Piece')
|
||||
if world.bombbag[player]:
|
||||
major_item_set.add('Bomb Upgrade (+10)')
|
||||
@@ -416,11 +416,11 @@ def filter_locations(item_to_place, locations, world, vanilla_skip=False, potion
|
||||
return filtered
|
||||
if world.algorithm == 'district':
|
||||
config = world.item_pool_config
|
||||
if ((isinstance(item_to_place,str) and item_to_place == 'Placeholder')
|
||||
if ((isinstance(item_to_place, str) and item_to_place == 'Placeholder')
|
||||
or item_to_place.name in config.item_pool[item_to_place.player]):
|
||||
restricted = config.location_groups[0].locations
|
||||
filtered = [l for l in locations if l.name in restricted and l.player in restricted[l.name]]
|
||||
return filtered if len(filtered) > 0 else locations
|
||||
return filtered
|
||||
elif potion:
|
||||
restricted = config.location_groups[0].locations
|
||||
filtered = [l for l in locations if l.name not in restricted or l.player not in restricted[l.name]]
|
||||
@@ -439,14 +439,14 @@ def filter_locations(item_to_place, locations, world, vanilla_skip=False, potion
|
||||
return locations
|
||||
|
||||
|
||||
def filter_pot_locations(locations, world):
|
||||
def filter_special_locations(locations, world, vanilla_matcher):
|
||||
if world.algorithm == 'district':
|
||||
config = world.item_pool_config
|
||||
restricted = config.location_groups[0].locations
|
||||
filtered = [l for l in locations if l.name not in restricted or l.player not in restricted[l.name]]
|
||||
return filtered if len(filtered) > 0 else locations
|
||||
if world.algorithm == 'vanilla_fill':
|
||||
filtered = [l for l in locations if l.pot and l.pot.item in [PotItem.Chicken, PotItem.BigMagic]]
|
||||
filtered = [l for l in locations if vanilla_matcher(l)]
|
||||
return filtered if len(filtered) > 0 else locations
|
||||
return locations
|
||||
|
||||
|
||||
576
source/logic/Rule.py
Normal file
576
source/logic/Rule.py
Normal file
@@ -0,0 +1,576 @@
|
||||
import itertools
|
||||
|
||||
from collections import OrderedDict
|
||||
try:
|
||||
from fast_enum import FastEnum
|
||||
except ImportError:
|
||||
from enum import IntFlag as FastEnum
|
||||
|
||||
from BaseClasses import CrystalBarrier, KeyRuleType
|
||||
from Dungeons import dungeon_keys
|
||||
|
||||
|
||||
class RuleType(FastEnum):
|
||||
Conjunction = 0
|
||||
Disjunction = 1
|
||||
Item = 2
|
||||
Glitch = 3
|
||||
Reachability = 4
|
||||
Static = 5
|
||||
Bottle = 6
|
||||
Crystal = 7
|
||||
Barrier = 8
|
||||
Hearts = 9
|
||||
Unlimited = 10
|
||||
ExtendMagic = 11
|
||||
Boss = 12
|
||||
Negate = 13
|
||||
LocationCheck = 14
|
||||
SmallKeyDoor = 15
|
||||
|
||||
|
||||
class Rule(object):
|
||||
|
||||
def __init__(self, rule_type):
|
||||
self.rule_type = rule_type
|
||||
self.sub_rules = []
|
||||
self.principal = None
|
||||
self.player = 0
|
||||
self.resolution_hint = None
|
||||
self.barrier = None
|
||||
self.flag = None
|
||||
self.locations = []
|
||||
self.count = 1
|
||||
|
||||
self.std_req = None
|
||||
|
||||
self.rule_lambda = lambda state: True
|
||||
|
||||
def eval(self, state):
|
||||
return self.rule_lambda(state)
|
||||
|
||||
def get_requirements(self, progressive_flag=True):
|
||||
if not self.std_req:
|
||||
reqs = rule_requirements[self.rule_type](self, progressive_flag)
|
||||
self.std_req = standardize_requirements(reqs, progressive_flag)
|
||||
return self.std_req
|
||||
|
||||
def __str__(self):
|
||||
return str(self.__unicode__())
|
||||
|
||||
def __unicode__(self):
|
||||
return rule_prints[self.rule_type](self)
|
||||
|
||||
|
||||
rule_prints = {
|
||||
RuleType.Conjunction: lambda self: f'({" and ".join([str(x) for x in self.sub_rules])})',
|
||||
RuleType.Disjunction: lambda self: f'({" or ".join([str(x) for x in self.sub_rules])})',
|
||||
RuleType.Item: lambda self: f'has {self.principal}' if self.count == 1 else f'has {self.count} {self.principal}(s)',
|
||||
RuleType.Reachability: lambda self: f'canReach {self.principal}',
|
||||
RuleType.Static: lambda self: f'{self.principal}',
|
||||
RuleType.Crystal: lambda self: f'has {self.principal} crystals',
|
||||
RuleType.Barrier: lambda self: f'{self.barrier} @ {self.principal}',
|
||||
RuleType.Hearts: lambda self: f'has {self.principal} hearts',
|
||||
RuleType.Unlimited: lambda self: f'canBuyUnlimited {self.principal}',
|
||||
RuleType.ExtendMagic: lambda self: f'magicNeeded {self.principal}',
|
||||
RuleType.Boss: lambda self: f'canDefeat({self.principal.defeat_rule})',
|
||||
RuleType.Negate: lambda self: f'not ({self.sub_rules[0]})',
|
||||
RuleType.LocationCheck: lambda self: f'{self.principal} in [{", ".join(self.locations)}]',
|
||||
RuleType.SmallKeyDoor: lambda self: f'doorOpen {self.principal[0]}:{self.principal[1]}'
|
||||
}
|
||||
|
||||
|
||||
def or_rule(rule1, rule2):
|
||||
return lambda state: rule1(state) or rule2(state)
|
||||
|
||||
|
||||
def and_rule(rule1, rule2):
|
||||
return lambda state: rule1(state) and rule2(state)
|
||||
|
||||
|
||||
class RuleFactory(object):
|
||||
|
||||
@staticmethod
|
||||
def static_rule(boolean):
|
||||
rule = Rule(RuleType.Static)
|
||||
rule.principal = boolean
|
||||
rule.rule_lambda = lambda state: boolean
|
||||
return rule
|
||||
|
||||
@staticmethod
|
||||
def conj(rules):
|
||||
if len(rules) == 1:
|
||||
return rules[0]
|
||||
rule = Rule(RuleType.Conjunction)
|
||||
rule_lambda = None
|
||||
for r in rules:
|
||||
if r is None:
|
||||
continue
|
||||
if r.rule_type == RuleType.Conjunction:
|
||||
rule.sub_rules.extend(r.sub_rules) # todo: this extension for the lambda calc
|
||||
elif r.rule_type == RuleType.Static and r.principal: # remove static flag if unnecessary
|
||||
continue
|
||||
elif r.rule_type == RuleType.Static and not r.principal: # always evaluates to false
|
||||
return r
|
||||
else:
|
||||
rule.sub_rules.append(r)
|
||||
if not rule_lambda:
|
||||
rule_lambda = r.rule_lambda
|
||||
else:
|
||||
rule_lambda = and_rule(rule_lambda, r.rule_lambda)
|
||||
rule.rule_lambda = rule_lambda if rule_lambda else lambda state: True
|
||||
return rule
|
||||
|
||||
@staticmethod
|
||||
def disj(rules):
|
||||
if len(rules) == 1:
|
||||
return rules[0]
|
||||
rule = Rule(RuleType.Disjunction)
|
||||
rule_lambda = None
|
||||
for r in rules:
|
||||
if r is None:
|
||||
continue
|
||||
if r.rule_type == RuleType.Disjunction:
|
||||
rule.sub_rules.extend(r.sub_rules) # todo: this extension for the lambda calc
|
||||
elif r.rule_type == RuleType.Static and not r.principal: # remove static flag if unnecessary
|
||||
continue
|
||||
elif r.rule_type == RuleType.Static and r.principal: # always evaluates to true
|
||||
return r
|
||||
else:
|
||||
rule.sub_rules.append(r)
|
||||
if not rule_lambda:
|
||||
rule_lambda = r.rule_lambda
|
||||
else:
|
||||
rule_lambda = or_rule(rule_lambda, r.rule_lambda)
|
||||
rule.rule_lambda = rule_lambda if rule_lambda else lambda state: True
|
||||
return rule
|
||||
|
||||
@staticmethod
|
||||
def item(item, player, count=1):
|
||||
rule = Rule(RuleType.Item)
|
||||
rule.principal = item
|
||||
rule.player = player
|
||||
rule.count = count
|
||||
rule.rule_lambda = lambda state: state.has(item, player, count)
|
||||
return rule
|
||||
|
||||
@staticmethod
|
||||
def bottle(player):
|
||||
rule = Rule(RuleType.Bottle)
|
||||
rule.player = player
|
||||
rule.rule_lambda = lambda state: state.has_bottle(player)
|
||||
return rule
|
||||
|
||||
@staticmethod
|
||||
def crystals(number, player):
|
||||
rule = Rule(RuleType.Crystal)
|
||||
rule.principal = number
|
||||
rule.player = player
|
||||
rule.rule_lambda = lambda state: state.has_crystals(number, player)
|
||||
return rule
|
||||
|
||||
@staticmethod
|
||||
def barrier(region, player, barrier):
|
||||
rule = Rule(RuleType.Barrier)
|
||||
rule.principal = region
|
||||
rule.player = player
|
||||
rule.barrier = barrier
|
||||
rule.rule_lambda = lambda state: state.can_cross_barrier(region, player, barrier)
|
||||
return rule
|
||||
|
||||
@staticmethod
|
||||
def hearts(number, player):
|
||||
rule = Rule(RuleType.Hearts)
|
||||
rule.principal = number
|
||||
rule.player = player
|
||||
rule.rule_lambda = lambda state: state.has_hearts(number, player)
|
||||
return rule
|
||||
|
||||
@staticmethod
|
||||
def unlimited(item, player, shop_regions):
|
||||
rule = Rule(RuleType.Unlimited)
|
||||
rule.principal = item
|
||||
rule.player = player
|
||||
rule.locations = shop_regions # list of regions where said item can be bought
|
||||
rule.rule_lambda = lambda state: state.can_buy_unlimited(item, player)
|
||||
return rule
|
||||
|
||||
@staticmethod
|
||||
def extend_magic(player, magic, difficulty, magic_potion_regions, flag):
|
||||
rule = Rule(RuleType.ExtendMagic)
|
||||
rule.principal = magic
|
||||
rule.player = player
|
||||
rule.resolution_hint = difficulty # world difficulty setting
|
||||
rule.locations = magic_potion_regions # list of regions where blue/green can be bought
|
||||
rule.flag = flag
|
||||
rule.rule_lambda = lambda state: state.can_extend_magic(player, magic, flag)
|
||||
return rule
|
||||
|
||||
@staticmethod
|
||||
def boss(boss):
|
||||
rule = Rule(RuleType.Boss)
|
||||
rule.principal = boss
|
||||
rule.rule_lambda = lambda state: boss.defeat_rule.eval(state)
|
||||
return rule
|
||||
|
||||
@staticmethod
|
||||
def neg(orig):
|
||||
rule = Rule(RuleType.Negate)
|
||||
rule.sub_rules.append(orig)
|
||||
rule.rule_lambda = lambda state: not orig.rule_lambda(state)
|
||||
return rule
|
||||
|
||||
@staticmethod
|
||||
def check_location(item, location, player):
|
||||
rule = Rule(RuleType.LocationCheck)
|
||||
rule.principal = item
|
||||
rule.location = location
|
||||
rule.player = player
|
||||
rule.rule_lambda = eval_location(item, location, player)
|
||||
return rule
|
||||
|
||||
@staticmethod
|
||||
def small_key_door(door_name, dungeon, player, door_rules):
|
||||
rule = Rule(RuleType.SmallKeyDoor)
|
||||
rule.principal = (door_name, dungeon)
|
||||
rule.player = player
|
||||
rule.resolution_hint = door_rules # door_rule object from KeyDoorShuffle
|
||||
rule.rule_lambda = eval_small_key_door(door_name, dungeon, player)
|
||||
return rule
|
||||
|
||||
|
||||
def eval_location(item, location, player):
|
||||
return lambda state: eval_location_main(item, location, player, state)
|
||||
|
||||
|
||||
def eval_location_main(item, location, player, state):
|
||||
location = state.world.get_location(location, player)
|
||||
return location.item and location.item.name == item and location.player == player
|
||||
|
||||
|
||||
def eval_small_key_door_main(state, door_name, dungeon, player):
|
||||
if state.is_door_open(door_name, player):
|
||||
return True
|
||||
key_logic = state.world.key_logic[player][dungeon]
|
||||
door_rule = key_logic.door_rules[door_name]
|
||||
door_openable = False
|
||||
for ruleType, number in door_rule.new_rules.items():
|
||||
if door_openable:
|
||||
return True
|
||||
if ruleType == KeyRuleType.WorstCase:
|
||||
door_openable |= state.has_sm_key(key_logic.small_key_name, player, number)
|
||||
elif ruleType == KeyRuleType.AllowSmall:
|
||||
if (door_rule.small_location.item and door_rule.small_location.item.name == key_logic.small_key_name
|
||||
and door_rule.small_location.item.player == player):
|
||||
return True # always okay if allow small is on
|
||||
elif isinstance(ruleType, tuple):
|
||||
lock, lock_item = ruleType
|
||||
# this doesn't track logical locks yet, i.e. hammer locks the item and hammer is there, but the item isn't
|
||||
for loc in door_rule.alternate_big_key_loc:
|
||||
spot = state.world.get_location(loc, player)
|
||||
if spot.item and spot.item.name == lock_item:
|
||||
door_openable |= state.has_sm_key(key_logic.small_key_name, player, number)
|
||||
break
|
||||
return door_openable
|
||||
|
||||
|
||||
def eval_small_key_door(door_name, dungeon, player):
|
||||
return lambda state: eval_small_key_door_main(state, door_name, dungeon, player)
|
||||
|
||||
|
||||
def conjunction_requirements(rule, f):
|
||||
combined = [ReqSet()]
|
||||
for r in rule.sub_rules:
|
||||
result = r.get_requirements(f)
|
||||
combined = merge_requirements(combined, result)
|
||||
return combined
|
||||
|
||||
|
||||
def disjunction_requirements(rule, f):
|
||||
results = []
|
||||
for r in rule.sub_rules:
|
||||
result = r.get_requirements(f)
|
||||
results.extend(result)
|
||||
return results
|
||||
|
||||
|
||||
rule_requirements = {
|
||||
RuleType.Conjunction: conjunction_requirements,
|
||||
RuleType.Disjunction: disjunction_requirements,
|
||||
RuleType.Item: lambda rule, f: [ReqSet([Requirement(ReqType.Item, rule.principal, rule.player, rule, rule.count)])],
|
||||
RuleType.Reachability: lambda rule, f: [ReqSet([Requirement(ReqType.Reachable, rule.principal, rule.player, rule)])],
|
||||
RuleType.Static: lambda rule, f: static_req(rule),
|
||||
RuleType.Crystal: lambda rule, f: crystal_requirements(rule),
|
||||
RuleType.Bottle: lambda rule, f: [ReqSet([Requirement(ReqType.Item, 'Bottle', rule.player, rule, 1)])],
|
||||
RuleType.Barrier: lambda rule, f: barrier_req(rule),
|
||||
RuleType.Hearts: lambda rule, f: empty_req(), # todo: the one heart container
|
||||
RuleType.Unlimited: lambda rule, f: unlimited_buys(rule),
|
||||
RuleType.ExtendMagic: lambda rule, f: magic_requirements(rule),
|
||||
RuleType.Boss: lambda rule, f: rule.principal.defeat_rule.get_requirements(f),
|
||||
RuleType.Negate: lambda rule, f: empty_req(), # ignore these and just don't flood the key too early
|
||||
RuleType.LocationCheck: lambda rule, f: location_check(rule),
|
||||
RuleType.SmallKeyDoor: lambda rule, f: small_key_reqs(rule)
|
||||
}
|
||||
|
||||
|
||||
avail_crystals = ['Crystal 1', 'Crystal 2', 'Crystal 3', 'Crystal 4', 'Crystal 5', 'Crystal 6', 'Crystal 7']
|
||||
|
||||
|
||||
def crystal_requirements(rule):
|
||||
crystal_rules = map(lambda c: Requirement(ReqType.Item, c, rule.player, rule), avail_crystals)
|
||||
combinations = itertools.combinations(crystal_rules, rule.principal)
|
||||
counter_list = []
|
||||
for combo in combinations:
|
||||
counter_list.append(ReqSet(combo))
|
||||
return counter_list
|
||||
|
||||
|
||||
# todo: 1/4 magic
|
||||
def magic_requirements(rule):
|
||||
if rule.principal <= 8:
|
||||
return [set()]
|
||||
bottle_val = 1.0
|
||||
if rule.resolution_hint == 'expert' and not rule.flag:
|
||||
bottle_val = 0.25
|
||||
elif rule.resolution_hint == 'hard' and not rule.flag:
|
||||
bottle_val = 0.5
|
||||
base, min_bot, reqs = 8, None, []
|
||||
for i in range(1, 5):
|
||||
if base + bottle_val*base*i >= rule.principal:
|
||||
min_bot = i
|
||||
break
|
||||
if min_bot:
|
||||
for region in rule.locations:
|
||||
reqs.append(ReqSet([Requirement(ReqType.Item, 'Bottle', rule.player, rule, min_bot),
|
||||
Requirement(ReqType.Reachable, region, rule.player, rule)]))
|
||||
if rule.principal <= 16:
|
||||
reqs.append(ReqSet([Requirement(ReqType.Item, 'Magic Upgrade (1/2)', rule.player, rule, 1)]))
|
||||
return reqs
|
||||
else:
|
||||
base, min_bot = 16, 4
|
||||
for i in range(1, 5):
|
||||
if base + bottle_val*base*i >= rule.principal:
|
||||
min_bot = i
|
||||
break
|
||||
if min_bot:
|
||||
for region in rule.locations:
|
||||
reqs.append(ReqSet([Requirement(ReqType.Item, 'Magic Upgrade (1/2)', rule.player, rule, 1),
|
||||
Requirement(ReqType.Item, 'Bottle', rule.player, rule, min_bot),
|
||||
Requirement(ReqType.Reachable, region, rule.player, rule)]))
|
||||
return reqs
|
||||
|
||||
|
||||
def static_req(rule):
|
||||
return [ReqSet()] if rule.principal else [ReqSet([Requirement(ReqType.Item, 'Impossible', rule.player, rule)])]
|
||||
|
||||
|
||||
def barrier_req(rule):
|
||||
return [ReqSet([Requirement(ReqType.Reachable, rule.principal, rule.player, rule, crystal=rule.barrier)])]
|
||||
|
||||
|
||||
def empty_req():
|
||||
return [ReqSet()]
|
||||
|
||||
|
||||
def location_check(rule):
|
||||
return [ReqSet([Requirement(ReqType.Placement, rule.principal, rule.player, rule, locations=rule.locations)])]
|
||||
|
||||
|
||||
def unlimited_buys(rule):
|
||||
requirements = []
|
||||
for region in rule.locations:
|
||||
requirements.append(ReqSet([Requirement(ReqType.Reachable, region, rule.player, rule)]))
|
||||
return requirements
|
||||
|
||||
|
||||
def small_key_reqs(rule):
|
||||
requirements = []
|
||||
door_name, dungeon = rule.principal
|
||||
key_name = dungeon_keys[dungeon]
|
||||
for rule_type, number in rule.resolution_hint.new_rules.items():
|
||||
if rule_type == KeyRuleType.WorstCase:
|
||||
requirements.append(ReqSet([Requirement(ReqType.Item, key_name, rule.player, rule, number)]))
|
||||
elif rule_type == KeyRuleType.AllowSmall:
|
||||
small_loc = rule.resolution_hint.small_location.name
|
||||
requirements.append(ReqSet([
|
||||
Requirement(ReqType.Placement, key_name, rule.player, rule, locations=[small_loc]),
|
||||
Requirement(ReqType.Item, key_name, rule.player, rule, number)]))
|
||||
elif isinstance(rule_type, tuple):
|
||||
lock, lock_item = rule_type
|
||||
locs = [x.name for x in rule.resolution_hint.alternate_big_key_loc]
|
||||
requirements.append(ReqSet([
|
||||
Requirement(ReqType.Placement, lock_item, rule.player, rule, locations=locs),
|
||||
Requirement(ReqType.Item, key_name, rule.player, rule, number)]))
|
||||
return requirements
|
||||
|
||||
|
||||
class ReqType(FastEnum):
|
||||
Item = 0
|
||||
Placement = 2
|
||||
|
||||
|
||||
class ReqSet(object):
|
||||
|
||||
def __init__(self, requirements=None):
|
||||
if requirements is None:
|
||||
requirements = []
|
||||
self.keyed = OrderedDict()
|
||||
for r in requirements:
|
||||
self.keyed[r.simple_key()] = r
|
||||
|
||||
def append(self, req):
|
||||
self.keyed[req.simple_key()] = req
|
||||
|
||||
def get_values(self):
|
||||
return self.keyed.values()
|
||||
|
||||
def merge(self, other):
|
||||
new_set = ReqSet(self.get_values())
|
||||
for r in other.get_values():
|
||||
key = r.simple_key()
|
||||
if key in new_set.keyed:
|
||||
new_set.keyed[key] = max(r, new_set.keyed[key], key=lambda r: r.amount)
|
||||
else:
|
||||
new_set.keyed[key] = r
|
||||
return new_set
|
||||
|
||||
def redundant(self, other):
|
||||
for k, req in other.keyed.items():
|
||||
if k not in self.keyed:
|
||||
return False
|
||||
elif self.keyed[k].amount < req.amount:
|
||||
return False
|
||||
return True
|
||||
|
||||
def different(self, other):
|
||||
for key in self.keyed.keys():
|
||||
if key not in other.keyed:
|
||||
return True
|
||||
if key in other.keyed and self.keyed[key].amount > other.keyed[key].amount:
|
||||
return True
|
||||
return False
|
||||
|
||||
def find_item(self, item_name):
|
||||
for key, req in self.keyed.items():
|
||||
if req.req_type == ReqType.Item and req.item == item_name:
|
||||
return req
|
||||
return None
|
||||
|
||||
def __eq__(self, other):
|
||||
for key, req in self.keyed.items():
|
||||
if key not in other.keyed:
|
||||
return False
|
||||
if req.amount != other.keyed[key].amount:
|
||||
return False
|
||||
for key in other.keyed:
|
||||
if key not in self.keyed:
|
||||
return False
|
||||
return True
|
||||
|
||||
def __str__(self):
|
||||
return str(self.__unicode__())
|
||||
|
||||
def __unicode__(self):
|
||||
return " and ".join([str(x) for x in self.keyed.values()])
|
||||
|
||||
|
||||
class Requirement(object):
|
||||
|
||||
def __init__(self, req_type, item, player, rule, amount=1, crystal=CrystalBarrier.Null, locations=()):
|
||||
self.req_type = req_type
|
||||
self.item = item
|
||||
self.player = player
|
||||
self.rule = rule
|
||||
self.amount = amount
|
||||
self.crystal = crystal
|
||||
self.locations = tuple(locations)
|
||||
|
||||
def simple_key(self):
|
||||
return self.req_type, self.item, self.player, self.crystal, self.locations
|
||||
|
||||
def key(self):
|
||||
return self.req_type, self.item, self.player, self.amount, self.crystal, self.locations
|
||||
|
||||
def __eq__(self, other):
|
||||
if isinstance(other, Requirement):
|
||||
return self.key() == other.key()
|
||||
return NotImplemented
|
||||
|
||||
def __hash__(self):
|
||||
return hash(self.key())
|
||||
|
||||
def __str__(self):
|
||||
return str(self.__unicode__())
|
||||
|
||||
def __unicode__(self):
|
||||
if self.req_type == ReqType.Item:
|
||||
return f'has {self.item}' if self.amount == 1 else f'has {self.amount} {self.item}(s)'
|
||||
elif self.req_type == ReqType.Placement:
|
||||
return f'{self.item} located @ {",".join(self.locations)}'
|
||||
|
||||
|
||||
# requirement utility methods
|
||||
def merge_requirements(starting_requirements, new_requirements):
|
||||
merge = []
|
||||
for req in starting_requirements:
|
||||
for new_r in new_requirements:
|
||||
merge.append(req.merge(new_r))
|
||||
return reduce_requirements(merge)
|
||||
|
||||
|
||||
only_one = {'Moon Pearl', 'Hammer', 'Blue Boomerang', 'Red Boomerang', 'Hookshot', 'Mushroom', 'Powder',
|
||||
'Fire Rod', 'Ice Rod', 'Bombos', 'Ether', 'Quake', 'Lamp', 'Shovel', 'Ocarina', 'Bug Catching Net',
|
||||
'Book of Mudora', 'Magic Mirror', 'Cape', 'Cane of Somaria', 'Cane of Byrna', 'Flippers', 'Pegasus Boots'}
|
||||
|
||||
|
||||
def standardize_requirements(requirements, progressive_flag):
|
||||
assert isinstance(requirements, list)
|
||||
for req in requirements:
|
||||
for thing in req.get_values():
|
||||
if thing.item in only_one and thing.amount > 1:
|
||||
thing.amount = 1
|
||||
if progressive_flag:
|
||||
substitute_progressive(req)
|
||||
return reduce_requirements(requirements)
|
||||
|
||||
|
||||
def reduce_requirements(requirements):
|
||||
removals = []
|
||||
reduced = list(requirements)
|
||||
# subset manip
|
||||
ttl = len(reduced)
|
||||
for i in range(0, ttl - 1):
|
||||
for j in range(i + 1, ttl):
|
||||
req, other_req = reduced[i], reduced[j]
|
||||
if req.redundant(other_req):
|
||||
removals.append(req)
|
||||
elif other_req.redundant(req):
|
||||
removals.append(other_req)
|
||||
for removal in removals:
|
||||
if removal in reduced:
|
||||
reduced.remove(removal)
|
||||
assert len(reduced) != 0
|
||||
return reduced
|
||||
|
||||
|
||||
progress_sub = {
|
||||
'Fighter Sword': ('Progressive Sword', 1),
|
||||
'Master Sword': ('Progressive Sword', 2),
|
||||
'Tempered Sword': ('Progressive Sword', 3),
|
||||
'Golden Sword': ('Progressive Sword', 4),
|
||||
'Power Glove': ('Progressive Glove', 1),
|
||||
'Titans Mitts': ('Progressive Glove', 2),
|
||||
'Bow': ('Progressive Bow', 1),
|
||||
'Silver Arrows': ('Progressive Bow', 2),
|
||||
'Blue Mail': ('Progressive Armor', 1),
|
||||
'Red Mail': ('Progressive Armor', 2),
|
||||
'Blue Shield': ('Progressive Shield', 1),
|
||||
'Red Shield': ('Progressive Shield', 2),
|
||||
'Mirror Shield': ('Progressive Shield', 3),
|
||||
}
|
||||
|
||||
|
||||
def substitute_progressive(req):
|
||||
for item in req.get_values():
|
||||
if item.item in progress_sub.keys():
|
||||
item.item, item.amount = progress_sub[item.item]
|
||||
@@ -2561,9 +2561,13 @@ mandatory_connections = [('Lost Woods Hideout (top to bottom)', 'Lost Woods Hide
|
||||
('Lumberjack Tree (top to bottom)', 'Lumberjack Tree (bottom)'),
|
||||
('Death Mountain Return Cave E', 'Death Mountain Return Cave (right)'),
|
||||
('Death Mountain Return Cave W', 'Death Mountain Return Cave (left)'),
|
||||
('Old Man Cave Dropdown', 'Old Man Cave'),
|
||||
('Spectacle Rock Cave Drop', 'Spectacle Rock Cave (Bottom)'),
|
||||
('Spectacle Rock Cave Peak Drop', 'Spectacle Rock Cave (Bottom)'),
|
||||
('Old Man Cave Dropdown', 'Old Man Cave (East)'),
|
||||
('Old Man Cave W', 'Old Man Cave (West)'),
|
||||
('Old Man Cave E', 'Old Man Cave (East)'),
|
||||
('Spectacle Rock Cave Drop', 'Spectacle Rock Cave Pool'),
|
||||
('Spectacle Rock Cave Peak Drop', 'Spectacle Rock Cave Pool'),
|
||||
('Spectacle Rock Cave West Edge', 'Spectacle Rock Cave (Bottom)'),
|
||||
('Spectacle Rock Cave East Edge', 'Spectacle Rock Cave Pool'),
|
||||
('Old Man House Front to Back', 'Old Man House Back'),
|
||||
('Old Man House Back to Front', 'Old Man House'),
|
||||
('Spiral Cave (top to bottom)', 'Spiral Cave (Bottom)'),
|
||||
@@ -2582,11 +2586,19 @@ mandatory_connections = [('Lost Woods Hideout (top to bottom)', 'Lost Woods Hide
|
||||
('Sewer Drop', 'Sewers Rat Path'),
|
||||
('Missing Smith', 'Missing Smith'),
|
||||
('Bat Cave Door', 'Bat Cave (left)'),
|
||||
('Good Bee Cave Front to Back', 'Good Bee Cave (back)'),
|
||||
('Good Bee Cave Back to Front', 'Good Bee Cave'),
|
||||
('Capacity Upgrade East', 'Capacity Fairy Pool'),
|
||||
('Capacity Fairy Pool West', 'Capacity Upgrade'),
|
||||
('Bonk Fairy (Dark) Pool', 'Bonk Fairy Pool'),
|
||||
('Bonk Fairy (Light) Pool', 'Bonk Fairy Pool'),
|
||||
|
||||
('Hookshot Cave Front to Middle', 'Hookshot Cave (Middle)'),
|
||||
('Hookshot Cave Middle to Front', 'Hookshot Cave (Front)'),
|
||||
('Hookshot Cave Middle to Back', 'Hookshot Cave (Back)'),
|
||||
('Hookshot Cave Back to Middle', 'Hookshot Cave (Middle)'),
|
||||
('Hookshot Cave Back to Fairy', 'Hookshot Cave (Fairy Pool)'),
|
||||
('Hookshot Cave Fairy to Back', 'Hookshot Cave (Back)'),
|
||||
('Hookshot Cave Bonk Path', 'Hookshot Cave (Bonk Islands)'),
|
||||
('Hookshot Cave Hook Path', 'Hookshot Cave (Hook Islands)'),
|
||||
('Superbunny Cave Climb', 'Superbunny Cave (Top)'),
|
||||
@@ -2606,7 +2618,7 @@ default_connections = {'Lost Woods Gamble': 'Lost Woods Gamble',
|
||||
'Lumberjack Tree Exit': 'Lumberjack Area',
|
||||
'Death Mountain Return Cave (East)': 'Death Mountain Return Cave (right)',
|
||||
'Death Mountain Return Cave Exit (East)': 'West Death Mountain (Bottom)',
|
||||
'Old Man Cave (East)': 'Old Man Cave',
|
||||
'Old Man Cave (East)': 'Old Man Cave (East)',
|
||||
'Old Man Cave Exit (East)': 'West Death Mountain (Bottom)',
|
||||
'Spectacle Rock Cave': 'Spectacle Rock Cave (Top)',
|
||||
'Spectacle Rock Cave Exit (Top)': 'West Death Mountain (Bottom)',
|
||||
|
||||
228
source/rom/DataTables.py
Normal file
228
source/rom/DataTables.py
Normal file
@@ -0,0 +1,228 @@
|
||||
from collections import defaultdict
|
||||
|
||||
from Utils import snes_to_pc, int24_as_bytes, int16_as_bytes, load_cached_yaml, pc_to_snes
|
||||
|
||||
from source.dungeon.EnemyList import EnemyTable, init_vanilla_sprites, vanilla_sprites, init_enemy_stats, EnemySprite
|
||||
from source.dungeon.EnemyList import sprite_translation
|
||||
from source.dungeon.RoomHeader import init_room_headers
|
||||
from source.dungeon.RoomList import Room0127
|
||||
from source.enemizer.OwEnemyList import init_vanilla_sprites_ow, vanilla_sprites_ow
|
||||
from source.enemizer.SpriteSheets import init_sprite_sheets, init_sprite_requirements, SheetChoice
|
||||
|
||||
|
||||
def convert_area_id_to_offset(area_id):
|
||||
if area_id < 0x40:
|
||||
return area_id
|
||||
if 0x40 <= area_id < 0x80:
|
||||
return area_id + 0x40
|
||||
if 0x90 <= area_id <= 0xCF:
|
||||
return area_id - 0x50
|
||||
raise Exception(f'{hex(area_id)} is not a valid area id for offset math')
|
||||
|
||||
|
||||
class DataTables:
|
||||
def __init__(self):
|
||||
self.room_headers = None
|
||||
self.room_list = None
|
||||
self.sprite_sheets = None
|
||||
self.uw_enemy_table = None
|
||||
self.ow_enemy_table = None
|
||||
self.pot_secret_table = None
|
||||
self.overworld_sprite_sheets = None
|
||||
|
||||
# associated data
|
||||
self.sprite_requirements = None
|
||||
self.room_requirements = None
|
||||
self.enemy_stats = None
|
||||
self.enemy_damage = None
|
||||
self.bush_sprite_table = {}
|
||||
|
||||
# enemizer conditions
|
||||
self.uw_enemy_denials = {}
|
||||
self.ow_enemy_denials = {}
|
||||
self.uw_enemy_drop_denials = {}
|
||||
self.sheet_choices = []
|
||||
denial_data = load_cached_yaml(['source', 'enemizer', 'enemy_deny.yaml'])
|
||||
for denial in denial_data['UwGeneralDeny']:
|
||||
self.uw_enemy_denials[denial[0], denial[1]] = {sprite_translation[x] for x in denial[2]}
|
||||
for denial in denial_data['OwGeneralDeny']:
|
||||
self.ow_enemy_denials[denial[0], denial[1]] = {sprite_translation[x] for x in denial[2]}
|
||||
for denial in denial_data['UwEnemyDrop']:
|
||||
self.uw_enemy_drop_denials[denial[0], denial[1]] = {sprite_translation[x] for x in denial[2]}
|
||||
weights = load_cached_yaml(['source', 'enemizer', 'enemy_weight.yaml'])
|
||||
self.uw_weights = {sprite_translation[k]: v for k, v in weights['UW'].items()}
|
||||
self.ow_weights = {sprite_translation[k]: v for k, v in weights['OW'].items()}
|
||||
sheet_weights = load_cached_yaml(['source', 'enemizer', 'sheet_weight.yaml'])
|
||||
for item in sheet_weights['SheetChoices']:
|
||||
choice = SheetChoice(tuple(item['slots']), item['assignments'], item['weight'])
|
||||
self.sheet_choices.append(choice)
|
||||
|
||||
def write_to_rom(self, rom, colorize_pots=False, increase_bush_sprite_chance=False):
|
||||
if self.pot_secret_table.size() > 0x11c0:
|
||||
raise Exception('Pot table is too big for current area')
|
||||
self.pot_secret_table.write_pot_data_to_rom(rom, colorize_pots, self)
|
||||
for room_id, header in self.room_headers.items():
|
||||
data_location = (0x30DA00 + room_id * 14) & 0xFFFF
|
||||
rom.write_bytes(snes_to_pc(0x04F1E2) + room_id * 2, int16_as_bytes(data_location))
|
||||
header.write_to_rom(rom, snes_to_pc(0x30DA00)) # new header table, bank30, tables.asm
|
||||
room_start_address = 0x378000
|
||||
for room_id, room in self.room_list.items():
|
||||
rom.write_bytes(snes_to_pc(0x1F8000 + room_id * 3), int24_as_bytes(room_start_address))
|
||||
door_start, bytes_written = room.write_to_rom(snes_to_pc(room_start_address), rom)
|
||||
rom.write_bytes(snes_to_pc(0x1F83C0 + room_id * 3), int24_as_bytes(room_start_address + door_start))
|
||||
room_start_address += bytes_written
|
||||
if room_start_address > 0x380000:
|
||||
raise Exception('Room list exceeded bank size')
|
||||
# size notes: bank 03 uses 140E bytes
|
||||
# bank 0A uses 372A bytes
|
||||
# bank 1F uses 77CE bytes: total is about a bank and a half
|
||||
# probably should reuse bank 1F if writing all the rooms out
|
||||
for sheet in self.sprite_sheets.values():
|
||||
sheet.write_to_rom(rom, snes_to_pc(0x00DB97)) # bank 00, SheetsTable_AA3
|
||||
if self.uw_enemy_table.size() > 0x2800:
|
||||
raise Exception('Sprite table is too big for current area')
|
||||
self.uw_enemy_table.write_sprite_data_to_rom(rom)
|
||||
self.uw_enemy_table.check_special_bitmasks_size()
|
||||
self.uw_enemy_table.write_special_bitmask_table(rom)
|
||||
for area_id, sheet in self.overworld_sprite_sheets.items():
|
||||
if area_id in [0x80, 0x81]:
|
||||
offset = area_id - 0x80 # 02E575 for special areas?
|
||||
rom.write_byte(snes_to_pc(0x02E576+offset), sheet.id)
|
||||
else:
|
||||
offset = convert_area_id_to_offset(area_id)
|
||||
rom.write_byte(snes_to_pc(0x00FA81+offset), sheet.id)
|
||||
# _00FA81 is LW normal
|
||||
# _00FAC1 is LW post-aga
|
||||
# _00FB01 is DW
|
||||
self.write_ow_sprite_data_to_rom(rom)
|
||||
for sprite, stats in self.enemy_stats.items():
|
||||
# write health to rom
|
||||
if stats.health is not None:
|
||||
if isinstance(stats.health, tuple):
|
||||
if sprite == EnemySprite.Octorok4Way: # skip this one
|
||||
continue
|
||||
if sprite in special_health_table:
|
||||
a1, a2 = special_health_table[sprite]
|
||||
rom.write_byte(snes_to_pc(a1), stats.health[0])
|
||||
rom.write_byte(snes_to_pc(a2), stats.health[1])
|
||||
else:
|
||||
rom.write_byte(snes_to_pc(0x0DB173+int(sprite)), stats.health)
|
||||
# write damage class to rom
|
||||
if stats.damage is not None:
|
||||
if isinstance(stats.damage, tuple):
|
||||
if sprite == EnemySprite.Octorok4Way: # skip this one
|
||||
continue
|
||||
if sprite in special_damage_table:
|
||||
a1, a2 = special_damage_table[sprite]
|
||||
rom.write_byte(snes_to_pc(a1), stats.dmask | stats.damage[0])
|
||||
rom.write_byte(snes_to_pc(a2), stats.dmask | stats.damage[1])
|
||||
else:
|
||||
rom.write_byte(snes_to_pc(0x0DB266+int(sprite)), stats.dmask | stats.damage)
|
||||
# write damage table to rom
|
||||
for idx, damage_list in self.enemy_damage.items():
|
||||
rom.write_bytes(snes_to_pc(0x06F42D + idx * 3), damage_list)
|
||||
# write bush spawns to rom:
|
||||
for area_id, bush_sprite in self.bush_sprite_table.items():
|
||||
rom.write_byte(snes_to_pc(0x368120 + area_id), bush_sprite.sprite)
|
||||
if increase_bush_sprite_chance:
|
||||
rom.write_bytes(snes_to_pc(0x1AFBBB), [
|
||||
0x01, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x12,
|
||||
0x0F, 0x01, 0x0F, 0x0F, 0x11, 0x0F, 0x0F, 0x03
|
||||
])
|
||||
|
||||
def write_ow_sprite_data_to_rom(self, rom):
|
||||
# calculate how big this table is going to be?
|
||||
# bytes = sum(1+len(x)*3 for x in self.ow_enemy_table.values() if len(x) > 0)+1
|
||||
# ending_byte = 0x09CB3B + bytes
|
||||
max_per_state = {0: 0x40, 1: 0x90, 2: 0x8D} # dropped max on state 2 to steal space for a couple extra sprites (Murahdahla)
|
||||
pointer_address = snes_to_pc(0x09C881)
|
||||
data_pointer = snes_to_pc(0x09CB3B) # was originally 0x09CB41 - stealing space for a couple extra sprites (Murahdahla)
|
||||
empty_pointer = pc_to_snes(data_pointer) & 0xFFFF
|
||||
rom.write_byte(data_pointer, 0xff)
|
||||
cached_dark_world = {}
|
||||
data_pointer += 1
|
||||
for state in range(0, 3):
|
||||
if state > 0: # move pointer to next section
|
||||
pointer_address += max_per_state[state-1] * 2
|
||||
for screen in range(0, max_per_state[state]):
|
||||
internal_screen_id = screen
|
||||
if state == 0:
|
||||
internal_screen_id += 0x200
|
||||
if state == 2 and screen < 0x40:
|
||||
internal_screen_id += 0x90
|
||||
# has no sprites
|
||||
if internal_screen_id not in self.ow_enemy_table or len(self.ow_enemy_table[internal_screen_id]) == 0:
|
||||
rom.write_bytes(pointer_address + screen * 2, int16_as_bytes(empty_pointer))
|
||||
else:
|
||||
if state == 2 and screen >= 0x40: # state 2 uses state 1 pointer for screens >= 0x40
|
||||
rom.write_bytes(pointer_address + screen * 2, cached_dark_world[screen])
|
||||
# the sprites are already written out
|
||||
elif len(self.ow_enemy_table[internal_screen_id]) > 0:
|
||||
data_address = pc_to_snes(data_pointer) & 0xFFFF
|
||||
ref = int16_as_bytes(data_address)
|
||||
if screen >= 40:
|
||||
cached_dark_world[screen] = ref
|
||||
rom.write_bytes(pointer_address + screen * 2, ref)
|
||||
for sprite in self.ow_enemy_table[internal_screen_id]:
|
||||
data = sprite.sprite_data()
|
||||
rom.write_bytes(data_pointer, data)
|
||||
data_pointer += len(data)
|
||||
rom.write_byte(data_pointer, 0xff)
|
||||
data_pointer += 1
|
||||
|
||||
|
||||
special_health_table = {
|
||||
EnemySprite.Octorok: (0x068F76, 0x068F77),
|
||||
EnemySprite.HardhatBeetle: (0x06911F, 0x069120),
|
||||
EnemySprite.Tektite: (0x068D97, 0x068D98),
|
||||
EnemySprite.CricketRat: (0x068876, 0x068877),
|
||||
EnemySprite.Keese: (0x06888A, 0x06888B),
|
||||
EnemySprite.Snake: (0x0688A6, 0x0688A7),
|
||||
EnemySprite.Raven: (0x068965, 0x068966)
|
||||
}
|
||||
|
||||
special_damage_table = {
|
||||
EnemySprite.Octorok: (0x068F74, 0x068F75),
|
||||
EnemySprite.Tektite: (0x068D99, 0x068D9A),
|
||||
EnemySprite.CricketRat: (0x068874, 0x068875),
|
||||
EnemySprite.Keese: (0x068888, 0x068889),
|
||||
EnemySprite.Snake: (0x0688A4, 0x0688A5),
|
||||
EnemySprite.Raven: (0x068963, 0x068964)
|
||||
}
|
||||
|
||||
|
||||
def init_data_tables(world, player):
|
||||
data_tables = DataTables()
|
||||
data_tables.room_headers = init_room_headers()
|
||||
data_tables.room_list = {}
|
||||
if world.pottery[player] not in ['none']:
|
||||
data_tables.room_list[0x0127] = Room0127
|
||||
data_tables.sprite_requirements = init_sprite_requirements()
|
||||
data_tables.sprite_sheets = init_sprite_sheets(data_tables.sprite_requirements)
|
||||
init_vanilla_sprites()
|
||||
data_tables.enemy_stats = init_enemy_stats()
|
||||
uw_table = data_tables.uw_enemy_table = EnemyTable()
|
||||
for room, sprite_list in vanilla_sprites.items():
|
||||
for sprite in sprite_list:
|
||||
uw_table.room_map[room].append(sprite.copy())
|
||||
data_tables.overworld_sprite_sheets = {}
|
||||
data_tables.ow_enemy_table = defaultdict(list)
|
||||
init_vanilla_sprites_ow()
|
||||
for area, sprite_list in vanilla_sprites_ow.items():
|
||||
for sprite in sprite_list:
|
||||
if sprite.bonk and world.shuffle_bonk_drops[player]:
|
||||
sprite.kind = EnemySprite.GreenRupee
|
||||
data_tables.ow_enemy_table[area].append(sprite.copy())
|
||||
data_tables.enemy_damage = {k: list(v) for k, v in world.damage_table[player].enemy_damage.items()}
|
||||
# todo: more denials based on enemy drops
|
||||
return data_tables
|
||||
|
||||
|
||||
def get_uw_enemy_table():
|
||||
init_vanilla_sprites()
|
||||
uw_table = EnemyTable()
|
||||
for room, sprite_list in vanilla_sprites.items():
|
||||
for sprite in sprite_list:
|
||||
uw_table.room_map[room].append(sprite.copy())
|
||||
return uw_table
|
||||
|
||||
1
source/rom/__init__.py
Normal file
1
source/rom/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
# do nothing, just exist to make "source" package
|
||||
@@ -32,6 +32,39 @@ def roll_settings(weights):
|
||||
return default
|
||||
return choice
|
||||
|
||||
def get_choice_bool(option, root=weights):
|
||||
choice = get_choice(option, root)
|
||||
if choice is True or choice == 'on':
|
||||
return True
|
||||
if choice is False or choice == 'off':
|
||||
return False
|
||||
if choice is None:
|
||||
return choice
|
||||
raise Exception("This fields needs to be true/false or off/on")
|
||||
|
||||
def get_choice_non_bool(option, root=weights):
|
||||
choice = get_choice(option, root)
|
||||
if choice is True or choice == 'on':
|
||||
return 'on'
|
||||
if choice is False or choice == 'off':
|
||||
return 'off'
|
||||
return choice
|
||||
|
||||
def get_choice_yn(option, root=weights):
|
||||
choice = get_choice(option, root)
|
||||
if choice is True or choice == 'yes':
|
||||
return 'yes'
|
||||
if choice is False or choice == 'no':
|
||||
return 'no'
|
||||
return choice
|
||||
|
||||
|
||||
def get_choice_bool_default(option, root=weights, default=None):
|
||||
choice = get_choice_bool(option, root)
|
||||
if choice is None and default is not None:
|
||||
return default
|
||||
return choice
|
||||
|
||||
while True:
|
||||
subweights = weights.get('subweights', {})
|
||||
if len(subweights) == 0:
|
||||
@@ -46,9 +79,10 @@ def roll_settings(weights):
|
||||
|
||||
ret.algorithm = get_choice('algorithm')
|
||||
|
||||
glitch_map = {'none': 'noglitches', 'minorglitches': 'minorglitches', 'no_logic': 'nologic',
|
||||
glitch_map = {'none': 'noglitches', 'minorglitches': 'minorglitches',
|
||||
'hmg': 'hybridglitches', 'hybridglitches': 'hybridglitches',
|
||||
'owg': 'owglitches', 'owglitches': 'owglitches'}
|
||||
'owg': 'owglitches', 'owglitches': 'owglitches',
|
||||
'no_logic': 'nologic'}
|
||||
glitches_required = get_choice('glitches_required')
|
||||
if glitches_required is not None:
|
||||
if glitches_required not in glitch_map.keys():
|
||||
@@ -62,8 +96,8 @@ def roll_settings(weights):
|
||||
dungeon_items = get_choice('dungeon_items')
|
||||
dungeon_items = '' if dungeon_items == 'standard' or dungeon_items is None else dungeon_items
|
||||
dungeon_items = 'mcsb' if dungeon_items == 'full' else dungeon_items
|
||||
ret.mapshuffle = get_choice('map_shuffle') == 'on' if 'map_shuffle' in weights else 'm' in dungeon_items
|
||||
ret.compassshuffle = get_choice('compass_shuffle') == 'on' if 'compass_shuffle' in weights else 'c' in dungeon_items
|
||||
ret.mapshuffle = get_choice_bool('map_shuffle') if 'map_shuffle' in weights else 'm' in dungeon_items
|
||||
ret.compassshuffle = get_choice_bool('compass_shuffle') if 'compass_shuffle' in weights else 'c' in dungeon_items
|
||||
if 'smallkey_shuffle' in weights:
|
||||
ret.keyshuffle = get_choice('smallkey_shuffle')
|
||||
else:
|
||||
@@ -71,23 +105,23 @@ def roll_settings(weights):
|
||||
ret.keyshuffle = 'wild'
|
||||
if 'u' in dungeon_items:
|
||||
ret.keyshuffle = 'universal'
|
||||
ret.bigkeyshuffle = get_choice('bigkey_shuffle') == 'on' if 'bigkey_shuffle' in weights else 'b' in dungeon_items
|
||||
ret.bigkeyshuffle = get_choice_bool('bigkey_shuffle') if 'bigkey_shuffle' in weights else 'b' in dungeon_items
|
||||
|
||||
ret.accessibility = get_choice('accessibility')
|
||||
ret.restrict_boss_items = get_choice('restrict_boss_items')
|
||||
|
||||
overworld_shuffle = get_choice('overworld_shuffle')
|
||||
ret.ow_shuffle = overworld_shuffle if overworld_shuffle != 'none' else 'vanilla'
|
||||
ret.ow_terrain = get_choice('overworld_terrain') == 'on'
|
||||
ret.ow_terrain = get_choice_bool('overworld_terrain')
|
||||
valid_options = {'none': 'none', 'polar': 'polar', 'grouped': 'polar', 'chaos': 'unrestricted', 'unrestricted': 'unrestricted'}
|
||||
ret.ow_crossed = get_choice('overworld_crossed')
|
||||
ret.ow_crossed = valid_options[ret.ow_crossed] if ret.ow_crossed in valid_options else 'none'
|
||||
ret.ow_keepsimilar = get_choice('overworld_keepsimilar') == 'on'
|
||||
ret.ow_mixed = get_choice('overworld_swap') == 'on'
|
||||
ret.ow_whirlpool = get_choice('whirlpool_shuffle') == 'on'
|
||||
ret.ow_keepsimilar = get_choice_bool('overworld_keepsimilar')
|
||||
ret.ow_mixed = get_choice_bool('overworld_swap')
|
||||
ret.ow_whirlpool = get_choice_bool('whirlpool_shuffle')
|
||||
overworld_flute = get_choice('flute_shuffle')
|
||||
ret.ow_fluteshuffle = overworld_flute if overworld_flute != 'none' else 'vanilla'
|
||||
ret.bonk_drops = get_choice('bonk_drops') == 'on'
|
||||
ret.bonk_drops = get_choice_bool('bonk_drops')
|
||||
entrance_shuffle = get_choice('entrance_shuffle')
|
||||
ret.shuffle = entrance_shuffle if entrance_shuffle != 'none' else 'vanilla'
|
||||
overworld_map = get_choice('overworld_map')
|
||||
@@ -98,29 +132,30 @@ def roll_settings(weights):
|
||||
ret.door_type_mode = get_choice('door_type_mode')
|
||||
ret.trap_door_mode = get_choice('trap_door_mode')
|
||||
ret.key_logic_algorithm = get_choice('key_logic_algorithm')
|
||||
ret.decoupledoors = get_choice('decoupledoors') == 'on'
|
||||
ret.door_self_loops = get_choice('door_self_loops') == 'on'
|
||||
ret.experimental = get_choice('experimental') == 'on'
|
||||
ret.collection_rate = get_choice('collection_rate') == 'on'
|
||||
ret.decoupledoors = get_choice_bool('decoupledoors')
|
||||
ret.door_self_loops = get_choice_bool('door_self_loops')
|
||||
ret.experimental = get_choice_bool('experimental')
|
||||
ret.collection_rate = get_choice_bool('collection_rate')
|
||||
|
||||
ret.dungeon_counters = get_choice('dungeon_counters') if 'dungeon_counters' in weights else 'default'
|
||||
ret.dungeon_counters = get_choice_non_bool('dungeon_counters') if 'dungeon_counters' in weights else 'default'
|
||||
if ret.dungeon_counters == 'default':
|
||||
ret.dungeon_counters = 'pickup' if ret.door_shuffle != 'vanilla' or ret.compassshuffle == 'on' else 'off'
|
||||
|
||||
ret.pseudoboots = get_choice('pseudoboots') == 'on'
|
||||
ret.shopsanity = get_choice('shopsanity') == 'on'
|
||||
keydropshuffle = get_choice('keydropshuffle') == 'on'
|
||||
ret.dropshuffle = get_choice('dropshuffle') == 'on' or keydropshuffle
|
||||
ret.pseudoboots = get_choice_bool('pseudoboots')
|
||||
ret.shopsanity = get_choice_bool('shopsanity')
|
||||
keydropshuffle = get_choice_bool('keydropshuffle')
|
||||
ret.dropshuffle = get_choice('dropshuffle') if 'dropshuffle' in weights else 'none'
|
||||
ret.dropshuffle = 'keys' if ret.dropshuffle == 'none' and keydropshuffle else ret.dropshuffle
|
||||
ret.pottery = get_choice('pottery') if 'pottery' in weights else 'none'
|
||||
ret.pottery = 'keys' if ret.pottery == 'none' and keydropshuffle else ret.pottery
|
||||
ret.colorizepots = get_choice_default('colorizepots', default='on') == 'on'
|
||||
ret.shufflepots = get_choice('pot_shuffle') == 'on'
|
||||
ret.aga_randomness = get_choice('aga_randomness') == 'on'
|
||||
ret.colorizepots = get_choice_bool_default('colorizepots', default=True)
|
||||
ret.shufflepots = get_choice_bool('pot_shuffle')
|
||||
ret.aga_randomness = get_choice_bool('aga_randomness')
|
||||
ret.mixed_travel = get_choice('mixed_travel') if 'mixed_travel' in weights else 'prevent'
|
||||
ret.standardize_palettes = (get_choice('standardize_palettes') if 'standardize_palettes' in weights
|
||||
else 'standardize')
|
||||
|
||||
goal = get_choice('goals')
|
||||
goal = get_choice_default('goals', default='ganon')
|
||||
if goal is not None:
|
||||
ret.goal = {'ganon': 'ganon',
|
||||
'fast_ganon': 'crystals',
|
||||
@@ -134,9 +169,9 @@ def roll_settings(weights):
|
||||
|
||||
ret.openpyramid = get_choice('open_pyramid') if 'open_pyramid' in weights else 'auto'
|
||||
|
||||
ret.shuffleganon = get_choice('shuffleganon') == 'on'
|
||||
ret.shufflelinks = get_choice('shufflelinks') == 'on'
|
||||
ret.shuffletavern = get_choice('shuffletavern') == 'on'
|
||||
ret.shuffleganon = get_choice_bool('shuffleganon')
|
||||
ret.shufflelinks = get_choice_bool('shufflelinks')
|
||||
ret.shuffletavern = get_choice_bool('shuffletavern')
|
||||
|
||||
ret.crystals_gt = get_choice('tower_open')
|
||||
ret.crystals_ganon = get_choice('ganon_open')
|
||||
@@ -154,12 +189,12 @@ def roll_settings(weights):
|
||||
if ret.mode == 'retro':
|
||||
ret.mode = 'open'
|
||||
ret.retro = True
|
||||
ret.retro = get_choice('retro') == 'on' # this overrides world_state if used
|
||||
ret.retro = get_choice_bool('retro') # this overrides world_state if used
|
||||
ret.take_any = get_choice_default('take_any', default='none')
|
||||
|
||||
ret.bombbag = get_choice('bombbag') == 'on'
|
||||
ret.bombbag = get_choice_bool('bombbag')
|
||||
|
||||
ret.hints = get_choice('hints') == 'on'
|
||||
ret.hints = get_choice_bool('hints')
|
||||
|
||||
swords = get_choice('weapons')
|
||||
if swords is not None:
|
||||
@@ -196,6 +231,7 @@ def roll_settings(weights):
|
||||
ret.enemy_damage = damage_choice
|
||||
|
||||
ret.enemy_health = get_choice('enemy_health')
|
||||
ret.any_enemy_logic = get_choice('any_enemy_logic')
|
||||
|
||||
ret.beemizer = get_choice('beemizer') if 'beemizer' in weights else '0'
|
||||
|
||||
@@ -211,18 +247,17 @@ def roll_settings(weights):
|
||||
if 'rom' in weights:
|
||||
romweights = weights['rom']
|
||||
ret.sprite = get_choice('sprite', romweights)
|
||||
ret.disablemusic = get_choice('disablemusic', romweights) == 'on'
|
||||
ret.quickswap = get_choice('quickswap', romweights) == 'on'
|
||||
ret.reduce_flashing = get_choice('reduce_flashing', romweights) == 'on'
|
||||
ret.msu_resume = get_choice('msu_resume', romweights) == 'on'
|
||||
ret.disablemusic = get_choice_bool('disablemusic', romweights)
|
||||
ret.quickswap = get_choice_bool('quickswap', romweights)
|
||||
ret.reduce_flashing = get_choice_bool('reduce_flashing', romweights)
|
||||
ret.fastmenu = get_choice('menuspeed', romweights)
|
||||
ret.heartcolor = get_choice('heartcolor', romweights)
|
||||
ret.heartbeep = get_choice('heartbeep', romweights)
|
||||
ret.heartbeep = get_choice_non_bool('heartbeep', romweights)
|
||||
ret.ow_palettes = get_choice('ow_palettes', romweights)
|
||||
ret.uw_palettes = get_choice('uw_palettes', romweights)
|
||||
ret.shuffle_sfx = get_choice('shuffle_sfx', romweights) == 'on'
|
||||
ret.shuffle_sfxinstruments = get_choice('shuffle_sfxinstruments', romweights) == 'on'
|
||||
ret.shuffle_songinstruments = get_choice('shuffle_songinstruments', romweights) == 'on'
|
||||
ret.msu_resume = get_choice('msu_resume', romweights) == 'on'
|
||||
ret.shuffle_sfx = get_choice_bool('shuffle_sfx', romweights)
|
||||
ret.shuffle_sfxinstruments = get_choice_bool('shuffle_sfxinstruments', romweights)
|
||||
ret.shuffle_songinstruments = get_choice_bool('shuffle_songinstruments', romweights)
|
||||
ret.msu_resume = get_choice_bool('msu_resume', romweights)
|
||||
|
||||
return ret
|
||||
|
||||
Reference in New Issue
Block a user