opentibiabr / canary

Canary Server 13.x for OpenTibia community.
https://docs.opentibiabr.com/
GNU General Public License v2.0
358 stars 594 forks source link

Convergence Fusion price calculation is wrong #2523

Open suencet opened 5 months ago

suencet commented 5 months ago

Priority

Medium

Area

What happened?

It seems like Convergence Fusion price calculation is bugged. For example, making item from tier0 to tier1 is always free. Client is showing correct price but the amount taken from bank account is always lower than it's supposed to. Fusion of tier3 item will cost you as if you had tier2 item tiers etc

What OS are you seeing the problem on?

Linux, Windows

Code of Conduct

un000000 commented 5 months ago

try this: https://github.com/opentibiabr/canary/pull/2092

valdzera commented 5 months ago

Replace this code in player.cpp:

if (convergence) {
    firstForgedItem->setTier(tier + 1);
    history.dustCost = dustCost;
    setForgeDusts(getForgeDusts() - dustCost);

    uint64_t cost = 0;
    for (const auto* itemClassification : g_game().getItemsClassifications()) {
        if (itemClassification->id != firstForgingItem->getClassification()) {
            continue;
        }
        for (const auto &[mapTier, mapPrice] : itemClassification->tiers) {
            if (mapTier == firstForgingItem->getTier()) {
                cost = mapPrice.convergenceFusionPrice;
                break;
            }
        }

for this one:

if (convergence) {
    firstForgedItem->setTier(tier + 1);
    history.dustCost = dustCost;
    setForgeDusts(getForgeDusts() - dustCost);

    uint64_t cost = 0;
    for (const auto* itemClassification : g_game().getItemsClassifications()) {
        if (itemClassification->id != firstForgingItem->getClassification()) {
            continue;
        }
    for (const auto &[mapTier, mapPrice] : itemClassification->tiers) {
            if (mapTier == firstForgingItem->getTier() + 1) {
                cost = mapPrice.convergenceFusionPrice;
                break;
            }
        }

It should fix it.

suencet commented 5 months ago

Replace this code in player.cpp:

if (convergence) {
  firstForgedItem->setTier(tier + 1);
  history.dustCost = dustCost;
  setForgeDusts(getForgeDusts() - dustCost);

  uint64_t cost = 0;
  for (const auto* itemClassification : g_game().getItemsClassifications()) {
      if (itemClassification->id != firstForgingItem->getClassification()) {
          continue;
      }
      for (const auto &[mapTier, mapPrice] : itemClassification->tiers) {
          if (mapTier == firstForgingItem->getTier()) {
              cost = mapPrice.convergenceFusionPrice;
              break;
          }
      }

for this one:

if (convergence) {
  firstForgedItem->setTier(tier + 1);
  history.dustCost = dustCost;
  setForgeDusts(getForgeDusts() - dustCost);

  uint64_t cost = 0;
  for (const auto* itemClassification : g_game().getItemsClassifications()) {
      if (itemClassification->id != firstForgingItem->getClassification()) {
          continue;
      }
  for (const auto &[mapTier, mapPrice] : itemClassification->tiers) {
          if (mapTier == firstForgingItem->getTier() + 1) {
              cost = mapPrice.convergenceFusionPrice;
              break;
          }
      }

It should fix it.

This one worked, thank you a lot sir!

valdzera commented 5 months ago

The logic for Convergence Fusion in protocolgame.cpp accounts for the tier as tier - 1:


// Exalted core table per tier
msg.addByte(static_cast<uint8_t>(tierCorePrices.size()));
for (const auto &[tier, cores] : tierCorePrices) {
    msg.addByte(tier);
    msg.addByte(cores);
}

// Convergence fusion prices per tier
msg.addByte(static_cast<uint8_t>(convergenceFusionPrices.size()));
for (const auto &[tier, price] : convergenceFusionPrices) {
    msg.addByte(tier - 1);
    msg.add<uint64_t>(price);
}

// Convergence transfer prices per tier
msg.addByte(static_cast<uint8_t>(convergenceTransferPrices.size()));
for (const auto &[tier, price] : convergenceTransferPrices) {
    msg.addByte(tier);
    msg.add<uint64_t>(price);
}

This approach is likely adopted for client-side interpretation because removing the -1 caused the client to crash during a Convergence Fusion operation.

Thus, the logic behind the calculation was incorrect. Given that protocolgame.cpp handles Convergence Fusion with tier - 1, I had to adjust by adding +1 to account for the item as if it were tier 0.

Aerwix commented 4 months ago

Replace this code in player.cpp:

if (convergence) {
  firstForgedItem->setTier(tier + 1);
  history.dustCost = dustCost;
  setForgeDusts(getForgeDusts() - dustCost);

  uint64_t cost = 0;
  for (const auto* itemClassification : g_game().getItemsClassifications()) {
      if (itemClassification->id != firstForgingItem->getClassification()) {
          continue;
      }
      for (const auto &[mapTier, mapPrice] : itemClassification->tiers) {
          if (mapTier == firstForgingItem->getTier()) {
              cost = mapPrice.convergenceFusionPrice;
              break;
          }
      }

for this one:

if (convergence) {
  firstForgedItem->setTier(tier + 1);
  history.dustCost = dustCost;
  setForgeDusts(getForgeDusts() - dustCost);

  uint64_t cost = 0;
  for (const auto* itemClassification : g_game().getItemsClassifications()) {
      if (itemClassification->id != firstForgingItem->getClassification()) {
          continue;
      }
  for (const auto &[mapTier, mapPrice] : itemClassification->tiers) {
          if (mapTier == firstForgingItem->getTier() + 1) {
              cost = mapPrice.convergenceFusionPrice;
              break;
          }
      }

It should fix it.

It this working correctly according to Cip's behaviour? If yes, why you don't send a Pull Request?

valdzera commented 4 months ago

Replace this code in player.cpp:


if (convergence) {

    firstForgedItem->setTier(tier + 1);

    history.dustCost = dustCost;

    setForgeDusts(getForgeDusts() - dustCost);

    uint64_t cost = 0;

    for (const auto* itemClassification : g_game().getItemsClassifications()) {

        if (itemClassification->id != firstForgingItem->getClassification()) {

            continue;

        }

        for (const auto &[mapTier, mapPrice] : itemClassification->tiers) {

            if (mapTier == firstForgingItem->getTier()) {

                cost = mapPrice.convergenceFusionPrice;

                break;

            }

        }

for this one:


if (convergence) {

    firstForgedItem->setTier(tier + 1);

    history.dustCost = dustCost;

    setForgeDusts(getForgeDusts() - dustCost);

    uint64_t cost = 0;

    for (const auto* itemClassification : g_game().getItemsClassifications()) {

        if (itemClassification->id != firstForgingItem->getClassification()) {

            continue;

        }

    for (const auto &[mapTier, mapPrice] : itemClassification->tiers) {

            if (mapTier == firstForgingItem->getTier() + 1) {

                cost = mapPrice.convergenceFusionPrice;

                break;

            }

        }

It should fix it.

It this working correctly according to Cip's behaviour? If yes, why you don't send a Pull Request?

Yes. I will do it tomorrow, sorry about that.

github-actions[bot] commented 1 month ago

This issue is stale because it has been open 120 days with no activity.