Skip to content

Commit

Permalink
Merge pull request #23 from Elagatua/feature/dev-merge
Browse files Browse the repository at this point in the history
Feature/dev merge
  • Loading branch information
Elagatua authored Sep 15, 2022
2 parents e1d7251 + 1ab2489 commit 5e5b7cc
Show file tree
Hide file tree
Showing 111 changed files with 22,924 additions and 22,658 deletions.
1,740 changes: 871 additions & 869 deletions ASM/build/asm_symbols.txt

Large diffs are not rendered by default.

Binary file modified ASM/build/bundle.o
Binary file not shown.
371 changes: 186 additions & 185 deletions ASM/build/c_symbols.txt

Large diffs are not rendered by default.

117 changes: 63 additions & 54 deletions ASM/c/dungeon_info.c

Large diffs are not rendered by default.

44 changes: 27 additions & 17 deletions ASM/c/get_items.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,14 @@ extern uint8_t OCARINAS_SHUFFLED;
override_t cfg_item_overrides[512] = { 0 };
int item_overrides_count = 0;

override_t pending_item_queue[3] = { 0 };
z64_actor_t *dummy_actor = NULL;

// Co-op state
extern uint8_t PLAYER_ID;
extern uint8_t PLAYER_NAME_ID;
extern uint16_t INCOMING_PLAYER;
extern uint16_t INCOMING_ITEM;
extern uint8_t MW_SEND_OWN_ITEMS;
extern override_key_t OUTGOING_KEY;
extern uint16_t OUTGOING_ITEM;
extern uint16_t OUTGOING_PLAYER;
Expand Down Expand Up @@ -152,18 +152,21 @@ void clear_override() {
}

void set_outgoing_override(override_t *override) {
OUTGOING_KEY = override->key;
OUTGOING_ITEM = override->value.item_id;
OUTGOING_PLAYER = override->value.player;
if (override->key.type != OVR_DELAYED || override->key.flag != 0xFF) { // don't send items received from incoming back to outgoing
OUTGOING_KEY = override->key;
OUTGOING_ITEM = override->value.item_id;
OUTGOING_PLAYER = override->value.player;
}
}

