ETA: I think you can actually set constants inside plugin_init for less hooking involved. I checked that when I was remaking your pcblock pull request into plugin (my actual Herc version is few months old, and probably not updating until deal with monster.conf is finished).
this post reserve to explain in detail what each constant do
as there are some of them doesn't really work, and some has to work with others
1st thing that you need to know is, the monsters stats has been calculated the moment the monster is spawned
so adding modify the monster's agi will not increase its flee, for example
have to modify its flee instead ...
damn ... now going out for lunch
having someone stay over really sux
need to summon a hp 10,000,000 poring ?
or you want to make emperium move ?
yes, this plugin allows you to customize your monsters attribute
Download : 1.2
patch <-- rathena fellows, you are welcome to plagiarize this command, since your setunitdata can't change stats LOL
I experienced in the past that, sometimes when my internet connection reset, my post will looks like rubbish
this time I will make multiple posts to reduce the risk of my explanation so they wont get edited
As large as of a strain it is on server, I'd advice to use loadmapevent better here, just to avoid recall thing. If you don't care for recall Annie's suggestion is way better.
The past week I've been messing around with processing how to utilise the storage better for my in-game NPCs & scripts.
Coming from rA, I noticed we didn't have the script commands "storageadditem", "storagecountitem", "storagedelitem".
Because of that I thought I should give it a try and aim to develop a plugin or a means, to make it possible to use this functionality again.
How to use:
you can use storageadditem to add an item name or itemid to a players storage. storageadditem <item id>, <amount>{, <account id>} storageadditem<item name>, <amount>{, <account id>} Example: storageadditem(501,10);
you can use storagecountitem to count a specific item name or itemid in a players storage. storagecountitem(nameID,{accountID}) returns number of items that meet the conditions Example: .@pots = storagecountitem(501);
you can use storagedeltitem to delete a specific item name or itemid in a players storage. storagedelitem <item id>,<amount>{,<account id>} storagedelitem "<item name>",<amount>{,<account id>} Deletes items from the target/attached player. Example: storagedelitem(501,.@pots);
Read the Hercules Plugin Manager wiki page if you don't know how to add this functionality to your server.
If you have any questions, suggestions or notice any bugs, kindly let me know and I'll see what I can do about it.
Just like the Item DB, the Mob DB has a less than optimal (read: terrible) format, that doesn't play well with Git or any other Version Control System.
For example, this is a snippet from the current file:
1012,RODA_FROG,Roda Frog,Roda Frog,5,133,0,6,5,1,11,14,0,5,1,5,5,5,10,5,10,12,1,5,21,0x81,200,2016,816,288,0,0,0,0,0,0,0,918,9000,908,500,511,300,721,7,713,2000,0,0,0,0,0,0,0,0,4014,11013,WOLF,Wolf,Wolf,25,919,0,329,199,1,37,46,0,0,1,20,28,15,32,20,10,12,1,2,22,0x1089,200,1054,504,432,0,0,0,0,0,0,0,1011,20,920,9000,2308,10,517,650,528,1050,919,5500,578,600,0,0,0,0,4029,1
1014,SPORE,Spore,Spore,16,510,0,66,108,1,24,48,0,5,1,12,12,5,19,8,10,12,1,3,21,0x81,200,1872,672,288,0,0,0,0,0,0,0,921,9000,507,800,510,50,743,10,2220,40,7033,5,578,600,0,0,0,0,4022,11015,ZOMBIE,Zombie,Zombie,15,534,0,50,33,1,67,79,0,10,1,8,7,0,15,0,10,12,1,1,29,0x3885,400,2612,912,288,0,0,0,0,0,0,0,957,9000,724,5,938,1000,958,50,727,70,0,0,0,0,0,0,0,0,4038,1
Can you tell, at a glance, if any of these mobs drops a Strawberry? You certainly can't (unless you already know).
Now, after locating the Strawberry drop, what happens if we want to remove it?
1012,RODA_FROG,Roda Frog,Roda Frog,5,133,0,6,5,1,11,14,0,5,1,5,5,5,10,5,10,12,1,5,21,0x81,200,2016,816,288,0,0,0,0,0,0,0,918,9000,908,500,511,300,721,7,713,2000,0,0,0,0,0,0,0,0,4014,11013,WOLF,Wolf,Wolf,25,919,0,329,199,1,37,46,0,0,1,20,28,15,32,20,10,12,1,2,22,0x1089,200,1054,504,432,0,0,0,0,0,0,0,1011,20,920,9000,2308,10,517,650,528,1050,919,5500,0,0,0,0,0,0,4029,1
1014,SPORE,Spore,Spore,16,510,0,66,108,1,24,48,0,5,1,12,12,5,19,8,10,12,1,3,21,0x81,200,1872,672,288,0,0,0,0,0,0,0,921,9000,507,800,510,50,743,10,2220,40,7033,5,0,0,0,0,0,4022,11015,ZOMBIE,Zombie,Zombie,15,534,0,50,33,1,67,79,0,10,1,8,7,0,15,0,10,12,1,1,29,0x3885,400,2612,912,288,0,0,0,0,0,0,0,957,9000,724,5,938,1000,958,50,727,70,0,0,0,0,0,0,0,0,4038,1
How many Strawberry entries did I remove and from which lines? Can you tell at a glance? Certainly not.
What happens if we try to diff it? (this is the output of 'git diff' with the modified file)
@@ -16,8 +16,8 @@
1010,WILOW,Willow,Willow,4,95,0,5,4,1,9,12,5,15,1,4,8,30,9,10,10,12,1,3,22,0x81,200,1672,672,432,0,0,0,0,0,0,0,902,9000,1019,100,907,1500,516,700,1068,3500,1067,2000,1066,1000,0,0,0,0,4010,1
1011,CHONCHON,Chonchon,Chonchon,4,67,0,5,4,1,10,13,10,0,1,10,4,5,12,2,10,12,0,4,24,0x181,200,1076,576,480,0,0,0,0,0,0,0,998,50,935,6500,909,1500,1205,55,601,100,742,5,1002,150,0,0,0,0,4009,1
1012,RODA_FROG,Roda Frog,Roda Frog,5,133,0,6,5,1,11,14,0,5,1,5,5,5,10,5,10,12,1,5,21,0x81,200,2016,816,288,0,0,0,0,0,0,0,918,9000,908,500,511,300,721,7,713,2000,0,0,0,0,0,0,0,0,4014,1
-1013,WOLF,Wolf,Wolf,25,919,0,329,199,1,37,46,0,0,1,20,28,15,32,20,10,12,1,2,22,0x1089,200,1054,504,432,0,0,0,0,0,0,0,1011,20,920,9000,2308,10,517,650,528,1050,919,5500,578,600,0,0,0,0,4029,1
-1014,SPORE,Spore,Spore,16,510,0,66,108,1,24,48,0,5,1,12,12,5,19,8,10,12,1,3,21,0x81,200,1872,672,288,0,0,0,0,0,0,0,921,9000,507,800,510,50,743,10,2220,40,7033,5,578,600,0,0,0,0,4022,1
+1013,WOLF,Wolf,Wolf,25,919,0,329,199,1,37,46,0,0,1,20,28,15,32,20,10,12,1,2,22,0x1089,200,1054,504,432,0,0,0,0,0,0,0,1011,20,920,9000,2308,10,517,650,528,1050,919,5500,0,0,0,0,0,0,4029,1
+1014,SPORE,Spore,Spore,16,510,0,66,108,1,24,48,0,5,1,12,12,5,19,8,10,12,1,3,21,0x81,200,1872,672,288,0,0,0,0,0,0,0,921,9000,507,800,510,50,743,10,2220,40,7033,5,0,0,0,0,0,4022,1
1015,ZOMBIE,Zombie,Zombie,15,534,0,50,33,1,67,79,0,10,1,8,7,0,15,0,10,12,1,1,29,0x3885,400,2612,912,288,0,0,0,0,0,0,0,957,9000,724,5,938,1000,958,50,727,70,0,0,0,0,0,0,0,0,4038,1
1016,ARCHER_SKELETON,Archer Skeleton,Archer Skeleton,31,3040,0,483,283,9,128,153,0,0,1,8,14,5,90,5,10,12,1,1,29,0x2085,300,2864,864,576,0,0,0,0,0,0,0,932,4500,756,70,2285,3,1708,35,1752,1000,507,1800,1701,150,0,0,0,0,4094,1
//1017,THIEF_BUG_FEMALE,Thief Bug Female,Thief Bug Female,10,170,0,35,18,1,33,40,5,5,1,15,10,5,23,5,10,12,1,4,27,0x651,200,988,288,768,0,0,0,0,0,0,0,955,3500,910,250,1108,15,928,200,507,400,716,50,1002,400,0,0,0,0,4026,1
Oh, so two lines were modified. Now, to locate the entry that was changed. By the way, you didn't notice that I purposely introduced a syntax error, did you? (hint: count the commas in the SPORE line: there's one less entry!)
Now what happens if someone else changes the file (on a nearby, but unrelated line), and you pull the change?
<<<<<<< HEAD
1012,RODA_FROG,Roda Frog,Roda Frog,5,133,0,6,5,1,11,14,0,5,1,5,5,5,10,5,10,12,1,5,21,0x81,200,2016,816,288,0,0,0,0,0,0,0,918,9000,908,500,511,300,721,7,713,2000,0,0,0,0,0,0,0,0,4014,1
1013,WOLF,Wolf,Wolf,25,919,0,329,199,1,37,46,0,0,1,20,28,15,32,20,10,12,1,2,22,0x1089,200,1054,504,432,0,0,0,0,0,0,0,1011,20,920,9000,2308,10,517,650,528,1050,919,5500,0,0,0,0,0,0,4029,1
1014,SPORE,Spore,Spore,16,510,0,66,108,1,24,48,0,5,1,12,12,5,19,8,10,12,1,3,21,0x81,200,1872,672,288,0,0,0,0,0,0,0,921,9000,507,800,510,50,743,10,2220,40,7033,5,0,0,0,0,0,4022,1
=======1012,RODA_FROG,Roda Frog,Roda Frog,5,133,0,6,5,1,11,14,0,5,1,5,5,5,10,5,10,12,1,5,21,0x81,200,2016,816,288,0,0,0,0,0,0,0,918,9000,908,500,511,300,721,7,713,2000,578,600,0,0,0,0,0,0,4014,1
1013,WOLF,Wolf,Wolf,25,919,0,329,199,1,37,46,0,0,1,20,28,15,32,20,10,12,1,2,22,0x1089,200,1054,504,432,0,0,0,0,0,0,0,1011,20,920,9000,2308,10,517,650,528,1050,919,5500,578,600,0,0,0,0,4029,1
1014,SPORE,Spore,Spore,16,510,0,66,106,1,24,48,0,5,1,12,12,5,19,8,10,12,1,3,21,0x81,200,1872,672,288,0,0,0,0,0,0,0,0,921,9000,507,800,510,50,743,10,2220,40,7033,5,578,600,0,0,0,0,4022,1
>>>>>>> upstream change
Well, have fun figuring out how to merge it! (hint: a Strawberry drop was added to RODA_FROG -- could you tell? And now, are you sure nothing else was changed? Doublecheck? Would you believe it if I said that SPORE's Job EXP was also decreased by two? Anything else? I'll leave that as homework.)
How do we fix it?
Once again, we're switching to a different file format. Just like last time, it'll be libconfig. We're aware there are plenty of other suitable file formats out there (who said yaml?), but unfortunately this is not the time and place to change what was already started, and we'll have to stick with libconfig for the time being. (we'll see about writing some tools that leverage the Hercules libconfig parser to lessen everyone's pain).
Some highlights:
There is no need for those annoying sequences of zeros. If a mob drops less than 10 items, only the needed entries will be there.
The mob_db2 entries can be left incomplete and set to inherit the original mob_db entry. If you want your SPORE to have higher Attack, , you can just write that in your mob_db2, and let it read the other values from the mob_db, so that if we update them, you get the update automatically
We can finally add more fields (to support new features) to the file at any time, easily and without having to edit all the lines (or force you to edit all the lines of your custom mob_db2)!
What does it look like?
Each entry follows this structure:
{
// =================== Mandatory fields ===============================
Id: ID (int)
SpriteName: "SPRITE_NAME" (string)
Name: "Mob name" (string)
// =================== Optional fields ================================
Lv: level (int, defaults to 1)
Hp: health (int, defaults to 1)
Sp: mana (int, defaults to 0)
Exp: basic experience (int, defaults to 0)
JExp: job experience (int, defaults to 0)
AttackRange: attack range (int, defaults to 1)
Attack: [attack1, attack2] (int, defaults to 0)
Def: defence (int, defaults to 0)
Mdef: magic defence (int, defaults to 0)
Stats: {
Str: strength (int, defaults to 0)
Agi: agility (int, defaults to 0)
Vit: vitality (int, defaults to 0)
Int: intelligence (int, defaults to 0)
Dex: dexterity (int, defaults to 0)
Luk: luck (int, defaults to 0)
}
ViewRange: view range (int, defaults to 1)
ChaseRange: chase range (int, defaults to 1)
Size: size (int, defaults to 1)
Race: race (int, defaults to 0)
Element: (type, level)
Mode: {
CanMove: true/false (bool)
Looter: true/false (bool)
Aggressive: true/false (bool)
Assist: true/false (bool)
CastSensorIdle:true/false (bool)
Boss: true/false (bool)
Plant: true/false (bool)
CanAttack: true/false (bool)
Detector: true/false (bool)
CastSensorChase: true/false (bool)
ChangeChase: true/false (bool)
Angry: true/false (bool)
ChangeTargetMelee: true/false (bool)
ChangeTargetChase: true/false (bool)
TargetWeak: true/false (bool)
}
MoveSpeed: move speed (int, defaults to 0)
AttackDelay: attack delay (int, defaults to 4000)
AttackMotion: attack motion (int, defaults to 2000)
DamageMotion: damage motion (int, defaults to 0)
MvpExp: mvp experience (int, defaults to 0)
MvpDrops: {
AegisName: chance (string: int)
...
}
Drops: {
AegisName: chance (string: int)
...
}
}
Here's a PORING in the old format:
1002,PORING,Poring,Poring,1,50,0,2,1,1,7,10,0,5,1,1,1,0,6,30,10,12,1,3,21,0x83,400,1872,672,480,0,0,0,0,0,0,0,909,7000,1202,100,938,400,512,1000,713,1500,512,150,619,20,0,0,0,0,4001,1
And here's the same PORING in the new format:
{
Id: 1002
SpriteName: "PORING"
Name: "Poring"
Lv: 1
Hp: 50
Sp: 0
Exp: 2
JExp: 1
AttackRange: 1
Attack: [7, 10]
Def: 0
Mdef: 5
Stats: {
Str: 1
Agi: 1
Vit: 1
Int: 0
Dex: 6
Luk: 30
}
ViewRange: 10
ChaseRange: 12
Size: 1
Race: 3
Element: (1, 1)
Mode: {
CanMove: true
Looter: true
CanAttack: true
}
MoveSpeed: 400
AttackDelay: 1872
AttackMotion: 672
DamageMotion: 480
MvpExp: 0
Drops: {
Jellopy: 7000
Knife_: 100
Sticky_Mucus: 400
Apple: 1000
Empty_Bottle: 1500
Apple: 150
Unripe_Apple: 20
Poring_Card: 1
}
},
Not convinced yet it's better?
It's true that you need to convert your item database to the new format, but we can do it for you!
Go to http://haru.ws/hercules/mobdbconverter/ and paste (or upload) your mob_db2.txt (or even your mob_db.txt if you have custom entries there), pick between renewal or pre-renewal (or upload your item_db if it's customized), press the Convert button, wait a few seconds and you're done! It's already converted for you. Easy, isn't it?
Don't trust us? No, no, we don't need your custom mobs, you can sleep safe... But if you still don't want to paste anything on a website... well, we have provided the source code of the converter script! It's in the 'tools' folder of the Hercules repository. All you need is a Python interpreter, version 2.6 or newer (and if you're running Linux or Mac OS, on either your server or your own computer, it's almost certain that you already have that). All you have to do is run it (example: python tools/mobdbconverter.py pre-re . < db/mob_db2.txt > db/mob_db2.conf), and your item database will be converted in a split second!
What if I was using SQL mob databases?
Well, you're out of luck. It was deprecated long ago and it's being removed. It'll stay available for website/control panel purposes though. An automated converter (much like the db2sql plugin for the item db) will be available soon, and even executed automatically whenever we update the mob db, to keep the sql counterpart in sync!
I have this event mob entry that came with an old script I downloaded...
No worries, you can get it converted. Use the same script (or the provided web page) you'd use to convert an entire mob database, it'll work just fine even for a mob or two!
Special thanks
To Ind, for bringing up the idea, a long time ago.
To Andrei Karas for actually doing it, after picking up this project from the bottom of our forgotten items box.
To me, for putting this at the bottom of the forgotten items box, and burying it with several other things so that it'd stay there until now (sigh)
Links
Merged pull request.
Web-based converter.
Yup, sleep2 returns a bool if the player is still attached. The problem is, in this case as there would be no player attached it'll return 0 and it won't even run the cycle.
contact me on facebook! join discord for freebies!
welcome to my paid services.
below you can find a variety of things I can do to make your server stand out! if you need anything else, just ask.
Logo 25$*
Patcher 20$*
Animated Banner 10$*
Advertising Banner 10$*
Loading Screen 2$*
Login Screen 5$*
Facebook Banner + Profile 10$*
Forum Skin 30$*
Wiki Skin 20$*
Interface Skin 20$*
Website 30$*
Icons 2$*
*Please note that prices listed are for re-sellers and come without PSD. *For exclusive graphics with or without PSD please ask for a quote.
Advertising 10$/week*
Wiki Editor 20$/week*
Support GM 20$/week*
Event GM 20$/week*
Fast Refresh Client 50$*
Normal Client 10$*
FluxCP Setup 10$*
Scripts 5$*
Singature 5$*
well, that was pretty much all I could think of. for a preview of my works please check the second post below! if you need anything else, just ask.
I think this would be a bit more useful
*questinfo <Quest ID>, <Icon> {, <Map Mark Color>{, <Job Class>}};This is esentially a combination of checkquest and showevent. Use this onlyin an OnInit label. For the Quest ID, specify the quest ID that you wantchecked if it has been started yet.For Icon, use one of the following:No Icon : QTYPE_NONE! Quest Icon : QTYPE_QUEST? Quest Icon : QTYPE_QUEST2! Job Icon : QTYPE_JOB? Job Icon : QTYPE_JOB2! Event Icon : QTYPE_EVENT? Event Icon : QTYPE_EVENT2Warg : QTYPE_WARGWarg Face : QTYPE_WARG2 (Only for packetver >= 20120410)Map Mark Color, when used, creates a mark in the user's mini map on the position of the NPC,the available color values are:0 - No Marker1 - Yellow Marker2 - Green Marker3 - Purple MarkerWhen a user shows up on a map, each NPC is checked for questinfo that has been set.If questinfo is present, it will check if the quest has been started, if it has not, the bubble will appear.Optionally, you can also specify a Job Class if the quest bubble should only appear for a certain class.Exampleizlude,100,100,4 script Test 844,{ mes "[Test]"; mes "Hello World."; close; OnInit: questinfo 1001, QTYPE_QUEST, 0, Job_Novice; end;}
I think this would be a bit more useful
*questinfo <Quest ID>, <Icon> {, <Map Mark Color>{, <Job Class>}};This is esentially a combination of checkquest and showevent. Use this onlyin an OnInit label. For the Quest ID, specify the quest ID that you wantchecked if it has been started yet.For Icon, use one of the following:No Icon : QTYPE_NONE! Quest Icon : QTYPE_QUEST? Quest Icon : QTYPE_QUEST2! Job Icon : QTYPE_JOB? Job Icon : QTYPE_JOB2! Event Icon : QTYPE_EVENT? Event Icon : QTYPE_EVENT2Warg : QTYPE_WARGWarg Face : QTYPE_WARG2 (Only for packetver >= 20120410)Map Mark Color, when used, creates a mark in the user's mini map on the position of the NPC,the available color values are:0 - No Marker1 - Yellow Marker2 - Green Marker3 - Purple MarkerWhen a user shows up on a map, each NPC is checked for questinfo that has been set.If questinfo is present, it will check if the quest has been started, if it has not, the bubble will appear.Optionally, you can also specify a Job Class if the quest bubble should only appear for a certain class.Exampleizlude,100,100,4 script Test 844,{ mes "[Test]"; mes "Hello World."; close; OnInit: questinfo 1001, QTYPE_QUEST, 0, Job_Novice; end;}
Bunch edit as in you can now edit few items at once, for example if you'll highlight few items inside item_db and edit weight to 10, all highlighted items will change their weight to 10.
SDE also has client description autocomplete depending on item_db1/2.
Python script lets you make your own changes depending on your own conditions, but that requires some Python knowledge, check the topic I linked you to, Tokei wrote some example python scripts.
Bunch edit as in you can now edit few items at once, for example if you'll highlight few items inside item_db and edit weight to 10, all highlighted items will change their weight to 10.
SDE also has client description autocomplete depending on item_db1/2.
Python script lets you make your own changes depending on your own conditions, but that requires some Python knowledge, check the topic I linked you to, Tokei wrote some example python scripts.
Well, not quite what you're thinking about, but you can summon effect from NPC using several different commands:
skilleffect;npcskilleffect;specialeffect;specialeffect2;misceffect;
You can read their descriptions inside doc/script_commands.txt and choose whichever you see most fitting.
But be warned, those only summon effect for the predefined duration of the effect itself (only), so if you want a continuous animation you'd need to refresh the animation calling every now and then, and for that npc timer will come in handy
But there is an example of how clif->soundeffect is used O_o
clif->soundeffect(<session data of who you send it to>, <source block list>, <name of file to play relative to datawav>, 0 <type, stands for play once, iirc other types except 0 do not work>)
What exactly do you mean by "example" then? If you want to use it as skill sound with area you'll be better off using clif->soundeffectall btw.
Well, I see few problems with checking if item is bound, since you'll need to check some specific item, as it is stored inside item itself. If you plan to delete it afterward you'll need to delete it by its index, and I believe there's no command to do that by default. And that there can be both bound and non-bound item inside player inventory does not make it easier. Albeit delitem prefers normal items over bound/carded ones, but don't take my word for it.
For the flag checking you can use this command that was made for me by a friend long ago:
/* [List of Restrictions] ITR_NONE 0 ITR_NODROP 1 ITR_NOTRADE 2 ITR_PARTNEROVERRIDE 4 ITR_NOSELLTONPC 8 ITR_NOCART 16 ITR_NOSTORAGE 32 ITR_NOGSTORAGE 64 ITR_NOMAIL 128 ITR_NOAUCTION 256 ITR_ALL 511 Usage in scripts: chk_restrictions(ItemID);*/BUILDIN(chk_restrictions) { struct item_data *item_info; int item_id, item_tradable; item_id = script_getnum(st,2); //Value sent by the script (Item ID) if(itemdb->exists(item_id)) item_info = itemdb->search(item_id); else { script_pushint(st,-1); //If the ID is invalid it stops here and returns -1 return true; } item_tradable = item_info->flag.trade_restriction; script_pushint(st, item_tradable); //Returns the sum of restrictions return true;}
It returns combined value of restrictions on item, so if you want to check if it's tradeable, then
chk_restrictions(item)&2
must be 0.
Makes it easy to use inside ifs:
if( chk_restrictions(item)&2 ) { // Item is non-tradeable, prevent script from advancing}
rA uses completely different instance setting, it has instance_db, so it doesn't need instance_attachmap/instance_set_timeout. Also, there's no instance map name emulation or character/guild/anyone instances.
I think this should work, didn't test it though
prontera,150,150,5 script codes 89,{
set .@n$,"[code Creator]";
mes .@n$;
mes "This code will only work with the help of the Administrator. Please give this code to our Administrator so that they can Reset your System Credential.";
next;
mes .@n$;
mes "Please write this down.";
mes "===================================";
for (.@i = 0; .@i< 10; .@i++) {
.@ch$ = .codes$[rand(getarraysize(.codes$))];
.@gen$[.@i] = (rand(2)?strtolower(.@ch$):.@ch$);
}
mes "Your Code is: " + implode(.@gen$);
close;
OnInit:
setarray .codes$[0],"A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z","1","2","3","4","5","6","7","8","9","0"; end;}
First, you need to add the actual code inside src/map/atcommand.c, along with adding command to the list in the bottom of it. Plugin is a good (and even better imo) alternative to editing src files. Then you recompile (or compile and activate plugin), and edit conf/groups.conf to make the command accessible by players/GMs. That's pretty much it.