{{indexmenu_n>30}} ====== Player Inventory ====== The inventory is a bag of items the player finds during the game and applies to things on the level: a key to a lock, a crowbar to a lid, a coin to a machine. An item is a string key (''hammer123''), and everything you do with it comes down to codes: the player applies an item, and the engine submits a code for them. There are two versions of the inventory, and they live side by side. * **The second** — a panel at the bottom of the screen, a bag with a counter, and items applied to **zones** on the task picture. One line in the task script turns it on, and it asks for no room in the task text. This page is about it. * **The first** — a list of items inside a block the author sets aside, with two buttons on an item: the eye and "use". It [[#the_first_version|works the way it always worked]] and is described at the end of the page; running games are not deprived of it. A level picks one of the two: whichever function the script called is the one that renders. ===== What the Player Sees ===== At the bottom of the screen there is a bag button. It shows the total number of items and, separately, "+N" — how many are new; while there are new ones, the bag shakes. {{ :authors_main:task_editor:advanced:inventory2_bag_en.png?800 |The collapsed bag: how many items in total and how many of them are new}} The button opens a strip of items; new ones are highlighted yellow and stop being new as soon as the player touches them — hovers, taps, or drags. {{ :authors_main:task_editor:advanced:inventory2_panel_en.png?800 |The open panel: the strip of items at the bottom of the screen, the new item highlighted}} There are two ways to apply an item, and they are equal: * **drag** the item onto the place of application; * **click** the item, then click the place of application. As soon as the item is "in hand", every place it can be applied to lights up on the level — the **zones**. At the same moment two more receivers appear next to the bag: "use" (no zone, the item on its own) and the eye — look at the item full size. {{ :authors_main:task_editor:advanced:inventory2_zones_en.png?800 |An item in hand: the zones have lit up on the picture, and next to the bag are the eye and "use"}} Let go past a receiver or click an empty spot, and the item goes back into the bag. What came of the application the player sees on the item itself: it fitted — the item jumps green; it did not — it shakes its head red. If a bonus took the item, it dissolves where it was carried to. Until the answer arrives the item pulses in place. The open panel and the point the player scrolled the strip to survive a page reload: a code is entered, the level changes — the bag stays open at the same place. The panel is pinned to the bottom of the window instead of standing in the task text, so on a phone the item and the place of application do not have to fit on the screen at once. {{ :authors_main:task_editor:advanced:inventory2_phone_en.png?400 |A narrow screen: the strip and the receivers are pinned to the bottom and do not scroll away}} ===== Turning It On ===== In the **task script** (the field at the bottom of the level): showInventoryItems2({gameId: 1234}); Nothing else is needed — no block in the task text, no ''id''; the engine draws the panel itself. ''gameId'' is the game whose folder holds the item images. It can be omitted, and then the current game is used — but see [[#item_images_after_copying_a_game|copying a game]]. > **The call must be in the task script.** The engine loads the second version after seeing ''showInventoryItems2'' in the level's script; from the task text, from a bonus, or from the game's common header it will not load it — the function will simply not exist. > > And **there must be exactly one call**: it takes the accumulated list of items, so a second one within the same render draws an empty bag. ===== Items ===== ==== Where They Come From ==== An item is given out from a bonus's **"Text after solution"** — in **"Source"** mode: It is taken away from there too, by a bonus of a later step: > The engine runs the texts of solved bonuses **afresh on every redraw of the page**. The list of items is therefore stored nowhere: it is assembled from scratch every time out of what has already been solved. The server knows nothing about items. The same fact gives the opposite trick: hand out items not from bonuses but from the **task script itself**, working out from the entered codes what should be in the bag right now. The shelf example level is built that way — a book can be put on the shelf, taken off, and swapped for another, and no separate codes are needed for it. > **Spanning bonus.** An item given by a spanning bonus cannot be taken away by an ordinary level bonus — only by a spanning bonus with a higher sequence number. **An item does not travel to the next level by itself.** A level's bonus does not run on another level, so the item is not there either. A thing carried through the whole game is given out by a **spanning** bonus. ==== Item Images ==== An item's picture is looked up by file name: **''item_''** is the icon in the strip, **''item__big''** is what the eye opens. There is no need to upload both by hand. Upload **one** picture named ''item_hammer123.png'' to the game's files: if it is **512 pixels or more on both sides**, the engine splits it into the icon and the large version itself. Smaller, and it stays a single file, and the eye shows that same one. In the list of uploaded files such a picture gets a ready-made line, ''addInventoryItem('hammer123')'' — a click copies it to the clipboard. That is what goes into the bonus: an item is connected by its key, not by a file address. The engine keeps such a file's name as it is, even with "Keep the name" unchecked: the inventory looks the picture up by name. The key is taken from the name together with its case — it is exactly the string that goes into ''addInventoryItem()''. === Format === By default the engine looks for ''.jpg''. Pictures in another format — including the transparent png the slot and the shadow in the panel were made for — are declared once per game, in the **"Common HTML header"**: The icon and the large view are declared separately: they may be in different formats. A one-off exception goes as the second argument: addInventoryItem('map7', {icon: 'png', big: 'png'}); The extension is **not part of the key**: the key is the code that goes to the server. === Item Images After Copying a Game === Item images are taken from the folder of the game whose number you passed. Copying a game does not copy its files, so in the copy the pictures are gone — unless ''gameId'' is named explicitly, or if it points at the copy itself. Bind the inventory to the game the pictures were uploaded to: showInventoryItems2({gameId: 3493}); The same number can be set once for the whole game, in the **"Common HTML header"** — it is copied together with the game: ===== Zones of Application ===== A **zone** is a place on the level an item is applied to: a door, a lock, a merchant, a shelf slot. A zone has a code. When the player applies an item to a zone, the engine submits a **compound code: the zone's code plus the item's key**. A crowbar (''crowbar'') on the ''lid'' zone is the code ''lidcrowbar''. That is the code the bonus which opens the lid must have. {{ :authors_main:task_editor:advanced:inventory2_apply_en.gif |The crowbar on the lever: the code is the zone's name plus the item's key}} A zone with no code behind it simply answers "did not fit", and the item returns to the bag. There is no need to invent "empty" zones: a zone with no matching item is harmless. Applying **without a zone** — "use" next to the bag — submits a code equal to the item's key (the same as in the first version). > **The zone's code and the key are glued together with no separator**, so keep the names apart yourself: the zone ''slot'' with the item ''1book'' and the zone ''slot1'' with the item ''book'' give one and the same code. The engine does not check on the player's side which item fits which zone, and it will not: the right answer would then be lying in the page source. Any item on any zone is just a code, and it is the server that answers it. ==== Declaring a Zone ==== Four ways, and all of them are about the same thing — a point and a radius around it. They differ only in where the point comes from. === A Point on a Picture (Inline SVG) === The main way when a picture has several places of application. In the task text, in **"Source"** mode: The coordinates live in the ''viewBox'' system, that is, they are tied to the picture rather than to the screen: phone, desktop, rotation, zoom — the point stays in the same place of the drawing. Nothing has to be recalculated. ''r'' is the radius of application **in the picture's units**. On a small screen the picture shrinks, and the zone would shrink with it — so the engine raises the hit area to the size of a finger by itself. Not only ''circle'' works: any shape's bounding box is taken. > A picture inserted as '''' cannot be marked up this way: an external svg has no content the engine can reach. For a picture in '''' use the percentages below. === Percentages on a Picture === The cheapest way when you would rather not bother with svg: After the colon — the zone's code, then percentages of the picture's own size: x, y and (optionally) the radius. One attribute can hold as many zones as you like, separated by spaces. An icon of its own cannot be set this way — only one common to every zone of that host. If each needs its own, use ''data-inventory-zone'' on separate elements or ''addInventoryZone()''. === Any Element of the Page ===
The merchant
The hit area is the element's whole rectangle. This is the answer for "the zone is a block of text, a whole picture, or a button". === From a Script === A zone that is not on the level to begin with is declared by a call — in the task script or in a bonus's "Text after solution": addInventoryZone('box', {el: '#room', x: 120, y: 150, r: 45}); The first argument is the zone's code. Then: ^ Field ^ What it means ^ | ''el'' | the host: a selector or an element. **Required** — it sets the coordinate system | | ''x'', ''y'' | the position inside the host; without them — the element's centre, and the hit area is its whole rectangle | | ''r'' | the radius of application; without it — the size of the icon, raised to a finger | | ''icon'' | the zone's own icon; without it the common one | **The host decides the units**: an inline svg means its ''viewBox'' coordinates, any other element means percentages of its rectangle (the radius, percentages of the shorter side). The same ''{x: 150, y: 262}'' means different things on an svg and on a picture. There are no absolute screen coordinates on purpose: they would slide away on the very first different screen. Calling again with the same code does not start a second zone but **updates the existing one**. That also means a zone can be moved: recalculate the position and call again. To remove one — ''removeInventoryZone('door')''. This call takes down a zone from the markup too, but only until the next auto update: the html comes from the server again, and the zone is back. Such a zone has to be removed where everything else on the level is removed — with a [[en:authors_main:task_editor:advanced:edit_templates|template on the server]]. A zone from a script **overrides** a zone from the markup with the same code. ==== An Icon of Your Own ==== By default every zone gets one common semi-transparent icon. Your own is set with the ''data-inventory-zone-icon'' attribute in the markup or the ''icon'' field of ''addInventoryZone()'', and its kind does not have to be declared — the engine tells them apart itself: * ''fa-lock'' — a font-awesome glyph; * a path or an address — a picture of your own; * anything else — just a character. ==== Zones That Are Not There Yet ==== Which zones exist usually depends on what the player has already done: an opened crate has no zones, and the machine's slot appears together with the coin. The markup for that is convenient to assemble with [[en:authors_main:task_editor:advanced:edit_templates|templates]], ''{% match bonus_N %}'' — they are computed on the server, so the page source under the player holds only the layers and zones that are visible right now. Templates work the same way in the task script, but the template lines are commented out with a double slash — the engine strips it itself: // {% match bonus_2}:{ // {%= leverdncrowbar}:{ addInventoryZone('leverup', {el: '#quest_room', x: 288, y: 305, r: 45}); // %} // {%= ?}:{ addInventoryZone('leverdn', {el: '#quest_room', x: 315, y: 112, r: 45}); // %} // %} ===== Worth Knowing ===== * **An item's key is a code.** Dots, quotes, and extensions must not go into it. * **Applying is always silent:** nothing appears in the answer form. All the feedback is on the item itself and on the zone. * **The engine reads the verdict out of the "Previous answers" block.** With monitoring switched off on the level the item simply returns to the bag in silence — no green, no red. * **The same wrong code does not go to the server a second time.** The item comes back at once, with the same verdict as last time — no attempt is spent. * **A hidden host is no zone.** A zone on an element inside a collapsed ''
'', on ''display: none'', or on a picture that has not loaded yet will not appear until the host shows itself. The engine recounts on its own: on a window resize, on a picture's load, and at the moment the player picks an item up. * **While an item is in hand, a zone's icon lies over the page** and intercepts the click on whatever is beneath it — including your own button. * **A bonus's synonyms are a state.** A bonus's value in a template is its **last** entered answer, and each new synonym replaces the previous one. That is why the lever goes back and forth and the book is put up and taken down: two synonyms on one bonus instead of two bonuses. * **A bonus description marked ''%hide%''** is not in the page source until it is solved — the chain of applications cannot be peeked at. * A bonus hidden by the engine is printed **without** the answer entered into it. If a script needs that answer, hide the bonuses block with a style rather than with the mark. * The panel lives outside the auto-updating part of the page: somebody else's code or a new hint will not close it and will not take away the selected item. * An open panel pushes the bottom of the page away. Your own block pinned to the bottom will argue with it. What the inventory does not have: **quantity** (an item is either there or not — "three coins" are made of three items or three codes), sorting, and dragging an item onto an item. ===== Examples in the Game ===== * [[https://qeng.org/game.php?jump_to&gid=3493&task_id=83700|Inventory: the room]] — items are found and applied to points on a picture: a crowbar, a lever, a lock, a lid, a coin into a machine. Zones from a script, scene layers from templates. * [[https://qeng.org/game.php?jump_to&gid=3493&task_id=83701|Inventory: the shelf]] — items are not handed out by bonuses at all: what is in the bag and what stands on the shelf is worked out by the script from the entered codes every time. Both levels carry a "How is it done?" section inside them with a walkthrough. ===== The First Version ===== It works the way it always worked. The difference is that the inventory is rendered inside a block the author sets aside, there are no zones, and a selected item has two buttons — the eye and "use". {{ :authors_main:inventory_en.png?800 |The first version's inventory: items arrive for solved bonuses}} {{ :authors_main:inventory_item_en.png?800 |A selected item: the eye shows the picture full size, the tick uses the item}} - In the task text (in **"Source"** mode) — a block where the list should be shown:
Loading inventory...
- In the task script — the call: showInventoryItems('inventory_container'); The second parameter is the same binding of pictures to another game: ''showInventoryItems('inventory_container', 1234)''. Items are given and taken the same way, with ''addInventoryItem()'' and ''removeInventoryItem()'' in a bonus's "Text after solution". The "use" button submits a code equal to the item's key. {{ :authors_main:inventory_use_en.gif |An item arrives for a bonus, and "use" types its code for the player}} Example in the game: [[https://qeng.org/game.php?jump_to&gid=3493&task_id=68367|Inventory]]. ===== See Also ===== * [[en:authors_main:task_editor:advanced:edit_templates|Templates]] — ''{% match bonus_N %}'' for a scene and for zones that depend on the state of the level. * [[en:authors_main:task_editor:advanced:composite_codes|Composite codes]] — the level's final code, assembled from parts. * [[en:authors_main:task_editor:advanced:author_scripts|Interactive elements (scripts)]] — the other functions available in the task script.