PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Heal-Script funktioniert nicht/Hilfe und Erklärungen



spike
14.05.2012, 19:35
Hallo Leute,

ich möchte einmal vorweg sagen: Ich kann VB, PHP, MySQL, HTML, CSS und für Gmod ein bisschen E2. Jetzt würde ich noch gerne Lua lernen und mit einem kleinem Script anfangen. Folgendes habe ich zusammengeschrieben:

function healPlyer(ply, txt, args)

if string.find(txt, "!giveHP") == 1 then
ply:ChatPrint("Du hast jetzt 10000 HP")
ply:SetHealth(10000)

end
end
hook.Add("PlayerSay", "healPlayerHook", healPlayer)

Ich habe zu dem Script jetzt ein paar Fragen, wäre schön wenn ihr mir die beantworten könntet:

1. Bei der function stehen in den Klammern Variablen, sind die festgelegt oder ist das immer so, 1. der Playername, 2. das was er schreibt und 3. alles was sonst noch irgendwie folgt?
2. Gibt es eine Seite wo ich alle Klassen (z.B. SetHealth) finden kann? Die hier im Forum bei den angepinnten Themen geht nicht. Zwar habe ich was im deutschen Wiki gefunden, aber so eine Liste noch nicht.
3. Muss der hook immer am Ende stehen? Wieso?
4. Wo muss ich so ein Script jetzt reinlegen um es im Multiplayer (also über meinen PC als Server mit freunden) benutzen zu können? Den Addon-Ordner oder lua?

Achja und 5. kann mir jemand sagen warum das ganze nicht funktioniert?

Ich wäre euch super dankbar wenn ihr mir helfen könntet :)

Grüße
Spike

gamerpaddy
14.05.2012, 20:11
Ja es ist ein Callback von dem PlayerSay hook (liest den chat aus)

man kann die variablen ply txt und args austauschen, nur die reihenfolge bleibt gleich
in dem fall wird die funktion aufgerufen sobalt einer was in den chat schreibt

ply - ply ist ein entity, und zwar der Spieler der das geschrieben hat
txt - txt ist der Komplette text! args sind nur die wörter (getrennt durch leerzeichen)
-dafuq args irritierte mich, public ist true wenn hauptchat, false wenn teamchat

RP-01
14.05.2012, 20:19
zu 1: Die kannst du nennen wie du willst. Aber es stimmt, dass die erste Variable immer für den betreffenden Player und die zweite für den betroffenen Chattext steht. Die dritte Variable allerdings gibt, in Form eines Booleans, aus, ob der Text ein öffentlicher, oder Teaminterner Chattext ist. Siehe Gamemode.PlayerSay http://wiki.garrysmod.com/favicon.ico (http://maurits.tv/data/garrysmod/wiki/wiki.garrysmod.com/index8519.html?title=Gamemode.PlayerSay)
Übrigens: Wenn du z.B. nur die 1. oder 1. und 2. Variable benötigst, kannst du die 2. und 3. bzw. die 3. auch weglassen.

