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

New side quest

Grey Roger

Sea Dog
Staff member
Administrator
Storm Modder
I'm working on a little sidequest which I hope people will find amusing. It's based very loosely on a swindle perpetrated in Germany at the turn of the 20th century, and which will require a good deal of artistic licence. (Holland already plays the role of Brandenburg for the purpose of getting a couple of ships into the game. It will do so again for this little story.)

You'll start by meeting a man named Willem Voigt in Philipsburg tavern. (Replace "Willem" with the German "Wilhelm" and look him up on Wikipedia, and you'll find the original story...) He has a cunning plan to rob a governor.
He wants to dress up as a soldier, march into the townhall, pretend to arrest the governor for fraud, confiscate the cashbox as evidence, and get out of there before anyone realises what's happened.

But Voigt is already under suspicion. He's also not especially brave, though he is good-natured and doesn't want to upset anyone unnecessarily.
When you try to leave Philipsburg, a guard arrests him and wants to arrest you as an accomplice. When you claim you know nothing of Voigt's schemes and merely accepted a fare from him to take him to Port Royale, he backs you up. Or, if you try to go down the tunnel to Marigot, Voigt simply refuses to follow you.

This short quest is merely intended to give you the idea of the scam. With Voigt out of the way, it's up to you to do the job yourself.
The real Wilhelm Voigt got his uniform by buying bits of it from various fleamarkets. You'll do it by finding a soldier in any Dutch tavern, getting him drunk, and stealing his uniform. But that's just a common soldier's uniform, whereas you need the uniform of an army kapitein. The tailor will do that, if you have proof that you're entitled to wear a captain's uniform. You can get that from Yedam Kinne, the forger in Bridgetown, provided you haven't already killed him - if you have, I'll have to make alternative arrangements.

Then you'll commandeer a couple of real soldiers to assist you. You go into Kralendijk townhall, arrest the governor, grab the loot, and get out of town.

If you ever return to Kralendijk, you'll be arrested and imprisoned. And then pardoned. The king has read about the whole thing and was highly amused. The real Wilhelm Voigt was also caught, imprisoned, and pardoned by the Kaiser.

The Kapitein of Kralendijk is coming...
 
I need to give the Kralendijk tailor some dialog related to this quest. What is the preferred method - edit the general "tailor_dialog.c/h"which seems to be used by all tailors, or make a specific copy for this one and then edit "PROGRAM\Characters\init\Douwesen.c" to make him use it?
 
I need to give the Kralendijk tailor some dialog related to this quest. What is the preferred method - edit the general "tailor_dialog.c/h"which seems to be used by all tailors, or make a specific copy for this one and then edit "PROGRAM\Characters\init\Douwesen.c" to make him use it?
Probably the best solution would be to use the "two dialogs for one character" method that is also used for governors now.
All quest-specific dialog can be in the individual dialogs, while the generic tailor functionality remains localized in one single file.
That prevents copying existing code, because that becomes very difficult to maintain.

Maybe in this case, you can do it in reverse?
So all tailors would share the same base dialog, but you can give them an inidividual quest dialog in addition.
 
