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 - Scavenger

#221
The ViewFrame struct doesn't seem to have the flipped property, and there doesn't seem to be any indication that I could get at it from the API. Would it be possible to use GetGameParameter with GP_ISFRAMEFLIPPED through GetScriptFunctionAddress, even though the function is obsolete? (I'll admit I don't know how to use GetScriptFunctionAddress at all :() I really need to know whether a frame in a view is flipped or not or the effect I'm programming is completely useless.

EDIT: I did it:

Code: C++

	int (*sfGetGameParameter)(int,int,int,int);
	sfGetGameParameter = ((int(*)(int,int,int,int)) engine->GetScriptFunctionAddress("GetGameParameter"));
	int flipped = sfGetGameParameter(13,currchar->view+1,currchar->loop,currchar->frame);
#222
Hey, I wanted to ask a question about AGS' sprite loading, but I didn't want to fill up the Technical forum with new topics, so if it's OK I'll ask it here?

Does AGS only load a sprite once it's currently being used? I have an idea for tinting the colours of characters in 8-bit and I need to access their sprites as they're being used, and I need to know whether or not AGS keeps the sprites past the point they're being used.

Basically, I need to know if I can catch a character's current ViewFrame sprite as it's being loaded with AGSE_SPRITELOAD, run my image process on it, and then repeat for every frame of their animation. I don't want strange things like tinted sprites showing up when I've turned tinting off, or normal sprites showing up. Does the sprite get unloaded as soon as the view moves on to the next frame, or does it stick around for the length of the view?
#223
Crimson Wizard: Thankyou! It works fine now. I've got the palette cycling and it looks great, with a couple of hiccups that I can work around when doing the final art for a game.

Snarky: I'm using a set of 8 LUTs, each 256x256 in size, for every palette I have translucency on. Each LUT is roughly 10% more translucent than the last. I'm currently using a single palette for many different backgrounds, so I don't have to generate that many of them. I just needed to figure out how to point the renderer towards the right part of the table. I tripped up on some simple math, I think.
#224
The old question:
Spoiler
Hey, I'm just finishing off some functions in my translucency plugin, and I've come up with a problem that I can't solve easily. I'm trying to make sure that I can keep the translucency consistent with the real colours of a sprite while I cycle the palette (so I can have, for instance, a translucent waterfall that cycles while still being translucent or a magical rainbow that cycles). For this, I assume I need to create some way of creating an array of values that points the renderer to the right part of the LUT (if 22 cycles to 23, then entry 23 on the LUT needs to be rerouted to 22's entry, or any translucent sprite containing index 23 will still treat it as if it was the original colour)

I'm running into problems because I don't think I'm approaching this right. I have a function to remap an array in parallel to palette cycling, not sure if I'm doing it right:

Code: C++

unsigned char cycle_remap [256];

void ResetRemapping () //Called when a room is loaded, so that the array corresponds 1:1 with the palette.
{
	for (int j = 0; j < 256; ++j)
	{
		cycle_remap [j] = j;
	}
}

void CycleRemap (int start, int end)
{
	if (end > start)
	{
		int diff = end - start;
		int i = 0;
		int wraparound = cycle_remap [end];
		while (i < diff)
		{
			cycle_remap [end-i-1] = cycle_remap [end-i];
			i++;
		}
		cycle_remap [start] = wraparound;
	}
	else
	{
		int diff = start - end;
		int i = 0;
		int wraparound = cycle_remap [start];
		while (i < diff)
		{
			cycle_remap [end+i+1] = cycle_remap [end+i];
			i++;
		}
	}
}


It's meant to match what happens to the palette slots when called with CyclePalette, but it just seems to turn everything one colour. Is this code even right?
[close]

Just so I don't start like fifty different topics, I'll ask my new question here, it's related:

Does AGS only load a sprite once it's currently being used? I have an idea for tinting the colours of characters in 8-bit and I need to access their sprites as they're being used, and I need to know whether or not AGS keeps the sprites past the point they're being used.

Basically, I need to know if I can catch a character's current ViewFrame sprite as it's being loaded with AGSE_SPRITELOAD, run my image process on it, and then repeat for every frame of their animation. I don't want strange things like tinted sprites showing up when I've turned tinting off, or normal sprites showing up. Does the sprite get unloaded as soon as the view moves on to the next frame?
#225
This:

Code: ags
    if (which == 5)
      s = "&5 DIALOG 5";
      vs = aAopentrunk;


needs to be:

Code: ags
if (which == 5)
    {
        s = "&5 DIALOG 5";
        vs = aAopentrunk;
    }


You're still missing the brackets on the code - make sure to double check them, otherwise the if statement will only apply to the first function run after it, and always run the one after that.
#226
Yeah, this is way beyond the scope of anything you can personally do in the AGS engine, since this is a bug that is the fault of Windows rather than AGS itself. AGS is just the latest in a long line of games that have wacky colours because of dodgy DirectDraw stuff. There's a lot of cool stuff you can do in 8-bit, but if you aren't doing any of that, it's way better to go with 32bit. Even though I love 8-bit so very much, I wouldn't wish it's problems on anyone.

There are a couple of solutions to this problem, as far as I can tell, but they're both pretty techy. The first is a registry entry, the second is patching allegro itself.

Code: ags
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\DirectDraw\Compatibility\GameName]
"Name"="GameName.exe"
"Flags"=hex:00,08,00,00
"ID"=dword:33c6e80c //This needs to be the ID DirectDraw kicks out into MostRecentApplication. I think this is dependent only on the exe file itself, so shouldn't change from computer to computer - so you only need one .reg file to fix every player's instance of the game. Two if they're running 64bit, since this would need to be copied into the 64bit registry area too.


I believe the problem is that while running full screen, Windows tries to take control of the palette and this messes up all the colours, but when running Windowed mode DirectDraw never actually changes the display mode (and so Windows never tries to change the palette). The allegro patch (which works on 4.2 & 4.4, AGS uses 4.2.4) is:

Code: ags

#include "wddraw.h"
//Include the above at the top.

//Below should go into the allegro/src/win32/wwnd.c file as part of the windows callback code.
      case WM_QUERYNEWPALETTE:
      case WM_PALETTECHANGED:
         if ((HWND)wparam != wnd && gfx_directx_primary_surface) {
            IDirectDrawSurface2_SetPalette(gfx_directx_primary_surface->id, ddpalette);
            InvalidateRect(wnd, NULL, 1);
         }
         return 0;


Looking at it, guessing that it resets the palette to what DirectDraw is using every time Windows tries to change it. I've seen this kicking around a few places where this exact palette bug shows up, and it might be a permanent solution. I'm afraid I'm not nearly as confident at compiling as I should be, so I can't test it.
#227
I didn't know Substring was resource intensive, it didn't seem to slow anything down.

Is String.Chars also doing anything other than acting as an array of chars, though? Why would I need to put the contents in c when I could just reference the array directly (instead of the silly 1 length substrings I've been using)?
#228
Ah, OK, I seperated the sinetimer into it's own thing, made it run on it's own timer (0-65536), and it works fine now! I really should comment my own code better. Thankyou!
#229
I'm currently working on a text renderer so I can do fancy text effects and coloured text and all that, and I'm currently trying to do a flowing sine wave for the text. The good news is, I can draw the text in a sine wave. The bad news is, I can't seem to get it to move. It remains a static sine wave no matter where I put the sinetimer, or what values I give it. I need it to shift right with time.

My full code is:

Code: AGS
// room script file

DynamicSprite *textarea;
Overlay *ov;
String targettxt;
int targettxtlength;
String txt;
int counter;
int delay;
int targetindex;
int length;
int sinetimer;

bool renderingtext;
bool renderingcomplete;

function DisplayRenderedText (String text, int textdelay)
{
  targettxt = text.Copy ();
  targetindex = 0;
  delay = textdelay;
  counter = 0;
  renderingtext = true;
  txt = String.Format("");
  while (targettxt.Substring (targetindex, 1) == "@") //if the current character is the escape code.
        {
            targetindex++;
            if (targettxt.Substring (targetindex, 1) == "j") // if the escape code is "jitter"
            {
              targetindex+=2;
            }
            else if (targettxt.Substring (targetindex, 1) == "t") //if escape code is "tremor", for really tiny jitters.
            {
              targetindex++;
            }
            else if (targettxt.Substring (targetindex, 1) == "n") // if the escape code is "normal"
            {
              targetindex++;
            }
            else if (targettxt.Substring (targetindex, 1) == "c") // if the escape code is "colour"
            {
              targetindex+=4;
            }
            else if (targettxt.Substring (targetindex, 1) == "f") // if the escape code is "font"
            {
              targetindex+=3;
            }
            else if (targettxt.Substring (targetindex, 1) == "s") // if the escape code is "sine"
            {
              targetindex+=3;
            }
            else if (targettxt.Substring (targetindex, 1) == "p") // if the escape code is "pause"
            {
              targetindex+=2;
            }
            else if (targettxt.Substring (targetindex, 1) == "[") // if the escape code is "carriage return"
            {
              targetindex+=1;
            }
        }
}

String ProgressCurrentText ()
{
  if (counter == delay)
  {
  if (targetindex < targettxt.Length)
  {
    targetindex++;
      while (targettxt.Substring (targetindex, 1) == "@") //if the current character is the escape code.
        {
            targetindex++;
            if (targettxt.Substring (targetindex, 1) == "j") // if the escape code is "jitter"
            {
              targetindex+=2;
            }
            else if (targettxt.Substring (targetindex, 1) == "t") //if escape code is "tremor", for really tiny jitters.
            {
              targetindex++;
            }
            else if (targettxt.Substring (targetindex, 1) == "n") // if the escape code is "normal"
            {
              targetindex++;
            }
            else if (targettxt.Substring (targetindex, 1) == "c") // if the escape code is "colour"
            {
              targetindex+=4;
            }
            else if (targettxt.Substring (targetindex, 1) == "s") // if the escape code is "sine"
            {
              targetindex+=3;
            }
            else if (targettxt.Substring (targetindex, 1) == "f") // if the escape code is "font"
            {
              targetindex+=3;
            }
            else if (targettxt.Substring (targetindex, 1) == "p") //If the escape code is pause.
            {
              targetindex++;
              String s_amount = targettxt.Substring (targetindex, 1);
              if (s_amount.AsInt > 0) counter = (s_amount.AsInt * delay) * (-1);
              else AbortGame ("Invalid pause amount (1-9)");
            }
            else if (targettxt.Substring (targetindex, 1) == "[") //If the escape code is pause.
            {
              targetindex++;
            }
        }
  }
  }
  else counter++;
  return targettxt.Substring (0, targetindex);
}

function RenderText (String text, int x, int y)
{
  int curry;
  int mode;
  int modedata;
  int modedata2;
  int color;
  int font;
  int prog;
  DrawingSurface *surf = textarea.GetDrawingSurface ();
  surf.Clear ();
  surf.DrawingColor = color;
  int i;
  curry = y;
  prog=0;
  while (i < text.Length)
  {
    surf.DrawingColor = color;
    if (text.Substring (i, 1) == "@") //if the current character is the escape code.
        {
          i++;
          if (text.Substring (i, 1) == "j") // if the escape code is "jitter"
          {
            mode = 1;
            i++;
            String s_amount = text.Substring (i, 1);
            if (s_amount.AsInt > 0) modedata = s_amount.AsInt;
            else AbortGame ("Invalid Jitter amount (1-9)");
            i++;
          }
          else if (text.Substring (i, 1) == "t") //if escape code is "tremor", for really tiny jitters.
          {
            mode = 2;
            i++;
          }
          else if (text.Substring (i, 1) == "n") // if the escape code is "normal"
          {
            mode = 0;
            i++;
          }
          else if (text.Substring (i, 1) == "s") // if the escape code is "sine"
          {
            mode = 3;
            i++;
           String h_amount = text.Substring (i, 1);
           if (h_amount.AsInt > 0) modedata = h_amount.AsInt;
           else AbortGame ("Invalid sine height amount (1-9)");
           i++;
           String w_amount = text.Substring (i, 1);
           if (w_amount.AsInt > 0) modedata2 = w_amount.AsInt;
           else AbortGame ("Invalid sine period amount (1-9)");
           i++;
          }
          else if (text.Substring (i, 1) == "c") // if the escape code is "colour"
          {
            i++;
            String colordata = text.Substring (i, 3);
            if (colordata.AsInt > 0) color = colordata.AsInt;
            else AbortGame ("Invalid color number.");
            i+=3;
          }
          else if (text.Substring (i, 1) == "f") // if the escape code is "font"
          {
            i++;
            String fontdata = text.Substring (i, 2);
            if (fontdata.AsInt > 0 || fontdata.CompareTo ("00") == 0) font = fontdata.AsInt;
            else AbortGame ("Invalid font number.");
            i+=2;
          }
          else if (text.Substring (i, 1) == "[") // if the escape code is the AGS carriage return
          {
            prog = 0;
            curry+= GetTextHeight ("Quick brown fox jumped over the Lazy dog",font, 320) + 1;
            i++;
          }
          else if (text.Substring (i, 1) == "p") //If the escape code is pause.
          {
            i+=2; //This escape code is not for this part of the renderer.
          }
          else AbortGame ("Invalid text escape code.");
        }
    else 
    {
      if (mode == 0) // normal mode
      {
        surf.DrawString (x+prog, curry, font, text.Substring (i, 1));
      }
      else if (mode == 1) //jitter mode
      {
        surf.DrawString (x+prog+Random(1), curry+(Random(modedata*2)-modedata), font, text.Substring (i, 1));
      }
      else if (mode == 2) //tremor mode
      {
        surf.DrawString (x+prog+Random(1), curry+Random(1), font, text.Substring (i, 1));
      }
      else if (mode == 3) //sine mode
      {
        if (sinetimer < modedata2) sinetimer++;
        else sinetimer = 0;
        float period = (2.0*Maths.Pi)/(IntToFloat (modedata2));
        float offset = IntToFloat(modedata) * Maths.Sin ((period * IntToFloat (sinetimer)) - IntToFloat(i));
        surf.DrawString (x+prog, curry+FloatToInt (offset, eRoundNearest), font, text.Substring (i, 1));
      }
    prog += GetTextWidth (text.Substring (i, 1), font);
    i++;
    }
  }
  surf.Release ();
  ov = Overlay.CreateGraphical (0, 0, textarea.Graphic, true);
}

function GetRenderTextWidth (String text)
{
  int font;
  int currfont;
  int totallength;
  int i;
  while (i < text.Length)
  {
    if (text.Substring (i, 1) == "@") //if the current character is the escape code.
    {
      i++;
      if (text.Substring (i, 1) == "j") // if the escape code is "jitter"
      {
        i+=2;
      }
      else if (text.Substring (i, 1) == "t") //if escape code is "tremor", for really tiny jitters.
      {
        i++;
      }
      else if (text.Substring (i, 1) == "n") // if the escape code is "normal"
      {
        i++;
      }
      else if (text.Substring (i, 1) == "c") // if the escape code is "colour"
      {
        i+=4;
      }
      else if (text.Substring (i, 1) == "f") // if the escape code is "font"
      {
        i++;
        String fontdata = text.Substring (i, 2);
        if (fontdata.AsInt > 0 || fontdata.CompareTo ("00") == 0) currfont = fontdata.AsInt;
        else AbortGame ("Invalid font number.");
        i+=2;
      }
      else if (text.Substring (i, 1) == "p") //If the escape code is pause.
      {
        i+=2; //This escape code is not for this part of the renderer.
      }
      else if (text.Substring (i, 1) == "s") //If the escape code is sine.
      {
        i+=3; 
      }
      else if (text.Substring (i, 1) == "[") //If the escape code is pause.
      {
        i++;
        totallength = 0;
      }
      else AbortGame ("Invalid text escape code.");
    }
    else 
    {
    totallength += GetTextWidth (text.Substring (i, 1), font);
    i++;
    }
  }
    return totallength;
}

function room_AfterFadeIn()
{
textarea = DynamicSprite.Create (320, 200);
DisplayRenderedText ("@c015@s21 This is a test string.",5);
}


function room_RepExec()
{
  String newtext = ProgressCurrentText ();
  RenderText (newtext, 30, 20);
}


And the actual drawing code is:

Code: AGS
      else if (mode == 3) //sine mode
      {
        if (sinetimer < modedata2) sinetimer++;
        else sinetimer = 0;
        float period = (2.0*Maths.Pi)/(IntToFloat (modedata2));
        float offset = IntToFloat(modedata) * Maths.Sin ((period * IntToFloat (sinetimer)) - IntToFloat(i));
        surf.DrawString (x+prog, curry+FloatToInt (offset, eRoundNearest), font, text.Substring (i, 1));
      }


I'm really stumped as to how to get it to move with time. There must be something obvious that I'm missing, but for the life of me I can't see what it is. Can anyone help?
#230
Try downloading this one?
#231
OK, it didn't seem like that much of a problem to try and rig up something that would work:



Game project is here

It all predicates about finding the length of the line, and then putting the mouse back to a position where the line isn't over 50 pixels. It works quite well. Also, I tried to smooth the line a bit with some grey pixels, it looks a LITTLE smoother but it's literally just five seconds of work to avoid some of the harshness of the original.
#232
It's very very rough, but it's the quickest solution I could think of to make a dotted line:


Game project is here.
#233
Alright, I managed to do this:

Code: C++
	if (event == AGSE_SAVEGAME)
	{
		for (int i = 0; i < 10; ++i)
			{
				engine->FWrite(&overlay[i].sprite, sizeof(int), data);
				engine->FWrite(&overlay[i].x, sizeof(int), data);
				engine->FWrite(&overlay[i].y, sizeof(int), data);
				engine->FWrite(&overlay[i].level, sizeof(int), data);
				engine->FWrite(&overlay[i].trans, sizeof(int), data);
				engine->FWrite(&overlay[i].enabled, sizeof(bool), data);
			}
		engine->FWrite(&clutslot, sizeof(int), data);
	}
	if (event == AGSE_RESTOREGAME)
	{
		for (int i = 0; i < 10; ++i)
			{
				engine->FRead(&overlay[i].sprite, sizeof(int), data);
				engine->FRead(&overlay[i].x, sizeof(int), data);
				engine->FRead(&overlay[i].y, sizeof(int), data);
				engine->FRead(&overlay[i].level, sizeof(int), data);
				engine->FRead(&overlay[i].trans, sizeof(int), data);
				engine->FRead(&overlay[i].enabled, sizeof(bool), data);
			}
		engine->FRead(&clutslot, sizeof(int), data);
	}


And it seems to be working! It just needed that little & sign I've seen before where things wouldn't take anything but pointers. Hopefully that'll be all for this plugin!
#234
Okay, one last question and my plugin will be fully complete.

I have the following struct and variable I need to save in AGSE_SAVEGAME and restore otherwise my plugin will not carry over effects when I restore the game.

Code: ags
struct transoverlaytype {
	int sprite;
	int x;
	int y;
	int trans;
	int level;
	bool enabled;
} overlay[10];

int clutslot;


How would I write and read this data with FWrite/FRead? Can I directly type in engine->FWrite(*overlay,??,data), or do I need to format it somehow? I'm a little lost at this point.
#235
This week, I've been focusing on the more codey aspects of my game again, and I'll tell you, this is a major breakthrough in terms of visual effects for DWEF. I had translucent stuff before, but it always bogged the game down to such a low frame rate that it was utterly useless. So, I wrote a plugin that would do the rendering for me, just like the original DWEF had, and this time, it will be a lot better. The plugin will be open source in case anybody wants it, but I doubt anybody but me is using 8-bit anymore anyway.

Here's a quick and dirty test with some placeholder pizza on a placeholder background. Look at those smooth 60fps, I would use this plugin for pretty much anything:


Don't worry, I have been working on the actual game as well, this is just a quick brain refresher before I dive back into the scripting of the game. It's just that I haven't been working on art assets for it, and so what I do have is not in any position to be shown. I hope to have many things to show in the future!
#236
Oh my god, I didn't think it would be that simple, I'm so used to things going x-y and not y-x.

It. Works.



Thank you so much! Now I can make all the neat effects I could possibly want!! A full screen translucent overlay with no overhead and no green tinge like I had last time! I'm going to use the hell out of this thing!
#237
That was for the editor plugin, AFAIK. I couldn't find one for the engine plugin. It doesn't matter, though, I've already done it.

I'm currently trying to render a translucent sprite using the same method as I use in my module, but hopefully this is faster. I've coded out something that will write a 320x200 sprite to the screen, but as soon as it tries to run AGS throws up an illegal exception. The plugin runs when this code isn't running, so it's not anything outside of this:

Quote
---------------------------
Illegal exception
---------------------------
An exception 0xC0000005 occurred in ACWIN.EXE at EIP = 0x10001202 ; program pointer is +5, ACI version 3.21.1115, gtags (920,320)

And the code I was using is:

Code: ags


int LoadCLUT (int slot) 
{
	clutslot = slot;
	return 0;
}
//This is run in the Room After Fade in manually, to point the plugin towards a 256*2048 CLUT I made earlier. 

int AGS_EngineOnEvent (int event, int data) {
  if (event == AGSE_POSTSCREENDRAW) {
    if (clutslot > 0)
	{
		// Get a reference to the screen we'll draw onto
		BITMAP *virtsc = engine->GetVirtualScreen();
		BITMAP *clutspr = engine->GetSpriteGraphic (clutslot);
		BITMAP *rain = engine->GetSpriteGraphic (920);
		unsigned char **charbuffer = engine->GetRawBitmapSurface (virtsc);
		unsigned char **clutarray = engine->GetRawBitmapSurface (clutspr);
		unsigned char **rainarray = engine->GetRawBitmapSurface (rain);
		int x = 0;
		int y = 0;
		int transamount = 256 * 4;
		while (y < 200)
		{
			while (x < 320)
			{
				charbuffer[x][y] = clutarray [charbuffer[x][y]][rainarray [x][y]+transamount];	//This compares the screen's colour and the sprite's colour, and adds an offset
                                                                                                                //so we're clearly in the 50% transparency zone. I'll add 0 index checking later.
				x++;
			}
			x=0;
			y++;
		}

		// Release the screen so that the engine can continue
		engine->ReleaseBitmapSurface (virtsc);
		engine->ReleaseBitmapSurface (clutspr);
		engine->ReleaseBitmapSurface (rain);
	}
	}
  return 0;
}


I'm not exactly sure what's going on, as it should work, unless this is way out of my league C++ wise.
#238
Alright, I've managed to compile it! Thanks! The rest should be just fine.
#239
Hey, I'm trying to write a short engine plugin for my game, but I've long since switched computers and lost all of my Visual Studio stuff. I know a bit of C++ so the coding itself isn't an issue, but setting up the project is. I've plum forgotten how to set it up. Compiling was always a weak point for me. I've tried a few versions of VS, but none of them seem to have the DLL Project set up I remember?

Could someone tell me which version of VS I need and the settings I need to use, or link me to a VS project version of the engine plugin sample code? I can work it out from there, but I have no idea where to begin. The only projects I can find for AGS plugins are the editor ones. :(
#240
General Discussion / Re: lovecraft game
Fri 24/07/2015 14:40:44
All of HP Lovecraft's work is in the public domain, you can see here. Legal minefields abound when you get into later works, especially stuff repurposed or portrayed by Chaosium for their Call of Cthulhu game (which uses stuff written by people other than Lovecraft). Lovecraft himself was very free with his creations and really wanted people to write stories about the Cthulhu Mythos, which is partly why it's so widespread today.

If you just use the themes of the Cthulhu Mythos, so long as you stick to ones mentioned in public domain works (most of them), you will be fine.

However, please, I beg you, do not do Shadow over Innsmouth. E v e r y o n e does Shadow over Innsmouth. There must be thirty different adaptations of that one book.
SMF spam blocked by CleanTalk