Add bombchu drops (#1257)

* Add bombchu drops

* Force 3D bombchu drops

* Move bombchu drop conditions for better clarity

* Fix grouping on chu drop condition
This commit is contained in:
lilDavid 2022-08-23 19:14:17 -05:00 committed by GitHub
parent ca08680a12
commit 4680641514
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 69 additions and 5 deletions

View File

@ -1359,6 +1359,8 @@ namespace SohImGui {
); );
PaddedEnhancementCheckbox("No Random Drops", "gNoRandomDrops", true, false); PaddedEnhancementCheckbox("No Random Drops", "gNoRandomDrops", true, false);
Tooltip("Disables random drops, except from the Goron Pot, Dampe, and bosses"); Tooltip("Disables random drops, except from the Goron Pot, Dampe, and bosses");
PaddedEnhancementCheckbox("Enable Bombchu Drops", "gBombchuDrops", true, false);
Tooltip("Bombchus will sometimes drop in place of bombs");
PaddedEnhancementCheckbox("No Heart Drops", "gNoHeartDrops", true, false); PaddedEnhancementCheckbox("No Heart Drops", "gNoHeartDrops", true, false);
Tooltip("Disables heart drops, but not heart placements, like from a Deku Scrub running off\nThis simulates Hero Mode from other games in the series"); Tooltip("Disables heart drops, but not heart placements, like from a Deku Scrub running off\nThis simulates Hero Mode from other games in the series");
PaddedEnhancementCheckbox("Always Win Goron Pot", "gGoronPot", true, false); PaddedEnhancementCheckbox("Always Win Goron Pot", "gGoronPot", true, false);
@ -2228,6 +2230,8 @@ namespace SohImGui {
CVar_SetS32("gNoRandomDrops", 0); CVar_SetS32("gNoRandomDrops", 0);
// No Heart Drops // No Heart Drops
CVar_SetS32("gNoHeartDrops", 0); CVar_SetS32("gNoHeartDrops", 0);
// Enable Bombchu Drops
CVar_SetS32("gBombchuDrops", 0);
// Always Win Goron Pot // Always Win Goron Pot
CVar_SetS32("gGoronPot", 0); CVar_SetS32("gGoronPot", 0);

View File

@ -271,7 +271,8 @@ typedef enum {
/* 0x16 */ ITEM00_SHIELD_HYLIAN, /* 0x16 */ ITEM00_SHIELD_HYLIAN,
/* 0x17 */ ITEM00_TUNIC_ZORA, /* 0x17 */ ITEM00_TUNIC_ZORA,
/* 0x18 */ ITEM00_TUNIC_GORON, /* 0x18 */ ITEM00_TUNIC_GORON,
/* 0x19 */ ITEM00_BOMBS_SPECIAL /* 0x19 */ ITEM00_BOMBS_SPECIAL,
/* 0x20 */ ITEM00_BOMBCHU,
} Item00Type; } Item00Type;
struct EnItem00; struct EnItem00;

View File

