• New Horizons on Maelstrom
    Maelstrom New Horizons


    Visit our website www.piratehorizons.com to quickly find download links for the newest versions of our New Horizons mods Beyond New Horizons and Maelstrom New Horizons!

Fixed Ships with no cannons have no calibre in a transfer

Mere_Mortal

Free Like a Radical
Storm Modder
Okay, so if a ship has no guns and some are transferred onto it (not bought, that works differently, this is a ship-to-ship transfer), then because it has a zero calibre (because it has no guns) the guns being transferred will not have a calibre defined. This means that it would not be possible to fire them.

I’m struggling to get my head around the way the code is keeping track of the guns going back and forth, but one thing stands out... there is no exit confirmation in this scenario. Therefore, although the guns are transferred the calibre is not being set because that is what the confirmation does.

For some reason, the current number of guns being transferred is dropping into a negative number at some point for the ship which is taking them (the one with no guns to begin with), I cannot fathom why this is happening.
 
Last edited:
I know ships with no cannons get the NONE_CANNON type. Might be CANNON_NONE as well.
That is probably defined as being -1 .
 
There needs to be a workaround for this. Either the transfer can take place and the calibre be applied properly, no transfer takes places at all or else the player is warned that the guns will essentially be rendered useless.
I know ships with no cannons get the NONE_CANNON type. Might be CANNON_NONE as well.
That is probably defined as being -1 .
Wait, is that what type “31” is? Okay then, so it is. CANNON_TYPE_NONECANNON it would appear. ;)
Code:
void ProcessExit()
{
   ...
   if (curQty != 0 && xi_refCharacter.ship.cannons.type == "31") {
     SetCharacterCannonType(xi_refCharacter,GetCaracterShipCannonsType(tmpChar))
   }
   if (enCurQty != 0 && tmpChar.ship.cannons.type == "31") {
     SetCharacterCannonType(tmpChar,GetCaracterShipCannonsType(xi_refCharacter))
   }
   ...
Sorted! :woot At least I think that’ll work.
 
Last edited:
There is a #define for it somewhere. Maybe it is CANNON_TYPE_NONE . Our maybe that with CANNONS instead.
Can't remember off the top of my head.

Look up the function definition for GiveShip2Character in NK.c .
I know it is referenced in there.
 
Yeah, I found that. I already noticed type 31 in a dump for the ship. I can easily check that attribute so it’s just a matter of looking to see if a ship with that type is getting any guns. Basically, what should be happening is that instead of it having no calibre at all, it should temporarily be regarded as having the same calibre as the ship the guns are coming from. If no transfer takes place then the calibre stays at zero.
 
Yeah, I found that. I already noticed type 31 in a dump for the ship. I can easily check that attribute so it’s just a matter of looking to see if a ship with that type is getting any guns. Basically, what should be happening is that instead of it having no calibre at all, it should temporarily be regarded as having the same calibre as the ship the guns are coming from. If no transfer takes place then the calibre stays at zero.
What if you remove all cannons from a ship that can have a maximum of 4lbs cannons, then transfer a 32lbs cannon on it?
I think that should either not be allowed OR the cannons should be downgraded to the maximum that the ship can handle.
 
Yeah. The code I posted was something I was looking at but you rightly mentioned about preventing ships receiving too big a calibre, which that wouldn’t do alone. I’ll look into it again at some point.
 
I think you where close, I sugest changing this:
Code:
if(myCurQty>0)
    {
        if(myCaliber>enCaliber) SetCharacterCannonType(xi_refCharacter, GetCaracterShipCannonsType(tmpChar));
        else SetCharacterCannonType(xi_refCharacter, GetCaracterShipCannonsType(xi_refCharacter));
    }

    if(enCurQty>0)
    {
        if(enCaliber>myCaliber) SetCharacterCannonType(tmpChar, GetCaracterShipCannonsType(xi_refCharacter));
        else SetCharacterCannonType(tmpChar, GetCaracterShipCannonsType(tmpChar));
    }
to
Code:
    if(myCurQty>0)
    {
        if(myCaliber == CANNON_TYPE_NONECANNON)
        {
            SetCharacterCannonType(xi_refCharacter, GetCaracterShipCannonsType(tmpChar));
        }
        else
        {
            if(myCaliber>enCaliber) SetCharacterCannonType(xi_refCharacter, GetCaracterShipCannonsType(tmpChar));
            else SetCharacterCannonType(xi_refCharacter, GetCaracterShipCannonsType(xi_refCharacter));
        }
    }

    if(enCurQty>0)
    {
        if(enCaliber == CANNON_TYPE_NONECANNON)
        {
            SetCharacterCannonType(tmpChar, GetCaracterShipCannonsType(xi_refCharacter));
        }
        else
        {
            if(enCaliber>myCaliber) SetCharacterCannonType(tmpChar, GetCaracterShipCannonsType(xi_refCharacter));
            else SetCharacterCannonType(tmpChar, GetCaracterShipCannonsType(tmpChar));
        }
    }

I think this should do it but I'm not sure.
I included a file where it is change, if someone can test it, it would be nice.

new fix: Confirmed Bug - Ships with no cannons have no calibre in a transfer | PiratesAhoy!
 
Last edited:
Looking into @Levis' proposed fix, it does not seem like this would work for two separate reasons.

1. CANNON_TYPE_NONECANNON is defined as 31
If the player has "none cannons", then 'GetCaracterShipCannonsType(xi_refCharacter)' returns 'CANNON_TYPE_NONECANNON' (e.g. 31).
Then 'sti(GetCannonCaliber(GetCaracterShipCannonsType(xi_refCharacter)))' returns 0 and 'myCaliber' ends up being '0'.
So this will never return 'true':
Code:
if(myCaliber == CANNON_TYPE_NONECANNON)

2. GetCaracterShipCannonsType does this:
Code:
int GetCaracterShipCannonsType(ref _refCharacter)
{
   if(!CheckAttribute(_refCharacter,"Ship.Cannons.Type")) return CANNON_TYPE_NONECANNON;
   return sti(_refCharacter.Ship.Cannons.Type);
}

And SetCharacterCannonType does this:
Code:
void SetCharacterCannonType(ref rCharacter,int nCannonType)
{
   rCharacter.Ship.Cannons.Type = nCannonType;
}

So you'd end up reading the current player cannon type, then setting the current player cannon type to what it already was.
 
While thinking this through, at one point I came up with a complicated solution with something like this:
Code:
ref rShip = GetCharacterShipType(xi_refCharacter);
if (myCaliber == 0 && CheckAttribute(rShip, "Cannon"))   SetCharacterCannonType(xi_refCharacter, sti(rShip.Cannon));

But thinking about it further, is there any reason why the below would NOT work?
Code:
   if(myCurQty>0)
   {
     if(myCaliber>enCaliber || myCaliber == 0) SetCharacterCannonType(xi_refCharacter, GetCaracterShipCannonsType(tmpChar));
     //else SetCharacterCannonType(xi_refCharacter, GetCaracterShipCannonsType(xi_refCharacter));
   }
If you are adding cannons and you have zero calibre (because you have no cannons), then set your calibre to match with the enemy.
If not, then do nothing because you already have the cannon type that it is setting anyway.

Getting a bit confused between 'myQty' and 'myCurQty'. Maybe the other one should be used?
By the looks of it, 'myQty' actually serves no purpose.

This will probably require a bit more thorough thought and testing by the person doing the fixing to ensure it ends up doing what we think it should be doing.
So since @Levis started on this, I'm more than happy to let him finish it too. :doff
 
@Pieter Boelen shouldn't changing
CANNON_TYPE_NONECANNON to 0
work in my solution?
 
@Pieter Boelen shouldn't changing
CANNON_TYPE_NONECANNON to 0
work in my solution?
Sounds like a scary thing to do. I've become quite cautious indeed after all the hardship we went through last year.
Anyway, why would you change the #define when checking 'myCaliber == 0' should work too?
 
Sounds like a scary thing to do. I've become quite cautious indeed after all the hardship we went through last year.
Anyway, why would you change the #define when checking 'myCaliber == 0' should work too?
Thats what I mean
 
Thats what I mean
By the looks of it, that would end up being functionally equivalent to my proposal above.
Only difference is that the version I suggested uses less code.

My main confusion with it now is the difference between 'myQty' and 'myCurQty' and which of those two should actually be used.
 
By the looks of it, that would end up being functionally equivalent to my proposal above.
Only difference is that the version I suggested uses less code.

My main confusion with it now is the difference between 'myQty' and 'myCurQty' and which of those two should actually be used.
The function which where present already use myCurQty, I believe you need to use that one too.
Your solution looks good too.
 
well best way is to test. Same story I can't test untill 10 PM tonight or so, so if someone has some time please test.
Place this in \PROGRAM\interface

@Pieter Boelen I left the if statement in tact because I think that one is needed in some cases.
 

Attachments

  • transfer_cannons.c
    49.1 KB · Views: 118
I left the if statement in tact because I think that one is needed in some cases.
What cases though? As far as I can tell, it reads what it is, then sets back what it already was.
Anyway, I suppose there is no harm in leaving that in place. Shouldn't do any harm at least. :shrug
 
Back
Top