Skocz do zawartości
  • 👋 Witaj na MPCForum!

    Przeglądasz forum jako gość, co oznacza, że wiele świetnych funkcji jest jeszcze przed Tobą! 😎

    • Pełny dostęp do działów i ukrytych treści
    • Możliwość pisania i odpowiadania w tematach
    • System prywatnych wiadomości
    • Zbieranie reputacji i rozwijanie swojego profilu
    • Członkostwo w jednej z największych społeczności graczy

    👉 Dołączenie zajmie Ci mniej niż minutę – a zyskasz znacznie więcej!

    Zarejestruj się teraz

Pisanie skryptów, cz. 7


Rekomendowane odpowiedzi

Opublikowano

http://www.mpcforum.pl/topic/1274238-pisanie-skryptow-cz-8/ - Część 8
http://www.mpcforum.pl/topic/1273792-pisanie-skryptow-cz-7/ - Część 7
http://www.mpcforum.pl/topic/1273566-pisanie-skryptow-cz-6/ - Część 6
http://www.mpcforum.pl/topic/1232331-pisanie-skryptow-cz-5/ - Część 5
http://www.mpcforum.pl/topic/1231168-pisanie-skryptow-cz-4/ - Część 4
http://www.mpcforum.pl/topic/1230769-pisanie-skryptow-cz-3/ - Część 3
http://www.mpcforum.pl/topic/1230734-pisanie-skryptow-cz-2/ - Część 2
http://www.mpcforum.pl/topic/1230572-pisanie-skryptow-cz-1/ - Część 1

Czołem!

Ta część nie jest tak naprawdę związana z LoLem, a bardziej z samym programowaniem. Będzie ona dotyczyła funkcji, praktycznego ich wykorzystania oraz list/tablic.

Aha, i jeżeli jeszcze nie przerzuciliście się na Notepad++, zróbcie to teraz.

1. Funkcje - trochę więcej o nich.

Jak pewnie przypominacie sobie pierwszą część poradnika, opisałem tam, jak definiować funkcje i je wywoływać. Napisałem też, że istnieją specjalne funkcje, tzw. callbacki. To teraz czas na ich praktyczne wykorzystanie. Dzięki nimi nasz kod stanie się znacznie przejrzystszy i łatwiejszy w analizowaniu.
Bierzemy nasz kod z poprzedniej części:
 

function OnLoad()
     ts = TargetSelector(TARGET_LOW_HP_PRIORITY,625)
     Config = scriptConfig("Ryze Combo", "ryzecombo77")
     Config:addParam("combo", "Combo", SCRIPT_PARAM_ONKEYDOWN, false, 32)
     Config:addParam("usespellr", "Uzyj R", SCRIPT_PARAM_ONOFF, true)
     Config:addParam("circle", "Rysuj zasieg Q", SCRIPT_PARAM_ONKEYTOGGLE, true, string.byte("M"))
end

function OnTick()
     DFGslot = GetInventorySlotItem(3128)
     ZHGslot = GetInventorySlotItem(3157)
     ts:update()
     if (ts.target ~= nil) then
          if (Config.combo) then
               if (myHero:CanUseSpell(_R) == READY) then
                    if (Config.usespellr) then
                         CastSpell(_R, ts.target)
                    end
               end
               if (DFGslot ~= nil) then
                    if (myHero:CanUseSpell(DFGslot) == READY) then
                         CastSpell(DFGslot, ts.target)
                    end
               end
               if (myHero:CanUseSpell(_Q) == READY) then
                    CastSpell(_Q, ts.target)
               end
               if (myHero:CanUseSpell(_E) == READY) then
                    CastSpell(_E, ts.target)
               end
               if (myHero:CanUseSpell(_W) == READY) then
                    CastSpell(_W, ts.target)
               end
               if (ZHGslot ~= nil) then
                    if (myHero:CanUseSpell(ZHGslot) == READY and myHero:CanUseSpell(_Q) ~= READY and myHero:CanUseSpell(_W) ~= READY and myHero:CanUseSpell(_E) ~= READY and myHero:CanUseSpell(_R)~= READY) then
                         CastSpell(ZHGslot)
                    end
               end
          end
     end
