Название:Full-Inventory Crafting System Авторы:bowser499 aka [DUOS] and SirNikolas Тип исполнения:JASS2 and cJass Тестовая карта:Присутствует Минимальный патч:Любой
Одна из нашумевших наработок, которую мало кто доводил до конца конкретно на JASS2. Из-за крайней сложности её создания решил выложить, так как это решит много вопросов, с этим связанных.
Возможности:
Сбор при полном инвентаре (рецепты максимум до 7 слотов);
Сбор с участием идентичных предметов;
Смена иконки предмета из магазина и предмета в инвентаре (покупаешь рецепт с иконкой сборного предмета - в инвентарь идет свиток);
Смена предмета на деактивированный предмет (любой, кто берет предмет, не принадлежащий ему, не получает свойств предмета);
Сложение "зарядов" предметов (банка с 3 зарядами + банка с 8 зарядами = банка с 11 зарядами).
База данных предметов и рецептов формируется по следующему принципу:
1. Создаются в РО три копии одного и того же предмета:
Normal (обычный предмет, находится у купившего)
Rune (используется мгновенно, находится в магазине и лежит на земле)
Disabled (находится у того, кто "украл" предмет)
2. Rune-копии добавляются в магазины. 3. В триггере инициализации регистрируются предметы путем вызова для каждого FICS_Register(rawNormal, rawRune, rawDisabled, goldCost, lumberCost). Каждому предмету дается порядковый номер, начиная с единицы. 4. После заполнения всех предметов вызывается функция FICS_Proceed(). 5. Наконец, составляется список рецептов. Вызывается функция FICS_RegisterN(resultId, id0, id1, ..., idN), где N - количество ингредиентов, а resultId, id0, id1, ..., id6 - порядковые номера предметов.
Импорт наработки:
Версия JASS2: 1. Скопируйте основной код карты FICS v1.5.w3x в основной код своей карты. 2. Скопируйте триггер "FICS". 3. Скопируйте все переменные (для облегчения задачи можно скопировать, а затем удалить триггер "FICS variables", если включено автоматическое создание переменных).
Версия cJass: 1. Скопируйте триггер "FICS cJass" (и разблокируйте его).
private constant timer T = CreateTimer(); private item Dropped[ ]; private int DropNum[ ], Temp[21]; private int DropCount = 0; private int Ids[ ], Num[ ], Length = 0; private int Items[500][5], Recipes[256][8]; private int ItemCount = 0, RecipeCount = 0; private int FirstList[ ], LastList[ ]; private int Recipe[ ], Next[ ], ListCount = 0; private bool Flag = true;
public int Register(int id, int rune, int dis, int gcost, int lcost) { ItemCount++; Ids [Length]= id; Ids[Length + 1] = rune; Ids[Length + 2] = dis; Num [Length]= ItemCount; Num[Length + 1] = ItemCount; Num[Length + 2] = ItemCount; Length += 3; Items[ItemCount][0] = id; Items[ItemCount][1] = rune; Items[ItemCount][2] = dis; Items[ItemCount][3] = gcost; Items[ItemCount][4] = lcost; return ItemCount; }
//Сортировка расческой public void Proceed() { int jump = Length; bool end = true; whilenot jump == 1 && end { if jump > 1 { jump = R2I(jump * .802); } end = true; for (int i = 0; i + jump < Length; i++) { if Ids [i]> Ids[i + jump] { int t = Ids[i]; Ids [i]= Ids[i + jump]; Ids[i + jump] = t; t = Num[i]; Num [i]= Num[i + jump]; Num[i + jump] = t; end = false; } } } }
private int BinSearch(int id) { int first = 0, last = Length; if id >= Ids[0] && id <= Ids[last - 1] { whilenot first >= last { int mid = (first + last) / 2; if id <= Ids [mid]{ last = mid; } else { first = mid + 1; } } if id == Ids [last]{ return Num[last]; } } return 0; }
public void Register7(int result, int i0, int i1, int i2, int i3, int i4, int i5, int i6) { #for j(0, 6) Temp [j]= i##j; #endfor RecipeCount++; //Записываем в Recipes сортированные по невозрастанию индексы for (int i = 0) { if Temp [i]> 0 { if Temp[i]:LastList == 0 || Temp[i]:LastList:Recipe != RecipeCount { ListCount++; if Temp[i]:LastList == 0 { Temp[i]:FirstList = ListCount; } else { Temp[i]:LastList:Next = ListCount; } Temp[i]:LastList = ListCount; Temp[i]:LastList:Recipe = RecipeCount; Temp[i]:LastList:Next = 0; } int j = i; whilenot j == 0 || Recipes[RecipeCount][j - 1] >= Temp [i]{ Recipes[RecipeCount] [j]= Recipes[RecipeCount][j - 1]; j--; } Recipes[RecipeCount] [j]= Temp[i]; } exitwhen i == 6; i++; } Recipes[RecipeCount][7] = result; }
public void Register6(int result, int i0, int i1, int i2, int i3, int i4, int i5) { Register7(result, i0, i1, i2, i3, i4, i5, 0); }
public void Register5(int result, int i0, int i1, int i2, int i3, int i4) { Register6(result, i0, i1, i2, i3, i4, 0); }
public void Register4(int result, int i0, int i1, int i2, int i3) { Register5(result, i0, i1, i2, i3, 0); }
public void Register3(int result, int i0, int i1, int i2) { Register4(result, i0, i1, i2, 0); }
public void Register2(int result, int i0, int i1) { Register3(result, i0, i1, 0); }
//Бесполезная штука, в общем-то, но такое тоже возможно public void Register1(int result, int i0) { Register2(result, i0, 0); }
Спасибо. Система очень помогла. Только одно: у меня работало для одного игрока: красного - Player(0). Другим выдавал дисаблед предметы(Даже если покупал сам). Не знаю, может кому поможет: в функциях
Code
function Item_GetOwningPlayer takes item i returns player return Player(LoadInteger(udg_FicsHash,GetHandleId(i),10)) endfunction
function Item_SetOwningPlayer takes item i, player p returns nothing call SaveInteger(udg_FicsHash,GetHandleId(i),10,GetPlayerId(p)) endfunction
Заменил сохранение и загрузку интегера Id игрока на хэндл игрока. Стало работать для всех игроков.
А смысл? Разве мы не можем сказать, какой ID будет у какого игрока? Протестируй еще раз: вполне возможно, что после этого изменения можно пользоваться чужими предметами.
Вклеил систему в карту: сначала подстроил под неё - тестил, получил то, что выше описал. Потом попробовал ничего не трогать, тоже самое вышло. Чёрт знает. Я пока в джасе нуб, раз десятый уже просматриваю код: вроде всё верно.
Да. Создал там другого игрока: тоже самое - выдаёт Disabled предметы.
Добавлено (31 Май 2012, 23:34:04) --------------------------------------------- Несколько переделал систему: вместо сохранения в хеш-таблице Id игрока сделал присваивание предмету игрока (SetItemPlayer). Сразу говорю, не знаю на сколько утечна эта функция, но система стала работать для всех игроков(Тестил в своей карте). Изменил наработку [DUOS]'a: так же добавил совместимую c FICS систему собирания предметов магическим кругом (как в доте). Я думаю, что это полезно будет тем, кто систему использовать будет. Протестите, сам я багов не нашёл.
Добавлено (02 Июнь 2012, 00:01:55) --------------------------------------------- Друзья, нашёл баг (который так же присутствовал в варсии 1.2) - При передаче предмета напрямую (Не кладя на землю, а перетаскиванием иконки предмета на героя/юнита) юниту, не принадлежащему игроку предмет сохранялся в форме Normal. Исправлено!
Добавил: 1)Магический круг выкидывает на свою позицию предметы при покупке 2)Магический круг собирает предметы из НЕгероев, находящихся в области сбора (Если планируете использовать курьеров и т.д.)
Добавлено (18 Января 2013, 21:50:46) --------------------------------------------- SirNikolas другая проблема теперь(( Работает для игрока красного только((( Скиньте плз для 12 игроков. Очень прошу.
Добавлено (21 Января 2013, 15:07:52) --------------------------------------------- SirNikolas Перезалейте пожалуйста версию 1.4. В 1.2 работает только на красного игрока(((
Дело в том, что уже есть функция Register, принимающая 5 аргументов. К тому же, я стремился сделать так, чтобы интерфейс библиотеки был одинаковым для всех языков. И мне это удалось.