GameMaker Dropping Inventory to Game World

T

Tyler Ratliff

Guest
Ill try to keep this short and simple as I am relatively new and eager to learn. For reference, I have built my inventory based on GM Wolf's design on YouTube. I am customizing and attempting to improve it for a game I am building as well as to understand GML a little bit better. I have everything fully functional except getting the items to appear in the game world once they are dropped from the inventory. I can post any code needed and will try to provide useful resources. The player clicks on an item with the middle mouse button and the inventory goes down by one. I am just not sure what array or design I need to use/write to convert the inventory items to a dropped object item in the game world. The first code section here is the inventories CREATE event which stores the item information (could I use these to reference the dropped item?):

Code:
///Define Items and Items Sprites

enum items
{
    health_potion,        ///ID 0
    bones,              ///ID 1
    feathers,           ///ID 2
    raw_chicken         ///iD 3
}

    sprite[items.health_potion] = spr_health_potion;   
    sprite[items.bones] = spr_bones;
    sprite[items.feathers] = spr_feathers;
    sprite[items.raw_chicken] = spr_raw_chicken;
    
    script[items.health_potion] = scr_use_health_potion;
    script[items.bones] = noone;
    script[items.feathers] = noone;
    script[items.raw_chicken] = noone;
This is also listed under Create and serves the purpose of having items in the inventory on game start:
Code:
for(var i = 0; i < slot_number; i++)
{
    slot[i]=noone;
    slot_n[i] = 0;
}

slot[10]=items.health_potion;
This is from the global middle mouse button pressed (drops one of the item)
Code:
if (slot[slot_clicked] != noone) {       
    slot[slot_clicked] = dropping;
    scr_drop_item(slot_clicked, 1)
    }
}
and its referenced script:
Code:
///scr_remove_item(slot, number);
slot_n[argument0] -= argument1;
if slot_n[argument0] = 0
{
    slot[argument0] = noone;
} else {
    instance_create_layer(obj_player.x+30, obj_player.y+30, obj_inventory_drop)
    
}
slot_n is where the amount of the item is stored.

Am I able to use my existing codes to be able to drop the items into the overworld? Or do I have to set more things up? If so, what direction should I look into? I am new but willing to research and learn. I can also again post any or all of the code I am using if this would not be enough! Thank you!
 

samspade

Member
Yes. It also seems like your existing code already does that, or perhaps should with a little tweaking. The code seems pretty straight forward, though there are a few things I don't understand:
  • You have two slot arrays. slot, and slot_n. What are each of these supposed to be and why is only slot assigned a health potion?
  • What is slot[slot_clicked] = dropping supposed to do? Maybe a better way to ask it is what is the value of dropping, and why are you replacing the current value of slot with it?
Then there are a few things that seem slightly wrong in the code. For example, it seems like you should reduce the value of slot_n which appears to stand for the amount of an item in a slot, after you drop, not before as if you do it before then if there is only one item, it will reach 0 before doing anything.

Finally, to accomplish what you want it seems like all you really need to do is the following:

Code:
///scr_remove_item(slot, number);
if slot_n[argument0] = 0
{
   slot[argument0] = noone;
} else {
   var new_item_drop = instance_create_layer(obj_player.x+30, obj_player.y+30, obj_inventory_drop)
   with (new_item_drop) 
   {
     //set values of the item here. Seems like given your code it should look something like this:
     sprite_index = other.sprite[slot[argument0]];
     script = other.script[slot[argument0]];
   }
}
slot_n[argument0] -= argument1;
The above will only work if you can never drop more than one item at a time. If you can drop more than one, you'd want to wrap it in some type of for loop.

As to setting the values, I guessed at what it should look like, but you essentially just need some way of determining what item was dropped and then using that to set the values of the newly created inventory drop.
 
T

Tyler Ratliff

Guest
Thank you so much for your reply and for helping me start to understand my own problem! The dropping variable is a leftover piece I had put in when trying to solve this. It has been removed and is now irrelevant.
slot is the item that is in the slot and slot_n is the amount of the item in the slot so you are correct! I'm gonna go ahead and try out that modified script to see if it can successfully pull something into the world. :)
 
T

Tyler Ratliff

Guest
Code:
___________________________________________
############################################################################################
FATAL ERROR in
action number 1
of Mouse Event for Glob Middle Pressed
for object obj_inventory:

Variable obj_inventory_drop.slot(100025, 9) not set before reading it.
 at gml_Script_scr_drop_item (line 14) -      sprite_index = other.sprite[slot[argument0]];
############################################################################################
--------------------------------------------------------------------------------------------
stack frame is
gml_Script_scr_drop_item (line 14)
called from - gml_Object_obj_inventory_Mouse_55 (line 17) -        scr_drop_item(slot_clicked, 1)
new scr_drop_item
Code:
///scr_remove_item(slot, number);
if slot_n[argument0] = 0
{
   slot[argument0] = noone;
} else {
   var new_item_drop = instance_create_layer(obj_player.x+30, obj_player.y+30, "Instances", obj_inventory_drop)
   with (new_item_drop)
   {
     //set values of the item here. Seems like given your code it should look something like this:
     sprite_index = other.sprite[slot[argument0]];
     script = other.script[slot[argument0]];
   }
}
slot_n[argument0] -= argument1;


Middle button click for inv: (most of the top section here is just determining mouse position relative to gui and calculating the slot being clicked)
Code:
var gui_mouse_x = device_mouse_x_to_gui(0);
var gui_mouse_y = device_mouse_y_to_gui(0);

if (mouse_slot == noone) and (gui_mouse_x > x_off)  and (gui_mouse_x < x_off + inventory_width * 64) and (gui_mouse_y > y_off) and (gui_mouse_y < y_off + (slot_number / inventory_width) * 64)

{
var xx = (gui_mouse_x - x_off) div 64; //Number after div is width of the slot
var yy = (gui_mouse_y - y_off) div 64;

var slot_clicked = xx + (yy * 4);    ///4 may have to be changed to number of slot columns

if (slot[slot_clicked] != noone) {       
    scr_drop_item(slot_clicked, 1)
    }
}
 

samspade

Member
The error is because I should have put other.slot as slot is a variable of the creating instance, not new_item_drop. Even if you fix that though you'll probably have to change some other things as well. I'd be surprised if my guess worked as written.
 
D

Deleted member 16767

Guest
instance_create_layer(obj_player.x+30, obj_player.y+30, obj_inventory_drop)
Hmm. Maybe specify on which layer it will appear on and make it always on top?
 
T

Tyler Ratliff

Guest
Thanks for the replies, guys! Spent a few more hours on it and all I have to show is a hackjob that somewhat represents the example script samspade sent. I am defeated for the time being. :(
 

Rob

Member
I find it easier to plan the logic out when I'm struggling.

The logic you want is:
  • Check for the player input
  • If they're pressing the drop key do this:
  • Check what item is being dropped
  • Create an item instance underneath the player ( making sure you fill in the function properly because the instance_create_layer you posted is missing at least one variable
  • Minus one from the item stack
  • Feel happy you fixed the problem.
I'm sure you already figured the logic out but your implementation is off. If you follow the advice of the previous posters then I'm pretty sure it will work.

I also have a video that covers everything you're trying to do with the added bonus of allowing the item to be picked up again.

 
Top