• 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 Crewmember as an officer. Salary.

Serge Grey

Powder Monkey
1. PoTC NG Build 14, Tuesday 27th March 2018
2. Noticed, when a sailor of your ship goes ashore with you and you ask him "You must have gained some experience... ...But how good are you really?", there is already increased salary value for him. And this value increases with each next same question about. If you hire him as an officer, monthly salary will increase significantly too. Any officer's finance report shows it.

Anyway it would be more realistic if with one new officer from your crew, crew's number decreased for one.

3. OK.
4. Program\internalsettings.h changes only (// Included in Iron Man Mode and // LOG, LOOKS & EFFECTS sections).
5. OK.
 

Attachments

  • compile.log
    4.2 KB · Views: 175
  • system.log
    4.4 KB · Views: 181
  • -=Serge=- Barbados.7z
    631.9 KB · Views: 182
Last edited:
Looking into this:
I found the dialog file in which you can promote a crewmember to officer - "permanent_crewmember_dialog.c". At case "enlist_me", which is where the crewmember becomes an officer, there's this line:
Code:
if(MAX_CREWMEMBERS>1){MAX_CREWMEMBERS=MAX_CREWMEMBERS-1;}
MAX_CREWMEMBERS seems to be something to do with tracking how many crew you have ashore.

If you take some crew ashore and some of them get killed (quite likely, as the gang will probably trigger some random raids), the ship's crew is reduced at some point, probably when you return to the ship. But I can't find the code which does it. And, as pointed out, the ship's crew is not reduced when you return with an otherwise intact shore party, minus 1 because he's now an officer. @Pieter Boelen: any idea where I can look for the relevant code?
 
PROGRAM\DIALOGS\permanent_crewmember_dialog.c:
Code:
        case "enlist_me":
            if(MAX_CREWMEMBERS>1){MAX_CREWMEMBERS=MAX_CREWMEMBERS-1;}

PROGRAM\Loc_ai\LAi_init.c:
Code:
                        if(Lai_IsDead(crew))
                        {
                            RemoveCharacterCrew(mainChr,1);
                            if(MAX_CREWMEMBERS  > 0){MAX_CREWMEMBERS = MAX_CREWMEMBERS-1;}
                            if(MAX_CREWMEMBERS == 0) LANDCREWMEMBERS = false; // PB: If all your crew died, disable this mod
                        }
I think both sections of code should ideally be the same; but as you can see, they're not. :facepalm

Crewmember officer price is here:
Code:
    int min_off_price = makeint( 1000 * sqrt(sti(NPChar.rank)) );
    if(sti(NPChar.quest.OfficerPrice) < min_off_price) NPChar.quest.OfficerPrice = min_off_price; // PB: Increased salary for better crewmember as officer
It shouldn't randomly go up; but does go up if the crewmember levels up.
 
Thanks! I'll leave salaries alone - if he's an officer then presumably his salary is calculated the same way as any other officer. But that code in "LAi_init.c" for removing a crewmember does look more complete and correct than the version in "permanent_crewmember_dialog.c", so I'll copy it into place. "permanent_crewmember_dialog.c" also has several lines of hard-wired dialog text, so I'll transfer those into "permanent_crewmember_dialog.h" and replace them with "DLG_TEXT" references.
 
I'll leave salaries alone - if he's an officer then presumably his salary is calculated the same way as any other officer.
Once he's actually hired, he should become as much a regular officer as any other.
But prior to being hired, the initial officer price should be calculated differently.
 
The fix to "permanent_crewmember_dialog.c" worked - after I'd replaced "mainChr" with "PChar", that is. Promoting a crewmember to officer instantly reduced the ship's crew by 1.

Any suggestions on what to do about initial officer price? I can confirm that if you repeatedly ask him "How good are you really?", his price goes up, though you need to work at it by first asking him, then telling him to get back to work, then asking him again. (Maybe he thinks that if you're that interested in him, he can demand more money. Wrong. I told him to return to the ship. The next crewman was back to the original starting salary, and he's the one I promoted to officer. :D)
 
The price is only set at the start of the dialog, right?
Then the only explanation I can think of is that the skill-viewing interface is interfering with it somehow.
 
In "permanent_crewmember_dialog.c":
Code:
       case "ShowSkills":
           // Aconcagua: LaunchOfficer uses separate interface now
           Diag.CurrentNode = "ReturnfromSkillview";
           NPChar.quest.OfficerPrice = CalcEncOfficerPrice(NPChar); // <--- This looks suspicious
           Pchar.Quest.Last_Enc_Officer = NPChar.Index;
           DialogExit();           
           LaunchOfficer(NPChar); // MAXIMUS interface MOD
       break;

'CalcEncOfficerPrice' is defined in "CharacterUtilite.c":
Code:
 int CalcEncOfficerPrice(ref officer)
{
   return makeint(sti(officer.quest.officerprice) * OFF_PRICE_SCALAR * PayScaleFactor());
}
Which means that dialog case is setting NPChar.quest.OfficerPrice by using a function which applies a multiplier to NPChar.quest.OfficerPrice.

Next chance I get to play the game, I'm going to see what happens if I use 'GetBaseOfficerPrice' instead...
 
Good find! What about just removing that 'CalcEncOfficerPrice' line altogether?
I'd assume you then just get the fixed price per character level that is set at the top of the dialog.
 
Presumably there's a reason why he's not allowed a salary based on skills, officer type and the "OPRICE_LEVEL_MULT" variable defined in "InternalSettings.h"?

How about this. At the top, the officer presumably has the "quest.OfficerPrice" attribute otherwise the lines which check it would fail. But as a check:
Code:
if(!CheckAttribute(NPChar, "quest.OfficerPrice")) NPChar.quest.OfficerPrice = GetBaseOfficerPrice(NPChar);
That goes above the check for minimum salary, so if the base price is less than that minimum, "quest.OfficerPrice" is set to the minimum.

And then, one way or another, his salary is set at the top of the dialog so it doesn't need to be set again at case "ShowSkills".
 
Presumably there's a reason why he's not allowed a salary based on skills, officer type and the "OPRICE_LEVEL_MULT" variable defined in "InternalSettings.h"?
I think I just added that have a lower price than non-crew officers; but mainly just to keep it simple.
No real need to keep it as-is though.

At the top, the officer presumably has the "quest.OfficerPrice" attribute otherwise the lines which check it would fail.
Good point! Hmm... I wonder how that could possibly have worked then. o_O

What I do know is that with @Levis' Levelling system, now ALL characters get an officer price assigned straight away.
That at least explains why it doesn't cause errors now.

Now I wonder what would happen if all that pricing code is removed from that dialog file altogether.
It's already taken care of elsewhere anyway... :unsure
 
It probably won't do any harm. On the other hand, it definitely does no harm setting the price here as well, especially if we want these guys to have a different starting salary from other officers. (Though the first time the officer earns a level increase, the levelling system will probably put him on the standard salary scale anyway.)

As for the minimum price check, that doesn't give him a lower price than others. It works out a minimum price based purely on his level and, if his current price is less than that, his price is set to that minimum. In other words, it may give him a higher price than others. ;)
 
I don't think promoting your own crew should be extra-expensive, should it?

If we'd want full control over the price, maybe skip the CheckAttribute.
 
Further alteration to give ex-crewmember officers a different starting salary to other officers is left as an exercise to other modders, and probably another thread. ;)

