PDA

View Full Version : Critical bug - GivePlayerWeapon


[BEP]AcerPilot
04/07/2011, 12:39 PM
I noticed a few days ago that the function "GivePlayerWeapon" is bugged. Not the whole function, but it's last parameter, "ammo". I have this code in my script:

GivePlayerWeapon(playerid, 32, 20);

It would give me a Tec9 with 20 bullets, but instead of 20 it gives me 520 bullets (420-100)! I think it's value is mixing with other weapons value, because when I bought the Tec9 on ammunation (I have weapon buy system), I was holding an Desert Eagle with 500 bullets (I wanted to be 500, not bug).

When I have no weapon it gives me the 20 bullets, withouth the additional 500.

I hope this can be fixed as soon as possible, because for a RP servers it's very bad having more bullets than you deserve to, as you only paid for 20 bullets.

cessil
05/07/2011, 04:23 AM
I don't think i understand your problem fully, it sounds like you're saying you get 500 extra ammo when you have a deagle with 500 ammo.
If you have an smg with 500 bullets and buy a tec 9 with 20 then yes you'll get 520 ammo for the tec 9, there are simple work arounds for this and is a GTA SA thing

leong124
05/07/2011, 05:05 AM
If you have a weapon in that slot already, you ammo will be added.
For example if you have an MP5 with 500 ammo, and you give the player a UZI with 500 ammo,
he will have a UZI of 1000 ammo.
The solution is to store their current weapons, reset their weapons, and give them back with the new ammo.

So to conclude, this is not a bug.

Roland45
05/07/2011, 05:49 AM
OR you can play as the ammo were compatible for the other weapon

[BEP]AcerPilot
06/07/2011, 04:16 AM
Hum.. Ok, thanks.

@Leong: how would I do what you recommended? Because if I do GivePlayerWeapon the ammo wouldn't be added again?

leong124
06/07/2011, 04:38 AM
Firstly use GetPlayerWeaponData to get all the weapons of a player.
Then You can use ResetPlayerWeapons to clear his weapons.
After that you give them back all the weapons they have, except the weapon you wanted to give them.
Finally you can give the weapon you want to give to him.

[BEP]AcerPilot
06/07/2011, 10:53 PM
Thanks for your answer Leong. I did what you recommended but didn't work. Take a look at my code:

stock GivePlayerWeaponEx(playerid, gun, ammo)
{
new weapons[13], ammovar[13];

for(new i = 0; i < 13; i++)
{
GetPlayerWeaponData(playerid, i, weapons[i], ammovar[i]);
}

ResetPlayerWeapons(playerid);

for(new i = 0; i < 13; i++)
{
GivePlayerWeapon(playerid, weapons[i], ammovar[i]);
}

GivePlayerWeapon(playerid, gun, ammo);
}

OBS for admins: I think this topic should be renamed to "How to fix GivePlayerWeapon bug" and should be moved to "Scripting Discussion".

leong124
07/07/2011, 04:46 AM
AcerPilot;1279629']Thanks for your answer Leong. I did what you recommended but didn't work. Take a look at my code:

stock GivePlayerWeaponEx(playerid, gun, ammo)
{
new weapons[13], ammovar[13];

for(new i = 0; i < 13; i++)
{
GetPlayerWeaponData(playerid, i, weapons[i], ammovar[i]);
}

ResetPlayerWeapons(playerid);

for(new i = 0; i < 13; i++)
{
GivePlayerWeapon(playerid, weapons[i], ammovar[i]);
}

GivePlayerWeapon(playerid, gun, ammo);
}

OBS for admins: I think this topic should be renamed to "How to fix GivePlayerWeapon bug" and should be moved to "Scripting Discussion".

