TEMPLATE: 9-verb MI-style 1.6.4 - Last update: 4th April 2019

Started by abstauber, Thu 17/09/2009 16:16:37

Previous topic - Next topic

WatchDaToast

Hey, I hope it`s ok to bump this thread so I can ask something :D
I have been using this awesome template for a while to create my game, and only now have I stumbled across a little problem:
So far I could not find a way to make an on-screen object usable in the same way as an inventory item. So when you choose "Use" on that object,
the GUI will Show "Use Object with...", so I can use that object with another on-screen object.
I really have no idea how to achieve something like this. D:
It would be awesome if someone here could please help me out with this! :D

Khris

The template doesn't support this; you'll have to script it yourself.

A "simple" way (or rather workaround) would be to allow the player to take the object, but when they walk away too far, remove it from their inventory again with an appropriate message (using a region to trigger that).

WatchDaToast

#242
It`s me again :grin: Thanks for your answer Khris, however I totally forgot to look around in here again as I was experimenting around with the problem I mentioned above.

I am having a new question here...
It seems to be the case that the player character automatically moves towards another character when "Talk To" is selected.
Is there a way to remove that? I am having a few situations in the game where to player is supposed to stand on his spot when he greets another character from the distance.

Edit:
I managed to accomplish what I envisioned by removing this in the GuiScript:


...and thus, turning it into this:


Did the same for the "GiveTo" command and the TalkTo-function that is called via right click.
Works fine so far, now that I can manually set the WalkTo-points in my scripts, however it feels kinda wrong to edit the template this way.
I hope there are no problems arising from this (wtf)

Khris

If you look at the start of the if block, right above the line you changed, you'll see that switching off the automatic approach is already available by setting approachCharInteract = false; at the top of guiscript.asc (together with a few other settings, like for instance the action bar's text color).

This also means that the change you made shouldn't have any unforeseen negative consequences since it has the exact same effect :)

WatchDaToast

Aah, so I could have just changed that instead. Good to know, thanks! ;-D

abstauber

Here's a small bugfix release. I actually fixed this in the repo months ago, but forgot to compile a new template. So here it is :)

Crimson Wizard

Quote from: Monsieur OUXX on Tue 03/07/2018 21:35:08
I'm trying to branch and/or create a pull request but it seems disabled in github. Have you disabled it for that project?

I don't think pulls are disabled, how do you do branching? Have you forked your own repository?

Monsieur OUXX

#247
Issue I had with git:
Spoiler

1) cloned repo locally
2) using Git's local client interface, created a branch called "objectified"
3) Made changes
4) Commited changes (to local)
5) Tried to push changes --> it prompts me for my git credentials --> OK --> then it prompts me for some "git.com" credentials
   --> KO : It says "remote: Permission to dkrey/ags_9verb-template.git denied to jeancallisti. fatal: unable to access 'https://github.com/dkrey/ags_9verb-template.git/';: The requested URL returned error: 403"

Note : 'jeancallisti' is my git account name.
[close]

EDIT: here is how I solved it :
Spoiler



- when I cloned abstauber's remote repo, I wasn't logged into git, I just took the URL as it appeared on the screen.
- because of that, the URL did not contain my username, but instead Abstauber's user name : https://github.com/dkrey/ags_9verb-template.git
- The clone and the first commit went perfect so I didn't even notice, but that url was still stored in .git/config
- I had to edit that file manually with the proper URL : https://github.com/jeancallisti/ags_9verb-template.git
- Now the push went fine and my fork is in my own remote repo.
- Off to the pull request!

https://stackoverflow.com/questions/7438313/pushing-to-git-returning-error-code-403-fatal-http-request-failed

(phew, git is the only software I've ever encountered that's at the same time very straightforward and yet causing neverending confusion and human mistakes)
[close]
 

Crimson Wizard

#248
Repositories are of course protected against direct pushes by default, otherwise anyone could modify anyone's repository at will without asking.
You need to create your own remote to be able to push there, and then create pull requests for abstauber's.

