1. Dismiss Notice
  2. GOG.com logo

    Thanks to YOUR votes, GOG.com now sells:
    - Sea Dogs - Sea Dogs: Caribbean Tales
    - Sea Dogs: City of Abandoned Ships

    Vote now to add Pirates of the Caribbean to the list!

    Dismiss Notice
  3. Under the Crossbones Podcast

    A Pirate Podcast with Interviews
    Music, Comedy and all things Pirate!

    - Episode Guide - About - Subscribe -
    - Twitter - Facebook - iTunes - Android -
    - Youtube - Fill the Coffers -

    Dismiss Notice
  4. New Horizons logo

    Quick links for PotC: New Horizons
    - Download latest version
    - Wiki - FAQ - Report bugs here
    - ModDB profile

  5. GOF logo

    Quick links for AoP2: Gentlemen of Fortune 2
    - Downloads and info
    - Historical Immersion Supermod
    - ModDB Profile

Dismiss Notice
New to the forum?
Please take a moment to read our Welcome Message and Forum Rules.

Solved Dutchman Quest Revisions (Test Game Download Included)

Discussion in 'Sea Dogs: Caribbean Tales' started by Modder01, Oct 11, 2017.

  1. Modder01

    Modder01 Freebooter Storm Modder

    Joined:
    Feb 1, 2014
    Messages:
    294
    Gender:
    Male
    Location:
    Oxford, Michigan, USA
    Logs from Latest Run, computer crashed two times due to that new change... Here:
     

    Attached Files:

  2. ChezJfrey

    ChezJfrey Master Mariner Storm Modder

    Joined:
    Apr 24, 2015
    Messages:
    226
    At the minimum, we would expect that the boarding_enemy would have had that charge_max and I wonder if that is why the gun is never used. Should have been set so let's see what's happening during char setup. Find these files/functions and add traces:

    characters\CharacterUtilite.c
    Code:
    void EquipCharacterByItem(ref chref, string itemID)
    {
       aref arItm;
    trace("EquipCharacterByItem " + itemID);
       if( !CheckCharacterItem(chref, itemID) ) return;
       if( Items_FindItem(itemID, &arItm)<0 )   return;
       if( !CheckAttribute(arItm, "groupID") ) return;
    
       string groupName = arItm.groupID;
       string oldItemID = GetCharacterEquipByGroup(chref, groupName);
       if(oldItemID==itemID) return;
       chref.equip.(groupName) = itemID;
    
       if(IsEntity(chref))
       {   trace("calling SetEquipedItemToCharacter " + itemID);
            SetEquipedItemToCharacter(chref, groupName, itemID);
       }
       if(groupName==GUN_ITEM_TYPE && sti(chref.index)==GetMainCharacterIndex())
       {   LAi_GunSetUnload(chref);
       }
       if(groupName==SABERGUN_ITEM_TYPE && sti(chref.index)==GetMainCharacterIndex())
       {   LAi_GunSetUnload(chref);
       }
    }
    
    void SetEquipedItemToCharacter(ref chref, string groupID, string itemID)
    {
       object emptyItm;
       aref arItm;
       string modelName = "";
       makearef(arItm,emptyItm);
       if(itemID!="")
       {
           if( !CheckCharacterItem(chref,itemID) ) return;
           Items_FindItem(itemID,&arItm);
       }
    
       switch(groupID)
       {
       case SPYGLASS_ITEM_TYPE:
           if(CheckAttribute(arItm,"id"))
           {
               setTelescopeInitParameters(arItm);
           }
       break;
    
       case GUN_ITEM_TYPE:
           trace("GUN_ITEM_TYPE " + itemID);
           if(CheckAttribute(arItm,"model"))   {modelName = arItm.model;}
           SendMessage(chref,"ls",MSG_CHARACTER_SETGUN,modelName);
           if(CheckAttribute(arItm,"chargeQ"))
           {
               trace("calling LAi_GunSetChargeQuant " + arItm.chargeQ);
               LAi_GunSetChargeQuant(chref,sti(arItm.chargeQ));
           } else
           {   LAi_GunSetChargeQuant(chref,0);
           }
           if(CheckAttribute(arItm,"chargespeed") && stf(arItm.chargespeed)>0.0)
           {   LAi_GunSetChargeSpeed(chref,1.0/stf(arItm.chargespeed));
           } else
           {   LAi_GunSetChargeSpeed(chref,0.0);
           }
           if(CheckAttribute(arItm,"dmg_min"))
           {   LAi_GunSetDamageMin(chref,stf(arItm.dmg_min));
           } else
           {   LAi_GunSetDamageMin(chref,0.0);
           }
           if(CheckAttribute(arItm,"dmg_max"))
           {   LAi_GunSetDamageMax(chref,stf(arItm.dmg_max));
           } else
           {   LAi_GunSetDamageMax(chref,0.0);
           }
           if(CheckAttribute(arItm,"accuracy"))
           {   LAi_GunSetAccuracy(chref,stf(arItm.accuracy)*0.01);
           } else
           {   LAi_GunSetAccuracy(chref,0.0);
           }
       break;
    
       case BLADE_ITEM_TYPE:
           float liveTime = 0.1;
           int colors = argb(64, 64, 64, 64);
           int colore = argb(0, 32, 32, 32);
           if(CheckAttribute(arItm,"model"))   {modelName = arItm.model;}
           if(CheckAttribute(arItm, "blade.time"))   {liveTime = stf(arItm.blade.time);}
           if(CheckAttribute(arItm, "blade.colorstart"))   {colors = sti(arItm.blade.colorstart);}
           if(CheckAttribute(arItm, "blade.colorend"))   {colore = sti(arItm.blade.colorend);}
           SendMessage(chref, "llsfll", MSG_CHARACTER_SETBLADE, 0, modelName, liveTime, colors, colore);
           if(CheckAttribute(arItm,"dmg_min"))
           {   LAi_BladeSetDamageMin(chref,stf(arItm.dmg_min));
           } else
           {   LAi_BladeSetDamageMin(chref,0.0);
           }
           if(CheckAttribute(arItm,"dmg_max"))
           {   LAi_BladeSetDamageMax(chref,stf(arItm.dmg_max));
           } else
           {   LAi_BladeSetDamageMax(chref,0.0);
           }
           if(CheckAttribute(arItm,"piercing"))
           {   LAi_BladeSetPiercing(chref,stf(arItm.piercing)*0.01);
           } else
           {   LAi_BladeSetPiercing(chref,0.0);
           }
           if(CheckAttribute(arItm,"block"))
           {   LAi_BladeSetBlock(chref,stf(arItm.block)*0.01);
           } else
           {   LAi_BladeSetBlock(chref,0.0);
           }
       break;
    
       case SABERGUN_ITEM_TYPE:
           float liveTime2 = 0.1;
           int colors2 = argb(64, 64, 64, 64);
           int colore2 = argb(0, 32, 32, 32);
           if(CheckAttribute(arItm,"model"))   {modelName = arItm.model;}
           if(CheckAttribute(arItm, "blade.time"))   {liveTime2 = stf(arItm.blade.time);}
           if(CheckAttribute(arItm, "blade.colorstart"))   {colors2 = sti(arItm.blade.colorstart);}
           if(CheckAttribute(arItm, "blade.colorend"))   {colore2 = sti(arItm.blade.colorend);}
           SendMessage(chref, "llsfll", MSG_CHARACTER_SETBLADE, 1, modelName, liveTime2, colors2, colore2);
           if(CheckAttribute(arItm,"dmg_min"))
           {   LAi_BladeSetDamageMin(chref,stf(arItm.dmg_min));
           } else
           {   LAi_BladeSetDamageMin(chref,0.0);
           }
           if(CheckAttribute(arItm,"dmg_max"))
           {   LAi_BladeSetDamageMax(chref,stf(arItm.dmg_max));
           } else
           {   LAi_BladeSetDamageMax(chref,0.0);
           }
           if(CheckAttribute(arItm,"piercing"))
           {   LAi_BladeSetPiercing(chref,stf(arItm.piercing)*0.01);
           } else
           {   LAi_BladeSetPiercing(chref,0.0);
           }
           if(CheckAttribute(arItm,"block"))
           {   LAi_BladeSetBlock(chref,stf(arItm.block)*0.01);
           } else
           {   LAi_BladeSetBlock(chref,0.0);
           }
       break;
       }
    }
    
    loc_ai\LAi_character.c

    Code:
    void LAi_GunSetChargeQuant(aref chr, int quant)
    {
        trace("LAi_GunSetChargeQuant " + quant);
       if(quant < 0) quant = 0;
       if(quant > 4) quant = 4;
       trace("setting charge_max " + quant);
       chr.chr_ai.charge_max = quant;
       chr.chr_ai.charge = quant;
       chr.chr_ai.chargeprc = "1";
    }
    
     
  3. Modder01

    Modder01 Freebooter Storm Modder

    Joined:
    Feb 1, 2014
    Messages:
    294
    Gender:
    Male
    Location:
    Oxford, Michigan, USA
    The Logs As Requested:
     

    Attached Files:

  4. ChezJfrey

    ChezJfrey Master Mariner Storm Modder

    Joined:
    Apr 24, 2015
    Messages:
    226
    That gun6 equip is not getting anywhere toward setting the charges for Davy. Let's add some more to see what the hangup might be in CharacterUtilite.c:

    Code:
    void EquipCharacterByItem(ref chref, string itemID)
    {
        aref arItm;
    trace("EquipCharacterByItem " + itemID);
        if( !CheckCharacterItem(chref, itemID) ) return;
    trace("checked " + itemID);
        if( Items_FindItem(itemID, &arItm)<0 )    return;
        if( !CheckAttribute(arItm, "groupID") ) return;
    
        string groupName = arItm.groupID;
        string oldItemID = GetCharacterEquipByGroup(chref, groupName);
    trace("oldItemID " + oldItemID);
        if(oldItemID==itemID) return;
        chref.equip.(groupName) = itemID;
    trace("IsEntity(chref) " + IsEntity(chref));
        if(IsEntity(chref))
        {    trace("calling SetEquipedItemToCharacter " + chref.id + ", " + itemID);
            SetEquipedItemToCharacter(chref, groupName, itemID);
        }
        if(groupName==GUN_ITEM_TYPE && sti(chref.index)==GetMainCharacterIndex())
        {    LAi_GunSetUnload(chref);
        }
        if(groupName==SABERGUN_ITEM_TYPE && sti(chref.index)==GetMainCharacterIndex())
        {    LAi_GunSetUnload(chref);
        }
    }
     
  5. Modder01

    Modder01 Freebooter Storm Modder

    Joined:
    Feb 1, 2014
    Messages:
    294
    Gender:
    Male
    Location:
    Oxford, Michigan, USA
    Logs based on above traces:
     

    Attached Files:

  6. Modder01

    Modder01 Freebooter Storm Modder

    Joined:
    Feb 1, 2014
    Messages:
    294
    Gender:
    Male
    Location:
    Oxford, Michigan, USA
    Google drive is being a royal pain uploading the latest version so I have created a mega account to try and have a more reliable file host...
     
  7. ChezJfrey

    ChezJfrey Master Mariner Storm Modder

    Joined:
    Apr 24, 2015
    Messages:
    226
    The reason the max_charge is not being set is due to IsEntity returning negative. I see now that GenerateCharacter does not actually send a message to create an entity, yet CreateFantom character does. Hence the need to copy stuff...but it does not copy the chr_ai attributes associated with gun charge...I think this will do it:

    Change these lines in ChangeAttributesFromCharacter

    Code:
    if (CheckAttribute(PastChref, "equip.blade"))
        {
           //CopyChref.equip.blade =   PastChref.equip.blade;
           EquipCharacterByItem(CopyChref, PastChref.equip.blade);
       }
       if (CheckAttribute(PastChref, "equip.gun"))
        {
           //CopyChref.equip.gun   =   PastChref.equip.gun;
           EquipCharacterByItem(CopyChref, PastChref.equip.gun);
       }
    
     
    Last edited: Oct 20, 2017
  8. Modder01

    Modder01 Freebooter Storm Modder

    Joined:
    Feb 1, 2014
    Messages:
    294
    Gender:
    Male
    Location:
    Oxford, Michigan, USA
    I have been having trouble uploading to file hosts recently. Expect a reply this coming Sunday or Monday as my home machine's client has not been updated.
     
  9. Modder01

    Modder01 Freebooter Storm Modder

    Joined:
    Feb 1, 2014
    Messages:
    294
    Gender:
    Male
    Location:
    Oxford, Michigan, USA
    The character is still not shooting at me.... Logs:
     

    Attached Files:

  10. ChezJfrey

    ChezJfrey Master Mariner Storm Modder

    Joined:
    Apr 24, 2015
    Messages:
    226
    Well, the good news is that the last change was correct, the standin char is a valid entity, and the gun charge attributes are now being set correctly:

    LoadLocation(ref loc) CaptainCabine
    GUN_ITEM_TYPE gun1
    calling LAi_GunSetChargeQuant 1
    LAi_GunSetChargeQuant 1
    setting charge_max 1
    EquipCharacterByItem blade1
    checked blade1
    oldItemID
    IsEntity(chref) 0
    Special Character
    EquipCharacterByItem blade19
    checked blade19
    oldItemID blade1
    IsEntity(chref) 1
    calling SetEquipedItemToCharacter Location fantom character <0>, blade19
    EquipCharacterByItem gun6
    checked gun6
    oldItemID
    IsEntity(chref) 1
    calling SetEquipedItemToCharacter Location fantom character <0>, gun6
    GUN_ITEM_TYPE gun6
    calling LAi_GunSetChargeQuant 4
    LAi_GunSetChargeQuant 4
    setting charge_max 4
    Standin capt .model (attr funct)= pirate_5
    Standin capt .equip.gun (attr funct)= gun6
    Standin capt .equip.blade (attr funct)= blade19
    Standin capt .location (attr funct)= CaptainCabine
    Standin capt .model = pirate_5
    Standin capt .equip.gun = gun6
    Standin capt .equip.blade = blade19
    Standin capt .location = CaptainCabine
    charge max 4
    charge curr 4

    As for the actual character not using the gun, seems a peculiarity with CT, of which I am not yet sure about the cause. I thought it was those gun attributes, but we can see from the log they are now being set properly, so it remains a mystery why the NPC refuses to actually use the gun.
     
  11. ChezJfrey

    ChezJfrey Master Mariner Storm Modder

    Joined:
    Apr 24, 2015
    Messages:
    226
    OK, I made a console.c, with the same methods to replicate this character scenario, but instead on the pier so I could debug why the character never pulls a pistol. It of course did as you describe, no matter how long I evaded just out of reach, the NPC never fired. But, I eventually figured it all out. Some if is errors in the .ani files, and also a bug fixed in later versions, along with one piece missing to help initiate a call in the engine to kick off the correct event to enable NPC firing. Let me clean up my files and package this up, as it requires modification of .ani files, LAi_events.c, LAi_utils.c, characters.c.
     
  12. ChezJfrey

    ChezJfrey Master Mariner Storm Modder

    Joined:
    Apr 24, 2015
    Messages:
    226
    Pick it up here: MEGA

    GunFix.zip

    Also, in void LAi_SetBoardingCaptain, add two lines before LAi_CreateFantomCharacterEx:

    Code:
        TempFightChar.skill.fencing = boarding_enemy.skill.fencing;
        TempFightChar.skill.gun = boarding_enemy.skill.gun;
        chr = LAi_CreateFantomCharacterEx(model, ani, "rld", sLoc);
     
  13. Modder01

    Modder01 Freebooter Storm Modder

    Joined:
    Feb 1, 2014
    Messages:
    294
    Gender:
    Male
    Location:
    Oxford, Michigan, USA
    The gun fix has made the boarding defenders more trigger happy, but the commander still refuses to return fire...Logs:
     

    Attached Files:

  14. ChezJfrey

    ChezJfrey Master Mariner Storm Modder

    Joined:
    Apr 24, 2015
    Messages:
    226
    Here is what I used to test it while standing on the pier in town. It matches the code in the boarding captain logic and works, if you keep your distance long enough:

    Code:
    void ExecuteConsole()
    {
        ref pchar = GetMainCharacter();
    
        int limit = SpawnDutchman();
        ref chr;
        string ani;
        ref boarding_enemy = &characters[limit];
        string model = LAi_GetBoardingModel(boarding_enemy, &ani);
        string sLoc = "reload1";
        TempFightChar.skill.fencing = boarding_enemy.skill.fencing;
        TempFightChar.skill.gun = boarding_enemy.skill.gun;
        chr = LAi_CreateFantomCharacterEx(model, ani, "reload", sLoc);
        if(CheckAttribute(boarding_enemy, "copyme") && sti(boarding_enemy.copyme) == 1) {
            trace("Special Character");
            ChangeAttributesFromCharacter(chr, boarding_enemy, false);
        }
    
        SetNewModelToChar(chr);
    
        LAi_group_MoveCharacter(chr, LAI_GROUP_BRDENEMY);
        LAi_group_FightGroupsEx(LAI_GROUP_PLAYER, LAI_GROUP_BRDENEMY, true, nMainCharacterIndex, -1, false, false);
        LAi_group_SetCheckEvent(LAI_GROUP_BRDENEMY);
        Log_SetStringToLog("Executed Console");
    
    }
    If it doesn't work in the cabin, I don't know why that would occur.
     
  15. Modder01

    Modder01 Freebooter Storm Modder

    Joined:
    Feb 1, 2014
    Messages:
    294
    Gender:
    Male
    Location:
    Oxford, Michigan, USA
    Well it's no great loss if the captain doesn't do that... At least the boarding defenders are shooting correctly now... :p... Next on the list is the win conditions. They are not working at all...
     
  16. ChezJfrey

    ChezJfrey Master Mariner Storm Modder

    Joined:
    Apr 24, 2015
    Messages:
    226
    In void ChangeAttributesFromCharacter, add:

    Code:
    if (CheckAttribute(PastChref, "SuperShooter"))
        {
           CopyChref.SuperShooter         = PastChref.SuperShooter;
       }
    In SpawnDutchman(), add:

    characters[qChar].SuperShooter = true;

    In LAi_fightparams.c, float LAi_NPC_GetFireActive(), change:
    Code:
    float LAi_NPC_GetFireActive()
    {
        float MOD_SKILL_ENEMY_RATE = 3.0;
    
       aref chr = GetEventData();
       float level = LAi_GetCharacterGunLevel(chr);
       npc_return_tmp = 0.001 + level*0.06;
       // boal íàøè îôèöåðû ïóëÿò èç âñåõ ñòâîëîâ -->
       if (chr.chr_ai.group == LAI_GROUP_PLAYER)
       {
            npc_return_tmp = 0.38 + npc_return_tmp;
       }
       else
       {
       // boal íàøè îôèöåðû ïóëÿò èç âñåõ ñòâîëîâ <--
           if (CheckAttribute(chr, "SuperShooter"))
           {
               npc_return_tmp = npc_return_tmp + 0.4 * MOD_SKILL_ENEMY_RATE / 10.0;
           }
           else
           {
               npc_return_tmp = npc_return_tmp + 0.1 * MOD_SKILL_ENEMY_RATE / 10.0;
           }
       }
       //if (npc_return_tmp > 0.5) npc_return_tmp = 0.5;
    
       if(!iArcadeFencingAI)
       {
           npc_return_tmp = npc_return_tmp  +  0.03;
           //if (npc_return_tmp > 0.5) npc_return_tmp = 0.5;
       }
    
       return npc_return_tmp;
    }
    To debug win conditions, in interface\ransack_main.c:
    Code:
    void ProcessCancelExit()
    
    if(n<0) {
           trace("ransack n is zero " + refEnepchararacter.id);
           ShipDead(sti(refEnepchararacter.index),KILL_BY_ABORDAGE,sti(pchar.index));
       } else {
           trace("ransack n is other " + refEnepchararacter.id);
    ....
    
    quests_check.c

    Code:
    case "NPC_Death":
       trace("NPC_Death " + refcharacter.id);
           return CharacterIsDead(refCharacter);
       break;
    
     
  17. Modder01

    Modder01 Freebooter Storm Modder

    Joined:
    Feb 1, 2014
    Messages:
    294
    Gender:
    Male
    Location:
    Oxford, Michigan, USA
    Latest Run Logs:
     

    Attached Files:

  18. ChezJfrey

    ChezJfrey Master Mariner Storm Modder

    Joined:
    Apr 24, 2015
    Messages:
    226
    I kind of suspected it would be here...should have probably had you do this to begin with. Slight addition and change in the ransack_main, swap the order and add hp:

    ShipDead(...
    trace("ransack n is zero " + refEnepchararacter.id + ", " + refEnepchararacter.chr_ai.hp);

    I suspect we will not see a zero for hp.
     
  19. Modder01

    Modder01 Freebooter Storm Modder

    Joined:
    Feb 1, 2014
    Messages:
    294
    Gender:
    Male
    Location:
    Oxford, Michigan, USA
    We do see a Zero..
    Logs for Changed code:
     

    Attached Files:

  20. ChezJfrey

    ChezJfrey Master Mariner Storm Modder

    Joined:
    Apr 24, 2015
    Messages:
    226
    Yep. Turns out my suspicion was not even close. It's because OnQuestComplete is called, and it's missing your Dutch Encounter. This should get everything...find and change the following to add DutchEncounterQuestComplete:

    battle_interface/utils.c

    Code:
    void procTimerTimeOut()
    {
       QuestComplete(objTimerInterface.questtype, objTimerInterface.questname);
       StoryLineQuestComplete(objTimerInterface.questtype, objTimerInterface.questname);
       DutchEncounterQuestComplete(objTimerInterface.questtype, objTimerInterface.questname);
    }
    quests_check.c

    Code:
    void OnQuestComplete(aref quest, string sQuestname)
    {
       if(!CheckAttribute(quest,"over") && CheckAttribute(quest,"win_condition"))
       {
           quest.over = "yes";
           QuestComplete(quest.win_condition, sQuestName);
           StoryLineQuestComplete(quest.win_condition, sQuestName);
           DutchEncounterQuestComplete(quest.win_condition, sQuestName);
       }
    }
    
    void OnQuestFailed(aref quest, string sQuestName)
    {
       if(CheckAttribute(quest,"fail_condition"))
       {
           quest.over = "yes";
           QuestComplete(quest.fail_condition, sQuestName);
           StoryLineQuestComplete(quest.fail_condition, sQuestName);
           DutchEncounterQuestComplete(quest.fail_condition, sQuestName);
       }
    }
    
     

Share This Page