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

#241
Yeah, there's a lot of really old, hard-coded behavior in AGS.

Especially the blocking thing can be frustrating, but there's no easy solution for that. You need blocking commands or basic beginner scripts are impossible. However blocking also blocks stuff, which can get in the way of other things.

The fading can be solved with custom code and a black GUI, this way you can make it non-blocking. However this means other commands might now run too soon.

In short: this is unlikely to be "solved" in AGS 4, because there's nothing to solve here. You simply need to learn how to write code for an event-based engine.
#242
@lapsking I saw you asking about non-blocking code in the AGS 4 thread.

The solution is indeed to simply append "_always" to the repeatedly_execute function's name.
This is basically a bug in my module and I've updated the download accordingly.
#243
@Akril15

This is a bug in the module.

Line 144 is this:
Code: ags
static void Mirrors2::NewMirror( Object* mask,  //set to null if no mask

This means it is valid to pass "null" as the first parameter. However as soon as you create a second mirror with no object anywhere in your game, the module mistakenly thinks you're reusing the object, and there's additional bugs further down where the modules assumes that mask is always != null.

If you always pass an object as first parameter, the module also wrongly assumes you're reusing an object if it has the same ID as a previous mirror's mask object. That's because the module stores a pointer to the room object, which is just a pointer to "object[1]" for instance; an array which gets reused for the new room's objects.

The Demo game happens to use object #0 in the harbor room and objects #1, #2 and #3 in the crystals room, which is how the bug was accidentally avoided.

To fix the bug, find line 135:
Code: ags
    if (data[i].mask == mask)

Change it to:
Code: ags
    if (mask != null && data[i].mask == mask && data[i].room == player.Room)
#244
Just in general, please always describe what the actual result is, as opposed to what you expected.

From your code it looks like you simply forgot to call player.ChangeView().

Code: ags
  // after player.StopMoving();
  if (speed == 5) player.ChangeView(PLAYER_WALK);
  else player.ChangeView(PLAYER_RUN);
#245
I wrote this from memory so I didn't realize the CopyTransparencyMask() method requires a slot.

Regarding your code, I assume you put this in a function? Which one?
Also, the error is the dreaded non-specific 0xC0000005 one, not sure what's causing this.
#246
As for the distance question, the approach primarily depends on the perspective of your graphics. Is it top-down? Sideview? In-between?

Collision checks in a 2D game are usually done via hitboxes; each game loop you calculate a rectangle for the sword based on the player's position, direction they're facing in and animation frame.
The same is done for the enemy's body.
Next you do a rectangle vs rectangle check and if they overlap, you process the hit.

I'd use a struct like:
Code: ags
managed struct Rectangle {
  int x1, y1, x2, y2;
  import boolean Overlaps(Rectangle* other);
};

The function looks like this:
Code: ags
boolean Rectangle::Overlaps(Rectangle* other) {
  if (this.x1 > other.x2 || this.x2 < other.x1) return false;
  if (this.y1 > other.y2 || this.y2 < other.y1) return false;
  return true;
}

You can now use that like:
Code: ags
#define ENEMY_COUNT 10

Rectangle* playerSword;
Rectangle* enemies[ENEMY_COUNT];

void game_start() {
  playerSword = new Rectangle;
  for (int i = 0; i < ENEMY_COUNT; i++) enemies[i] = new Rectangle;
}

void UpdateHitboxes() {
  // very rough example code
  playerSword.x1 = player.x + 5;
  enemy[0].x1 = cEnemy1.x - 10;
  // ...
}

void CheckCollisions() {
  for (int i = 0; i < ENEMY_COUNT; i++) {
    if (playerSword.Overlaps(enemies[i])) {
      // enemy #i just got hit
    }
  }
}
#247
So this is happening to only one beta tester? Not the others?

From the module's code and the fact that you're only using one mirror per room, I don't see what could cause this error.
An easy way to cause the error is to create two mirrors and pass the same object as the first parameter.
But you're not doing that in the code you posted.
#248
It looks like you need to do the following:

First, import a png that has a part of the walkable area (any color for the area, everything else transparent) to define the shape. Repeat for every part of the walkable area.

In game,
1. create a dynamic sprite (1) from the imported shape sprite
2. create a second dynamic sprite (2) and fill it with DrawingColor [AreaNumber] by drawing a rectangle to it
3. use CopyTransparencyMask to copy the transparency from (1) to (2)
4. get the drawing surface for the walkable areas, clear it, then draw sprite (2) to it

You obviously do this in a custom function, passing the area number i.e. color and sprite slot into it.
#249
Just to make sure: you're using AGS 4, right?
#250
You don't have to export functions (only variables), and you can organize stuff with structs.

Example module code:

Code: ags
// header
struct Roger {
  import static void handleInteract();
};

// main module script

static void Roger::handleInteract() {
  Display("Interacting with NPC1");
}

In the global script you can now do
Code: ags
function cRoger_Interact(Character *theCharacter, CursorMode mode)
{
  Roger.handleInteract();
}
#251
The Crop command's 3rd and 4th parameters are width and height, not x2 and y2.
I.e. you need to remove " + spacex" when you pass the width.

As for looping, replace "spacex += 1;" with:
Code: ags
  spacex = (spacex + 1) % (Game.SpriteWidth[946] - Game.SpriteWidth[948]);

The mod operator calculates the reminder, meaning it's the shorter way of doing:
Code: ags
  spacex++;
  if (spacex == SMALLEST_INVALID_VALUE) spacex = 0;

Btw: you can do this without cropping / copying the transparency mask: put the room background including holes for the windows in a sprite, then simply draw the stars followed by the room sprite to the room background's DrawingSurface.
#252
Please always post the actual code you have.

The following works fine for me:
Code: ags
  gDraggable.Visible = true;
  WaitMouseKey(1000);
  gDraggable.Visible = false;

I can simply click anywhere and the GUI disappears again.

To have the GUI stay on the screen until it is clicked, you need to use on_event:
Code: ags
void on_event(EventType event, int data) {
  if (event == eEventGUIMouseDown && data == gDraggable.ID) gDraggable.Visible = false;
}
#253
#254
You can simply put a bunch of player.Say("..."); commands in your script instead of using a dialog.

You can also use a custom property; add one for rooms to the schema (type: String, name: description).
Then add a new script above the two-click handler one:
Code: ags
function on_mouse_click(MouseButton which)
{
  if (GetLocationType(mouse.x,mouse.y) == eLocationNothing && which == eMouseRight) {
    ClaimEvent();
    player.Say(Room.GetTextProperty("description"));
  }
}

This way you won't have to paste this function into each new room.
#255
Hey, it's pretty simple actually :)

Just redownload the module.
I've added two commands:

Code: ags
  MusicPlayer.Shuffle(bool shuffle); // true / false to turn shuffle on / off
  MusicPlayer.Next(); // skip to next track
#256
Apparently this is an actual billboard in San Francisco:

#257
The page you linked to mentions the two places where you can put the acsetup.cfg containing the [log] lines:

user's global config: %USERPROFILE%/Saved Games/Adventure Game Studio/acsetup.cfg
user's game config: %USERPROFILE%/Saved Games/GAMENAME/acsetup.cfg

I tried the global config and it worked on the sport.
#258
I'm reasonably sure that you can add/remove rooms from a game by simply moving the files (.crm & .asc) inside/out of the game folder (while the editor is closed of course).

That should be enough to reduce the compile time. Other resources like audio files and sprites cannot be split anyway afaik.
#259
The easiest way is to set the label's text to "@OVERHOTSPOT@"; this is sufficient for characters, objects and hotspots.
If you also need inv items, buttons, etc. it gets slightly more complicated; check the reply I posted in the other thread: https://www.adventuregamestudio.co.uk/forums/index.php?msg=636664467
#260
Do you already have code that's handling this? Or are you using an @OVERHOTSPOT@ label?
In both cases you need something like
Code: ags
  GUIControl* gc = GUIControl.GetAtScreenXY(mouse.x, mouse.y);
  if (gc != null && gc.AsButton != null) lblHotspot.Text = gc.AsButton.Name;
  else lblHotspot.Text = Game.GetLocationName(mouse.x, mouse.y);
inside repeatedly_execute.
SMF spam blocked by CleanTalk