• 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!

WIP Improve the Crewmembers on Shore Mod

I need some help with this. Can someone tell me what the following things mean? They're just fragments of code, not in any particular order.

Code:
          MyFlag = GetCurrentFlag();
           if(GetFlagRMRelation(sti(Npchar.nation)) <= REL_WAR && rand(10)>8)

Code:
              if(rand(makeint(pchar.skill.leadership))>5)

Code:
            if(MyFlag == PIRATE && rand(10)>8)

The 2nd one is particularly odd. It would seem like it's meant to trigger what's beneath it if you have a leadership higher than 5, but the way the dialogue's been written would suggest that lower than 5 would make more sense. Unless high leadership is associated with being able to conceal your identity, rather than being easy to recognise. Which of the two should it be?
 
1st. Checks if you are flying a hostile FLAG, but doesn't care about your ACTUAL nation relations.
If not used well, this could be very annoying as you may be treated as an enemy when you're not.

2nd. Takes a random number between 0 and your leadership skill, then checks if that is above 5.
This would NEVER happen as long as your leadership is 5 or less and would give a 50/50 chance at 10 leadership.
If it is meant to be something about "being able to conceal your identity", using GetChanceDetectFalseFlag() in some way would make much more sense.

3rd. If you're flying a pirate flag, that gives a 20% chance of.... something?
 
1st. Checks if you are flying a hostile FLAG, but doesn't care about your ACTUAL nation relations.
If not used well, this could be very annoying as you may be treated as an enemy when you're not.

2nd. Takes a random number between 0 and your leadership skill, then checks if that is above 5.
This would NEVER happen as long as your leadership is 5 or less and would give a 50/50 chance at 10 leadership.
If it is meant to be something about "being able to conceal your identity", using GetChanceDetectFalseFlag() in some way would make much more sense.

3rd. If you're flying a pirate flag, that gives a 20% chance of.... something?

1: That should be okay then, for this particular dialogue, since all nations are hostile to pirates. I'll keep it in mind for the other ones though.

2: Ahh, i see. The thing is, that whole section checks your flag AND your leadership, to see if you'd be recognised by your face anyway despite having succesfully landed in port under a false flag.

3: That something was not that important, i just wanted to know what that line did. :)

What's this though?

Code:
            if(myflag == MakeInt(Npchar.nation))

Code:
        if (frnd() < GetChanceDetectFalseFlag())
 
Last edited:
This bit also confuses me:

