• 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 Crew salary estimates are wrong

jsv

Freebooter
Storm Modder
Just another todo list entry. I plan to look into it myself later next week.

After starting a new game, I hired crew and a couple of officers then went on repairs. Here are salary estimates after 3 days of game time:
badmath3.jpg

Officers' pay estimate seems to be within reason, that of the crew is not.
 
What is wrong about it?

I think the F2> Ship> Crew interface should give you the same numbers, no?
 
What is wrong about it?

I think the F2> Ship> Crew interface should give you the same numbers, no?
I think he means its the 3th day so about 1/10 of the amount should be owed now so that amount times 10 should give you the monthly pay.
For officer this seems about right. But for the crew the amount owed is way higher then the amount per month divided by 10.
 
There is some complex coding in place for that if I remember.
This is to take care of the number of crew changing throughout the month.
 
I think he means its the 3th day so about 1/10 of the amount should be owed now so that amount times 10 should give you the monthly pay.
For officer this seems about right. But for the crew the amount owed is way higher then the amount per month divided by 10.
Exactly. By the end of the much I'll be paying the crew much more than those 2106 returned by GetEstimatedCrewPay.
 
If is quite impossible to estimate a value per month anyway; just a value for THIS month.
Imagine sailing with 1 crew until the 30th and then hiring a 1000.
Then this month you should pay 1 crew for 30 days and 1000 crew for 1 day.
But next month it would be 1000 crew for ALL days.

Not sure how that is currently set up in the game code though.
 
If is quite impossible to estimate a value per month anyway; just a value for THIS month.
Imagine sailing with 1 crew until the 30th and then hiring a 1000.
Oh, let's not imagine that. :) Imagine I'm a trader. I own a hoy. I hired a crew of 24 for her first thing in the morning. I fully expect to keep that crew of 24 as long as I keep that hoy. I want to know how much I'm going to pay monthly, given nothing dramatic is happened. What's so impossible about that? And that's exactly what GetEstimatedCrewPay tries to do:

Code:
int GetEstimatedCrewPay()
{
    ref mchref = GetMainCharacter();
    if (CheckAttribute(mchref,"isnotcaptain")) return 0;        // LDH 16Apr09

    float fEstCrewPay = 0;
    //add crew pay owed:
    int LeaderShip = GetShipSkill(mchref,SKILL_LEADERSHIP);
    float fCrewScalar = (1.0 - (makefloat(LeaderShip)*makefloat(1.0+GetOfficersPerkUsing(mchref,"IronWill"))/40.0)) * (0.5 + makefloat(GetDifficulty())*0.5);
    fEstCrewPay += GetSquadronTotalCrewQuantity(mchref)*BASE_CREW_PAY * fCrewScalar * SALARY_MULTIPLIER;
    return makeint(fEstCrewPay);
}

Not sure how that is currently set up in the game code though.
The actual payment is calculated daily and is accumulated in .quest.CrewPayOwed.

Here is the relevant part of DoDailyCrewPay:
Code:
    float fCrewPay = 0;
    //add crew pay owed:
    int LeaderShip = GetShipSkill(mchref,SKILL_LEADERSHIP);
    float fCrewScalar = (1.0 - (
                                makefloat(LeaderShip)
                                * makefloat(1.0+GetOfficersPerkUsing(mchref,"IronWill")) / 40.0
                         )) * (0.5 + makefloat(GetDifficulty())*0.5);
    if(CheckAttribute(mchref,"quest.CrewPayOwed")) fCrewPay = stf(mchref.quest.CrewPayOwed);
    fCrewPay += crewQ*BASE_CREW_PAY *12/365 * fCrewScalar * SALARY_MULTIPLIER;
    mchref.quest.CrewPayOwed = fCrewPay;
CrewQ being the result of GetSquadronTotalCrewQuantity.

So far I do not understand why there is such big discrepancy...
 
Best solution might be too have one single function to calculate salaries.
I think at the moment the same or similar code can be found in multiple spots, which probably isn't helping. :facepalm
 
@jsv could you maybe take a look at this and see if you can get one function which can be used everywhere?
 