zu 2: Da die offiziele Wiki im Moment "überarbeitet" wird, nutze folgende Ersatzlinks in der Zeit: GMod Wiki Overview (http://maurits.tv/data/garrysmod/wiki/wiki.garrysmod.com/index4875.html?title=Main_Page), Lua Functions (http://maurits.tv/data/garrysmod/wiki/wiki.garrysmod.com/index09a4.html?title=Lua_Libraries), Lua Hooks (http://maurits.tv/data/garrysmod/wiki/wiki.garrysmod.com/indexd101.html?title=Gamemode_Hooks)

zu 3: Nein, muss er nicht. Es kann auch wie folgt aussehen:hook.Add( "PlayerSay", "healPlayerHook", function( ply, txt, public )
if string.sub(txt, 1, 7) == "!giveHP" then
ply:ChatPrint("Du hast jetzt 10000 HP")
ply:SetHealth(10000)
end
end )(Habe in dem Code string.find, durch das entsprechende Equivalent der string.sub-Funktion ausgetauscht. Selbes Ergebnis, bloß mehr toll.)

zu 4: Du kannst den Script entweder in den "lua/autorun/server" Ordner legen, oder in entsprechendem AddOn-Format (http://maurits.tv/data/garrysmod/wiki/wiki.garrysmod.com/index9be1.html?title=Addons_Guide/Step_Two:_Installing), im AddOn-Ordner platzieren.

Zu deinem Problem: Die Funktion, die im Hook aufgerufen werden soll, hat einen anderen Namen als die Funktion die oben tatsächlich steht. (healPlayer != healPlyer)


@[FX]CJ[CSR]:
In dem Hook gibt es aber keine Arguments-Table.

spike
14.05.2012, 20:43
Okay, danke für die Antworten. Folgendermaßen habe ich das jetzt umfunktioniert:


function healPlayer(ply, txt)

commands = string.Explode(" ")
if string.lower(commands[1,string]) == "!givehp" then

if ply:isAdmin then

playerTarget = commands[2,string]

if playerTarget:isConnected then
playerTarget:ChatPrint("Du hast jetzt 10.000 HP!")
playerTarget:SetHealth(10000)

else
ply.ChatPrint("Spieler nicht gefunden!")

end

else
ply:ChatPrint("Du bist kein Admin")

end

end
end
hook.Add("PlayerSay", "healPlayerHook", healPlayer)

Ich werde jetzt testen ob er so funktioniert, habe aber noch eine Frage zum Debuggen: Kann ich das Script im Server reloaden? Sonst muss ich immer eine Map starten, wenn es nicht geht wieder dicht machen, dann wieder starten und das laden dauert immer so lange. Gibt es da eine Möglichkeit?

Achso, nochwas: Wie kann ich verhindern das der Command im Chat für alle zum Lesen steht? Mit return ""?

Vielen dank für die Links! Also gibt mir die 3. Variable nur boolisch zurück welcher Chat benutzt wurde?

RP-01
14.05.2012, 20:59
Okay, danke für die Antworten. Folgendermaßen habe ich das jetzt umfunktioniert:
<code>
Der Code wird nicht funktionieren, sag ich dir jetzt schon.

Ich werde jetzt testen ob er so funktioniert, habe aber noch eine Frage zum Debuggen: Kann ich das Script im Server reloaden? Sonst muss ich immer eine Map starten, wenn es nicht geht wieder dicht machen, dann wieder starten und das laden dauert immer so lange. Gibt es da eine Möglichkeit?
Ja, man kann den script reloaden: lua_openscript <pfad zum script>/datei.lua

Achso, nochwas: Wie kann ich verhindern das der Command im Chat für alle zum Lesen steht? Mit return ""?
Indeed, einfach "return" oder "return nil" an's Ende.

Vielen dank für die Links! Also gibt mir die 3. Variable nur boolisch zurück welcher Chat benutzt wurde?
Genau. Der Bool gibt nur an, welcher Chat benutzt wurde.

spike
14.05.2012, 22:40
Okay, du hast recht, er funktioniert nicht. Ich habe nochmal am Code ein bisschen gebastelt, funktionieren tut er aber trozdem nicht. Vielleicht sieht ja jemand meinen Fehler und kann mich berichtigen.



function healPlayer(ply, txt) // Erstellt eine Funktion mit Spielernamen und Eingabe

split = string.Explode(" ", txt) // Legt für jedes getrennte Wort ein neues Feld an
command = split[1] // Der Inhalt vom 1. Feld
name = split[2] // Der Inhalt vom 2. Feld

if string.upper(command) == "!GIVEHP" then // Wenn der String !GIVEHP lautet

if ply:isAdmin then // Und der Spieler admin ist

if name:isConnected then // Teste ob der andere Spieler online ist

ply:ChatPrint("Du hast einem Spieler 10.000 HP gegeben!") // Dann geb dem Admin eine Nachricht aus
name:ChatPrint("Dir wurden 10.000 HP gegeben!") // Und dem betroffenen Spieler
name:SetHealth(10000) // Setze die HP des Zielspielers auf 10.000

else // Ist das Ziel nicht online

ply:ChatPrint("Spieler nicht gefunden!") // Sage das er nicht online ist
end

else // Ist der Benutzer kein Admin

ply:ChatPrint("Du bist kein Admin!") // Sage das er keiner ist
end
end
end
hook.Add("PlayerSay", "healPlayerHook", healPlayer) // Lege einen Auslöser für die Funktion fest


Kannst du mir sonst nochmal sagen welchen Pfad ich angeben muss? Relativ zu? Oder den kompletten? Ich habe versucht:

lua_openscript lua/server/autorun/adminhp.lua
lua_openscript garrysmod/lua/server/autorun/adminhp.lua

Ich werde mich dann morgen durch die Basics arbeiten, die anscheind komplizierter sind als ich dachte. Ah, dazu noch eine Frage:
Warum wird "string.find" klein- und "string.Explode" großgeschrieben?

Grüße und gute Nacht
Spike

gamerpaddy
15.05.2012, 11:54
name ist ein string, wie willst du nem string leben geben?

probier folgendes
der abschnitt if isConnnected weglassen

alles darunter (bis chatprint...end)
mit dem austauschen



for k,v in pairs(player.GetAll()) do
if string.find(string.lower(v:Nick()), name) then
v:ChatPrint("Dir wurden 10.000 HP gegeben!") // Und dem betroffenen Spieler
v:SetHealth(10000) // Setze die HP des Zielspielers auf 10.000
end
end

wenn jemand gamer532 und ein anderer gamer949 heisst, kannst du mit !givehp gamer beiden 10k geben

spike
15.05.2012, 13:38
Okay, werde ich probieren - sofern das Script funktioniert. Ich habe mir den Code mal angesehen auf der englischen Wiki, mich stört es da sehr das es immer heisst "Du musst nicht wissen wie das funktioniert, nur wie man es benutzt". Ich habe wohl verstanden das es Key und Value gibt, aber womit werden die beladen? Key der Player und Value die einzelnen Informationen?

Ich habe jetzt das Problem, dass mein Gmod das Script nicht mehr startet. Wenn ich es mit "lua_run" versuche kommt das:

] lua_run adminheal.lua
> adminheal.lua...
[lua_run:1] '=' expected near '<eof>'


Und bei der richtigen Ausführung mit "lua_openscript" das:

] lua_openscript adminheal.lua
Running script adminheal.lua...
Couldn't include file 'adminheal.lua' (File not found) (<nowhere>)


