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

Fixed Drinking and Gambling at the Tavern

Would using LAi_FindRandomLocator("sit") be of any help? If I recall, that function should only return empty locators.

It might be...:unsure if I'm going to look at getting PChar to only sit at vacant spaces, :drunk which is where this is heading :). Is there an equivalent test to find if a specific locator is already occupied?

There IS a bedroom angle there which works once you reach rank 4/5. @Levis definitely made some updates to that as well.
I think I looked at that :loveand it doesn't seem to involve the "without_money" dialogue cases (and reputation loss) as it stands. I will continue to search as I work on the sitting problem but am tempted just to change the code for the other taverns to what I did for FdF with the waitress, take out the -1 reputation tweak the dialogue a little and see if anyone finds it a problem.
 
Yeah there is a bedroom part indeed and i reused a line. Change it if you want. If you talk to the officiant sometimes she offers a sample of her charms. If you accept it you will see the dialog.
 
It might be...:unsure if I'm going to look at getting PChar to only sit at vacant spaces, :drunk which is where this is heading :). Is there an equivalent test to find if a specific locator is already occupied?
@Levis would know that better since he rewrote the LAi_FindRandomLocator function.
It is defined in PROGRAM\Loc_ai\LAi_utils.c if you want to see what it does.

This one might be interesting too:
Code:
string LAi_FindNearestFreeLocator(string group, float x, float y, float z)

I'm not seeing a specific function that checks if a specific locator is occupied though.

I think I looked at that :loveand it doesn't seem to involve the "without_money" dialogue cases (and reputation loss) as it stands. I will continue to search as I work on the sitting problem but am tempted just to change the code for the other taverns to what I did for FdF with the waitress, take out the -1 reputation tweak the dialogue a little and see if anyone finds it a problem.
I think I traced where it's used. From Habitue_dialog.c:
Code:
    case "sit_case_4_exit":
       Diag.CurrentNode = Diag.TempNode;
       DialogExit();
       pchar.quest.friend_in_tavern = npchar.id;
       AddDialogExitQuest("without_memory");
     break;
Then quests_common.c:
Code:
    case "without_memory":
       LAi_Fade("exit_sit_2", "saved_by_off");
     break;
