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

Topics - monkey0506

#161
Several of you messaged me about my avatar kicking up a 'localhost' != 'www1.meleepta.com' certificate signing error. It would seem that my webhost is experiencing continued technical difficulties. Their hired tech support guys really screwed them over and have caused them no end of trouble. They are currently in the process of having to transfer all their data to a new server.

I'm sticking with them because I've read a lot of good things about this host (and I'd be really hard pressed to beat their free service package), but for now I'll have to take down my avatar until I figure out what's going on here.

-monkey
#162
I know there's topics floating around here for various different "post webhosts here" but I was mainly wondering if anyone was familiar with this particular host. Free webhosts are usually crap and the ones that look like they're too good to be true usually are. So I came across this host:

http://x10hosting.com/

Ad-free hosting with PHP, MySQL, cPanel, Linux server running Apache, .htaccess support, FTP, web email, domain hosting, 3 subdomains, 300 MB space and 10 GB monthly bandwidth? It definitely seems too good to be true. However me and 110mb are butting heads again because they keep taking away features that used to be free, so I was in the market for a decent free webhost.

One thing I can say is that using their website is rather annoying (signing up wasn't the simplest thing to do with all the ads in the way). However, I have a semi-functional site (mostly just hosting my files like before only the actual pages are toned down a bit (aww...no more php errors :P)). I used FTP to transfer over 20 MB of files at decent speeds. I even set up an email forwarder so that now addresses such as monkey_05_06@meleepta.com or admin@meleepta.com (should) automatically forward to my Gmail.

So aside from their main site being loaded with ads (presumably to compensate for the fact that I chose their 'ad-free' hosting package), I seem to have stumbled upon a decent free webhost. But again all this does beg the questions: Is it for real? What's the catch?

If anyone has an opinion of this host, I would appreciate any input as I have never used them previously. For now I'll host my (pitiful excuse for a) site there (and perhaps even convince myself I'll actually put up some proper pages ::)). If I do encounter any problems, I'll be sure to post about it here. But until then...