There are already "tailor_dialog.c/h" and "tailor.c/h". The latter is the "Dialog.Filename.Groupdialog". But whereas the "Dialog.Filename.Groupdialog" for governors is the one which deals with generic governor stuff, for tailors it's the one which deals with @Levis' fetch quest stuff - tailors seem to have them reversed. (So, apparently, do blacksmiths and priests, and in both cases it's also the group file which handles @Levis quests.)
 
There are already "tailor_dialog.c/h" and "tailor.c/h". The latter is the "Dialog.Filename.Groupdialog". But whereas the "Dialog.Filename.Groupdialog" for governors is the one which deals with generic governor stuff, for tailors it's the one which deals with @Levis' fetch quest stuff - tailors seem to have them reversed. (So, apparently, do blacksmiths and priests, and in both cases it's also the group file which handles @Levis quests.)
Indeed it can work either way.

Of course since both the tailor code AND the Fetch Quest functionality are generic, it would make the most sense for all of that to be in the same file.
I think the only reason why it isn't, is because gunsmiths get a different GroupDialog.

In theory, I think you can create a second, additional GroupDialog purely for your own purposes.

Alternatively, doesn't "tailor.c" contain a lot of actual functions? If so, move those functions to, say, PROGRAM\Models\models.c .
That leaves only dialog code in the actual dialog file.
Then if you make a Douwesen-only copy of that file, it doesn't matter so much for maintainability.
At least then all the actual code is read from one single place anyway. Maybe that would be easiest?
 
Indeed it can work either way.

Of course since both the tailor code AND the Fetch Quest functionality are generic, it would make the most sense for all of that to be in the same file.
I think the only reason why it isn't, is because gunsmiths get a different GroupDialog.
Yes, "Gunsmith_fetch.c". Guess what that does. ;)

Alternatively, doesn't "tailor.c" contain a lot of actual functions? If so, move those functions to, say, PROGRAM\Models\models.c .
That leaves only dialog code in the actual dialog file.
Then if you make a Douwesen-only copy of that file, it doesn't matter so much for maintainability.
At least then all the actual code is read from one single place anyway. Maybe that would be easiest?
It is "tailor_dialog.c" which contains actual functions. "tailor.c" is just fetch-quest stuff. I'm becoming inclined to add my bit to "tailor.c/h", with a check 'if PChar.location == "Douwesen_TailorsShop"' to make sure it only activates if you're in the right place.
 
Yes, "Gunsmith_fetch.c". Guess what that does. ;)
Almost the same, but slightly different. :wp

It is "tailor_dialog.c" which contains actual functions. "tailor.c" is just fetch-quest stuff.
Ah, then I got my filenames mixed up. Move those functions from "tailor_dialog.c" to models.c, then copy "tailor_dialog.c" for your specific guy.

I'm becoming inclined to add my bit to "tailor.c/h", with a check 'if PChar.location == "Douwesen_TailorsShop"' to make sure it only activates if you're in the right place.
Not the cleanest solution, but should work.
There are so many messy solutions already implemented and so few people doing active modding these days, so skipping to an easy solution might indeed be wise.
 
Another problem with cleaning the functions out of "tailor_dialog.c" and then making a town-specific version is that there's also a lot of code from @El_Rapido to do general tailor-specific cheaty stuff such as buy the pirate collection, reset character or reset perks. If you're trying for easy maintainability, we're still better off having one general tailor dialog. Then I put my quest stuff into it with the check that you're in the right place. (I already had to do something similar in "Ardent", to "Fadrique Castillo_dialog.c". Fadrique Castillo is the tavern keeper in Havana, but the same dialog file is also used by Valerio Xalmiento in Cartagena, and he's the one I needed for the convoy mission. So "Fadrique Castillo_dialog.c" checks if you're in Cartagena tavern before allowing the storyline dialog.)

"tailor.c" is already used for quest purposes. I may as well use it for mine as well. :D
 
Another problem with cleaning the functions out of "tailor_dialog.c" and then making a town-specific version is that there's also a lot of code from @El_Rapido to do general tailor-specific cheaty stuff such as buy the pirate collection, reset character or reset perks. If you're trying for easy maintainability, we're still better off having one general tailor dialog.
That El Rapido stuff is in the dialog code though, not in the functions, right?

we're still better off having one general tailor dialog. Then I put my quest stuff into it with the check that you're in the right place. (I already had to do something similar in "Ardent", to "Fadrique Castillo_dialog.c". Fadrique Castillo is the tavern keeper in Havana, but the same dialog file is also used by Valerio Xalmiento in Cartagena, and he's the one I needed for the convoy mission. So "Fadrique Castillo_dialog.c" checks if you're in Cartagena tavern before allowing the storyline dialog.)
In the end, the ultimate goal is to use "whatever works". :razz
 
