Archived copy of war3source.com, the War3Source forum (2009–2020), rebuilt from the Internet Archive by wc3mods.net. This page was captured on 2012-10-25 (original capture). Forum · All archived topics · Wiki · Bug tracker · Blog
Chat

War3:Source
October 24, 2012, 07:18:25 PM *
Welcome, Guest. Please login or register.
Did you miss your activation email?

Login with username, password and session length
News: Download: http://war3source.com/index.php?board=9.0
What is War3Source?: http://war3source.com/index.php?topic=200.0
Sample Stats: http://war3source.com/war3stats
Steam Community Group: http://steamcommunity.com/groups/war3source
War3Source SVN Checkout: http://ownageclan.com/svn/war3source/
War3Source servers: http://www.game-monitor.com/search.php?vars=war3_version=
 
   Home   Help Search Login Register  
Pages: [1] 2
  Print  
Author Topic: [Russian] смена оружия (и всё что с ним связано)  (Read 992 times)
Arturius
Moderator
Full Member
*****
Posts: 155



View Profile Email
« on: October 27, 2011, 02:33:20 AM »

Прошу помощи у знающих людей, так как своего ума ещё не нарастил Cheesy.
У расы Strider Hiryu во время работы абилити совершается полёт, во время которого он становится невидимым и оружие должно сменятся на нож. А после завершения абилити, оружие должно возвращаться. И вот именно в этой смене загвоздка. В коде это реализовано так:
Code:
//Объявлены глобальные переменные
new String:Temp1[MAXPLAYERS][32], String:Temp2[MAXPLAYERS][32];

//Далее в коде абилити при нажатии кнопки
...
new wep1 = GetPlayerWeaponSlot( client, CS_SLOT_PRIMARY );
new wep2 = GetPlayerWeaponSlot( client, CS_SLOT_SECONDARY );
new wep3 = GetPlayerWeaponSlot( client, 2 );

EquipPlayerWeapon( client, wep3 );

if( IsValidEdict( wep1 ) )
GetEdictClassname( wep1, Temp1[client], 32 );

if( IsValidEdict( wep2 ) )
GetEdictClassname( wep2, Temp2[client], 32 );

if( IsValidEdict( wep1 ) )
UTIL_Remove( wep1 );

if( IsValidEdict( wep2 ) )
UTIL_Remove( wep2 );

War3_WeaponRestrictTo( client, thisRaceID, "weapon_knife" );
...

//Далее в коде абилити при отпускании кнопки
...
GivePlayerItem( client, Temp1[client] );
GivePlayerItem( client, Temp2[client] );
...

Загвоздка в том, что new wep3 = GetPlayerWeaponSlot( client, 2 ); не работает, т.к. слот 2 в cstrike.inc никак не обозначен и вызывает ошибку. Я закомментировал строки new wep3 = GetPlayerWeaponSlot( client, 2 ); и EquipPlayerWeapon( client, wep3 );, но эффекта не достиг. Кроме того, даже выбросив оружие во время игры до включения абилити, после завершения абилити оно возвращается. Так ведь можно сбросить кому-то авп, включить абилку и получить себе новую бесплатно Cheesy. Подскажите, как возможно с этим справиться?
« Last Edit: November 04, 2011, 12:09:53 PM by Arturius » Logged
Frenzzy
Moderator
Full Member
*****
Posts: 217


337905984 frenzzy@live.ru
View Profile WWW
« Reply #1 on: October 30, 2011, 02:28:36 PM »

Weapon Slot 2 - в ксс это нож
Quote
#define CS_SLOT_PRIMARY            0      /**< Primary weapon slot. */
#define CS_SLOT_SECONDARY        1      /**< Secondary weapon slot. */
#define CS_SLOT_MELEE                2      /**< Melee weapon slot (knife). */
#define CS_SLOT_GRENADE            3      /**< Grenade slot (will only return one grenade). */
#define CS_SLOT_C4                     4      /**< C4 slot. */

Вместо
new wep3 = GetPlayerWeaponSlot(client, 2);
EquipPlayerWeapon(client, wep3);
используй
FakeClientCommand(client, "use weapon_knife");
чтобы игрок переключился на нож.

