How would I compare results in lua - lua

DISCLAIMER: The title is bad but I dont know how else to word it
Issue: I am trying to compare entities in a FiveM script I am working on and tell if a player is close to a valid animal model and I cant get it to work and the only model being detected is the player its self
Current code:
local QBCore = exports['qb-core']:GetCoreObject()
local animals = GetGamePool('CPed')
local hasTool = false
local hasKnife =
QBCore.Functions.HasItem('Knife', function(result)
if result then
hasTool = true
hasKnife = true
end
end)
for k, v in pairs(animals) do
local animal = animals[k]
local animalModel = GetEntityModel(animal)
local animalHash = GetHashKey(animal)
local boar = GetHashKey('a_c_boar')
local deer = GetHashKey('a_c_deer')
local coyote = GetHashKey('a_c_coyote')
print("Deer: " .. deer .. "boar: " .. boar .. "coyote: " .. coyote)
if animalHash == boar or deer or coyote then
local entPos = GetEntityCoords(v)
local playerPos = GetEntityCoords(PlayerPedId())
if #(entPos - playerPos) < 1.0 then
foundAnimal = v
print("Animal close by" .. animalHash)
break
end
else
print("No animals found")
end
end
Other things I have tried:
local QBCore = exports['qb-core']:GetCoreObject()
local animals = GetGamePool('CPed')
local validAnimals = {
["a_c_boar"] = true,
["a_c_coyote"] = true,
["a_c_crow"] = true,
["a_c_deer"] = true,
["a_c_mtlion"] = true,
["a_c_pig"] = true,
["a_c_rabbit_01"] = true,
}
local hasTool = false
local hasKnife =
QBCore.Functions.HasItem('Knife', function(result)
if result then
hasTool = true
hasKnife = true
end
end)
for k, v in pairs(animals) do
local animal = animals[k]
local animalModel = GetEntityModel(animal)
local animalModelName = GetEntityModel(animalModel)
if validAnimals[animalModelName] then
local entPos = GetEntityCoords(v)
local playerPos = GetEntityCoords(PlayerPedId())
if #(entPos - playerPos) < 2.0 then
foundAnimal = v
print("Found animal" .. foundAnimal .. "!" .. "Model: " .. entModel)
break
end
end
local QBCore = exports['qb-core']:GetCoreObject()
Citizen.CreateThread(function ()
local animals = GetGamePool('CPed')
local validAnimals = {
["a_c_boar"] = true,
["a_c_coyote"] = true,
["a_c_crow"] = true,
["a_c_deer"] = true,
["a_c_mtlion"] = true,
["a_c_pig"] = true,
["a_c_rabbit_01"] = true,
}
local hasTool = false
local hasKnife =
QBCore.Functions.HasItem('Knife', function(result)
if result then
hasTool = true
hasKnife = true
end
end)
for k, v in pairs(animals) do
local entModel = GetEntityModel(v)
if validAnimals[entModel] then
local entPos = GetEntityCoords(v)
local playerPos = GetEntityCoords(PlayerPedId())
if #(entPos - playerPos) < 2.0 then
foundAnimal = v
print("Found animal" .. foundAnimal .. "!" .. " " .. "Model: " .. entModel)
break
end
end)
Edit: I have tried a few other things aswell but i dont have those versions saved
Edit2: The current code the if statement seems like it doesnt even check anything its like all the code inside of it will run even if and the hashes dont match
Edit3: This also could be a distance calculation issue with the vector3 im not sure tho

Related

Unable to assign property AnimationId. Content expected, got nil

