So has a kyr system been created?

Started by Imc7r, Tue 20/02/2018 16:55:52

Previous topic - Next topic

Imc7r

#40
QuoteNo, but now when you said this, I am beginning to think that's the only way, except for scripting custom blocking/pathfinding.

Oh im not opposing the idea I was just asking, I already started using that way. So in addition to the 8 objects I added some 90x90 pixels another 8 objects that will be used for blocking only. For now I made them red squares so it is visible where they block. I partially made it work but the boxes are so out of position for the trees. Im not sure what formula to use to cover the bottom of the trees simply (the middle of the bottom of each image whether resized or not, I have the baseline but it didnt help much), here is what each means in my code

Crimson Wizard

#41
I will be frank, the code that I see on your pic is pretty weird.

You first draw the tree sprite onto room-sized surface in original size, then resize the surface... I think that means that not only width and height of the tree will be changed, but its X and Y will also change (final tree image may get shifted away from the position you wanted).
Also, I cannot make any sense out of adding propScale to the surface's sizes. If that's really is a scale factor, then it's wrong, so that's probably not the scale factor, but the final tree size?? or not....

By the way, the Baseline calculation is also wrong. You are using original coordinates propY and Game.SpriteHeight to calculate its position, but they are no longer applicable to the final resized image. You should be multiplying these values by the image scale factor (see below).

If you look for the DrawImage article in the manual, you will see that it has optional width and height parameters. They let you resize an image when you are drawing it.
So the resizing code could probably look like this:
Code: ags

int scale ... // assuming you calculated scale somehow
int orig_width = Game.SpriteWidth[prop[i]];
int orig_height = Game.SpriteHeight[prop[i]];
int final_width = orig_width * scale;
int final_height = orig_height * scale;
EnvPropSurface[i] = EnvProp[i].GetDrawingSurface();
EnvPropSurface[i].DrawImage(propX[i], propY[i], prop[i], 0, final_width, final_height);
EnvPropSurface[i].Release();

In such case there is no need to resize large dynamic sprite, and also prop coordinates stay the same.




Alright, that said, if we still stick to your formulas, then to calculate the "block" object position you need to know following:
1) The size and position of Blocking area relative to the original sprite's size. This you have to define yourself, because only you know it, and you draw these sprites.
Let's call these OrigBlockX, OrigBlockY, OrigBlockWidth and OrigBlockHeight.
2) The size and position of Blocking area relative to the resized sprite. For these you need to multiply previous values by the same factor you are using to resize the sprite.

Since you are resizing whole final image, then every coordinate has to be resized as well:
Code: ags

// The scale factor is a relation between final size of large dynamic sprite and its original size
// (normally I'd suggest to use Room.Width and Room.Height here instead of literal numbers)
float ScaleX = IntToFloat(propScale[i] + EnvProp[i].Width) / 1920.0;
float ScaleY = IntToFloat(propScale[i] + EnvProp[i].Height) / 1080.0;
ScaledBlockX = FloatToInt(IntToFloat(OrigBlockX * ScaleX));
ScaledBlockY = FloatToInt(IntToFloat(OrigBlockY * ScaleY));
ScaledBlockWidth = FloatToInt(IntToFloat(OrigBlockWidth * ScaleX));
ScaledBlockHeight = FloatToInt(IntToFloat(OrigBlockHeight * ScaleY));

Again, these coordinates are positions of the blocking area related to the resized sprite's local coordinates. This is not final.

How to find the position of the blocking rectangle in the room:
Code: ags

// This is where your resized tree is actually positioned in the room
int RealPropX = object[i].X + FloatToInt(IntToFloat(propX[i] * ScaleX));
int RealPropY = object[i].Y + FloatToInt(IntToFloat(propY[i] * ScaleY));
// So, and the blocking object rectangle will be
int BlockRoomX = RealPropX + ScaledBlockX;
int BlockRoomY = RealPropY + ScaledBlockY;
int BlockRoomWidth = ScaledBlockWidth;
int BlockRoomHeight = ScaledBlockHeight;


EDIT: Realized a bit later, but we may actually skip ScaledBlockWidth/Height part and do following:
Code: ags

