Weapon change system

skofrant

Member
Hi all,
I have a request, can someone help me in preparing such a template of the weapon change system?

already describes what I mean ..
I have such a hero code below ... my hero after pressing the action button in this case X. shoots a bullet.
And that's ok. this ball has an unlimited number of bullet.

I would like to be able to choose 4 more weapons besides the primary weapon.


the only condition is that I need to find a given weapon on the board ... suppose there is a weapon on the board, I pick it up and automatically add that weapon to the hero with any amount of ammo which is limited. This weapon icon will automatically be added to the game HUD with the ammo sprites of whatever weapon it has.

The choice of weapons, for example, would be under the button of one of the keys 1,2,3,4 and 5


code below my hero step


GML:
//Normal movement
if ladder == false
{
if key_check_pressed(key.jump)  && inAir == false
{
vspd = -10-sign;
jumpStr = 5;


if key_check(key.down) && place_meeting(x,y+1,par_solid_ghost)
{
y += 4;
vspd = 0;
jumpStr = 0;
jumpTimes = 0;
}
}

else if key_check(key.jump) && jumpStr> 0
{
audio_play_sound(music_jump, 1, false);   //jump music
vspd -= 2+sign;
jumpStr--;
}
else
{
if key_check_released(key.jump) && jumpStr > 2
{
vspd += 2+sign;
}

jumpStr = 0;
}


///the code responsible for the hero's shot
if keyboard_check_pressed(ord('X')) && attClock == false && instance_number(obj_bullet)< 3 {
attClock = 30;   
curAttack= 1;
with instance_create(x,y,par_attack) {
     sprite_index = mask_player_attack;
     image_xscale = other.image_xscale;

{
    var box, ID;
    if image_xscale == -1
        box = bbox_left;
    else
        box = bbox_right;
      
    ID = instance_create(box+image_xscale*49, y-17, obj_bullet);
    ID.hspeed = image_xscale * 15;
    owner = par_player;
audio_play_sound(shot_sounds, 1, false); //shot sounds
}     
}
  }



//ladder

if  place_meeting(x,y,par_climbable) && place_meeting(x,y-32,par_climbable) && place_meeting(x,y+5,par_climbable) && (key_check(key.up) || key_check(key.down))
{
ladder = true;
vspd = 0;
hspd = 0;
}
}



//climbing

if ladder == true
{
var __hsign = key_check(key.right)-key_check(key.left);
var __vsign = key_check(key.down)-key_check(key.up);

hspd = min(max(hspd+__hsign,-2),2);
vspd = min(max(vspd+__vsign*2,-4),4);

if __vsign == -1 && !place_meeting(x,y-32,par_climbable)
{
ladder = false;
vspd = -10;
}

if __hsign != 0
{
image_xscale = __hsign;
}

if !place_meeting(x,y,par_climbable) || !place_meeting(x,y+32,par_climbable)
{
ladder = false;
}
}

////Ghost platform the ladder inherits from
////Normal movement
if ladder == false {
     if key_check(key.down) && inAir == false{

   ////Step down
   if key_check(key.down) && place_meeting(x,y+1,obj_par_ladder_solid_ghost){


    y += 4; // Changing this value causes the hero to grab the top edge of the ladder after pressing the down button, but the screen will jump for a split second
    vspd = 0;

    jumpStr = 0;
    jumpTimes = 0;

}
}

////Hero can shoot from the ladder
if keyboard_check_pressed(ord('X')) && ladder==true && attClock == false  && place_meeting(x,y,par_climbable)   &&  instance_number(obj_bullet) < 3
{
attClock = 30;   
curAttack = 1;
with instance_create(x,y,par_attack) {

     sprite_index = spr_player_shoot_ladder;
    
     image_xscale = other.image_xscale;

{
    var box, ID;
    if image_xscale == -1
        box = bbox_left;
    else
        box = bbox_right;
        
    ID = instance_create(box+image_xscale*-10, y-17, obj_bullet);
        ID.hspeed = image_xscale * 15;
        owner = par_player;
audio_play_sound(shot_sounds, 1, false); //shot sounds
}     
 }
  }






   }

My hero's attack collision sprite is the hand from which the hero shoots, so I don't need to change the hero's sprite but create a new one corresponding to the weapon that will be displayed on the palm as in the code above.

In the picture below I described it in the form of a drawing in more detail.

Thank you


 

Rob

Member
I think this is a perfect time to use an array or data structure.

GML:
//Create event of a CONTROLLER object - make it persistent so the data can be used in multiple rooms

//This enumerator is just to make the code more readable and so we can use "have_found" and "ammo" in place of "0" and "1"
enum e_weapons{
   have_found,
   ammo,
}

var total_weapons = 5;

for (var i = 0; i < total_weapons; i ++){
    //For ALL the weapon slots, say the player has not yet found it and set ammo to 0
    global.weapons[e_weapons.have_found, i] = false;
    global.weapons[e_weapons.ammo, i] = 0;
}

//Give first weapon and 100 rounds to player
global.weapons[e_weapons.have_found, 0] = true;
global.weapons[e_weapons.ammo, 0] = 100;
This might mean making other changes to your code as well, but making this transition will mean that in the future you'll actually need less code for this kind of thing as one code block can be run for ALL weapon types.

When you want to display the weapons, you use a for loop to check whether the entry for "have_found" is true or false. If true, display it, if false, do not. E.G:


GML:
//draw_gui event
var box_width = sprite_get_width(spr_weapon_box); //how wide is each box that will display a weapon?

for (var i = 0; i < total_weapons; i ++){
   draw_x = i * box_width;
   draw_y = 0; //Assuming sprites origin is drawn from top left

   //if you have each weapon image in the same sprite, you can draw them all just using "i"
   if ( global.weapons[e_weapons.have_found, i] == true ) draw_sprite(spr_weapon_box, i, draw_x, draw_y);
}
 
Last edited:

skofrant

Member
Thank you very much ;-)

I understand that I have to add to the collision with the player, for example, a weapon object one of the five where, when I get it here , will I see its sprite at the top on the HUD bar?
could you yet help me with this? e.g. I find one of the five weapons and I get it, it has, for example, 10 ammunition and the hud bar will display this weapon as a sprite with the amount of ammunition.??


