Enable dialogue if player has looked at an object

Started by timebandit, Fri 08/01/2021 11:45:15

Previous topic - Next topic

timebandit

I want to make it so that cPlayer has to have had looked at an object, oHouse, before dKing2 happens.

I know what I would write if dKing2 was enabled by a dialogue option from another dialogue:
Code: ags

Function cKing_Interact
{
if (dTroll.HasOptionBeenChosen(1))
{dKing2.Start();
}
else {dKing1.Start();}
}


So for necessary dialogues, I would need
"dTroll.HasOptionBeenChosen(number)".

And for necessary inventory items, I would need
"Player.HasInventory(iFootball)".

But what do I need to write if I want dKing2 to happen after cPlayer has looked at an object?

I haven't been able to find the answer in the manual, unlike the other two "conditions" I've mentioned here.

I searched the forums and found someone writing "(UsedAction (A_LOOK_AT))" but it didn't work for me and it was only written once on this forum.

eri0o

You can create a global boolean variable like has_looked_at_house and set it to true after the player has done the action you want and just check for it when interacting with the King character. If you go this route there is a global variable menu in Project Explorer that should help making this easier.

See adventuregamestudio.github.io/ags-manual/GlobalVariables.html

If both the interactions (looking at the house and interacting with the king) are in the same room, then you don't even need a global variable at all, just declare the boolean variable at the top of the room script and set and check it in the appropriate look and interact functions. edit: I just remembered that character interactions are always in global script, while the object will be in Room Script. :/

isatche

I would use variables here. Add something like: int look=0; at the very top
When the character looks at that something, add this line below the look description: look=1;
The you just check if (look==1) {dKing2.Start();} else {dKing1.Start();}

I hope it helps :)

P.S. I didn't test the code, it's just the path I would take.

timebandit

Thanks to both of you. I haven't really understood how I create and define a global variable yet so I guess I'll have to understand that before I can proceed with your solutions.

Khris

The Global Variables pane is part of the project tree in the editor. Open it and right-click the empty list to create a new variable.

timebandit

But how do I tell AGS that the variable "has_looked_at_object" is supposed to relate to the player looking at the object? How do I define what the variable actually relates to?

Khris

You don't have to do that at all, you set the variable when you want it to change, and you read the variable when you want to know its value.
If you're concerned with remembering what the variable is used for, use a name like "player_has_looked_at_weird_box_in_ante_room".

Manu

Quote from: timebandit on Tue 19/01/2021 16:36:45
But how do I tell AGS that the variable "has_looked_at_object" is supposed to relate to the player looking at the object? How do I define what the variable actually relates to?

I know that people more expert than me will disagree, but this is why I prefer to use the custom properties of the objects. In my case I have defined a new boolean property called "hasBeenExamined" and it applies to all objects. This way I can do something like:

Code: ags

if (oNotebook.GetProperty("hasBeenExamined")) {
   dDialog1.Start();
}
else {
   cCharacter.Say("Can't talk right now");
}


I believe it's more readable even thought the fact that there is no autocomplete/syntax check on the name of the property is annoying.

Crimson Wizard

#8
Quote from: emabolo on Wed 20/01/2021 18:29:07
I know that people more expert than me will disagree

Not at all, since custom properties were made precisely to be able to attach something new to game objects. The way they are currently made is not convenient for giving unique traits to individual objects, so that's a matter of compromise.

The biggest limitation of custom property actually is that it can only be an integer number or String, and nothing else. Also, as its bound to object, you cannot access it if the object is in another room.

timebandit

Quote from: emabolo on Wed 20/01/2021 18:29:07

I know that people more expert than me will disagree, but this is why I prefer to use the custom properties of the objects. In my case I have defined a new boolean property called "hasBeenExamined" and it applies to all objects. This way I can do something like:

Code: ags

if (oNotebook.GetProperty("hasBeenExamined")) {
   dDialog1.Start();
}
else {
   cCharacter.Say("Can't talk right now");
}


Could you write a step-by-step guide of what you do when creating the variable "hasBeenExamined" and making it work? Like, first you click "create global variable" or what it now says on the sidebar. What do you do after that?

Khris

emabolo is doing precisely not that but creating custom properties instead.

