Code:
//if call @IfTextContains 2 mainTextPointer 3@ pieceToFindPointer 4@
:IfTextContains
{
0@ - the main text
1@ - piece of text to be found within the main text
}
0C18: 31@ = strstr string1 0@ string2 1@
if 31@ > 1
then
0485: return_true
else
059A: return_false
end
ret 0
Code:
{$CLEO .cs}
0000: NOP
// wait to make sure the samp chat is there
repeat
wait 50
until 0AFA: is_samp_structures_available
// prepare the data
alloc 0@ 100 // main text
format 0@ "Important message received: It's ok to be white."
alloc 1@ 100 // piece of text to check for
format 1@ "message received"
alloc 2@ 100 // piece of text that is deliberately different from the original
format 2@ "nussugu rucuuvud"
// use the actual function
if call @IfTextContains 2 mainTextPointer 0@ pieceToFindPointer 1@
then
chatmsg "'message received' was found within the provided text" -1
end
if call @IfTextContains 2 mainTextPointer 0@ pieceToFindPointer 2@
then
//nothing
else
chatmsg "'nussugu rucuuvud' was NOT found within the provided text" -1
end
// terminate this mod
end_thread
// the actual function which can be put anywhere at the end of the script (outside of any loops/labels/codeflow)
//if call @IfTextContains 2 mainTextPointer 3@ pieceToFindPointer 4@
:IfTextContains
{
0@ - the main text
1@ - piece of text to be found within the main text
}
0C18: 31@ = strstr string1 0@ string2 1@
if 31@ > 1
then
0485: return_true
else
059A: return_false
end
ret 0
Code:
if 0C18: 31@ = strstr mainTextPointer 0@ pieceToFindPointer 1@
then
chatmsg "Phrase was found within text. Pointer to it = %d" -1 31@
end
Neccessary part of the code which has to be put somewhere at the end of the script (not inside any loop):
Usage:
Example of a full code:
Code:
//if 0AB1: call_scm_func @IfTextContains 2 mainTextPointer 0@ pieceToFindPointer 1@ _returnedPointer 2@
:IfTextContains
{
0@ - the main text
1@ - piece of text to be found within the main text
}
0AB1: @StrLen 1 strPtr 0@ _length 31@
0AB1: @StrLen 1 strPtr 1@ _length 30@
//initial length check (the phrase can't be longer than the main text)
if 001D: 30@ > 31@ // (int)
then
059A: return_false
0AB2: ret 1 0
end
31@ -= 1
26@ = 0 // counter of the same chars in a row
for 29@ = 0 to 31@ // for each char of the main text (29@ = index)
0085: 24@ = 0@ // (int)
005A: 24@ += 29@ // (int)
0A8D: 28@ = read_memory 24@ size 1 virtual_protect 0
0085: 23@ = 1@ // (int)
005A: 23@ += 26@ // (int)
0A8D: 27@ = read_memory 23@ size 1 virtual_protect 0
if 003B: 28@ == 27@ // (int)
then
26@++
if 002D: 26@ >= 30@ // (int)
then
0485: return_true
0062: 24@ -= 30@ // (int)
24@ += 1
0AB2: ret 1 24@
end
else
if 26@ > 0
then
29@-- //check the same char again and assume it's the begining of the string but only if there was matching parts before (otherwise it would go back all the time and make infinite loop)
end
26@ = 0
end
end
059A: return_false
0AB2: ret 1 0
//0AB1: @StrLen 1 strPtr 0@ _length 31@
:StrLen
{
0@ - string pointer
}
30@ = 0
for 31@ = 0 to 100000
0A8D: 29@ = read_memory 0@ size 1 virtual_protect 0
if 29@ == 0
then
break
else
30@++
0@++
end
end
0AB2: ret 1 30@
Usage:
Code:
if 0AB1: call_scm_func @IfTextContains 2 mainTextPointer 0@ pieceToFindPointer 1@ _returnedPointer 2@
then
//2@ is the pointer to the substring
end
Example of a full code:
Code:
{$CLEO .cs}
0000: NOP
wait 20000
{
----------------------
PREPARATION
----------------------
}
0AC8: 0@ = allocate_memory_size 100
0AC8: 1@ = allocate_memory_size 100
0AD3: 0@ = format "Important message"
0AD3: 1@ = format "ant"
{
----------------------
USAGE
----------------------
}
if 0AB1: call_scm_func @IfTextContains 2 mainTextPointer 0@ pieceToFindPointer 1@ _returnedPointer 2@
then
0AD1: show_formatted_text_highpriority "Text ~G~contains ~W~the phrase. Pointer: %d" time 2000 2@
chatmsg 2@ -1
wait 2000
else
0AD1: show_formatted_text_highpriority "Text ~R~doesn't contain ~w~the phrase" time 2000
wait 2000
end
0A93: end_custom_thread
{
----------------------
FUNCTIONS
----------------------
}
//if 0AB1: call_scm_func @IfTextContains 2 mainTextPointer 0@ pieceToFindPointer 1@ _returnedPointer 2@
:IfTextContains
{
0@ - the main text
1@ - piece of text to be found within the main text
}
0AB1: @StrLen 1 strPtr 0@ _length 31@
0AB1: @StrLen 1 strPtr 1@ _length 30@
//initial length check (the phrase can't be longer than the main text)
if 001D: 30@ > 31@ // (int)
then
059A: return_false
0AB2: ret 1 0
end
31@ -= 1
26@ = 0 // counter of the same chars in a row
for 29@ = 0 to 31@ // for each char of the main text (29@ = index)
0085: 24@ = 0@ // (int)
005A: 24@ += 29@ // (int)
0A8D: 28@ = read_memory 24@ size 1 virtual_protect 0
0085: 23@ = 1@ // (int)
005A: 23@ += 26@ // (int)
0A8D: 27@ = read_memory 23@ size 1 virtual_protect 0
if 003B: 28@ == 27@ // (int)
then
26@++
if 002D: 26@ >= 30@ // (int)
then
0485: return_true
0062: 24@ -= 30@ // (int)
24@ += 1
0AB2: ret 1 24@
end
else
if 26@ > 0
then
29@-- //check the same char again and assume it's the begining of the string but only if there was matching parts before (otherwise it would go back all the time and make infinite loop)
end
26@ = 0
end
end
059A: return_false
0AB2: ret 1 0
//0AB1: @StrLen 1 strPtr 0@ _length 31@
:StrLen
{
0@ - string pointer
}
30@ = 0
for 31@ = 0 to 100000
0A8D: 29@ = read_memory 0@ size 1 virtual_protect 0
if 29@ == 0
then
break
else
30@++
0@++
end
end
0AB2: ret 1 30@