Хм, всегда думал она именно так и работает... Правда насколько понимаю это коэффициент от текущего значения, то есть
SetUnitTimeScale(u, 5)
SetUnitTimeScale(u, 5)
увеличение скорости в 25 раз
map_maiker, склоны = "искривление" + модель склона. Для летающих делаешь триггер корректирующий высоту полета. Воду из катомных моделей собирать надо будет.
МрачныйВорон, дебаггер от берги работает только для триггеров и таймеров.
local realTimerStart = TimerStart
TimerStart = function(timer, duration, repeating, callback)
local pcallback = function()
if callback == nil then return end
local status, err = pcall(callback)
if not status then
print(err)
end
end
realTimerStart(timer, duration, repeating, pcallback)
end
Есть функция pcall, которой берги и пользуется. www.lua.org/pil/8.4.html Она позволяет вызвать какую-то функцию таким образом, что можно отследить ошибку внутри функции без прерывания потока, потом можно ее вывести например через print. Таким же образом можно ее использовать например в инициализации модуля. Кривоватенько, но чтобы передать основную идею:
math.lua
function init()
local math = {}
function math.add(a, b)
return a + b
end
return math + 1
end
local success, result = pcall(init)
if (success) then
return result
else
print(err)
end
В этом случае будет выведена ошибка связанная со строкой "return math + 1", так как нельзя складывать таблицу и число. При этом выполнение потока не прервется.
МрачныйВорон, если используешь сторонний редактор кода, лучше весь код использовать внутри pcall или xpcall. Тогда все эти "обрывы" можно будет выводить с текстом ошибки.
МрачныйВорон, 'uhpr' - id этого филда (u - unit h - health p - points r - regeneration). Они в архиве игры где-то перечислены, уже не помню где.
ConvertUnitRealField(FourCC('uhpr')) == UNIT_RF_HIT_POINTS_REGENERATION_RATE
МрачныйВорон, абсолютно не тестировал, но примерно так
Screen.lua
local Screen = {}
Screen.pos = {0, 0}
Screen.size = {0.8, 0.6}
local pixel_w = 0
local pixel_h = 0
local function update()
local cur_pixel_width = BlzGetLocalClientWidth()
local cur_pixel_height = BlzGetLocalClientHeight()
if (cur_pixel_width == pixel_w and cur_pixel_height == pixel_h) then
return
end
pixel_w = cur_pixel_width
pixel_h = cur_pixel_height
local default_zone_width = cur_pixel_height * 0.8 / 0.6
Screen.size[0] = 0.8 * cur_pixel_width / default_zone_width
Screen.pos[0] = - (Screen.__size.x - 0.8) / 2
end
local timer = CreateTimer()
TimerStart(timer, 1, true, update)
update()
return Screen
Grid
local Grid = {}
local COLS = 7
local ROWS = 7
local __pos = {0, 0}
local __size = {0, 0}
local btns = {}
local tools = {}
local parent = BlzGetFrameByName("ConsoleUIBackdrop", 0)
for x = 1, COLS do
btns[x] = {}
tools[x] = {}
for y = 1, ROWS do
btns[x][y] = BlzCreateFrameByType("GLUETEXTBUTTON", "MyButton", parent, "ScriptDialogButton", 0)
BlzFrameSetAlpha(btns[x][y], 25)
BlzFrameSetAbsPoint(btns[x][y], FRAMEPOINT_BOTTOMLEFT, 0, 0)
BlzFrameSetSize(btns[x][y], 0, 0)
tools[x][y] = BlzCreateFrameByType("FRAME", "FaceFrame", parent, "", 0)
BlzFrameSetAlpha(tools[x][y], 0)
BlzFrameSetAbsPoint(tools[x][y], FRAMEPOINT_BOTTOMLEFT, 0, 0)
BlzFrameSetSize(tools[x][y], 0, 0)
BlzFrameSetTooltip(btns[x][y], tools[x][y])
end
end
local function __updateGrid()
local w = __size[0] / COLS
local h = __size[1] / ROWS
for x = 1, COLS do
for y = 1, ROWS do
BlzFrameSetAbsPoint(btns[x][y], FRAMEPOINT_BOTTOMLEFT, __pos[0] + x * w, __pos[1] + y * h)
end
end
end
function Grid.setPos(pos)
__pos = pos
__updateGrid()
end
function Grid.setSize(size)
__size = size
__updateGrid()
end
-- return true, x, y, w, h
-- return false
function Grid.mouseROI()
local w = __size[0] / COLS
local h = __size[1] / ROWS
for x = 1, COLS do
for y = 1, ROWS do
local found = BlzFrameIsVisible(tools[x][y])
if (found) then
return true, __pos[0] + x * w, __pos[1] + y * h, w, h
end
end
end
return false
end
return Grid
Detector
local Screen = require('Screen')
local Grid = require('Grid')
local Detector = {}
local timer = CreateTimer()
local ROI = 3
local PREC = 0.01
Detector.x = 0
Detector.y = 0
Detector.w = 0
Detector.h = 0
local function __getBetterPos()
local t = CreateTimer()
TimerStart(t, 0.025, false, function()
DestroyTimer(t)
local found, x, y, w, h = Grid.mouseROI()
Detector.x = x
Detector.y = y
Detector.w = w
Detector.h = h
if (not found) then
return
end
if (w > PREC or h > PREC) then
__getBetterPos()
end
Grid.setPos({x - w * (ROI - 1) / 2, y - h * (ROI - 1) / 2})
Grid.setSize({w * ROI, h * ROI})
end)
end
local timer = CreateTimer()
TimerStart(t, 0.5, true, function()
Detector.x = Screen.pos[0]
Detector.y = Screen.pos[1]
Detector.w = Screen.size[0]
Detector.h = Screen.size[1]
__getBetterPos()
end)
return Detector
Сделал свою реализацию, правда на TypeScript и своих либах, но думаю тут главное уловить суть. Несмотря на код, у всех фреймов реальный предок - BlzGetFrameByName("ConsoleUIBackdrop", 0). В видео мерцание, вызвано неполной прозрачность фреймов, для демонстрации. Координаты обновляются примерно каждые 0.2сек. Используется 64 фрейма.
Основная идея была сделать сетку из GlueTextButton (в коде сетка 8х8), в сетке с помощью определения видимости Tooltip определяется ячейка, содержащая курсор. Как оказалось работает гораздо быстрее ивента FRAMEEVENT_MOUSE_ENTER (раз в 10).
Сначала сетка строится на весь экран, определяется ячейка с курсором. Вокруг этой ячейки выделяется регион интереса (3х3) и сетка перестраивается в этом регионе. Процедура повторяется пока точность не достигнет заданной или пока сетка не потеряет курсор. Стоит добавить выходные фильтры.
Работает в том числе вне 8:6
Видео
Grid.ts
import * as Frame from '../../FrameExt'
import { Color, Vec2 } from '../../Utils'
const COLOR = new Color(0, 0, 0, 0.1)
export class MouseDetectGrid extends Frame.SimpleEmpty {
constructor(cols: number, rows: number){
super()
this.__grid_btn = []
this.__grid_tool = []
for (let x = 0; x < cols; x++){
this.__grid_btn.push([])
this.__grid_tool.push([])
for (let y = 0; y < rows; y++){
let btn = new Frame.GlueTextButton()
this.__grid_btn[x].push(btn)
btn.parent = this
btn.color = COLOR
let tool = new Frame.Backdrop()
this.__grid_tool[x].push(tool)
tool.visible = false
tool.color = new Color(0, 0, 0, 0)
BlzFrameSetTooltip(btn.handle, tool.handle)
}
}
}
getMousePos(){
for (let x = 0; x < this.__grid_btn.length; x++){
for (let y = 0; y < this.__grid_btn[x].length; y++){
let tool = this.__grid_tool[x][y]
if (tool.visible){
let btn = this.__grid_btn[x][y]
return $multi(true, this.pos.add(btn.pos), btn.size)
}
}
}
return $multi(false, this.pos, this.size)
}
protected _set_size(size: Vec2){
super._set_size(size)
let btn_size = new Vec2(size.x / this.__grid_btn.length,
size.y / this.__grid_btn[0].length)
for (let x = 0; x < this.__grid_btn.length; x++){
for (let y = 0; y < this.__grid_btn[x].length; y++){
this.__grid_btn[x][y].size = btn_size
this.__grid_btn[x][y].pos = new Vec2(x * btn_size.x, y * btn_size.y)
}
}
}
private __grid_btn: Frame.GlueTextButton[][]
private __grid_tool: Frame.Backdrop[][]
}
MouseDetector.ts
import * as Frame from '../../FrameExt'
import { hTimer } from '../../Handle'
import { Vec2 } from '../../Utils'
import { MouseDetectGrid } from './Grid'
const STEP_TIME = 0.025
const GRID_SIZE = 8
const ROI_SIZE = 3
export class MouseDetector {
constructor(){
this.precision = 0.01
this.__pos = Frame.Screen.pos
this.__size = Frame.Screen.size
this.__grid = new MouseDetectGrid(GRID_SIZE, GRID_SIZE)
let t = new hTimer()
t.addAction(() => {
this.__pos = Frame.Screen.pos
this.__size = Frame.Screen.size
this.__grid.pos = this.__pos
this.__grid.size = this.__size
this.__getBetterPos()
})
let period = STEP_TIME
let tmp = this.precision
while (tmp < Frame.Screen.size.x){
tmp *= GRID_SIZE / ROI_SIZE
period += STEP_TIME
}
t.start(period, true)
}
getMouse(){
return this.__pos
}
private __getBetterPos(){
let t = new hTimer()
t.addAction(() => {
t.destroy()
let found: boolean
[found, this.__pos, this.__size] = this.__grid.getMousePos()
if (!found){
return
}
this.__grid.pos = this.__pos.sub(this.__size.mult((ROI_SIZE - 1) / 2))
this.__grid.size = this.__size.mult(ROI_SIZE)
print(this.__pos.toString(), this.__size.toString())
if (this.__size.x > this.precision || this.__size.y > this.precision){
this.__getBetterPos()
}
})
t.start(STEP_TIME, false)
}
precision: number
private __pos: Vec2
private __size: Vec2
private __grid: MouseDetectGrid
}
PT153, уверен, что под капотом множественный return всегда через таблицы?
Вроде все происходит без упаковки в таблицу в первом случае.
return a, b
return {a, b}
МрачныйВорон, Несколько значений по одному ключу? Можно, но либо упаковав их в таблицу (то есть на самом деле возвращает только 1 объект - таблицу), либо через метатаблицы, но это сложнее.
А для автоматического удаления неиспользуемых данных из таблиц нужно использовать метаметод __mode.
Много интересного и непонятного, по началу, по метатаблицам habr.com/ru/post/346892
function newArray(dim_count, dim_size)
local arr = {}
for i = 1, dim_size do
if (dim_count > 1) then
arr[i] = newArray(dim_count - 1, dim_size)
end
end
return arr
end
local a = newArray(2, 10)
a[1][1] = 5 -- OK
a[1][1][1] = 5 -- Error
a[12][12] = 5 -- Error
print(a[1][1]) -- a[1][1] == 5
Bergi_Bear, преодолеть, согласен, не получится. Но была у меня мысль, что у каждого игрока есть невидимый юнит, скажем так, некоторая сущность для физики, определяющая хит-боксы. Именно они синхронизируются у игроков. При этом каждый локальный игрок не ждем пока эти сущности синхронизируются, а управляет своим effect, который для игрока локального выглядит как его персонаж и мгновенно реализует действия игрока. Затем физические сущности синхронизируют эти действия. Задержку не изменит, но уменьшит чувство заторможенности персонажа. Сдается мне что-то подобное работает в близзов в Overwatch. Ведь обмен данными с сервером там достаточно редкий, сейчас кажется 60 тиков/сек, а до этого было вроде 30.
Bergi_Bear, нашел способ на 99% избавиться от проблемы. Для изображения 64х64 делаю новую картинку с 2 слоями. Фоновый цвет удаляю. В одном слое ставлю по центру нужное изображение, в другом слое то же самое изображение только увеличиваю до 126х126 и 1 альфа канала.
» WarCraft 3 / Нативка SetUnitTimeScale
SetUnitTimeScale(u, 5)
SetUnitTimeScale(u, 5)
увеличение скорости в 25 раз
Отредактирован Nelloy
» WarCraft 3 / Запуск .exe из архива карты
» WarCraft 3 / Lua: как вызвать без аргументов функцию?
Отредактирован Nelloy
» WarCraft 3 / Lua: как вызвать без аргументов функцию?
math.lua
» WarCraft 3 / Lua: как вызвать без аргументов функцию?
Отредактирован Nelloy
» WarCraft 3 / Реген хп на джассе
ConvertUnitRealField(FourCC('uhpr')) == UNIT_RF_HIT_POINTS_REGENERATION_RATE
» WarCraft 3 / Реген хп на джассе
» WarCraft 3 / Реген хп на джассе
» WarCraft 3 / Реген хп на джассе
» WarCraft 3 / Ошибка в скрипте (Lua)
Отредактирован Nelloy
» WarCraft 3 / Отслеживание мышки
Отредактирован Nelloy
» WarCraft 3 / Отслеживание мышки
Основная идея была сделать сетку из GlueTextButton (в коде сетка 8х8), в сетке с помощью определения видимости Tooltip определяется ячейка, содержащая курсор. Как оказалось работает гораздо быстрее ивента FRAMEEVENT_MOUSE_ENTER (раз в 10).
Сначала сетка строится на весь экран, определяется ячейка с курсором. Вокруг этой ячейки выделяется регион интереса (3х3) и сетка перестраивается в этом регионе. Процедура повторяется пока точность не достигнет заданной или пока сетка не потеряет курсор. Стоит добавить выходные фильтры.
Работает в том числе вне 8:6
Отредактирован Nelloy
» WarCraft 3 / Отслеживание мышки
Отредактирован Nelloy
» WarCraft 3 / Отслеживание мышки
» WarCraft 3 / lua: ошибка
» WarCraft 3 / lua-дебаг система для варика существует? +двумерные массивы
цикл с предусловием, тело цикла выполняется до тех пор пока условие == true
например можно переделать обычных for в цикл while
Отредактирован Nelloy
» WarCraft 3 / lua-дебаг система для варика существует? +двумерные массивы
Вроде все происходит без упаковки в таблицу в первом случае.
return a, b
return {a, b}
А для автоматического удаления неиспользуемых данных из таблиц нужно использовать метаметод __mode.
Много интересного и непонятного, по началу, по метатаблицам habr.com/ru/post/346892
Отредактирован Nelloy
» WarCraft 3 / lua-дебаг система для варика существует? +двумерные массивы
» WarCraft 3 / Режим графики игрока SD или HD?
» WarCraft 3 / Вопрос по мемхаку.
» WarCraft 3 / Пеоны разбойники
» WarCraft 3 / Пеоны разбойники
» WarCraft 3 / CreateImage артефакты
» WarCraft 3 / CreateImage артефакты
Bergi_Bear, сохранил в формате paint.net, с сохранением слоев и в dds
» WarCraft 3 / CreateImage артефакты