[...]
    case "saved_by_off":
       LAi_SetStayType(pchar);
       AddMoneyToCharacter(pchar, -100);
       homelocation = pchar.location;
       switch(homelocation)
       {
         case "Redmond_tavern":
           PlaceCharacter(characterFromID("Redmond_officiant"), "goto");
           characters[GetCharacterIndex("Redmond_officiant")].dialog.currentnode = "without_money"; // <-------------------- HERE -------------------------
           LAi_SetActorType(characterFromID("Redmond_officiant"));
           LAi_ActorDialog(characterFromID("Redmond_officiant"), pchar, "officiant_back_to_citizen", 5.0, 1.0);
         break;
Looks to be related to drinking in the tavern.
 
I'm not seeing a specific function that checks if a specific locator is occupied though

Right. I was hoping there would be, to use in the hard coded examples to check if they are occupied before looking for an alternative (since they are obviously the "best" positions to use). Never mind I'll see how the functions you named behave.

I think I traced where it's used. From Habitue_dialog.c:. Looks to be related to drinking in the tavern.

Yes I know that's "my" drinking case - so hopefully it's just the slightly inappropriate dialogue and reputation loss that looked a bit odd and led me to think it might be "borrowed" from another use. :shrug

OK I'll leave you in peace and crack on with trying to sort sitting at tables :type1
 
I believe there are also functions to find free locators. Search that file and you'll find them I hope
 
:ahoyTurns out this was all stock game POTC code so I needn't have worried about it looking odd - it always was! :(

I have set up a check of the coordinates of the preferred sit locator. :checklistIf that is occupied it searches for the nearest free sit locator, however I have additional hard coded checks that the locator found is at the same table. If this fails it defaults to "sitting" where you began the dialogue. [That is why if you go behind someone to speak to them you end up "sitting" behind them].

I have tweaked the positions of a couple of locators (just by fractions so it shouldn't affect anything else so that the nearest sit locator is not at the next table in a couple of cases.

I haven't touched the "habitue.location" default which could indeed put you at a distant table if the circumstances are unfavourable and the tavern crowded since it only finds the nearest free sit locator. However for the two taverns that have regular occupants (Tortuga and Point-a-Pietre) there is hardcoding for where you will sit. The rest are pretty empty so probably don't often cause problems.

It would have been easier if the locators were put in the GM file in the same order as their labels - then the index which could be used to call up the coordinates would be more logical. Even better would be if the locators had been grouped 11,12,13,14 at table 1, 21,22,23,24 at table 2 and so on....! but too much work to do that now with all the impacts of changed locatore references.:fiddler

However on the "nice to do" list for build 15 would be to add some more locators at tables that only have two currently - which would reduce the fake "sitting" in thin air occurences. FdF for example often puts the NPC drinking/ gambling character opposite the smuggling agent on a table with only two locators.:nogood

I have also added the changes to officiant behaviour for all taverns.

The QC_brothel seems a complete pigs ear - copied code with no actual dialogues, location or locators as far as I can see, :shock I kept well clear of that!
 

Attachments

  • drinking fix.7z
    38.6 KB · Views: 148
Re-reading the thread to make sure I hadn't missed anything I picked up on this

Would using LAi_FindRandomLocator("sit") be of any help? If I recall, that function should only return empty locators.
But of course that doesn't mean it is a locator near to where you were standing
(my emphasis).

The tests I was applying were looking for the nearest locator to the NPC - perhaps a combination with a PChar location test if the first fails could be added to further increase the chance of getting a proper "sit at the right table in empty space".

Put what I have done so far in for now - I'll look at the extra possibility and be back later (likely much later because I'm pretty much fully occupied for the next three weeks after tomorrow).
 
I've now just added this into my game; you've been working really hard at this, haven't you?
Thanks a lot for your efforts! :bow

I suppose this one can go to "Needs Testing" now, right?
 
I've now just added this into my game; you've been working really hard at this, haven't you?
Thanks a lot for your efforts! :bow

I suppose this one can go to "Needs Testing" now, right?

Yep Lots of trial and even more error. :modding I still haven't really fully grasped attributes and indexes :confused: but I'm getting there.

Certainly does need testing!!
 
If there's anything we can help with just ask. :yes
Thanks for that, unfortunately currently most of my questions are in the vein of "why didn't that work?" to which the answer is more often than not "Bad syntax". I think if I was starting again my persona would be more appropriate as B(r))ad Syntax.

On that note @Pieter Boelen thanks for catching the typos - there was another one in a couple of sit locators being sirX locators (probably slipped in from the correct titles thread) which would only show through not being actioned where appropriate, don't know if you caught it because I'm only just uploading the latest version.

Anyway here is a further attempt with a PChar (well actually GetMainCharacter) location nearest available sit locator search added in for two instances (large and small taverns) where it should cover using the fourth spot at a table. No doubt during winmerge you will keep an eye out for any additional gaffs.
 

Attachments

  • quests_common.7z
    31.1 KB · Views: 134
Indeed I didn't notice the sirX ones. Thanks for catching that one! :cheers
 