float ScaleX = IntToFloat(propScale[i] + EnvProp[i].Width) / 1920.0;
float ScaleY = IntToFloat(propScale[i] + EnvProp[i].Height) / 1080.0;

int BlockRoomX = object[i].X + FloatToInt(IntToFloat((propX[i] + OrigBlockX) * ScaleX));
int BlockRoomY = object[i].Y + FloatToInt(IntToFloat((propY[i] + OrigBlockY) * ScaleY));
int BlockRoomWidth = FloatToInt(IntToFloat(OrigBlockWidth * ScaleX));
int BlockRoomHeight = FloatToInt(IntToFloat(OrigBlockHeight * ScaleY));

That should give identical results.


NOTE: the actual Baseline formula is also:
Code: ags

int RealPropY = object[i].Y + FloatToInt(IntToFloat(propY[i] * ScaleY));
int RealPropHeight = FloatToInt(IntToFloat(Game.SpriteHeight(prop[i]) * ScaleY));
object[i].Baseline = object[i].Y - Room.Height + RealPropY + RealPropHeight);



Now, I have to admit that I did not test all this, but only figured in my head. So I cannot 100% guarantee that's correct. I'd need to have actual test game on my computer to experiment with.
In any case, I strongly advise to clarify the resizing code you are using. Especially since you say yourself that you do not know the reason behind some formula. Because as you progress further this situation will only worsen...

Imc7r

#42
That's a lot of posting I appreciate the time on it! Yes the code is messy and you are correct about resizing, I thought I may have to multiply by the same scaling factor, I was about to test the displacement if image is resized, this may also be the reason why things appear way off. Im going to work on improving that code because some things are made bad I agree. But let me explain why some things are as you see them, I had  to do a lot of math, it was like as if I was trying to find a distance or make ratios between positions to make things scale up/down based on where they are located Y-wise.

The reason why I added a "Scaling Factor" was exactly because I wanted to make the objects, the lower they are on the Y axis, the bigger they are , on the very top they had to be scaled down to serve as a distant background.

I MISSED the SCALE parameters of Draw Image, you are right, then I can use just those instead of separate vars, I completely omit these not seeing they exist! (thanks). And then I dont need an extra scaling it can be all happening within the Draw image line.

You said prop coordinates stayed the same if I used the Draw Image Width Height scaling, then this is the first thing I just corrected. Here is the improved code:

Code: ags

function room_Load()
{
  SetBackgroundFrame(season);
  
  if (Game.DoOnceOnly("3"))
  {
    exitEast = true;
    exitNorth = true;
    exitSouth = false;
    exitWest = false;

//code to decide Props ID randomized then

    
    for (int i = 0; i<=7; i++)
    {
      propX[i] = Random(System.ViewportWidth);
      propY[i] = Random(FloatToInt(IntToFloat(System.ViewportHeight) * 0.37, eRoundNearest));
      propScale[i] = IntToFloat(propY[i]) / 100.0;
      if (propScale[i] < 1.20) { propScale[i] = 1.20; }
      object[i].Baseline = object[i].Y - Room.Height + propY[i] + FloatToInt(IntToFloat(Game.SpriteHeight[prop[i]]) * propScale[i], eRoundNearest);
      
      EnvProp[i] = DynamicSprite.Create(Room.Width, Room.Height,  true);
      EnvPropSurface[i] = EnvProp[i].GetDrawingSurface();
      EnvPropSurface[i].DrawImage( propX[i], propY[i], prop[i], 0, FloatToInt((IntToFloat(Game.SpriteWidth[prop[i]]) * propScale[i]), eRoundNearest), FloatToInt((IntToFloat(Game.SpriteHeight[prop[i]]) * propScale[i]), eRoundNearest));
      
      propTint[i] = 50.0 - (IntToFloat(object[i].Baseline) / 3.148) * 0.0462;
      
      if (prop[i] == 9 || prop[i] == 10 || prop[i] == 12 || prop[i] == 13 || prop[i] == 16 || prop[i] == 17 || prop[i] == 19 || prop[i] == 20 || prop[i] == 23 || prop[i] == 24 || prop[i] == 26 || prop[i] == 27)
      { EnvProp[i].Tint(1, 1, 1, FloatToInt(propTint[i]), 0); }
      
      object[i + 8].SetPosition(propX[i] + FloatToInt((IntToFloat(Game.SpriteWidth[prop[i]]) *  propScale[i] / 2.00) - (IntToFloat(Game.SpriteWidth[29]) / 2.00), eRoundNearest),  object[i].Baseline); 
      
      if (prop[i] == 13 || prop[i] == 20)
      { object[i + 8].SetPosition(propX[i] + FloatToInt((IntToFloat(Game.SpriteWidth[prop[i]]) *  propScale[i] / 2.00) - (IntToFloat(Game.SpriteWidth[29]) / 2.00), eRoundNearest) + FloatToInt(50.0 * propScale[i], eRoundNearest),  object[i].Baseline); }
      else if (prop[i] == 27)
      { object[i + 8].SetPosition(propX[i] + FloatToInt((IntToFloat(Game.SpriteWidth[prop[i]]) *  propScale[i] / 2.00) - (IntToFloat(Game.SpriteWidth[29]) / 2.00), eRoundNearest) + FloatToInt(80.0 * propScale[i], eRoundNearest),  object[i].Baseline); }      
      
      object[i + 8].BlockingWidth = FloatToInt(IntToFloat(Game.SpriteWidth[29]) * propScale[i], eRoundNearest);
      object[i + 8].BlockingHeight = FloatToInt(IntToFloat(Game.SpriteHeight[29]) * propScale[i], eRoundNearest);
      object[i + 8].Solid = true;
   
      object[i].Graphic = EnvProp[i].Graphic;
      EnvPropSurface[i].Release();   
      //EnvProp[i].Delete();
    }
  }
}
   