end

function OnDraw()
     if (Config.circle) then
          DrawCircle(myHero.x, myHero.y, myHero.z, 625, 0xFF00FF)
     end
end

Co można uczynić, by kod był bardziej przejrzysty? Na przykład usunąć z OnTick CastSpell() czy myHero:CanUseSpell i zastąpić to czymś ładniejszym. I tutaj przychodzą nam z pomocą funkcje. Dopiszmy na samym końcu skryptu następujące linijki:
 

function CastR()
     if (myHero:CanUseSpell(_R) == READY) then
          if (Config.usespellr) then
               CastSpell(_R, ts.target)
          end
     end
end

function CastDFG()
     if (DFGslot ~= nil) then
          if (myHero:CanUseSpell(DFGslot) == READY) then
               CastSpell(DFGslot, ts.target)
          end
     end
end

function CastQ()               
     if (myHero:CanUseSpell(_Q) == READY) then
          CastSpell(_Q, ts.target)
     end
end

function CastE()
     if (myHero:CanUseSpell(_E) == READY) then
          CastSpell(_E, ts.target)
     end
end

function CastW()
     if (myHero:CanUseSpell(_W) == READY) then
          CastSpell(_W, ts.target)
     end
end

function CastZHG()
     if (ZHGslot ~= nil) then
          if (myHero:CanUseSpell(ZHGslot) == READY and myHero:CanUseSpell(_Q) ~= READY and myHero:CanUseSpell(_W) ~= READY and myHero:CanUseSpell(_E) ~= READY and myHero:CanUseSpell(_R)~= READY) then
               CastSpell(ZHGslot)
          end
     end
end

function InitConfig()
     Config = scriptConfig("Ryze Combo", "ryzecombo77")
     Config:addParam("combo", "Combo", SCRIPT_PARAM_ONKEYDOWN, false, 32)
     Config:addParam("usespellr", "Uzyj R", SCRIPT_PARAM_ONOFF, true)
     Config:addParam("circle", "Rysuj zasieg Q", SCRIPT_PARAM_ONKEYTOGGLE, true, string.byte("M"))
end

function CircleQ()
     if (Config.circle) then
          DrawCircle(myHero.x, myHero.y, myHero.z, 625, 0xFF00FF)
     end
end

Co zrobiliśmy? Utworzyliśmy kilka funkcji: CastQ(), CastW(), CastE(), CastR(), CastDFG(), CastZHG(), InitConfig() oraz CircleQ(). Teraz, zamiast umieszczać wszystko w jeden funkcji OnTick(), możemy rozłożyć każdą czynność na inną funkcję. Dodatkowo, teraz nasze callbacki wyglądają tak:
 

function OnLoad()
     ts = TargetSelector(TARGET_LOW_HP_PRIORITY,625)
     InitConfig()
end

function OnTick()
     DFGslot = GetInventorySlotItem(3128)
     ZHGslot = GetInventorySlotItem(3157)
     ts:update()
     if (ts.target ~= nil) then
          if (Config.combo) then
               CastR()
               CastDFG()
               CastQ()
               CastE()
               CastW()
               CastZHG()
          end
     end
end

function OnDraw()
     CircleQ()
end

Czyż nie wygląda to przejrzyściej? Dodatkowo możemy wywoływać te funkcje kilkukrotnie bez potrzeby przepisywania całego kodu. Funkcji można w skrypcie dać tyle, ile chcesz.

2. Listy

Lista jest to kontener danych służący do łatwego ich przechowywania. @Marcoly - naucz się, że to się nie nazywa tablica!

Przykład listy:

function OnLoad()
     b = {kappa = 1940, include = "iostream", meh = "aio", huh = 123}
     PrintChat(tostring(b.kappa))
     PrintChat(b.include)
     PrintChat(b.meh)
     PrintChat(tostring(b.huh))
     PrintChat(tostring(b.nie_ma))
end

Lista przyjmie dowolny typ danych (np. logiczny [false/true], liczbowy [41/167.13], znakowy ["test"/"jakies znaczki"]). Znakowy typ danych bierzemy w cudzysłowy!
Tostring konwertuje dowolny typ danych na znakowy.
Oczekiwany wynik:
305861408730239358546.jpg
Teraz wróćmy do LoLa - czas na praktyczne wykorzystanie list. Zróbmy listy spelli.

