I want it to loop only once - loops

I have a problem with looping. I want it to loop only once, but it prints constantly. If I do return, the script will stop, i don't want that, because i would have to restart server always the script would be triggered. Any idea how to solve this problem?
local hit = GetPedLastDamageBone(ped)
local chance = math.random(0,10)
local ped = PlayerPedId()
while true do
Wait(0)
if GetEntityHealth(ped) > 0 then
if DMGByWeapon then
if hit == 45454 or 33646 then
print("Foot")
end
end
end
end

I want it to loop only once
The whole purpose of a loop is to execute a block of code multiple times.
So if you only want to loop once, you don't need a loop. Just remove the loop from your code.
local hit = GetPedLastDamageBone(ped)
local chance = math.random(0,10)
local ped = PlayerPedId()
Wait(0)
if GetEntityHealth(ped) > 0 then
if DMGByWeapon then
if hit == 45454 or 33646 then
print("Foot")
end
end
end
but it prints constantly.
while true do end
is an infinite loop. The condition is always true and will never change so the loop will run forever.
If I do return, the script will stop
Your script file is compiled as a chunk. Chunks are treated as the body of an anonymous function. return will terminate that function and hence your script unless you use it inside a function definiton in that chunk.
If you want to stop a loop prematurely use break
Please read the Lua manual and do a beginners tutorial.
if hit == 45454 or 33646 then
print("Foot")
end
Is eqivalent to
if hit == 45454 or true then
print("Foot")
end
which simplifies to
if true then
print("Foot")
end
or simply
print("Foot")
Any value that is neither nil nor false is true
So 33646 is logically true. oring anything with true yields true
An if statement with a condition that is always met is pointless.
Instead of nesting several if statements you can simply combine the conditions using logical operators.
So instead of
if GetEntityHealth(ped) > 0 then
if DMGByWeapon then
if hit == 45454 or 33646 then
print("Foot")
end
end
end
You could write
if GetEntityHealth(ped) > 0 and DMGByWeapon then
print("Foot")
end
But if you really want to use that if statement you need to fix the condition:
if hit == 45454 or hit == 33646 then
print("Foot")
end

Related

Dealing with errors while parsing strings