I don't know what's happening, but i'm getting that error in output. Apparently every animations of the Anims table and normalcombo table exists, and the property too. I tested it in Commandbar but didn't work. I don't know how to fix it and don't know what's the problem. Please help me. Code below:
--Local Script
local Replicated = game:GetService("ReplicatedStorage")
local UIS = game:GetService("UserInputService")
local Remote = Replicated.CombateEvent
local Player = game.Players.LocalPlayer
local Char = Player.CharacterAdded:Wait()
local Humanoid = Char:WaitForChild("Humanoid")
local istoolequipped = false
script.Parent.Equipped:Connect(function()
istoolequipped = true
end)
script.Parent.Unequipped:Connect(function()
istoolequipped = false
end)
local lastM1Time = 0
local lastM1End = 0
local combo = 1
local canAir = true
local Anims = {
"rbxassetid://12270296026",
"rbxassetid://12290262661",
"rbxassetid://12290234803",
}
local normalcombo = {
"rbxassetid://12303443278",
"rbxassetid://12303443278",
"rbxassetid://12303527113",
"rbxassetid://12303770582"
}
function hb(size, cframe, ignore, char)
local hitbox = Instance.new("Part", workspace)
hitbox.Size = size
hitbox.CFrame = cframe
hitbox.Anchored = true
hitbox.CanCollide = false
hitbox.Transparency = .6
hitbox.Name = "hb"
hitbox.Material = Enum.Material.ForceField
hitbox.CanQuery = false
local connection
connection = hitbox.Touched:Connect(function()
connection:Disconnect()
end)
local lasttarget
for _, v in pairs(hitbox:GetTouchingParts()) do
if v.Parent:FindFirstChild("Humanoid") and table.find(ignore, v.Parent.Name) == nil then
if lasttarget then
if (lasttarget.Position - char.PrimaryPart.Position).Magnitude > (v.Position - char.PrimaryPart.Position).Magnitude then
lasttarget = v.Parent.PrimaryPart
end
else
lasttarget = v.Parent.PrimaryPart
end
end
end
hitbox:Destroy()
if lasttarget then
return lasttarget.Parent
else
return nil
end
end
UIS.InputBegan:Connect(function(input, istyping)
if istyping then return end
if input.UserInputType == Enum.UserInputType.MouseButton1 and tick() - lastM1Time > .3 and tick() - lastM1End > .7 and istoolequipped then
if tick() - lastM1Time > .7 then
combo = 0
end
lastM1Time = tick()
local animation = Instance.new("Animation", workspace.Animation)
local air = nil
if UIS:IsKeyDown("Space") and canAir == true and combo == 2 then
canAir = false
air = "Up"
animation.AnimationId = Anims[1]
elseif UIS:IsKeyDown("Space") and combo == 3 and not canAir then
air = "Down"
animation.AnimationId = Anims[2]
else
animation.AnimationId = normalcombo[combo]
end
local load = Humanoid:LoadAnimation(animation)
load:Play()
animation:Destroy()
local hitTarg = hb(Vector3.new(3,5,3), Char.PrimaryPart.CFrame * CFrame.new(0,0,-3), {Char}, Char)
local Info = {
["Target"] = hitTarg,
["Combo"] = combo,
["Character"] = Char,
["Air"] = air
}
Remote:FireServer("Combo", Info)
if combo == #normalcombo then
combo = 1
lastM1End = tick()
else
combo += 1
end
Humanoid.WalkSpeed = 0
task.wait(.4)
Humanoid.WalkSpeed = 16
end
end)
The error send me to this line: "animation.AnimationId = normalcombo[combo]"
The error is telling you that normalcombo[combo] is returning nil when it should be a content url. That means that combo isn't a value between 1 and #normalcombo (4).
The only place where that could be is here :
if tick() - lastM1Time > .7 then
combo = 0
end
Here you are resetting the combo counter, but you set it too low. Arrays in lua are 1-indexed. You need to set it to :
combo = 1

FiveM client lua. Problem with shops point