GML:
Variable obj_game_controller.total_weapons(100070, -2147483648) not set before reading it.
 at gml_Object_obj_game_controller_DrawGUI_1 (line 50) - for (var i = 0; i < total_weapons; i ++){ ############################################################################################
 
Last edited:

skofrant

Member
GML:
//Create event of a CONTROLLER object - make it persistent so the data can be used in multiple rooms

//This enumerator is just to make the code more readable and so we can use "have_found" and "ammo" in place of "0" and "1"
enum e_weapons{
   have_found,
   ammo,
}

enum e_weapons2{
   have_found,
   ammo,
}

enum e_weapons3{
   have_found,
   ammo,
}

enum e_weapons4{
   have_found,
   ammo,
}

enum e_weapons5{
   have_found,
   ammo,
}


var total_weapons = 5;

for (var i = 0; i < total_weapons; i ++){
    //For ALL the weapon slots, say the player has not yet found it and set ammo to 0
    global.weapons[e_weapons.have_found, i] = false;
    global.weapons[e_weapons.ammo, i] = 0;
    global.weapons[e_weapons2.have_found, i] = false;
    global.weapons[e_weapons2.ammo, i] = 0;
    global.weapons[e_weapons3.have_found, i] = false;
    global.weapons[e_weapons3.ammo, i] = 0;
    global.weapons[e_weapons4.have_found, i] = false;
    global.weapons[e_weapons4.ammo, i] = 0;
    global.weapons[e_weapons5.have_found, i] = false;
    global.weapons[e_weapons5.ammo, i] = 0;




}

//Give first weapon and 100 rounds to player
global.weapons[e_weapons.have_found, 0] = true;
global.weapons[e_weapons.ammo, 0] = 100

global.weapons[e_weapons2.have_found, 0] = true;
global.weapons[e_weapons2.ammo, 0] = 30;

global.weapons[e_weapons3.have_found, 0] = true;
global.weapons[e_weapons3.ammo, 0] = 20;

global.weapons[e_weapons4.have_found, 0] = true;
global.weapons[e_weapons4.ammo, 0] = 10;

global.weapons[e_weapons5.have_found, 0] = true;
global.weapons[e_weapons5.ammo, 0] = 5;


Draw gui


GML:
//draw_gui event
var box_width = sprite_get_width(spr_weapon_box); //how wide is each box that will display a weapon?

for (var i = 0; i < total_weapons; i ++){
   draw_x = i * box_width;
   draw_y = 0; //Assuming sprites origin is drawn from top left

   //if you have each weapon image in the same sprite, you can draw them all just using "i"
   if ( global.weapons [e_weapons.have_found, i] == true ) draw_sprite(spr_weapon_box, i, draw_x, draw_y);
   if ( global.weapons2[e_weapons.have_found, i] == true ) draw_sprite(spr_weapon_box2, i, draw_x, draw_y);
   if ( global.weapons3[e_weapons.have_found, i] == true ) draw_sprite(spr_weapon_box3, i, draw_x, draw_y);
   if ( global.weapons4[e_weapons.have_found, i] == true ) draw_sprite(spr_weapon_box4, i, draw_x, draw_y);
   if ( global.weapons5[e_weapons.have_found, i] == true ) draw_sprite(spr_weapon_box5, i, draw_x, draw_y);



}
 
Last edited:

woods

Member
//Give first weapon and 100 rounds to player
global.weapons[e_weapons.have_found, 0] = true;
global.weapons[e_weapons.ammo, 0] = 100;
//Give second weapon and 100 rounds to player ?
global.weapons[e_weapons.have_found, 1] = true;
global.weapons[e_weapons.ammo, 1] = 100;

//Give third weapon and 100 rounds to player ?
global.weapons[e_weapons.have_found, 2] = true;
global.weapons[e_weapons.ammo, 2] = 100;
 

Rob

Member
@skofrant you only need one enumerator, because each of the 2 stats will be used by each weapon entry

IF you want the player to switch between the weapons, you can have a variable called current_weapon, which will hold a value of between 0 and (total_weapons - 1)
Then you can do stuff like:

GML:
//Reduce the current weapon's ammo by 1
global.weapons[e_weapons.ammo, current_weapon] -= 1;
 

skofrant

Member
Thanx
i Iunderstand i need one enumerator



I already have five types of weapons defined Weapons Type with different damage strength and now yes


the player finds, for example, weapon number 3 in the game

In the object of the weapon number 3 which I have to define something in some event code?
In object, e.g. weapon 3. I seting collisions with the player. When the player takes it, he will get this weapon and the amount of assigned ammunition which is limited?

Now in this collision with the player I have to
When I want to display the weapons, I use a for loop to check whether the entry for "have_found" is true or false?
After pressing the button on the keyboard, e.g. 1 selects and displays a standard weapon with no ammunition limit, i.e. Obj_bullet (the one I have above in my hero's code)
After pressing the 2 key, the number two weapon is displayed with the amount of ammunition I have, provided that the player has this weapon and found it on the board
And so on and so forth...




collision of the player with the weapon No. 3

GML:
global.weapons[e_weapons.have_found, 3] = true;
global.weapons[e_weapons.ammo, 3] = 20;
global.weapons[e_weapons.ammo, current_weapon] -= 1;

I don't know if I understand it well
if not, what exactly do I have to enter, for example, in weapon object numer 3 and in the player's collision with weapon object numer 3?


GML:
//Create event of a CONTROLLER object - make it persistent so the data can be used in multiple rooms

//This enumerator is just to make the code more readable and so we can use "have_found" and "ammo" in place of "0" and "1"
enum e_weapons{
   have_found,
   ammo,
}



var total_weapons = 5;

for (var i = 0; i < total_weapons; i ++){
    //For ALL the weapon slots, say the player has not yet found it and set ammo to 0
    global.weapons[e_weapons.have_found, 1] = false;
    global.weapons[e_weapons.ammo, 1] = 0;
    global.weapons[e_weapons.have_found, 2] = false;
    global.weapons[e_weapons.ammo, 2] = 0;
    global.weapons[e_weapons.have_found, 3] = false;
    global.weapons[e_weapons.ammo, 3] = 0;
    global.weapons[e_weapons.have_found, 4] = false;
    global.weapons[e_weapons.ammo, 4] = 0;
    global.weapons[e_weapons.have_found, 5] = false;
    global.weapons[e_weapons.ammo, 5] = 0;




}

//Give first weapon and 100 rounds to player
global.weapons[e_weapons.have_found, 1] = true;
global.weapons[e_weapons.ammo, 1] = 100

global.weapons[e_weapons.have_found, 2] = true;
global.weapons[e_weapons.ammo, 2] = 30;

global.weapons[e_weapons.have_found, 3] = true;
global.weapons[e_weapons.ammo, 3] = 20;

global.weapons[e_weapons.have_found,4] = true;
global.weapons[e_weapons.ammo, 4] = 10;

global.weapons[e_weapons.have_found, 5] = true;
global.weapons[e_weapons.ammo, 5] = 5;

GML:
//draw_gui event
var box_width = sprite_get_width(spr_weapon_box); //how wide is each box that will display a weapon?

for (var i = 0; i < total_weapons; i ++){
   draw_x = i * box_width;
   draw_y = 0; //Assuming sprites origin is drawn from top left

   //if you have each weapon image in the same sprite, you can draw them all just using "i"
   if ( global.weapons[e_weapons.have_found, 1] == true ) draw_sprite(spr_weapon_box,  1, draw_x, draw_y);
   if ( global.weapons[e_weapons.have_found, 2] == true ) draw_sprite(spr_weapon_box2, 2, draw_x, draw_y);
   if ( global.weapons[e_weapons.have_found, 3] == true ) draw_sprite(spr_weapon_box3, 3, draw_x, draw_y);
   if ( global.weapons[e_weapons.have_found, 4] == true ) draw_sprite(spr_weapon_box4, 4, draw_x, draw_y);
   if ( global.weapons[e_weapons.have_found, 5] == true ) draw_sprite(spr_weapon_box5, 5, draw_x, draw_y);



}

And I wonder why it shows the error

GML:
Variable obj_game_controller.total_weapons(100070, -2147483648) not set before reading it.
at gml_Object_obj_game_controller_DrawGUI_1 (line 52) - for (var i = 0; i < total_weapons; i ++){ ############################################################################################
--------------------------------------------------------------------------------------------
 
Last edited:

TailBit

Member
You got "var" in front of total_weapons in the create event, meaning the variable will no longer exist after that event.

Just remove the "var" part
 

skofrant

Member
Ok I deleted var in create with total_weapons no longer error pops up. Thanks wrong earlier I got it.
 
Last edited:

woods

Member
dont arrays and lists and such start with number zero instead of one?

so a list or array of 5 things would start at 0 and go to 4...
not start at 1 and go to 5

wouldnt that throw an error?
 

skofrant

Member
I don't know because a friend above wrote this code for me ... I'm trying to analyze it
but if I have 5 types of weapons then total_weapons equals 5
 

FrostyCat

Redemption Seeker
Then your friend is a muggle. Only muggles start counting in arrays from 1.

Get rid of the var in total_weapons. Set up the second index of your 2D array to count from 0-4 instead of 1-5. Then it will work with the zero-indexed code you were given later.
 

TailBit

Member
Your loops should take advantage of the "i" variable that increases, both to set the default values of the array, and drawing if you put all the sprites of the spr_weapon_boxes as subimages of spr_weapon_box instead of 1 sprite for each..

I also use the index as the first value in the array:
array[index,n]
because you can give the 2nd value different lengths for each index, but not the other way around .. but .. you can ignore that, as you array will be fully filled in both directions so there will be no wasted data anyway.

GML:
enum e_weapons{
   have_found,
   ammo,
}

total_weapons = 5;

for (var i = 0; i < total_weapons; i ++){
    //For ALL the weapon slots, say the player has not yet found it and set ammo to 0
    global.weapons[e_weapons.have_found, i] = false;
    global.weapons[e_weapons.ammo, i] = 0;
}

//Give first weapon and 100 rounds to player
global.weapons[e_weapons.have_found, 0] = true;
global.weapons[e_weapons.ammo, 0] = 100

global.weapons[e_weapons.have_found, 1] = true;
global.weapons[e_weapons.ammo, 1] = 30;

global.weapons[e_weapons.have_found, 2] = true;
global.weapons[e_weapons.ammo, 2] = 20;

global.weapons[e_weapons.have_found,3] = true;
global.weapons[e_weapons.ammo, 3] = 10;

global.weapons[e_weapons.have_found, 4] = true;
global.weapons[e_weapons.ammo, 4] = 5;

GML:
//draw_gui event
var box_width = sprite_get_width(spr_weapon_box); //how wide is each box that will display a weapon?

for (var i = 0; i < total_weapons; i ++){
   draw_x = i * box_width;
   draw_y = 0; //Assuming sprites origin is drawn from top left

   //if you have each weapon image in the same sprite, you can draw them all just using "i"
   if ( global.weapons[e_weapons.have_found, i] == true ) draw_sprite(spr_weapon_box,  i, draw_x, draw_y);
}
 

skofrant

Member
A friend wanted to help. I appreciate any help, there are no infallible people.

Could any of you fold this for me? so that it would work.

Exactly what I need ..

I have 5 types of weapons

a) obj_bullet this basic unlimited number of bullets,
b) second weapon obj_shotgun with a limited number of bullets,
c) a third obj_magma weapon with a limited number of bullets,
d) fourth weapon obj_laser with a limited number of bullet,
e) fifth weapon obj_crossbow with a limited number of bullets,