EDIT: After changing some things into this, it works! Thanks for some suggestions I based it on these ideas you posted but also entirely remade some formulas myself. The squares are always centered in the bottom center of the image. Now that I got them where I wanted I could use Solid but I would still need to increase blocking based on the scaled image, so I will use Blocking W/H. I tested it and im not sure of Blocking Height/Width worked without Solid, as Char still went thru, I had to enable Solid too. Oh the manual says it needs Solid to work so yes, done with this Random system ! (Next I will work one one Day/Night ez cycle just some dark transparent screen, new post if I come across such confusing system but I think I did the HARDEST of my game, since it is so uncommon to do such a system). Thanks for the help with all that, I will give credit for all the help.

Imc7r

#43
With the above a large milestone was made.  Im not planning to make other complex things other than the other things I mentioned in my first posts, all less complex and more common. I may be having some smaller questions mostly related to unexplained problems that make no sense to not work, and I should be able to do the rest on my own. Here is one:

Prob 1) - Solved
I cannot understand why my character refuses to Change Room on the Right. In the starting room 1 I set the function for 'Walks off left edge' and 'right edge' and it changes to room 2 that is on the left. So this works, but then when he appears at Room 2 (If he left room 1 [x_______| on the left there I set his X to e.g 1900 (out of room width 1920) to be there |_______x| in room 2 . So. he walks at the Right edge of Room 2 and nothing happens. I tried in Room 1 to go Right and also nothing happens, even though I set the function for Right edge. In room 2 (created from template of Room 1 with all objects already set), I removed block code or anything in case it was blocking but he still doesnt change room e.g back to room 1 on the Right. Im using the Single Cursor template but it has code related to mouse click, I use arrows for walking so it is not the reason I think, since it works at least on the Left screen.

In the 'Edges' of the room BottomEdgeY (default 198), TopEdgeY (default 40), LeftEdgeX (0) and RightEdgeX (317) not sure if I had to change them for 1920x1080. Bingo. This was the culprit. I had to modify to my HD edges like 1910 for Right X.

Prob 2) - Solved
I noticed that in order to preserve the system of randomly placed objects so as to be the same, I need to have it at 'First time enter the room' event. Though, the items are then created after you see the screen so they pop up suddenly which makes them unrealistic, I would prefer to hide the generation of objects like 'Before Fade In' but this one won't preserve the initially created Dynamic Sprites and will recreate new ones & new positions when returning to the room. This would be better for elegance, even though they are popping up like that just once. I tried adding a Fade to hide the sudden appearance of objects but it seems First Time Enter still waits for the Before Fade In event. Splitting the code by generating the variable values at First Time and drawing image in Before Fade In also didnt work because First Time Enter may be running after Before/After Fade In.

EDIT: thanks for the below~ it works
AND I noticed, if I want to start at random room, even though I had to set an existing room for Char's starting room, I can use this   MyChar.ChangeRoom(Random(1) + 1); in function game_start() event in Global Script.

Crimson Wizard

#44
Quote from: Imc7r on Fri 27/04/2018 23:37:51
Prob 2) - Unsolved
I noticed that in order to preserve the system of randomly placed objects so as to be the same, I need to have it at 'First time enter the room' event. Though, the items are then created after you see the screen so they pop up suddenly which makes them unrealistic, I would prefer to hide the generation of objects like 'Before Fade In' but this one won't preserve the initially created Dynamic Sprites and will recreate new ones when returning to the room. This would be better for elegance, even though they are popping up like that just once. I tried adding a Fade to hide the sudden appearance of objects but it seems First Time Enter still waits for the Before Fade In event.