Will do. Crew-related stuff looks straightforward enough (still it's buggy somehow :)). Officer/passenger code is more hairy, but should be doable as well.
I'm not sure yet how busy I'll be with my work this week, but I hope to find some time.
 
Before I start hacking at the code, let's see if I myself get the math right.

I start a new Sea Hawk game at swashbuckler difficulty and fire some crew so I have only 10.

BASE_CREW_PAY = 12 and the default SALARY_MULTIPLIER = 3, so unmodified monthly salary for 10 men is 360;
The modifier for swashbuckler difficulty (4) is 4/2+0.5 = 2.5.
Nataniel Hawk's leadership is 1, no Iron Will, the modifier for leadership is 1 - 1/40 = 0.975.
So, for this crew, the expected monthly salary is 360*2.5*0.975 = 877.5 (both GetEstimatedCrewPay and GetRaiseMoraleCost return 877, so this seems about right).
Expected daily increment to CrewPayOwed is 877.5*12/365 ~= 28.85; 28 after rounding down by makeint.
If nothing changes, the actual payment for April will be 28*30 = 840.
Are those the numbers we want?


Edit: it's not rounded down and it's Apr 16th already, so make that 865.5 for 30 days.
Interestingly enough, the actual daily increase to CrewPayOwed in this particular game is not higher than my estimate, but, instead, lower: 21.9375... Well, I guess I have to refactor the code first and then, if the numbers still do not match, think why :)
 
Last edited:
ofcourse depending on where in the month zou fired them right?
If you fire them halfway trough the month it should take into account the part where you had more too.
 
I mean the starting date for the Sea Hawk game is 16th Apr, not the 1st. Firing those guys was the first thing I've done.
When the CrewPayOwed attribute was calculated for the first time, I only had 10 crewmen.
 
Ah, one mystery solved. Interface screens (salary screen included) use CalcSquadronPayment function, which uses its own exclusive CalcCrewPayment function, which happens to be completely wrong.
That CalcCrewPayment thing thinks the difficulty and leadership modifiers are not factored into CrewPayOwed, so it applies them again. That explains that difference in my first post.

The entire mess is worse than I initially thought. There is berthing code that uses its own routines and there are remnants of no longer used CrewPayment attribute all over the code. It will take some time to sort this out...
 
Could it be that the code gets confused when you don't start playing at the beginning of the month?
So the estimated pay will assume that it IS a full monthly pay, except that it isn't?
 
Ah, one mystery solved. Interface screens (salary screen included) use CalcSquadronPayment function, which uses its own exclusive CalcCrewPayment function, which happens to be completely wrong.
That CalcCrewPayment thing thinks the difficulty and leadership modifiers are not factored into CrewPayOwed, so it applies them again. That explains that difference in my first post.

The entire mess is worse than I initially thought. There is berthing code that uses its own routines and there are remnants of no longer used CrewPayment attribute all over the code. It will take some time to sort this out...
I was afraid of that. When you mentioned it, I remembered seeing very similar code scattered throughout the game. That is never a good thing, as far as I'm concerned;
if something CAN be done with a single function, that makes it so much simpler and massively reduces the chance for such silly inconsistencies.
So it'll be great if you can do that and relay all pay-related functionality to that same one instead.

If you need any assistance with it, of course let us know!
And in case you didn't know it yet, some of these might be helpful:
Tutorial - Modding Tips & Tricks | PiratesAhoy!
 
Both estimated pay and the value accumulated in CrewPayOwed are roughly correct (there is a little discrepancy that I haven't yet figured out).
The salary screen use a wrong value (with modifiers for difficulty and leadership applied twice), though. On the highest difficulty you pay about twice as much as you should, more without decent leadership.

The estimated pay is what you'll be paying after a month (365/12 days) from today, it doesn't look at the current date. That's ok with me. We can try to estimate what you'll be paying at the payday instead, but I don't know if it's worth the effort.
 
The estimated pay is what you'll be paying after a month (365/12 days) from today, it doesn't look at the current date. That's ok with me. We can try to estimate what you'll be paying at the payday instead, but I don't know if it's worth the effort.
Probably not. Simple is good. :cheeky
 
If you need any assistance with it, of course let us know!
Well, there is one thing in the salary logic I don't fully understand, as I do not remember the game all that well. In payment-related code there are multiple checks for "isnotcaptain" attribute. When the main character is not a captain? And, more importantly, can there be situations when you are not a captain but still need to pay the crew (some of the code suggests otherwise, but I'd like to be sure)?
 
In payment-related code there are multiple checks for "isnotcaptain" attribute. When the main character is not a captain?
At the moment only exclusively in the Hornblower storyline when you are a Midshipman on a large ship.
While you are still the main character, of course, for story purposes you're not actually meant to be in charge.

And, more importantly, can there be situations when you are not a captain but still need to pay the crew (some of the code suggests otherwise, but I'd like to be sure)?
The whole purpose of that attribute is to NOT have the player pay any salary in that case.
Since you're not in charge, but are just a crewmember/officer on board, you shouldn't need to have the responsibility to pay for the rest of the crew either. ;)

So basically, if "isnotcaptain", both estimated and actual salaries should be 0.
 
  • Like
Reactions: jsv
Back
Top