Zeige Ergebnis 1 bis 13 von 13
  1. #1
    Sektionsleiter Maps Benutzerbild von WaterKnight
    Registriert seit
    Aug 2003
    BNet Account
    WaterKnight
    Beiträge
    4.420

    [LUA] SpellObjectCreation

    Für Channel-based Spells braucht man diesen ObjectMerger-Hotfix.

    Hi,
    Da kürzlich meine .w3a-Datei korrupt war, welche die Objekt-Editor-Fähigkeiten einer Map enthält und ich außerdem schon immer mal alle Fähigkeiten mit dem Jass-Code verknüpfen wollte, um einer modulhaften Schreibweise gerecht zu werden, habe ich mir einen Textmacro-ObjectMerger-Kombinations-Standard für Fähigkeiten auf Basis von Kanalisieren überlegt (geht aber auch bei anderen Fähigkeiten, da viele Felder ja bei jeder vorhanden sind). Die Systemfähigkeiten hatte ich sowieso schon lange über ObjectMerger abgewickelt, nur schrieb ich da immer einen Lua-Block hin und das sähe recht unbequem aus und wäre auch fehleranfällig, wenn ich das bei jedem Feature-Spell machen würde, die öfters mal ausgetauscht und verändert werden. Das Zweite ist, dass man gerne Objekt-Editor-Daten für die Trigger übernimmt, ohne alles manuell abzuschreiben. Also verbinde ich LUA- und Jass in Textmacros. Das große Manko ist, dass Jasshelper sich beim Aufrufen externer Tools ziemlich schwer tut, der ObjectMerger selber ist schnell, aber ihn jedesmal in neuem Externalblock zu callen, nicht. Ich verwende einen Textmacro-Parameter zum Auskommentieren, die Objekte müssen ja nicht bei jedem Speichern neu erzeugt werden.

    struct Spell  //zum Mitloggen
    method SetAreaRange takes integer level, integer value returns nothing
    method SetChannelTime takes integer level, real value returns nothing
    method SetCooldown takes integer level, real value returns nothing
    method SetManaCost takes integer level, integer value returns nothing
    method SetOrder takes Order value returns nothing //bzw. integer, bei mir ist Order eine extra Klasse
    method SetRange takes integer level, integer value returns nothing
    method SetTargetType takes integer value returns nothing

    static method CreateFromSelf takes integer self returns thistype
    endstruct

    struct SpellObjectCreation
    static constant integer TARGET_TYPE_IMMEDIATE = 0
    static constant integer TARGET_TYPE_PASSIVE = 1
    static constant integer TARGET_TYPE_POINT = 2
    static constant integer TARGET_TYPE_POINT_OR_UNIT = 3
    static constant integer TARGET_TYPE_UNIT = 4
    static Spell TEMP
    endstruct

    //! externalblock extension=lua ObjectMerger $FILENAME$
    //! i file = io.open("spellsDelete.lua", "r")

    //! i if (file ~= nil) then
    //! i delCur = file:read() + 0

    //! i for i = 0, delCur, 1 do
    //! i os.remove("spell"..i..".lua")
    //! i end

    //! i file:close()
    //! i end

    //! i file = io.open("spells.lua", "w+")

    //! i file:write(-1)

    //! i file:close()

    //! i file = io.open("spellsDelete.lua", "w+")

    //! i file:write(-1)

    //! i file:close()

    //! i file = io.open("objectMergerInput.lua", "w+")

    //! i file:close()
    //! endexternalblock

    //! textmacro Spell_OpenScope takes doExternal
    $doExternal$//! externalblock extension=lua ObjectMerger $FILENAME$
    //! i file = io.open("spells.lua", "r")

    //! i cur = file:read() + 1

    //! i file:close()

    //! i file = io.open("spells.lua", "w+")

    //! i file:write(cur)

    //! i file:close()

    //! i file = io.open("spellsDelete.lua", "r")

    //! i delCur = file:read() + 0

    //! i file:close()

    //! i if (cur > delCur) then
    //! i file = io.open("spellsDelete.lua", "w+")

    //! i file:write(cur)

    //! i file:close()
    //! i end

    //! i file = io.open("spell"..cur..".lua", "w+")

    //! i file:close()

    //! i function writeLua(code)
    //! i file = io.open("spells.lua", "r")

    //! i cur = file:read()

    //! i file:close()

    //! i file = io.open("spell"..cur..".lua", "a")

    //! i file:write(code)

    //! i file:close()
    //! i end

    //! i writeLua([[
    //! i Math = {}

    //! i Math.QUARTER_ANGLE = 1.57

    //! i function set(field, value, default)
    //! i if (value == nil) then
    //! i makechange(current, field, default)
    //! i else
    //! i makechange(current, field, value)
    //! i end
    //! i end

    //! i function setLv(field, level, value, default)
    //! i if (value == nil) then
    //! i makechange(current, field, level, default)
    //! i else
    //! i makechange(current, field, level, value)
    //! i end
    //! i end

    //! i function setLevelsAmount(value)
    //! i levelsAmount = value

    //! i if (value == 1) then
    //! i tooltip[1] = "|cff00bfff"..name.."|r"
    //! i else
    //! i for i = 1, value, 1 do
    //! i tooltip[i] = "|cff00bfff"..name.."|r [|cffffcc00Level "..i.."|r]"
    //! i end
    //! i end
    //! i end

    //! i function addData(name, values)
    //! i if (name == nil) then
    //! i return
    //! i end

    //! i it = 1

    //! i datasCount = datasCount + 1

    //! i datas[datasCount] = name
    //! i datasValue[datasCount] = {}

    //! i while (values[it] ~= nil) do
    //! i datasValue[datasCount][it] = values[it]

    //! i it = it + 1
    //! i end
    //! i end

    //! i areaRange = {}
    //! i castTime = {}
    //! i channelTime = {}
    //! i cooldown = {}
    //! i datas = {}
    //! i datasCount = 0
    //! i datasValue = {}
    //! i isHeroSpell = false
    //! i manaCost = {}
    //! i range = {}
    //! i showAreaRange = {}
    //! i targets = {}
    //! i tooltip = {}
    //! i uberTooltip = {}
    //! i ]])
    $doExternal$//! endexternalblock
    //! endtextmacro

    //! textmacro Spell_Create takes doExternal, var, raw, name
    $doExternal$//! externalblock extension=lua ObjectMerger $FILENAME$
    //! i function writeLua(code)
    //! i file = io.open("spells.lua", "r")

    //! i cur = file:read()

    //! i file:close()

    //! i file = io.open("spell"..cur..".lua", "a")

    //! i file:write(code)

    //! i file:close()
    //! i end

    //! i writeLua([[
    //! i name = "$name$"
    //! i raw = "$raw$"
    //! i ]])
    $doExternal$//! endexternalblock

    set $var$ = Spell.CreateFromSelf('$raw$')

    set SpellObjectCreation.TEMP = $var$

    call SpellObjectCreation.TEMP.SetName("$name$")
    //! endtextmacro

    //! textmacro Spell_SetLevelsAmount takes doExternal, value
    $doExternal$//! externalblock extension=lua ObjectMerger $FILENAME$
    //! i function writeLua(code)
    //! i file = io.open("test.lua", "a")

    //! i file:write(code)

    //! i file:close()
    //! i end

    //! i writeLua([[
    //! i setLevelsAmount($value$)
    //! i ]])
    $doExternal$//! endexternalblock

    call SpellObjectCreation.TEMP.SetLevelsAmount($value$)
    //! endtextmacro

    //! textmacro Spell_SetTypes takes doExternal, value
    $doExternal$//! externalblock extension=lua ObjectMerger $FILENAME$
    //! i function writeLua(code)
    //! i file = io.open("test.lua", "a")

    //! i file:write(code)

    //! i file:close()
    //! i end

    //! i writeLua([[
    //! i setobjecttype("abilities")

    //! i if ("$value$" == "NORMAL") then
    //! i channelBased = true
    //! i showAreaRange = {}
    //! i createobject("ANcl", raw)

    //! i set("acap", "")
    //! i set("acat", "")
    //! i set("aeat", "")
    //! i set("aher", "\0")
    //! i set("ahky", "")
    //! i set("anam", name)
    //! i set("ata0", "")
    //! i set("atat", "")
    //! i elseif ("$value$" == "PARALLEL_IMMEDIATE") then
    //! i createobject("Absk", raw)

    //! i set("ahky", "")
    //! i set("anam", name)
    //! i set("ata0", "")
    //! i set("atat", "")
    //! i elseif ("$value$" == "PASSIVE") then
    //! i createobject("Agyb", raw)

    //! i set("acap", "")
    //! i set("acat", "")
    //! i set("aeat", "")
    //! i set("aher", "\0")
    //! i set("ahky", "")
    //! i set("anam", name)
    //! i set("areq", "")
    //! i set("ata0", "")
    //! i set("atat", "")
    //! i elseif (string.sub("$value$", 1, 1 + 7 - 1) == "SPECIAL") then
    //! i createobject(string.sub("$value$", 1 + 7 + 1, string.len("$value$")), raw)

    //! i set("acap", "")
    //! i set("acat", "")
    //! i set("aeat", "")
    //! i set("aher", "\0")
    //! i set("ahky", "")
    //! i set("anam", name)
    //! i set("ata0", "")
    //! i set("atat", "")
    //! i end

    //! i if (levelsAmount == nil) then
    //! i setLevelsAmount(1)
    //! i end
    //! i ]])
    $doExternal$//! endexternalblock

    if (SpellObjectCreation.TEMP.GetLevelsAmount() == 0) then
    call SpellObjectCreation.TEMP.SetLevelsAmount(1)
    endif
    //! endtextmacro

    //! textmacro Spell_Finalize takes doExternal
    $doExternal$//! externalblock extension=lua ObjectMerger $FILENAME$
    //! i function writeLua(code)
    //! i file = io.open("spells.lua", "r")

    //! i cur = file:read()

    //! i file:close()

    //! i file = io.open("spell"..cur..".lua", "a")

    //! i file:write(code)

    //! i file:close()
    //! i end

    //! i writeLua([[
    //! i function replace(a, sub, rep)
    //! i c = 1

    //! i while (c < string.len(a) - string.len(sub) + 2) do
    //! i if (string.sub(a, c, c + string.len(sub) - 1) == sub) then
    //! i a = string.sub(a, 1, c - 1)..rep..string.sub(a, c + string.len(sub))
    //! i else
    //! i c = c + 1
    //! i end
    //! i end

    //! i return a
    //! i end

    //! i function replaceTags(a, level)
    //! i a = string.gsub(a, "<level>", level)
    //! i a = string.gsub(a, "<prevLevel>", level - 1)

    //! i a = string.gsub(a, "<areaRange>", areaRange[level])
    //! i a = string.gsub(a, "<channelTime>", channelTime[level])
    //! i a = string.gsub(a, "<cooldown>", cooldown[level])
    //! i a = string.gsub(a, "<manaCost>", manaCost[level])
    //! i for i = 1, levelsAmount, 1 do
    //! i a = string.gsub(a, "<areaRange"..i..">", areaRange[i])
    //! i a = string.gsub(a, "<channelTime"..i..">", channelTime[i])
    //! i a = string.gsub(a, "<cooldown"..i..">", cooldown[i])
    //! i a = string.gsub(a, "<manaCost"..i..">", manaCost[i])
    //! i end

    //! i for i = 1, datasCount, 1 do
    //! i if (datasValue[i][level] == nil) then
    //! i a = replace(a, "<"..datas[i]..">", datasValue[i][1])
    //! i else
    //! i a = replace(a, "<"..datas[i]..">", datasValue[i][level])
    //! i end

    //! i if (type(datasValue[i][level]) == "number") then
    //! i a = replace(a, "<"..datas[i]..",%>", (datasValue[i][level] * 100).."%")
    //! i end

    //! i for i2 = 1, levelsAmount, 1 do
    //! i a = replace(a, "<"..datas[i]..i2..">", datasValue[i][i2])

    //! i if (type(datasValue[i][i2]) == "number") then
    //! i a = replace(a, "<"..datas[i]..i2..",%>", (datasValue[i][i2] * 100).."%")
    //! i end
    //! i end
    //! i end

    //! i return a
    //! i end

    //! i set("alev", levelsAmount)

    //! i for i = 1, levelsAmount, 1 do
    //! i if (researchUberTooltip ~= nil) then
    //! i if (researchUberTooltip[i] ~= nil) then
    //! i researchUberTooltip[i] = replaceTags(researchUberTooltip[i], i)
    //! i end
    //! i end
    //! i if (uberTooltip[i] ~= nil) then
    //! i uberTooltip[i] = replaceTags(uberTooltip[i], i)
    //! i end
    //! i end

    //! i set("aani", animation, "")
    //! i set("aart", icon, "")
    //! i set("abpx", x, 0)
    //! i set("abpy", y, 0)
    //! i for i = 1, levelsAmount, 1 do
    //! i if (showAreaRange[i]) then
    //! i setLv("aare", i, areaRange[i], 0)
    //! i end
    //! i setLv("acas", i, castTime[i], 0)
    //! i setLv("acdn", i, cooldown[i], 0)
    //! i setLv("amcs", i, manaCost[i], 0)
    //! i setLv("aran", i, range[i], 0)
    //! i setLv("atar", i, targetsAll, "")
    //! i end

    //! i for i = 1, levelsAmount, 1 do
    //! i if (targets[i] ~= nil) then
    //! i setLv("atar", i, targets[i])
    //! i end
    //! i end

    //! i for i = 1, levelsAmount, 1 do
    //! i if (hotkey == nil) then
    //! i setLv("atp1", i, tooltip[i], "")
    //! i else
    //! i setLv("atp1", i, "(|cffffcc00"..hotkey.."|r) "..tooltip[i], "")
    //! i end
    //! i end
    //! i for i = 1, levelsAmount, 1 do
    //! i setLv("aub1", i, uberTooltip[i], "")
    //! i end
    //! i if (channelBased) then
    //! i if (order ~= nil) then
    //! i for i = 1, levelsAmount, 1 do
    //! i setLv("Ncl6", i, order)
    //! i end
    //! i end
    //! i for i = 1, levelsAmount, 1 do
    //! i setLv("Ncl1", i, channelTime[i], 0)
    //! i setLv("Ncl2", i, targetType, 0)
    //! i end

    //! i for i = 1, levelsAmount, 1 do
    //! i if (showAreaRange[i]) then
    //! i setLv("Ncl3", i, 19)
    //! i else
    //! i setLv("Ncl3", i, 17)
    //! i end
    //! i setLv("Ncl4", i, 0)
    //! i setLv("Ncl5", i, "\0")
    //! i end
    //! i end

    //! i if (isHeroSpell) then
    //! i for i = 1, 5, 1 do
    //! i createobject("ANeg", "C"..researchRaw..i)

    //! i set("abpx", 0)
    //! i set("abpy", 0)
    //! i set("ahky", "")
    //! i set("alev", levelsAmount)
    //! i set("anam", name.." Hero Spell Replacer "..i)
    //! i set("arac", "other")
    //! i set("aret", "")
    //! i set("arhk", "")
    //! i set("arpx", 0)
    //! i set("arut", "")
    //! i for i2 = 1, levelsAmount, 1 do
    //! i setLv("abuf", i2, "BHSR")
    //! i setLv("atp1", i2, "")
    //! i setLv("aub1", i2, "")
    //! i setLv("Neg1", i2, 0)
    //! i setLv("Neg2", i2, 0)
    //! i if (i2 == 1) then
    //! i setLv("Neg3", i2, "AHS"..i..",F"..researchRaw..i2)
    //! i else
    //! i setLv("Neg3", i2, "F"..researchRaw..(i2 - 1)..",F"..researchRaw..i2)
    //! i end
    //! i setLv("Neg4", i2, "")
    //! i setLv("Neg5", i2, "")
    //! i setLv("Neg6", i2, "")
    //! i end
    //! i end

    //! i for i = 1, levelsAmount, 1 do
    //! i createobject("ANcl", "F"..researchRaw..i)

    //! i set("aani", "")
    //! i set("aart", "")
    //! i set("abpx", 0)
    //! i set("acap", "")
    //! i set("acat", "")
    //! i set("aeat", "")
    //! i set("ahky", "")
    //! i set("alev", 1)
    //! i set("anam", name.." Hero Spell Learner "..i)
    //! i set("arac", "other")
    //! i for i2 = 1, 5, 1 do
    //! i setLv("aran", i2, 0)
    //! i setLv("Ncl1", i2, 0)
    //! i setLv("Ncl3", i2, 0)
    //! i setLv("Ncl4", i2, 0)
    //! i setLv("Ncl5", i2, "\0")
    //! i end
    //! i set("arar", icon, "")
    //! i set("aret", "Learn (|cffffcc00"..hotkey.."|r) |cff00bfff"..name.."|r [|cffffcc00Level %d|r]")
    //! i set("arhk", hotkey)
    //! i set("arut", researchUberTooltip[i], "")
    //! i set("ata0", "")
    //! i set("atat", "")
    //! i setLv("atp1", 1, "")
    //! i setLv("aub1", 1, "")
    //! i setLv("Ncl6", 1, "")
    //! i end
    //! i end
    //! i ]])

    //! i file = io.open("spell"..cur..".lua", "r")

    //! i code = file:read("*a")

    //! i file:close()

    //! i file = io.open("objectMergerInput.lua", "w+")

    //! i file:write(code)

    //! i file:close()

    //! i file = io.open("spells.lua", "r")

    //! i cur = file:read() - 1

    //! i file:close()

    //! i file = io.open("spells.lua", "w")

    //! i file:write(cur)

    //! i file:close()
    $doExternal$//! endexternalblock

    if (SpellObjectCreation.IS_HERO_SPELL) then
    call HeroSpell.InitSpell(SpellObjectCreation.TEMP, SpellObjectCreation.RESEARCH_RAW, SpellObjectCreation.RESEARCH_REPLACER_RAW)
    endif

    $doExternal$//! external ObjectMerger objectMergerInput.lua
    //! endtextmacro

    //! textmacro Spell_SetAnimation takes doExternal, value
    $doExternal$//! externalblock extension=lua ObjectMerger $FILENAME$
    //! i function writeLua(code)
    //! i file = io.open("spells.lua", "r")

    //! i cur = file:read()

    //! i file:close()

    //! i file = io.open("spell"..cur..".lua", "a")

    //! i file:write(code)

    //! i file:close()
    //! i end

    //! i writeLua([[
    //! i animation = "$value$"
    //! i ]])
    $doExternal$//! endexternalblock
    //! endtextmacro

    //! textmacro Spell_SetAreaRange takes doExternal, value, showGraphic
    $doExternal$//! externalblock extension=lua ObjectMerger $FILENAME$
    //! i function writeLua(code)
    //! i file = io.open("spells.lua", "r")

    //! i cur = file:read()

    //! i file:close()

    //! i file = io.open("spell"..cur..".lua", "a")

    //! i file:write(code)

    //! i file:close()
    //! i end

    //! i writeLua([[
    //! i areaRange[1] = $value$
    //! i showAreaRange[1] = $showGraphic$
    //! i ]])
    $doExternal$//! endexternalblock

    call SpellObjectCreation.TEMP.SetAreaRange(1, $value$)
    //! endtextmacro

    //! textmacro Spell_SetAreaRange3 takes doExternal, value, value2, value3, showGraphic
    $doExternal$//! externalblock extension=lua ObjectMerger $FILENAME$
    //! i function writeLua(code)
    //! i file = io.open("spells.lua", "r")

    //! i cur = file:read()

    //! i file:close()

    //! i file = io.open("spell"..cur..".lua", "a")

    //! i file:write(code)

    //! i file:close()
    //! i end

    //! i writeLua([[
    //! i areaRange[1] = $value$
    //! i areaRange[2] = $value2$
    //! i areaRange[3] = $value3$
    //! i showAreaRange[1] = $showGraphic$
    //! i showAreaRange[2] = $showGraphic$
    //! i showAreaRange[3] = $showGraphic$
    //! i ]])
    $doExternal$//! endexternalblock

    call SpellObjectCreation.TEMP.SetAreaRange(1, $value$)
    call SpellObjectCreation.TEMP.SetAreaRange(2, $value2$)
    call SpellObjectCreation.TEMP.SetAreaRange(3, $value3$)
    //! endtextmacro

    //! textmacro Spell_SetAreaRangeLv takes doExternal, level, value, showGraphic
    $doExternal$//! externalblock extension=lua ObjectMerger $FILENAME$
    //! i function writeLua(code)
    //! i file = io.open("spells.lua", "r")

    //! i cur = file:read()

    //! i file:close()

    //! i file = io.open("spell"..cur..".lua", "a")

    //! i file:write(code)

    //! i file:close()
    //! i end

    //! i writeLua([[
    //! i areaRange[$level$] = $value$
    //! i showAreaRange[$level$] = $showGraphic$
    //! i ]])
    $doExternal$//! endexternalblock

    call SpellObjectCreation.TEMP.SetAreaRange(level, $value$)
    //! endtextmacro

    //! textmacro Spell_SetButtonPosition takes doExternal, x, y
    $doExternal$//! externalblock extension=lua ObjectMerger $FILENAME$
    //! i function writeLua(code)
    //! i file = io.open("spells.lua", "r")

    //! i cur = file:read()

    //! i file:close()

    //! i file = io.open("spell"..cur..".lua", "a")

    //! i file:write(code)

    //! i file:close()
    //! i end

    //! i writeLua([[
    //! i x = $x$
    //! i y = $y$
    //! i ]])
    $doExternal$//! endexternalblock
    //! endtextmacro

    //! textmacro Spell_SetCastTime takes doExternal, value
    $doExternal$//! externalblock extension=lua ObjectMerger $FILENAME$
    //! i function writeLua(code)
    //! i file = io.open("spells.lua", "r")

    //! i cur = file:read()

    //! i file:close()

    //! i file = io.open("spell"..cur..".lua", "a")

    //! i file:write(code)

    //! i file:close()
    //! i end

    //! i writeLua([[
    //! i castTime[1] = $value$
    //! i ]])
    $doExternal$//! endexternalblock
    //! endtextmacro

    //! textmacro Spell_SetCastTime3 takes doExternal, value, value2, value3
    $doExternal$//! externalblock extension=lua ObjectMerger $FILENAME$
    //! i function writeLua(code)
    //! i file = io.open("spells.lua", "r")

    //! i cur = file:read()

    //! i file:close()

    //! i file = io.open("spell"..cur..".lua", "a")

    //! i file:write(code)

    //! i file:close()
    //! i end

    //! i writeLua([[
    //! i castTime[1] = $value$
    //! i castTime[2] = $value2$
    //! i castTime[3] = $value3$
    //! i ]])
    $doExternal$//! endexternalblock
    //! endtextmacro

    //! textmacro Spell_SetCastTimeLv takes doExternal, level, value
    $doExternal$//! externalblock extension=lua ObjectMerger $FILENAME$
    //! i function writeLua(code)
    //! i file = io.open("spells.lua", "r")

    //! i cur = file:read()

    //! i file:close()

    //! i file = io.open("spell"..cur..".lua", "a")

    //! i file:write(code)

    //! i file:close()
    //! i end

    //! i writeLua([[
    //! i castTime[$level$] = $value$
    //! i ]])
    $doExternal$//! endexternalblock
    //! endtextmacro

    //! textmacro Spell_SetChannelTime takes doExternal, value
    $doExternal$//! externalblock extension=lua ObjectMerger $FILENAME$
    //! i function writeLua(code)
    //! i file = io.open("spells.lua", "r")

    //! i cur = file:read()

    //! i file:close()

    //! i file = io.open("spell"..cur..".lua", "a")

    //! i file:write(code)

    //! i file:close()
    //! i end

    //! i writeLua([[
    //! i channelTime[1] = $value$
    //! i ]])
    $doExternal$//! endexternalblock

    call SpellObjectCreation.TEMP.SetChannelTime(1, $value$)
    //! endtextmacro

    //! textmacro Spell_SetChannelTime3 takes doExternal, value, value2, value3
    $doExternal$//! externalblock extension=lua ObjectMerger $FILENAME$
    //! i function writeLua(code)
    //! i file = io.open("spells.lua", "r")

    //! i cur = file:read()

    //! i file:close()

    //! i file = io.open("spell"..cur..".lua", "a")

    //! i file:write(code)

    //! i file:close()
    //! i end

    //! i writeLua([[
    //! i channelTime[1] = $value$
    //! i channelTime[2] = $value2$
    //! i channelTime[3] = $value3$
    //! i ]])
    $doExternal$//! endexternalblock

    call SpellObjectCreation.TEMP.SetChannelTime(1, $value$)
    call SpellObjectCreation.TEMP.SetChannelTime(2, $value2$)
    call SpellObjectCreation.TEMP.SetChannelTime(3, $value3$)
    //! endtextmacro

    //! textmacro Spell_SetChannelTimeLv takes doExternal, level, value
    $doExternal$//! externalblock extension=lua ObjectMerger $FILENAME$
    //! i function writeLua(code)
    //! i file = io.open("spells.lua", "r")

    //! i cur = file:read()

    //! i file:close()

    //! i file = io.open("spell"..cur..".lua", "a")

    //! i file:write(code)

    //! i file:close()
    //! i end

    //! i writeLua([[
    //! i channelTime[$level$] = $value$
    //! i ]])
    $doExternal$//! endexternalblock

    call SpellObjectCreation.TEMP.SetChannelTime($level$, $value$)
    //! endtextmacro

    //! textmacro Spell_SetCooldown takes doExternal, value
    $doExternal$//! externalblock extension=lua ObjectMerger $FILENAME$
    //! i function writeLua(code)
    //! i file = io.open("spells.lua", "r")

    //! i cur = file:read()

    //! i file:close()

    //! i file = io.open("spell"..cur..".lua", "a")

    //! i file:write(code)

    //! i file:close()
    //! i end

    //! i writeLua([[
    //! i cooldown[1] = $value$
    //! i ]])
    $doExternal$//! endexternalblock

    call SpellObjectCreation.TEMP.SetCooldown(1, $value$)
    //! endtextmacro

    //! textmacro Spell_SetCooldown3 takes doExternal, value, value2, value3
    $doExternal$//! externalblock extension=lua ObjectMerger $FILENAME$
    //! i function writeLua(code)
    //! i file = io.open("spells.lua", "r")

    //! i cur = file:read()

    //! i file:close()

    //! i file = io.open("spell"..cur..".lua", "a")

    //! i file:write(code)

    //! i file:close()
    //! i end

    //! i writeLua([[
    //! i cooldown[1] = $value$
    //! i cooldown[2] = $value2$
    //! i cooldown[3] = $value3$
    //! i ]])
    $doExternal$//! endexternalblock

    call SpellObjectCreation.TEMP.SetCooldown(1, $value$)
    call SpellObjectCreation.TEMP.SetCooldown(2, $value2$)
    call SpellObjectCreation.TEMP.SetCooldown(3, $value3$)
    //! endtextmacro

    //! textmacro Spell_SetCooldownLv takes doExternal, level, value
    $doExternal$//! externalblock extension=lua ObjectMerger $FILENAME$
    //! i function writeLua(code)
    //! i file = io.open("spells.lua", "r")

    //! i cur = file:read()

    //! i file:close()

    //! i file = io.open("spell"..cur..".lua", "a")

    //! i file:write(code)

    //! i file:close()
    //! i end

    //! i writeLua([[
    //! i cooldown[$level$] = $value$
    //! i ]])
    $doExternal$//! endexternalblock

    call SpellObjectCreation.TEMP.SetCooldown($level$, $value$)
    //! endtextmacro

    //! textmacro Spell_SetData takes doExternal, var, name, value
    $doExternal$//! externalblock extension=lua ObjectMerger $FILENAME$
    //! i function writeLua(code)
    //! i file = io.open("spells.lua", "r")

    //! i cur = file:read()

    //! i file:close()

    //! i file = io.open("spell"..cur..".lua", "a")

    //! i file:write(code)

    //! i file:close()
    //! i end

    //! i writeLua([[
    //! i addData("$name$1", {$value$})
    //! i ]])
    $doExternal$//! endexternalblock

    set thistype.$var$ = $value$
    //! endtextmacro

    //! textmacro Spell_SetData3 takes doExternal, var, name, value, value2, value3
    $doExternal$//! externalblock extension=lua ObjectMerger $FILENAME$
    //! i function writeLua(code)
    //! i file = io.open("spells.lua", "r")

    //! i cur = file:read()

    //! i file:close()

    //! i file = io.open("spell"..cur..".lua", "a")

    //! i file:write(code)

    //! i file:close()
    //! i end

    //! i writeLua([[
    //! i addData("$name$", {$value$, $value2$, $value3$})
    //! i ]])
    $doExternal$//! endexternalblock

    set thistype.$var$[1] = $value$
    set thistype.$var$[2] = $value2$
    set thistype.$var$[3] = $value3$
    //! endtextmacro

    //! textmacro Spell_SetIcon takes doExternal, value
    $doExternal$//! externalblock extension=lua ObjectMerger $FILENAME$
    //! i function writeLua(code)
    //! i file = io.open("spells.lua", "r")

    //! i cur = file:read()

    //! i file:close()

    //! i file = io.open("spell"..cur..".lua", "a")

    //! i file:write(code)

    //! i file:close()
    //! i end

    //! i writeLua([[
    //! i icon = "$value$"
    //! i ]])
    $doExternal$//! endexternalblock

    call SpellObjectCreation.TEMP.SetIcon("$value$")
    //! endtextmacro

    //! textmacro Spell_SetManaCost takes doExternal, value
    $doExternal$//! externalblock extension=lua ObjectMerger $FILENAME$
    //! i function writeLua(code)
    //! i file = io.open("spells.lua", "r")

    //! i cur = file:read()

    //! i file:close()

    //! i file = io.open("spell"..cur..".lua", "a")

    //! i file:write(code)

    //! i file:close()
    //! i end

    //! i writeLua([[
    //! i manaCost[1] = $value$
    //! i ]])
    $doExternal$//! endexternalblock

    call SpellObjectCreation.TEMP.SetManaCost(1, $value$)
    //! endtextmacro

    //! textmacro Spell_SetManaCost3 takes doExternal, value, value2, value3
    $doExternal$//! externalblock extension=lua ObjectMerger $FILENAME$
    //! i function writeLua(code)
    //! i file = io.open("spells.lua", "r")

    //! i cur = file:read()

    //! i file:close()

    //! i file = io.open("spell"..cur..".lua", "a")

    //! i file:write(code)

    //! i file:close()
    //! i end

    //! i writeLua([[
    //! i manaCost[1] = $value$
    //! i manaCost[2] = $value2$
    //! i manaCost[3] = $value3$
    //! i ]])
    $doExternal$//! endexternalblock

    call SpellObjectCreation.TEMP.SetManaCost(1, $value$)
    call SpellObjectCreation.TEMP.SetManaCost(2, $value2$)
    call SpellObjectCreation.TEMP.SetManaCost(3, $value3$)
    //! endtextmacro

    //! textmacro Spell_SetManaCostLv takes doExternal, level, value
    $doExternal$//! externalblock extension=lua ObjectMerger $FILENAME$
    //! i function writeLua(code)
    //! i file = io.open("spells.lua", "r")

    //! i cur = file:read()

    //! i file:close()

    //! i file = io.open("spell"..cur..".lua", "a")

    //! i file:write(code)

    //! i file:close()
    //! i end

    //! i writeLua([[
    //! i manaCost[$level$] = $value$
    //! i ]])
    $doExternal$//! endexternalblock

    call SpellObjectCreation.TEMP.SetManaCost($level$, $value$)
    //! endtextmacro

    //! textmacro Spell_SetOrder takes doExternal, value
    $doExternal$//! externalblock extension=lua ObjectMerger $FILENAME$
    //! i function writeLua(code)
    //! i file = io.open("spells.lua", "r")

    //! i cur = file:read()

    //! i file:close()

    //! i file = io.open("spell"..cur..".lua", "a")

    //! i file:write(code)

    //! i file:close()
    //! i end

    //! i writeLua([[
    //! i order = "$value$"
    //! i ]])
    $doExternal$//! endexternalblock

    call SpellObjectCreation.TEMP.SetOrder(Order.GetFromSelf(OrderId("$value$")))
    //! endtextmacro

    //! textmacro Spell_SetRange takes doExternal, value
    $doExternal$//! externalblock extension=lua ObjectMerger $FILENAME$
    //! i function writeLua(code)
    //! i file = io.open("spells.lua", "r")

    //! i cur = file:read()

    //! i file:close()

    //! i file = io.open("spell"..cur..".lua", "a")

    //! i file:write(code)

    //! i file:close()
    //! i end

    //! i writeLua([[
    //! i range[1] = $value$
    //! i ]])
    $doExternal$//! endexternalblock

    call SpellObjectCreation.TEMP.SetRange(1, $value$)
    //! endtextmacro

    //! textmacro Spell_SetRange3 takes doExternal, value, value2, value3
    $doExternal$//! externalblock extension=lua ObjectMerger $FILENAME$
    //! i function writeLua(code)
    //! i file = io.open("spells.lua", "r")

    //! i cur = file:read()

    //! i file:close()

    //! i file = io.open("spell"..cur..".lua", "a")

    //! i file:write(code)

    //! i file:close()
    //! i end

    //! i writeLua([[
    //! i range[1] = $value$
    //! i range[2] = $value2$
    //! i range[3] = $value3$
    //! i ]])
    $doExternal$//! endexternalblock

    call SpellObjectCreation.TEMP.SetRange(1, $value$)
    call SpellObjectCreation.TEMP.SetRange(2, $value2$)
    call SpellObjectCreation.TEMP.SetRange(3, $value3$)
    //! endtextmacro

    //! textmacro Spell_SetRangeLv takes doExternal, level, value
    $doExternal$//! externalblock extension=lua ObjectMerger $FILENAME$
    //! i function writeLua(code)
    //! i file = io.open("spells.lua", "r")

    //! i cur = file:read()

    //! i file:close()

    //! i file = io.open("spell"..cur..".lua", "a")

    //! i file:write(code)

    //! i file:close()
    //! i end

    //! i writeLua([[
    //! i range[$level$] = $value$
    //! i ]])
    $doExternal$//! endexternalblock

    call SpellObjectCreation.TEMP.SetRange($level$, $value$)
    //! endtextmacro

    //! textmacro Spell_SetTargets takes doExternal, value
    $doExternal$//! externalblock extension=lua ObjectMerger $FILENAME$
    //! i function writeLua(code)
    //! i file = io.open("spells.lua", "r")

    //! i cur = file:read()

    //! i file:close()

    //! i file = io.open("spell"..cur..".lua", "a")

    //! i file:write(code)

    //! i file:close()
    //! i end

    //! i writeLua([[
    //! i targetsAll = "$value$"
    //! i ]])
    $doExternal$//! endexternalblock
    //! endtextmacro

    //! textmacro Spell_SetTargetsLv takes doExternal, level, value
    $doExternal$//! externalblock extension=lua ObjectMerger $FILENAME$
    //! i function writeLua(code)
    //! i file = io.open("spells.lua", "r")

    //! i cur = file:read()

    //! i file:close()

    //! i file = io.open("spell"..cur..".lua", "a")

    //! i file:write(code)

    //! i file:close()
    //! i end

    //! i writeLua([[
    //! i targets[$level$] = "$value$"
    //! i ]])
    $doExternal$//! endexternalblock
    //! endtextmacro

    //! textmacro Spell_SetTargetType takes doExternal, value
    $doExternal$//! externalblock extension=lua ObjectMerger $FILENAME$
    //! i function writeLua(code)
    //! i file = io.open("spells.lua", "r")

    //! i cur = file:read()

    //! i file:close()

    //! i file = io.open("spell"..cur..".lua", "a")

    //! i file:write(code)

    //! i file:close()
    //! i end

    //! i writeLua([[
    //! i if ("$value$" == "IMMEDIATE") then
    //! i targetType = 0
    //! i elseif ("$value$" == "POINT") then
    //! i targetType = 2
    //! i elseif ("$value$" == "POINT_OR_UNIT") then
    //! i targetType = 3
    //! i elseif ("$value$" == "UNIT") then
    //! i targetType = 1
    //! i end
    //! i ]])
    $doExternal$//! endexternalblock

    call SpellObjectCreation.TEMP.SetTargetType(SpellObjectCreation.TARGET_TYPE_$value$)
    //! endtextmacro

    //! textmacro Spell_SetTooltip takes doExternal, value
    $doExternal$//! externalblock extension=lua ObjectMerger $FILENAME$
    //! i function writeLua(code)
    //! i file = io.open("spells.lua", "r")

    //! i cur = file:read()

    //! i file:close()

    //! i file = io.open("spell"..cur..".lua", "a")

    //! i file:write(code)

    //! i file:close()
    //! i end

    //! i writeLua([[
    //! i tooltip[1] = "$value$"
    //! i ]])
    $doExternal$//! endexternalblock
    //! endtextmacro

    //! textmacro Spell_SetTooltip3 takes doExternal, value, value2, value3
    $doExternal$//! externalblock extension=lua ObjectMerger $FILENAME$
    //! i function writeLua(code)
    //! i file = io.open("spells.lua", "r")

    //! i cur = file:read()

    //! i file:close()

    //! i file = io.open("spell"..cur..".lua", "a")

    //! i file:write(code)

    //! i file:close()
    //! i end

    //! i writeLua([[
    //! i tooltip[1] = "$value$"
    //! i tooltip[2] = "$value2$"
    //! i tooltip[3] = "$value3$"
    //! i ]])
    $doExternal$//! endexternalblock
    //! endtextmacro

    //! textmacro Spell_SetTooltipLv takes doExternal, level, value
    $doExternal$//! externalblock extension=lua ObjectMerger $FILENAME$
    //! i function writeLua(code)
    //! i file = io.open("spells.lua", "r")

    //! i cur = file:read()

    //! i file:close()

    //! i file = io.open("spell"..cur..".lua", "a")

    //! i file:write(code)

    //! i file:close()
    //! i end

    //! i writeLua([[
    //! i tooltip[$level$] = "$value$"
    //! i ]])
    $doExternal$//! endexternalblock
    //! endtextmacro

    //! textmacro Spell_SetUberTooltip takes doExternal, value
    $doExternal$//! externalblock extension=lua ObjectMerger $FILENAME$
    //! i function writeLua(code)
    //! i file = io.open("spells.lua", "r")

    //! i cur = file:read()

    //! i file:close()

    //! i file = io.open("spell"..cur..".lua", "a")

    //! i file:write(code)

    //! i file:close()
    //! i end

    //! i writeLua([[
    //! i uberTooltip[1] = "$value$"
    //! i ]])
    $doExternal$//! endexternalblock
    //! endtextmacro

    //! textmacro Spell_SetUberTooltip3 takes doExternal, value, value2, value3
    $doExternal$//! externalblock extension=lua ObjectMerger $FILENAME$
    //! i function writeLua(code)
    //! i file = io.open("spells.lua", "r")

    //! i cur = file:read()

    //! i file:close()

    //! i file = io.open("spell"..cur..".lua", "a")

    //! i file:write(code)

    //! i file:close()
    //! i end

    //! i writeLua([[
    //! i uberTooltip[1] = "$value$"
    //! i uberTooltip[2] = "$value2$"
    //! i uberTooltip[3] = "$value3$"
    //! i ]])
    $doExternal$//! endexternalblock
    //! endtextmacro

    //! textmacro Spell_SetUberTooltipLv takes doExternal, level, value
    $doExternal$//! externalblock extension=lua ObjectMerger $FILENAME$
    //! i function writeLua(code)
    //! i file = io.open("spells.lua", "r")

    //! i cur = file:read()

    //! i file:close()

    //! i file = io.open("spell"..cur..".lua", "a")

    //! i file:write(code)

    //! i file:close()
    //! i end

    //! i writeLua([[
    //! i uberTooltip[$level$] = "$value$"
    //! i ]])
    $doExternal$//! endexternalblock
    //! endtextmacro

    //! textmacro Spell_SetResearchUberTooltipLv takes doExternal, level, value
    $doExternal$//! externalblock extension=lua ObjectMerger $FILENAME$
    //! i function writeLua(code)
    //! i file = io.open("spells.lua", "r")

    //! i cur = file:read()

    //! i file:close()

    //! i file = io.open("spell"..cur..".lua", "a")

    //! i file:write(code)

    //! i file:close()
    //! i end

    //! i writeLua([[
    //! i researchUberTooltip[$level$] = "$value$"
    //! i ]])
    $doExternal$//! endexternalblock
    //! endtextmacro


    Nun werden sich einige fragen, warum ich beispielsweise SetTooltip und SetTooltip3 genommen habe, statt bei SetTooltip einfach das Level mit zu übergeben. Das liegt daran, dass wie gesagt, es effektiver ist, ein einziges Mal den ObjectMerger zu runnen statt öfters. Zum anderen hat man dann gleich eine schöne Liste und schreibt nicht zu viel untereinander.

    Hätte ich alle möglichen, unterschiedlichen Parameter aber in ein Macro gestopft, hätte ich mehr gesetzt als nötig und das wäre kaum noch leserlich, zumal die Felder durch die Stufenanzahl eben dynamisch sind. Am Liebsten wäre es mir ja gewesen, die Parameter etwa so anzugeben:

    //! runtextmacro Spell_Create("", "A000", "name=Musterspell levels=3 manacost=[40, 30, 20] range=[100., 200., 300.] hotkey=Q")


    dass man einen einzelnen dynamischen String hat, in dem alles drin stehen kann und der geparst wird. Das kann man in LUA machen, habe ich auch schon. Das Problem ist nur, wie man die Informationen zurück in Jass bekommt. Dazu gibts zwar auch Ansätze, aber die sind bisher nicht gerade zufriedenstellend.


    Ein Beispiel könnte dann so aussehen:

    struct ArcticBlink
    //! runtextmacro Spell_OpenScope("/") //Der erste Parameter entscheidet jeweils, ob das Externe aufgerufen wird. Bei "" ja, bei "/" nein.

    static method Init takes nothing returns nothing
    //! runtextmacro Spell_Create("/", "THIS_SPELL", "AArB", "Arctic Blink") //In THIS_SPELL wird das Jass-Spellobjekt gelagert, in dem dann nützliche Informationen stehen könnten, wenn man was mitloggt.

    //! runtextmacro Spell_SetType("/", "NORMAL")

    //! runtextmacro Spell_SetAnimation("/", "spell")
    //! runtextmacro Spell_SetButtonPosition("/", "0", "2")
    //! runtextmacro Spell_SetCooldown("/", "10.")
    //! runtextmacro Spell_SetIcon("/", "ReplaceableTextures\\CommandButtons\\BTNBearBlink.blp")
    //! runtextmacro Spell_SetManaCost("/", "40")
    //! runtextmacro Spell_SetOrder("/", "thunderbolt")
    //! runtextmacro Spell_SetRange("/", "800.")
    //! runtextmacro Spell_SetTargetType("/", "UNIT")

    //was sonst noch so zum Spellinit gehört
    endmethod

    //! runtextmacro Spell_Finalize("/")
    endstruct
    Geändert von WaterKnight (04. Januar 2012 um 18:48 Uhr)
    Water's Footmen Wars
    Defend Wintercastle
    Mana
    God's Ascension (coming soon)
    Dark Colony (coming soon)

    Versunkene Zeiten - Vortex - Wild Scope - Hells Edge -
    Prison Break

  2. #2
    Staff Maps
    Map-Contests
    Benutzerbild von muzzel
    Registriert seit
    Sep 2008
    Ort
    BaWü
    BNet Account
    muzzel
    Beiträge
    3.229
    OMG ist das geil, sehr schön =)
    War schon kurz davor LUA zu lernen um sowas selbst zu schreiben. Nett wäre aber noch eine Erweiterung auf Items

    <Argon]> in der zeit, in der ich das mit tikz gebastelt hab, hätt ich das als 2m^2 holzskulptur schnitzen können
    <Argon]> mit nem Skalpell
    Penguin World Domination - be part of it!
    » LaTeX2png Converter | Gaias Retaliation ORPG | Ulumulu Entertainment | AAT

  3. #3
    Sektionsleiter Maps Benutzerbild von WaterKnight
    Registriert seit
    Aug 2003
    BNet Account
    WaterKnight
    Beiträge
    4.420
    Wie gesagt, die Externalblocks runnen ist ziemlich langsam. Ich habe heute gemerkt, dass Jasshelper den ganzen Tempordner von Local Files vollsetzt mit Inputzeilen für die Externalblocks und die erstellten Dateien nicht wieder löscht. Konnte deswegen nimmer abspeichern, weil er anscheinend alle Namen aufgebraucht hatte.

    Es geht auch mit Units, die haben nur eine ganze Menge Einträge. Naja das Prinzip zu übertragen ist aber kein Problem, kanns dir im IRC zeigen, wenn du willst. Was ich auf jeden Fall mal noch posten könnte, in anderem Thread, wären Custom Buffs über Tornado-Aura, weil man da gut was automatisieren kann, was bei vielen Maps Sinn macht.

    edit: Hab' ne Lösung. Wenn man statt $FILENAME$ eine existierende Datei angibt, erstellt er zwar immer noch Neue in Temp, aber bei mir läufts wesentlich schneller. Also mal die $FILENAME$ durch "test.lua" ersetzen und im JNGP-Hauptverzeichnis eine Datei mit demselben Namen erzeugen.

    edit2: Nochmal SetTooltip- und SetUberTooltip-Levelvarianten, damit die Parameter nicht zu lang werden und es übersichtlicher ist.

    edit3: oben eingefügt

    und noch eine andere Spellbasis, die man öfter gebrauchen könnte:

    edit3: oben eingefügt

    Das ist die Fähigkeit 'Berserk', die hat kein Target und ist parallel castbar, unterbricht also keine Orders, Einheit muss nicht anhalten. Die Fähigkeit hat einen Buff, den sollte man dann noch bei EVENT_UNIT_SPELL_ENDCAST entfernen, das muss man aber nicht bei jeder Fähigkeit einzeln tun. Bei der kann man natürlich nicht die Order ändern, eine zweite Fähigkeit, die ich auch hätte nehmen können, wäre 'Windlauf' gewesen. So und so müsste man aber darauf achten, dass man nicht zwei gleichbasierende Fähigkeiten benutzt.
    Geändert von WaterKnight (30. März 2011 um 10:59 Uhr)
    Water's Footmen Wars
    Defend Wintercastle
    Mana
    God's Ascension (coming soon)
    Dark Colony (coming soon)

    Versunkene Zeiten - Vortex - Wild Scope - Hells Edge -
    Prison Break

  4. #4
    Sektionsleiter Maps Benutzerbild von WaterKnight
    Registriert seit
    Aug 2003
    BNet Account
    WaterKnight
    Beiträge
    4.420
    Das mit der test.lua ging doch nicht. JassHelper sucht die zwar und benutzt sie auch, schreibt aber nicht den Externalblock rein. Ich habe nun auch herausgefunden, dass es weniger daran liegt, dass JassHelper die ganzen Files createt, sondern dass die setobjecttype-Funktion von ObjectMerger einfach aus irgendwelchen Gründen extrem langsam ist. Ich benutzte das oben bei jedem Textmacro, also disponiere ich jetzt mal um.

    Und zwar trage ich erstmal die ganzen Inputs für einen Spell zusammen in eine Datei. Anschließend übergebe ich diese an ObjectMerger. Der Nachteil ist, dass ich jetzt ein Endzeichen brauche. Ich habe es mal Spell_Finalize genannt. Ansich könnte ich machen, dass nur das auskommentiert werden brauch, weil setobjecttype erst an der Stelle aufgerufen wird, nur sind die anderen Externalcalls halt trotzdem nicht kostenlos. Also ich machs einfach immer so, dass ich mit der Replace-Funktion im Auslöser-Editor alle ("/" auf einmal durch ("" ersetze bzw. umgedreht, ist sonst eher ungewöhnlich, dass man das bei Jassfunktionen hat.

    test.j braucht man jetzt also nicht mehr, nur test.lua. Das Zusammenwerfen hat noch den netten Nebeneffekt, dass, weil das dann ja ein Externalblock ist, ich Variablen und Funktionen sharen kann. Ich kann also jetzt die Stufenzahl beispielsweise unten nutzen, ohne dass ich das nochmal extra aus einer anderen Datei laden müsste. Dadurch kann ich mir dann sowas wie SetOrder3 sparen.
    Water's Footmen Wars
    Defend Wintercastle
    Mana
    God's Ascension (coming soon)
    Dark Colony (coming soon)

    Versunkene Zeiten - Vortex - Wild Scope - Hells Edge -
    Prison Break

  5. #5
    Sektionsleiter Maps Benutzerbild von WaterKnight
    Registriert seit
    Aug 2003
    BNet Account
    WaterKnight
    Beiträge
    4.420
    So, ich habe jetzt eine Lösung gefunden, besonders schön ist die aber noch nicht.

    Problem war, dass ObjectMerger die Felder Ncl2 und Ncl3 der Channel-Ability nicht richtig erkannte, sie als Stringwerte einstufte, in die .w3a schrieb und Wc3 dann nicht damit arbeiten kann/das Richtige bekommt.

    Ich weiß nicht, ob PitzerMike, der Erfinder des ObjectMerger-Tools, es bei Gelegenheit mal fixt, aber er hat mir vorgeschlagen, vorerst die AbilityMetaData.slk zu bearbeiten. Da stehen die Variablentypen der Felder drin und wenn Ncl2/3 auf int für Integer gesetzt werden, geht das auch, weil sie scheinbar auf Wrapper-Typen standen, die eigentlich Integers sind.

    Zumindest bräuchte man dann jetzt also die bearbeitete Slk und müsste diese in Warcraft III\Units\AbilityMetaData.slk tun und damit abspeichern. Die Sonderdarstellungen von Ncl2/3 mit Kombobox/Checkboxen im Objekt-Editor gehen dann nicht mehr richtig, was ich jetzt nicht besonders schlimm fände, aber ich würds vielleicht nicht allen vorsetzen. Die bessere Alternative wäre also, die Datei nur während des Speicherns zu ersetzen, was per lua-Script zwar funktionieren würde, aber da wäre es toll, wenn man zumindest schonmal die Datei irgendwo ausgepackt hat und sie nur rein-/rausschieben oder renamen braucht. Erstmal schauen, ob sich was ergibt, ums besser zu machen.

    Datei ist im Anhang

    edit: Habe die Datei wieder entfernt, weil ein Hotfix von Pitzermike existiert, der das Problem alleine beseitigt. Link ist oben.
    Geändert von WaterKnight (28. März 2011 um 20:14 Uhr)
    Water's Footmen Wars
    Defend Wintercastle
    Mana
    God's Ascension (coming soon)
    Dark Colony (coming soon)

    Versunkene Zeiten - Vortex - Wild Scope - Hells Edge -
    Prison Break

  6. #6
    Sektionsleiter Maps Benutzerbild von WaterKnight
    Registriert seit
    Aug 2003
    BNet Account
    WaterKnight
    Beiträge
    4.420
    Update: Gibt jetzt nicht mehr verschiedene Spell_Creates, sondern man setzt per Spell_SetType, auf was die Fähigkeit basiert (NORMAL --> Channel, PASSIVE --> Gyrokopterbomben (machen nichts), PARALLEL_IMMEDIATE --> Berserk von Orcs und SPECIAL --> man gibt die baseRaw selber an, dazu schreibt man sie direkt hinter dieses Keyword zB. SPECIAL_Apsh, wird per Substring rausgefiltert. Spell_SetType sollte direkt nach Spell_Create gemacht werden, weil in Spell_SetType das Objekt zum Weiterarbeiten erzeugt wird. Wobei ichs dann mal ändern und alles in Spell_Finalize verschieben werde, gibt mehr Flexibilität.
    Dann werden nun verschiedene Tags in Tooltips ersetzt:

    <areaRange>, <channelTime>, <cooldown>, <manaCost>, <level>, <prevLevel>

    Die ersetzen jeweils die Werte bezüglich des aktuellen Levels. Man kann aber auch auf andere Level zugreifen mit <areaRange1>, <areaRange2>, ..., <areaRange<prevLevel>>, <areaRange<level>>. Weiterhin kann man mit Spell_SetData eigene Tags definieren.
    Water's Footmen Wars
    Defend Wintercastle
    Mana
    God's Ascension (coming soon)
    Dark Colony (coming soon)

    Versunkene Zeiten - Vortex - Wild Scope - Hells Edge -
    Prison Break

  7. #7
    Sektionsleiter Maps Benutzerbild von WaterKnight
    Registriert seit
    Aug 2003
    BNet Account
    WaterKnight
    Beiträge
    4.420
    Update: Vorher hat irgendwie das Setzen des TargetTypes gefehlt, ist nun drin. Bei den Replacement Tags kann man jetzt auch <name,%> benutzen, damit der Wert x100 gerechnet und ein %-Zeichen dahinter platziert wird. Da Externalscripts von oben nach unten in Reihe ausgeführt werden und es bei mir zum Beispiel so ist, dass einige Spellparts über dem Init stehen, in dem der Spell jass-wise erzeugt wird, habe ich jetzt die Teile voneinander getrennt. Das heißt, man kann den spellzugehörigen Externalblock schon vorher starten ohne Jasszeilen.

    //! textmacro Spell_OpenScope takes doExternal
    $doExternal$//! externalblock extension=lua ObjectMerger $FILENAME$
    //! i file = io.open("spells.lua", "r")

    //! i cur = file:read() + 1

    //! i file:close()

    //! i file = io.open("spells.lua", "w+")

    //! i file:write(cur)

    //! i file:close()

    //! i file = io.open("spellsDelete.lua", "r")

    //! i delCur = file:read() + 0

    //! i file:close()

    //! i if (cur > delCur) then
    //! i file = io.open("spellsDelete.lua", "w+")

    //! i file:write(cur)

    //! i file:close()
    //! i end

    //! i file = io.open("spell"..cur..".lua", "w+")

    //! i file:close()

    //! i function writeLua(code)
    //! i file = io.open("spells.lua", "r")

    //! i cur = file:read()

    //! i file:close()

    //! i file = io.open("spell"..cur..".lua", "a")

    //! i file:write(code)

    //! i file:close()
    //! i end

    //! i writeLua([[
    //! i Math = {}

    //! i Math.QUARTER_ANGLE = 1.57

    //! i function set(field, value, default)
    //! i if (value == nil) then
    //! i makechange(current, field, default)
    //! i else
    //! i makechange(current, field, value)
    //! i end
    //! i end

    //! i function setLv(field, level, value, default)
    //! i if (value == nil) then
    //! i makechange(current, field, level, default)
    //! i else
    //! i makechange(current, field, level, value)
    //! i end
    //! i end

    //! i function setLevelsAmount(value)
    //! i levelsAmount = value

    //! i if (value == 1) then
    //! i tooltip[1] = "|cff00bfff"..name.."|r"
    //! i else
    //! i for i = 1, value, 1 do
    //! i tooltip[i] = "|cff00bfff"..name.."|r [|cffffcc00Level "..i.."|r]"
    //! i end
    //! i end
    //! i end

    //! i function addData(name, values)
    //! i if (name == nil) then
    //! i return
    //! i end

    //! i it = 1

    //! i datasCount = datasCount + 1

    //! i datas[datasCount] = name
    //! i datasValue[datasCount] = {}

    //! i while (values[it] ~= nil) do
    //! i datasValue[datasCount][it] = values[it]

    //! i it = it + 1
    //! i end
    //! i end

    //! i areaRange = {}
    //! i castTime = {}
    //! i channelTime = {}
    //! i cooldown = {}
    //! i datas = {}
    //! i datasCount = 0
    //! i datasValue = {}
    //! i isHeroSpell = false
    //! i manaCost = {}
    //! i range = {}
    //! i showAreaRange = {}
    //! i targets = {}
    //! i tooltip = {}
    //! i uberTooltip = {}
    //! i ]])
    $doExternal$//! endexternalblock
    //! endtextmacro


    Man ruft also zuerst Spell_OpenScope auf, dann Spell_Create, dann die Optionen und zuletzt Spell_Finalize, was das ganze Scope wieder abschließt. Spell_OpenScope kann also auch außerhalb von Funktionen stehen, Finalize konnte es vorher schon. Das hat noch den Vorteil, das habe ich jetzt auch implementiert, dass man Spelldefinitionen external-wise schachteln kann. Dazu wird für jedes Scope eine eigene Datei angelegt, bis es abgeschlossen wird (Finalize schließt das zuletzt geöffnete Scope) und in einer globalen Datei steht der Zähler. Damit ich den ObjectMerger dann per //! external aufrufen kann, wird das Skript vorher noch in eine andere globale Datei umgeladen.

    Die Dateien werden bei Finalize nicht gelöscht, damit man besser debuggen kann. Nur zu Beginn des Speicherns wird gecleart und die überschüssigen Spellinstanzen weggehauen. Dafür ist dieses statische Skript im Header verantwortlich:

    //! externalblock extension=lua ObjectMerger $FILENAME$
    //! i file = io.open("spellsDelete.lua", "r")

    //! i if (file ~= nil) then
    //! i delCur = file:read() + 0

    //! i for i = 0, delCur, 1 do
    //! i os.remove("spell"..i..".lua")
    //! i end

    //! i file:close()
    //! i end

    //! i file = io.open("spells.lua", "w+")

    //! i file:write(-1)

    //! i file:close()

    //! i file = io.open("spellsDelete.lua", "w+")

    //! i file:write(-1)

    //! i file:close()

    //! i file = io.open("objectMergerInput.lua", "w+")

    //! i file:close()
    //! endexternalblock
    Water's Footmen Wars
    Defend Wintercastle
    Mana
    God's Ascension (coming soon)
    Dark Colony (coming soon)

    Versunkene Zeiten - Vortex - Wild Scope - Hells Edge -
    Prison Break

  8. #8
    Sektionsleiter Maps Benutzerbild von WaterKnight
    Registriert seit
    Aug 2003
    BNet Account
    WaterKnight
    Beiträge
    4.420
    Entwickle zurzeit eine neue Methode, die es mir ermöglichen sollte, die Externalcalls auf ein Minimum zu reduzieren, wodurch die Speicherzeit erheblich verkürzt wird, und bei der ich nicht mehr lästig manuell alles ein-/ausgeschaltet werden muss.

    Alle Objekte, oder in dem Fall erst einmal Spells, werden ausgelagert in Tabellendateien. Die Pfade werden in einem Sammelpunkt gespeichert. Der Editor macht einen einzelnen, konstant aktivierten Externalcall. Das aufgerufene Script geht alle Spelldateien durch und übermittelt die Daten bei Bedarf an ObjectMerger. "Bedarf" ermittle ich zurzeit anhand der FileTime, wann eine Datei zum letzten Mal modifiziert wurde, damit es automatisch geht und ich Excel für die Tabellen nutzen kann statt einem eigenen Programm. Außerdem wird für jede Datei ein Jassskript erzeugt, damit man die Spelldaten dann auch ingame zur Verfügung hat, worum es bei der ganzen Sache ja ging. Diese .j-Files importiert man mit der Direktive von vJass.

    Der Knackpunkt ist nur, dass JassHelper Externalcalls zuletzt ausführt und somit die Imports noch nicht vorhanden/aktualisiert sind beim ersten Speichern. Falls JassHelper rekursiv-sicher ist, könnte man über den Externalcall noch einmal am Ende JassHelper ausführen, wenn man an das Script kommt.
    Water's Footmen Wars
    Defend Wintercastle
    Mana
    God's Ascension (coming soon)
    Dark Colony (coming soon)

    Versunkene Zeiten - Vortex - Wild Scope - Hells Edge -
    Prison Break

  9. #9
    Sektionsleiter Maps Benutzerbild von WaterKnight
    Registriert seit
    Aug 2003
    BNet Account
    WaterKnight
    Beiträge
    4.420
    So, bin fast fertig. Habe mir noch ein Mini-VisualBasic-Prog geschrieben, um die Tabellen besser schreiben zu können. Excel hat da etwas gepfuscht. Die Daten sind schnell und einfach veränderbar.

    In der ersten Spalte stehen die Felder wie zum Beispiel "name", "cooldown", "manaCost". Die zweite Spalte ist der Identifier für Jass, in welcher Jassvariablen die Werte vom Feld gespeichert werden sollen. Der Rest sind die Werte für die einzelnen Levels. Ein großer Vorteil ist, was ich jetzt schon beim Konvertieren gemerkt habe, dass wenn zum Beispiel eine Fähigkeit auf jeder Stufe 20 Mana kosten soll, ich nicht von Level 1 bis 5 die 20 eintragen muss, sondern ich habe es einfach so gemacht, dass leere Felder automatisch mit dem letzten Wert aufgefüllt werden. Dadurch sieht man schön, welche Attribute eines Spells sich beim Stufenaufstieg ändern. Außerdem weiß ich zum Beispiel anhand der Spellklasse, wie viele Levels standardmäßig vorhanden sind. Also ein paar Default-Werte und -Algorithmen werden gleich zur Compilerzeit angewendet. Dadurch, dass ich den Jasscode direkt aus Lua erschaffe, habe ich viel mehr Möglichkeiten, als mir das Textmacro in vJass bot. Es sieht nicht mehr so hässlich aus.

    Der Aufruf des Updaters dann über jasshelper externalcall geht auch soweit. Zudem fasse ich alle Inputs für den ObjectMerger zusammen, damit der nur einmal die langsame setobjecttype-Funktion bemühen muss, was noch einmal Speedbonus einbringt. Mal schauen, wie lange es am Ende lädt, wenn ich alle Daten konvertiert und registriert habe. Es war bei DWC teilweise wirklich unerträglich. Vielleicht kann man dann ja irgendwann auch noch machen, dass nicht ObjectMerger aufgerufen wird sondern direkt die AbilityData.slk modifiziert wird. Die braucht das Spiel nämlich nur einmal zu lesen, was auch wesentlich schneller geht und danach verursachen die dort eingetragenen Ability-Objekte keinen Preload mehr, wodurch die Ingame-Ladezeit meiner Map stark verkürzt wäre.

    edit: Eine Raw Id anzugeben, wird dann auch obsolet, weil einfach jedem Pfad eine einzigartige Id generiert wird. Ich liste dann in dem Tabellenprogramm noch alle Objekte über Name oder Pfad auf, damit man schnell alle Objekte auf einen Blink hat und bearbeiten kann wie im Objekt-Editor und nicht jedesmal über den Windows-File-Dialog gehen muss. Es wäre nun ebenfalls theoretisch möglich, im ObjectMerger die Daten anderer Objekte abzugreifen, um sie beispielsweise in Tooltips einzubinden.
    Geändert von WaterKnight (12. Mai 2012 um 11:34 Uhr)
    Water's Footmen Wars
    Defend Wintercastle
    Mana
    God's Ascension (coming soon)
    Dark Colony (coming soon)

    Versunkene Zeiten - Vortex - Wild Scope - Hells Edge -
    Prison Break

  10. #10
    Sektionsleiter Maps Benutzerbild von WaterKnight
    Registriert seit
    Aug 2003
    BNet Account
    WaterKnight
    Beiträge
    4.420
    Während fast alle SpellDaten transformiert wurden und ich dasselbe dann noch für Units machen werde, da wohl aber mit einem Script, dass es automatisch umwandelt, habe ich mir noch die Frage gestellt, wie ich das mit Subparts von Spells machen werde, also Daten, die codetechnisch in einer Unterstruktur gelagert sind. Diese werde ich nicht direkt in die globale Liste eintragen, sondern sie kommen in ein extra include-Field im Spellobjekt. Wenn es geladen wird, werden alle Pfade in diesem Feld ebenfalls aufgerufen und die neuen Daten für das Oberobjekt durch Präfix sichtbar, damit man sie in Tooltips verwenden kann. Sind da Aufgaben für den ObjectMerger, werden diese ebenfalls abgehandelt. Des Weiteren überlege ich, ob es noch eine bessere Methode gibt, zu wissen, ob eine Variable Level besitzt oder nicht, also eine Arrayvariable ist oder nicht, da ich wie gesagt die Autofill-Option genutzt habe. Das heißt, mein Objekt selber weiß derzeit nicht, ob ein Feld stufenbasiert ist oder nicht. Bei dem Standardzeug ist es klar, bei Custom-Sachen liegt das Problem. JassHelper bietet aber meines Wissens nach auch keine Möglichkeit, das zu überprüfen in einem static if. Ich will nicht in den .j-Dateien rumsuchen, die sollen nur importieren. Andersherum ist es nicht zugeordnet. Falls ich mich dazu entschließen sollte, die Variablendeklaration auch mit generieren zu lassen, dann muss ich die Information auf jeden Fall mit einbauen.
    Water's Footmen Wars
    Defend Wintercastle
    Mana
    God's Ascension (coming soon)
    Dark Colony (coming soon)

    Versunkene Zeiten - Vortex - Wild Scope - Hells Edge -
    Prison Break

  11. #11
    Sektionsleiter Maps Benutzerbild von WaterKnight
    Registriert seit
    Aug 2003
    BNet Account
    WaterKnight
    Beiträge
    4.420
    Obwohl das jetzt soweit klappt, werde ich das mit include doch noch einmal anders machen. Um es auf einer allgemeingültigeren Ebene zu gestatten und die Eintragungen zu vermeiden, werde ich die Ordnerstruktur als Maß nehmen. Außerdem werden nicht alle Unterobjektdaten vorgeladen, sondern nur wenn es gebraucht wird. Die Variablen beinhalten jetzt alle einheitlich den Unterpfad, so dass das eindeutig ist und ich weiß, wo zu suchen ist. Letztendlich ist es sogar besser möglich, aus gänzlich anderen Objekten zu lesen.
    Water's Footmen Wars
    Defend Wintercastle
    Mana
    God's Ascension (coming soon)
    Dark Colony (coming soon)

    Versunkene Zeiten - Vortex - Wild Scope - Hells Edge -
    Prison Break

  12. #12
    Sektionsleiter Maps Benutzerbild von WaterKnight
    Registriert seit
    Aug 2003
    BNet Account
    WaterKnight
    Beiträge
    4.420
    Bin fast fertig.

    Also ich habe jetzt einen PathViewer, der mir die Ordnerstruktur anzeigt und jeweils die Skript- und Objektdaten auf dem Pfad. Die kann man dann sofort öffnen und bearbeiten mit anderen Programmen.

    Für die Objektdaten verwende ich meinen eigenen Editor, der quasi nur ein DataGrid darstellt und damit sehr flexibel ist. Um nicht alles manuell von dem alten System oben konvertieren zu müssen, habe ich noch eine Übersetzerfunktion eingebaut. Die verschiedenen Objektarten werden zurzeit per Extension unterschieden, damit ich die Dateien nicht extra öffnen und die Klassifikation ins DataGrid schreiben muss. Ist dann für den ObjectMerger interessant, um welchen Objekttyp es sich handelt.

    Dann habe ich einen Loader, der aus den Objektdaten Jassdateien erstellt, den ObjectMerger runnt und der alle Jassskripte zusammenfasst, damit ich die Importzeilen nicht schreiben muss. Zumal die //! import-Funktion von vJass eh flawed ist.

    Der Loader wird von einem Starter initiiert, der die jasshelper.exe in JNGP ersetzt, damit zuerst der Loader runnt und danach die vJass-Kompilierung erfolgt. Damit benötige ich auch kein zweites Mal Speichern im Editor mehr.

    Friede, Freude, Eierkuchen. Das einzige, was ich nur noch machen müsste, ist die Funktionalität in den PathViewer einzubauen, dass man die Reihenfolge festlegen kann, weil der Header scriptwise ja zum Beispiel oben stehen sollte.

    Mit den auto-imported Objektdaten schrumpfen die Skripte ein wenig und es sieht schöner aus. Man muss keine Deklaration von statischen Variablen mehr vornehmen, die einem Spell zugeordnet sind, weil vorher sah das so aus:

    static real array DAMAGE

    ...

    //! runtextmacro Spell_SetData5(..., "DAMAGE", "100", "200", "300", "400", "500")


    Da war es notwendig, die Levelzahl anzugeben (SetData5), ich musste zweimal den Variablenidentifier schreiben, Array ja/nein angeben, obwohl das durch die Levelzahl bedingt war und aufpassen, dass der Variablentyp stimmte. Wenn eine der beiden Zeilen wegfiel, war die andere nicht automatisch auch aus dem Verkehr gezogen. Jetzt werden primitive Variablen direkt anhand der Werte erkannt. Spezielle, die halt selten sind, müssen nur einmal geschrieben werden. Ebenso brauche ich nicht mehr überall die hässlichen Quotes und Backslashes müssen nicht mehr verdoppelt werden.

    Mit ObjectMerger habe ich noch nicht probiert, zumal ich die Buffs bisher nicht übersetzt habe, aber bisher dauert der ganze Kompiliervorgang nur wenige Sekunden mit meinen >3mb Skripten in DWC, für das ich dieses System jetzt eben nutzen will.
    Geändert von WaterKnight (18. Juni 2012 um 18:50 Uhr)
    Water's Footmen Wars
    Defend Wintercastle
    Mana
    God's Ascension (coming soon)
    Dark Colony (coming soon)

    Versunkene Zeiten - Vortex - Wild Scope - Hells Edge -
    Prison Break

  13. #13
    Sektionsleiter Maps Benutzerbild von WaterKnight
    Registriert seit
    Aug 2003
    BNet Account
    WaterKnight
    Beiträge
    4.420
    Habe mir nun noch ein weiteres Tool geschrieben, mit dem ich, statt den ObjectMerger aufzurufen, aus den Objektdaten Slk-Dateien zusammensetze. Die werden dann auch automatisch mit dem FileImporter aus grimext importiert. Wc3 lädt Slks wesentlich schneller und man braucht nicht mehr alles zu preloaden. Ein Problem ist, dass Abilities und Upgrades nur Felder bis Stufe 4 haben und ich bisher keine Möglichkeit gefunden habe, das so zu erweitern, dass es von Wc3 akzeptiert wird. Das Tool und die anderen kann man allerdings noch auf weitere Objekttypen erweitern, mit denen ObjectMerger nichts am Hut hatte. Habe mir gedacht Lightnings, Weathereffects oder Splats machen Sinn, lokal zu deklarieren. Vorher musste man die, wenn man sie beispielsweise für einen Spell verwenden wollte, immer global in die Slk schreiben.
    Water's Footmen Wars
    Defend Wintercastle
    Mana
    God's Ascension (coming soon)
    Dark Colony (coming soon)

    Versunkene Zeiten - Vortex - Wild Scope - Hells Edge -
    Prison Break

Forumregeln

  • Es ist dir nicht erlaubt, neue Themen zu verfassen.
  • Es ist dir nicht erlaubt, auf Beiträge zu antworten.
  • Es ist dir nicht erlaubt, Anhänge hochzuladen.
  • Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.
  •