War3_WeaponRestrictTo(client, thisRaceID, "weapon_knife");
Эта функция принудительно выбрасывает у игрока все оружие кроме ножа. Eсли хочешь забрать у игрока оружие, используй RemovePlayerItem() перед этим.
Logged

O_o
Arturius
Moderator
Full Member
*****
Posts: 155



View Profile Email
« Reply #2 on: October 30, 2011, 03:06:51 PM »

Дело в том, что, как я понял, слоты обозначены в файле cstrike.inc. Но у меня в нём только:
Quote
#define CS_SLOT_PRIMARY      0   /**< Primary weapon slot. */
#define CS_SLOT_SECONDARY   1   /**< Secondary weapon slot. */
#define CS_SLOT_GRENADE      3   /**< Grenade slot (will only return one grenade). */
#define CS_SLOT_C4         4   /**< C4 slot. */
Как видите, CS_SLOT_MELEE отсутствует. Так должно быть или мне следует добавить эту строчку в файл?

Про FakeClientCommand и RemovePlayerItem я понял. Но подскажите ещё, каким образом лучше запомнить, что именно было у игрока в слотах в момент перед срабатыванием абилити, чтобы потом вставить это после окончания абилити? Или тот вариант выше вполне работоспособен?
Logged
Frenzzy
Moderator
Full Member
*****
Posts: 217


337905984 frenzzy@live.ru
View Profile WWW
« Reply #3 on: October 30, 2011, 10:21:55 PM »

Если с минимальными изменениями, то я бы сделал примерно так:
Quote
new wep1 = GetPlayerWeaponSlot(client, CS_SLOT_PRIMARY);
if (IsValidEdict(wep1))
{
    GetEdictClassname(wep1, Temp1[client], 32);
    RemovePlayerItem(client, wep1);
    AcceptEntityInput(wep1, "Kill");
}

new wep2 = GetPlayerWeaponSlot(client, CS_SLOT_SECONDARY);
if (IsValidEdict(wep2))
{
    GetEdictClassname(wep2, Temp2[client], 32);
    RemovePlayerItem(client, wep2);
    AcceptEntityInput(wep2, "Kill");
}

War3_WeaponRestrictTo(client, thisRaceID, "weapon_knife");
FakeClientCommand(client, "use weapon_knife");
Сохраняются только Primary и Secondary weapons.. соответственно только они и возвращаются.
Logged

O_o
Arturius
Moderator
Full Member
*****
Posts: 155



View Profile Email
« Reply #4 on: October 31, 2011, 06:27:38 AM »

Сапсибо, Frenzzy! Ваши советы очень помогли. Если Вы не против, то я ещё немного воспльзуюсь Вашей помощью.
Скажите пожалуйста, если использовать такой вот код для замены одного оружия на другое?
Quote
new wep1 = GetPlayerWeaponSlot( client, CS_SLOT_PRIMARY );
if (IsValidEdict(wep1))
{
   RemovePlayerItem(client, wep1);
   GivePlayerItem( client, "weapon_m4a1" );
}

IsValidEdict(wep1) - требуется для проверки на ненулевое значение, т.к. при нулевом значении не происходит RemovePlayerItem(client, wep1);.
Но что делать, если в начале первого раунда или после ручного выброса оружия в игре в первом слоте оружие отсутствует? Тогда замена не произойдёт. Как избежать такой ситуации?
Logged
Frenzzy
Moderator
Full Member
*****
Posts: 217


337905984 frenzzy@live.ru
View Profile WWW
« Reply #5 on: October 31, 2011, 06:49:55 AM »

Quote
// Получаем основное оружие игрока
new weapon = GetPlayerWeaponSlot(client, CS_SLOT_PRIMARY);

// Если оно существует
if (IsValidEdict(weapon))
{
    // Отнимаем
    RemovePlayerItem(client, weapon);
    // И удаляем
    AcceptEntityInput(weapon, "Kill");
}

// Даем новое оружие
weapon = GivePlayerItem(client, "weapon_m4a1");

// Если оружие создано успешно
if (IsValidEdict(weapon))
{
    // Можно с ним что-нибудь сделать..
    EquipPlayerWeapon(client, weapon);
}
« Last Edit: October 31, 2011, 07:05:14 AM by Frenzzy » Logged

O_o
Arturius
Moderator
Full Member
*****
Posts: 155



View Profile Email
« Reply #6 on: October 31, 2011, 09:10:13 AM »

