Forum Stalker.pl • Zobacz temat - [LUA] generowanie nazwy zmiennej

[LUA] generowanie nazwy zmiennej

Regulamin forum
Dział "Tworzenie Modyfikacji" służy do zadawania pytań odnośnie tworzenia modyfikacji, edytowania plików gry, oraz pisania tzw. tutoriali, czyli poradników odnośnie modyfikowania gry.
Nie zadajemy tutaj pytań odnośnie modyfikacji gotowych (nie dyskutujemy o nich!), prócz prób ich połączenia etc.


Przy cytowaniu plików *.LTX stosować tag [SYNTAX="ini"], przy cytowaniu plików *.script [SYNTAX="lua"] a przy cytowaniu plików *.xml - [SYNTAX="xml"].

[LUA] generowanie nazwy zmiennej

Postprzez Plaargath w 11 Lut 2015, 15:49

Taka zagwozdka:
Mam sobie w jednym skrypcie, powiedzmy skrypt_pierwszy.script kilka zmiennych:

Kod: [ Pobierz ] [ Ukryj ]
local has_item1_improved = false
local has_item2_improved = false
local has_item3_improved = false
-- i tak dalej
 

I robię w innym pliku funkcję, która odpala się z callbacka przy użyciu itemów "item1", "item2", "item3" i tak dalej. Ma ona powodować:
1. że użyty item podmieni się na ulepszoną wersję tego itema (czyli "item1" na "item1_improved", "item2" na "item2_improved" i tak dalej)
2. nadać zmiennej z odpowiednim numerkiem w nazwie, tej z pliku skrypt_pierwszy, wartość true
Pierwsze to nie problem, mam problem z drugim.

Kod: [ Pobierz ] [ Ukryj ]
function improve_item(obj)
        local sec = obj:section()
        local item_improved = tostring(sec.."_improved")
        local alife():create(item_improved,db.actor:position(),0,0,0)
        skrypt_pierwszy.has_item1_improved = true -- to jest linia, której nie potrafię zrobić
end
 

Powyższy kod itemki podmienia poprawnie, ale obsłuży tylko zmienną has_item1_improved. Chciałbym to tak ustawić, żeby generowało mi samo odpowiednią nazwę zmiennej do nadania jej wartości true w skrypt_pierwszy (tak jak elegancko generuje stringa z nazwą itema do zespawnowania).
Myślałem, że pobawię się tak:

Kod: [ Pobierz ] [ Ukryj ]
skrypt_pierwszy.has_..item_improved = true
 

ale nie działało. Doczytałem, że concatenate tworzy zawsze nowego stringa i dlatego to nie hula. Jak mogę w jednej czy kilku liniach wygenerować sobie nazwę tej zmiennej? Przeraża mnie alternatywa - tworzenie od za*bania if'ów na dziesiątki linijek dla wszystkich itemów...
Image Image

Merkantylizm, srerkantylizm.
Awatar użytkownika
Plaargath
Weteran

Posty: 653
Dołączenie: 23 Mar 2010, 15:12
Ostatnio był: 25 Paź 2023, 21:53
Kozaki: 234

Reklamy Google

Re: [LUA] generowanie nazwy zmiennej

Postprzez Cromm Cruac w 11 Lut 2015, 16:25

Funkcje i zmienne są trzymane w tablicy
Kod: [ Pobierz ] [ Ukryj ]
this["has_"..item_improved] = true


Tak rozwijając temat, jeśli masz np. numerowane funkcje to możesz je tak samo dynamicznie wywołać
Kod: [ Pobierz ] [ Ukryj ]
function funkcja1()
   ...
end
function funkcja2()
   ...
end

numer = 1
x = this["funkcja"..numer]() --to samo co x = funkcja1()
 
Image

"Twoja opowieść mnie znudziła albowiem nie była o mnie" - Król Julian

Za ten post Cromm Cruac otrzymał następujące punkty reputacji:
Positive Plaargath.
Awatar użytkownika
Cromm Cruac
Modder