I wish my main weapon (obj_bullet) was displayed in the hud bar at the top of the screen.
And the next weapons (2,3,4,5)ones only when I find them on the game board.
And displayed in that one sprite with the assigned amount of ammo that has a limit.

Under the keyboard, for example, Buttons 1,2,3,4,5 assigned weapons; or under the "S" button assign a weapon selection

What do I need to define in these five weapons event objects?
What must be defined in the collision event of the player with weapons?
The hero finds a weapon and assigns it to himself and then adds it to the hud bar along with the amount of ammunition
 
Last edited:

TailBit

Member
I would recommend making another enum for each type of gun:
Code:
enum e_gun { basic, shotgun, magma, laser, crossbow }
that way e_gun.basic to e_gun.crossbow will give you the numbers 0 to 4 without you having trouble remember which is which ..

Atm all the weapons are set to be visible right from the beginning, so you don't want that, just remove:
Code:
//Give first weapon and 100 rounds to player
global.weapons[e_weapons.have_found, 0] = true;
global.weapons[e_weapons.ammo, 0] = 100

global.weapons[e_weapons.have_found, 1] = true;
global.weapons[e_weapons.ammo, 1] = 30;

global.weapons[e_weapons.have_found, 2] = true;
global.weapons[e_weapons.ammo, 2] = 20;

global.weapons[e_weapons.have_found,3] = true;
global.weapons[e_weapons.ammo, 3] = 10;

global.weapons[e_weapons.have_found, 4] = true;
global.weapons[e_weapons.ammo, 4] = 5;
you only want the first weapon:
Code:
global.weapons[e_weapons.have_found, e_gun.basic] = true;
global.weapons[e_weapons.ammo, e_gun.basic] = -1;
here I also set ammo to -1 as a indicator that it is unlimited.

you should also have a variable to tell which weapon that is selected, like: current_weapon

so .. in your obj_magma create event:
Code:
gun = e_gun.magma;
collision event:
Code:
global.weapons[e_weapons.have_found, gun] = true;
global.weapons[e_weapons.ammo, gun] += 30;
so when you press the fire button then you can do something like:
lmb event:
Code:
// if ammo is -1 (infinite) or greater then 0 .. then fire
if (global.weapons[e_weapons.ammo,current_weapon] == -1)
|| (global.weapons[e_weapons.ammo,current_weapon] > 0){
   
    var dir = point_direction(x,y,mouse_x,mouse_y);
   
    // you can give each weapon a number telling how many bullets it should shoot at once, or what dmg the bullet should have, sprite, aim, recoil, lost of stuff to add to your "e_weapons"  .. the laser might have to be its separate thing
    repeat(1){
        var ins = instance_create_layer(x+lengthdir_x(10,dir),y+lengthdir_y(10,dir),obj_bullet,"Instances"); // using lengthdir to position the bullet a bit away from the body
        ins.dmg = 4;
        ins.direction = dir + irandom_range(-10,10);
    }
    
    // if ammo isn't infinite .. lower it
    if (global.weapons[e_weapons.ammo,current_weapon] != -1) global.weapons[e_weapons.ammo,current_weapon] -= 1;

   // then set weapon cooldown .. and you should also check for that before you are allowed to fire again
}

pressing the buttons 1-5
Code:
for(var i=0;i<weapons_total;i++)
    if keyboard_check_pressed(ord("1")+i)
        if global.weapons[e_weapons.have_found,i]
            current_weapon = i;
or under the "S" button assign a weapon selection.
let the weapon wheel be for now :3 .. it's not that hard .. you pretty much have to sum up the weapons you have found and then split the circle in that many slices, then check what slice you are within when you click again .. but, just let that be for now .. you should focus on understanding the array system instead.

The hero finds a weapon and assigns it to himself and then adds it to the hud bar along with the amount of ammunition
this sounds more like a inventory system
 

skofrant

Member
Thank you very much for your help and description. I will analyze the code line by line.

I must add this enum below because I see that you made a separate one for the weapon ...


GML:
enum e_weapons{
   have_found,
   ammo,
}

total_weapons = 5;

for (var i = 0; i < total_weapons; i ++){
    //For ALL the weapon slots, say the player has not yet found it and set ammo to 0
    global.weapons[e_weapons.have_found, i] = false;
    global.weapons[e_weapons.ammo, i] = 0;
}

Another question about draw gui

Currently, this cheat below shows me some weapon sprites.
I would like him to show me a basic weapon at the beginning and if I find one of the 4 weapons, he showed me another weapon in one sprite, etc ...

GML:
//draw_gui event
var box_width = sprite_get_width(spr_weapon_box); //how wide is each box that will display a weapon?

for (var i = 0; i < total_weapons; i ++){
   draw_x = i * box_width;
   draw_y = 0; //Assuming sprites origin is drawn from top left

   //if you have each weapon image in the same sprite, you can draw them all just using "i"
   if ( global.weapons[e_weapons.have_found, i] == true ) draw_sprite(spr_weapon_box,  i, draw_x, draw_y);
}
 

TailBit

Member
Currently, this cheat below shows me some weapon sprites.
I would like him to show me a basic weapon at the beginning and if I find one of the 4 weapons, he showed me another weapon in one sprite, etc ...
The code should already be doing that..

It should draw each weapon IF have_found have been set to true for that weapon

you just need to fix it so that spr_weapon_box contain a subimage of each weapon in the order you want them

in the beginning you only want to set the first gun to true:

GML:
global.weapons[e_weapons.have_found, e_gun.basic] = true;
global.weapons[e_weapons.ammo, e_gun.basic] = -1;
not the other weapons.. then it should only show the first weapon
 

skofrant

Member
Thank you again for your help ... I will test it tomorrow.

This is what the code in the create event should look like? twice an enum?

obj_game_controller (persistent)

create

GML:
//Create event of a CONTROLLER object - make it persistent so the data can be used in multiple rooms

//This enumerator is just to make the code more readable and so we can use "have_found" and "ammo" in place of "0" and "1"


enum e_weapons{
   have_found,
   ammo,
}

total_weapons = 5;

for (var i = 0; i < total_weapons; i ++){
    //For ALL the weapon slots, say the player has not yet found it and set ammo to 0
    global.weapons[e_weapons.have_found, i] = false;
    global.weapons[e_weapons.ammo, i] = 0;
}


enum e_gun {
     basic,
     shotgun,
     magma,
     laser,
     crossbow
}



global.weapons[e_weapons.have_found, e_gun.basic] = true;
global.weapons[e_weapons.ammo, e_gun.basic] = -1;






//Give first weapon and 100 rounds to player
global.weapons[e_weapons.have_found, 0] = true;
global.weapons[e_weapons.ammo, 0] = 100

global.weapons[e_weapons.have_found, 1] = true;
global.weapons[e_weapons.ammo, 1] = 30;

global.weapons[e_weapons.have_found, 2] = true;
global.weapons[e_weapons.ammo, 2] = 20;

global.weapons[e_weapons.have_found,3] = true;
global.weapons[e_weapons.ammo, 3] = 10;

global.weapons[e_weapons.have_found, 4] = true;
global.weapons[e_weapons.ammo, 4] = 5;
And the last question is how to combine this part of the code

GML:
// if ammo is -1 (infinite) or greater then 0 .. then fire
if (global.weapons[e_weapons.ammo,current_weapon] == -1)
|| (global.weapons[e_weapons.ammo,current_weapon] > 0){
 
    var dir = point_direction(x,y,mouse_x,mouse_y);
 
    // you can give each weapon a number telling how many bullets it should shoot at once, or what dmg the bullet should have, sprite, aim, recoil, lost of stuff to add to your "e_weapons"  .. the laser might have to be its separate thing
    repeat(1){
        var ins = instance_create_layer(x+lengthdir_x(10,dir),y+lengthdir_y(10,dir),obj_bullet,"Instances"); // using lengthdir to position the bullet a bit away from the body
        ins.dmg = 4;
        ins.direction = dir + irandom_range(-10,10);
    }
   
    // if ammo isn't infinite .. lower it
    if (global.weapons[e_weapons.ammo,current_weapon] != -1) global.weapons[e_weapons.ammo,current_weapon] -= 1;

   // then set weapon cooldown .. and you should also check for that before you are allowed to fire again
}


