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

Solved Dutchman Quest Revisions (Test Game Download Included)

Logbook now updates for dutchman death without commander killed by aboardage, however it does not re-spawn... Also the quest updates that logbook entry twice... Still testing for the win condition...
EDIT:
Win works perfectly....
 
Last edited:
Try changing condition for !=KILL_BY_ABORDAGE to this:

Pchar.quest.dutchman_Respawn.win_condition.l1 = "ExitFromSea");
PChar.quest.dutchman_Respawn.win_condition = "spawn_dutchman";

That won't do exactly what you wanted...to leave Grenada. But as soon as you exit sea, it should recall the spawn_dutchman case and you can check the log to verify.
 
The Dutchman, in that previous test, was killed by a storm that I spawned into while avoiding pirates... I also want to hear the possibility of correcting the island spawn locators around Grenada. It appears that despite my best efforts, the quest still occasionally wants to spawn the Dutchman on a invalid locator around Grenada. Also I would like to add that when the Dutchman is spawned, he is spawned with some of his health missing due to colliding somehow with the island before encountering me....
 
I did the test again and sunk it with a war galleon I stole from the pirates, however the ship didn't respawn....
 
Logs:
 

Attachments

  • compile.log
    180.1 KB · Views: 222
  • error.log
    17.2 KB · Views: 247
  • system.log
    24.8 KB · Views: 225
Good news. Even without your save, I constructed some console.c code to replicate the one part not yet working and this will probably do it:

First, there are a couple bugs in the original CT CharacterUtilite.c. Change these two functions:

Code:
int GetCharacterCurrentIsland(ref _refCharacter)
{
    //#20171026-01 Bug fix
    int curLocNum = FindLocation(_refCharacter.location);
    if(curLocNum<0) return -1;
    return GetIslandIdxByLocationIdx(curLocNum);
}

int GetIslandIdxByLocationIdx(int locIdx)
{
    aref rootar,ar;
    makearef(rootar,Locations[0].IslandsList);
    for(int i=0; i<GetAttributesNum(rootar); i++)
    {
        ar = GetAttributeN(rootar,i);
        //#20171026-01 Bug fix Begin of next island locators is same as end of previous
        if( locIdx>=sti(ar.begin) && locIdx<sti(ar.end) )
        {
            return FindIsland(GetAttributeName(ar));
        }
    }
    return -1;
}

In quests_check.c, I developed a way to get your desired feature to indicate that you left the island. Find function bool ProcessCondition(aref condition), scroll toward the end and insert, immediately after the case "ActIntoLocator": break; statement:

Code:
    case "ActIntoLocator":
    .
    .
    .
    break;
    //#20171026-02 Add ExitIsland quest condition
    case "ExitIsland":
        if(CheckAttribute(worldMap, "isLoaded") && worldMap.isLoaded == "true")
        {
            if(worldMap.island != condition.island)
                return true;
            else
                return false;
        }
        if(bSeaActive)
        {
            if(CheckAttribute(AISea, "island") && AISea.Island != condition.island)
                return true;
            else
                return false;
        }
        int myIslandIdx = GetCharacterCurrentIsland(refCharacter);
        if(myIslandIdx > -1) {
             string myisland = Islands[myIslandIdx].id;
             if(myisland != condition.island)
                return true;
        }
        return false;
    break;

Last, change dutch_encounter.c:

Code:
            case "dutchman_KillJones":
           //Kill Jones by function
           chr = GetCharacter(GetCharacterIndex("Davy Jones"));
           if( CheckAttribute(chr,"Killer.status") && sti(chr.Killer.status)==KILL_BY_ABORDAGE )
           {
                SetQuestHeader("Dutchman");
                AddQuestRecord("Dutchman", "3_captured");
                trace("*** Davy Jones Killed by Abordage");
                DoQuestCheckDelay("dutchman_dead", 2.0);
            }
            else
            {
                trace("Flying Dutchman Killed by Cannonfire");
                SetQuestHeader("Dutchman");
                AddQuestRecord("Dutchman", "2_failed");
                LAi_group_Delete("FlyingDutchman"); //Sea group
                Pchar.quest.spawn_dutchman.win_condition.l1 = "ExitIsland");
                Pchar.quest.spawn_dutchman.win_condition.l1.island = "Guadeloupe");
                PChar.quest.spawn_dutchman.win_condition = "spawn_dutchman";
            }
       break;
 
Good news. Even without your save, I constructed some console.c code to replicate the one part not yet working and this will probably do it:

First, there are a couple bugs in the original CT CharacterUtilite.c. Change these two functions:

Code:
int GetCharacterCurrentIsland(ref _refCharacter)
{
    //#20171026-01 Bug fix
    int curLocNum = FindLocation(_refCharacter.location);
    if(curLocNum<0) return -1;
    return GetIslandIdxByLocationIdx(curLocNum);
}

int GetIslandIdxByLocationIdx(int locIdx)
{
    aref rootar,ar;
    makearef(rootar,Locations[0].IslandsList);
    for(int i=0; i<GetAttributesNum(rootar); i++)
    {
        ar = GetAttributeN(rootar,i);
        //#20171026-01 Bug fix Begin of next island locators is same as end of previous
        if( locIdx>=sti(ar.begin) && locIdx<sti(ar.end) )
        {
            return FindIsland(GetAttributeName(ar));
        }
    }
    return -1;
}

In quests_check.c, I developed a way to get your desired feature to indicate that you left the island. Find function bool ProcessCondition(aref condition), scroll toward the end and insert, immediately after the case "ActIntoLocator": break; statement:

Code:
    case "ActIntoLocator":
    .
    .
    .
    break;
    //#20171026-02 Add ExitIsland quest condition
    case "ExitIsland":
        if(CheckAttribute(worldMap, "isLoaded") && worldMap.isLoaded == "true")
        {
            if(worldMap.island != condition.island)
                return true;
            else
                return false;
        }
        if(bSeaActive)
        {
            if(CheckAttribute(AISea, "island") && AISea.Island != condition.island)
                return true;
            else
                return false;
        }
        int myIslandIdx = GetCharacterCurrentIsland(refCharacter);
        if(myIslandIdx > -1) {
             string myisland = Islands[myIslandIdx].id;
             if(myisland != condition.island)
                return true;
        }
        return false;
    break;

Last, change dutch_encounter.c:

Code:
            case "dutchman_KillJones":
           //Kill Jones by function
           chr = GetCharacter(GetCharacterIndex("Davy Jones"));
           if( CheckAttribute(chr,"Killer.status") && sti(chr.Killer.status)==KILL_BY_ABORDAGE )
           {
                SetQuestHeader("Dutchman");
                AddQuestRecord("Dutchman", "3_captured");
                trace("*** Davy Jones Killed by Abordage");
                DoQuestCheckDelay("dutchman_dead", 2.0);
            }
            else
            {
                trace("Flying Dutchman Killed by Cannonfire");
                SetQuestHeader("Dutchman");
                AddQuestRecord("Dutchman", "2_failed");
                LAi_group_Delete("FlyingDutchman"); //Sea group
                Pchar.quest.spawn_dutchman.win_condition.l1 = "ExitIsland");
                Pchar.quest.spawn_dutchman.win_condition.l1.island = "Guadeloupe");
                PChar.quest.spawn_dutchman.win_condition = "spawn_dutchman";
            }
       break;
Why Guadeloupe?
 
I tested it and the game crashes when the Dutchman sinks.... I tested twice... Interesting thing is that the first run had an error log while the second run didn't... Logs of 2nd run:
 

Attachments

  • compile.log
    27.1 KB · Views: 224
  • system.log
    4.6 KB · Views: 228
The crash looks to be a completely unrelated problem, not the scenario we are resolving. The crash is in system.log: Assert failed in AIShipCannonController.cpp line 870, expression string pADamages

But look at your compile.log...the change worked for respawn.

Midway in the file, is the first instance:

*** Davy Jones login successful
returning qChar = 317

His respawn at the end:

NPC_Death Davy Jones
Flying Dutchman Killed by Cannonfire
Quest ADDED
Davy exist = 317
*** Davy Jones login successful
returning qChar = 317
 
I think the problem for the crash is use of SetBaseShipData. It removes the .damages attribute. On first char/ship init, it's probably fine because that attribute gets created by the engine on ship initialization. But, for re-use of the same char/ship, calling SetBaseShipData removes .damages, doesn't re-init the ship in the engine and causes the problem. Gonna have to figure a way around that.
 
Let's abandon SetBaseShipData in the dutchman. Add these to CharacterUtilite.c:

Code:
//Borrow COAS
void PGG_UpdateShipEquip(ref chr)
{

    if (sti(chr.Ship.Type) == SHIP_NOTUSED) return;

    ref refTown, chref;
    string curTown;

    ProcessHullRepair(chr, 100.0);
    ProcessSailRepair(chr, 100.0);
    SetCrewQuantityFull(chr);
    Fantom_SetCannons(chr, "pirate");
    Fantom_SetBalls(chr, "pirate");
    Fantom_SetGoods(chr, "pirate");
}
//Borrow COAS
void SetCrewQuantityFull(ref _refCharacter)
{
    SetCrewQuantity(_refCharacter, GetMaxCrewQuantity(_refCharacter));
}

Change call in SpawnDutchman():
Code:
     else { //Reset ship attributes (restock HP, ammo, etc.)
        PGG_UpdateShipEquip(GetCharacter(qChar));
    }
 
Let's abandon SetBaseShipData in the dutchman. Add these to CharacterUtilite.c:

Code:
//Borrow COAS
void PGG_UpdateShipEquip(ref chr)
{

    if (sti(chr.Ship.Type) == SHIP_NOTUSED) return;

    ref refTown, chref;
    string curTown;

    ProcessHullRepair(chr, 100.0);
    ProcessSailRepair(chr, 100.0);
    SetCrewQuantityFull(chr);
    Fantom_SetCannons(chr, "pirate");
    Fantom_SetBalls(chr, "pirate");
    Fantom_SetGoods(chr, "pirate");
}
//Borrow COAS
void SetCrewQuantityFull(ref _refCharacter)
{
    SetCrewQuantity(_refCharacter, GetMaxCrewQuantity(_refCharacter));
}

Change call in SpawnDutchman():
Code:
     else { //Reset ship attributes (restock HP, ammo, etc.)
        PGG_UpdateShipEquip(GetCharacter(qChar));
    }
The Dutchman Still doesn't re-spawn... At least the game doesn't crash anymore... (After sinking I returned to the worldmap then sailed around a bit then came back to grenada)... Logs:
 

Attachments

  • compile.log
    35 KB · Views: 235
  • error.log
    3.5 KB · Views: 253
  • system.log
    11.1 KB · Views: 241
I think I'm going to need that save and sink it myself. Your log is showing:

Flying Dutchman Killed by Cannonfire
Quest ADDED
*** Davy Jones login successful

That is way too quick...you should have to leave first for the ExitIsland to initiate the Davy Jones rebirth, but it's immediately recognized as true. When I do this in my console.c replica, it works, but when run through the NPC_Death scenario, it's firing immediately.
 
OK, no need for the save, I just adjusted the ship hp to 10 so I'd sink it with one hit. I figured out both why your double log post and no respawn; NPC_Death is finding your respawned char immediately and noting it is still dead (due to zero chr_ai.hp) so it repeats that part of the process for the log and also doesn't ever show up because the char is dead. In SpawnDutchman:

Code:
else { //Reset ship attributes (restock HP, ammo, etc.)
        PGG_UpdateShipEquip(GetCharacter(qChar));
        LAi_SetCurHPMax(GetCharacter(qChar));
    }

Of course I'm also dumb...I finally understand your questioning now about Guadeloupe...yes, change that to Grenada. I was testing where my character already was, Guadeloupe and got it to work with the HP fix above, but obviously you wanted everything in Grenada but I failed to put that fact together when you asked about it before, LOL:

Code:
                Pchar.quest.spawn_dutchman.win_condition.l1 = "ExitIsland");
                Pchar.quest.spawn_dutchman.win_condition.l1.island = "Grenada");
                PChar.quest.spawn_dutchman.win_condition = "spawn_dutchman";
 
Last edited:
Updated version with latest edits (excluding your latest fixes - will manually update it when I get home tomorrow from my dorm):
CTSupermod.zip

In the meantime, I will test those edits with the school client.
 
The Dutchman finally re-spawns, however the cannons on the ship post re-spawn are not correct. 48 pdr demi-cannons are supposed to be the dutchman's cannons...
 
Logs from latest run:
 

Attachments

  • compile.log
    58.2 KB · Views: 217
  • error.log
    3.6 KB · Views: 223
  • system.log
    21.2 KB · Views: 201
The Dutchman finally re-spawns, however the cannons on the ship post re-spawn are not correct. 48 pdr demi-cannons are supposed to be the dutchman's cannons...

I'm guessing that call to update the ship equipment (replenish cannon balls, etc.), might quash the cannon override you had in the initial char setup. Just copy that characters[qChar].Ship.Cannons.Type = CANNON_TYPE_CANNON_LBS48; line into the else block, after the ShipEquip call.
 
That works and the respawned captain even shoots at me this time.... The Topic is now resolved and now we can iron out some of the bugs that occur in the game.
 
Back
Top