Menu

Show posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.

Show posts Menu

Messages - monkey0506

#341
Yes, unfortunately I think I lost my hosting I was using. Haven't really decided what I'm going to do about it yet. May be time to start using my agser.me account...

In any case, I can put up a temporary link if anyone needs it.
#342
I didn't change the way the keyboard is toggled. Unless your device doesn't have a menu button then it should be working. If you don't have physical hardware buttons, well that's something else we need to address, though off the top of my head, I'm not sure what the best approach would be here.
#343
There were some last minute changes which weren't thoroughly tested before they were committed into this version. That's my fault, and has been fixed for the next alpha release (which should be out soon).
#344
A couple more tips (about forum etiquette): It's not necessary to quote the entire post to respond to someone, nor is it necessary to create separate posts (it's actually against the rules ;)). Just put the name of who you're addressing, and use quotes to give emphasis to particular things you are responding to.

As far as the code, I figured that you probably didn't want the same text over and over, but my post was getting pretty long as it was. The modules (not the same as plugins) sound like what you're looking for, but let me just say you should not try to use both of them together. They are independently coded to approach the same problem in different ways. For what it's worth, the module I wrote is more current, but many people seem to prefer SSH's module (I'll leave that to you ;)).

Extending from what we have in my last post, you need to use an array. Think of it as a collection of variables that all share the same name. We'll use your existing dialoghi variable to keep track of which line of background speech we're currently on, and store the actual text inside of the array. Like this:

Code: ags
int dialoghi = 0;
String dialoglines[]; // the array of dialog text
#define DIALOG_COUNT 13 // how many lines of dialog do we have

function room_Load()
{
  dialoglines = new String[DIALOG_COUNT]; // initialize the array itself
  dialoglines[0] = "asdas"; // fill in each line of dialog, starting from index 0...
  dialoglines[1] = "asdaf";
  // ...
  dialoglines[12] = "asdaz"; // ...and ending with DIALOG_COUNT - 1
}
 
function room_RepExec()
{
  if (BISTICCIO)
  {
    if ((dialoghi == 0) || (IsTimerExpired(1))) // this is SLIGHTLY redundant (if dialoghi is 0), but it saves us duplicating other code
    {
      if ((dialoghi >= 0) && (dialoghi < DIALOG_COUNT)) // 0 <= dialoghi < 13
      {
        // note these lines aren't duplicated 13 times!
        cbibl.LockView(43);
        cbibl.Animate(0, 6, eRepeat, eNoBlock, eForwards);
        cbibl.SayBackground(dialoglines[dialoghi]); // NOTICE we changed this! we now say whichever text line has the same # as dialoghi
        SetTimer(1, 80);
        SetTimer(2, 60);
        dialoghi++;
      }
      else if (dialoghi == DIALOG_COUNT) // ONLY if the previous condition was FALSE, then check this one
      {
        dialoghi = 0;
      }
    } // has timer 1 expired
    if (IsTimerExpired(2)) // no ELSE, we want to check timer 2 whether timer 1 has gone off or not
    {
      cbibl.UnlockView();
      SetTimer(1, 20);
    }
  }
}


By using dialoghi as an index to the array, we select each line in order, letting you display as many messages as you need (just update DIALOG_COUNT and add your text). This is a step toward making your code more generic, which as I said before can have many benefits.
#345
There are three major problems I see with your code.

Problem 1: You believe that whitespace in code is evil. While it can be overdone, unless your mission statement is to have no one ever see, read, use, or understand your code, then whitespace is a must. As a general rule of thumb, if you're putting more than one command on a single line, you're probably doing it wrong.

Code: ags
int dialoghi = 0;

function room_RepExec()
{
  if (BISTICCIO)
  {
    if (dialoghi == 0)
    {
      cbibl.LockView(43);
      cbibl.Animate(0, 6, eRepeat, eNoBlock, eForwards);
      cbibl.SayBackground("asdas");
      SetTimer(1, 80);
      SetTimer(2, 60);
      dialoghi++;
    }
    if (IsTimerExpired(2))
    {
      cbibl.UnlockView();
      SetTimer(1, 20);
    }
    if (dialoghi == 1 && IsTimerExpired(1))
    {
      cbibl.LockView(43);
      cbibl.Animate(0, 6, eRepeat, eNoBlock, eForwards);
      cbibl.SayBackground("asdas");
      SetTimer(1, 80);
      SetTimer(2, 60);
      dialoghi++;
    }
    if (dialoghi == 2 && IsTimerExpired(1))
    {
      cbibl.LockView(43);
      cbibl.Animate(0, 6, eRepeat, eNoBlock, eForwards);
      cbibl.SayBackground("asdas");
      SetTimer(1, 80);
      SetTimer(2, 60);
      dialoghi++;
    }
    if (dialoghi == 3 && IsTimerExpired(1))
    {
      cbibl.LockView(43);
      cbibl.Animate(0, 6, eRepeat, eNoBlock, eForwards);
      cbibl.SayBackground("asdas");
      SetTimer(1, 80);
      SetTimer(2, 60);
      dialoghi++;
    }
    if (dialoghi == 4 && IsTimerExpired(1))
    {
      cbibl.LockView(43);
      cbibl.Animate(0, 6, eRepeat, eNoBlock, eForwards);
      cbibl.SayBackground("asdas");
      SetTimer(1, 80);
      SetTimer(2, 60);
      dialoghi++;
    }
    if (dialoghi == 5 && IsTimerExpired(1))
    {
      cbibl.LockView(43);
      cbibl.Animate(0, 6, eRepeat, eNoBlock, eForwards);
      cbibl.SayBackground("asdas");
      SetTimer(1, 80);
      SetTimer(2, 60);
      dialoghi++;
    }
    if (dialoghi == 6 && IsTimerExpired(1))
    {
      cbibl.LockView(43);
      cbibl.Animate(0, 6, eRepeat, eNoBlock, eForwards);
      cbibl.SayBackground("asdas");
      SetTimer(1, 80);
      SetTimer(2, 60);
      dialoghi++;
    }
    if (dialoghi == 7 && IsTimerExpired(1))
    {
      cbibl.LockView(43);
      cbibl.Animate(0, 6, eRepeat, eNoBlock, eForwards);
      cbibl.SayBackground("asdas");
      SetTimer(1, 80);
      SetTimer(2, 60);
      dialoghi++;
    }
    if (dialoghi == 8 && IsTimerExpired(1))
    {
      cbibl.LockView(43);
      cbibl.Animate(0, 6, eRepeat, eNoBlock, eForwards);
      cbibl.SayBackground("asdas");
      SetTimer(1, 80);
      SetTimer(2, 60);
      dialoghi++;
    }
    if (dialoghi == 9 && IsTimerExpired(1))
    {
      cbibl.LockView(43);
      cbibl.Animate(0, 6, eRepeat, eNoBlock, eForwards);
      cbibl.SayBackground("asdas");
      SetTimer(1, 80);
      SetTimer(2, 60);
      dialoghi++;
    }
    if (dialoghi == 10 && IsTimerExpired(1))
    {
      cbibl.LockView(43);
      cbibl.Animate(0, 6, eRepeat, eNoBlock, eForwards);
      cbibl.SayBackground("asdas");
      SetTimer(1, 80);
      SetTimer(2, 60);
      dialoghi++;
    }
    if (dialoghi == 11 && IsTimerExpired(1))
    {
      cbibl.LockView(43);
      cbibl.Animate(0, 6, eRepeat, eNoBlock, eForwards);
      cbibl.SayBackground("asdas");
      SetTimer(1, 80);
      SetTimer(2, 60);
      dialoghi++;
    }
    if (dialoghi == 12 && IsTimerExpired(1))
    {
      cbibl.LockView(43);
      cbibl.Animate(0, 6, eRepeat, eNoBlock, eForwards);
      cbibl.SayBackground("asdas");
      SetTimer(1, 80);
      SetTimer(2, 60);
      dialoghi++;
    }
    if (dialoghi == 13 && IsTimerExpired(1))
    {
      dialoghi = 0;
    }
  }
}


Problem 2: You're breaking one of the first rules of programming: DO NOT repeat yourself. You have the following six lines of code repeated thirteen times:

Code: ags
      cbibl.LockView(43);
      cbibl.Animate(0, 6, eRepeat, eNoBlock, eForwards);
      cbibl.SayBackground("asdas");
      SetTimer(1, 80);
      SetTimer(2, 60);
      dialoghi++;


There is no excuse for copypasta like this showing up in your code. If necessary, create a separate function. In your case, however, it's a matter of...

Problem 3: Abusing conditional statements.

If you are checking the same condition (e.g., IsTimerExpired(1)) several times when you have no logical reason to believe that the result may have changed in-between, then you are doing it wrong. If you find yourself checking multiple values of a variable as separate conditions with the same end-result, then you are doing it wrong. If you are checking that a variable value falls within a certain range by using multiple equals checks, then you are doing it wrong.

Here is a more realistic example of what your above code should look like:

Code: ags
int dialoghi = 0;

function room_RepExec()
{
  if (BISTICCIO)
  {
    if ((dialoghi == 0) || (IsTimerExpired(1))) // this is SLIGHTLY redundant (if dialoghi is 0), but it saves us duplicating other code
    {
      if ((dialoghi >= 0) && (dialoghi < 13)) // 0 <= dialoghi < 13
      {
        // note these lines aren't duplicated 13 times!
        cbibl.LockView(43);
        cbibl.Animate(0, 6, eRepeat, eNoBlock, eForwards);
        cbibl.SayBackground("asdas");
        SetTimer(1, 80);
        SetTimer(2, 60);
        dialoghi++;
      }
      else if (dialoghi == 13) // ONLY if the previous condition was FALSE, then check this one
      {
        dialoghi = 0;
      }
    } // has timer 1 expired
    if (IsTimerExpired(2)) // no ELSE, we want to check timer 2 whether timer 1 has gone off or not
    {
      cbibl.UnlockView();
      SetTimer(1, 20);
    }
  }
}





I realize you are probably fairly new to programming, so please don't take this the wrong way. However, if you look at the expanded version of your code (Problem 1) and compare it to the final version (Problem 3), you'll see that I've cut over 77% of the lines while still maintaining readable code. The benefits of basic programming concepts like these speak for themselves.

As to your actual solution, there isn't really anything that could be done much more eloquently in terms of getting the speech animation to play for background speech aside from making the code more generic*. I've authored a few modules (QueuedSpeech, PersistentSpeech) that manually control the speech animation in-sync with non-standard character speech (e.g., not a blocking Say command). If you're interested, you could look at those modules, or else myself (and others) would be able to show you how to pull that particular feature and use it in your game, but I first feel that it is more important that you understand these more basic programming concepts. Once you have a strong grasp on the basics, then branching out into more advanced topics will be within your reach.

*And for what it's worth, generic programming isn't always simpler, cleaner, or more eloquent than a specialized solution. Instead, I mean that generic code would be more versatile, easily applied to other characters in other situations, adapt to variable game speed, text reading speed, and the like.

Edit: Looking back over this, I realized that the dialoghi == 0 condition actually doesn't depend on the timer, which is what sets everything else in motion. I amended my modified code to reflect this. Again, there are other ways you could accomplish that result, but this is effective enough to show what I am talking about.
#346
Well as particularly terrifying as that all looks (especially as an animated GIF), I'm glad that you got it sorted out. ;)
#347
Yeah, there are some nuances with soft vs hard links and the mklink utility that probably aren't immediately apparent, but in general hard links are what you would want for this type of thing (and for that, the mklink tool needs the "/H" switch ;)). For what it's worth, you also brought to my attention the fact that Win XP doesn't have the mklink utility, so I put in a bugfix for the latest editor for that case as well. ;)

And with the help of Reflector (the .NET disassembly tool), I've managed to recreate and update the source for the Libraries module plugin into a mostly functional state. I have a couple of things to do to get it working with the latest editor and then I'll gladly upload the source to GitHub. And if you'd like it would probably be pretty easy to tweak it to use hard links instead of copying the files (the way I'm doing it right now is a huge mess anyway, honestly...what was I thinking 4 years ago?).
#348
If the text should just stay in one spot and show what the mouse is over, the simplest way of doing it is to create a GUI (Visibility: Normal, initially on) and put a GUI Label control on it. Then set the label text to @OVERHOTSPOT@. If you need something more complex (adding verbs, etc.) then it will be a bit more complicated, but it's still pretty simple:

Code: ags
// GlobalScript.asc

function repeatedly_execute() // should already exist, add it if not
{
  // executes commands repeatedly, once per game loop, only during non-blocking events
  String location = Game.GetLocationName(mouse.x, mouse.y);
  if (location == null) location = "";
  String verb = "";
  if (mouse.Mode == eModeWalkto) verb = "Walk to";
  else if (mouse.Mode == eModeLookat) verb = "Look at";
  // ...
  else if (mouse.Mode == eModeInteract) verb = "Use";
  lblLocation.Text = String.Format("%s %s", verb, location);
}
#349
Someone contacted me via PM, and brought up an important issue that will need to be addressed. Android 4.4.2 (Kitkat) removed the ability for an app to write to any folder on the SD card that it does not own. This can easily be resolved by those who have rooted devices (like myself), but we should come up with a more general solution (e.g., take ownership of the /~external-storage/ags folder from the launcher app). I'm also not sure how this will play into virtual storage mounted by standalone apps (e.g., mounted OBB files). This will need to be addressed, as more and more users are on the latest versions of Android.
#350
This is kind of what I was doing with the Libraries editor plugin (except just keeping a central store of modules and copying them, not soft/hard linking them), but nobody really seemed interested so I just kind of gave up on it.

Also, just a note but you're using two different methods here for linking. On Windows 7 you're soft linking files (which sets the 'L' attribute) whereas on Windows XP you're hard linking files (which does not). The differences between them may have minor or insignificant side-effects for what you're doing here, but of particular note is the fact that hard links won't have the L attribute set (unless, perhaps, you've hard linked a soft link, which I'm not entirely sure is possible) so your method for deleting links won't always work and also if the original file is deleted then your soft links will be broken.

