OSP Code QoL Trade Screen Replacer (WIP Code)

Users who are viewing this thread

Leonion

Master Knight
Native Trade Screen is a hard-coded presentations with very limited functionality/"editability".
Therefore I decided to replace it...

First, a video of what was done by now:

It's a custom presentation.
Second, what I do on this video:
1. Just showing overall look and item description pop-ups.
2. Top left corner - there is a button to switch merchants without exiting the screen.
3. DEAL button - it buys and sells items to and from the current merchant if both player and the merchant have enough money.
Before I do this, I select these items using left mouse button.
4.1. SELL AFTER button - it sells all items after a selected item (+this item too).
4.2. SELL BEFORE button - it sells all items before a selected item (+this item too) - for those who like to keep important/permanent stuff and food at the bottom of the inventory.
Both these buttons sell items to all merchants, preferring to distribute them among merchants depending on their type (armor to armourer, horses to horse merchant etc.).
5. Then I move/switch items using right mouse button (first I click item 1 and then I click either item 2 or empty space).
Item requirements and item type are taken into account, that's why replacing body armor with a bow doesn't work.
6. Finally, I buy an armor and then sell it by clicking left mouse button while holding CTRL (any CTRL). This way allows to buy or sell items one by one and immediately (instead of first selecting and then clicking "Deal!").
Third, the code of the presentation:
https://pastebin.com/ghp91xB4
Damn you, tiny character limit... :evil:
Oh, and this is only meant to work on gunless mods. No muskets, pistols etc. are included in the code.
Forth, what else you need for this...:
1. You may need to add some meshes to the list of meshes in module_meshes file if the compiler says they're missing. They should all be present in user_interface_b.brf
2. You need script_dplmc_get_item_value_with_imod from Diplomacy OSP (in my presentation it's called simply script_get_item_value_with_imod).
3. You need to edit the module_game_menus file. Personally, I suggest making new trade screen optional, something like this:
Code:
      ("trade_with_arms_merchant",[(party_slot_ge, "$current_town", slot_town_weaponsmith, 1)],
       "Trade with the arms merchant.",
       [
           (party_get_slot, "$temp_2", "$current_town", slot_town_weaponsmith),
		   (try_begin),
				(troop_slot_eq, "trp_globals_troop", slot_old_trade_menu_enabled, 1),
				(change_screen_trade, "$temp_2"),
		   (else_try),
				(start_presentation, "prsnt_trade_screen_replacer"),
		   (try_end),
        ]),
      ("trade_with_armor_merchant",[(party_slot_ge, "$current_town", slot_town_armorer, 1)],
       "Trade with the armor merchant.",
       [
           (party_get_slot, "$temp_2", "$current_town", slot_town_armorer),
		   (try_begin),
				(troop_slot_eq, "trp_globals_troop", slot_old_trade_menu_enabled, 1),
				(change_screen_trade, "$temp_2"),
		   (else_try),
				(start_presentation, "prsnt_trade_screen_replacer"),
		   (try_end),
        ]),
      ("trade_with_horse_merchant",[(party_slot_ge, "$current_town", slot_town_horse_merchant, 1)],
       "Trade with the horse merchant.",
       [
           (party_get_slot, "$temp_2", "$current_town", slot_town_horse_merchant),
		   (try_begin),
				(troop_slot_eq, "trp_globals_troop", slot_old_trade_menu_enabled, 1),
				(change_screen_trade, "$temp_2"),
		   (else_try),
				(start_presentation, "prsnt_trade_screen_replacer"),
		   (try_end),
        ]),
      ("trade_with_goods_merchant",[(party_slot_ge, "$current_town", slot_town_merchant, 1)],
       "Trade with the goods merchant.",
       [
           (party_get_slot, "$temp_2", "$current_town", slot_town_merchant),
		   (try_begin),
				(troop_slot_eq, "trp_globals_troop", slot_old_trade_menu_enabled, 1),
				(change_screen_trade, "$temp_2"),
		   (else_try),
				(start_presentation, "prsnt_trade_screen_replacer"),
		   (try_end),
        ]),
4. You also need to edit the game_get_item_extra_text script by adding this right after store_script_param operations:
Code:
	  (try_begin),
		(eq, reg58, -567), #special check to make sure we are in trade screen
		(assign, ":real_extra_text_id", ":extra_text_id"),
		(try_begin),
			(is_between, ":item_no", food_begin, food_end),
			(neq, reg59, reg60),
			(val_add, ":extra_text_id", -1),
			(eq, ":real_extra_text_id", 0),
			(set_result_string, "@Remaining amount: ({reg59}/{reg60})"),
			(set_trigger_result, 0xFF9933),
		(try_end),
		(try_begin),
			(item_slot_eq, ":item_no", slot_item_type, itp_type_bow),
			(val_add, ":extra_text_id", -1),
			(eq, ":real_extra_text_id", 0),
			(set_result_string, "@Requires Power Draw: {reg60}"),
			(try_begin),
				(store_skill_level, ":skill_level", skl_power_draw, "trp_player"),
				(ge, ":skill_level", reg60),
				(set_trigger_result, 0x00FF00),
			(else_try),
				(set_trigger_result, 0xFF0000),
			(try_end),
		(try_end),
		(try_begin),
			(item_slot_eq, ":item_no", slot_item_type, itp_type_thrown),
			(val_add, ":extra_text_id", -1),
			(eq, ":real_extra_text_id", 0),
			(set_result_string, "@Requires Power Throw: {reg60}"),
			(try_begin),
				(store_skill_level, ":skill_level", skl_power_throw, "trp_player"),
				(ge, ":skill_level", reg60),
				(set_trigger_result, 0x00FF00),
			(else_try),
				(set_trigger_result, 0xFF0000),
			(try_end),
		(try_end),
		(try_begin),
			(item_slot_eq, ":item_no", slot_item_type, itp_type_horse),
			(val_add, ":extra_text_id", -1),
			(eq, ":real_extra_text_id", 0),
			(set_result_string, "@Requires Riding: {reg60}"),
			(try_begin),
				(store_skill_level, ":skill_level", skl_riding, "trp_player"),
				(ge, ":skill_level", reg60),
				(set_trigger_result, 0x00FF00),
			(else_try),
				(set_trigger_result, 0xFF0000),
			(try_end),
		(try_end),
		(try_begin),
			(item_slot_eq, ":item_no", slot_item_type, itp_type_shield),
			(val_add, ":extra_text_id", -1),
			(eq, ":real_extra_text_id", 0),
			(set_result_string, "@Requires Shield: {reg60}"),
			(try_begin),
				(store_skill_level, ":skill_level", skl_shield, "trp_player"),
				(ge, ":skill_level", reg60),
				(set_trigger_result, 0x00FF00),
			(else_try),
				(set_trigger_result, 0xFF0000),
			(try_end),
		(try_end),
		(try_begin),
			(this_or_next|item_slot_eq, ":item_no", slot_item_type, itp_type_one_handed_wpn),
			(this_or_next|item_slot_eq, ":item_no", slot_item_type, itp_type_two_handed_wpn),
			(this_or_next|item_slot_eq, ":item_no", slot_item_type, itp_type_polearm),
			(this_or_next|item_slot_eq, ":item_no", slot_item_type, itp_type_crossbow),
			(this_or_next|item_slot_eq, ":item_no", slot_item_type, itp_type_head_armor),
			(this_or_next|item_slot_eq, ":item_no", slot_item_type, itp_type_body_armor),
			(this_or_next|item_slot_eq, ":item_no", slot_item_type, itp_type_foot_armor),
			(item_slot_eq, ":item_no", slot_item_type, itp_type_hand_armor),
			(val_add, ":extra_text_id", -1),
			(eq, ":real_extra_text_id", 0),
			(set_result_string, "@Requires Strength: {reg60}"),
			(try_begin),
				(store_attribute_level, ":skill_level", "trp_player", ca_strength),
				(ge, ":skill_level", reg60),
				(set_trigger_result, 0x00FF00),
			(else_try),
				(set_trigger_result, 0xFF0000),
			(try_end),
		(try_end),
	  (try_end),
And I think that's al...
Fifth, about pros, cons etc.
Pros:
+ something you can edit however you want
+ not only you can sell items in large numbers (which saves you a lot of time), but you have full control over what you sell (unlike autoloot/autosell where you're blind and you have to rely on a certain "border" price)
+ you can switch merchants without exiting/reentering the screen

Cons:
- for now no way to try an item before buying it. You can only move/switch your own items.
- item info pop-up only displays "Buying price" regardless of your/merchant inventory. The number is accurate (your items' "Buying price" is actually carefully calculated selling price), but the phrase itself cannot be changed (although when it comes to your items you can just read it from the merchant's perspective - a buying price for him/her). In theory, it is possible to make a custom dynamic pop-up inside the presentation, but I'm afraid it will be too messy.
- item info pop-up only displays max quantity of food, therefore I had to add that new orange line that mentions actual quantity.
- after you make changes in the inventory (buy/sell something) the presentation is reloaded and therefore it brings you back to the top of the inventory (not the best thing for those who like to "live" on the bottom), but, again, this replacer can easily be made optional
Now, does anyone have any improvement ideas, including ideas on how to fix "cons"?
And do you think this whole idea is worth it in the first place?
My personal primary interest in this is saving time (selling items in large numbers) while seeing what I actually sell.
 
HarryPham123 said:
i meant the link that you gave us is not working  :!: :?: the code of the presentation
What exactly in this link is not working?
"Server not found" or ... [insert_other_possible_errors_here]?
Because I could open it before and can open it right now:
3PSZLNJ.jpg
And there are 13 unique visits to this unlisted page, so they must come from here, from other people.
 
Leonion said:
HarryPham123 said:
i meant the link that you gave us is not working  :!: :?: the code of the presentation
What exactly in this link is not working?
"Server not found" or ... [insert_other_possible_errors_here]?
Because I could open it before and can open it right now:
3PSZLNJ.jpg
And there are 13 unique visits to this unlisted page, so they must come from here, from other people.

oh i have fixed it  :grin: sorry for bothering you :grin:
 
It turned out heavy and spirited horses don't add +1 to requirement [any more]. I fixed it in the code, but if you alredy use it, you need to update these 2 places:
Code:
            (item_get_difficulty, reg60, ":item_no"),
            (try_begin),
                (eq, ":imod", imod_masterwork), (val_add, reg60, 4),
            (else_try),
                (neg|item_slot_eq, ":item_no", slot_item_type, itp_type_horse),
                (eq, ":imod", imod_heavy), (val_add, reg60, 1),
            (else_try),
                (eq, ":imod", imod_strong), (val_add, reg60, 2),
            (else_try),
                (eq, ":imod", imod_stubborn), (val_add, reg60, 1),
            (else_try),
                (eq, ":imod", imod_timid), (val_add, reg60, -1), (val_max, reg60, 0),
            # (else_try),
                # (eq, ":imod", imod_spirited), (val_add, reg60, 1),
            (else_try),
                (eq, ":imod", imod_champion), (val_add, reg60, 2),
            (try_end),
Code:
                (item_get_difficulty, ":item_diff", ":item_in_question"),
                (try_begin),
                    (eq, ":imod", imod_masterwork), (val_add, ":item_diff", 4),
                (else_try),
                    (neg|item_slot_eq, ":item_in_question", slot_item_type, itp_type_horse),
                    (eq, ":imod", imod_heavy), (val_add, ":item_diff", 1),
                (else_try),
                    (eq, ":imod", imod_strong), (val_add, ":item_diff", 2),
                (else_try),
                    (eq, ":imod", imod_stubborn), (val_add, ":item_diff", 1),
                (else_try),
                    (eq, ":imod", imod_timid), (val_add, ":item_diff", -1), (val_max, reg60, 0),
                # (else_try),
                    # (eq, ":imod", imod_spirited), (val_add, ":item_diff", 1),
                (else_try),
                    (eq, ":imod", imod_champion), (val_add, ":item_diff", 2),
                (try_end),
The script also has some compatibility issues with xgm_item_powers code (OSP where you can give bonus stats to items), so instead of using its injector for game_get_item_extra_text script, add that part manually after the trade screen code.
(this_or_next|item_slot_eq, ":item_no", slot_item_type, itp_type_foot_armor),
(item_slot_eq, ":item_no", slot_item_type, itp_type_hand_armor),
(val_add, ":extra_text_id", -1),
(eq, ":real_extra_text_id", 0),
(set_result_string, "@Requires Strength: {reg60}"),
(try_begin),
(store_attribute_level, ":skill_level", "trp_player", ca_strength),
(ge, ":skill_level", reg60),
(set_trigger_result, 0x00FF00),
(else_try),
(set_trigger_result, 0xFF0000),
(try_end),
(try_end),
  (try_end),
#[the last pieces of trade screen code above]
  (try_begin),
      (this_or_next|neq, reg58, -567), (neq, ":real_extra_text_id", 0),
  (call_script, "script_cf_xgm_get_item_extra_text", ":item_no", ":extra_text_id", ":item_modifier"),
      (set_result_string, "@{s0}"),
      (set_trigger_result, reg0),
    (else_try),

#[the first pieces of native code below]
      (is_between, ":item_no", food_begin, food_end),
      (try_begin),
          (eq, ":extra_text_id", 0),
          (assign, ":continue", 1),
            (try_begin),
 
Very impressive addition to OSP options. I particularly like the ability to toggle instantly between merchants. Unfortunately, as a sad slave of fashion, I’m wedded to trying on clothes before buying them - stats are one thing, but for me it’s got to look good as well.
Keep up your great work.  :grin:
 
Very nice! I have a similar idea for the character creation screen and all the other hard-coded screens as well. One day, I can envision us playing on a "floating chassis" of sorts.
 
If anybody's using it - sorry, I made a stupid mistake in sell after/before part.
h-331.jpg
Those 8 operations were in the place of the red line and should be moved to where they're on the screenshot (inside try_for_range block, not before it). The old position basically made merchants have infinite money to buy your goods (not that bad a bug, but still :smile:).
Please correct it in your files.
 
So after doing a lot of research I chose this as my first mod to incorporate into M&B... naturally I have an issue that arose and I do not know how to resolve. I started by compiling a fresh download of the module system and it worked, but when adding in this code I get the following error:

NameError: name 'mesh_inventory_window_b' is not defined

I am assuming I need to add mesh_inventory_window_b to module_meshes.py

but how is this done? I did try looking for how this is done and did not see a link or other forum subject that looked relevant. If someone could point me in the right direction I would greatly appreciate the help.
 
Thank you,

I did add that to meshes then got other errors about slot_item_type being unrecognized...

Here is what I did

1. start with fresh copy of Module System 1.171
2. Added the Presentation code to the bottom of the module_presentations.py between end comment about Invasion mode End and the final bracket
3. Copied the dplmc_get_item_value_with_imod from Diplomacy module_scripts.py to the end of my module_scripts.py between end comment about Invasion mode End and the final bracket
4. Added the code into module_scripts.py into the game_get_item_extra_text area as described
5. added the inventory_window_b snippet to the end of module_meshes.py

compiled at this point and recieved a few errors

6. added to the headers of  module_presentations.py
Code:
from header_items import *
from header_item_modifiers import *
from header_skills import *

7. compiled again and got errors about slot_item_type still being unrecognized
8. changed all mentions of slot_item_type to ":i_slot" (with the quotes) in both module_presentations.py and module_scripts.py
9. compiled, errors no longer about unrecognized, but now "ERROR: Usage of unassigned local variable: :i_slot"

10. loaded game and it appears to be running the code
 
Back
Top Bottom