Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ambient dialogs of rogue not available #166

Merged
merged 1 commit into from Oct 31, 2021
Merged

Ambient dialogs of rogue not available #166

merged 1 commit into from Oct 31, 2021

Conversation

AmProsius
Copy link
Owner

@AmProsius AmProsius commented Oct 10, 2021

Describe the bug
Two ambient dialogs of a rogue in the New Camp are not available due to a missing variable set.

Expected behavior
Ambient dialogs of a rogue in the New Camp are now available.

Additional context

FUNC INT Info_ORG_829_SpecialInfo_Condition()
{
if (Org_829_GotJoint == TRUE)
{
return 1;
};
};

FUNC INT Info_ORG_829_PERM_Condition()
{
if (Org_829_GotJoint == TRUE)
{
return 1;
};
};

@AmProsius AmProsius added validation: required provided fix labels Feb 28, 2021
@AmProsius
Copy link
Owner Author

@AmProsius AmProsius commented Feb 28, 2021

if ( (Npc_HasItems(other,ItMiJoint_1)>0) || (Npc_HasItems(other,ItMiJoint_2)>0) || (Npc_HasItems(other,ItMiJoint_3)>0) )
{
if (Npc_HasItems(other,ItMiJoint_1))
{ B_GiveInvItems (other,self,ItMiJoint_1,1); }
else if (Npc_HasItems(other,ItMiJoint_2))
{ B_GiveInvItems (other,self,ItMiJoint_2,1); }
else if (Npc_HasItems(other,ItMiJoint_3))
{ B_GiveInvItems (other,self,ItMiJoint_3,1); };
AI_Output (self, other,"Info_ORG_829_OfferJoint_06_01"); //Sure! Are you one of the dealers from the Sect Camp or what?
NC_Joints_verteilt = NC_Joints_verteilt + 1;
}

changed to

    if ( (Npc_HasItems(other,ItMiJoint_1)>0) || (Npc_HasItems(other,ItMiJoint_2)>0) || (Npc_HasItems(other,ItMiJoint_3)>0) )
    {
        if      (Npc_HasItems(other,ItMiJoint_1))
        {   B_GiveInvItems (other,self,ItMiJoint_1,1);   }
        else if (Npc_HasItems(other,ItMiJoint_2))
        {   B_GiveInvItems (other,self,ItMiJoint_2,1);   }
        else if (Npc_HasItems(other,ItMiJoint_3))
        {   B_GiveInvItems (other,self,ItMiJoint_3,1);   };

        AI_Output (self, other,"Info_ORG_829_OfferJoint_06_01"); //Sure! Are you one of the dealers from the Sect Camp or what?

        NC_Joints_verteilt = NC_Joints_verteilt + 1;
        Org_829_GotJoint = TRUE;
    }

@szapp
Copy link
Collaborator

@szapp szapp commented Apr 5, 2021

A downside of the suggested fix is, that it will not take effect on savegames where the dialog had already been spoken. I think that is a problem, because we could no longer claim that the fixes are applied irrespective of the savegame/story progression.

@AmProsius
Copy link
Owner Author

@AmProsius AmProsius commented Apr 6, 2021

Can't we check if Info_ORG_829_OfferJoint_06_01 has already been spoken at least once and then set the variable manually? The variable would have to be resetted on saves of course.

@szapp
Copy link
Collaborator

@szapp szapp commented Apr 6, 2021

UPDATE I might have misread your suggestion. You are proposing to not check if the dialog has been told but if the specific output unit Info_ORG_829_OfferJoint_06_01 has been spoken? That cannot be checked. Gothic does not keep track of whether individual output units have been triggered - only full dialogs by their info instance.

I think that would be equivalent to replacing the condition Org_829_GotJoint == TRUE with Npc_KnowsInfo(hero, Info_ORG_829_OfferJoint), no need to bother with the variable. I have thought about that too, but there is a problem. The dialog having been told does not mean that the player gave the NPC a joint (see the if-condition within the dialog info function).

At the moment I don't see a way of enabling these two unavailable dialogs without introducing other inconsistencies or while keeping the patch savegame-independent.

Since the NPC does not immediately use the joint I thought we could check if the info was told and the NPC has a joint in their inventory. Unfortunately, he may smoke it during his daily routine (see below).

func void B_ChooseJoint (VAR C_NPC self)
{
PrintDebugNpc (PD_TA_DETAIL, "B_ChooseJoint");
self.aivar[AIV_ITEMSTATUS] = TA_IT_JOINT;
if (Npc_HasItems (self,ItMiJoint_1) == 0)
{
CreateInvItem (self,ItMiJoint_1);
};
AI_UseItemToState ( self, ItMiJoint_1,0);
self.aivar[AIV_ITEMFREQ]=1;
};

@szapp
Copy link
Collaborator

@szapp szapp commented Apr 6, 2021

If I am not mistaken, Gothic may actually save how often an output unit was played. I'm really not sure yet, but that would solve so many problems (e.g. all the dialogs where permanent is illegally set). I will investigate when I have the time!

Update: This information is not persistent. There is no way to reliably check whether an individual output unit was spoken.

@szapp
Copy link
Collaborator

@szapp szapp commented Apr 27, 2021

Going back to this issue, I think we will need to compromise.

In the original game the NPC ORG_829_Organisator is exclusively appointed the state ZS_GuardPassage in their daily routine. If nothing was changed about that state, the NPC will never smoke. That, in turn means, we could assume that if the dialog Info_ORG_829_OfferJoint was spoken and the NPC has a joint in their inventory, that the player gave it to them.

Although not an ideal solution, it is a robust one as far as the original scripts are concerned. So I suggest to change the dialog conditions:

FUNC INT Info_ORG_829_SpecialInfo_Condition()
{
if (Org_829_GotJoint == TRUE)
{
return 1;
};
};

changed to

FUNC INT Info_ORG_829_SpecialInfo_Condition() 
{ 
    if (Org_829_GotJoint == TRUE)
    || ((Npc_KnowsInfo(hero, Info_ORG_829_OfferJoint)) && ((Npc_HasItems(self, ItMiJoint_1))
                                                       ||  (Npc_HasItems(self, ItMiJoint_2))
                                                       ||  (Npc_HasItems(self, ItMiJoint_3))))
    { 
        return 1; 
    }; 
}; 

and

FUNC INT Info_ORG_829_PERM_Condition()
{
if (Org_829_GotJoint == TRUE)
{
return 1;
};
};

changed to

FUNC INT Info_ORG_829_PERM_Condition() 
{ 
    if (Org_829_GotJoint == TRUE)
    || ((Npc_KnowsInfo(hero, Info_ORG_829_OfferJoint)) && ((Npc_HasItems(self, ItMiJoint_1))
                                                       ||  (Npc_HasItems(self, ItMiJoint_2))
                                                       ||  (Npc_HasItems(self, ItMiJoint_3))))
    { 
        return 1; 
    }; 
}; 

This, of course, entails to check if these items exist. In a script hook of these dialog conditions, return false when the inverse of the added condition is true (as we usually do in these info condition script hooks).

@szapp szapp added compatibility: easy impl: hook script func type: session fix labels Apr 27, 2021
@szapp szapp added this to Dialog: Info condition in Fix templates Apr 27, 2021
@AmProsius AmProsius added this to the v1.2.0 milestone May 7, 2021
@AmProsius AmProsius added this to To Do in v1.2.0 via automation May 7, 2021
@AmProsius AmProsius self-assigned this May 7, 2021
@AmProsius AmProsius moved this from To Do to In Progress in v1.2.0 Oct 10, 2021
@AmProsius AmProsius requested a review from szapp Oct 10, 2021
@AmProsius AmProsius removed their assignment Oct 10, 2021
@AmProsius
Copy link
Owner Author

@AmProsius AmProsius commented Oct 10, 2021

It's a cool feeling to finally hear dialogs I've never heard before!

@AmProsius AmProsius added validation: validated and removed validation: required labels Oct 10, 2021
@AmProsius AmProsius removed the request for review from szapp Oct 31, 2021
@AmProsius AmProsius merged commit 4f1e261 into master Oct 31, 2021
@AmProsius AmProsius deleted the bug166 branch Oct 31, 2021
v1.2.0 automation moved this from In Progress to Done Oct 31, 2021
Copy link
Collaborator

@szapp szapp left a comment

I know this fix already found its way into the release, but we should revise it. I didn't have the time to review it until now. We can discuss how to improve it here.

cond4 = !Npc_HasItems(self, joint3Id);

// Return false if either of the conditions is true
if (cond1) || (cond2 && cond3 && cond4) {
Copy link
Collaborator

@szapp szapp Jan 10, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This if-condition might cause issues. It will prevent the dialog from appearing if the variable is Org_829_GotJoint is true but the NPC no longer has the items. We will have to revise this if-condition. We can brain storm some ideas here.

Since we are adding an or-condition, it is dangerous to prematurely return false. Likewise, it is dangerous to return true, because a mod could have added new conditions in the dialog condition function.

I wonder if it will be enough to just change the order: Run the original function first (use ContinueCall() in the beginning and collect its return value). If the return value is true, return true, if it is false, add our new conditions and return true/false. If I am not mistaken we might have done this in a few fixes. Maybe we can find those dialog fixes.

Copy link
Owner Author

@AmProsius AmProsius Jan 18, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually this is how we handled these types of issues in the past (see #66 for reference). We should revisit these fixes as well then.

I can also do something like we did in #96.

Copy link
Collaborator

@szapp szapp Jan 18, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree with the comment about #66. That may be worth worrying about, if the dialog was an important one and is likely to be changed in a mod. Here - you are right - there is no need to overthink it.

Nevertheless, the issue I mentioned in the first paragraph in the comment above should be addressed. And I think your suggestion with #96 sounds great.

What we should do is check if the variable that is used to check whether the joint has been given is false. If so, check if the dialog was told and the NPC has either of the items and then set the variable to true. After that (irrespective of the check of the variable) the original function should be triggered.

/*
* #166 Ambient dialogs of rogue not available
*
* There does not seem an easy way to test this fix programmatically, so this test relies on manual confirmation.
Copy link
Collaborator

@szapp szapp Jan 10, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There should actually be a way to check this with an automatic test. As found in similar tests, set the dialog Info_ORG_829_OfferJoint to told, trigger the condition function, and check its return value.

@AmProsius AmProsius restored the bug166 branch Jan 13, 2022
@AmProsius AmProsius added this to In Progress in v1.3.0 via automation Jan 13, 2022
@AmProsius AmProsius removed this from the v1.2.0 milestone Jan 13, 2022
@AmProsius AmProsius added this to the v1.3.0 milestone Jan 13, 2022
@AmProsius AmProsius self-assigned this Jan 13, 2022
AmProsius added a commit that referenced this issue Jan 18, 2022
@szapp szapp moved this from Modify dialog conditions to Add dialog conditions in Fix templates Feb 6, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
compatibility: easy impl: hook script func provided fix type: session fix validation: validated
Projects
Fix templates
Add dialog conditions
v1.3.0
  
In Progress
v1.2.0
  
Done
Development

Successfully merging this pull request may close these issues.

None yet

2 participants