Legacy GM Swapping Weapon Objects

Z

zoncxs

Guest
Hello all! I am new to Game maker studio and started my first project 2 weeks ago. I followed all the steps on heartbeast youtube channel (all 32 videos on the beginner tutorial).

Once I got that far I wanted to back step, that is to say undo the edits I made to my game following video 32. This is because that video makes it so that the sprites of the objects swap places, making it look like you are picking up an object (or weapon) without changing anything else.

video 31 shows you how to make an object animate with the player object, that is to say swing a weapon with the weapon being a separate object. This is where my issues come in.

I thought I undid everything to get to that point but for some reason I get a few glitches:

1- the object does not animate when I attack, instead it spawns the object.

2- swapping the objects causes the attack state to spawn a different object. for example, if I try to swap the sword for the axe, it instead swaps it for an enemy object.

3- none of the weapon objects that I place in the room are visible.


Here is what I have that I need to modify (note, the room uses physics):

OBJECTS
obj_player
obj_weapon_animation
obj_sword
obj_stick
obj_axe

SCRIPTS
scr_move_state
scr_attack_state
scr_swap_weapons
scr_animation_hit_frame


the obj_player has the variable "weapon = obj_stick" in its create event and is set to use physics.

the obj_weapon_animation has:
create event
dir = 0;


step event
if (image_angle >= dir-45) {
image_angle -= 15;
} else {
instance_destroy();
}

end step event
if(instance_exists(obj_player)) {
x = obj_player.x;
y = obj_player.y;
} else {
instance_destroy();
}
collision event
with wall and player


obj_sword obj_axe and obj_stick have the obj_weapon_animation as the parent and the correct sprites for them, and are set to use physics.


scr_move_state has:
//swap weapons on ground
if (obj_input.swap_key) {
var nearest_weapon = instance_nearest(x, y, obj_weapon_animation);
if (place_meeting(x, y+4, nearest_weapon)) {
scr_swap_weapons(nearest_weapon);
}
}

scr_attack_state has:
if (scr_animation_hit_frame(2)) {
var attack_animation = instance_create(x, y, weapon);
attack_animation.dir = face*90;
attack_animation.image_angle = (face*90)+45;
}

scr_swap_weapons has:
var new_weapon = argument0;
var temp = weapon;
weapon = new_weapon.sprite_index;
new_weapon.sprite_index = temp;

scr_animation_hit_frame has:
var frame = argument0;
return (image_index >= frame+1 - image_speed) and (image_index < frame+1);



I want to be able to swap the weapon objects because each weapon will have a different hitbox and stats.
 
C

chico_haze

Guest
It looks like you start out with weapon assigned to an object, then when you run scr_swap_weapon() you assign weapon to a sprite_index.

If weapon starts out as an object, it should stay an object.

for scr_swap_weapons you could try just switching the positions of the two objects and assigning your 'weapon' variable to the new weapon so it will travel around with the player.

//scr_swap_weapons(new_weapon)
var new_weapon = argument0;
instance_exists(obj_player.weapon){​
// Put the current weapon on the ground
obj_player.weapon.x = new_weapon.x;
obj_player.weapon.y = new_weapon.y;​
}
// Pick up the new weapon
obj_player.weapon = new_weapon;
obj_player.weapon.x = obj_player.x;
obj_player.weapon.y = obj_player.y;


Then update the weapon x,y coords from the player object, not the weapon object. So in the obj_player step you have;
if(instance_exists(weapon)){
weapon.x = x;
weapon.y = y;​
}​
 
Z

zoncxs

Guest
Sadly it still does not work. The weapon the player has is not visible unless you attack (think Legend of Zelda for the nes).

Rather than use sprite_index, since that is not what I want to do as you mentioned, I am using this:

scr_swap_weapons
var new_weapon = argument0;
var temp = weapon;
weapon = new_weapon;
new_weapon = temp;


