Jump to content

meko

Core Developers
  • Content Count

    363
  • Joined

  • Days Won

    46

Reputation Activity

  1. Upvote
    meko got a reaction from Legend in Race condition in char server: please update   
    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.
  2. Upvote
    meko got a reaction from Thyr in Antibot Killer 6 by Myzter   
    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
  3. Upvote
    meko got a reaction from Sephus in Race condition in char server: please update   
    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.
  4. Upvote
    meko got a reaction from luan122 in tryin' to teleport and gettin' error   
    Are you using a custom map or a built-in map? make sure it is in db/map_index.txt and if it's a new map update the mapcache
  5. Upvote
    meko got a reaction from Daehyon in How to update Herc without git clone   
    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
  6. Upvote
    meko got a reaction from Sephus in Updating Hercules [git pull problem]   
    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
  7. Upvote
    meko reacted to Habilis in Overwrite schema ragnarok in phpadmin   
    You cannot just change emulators and expect DataBase to be 100% compatible...
     
    If you want to keep data you need to analyze and do a conversion.
     
    If you don't want to keep data, use a fresh database.
  8. Upvote
    meko reacted to Sephus in Herc or Idathena?   
    IdAthena is an Indonesian localisation of the emulator if I'm not mistaken? Hercules has HULD that supports localisation of scripts, the benefit of which outweighs using any other localised emulator. Because your users will be able to understand your server in their own language, if you support it. Hercules makes this possible.
    This among other several reasons why it is far more superior to rA or any other (and I don't mean to put them down but the code speaks for itself).
  9. Like
    meko got a reaction from Hyroshima in Array manipulation functions   
    View File 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 entries
    setarray(.@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 entries setarray(.@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 -1 setarray(.@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 -1 setarray(.@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 false setarray(.@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 entries setarray(.@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 entries setarray(.@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 true setarray(.@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 array setarray(.@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 array setarray(.@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 array setarray(.@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 array setarray(.@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 entry setarray(.@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 array setarray(.@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 entry setarray(.@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 array setarray(.@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 true setarray(.@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 entries
    setarray(.@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 arrays
    setarray(.@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 entries
    function 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 true
    setarray(.@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 true
    setarray(.@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 meko Submitted 05/29/17 Category Quest, Shops, Functions & Algorithms  
  10. Upvote
    meko got a reaction from Neffletics in Array manipulation functions   
    View File 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 entries
    setarray(.@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 entries setarray(.@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 -1 setarray(.@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 -1 setarray(.@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 false setarray(.@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 entries setarray(.@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 entries setarray(.@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 true setarray(.@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 array setarray(.@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 array setarray(.@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 array setarray(.@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 array setarray(.@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 entry setarray(.@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 array setarray(.@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 entry setarray(.@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 array setarray(.@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 true setarray(.@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 entries
    setarray(.@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 arrays
    setarray(.@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 entries
    function 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 true
    setarray(.@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 true
    setarray(.@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 meko Submitted 05/29/17 Category Quest, Shops, Functions & Algorithms  
  11. Upvote
    meko got a reaction from AnnieRuru in Array manipulation functions   
    View File 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 entries
    setarray(.@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 entries setarray(.@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 -1 setarray(.@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 -1 setarray(.@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 false setarray(.@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 entries setarray(.@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 entries setarray(.@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 true setarray(.@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 array setarray(.@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 array setarray(.@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 array setarray(.@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 array setarray(.@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 entry setarray(.@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 array setarray(.@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 entry setarray(.@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 array setarray(.@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 true setarray(.@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 entries
    setarray(.@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 arrays
    setarray(.@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 entries
    function 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 true
    setarray(.@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 true
    setarray(.@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 meko Submitted 05/29/17 Category Quest, Shops, Functions & Algorithms  
  12. Upvote
    meko reacted to suezo0621 in [Free Release] Chubby Chick   
    File Name: [Free Release] Chubby Chick
    File Submitter: suezo0621
    File Submitted: 14 Aug 2016
    File Category: Sprites & Palettes
     
    cute headgear, enjoy it!
     
    Preview:

     
    [file include]
    * collection.bmp
    * item.bmp
    * drop.act
    * drop.spr
    * equip.act
    * equip.spr
     
    Click here to download this file
  13. Upvote
    meko got a reaction from tedexx in Randomization helper functions   
    View File 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 arguments
    emotion(any(e_hmm, e_grat, e_yawn)); // do any of those 3 emotes  


    any_of(<array>)
    > returns a random entry from the passed array setarray(.@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 entry
    setarray(.@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 meko Submitted 05/29/17 Category Quest, Shops, Functions & Algorithms  
  14. Upvote
    meko got a reaction from xVec in Area timer functions   
    View File 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 players
    areatimer("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 players
    areatimer2("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 players
    areadeltimer("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 players
    maptimer("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 players
    maptimer2("prontera", 500, "MyNPC:MyEvent");    
     
    mapdeltimer("<map>", "<event>")
    makes all players on the map remove their timers for <event>
    > returns the number of affected players
    mapdeltimer("prontera", "MyNPC:MyEvent");         globaltimer(<tick>, "<event>")
    makes all players everywhere call <event> after <tick> ms
    > returns the number of affected players globaltimer(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 meko Submitted 05/29/17 Category Quest, Shops, Functions & Algorithms  
  15. Upvote
    meko got a reaction from tedexx in Safe string manipulation functions   
    View File 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 capitalized capitalize("the quick brown fox") // The quick brown fox


    titlecase("<string>")
    returns <string> with the first letter of every word capitalized titlecase("the quick brown fox") // The Quick Brown Fox


    camelcase("<string>")
    returns <string> concatenated in a camelCase fashion camelcase("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 end strip(" 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> reversed reverse("Hello world!") // !dlrow olleH


    repeat("<string>", <multiplier>)
    repeats <string> <multiplier> times repeat("Foo", 4) // FooFooFooFoo


    shuffle("<string>")
    returns <string> shuffled
    shuffle("abcdefg") // dgabefc (example, unpredictable)
     
    Submitter meko Submitted 05/29/17 Category Quest, Shops, Functions & Algorithms  
  16. Upvote
    meko got a reaction from tedexx in Area timer functions   
    View File 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 players
    areatimer("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 players
    areatimer2("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 players
    areadeltimer("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 players
    maptimer("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 players
    maptimer2("prontera", 500, "MyNPC:MyEvent");    
     
    mapdeltimer("<map>", "<event>")
    makes all players on the map remove their timers for <event>
    > returns the number of affected players
    mapdeltimer("prontera", "MyNPC:MyEvent");         globaltimer(<tick>, "<event>")
    makes all players everywhere call <event> after <tick> ms
    > returns the number of affected players globaltimer(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 meko Submitted 05/29/17 Category Quest, Shops, Functions & Algorithms  
  17. Upvote
    meko got a reaction from Thyr in Anyone can recommend that can host ragnarok server?   
    For the cheapest VPS offers have a look at LowEndBox.
    Keep in mind that most of those cheep providers advertised on LowEndBox do not offer DDOS protection.
     
     
     
    As for a guide to setting up a VPS running Hercules, I would first advise you to learn the basics of Linux:
    https://www.linux.com/learn/complete-beginners-guide-linux
    https://opensource.com/education/14/4/windows-to-linux-system-administration
    http://linuxsurvival.com/linux-tutorial-introduction/
     
    For the distribution, I recommend Debian, or Ubuntu Server (which is itself based on Debian)
     
     
    What is a VPS, what are the limitations:
    http://www.webhostingsecretrevealed.net/vps-hosting-guide/
     
     
    How to use SSH:
    https://support.suso.com/supki/SSH_Tutorial_for_Linux
    https://www.ssh.com/ssh/putty/windows/
     
     
    How to use git:
    https://try.github.io
    https://git-scm.com/documentation
     
     
    How to compile Hercules:
    https://github.com/HerculesWS/Hercules/blob/master/README.md#prerequisites
     
    How to use SQL:
    https://www.amazon.com/dp/1593271905/
  18. Upvote
  19. Upvote
    meko got a reaction from Thyr in @feelreset @hatereset commands for normal players   
    Add them in /conf/groups.conf to the group that has id: 0, usually this group is named "Player".
     
    In the Commands section of this group, add the following:
    feelreset: true allskill: true  
    For @hatereset I could not find this command in the source.
  20. Upvote
    meko got a reaction from Legend in Event Rewarder   
    Here, I made this for you:
    - script @give FAKE_NPC,{ end; OnCall: .@full$ = implode(.@atcmd_parameters$[0], " "); // put the string back together if ((.@full$ ~= "^([1-9]{1,10}) ([Zz]enys?|[Ii]tems? ([0-9]+)|[Cc]ash(?: ?point)?s?) to (.{1,23})$") == false) { dispbottom("@give : Invalid syntax!"); dispbottom("@give : Proper syntax is @give <amount> <zeny | item <name> | cash> to <player name>"); end; } .@amount = max(1, atoi($@regexmatch$[1])); .@type = ord(strtolower($@regexmatch$[2])); .@item = atoi($@regexmatch$[3]); .@player$ = escape_sql($@regexmatch$[4]); .@player = getcharid(CHAR_ID_ACCOUNT, .@player$); .@char = getcharid(CHAR_ID_CHAR, .@player$); .@count = query_sql(sprintf("SELECT `name`, `char_id`, `account_id` " "FROM `char` " "WHERE `name` = '%s' LIMIT 1;", .@player$), .@player$, .@char, .@player); if (.@count < 1 || .@player < 1 || .@char < 1) { dispbottom("@give : Player not found in database!"); end; } switch (.@type) { case 122: // ZENY if (isloggedin(.@player, .@char)) { charcommand(sprintf("#zeny \"%s\" %i", .@player$, .@amount)); } else { query_sql(sprintf("INSERT INTO `mail` (send_name,dest_name,dest_id,title,time,zeny) " "VALUES ('%s','%s',%i,'%s',%i,%i);", "SRV", .@player$, .@char, "Event Reward", gettimetick(2), .@amount)); } break; case 105: // ITEM if (.@item < 1 || getiteminfo(.@item, 0) < 0) { dispbottom("@give : Item not found!"); end; } if (isloggedin(.@player, .@char)) { getitem(.@item, .@amount, .@player); } else { query_sql(sprintf("INSERT INTO `mail` (send_name,dest_name,dest_id,title,time,amount,nameid) " "VALUES ('%s','%s',%i,'%s',%i,%i,%i);", "SRV", .@player$, .@char, "Event Reward", gettimetick(2), .@amount, .@item)); } break; case 99: // CASH if (isloggedin(.@player, .@char)) { set(getvariableofpc(#CASHPOINTS, .@player), getvariableofpc(#CASHPOINTS, .@player) + .@amount); } else { query_sql(sprintf("UPDATE `acc_reg_num_db` " "SET `index` = `index` + %i " "WHERE `account_id` = %i AND `key` = '#CASHPOINTS';", .@amount, .@player)); } } dispbottom(sprintf("@give : Reward has been delivered to `%s`.", .@player$)); end; OnInit: bindatcmd("give", "@give::OnCall", 0, 99, 0); // <<< MAKE SURE YOU CHANGE THE GROUP ID HERE }  
    Example usage:
    @give 50 zeny to meko @give 69 cash to meko @give 1 item 508 to meko  
    If the player is online the reward is delivered instantly; If the player is offline the reward is delivered via the mail system (except for Cash rewards)
  21. Upvote
    meko reacted to Dastgir in Require a certain amount of reputation, posts and time registered to perform Downloads.   
    For me, I don't feel we need any restriction, we are open-source community, putting any restriction will discourage user from using forum and it would give rise to many spam accounts and more importantly, it will lead to increase demand for paid developers and as a result less scripts/mods would be released for free.
  22. Upvote
    meko reacted to Sephus in Require a certain amount of reputation, posts and time registered to perform Downloads.   
    From a realistic perspective, lets not. Why? Take for example one of those websites or forum that release something but require you to post a reply before showing you the link to download. I would prefer one's genuine gratitude or none at all, rather than forced.
  23. Upvote
    meko got a reaction from Echoes in Recent changes to the Hercules engine   
    It seems there's been no changelog since quite a while so here's one highlighting the most recent changes related to scripting. Sorry if that's not the right category, please move accordingly.     New script commands: chr ord gettimer getunits getvariableofpc can_use_command has_permission addchannelhandler removechannelhandler setunitdata getunitdata getunitname setunitname getequipisenableopt getequippedoptioninfo getequipoptioninfo setequipoption navigateto   Modified script commands (extra parameters): strcharinfo strnpcinfo addtimer deltimer addtimercount checkoption checkoption1 checkoption2 setoption warpparty warpguild classchange   New params: BankVault  
     
    Big projects currently in development:
    Implementation of the official Clan system Implementation of the official RoDEX system Implementation of the official Achievements system Complete rewrite of the map cache system
  24. Upvote
    meko got a reaction from Like it~* in Recent changes to the Hercules engine   
    It seems there's been no changelog since quite a while so here's one highlighting the most recent changes related to scripting. Sorry if that's not the right category, please move accordingly.     New script commands: chr ord gettimer getunits getvariableofpc can_use_command has_permission addchannelhandler removechannelhandler setunitdata getunitdata getunitname setunitname getequipisenableopt getequippedoptioninfo getequipoptioninfo setequipoption navigateto   Modified script commands (extra parameters): strcharinfo strnpcinfo addtimer deltimer addtimercount checkoption checkoption1 checkoption2 setoption warpparty warpguild classchange   New params: BankVault  
     
    Big projects currently in development:
    Implementation of the official Clan system Implementation of the official RoDEX system Implementation of the official Achievements system Complete rewrite of the map cache system
  25. Upvote
    meko got a reaction from tedexx in Require a certain amount of reputation, posts and time registered to perform Downloads.   
    This will just encourage people making spam posts to increase their post count, and encourage creating other accounts to increase reputation. It makes everything cumbersome for everyone. You cannot and should not force people to contribute. You'll just end up driving away possible contributors to other projects (ie rAthena). Most people nowadays prefer to try first, then if they like it they come back and contribute. If people feel forced they just bail.
×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.