How do you call a script from another script in roblox studio - roblox

I was following a tutorial of AlvinBlox and came across not an error but it does not run something I wanted to happen.
Basically when the egg is clicked it need to hatch in a studio but it just prints the pet name and does not hatch the egg
This is the script where I need to code to call the script with the hatching mechanism:
local cost = 500
local petModule = require(game.ServerScriptService:WaitForChild("PetModule"))
script.Parent.ClickDetector.MouseClick:Connect(function(player)
if player.leaderstats.Cash.Value >= cost then
player.leaderstats.Cash.Value = player.leaderstats.Cash.Value - cost
local pet = petModule.chooseRandomPet()
print(pet.Name.." selected")
game.ReplicatedStorage.HatchEgg:FireClient(player)
end
end)
I was trying to hatch an egg but it doesn't hatch it.

You never passed the pet to the client.
game.ReplicatedStorage.HatchEgg:FireClient(player, pet)

Related

Passing information between two models WITHOUT the use of Levelspace or Hubnet

Is it possible to pass information between Netlogo models without using LevelSpace or Hubnet? I'm trying to output variables from one model and into a second model. The reason I don't want to use LevelSpace for this is because I'm using the xw (xtraWidget) extension as a frontend UI for my models and LevelSpace does not allow the xw extension to activate when models open. Hubnet is for LAN operations and these models will be on a server online.
Do all of the models involved use xw? If only one does, you could have the model be the LevelSpace parent.
If more than one does, probably the simplest way to do this is by communicating by writing to and reading from a file. The safest version of this is to have the sender wait for a file to not exist, open the file, write to it, and closes the file. The receiver, similarly, waits for the file to exist, opens the file, reads from it, then closes the file and deletes it, indicating to the sender that it has finished reading. This should avoid most weird timing issues and, for instance, Windows locking open files and the like, but it does require the two models stay in lock step, as they will block on sending and receiving. This would look like so:
Sender:
to send-data [ filename data ]
while [ file-exists? filename ] [] ; Could add a `wait` so this doesn't eat as much cpu while waiting
file-open filename
file-write data
file-close
end
Receiver:
to-report receive-data [ filename ]
while [ not file-exists? filename ] [] ; Could also add a `wait` here
file-open "filename"
let data file-read
file-close
file-delete filename
report data
end
Example usage:
Sender:
observer> send-data "foo" 123 send-data "foo" 456
Receiver:
observer> show receive-data "foo" show receive-data "foo"
observer: 123
observer: 456
Another way to do this (and probably much better) would be to use the Python extension to perform inter-process communication via the multiprocessing library. If you're interested in this method, add a comment, and I can write up some example code. Here are the related docs to get you started: https://docs.python.org/3/library/multiprocessing.html#using-a-remote-manager
Update with Python solution:
The idea here is to start a multiprocessing server that the models then connect to. One model will start the server, then both models will create clients that connect to that server. They will then pass data via a queue in that server.
First, we setup python and import the libraries we care about. This will be run on both models.
to setup-python
py:setup py:python3
(py:run
"from multiprocessing.managers import BaseManager"
"from multiprocessing import Process"
"from queue import Queue")
end
We start the server (in just one of the models) like so:
to start-server
(py:run
"def start_server():"
" class QueueManager(BaseManager): pass"
" queue = Queue()"
" QueueManager.register('get_queue', callable=lambda:queue)"
" m = QueueManager(address=('', 50000), authkey=b'turtles')"
" s = m.get_server()"
" s.serve_forever()"
"proc = Process(target=start_server) "
"proc.start()")
end
We then start the client in both models like so:
to start-client
(py:run
"class QueueManager(BaseManager): pass"
"QueueManager.register('get_queue')"
"m = QueueManager(address=('', 50000), authkey=b'turtles')"
"m.connect()"
"queue = m.get_queue()")
end
We can then send and receive data with the following:
to send-data [ data ]
py:set "data" data
(py:run "queue.put(data)")
end
to-report receive-data
report (py:runresult "queue.get(block=False)")
end
Note that I set receive-data to not wait for data; it will just error if there's no data waiting. If you do block, it's pretty easy to freeze NetLogo (and then you have to go and kill the underlying python process manually). You'll probably want to adjust that behavior. See https://docs.python.org/3/library/queue.html#queue.Queue.get for various options, or just throw a carefully around the whole thing and report a default value when you get an error.
Putting it all together, on one model we have something like:
observer> setup-python
observer> start-server
observer> start-client
observer> send-data 123
observer> send-data 456
and in the other model we have:
observer> setup-python
observer> start-client
observer> show receive-data
observer: 123
observer> show receive-data
observer: 456
A few notes:
start-client and start-server should be run exactly once after setup-python. If you want to call them again, you need to call setup-python again to shutdown the python process. You might get something like [Errno 98] Address already in use when restarting a client after restarting the server; just wait a sec for the old server to die and try again.
If you want to send and receive data in both directions, I recommend adding an additional queue. While a queue is bidirectional here, you might have the senders eating their own messages if you try to reuse it.
Be prepared to manually kill the python process if NetLogo locks up. It's supposed respect halt (and does sometimes), but not always.
Hope that helps!