That El Rapido stuff is in the dialog code though, not in the functions, right?
Exactly. So if the intention is to make it easy to maintain the contents of the dialog file, whether it's the functions or El Rapido's dialog stuff, then making a separate copy of the dialog file is probably not a good idea even if the functions are removed.
In the end, the ultimate goal is to use "whatever works". :razz
Fair enough. I'll do my work in "tailor.c/h", and make it conditional on you being in the Kralendijk tailor shop as opposed to any other tailor shop.
 
@Pieter Boelen: is there a way to increase your fame? Partly for this sidequest, and partly for Hornblower, who is apparently famous judging by some dialogs and completely unknown according to his actual fame rating.
 
@Pieter Boelen: is there a way to increase your fame? Partly for this sidequest, and partly for Hornblower, who is apparently famous judging by some dialogs and completely unknown according to his actual fame rating.
Fame is calculated through a complex formula that I would have wanted to modify ages ago, but never had time for.
Now I don't know if and when that might happen, so I'll focus my answer on tweaking the existing system instead.

The easiest way to increase Fame is, by far, to just give the player extra Wealth.
Other factors are Privateer/Navy rank (if I recall?) and definitely whether you're married or not.
Maybe we should add an extra character attribute where you can boost player fame for quest purposes without doing any of that.

Can you upload CharacterUtilite.c? I think the relevant code is in there.
 
Here it is...
This is the relevant function:
Code:
//returns fame. If iNation == -1, interprets this as getting fame for general purposes (i.e. crew)
float GetFame(ref pchar, int iNation)
{
 bool crew = (iNation == -1);
 int rank = sti(pchar.rank);
 int i;
 int PerkIron;
 int PerkChar;
 int PerkWC;
 int skillLead;
 int skillLuck;
 float nrank = 1.0;
 int numnat;
 if(crew)
 {
  PerkIron  = GetOfficersPerkUsing(pchar,"IronWill");
  //PerkChar  = GetOfficersPerkUsing(pchar,"Charisma"); //to be added, prereq iron will //Removed by Levis untill is't well done
  //PerkWC    = GetOfficersPerkUsing(pchar,"WitCharm"); //to be added, prereq charisma //Removed by Levis untill is't well done
  skillLead = GetShipSkill(pchar,SKILL_LEADERSHIP);
  skillLuck = GetShipSkill(pchar,SKILL_SNEAK);
  nrank = 0;
  numnat = 0;
  for(i = 0; i < NATIONS_QUANTITY; i++)
  {
   if(GetRank(pchar, i))
   {
    numnat++;
    nrank += makefloat(GetRank(pchar, i))/24.0;
   }
  }
  if(numnat>0) { nrank = (nrank / makefloat(numnat)) * sqrt(numnat); }
  else { nrank = 0; }
 }
 else
 {
  PerkIron  = CheckPerkForSingleCharacter(pchar,"IronWill");
  //PerkChar  = CheckPerkForSingleCharacter(pchar,"Charisma"); //to be added, prereq iron will //Removed by Levis untill is't well done
  //PerkWC    = CheckPerkForSingleCharacter(pchar,"WitCharm"); //to be added, prereq charisma //Removed by Levis untill is't well done
  skillLead = CalcCharacterSkill(pchar,SKILL_LEADERSHIP);
  skillLuck = CalcCharacterSkill(pchar,SKILL_SNEAK);
  if(iNation == PIRATE) // new code 04-09-06, so if querying pirate fame you get extra for having ranks.
  {
   for(i = 0; i < NATIONS_QUANTITY; i++)
   {
    if(GetRank(pchar, i))
    {
     numnat++;
     nrank += makefloat(GetRank(pchar, i))/24.0;
    }
   }
   if(numnat>0) { nrank = (nrank / makefloat(numnat)) * sqrt(numnat); }
   else { nrank = 0; }
  }
  else
  {
   nrank = makefloat(GetRank(pchar, iNation))/12.0;
  }
 }

 float lastcsr = 1.0;
 if(CheckAttribute(pchar,"Crewstatus.lastcsr")) lastcsr = stf(pchar.CrewStatus.lastcsr);
 else pchar.CrewStatus.lastcsr = lastcsr;
 //unclamp lastcsr
 if(lastcsr > 1.0) lastcsr = 1.0/(2.0-lastcsr);
 //mult csr
 if(lastcsr > 1) lastcsr = 1.0 + (lastcsr-1.0) * FAME_CSR_SCALE;
 //else lastcsr = 1 - ((1 - lastcsr) * FAME_CSR_SCALE);

 //clamp csr to min/max
 if(lastcsr < FAME_CSR_MIN) lastcsr = FAME_CSR_MIN;
 if(lastcsr > FAME_CSR_MAX) lastcsr = FAME_CSR_MAX;

 int gold = GetCharacterWealth(pchar);
 int land = GetCharacterLand(pchar);

 float perkscale = 0.0;
 if(PerkIron)
 {
  perkscale = 0.25;
   //Removed by Levis until it's well done
  /*if(PerkChar)
  {
   perkscale = 0.5;
   if(PerkWC) { perkscale = 1.0; }
  }*/
 }

 float points = 1.0;
 //calc points; 200 good for lvl10 char with 5/5, 300k gp, 1k acres
 points *= (1.0 + skillLead/10.0 + rand(skillLuck)/20.0 + perkscale);
 points *= sqrt(rank)/2.0;
 points *= (1.0 + nrank);
 points *= (sqrt(makefloat(gold))/20.0 + floatret(!crew,3.0*sqrt(pow(land/100.0,1.25)),0));
 if(crew) points *= lastcsr;
 if(iNation == PIRATE) { points *= (FAME_PIRNATION_CSR_BASE+ lastcsr * FAME_PIRNATION_CSR_SCALAR); } // NK 04-09-06 so if querying fame with nation pirate, csr counts.
 points *= FAME_SCALAR;
 if(crew) points = 0.1 + sqrt(sqrt(pow(points,1.5))) / 10.0;
 return points;
}
Maybe add an extra line like this:
Code:
 if(crew) points = 0.1 + sqrt(sqrt(pow(points,1.5))) / 10.0;
    if (CheckAttribute(pchar,"extra_fame")) points += stf(pchar.extra_fame); // PB: Add extra fame for quest purposes
 return points;
}
Would that help you?
 
