Bergi_Bear, у тебя наверное старый cJass был.
Я уже год на нем пишу и могу уверенно сказать:
на cJass код пишется намного удобнее и быстрее
имхо - на обычном JASS дохера ненужных букв пишется
попробуй что я сделал)
GetMouseX() не может вызывать десинхрон, т.к не создает хендл
Десинхронило потому что ты делал условие if x>=1485 and x<=1485+61 and y>=1000 and y<=1064 then
на машинах других игроков X был равен 0 и поэтому он не проходил через условие, т.е получается что ты создавал игровой объект локально
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
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, оно на некоторых машинах выдает неправильное значение и может случиться десинхрон
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
здесь можно разделить нужные задачи на 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
//Ну и как говорилось выше - для синхронизации требуется время
Bergi_Bear, я же сказал, работа с объектами требует синхронизацию
если он просто хочет перемещать камеру - то ему не надо синхронизировать
т.е в любом случае ему понадобится GetLocalPlayer(), а при работе с объектами ещё и синхронизация
UPD:
перемещать камеру или редактировать интерфейс
вполне должно работать через GetLocalPlayer(), но если ты попытаешься как то работать с объектами используя эту инфу - то тебе понадобится синхронизация.
А к примеру чтобы тупо двигать игровую камеру по курсору - легко)
//===========================================================================
// 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 тоже имеет хендл)
DracoL1ch, SquareRoot внутри движка отличается от того что в JASS?
Ну я имел в виду близзарды делали sqrt в JASS по своему или юзнули тот что доступен в ++?
Ну чтобы не было так что я посчитаю 600.123 расстояния, а движок 600 ровно
DracoL1ch, но если я из JASS получаю 600.014832, а исходя из опыта - игра получает ровно 600.000000
Т.е я задаю юниту 832.000 по Y, даю приказ атаковать - он никуда не уходит и в момент атаки имеет эти координаты
Далее я задаю юниту уже 832.001 по Y, опять даю приказ атаковать и в момент атаки координаты уже около 824, имхо игра не позволила ему атаковать с 832.001, что говорит о точности вычислений в движке.
Как я знаю движок на C++ писался, поэтому тем более)
По идее уже пофиг на точность, буду юзать IsUnitInRange
В планах сделать поиск ближайшего юнита, там уже смогу юзнуть бд и думаю не будет важна точность
Я думаю, что 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 который считает по координатам), как раз то что надо и нагрузки меньше будет
короче, закрыл вопрос
так же как в ГУИ 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)))
т.е на самом деле в этой ситуации происходят два простых вычисления:
Наверное, тут роль может играть ещё ось Z. Ты ведь чисто по X и Y рассматриваешь?
высота в варкрафте не влияет на расстояние)
проверял уже
Но я уже сказал) Мне грубо говоря пофиг что там с дальностью атаки у юнитов, главное что она не превышает своего максимума
В данный момент я сомневаюсь в точности вычислений из под JASS
Т.к посчитал через теорему, получил 832.015
Посчитал просто Y2 минус Y1 получил 832.000
А если точность вычислений теоремы в JASS такая же как и в движке, то всё очень хорошо и можно будет закрыть вопрос.
Осталось подождать того кто сможет сказать это с уверенностью)
8gabriel8:
832.015 во всех случаях
слева, сверху, справа, снизу. И модель убирал и точку начала атаки
Убрал теорему Пифагора и посчитал просто по Y координатам и вышло ровно 832
Поставил 833 и показало 824.090
Я сделал вывод себе: теорема Пифагора немного неточная в варкрафте и юнит не всегда встает ровно в нужный радиус атаки (но при этом не превышает свой же доступный радиус атаки)
Короче, вот что нужно выяснить
Использует ли варкрафт на нативном уровне теорему так же как и в JASS?
Т.е в плане точности
К примеру игра получит расстояние 50, а в JASS будет 49.99999
Плохой пример, но думаю понятно
В AOE способностей игра вычитает физ. размер из расстояния между координатами и проверяет получилось или нет меньше требуемого AOE
Если смотреть на глаз, то именно так и выходит
Создаешь дамми, сохраняешь в SetUnitUserData нужный урон и заставляешь его кидать молоток в цель.
Цель получила урон, проверяешь является ли атакующий тем самым дамми, берешь урон из GetUnitUserData и наносишь его цели
Перед тем как кидать молоток, зарегистрируй событие на получение урона для цели.
И в самом получении урона делай проверку чтобы урон был больше 0.00 (т.к могут прилетать ложные срабатывания триггера)
не обязательно, у меня в одной карте окошко со списком ~1000 триггеров открылось за 3-4 сек
Ну где действие "Отключить триггер" и т.д, там же выбираешь триггер в списке
И автор вопрос сказал же)
через некоторое время
плюс вот это
да и просто открытие списка, где указаны типы юнита(Triggering unit, Entering unit, Casting unit и т.д.)
WindMaster, компы случайно не калькуляторы?)
На первом месте то что может создавать лаги - это если в обзоре редактора слишком много объектов или обзор на карту слишком большой (т.е карта 480x480 и ты смотришь на всю карту)
На втором месте - большое кол-во действий в триггере в котором идет работа
Остальные вещи никак не нагружают редактор
И то, при всем выше сказанном не должны так лагать простейшие гуи-окна
» WarCraft 3 / Перевод карты
» WarCraft 3 / Не могу одолеть GetLocalPlayer()!!!!!!
Я уже год на нем пишу и могу уверенно сказать:
на cJass код пишется намного удобнее и быстрее
имхо - на обычном JASS дохера ненужных букв пишется
Ред. Hodor
» WarCraft 3 / Не могу одолеть GetLocalPlayer()!!!!!!
GetMouseX() не может вызывать десинхрон, т.к не создает хендл
Десинхронило потому что ты делал условие if x>=1485 and x<=1485+61 and y>=1000 and y<=1064 then
на машинах других игроков X был равен 0 и поэтому он не проходил через условие, т.е получается что ты создавал игровой объект локально
Ред. Hodor
» WarCraft 3 / Не могу одолеть GetLocalPlayer()!!!!!!
Ред. Hodor
» WarCraft 3 / Не могу одолеть GetLocalPlayer()!!!!!!
вот пример:
переменная X имеет значение 0
далее
на машинах синего и остальных игроков X будет равен 0
а на машине красного игрока X будет равен 1
в самой функции там будет условие:
Ред. Hodor
» WarCraft 3 / Не могу одолеть GetLocalPlayer()!!!!!!
И не юзай IsUnitSelected, оно на некоторых машинах выдает неправильное значение и может случиться десинхрон
» WarCraft 3 / Не могу одолеть GetLocalPlayer()!!!!!!
» WarCraft 3 / RenderEdge(memhak)
В первом случае если не синхронизировать данные - то будет десинхрон
А во втором случае можно как угодно шаманить с GetLocalPlayer()
Если надо каждому игроку вывести координаты его мышки:
Если надо определенному игроку вывести координаты его мышки:
Если надо определенному игроку создать спецэффект:
А вот если нужно будет создать юнита в координатах мышки игрока:
Ред. Hodor
» WarCraft 3 / RenderEdge(memhak)
Bergi_Bear, я же сказал, работа с объектами требует синхронизацию
если он просто хочет перемещать камеру - то ему не надо синхронизировать
т.е в любом случае ему понадобится GetLocalPlayer(), а при работе с объектами ещё и синхронизация
UPD:
перемещать камеру или редактировать интерфейс
Ред. Hodor
» WarCraft 3 / RenderEdge(memhak)
Нужно чуть переделать SyncReal, чтобы синхронизировало два значения
» WarCraft 3 / RenderEdge(memhak)
А к примеру чтобы тупо двигать игровую камеру по курсору - легко)
Ред. Hodor
» WarCraft 3 / Вопрос о texttag
» WarCraft 3 / Нативный AOE поиск юнитов в JASS
Ну я имел в виду близзарды делали sqrt в JASS по своему или юзнули тот что доступен в ++?
Ну чтобы не было так что я посчитаю 600.123 расстояния, а движок 600 ровно
» WarCraft 3 / Нативный AOE поиск юнитов в JASS
Т.е я задаю юниту 832.000 по Y, даю приказ атаковать - он никуда не уходит и в момент атаки имеет эти координаты
Далее я задаю юниту уже 832.001 по Y, опять даю приказ атаковать и в момент атаки координаты уже около 824, имхо игра не позволила ему атаковать с 832.001, что говорит о точности вычислений в движке.
Как я знаю движок на C++ писался, поэтому тем более)
По идее уже пофиг на точность, буду юзать IsUnitInRange
В планах сделать поиск ближайшего юнита, там уже смогу юзнуть бд и думаю не будет важна точность
Ред. Hodor
» WarCraft 3 / Нативный AOE поиск юнитов в JASS
Это если поставить героя на расстоянии 833.000, то ему придется чуть чуть пройти, короче проехали.
Главное чтобы точность работы с float была такая же как в движке.
IsUnitInRange
Тут тоже считает по расстоянию между координатами)
До завтра подержу вопрос открытым, вдруг кто то ещё знаниями поделится)
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 который считает по координатам), как раз то что надо и нагрузки меньше будет
короче, закрыл вопрос
Ред. Hodor
» WarCraft 3 / Нативный AOE поиск юнитов в JASS
Беру из координат X2 Y2 вычитаю X1 Y1 и потом полученные dx dy по отдельности возвожу в квадрат и слагаю, в конце из полученного числа вычисляю корень
» WarCraft 3 / Нативный AOE поиск юнитов в JASS
проверял уже
Но я уже сказал) Мне грубо говоря пофиг что там с дальностью атаки у юнитов, главное что она не превышает своего максимума
В данный момент я сомневаюсь в точности вычислений из под JASS
Т.к посчитал через теорему, получил 832.015
Посчитал просто Y2 минус Y1 получил 832.000
А если точность вычислений теоремы в JASS такая же как и в движке, то всё очень хорошо и можно будет закрыть вопрос.
Осталось подождать того кто сможет сказать это с уверенностью)
Ред. Hodor
» WarCraft 3 / Нативный AOE поиск юнитов в JASS
832.015 во всех случаях
слева, сверху, справа, снизу. И модель убирал и точку начала атаки
Убрал теорему Пифагора и посчитал просто по Y координатам и вышло ровно 832
Поставил 833 и показало 824.090
Я сделал вывод себе: теорема Пифагора немного неточная в варкрафте и юнит не всегда встает ровно в нужный радиус атаки (но при этом не превышает свой же доступный радиус атаки)
Короче, вот что нужно выяснить
Использует ли варкрафт на нативном уровне теорему так же как и в JASS?
Т.е в плане точности
К примеру игра получит расстояние 50, а в JASS будет 49.99999
Плохой пример, но думаю понятно
Ред. Hodor
» WarCraft 3 / Нативный AOE поиск юнитов в JASS
8gabriel8: Т.е юнит может не остановиться именно на радиусе 832, а чуть дальше пройти до радиуса ~830?
» WarCraft 3 / Нативный AOE поиск юнитов в JASS
там просто по координатам)
В AOE способностей игра вычитает физ. размер из расстояния между координатами и проверяет получилось или нет меньше требуемого AOE
Если смотреть на глаз, то именно так и выходит
» WarCraft 3 / Нативный AOE поиск юнитов в JASS
физ. размер атакующего 32
физ. размер цели 200
Хочется узнать, использует ли движок такой же способ AOE поиска, который хочу сделать я
» WarCraft 3 / Нанесение урона в момент попадания по цели
Цель получила урон, проверяешь является ли атакующий тем самым дамми, берешь урон из GetUnitUserData и наносишь его цели
Перед тем как кидать молоток, зарегистрируй событие на получение урона для цели.
И в самом получении урона делай проверку чтобы урон был больше 0.00 (т.к могут прилетать ложные срабатывания триггера)
Ред. Hodor
» WarCraft 3 / Как ускорить работу редактора карт?
Ну где действие "Отключить триггер" и т.д, там же выбираешь триггер в списке
И автор вопрос сказал же) плюс вот это
Ред. Hodor
» WarCraft 3 / Как ускорить работу редактора карт?
На первом месте то что может создавать лаги - это если в обзоре редактора слишком много объектов или обзор на карту слишком большой (т.е карта 480x480 и ты смотришь на всю карту)
На втором месте - большое кол-во действий в триггере в котором идет работа
Остальные вещи никак не нагружают редактор
И то, при всем выше сказанном не должны так лагать простейшие гуи-окна
Ред. Hodor
» WarCraft 3 / Как ускорить работу редактора карт?