But putting that line at the top of the dialog and removing the "CalcEncOfficerPrice" line certainly fixes the bug. I can now talk to the crewmember and repeatedly ask him to show how good he is, then tell him to return to work, and he always gives the same price.

One other fix, or rather the same fix applied to another part of the dialog, was necessary. If you ask the crewmember how good he is and note his price, then hire him and look at his stats, his price has gone up. That's because there's another "CalcEncOfficerPrice" line at case "enlist_me". Removing that line means that his actual starting salary when you hire him is the same as the starting salary shown when you ask how good he is.

@Serge Grey: put "permanent_crewmember_dialog.c" into "PROGRAM\DIALOGS" and put "permanent_crewmember_dialog.h" into "PROGRAM\DIALOGS\ENGLISH".
 

Attachments

  • permanent_crewmember_dialog.c
    7.5 KB · Views: 179
  • permanent_crewmember_dialog.h
    1.2 KB · Views: 177
Further alteration to give ex-crewmember officers a different starting salary to other officers is left as an exercise to other modders, and probably another thread. ;)
Their salary is too big. 6653 per month as a starting (non cremember officer from tavern wants ~590), while:
NPchar.quest.OfficerPrice = 3802 and, by the way, min_off_price = 2000. o_O

I do not know where they were defined, but anyway, easiest way is to get price from GetBaseOfficerPrice(NPChar).
If there are not any reasons to calculate crewmember's salary by some other way, i guess, it may be the next (PROGRAM\DIALOGS\permanent_crewmember_dialog.c):
Code:
    NPChar.quest.officertype = OFFIC_TYPE_ABORDAGE;
    NPChar.quest.OfficerPrice = GetBaseOfficerPrice(NPchar)*0.9;
    // if(!CheckAttribute(NPChar, "quest.OfficerPrice")) NPChar.quest.OfficerPrice = GetBaseOfficerPrice(NPChar);
    // int min_off_price = makeint( 1000 * sqrt(sti(NPChar.rank)) );
 
    // if(sti(NPChar.quest.OfficerPrice) < min_off_price) NPChar.quest.OfficerPrice = min_off_price; // PB: Increased salary for better crewmember as officer