Give it a try if you'd like. It does sound a very nice package.
#163
We have the ability to redefine the save directory using Game.SetSaveGameDirectory, and for some functions (like File.Open if we need to use the save directory we can use the $SAVEGAMEDIR$ tag. However, not all functions make use of the $SAVEGAMEDIR$ tag, and there's no way for us to simply read it back.

If there were a Game.SaveGameDirectory property (read only of course; leaving the SetSaveGameDirectory function in place to reject invalid directories) then we could read the current save directory for functions that may need it.

Specifically I was working with ListBox.FillDirList when I realized that we can use fully qualified paths with this function such as "./dir/*.*" or even "D:/dir1/dir2/*.gif" but we simply cannot (unless we have explicitly set and stored elsewhere) know what the current save directory is set to.

Especially with the move toward keeping AGS files in the 'My Documents' folder to prevent Vista throwing a tantrum, I believe it important for us to be able to read back the fully-expanded current save directory; or at the very least, for ListBox.FillDirList to support the $SAVEGAMEDIR$ and $MYDOCS$ tags. That's not so much to ask, is it? :=
#164
One issue that has been brought up with AGS 3.0 is that in removing some of the static limits, some of the AGS_MAX_* constants have been removed. Namely AGS_MAX_CHARACTERS and AGS_MAX_GUIS are no longer available since these limits are no more.

The alternative method for arrays based on these values is to use dynamic arrays. The problem with this is that scripts using dynamic arrays aren't backwards compatible while scripts using the old AGS_MAX_* constants aren't forward-compatible. Short of using loads of #ifdef/#ifndef-s it seemed that our scripts would be restricted to "AGS 2.72-" or "AGS 3.0+" versions.

However, it is possible to future-proof your old AGS 2.72- modules for this change. Simply adding a few lines will make it possible to leave your scripts otherwise in-tact.

First you'll need to define the now-missing constants. If you used the old AGS_MAX_* constants in your script header you'll need to add these lines to the top of your header, otherwise it's best to just add them to the top of the main script:

Code: ags
#ifdef AGS_SUPPORTS_IFVER
#ifver 3.0
#define AGS_MAX_CHARACTERS // $AUTOCOMPLETEIGNORE$
#define AGS_MAX_GUIS // $AUTOCOMPLETEIGNORE$
#define IS_AGS_3_0 // $AUTOCOMPLETEIGNORE$
#endif
#endif


Adding the #define but ending it in a comment instead of a value means that the #define will be replaced by nothing. Hence:

Code: ags
int CharacterBuffer[AGS_MAX_CHARACTERS];


Would be interpreted as:

Code: ags
int CharacterBuffer[];


A dynamic array. Ending the lines in $AUTOCOMPLETEIGNORE$ simply makes sure that the autocomplete won't try to carry the values over to other scripts since we're going to destroy these temporary #define-s when we're done with them. The IS_AGS_3_0 #define simply gives us an easier way to check if we are using AGS 3.0 (i.e., checking 1 #define instead of checking a #define and then using #ifver again).

The next set of lines you'll need to add go into your main script's game_start function which is where you'll initialize any dynamic arrays (if the user is using AGS 3.0).

Code: ags
// inside game_start
#ifdef IS_AGS_3_0
CharacterBuffer = new int[Game.CharacterCount];
GUIBuffer = new int[Game.GUICount];
//etc.
#undef AGS_MAX_CHARACTERS
#undef AGS_MAX_GUIS
#define AGS_MAX_CHARACTERS Game.CharacterCount // $AUTOCOMPLETEIGNORE$
#define AGS_MAX_GUIS Game.GUICount // $AUTOCOMPLETEIGNORE$
#endif


These lines will allocate the memory for your dynamic array. Since there's no "max" value for Characters or GUIs in AGS 3.0, we can use the actual number of them in the game instead.

(Edit) I forgot that you may want to use the constants for something other than just creating the arrays. The above now assigns the constants useful values after the (dynamic) arrays have been created. ;)

(Edit^3) Tested it and assigning the values of Game.CharacterCount and Game.GUICount appear to work, but we have to remove the empty #define-s first before we can assign the new values.

And finally at the end of your main script you'll need to add these lines in:

Code: ags
#ifdef IS_AGS_3_0
#undef AGS_MAX_CHARACTERS
#undef AGS_MAX_GUIS
#undef IS_AGS_3_0
#endif


This will destroy our "temporary" #define-s now that we're done with them.

Note that this method will NOT work if you were using the AGS_MAX_* constants to create arrays of custom structs as AGS 3.0 does not currently allow for dynamic arrays of custom structs. With luck future versions will allow this, but until then the only alternatives for scripts relying on these custom struct arrays would be a) separate version-dependent scripts or b) reworking the script to not require the struct.

In any case, I hope perhaps some of my fellow moduleers will find this useful. ;)
#165
Since a certain somebody won't quit pestering me, I've decided to just use my third-place entry from the December '06 colouring ball for this week[ish]'s animation competition:


Mirror

I'm not very good at art much so I realize this looks nothing like its unnamed reference picture, but as I said, it got me third place (see my siggy :D) and I figure it's good enough for an animation.

Make him do something exciting. Break-dancing. Exploding. Spontaneously combusting. Bonus points for originality of the idea. ;)

I'll go ahead and open the competition today: 25 October and run it for a couple days past the one-week mark. Ready? Go!
#166
General Discussion / Wireless woes...
Tue 16/10/2007 05:37:04
My younger sister was given a computer by our grandmother a while back. It's worth noting that my grandmother is amongst the least tech savvy people in the world, though she definitely does always try new things...which invariably screws up her computer...which I invariably have to repair...but I digress.