I have a problem with dots, when you enter a clothing store or a barbershop, the menu opens and works well. But after that, anywhere on the map, when you press E, the menu of a clothing store or a barbershop opens.
Here is the code itself, I myself do not know what the problem is there.
QBCore = exports['qb-core']:GetCoreObject()
local LastZone = nil
local CurrentAction = nil
local CurrentActionMsg = ''
local hasAlreadyEnteredMarker = false
local allMyOutfits = {}
local isPurchaseSuccessful = false
local PlayerData = {}
-- Net Events
RegisterNetEvent('QBCore:Client:OnPlayerLoaded', function()
QBCore.Functions.TriggerCallback('fivem-appearance:getPlayerSkin', function(appearance)
exports['fivem-appearance']:setPlayerAppearance(appearance)
PlayerData = QBCore.Functions.GetPlayerData()
if Config.Debug then -- This will detect if the player model is set as "player_zero" aka michael. Will then set the character as a freemode ped based on gender.
Wait(5000)
if GetEntityModel(PlayerPedId()) == `player_zero` then
print('Player detected as "player_zero", Starting CreateFirstCharacter event')
TriggerEvent('qb-clothes:client:CreateFirstCharacter')
end
end
end)
end)
RegisterNetEvent('qb-clothes:client:CreateFirstCharacter', function() -- Event renamed so you dont need to change anything for this to work... hopefully....
QBCore.Functions.GetPlayerData(function(PlayerData)
local skin = 'mp_m_freemode_01'
if PlayerData.charinfo.gender == 1 then
skin = "mp_f_freemode_01"
end
exports['fivem-appearance']:setPlayerModel(skin)
local config = {
ped = false,
headBlend = true,
faceFeatures = true,
headOverlays = true,
components = true,
props = true,
}
exports['fivem-appearance']:setPlayerAppearance(appearance)
exports['fivem-appearance']:startPlayerCustomization(function(appearance)
if (appearance) then
TriggerServerEvent('fivem-appearance:save', appearance)
print('Player Clothing Saved')
else
print('Canceled')
end
end, config)
end)
end, false)
AddEventHandler('fivem-appearance:hasExitedMarker', function(zone)
CurrentAction = nil
end)
RegisterNetEvent('fivem-appearance:clothingShop', function()
exports['qb-menu']:openMenu({
{
header = "👚 | Clothing Store Options",
isMenuHeader = true, -- Set to true to make a nonclickable title
},
{
header = "Buy Clothing - $"..Config.Money,
txt = "Pick from a wide range of items to wear",
params = {
event = "fivem-appearance:clothingMenu",
}
},
{
header = "Change Outfit",
txt = "Pick from any of your currently saved outfits",
params = {
event = "fivem-appearance:pickNewOutfit",
args = {
number = 1,
id = 2
}
}
},
{
header = "Save New Outfit",
txt = "Save a new outfit you can use later on",
params = {
event = "fivem-appearance:saveOutfit",
}
},
{
header = "Delete Outfit",
txt = "Yeah... We didnt like that one either",
params = {
event = "fivem-appearance:deleteOutfitMenu",
args = {
number = 1,
id = 2
}
}
},
})
end)
RegisterNetEvent('fivem-appearance:pickNewOutfit', function(data)
local id = data.id
local number = data.number
TriggerEvent('fivem-appearance:getOutfits')
Wait(150)
local outfitMenu = {
{
header = '< Go Back',
params = {
event = 'fivem-appearance:clothingShop'
}
}
}
for i=1, #allMyOutfits, 1 do
outfitMenu[#outfitMenu + 1] = {
header = allMyOutfits[i].name,
params = {
event = 'fivem-appearance:setOutfit',
args = {
-- number = (1 + i),
ped = allMyOutfits[i].pedModel,
components = allMyOutfits[i].pedComponents,
props = allMyOutfits[i].pedProps
}
}
}
end
exports['qb-menu']:openMenu(outfitMenu)
end)
RegisterNetEvent('fivem-appearance:getOutfits', function()
TriggerServerEvent('fivem-appearance:getOutfits')
end)
RegisterNetEvent('fivem-appearance:sendOutfits', function(myOutfits)
local Outfits = {}
for i=1, #myOutfits, 1 do
table.insert(Outfits, {id = myOutfits[i].id, name = myOutfits[i].name, pedModel = myOutfits[i].ped, pedComponents = myOutfits[i].components, pedProps = myOutfits[i].props})
end
allMyOutfits = Outfits
end)
RegisterNetEvent('fivem-appearance:setOutfit', function(data)
local pedModel = data.ped
local pedComponents = data.components
local pedProps = data.props
local playerPed = PlayerPedId()
local currentPedModel = exports['fivem-appearance']:getPedModel(playerPed)
if currentPedModel ~= pedModel then
exports['fivem-appearance']:setPlayerModel(pedModel)
Wait(500)
playerPed = PlayerPedId()
exports['fivem-appearance']:setPedComponents(playerPed, pedComponents)
exports['fivem-appearance']:setPedProps(playerPed, pedProps)
local appearance = exports['fivem-appearance']:getPedAppearance(playerPed)
TriggerServerEvent('fivem-appearance:save', appearance)
else
exports['fivem-appearance']:setPedComponents(playerPed, pedComponents)
exports['fivem-appearance']:setPedProps(playerPed, pedProps)
local appearance = exports['fivem-appearance']:getPedAppearance(playerPed)
TriggerServerEvent('fivem-appearance:save', appearance)
end
-- TriggerEvent('fivem-appearance:clothingShop')
end)
RegisterNetEvent('fivem-appearance:saveOutfit', function()
local keyboard = exports['qb-input']:ShowInput({
header = "Name your outfit",
submitText = "Create Outfit",
inputs = {
{
text = "Outfit Name",
name = "input",
type = "text",
isRequired = true
},
},
})
if keyboard ~= nil then
local playerPed = PlayerPedId()
local pedModel = exports['fivem-appearance']:getPedModel(playerPed)
local pedComponents = exports['fivem-appearance']:getPedComponents(playerPed)
local pedProps = exports['fivem-appearance']:getPedProps(playerPed)
Wait(500)
TriggerServerEvent('fivem-appearance:saveOutfit', keyboard.input, pedModel, pedComponents, pedProps)
QBCore.Functions.Notify('Outfit '..keyboard.input.. ' has been saved', 'success')
end
end)
RegisterNetEvent('fivem-appearance:deleteOutfitMenu', function(data)
local id = data.id
local number = data.number
TriggerEvent('fivem-appearance:getOutfits')
Wait(150)
local DeleteMenu = {
{
header = '< Go Back',
params = {
event = 'fivem-appearance:clothingShop'
}
}
}
for i=1, #allMyOutfits, 1 do
DeleteMenu[#DeleteMenu + 1] = {
header = 'Delete "'..allMyOutfits[i].name..'"',
txt = 'You will never be able to get this back!',
params = {
event = 'fivem-appearance:deleteOutfit',
args = allMyOutfits[i].id
}
}
end
exports['qb-menu']:openMenu(DeleteMenu)
end)
RegisterNetEvent('fivem-appearance:deleteOutfit', function(id)
TriggerServerEvent('fivem-appearance:deleteOutfit', id)
-- TriggerEvent('fivem-appearance:clothingShop')
QBCore.Functions.Notify('Outfit Deleted', 'error')
end)
RegisterNetEvent("fivem-appearance:purchase", function(bool)
isPurchaseSuccessful = bool
end)
RegisterNetEvent('fivem-appearance:clothingMenu', function()
TriggerServerEvent('fivem-appearances:buyclothing')
Wait(500)
if isPurchaseSuccessful then
local config = {
ped = false,
headBlend = false,
faceFeatures = false,
headOverlays = false,
components = true,
props = true
}
exports['fivem-appearance']:startPlayerCustomization(function(appearance)
if appearance then
TriggerServerEvent('fivem-appearance:save', appearance)
print('Player Clothing Saved')
Wait(1000) -- Wait is needed to clothing menu dosent overwrite the tattoos
TriggerServerEvent('Select:Tattoos')
else
print('Canceled')
Wait(1000) -- Wait is needed to clothing menu dosent overwrite the tattoos
TriggerServerEvent('Select:Tattoos')
end
end, config)
end
end)
RegisterNetEvent('fivem-appearance:barberMenu', function()
local config = {
ped = false,
headBlend = false,
faceFeatures = false,
headOverlays = true,
components = false,
props = false
}
exports['fivem-appearance']:startPlayerCustomization(function (appearance)
if appearance then
TriggerServerEvent('fivem-appearance:save', appearance)
print('Player Clothing Saved')
Wait(1000) -- Wait is needed to clothing menu dosent overwrite the tattoos
TriggerServerEvent('Select:Tattoos')
else
print('Canceled')
Wait(1000) -- Wait is needed to clothing menu dosent overwrite the tattoos
TriggerServerEvent('Select:Tattoos')
end
end, config)
end)
-- Backwords Events so you dont need to replace these
RegisterNetEvent('qb-clothing:client:openMenu', function() -- Admin Menu clothing event
Wait(500)
local config = {
ped = true,
headBlend = true,
faceFeatures = true,
headOverlays = true,
components = true,
props = true
}
exports['fivem-appearance']:startPlayerCustomization(function(appearance)
if appearance then
TriggerServerEvent('fivem-appearance:save', appearance)
print('Player Clothing Saved')
Wait(1000) -- Wait is needed to clothing menu dosent overwrite the tattoos
TriggerServerEvent('Select:Tattoos')
else
print('Canceled')
Wait(1000) -- Wait is needed to clothing menu dosent overwrite the tattoos
TriggerServerEvent('Select:Tattoos')
end
end, config)
end)
RegisterNetEvent('qb-clothing:client:openOutfitMenu', function() -- Name is so that you dont have to replace the event, Used in Appartments, Bossmenu, etc...
exports['qb-menu']:openMenu({
{
header = "👔 | Outfit Options",
isMenuHeader = true, -- Set to true to make a nonclickable title
},
{
header = "Change Outfit",
txt = "Pick from any of your currently saved outfits",
params = {
event = "fivem-appearance:pickNewOutfitApp",
args = {
number = 1,
id = 2
}
}
},
{
header = "Save New Outfit",
txt = "Save a new outfit you can use later on",
params = {
event = "fivem-appearance:saveOutfit",
}
},
{
header = "Delete Outfit",
txt = "Yeah... We didnt like that one either",
params = {
event = "fivem-appearance:deleteOutfitMenu",
args = {
number = 1,
id = 2
}
}
},
})
end)
RegisterNetEvent('fivem-appearance:pickNewOutfitApp', function(data)
local id = data.id
local number = data.number
TriggerEvent('fivem-appearance:getOutfits')
Wait(150)
local outfitMenu = {
{
header = '< Go Back',
params = {
event = 'qb-clothing:client:openOutfitMenu'
}
}
}
for i=1, #allMyOutfits, 1 do
outfitMenu[#outfitMenu + 1] = {
header = allMyOutfits[i].name,
params = {
event = 'fivem-appearance:setOutfit',
args = {
-- number = (1 + i),
ped = allMyOutfits[i].pedModel,
components = allMyOutfits[i].pedComponents,
props = allMyOutfits[i].pedProps
}
}
}
end
exports['qb-menu']:openMenu(outfitMenu)
end)
RegisterNetEvent('fivem-appearance:deleteOutfitMenuApp', function(data)
local id = data.id
local number = data.number
TriggerEvent('fivem-appearance:getOutfits')
Wait(150)
local DeleteMenu = {
{
header = '< Go Back',
params = {
event = 'fivem-appearance:clothingShop'
}
}
}
for i=1, #allMyOutfits, 1 do
DeleteMenu[#DeleteMenu + 1] = {
header = 'Delete "'..allMyOutfits[i].name..'"',
txt = 'You will never be able to get this back!',
params = {
event = 'fivem-appearance:deleteOutfit',
args = allMyOutfits[i].id
}
}
end
exports['qb-menu']:openMenu(DeleteMenu)
end)
-- Theads
CreateThread(function()
while true do
Wait(0)
if CurrentAction ~= nil then
if IsControlPressed(1, 38) then
Wait(500)
if CurrentAction == 'clothingMenu' then
TriggerEvent("fivem-appearance:clothingShop")
end
if CurrentAction == 'barberMenu' then
TriggerEvent("fivem-appearance:barberMenu")
end
end
end
end
end)
CreateThread(function()
for k,v in ipairs(Config.BarberShops) do
local blip = AddBlipForCoord(v)
SetBlipSprite (blip, 71)
-- SetBlipColour (blip, 47)
SetBlipScale (blip, 0.7)
SetBlipAsShortRange(blip, true)
BeginTextCommandSetBlipName('STRING')
AddTextComponentSubstringPlayerName('Barber Shop')
EndTextCommandSetBlipName(blip)
end
for k,v in ipairs(Config.ClothingShops) do
local data = v
if data.blip == true then
local blip = AddBlipForCoord(data.coords)
SetBlipSprite (blip, 73)
-- SetBlipColour (blip, 47)
SetBlipScale (blip, 0.7)
SetBlipAsShortRange(blip, true)
BeginTextCommandSetBlipName('STRING')
AddTextComponentSubstringPlayerName('Clothing Store')
EndTextCommandSetBlipName(blip)
end
end
end)
CreateThread(function()
while true do
local playerCoords, isInClothingShop, isInPDPresets, isInBarberShop, currentZone, letSleep = GetEntityCoords(PlayerPedId()), false, false, nil, true
local sleep = 2000
for k,v in pairs(Config.ClothingShops) do
local data = v
local distance = #(playerCoords - data.coords)
if distance < Config.DrawDistance then
sleep = 500
if distance < data.MarkerSize.x then
isInClothingShop, currentZone = true, k
end
end
end
for k,v in pairs(Config.BarberShops) do
local distance = #(playerCoords - v)
if distance < Config.DrawDistance then
sleep = 500
if distance < Config.MarkerSize.x then
isInBarberShop, currentZone = true, k
end
end
end
if (isInClothingShop and not hasAlreadyEnteredMarker) or (isInClothingShop and LastZone ~= currentZone) then
hasAlreadyEnteredMarker, LastZone = true, currentZone
CurrentAction = 'clothingMenu'
exports['qb-drawtext']:DrawText('[E] Clothing Menu','left')
end
if (isInBarberShop and not hasAlreadyEnteredMarker) or (isInBarberShop and LastZone ~= currentZone) then
hasAlreadyEnteredMarker, LastZone = true, currentZone
CurrentAction = 'barberMenu'
exports['qb-drawtext']:DrawText('[E] Barber Menu','left')
end
if not isInClothingShop and not isInBarberShop and hasAlreadyEnteredMarker then
hasAlreadyEnteredMarker = false
sleep = 0
TriggerEvent('fivem-appearance:hasExitedMarker', LastZone)
exports['qb-drawtext']:HideText()
end
Wait(sleep)
end
end)
-- Command(s)
RegisterCommand('reloadskin', function()
local playerPed = PlayerPedId()
local maxhealth = GetEntityMaxHealth(playerPed)
local health = GetEntityHealth(playerPed)
QBCore.Functions.TriggerCallback('fivem-appearance:getPlayerSkin', function(appearance)
exports['fivem-appearance']:setPlayerAppearance(appearance)
end)
for k, v in pairs(GetGamePool('CObject')) do
if IsEntityAttachedToEntity(PlayerPedId(), v) then
SetEntityAsMissionEntity(v, true, true)
DeleteObject(v)
DeleteEntity(v)
end
SetPedMaxHealth(PlayerId(), maxhealth)
Citizen.Wait(1000) -- Safety Delay
SetEntityHealth(PlayerPedId(), health)
end
end)
-- Testing Command
RegisterCommand('clothingmenu', function()
local config = {
ped = true,
headBlend = true,
faceFeatures = true,
headOverlays = true,
components = true,
props = true,
}
exports['fivem-appearance']:startPlayerCustomization(function (appearance)
if (appearance) then
TriggerServerEvent('fivem-appearance:save', appearance)
print('Player Clothing Saved')
Wait(1000) -- Wait is needed to clothing menu dosent overwrite the tattoos
TriggerServerEvent('Select:Tattoos')
else
print('Canceled')
Wait(1000) -- Wait is needed to clothing menu dosent overwrite the tattoos
TriggerServerEvent('Select:Tattoos')
end
end, config)
end, false)
I tried to set the boundaries of the vectors, it did not help. Tried to find the error but couldn't...
The problem is that the CurrentAction variable is never being reset to nil, so the thread you started to monitor for that keypress continues to "react" to it with the last visited store.
The way the code is written, it appears as though it is meant to be reset to nil only when the when hasExitedMarker function is triggered, but you only trigger this in one place - and it is only conditionally run only if hasAlreadyEnteredMarker is set to true when a shop is detected as being exited. I have a feeling that variable is not being properly maintained.
You can see how this quickly turns into a daisy-chain of state that must be maintained "just so".
Without undergoing a massive debugging session on your behalf, I can only suggest you debug these variables by outputting them to the screen, and watching for when they are set and properly unset (or not).
Higher level advice might be to add whatever routine you use to detect entry/exit into barber/clothing shops to a standalone function you can call directly from the keypress event handler, and skip handling it if you are not in the expected location. This won't solve your original problem of your application state falling into disrepair, but it gives you a chance to "fix" your state on keypress if it turns out you are handling it when you shouldn't be.