Очередное спасибо Вам за толковое объяснение!
Это работает. Но судя по всему, моё невежество настолько велико, что каждый следующий шаг ведёт к новым вопросам Cheesy.
Я столкнулся с очередной проблемой... Оружие создаётся прекрасно, экипируется замечательно и даже переключается на него без заминок! Но к сожалению, у каждого вновь созданного оружия только один магазин с патронами. Как при создании и экипировке оружия добавить к нему и магазинов с патронами?

P.S.
Мне кажется, ещё немного и эту тему можно будет переводить в раздел уроков.
Logged
Divix
Sr. Member
****
Posts: 280


View Profile Email
« Reply #7 on: October 31, 2011, 01:28:11 PM »

Но к сожалению, у каждого вновь созданного оружия только один магазин с патронами. Как при создании и экипировке оружия добавить к нему и магазинов с патронами?

Добавь это
Code:
/*
  Weapon: weapon_deagle         Offset: 1   Count: 35
  Weapon: weapon_ak47           Offset: 2   Count: 90
  Weapon: weapon_aug            Offset: 2   Count: 90
  Weapon: weapon_g3sg1          Offset: 2   Count: 90
  Weapon: weapon_scout          Offset: 2   Count: 90
  Weapon: weapon_sg550          Offset: 3   Count: 90
  Weapon: weapon_sg552          Offset: 3   Count: 90
  Weapon: weapon_famas          Offset: 3   Count: 90
  Weapon: weapon_galil          Offset: 3   Count: 90
  Weapon: weapon_m4a1           Offset: 3   Count: 90
  Weapon: weapon_m249           Offset: 4   Count: 200
  Weapon: weapon_awp            Offset: 5   Count: 30
  Weapon: weapon_elite          Offset: 6   Count: 120
  Weapon: weapon_glock          Offset: 6   Count: 120
  Weapon: weapon_mp5navy        Offset: 6   Count: 120
  Weapon: weapon_tmp            Offset: 6   Count: 120
  Weapon: weapon_xm1014         Offset: 7   Count: 32
  Weapon: weapon_m3             Offset: 7   Count: 32
  Weapon: weapon_mac10          Offset: 8   Count: 100
  Weapon: weapon_ump45          Offset: 8   Count: 100
  Weapon: weapon_usp            Offset: 8   Count: 100
  Weapon: weapon_p228           Offset: 9   Count: 52
  Weapon: weapon_p90            Offset: 10  Count: 100
  Weapon: weapon_fiveseven      Offset: 10  Count: 100
*/
new ammoOffset = FindSendPropInfo("CCSPlayer", "m_iAmmo");
SetEntData(client, ammoOffset+(weapon_offset*4), count); // weapon_offset и count написаны выше
« Last Edit: October 31, 2011, 01:34:57 PM by Divix » Logged
Frenzzy
Moderator
Full Member
*****
Posts: 217


337905984 frenzzy@live.ru
View Profile WWW
« Reply #8 on: November 01, 2011, 01:21:51 AM »

Вместо
EquipPlayerWeapon(client, weapon);
используй
FakeClientCommand(client, "use weapon_m4a1");
для переключение на новое оружие.
И доп. обойма не будет опустошаться.

Либо..
Quote
new weapon = GivePlayerItem(client, "weapon_m4a1"); // primary weapon
if (IsValidEdict(weapon))
{
    new clip = 31; // Основная обойма
    SetEntProp(weapon, Prop_Data, "m_iClip1", clip); // primary: m_iClip1, secondary: m_iClip2
    
    new ammo = 91; // Доп. обойма
    new offset = FindDataMapOffs(client, "m_iAmmo")
    new ammotype = GetEntProp(weapon, Prop_Data, "m_iPrimaryAmmoType"); // primary: m_iPrimaryAmmoType, secondary: m_iSecondaryAmmoType
    SetEntData(client, offset + ammotype * 4, ammo, 4, true);
}
« Last Edit: November 01, 2011, 01:54:12 AM by Frenzzy » Logged

O_o
Arturius
Moderator
Full Member
*****
Posts: 155



View Profile Email
« Reply #9 on: November 01, 2011, 02:14:01 AM »