The computer is rather old as indicated by the Pentium II CPU, 256 MB of RAM, and 6 GB HDD. However my grandmother still found it necessary to install Windows XP. Alongside her existing Windows 98 installation. Not over the top...she wanted to keep both OSes installed. However she later decided to manually remove Windows 98 by simply deleting all the files.

Essentially this computer was screwed. So I decided on my favourite cure-all solution. Format the hard drive! Somehow I always tend to forget how many problems this generally creates...though once set up it usually does solve a lot of problems simply by doing a clean install.

It was easy formatting and installing Windows 98; the problems started from there. My sister has a Linksys Wireless-G USB Network Adapter that I couldn't get to install properly on Windows 98. So I figured that hardwiring her computer to the router and installing Windows Updates might fix the problem. This lead to more problems...

Namely the fact that her Ethernet card apparently didn't have a driver installed either. I tried several generic drivers (unsuccessfully) before I came across one intelligent post on some tech forum. It said that most cards have some type of manufacturer or part number listed on the card. So I opened up the case and sure enough, right there on the card was the manufacturer and part number. With this I was able to download the proper driver to install the Ethernet card.

Now I was finally able to connect to the Internet on my sister's computer....maybe. See...the first edition of Windows 98 was released with Internet Explorer 4. Funny thing about the internet though...it has a way of evolving. So much so that most web pages don't work well (if at all) with IE4. "Most web pages" including Microsoft's website...up to and including Windows Update. So I tried copying the IE6 downloader/installer to my sister's computer. It wouldn't connect.

I searched for hours to find a FULL version of IE6 instead of the downloader route. Once that was installed I was finally able to run Windows Updates. I was somewhat upset to find out that the updates still didn't find a better display adapter though. At this point I was still running at 640x480 resolution in 16-color (not 16-bit) mode. Then I came across this website which tells how to determine which graphics/video card your computer is using.

Since my sister has on-board graphics it was hard for me to try and determine this and testing random adapters was getting troublesome. But using the Windows debugger I was able to determine that she has an nVidia Riva 128. After hours of staring at the same 16 colors I was finally able to change to 800x600x16. So much nicer.

However...there's still one pending issue. The wireless USB adapter. Even after updating Windows the adapter still has that stupid yellow exclamation point. The error is apparently (from what I've read) due to two drivers: NDIS.VXD and NTKERN.VXD. From the research I've done, this is a rather common problem between Windows 98 and several network adapters (wired and wireless). The only solution I can seem to find for FIRST EDITION Windows 98 users...upgrade.

The problem is that this isn't really practical. If anyone knows any other solutions, any suggestions would be much appreciated. Other than that about the only thing I can think of would be to get the drivers from someone with Windows 98SE (Second Edition). :-\
#167
Wouldn't it be nice if there were some way to render text as a sprite?

Workaround:

Code: ags
DynamicSprite* RenderTextAsSprite(int width, FontType font, int color, String text, Alignment align) {
  if ((width <= 0) || (font < 0) || (font >= Game.FontCount) || (text == null) || (text == "")) return null;
  DynamicSprite* sprite = DynamicSprite.CreateFromScreenShot(width, GetTextHeight(text, font, width));
  DrawingSurface* surface = sprite.GetDrawingSurface();
  surface.Clear();
  if (color < 0) color = 0;
  surface.DrawingColor = color;
  String buffer = "";
  int i = 0, w = 0, y = 0;
  while (i < text.Length) {
    if (GetTextWidth(buffer.AppendChar(text.Chars[i]), font) <= width) buffer = buffer.AppendChar(text.Chars[i]);
    else {
      while ((buffer.Contains(" ") != -1) && (buffer.Chars[buffer.Length - 1] != ' ')) {
        buffer = buffer.Truncate(buffer.Length - 1);
        i--;
        }
      w = GetTextWidth(buffer, font);
      if (align == eAlignLeft) surface.DrawString(0, y, font, buffer);
      else if (align == eAlignCentre) surface.DrawString((width - w) / 2, y, font, buffer);
      else if (align == eAlignRight) surface.DrawString(width - w, y, font, buffer);
      y += GetTextHeight(buffer, font, w + 1);
      i--;
      buffer = "";
      }
    i++;
    }
  w = GetTextWidth(buffer, font);
  if (align == eAlignLeft) surface.DrawString(0, y, font, buffer);
  else if (align == eAlignCentre) surface.DrawString((width - w) / 2, y, font, buffer);
  else if (align == eAlignRight) surface.DrawString(width - w, y, font, buffer);
  surface.Release();
  return sprite;
  }


