-
Content Count
363 -
Joined
-
Days Won
46
Posts posted by meko
-
-
Handling of item storage has been split into a separate packet, but while this fixed a bug, it introduced a race condition, which when exploited allows to duplicate items.
A new patch has been issued and the exploit is no longer reproducible. If you are using a version between e8affc4 and f30edc7 (inclusive) make sure you update ASAP to d2af893 (stable) or later version and compile it.
Affected versions, from oldest to most recent:
- e8affc41f106503b530abaa7faa20d6e63b727b8
- d966a8e6860d418bb3a235e57928436127eba555
- cb3e2f5f3b91d0a1f7711eff9c10ae9a655a74f2
- 50848cc7f79aa516351e4a4d673df53f4881eb4d
- 5383a14853327c123cbb037d3680aaa3d8c3e724
- 8c5b8ac7d87d8d4dc49d3ff1768f8884a0d75d72
- 7c6673e13fdd75a4137a9d7ef94e04d96e053422
- d90e8ce0d8ba8677567a5a5adebb62ba97e8a0b3
- b950a589e59e2bf074f67c75aaacf3f82424d4fe
- 4b208e41d1d5cc995c2816e8f34c1ad8b0a7327d
- 47a1e679cd35dc2e524fbeb31891d85e497821ce
- f30edc7f02fb0c290d302d9abc77d970bb05fb62
To know which version you are on:
- start Hercules (login server, char server or map server)
- it will say something like the following:
[Info]: Git revision (src): 'e6ab2a9ec6f5be8927eeca667ff477086f5e2e8e'
If any other issue is found, this post will be updated.
Want to receive email notifications about important issues in the future?
Go to Repository News and hit the follow button
Need help updating to a newer version?
You can get free support in the #Hercules channel of the Rizon network.
-
Another race condition has been found and patched. If you are using a version between e8affc4 and f30edc7 make sure you update ASAP to d2af893 or later version
See http://herc.ws/board/topic/14837-race-condition-in-char-server-please-update/
-
I would need to have a look at your script then
-
skill(<skill id>, <level>{, <flag>})
For <flag> make sure you put 0
Example:
skill(TF_THROWSTONE, 1, 0);
-
Bots will always be there no matter what you do; even if you manually do botchecks
Let's say I am a bot user, even if your questions are unpredictable and change every single time, nothing prevents me from creating a remote-controlled bot. I could set up a bot that automatically farms and whenever a botcheck is performed the bot would stop completely and send me a text message. I would then remotely answer the botcheck question and the bot would resume operation and you would have no way to differentiate this from a normal player.
Plus, botchecking only ends up annoying legitimate users: not everybody is good at math, or has good eyesight to solve captchas
-
-
Very nice, haven't updated my herc files in a while, glad to see some awesome changes. Thanks for the summary.
I concur. Last updated Herc October 2016, seems there's tons of new stuff since then. In the process of getting up to speed.
I suggest stay on your version updated one seems very unstable.
Actually there was an issue with item cloning; but this was resolved
-
if you absolutely refuse to use git at all then the only way is to download a zip file (highly not recommended, because you loose the history)
else, see http://herc.ws/board/topic/14830-updating-hercules-git-pull-problem/#entry82925
if you don't want to use the command-line interface I recommend Github Desktop instead of TortoiseGIT
If you encounter a problem I can give step-by-step instructions on IRC: #Hercules @ Rizon
make sure to say "meko" in the channel so I get notified
-
So the bot killer asks to solve math equations? that's... actually the thing bots are best at
-
It seems you did not hear my advise and learn the basics of git;
The reason you cannot pull is because you do not have a git environment: you downloaded a zip instead of cloning.
Do the following:
- Delete the folder you unzipped to (it's likely too messy by now)
- Create a github account
- Make note of your github username
- Log in to your github account
- Go to https://github.com/HerculesWS/Hercules and click the Fork button
- Open an ssh connection to your VPS and use the following commands one by one:
git clone --origin upstream git://github.com/HerculesWS/Hercules.git git config --global url."https://".pushinsteadOf git:// cd Hercules git remote add origin git://github.com/<your github username>/Hercules.git git fetch --all
- Now that you have a clean environment set up, build Hercules from this Hercules directory
And thereafter, whenever you want to update:
- Connect through ssh to your vps:
cd Hercules git pull upstream master
- ... and then build again
PS- forking is usually not necessary if you just want to run a vanilla server, but if you ever want to make modifications you'll have this fork ready
PS2- I noticed you are logged in to your VPS as root; running a publicly accessible server (ie Hercules) from a superuser account is very bad practice, as if any vulnerability is found the attacker would gain FULL ACCESS to your VPS
-
If all you want is get the location then getmapxy() works just fine, no need to use more "advanced" commands such as getunitdata
-
Why not just disable the skills that cause those status instead of disabling the status themselves? And you can easily remove them when the player enters the map with OnPCLoadMapEvent
-
your .@x and .@y do not get the right data because you call getunitdata() improperly: you have to specify the data type, which would be UDT_MAPIDXY in your case
see https://github.com/HerculesWS/Hercules/blob/master/doc/script_commands.txt#L9636
-
This is because 32767 (0x7FFF) is the maximum value of a signed 16-bit integer, but clients after 20071113 do support 32-bit integers for the damage packet
-
-
Si utiliser la console est trop ardu, je te conseille HeidiSQL (100% gratuit)
Tu peux importer tes fichiers .sql une fois connecté
-
Array manipulation functions
This script provides various array manipulation functions, and more might be added in the future.
All of those functions (except the arithmetic ones) work with both integer and string arrays.The start of the array is always implicitly index 0, unless an index is specified, ie @array[index]
array_pad(<array>, <size>, <value>)
pads the array left or right with <value> until it reaches <size> size. If <size> is negative it will pad left.
> returns the number of added entriessetarray(.@foo, 1, 2, 3, 4, 5); // initialize the array array_pad(.@foo, 8, 69); // => 3 // array is now: 1, 2, 3, 4, 5, 69, 69, 69
setarray(.@foo, 1, 2, 3, 4, 5); // initialize the array array_pad(.@foo, -8, 69); // => 3 // array is now: 69, 69, 69, 1, 2, 3, 4, 5
array_replace(<array>, <needle>, <replacement>{, <neq>})
finds every occurrence of <needle> within the array and replaces it with <replacement>. if <neq> is true, finds entries that do not match instead
> returns the number of changed entriessetarray(.@foo, 1, 1, 3, 1, 5); // initialize the array array_replace(.@foo, 1, 69); // => 3 // array is now: 69, 69, 3, 69, 5
array_find(<array>, <needle>{, <neq>})
finds the first occurrence of <needle> within the array. if <neq> is true, finds entries that do not match instead
> returns the index, or if none is found returns -1setarray(.@foo, 1, 2, 3, 4, 5); // initialize the array array_find(.@foo, 3); // => 2 array_find(.@foo, 1); // => 0 array_find(.@foo, 6); // => -1
array_rfind(<array>, <needle>{, <neq>})
like array_find, but finds the last occurrence. if <neq> is true, finds entries that do not match instead
> returns the index, or if none is found returns -1setarray(.@foo, 1, 2, 3, 4, 3); // initialize the array array_rfind(.@foo, 3); // => 4 array_rfind(.@foo, 4); // => 3 array_rfind(.@foo, 6); // => -1
array_exists(<array>, <needle>{, <neq>})
very similar to array_find() but it instead just checks if it exists or not. if <neq> is true, finds entries that do not match instead> returns true or falsesetarray(.@foo, 1, 2, 3, 4, 5); // initialize the array array_exists(.@foo, 3); // => true array_exists(.@foo, 6); // => false
array_count(<array>, <needle>{, <neq>})
similar to array_find() but iterates through the whole array. if <neq> is true, finds entries that do not match instead
> returns the total number of occurrences of <needle>setarray(.@foo, 1, 69, 3, 69, 5); // initialize the array array_count(.@foo, 69); // => 2
array_entries(<array>)
a wrapper around array_count(). behaves similarly to getaraysize() but does not count holes
> returns the number of non-empty entriessetarray(.@foo, 1, 2, 0, 0, 5); // initialize the array getarraysize(.@foo); // => 5 array_entries(.@foo); // => 3
array_remove(<array>, <needle>{, <neq>})
finds and removes every occurrence of <needle> from the array, while shifting left. if <neq> is true, finds entries that do not match instead
> returns the number of removed entriessetarray(.@foo, 1, 69, 3, 69, 5); // initialize the array array_remove(.@foo, 69); // => 2 // array is now: 1, 3, 5
array_reverse(<array>)
reverses the array
> returns truesetarray(.@foo, 1, 2, 3, 4, 5); // initialize the array array_reverse(.@foo); // => true // array is now: 5, 4, 3, 2, 1
array_sum(<array>)
iterates through the whole array to perform an arithmetic addition
> returns the sum of every entries of the arraysetarray(.@foo, 1, 2, 3, 4, 5); // initialize the array array_sum(.@foo); // ((((1 + 2) + 3) + 4) + 5) => 15
array_difference(<array>)
iterates through the whole array to perform an arithmetic subtraction
> returns the difference of every entries of the arraysetarray(.@foo, 1, 2, 3, 4, 5); // initialize the array array_difference(.@foo); // ((((1 - 2) - 3) - 4) - 5) => -13
array_product(<array>)
iterates through the whole array to perform an arithmetic multiplication
> returns the product of every entries of the arraysetarray(.@foo, 1, 2, 3, 4, 5); // initialize the array array_product(.@foo); // ((((1 * 2) * 3) * 4) * 5) => 120
array_quotient(<array>)
iterates through the whole array to perform an arithmetic division
> returns the quotient of every entries of the arraysetarray(.@foo, 1, 2, 3, 4, 5); // initialize the array array_quotient(.@foo); // ((((1 / 2) / 3) / 4) / 5) => 0
array_shift(<array>)
removes the first entry of the array, while shifting left
> returns the value of the removed entrysetarray(.@foo, 1, 2, 3, 4, 5); // initialize the array array_shift(.@foo); // => 1 // array is now: 2, 3, 4, 5
array_unshift(<array>, <value>)
adds <value> to the start of the array, while shifting right
> returns the new size of the arraysetarray(.@foo, 1, 2, 3, 4, 5); // initialize the array array_unshift(.@foo, 69); // => 6 // array is now: 69, 1, 2, 3, 4, 5
array_pop(<array>)
removes the last entry of the array
> returns the value of the removed entrysetarray(.@foo, 1, 2, 3, 4, 5); // initialize the array array_pop(.@foo); // => 5 // array is now: 1, 2, 3, 4
array_push(<array>, <value>)
adds <value> to the end of the array
> returns the new size of the arraysetarray(.@foo, 1, 2, 3, 4, 5); // initialize the array array_push(.@foo, 69); // => 6 // array is now: 1, 2, 3, 4, 5, 69
array_shuffle(<array>)
shuffles the array
> returns truesetarray(.@foo, 1, 2, 3, 4, 5); // initialize the array array_shuffle(.@foo); // => true // array is now: 1, 4, 2, 3, 5 (example, unpredictable)
array_unique(<array>{, <threshold>})
allows array entries to appear up to <threshold> times (1 by default) and removes the extraneous ones. useful to remove duplicate entries
> returns the number of removed entriessetarray(.@foo, 1, 3, 3, 4, 5); // initialize the array array_unique(.@foo); // => 1 // array is now: 1, 3, 4, 5
array_diff(<base array>, <array>{, <array>...}, <result array>)
compares the base array against one or more other arrays and fills the result array with the entries in base array that are not present in any of the other arrays
> returns the number of entries not found in other arrayssetarray(.@base, 1, 2, 3, 4, 5, 6, 7, 8); // initialize the base array // fill the arrays to compare with the base array: setarray(.@foo, 2, 3, 4, 5, 6, 7, 8); // missing "1" setarray(.@bar, 1, 2, 3, 4, 6, 7, 8); // missing "5" setarray(.@baz, 1, 2, 3, 4, 5, 6, 7); // missing "8" // compare foo, bar and baz against base, and fill result: array_diff(.@base, .@foo, .@bar, .@baz, .@result); // => 3 // .@result is now: 1, 5, 8
array_filter(<array>, "<function>")
filters the array using a function that is tested against every entries. if the function returns false, the relevant entry is removed and the array is shifted left
> returns the number of removed entriesfunction script is_prime { if (getarg(0) <= 1) return false; for (.@i = 2; .@i <= getarg(0) / 2; ++.@i) if ((getarg(0) % .@i) == 0) return false; return true; } setarray(.@foo, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); array_filter(.@foo, "is_prime"); // => 9 // array is now: 2, 3, 5, 7, 11, 13
array_sort(<array>)
sorts the array in ascending order
> returns truesetarray(.@foo, 2, 1, 8, 4, 5, 7, 6, 3); // initialize the array array_sort(.@foo); // => true // array is now: 1, 2, 3, 4, 5, 6, 7, 8
array_rsort(<array>)
sorts the array in descending order
> returns truesetarray(.@foo, 2, 1, 8, 4, 5, 7, 6, 3); // initialize the array array_rsort(.@foo); // => true // array is now: 8, 7, 6, 5, 4, 3, 2, 1
Requires Hercules of June 24 2017 or newer version
--------------------------------------------------------------------------------------
This script was made by me, for The Mana World + Evol.
License: public domain (CC0)
-
Submitter
-
Submitted05/29/17
-
Category
-
-
Randomization helper functions
This script provides syntactic sugar for randomization.
Works fine with both strings and integers.any(<arg>{, <arg>{, ...}})
> returns a random argument from the passed argumentsemotion(any(e_hmm, e_grat, e_yawn)); // do any of those 3 emotes
any_of(<array>)
> returns a random entry from the passed arraysetarray(.@foo, 1, 2, 3, 4); // build the array // ... later in the code: mes(any_of(.@foo)); // print any number from the array
relative_array_random(<array: 0, {[value, probability]...}>{, <recalculate>})
a more powerful version of any_of(), which allows to assign arbitrary probabilities to every entry instead of being rand(size) for every one.
the first value of the array is reserved and must be 0, and every entry must be a tuple of [value, probability].
if the array is modified between invocations please pass true as second argument to re-calculate the total probability.
probabilities are arbitrary and can be any number between 1 and INT_MAX.
> returns the random entrysetarray(.@foo, 0, // <= always 0 111, 6, 222, 12, // <= [value, probability] 333, 20, 444, 4); relative_array_random(.@foo); // => 333 (example, unpredictable)
--------------------------------------------------------------------------------------
This script was made by me, for The Mana World + Evol.
License: public domain (CC0)
-
Submitter
-
Submitted05/29/17
-
Category
-
-
Safe string manipulation functions
This script provides safe string manipulation functions that do not require PCRE to be enabled at compile time, making your scripts more portable.
startswith("<string>", "<substring>")
returns true if <string> begins with <substring>startswith("hypothermia", "hypo") // true startswith("hypothermia", "hyper") // false
endswith("<string>", "<substring>")
returns true if <string> ends with <substring>endswith("hypothermia", "thermia") // true endswith("hypothermia", "glycemia") // false
capitalize("<string>")
returns <string> with its first letter being capitalizedcapitalize("the quick brown fox") // The quick brown fox
titlecase("<string>")
returns <string> with the first letter of every word capitalizedtitlecase("the quick brown fox") // The Quick Brown Fox
camelcase("<string>")
returns <string> concatenated in a camelCase fashioncamelcase("the quick brown fox") // theQuickBrownFox
zfill("<string>"{, <width>{, "<padding>"}})
returns <string> padded to the left up to <width> with <padding>zfill(69, 6, "0"); // 000069 zfill(1337, 6, "0"); // 001337
format_number(<number>{, "<separator>"})
formats a number with <separator>format_number(50) // 50 format_number(50000) // 50,000 format_number(5000000) // 5,000,000
strip("<string>")
returns <string> without spaces at the beginning or endstrip(" the quick brown fox") // "the quick brown fox" strip("the quick brown fox ") // "the quick brown fox" strip(" the quick brown fox ") // "the quick brown fox"
reverse("<string>")
returns <string> reversedreverse("Hello world!") // !dlrow olleH
repeat("<string>", <multiplier>)
repeats <string> <multiplier> timesrepeat("Foo", 4) // FooFooFooFoo
shuffle("<string>")
returns <string> shuffledshuffle("abcdefg") // dgabefc (example, unpredictable)
-
Submitter
-
Submitted05/29/17
-
Category
-
-
Area timer functions
This script provides functions to add (or remove) timers to every player in the area or map.
areatimer("<map>", <x1>, <y1>, <x2>, <y2>, <tick>, "<event>")
makes all players in the square area call <event> after <tick> ms
> returns the number of affected playersareatimer("prontera", 55, 60, 150, 180, 500, "MyNPC:MyEvent");
areatimer2("<map>", <x1>, <y1>, <x2>, <y2>, <tick>, "<event>")
identical to areatimer, but also removes any existing timer before adding the new one
> returns the number of affected playersareatimer2("prontera", 55, 60, 150, 180, 500, "MyNPC:MyEvent");
areadeltimer("<map>", <x1>, <y1>, <x2>, <y2>, "<event>")
makes all players in the square area remove their timers for <event>
> returns the number of affected playersareadeltimer("prontera", 55, 60, 150, 180, "MyNPC:MyEvent");
maptimer("<map>", <tick>, "<event>")
makes all players in the map call <event> after <tick> ms
> returns the number of affected playersmaptimer("prontera", 500, "MyNPC:MyEvent");
maptimer2("<map>", <tick>, "<event>")
identical to maptimer() but also removes any existing timer before adding the new one
> returns the number of affected playersmaptimer2("prontera", 500, "MyNPC:MyEvent");
mapdeltimer("<map>", "<event>")
makes all players on the map remove their timers for <event>
> returns the number of affected playersmapdeltimer("prontera", "MyNPC:MyEvent");
globaltimer(<tick>, "<event>")
makes all players everywhere call <event> after <tick> ms
> returns the number of affected playersglobaltimer(500, "MyNPC:MyEvent");
Requires Hercules v2018.06.03 or newer version
--------------------------------------------------------------------------------------
This script was made by me, for The Mana World + Evol.
License: public domain (CC0)
-
Submitter
-
Submitted05/29/17
-
Category
-
-
There is no need to use global variables ($@) or to use attachrid
getmapxy(@evt_map$, @evt_x, @evt_y, UNITTYPE_PC); // save the previous position warp(.map$, .warp_x, .warp_y); // warp the player to your event end; OnWarpBack: warp(@evt_map$, @evt_x, @evt_y); end; OnEventEnd: .@count = getunits(BL_PC, .@players, false, .map$); for (.@i = 0; .@i < .@count; .@i++) { addtimer(rand(500), strnpcinfo(0) + "::OnWarpBack", .@players[.@i]); } end; OnInit: .map$ = "the-map"; // map of the event .warp_x = 50; // the x position to warp the player to .warp_y = 50; // the y position to warp the player to
-
File Name: Soul Menhir
File Submitter: meko
File Submitted: 29 May 2017
File Category: Utility
The Soul Menhir slowly regenerates the SP of anyone sitting near it.
Make sure to change the map, x, y and the sprite.
Requires Hercules of April 8th 2017 or newer version
--------------------------------------------------------------------------------------
This script was made by me, for The Mana World + Evol.
License: public domain (CC0)
-
An SSD (solid-state disk) is much much faster at reading and writing than a traditional HDD (hard disk drive), and generally more stable since it has no moving parts.
The difference between KVM and OpenVZ is that KVM uses hardware virtualization (aka an hypervisor) while OpenVZ uses OS-level virtualization (aka a container).
A hypervisor basically emulates the whole machine while a container just emulates the user-space and runs it on top of a shared kernel. Because of the added layer of abstraction offfered by hypervisors the performance is slightly worse than for containers.
-
Well of course it didn't continue: you used close; instead of break;
Changing it to random points
in Script Support
Posted
This whole script is very ugly, but if you want a quick, dirty patch just change line 125 from
to
And then on line 45 change the value of .gold_amount to the max value you want (ie 5)