Rules changes

Implement Big Magic/Chicken/Fairy spawn items
This commit is contained in:
aerinon
2022-10-03 16:12:05 -06:00
parent b71c7aa2b4
commit a5fc4dd7a6
5 changed files with 82 additions and 79 deletions

View File

@@ -1945,8 +1945,8 @@ def init_vanilla_sprites():
create_sprite(0x010c, EnemySprite.GreenEyegoreMimic, 0x00, 0, 0x08, 0x14, 'Mimic Cave')
create_sprite(0x010c, EnemySprite.GreenEyegoreMimic, 0x00, 0, 0x0c, 0x14, 'Mimic Cave')
create_sprite(0x010c, EnemySprite.GreenEyegoreMimic, 0x00, 0, 0x0c, 0x1a, 'Mimic Cave')
create_sprite(0x010d, EnemySprite.SparkCW, 0x00, 0, 0x05, 0x16, 'Mimic Cave')
create_sprite(0x010d, EnemySprite.SparkCCW, 0x00, 0, 0x0a, 0x16, 'Mimic Cave')
create_sprite(0x010d, EnemySprite.SparkCW, 0x00, 0, 0x05, 0x16, 'Mire Shed')
create_sprite(0x010d, EnemySprite.SparkCCW, 0x00, 0, 0x0a, 0x16, 'Mire Shed')
create_sprite(0x010e, EnemySprite.DarkWorldHintNpc, 0x00, 0, 0x06, 0x06)
create_sprite(0x010e, EnemySprite.DarkWorldHintNpc, 0x00, 0, 0x18, 0x06)
create_sprite(0x010f, EnemySprite.Shopkeeper, 0x00, 0, 0x07, 0x15)
@@ -2005,8 +2005,7 @@ def kill_rules(world, player, stats):
bomb=2, silver=3, fire=None),
EnemySprite.MiniMoldorm: defeat_rule(world, player, h(EnemySprite.MiniMoldorm), ice=1, hook=True),
EnemySprite.Sluggula: defeat_rule(world, player, h(EnemySprite.Sluggula), bomb=None),
# too hard to hit red biris with arrows
EnemySprite.RedBari: defeat_rule(world, player, h(EnemySprite.RedBari) * 3, arrow=None, ice=2, hook=True),
EnemySprite.RedBari: or_rule(has('Fire Rod', player), and_rule(has_sword(player), has('Bombos', player))),
EnemySprite.BlueBari: defeat_rule(world, player, h(EnemySprite.BlueBari), ice=2, hook=True),
EnemySprite.HardhatBeetle: defeat_rule(world, player, h(EnemySprite.HardhatBeetle),
arrow=None, bomb=None, fire=None),
@@ -2101,18 +2100,22 @@ class EnemyTable:
def setup_enemy_locations(world, player):
for super_tile, enemy_list in world.data_tables[player].uw_enemy_table.room_map.items():
for index, sprite in enumerate(enemy_list):
if valid_drop_location(sprite, world, player):
if valid_drop_location(sprite, index, world, player):
create_drop_location(sprite, index, super_tile, world, player)
def valid_drop_location(sprite, world, player):
exceptions = {0xf1: [4, 5]} # these keese cannot be lured away
def valid_drop_location(sprite, index, world, player):
if world.dropshuffle[player] == 'underworld':
if sprite.drops_item and sprite.drop_item_kind == 0xe4:
# already has a location
return False
elif sprite.sub_type != SpriteType.Overlord:
stat = world.data_tables[player].enemy_stats[sprite.kind]
return not stat.static and stat.drop_flag
return stat.drop_flag and (sprite.super_tile not in exceptions
or index not in exceptions[sprite.super_tile])
def create_drop_location(sprite, index, super_tile, world, player):
@@ -2120,10 +2123,11 @@ def create_drop_location(sprite, index, super_tile, world, player):
address = drop_address(index, super_tile)
region_name = sprite.region
parent = world.get_region(region_name, player)
descriptor = f'Enemy #{index+1}'
enemy_name = enemy_names[sprite.kind]
descriptor = f'{enemy_name} #{index+1}'
modifier = parent.hint_text not in {'a storyteller', 'fairies deep in a cave', 'a spiky hint',
'a bounty of five items', 'the sick kid', 'Sahasrahla'}
hint_text = f'{"held by an enemy"} {"in" if modifier else "near"} {parent.hint_text}'
hint_text = f'held by a {enemy_name} {"in" if modifier else "near"} {parent.hint_text}'
drop_location = Location(player, f'{region_name} {descriptor}', address, hint_text=hint_text, parent=parent)
world.dynamic_locations.append(drop_location)
drop_location.drop = sprite
@@ -2272,6 +2276,21 @@ def can_bow_kill(world, player, damage, silver_damage, health):
return can_shoot_arrows(world, player)
def can_quake_kill(world, player, damage, health):
magic_needed = math.ceil(health / damage) * 2
if magic_needed > 8:
return and_rule(has('Quake', player), has_sword(player), can_extend_magic(world, player, magic_needed))
else:
return and_rule(has('Quake', player), has_sword(player))
def can_ether_kill(world, player, damage, health):
magic_needed = math.ceil(health / damage) * 2
if magic_needed > 8:
return and_rule(has('Ether', player), has_sword(player), can_extend_magic(world, player, magic_needed))
else:
return and_rule(has('Ether', player), has_sword(player))
# main enemy types
def defeat_rule(world, player, health, class1=1,
arrow: typing.Optional[int] = 1, silver=1,
@@ -2321,6 +2340,49 @@ def can_shoot_arrows(world, player):
def can_use_bombs(world, player):
return or_rule(RuleFactory.static_rule(not world.bombbag[player]), has('Bomb Upgrade (+10)', player))
special_rules_check = {
'Swamp Waterway': None,
'Hera Back': [5, 6],
'GT Petting Zoo': [1, 4, 5, 7],
'Mimic Cave': [3, 4],
'Ice Hookshot Ledge': None,
'TR Hub Ledges': [3, 4, 5, 6, 7],
'Old Man Cave': None,
'Old Man House Back': [4, 5, 6],
'Death Mountain Return Cave (left)': None,
'Death Mountain Return Cave (right)': [1, 2, 3, 6, 7]
}
def special_rules_for_region(world, player, region_name, location, original_rule, enemy):
if region_name == 'Swamp Waterway':
stats = world.data_tables[player].enemy_stats[enemy.kind]
return or_rule(can_quake_kill(world, player, 64, stats.health), can_ether_kill(world, player, 64, stats.health))
elif region_name in ['Hera Back', 'GT Petting Zoo', 'Mimic Cave']:
enemy_number = int(location.name.split('#')[1])
if enemy_number in special_rules_check[region_name]:
return and_rule(original_rule, has_boomerang(player))
else:
return original_rule
elif region_name == 'Ice Hookshot Ledge': # enemizer has these hardcoded to red baris for now
return and_rule(or_rule(has('Fire Rod', player), and_rule(has_sword(player), has('Bombos', player))),
or_rule(has_boomerang(player), has('Hookshot', player)))
elif region_name in ['TR Hub Ledges', 'Old Man Cave', 'Old Man House Back',
'Death Mountain Return Cave (left)', 'Death Mountain Return Cave (right)']:
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
return original_rule
enemy_names = {
0x00: 'Raven',
0x01: 'Vulture',