Support trolls

This commit is contained in:
2023-06-14 19:04:45 -05:00
parent 0d7348a593
commit d79427431e
8 changed files with 80 additions and 5 deletions

View File

@@ -35,7 +35,7 @@ def adjust(args):
args.sprite, args.ow_palettes, args.uw_palettes, args.reduce_flashing, args.shuffle_sfx,
args.msu_resume)
output_path.cached_path = args.outputpath
# output_path.cached_path = args.outputpath
rom.write_to_file(output_path('%s.sfc' % outfilebase))
logger.info('Done. Enjoy.')

View File

@@ -105,6 +105,7 @@ class World(object):
self.sanc_portal = {}
self.fish = BabelFish()
self.pot_contents = {}
self.trolls = {}
for player in range(1, players + 1):
def set_player_attr(attr, val):
@@ -177,6 +178,7 @@ class World(object):
set_player_attr('exp_cache', defaultdict(dict))
set_player_attr('enabled_entrances', {})
set_player_attr('trolls', False)
def finish_init(self):
for player in range(1, self.players + 1):
@@ -184,6 +186,8 @@ class World(object):
self.mode[player] = 'open'
if self.goal[player] == 'completionist':
self.accessibility[player] = 'locations'
if self.trolls[player]:
self.can_take_damage[player] = False
def get_name_string_for_object(self, obj):
return obj.name if self.players == 1 else f'{obj.name} ({self.get_player_names(obj.player)})'
@@ -352,7 +356,7 @@ class World(object):
return True
else:
return False
def check_for_door(self, doorname, player):
if isinstance(doorname, Door):
return doorname

View File

@@ -38,6 +38,8 @@ def LanmolasDefeatRule(state, player):
state.has_special_weapon_level(player, 1)))
def MoldormDefeatRule(state, player):
if state.world.trolls[player] and not (state.has('Blue Boomerang', player) or state.has('Red Boomerang', player) or state.has('Hookshot', player)):
return False
return (state.special_weapon_check(player, 1) and
(state.has_blunt_weapon(player) or state.has_special_weapon_level(player, 1)))
@@ -74,6 +76,8 @@ def MothulaDefeatRule(state, player):
state.has_special_weapon_level(player, 1)))
def BlindDefeatRule(state, player):
if state.world.trolls[player]:
return state.has('Shovel', player)
return (state.special_weapon_check(player, 1) and
(state.has_blunt_weapon(player) or state.has('Cane of Somaria', player) or
state.has('Cane of Byrna', player) or state.has_special_weapon_level(player, 1)))
@@ -107,6 +111,14 @@ def VitreousDefeatRule(state, player):
state.has_special_weapon_level(player, 2)))
def TrinexxDefeatRule(state, player):
if state.world.trolls[player]:
if not (state.has('Bombos', player) and state.has('Ether', player)):
return False
return (state.has('Hammer', player) or
state.has_real_sword(player, 3) or
state.has_special_weapon_level(player, 4) or
((state.has_real_sword(player, 2) or state.has_special_weapon_level(player, 3))
and state.can_extend_magic(player, 24)))
if not (state.has('Fire Rod', player) and state.has('Ice Rod', player)):
return False
if not state.special_weapon_check(player, 2):

5
CLI.py
View File

@@ -147,7 +147,7 @@ def parse_cli(argv, no_defaults=False):
'heartbeep', 'remote_items', 'shopsanity', 'dropshuffle', 'pottery', 'keydropshuffle',
'mixed_travel', 'standardize_palettes', 'code', 'reduce_flashing', 'shuffle_sfx',
'msu_resume', 'collection_rate', 'colorizepots', 'decoupledoors', 'door_type_mode',
'bonk_drops', 'trap_door_mode', 'key_logic_algorithm']:
'bonk_drops', 'trap_door_mode', 'key_logic_algorithm', 'trolls']:
value = getattr(defaults, name) if getattr(playerargs, name) is None else getattr(playerargs, name)
if player == 1:
setattr(ret, name, {1: value})
@@ -360,7 +360,8 @@ def parse_settings():
"outputpath": os.path.join("."),
"saveonexit": "ask",
"outputname": "",
"startinventoryarray": {}
"startinventoryarray": {},
"trolls": False,
}
if sys.platform.lower().find("windows"):

View File