3. Wykorzystanie list


SpellQ = {id = "Q", range = 625, ready = false}
SpellW = {id = "W", range = 600, ready = false}
SpellE = {id = "E", range = 600, ready = false}
SpellR = {id = "R", range = nil, ready = false}

Ta lista zawiera nazwy, zasięgi oraz czy spell jest gotowy. W przypadku ulti zasięg wynosi "nil", czyli nic. "false" jest to wartość fałszywa dla typu logicznego; przeciwieństwem jest "true".
Nie jest to jednak takie proste, aby SpellQ.ready działało, trzeba to przypisać. Piszemy w takim razie:
 

SpellQ.ready = (myHero:CanUseSpell(_Q) == READY)
SpellW.ready = (myHero:CanUseSpell(_W) == READY)
SpellE.ready = (myHero:CanUseSpell(_E) == READY)
SpellR.ready = (myHero:CanUseSpell(_R) == READY)

Zasięgów użyjemy do ustawienia Target Selectora oraz kółek pokazujących zasięg. ID wykorzystamy w Configu.
W Configu usuwamy linijkę dotyczącą kółka Q i wpisujemy następujące opcje:

Config:addParam("circleQ", "Rysuj zasieg " .. SpellQ.id, SCRIPT_PARAM_ONKEYTOGGLE, true, string.byte("M"))
Config:addParam("circleWE", "Rysuj zasieg " .. SpellW.id .. " i " .. SpellE.id, SCRIPT_PARAM_ONKEYTOGGLE, true, string.byte("N"))

Teraz wracamy do naszych funkcji. InitConfig() zmieniamy, by wyglądało o tak:

function InitConfig()
     Config = scriptConfig("Ryze Combo", "ryzecombo77")
     Config:addParam("combo", "Combo", SCRIPT_PARAM_ONKEYDOWN, false, 32)
     Config:addParam("usespellr", "Uzyj R", SCRIPT_PARAM_ONOFF, true)
     Config:addParam("circleQ", "Rysuj zasieg " .. SpellQ.id, SCRIPT_PARAM_ONKEYTOGGLE, true, string.byte("M"))
     Config:addParam("circleWE", "Rysuj zasieg " .. SpellW.id .. " i " .. SpellE.id, SCRIPT_PARAM_ONKEYTOGGLE, true, string.byte("N"))
end

Funkcję CircleQ() przemianowujemy na CircleSpells(), która ma wyglądać o tak:
 
 

function CircleSpells()
     if (Config.circleQ) then
          DrawCircle(myHero.x, myHero.y, myHero.z, SpellQ.range, 0xFF00FF)
     end
     if (Config.circleWE) then
          DrawCircle(myHero.x, myHero.y, myHero.z, SpellW.range, 0xFFFF00)
     end
end

Oczywiście, poza Configiem, kółkami i "gotowościami" spelli musimy zainicjować także samą listę. Musimy wstawić te zmienne do OnLoad(). Dlatego zrobimy nową funkcję, w nich wkleimy te zmienne i tę funkcję wstawimy do OnLoad(). Kodzik:

function InitVars()
     SpellQ = {id = "Q", range = 625, ready = false}
     SpellW = {id = "W", range = 600, ready = false}
     SpellE = {id = "E", range = 600, ready = false}
     SpellR = {id = "R", range = nil, ready = false}

     SpellQ.ready = (myHero:CanUseSpell(_Q) == READY)
     SpellW.ready = (myHero:CanUseSpell(_W) == READY)
     SpellE.ready = (myHero:CanUseSpell(_E) == READY)
     SpellR.ready = (myHero:CanUseSpell(_R) == READY)
end

Teraz możemy podmienić wszystkie myHero:CanUseSpell(_Q/W/E/R) == READY na SpellQ/W/E/R.ready. Czyli z:
 

function CastQ()               
     if (myHero:CanUseSpell(_Q) == READY) then
          CastSpell(_Q, ts.target)
     end
end

powstaje:

function CastQ()               
     if spellQ.ready then
          CastSpell(_Q, ts.target)
     end