Posty: 2542
Dołączenie: 22 Sty 2010, 19:01
Ostatnio był: 01 Cze 2024, 23:08
Miejscowość: Londyn / Bielsko-Biała
Kozaki: 1077

Re: [LUA] generowanie nazwy zmiennej

Postprzez Plaargath w 14 Lut 2015, 01:24

Cromm Cruac napisał(a):Funkcje i zmienne są trzymane w tablicy

A, no dyć! Dzięki za przypomnienie, no przeca. Oh, i kodzik od razu taki schludny :)

- - -

Pany! :+:
Mam bóle porodowe związane ze skracaniem wielgachnych skryptów do jakichś bardziej eleganckich tworów.

Co ja tu źle robię? Mam wrażenie, że for się w ogóle nie wykonuje (tzn. wiem, że się wykonuje, ale nawet końcowe alife create się w grze nie dzieje...). Sądzę, że coś pierdzielę przy tablicy. Syntax jest OK - nawet przepuściłem przez sprawdzacz w odruchu bezradności - znaczit logika nielogiczna.
Taka sytuacja:
Kod: [ Pobierz ] [ Ukryj ]
                local t = {"has_tools4", "has_tools3", "has_tools2", "has_tools"}
                if db.actor:object("tools4") ~= nil then has_tools4 = true end
                if db.actor:object("tools3") ~= nil then has_tools3 = true end
                if db.actor:object("tools2") ~= nil then has_tools2 = true end
                if db.actor:object("tools")  ~= nil then has_tools = true end

                for i = 4, 1, -1 do
                        if i > 1 then
                                if t["has_tools"..i] then
                                        local getrid = (db.actor:object("tools"..i))
                                        alife():release(alife():object(getrid:id()), true)
                                end
                                break
                        else
                                if t["has_tools"] then
                                        local getrid = (db.actor:object("tools"))
                                        alife():release(alife():object(getrid:id()), true)
                                end
                        end
                        alife():create("new_item",db.actor:position(),0,0,0)
                end
 

Uwagi moderatora:

Ale podbij temat zamiast dublować posty. - Wheeljack
Image Image

Merkantylizm, srerkantylizm.
Awatar użytkownika
Plaargath
Weteran

Posty: 653
Dołączenie: 23 Mar 2010, 15:12
Ostatnio był: 25 Paź 2023, 21:53
Kozaki: 234

Re: [LUA] generowanie nazwy zmiennej

Postprzez tt44 w 14 Lut 2015, 20:02

Kod: [ Pobierz ] [ Ukryj ]
local t = {
        "tools" = true,
        "tools2" = true,
        "tools3" = true,
        "tools4" = true
}
                for i = 4, 1, -1 do
                        if i > 1 then
                                for index = 0, db.actor:object_count() - 1 do
                                        local section = db.actor:object(index):section()
                                        if t[section] then
                                                local getrid = db.actor:object(index)
                                                alife():release(alife():object(getrid:id()), true)
                                        end
                                end
                                break
                        else
                                if db.actor:object("tools") then
                                        local getrid = (db.actor:object("tools"))
                                        alife():release(alife():object(getrid:id()), true)
                                end
                        end
                        alife():create("new_item",db.actor:position(),0,0,0)
                end

 

Za ten post tt44 otrzymał następujące punkty reputacji:
Positive Plaargath.
tt44
Stalker

Posty: 88
Dołączenie: 12 Lut 2013, 19:02
Ostatnio był: 24 Cze 2017, 19:07
Kozaki: 60

Re: [LUA] generowanie nazwy zmiennej

Postprzez Plaargath w 16 Lut 2015, 00:16

Powyższy kod powoduje, że skrypt głupieje - zero działania, nawet funkcje obok przestają działać.
Próbuję dociec, w czym rzecz. Wywalam całego for'a i zostaje samo:

Kod: [ Pobierz ] [ Ukryj ]
local t = {
        "tools" = true,
        "tools2" = true,
        "tools3" = true,
        "tools4" = true
}
-- plus poniższa linijka na koniec, żebym wiedział czy wykonało
alife():create("new_item",db.actor:position(),0,0,0)
 

Nic, nie tworzy itema. Coś mu bardzo nie pasuje, bo nawet funkcje obok przestają działać. Dopiero, kiedy zrobię tak:

Kod: [ Pobierz ] [ Ukryj ]
local t = {
        ["tools"] = true,
        ["tools2"] = true,
        ["tools3"] = true,
        ["tools4"] = true
}
-- plus poniższa linijka na koniec, żebym wiedział czy wykonało
alife():create("new_item",db.actor:position(),0,0,0)
 

to tworzy itema.

No to wklejam wyciętego for'a - i znowu schody.
Mamy zatem całość taką:
Kod: [ Pobierz ] [ Ukryj ]
                local t = {
                        ["tools"] = true,
                        ["tools2"] = true,
                        ["tools3"] = true,
                        ["tools4"] = true
                }

                for i = 4, 1, -1 do
                        if i > 1 then
                                for index = 0, db.actor:object_count() - 1 do
                                        local section = db.actor:object(index):section()
                                        if t[section] then
                                                local getrid = db.actor:object(index)
                                                alife():release(alife():object(getrid:id()), true)
                                        end
                                end
                                break
                        else
                                if db.actor:object("tools") then
                                        local getrid = (db.actor:object("tools"))
                                        alife():release(alife():object(getrid:id()), true)
                                end
                        end
                alife():create("new_item",db.actor:position(),0,0,0)
                end
 

Testuję. Efekt: z ekwipunku znika wszystko, new_item się nie tworzy. Wszystko czyli wszystkie toolsy, dowolna ich ilość dowolnego typu - ile tylko mam toolsów któregokolwiek rodzaju przy sobie, wszystkie idą w hugo.

Trocha już głupieję od tego. Co tu trzeba dalej zmienić? Docelowo chcę, żeby zabrało toolsy z najwyższym numerem, zastąpiło je toolsami z niższym o jeden numerem (tools4->tools3, tools3->tools2 itd.) i zespawnowało new_item.

EDIT:
wypieprzyłem przedostatnią linijkę (tą z alife create) i zastąpiłem break'a tym:
return alife():create("new_item",db.actor:position(),0,0,0)
new_item już się spawnuje, toolsy oczywiście bez zmian.

EDIT2:
teraz tą linijkę zastępującą poprzedniego break'a przerzucam o dwie wyżej, tak, że jest zaraz za alife release
efekt: usuwa toolsa, tworzy new_item. Problem jest tylko taki: z tak skonstruowanym skryptem, jeśli posiadam w ekwipunku tools, tools2, tools3, tools4, to wybierze te, które pierwsze były do ekwipunku wrzucone, leci po object indexie, pierwszy chronologicznie się zgadza, no to sru go do piachu i kończymy funkcję. A jednak chodzi o to, żeby zaczął od "4" w nazwie itema i leciał w dół, aż do beznumerowego odpowiednika "1".
Też nie bardzo wiem, jak się zabrać za zespawnowanie toolsa z niższym numerem...
Image Image

Merkantylizm, srerkantylizm.
Awatar użytkownika
Plaargath
Weteran

Posty: 653
Dołączenie: 23 Mar 2010, 15:12
Ostatnio był: 25 Paź 2023, 21:53
Kozaki: 234

Re: [LUA] generowanie nazwy zmiennej

Postprzez tt44 w 16 Lut 2015, 11:59

O ile dobrze zrozumiałem to chodzi o to, żeby po prostu każdy tools zastępował się numer mniejszym?
Jeśli tak, to wystarczy taki zapis:
Kod: [ Pobierz ] [ Ukryj ]
local t = {
        {"tools4", "tools3"},
        {"tools3", "tools2"},
        {"tools2", "tools"}
}