Press "Fork" button at abstrauber's page: that will create your remote copy, under your github account. Then either clone your remote to your local machine and redo your changes there (and push).
or, if you know how to configure remotes in local github repository, you could just switch path and tell it to sync with your remote instead of abstauber's.


Monsieur OUXX

#249
Is the github repo up to date? 1.6.3 is from June 2018 but the repo shows last changes from 9 months ago.
 

abstauber

Yes, the repo is up to date, I just added the tag for 1.6.3 belatedly.
I am still pondering about your pull request though. I agree that it's not very elegant to define all the settings in one giant init function and your code clean up sure is nice. On the other hand it doesn't seem very user friendly or at least I'm a bit concerned that it's so complicated that it might put users off

So instead of this
Code: ags

    CDG.uparrow_img     = 124;
    CDG.uparrow_xpos    = 137;
    CDG.init();


you have to do that
Code: ags
  
  int spriteSettings[] = CustomDialogGui.GetDefaultSettings_Sprites();
  spriteSettings[eCustomDialog_uparrow_img] = 124; //custom sprite for up arrow
  spriteSettings[eCustomDialog_uparrow_hi_img] = 137; //custom sprite for highlighted up arrow
  CDG.ApplySettings_Sprites(spriteSettings); //apply the changes
  CDG.init();


And for every other settings group you need to create a new array. So what's the benefit apart from coding zen ;)
Anyone else has an opinion on this?


Crimson Wizard

#251
Quote from: abstauber on Fri 27/07/2018 13:27:46
I am still pondering about your pull request though. I agree that it's not very elegant to define all the settings in one giant init function and your code clean up sure is nice. On the other hand it doesn't seem very user friendly or at least I'm a bit concerned that it's so complicated that it might put users off
<...>
And for every other settings group you need to create a new array. So what's the benefit apart from coding zen ;)
Anyone else has an opinion on this?

I mentioned mine here: http://www.adventuregamestudio.co.uk/forums/index.php?topic=56226.msg636589682#msg636589682
Monsieur OUXX also explained why he needs it there; idk if that's rational for everyone though.

My impression was that there must be a way to expose these variables as "property array" without having them as arrays internally. But I did not have spare time to try that idea out and make an actual example.

EDIT: What I mean by "property array", you could declare an attribute of array type like this (random example):
Code: ags

struct CustomDialog
{
    import attribute int IndexedOptions[];
}

And then implement like
Code: ags

int CustomDialog::geti_IndexedOptions(int index)
{
    if (index == 0) return dlg.background_color;
    if (index == 1) return dlg.foreground_color;
}
void CustomDialog::seti_IndexedOptions(int index, int value)
{
    if (index == 0) dlg.background_color = value;
    if (index == 1) dlg.foreground_color = value;
}

Monsieur OUXX

Yes, the core reason was to expose stuff. The thing in abstauber's module that's most likely to be changed immediately after importing are the sprites and other settings. Thzrefore I exposed that part.
Ultimately that allows to set up your game around the module without having to modify the module's code (that would not be a problem with other languages, but with AGS it's a nightmare to have to re-import and re-modify an imported third-party module every time it's modified by its creator).

Quote from: abstauber on Fri 27/07/2018 13:27:46
for every other settings group you need to create a new array.
Well you need to do that only if you want to change the default settings. Otherwise that's zero extra code.
 

Crimson Wizard

#253
Quote from: Monsieur OUXX on Fri 27/07/2018 14:03:24
Yes, the core reason was to expose stuff. The thing in abstauber's module that's most likely to be changed immediately after importing are the sprites and other settings. Thzrefore I exposed that part.
Ultimately that allows to set up your game around the module without having to modify the module's code (that would not be a problem with other languages, but with AGS it's a nightmare to have to re-import and re-modify an imported third-party module every time it's modified by its creator).

Well, one thing is exposing options which is a right way to do, but another is exposing them as arrays, and that was what I found unusual and potentially inconvenient.

I have a feeling that there might be other ways to enumerate these options on your own without changing them to arrays in the standard template.

abstauber

