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

#61
I assume the issue is that restarting the game would reset the achievement variables (unless you meticulously reset every game related variable manually - which would be very time consuming). I would have to functions:
Code: AGS
void WriteAchievements(){ //Write achievement data to file
  File *i = File.Open("Achievements.dat",eFileWrite);
  i.Write(Var1); //where Var are your variables
  i.Write(Var2);
  i.Write(Var3);
  //etc etc
}
void ReadAchievements(){//Read Achievement data from file
  if (!File.Exists("Achievements.dat")) return; //if the file hasn't been created yet, exit the function
  File *i = File.Open("Achievements.dat",eFileRead);
  Var1 = i.ReadInt();
  Var2 = i.ReadInt();
  Var3 = i.ReadInt();
  //etc etc
}

Then, there are two points at which you need to call each. you need to call WriteAchievements() whenever the player quits the game, or when the game is about to restart (so just before you call QuitGame(0) or RestartGame())

There are two points you should call ReadAchievements() - that is in game_start() and on_event for when the game is restored. like:
Code: AGS
function game_start(){
  ReadAchievements();
}
function on_event(EventType Event, int data){
  if(Event == eEventRestoreGame){ //After a reload
    ReadAchievements()
  }
}

(all this has sort of been tested, but a long time ago)

Hope that helps :)
#62
One way I can see is to set object precedence over other available interactions in on_mouse_click. I don't know what mouse setup you have, but if you had something like:
Code: AGS
function on_mouse_click(MouseButton button)
{
  //Stuff
  if(button == eMouseLeft){
    ProcessClick(mouse.x, mouse.y, Mouse.Mode);
  }
  //Stuff
}
 
You could change it to:
Code: AGS
function on_mouse_click(MouseButton button)
{
  //Stuff
  if(button == eMouseLeft){
    Object *o = Object.GetAtScreenXY(mouse.x, mouse.y);
    if(o != null) o.RunInteraction(Mouse.Mode); //IF there is an object under the mouse pointer, run object interaction
    else ProcessClick(mouse.x, mouse.y, Mouse.Mode); //else proceed as normal
  }
  //Stuff
}

Not tested, but will hopefully work

Hope that helps! :)

EDIT: Beaten by san.daniele :)
#63
You can reference a font through it's enumerated index. Something like:
Code: AGS
int f = eFontFont0;
Overlay *v = Overlay.CreateTextual(40, 40, 40, f, 6, "hi!");//where f stands in for the FontType parameter


I don't know if the wording I've used is correct, but the code works :-D
#64
Congratulations on your first game! Ahh, I remember the heady days of 14... I think I'd just about grasped the concept of a variable by the end of that year. Needless to say, you're miles ahead of where I was :-D. I can't wait to see what you produce over the coming years! :)

Just a small bug:
Spoiler
I can't seem to get out of the room with the receptionist once I'm in it...I might be missing something though...
[close]
#65
For the typewritten speech, you could do this, although it's a bit more hassle: you'll have to use a custom function (I prefer extender function) for speech instead of using commands like 'Say()' and have that typewrite. you'll probably want a while loop within the function that truncates the string to a lesser and lesser degree every so-many game loops. Maybe something like:
Code: AGS
void Comment(this Character*, String m){ //extender function
  this.StopMoving();
  Overlay* bgs;
  this.LockView(this.SpeechView);
  this.Animate(this.Loop, 3, eRepeat, eNoBlock, eForwards);
  int timer = ((m.Length/Game.TextReadingSpeed + 1) * GetGameSpeed())/m.Length; //get how long every wait should be
                                                                                //the reason this has to be calculated 
                                                                                //is because AGS calculates speech time
                                                                                //in 15 character - 40 game loop steps
  int i = 1;
  while (i<=m.Length){
    bgs = this.SayBackground(m.Truncat(i));
    Wait(timer);
    i ++;
  }
  if (bgs != null && bgs.Valid) bgs.Remove();
  this.UnlockView();
}
//then to call it
cChar.Comment("Blah");

