Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion mm/2s2h/GameInteractor/GameInteractor.h
Original file line number Diff line number Diff line change
Expand Up @@ -257,13 +257,15 @@ typedef enum {
VB_SET_CAMERA_AT_EYE,
VB_SET_CAMERA_FOV,
VB_USE_ITEM_CONSIDER_ITEM_ACTION,
VB_ENEMY_DROP_COLLECTIBLE,
VB_DROP_COLLECTIBLE,
VB_TREE_DROP_COLLECTIBLE,
VB_DRAW_SLIME_RANDO_ITEM,
VB_ENABLE_OBJECT_DEPENDENCY,
VB_OBJ_MURE2_SET_CHILD_ROOM,
VB_OBJ_MURE3_DROP_COLLECTIBLE,
VB_SET_PLAYER_CYLINDER_OC_FLAGS,
VB_GORON_RACE_RUBBERBANDING,
VB_APPLY_BONK_TO_ACTOR,
} GIVanillaBehavior;

typedef enum {
Expand Down
1 change: 1 addition & 0 deletions mm/2s2h/Rando/ActorBehavior/ActorBehavior.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ void Rando::ActorBehavior::OnFileLoad() {
Rando::ActorBehavior::InitObjMoonStoneBehavior();
Rando::ActorBehavior::InitObjSnowballBehavior();
Rando::ActorBehavior::InitObjTaruBehavior();
Rando::ActorBehavior::InitObjTreeBehavior();
Rando::ActorBehavior::InitObjTsuboBehavior();
Rando::ActorBehavior::InitObjWarpstoneBehavior();
Rando::ActorBehavior::InitPlayerBehavior();
Expand Down
1 change: 1 addition & 0 deletions mm/2s2h/Rando/ActorBehavior/ActorBehavior.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ void InitObjGrassBehavior();
void InitObjMoonStoneBehavior();
void InitObjSnowballBehavior();
void InitObjTaruBehavior();
void InitObjTreeBehavior();
void InitObjTsuboBehavior();
void InitObjWarpstoneBehavior();
void InitPlayerBehavior();
Expand Down
2 changes: 1 addition & 1 deletion mm/2s2h/Rando/ActorBehavior/EnemyDrops.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ void SpawnEnemyDrop(Vec3f position, Actor* actor, RandoCheckId randoCheckId) {
}

void Rando::ActorBehavior::InitEnemyDropBehavior() {
COND_VB_SHOULD(VB_ENEMY_DROP_COLLECTIBLE, IS_RANDO, {
COND_VB_SHOULD(VB_DROP_COLLECTIBLE, IS_RANDO, {
Vec3f position = va_arg(args, Vec3f);

if (RANDO_SAVE_OPTIONS[RO_SHUFFLE_ENEMY_DROPS] == RO_GENERIC_OFF) {
Expand Down
239 changes: 239 additions & 0 deletions mm/2s2h/Rando/ActorBehavior/ObjTree.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,239 @@
#include "ActorBehavior.h"
#include <libultraship/bridge/consolevariablebridge.h>
#include "2s2h/CustomItem/CustomItem.h"
#include "assets/2s2h_assets.h"
#include "2s2h/ObjectExtension/ActorListIndex.h"
#include "2s2h/ShipUtils.h"

extern "C" {
#include "variables.h"
}

std::map<std::pair<float, float>, RandoCheckId> manInTheTreeRupeeMap = {
{ { 3508.0f, 1879.0f }, RC_TERMINA_FIELD_MAN_IN_THE_TREE_RUPEE_01 },
{ { 3488.0f, 1909.0f }, RC_TERMINA_FIELD_MAN_IN_THE_TREE_RUPEE_02 },
};

std::map<std::tuple<s16, s16, s16>, RandoCheckId> treeActorIdMap = {
// Beneath the Well
{ { SCENE_REDEAD, 9, 3 }, RC_BENEATH_THE_WELL_TREE },

// Cucco Shack
{ { SCENE_F01C, 0, 12 }, RC_CUCCO_SHACK_TREE },

// Gorman Track
{ { SCENE_KOEPONARACE, 0, 11 }, RC_GORMAN_TRACK_TREE_01 },
{ { SCENE_KOEPONARACE, 0, 12 }, RC_GORMAN_TRACK_TREE_02 },
{ { SCENE_KOEPONARACE, 0, 13 }, RC_GORMAN_TRACK_TREE_03 },
{ { SCENE_KOEPONARACE, 0, 14 }, RC_GORMAN_TRACK_TREE_04 },
{ { SCENE_KOEPONARACE, 0, 15 }, RC_GORMAN_TRACK_TREE_05 },
{ { SCENE_KOEPONARACE, 0, 16 }, RC_GORMAN_TRACK_TREE_06 },
{ { SCENE_KOEPONARACE, 0, 17 }, RC_GORMAN_TRACK_TREE_07 },
{ { SCENE_KOEPONARACE, 0, 18 }, RC_GORMAN_TRACK_TREE_08 },
{ { SCENE_KOEPONARACE, 0, 19 }, RC_GORMAN_TRACK_TREE_09 },
{ { SCENE_KOEPONARACE, 0, 20 }, RC_GORMAN_TRACK_TREE_10 },
{ { SCENE_KOEPONARACE, 0, 21 }, RC_GORMAN_TRACK_TREE_11 },
{ { SCENE_KOEPONARACE, 0, 22 }, RC_GORMAN_TRACK_TREE_12 },
{ { SCENE_KOEPONARACE, 0, 23 }, RC_GORMAN_TRACK_TREE_13 },
{ { SCENE_KOEPONARACE, 0, 24 }, RC_GORMAN_TRACK_TREE_14 },
{ { SCENE_KOEPONARACE, 0, 25 }, RC_GORMAN_TRACK_TREE_15 },
{ { SCENE_KOEPONARACE, 0, 26 }, RC_GORMAN_TRACK_TREE_16 },
{ { SCENE_KOEPONARACE, 0, 27 }, RC_GORMAN_TRACK_TREE_17 },
{ { SCENE_KOEPONARACE, 0, 28 }, RC_GORMAN_TRACK_TREE_18 },
{ { SCENE_KOEPONARACE, 0, 29 }, RC_GORMAN_TRACK_TREE_19 },
{ { SCENE_KOEPONARACE, 0, 30 }, RC_GORMAN_TRACK_TREE_20 },
{ { SCENE_KOEPONARACE, 0, 31 }, RC_GORMAN_TRACK_TREE_21 },
{ { SCENE_KOEPONARACE, 0, 32 }, RC_GORMAN_TRACK_TREE_22 },
{ { SCENE_KOEPONARACE, 0, 33 }, RC_GORMAN_TRACK_TREE_23 },
{ { SCENE_KOEPONARACE, 0, 34 }, RC_GORMAN_TRACK_TREE_24 },
{ { SCENE_KOEPONARACE, 0, 35 }, RC_GORMAN_TRACK_TREE_25 },

// Great Bay Coast
{ { SCENE_30GYOSON, 0, 10 }, RC_GREAT_BAY_COAST_TREE_01 },
{ { SCENE_30GYOSON, 0, 11 }, RC_GREAT_BAY_COAST_TREE_02 },
{ { SCENE_30GYOSON, 0, 12 }, RC_GREAT_BAY_COAST_TREE_03 },
{ { SCENE_30GYOSON, 0, 13 }, RC_GREAT_BAY_COAST_TREE_04 },

// Path to Mountain Village
{ { SCENE_13HUBUKINOMITI, 0, 14 }, RC_PATH_TO_MOUNTAIN_VILLAGE_TREE_01 },
{ { SCENE_13HUBUKINOMITI, 0, 15 }, RC_PATH_TO_MOUNTAIN_VILLAGE_TREE_02 },
{ { SCENE_13HUBUKINOMITI, 0, 16 }, RC_PATH_TO_MOUNTAIN_VILLAGE_TREE_03 },
{ { SCENE_13HUBUKINOMITI, 0, 17 }, RC_PATH_TO_MOUNTAIN_VILLAGE_TREE_04 },

// Path to Snowhead
{ { SCENE_14YUKIDAMANOMITI, 0, 22 }, RC_PATH_TO_SNOWHEAD_TREE_01 },
{ { SCENE_14YUKIDAMANOMITI, 0, 23 }, RC_PATH_TO_SNOWHEAD_TREE_02 },
{ { SCENE_14YUKIDAMANOMITI, 0, 24 }, RC_PATH_TO_SNOWHEAD_TREE_03 },
{ { SCENE_14YUKIDAMANOMITI, 0, 25 }, RC_PATH_TO_SNOWHEAD_TREE_04 },

// Road to Southern Swamp
{ { SCENE_24KEMONOMITI, 0, 26 }, RC_ROAD_TO_SOUTHERN_SWAMP_TREE_01 },
{ { SCENE_24KEMONOMITI, 0, 27 }, RC_ROAD_TO_SOUTHERN_SWAMP_TREE_02 },
{ { SCENE_24KEMONOMITI, 0, 28 }, RC_ROAD_TO_SOUTHERN_SWAMP_TREE_03 },
{ { SCENE_24KEMONOMITI, 0, 29 }, RC_ROAD_TO_SOUTHERN_SWAMP_TREE_04 },
{ { SCENE_24KEMONOMITI, 0, 30 }, RC_ROAD_TO_SOUTHERN_SWAMP_TREE_05 },
{ { SCENE_24KEMONOMITI, 0, 31 }, RC_ROAD_TO_SOUTHERN_SWAMP_TREE_06 },

// Romani Ranch
{ { SCENE_F01, 0, 20 }, RC_ROMANI_RANCH_TREE_01 },
{ { SCENE_F01, 0, 21 }, RC_ROMANI_RANCH_TREE_02 },
{ { SCENE_F01, 0, 22 }, RC_ROMANI_RANCH_TREE_03 },
{ { SCENE_F01, 0, 23 }, RC_ROMANI_RANCH_TREE_04 },
{ { SCENE_F01, 0, 24 }, RC_ROMANI_RANCH_TREE_05 },
{ { SCENE_F01, 0, 25 }, RC_ROMANI_RANCH_TREE_06 },
{ { SCENE_F01, 0, 26 }, RC_ROMANI_RANCH_TREE_07 },

// Termina Field
// RC_TERMINA_FIELD_MAN_IN_THE_TREE_RUPEE_01 also handles RC_TERMINA_FIELD_MAN_IN_THE_TREE_RUPEE_02
{ { SCENE_00KEIKOKU, 0, 167 }, RC_TERMINA_FIELD_MAN_IN_THE_TREE_RUPEE_01 },
{ { SCENE_00KEIKOKU, 0, 168 }, RC_TERMINA_FIELD_TREE_01 },
{ { SCENE_00KEIKOKU, 0, 169 }, RC_TERMINA_FIELD_TREE_02 },

// Path to Goron Village
{ { SCENE_17SETUGEN2, 0, 7 }, RC_TWIN_ISLANDS_SPRING_TREE_01 },
{ { SCENE_17SETUGEN2, 0, 8 }, RC_TWIN_ISLANDS_SPRING_TREE_02 },
{ { SCENE_17SETUGEN2, 0, 9 }, RC_TWIN_ISLANDS_SPRING_TREE_03 },
{ { SCENE_17SETUGEN, 0, 7 }, RC_TWIN_ISLANDS_TREE_01 },
{ { SCENE_17SETUGEN, 0, 8 }, RC_TWIN_ISLANDS_TREE_02 },
{ { SCENE_17SETUGEN, 0, 9 }, RC_TWIN_ISLANDS_TREE_03 },

// Zora Cape
{ { SCENE_31MISAKI, 0, 24 }, RC_ZORA_CAPE_TREE_01 },
{ { SCENE_31MISAKI, 0, 25 }, RC_ZORA_CAPE_TREE_02 },
{ { SCENE_31MISAKI, 0, 26 }, RC_ZORA_CAPE_TREE_03 },
{ { SCENE_31MISAKI, 0, 27 }, RC_ZORA_CAPE_TREE_04 },
{ { SCENE_31MISAKI, 0, 28 }, RC_ZORA_CAPE_TREE_05 },
};

std::map<RandoCheckId, EnItem00*> currentlySpawnedItems;

void ApplyGravityToSpawnedItem(RandoCheckId randoCheckId) {
auto findItem = currentlySpawnedItems.find(randoCheckId);
if (findItem != currentlySpawnedItems.end()) {
findItem->second->actor.gravity = -1.4f;
}
}

void SpawnTreeDrop(Vec3f pos, RandoCheckId randoCheckId) {
int customItemFlags = CustomItem::KILL_ON_TOUCH | CustomItem::ABLE_TO_ZORA_RANG;

if (RANDO_SAVE_OPTIONS[RO_PEEK_TREE_DROPS] == RO_GENERIC_OFF) {
customItemFlags |= CustomItem::TOSS_ON_SPAWN;
}

EnItem00* spawnedItem = CustomItem::Spawn(
pos.x - 20.0f, pos.y + 200.0f, pos.z + 25.0f, 0, customItemFlags, randoCheckId,
[](Actor* actor, PlayState* play) {
RandoSaveCheck& randoSaveCheck = RANDO_SAVE_CHECKS[CUSTOM_ITEM_PARAM];
randoSaveCheck.eligible = true;
},
[](Actor* actor, PlayState* play) {
auto& randoSaveCheck = RANDO_SAVE_CHECKS[CUSTOM_ITEM_PARAM];
Matrix_Scale(30.0f, 30.0f, 30.0f, MTXMODE_APPLY);
Rando::DrawItem(Rando::ConvertItem(randoSaveCheck.randoItemId, (RandoCheckId)CUSTOM_ITEM_PARAM), actor);
});

auto findItem = currentlySpawnedItems.find(randoCheckId);
if (findItem == currentlySpawnedItems.end()) {
currentlySpawnedItems.insert({ randoCheckId, spawnedItem });
}

if (randoCheckId == RC_TERMINA_FIELD_MAN_IN_THE_TREE_RUPEE_01) {
pos.x += 40.0f;
SpawnTreeDrop(pos, RC_TERMINA_FIELD_MAN_IN_THE_TREE_RUPEE_02);
}
}

void IdentifyTree(Actor* actor, bool* should) {
s16 actorListIndex = GetActorListIndex(actor);
RandoCheckId randoCheckId = RC_UNKNOWN;

auto it = treeActorIdMap.find({ gPlayState->sceneId, gPlayState->roomCtx.curRoom.num, actorListIndex });
if (it != treeActorIdMap.end()) {
randoCheckId = it->second;
}

if (!RANDO_SAVE_CHECKS[randoCheckId].shuffled || RANDO_SAVE_CHECKS[randoCheckId].cycleObtained) {
return;
}

if (!RANDO_SAVE_CHECKS[randoCheckId].obtained && RANDO_SAVE_OPTIONS[RO_PEEK_TREE_DROPS] == RO_GENERIC_ON) {
SpawnTreeDrop(actor->world.pos, randoCheckId);
}

Rando::ActorBehavior::GetObjectRandoCheckId(actor);
}

void Rando::ActorBehavior::InitObjTreeBehavior() {
COND_ID_HOOK(ShouldActorInit, ACTOR_EN_WOOD02, IS_RANDO, IdentifyTree);
COND_ID_HOOK(ShouldActorInit, ACTOR_OBJ_TREE, IS_RANDO, IdentifyTree);
COND_ID_HOOK(ShouldActorInit, ACTOR_OBJ_YASI, IS_RANDO, IdentifyTree);
COND_ID_HOOK(ShouldActorInit, ACTOR_EN_SNOWWD, IS_RANDO, IdentifyTree);

COND_VB_SHOULD(VB_APPLY_BONK_TO_ACTOR, IS_RANDO, {
Actor* tree = va_arg(args, Actor*);
if (tree == nullptr) {
return;
}

if (tree->id != ACTOR_EN_WOOD02 && tree->id != ACTOR_OBJ_TREE && tree->id != ACTOR_OBJ_YASI &&
tree->id != ACTOR_EN_SNOWWD) {
return;
}
RandoCheckId randoCheckId = GetObjectRandoCheckId(tree);
if (randoCheckId == RC_UNKNOWN) {
return;
}

if (!RANDO_SAVE_CHECKS[randoCheckId].obtained) {
if (RANDO_SAVE_OPTIONS[RO_PEEK_TREE_DROPS] == RO_GENERIC_ON) {
ApplyGravityToSpawnedItem(randoCheckId);
} else {
SpawnTreeDrop(tree->world.pos, randoCheckId);
}
}
});

COND_VB_SHOULD(VB_TREE_DROP_COLLECTIBLE, IS_RANDO, {
Actor* tree = va_arg(args, Actor*);

if (RANDO_SAVE_OPTIONS[RO_SHUFFLE_TREE_DROPS] != RO_GENERIC_OFF) {
if (tree != NULL) {
RandoCheckId randoCheckId = GetObjectRandoCheckId(tree);
if (randoCheckId == RC_UNKNOWN) {
return;
}

if (!RANDO_SAVE_CHECKS[randoCheckId].obtained) {
ApplyGravityToSpawnedItem(randoCheckId);
*should = false;
}
}
}
});

COND_VB_SHOULD(VB_DROP_COLLECTIBLE, IS_RANDO, {
Vec3f position = va_arg(args, Vec3f);
RandoCheckId randoCheckId = RC_UNKNOWN;

if (RANDO_SAVE_OPTIONS[RO_SHUFFLE_TREE_DROPS] == RO_GENERIC_OFF) {
return;
}

if (gPlayState->sceneId == SCENE_00KEIKOKU) {
auto it = manInTheTreeRupeeMap.find({ position.x, position.z });
if (it == manInTheTreeRupeeMap.end()) {
return;
} else {
randoCheckId = it->second;
}
}

if (!RANDO_SAVE_CHECKS[randoCheckId].obtained) {
ApplyGravityToSpawnedItem(randoCheckId);
*should = false;
}
});

COND_HOOK(OnSceneInit, IS_RANDO, [](s16 sceneId, s8 spawnNum) { currentlySpawnedItems.clear(); });
}
1 change: 1 addition & 0 deletions mm/2s2h/Rando/CheckTracker/CheckTracker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ std::vector<const char*> checkTypeIconList = {
/*RCTYPE_SONG*/ gItemIconSongNoteTex,
/*RCTYPE_STRAY_FAIRY*/ gStrayFairyGreatBayIconTex,
/*RCTYPE_TINGLE_SHOP*/ gItemIconAdultsWalletTex,
/*RCTYPE_TREE*/ gItemIconDekuStickTex,
};

static constexpr ImVec4 tintColor = {};
Expand Down
3 changes: 2 additions & 1 deletion mm/2s2h/Rando/Logic/Regions/BeneathTheWell.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,8 @@ static RegisterShipInitFunc initFunc([]() {
};
Regions[RR_BENEATH_THE_WELL_COW_ROOM] = RandoRegion{ .name = "Cow Room", .sceneId = SCENE_REDEAD,
.checks = {
CHECK(RC_BENEATH_THE_WELL_COW, CAN_PLAY_SONG(EPONA))
CHECK(RC_BENEATH_THE_WELL_COW, CAN_PLAY_SONG(EPONA)),
CHECK(RC_BENEATH_THE_WELL_TREE, true),
},
.connections = {
CONNECTION(RR_BENEATH_THE_WELL_RIGHT_FIRE_KEESE, true),
Expand Down
33 changes: 33 additions & 0 deletions mm/2s2h/Rando/Logic/Regions/MilkRoad.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ static RegisterShipInitFunc initFunc([]() {
CHECK(RC_CUCCO_SHACK_LARGE_CRATE_01, true),
CHECK(RC_CUCCO_SHACK_LARGE_CRATE_02, true),
CHECK(RC_CUCCO_SHACK_LARGE_CRATE_03, true),
CHECK(RC_CUCCO_SHACK_TREE, true),
},
.exits = { // TO FROM
EXIT(ENTRANCE(ROMANI_RANCH, 4), ENTRANCE(CUCCO_SHACK, 0), true),
Expand Down Expand Up @@ -77,6 +78,31 @@ static RegisterShipInitFunc initFunc([]() {
CHECK(RC_GORMAN_TRACK_GRASS_22, true),
CHECK(RC_GORMAN_TRACK_GRASS_23, true),
CHECK(RC_GORMAN_TRACK_GRASS_24, true),
CHECK(RC_GORMAN_TRACK_TREE_01, true),
CHECK(RC_GORMAN_TRACK_TREE_02, true),
CHECK(RC_GORMAN_TRACK_TREE_03, true),
CHECK(RC_GORMAN_TRACK_TREE_04, true),
CHECK(RC_GORMAN_TRACK_TREE_05, true),
CHECK(RC_GORMAN_TRACK_TREE_06, true),
CHECK(RC_GORMAN_TRACK_TREE_07, true),
CHECK(RC_GORMAN_TRACK_TREE_08, true),
CHECK(RC_GORMAN_TRACK_TREE_09, true),
CHECK(RC_GORMAN_TRACK_TREE_10, true),
CHECK(RC_GORMAN_TRACK_TREE_11, true),
CHECK(RC_GORMAN_TRACK_TREE_12, true),
CHECK(RC_GORMAN_TRACK_TREE_13, true),
CHECK(RC_GORMAN_TRACK_TREE_14, true),
CHECK(RC_GORMAN_TRACK_TREE_15, true),
CHECK(RC_GORMAN_TRACK_TREE_16, true),
CHECK(RC_GORMAN_TRACK_TREE_17, true),
CHECK(RC_GORMAN_TRACK_TREE_18, true),
CHECK(RC_GORMAN_TRACK_TREE_19, true),
CHECK(RC_GORMAN_TRACK_TREE_20, true),
CHECK(RC_GORMAN_TRACK_TREE_21, true),
CHECK(RC_GORMAN_TRACK_TREE_22, true),
CHECK(RC_GORMAN_TRACK_TREE_23, true),
CHECK(RC_GORMAN_TRACK_TREE_24, true),
CHECK(RC_GORMAN_TRACK_TREE_25, true),
},
.exits = { // TO FROM
EXIT(ENTRANCE(MILK_ROAD, 2), ENTRANCE(GORMAN_TRACK, 3), RANDO_EVENTS[RE_COWS_FROM_ALIENS]),
Expand Down Expand Up @@ -186,6 +212,13 @@ static RegisterShipInitFunc initFunc([]() {
CHECK(RC_ROMANI_RANCH_GRASS_55, true),
CHECK(RC_ROMANI_RANCH_GRASS_56, true),
CHECK(RC_ROMANI_RANCH_GRASS_57, true),
CHECK(RC_ROMANI_RANCH_TREE_01, true),
CHECK(RC_ROMANI_RANCH_TREE_02, true),
CHECK(RC_ROMANI_RANCH_TREE_03, true),
CHECK(RC_ROMANI_RANCH_TREE_04, true),
CHECK(RC_ROMANI_RANCH_TREE_05, true),
CHECK(RC_ROMANI_RANCH_TREE_06, true),
CHECK(RC_ROMANI_RANCH_TREE_07, true),
},
.exits = { // TO FROM
EXIT(ENTRANCE(MILK_ROAD, 1), ENTRANCE(ROMANI_RANCH, 0), true),
Expand Down
Loading