for k, v in pairs(t) do
        if db.actor:object(v[1]) then
                alife():release(alife():object(db.actor:object(v[1]):id()), true)
                alife():create(v[2], db.actor:position(),0,0,0)
        end
end
 
tt44
Stalker

Posty: 88
Dołączenie: 12 Lut 2013, 19:02
Ostatnio był: 24 Cze 2017, 19:07
Kozaki: 60

Re: [LUA] generowanie nazwy zmiennej

Postprzez Plaargath w 16 Lut 2015, 15:09

Jeju, świetny pomysł na skrócenie tego.
Problem jest tylko taki, że nie działa - efektem jest brak efektu, nic się nie dzieje. Jakby ifa nie spełniało.
Image Image

Merkantylizm, srerkantylizm.
Awatar użytkownika
Plaargath
Weteran

Posty: 653
Dołączenie: 23 Mar 2010, 15:12
Ostatnio był: 25 Paź 2023, 21:53
Kozaki: 234

Re: [LUA] generowanie nazwy zmiennej

Postprzez tt44 w 16 Lut 2015, 16:07

Nie mam pojęcia dlaczego nie działa. W jakim callbacku dodałeś ten skrypt?
tt44
Stalker

Posty: 88
Dołączenie: 12 Lut 2013, 19:02
Ostatnio był: 24 Cze 2017, 19:07
Kozaki: 60

Re: [LUA] generowanie nazwy zmiennej

Postprzez Plaargath w 16 Lut 2015, 21:59

Wiesz co, konstrukcja i zagnieżdżenie były ok. Coś się kaszani w momencie samego definiowania tablic. Wszystko niby ok, robię z jednym okiem w podręczniku i niby poprawnie, ale potem on tych zmiennych nie widzi, ma je za nil. Nie mam pojęcia czemu. Uczę się dopiero wykorzystywać potencjał tablic, jeszcze na poziomie samego syntaxu nie jestem zbyt pewny siebie.

W każdym razie taki kod jak poniżej działa dokładnie tak, jak chcę. Pewnie zastosowanie bardziej rozbudowanej tablicy i for in pairs byłoby jeszcze bardziej ergonomiczne, ale w tym momencie nie mam już na to czasu. Zadziałało, nie ma śmietnika, więc zadowalam się tym na ten moment, bo pilniejsza robota jest (ta pieprzona funkcja eat to priorytet). Za jakiś czas na pewno do tego wrócę, bo to bardzo ciekawe wyzwanie jest.

A to mi zahulało:
Kod: [ Pobierz ] [ Ukryj ]
        local t_tools = {
                [1] = "tools",
                [2] = "tools2",
                [3] = "tools3",
                [4] = "tools4
        }
        local has_any_tools

        for i = 1,#t_tools do
                if db.actor:object(t_tools[i]) then
                        has_any_tools = true
                end
        end

        if not has_any_tools then
                return alife():create(sec,db.actor:position(),0,0,0)
        end

        for i = #t_tools,1,-1 do
                if i <= 3 then
                        if db.actor:object(t_tools[i]) then
                                alife():create(t_tools[i+1],db.actor:position(),0,0,0)
                                local getrid = (db.actor:object(t_tools[i]))
                                alife():release(alife():object(getrid:id()), true)
                                alife():create(sec_new,db.actor:position(),0,0,0)
                                break
                        end
                else
                        if db.actor:object(t_tools[i]) then
                                local getrid = (db.actor:object(t_tools[i]))
                                alife():release(alife():object(getrid:id()), true)
                                alife():create(sec_new,db.actor:position(),0,0,0)
                                break
                        end
                end
Image Image

Merkantylizm, srerkantylizm.
Awatar użytkownika
Plaargath
Weteran

Posty: 653
Dołączenie: 23 Mar 2010, 15:12
Ostatnio był: 25 Paź 2023, 21:53
Kozaki: 234


Powróć do Zew Prypeci

Kto jest na forum

Użytkownicy przeglądający to forum: Brak zarejestrowanych użytkowników oraz 1 gość