With my below part of the code in step where I have an attack after pressing the x button (I have a basic unlimited weapon here)



step event obj_hero

GML:
///the code responsible for the hero's shot
if keyboard_check_pressed(ord('X')) && attClock == false && instance_number(obj_bullet)< 3 {
attClock = 30;  
curAttack= 1;
with instance_create(x,y,par_attack) {
     sprite_index = mask_player_attack;
     image_xscale = other.image_xscale;

{
    var box, ID;
    if image_xscale == -1
        box = bbox_left;
    else
        box = bbox_right;
     
    ID = instance_create(box+image_xscale*49, y-17, obj_bullet);
    ID.hspeed = image_xscale * 15;
    owner = par_player;
audio_play_sound(shot_sounds, 1, false); //shot sounds
}    
}
  }
 
Last edited:

skofrant

Member
I'm using GMS 1.4

I'm using this platform game engine



Below also a link to a code preview


link1



link2


The hero's step event, where I have an attack code assigned to the x button, do I have to create the same code for each separate weapon from the list? or only this one is enough?
Above this is my attack code for Unlimited ammo (obj_bullet) or (obj_projectile)


How to put it all together? I currently have yes


obj_game_controller (persistent)

create

GML:
//Create event of a CONTROLLER object - make it persistent so the data can be used in multiple rooms

//This enumerator is just to make the code more readable and so we can use "have_found" and "ammo" in place of "0" and "1"


enum e_weapons{
   have_found,
   ammo,
}

total_weapons = 5;
current_weapon = 0;


for (var i = 0; i < total_weapons; i ++){
    //For ALL the weapon slots, say the player has not yet found it and set ammo to 0
    global.weapons[e_weapons.have_found, i] = false;
    global.weapons[e_weapons.ammo, i] = 0;
}


enum e_gun {
     basic,
     shotgun,
     magma,
     laser,
     crossbow
}



global.weapons[e_weapons.have_found, e_gun.basic] = true;
global.weapons[e_weapons.ammo, e_gun.basic] = -1;






//Give first weapon and 100 rounds to player
global.weapons[e_weapons.have_found, 0] = true;
global.weapons[e_weapons.ammo, 0] = 100

global.weapons[e_weapons.have_found, 1] = true;
global.weapons[e_weapons.ammo, 1] = 30;

global.weapons[e_weapons.have_found, 2] = true;
global.weapons[e_weapons.ammo, 2] = 20;

global.weapons[e_weapons.have_found,3] = true;
global.weapons[e_weapons.ammo, 3] = 10;

global.weapons[e_weapons.have_found, 4] = true;
global.weapons[e_weapons.ammo, 4] = 5;

obj_game_controller (persistent)

Draw GUI


GML:
//draw_gui event
var box_width = sprite_get_width(spr_weapon_box); //how wide is each box that will display a weapon?

for (var i = 0; i < total_weapons; i ++){
   draw_x = i * box_width;
   draw_y = 0; //Assuming sprites origin is drawn from top left

   //if you have each weapon image in the same sprite, you can draw them all just using "i"
   if ( global.weapons[e_weapons.have_found, i] == true ) draw_sprite(spr_weapon_box,  i, draw_x, draw_y);
}

obj_hero

step
(part of the code where I have an attack when pressing the X button)


GML:
///the code responsible for the hero's shot
if keyboard_check_pressed(ord('X')) && attClock == false && instance_number(obj_bullet)< 3 { [B]//obj_bullet a primary weapon with unlimited ammo[/B]
attClock = 30;
curAttack= 1;
with instance_create(x,y,par_attack) {
     sprite_index = mask_player_attack;
     image_xscale = other.image_xscale;

{
    var box, ID;
    if image_xscale == -1
        box = bbox_left;
    else
        box = bbox_right;

    ID = instance_create(box+image_xscale*49, y-17, obj_bullet);
    ID.hspeed = image_xscale * 15;
    owner = par_player;
audio_play_sound(shot_sounds, 1, false); //shot sounds
}
}
  }


in each of these additional weapons, in addition to the primary weapon, gives such variables in the create event?


create

obj_basic (obj_bullet)


GML:
gun = e_gun.basic;

create

obj_magma


GML:
gun = e_gun.magma;

create

obj_shotgun


GML:
gun = e_gun.shotgun;

create

obj_laser

GML:
gun = e_gun.laser;

create

obj_crossbow

GML:
gun = e_gun.crossbow;

Anything else to add in the code for these additional weapons?
And what about the current_weapon variable in what objects does it have to be? only in the main one? obj_game_controller (persistent) or maybe yet in other facilities?
What initial value in create event should this variable have current_weapon ?





And if there is a collision with a player, when he finds a weapon on the board, shouldn't it be specified what kind of weapon is it?



collision event: with obj_hero
(it is a object_weapon, when the hero hovers it, the object will disappear and the hero will receive a weapon e.g. magma and its ammo)



GML:
global.weapons[e_weapons.have_found, gun] = true;
global.weapons[e_weapons.ammo, gun] += 30;
 
Last edited:

TailBit

Member
There is no need to PM me to respond to the topic .. don't expect instant response on a forum ..

Your friend is giving you a bit complicated code .. creating a parent object that makes the bullet .. also, you are shooting your weapon pickup?? ..
Code:
///the code responsible for the hero's shot
if keyboard_check_pressed(ord('X')) && attClock == false && instance_number(obj_bullet)< 3 { //obj_bullet a primary weapon with unlimited ammo[/B]
    attClock = 30;
    curAttack= 1;
   
    with instance_create(x,y,par_attack) {
         sprite_index = mask_player_attack;
         image_xscale = other.image_xscale;

        {
            var box, ID;
            if image_xscale == -1
                box = bbox_left;
            else
                box = bbox_right;

            ID = instance_create(box+image_xscale*49, y-17, obj_bullet);
            ID.hspeed = image_xscale * 15;
            owner = par_player;
            audio_play_sound(shot_sounds, 1, false); //shot sounds
        }
    }
}
I do think you are a bit lost in all of this .. I would really recommend you to just make a simple shooting code with no arrays and just 1 gun yourself, so that you made a code that you know how works .. then you turn it into an array..

for example the shooting code:

player object
create
Code:
have = true;
ammo = 10;
firerate = 15;
dmg_min = 3;
dmg_max = 5;

attClock = 0;
step event:
Code:
attClock--

if keyboard_check_pressed(ord('X'))
&& attClock <= 0
&& ammo > 0 {
    attClock = firerate;
    ammo -= 1;

    var ins = instance_create(x, y-17, obj_bullet);
    ins.hspeed = image_xscale * 15;
    ins.dmg = irandom_range(dmg_min,dmg_max);

    audio_play_sound(shot_sounds, 1, false); //shot sounds

}
then you can later turn it into an array:

control object create
Code:
enum e_wep { have,ammo,firerate,dmg_min,dmg_max }
enum e_gun { basic } // and so on

current_weapon = 0;
weapons_total = i;

var i = 0;
global.wep[i, e_wep.have] = true;
global.wep[i ,e_wep.ammo] = 10;
global.wep[i ,e_wep.firerate] = 15;
global.wep[i ,e_wep.dmg_min] = 3;
global.wep[i ,e_wep.dmg_max] = 5;

// you can increase i by 1 and copy that global.wep cluster to add another weapon
player object create
Code:
attClock = 0;
step event:
Code:
attClock--

var cur = obj_control.current_weapon; // the control object have the index of the current weapon, so we need to fetch that first

if keyboard_check_pressed(ord('X'))
&& attClock <= 0
&& global.wep[cur,e_wep.ammo] > 0{
    attClock = global.wep[cur,e_wep.firerate];
    global.wep[cur,e_wep.ammo]-=1;

    var ins = instance_create(x, y-17, obj_bullet);
    ins.hspeed = image_xscale * 15;
    ins.dmg = irandom_range(global.wep[cur,e_wep.dmg_min],global.wep[cur,e_wep.dmg_max]);

    audio_play_sound(shot_sounds, 1, false); //shot sounds

}
This is just to show that it isn't that much trouble to turn a fire code into an array, but you really should try implement what you need first .. should gun have a clip, clip size,clip reload speed differ from fire delay, fire multiple shots at once, reload when clip is empty, if you can do that without an array then take the next step

On the other hand, you should also familiarize yourself more with arrays

for example if you have 2 objects in an array and a code like this
Code:
selected = 0;
total = 2;

obj[0] = obj_a;
obj[1] = obj_b;
then on mouse left press event:
Code:
instance_create(mouse_x,mouse_y,obj[selected])
and on mouse right press event
Code:
selected++;
if (selected == total) selected = 0;
That would create obj_a when you press with RMB, and LMB would switch so you would create the next one in the array the next time you press RMB .. pretty much how weapon swapping would be ..
 