Such a function would also provide a workaround for the outstanding request for aligned textual overlays (using a graphical overlay instead):

Code: ags
Overlay* OverlayCreateTextualAligned(int x, int y, int width, FontType font, int color, String text, Alignment align) {
  DynamicSprite* sprite = RenderTextAsSprite(width, font, color, text, align);
  if (sprite == null) return null;
  return Overlay.CreateGraphical(x, y, sprite.Graphic, true);
  }


BUG NOTE: Scripting the workaround for the text rendering function actually led me to discover what I believe would be considered bugs in AGS. For example, when using hyphens (-) and periods/full stops/dots (.) as separators instead of whitespace (to see how AGS handled width-based line-breaking), I often found that characters at the end of the line were lost. Even when using Character.Say I found similar results with characters disappearing. Since I considered this a bug, I've tried to make sure that the above workaround function does not lose such characters in the jet stream.
#168
I was wondering what the 'default width' is when displaying character speech. I was attempting a "background-style" speech function using an Overlay, but when creating the Overlay I have to know the width. I would like to be able to default on this parameter, but I'm not sure what value to use.
#169
The first thing I was really curious about is what happens when an object gets obliterated by merging it into the background. The manual seems pretty explicit when it states:

QuoteNOTE: after calling this function, you cannot use the object any more and it is permanently removed from the game.

But what about the my scripts? Will they crash if I try to use an object after merging it? Will it horribly corrupt my computer's memory, frying my RAM (and eggs)? Will it bring "The War on Terror" to a terrifying end?

So many questions...there was only one way to find out.

Huh. It seems that even after the object has been completely and utterly destroyed...I can still access it via the script! I love AGS!

This lead to new ideas. If I can still access the instance of the Object struct...can I do other things too? Can I assign it a new graphic? Can I successfully Tint and Merge the new graphic? Can I remove the previous graphic from the room's background?

The answer is to all these questions is yes. The last seemed the least obvious since AGS doesn't have any specific function for doing so, but it would seem that the methods used by Object.MergeIntoBackground() and the RawDraw functions are the same. In short, I found that if I call RawSaveScreen, Object.MergeIntoBackground(), and then RawRestoreScreen(), the RawRestoreScreen will actually remove the object's graphic from the room bitmap.

Something else I discovered is that although I can use a single object to merge multiple tinted graphics into the room background, any "new" sprites following the object's original merged graphic apparently aren't being "painted" on the screen properly. It seems that they don't actually appear until I move the mouse over them. Unless I have saved and restored the raw state of the screen (permanently saving the previously merged sprites to the room's bitmap).

As for practical use of this knowledge, this could provide a workaround for DynamicSprite tinting but with two major drawbacks:

1. You do in fact lose an object from any room you want to use this functionality in. You can still use the object within the script. Hell, with a bit of scripting you could even make it so it were like the object was still there. But AGS will not handle it as an object.
2. Any sprite you wanted to tint would have to be at the same color depth as the current room background.

If you can live with this though, it would be possible to grab tinted copies of dynamic sprites like this:

Code: ags
// global script
DynamicSprite* dsPlayerGreyscale;

