diff --git a/scripts/4_World/YALootBoxes_ActionOpen.c b/scripts/4_World/YALootBoxes_ActionOpen.c index 937e3dd..081498c 100644 --- a/scripts/4_World/YALootBoxes_ActionOpen.c +++ b/scripts/4_World/YALootBoxes_ActionOpen.c @@ -38,8 +38,13 @@ class YALB_ActionOpenLootbox : ActionContinuousBase return ContinuousInteractActionInput; } - // Only offer the action if: target is our lootbox, it's locked, - // and the player is holding a valid key item for it. + // Offer the action when the target is our lootbox, it's locked, and the + // player is holding *some* item. We deliberately do NOT check the specific + // key item here: ActionCondition runs client-side to display the prompt, + // but the box-type config (required items) lives in $profile and is loaded + // server-side only, so GetTypeDef() is null on clients. The exact key-item + // requirement is enforced authoritatively in OnFinishProgressServer; the + // proximity "Requires: X" message tells the player what to hold. override bool ActionCondition(PlayerBase player, ActionTarget target, ItemBase item) { YALootBoxes_Base box = YALootBoxes_Base.Cast(target.GetObject()); @@ -49,10 +54,7 @@ class YALB_ActionOpenLootbox : ActionContinuousBase ItemBase handItem = player.GetItemInHands(); if (!handItem) return false; - YALB_BoxTypeDef def = box.GetTypeDef(); - if (!def) return false; - - return def.IsValidKeyItem(handItem.GetType()); + return true; } override int GetDuration(ActionData action_data) @@ -76,6 +78,15 @@ class YALB_ActionOpenLootbox : ActionContinuousBase ItemBase handItem = player.GetItemInHands(); + // Authoritative key-item gate (ActionCondition can't do this on the + // client - see note there). Wrong/empty item: tell the player what's + // needed and bail without rolling. + if (!handItem || !def.IsValidKeyItem(handItem.GetType())) + { + YALB_NotifyPlayer(player, "Requires: " + def.GetRequiredItemsDisplayString()); + return; + } + float roll = Math.RandomFloat01(); if (roll <= def.openChance) {