SA-MP Forums Archive
[Tutorial] OnPlayerWeaponChange::OnPlayerAmmoChange::Weapon_A C - Printable Version

+- SA-MP Forums Archive (https://sampforum.blast.hk)
+-- Forum: Non-English (https://sampforum.blast.hk/forumdisplay.php?fid=9)
+--- Forum: Languages (https://sampforum.blast.hk/forumdisplay.php?fid=33)
+---- Forum: Русский/Russian (https://sampforum.blast.hk/forumdisplay.php?fid=32)
+----- Forum: Релизы/Releases (https://sampforum.blast.hk/forumdisplay.php?fid=66)
+----- Thread: [Tutorial] OnPlayerWeaponChange::OnPlayerAmmoChange::Weapon_A C (/showthread.php?tid=450993)



OnPlayerWeaponChange::OnPlayerAmmoChange::Weapon_A C - Seregamil1 - 15.07.2013

Добрый день!

В общем данное решение позволит использовать такие каллбэки как OnPlayer(Weapon/Ammo)Change

Функции скрипта

PHP Code:
    OnPlayerWeaponChange проверяеткогда игрок сменил оружие
    OnPlayerAmmoChange 
проверяеткогда игрок изменил патроны
    giveWeapon 
выдать игроку то или иное оружие
    getAmmo 
узнать кол-во патронов по ID оружия
    giveAmmo 
выдать то или иное кол-во патронов игроку по ID оружия
    setAmmo 
установить то или иное кол-во патронов игроку по ID оружия
    resetWeapons 
аннулировать оружие у игрока
    weapon_slot 
узнать слот оружия по его ID 
Говорю сразу, есть функции, которые вам покажутся пабликовскими и т.д., но писал я их сам лично, используя лишь сборку моделек, т.к. у меня небыло инета 2 недели)

Важно:

PHP Code:
    Одна недоработка неуспевает определить скорость смены патронов с точностью до 1
        у минигана
огнеметатеков
    При коннекте следует обнулять оружие у игроков
    И советую не делать что
-то подобное#define GivePlayerWeapon giveWeapon,
        
т.кчит использует именно стандартные функции,
        
а в данной ситуации вы приравняете серверные к стандартным и все пойдет не по плану 
Сам скрипт:

PHP Code:
#include a_samp
#define dcmd(%1,%2,%3) if((strcmp((%3)[1],#%1,true,(%2))==0)&&((((%3)[(%2)+1]==0)&&(dcmd_%1(playerid,"")))||(((%3)[(%2)+1]==32)&&(dcmd_%1(playerid,(%3)[(%2)+2]))))) return 1
#define CMD(%0) if (strcmp(%0, cmdtext, true, strlen(%0)) == 0)
forward OnPlayerWeaponChange(playeridold_weaponnew_weapon);
forward OnPlayerAmmoChange(playeridold_ammonew_ammo);
forward AC_Detect();
main(){}
new 
last_weapons[MAX_PLAYERS char];
new 
ammo_slot[MAX_PLAYERS][13];
public 
OnGameModeInit(){
    
SetTimer("AC_Detect",20,true);
    return 
1;
}
public 
AC_Detect(){
    for(new 
playerid;playerid!=GetMaxPlayers();playerid++){
        if(
IsPlayerConnected(playerid) == || IsPlayerNPC(playerid)) continue;
        if(
GetPlayerAmmo(playerid) > getAmmo(playerid,GetPlayerWeapon(playerid))) resetWeapons(playerid);//weapon_anti-cheat
        
if(GetPlayerWeapon(playerid) != last_weapons{playerid}) OnPlayerWeaponChange(playerid,last_weapons{playerid}, GetPlayerWeapon(playerid));
        if(
GetPlayerWeapon(playerid) == last_weapons{playerid} && GetPlayerAmmo(playerid) != ammo_slot[playerid][weapon_slot(GetPlayerWeapon(playerid))]) OnPlayerAmmoChange(playeridammo_slot[playerid][weapon_slot(GetPlayerWeapon(playerid))], GetPlayerAmmo(playerid));
    }
}
public 
OnPlayerAmmoChange(playeridold_ammonew_ammo){//by Seregamil
    //  playerid - игрок, у которого сменились патроны в слоте
    //  old_ammo - прошлое кол-во патронов
    //  new_ammo - новое кол-во патронов
    
    
new str[128];
    
format(str,128,"{00ff00}OnPlayerAmmoChange: Игрок: %d | Оружие: %d (Слот: %d) | Старое значение: %d | Новое: %d",playeridGetPlayerWeapon(playerid), weapon_slot(GetPlayerWeapon(playerid)), old_ammonew_ammo);
    
SendClientMessageToAll(-1,str);
    
    
ammo_slot[playerid][weapon_slot(GetPlayerWeapon(playerid))] = new_ammo;
}
public 
OnPlayerWeaponChange(playeridold_weaponnew_weapon){//by Seregamil
    //    playerid - игрок, сменивший оружие
     //    old_weapon - оружие, которое сменили
    //  new_weapon - оружие, на которое сменили
    
new ammo_oldokda;
    
GetPlayerWeaponData(playeridweapon_slot(old_weapon), okdaammo_old);
    
giveAmmo(playeridold_weapon, -((getAmmo(playeridold_weapon)-ammo_old)));
    new 
str[128];
    
format(str,128,"OnPlayerWeaponChange: Игрок: %d, Старое оружие: %d, Новое оружие: %d, Значение патронов в анти-чите: %d",playerid,old_weapon,new_weapon,getAmmo(playerid,old_weapon));
    
SendClientMessageToAll(-1,str);
    
last_weapons{playerid} = new_weapon;//установим на старое оружие то, которое сейчас в руках
}
public 
OnPlayerConnect(playerid){
    
resetWeapons(playerid);
    return 
1;
}
public 
OnPlayerCommandText(playeridcmdtext[])
{
    
CMD("/gun_1") return giveWeapon(playerid,random(39),500);
    
CMD("/ammo") return setAmmo(playerid,24,375);
    
dcmd(gun,3,cmdtext);
    return 
0;
}
dcmd_gun(playerid,params[]) return GivePlayerWeapon(playerid,strval(params),random(435));
giveWeapon(playeridweaponidammo){//by Seregamil
    
new use_weap[100];
    
format(use_weap,100,"ac_weapon_%d",weapon_slot(weaponid));
    
SetPVarInt(playerid,use_weap,GetPVarInt(playerid,use_weap)+ammo);
    
    return 
GivePlayerWeapon(playerid,weaponidammo);
}
getAmmo(playeridweaponid){ //by Seregamil
    
new use_weap[100];
    
format(use_weap,100,"ac_weapon_%d",weapon_slot(weaponid));
    return 
GetPVarInt(playerid,use_weap);
}
giveAmmo(playeridweaponidammo){//by Seregamil
    
new use_weap[100];
    
format(use_weap,100,"ac_weapon_%d",weapon_slot(weaponid));
    
SetPVarInt(playerid,use_weap,GetPVarInt(playeriduse_weap)+ammo);
}
setAmmo(playerid,weaponidammo){//by Seregamil
    
new use_weap[100];
    
format(use_weap,100,"ac_weapon_%d",weapon_slot(weaponid));
    
SetPVarInt(playerid,use_weap,ammo);
    return 
SetPlayerAmmo(playerid,weaponidammo);
}
weapon_slot(weaponid){//by Seregamil
    
switch(weaponid){
        case 
0,1:         return 0;
        case 
2..9:         return 1;
        case 
22..24:     return 2;
        case 
25..27:     return 3;
        case 
28,29,32:     return 4;
        case 
30,31:     return 5;
        case 
33,34:     return 6;
        case 
35..38:    return 7;
        case 
16..18:    return 8;
        case 
41..43:     return 9;
        case 
10..15:    return 10;
        case 
44..46:    return 11;
        case 
40:        return 12;
    }
    return -
1;
}
resetWeapons(playerid){//by Seregamil
    
new clear[128];
    for(new 
i;i!=13;i++){
        
format(clear,sizeof clear,"ac_weapon_%d",i);
        
SetPVarInt(playerid,clear,0);
     }
    return 
ResetPlayerWeapons(playerid);

При использовании данной системы следует заменить все GivePlayerWeapon | ResetPlayerWeapons | SetPlayerAmmo на giveWeapon | resetWeapons | setAmmo соответственно!

Автор: Seregamil


Re: OnPlayerWeaponChange::OnPlayerAmmoChange::Weapon_A C - -Stranger- - 15.07.2013

Quote:

...
OnPlayerWeaponChange - проверяет, когда игрок сменил оружие
OnPlayerAmmoChange - проверяет, когда игрок изменил патроны
...

Может это колбеки? И если это так, то они ничего не проверяют а вызываться когда происходит событие...


Re: OnPlayerWeaponChange::OnPlayerAmmoChange::Weapon_A C - stabker - 15.07.2013

Другой вариант (не компилил, могут быть ошибки)

pawn Code:
public OnPlayerUpdate(playerid)
{
    static Ammo[MAX_PLAYERS], Weap[MAX_PLAYERS], dammo = GetPlayerAmmo(playerid), dweap = GetPlayerWeapon(playerid);
    if(Ammo[playerid] != dammo && Weap[playerid] == dweap[playerid])
    {
        CallLocalFunction("OnPlayerAmmoChange", "dddd", playerid, Weap[playerid], Ammo[playerid], dammo[playerid]);
        Ammo[playerid] = dammo;
    }
    if(Weap[playerid] != dweap)
    {
        CallLocalFunction("OnPlayerWeaponChange", "ddddd", playerid, Weap[playerid], Ammo[playerid], dweap[playerid], dammo[playerid]);
        Ammo[playerid] = dammo, Weap[playerid] = dweap;
    }
}

forward OnPlayerAmmoChange(const playerid, const weapon, const oldammo, const newammo);
public OnPlayerAmmoChange(const playerid, const weapon, const oldammo, const newammo)
{
}

forward OnPlayerWeaponChange(const playerid, const oldweapon, const oldammo, const newweapon, const newammo);
public OnPlayerWeaponChange(const playerid, const oldweapon, const oldammo, const newweapon, const newammo)
{
}



Re: OnPlayerWeaponChange::OnPlayerAmmoChange::Weapon_A C - Stepashka - 15.07.2013

Только вот это не Tutorial.


Re: OnPlayerWeaponChange::OnPlayerAmmoChange::Weapon_A C - Seregamil1 - 16.07.2013

Quote:

public OnPlayerUpdate(playerid)

Иногда неуспевает за оружием с быстрой скорострельностью
Quote:

Может это колбеки? И если это так, то они ничего не проверяют а вызываться когда происходит событие...

Quote:

использовать такие каллбэки как OnPlayer(Weapon/Ammo)Change




Re: OnPlayerWeaponChange::OnPlayerAmmoChange::Weapon_A C - White_116 - 16.07.2013

Quote:
Originally Posted by Seregamil1
View Post
Иногда неуспевает за оружием с быстрой скорострельностью
Нужно ли это?
Quote:

public OnPlayerUpdate(playerid)

он тем и хорош, что приносит те данные, которые нужно. В твоём случае лишний раз будет проверять и афк игроков. Да и очень частый вызов не так полезен для самого сервера в целом.


Re: OnPlayerWeaponChange::OnPlayerAmmoChange::Weapon_A C - stabker - 16.07.2013

Настаивать не буду, но, что-то я очень сомневаюсь, что OnPlayerUpdate, учитывая условия его вызова, может не успеть за обновлением патронов.

P.S. Только что посмотрел код внимательней и заметил, что вы очень часто вызываете нативные функции, при каждой проверке. Лучше создать переменную, записать туда данные полученные нативной функцией и уже обрабатывать их, это довольно быстрее. Не придираюсь, это просто полезный совет


Re: OnPlayerWeaponChange::OnPlayerAmmoChange::Weapon_A C - Richard_Gere - 16.07.2013

Лучше использовать OnPlayerUpdate, в таймере нужно учесть еще случаи когда игрок АФК, только заспавнился или вообще спавнился он или нет. Если не исключить игроков с GetPlayerState(playerid) == PLAYER_STATE_SPAWNED в таймере, то при спавне оружие будет пропадать. Именно из-за кучи проверок я перевел похожий способ обновления оружия на OnPlayerUpdate.