• Print

Author Topic: Confused a little.  (Read 5254 times)

0 Members and 1 Guest are viewing this topic.

Offline [?] The Last Centurion

  • Newbie
  • *
  • Posts: 23
  • Karma: 2
Confused a little.
« on: January 01, 2018, 04:23:23 pm »
I am currently trying to make a script that creates a command, and then displays a chat message to everyone currently connected to the server. After 30 seconds, another message is sent and the timer is stopped, or upon death, the same message for the timer being over is sent.

I currently get the error:
Code: [Select]
[ERROR] lua/autorun/server/advert.lua:7: function arguments expected near '.'
  1. unknown - lua/autorun/server/advert.lua:0



Code: Lua
  1. hook.Add( "OnPlayerChat", "AdvertCommand", function( ply, strText, bTeam, bDead )
  2.  
  3.         strText = string.lower( strText )
  4.  
  5.         if ( strText == "/terror" ) then
  6.                 for k, ply in pairs( player.GetAll() ) do
  7.                         ply:chat.AddText((Color(255, 255, 0), "[Advert] ", ply:Nick(),  " Terror, 30 seconds"))
  8.                 end
  9.                 //timer.Simple( 30, function() chat.AddText( Color(255, 255, 0), "Terror over") end )
  10.                 timer.Create("terrortimer", 30, 1, function()
  11.                         for k, ply in pairs( player.GetAll() ) do
  12.                         ply:chat.AddText(Color(255, 255, 0), "Terror Over")
  13.                         end
  14.                 end)
  15.                 if ply:PlayerDeath( victim, inflictor, attacker ) then
  16.                         timer.Stop(terrortimer)
  17.                         for k, ply in pairs( player.GetAll() ) do
  18.                         ply:chat.AddText(Color(255, 255, 0), "Terror Over")
  19.                         end
  20.                 end
  21.         return true
  22.         end
  23. end)

I have tried using PrintMessage, and PlayerChat. I do want to have the ability to customize colour too.

Offline iViscosity

  • Respected Community Member
  • Hero Member
  • *****
  • Posts: 803
  • Karma: 58
Re: Confused a little.
« Reply #1 on: January 01, 2018, 05:32:18 pm »
I see a lot of things wrong with this.

First, chat.AddText is not in the Player metatable, so calling ply:chat.AddText will just throw an error (which is where the error you're getting is coming from).

Second, you can't call "ply:PlayerDeath()". PlayerDeath, for one, is a serverside hook (which you're trying to call inside a clientside OnPlayerChat hook) and, like chat.AddText, PlayerDeath is not in the Player metatable. Instead, is a gamemode hook. This has to be called on it's own hook.Add() declaration.

Third, timer.Stop doesn't erase the timer, it simply stops it and sets it's timer to 0. Using timer.Create() on an already existing timer isn't a great idea. The best way to do this is to use timer.Remove.

Also, put this file in 'lua/autorun' and not 'lua/autorun/server'.

The way I would tackle this is by doing this:

Using the net library, you can send specific data/messages to specific players or every player from the Server. This allows the Server to verify that something has occurred, and then let the Client know about it. The first thing I'd use to start doing this is using util.AddNetworkString in order to set a String to be able to send specific data to the client in an identifiable way.

Code: Lua
  1. if ( SERVER ) then
  2.     util.AddNetworkString( "TerrorExists" )
  3.     util.AddNetworkString( "TerrorEnd" )
  4.     util.AddNetworkString( "TerrorBegin" )
  5. end
  6.  

I'd use a GM:PlayerSay hook to find when someone says "/terror". This is done similarly to how you're doing it in your script, but instead it would (1) check if the terrortimer already exists, and if it does do nothing but let the player know Terror is already active, and if not it will create the timer; (2) assign a "terror" variable to the player, so that I can use a GM:PlayerDeath hook to check if that person has died, and if they have announce it and destroy the timer.
Code: Lua
  1. hook.Add( "PlayerSay", "CheckForTerrorCommand", function( ply, text, team )
  2.         text = string.lower( text ) -- Force it into lowercase.
  3.         if ( string.sub( text, 1, 7 ) == "/terror" ) then -- Incase there's any more spaces or something else in the string, this checks only the first 7 characters.
  4.                 if ( timer.Exists( "terrortimer" ) ) then
  5.                         net.Start( "TerrorExists" )
  6.                                 net.WriteString( ply:Nick() .. ", Terror is already active" ) -- Feel free to change this to whatever you want.
  7.                         net.Send( ply ) -- Sends this string to only the player calling it.
  8.                         return "" -- Makes nothing appear in the chat, and nothing else to happen.
  9.                 else
  10.                         ply.terrorActive = true -- This assigns a player variable. This is used to check when the player dies.
  11.                         net.Start( "TerrorBegin" )
  12.                                 net.WriteColor( Color( 255, 255, 0, 255 ) ) -- Writes the color you want.
  13.                                 net.WriteString( "[Advert] " .. ply:Nick() .. " Terror, 30 seconds" ) -- The message you want to display.
  14.                         net.Broadcast() -- This sends the message to everyone.
  15.                         timer.Create( "terrortimer", 30, 1, function()
  16.                                 ply.terrorActive = false
  17.                                 net.Start( "TerrorEnd" )
  18.                                         net.WriteColor( Color( 255, 255, 0, 255 ) )
  19.                                         net.WriteString( "Terror over." )
  20.                                 net.Broadcast()
  21.                         end )
  22.                 end
  23.         end
  24. end )

Then I would write up a quick GM:PlayerDeath hook in order to check if the player who activated the terror has died. Since this hook is called every time a player dies, we can check if the player passed in the "victim" argument is the one who has "terrorActive" as "true", and if s/he is, announce that Terror is over.

Code: Lua
  1. hook.Add( "PlayerDeath", "CheckForTerrorDeath", function( vic, inf, att )
  2.         if ( vic.terrorActive and vic.terrorActive == true ) then
  3.                 vic.terrorActive = false
  4.                 timer.Remove( "terrortimer" )
  5.                 net.Start( "TerrorEnd" )
  6.                         net.WriteColor( Color( 255, 255, 0, 255 ) )
  7.                         net.WriteString( "Terror over." )
  8.                 net.Broadcast()
  9.         end
  10. end )
  11.  

Now, we need the Client to be able to (1) receive and (2) interpret the net messages. We can accomplish this through net.Receive. This function allows us to read a given NetworkString ("TerrorExists", "TerrorBegin", or "TerrorEnd") and do something with it. This is also where you're going to use chat.AddText. Since we already wrote our Colour and String, all we have to do is read them and then put them in our function:

Code: Lua
  1. net.Receive( "TerrorExists", function( len )
  2.         local str = net.ReadString()
  3.  
  4.         chat.AddText( str )
  5. end )
  6.  
  7. net.Receive( "TerrorBegin", function( len )
  8.         -- Data MUST be read in the same order we write it, and above I wrote the colour first, so the colour has to be READ first and THEN the string.
  9.         local col = net.ReadColor()
  10.         local str = net.ReadString()
  11.  
  12.         chat.AddText( col, str )
  13. end )
  14.  
  15. net.Receive( "TerrorEnd", function( len )
  16.         local col = net.ReadColor()
  17.         local str = net.ReadString()
  18.  
  19.         chat.AddText( col, str )
  20. end )
  21.  