!This is thoroughly untested!
The only problem is that this is not skippable. Also, you can't control where the command is put. For that, you may want to change the code like this:
Code: AGS
void CommentAt(this Character*, String m, int X, int Y, int Width, int ColorIndex){ //extender function
  this.StopMoving();
  Overlay* bgs = Overlay.CreateTextual(X,Y,Width, Game.SpeechFont, ColorIndex, ""); //initialize the overlay to display a text
;
  this.LockView(this.SpeechView);
  this.Animate(this.Loop, 3, eRepeat, eNoBlock, eForwards);
  int timer = ((m.Length/Game.TextReadingSpeed + 1) * GetGameSpeed())/m.Length; //get how long every wait should be
                                                                                //the reason this has to be calculated 
                                                                                //is because AGS calculates speech time
                                                                                //in 15 character - 40 game loop steps
  int i = 1;
  while (i<=m.Length){
    String s = m.Truncate(i);
    bgs.SetText(Width, Game.SpeechFont, ColorIndex, s); //change the text to the truncated string
    Wait(timer);
    i ++;
  }
  if (bgs != null && bgs.Valid) bgs.Remove();
  this.UnlockView();
}
//then to call it
cChar.CommentAt("Blah", 200, 200, 200, 15);

!Again: thoroughly untested!
  This isn't the most optimized solution I'm sure, but it's something to start on.

Hope that helps! :)

EDIT: Oops, just realized the maths was wrong for the loop. now fixed
#66
In the editor, click on the 'General Settings' node and go to 'Visual' -> 'When player interface is disabled, GUIs should' and change the setting to the one you want.

Hope that helps :)
#67
General Discussion / Re: The Bombing in Boston
Wed 17/04/2013 21:17:22
 A tragedy is always a tragedy, no matter where it is. If only other tragedies could be treated with equal significance.

Regardless, my best thoughts and wishes go out to everyone affected by this
#68
Hello Cerno

I just saw this in passing, so I'll offer some thoughts and hope they are relevant :D

1) There is a bit of a middle ground: in the room editor, you can middle click on the part of the room you are interested in and select 'copy coordinates to clipboard' (basically copy the coordinates), which you can then paste as normal anywhere you like. It's not the same as having some points mind, but it's something.

2) You can't access objects/hotspots/regions by name from an external script (well, you can't ever access a region by name) but you can access them via their index and type. Something like:
Code: AGS
int x = object[1].X //Get the X coordinate of object ID 1

    Of course, this style will only affect/effect the specific object in the currently loaded room, but being able to access any object in any room isn't practical. Not only would every object now have to have a unique name, but every room (I imagine) would have to be loaded in at all time for changes to take place consistently.

I hope my thoughts have proven useful :)
#69
Hello Cerno

There's a function called repeatedly_execute_always() which you need to add in yourself inside the .asc: it functions like repeatedly_execute() except it is called at all times, even if the game is executing a blocking action. For this example, you could check if the character was walking, and if so call on_mouse_click():
Code: AGS
function repeatedly_execute_always() 
{
  if(player.Moving){
    if(Mouse.IsButtonDown(eMouseLeft)){
      player.StopMoving();
      on_mouse_click(eMouseLeft);
    }
    else if(Mouse.IsButtonDown(eMouseRight)){
      player.StopMoving();
      on_mouse_click(eMouseRight);
    }
  }
}

Not tested

There is, of course, an inherent problem, where if you want to force the player to move somewhere, he/she can still click somewhere else and interrupt it. I'd suggest perhaps having the following amendments:
Code: AGS
//at top of script
bool UnForcedMove; //'false' = they cannot interrupt movement, 'true' = they can. The default start is 'false'
//Then in on_mouse_click():
if (process == false)
              {
                // Cerno: This is the interesting part
                UnForcedMove = true; //if the player clicks somewhere - set UnForcedMove to 'true'
                ProcessClick(mousex,mousey, eModeWalkto);  //move to that spot
              }
//then in repeatedly_execute_always():
function repeatedly_execute_always() 
{
  if(player.Moving && UnForcedMove){ //if the player is moving AND it is because he/she clicked somewhere
    if(Mouse.IsButtonDown(eMouseLeft)){
      player.StopMoving();
      UnForcedMove = false; //set this to false so if the next interaction activates a forced movement, they cannot block it.
      on_mouse_click(eMouseLeft);
    }
    else if(Mouse.IsButtonDown(eMouseRight)){
      player.StopMoving();
      UnForcedMove = false;
      on_mouse_click(eMouseRight);
    }
  }
  else if(UnForcedMove) UnForcedMove = false; //if the player is standing still, but UnForcedMove is still 'true', set it to 'false'
}

Again, not tested - the idea is that UnForcedMove is true when the player decides to walk somewhere, but if you want the player to walk somewhere, UnForcedMove will be false and therefore the player cannot interrupt where you want them to go.

