Using "\n" in Garry's Mod draw.DrawText - lua

I want to make an admin-online list. I have the v:Nick() part down but I want to place a new line after it.
Example: (At the top right corner, the names are INSIDE OF EACH OTHER.)

I'm not sure how to go about it, I'm not a VGUI kind of guy, but I believe I have found a solution.
You could make a transparent panel with a DListView like this:
local DermaPanel = vgui.Create( "DFrame" )
DermaPanel:SetPos( 50,50 )
DermaPanel:SetSize( 500, 700 )
DermaPanel:SetTitle( "Admins online" )
DermaPanel:SetVisible( false )
DermaPanel:SetDraggable( false )
DermaPanel:ShowCloseButton( false )
DermaPanel:MakePopup()
local DermaListView = vgui.Create("DListView")
DermaListView:SetParent(DermaPanel)
DermaListView:SetPos(25, 50)
DermaListView:SetSize(450, 625)
DermaListView:SetMultiSelect(false)
DermaListView:AddColumn("Name") -- Add column
DermaListView:AddColumn("Rank")
for k,v in pairs(ply:GetUserGroup() == "admin" or "superadmin" or "owner") do
DermaListView:AddLine(v:Nick(),v:GetUserGroup()) -- Add lines
end
Now all you have to do is a little ScrW() and ScrH() for re-sizing and you should be good to go!
Also, I got this code from https://maurits.tv/data/garrysmod/wiki/wiki.garrysmod.com/indexe102.html so I could save time, I would really recommend checking it out if you have a chance!
Hope I could help, Birdboat

Related

Prevent a file being written to more than once without file:close()

I'm currently working on a logging system. My problems arise when using for loops and file writing. Here is a small example:
file = io.open("text.txt","a") --text.txt can be literally anything
for i=1,8 do
if x == true then
file:write("X is true.")
elseif y == true then
file:write("Y is true.")
end
end
Is there a way to stop the file from being written to multiple times without using file:close()? I have a huge number of different file:write sections, and adding file:close() after all of them would be a massive problem.
If file:close() every time is a massive problem, then this is the custom logic you need.
myFileMetatable = {} --implement all necessary file operations here
function myFileMetatable.write(self, str)
if not self.written then
self.written = true
self.f:write(str)
end
end
function myFileMetatable.close(self)
self.f:close()
end
myFile = {}
function myFile.open(filename, mode)
local t = {f = io.open(filename, mode)}
setmetatable(t, {__index = myFileMetatable})
return t
end
--now you can do
file = myFile.open("test", "w")
file:write("test")
file:write("hello")
file:write("world")
file:close() --and only "test" will be written
Note that this is probably much better than replacing file:write(str) with something file_write(file, str), since you need to store somewhere the fact that the file has already been written to, which you cannot store inside the FILE* object and using a global variable for that will break when using multiple files. That's why I wrap the FILE* object in a table and use myFileMetatable to implement my own methods that I will need.
However, if you need just one file at a time and don't mind the global variable then this is more efficient.
file_written = false
function file_write(file, str)
if not file_written then
file_written = true
file:write(str)
end
end
file = io.open("test", "w")
file_write(file, "test")
file_write(file, "hello")
file_write(file, "world")
file:close()
Mind that it's not as pretty as the first example and you might face a problem in the future, if you decide to expand beyond one file.
How Egor Skriptunoff already said, I'll recommend you to write your own writing function. I'm normally using sth. like this:
local function writeFile(filePath, str)
local outfile = io.open(filePath, 'w')
outfile:write(str)
outfile:close()
end
For appending to the file easily change the mode from w to a.
For my specific case, I've found a solution - since I just want a single option to print, and it's the last option (rather than the first, and I should've specified this), I can just set a variable to what I want my output to be and write that at the end.
log = ""
if x == 2 then
log = "X is 2."
elseif y == 2 then
log = "Y is 2."
end
file:write(log)
For the last option, I'd refer anyone to the accepted answer which should be perfect.

How do I do "io.read" twice on one variable after inputting the wrong type?

Heyo. I'm pretty new to Lua (although I do code with Java), so I don't really know anything on this. I'm basically trying to get a user's input, and if it's not the right type, then restart. Now, I'm not sure if it's just Lua or my IDE (I'm using ZeroBrane Studio if that helps), but it won't reinput for whatever reason. (it just loops, meaning it skips the io.read line)
::restart::
...
a = io.read("*number")
if unit == nil then
print("Error! Incorrect Input!\nRestarting...")
goto restart
end
Oh, and yes, I'm using goto commands for restart. I thought that might be what's causing the issue, but I also tried this:
a = io.read("*number") --input non-number
print(a) --prints
a = io.read("*number") --skips
print(a) --prints
When you input a number, it doesn't skip.
Any help would be nice. Thanks in advance.
nvm i solved it myself
local a
repeat
a = io.read(); a = tonumber(a)
if not a then
print("Incorrect Input!\n(Try using only numbers)")
end
until a
::restart::
local a = io.read("*n", "*l")
if a == nil then
io.read("*l") -- skip the erroneous input line
print("Error! Incorrect Input!\nRestarting...")
goto restart
end
P.S.
Feel free to use goto whenever it makes your code more understandable.
For example, using while of repeat-until loop in this code wouldn't make it better (you would need either additional local variable or break statement).
Instead of using the built-in filter of io.read() (which I do think is bugged sometimes) you should consider using an own little function to ensure that the correct data will be give by the user.
This is such a function:
function --[[ any ]] GetUserInput(--[[ string ]] expectedType, --[[ string ]] errorText)
local --[[ bool ]] needInput = true
local --[[ any ]] input = nil
while needInput do
input = GetData()
if ( type(input) == expectedType ) then
needInput = false
else
print(errorText)
end
end
return input
end
You can then call it with:
local userInput = GetUserInput("number", "Error: Incorrect Input! Please give a number.")
Oh and on a sidenote: Goto is considered bad practice.

GMOD Lua Use type doesn't matter?

recently I have been creating an imitation HarborRP gamemode for Garry's Mod, and I'm trying to recreate the Smuggler NPC (You'll know what I mean if you've ever played HarborRP) So basically I want the NPC to open ONE Derma-Frame window when the player presses their use key on it. I have the NPC created and all of that, but when the player simply presses their use key on the NPC, a million windows pop up, I have the NPC/Entity's use type set to SIMPLE_USE, but it seems like that doesn't matter because so many windows pop up. the VGUI/Derma Frame's settings is set to MakePopup() but that doesn't matter either. See if you can find whats wrong with it, I have very little knowledge of LUA.
init.lua file:
include("shared.lua")
AddCSLuaFile("cl_init.lua")
AddCSLuaFile("shared.lua")
util.AddNetworkString("smug")
hook.Add("PlayerUse", "menuu", function(ply, ent)
net.Start("smug")
net.Send(ply)
end)
function ENT:Initialize()
self:SetModel('models/humans/group01/female_01.mdl')
self:SetHullType(HULL_HUMAN)
self:SetHullSizeNormal()
self:SetNPCState(NPC_STATE_SCRIPT)
self:SetSolid(SOLID_BBOX)
self:SetUseType(SIMPLE_USE)
self:DropToFloor()
end
cl_init.lua file:
include("shared.lua")
function ENT:Draw()
self.Entity:DrawModel()
end
net.Receive("smug", function()
if( !frame ) then
local frame = vgui.Create("DFrame")
frame:SetSize(900,600)
frame:SetPos(ScrW()/2-450,ScrH()/2-300)
frame:SetVisible(true)
frame:MakePopup()
frame:SetDeleteOnClose(true)
elseif (frame) then print("HI")
end
end)
shared.lua file:
ENT.Base = "base_ai"
ENT.Type = "ai"
ENT.PrintName = "[DEV] Smuggler NPC"
ENT.Category = "InVaLiD's HBRP Entities"
ENT.Author = "InVaLiD"
ENT.Spawnable = true
ENT.AdminSpawnable = true
ENT.AutomaticFrameAdvance = true
Something To Note
All of these files are in the addons/smug_npc/lua/entities/ folder.
Yes, I know I have weird names for things, that's just me.
I have a basic to no knowledge of lua, so explain things please :)
I really do appreciate your help, and your will to help people, please know that I thank you all for being here just to sort other people's problems even though you could be spending your time doing something productive, Thank you!
You need to put your code that does net.Send into the entities ENT:Use function rather than on the PlayerUse hook.
function ENT:Use(ply)
net.Start("smug")
net.Send(ply)
end
The below line which you already have in your code in the initialize function makes the entity call the ENT:Use function once when a player presses E on it, which it seems that you want to do so that is good:
self:SetUseType(SIMPLE_USE)
Also, I recommend checking out the gmod forums if you need developer help in future.
GMod forums: https://gmod.facepunch.com/f

call a function from inside a table that's inside another table in lua

I am attempting to build my first game using love2D, I have hit a problem.
The game is a bubble popping game, I want to assign a bubble to each letter on the keyboard so that when a letter is pressed, the bubble will pop.
I have an external file called "bubble.lua" which I have tried to make an object "bubble" with.
to do that I have created a table "bubble" in the bubble.lua which contains functions and variables. Now, this file works when called from main.lua using just one bubble, however I am going to need 26 bubbles so I thought it would be best to store each bubble in another table. For the purpose of trying this I just stored one bubble using 1 as the key.This is where I have problems.
require "bubble"
local bubbles = {}
function love.load()
bubbles[1] = bubble.load(100, 100)
end
function love.draw()
for bubble in bubbles do
bubble.draw()
end
end
function love.keypressed(key)
bubbles[key].bubble.pop()
end
Firstly, I know that the for loop in love.draw() does not work, and the line "bubble[key].bubble.pop" seems to return nil as well
The for loop I can probably find the solution myself online, my main problem is the "bubble[key].bubble.pop()" line, I cannot work out what's wrong or how to fix it.
Can anybody help me?
You may want to look at this as well:
bubble.lua
bubble = {}
function bubble.load(posX, posY)
bubble.x = posX
bubble.y = posY
bubble.popped = false
end
function bubble.draw()
if not bubble.popped then
love.graphics.rectangle("line", bubble.x, bubble.y, 37, 37)
else
love.graphics.rectangle("line", bubble.x, bubble.y, 37, 100)
end
end
function bubble.pop()
bubble.popped = true
end
Edit:
Following the advice of the answer below I now have the following error when I press "a":
main.lua:14: attempt to index a nil value
the updated code is below
main.lua
require "bubble"
local bubbles = {}
function love.load()
bubbles["a"] = bubble.load(100, 100)
end
function love.draw()
for key, bubble in pairs(bubbles) do
bubble.draw()
end
end
function love.keypressed(key)
bubbles[key].pop()
end
any thoughts?
There are several issues with this code. First, you index by number when you initialize bubbles (bubbles[1]), but access them using the key as the index (bubbles[key]), which is NOT a number. You need to settle on one mechanism to index the bubbles. Let's say you picked using key as the index (instead of the number).
This loop:
for bubble in bubbles do
bubble.draw()
end
should be written as:
for key, bubble in pairs(bubbles) do
bubble.draw()
end
and instead of bubbles[key].bubble.pop() you can simply do bubbles[key].pop() as bubbles[key] already returns the bubble you can pop.
To initialize, instead of bubbles[1] you need to do bubbles['a'] (or whatever other value is used by key in love.keypressed(key)).

Implementing TFlers in my game

i'm trying to design a game that was initially designed for 1680 x 1050.. however i implemented Tflers in my project and it not going that well.
First in my love.load i added:
function love.load()
TLfres.setScreen({w= 1680, h = 1200, full=true, vsync = false, aa=0}, 1, false, true)
end
Then in my love.draw():
function love.draw()
TLfres.transform()
love.graphics.setBackgroundColor(0,0,0)
if GameState == "MainMenu" then
love.graphics.draw(background,0,0)
love.graphics.draw(picture, 200, 200)
end
if GameState == "PaintGame" then
love.graphics.setBackgroundColor(20,191,243)
love.graphics.draw(easel, 640,360)
love.graphics.draw(cursor, love.mouse.getX(), love.mouse.getY())
end
TLfres.letterbox(16,9)
end
However i'm getting this error:
TLfres.lua.13: attempt to call field 'setMode' ( a nil value )
How to get rid of this error??
I realized that tlfres requires the old verison of love in order to work, however I want it on the newest version of love. how can I optimize it to work? Thanks!
Thanks guys!
I would add a comment, but I don't have enough reputation.
As of LÖVE 0.9.0, love.graphics.setMode was replaced with love.window.setMode. Talk with the library creator about that.

Resources