mirror of
https://github.com/HarbourMasters/Shipwright.git
synced 2025-08-21 05:43:42 -07:00
Add custom collectible thing
This commit is contained in:
parent
796576717f
commit
05539fee03
7 changed files with 256 additions and 3 deletions
|
@ -306,6 +306,7 @@ typedef enum {
|
||||||
/* 0x99 */ ITEM_STICK_UPGRADE_30,
|
/* 0x99 */ ITEM_STICK_UPGRADE_30,
|
||||||
/* 0x9A */ ITEM_NUT_UPGRADE_30,
|
/* 0x9A */ ITEM_NUT_UPGRADE_30,
|
||||||
/* 0x9B */ ITEM_NUT_UPGRADE_40,
|
/* 0x9B */ ITEM_NUT_UPGRADE_40,
|
||||||
|
/* 0x9C */ ITEM_SHIP, // SOH [Enhancement] Added to enable custom item gives
|
||||||
/* 0xFC */ ITEM_LAST_USED = 0xFC,
|
/* 0xFC */ ITEM_LAST_USED = 0xFC,
|
||||||
/* 0xFE */ ITEM_NONE_FE = 0xFE,
|
/* 0xFE */ ITEM_NONE_FE = 0xFE,
|
||||||
/* 0xFF */ ITEM_NONE = 0xFF
|
/* 0xFF */ ITEM_NONE = 0xFF
|
||||||
|
@ -455,9 +456,10 @@ typedef enum {
|
||||||
/* 0x79 */ GI_NUT_UPGRADE_30,
|
/* 0x79 */ GI_NUT_UPGRADE_30,
|
||||||
/* 0x7A */ GI_NUT_UPGRADE_40,
|
/* 0x7A */ GI_NUT_UPGRADE_40,
|
||||||
/* 0x7B */ GI_BULLET_BAG_50,
|
/* 0x7B */ GI_BULLET_BAG_50,
|
||||||
/* 0x7C */ GI_ICE_TRAP, // freezes link when opened from a chest
|
/* 0x7C */ GI_SHIP, // SOH [Enhancement] Added to enable custom item gives
|
||||||
/* 0x7D */ GI_TEXT_0, // no model appears over Link, shows text id 0 (pocket egg)
|
/* 0x7D */ GI_ICE_TRAP, // freezes link when opened from a chest
|
||||||
/* 0x84 */ GI_MAX
|
/* 0x7E */ GI_TEXT_0, // no model appears over Link, shows text id 0 (pocket egg)
|
||||||
|
/* 0x7F */ GI_MAX
|
||||||
} GetItemID;
|
} GetItemID;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
|
|
209
soh/soh/Enhancements/custom-collectible/CustomCollectible.cpp
Normal file
209
soh/soh/Enhancements/custom-collectible/CustomCollectible.cpp
Normal file
|
@ -0,0 +1,209 @@
|
||||||
|
#include "CustomCollectible.h"
|
||||||
|
#include <libultraship/libultraship.h>
|
||||||
|
#include "soh/Enhancements/game-interactor/GameInteractor.h"
|
||||||
|
#include "soh/Enhancements/randomizer/3drando/random.hpp"
|
||||||
|
#include "soh/frame_interpolation.h"
|
||||||
|
#include "soh/Enhancements/custom-message/CustomMessageManager.h"
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
#include "z64actor.h"
|
||||||
|
#include "functions.h"
|
||||||
|
#include "variables.h"
|
||||||
|
#include "macros.h"
|
||||||
|
#include "objects/object_md/object_md.h"
|
||||||
|
extern PlayState* gPlayState;
|
||||||
|
}
|
||||||
|
|
||||||
|
EnItem00* CustomCollectible::Spawn(f32 posX, f32 posY, f32 posZ, s16 rot, s16 flags, s16 params, ActorFunc actionFunc,
|
||||||
|
ActorFunc drawFunc) {
|
||||||
|
if (!gPlayState) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
Actor* actor = Actor_Spawn(&gPlayState->actorCtx, gPlayState, ACTOR_EN_ITEM00, posX, posY, posZ, flags, rot, params, ITEM00_NONE, 0);
|
||||||
|
EnItem00* enItem00 = (EnItem00*)actor;
|
||||||
|
|
||||||
|
if (actionFunc != NULL) {
|
||||||
|
enItem00->actionFunc = (EnItem00ActionFunc)actionFunc;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (drawFunc != NULL) {
|
||||||
|
actor->draw = drawFunc;
|
||||||
|
}
|
||||||
|
|
||||||
|
return enItem00;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CustomCollectible_Init(Actor* actor, PlayState* play) {
|
||||||
|
EnItem00* enItem00 = (EnItem00*)actor;
|
||||||
|
|
||||||
|
if (CUSTOM_ITEM_FLAGS & CustomCollectible::STOP_BOBBING) {
|
||||||
|
actor->shape.yOffset = 1250.0f;
|
||||||
|
} else {
|
||||||
|
actor->shape.yOffset = (Math_SinS(actor->shape.rot.y) * 150.0f) + 1250.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CUSTOM_ITEM_FLAGS & CustomCollectible::HIDE_TILL_OVERHEAD) {
|
||||||
|
Actor_SetScale(actor, 0.0f);
|
||||||
|
} else {
|
||||||
|
Actor_SetScale(actor, 0.015f);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CUSTOM_ITEM_FLAGS & CustomCollectible::KEEP_ON_PLAYER) {
|
||||||
|
Math_Vec3f_Copy(&actor->world.pos, &GET_PLAYER(play)->actor.world.pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CUSTOM_ITEM_FLAGS & CustomCollectible::TOSS_ON_SPAWN) {
|
||||||
|
actor->velocity.y = 8.0f;
|
||||||
|
actor->speedXZ = 2.0f;
|
||||||
|
actor->gravity = -1.4f;
|
||||||
|
actor->world.rot.y = Rand_ZeroOne() * 40000.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
enItem00->unk_15A = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// By default this will just assume the GID was passed in as the rot z, if you want different functionality you should
|
||||||
|
// override the draw
|
||||||
|
void CustomCollectible_Draw(Actor* actor, PlayState* play) {
|
||||||
|
Matrix_Scale(30.0f, 30.0f, 30.0f, MTXMODE_APPLY);
|
||||||
|
GetItem_Draw(play, CUSTOM_ITEM_PARAM);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CustomCollectible_Update(Actor* actor, PlayState* play) {
|
||||||
|
EnItem00* enItem00 = (EnItem00*)actor;
|
||||||
|
Player* player = GET_PLAYER(play);
|
||||||
|
|
||||||
|
if (!(CUSTOM_ITEM_FLAGS & CustomCollectible::STOP_SPINNING)) {
|
||||||
|
actor->shape.rot.y += 960;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CUSTOM_ITEM_FLAGS & CustomCollectible::STOP_BOBBING) {
|
||||||
|
actor->shape.yOffset = 1250.0f;
|
||||||
|
} else {
|
||||||
|
actor->shape.yOffset = (Math_SinS(actor->shape.rot.y) * 150.0f) + 1250.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CUSTOM_ITEM_FLAGS & CustomCollectible::HIDE_TILL_OVERHEAD) {
|
||||||
|
Actor_SetScale(actor, 0.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CUSTOM_ITEM_FLAGS & CustomCollectible::KEEP_ON_PLAYER) {
|
||||||
|
actor->gravity = 0.0f;
|
||||||
|
Math_Vec3f_Copy(&actor->world.pos, &GET_PLAYER(play)->actor.world.pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CUSTOM_ITEM_FLAGS & CustomCollectible::KILL_ON_TOUCH) {
|
||||||
|
// Pretty self explanatory, if the player is within range, kill the actor and call the action function
|
||||||
|
if ((actor->xzDistToPlayer <= 50.0f) && (fabsf(actor->yDistToPlayer) <= fabsf(20.0f))) {
|
||||||
|
if (enItem00->actionFunc != NULL) {
|
||||||
|
enItem00->actionFunc(enItem00, play);
|
||||||
|
CUSTOM_ITEM_FLAGS |= CustomCollectible::CALLED_ACTION;
|
||||||
|
}
|
||||||
|
Actor_Kill(actor);
|
||||||
|
}
|
||||||
|
} else if (CUSTOM_ITEM_FLAGS & CustomCollectible::GIVE_OVERHEAD) {
|
||||||
|
// If the item hasn't been picked up (unk_15A == -1) and the player is within range
|
||||||
|
if (enItem00->unk_15A == -1 && (actor->xzDistToPlayer <= 50.0f) &&
|
||||||
|
(fabsf(actor->yDistToPlayer) <= fabsf(20.0f))) {
|
||||||
|
// Fire the action function
|
||||||
|
if (enItem00->actionFunc != NULL) {
|
||||||
|
enItem00->actionFunc(enItem00, play);
|
||||||
|
CUSTOM_ITEM_FLAGS |= CustomCollectible::CALLED_ACTION;
|
||||||
|
}
|
||||||
|
Sfx_PlaySfxCentered(NA_SE_SY_GET_ITEM);
|
||||||
|
// Set the unk_15A to 15, this indicates the item has been picked up and will start the overhead animation
|
||||||
|
enItem00->unk_15A = 15;
|
||||||
|
CUSTOM_ITEM_FLAGS |= CustomCollectible::STOP_BOBBING;
|
||||||
|
CUSTOM_ITEM_FLAGS |= CustomCollectible::KEEP_ON_PLAYER;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the item has been picked up
|
||||||
|
if (enItem00->unk_15A > 0) {
|
||||||
|
// Reduce the size a bit, but also makes it visible for HIDE_TILL_OVERHEAD
|
||||||
|
Actor_SetScale(actor, 0.010f);
|
||||||
|
|
||||||
|
// Decrement the unk_15A, which will be used to bob the item up and down
|
||||||
|
enItem00->unk_15A--;
|
||||||
|
|
||||||
|
// Account for the different heights of the player forms
|
||||||
|
f32 height = 45.0f;
|
||||||
|
// TODO: Check for adult?
|
||||||
|
|
||||||
|
// Bob the item up and down
|
||||||
|
actor->world.pos.y += (height + (Math_SinS(enItem00->unk_15A * 15000) * (enItem00->unk_15A * 0.3f)));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Finally, once the bobbing animation is done, kill the actor
|
||||||
|
if (enItem00->unk_15A == 0) {
|
||||||
|
Actor_Kill(actor);
|
||||||
|
}
|
||||||
|
} else if (CUSTOM_ITEM_FLAGS & CustomCollectible::GIVE_ITEM_CUTSCENE) {
|
||||||
|
// If the item hasn't been picked up and the player is within range
|
||||||
|
if (!Actor_HasParent(actor, play) && enItem00->unk_15A == -1) {
|
||||||
|
Actor_OfferGetItem(actor, play, GI_SHIP, 50.0f, 20.0f);
|
||||||
|
} else {
|
||||||
|
if (enItem00->unk_15A == -1) {
|
||||||
|
CUSTOM_ITEM_FLAGS |= CustomCollectible::STOP_BOBBING;
|
||||||
|
CUSTOM_ITEM_FLAGS |= CustomCollectible::KEEP_ON_PLAYER;
|
||||||
|
CUSTOM_ITEM_FLAGS |= CustomCollectible::HIDE_TILL_OVERHEAD;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Begin incrementing the unk_15A, indicating the item has been picked up
|
||||||
|
enItem00->unk_15A++;
|
||||||
|
|
||||||
|
// For the first 20 frames, wait while the player's animation plays
|
||||||
|
if (enItem00->unk_15A >= 20) {
|
||||||
|
// After the first 20 frames, show the item and call the action function
|
||||||
|
if (enItem00->unk_15A == 20 && enItem00->actionFunc != NULL) {
|
||||||
|
enItem00->actionFunc(enItem00, play);
|
||||||
|
CUSTOM_ITEM_FLAGS |= CustomCollectible::CALLED_ACTION;
|
||||||
|
}
|
||||||
|
// Override the bobbing animation to be a fixed height
|
||||||
|
actor->shape.yOffset = 900.0f;
|
||||||
|
Actor_SetScale(actor, 0.007f);
|
||||||
|
|
||||||
|
f32 height = 45.0f;
|
||||||
|
// TODO: Check for adult?
|
||||||
|
|
||||||
|
actor->world.pos.y += height;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Once the player is no longer in the "Give Item" state, kill the actor
|
||||||
|
if (!(player->stateFlags1 & PLAYER_STATE1_GETTING_ITEM)) {
|
||||||
|
Actor_Kill(actor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (actor->gravity != 0.0f) {
|
||||||
|
Actor_MoveForward(actor);
|
||||||
|
Actor_UpdateBgCheckInfo(play, actor, 20.0f, 15.0f, 15.0f, 0x1D);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (actor->bgCheckFlags & 0x0003) {
|
||||||
|
actor->speedXZ = 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
Collider_UpdateCylinder(actor, &enItem00->collider);
|
||||||
|
CollisionCheck_SetAC(play, &play->colChkCtx, &enItem00->collider.base);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CustomCollectible::RegisterHooks() {
|
||||||
|
GameInteractor::Instance->RegisterGameHookForID<GameInteractor::ShouldActorInit>(
|
||||||
|
ACTOR_EN_ITEM00, [](void* actorRef, bool* should) {
|
||||||
|
Actor* actor = (Actor*)actorRef;
|
||||||
|
if (actor->params != ITEM00_NONE) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
actor->init = CustomCollectible_Init;
|
||||||
|
actor->update = CustomCollectible_Update;
|
||||||
|
actor->draw = CustomCollectible_Draw;
|
||||||
|
actor->destroy = NULL;
|
||||||
|
|
||||||
|
// Set the rotX/rotZ back to 0, the original values can be accessed from actor->home
|
||||||
|
actor->world.rot.x = 0;
|
||||||
|
actor->world.rot.z = 0;
|
||||||
|
});
|
||||||
|
}
|
24
soh/soh/Enhancements/custom-collectible/CustomCollectible.h
Normal file
24
soh/soh/Enhancements/custom-collectible/CustomCollectible.h
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
extern "C" {
|
||||||
|
#include "z64actor.h"
|
||||||
|
}
|
||||||
|
|
||||||
|
#define CUSTOM_ITEM_FLAGS (actor->home.rot.x)
|
||||||
|
#define CUSTOM_ITEM_PARAM (actor->home.rot.z)
|
||||||
|
|
||||||
|
namespace CustomCollectible {
|
||||||
|
|
||||||
|
enum CustomCollectibleFlags : int16_t {
|
||||||
|
KILL_ON_TOUCH = 1 << 0, // 0000 0000 0000 0001
|
||||||
|
GIVE_OVERHEAD = 1 << 1, // 0000 0000 0000 0010
|
||||||
|
GIVE_ITEM_CUTSCENE = 1 << 2, // 0000 0000 0000 0100
|
||||||
|
HIDE_TILL_OVERHEAD = 1 << 3, // 0000 0000 0000 1000
|
||||||
|
KEEP_ON_PLAYER = 1 << 4, // 0000 0000 0001 0000
|
||||||
|
STOP_BOBBING = 1 << 5, // 0000 0000 0010 0000
|
||||||
|
STOP_SPINNING = 1 << 6, // 0000 0000 0100 0000
|
||||||
|
CALLED_ACTION = 1 << 7, // 0000 0000 1000 0000
|
||||||
|
TOSS_ON_SPAWN = 1 << 8, // 0000 0001 0000 0000
|
||||||
|
};
|
||||||
|
void RegisterHooks();
|
||||||
|
EnItem00* Spawn(f32 posX, f32 posY, f32 posZ, s16 rot, s16 flags, s16 params, ActorFunc actionFunc = NULL,
|
||||||
|
ActorFunc drawFunc = NULL);
|
||||||
|
}; // namespace CustomCollectible
|
|
@ -84,6 +84,7 @@ Sail* Sail::Instance;
|
||||||
#include "Enhancements/mods.h"
|
#include "Enhancements/mods.h"
|
||||||
#include "Enhancements/game-interactor/GameInteractor.h"
|
#include "Enhancements/game-interactor/GameInteractor.h"
|
||||||
#include "Enhancements/randomizer/draw.h"
|
#include "Enhancements/randomizer/draw.h"
|
||||||
|
#include "Enhancements/custom-collectible/CustomCollectible.h"
|
||||||
#include <libultraship/libultraship.h>
|
#include <libultraship/libultraship.h>
|
||||||
|
|
||||||
// Resource Types/Factories
|
// Resource Types/Factories
|
||||||
|
@ -703,6 +704,7 @@ extern "C" void VanillaItemTable_Init() {
|
||||||
GET_ITEM(ITEM_NUT_UPGRADE_30, OBJECT_GI_NUTS, GID_NUTS, 0xA7, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_LESSER, MOD_NONE, GI_NUT_UPGRADE_30),
|
GET_ITEM(ITEM_NUT_UPGRADE_30, OBJECT_GI_NUTS, GID_NUTS, 0xA7, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_LESSER, MOD_NONE, GI_NUT_UPGRADE_30),
|
||||||
GET_ITEM(ITEM_NUT_UPGRADE_40, OBJECT_GI_NUTS, GID_NUTS, 0xA8, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_LESSER, MOD_NONE, GI_NUT_UPGRADE_40),
|
GET_ITEM(ITEM_NUT_UPGRADE_40, OBJECT_GI_NUTS, GID_NUTS, 0xA8, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_LESSER, MOD_NONE, GI_NUT_UPGRADE_40),
|
||||||
GET_ITEM(ITEM_BULLET_BAG_50, OBJECT_GI_DEKUPOUCH, GID_BULLET_BAG_50, 0x6C, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE, GI_BULLET_BAG_50),
|
GET_ITEM(ITEM_BULLET_BAG_50, OBJECT_GI_DEKUPOUCH, GID_BULLET_BAG_50, 0x6C, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE, GI_BULLET_BAG_50),
|
||||||
|
GET_ITEM(ITEM_SHIP, OBJECT_UNSET_16E, GID_MAXIMUM, 0x00, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE, GI_SHIP),
|
||||||
GET_ITEM_NONE,
|
GET_ITEM_NONE,
|
||||||
GET_ITEM_NONE,
|
GET_ITEM_NONE,
|
||||||
GET_ITEM_NONE // GI_MAX - if you need to add to this table insert it before this entry.
|
GET_ITEM_NONE // GI_MAX - if you need to add to this table insert it before this entry.
|
||||||
|
@ -1173,6 +1175,7 @@ extern "C" void InitOTR() {
|
||||||
DebugConsole_Init();
|
DebugConsole_Init();
|
||||||
|
|
||||||
InitMods();
|
InitMods();
|
||||||
|
CustomCollectible::RegisterHooks();
|
||||||
ActorDB::AddBuiltInCustomActors();
|
ActorDB::AddBuiltInCustomActors();
|
||||||
// #region SOH [Randomizer] TODO: Remove these and refactor spoiler file handling for randomizer
|
// #region SOH [Randomizer] TODO: Remove these and refactor spoiler file handling for randomizer
|
||||||
CVarClear(CVAR_GENERAL("RandomizerNewFileDropped"));
|
CVarClear(CVAR_GENERAL("RandomizerNewFileDropped"));
|
||||||
|
|
|
@ -399,6 +399,9 @@ DrawItemTableEntry sDrawItemTable[] = {
|
||||||
* Calls the corresponding draw function for the given draw ID
|
* Calls the corresponding draw function for the given draw ID
|
||||||
*/
|
*/
|
||||||
void GetItem_Draw(PlayState* play, s16 drawId) {
|
void GetItem_Draw(PlayState* play, s16 drawId) {
|
||||||
|
if (drawId < 0 || drawId >= GID_MAXIMUM) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
sDrawItemTable[drawId].drawFunc(play, drawId);
|
sDrawItemTable[drawId].drawFunc(play, drawId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1891,6 +1891,12 @@ u8 Return_Item(u8 itemID, ModIndex modId, ItemID returnItem) {
|
||||||
* @return u8
|
* @return u8
|
||||||
*/
|
*/
|
||||||
u8 Item_Give(PlayState* play, u8 item) {
|
u8 Item_Give(PlayState* play, u8 item) {
|
||||||
|
// TODO: Add ShouldItemGive
|
||||||
|
// if (!GameInteractor_ShouldItemGive(item) || item == ITEM_SHIP) {
|
||||||
|
if (item == ITEM_SHIP) {
|
||||||
|
return ITEM_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
//prevents getting sticks without the bag in case something got missed
|
//prevents getting sticks without the bag in case something got missed
|
||||||
if (
|
if (
|
||||||
IS_RANDO &&
|
IS_RANDO &&
|
||||||
|
@ -2486,6 +2492,11 @@ u8 Item_CheckObtainability(u8 item) {
|
||||||
s16 slot = SLOT(item);
|
s16 slot = SLOT(item);
|
||||||
s32 temp;
|
s32 temp;
|
||||||
|
|
||||||
|
// SOH [Enhancements] Added to enable custom item gives
|
||||||
|
if (item == ITEM_SHIP) {
|
||||||
|
return ITEM_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
if (item >= ITEM_STICKS_5) {
|
if (item >= ITEM_STICKS_5) {
|
||||||
slot = SLOT(sExtraItemBases[item - ITEM_STICKS_5]);
|
slot = SLOT(sExtraItemBases[item - ITEM_STICKS_5]);
|
||||||
}
|
}
|
||||||
|
|
|
@ -7312,6 +7312,7 @@ s32 Player_ActionHandler_2(Player* this, PlayState* play) {
|
||||||
interactedActor->id == ACTOR_EN_ITEM00 &&
|
interactedActor->id == ACTOR_EN_ITEM00 &&
|
||||||
interactedActor->params != ITEM00_HEART_PIECE &&
|
interactedActor->params != ITEM00_HEART_PIECE &&
|
||||||
interactedActor->params != ITEM00_SMALL_KEY &&
|
interactedActor->params != ITEM00_SMALL_KEY &&
|
||||||
|
interactedActor->params != ITEM00_NONE &&
|
||||||
interactedActor->params != ITEM00_SOH_GIVE_ITEM_ENTRY &&
|
interactedActor->params != ITEM00_SOH_GIVE_ITEM_ENTRY &&
|
||||||
interactedActor->params != ITEM00_SOH_GIVE_ITEM_ENTRY_GI
|
interactedActor->params != ITEM00_SOH_GIVE_ITEM_ENTRY_GI
|
||||||
) ||
|
) ||
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue