I am using WorldToScreenPoint and GetPartsObscuringTarget. What I am trying to fix is that a player must detect parts of player on a different team. For example, there is a player on a team alone trying to find other players by detecting one of their humanoid parts. The script only detect parts inside the Workspace.
I've tried using Player.CharacterAdded:Wait() and a nested loop to go through players if they are on the same team or not. This didn't worked. I've been trying to fix this for the past 2 weeks.
local Player = game.Players.LocalPlayer
local Character = workspace:FindFirstChild(Player.Name)
game:GetService("RunService").Heartbeat:Connect(function()
for _, object in pairs(Character:GetDescendants()) do
if object:IsA("Part") or object:IsA("MeshPart") then
if not object:IsDescendantOf(game.Players.LocalPlayer.Character) then
local object2,visible = workspace.CurrentCamera:WorldToScreenPoint(object.Position)
if visible == true then
local pos1 = workspace.CurrentCamera.CFrame.Position
local pos2 = object.Position
local castPoints = {pos1,pos2}
local ignoreList = {game.Players.LocalPlayer.Character, object}
local obstructs = workspace.CurrentCamera:GetPartsObscuringTarget(castPoints,ignoreList)
if obstructs[1] then
return
elseif not obstructs[1] then
print(object.Name.." has been detected!")
end
elseif visible ~= true then
print("You are now incognito.")
return
end
end
end
end
end)
Related
Hello so today i just learn roblox studio to create a game. Im making a script where certain music will play if the player hit / enter the area and if the player leave the area music will also change. I tried to create the script but i got an error, the error is the background music does not stop and the elevator music does not play when player leave the part / area. Is there something wrong the code ?
local SoundService = game:GetService("SoundService")
local backgroundMusic = SoundService.BackgroundMusic
local elevatorMusic = SoundService.Elevator
local part = workspace.InsideBuilding
local musicPlayed = false
local CurrentArea = nil
elevatorMusic:Play()
part.Touched:Connect(function(hit)
local character = game.Players:playerFromCharacter(hit.Parent)
if character:IsA("Player") and character then
if part ~= CurrentArea then
CurrentArea = part
elevatorMusic:Stop()
if not backgroundMusic.IsPlaying then
backgroundMusic:Play()
end
elseif CurrentArea == nil then
backgroundMusic:Stop()
elevatorMusic:Play()
end
end
end)
The local part is the floor of the building.
You should Run the part when the music plays when the player touches the part:
also you did the touching mechanism wrong
local SoundService = game:GetService("SoundService")
local backgroundMusic = SoundService.BackgroundMusic
local elevatorMusic = SoundService.Elevator
local part = workspace.InsideBuilding
local musicPlayed = false
local CurrentArea = nil
part.Touched:Connect(function(hit)
if hit.parent:findfirstchild("Humaniod")
elevatorMusic:Play()
if part ~= CurrentArea then
CurrentArea = part
elevatorMusic:Stop()
if not backgroundMusic.IsPlaying then
backgroundMusic:Play()
end
elseif CurrentArea == nil then
backgroundMusic:Stop()
elevatorMusic:Play()
end
end
end)
hope this helped you
I am making a game where when a part at the front of a car touches another part, the other part becomes unanchored. I am making a different script that gives the player a coin every time they do this. Yes, I have already made a leaderstats script. code:
function onPartTouched(otherPart)
local characterModel = otherPart.Parent
local player = game.Players:GetPlayerFromCharacter(characterModel)
if player then
local coins = player.leaderstats.coins
coins.Value = coins.Value + 1
end
end
You do actually have to attach the function lol
function onPartTouched(otherPart)
local characterModel = otherPart.Parent
local player = game.Players:GetPlayerFromCharacter(characterModel)
if player then
local coins = player.leaderstats.coins
coins.Value = coins.Value + 1
end
end
MyPart.Touched:Connect(onPartTouched)
I'm trying to make a game in Roblox (a tycoon) and, considering it's my first time making a game, I'm using some pre-made scripts and models along with youtube tutorials. My problem right now is that I have two scripts, both under the same name, DevProductHandler, (I've tried changing their names but the problem still persists) and it seems like only one will run at a time whenever I test the game. Disabling one script allows the other to run perfectly fine, and enabling both causes only one script to work, randomly picking which one will run each time.
One of the scripts is meant to control purchasing products that are prompted from a GUI, and the other controls purchases prompted from tycoon buttons that you walk on top of. I've tried merging the scripts by copy-pasting one underneath the other, but it still only makes the GUI DevProductHandler script work. I don't know if there are some overlapping variables or something that would cause one script to not allow the other to run, but I think that's most likely the issue, although I'm not sure how to go about fixing that I'm new at Lua and game creation so I was wondering if anyone could help me find out the issue. These are the scripts.
local Tycoon = script.Parent.Tycoons:GetChildren()[1]
script.Parent = game.ServerScriptService
local DevProducts = {}
local MarketplaceService = game:GetService('MarketplaceService')
for i,v in pairs(Tycoon:WaitForChild('Buttons'):GetChildren()) do
if v:FindFirstChild('DevProduct') then
if v.DevProduct.Value > 0 then
DevProducts[v.DevProduct.Value] = v -- the button
end
end
end
MarketplaceService.ProcessReceipt = function(receiptInfo)
for i,plr in pairs(game.Players:GetPlayers()) do
if plr.userId == receiptInfo.PlayerId then
if DevProducts[receiptInfo.ProductId] then
local obj = DevProducts[receiptInfo.ProductId]
local PlrT = game.ServerStorage.PlayerMoney:WaitForChild(plr.Name).OwnsTycoon
if PlrT.Value ~= nil then
--if PlrT.Value.PurchasedObjects:FindFirstChild(obj.Object.Value) == false then
local PlayerStats = game.ServerStorage.PlayerMoney:FindFirstChild(plr.Name)
Create({[1] = 0,[2] = obj,[3] = PlayerStats}, PlrT.Value.BuyObject)
--end
end
end
end
end
end
function Create(tab, prnt)
local x = Instance.new('Model')
Instance.new('NumberValue',x).Value = tab[1]
x.Value.Name = "Cost"
Instance.new('ObjectValue',x).Value = tab[2]
x.Value.Name = "Button"
local Obj = Instance.new('ObjectValue',x)
Obj.Name = "Stats"
Obj.Value = tab[3]
x.Parent = prnt
end
Above is the script for prompts from walking over buttons.
old_fog = game.Lighting.FogStart
local MarketplaceService = game:GetService("MarketplaceService")
function getPlayerFromId(id)
for i,v in pairs(game.Players:GetChildren()) do
if v.userId == id then
return v
end
end
return nil
end
MarketplaceService.ProcessReceipt = function(receiptInfo)
local productId = receiptInfo.ProductId
local playerId = receiptInfo.PlayerId
local player = getPlayerFromId(playerId)
local productName
if productId == 1172271849 then
local cashmoney = game.ServerStorage.PlayerMoney:FindFirstChild(player.Name)
if cashmoney then
cashmoney.Value = cashmoney.Value + 10000
end
elseif productId == 1172270951 then
local cashmoney = game.ServerStorage.PlayerMoney:FindFirstChild(player.Name)
if cashmoney then
cashmoney.Value = cashmoney.Value + 100000
end
elseif productId == 1172270763 then
local cashmoney = game.ServerStorage.PlayerMoney:FindFirstChild(player.Name)
if cashmoney then
cashmoney.Value = cashmoney.Value + 1000000
end
elseif productId == 1172272327 then
local cashmoney = game.ServerStorage.PlayerMoney:FindFirstChild(player.Name)
if cashmoney then
cashmoney.Value = cashmoney.Value + cashmoney.Value
end
elseif productId == 1172273117 then
local char = player.Character
if char then
local human = char:FindFirstChild("Humanoid")
if human then
human.WalkSpeed = human.WalkSpeed + human.WalkSpeed
end
end
elseif productId == 1172273437 then
game.ServerStorage.HyperlaserGun:Clone().Parent=player.Backpack
elseif productId == 1172272691 then
game.ServerStorage.FlyingCarpet:Clone().Parent=player.Backpack
end
return Enum.ProductPurchaseDecision.PurchaseGranted
end
Above is the script for purchases from a GUI prompt.
From the Roblox manual:
As with all callbacks, this function should be set once and only once
by a single Script. If you're selling multiple products in your game,
this callback must handle receipts for all of them.
You're implementing game:GetService('MarketplaceService').ProcessReceipt in both scripts. One overwrite the other.
I am trying to make a maze/horror game. I used an online template in the Roblox library as my enemy. I used pathfinder as you will see in the code below. It's finding me like it's supposed to, except it only goes for my LAST position. As you can see in the image below, it completely skipped me, went to my LAST position, then started chasing me. I don't know why it only goes for my last position, and not my current position.
local PathFindingS = game:GetService("PathfindingService")
local humanoid = script.Parent:WaitForChild("Humanoid")
local rootPart = script.Parent:WaitForChild("HumanoidRootPart")
local Players = game:GetService("Players")
game.Workspace.Fruity.Humanoid.WalkSpeed = 60
--To calculate the path
while wait() do
for i, player in pairs(game.Players:GetPlayers()) do
local character = game.Workspace:WaitForChild(player.Name)
local characterPos = character.PrimaryPart.Position
local path = PathFindingS:CreatePath()
path:ComputeAsync(rootPart.Position, characterPos)
game.Workspace.Fruity.HumanoidRootPart:SetNetworkOwner(nil)
local waypoints = path:GetWaypoints()
for i, waypoint in pairs(waypoints) do
local part = Instance.new("Part")
part.Shape = "Ball"
part.Material = "Neon"
part.Size = Vector3.new(0.6,0.6,0.6)
part.Position = waypoint.Position + Vector3.new(0,2,0)
part.Anchored = true
part.CanCollide = false
part.Parent = game.Workspace
humanoid:MoveTo(waypoint.Position)
humanoid.MoveToFinished:Wait()
end
end
end
Your NPC's pathfinding updates when you call path:ComputeAsync(rootPart.Position, characterPos). The reason it is not updating more frequently is that you are blocking the start of the next loop with the last line : humanoid.MoveToFinished:Wait()
Your code is telling the NPC that it must walk to every single point between every single player, which could take minutes at a time, before ever calculating the path again.
The way to fix this is to make it so that the path can be recalculated quickly and asynchronously. To do this, try something like this :
local PathfindingService = game:GetService("PathfindingService")
local PlayerService = game:GetService("Players")
local humanoid = script.Parent:WaitForChild("Humanoid")
local rootPart = script.Parent:WaitForChild("HumanoidRootPart")
-- create a place where pathfinding orbs can be created and destroyed quickly
local shouldDebugPath = true
local OrbFolder = Instance.new("Folder", game.Workspace)
OrbFolder.Name = "Debug - Orbs"
local OrbTemplate = Instance.new("Part")
OrbTemplate.Shape = Enum.PartType.Ball
OrbTemplate.Material = Enum.Material.Neon
OrbTemplate.Size = Vector3.new(0.6,0.6,0.6)
OrbTemplate.Anchored = true
OrbTemplate.CanCollide = false
local function createWaypoint(position)
local orb = OrbTemplate:Clone()
orb.Position = position + Vector3.new(0,2,0)
orb.Parent = OrbFolder
return orb
end
-- set up some navigation variables and set up a chain
-- so that when the humanoid arrives at a waypoint,
-- it automatically selects the next point.
local currentOrbIndex = 0
local currentPath = {} -- store pathfinding waypoints here
local function moveToNextWaypoint(previousPointReached)
currentOrbIndex += 1
if currentOrbIndex > #currentPath then
return
end
local nextWaypoint = currentPath[currentOrbIndex]
humanoid:MoveTo(nextWaypoint.Position)
end
humanoid.MoveToFinished:Connect(moveToNextWaypoint)
-- calculate and continually update the path
local pauseLength = 1.0 --seconds (lower this number to speed up refresh rate)
while wait(pauseLength) do
-- find the closest player's character model
local targetCharacter = nil
local closestDist = math.huge
local playerList = PlayerService:GetPlayers()
for i, player in pairs(playerList) do
-- check that the player's character has spawned in
local character = player.Character
if not character then
continue
end
-- do some quick maths and select which player is closest
local p1 = character.PrimaryPart.Position
local p2 = rootPart.Position
local d = math.abs((p1 - p2).Magnitude)
if d < closestDist then
closestDist = d
targetCharacter = character
end
end
-- check that there are actually players in the server
if targetCharacter == nil then
continue
end
-- compute the path to the character
local characterPos = targetCharacter.PrimaryPart.Position
local path = PathfindingService:CreatePath()
path:ComputeAsync(rootPart.Position, characterPos)
local waypoints = path:GetWaypoints()
-- debug : show the path to the player
if shouldDebugPath then
OrbFolder:ClearAllChildren()
for i, waypoint in pairs(waypoints) do
local position = waypoint.Position
createWaypoint(position)
end
end
-- start the player walking towards the nearest player
currentOrbIndex = 0
currentPath = waypoints
moveToNextWaypoint()
end
This solution recalculates the path to the nearest player every 1 second. That path is stored as a series of waypoints and it uses the Humanoid.MoveToFinished signal as the trigger to move to the next known waypoint. Whenever the path is recalculated, we simply start the process over.
With this system, the loop isn't blocked and the distance and path to the different players can be regularly recalculated. This allows the NPC to dynamically switch targets towards the closest player too.
I am working on a game in which you can sail with boats. My script works but I wonder if I am doing it right?
What I'm trying to do is that as soon as you spawn a boot the name of the boot is the userID + the name of the ship.
This works fine thanks to one guy on this forum (Much Love)!
So now I wanted to write a script inside the seat as soon as another player or the player himself sits on the chair changes the name of the boat to that player name + boat name. This works, but now I have managed to get the name of the player and not his id. I prefer the ID of the player. How do you do that?
Because I get the player name instead of his id. I had to make another check to see if the boat does not already exist. Now 1 player can get 2 boats because player.Name and player.UserID do not match.
So my question is how do I get the userID instead of its name from the script below so that a player can take over the boat but not get 2 boats in the end?
I'm sorry for my bad coding i'm new to this :) Thanks for helping out!
Script inside of seat:
local Seat = script.Parent
local debounceCheck = false
local ChangeBoatName = script.Parent.Parent
local boatname = "ShipOnePerson"
Seat.Changed:Connect(function(player)
if Seat.Occupant ~= nil then
if Seat.Occupant.Parent.Name ~= "PlayerNameHere" then
local PlayerToNewBoat = game.Players:FindFirstChild(Seat.Occupant.Parent.Name)
local Character = PlayerToNewBoat.Character or PlayerToNewBoat.CharacterAdded:Wait()
if not debounceCheck then
-- Is it Occupant?
debounceCheck = true
-- Mark it as Occupant, so that other handlers don't execute
if ChangeBoatName then
local plruserid = Seat.Occupant.Parent.Name
local SetNameToBoat = plruserid..boatname
local NewBoat = ChangeBoatName
NewBoat.Name = SetNameToBoat
NewBoat.Parent = game.Workspace
print(NewBoat)
end
end
else
debounceCheck = false
-- Mark it as not Occupant, so other handlers can execute again
end
else
debounceCheck = false
-- Mark it as not Occupant, so other handlers can execute again
end
end)
My second question is how can I make sure that as soon as you press the button RegenButton it first checks if there is already a boat in that place and if so how do I make sure that you cannot spawn?
Below is the code that is in the button regenbutton
local cd = workspace.Regenbutton:WaitForChild('ClickDetector')
local boat = game:GetService('ServerStorage'):WaitForChild('ShipOnePerson')
local button = workspace:WaitForChild('Regenbutton')
local debounce = false
local boatname = "ShipOnePerson"
cd.MouseHoverEnter:Connect(function()
button.Transparency = 0.5
end)
cd.MouseHoverLeave:Connect(function()
button.Transparency = 0
end)
cd.MouseClick:Connect(function(player)
local plruserid = player.UserId
local SetNameToBoat = plruserid..boatname
local plrextraboat = player.Name..boatname
print(SetNameToBoat)
local oldboat = workspace:FindFirstChild(SetNameToBoat)
local oldboat2 = workspace:FindFirstChild(plrextraboat)
if not debounce then
if oldboat then
oldboat:destroy()
end
if oldboat2 then
oldboat2:destroy()
end
debounce = true
local NewBoat = boat:Clone()
NewBoat.Name = SetNameToBoat
NewBoat.Parent = game.Workspace
wait(5)
debounce = false
end
end)
So my question is how do I get the userID instead of its name
Instead of Player.Name use Player.UserId
My second question is how can I make sure that as soon as you press the button RegenButton it first checks if there is already a boat in that place and if so how do I make sure that you cannot spawn?
You could use Instance.GetChildren to get a list of all children, then iterate over that list in a loop. Check wether any of those children is a boat Instance.IsA and if so, check whether it is in the spawn location.