skofrant

Member
However I will stick with my second version. I created a simple system for changing weapons on "if".
maybe more code, but more understandable for me and easier to implement .. I had practically little to do with arrays ..
my weapon change system works, but I have a little problem when I find a gun on the board and go to the next room, I have no weapons and ammunition.
 
Last edited:

TheouAegis

Member
However I will stick with my second version. I created a simple system for changing weapons on ifach.
maybe more code, but more understandable for me and easier to implement .. I had practically little to do with arrays ..
my weapon change system works, but I have a little problem when I find a gun on the board and go to the next room, I have no weapons and ammunition.
No, focus on this thread. Ignore the other threat now. Your "working code" is garbage anyway. Learn how to work with arrays and enumerators properly like everybody's teaching you here, and abandon your verbose method you are relying on in the other thread, as you are just going to screw everything up from here on out if you stick with the code you are trying to use in that other thread.

I mean, seriously dude, what are you planning on doing for you weapon checks?
Code:
if global.primaryweapon=0 && global.shotgun=1 && global.magma=0 && global.laser=0 && global.crossbow=0 { }
else
if global.primaryweapon=0 && global.shotgun=0 && global.magma=1 && global.laser=0 && global.crossbow=0 { }
else
if global.primaryweapon=0 && global.shotgun=0 && global.magma=0 && global.laser=1 && global.crossbow=0 { }
else
if global.primaryweapon=0 && global.shotgun=1 && global.magma=0 && global.laser=0 && global.crossbow=0 { }
else
if global.primaryweapon=0 && global.shotgun=0 && global.magma=0 && global.laser=0 && global.crossbow=1 { }
those are just the conditional for checking what gun is shooting. You'd have to do it all over again when you pick up ammo as well. And then one day you decide it would be easier to just copy paste the same code over and over and change the numbers, but you forget to change one of the numbers and now your code stops working.

We're not telling you to use arrays and all this other stuff simply because we think it's better, we are doing so because your method does not work. Just look at the US government - they write bills like you write code and now citizens are rioting.
🧐

If you use the array method, you can change what gun is equipped with one single variable. You can check if when you pick up ammo you need to switch to the weapon you picked the ammo up for with the check of one single variable. You can add even more weapons later on with the change of one single variable and a couple more entries in the array.

You can calculate the area of a circle using nothing but addition, but that would be a major pain in the ass, which is why they don't teach you that in school. It's the same thing here.
👨‍🎓
 

skofrant

Member
I really appreciate what you guys do for me, I just mentioned that I didn't really deal with the boards...
in this case, I more need one ready-made template of working code to make it work, and I could analyze it line by line ..
Here my colleagues started well at the beginning..first there was one solution..one of you said that it was wrong..that another person showed another solution..but there are many unknowns.
I just freaked out what to do ...
several versions of the code resulted from this .. I thought I described it quite clearly in the post.


ok let's try again simpler ..

I have a request, can someone help me in preparing such a template of the weapon change system?

already describes what I mean ..
I have such a hero code below ... my hero after pressing the action button in this case X. shoots a bullet.
And that's ok. this ball has an unlimited number of bullet.

I would like to be able to choose 4 more weapons besides the primary weapon.


the only condition is that I need to find a given weapon on the board ... suppose there is a weapon on the board, I pick it up and automatically add that weapon to the hero with any amount of ammo which is limited. This weapon icon will automatically be added to the game HUD with the ammo sprites of whatever weapon it has.

The choice of weapons, for example, would be under the button of one of the keys 1,2,3,4 and 5


and now, after modifications, this is what it looks like in my code ..


player object
create


GML:
have = true;
ammo = 10;
firerate = 15;
dmg_min = 3;
dmg_max = 5;

attClock = 0;
player object

step


GML:
attClock--

var cur = obj_control.current_weapon; // the control object have the index of the current weapon, so we need to fetch that first

if keyboard_check_pressed(ord('X'))
&& attClock <= 0
&& global.wep[cur,e_wep.ammo] > 0{
    attClock = global.wep[cur,e_wep.firerate];
    global.wep[cur,e_wep.ammo]-=1;

    var ins = instance_create(x, y-17, obj_bullet);
    ins.hspeed = image_xscale * 15;
    ins.dmg = irandom_range(global.wep[cur,e_wep.dmg_min],global.wep[cur,e_wep.dmg_max]);

    audio_play_sound(shot_sounds, 1, false); //shot sounds

}

control object perssistent

GML:
enum e_wep { have,ammo,firerate,dmg_min,dmg_max }
enum e_gun   { basic,magma,shotgun,laser,crossbow }

current_weapon = 0;
weapons_total = 5;



for (var i = 0; i < weapons_total; i ++){
    //For ALL the weapon slots, say the player has not yet found it and set ammo to 0
    global.wep[e_wep.have, i] = false;
    global.wep[e_wep.ammo, i] = 0;
}





var i = 0;
global.wep[i, e_wep.have] = true;
global.wep[i ,e_wep.ammo] = 10;
global.wep[i ,e_wep.firerate] = 15;
global.wep[i ,e_wep.dmg_min] = 3;
global.wep[i ,e_wep.dmg_max] = 5;

// you can increase i by 1 and copy that global.wep cluster to add another weapon



global.wep[e_wep.have,e_gun.basic] = true;
global.wep[e_wep.ammo,e_gun.basic] = -1;


//Give first weapon and 100 rounds to player
global.wep[e_wep.have, 0] = true;
global.wep[e_wep.ammo, 0] = 100

global.wep[e_wep.have, 1] = true;
global.wep[e_wep.ammo, 1] = 30;

global.wep[e_wep.have, 2] = true;
global.wep[e_wep.ammo, 2] = 20;

global.wep[e_wep.have,3] = true;
global.wep[e_wep.ammo, 3] = 10;

global.wep[e_wep.have, 4] = true;
global.wep[e_wep.ammo, 4] = 5;



control object perssistent

draw gui

GML:
//draw_gui event
var box_width = sprite_get_width(spr_weapon_box); //how wide is each box that will display a weapon?

for (var i = 0; i < weapons_total; i ++){
   draw_x = i * box_width;
   draw_y = 0; //Assuming sprites origin is drawn from top left

   //if you have each weapon image in the same sprite, you can draw them all just using "i"
   if ( global.wep[e_wep.have, i] == true ) draw_sprite(spr_weapon_box,  i, draw_x, draw_y);
}

pressing the buttons 1-5

GML:
for(var i=0;i<weapons_total;i++)
    if keyboard_check_pressed(ord("1")+i)
        if global.wep[e_wep.have,i]
            current_weapon = i;

obj_magma create event:




GML:
gun = e_gun.magma;

collision event: obj_chest (chest with weapons and ammunition)




GML:
 global.wep[e_wep.have, gun] = true;
global.wep[e_wep.ammo, gun] += 30;

yes I currently have

I don't have a mouse choice of weapons because this is a platform game, not a shooter


only this code is incomplete ok, I omit that I have to add more weapons there, I will just handle it ... but as I mentioned this code is not complete ..
As a greeting I get an error with this variable ... I added everything according to the instructions above
 
Last edited:

skofrant

Member
Tries to analyze it ..
I wonder why this error above is popping up ..

Ok I added the rest of the weapons to the enum in the event create obj_game_controler which is perssistent.
how to complete this code andI would like the weapon selection under buttons 1 to 5 to work fix the above error?
provided that I find an additional weapon on the board and then it will be displayed on the gui bar along with the amount of ammo
 

skofrant

Member
Could any of you help me finish this code and show me where the bug is?

So this is how I find a chest with a weapon on the stage(room), let it be, for example, magma
when I overlap this object, the hero should get a magma weapon and ammunition for it, for example limited 20 ammo
This weapon should be displayed on the gui bar with the amount of ammunition assigned to it.It is best if all weapons are in one sprite which has several pictures, i.e. 5 pictures and with the key from 1 to 5 I will select them.

obj_chestwithweapons
The collision of the hero with the crate

Here also shows the error when the player touches the weapon chest!



GML:
global.wep[e_wep.have, gun.magma] = true;
global.wep[e_wep.ammo, gun.magma] += 30;

This entry is added to the magma object in event create.

obj_magma

create

GML:
gun = e_gun.magma;

After pressing one of the five buttons I choose a weapon. By default, I have a basic unlimited weapon, so I can only choose the one at the beginning, but if I find more weapons, I should choose more of them then:

obj_game_controller (perssistent)