Auch wenn ich statt "adminheal.lua" "autorun" lädt das Script nicht - jedenfalls gibt es keine Reaktionen auf meine Eingaben im Chat.

] lua_openscript autorun
Running script autorun...
LuaGetfile: Not Loading autorun
Couldn't include file 'autorun' (File not found) (<nowhere>)


Jetzt habe ich gerade am Anfang der Funktion folgendes hinzugefügt:

Msg("Das Script läuft.")

[...CODE...]

hook.Add("PlayerSay", "healPlayerHook", healPlayer)

Eigentlich sollte - sofern das Script läuft - in der Konsole die Nachricht "Das Script läuft." auftauchen wenn jemand was schreibt. Tut es aber nicht - sehe aber gerade das es ja keine Sonderzeichen geben darf, probiere es gleich nochmal. Was hab ich da jetzt verbockt?

Achso, danke das ihr mir helft. Ich hab mir den Einstieg in Lua so einfach wie in E2 vorgestellt. Damit lag ich wohl daneben.

Grüße
Spike

gamerpaddy
15.05.2012, 13:47
wo liegt das script denn?
im autorun dann:
lua_openscript autorun/adminheal.lua
immer vollen pfad ab lua ordner angeben, du kannst keine ordner ausführen nur dateien

Lua ist eine klasse für sich. E2 ist so einfach, weil viele funktionen bekannt sind die in lua etwas verstecker sind
wie zb. sin(x) heisst in Lua math.sin(x) - es macht den Script übersichtlicher mit funktionen aus librarys zu arbeiten
aber nicht einfacher