is it possible to copy the current state of the statechart from one agent to another?

I am trying to make a model to simulate the contagion of covid in public spaces using a mix between SEIR and pedestrian models.
In another question I asked to use a static population. They suggested that before deleting the agent a copy be saved in a list and after the first X agents have been generated I want the next agent generated by the pedSource to be one of the list.
Currently what I do is take a random agent from the list and if it is infected I send a message to the new agent so that it goes into the infected state. But by doing that I am resetting the timeout to recover every time an agent enters the zone that I am modeling.
this is the code that currently runs in the pedSource on exit:
if (personasEnCasa.size()+personasEnSuper.size() > poblacionMaxima){
Persona p = randomFrom(personasEnCasa);
if (p.statechart.getState() == Persona.Infeccioso){
send("Contagiado", ped);
};
personasEnCasa.remove(p);
};
personasEnSuper is my population of Persona, personasEnCasa is my list of agents outside the zone and and poblacionMaxima is the maximum number of agents in the lista and the population
I would like to be able to copy the current statechart of the agent in the list to the agent that generates my pedSource. Or use something similar to a pedSource.inject () but inserting an agent from the list instead of a new one. But I did not know how to do it.
is there any way to do this?
your ped already exists and you don't need to copy it you can just move it to the flow like this, with pedWait being any pedestrian block that you want, so instead of send("Contagiado", ped); you would do enter.take(ped);
but if you insist in using the send, then you can use branches on your statechart to define where this ped goes:
you will need in this case before the send, use ped.infectious=true; and the condition in the branch would be infectious==true to move to the infectious state.
As a side note, instead of p.statechart.getState() == Persona.Infeccioso you should use p.statechart.getState().equals(Persona.Infeccioso)
use == only with primitives such as boolean, int and double, otherwise you are susceptible to errors that are very difficult to discover

difficult to find the current location of agents in Anylogic simulation

i built a simple model for pedestrian movement from start line towards target line, I want to find the number of moving agents in some area using the XY-coordinates (from X=150 to X=350, Y is the same )
The action for the event is to get the count of agents in that area and set the value for the variable crowd1:
crowd1=count(agents(), p-> p.getX()>150 && p.getX()<350)
the problem is that it's always 0 , even though the gents are moving in the simulation.
There are no agents in your environment because you haven't created any agent type... For your code to work you need to have a population of pedestrians registered in your environment (meaning that you have to create the agent type and add it to main as a populatin), and then you have to add to a custom population the agents created in pedSource...
Otherwise, you can use this code:
count(pedGoTo.getPeds(),p->p.getX()>150 && p.getX()<350)

Discrete Event Scheduling in NetLogo: Executing some command on some specific tick

My code has one condition:
if ticks = 10^7 [ do-something ]
Now this condition is checked on every ticks though I know exactly when I have to execute the command. This might be slowing my code. The time extension does exactly this by time:go command. My command using time extension is:
time:schedule-event patches task do-something 1000000
But this throwing an error:
Extension exception: Attempted to schedule an event for tick 999999.0 which is before the present 'moment' of 1000000.0
error while observer running TIME:SCHEDULE-EVENT
called by procedure GO
called by Button 'go'
Is there something I am missing? Or any other efficient way to schedule some event at specific tick without checking the ticks condition every tick?
If this looks like a bug in the time extension, please post it at https://github.com/colinsheppard/time/issues
and tell us where we can find your code. (Or email it to me.)

Managing Place Instances in Roblox

So, apparently Roblox now has a way to Teleport players between places.
That's great, but for the game I have in mind I need to have very fine-grained control over which players are let into which servers (or as Roblox seems to call them, "place instances"). How can I explicitly teleport a player or group of players to a new place instance with no other players in it?
You can find the relevant article on the wiki here
Here is an example code:
local AssetService = Game:GetService(“AssetService”)
local TeleportService = Game:GetService("TeleportService")
local NewPlaceName = "New place #: " .. math.random() * 100
local NewPlaceId = AssetService:CreatePlaceAsync(NewPlaceName , [ID of template] )
for i,Player in ipairs(Game.Players:GetPlayers()) do
TeleportService:Teleport(NewPlaceId , Player)
end
The code will make a new instance from an template with the id [ID of template] and then send all players in the current game to that instance.
You can get more control by using the DataStore (as seen in example)
Try making a Reserve Server. Reserve servers are generated to lock players out and hide the server, players can only join the server when the script you have made teleported them to the place it is running with the code it generated.
https://developer.roblox.com/api-reference/function/TeleportService/ReserveServer