18

» WarCraft 3 / Не могу одолеть GetLocalPlayer()!!!!!!

Bergi_Bear, у тебя наверное старый cJass был.
Я уже год на нем пишу и могу уверенно сказать:
на cJass код пишется намного удобнее и быстрее
имхо - на обычном JASS дохера ненужных букв пишется
18

» WarCraft 3 / Не могу одолеть GetLocalPlayer()!!!!!!

попробуй что я сделал)
GetMouseX() не может вызывать десинхрон, т.к не создает хендл

Десинхронило потому что ты делал условие if x>=1485 and x<=1485+61 and y>=1000 and y<=1064 then
на машинах других игроков X был равен 0 и поэтому он не проходил через условие, т.е получается что ты создавал игровой объект локально
18

» WarCraft 3 / Не могу одолеть GetLocalPlayer()!!!!!!

Bergi_Bear, игрока не надо передавать, только у нужного игрока переменная будет положительной
вот пример:
переменная X имеет значение 0
далее
if GetLocalPlayer() == Player(0) then
	set x = 1
endif
далее вызываешь функцию и передаешь туда эту переменную X
на машинах синего и остальных игроков X будет равен 0
а на машине красного игрока X будет равен 1
в самой функции там будет условие:
if x == 0 then
	set eff = ""
endif
т.е получается у синего и остальных игроков модель эффекта будет спрятана, а у красного игрока нет, т.к x = 1
18

» WarCraft 3 / Не могу одолеть GetLocalPlayer()!!!!!!

а ещё лучше - упростить вот так:
function AddLocalEffect takes string eff, real x, real y, bool b returns effect
	if not b then
		set eff = ""
	endif
	return AddSpecialEffect(eff, x, y)
endfunction
bool это boolean, просто по привычке написал)

И не юзай IsUnitSelected, оно на некоторых машинах выдает неправильное значение и может случиться десинхрон
18

» WarCraft 3 / Не могу одолеть GetLocalPlayer()!!!!!!

function AddLocalEffect takes string eff, real x, real y, bool b returns effect
	local string e = ""
	if b then
		set e = eff
	endif
	return AddSpecialEffect(e, x, y)
endfunction

function Trig_TTTT_Actions takes nothing returns nothing
local real x = 0
local real y = 0
local integer k=0
local unit u=null
set u=h[0]
if GetLocalPlayer()==Player(0) then
set x=GetMouseX()// координаты мыши на экране у локального игрока
set y=GetMouseY()// в дебаг выводит всё верно
endif
if GetUnitAbilityLevel(u,'A001')>=1 and IsUnitSelected(u,GetOwningPlayer(u)) then
call AddLocalEffect("war3mapImported\\RedRange.mdl",GetUnitX(u),GetUnitY(u),x>=1485 and x<=1485+61 and y>=1000 and y<=1064)? // создание эффекта вызывает десинх
endif
set u=null
endfunction
18

» WarCraft 3 / RenderEdge(memhak)

здесь можно разделить нужные задачи на 2 категории:
  1. работа с игровыми объектами (юниты, разрушаемые объекты, таймеры и т.д)
  2. работа с визуальным отображением (положение камеры, интерфейс, и т.д)

В первом случае если не синхронизировать данные - то будет десинхрон
А во втором случае можно как угодно шаманить с GetLocalPlayer()

Если надо каждому игроку вывести координаты его мышки:
call BJDebugMsg(R2S(GetMouseX())+" - "+R2S(GetMouseY()))
//У каждого игрока на экране будут свои координаты мышки

Если надо определенному игроку вывести координаты его мышки:
if( GetLocalPlayer() == p ) then
	call BJDebugMsg(R2S(GetMouseX())+" - "+R2S(GetMouseY()))
endif
//У игрока "p" на экране будут выведены координаты его мышки

Если надо определенному игроку создать спецэффект:
local string s = ""
if( GetLocalPlayer() == p ) then
	set s = "effect.mdx"
