Add cane-only modes
This commit is contained in:
128
BaseClasses.py
128
BaseClasses.py
@@ -365,6 +365,19 @@ class World(object):
|
|||||||
ret.prog_items['L2 Bombs', item.player] += 1
|
ret.prog_items['L2 Bombs', item.player] += 1
|
||||||
else:
|
else:
|
||||||
ret.prog_items['L1 Bombs', item.player] += 1
|
ret.prog_items['L1 Bombs', item.player] += 1
|
||||||
|
elif 'Cane' in item.name:
|
||||||
|
if ret.has('L5 Cane', item.player):
|
||||||
|
pass
|
||||||
|
elif ret.has('L4 Cane', item.player):
|
||||||
|
ret.prog_items['L5 Cane', item.player] += 1
|
||||||
|
elif ret.has('L3 Cane', item.player):
|
||||||
|
ret.prog_items['L4 Cane', item.player] += 1
|
||||||
|
elif ret.has('L2 Cane', item.player):
|
||||||
|
ret.prog_items['L3 Cane', item.player] += 1
|
||||||
|
elif ret.has('L1 Cane', item.player):
|
||||||
|
ret.prog_items['L2 Cane', item.player] += 1
|
||||||
|
else:
|
||||||
|
ret.prog_items['L1 Cane', item.player] += 1
|
||||||
elif 'Glove' in item.name:
|
elif 'Glove' in item.name:
|
||||||
if ret.has('Titans Mitts', item.player):
|
if ret.has('Titans Mitts', item.player):
|
||||||
pass
|
pass
|
||||||
@@ -393,6 +406,11 @@ class World(object):
|
|||||||
ret.prog_items[item.name, item.player] += 1
|
ret.prog_items[item.name, item.player] += 1
|
||||||
elif item.advancement or item.smallkey or item.bigkey:
|
elif item.advancement or item.smallkey or item.bigkey:
|
||||||
ret.prog_items[item.name, item.player] += 1
|
ret.prog_items[item.name, item.player] += 1
|
||||||
|
if item.name.endswith(' Cane'):
|
||||||
|
if ret.world.swords[item.player] == 'byrna' and not ret.has('Cane of Byrna', item.player):
|
||||||
|
ret.prog_items['Cane of Byrna', item.player] += 1
|
||||||
|
if ret.world.swords[item.player] == 'somaria' and not ret.has('Cane of Somaria', item.player):
|
||||||
|
ret.prog_items['Cane of Somaria', item.player] += 1
|
||||||
|
|
||||||
for item in self.itempool:
|
for item in self.itempool:
|
||||||
soft_collect(item)
|
soft_collect(item)
|
||||||
@@ -1239,8 +1257,8 @@ class CollectionState(object):
|
|||||||
return basemagic >= smallmagic
|
return basemagic >= smallmagic
|
||||||
|
|
||||||
def can_kill_most_things(self, player, enemies=5):
|
def can_kill_most_things(self, player, enemies=5):
|
||||||
return (self.bomb_mode_check(player, 1) and
|
return (self.special_weapon_check(player, 1) and
|
||||||
(self.has_blunt_weapon(player) or self.has_bomb_level(player, 1)
|
(self.has_blunt_weapon(player) or self.has_special_weapon_level(player, 1)
|
||||||
or self.has('Cane of Somaria', player)
|
or self.has('Cane of Somaria', player)
|
||||||
or (self.has('Cane of Byrna', player) and (enemies < 6 or self.can_extend_magic(player)))
|
or (self.has('Cane of Byrna', player) and (enemies < 6 or self.can_extend_magic(player)))
|
||||||
or self.can_shoot_arrows(player)
|
or self.can_shoot_arrows(player)
|
||||||
@@ -1259,7 +1277,7 @@ class CollectionState(object):
|
|||||||
# In the future, this can be used to check if the player starts without bombs
|
# In the future, this can be used to check if the player starts without bombs
|
||||||
def can_use_bombs(self, player):
|
def can_use_bombs(self, player):
|
||||||
if self.world.swords[player] == 'bombs':
|
if self.world.swords[player] == 'bombs':
|
||||||
return self.has_bomb_level(player, 1)
|
return self.has_special_weapon_level(player, 1)
|
||||||
return (not self.world.bombbag[player] or self.has('Bomb Upgrade (+10)', player)) and ((hasattr(self.world, "override_bomb_check") and self.world.override_bomb_check) or self.can_farm_bombs(player))
|
return (not self.world.bombbag[player] or self.has('Bomb Upgrade (+10)', player)) and ((hasattr(self.world, "override_bomb_check") and self.world.override_bomb_check) or self.can_farm_bombs(player))
|
||||||
|
|
||||||
def can_hit_crystal(self, player):
|
def can_hit_crystal(self, player):
|
||||||
@@ -1316,23 +1334,41 @@ class CollectionState(object):
|
|||||||
return False;
|
return False;
|
||||||
return self.has_sword(player, level)
|
return self.has_sword(player, level)
|
||||||
|
|
||||||
def has_bomb_level(self, player, level):
|
def has_special_weapon_level(self, player, level):
|
||||||
if self.world.swords[player] != 'bombs':
|
if self.world.swords[player] == 'bombs':
|
||||||
|
if level == 5:
|
||||||
|
return self.has('L5 Bombs', player)
|
||||||
|
elif level == 4:
|
||||||
|
return self.has('L5 Bombs', player) or self.has('L4 Bombs', player)
|
||||||
|
elif level == 3:
|
||||||
|
return self.has('L5 Bombs', player) or self.has('L4 Bombs', player) or self.has('L3 Bombs', player)
|
||||||
|
elif level == 2:
|
||||||
|
return self.has('L5 Bombs', player) or self.has('L4 Bombs', player) or self.has('L3 Bombs', player) or self.has('L2 Bombs', player)
|
||||||
|
elif level == 1:
|
||||||
|
return self.has('L5 Bombs', player) or self.has('L4 Bombs', player) or self.has('L3 Bombs', player) or self.has('L2 Bombs', player) or self.has('L1 Bombs', player)
|
||||||
|
return True
|
||||||
|
elif self.world.swords[player] in ['byrna', 'somaria', 'cane']:
|
||||||
|
if self.world.swords[player] == 'cane' and not self.has('Cane of Somaria', player) and not self.has('Cane of Byrna', player):
|
||||||
|
return False
|
||||||
|
if level == 5:
|
||||||
|
return self.has('L5 Cane', player)
|
||||||
|
elif level == 4:
|
||||||
|
return self.has('L5 Cane', player) or self.has('L4 Cane', player)
|
||||||
|
elif level == 3:
|
||||||
|
return self.has('L5 Cane', player) or self.has('L4 Cane', player) or self.has('L3 Cane', player)
|
||||||
|
elif level == 2:
|
||||||
|
return self.has('L5 Cane', player) or self.has('L4 Cane', player) or self.has('L3 Cane', player) or self.has('L2 Cane', player)
|
||||||
|
elif level == 1:
|
||||||
|
return self.has('L5 Cane', player) or self.has('L4 Cane', player) or self.has('L3 Cane', player) or self.has('L2 Cane', player) or self.has('L1 Cane', player)
|
||||||
|
return True
|
||||||
|
else:
|
||||||
return False
|
return False
|
||||||
if level == 5:
|
|
||||||
return self.has('L5 Bombs', player)
|
|
||||||
elif level == 4:
|
|
||||||
return self.has('L5 Bombs', player) or self.has('L4 Bombs', player)
|
|
||||||
elif level == 3:
|
|
||||||
return self.has('L5 Bombs', player) or self.has('L4 Bombs', player) or self.has('L3 Bombs', player)
|
|
||||||
elif level == 2:
|
|
||||||
return self.has('L5 Bombs', player) or self.has('L4 Bombs', player) or self.has('L3 Bombs', player) or self.has('L2 Bombs', player)
|
|
||||||
elif level == 1:
|
|
||||||
return self.has('L5 Bombs', player) or self.has('L4 Bombs', player) or self.has('L3 Bombs', player) or self.has('L2 Bombs', player) or self.has('L1 Bombs', player)
|
|
||||||
return True
|
|
||||||
|
|
||||||
def bomb_mode_check(self, player, level):
|
def special_weapon_check(self, player, level):
|
||||||
return self.world.swords[player] != 'bombs' or self.has_bomb_level(player, level)
|
if self.world.swords[player] in ['bombs', 'byrna', 'somaria', 'cane']:
|
||||||
|
return self.has_special_weapon_level(player, level)
|
||||||
|
else:
|
||||||
|
return True
|
||||||
|
|
||||||
def can_hit_stunned_ganon(self, player):
|
def can_hit_stunned_ganon(self, player):
|
||||||
ganon_item = self.world.ganon_item[player]
|
ganon_item = self.world.ganon_item[player]
|
||||||
@@ -1375,7 +1411,7 @@ class CollectionState(object):
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
def can_use_medallions(self, player):
|
def can_use_medallions(self, player):
|
||||||
return self.has_sword(player) or self.world.swords[player] == 'bombs'
|
return self.has_sword(player) or self.world.swords[player] in ['bombs', 'byrna', 'somaria', 'cane']
|
||||||
|
|
||||||
def has_blunt_weapon(self, player):
|
def has_blunt_weapon(self, player):
|
||||||
return self.has_real_sword(player) or self.has('Hammer', player)
|
return self.has_real_sword(player) or self.has('Hammer', player)
|
||||||
@@ -1491,6 +1527,24 @@ class CollectionState(object):
|
|||||||
else:
|
else:
|
||||||
self.prog_items['L1 Bombs', item.player] += 1
|
self.prog_items['L1 Bombs', item.player] += 1
|
||||||
changed = True
|
changed = True
|
||||||
|
elif 'Cane' in item.name:
|
||||||
|
if self.has('L5 Cane', item.player):
|
||||||
|
pass
|
||||||
|
elif self.has('L4 Cane', item.player):
|
||||||
|
self.prog_items['L5 Cane', item.player] += 1
|
||||||
|
changed = True
|
||||||
|
elif self.has('L3 Cane', item.player):
|
||||||
|
self.prog_items['L4 Cane', item.player] += 1
|
||||||
|
changed = True
|
||||||
|
elif self.has('L2 Cane', item.player):
|
||||||
|
self.prog_items['L3 Cane', item.player] += 1
|
||||||
|
changed = True
|
||||||
|
elif self.has('L1 Cane', item.player):
|
||||||
|
self.prog_items['L2 Cane', item.player] += 1
|
||||||
|
changed = True
|
||||||
|
else:
|
||||||
|
self.prog_items['L1 Cane', item.player] += 1
|
||||||
|
changed = True
|
||||||
elif 'Glove' in item.name:
|
elif 'Glove' in item.name:
|
||||||
if self.has('Titans Mitts', item.player):
|
if self.has('Titans Mitts', item.player):
|
||||||
pass
|
pass
|
||||||
@@ -1541,6 +1595,13 @@ class CollectionState(object):
|
|||||||
elif event or item.advancement:
|
elif event or item.advancement:
|
||||||
self.prog_items[item.name, item.player] += 1
|
self.prog_items[item.name, item.player] += 1
|
||||||
changed = True
|
changed = True
|
||||||
|
if item.name.endswith(' Cane'):
|
||||||
|
if self.world.swords[item.player] == 'byrna' and not self.has('Cane of Byrna', item.player):
|
||||||
|
self.prog_items['Cane of Byrna', item.player] += 1
|
||||||
|
changed = True
|
||||||
|
if self.world.swords[item.player] == 'somaria' and not self.has('Cane of Somaria', item.player):
|
||||||
|
self.prog_items['Cane of Somaria', item.player] += 1
|
||||||
|
changed = True
|
||||||
|
|
||||||
self.stale[item.player] = True
|
self.stale[item.player] = True
|
||||||
|
|
||||||
@@ -1576,6 +1637,19 @@ class CollectionState(object):
|
|||||||
to_remove = 'L1 Bombs'
|
to_remove = 'L1 Bombs'
|
||||||
else:
|
else:
|
||||||
to_remove = None
|
to_remove = None
|
||||||
|
elif 'Cane' in to_remove:
|
||||||
|
if self.has('L5 Cane', item.player):
|
||||||
|
to_remove = 'L5 Cane'
|
||||||
|
elif self.has('L4 Cane', item.player):
|
||||||
|
to_remove = 'L4 Cane'
|
||||||
|
elif self.has('L3 Cane', item.player):
|
||||||
|
to_remove = 'L3 Cane'
|
||||||
|
elif self.has('L2 Cane', item.player):
|
||||||
|
to_remove = 'L2 Cane'
|
||||||
|
elif self.has('L1 Cane', item.player):
|
||||||
|
to_remove = 'L1 Cane'
|
||||||
|
else:
|
||||||
|
to_remove = None
|
||||||
elif 'Glove' in item.name:
|
elif 'Glove' in item.name:
|
||||||
if self.has('Titans Mitts', item.player):
|
if self.has('Titans Mitts', item.player):
|
||||||
to_remove = 'Titans Mitts'
|
to_remove = 'Titans Mitts'
|
||||||
@@ -1601,7 +1675,15 @@ class CollectionState(object):
|
|||||||
to_remove = None
|
to_remove = None
|
||||||
|
|
||||||
if to_remove is not None:
|
if to_remove is not None:
|
||||||
|
if to_remove.endswith(' Cane') and not self.has('L5 Cane', item.player) and not self.has('L4 Cane', item.player) and not self.has('L3 Cane', item.player) and not self.has('L2 Cane', item.player) and not self.has('L1 Cane', item.player):
|
||||||
|
if self.world.swords[item.player] == 'byrna':
|
||||||
|
self.prog_items['Cane of Byrna', item.player] -= 1
|
||||||
|
if self.prog_items['Cane of Byrna', item.player] < 1:
|
||||||
|
del (self.prog_items['Cane of Byrna', item.player])
|
||||||
|
if self.world.swords[item.player] == 'somaria':
|
||||||
|
self.prog_items['Cane of Somaria', item.player] -= 1
|
||||||
|
if self.prog_items['Cane of Somaria', item.player] < 1:
|
||||||
|
del (self.prog_items['Cane of Somaria', item.player])
|
||||||
self.prog_items[to_remove, item.player] -= 1
|
self.prog_items[to_remove, item.player] -= 1
|
||||||
if self.prog_items[to_remove, item.player] < 1:
|
if self.prog_items[to_remove, item.player] < 1:
|
||||||
del (self.prog_items[to_remove, item.player])
|
del (self.prog_items[to_remove, item.player])
|
||||||
@@ -2940,8 +3022,8 @@ class Spoiler(object):
|
|||||||
'experimental': self.world.experimental,
|
'experimental': self.world.experimental,
|
||||||
'keydropshuffle': self.world.keydropshuffle,
|
'keydropshuffle': self.world.keydropshuffle,
|
||||||
'shopsanity': self.world.shopsanity,
|
'shopsanity': self.world.shopsanity,
|
||||||
'triforcegoal': self.world.treasure_hunt_count,
|
'triforcegoal': self.world.treasure_hunt_count,
|
||||||
'triforcepool': self.world.treasure_hunt_total,
|
'triforcepool': self.world.treasure_hunt_total,
|
||||||
'code': {p: Settings.make_code(self.world, p) for p in range(1, self.world.players + 1)}
|
'code': {p: Settings.make_code(self.world, p) for p in range(1, self.world.players + 1)}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3320,7 +3402,7 @@ er_mode = {"vanilla": 0, "simple": 1, "restricted": 2, "full": 3, "lite": 4, "le
|
|||||||
# byte 1: LLLW WSSS (logic, mode, sword)
|
# byte 1: LLLW WSSS (logic, mode, sword)
|
||||||
logic_mode = {"noglitches": 0, "minorglitches": 1, "nologic": 2, "owglitches": 3, "majorglitches": 4}
|
logic_mode = {"noglitches": 0, "minorglitches": 1, "nologic": 2, "owglitches": 3, "majorglitches": 4}
|
||||||
world_mode = {"open": 0, "standard": 1, "inverted": 2}
|
world_mode = {"open": 0, "standard": 1, "inverted": 2}
|
||||||
sword_mode = {"random": 0, "assured": 1, "swordless": 2, "vanilla": 3, "bombs": 4, "pseudo": 5, "assured_pseudo": 6}
|
sword_mode = {"random": 0, "assured": 1, "swordless": 2, "vanilla": 3, "bombs": 4, "pseudo": 5, "assured_pseudo": 5, "byrna": 6, "somaria": 6, "cane": 6}
|
||||||
|
|
||||||
# byte 2: GGGD DFFH (goal, diff, item_func, hints)
|
# byte 2: GGGD DFFH (goal, diff, item_func, hints)
|
||||||
goal_mode = {"ganon": 0, "pedestal": 1, "dungeons": 2, "triforcehunt": 3, "crystals": 4}
|
goal_mode = {"ganon": 0, "pedestal": 1, "dungeons": 2, "triforcehunt": 3, "crystals": 4}
|
||||||
|
|||||||
44
Bosses.py
44
Bosses.py
@@ -16,7 +16,7 @@ def BossFactory(boss, player):
|
|||||||
|
|
||||||
def ArmosKnightsDefeatRule(state, player):
|
def ArmosKnightsDefeatRule(state, player):
|
||||||
# Magic amounts are probably a bit overkill
|
# Magic amounts are probably a bit overkill
|
||||||
return (state.bomb_mode_check(player, 1) and
|
return (state.special_weapon_check(player, 1) and
|
||||||
(state.has_blunt_weapon(player) or
|
(state.has_blunt_weapon(player) or
|
||||||
state.can_shoot_arrows(player) or
|
state.can_shoot_arrows(player) or
|
||||||
(state.has('Cane of Somaria', player) and state.can_extend_magic(player, 10)) or
|
(state.has('Cane of Somaria', player) and state.can_extend_magic(player, 10)) or
|
||||||
@@ -25,38 +25,38 @@ def ArmosKnightsDefeatRule(state, player):
|
|||||||
(state.has('Fire Rod', player) and state.can_extend_magic(player, 32)) or
|
(state.has('Fire Rod', player) and state.can_extend_magic(player, 32)) or
|
||||||
state.has('Blue Boomerang', player) or
|
state.has('Blue Boomerang', player) or
|
||||||
state.has('Red Boomerang', player) or
|
state.has('Red Boomerang', player) or
|
||||||
state.has_bomb_level(player, 1)))
|
state.has_special_weapon_level(player, 1)))
|
||||||
|
|
||||||
def LanmolasDefeatRule(state, player):
|
def LanmolasDefeatRule(state, player):
|
||||||
return (state.bomb_mode_check(player, 1) and
|
return (state.special_weapon_check(player, 1) and
|
||||||
(state.has_blunt_weapon(player) or
|
(state.has_blunt_weapon(player) or
|
||||||
state.has('Fire Rod', player) or
|
state.has('Fire Rod', player) or
|
||||||
state.has('Ice Rod', player) or
|
state.has('Ice Rod', player) or
|
||||||
state.has('Cane of Somaria', player) or
|
state.has('Cane of Somaria', player) or
|
||||||
state.has('Cane of Byrna', player) or
|
state.has('Cane of Byrna', player) or
|
||||||
state.can_shoot_arrows(player) or
|
state.can_shoot_arrows(player) or
|
||||||
state.has_bomb_level(player, 1)))
|
state.has_special_weapon_level(player, 1)))
|
||||||
|
|
||||||
def MoldormDefeatRule(state, player):
|
def MoldormDefeatRule(state, player):
|
||||||
return (state.bomb_mode_check(player, 1) and
|
return (state.special_weapon_check(player, 1) and
|
||||||
(state.has_blunt_weapon(player) or state.has_bomb_level(player, 1)))
|
(state.has_blunt_weapon(player) or state.has_special_weapon_level(player, 1)))
|
||||||
|
|
||||||
def HelmasaurKingDefeatRule(state, player):
|
def HelmasaurKingDefeatRule(state, player):
|
||||||
return (state.bomb_mode_check(player, 2) and
|
return (state.special_weapon_check(player, 2) and
|
||||||
(state.has('Hammer', player) or state.can_use_bombs(player)) and
|
(state.has('Hammer', player) or state.can_use_bombs(player)) and
|
||||||
(state.has_real_sword(player) or state.can_shoot_arrows(player) or state.has_bomb_level(player, 2)))
|
(state.has_real_sword(player) or state.can_shoot_arrows(player) or state.has_special_weapon_level(player, 2)))
|
||||||
|
|
||||||
def ArrghusDefeatRule(state, player):
|
def ArrghusDefeatRule(state, player):
|
||||||
if not state.has('Hookshot', player):
|
if not state.has('Hookshot', player):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
if not state.bomb_mode_check(player, 2):
|
if not state.special_weapon_check(player, 2):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# TODO: ideally we would have a check for bow and silvers, which combined with the
|
# TODO: ideally we would have a check for bow and silvers, which combined with the
|
||||||
# hookshot is enough. This is not coded yet because the silvers that only work in pyramid feature
|
# hookshot is enough. This is not coded yet because the silvers that only work in pyramid feature
|
||||||
# makes this complicated
|
# makes this complicated
|
||||||
if state.has_blunt_weapon(player) or state.has_bomb_level(player, 2):
|
if state.has_blunt_weapon(player) or state.has_special_weapon_level(player, 2):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
return ((state.has('Fire Rod', player) and (state.can_shoot_arrows(player) or state.can_extend_magic(player, 12))) or #assuming mostly gitting two puff with one shot
|
return ((state.has('Fire Rod', player) and (state.can_shoot_arrows(player) or state.can_extend_magic(player, 12))) or #assuming mostly gitting two puff with one shot
|
||||||
@@ -64,7 +64,7 @@ def ArrghusDefeatRule(state, player):
|
|||||||
|
|
||||||
|
|
||||||
def MothulaDefeatRule(state, player):
|
def MothulaDefeatRule(state, player):
|
||||||
return (state.bomb_mode_check(player, 1) and
|
return (state.special_weapon_check(player, 1) and
|
||||||
(state.has_blunt_weapon(player) or
|
(state.has_blunt_weapon(player) or
|
||||||
(state.has('Fire Rod', player) and state.can_extend_magic(player, 10)) or
|
(state.has('Fire Rod', player) and state.can_extend_magic(player, 10)) or
|
||||||
# TODO: Not sure how much (if any) extend magic is needed for these two, since they only apply
|
# TODO: Not sure how much (if any) extend magic is needed for these two, since they only apply
|
||||||
@@ -72,15 +72,15 @@ def MothulaDefeatRule(state, player):
|
|||||||
(state.has('Cane of Somaria', player) and state.can_extend_magic(player, 16)) or
|
(state.has('Cane of Somaria', player) and state.can_extend_magic(player, 16)) or
|
||||||
(state.has('Cane of Byrna', player) and state.can_extend_magic(player, 16)) or
|
(state.has('Cane of Byrna', player) and state.can_extend_magic(player, 16)) or
|
||||||
state.can_get_good_bee(player) or
|
state.can_get_good_bee(player) or
|
||||||
state.has_bomb_level(player, 1)))
|
state.has_special_weapon_level(player, 1)))
|
||||||
|
|
||||||
def BlindDefeatRule(state, player):
|
def BlindDefeatRule(state, player):
|
||||||
return (state.bomb_mode_check(player, 1) and
|
return (state.special_weapon_check(player, 1) and
|
||||||
(state.has_blunt_weapon(player) or state.has('Cane of Somaria', player) or
|
(state.has_blunt_weapon(player) or state.has('Cane of Somaria', player) or
|
||||||
state.has('Cane of Byrna', player) or state.has_bomb_level(player, 1)))
|
state.has('Cane of Byrna', player) or state.has_special_weapon_level(player, 1)))
|
||||||
|
|
||||||
def KholdstareDefeatRule(state, player):
|
def KholdstareDefeatRule(state, player):
|
||||||
return (state.bomb_mode_check(player, 2) and
|
return (state.special_weapon_check(player, 2) and
|
||||||
(
|
(
|
||||||
state.has('Fire Rod', player) or
|
state.has('Fire Rod', player) or
|
||||||
(
|
(
|
||||||
@@ -90,7 +90,7 @@ def KholdstareDefeatRule(state, player):
|
|||||||
)
|
)
|
||||||
) and
|
) and
|
||||||
(
|
(
|
||||||
state.has_bomb_level(player, 2) or state.has_blunt_weapon(player) or
|
state.has_special_weapon_level(player, 2) or state.has_blunt_weapon(player) or
|
||||||
(state.has('Fire Rod', player) and state.can_extend_magic(player, 20)) or
|
(state.has('Fire Rod', player) and state.can_extend_magic(player, 20)) or
|
||||||
# FIXME: this actually only works for the vanilla location for swordless
|
# FIXME: this actually only works for the vanilla location for swordless
|
||||||
(
|
(
|
||||||
@@ -102,21 +102,21 @@ def KholdstareDefeatRule(state, player):
|
|||||||
))
|
))
|
||||||
|
|
||||||
def VitreousDefeatRule(state, player):
|
def VitreousDefeatRule(state, player):
|
||||||
return (state.bomb_mode_check(player, 2) and
|
return (state.special_weapon_check(player, 2) and
|
||||||
(state.can_shoot_arrows(player) or state.has_blunt_weapon(player) or
|
(state.can_shoot_arrows(player) or state.has_blunt_weapon(player) or
|
||||||
state.has_bomb_level(player, 2)))
|
state.has_special_weapon_level(player, 2)))
|
||||||
|
|
||||||
def TrinexxDefeatRule(state, player):
|
def TrinexxDefeatRule(state, player):
|
||||||
if not (state.has('Fire Rod', player) and state.has('Ice Rod', player)):
|
if not (state.has('Fire Rod', player) and state.has('Ice Rod', player)):
|
||||||
return False
|
return False
|
||||||
if not state.bomb_mode_check(player, 2):
|
if not state.special_weapon_check(player, 2):
|
||||||
return False
|
return False
|
||||||
return (state.has('Hammer', player) or
|
return (state.has('Hammer', player) or
|
||||||
state.has_real_sword(player, 3) or
|
state.has_real_sword(player, 3) or
|
||||||
state.has_bomb_level(player, 4) or
|
state.has_special_weapon_level(player, 4) or
|
||||||
((state.has_real_sword(player, 2) or state.has_bomb_level(player, 3))
|
((state.has_real_sword(player, 2) or state.has_special_weapon_level(player, 3))
|
||||||
and state.can_extend_magic(player, 16)) or
|
and state.can_extend_magic(player, 16)) or
|
||||||
((state.has_real_sword(player) or state.has_bomb_level(player, 2))
|
((state.has_real_sword(player) or state.has_special_weapon_level(player, 2))
|
||||||
and state.can_extend_magic(player, 32)))
|
and state.can_extend_magic(player, 32)))
|
||||||
|
|
||||||
def AgahnimDefeatRule(state, player):
|
def AgahnimDefeatRule(state, player):
|
||||||
|
|||||||
36
ItemList.py
36
ItemList.py
@@ -34,7 +34,7 @@ normalfinal25extra = ['Rupees (20)'] * 23 + ['Rupees (5)'] * 2
|
|||||||
|
|
||||||
Difficulty = namedtuple('Difficulty',
|
Difficulty = namedtuple('Difficulty',
|
||||||
['baseitems', 'bottles', 'bottle_count', 'same_bottle', 'progressiveshield',
|
['baseitems', 'bottles', 'bottle_count', 'same_bottle', 'progressiveshield',
|
||||||
'basicshield', 'progressivearmor', 'basicarmor', 'swordless', 'bombs_only',
|
'basicshield', 'progressivearmor', 'basicarmor', 'swordless', 'bombs_only', 'cane_only',
|
||||||
'progressivesword', 'basicsword', 'basicbow', 'timedohko', 'timedother',
|
'progressivesword', 'basicsword', 'basicbow', 'timedohko', 'timedother',
|
||||||
'retro', 'bombbag',
|
'retro', 'bombbag',
|
||||||
'extras', 'progressive_sword_limit', 'progressive_shield_limit',
|
'extras', 'progressive_sword_limit', 'progressive_shield_limit',
|
||||||
@@ -55,6 +55,7 @@ difficulties = {
|
|||||||
basicarmor = ['Blue Mail', 'Red Mail'],
|
basicarmor = ['Blue Mail', 'Red Mail'],
|
||||||
swordless = ['Rupees (20)'] * 4,
|
swordless = ['Rupees (20)'] * 4,
|
||||||
bombs_only = ['Progressive Bombs'] * 4,
|
bombs_only = ['Progressive Bombs'] * 4,
|
||||||
|
cane_only = ['Progressive Cane'] * 3 + ['Rupees (20)'],
|
||||||
progressivesword = ['Progressive Sword'] * 4,
|
progressivesword = ['Progressive Sword'] * 4,
|
||||||
basicsword = ['Fighter Sword', 'Master Sword', 'Tempered Sword', 'Golden Sword'],
|
basicsword = ['Fighter Sword', 'Master Sword', 'Tempered Sword', 'Golden Sword'],
|
||||||
basicbow = ['Bow', 'Silver Arrows'],
|
basicbow = ['Bow', 'Silver Arrows'],
|
||||||
@@ -82,6 +83,7 @@ difficulties = {
|
|||||||
basicarmor = ['Progressive Armor'] * 2, # neither will count
|
basicarmor = ['Progressive Armor'] * 2, # neither will count
|
||||||
swordless = ['Rupees (20)'] * 4,
|
swordless = ['Rupees (20)'] * 4,
|
||||||
bombs_only = ['Progressive Bombs'] * 4,
|
bombs_only = ['Progressive Bombs'] * 4,
|
||||||
|
cane_only = ['Progressive Cane'] * 3 + ['Rupees (20)'],
|
||||||
progressivesword = ['Progressive Sword'] * 4,
|
progressivesword = ['Progressive Sword'] * 4,
|
||||||
basicsword = ['Fighter Sword', 'Master Sword', 'Master Sword', 'Tempered Sword'],
|
basicsword = ['Fighter Sword', 'Master Sword', 'Master Sword', 'Tempered Sword'],
|
||||||
basicbow = ['Bow'] * 2,
|
basicbow = ['Bow'] * 2,
|
||||||
@@ -109,6 +111,7 @@ difficulties = {
|
|||||||
basicarmor = ['Progressive Armor'] * 2, # neither will count
|
basicarmor = ['Progressive Armor'] * 2, # neither will count
|
||||||
swordless = ['Rupees (20)'] * 4,
|
swordless = ['Rupees (20)'] * 4,
|
||||||
bombs_only = ['Progressive Bombs'] * 4,
|
bombs_only = ['Progressive Bombs'] * 4,
|
||||||
|
cane_only = ['Progressive Cane'] * 3 + ['Rupees (20)'],
|
||||||
progressivesword = ['Progressive Sword'] * 4,
|
progressivesword = ['Progressive Sword'] * 4,
|
||||||
basicsword = ['Fighter Sword', 'Fighter Sword', 'Master Sword', 'Master Sword'],
|
basicsword = ['Fighter Sword', 'Fighter Sword', 'Master Sword', 'Master Sword'],
|
||||||
basicbow = ['Bow'] * 2,
|
basicbow = ['Bow'] * 2,
|
||||||
@@ -283,8 +286,7 @@ def generate_itempool(world, player):
|
|||||||
for item in precollected_items:
|
for item in precollected_items:
|
||||||
world.push_precollected(ItemFactory(item, player))
|
world.push_precollected(ItemFactory(item, player))
|
||||||
|
|
||||||
if (world.mode[player] == 'standard' and not (world.state.has_bomb_level(player, 1) if world.swords[player] else world.state.has_blunt_weapon(player))
|
if world.mode[player] == 'standard' and not (world.state.has_special_weapon_level(player, 1) if world.swords[player] in ['bombs', 'byrna', 'somaria', 'cane'] else world.state.has_blunt_weapon(player)):
|
||||||
and not world.state.has_bomb_level(player, 1)):
|
|
||||||
if world.swords[player] == 'bombs' and "Link's Uncle" not in placed_items:
|
if world.swords[player] == 'bombs' and "Link's Uncle" not in placed_items:
|
||||||
possible_weapons = []
|
possible_weapons = []
|
||||||
for item in pool:
|
for item in pool:
|
||||||
@@ -293,6 +295,22 @@ def generate_itempool(world, player):
|
|||||||
starting_weapon = random.choice(possible_weapons)
|
starting_weapon = random.choice(possible_weapons)
|
||||||
placed_items["Link's Uncle"] = starting_weapon
|
placed_items["Link's Uncle"] = starting_weapon
|
||||||
pool.remove(starting_weapon)
|
pool.remove(starting_weapon)
|
||||||
|
elif world.swords[player] in ['byrna', 'somaria'] and "Link's Uncle" not in placed_items:
|
||||||
|
possible_weapons = []
|
||||||
|
for item in pool:
|
||||||
|
if item in ['Progressive Cane', 'L1 Cane', 'L2 Cane', 'L3 Cane', 'L4 Cane', 'L5 Cane']:
|
||||||
|
possible_weapons.append(item)
|
||||||
|
starting_weapon = random.choice(possible_weapons)
|
||||||
|
placed_items["Link's Uncle"] = starting_weapon
|
||||||
|
pool.remove(starting_weapon)
|
||||||
|
elif world.swords[player] in ['cane'] and "Link's Uncle" not in placed_items:
|
||||||
|
possible_weapons = []
|
||||||
|
for item in pool:
|
||||||
|
if item in ['Cane of Byrna', 'Cane of Somaria']:
|
||||||
|
possible_weapons.append(item)
|
||||||
|
starting_weapon = random.choice(possible_weapons)
|
||||||
|
placed_items["Link's Uncle"] = starting_weapon
|
||||||
|
pool.remove(starting_weapon)
|
||||||
elif "Link's Uncle" not in placed_items:
|
elif "Link's Uncle" not in placed_items:
|
||||||
found_sword = False
|
found_sword = False
|
||||||
found_bow = False
|
found_bow = False
|
||||||
@@ -866,6 +884,14 @@ def get_pool_core(progressive, shuffle, difficulty, treasure_hunt_total, timer,
|
|||||||
pool.extend(diff.swordless)
|
pool.extend(diff.swordless)
|
||||||
elif swords == 'bombs':
|
elif swords == 'bombs':
|
||||||
pool.extend(diff.bombs_only)
|
pool.extend(diff.bombs_only)
|
||||||
|
elif swords == 'byrna':
|
||||||
|
pool = [item.replace('Cane of Byrna', 'Progressive Cane') for item in pool]
|
||||||
|
pool.extend(diff.cane_only)
|
||||||
|
elif swords == 'somaria':
|
||||||
|
pool = [item.replace('Cane of Somaria', 'Progressive Cane') for item in pool]
|
||||||
|
pool.extend(diff.cane_only)
|
||||||
|
elif swords == 'cane':
|
||||||
|
pool.extend(diff.cane_only)
|
||||||
elif swords == 'vanilla':
|
elif swords == 'vanilla':
|
||||||
swords_to_use = diff.progressivesword.copy() if want_progressives() else diff.basicsword.copy()
|
swords_to_use = diff.progressivesword.copy() if want_progressives() else diff.basicsword.copy()
|
||||||
random.shuffle(swords_to_use)
|
random.shuffle(swords_to_use)
|
||||||
@@ -974,7 +1000,7 @@ def make_custom_item_pool(progressive, shuffle, difficulty, timer, goal, mode, s
|
|||||||
itemtotal = itemtotal + customitemarray["generickeys"]
|
itemtotal = itemtotal + customitemarray["generickeys"]
|
||||||
|
|
||||||
customitems = [
|
customitems = [
|
||||||
"Bow", "Silver Arrows", "Blue Boomerang", "Red Boomerang", "Hookshot", "Mushroom", "Magic Powder", "Fire Rod", "Ice Rod", "Bombos", "Ether", "Quake", "Lamp", "Hammer", "Shovel", "Ocarina", "Bug Catching Net", "Book of Mudora", "Cane of Somaria", "Cane of Byrna", "Cape", "Pegasus Boots", "Power Glove", "Titans Mitts", "Progressive Glove", "Flippers", "Piece of Heart", "Boss Heart Container", "Sanctuary Heart Container", "Master Sword", "Tempered Sword", "Golden Sword", "L1 Bombs", "L2 Bombs", "L3 Bombs", "L4 Bombs", "L5 Bombs", "Progressive Bombs", "Blue Shield", "Red Shield", "Mirror Shield", "Progressive Shield", "Blue Mail", "Red Mail", "Progressive Armor", "Magic Upgrade (1/2)", "Magic Upgrade (1/4)", "Bomb Upgrade (+5)", "Bomb Upgrade (+10)", "Arrow Upgrade (+5)", "Arrow Upgrade (+10)", "Single Arrow", "Arrows (10)", "Single Bomb", "Bombs (3)", "Rupee (1)", "Rupees (5)", "Rupees (20)", "Rupees (50)", "Rupees (100)", "Rupees (300)", "Rupoor", "Blue Clock", "Green Clock", "Red Clock", "Progressive Bow", "Bombs (10)", "Triforce Piece", "Triforce"
|
"Bow", "Silver Arrows", "Blue Boomerang", "Red Boomerang", "Hookshot", "Mushroom", "Magic Powder", "Fire Rod", "Ice Rod", "Bombos", "Ether", "Quake", "Lamp", "Hammer", "Shovel", "Ocarina", "Bug Catching Net", "Book of Mudora", "Cane of Somaria", "Cane of Byrna", "Cape", "Pegasus Boots", "Power Glove", "Titans Mitts", "Progressive Glove", "Flippers", "Piece of Heart", "Boss Heart Container", "Sanctuary Heart Container", "Master Sword", "Tempered Sword", "Golden Sword", "L1 Bombs", "L2 Bombs", "L3 Bombs", "L4 Bombs", "L5 Bombs", "Progressive Bombs", "L1 Cane", "L2 Cane", "L3 Cane", "L4 Cane", "L5 Cane", "Progressive Cane", "Blue Shield", "Red Shield", "Mirror Shield", "Progressive Shield", "Blue Mail", "Red Mail", "Progressive Armor", "Magic Upgrade (1/2)", "Magic Upgrade (1/4)", "Bomb Upgrade (+5)", "Bomb Upgrade (+10)", "Arrow Upgrade (+5)", "Arrow Upgrade (+10)", "Single Arrow", "Arrows (10)", "Single Bomb", "Bombs (3)", "Rupee (1)", "Rupees (5)", "Rupees (20)", "Rupees (50)", "Rupees (100)", "Rupees (300)", "Rupoor", "Blue Clock", "Green Clock", "Red Clock", "Progressive Bow", "Bombs (10)", "Triforce Piece", "Triforce"
|
||||||
]
|
]
|
||||||
for customitem in customitems:
|
for customitem in customitems:
|
||||||
pool.extend([customitem] * customitemarray[get_custom_array_key(customitem)])
|
pool.extend([customitem] * customitemarray[get_custom_array_key(customitem)])
|
||||||
@@ -1049,7 +1075,7 @@ def test():
|
|||||||
for goal in ['ganon', 'triforcehunt', 'pedestal']:
|
for goal in ['ganon', 'triforcehunt', 'pedestal']:
|
||||||
for timer in ['none', 'display', 'timed', 'timed-ohko', 'ohko', 'timed-countdown']:
|
for timer in ['none', 'display', 'timed', 'timed-ohko', 'ohko', 'timed-countdown']:
|
||||||
for mode in ['open', 'standard', 'inverted', 'retro']:
|
for mode in ['open', 'standard', 'inverted', 'retro']:
|
||||||
for swords in ['random', 'assured', 'swordless', 'vanilla', 'bombs']:
|
for swords in ['random', 'assured', 'swordless', 'vanilla', 'bombs', 'byrna', 'somaria', 'cane']:
|
||||||
for progressive in ['on', 'off']:
|
for progressive in ['on', 'off']:
|
||||||
for shuffle in ['vanilla', 'full', 'crossed', 'insanity']:
|
for shuffle in ['vanilla', 'full', 'crossed', 'insanity']:
|
||||||
for logic in ['noglitches', 'minorglitches', 'owglitches', 'nologic']:
|
for logic in ['noglitches', 'minorglitches', 'owglitches', 'nologic']:
|
||||||
|
|||||||
12
Items.py
12
Items.py
@@ -168,10 +168,16 @@ item_table = {'Bow': (True, False, None, 0x0B, 200, 'You have\nchosen the\narche
|
|||||||
'Bee Trap': (False, False, None, 0xB0, 50, 'We will sting your face a whole lot!', 'and the sting buddies', 'the beekeeper kid', 'insects for sale', 'shroom pollenation', 'bottle boy has mad bees again', 'friendship'),
|
'Bee Trap': (False, False, None, 0xB0, 50, 'We will sting your face a whole lot!', 'and the sting buddies', 'the beekeeper kid', 'insects for sale', 'shroom pollenation', 'bottle boy has mad bees again', 'friendship'),
|
||||||
'L1 Bombs': (True, False, 'SwordBomb', 0xB1, 50, 'Some basic\nexplosives\nrest here!', 'the basic grenades', 'the bomb-holding kid', 'booms for sale', 'blend fungus into bombs', '\'splosion boy explodes again', 'basic bombs'),
|
'L1 Bombs': (True, False, 'SwordBomb', 0xB1, 50, 'Some basic\nexplosives\nrest here!', 'the basic grenades', 'the bomb-holding kid', 'booms for sale', 'blend fungus into bombs', '\'splosion boy explodes again', 'basic bombs'),
|
||||||
'L2 Bombs': (True, False, 'SwordBomb', 0xB2, 100, 'Some decent\nexplosives\nrest here!', 'the decent grenades', 'the bomb-holding kid', 'better booms for sale', 'blend fungus into bombs', '\'splosion boy explodes again', 'fancy bombs'),
|
'L2 Bombs': (True, False, 'SwordBomb', 0xB2, 100, 'Some decent\nexplosives\nrest here!', 'the decent grenades', 'the bomb-holding kid', 'better booms for sale', 'blend fungus into bombs', '\'splosion boy explodes again', 'fancy bombs'),
|
||||||
'L3 Bombs': (True, False, 'SwordBomb', 0xB3, 150, 'Some good\nexplosives\nrest here!', 'the good grenades sword', 'the bomb-holding kid', 'better booms for sale', 'blend fungus into bombs', '\'splosion boy explodes again', 'fancy bombs'),
|
'L3 Bombs': (True, False, 'SwordBomb', 0xB3, 150, 'Some good\nexplosives\nrest here!', 'the good grenades', 'the bomb-holding kid', 'better booms for sale', 'blend fungus into bombs', '\'splosion boy explodes again', 'fancy bombs'),
|
||||||
'L4 Bombs': (True, False, 'SwordBomb', 0xB4, 200, 'The golden\nexplosives\nrest here!', 'the golden grenades', 'the bomb-holding kid', 'better booms for sale', 'blend fungus into bombs', '\'splosion boy explodes again', 'fancy bombs'),
|
'L4 Bombs': (True, False, 'SwordBomb', 0xB4, 200, 'The golden\nexplosives\nrest here!', 'the golden grenades', 'the bomb-holding kid', 'better booms for sale', 'blend fungus into bombs', '\'splosion boy explodes again', 'fancy bombs'),
|
||||||
'L5 Bombs': (True, False, 'SwordBomb', 0xB5, 200, 'The golden\nexplosives\nrest here!', 'the golden grenades', 'the bomb-holding kid', 'better booms sale', 'blend fungus into bombs', '\'splosion boy explodes again', 'fancy bombs'),
|
'L5 Bombs': (True, False, 'SwordBomb', 0xB5, 200, 'The golden\nexplosives\nrest here!', 'the golden grenades', 'the bomb-holding kid', 'better booms for sale', 'blend fungus into bombs', '\'splosion boy explodes again', 'fancy bombs'),
|
||||||
'Progressive Bombs': (True, False, 'SwordBomb', 0xB6, 200, 'throw more\npowerful\nexplosives', 'the unknown grenades', 'the bomb-holding kid', 'better booms sale', 'blend fungus into bombs', '\'splosion boy explodes again', 'fancy bombs'),
|
'Progressive Bombs': (True, False, 'SwordBomb', 0xB6, 200, 'throw more\npowerful\nexplosives', 'the unknown grenades', 'the bomb-holding kid', 'better booms for sale', 'blend fungus into bombs', '\'splosion boy explodes again', 'fancy bombs'),
|
||||||
|
'L1 Cane': (True, False, 'SwordCane', 0xB7, 50, 'A basic\nstick\nrests here!', 'the basic stick', 'the stick-holding kid', 'stick for sale', 'fungus into stick', 'cane boy improves again', 'basic cane'),
|
||||||
|
'L2 Cane': (True, False, 'SwordCane', 0xB8, 100, 'A decent\nstick\nrests here!', 'the decent stick', 'the stick-holding kid', 'better stick for sale', 'fungus into stick', 'cane boy improves again', 'fancy cane'),
|
||||||
|
'L3 Cane': (True, False, 'SwordCane', 0xB9, 150, 'A good\nstick\nrests here!', 'the good stick', 'the stick-holding kid', 'better stick for sale', 'fungus into stick', 'cane boy improves again', 'fancy cane'),
|
||||||
|
'L4 Cane': (True, False, 'SwordCane', 0xBA, 200, 'A golden\nstick\nrests here!', 'the golden stick', 'the stick-holding kid', 'better stick for sale', 'fungus into stick', 'cane boy improves again', 'fancy cane'),
|
||||||
|
'L5 Cane': (True, False, 'SwordCane', 0xBB, 200, 'A golden\nstick\nrests here!', 'the golden stick', 'the stick-holding kid', 'better stick for sale', 'fungus into stick', 'cane boy improves again', 'fancy cane'),
|
||||||
|
'Progressive Cane': (True, False, 'SwordCane', 0xBC, 200, 'a better\nstick\nrests here!', 'the unknown stick', 'the stick-holding kid', 'better stick for sale', 'fungus into stick', 'cane boy improves again', 'fancy cane'),
|
||||||
'Red Potion': (False, False, None, 0x2E, 150, 'Hearty red goop!', 'and the red goo', 'the liquid kid', 'potion for sale', 'free samples', 'bottle boy has red goo again', 'a red potion'),
|
'Red Potion': (False, False, None, 0x2E, 150, 'Hearty red goop!', 'and the red goo', 'the liquid kid', 'potion for sale', 'free samples', 'bottle boy has red goo again', 'a red potion'),
|
||||||
'Green Potion': (False, False, None, 0x2F, 60, 'Refreshing green goop!', 'and the green goo', 'the liquid kid', 'potion for sale', 'free samples', 'bottle boy has green goo again', 'a green potion'),
|
'Green Potion': (False, False, None, 0x2F, 60, 'Refreshing green goop!', 'and the green goo', 'the liquid kid', 'potion for sale', 'free samples', 'bottle boy has green goo again', 'a green potion'),
|
||||||
'Blue Potion': (False, False, None, 0x30, 160, 'Delicious blue goop!', 'and the blue goo', 'the liquid kid', 'potion for sale', 'free samples', 'bottle boy has blue goo again', 'a blue potion'),
|
'Blue Potion': (False, False, None, 0x30, 160, 'Delicious blue goop!', 'and the blue goo', 'the liquid kid', 'potion for sale', 'free samples', 'bottle boy has blue goo again', 'a blue potion'),
|
||||||
|
|||||||
78
Rom.py
78
Rom.py
@@ -33,7 +33,7 @@ from source.classes.SFX import randomize_sfx
|
|||||||
|
|
||||||
|
|
||||||
JAP10HASH = '03a63945398191337e896e5771f77173'
|
JAP10HASH = '03a63945398191337e896e5771f77173'
|
||||||
RANDOMIZERBASEHASH = '7c1873254dcd5fb8b18934d806cd1949'
|
RANDOMIZERBASEHASH = 'b61fd3ea2d9c4c0465317052fa30a721'
|
||||||
|
|
||||||
|
|
||||||
class JsonRom(object):
|
class JsonRom(object):
|
||||||
@@ -1006,7 +1006,10 @@ def patch_rom(world, rom, player, team, enemized, is_mystery=False):
|
|||||||
TRIFORCE_PIECE = ItemFactory('Triforce Piece', player).code
|
TRIFORCE_PIECE = ItemFactory('Triforce Piece', player).code
|
||||||
GREEN_CLOCK = ItemFactory('Green Clock', player).code
|
GREEN_CLOCK = ItemFactory('Green Clock', player).code
|
||||||
|
|
||||||
rom.write_byte(0x18004F, 0x01) # Byrna Invulnerability: on
|
if world.swords[player] in ['byrna', 'cane']:
|
||||||
|
rom.write_byte(0x18004F, 0x00) # Byrna Invulnerability: off
|
||||||
|
else:
|
||||||
|
rom.write_byte(0x18004F, 0x01) # Byrna Invulnerability: on
|
||||||
|
|
||||||
# handle difficulty_adjustments
|
# handle difficulty_adjustments
|
||||||
if world.difficulty_adjustments[player] == 'hard':
|
if world.difficulty_adjustments[player] == 'hard':
|
||||||
@@ -1060,8 +1063,6 @@ def patch_rom(world, rom, player, team, enemized, is_mystery=False):
|
|||||||
rom.write_byte(0x180085, 0x80) # full
|
rom.write_byte(0x180085, 0x80) # full
|
||||||
#Cape magic cost
|
#Cape magic cost
|
||||||
rom.write_bytes(0x3ADA7, [0x04, 0x08, 0x10])
|
rom.write_bytes(0x3ADA7, [0x04, 0x08, 0x10])
|
||||||
# Byrna Invulnerability: on
|
|
||||||
rom.write_byte(0x18004F, 0x01)
|
|
||||||
#Enable catching fairies
|
#Enable catching fairies
|
||||||
rom.write_byte(0x34FD6, 0xF0)
|
rom.write_byte(0x34FD6, 0xF0)
|
||||||
# Rupoor negative value
|
# Rupoor negative value
|
||||||
@@ -1267,6 +1268,64 @@ def patch_rom(world, rom, player, team, enemized, is_mystery=False):
|
|||||||
rom.write_bytes(0x118188, credits_string_bot("TEMPERED BOMBS"))
|
rom.write_bytes(0x118188, credits_string_bot("TEMPERED BOMBS"))
|
||||||
rom.write_bytes(0x1181A6, credits_string_top("GOLD BOMBS"))
|
rom.write_bytes(0x1181A6, credits_string_top("GOLD BOMBS"))
|
||||||
rom.write_bytes(0x1181C4, credits_string_bot("GOLD BOMBS"))
|
rom.write_bytes(0x1181C4, credits_string_bot("GOLD BOMBS"))
|
||||||
|
elif world.swords[player] in ['byrna', 'somaria', 'cane']:
|
||||||
|
rom.write_byte(0x180040, 0x01) # open curtains
|
||||||
|
rom.write_byte(0x180041, 0x02) # swordless medallions (always)
|
||||||
|
rom.write_byte(0x180034, 0x00) # starting max bombs = 0
|
||||||
|
|
||||||
|
# remove magic cost of cane(s)
|
||||||
|
if world.swords[player] in ['byrna', 'cane']:
|
||||||
|
rom.write_bytes(0x045C42, [0x00, 0x00, 0x00])
|
||||||
|
rom.write_bytes(0x045CC7, [0xEA, 0xEA])
|
||||||
|
rom.write_byte(0x045CCD, 0x81)
|
||||||
|
rom.write_bytes(0x03B088, [0x00, 0x00, 0x00])
|
||||||
|
rom.write_bytes(0x03B0A8, [0xEA, 0xEA])
|
||||||
|
rom.write_byte(0x03B0AE, 0x81)
|
||||||
|
rom.write_bytes(0x18016B, [0x00, 0x00, 0x00])
|
||||||
|
if world.swords[player] in ['somaria', 'cane']:
|
||||||
|
rom.write_bytes(0x03B07C, [0x00, 0x00, 0x00, 0x00, 0x00, 0x00])
|
||||||
|
rom.write_bytes(0x03B0A8, [0xEA, 0xEA])
|
||||||
|
rom.write_byte(0x03B0AE, 0x81)
|
||||||
|
|
||||||
|
if world.swords[player] == 'byrna':
|
||||||
|
rom.write_byte(0x18002F, 0x03)
|
||||||
|
colr = 0x2C
|
||||||
|
elif world.swords[player] == 'somaria':
|
||||||
|
rom.write_byte(0x18002F, 0x04)
|
||||||
|
colr = 0x24
|
||||||
|
elif world.swords[player] == 'cane':
|
||||||
|
rom.write_byte(0x18002F, 0x05)
|
||||||
|
colr = 0x28
|
||||||
|
|
||||||
|
spritedata = [
|
||||||
|
0xF5, 0x20, 0xF5, 0x20, 0xF5, 0x20, 0xF5, 0x20,
|
||||||
|
0xDC, colr, 0xDD, colr, 0xEC, colr, 0x17, colr,
|
||||||
|
0xDC, colr, 0xDD, colr, 0xEC, colr, 0x18, colr,
|
||||||
|
0xDC, colr, 0xDD, colr, 0xEC, colr, 0x19, colr,
|
||||||
|
0xDC, colr, 0xDD, colr, 0xEC, colr, 0x1A, colr,
|
||||||
|
0xDC, colr, 0xDD, colr, 0xEC, colr, 0x1B, colr,
|
||||||
|
0xF5, 0x20, 0xF5, 0x20, 0xF5, 0x20, 0xF5, 0x20,
|
||||||
|
0xDC, colr, 0xDD, colr, 0xEC, colr, 0x17, colr,
|
||||||
|
0xDC, colr, 0xDD, colr, 0xEC, colr, 0x18, colr,
|
||||||
|
0xDC, colr, 0xDD, colr, 0xEC, colr, 0x19, colr,
|
||||||
|
0xDC, colr, 0xDD, colr, 0xEC, colr, 0x1A, colr,
|
||||||
|
0xDC, colr, 0xDD, colr, 0xEC, colr, 0x1B, colr,
|
||||||
|
];
|
||||||
|
rom.write_bytes(0x06FC51, spritedata)
|
||||||
|
|
||||||
|
# update sword references in credits to cane
|
||||||
|
rom.write_bytes(0x11807A, credits_string_top("FIRST CANE "))
|
||||||
|
rom.write_bytes(0x118098, credits_string_bot("FIRST CANE "))
|
||||||
|
rom.write_bytes(0x1180B6, credits_string_top("CANELESS "))
|
||||||
|
rom.write_bytes(0x1180D4, credits_string_bot("CANELESS "))
|
||||||
|
rom.write_bytes(0x1180F2, credits_string_top("FIGHTER'S CANE "))
|
||||||
|
rom.write_bytes(0x118110, credits_string_bot("FIGHTER'S CANE "))
|
||||||
|
rom.write_bytes(0x11812E, credits_string_top("MASTER CANE "))
|
||||||
|
rom.write_bytes(0x11814C, credits_string_bot("MASTER CANE "))
|
||||||
|
rom.write_bytes(0x11816A, credits_string_top("TEMPERED CANE "))
|
||||||
|
rom.write_bytes(0x118188, credits_string_bot("TEMPERED CANE "))
|
||||||
|
rom.write_bytes(0x1181A6, credits_string_top("GOLD CANE "))
|
||||||
|
rom.write_bytes(0x1181C4, credits_string_bot("GOLD CANE "))
|
||||||
|
|
||||||
# set up clocks for timed modes
|
# set up clocks for timed modes
|
||||||
if world.shuffle[player] == 'vanilla':
|
if world.shuffle[player] == 'vanilla':
|
||||||
@@ -1387,15 +1446,15 @@ def patch_rom(world, rom, player, team, enemized, is_mystery=False):
|
|||||||
elif startingstate.has('Fighter Sword', player):
|
elif startingstate.has('Fighter Sword', player):
|
||||||
equip[0x359] = 1
|
equip[0x359] = 1
|
||||||
|
|
||||||
if startingstate.has('L5 Bombs', player):
|
if startingstate.has('L5 Bombs', player) or startingstate.has('L5 Cane', player):
|
||||||
equip[0x38F] = 5
|
equip[0x38F] = 5
|
||||||
elif startingstate.has('L4 Bombs', player):
|
elif startingstate.has('L4 Bombs', player) or startingstate.has('L4 Cane', player):
|
||||||
equip[0x38F] = 4
|
equip[0x38F] = 4
|
||||||
elif startingstate.has('L3 Bombs', player):
|
elif startingstate.has('L3 Bombs', player) or startingstate.has('L3 Cane', player):
|
||||||
equip[0x38F] = 3
|
equip[0x38F] = 3
|
||||||
elif startingstate.has('L2 Bombs', player):
|
elif startingstate.has('L2 Bombs', player) or startingstate.has('L2 Cane', player):
|
||||||
equip[0x38F] = 2
|
equip[0x38F] = 2
|
||||||
elif startingstate.has('L1 Bombs', player):
|
elif startingstate.has('L1 Bombs', player) or startingstate.has('L1 Cane', player) or world.swords[player] == 'cane':
|
||||||
equip[0x38F] = 1
|
equip[0x38F] = 1
|
||||||
|
|
||||||
if startingstate.has('Mirror Shield', player):
|
if startingstate.has('Mirror Shield', player):
|
||||||
@@ -1425,6 +1484,7 @@ def patch_rom(world, rom, player, team, enemized, is_mystery=False):
|
|||||||
'Titans Mitts', 'Power Glove', 'Progressive Glove',
|
'Titans Mitts', 'Power Glove', 'Progressive Glove',
|
||||||
'Golden Sword', 'Tempered Sword', 'Master Sword', 'Fighter Sword', 'Progressive Sword',
|
'Golden Sword', 'Tempered Sword', 'Master Sword', 'Fighter Sword', 'Progressive Sword',
|
||||||
'L5 Bombs', 'L4 Bombs', 'L3 Bombs', 'L2 Bombs', 'L1 Bombs', 'Progressive Bombs',
|
'L5 Bombs', 'L4 Bombs', 'L3 Bombs', 'L2 Bombs', 'L1 Bombs', 'Progressive Bombs',
|
||||||
|
'L5 Cane', 'L4 Cane', 'L3 Cane', 'L2 Cane', 'L1 Cane', 'Progressive Cane',
|
||||||
'Mirror Shield', 'Red Shield', 'Blue Shield', 'Progressive Shield',
|
'Mirror Shield', 'Red Shield', 'Blue Shield', 'Progressive Shield',
|
||||||
'Red Mail', 'Blue Mail', 'Progressive Armor',
|
'Red Mail', 'Blue Mail', 'Progressive Armor',
|
||||||
'Magic Upgrade (1/4)', 'Magic Upgrade (1/2)']:
|
'Magic Upgrade (1/4)', 'Magic Upgrade (1/2)']:
|
||||||
|
|||||||
30
Rules.py
30
Rules.py
@@ -337,11 +337,11 @@ def global_rules(world, player):
|
|||||||
set_rule(world.get_entrance('Mire Lobby Gap', player), lambda state: state.has_Boots(player) or state.has('Hookshot', player))
|
set_rule(world.get_entrance('Mire Lobby Gap', player), lambda state: state.has_Boots(player) or state.has('Hookshot', player))
|
||||||
set_rule(world.get_entrance('Mire Post-Gap Gap', player), lambda state: state.has_Boots(player) or state.has('Hookshot', player))
|
set_rule(world.get_entrance('Mire Post-Gap Gap', player), lambda state: state.has_Boots(player) or state.has('Hookshot', player))
|
||||||
set_rule(world.get_entrance('Mire Falling Bridge WN', player), lambda state: state.has_Boots(player) or state.has('Hookshot', player)) # this is due to the fact the the door opposite is blocked
|
set_rule(world.get_entrance('Mire Falling Bridge WN', player), lambda state: state.has_Boots(player) or state.has('Hookshot', player)) # this is due to the fact the the door opposite is blocked
|
||||||
set_rule(world.get_entrance('Mire 2 NE', player), lambda state: state.bomb_mode_check(player, 1) and
|
set_rule(world.get_entrance('Mire 2 NE', player), lambda state: state.special_weapon_check(player, 1) and
|
||||||
(state.has_real_sword(player) or
|
(state.has_real_sword(player) or
|
||||||
(state.has('Fire Rod', player) and (state.can_use_bombs(player) or state.can_extend_magic(player, 9))) or # 9 fr shots or 8 with some bombs
|
(state.has('Fire Rod', player) and (state.can_use_bombs(player) or state.can_extend_magic(player, 9))) or # 9 fr shots or 8 with some bombs
|
||||||
(state.has('Ice Rod', player) and state.can_use_bombs(player)) or # freeze popo and throw, bomb to finish
|
(state.has('Ice Rod', player) and state.can_use_bombs(player)) or # freeze popo and throw, bomb to finish
|
||||||
state.has('Hammer', player) or state.has('Cane of Somaria', player) or state.can_shoot_arrows(player) or state.has_bomb_level(player, 1))) # need to defeat wizzrobes, bombs don't work ...
|
state.has('Hammer', player) or state.has('Cane of Somaria', player) or state.can_shoot_arrows(player) or state.has_special_weapon_level(player, 1))) # need to defeat wizzrobes, bombs don't work ...
|
||||||
# byrna could work with sufficient magic
|
# byrna could work with sufficient magic
|
||||||
set_rule(world.get_location('Misery Mire - Spike Chest', player), lambda state: (state.world.can_take_damage and state.has_hearts(player, 4)) or state.has('Cane of Byrna', player) or state.has('Cape', player))
|
set_rule(world.get_location('Misery Mire - Spike Chest', player), lambda state: (state.world.can_take_damage and state.has_hearts(player, 4)) or state.has('Cane of Byrna', player) or state.has('Cape', player))
|
||||||
set_rule(world.get_entrance('Mire Left Bridge Hook Path', player), lambda state: state.has('Hookshot', player))
|
set_rule(world.get_entrance('Mire Left Bridge Hook Path', player), lambda state: state.has('Hookshot', player))
|
||||||
@@ -593,7 +593,7 @@ def global_rules(world, player):
|
|||||||
|
|
||||||
set_rule(
|
set_rule(
|
||||||
world.get_location('Ganon', player),
|
world.get_location('Ganon', player),
|
||||||
lambda state: (state.has_real_sword(player, 2) or state.has_bomb_level(player, 3))
|
lambda state: (state.has_real_sword(player, 2) or state.has_special_weapon_level(player, 3))
|
||||||
and state.has_fire_source(player)
|
and state.has_fire_source(player)
|
||||||
and state.has_crystals(world.crystals_needed_for_ganon[player], player)
|
and state.has_crystals(world.crystals_needed_for_ganon[player], player)
|
||||||
and (state.has_real_sword(player, 3) or
|
and (state.has_real_sword(player, 3) or
|
||||||
@@ -604,7 +604,7 @@ def global_rules(world, player):
|
|||||||
|
|
||||||
set_rule(
|
set_rule(
|
||||||
world.get_entrance('Ganon Drop', player),
|
world.get_entrance('Ganon Drop', player),
|
||||||
lambda state: state.has_real_sword(player, 2) or state.has_bomb_level(player, 3))
|
lambda state: state.has_real_sword(player, 2) or state.has_special_weapon_level(player, 3))
|
||||||
# need to damage ganon to get tiles to drop
|
# need to damage ganon to get tiles to drop
|
||||||
|
|
||||||
def bomb_rules(world, player):
|
def bomb_rules(world, player):
|
||||||
@@ -860,6 +860,8 @@ def default_rules(world, player):
|
|||||||
swordless_rules(world, player)
|
swordless_rules(world, player)
|
||||||
if world.swords[player] == 'bombs':
|
if world.swords[player] == 'bombs':
|
||||||
bomb_mode_rules(world, player)
|
bomb_mode_rules(world, player)
|
||||||
|
if world.swords[player] in ['byrna', 'somaria', 'cane']:
|
||||||
|
cane_mode_rules(world, player)
|
||||||
if world.swords[player] in ['pseudo', 'assured_pseudo']:
|
if world.swords[player] in ['pseudo', 'assured_pseudo']:
|
||||||
pseudo_sword_mode_rules(world, player)
|
pseudo_sword_mode_rules(world, player)
|
||||||
|
|
||||||
@@ -1531,11 +1533,25 @@ def bomb_mode_rules(world, player):
|
|||||||
set_rule(world.get_entrance('Tower Altar NW', player), lambda state: True)
|
set_rule(world.get_entrance('Tower Altar NW', player), lambda state: True)
|
||||||
set_rule(world.get_entrance('Skull Vines NW', player), lambda state: True)
|
set_rule(world.get_entrance('Skull Vines NW', player), lambda state: True)
|
||||||
|
|
||||||
set_rule(world.get_location('Ether Tablet', player), lambda state: state.has('Book of Mudora', player) and state.has_bomb_level(player, 2))
|
set_rule(world.get_location('Ether Tablet', player), lambda state: state.has('Book of Mudora', player) and state.has_special_weapon_level(player, 2))
|
||||||
set_rule(world.get_location('Bombos Tablet', player), lambda state: state.has('Book of Mudora', player) and state.has_bomb_level(player, 2))
|
set_rule(world.get_location('Bombos Tablet', player), lambda state: state.has('Book of Mudora', player) and state.has_special_weapon_level(player, 2))
|
||||||
|
|
||||||
if world.mode[player] != 'inverted':
|
if world.mode[player] != 'inverted':
|
||||||
set_rule(world.get_entrance('Agahnims Tower', player), lambda state: state.has('Cape', player) or state.has_bomb_level(player, 2) or state.has('Beat Agahnim 1', player)) # barrier gets removed after killing agahnim, relevant for entrance shuffle
|
set_rule(world.get_entrance('Agahnims Tower', player), lambda state: state.has('Cape', player) or state.has_special_weapon_level(player, 2) or state.has('Beat Agahnim 1', player)) # barrier gets removed after killing agahnim, relevant for entrance shuffle
|
||||||
|
|
||||||
|
set_rule(world.get_entrance('Turtle Rock', player), lambda state: state.has_turtle_rock_medallion(player) and state.can_reach('Turtle Rock Ledge', 'Region', player)) # sword not required to use medallion in bomb-only
|
||||||
|
add_bunny_rule(world.get_entrance('Turtle Rock', player), player)
|
||||||
|
add_bunny_rule(world.get_entrance('Misery Mire', player), player)
|
||||||
|
|
||||||
|
def cane_mode_rules(world, player):
|
||||||
|
set_rule(world.get_entrance('Tower Altar NW', player), lambda state: True)
|
||||||
|
set_rule(world.get_entrance('Skull Vines NW', player), lambda state: True)
|
||||||
|
|
||||||
|
set_rule(world.get_location('Ether Tablet', player), lambda state: state.has('Book of Mudora', player) and state.has_special_weapon_level(player, 2))
|
||||||
|
set_rule(world.get_location('Bombos Tablet', player), lambda state: state.has('Book of Mudora', player) and state.has_special_weapon_level(player, 2))
|
||||||
|
|
||||||
|
if world.mode[player] != 'inverted':
|
||||||
|
set_rule(world.get_entrance('Agahnims Tower', player), lambda state: state.has('Cape', player) or state.has_special_weapon_level(player, 2) or state.has('Beat Agahnim 1', player)) # barrier gets removed after killing agahnim, relevant for entrance shuffle
|
||||||
|
|
||||||
set_rule(world.get_entrance('Turtle Rock', player), lambda state: state.has_turtle_rock_medallion(player) and state.can_reach('Turtle Rock Ledge', 'Region', player)) # sword not required to use medallion in bomb-only
|
set_rule(world.get_entrance('Turtle Rock', player), lambda state: state.has_turtle_rock_medallion(player) and state.can_reach('Turtle Rock Ledge', 'Region', player)) # sword not required to use medallion in bomb-only
|
||||||
add_bunny_rule(world.get_entrance('Turtle Rock', player), player)
|
add_bunny_rule(world.get_entrance('Turtle Rock', player), player)
|
||||||
|
|||||||
Binary file not shown.
@@ -37,6 +37,9 @@
|
|||||||
"pseudo",
|
"pseudo",
|
||||||
"assured_pseudo",
|
"assured_pseudo",
|
||||||
"bombs",
|
"bombs",
|
||||||
|
"byrna",
|
||||||
|
"somaria",
|
||||||
|
"cane",
|
||||||
"vanilla"
|
"vanilla"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user