I want to do something with event listener in lua, this is for example :
function onTouch(event)
if(event.target.frame == 2) then
event.target:setFrame(1)
elseif(event.target.frame == 3) then
bar:setFrame(bar.frame + 1)
event.target:setFrame(1)
event.target:play()
end
end
those if-end will work when object is in touch, but how I want that thing work when frame change ? I try onFrameChange but there's nothing happened.
Thanks before, im newbie :D
You need the enterFrame listener
function printTimeSinceStart( event )
if(object.frame == 2) then
object:setFrame(1)
elseif(object.frame == 3) then
bar:setFrame(bar.frame + 1)
object:setFrame(1)
object:play()
end
end
Runtime:addEventListener("enterFrame", onEnterFrame)
Related
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'm practicing some basic coding, I'm running a simple math program running in the terminal on Visual Studio Code.
How do I create an option to return to the beginning of the program, or exit the program after getting caught in an if statement?
Example:
#beginning of program
user_input=input('Please select "this" or "that": ')
findings=user_input
If findings == this:
print(this)
# How can I redirect back to first user input question, instead
# of just ending here?
if findings == that:
print (that)
# Again, How do I redirect back to first user input, instead of
# the program ending here?
# Can I setup a Play_again here with options to return to user_input,
# or exit program? And then have all other If statements
# redirect here after completion? How would I do that? with
# another If? or with a for loop?
#end program
You can try wrapping the whole program in a while loop like this:
while(True):
user_input=input('Please select "this" or "that": ')
this = 'foo'
if user_input == this:
print(this)
continue
if user_input == this:
print(this)
continue
Unfortunately, that 'another technique' I thought of using didn't work.
Here's the code (the first example modified):
import sys
def main():
# Lots of setup code here.
def start_over():
return #Do nothing and continue from the next line
condition = 1==1 #Just a sample condition, replace it with "check(condition)".
float_condition = condition
def play(*just_define:bool):
if not just_define:
play_again = input('play again? "y" or "n"')
if play_again == 'y':
start_over() #Jump to the beginning of the prohram.
if play_again == 'n':
sys.exit() #Exit the program
while True:
if float_condition == True:
# print(float_condition)
play() #skip to play_again from here?
if float_condition == False:
#print(float_condition)
play() #skip to play_again from here?
#I removed the extra "main()" which was here because it'd cause an infinite loop-like error.
main()
Output:
play again? "y" or "n"y
play again? "y" or "n"n
Process finished with exit code 0
The * in the play(*just_define:bool) function makes the just_define parameter optional. Use the parameter if you want to only tell Python to search for this function, so it doesn't throw a ReferenceError and not execute anything that's after the line if not just_define:. How to call like so: play(just_define=True).
I've used nested functions. I've defined play so that you can call it from other places in your code.
Thanks to #Hack3r - I was finally able to choose to return back to the beginning of the program or exit out. But it resulted in a new issue. Now my print(results) are printing 4 or 5 times...
Here is the actual code I built and am working with:
def main():
math_Options=['Addition +','Subtraction -','Multiplication *','Division /']
math_func=['+','-','*','/']
for options in math_Options:
print(options)
print('Lets do some Math! What math function would you like to use? ')
while True:
my_Math_Function = input('Please make your choice from list above using the function symbol: ')
my_Number1=input('Please select your first number: ')
x=float(my_Number1)
print('Your 1st # is: ', x)
my_Number2=input('Please select your Second Number: ')
y=float(my_Number2)
print('Your 2nd # is: ', y)
z=float()
print('')
for Math_function in math_func:
if my_Math_Function == math_func[0]:
z=x+y
if my_Math_Function == math_func[1]:
z=x-y
if my_Math_Function == math_func[2]:
z=x*y
if my_Math_Function == math_func[3]:
z=x/y
if (z % 2) == 0 and z>0:
print(z, ' Is an EVEN POSITIVE Number')
if (z % 2) == 1 and z>0:
print(z, ' IS a ODD POSTIVE Number')
if (z % 2) == 0 and z<0:
print(z, ' Is an EVEN NEGATIVE Number')
if (z % 2) ==1 and z<0:
print(z, ' IS a ODD NEGATIVE Number')
if z==0:
print(z, 'Is is Equal to Zero')
print('')
play_again=input('Would you like to play again? "y" or "n" ')
if play_again == 'y':
continue
if play_again == 'n':
break
main()
main()
I come from a C#/Java background and have never touched Lua before.
I want the addon to show a message (default message window) that prints out the class of the target whenever I click on and target another player, and ONLY when I target a player. I have two files, SpeccySpecs.lua (contains the functions needed to handle the event) and SpeccySpecs.xml (contains the frame to run the function). Whenever I run the addon ingame, I am getting nil errors because my Core.lua file is returning nil when requiring the .xml file and my .xml file returns a nil from the OnTarget() function in SpeccySpecs.lua.
I have tried to solve this in multiple ways, one of which was by creating a local table and requiring it in Core.lua, where I'd eventually call the function inside the table, but it also returned nil. I've been using
sites such as:
https://wowpedia.fandom.com/wiki/Events
https://wowwiki-archive.fandom.com/wiki/Event_API
https://www.lua.org/
But what I've tried simply hasn't worked, and I assume I'm forgetting something small in the Lua code.
SpeccySpecs.lua
local function getPlayerClass()
local playerClassName = nil;
local playerClassFilename = nil;
local playerClassId = nil;
if UnitClass("target") ~= nil
then
playerClassName, playerClassFilename, playerClassId = UnitClass("target");
if playerClassName == 1 -- Warrior
then message ("It's a warrior")
elseif playerClassId == 2 -- Paladin
then message ("It's a paladin")
elseif playerClassId == 3 -- Hunter
then message ("It's a hunter")
elseif playerClassId == 4 -- Rogue
then message ("It's a rogue")
elseif playerClassId == 5 -- Priest
then message ("It's a priest")
elseif playerClassId == 6 -- Death Knight
then message ("It's a death knight")
elseif playerClassId == 7 -- Shaman
then message ("It's a shaman")
elseif playerClassId == 8 -- Mage
then message ("It's a mage")
elseif playerClassId == 9 -- Warlock
then message ("It's a warlock")
elseif playerClassId == 10 -- Monk
then message ("It's a monk")
elseif playerClassId == 11 -- Druid
then message ("It's a druid")
elseif playerClassId == 12 -- Demon Hunter
then message ("It's a demon hunter")
else message ("That class does not exist")
end
else message ("Please target a player")
end
end
function OnTarget(self, event, ...)
print(event)
return getPlayerClass()
end
SpeccySpecs.xml
<UI>
<Script file="SpeccySpecs.lua"/>
<Frame name="SpeccyFrame">
<Scripts>
<OnEvent function="OnTarget"/>
</Scripts>
</Frame>
</UI>
Core.lua
PlayerClassFrame = require "SpeccySpecs.xml";
return PlayerClassFrame
Thanks in advance for the help, everyone.
Goes like this:
make frame (yours is in xml) > OnLoad event handler > register for events > event fired > handle events
1) You don't need the require or the core.lua:
WoW has its own explicit ordered loading process that uses toc files and includes in xml.
Your toc file probably looks like:
# some stuff
MyAddon.xml
Then your MyAddon.xml loads:
<UI>
<Script file="MyAddon.lua"/>
<Frame name="MyAddonFrame">
Which then loads the .lua file first, so that all the things in the .lua file are available to be referenced as the frame xml loads.
2) You are missing registering for a specific event:
For example:
<OnLoad> self:RegisterEvent("PLAYER_ENTERING_WORLD") </OnLoad>
So that you end up with something like:
<OnLoad> self:RegisterEvent("PLAYER_ENTERING_WORLD") </OnLoad>
<OnEvent> print("Event name " .. event) </OnEvent>
You need to go find a specific event that deals with when something is targeted that comes as close as possible to fitting what you need.
3) You need to pass the telemetry from the event to the handler function:
<OnEvent> MyAddon:OnEvent(self, event, ...) </OnEvent>
The self is the current frame, event is given to you hind the scenes as OnEvent here just becomes compiled into a regular Lua function and gets event passed to it, and ... is a Lua type of list used for unnamed parameters, which you can break out into Lua variables later.
4) You need a repeatable way to expose your Lua code across files
This needs to be in a way that does not clash with WoW or other addons.
MyAddon = {}
Is one way. This makes a single Lua table with a global unique name that you can stick functions in so they can be found elsewhere outside that one file.
Anything in WoW that is not 'local' goes into a single environment Lua global name space across all addons and wow.
5) You need to accept the parameters for telemetry from the event:
And process the telemetry to eek out what you more specifically need
function MyAddon:OnEvent(frame, event, ...)
if event == "SOME_EVENT_NAME" then
local _, name = ...
if is this some player then
MyAddon:SomePlayerDidSomething(name)
end
elseif event == "SOME_EVENT_NAME" then
end
end
This should get you started for the basic addon process.
After all that is working, then you need a way to make the business end more data driven, which will in theory make it more code-size and speed efficient.
6) Add a table to lookup strings for ids:
MyAddon.classNames = {
[1] = "warrior",
[2] = "paladin",
[3] = "hunter",
}
See https://www.lua.org/pil/3.6.html
Which will allow you to construct code more like this:
local className = self.classNames[playerClassId]
if className then
message("It's a " .. className .. ".")
end
This should get you started overall. It's hard to find the right resource often to get you off the ground at the very beginning. You got pretty far.
You don't necessarily need an XML file, it can all be done in Lua. Also, require() does not exist in the WoW environment, that's handled by listing your files in the TOC
The page you linked has the PLAYER_TARGET_CHANGED event. You can check if a unit is player with UnitIsPlayer()
Your code would look something like this:
SpeccySpecs.toc
## Interface: 90105
## Version: 1.0.0
## Title: SpeccySpecs
## Notes: Some Description
## Author: YourName
SpeccySpecs.lua
SpeccySpecs.lua
local classes = {
[1] = "warrior",
[2] = "paladin",
[3] = "hunter",
[4] = "rogue",
[5] = "priest",
[6] = "death knight",
[7] = "shaman",
[8] = "mage",
[9] = "warlock",
[10] = "monk",
[11] = "druid",
[12] = "demon hunter",
}
local function getPlayerClass(unit)
if UnitExists(unit) then
local text
if UnitIsPlayer(unit) then
local _, _, classId = UnitClass(unit)
local name = classes[classId]
if name then
text = "It's a "..name
else
text = "That class does not exist"
end
else
text = "Please target a player"
end
message(text)
end
end
local function OnEvent(self, event)
getPlayerClass("target")
end
local f = CreateFrame("Frame")
f:RegisterEvent("PLAYER_TARGET_CHANGED")
f:SetScript("OnEvent", OnEvent)
Or as a minimal example:
local f = CreateFrame("Frame")
f:RegisterEvent("PLAYER_TARGET_CHANGED")
f:SetScript("OnEvent", function(self, event)
if UnitIsPlayer("target") then
print("It's a "..UnitClass("target"))
end
end)
i'm a bit beginner about coding, and my english isn't great, i hope i'll be able to make my question clear:
So I have a for-loop in my code, and 2 if in it, in each if, I see if something is true or false, if it's true, I delete a portion of the loop. like that:
for n=#Test,1, -1 do
if Test[n].delete == true then
table.remove(Test, n )
end
if Test[n].y > 0 then
table.remove(Test, n )
end
end
kind of like that, and my problem is, if the first if make Test[n] being deleted, then the game crash at the next if because Test[n] Doesn't exist anymore. I solved the problem by making 2 for-loop, one for each if.
But I saw someone who did it without 2 for-loop, and it's not crashing, I tried to figure what was wrong but I can't find it.
If someone could find what is wrong with what I wrote, I would be thankful!
So here is the moment that makes problem in my code, on line 9, if the condition are met, i table.remove(ListeTirs, n ), then on line 17, when code try to find it again for test it, it bug :
for n=#ListeTirs,1, -1 do
if ListeTirs[n].Type == "Gentils"
then local nAliens
for nAliens=#ListeAliens,1,-1 do
if
Collide(ListeTirs[n], ListeAliens[nAliens]) == true
then
ListeTirs[n].Supprime = true
table.remove(ListeTirs, n )
ListeAliens[nAliens].Supprime = true
table.remove(ListeAliens, nAliens)
end
end
end
if
ListeTirs[n].y < 0 - ListeTirs[n].HauteurMoitie or ListeTirs[n].y > Hauteur + ListeTirs[n].HauteurMoitie or ListeTirs[n].x > Largeur + ListeTirs[n].LargeurMoitie or ListeTirs[n].x < 0 - ListeTirs[n].LargeurMoitie
then
ListeTirs[n].Supprime = true
table.remove(ListeTirs, n)
end
end
I hope it's clear, I could post the whole code but I don't feel it's necessary, if it is, I will add it.
Thank you :)
for n=#Test,1, -1 do
local should_be_removed
-- just mark for deletion
if Test[n].delete = true then
should_be_removed = true
end
-- just mark for deletion
if Test[n].y > 0 then
should_be_removed = true
end
-- actually delete (at the very end of the loop body)
if should_be_removed then
table.remove(Test, n )
end
end
I have an if:
-12.times do |control|
-dia += 1
-if control == 1
%a#hoy{:href=>'/dias/algo'}<
-else
%a{:href=>'/dias/algo'}<
=dia
%span=dias[rand(7)]
The problem is I need =dia and span elements inside the anchor tag in both cases (true/false), and when I quit one identation it fails, because haml will end the if (which is also normal).
Is there any way to force end an if? I have tried it in many ways, but couldn't find the right way if it exist.
Thanks.
-12.times do |control|
-dia += 1
%a{:id => control == 1 ? "hoy" : "", :href=>'/dias/algo'}<
=dia
%span=dias[rand(7)]
Didn't test it but it should work ...