Quote from: Monsieur OUXX on Fri 27/07/2018 14:03:24
Ultimately that allows to set up your game around the module without having to modify the module's code (that would not be a problem with other languages, but with AGS it's a nightmare to have to re-import and re-modify an imported third-party module every time it's modified by its creator)

Manually editing the CDG.init() function was the never the intended way of using the module. All variables inside the CDG struct are accessible from everywhere, so you can modify the dialog GUI from every script below the dialog script. So if you do the setup in game_start inside the globalscript (like you do now), you still will be fine, even if the module code changes.

To be honest, the best way of handling / designing custom dialogs would be inside the AGS Editor :P

Monsieur OUXX

#255
Quote from: abstauber on Fri 27/07/2018 14:35:25
All variables inside the CDG struct are accessible from everywhere, so you can modify the dialog GUI from every script below the dialog script.

Yes, but I don't want to change the global variables anywhere in the code. I want to pass the global variables to that module only once, and then change the variables defined in that module, only in my one custom script that initializes that module.
Moreover, that's only 1/4 of what my changes do :
Spoiler

1) they make the things accessible from outside (your answer addresses this, and I accept it)
2) they group the settings by category
3) they make them reflexive (accessible by index or name in the array of settings, allowing to tie them to an in-game console system)
4) they clarify the initialization sequence and keep the object in a consistent state (by letting you change a few settings and then calling the corresponding function in the module to apply them, instead of changing some variables values directly and then not being sure of what should be done for the change to be taken in account, or if something was broken).
[close]

More generally, I'd say that you guys have no mercy ;-D for people who build huge huge systems around your modules, because you don't perceive how much the smallest hesitations on the scripter's side ends adding up to lots of time wasted ("wait -- Did I change this setting myself or was it always like that? Should this module come before or after that other module? Damn there's an update. Is this new value meant to be overwritten by the custom value I used 2 years ago? I don't remember." etc.)
So anyways, at this stage I've explained why I went for those changes, that was my attempt at making your module more sealed from the rest of the code. So it's only my ego that keeps talking, there's no point in trying to convince you.
Thanks for taking the time of answering! See you around guys.
 

Crimson Wizard

#256
@Monsieur OUXX, These are valid points, actually, I don't know why you think that there is no point in trying to convince... I've automatically agreed to most of what you've said before, but I am not the template's author. Can't say for abstauber, but as I kept repeating my only confusion was about arrays part.

Quote from: Monsieur OUXX on Mon 30/07/2018 18:51:22
3) they make them reflexive (accessible by index or name in the array of settings, allowing to tie them to an in-game console system)
But could not this be also done without modifying the template itself (or rather - without having arrays inside abstauber's module itself, since there could be improvements of other sort)? I've shown an example of indexer property above, you could do this as a wrapper around abstauber's module, and even have these properties accessed by a string if you prefer. This way there will be two optional ways to access these settings: via strongly typed variables/attributes, and via custom indexer attribute(s).

Furthermore, with such approach you will have greater control, because if module changes with new update, you may still keep old order of variables in the indexer if you need one (e.g. in case you were saving these to the ordered list in file).

Quote from: Monsieur OUXX on Mon 30/07/2018 18:51:22
4) they clarify the initialization sequence and keep the object in a consistent state (by letting you change a few settings and then calling the corresponding function in the module to apply them, instead of changing some variables values directly and then not being sure of what should be done for the change to be taken in account, or if something was broken).
This problem is because majority of the classic modules and templates are written in "C-style" (which is actually not real "C-style", but rather "bad C-style"), where many variables are just left public. Normally they should be hidden behind Set/Get functions or properties (attributes in AGS), which are get/set functions too internally. And when SetX function is called, it should've taken the setting change into account (or at least user could presume it does).

Snarky

Quote from: Crimson Wizard on Fri 27/07/2018 13:39:19
What I mean by "property array", you could declare an attribute of array type like this (random example):
Code: ags

struct CustomDialog
{
    import attribute int IndexedOptions[];
}

And then implement like
Code: ags

