|
Arturius
|
 |
« on: October 27, 2011, 02:33:20 AM » |
|
Прошу помощи у знающих людей, так как своего ума ещё не нарастил  . У расы Strider Hiryu во время работы абилити совершается полёт, во время которого он становится невидимым и оружие должно сменятся на нож. А после завершения абилити, оружие должно возвращаться. И вот именно в этой смене загвоздка. В коде это реализовано так: //Объявлены глобальные переменные 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 );, но эффекта не достиг. Кроме того, даже выбросив оружие во время игры до включения абилити, после завершения абилити оно возвращается. Так ведь можно сбросить кому-то авп, включить абилку и получить себе новую бесплатно  . Подскажите, как возможно с этим справиться?
|
|
|
|
« Last Edit: November 04, 2011, 12:09:53 PM by Arturius »
|
Logged
|
|
|
|
|
Frenzzy
|
 |
« Reply #1 on: October 30, 2011, 02:28:36 PM » |
|
Weapon Slot 2 - в ксс это нож #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
|
 |
« Reply #2 on: October 30, 2011, 03:06:51 PM » |
|
Дело в том, что, как я понял, слоты обозначены в файле cstrike.inc. Но у меня в нём только: #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
|
 |
« Reply #3 on: October 30, 2011, 10:21:55 PM » |
|
Если с минимальными изменениями, то я бы сделал примерно так: 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
|
 |
« Reply #4 on: October 31, 2011, 06:27:38 AM » |
|
Сапсибо, Frenzzy! Ваши советы очень помогли. Если Вы не против, то я ещё немного воспльзуюсь Вашей помощью. Скажите пожалуйста, если использовать такой вот код для замены одного оружия на другое? new wep1 = GetPlayerWeaponSlot( client, CS_SLOT_PRIMARY ); if (IsValidEdict(wep1)) { RemovePlayerItem(client, wep1); GivePlayerItem( client, "weapon_m4a1" ); }
IsValidEdict(wep1) - требуется для проверки на ненулевое значение, т.к. при нулевом значении не происходит RemovePlayerItem(client, wep1);. Но что делать, если в начале первого раунда или после ручного выброса оружия в игре в первом слоте оружие отсутствует? Тогда замена не произойдёт. Как избежать такой ситуации?
|
|
|
|
|
Logged
|
|
|
|
|
Frenzzy
|
 |
« Reply #5 on: October 31, 2011, 06:49:55 AM » |
|
// Получаем основное оружие игрока 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
|
 |
« Reply #6 on: October 31, 2011, 09:10:13 AM » |
|
Очередное спасибо Вам за толковое объяснение! Это работает. Но судя по всему, моё невежество настолько велико, что каждый следующий шаг ведёт к новым вопросам  . Я столкнулся с очередной проблемой... Оружие создаётся прекрасно, экипируется замечательно и даже переключается на него без заминок! Но к сожалению, у каждого вновь созданного оружия только один магазин с патронами. Как при создании и экипировке оружия добавить к нему и магазинов с патронами? P.S. Мне кажется, ещё немного и эту тему можно будет переводить в раздел уроков.
|
|
|
|
|
Logged
|
|
|
|
|
Divix
|
 |
