AGS Awards votes close at 13:59 BST on Wednesday 07 March 2018. You've already voted, so you've got 14 days and 2 hours left to wait before voting closes!

Show Posts

You can view here all posts made by this member. Note that you can only see posts made in areas to which you currently have access.


Topics - Snarky

Pages: [1] 2 3 ... 10
1
It's time to start working on the client for the 2017 AGS Awards! 8-0

I plan to handle the coding side of things again, but I could really use some help with the resources. Some of them are starting to show their age, and the update last year was a bit of a rush job, with ugly placeholder elements.

Add spoiler tag for Hidden:


Notice the use of three different button styles, unstyled listboxes, and the crude red arrow highlighting your character.
A list of things I have in mind (for overall reference, the client is 1280x720 in 32-bit):

  • New buttons and GUI elements. I intend to redesign the GUI quite a bit, moving away from the black screens that currently cover up the entire background. I'm leaning towards a tabbed interface. I also want to make all the buttons consistent, and make it so they fade out unless you move the cursor close. The chat history window also needs to be fixed. This task might involve collaborating on the UI redesign, or just making a template for the button/slider styles or drawing graphics for the button symbols.
  • Related to that: Perhaps a new cursor (not sure I like the current one), and definitely a new "character highlighter". Currently it's just a crude red arrow; I was thinking an animated glowing ball oscillating up and down over your head. (Might want this in two colors: one for you and one for highlighting other characters.)
  • Trophies! It would be really cool if winners could receive an actual trophy. There was a trophy in SSH's non-online Awards ceremony games, but I don't think the graphic style really fits:
    Add spoiler tag for Hidden:
  • Graphics and animations for the on-stage screen (320x240 canvas, with the top partially obscured):
    • New animated "interstitial" screens: some kind of AGS logo, or saying "2017 AGS Awards" or something like that, with some sort of calm (looping) animation livening it up. (The 2015 client had one of these, but I don't have access to it.)
    • Screens announcing the various categories (Best Backgrounds, Best Voice Acting, etc.): Probably some kind of logo or drawing symbolizing that category.
    • New "animated gif" meme-style reactions, ideally taken from AGS games or at least adventure games.
    • Surprises and other fun things to put up on the screen.
    • And if any graphically gifted AGSers have good ideas for how to format the presentations of nominees and winners in each category (particularly for things like Best Character, Best Animations, Best Character art), I'm all ears.
  • New DJ characters/platform (updating or replacing the pixel Daft Punk).
  • Also, new music for the DJs to play! A range of tunes, from catchy party music to calm background audio. New/alternative music cues for the ceremony would also be interesting.
  • There was some complaint last year that the font was difficult to read. If anyone has any suggestion for fonts to use for the chat window or above characters' heads (or other things), let me know. (We should be able to do proper rendering and outlining of antialiased text now, so don't feel limited to pixel fonts.)

Also, Noa's performance of "Troll Song" from the 2014 ceremony was one of my favorite parts of that event, and it would be cool if anyone wants to do something like that (or has some other idea to enrich the show):