endif
call AddSpecialEffect(s, x, y)
//Игроку "p" будет создан спецэффект в координатах x,y (спецэффект не будет виден другим игрокам)

А вот если нужно будет создать юнита в координатах мышки игрока:
call SyncReal(p, GetMouseX(), GetMouseY())
call CreateUnit(p, 'hfoo', sync_x, sync_y, 270.)
//Игроку "p" будет создан пехотинец в координатах его мышки
//Функцию SyncReal смотри в статье GetLocalPlayer(), но надо будет чуть её дополнить, чтобы она писала синхронизированные значение в глобалки sync_x, sync_y
//Ну и как говорилось выше - для синхронизации требуется время
18

» WarCraft 3 / RenderEdge(memhak)

А если не работать с объектами, а просто перемещать камеру к примеру, то вот:
if( GetLocalPlayer() == Player(0) )
{
	SetCameraPosition(GetMouseX(), GetMouseY())
}

Bergi_Bear, я же сказал, работа с объектами требует синхронизацию
если он просто хочет перемещать камеру - то ему не надо синхронизировать
т.е в любом случае ему понадобится GetLocalPlayer(), а при работе с объектами ещё и синхронизация

UPD:
перемещать камеру или редактировать интерфейс
18

» WarCraft 3 / RenderEdge(memhak)

Bergi_Bear:
GetLocalPlayer() как раз так и не нуждается в синхрониции, а человек спрашивал за неё

Нужно чуть переделать SyncReal, чтобы синхронизировало два значения
SyncReal(Player(0), GetMouseX(), GetMouseY())
CreateUnit(Player(0), 'hfoo', sync_float1, sync_float2, 270.)
18

» WarCraft 3 / RenderEdge(memhak)

вполне должно работать через GetLocalPlayer(), но если ты попытаешься как то работать с объектами используя эту инфу - то тебе понадобится синхронизация.
А к примеру чтобы тупо двигать игровую камеру по курсору - легко)
18

» WarCraft 3 / Вопрос о texttag

HandleCounter, нашел на xgm
//===========================================================================
//    A simple handle counter that shows:
//          * Maximum handles reached
//          * Elapsed seconds
//
//========== FOR VERSION 1.24+ ONLY ==========
//
//    The leaderboard can be accessed with
//          HandleCounter_LEADERBOARD
//    The clock (timer) can be accessed with
//          HandleCounter_CLOCK
//
//    This could be useful only if you'd like to see
//    if your map is leaking a lot of handles.
//    Otherwise it isn't really needed.
//
//    Requires a vJASS compiler to work.
//
//    To use: 
//          Create a trigger named HandleCounter,
//          convert to custom script and paste this.
//===========================================================================
library HandleCounter initializer Init
//===========================================================================
// Configurables
//===========================================================================
globals
// Leaderboard title/name.
    private constant string TITLE = "Handle Counter"
// Text that represents the time.
    private constant string TIME_TEXT = "Elapsed Time:"
// Should the leaderboard show time as well? True or false.
    private constant boolean SHOW_TIME = true
// How often should the handle count update (of course this is not for the clock).
    private constant real UPDATE_PERIOD = 0.25
// Number of locations created for better counting result.
    private constant integer STACK_END_TRESHOLD = 15
// Player(0) = Player 1 (Red); Player(1) = Player 2 (Blue); etc.

// Player color of the maximum handles text.
    private constant player MAX = Player(0)
// Player color of the time text.
    private constant player TIME = Player(1)
endglobals
//===========================================================================
// Do not edit bellow this point unless you know what you're doing.
//===========================================================================
globals
    public leaderboard LEADERBOARD = null 
    public timer CLOCK = null
    private integer CURRENT_HANDLE = 0
    private integer MAX_HANDLE = 0
    private integer SECONDS = 0
endglobals
private function UpdateTime takes nothing returns nothing
    set SECONDS = SECONDS + 1
    call LeaderboardSetItemLabel(LEADERBOARD, 1, TIME_TEXT)
    call LeaderboardSetItemValue(LEADERBOARD, 1, SECONDS)
endfunction
private function Callback takes nothing returns nothing
    local location array loc
    local integer a = 0
    local integer index 
    local integer prevIndex = 0
    local integer next = 0
    loop
        set loc[a] = Location(0., 0.)
        set index = GetHandleId(loc[a]) - 0x100000
        set a = a + 1
        if index == prevIndex + 1 then
            set next = next + 1
        else
            set next = 0
        endif
        set prevIndex = index
        exitwhen next >= STACK_END_TRESHOLD
    endloop
    call LeaderboardSetItemValue(LEADERBOARD, 0, index - a)
    loop
        set a = a - 1
        call RemoveLocation(loc[a])
        set loc[a] = null
        exitwhen a <= 0
    endloop
endfunction
private function Actions takes nothing returns nothing
    local timer tim = GetExpiredTimer()
    set LEADERBOARD = CreateLeaderboard()
    call LeaderboardSetLabel(LEADERBOARD, TITLE)
    call PlayerSetLeaderboard(GetLocalPlayer(), LEADERBOARD)
    call LeaderboardDisplay(LEADERBOARD, true)
    call TimerStart(tim, UPDATE_PERIOD, true, function Callback)
    call LeaderboardAddItem(LEADERBOARD, "Max Handles", 0, MAX)
    call LeaderboardSetSizeByItemCount(LEADERBOARD, 1)
    if SHOW_TIME then
        set CLOCK = CreateTimer()
        call TimerStart(CLOCK, 1., true, function UpdateTime)
        call LeaderboardAddItem(LEADERBOARD, "", 1, TIME)
        // Prevent leaderboard showing "1" during the first second.
        call LeaderboardSetItemLabel(LEADERBOARD, 1, TIME_TEXT)
        call LeaderboardSetItemValue(LEADERBOARD, 1, SECONDS)
        call LeaderboardSetSizeByItemCount(LEADERBOARD, 2)
    endif
    set tim = null
endfunction
private function Init takes nothing returns nothing
    call TimerStart(CreateTimer() , 0., false, function Actions)
endfunction
endlibrary 
Я так однажды понял что TriggerSleepAction тоже имеет хендл)
18

» WarCraft 3 / Нативный AOE поиск юнитов в JASS

DracoL1ch, SquareRoot внутри движка отличается от того что в JASS?
Ну я имел в виду близзарды делали sqrt в JASS по своему или юзнули тот что доступен в ++?

Ну чтобы не было так что я посчитаю 600.123 расстояния, а движок 600 ровно
18

» WarCraft 3 / Нативный AOE поиск юнитов в JASS

DracoL1ch, но если я из JASS получаю 600.014832, а исходя из опыта - игра получает ровно 600.000000
Т.е я задаю юниту 832.000 по Y, даю приказ атаковать - он никуда не уходит и в момент атаки имеет эти координаты
Далее я задаю юниту уже 832.001 по Y, опять даю приказ атаковать и в момент атаки координаты уже около 824, имхо игра не позволила ему атаковать с 832.001, что говорит о точности вычислений в движке.
Как я знаю движок на C++ писался, поэтому тем более)

По идее уже пофиг на точность, буду юзать IsUnitInRange

В планах сделать поиск ближайшего юнита, там уже смогу юзнуть бд и думаю не будет важна точность
18

» WarCraft 3 / Нативный AOE поиск юнитов в JASS

PT153:
Я думаю, что UrsaBoss опечатался и хотел написать 834.090.
824.090
Это если поставить героя на расстоянии 833.000, то ему придется чуть чуть пройти, короче проехали.

Главное чтобы точность работы с float была такая же как в движке.

IsUnitInRange
Тут тоже считает по расстоянию между координатами)