(ROBLOX) Dont add gui when other player join

I would explain better here, I'm doing a role game and I do ranks enter image description here
But if somebody another joins then the text over the head will Destroy and to another player spawn the GUI.
The script:
local ServerStorage = game:GetService("ServerStorage")
local Tag = ServerStorage.Tag
local CloneTag = Tag:Clone()
local NameTag = CloneTag.NameTag
local RankTag = CloneTag.RankTag
local VIPTag = CloneTag.VIPTag
game.Players.PlayerAdded:Connect(function(player)
player.CharacterAdded:Connect(function(char)
CloneTag.Parent = char.Head
if player:IsInGroup(14472135) then
if player:GetRankInGroup(14472135) == 1 then
NameTag.Text = player.Name
RankTag.Text = "Trainee"
elseif player:GetRankInGroup(14472135) == 2 then
NameTag.Text = player.Name
RankTag.Text = "Police"
elseif player:GetRankInGroup(14472135) == 3 then
NameTag.Text = player.Name
RankTag.Text = "Specialist"
elseif player:GetRankInGroup(14472135) == 4 then
NameTag.Text = player.Name
RankTag.Text = "Sergeant"
elseif player:GetRankInGroup(14472135) == 252 then
NameTag.Text = player.Name
RankTag.Text = "Corporal"
elseif player:GetRankInGroup(14472135) == 253 then
NameTag.Text = player.Name
RankTag.Text = "Major"
elseif player:GetRankInGroup(14472135) == 254 then
NameTag.Text = player.Name
RankTag.Text = "Lieutenant"
VIPTag.Visible = true
elseif player:GetRankInGroup(14472135) == 255 then
NameTag.Text = player.Name
RankTag.Text = "Colonel"
VIPTag.Visible = true
end
else
NameTag.Text = player.Name
RankTag.Text = "Immigrant"
end
end)
end)
Any Suggestion?
Thanks
As I said in my comment, you simply move the variables so that the cloning is done when a character spawns. There are also ways to make this code better. (1) You can use a table to specify each rank's text, which will shorten it. You can use another table (or the same table with more detailed table values) to store the visibility of the VIP tag. (2) You also don't need to do NameTag.Text = player.Name in every if-elseif body, you can move it out of the if so that it will always happen.
I can show a quick example of fix #1:
local ranks = {
[1] = "Trainee",
[2] = "Police",
[3] = "Specialist",
--...
[255] = "Colonel"
}
local rankVIP = {
[254] = true,
[255] = true
}
and then, all you need to set someone's rank label's text is this:
local rankInGroup = player:GetRankInGroup(14472135)
RankTag.Text = ranks[rankInGroup]
VIPTag.Visible = rankVIP[rankInGroup] or false
Here, the or false means "if I couldn't find this (if this is nothing, if this is nil), make the visibility false. If I did find something, then it will be that."
With all of the fixes and improvements, here is the new code:
local ServerStorage = game:GetService("ServerStorage")
local Tag = ServerStorage.Tag
local ranks = {
[1] = "Trainee",
[2] = "Police",
[3] = "Specialist",
[4] = "Sergeant",
[252] = "Corporal",
[253] = "Major",
[254] = "Lieutenant",
[255] = "Colonel"
}
local rankVIP = {
[254] = true,
[255] = true
}
game.Players.PlayerAdded:Connect(function(player)
player.CharacterAdded:Connect(function(char)
local CloneTag = Tag:Clone()
local NameTag = CloneTag.NameTag
local RankTag = CloneTag.RankTag
local VIPTag = CloneTag.VIPTag
NameTag.Text = player.Name
CloneTag.Parent = char.Head
if player:IsInGroup(14472135) then
local rankInGroup = player:GetRankInGroup(14472135)
RankTag.Text = ranks[rankInGroup]
VIPTag.Visible = rankVIP[rankInGroup] or false
else
RankTag.Text = "Immigrant"
end
end)
end)

