(Solved)GrimQuest registration issues

Started by Construed, Mon 28/10/2013 14:50:21

Previous topic - Next topic

Construed

Hello again all, I have this code given to me by Khris, but AS-IS it only works for 2 of 3 textboxes on a form and I don't understand it enough to know if its even possible to add a third textbox to it:
Code: ags

       void on_event(EventType event, int data) {
      if (event == eEventGUIMouseUp) {
        GUI *theGUI = gGui9;         //  <------- insert your GUI's name here!
     
        // textbox clicking
        if (data == theGUI.ID) {
         
          GUIControl *gc = GUIControl.GetAtScreenXY(mouse.x, mouse.y);
          if (gc == null) return;  
          TextBox *tb = gc.AsTextBox;
          if (tb == null) return;
         
          int i;
          while (i < theGUI.ControlCount) {
            if (theGUI.Controls[i].AsTextBox != null)
              theGUI.Controls[i].Enabled = false;
             
            i++;
          }
          //TextBox1.Visible=true;
          TextBox2.Visible=true;
          mail.Visible=true;
          tb.Enabled = true;
        }
      }
    }


Also I'm trying to think of a way or function that causes a gui to open upon restoring a character no matter what other conditions there may be.

Thanks for reading!
-J
I felt sorry for myself because I had no shoes.
Then I met the man with no feet.

Khris

You're not supposed to add those .Visible commands down there.

What this code does is (for a specific GUI!) check whether the user clicked on a textbox, and if they did, disable all other textboxes on the same GUI.
You can add textboxes to your GUI as much as you want, and the code will work fine (and without explicitly referencing the textboxes by name anywhere). Just make sure to disable all textboxes except the first one.

Now if you are showing multiple GUIs with textboxes, the code has to be changed a bit:

Code: ags
void on_event(EventType event, int data) {
	
	if (event == eEventGUIMouseUp) {
		
		// find textbox under mouse 
		GUIControl *gc = GUIControl.GetAtScreenXY(mouse.x, mouse.y);
		if (gc == null) return;  
		TextBox *tb = gc.AsTextBox;
		if (tb == null) return;
		
		// disable all visible textboxes except the one that was clicked
		int i = 0, j;
		while (i < Game.GUICount) {
			// is GUI "interactable"?
			if (gui[i].Visible && gui[i].Clickable) {
				j = 0;
				while (j < gui[i].ControlCount) {
					if (gui[i].Controls[j].AsTextBox != null)
						gui[i].Controls[j].Enabled = false;
					j++;
				}
			}
			i++;
		}
		// enable clicked textbox
		tb.Enabled = true;
	}
}

(untested)


Construed

I just realized I moved the password entry GUI to another screen inside the game because when you load a game any commands made in the previous GUI seem to be eliminated by the LOAD functions, So I dont actually need it for another GUI, although that code does seem to work :)

The only problem I'm having with it is you have to click one of the boxes first or it will write in all of them.

I felt sorry for myself because I had no shoes.
Then I met the man with no feet.

Khris

#3
If I may:
Quote from: Khris on Mon 28/10/2013 15:03:36Just make sure to disable all textboxes except the first one.

You can do this in game_start:
Code: ags
  tbMyTextBox.Enabled = false;
  ...

Construed

Facepalm!
I thought the disable had to be done from your code and didn't think a simple TextBox2.Enabled=false; would do it, but it works great! I'm just going to use that new piece of code you gave me in case in the future I have multiple textboxes on multiple gui's cause it seems to work fine.
Such a relief to have a more functional registration GUI!

Do you know how I can do a string comparison on a Display(%s, junk); to filter out certain messages that are displayed?
Thanks Khris!
-J
I felt sorry for myself because I had no shoes.
Then I met the man with no feet.

Calin Leafshade

Code: ags

    String dirtyString = "Jesus, Fuck this shit"
    String newString = dirtyString.Replace("jesus", "jeezy")
    newString = newString.Replace("fuck", "fig") // note we edit the new string
    newString = newString.Replace("shit", "shoe")
    Display(newString); // Displays "jeezy, fig this shoe"


If you have a list of bad words to replace in an array then you can iterate through them to avoid a lot of code duplication.

Note you also have to deal with restoring capitalisation but if its just for chat sanitizing then i doubt it matter.s

Construed

You probably answered my question well, But I have some confusion, possibly based on the type of Displaying I'm doing.
see this code
Code: ags