I thought that should work but now I have the following issue:
ERROR in
action number 1
of Step Event0
for object obj_player:

Creating instance for non-existing object: 100017
at gml_Script_scr_attack_state (line 6) - var attack_animation = instance_create(x, y, weapon);
############################################################################################
--------------------------------------------------------------------------------------------
stack frame is
gml_Script_scr_attack_state (line 6)
called from - gml_Object_obj_player_StepNormalEvent_1 (line 4) - script_execute (state);


This only happens after I try to swap with a weapon object on the ground. It appears like nothing got swapped but when I attack this error happens.

Also note, I am using physics, with it on. If I turn off physics for the weapons I can attack and the weapons animate without a problem, except that all the weapons on the ground are invisible and I can not interact with them.


Lets break it down to simplify it. I want to press a button and create an object. I then want to be able to change what object I create by using a different button and picking up a different object, this replaces the picked up object with the object I had. I would then be able to create the newly picked up object. Once I got that part worked out I could then move on.
 
Z

zoncxs

Guest
You know what? I am going to stop trying this effect, it is needless when I will have an inventory system. instead I will need to be able to pick up the object, have it destroyed, but in the process store its id in the players inventory. I am working on making an inventory system now and will update if it works.
 
Z

zoncxs

Guest
I got an inventory menu working, I have it set up like my pause menu, which I need to fix (I have a start up menu, in it you can still hit pause which messes up loading a previous game, which I need to fix...) I am still keeping the swapping part, but instead of swapping it deletes the object and will store its id in an array in the inventory menu...now my problem is that my menus don't work correctly.

When I am on the main menu screen there are only 2 options: new game, and exit. Both work.

While in game you can press the "pause_key" (I have it set for "P" or the start button on a controller) and it goes to the pause menu which only has 2 choices, return or exit.. Return send you back to the main menu for some reason...
 
Z

zoncxs

Guest
Here is my Pause code:

RETURN is a Macro that is equal to 0.
Obj_input calls the scr_get_input which has all the info for what each button variable is assigned.
pause_key is set as "gamepad_button_check_pressed (0, gp_start);" and "keyboard_check_pressed(ord("P"));"
Inventory_key is set up in the same fashion, using "I" or Select button.

Inside my script Move State:
// pause the game
if (obj_input.pause_key) {
if (room != rm_pause) {
if (instance_exists(obj_player)) {
obj_player.persistent = false;
}
previous_room = room;
room_persistent = true;
room_goto(rm_pause);
} else {
room_goto(previous_room);
}
obj_input.pause_key = false;
}

// inventory menu
if (obj_input.inventory_key) {
if (room != rm_inventory) {
if (instance_exists(obj_player)) {
obj_player.persistent = false;
}
previous_room = room;
room_persistent = true;
room_goto(rm_inventory);
} else {
room_goto(previous_room);
}
obj_input.pause_key = false;
}


Pause Menu Object:
Create Event:
/// initialize the menu
title = "Game Paused";

option[0] = "Return";
option[1] = "Exit";

//Menu index
menu_index = 0;

Alarm 0:
Alarm for the menu

Step Event:
/// control the menu
// move down the menu
if (alarm[0] <= 0) {
if (obj_input.down_key or obj_input.yaxis > .5) {
if (menu_index < array_length_1d(option)-1) {
menu_index++;
} else {
menu_index = 0;
}
alarm[0] = room_speed/6;
}

// move up the menu
if (obj_input.up_key or obj_input.yaxis < -.5) {
if (menu_index >0) {
menu_index--;
} else {
menu_index = array_length_1d(option)-1;
}
alarm[0] = room_speed/6;
}

// choose an option
if (obj_input.action_key) {
switch (menu_index) {
case 0:
obj_player_stats.room_start_action = RETURN;
room_goto(obj_player_stats.previous_room);
break;

case 1:
game_end();
break;

default:
break;
}
obj_input.action_key = false;
}
}

