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

#501
internal constructors would probably work for what I was proposing. I still think that static classes make sense as an indication that a type is only used to organize related data (methods and properties), all of which are static themselves, of course.
#502
Here's my thoughts on the discussion so far:

* static structs should be allowed where they make sense, like Game, Room, and System.
* The Mouse.x and Mouse.y instance fields should be replaced by static properties, and the struct made static.
* The compiler will also then need a fix for accessing non-static members of a static member, e.g., System.AudioChannels[3].PlayingClip
* The new keyword internal should be added for structs that cannot be instanciated using keyword new
* internal structs should have access to a protected constructor, and should be able to return managed instances of the class by invoking it (e.g., via a static Create method, where appropriate)
* If reasonably possible, every existing "managed struct" should be revised to be an "autoptr managed struct" (this seems to work for user types already!)
* "autoptr managed struct" should be replaced by the new keyword class, a nullable reference type

Expanding from my earlier sample code, this feels much nicer:

Code: ags
function game_start()
{
  DynamicAttribute da1 = DynamicAttribute.Create();
  da1.DisplayInfo();
  DynamicAttribute da2 = DynamicAttribute.Create(42, "3.14", "Hello World!");
  da2.DisplayInfo();
  da1.iProperty = 24;
  da1.fProperty = 4.13;
  da1.sProperty = "!dlroW olleH";
  da1.DisplayInfo();
  DynamicAttribute array[] = CreateDynamicAttributeArray(5);
  array[3].iProperty = 1234;
  array[3].DisplayInfo();
}