void ReceiveNickserv(String message)
{


        Display("%s", ircMessage);
        ReceiveNickserv(ircMessage);
        

}


Display("%s", ircMessage);
Can display multiple messages from nickserv and the particular one I'm trying to block or change is:
"if this is your nickname type /msg nickserv identify password"

Thanks for taking the time to help,

-J
I felt sorry for myself because I had no shoes.
Then I met the man with no feet.

Construed

#7
Well, I tried to implement it with my lack of AGS code formatting with no success...
It compiled ok but did not achieve its effect, I'm sure I did not format the ags code correctly.
Code: ags

void ReceiveNickserv(String message)
{
        String dirtyString = "If this is your nickname, type /msg NickServ IDENTIFY <password>";
        String newString = dirtyString.Replace("If this is your nickname, type /msg NickServ IDENTIFY <password>", "Loading...");
        Display(newString);

        Display("%s", ircMessage);
        ReceiveNickserv(ircMessage);

}


Edit: Edited code above to have case sensitive dirtystring..
I felt sorry for myself because I had no shoes.
Then I met the man with no feet.

Crimson Wizard

#8
There are several interwined mistakes here.

First of all, you are displaying a message twice (and these are different messages):
Code: ags

Display(newString);

Display("%s", ircMessage);


Secondly, you change the new local string, not the variable you use later. You should, perhaps, remove any mentioning of "dirtyString", and do this instead:
Code: ags

void ReceiveNickserv(String message)
{
        String newString = ircMessage.Replace("If this is your nickname, type /msg NickServ IDENTIFY <password>", "Loading...");
        Display(newString); // display fixed string on screen
        ReceiveNickserv(ircMessage); // yet pass the real original string further
}


Third, what is with "String message" parameter? You receive it in this function, but it is not used anywhere, instead you are using some "ircMessage" (which is a global variable, I guess?). What is "message" needed for?

Fourth, "Replace" is used to replace multiple accounts of same substrings in text. I suppose Calin just did not understand your intentions correctly when suggesting using it. In your case it will be simplier to just compare strings and change its value by assignment:
Code: ags

String newString = ircMessage;
if (newString == "If this is your nickname, type /msg NickServ IDENTIFY <password>")
   newString = "Loading...";
Display(newString);

EDIT: Upon thinking, what I said about being "simplier" here probably not true, because the result is the same, and the second variant has 1 extra line of code compared to the "Replace". :) I should have rather said it is more "common" thing to do. So, use what you like more.

Finally, as a tip, this:
Code: ags

Display("%s", some_string_variable);

is just an excessive way to write
Code: ags

Display(some_string_variable);



EDIT: yes, another important thing is that it is not recommended to put plain text everywhere, because it is easy to make a typo and thus break the program.
Try to create a number of global String variables (or an array of strings, see what fits best), initialize them in "game_start" function, and use them instead.

Construed

Code: ags

String newString = ircMessage; 

if (newString == "If this is your nickname, type /msg NickServ IDENTIFY <password>")
   newString = "Loading...";
Display(newString);


Getting this error at String newString:
GlobalScript.asc(47): Error (line 1): cannot assign initial value to global pointer

Code: ags

void ReceiveNickserv(String message)
{
        String newString = ircMessage.Replace("If this is your nickname, type /msg NickServ IDENTIFY <password>", "Loading...");
        Display(newString); // display fixed string on screen
        ReceiveNickserv(ircMessage); // yet pass the real original string further
}

Compiles fine, but has no effect on the message?

I thank you greatly for the detailed explanation, I shall read it several times until I comprehend it!

-J
I felt sorry for myself because I had no shoes.
Then I met the man with no feet.

Construed

Hmm, I've been trying these methods in every way possible and nothing seems to work, keep in mind the message is coming from the server and not the game, that may have something to do with it?
I felt sorry for myself because I had no shoes.
Then I met the man with no feet.

Crimson Wizard

Maybe it is not the message you are trying to replace? Are not you making any typos, for instance?
Are you sure the message is displayed only at this point?

Will this make any effect, if you temporarily write this for a test:
Code: ags

void ReceiveNickserv(String message)
{
        Display("We do not display anything useful here");
        ReceiveNickserv(ircMessage);
}

Construed

It was loading from another location also but after fixing it
Code: ags

