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

Tweaking the Coastraiders Mod: Code help needed

jmv575

Landlubber
Storm Modder
Here is the code for the Coastraiders mod by (I believe) CouchCaptainCharles:
<!--c1--><div class='codetop'>CODE</div><div class='codemain'><!--ec1-->// ccc CR ->

void SetCoastTraffic(string islandstr)

{

    ref Pchar, CurIsland, cr;

    string chrstr;

    int crnation;

    string sFantomType;

    Pchar = GetMainCharacter();

    int i = 1;

    int j;

    CurIsland = GetIslandByIndex(FindIsland(islandstr));    

    chrstr = "Cr" + islandstr;



    for( j = 1; j <7; j++)    //Loop to reset relation BEFORE groupcreation

    {

 cr = CharacterFromID(chrstr + j );

 SetCharacterRelationBoth(sti(cr.index), GetMainCharacterIndex(), RELATION_NEUTRAL);

    }



    while(i < 6-(REDUCE_CR*2 + (sti(CurIsland.smuggling_nation) == PIRATE)*2))  // 1st loop to create 3 groups for 2 ships each, NK to reduce at pirate islands

    {

 string crg = chrstr + i;

 Group_DeleteGroup(crg);    //to clear for SeaLogin

 string pos = "Quest_Ship_"  + (1 + rand(16));      //random position



 Group_CreateGroup(crg);

 Group_SetGroupCommander(crg, crg);

 Group_SetAddress(crg, islandstr, "Quest_Ships", pos);

 if (rand(100) < COASTRAIDER_CHANCE)

 {

     crnation= PIRATE;

 }

 else

 {

     crnation =  sti(CurIsland.smuggling_nation);

     // crg is string, not object - crg.nation = crnation;      //nation for group

     if (GetRMRelationType(GetRMRelation(GetMainCharacter(),crnation))) // NK change to use RM

     {

   Group_SetTaskRunAway(crg);

   Group_LockTask(crg);

     }

     else

     {

   Group_SetTaskMove(crg, 10000.0, 10000.0);

     }

 }



 for( j = 0; j <2; j++)    // 2nd loop to create 2 ships for each group

 {

     cr = CharacterFromID(chrstr + (i+j));

     cr.nation    = crnation;      //nation for character

     SetRandomNameToCharacter(cr);



     if (crnation== PIRATE)

     {

   cr.quest.officertype = OFFIC_TYPE_CAPPIRATE;

   sFantomType = "pirate";

     }

     else

     {

   cr.quest.officertype = OFFIC_TYPE_CAPMERCHANT;

   sFantomType = "trade";

     }

     cr.FantomType = sFantomType;

     LAi_Create_Officer(0, cr);

     //cr.rank = makeint(Pchar.rank) + Rand(5);      //sets NEW rank! // NK, disabled, leads to weird XP bug...

     int skip = -10 + sti(Pchar.rank) + GetDifficulty()*2;

     if(skip > 30) skip = 30;



     int crship = skip + Rand(70 + GetDifficulty()*5) + Rand(70 + GetDifficulty()*5);  //select shiptype

     if (crship>150) crship = 162 + Rand(30);

     if(crship < 0) crship = 0;

     while(true)

     {

   if(crship < SHIP_TYPES_QUANTITY)

   {

       if(sti(ShipsTypes[crship].CanEncounter) && ShipsTypes[crship].id != "BlackPearl")

       {

     if(crnation != PIRATE) { break; }

     if(sti(ShipsTypes[crship].class) >= MAXPIRATECLASS) { break; }

       }

   }

   crship = skip + Rand(70 + GetDifficulty()*5) + Rand(70 + GetDifficulty()*5);  //select shiptype

   if (crship>150) crship = 162 + Rand(30);

   if(crship < 0) crship = 0;

     }

     /*int crship = makeint(cr.rank)*10 + 20 -Rand(30);  //select shiptype

     if (crship>167) crship = makeint(170+Rand(15) );*/

     Ship_CreateForCharacter(cr, crship, "Coaster")



   //equip ship

     Ship_SetFantomData(cr);

     Fantom_SetCannons(cr, sFantomType);

     Fantom_SetBalls(cr, sFantomType);

     Fantom_SetSails(cr, sFantomType);

     Fantom_SetGoods(cr, sFantomType);

     Fantom_SetRandomMoney(cr, sFantomType);

     

     SetRandomNameToShip(cr);



     if (crnation== PIRATE)

     {

   cr.perks.list.ShipSpeedUp = true;

   cr.Ship.crew.quantity = MakeInt(GetMaxCrewQuantity(cr));

     }

     SetCharacterRelationBoth(sti(cr.index), GetMainCharacterIndex(), GetRMRelationType(GetRMRelation(GetMainCharacter(), sti(cr.nation)))); // NK set base relation to avoid gray icon

     string crgm = chrstr + (i +j);    //add to group

     Group_addCharacter(crg, crgm);



     // NK to convert shipname to nice string

     if(LogsToggle) {

     Log_SetStringToLog("A " + XI_ConvertString(ShipsTypes[crship].sname) + " with " + GetNationNameByType(sti(cr.nation)) + "'s flag sighted at " +  islandstr); Log_SetStringToLog("-"); }



     if (islandstr ==  "QuebradasCostillas") {setCharacterShipLocation(cr,"QC_port")}

     if (islandstr ==  "IslaMuelle") {setCharacterShipLocation(cr,"Muelle_port")}

     if (islandstr ==  "FalaiseDeFleur") {setCharacterShipLocation(cr, "Falaise_de_fleur_port_01")}

     else  setCharacterShipLocation(cr, islandstr + "_port");      //ships in port, just eyecandy

 }

 i=i+2  //doublestep for grouploop

    }

}