To sum it up, a soft symbolic link is like a file pointer, and the file only exists in one place; a hard symbolic link is an actual file, it can just "exist" in more than one place on the disk without consuming extra memory (e.g., appearing in separate directories).

I'd recommend switching to hard links on Windows 7 by passing the "/H" flag to the mklink utility. If you want to delete them, on Windows 7 and XP you can delete a hard link just as you would a normal file (because they are, in fact, normal files). If you want to break the link then you can copy the files (destination or source, they're the same), delete them (from the destination, not the source), and then move the copies back to the destination. This will create separate copies that will no longer modify the source files.
#351
You said that the dialog option should be turned off when the player picks up an item from the room, yes? There's a number of ways you could do this. Probably the most sensible, though, would be just to add it to the same function where the player picks the item up. Presumably you have an object (or maybe character) in the room, and when the player does the pick up interaction, it turns off and they are given the inventory item. So, something like this should do it:

Code: ags
function oMysteriousItem_Pickup()
{
  oMysteriousItem.Visible = false; // turn the object off
  player.AddInventory(iMysteriousItem); // add the inventory item
  dMysteriousNPC.SetOptionState(4, eOptionOffForever); // hide the dialog option, whichever option number it is
}


You should probably already have the first few lines of that for picking up the item, what you need is the Dialog.SetOptionState function to turn off the relevant option in the dialog tree. You can also call this function within dialog scripts, or pretty much anywhere else you want.
#352
Engine Development / Re: AGS engine Linux port
Wed 24/12/2014 06:59:38
And, I managed to track the problem down (with only a small amount of egg on my face :-[ ). I've been referring to "ac2game.dta" (because that's what the editor calls it!) but the engine refers to "ac2game.dat".