There's more efficient ways to code this, but it's a start

Hope it helps! (and works...unfortunately I don't have time to test...) :)
#70
I'm not quite sure what you mean: would you like "CauseOfDeath" the enumerated type (I assume that's what it is) to be available to "btnTryAgain_OnClick", or would you like the value supplied to be available i.e. "cod"
If you mean the value supplied - no, there is no way "btnTryAgain_onClick" can access "cod" as it is local to the instance of the "ShowDeathGui" function (as far as I'm aware). However, if you want to keep everything in one line, or only want a "CauseOfDeath" variable local to the GlobalScript (I presume that's where it is), you can make another value there, something like:
Code: AGS
//top of global script
CauseOfDeath cause;
//Then your function
function ShowDeathGui(CauseOfDeath cod){ //If you've used other values such as void, replace appropriately
  cause = cod;
  //etc etc
}
//Then elsewhere
function btnTryAgain_OnClick(GUIControl *control, MouseButton button)
{
 if(cause == blah)
 //etc etc
}


At the end of the day, it really just comes down to style - this method will mean that you can keep your function the same, and not need a global variable.

Hope that helps! :)
#71
Hello Adeel, welcome to the forums :)

If you go through the tutorial, you'll find what you want with dialogues. In the editor, go to Help -> Contents -> Tutorial.

Also if you're new, I'd check out densming's video series - that should get you set up with a lot of the basic scripting you'll want.

Have you read the *Read First *Before* Posting thread? It's a good idea if you haven't.

Also, it's very likely that your question has already been answered, so it's a good idea to use the search bar on this site before opening a new thread

Hope you enjoy AGS!
#72
What does dConversation consist of? Does the player have a dialog option or is it just the characters talking? In the former case, I'd just stick all the code going from walking to B onwards inside dialog script, something like:
Code: AGS
//in dialog script
@1
PlayerCharacter: Blah
OtherCharacter: Stuff
  cPlayerCharacter.Walk(x,y,eBlock);
  [other stuff] //etc etc


If, however, the player doesn't have to choose any options, then you don't really have to have dConversation at all, just put all the talking in the function:
Code: AGS
function cOtherCharacter_Talk()
{
  cPlayerCharacter.Walk(225, 235,  eBlock);
  cPlayerCharacter.FaceCharacter(cOtherCharacter);
  cOtherCharacter.Say("Blah");
  cPlayerCharacter.Say("Stuff");
}


However, this won't solve the issue that RunInteraction seems to be non-blocking. (The manual strangely doesn't mention it) I can see two solutions:

1) If you don't mind replicating code, doing what you did in the second implementation should work fine, just swap dConversation.Start() with cOtherCharacter.Say("Blah") etc etc.

2) If you want to never replicate the code, you could stick it in an external function. Something like:
Code: AGS
 //Somewhere in global script above cOtherCharacter_Talk()
function TalkToOtherChar(){
  cPlayerCharacter.Walk(225, 235,  eBlock);
  cPlayerCharacter.FaceCharacter(cOtherCharacter);
  cOtherCharacter.Say("Blah");
  cPlayerCharacter.Say("Stuff");
}
//Then
function cOtherCharacter_Talk()
{
  TalkToOtherChar();
}
//And again, in the cutscene code:
  TalkToOtherChar();
  cPlayerCharacter.Walk(x, y, eBlock);
  [other stuff]


This should hopefully do the trick :)
#73
The problem may lie in this line:
Code: AGS
else if (IsInteractionAvailable(mouse.x, mouse.y, mode)) ProcessClick(mouse.x, mouse.y, mode);

From the manual:
Quote[isInteractionAvailable] is very similar to ProcessClick, except that rather than carry out any interactions it encounters, it simply returns 1 if something would have happened, or 0 if unhandled_event would have been run.
Therefore, you are only calling ProcessClick when an interaction IS available, and never when it would carry over to an unhandled event.
You could try changing it to this:
Code: AGS
//from the bottom half
  else if ((button == eMouseLeft) && (player.ActiveInventory == null) && (GetLocationType(mouse.x, mouse.y) == eLocationNothing))
  {
    ProcessClick(mouse.x, mouse.y, eModeWalkto);
  }
  else if ((button == eMouseRight) && (player.ActiveInventory != null))
  {
    player.ActiveInventory = null;
  }
  else ProcessClick(mouse.x, mouse.y, mode);