// some function
RawSaveScreen();
RawClearScreen(63519); // 'magic' transparent pink
ViewFrame* vf = Game.GetViewFrame(player.View, player.Loop, player.Frame);
object[0].Graphic = vf.Graphic;
object[0].Tint(100, 100, 100, 100, 100);
object[0].X = 0;
object[0].Y = Game.SpriteHeight[vf.Graphic];
object[0].MergeIntoBackground();
dsPlayerGreyscale = DynamicSprite.CreateFromBackground(GetBackgroundFrame(), 0, 0, Game.SpriteWidth[vf.Graphic], Game.SpriteHeight[vf.Graphic]);
RawRestoreScreen();


You could then do whatever you wanted with your tinted sprite. Clearly a DynamicSprite.Tint function would be much more beneficial to this cause...yet this is probably the first workaround I've discovered (actually before using objects I tried using DynamicSprite.CreateFromScreenshot but that requires the screen to actually reflect the changes, i.e., showing the magic pink screen, even if just for a second (or 1/40th of a second :P)). Still I think it could prove useful for someone who really felt they needed it.
#170
Implements functions for working with multidimensional dynamic arrays. Supports int, String, and float. Supports any number of dimensions of any size, but note that the total product of every dimension's size can be no larger than 1000000 (one million) as this is the current maximum size of a dynamic array.

Download BROKEN!
Read the manual online

This module was really never very useful given the number of iterations it used in trying to verify the size of the arrays. In practice it was better to create a specialized function than use the functions the module offered.

With regard to a question that was raised, AGS 3 does support dynamic arrays which is how this module was implemented. The problem with this module was that there isn't currently a way to check the size of a dynamic array so I tried to verify the size.

I may release a modified version, but until then I highly recommend taking a look at my Stack module. You can push any type of data, including other stack objects onto each stack, so simulating the multidimensional array functionality wouldn't be terribly difficult.
#171
There appears to be a bug when attempting to access a function or property of an attribute (of which every property of every AGS managed type is). The problem was discovered by joelphilippage and Gilbot here, I have simply diagnosed why it is occurring.

QuoteBased on my tests, it would appear the reason for this bug has to do with the way AGS handles its managed types. Every property of every managed AGS type is imported as an attribute. The way an attribute works, every time the property is accessed a function is called to either get or set the value of the property. So if we type this:

Code: ags
Game.GlobalStrings[0] = "Hello";
Game.GlobalStrings[0] = Game.GlobalStrings[0].Append(" World!");


What is actually happening (internally) is this:

Code: ags
Game.seti_GlobalStrings(0, "Hello");
Game.seti_GlobalStrings(0, Game.geti_GlobalStrings(0).Append(" World!"));


The return type of the Game.geti_GlobalStrings function is a String, however we obviously can't directly call the Append function on the returned String. This is where the bug occurs, and it probably isn't one that could easily be fixed any time soon, so the safest bet is to do the following instead:

Code: ags
Game.GlobalStrings[0] = "Hello";
Game.GlobalStrings[0] = String.Format("%s World!", Game.GlobalStrings[0]);


Which will be handled internally as:

Code: ags
Game.seti_GlobalStrings(0, "Hello");
Game.seti_GlobalStrings(0, String.Format("%s World!", Game.geti_GlobalStrings(0)));


Which is why it works.

The problem directly deals with the way attributes work which means that things like the Game.GlobalStrings are only useful for storing/retrieving text values, but attempting to call any of the normal String functions/properties, such as to retrieve the String's length, append text, etc. will cause a compile-time crash.

A workaround for the Append/AppendChar functions would be to use the Format function instead, however if you want to get the Length, access the individual Chars, or any of the other functions/properties you would first need to copy the global String into a local copy like this:

Code: ags
String gs10 = Game.GlobalStrings[10];
Display("global string 10 length: %d", gs10.Length);


