Autobuy problem resulting in crash
-
Ahoy @ all.
I think i found a problem within the hooking of autobuy and want to present a solution. But first wanted to ask if i am on the right way.
Fact is there is a division by zero implemented.
Archetype::Equipment *eq = Archetype::GetEquipment ((*it4).iArchID); if (iRemHoldSize < (eq->fVolume * (*it4).iCount)) { uint iNewCount = iRemHoldSize / (uint)eq->fVolume; if (!iNewCount) { //PrintUserCmdText (iClientID, L"Auto-Buy (%s): FAILED! Insufficient cargo space", (*it4).wscDescription.c_str ()); continue; } else { (*it4).iCount = iNewCount; } }
In case there are more items to missing than fitting into cargo. The number of items that can be bought until the cargo limit is reached is calculated. But if the volume of one item is smaller than 1 then the game crashes with a division by zero. Because there is a typecast from eq->fVolume to integer it will be a 0. The calculation should be:
uint iNewCount = (uint)(iRemHoldSize / eq->fVolume);
What ya say?
-
Gonna use that as i have seem to find another problem with the autobuy. Its again if the volume is less than 1.
Somewhen later the remaining holdsize is corrected with the following line:
int iCost = ((int)fPrice * (*it4).iCount); .... iRemHoldSize -= ((int)eq->fVolume * (*it4).iCount);
But it should be more like, because making int of a float less than 1 makes it 0. Multiplying something with 0 is always 0 - hence the remaining cargo hold cannot be corrected properly.
int iCost = (int)(fPrice * (*it4).iCount); ... iRemHoldSize -= (int)(eq->fVolume * (*it4).iCount);
Didnt tested it yet - but seems to be a reasonable bug…
-
Not necessarily
BTW yesterday i had in mind to make an EnumCargo Routine that returns a float value of the remaining hold. Currently its always int (what is not wrong - but not accurate :)). Especially if you have items with a volume lower than 1.
Not really a bug - but maybe an improvement… -
Found another issue which might lead to wrong autobuy. If a ship has no batts/bots defined it can happen that the autobuy buys nearly 4 billion items
here the code:
foreach(lstCargo, CARGO_INFO, it) { AUTOBUY_CARTITEM aci; if((*it).iArchID == iNanobotsID) { aci.iArchID = iNanobotsID; aci.iCount = ship->iMaxNanobots - (*it).iCount; aci.wscDescription = L"Nanobots"; lstCart.push_back(aci); bNanobotsFound = true; } else if((*it).iArchID == iShieldBatsID){ aci.iArchID = iShieldBatsID; aci.iCount = ship->iMaxShieldBats - (*it).iCount; aci.wscDescription = L"Shield Batteries"; lstCart.push_back(aci); bShieldBattsFound = true; } }
Should be changed to:
foreach (lstCargo, CARGO_INFO, it) { AUTOBUY_CARTITEM aci; if (((*it).iArchID == iNanobotsID) && (ship->iMaxNanobots > 0)) { aci.iArchID = iNanobotsID; aci.iCount = ship->iMaxNanobots - (*it).iCount; aci.wscDescription = L"Nanobots"; lstCart.push_back (aci); bNanobotsFound = true; } else if (((*it).iArchID == iShieldBatsID) && (ship->iMaxShieldBats > 0)) { aci.iArchID = iShieldBatsID; aci.iCount = ship->iMaxShieldBats - (*it).iCount; aci.wscDescription = L"Shield Batteries"; lstCart.push_back (aci); bShieldBattsFound = true; } } if ((!bNanobotsFound) && (ship->iMaxNanobots > 0)) { // no nanos found -> add all AUTOBUY_CARTITEM aci; aci.iArchID = iNanobotsID; aci.iCount = ship->iMaxNanobots; aci.wscDescription = L"Nanobots"; lstCart.push_back (aci); } if ((!bShieldBattsFound) && (ship->iMaxShieldBats > 0)) { // no batts found -> add all AUTOBUY_CARTITEM aci; aci.iArchID = iShieldBatsID; aci.iCount = ship->iMaxShieldBats; aci.wscDescription = L"Shield Batteries"; lstCart.push_back (aci); } }