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

Included in Build Proposed change to "relation" quest check

Grey Roger

Sea Dog
Staff member
Administrator
Storm Modder
One of the conditions defined in "quests_check.c" is "relation". This activates if your relation with a given nation changes to a given status - "Friendly", "Hostile" or "Neutral".

As far as I know, at present I'm the only one using this check. Lucia and Edmundo de la Vega, being daughter and son of a Spanish governor, are patriotic and will only accept your hand in marriage or a post as officer on your ship if you are at peace with Spain. If, having married or hired them, you then turn hostile to Spain, they regard this as a personal betrayal and leave you.

But that condition check uses 'GetNationRelation2Character' to determine your relation to the nation. After some checking, this ends up calling 'GetFlagRMRelation'. So Lucia and Edmundo feel betrayed if you hoist a false enemy flag.

Any objection to changing the check to use 'GetRMRelation' and 'GetRMRelationType' instead, so it looks at your genuine relation to the nation, not your flag's relation?
 
Indeed I do not remember ever seeing this used anywhere.
It is probably stock game code and the stock game did not have false flags anyway.
It makes absolute sense to have it check the actual relations and not the flag relations.

Just to be certain, can you post nations.c?
I thought 'GetNationRelation2MainCharacter' should already be the REAL relations, so I'd like to double-check on that....
 
This is the version included in the 22nd May update. In particular:
Code:
int GetNationRelation2MainCharacter(int iNation)
{
   if (!IsEntity(&worldMap) || GetCurrentFlag() == PERSONAL_NATION) // PB: GetFlagRMRelation for PERSONAL_NATION ends up calling this function again, creating an endless loop!
   {
     return GetRMRelationType(GetRMRelation(GetMainCharacter(), iNation));
   }
   else
   {
     return GetFlagRMRelation(iNation); // PB: Worldmap calls this function from engine!
   }
}

Anyway, I know the quest check triggers if you hoist a false flag because I hoisted a false French flag to enter St. Pierre to conclude the Blacque Family side quest, then wondered why Lucia had disappeared. Spain was still Neutral.
 

Attachments

  • nations.c
    60.8 KB · Views: 336
Indeed I was right, that function does return the actual relation, except when you're on the WorldMap.
I had to make a very ugly change to that function to get the "worldmap follow ships" to take into account your (false) flag.

I imagine that quest update could then indeed trigger if you're on the worldmap with a false hostile flag, which is obviously unintentional.
Using 'GetRMRelationType(GetRMRelation(GetMainCharacter(), iNation))' directly is far safer, so go for it! :onya
 
@Grey Roger: So then the change you propose would be this one, right?
Code:
  case "relation":
   //   i = GetNationRelation2Character(GetNationTypeByID(condition.nation),sti(refCharacter.index));
     i = GetRMRelationType(GetRMRelation(refCharacter, GetNationTypeByID(condition.nation))); // GR
     bTmp = false;
     switch(condition.relation)
     {
       case "Friendly":   bTmp = i==RELATION_FRIEND; break;
       case "Hostile":     bTmp = i==RELATION_ENEMY; break;
       case "Neutral":     bTmp = i==RELATION_NEUTRAL; break;
     }
     return bTmp;
   break;

Are you sure that condition is never used anywhere? If so, I'd propose making these changes too:
Code:
  case "relation":
     return GetRMRelationType(GetRMRelation(refCharacter, sti(condition.nation) )) == sti(condition.relation); // GR
   /*   i = GetNationRelation2Character(GetNationTypeByID(condition.nation),sti(refCharacter.index));
     bTmp = false;
     switch(condition.relation)
     {
       case "Friendly":   bTmp = i==RELATION_FRIEND; break;
       case "Hostile":     bTmp = i==RELATION_ENEMY; break;
       case "Neutral":     bTmp = i==RELATION_NEUTRAL; break;
     }
     return bTmp;*/
   break;

That does mean you should use the nation and relation integer #defines instead of their string IDs.
But I reckon that is good practice anyway and it makes for much cleaner code.
 
@Grey Roger: So then the change you propose would be this one, right?
Code:
  case "relation":
   //   i = GetNationRelation2Character(GetNationTypeByID(condition.nation),sti(refCharacter.index));
     i = GetRMRelationType(GetRMRelation(refCharacter, GetNationTypeByID(condition.nation))); // GR
     bTmp = false;
     switch(condition.relation)
     {
       case "Friendly":   bTmp = i==RELATION_FRIEND; break;
       case "Hostile":     bTmp = i==RELATION_ENEMY; break;
       case "Neutral":     bTmp = i==RELATION_NEUTRAL; break;
     }
     return bTmp;
   break;
Yes, that's it. About the only difference between this and the version I wrote and tested is that I've got the commented out line below the new line. :D

Are you sure that condition is never used anywhere? If so, I'd propose making these changes too:
Code:
  case "relation":
     return GetRMRelationType(GetRMRelation(refCharacter, sti(condition.nation) )) == sti(condition.relation); // GR
   /*   i = GetNationRelation2Character(GetNationTypeByID(condition.nation),sti(refCharacter.index));
     bTmp = false;
     switch(condition.relation)
     {
       case "Friendly":   bTmp = i==RELATION_FRIEND; break;
       case "Hostile":     bTmp = i==RELATION_ENEMY; break;
       case "Neutral":     bTmp = i==RELATION_NEUTRAL; break;
     }
     return bTmp;*/
   break;

That does mean you should use the nation and relation integer #defines instead of their string IDs.
But I reckon that is good practice anyway and it makes for much cleaner code.
I'm not 100% sure that the condition is not used anywhere else. Besides, I've already gone with the first version, it works, Lucia now only gets upset if you're genuinely hostile to Spain, and I have other things to do to "Ardent" rather than rewrite something that works. :p
 
I'm not 100% sure that the condition is not used anywhere else. Besides, I've already gone with the first version, it works, Lucia now only gets upset if you're genuinely hostile to Spain, and I have other things to do to "Ardent" rather than rewrite something that works. :p
I'll defer to your judgement then.
My second version does look cleaner and shorter, but it indeed isn't necessary.
Might as well stick with what works. :yes
 
One reason why I like it as it is now, is that there are only three clearly defined statuses - "Friendly", "Hostile" or "Neutral". I can't see why you'd need higher precision than that, and it could make using the condition trickier if it requires the exact integer rather than the simple label. Lucia wouldn't need to get upset when you became hostile to Spain, she'd need to decide exactly how hostile you are before she decides to leave. xD
 
One reason why I like it as it is now, is that there are only three clearly defined statuses - "Friendly", "Hostile" or "Neutral". I can't see why you'd need higher precision than that, and it could make using the condition trickier if it requires the exact integer rather than the simple label.
My code suggestion does not change that at all. Just instead of typing "Friendly" in the code, you would type RELATION_FRIEND . And instead of typing "Spain", you would use SPAIN .
Those are the ways such references are used most of the time and it is safer for potential future changes to use the global #defines instead of strings that might differ frm file to file.
But really my suggested change only bypasses some superfluous conversions back and forth, but does not change the actual logic behind it.
 
Back
Top