Andererseits kann man in E2 nicht soviel machen, wie in lua (da der Lua code, der E2 es ermöglicht sachen zu tun eigene begrenzungen hat (wie zb. kein setPos auf fremde sachen)


Zumindest (finde ich) sind Lua und E2 die "übersichtlichsten" & einfachsten Scriptsprachen die ich kenne.. bin an vielen weiteren gescheitert
(lag aber meisten daran, dass man die Funktionsnamen nicht kannte aber die Syntax beherrschte)
E2 ist auch deswegen so einfach, weil die motivation da ist - mit anderen zu Scripten (was in np++ oder VC studio nicht geht :)

spike
15.05.2012, 14:06
Ich fand bisher PHP am einfachsten, bin aber trozdem daran Lua zu lernen. Es gibt ja so viele Möglichkeiten, bei denen man Lua anwenden kann.

Ich habe was rausgefunden: Ich habe immer als Pfad den Dateinamen angegeben und dann rumexperimentiert. Als ich dann auf einer Seite auf den Hinweis gestoßen bin, dass "lua" der Ausgangsordner ist, konnte ich das Script starten. Warum es aber nicht von selbst laufen will weiss ich nicht. Folgendes kommt beim manuellen Start:


Running script autorun/server/adminheal.lua...
Hook 'healPlayerHook' Failed: [lua\autorun\server\adminheal.lua:8] attempt to call method 'isAdmin' (a nil value)
Spike: !givehp Spike


So sieht die Ecke des Codes aus:

if ply:isAdmin() then // Und der Spieler admin ist

for k,v in pairs(player.GetAll()) do
if string.find(string.lower(v:Nick()), name) then
v:ChatPrint("Dir wurden 10.000 HP gegeben!") // Und dem betroffenen Spieler
v:SetHealth(10000) // Setze die HP des Zielspielers auf 10.000
else
ply:ChatPrint("Kein Spieler gefunden!")

end
end

else // Ist der Benutzer kein Admin

ply:ChatPrint("Du bist kein Admin!") // Sage das er keiner ist
end
Warum gibt mir "isAdmin" nichts zurück? Hab ich die Funktion falsch eingesetzt? Ahja, das Script liegt in "Pfad zum Steamaccount\garrysmod\garrysmod\lua\autorun\serve r\adminheal.lua"

Ich find die Syntax von Lua bisher komisch, kann mich aber daran gewöhnen ;)

Grüße
Spike

RP-01
15.05.2012, 14:23
IsAdmin, nicht isAdmin. Benutz doch auch die Dokumentationen, wenn du die Links dazu hast.

spike
15.05.2012, 18:35
Vielen dank! Es klappt, kann mir aber vielleicht nochmal jemand sagen, ob ich das so alles richtig verstanden habe? Bzw. was das ich nicht verstanden habe berichtigen?


function healPlayer(ply, txt) // Erstellt eine Funktion mit Spielernamen und Eingabe

local split = string.Explode(" ", txt) // Legt für jedes getrennte Wort ein neues Feld an
local command = split[1] // Der Inhalt vom 1. Feld
local pname = split[2]
Erstellt eine Funktion die "healPlayer" heisst und da Funktionen immer "()" haben gibt diese an 1. Stelle den Spielernamen, an 2. Stelle den eingegebenen Text und an 3. Stelle den benutzten Chat aus.
Dann wird "split" als lokale Variable definiert und als Array gefüllt, jedes Feld ist durch ein Leerzeichen in der Benutzereingabe getrennt.
Nun werden die lokalen Variablen "command" und "pname" mit dem jeweiligen Feld des Arrrays bestückt.


if string.upper(command) == "!GIVEHP" then // Wenn der String !GIVEHP lautet

if ply:IsAdmin() then // Und der Spieler admin ist