The GetLocationType check in line 2 means that clause is executed when the cursor is not over a hotspot, object or character.

Hope this helps! :)
#74
@Billbis: Unfortunatley I was just looking that up, apparently it ignores all interfaces, which includes the buttons on them.

@TMuh: I don't know whether there is another way of calling that function, but what you could do is take the code in the BtnDevelopOK_OnClick function, and put it in another function which both instances can call. Like:
Code: AGS
function Do_Stuff()
{
...Some code...  
}
//Then later on
function BtnDevelopOK_OnClick(GUIControl *control, MouseButton button)
{
  Do_Stuff()
}
//Then in on_key_press()
if (keycode == eKeyReturn && gDevelop.Visible == true && TxtBoxDevelop.Enabled == true) Do_Stuff();

I don't know if there are other ways to simulate button presses, but that should do it.

Hope that helps!
#75
For 2): It might be that the 'cursor hotspot' for the pointer mode and wait mode are different, which would might (I haven't tested this) cause a jump.
#76
I know this solves the initial issue as well as the NRA solves gun crime (satire! :D) but just for this instance, instead of using the GUI animation module, you could stick a button on the GUI and animate that (and see if it works). I know it's less elegant, but unfortunately I've never used the module either... Remember though that buttons have different parameters, namely:  Button.Animate(int view, int loop, int delay, RepeatStyle).

Hope that helps!
#77
Hello Khris!

Ahh, I keep forgetting it's an Overlay, thanks! As for the lack of using a speaking view, hopefully forcing a repeated animation will work. As I don't have any speech animations to date, I tested this out very rudimentary, but it seemed to work:
Code: AGS
void Comment(this Character*, String m){
  Overlay* bgs = this.SayBackground(m);
  this.LockView(this.NormalView + 1); //The talking view is always 1 above the normal view
  this.Animate(this.Loop, 5, eRepeat, eNoBlock, eForwards);
  WaitMouseKey((m.Length/Game.TextReadingSpeed + 1) * GetGameSpeed()); //so wait time can be skipped
  if (bgs != null && bgs.Valid) bgs.Remove();
  this.UnlockView();
}


Thanks again! :)
#78
Hello Slasher

Thank-you very much :) using SayBackground() and an enforced wait did the trick. I was worried that the functionality of Say() would be lost, i.e. the fact that it is blocking, and simultaneously having the ability to skip through the speech, but WaitMouseKey() did the trick.

if anyone is interested, the code is:
Code: AGS
//somewhere, then imported
void Comment(this Character*, String m){
  this.SayBackground(m);
  WaitMouseKey((m.Length/Game.TextReadingSpeed + 1) * GetGameSpeed()); //so wait time can be skipped
  this.SayBackground(""); //so that if wait time is skipped, the character stops talking
}
//elswhere
player.Comment("Woohoo!");


Thanks again!
#79
Hello Everyone!
I have some code where characters talk in the background. Nothing fancy really, just have this setup:
Code: AGS
void Cut1(){
  Character *c;
  String m;
  if(Cut1Stage == 0){ m = "Some stuff"; c = cChar1;}
  else if(Cut1Stage == 1){ m = "Some Other stuff"; c = cChar2;}
  else if(Cut1Stage == 2){ m = "Even more!"; c = cChar1;}
  //etc etc.
  Cut1Stage ++;
  c.SayBackground(m);
  Cut1Timer = (m.Length/Game.TextReadingSpeed + 1) * GetGameSpeed();
}
 //Then in rep_exec_always():
function repeatedly_execute_always(){
  if(Cut1On && Cut1Timer > 0) Cut1Timer --; //if one is still talking, count down
  else if(Cut1On && Cut1Timer <= 0) Cut1(); //else get to the next bit
}

It all works fine left on it's own. The problem is when the player character says something (player.Say("blah")) it cuts off the character talking in the background (as in, they're speech completely disappears). Is there an option to change that, or is it supposed to be like that? Or (most likely) am I doing something wrong?

Thanks in advanced!
#80
Hmm, the only other piece of info is that the first 1024x768 game was emailed to myself, so the files aren't strictly speaking the originals. But again, that probably shouldn't factor. I've set up a new game project at 1024x768 and it all works fine (i.e. the graphic is drawn). Apologies if this was a waste of time, and many thanks again for taking the time to read and comment Khris :)
SMF spam blocked by CleanTalk