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

#101
I wrote a function for picking up an object a while ago, which worked fine. I've recently added another animation, and now it doesn't.
HOWEVER, if I turn off or delete code for the animation I've added, it still does it.

Here's my code:
Code: ags

function hStick_Interact()
{
	cJulius.FaceObject(oStick);
	cJulius.SayBubble("&244 It's my friend - mr sticky-stick.");
	cJulius.PickUp(eLow, iStick, oStick);
	hStick.Enabled=false;
}


in GlobalScript.asc:
Code: ags

function PickUp (this Character*, PickUpHeight height, InventoryItem *i, Object *o, bool visibility)
{
    int loop=0;
    int _height=0;
	
    if (height == eLow) {
        _height=50;     //low animation
    }
    if (height == eHigh) {
        _height=49;	//high animation
    }
	
    if (this.x <= o.X) {
        loop=2;	//right
    } else {
        loop=1;	//left
    }
	
    this.LockView(_height);
    this.Animate(loop, 0, eOnce, eBlock);
    this.AddInventory(i, 0);
    o.Visible = visibility;
    this.UnlockView();
}


Firstly, I have tried this with and without UnlockView().

For the code:
-first, julius walks to a predefined position for hStick, a hotspot.
-then he faces the stick
-he say's something ("It's my friend - mr sticky-stick.")
    -it goes into the function pickup - this is a low pickup, to the right, so:
        LockView(50);
        Animate(2, 0, eOnce, eBlock);
    -the animation is supposed to happen - IT DOESN'T
    -inventory item is added, object is set to invisible
    -view is Unlocked (or not, when I comment it out, makes no difference anyway)
-the HotSpot for this object, hStick, is switched off

Here's a video:

video

yes, I have tried plotting out the course of the code with breakpoints, this appears to be the only way.

Why, oh god why, is it not animating?
#102
I want to move a large image (1024x7068) from top-to-bottom, on a 1024x768 room screen. This is for the credits.
Can I do it without flicker/jaggedness?
Can I do it *at all*, or should I find a module?
#103
Been playing with sound (again...) and this time, it's completely stuffed.
Everything was working.

BEACH room:
Code: ags

function room_FirstLoad()
{
    SetGameOption(OPT_CROSSFADEMUSIC, 2);
}

function room_Load()
{
...
    SOUNDS=aOcean_crash.PlayFrom(oceanThemePos, eAudioPriorityNormal, eRepeat);
    MUSIC=a1_beachTheme_5_0.PlayFrom(beachThemePos, eAudioPriorityNormal, eRepeat);
...
}

function room_RepExec()
{
...
    beachThemePos=MUSIC.Position+1100;
    oceanThemePos=SOUNDS.Position;
...
}


CAVE room (to the left of BEACH room)
Code: ags

function room_Load()
{
...
    if (cJulius.PreviousRoom == BEACH) {
        MUSIC=a1_beachTheme_5_0_CAVE.PlayFrom(beachThemePos, eAudioPriorityNormal, eRepeat);
    } 
	
    if (SOUNDS.PlayingClip!=aWater_dripping) {
        SOUNDS=aWater_dripping.Play(eAudioPriorityNormal, eRepeat);
    }
}

function room_RepExec()
{
beachThemePos=MUSIC.Position+1100;
...
}


...but assignments to MUSIC channel just... don't come on - at this time, or anytime after that.

