summaryrefslogtreecommitdiff
path: root/src/code
diff options
context:
space:
mode:
Diffstat (limited to 'src/code')
-rw-r--r--src/code/z_actor.c67
-rw-r--r--src/code/z_en_a_keep.c2
-rw-r--r--src/code/z_player_lib.c6
-rw-r--r--src/code/z_sub_s.c96
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);
}
/**