Start generation from "Before fade-in", but call generation function under this condition:
Code: ags

if (Game.DoOnceOnly("RoomNGenerated"))
    GenerateRoom();


"RoomNGenerated" should be a unique ID for each room.

Alternatively you may use some boolean variable per room for the same purpose.

Imc7r

#45
I'm trying some UI changes to fit the Kyr style and I read some related threads but I can still mess up some things.

1. SOLVED Is there a way to make the UI menu pop up when Mouse moves at the bottom of the screen? One thing I like over the old styles is the ability to hide the menu when not called but it would be better at the bottom. I noticed gIconbar has the option to Pop Up from top only so my guess is the same does not work from Bottom?

----What I did was set the Visibility to Normal, Initially Off, then

Code: ags
function repeatedly_execute_always() {
  
  if (player.Room <= 300)
  {  
    if (gIconbar.Visible == false && mouse.y >= FloatToInt(IntToFloat(System.ViewportHeight) * 0.98, eRoundNearest) &&
    ( mouse.x >= FloatToInt(IntToFloat(System.ViewportWidth) * 0.01, eRoundNearest) || mouse.x >= FloatToInt(IntToFloat(System.ViewportWidth) * 0.99, eRoundNearest)))
    {
      gIconbar.Visible = true;
    }
    else if (mouse.y < FloatToInt(IntToFloat(System.ViewportHeight) * 0.81, eRoundNearest))
    {
      gIconbar.Visible = false;
    }


------------------------

2. SOLVED
I will also do like Kyrandia when mouse is say 10 pixels from some edge (but not corner that will be used for showing the UI) the pointer icon changes and a click means walk to that end automatically, to change screen. I have the code to change room when the char reaches just need to command him, but that might be the same as my main question switching modes as a single cursor w left click? (EDIT - so far may be like how i did the above code)

Trying to change arrow  at the edge of each direction and if it is not where you can change screen show the red X that you cannot exit that way. I declare these bools in each room script (because where you can go varies from room to room):

Code: ags

import bool itemIsSelected;

//to change cursor at each edge including the X cursor
function room_RepExec()
{
  if (itemIsSelected == false)
  {
    if (mouse.x <= FloatToInt(IntToFloat(System.ViewportWidth) * 0.005, eRoundNearest))
    {
      if (exitEast == true)
      { 
        mouse.ChangeModeGraphic(Mouse.Mode, 6);
      }
      else if (exitEast == false)
      {
        mouse.ChangeModeGraphic(Mouse.Mode, 37);
      }
    }
    else if (mouse.x >= FloatToInt(IntToFloat(System.ViewportWidth) * 0.97, eRoundNearest))
    {
      if (exitWest == true)
      { 
        mouse.ChangeModeGraphic(Mouse.Mode, 7);
      }
      else if (exitWest == false)
      {
        mouse.ChangeModeGraphic(Mouse.Mode, 37);
      }
    }
    else if (mouse.y <= FloatToInt(IntToFloat(System.ViewportHeight) * 0.009, eRoundNearest))
    {
      if (exitNorth == true)
      {
        mouse.ChangeModeGraphic(Mouse.Mode, 4);
      }
      else if (exitNorth == false)
      {
        mouse.ChangeModeGraphic(Mouse.Mode, 37);
      }
    }
    else if (mouse.y >= FloatToInt(IntToFloat(System.ViewportHeight) * 0.94, eRoundNearest))
    {
      if (exitSouth == true)
      {
        mouse.ChangeModeGraphic(Mouse.Mode, 1);
      }
      else if (exitSouth == false)
      {
        mouse.ChangeModeGraphic(Mouse.Mode, 37);
      }
    }
    else
    {
        mouse.ChangeModeGraphic(Mouse.Mode, 2061);
    }    
  }
}



3. SOLVED
The biggest thing is how do I make the cursor do specific actions as one? I created a custom Mouse Cursor and added in global script on startup to disabled Look, Inventory, Talk To, Pickup.  So by default it should do the same as walk but when clicking on hotspots and things, should it be coded things to happen when the mouse is at certain region? How does it change the mode, do I still need to switch to modes ? Im not sure

Inventory window will be deleted as it will be part of the main panel but how it will detect items placed in the main panel and how to place them will deal later.

Crimson Wizard

#46
Quote from: Imc7r on Fri 18/05/2018 20:51:14
3. UNSOLVED
The biggest thing is how do I make the cursor do specific actions as one? I created a custom Mouse Cursor and added in global script on startup to disabled Look, Inventory, Talk To, Pickup.  So by default it should do the same as walk but when clicking on hotspots and things, should it be coded things to happen when the mouse is at certain region? How does it change the mode, do I still need to switch to modes ? Im not sure

I see you have posted the script example below your question, that kind of script might actually for work for you. You just have to modify it for you particular needs.

Just in case, some clarification.
Mouse Modes are made for convenience when using Sierra-like cursor mechanics, when each cursor type has its action. Then you may just script
Code: ags

if (button == eMouseLeft)
    Room.ProcessClick(mouse.x, mouse.y, mouse.Mode);

Which means "refer to this cursor's mode to trigger corresponding interaction".
Notice, that you still tell engine what to do, there is no automatic action here on mouse click. And if you want custom behavior, you simply change ProcessClick parameters to something else.

For example, in the Khris's script you posted above, the "mode" parameter sent to ProcessClick is determined not by mouse mode (since it stays the same), but by other conditions, such as mouse button or kind of location you click on.

You may devise your own rules, for instance, change the interaction depending on type of object:
Code: ags

int mode = eModeInteract;
int lt = GetLocationType(mouse.x, mouse.y);
if (lt == eLocationCharacter)
    mode = eModeSpeak;
Room.ProcessClick(mouse.x, mouse.y, mode);


Or make use of Custom Properties to know which action to run on the hotspot, but then you will have to get actual object using GetAtScreenXY
Code: ags

Character *ch = Character.GetAtScreenXY(mouse.x, mouse.y);
Object *obj = Object.GetAtScreenXY(mouse.x, mouse.y);

int mode = eModeWalk;
if (ch != null)
    mode = ch.GetProperty("DefaultAction");
else if (obj != null)
    mode = obj.GetProperty("DefaultAction");
Room.ProcessClick(mouse.x, mouse.y, mode);




Another ability that you have is RunInteraction function (it is applicable to most game classes, such as Characters, Objects etc). The difference between ProcessClick and RunInteraction is that ProcessClick first finds out what actual object will receive the event, and then calls RunInteraction for it. Calling RunInteraction yourself gives you precise control over which object will that be.
You may even do multiple RunInteraction calls for different objects or with different interaction modes sequentially.

Imc7r

#47
In solution 1 and 2 I shared the code, I built my bottom pop-up gIconbar menu and cursor change at edges, as well as Walk player to edges, also cursor change to X cursor if you can't go there and play sound, for now I dont hear sounds even when imported but this will be dealt at later point. Since the game cannot detect 'Current cursor image used' when it is set in the rooms and what edge the cursor will be changes from room to room, since some rooms you go 4 ways others only 2 or 3 etc. Then I put the edgeCursor integer to be updated as a var when cursor icon changes, so it all goes under the

if edgeCursor == 0 which is when the cursor is within the game and not any edge cursor do: all the different things you can do with left-click.
Thx for the explanation I will play around with these.

Crimson Wizard

#48
Quote from: Imc7r on Sun 20/05/2018 20:27:21Since the game cannot detect 'Current cursor image used' when it is set in the rooms and what edge the cursor will be changes from room to room, since some rooms you go 4 ways others only 2 or 3 etc. Then I put the edgeCursor integer to be updated as a var when cursor icon changes

You could use Mouse.ChangeModeGraphic, then it will tell you which graphic is that with Mouse.GetModeGraphic. Also then you won't have to have multiple cursor modes for this, only different sprites.

Aside from that, I strongly recommend using System.ViewportWidth and System.ViewportHeight when you refer to the size of the screen, and Room.Width and Room.Height when you refer to the size of the room, instead of putting literal coordinates in the general scripts. The latter is more important, because you may happen to have scrolling rooms later at some point, then your scripts will work incorrectly.

Imc7r

#49
Quote from: Crimson Wizard on Sun 20/05/2018 20:41:25
You could use Mouse.ChangeModeGraphic, then it will tell you which graphic is that with Mouse.GetModeGraphic. Also then you won't have to have multiple cursor modes for this, only different sprites.

Aside from that, I strongly recommend using System.ViewportWidth and System.ViewportHeight when you refer to the size of the screen, and Room.Width and Room.Height when you refer to the size of the room, instead of putting literal coordinates in the general scripts. The latter is more important, because you may happen to have scrolling rooms later at some point, then your scripts will work incorrectly.

Ah, I was using UseModeGraphic and I checked it was always returning the default icon with Mouse.GetModeGraphic that's why I used other variables but now I made it all work with ChangeModeGraph. I deleted the other cursors, now it works the same. I started using SystemViewports and updated all my code where I use e.g 1900 of 1920 which is 98% to be e.g 0.98 * system.. width, even updated here in the posts. Thanks, I dont think I would use other types of rooms but it could come in handy if I resized things.

Well there are things not clearly posted in the Khris code like he posts ProcessClick but that requires e.g Room.ProcessClick. And Im also not sure if im doing those right as nothing happens. So far I do:

function game_start() {
  mouse.DisableMode(eModeLookat);
  mouse.DisableMode(eModeInteract);
  mouse.DisableMode(eModeTalkto);
  mouse.DisableMode(eModeUseinv);
  mouse.DisableMode(eModePickup);
  mouse.DisableMode(eModeWait);
  mouse.EnableMode(eModeKyrCursor);
  mouse.Mode = 8;

and then at
function on_mouse_click(MouseButton) - any mouse button will do the same, I will not restrict button.

if (GetLocationType(mouse.x, mouse.y) == eLocationNothing) { Room.ProcessClick(mouse.x, mouse.y, eModeWalkto); }
^ that doesnt work, I just tried to see from Khris code (unless it doesnt work because my objects cover the whole screen only the dynamic images are part of it) I dont mind using other way or detecting only if there is hotspots/chars. For random trees unless I assign a hotspot or something, clicking on them should be walkable as if there is nothing even though they are part of whole screen object.

I think I get it though, the simplest is, if I do (if there is object hot spot character whatevr do ..... stuff)

ELSE
  else { player.Walk(mouse.x,  mouse.y); }

Crimson Wizard

Quote from: Imc7r on Mon 21/05/2018 00:50:28
  mouse.Mode = 8;
You could also do "mouse.Mode = eModeKyrCursor;"

Quote from: Imc7r on Mon 21/05/2018 00:50:28
if (GetLocationType(mouse.x, mouse.y) == eLocationNothing) { Room.ProcessClick(mouse.x, mouse.y, eModeWalkto); }
^ that doesnt work, I just tried to see from Khris code (unless it doesnt work because my objects cover the whole screen only the dynamic images are part of it) I dont mind using other way or detecting only if there is hotspots/chars. For random trees unless I assign a hotspot or something, clicking on them should be walkable as if there is nothing even though they are part of whole screen object.

Oh right, you have that big object, or objects that cover all screen... this is also another reason to have small objects per each tree only roughly the size of tree.

Anyway, first thing to check is that you have "Pixel-perfect click detection" enabled in General Settings (Visual category).
Other thing to test out is set these large objects Clickable property to false.
I do not remember right away whether GetLocation acknowledges these settings, probably it should.
On the other hand this may be something else wrong with the script.

Imc7r

#51
Quote from: Crimson Wizard on Mon 21/05/2018 01:05:18
Oh right, you have that big object, or objects that cover all screen... this is also another reason to have small objects per each tree only roughly the size of tree.

Yes but if you think about it, even if a tree object/dynamic sprite took 1/8 of the screen width, every time there was a tree you would not be able to use things at its base even if there was transparent areas. So making those uninteractable while other things are placed too works fine for me. That works already to click on chars on top of these large objects:

Code: ags
    else if (GetLocationType(mouse.x, mouse.y) == eLocationCharacter)
    {
      Room.ProcessClick(mouse.x,  mouse.y,  eModeTalkto);


I set the character  talk, even used right click for general look at, so im on the page of Inventory. Few questions: I remember from page 1 that I was better off using characters as inventory that when clicked you get the item cursor as if picked, character hides (in room -1) or disappears etc. My question is, I noticed there are Custom values but if I can't differentiate different types of chars, it will be of no use to me. I want to assign text property Item to all chars that will be items but not to others. If I couldn't use Custom Value I would just IF every single char that is item or vice-versa but I see more use in Custom value if it could distinguish same type e.g between chars.

Crimson Wizard

#52
Quote from: Imc7r on Tue 22/05/2018 23:24:42My question is, I noticed there are Custom values but if I can't differentiate different types of chars, it will be of no use for me. I want to assign text property Item to all chars that will be items but not to others, so t hat I have a condition if (value is Item) ---do this, instead of IF every single character that is item or not so as to have a different outcome if it is a character or "item character". E.g if character - talk if not, - the pick up item stuff.

These are not really "attribute" kind of properties, but "variable" kind, in other words property will be attached to all of them, but its value may be different.

In other words, you create property "Item" for everyone, but then set values "Yes" or "No" for particular characters.

For your case a custom property of type boolean could be enough, but who knows maybe you will need more character types. So you may even make property "CharacterType", and set value "Item" to ones who are items. Then condition would be:
Code: ags

if (ch.GetTextProperty("CharacterType") == "Item")

Imc7r

#53
Oh I was new to this, so I can use a common name like CharType and just change/compare the value of the types I want to distinguish. Can I set the value of each character from the Editor or only with script? If I can manually add the 'Item' value to such characters but I think I can only edit the default value that applies to all from the Editor.

I made a nice way to mimic Kyrandia inventory like that, tomorrow i'll only make the items show up in the inventory window:

I will just try when I click on the visible inventory panel, item to get placed there.


Crimson Wizard

Quote from: Imc7r on Wed 23/05/2018 01:35:39
Oh I was new to this, so I can use a common name like CharType and just change/compare the value of the types I want to distinguish. Can I set the value of each character from the Editor or only with script? If I can manually add the 'Item' value to such characters but I think I can only edit the default value that applies to all from the Editor.

Default/starting values are set in the editor, but may be changed in script using SetProperty/SetTextProperty.

Imc7r

#55
^ Yes but you cannot set the default value to be different for different chars (e.g char 1 has default value text "hero", char2 has default "item", char3 "item" too), they all would start with what you typed as value, so I have to use script to change the value of each item that pops up in the world. That's fine.

I have this more 'how to build the code for this' I actually am weak on using (something) * (something) in script, barely made one thing work.
I want to have say if (at the mouse click event and gIconBar.visible == true, it now contains the InventoryWindow) to show:

(if Mouse.x and Mouse.Y triggered by the mouse click event are within the InvWindow) then check if (slot 1 in the inventory is NOT busy, place an item, else at slot 2, else, at slot 3). The slots are just part of the gIconbar image, the Invwindow is a rectangle area,  and I  read some manual stuff dont know how 'cells' are used in an inventory box and what prevents from placing an item on top of another. I could not find any info for this.

Crimson Wizard

#56
Quote from: Imc7r on Wed 23/05/2018 15:01:08
^ Yes but you cannot set the default value to be different for different chars (e.g char 1 has default value text "hero", char2 has default "item", char3 "item" too), they all would start with what you typed as value, so I have to use script to change the value of each item that pops up in the world. That's fine.

No you can, that's the point of the system, because originally you could not change values in script at all.
Simply find "Properties" property in particular character's pane, click on (...) and change starting value there.

I was perhaps not clear enough, when saying "Default/starting value" I meant they are different values, not same.

"Default value" is the one set when you edit Properties Schema. This is the value that will be assigned to all characters until you change it later.
"Starting value" is per-character value that you set for particular character in its properties.



Quote from: Imc7r on Wed 23/05/2018 15:01:08
I have this more 'how to build the code for this' I actually am weak on using (something) * (something) in script, barely made one thing work.
I want to have say if (at the mouse click event and gIconBar.visible == true, it now contains the InventoryWindow) to show:

(if Mouse.x and Mouse.Y triggered by the mouse click event are within the InvWindow) then check if (slot 1 in the inventory is NOT busy, place an item, else at slot 2, else, at slot 3). The slots are just part of the gIconbar image, the Invwindow is a rectangle area,  and I  read some manual stuff dont know how 'cells' are used in an inventory box and what prevents from placing an item on top of another. I could not find any info for this.

I need to clarify this, are you using builtin InventoryWindow, or trying to script your own? In builtin one you cannot choose at which exactly slot to place an item, it does not have such functionality. It simply displays the items from Character's inventory in some order (don't remember which one, probably in the order you found them).
From your description (slot 1 in the inventory is NOT busy, place an item, else at slot 2, else, at slot 3) this behavior may be achieved by simply using builtin InventoryWindow and giving item to character using Character.AddInventory. InventoryWindow will do the rest on its own.

Imc7r

#57
Oh I didn't see the field before 'Edit schema' has almost invisible field that doesn't say it is starting value but it works now thanks.

And I can try with the default Inventory scripts, I do use custom type tho  but what LucasArts and the AGS defaults do is when character clicks on item in the world, it immediately appears in the inventory. I want like in Kyrandia you have to navigate your cursor (already set to the item icon) to the inventory window before the 'create inventory' kind of scripts. As for how it positions, I will see later cause my inventory image has different places to put items on would have been better if I could choose where but for now let's have it drop at the inventory.

I'm trying to get the correct mouse check, it is not GUI, I tried GUIControl * inventoryArea, my InventoryWindow is part of gIconbar, dunno if I have to still enable inventory

Crimson Wizard

#58
Quote from: Imc7r on Wed 23/05/2018 21:13:06
And I can try with the default Inventory but what it does is when character clicks on item in the world, it immediately appears in the inventory. I want like in Kyrandia you have to navigate your cursor (already set to the item icon) to the inventory window before the 'create inventory' kind of scripts.

Oh, I see now.

Hmm. Well, then it should probably be done in following way:
1) On left-clicking a "item" on ground you hide the character, and remember the corresponding InventoryItem* in some variable, let's say "PickedUpItem". Also switch mouse.Mode to eModeUseInv, or simply change mouse graphic to the item's sprite (depends on how you handle modes).
Note, you cannot use Character.ActiveInventory property, because it's restricted to only items that is already in inventory.
So now, the item is not yet in inventory (and not displayed in InventoryWindow), but it is stored in a variable and displayed on cursor.


2) On left-clicking on InventoryWindow you check whether item variable "PickedUpItem" holds a valid pointer. If it does, then you call player.AddInventory(PickedUpItem), reset "PickedUpItem" to null, reset cursor graphic.

Detecting that left click was made over inventory window is done like this:
Code: ags

function on_mouse_click(MouseButton button)
{
   if (button == eMouseLeftInv)
   {
       // put into inventory
   }
}



PS.
Code: ags

inventoryArea = GUIControl.GetAtScreenXY(mouse.x, mouse.y); //well this seems to be wrong here already display shows nothing
Display("%s", inventoryArea);

if (inventoryArea == InventoryWindow)
{
    player.Say("You got it");
}

Not sure why the condition below does not work, but its lucky this Display did not crash the game, because "%s" expects String, and you pass a pointer to object there (EDIT: oh, it probably won't crash, but not display anything at all). The proper format for pointers is "%p".

Imc7r

#59
1. Unable to click item hidden behind Solved

See else if (itemIsSelected == true && gIconbar.Visible

2. Create item at inventory after clicking in the inv window Solved

See function on_event(EventType event, int guiType)

SMF spam blocked by CleanTalk