What happens:
The music stops (doesn't fade out to silence) forever.

What's supposed to happen:
The track from the previous room fades out, and this new one fades in on assignment (eg. MUSIC=aMusic.Play)

What's going on?
-Is it due to order of functions? (I thought it was: FirstLoad -> Load -> AfterFadein)?
-Is it due to me not deleting the AudioCache directory and starting again?
-Is it due to a bug or should I reload the editor?
#104
I'd like to write something like this:

Code: ags

if (cCharacter.HasInventory(iItem) && this item we've been talking about is iItem and iItem.Graphic==123) {
...


If I just say this, the second part of the expression is not necessarily associated with a item actually in your inventory -- in fact, does it just mean 'the graphic of the general item', and not the one you may/may not have?

Confused :/
#105
I've recently come across a file called '1321_110_combined.ogg' - Get's the error 'Unexpected error: Filename too long (limit is 12 chars): '1321_110_combined.ogg''

I shortened the filename to CombinedLine.ogg ('aCombinedLine'), but it still complains about the file which no longer exists.

I can't rename the file to it's old name; it's too long.
I can't keep the filename; it always gets an error.
I can't change it; there's always the error for the old filename, which doesn't exist.
I deleted the Audio file (and associated filename), deleted everything in AudioCache; re-added the Audio file (from the new filename, CombinedLine.ogg); doesn't work, same error.

Help please, can't compile my game which is already 700mb and taken a year to write!
#106
I've probably asked this before, but humour me.

I'm trying to run an animation at the begining of each question in a dialog:

Code: ags

@2
cJulius.LockView(82);
cJulius.Animate(2,0,eOnce,eBlock);
cJulius.SayBubble("&1301 'What's your favourite character?'");
...


However, the animation is a bit too long - ~2 seconds. Because it's blocking, I can't skip it, even as it delays every single question. BUT If I change it to eNoBlock, it doesn't happen.
Same for the following:

Code: ags

@1
cJulius.LockView(82);
while (!cJulius.Animating) {
	cJulius.Animate(2,0,eOnce,eNoBlock);
}


and

Code: ags

@1
cJulius.LockView(82);	//read's script
cJulius.Animate(2,0,eOnce,eNoBlock);
cJulius.UnlockView();


and

Code: ags

@1
cJulius.LockView(82);	//read's script
cJulius.Animate(2,0,eOnce,eNoBlock);
*all the other lines*
cJulius.UnlockView();


Basically, how can I get a NoBlocking view to just play, once; but if I click or press space-bar it moves on instantly to the next animation (talking)?
#107
Well, it's the most dreaded error of them all; a dialogue closing brace error.
It only tells you that a dialogue has a buffer overflow (but not where! You left out a closing " in 500 lines of code, which you now have to check); or a buffer overflow on the wrong dialogue (complains of dialogue 3 when it was dialogue 2); or 'nested function' - probably means you did something like this:

Code: ags

function foo (args) {
  some stuff;

//<--- MISSING CLOSING BRACE

function bar (args) {
  more stuff;
}


I have the 'line 1: nested functions are not supported' error for a dialog; but nothing of the above in my code.
I deleted everything in the dialogue; same error (but it can't be that dialog, because it has nothing in it!)
I checked the dDialog.Start() function, and all the code before and after it; no problems - unless someone can find the problem:

Code: ags

function cAlien_Talk()
{
  cJulius.Walk(256, 248, eBlock, eWalkableAreas);
  cJulius.FaceCharacter(cAlien, eBlock);
  dAlien.Start();        //talk to alien
}

function cHoF_Talk()
{
  dHoF.Start();    //talk to HoF - dialog 10
}

function gInventory_OnClick(GUI *theGui, MouseButton button)
{
  //some random function with nothing in it
}


Then I checked Dialog 9 and 11 (the error was with dHoF, dialog 10); nothing. Deleted everything in 9 10 and 11; stll had error for line 1 of dialog 10.

Deleted my most recent change to the GlobalScript.asc; no change, same error

My question is:
How are dialogs processed - one after the other (dialog 10, 11, 12...), or from the entry point (dialog.start()) or in some other way?

Why don't errors in them have a line number *in* the dialog, not just "there was an error in your dialog, or around it, idk"?

Why is it so impossible to find a nested function when it happens anywhere in your project, and the error refers to a dialog that doesn't have it?


Please help. I have a horrible feeling that this will make it impossible to F5/test the game until I'd been through 750,000 lines of code (not an exaggeration) :/
#108
Hi,

I've been wanting to write a piece of text in the game to describe an object, and bring it up on an overlay at the bottom-centre of the screen. Something like this:


I've been searching, but still can't find how to do it. Also I've been having problems with overlays... which basically means I don't know how to use them :P

Here's my code for the mouse graphic - it updates to an 'active cursor' when we're over something we want to look at/talk to/interact with/etc:
Code: ags

function UpdateMouseGraphic ()
{
  int newGraphic;
  int lt = GetLocationType(mouse.x, mouse.y);

  if (mouse.Mode==eModeUseinv) return;

  if (mouse.Mode==eModeWalkto) {
    newGraphic=3; //stand still
    if (gInventory.Visible==true) {
		} else if (GetWalkableAreaAt(mouse.x, mouse.y) !=0) {
      newGraphic=2054;  //walking
    }
  }
  
  else if (mouse.Mode==eModeLookat) {		//LOOKAT
    newGraphic=105; //eye close
    Hotspot *hs = Hotspot.GetAtScreenXY(mouse.x, mouse.y);
    Object *ob = Object.GetAtScreenXY(mouse.x, mouse.y);
		InventoryItem *inve = InventoryItem.GetAtScreenXY(mouse.x, mouse.y);

		if (gInventory.Visible==true && inve!=null) {
			if (inve.IsInteractionAvailable(eModeLookat)) {
				newGraphic=2056;  //eye open
			}
			
		//looking at hotspot
    } else {
			if (lt == eLocationHotspot) {
				if (hs != hotspot[0]) {
					if (hs.GetProperty("hidden")==false) {
						if(hs.IsInteractionAvailable(eModeLookat)) { 
							 newGraphic=2056;	//eye open
						}
					}
				}
			}
			
			//looking at object
			else if (lt == eLocationObject && ob.IsInteractionAvailable(eModeLookat) && ob.Visible == true) {
				newGraphic=2056;  //eye open
			}
		}
	}
	
  else if (mouse.Mode==eModeInteract) {		//INTERACTION
    newGraphic = 2;  //interact off
    Hotspot *hs = Hotspot.GetAtScreenXY(mouse.x, mouse.y);
    Object *ob = Object.GetAtScreenXY(mouse.x, mouse.y);
		
 		InventoryItem *inve = InventoryItem.GetAtScreenXY(mouse.x, mouse.y);

		//interacting with inventory item
		if (gInventory.Visible==true && inve!=null) {
			if (inve.IsInteractionAvailable(eModeLookat)) {
				newGraphic=286;
			}
		} else {

			//interacting with hotspot
			if (hs != hotspot[0]) {
				if (hs.GetProperty("hidden")==false) {
					if (hs.IsInteractionAvailable(eModeInteract)) {
						newGraphic=286;
					}
				}
			}
			
			else if (lt == eLocationObject) {
				if (ob.Visible==true) {
					if (ob.IsInteractionAvailable(eModeInteract)) {
						newGraphic=286;
					}
				}
			}
		}
	}
	
	else if (mouse.Mode==eModeTalkto) {		//TALKTO
		newGraphic = 2058;  //talk off
		Character *ch = Character.GetAtScreenXY(mouse.x, mouse.y);
		Object *ob = Object.GetAtScreenXY(mouse.x, mouse.y);
		InventoryItem *inve = InventoryItem.GetAtScreenXY(mouse.x, mouse.y);
		
		if (gInventory.Visible==true && inve!=null) {
		} else {
			if (lt == eLocationCharacter) {
				if (ch != null) {
					if (player.ID != ch.ID) {
						newGraphic = 213; //talk on
					}
				}
			}
			else if (lt == eLocationObject && ob.Visible && ob.IsInteractionAvailable(eModeTalkto)) {
				newGraphic=213;
			}
		}
  } 

  if (newGraphic != mouse.GetModeGraphic(mouse.Mode)) {
    mouse.ChangeModeGraphic(mouse.Mode, newGraphic);
  }
	
}


I'm assuming that after each MouseMode check, I put the decription in after every "newGraphic = ACTIVE_ICON" line:
Code: ags

...
if (mouse.Mode==eModeTalkto) {		//TALKTO
newGraphic = 2058;  //talk off
Character *ch = Character.GetAtScreenXY(mouse.x, mouse.y);
		
if (lt == eLocationCharacter) {
	if (ch != null) {
		if (player.ID != ch.ID) {
			newGraphic = 213; //talk on
                        Overlay "this is a "+character.Description;
		}
	}
}
...


Is this correct? Should I do something simple like this?
What is the correct Overlay code?
#109
I'm sure I'm missing something really, really obvious. Here's the code:

in GlobalScript:
Code: ags

function CheckLoop (this Character*)
{
	if (this.Loop==0) { return "eDirectionDown"; }
	if (this.Loop==1) { return "eDirectionLeft"; }
	if (this.Loop==2) { return "eDirectionRight"; }
	if (this.Loop==3) { return "eDirectionUp"; }
	if (this.Loop==6) { return "eDirectionDownLeft"; }
	if (this.Loop==7) { return "eDirectionUpLeft"; }
	if (this.Loop==4) { return "eDirectionDownRight"; }
	if (this.Loop==5) { return "eDirectionUpRight"; }
}


First, this function takes the loop of an 8-directon character, then returns a String depending on what it is.
Yes, I checked this was in the header: all correct.

In OLD_ROOM:
Code: ags

    savex=cJulius.x;                           //save character's current X position  
    savey=cJulius.y;                           //save character's current Y position
    savedirection=cJulius.CheckLoop();         //get direction of character as String, and save it also
    cJulius.ChangeRoom(NEW_ROOM, 2000, 2000);  //change to new room


This saves the position in a room to temporary variables (savedirection is a String), and then changes to a new room NEW_ROOM, with the character (cJulius) off-screen (background is 1024x768).

In NEW_ROOM:
Code: ags

cJulius.ChangeRoom(OLD_ROOM, savex, savey, savedirection);


When we go *back* to OLD_ROOM with the above command, the temporary storage of the character's last position is restored, and we travel back to room OLD_ROOM.

Error is:
(line 3, GlobalScript, first if statement in CheckLoop) Type mismatch: cannot convert 'string' to 'int'

OLD_ROOM is a normal room
NEW_ROOM is a 'detail' or 'feature' room - it doesn't have Characters and Objects, rather it is a close-up of an object in a room; a puzzle in this "room" is solved, then we go back to our normal story-driven, visible character room and get on with things.
#110
Advanced Technical Forum / Simultaneous Speech
Tue 23/01/2018 21:20:44
Hi,

I've been trying to find this for some time; and I have someone who I was prepared to pay to make a plugin for it, but he's not avilable atm.

Are there any functions, plugins, or anything else, that can produce code which follows these principles:
-saying lines of character A would be said, and block other lines of the same character (so lines A1 A2 and A3 would be said one after the other, A1 A2 A3)
-saying lines of character A and B would have them both spoken simultaneously, so A1 and B1 would be spoken at the same time.

so:

Code: ags

//said one after the other: - "1 and 2"
cA.SimultanneousSpeech("1 ")
cA.SimultanneousSpeech("and 2")

//said simultaneously
//"1 2 3" 
//"4 5 6" 
cA.SimultanneousSpeech("1 2 3")
cB.SimultanneousSpeech("4 5 6")

//all speech is paused, or cache is cleaned - this makes easy to differentiate A B A from all being played simultaneously
PauseAllSpeech()

//B says something
cB.SimultanneousSpeech("something")
PauseAllSpeech()
//A says something else
cA.SimultanneousSpeech("something else")


Instead of PauseAllSpeech(), perhaps using a blocking function like Say would be easier?..

This allows speech, and lipsync (using TotalLipSync) to work independantly of eachother - in other word, on 2 or 3 characters simultaneously.
#111
There are a few things which have always bugged me about AGS, or made it 50 times harder to achieve a simple thing. They are:

-There is only 1 step of 'undo' in the walkable/walk behind editor window. This means that two bad clicks (ie. filling in the screen with 1 colour, then drawing a dot, then growning "oh god no..." after 3 hours of painstaking work which you now have to repeat) means it's all over. Like with CTRL+Z and CTRL+Y, I'm hoping someone could expand this to 50 or 100 clicks?

-Editor window a bit primitive? No problem - you can open a 'walk behind' masking image! Except this is actually harder than just drawing it on the main window. This is a major problem. I've been able to find two tutorials (none of the pictures in them work anymore - 'bandwidth exceeded'), and basically what works is:
   1. go to mspaint (not even in Windows as of 10, has to be added back the sneaky way, will be gone forever by 11)
   2. edit a mask, using colours that you get somehow (what are their codes?..)
   3. save it as an 8bit BMP (the only editor that does this easily, or doesn't change an 8bit to a 16bit bmp when you add a layer, etc.)
   4. try this one, find it's 2 pixels too wide; go back into mspaint and edit it - single layer, using primitive tools - so that it's size is corrected. Then discover it's now 2 pixels too wide... then tear out your hair.

All this could be solved by:
-allowing import of BMP's that are 8bit, 16bit, or 32bit colour
-allowing multiple layers (like in Photoshop) without breaking the image
-allowing colours that are not *exactly* #009900 etc., but instead using the first 15 colours, and then converting them to the ones used in the editor

The ONE problem in this situation is: in the editor you HAVE the background, in mspaint or Photoshop, you DON't have the background. Unless, you use a 2nd layer on an image, copy the first to an 8bit BMP, and then hopefully, it stays that way. Seriously, I have 2 files that are 8bit BMPs, and I don't even know how I created them.

Just make the file specifications more accepting.

-Allowing walk-behinds to be independently turned on and off, rather than just 'ignore all' or 'enable all'

-Multiple layers can't be seen in the editor. Rather than seeing just walkable areas, or JUST walk behinds, or JUST objects, why not allow ALL (or some) to be seen AT THE SAME TIME? I can't tell you how many hours I've spent getting one thing or the other to line up with something else, but can't because I can see only one layer at a time. Why not just have the layers as tickboxes, turning on or off depending on what you want to see? Objects, Edges, Characters, Hotspots independant; Walkable areas or Walk behinds or Regions visible also.
Once again, one simple change that would allow this editor to be useufl rather than a hinderence.

-Larger graphics in the Sprites window. If I look at 20 frames of animation, I find it hard to tell each one apart. But if I could use a slider to see them as small, large, larger, big, xbig? This would be a simple change that meant I wouldn't have to open (one at a goddamn time) image in the default image editor (which I have to set manually) just to see it.


Now, I do apologise if I've hurt anyone feelings during this 20min bitch-fest about the Editor. Truly, I do, and I expect to use it for no cost and with no license in return for features for free and instaneously. HOWEVER, these are problems which must have something done about them.
AND

I HAVE $$$ MONEY $$$

I'm happy to pay like AU$3,000 for these changes (or perhaps $1,500 *each*). Please contact me PM if you'd like.
Otherwise, please reply.
#112
I have the following code:

Code: ags

...

@5
	if (cond) {
                conversation 1
		return RUN_DIALOG_RETURN;
	} else {
                conversation 2
goto-dialog 49 
	}
return

...


But the following error:
'Dialog 45(115): Script commands can only be used in the area between a @ entry point and the closing return/stop statement
Dialog 45(116): The command 'return' will be ignored since the script for this option has already finished
Dialog 45(117): Error (line 117): PE04: parse error at 'else''

If I alter lines 11 or 6 (return, return RUN_DIALOG_RETURN statement) - error still happens.

I'm aware of the RUN_ statements - return, previous, and stop - but there isn't one 'goto a dialog'. Otherwise I'd say by problems would be simple.

Am I doing this wrong? Is there *any* way to do this?
I'm asking because there doesn't seem to be anything on the net.
#113
Hi, I've been having trouble inserting an image, then going back to the main game. The insert is like a title card; appears for a second while some audio plays, everything else is fade out, goes back to normal background, everything is faded in and restored.

Code: ags

cGiraffe.Say("&21 YES, HE'S A HU--");

//the title card:	
DrawingSurface *surface = Room.GetDrawingSurfaceForBackground();
surface.DrawImage(1, 1, 135);
surface.Release(); 		

//audio to go with title card	
cDummy.Say("&1 Six hours later...");

//everything's restored:
DrawingSurface *surface2 = Room.GetDrawingSurfaceForBackground();
surface2.DrawImage(0, 0, 2280);
surface2.Release();

//thing's continue like a chunk of time was taken out by title card:
cGiraffe.Say("&22 ANYWAY SO I SAY'S TO HIM, MAYBE IF YOU DIDN'T DROP THE BOOK *QUITE* SO OFTEN, IT WOULDN'T SMELL FISHY!");


The problem is;
If I use FadeOut/FadeIn, it goes to absolute black, and the characters cannot be seen (good), but neithey can the title card (bad);
If I just do it as above, and just draw the title card, all the characters and objects apear (bad).

Video:
http://redrom.ltd/img/6hours.webm

Can I do this any other way than: setting everything to invisible, draw title card, say speech, draw back background, make all visible again?

Also while we're at it; how would I make the background and object's fade out, but *not* the character? Similar to a scene in which Guybrush dies in the Something of Monkey Island? (background fades out; then guybrush falls; then he fades out; then everything fades in again at a different location).

#114
I realise that compiling generally means taking all non-commented code, converting it to object code, and finally to binary. However, since AGS is a script engine (correct me if I'm wrong), and has a copy of the game scripts within the interpretor within an .exe file, it could be thought of as an exe which is really just one giant complex zip file?

So basically, what conditions are scripts in when they're compiled/'published'? Do they contain words but not comments; verbatim without line breaks; absolutely the same as original; or pure binary?
#115
Hi
I had the editor crash when there were too many tabs open (about 60). There was an error; but then *boom* gone.
On restarting it, I was told I can't load a game because it's still open in another editor -- _OpenInEditor.lock strikes again.
I tried deleting it, but couldn't.

I thought it might be due to the file being 0 bytes; but nothing can open it to edit it.
I've checked permissions, and I have full control - but can't delete.
I checked on my mac, via the windows share, to see if it would delete - nope.
I actually got a program called Unlocker to delete it - even this couldn't do it.

So basically, I can't edit the project until this is fixed.

Anyone who can help, I would be indebted, because I'm releasing a demo soon :/
#116
Hi,

I know how to change a buttons graphic in a GUI:

Code: ags

button.NormalGraphic = 123;


These are for buttons which show inventory items that are there (graphic=123) or not there yet (graphic=456) - they don't need to be clicked, and have no script attached.

But what about when a GUI is invisible? Or, when it's visible, and drops down from the the top with mousover? Can I have code which 'prepares' the graphic for when the GUI is visible or partly visible? (I'm using gIconBar 'when mouse moves over the top of the screen').

Which makes it hard, since I know the code, but not where to put it :/
In rep_exec in global script??...
#117
I'm using the Phylactere script to render speech which is normally used by Speak; and it works very well.
For my speechbubble background, I've chosen a translucent black; however, when it comes into contact with the black of a game background, it turns blue....? Why is it doing this?
Check this:


Here is my code:

Code: ags

// Require: AGS 3

Phylactere_Param phylactere;
export phylactere;

int Phylactere_col_r;
int Phylactere_col_g;
int Phylactere_col_b;

function game_start() {
  /* ------------- PARAMETRAGE --------------- */
  phylactere.background_color = 65535;
  phylactere.is_transparent = true;
  phylactere.outline_color = 0;
  phylactere.speed = 35;
  phylactere.transparency = 30;
  phylactere.transparency_red = 0;
  phylactere.transparency_green = 0;
  phylactere.transparency_blue = 0;
  phylactere.width = 300;
  phylactere.distance_from_head = 6;
  phylactere.view_speed = 5;
  phylactere.ajust_htext = 5;
  phylactere.skip_mode = eSkipKeyOrClick;
  /* ------------------------------------------ */
  
}

function getRVG(int color) {
  int c = color;
  if (c == -1) c = 63519;
  int cc = c / 2048;
  int cr , cg, cb;
  cr = cc * 8;
  c = c - (cc * 2048);
  cc = c / 64;
  cg = (cc * 8);
  c = c - (cc * 64);
  if (cg > 0) {
    cg += 4;
    c -= 32;
  }
  cb = c * 8;
  if (cb < 0) {
    if (cg > 4) cg -= 4;
    cb = 256 + cb;
  }
  Phylactere_col_r = ((cr * phylactere.transparency) + (phylactere.transparency_red * (100 - phylactere.transparency))) / 100;
  if (Phylactere_col_r > 255) Phylactere_col_r = 255;
  if (Phylactere_col_r < 0) Phylactere_col_r = 0;
  Phylactere_col_g = ((cg * phylactere.transparency) + (phylactere.transparency_green * (100 - phylactere.transparency))) / 100;
  if (Phylactere_col_g > 255) Phylactere_col_g = 255;
  if (Phylactere_col_g < 0) Phylactere_col_g = 0;
  Phylactere_col_b = ((cb * phylactere.transparency) + (phylactere.transparency_blue * (100 - phylactere.transparency))) / 100;
  if (Phylactere_col_b > 255) Phylactere_col_b = 255;
  if (Phylactere_col_b < 0) Phylactere_col_b = 0;
}

function Phylactere(this Character* , String str,  PhylactereQueueMode mode) {
 
  String speechnum;
 
  if (str.IndexOf("&") != -1) {
    speechnum = str.Substring(str.IndexOf("&"), str.IndexOf(" ")+1);
    str = str.Substring(str.IndexOf(" "), str.Length-1);
  } else {
    str = str.Copy();
  }

  
  if (IsTranslationAvailable()) str = GetTranslation(str);
 
  String GQueue[20]; // Dessin de la Queue (X = Contour, O = Fond)
  int queue_height = 0;
 
  if (mode == ePhylactereTalking) {
    GQueue[01] = "OOOOOOOO";
    GQueue[02] = "XOOOOOXX";
    GQueue[03] = "XOOOOX  ";
    GQueue[04] = "XOOOOX  ";
    GQueue[05] = " XOOOX  ";
    GQueue[06] = " XOOOX  ";
    GQueue[07] = "  XOOOX ";
    GQueue[08] = "   XOOOX";
    GQueue[09] = "    XXX ";
    queue_height = 9;
  }

  if (mode == ePhylactereThinking) {
    GQueue[01] = "        ";
    GQueue[02] = "        ";
    GQueue[03] = "  XX    ";
    GQueue[04] = " XOOX   ";
    GQueue[05] = "XOOOOX  ";
    GQueue[06] = "XOOOOX  ";
    GQueue[07] = " XOOX   ";
    GQueue[08] = "  XX    ";
    GQueue[09] = "        ";
    GQueue[10] = "    XX  ";
    GQueue[11] = "   XOOX ";
    GQueue[12] = "   XOOX ";
    GQueue[13] = "    XX  ";
    queue_height = 13;
  }
  
  // Controle des parametres
  if (phylactere.transparency < 0) phylactere.transparency = 0;
  if (phylactere.transparency > 100) phylactere.transparency = 100;
  if (phylactere.transparency_red < 0) phylactere.transparency_red = 0;
  if (phylactere.transparency_red > 255) phylactere.transparency_red = 255;
  if (phylactere.transparency_green < 0) phylactere.transparency_green = 0;
  if (phylactere.transparency_green > 255) phylactere.transparency_green = 255;
  if (phylactere.transparency_blue < 0) phylactere.transparency_blue = 0;
  if (phylactere.transparency_blue > 255) phylactere.transparency_blue = 255;
  if ((phylactere.skip_mode != eSkipTimer) && (phylactere.skip_mode != eSkipKeyOrClick) && (phylactere.skip_mode != eSkipOnlyKeyOrClick)) phylactere.skip_mode = eSkipTimer;

  // Arrêt du personnage si en mouvement
  if (phylactere.is_transparent) {
    if (this.Moving) this.StopMoving();
  }
  int char_x = this.x;
  int char_y = this.y;
  int view_x = GetViewportX();
  int view_y = GetViewportY();

  // Création de la surface
  DynamicSprite *screen = DynamicSprite.CreateFromBackground();
  DrawingSurface *surface = screen.GetDrawingSurface();
  surface.Clear();
  int screen_width = surface.Width;
  int screen_height = surface.Height;

  // Lance l'animation "Speech"
  if (this.SpeechView > 0) {
    if (mode != ePhylactereThinking) {
      this.LockView(this.SpeechView);
      this.Animate(this.Loop, phylactere.view_speed , eRepeat, eNoBlock);
    }
  }

  // Recupération de la hauteur du personnage
  ViewFrame *char_frame = Game.GetViewFrame(this.View , this.Loop, this.Frame);
  int char_height = FloatToInt(IntToFloat(Game.SpriteHeight[char_frame.Graphic]) * IntToFloat(this.Scaling) / 100.0);
  
  // Découpage de la phrase
  String line[101];
  int line_width[101];
  int line_height[101];
  int nb_lines = 0;
  String tmp_line = str.Substring(0, 1);
  String tmp_line2 = "";
  int ind_str = 1;
  int width_max = 0;
  int height_max = 0;
  while ((ind_str < str.Length) && (nb_lines < 99)) {
    tmp_line2 = tmp_line.AppendChar(str.Chars[ind_str]);
    if (GetTextWidth(tmp_line2, Game.SpeechFont) > phylactere.width) {
      int seek_blank = tmp_line.Length - 1;
      while (seek_blank > 0 && tmp_line.Chars[seek_blank] != ' ') {
        seek_blank--;
      }
      if (seek_blank > 0) {
        tmp_line2 = tmp_line.Substring(seek_blank + 1 , tmp_line.Length - seek_blank);
        tmp_line2 = tmp_line2.AppendChar(str.Chars[ind_str]);
        tmp_line = tmp_line.Substring(0, seek_blank);
      } else {
        tmp_line2 = "";
        tmp_line2 = tmp_line2.AppendChar(str.Chars[ind_str]);
      }
      nb_lines++;
      line[nb_lines] = tmp_line;
      line_width[nb_lines] = GetTextWidth(line[nb_lines], Game.SpeechFont);
      line_height[nb_lines] = GetTextHeight(line[nb_lines], Game.SpeechFont, screen_width);
      if (line_width[nb_lines] > width_max) width_max = line_width[nb_lines];
      height_max = height_max + line_height[nb_lines];
    }
    tmp_line = tmp_line2;
    tmp_line2 = "";
    ind_str++;
  }
  nb_lines++;
  line[nb_lines] = tmp_line;
  line_width[nb_lines] = GetTextWidth(line[nb_lines], Game.SpeechFont);
  line_height[nb_lines] = GetTextHeight(line[nb_lines], Game.SpeechFont, screen_width);
  if (line_width[nb_lines] > width_max) width_max = line_width[nb_lines];
  height_max = height_max + line_height[nb_lines];

  // Calcul positions du texte
  int texte_x = char_x - (width_max / 2) - GetViewportX();
  int texte_y = char_y - char_height - height_max - GetViewportY() - queue_height - phylactere.distance_from_head;
  if (texte_x < 0) texte_x = 0;
  if (texte_y < 0) texte_y = 0;
  if (texte_x + width_max + GetViewportX() > screen_width) texte_x = screen_width - width_max - GetViewportX();
  
  // Calcul positions de la bulle
  int bulle_x1 = texte_x - 5;
  int bulle_y1 = texte_y - 9 + phylactere.ajust_htext;    //CHEAT, set to 1
  int bulle_x2 = texte_x + width_max + 5;
  int bulle_y2 = texte_y + height_max + phylactere.ajust_htext;
  
  // ---- Bulle ----
  DrawingSurface* background_surface;
  DynamicSprite* background_sprite;
  
  if (phylactere.is_transparent) {
    bool mouse_visible_before = Mouse.Visible;
    if (mouse_visible_before) Mouse.Visible = false;
    //Wait(1);
    background_sprite = DynamicSprite.CreateFromScreenShot();
    if (mouse_visible_before) Mouse.Visible = true;
    background_surface = background_sprite.GetDrawingSurface();
    int by = bulle_y1;
    int bx;
    while (by <= bulle_y2) {
      bx = bulle_x1;
      while (bx <= bulle_x2) {
        int col = background_surface.GetPixel(bx, by);
        getRVG(col);
        surface.DrawingColor = Game.GetColorFromRGB(Phylactere_col_r, Phylactere_col_g, Phylactere_col_b);
        surface.DrawPixel(bx, by);
        bx++;
      }
      by++;
    }
    
    bx = bulle_x1 - 1;
    by = bulle_y1 + 1;
    while (by <= bulle_y2 - 1) {
      int col = background_surface.GetPixel(bx, by);
      getRVG(col);
      surface.DrawingColor = Game.GetColorFromRGB(Phylactere_col_r, Phylactere_col_g, Phylactere_col_b);
      surface.DrawPixel(bx, by);
      by++;
    }

    bx = bulle_x2 + 1;
    by = bulle_y1 + 1;
    while (by <= bulle_y2 - 1) {
      int col = background_surface.GetPixel(bx, by);
      getRVG(col);
      surface.DrawingColor = Game.GetColorFromRGB(Phylactere_col_r, Phylactere_col_g, Phylactere_col_b);
      surface.DrawPixel(bx, by);
      by++;
    }

    bx = bulle_x1 + 1;
    by = bulle_y1 - 1;
    while (bx <= bulle_x2 - 1) {
      int col = background_surface.GetPixel(bx, by);
      getRVG(col);
      surface.DrawingColor = Game.GetColorFromRGB(Phylactere_col_r, Phylactere_col_g, Phylactere_col_b);
      surface.DrawPixel(bx, by);
      bx++;
    }

    bx = bulle_x1 + 1;
    by = bulle_y2 + 1;
    while (bx <= bulle_x2 - 1) {
      int col = background_surface.GetPixel(bx, by);
      getRVG(col);
      surface.DrawingColor = Game.GetColorFromRGB(Phylactere_col_r, Phylactere_col_g, Phylactere_col_b);
      surface.DrawPixel(bx, by);
      bx++;
    }

    bx = bulle_x1 - 2;
    by = bulle_y1 + 3;
    while (by <= bulle_y2 - 3) {
      int col = background_surface.GetPixel(bx, by);
      getRVG(col);
      surface.DrawingColor = Game.GetColorFromRGB(Phylactere_col_r, Phylactere_col_g, Phylactere_col_b);
      surface.DrawPixel(bx, by);
      by++;
    }

    bx = bulle_x2 + 2;
    by = bulle_y1 + 3;
    while (by <= bulle_y2 - 3) {
      int col = background_surface.GetPixel(bx, by);
      getRVG(col);
      surface.DrawingColor = Game.GetColorFromRGB(Phylactere_col_r, Phylactere_col_g, Phylactere_col_b);
      surface.DrawPixel(bx, by);
      by++;
    }

    bx = bulle_x1 + 3;
    by = bulle_y1 - 2;
    while (bx <= bulle_x2 - 3) {
      int col = background_surface.GetPixel(bx, by);
      getRVG(col);
      surface.DrawingColor = Game.GetColorFromRGB(Phylactere_col_r, Phylactere_col_g, Phylactere_col_b);
      surface.DrawPixel(bx, by);
      bx++;
    }

    bx = bulle_x1 + 3;
    by = bulle_y2 + 2;
    while (bx <= bulle_x2 - 3) {
      int col = background_surface.GetPixel(bx, by);
      getRVG(col);
      surface.DrawingColor = Game.GetColorFromRGB(Phylactere_col_r, Phylactere_col_g, Phylactere_col_b);
      surface.DrawPixel(bx, by);
      bx++;
    }

  } else {
    surface.DrawingColor = phylactere.background_color;
    surface.DrawRectangle(bulle_x1 , bulle_y1 ,  bulle_x2 ,  bulle_y2);
    surface.DrawLine(bulle_x1 - 1, bulle_y1 + 1 ,  bulle_x1 - 1 ,  bulle_y2 - 1);
    surface.DrawLine(bulle_x2 + 1, bulle_y1 + 1 ,  bulle_x2 + 1 ,  bulle_y2 - 1);
    surface.DrawLine(bulle_x1 + 1 ,  bulle_y1 - 1 ,  bulle_x2 - 1 ,  bulle_y1 - 1);
    surface.DrawLine(bulle_x1 + 1 ,  bulle_y2 + 1 ,  bulle_x2 - 1 ,  bulle_y2 + 1);
    surface.DrawLine(bulle_x1 - 2, bulle_y1 + 3 ,  bulle_x1 - 2 ,  bulle_y2 - 3);
    surface.DrawLine(bulle_x2 + 2, bulle_y1 + 3 ,  bulle_x2 + 2 ,  bulle_y2 - 3);
    surface.DrawLine(bulle_x1 + 3 ,  bulle_y1 - 2 ,  bulle_x2 - 3 ,  bulle_y1 - 2);
    surface.DrawLine(bulle_x1 + 3 ,  bulle_y2 + 2 ,  bulle_x2 - 3 ,  bulle_y2 + 2);
  }

  // ---- Contours ----
  surface.DrawingColor = phylactere.outline_color;
  surface.DrawLine(bulle_x1 - 3, bulle_y1 + 3 ,  bulle_x1 - 3 ,  bulle_y2 - 3);
  surface.DrawLine(bulle_x2 + 3, bulle_y1 + 3 ,  bulle_x2 + 3 ,  bulle_y2 - 3);
  surface.DrawLine(bulle_x1 + 3 ,  bulle_y1 - 3 ,  bulle_x2 - 3 ,  bulle_y1 - 3);
  surface.DrawLine(bulle_x1 + 3 ,  bulle_y2 + 3 ,  bulle_x2 - 3 ,  bulle_y2 + 3);
  
  //---- Angle supérieur gauche ----
  surface.DrawPixel(bulle_x1 - 2 , bulle_y1 + 2);
  surface.DrawPixel(bulle_x1 - 2 , bulle_y1 + 1);
  surface.DrawPixel(bulle_x1 - 1 , bulle_y1);
  surface.DrawPixel(bulle_x1 , bulle_y1 - 1);
  surface.DrawPixel(bulle_x1 + 1 , bulle_y1 - 2);
  surface.DrawPixel(bulle_x1 + 2 , bulle_y1 - 2);

  //---- Angle supérieur droit ----
  surface.DrawPixel(bulle_x2 + 2 , bulle_y1 + 2);
  surface.DrawPixel(bulle_x2 + 2 , bulle_y1 + 1);
  surface.DrawPixel(bulle_x2 + 1 , bulle_y1);
  surface.DrawPixel(bulle_x2 , bulle_y1 - 1);
  surface.DrawPixel(bulle_x2 - 1 , bulle_y1 - 2);
  surface.DrawPixel(bulle_x2 - 2 , bulle_y1 - 2);

  //---- Angle inférieur gauche ----
  surface.DrawPixel(bulle_x1 - 2 , bulle_y2 - 2);
  surface.DrawPixel(bulle_x1 - 2 , bulle_y2 - 1);
  surface.DrawPixel(bulle_x1 - 1 , bulle_y2);
  surface.DrawPixel(bulle_x1 , bulle_y2 + 1);
  surface.DrawPixel(bulle_x1 + 1 , bulle_y2 + 2);
  surface.DrawPixel(bulle_x1 + 2 , bulle_y2 + 2);

  //---- Angle inférieur droit ----
  surface.DrawPixel(bulle_x2 + 2 , bulle_y2 - 2);
  surface.DrawPixel(bulle_x2 + 2 , bulle_y2 - 1);
  surface.DrawPixel(bulle_x2 + 1 , bulle_y2);
  surface.DrawPixel(bulle_x2 , bulle_y2 + 1);
  surface.DrawPixel(bulle_x2 - 1 , bulle_y2 + 2);
  surface.DrawPixel(bulle_x2 - 2 , bulle_y2 + 2);
  
  // ---- Queue ----
  int char_dir = this.Loop; // 0=bas , 1=gauche, 2=droite, 3=haut
  int qy = bulle_y2 + 3;
  int qx;
  if ((char_dir == 1) || (char_dir == 0)) {
    qx = char_x - 10 - GetViewportX();
  } else {
    qx = char_x + 10 - GQueue[1].Length - GetViewportX();
  }
  int j = 1;
  while (j <= queue_height) {
    int i = 0; 
    while (i < GQueue[j].Length) {
      bool visible = false;
      if (GQueue[j].Chars[i] == 'X') {
        surface.DrawingColor = phylactere.outline_color;
        visible = true;
      }
      if (GQueue[j].Chars[i] == 'O') {
        if (phylactere.is_transparent) {
          int col;
          if ((char_dir == 1) || (char_dir == 0)) {
            col = background_surface.GetPixel(qx + i ,  qy + j - 1);
          } else {
            col = background_surface.GetPixel(qx + GQueue[j].Length - i ,  qy + j - 1);
          }
          getRVG(col);
          surface.DrawingColor = Game.GetColorFromRGB(Phylactere_col_r, Phylactere_col_g, Phylactere_col_b);
        } else {
          surface.DrawingColor = phylactere.background_color;
        }
        visible = true;
      }
      if (visible) {
        if ((char_dir == 1) || (char_dir == 0)) {
          surface.DrawPixel(qx + i ,  qy + j - 1);
        } else {
          surface.DrawPixel(qx + GQueue[j].Length - i ,  qy + j - 1);
        }
      }
      i++; 
    }
    j++;
  }
  if (phylactere.is_transparent) {
    background_surface.Release();
    background_sprite.Delete();
  }

  // Texte
  surface.DrawingColor = this.SpeechColor;
  int ii = 0;
  int jj = 0;
  while (ii < nb_lines) {
    ii++;
    surface.DrawString(texte_x + (width_max - line_width[ii]) / 2 , texte_y + jj , Game.SpeechFont ,  line[ii]); 
    jj = jj + line_height[ii]; 
  }

  // Affichage de la bulle
  int pos_x = bulle_x1 - 4;
  if (pos_x < 0) pos_x = 0;
  int pos_y = bulle_y1 - 4;
  if (pos_y < 0) pos_y = 0;
  int lng_x = bulle_x2 + 4;
  int lng_y = bulle_y2 + 4 + queue_height;
  
  if (lng_x >= screen_width) lng_x = screen_width - 1;
  if (lng_y >= screen_height) lng_y = screen_height - 1;

  DynamicSprite* ds = DynamicSprite.CreateFromDrawingSurface(surface, pos_x, pos_y, lng_x - pos_x + 1 ,  lng_y - pos_y + 1);
  surface.Release();
  Overlay* bulle = Overlay.CreateGraphical(pos_x, pos_y, ds.Graphic, true);

  // Attente
  int tempo = FloatToInt(IntToFloat(str.Length) * IntToFloat(phylactere.speed) / 10.0);
  if (tempo < 40) tempo = 40;
  bool stop = false;
  
  if (speechnum != null) {
    this.SaySync(speechnum.Append(str));  
    this.Say(speechnum);                  //speak the line
  }
  
  if (speechnum==null) {  
    while (!stop){
      if (!phylactere.is_transparent) {
        bulle.Remove();
        int nx = pos_x + (this.x - char_x) - (GetViewportX() - view_x);
        int ny = pos_y + (this.y - char_y) - (GetViewportY() - view_y);
        bulle = Overlay.CreateGraphical(nx, ny, ds.Graphic, true);
      }
      if (phylactere.skip_mode != eSkipOnlyKeyOrClick) tempo--;
      if (phylactere.skip_mode == eSkipKeyOrClick) {
        int wm = WaitMouseKey(1);
        if (wm == 1) stop = true;
      }
      if (phylactere.skip_mode == eSkipTimer) {
        Wait(1);
      }
      if (tempo == 0) stop = true;
    }
  }
  
  // Efface la bulle
  ds.Delete();
  screen.Delete();
  bulle.Remove();
  
  // Arrete l'animation Speech
  if (this.SpeechView > 0) {
    if (mode != ePhylactereThinking) {
      this.UnlockView();
    }
  }
  Wait(1);
    
}


As you can see I've only changed about 5 lines of code to integrate in the numbered speech system, but I thought I should post all.

You can get Phylactere here.
#118
Hi

I've written the folowing code for 2 rooms, Cave and Beach. Player starts out in Beach. The same song (or a very similar version called a1_beachTheme_5_0_CAVE) plays in Cave at exactly the same position; I keep the global variable beachThemePos to track the current position in the audio.

My question is:
a) why does it crash with 'beachThemePos' directly after I play 'chan1=a1_beachTheme_5_......'  ?  I initalise the variable; still crashes. I make sure MaxChannels is 50; still crashes.
b) how do I keep track of a track's position number? I thought it was by typing beachThemePos=chan1.PositionMs, but obviously not. It gives a position in the current track - but can I track this to be the one playing 'a1_beachTheme_...'? If a track is position [4], how do I make sure when I seek, it always does this to position 4? adiochannel.seek[4]? No idea how this works.

Beach:
Code: ags

function room_FirstLoad()
{
    SetGameOption(OPT_CROSSFADEMUSIC, 2);
}
 
function room_AfterFadeIn()
{
  if (cJulius.PreviousRoom == CAVE) {
    aWater_dripping.Stop();
  }
 
  if (chan1==null) {
    chan1=aOcean_crash.PlayFrom(oceanThemePos, eAudioPriorityHigh, eRepeat);
    chan1=a1_beachTheme_5_0.PlayFrom(beachThemePos, eAudioPriorityNormal, eRepeat);    //run the first time I'm in Bach -- ie. after game loads
  } else {
    chan1=a1_beachTheme_5_0.PlayFrom(beachThemePos, eAudioPriorityNormal, eRepeat);    //runs every time after that
  }             
}
 
function room_RepExec()
{
  beachThemePos=chan1.PositionMs;
}



Cave:
Code: ags

function room_AfterFadeIn()
{
  if (cJulius.PreviousRoom == BEACH) {
    chan1=a1_beachTheme_5_0_CAVE.PlayFrom(beachThemePos, eAudioPriorityNormal, eRepeat);
  } 
        
  if (chan1.PlayingClip!=aWater_dripping) {
    chan1=aWater_dripping.Play(eAudioPriorityNormal, eRepeat);
  }
}
 
function room_RepExec()
{
  beachThemePos=chan1.PositionMs;
}
#119
Hi,

I'm having a problem with my music while speech is being played. This isn't just the suond volume during a dialog; it's during actua speech.
I thought there must be any easy way to fix this (10% volume during speech, 100% rest of time), but can't find the option is Game options or anywhere else.
Can sound volume be altered during a dialog and/or during speech play?

Thank you :)
#120
I'm still working my way through the custom dialogue tree (http://www.adventuregamestudio.co.uk/manual/ags44.htm) - but one question, what about image buttons for dialogue choices?
I imagine you could write a sprite number in the question part of the dialogue, then use this to dig the sprite out and use it for the image on the dialogue choice. But how? How do you refer to an image in the sprite file, image.Graphic? Is there a script or plugin to do this already?
SMF spam blocked by CleanTalk