Спасибо за совет! Ещё вопрос. А в каких случаях и каким образом используется War3_GiveWeaponAmmo из файла AmmoControl.inc?
« Last Edit: November 01, 2011, 08:43:55 AM by Arturius » Logged
Frenzzy
Moderator
Full Member
*****
Posts: 217


337905984 frenzzy@live.ru
View Profile WWW
« Reply #10 on: November 01, 2011, 08:39:28 AM »

Код из моего предыдущего сообщения можно переписать так:
Quote
new weapon = GivePlayerItem(client, "weapon_m4a1");
if (IsValidEdict(weapon))
{
    War3_GiveWeaponAmmo(client, weapon, 91, 31);
}
Это даст тот же эффект и не нужно думать над тем какой нужно использовать офсет для текущего оружия.
Logged

O_o
Arturius
Moderator
Full Member
*****
Posts: 155



View Profile Email
« Reply #11 on: November 01, 2011, 08:44:50 AM »

Хочу поделиться плодом ваших стараний и моей навязчивости. Переделал расу Agent используя ваши советы и добавил к ней файлы перевода. Вроде всё работает. Проверьте.
1. При спауне расы иногда не выдавалось оружие. Исправил.
2. Добавил файлы перевода.
3. Отказался от использования haaaxfunctions.inc

И огромнейшее спасибо за вашу помощь!
« Last Edit: November 01, 2011, 08:48:45 AM by Arturius » Logged
Arturius
Moderator
Full Member
*****
Posts: 155



View Profile Email
« Reply #12 on: November 02, 2011, 06:43:55 AM »

И ещё один вопрос возник. При рестрикте всего оружия, кроме ножа, всё равно остаётся возможность покупки оружия. Хотя оружие автоматически выбрасывается, есть ли возможность не позволять закупку оружия? Деньги ведь тратятся и оружие валяется. Не для себя, так хоть другим достанется. А не должно!
Logged
Frenzzy
Moderator
Full Member
*****
Posts: 217


337905984 frenzzy@live.ru
View Profile WWW
« Reply #13 on: November 02, 2011, 10:50:41 AM »

К сожалению так работает стандартная вар3 функция War3_WeaponRestrictTo(). Если вы хотите более продвинутый запрет оружия, напишите его сами или просите авторов вар3 исправить это недоразумение. Тем более что с новыми функциями sourcemod 1.4 это сделать совсем просто.
Logged

O_o
Arturius
Moderator
Full Member
*****
Posts: 155



View Profile Email
« Reply #14 on: November 03, 2011, 01:42:05 AM »

Мой следующий вопрос несколько не в тему, но всё же...
Объясните мне пожалуйста, в функции War3_DealDamage что означает последний параметр и откуда он берётся?
Quote
War3_DealDamage(victim,ShadowStrikeInitialDamage,attacker,DMG_BULLET,"shadowstrike");
Я смотрел описание функции в War3Source_Interface.inc, но толком не понял, что там к чему.

И да, в cstrike.inc я нашёл forward Action:CS_OnBuyCommand(client, const String:weapon[]);, но не понимаю, как его использовать.
« Last Edit: November 03, 2011, 02:02:29 AM by Arturius » Logged
Frenzzy
Moderator
Full Member
*****
Posts: 217


337905984 frenzzy@live.ru
View Profile WWW
« Reply #15 on: November 03, 2011, 03:10:27 AM »


Если ты про 5-ый параметр (а не про последний) функции War3_DealDamage(), то там должно быть указано название оружия котором наносится урон. Если ты укажешь там например weapon_awp то в игре отобразится как-будто урон нанесли с авп.

Quote
/**
 * Вызывается, когда игрок пытается купить предмет.
 * Верните Plugin_Continue чтобы разрешить покупку
 * или другое действие для запрета.
 *
 * @param client   Индекс клиента
 * @param weapon   Название оружия
 */

public Action:CS_OnBuyCommand(client, const String:weapon[])
{
    // Если у клиента текущая раса
    if (War3_GetRace(client) == thisRaceID)
    {
        // Если покупаемое оружие калаш или эмка
        if (StrEqual(weapon, "ak47") || StrEqual(weapon, "m4a1"))
        {
            // Остановить покупку
            return Plugin_Handled;
        }
    }
   
    // Продолжить работу плагина
    return Plugin_Continue;
}
« Last Edit: November 03, 2011, 08:01:19 AM by Frenzzy » Logged