void push_pending_item(override_t override) {
for (int i = 0; i < array_size(pending_item_queue); i++) {
if (pending_item_queue[i].key.all == 0) {
pending_item_queue[i] = override;
for (int key_scene = 0x30; key_scene < 0x36; key_scene += 2) {
if (z64_file.scene_flags[key_scene].unk_00_ == 0) {
z64_file.scene_flags[key_scene].unk_00_ = override.key.all;
z64_file.scene_flags[key_scene + 1].unk_00_ = override.value.all;
break;
}
if (pending_item_queue[i].key.all == override.key.all) {
if (z64_file.scene_flags[key_scene].unk_00_ == override.key.all) {
// Prevent duplicate entries
break;
}
Expand Down Expand Up @@ -194,10 +197,11 @@ void push_delayed_item(uint8_t flag) {
}

void pop_pending_item() {
pending_item_queue[0] = pending_item_queue[1];
pending_item_queue[1] = pending_item_queue[2];
pending_item_queue[2].key.all = 0;
pending_item_queue[2].value.all = 0;
for (int scene = 0x30; scene < 0x34; scene++) {
z64_file.scene_flags[scene].unk_00_ = z64_file.scene_flags[scene + 2].unk_00_;
}
z64_file.scene_flags[0x34].unk_00_ = 0;
z64_file.scene_flags[0x35].unk_00_ = 0;
}

void after_key_received(override_key_t key) {
Expand All @@ -221,8 +225,8 @@ void after_key_received(override_key_t key) {
}

void pop_ice_trap() {
override_key_t key = pending_item_queue[0].key;
override_value_t value = pending_item_queue[0].value;
override_key_t key = { .all = z64_file.scene_flags[0x30].unk_00_ };
override_value_t value = { .all = z64_file.scene_flags[0x31].unk_00_ };
if (value.item_id == 0x7C && value.player == PLAYER_ID) {
push_pending_ice_trap();
pop_pending_item();
Expand All @@ -236,11 +240,11 @@ void after_item_received() {
return;
}

if (active_override_is_outgoing) {
if (MW_SEND_OWN_ITEMS || active_override_is_outgoing) {
set_outgoing_override(&active_override);
}

if (key.all == pending_item_queue[0].key.all) {
if (key.all == z64_file.scene_flags[0x30].unk_00_) {
pop_pending_item();
}
after_key_received(key);
Expand All @@ -266,7 +270,10 @@ inline uint32_t link_is_ready() {
}

void try_pending_item() {
override_t override = pending_item_queue[0];
override_t override = {
.key.all = z64_file.scene_flags[0x30].unk_00_,
.value.all = z64_file.scene_flags[0x31].unk_00_,
};

if(override.key.all == 0) {
return;
Expand Down Expand Up @@ -363,6 +370,9 @@ void get_skulltula_token(z64_actor_t *token_actor) {
} else if (player != PLAYER_ID) {
set_outgoing_override(&override);
} else {
if (MW_SEND_OWN_ITEMS) {
set_outgoing_override(&override);
}
z64_GiveItem(&z64_game, item_row->action_id);
call_effect_function(item_row);
}
Expand Down
18 changes: 9 additions & 9 deletions ASM/src/bonk.asm
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ BONK_LAST_FRAME:
jal 0x80390B18 ; func_80838178, static location as part of player overlay
nop

; One Bonk KO setting enabled
; Bonk damage enabled
lw t0, CFG_DEADLY_BONKS
beqz t0, @@return_bonk_frame
nop
Expand All @@ -33,7 +33,7 @@ SET_BONK_FLAG:
or a0, s0, $zero
addiu a1, $zero, 0x00FF

; One Bonk KO setting enabled
; Bonk damage enabled
lw t0, CFG_DEADLY_BONKS
beqz t0, @@return_bonk_flag
nop
Expand All @@ -56,7 +56,7 @@ CHECK_FOR_BONK_CANCEL:
addiu $at, $zero, 0x0002
lui t1, 0x8012

; One Bonk KO setting enabled
; Bonk damage enabled
lw t8, CFG_DEADLY_BONKS
beqz t8, @@return_bonk_check
nop
Expand Down Expand Up @@ -134,13 +134,10 @@ APPLY_BONK_DAMAGE:


KING_DODONGO_BONKS:
; displaced code
lh t2, 0x0032(s1)
mtc1 $zero, $f16

; One Bonk KO setting enabled
lw t0, CFG_DEADLY_BONKS
beqz t0, @@return_bonk_kd
lh t0, CFG_BONK_DAMAGE
addiu t2, $zero, 0xFFFE
bne t0, t2, @@return_bonk_kd
nop

; Set King Dodongo health to zero
Expand All @@ -150,6 +147,9 @@ KING_DODONGO_BONKS:
sh $zero, 0x0184(s0) ; this->health

@@return_bonk_kd:
; displaced code
lh t2, 0x0032(s1)
mtc1 $zero, $f16
jr ra
nop

Expand Down
6 changes: 5 additions & 1 deletion ASM/src/config.asm
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ PLANDOMIZER_USED:
; Any changes made here should be documented in Notes/auto-tracker-ctx.md
AUTO_TRACKER_CONTEXT:
AUTO_TRACKER_VERSION:
.word 2 ; Increment this if the auto-tracker context layout changes
.word 3 ; Increment this if the auto-tracker context layout changes

CFG_DUNGEON_INFO_ENABLE:
.word 0
Expand Down Expand Up @@ -214,4 +214,8 @@ TRIFORCE_PIECES_REQUIRED:
SPECIAL_DEAL_COUNTS:
.endarea

.area 9 * 0x17, 0x20
CFG_DUNGEON_REWARD_AREAS:
.endarea

.align 4
6 changes: 5 additions & 1 deletion ASM/src/coop_state.asm
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
COOP_CONTEXT:

COOP_VERSION:
.word 2 ; Increment this if layout of co-op state changes
.word 3 ; Increment this if layout of co-op state changes

PLAYER_ID:
.byte 0x00 ; Written by frontend
Expand All @@ -11,6 +11,10 @@ INCOMING_PLAYER:
.halfword 0x0000
INCOMING_ITEM:
.halfword 0x0000
MW_SEND_OWN_ITEMS:
; Written by multiworld plugin. If nonzero, the OUTGOING fields are set even if
; we find our own item, for the plugin's information.
.byte 0x00
.align 4

OUTGOING_KEY:
Expand Down
6 changes: 3 additions & 3 deletions Cosmetics.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ def patch_model_colors(rom, color, model_addresses):
main_addresses, dark_addresses, light_addresses = model_addresses

if color is None:
for address in main_addresses + dark_addresses:
for address in main_addresses + dark_addresses + light_addresses:
original = rom.original.read_bytes(address, 3)
rom.write_bytes(address, original)
return
Expand Down Expand Up @@ -108,9 +108,9 @@ def patch_tunic_colors(rom, settings, log, symbols):
else:
color = hex_to_color(tunic_option)
tunic_option = 'Custom'
# "Weird" weirdshots will crash if the Kokiri Tunic Green value is > 0x99. Brickwall it.
# "Weird" weirdshots will crash if the Kokiri Tunic Green value is > 0x99 and possibly 0x98. Brickwall it.
if settings.logic_rules != 'glitchless' and tunic == 'Kokiri Tunic':
color[1] = min(color[1],0x98)
color[1] = min(color[1], 0x97)
rom.write_bytes(address, color)

# patch the tunic icon
Expand Down
44 changes: 26 additions & 18 deletions EntranceShuffle.py
Original file line number Diff line number Diff line change
Expand Up @@ -350,49 +350,49 @@ def _add_boss_entrances():
'exit_blue_warp': reverse['blue_warp']
}

for type, source, target, boss, dungeon, index, rindex, addresses in [
for type, source, target, dungeon, index, rindex, addresses in [
(
'ChildBoss', 'Deku Tree Boss Door', 'Gohma Boss Room', 'Queen Gohma',
'ChildBoss', 'Deku Tree Boss Door', 'Queen Gohma Boss Room',
'KF Outside Deku Tree -> Deku Tree Lobby',
0x040f, 0x0252, [ 0xB06292, 0xBC6162, 0xBC60AE ]
),
(
'ChildBoss', 'Dodongos Cavern Boss Door', 'King Dodongo Boss Room', 'King Dodongo',
'ChildBoss', 'Dodongos Cavern Boss Door', 'King Dodongo Boss Room',
'Death Mountain -> Dodongos Cavern Beginning',
0x040b, 0x00c5, [ 0xB062B6, 0xBC616E ]
),
(
'ChildBoss', 'Jabu Jabus Belly Boss Door', 'Barinade Boss Room', 'Barinade',
'ChildBoss', 'Jabu Jabus Belly Boss Door', 'Barinade Boss Room',
'Zoras Fountain -> Jabu Jabus Belly Beginning',
0x0301, 0x0407, [ 0xB062C2, 0xBC60C2 ]
),
(
'AdultBoss', 'Forest Temple Boss Door', 'Phantom Ganon Boss Room', 'Phantom Ganon',
'AdultBoss', 'Forest Temple Boss Door', 'Phantom Ganon Boss Room',
'SFM Forest Temple Entrance Ledge -> Forest Temple Lobby',
0x000c, 0x024E, [ 0xB062CE, 0xBC6182 ]
),
(
'AdultBoss', 'Fire Temple Boss Door', 'Volvagia Boss Room', 'Volvagia',
'AdultBoss', 'Fire Temple Boss Door', 'Volvagia Boss Room',
'DMC Fire Temple Entrance -> Fire Temple Lower',
0x0305, 0x0175, [ 0xB062DA, 0xBC60CE ]
),
(
'AdultBoss', 'Water Temple Boss Door', 'Morpha Boss Room', 'Morpha',
'AdultBoss', 'Water Temple Boss Door', 'Morpha Boss Room',
'Lake Hylia -> Water Temple Lobby',
0x0417, 0x0423, [ 0xB062E6, 0xBC6196 ]
),
(
'AdultBoss', 'Spirit Temple Boss Door', 'Twinrova Boss Room', 'Twinrova',
'AdultBoss', 'Spirit Temple Boss Door', 'Twinrova Boss Room',
'Desert Colossus -> Spirit Temple Lobby',
0x008D, 0x02F5, [ 0xB062F2, 0xBC6122 ]
),
(
'AdultBoss', 'Shadow Temple Boss Door', 'Bongo Bongo Boss Room', 'Bongo Bongo',
'AdultBoss', 'Shadow Temple Boss Door', 'Bongo Bongo Boss Room',
'Graveyard Warp Pad Region -> Shadow Temple Entryway',
0x0413, 0x02B2, [ 0xB062FE, 0xBC61AA ]
)
]:
d = {'index': index, 'patch_addresses': addresses, 'boss': boss}
d = {'index': index, 'patch_addresses': addresses}
d.update(dungeon_data[dungeon])
entrance_shuffle_table.append(
(type, (f"{source} -> {target}", d), (f"{target} -> {source}", {'index': rindex}))
Expand Down Expand Up @@ -787,10 +787,12 @@ def check_entrances_compatibility(entrance, target, rollbacks=(), placed_one_way
except HintAreaNotFound:
pass # not connected to a hint area yet, will be checked when shuffling two-way entrances
else:
for placed_entrance in (*rollbacks, *placed_one_way_entrances):
# Check all already placed entrances of the same type (including priority entrances placed separately)
for rollback in (*rollbacks, *placed_one_way_entrances):
try:
if HintArea.at(placed_entrance[0].connected_region) == hint_area:
raise EntranceShuffleError(f'Another one-way entrance already leads to {hint_area}')
placed_entrance = rollback[0]
if entrance.type == placed_entrance.type and HintArea.at(placed_entrance.connected_region) == hint_area:
raise EntranceShuffleError(f'Another {entrance.type} entrance already leads to {hint_area}')
except HintAreaNotFound:
pass

Expand Down Expand Up @@ -828,8 +830,12 @@ def validate_world(world, worlds, entrance_placed, locations_to_ensure_reachable
if not max_search.visited(location):
raise EntranceShuffleError('%s is unreachable' % location.name)

if world.shuffle_interior_entrances and (any(hint_type in world.settings.misc_hints for hint_type in misc_item_hint_table) or world.settings.hints != 'none') and \
(entrance_placed == None or entrance_placed.type in ['Interior', 'SpecialInterior']):
if (
world.shuffle_interior_entrances and (
(world.dungeon_rewards_hinted and False) or #TODO enable if boss reward shuffle and/or mixed pools bosses are on
any(hint_type in world.settings.misc_hints for hint_type in misc_item_hint_table) or world.settings.hints != 'none'
) and (entrance_placed == None or entrance_placed.type in ['Interior', 'SpecialInterior'])
):
# Ensure Kak Potion Shop entrances are in the same hint area so there is no ambiguity as to which entrance is used for hints
potion_front_entrance = get_entrance_replacing(world.get_region('Kak Potion Shop Front'), 'Kakariko Village -> Kak Potion Shop Front')
potion_back_entrance = get_entrance_replacing(world.get_region('Kak Potion Shop Back'), 'Kak Backyard -> Kak Potion Shop Back')
Expand Down Expand Up @@ -881,14 +887,16 @@ def validate_world(world, worlds, entrance_placed, locations_to_ensure_reachable
# so the restriction also needs to be checked here
for idx1 in range(len(placed_one_way_entrances)):
try:
hint_area1 = HintArea.at(placed_one_way_entrances[idx1][0].connected_region)
entrance1 = placed_one_way_entrances[idx1][0]
hint_area1 = HintArea.at(entrance1.connected_region)
except HintAreaNotFound:
pass
else:
for idx2 in range(idx1):
try:
if hint_area1 == HintArea.at(placed_one_way_entrances[idx2][0].connected_region):
raise EntranceShuffleError(f'Multiple one-way entrances lead to {hint_area1}')
entrance2 = placed_one_way_entrances[idx2][0]
if entrance1.type == entrance2.type and hint_area1 == HintArea.at(entrance2.connected_region):
raise EntranceShuffleError(f'Multiple {entrance1.type} entrances lead to {hint_area1}')
except HintAreaNotFound:
pass

Expand Down
6 changes: 2 additions & 4 deletions Fill.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from State import State
from Rules import set_shop_rules
from Location import DisableType
from LocationList import location_groups
from ItemPool import remove_junk_items, triforce_blitz_items
from Item import ItemFactory, ItemInfo
from Search import Search
Expand All @@ -22,10 +23,7 @@ class FillError(ShuffleError):
# Places all items into the world
def distribute_items_restrictive(window, worlds, fill_locations=None):
if worlds[0].settings.shuffle_song_items == 'song':
song_location_names = [
'Song from Royal Familys Tomb', 'Song from Impa', 'Song from Malon', 'Song from Saria',
'Song from Ocarina of Time', 'Song from Windmill', 'Sheik in Forest', 'Sheik at Temple',
'Sheik in Crater', 'Sheik in Ice Cavern', 'Sheik in Kakariko', 'Sheik at Colossus']
song_location_names = location_groups['Song']
elif worlds[0].settings.shuffle_song_items == 'dungeon':
song_location_names = [
'Deku Tree Queen Gohma Heart', 'Dodongos Cavern King Dodongo Heart',
Expand Down
8 changes: 8 additions & 0 deletions GUI/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -153,5 +153,13 @@
"typescript": "3.2.4",
"web-animations-js": "2.2.5",
"zone.js": "0.8.29"
},
"overrides": {
"browserslist": {
"caniuse-lite": "1.0.30001393"
},
"autoprefixer": {
"caniuse-lite": "1.0.30001393"
}
}
}
10 changes: 8 additions & 2 deletions Goals.py
Original file line number Diff line number Diff line change
Expand Up @@ -317,7 +317,7 @@ def search_goals(categories, reachable_goals, search, priority_locations, all_lo
for world_id in hintable_states:
# Placeholder weights to be set for future bottleneck targeting.
# 0 weights for always-hinted locations isn't relevant currently
# but is intended to screen out contributions to the overall
# but is intended to screen out contributions to the overall
# goal/category weights
if location.name in always_locations or location.name in location.world.hint_exclusions:
location_weights = (location, 0, 0)
Expand All @@ -339,8 +339,14 @@ def search_goals(categories, reachable_goals, search, priority_locations, all_lo


def maybe_set_misc_item_hints(location):
if not location.item:
return
if location.item.world.dungeon_rewards_hinted and location.item.name in location.item.world.rewardlist:
if location.item.name not in location.item.world.hinted_dungeon_reward_locations:
location.item.world.hinted_dungeon_reward_locations[location.item.name] = location
logging.getLogger('').debug(f'{location.item.name} [{location.item.world.id}] set to [{location.name}]')
for hint_type in misc_item_hint_table:
item = location.item.world.misc_hint_items[hint_type]
if hint_type not in location.item.world.misc_hint_item_locations and location.item and location.item.name == item:
if hint_type not in location.item.world.misc_hint_item_locations and location.item.name == item:
location.item.world.misc_hint_item_locations[hint_type] = location
logging.getLogger('').debug(f'{item} [{location.item.world.id}] set to [{location.name}]')
Loading

0 comments on commit 5e5b7cc

Please sign in to comment.