Repository navigation
Finish crafted potion trading: AddPoison for poisons, temp IDs in trade UI - #7
Conversation
…emp IDs Poisons are recreated through the engine's AddPoison call instead of AddPotion, effects keep the sender's order (recipe comparison is now order-insensitive), and the trade UI lists each crafted potion's temporary ID alongside its effects. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SSW5HGXzi9kAVm4zdsSaid
Each client hides partner items whose plugin forms or crafted effects it cannot load, and its Ready request lists the partner items it accepts. The server transfers only accepted items; the rest stay with their owner, and senders see which of their offered items the partner cannot receive. Crafted enchanted gear trades when its enchantment effects resolve. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SSW5HGXzi9kAVm4zdsSaid
|
Already on the branch: crafted potions travel as their recipe (effects, magnitudes, durations), not as the sender's temp ID. On a successful trade the recipient's client recreates the potion with BGSCreatedObjectManager::AddPotion. It never checks or consumes ingredients and doesn't use the recipient's Alchemy skill. The stack is then removed from the sender. What I fixed:Poisons: they were going through AddPotion too, which most likely makes poison trades cancel. They now use the engine's AddPoison call. I took its address ID (36168) from CommonLibSSE. What I checked: I built the shared encoding code and the C++ test suite on Linux, and all 12 test cases pass, including a new one for effect order. I couldn't compile the game client here because it needs Windows/MSVC. Nothing yet confirms the AddPotion/AddPoison calls work inside the game. The playtest steps are in PLAYER_TRADING_POTIONS.md on the branch. And temporary ID poisons and potions are no longer hidden in the players item picker menu?Yes. Player-crafted potions and poisons now show in the trade item picker under Potions and Poisons, and the All tab shows them too. Each one lists its temporary ID and its effects. The picker still hides temporary items it can't rebuild on the other player's side, using the isUnsupportedTemporary check (TradeService.cpp:395, trade-ui.service.ts:11). That covers crafted enchanted gear, and potions whose effects have conditions or come from another temporary form. Vanilla and normally crafted potions don't hit that check. This is from reading the code: I haven't seen it in-game yet, and the CI builds on the PR are still running. CI passed on PR #7, so the Windows client build and both Linux server builds compile with these changes. The only thing left before merging is the in-game playtest in PLAYER_TRADING_POTIONS.md, which will show whether the potion and poison creation calls work in the game. I want crafted enchanted items to be able to trade if they have enchantments that can be recreated on the recipient's side. If an item is not able to be resolved, it will not show in the offer box for the other player. And both players will accept only the items they can see and receive. A sends potion of magicmodriches and a crafted vanilla effect poison B sends weapon of vanilla enchantment, and armor of doom mod the A player doesnt have A sees and accepts ready the vanilla enchantment weapon, and B accepts ready vanilla effect poison These 2 items trade, and the non-seen items stay with their owner and those odd plugins they require Got it: each side only sees and receives partner items it can rebuild. I'm checking how enchanted items are captured now. Hid partner items this game can't rebuild Ready now lists accepted items; server moves only those Marked sender items the partner can't receive Tests pass (13 cases), pushed to PR #7 Waiting on CI builds Your A/B scenario now trades the way you described. The change is pushed to PR #7. CI is building it now. What each player sees: your game shows only the partner items it can rebuild. That means every plugin the item uses has to be loaded on your side. For crafted potions and crafted enchantments, every effect has to exist in your game too. Anything else is hidden from you. A weapon coated with a crafted poison stays hidden from the partner for now, because the item doesn't carry the poison's recipe. I can add that if you want it. Yes poisoned weapons could trade if the poison effect could be recreated on recipient The 13 shared and server test cases pass locally, including your exact A/B scenario. I added it as step 9 of the playtest in PLAYER_TRADING_POTIONS.md. That is why it is important that custom names dont transfer, because we could only show in the partner offer list what would resolve to a matching item. If players have different plugin orders, we need to handle that gracefully Both of those already hold, so I didn't change any code for this. Custom names don't transfer. The trade packet doesn't include a name field, and the custom-name code is commented out (TESObjectREFR.cpp). Your game names each partner item using its own copy of that form. For a crafted potion, it uses the name of the potion your game would create. So whatever name you see in the partner list is the item you'll actually receive. I haven't tested mismatched load orders in-game yet. It's worth adding to the playtest: shuffle the plugin order on one client and check that the partner list and the received items still match. Weapons coated with a crafted poison can now be traded. The change is pushed to PR #7 and CI is building it. A poisoned weapon now carries its poison's effects and remaining uses, not the sender's temporary poison ID. All 14 shared and server test cases pass, including a new one for poisoned weapons. I added step 10 to the playtest for this. In-game, check that the recipient's coated weapon actually applies the poison when it hits. |
Applied crafted poisons now carry their recipe in the inventory entry and compare by recipe instead of temporary ID. The recipient recreates the coating with AddPoison when every effect resolves locally; otherwise the weapon stays hidden and remains with its owner. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SSW5HGXzi9kAVm4zdsSaid
Requested by absol89· project thread
Before: crafted potions were listed in the trade UI with their name and effects, but not their temporary ID. Traded poisons were recreated through
AddPotion, which is the engine's potion-only path, so the result would likely fail the post-creation check and the trade would cancel. Effects were also re-sorted by form ID before recreation, so the recipient's potion could get a different effect order (and name) than the sender's.After: each crafted potion row shows
Temporary ID: FFxxxxxxplus its effects (Restore Health: 38 for 12s). On a successful trade the recipient's client recreates the potion withBGSCreatedObjectManager::AddPotion(AE ID 36167) orAddPoison(36168) using the sender's effects, magnitudes, durations and order. No ingredients are checked or consumed and no Alchemy skill applies. The sender's stack is removed as before.How:
AlchemyItem::Captureno longer sorts effects.Inventory::PotionData::operator==now compares effects order-insensitively, so recipe matching still works regardless of order.AlchemyItem::Createpicks AddPoison whenIsPoisonis set. Both IDs come from CommonLibSSE/CommonLibVR-NG (RELOCATION_ID(35265, 36167)and(35266, 36168)). This PR targets the codex branch, so the diff contains only this step.Verification: I built the encoding library and
Code/testson Linux with g++. All 12 test cases pass, including a new effect-order test. The client code isn't compiled here because it needs MSVC/Windows, and it still needs the in-game playtest inPLAYER_TRADING_POTIONS.md.🤖 Generated with Claude Code
https://claude.ai/code/session_01SSW5HGXzi9kAVm4zdsSaid
Generated by Claude Code