@@ -1126,6 +1126,10 @@ def get_pool_core(world, player, progressive, shuffle, difficulty, treasure_hunt
pool.remove('Piece of Heart')
pool.extend(['Rupees (20)'] * 12)
if world.trolls[player]:
pool.remove('Rupees (20)')
pool.extend(['Magic Upgrade (1/2)'])
if bombbag:
pool = [item.replace('Bomb Upgrade (+5)','Rupees (5)') for item in pool]
pool = [item.replace('Bomb Upgrade (+10)','Rupees (5)') for item in pool]

40
Rom.py
View File

@@ -2715,6 +2715,46 @@ def write_strings(rom, world, player, team):
rom.write_byte(0x04a529, 0x19) # x tile shifted right a few tiles
rom.write_byte(0x04a52e, 0x06) # follower set to blind maiden
if world.trolls[player]:
tt['telepathic_tile_eastern_palace'] = "Health will not help you against the Armos Knights."
tt['telepathic_tile_desert_bonk_torch_room'] = "Who ever saw lanmolas fly so fast?"
tt['telepathic_tile_tower_of_hera_entrance'] = "Please stop tickling my tail. It makes me freeze up and lower my defenses.\n\n - Moldorm"
tt['telepathic_tile_tower_of_hera_floor_4'] = "Hookshots and boomerangs are forbidden in my tower.\n\n - Moldorm"
tt['telepathic_tile_spectacle_rock'] = "With greater health and armor come shorter periods of refuge from damage."
tt['telepathic_tile_castle_tower'] = "Agahnim does not care for your foolish mortal patterns."
tt['telepathic_tile_palace_of_darkness'] = "Who weakened my mask?\n\n - Helmasaur King"
tt['telepathic_tile_swamp_entrance'] = "Please take your boots off before entering my room.\n\n - Arrghus"
tt['telepathic_tile_thieves_town_upstairs'] = "Secret power is said to be in the shovel."
tt['blind_by_the_light'] = "I'd really dig it if you didn't bring a shovel."
tt['telepathic_tile_ice_entrace'] = "Kholdstare's hypnotic eyes can be confusing..."
tt['telepathic_tile_ice_stalfos_knights_room'] = "Bomb fuses may be shorter or longer than they appear."
tt['telepathic_tile_ice_large_room'] = "Does your sword feel heavier than usual?"
tt['telepathic_tile_misery_mire'] = "Vitreous' small eyes require explosives to defeat."
tt['telepathic_tile_turtle_rock'] = "Trinexx has upped her defenses, requiring more powerful spells to defeat her. Consider whether you have enough magic reserves."
ganon_mock = 'Can you keep up with my changing weaknesses?';
tt['ganon_phase_3_no_bow'] = ganon_mock
tt['ganon_phase_3_no_silvers'] = ganon_mock
tt['ganon_phase_3_no_silvers_alt'] = ganon_mock
tt['ganon_phase_3_silvers'] = ganon_mock
tt.insertText('ganon_fall_in_mushroom', "I smell a mushroom!")
tt.insertText('ganon_phase_3_mushroom', "Your mushroom grants me invulnerability!")
tt.insertText('ganon_phase_4_silvers', "\n SILVER ARROWS ")
tt.insertText('ganon_phase_4_boomerang', "\n BOOMERANG ")
tt.insertText('ganon_phase_4_hookshot', "\n HOOKSHOT ")
tt.insertText('ganon_phase_4_bomb', "\n BOMB ")
tt.insertText('ganon_phase_4_powder', "\n POWDER ")
tt.insertText('ganon_phase_4_fire_rod', "\n FIRE ROD ")
tt.insertText('ganon_phase_4_ice_rod', "\n ICE ROD ")
tt.insertText('ganon_phase_4_bombos', "\n BOMBOS ")
tt.insertText('ganon_phase_4_ether', "\n ETHER ")
tt.insertText('ganon_phase_4_quake', "\n QUAKE ")
tt.insertText('ganon_phase_4_hammer', "\n HAMMER ")
tt.insertText('ganon_phase_4_bee', "\n BEE ")
tt.insertText('ganon_phase_4_somaria', "\n SOMARIA ")
tt.insertText('ganon_phase_4_byrna', "\n BYRNA ")
# inverted spawn menu changes
if world.mode[player] == 'inverted':
tt['menu_start_2'] = "{MENU}\n{SPEED0}\n≥@'s House\n Dark Chapel\n{CHOICE3}"

10
Text.py
View File

@@ -1390,6 +1390,16 @@ class TextTable(object):
return data.ljust(self.SIZE, b'\xff')
return data
def insertText(self, key, value):
if key in self._text:
raise KeyError(key)
if isinstance(value, str):
self._text[key] = CompressedTextMapper.convert(value)
else:
self._text[key] = value
self._text.move_to_end('end_pad_data')
self._text.move_to_end('terminator')
def removeUnwantedText(self):
nomessage = bytes(CompressedTextMapper.convert("{NOTEXT}", False))
messages_to_zero = [

View File

@@ -603,5 +603,9 @@
]
},
"outputname": {},
"code": {}
"code": {},
"trolls": {
"action": "store_true",
"type": "bool"
}
}