As mentioned in the above quote, this would probably be difficult to fix as the way attributes are handled would have to be completely revised, but I think it is important that the bug be recognized.
#172
Seeing as HoN hasn't logged on in over 4 months, I figure it's probably safe to adopt his module. I've fixed some bugs that I encountered with HoN's module directly linked to the reliability of the data encryption (i.e., the ability to successfully decrypt it, not the strength of the encryption).

There are no longer any Raw functions; all data is encrypted so that if the file is read back a char at a time it can be successfully decrypted. Raw functions would break this functionality.

I've also added functions for encrypting/decrypting a single file (at a time) in the background. This way you can, for example, encrypt your data prior to distribution then decrypt it while the user plays the game. The default rate for encryption/decryption in the background is 1024 bytes per game loop (which my tests show result in no hit to game speed). This translates to 1 KB per game loop or ~40 KB per second. Any rate higher than this will result in DRAMATIC drop in game speed, although you can specify a lower value if you wish.

This module should be compatible with AGS 2.72 and 2.8 Beta 1+. I haven't tested it on any other versions, though it may be compatible with other versions 2.71 (it uses the new-style Strings; it will not be compatible with 2.7; also it only may be compatible with 2.71). Note that when importing it into 2.72 I received a warning that the module may be corrupt, however it compiled and ran perfectly. This may be an issue with exporting the module from AGS 2.8...?

Other than that...you can read the manual online here which includes the new function/property list as well as a description of how to use them. Feel free to ask if you have any questions.

And finally, you can download the module here.

You can also download the sample game I've written for testing encryption/decryption of a video here (Requires AGS 2.8 Beta 5+).
#173
Trying to display multiple characters back from a file at once, I discovered what would appear to be a bug. I did this:

Code: ags
File f = File.Open("file.txt", eFileWrite);
f.WriteRawChar('x');
f.WriteRawChar('y');
f.WriteRawChar('z');
f.Close();
f = File.Open("file.txt", eFileRead);
Display("read back: %c, %c, %c", f.ReadRawChar(), f.ReadRawChar(), f.ReadRawChar());
f.Close();


The expected output of course being:

read back: x, y, z

However the actual output I got was this:

read back: z, y, x

Splitting the single Display statement into three gave me the output I expected, printing out the letters in the desired order.

If anyone could shed any light on why this behaviour takes place it would be greatly appreciated. Until then I can simply split up my output.
#174
Someone I know recently convinced me to sign up for (against my better judgment) yet another of these sites claiming to pay you simply for completing their sponsor's offers. Most of these simply include "fill out the first two pages of 'Click Here to claim your FREE* PS3/Xbox 360/HDTV/Laptop/etc.'" and the like.

According to the site, their minimum payout is $10USD. I currently have...been wasting a lot of time on this site, yes...and have about $50USD in pending offers, and only $3USD in completed offers.

The person who convinced me to register for the site insists it's legitimate, and it seems like it might be, but honestly, how can I expect to get paid just for sitting on the computer filling out surveys for "FREE*" items I'll never see?

I'll withhold the name of the particular site (since I think it may be taboo to mention specifically which one I've registered to), but has anyone ever actually done this type of thing and received ANY payment (no matter how minimal)? It just seems a bit too good to be true...so my instinct tells me it probably is.

Yes...well I have to go to "work" tomorrow...and I have to go early at that. So I need sleep. Adios.
#175
Although it's not necessarily a high-priority request, would it be possible to implement some method of simulating the built-in functions such as on_mouse_click, on_key_press, on_event, etc.?

I have a certain idea I've been playing with, but something that's been preventing me from realizing the idea is that I have no way of calling these functions...properly. Within a module I can have my own versions of these functions which I could call, but what I need is rather to tell AGS to react as though the function was being called normally, i.e., queuing up the function from every script.

What I'm thinking of isn't high enough priority for me to go into any detail (as with most of my requests :P), however it suffices me to say that for this particular idea simulating these functions is the only possible solution. If it's not possible, or just not a practical request, then so it shall be. 8)
#176
My time spent in these forums has been less and less these days, and sporadic as well. But I couldn't help but look when I saw yet another Monkey Island thread getting locked. Cyrus in his enthusiastic spasm of love for the games dug up a rather old thread. I don't mean to single him out, lots of people do this. He's just the most recent example.