// ccc CR <-<!--c2--></div><!--ec2-->

This is an overall great mod, but I'd like to make it possible for enemy naval vessels to also raid the coast, not just pirates. I think I generally know what to do but my knowledge of code is very small. I've tried this but it doesn't answer. Any assitance would be great.

<!--c1--><div class='codetop'>CODE</div><div class='codemain'><!--ec1-->// ccc CR ->

void SetCoastTraffic(string islandstr)

{

    ref Pchar, CurIsland, cr;

    string chrstr;

    int crnation;

    string sFantomType;

    Pchar = GetMainCharacter();

    int i = 1;

    int j;

    CurIsland = GetIslandByIndex(FindIsland(islandstr));    

    chrstr = "Cr" + islandstr;



    for( j = 1; j <7; j++)    //Loop to reset relation BEFORE groupcreation

    {

 cr = CharacterFromID(chrstr + j );

 SetCharacterRelationBoth(sti(cr.index), GetMainCharacterIndex(), RELATION_NEUTRAL);

    }



    while(i < 6-(REDUCE_CR*2 + (sti(CurIsland.smuggling_nation) == PIRATE)*2))  // 1st loop to create 3 groups for 2 ships each, NK to reduce at pirate islands

    {

 string crg = chrstr + i;

 Group_DeleteGroup(crg);    //to clear for SeaLogin

 string pos = "Quest_Ship_"  + (1 + rand(16));      //random position



 Group_CreateGroup(crg);

 Group_SetGroupCommander(crg, crg);

 Group_SetAddress(crg, islandstr, "Quest_Ships", pos);

 if (rand(100) < COASTRAIDER_CHANCE)

 {

     if (sti(CurIsland.smuggling_nation) = ENGLAND

     {

crnation= FRANCE;

     }

     if (sti(CurIsland.smuggling_nation) = FRANCE

     {

     crnation= ENGLAND;

     }

     if (sti(CurIsland.smuggling_nation) = SPAIN

     {

     crnation= ENGLAND;

     }

     if (sti(CurIsland.smuggling_nation) = HOLLAND

     {

     crnation = PIRATE;

     }

     if (sti(CurIsland.smuggling_nation) = PORTUGAL

     {

     crnation = PIRATE;

     }

 }

 else

 {

     crnation =  sti(CurIsland.smuggling_nation);

     // crg is string, not object - crg.nation = crnation;      //nation for group

     if (GetRMRelationType(GetRMRelation(GetMainCharacter(),crnation))) // NK change to use RM

     {

   Group_SetTaskRunAway(crg);

   Group_LockTask(crg);

     }

     else

     {

   Group_SetTaskMove(crg, 10000.0, 10000.0);

     }

 }



 for( j = 0; j <2; j++)    // 2nd loop to create 2 ships for each group

 {

     cr = CharacterFromID(chrstr + (i+j));

     cr.nation    = crnation;      //nation for character

     SetRandomNameToCharacter(cr);



     if (crnation== PIRATE)

     {

   cr.quest.officertype = OFFIC_TYPE_CAPPIRATE;

   sFantomType = "pirate";

     }

     else

     {

   cr.quest.officertype = OFFIC_TYPE_CAPMERCHANT;

   sFantomType = "trade";

     }

     cr.FantomType = sFantomType;

     LAi_Create_Officer(0, cr);

     //cr.rank = makeint(Pchar.rank) + Rand(5);      //sets NEW rank! // NK, disabled, leads to weird XP bug...

     int skip = -10 + sti(Pchar.rank) + GetDifficulty()*2;

     if(skip > 30) skip = 30;



     int crship = skip + Rand(70 + GetDifficulty()*5) + Rand(70 + GetDifficulty()*5);  //select shiptype

     if (crship>150) crship = 162 + Rand(30);

     if(crship < 0) crship = 0;

     while(true)

     {

   if(crship < SHIP_TYPES_QUANTITY)

   {

       if(sti(ShipsTypes[crship].CanEncounter) && ShipsTypes[crship].id != "BlackPearl")

       {

     if(crnation != PIRATE) { break; }

     if(sti(ShipsTypes[crship].class) >= MAXPIRATECLASS) { break; }

       }

   }

   crship = skip + Rand(70 + GetDifficulty()*5) + Rand(70 + GetDifficulty()*5);  //select shiptype

   if (crship>150) crship = 162 + Rand(30);

   if(crship < 0) crship = 0;

     }

     /*int crship = makeint(cr.rank)*10 + 20 -Rand(30);  //select shiptype

     if (crship>167) crship = makeint(170+Rand(15) );*/

     Ship_CreateForCharacter(cr, crship, "Coaster")



   //equip ship

     Ship_SetFantomData(cr);

     Fantom_SetCannons(cr, sFantomType);

     Fantom_SetBalls(cr, sFantomType);

     Fantom_SetSails(cr, sFantomType);

     Fantom_SetGoods(cr, sFantomType);

     Fantom_SetRandomMoney(cr, sFantomType);

     

     SetRandomNameToShip(cr);



     if (crnation== PIRATE)

     {

   cr.perks.list.ShipSpeedUp = true;

   cr.Ship.crew.quantity = MakeInt(GetMaxCrewQuantity(cr));

     }

     SetCharacterRelationBoth(sti(cr.index), GetMainCharacterIndex(), GetRMRelationType(GetRMRelation(GetMainCharacter(), sti(cr.nation)))); // NK set base relation to avoid gray icon

     string crgm = chrstr + (i +j);    //add to group

     Group_addCharacter(crg, crgm);



     // NK to convert shipname to nice string

     if(LogsToggle) {

     Log_SetStringToLog("A " + XI_ConvertString(ShipsTypes[crship].sname) + " with " + GetNationNameByType(sti(cr.nation)) + "'s flag sighted at " +  islandstr); Log_SetStringToLog("-"); }



     if (islandstr ==  "QuebradasCostillas") {setCharacterShipLocation(cr,"QC_port")}

     if (islandstr ==  "IslaMuelle") {setCharacterShipLocation(cr,"Muelle_port")}

     if (islandstr ==  "FalaiseDeFleur") {setCharacterShipLocation(cr, "Falaise_de_fleur_port_01")}

     else  setCharacterShipLocation(cr, islandstr + "_port");      //ships in port, just eyecandy

 }

 i=i+2  //doublestep for grouploop

    }

}

// ccc CR <-<!--c2--></div><!--ec2-->
 
All I notice right away, is that you need to use two = in if statements.
I.e. if(nation == othernation).
Because == (a test) and = (an operator) are different things; the first returns true or false, the latter sets the `left-side` thing equal to the `right-side` thing.

That aside, however, there's trouble doing this the short and simple way, because the code as of now assumes that any ship whose nation is not PIRATE is a tradeship, and sets it up accordingly.

So basically we need to both add a new bit near the top to choose the raiding nation, but also further down add choices for warship type (vs pirate type or trade type).

Also, POTC already includes a function,
int FindEnemyNation2Nation(int iNation)
in nations.c which does some of the work for us (returns at nation at war with the passed nation). I recommend using this rather than `hard-coding` nation choice because if nation relations switch during the game the FindEnemyNation function will take that into account.

So, here's what I'd suggest.

First, we need to add a function I forgot: CaptainTypeFromFantomType.
This translates fantomtype (war, trade, pirate) to the type of captain for each (CAPNAVY, CAPMERCHANT, CAPPIRATE)

I put it at the bottom of dialog_func.c, and it goes like this:
<!--c1--><div class='codetop'>CODE</div><div class='codemain'><!--ec1-->// NK -->

//return captain type based on fantomtype

string CaptainTypeFromFantomType(string ftype)

{

    switch(ftype)

    {

 case "pirate": return OFFIC_TYPE_CAPPIRATE;

 case "trade": return OFFIC_TYPE_CAPMERCHANT;

 case "war": return OFFIC_TYPE_CAPNAVY;

 return OFFIC_TYPE_CAPNAVY;

    }

}

// NK <--<!--c2--></div><!--ec2-->


Next, we add NAVYRAIDER_CHANCE to buildsettings.h
<!--c1--><div class='codetop'>CODE</div><div class='codemain'><!--ec1-->#define NAVYRAIDER_CHANCE 50 //Ditto, but chance that raider is a foreign warship. Chance for that is coastraider_chance * navyraider_chance<!--c2--></div><!--ec2-->

Then, we modify the `nation-assignment` bit of SetCoastTraffic.
find
<!--c1--><div class='codetop'>CODE</div><div class='codemain'><!--ec1-->  if (rand(100) < COASTRAIDER_CHANCE)

 {

     crnation= PIRATE;

 }

 else

 {

     crnation =  sti(CurIsland.smuggling_nation);<!--c2--></div><!--ec2-->

and replace with:

<!--c1--><div class='codetop'>CODE</div><div class='codemain'><!--ec1-->  if (rand(100) < COASTRAIDER_CHANCE)

 {

     if(rand(100) < NAVYRAIDER_CHANCE)

     {

   crnation = FindEnemyNation2Nation(int sti(CurIsland.smuggling_nation));

   sFantomType = "war";

     }

     else

     {

   crnation= PIRATE;

   sFantomType = "pirate";

     }

 }

 else

 {

     crnation =  sti(CurIsland.smuggling_nation);

     sFantomType = "trade";<!--c2--></div><!--ec2-->


Then, further down, we call our new function. Replace
<!--c1--><div class='codetop'>CODE</div><div class='codemain'><!--ec1-->if (crnation== PIRATE)

     {

   cr.quest.officertype = OFFIC_TYPE_CAPPIRATE;

   sFantomType = "pirate";

     }

     else

     {

   cr.quest.officertype = OFFIC_TYPE_CAPMERCHANT;

   sFantomType = "trade";

     }<!--c2--></div><!--ec2-->

with
<!--c1--><div class='codetop'>CODE</div><div class='codemain'><!--ec1-->      cr.quest.officertype = CaptainTypeFromFantomType(sFantomType); // NK `04-08`-27<!--c2--></div><!--ec2-->


And that should do it. <img src="http://www.piratesahoy.com/forum/style_emoticons/<#EMO_DIR#>/smile.gif" style="vertical-align:middle" emoid=":)" border="0" alt="smile.gif" />
(Can't test ATM, maybe I screwed up. You'll have to find out the hard way. <img src="http://www.piratesahoy.com/forum/style_emoticons/<#EMO_DIR#>/wink.gif" style="vertical-align:middle" emoid=";)" border="0" alt="wink.gif" /> )
 
I get an error when I try to open the game now. Thanks for your help though.
I'll restore the old files for now and work on something else. Thanks again for the prompt response.

Its great to have you back.
 
what i'd like to see in the coastraiders mod - it'd be great if it was implemented with the `pirate-hunting` quests. if pirates are around the island and you sink/capture them, then the governor should reward you (instead of one mysteriously appearing when the governor gives you the quests hehe <img src="http://www.piratesahoy.com/forum/style_emoticons/<#EMO_DIR#>/laugh.gif" style="vertical-align:middle" emoid="xD:" border="0" alt="laugh.gif" /> ). and i think the probability of seeing them should be much lower (i know you can change this in buildsettings.h though...) <img src="http://www.piratesahoy.com/forum/style_emoticons/<#EMO_DIR#>/happy.gif" style="vertical-align:middle" emoid="^_^" border="0" alt="happy.gif" />
 
Would there be a way to have Merchant shipping update automatically but Pirates update only once they are sunk or captured? I like the idea of starting out a naval career in a small cutter, sloop, or lugger and have a sort of coast guard function... patrolling the island for pirates. You could do this as a Lt, and then once you were made a Commander you could go on your first cruise etc...
 
JMV: Thanks. <img src="http://www.piratesahoy.com/forum/style_emoticons/<#EMO_DIR#>/oops3.gif" style="vertical-align:middle" emoid=":eek:ops2" border="0" alt="oops3.gif" /> It's good to be back, and catch up with you all. <img src="http://www.piratesahoy.com/forum/style_emoticons/<#EMO_DIR#>/smile.gif" style="vertical-align:middle" emoid=":)" border="0" alt="smile.gif" />

Found the errors I hope (finally got POTC running).
First, FindEnemyNation2Nation(int sti........
should be FindEnemyNation2Nation(sti.......

second, the func in dialog_func.c should be:
<!--c1--><div class='codetop'>CODE</div><div class='codemain'><!--ec1-->string CaptainTypeFromFantomType(string ftype)

{

    switch(ftype)

    {

 case "pirate": return OFFIC_TYPE_CAPPIRATE; break;

 case "trade": return OFFIC_TYPE_CAPMERCHANT; break;

 case "war": return OFFIC_TYPE_CAPNAVY; break;

    }

    return OFFIC_TYPE_CAPNAVY;

}<!--c2--></div><!--ec2-->
 
Kieron: You can do this I think.
Just edit aiship.c->ShipDead(), the RM --> section, so it also sets pchar.quest.generate_kill_quest = "completed" and set pchar.quest.killmoney to the appropriate amount (or if it's `non-zero`, increment).

However, as someone in the bugs thread IIRC noticed, this bit needs to be overhauled so it's governor/island specific (as right now it applies to any governor since it's the pchar's attribute that's checked, not the governor's).
 
JMV: Hmm. (re: persistant pirates)
I don't ATM see a `quick-n`-easy way to do this, because of the nature of SetCoastTraffic (it overwrites all chars each time).
What could be done is to first add an attribute for each CT/CR char, last_generated, and the date.
Then, go through all the characters and see which are alive and which dead. If the char is dead, or last_generated is old enough, "clear" the slot and generate new (if rand() < whatever chance to make new).
If not, skip the slot.

That would require rewriting to use a for loop instead of a while loop though.
 
Great idea to add more nations. Could make interesting `three-party` battles: locals vs pirates vs hostile navy (I love it if my enemies fight each other <img src="http://www.piratesahoy.com/forum/style_emoticons/<#EMO_DIR#>/dev.gif" style="vertical-align:middle" emoid=":d:" border="0" alt="dev.gif" /> )
 
WB, CCC, hope you had a nice time camping!

I am glad this is being worked on, too. I, like you, CCC, love it when my enemies are fighting. Talk about an interesting battle when YOU dive in! <img src="http://www.piratesahoy.com/forum/style_emoticons/<#EMO_DIR#>/icon_mrgreen1.gif" style="vertical-align:middle" emoid=":cheeky" border="0" alt="icon_mrgreen1.gif" />
 
Back
Top