Modding Lua script for a game, Sintax and Assets, Transport Fever 2

I am attempting to mod a basic lua script. Under the below code, where "lineInfo.itemsTransported.PASSENGERS" "then: P" is renaming things in game based on whether or not I am selecting a Cargo or Passenger vehicle. I would like the system to signify whether or not I am selecting a "train" or "truck"
Modding instruction manual: https://www.transportfever2.com/wiki/doku.php?id=modding:scriptingbasics
I know how to modify and read lua code, to a degree. But I don't know how to reference another asset. I have read through a good portion of the modding wiki, but as a lehman, I don't know if I should be referencing syntax, or assets, or what its called what Im looking for. Thank you for the help.
////////highlighted section of code first, whole script including snippet below
if (lineInfo.itemsTransported.PASSENGERS ~= nil) then
newLineName = "P"
else
newLineName = "C"
isCargo = true
inner = false
end```
//////// whole code from here down //////////////////////
```function data()
return {
guiInit = function()
local text = api.gui.comp.TextView.new("Rename Lines")
text:setId("mainMenuLeft.LineRename.button.text")
local lineRenameButton = api.gui.comp.Button.new(text, true)
lineRenameButton:setId("mainMenuLeft.LineRename.button")
local mainMenuLeftLayout = api.gui.util.getById("mainMenuLeftLayout")
local numItems = mainMenuLeftLayout:getNumItems()
mainMenuLeftLayout:addItem(lineRenameButton)
lineRenameButton:onClick(
function ()
local lineList = api.gui.comp.Table.new(1, "MULTI")
local text = api.gui.comp.TextView.new("Rename Line")
local renameButton = api.gui.comp.Button.new(text, true)
local lines = api.engine.system.lineSystem.getLines()
local lineHeaderTextView = api.gui.comp.TextView.new("Name")
local textViewList = {}
lineList:setHeader({lineHeaderTextView})
for i, line in ipairs(lines) do
local lineInfo = game.interface.getEntity(line)
local lineTextView = api.gui.comp.TextView.new(lineInfo.name)
lineTextView:addStyleClass("table-item")
lineList:addRow({lineTextView})
textViewList[i] = lineTextView
end
local layout = api.gui.layout.BoxLayout.new("VERTICAL")
local scrollArea = api.gui.comp.ScrollArea.new(lineList,"ScrollTable")
local size = api.gui.util.Size.new(300,800)
scrollArea:setMaximumSize(size)
layout:addItem(scrollArea)
layout:addItem(renameButton)
local win = api.gui.comp.Window.new("Rename Lines", layout)
win:addHideOnCloseHandler()
renameButton:onClick(
function()
local selectedLines = lineList:getSelected()
for i, lineIndex in ipairs(selectedLines) do
if(type(lines[lineIndex+1]) == "number") then
local newName = renameLine(lines[lineIndex+1])
textViewList[lineIndex+1]:setText(newName)
end
end
end
)
end
)
end
}
end```
function renameAllLines()
local lines = api.engine.system.lineSystem.getLines()
for i, line in ipairs(lines) do
renameLine(line)
end
end
function renameLine(line)
local inner = true
local isCargo = false
local lineInfo = game.interface.getEntity(line)
local newLineName = lineInfo.name
if #lineInfo.stops > 0 then
if (lineInfo.itemsTransported.PASSENGERS ~= nil) then
newLineName = "P"
else
newLineName = "C"
isCargo = true
inner = false
end
local prevName = ""
for i, stop in ipairs(lineInfo.stops) do
local townStop = game.interface.getEntity(stop).stations[1]
local stopName = game.interface.getEntity(stop).name
local town = api.engine.system.stationSystem.getTown(townStop)
local townName = api.engine.getComponent(town, api.type.ComponentType.NAME).name
if isCargo and string.find(stopName, "Street") == nil then
newLineName = newLineName .. "-" .. stopName
prevName = stopName
else
if prevName ~= townName then
if i > 1 then
inner = false
end
newLineName = newLineName .. "-" .. townName
prevName = townName
end
end
end
if inner then
newLineName = newLineName .. " " .. "Inner"
end
api.cmd.sendCommand(api.cmd.make.setName(line, newLineName))
end
return newLineName
end`