it is set under the "1" button in obj_game_controler (perssistent_ do not know if it should not be in the event step

keypress 1


GML:
for(var i=0;i<weapons_total;i++)
    if keyboard_check_pressed(ord("1")+i)
        if global.wep[e_wep.have,i]
            current_weapon = i;
obj_game_controller (perssistent)

create

There is something wrong with this code in the create event.


GML:
enum e_wep { have,ammo,firerate,dmg_min,dmg_max }
enum e_gun   { basic,magma,shotgun,laser,crossbow }

current_weapon = 0;
weapons_total = 5;



for (var i = 0; i < weapons_total; i ++){
    //For ALL the weapon slots, say the player has not yet found it and set ammo to 0
    global.wep[e_wep.have, i] = false;
    global.wep[e_wep.ammo, i] = 0;
}





var i = 0;
global.wep[i, e_wep.have] = true;
global.wep[i ,e_wep.ammo] = 10;
global.wep[i ,e_wep.firerate] = 15;
global.wep[i ,e_wep.dmg_min] = 3;
global.wep[i ,e_wep.dmg_max] = 5;

// you can increase i by 1 and copy that global.wep cluster to add another weapon



global.wep[e_wep.have,e_gun.basic] = true;
global.wep[e_wep.ammo,e_gun.basic] = -1;


//Give first weapon and 100 rounds to player
global.wep[e_wep.have, 0] = true;
global.wep[e_wep.ammo, 0] = 100

global.wep[e_wep.have, 1] = true;
global.wep[e_wep.ammo, 1] = 30;

global.wep[e_wep.have, 2] = true;
global.wep[e_wep.ammo, 2] = 20;  //magma

global.wep[e_wep.have,3] = true;
global.wep[e_wep.ammo, 3] = 10;

global.wep[e_wep.have, 4] = true;
global.wep[e_wep.ammo, 4] = 5;

obj_game_controller(perssistent)

in one sprite somewhere at the top of the screen so that the weapon is displayed when I get it. First, the primary weapon is displayed all the time, and after finding another weapon, it added and displayed as a sprite .. and the next ones were also found .. in one sprite.

draw GUI

GML:
//draw_gui event
var box_width = sprite_get_width(spr_weapon_box); //how wide is each box that will display a weapon?

for (var i = 0; i < weapons_total; i ++){
   draw_x = i * box_width;
   draw_y = 0; //Assuming sprites origin is drawn from top left

   //if you have each weapon image in the same sprite, you can draw them all just using "i"
   if ( global.wep[e_wep.have, i] == true ) draw_sprite(spr_weapon_box,  i, draw_x, draw_y);
}

obj_player

step

Something is wrong here, because the hero fires one shot ONLY, and then he does not fire the weapon at all


GML:
attClock--

var cur = obj_control.current_weapon; // the control object have the index of the current weapon, so we need to fetch that first

if keyboard_check_pressed(ord('X'))
&& attClock <= 0
&& global.wep[cur,e_wep.ammo] > 0{
    attClock = global.wep[cur,e_wep.firerate];
    global.wep[cur,e_wep.ammo]-=1;

    var ins = instance_create(x, y-17, obj_bullet); [B]//basic weapon[/B]
    ins.hspeed = image_xscale * 15;
    ins.dmg = irandom_range(global.wep[cur,e_wep.dmg_min],global.wep[cur,e_wep.dmg_max]);

    audio_play_sound(shot_sounds, 1, false); //shot sounds

}
 
Last edited:

TailBit

Member
weapons_total should be a number, not i, my bad.

Now the other problem is that my code got the weapon index first and enum after
global.wep[ index, e_wep.X ]
While the earlier code got the enum first and index last
global.wep[ e_wep.X , index ]
You can not mix these, so choose one and change the rest to match.

The reason all the guns show up is because you set their "have" to true for all of them in the create event

Edit: these instructions are pretty straight forward, so I'll let you handle it 👍
 
Last edited:

skofrant

Member
Could you help me correct this event code from create in obj_game_controler? and the rest of the code
I'm sorry for you and I'm bothering you all, but I want to finally finish it and close the topic
 

skofrant

Member
I don't know how to fix it anymore ... in event create:/
obj_game_controler(perssistent)





GML:
enum e_wep { have,ammo,firerate,dmg_min,dmg_max }
enum e_gun   { basic,magma,shotgun,laser,crossbow }

current_weapon = 0;
weapons_total = 5;



for (var i = 0; i < weapons_total; i ++){
    //For ALL the weapon slots, say the player has not yet found it and set ammo to 0
    global.wep[i,e_wep.have] = false;
    global.wep[i,e_wep.ammo, i] = 0;
}


global.wep[0,e_wep.have,e_gun.basic] = true;
global.wep[0,e_wep.ammo,e_gun.basic] = -1;


var i = 0;
global.wep[0, e_wep.have] = true;
global.wep[0 ,e_wep.ammo] = 100; //unlimited
global.wep[0 ,e_wep.firerate] = 15;
global.wep[0 ,e_wep.dmg_min] = 3;
global.wep[0 ,e_wep.dmg_max] = 5;



global.wep[1, e_wep.have] = true;
global.wep[1 ,e_wep.ammo] = 30;
global.wep[1 ,e_wep.firerate] = 15;
global.wep[1 ,e_wep.dmg_min] = 3;
global.wep[1 ,e_wep.dmg_max] = 5;


global.wep[2, e_wep.have] = true;
global.wep[2 ,e_wep.ammo] = 20;
global.wep[2 ,e_wep.firerate] = 15;
global.wep[2 ,e_wep.dmg_min] = 3;
global.wep[2 ,e_wep.dmg_max] = 5;



global.wep[3, e_wep.have] = true;
global.wep[3 ,e_wep.ammo] = 10;
global.wep[3 ,e_wep.firerate] = 15;
global.wep[3 ,e_wep.dmg_min] = 3;
global.wep[3 ,e_wep.dmg_max] = 5;



global.wep[4, e_wep.have] = true;
global.wep[4 ,e_wep.ammo] = 5;
global.wep[4 ,e_wep.firerate] = 15;
global.wep[4 ,e_wep.dmg_min] = 3;
global.wep[4 ,e_wep.dmg_max] = 5;

obj_game_controller (perssistent)

draw GUI

Even if I have no ammo but i found a new weapon, it should already be visible in the GUI bar



GML:
//draw_gui event
var box_width = sprite_get_width(spr_weapon_box); //how wide is each box that will display a weapon?

for (var i = 0; i < weapons_total; i ++){
   draw_x = i * box_width;
   draw_y = 0; //Assuming sprites origin is drawn from top left

   //if you have each weapon image in the same sprite, you can draw them all just using "i"
   if ( global.wep[e_wep.have, i] == true ) draw_sprite(spr_weapon_box,  i, draw_x, draw_y);
}


obj_chestwithweapons
The collision of the hero with the crate

Here also shows the error when the player touches the weapon chest!

GML:
FATAL ERROR in
action number 1
of  Step Eventobj_skrzynia
for object obj_player:

Variable obj_player.gun(100094, -2147483648) not set before reading it.
at gml_Object_obj_player_CollisionEvent_37_1 (line 3) - global.wep[e_wep.have, gun] = true;


GML:
global.wep[e_wep.have, gun.magma] = true;
global.wep[e_wep.ammo, gun.magma] += 30;

obj_magma
Or only this entry is enough in the create event to add this new weapon?
create


GML:
gun = e_gun.magma;

obj_game_controller (perssistent)

it is set under the "1" button in obj_game_controler (perssistent_ do not know if it should not be in the event step

keypress 1


GML:
for(var i=0;i<weapons_total;i++)
    if keyboard_check_pressed(ord("1")+i)
        if global.wep[e_wep.have,i]
            current_weapon = i;
 
Last edited:

skofrant

Member
I have already repaired many things ... I'll tell you everybody what still doesn't work ;

1. the hero still has a limited basic weapon...
I know .. in create event obj_game_controler i have to declare the value -1 so that this primary weapon is not limited .. how to do it? because I am lost already.


The solution might be this seting the basic weapon ammo to 100 each step so the player never runs out

obj_game_controller (perssistent)

step


GML:
if global.wep[0 ,e_wep.ammo] <= 100
{
global.wep[0 ,e_wep.ammo] = 100;
}

obj_game_controller (perssistent)

create


GML:
enum e_wep { have,ammo,firerate,dmg_min,dmg_max }
enum e_gun   {basic,magma,shotgun,laser,crossbow}

current_weapon = 0;
weapons_total = 5;






var i = 0;

global.wep[0, e_wep.have] = true;
global.wep[0 ,e_wep.ammo] = 10; //unlimited
global.wep[0 ,e_wep.firerate] = 15;
global.wep[0 ,e_wep.dmg_min] = 3;
global.wep[0 ,e_wep.dmg_max] = 5;



global.wep[1, e_wep.have] = false;
global.wep[1 ,e_wep.ammo] = 30;
global.wep[1 ,e_wep.firerate] = 15;
global.wep[1 ,e_wep.dmg_min] = 3;
global.wep[1 ,e_wep.dmg_max] = 5;


global.wep[2, e_wep.have] = false;
global.wep[2 ,e_wep.ammo] = 20;
global.wep[2 ,e_wep.firerate] = 15;
global.wep[2 ,e_wep.dmg_min] = 3;
global.wep[2 ,e_wep.dmg_max] = 5;



global.wep[3, e_wep.have] = false;
global.wep[3 ,e_wep.ammo] = 10;
global.wep[3 ,e_wep.firerate] = 15;
global.wep[3 ,e_wep.dmg_min] = 3;
global.wep[3 ,e_wep.dmg_max] = 5;



global.wep[4, e_wep.have] = false;
global.wep[4 ,e_wep.ammo] = 5;
global.wep[4 ,e_wep.firerate] = 15;
global.wep[4 ,e_wep.dmg_min] = 3;
global.wep[4 ,e_wep.dmg_max] = 5;
it doesn't help to change the value here to -1 because then the hero doesn't shoot at all.


GML:
global.wep[0 ,e_wep.ammo] = -1;

it is in a collision with the player, but i modified it..now the bug does not pop up..but still does not add a new weapon to the hero


obj_chest
chest with weapons and ammunition

colission with the hero
(obj_player)

GML:
///weapon magma

global.wep[1,e_wep.have] = true;
global.wep[1,e_wep.ammo] += 30;

i probably need to declare something in the create event in the weapon obj_magma
So that the player, after taking the ammunition box, would get this weapon and ammunition

obj_magma

create


GML:
gun = e_gun.magma;
 
Last edited:

TailBit

Member
Atm your shooting code says something like
Code:
&& ammo > 0{

    ammo-=1;
But you need to handle -1 as acceptable and not lower the ammo value if it is -1, so it would end up like

Code:
&& (ammo > 0 || ammo == -1){

    if(ammo != -1) ammo-=1;
|| is the same as or

Now try implement this pseudocode correctly.

For the weapons, it is enough to set the weapon index in the collision event, then you don't need the create event at all.
 

skofrant

Member
something like that?

GML:
if (global.wep[0 ,e_wep.ammo] > 0 || global.wep[0 ,e_wep.ammo] == -1){

    if(global.wep[0 ,e_wep.ammo] != -1) global.wep[0 ,e_wep.ammo]-=1;
    
    }
 

TailBit

Member
You are already setting the index correct in the magma weapon, you could use e_gun.magma instead of the number, but both works

Still need to set "have" to false for most of the weapons in the create event

Edit: still got 3 hours left at work, so wont answer more before I'm done :p
 

skofrant

Member
but I have "have" set to false in the event create ... only one "have" is set to true because it is the primary weapon ..:/

the weapon magma still does not add to me, even though as you wrote correctly, I declared it in a collision with the hero
 

skofrant

Member
obj_game_controller (perssistent)

create

I think it's okay now here


GML:
enum e_wep { have,ammo,firerate,dmg_min,dmg_max }
enum e_gun   {basic,magma,shotgun,laser,crossbow}

current_weapon = 0;
weapons_total = 5;



var i = 0;


//primary weapon
global.wep[0, e_wep.have] = false;
global.wep[0 ,e_wep.ammo] = 100; //unlimited
global.wep[0 ,e_wep.firerate] = 15;
global.wep[0 ,e_wep.dmg_min] = 3;
global.wep[0 ,e_wep.dmg_max] = 5;


//magma weapon
global.wep[1, e_wep.have] = false;
global.wep[1 ,e_wep.ammo] = 30;
global.wep[1 ,e_wep.firerate] = 15;
global.wep[1 ,e_wep.dmg_min] = 3;
global.wep[1 ,e_wep.dmg_max] = 5;

//shotgun weapon
global.wep[2, e_wep.have] = false;
global.wep[2 ,e_wep.ammo] = 20;
global.wep[2 ,e_wep.firerate] = 15;
global.wep[2 ,e_wep.dmg_min] = 3;
global.wep[2 ,e_wep.dmg_max] = 5;


//laser weapon
global.wep[3, e_wep.have] = false;
global.wep[3 ,e_wep.ammo] = 10;
global.wep[3 ,e_wep.firerate] = 15;
global.wep[3 ,e_wep.dmg_min] = 3;
global.wep[3 ,e_wep.dmg_max] = 5;


//crossbow weapon
global.wep[4, e_wep.have] = false;
global.wep[4 ,e_wep.ammo] = 5;
global.wep[4 ,e_wep.firerate] = 15;
global.wep[4 ,e_wep.dmg_min] = 3;
global.wep[4 ,e_wep.dmg_max] = 5;

He still does not give me a magma weapon, although the hero takes the weapon, he still shoots the primary weapon..switching with buttons from 1 to 5 does not help

obj_chest
chest with weapons and ammunition

colission with the hero
(obj_player)


GML:
///weapon magma

global.wep[1,e_wep.have] = true;
global.wep[1,e_wep.ammo] += 30;

optional

obj_magma

create



GML:
gun = e_gun.magma;
 

skofrant

Member
I think something is missing ...
if there is a variable to choose a weapon then it should not be in the hero event create ??

"current_weapon"


obj_player

create


GML:
attClock = 0;

have = true;
ammo = 10;
firerate = 15;
dmg_min = 3;
dmg_max = 5;

obj_player

step


GML:
attClock--

var cur = obj_game_controller.current_weapon; // the control object have the index of the current weapon, so we need to fetch that first

if keyboard_check_pressed(ord('X'))
&& attClock <= 0
&& global.wep[cur,e_wep.ammo] > 0{
    attClock = global.wep[cur,e_wep.firerate];
    global.wep[cur,e_wep.ammo]-=1;

    var ins = instance_create(x, y-17, obj_bullet); ///[B][SIZE=7][FONT=arial] despite switching weapons to magma, the hero still fires his primary weapon[/FONT][/SIZE][/B]
    ins.hspeed = image_xscale * 15;
    ins.dmg = irandom_range(global.wep[cur,e_wep.dmg_min],global.wep[cur,e_wep.dmg_max]);

    //audio_play_sound(shot_sounds, 1, false); //shot sounds

}
obj_player

step 2



GML:
///Sprites
if !place_meeting(x,y,obj_water) {
if inAir == false && keyboard_check(kRight) = keyboard_check(kLeft) && sprite_index != spr_player_stand && climbing == false {
  sprite_index = spr_player_stand;
  image_index = 0;
}
if inAir == false && (keyboard_check(kRight) || keyboard_check(kLeft)) && keyboard_check(kRight) != keyboard_check(kLeft) && sprite_index != spr_player_run && climbing == false {
  sprite_index = spr_player_run;
  image_index = 0;
}
if inAir == true && climbing == false {
  sprite_index = spr_player_air;
  if vspd <= -1 {
   image_index = 0;
  } else if vspd >= 1 {
   image_index = 2;
  } else {
   image_index = 1;
  }
}

if climbing == true {
  if x == xprevious && y == yprevious {
   if sprite_index != spr_player_hang {
    sprite_index = spr_player_hang;
   }
  } else {
   if sprite_index != spr_player_climb {
    sprite_index = spr_player_climb;
   }
  }
}

if attClock > 0 && curAttack == 0 {
  sprite_index = spr_player_attack;
  image_index = 14-(attClock);
  attClock -= 1;
}
if attClock > 0 && curAttack == 1 {
  sprite_index = spr_player_shoot;
  image_index = 6-(attClock);
  attClock -= 1;
}
swimDir = point_direction(xprevious,yprevious,x,y);
drawAngle = swimDir;
if image_xscale < 0 {
  drawAngle += 180;
}
} else {
if sprite_index != spr_player_water {
  sprite_index = spr_player_water;
  image_index = 0;
}

if keyboard_check(kRight) && !keyboard_check(kLeft) && image_xscale = -1 {
  image_xscale = 1;
  drawAngle -= 180;
} else if keyboard_check(kLeft) && !keyboard_check(kRight) && image_xscale = 1 {
  image_xscale = -1;
  drawAngle += 180;
}

if abs(keyboard_check(kRight)-keyboard_check(kLeft))+abs(keyboard_check(kDown)-keyboard_check(kUp)) != 0 {
  image_index += 2;
  if image_xscale > 0 {
   drawAngle -= angle_difference(drawAngle,swimDir)/16;
  } else {
   drawAngle -= angle_difference(drawAngle,180+swimDir)/16;
  }
}
}
 
Last edited:

skofrant

Member
it's strange that if I take in magma weapon crates, the code below works, because the sprite changes to magma sprite, but the hero still shoots the basic weapon:/


obj_chest
chest with weapons and ammunition

colission with the hero
(obj_player)


GML:
///weapon magma

global.wep[1,e_wep.have] = true;
global.wep[1,e_wep.ammo] += 30;
optional

obj_magma

create


GML:
gun = e_gun.magma;


obj_game_controller (perssistent)

draw GUI



GML:
//draw_gui event
var box_width = sprite_get_width(mask_explosion); //how wide is each box that will display a weapon?

for (var i = 0; i < weapons_total; i ++){
   draw_x = i * box_width;
   draw_y = 0; //Assuming sprites origin is drawn from top left

   //if you have each weapon image in the same sprite, you can draw them all just using "i"
   if ( global.wep[i,e_wep.have] == true ) draw_sprite(spr_weapon,  i, draw_x, draw_y);
}
 
Last edited:

skofrant

Member
Maybe something needs to be implemented in these other weapons? because how do know that the hero will use a different weapon than the basic one?

obj_magma, obj_laser, obj_shotgun and obj_crossbow


These weapons all have the same code as the primary weapons, only with a different sprite.
 

woods

Member
looks like you might need another entry in your enum e_wep..
ammo_type

and in each of your weapon lists set the ammo_type to the obj_bullet that matches your gun
then you can reference that ammo_type variable to draw the right bullet instead of obj_bullet(which is for the basic primary weapon)


right?
 

woods

Member
in your shoot code you have a x pressed event...
you call everything about your weapon here.. timer for reload.. amount of ammo.. it only makes sense that you would do the same for the bullet. ;o)

where you have create obj_bullet...... change that up the same way you did for setting the correct gun..
 

woods

Member
i donno if this will work.. but i see the logic behind it..
obj_game_controller
create event:

add ammo_type to your enum e_wep

then add it to your
//primary weapon
global.wep[0 ,e_wep.ammo_type] = obj_bullet;


//magma weapon
global.wep[1 ,e_wep.ammo_type] = obj_magma_bullet; // or whatever your bullet object is

...continue for each weapon...

====

then in your obj_player
step event:

GML:
attClock--

var cur = obj_game_controller.current_weapon; // the control object have the index of the current weapon, so we need to fetch that first

if keyboard_check_pressed(ord('X'))
&& attClock <= 0
&& global.wep[cur,e_wep.ammo] > 0{
    attClock = global.wep[cur,e_wep.firerate];
    global.wep[cur,e_wep.ammo]-=1;

    var ins = instance_create(x, y-17, obj_bullet); // this line here needs some love
    ins.hspeed = image_xscale * 15;
    ins.dmg = irandom_range(global.wep[cur,e_wep.dmg_min],global.wep[cur,e_wep.dmg_max]);

    //audio_play_sound(shot_sounds, 1, false); //shot sounds

}
put this line in there instead
var ins = instance_create(x, y-17,global.wep[cur,e_wep.ammo_type] );


if this doesnt work... at least i think its on the right track. (maybe somebody with a bit more experience can help us out ;o) )
 

skofrant

Member
hmmmm...

does not display an error, but also does not change weapons ... are we close to the solution?


obj_game_controller (perssistent)

create


GML:
enum e_wep { have,ammo,firerate,dmg_min,dmg_max,ammo_type }
enum e_gun   { basic,magma,shotgun,laser,crossbow }




current_weapon = 0;
weapons_total = 5;



var i = 0;


//primary weapon(bullet)

global.wep[0 ,e_wep.ammo_type] = obj_bullet;
global.wep[0, e_wep.have] = false;
global.wep[0 ,e_wep.ammo] = 100; //unlimited
global.wep[0 ,e_wep.firerate] = 5;
global.wep[0 ,e_wep.dmg_min] = 3;
global.wep[0 ,e_wep.dmg_max] = 5;


//magma weapon

global.wep[1 ,e_wep.ammo_type] = obj_magma;
global.wep[1, e_wep.have] = false;
global.wep[1 ,e_wep.ammo] = 30;
global.wep[1 ,e_wep.firerate] = 10;
global.wep[1 ,e_wep.dmg_min] = 3;
global.wep[1 ,e_wep.dmg_max] = 5;

//shotgun weapon

global.wep[2 ,e_wep.ammo_type] = obj_shotgun;
global.wep[2, e_wep.have] = false;
global.wep[2 ,e_wep.ammo] = 20;
global.wep[2 ,e_wep.firerate] = 15;
global.wep[2 ,e_wep.dmg_min] = 3;
global.wep[2 ,e_wep.dmg_max] = 5;


//laser weapon

global.wep[3 ,e_wep.ammo_type] = obj_laser;
global.wep[3, e_wep.have] = false;
global.wep[3 ,e_wep.ammo] = 10;
global.wep[3 ,e_wep.firerate] = 20;
global.wep[3 ,e_wep.dmg_min] = 3;
global.wep[3 ,e_wep.dmg_max] = 5;


//crossbow weapon

global.wep[4 ,e_wep.ammo_type] = obj_crossbow;
global.wep[4, e_wep.have] = false;
global.wep[4 ,e_wep.ammo] = 5;
global.wep[4 ,e_wep.firerate] = 25;
global.wep[4 ,e_wep.dmg_min] = 3;
global.wep[4 ,e_wep.dmg_max] = 5;


obj_player

step



GML:
 attClock--

var cur = obj_game_controller.current_weapon; // the control object have the index of the current weapon, so we need to fetch that first

if keyboard_check_pressed(ord('X'))
&& attClock <= 0
&& global.wep[cur,e_wep.ammo] > 0{
    attClock = global.wep[cur,e_wep.firerate];
    global.wep[cur,e_wep.ammo]-=1;

    var ins = instance_create(x, y-17,global.wep[cur,e_wep.ammo_type] );
    //var ins = instance_create(x, y-17, obj_bullet); // this line here needs some love
    ins.hspeed = image_xscale * 15;
    ins.dmg = irandom_range(global.wep[cur,e_wep.dmg_min],global.wep[cur,e_wep.dmg_max]);

    //audio_play_sound(shot_sounds, 1, false); //shot sounds

}
 
Last edited:

skofrant

Member
Ech:/

The solution is probably close ... but what's the reason other weapons don't work? the chest with weapons and magma ammunition the hero gets on this stage(room).. the condition is fulfilled .. and the sprite changes too ... but the hero continues to shoot his primary weapon ..
 

woods

Member
in the collision with weapon chest and player we have:
set the weapon to have it picked up;
add 30 ammo for that weapon;

GML:
///weapon magma

global.wep[1,e_wep.have] = true;
global.wep[1,e_wep.ammo] += 30;
we need to set the player to have the magma weapon equipped (current_weapon) when we press 2.

alot has been shuffled around.
what is the current code you have to change your weapons? (for keypress "1" and "2")
 

TailBit

Member
Okay, you would ofc want to have the basic weapon from the beginning, so that one should be true from the start
global.wep[0, e_wep.have] = true;
but also does not change weapons ... are we close to the solution?
It should change the bullet fired, so .. noticeable if you give them different sprite

usually I would just have 1 bullet object and have the code change the sprite of it on creation, but just having different bullet objects works too ..

But yeah, after picking up the magma weapon then you should be able to change to it .. so to make sure what something does happen, in the draw event.. just draw the value of current_weapon

I swapped i and e_wep.have in this so it matches what you ended up using, this is for the step event:
GML:
for(var i=0;i<weapons_total;i++)
    if keyboard_check_pressed(ord("1")+i)
        if global.wep[i,e_wep.have]
            current_weapon = i;
Then we got your draw gui code, this line:
Code:
   if ( global.wep[i,e_wep.have] == true ) draw_sprite(spr_weapon,  i, draw_x, draw_y);
you should put the draw_sprite in brackets, and add a draw_text with it .. make it draw the ammo value at the same location

what we also could do is to have it highlight the selected weapon .. maybe by drawing a different sprite if (i=current_weapon) .. or change the blend mode

EDIT: oh, how do you want to draw the weapon on your character.. if you just want to draw the gun sprite on top of him then you could just add the gun sprite to the weapon array:
global.wep[0, e_wep.gun_sprite] = SPRITE;
and in the draw event of your character:
GML:
draw_self()
draw_sprite(global.wep[obj_control.current_weapon, e_wep.gun_sprite],0,x,y)
but you might want to use draw_sprite_ext so you can flip the gun with image_xscale
 
Last edited:
Top