Hi,
I need some help for my script : I create a simple derma openable with a console command and in it i would like to see ( if the player is dead when he open it ) the killer name and the weapon which kill him.
I tried this :
[CODE]local killer = ply:GetAttacker()
local killwith = ply:GetInflictor()
-- and then to test if it works
print( killer )
print( killwith )[/CODE]
But it doens't work [CODE]attempt to call method 'GetAttacker'[/CODE]
Can somebody help me please ? :'[
That only works with [URL="https://wiki.garrysmod.com/page/Category:CTakeDamageInfo"]CTakeDamageInfo[/URL], which you can get in [img]http://wiki.garrysmod.com/favicon.ico[/img] [url=http://wiki.garrysmod.com/page/GM/DoPlayerDeath]GM:DoPlayerDeath[/url], [img]http://wiki.garrysmod.com/favicon.ico[/img] [url=http://wiki.garrysmod.com/page/GM/EntityTakeDamage]GM:EntityTakeDamage[/url], and [img]http://wiki.garrysmod.com/favicon.ico[/img] [url=http://wiki.garrysmod.com/page/GM/ScalePlayerDamage]GM:ScalePlayerDamage[/url].
Ply (assuming ply is a player entity) is not a CTakeDamageInfo object, so that's why it doesn't work.
[editline]17th August 2017[/editline]
You could display the killer on the menu by [URL="https://wiki.garrysmod.com/page/Net_Library_Usage"]using networking[/URL] to send [URL="https://wiki.garrysmod.com/page/net/WriteEntity"]the killer entity[/URL] to [URL="https://wiki.garrysmod.com/page/net/Send"]the killed player[/URL] from a [URL="http://wiki.garrysmod.com/page/GM/DoPlayerDeath"]DoPlayerDeath[/URL] hook.
However, this is a pretty annoying method. I just can't think of a better one.
[QUOTE]You could display the killer on the menu by using networking to send the killer entity to the killed player from a DoPlayerDeath hook.
However, this is a pretty annoying method. I just can't think of a better one.[/QUOTE]
Yes that's exaclly what i want to do but I don't know how to use Networking...
[url]http://wiki.garrysmod.com/page/Net_Library_Usage[/url]
In the DoPlayerDeath hook that was posted earlier, send a message containing the killer to the victim. Then on the client save the killer in a variable that you can read in your derma screen
Ok I will try with this thank you ! :)
How, with the Net Usage, can I send information from server to client ? I don't understand very well the library... :/
[QUOTE=Ezotose;52593975]How, with the Net Usage, can I send information from server to client ? I don't understand very well the library... :/[/QUOTE]
Think of it like 2 people having a conversation.
[B]Person 1 (the server) and person 2 (the client).[/B]
Person 1 want's to say something, so they open there mouth (net.Start) and, for example, say a number (net.WriteInt) and then confirm who there saying it to (net.Send).
Person 2 will listen for when person 1 say's something relevant (net.Recieve) and will note down what they say (net.ReadInt).
For the scenario above to work it does require a few extra details which are explained in the code below.
Here is how it would look:
[CODE]
-- SERVER
util.AddNetworkString("message") -- make sure your names are unique and descriptive of what they do
local number = 5 -- The number the server will say
net.Start("message") -- Where the server open its mouth
net.WriteInt(number, 32) -- Where the server says the number, as well as the amount of bits it will use
net.Send(ply) -- Where it defines who will receive this message
----------------------------------------------------------------------
-- CLIENT
net.Recieve("message", function() -- Where the client hears the message
local number = net.ReadInt(32) -- Where the client notes down the number, you MUST have the same bitcount as used in the server code
end)[/CODE]
Not all data types need to have a bit count defined, check the wiki for the relevant one.
A more complex emample is where we send a message from the client to the server and then back to the client.
[B]
Person 1 (the server) and person 2 (the client).[/B]
Person 2 would say (net.Start) a message (net.WriteString) to the Person 1 (net.SendToServer).
Person 1 would listen out for the message (net.Recieve) and note down what they have to say (net.ReadString).
Person 2 would then respond (net.Start) with saying the same message (net.WriteString) back to Person 1 (net.Send).
Person 1 would then say the received message in the console (print)
[CODE]
-- CLIENT
local button = vgui.Create("DButton") -- Makes a interface
button:SetPos(0,0)
button:SetSize(50,50)
button:SetText("Sends message to server")
button.DoClick = function() -- When the button is pressed it runs the following code
net.Start("messageName") -- Client opens its mouth
net.writeString("hi") -- Client says its message
net.SendToServer() -- Client sends it to the server
end
--------------------------------------------------------------
-- SERVER
util.AddNetworkString("messageName") -- make sure your names are unique and descriptive of what they do
util.AddNetworkString("messageName2") -- make sure your names are unique and descriptive of what they do
net.Recieve("messageName", function(_, ply) -- Server hears what the client says and gets there details ( being ply)
local message = net.ReadString() -- Server notes down what it says
net.Start("messageName2") -- Server opens its mouth
net.WriteString(message) -- Server repeats what it noted down earlier
net.Send(ply) -- Server defines who its speaking to (it knows this because ply is defined when the original net message was sent)
end)
--------------------------------------------------------------
-- CLIENT (continued)
net.Recieve("messageName2", function()
local message = net.ReadString()
print(message) -- Prints "hi" in console
end)
[/CODE]
I hope this explanation helps :)
Thank's very munch for your anwser !
And for my script, the server will have to open the mouse (net.Start) in the Hook OnDeath and say (net.WriteString) the attacker and the inflictor ?
And then the client will have to listen (net.Recieve) and write the informations (net.ReadString) ?
Somethink like this :
[CODE]
util.AddNetworkString("message")
function GM:PlayerDeath( victim, inflictor, attacker )
net.Start("message")
net.WriteInt(attacker, 32)
net.WriteInt(inflictor, 34)
net.Send(ply)
end
---------------------------------------------------------------------
-- CLIENT
net.Recieve("message", function()
local killer = net.ReadInt(32)
local killwith =net.ReadInt(34)
end)
[/CODE]
?
Okay here's what you had:
[CODE]
util.AddNetworkString("message")
function GM:PlayerDeath( victim, inflictor, attacker )
net.Start("message")
net.WriteInt(attacker, 32)
net.WriteInt(inflictor, 34)
net.Send(ply)
end
---------------------------------------------------------------------
-- CLIENT
net.Recieve("message", function()
local killer = net.ReadInt(32)
local killwith =net.ReadInt(34)
end)
[/CODE]
Here's it fixed up:
[CODE]
util.AddNetworkString("somebodyDroppedDeadFred")
function GM:PlayerDeath( victim, inflictor, attacker )
net.Start("somebodyDroppedDeadFred") -- renamed for clarity
net.WriteEntity(attacker) -- We don't want to send an integer, let's send instead the attacker entity.
net.WriteEntity(inflictor) -- Let's send the inflictor entity (for local translation)
net.Send(victim) -- ply isn't defined on the server, victim is
end
---------------------------------------------------------------------
-- CLIENT
net.Receive("somebodyDroppedDeadFred", function()
local killer = net.ReadEntity() -- we can read them off like this, I didn't think ReadEntity needed arguments
local killwith = net.ReadEntity()
chat.AddText("You were killed by " ..killer:Nick().. " with a " .. killwith:GetName())
end)
[/CODE]
Okay thank's very munch everybody, but when i try he say :
[code]attempt to concatenate global 'killwith' (a nil value)
[/code]
[QUOTE]
[CODE]
util.AddNetworkString("message")
function GM:PlayerDeath( victim, inflictor, attacker )
net.Start("message")
net.WriteInt(attacker, 32)
net.WriteInt(inflictor, 34)
net.Send(ply)
end
---------------------------------------------------------------------
-- CLIENT
net.Recieve("message", function()
local killer = net.ReadInt(32)
local killwith =net.ReadInt(34)
end)
[/CODE][/QUOTE]
You got the server-client logic right, but you got hooks muddled up and I don't think you are familiar with datatypes and bits!
So firstly, GM:PlayerDeath is [B]NOT[/B] a hook. You shouldn't touch this unless you are making a gamemode or you know what you are doing.
A hook is like a listener. It To run code every time a hook is run you will use [URL="http://wiki.garrysmod.com/page/hook/Add"]hook.Add[/URL]. An example if what a hook will look like is:
[CODE]hook.Add("hookName", "uniqueHookName", function(argument1, agument2) -- (limited to how many the hook has)
-- your code here
end)[/CODE]
You are trying to do is listen to the PlayerDeath hook. You would simple replace "hookName" with "PlayerDeath" and make sure you have the correct arguments.
[CODE]hook.Add("PlayerDeath", "uniqueHookName", function(victim, weapon, attacker) -- (limited to how many the hook has)
-- your code here
end)[/CODE]
Next you want to send the data to the client. To know what datatype we are going to use we need to know what datatypes are. I made a table of the common datatypes used (there are more but its up to you to research):
[IMG]https://i.gyazo.com/af4e6b075357912924dbd242f81ee03d.png[/IMG]
If you are even unsure of the datatype of something you can use [URL="http://wiki.garrysmod.com/page/Global/type"]type()[/URL] to find out. For example print(type("hi")) and it will return string.
[CODE]
print(type("hi")) -- returns "string"
[/CODE]
To know what datatypes the arguments are it says on the wiki page of the hook you are calling.
[IMG]https://i.gyazo.com/1327828294e620c6c7b6e95358dd8e76.png[/IMG]
[B]and also[/B]
[IMG]https://i.gyazo.com/dd3bea40223418e93d31f5936b718708.png[/IMG]
So going back to sending the message to the client, we want to send the data as a entity datatype (we can send player data as an entity datatype as a player is a entity). This is what it will look like:
[CODE]
hook.Add("PlayerDeath", "uniqueHookName", function(victim, weapon, attacker) -- (limited to how many the hook has)
net.Start("name")
net.WriteEntity(victim)
net.WriteEntity(attacker)
net.Send(victim) -- depends on who you want to send this message to
end)
[/CODE]
Another thing I noticed is on your second WriteInt you put 34 bits
[CODE]
local killwith =net.ReadInt(34)
[/CODE]
The maximum is 32 bits. If you are unsure of what bits I highlt advise some research in your own time!
Edit:
Milkshaker got to the code before me but I still give some explanations so I wont ninja :)
[QUOTE=Bings;52594526]So going back to sending the message to the client, we want to send the data as a entity datatype[/QUOTE]
When you use net.WriteEntity you don't send the entity, you send the entity's index. net.Read/WriteEntity are Lua functions, you can check the source [URL="https://github.com/Facepunch/garrysmod/blob/master/garrysmod/lua/includes/extensions/net.lua#L50-L67"]here[/URL].
[QUOTE=txike;52594573]When you use net.WriteEntity you don't send the entity, you send the entity's index. net.Read/WriteEntity are Lua functions, you can check the source [URL="https://github.com/Facepunch/garrysmod/blob/master/garrysmod/lua/includes/extensions/net.lua#L50-L67"]here[/URL].[/QUOTE]
Very true - I wasn't thinking 100%. Thanks for spotting that :happy:
He already say [code]attempt to concatenate global 'killwith' (a nil value)[/code] in the client side.
But it make this like you :
[code]
net.Receive("DeathInfo", function()
local killer = net.ReadEntity()
local killwith = net.ReadEntity()
end)
[/code]
Where are you using killwith? That code shouldn't cause an error.
Did i need to use the killwith and killer in the net.Receive ?
You should read up on [URL="http://lua-users.org/wiki/ScopeTutorial"]scoping[/URL]. It will probably help you a lot in the future too.
I know how to use a function() but is net.Receive no... :/
[QUOTE=Ezotose;52594666]I know how to use a function() but is net.Receive no... :/[/QUOTE]
[QUOTE=Lua Wiki]Local variables only exist in the block they were created in. Outside of the block, they do not exist any more.[/QUOTE]
Sorry, you need to Log In to post a reply to this thread.