Geld für jeden getöteten Zombie
Hallo Welt!
Ich hoffe jemand hat ein wenig Zeit und Lust mir bei meinem kleinem Problem zu helfen.
Wie der Titel bereits sagt, möchte ich das der Spieler für jeden erlegten Zombie etwas Geld bekommt, die Menge des Geldes hängt davon ab welcher Zombie getötet wird. Für eine lächerliche Headcrab soll man natürlich weniger Geld bekommen als für einen Antilon Guard. Ich habe außerdem noch ein Fenster indem die aktuelle Geldmenge ausgegeben werden soll.
Ich denke ich benötige die Funktion GM:OnNPCKilled Da diese ja immer dann aufgerufen wird, wenn ein NPC sich verabschiedet. Ich dachte mir ich mach es so, brauche aber hilfe bei den stellen die ich mit rot markiert habe.
<init.lua>
Code:
local function GM:OnNPCKilled(victim,killer,weapon)
if victim == Headcrab and Player=killer then
AddMoney(5) --Addiert 5 zur Variable Money
elseif victim == Antilon Guard and Player=killer then
AddMoney(200)
end
end
--Ausgelöst durch drücken von F4 (Zum Öffnen des Fensters)
function GM:ShowSpare2(ply)
umsg.Start("Openup", PopUp01) umsg.End()
end
Was füge ich für Headcreab und Antilon Guard ein damit der Code tatsächlich funktioniert?:(
Wie realisiere ich es das die Aktion nur ausgelöst wird wenn ich selbst den Feind ausgeschaltet habe,
ich will ja nicht das ich Geld für Zombies bekomme die durch andere getötet wurden. Geht das so mit dem Code wie er da steht?
<shared.lua>
--Hier befinden sich meine beiden Funktionen AddMoney() und GetMoney()
Code:
Money = 0
function AddMoney(x)
Money = Money + x
print(x .." $ Hinzugefügt")
end
function GetMoney()
print(Money)
return Money
end
concommand.Add("getmoney", GetMoney)
Ich weiss nicht ob das mit dem Geld so hinhaut, ich denke eher nicht, da die Variable Money wahrscheinlich immer wieder den Wert 0 bekommt. Kann ich mein Vorhaben eigentlich so einfach lösen, oder bin ich gezwungen die Werte in Datenbanken zu speichern?
<cl_init.lua>
Das ist der Code für mein kleines Fenster das den aktuellen Geldstand anzeigt.
Code:
function PopUp01()
local ply = LocalPlayer()
local Fenster = vgui.Create("DFrame")
local Label01 = vgui.Create("DLabel",Fenster)
Fenster:SetPos(50,50)
Fenster:SetSize(100,300)
Fenster:SetTitle("Money")
Fenster:SetVisible(true)
Fenster:ShowCloseButton(true)
Fenster:SetDraggable(true)
Fenster:MakePopup()
Label01:SetPos(5,20)
Label01:SetSize(260,20)
Label01:SetColor(Color(255,255,255,255))
Label01:SetFont("default")
Label01:SetText( "Geld: " ..GetMoney() )
end
usermessage.Hook("Openup", PopUp01)
Ich hoffe wirklich sehr das mir jemand helfen kann. Ich wäre euch sehr dankbar ! ;)
-Eddman
AW: Geld für jeden getöteten Zombie
Wo soll dein Code denn hin? Soll der direkt in einen Gamemode implementiert sein, oder unabhänig implementirbar (z.B. im AddOn-Format) sein?
Ich würde dir empfehlen ein serverseitge Autorun-Datei (eine .lua DAtei in "lua/autorun/server") anzulegen, und dort deine OnNPCKilled-Funktion als Hook zu hinterlegen, in der Form:Add/GetMoney kommt dann in eine Datei, welche direkt in den autorun Ordner gelegt wird, und der Fenster-Kram in eine Datei innerhalb von autorun/client.
Für "victim == Headcrab/Antlion/etc." musst du einsetzen.
Für Player=killer müsstest du einsetzen.
AW: Geld für jeden getöteten Zombie
Hi RP-01. Vielen Dank für deinen hilfreiche Beitrag! :) so geht das also... Der Mod ist in einem eigenem Gamemode implementiert. Danke für deine Tipps, ich behalte es mir auf jedenfall im Hinterkopf. Kannst du dir mein "Money Problem" bitte auch mal kurz ansehen? Klappt das so wie ich es gemacht habe, oder bekommt die Variable dann immer einfach wieder den Wert 0 ? :-? Ich werds mal testen.
(PS: Gibt es hier eigentlich keinen Danke Button?)
Note: Bin noch ein ziemlicher Neuling im Lua Modden, habe erst vor einer Woche damit begonnen mich Intensiv mit LUA zu beschäftigen. Daher noch die Anfangsschwierigkeiten.
AW: Geld für jeden getöteten Zombie
Den Dankebutton bekommt man erst ab einer bestimmten Anzahl von Beiträgen (5, 10, keine Ahnung genau)
Bei jedem Serverneustart wird auf alle Fälle der Geldbetrag zurückgesetzt _und_ der Betrag ist nur Clientseitig verfügbar.
Du müsstest den Betrag auch auf dem Server für jeden Spieler einzeln speichern. Klappt anfangs gut mit der internen SQLite Datenbank von Garrys Mod - siehe http://wiki.garrysmod.com/page/Libraries/sql
AW: Geld für jeden getöteten Zombie
Zitat:
Zitat von
minifisch
Den Dankebutton bekommt man erst ab einer bestimmten Anzahl von Beiträgen
Wollte mich bei RP-01 bedanken, aber die werden schon Ihre Gründe dafür haben denke ich, auch wenn mir nicht einfällt welche :D
Danke für den Tipp mit SQLite. Aber vorerst genügt es mir vollkommen wenn der Betrag nach dem Verlassen des Spiels wieder 0 ist, erstmal kleine Kuchen backen.;) Werde ich mir aber als nächstes vornehmen. Hier der Aktuelle Stand:
<init.lua>
Code:
function GM:OnNPCKilled(victim,killer,weapon)
if victim:GetClass() == npc_zombie and killer:IsPlayer() then
AddMoney(25)
print("Zombie killed")
end
end
Ich habe jeweils eine Print Methode hingesetzt um zu testen ob es erkannt wird wenn ich einen Zombie vom Typ "npc_zombie" ins nirvana schick, aber in der Konsole erscheint nichts :?: Wenn ich mit meinem Konsolenkommando die Funktion GetMoney() Aufrufe steht dort auch immernoch 0 dort ? Weiss jemand was ich falsch gemacht habe?
AW: Geld für jeden getöteten Zombie
Ist so wie minifish es sagt, allerdings gibt es noch simplere Methoden das umzusetzen;
Pro Spieler der beitritt, wird z.B. in garrysmod/data/rp_data eine Datei mit seiner SteamID angelegt (Vorsicht, da die ID zwei ":" enthält. Am besten in allem verknüpften Code durch ein gleiches Zeichen ersetzen oder komplett entfernen.). Darin könntest du dann Sachen wie "money" oder allgemeine Daten und Statistiken abspeichern.
- Wenn ein Spieler joined, überprüfen ob er bereits eine Datei hat. Wenn nicht, neue Table für den Player im Script anlegen, alles auf 0/den Standardwert setzen und den Inhalt dann in die entsprechende Datei schreiben. Ansonsten nur die Daten auslesen, und in eine Tabelle im Script schreiben.
- Wenn irgendwo eine Änderung vorgenommen werden soll, Änderung vorerst in seiner Table im Script durchführen.
- Wenn ein Spieler leavt, oder wenn der Server ausgeschaltet/restarted wird (beides per Hook überprüfbar), aktuellen Inhalt der Tabelle(n) in Datei(en) schreiben.
- Um Datenverlust bei Crashes etc. vorzubeugen, im 10 bis 60 Sekundentakt Tabelleninhalte in Datei schreiben, sofern sich seit dem letzten Schreiben überhaupt etwas verändert hat. Muss oder sollte man auch nicht für jeden Spieler simultan machen. Man könnte z.B. alle 0,5s eine Datei aktualisieren.
Wenn du jetzt bei jeder Änderung einen Eintrag aus der SQL-Datenbank auslesen und wieder reinschreiben würdest bzw. die Datei auslesen und neu beschreiben würdest, wäre das bei vielen Kills innerhlab einer kurzen Zeitspanne (z.B. 7 Kills gleichzeitig durch eine Granate) sehr unperformant. 'Kannst natürlich auch die SQLite Datenbanken nach dem selben Prinzip verwenden.
Edit: -snip-
AW: Geld für jeden getöteten Zombie
Hi RP-01, danke ! :) Sehr ausführlich, das werde ich auf jeden fall zu Rate ziehen wenn ich das dann tatsächlich so mache. Ich habe mir auch schon zwei englische Tutorials dazu auf YT angesehen. Aber wie gesagt will ich erstmal kleine Kuchen backen und das ganze nur für den Singleplayer auslegen ;)
Naja erstmal muss ich es überhaupt hinbekommen das überhaupt was passiert. Ich bitte dich/euch meinen vorherigen Post mal anzusehen wenn Zeit & Lust. Ich komm immernoch nicht darauf warum das so nicht hinhaut :/
AW: Geld für jeden getöteten Zombie
Whoops, habe deinen vorherigen Beitrag übersehen.
Also zuerst mal muss npc_zombie in Anführungszeichen, also "npc_zombie", da GetClass() 'nen String ausgibt.
Und die Money-Funktionen geben bei mir serverseitig alles zurück, wenn ich das Zeugs über lua_run aufrufe. Und Clientside, wenn ich es direkt mit if CLIENT then <> end in einer Datei aufrufe.
lua_run_cl scheint momentan nicht zu funktionieren, da ich durch den Command rein gar nichts mehr ausführen kann..
AW: Geld für jeden getöteten Zombie
ahhh...! Ein typischer Anfängerfehler... :bang: Danke!!
Die Sache mit dem Money ist auch fast gelöst.
Es gibt nur noch ein Problem, wenn ich einen Zombie kill, bekomme ich 20 $, der Konsolenkommand getmoney hat bestätigt das diese auch erfolgreich hinzugefügt wurden.
Aber wenn ich das Fenster öffne steht dort immernoch das ich 0 $ habe? hmm, ich schau mir das mal genauer an.
AW: Geld für jeden getöteten Zombie
Dann mach mal local Money = 0 (lokale Variable) in der 1. Zeile, anstatten von Money = 0 (globale Variable).
AW: Geld für jeden getöteten Zombie
Zitat:
Zitat von
RP-01
Dann mach mal local Money = 0 (lokale Variable) in der 1. Zeile, anstatten von Money = 0 (globale Variable).
Das ändert leider auch nichts. Leider Immernoch das selbe Problem, hmmm
AW: Geld für jeden getöteten Zombie
Woran könnte es wohl noch liegen, ich rätsel schon sehr lange und komm einfach nicht drauf :/
AW: Geld für jeden getöteten Zombie
Mir ist gerade eingefallen warum. :D
Der Hook OnNPCKilled wird nur serverseitig ausgeführt, und somit wird auch die Funktion AddMoney nur serverseitig aufgerufen. Was du in deinem Code nun also tust, ist folgendes: Du führst bei der Tötung eines Zombies AddMoney(20) serverseitig aus, womit die Variable Money auch nur serverseitig geändert (um 20 vergrößert) wird. Danach gehst du in deinem clientside Code hin, und rufst für das GUI die variable Money auf, welche dann allerdings immer noch auf 0 steht, da du sie nur serverseitig geändert hast, nie aber clientseitig (Du rufst in dem CS Code die CS Variable Money auf).
Ergo: Du musst die Variable Money nach Veränderung vom Server zum Client senden, damit du auch den aktuellen, serverseitig errechneten Wert beim Client hast.
Das könntest du entweder mit dem neuen net-Modul von GMod 13 realiseren, oder mit den älteren, aber etwas simpleren Usermessages.
Und noch ein Hinweis: Wenn du jetzt mehrere Clients (auch Bots zählen als solche) auf dem Server hast, wird nach deinem bisherigen Code einfach alles zusammenaddiert und jeder hat letztendlich den selben Wert in Money stehen.
Edit: Wäre übriegns cool, wenn du hier mal verifizieren könntest, dass du GMod auch wirklich besitzt.
AW: Geld für jeden getöteten Zombie
Ahh, so geht das also ! Hört sich logisch an, ich teste es später mal gleich und berichte dann.Thx für die Hilfe :)
PS: Ich wollte mich bereits verifizieren, aber es ist fehlgeschlagen weil ich kein öffentliches Profil habe, muss später mal schauen wie ich es öffentliche mache dann tue ich es aufjedenfall ;)
EDIT#1: Bin nun ein verifizierter GMOD Nutzer 8) PS: Ich poste später ob es funktioniert hat
EDIT#2: Jetzt funktioniert es!! thx:up: Habe es über usermessage gelöst, da mir leider nicht bekannt ist, wie ich es mit dem Net-Modul lösen kann. Hier mein Code falls jemand anderes mal das selbe Problem hat ;)
<cl_init.lua>
Code:
function UpdateMoney(data)
Geld = data:ReadLong()
return Geld
end
usermessage.Hook("moneyupdate", UpdateMoney)
function GetGeld()
return Geld
end
--Beim Button muss die Funktion GetMoney() mit der neuen Funktion GetGeld() ersetzt werden.
<init.lua>
Hier habe ich am Ende der Funktion GM:OnNPCKilled diesen Code hinzugefügt:
Code:
umsg.Start("moneyupdate")
umsg.Long(Money)
umsg.End()
PS:
Zitat:
Zitat von
RP-01
Und noch ein Hinweis: Wenn du jetzt mehrere Clients (auch Bots zählen als solche) auf dem Server hast, wird nach deinem bisherigen Code einfach alles zusammenaddiert und jeder hat letztendlich den selben Wert in Money stehen.
Achso, hmm. Weisst du was ich abändern muss damit das nicht so ist? Oder ist das zu aufwendig :/? Ich werd mal überlegen.
AW: Geld für jeden getöteten Zombie
Du solltest die Zeile usermessage.Hook("moneyupdate", UpdateMoney) in den clientside Code verschieben, damit das nachher mit mehreren Clients auch funktioniert. Dass das so im SS Code überhaupt geht, ist eigentlich mehr oder weniger ein Zufall/Bug. Die Datenübertragung dauert aus irgend einem Grund auch länger, und außerdem entspricht es eigentlich nicht der Art und Weise, wie man die Funktion verwenden sollte.
Zitat:
Zitat von
Eddman
Achso, hmm. Weisst du was ich abändern muss damit das nicht so ist? Oder ist das zu aufwendig :/? Ich werd mal überlegen.
Willst du, dass das Geld nur für eine Sitzung jeweils behalten, oder irgendwo dauerhaft für jeden Spieler gespeichert wird? Im Prinzip könntest du auch zuerst ersteres machen, und letzters darauf aufbauen.
AW: Geld für jeden getöteten Zombie
Zitat:
Außerdem hast du mit dem Code jetzt noch nicht das Problem gelöst, dass jeder Spieler sein eigenes Geld dort stehen hat. So wie ich das dem jetzigen Stand nämlich entnehmen kann, wird alles Geld was die Spieler erkillen auf dem Server zusammen addiert. Zudem ist es kein Gute Idee, solche Daten vom Client zum Server zu senden. Wenn sich einer den Quellcode ansieht, könnte er einfach per Skript oder lua_run_cl
Hmm, Jetzt wo du es sagst, stimmt. Thx für die info! Das mit lua_run ist ja fies :-? Die einzige Möglichkeit die mir momentan dagegen einfällt ist, den Quellcode zu verschlüsseln nachdem er Fertiggestellt ist. Aber bin natürlich für Alternativvorschläge offen.
Zitat:
Ansonsten gehört nicht in shared, sondern in die Server-Umgebung. Der Wert soll ja schließlich nur beim Server draufgeschlagen werden, und nicht noch mal bei'm Client. Die einzig richtige Methode für shared wäre, wenn du es so schreibst:
Dachte ich auch, aber beim Client ist der Wert der selbe wie beim Server ;) Auch mit meinem Code
Zitat:
Wenn ich morgen früh in der Schule Zeit habe, kann ich dir den Code mal eben schnell zusammenschreiben. Als Orientierung wie's richtig geht.
Das wär echt nice! :)
AW: Geld für jeden getöteten Zombie
Zitat:
Zitat von
Eddman
Hmm, Jetzt wo du es sagst, stimmt. Thx für die info! Das mit lua_run ist ja fies :-? Die einzige Möglichkeit die mir momentan dagegen einfällt ist, den Quellcode zu verschlüsseln nachdem er Fertiggestellt ist. Aber bin natürlich für Alternativvorschläge offen.
Zitat:
Zitat von
RP-01
Du hättest es sollen nach wie vor über den
OnNPCKilled-Hook serverseitig machen, für jeden aktiven Spieler 'nen extra Table-Eintrag in einer Variable innerhalb von
init.lua erstellen, und den Wert nach Veränderung oder wie in
diesem Post beschrieben anschließend zum Client senden.
Zitat:
Zitat von
Eddman
Das wär echt nice! :)
Um ehrlich zu sein, bin ich gerade viel zu faul für sowas. Wenn du dich allerdings selbst ran machst, bringt's dir eh mehr und ich kann dir auch gerne weiterhin sagen, was jeweils falsch ist oder was besser gemacht werden könnte.
AW: Geld für jeden getöteten Zombie
AW: Geld für jeden getöteten Zombie
Habe mich umentschieden. Habe gerade Lust drauf, und Code das heute Nachmittag doch mal eben schnell vor.
Wenn du willst, kannst du mich auch mal in Steam adden.
AW: Geld für jeden getöteten Zombie
Danke ;)
klar adde ich dich, danke für das angebot :)
Edit: Wie soll das mit dem Link funktionieren? Hab das noch nie so gemacht.
AW: Geld für jeden getöteten Zombie
Spoiler:
sv_zmoney.lua
Dieser Code muss serverside ausgefürt werden.
PHP-Code:
local money = {} //Table, in der das Geld für jeden Spieler gespeichert werden soll
util.AddNetworkString( "zmoney" ) //Precache net message name
function AddMoney( ply, amount, addplyifmissing ) //ply = Player, dem das Geld hinzugefügt werden soll (player), amount = der Wert, der dazu addiert werden soll (float/integer/number), addplyifmissing = Soll der spezifisierte Spieler zur Table hinzugefügt werden, falls nicht in der Table? (boolean)
if money[ ply:SteamID() ] != nil then //wenn
money[ ply:SteamID() ] = money[ ply:SteamID() ] +amount
else //Wenn Spieler nicht in der Table
if addplyifmissing then
AddPlayerToPayroll( ply )
AddMoney( ply, amount, false )
else
ErrorNoHalt( "Specified Player '"..ply.."' not in table!" )
end
end
end
function SetMoney( ply, amount, addplyifmissing ) //amount = der Wert, der als Geldbetrag GESETZT werden soll
if money[ ply:SteamID() ] != nil then
money[ ply:SteamID() ] = amount
else
if addplyifmissing then
AddPlayerToPayroll( ply )
SetMoney( ply, amount, false )
else
ErrorNoHalt( "Specified Player '"..ply.."' not in table!" )
end
end
end
function GetMoney( ply ) //ply = Player, dessen "Kontostand" man wissen will
if money[ ply:SteamID() ] != nil then
return money[ ply:SteamID() ]
else
ErrorNoHalt( "Specified Player '"..ply.."' not in table!" )
end
end
function AddPlayerToPayroll( ply )
money[ ply:SteamID() ] = 0 //erstellt in der Table einen Eintrag mit Namen der SteamID des gejointen Players, welcher auf 0 gesetzt wird
end
//Dieser Hook registriert den Spieler in unserer Table beim ersten Spawnen
hook.Add( "PlayerInitialSpawn", "zmoney_register_ply",
function( ply )
AddPlayerToPayroll( ply )
end
)
//Dieser Hook sollte selbsterklärend sein
hook.Add( "OnNPCKilled", "zmoney",
function( victim, killer, weapon )
if victim:GetClass() == "npc_zombie" then
AddMoney( killer, 20, true )
print( killer:Nick().." received 20$ for killing a "..victim:GetClass().." with a "..weapon:GetClass().."!" )
//Zeugs zum Client senden, damit der den selben Stuff hat, wie der Server
net.Start( "zmoney" )
net.WriteFloat( GetMoney( killer ) )
net.Send( killer )
end
end
)
//BIG NOTE: Statt die Variante mit der Table, geht auch noch etwas anderes: Man nimmt einfach nach wie vor den Spieler, und macht hinter das Objekt (ply) einfach noch .Money dahinter; also ply.Money.
//So kann man dem Entity neh eigene Variable setzen. Würde in AddMoney so aussehen:
--[[
function AddMoney( ply, amount ) //ply = Player, dem das Geld hinzugefügt werden soll (player), amount = der Wert, der dazu addiert werden soll (float/integer/number)
if ply.Money then
ply.Money = ply.Money +amount
else
ply.Money = amount
end
end]]
//Ginge auch. Aber wenn der Player nur mal kurz rejoinen will, ist alles gleich wieder weg. Außerdem können die Clients den Wert nicht auslesen, da das Entity SS ist. Heißt also, dass man den Wert trotzdem wieder zum Client rübersenden muss
//Für den Fall wäre diese Variante schlichtweg noch etwas weniger Schreibarbeit. Die andere Variante hingegen kannst du allgemein bzw. überall verwenden. Außerdem läufst du nicht auf Gefahr mit anderen Variablen zu kollidieren, wenn bei dir oder dem Nutzer noch andere AddOns installiert sind.
Spoiler:
cl_zmoney.lua
Dieser Code muss clientside ausgefürt werden.
PHP-Code:
local money = 0
net.Receive( "zmoney", function( len, ply ) money = net.ReadFloat() end ) //empfängt den Wert vom Server
function GetMoneyCS() return money end //gibt dir clientseitig dein Geld aus
Durch den Spaß bin ich jetzt wieder mal in GMod an etwas am arbeiten. :D
AW: Geld für jeden getöteten Zombie
Vielen vielen Dank für die Mühe :) :up: Vor allem danke das du es so schön auskommentiert hast! Sehr hilfreich! :up:
Zitat:
Zitat von
RP-01
Durch den Spaß bin ich jetzt wieder mal in GMod an etwas am arbeiten. :D
An was wenn ich fragen darf :?
Ich habe gerade auch ein paar gute Ideen die ich in nächster Zeit versuchen werde umzusetzen, z.B. eine runde Platte die einen nach oben katapultiert wenn man sie betritt, weiss nicht ob es das schon gibt, aber der Code sollte eigentlich ziemlich einfach sein nehme ich mal an.