Good so far? Good. Now, since this is all in a shared file (it's usable on both the client and server), we need to make sure Lua knows when to check for Serverside-only code and Clientside-only code. We can accomplish this by checking if we're on the SERVER or the CLIENT (Yes, they have to be capitalized).

Code: Lua
  1. if ( SERVER ) then
  2.         AddCSLuaFile()
  3.  
  4.         util.AddNetworkString( "TerrorExists" )
  5.         util.AddNetworkString( "TerrorEnd" )
  6.         util.AddNetworkString( "TerrorBegin" )
  7.        
  8.         hook.Add( "PlayerSay", "CheckForTerrorCommand", function( ply, text, team )
  9.                 text = string.lower( text ) -- Force it into lowercase.
  10.                 if ( string.sub( text, 1, 7 ) == "/terror" ) then -- Incase there's any more spaces or something else in the string, this checks only the first 7 characters.
  11.                         if ( timer.Exists( "terrortimer" ) ) then
  12.                                 net.Start( "TerrorExists" )
  13.                                         net.WriteString( ply:Nick() .. ", Terror is already active" ) -- Feel free to change this to whatever you want.
  14.                                 net.Send( ply ) -- Sends this string to only the player calling it.
  15.                                 return "" -- Makes nothing appear in the chat, and nothing else to happen.
  16.                         else
  17.                                 ply.terrorActive = true -- This assigns a player variable. This is used to check when the player dies.
  18.                                 net.Start( "TerrorBegin" )
  19.                                         net.WriteColor( Color( 255, 255, 0, 255 ) ) -- Writes the color you want.
  20.                                         net.WriteString( "[Advert] " .. ply:Nick() .. " Terror, 30 seconds" ) -- The message you want to display.
  21.                                 net.Broadcast() -- This sends the message to everyone.
  22.                                 timer.Create( "terrortimer", 30, 1, function()
  23.                                         ply.terrorActive = false
  24.                                         net.Start( "TerrorEnd" )
  25.                                                 net.WriteColor( Color( 255, 255, 0, 255 ) )
  26.                                                 net.WriteString( "Terror over." )
  27.                                         net.Broadcast()
  28.                                 end )
  29.                         end
  30.                 end
  31.         end )
  32.  
  33.         hook.Add( "PlayerDeath", "CheckForTerrorDeath", function( vic, inf, att )
  34.                 if ( vic.terrorActive and vic.terrorActive == true ) then
  35.                         vic.terrorActive = false
  36.                         timer.Remove( "terrortimer" )
  37.                         net.Start( "TerrorEnd" )
  38.                                 net.WriteColor( Color( 255, 255, 0, 255 ) )
  39.                                 net.WriteString( "Terror over." )
  40.                         net.Broadcast()
  41.                 end
  42.         end )
  43. elseif ( CLIENT ) then
  44.         net.Receive( "TerrorExists", function( len )
  45.                 local str = net.ReadString()
  46.  
  47.                 chat.AddText( str )
  48.         end )
  49.  
  50.         net.Receive( "TerrorBegin", function( len )
  51.                 -- Data MUST be read in the same order we write it, and above I wrote the colour first, so the colour has to be READ first.
  52.                 local col = net.ReadColor()
  53.                 local str = net.ReadString()
  54.  
  55.                 chat.AddText( col, str )
  56.         end )
  57.  
  58.         net.Receive( "TerrorEnd", function( len )
  59.                 local col = net.ReadColor()
  60.                 local str = net.ReadString()
  61.  
  62.                 chat.AddText( col, str )
  63.         end )
  64. end
  65.  

That should pretty much cover it. I tried to teach you as I went, so please don't just copy and paste the final copy and move on. Also keep in mind that I wrote this without testing it, so there can and probably will be errors. However, if you do run into errors, please try to solve them first. The best way to learn is to fix mistakes. Obviously, if you can't figure them out, feel free to respond and I'll try to walk you through it.

Also, here's a challenge for you: I called 'net.Start( "TerrorEnd" )' ... twice. This could be done much more efficiently; try to figure that out.
« Last Edit: January 01, 2018, 05:33:51 pm by iViscosity »
I'm iViscosity. I like gaming and programming. Need some help? Shoot me PM.

Offline [?] The Last Centurion

  • Newbie
  • *
  • Posts: 23
  • Karma: 2
Re: Confused a little.
« Reply #2 on: January 01, 2018, 07:10:37 pm »
Would I add an "else if" after the check for /terror if I wanted to add another command?

Offline iViscosity

  • Respected Community Member
  • Hero Member
  • *****
  • Posts: 803
  • Karma: 58
Re: Confused a little.
« Reply #3 on: January 01, 2018, 07:14:40 pm »
It would be "elseif" but yes.
I'm iViscosity. I like gaming and programming. Need some help? Shoot me PM.

Offline [?] The Last Centurion

  • Newbie
  • *
  • Posts: 23
  • Karma: 2
Re: Confused a little.
« Reply #4 on: January 01, 2018, 07:36:50 pm »
Sorry, I know programming (mostly how it works) just not what anything is, if that makes sense. I've also attempted to create a "/over" command to end the terror early if the player so wishes, so I will be reporting my results when/if it works or when I give up if I get errors.

Also, with the way the writing for the network works, how would I add more than one color? e.g. [Advert](yellow) name(white) Terror(red)? I thought I could just break it down in parts, and colour each string, but then I assumed it would then send each message and they would appear vertically instead of as a single line.

Offline [?] The Last Centurion

  • Newbie
  • *
  • Posts: 23
  • Karma: 2
Re: Confused a little.
« Reply #5 on: January 01, 2018, 07:53:46 pm »
So I've tried to add an "over" command and it doesn't work, I get
Code: [Select]
[ERROR] lua/autorun/advert.lua:31: function arguments expected near '=='
  1. unknown - lua/autorun/advert.lua:0

Code: Lua
  1.                 hook.Add( "PlayerSay", "CheckForTerrorCommand", function( ply, text, team )
  2.                 text = string.lower( text ) -- Force it into lowercase.
  3.                 if ( string.sub( text, 1, 7 ) == "/terror" ) then -- Incase there's any more spaces or something else in the string, this checks only the first 7 characters.
  4.                         if ( timer.Exists( "terrortimer" ) ) then
  5.                                 net.Start( "TerrorExists" )
  6.                                         net.WriteString( ply:Nick() .. ", Terror is already active." ) -- Feel free to change this to whatever you want.
  7.                                 net.Send( ply ) -- Sends this string to only the player calling it.
  8.                                 return "" -- Makes nothing appear in the chat, and nothing else to happen.
  9.                         else
  10.                                 ply.terrorActive = true -- This assigns a player variable. This is used to check when the player dies.
  11.                                 net.Start( "TerrorBegin" )
  12.                                         net.WriteColor( Color( 255, 255, 0, 255 ) ) -- Writes the color you want.
  13.                                         net.WriteString("[Advert] " .. ply:Nick() .. " Terror, 30 seconds." ) -- The message you want to display.
  14.                                 net.Broadcast() -- This sends the message to everyone.
  15.                                 timer.Create( "terrortimer", 30, 1, function()
  16.                                         ply.terrorActive = false
  17.                                         net.Start( "TerrorEnd" )
  18.                                                 net.WriteColor( Color( 255, 255, 0, 255 ) )
  19.                                                 net.WriteString(ply:Nick() .. "'s Terror is over." )
  20.                                         net.Broadcast()
  21.                                 end )
  22.                             end
  23.                 elseif (string.sub( text, 1, 6 ) == "/tover" ) then
  24.                                 if (ply:terrorActive == true) then
  25.                                         ply.terrorActive = false
  26.                                         timer.Remove( "terrortimer" )
  27.                                 else
  28.                                 net.Start( "TerrorEnd" )
  29.                                 net.WriteColor( Color( 255, 255, 0, 255 ) )
  30.                                 net.WriteString(ply:Nick() .. "'s Terror is over." )
  31.                                 net.Broadcast()
  32.                         end
  33.                 end
  34.             return ""
  35.         end )
  36.  
  37.  
« Last Edit: January 01, 2018, 07:58:20 pm by [?] The Last Centurion »

Offline [?] The Last Centurion

  • Newbie
  • *
  • Posts: 23
  • Karma: 2
Re: Confused a little.
« Reply #6 on: January 01, 2018, 08:34:30 pm »
So, I'm back with another question related to my /terror command, more of an addition, if you will. I want to display 3D text above the player who executes /terror. I have the other file untouched, except for that change that is in one of my replies prior. I then found this:
Code: Lua
  1. include("advert.lua")
  2. function DrawAdvertIndicator(ply)
  3.         local zOffset = 50
  4.         local x = ply:GetPos().x                        //Get the X position of our player
  5.         local y = ply:GetPos().y                        //Get the Y position of our player
  6.         local z = ply:GetPos().z                        //Get the Z position of our player
  7.         local pos = Vector(x,y,z+zOffset)       //Add our offset onto the Vector
  8.         local pos2d = pos:ToScreen()            //Change the 3D vector to a 2D one
  9.         draw.DrawText("Terror","Default",pos2d.x,pos2d.y,Color(255,0,0,255),TEXT_ALIGN_CENTER)  //Draw the indicator
  10. end
  11.  
  12. hook.Add("HUDPaint", "LoopThroughPlayers", function()
  13.         for k,v in(player.GetAll()) do
  14.                 if v:terrorActive then
  15.                         DrawAdvertIndicator(v)
  16.                 end
  17.         end
  18. end)
  19.  
I changed the if check from v:IsAdmin to v:terrorActive, and renamed the function. I'm not sure if there's a way to test this (I could maybe offset the text so I can see it myself) but I'm not sure if this actually works.

I also moved the advert lua file (the file this thread was for) and moved it into it's own
Code: [Select]
addon/lua/autorun directory. Both files are in that autorun folder.

Offline [?] The Last Centurion

  • Newbie
  • *
  • Posts: 23
  • Karma: 2
Re: Confused a little.
« Reply #7 on: January 02, 2018, 09:31:22 pm »
So I've made a lot of changes with help from the Garry's Mod Discord for a sense of direction, and I'm stuck on how I would make the convars uneditable when terrorActive == true. I also do not know if the convars are server-sided/uneditable by clients.

Code: Lua
  1. if ( SERVER ) then
  2.         AddCSLuaFile()
  3.  
  4.         util.AddNetworkString( "TerrorExists" )
  5.         util.AddNetworkString( "TerrorEnd" )
  6.         util.AddNetworkString( "TerrorBegin" )
  7.  
  8.  
  9.         terrorcd = CreateConVar( "sv_terrorcd", 900, rep, "Set the cooldown of terror." )
  10.         terrordur = CreateConVar( "sv_terrordur", 30, rep, "Set the duration of terror." )
  11.         terrorunit = CreateConVar( "sv_terrorunit", 1, rep, "Set the unit of terrordur" )
  12.  
  13. function startterror( ply, text, team )
  14.     text = string.lower( text )
  15.     if ( string.sub( text, 1, 7 ) == "/terror" ) then
  16.         value = GetConVar( "sv_terrordur" ):GetInt()
  17.         units = GetConVar( "sv_terrorunit" ):GetInt()
  18.  
  19.           if (units == 1) then
  20.                 unit = "seconds."
  21.         elseif (units == 0) then
  22.                 unit = "minutes."
  23.         end
  24.  
  25.         if ( timer.Exists( "terrortimer" ) ) then
  26.              net.Start( "TerrorExists" )
  27.                 net.WriteString( ply:Nick() .. ", terror is already active." )
  28.                 net.Send( ply )
  29.             return ""
  30.         else
  31.             ply.terrorActive = true
  32.             net.Start( "TerrorBegin" )
  33.                 net.WriteColor( Color( 255, 255, 0, 255 ) )
  34.                 net.WriteString( "[Advert] " .. ply:Nick() .. ": terror, " .. value .. " " .. unit)
  35.             net.Broadcast()
  36.                     timer.Create( "terrortimer", 30, 1, function()
  37.                         ply.terrorActive = false
  38.                         net.Start( "TerrorEnd" )
  39.                             net.WriteColor( Color( 255, 255, 0, 255 ) )
  40.                             net.WriteString( "[Advert] " .. ply:Nick() .. "'s terror timed out." )
  41.                         net.Broadcast()
  42.                     end )
  43.                 end
  44.             end
  45.  
  46.         if ( string.sub(text, 1, 7) == "/terror" ) then
  47.                 return ""
  48.         elseif ( ply.terrorActive == true and string.sub(text, 1, 5) == "/over" ) then
  49.                 ply.terrorActive = false
  50.                 timer.Remove( "terrortimer" )
  51.                         net.Start( "TerrorEnd" )
  52.                 net.WriteColor( Color( 255, 255, 0, 255 ) )
  53.                 net.WriteString( "[Advert] " .. ply:Nick() .. " ended their terror." )
  54.             net.Broadcast()
  55.             return ""
  56.         end
  57.     end
  58. hook.Add( "PlayerSay", "Checkforcommand", startterror )
  59.  
  60.  
  61. function endterror( vic, inf, att )
  62.     if ( vic.terrorActive == true ) then
  63.         vic.terrorActive = false
  64.         timer.Remove( "terrortimer" )
  65.         net.Start( "TerrorEnd" )
  66.             net.WriteColor( Color( 255, 255, 0, 255 ) )
  67.             net.WriteString( "[Advert] " .. vic:Nick() .. "'s terror was ended by suicide." )
  68.         net.Broadcast()
  69.     elseif ( vic.terrorActive == true and att == !vic ) then
  70.         vic.terrorActive = false
  71.         timer.Remove( "terrortimer" )
  72.         net.Start( "TerrorEnd" )
  73.                 net.WriteColor( Color( 255, 255, 0, 255 ) )
  74.             net.WriteString( "[Advert] " .. vic:Nick() .. "'s terror was ended by " .. att:Nick() )
  75.         net.Broadcast()
  76.     end
  77. end
  78. hook.Add( "PlayerDeath", "CheckForTerrorDeath", endterror )
  79.  
  80.  
  81. elseif ( CLIENT ) then
  82.         net.Receive( "TerrorExists", function( len )
  83.                 local str = net.ReadString()
  84.  
  85.                 chat.AddText( str )
  86.         end )
  87.  
  88.         net.Receive( "TerrorBegin", function( len )
  89.                 local col = net.ReadColor()
  90.                 local str = net.ReadString()
  91.                 local value = GetConVar( "terrordur" ):GetInt()
  92.  
  93.                 chat.AddText( col, str , value)
  94.         end )
  95.  
  96.         net.Receive( "TerrorEnd", function( len )
  97.                 local col = net.ReadColor()
  98.                 local str = net.ReadString()
  99.  
  100.                 chat.AddText( col, str )
  101.         end )
  102. end
  103.  

  • Print