[SM] Случайное оружие

Тема в разделе "Программирование / Скриптинг", создана пользователем diller110, 2 фев 2015.

  1. diller110

    diller110

    Сообщения:
    138
    Симпатии:
    48
    Здравствуйте, помогите пожалуйста с кодом, а именно концепцией решения проблемы.
    Плагин выдает оружие при вводе команды, оружие выбирается рандомно, но не имеет ограничения за раунд.
    Набросок плагина вот:
    public Action:Command_DropJoke(client, args)
    {
    if (IsPlayerAlive(client)) {
    if (g_Drop == 1) {
    new String:DropWinner[MAX_NAME_LENGTH];
    GetClientName(client, DropWinner, sizeof(DropWinner));
    Client_RemoveAllWeapons(client);
    Client_SetMaxSpeed(client, 400.0);

    new DropRandom = GetRandomInt(0, 35);
    GivePlayerItem(client, Weapon_names[DropRandom]);
    CGOPrintToChatAll("%s {GRAY}выйграл %s! Попробуй и ты: !drop", DropWinner, Weapon_names[DropRandom]);
    g_Drop--;
    } else {
    CGOPrintToChat(client, "{GRAY}Вы уже использовали {LIGHTOLIVE}!drop{GRAY} в этом раунде.");
    }
    } else {
    CGOPrintToChat(client, "{GRAY}Вы не можете использовать {LIGHTOLIVE}!drop{GRAY}, если вы мертвы или в спектрах.");
    }
    return Plugin_Handled;
    }
    Для ограничения использования комманды я создал глобальную переменную g_Drop = 1, которая уменьшается на 1 при использовании команды и увеличивается на 1 при смерти.
    Но поскольку переменная глобальная и не привязана ни к чему, при использовании команды одним игроком, она, видимо, уменьшается и препятствует использованию другими игроками. На деле команда вообще никогда не работает, поскольку не выполняется условие g_Drop == 1.

    Дайте совет, как разделить переменную для каждого игрока(полный ноль на самом деле в этом), и прочие советы по реализации плагина. Заранее благодарю.
     

    Вложения:

    • drop.sp
      Размер файла:
      1,9 КБ
      Просмотров:
      4
    Последнее редактирование: 2 фев 2015
  2. FrozDark

    FrozDark Команда сайта HLMod Модератор

    Сообщения:
    1.761
    Симпатии:
    1.915
    прикрепляйте наброски к сообщениям в формате sp
     
  3. diller110

    diller110

    Сообщения:
    138
    Симпатии:
    48
    Т.е. мы создаем массив из Maxplayers игроков. Определяем все значения начальными 1-ами:
    new g_Drop[MAXPLAYERS+1] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1} Если на сервере например 10 максимум.
    Значит визуально массив выглядит так:
    g_Drop[0] = 1;
    g_Drop[1] = 1;
    g_Drop[n] = 1;....

    Тогда какое значение в [] подставлять для его изменения например в Event_PlayerDeath?
     
  4. AlmazON

    AlmazON деревянный © yand3xmail

    Сообщения:
    4.566
    Симпатии:
    1.988
    diller110, основу сделал ниже на примере с bool. Т.е. работает 1 раз за 1 жизнь:
    PHP:
    #include <sourcemod>
    #include <sdktools>
    #include <csgo_colors>
    #include <smlib>

    new const String:Weapon_names[36] [] = {
        
    "weapon_ak47""weapon_aug""weapon_bizon""weapon_deagle""weapon_decoy""weapon_elite""weapon_famas""weapon_fiveseven""weapon_flashbang",
        
    "weapon_g3sg1""weapon_galilar""weapon_glock""weapon_hegrenade""weapon_hkp2000""weapon_incgrenade""weapon_knife""weapon_m249""weapon_m4a1",
        
    "weapon_mac10""weapon_mag7""weapon_molotov""weapon_mp7""weapon_mp9""weapon_negev""weapon_nova""weapon_p250""weapon_p90""weapon_sawedoff",
        
    "weapon_scar20""weapon_sg556""weapon_smokegrenade""weapon_ssg08""weapon_taser""weapon_tec9""weapon_ump45""weapon_xm1014"
    };
    new 
    bool:g_Drop[MAXPLAYERS+1];

    public 
    Plugin:myinfo =
    {
        
    name "Drop",
    }

    public 
    OnPluginStart()
    {
        
    RegConsoleCmd("sm_drop"Command_DropJoke"Joke with Drop command");
        
    HookEvent("player_death"Event_PlayerDeath);
    }
    public 
    Action:Command_DropJoke(clientargs)
    {
        if (
    client)
        {
            if (
    IsPlayerAlive(client))
            {
                if (
    g_Drop[client]) CGOPrintToChat(client"{GRAY}Вы уже использовали {LIGHTOLIVE}!drop{GRAY} в этом раунде.");
                else
                {
                    
    g_Drop[client] = true;
                    
    decl String:DropWinner[MAX_NAME_LENGTH];
                    
    GetClientName(clientDropWinnerMAX_NAME_LENGTH);
                    
    Client_RemoveAllWeapons(client);
                    
    Client_SetMaxSpeed(client400.0);
                    
                    new 
    DropRandom GetRandomInt(035);
                    
    GivePlayerItem(clientWeapon_names[DropRandom]);
                    
    CGOPrintToChatAll("%s {GRAY}выйграл %s! Попробуй и ты: !drop"DropWinnerWeapon_names[DropRandom]);
                }
            }
            else 
    CGOPrintToChat(client"{GRAY}Вы не можете использовать {LIGHTOLIVE}!drop{GRAY}, если вы мертвы или в спектрах.");
        }
        return 
    Plugin_Handled
    }
    public 
    Event_PlayerDeath(Handle:eventString:name[], bool:dontBroadcastg_Drop[GetClientOfUserId(GetEventInt(E"userid"))] = false;
     
    diller110 нравится это.
  5. diller110

    diller110

    Сообщения:
    138
    Симпатии:
    48
    Спасибо за советы! На самом деле я тоже сделал только основу, первый плагин, коплю опыт. Вопросов попутно только больше...

    В основном Actione проиндексировал g_Drop по примеру из PlayerDeath:
    g_Drop[GetClientOfUserId(GetEventInt(Event_PlayerDeath, "userid"))
    Все хорошо только несоответствие tag выдает, как предупреждение(warning 213). Наверно не страшно, но интересно как исправить.

    Еще вопрос, значение decl String:DropWinner[MAX_NAME_LENGTH]; "задекларировали", для чего это нужно?

    И еще вопрос, if (client) {..} как понимаю это защита от ввода команды с сервера?

    И еще вопросик, sm_drop стандартная sm команда, которая кидает вещи, причем странным образом. При вводе команды уже с моим плагином, она конечно выполняется, но в чат помимо моего вводится мол вы ввели команду не корректно, правильно sm_drop target weapon, можно ли скрыть это сообщение, или вообще заблокировать стандартное выполнение. Не очень надо конечно, но интересно.
     
  6. AlmazON

    AlmazON деревянный © yand3xmail

    Сообщения:
    4.566
    Симпатии:
    1.988
    Создан массив bool переменных, а ты, видимо, пытаешься править в int. Убери bool: в самом начале.
    Выше скорость, короче говоря. Меньше задержка для создания массива.
    Да.
     
    diller110 нравится это.
  7. diller110

    diller110

    Сообщения:
    138
    Симпатии:
    48
    bool убрал, ошибка оставалась, добавил к GetEventInt(Event_PlayerDeath, "userid")
    Handle: перед Event_PlayerDeath, ошибка исчезла, хотя объяснить почему не смогу.
    Спасибо, очень познавательный урок!)
     
  8. AlmazON

    AlmazON деревянный © yand3xmail

    Сообщения:
    4.566
    Симпатии:
    1.988
    Конечно нужен Handle события, я просто копирнул у себя и забыл подставить твоё название) Оффтоп
     
  9. diller110

    diller110

    Сообщения:
    138
    Симпатии:
    48
    Еще нужна помощь. Как лучше реализовать выдачу оружия. Первый раз была отчистка всего инвертаря с помощью smlib функции Client_RemoveAllWeapons(client, "weapon_c4"); (все кроме бомбы), а потом выдача ножа - GivePlayerItem(client, Weapon_names[15]); и уже рандомного оружия.

    Но возникает ощущение незаконченности и вообще недоделки, т.к. при дропе удаляется все оружие, было ли у вас AWP, или просто глок.

    Как лучше реализовать выдачу? В smlib есть несколько функций например: Client_EquipWeapon(client, weapon) и Client_GiveWeapon(client, className[]). В первом случае нужен weapon - Entity index of the weapon, в втором className[] - weapon classname string. В обоих случаях не знаю где эти значения взять.

    ____
    Вообще проблема с Entity. Кусок кода, который я любезно одолжил не помню откуда:
    new const String:Weapon_names[36] [] = {
    "weapon_ak47", "weapon_aug", "weapon_bizon", .... Дает нам Weapon_Names(Source), это уже Entity?, если да то как получить их Index?
     
  10. AlmazON

    AlmazON деревянный © yand3xmail

    Сообщения:
    4.566
    Симпатии:
    1.988
    GivePlayerItem - нужен classname (название) оружия. Берём просто из составленного тобой списка выдаваемого оружия текущее оружие и всё - никаких smlib не требуется! Так в чём же состоит задача? Узнать, какое оружие в руках у игрока или вообще какое он с собой носит (в слотах)?
     
  11. diller110

    diller110

    Сообщения:
    138
    Симпатии:
    48
    GivePlayerItem как я понимаю просто кидает предмет под игрока, и игрок его берет, если у него свободны слот. Если нет оружие просто падает под ноги. Я бы хотел, чтобы оружие в рука заменялось оружием дропа.
    Как вариант, в массиве найти все строки с основным оружием и вторичным, и для каждого условие сделать типо сначала удалить оружие для этого слота потом выкинуть.
    Но как-то такое решение в лоб не красиво выглядит.
    EquipPlayerWeapon - думаю подошел бы, однако незнаю как получить для него аргумент
    weapon - CBaseCombatWeapon entity index.
     
  12. AlmazON

    AlmazON деревянный © yand3xmail

    Сообщения:
    4.566
    Симпатии:
    1.988
    Нет, не кидает, если слот даваемого оружия пустой.
    Тогда узнаём оружие игрока в нужном слоте (основное/вторичное), удаляем и GivePlayerItem - если основное, то оно уже будет в руках, а если вторичное - появится сразу после переключения на него. Под ногами ничего не будет. Только дефуз так выдаётся, а оружие - нет.
    Написал бы теперь пример, да боюсь, без встраивания в твой код опять возникнут вопросы.
     
    diller110 нравится это.
  13. TolikCorp

    TolikCorp

    Сообщения:
    855
    Симпатии:
    271
    Кстати, лучше на спавне изменять значение g_Drop[бла бла] = false;
     
    diller110 нравится это.
  14. AlmazON

    AlmazON деревянный © yand3xmail

    Сообщения:
    4.566
    Симпатии:
    1.988
    Верно. Тогда не нужно ловить дисконнект игрока - состояние переменной всегда будет актуальным.
     
    diller110 нравится это.
  15. diller110

    diller110

    Сообщения:
    138
    Симпатии:
    48
    Да спасибо за совет. Только поставил на начало раунда.

    Дела обстоят так. Команда GivePlayerItem(client, Weapon_names[DropRandom]);
    Предмет кидается в мир под игрока, если слот пустой он разумеется его берет. Если например с прошлого раунда оружие осталось, то предмет падает под ноги. Я бы хотел сделать замену предмета из инвертаря на предмет рандома.

    Как получить информацию об определенном слоте оружия? Я попробывал вот так: (С помощью smlib)
    new Primary = Client_GetWeaponBySlot(client, 1);
    new Secondary = Client_GetWeaponBySlot(client, 2);
    CGOPrintToChat(client, "Индекс вашего первого оружия: %d. Индекс второго: %d.", Primary, Secondary);

    _____________
    После некоторых манипуляция получилось получить, то что я хотел.
    GetEntityClassname(Client_GetWeaponBySlot(client, slot);
    где слот: 0 - основное оружие, 1 - пистолеты, 2 - нож.

    Осталось сделать условия для определенных id из массива с названиями оружия. Хотя уверен есть способы сделать все более просто.

    Есть способ получить тип предмета? Например weapon_ak47 - primary_weapon,
    weapon_p2000 - pistol, weapon_knife - knife.
     
  16. AlmazON

    AlmazON деревянный © yand3xmail

    Сообщения:
    4.566
    Симпатии:
    1.988
    diller110, так можно:
    PHP:
    #include <cstrike>
    #include <sdktools_functions>
    #include <sdktools_entinput>


    new Primary GetPlayerWeaponSlot(clientCS_SLOT_PRIMARY);
    if (
    Primary != -1)
    {
        
    //RemovePlayerItem(client, Primary);
        
    AcceptEntityInput(Primary"Kill");
        
    CGOPrintToChat(client"В 1 слоте находилось оружие с индексом %i."Primary);
    }
    else
    {
        
    CGOPrintToChat(client"Ваш слот первичного оружия пуст!");
    }
    if (
    GivePlayerItem(clientWeapon_names[DropRandom]) != -1)
    {
        
    CGOPrintToChat(client"У вас %sбыло оружия! Вам было выдано: %s."Primary != -"":"НЕ "Weapon_names[DropRandom]);
    }
    else
    {
        
    CGOPrintToChat(client"Не удалось выдать оружие: %s (не существует в текущей игре!)."Weapon_names[DropRandom]);
    }
    Так же и с вторичным оружием, только слот меняешь (CS_SLOT_PRIMARY на CS_SLOT_SECONDARY).
     
    Последнее редактирование: 6 фев 2015
  17. R1KO

    R1KO Супер-модератор

    Сообщения:
    5.999
    Симпатии:
    2.992
    AlmazON, слоты:
    0 - основное (автоматы, снайперки),
    1 - вторичное (пистолеты)
    2 - нож
    3- гранаты
    4 - с4
     
    diller110 нравится это.
  18. TolikCorp

    TolikCorp

    Сообщения:
    855
    Симпатии:
    271
    Выдержка из cstrike.inc:
    PHP:
    #define CS_SLOT_PRIMARY        0    /**< Primary weapon slot. */
    #define CS_SLOT_SECONDARY    1    /**< Secondary weapon slot. */
    #define CS_SLOT_KNIFE        2    /**< Knife slot. */
    #define CS_SLOT_GRENADE        3    /**< Grenade slot (will only return one grenade). */
    #define CS_SLOT_C4            4    /**< C4 slot. */
    Тем более, что уже подключено: #include <cstrike>
     
    diller110 и AlmazON нравится это.
  19. diller110

    diller110

    Сообщения:
    138
    Симпатии:
    48
    Всем спасибо! Теперь все работает так, как должно работать)

    А есть еще что-нибудь в документации по поводу classname или к чему принадлежат названия типа: weapon_awp, weapon_knife.
    А то сейчас вывожу в чат оружие которым убили и помимо стандартных из: https://wiki.alliedmods.net/Counter-Strike:_Global_Offensive_Weapons , например вместо weapon_m4a1 выводит weapon_m4a1_silenced, вместо weapon_knife - knife_butterfly(из плагина knife choise). Где можно увидеть полный список подобных названий?
     
    Последнее редактирование: 6 фев 2015
  20. TolikCorp

    TolikCorp

    Сообщения:
    855
    Симпатии:
    271
    Лучше пролистай все стандартные инклуды.
    Учись по примерам, открой тот же WeaponRestrict - там гигантское множество трюков с пушками, логики и прочего.
     
    diller110 нравится это.