O_o
Arturius
Moderator
Full Member
*****
Posts: 155



View Profile Email
« Reply #16 on: November 03, 2011, 06:17:52 AM »

Чувствую себя как обезьяна с гранатой, которой пытается сбить кокос. Не знаю, правильно ли я сделал, но разместил Ваш пример в конец файла расы и добавил CS_OnBuyCommand; в функцию public OnPluginStart().
Code:
public OnPluginStart()
{
LoadTranslations("w3s.race.crhound.phrases");
CS_OnBuyCommand;
}

При компиляции выдаётся предупреждение:
Code:
//// War3Source_CustomRace_CrazyHound.sp
// War3Source_CustomRace_CrazyHound.sp(43) : warning 215: expression has no effect
// Header size:           4804 bytes
// Code size:            16060 bytes
// Data size:             6888 bytes
// Stack/heap size:      16384 bytes; Total requirements:   44136 bytes
//
// 1 Warning.
//
// Compilation Time: 2,53 sec
// ----------------------------------------

Хотя в игре всё работает и закупка обозначенного оружия не происходит. Но если я пытаюсь пойти от обратного:
Code:
// Если покупаемое оружие не калаш или не эмка
        if (!StrEqual(weapon, "ak47") || !StrEqual(weapon, "m4a1"))
то вообще ничего не закупается. Может я не так гранату держу или не туда кидаю? Cheesy
Logged
Frenzzy
Moderator
Full Member
*****
Posts: 217


337905984 frenzzy@live.ru
View Profile WWW
« Reply #17 on: November 03, 2011, 07:58:37 AM »

..добавил CS_OnBuyCommand; в функцию public OnPluginStart().
Полный бред, зачем она там? Достаточно добавить #include <cstrike> до объявления функции, чтобы она работала.

Quote
    &&    // и
    ||     // или
    ==    // равно
    !=     // не равно

if (StrEqual(weapon, "ak47") || StrEqual(weapon, "m4a1")) // Если одно из выражений возвращает true
if (StrEqual(weapon, "ak47") && StrEqual(weapon, "m4a1")) // Если оба выражения возвращают true
if (!StrEqual(weapon, "ak47") && !StrEqual(weapon, "m4a1")) // Если оба выражения возвращают false
Введение в SourcePawn (там есть на русском)

Quote
public Action:CS_OnBuyCommand(client, const String:weapon[])
{
    // Если у игрока НЕ наша раса
    if (War3_GetRace(client) != thisRaceID)
    {
        // То просто продолжим работу плагина
        return Plugin_Continue;
    }
    
    // Если игрок покупает..
    if (StrEqual(weapon, "knife") ||         // Нож, или..
        StrEqual(weapon, "vest") ||          // Броню, или..
        StrEqual(weapon, "vesthelm") ||   // Броню со шлемом, или..
        StrEqual(weapon, "defuser") ||     // Щипцы, или..
        StrEqual(weapon, "nvgs"))           // Прибор ночного видения, то
    {
        // Разрешить покупку
        return Plugin_Continue;
    }
    
    // Во всех остальных случаях запретить покупку
    return Plugin_Handled;
}
Weapon Names (похоже эта информация устарела)
« Last Edit: November 03, 2011, 08:13:32 AM by Frenzzy » Logged

O_o
Arturius
Moderator
Full Member
*****
Posts: 155



View Profile Email
« Reply #18 on: November 03, 2011, 08:49:13 AM »

Я же говорю, как с гранатой. Grin Начал её кидать куда попало, вместо того, чтобы просто её положить и не трогать Cheesy. Спасибо! Всё работает!

А вот с операторами сравнения надо бы разобраться! Верно же у меня было, если я хотел разрешить закупку только м4а1 или калаша?
Code:
...
//если (StrEqual(weapon, "ak47")=ложно или StrEqual(weapon, "m4a1")=ложно)
if (!StrEqual(weapon, "ak47") || !StrEqual(weapon, "m4a1"))

{
       // Остановить покупку
       return Plugin_Handled;
}
...
А то у меня складывается впечатление, что я и в этом уже не разбираюсь Grin.
« Last Edit: November 03, 2011, 09:17:50 AM by Arturius » Logged
Frenzzy
Moderator
Full Member
*****
Posts: 217


