From 0e806d9be33474bad6e686d4e1685ac7ec1c5351 Mon Sep 17 00:00:00 2001 From: Ivan Sokolov Date: Sun, 18 Jun 2023 17:36:50 +0800 Subject: [PATCH 1/3] Add feature for automatic calculation of barter money --- src/inventory.cc | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/src/inventory.cc b/src/inventory.cc index 351584c3..89326848 100644 --- a/src/inventory.cc +++ b/src/inventory.cc @@ -263,6 +263,7 @@ static void inventoryWindowOpenContextMenu(int eventCode, int inventoryWindowTyp static int _move_inventory(Object* a1, int a2, Object* a3, bool a4); static int _barter_compute_value(Object* a1, Object* a2); static int _barter_attempt_transaction(Object* a1, Object* a2, Object* a3, Object* a4); +static int _barter_get_quantity_moved_items(Object* item, int maxQuantity, bool fromPlayerToNpc); static void _barter_move_inventory(Object* a1, int quantity, int a3, int a4, Object* a5, Object* a6, bool a7); static void _barter_move_from_table_inventory(Object* a1, int quantity, int a3, Object* a4, Object* a5, bool a6); static void inventoryWindowRenderInnerInventories(int win, Object* a2, Object* a3, int a4); @@ -4755,6 +4756,27 @@ static int _barter_attempt_transaction(Object* a1, Object* a2, Object* a3, Objec return 0; } +static int _barter_get_quantity_moved_items(Object* item, int maxQuantity, bool fromPlayerToNpc) { + if (maxQuantity <= 1) { + return maxQuantity; + } + + int quantityToMove = -1; + if (item->pid == PROTO_ID_MONEY && !gGameDialogSpeakerIsPartyMember) { + // Calculate change money automatically + int totalCostPlayer = objectGetCost(_ptable); + int totalCostNpc = _barter_compute_value(gDude, _target_stack[0]); + quantityToMove = fromPlayerToNpc ? std::min(totalCostNpc - totalCostPlayer, maxQuantity): + std::min(totalCostPlayer - totalCostNpc, maxQuantity); + } + // If the item is not money or player wants to add extra money + // then open window to set quantity manually + if (quantityToMove <= 0) { + quantityToMove = inventoryQuantitySelect(INVENTORY_WINDOW_TYPE_MOVE_ITEMS, item, maxQuantity); + } + return quantityToMove; +} + // 0x474DAC static void _barter_move_inventory(Object* a1, int quantity, int a3, int a4, Object* a5, Object* a6, bool a7) { @@ -4813,7 +4835,7 @@ static void _barter_move_inventory(Object* a1, int quantity, int a3, int a4, Obj if (a7) { if (mouseHitTestInWindow(gInventoryWindow, INVENTORY_TRADE_INNER_LEFT_SCROLLER_TRACKING_X, INVENTORY_TRADE_INNER_LEFT_SCROLLER_TRACKING_Y, INVENTORY_TRADE_INNER_LEFT_SCROLLER_TRACKING_MAX_X, INVENTORY_SLOT_HEIGHT * gInventorySlotsCount + INVENTORY_TRADE_INNER_LEFT_SCROLLER_TRACKING_Y)) { - int quantityToMove = quantity > 1 ? inventoryQuantitySelect(INVENTORY_WINDOW_TYPE_MOVE_ITEMS, a1, quantity) : 1; + int quantityToMove = _barter_get_quantity_moved_items(a1, quantity, a7); if (quantityToMove != -1) { if (itemMoveForce(_inven_dude, a6, a1, quantityToMove) == -1) { // There is no space left for that item. @@ -4826,7 +4848,7 @@ static void _barter_move_inventory(Object* a1, int quantity, int a3, int a4, Obj } } else { if (mouseHitTestInWindow(gInventoryWindow, INVENTORY_TRADE_INNER_RIGHT_SCROLLER_TRACKING_X, INVENTORY_TRADE_INNER_RIGHT_SCROLLER_TRACKING_Y, INVENTORY_TRADE_INNER_RIGHT_SCROLLER_TRACKING_MAX_X, INVENTORY_SLOT_HEIGHT * gInventorySlotsCount + INVENTORY_TRADE_INNER_RIGHT_SCROLLER_TRACKING_Y)) { - int quantityToMove = quantity > 1 ? inventoryQuantitySelect(INVENTORY_WINDOW_TYPE_MOVE_ITEMS, a1, quantity) : 1; + int quantityToMove = _barter_get_quantity_moved_items(a1, quantity, a7); if (quantityToMove != -1) { if (itemMoveForce(a5, a6, a1, quantityToMove) == -1) { // You cannot pick that up. You are at your maximum weight capacity. From a949178e3044ae1e7c458fa1c023d622d6f3e738 Mon Sep 17 00:00:00 2001 From: Ivan Sokolov Date: Wed, 21 Jun 2023 21:13:06 +0800 Subject: [PATCH 2/3] Set recomended ammount of money to be moved for barter The feature works in any direction to move from/to player/npc and from/to inventory/table --- src/inventory.cc | 55 +++++++++++++++++++++++++++++++----------------- 1 file changed, 36 insertions(+), 19 deletions(-) diff --git a/src/inventory.cc b/src/inventory.cc index 89326848..fad55600 100644 --- a/src/inventory.cc +++ b/src/inventory.cc @@ -263,7 +263,7 @@ static void inventoryWindowOpenContextMenu(int eventCode, int inventoryWindowTyp static int _move_inventory(Object* a1, int a2, Object* a3, bool a4); static int _barter_compute_value(Object* a1, Object* a2); static int _barter_attempt_transaction(Object* a1, Object* a2, Object* a3, Object* a4); -static int _barter_get_quantity_moved_items(Object* item, int maxQuantity, bool fromPlayerToNpc); +static int _barter_get_quantity_moved_items(Object* item, int maxQuantity, bool fromPlayer, bool fromInventory); static void _barter_move_inventory(Object* a1, int quantity, int a3, int a4, Object* a5, Object* a6, bool a7); static void _barter_move_from_table_inventory(Object* a1, int quantity, int a3, Object* a4, Object* a5, bool a6); static void inventoryWindowRenderInnerInventories(int win, Object* a2, Object* a3, int a4); @@ -272,7 +272,7 @@ static void _container_exit(int keyCode, int inventoryWindowType); static int _drop_into_container(Object* a1, Object* a2, int a3, Object** a4, int quantity); static int _drop_ammo_into_weapon(Object* weapon, Object* ammo, Object** a3, int quantity, int keyCode); static void _draw_amount(int value, int inventoryWindowType); -static int inventoryQuantitySelect(int inventoryWindowType, Object* item, int a3); +static int inventoryQuantitySelect(int inventoryWindowType, Object* item, int max, int suggestedValue=1); static int inventoryQuantityWindowInit(int inventoryWindowType, Object* item); static int inventoryQuantityWindowFree(int inventoryWindowType); @@ -4756,25 +4756,42 @@ static int _barter_attempt_transaction(Object* a1, Object* a2, Object* a3, Objec return 0; } -static int _barter_get_quantity_moved_items(Object* item, int maxQuantity, bool fromPlayerToNpc) { +static int _barter_get_quantity_moved_items( + Object* item, + int maxQuantity, + bool fromPlayer, + bool fromInventory +) { if (maxQuantity <= 1) { return maxQuantity; } - int quantityToMove = -1; + int suggestedValue = 1; if (item->pid == PROTO_ID_MONEY && !gGameDialogSpeakerIsPartyMember) { // Calculate change money automatically int totalCostPlayer = objectGetCost(_ptable); int totalCostNpc = _barter_compute_value(gDude, _target_stack[0]); - quantityToMove = fromPlayerToNpc ? std::min(totalCostNpc - totalCostPlayer, maxQuantity): - std::min(totalCostPlayer - totalCostNpc, maxQuantity); - } - // If the item is not money or player wants to add extra money - // then open window to set quantity manually - if (quantityToMove <= 0) { - quantityToMove = inventoryQuantitySelect(INVENTORY_WINDOW_TYPE_MOVE_ITEMS, item, maxQuantity); - } - return quantityToMove; + int balance = totalCostPlayer - totalCostNpc; + bool balancePositive = true; + if (balance < 0) { + balancePositive = false; + balance = -balance; + } + // fromPlayer | fromInventory | balancePositive | suggestedVale + // 0 | 0 | 0 | abs(balance) + // 0 | 0 | 1 | 1 + // 0 | 1 | 0 | 1 + // 0 | 1 | 1 | balance + // 1 | 0 | 0 | 1 + // 1 | 0 | 1 | balance + // 1 | 1 | 0 | abs(balance) + // 1 | 1 | 1 | 1 + // if balance 0 then suggestedVale is 1 + if (balance != 0 && !(fromPlayer ^ fromInventory ^ balancePositive)) { + suggestedValue = std::min(balance, maxQuantity); + } + } + return inventoryQuantitySelect(INVENTORY_WINDOW_TYPE_MOVE_ITEMS, item, maxQuantity, suggestedValue); } // 0x474DAC @@ -4835,7 +4852,7 @@ static void _barter_move_inventory(Object* a1, int quantity, int a3, int a4, Obj if (a7) { if (mouseHitTestInWindow(gInventoryWindow, INVENTORY_TRADE_INNER_LEFT_SCROLLER_TRACKING_X, INVENTORY_TRADE_INNER_LEFT_SCROLLER_TRACKING_Y, INVENTORY_TRADE_INNER_LEFT_SCROLLER_TRACKING_MAX_X, INVENTORY_SLOT_HEIGHT * gInventorySlotsCount + INVENTORY_TRADE_INNER_LEFT_SCROLLER_TRACKING_Y)) { - int quantityToMove = _barter_get_quantity_moved_items(a1, quantity, a7); + int quantityToMove = _barter_get_quantity_moved_items(a1, quantity, a7, true); if (quantityToMove != -1) { if (itemMoveForce(_inven_dude, a6, a1, quantityToMove) == -1) { // There is no space left for that item. @@ -4848,7 +4865,7 @@ static void _barter_move_inventory(Object* a1, int quantity, int a3, int a4, Obj } } else { if (mouseHitTestInWindow(gInventoryWindow, INVENTORY_TRADE_INNER_RIGHT_SCROLLER_TRACKING_X, INVENTORY_TRADE_INNER_RIGHT_SCROLLER_TRACKING_Y, INVENTORY_TRADE_INNER_RIGHT_SCROLLER_TRACKING_MAX_X, INVENTORY_SLOT_HEIGHT * gInventorySlotsCount + INVENTORY_TRADE_INNER_RIGHT_SCROLLER_TRACKING_Y)) { - int quantityToMove = _barter_get_quantity_moved_items(a1, quantity, a7); + int quantityToMove = _barter_get_quantity_moved_items(a1, quantity, a7, true); if (quantityToMove != -1) { if (itemMoveForce(a5, a6, a1, quantityToMove) == -1) { // You cannot pick that up. You are at your maximum weight capacity. @@ -4922,7 +4939,7 @@ static void _barter_move_from_table_inventory(Object* a1, int quantity, int a3, if (a6) { if (mouseHitTestInWindow(gInventoryWindow, INVENTORY_TRADE_LEFT_SCROLLER_TRACKING_X, INVENTORY_TRADE_LEFT_SCROLLER_TRACKING_Y, INVENTORY_TRADE_LEFT_SCROLLER_TRACKING_MAX_X, INVENTORY_SLOT_HEIGHT * gInventorySlotsCount + INVENTORY_TRADE_LEFT_SCROLLER_TRACKING_Y)) { - int quantityToMove = quantity > 1 ? inventoryQuantitySelect(INVENTORY_WINDOW_TYPE_MOVE_ITEMS, a1, quantity) : 1; + int quantityToMove = _barter_get_quantity_moved_items(a1, quantity, a6, false); if (quantityToMove != -1) { if (itemMoveForce(a5, _inven_dude, a1, quantityToMove) == -1) { // There is no space left for that item. @@ -4935,7 +4952,7 @@ static void _barter_move_from_table_inventory(Object* a1, int quantity, int a3, } } else { if (mouseHitTestInWindow(gInventoryWindow, INVENTORY_TRADE_RIGHT_SCROLLER_TRACKING_X, INVENTORY_TRADE_RIGHT_SCROLLER_TRACKING_Y, INVENTORY_TRADE_RIGHT_SCROLLER_TRACKING_MAX_X, INVENTORY_SLOT_HEIGHT * gInventorySlotsCount + INVENTORY_TRADE_RIGHT_SCROLLER_TRACKING_Y)) { - int quantityToMove = quantity > 1 ? inventoryQuantitySelect(INVENTORY_WINDOW_TYPE_MOVE_ITEMS, a1, quantity) : 1; + int quantityToMove = _barter_get_quantity_moved_items(a1, quantity, a6, false); if (quantityToMove != -1) { if (itemMoveForce(a5, a4, a1, quantityToMove) == -1) { // You cannot pick that up. You are at your maximum weight capacity. @@ -5596,7 +5613,7 @@ static void _draw_amount(int value, int inventoryWindowType) } // 0x47688C -static int inventoryQuantitySelect(int inventoryWindowType, Object* item, int max) +static int inventoryQuantitySelect(int inventoryWindowType, Object* item, int max, int suggestedValue) { ScopedGameMode gm(GameMode::kCounter); @@ -5605,7 +5622,7 @@ static int inventoryQuantitySelect(int inventoryWindowType, Object* item, int ma int value; int min; if (inventoryWindowType == INVENTORY_WINDOW_TYPE_MOVE_ITEMS) { - value = 1; + value = suggestedValue; if (max > 99999) { max = 99999; } From 0e31ac4753b9b3eed096e83ba1f9d17737d6f8c8 Mon Sep 17 00:00:00 2001 From: Ivan Sokolov Date: Thu, 22 Jun 2023 00:38:18 +0800 Subject: [PATCH 3/3] Simplyfy logic to calc suggested amount of barter money --- src/inventory.cc | 29 ++++++++--------------------- 1 file changed, 8 insertions(+), 21 deletions(-) diff --git a/src/inventory.cc b/src/inventory.cc index fad55600..c5ee3dd8 100644 --- a/src/inventory.cc +++ b/src/inventory.cc @@ -272,7 +272,7 @@ static void _container_exit(int keyCode, int inventoryWindowType); static int _drop_into_container(Object* a1, Object* a2, int a3, Object** a4, int quantity); static int _drop_ammo_into_weapon(Object* weapon, Object* ammo, Object** a3, int quantity, int keyCode); static void _draw_amount(int value, int inventoryWindowType); -static int inventoryQuantitySelect(int inventoryWindowType, Object* item, int max, int suggestedValue=1); +static int inventoryQuantitySelect(int inventoryWindowType, Object* item, int max, int defaultValue=1); static int inventoryQuantityWindowInit(int inventoryWindowType, Object* item); static int inventoryQuantityWindowFree(int inventoryWindowType); @@ -4771,24 +4771,11 @@ static int _barter_get_quantity_moved_items( // Calculate change money automatically int totalCostPlayer = objectGetCost(_ptable); int totalCostNpc = _barter_compute_value(gDude, _target_stack[0]); - int balance = totalCostPlayer - totalCostNpc; - bool balancePositive = true; - if (balance < 0) { - balancePositive = false; - balance = -balance; - } - // fromPlayer | fromInventory | balancePositive | suggestedVale - // 0 | 0 | 0 | abs(balance) - // 0 | 0 | 1 | 1 - // 0 | 1 | 0 | 1 - // 0 | 1 | 1 | balance - // 1 | 0 | 0 | 1 - // 1 | 0 | 1 | balance - // 1 | 1 | 0 | abs(balance) - // 1 | 1 | 1 | 1 - // if balance 0 then suggestedVale is 1 - if (balance != 0 && !(fromPlayer ^ fromInventory ^ balancePositive)) { - suggestedValue = std::min(balance, maxQuantity); + // Actor's balance: negative - the actor must add money to balance the tables and vice versa + int balance = fromPlayer ? totalCostPlayer - totalCostNpc : totalCostNpc - totalCostPlayer; + + if ( (balance < 0 && fromInventory) || (balance > 0 && !fromInventory) ) { + suggestedValue = std::min(std::abs(balance), maxQuantity); } } return inventoryQuantitySelect(INVENTORY_WINDOW_TYPE_MOVE_ITEMS, item, maxQuantity, suggestedValue); @@ -5613,7 +5600,7 @@ static void _draw_amount(int value, int inventoryWindowType) } // 0x47688C -static int inventoryQuantitySelect(int inventoryWindowType, Object* item, int max, int suggestedValue) +static int inventoryQuantitySelect(int inventoryWindowType, Object* item, int max, int defaultValue) { ScopedGameMode gm(GameMode::kCounter); @@ -5622,11 +5609,11 @@ static int inventoryQuantitySelect(int inventoryWindowType, Object* item, int ma int value; int min; if (inventoryWindowType == INVENTORY_WINDOW_TYPE_MOVE_ITEMS) { - value = suggestedValue; if (max > 99999) { max = 99999; } min = 1; + value = std::clamp(defaultValue, min, max); } else { value = 60; min = 10;