I avoided dealing with "pointers" by defining the type as "autoptr managed struct DynamicAttribute" (hence my extension of Calin's suggestion to rename it to "class").

This will break a lot of things in user scripts, but I think it's necessary moving forward to develop the language.

Edit: btw, inb4wut -- I just wanted to point out, before anyone gets all flustered and confused, that AGS already has the autoptr keyword, but the only case where it's used is the String type. I'm not sure if it's fit for general use, which is why I said, "If reasonably possible...". As I said though, it seems to run without causing any problems.
#503
Quote from: SpeechCenter on Fri 04/07/2014 04:49:55By the way, I would still consider changing the classes to static to indicate classes that cannot be instantiated, assuming backwards compatibility can be maintained. Hence it would allow using a static class modifier in the language.

I definitely agree that since we already have a static keyword, that it makes sense to reuse it to allow pure static classes, like Game, Room, and System (and Mouse too, if we could get proper X and Y static attributes to replace the instance fields -- though this would break basically every active AGS project's scripts over a capitalization issue :-\).
#504
I'm glad you got it working the way you needed. :) Cheers!

Spoiler
Code: ags
// WARNING: THE FOLLOWING CODE IS FOR DEMONSTRATIVE PURPOSES ONLY AND IS NOT FIT FOR ACTUAL USE
int GetAdjustedLength(String text)
{
  if (text == null) text = "";
  String buffer = text;
  if (buffer.StartsWith("&"))
  {
    // instead of looping through the whole string, you could...
    buffer = buffer.Substring(1, buffer.Length - 1); // snip the ampersand off
    int i = buffer.AsInt; // snag the integer value (assuming it starts with a value less than 2.14 billion)
    String buffer2 = String.Format("%d", i); // format the integer back as a string
    if (!String.IsNullOrEmpty(buffer2)) // (optional) safety check
    {
      if (!buffer.StartsWith(buffer2)) AbortGame("Blast, this convoluted mess didn't work for \"%s\"", text); // (optional) safety check
      buffer = buffer.Substring(buffer2.Length, buffer.Length - buffer2.Length); // truncate the integer length from the buffer
      // the additional safety checks, allocations, and copying this requires will most likely result in less efficient code
      // than just iterating the string yourself (even though the C++ code the engine invokes is faster than the raw AGScript)
      // also, don't ask my why I posted this. I just thought it was an interesting approach, though I'd stick to the first code.
    }
  }
  int length = buffer.Length;
  // do algorithm and stuff
  return length;
}
[close]
#505
Mouse.x and Mouse.y are non-static fields, only accessible through the mouse instance (hence my insistence that for the time being, the Mouse class not be used statically). Aside from that, the Game type only has static properties and methods, but therein is my point that creating instances of the type is useless.
#506
Double-post for an unrelated issue.

A thought just occurred to me here, but what should be the expected behavior if the user tries to create new instances of the built-in types? For example, the following code is now perfectly valid:

Code: ags
GUI *new_gui = new GUI;
Character *new_character = new Character;
Object *new_object = new Object;


Of course, while these are valid script objects, they're totally unusable. They all have invalid IDs, and other invalid read-only attributes. Attempting to display new_gui, for example, aborts with an error that an invalid GUI was specified. This makes sense of course, but should it really be deferred to a run-time crash to handle this?

Making matters even worse is the auto-pointer nature of the String class:

Code: ags
String s = new String;


May look perfectly fine, and it even compiles now! But when the run-time encounters this line, it crashes with an error message that a user object of 0 bytes was requested. This isn't very friendly.

We could just denote in the manual that the new keyword is not meant for any basic or built-in types, but nobody reads the manual anyway, so we'd end up with dozens of tech help threads due to run-time crashing.

It may actually prove useful to allow the dynamic creation of some of these built-in types, say, a temporary dummy character only needed in one room. However, this would require additional steps to ensure that these objects are created in a meaningful and useful state. Conversely, we may also need to have a way to disallow dynamic instanciation of certain types (for example, extra Game or Mouse objects wouldn't make sense).
#507
If you're already calculating the width based on the string's length, then all that's left to do is snip that bit off before you check the length...

Code: ags
String text = "&1Hello World!"; // presumably this would actually be a function parameter (static text is for example purposes only, and otherwise doesn't make sense :P)
String buffer = text;
if (text.StartsWith("&"))
{
  int i = 1;
  bool break = false;
  while ((i < text.Length) && (!break)) // find the first character that is not a number
  {
    break = ((text.Chars[i] < '0') || (text.Chars[i] > '9')); // break out of the loop if character i is not a number
    i++;
  }
  if (i < text.Length) buffer = text.Substring(i, text.Length - i);
  else buffer = "";
}
// now do the algorithm against buffer.Length instead of text.Length
#508
Quote from: Crimson Wizard on Thu 03/07/2014 12:23:04
Code: ags
Tint(int red, int green, int blue, int saturation = -1, int luminance = -1)

Other built-in functions typically defer to the SCR_NO_VALUE macro for optional parameters.
#509
Quote from: Gurok on Wed 02/07/2014 13:48:56monkey_05_06, your example should now compile.

It relates to forward declarations. They don't know the size of themselves. That's fine, but all pointer declarations should have a size of 4.

I can confirm that your fix does allow it to compile. The explanation also makes sense, as does the solution. :)

Quote from: Gurok on Wed 02/07/2014 13:48:56You should now be able to create an array of your managed struct too.

I can also confirm this is working, though it took me a second to realize that I'm now responsible for creating the objects in the array too (simple enough to handle with a "CreateArray" function). Now if only we could have dynamic arrays as struct members... (roll)

Quote from: Gurok on Wed 02/07/2014 13:48:56I haven't implemented constructors, but I'll be adding them after I fully investigate this pointer issue. And possibly clean up some other areas.

This will definitely be helpful as well. :)
#510
Quote from: Crimson Wizard on Tue 01/07/2014 16:08:54Properties fail to work for some reason (unresolved import with weird error message).
I suspect that compiler needs to handle special case there.

Actually, they work fine (download my test case). Since you're working with a user-defined type, the user also has to define the accessor methods. I've used extender methods so the accessors don't show up as normal member methods, but it is apparently working! :) And just in case anyone hasn't seen it, the attribute tutorial in the wiki is probably a good place to start.

The one issue I did have was with a static method returning a new pointer to the user type. The compiler complained that the "Size of identifier does not match prototype":

Code: ags
managed struct UserObject
{
  import static UserObject* Create();
};

static UserObject* UserObject::Create() // apparently doesn't work! "Size of identifier does not match prototype"
{
}


Other than that, this is pretty useful and exciting stuff. Thanks for taking the time to look into it. :=
#511
Quote from: slasher on Mon 30/06/2014 06:00:20Game.MinimumTextDisplayTimeMs would work but I would have to change it every time before and after (with / without a function for it).

This is the entire purpose of functions, especially custom ones like Khris provided. Knowing when to create a custom function (e.g., whenever you're calling more than a few lines of functionally identical code from more than one or two places in your script) is one of the most basic concepts of programming. You really should stop trying to find ways around it.
#512
As an additional note, you could also set Game.MinimumTextDisplayTimeMs before and after calling DisplayTopBar to ensure the text is displayed for a minimum duration of time before disappearing. The values of TextReadingSpeed and MinimumTextDisplayTimeMs are used just-in-time when speech/display functions are called, so there's no reason this shouldn't work.
#513
#514
Quote from: Crimson Wizard on Sun 22/06/2014 21:30:07Also, probably AGS.Native should be completely rewritten into C# (probably should be anyway).

This.

I'm working and going to school full-time, so my spare time has been greatly diminished, but given the preliminary work I did in porting the room loading code into C#, I feel pretty confident that I could make some headway on this front.
#515
All part of the engine you're writing from scratch in Lua amirite?

on_mouse_click ignoring clicks on GUIs was an intentional, by-design feature of the engine to distinguish between clicking anywhere in the actual game versus an interface_click. You can call it a stupid naming convention all day long, but there was obvious logic behind it. Oh, and you can make sure to not make any stupid blunders like that in your engine. Which is releasing soon, amirite? I mean, I've been holding my breath waiting for the first ever modern game engine, the first ever game engine to use a real language like Lua, the first ever modern game engine designed to make 2D, 2.5D, and 3D games with the same ease of use, the first ever game engine to allow you to make commercial games, the first ever game engine to run on every platform from DOS to PS4. Can't wait.
#516
Quote from: Calin Leafshade on Mon 16/06/2014 22:39:52I still think this distinction is utterly stupid.

This is due to the fact that AGS treats inventory items as part of a GUI (for which on_mouse_click is not called). While it would make sense (now) to make this invisible to the user (and probably add a proper LocationType for InventoryItems as well), it would actually break existing game scripts -- the very reason why it is the way it is.

Of course, considering AGS is completely broken and unusable for any purpose, someone should just write a new one in Lua anyway.
#517
I don't think Resonance used AGS 3.3.0 seeing as it (the game) was released two years ago.

You could try running the game with the 3.3.0 engine though. IIRC you can copy the 3.3.0 "acwin.exe" file into the game directory and then create a shortcut that targets "acwin.exe resonance.exe". Could be wrong about that last bit, but I know you can run the game using different engine versions.
#518
You could just use the actual sprite slot numbers as the password key. Something like:

Angel Sprite: 72
Catapult Sprite: 43
Chimera Sprite: 115
Correct Password: 4311572

Angel x3 = 727272
Catapult-Chimera-Chimera = 43115115
Chimera-Angel-Chimera = 11572115

You could simply use:

Code: ags
sPassword.Append(String.Format("%d", clickedPanel.Graphic));


where clickedPanel is an Object* to whichever panel was most recently clicked on. This approach could be problematic if you have, say, a fourth sprite slot number 243, because then the sequence "24311572" would end with "4311572". So, you'd have to watch out for that caveat and maybe change some sprite numbers, but otherwise it's functionally the same.
#519
Beginners' Technical Questions / Re: Agstouch?
Sat 07/06/2014 05:02:48
AFAIK that is a plugin developed directly by WEG. They're usually willing to share stuff like that if you ask them. ;)
#520
You authored that code yourself, and it doesn't reference the Steamworks API, so I have no issues with you leaving the code public. Bear in mind that the Steam for Linux version of AGS games uses the original Windows EXE (meaning, no DRM) and there are official versions of the AGSteam plugin available for Linux. If you want to include other features in your stub then feel free -- I can't tell you what to do with your own code. By comparison, if the Steam client isn't running then the official AGSteam plugin functions should all be no-ops.
SMF spam blocked by CleanTalk