I found the cause for this bug. It's located in src/cmd/unit_generic.cpp
I) ROOT CAUSE:
Below you can read the relevant code extract, broken down into separate sections for explanatory reasons.
In the code below,
up->mount is the weapon (of any sort) that is evaluated for eligibility and
mount[jmod] is a mount of the player's ship.
I've broken the code into 4 phpbb blocks purely for ease of explanation, but the 4 extracts below are directly following each other in the source.
Basically this code extract will be crossed through if the type of the examined ship's mount fits the type of mount for the upgrade being evaluated for eligibility.
If at any point the boolean
cancompletefully is allocated to false, the weapon ends up not being eligible for this mount of the player's ship.
We'll use the example of a Dostoevsky ship trying to mount a torpedo.
I.A) Installing a new weapon on an empty mount, or a mount with a different weapon previously installed.
Code: Select all
if (up->mounts[i].type->weapon_name != mounts[jmod].type->weapon_name || mounts[jmod].status
== Mount::DESTROYED || mounts[jmod].status == Mount::UNCHOSEN) {
//If missile, can upgrade directly, if other type of ammo, needs actual gun to be present.
if (isammo && !ismissiletype) {
cancompletefully = false;
} else {
++numave; //ok now we can compute percentage of used parts
Mount upmount( up->mounts[i] );
if (templ) {
if (templ->GetNumMounts() > jmod) {
if (templ->mounts[jmod].volume != -1)
if (upmount.ammo*upmount.type->volume > templ->mounts[jmod].volume)
upmount.ammo = (int) ( (templ->mounts[jmod].volume+1)/upmount.type->volume );
}
}
//compute here
percentage += mounts[jmod].Percentage( &upmount );
//if we wish to modify the mounts
if (touchme)
//switch this mount with the upgrador mount
mounts[jmod].ReplaceMounts( this, &upmount );
}
} else {
Note in the above there is never any sort of comparison between the volume of the upgrade and the volume accepted by the ship's mount. Only the type of mount has to fit (this is handled by code above my extract in the source file
unit_generic.cpp).
I.B) Adding ammo to an already mounted gun or missile rack, including when said mount has 0 ammo remaining.
Code: Select all
if (isammo && up->mounts[i].type->weapon_name == mounts[jmod].type->weapon_name) {
//if is ammo and is same weapon type
int tmpammo = mounts[jmod].ammo;
if (mounts[jmod].ammo != -1 && up->mounts[i].ammo != -1) {
tmpammo += up->mounts[i].ammo;
if (templ) {
if (templ->GetNumMounts() > jmod) {
if (templ->mounts[jmod].volume != -1) {
if (templ->mounts[jmod].volume < mounts[jmod].type->volume*tmpammo) {
tmpammo =
(int) floor( .125
+( (0
+templ->mounts[jmod].volume)
/mounts[jmod].type->volume ) );
}
}
}
}
Code: Select all
if (tmpammo*mounts[jmod].type->volume > mounts[jmod].volume)
tmpammo = (int) floor( .125+( (0+mounts[jmod].volume)/mounts[jmod].type->volume ) );
In the above the available volume of the ship's mount has been evaluated against the volume required to add one to its ammo count.
But in the case of a Dosto and a torpedo, the volume of the ship's mount is 32, while the volume necessary per torpedo is 100.
I don't know where the 0.125 comes from, but in the Dosto/Torpedo example it's not enough to bring
tmpammo to a value of one...
Code: Select all
if (tmpammo > mounts[jmod].ammo) {
cancompletefully = true;
if (touchme)
mounts[jmod].ammo = tmpammo;
} else {
cancompletefully = false;
}
}
} else {
cancompletefully = false;
}
}
II) SUGGESTED FIXES:
II.A) Treat a mount with zero ammo remaining same as an empty mount
This is author's preferred approach at this stage, being that it is probably the safest in order to achieve consistency.
I've also proposed this fix on SF in the bug tracking system.
svn diff
Code: Select all
Index: src/cmd/unit_generic.cpp
===================================================================
--- src/cmd/unit_generic.cpp (revision 13449)
+++ src/cmd/unit_generic.cpp (working copy)
@@ -6366,7 +6366,7 @@
//only look at this mount if it can fit in the rack
if ( (unsigned int) (up->mounts[i].type->size) == (up->mounts[i].type->size&mounts[jmod].size) ) {
if (up->mounts[i].type->weapon_name != mounts[jmod].type->weapon_name || mounts[jmod].status
- == Mount::DESTROYED || mounts[jmod].status == Mount::UNCHOSEN) {
+ == Mount::DESTROYED || mounts[jmod].status == Mount::UNCHOSEN || mounts[jmod].ammo == 0) {
//If missile, can upgrade directly, if other type of ammo, needs actual gun to be present.
if (isammo && !ismissiletype) {
cancompletefully = false;
II.B) Override of volume ratio calculation so that a stock of 1 ammo is always authorized
I haven't done any sort of testing on that one, but it's a possibility after all. I can only tell you that for me it compiles. I'd consider it less reliable so long as the same kind of volume check that there is in I.B is not added in I.A.
svn diff
Code: Select all
Index: src/cmd/unit_generic.cpp
===================================================================
--- src/cmd/unit_generic.cpp (revision 13449)
+++ src/cmd/unit_generic.cpp (working copy)
@@ -6397,17 +6397,17 @@
if (templ->GetNumMounts() > jmod) {
if (templ->mounts[jmod].volume != -1) {
if (templ->mounts[jmod].volume < mounts[jmod].type->volume*tmpammo) {
- tmpammo =
+ tmpammo = std::min( 1,
(int) floor( .125
+( (0
+templ->mounts[jmod].volume)
- /mounts[jmod].type->volume ) );
+ /mounts[jmod].type->volume ) ) );
}
}
}
}
if (tmpammo*mounts[jmod].type->volume > mounts[jmod].volume)
- tmpammo = (int) floor( .125+( (0+mounts[jmod].volume)/mounts[jmod].type->volume ) );
+ tmpammo = std::min( 1, (int) floor( .125+( (0+mounts[jmod].volume)/mounts[jmod].type->volume ) ) );
if (tmpammo > mounts[jmod].ammo) {
cancompletefully = true;
if (touchme)
III)
DISCUSSION:
Both fixes I suggest are on the generous side. After all, we could consider that if a mount's volume is insuffcient, even if it is of the right type, then it should not be possible to install the weapon there... But in the particular case of a Dostoevsky, we can be sure it was the content dev's intent to allow the ship to carry a torpedo, if only a single one... Personally as a player I would kind of feel spoiled if this was changed somehow.
In some cases this might be exceedingly generous though. Once, when I was pretty deep in Rlaan space, couldn't find any torpedo so I bought a miniature grav-thumper to the insects (btw, is it intended that an ammo gun can fit to a missile mount?). The weapon initially came with 8 ammo. But I seem to remember that, when buying ammo to refill, I could never bring the ammo count above 1. Selling and rebuying the weapon at any given upgrade center was expensive, but it did bring the ammo count back to 8... I suspect the reason for this was that there isn't any sort of volume check in the code extract I.A above. Had there been, I suspect my ammo count would have been one also when buying the weapon brand new.
Maybe a fair compromise would be to add some volume check within I.A (like the one there is in I.B, but in both I.A and I.B add an override so that a raw capacity of zero coming out of the volume calculation is transformed into a capacity of 1.