lua open a file with a table and change certain values

I have a file with a large table. Need to open it, get certain values and replace other values with the new ones. With this example, Females and Males Classroom a and b must equal Teachers Classroom a and b.
Read as much as I can on IO, but I cannot seem to get this to work correctly. Any help will be greatly appreciated.
--file with sample data to test, original file has 7000+lines
theData =
{
["theSchool"] =
{
["theTeachers"] =
{
["theClassroom"] =
{
["a"] = 001,
["b"] = 002,
},
},
["theFemales"] =
{
["theClassroom"] =
{
["a"] = 005,
["b"] = 010,
},
},
["theMales"] =
{
["theClassroom"] =
{
["a"] = 012,
["b"] = 014,
},
},
},
}
Then the function file looks like this
local file = io.open(filepath,'r')
local newCa = '["a"] = '..theData.theSchool.theTeachers.theClassroom.a
local newCb = '["b"] = '..theData.theSchool.theTeachers.theClassroom.b
local replaceFa = '["a"] = '..tostring(theData.theSchool.theFemales.theClassroom.a)
local replaceFb = '["b"] = '..tostring(theData.theSchool.theFemales.theClassroom.b)
local replaceMa = '["a"] = '..tostring(theData.theSchool.theMales.theClassroom.a)
local replaceMb = '["b"] = '..tostring(theData.theSchool.theMales.theClassroom.b)
file:close()
--Will it work?
print("Original Values:")
print(newCa)
print(newCb)
print(replaceFa)
print(replaceFb)
print(replaceMa)
print(replaceMb)
file = io.open(filepath,'r+')
function lines_from(filepath)
lines = {}
for line in io.lines(filepath) do
lines[#lines + 1] = line
end
return lines
end
local lines = lines_from(filepath)
for k,v in ipairs(lines) do
if v == replaceFa then
file:write(newCa..'\n')
elseif v == replaceFb then
file:write(newCb..'\n')
elseif v == replaceMa then
file:write(newCa..'\n')
elseif v == replaceMb then
file:write(newCb..'\n')
else
file:write(v..'\n')
end
--('[' .. k .. ']', v)
end
--replaceF = {[a] = newCa, [b] = newCb}
--replaceM = {[a] = newCa, [b] = newCb}
--file:write(replaceF)
--file:write(replaceM)
--print(tostring(theData.theSchool.theFemales.theClassroom.a))
file:close()
file = io.open(filepath,'r')
--Did it work?
print("New Values:")
print(theData.theSchool.theTeachers.theClassroom.a)
print(theData.theSchool.theTeachers.theClassroom.b)
print(theData.theSchool.theFemales.theClassroom.a)
print(theData.theSchool.theFemales.theClassroom.b)
print(theData.theSchool.theMales.theClassroom.a)
print(theData.theSchool.theMales.theClassroom.b)```
> I'll remove all the print things after it works.
try this solution, loading the table in one read of the file will be faster, and writing is also better with one command write
--- read
local handle = io.open("data.lua",'rb')
local data = handle:read("*a")
handle:close()
data = data .. "\n return theData"
local t = loadstring(data)()
-- edit
theData.theSchool.theTeachers.theClassroom.a = theData.theSchool.theTeachers.theClassroom.a + 1
-- write
local function concat(t, r)
r = r or {}
for k,v in pairs(t) do
if type(v)=="table" then
r[#r+1] = string.format('\t["%s"]={\n',k )
concat(v, r)
r[#r+1] = "\t},\n"
else
r[#r+1] = string.format('\t\t["%s"]=%03s,\n',k ,v )
end
end
return r
end
local r = concat(t)
local text = "theData = { \n " .. table.concat(r) .. "}"
print(text) -- just control
local handle = io.open("data.lua",'wb')
local data = handle:write(text)
handle:close()

Resources