Draw GUI:
/// draw the menu
var xx = display_get_gui_width()/2;
var yy = display_get_gui_height()/2;
draw_set_halign(fa_center);
draw_text(xx, yy-64, title);

for (var i=0; i<=array_length_1d(option)-1; i++) {
draw_set_color(c_gray);
if (i == menu_index) {
draw_set_color(c_white);
}
draw_text(xx, yy+(i*32), option);
}
draw_set_color(c_white);
draw_set_halign(fa_left);




START UP MENU OBJECT:
Create Event:
/// initialize the menu
title = "Project Z";

option[0] = "New Game";
option[1] = "Quit";

//Menu index
menu_index = 0;


if (room == rm_start_menu) {
if (instance_exists(obj_player)) {
obj_player.persistent = false;
}
}

Alarm 0:
Menu Alarm

Step Event:
/// control the menu

//move down the menu
if (alarm[0] <= 0) {
if (obj_input.down_key or obj_input.yaxis > .5) {
if (menu_index < array_length_1d(option)-1) {
menu_index++;
} else {
menu_index = 0;
}
alarm[0] = room_speed/6;
}

// move up the menu
if (obj_input.up_key or obj_input.yaxis < -.5) {
if (menu_index >0) {
menu_index--;
} else {
menu_index = array_length_1d(option)-1;
}
alarm[0] = room_speed/6;
}

//choose an option
if (obj_input.action_key) {
switch (menu_index) {
case 0:
obj_player_stats.room_start_action = NEW_ROOM;
room_goto(rm_1);
break;

case 1:
game_end();
break;

default:
break;
}
obj_input.action_key = false;
}
}

Draw GUI:
/// draw the menu
var xx = display_get_gui_width()/2;
var yy = display_get_gui_height()/2;
draw_set_halign(fa_center);
draw_text(xx, yy-64, title);

for (var i=0; i<=array_length_1d(option)-1; i++) {
draw_set_color(c_gray);
if (i == menu_index) {
draw_set_color(c_white);
}
draw_text(xx, yy+(i*32), option);
}
draw_set_color(c_white);
draw_set_halign(fa_left);


PLAYER STATS OBJECT:
Create Event:
//get the player's xstart and ystart
if (instance_exists(obj_player)) {
player_xstart = obj_player.x;
player_ystart = obj_player.y;
} else {
player_xstart = 0;
player_ystart = 0;
}


// save the previous room
previous_room = room;


room_start_action = NEW_ROOM;

Room Start Event:
///remember the player's start position

if (room == rm_pause or rm_inventory) exit;

switch (room_start_action) {
case RETURN:
break;

case NEW_ROOM:
default:
if (instance_exists(obj_player)) {
player_xstart = obj_player.x;
player_ystart = obj_player.y;
}
break;
}
room_persistent = false;
room_start_action = NEW_ROOM;
 
Z

zoncxs

Guest
My inventory menu has changed, instead I have it appear over the screen like Dark Souls or Phantasy Star Online. I disabled my pause menu until I can figure out what went wrong, I will start that over from scratch most likely. So now my next problem is that my inventory menu does not save. I have it as follows:

// inventory menu
if (obj_input.inventory_key) {
if !instance_exists(obj_inventory_menu){
instance_create(0,0,obj_inventory_menu);
} else if (instance_deactivate_object(obj_inventory_menu)){
instance_activate_object(obj_inventory_menu);
} else {
instance_deactivate_object(obj_inventory_menu);
}
obj_input.inventory_key = false;
}

My thought process was that first if the inventory object does not exists make it. Then if it is not active, make it active, lastly if it is active then deactivate it. I was also thinking about simply turning its Visible on and off, but that would not stop the player from actually using the inventory, you just wouldn't be able to see what you are doing. What would be a way to store the data in the inventory? so that you can toggle the view.
 
Top