@ -70,6 +70,7 @@ static void* sItemDropTex[] = {
gDropRecoveryHeartTex, gDropBombTex, gDropArrows1Tex, gDropArrows2Tex, gDropRecoveryHeartTex, gDropBombTex, gDropArrows1Tex, gDropArrows2Tex,
gDropArrows3Tex, gDropBombTex, gDropDekuNutTex, gDropDekuStickTex, gDropArrows3Tex, gDropBombTex, gDropDekuNutTex, gDropDekuStickTex,
gDropMagicLargeTex, gDropMagicSmallTex, gDropDekuSeedsTex, gDropKeySmallTex, gDropMagicLargeTex, gDropMagicSmallTex, gDropDekuSeedsTex, gDropKeySmallTex,
// OTRTODO: use 2D bombchu texture
}; };
static u8 sItemDropIds[] = { static u8 sItemDropIds[] = {
@ -390,6 +391,7 @@ void EnItem00_Init(Actor* thisx, GlobalContext* globalCtx) {
case ITEM00_RUPEE_ORANGE: case ITEM00_RUPEE_ORANGE:
case ITEM00_RUPEE_PURPLE: case ITEM00_RUPEE_PURPLE:
case ITEM00_FLEXIBLE: case ITEM00_FLEXIBLE:
case ITEM00_BOMBCHU:
yOffset = 500.0f; yOffset = 500.0f;
Actor_SetScale(&this->actor, 0.01f); Actor_SetScale(&this->actor, 0.01f);
this->scale = 0.01f; this->scale = 0.01f;
@ -507,6 +509,9 @@ void EnItem00_Init(Actor* thisx, GlobalContext* globalCtx) {
case ITEM00_TUNIC_GORON: case ITEM00_TUNIC_GORON:
case ITEM00_BOMBS_SPECIAL: case ITEM00_BOMBS_SPECIAL:
break; break;
case ITEM00_BOMBCHU:
Item_Give(globalCtx, ITEM_BOMBCHUS_5);
break;
} }
if (!Actor_HasParent(&this->actor, globalCtx)) { if (!Actor_HasParent(&this->actor, globalCtx)) {
@ -537,7 +542,8 @@ void func_8001DFC8(EnItem00* this, GlobalContext* globalCtx) {
(this->actor.params == ITEM00_HEART_PIECE)) { (this->actor.params == ITEM00_HEART_PIECE)) {
this->actor.shape.rot.y += 960; this->actor.shape.rot.y += 960;
} else { } else {
if ((this->actor.params >= ITEM00_SHIELD_DEKU) && (this->actor.params != ITEM00_BOMBS_SPECIAL)) { if ((this->actor.params >= ITEM00_SHIELD_DEKU) && (this->actor.params != ITEM00_BOMBS_SPECIAL) &&
(this->actor.params != ITEM00_BOMBCHU)) {
if (this->unk_15A == -1) { if (this->unk_15A == -1) {
if (Math_SmoothStepToS(&this->actor.shape.rot.x, this->actor.world.rot.x - 0x4000, 2, 3000, 1500) == if (Math_SmoothStepToS(&this->actor.shape.rot.x, this->actor.world.rot.x - 0x4000, 2, 3000, 1500) ==
0) { 0) {
@ -640,7 +646,8 @@ void func_8001E304(EnItem00* this, GlobalContext* globalCtx) {
if (this->actor.params <= ITEM00_RUPEE_RED) { if (this->actor.params <= ITEM00_RUPEE_RED) {
this->actor.shape.rot.y += 960; this->actor.shape.rot.y += 960;
} else if ((this->actor.params >= ITEM00_SHIELD_DEKU) && (this->actor.params != ITEM00_BOMBS_SPECIAL)) { } else if ((this->actor.params >= ITEM00_SHIELD_DEKU) && (this->actor.params != ITEM00_BOMBS_SPECIAL) &&
(this->actor.params != ITEM00_BOMBCHU)) {
this->actor.world.rot.x -= 700; this->actor.world.rot.x -= 700;
this->actor.shape.rot.y += 400; this->actor.shape.rot.y += 400;
this->actor.shape.rot.x = this->actor.world.rot.x - 0x4000; this->actor.shape.rot.x = this->actor.world.rot.x - 0x4000;
@ -722,7 +729,8 @@ void EnItem00_Update(Actor* thisx, GlobalContext* globalCtx) {
EnItem00* this = (EnItem00*)thisx; EnItem00* this = (EnItem00*)thisx;
s32 pad; s32 pad;
if (CVar_GetS32("gNewDrops", 0)) { //set the rotation system on selected model only :) // OTRTODO: remove special case for bombchu when its 2D drop is implemented
if (CVar_GetS32("gNewDrops", 0) || this->actor.params == ITEM00_BOMBCHU) { //set the rotation system on selected model only :)
if ((this->actor.params == ITEM00_RUPEE_GREEN) || (this->actor.params == ITEM00_RUPEE_BLUE) || if ((this->actor.params == ITEM00_RUPEE_GREEN) || (this->actor.params == ITEM00_RUPEE_BLUE) ||
(this->actor.params == ITEM00_RUPEE_RED) || (this->actor.params == ITEM00_ARROWS_SINGLE) || (this->actor.params == ITEM00_RUPEE_RED) || (this->actor.params == ITEM00_ARROWS_SINGLE) ||
(this->actor.params == ITEM00_ARROWS_SMALL) || (this->actor.params == ITEM00_ARROWS_MEDIUM) || (this->actor.params == ITEM00_ARROWS_SMALL) || (this->actor.params == ITEM00_ARROWS_MEDIUM) ||
@ -730,7 +738,8 @@ void EnItem00_Update(Actor* thisx, GlobalContext* globalCtx) {
(this->actor.params == ITEM00_BOMBS_B) || (this->actor.params == ITEM00_NUTS) || (this->actor.params == ITEM00_BOMBS_B) || (this->actor.params == ITEM00_NUTS) ||
(this->actor.params == ITEM00_MAGIC_SMALL) || (this->actor.params == ITEM00_SEEDS) || (this->actor.params == ITEM00_MAGIC_SMALL) || (this->actor.params == ITEM00_SEEDS) ||
(this->actor.params == ITEM00_MAGIC_LARGE) || (this->actor.params == ITEM00_HEART) || (this->actor.params == ITEM00_MAGIC_LARGE) || (this->actor.params == ITEM00_HEART) ||
(this->actor.params == ITEM00_BOMBS_SPECIAL) || this->actor.params == ITEM00_HEART_PIECE) { (this->actor.params == ITEM00_BOMBS_SPECIAL) || this->actor.params == ITEM00_HEART_PIECE ||
(this->actor.params == ITEM00_BOMBCHU)) {
this->actor.shape.rot.y += 960; this->actor.shape.rot.y += 960;
} }
if (this->actor.params == ITEM00_SMALL_KEY && !gSaveContext.n64ddFlag) { if (this->actor.params == ITEM00_SMALL_KEY && !gSaveContext.n64ddFlag) {
@ -891,6 +900,9 @@ void EnItem00_Update(Actor* thisx, GlobalContext* globalCtx) {
break; break;
case ITEM00_BOMBS_SPECIAL: case ITEM00_BOMBS_SPECIAL:
break; break;
case ITEM00_BOMBCHU:
Item_Give(globalCtx, ITEM_BOMBCHUS_5);
break;
} }
params = &this->actor.params; params = &this->actor.params;
@ -1212,6 +1224,15 @@ void EnItem00_Draw(Actor* thisx, GlobalContext* globalCtx) {
EnItem00_DrawCollectible(this, globalCtx); EnItem00_DrawCollectible(this, globalCtx);
break; break;
} }
case ITEM00_BOMBCHU:
// OTRTODO: Stop forcing chu drops to be 3D when the texture is added
Actor_SetScale(&this->actor, 0.2f);
this->scale = 0.2f;
this->actor.shape.yOffset = 50.0f;
this->actor.world.rot.x = 0x4000;
this->actor.shape.shadowScale = 0.3f;
GetItem_Draw(globalCtx, GID_BOMBCHU);
break;
case ITEM00_SHIELD_DEKU: case ITEM00_SHIELD_DEKU:
GetItem_Draw(globalCtx, GID_SHIELD_DEKU); GetItem_Draw(globalCtx, GID_SHIELD_DEKU);
break; break;
@ -1370,6 +1391,9 @@ void EnItem00_DrawCollectible(EnItem00* this, GlobalContext* globalCtx) {
if (this->actor.params == ITEM00_BOMBS_SPECIAL) { if (this->actor.params == ITEM00_BOMBS_SPECIAL) {
texIndex = 1; texIndex = 1;
// OTRTODO: 2D bombchu drops
//} else if (this->actor.params == ITEM00_BOMBCHU) {
// texIndex = 12;
} else if (this->actor.params >= ITEM00_ARROWS_SMALL) { } else if (this->actor.params >= ITEM00_ARROWS_SMALL) {
texIndex -= 3; texIndex -= 3;
} }
@ -1435,6 +1459,36 @@ void EnItem00_DrawHeartPiece(EnItem00* this, GlobalContext* globalCtx) {
} }
} }
/**
* Sometimes convert the given drop ID into a bombchu.
* Returns the new drop type ID.
*/
s16 EnItem00_ConvertBombDropToBombchu(s16 dropId) {
if (INV_CONTENT(ITEM_BOMBCHU) == ITEM_NONE) {
return dropId;
}
if (INV_CONTENT(ITEM_BOMB) == ITEM_NONE) {
return ITEM00_BOMBCHU;
}
if (AMMO(ITEM_BOMB) <= 15) {
// Player needs bombs and might need chus, so drop whichever has less
if (AMMO(ITEM_BOMB) <= AMMO(ITEM_BOMBCHU)) {
return dropId;
} else {
return ITEM00_BOMBCHU;
}
} else {
// Player has enough bombs, so drop chus if they need some, else it's 50/50
if (AMMO(ITEM_BOMBCHU) <= 15) {
return ITEM00_BOMBCHU;
} else {
return Rand_Next() % 2 ? dropId : ITEM00_BOMBCHU;
}
}
}
/** /**
* Converts a given drop type ID based on link's current age, health and owned items. * Converts a given drop type ID based on link's current age, health and owned items.
* Returns a new drop type ID or -1 to cancel the drop. * Returns a new drop type ID or -1 to cancel the drop.
@ -1452,6 +1506,11 @@ s16 func_8001F404(s16 dropId) {
} }
} }
if (CVar_GetS32("gBombchuDrops", 0) &&
(dropId == ITEM00_BOMBS_A || dropId == ITEM00_BOMBS_B || dropId == ITEM00_BOMBS_SPECIAL)) {
dropId = EnItem00_ConvertBombDropToBombchu(dropId);
}
// This is convoluted but it seems like it must be a single condition to match // This is convoluted but it seems like it must be a single condition to match
// clang-format off // clang-format off
if (((dropId == ITEM00_BOMBS_A || dropId == ITEM00_BOMBS_SPECIAL || dropId == ITEM00_BOMBS_B) && INV_CONTENT(ITEM_BOMB) == ITEM_NONE) || if (((dropId == ITEM00_BOMBS_A || dropId == ITEM00_BOMBS_SPECIAL || dropId == ITEM00_BOMBS_B) && INV_CONTENT(ITEM_BOMB) == ITEM_NONE) ||