mirror of
https://github.com/HarbourMasters/Shipwright.git
synced 2025-01-10 13:38:08 -05:00
Holiday Modding Event - Bomb Arrows (#4573)
* Bomb Arrows: Turn arrows into bomb arrows * Bomb Arrows: Drain bombs when fired * Bomb Arrows: Equip Over Bow * Bomb Arrows: Item icons and ammo counts * Bomb Arrows: Save files * Bomb Arrows: Fix equip and ammo display bugs * Bomb Arrows: Interactions with multi-arrows * Bomb Arrows: Fix fuse graphics
This commit is contained in:
parent
0f48970576
commit
f1dc432589
136
soh/soh/Enhancements/Holiday/lilDavid.cpp
Normal file
136
soh/soh/Enhancements/Holiday/lilDavid.cpp
Normal file
@ -0,0 +1,136 @@
|
||||
#include "Holiday.hpp"
|
||||
|
||||
#include "utils/StringHelper.h"
|
||||
|
||||
extern "C" {
|
||||
#include "macros.h"
|
||||
#include "functions.h"
|
||||
#include "variables.h"
|
||||
extern PlayState* gPlayState;
|
||||
}
|
||||
|
||||
#include "src/overlays/actors/ovl_En_Arrow/z_en_arrow.h"
|
||||
#include "src/overlays/actors/ovl_En_Bom/z_en_bom.h"
|
||||
|
||||
extern "C" {
|
||||
void func_809B45E0(EnArrow*, PlayState*);
|
||||
void func_809B4640(EnArrow*, PlayState*);
|
||||
}
|
||||
|
||||
#define AUTHOR "lilDavid"
|
||||
#define CVAR(v) "gHoliday." AUTHOR "." v
|
||||
|
||||
static void OnConfigurationChanged() {
|
||||
if (!CVarGetInteger(CVAR("BombArrows.Enabled"), 0))
|
||||
CVarSetInteger(CVAR("BombArrows.Active"), 0);
|
||||
|
||||
COND_HOOK(OnSaveFile, CVarGetInteger(CVAR("BombArrows.Enabled"), 0), [](int32_t file) {
|
||||
std::string cvar = StringHelper::Sprintf("%s%d", CVAR("BombArrows.Save"), file);
|
||||
CVarSetInteger(cvar.c_str(), CVarGetInteger(CVAR("BombArrows.Active"), 0));
|
||||
Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick();
|
||||
});
|
||||
|
||||
COND_HOOK(OnLoadFile, CVarGetInteger(CVAR("BombArrows.Enabled"), 0), [](int32_t file) {
|
||||
std::string cvar = StringHelper::Sprintf("%s%d", CVAR("BombArrows.Save"), file);
|
||||
CVarSetInteger(CVAR("BombArrows.Active"), CVarGetInteger(cvar.c_str(), 0));
|
||||
});
|
||||
|
||||
COND_HOOK(OnCopyFile, CVarGetInteger(CVAR("BombArrows.Enabled"), 0), [](int32_t from, int32_t to) {
|
||||
std::string cvarFrom = StringHelper::Sprintf("%s%d", CVAR("BombArrows.Save"), from);
|
||||
std::string cvarTo = StringHelper::Sprintf("%s%d", CVAR("BombArrows.Save"), to);
|
||||
CVarSetInteger(cvarTo.c_str(), CVarGetInteger(cvarFrom.c_str(), 0));
|
||||
Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick();
|
||||
});
|
||||
|
||||
COND_HOOK(OnDeleteFile, CVarGetInteger(CVAR("BombArrows.Enabled"), 0), [](int32_t file) {
|
||||
std::string cvar = StringHelper::Sprintf("%s%d", CVAR("BombArrows.Save"), file);
|
||||
CVarSetInteger(cvar.c_str(), 0);
|
||||
Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick();
|
||||
});
|
||||
|
||||
COND_ID_HOOK(OnActorInit, ACTOR_EN_ARROW, CVarGetInteger(CVAR("BombArrows.Enabled"), 0), [](void* actorRef) {
|
||||
EnArrow* arrow = (EnArrow*) actorRef;
|
||||
if (!CVarGetInteger(CVAR("BombArrows.Active"), 0) ||
|
||||
arrow->actor.params != ARROW_NORMAL || AMMO(ITEM_BOMB) == 0 ||
|
||||
gSaveContext.minigameState == 1 || gPlayState->shootingGalleryStatus > 1)
|
||||
return;
|
||||
|
||||
EnBom* bomb = (EnBom*) Actor_SpawnAsChild(&gPlayState->actorCtx, &arrow->actor, gPlayState, ACTOR_EN_BOM,
|
||||
arrow->actor.world.pos.x, arrow->actor.world.pos.y, arrow->actor.world.pos.z,
|
||||
0, 0, 0, BOMB_BODY);
|
||||
if (bomb == nullptr)
|
||||
return;
|
||||
|
||||
Actor_SetScale(&bomb->actor, 0.003f);
|
||||
bomb->timer = 65;
|
||||
});
|
||||
|
||||
COND_ID_HOOK(OnActorUpdate, ACTOR_EN_ARROW, CVarGetInteger(CVAR("BombArrows.Enabled"), 0), [](void* actorRef) {
|
||||
EnArrow* arrow = (EnArrow*) actorRef;
|
||||
if (!arrow->actor.child || arrow->actor.child->id != ACTOR_EN_BOM)
|
||||
return;
|
||||
|
||||
EnBom* bomb = (EnBom*) arrow->actor.child;
|
||||
bomb->actor.world.pos = arrow->actor.world.pos;
|
||||
f32 r = 8.0f;
|
||||
f32 xrot = arrow->actor.world.rot.x;
|
||||
f32 yrot = arrow->actor.world.rot.y;
|
||||
bomb->actor.world.pos.x += r * Math_CosS(xrot) * Math_SinS(yrot);
|
||||
bomb->actor.world.pos.y -= r * Math_SinS(xrot) + 2.0f;
|
||||
bomb->actor.world.pos.z += r * Math_CosS(xrot) * Math_CosS(yrot);
|
||||
|
||||
if (arrow->actor.parent == nullptr) {
|
||||
if (bomb->timer > 60) {
|
||||
Inventory_ChangeAmmo(ITEM_BOMB, -1);
|
||||
}
|
||||
bomb->timer = 52;
|
||||
} else {
|
||||
bomb->timer = 62;
|
||||
}
|
||||
|
||||
if (arrow->actionFunc == func_809B45E0 ||
|
||||
arrow->actionFunc == func_809B4640 ||
|
||||
arrow->actor.params == ARROW_NORMAL_LIT)
|
||||
{
|
||||
arrow->actor.child = nullptr;
|
||||
bomb->actor.parent = nullptr;
|
||||
bomb->timer = 2;
|
||||
Actor_Kill(&arrow->actor);
|
||||
}
|
||||
});
|
||||
|
||||
COND_ID_HOOK(OnActorKill, ACTOR_EN_ARROW, CVarGetInteger(CVAR("BombArrows.Enabled"), 0), [](void* actorRef) {
|
||||
EnArrow* arrow = (EnArrow*) actorRef;
|
||||
if (!arrow->actor.child || arrow->actor.child->id != ACTOR_EN_BOM)
|
||||
return;
|
||||
Actor_Kill(arrow->actor.child);
|
||||
});
|
||||
|
||||
COND_ID_HOOK(OnActorUpdate, ACTOR_EN_BOM, CVarGetInteger(CVAR("BombArrows.Enabled"), 0), [](void* actorRef) {
|
||||
EnBom* bomb = (EnBom*) actorRef;
|
||||
if (!bomb->actor.parent || bomb->actor.parent->id != ACTOR_EN_ARROW)
|
||||
return;
|
||||
|
||||
if (bomb->timer > 55 && bomb->timer < 60)
|
||||
bomb->timer += 4;
|
||||
if (bomb->timer > 45 && bomb->timer < 50)
|
||||
bomb->timer += 4;
|
||||
});
|
||||
}
|
||||
|
||||
static void DrawMenu() {
|
||||
ImGui::SeparatorText(AUTHOR);
|
||||
if (UIWidgets::EnhancementCheckbox("Bomb Arrows", CVAR("BombArrows.Enabled"))) {
|
||||
OnConfigurationChanged();
|
||||
}
|
||||
}
|
||||
|
||||
static void RegisterMod() {
|
||||
// #region Leave this alone unless you know what you are doing
|
||||
OnConfigurationChanged();
|
||||
// #endregion
|
||||
|
||||
CVarSetInteger(CVAR("BombArrows.Active"), 0);
|
||||
}
|
||||
|
||||
static Holiday holiday(DrawMenu, RegisterMod);
|
@ -37,6 +37,7 @@ DEFINE_HOOK(OnOpenText, (u16 * textId, bool* loadFromMessageTable));
|
||||
DEFINE_HOOK(OnVanillaBehavior, (GIVanillaBehavior flag, bool* result, va_list originalArgs));
|
||||
DEFINE_HOOK(OnSaveFile, (int32_t fileNum));
|
||||
DEFINE_HOOK(OnLoadFile, (int32_t fileNum));
|
||||
DEFINE_HOOK(OnCopyFile, (int32_t sourceFileNum, uint32_t destFileNum));
|
||||
DEFINE_HOOK(OnDeleteFile, (int32_t fileNum));
|
||||
|
||||
DEFINE_HOOK(OnDialogMessage, ());
|
||||
|
@ -184,6 +184,10 @@ void GameInteractor_ExecuteOnLoadFile(int32_t fileNum) {
|
||||
GameInteractor::Instance->ExecuteHooks<GameInteractor::OnLoadFile>(fileNum);
|
||||
}
|
||||
|
||||
void GameInteractor_ExecuteOnCopyFile(int32_t sourceFileNum, int32_t destFileNum) {
|
||||
GameInteractor::Instance->ExecuteHooks<GameInteractor::OnCopyFile>(sourceFileNum, destFileNum);
|
||||
}
|
||||
|
||||
void GameInteractor_ExecuteOnDeleteFile(int32_t fileNum) {
|
||||
GameInteractor::Instance->ExecuteHooks<GameInteractor::OnDeleteFile>(fileNum);
|
||||
}
|
||||
|
@ -40,6 +40,7 @@ bool GameInteractor_Should(GIVanillaBehavior flag, uint32_t result, ...);
|
||||
// MARK: - Save Files
|
||||
void GameInteractor_ExecuteOnSaveFile(int32_t fileNum);
|
||||
void GameInteractor_ExecuteOnLoadFile(int32_t fileNum);
|
||||
void GameInteractor_ExecuteOnCopyFile(int32_t sourceFileNum, int32_t destFileNum);
|
||||
void GameInteractor_ExecuteOnDeleteFile(int32_t fileNum);
|
||||
|
||||
// MARK: - Dialog
|
||||
|
@ -2458,6 +2458,7 @@ void SaveManager::CopyZeldaFile(int from, int to) {
|
||||
fileMetaInfo[to].buildVersionPatch = fileMetaInfo[from].buildVersionPatch;
|
||||
SohUtils::CopyStringToCharArray(fileMetaInfo[to].buildVersion, fileMetaInfo[from].buildVersion,
|
||||
ARRAY_COUNT(fileMetaInfo[to].buildVersion));
|
||||
GameInteractor::Instance->ExecuteHooks<GameInteractor::OnCopyFile>(from, to);
|
||||
}
|
||||
|
||||
void SaveManager::DeleteZeldaFile(int fileNum) {
|
||||
|
@ -4722,6 +4722,11 @@ void Interface_DrawAmmoCount(PlayState* play, s16 button, s16 alpha) {
|
||||
}
|
||||
|
||||
ammo = AMMO(i);
|
||||
if (CVarGetInteger("gHoliday.lilDavid.BombArrows.Active", 0) &&
|
||||
gSaveContext.equips.buttonItems[button] == ITEM_BOW &&
|
||||
AMMO(ITEM_BOMB) != 0 && AMMO(ITEM_BOMB) < AMMO(ITEM_BOW)) {
|
||||
ammo = AMMO(ITEM_BOMB);
|
||||
}
|
||||
|
||||
gDPPipeSync(OVERLAY_DISP++);
|
||||
|
||||
@ -4734,6 +4739,11 @@ void Interface_DrawAmmoCount(PlayState* play, s16 button, s16 alpha) {
|
||||
if (ammo < 0) {
|
||||
ammo = 0;
|
||||
}
|
||||
} else if (gSaveContext.equips.buttonItems[button] == ITEM_BOW &&
|
||||
CVarGetInteger("gHoliday.lilDavid.BombArrows.Active", 0)) {
|
||||
if (AMMO(ITEM_BOMB) != 0 && ammo == MIN(CUR_CAPACITY(UPG_QUIVER), CUR_CAPACITY(UPG_BOMB_BAG))) {
|
||||
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, 120, 255, 0, alpha);
|
||||
}
|
||||
} else if (((i == ITEM_BOW) && (AMMO(i) == CUR_CAPACITY(UPG_QUIVER))) ||
|
||||
((i == ITEM_BOMB) && (AMMO(i) == CUR_CAPACITY(UPG_BOMB_BAG))) ||
|
||||
((i == ITEM_SLINGSHOT) && (AMMO(i) == CUR_CAPACITY(UPG_BULLET_BAG))) ||
|
||||
@ -5311,6 +5321,9 @@ void Interface_Draw(PlayState* play) {
|
||||
if (gSaveContext.equips.buttonItems[1] < 0xF0) {
|
||||
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, 255, 255, 255, interfaceCtx->cLeftAlpha);
|
||||
gDPSetCombineMode(OVERLAY_DISP++, G_CC_MODULATERGBA_PRIM, G_CC_MODULATERGBA_PRIM);
|
||||
if (gSaveContext.equips.buttonItems[1] == ITEM_BOW && CVarGetInteger("gHoliday.lilDavid.BombArrows.Active", 0)) {
|
||||
Interface_DrawItemIconTexture(play, gItemIcons[ITEM_BOMB], 1);
|
||||
}
|
||||
Interface_DrawItemIconTexture(play, gItemIcons[gSaveContext.equips.buttonItems[1]], 1);
|
||||
gDPPipeSync(OVERLAY_DISP++);
|
||||
gDPSetCombineLERP(OVERLAY_DISP++, PRIMITIVE, ENVIRONMENT, TEXEL0, ENVIRONMENT, TEXEL0, 0, PRIMITIVE, 0,
|
||||
@ -5324,6 +5337,9 @@ void Interface_Draw(PlayState* play) {
|
||||
if (gSaveContext.equips.buttonItems[2] < 0xF0) {
|
||||
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, 255, 255, 255, interfaceCtx->cDownAlpha);
|
||||
gDPSetCombineMode(OVERLAY_DISP++, G_CC_MODULATERGBA_PRIM, G_CC_MODULATERGBA_PRIM);
|
||||
if (gSaveContext.equips.buttonItems[2] == ITEM_BOW && CVarGetInteger("gHoliday.lilDavid.BombArrows.Active", 0)) {
|
||||
Interface_DrawItemIconTexture(play, gItemIcons[ITEM_BOMB], 2);
|
||||
}
|
||||
Interface_DrawItemIconTexture(play, gItemIcons[gSaveContext.equips.buttonItems[2]], 2);
|
||||
gDPPipeSync(OVERLAY_DISP++);
|
||||
gDPSetCombineLERP(OVERLAY_DISP++, PRIMITIVE, ENVIRONMENT, TEXEL0, ENVIRONMENT, TEXEL0, 0, PRIMITIVE, 0,
|
||||
@ -5337,6 +5353,9 @@ void Interface_Draw(PlayState* play) {
|
||||
if (gSaveContext.equips.buttonItems[3] < 0xF0) {
|
||||
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, 255, 255, 255, interfaceCtx->cRightAlpha);
|
||||
gDPSetCombineMode(OVERLAY_DISP++, G_CC_MODULATERGBA_PRIM, G_CC_MODULATERGBA_PRIM);
|
||||
if (gSaveContext.equips.buttonItems[3] == ITEM_BOW && CVarGetInteger("gHoliday.lilDavid.BombArrows.Active", 0)) {
|
||||
Interface_DrawItemIconTexture(play, gItemIcons[ITEM_BOMB], 3);
|
||||
}
|
||||
Interface_DrawItemIconTexture(play, gItemIcons[gSaveContext.equips.buttonItems[3]], 3);
|
||||
gDPPipeSync(OVERLAY_DISP++);
|
||||
gDPSetCombineLERP(OVERLAY_DISP++, PRIMITIVE, ENVIRONMENT, TEXEL0, ENVIRONMENT, TEXEL0, 0, PRIMITIVE, 0,
|
||||
@ -5396,6 +5415,9 @@ void Interface_Draw(PlayState* play) {
|
||||
if (gSaveContext.equips.buttonItems[4] < 0xF0) {
|
||||
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, 255, 255, 255, interfaceCtx->dpadUpAlpha);
|
||||
gDPSetCombineMode(OVERLAY_DISP++, G_CC_MODULATERGBA_PRIM, G_CC_MODULATERGBA_PRIM);
|
||||
if (gSaveContext.equips.buttonItems[4] == ITEM_BOW && CVarGetInteger("gHoliday.lilDavid.BombArrows.Active", 0)) {
|
||||
Interface_DrawItemIconTexture(play, gItemIcons[ITEM_BOMB], 4);
|
||||
}
|
||||
Interface_DrawItemIconTexture(play, gItemIcons[gSaveContext.equips.buttonItems[4]], 4);
|
||||
gDPPipeSync(OVERLAY_DISP++);
|
||||
gDPSetCombineLERP(OVERLAY_DISP++, PRIMITIVE, ENVIRONMENT, TEXEL0, ENVIRONMENT, TEXEL0, 0, PRIMITIVE, 0,
|
||||
@ -5407,6 +5429,9 @@ void Interface_Draw(PlayState* play) {
|
||||
if (gSaveContext.equips.buttonItems[5] < 0xF0) {
|
||||
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, 255, 255, 255, interfaceCtx->dpadDownAlpha);
|
||||
gDPSetCombineMode(OVERLAY_DISP++, G_CC_MODULATERGBA_PRIM, G_CC_MODULATERGBA_PRIM);
|
||||
if (gSaveContext.equips.buttonItems[5] == ITEM_BOW && CVarGetInteger("gHoliday.lilDavid.BombArrows.Active", 0)) {
|
||||
Interface_DrawItemIconTexture(play, gItemIcons[ITEM_BOMB], 5);
|
||||
}
|
||||
Interface_DrawItemIconTexture(play, gItemIcons[gSaveContext.equips.buttonItems[5]], 5);
|
||||
gDPPipeSync(OVERLAY_DISP++);
|
||||
gDPSetCombineLERP(OVERLAY_DISP++, PRIMITIVE, ENVIRONMENT, TEXEL0, ENVIRONMENT, TEXEL0, 0, PRIMITIVE, 0,
|
||||
@ -5418,6 +5443,9 @@ void Interface_Draw(PlayState* play) {
|
||||
if (gSaveContext.equips.buttonItems[6] < 0xF0) {
|
||||
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, 255, 255, 255, interfaceCtx->dpadLeftAlpha);
|
||||
gDPSetCombineMode(OVERLAY_DISP++, G_CC_MODULATERGBA_PRIM, G_CC_MODULATERGBA_PRIM);
|
||||
if (gSaveContext.equips.buttonItems[6] == ITEM_BOW && CVarGetInteger("gHoliday.lilDavid.BombArrows.Active", 0)) {
|
||||
Interface_DrawItemIconTexture(play, gItemIcons[ITEM_BOMB], 6);
|
||||
}
|
||||
Interface_DrawItemIconTexture(play, gItemIcons[gSaveContext.equips.buttonItems[6]], 6);
|
||||
gDPPipeSync(OVERLAY_DISP++);
|
||||
gDPSetCombineLERP(OVERLAY_DISP++, PRIMITIVE, ENVIRONMENT, TEXEL0, ENVIRONMENT, TEXEL0, 0, PRIMITIVE, 0,
|
||||
@ -5429,6 +5457,9 @@ void Interface_Draw(PlayState* play) {
|
||||
if (gSaveContext.equips.buttonItems[7] < 0xF0) {
|
||||
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, 255, 255, 255, interfaceCtx->dpadRightAlpha);
|
||||
gDPSetCombineMode(OVERLAY_DISP++, G_CC_MODULATERGBA_PRIM, G_CC_MODULATERGBA_PRIM);
|
||||
if (gSaveContext.equips.buttonItems[7] == ITEM_BOW && CVarGetInteger("gHoliday.lilDavid.BombArrows.Active", 0)) {
|
||||
Interface_DrawItemIconTexture(play, gItemIcons[ITEM_BOMB], 7);
|
||||
}
|
||||
Interface_DrawItemIconTexture(play, gItemIcons[gSaveContext.equips.buttonItems[7]], 7);
|
||||
gDPPipeSync(OVERLAY_DISP++);
|
||||
gDPSetCombineLERP(OVERLAY_DISP++, PRIMITIVE, ENVIRONMENT, TEXEL0, ENVIRONMENT, TEXEL0, 0, PRIMITIVE, 0,
|
||||
|
@ -287,7 +287,12 @@ void EnBom_Update(Actor* thisx, PlayState* play2) {
|
||||
|
||||
// spawn spark effect on even frames
|
||||
effPos = thisx->world.pos;
|
||||
if (CVarGetInteger("gHoliday.lilDavid.BombArrows.Active", 0) &&
|
||||
thisx->parent && thisx->parent->id == ACTOR_EN_ARROW) {
|
||||
effPos.y += 5.0f;
|
||||
} else {
|
||||
effPos.y += 17.0f;
|
||||
}
|
||||
if ((play->gameplayFrames % 2) == 0) {
|
||||
EffectSsGSpk_SpawnFuse(play, thisx, &effPos, &effVelocity, &effAccel);
|
||||
}
|
||||
|
@ -1136,6 +1136,21 @@ void KaleidoScope_UpdateItemEquip(PlayState* play) {
|
||||
}
|
||||
}
|
||||
|
||||
if (CVarGetInteger("gHoliday.lilDavid.BombArrows.Enabled", 0)) {
|
||||
if (pauseCtx->equipTargetSlot == SLOT_BOW) {
|
||||
CVarSetInteger("gHoliday.lilDavid.BombArrows.Active", 0);
|
||||
}
|
||||
u8 equipped_slot = gSaveContext.equips.cButtonSlots[pauseCtx->equipTargetCBtn];
|
||||
if (!CVarGetInteger("gHoliday.lilDavid.BombArrows.Active", 0) &&
|
||||
pauseCtx->equipTargetItem == ITEM_BOMB && equipped_slot == SLOT_BOW)
|
||||
{
|
||||
CVarSetInteger("gHoliday.lilDavid.BombArrows.Active", 1);
|
||||
pauseCtx->equipTargetItem = ITEM_BOW;
|
||||
pauseCtx->equipTargetSlot = SLOT_BOW;
|
||||
Audio_PlaySoundGeneral(NA_SE_SY_SET_FIRE_ARROW, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
|
||||
}
|
||||
}
|
||||
|
||||
// If the item is on another button already, swap the two
|
||||
uint16_t targetButtonIndex = pauseCtx->equipTargetCBtn + 1;
|
||||
for (uint16_t otherSlotIndex = 0; otherSlotIndex < ARRAY_COUNT(gSaveContext.equips.cButtonSlots);
|
||||
|
Loading…
Reference in New Issue
Block a user