Pulstar's Forum Posts

  • Ah ok, I did not notice the edit, sorry. You are using array.indexof(0) to find the empty right? Also a valid way to do it, never thought of it. Anyway I have some suggestions as to the solution. I will give you two solutions actually, the first one is applicable in your case since you store type at index y=0. The second is more general if you need to check things at other y indexes.

    Specific for type stored at y=0:

    Remember that snazzy indexof you are using? Use array.indexof(block.type). It will return an index of 0 or greater if the block of that type is already in the array. It will return -1 if the block type has not yet been added to the inventory at all. And if the block type is in the array, you can use the same expression to tell the function at which index to add the new block amount.

    General:

    What I do is the following. Create a local variable "IsInInventory" or something similar in the event. Default value 0. Create another for the type of item you add if needed.

    Event conditions

    Loop for every X element of the inventory.

    Inventory value at (Self.CurX,0) = type

    Event Actions

    set value "IsInInventory" to 1

    Next you just make an event with condition IsInInventory=1 and do whatever you need to do.

    BTW I like your project, pretty cool.

  • Personally I would not use the array size as the inventory size, Instead I would add a variable to the array object and call it "ItemLimit" or similar, next I would set the default inventory array width to 0.

    Every time an item is added or removed I would push or pop an array X element. That way you would know for sure that every X element is an item, so if array.width would equal "ItemLimit" you would know it is full. And if it is full, you would prevent any item add events from firing.

  • But those classic RPG's used layout yes?

    I assume you meant to ask if they had a separate layout/screen/scene for the inventory or if the inventory window.

    Now that is a good question, but overall in the case of here and now with construct 2 I think how they handled it is not really relevant. We are not bound by the same limitations of the hardware and tools but have different limitations due to the nature of construct 2. I think that at least for the PS1 games it was not a separate scene, because they would have to load it from the CD each time then load back the actual game world scene from the CD. But that's just a guess.

    If you can make it work you can use a separate layout, however you need to consider that:

    1) you will need to make sure the objects you interact with (such as the player or party members) get transferred between the layouts.

    2) the state of the game layout after you switch back is exactly the same. IIRC if you switch to a layout the initial objects and their placing is restored in addition to any objects that had persistent behaviour.

    If you do it on the same layout but as a different layer that is invisible when the inventory is closed:

    1) you will need to "pause" all enemy movement etc.

    2) you will need to make sure player input events for movement or other actions does not trigger when doing something in the inventory. For example I needed to make sure that if I click on an item in my inventory window, the player character will not start moving to the tile hidden behind the inventory window.

    All of the issues in both approaches can be overcome, but you will need to think or look for the solutions and decide what you want to use. There is no universal "best" way to do this, there is one that is best for you and finding out what it is might take trying and experimenting and even failing. But do not get discouraged, Rome was not built in a single day and knowing what doesn't work and why is important to know what works

  • Depends on the target device and what you do with the objects and how often. I found out the hard way why using sprites as tiles for a game with Z-levels is bad, especially when you have a couple thousand of them. But I digress. And you want infinite inventories anyway.

    But generally I would recommend against having such a thing as an item object for each item when not necessary and that is the approach I took when doing inventory systems in some of my attempts at such.

    What I do instead is the following. Store items only in an array, they exist only as a columns in arrays. An array with many rows mind you as it contains general information such as item type, sub-type, weight, size, sprite, name and description. It also has a bunch of rows dedicated to "special" data. In those rows I store coma separated value strings that are different for each item type. For example weapons have different strings, armor has differently formatted strings etc.

    So how do I fire a gun a with that or equip body armor? There are two approaches I am considering now but I will most likely use the second one (I used the first in the past):

    1) Have a weapon object created and assigned to the player, just one. It is in reality a container, a shapeshifter that takes the properties of whatever weapon is currently equipped by the assigned parent player or NPC object. Whenever the weapon is changed, a function will reset all its variables and load new values. The new values will be taken from the "special" data strings. The logic of the function will retrieve the special string and next, using the tokenat expression, load the weapon properties into the weapon object. Next I use the weapon object in the events as I please.

    2) Do not have a separate object altogether, store all equipped weapon data as variables of the NPC object. Otherwise it will work the same as approach 1.

    Now you asked how Final Fantasy etc. manage infinite items. They don't use object obviously for each item. When you look at an inventory you are looking at a graphical representation of an array. What they do, what I do and indeed what even such advanced business software such as SAP do (at least for multiple single value selection fields) is that they have a set number of list position objects or slot objects. Each slot is assigned an ordered position from 0 to X.

    Next what they do is store the index of the first object in the table/inventory they are showing, let's call it "i" for short. When you scroll the list a function is called updating the index of the currently displayed first object. Next the list is refreshed and the code uses a loop to put the data of item "i" into the first slot object, "i"+1 into the second slot object etc. i=4 would mean that object with index 4 (so the 5th row) of the inventory array would be shown first (top of the list/first slot).

    So you only need slot objects to show the item, as many as fit in the inventory window you designed. They will never change position, they will only change their appearance.

    Bah, if you are using only a text based inventory without any item icons or anything like earlier FF games did, you could do it with a single text object. You would just need to know how many rows you can fit in the text and how much text in a row (I recommend using monospace fonts for that, which is also what systems displaying lots of lists and tables such as SAP do).

    It would look like:

    set text as array.at(i,0) [0 would be the y index of the item name in this example]

    loop for 1 to number of rows

    append text [newline&array.at(i+loopindex(),0)]

    However making things such as highlighting the selected item, selecting it with clicking etc. would require additional objects.

    tl;dr version store the data that is needed as an object now as an object, keep everything that you need later in arrays.

  • > Please clarify what exactly you want to do. Do you want to copy 3 new items or add an item with 3 properties?

    >

    * Item on ground has;

    HpID:175

    MpID:125

    VitalityID:100

    * - When the item goes from ground to inventory, we want the HP/MP/Vitality ID values to follow

    The first thing you need to do is define how you store the HP/MP/Vitality data of the item, so from where is the data supposed to be copied. Let's assume the simplest case, that you have it as variables of an object (sprite) that represents the item. On Item pickup the object will be destroyed but only after you store the item in the inventory.

    This is how it can be done (there are arguably better, but more complicated and requiring more explaining ways). For example:

    When the player clicks or does some other action triggering item pickup, you call an "Item Pickup" function, and pass all the properties of the object as parameters of the function. So name, HpID etc. would all be instance variables of the item object (sprite).

    So you would have a call function "item pickup" action with parameter 0 = item.name, parameter 1 = item.HpID, parameter 2 = item.MpID and parameter 3 = item.VitalityID.

    Next you need to have the "item pickup" function store the data passed as parameters in the inventory array. I have no idea how many item statistics you exactly need, but you need at least 4. So your array, if it is a 2D array like in the inventory tutorial example, it needs a height of 4.

    Now, the important thing you need to do, is to write down which row stores what information for an item. Let's assume for the purpose of this example the following, as it is consistent with what we used in the parameters:

    y = 0 is the name of the item

    y = 1 is HpID

    y = 2 is MpID

    y = 3 is VitalityID

    Assuming you know into which element x (slot) you want to put the item into, which I shall simply call "i" (short for index) here, all you need to do is use the set array value at action as follows in the "on function "Item Pickup" event:

    Set value at X=i Y=0 to function.param(0)

    Set value at X=i Y=1 to function.param(1)

    Set value at X=i Y=2 to function.param(2)

    Set value at X=i Y=3 to function.param(3)

    That's it, the data will be stored in the array. You just need to know at what element x to store it, pass the right values in the function and make sure the array has the correct height so that it can store y from 0 to 3.

  • Please clarify what exactly you want to do. Do you want to copy 3 new items or add an item with 3 properties?

  • Hi, I am doing an inventory system myself currently, displayed as a grid (it works so far) and also did some stuff related to it in the past.

    1) The example in the tutorial has a function for that "AddToInv". From what I understand you pass the ID of the item as parameter 0 when you call the function "AddToInv". Look into the capx of the tutorial for the function call action in event 6.

    2) If you are using the exact same functions as the tutorial you can't just change to the height to 6 to have a 6 by 6 grid as the example uses row 1 on the Y axis to store the number of items of a given ID.

    There are basically two approaches here, both are valid and possible to use, but I believe the first one is a lot easier to manage (and I used it myself):

    A) Always use the X axis to store items and the Y elements for each X axis element as the items properties. So have an array of 36 width with whatever height you need (I do not know what information besides item name you need to store in the array).

    Advantages:

    • very easy to add remove new items from the array, as you can just pop and push, and use "array.width-1" to retrieve the index of the last added (empty) x element, and don't need to do custom functions for it.
    • counting empty space or number of items is easy (equal to array.width).

    Disadvantage:

    • requires a bit of tinkering to have it display as an item grid. Basically you need to map a one dimensional X index to a row/column combination. Not hard, but it is some extra work. But not much as your inventory slots will need a row and column position anyway, regardless if you go with a 2D array or a 3D array.

    B) Do a 3 dimensional array, with x and y being grid position and z-axis elements being item data. IMO this is a lot better for maps or other grid-based structures where you need to check relative position, calculate distance, angle or do any kind of shapes. Personally I use a 3D array for a tilemap.

    Advantages:

    • easier to map to a grid

    Disadvantages:

    • counting empty slots or finding an empty slot is more difficult.
    • you can't just add a new item by pushing a new X level element easily. Well you can, but you are basically creating new slots at the same time. So to use the array effectively, you would need to have logic to find if you have empty slots, where there is an empty slot and if no empty slots are available to push a new array element.
  • In your situation I figure spawn might be more convenient.

    I would remove the containers, otherwise you will end up with creating too many detectors and badguys. Bah, I am not sure if this would not create a feedback loop if you forget to remove the containers. Badguy spawns detector via event, detector spawns rest of container on event creating new badguy, badguy spawns new detector via event etc.

  • Yeah, I read that was the case. So, should I give each badguy a variable, put the detectors in each badguy's container, assign a variable to all the detectors and badguys, and pick each of them and give them the nearest UID?

    Or should I just duplicate code?

    Do something like below.

    On family "badguy" created

    For each "badguy"

    create/spawn detector

    set variable "detector.parent" to "badguy.UID"

    Then if the detector colides with whatever it is to collide with do:

    On detector collides with whatever

    for each detector

    pick badguy by uid [detector.parent]

    do events for badguy

    Should work IIRC. Let me know if it does not, I will be using a similar method to link inventories to NPCs and Loot Containers in my current project.

    Also family.uid=object.uid, you can also use that to check if a family member is a particular object type IIRC.

  • You could turn it off with a first subevent in the event block for the object, do whatever picking/collision condition in the next sub-event and re-enable the solid behaviour in the 3rd sub-event. If done within the same event block this should have no impact on other events.

    I used a similar solution for a tilemap with multiple z-levels when I needed to do fog-of-war. Seemed to work.

  • Please provide a new download link/URL, it doesn't appear to work.

    However there is one reason why it could be saving just one block, you need to do the saving action for each block objects, so a for each loop needs to be used. This is usually the case when an action is done just for one object correctly in an event, and what you are describing basically requires the use of a for each loop.

  • I assume the tiles are made of sprite objects and you are not using a tilemap.

    If you need to use for each, first set all the limiting conditions and to for each as the last condition. For each is slow so it is best to limit the instances it checks. With so many isometric tile objects you want to avoid doing for each unless necessary.

    Also why are you checking it every tick? What is the purpose of it? Is there not some particular triggering action that mandates a check which could trigger a function?

  • > Don't move the tilemap - scroll the viewpoint using 'System> Scroll to' events.

    >

    I better explain myself better. My tilemap map has its own layer.

    7-etc.

    6-etc.

    5-skills

    4-Map

    3-UI

    2-game layer

    1-background1

    0-background2

    Can you "scroll to" using only a layer? I imagined that would only move the viewport and i need to move the tilemap within the map layer only

    Set parralax to 0,0 on the layers not containing objects that have locations on the map (so any UIs, minimap/worldmap windows etc.), that way the layers will not scroll when any scroll commands are issued.

    For finding the portal coords you will have a bigger challenge, depends how many portals you have per map. Personally I am doing a random map generator myself at the moment and I store all tilemap data within an array that uses Z-levels to store different info about a tile (such as bitwise sum for autotile, passability, fog of war visibility/discovered status etc.). So if you also use a similar method you could iterate through the map array until you find the right portal tile and upon finding it fire the whole scroll2portal function.

    The easier way would be to not have the portal as a tile but as a sprite object drawn/created on top of an empty tile. That way you could use regular picking via events which would make the whole thing easier. I use a similar solution for some objects myself, most notable doors as they are animated and need additional data such as open/closed state and will later use it for loot boxes.

  • Try Construct 3

    Develop games in your browser. Powerful, performant & highly capable.

    Try Now Construct 3 users don't see these ads
  • In theory yes (never bothered to do it myself but the functionality is in place). You will need to retrieve the correct answer from somewhere and store it in a string, but I assume you will be loading new questions via events anyway so you will be doing it then. Once you have text variable [answer] stored do the following on text changed in textbox.

    event

    condition

    User finishes entering answer and confirms (clicks a confirm button or presses enter or something, don;t use the textbox changed text condition as it triggers every time when you type inside it)

    no actions

    sub-event -1

    condition

    textbox compare text to text stored in [answer]

    action

    call function "correct"

    sub-event -2

    condition

    else (system conditons)

    action

    call function "wrong"

  • Hi, I think I know what you want to do.

    First you need to make sure nothing else is setting the scrolling (not sure if you use scrolling to the player or if you have free scrolling in your project).

    Easiest way to do it is with some trigonometry, but you also need to store the scroll to points, either create two global variables called scroll2x and scroll2y or add those as instance variables to the player, maybe even create an object that is invisible called camera and have it store all kinds of variables related to scrolling mode. The reason why the latter might be more useful is that you can use the object as a storage for all kinds of boolean variables (like IsScrolling2Portal).

    Regardless, here is an example, because it was faster to make this than explains:

    https://www.dropbox.com/s/m9f65q4mn5yv0 ... .capx?dl=1

    It took me longer than expected to make this, mostly because I forgot the proper order of parameters for distance and angle functions. Mornings are not my best time of the day.

    I cheated a bit as I set scroll2x and scroll2y in the same event when picking the random location of the portal tile instead of searching for it in the tile map. Normally you will need to obtain it otherwise somehow, assuming your maps are not randomly generated that should be fairly easy to do.