Finally, I hope to improve the dynamic applause system, and make a similar system for dynamic laughter. (I'm also considering adding "crowd noise".) To make that happen, I need a pool of audio clips to use.

Add spoiler tag for Hidden:
For the applause, I currently have six levels of intensity, depending on how many people are clapping (single person clapping, scattered applause, modest applause, general applause, enthusiastic applause, ecstatic applause), each with short and long clips (short clips are played during presentations, long clips when the floor is open). For some levels there are a couple of different clips of each type, picked at random. All in all, there are 20 different clips of people clapping (some of which aren't that great, and should be replaced). Something similar would be nice for laughter. Tracking down and editing the clips is quite time-consuming, so if someone wants to help out with that I'd appreciate it. (Also, the clips should be properly licensed, giving us the right to use them.)
Oh, and like every year, AGS character avatars are much appreciated! Send me your chars!

Exactly how we're going to do this depends a bit on your interest and feedback. For some things we might run a contest or workshop thread. Mostly it'll probably be discussions over PMs.

I can't guarantee the inclusion of what you make in the ceremony, so if you're thinking of doing something that would be a lot of effort, maybe run it by me first (e.g. if 20 different people each want to do some sort of performance, that's probably a bit much – we might have to arrange a separate AGS Talent Night instead).

3
PC Gamer is running an interview by Richard Cobbett with Eugene Sandulenko ("Sev"), the ScummVM project lead, on the occasion of the release of ScummVM v2.0 (hooray!)

He has this to say about AGS (not hooray!):

Quote
The most notable omission though has to be AGS—Adventure Game Studio. This is the software behind 99 percent of freeware and indie adventures this side of the millennium, ranging from the Chzo Mythos and Larry Vales to the Blackwell series and next year’s Unavowed. Early versions are a pain, to put it mildly, as anyone who’s ever tried getting something like Quest For Glory IV 1/2: So You Thought You Were A Hero to run can attest. (Top tip: don’t!) The audience and features seem perfect for ScummVM. Yet still, no support.

"AGS is... unfortunate for us," admits Sandulenko. "Once the original author published the source code, we were pretty excited and we started working on it. We really had high hopes. But then when we mentioned it in the AGS forums, where the game authors are, there was a huge uproar. They didn't want it. They disliked the idea. They jumped on our poor developer so hard that they left in disgust, not wanting to touch it any more. I don't know why there was such opposition. We wanted to do it in the proper way, in the ScummVM spirit, and keep it updated as AGS was upgraded and improved over time. Later there was some talk of 'letting' us handle old game compatibility and so on, but... well, yeah... thanks? That’s not really in the spirit of our project."

Most of the debate he's referring to is in this thread. I would say his summary mischaracterizes the events a great deal.

4
Christmas! It's the most wonderful time of the year, according to some. I'm a total sucker for all the sappy, romanticized Christmas kitsch, and I'm sitting here looking at the snow falling outside, about to bake some lussekatter (saffron buns).

So, in the spirit of the season, what are some good Christmas-y adventure games?

6
I'm having a weird issue with Speech.SkipStyle. When it is set to eSkipTime (which is 2), it reports its value as -1 instead:

Code: Adventure Game Studio
  1.   Speech.SkipStyle = eSkipTime;
  2.   Display("Speech.Skipstyle is %d. eSkipTime is %d", Speech.SkipStyle, eSkipTime);

This displays "Speech.Skipstyle is -1. eSkipTime is 2"

Other than that, it appears to work OK. Speech behaves correctly: it times out but cannot be dismissed with mouse or keyboard.

If I try to actively set Speech.SkipStyle to -1, the game crashes, with an error message saying I used an illegal value.

7
This code is part of the SpeechBubble module I just posted, but since it has more general-purpose application, I thought it deserved its own post.

Displaying text with a TrueType (.ttf) font in AGS has some well-known limitations:

  • If you place anti-aliased text on a semi-transparent background (e.g. as a label on a semi-transparent GUI), the anti-aliasing "pokes holes" in the background. This looks terrible.
  • With anti-aliased text, the AGS auto-outline feature often does not work very well, with gaps and other artifacts.
  • The auto-outline can only be one pixel wide.
  • The outline can only be black. (You can set it to a different color using game.text_shadow_color, but it will affect ALL the text on the screen.)

Here are two functions to work around those issues. They take advantage of the fact that DrawingSurface.DrawImage() does correct alpha-blending. You can use this to draw an anti-aliased string onto any DrawingSurface without artifacts. And by "stamping" multiple copies of the string in a pattern of 1-pixel displacements, you can also create an arbitrarily wide outline of any color you like.

The drawback is that it is slower, particularly if you want to draw a very wide outline (a 5-pixel outline will do something like 20 DrawImage() operations). However, I've found that in practice it runs fast enough to not be a problem for typical uses. (There are also some optimizations still possible in this code, particularly if you don't need the ability to draw the text at <100% opacity.)

Code: Adventure Game Studio
  1. /// The shape of a text outline
  2. enum TextOutlineStyle
  3. {
  4.   /// A circular, rounded outline
  5.   eTextOutlineRounded = 0,
  6.   /// A square "block" outline
  7.   eTextOutlineSquare
  8. };
  9.  
  10. // To work around the AGS bug where antialiasing "pokes holes" in semi-transparent canvases
  11. void drawStringWrappedAA(this DrawingSurface*, int x, int y, int width, FontType font, Alignment alignment, String message, int transparency)
  12. {
  13.   DynamicSprite* textSprite = DynamicSprite.Create(this.Width, this.Height, true);
  14.   DrawingSurface* textSurface = textSprite.GetDrawingSurface();
  15.   textSurface.DrawingColor = this.DrawingColor;
  16.   textSurface.DrawStringWrapped(x, y, width, font, alignment, message);
  17.   textSurface.Release();
  18.   this.DrawImage(0, 0, textSprite.Graphic, transparency);
  19.   textSprite.Delete();
  20. }
  21.  
  22. // Draw a string with outline (make sure the canvas has at least outlineWidth pixels on each side of the string)
  23. void drawStringWrappedOutline(this DrawingSurface*, int x, int y, int width, TextOutlineStyle outlineStyle, FontType font,  Alignment alignment, String message, int transparency, int outlineColor, int outlineWidth)
  24. {
  25.   // This is what we draw on (because we might need to copy with transparency)
  26.   DynamicSprite* outlineSprite = DynamicSprite.Create(this.Width, this.Height, true);
  27.   DrawingSurface* outlineSurface = outlineSprite.GetDrawingSurface();
  28.  
  29.   // This holds multiple horizontal copies of the text
  30.   // We copy it multiple times (shifted vertically) onto the outlineSprite to create the outline
  31.   DynamicSprite* outlineStripSprite = DynamicSprite.Create(this.Width, this.Height, true);
  32.   DrawingSurface* outlineStripSurface = outlineStripSprite.GetDrawingSurface();
  33.  
  34.   // This is our "text stamp" that we use to draw the outline, we copy it onto outlineStripSprite
  35.   DynamicSprite* textSprite = DynamicSprite.Create(this.Width, this.Height, true);
  36.   DrawingSurface* textSurface = textSprite.GetDrawingSurface();
  37.  
  38.   // Draw our text stamp
  39.   textSurface.DrawingColor = outlineColor;
  40.   textSurface.DrawStringWrapped(x, y, width, font, alignment, message);
  41.   textSurface.Release();
  42.  
  43.   switch(outlineStyle)
  44.   {
  45.     case eTextOutlineRounded:
  46.     {
  47.       // Draw Circular outline
  48.       int maxSquare = outlineWidth*outlineWidth+1; // Add 1 for rounding purposes, to avoid "pointy corners"
  49.       int maxWidth = 0;
  50.       outlineStripSurface.DrawImage(0, 0, textSprite.Graphic);
  51.       // We loop from top and bottom to the middle, making the outline wider and wider, to form circular outline
  52.       for(int i = outlineWidth; i > 0; i--)
  53.       {
  54.         // Here's the circular calculation...
  55.         while(i*i + maxWidth*maxWidth <= maxSquare)
  56.         {
  57.           // Increase width of the outline if necessary
  58.           maxWidth++;
  59.           outlineStripSurface.DrawImage(-maxWidth, 0, textSprite.Graphic);
  60.           outlineStripSurface.DrawImage(maxWidth, 0, textSprite.Graphic);
  61.           outlineStripSurface.Release();
  62.           outlineStripSurface = outlineStripSprite.GetDrawingSurface();
  63.         }
  64.         // Draw outline strip above and below
  65.         outlineSurface.DrawImage(0, -i, outlineStripSprite.Graphic);
  66.         outlineSurface.DrawImage(0, i, outlineStripSprite.Graphic);
  67.       }
  68.       // Finally the middle strip
  69.       outlineSurface.DrawImage(0, 0, outlineStripSprite.Graphic);
  70.       break;
  71.     }
  72.     case eTextOutlineSquare:
  73.     {
  74.       // Draw square block outline
  75.       // Just draw the full outline width onto the strip
  76.       for(int i = -outlineWidth; i <= outlineWidth; i++)
  77.         outlineStripSurface.DrawImage(i, 0, textSprite.Graphic);
  78.       outlineStripSurface.Release();
  79.       // Draw the full outline height
  80.       for(int j = -outlineWidth; j <= outlineWidth; j++)
  81.         outlineSurface.DrawImage(0, j, outlineStripSprite.Graphic);
  82.       break;
  83.     }
  84.   }
  85.   textSprite.Delete();
  86.   outlineStripSurface.Release();
  87.   outlineStripSprite.Delete();
  88.  
  89.   /// Now draw the text itself on top of the outline
  90.   outlineSurface.DrawingColor = this.DrawingColor;
  91.   outlineSurface.drawStringWrappedAA(x, y, width, font, alignment, message, 0);
  92.   outlineSurface.Release();
  93.   // ... And copy it onto our canvas
  94.   this.DrawImage(0, 0, outlineSprite.Graphic, transparency);
  95.   outlineSprite.Delete();
  96. }

8
Modules & Plugins / MODULE: SpeechBubble v0.8.0
« on: 03 Dec 2017, 11:28 »
Here's a module to do comic book-style speech bubbles. It's an alternative to Phylactere, because the older module doesn't work properly with 32-bit color. This module requires AGS 3.4, and for now it only works in 32-bit mode (or rather, transparency only works in 32-bit mode).

Initial development of this module was paid for by bx83, who agreed to allow it to be open-sourced.

To use, you call Character.SayBubble():

Code: Adventure Game Studio
  1.   player.SayBubble("This line will be said in a speech bubble.");

To configure, you set the SpeechBubble properties:

Code: Adventure Game Studio
  1.   SpeechBubble.BorderColor = Game.GetColorFromRGB(0,128,0);
  2.   SpeechBubble.BackgroundColor = Game.GetColorFromRGB(128,255,128);
  3.   SpeechBubble.BackgroundTransparency = 33;
  4.   SpeechBubble.PaddingTop = 5;
  5.   SpeechBubble.PaddingBottom = 5;
  6.   SpeechBubble.PaddingLeft = 15;
  7.   SpeechBubble.PaddingRight = 15;

(You should probably do this in game_start() in GlobalScript.)

This module is still under development, and is currently missing some functionality (in particular support for background speech). Please report any bugs you experience.

The module is available on GitHub.

Download SpeechBubble v0.8.0

Change Log:
0.8.0
-Implemented Character.SayBackgroundBubble()
-Added SpeechBubble.DefaultGui property
-Fixed crash with characters that don't have a speech view set

0.7.6
-Fixed an issue with lines with speech clips in text-only mode

0.7.5
-Initial pre-release

11
I want to block indefinitely until a mouse or key is pressed. AGS only offers timed blocks in WaitKey() and WaitMouseKey(), but if the timing is long enough that's probably fine. So I want to put in as big a number as I can when calling these functions.

The int maxvalue is 2,147,483,647 (according to the manual). But trying to Wait() or WaitKey() for that length of time (or 1 less, in case it has to be able to go above it) doesn't work: it just gets ignored. What's the biggest number you can provide as an argument to the Wait...() functions?

(Though since there's no WaitMouse(), I'll probably have to build my own solution anyway, with Wait(1); in a loop, and flag that gets set on the keyboard/mouse events.)

12
Is there some way to find out from within AGS how long a certain speech clip is, without playing it?

Here's why I'm asking:

When you call Character.Say() with a voice clip (e.g. player.Say("&14 This line has voice-over");), the speech lasts as long as the clip, logically enough. (Depending on your Speech.SkipStyle setting the text may stay on screen longer, but the character won't do the Talk animation.)

However, if you set your Speech.VoiceMode to eSpeechTextOnly, the voice clip is ignored, and it seems the game falls back to using the standard AGS formula for how long to display the text, based on the string length and  Game.TextReadingSpeed.

I want to be able to maintain the same timing whether or not speech is turned on. If I could get the length of the speech clip I could do that (writing my own little function to manually do the Talk animation and time it correctly).

13
I have a question for the engine experts. In 32-bit, AGS allows you to set the transparency of various things and drawing operations as a percentage (0-100). However, 32-bit color actually uses an 8-bit alpha channel internally (0-255). Do you know how this is mapped?

For example, if I set the transparency of a GUI to 3%, am I really setting it to the closest alpha value, 8? (8/255 = 0.03137..., or about 3.14%). Is this calculated as (in AGS syntax) int alpha = FloatToInt( IntToFloat(percentage)*255.0/100.0, eRoundNearest), or some other way?

14
I've noticed that a few functions in the editor don't work for enums, and one other thing for user-defined structs (I'm testing in version 3.4.0.16).

Enums
  • Auto-complete doesn't work for enum types. For example, if you want to use the built-in enum CharacterDirection, the auto-complete list pops up once you type "Cha", but CharacterDirection does not appear in the list. This is also true of user-defined enum types.
  • The "Go to definition" function (available by right-clicking on an instance of the enum name in the editor) doesn't work for user-defined enum types (and obviously not for built-in enum types). Nothing happens. However, "Find all usages" does work, with the definition included in the list of results.
  • A smaller matter, but if you declare an enum variable and try to set it on the same line, the auto-complete dropdown with the valid values doesn't appear right away when you type "=". Once you start typing a name, the regular auto-complete (with all other matching tokens as well) shows up after three characters as usual. Again, this applies both to built-in and user-defined enums. So, for example:
Code: Adventure Game Studio
  1.   CharacterDirection exitDirection = eDirectionLeft;

You get no dropdown after "=". After "eDi" you get the full list with "eDirectionDown" (the first matching token) highlighted. But:

Code: Adventure Game Studio
  1.   CharacterDirection exitDirection;
  2.   exitDirection = eDirectionLeft;

On the second line you get a dropdown after "=" with just the CharacterDirection values.

Ideally you would get a list with all the CharacterDirection values AND all the CharacterDirection variables only. Alternatively the list of values could show up after the =, but if you type something else it could disappear and after three characters you'd get the the full list. In any case, it should probably behave the same way whether you define and set the variable on one line or multiple.

Structs
  • For user-defined structs, the right-click situation is reversed. "Go to definition" works, but "Show all instances" doesn't. Or rather, it only finds instances in the current script. This applies both to the data type and to variables of that type. So if you export a user-defined struct variable from your script and use it in some other script, "Show all instances" will incorrectly claim that it's not being used anywhere else. This is perhaps the most serious, since it's actively misleading. I've had a lot of failures to compile because of this.

17
Another thing that seems to break the AGS scripting language: chaining together attributes that represent dynamically generated managed structs.

I'll explain. I have a managed struct that just holds a bunch of related data (I use a managed struct so I can put it inside various other structs and arrays):

Code: Adventure Game Studio
  1. managed struct Data
  2. {
  3.   int a;
  4.   int b;
  5. };

However, I also need to include this in some other managed structs. Since you can't store a managed struct in a managed struct, I've added some functions to convert Data to array form:

Code: Adventure Game Studio
  1. // I've used a static extender function, available with AGS 3.4, but it's the same with a regular static function
  2.  
  3. Data* fromArray(static Data, int array[])
  4. {
  5.   Data* d = new Data;
  6.   d.a = array[0];
  7.   d.b = array[1];
  8.  
  9.   return d;
  10. }
  11.  
  12. int[] toArray(this Data*)
  13. {
  14.   int array[] = new int[2];
  15.   array[0] = this.a;
  16.   array[1] = this.b;
  17.   return array;
  18. }

Now I can store it in an array inside my other managed structs, and use an attribute with getters and setters calling the conversion methods to make the whole thing transparent:

Code: Adventure Game Studio
  1. // Header
  2. managed struct Primary
  3. {
  4.   // Underlying array
  5.   protected int _data[2];
  6.  
  7.   // Attribute, accessors
  8.   import attribute Data* data;
  9.   import Data* get_data();        // $AUTOCOMPLETEIGNORE$
  10.   import void set_data(Data* d);  // $AUTOCOMPLETEIGNORE$};
  11.  
  12. // Script
  13.  
  14. Data* Primary::get_data()
  15. {
  16.   // Has to be a dynamic array, so make a copy
  17.   int array[] = new int[2];
  18.   for(int i=0; i<2; i++)
  19.     array[i]=this._data[i];
  20.  
  21.   return Data.fromArray(array);
  22. }
  23.  
  24. // Note this works as pass-by-value, not reference
  25. void Primary::set_data(Data* d)
  26. {
  27.   if(d != null)
  28.   {
  29.     this._data[0] = d.a;
  30.     this._data[1] = d.b;
  31.   }
  32. }

This works fine so far:

Code: Adventure Game Studio
  1.   Data* raw = new Data;
  2.   raw.a = 2; raw.b = 3;
  3.  
  4.   Primary* p = new Primary;
  5.   p.data = raw;
  6.  
  7.   // These should display the same
  8.   Display("Raw data a:%d b:%d", raw.a, raw.b);            // Displays: "Raw data a:2 b:3"
  9.   Display("Primary data a:%d b:%d", p.data.a, p.data.b);  // Displays: "Raw data a:2 b:3"

However, I also have another managed struct that uses Data. The actual link is a bit complex, but basically it's supposed to use the Data values associated with a particular Primary struct that is looked up in an array based on other fields; the Data* attribute is therefore read-only. So I tried to do something like this:

Code: Adventure Game Studio
  1. // Header
  2. import Primary* primaries[10];
  3.  
  4. managed struct Secondary
  5. {
  6.   int primaryIndex;    // index into primaries[]
  7.  
  8.   // Attribute, accessor
  9.   import readonly attribute Data* data;
  10.   import Data* get_data();        // $AUTOCOMPLETEIGNORE$
  11. };
  12.  
  13. // Script
  14. Data* Secondary::get_data()
  15. {
  16.   if(this.primaryIndex != -1)
  17.   {
  18.     Data* d = primaries[this.primaryIndex].data;
  19.     return d;
  20.   }
  21.   return null;
  22. }

So, putting it all together, I try this:

Code: Adventure Game Studio
  1.   Data* raw = new Data;
  2.   raw.a = 2; raw.b = 3;
  3.  
  4.   primaries[0] = new Primary;
  5.   primaries[0].data = raw;
  6.  
  7.   Secondary* s = new Secondary;
  8.   s.primaryIndex = 0;
  9.  
  10.   Display("Raw data a:%d b:%d", raw.a, raw.b);
  11.   Display("Primary data a:%d b:%d", primaries[0].data.a, primaries[0].data.b);
  12.   Display("Secondary data a:%d b:%d", s.data.a, s.data.b); // CRASH!

The last line crashes with a null exception. After some testing, it seems that s.data is always null. Doing exactly the same calculation outside of the attribute accessor works:

Code: Adventure Game Studio
  1.   Data* test1 = s.data;                            // This will be null...
  2.   Data* test2 = primaries[s.primaryIndex].data;    // ... while this will be a valid object

So is it a problem with trying to "chain" attribute accessors together like this? If I rewrite Secondary::get_data() as a direct copy of Primary::get_data() (making the _data[] array not protected and accessing it directly), it works, but it's an ugly workaround.

I've also got an inkling that it could have something to do with the readonly tag on the attribute. Oddly, when I take it away and try to provide a dummy setter, I get a hard crash (i.e. not to debugger) at an earlier line instead:

Quote
---------------------------
Illegal exception
---------------------------
An exception 0xC0000005 occurred in ACWIN.EXE at EIP = 0x00401633 ; program pointer is +1101, ACI version 3.4.0.16, gtags (0,0)

AGS cannot continue, this exception was fatal. Please note down the numbers above, remember what you were doing at the time and post the details on the AGS Technical Forum.

in "AttributeTest.asc", line 49
from "room1.asc", line 54
from "room1.asc", line 63


Most versions of Windows allow you to press Ctrl+C now to copy this entire message to the clipboard for easy reporting.

An error file CrashInfo.dmp has been created. You may be asked to upload this file when reporting this problem on the AGS Forums. (code 0)
---------------------------
OK   
---------------------------

The line reference is to Data* d = primaries[this.primaryIndex].data; in Secondary::get_data().

I don't really have a good understanding of what's going on.

18
I'm experiencing... weirdness, and sometimes crashes, in methods of managed structs that use the this-pointer, if I delete/overwrite all external handles to the object partway through the method.

The setup is something like this:

Code: Adventure Game Studio
  1. // Simplified struct
  2. managed struct Job
  3. {
  4.   int value;
  5. };
  6.  
  7. // A different script:
  8.  
  9. // I need to keep track of a bunch of jobs
  10. Job* jobPool[100];
  11.  
  12. // This function manipulates the job pool
  13. void Process(this Job*, int index)
  14. {
  15.   Display("This Job rating: %d", this.value); // I access the value
  16.  
  17.   // THE IMPORTANT BIT:
  18.   // Then delete a particular entry in the jobPool
  19.   jobPool[index] = null;
  20.   // ... and create a new Job
  21.   Job* job = new Job;
  22.   job.value = 20;
  23.  
  24.   Display("This Job rating recheck: %d", this.value); // I access the value FOR THIS JOB again
  25. }
  26.  
  27. // And I call that function:
  28. void someOtherFunction()
  29. {
  30.   // Fill the job pool
  31.   for(int i=0; i<100; i++)
  32.   {
  33.     jobPool[i] = new Job;
  34.     jobPool[i].value = i*2;
  35.   }
  36.  
  37.   // ... and later on
  38.   jobPool[5].Process(5); // The SAME NUMBER
  39. }

So I'm calling Job.Process() on jobPool[5], telling it to remove the entry in jobPool[5] from the array (in my real program, Job.Process() handles the indexes and always removes the job you call it on from the array, but let's keep it simple here). Since this is done with pointers, the object itself should not be affected (though we won't have any way to reference it after the function completes).

However, what actually happens is that it Displays:

This Job rating: 10 (the original value, correctly)
This Job rating recheck: 20 (the value of the new Job we made, job)

In other words, the this pointer is now pointing to the wrong Job!

If I remove the jobPool[index] = null; on line 19, this doesn't happen. I'm guessing that since the only external reference to this object is the entry in jobPool[5], setting that to null reduces its reference count to 0 and marks the object as deleted, even though we're still inside a function that has a local pointer to it, and that the new object is therefore slotted into the newly "free" memory, so that the this-pointer ends up pointing to it by "accident" (supporting this theory, if I add the line Job* j = jobPool[5]; on line 36 right before I call jobPool[5].Process(5); it also doesn't happen).

Under other circumstances, this can cause AGS to crash with the error "Pointer cast failure: the object being pointed to is not in the managed object pool", but I'm not able to recreate that crash in a simple sample program.

19
Beginners' Technical Questions / AGS games run slow in VM
« on: 15 Oct 2017, 08:08 »
I'm on a MacBook, and running Windows in a Virtual Machine to work on AGS games. I've used both Parallels and VirtualBox for my VM.

Windows runs pretty smoothly inside the VM, and I can use most apps no problem. However, when I try to run an AGS game with the debugger and sound, it is very sluggish (appearing to run at somewhere between 10 and 20 loops per second). Running it outside the debugger, or without sound, it runs much better, close to the standard 40 loops/second (the mouse cursor still lags a bit).

This isn't a huge problem, since I can usually just set "No Digital Sound" in winsetup. But is there anything else I can do to speed things up?

20
I have some Character* variables in a module script that I need to expose, but that I would like to stay read-only outside of the script. To that end, instead of just exporting the variables globally, I'm trying to put them as static attributes inside of a struct, with getters that return the script-local values:

Code: Adventure Game Studio
  1. struct MyModule
  2. {
  3.   import static readonly attribute Character* ActiveCharacter;  // $AUTOCOMPLETESTATICONLY$
  4.   import static Character* get_ActiveCharacter();               // $AUTOCOMPLETEIGNORE$
  5. };

Implemented in the script as:

Code: Adventure Game Studio
  1. Character* _activeCharacter;
  2. static Character* MyModule::get_ActiveCharacter()
  3. {
  4.   return _activeCharacter;
  5. }

However, when I try to actually refer to this character, I get a compilation error:

Code: Adventure Game Studio
  1.   MyModule.ActiveCharacter.Say("Blah blah"); // Fails to compile

"must have an instance of the struct to access a non-static member"

It works (or at least, it doesn't throw a compilation error: I haven't been able to test it live) if I instead write:

Code: Adventure Game Studio
  1.   Character* c = MyModule.ActiveCharacter
  2.   c.Say("Blah blah");

However, that is massively less convenient, and makes the whole approach pretty much useless for me.

It seems to be related to this bug: http://www.adventuregamestudio.co.uk/forums/index.php?topic=32083.0

Is there any way around this or some way to fix it?

Pages: [1] 2 3 ... 10