Relevant commits:

de3ac29, "Initial import" (Editor)

a45f1a5, "Initial release of AGS Engine source code!"

This bug has been around since before the git repositories were ever created. The only prior references (in editor code, referenced by a constant) were both in Editor/AGS.Editor/GUI/GUIController.cs, used at line 909 as a fall-back when loading a game file and line 976 as a fall-back when creating a new game (from a template file). With the one-way upgrade that the editor has done since AGS 3.0, it's highly unlikely that either of these ever would have arisen to cause problems. I will submit a quick commit to fix this in the editor code (fef66bf), mainly because it's only referenced in one place (defining the constant) whereas the editor references the string "ac2game.dat" in several locations.

Sorry about the confusion! This should amend the issue with the 3.4.0.2 Linux builds not running, they just need the data file renamed. 8-)
#353
Engine Development / Re: AGS engine Linux port
Wed 24/12/2014 03:11:06
Whom are you telling to stop throwing around angry smileys? I don't see anyone doing that. If you meant me, let me clarify that I have previously used the startgame script with ac2game.dta files without modification to the script. This method no longer works, although it should, as the engine should be receiving the data directory as the working directory. Based on the above, however, it also appears that the engine is not detecting the data file unless it is given as a parameter explicitly to the engine, not the script. The engine should be able to find the data file in the working directory, which actually appears to be the underlying problem, though it should also be pointed out that the script does not appear to be passing the command line arguments to the engine properly.