int CustomDialog::geti_IndexedOptions(int index)
{
    if (index == 0) return dlg.background_color;
    if (index == 1) return dlg.foreground_color;
}
void CustomDialog::seti_IndexedOptions(int index, int value)
{
    if (index == 0) dlg.background_color = value;
    if (index == 1) dlg.foreground_color = value;
}


Wait, can you actually do this in AGS script, or is this just something that ought to be possible? I never knew about this, if it's possible! Way cool!

Quote from: Crimson Wizard on Mon 30/07/2018 19:17:36
This problem is because majority of the classic modules and templates are written in "C-style" (which is actually not real "C-style", but rather "bad C-style"), where many variables are just left public. Normally they should be hidden behind Set/Get functions or properties (attributes in AGS), which are get/set functions too internally. And when SetX function is called, it should've taken the setting change into account (or at least user could presume it does).

Yeah, but on the other hand, in the SpeechBubble module, more than half the code is just getters and setters for the various attributes. 8-0

If you're not actually doing any logic in them (I'm doing this whole inheritance system, which is part of the reason it takes up so many lines), just setting and returning an underlying variable, there's really no benefit: it just takes up space in the module, makes the code harder to skim, is a potential source of bugs (if, for example, you copy-paste the getters and setters and miss one of the variables that need to be changed), and adds a little bit of execution overhead.

You can replace a variable with an identically named attribute later on without changing any of the code that calls it (one of the great benefits of properties/attributes over getter/setter functions), so you might as well leave them as plain public member variables until you actually have any need for special handling.

abstauber

@Monsieur OUXX:
First of all, I really appreciate that you share your hard work with us/me and it's quite educational how you did things.
That said, I do not understand why you haven't refactored the fully fledged dialog module instead (http://www.adventuregamestudio.co.uk/forums/index.php?topic=36313.0) :confused:
If I accept your pull request now I'm in the delicate position that I have to apply all your changes to the parent module at some point.

Btw. because of this problem I usually do not integrate 3rd party modules in my templates. For the dialog GUI I made an exception because the default dialog in AGS is very very basic.
Also if I accept the pull request, it would make sense to apply these changes to the GUI script itself. This would as well be a major task and the new settings array doesn't help code-readability either.

Another thing is the refactored module still has around 13 options left which are not covered by the settings array - correct me if I'm wrong.
Edit: The function dropdown in the AGSEditor is also broken in your version of the customdialoggui.asc.

But enough of that... my main point is: if we change the way how variables are assigned, let's do it for the whole template.
I agree with Snarky: adding dozens of setters and getters (I know this from some if my modules too) blows up the code a lot. I like CW's approach, just with an enum instead of plain index numbers. But what difference makes " import attribute int " instead of a regular import?

Snarky

Quote from: abstauber on Tue 31/07/2018 09:21:25
I agree with Snarky: adding dozens of setters and getters (I know this from some if my modules too) blows up the code a lot. I like CW's approach, just with an enum instead of plain index numbers. But what difference makes " import attribute int " instead of a regular import?

Regular imports are just for functions: You don't import a member variable into a struct, you just declare it, and it gets added to that struct's data schema (so for every instance of the struct, you have to allocate that amount of memory to store it). Attributes, on the other hand, create properties that look like variables from the outside.

Declaring something as an attribute import means that it's "not a real variable": it's a function or functions called accessors (the getters and setters) pretending to be a variable. Functions aren't stored with the struct data, so they take up no additional space for each instance. Normally the important thing is that you can perform processing when you set the value, such as validation or updating other dependent data, and that you can store the data in a single, canonical representation but access it in alternative forms that are simply generated on demand (for example getting the right-edge coordinate of an object by adding the left-edge coordinate and the width, rather than storing it redundantly).

For properties that are regular variable types this is fairly routine, but I didn't know you could (in AGS) also write accessors that pretend to be not just a variable but an array of variables.

Sorry if this seems patronizing, you probably knew most of it already, but I wasn't sure exactly what part of it had you confused.

SMF spam blocked by CleanTalk