Anyway, it reminded me of this thing my friend sent me once...

lol, Monkey Island!

To me...that is one of the most accurate depiction of the mind of 70% of the budding 13 year olds who come across this website I've ever seen. :D

On the topic of Monkey Island 2's The Man Now, Dawg!:

Acappella Stan sells to Guybrush
Guybrush shuts Stan the hell up
Wally, the original emo kid

That's all I've got to say about that.
#177
More suggestions for overlays. Hooray.

I would find it very useful if we had some functions to merge overlays together (possibly another for merging new sprites into the overlay). Something like this:

void Overlay.MergeOverlay(int x, int y, Overlay* otherOverlay, int width=SCR_NO_VALUE, int height=SCR_NO_VALUE)
void Overlay.MergeSprite(int x, int y, int slot, bool transparent, int width=SCR_NO_VALUE, int height=SCR_NO_VALUE)

X and Y would of course be relative to the..erm..parent overlay. WIDTH and HEIGHT would default to the width/height of the overlay/sprite you are merging in, otherwise they would be cropped.

Also it appears that there's no way to get the width or height of an overlay. This could be useful to know.

It might not be very obvious why one might need to do this, but, for example, if a module writer wanted to piece together a single graphic from several other graphics he could either use the RawDraw functions or he could use Overlays. There's really no other alternative (plugin? :X) at this point. Assuming that said graphic is expected to move around the screen, RawDraw functions wouldn't really be very practical. So then the module writer is left no choice but to use a single overlay for every single graphic he wants to use in creating this larger graphic. There's no guarantee that he will be able to create as many overlays as he needs, so it all boils down to nothing more than luck and hoping that he'll have enough overlays available to piece together this graphic. Mmm...tasty Propagandistic-logical-fallacy soup.

But seriously, in such a situation, though not necessarily the most common of cases, it could be difficult to ensure that the graphic was properly created. I have personally encountered several instances where I would have found such a function extremely beneficial, however have found myself unable to efficiently replicate any such functionality. Just an idea.
#178
Hooray...in all the spare time I have working...50...55...64 hours a week (the last two weeks' and this week's schedules (respectively))...I've managed to discover another mostly useless workaround to a major flaw in AGS. :P

It's very hackish, no guarantee that it would work in future versions, stupidly complex to actually implement for the trouble it's worth (i.e., I'm not sure the benefit outweighs the hassle of implementation)...etc., etc.

But all that aside, I've discovered a workaround to custom struct[ure]s having static properties. The basic setup goes something like this:

Code: ags
// script header

struct MyStruct {
  import static attribute int MyStaticInt; // $AUTOCOMPLETESTATICONLY$
  protected import int get_MyStaticInt(); // $AUTOCOMPLETEIGNORE$
  protected import void set_MyStaticInt(int value); // $AUTOCOMPLETEIGNORE$
  };

// main script

int MyStruct_MyStaticInt;

protected int MyStruct::get_MyStaticInt() {
  return MyStruct_MyStaticInt;
  }

protected void MyStruct::set_MyStaticInt(int value) {
  MyStruct_MyStaticInt = value;
  }


The way AGS works with static properties, you must import an attribute into the struct. So the generic formula for importing the property is something like this:

Code: ags
import static attribute TYPE NAME;


Where TYPE is the data type of the variable you want to create (i.e., int, float, String, etc.) and NAME is the name you want to give it. Adding the comment "$AUTOCOMPLETESTATICONLY$" will tell the script autocomplete to only autocomplete the property if it is being accessed statically.

You must then import get/set functions for the property like this:

Code: ags
import TYPE get_NAME();
import void set_NAME(TYPE value);


You can optionally make them protected, however if you do this you can't access these function from within any static functions of your struct (if you will need to access the static property from within your static functions, it is advised you leave the "protected" keyword off). If you don't need access to them within static functions, it will help to hide/protect the functions from the users, as they don't really need to use the get/set functions, they have direct access to the static property. Another method of security you can put in place (though it won't actually prevent the user from calling these functions, it will hide them from the autocomplete) is to put the comment "$AUTOCOMPLETEIGNORE$" at the end of each of these lines. This will make the autocomplete ignore these functions.