До завтра подержу вопрос открытым, вдруг кто то ещё знаниями поделится)
Выводи все 9 цифр после запятой. Или вот этой функцией.
function R2SX takes real r returns string
    return R2SW(r, 0, -1)
endfunction
832.014832


UPD:
как я уже определил с помощью BJDebugMsg - вся неточность в SquareRoot, т.е я передаю туда 692224.000 (квадрат 832), а мне возвращает 832.014832

короче, додумался сделать такой тест точности теоремы в движке:
оба юнита стоят в одинаковых X координатах, а атакующий смещен вверх от цели ровно на 832.000
832.000 это максимальный радиус атаки (т.к физ. размер атакующего 32, физ. размер цели 200 и дальность атаки 600)
если я задам атакующему координаты выше 832.000, то атакующий автоматически сдвинется с места и его координаты при атаке уже будут примерно 824 (округляя), а если я задам 832 или ниже, то атакующий никуда не сдвинется
Т.е при событии атаки я вычисляю разницу между Y координатой обоих целей

Это понятно
Я задаю 832 по Y и начинаю измерять расстояние, если я использую SquareRoot((y2-y1)*(y2-y1)) - то получаю 832.014832
делая нехитрые вычисления я нахожу "дальность атаки", т.е 832.014832 минус 200 и минус 32 и получаю 600,014832
Т.е атакующий по мнению SquareRoot "бьет с расстояния 600,014832", а это уже выше 600

А вот если я задам Y координату 832.014 или даже 832.001, то во время начала атаки используя разницу в Y координатах - будет около 824
Т.е получается что с 832.001 расстояния невозможно начать атаку и юнит "идет до цели"
Я ставлю обратно 832 в Y и всё замечательно

Учитывая то что я говорил выше - получается что SquareRoot в движке игре полностью точный, а SquareRoot в JASS нет

Попробовал Pow(dy*dy, .5), там такая же неточность, но уже не выше допустимого значения, а ниже
831.998901

Абсолютный бред
Сделал вот так: SquareRoot(SquareRoot(dy*dy)*SquareRoot(dy*dy))
И всё равно выдало 832.014832
Повторюсь, dy == 832

Столько часов делал бд со всеми физ. размерами и дальностями атаки, а оно вот как
Может быть есть какие нибудь способы сделать чтобы всё было точно?
Не предлагайте округлять, 832 это просто тестовое число, в игре же могут быть абсолютно разные числа


UPD:
извиняюсь, IsUnitsInRange считает не по координатам, а по физ. размерам + дальность (я думал из за Range в GroupEnumUnitsInRange который считает по координатам), как раз то что надо и нагрузки меньше будет
короче, закрыл вопрос
18

» WarCraft 3 / Нативный AOE поиск юнитов в JASS

8gabriel8:
Кстати, как именно ты считаешь через теорему?
так же как в ГУИ DistanceBetweenPoints
Беру из координат X2 Y2 вычитаю X1 Y1 и потом полученные dx dy по отдельности возвожу в квадрат и слагаю, в конце из полученного числа вычисляю корень
local real dx = GetUnitX(gg_unit_hdhw_0001) - GetUnitX(gg_unit_Hblm_0000)
local real dy = GetUnitY(gg_unit_hdhw_0001) - GetUnitY(gg_unit_Hblm_0000)
call BJDebugMsg(R2S(SquareRoot(dx * dx + dy * dy)))
т.е на самом деле в этой ситуации происходят два простых вычисления:
  1. 832 умножается на 832
  2. и потом из этого вычисляется корень
и корень равен 832.015
18

» WarCraft 3 / Нативный AOE поиск юнитов в JASS

8gabriel8:
Наверное, тут роль может играть ещё ось Z. Ты ведь чисто по X и Y рассматриваешь?
высота в варкрафте не влияет на расстояние)
проверял уже

Но я уже сказал) Мне грубо говоря пофиг что там с дальностью атаки у юнитов, главное что она не превышает своего максимума
В данный момент я сомневаюсь в точности вычислений из под JASS
Т.к посчитал через теорему, получил 832.015
Посчитал просто Y2 минус Y1 получил 832.000

А если точность вычислений теоремы в JASS такая же как и в движке, то всё очень хорошо и можно будет закрыть вопрос.
Осталось подождать того кто сможет сказать это с уверенностью)
18

» WarCraft 3 / Нативный AOE поиск юнитов в JASS

8gabriel8:
832.015 во всех случаях
слева, сверху, справа, снизу. И модель убирал и точку начала атаки

Убрал теорему Пифагора и посчитал просто по Y координатам и вышло ровно 832

Поставил 833 и показало 824.090

Я сделал вывод себе: теорема Пифагора немного неточная в варкрафте и юнит не всегда встает ровно в нужный радиус атаки (но при этом не превышает свой же доступный радиус атаки)

Короче, вот что нужно выяснить
Использует ли варкрафт на нативном уровне теорему так же как и в JASS?
Т.е в плане точности
К примеру игра получит расстояние 50, а в JASS будет 49.99999
Плохой пример, но думаю понятно
18

» WarCraft 3 / Нативный AOE поиск юнитов в JASS

меньше требуемого AOE
меньше или равно, чуть ошибся

8gabriel8:
А такая точность критична, ведь погрешность маленькая?
Наверное, тут может быть связано с точкой начала атаки у юнита в РО.
Т.е юнит может не остановиться именно на радиусе 832, а чуть дальше пройти до радиуса ~830?
18

» WarCraft 3 / Нативный AOE поиск юнитов в JASS

PT153:
А ландшафт плоский?
да
Я бы АОЕ поиск делал через GroupEnumUnitInRange.
там просто по координатам)

В AOE способностей игра вычитает физ. размер из расстояния между координатами и проверяет получилось или нет меньше требуемого AOE
Если смотреть на глаз, то именно так и выходит
18

» WarCraft 3 / Нативный AOE поиск юнитов в JASS

PT153:
А какая вообще дальность атаки?
у атакующего 600
физ. размер атакующего 32
физ. размер цели 200

Хочется узнать, использует ли движок такой же способ AOE поиска, который хочу сделать я
18

» WarCraft 3 / Нанесение урона в момент попадания по цели

Создаешь дамми, сохраняешь в SetUnitUserData нужный урон и заставляешь его кидать молоток в цель.
Цель получила урон, проверяешь является ли атакующий тем самым дамми, берешь урон из GetUnitUserData и наносишь его цели
Перед тем как кидать молоток, зарегистрируй событие на получение урона для цели.
И в самом получении урона делай проверку чтобы урон был больше 0.00 (т.к могут прилетать ложные срабатывания триггера)
18

» WarCraft 3 / Как ускорить работу редактора карт?

8gabriel8:
WindMaster, приложи карту, пусть UrsaBoss сам увидит.
не обязательно, у меня в одной карте окошко со списком ~1000 триггеров открылось за 3-4 сек
Ну где действие "Отключить триггер" и т.д, там же выбираешь триггер в списке

И автор вопрос сказал же)
через некоторое время
плюс вот это
да и просто открытие списка, где указаны типы юнита(Triggering unit, Entering unit, Casting unit и т.д.)
18

» WarCraft 3 / Как ускорить работу редактора карт?

WindMaster, компы случайно не калькуляторы?)
На первом месте то что может создавать лаги - это если в обзоре редактора слишком много объектов или обзор на карту слишком большой (т.е карта 480x480 и ты смотришь на всю карту)
На втором месте - большое кол-во действий в триггере в котором идет работа
Остальные вещи никак не нагружают редактор
И то, при всем выше сказанном не должны так лагать простейшие гуи-окна
18

» WarCraft 3 / Как ускорить работу редактора карт?

Когда начнет лагать - проверь состояние компьютера в диспетчере задач