XGM Forum
Сайт - Статьи - Проекты - Ресурсы - Блоги

Форуме в режиме ТОЛЬКО ЧТЕНИЕ. Вы можете задать вопросы в Q/A на сайте, либо создать свой проект или ресурс.
Вернуться   XGM Forum > Warcraft> Академия: форум для вопросов> Jass
Ник
Пароль
Войти через VK в один клик
Сайт использует только имя.

Закрытая тема
 
Лось

offline
Опыт: 7,223
Активность:
В JNGP паке есть справочник по ф-иям, про struct написано в теме с JNGP'ом. Ещё можно юзать JassCraft там тоже спрвочник по ф-иям и хайтлайтер (он есть в утилитах на сайте).
Старый 28.08.2008, 15:30
df Hunter
Нападатель
offline
Опыт: 5,749
Активность:
if IsUnitType(u, ut)==true then
как раз для некоторых ut это надо так делать вроде, ибо баг
== =) sry for post edit :P

Отредактировано Toadcop, 28.08.2008 в 20:04.
Старый 28.08.2008, 17:03
adic3x

offline
Опыт: 108,439
Активность:
Цитата:
как раз для некоторых ut это надо так делать вроде, ибо баг

ибо багу в студию) я тестил оно норм работало...
Старый 28.08.2008, 20:43
Dragon27

offline
Опыт: 6,779
Активность:
ADOLF, эта ошибка вроде в статье описана: http://xgm.guru/articles.php?section=wc3&name=spellmaking3

» Из статьи

function Trig_Lame_Condition takes nothing returns boolean
return (IsUnitType(GetTriggerUnit() , UNIT_TYPE_TOWNHALL) == true)
endfunction

function Trig_Lame_Condition takes nothing returns boolean
return IsUnitType(GetTriggerUnit() , UNIT_TYPE_TOWNHALL)
endfunction

На первый взгляд обе они верны, и должны работать одинаково. Первая из них работает правильно, в то время как вторая всегда возвращает false. Используем return bug, чтобы посмотреть, что на самом деле возвращает функция IsUnitType. В идеале 1 должна соответствовать значению true, а 0 – значению false. Воспользуемся функцией:

function B2I takes boolean b returns integer
return b
return 0
endfunction

Оказывается, что конструкция B2I(IsUnitType(whatever, UNIT_TYPE_TOWNHALL)) не возвращает 1, она возвращает 64!

Таким образом, функция IsUnitType(whatever, UNIT_TYPE_TOWNHALL), в случае, когда юнит принадлежит типу TOWNHALL, вместо 'boolean 1', возвращает 'boolean 64' и это integer значение приводится к типу boolean.

Сравнение этого булевого значения ('boolean 64') с true (==true) вернет true, и оно также будет корректно работать в операторах if, elseif и exitwhen.

Но при использовании в булевских выражениях (boolexprs), величина 'boolean 64' будет равна значению false.

Вот такой вот очередной забавный баг от blizzard. Функция IsUnitType также некорректно работает для типов юнитов:

GROUND 8
FLYING 2
RANGED_ATTACKER 1 //как и HERO
Старый 28.08.2008, 21:10
exploder
iOS zealot
offline
Опыт: 19,394
Активность:
Она же ошибка boolexpr. Довольно боянистая штука. Ссылка на тред с багом есть в статье Blade.dk, если вы внимаетльно читали мой перевод могли видет описание этого бага. Как это сделал комрад Dragon27.
Старый 29.08.2008, 00:46
adic3x

offline
Опыт: 108,439
Активность:
а теперь скажу я - я тестил добавление юнита в группу через булекспр, и указывал через ib2 ретурн баговый любые значения (0x00000001 to 0xffffffff) - и юнит благополучно добавлялся в группу

то что описанно в статье либо следсвие кривых рук, либо старой версии вара

Цитата:
Сравнение этого булевого значения ('boolean 64') с true (==true) вернет true, и оно также будет корректно работать в операторах if, elseif и exitwhen.


любое ненулевое значение - труе
Старый 29.08.2008, 02:07
Integro
старожило
offline
Опыт: 630
Активность:
Покажите новичку в Jass на примере этого кода, как его монжно оптимизировать и способы, кому не лень объясните подробно):

Код:
function GameTime takes nothing returns nothing
    loop
        exitwhen udg_GameEnd == true
        set udg_Seconds = udg_Seconds + 1
        if udg_Seconds == 10 then
            set udg_Seconds = 0
            set udg_TenSeconds = udg_TenSeconds + 1
            if udg_TenSeconds == 6 then
                set udg_TenSeconds = 0
                set udg_Minutes = udg_Minutes + 1
            endif
        endif
        call MultiboardSetItemValueBJ(GetLastCreatedMultiboard(),1,udg_Rows[12],"Время игры:        |cffe6d091" + I2S(udg_Minutes) + ":" + I2S(udg_TenSeconds) + I2S(udg_Seconds) + "|r")
        call PolledWait(0.97)
    endloop
endfunction

function PickAllPlayers takes nothing returns nothing
    call SetPlayerFlagBJ(PLAYER_STATE_GIVES_BOUNTY, true, GetEnumPlayer())
endfunction

function Start takes nothing returns nothing
    local integer i = 0
    call CreateDestructableLoc('Dofw',GetRectCenter(gg_rct_Red_Area),315.00,0.80,1)
    set udg_RedFlag = GetLastCreatedDestructable()
    call CreateDestructableLoc('LTcr',GetRectCenter(gg_rct_Blue_Area),235.00,0.80,1)
    set udg_BlueFlag = GetLastCreatedDestructable()
    set udg_Colour[1] = "|cffff0000"
    set udg_Colour[2] = "|cff0000ff"
    set udg_Colour[3] = "|cff00ffff"
    set udg_Colour[4] = "|cff800080"
    set udg_Colour[5] = "|cffffff00"
    set udg_Colour[6] = "|cffff8000"
    set udg_Colour[7] = "|cffff0000"
    set udg_Colour[8] = "|cffff0000"
    set udg_Colour[9] = "|cffff0000"
    loop
    exitwhen i == 9
        if GetPlayerSlotState(Player(i)) == PLAYER_SLOT_STATE_PLAYING then
            set udg_NumberOfPlayers = udg_NumberOfPlayers + 1
        endif
        set i = i + 1
    endloop
    call ForForce(GetPlayersAll(),function PickAllPlayers)
    set i = 0
endfunction

function InitTrig_Init takes nothing returns nothing
    call Start()
    call ExecuteFunc("GameTime")
endfunction
Старый 08.09.2008, 17:58
ScorpioT1000
Работаем
offline
Опыт: отключен
Цитата:
call CreateDestructableLoc('Dofw',GetRectCenter(gg_rct_Red_Area),315.00,0.80,1)
set udg_RedFlag = GetLastCreatedDestructable()
call CreateDestructableLoc('LTcr',GetRectCenter(gg_rct_Blue_Area),235.00,0.80,1)

все геты в переменки

ScorpioT1000 добавил:
Цитата:
if GetPlayerSlotState(Player(i)) == PLAYER_SLOT_STATE_PLAYING then

гет в переменку!
Старый 09.09.2008, 00:56
dk

offline
Опыт: 60,293
Активность:
Все эти геты возвращают точку, которая успешно утекает... Вобще юзать лучше координаты

dk добавил:
А в GameTime вобще оригинальный способ время считать) Количество итераций(прохождений) цикла в jass ограничено, да и вобще вайт в цикле не гуд... Лучше на подсчет времени отдельный триггер или таймер.
Старый 09.09.2008, 11:57
ShadoW DaemoN

offline
Опыт: 37,078
Активность:
ScorpioT1000, ты меня расстраиваешь...
Смысл заносить результат от Get...() в переменную, если она используется не более трех раз?

Integro, для начала было бы неплохо раскрыть все BJ:
Код:
function PickAllPlayers takes nothing returns nothing
    call SetPlayerFlagBJ(PLAYER_STATE_GIVES_BOUNTY, true, GetEnumPlayer())