In case you weren't aware (from not rtfm), the ac2game.dta file is the game. Nothing in the linked documentation says that the Windows executable must be provided (nor is this the case for the engine to run the game).
#354
I meant that it's hardly a justification (in itself) for not using AGS. ;)
#355
Besides, people have made adventure games without that feature for decades. Not to mention you can effectively work around it in code (with some obvious speed penalties, if you're accessing them hundreds or thousands of times per second).
#356
Engine Development / Re: AGS engine Linux port
Tue 23/12/2014 19:50:42
Are you running the Windows executable or the game data file? Because it's telling me it can't find the game data file.

Edit: Using the "startgame" script produced by "debian/make_ags+libraries.sh", I can only load the game using the full Windows executable. In fact, it seems that the script is ignoring its arguments altogether. Here are my results:

startgame script with extracted game data file
> ./startgame
> ./startgame ./
> ./startgame ./data
> ./startgame ./ac2game.dta
> ./startgame ./data/ac2game.dta
> ./startgame ./NotARealPath/ac2game.dta

AGS: Game data file could not be found


startgame script with Windows executable
> ./startgame
> ./startgame ./
> ./startgame ./data
> ./startgame ./Game.exe
> ./startgame ./data/Game.exe
> ./startgame ./NotARealPath/Game.exe

(game runs normally)


ags engine with extracted game data file
> ./data/ags64
> ./data/ags64 ./
> ./data/ags64 ./data
> ./data/ags64 ./ac2game.dta
> ./data/ags64 ./data/ac2game.dta
> ./data/ags64 ./NotARealPath/ac2game.dta
/data> ./ags64
/data> ./ags64 ./
/data> ./ags64 ./NotARealPath
/data> ./ags64 ./NotARealPath/ac2game.dta

AGS: Game data file could not be found

/data> ./ags64 ./ac2game.dta

(game runs normally)


ags engine with Windows executable
> ./data/ags64
> ./data/ags64 ./
> ./data/ags64 ./data
> ./data/ags64 ./Game.exe
> ./data/ags64 ./data/Game.exe
> ./data/ags64 ./NotARealPath/Game.exe
/data> ./ags64 ./NotARealPath
/data> ./ags64 ./NotARealPath/Game.exe

AGS: Game data file could not be found

/data> ./ags64
/data> ./ags64 ./
/data> ./ags64 ./Game.exe

(game runs normally)

Were some changes made to the generated "startgame" script? Because this script is also being used to set up the path for the Allegro modules based on system architecture (pointing it to lib32 or lib64 directory), as well as any plugins that the game may use. So simply running the engine directly is not a viable solution for developers or their end-users.

Particularly bothersome is that the script is apparently not passing its arguments to the engine at all.

For reference, this is the contents of the script file produced by the current develop-3.4.0 branch:

Code: text
#!/bin/sh
SCRIPTPATH="$(dirname "$(readlink -f $0)")"

if test "x$@" = "x-h" -o "x$@" = "x--help"
  then
    echo "Usage:" "$(basename "$(readlink -f $0)")" "[<ags options>]"
    echo ""
fi

if test $(uname -m) = x86_64
  then
    ALLEGRO_MODULES="$SCRIPTPATH/data/lib64" "$SCRIPTPATH/data/ags64" "$@" "$SCRIPTPATH/data/"
  else
    ALLEGRO_MODULES="$SCRIPTPATH/data/lib32" "$SCRIPTPATH/data/ags32" "$@" "$SCRIPTPATH/data/"
fi
#357
Engine Development / Re: AGS engine Linux port
Mon 22/12/2014 21:07:39
Okay, it's just come to my attention that apparently the Linux engine isn't running standalone game data files any more. I know it was at one point, but now it simply refuses to find them. I have tested this with the game data files produced by the amended develop-3.4.0 branch, as well as the stripped EXE (hex edited everything leading up to "CLIB\x1A", which marks the start of game data) from both the new and legacy game compilers. The Windows engine reads all of these data files without issue. I also attempted to pad the raw game data file with "\x00\x00\x00\x00CLIB\x01\x02\x03\x04SIGE" (zero, as a four-byte integer, followed by the CLIB signature), but to no avail.

This fundamentally breaks the Linux build option because it produces files that don't run. I am testing to see if I can figure out at what version this stopped working, but I also confirmed the same behavior from the master branch. >:(
#358
Quote from: tzachs on Sat 06/12/2014 02:20:03git doesn't know how to compare these changes, so it shows it as one deleted file and one added file (quite surprising actually, in TFS it knows to tag it as a "file rename" and shows the file differences as expected).

In my experience, once I actually commit a renamed file (and git permanently tracks that particular change), then git should be able to detect that the file is 95% the same (or what-have-you) just with a different name, and it can properly track it as a rename. I used a git repo for my final project at school, and this was the behavior that I observed.

I've also noticed that recently (new computer) I have a lot of superfluous changes to solution files (namely, AGSEditor.sln). I've tried to keep a closer eye on the changes I'm actually making and when I have a diff that I didn't make then I don't add it to the commit. From what I recall, the AGS.Native assembly also changes frequently, even without source code changes.
#359
Quote from: Calin Leafshade on Sun 21/12/2014 22:12:07Whats the purpose of the hard linking anyway?

I've brought this up several times, but in order to have each platform build to a separate deployable folder instead of stupidly throwing all of the files into some horrific conglomerate mess, the editor has to either a) copy every game resource file or b) hard link those resource files. When your game resource files reach into the gigabytes, copying them for each individual platform is, as you say, mental. Hard linking these files is the most sensible way of approaching this problem.

And to quell your fears, I've gotten it working just fine from a non-administrator account.
#360
Please pardon the double-post, but I think I've just about honed in on the issue with the legacy compile option not working. Foolishly, I wasn't telling the other build targets to not build if the legacy compiler was selected. The BuildTargetDataFile class will appropriately defer to that setting, and there is some code that was moved into BuildTargetWindows that still needs to be called, but the rest should be ignored from that point. I have a nearly-working build, and by nearly-working I mean that it almost works except that it doesn't. ;) The size of the generated EXE looks correct, and it's properly updating the icon which is a good sign, but it's not finding the data file embedded in the EXE (possibly I need to write the offset manually, or something). I will look into this, but for now I am falling asleep, so.
SMF spam blocked by CleanTalk