Here's how: https://www.adventuregamestudio.co.uk/manual/ags19.htm#topic30

Manu

Quote from: timebandit on Wed 27/01/2021 11:19:35
Could you write a step-by-step guide of what you do when creating the variable "hasBeenExamined" and making it work? Like, first you click "create global variable" or what it now says on the sidebar. What do you do after that?

Sorry for the delay, I didn't see your post, I hope you have already solved it. Anyway, just in case, here you have some more info

First, you have to define your new custom property. You do it by selecting an object (or hotspot, or inventory item) and accessing the Properties grid on the bottom right of the screen. Double-click "(Properties)" to open the definition of the custom properties. Initially, you won't see anything, so click  "Edit Schema" and then with a right-click, Add New Property. You can choose the type (for example "bool") and the default value (use "0", not "false").

What is important to understand, is that the properties are shared. If you create a property "hasBeenExamined" for the oKettle object, all the other objects can start using a new property called "hasBeenExamined", not just the kettle. But you can choose if the property applies only to objects, or also to hotspots for example. I normally select both inventory items and objects.

Now, in your code, you can do something like this:

Code: ags

oKettle_Look() {
 if (oKettle.GetProperty("hasBeenExamined") == 1) {
  player.Say("I already examined the kettle.");
 }
 else {
  player.Say("What a nice kettle!");
  oKettle.SetProperty("hasBeenExamined", 1);
 }
}


It's a bit ugly that you have to use double quotes, and the fact that there is no autocomplete, but you just need to be careful. Also, since the definition is shared, it's not a good idea to do something like "maxSpeed" for the object "car", "numBullets" for the object "gun", "inkColor" for the object "pencil"  and things like that. But for generic properties, especially boolean, like "isEmpty", "hasBeenUsed", "hasBeenExamined", and so on, I believe it's a good choice.


Crimson Wizard

#12
Quote from: emabolo on Mon 01/02/2021 15:17:32
It's a bit ugly that you have to use double quotes, and the fact that there is no autocomplete, but you just need to be careful.

I posted this in another recent thread where similar problem was brought up: you can declare macros for your strings, then you'll have autocomplete + compiler will detect if you use wrong name by mistake.

For example:
Code: ags

#define PROP_HASBEENEXAMINED "hasBeenExamined"


and then use it like
Code: ags

oKettle.GetProperty(PROP_HASBEENEXAMINED);

Kyrridas

sort of related:

is it possible to call a variable within the same dialogue? something like this, but that actually works:

Code: ags

@S
  if (TriedTheDoor == true){
  Option-on 4
  }


obviously that doesnt work because Option-on is dialog scripting that doesnt get along with normal scripting. so is there scripting (in either 'language') that would accomplish this task? it seems like it would be a pretty common adventure game mechanic.

my knee-jerk reaction is to simply create two dialogs that are identical, except for the additional option, and simply call the appropriate one when conversation is started. but that seems needlessly heavy-handed.


basically, the player can ask a bartender for a suggestion on how to proceed. and once you've tried his suggestion, talking to him again should give an option for "hey, i tried that thing and it didnt work", to which he replies with a different suggestion.

Crimson Wizard

Quote from: Kyrridas on Mon 08/02/2021 02:49:21
sort of related:

is it possible to call a variable within the same dialogue? something like this, but that actually works:

Code: ags

@S
  if (TriedTheDoor == true){
  Option-on 4
  }


obviously that doesnt work because Option-on is dialog scripting that doesnt get along with normal scripting. so is there scripting (in either 'language') that would accomplish this task?

Yes ofcourse, just remove indentation from "option-on".

Dialog scripts are treated like this: if command has no indentation - that's special dialog command, if it has indentation - that's regular script command.
Kind of primitive parsing, but guess that was easiest to do at the time...

Kyrridas

well, dang. that's easy enough. i figured indented and undented (is that a word?) scripting wouldn't function together like that. just tried it, works fine. thanks!

Crimson Wizard

#16
The dialog scripts are secretly converted into normal script during game compilation, so every option-on etc command ends up being either a regular script statement or a call to script function, like Dialog.SetOptionState.
Indentation rule there is only to make it easier for editor to distinguish them.

SMF spam blocked by CleanTalk