337905984 frenzzy@live.ru
View Profile WWW
« Reply #19 on: November 03, 2011, 01:53:32 PM »

Чтобы проверить, верно написано или нет, достаточно подставить реальные значения на место аргументов функции.

Quote
// К примеру, я покупаю калаш
public Action:CS_OnBuyCommand(Frenzzy, "ak47");

// Далее идет проверка, рассмотрим все по отдельности
if (!StrEqual("ak47", "ak47") || !StrEqual("ak47", "m4a1"))

// Проверка соответствия строк
StrEqual("ak47", "ak47") // вернет true
// Калаш равен калашу, строки соответствуют, функция возвращает true

// Знак ! превращает true в false
!true // вернет false

// Вторая часть выполняется подобным образом
StrEqual("ak47", "m4a1") // вернет false
!false // вернет true

// Подставим готовые значения и посмотрим что получилось
if (false || true) // вернет true, т.к. одно из значение верно
{
    // Остановить покупку ak47
    return Plugin_Handled;
}

Чтобы проверить другие варианты, самостоятельно подставь вначале m4a1 или другое оружие.
Или можешь поверить на слово, что любое оружие будет запрещено Tongue

И вообще я тебе в сообщениях выше привел 2 варианта как запретить одно или несколько или наоборот запретить все кроме одного или нескольких оружий.
Logged

O_o
Arturius
Moderator
Full Member
*****
Posts: 155



View Profile Email
« Reply #20 on: November 04, 2011, 12:41:04 AM »

И вообще я тебе в сообщениях выше привел 2 варианта как запретить одно или несколько или наоборот запретить все кроме одного или нескольких оружий.
Твой пример я прекрасно понял и успешно применил. Мне хотелось до конца разобраться с тем, что у меня не получилось и твёрдо знать почему. Спасибо за науку! Wink

Тем более, я не единственный тугодум на этом форуме Grin и твои разъяснения даром не пропадут.
Logged
Arturius
Moderator
Full Member
*****
Posts: 155



View Profile Email
« Reply #21 on: November 04, 2011, 12:08:51 PM »

Я снова к вам за новой для себя информацией.
Объясните пожалуйста, как работает функция War3_CachedDeadWeaponName и вообще функции серии War3_CachedDead и War3_Cached. Дело в том, что , насколько я понимаю, в расе Element (и некоторых других) эта функция включена для того, чтобы вспоминать какое оружие было у игрока в момент смерти для последующей его экипировки при возрождении. Но... похоже, что что-то там намудрено не так и запоминается то оружие, которое было в момент смерти в прошлом раунде, а не в этом.
Logged
Frenzzy
Moderator
Full Member
*****
Posts: 217


337905984 frenzzy@live.ru
View Profile WWW
« Reply #22 on: November 04, 2011, 02:25:31 PM »

Когда игрок умирает, оружие удаляется с карты? Вроде все должно работать.. хотя код этих рас я не смотрел.
Logged

O_o
Arturius
Moderator
Full Member
*****
Posts: 155



View Profile Email
« Reply #23 on: November 04, 2011, 02:52:38 PM »

Проверил, оружие остаётся на карте, выдаётся новое. И сообщение о предстоящем воскрешении выдаётся не за время до воскрешения, а уже во время. С моими-то поверхностными знаниями, я там мозг окончательно сломал.
Logged
Arturius
Moderator
Full Member
*****
Posts: 155



View Profile Email
« Reply #24 on: November 10, 2011, 05:24:15 AM »

Абсолютно точно могу сказать, что в первом раунде у расы Элемент при возрождении вообще не выдаётся оружие, только нож. А вот втором раунде выдаётся оружие которое было в первом. Как бы, War3_CachedDeadWeapon запоминает оружие предыдущего раунда. Сам не пойму почему, хотя у Орка в принципе такой же код, но всё работает как надо. Пробовал заменить код Элемента на код Орка по выдаче оружия при возрождении, с необходимыми переменными, но эффект остаётся такой же.
Logged
Pages: [1] 2
  Print  
 
Jump to:  

Powered by MySQL Powered by PHP Powered by SMF 1.1.11 | SMF © 2006-2009, Simple Machines LLC Valid XHTML 1.0! Valid CSS!