for k,v in pairs(player.GetAll()) do
if string.find(string.lower(v:Nick()), pname) then
v:ChatPrint("Dir wurden 10.000 HP gegeben!") // Und dem betroffenen Spieler
v:SetHealth(10000) // Setze die HP des Zielspielers auf 10.000

else
ply:ChatPrint("Spieler nicht gefunden!")

end
end

else // Ist der Benutzer kein Admin

ply:ChatPrint("Du bist kein Admin!") // Sage das er keiner ist
end
end
Der Command wird auf Großbuchstaben gestellt, damit die Groß- und Kleinschreibung des Befehls keine Rolle spielt. Dazu wird geprüft ob der eingegebene Command "!GIVEHP" ist.
Nun prüft das Script ob der Benutzer ein Admin ist, wenn nicht gibt es nur die Nachricht, er seie kein Admin. Wenn doch gehts weiter.
Also weiter in die Schleife wo ein "key" und eine "value" zusammengefügt werden aus den Daten der Spieler die gerade online sind. Die Schleife wird beendet wenn alle Spieler aufgenommen sind.
Nächste Zeile wird die Chateingabe in Kleinbuchstaben konvertiert und in der value "Nick()" nach dem angegebenen Zielnamen durchsucht.
Wenn ein Spieler mit dem Nick gefunden wurde geht es weiter, wenn nicht kommt die Meldung, es seie kein Spieler gefunden worden.
Ist der Spieler also online bekommt er die Nachricht für 10.000HP und die 10.000HP dazu.



return nil
end
hook.Add("PlayerSay", "healPlayerHook", healPlayer) // Lege einen Auslöser für die Funktion fest
Damit der Befehl nicht öffentlich sichtbar wird, gibt die Funktion nichts zurück mittels "return nil".
Jetzt wird zum Schluss der "Trigger" oder auch "hook" zum auslösen des Ereignisses hinzugefügt. 1. Stelle als String der Ereignisname, 2. Stelle als String die HookID und 3. Stelle die aufzurufende Funktion.

Habe ich das alles soweit richtig verstanden? Vielen dank für die ganze Hilfe :) Ich habe mir inzwischen einiges in der Doku angesehen, bin aber immer unsicher bei Schleifen. Auch in allen anderen Sprachen sind Schleifen meine "Feinde".


Grüße
Spike

Edit //
Wo finde ich die Bedank-Funktion hier? Ich sehe wohl das es Leute gibt, bei denen sich bedankt wurde, ich finde die Funktion aber nicht.

gamerpaddy
15.05.2012, 19:08
funktionen haben immer folgendes
"rückgabewert(return)" = "funktionsname"("Parameter1"),("parameter2").....)
die Parameter sind bei jeder funktion angepasst,
zb. bei RunConsoleCommand ist der Parameter 1 ein String, der Parameter 2 auch nur der erste gibt den Commandnamen an, der 2te und 3te und so weiter die parameter (RunConsoleCommand("say", "hello"))
(kann man mit concommand.Add("commandname", function(ply, cmd, args) über die args auslesen args[1] wäre argument 1 usw. 2 wäre argument 2)

Da gibt es aber noch Modifizierende Funktionen wie ent:SetPos oder ply:ConCommand ent:SetColor usw.
da sieht der command so aus
"rückgabewert" = "Eingabe, wie zb. ein entity das modifiziert werden soll":SetPos("argument1, in dem fall ein Vector")

Es gibt noch eine Kategorie, und zwar Funktionen in einem Table
(string.<funktionsname> draw.<funktionsname> math.<funktionsname> sind alles tables mit funktionen drinn)


Wo finde ich die Bedank-Funktion hier? Ich sehe wohl das es Leute gibt, bei denen sich bedankt wurde, ich finde die Funktion aber nicht.
http://s3.imgimg.de/uploads/dsfjhklktzer964ea1e3PNG.png

RP-01
15.05.2012, 19:31
Jetzt wird zum Schluss der "Trigger" oder auch "hook" zum auslösen des Ereignisses hinzugefügt.Nein, andersrum. Die Funktion wird an den Hook geknüpft, sodass beim geschehen der im Hook beschriebenen Aktion, eine andere Aktion ausgeführt wird.
Kleiner, jedoch feiner Unterschied. ;)