Next, in the main script, you must define a local variable that will be used internally for storing the value of the static property. Basically the static property will just serve as a pointer to this variable; if this variable changes, so will the static property. So, in the main script put:

Code: ags
TYPE STRUCTNAME_NAME;


You'll also need to define the get/set functions for our static property which due to the way this hack works is simply going to access our local variable:

Code: ags
TYPE STRUCTNAME::get_NAME() {
  return STRUCTNAME_NAME;
  }

void STRUCTNAME::set_NAME(TYPE value) {
  STRUCTNAME_NAME = value;
  }


So...maybe it would just be easier to implement get/set functions for the user to actually use. Or maybe it would be easier to import the variable outside of the struct. Who knows? Goodness knows I don't. But I do know how to make it work as a static variable. 1+ up for me. I think. Maybe. I need sleep.

[EDIT:]

I forgot to mention...if you want to access the static property from within other member functions, you must use the get/set functions OR access the local variable directly.

i.e.:

Code: ags
// script header

struct MyStruct {
  import static attribute int MyStaticInt;
  // blah
  import void RandomizeStaticInt(int min, int max);
  };

// main script

// blah

void MyStruct::RandomizeStaticInt(int min, int max) {
  // this.MyStaticInt = Random(max - min) + min; // THIS WILL CRASH
  // MyStruct.MyStaticInt = Random(max - min) + min; // THIS WILL ALSO CRASH
  // this.set_MyStaticInt(Random(max - min) + min); // doesn't crash
  // MyStruct_MyStaticInt = Random(max - min) + min; // doesn't crash
  }


You can access the static property anywhere you like so long as the structure has been defined (:P) and you're not trying to access it from within a member function of the structure.

Failure to comply with the access procedures will result in a run-time error such as (from AGS 2.8 alpha 6):

Quote---------------------------
Adventure Game Studio
---------------------------
An internal error has occurred. Please note down the following information.
If the problem persists, contact Chris Jones.
(ACI version 2.80.923)

Error: is_script_import: NULL pointer passed

---------------------------
OK   
---------------------------
#179
I know it's pretty basic to set this up, but it would be nice if AGS had a built-in method for calculating absolute value. I'm envisioning something like Math.Abs(float) because we could then use it properly with floats and for integers we could just pass in IntToFloat(X).

Workaround
Code: ags
// script header:
import float abs(float value);

// main script
float abs(float value) {
  if (value < 0.0) return -value;
  return value;
  }


Basically it would just be nice if say, a module writer wanted to use it in more than one of their modules they wouldn't have to duplicate the function...besides how hard would it really be to implement into AGS*? ;)

*I know Chris is updating the Editor right now for v2.8, but how about for v2.9 Beta 1 eh?
#180
Hey guys...so my mom bought a 320 GB SATA HDD for our computer that she wants me to install...but she doesn't want my stepdad to find out. Our computer is currently running 2 IDE HDDs (80 and 30 GB), so she wants to put the 30 GB drive in my sister's *ancient* computer which only has a 4 GB HDD.

I got everything hooked up...buuuuttt...the computer won't boot. I figured out that it actually won't boot up unless both the 80 GB and 30 GB HDDs are plugged in...does anyone know how I can fix this? I kind of need to get this computer put back together before my stepdad wakes up.....HELP?

Thanks,

monkey
SMF spam blocked by CleanTalk