diff options
Diffstat (limited to 'src/code')
| -rw-r--r-- | src/code/z_actor.c | 67 | ||||
| -rw-r--r-- | src/code/z_en_a_keep.c | 2 | ||||
| -rw-r--r-- | src/code/z_player_lib.c | 6 | ||||
| -rw-r--r-- | src/code/z_sub_s.c | 96 |
4 files changed, 109 insertions, 62 deletions
diff --git a/src/code/z_actor.c b/src/code/z_actor.c index a85c2f31b..1579c1ff9 100644 --- a/src/code/z_actor.c +++ b/src/code/z_actor.c @@ -1878,14 +1878,38 @@ s32 Actor_ProcessTalkRequest(Actor* actor, GameState* gameState) { return false; } -// Actor_OfferTalk / Actor_OfferGetItemExchange? Seems to be called with PLAYER_IA_MINUS1 if the same actor used -// Actor_OfferGetItem. -// This function is also used to toggle the "Speak" action on the A button -s32 func_800B8500(Actor* actor, PlayState* play, f32 xzRange, f32 yRange, PlayerItemAction exchangeItemId) { +/** + * This function covers offering the ability to `Talk` with the player. + * Passing an exchangeItemAction (see `PlayerItemAction`) allows the player to also use the item to initiate the + * conversation. + * + * This function carries a talk exchange request to the player actor if context allows it (e.g. the player is in range + * and not busy with certain things). The player actor performs the requested action itself. + * + * The following description of what the `exchangeItemAction` values can do is provided here for completeness, but these + * behaviors are entirely out of the scope of this function. All behavior is defined by the player actor. + * + * - Positive values (`PLAYER_IA_NONE < exchangeItemAction < PLAYER_IA_MAX`): + * Offers the ability to initiate the conversation with an item from the player. + * Not all positive values are implemented properly for this to work. + * Working ones are PLAYER_IA_PICTO_BOX and PLAYER_IA_BOTTLE_MIN <= exchangeItemAction < PLAYER_IA_MASK_MIN + * Note: While PLAYER_IA_BEANS works, it is special cased to just plant the bean with no talking. + * - `PLAYER_IA_NONE`: + * Allows the player to speak to or check the actor (by pressing A). + * - `PLAYER_IA_MINUS1`: + * Used by actors/player to continue the current conversation after a textbox is closed. + * + * @return true If the player actor is capable of accepting the offer. + * + * Note: There is only one instance of using this for actually using an item to start the conversation with the player. + * Every other instance is to either offer to speak, or continue the current conversation. + */ +s32 Actor_OfferTalkExchange(Actor* actor, PlayState* play, f32 xzRange, f32 yRange, + PlayerItemAction exchangeItemAction) { Player* player = GET_PLAYER(play); if ((player->actor.flags & ACTOR_FLAG_TALK_REQUESTED) || - ((exchangeItemId > PLAYER_IA_NONE) && Player_InCsMode(play)) || + ((exchangeItemAction > PLAYER_IA_NONE) && Player_InCsMode(play)) || (!actor->isTargeted && ((fabsf(actor->playerHeightRel) > fabsf(yRange)) || (actor->xzDistToPlayer > player->talkActorDistance) || (xzRange < actor->xzDistToPlayer)))) { @@ -1894,24 +1918,35 @@ s32 func_800B8500(Actor* actor, PlayState* play, f32 xzRange, f32 yRange, Player player->talkActor = actor; player->talkActorDistance = actor->xzDistToPlayer; - player->exchangeItemId = exchangeItemId; + player->exchangeItemAction = exchangeItemAction; CutsceneManager_Queue(CS_ID_GLOBAL_TALK); return true; } -s32 func_800B85E0(Actor* actor, PlayState* play, f32 radius, PlayerItemAction exchangeItemId) { - return func_800B8500(actor, play, radius, radius, exchangeItemId); +/** + * Offers a talk exchange request within an equilateral cylinder with the radius specified. + */ +s32 Actor_OfferTalkExchangeEquiCylinder(Actor* actor, PlayState* play, f32 radius, + PlayerItemAction exchangeItemAction) { + return Actor_OfferTalkExchange(actor, play, radius, radius, exchangeItemAction); } -s32 func_800B8614(Actor* actor, PlayState* play, f32 radius) { - return func_800B85E0(actor, play, radius, PLAYER_IA_NONE); +/** + * Offers a talk request within an equilateral cylinder with the radius specified. + */ +s32 Actor_OfferTalk(Actor* actor, PlayState* play, f32 radius) { + return Actor_OfferTalkExchangeEquiCylinder(actor, play, radius, PLAYER_IA_NONE); } -s32 func_800B863C(Actor* actor, PlayState* play) { +/** + * Offers a talk request within an equilateral cylinder whose radius is determined by the actor's collision check + * cylinder's radius. + */ +s32 Actor_OfferTalkNearColChkInfoCylinder(Actor* actor, PlayState* play) { f32 cylRadius = actor->colChkInfo.cylRadius + 50.0f; - return func_800B8614(actor, play, cylRadius); + return Actor_OfferTalk(actor, play, cylRadius); } s32 Actor_TextboxIsClosing(Actor* actor, PlayState* play) { @@ -1942,10 +1977,10 @@ s32 Actor_ChangeFocus(Actor* actor1, PlayState* play, Actor* actor2) { return false; } -PlayerItemAction Player_GetExchangeItemId(PlayState* play) { +PlayerItemAction Player_GetExchangeItemAction(PlayState* play) { Player* player = GET_PLAYER(play); - return player->exchangeItemId; + return player->exchangeItemAction; } s32 func_800B8718(Actor* actor, GameState* gameState) { @@ -1957,7 +1992,7 @@ s32 func_800B8718(Actor* actor, GameState* gameState) { return false; } -// Similar to func_800B8500 +// Similar to Actor_OfferTalkExchange s32 func_800B874C(Actor* actor, PlayState* play, f32 xzRange, f32 yRange) { Player* player = GET_PLAYER(play); @@ -4127,7 +4162,7 @@ s32 Npc_UpdateTalking(PlayState* play, Actor* actor, s16* talkState, f32 interac return false; } - if (!func_800B8614(actor, play, interactRange)) { + if (!Actor_OfferTalk(actor, play, interactRange)) { return false; } diff --git a/src/code/z_en_a_keep.c b/src/code/z_en_a_keep.c index a9bd49f6f..3f9f6b90e 100644 --- a/src/code/z_en_a_keep.c +++ b/src/code/z_en_a_keep.c @@ -77,7 +77,7 @@ void EnAObj_Idle(EnAObj* this, PlayState* play) { yawDiff = ABS_ALT((s16)(this->actor.yawTowardsPlayer - this->actor.shape.rot.y)); if ((yawDiff < 0x2800) || ((this->actor.params == AOBJ_SIGNPOST_ARROW) && (yawDiff > 0x5800))) { - func_800B863C(&this->actor, play); + Actor_OfferTalkNearColChkInfoCylinder(&this->actor, play); } } } diff --git a/src/code/z_player_lib.c b/src/code/z_player_lib.c index bd8a5b94e..cd91ee42d 100644 --- a/src/code/z_player_lib.c +++ b/src/code/z_player_lib.c @@ -1286,7 +1286,7 @@ void Player_SetModelGroup(Player* player, PlayerModelGroup modelGroup) { void func_80123C58(Player* player) { player->itemAction = player->heldItemAction; Player_SetModelGroup(player, Player_ActionToModelGroup(player, player->heldItemAction)); - player->unk_AA5 = 0; + player->unk_AA5 = PLAYER_UNKAA5_0; } void Player_SetEquipmentData(PlayState* play, Player* player) { @@ -2313,7 +2313,7 @@ s32 Player_OverrideLimbDrawGameplayFirstPerson(PlayState* play, s32 limbIndex, G Player* player = (Player*)actor; if (!Player_OverrideLimbDrawGameplayCommon(play, limbIndex, dList, pos, rot, actor)) { - if (player->unk_AA5 != 3) { + if (player->unk_AA5 != PLAYER_UNKAA5_3) { *dList = NULL; } else if (limbIndex == PLAYER_LIMB_LEFT_FOREARM) { *dList = sPlayerFirstPersonLeftForearmDLs[player->transformation]; @@ -3526,7 +3526,7 @@ void Player_PostLimbDrawGameplay(PlayState* play, s32 limbIndex, Gfx** dList1, G if ((player->getItemDrawIdPlusOne != (GID_NONE + 1)) || ((func_800B7118(player) == 0) && (heldActor != NULL))) { if (!(player->stateFlags1 & PLAYER_STATE1_400) && (player->getItemDrawIdPlusOne != (GID_NONE + 1)) && - (player->exchangeItemId != PLAYER_IA_NONE)) { + (player->exchangeItemAction != PLAYER_IA_NONE)) { Math_Vec3f_Copy(&sPlayerGetItemRefPos, &player->leftHandWorld.pos); } else { sPlayerGetItemRefPos.x = diff --git a/src/code/z_sub_s.c b/src/code/z_sub_s.c index 0f09f5912..4060c3361 100644 --- a/src/code/z_sub_s.c +++ b/src/code/z_sub_s.c @@ -209,8 +209,8 @@ s32 SubS_UpdateLimb(s16 newRotZ, s16 newRotY, Vec3f* pos, Vec3s* rot, s32 stepRo return true; } -void SubS_UpdateFlags(u16* flags, u16 setBits, u16 unsetBits) { - *flags = (*flags & ~unsetBits) | setBits; +void SubS_SetOfferMode(u16* flags, u16 offerMode, u16 mask) { + *flags = (*flags & ~mask) | offerMode; } /** @@ -815,60 +815,68 @@ s32 SubS_CopyPointFromPathCheckBounds(Path* path, s32 pointIndex, Vec3f* dst) { return true; } -//! TODO: Needs docs with func_800B8500 -s32 func_8013C964(Actor* actor, PlayState* play, f32 xzRange, f32 yRange, s32 itemId, s32 type) { - s32 ret = false; +/** + * Attempt to extend different offers to the player based on different checks + * and on the provided mode (see SubSOfferMode). + * + * The offer types are either GetItem (see Actor_OfferGetItem) or TalkExchange (see Actor_OfferTalkExchange), + * with more check variants provided for TalkExchange offers. + * + * @return `true` if offer was extended and the player can accept it + */ +s32 SubS_Offer(Actor* actor, PlayState* play, f32 xzRange, f32 yRange, s32 itemId, SubSOfferMode mode) { + s32 canAccept = false; s16 x; s16 y; f32 xzDistToPlayerTemp; Actor_GetScreenPos(play, actor, &x, &y); - switch (type) { - case 1: + switch (mode) { + case SUBS_OFFER_MODE_GET_ITEM: yRange = fabsf(actor->playerHeightRel) + 1.0f; xzRange = actor->xzDistToPlayer + 1.0f; - ret = Actor_OfferGetItem(actor, play, itemId, xzRange, yRange); + canAccept = Actor_OfferGetItem(actor, play, itemId, xzRange, yRange); break; - case 2: + case SUBS_OFFER_MODE_NEARBY: if ((fabsf(actor->playerHeightRel) <= yRange) && (actor->xzDistToPlayer <= xzRange)) { - ret = func_800B8500(actor, play, xzRange, yRange, itemId); + canAccept = Actor_OfferTalkExchange(actor, play, xzRange, yRange, itemId); } break; - case 3: + case SUBS_OFFER_MODE_ONSCREEN: //! @bug: Both x and y conditionals are always true, || should be an && if (((x >= 0) || (x < SCREEN_WIDTH)) && ((y >= 0) || (y < SCREEN_HEIGHT))) { - ret = func_800B8500(actor, play, xzRange, yRange, itemId); + canAccept = Actor_OfferTalkExchange(actor, play, xzRange, yRange, itemId); } break; - case 4: + case SUBS_OFFER_MODE_AUTO: yRange = fabsf(actor->playerHeightRel) + 1.0f; xzRange = actor->xzDistToPlayer + 1.0f; xzDistToPlayerTemp = actor->xzDistToPlayer; actor->xzDistToPlayer = 0.0f; actor->flags |= ACTOR_FLAG_10000; - ret = func_800B8500(actor, play, xzRange, yRange, itemId); + canAccept = Actor_OfferTalkExchange(actor, play, xzRange, yRange, itemId); actor->xzDistToPlayer = xzDistToPlayerTemp; break; - case 5: + case SUBS_OFFER_MODE_AUTO_TARGETED: //! @bug: Both x and y conditionals are always true, || should be an && if (((x >= 0) || (x < SCREEN_WIDTH)) && ((y >= 0) || (y < SCREEN_HEIGHT)) && (fabsf(actor->playerHeightRel) <= yRange) && (actor->xzDistToPlayer <= xzRange) && actor->isTargeted) { actor->flags |= ACTOR_FLAG_10000; - ret = func_800B8500(actor, play, xzRange, yRange, itemId); + canAccept = Actor_OfferTalkExchange(actor, play, xzRange, yRange, itemId); } break; - case 6: + case SUBS_OFFER_MODE_AUTO_NEARBY_ONSCREEN: //! @bug: Both x and y conditionals are always true, || should be an && if (((x >= 0) || (x < SCREEN_WIDTH)) && ((y >= 0) || (y < SCREEN_HEIGHT)) && (fabsf(actor->playerHeightRel) <= yRange) && (actor->xzDistToPlayer <= xzRange)) { actor->flags |= ACTOR_FLAG_10000; - ret = func_800B8500(actor, play, xzRange, yRange, itemId); + canAccept = Actor_OfferTalkExchange(actor, play, xzRange, yRange, itemId); } break; @@ -876,7 +884,7 @@ s32 func_8013C964(Actor* actor, PlayState* play, f32 xzRange, f32 yRange, s32 it break; } - return ret; + return canAccept; } const u8 sShadowMaps[4][12][12] = { @@ -1504,10 +1512,10 @@ s32 SubS_LineSegVsPlane(Vec3f* point, Vec3s* rot, Vec3f* unitVec, Vec3f* linePoi /** * Finds the first actor instance of a specified Id and category verified with a custom callback. - * The callback should return `true` when the actor is succesfully verified. + * The callback should return `true` when the actor is successfully verified. */ Actor* SubS_FindActorCustom(PlayState* play, Actor* actor, Actor* actorListStart, u8 actorCategory, s16 actorId, - void* verifyData, VerifyActor verifyActor) { + void* verifyData, VerifyFindActorFunc verifyActorFunc) { Actor* actorIter = actorListStart; if (actorListStart == NULL) { @@ -1517,36 +1525,40 @@ Actor* SubS_FindActorCustom(PlayState* play, Actor* actor, Actor* actorListStart while ((actorIter != NULL) && ((actorId != actorIter->id) || ((actorId == actorIter->id) && - ((verifyActor == NULL) || ((verifyActor != NULL) && !verifyActor(play, actor, actorIter, verifyData)))))) { + ((verifyActorFunc == NULL) || + ((verifyActorFunc != NULL) && !verifyActorFunc(play, actor, actorIter, verifyData)))))) { actorIter = actorIter->next; } return actorIter; } -//! TODO: Needs docs with func_800B8500 -s32 func_8013E748(Actor* actor, PlayState* play, f32 xzRange, f32 yRange, s32 exchangeItemId, void* data, - func_8013E748_VerifyFunc verifyFunc) { - s32 ret = false; +/** + * Will extend a TalkExchange offer to the player if the actor is verified with a custom callback. + * The callback should return `true` when the actor is successfully verified. + */ +s32 SubS_OfferTalkExchangeCustom(Actor* actor, PlayState* play, f32 xzRange, f32 yRange, s32 exchangeItemAction, + void* data, VerifyTalkExchangeActorFunc verifyActorFunc) { + s32 canAccept = false; - if ((verifyFunc == NULL) || ((verifyFunc != NULL) && verifyFunc(play, actor, data))) { - ret = func_800B8500(actor, play, xzRange, yRange, exchangeItemId); + if ((verifyActorFunc == NULL) || ((verifyActorFunc != NULL) && verifyActorFunc(play, actor, data))) { + canAccept = Actor_OfferTalkExchange(actor, play, xzRange, yRange, exchangeItemAction); } - return ret; + return canAccept; } s32 SubS_ActorAndPlayerFaceEachOther(PlayState* play, Actor* actor, void* data) { Player* player = GET_PLAYER(play); - Vec3s* yawTols = (Vec3s*)data; + Vec3s* yawRanges = (Vec3s*)data; s16 playerYaw = ABS(BINANG_SUB(Actor_WorldYawTowardActor(&player->actor, actor), player->actor.shape.rot.y)); s16 actorYaw = ABS(BINANG_SUB(actor->yawTowardsPlayer, actor->shape.rot.y)); s32 areFacing = false; - s32 actorYawTol = ABS(yawTols->y); - s32 playerYawTol; + s32 actorYawRange = ABS(yawRanges->y); + s32 playerYawRange; - if (actorYaw < (s16)actorYawTol) { - playerYawTol = ABS(yawTols->x); - if (playerYaw < (s16)playerYawTol) { + if (actorYaw < (s16)actorYawRange) { + playerYawRange = ABS(yawRanges->x); + if (playerYaw < (s16)playerYawRange) { areFacing = true; } } @@ -1554,14 +1566,14 @@ s32 SubS_ActorAndPlayerFaceEachOther(PlayState* play, Actor* actor, void* data) return areFacing; } -//! TODO: Needs docs with func_800B8500 -s32 func_8013E8F8(Actor* actor, PlayState* play, f32 xzRange, f32 yRange, s32 exhangeItemId, s16 playerYawTol, - s16 actorYawTol) { - Vec3s yawTols; +s32 SubS_OfferTalkExchangeFacing(Actor* actor, PlayState* play, f32 xzRange, f32 yRange, s32 exchangeItemAction, + s16 playerYawRange, s16 actorYawRange) { + Vec3s yawRanges; - yawTols.x = playerYawTol; - yawTols.y = actorYawTol; - return func_8013E748(actor, play, xzRange, yRange, exhangeItemId, &yawTols, SubS_ActorAndPlayerFaceEachOther); + yawRanges.x = playerYawRange; + yawRanges.y = actorYawRange; + return SubS_OfferTalkExchangeCustom(actor, play, xzRange, yRange, exchangeItemAction, &yawRanges, + SubS_ActorAndPlayerFaceEachOther); } /** |