You'll need to find the slot of the weapon.
For example if a player have an MP5 and you want to give him a UZI, which both are in slot 4, you'll have to do this:
stock GivePlayerWeaponEx(playerid, gun, ammo)
{
new weapons[13], ammovar[13];

for(new i = 0; i < 13; i++)
{
GetPlayerWeaponData(playerid, i, weapons[i], ammovar[i]);
}

ResetPlayerWeapons(playerid);

for(new i = 0; i < 13; i++)
{
if(i != 4) GivePlayerWeapon(playerid, weapons[i], ammovar[i]);// 4 is the slot for MP5 and UZI. You'll need to make a function to find the slots of the weapon you want to give, and replace with the number 4.
}

GivePlayerWeapon(playerid, gun, ammo);
}

Check it out:http://wiki.sa-mp.com/wiki/Weapons

BigETI
07/07/2011, 05:21 AM
That could help you:
#define INVALID_WEAPON_SLOT_ID -1

stock SetPlayerWeapon(playerid, weapon, ammo)
{
new tweapon[13], tammo[13];
for(new i = 0; i < 13; i++) if(GetWeaponSlot(weapon) != i) GetPlayerWeaponData(playerid, i, tweapon[i], tammo[i]);
tweapon[GetWeaponSlot(weapon)] = weapon;
tammo[GetWeaponSlot(weapon)] = ammo;
ResetPlayerWeapons(playerid);
for(new i = 0; i < 13; i++) GivePlayerWeapon(playerid, tweapon[i], tammo[i]);
SetPlayerArmedWeapon(playerid, weapon);
}

stock GetWeaponSlot(weaponid)
{
new slot;
switch(weaponid)
{
case 0,1: slot = 0;
case 2..9: slot = 1;
case 22..24: slot = 2;
case 25..27: slot = 3;
case 28,29,32: slot = 4;
case 30,31: slot = 5;
case 33,34: slot = 6;
case 35..38: slot = 7;
case 16..18,39: slot = 8;
case 41..43: slot = 9;
case 10..15: slot = 10;
case 44..46: slot = 11;
case 40: slot = 12;
default: slot = INVALID_WEAPON_SLOT_ID;
}
return slot;
}

Usage: SetPlayerWeapon(playerid, weapon, ammo);
Example: SetPlayerWeapon(playerid, 32, 20);
This stock will just set the players weapon ID and ammo instead of increasing the ammo.

[BEP]AcerPilot
07/07/2011, 10:59 AM
OK, thanks guys. I'll test the codes.

#EDIT: Worked. Thanks for all that answered in here. Admins can lock this topic if they want to.

#EDIT2: I just noticed when I put GivePlayerWeaponEx in the stock that logs in the player when he types /login, the server stop working. All commands are 'Server: Unknown Command' and all the functions that should be executed after GivePlayerWeaponEx aren't executed. I think it's because it's the first time he will receive the weapons. Suggestions?

leong124
08/07/2011, 04:54 AM
There should be crashing. Could you please show the GivePlayerWeaponEx code?

[BEP]AcerPilot
08/07/2011, 11:38 AM
Of couse, it's here:

stock GivePlayerWeaponEx(playerid, weapon, ammo)
{
new tweapon[13], tammo[13], count = 0, slot = GetWeaponSlot(weapon);

for(new i = 0; i < 13; i++)
{
if(slot != i)
{
GetPlayerWeaponData(playerid, i, tweapon[i], tammo[i]);

if(tweapon[i] == 0)
{
count++;
}
}
}

if(count >= 12)
{
return GivePlayerWeapon(playerid, weapon, ammo);
}
else
{
tweapon[slot] = weapon;
tammo[slot] = ammo;

ResetPlayerWeapons(playerid);

for(new i = 0; i < 13; i++)
{
GivePlayerWeapon(playerid, tweapon[i], tammo[i]);
}

SetPlayerArmedWeapon(playerid, weapon);
}

return 1;
}

I tried to make a fix to it. I created the 'count', and then, in the loop, if the weapon returned from GetPlayerWeaponData was equal to zero, count increments. Then I check if count is equal or bigger than 12 to check if the player has no weapons. If it's true, it returns the GivePlayerWeapon standard function, else, if he has a weapon, do the GivePlayerWeaponEx's fix code, but it didn't worked, also.