0.9 multiplier is to downgrade salary in comparison with other non crewmembers officers.

If it is necessary to take a value from quest.OfficerPrice for any quest situation or a similiar, it needs to change NPChar.quest.OfficerPrice in that place where it was defined. However, in this way, int min_off_price = makeint( 1000 * sqrt(sti(NPChar.rank))) is too big even for a eighth-level ex-crewmember.

If the last way may be the case, @Pieter Boelen, @Grey Roger, can you say me, where i can find the file, in which NPChar.quest.OfficerPrice was defined and for which reason min_off_price is so big?
 
Last edited:
Sorry, I can't confirm this. I tested it again last night, and the only discrepancy I got was the exact opposite - after I hired the crewmember, his salary was 1 lower than that shown previously.
Crewmember for hire:
crewmember_for_hire.jpg

After hiring him as an officer:
crewmember_hired.jpg

@Serge Grey: do you have the latest version of "permanent_crewmember_dialog.c"? Either from post #14 or from the newest installer?

About crewmember officer salary vs. any other officer salary: I don't think there should be a difference. On a pirate ship, if you were to offer a promoted crewmember less money for the same post as an officer hired at random from a tavern, you'd probably receive a free swimming lesson courtesy of the rest of the crew. :walkplank On any naval or merchant ship, officer salaries would be defined by Kings Regulations or company regulations, e.g. this chart showing rank groupings for the purpose of prize money - note the lack of distinction about where the officers were hired. ;) Which means I think I'll get rid of the lines about "min_off_price" - a promoted crewmember shouldn't be getting more than other officers either.
 
Good lesson for me, @Grey Roger.

I implied that in that time when NPchar.quest.OfficerPrice was 3802, preview of the crewmember showed me his salary as 6653, while he wasn't an officer yet. Anyway it (3802) was too big for 8-level crewmember. When he was hired, his salary was still the same. It was with Build 14 (23 March 2018) and permanent_crewmember_dialog.c from post #14.

Maybe you can find it using tip #4 here?
Tutorial - Modding Tips & Tricks
Unfortunately I can't look it up myself right now...
Thank you, @Pieter Boelen.

Installation of the last version of the game didn't resolved the problem. Crewmember's salary depends of difficultly level, but it is still 1700 vs 296 for the officer from the tavern on Landlubber at the start of FreePlay.
 
Last edited:
The problem is these two lines:
Code:
   int min_off_price = makeint( 1000 * sqrt(sti(NPChar.rank)) );
   if(sti(NPChar.quest.OfficerPrice) < min_off_price) NPChar.quest.OfficerPrice = min_off_price;
That makes it a multiple of 1000. As you noticed, random officers in taverns have a starting salary on the order of hundreds, not thousands. Remove those lines so that the officer's salary is whatever was already set (or 'GetBaseOfficerPrice(NPChar)' if for any reason it hasn't already been set).

The result:
Crewmember before and after hiring:
crewmember_for_hire.jpg crewmember_hired.jpg

Random tavern officer:
tavern_officer.jpg

The tavern officer is significantly cheaper, but that's because he's lower level. After using cheatmode to boost his level to the same as the ex-crewmember:
tavern_officer_boosted.jpg

Much closer. It may be that the calculation to raise an officer's salary when he gains a level doesn't quite match the salary of an officer who started at the higher level, and anyway there's a bit of randomisation in the initial salary calculation, so a difference of 745 vs. 750 isn't unreasonable.

The next thing I'm going to do is fiddle the crewmember's "loyality" and "alignment" attributes. These are part of a system whereby officers are randomly assigned alignment "good" or "evil", plus a loyalty rating, which are kept secret from the player. Some sidequests have checks and if you take an action which is deemed "good", then good officers gain loyalty and evil officers lose loyalty; vice versa if the action is regarded as "evil". There's no benefit for having a loyal officer but if his loyalty drops too far then he deserts. The thing about that crewmember is that although in the game he's just a randomly generated guy, the idea is supposed to be that this is someone who's been on your ship for a while, has proven himself loyal and capable, which is why you're rewarding him with a promotion. So, if your reputation is higher than "Bloke" or lower than "Rascal" then set his alignment to "good" or "evil" respectively, and if his "loyality" is less than 5 then set it to 5. (You've been actively working to raise / lower your reputation, so you've been playing as good/evil, and this guy approves.)
 
Back
Top