This shows you the differences between two versions of the page.
| Next revision | Previous revision | ||
| tutorial:esd-add-menu-reward [2026/06/20 20:49] – created jenovavirus | tutorial:esd-add-menu-reward [2026/06/20 23:27] (current) – and another one jenovavirus | ||
|---|---|---|---|
| Line 1: | Line 1: | ||
| - | ====== ESD: Add Menu and Rewards | + | ====== ESD: Add Menu and Trade Reward System |
| Authors: JeNoVaViRuS | Authors: JeNoVaViRuS | ||
| Line 7: | Line 7: | ||
| - | This tutorial will use esdtools python talk structure. Since this is python you NEED to pay attention to indents (otherwise it won't save). Copy and paste the existing indents if needed. | + | ===== Introduction ===== |
| - | You can write directly into the editor but it doesn' | + | |
| - | This tutorial will show how to add a custom menu in the talk menu o trade items. | + | This tutorial will use esdtools python talk structure. Since this is python you NEED to pay attention to indents (otherwise it won't save). Copy and paste the existing indents if needed. \\ |
| + | You can write directly into the editor but it doesn' | ||
| - | ===== Introduction ===== | + | This tutorial will show how to add a custom menu in the talk menu and trade items. \\ |
| - | All talk scripts are assigned to a character. Talk scripts can't be assigned to objects. | + | All talk scripts are assigned to a character. Talk scripts can't be assigned to objects. This means that every bonfire and covenant place without a leader has an invisible character standing there. |
| - | This means that every bonfire and covenant place without a leader has an invisible character standing there. | + | |
| You can use Smithbox to search a map for the invisible character (hemisphere shape and red mesh structure). \\ | You can use Smithbox to search a map for the invisible character (hemisphere shape and red mesh structure). \\ | ||
| Line 213: | Line 212: | ||
| + | Add 2 itemLots: | ||
| + | 3200920 (20x Throwing knife) \\ | ||
| + | 3200930 (1x Ember) \\ | ||
| + | DO NOT SET FLAGS FOR THEM! They need to be given repeatedly. \\ | ||
| + | Add the following " | ||
| + | 15000610: "Trade Firebomb for 20x Throwing Knife" \\ | ||
| + | 15000620: "Trade 3x Large Titanite Shard for Ember" \\ | ||
| + | 15001610: "No Firebomb in inventory" | ||
| + | 15001620: "3x Large Titanite Shards not in inventory" | ||
| + | We will add: | ||
| + | - a talk option | ||
| + | - a text menu there | ||
| + | - an exchange system (take an item from the player and award an item) | ||
| + | For the menu we add the new talk option: \\ | ||
| + | |||
| + | <code Python> | ||
| + | ... | ||
| + | # action: | ||
| + | AddTalkListDataIf(GetEventFlag(14000101) or GetEventFlag(2050), | ||
| + | # OUR CUSTOM TALK OPTION | ||
| + | # action: | ||
| + | AddTalkListData(4, | ||
| + | # action: | ||
| + | AddTalkListData(99, | ||
| + | ... | ||
| + | </ | ||
| + | |||
| + | ---- | ||
| + | |||
| + | then we add our check after the "elif GetTalkListEntryResult() == 3": | ||
| + | <code Python> | ||
| + | elif GetTalkListEntryResult() == 4: | ||
| + | assert t320000_x11() | ||
| + | assert not (CheckSpecificPersonMenuIsOpen(3, | ||
| + | </ | ||
| + | |||
| + | ---- | ||
| + | |||
| + | and here we add the actual state where we want to go: \\ | ||
| + | |||
| + | <code Python> | ||
| + | def t320000_x11(lot1=3200920, | ||
| + | """ | ||
| + | while True: | ||
| + | ClearTalkListData() | ||
| + | # goods1 = Firebomb | ||
| + | # goods2 = Large Titanie Shard | ||
| + | # action: | ||
| + | AddTalkListData(1, | ||
| + | # action: | ||
| + | AddTalkListData(2, | ||
| + | AddTalkListData(99, | ||
| + | ShowShopMessage(TalkOptionsType.Regular) | ||
| + | # Trade Firebomb for 20x Throwing Knife | ||
| + | if GetTalkListEntryResult() == 1: | ||
| + | assert (t320000_x12(lot1=lot1, | ||
| + | # Trade 3x Large Titanite Shard for Ember | ||
| + | elif GetTalkListEntryResult() == 2: | ||
| + | assert (t320000_x12(lot1=lot2, | ||
| + | elif GetTalkListEntryResult() == 99 or not (CheckSpecificPersonMenuIsOpen(1, | ||
| + | return 0 | ||
| + | </ | ||
| + | |||
| + | As you can see we change the value of " | ||
| + | |||
| + | IMPORTANT: You need to add these vars " | ||
| + | So in state " | ||
| + | |||
| + | <code Python> | ||
| + | call = t320000_x9() | ||
| + | </ | ||
| + | |||
| + | and you need to add it in the brackets so it gets passed to the state. \\ | ||
| + | |||
| + | <code Python> | ||
| + | call = t320000_x9(lot1=3200920, | ||
| + | </ | ||
| + | |||
| + | As you can see in the other states you can use the underscore so it uses the values that were passed from the call. \\ | ||
| + | I recommend atleast adding it in the main state " | ||
| + | |||
| + | ---- | ||
| + | |||
| + | Here we add another event that runs when one of the trade options was selected. \\ | ||
| + | We check for the lot1 var and then call state " | ||
| + | If it returns 0 (the player has the items) we take the items and call state " | ||
| + | If it returns 1 (the player doesn' | ||
| + | |||
| + | <code Python> | ||
| + | def t320000_x12(lot1=_, | ||
| + | if lot1 == 3200920: | ||
| + | call = t320000_x13(goods2=goods2, | ||
| + | if call.Get() == 0: | ||
| + | PlayerEquipmentQuantityChange(ItemType.Goods, | ||
| + | assert t320000_x14(lot1=lot1) | ||
| + | elif call.Get() == 1: | ||
| + | assert t320000_x15(action4=15001610) | ||
| + | elif lot1 == 3200930: | ||
| + | call = t320000_x13(goods2=goods2, | ||
| + | if call.Get() == 0: | ||
| + | PlayerEquipmentQuantityChange(ItemType.Goods, | ||
| + | assert t320000_x14(lot1=lot2) | ||
| + | elif call.Get() == 1: | ||
| + | assert t320000_x15(action4=15001620) | ||
| + | else: | ||
| + | pass | ||
| + | return 0 | ||
| + | </ | ||
| + | |||
| + | ---- | ||
| + | |||
| + | Here we pass the var " | ||
| + | However if your script would do the same thing for other talk options it is better to outsource it to another state and keep it clean. With 5 trade options it would be 5x times the lines. \\ | ||
| + | |||
| + | Check the players inventory for the items: \\ | ||
| + | |||
| + | <code Python> | ||
| + | def t320000_x13(goods2=_, | ||
| + | if z1 == goods2: | ||
| + | if ComparePlayerInventoryNumber(ItemType.Goods, | ||
| + | return 0 | ||
| + | else: | ||
| + | return 1 | ||
| + | elif z1 == goods3: | ||
| + | if ComparePlayerInventoryNumber(ItemType.Goods, | ||
| + | return 0 | ||
| + | else: | ||
| + | return 1 | ||
| + | </ | ||
| + | |||
| + | ---- | ||
| + | |||
| + | Reward the player with an item: \\ | ||
| + | |||
| + | <code Python> | ||
| + | def t320000_x14(lot1=_): | ||
| + | GetItemFromItemLot(lot1) | ||
| + | assert not IsMenuOpen(63) and GetCurrentStateElapsedFrames() > 1 | ||
| + | return 0 | ||
| + | </ | ||
| + | |||
| + | ---- | ||
| + | |||
| + | Show a text line to the player (if the player doesn' | ||
| + | |||
| + | <code Python> | ||
| + | def t320000_x15(action4=_): | ||
| + | OpenGenericDialog(7, | ||
| + | assert not CheckSpecificPersonGenericDialogIsOpen(0) | ||
| + | return 0 | ||
| + | </ | ||