leong124
09/07/2011, 01:26 AM
Seems that the code has no problem here.
Do you pass constants to this function?
Also, try to print out something inside this function and see which part of it crashes.

[BEP]AcerPilot
09/07/2011, 01:34 AM
No, no constants. I analised the code for some time and it's counting only the weapons that aren't from the passed function's weapon slot, because it's inside "slot != i". To catch all weapons, we would need to make a new loop to loop through all weapons, not only the ones that aren't from the passed weapon's slot. It would be like this:

stock GivePlayerWeaponEx(playerid, weapon, ammo)
{
new tweapon[13], tammo[13], count = 0, slot = GetWeaponSlot(weapon);

for(new i = 0; i < 13; i++)
{
GetPlayerWeaponData(playerid, i, tweapon[i], tammo[i]);

if(tweapon[i] == 0)
{
count++;
}
}

if(count >= 12)
{
return GivePlayerWeapon(playerid, weapon, ammo);
}
else
{
for(new i = 0; i < 13; i++)
{
if(slot != i)
{
GetPlayerWeaponData(playerid, i, tweapon[i], tammo[i]);

if(tweapon[i] == 0)
{
count++;
}
}
}

tweapon[slot] = weapon;
tammo[slot] = ammo;

ResetPlayerWeapons(playerid);

for(new i = 0; i < 13; i++)
{
GivePlayerWeapon(playerid, tweapon[i], tammo[i]);
}

SetPlayerArmedWeapon(playerid, weapon);
}

return 1;
}

I will test that later, then I report the results here.

About the function, it has 3 loops just for giving a weapon to a player, isn't there any way to improve that code? It seems to be deprecated.

leong124
12/07/2011, 02:31 AM
Actually you don't need to loop for the count, and loop for the same code twice.
If the player has no weapons, nothing is wrong even you use
GivePlayerWeapon(playerid, tweapon[i], tammo[i]);
because the two arrays are all initialised as 0 (Fist).

There's no point to get all the weapons also. The "slot != i" is used to escape from the weapon slot that is the same as the slot of the weapon that you want to give, therefore getting the weapon data about that slot is useless.

Probably the value passed into this function (weapon and ammo) is wrong that crashes the server, or the GetWeaponSlot returns invalid values. Check it or show it here.

There's is a faster method.
Firstly you can find out the slot of the weapon you give. Then check if that slot has weapon already, remove it and finally give the new weapon to the player.

[BEP]AcerPilot
23/07/2011, 01:18 AM
I just re-made the function and now it looks like:

stock GivePlayerWeaponEx(playerid, weapon, ammo)
{
new tweapon[13], tammo[13], slot = GetWeaponSlot(weapon);

for(new i = 0; i < 13; i++)
{
if(slot != i)
{
printf("Saving weapon %i with %i of ammo from slot %i.", tweapon[i], tammo[i], i);

GetPlayerWeaponData(playerid, i, tweapon[i], tammo[i]);
}
}

ResetPlayerWeapons(playerid);

tweapon[slot] = weapon;
tammo[slot] = ammo;

for(new i = 0; i < 13; i++)
{
printf("Giving back weapon %i with %i of ammo on slot %i.", tweapon[i], tammo[i], i);

GivePlayerWeapon(playerid, tweapon[i], tammo[i]);
}

SetPlayerArmedWeapon(playerid, weapon);

return 1;
}

It's working, I'm working on a system for GVPEx to detect when the player isn't holding any weapons and call the standard GVP, so I can define all GivePlayerWeapon to GivePlayerWeaponEx.

leong124
23/07/2011, 04:26 AM
Alright. This should work for all GivePlayerWeapon IMHO.
Imagine if a player has no weapons, the weapon IDs got from GetPlayerWeaponData will be 0.
Therefore this will not cause bug on this, as you are only giving fist(s) to the player.