endfunction
// ...преобразовывается в...
function PickAllPlayers takes nothing returns nothing
  call SetPlayerState(GetEnumPlayer(), PLAYER_STATE_GIVES_BOUNTY, 1)
endfunction

Код:
function Start takes nothing returns nothing
// . . .
  call CreateDestructableLoc('Dofw',GetRectCenter(gg_rct_Red_Area),315.00,0.80,1)
  set udg_RedFlag = GetLastCreatedDestructable()
  call CreateDestructableLoc('LTcr',GetRectCenter(gg_rct_Blue_Area),235.00,0.80,1)
  set udg_BlueFlag = GetLastCreatedDestructable()
// ...преобразовывается в...
  set udg_RedFlag  = CreateDestructable('Dofw', GetRectCenterX(gg_rct_Red_Area),  GetRectCenterY(gg_rct_Red_Area),  315.0, 0.8, 1)
  set udg_BlueFlag = CreateDestructable('LTcr', GetRectCenterX(gg_rct_Blue_Area), GetRectCenterY(gg_rct_Blue_Area), 235.0, 0.8, 1)
// . . .
endfunction

Код:
// а вот это особенно громоздкая функция (смотреть ее код)
  call MultiboardSetItemValueBJ(GetLastCreatedMultiboard(),1,udg_Rows[12],"bla")
// ...преобразовывается в...
  local multiboarditem mbi = null
  // . . .
  set mbi = MultiboardGetItem(bj_lastCreatedMultiboard, udg_Rows[12] - 1, 0)
  call MultiboardSetItemValue(mbi, "bla")
  call MultiboardReleaseItem(mbi)
  set mbi = null

Далее... Неправильный реализация алгоритма высчитывания прошедшего времени. Наиболее верное решение - использовать таймеры:
Код:
globals
  multiboarditem mbi = null
endglobals

function GameTime takes nothing returns nothing
  set udg_Time = udg_Time + 1
  call MultiboardSetItemValue(mbi, "Game time: " + I2S(udg_Time/60) + ":" + I2S(udg_Time - (udg_Time/60)*60))
endfunction
// . . .
function InitTrig_Init takes nothing returns nothing
  call Start() // inline should be done
  set mbi = MultiboardGetItem(bj_lastCreatedMultiboard, udg_Rows[12] - 1, 0)
  call TimerStart(CreateTimer(), 1.0, true, function GameTime)
endfunction

Еще было бы неплохо вынести текст "Время игры:" в отдельный столбик (чтобы лишний раз не задавать его, ибо текст статичен).
Ах да, еще и заинлайнить функцию Start() сразу в инициализацию.

Отредактировано ShadoW DaemoN, 09.09.2008 в 17:34.
Старый 09.09.2008, 12:08
J
expert
offline
Опыт: 48,447
Активность:
Цитата:
Сообщение от ShadoW DaemoN
Смысл заносить результат от Get...() в переменную, если она используется не более трех раз?
Потому что иначе ты эти точки потом не удалиш
нужно было просто сказать "юзай координаты"

ShadoW DaemoN меня удивляет как только ты мог оставить без внимания "секнды, десятки секунд"
логичнее было бы оставить просто секунды, и если сек больше 10 то добовлять "0"

+ у тебя ошибка в коде

Отредактировано Jon, 09.09.2008 в 13:03.
Старый 09.09.2008, 12:44
ShadoW DaemoN

offline
Опыт: 37,078
Активность:
Jon, я говорю про более общие случаи. В данном же коде целесообразней применить функции, работающие с координатами (что, собственно, и было мною показано).
А вот зачем результат от GetPlayerSlotState(Player(i)) заносить в переменную, для меня остается загадкой ^_^
Старый 09.09.2008, 12:49
adic3x

offline
Опыт: 108,439
Активность:
Код:
// .386 xD

globals
 multiboarditem mbi_x=null

 integer time=0x00
endglobals