It works, though that's part of 'GetFame', which calculates your fame as seen by a specific nation. The next function down, 'GetScore', is the one which calculates your fame as it is used to display your rating, e.g. "Unknown", "Acknowledged" etc. On the other hand, I rather like the idea of being able to alter your fame at a nation-specific level as that, presumably, is what is used to calculate the chances of a ship or fort recognising you. So:
Code:
    if(crew) points = 0.1 + sqrt(sqrt(pow(points,1.5))) / 10.0;
   string fame_name = "extra_fame" + iNation
   if (CheckAttribute(pchar, fame_name)) points += (stf(pchar.(fame_name))*FAME_SCALAR); // PB: Add extra fame for quest purposes
   return points;
And then, to use it:
Code:
           string fame_name = "extra_fame" + HOLLAND
           x = stf(GetAttribute(PChar, fame_name));
           if (x < 0) PChar.(fame_name) = 50.0;
           else PChar.(fame_name) = x + 50.0;
The extra fame from Holland still counts towards your rating. A bit of trial and error showed that boosting it by 50.0 is enough to get you from "Unknown" to "Barely Known", while the comment in 'GetFame' suggests that 200 is good for a level10 char with 300k gold and 1000 acres, and the sidequest isn't supposed to make you quite as famous as that!
 
On the other hand, I rather like the idea of being able to alter your fame at a nation-specific level as that, presumably, is what is used to calculate the chances of a ship or fort recognising you.
Have a look at the "chance detect false flag" function. I don't think that one is nation-specific.
If it isn't, perhaps that's something worth changing.

And then, to use it:
Sounds cool! :onya
 
Back
Top