I'm tasked with pulling relevent data out of a field which is essentially free text. I have been able to get the information I need 98% of the time by looking for keywords and using CASE statements to break the field down into 5 different fields.
My issue is I can't get around the last 2% because the errors don't follow any logical order - they are mostly misspellings.
I could bypass the field with a TRY CATCH, but I don't like giving up 4 good pieces of data when the routine is choking on one.
Is there any way to handle blanket errors within a CASE statement, or is there another option?
Current code, the 'b' with the commented out section is where it's choking right now:
CASE WHEN #Location = 0 THEN
CASE WHEN #Duration = 0 THEN
CASE WHEN #Timing = 0 THEN
SUBSTRING(#Comment,#Begin, #Context-#Begin)
ELSE
SUBSTRING(#Comment,#Begin, #Timing-#Begin)
END
ELSE SUBSTRING(#Comment,#Begin, #Duration-#Begin)
END
ELSE SUBSTRING(#Comment,#Begin, #Location-#Begin)
END AS Complaint
,CASE WHEN #Location = 0 THEN ''
ELSE
CASE WHEN #Duration = 0 THEN
CASE WHEN #Timing = 0 THEN SUBSTRING(#Comment,#Location+10, (#CntBegin-11))
ELSE SUBSTRING(#Comment,#Location+10, #Timing-(#Location+10))
END
ELSE SUBSTRING(#Comment,#Location+10, #Duration-(#Location+10))
END
END AS Location
,CASE WHEN #Timing = 0 THEN ''
ELSE
CASE WHEN #CntBegin = 0 THEN
SUBSTRING(#Comment,#Timing+#TimingEnd, (#Location+#Context)-(#Timing+#TimingEnd))
ELSE
'b'--SUBSTRING(#Comment,#Timing+#TimingEnd, (#Location+#CntBegin-1)-(#Timing+#TimingEnd))
END
END AS Timing
On this statement, which has a comma in an odd spot. I have to reference the comma usually for the #CntBegin, but in this case it's making my (#Location+#CntBegin-1) shorter then the (#Timing+#TimingEnd):
'Pt also presents with/for mild check MGP/MGD located in OU, since 12/2015 ? Stability.'
Please take into account, I'm not necessarily trying to fix this error, I'm looking for a way to handle any error that comes up as who knows what someone is going to type. I'd like to just display 'ERR' in that particular field when the code runs into something it can't handle. I just don't want the routine to die.
Assuming your error is due to the length parameter in SUBSTRING being less than 0. I always alias my parameters using CROSS APPLY and then validate the input before calling SUBSTRING(). Something like this should work:
SELECT
CASE WHEN CA.StringLen > 0 /*Ensure valid length*/
THEN SUBSTRING(#comment,#Timing+#TimingEnd,CA.StringLen)
ELSE 'Error'
END
FROM YourTable
CROSS APPLY (SELECT StringLen = (#Location+#CntBegin-1)-(#Timing+#TimingEnd)) AS CA

Logitech Lua Scripting and Looping

I'm having a little problem with my script here using a Logitech mouse. I will be using it for farming in a game.
function OnEvent(event, arg)
if event == "MOUSE_BUTTON_PRESSED" and arg == 5 then
for i = 0, 300 do
PressAndReleaseKey("f9")
Sleep(400)
PressAndReleaseKey("enter")
Sleep(600)
PressAndReleaseKey("f5")
Sleep(50)
PressMouseButton(1)
Sleep(50)
ReleaseMouseButton(1)
end
PressAndReleaseKey("1")
repeat
until IsMouseButtonPressed(3)
end
end
So it will loop for 300 times and then press 1 when it's done, then repeat the loop again for 300 times, so on & so on. Problem I'm facing is, when I'm trying to abort the script, it will first finish the for-loop before being stopped by using Right-click button(IsMouseButtonPressed(3)), which is really hard to time (300x is a lot)
How can I pause/stop it during the for-loop, would it be possible?
Frequently check if the button is pressed and break the loop.
Break up those long blocking Sleeps.
Instead of Sleep(400) consider doing something like
for i = 1, 400, 50 do
Sleep(50)
if IsMouseButtonPressed(3) then break end
end
You can use break to jump out of your for loop when IsMouseButtonPressed(3)
for i = 0, 300 do
if IsMouseButtonPressed(3) then
break -- exit for loop.
end
PressAndReleaseKey("f9")
Sleep(400)
PressAndReleaseKey("enter")
Sleep(600)
PressAndReleaseKey("f5")
Sleep(50)
PressMouseButton(1)
Sleep(50)
ReleaseMouseButton(1)
end
doing it like this means you can expect a maximum delay of 1.1 seconds due to the sleep calls, for the exit to be registered.
You could change your code by adding a function to poll IsMouseButtonPressed(3) during your sleep intervals.
local function MousePollingSleep(time)
loopCount = time / 50
for i = loopCount, 0, -1 do
if IsMouseButtonPressed(3) then
return false
end
sleepTime = (i >= 1 and 1 or i) * 50
Sleep(sleepTime)
end
return true
end
and change your for loop to
function OnEvent(event, arg)
if event == "MOUSE_BUTTON_PRESSED" and arg == 5 then
repeat
for i = 0, 300 do
PressAndReleaseKey("f9")
if MousePollingSleep(400) == false then break end
PressAndReleaseKey("enter")
if MousePollingSleep(600) == false then break end
PressAndReleaseKey("f5")
if MousePollingSleep(50) == false then break end
PressMouseButton(1)
if MousePollingSleep(50) == false then break end
ReleaseMouseButton(1)
end
ReleaseMouseButton(1)
PressAndReleaseKey("1")
until IsMouseButtonPressed(3)
end
end

Opensips avp_db_query can't compare null value

I am using avp_db_query to retrieve my table row, sometimes one field value is null. But when I use if condition it does not follow and move on.
avp_db_query("select status from orders where id = 1", "$avp(status);")
Now if i write condition
if($avp(status)==1){
do success
} else {
do failure
exit();
}
Above condition does not work on failure status and continue, but when I put two if conditions and check if it is equal to one or equal to 0 then it works.
another issue is if this column has null value than nothing work, and it proceeds with giving the following warning.
WARNING:core:comp_scriptvar: invalid EQUAL operation: left is
VARIABLE_ELEMENT/STRING_VAL, right is NUMBER/NO_VAL
You can test for NULL SQL column values with:
if ($avp(status) == "<null>")
... which is equivalent to:
if ($(avp(status)[0]) == "<null>")
It was the only way we could get this to work, given that the $avp(status) = NULL; statement is meant to delete the top-most value in the AVP's stack.
If you are claiming that the else statement is not executed when it should be, please give a minimally viable example, along with the output of opensips -V, possibly opening up a new issue, separately.

Concatenation operator in System verilog in a loop

I am trying to do the following : concat = {concat[7:0],clk} inside a forever loop as below :
bit [7:0] concat;
concat = 0;
forever begin
#(posedge clk);
concat = {concat[7:0],clk};
end
I wanted to know what value will it contain after 8 clock iterations at any point of time, if the initial value of concat = 0.
Can it be different from 'hAA or 'h55 at any point of time?
You can not just write concat = 0; you should either assign concat = 0; or
initial begin
concat = 0;
end
Forever can not be used like that, the only two top levels you're allowed are initial and always. You want some thing like the following for a simulation:
initial begin
forever begin
#(posedge clk);
concat = {concat[6:0],clk};
end
end
If you are writing for synthesis then you might want to imply a flip-flop:
always #(posedge clk) begin
concat = {concat[6:0],clk};
end
Once you have fixed your RTL it should be easy to try out on EDA Playground.
Since you have #(posdege clk), clk will always be 1 (or x) when evaluating the RHS of the assignment. So concat will be 'h00, 'h01, 'h03, 'h07, 'h17, ...
Also note that if any other thread tries to read concat on the same positive edge of clk, you have a race condition, so please use a NBA to make the assignment.

Case insensitive array in Lua

I'm trying to program an addon for WoW (in lua). It's a chat filter based on specific words. I can't figure out how to get the array of these words to be case insensitive, so that any upper/lower case combination of the word matches the array. Any ideas would be greatly appreciated. Thanks!
local function wordFilter(self,event,msg)
local keyWords = {"word","test","blah","here","code","woot"}
local matchCount = 0;
for _, word in ipairs(keyWords) do
if (string.match(msg, word,)) then
matchCount = matchCount + 1;
end
end
if (matchCount > 1) then
return false;
else
return true;
end
end
Use if msg:lower():find ( word:lower() , 1 , true ) then
==> it lower cases both of the arguments to string.find: hence case insensitivity.
Also I used string.find because you probably want the 'plain' option, which doesn't exist for string.match.
Also you can easily return on the first word found:
for _ , keyword in ipairs(keywords) do
if msg:lower():find( keyword:lower(), 1, true ) then return true end
end
return false
Define keyWords outside of function. Otherwise you're recreating
table every time just to thorw it away moments latter, wasting time
on both creation and GC.
Convert keyWords to patter that match
both upper and lower case letters.
You don't need captured data
from string, so use string.find for speed.
According to your
logic, if you've got more than one match you signal 'false'. Since
you need only 1 match, you don't need to count them. Just return
false as soon as you hit it. Saves you time for checking all
remaining words too. If later you decide you want more than one
match, you still better check it inside loop and return as soon as
you've reached desired count.
Don't use ipairs. It's slower than simple for loop from 1 to array length and ipairs is deprecated in Lua 5.2 anyway.
local keyWords = {"word","test","blah","here","code","woot"}
local caselessKeyWordsPatterns = {}
local function letter_to_pattern(c)
return string.format("[%s%s]", string.lower(c), string.upper(c))
end
for idx = 1, #keyWords do
caselessKeyWordsPatterns[idx] = string.gsub(keyWords[idx], "%a", letter_to_pattern)
end
local function wordFilter(self, event, msg)
for idx = 1, #caselessKeyWordsPatterns do
if (string.find(msg, caselessKeyWordsPatterns[idx])) then
return false
end
end
return true
end
local _
print(wordFilter(_, _, 'omg wtf lol'))
print(wordFilter(_, _, 'word man'))
print(wordFilter(_, _, 'this is a tEsT'))
print(wordFilter(_, _, 'BlAh bLAH Blah'))
print(wordFilter(_, _, 'let me go'))
Result is:
true
false
false
false
true
You can also arrange this with metatables, in an entirely transparent way:
mt={__newindex=function(t,k,v)
if type(k)~='string' then
error'this table only takes string keys'
else
rawset(t,k:lower(),v)
end
end,
__index=function(t,k)
if type(k)~='string' then
error'this table only takes string keys'
else
return rawget(t,k:lower())
end
end}
keywords=setmetatable({},mt)
for idx,word in pairs{"word","test","blah","here","code","woot"} do
keywords[word]=idx;
end
for idx,word in ipairs{"Foo","HERE",'WooT'} do
local res=keywords[word]
if res then
print(("%s at index %d in given array matches index %d in keywords"):format(word,idx,keywords[word] or 0))
else
print(word.." not found in keywords")
end
end
This way the table can be indexed in whatever case. If you add new words to it, it will automatically lower-case them too. You can even adjust it to allow matching with patterns or whatever you'd like.

Resources