function Per takes nothing returns nothing
 set time=time+0x01

 call MultiboardSetItemValue(mbi_x, "|cffff0000"+I2S(time/0x3c)+":"+I2S(time-time/0x3c*0x3c)+"|r")
 call MultiboardReleaseItem(mbi_x)
endfunction


function init takes nothing returns nothing

 set udg_RedFlag=CreateDestructable('Dofw', x., y., 315., .8, 0x01)
 set udg_BlueFlag=CreateDestructable('LTcr', x., y., 235., .8, 0x01)

 set udg_Colour[0x00]="|cffff0000"
 set udg_Colour[0x01]="|cff0000ff"
 set udg_Colour[0x02]="|cff00ffff"
 set udg_Colour[0x03]="|cff800080"
 // --->

 set udg_NumberOfPlayers=%2I(GetPlayerSlotState(Player(0x00)))+%2I(GetPlayerSlotState  (Player(0x01)))+%2I(GetPlayerSlotState(Player(0x02)))+%2I(GetPlayerSlotState(Pla  yer(0x031)))
 // --->

 call SetPlayerState(Player(0x00), PLAYER_STATE_GIVES_BOUNTY, 0x01)
 call SetPlayerState(Player(0x01), PLAYER_STATE_GIVES_BOUNTY, 0x01)
 call SetPlayerState(Player(0x02), PLAYER_STATE_GIVES_BOUNTY, 0x01)
 call SetPlayerState(Player(0x03), PLAYER_STATE_GIVES_BOUNTY, 0x01)
 // ---> 

 call TimerStart(CreateTimer(), 1., true, function Per)

 set mbi_x=MultiboardGetItem(board, x, y)

endfunction


насчет таймера пистаь щас влом)
насчет счетчика игроков неуверен, надо зрить что и когда и как оно возращает, возможно там таки надо сравниваться с константой и использовать B2I

заносить строки в массив - хз

Отредактировано ADOLF, 09.09.2008 в 16:48.
Старый 09.09.2008, 15:28
J
expert
offline
Опыт: 48,447
Активность:
эм... чето я непонял причем тут udg_knb_unit[i] > udg_knb_msize... может быть имелось ввиду i > udg_knb_msize?

ответ - я предпочел бы первый вариант

P.S.
как я понял ты пишеш систему динамеческого выделения памяти, т.е. просто ищещ свободную ячейку в массиве, заполняш, ищещ еще, заполняеш, если удалить нужно то удаляеш и снава потом заполняеш..........
тут лучше использовать стек свободных индексом, тогда можно вообще без цыкла обойтись
Старый 18.10.2008, 01:33
J
expert
offline
Опыт: 48,447
Активность:
писал чисто отруки, непроверял, по теории должно робить...
Код:
globals
    constant integer MININDEX = 1
    constant integer MAXINDEX = 300
    integer array NextOpenList
    integer FirstOpen
    integer TotalOpen
endglobals

function FineOpenIndex takes nothing returns integer
    local integer Slot = FirstOpen
    set FirstOpen = NextOpenList[Slot]
    set TotalOpen = TotalOpen - 1
    set NextOpenList[Slot] = -1
    return Slot
endfunction

function IndexIsOpen takes integer idx returns boolean
    return NextOpenList[idx] != -1
endfunction

function CleanIndex takes integer idx returns nothing
    if TotalOpen > 0 then
        set NextOpenList[idx] = FirstOpen
    else
        set NextOpenList[idx] = idx
    endif
    set TotalOpen = TotalOpen + 1
    set FirstOpen = idx
endfunction

function Init takes nothing returns nothing
    local integer i = MININDEX
    loop
        exitwhen i >= MAXSIZE
        set NextOpenList[i] = i+1
        set i = i + 1
    endloop
    set NextOpenList[i] = i
    set TotalOpen = MAXINDEX-MININDEX+1
    set FirstOpen = MININDEX
endfunction

Отредактировано Jon, 18.10.2008 в 02:22.
Старый 18.10.2008, 01:57
Toadcop

