mirror of
https://github.com/TwilitRealm/dusklight
synced 2026-08-25 06:41:30 -04:00
Implement foolish items
This commit is contained in:
+135
-97
@@ -32,6 +32,7 @@
|
||||
#include "d/actor/d_a_npc_zrc.h"
|
||||
#include "d/actor/d_a_npc_zrz.h"
|
||||
#include "d/actor/d_a_obj_bosswarp.h"
|
||||
#include "d/actor/d_a_shop_item.h"
|
||||
#include "d/actor/d_a_obj_swBallC.h"
|
||||
#include "d/actor/d_a_obj_zra_rock.h"
|
||||
#include "d/actor/d_a_tag_kmsg.h"
|
||||
@@ -157,7 +158,9 @@ DEFINE_HOOK(&dGameover_c::_create, dGameover_c___create);
|
||||
DEFINE_HOOK(&daObjSwBallC_c::Create, daObjSwBallC_c__Create);
|
||||
DEFINE_HOOK(&daObjSwBallC_c::actionWait, daObjSwBallC_c__actionWait);
|
||||
|
||||
DEFINE_HOOK_SYMBOL("daDitem_Execute", int(daDitem_c*), daDitem_c__execute);
|
||||
DEFINE_HOOK(&daDitem_c::CreateInit, daDitem_c__CreateInit);
|
||||
|
||||
DEFINE_HOOK(&daShopItem_c::CreateInit, daShopItem_c__CreateInit);
|
||||
|
||||
DEFINE_HOOK(&daObjBossWarp_c::demoProc, daObjBossWarp_c__demoProc);
|
||||
|
||||
@@ -195,6 +198,7 @@ DEFINE_HOOK(&daItem_c::itemGet, daItem_c__itemGet);
|
||||
|
||||
DEFINE_HOOK(&daObjLife_c::setEffect, daObjLife_c__setEffect);
|
||||
DEFINE_HOOK(&daObjLife_c::create, daObjLife_c__create);
|
||||
DEFINE_HOOK(&daObjLife_c::Create, daObjLife_c__Create);
|
||||
DEFINE_HOOK(&daObjLife_c::actionGetDemo, daObjLife_c__actionGetDemo);
|
||||
DEFINE_HOOK(&daObjLife_c::calcScale, daObjLife_c__calcScale);
|
||||
|
||||
@@ -1797,7 +1801,7 @@ HookAction hookPreSetGetSubBgm(ModContext*, void* args, void*, void*) {
|
||||
se_type = SETYPE_ITEM_GET_ME_S;
|
||||
}
|
||||
|
||||
if (se_type != SETYPE_NONE || i_itemNo == dItemNo_Randomizer_FOOLISH_ITEM_e) {
|
||||
if (se_type != SETYPE_NONE) {
|
||||
mDoAud_subBgmStart(bgmLabel[se_type]);
|
||||
dComIfGp_setMesgBgmOn();
|
||||
}
|
||||
@@ -2360,25 +2364,50 @@ HookAction hookPreSwBallActionWait(ModContext*, void* args, void*, void*) {
|
||||
return HOOK_SKIP_ORIGINAL;
|
||||
}
|
||||
|
||||
void hookPostDitemExecute(ModContext*, void* args, void* retval, void*) {
|
||||
void hookPostDitemCreateInit(ModContext*, void* args, void*, void*) {
|
||||
auto* i_this = mods::arg<daDitem_c*>(args, 0);
|
||||
|
||||
// Certain items use field models that are too big to fit in link's hands so we want to scale them down to fit.
|
||||
switch (i_this->m_itemNo) {
|
||||
// Certain items use field models that are too big to fit in link's hands so we want to scale
|
||||
// them down to fit.
|
||||
f32 modelScale = 0.0f;
|
||||
switch (i_this->getDisplayItemNo()) {
|
||||
case dItemNo_Randomizer_MIRROR_PIECE_1_e:
|
||||
case dItemNo_Randomizer_MIRROR_PIECE_2_e:
|
||||
case dItemNo_Randomizer_MIRROR_PIECE_3_e:
|
||||
case dItemNo_Randomizer_MIRROR_PIECE_4_e:
|
||||
{
|
||||
i_this->scale.x = 0.05f;
|
||||
modelScale = 0.05f;
|
||||
break;
|
||||
}
|
||||
case dItemNo_Randomizer_MASTER_SWORD_e:
|
||||
case dItemNo_Randomizer_LIGHT_SWORD_e:
|
||||
{
|
||||
i_this->scale.x = 0.001f;
|
||||
modelScale = 0.001f;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
i_this->setMaxScale(modelScale);
|
||||
i_this->scale.setall(modelScale);
|
||||
i_this->set_mtx();
|
||||
}
|
||||
|
||||
void hookPostShopItemCreateInit(ModContext*, void* args, void*, void*) {
|
||||
auto* i_this = mods::arg<daShopItem_c*>(args, 0);
|
||||
|
||||
switch (i_this->getDisplayItemNo()) {
|
||||
case dItemNo_Randomizer_MASTER_SWORD_e:
|
||||
case dItemNo_Randomizer_LIGHT_SWORD_e: {
|
||||
f32 modelScale = 0.35f;
|
||||
if (strcmp("R_SP109", dComIfGp_getStartStageName()) == 0 &&
|
||||
dComIfGp_getStartStageRoomNo() == 1)
|
||||
{
|
||||
modelScale *= 0.8f;
|
||||
}
|
||||
i_this->scale.setall(modelScale);
|
||||
i_this->set_mtx();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2671,7 +2700,7 @@ void hookPostMenuRingGetItemNum(ModContext*, void* args, void* retval, void*) {
|
||||
void hookPostItemCreateInit(ModContext*, void* args, void*, void*) {
|
||||
auto* i_this = mods::arg<daItem_c*>(args, 0);
|
||||
|
||||
switch (i_this->m_itemNo) {
|
||||
switch (i_this->getDisplayItemNo()) {
|
||||
case dItemNo_Randomizer_KAKERA_HEART_e:
|
||||
case dItemNo_Randomizer_UTAWA_HEART_e:
|
||||
case dItemNo_Randomizer_ARROW_1_e:
|
||||
@@ -2795,7 +2824,7 @@ HookAction hookPreObjLifeSetEffect(ModContext*, void* args, void*, void*) {
|
||||
auto* i_this = mods::arg<daObjLife_c*>(args, 0);
|
||||
|
||||
// In randomizer, we don't want rupees or poe souls to sparkle. They are bright enough.
|
||||
switch (i_this->m_itemNo) {
|
||||
switch (i_this->getDisplayItemNo()) {
|
||||
case dItemNo_Randomizer_GREEN_RUPEE_e:
|
||||
case dItemNo_Randomizer_BLUE_RUPEE_e:
|
||||
case dItemNo_Randomizer_RED_RUPEE_e:
|
||||
@@ -2857,90 +2886,95 @@ HookAction hookPreObjLifeCreate(ModContext*, void* args, void* retval, void*) {
|
||||
}
|
||||
fopAcM_SetParam(i_this, (params & 0xFFFFFF00) | itemId);
|
||||
}
|
||||
}
|
||||
|
||||
// Also adjust the height of the object depending on the item
|
||||
switch (itemId) {
|
||||
case dItemNo_Randomizer_MASTER_SWORD_e:
|
||||
case dItemNo_Randomizer_LIGHT_SWORD_e:
|
||||
case dItemNo_Randomizer_WOOD_SHIELD_e:
|
||||
case dItemNo_Randomizer_HYLIA_SHIELD_e:
|
||||
case dItemNo_Randomizer_SHIELD_e:
|
||||
case dItemNo_Randomizer_SPINNER_e:
|
||||
{
|
||||
i_this->current.pos.y += 30.f;
|
||||
break;
|
||||
}
|
||||
case dItemNo_Randomizer_WOOD_STICK_e:
|
||||
{
|
||||
i_this->current.pos.y += 60.f;
|
||||
break;
|
||||
}
|
||||
case dItemNo_Randomizer_SWORD_e:
|
||||
case dItemNo_Randomizer_MIRROR_PIECE_1_e:
|
||||
case dItemNo_Randomizer_MIRROR_PIECE_2_e:
|
||||
case dItemNo_Randomizer_MIRROR_PIECE_3_e:
|
||||
case dItemNo_Randomizer_MIRROR_PIECE_4_e:
|
||||
case dItemNo_Randomizer_FUSED_SHADOW_1_e:
|
||||
case dItemNo_Randomizer_FUSED_SHADOW_2_e:
|
||||
case dItemNo_Randomizer_FUSED_SHADOW_3_e:
|
||||
case dItemNo_Randomizer_COPY_ROD_e:
|
||||
case dItemNo_Randomizer_COPY_ROD_2_e:
|
||||
{
|
||||
i_this->current.pos.y += 50.f;
|
||||
break;
|
||||
}
|
||||
return HOOK_CONTINUE;
|
||||
}
|
||||
|
||||
case dItemNo_Randomizer_BOW_e:
|
||||
{
|
||||
i_this->current.pos.y += 55.f;
|
||||
break;
|
||||
}
|
||||
case dItemNo_Randomizer_BOOMERANG_e:
|
||||
case dItemNo_Randomizer_FISHING_ROD_1_e:
|
||||
case dItemNo_Randomizer_ARROW_LV2_e:
|
||||
case dItemNo_Randomizer_ARROW_LV3_e:
|
||||
{
|
||||
i_this->current.pos.y += 40.f;
|
||||
break;
|
||||
}
|
||||
case dItemNo_Randomizer_FOREST_SMALL_KEY_e:
|
||||
case dItemNo_Randomizer_MINES_SMALL_KEY_e:
|
||||
case dItemNo_Randomizer_LAKEBED_SMALL_KEY_e:
|
||||
case dItemNo_Randomizer_ARBITERS_SMALL_KEY_e:
|
||||
case dItemNo_Randomizer_SNOWPEAK_SMALL_KEY_e:
|
||||
case dItemNo_Randomizer_TEMPLE_OF_TIME_SMALL_KEY_e:
|
||||
case dItemNo_Randomizer_CITY_SMALL_KEY_e:
|
||||
case dItemNo_Randomizer_PALACE_SMALL_KEY_e:
|
||||
case dItemNo_Randomizer_HYRULE_SMALL_KEY_e:
|
||||
case dItemNo_Randomizer_FOREST_BOSS_KEY_e:
|
||||
case dItemNo_Randomizer_LAKEBED_BOSS_KEY_e:
|
||||
case dItemNo_Randomizer_ARBITERS_BOSS_KEY_e:
|
||||
case dItemNo_Randomizer_TEMPLE_OF_TIME_BOSS_KEY_e:
|
||||
case dItemNo_Randomizer_CITY_BOSS_KEY_e:
|
||||
case dItemNo_Randomizer_PALACE_BOSS_KEY_e:
|
||||
case dItemNo_Randomizer_HYRULE_BOSS_KEY_e:
|
||||
case dItemNo_Randomizer_SMALL_KEY2_e:
|
||||
case dItemNo_Randomizer_LV5_BOSS_KEY_e:
|
||||
case dItemNo_Randomizer_CAMP_SMALL_KEY_e:
|
||||
case dItemNo_Randomizer_BOSSRIDER_KEY_e:
|
||||
case dItemNo_Randomizer_PACHINKO_e:
|
||||
case dItemNo_Randomizer_BOMB_BAG_LV2_e:
|
||||
case dItemNo_Randomizer_BOMB_BAG_LV1_e:
|
||||
case dItemNo_Randomizer_BOMB_IN_BAG_e:
|
||||
case dItemNo_Randomizer_NORMAL_BOMB_e:
|
||||
case dItemNo_Randomizer_POU_SPIRIT_e:
|
||||
{
|
||||
i_this->current.pos.y += 20.f;
|
||||
break;
|
||||
}
|
||||
case dItemNo_Randomizer_ARMOR_e:
|
||||
{
|
||||
i_this->current.pos.y += 25.f;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
HookAction hookPreObjLifeCreateInit(ModContext*, void* args, void*, void*) {
|
||||
auto* i_this = mods::arg<daObjLife_c*>(args, 0);
|
||||
|
||||
if (i_this->m_itemNo == dItemNo_Randomizer_FOOLISH_ITEM_e) {
|
||||
const u8 stage = getStageID();
|
||||
i_this->mOverrideHover = stage == Hyrule_Field || stage == Upper_Zoras_River ||
|
||||
stage == Sacred_Grove || stage == Stallord ||
|
||||
stage == Zant_Main_Room;
|
||||
}
|
||||
|
||||
// Models use different origins, so keep their visible geometry above the pedestal or ground.
|
||||
switch (i_this->getDisplayItemNo()) {
|
||||
case dItemNo_Randomizer_MASTER_SWORD_e:
|
||||
case dItemNo_Randomizer_LIGHT_SWORD_e:
|
||||
case dItemNo_Randomizer_WOOD_SHIELD_e:
|
||||
case dItemNo_Randomizer_HYLIA_SHIELD_e:
|
||||
case dItemNo_Randomizer_SHIELD_e:
|
||||
case dItemNo_Randomizer_SPINNER_e: {
|
||||
i_this->current.pos.y += 30.f;
|
||||
break;
|
||||
}
|
||||
case dItemNo_Randomizer_WOOD_STICK_e: {
|
||||
i_this->current.pos.y += 60.f;
|
||||
break;
|
||||
}
|
||||
case dItemNo_Randomizer_SWORD_e:
|
||||
case dItemNo_Randomizer_MIRROR_PIECE_1_e:
|
||||
case dItemNo_Randomizer_MIRROR_PIECE_2_e:
|
||||
case dItemNo_Randomizer_MIRROR_PIECE_3_e:
|
||||
case dItemNo_Randomizer_MIRROR_PIECE_4_e:
|
||||
case dItemNo_Randomizer_FUSED_SHADOW_1_e:
|
||||
case dItemNo_Randomizer_FUSED_SHADOW_2_e:
|
||||
case dItemNo_Randomizer_FUSED_SHADOW_3_e:
|
||||
case dItemNo_Randomizer_COPY_ROD_e:
|
||||
case dItemNo_Randomizer_COPY_ROD_2_e: {
|
||||
i_this->current.pos.y += 50.f;
|
||||
break;
|
||||
}
|
||||
case dItemNo_Randomizer_BOW_e: {
|
||||
i_this->current.pos.y += 55.f;
|
||||
break;
|
||||
}
|
||||
case dItemNo_Randomizer_BOOMERANG_e:
|
||||
case dItemNo_Randomizer_FISHING_ROD_1_e:
|
||||
case dItemNo_Randomizer_ARROW_LV2_e:
|
||||
case dItemNo_Randomizer_ARROW_LV3_e: {
|
||||
i_this->current.pos.y += 40.f;
|
||||
break;
|
||||
}
|
||||
case dItemNo_Randomizer_FOREST_SMALL_KEY_e:
|
||||
case dItemNo_Randomizer_MINES_SMALL_KEY_e:
|
||||
case dItemNo_Randomizer_LAKEBED_SMALL_KEY_e:
|
||||
case dItemNo_Randomizer_ARBITERS_SMALL_KEY_e:
|
||||
case dItemNo_Randomizer_SNOWPEAK_SMALL_KEY_e:
|
||||
case dItemNo_Randomizer_TEMPLE_OF_TIME_SMALL_KEY_e:
|
||||
case dItemNo_Randomizer_CITY_SMALL_KEY_e:
|
||||
case dItemNo_Randomizer_PALACE_SMALL_KEY_e:
|
||||
case dItemNo_Randomizer_HYRULE_SMALL_KEY_e:
|
||||
case dItemNo_Randomizer_FOREST_BOSS_KEY_e:
|
||||
case dItemNo_Randomizer_LAKEBED_BOSS_KEY_e:
|
||||
case dItemNo_Randomizer_ARBITERS_BOSS_KEY_e:
|
||||
case dItemNo_Randomizer_TEMPLE_OF_TIME_BOSS_KEY_e:
|
||||
case dItemNo_Randomizer_CITY_BOSS_KEY_e:
|
||||
case dItemNo_Randomizer_PALACE_BOSS_KEY_e:
|
||||
case dItemNo_Randomizer_HYRULE_BOSS_KEY_e:
|
||||
case dItemNo_Randomizer_SMALL_KEY2_e:
|
||||
case dItemNo_Randomizer_LV5_BOSS_KEY_e:
|
||||
case dItemNo_Randomizer_CAMP_SMALL_KEY_e:
|
||||
case dItemNo_Randomizer_BOSSRIDER_KEY_e:
|
||||
case dItemNo_Randomizer_PACHINKO_e:
|
||||
case dItemNo_Randomizer_BOMB_BAG_LV2_e:
|
||||
case dItemNo_Randomizer_BOMB_BAG_LV1_e:
|
||||
case dItemNo_Randomizer_BOMB_IN_BAG_e:
|
||||
case dItemNo_Randomizer_NORMAL_BOMB_e:
|
||||
case dItemNo_Randomizer_POU_SPIRIT_e: {
|
||||
i_this->current.pos.y += 20.f;
|
||||
break;
|
||||
}
|
||||
case dItemNo_Randomizer_ARMOR_e: {
|
||||
i_this->current.pos.y += 25.f;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return HOOK_CONTINUE;
|
||||
@@ -2970,7 +3004,7 @@ HookAction hookPreObjLifeCalcScale(ModContext*, void* args, void* retval, void*)
|
||||
|
||||
// Change scale for certain items
|
||||
f32 newScale = 1.0f;
|
||||
switch (i_this->m_itemNo) {
|
||||
switch (i_this->getDisplayItemNo()) {
|
||||
case dItemNo_Randomizer_KAKERA_HEART_e:
|
||||
case dItemNo_Randomizer_UTAWA_HEART_e:
|
||||
case dItemNo_Randomizer_ARROW_10_e:
|
||||
@@ -3217,7 +3251,8 @@ ModResult initialize() {
|
||||
ADD_HOOK_POST(daObjSwBallC_c__Create, hookPostSwBallCreate);
|
||||
ADD_HOOK_PRE(daObjSwBallC_c__actionWait, hookPreSwBallActionWait);
|
||||
|
||||
ADD_HOOK_POST(daDitem_c__execute, hookPostDitemExecute);
|
||||
ADD_HOOK_POST(daDitem_c__CreateInit, hookPostDitemCreateInit);
|
||||
ADD_HOOK_POST(daShopItem_c__CreateInit, hookPostShopItemCreateInit);
|
||||
|
||||
ADD_HOOK_PRE(daObjBossWarp_c__demoProc, hookPreBossWarpDemoProc);
|
||||
ADD_HOOK_POST(daObjBossWarp_c__demoProc, hookPostBossWarpDemoProc);
|
||||
@@ -3247,6 +3282,7 @@ ModResult initialize() {
|
||||
|
||||
ADD_HOOK_PRE(daObjLife_c__setEffect, hookPreObjLifeSetEffect);
|
||||
ADD_HOOK_PRE(daObjLife_c__create, hookPreObjLifeCreate);
|
||||
ADD_HOOK_PRE(daObjLife_c__Create, hookPreObjLifeCreateInit);
|
||||
ADD_HOOK_PRE(daObjLife_c__actionGetDemo, hookPreObjLifeActionGetDemo);
|
||||
ADD_HOOK_PRE(daObjLife_c__calcScale, hookPreObjLifeCalcScale);
|
||||
|
||||
@@ -3353,7 +3389,8 @@ ModResult uninstall() {
|
||||
mods::hook::uninstall<daObjSwBallC_c__Create>(svc_hook);
|
||||
mods::hook::uninstall<daObjSwBallC_c__actionWait>(svc_hook);
|
||||
|
||||
mods::hook::uninstall<daDitem_c__execute>(svc_hook);
|
||||
mods::hook::uninstall<daDitem_c__CreateInit>(svc_hook);
|
||||
mods::hook::uninstall<daShopItem_c__CreateInit>(svc_hook);
|
||||
|
||||
mods::hook::uninstall<daObjBossWarp_c__demoProc>(svc_hook);
|
||||
|
||||
@@ -3378,6 +3415,7 @@ ModResult uninstall() {
|
||||
|
||||
mods::hook::uninstall<daObjLife_c__setEffect>(svc_hook);
|
||||
mods::hook::uninstall<daObjLife_c__create>(svc_hook);
|
||||
mods::hook::uninstall<daObjLife_c__Create>(svc_hook);
|
||||
mods::hook::uninstall<daObjLife_c__actionGetDemo>(svc_hook);
|
||||
mods::hook::uninstall<daObjLife_c__calcScale>(svc_hook);
|
||||
|
||||
|
||||
@@ -573,19 +573,10 @@ static bool checkFoolishItemEffectReady()
|
||||
return false;
|
||||
}
|
||||
|
||||
// Ensure there are pointers to the mMeterClass and mpMeterDraw structs
|
||||
if (!dMeter2Info_getMeterClass())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!dMeter2Info_getMeterClass()->getMeterDrawPtr())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Make sure Z button isn't dimmed
|
||||
if (dMeter2Info_getMeterClass()->getMeterDrawPtr()->getButtonZAlpha() != 1.f)
|
||||
if (dComIfGs_isEventBit(MIDNA_ACCOMPANIES_WOLF) && dMeter2Info_getMeterClass() &&
|
||||
dMeter2Info_getMeterClass()->getMeterDrawPtr() &&
|
||||
dMeter2Info_getMeterClass()->getMeterDrawPtr()->getButtonZAlpha() != 1.f)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -1032,7 +1023,7 @@ void randomizer_returnToSpawn(bool tryOverride) {
|
||||
dComIfGp_setNextStage("F_SP103", 1, 1, -1);
|
||||
}
|
||||
|
||||
u8 randomizer_getRandomFoolishItemModelID() {
|
||||
u8 randomizer_getRandomFoolishItemModelID(std::string_view checkName) {
|
||||
static constexpr auto foolishItemModels = std::to_array<u8>({
|
||||
dItemNo_Randomizer_ARMOR_e,
|
||||
dItemNo_Randomizer_WOOD_STICK_e,
|
||||
@@ -1053,8 +1044,13 @@ u8 randomizer_getRandomFoolishItemModelID() {
|
||||
dItemNo_Randomizer_ANCIENT_DOCUMENT_e,
|
||||
});
|
||||
|
||||
u8 selectedModal = foolishItemModels[static_cast<int>(cM_rnd() * foolishItemModels.size()) % foolishItemModels.size()];
|
||||
return verifyProgressiveItem(selectedModal);
|
||||
static constexpr char separator = '\0';
|
||||
const std::string& seedHash = randomizer_GetContext().mHash;
|
||||
u32 hash = randomizer::utility::crc32(seedHash.data(), seedHash.size());
|
||||
hash = randomizer::utility::crc32(&separator, sizeof(separator), hash);
|
||||
hash = randomizer::utility::crc32(checkName.data(), checkName.size(), hash);
|
||||
const u8 selectedModel = foolishItemModels[hash % foolishItemModels.size()];
|
||||
return verifyProgressiveItem(selectedModel);
|
||||
}
|
||||
|
||||
u32 getActorPatchesCurrentStageKey(u8 roomNo) {
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <optional>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
@@ -266,7 +267,7 @@ bool randomizer_mirrorChamberWallShouldExist();
|
||||
|
||||
void randomizer_returnToSpawn(bool tryDungeon);
|
||||
|
||||
u8 randomizer_getRandomFoolishItemModelID();
|
||||
u8 randomizer_getRandomFoolishItemModelID(std::string_view checkName);
|
||||
|
||||
/**
|
||||
* Helper function to convert raw bytes of a container to a hex string
|
||||
|
||||
@@ -83,61 +83,70 @@ std::optional<u16> parse_flag_check(const char* name, std::string_view prefix) {
|
||||
return static_cast<u16>(flag);
|
||||
}
|
||||
|
||||
bool set_resolution(
|
||||
const ItemCheckInfo* info, ItemCheckResolution* outResult, uint8_t resolvedItem) {
|
||||
outResult->item = resolvedItem;
|
||||
if (resolvedItem == dItemNo_Randomizer_FOOLISH_ITEM_e) {
|
||||
outResult->display_item = randomizer_getRandomFoolishItemModelID(info->name);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename Map>
|
||||
bool lookup_override(const Map& map, u16 key, uint8_t* out_item) {
|
||||
bool lookup_override(
|
||||
const Map& map, u16 key, const ItemCheckInfo* info, ItemCheckResolution* outResult) {
|
||||
const auto it = map.find(key);
|
||||
if (it == map.end()) {
|
||||
return false;
|
||||
}
|
||||
*out_item = static_cast<uint8_t>(verifyProgressiveItem(it->second));
|
||||
return true;
|
||||
return set_resolution(info, outResult, static_cast<uint8_t>(verifyProgressiveItem(it->second)));
|
||||
}
|
||||
|
||||
bool resolve_check(ModContext*, const ItemCheckInfo* info, ItemCheckResolution* out, void*) {
|
||||
bool resolve_check(ModContext*, const ItemCheckInfo* info, ItemCheckResolution* outResult, void*) {
|
||||
auto& ctx = randomizer_GetContext();
|
||||
|
||||
if (auto it = ctx.mItemLocations.find(info->name); it != ctx.mItemLocations.end()) {
|
||||
out->item = static_cast<uint8_t>(verifyProgressiveItem(it->second.itemId));
|
||||
return true;
|
||||
return set_resolution(
|
||||
info, outResult, static_cast<uint8_t>(verifyProgressiveItem(it->second.itemId)));
|
||||
}
|
||||
|
||||
if (auto key = parse_derived(info->name, ITEM_CHECK_CHEST_PREFIX)) {
|
||||
return lookup_override(ctx.mTreasureChestOverrides, key->key, &out->item);
|
||||
return lookup_override(ctx.mTreasureChestOverrides, key->key, info, outResult);
|
||||
}
|
||||
if (auto key = parse_derived(info->name, ITEM_CHECK_FREESTANDING_PREFIX)) {
|
||||
if (key->stage_id == Ook) {
|
||||
if (auto it = ctx.mItemLocations.find("Forest Temple Gale Boomerang");
|
||||
it != ctx.mItemLocations.end()) {
|
||||
out->item = static_cast<uint8_t>(verifyProgressiveItem(it->second.itemId));
|
||||
return true;
|
||||
return set_resolution(info, outResult,
|
||||
static_cast<uint8_t>(verifyProgressiveItem(it->second.itemId)));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return lookup_override(ctx.mFreestandingItemOverrides, key->key, &out->item);
|
||||
return lookup_override(ctx.mFreestandingItemOverrides, key->key, info, outResult);
|
||||
}
|
||||
if (auto flag = parse_flag_check(info->name, ITEM_CHECK_GOLDEN_WOLF_PREFIX)) {
|
||||
return lookup_override(ctx.mGoldenWolfOverrides, *flag, &out->item);
|
||||
return lookup_override(ctx.mGoldenWolfOverrides, *flag, info, outResult);
|
||||
}
|
||||
if (auto key = parse_derived(info->name, ITEM_CHECK_POE_PREFIX)) {
|
||||
return lookup_override(ctx.mPoeOverrides, key->key, &out->item);
|
||||
return lookup_override(ctx.mPoeOverrides, key->key, info, outResult);
|
||||
}
|
||||
if (auto stageId = parse_stage_check(info->name, ITEM_CHECK_BOSS_PREFIX)) {
|
||||
const u16 key = static_cast<u16>((*stageId << 8) | 0x9F);
|
||||
return lookup_override(ctx.mFreestandingItemOverrides, key, &out->item);
|
||||
return lookup_override(ctx.mFreestandingItemOverrides, key, info, outResult);
|
||||
}
|
||||
if (auto key = parse_derived(info->name, ITEM_CHECK_SHOP_PREFIX)) {
|
||||
return lookup_override(ctx.mShopOverrides, key->key, &out->item);
|
||||
return lookup_override(ctx.mShopOverrides, key->key, info, outResult);
|
||||
}
|
||||
if (auto key = parse_derived(info->name, ITEM_CHECK_SKY_PREFIX)) {
|
||||
return lookup_override(ctx.mSkyCharacterOverrides, key->key, &out->item);
|
||||
return lookup_override(ctx.mSkyCharacterOverrides, key->key, info, outResult);
|
||||
}
|
||||
|
||||
constexpr std::string_view bugPrefix{ITEM_CHECK_BUG_PREFIX};
|
||||
if (std::strncmp(info->name, bugPrefix.data(), bugPrefix.size()) == 0) {
|
||||
const u8 insect = static_cast<u8>(std::atoi(info->name + bugPrefix.size()));
|
||||
if (auto it = ctx.mBugRewardOverrides.find(insect); it != ctx.mBugRewardOverrides.end()) {
|
||||
out->item = static_cast<uint8_t>(verifyProgressiveItem(it->second));
|
||||
return true;
|
||||
return set_resolution(
|
||||
info, outResult, static_cast<uint8_t>(verifyProgressiveItem(it->second)));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
#define ITEM_SERVICE_ID "dev.twilitrealm.dusklight.item"
|
||||
#define ITEM_SERVICE_MAJOR 2u
|
||||
#define ITEM_SERVICE_MINOR 1u
|
||||
#define ITEM_SERVICE_MINOR 2u
|
||||
|
||||
/* 0 is never a valid handle. */
|
||||
typedef uint64_t ItemCheckHandle;
|
||||
@@ -97,6 +97,13 @@ typedef struct ItemService {
|
||||
ModContext* ctx, ItemGiveObserveFn fn, void* user_data, ItemGiveHandle* out_handle);
|
||||
|
||||
ModResult (*unobserve_gives)(ModContext* ctx, ItemGiveHandle handle);
|
||||
|
||||
/* Minor version 2 */
|
||||
|
||||
/* Resolve a live preview (item + display item) without granting an item or notifying give
|
||||
* observers. */
|
||||
ModResult (*resolve_check_full)(ModContext* ctx, const char* name, uint8_t vanilla_item,
|
||||
ItemCheckResolution* out_resolution);
|
||||
} ItemService;
|
||||
|
||||
MOD_DECLARE_SERVICE(ItemService, svc_item, ITEM_SERVICE_ID, ITEM_SERVICE_MAJOR, ITEM_SERVICE_MINOR);
|
||||
|
||||
@@ -550,7 +550,7 @@ static int daDitem_Execute(daDitem_c* i_this) {
|
||||
}
|
||||
|
||||
int daDitem_c::draw() {
|
||||
switch (m_itemNo) {
|
||||
switch (DUSK_IF_ELSE(getDisplayItemNo(), m_itemNo)) {
|
||||
case dItemNo_WOOD_STICK_e:
|
||||
draw_WOOD_STICK();
|
||||
break;
|
||||
|
||||
@@ -108,6 +108,7 @@ const char* daShopItem_c::getShopArcname() {
|
||||
mItemGiveTag = dusk::mods::item_give_tag_shop(mItemGiveOriginalNo);
|
||||
const auto [_, displayItem] =
|
||||
dusk::mods::item_check_resolve(mItemGiveTag, mItemGiveOriginalNo, this);
|
||||
setDisplayItemNo(displayItem);
|
||||
mItemOverridden = displayItem != mItemGiveOriginalNo;
|
||||
if (mItemOverridden) {
|
||||
mOverrideData = mData[mShopItemID];
|
||||
|
||||
@@ -75,6 +75,17 @@ ModResult item_resolve_check(
|
||||
return MOD_OK;
|
||||
}
|
||||
|
||||
ModResult item_resolve_check_full(ModContext* context, const char* name, uint8_t originalItemNo,
|
||||
ItemCheckResolution* outResolution) {
|
||||
if (mod_from_context(context) == nullptr || !is_valid_check_name(name) ||
|
||||
outResolution == nullptr)
|
||||
{
|
||||
return MOD_INVALID_ARGUMENT;
|
||||
}
|
||||
*outResolution = item_check_resolve(name, originalItemNo, nullptr);
|
||||
return MOD_OK;
|
||||
}
|
||||
|
||||
ModResult item_give_item(
|
||||
ModContext* context, const char* checkName, uint8_t itemNo, uint32_t flags) {
|
||||
auto* mod = mod_from_context(context);
|
||||
@@ -130,6 +141,7 @@ constexpr ItemService s_itemService{
|
||||
.give_item = item_give_item,
|
||||
.observe_gives = item_observe_gives,
|
||||
.unobserve_gives = item_unobserve_gives,
|
||||
.resolve_check_full = item_resolve_check_full,
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
Reference in New Issue
Block a user