end

Analogicznie robimy z W, E i R. Itemy na razie zostawiamy, jak są.

4. Końcowy kod

function OnLoad()
     InitVars()
     InitConfig()
end

function OnTick()
     DFGslot = GetInventorySlotItem(3128)
     ZHGslot = GetInventorySlotItem(3157)
     ts:update()
     if (ts.target ~= nil) then
          if (Config.combo) then
               CastR()
               CastDFG()
               CastQ()
               CastE()
               CastW()
               CastZHG()
          end
     end
end

function OnDraw()
     CircleSpells()
end

function CastR()
     if SpellR.ready then
          if (Config.usespellr) then
               CastSpell(_R, ts.target)
          end
     end
end

function CastDFG()
     if (DFGslot ~= nil) then
          if (myHero:CanUseSpell(DFGslot) == READY) then
               CastSpell(DFGslot, ts.target)
          end
     end
end

function CastQ()               
     if SpellQ.ready then
          CastSpell(_Q, ts.target)
     end
end

function CastE()
     if SpellE.ready then
          CastSpell(_E, ts.target)
     end
end

function CastW()
     if SpellW.ready then
          CastSpell(_W, ts.target)
     end
end

function CastZHG()
     if (ZHGslot ~= nil) then
          if (myHero:CanUseSpell(ZHGslot) == READY and myHero:CanUseSpell(_Q) ~= READY and myHero:CanUseSpell(_W) ~= READY and myHero:CanUseSpell(_E) ~= READY and myHero:CanUseSpell(_R)~= READY) then
               CastSpell(ZHGslot)
          end
     end
end

function InitConfig()
     Config = scriptConfig("Ryze Combo", "ryzecombo77")
     Config:addParam("combo", "Combo", SCRIPT_PARAM_ONKEYDOWN, false, 32)
     Config:addParam("usespellr", "Uzyj R", SCRIPT_PARAM_ONOFF, true)
     Config:addParam("circleQ", "Rysuj zasieg " .. SpellQ.id, SCRIPT_PARAM_ONKEYTOGGLE, true, string.byte("M"))
     Config:addParam("circleWE", "Rysuj zasieg " .. SpellW.id .. " i " .. SpellE.id, SCRIPT_PARAM_ONKEYTOGGLE, true, string.byte("N"))
end

function CircleSpells()
     if (Config.circleQ) then
          DrawCircle(myHero.x, myHero.y, myHero.z, SpellQ.range, 0xFF00FF)
     end
     if (Config.circleWE) then
          DrawCircle(myHero.x, myHero.y, myHero.z, SpellW.range, 0xFFFF00)
     end
end

function InitVars()
     SpellQ = {id = "Q", range = 625, ready = false}
     SpellW = {id = "W", range = 600, ready = false}
     SpellE = {id = "E", range = 600, ready = false}
     SpellR = {id = "R", range = nil, ready = false}

     SpellQ.ready = (myHero:CanUseSpell(_Q) == READY)
     SpellW.ready = (myHero:CanUseSpell(_W) == READY)
     SpellE.ready = (myHero:CanUseSpell(_E) == READY)
     SpellR.ready = (myHero:CanUseSpell(_R) == READY)
     
     ts = TargetSelector(TARGET_LOW_HP_PRIORITY,SpellQ.range)
end

 
Wszelkie błędy proszę mi wypomnieć, jestem już dzisiaj trochę zmęczony :f
Podpowiedzcie mi temat na jutro, bo nie wiem, o czym pisać :v
Polecam też bardziej zaawansowane poradniki Marcoly'ego:
http://www.mpcforum.pl/topic/1226948-api-sidas-auto-carry/
http://www.mpcforum.pl/topic/1157768-zastosowanie-lag-free-circles-we-wlasnym-skrypcie/
http://www.mpcforum.pl/topic/1229945-buffy-advanced-callbacks-vip/
Credits:
Marcoly

Skończ proszę się kompromitować. Jesteś nikim.

Zarchiwizowany

Ten temat przebywa obecnie w archiwum. Dodawanie nowych odpowiedzi zostało zablokowane.

×
×
  • Dodaj nową pozycję...