offline
Опыт: 54,313
Активность:
имхо бредово =\ ... нехочю сейчас полностью в логику въезжать.
здесь ТОКА 2 фичи.
  1. выделить УНИКАЛЬНЫЙ индекс
  2. иметь ВСЕ индексы вплотную. т.е. что бы луп делать оптимально
ну а оба вместе результат достигаютьса совмещением этих двух вещей =)
т.е.
иммем алгоритм типа
стек свободных хендлов - если он пустой - макс выделеный хендл +1 это уникальный ИД
плотный стек (как я его называю ну или лист что бы там небыло) делаетьса примерно так
учитывая что у нас елементов не больше 8000...
используем полученый уникальный ИД (см. выше) для записи в массив "позицый."
т.е. типо
addelement ->
set max=max+1
set elem[max]=x наш уникальный ИД
set pos[x]=max// нумеруем позицыю елемента.
removeelement ->
здесь фичя заключаетьса в перетаскивание последнего елемента на позицыю удаляемого тем самым мы "заделываем" дыру и уменьшаем кол елементов. т.е.
set elem[x]=elem[max]
set pos[elem[max]]=pos[x]
ну там обнулять можно можно и не обнулять
set max=max-1
ну на мой взгляд это "перфект метод" ибо это как бы 2 независимые структуры но тем не менее их можно легко и "правильно" связать.
не про ресайкл уникального ИД я просто не писал но там просто помещаетьса елемент в нужный стэк типо
set max=max+1
set stack[max]=x
...
ну вот типо того вообще это обсуждалось не раз уже на форуме ^_^
Старый 18.10.2008, 02:16
J
expert
offline
Опыт: 48,447
Активность:
Uksus потомучто во перых, никакого цыкла не будет, т.к. я сказал тебе как делать выше, ну или как тоадкоп сказал, а иначе это уже ну никак не быстро
во вторых я неуверен в разности скорости работы локалок и глобалок, не ну в яп разница есть конешно, и чисто логически предпологается разница, но это же джасс, кто-нить пусть даст исходник инторпретатора и там посмотрим...
ну даже если и есть разница я неуверен что она хоть както проявится... а создание локалки уже явно не в оптимальность
Старый 18.10.2008, 02:48
Toadcop

offline
Опыт: 54,313
Активность:
локалкам надо еще инцыализироватьса ;) т.е. если операцый до 6 где то... (с одной и той же переменой) то 100% лутче глобалку потом потихоньку локалки стают выгодней... но это зпдротство омг. ХОТЯ факт в том что иммено аллокацыя локальной пеменой не такая уж и быстрая почти как зипись в кеш чуть быстрей... (в статик кеш т.е. строки вбиты а не перемены и тем более не клеютьса)
Старый 18.10.2008, 02:55
adic3x

offline
Опыт: 108,439
Активность:
сабж, локалки не будут намного быстрее, даже в нагруженном цикле)
кста позрить аллокацию свободного индекса в вЖасс, вполне этичная штука
странный у жоника стек...) хотя, +1 к Тс в том плане что влом вникать чВ
Старый 18.10.2008, 08:54
Ranger21
I love beatiul days XD
offline
Опыт: 13,274
Активность:
Код:
globals
 group gr_temp=CreateGroup()
 boolexpr ex=null
endglobals

function xXx takes nothing returns boolean
 // action
 return false
endfunction

 // --->
 call GroupEnumUnitsInRange(gr_temp, x, y, r, ex)
 // <---

function init takes nothing returns nothin
 set ex=Condition(function xXx)
endfunction


Извиняюсь за поднятие топика, но лучше тут спросить...

А собственно, эта функция подходит для MUI способностей?
Я в плане том, что тут группа глобалка - хотя и происходит создание, но ведь она одна может быть ток?
В одно время несколько раз может запускаться call GroupEnumUnitsInRange(gr_temp, x, y, r, ex) или нет?
Старый 18.04.2009, 20:23
Закрытая тема

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск

Ваши права в разделе
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы можете скачивать файлы

BB-коды Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход



Часовой пояс GMT +3, время: 18:09.