« Reply #7 on: October 31, 2011, 01:28:11 PM » |
|
Но к сожалению, у каждого вновь созданного оружия только один магазин с патронами. Как при создании и экипировке оружия добавить к нему и магазинов с патронами?
Добавь это /* 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
|
 |
« Reply #8 on: November 01, 2011, 01:21:51 AM » |
|
Вместо EquipPlayerWeapon(client, weapon); используй FakeClientCommand(client, "use weapon_m4a1"); для переключение на новое оружие. И доп. обойма не будет опустошаться. Либо.. 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
|
 |
« 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
|
 |
« Reply #10 on: November 01, 2011, 08:39:28 AM » |
|
Код из моего предыдущего сообщения можно переписать так: new weapon = GivePlayerItem(client, "weapon_m4a1"); if (IsValidEdict(weapon)) { War3_GiveWeaponAmmo(client, weapon, 91, 31); }
Это даст тот же эффект и не нужно думать над тем какой нужно использовать офсет для текущего оружия.
|
|
|
|
|
Logged
|
O_o
|
|
|
|
Arturius
|
 |
« 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
|
 |
« Reply #12 on: November 02, 2011, 06:43:55 AM » |
|
И ещё один вопрос возник. При рестрикте всего оружия, кроме ножа, всё равно остаётся возможность покупки оружия. Хотя оружие автоматически выбрасывается, есть ли возможность не позволять закупку оружия? Деньги ведь тратятся и оружие валяется. Не для себя, так хоть другим достанется. А не должно!
|
|
|
|
|
Logged
|
|
|
|
|
Frenzzy
|
 |
« Reply #13 on: November 02, 2011, 10:50:41 AM » |
|
К сожалению так работает стандартная вар3 функция War3_WeaponRestrictTo(). Если вы хотите более продвинутый запрет оружия, напишите его сами или просите авторов вар3 исправить это недоразумение. Тем более что с новыми функциями sourcemod 1.4 это сделать совсем просто.
|
|
|
|
|
Logged
|
O_o
|
|
|
|
Arturius
|
 |
« Reply #14 on: November 03, 2011, 01:42:05 AM » |
|
Мой следующий вопрос несколько не в тему, но всё же... Объясните мне пожалуйста, в функции War3_DealDamage что означает последний параметр и откуда он берётся? 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
|
 |
« Reply #15 on: November 03, 2011, 03:10:27 AM » |
|
Если ты про 5-ый параметр (а не про последний) функции War3_DealDamage(), то там должно быть указано название оружия котором наносится урон. Если ты укажешь там например weapon_awp то в игре отобразится как-будто урон нанесли с авп. /** * Вызывается, когда игрок пытается купить предмет. * Верните 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
|
 |
« Reply #16 on: November 03, 2011, 06:17:52 AM » |
|
Чувствую себя как обезьяна с гранатой, которой пытается сбить кокос. Не знаю, правильно ли я сделал, но разместил Ваш пример в конец файла расы и добавил CS_OnBuyCommand; в функцию public OnPluginStart(). public OnPluginStart() { LoadTranslations("w3s.race.crhound.phrases"); CS_OnBuyCommand; } При компиляции выдаётся предупреждение: //// 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 // ---------------------------------------- Хотя в игре всё работает и закупка обозначенного оружия не происходит. Но если я пытаюсь пойти от обратного: // Если покупаемое оружие не калаш или не эмка if (!StrEqual(weapon, "ak47") || !StrEqual(weapon, "m4a1")) то вообще ничего не закупается. Может я не так гранату держу или не туда кидаю? 
|
|
|
|
|
Logged
|
|
|
|
|
Frenzzy
|
 |
« Reply #17 on: November 03, 2011, 07:58:37 AM » |
|
..добавил CS_OnBuyCommand; в функцию public OnPluginStart(). Полный бред, зачем она там? Достаточно добавить #include <cstrike> до объявления функции, чтобы она работала. && // и || // или == // равно != // не равно
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 (там есть на русском)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
|
 |
« Reply #18 on: November 03, 2011, 08:49:13 AM » |
|
Я же говорю, как с гранатой.  Начал её кидать куда попало, вместо того, чтобы просто её положить и не трогать  . Спасибо! Всё работает! А вот с операторами сравнения надо бы разобраться! Верно же у меня было, если я хотел разрешить закупку только м4а1 или калаша? ... //если (StrEqual(weapon, "ak47")=ложно или StrEqual(weapon, "m4a1")=ложно) if (!StrEqual(weapon, "ak47") || !StrEqual(weapon, "m4a1"))
{ // Остановить покупку return Plugin_Handled; } ... А то у меня складывается впечатление, что я и в этом уже не разбираюсь  .
|
|
|
|
« Last Edit: November 03, 2011, 09:17:50 AM by Arturius »
|
Logged
|
|
|
|
|
Frenzzy
|
 |
« Reply #19 on: November 03, 2011, 01:53:32 PM » |
|
Чтобы проверить, верно написано или нет, достаточно подставить реальные значения на место аргументов функции. // К примеру, я покупаю калаш 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 или другое оружие. Или можешь поверить на слово, что любое оружие будет запрещено  И вообще я тебе в сообщениях выше привел 2 варианта как запретить одно или несколько или наоборот запретить все кроме одного или нескольких оружий.
|
|
|
|
|
Logged
|
O_o
|
|
|
|
Arturius
|
 |
« Reply #20 on: November 04, 2011, 12:41:04 AM » |
|
И вообще я тебе в сообщениях выше привел 2 варианта как запретить одно или несколько или наоборот запретить все кроме одного или нескольких оружий.
Твой пример я прекрасно понял и успешно применил. Мне хотелось до конца разобраться с тем, что у меня не получилось и твёрдо знать почему. Спасибо за науку!  Тем более, я не единственный тугодум на этом форуме  и твои разъяснения даром не пропадут.
|
|
|
|
|
Logged
|
|
|
|
|
Arturius
|
 |
« Reply #21 on: November 04, 2011, 12:08:51 PM » |
|
Я снова к вам за новой для себя информацией. Объясните пожалуйста, как работает функция War3_CachedDeadWeaponName и вообще функции серии War3_CachedDead и War3_Cached. Дело в том, что , насколько я понимаю, в расе Element (и некоторых других) эта функция включена для того, чтобы вспоминать какое оружие было у игрока в момент смерти для последующей его экипировки при возрождении. Но... похоже, что что-то там намудрено не так и запоминается то оружие, которое было в момент смерти в прошлом раунде, а не в этом.
|
|
|
|
|
Logged
|
|
|
|
|
Frenzzy
|
 |
« Reply #22 on: November 04, 2011, 02:25:31 PM » |
|
Когда игрок умирает, оружие удаляется с карты? Вроде все должно работать.. хотя код этих рас я не смотрел.
|
|
|
|
|
Logged
|
O_o
|
|
|
|
Arturius
|
 |
« Reply #23 on: November 04, 2011, 02:52:38 PM » |
|
Проверил, оружие остаётся на карте, выдаётся новое. И сообщение о предстоящем воскрешении выдаётся не за время до воскрешения, а уже во время. С моими-то поверхностными знаниями, я там мозг окончательно сломал.
|
|
|
|
|
Logged
|
|
|
|
|
Arturius
|
 |
« Reply #24 on: November 10, 2011, 05:24:15 AM » |
|
Абсолютно точно могу сказать, что в первом раунде у расы Элемент при возрождении вообще не выдаётся оружие, только нож. А вот втором раунде выдаётся оружие которое было в первом. Как бы, War3_CachedDeadWeapon запоминает оружие предыдущего раунда. Сам не пойму почему, хотя у Орка в принципе такой же код, но всё работает как надо. Пробовал заменить код Элемента на код Орка по выдаче оружия при возрождении, с необходимыми переменными, но эффект остаётся такой же.
|
|
|
|
|
Logged
|
|
|
|
|