void ReceiveNickserv(String message)
{
        String newString = ircMessage.Replace("If this is your nickname, type /msg NickServ IDENTIFY <password>", "Loading...");
        Display(newString); // display fixed string on screen
        ReceiveNickserv(ircMessage); // yet pass the real original string further
}

Still has no effect :(
I felt sorry for myself because I had no shoes.
Then I met the man with no feet.

Crimson Wizard

#13
Construed, please, what effect do you have?
Does it display text you do not want to have displayed? What text is that? Can you make a screenshot?
Are you sure it is the only place where the text is displayed by "Display" command?

Do you need the message to pass further to ReceiveNickserv, or you need it to not be passed there too? Please explain.

Again, will this make any effect, if you temporarily write this for a test:
Code: ags

void ReceiveNickserv(String message)
{
        Display("We do not display anything useful here");
        ReceiveNickserv(ircMessage);
}

Will the message you don't want stop displaying, or will still be displayed?

Construed

Code: ags

void ReceiveNickserv(String message)
{
        Display("We do not display anything useful here");
        ReceiveNickserv(ircMessage);
}

Has the same exact effect as:
Code: ags

void ReceiveNickserv(String message)
{
        Display("%s", ircMessage);
        ReceiveNickserv(ircMessage);

}

and does not display "the We do not display anything useful here" msg at all.


To explain the issue further.
When the player loads his character, the game starts and a gui pops up asking for password, the player enters his password and the gui sends this message to NickServ: "IRCMsg("NICKSERV", String.Format("IDENTIFY %s", passt.Text));" where passt.text is the textbox on the gui where the player has entered his password, Then nickserv sends 3 messages to the player, 2 of which I wish to remove, here is a screenshot of one of them:


I do not wish to receive this message because the player isn't capable of issuing that command and it is hard coded into the game.
I'm sorry for any confusion I may have cause or requests I missed, my brain works differently than most people and I comprehend things differently, Sorry about that!
Thanks a million for helping!
-J
I felt sorry for myself because I had no shoes.
Then I met the man with no feet.

Crimson Wizard

#15
Omg, I probably had a temporary blindness or something, can't believe I missed this.

Just look at this:
Code: ags

void ReceiveNickserv(String message)
{
   <...>
   ReceiveNickserv(ircMessage);
}


You have a function ReceiveNickserv that calls exactly same function ReceiveNickserv. There are no quit condition, which means that if this function will be ever called, it will loop endlessly (until game crash due to running out of memory).
Which makes me think this function is never called at all. That Display command should be used somewhere else.

Construed

I just realized that it is actually this code that causes the game to recieve the messages from Nickserv:
Code: ags

      if (ircFrom == "NickServ")
          {
       Display("%s", ircMessage);
          }


I'm very sorry about that!
I felt sorry for myself because I had no shoes.
Then I met the man with no feet.

Construed

Quote from: Crimson Wizard on Tue 29/10/2013 01:01:51
Omg, I probably had a temporary blindness or something, can't believe I missed this.

Just look at this:
Code: ags

void ReceiveNickserv(String message)
{
   <...>
   ReceiveNickserv(ircMessage);
}


You have a function ReceiveNickserv that calls exactly same function ReceiveNickserv. There are no quit condition, which means that if this function will be ever called, it will loop endlessly (until game crash due to running out of memory).
Which makes me think this function is never called at all. That Display command should be used somewhere else.
Your absolutely right, I removed the function entirely and game performance has increased drastically!
I still need help figuring out how to block that msg though :(

Thanks a mill,
-J
I felt sorry for myself because I had no shoes.
Then I met the man with no feet.

Construed

Another question I have is where are those smiley faces coming from, I have looked through all the fonts and not found them.
I felt sorry for myself because I had no shoes.
Then I met the man with no feet.

Crimson Wizard

Quote from: Construed on Tue 29/10/2013 04:02:05
I still need help figuring out how to block that msg though :(
Well, just use the solution given previously but on the correct place, e.g.:
Code: ags

if (ircFrom == "NickServ")
{
   String newString = ircMessage;
   if (newString == "If this is your nickname, type /msg NickServ IDENTIFY <password>")
      newString = "Loading...";
   Display(newString);
}


The problem is though, that this line is not identical to what you get there. You need to find out what those smileys are.
Here I made an output of characters 1-255 with AGS default font:
[imgzoom]http://img5.imageshack.us/img5/3930/glax.png[/imgzoom]
As you may see, the black smiley is the second char (i.e. char = 2).

Try this:
Code: ags

if (ircFrom == "NickServ")
{
   String newString = ircMessage;
   String badString = "If this is your nickname, type /msg NickServ ";
   badString = badString.AppendChar(2);
   badString = badString.Append("IDENTIFY");
   badString = badString.AppendChar(2);
   badString = badString.Append(" <password>");
   if (newString == badString )
      newString = "Loading...";
   Display(newString);
}

That's not the most optimal way to do this, but we first need to make sure this at least works.

Construed

awesome! It seems to work great!
thanks a mill crimson, I really appreciate you taking the time to help!
I felt sorry for myself because I had no shoes.
Then I met the man with no feet.

Crimson Wizard

#21
Nice!

To make things better, you should make the "badString" a global variable and create it on game start to avoid repeating this process during client-server communications (because that may slow them).

To do so declare the variable at the top of the script:
Code: ags

String NickServ_BadString; // you may invent better name, of course

Make a small function that creates this string:
Code: ags

String CreateNickServBadString()
{
   String badString = "If this is your nickname, type /msg NickServ ";
   badString = badString.AppendChar(2);
   badString = badString.Append("IDENTIFY");
   badString = badString.AppendChar(2);
   badString = badString.Append(" <password>");
   return badString;
}


Initialize the string in "game_start" function:
Code: ags

NickServ_BadString = CreateNickServBadString();


EDIT: I forgot you can type special chars other way, using "%c" tag in string formatting:
Code: ags

NickServ_BadString = String.Format("If this is your nickname, type /msg NickServ %cIDENTIFY%c <password>", 2, 2);

You won't need CreateNickServBadString function in this case.


And use it in the previous code:
Code: ags

if (ircFrom == "NickServ")
{
   String newString = ircMessage;
   if (newString == NickServ_BadString)
      newString = "Loading...";
   Display(newString);
}


Something like that...

Construed

#22
Even better!
Thank you so much, I'm trying my best to avoid latency issues and this works great!
You are an AGS guru indeed!
-J

Edit:
Code: ags

NickServ_BadString = String.Format("If this is your nickname, type /msg NickServ %cIDENTIFY%c <password>", 2, 2);

Very nice!
I felt sorry for myself because I had no shoes.
Then I met the man with no feet.

Construed

Hey, I tried to add a secondary string replace like this:
Code: ags

NickServ_BadString = String.Format("If this is your nickname, type /msg NickServ %cIDENTIFY%c <password>", 2, 2);
NickServ_BadString2 = String.Format("Type /msg NickServ HELP %cIDENTIFY%c for more information", 2, 2);



Code: ags

if (ircFrom == "NickServ")
{
   String newString = ircMessage;
   String newString2 = ircMessage;
   
   if (newString == NickServ_BadString)
      newString = "Loading...";
      Display(newString);
 
   if (newString2 == NickServ_BadString2)
      newString2 = "Please try to register again";
      Display(newString2);

  
}


But it didn't work and it ruined the effect of the first one, If i remove it works fine still, but anyone have any idea how I add multiple of these string replacements?
I felt sorry for myself because I had no shoes.
Then I met the man with no feet.

Crimson Wizard

#24
You do not need two "newString" variables. If you need to do same action in two or more cases, combine conditions with OR (||) operator:

Code: ags

if (ircFrom == "NickServ")
{
   String newString = ircMessage;
   
   if (newString == NickServ_BadString || newString == NickServ_BadString2)
      newString = "Loading...";
   Display(newString);
}


Now, assuming there may be more "bad" strings, it is better to make an array of "bad" strings instead, and check for every element of that array.
Declaration:
Code: ags

#define TOTAL_BAD_STRINGS 2 // increase this if you need more
String NickServ_BadString[TOTAL_BAD_STRINGS];

In game_start():
Code: ags

NickServ_BadString[0] = String.Format("If this is your nickname, type /msg NickServ %cIDENTIFY%c <password>", 2, 2);
NickServ_BadString[1] = String.Format("Type /msg NickServ HELP %cIDENTIFY%c for more information", 2, 2);

Replacing bad strings:
Code: ags

if (ircFrom == "NickServ")
{
   String newString = ircMessage;

   // Compare with all bad strings and replace if needed
   int bad = 0;
   while (bad < TOTAL_BAD_STRINGS)
   {
      if (newString == NickServ_BadString[bad])
      {
         // bad string matched! replace
         newString = "Loading...";
         // since we do not need to check any more, this trick will force the loop to end prematurely
         bad = TOTAL_BAD_STRINGS;
      }
      else
         bad++; // increase index by one, will try next bad string next time
   }

   Display(newString);
}

Construed

Man this is some VERY awesome code and I can't thank you enough for sharing it with me!
I owe you big time!
One question though, Is it possible to assign different messages to the different NickServ_BadString's?

Thanks a million my friend, and please let me know if you need any graphics, web design, coding done, or anything else done! I really appreciate your time!
I felt sorry for myself because I had no shoes.
Then I met the man with no feet.

Crimson Wizard

Quote from: Construed on Wed 30/10/2013 00:18:39
One question though, Is it possible to assign different messages to the different NickServ_BadString's?
Can you elaborate?

Construed

Code: ags

NickServ_BadString[0] = String.Format("If this is your nickname, type /msg NickServ %cIDENTIFY%c <password>", 2, 2);
NickServ_BadString[1] = String.Format("Type /msg NickServ HELP %cIDENTIFY%c for more information", 2, 2);

Say if the string = badstring0 it could display "loading...."
but if the string = badstring1 it could display "click to continue...."
I felt sorry for myself because I had no shoes.
Then I met the man with no feet.

Crimson Wizard

Ooh. In such case you would need a Map. AGS does not have such built-in class, but you can emulate that (sort of) by using the struct that holds two strings: bad one and good one (a replacement).

Declaration:
Code: ags

// Declare the struct
struct StringReplacement
{
    String Bad;
    String Good;
};

// Declare the array of structs:
#define TOTAL_BAD_STRINGS 2 // increase this if you need more
StringReplacement NickServ_BadString[TOTAL_BAD_STRINGS];


Setup values in pairs (bad/good):
Code: ags

NickServ_BadString[0].Bad = String.Format("If this is your nickname, type /msg NickServ %cIDENTIFY%c <password>", 2, 2);
NickServ_BadString[0].Good = "Loading...";
NickServ_BadString[1].Bad = String.Format("Type /msg NickServ HELP %cIDENTIFY%c for more information", 2, 2);
NickServ_BadString[1].Good = "Click to continue...";


New replacement code (only shown the part that has to be modified):
Code: ags

<...>
      if (newString == NickServ_BadString[bad].Bad)
      {
         // bad string matched! replace
         newString = NickServ_BadString[bad].Good;
<...>
}

Construed

It works like a well oiled machine!
Code: ags

// Declare the struct
struct StringReplacement
{
    String Bad;
    String Good;
};
 
// Declare the array of structs:
#define TOTAL_BAD_STRINGS 4 // increase this if you need more
StringReplacement NickServ_BadString[TOTAL_BAD_STRINGS];


//--------------------------------------------------------------------------------
function game_start() {
  
NickServ_BadString[0].Bad = String.Format("If this is your nickname, type /msg NickServ %cIDENTIFY%c <password>", 2, 2);
NickServ_BadString[0].Good = "Loading...";
NickServ_BadString[1].Bad = String.Format("Type /msg NickServ HELP %cIDENTIFY%c for more information", 2, 2);
NickServ_BadString[1].Good = "Click to continue...";
NickServ_BadString[2].Bad = String.Format("Syntax: %cIDENTIFY%c <password>", 2, 2);
NickServ_BadString[2].Good = "Click to continue...";
NickServ_BadString[3].Bad = String.Format("Type %c/msg NickServ HELP IDENTIFY%c for more information", 2, 2);
NickServ_BadString[3].Good = "Please try again";


Code: ags

     if (ircFrom == "NickServ")
{
   String newString = ircMessage;
 
   // Compare with all bad strings and replace if needed
   int bad = 0;
   while (bad < TOTAL_BAD_STRINGS)
   {
           if (newString == NickServ_BadString[bad].Bad)
      {
         // bad string matched! replace
         newString = NickServ_BadString[bad].Good;
         // since we do not need to check any more, this trick will force the loop to end prematurely
         bad = TOTAL_BAD_STRINGS;
      }
      else
         bad++; // increase index by one, will try next bad string next time
   }
 
   Display(newString);
}

Many thanks Crimson!!
I felt sorry for myself because I had no shoes.
Then I met the man with no feet.

SMF spam blocked by CleanTalk