CJ[CSR];495919']Es gibt noch eine Kategorie, und zwar Funktionen in einem Table
(string.<funktionsname> draw.<funktionsname> math.<funktionsname> sind alles tables mit funktionen drinn)Das wäre zwar zu vermuten, stimmt aber so nicht. Die Funktionen befinden sich nicht in einer Table, sondern sind lediglich durch die diversen Namens-Präfixe (wie string, table, math, util, render usw.) einzeln gekennzeichnet, um sie leichter der korrekten Library zuordnen zu können.

spike
15.05.2012, 19:37
3990

Ich habe die Funktion nicht, es ist nur das "Melde"-Zeichen da, der andere Button nicht.


Das wäre zwar zu vermuten, stimmt aber so nicht. Die Funktionen befinden sich nicht in einer Table, sondern sind lediglich durch die diversen Namens-Präfixe (wie string, table, math, util, render usw.) einzeln gekennzeichnet, um sie leichter der korrekten Library zuordnen zu können.
Ja, das ist mir klar. Auch ein sehr tolles Thema mit der Vererbung... In Bio ist es fast so schlimm wie in der Programmierung... allerdings muss man nicht so viel auswendig lernen wenn es um Bio geht. Danke für die Zusammenfassung nochmal, aber eine Frage hat sich noch nicht geklärt: Warum werden manche Funktionen groß- und andere kleingeschrieben? Z.B. "string.Explode()" und "string.find()"?

RP-01
15.05.2012, 19:45
3990

Ich habe die Funktion nicht, es ist nur das "Melde"-Zeichen da, der andere Button nicht.Hm, das hatte ich früher auch mal. Schreib mal neh PN an Grüne Gurken, der wird das sicherlich fixen können.


Warum werden manche Funktionen groß- und andere kleingeschrieben? Z.B. "string.Explode()" und "string.find()"?Das hat keinen tieferen Sinn, und man kann es auch machen wie man lustig ist. Im Fall von string.Explode, fand Garry das große e anscheinend cooler als das kleine.

spike
15.05.2012, 21:04
Ah, okay. Ich habe Grüne Gurken eine PN geschickt. Ich bevorzuge das kleine "E", weil man da nicht Shift für drücken muss :P aber in Ordnung. Schon viel in Erfahrung gebracht dank euch.

isch
15.05.2012, 23:09
Soweit mir bekannt kann man sich erst ab einer bestimmten Anzahl an Beiträgen bei anderen Bedanken. Verhindert das man Fake-Accounts erstellen kann und "Danke" klicken kann. Du hast erst 11 Beiträge, liegt also vermutlich daran.

gamerpaddy
16.05.2012, 14:32
Achja bevor es jemand vergisst (Was jetzt eh schon zuspät ist, aber für die zukunft notwendig)
spike, du musst hier im forum vorweisen, dass du gmod gekauft hast
wie dies funktioniert steht hier
http://gmod.de/faq.php?faq=vb_board_usage#faq_steamauth

:)

spike
16.05.2012, 20:16
Danke für die Hinweise. CJ ich hab's versucht, aber es heisst immer, mein Profil sei nicht öffentlich. Obwohl ich für die Verifizierung alles auf Public gestellt habe.

Das kommt dann immer:

Ihr Steam Community Profil ist nicht öffentlich. Bitte änderen Sie Ihren Profil Status und versuchen Sie es dann noch einmal.
Ich habe Profilstatus, Kommentarrechte und Inventar auf Öffentlich gestellt UND bin sogar noch in der Steam-Com online.

http://www.abload.de/img/unbenanntc5kfd.png (http://www.abload.de/image.php?img=unbenanntc5kfd.png)