Code:
local DataStoreService = game:GetService("DataStoreService")
local InvDataStore = DataStoreService:GetDataStore("InvDataStore")
game.Players.PlayerAdded:Connect(function(player)
local Id = player.UserId
local Inventory = Instance.new("Folder")
Inventory.Name = "Inventory"
Inventory.Parent = player
local Inv = InvDataStore:GetAsync(Id)
print(Inv)
print(table.concat(Inv, " "))
end)
game.Players.PlayerRemoving:Connect(function(player)
local Id = player.UserId
local InvTable = {}
for i, v in pairs(game.Players:FindFirstChild(player.Name).Inventory:GetChildren()) do
print("Repear")
if v:IsA("NumberValue") then
table.insert(InvTable, v)
print(v)
end
end
print(InvTable)
print(table.concat(InvTable, " "))
InvDataStore:SetAsync(Id, InvTable)
end)
Output:
13:25:35.288 - Untitled Game auto-recovery file was created
Realism Mod is currently running v2.09! (x2)
table: 0x08cb53598b2d3aa1
table: 0xd8ce847b521d4091
1
13:26:26.703 - Disconnect from ::ffff:127.0.0.1|60556
Explorer:
It seems to be skipping this loop:
for i, v in pairs(game.Players:FindFirstChild(player.Name).Inventory:GetChildren()) do
print("Repear")
if v:IsA("NumberValue") then
table.insert(InvTable, v)
print(v)
end
end
as it seems to not print repear (repeat) OR v (Value) anyone know whats up?
Note: The thing i dont understand, is it doesnt print the value after the save, and before the save, and forgetting the for loop. I can provide extra things to.
It is ignoring the loop because when it gets to game.Players:FindFirstChild(player.Name) the return will be nil, due to that player just leaved the server. What you can try to do is iterating directly from the player object you have, you don't need to look for the object player if you already have it.
Try:
for i, v in pairs(player.Inventory:GetChildren()) do
print("Repear")
if v:IsA("NumberValue") then
table.insert(InvTable, v)
print(v)
end
end
also it is a good practice to store data during the game and not when it leaves, all those objects are removed too when the player leaves, it is better to handle the table during the game and during player removing just update the data store.
Also a good practice is to update datastore for the player every ~5 minutes
Related
I'm building a game in Roblox and I'm trying to make an NPC go towards the player using PathfindingService, and when the path doesn't work it wanders. However, I keep getting the error message "Unable to cast to Dictionary - Server - Script" and I can't seem to find the source of the issue.
I've checked my code for any tables or dictionaries that may be causing the problem, but I can't seem to find anything. Can anyone help me identify the issue and suggest a possible solution?
local PathfindingService = game:GetService("PathfindingService")
local Players = game:GetService("Players")
local NPC = script.Parent
local TargetPlayer = nil
local Path = nil
local CurrentWaypointIndex = 1
local WaypointReachedDistance = 2
function findTargetPlayer()
local players = Players:GetPlayers()
if #players > 0 then
return players[1]
end
return nil
end
function findPathToTarget()
if not TargetPlayer then
return
end
local humanoid = TargetPlayer.Character and TargetPlayer.Character:FindFirstChild("Humanoid")
if not humanoid then
return
end
local startPosition = NPC.HumanoidRootPart.Position
local endPosition = humanoid.RootPart.Position
Path = PathfindingService:CreatePath(startPosition, endPosition)
Path:ComputeAsync()
if Path.Status == Enum.PathStatus.Success then
CurrentWaypointIndex = 1
else
NPC.Humanoid.WalkToPoint = NPC.HumanoidRootPart.Position + Vector3.new(math.random(-5,5), 0, math.random(-5,5))
end
end
function updateWaypoint()
if not Path or CurrentWaypointIndex > #Path.Waypoints then
return
end
local currentWaypoint = Path.Waypoints[CurrentWaypointIndex]
local distanceToWaypoint = (currentWaypoint - NPC.HumanoidRootPart.Position).Magnitude
if distanceToWaypoint <= WaypointReachedDistance then
CurrentWaypointIndex += 1
end
NPC.Humanoid:MoveTo(NPC.HumanoidRootPart.Position + Vector3.new(math.random(-5,5), 0, math.random(-5,5)))
end
function updateTarget()
TargetPlayer = findTargetPlayer()
if TargetPlayer then
findPathToTarget()
end
end
while true do
updateTarget()
updateWaypoint()
wait(0.1)
end
I've tried various solutions, including changing the variable types and removing potential lists, but nothing has worked so far. I expected the script to run without errors and for the NPC to follow the player.
So I am making a CameraScript on roblox studio that when the player touches a robot, the camera focuses on the robot. But the for loop seems to not work though.
The script in game.StarterPlayer.StarterPlayerScripts:
workspace.CurrentCamera.CameraType = Enum.CameraType.Scriptable
game.Players.LocalPlayer.CharacterAdded:Connect(function(char)
local g = char.Name
print(g) --Just for debugging purposes
print("Player Loaded!")
tou(char)
end)
function tou(char)
print("Function had ran")
for _,p in pairs(char:GetChildren()) do
print("We're here loopin ur parts...")
p.Touched:Connect(function(hit)
print("Someone touched?")
if hit.Parent.Name == "Robot" and hit.Parent:IsA("Model") then
print("It's the robot!")
workspace.CurrentCamera.CFrame = hit.Parent.Look.CFrame
workspace.CurrentCamera.Focus = hit.Parent.Head.CFrame
print("Camlock should be successfull...")
else
print("That ain't a robot tho...")
end
end)
end
end
This is the piece of code that doesn't work:
for _,p in pairs(char:GetChildren()) do
print("We're here loopin ur parts...")
p.Touched:Connect(function(hit)
print("Someone touched?")
if hit.Parent.Name == "Robot" and hit.Parent:IsA("Model") then
print("It's the robot!")
workspace.CurrentCamera.CFrame = hit.Parent.Look.CFrame
workspace.CurrentCamera.Focus = hit.Parent.Head.CFrame
print("Camlock should be successfull...")
else
print("That ain't a robot tho...")
end
end)
end
I tried putting the for loop inside directly the CharacterAdded event, putting print() for debugging but it only printed these:
17:55:24.242 <username> - Client - CamLockOnKill:5
17:55:24.243 Player Loaded! - Client - CamLockOnKill:6
17:55:24.243 Function had ran - Client - CamLockOnKill:12
...but it didn't print the others.
It doesn't print We're here loopin ur parts... so the loop isn't run.
The only way to not run a generic for loop like
for _,p in pairs(char:GetChildren()) do
end
without errors is to provide an empty table to pairs.
So char does not have any children. Find out why you think it has children and why it does not.
I have a game I am coding in Tabletop Simulator where all players (P) is given a card (C). Once memorized all players put the card back into the deck (D), shuffled, and then all players are dealt one of the cards from the same deck (D). I am trying to code the simplest algorithm that prevents a player from getting their own card. Now when it comes to coding this should be simple I assume instead of creating simulations to run until it is successful.
Say you have the following:
deck, a randomized deck containing all the cards (including those the players have seen).
seen_card_id_by_player, a lookup table that give you the guid of the card a player has seen.
Then the solution is simply
local card_ids = {}
for i, card_data in ipairs(deck.getObjects()) do
table.insert(card_ids, card_data.guid)
end
for player, seen_card_id in pairs(seen_card_id_by_player) do
local card_id = table.remove(card_ids)
if card_id == seen_card_id then
local i = math.random(1, #card_ids)
card_ids[i], card_id = card_id, card_ids[i]
end
-- Deal the specific card.
deck.takeObject({
guid = card_ids[i],
position = player.getHandTransform().position,
flip = true,
})
end
When we pick the card the player has already seen, it is placed back at a random location among the remaining cards. This ensures that every card has an equal chance of being drawn by the next player. This is the underlying principle of the Fisher-Yates shuffle.
Full demonstration
function broadcast_error(msg)
broadcastToAll(msg, { r=1, g=0, b=0 })
end
function get_cards_seen_by_players()
local player_ids = Player.getAvailableColors()
local error = false
local seen_card_by_player = {}
for i, player_id in ipairs(player_ids) do
local player = Player[player_id]
local hand_objs = player.getHandObjects()
local player_error = false
if #hand_objs > 1 then
player_error = true
elseif #hand_objs == 1 then
local card = hand_objs[1]
if card.tag ~= "Card" then
player_error = true
else
seen_card_by_player[player] = card
end
end
if player_error then
broadcast_error(player_id .. " doesn't have a valid hand.")
error = true
end
end
if error then
return nil
end
return seen_card_by_player
end
function run()
local deck = getObjectFromGUID("...")
local seen_card_by_player = get_cards_seen_by_players()
if seen_card_by_player == nil or next(seen_card_by_player) == nil then
return
end
local seen_card_id_by_player = {}
for player, card in pairs(seen_card_by_player) do
local card_id = card.guid
seen_card_id_by_player[player] = card_id
card.putObject(deck)
end
deck.randomize()
local card_ids = {}
for i, card_data in ipairs(deck.getObjects()) do
table.insert(card_ids, card_data.guid)
end
for player, seen_card_id in pairs(seen_card_id_by_player) do
local card_id = table.remove(card_ids)
if card_id == seen_card_id then
local i = math.random(1, #card_ids)
card_ids[i], card_id = card_id, card_ids[i]
end
deck.takeObject({
guid = card_ids[i],
position = player.getHandTransform().position,
flip = true,
})
end
end
Create a game with a deck of cards. Place the above code in Global, replacing ... with the deck's GUID. To run the demonstration, deal one card to any number of players, then use /execute Global.call("run") in the chat window.
So, I've been working on this for the past week. I have tried everything (based on the knowledge I know) and yet nothing... my code didn't work the first time, the second time, the third time... the forth... etc... at the end, I let frustration take control of me and I ended up deleting the whole script. Luckily not the parts and models, otherwise I'm really screwed...
I need to create a game in which I have to create a keypad of sorts, at first I thought GUI would work... no, it needs to be SurfaceGUI, which I don't know how to handle well... Anyway, I needed to create a keypad using SurfaceGUI, and display it on a separate screen, as a typical keypad would...
The Player would first have to enter an "initial" number, meaning in order to enter the randomly generated number he first needed to input the static pin in order to "log in," after that, then he would try to guess the number...
I've literally tried everything I could but nothing... It's mainly because of my lack of experience in LUA, I'm more advanced in Python and barely know a thing in Java... If someone could assist me on how to do this, I would appreciate it greatly
First, download this and put it in a ScreenGui in StarterGui. Then, use the following LocalScript placed inside the PIN frame:
-- Script settings
local len = 4 -- replace this as needed...
local regen = false -- determines whether PIN will regenerate after a failed attempt
local regmes = "Enter PIN..." -- start message of PIN pad
local badmes = "Wrong PIN!" -- message displayed when PIN is wrong
local success = "Correct PIN!" -- message displayed when PIN is right
-- Script workings
local pin = script.Parent
local top = pin.Top
local txt = top.Numbers
local nums = top.NumKeys
local pin
local stpin
local nms
txt.Text = regmes
local see = game:GetStorage("ReplicatedStorage").PINActivate
local function activate()
if pin.Visible then
pin.Visible = false
for _, btn in pairs(nums:GetChildren()) do
btn.Active = false
end
return
else
pin.Visible = true
for _, btn in pairs(nums:GetChildren()) do
btn.Active = true
end
return
end
end
local function rand()
math.randomseed(os.time) -- better random numbers this way
return tostring(math.floor(math.random(0,9.9)))
end
local function gen()
nms = {rand()}
for i=2, len, 1 do
nms[#nms+1]=rand()
end
stpin = nms[1]
for i=2, #nms, 1 do
stpin = stpin..nms[i]
end
pin = tonumber(stpin) -- converts the number string into an actual number
end
gen()
local function activate(str)
if tonumber(str) ~= pin then
txt.Text = badmes
wait(2)
txt.Text = regmes
if regen then
gen()
wait(0.1)
end
return
else
txt.Text = success
wait(2)
activate()
-- insert code here...
end
end
for _, btn in pairs(nums:GetChildren()) do
btn.Activated:Connect(function()
if txt.Text == "Wrong PIN!" then return end
txt.Text = txt.Text..btn.Text
if string.len(txt.Text) >= len then
activate(txt.Text)
end
wait(0.1)
end)
end
see.OnClientEvent:Connect(activate)
And in a Script put this:
local Players = game:GetService("Players")
local see = game:GetService("ReplicatedStorage").PINActivate
local plr
-- replace Event with something like Part.Touched
Event:Connect(function(part)
if part.Parent.Head then
plr = Players:GetPlayerFromCharacter(part.Parent)
see:FireClient(plr)
end
end)
What this will do is bring up a ScreenGui for only that player so they can enter the PIN, and they can close it as well. You can modify as needed; have a great day! :D
There is an easier way, try this
First, Create a GUI in StarterGui, then, Create a textbox and postion it, after that, create a local script inside and type this.
local Password = math.random(1000, 9999)
print(Password)
game.ReplicatedStorage.Password.Value = Password
script.Parent.FocusLost:Connect(function(enter)
if enter then
if script.Parent.Text == tostring(Password) then
print("Correct!")
script.Parent.BorderColor3 = Color3.new(0, 255, 0)
Password = math.random(1000, 9999)
game.ReplicatedStorage.Correct1:FireServer()
print(Password)
game.ReplicatedStorage.Password.Value = Password
else
print("wrong!")
print(script.Parent.Text)
script.Parent.BorderColor3 = Color3.new(255, 0, 0)
end
end
end)
That's all in the textbox.
Or if you want a random username script, create a textlabel, then, create a local script in the textlabel and type in this.
local UserText = script.Parent
local Username = math.random(1,10)
while true do
if Username == 1 then
UserText.Text = "John"
elseif Username == 2 then
UserText.Text = "Thomas"
elseif Username == 3 then
UserText.Text = "Raymond"
elseif Username == 4 then
UserText.Text = "Ray"
elseif Username == 5 then
UserText.Text = "Tom"
elseif Username == 6 then
UserText.Text = "Kai"
elseif Username == 7 then
UserText.Text = "Lloyd"
elseif Username == 8 then
UserText.Text = "Jay"
elseif Username == 9 then
UserText.Text = "User"
else
UserText.Text = "Guest"
end
wait()
end
All of those if statments are checking what username has been chosen. I have made a roblox game like this recently, so I just took all the script from the game.
If you want to check out my game, Click Here
I am working on a larger project to write a code so the user can play Connect 4 against the computer. Right now, the user can choose whether or not to go first and the board is drawn. While truing to make sure that the user can only enter legal moves, I have run into a problem where my function legal_moves() takes 1 positional argument, and 0 are given, but I do not understand what I need to do to male everything agree.
#connect 4
#using my own formating
import random
#define global variables
X = "X"
O = "O"
EMPTY = "_"
TIE = "TIE"
NUM_ROWS = 6
NUM_COLS = 8
def display_instruct():
"""Display game instructions."""
print(
"""
Welcome to the second greatest intellectual challenge of all time: Connect4.
This will be a showdown between your human brain and my silicon processor.
You will make your move known by entering a column number, 1 - 7. Your move
(if that column isn't already filled) will move to the lowest available position.
Prepare yourself, human. May the Schwartz be with you! \n
"""
)
def ask_yes_no(question):
"""Ask a yes or no question."""
response = None
while response not in ("y", "n"):
response = input(question).lower()
return response
def ask_number(question,low,high):
"""Ask for a number within range."""
#using range in Python sense-i.e., to ask for
#a number between 1 and 7, call ask_number with low=1, high=8
low=1
high=NUM_COLS
response = None
while response not in range (low,high):
response=int(input(question))
return response
def pieces():
"""Determine if player or computer goes first."""
go_first = ask_yes_no("Do you require the first move? (y/n): ")
if go_first == "y":
print("\nThen take the first move. You will need it.")
human = X
computer = O
else:
print("\nYour bravery will be your undoing... I will go first.")
computer = X
human = O
return computer, human
def new_board():
board = []
for x in range (NUM_COLS):
board.append([" "]*NUM_ROWS)
return board
def display_board(board):
"""Display game board on screen."""
for r in range(NUM_ROWS):
print_row(board,r)
print("\n")
def print_row(board, num):
"""Print specified row from current board"""
this_row = board[num]
print("\n\t| ", this_row[num], "|", this_row[num], "|", this_row[num], "|", this_row[num], "|", this_row[num], "|", this_row[num], "|", this_row[num],"|")
print("\t", "|---|---|---|---|---|---|---|")
# everything works up to here!
def legal_moves(board):
"""Create list of column numbers where a player can drop piece"""
legals = []
if move < NUM_COLS: # make sure this is a legal column
for r in range(NUM_ROWS):
legals.append(board[move])
return legals #returns a list of legal columns
#in human_move function, move input must be in legal_moves list
print (legals)
def human_move(board,human):
"""Get human move"""
legals = legal_moves(board)
print("LEGALS:", legals)
move = None
while move not in legals:
move = ask_number("Which column will you move to? (1-7):", 1, NUM_COLS)
if move not in legals:
print("\nThat column is already full, nerdling. Choose another.\n")
print("Human moving to column", move)
return move #return the column number chosen by user
def get_move_row(turn,move):
move=ask_number("Which column would you like to drop a piece?")
for m in range (NUM_COLS):
place_piece(turn,move)
display_board()
def place_piece(turn,move):
if this_row[m[move]]==" ":
this_row.append[m[move]]=turn
display_instruct()
computer,human=pieces()
board=new_board()
display_board(board)
move= int(input("Move?"))
legal_moves()
print ("Human:", human, "\nComputer:", computer)
Right down the bottom of the script, you call:
move= int(input("Move?"))
legal_moves()
# ^ no arguments
This does not supply the necessary board argument, hence the error message.