Code:
          int MyNation = PERSONAL_NATION;
           int MyFlag = GetCurrentFlag();
           string nationme, nationhim;
           if(GetRMRelation(PChar, sti(Npchar.nation)) <= REL_WAR)
           {
             if(MyFlag == PIRATE && rand(10)>8)
             {
               Dialog.Text = DLG_TEXT[3];
               Link.l1 = DLG_TEXT[4];
               Link.l1.go = "exit";
               LAi_group_SetRelation("random_pirates_group", LAI_GROUP_PLAYER, LAI_GROUP_ENEMY);
             }

At his point i might as well post the whole thing here, but oh well. Is this for checking if you were trying to sail into a pirate port, under the pirate flag, while actually at war with the pirates?
 
1
Code:
            if(myflag == MakeInt(Npchar.nation))
Checks if the flag you are currently flying is the same as the nation of the character you are talking to.
Then the character should be friendly, I imagine?

Code:
        if (frnd() < GetChanceDetectFalseFlag())
frnd() returns a random 'float' value between 0.0 and 1.0 .
GetChanceDetectFalseFlag() returns a fixed value between 0.0 and 1.0 depending on player skills and fame.
This is the same functionality that is used at sea to check if your false flag has been recognized.

This bit also confuses me:

Code:
          int MyNation = PERSONAL_NATION;
           int MyFlag = GetCurrentFlag();
           string nationme, nationhim;
           if(GetRMRelation(PChar, sti(Npchar.nation)) <= REL_WAR)
           {
             if(MyFlag == PIRATE && rand(10)>8)
             {
               Dialog.Text = DLG_TEXT[3];
               Link.l1 = DLG_TEXT[4];
               Link.l1.go = "exit";
               LAi_group_SetRelation("random_pirates_group", LAI_GROUP_PLAYER, LAI_GROUP_ENEMY);
             }

At his point i might as well post the whole thing here, but oh well. Is this for checking if you were trying to sail into a pirate port, under the pirate flag, while actually at war with the pirates?
If you personally (PChar) are at war with the nation of that character (NPChar).
Then if you are flying a pirate flag and with a 20% chance at the following....

Actually, I had an alternate idea to the above.... what about using:
Code:
if(TradeCheck(PChar, NPChar, true))
That is quite a fancy function that is also used to determine if merchants/shipyard owners/tavern keepers are willing to do business with you.
See here for the details:
Code:
//find if merch will allow char to trade, based on char's RMRel with merch's
//nation, and char's rep.
bool TradeCheck(ref char, ref merch, bool first)
{
   if (LAi_IsCapturedLocation) return true; // KK
   int pNation = sti(char.nation);
   int mNation = sti(merch.nation);
   int rep = sti(char.reputation);
   float rel = 0.0;
   // PURSEON -->
   if(first)
   {
     rel = GetRMRelation(GetMainCharacter(), mNation);
     if(GetNationRelation(pNation, mNation) < RELATION_ENEMY && pNation != PERSONAL_NATION)     // your flag is NOT hostile to the merchant
     {
       if(rel <= REL_WAR)                                     // but you are flying a false flag!
       {
         if (frnd() < GetChanceDetectFalseFlag() || CheckAttribute(merch,"FalseFlagDetect"))   // checks if the merchant will believe you
         {
           merch.FalseFlagDetect = true;                           // you have been caught and the merchant won't be so trusting next time
         }
         else
         {
           rel = REL_AFTERATTACK;                               // believes you, but... still takes into account your reputation!
         }
       }
       else
       {
         DeleteAttribute(merch, "FalseFlagDetect");                       // you are actually friendly
       }
     }
     else
     {
       if(rel <= REL_WAR)                                     // are you at war or not?
       {
         merch.FalseFlagDetect = true;                             // merchant KNOWS you are an enemy and remembers this
       }
       else
       {
         DeleteAttribute(merch, "FalseFlagDetect");                       // you are actually friendly
       }
     }
     merch.traderelation = rel;
   }
   else
   {
     rel = sti(merch.traderelation); // PB: Use the SAME relation for the WHOLE dialog
   }
   // <--PURSEON
   //find loc
   bool strengthcomp;
   int locIdx = FindLoadedLocation();
   if(locIdx<0) return true;
   if( !CheckAttribute(&Locations[locIdx],"townsack") ) return true;

   // PB: Recoded Checks -->

   // -- Town fight strength vs. squadron fight strength --

   // Store/shipyard owner can be intimidated if player has three times more crew than the town has troops
   int ttroops = GetTownNumTroops(Locations[locIdx].townsack);
   int ptroops = GetSquadronCrewQuantity(char);

   if(ptroops > ttroops * 3) strengthcomp = true;

   // -- Actual Checks --

   if(mNation == PIRATE)
   {
     // Pirates don't do business with the navy
     if(ProfessionalNavyNation() == UNKNOWN_NATION)
     {
       // If you aren't hostile with the pirates, they'll always accept you
       if(rel  >  REL_WAR)                           return true;
       // If you have no loyalties to any one nation, they'll accept you too
       if(GetLetterOfMarqueQuantity() == 0)                 return true;
     }
   }
   else
   {
     // If you are Hostile with their nation, but you are a Hero
     if(rel <=  REL_WAR  && rep >= TRADEREP_ALL  )   return true;

     // If their nation is less than Hostile to you and you are Matey or better
     if(rel  >  REL_WAR  && rep >= TRADEREP_WAR  )   return true;

     // If their nation is better than Wary and you are Neutral or better
     if(rel  >= REL_AFTERATTACK && rep >= TRADEREP_NEUTRAL  )   return true;

     // If their nation is better than Neutral, you are Swindler or better and can intimidate them
     if(rel  >= REL_AMNESTY  && rep >= TRADEREP_STRENGTH && strengthcomp)   return true;

     // You have a Letter of Marque with the nation and have been promoted at least once
     if(GetRank(GetMainCharacter(), mNation) > 0  )   return true;

     // You are friendly to the pirates, flying a pirate flag and the town is tolerant of pirates
     if(CheckForPirateException(merch)  )   return true;
   }

   // PB: Recoded Checks <--

//MAXIMUS -[we are here already, why we can't complete our mission?]->
   if(first && CheckQuestAttribute("generate_trade_quest_progress", "begin") || CheckQuestAttribute("generate_trade_quest_progress",  "failed"))
   {
     if(char.quest.generate_trade_quest_progress.iTradeColony == GetCurrentTownID()) return true;
   }
//MAXIMUS <-[we are here already, why we can't complete our mission?]-
   return false;
}
I rewrote that at some point to make more sense and added quite a lot of explanatory comments to show what it does and why.
If you reckon that function works in a way that makes sense here as well, it might make for a simpler solution.
 
Actually, I had an alternate idea to the above.... what about using:
Code:
if(TradeCheck(PChar, NPChar, true))
That is quite a fancy function that is also used to determine if merchants/shipyard owners/tavern keepers are willing to do business with you.
See here for the details:
Code:
//find if merch will allow char to trade, based on char's RMRel with merch's
//nation, and char's rep.
bool TradeCheck(ref char, ref merch, bool first)
{
   if (LAi_IsCapturedLocation) return true; // KK
   int pNation = sti(char.nation);
   int mNation = sti(merch.nation);
   int rep = sti(char.reputation);
   float rel = 0.0;
   // PURSEON -->
   if(first)
   {
     rel = GetRMRelation(GetMainCharacter(), mNation);
     if(GetNationRelation(pNation, mNation) < RELATION_ENEMY && pNation != PERSONAL_NATION)     // your flag is NOT hostile to the merchant
     {
       if(rel <= REL_WAR)                                     // but you are flying a false flag!
       {
         if (frnd() < GetChanceDetectFalseFlag() || CheckAttribute(merch,"FalseFlagDetect"))   // checks if the merchant will believe you
         {
           merch.FalseFlagDetect = true;                           // you have been caught and the merchant won't be so trusting next time
         }
         else
         {
           rel = REL_AFTERATTACK;                               // believes you, but... still takes into account your reputation!
         }
       }
       else
       {
         DeleteAttribute(merch, "FalseFlagDetect");                       // you are actually friendly
       }
     }
     else
     {
       if(rel <= REL_WAR)                                     // are you at war or not?
       {
         merch.FalseFlagDetect = true;                             // merchant KNOWS you are an enemy and remembers this
       }
       else
       {
         DeleteAttribute(merch, "FalseFlagDetect");                       // you are actually friendly
       }
     }
     merch.traderelation = rel;
   }
   else
   {
     rel = sti(merch.traderelation); // PB: Use the SAME relation for the WHOLE dialog
   }
   // <--PURSEON
   //find loc
   bool strengthcomp;
   int locIdx = FindLoadedLocation();
   if(locIdx<0) return true;
   if( !CheckAttribute(&Locations[locIdx],"townsack") ) return true;

   // PB: Recoded Checks -->

   // -- Town fight strength vs. squadron fight strength --

   // Store/shipyard owner can be intimidated if player has three times more crew than the town has troops
   int ttroops = GetTownNumTroops(Locations[locIdx].townsack);
   int ptroops = GetSquadronCrewQuantity(char);

   if(ptroops > ttroops * 3) strengthcomp = true;

   // -- Actual Checks --

   if(mNation == PIRATE)
   {
     // Pirates don't do business with the navy
     if(ProfessionalNavyNation() == UNKNOWN_NATION)
     {
       // If you aren't hostile with the pirates, they'll always accept you
       if(rel  >  REL_WAR)                           return true;
       // If you have no loyalties to any one nation, they'll accept you too
       if(GetLetterOfMarqueQuantity() == 0)                 return true;
     }
   }
   else
   {
     // If you are Hostile with their nation, but you are a Hero
     if(rel <=  REL_WAR  && rep >= TRADEREP_ALL  )   return true;

     // If their nation is less than Hostile to you and you are Matey or better
     if(rel  >  REL_WAR  && rep >= TRADEREP_WAR  )   return true;

     // If their nation is better than Wary and you are Neutral or better
     if(rel  >= REL_AFTERATTACK && rep >= TRADEREP_NEUTRAL  )   return true;

     // If their nation is better than Neutral, you are Swindler or better and can intimidate them
     if(rel  >= REL_AMNESTY  && rep >= TRADEREP_STRENGTH && strengthcomp)   return true;

     // You have a Letter of Marque with the nation and have been promoted at least once
     if(GetRank(GetMainCharacter(), mNation) > 0  )   return true;

     // You are friendly to the pirates, flying a pirate flag and the town is tolerant of pirates
     if(CheckForPirateException(merch)  )   return true;
   }

   // PB: Recoded Checks <--

//MAXIMUS -[we are here already, why we can't complete our mission?]->
   if(first && CheckQuestAttribute("generate_trade_quest_progress", "begin") || CheckQuestAttribute("generate_trade_quest_progress",  "failed"))
   {
     if(char.quest.generate_trade_quest_progress.iTradeColony == GetCurrentTownID()) return true;
   }
//MAXIMUS <-[we are here already, why we can't complete our mission?]-
   return false;
}
I rewrote that at some point to make more sense and added quite a lot of explanatory comments to show what it does and why.
If you reckon that function works in a way that makes sense here as well, it might make for a simpler solution.

I'm not sure. The way the dialogue for the patrols is currently written means that you get different lines based on wether your flag is involved or not, and how. What the code above could be used for is a yes/no on wether a patrol will attack you, reducing the total patrol dialogue to about 4 lines, but i'm not sure if that's better, since that skips out on all the other dialogue we currently have. The main advantage of the code is that it considers the player's reputation and crew strength, which the patrol dialogue currently does not do. I suppose it's possible to copy some parts of the above code into the patrol dialogue to add those features though. It's difficult to say what the best idea is here, especially since some of the patrols are, in fact, pirates.

The random pirates and sailors are done though. Those were the easy ones. The soldier patrols are next.
 
I'm not sure. The way the dialogue for the patrols is currently written means that you get different lines based on wether your flag is involved or not, and how. What the code above could be used for is a yes/no on wether a patrol will attack you, reducing the total patrol dialogue to about 4 lines, but i'm not sure if that's better, since that skips out on all the other dialogue we currently have.
Doing it as per my suggestion DOES indeed substantially simplify it; that is very true.

It's difficult to say what the best idea is here, especially since some of the patrols are, in fact, pirates.
That TradeCheck function does also does something similar, but quite different, when you're dealing with pirates.
They don't care about your nation relations, but DO prefer if you have no LoMs. :cheeky
 
@Pieter Boelen shouldn't the check for leadership use one of the skillfunctions instead or taking it from the character attribute itself?
 
That TradeCheck function does also does something similar, but quite different, when you're dealing with pirates.
They don't care about your nation relations, but DO prefer if you have no LoMs. :cheeky

Yeah, i saw that. It's just that the nuances would be gone if we use it. I like the promise of simplicity, but the patrol dialogue is really quite a nice bit of AI that you usually don't see in videogames. I think i'll leave it like this, once it's fixed.
 
Yeah, i saw that. It's just that the nuances would be gone if we use it. I like the promise of simplicity, but the patrol dialogue is really quite a nice bit of AI that you usually don't see in videogames. I think i'll leave it like this, once the current stuff's fixed.
Fine by me. :doff

Do i need to adjust something? Just say the line and i'll paste it in.
IF you need to check the player leadership skills, I'd recommend using this:
Code:
if(rand(CalcCharacterSkill(pchar, SKILL_LEADERSHIP))>5)
But I think there should be no need for that check in the first place; something based on this one would probably be better:
Code:
if (frnd() < GetChanceDetectFalseFlag())
May depend on context though.
 
May depend on context though.

The context is usually that the dialogue checks for the false flag first and THEN checks if you're so famous that it won't matter how stealthily you snuck into port. Sometimes there's also different dialogue for when you can hire crew; they'll ask for a job either way, but they'll say something different at high leadership. It's purely a roleplaying thing in that case. I'll adjust it.
 
The context is usually that the dialogue checks for the false flag first and THEN checks if you're so famous that it won't matter how stealthily you snuck into port. Sometimes there's also different dialogue for when you can hire crew; they'll ask for a job either way, but they'll say something different at high leadership. It's purely a roleplaying thing in that case. I'll adjust it.
I believe things like how famous you are etc are already taken into account with the falseflag detection
 
I believe things like how famous you are etc are already taken into account with the falseflag detection

If that detection continues on land, i could remove the check for leadership. In fact, that would mean the whol dialogue tree needs to be rewritten.
 
The context is usually that the dialogue checks for the false flag first and THEN checks if you're so famous that it won't matter how stealthily you snuck into port.
The false flag detection chance function already includes an actual fame check,
because I figured back in a grey and distant past that if you're famous, you won't be able to get away with a false flag so easily.
So I don't think there should be an extra fame check afterwards, since that would be doing something similar twice....
 
If that detection continues on land, i could remove the check for leadership. In fact, that would mean the whol dialogue tree needs to be rewritten.
It does if you use it. ;)

If you're interested, this is exactly how that function works:
Code:
float GetChanceDetectFalseFlag()
{
   // original code -->
   //   float rank = GetRankFromPoints(GetScore(GetMainCharacter()));
   //   return CHANCE_DETECT_FALSE_FLAG_BASE+(CHANCE_DETECT_FALSE_FLAG_MAX-CHANCE_DETECT_FALSE_FLAG_BASE)*rank/MAX_RANK;
   // original code <--

   // PB -->
   if (iForceDetectionFalseFlag ==  1)   return 1.0;
   if (iForceDetectionFalseFlag == -1)   return 0.0;
   // PB <--

   // LDH -->
   ref mchr = GetMainCharacter(); // KK
   float score  = GetScore(mchr); // KK
   float rank  = GetRankFromPoints(score);
   int  sneak  = CalcCharacterSkill(mchr, SKILL_SNEAK);
   int difficulty = GetDifficulty();
   float chance = rank/MAX_RANK * (11.0-sneak)/10.0;
   chance = chance * difficulty/2.0;     // 0.5, 1.0, 1.5, 2.0
   if(IsCharacterPerkOn(mchr, "Disguiser")) chance = chance * 0.9;
   //   chance = chance * (difficulty+1)/3.0;     // alternate difficulty calculation 0.67, 1,0, 1.33, 1.67
   chance = fclamp(CHANCE_DETECT_FALSE_FLAG_BASE, CHANCE_DETECT_FALSE_FLAG_MAX, chance); // PURSEON: so chance doesn't go over min/max
   //   LogIt("False Flag Detection - Score: " + score + ", rank: " + rank + ", Sneak: " + sneak + ", Chance: " + chance*100.0 + "%"); // for testing
   //   LogIt("The chance of your false flag being detected is " + chance*100.0 + "%");   // Tell the player, it might get him used to looking for it.
   return chance;
   // LDH <--
}
 
The false flag detection chance function already includes an actual fame check,
because I figured back in a grey and distant past that if you're famous, you won't be able to get away with a false flag so easily.
So I don't think there should be an extra fame check afterwards, since that would be doing something similar twice....

Yeah... that actually means i need to rewrite the entire dialogue, since a significant chucnk of it was written with those additional fame checks in mind.
 
Yeah... that actually means i need to rewrite the entire dialogue, since a significant chucnk of it was written with those additional fame checks in mind.
For extra details, see my post above. You probably posted at the same time I did. ;)
 
Back
Top