Oh, an extra note about the sections of code like this:
Code:
      switch(pchar.location)
       {
         case "Redmond_tavern":
           if (characters[GetCharacterIndex(pchar.quest.friend_in_tavern)].location.locator == "sit1")
           {
             float lx = -0.169727
             float ly = 0.008688494;
             float lz = 6.345457;
             if((CheckLocationPosition(loadedLocation, lx,ly,lz))==true) ChangeCharacterAddressGroup(pchar, "Redmond_tavern", "sit", "sit11");break; // SPECIFICALLY THIS LINE
             GetCharacterPos(characters[GetCharacterIndex(pchar.quest.friend_in_tavern)], &x, &y, &z);
             nearloc = LAi_FindNearestFreeLocator("sit", x, y, z);
             if (nearloc=="sit9" ) ChangeCharacterAddressGroup(pchar, "Redmond_tavern", "sit", "sit9");
           }
           if (characters[GetCharacterIndex(pchar.quest.friend_in_tavern)].location.locator == "sit3")
           {
             lx =-0.2043872;
             ly = 0.02849323;
             lz = 5.419554;
             if((CheckLocationPosition(loadedLocation, lx,ly,lz))==true) ChangeCharacterAddressGroup(pchar, "Redmond_tavern", "sit", "sit2");break;
             GetCharacterPos(characters[GetCharacterIndex(pchar.quest.friend_in_tavern)], &x, &y, &z);
             nearloc = LAi_FindNearestFreeLocator("sit", x, y, z);
             if (nearloc=="sit12" ) ChangeCharacterAddressGroup(pchar, "Redmond_tavern", "sit", "sit12");
             if (nearloc=="sit13" ) ChangeCharacterAddressGroup(pchar, "Redmond_tavern", "sit", "sir13");
           }
         break;
Using "break" statements anywhere within the quest code can cause on-screen error messages.
Reason is that this line at the end of the quest code isn't executed:
Code:
PChar.questnotfound = true; // PB: Testing
We've had that before. :facepalm
 
Has anyone been making use of the "sitting at various taverns" options? Any problems with it anymore?
I'd really quite like to call it "Fixed"! :cheers
 
Oh, an extra note about the sections of code like this:
Code:
      switch(pchar.location)
       {
         case "Redmond_tavern":
           if (characters[GetCharacterIndex(pchar.quest.friend_in_tavern)].location.locator == "sit1")
           {
             float lx = -0.169727
             float ly = 0.008688494;
             float lz = 6.345457;
             if((CheckLocationPosition(loadedLocation, lx,ly,lz))==true) ChangeCharacterAddressGroup(pchar, "Redmond_tavern", "sit", "sit11");break; // SPECIFICALLY THIS LINE
             GetCharacterPos(characters[GetCharacterIndex(pchar.quest.friend_in_tavern)], &x, &y, &z);
             nearloc = LAi_FindNearestFreeLocator("sit", x, y, z);
             if (nearloc=="sit9" ) ChangeCharacterAddressGroup(pchar, "Redmond_tavern", "sit", "sit9");
           }
           if (characters[GetCharacterIndex(pchar.quest.friend_in_tavern)].location.locator == "sit3")
           {
             lx =-0.2043872;
             ly = 0.02849323;
             lz = 5.419554;
             if((CheckLocationPosition(loadedLocation, lx,ly,lz))==true) ChangeCharacterAddressGroup(pchar, "Redmond_tavern", "sit", "sit2");break;
             GetCharacterPos(characters[GetCharacterIndex(pchar.quest.friend_in_tavern)], &x, &y, &z);
             nearloc = LAi_FindNearestFreeLocator("sit", x, y, z);
             if (nearloc=="sit12" ) ChangeCharacterAddressGroup(pchar, "Redmond_tavern", "sit", "sit12");
             if (nearloc=="sit13" ) ChangeCharacterAddressGroup(pchar, "Redmond_tavern", "sit", "sir13");
           }
         break;
Using "break" statements anywhere within the quest code can cause on-screen error messages.
Reason is that this line at the end of the quest code isn't executed:
Code:
PChar.questnotfound = true; // PB: Testing
We've had that before. :facepalm
I'm not an expert programmer so I'm probably missing something, but it seems to me that the 'break' statement will exit the 'switch(pchar.location)' block and execution should then pass to whatever comes after the switch. If it doesn't hit that 'break' command because the 'if((CheckLocationPosition(loadedLocation, lx,ly,lz))==true)' condition has failed then it should get to the end of the case and hit a 'break' anyway. The 'PChar.questnotfound = true;' line is right at the end of the quest code file and is only reached if the outer switch which looks for the quest case has not recognised the quest name and triggered the appropriate quest case.

What bothers me is that I always thought that if several statements were conditional upon an 'if' passing then they need to be enclosed in brackets. Without the brackets, I'd have thought that only the first statement after the 'if' is affected by the condition. So if '(CheckLocationPosition(loadedLocation, lx,ly,lz))==true' passes then it will execute 'ChangeCharacterAddressGroup(pchar, "Redmond_tavern", "sit", "sit11")' - and then, regardless of the condition, it will hit the 'break' and skip the rest of the code in this case block. I'd have had:
Code:
if((CheckLocationPosition(loadedLocation, lx,ly,lz))==true)
{
ChangeCharacterAddressGroup(pchar, "Redmond_tavern", "sit", "sit11");
break;
}
 
I'm not an expert programmer so I'm probably missing something, but it seems to me that the 'break' statement will exit the 'switch(pchar.location)' block and execution should then pass to whatever comes after the switch. If it doesn't hit that 'break' command because the 'if((CheckLocationPosition(loadedLocation, lx,ly,lz))==true)' condition has failed then it should get to the end of the case and hit a 'break' anyway. The 'PChar.questnotfound = true;' line is right at the end of the quest code file and is only reached if the outer switch which looks for the quest case has not recognised the quest name and triggered the appropriate quest case.
You are very much correct.
I also misremembered; the problem I was referring to is when using "return" which stops the execution of the entire function altogether and DOES prevent the process from completing as intended.

What bothers me is that I always thought that if several statements were conditional upon an 'if' passing then they need to be enclosed in brackets. Without the brackets, I'd have thought that only the first statement after the 'if' is affected by the condition. So if '(CheckLocationPosition(loadedLocation, lx,ly,lz))==true' passes then it will execute 'ChangeCharacterAddressGroup(pchar, "Redmond_tavern", "sit", "sit11")' - and then, regardless of the condition, it will hit the 'break' and skip the rest of the code in this case block. I'd have had:
Code:
if((CheckLocationPosition(loadedLocation, lx,ly,lz))==true)
{
ChangeCharacterAddressGroup(pchar, "Redmond_tavern", "sit", "sit11");
break;
}
I do believe you've got a valid point there; not entirely sure if that second break would be executed properly because it is on the same line (unlikely).
It might indeed ALWAYS stop that switch from completion because it is second after the if-statement.

If I understand correctly what it is supposed to do, the following might be a safer alternative:
Code:
if((CheckLocationPosition(loadedLocation, lx,ly,lz))==true) // NOTE: You can do away with the "==true" altogether for all the code cares
{
ChangeCharacterAddressGroup(pchar, "Redmond_tavern", "sit", "sit11");
}
else
{
  GetCharacterPos(characters[GetCharacterIndex(pchar.quest.friend_in_tavern)], &x, &y, &z);
  nearloc = LAi_FindNearestFreeLocator("sit", x, y, z);
  if (nearloc=="sit9" ) ChangeCharacterAddressGroup(pchar, "Redmond_tavern", "sit", "sit9");
}
But I'm not sure what effect that should have; perhaps @pedrwyth could clarify.
 
I do believe you've got a valid point there; not entirely sure if that second break would be executed properly because it is on the same line (unlikely).
It might indeed ALWAYS stop that switch from completion because it is second after the if-statement.
It depends on how the compiler parses the line. A normal statement ends with ";", so it will recognise 'if (<condition>) <statement>;'. What I don't know is what it does when it finds 'if (<condition>) <statement1>; <statemen2t>;' - does it regard the first semi-colon as the end of the entire line and skip the rest, or does it regard the semi-colon merely as the end of <statement1> and then proceed onto <statement2>? Basically, 'if' conditions aside, can you have multiple statements on the same line separated by semi-colons, or does the compiler only look at one statement per line?

What happens, for example, if you have something like:
Code:
float lx = -0.169727; float ly = 0.008688494; float lz = 6.345457;
instead of having them each on a separate line?
 
It depends on how the compiler parses the line. A normal statement ends with ";", so it will recognise 'if (<condition>) <statement>;'. What I don't know is what it does when it finds 'if (<condition>) <statement1>; <statemen2t>;' - does it regard the first semi-colon as the end of the entire line and skip the rest, or does it regard the semi-colon merely as the end of <statement1> and then proceed onto <statement2>? Basically, 'if' conditions aside, can you have multiple statements on the same line separated by semi-colons, or does the compiler only look at one statement per line?

What happens, for example, if you have something like:
Code:
float lx = -0.169727; float ly = 0.008688494; float lz = 6.345457;
instead of having them each on a separate line?
I think that technically works, but I'm not at all sure how the if-statement version would behave. It is safer to use brackets in such a case.
To find out, we can use console with some LogIt lines in various configurations to see what displays and what doesn't and what causes error logs.
 
Back
Top