From 582336dff2bffba506891a54ecd9360e4fbdd65c Mon Sep 17 00:00:00 2001 From: Carlos Henrique Date: Thu, 20 Sep 2018 16:08:47 -0300 Subject: Added mapflags 'nostorage' and 'nogstorage' nostorage 1 -- blocks only @storage nostorage 2 -- blocks only openstorage(); nostorage 3 -- blocks @storage and openstorage() nogstorage 1 -- blocks only @gstorage nogstorage 2 -- blocks only guildopenstorage(); nogstorage 3 -- blocks @gstorage and guildopenstorage() --- doc/constants.md | 2 ++ doc/permissions.md | 1 + doc/script_commands.txt | 9 +++++++++ 3 files changed, 12 insertions(+) (limited to 'doc') diff --git a/doc/constants.md b/doc/constants.md index 276881a43..cca12c59a 100644 --- a/doc/constants.md +++ b/doc/constants.md @@ -362,6 +362,8 @@ - `mf_noviewid`: 56 - `mf_pairship_startable`: 57 - `mf_pairship_endable`: 58 +- `mf_nostorage`: 59 +- `mf_nogstorage`: 60 ### Cell Properties diff --git a/doc/permissions.md b/doc/permissions.md index 7d29b59fd..a8794ecae 100644 --- a/doc/permissions.md +++ b/doc/permissions.md @@ -48,4 +48,5 @@ disable_pickup | Ability to disable the player from picking up any i disable_exp | Ability to disable the player from gaining any experience point. disable_store | Ability to disable the player from using/openning npc and player stores. disable_skill_usage | Ability to disable the player from using any skill. +bypass_nostorage | Ability to bypass the nostorage and nogstorage mapflag. diff --git a/doc/script_commands.txt b/doc/script_commands.txt index 90d4d77cc..4d2517efa 100644 --- a/doc/script_commands.txt +++ b/doc/script_commands.txt @@ -5693,6 +5693,10 @@ storage window, to avoid any disruption when both windows overlap. openstorage(); end; +The mapflag 'nostorage' when set to type '2' (or 3), will not open the +account storage. Unless the character group has the permission 'bypass_nostorage'. +In case blocked by mapflag, returns 0. + --------------------------------------- *openmail() @@ -5754,6 +5758,10 @@ time. This will also fail and return 2 if the attached character does not belong to any guild. +The mapflag 'nogstorage' when set to type '2' (or 3), will not open the +guild storage. Unless the character group has the permission 'bypass_nostorage'. +In case blocked by mapflag, returns 1. + --------------------------------------- *guildchangegm(, ) @@ -8160,6 +8168,7 @@ Valid are: PERM_DISABLE_STORE PERM_DISABLE_EXP PERM_DISABLE_SKILL_USAGE + PERM_BYPASS_NOSTORAGE Example: -- cgit v1.2.3-70-g09d2 From 7b48fee4ffd90913e2beac51e0bed958129dd3e7 Mon Sep 17 00:00:00 2001 From: AnnieRuru Date: Sun, 27 Jan 2019 21:21:01 +0800 Subject: Add F_MesItemInfo function to show item name with description link also fix OldGlastHeim ITEMLINK display incorrectly --- doc/script_commands.txt | 10 +++++++++- npc/other/Global_Functions.txt | 23 ++++++++++++++++++++++- npc/re/instances/OldGlastHeim.txt | 4 ++-- 3 files changed, 33 insertions(+), 4 deletions(-) (limited to 'doc') diff --git a/doc/script_commands.txt b/doc/script_commands.txt index 26a4fbfb8..0e3e89df8 100644 --- a/doc/script_commands.txt +++ b/doc/script_commands.txt @@ -1228,7 +1228,7 @@ you have to set it back to black unless you want all the rest of the text be in that color: mes("This is ^FF0000 red ^000000 and this is ^00FF00 green, ^000000 so."); - mes(callfunc("F_MesColor", C_BLUE) +"This message is now in BLUE"); + mesf("%sThis message is now in BLUE.", F_MesColor(C_BLUE)); Notice that the text coloring is handled purely by the client. If you use non-English characters, the color codes might get screwed if they stick to @@ -1252,6 +1252,14 @@ This will allow you to visit 'Google' with the in-game browser using default dim Clicking 'Bing!' will open the in-game browser using the specified dimensions. (800x600) +If you're using client from 2013-01-30 onwards, you can also use to show +the item's description. Gravity changed this into since 2015-07-29 onwards. + + mes("Bring me an Apple512."); + mesf("Bring me an %s.", F_MesItemInfo(Apple)); + +This will show the item name and a clickable link for the item description. + --------------------------------------- *mesf(""{, {, {, ...}}}) diff --git a/npc/other/Global_Functions.txt b/npc/other/Global_Functions.txt index 904ed7165..d45b3c3e7 100644 --- a/npc/other/Global_Functions.txt +++ b/npc/other/Global_Functions.txt @@ -434,7 +434,7 @@ function script F_ShuffleNumbers { //== Function F_MesColor =================================== // Function to colorize npc dialog without having to memorize the color code // Examples: -// mes callfunc("F_MesColor", C_BLUE) +"This message is now in BLUE"; +// mesf("%sThis message is now in BLUE.", F_MesColor(C_BLUE)); function script F_MesColor { return sprintf("^%06X", min(getarg(0), 0xFFFFFF)); } @@ -475,3 +475,24 @@ function script F_GetTradeRestriction { .@trade$ += "NoAuction|"; } } + +//== Function F_MesItemInfo =================================== +// Show the item name and a clickable link for the item description +// Only works with mes and mesf, does not work in menu/select +function script F_MesItemInfo { + .@item = getarg(0); + .@itemname$ = getitemname(.@item); + if (.@itemname$ != "null") { + .@itemslot = getitemslots(.@item); + if (.@itemslot) + .@itemname$ = sprintf("%s [%d]", .@itemname$, .@itemslot); + } + else + .@itemname$ = "Unknown Item"; + if (PACKETVER >= 20150729) + return sprintf("%s%d", .@itemname$, .@item); + else if (PACKETVER >= 20130130) + return sprintf("%s%d", .@itemname$, .@item); + else + return .@itemname$; +} diff --git a/npc/re/instances/OldGlastHeim.txt b/npc/re/instances/OldGlastHeim.txt index 44b5f1e61..ec0efeb53 100644 --- a/npc/re/instances/OldGlastHeim.txt +++ b/npc/re/instances/OldGlastHeim.txt @@ -2744,7 +2744,7 @@ glast_01,188,273,5 script White Knight#1a 4_WHITEKNIGHT,{ close(); } mes("I exchange you a White Knight Card for ^0000FF3000 Coagulated Spell^000000 or ^FF000070 Contaminated Magic^000000."); - mes("White Knight Card4608"); + mes(F_MesItemInfo(White_Knightage_Card)); next(); setarray(.@item[0], Coagulated_Spell, Corrupted_Charm); setarray(.@cost[0], 3000, 70); @@ -2777,7 +2777,7 @@ glast_01,192,273,3 script Khalitzburg Knight#1a 4_F_KHALITZBURG,{ close(); } mes("I exchange you a Khalitzburg Knight Card for ^0000FF5000 Coagulated Spell^000000 or ^FF0000100 Contaminated Magic^000000."); - mes("Khalitzburg Knight Card4609"); + mes(F_MesItemInfo(Khali_Knightage_Card)); next(); setarray(.@item[0], Coagulated_Spell, Corrupted_Charm); setarray(.@cost[0], 5000, 100); -- cgit v1.2.3-70-g09d2 From 9fa9bddbbdbdb7a81b68cc9c8bc05da1efb0f68d Mon Sep 17 00:00:00 2001 From: AnnieRuru Date: Wed, 6 Feb 2019 13:46:49 +0800 Subject: Add new server define constant MAX_ITEM_ID --- doc/script_commands.txt | 1 + src/map/script.c | 1 + 2 files changed, 2 insertions(+) (limited to 'doc') diff --git a/doc/script_commands.txt b/doc/script_commands.txt index db851128f..c7ef18fc4 100644 --- a/doc/script_commands.txt +++ b/doc/script_commands.txt @@ -716,6 +716,7 @@ MAX_BANK_ZENY - Maximum Zeny in the bank MAX_BG_MEMBERS - Maximum BattleGround members MAX_CHAT_USERS - Maximum Chat users MAX_REFINE - Maximum Refine level +MAX_ITEM_ID - Maximum Item ID MAX_MENU_OPTIONS - Maximum NPC menu options MAX_MENU_LENGTH - Maximum NPC menu string length diff --git a/src/map/script.c b/src/map/script.c index be591a3ae..468ef322c 100644 --- a/src/map/script.c +++ b/src/map/script.c @@ -25843,6 +25843,7 @@ static void script_hardcoded_constants(void) script->set_constant("MAX_BG_MEMBERS",MAX_BG_MEMBERS,false, false); script->set_constant("MAX_CHAT_USERS",MAX_CHAT_USERS,false, false); script->set_constant("MAX_REFINE",MAX_REFINE,false, false); + script->set_constant("MAX_ITEM_ID",MAX_ITEM_ID,false, false); script->set_constant("MAX_MENU_OPTIONS", MAX_MENU_OPTIONS, false, false); script->set_constant("MAX_MENU_LENGTH", MAX_MENU_LENGTH, false, false); -- cgit v1.2.3-70-g09d2 From 76a336eea15b0af70ebe4d3dd13b25f1f503e03c Mon Sep 17 00:00:00 2001 From: AnnieRuru Date: Tue, 26 Feb 2019 17:51:04 +0800 Subject: Add missing documentation for disable battleground respawn - fix a minor bug that bg_create_team should return -1, as mentioned in doc/script_commands.txt --- doc/script_commands.txt | 7 +++++++ src/map/script.c | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) (limited to 'doc') diff --git a/doc/script_commands.txt b/doc/script_commands.txt index db851128f..b74a231d3 100644 --- a/doc/script_commands.txt +++ b/doc/script_commands.txt @@ -9616,6 +9616,11 @@ is run when they relog. refers to an NPC label that attaches to the character and is run when they die. Can be "" for empty. +If "-" is supplied for , this will remove the 1 second automatic +respawn on the battleground map. This allows for better manipulation of +. The player will have to be warped to desired location +at the end of . + Unlike the prior command, the latter will attach a GROUP in a waiting room to the battleground, and sets the array $@arenamembers[0] where 0 holds the IDs of the first group, and 1 holds the IDs of the second. @@ -9747,6 +9752,8 @@ mapflag%TAB%%TAB%battleground%TAB%2 This command will create a new BG Team. When player dies, they will be respawned map_name,X,Y as mentioned. +If "-" is supplied for the map name, this will remove the 1 second automatic +respawn on the battleground map. Command will return -1 if BG Creation is failed, else it will return the BG ID(Also known as TeamID). diff --git a/src/map/script.c b/src/map/script.c index 7578fcdcc..8096ec471 100644 --- a/src/map/script.c +++ b/src/map/script.c @@ -23687,7 +23687,7 @@ static BUILDIN(bg_create_team) if( strcmp(map_name,"-") != 0 ) { map_index = script->mapindexname2id(st,map_name); if( map_index == 0 ) { // Invalid Map - script_pushint(st,0); + script_pushint(st, -1); return true; } } -- cgit v1.2.3-70-g09d2 From c8e10d633d67b0ba0ff9d07d8521390a54aa63a3 Mon Sep 17 00:00:00 2001 From: AnnieRuru Date: Tue, 26 Feb 2019 21:25:51 +0800 Subject: Add MOB_CLONE_START & MOB_CLONE_END to server defined constants --- doc/script_commands.txt | 2 ++ src/map/script.c | 2 ++ 2 files changed, 4 insertions(+) (limited to 'doc') diff --git a/doc/script_commands.txt b/doc/script_commands.txt index db851128f..71a370832 100644 --- a/doc/script_commands.txt +++ b/doc/script_commands.txt @@ -718,6 +718,8 @@ MAX_CHAT_USERS - Maximum Chat users MAX_REFINE - Maximum Refine level MAX_MENU_OPTIONS - Maximum NPC menu options MAX_MENU_LENGTH - Maximum NPC menu string length +MOB_CLONE_START - Clone ID start from this range +MOB_CLONE_END - Clone ID end with this range Send targets and status options are also hard-coded and can be found in 'doc/constants.md'. diff --git a/src/map/script.c b/src/map/script.c index 7578fcdcc..013455c71 100644 --- a/src/map/script.c +++ b/src/map/script.c @@ -25845,6 +25845,8 @@ static void script_hardcoded_constants(void) script->set_constant("MAX_REFINE",MAX_REFINE,false, false); script->set_constant("MAX_MENU_OPTIONS", MAX_MENU_OPTIONS, false, false); script->set_constant("MAX_MENU_LENGTH", MAX_MENU_LENGTH, false, false); + script->set_constant("MOB_CLONE_START", MOB_CLONE_START, false, false); + script->set_constant("MOB_CLONE_END", MOB_CLONE_END, false, false); script->constdb_comment("status options"); script->set_constant("Option_Nothing",OPTION_NOTHING,false, false); -- cgit v1.2.3-70-g09d2 From c85d0d32a3674551a6b2f74029572e8eb6d0a0f4 Mon Sep 17 00:00:00 2001 From: AnnieRuru Date: Wed, 27 Feb 2019 02:32:58 +0800 Subject: Deprecate UDT_MAPIDXY constant - use *unitwarp for setunitdata - use *getmapxy for getunitdata --- db/constants.conf | 5 ++++- doc/script_commands.txt | 2 -- 2 files changed, 4 insertions(+), 3 deletions(-) (limited to 'doc') diff --git a/db/constants.conf b/db/constants.conf index 598bc89c4..6b541c9de 100644 --- a/db/constants.conf +++ b/db/constants.conf @@ -3853,7 +3853,10 @@ constants_db: { UDT_MAXSP: 6 UDT_MASTERAID: 7 UDT_MASTERCID: 8 - UDT_MAPIDXY: 9 + UDT_MAPIDXY: { + Value: 9 + Deprecated: true // for setunitdata use *unitwarp, for getunitdata use *getmapxy + } UDT_WALKTOXY: 10 UDT_SPEED: 11 UDT_MODE: 12 diff --git a/doc/script_commands.txt b/doc/script_commands.txt index db851128f..a0fac8f9b 100644 --- a/doc/script_commands.txt +++ b/doc/script_commands.txt @@ -10048,7 +10048,6 @@ Applicable Data Types (available as constants) - UDT_MAXSP: MAX SP (int) UDT_MASTERAID: Master Account ID (for Summons) (int) UDT_MASTERCID: Master Char ID (for Summons) (int) - UDT_MAPIDXY: Warp a Unit to a map. (Val1 = (string) MapName, Val2 = (int) x, Val3 = (int) y) UDT_WALKTOXY: Make a unit walk to certain co-ordinates. (Val1 = (int) x, Val2 = (int) y) UDT_SPEED: Unit Speed. (int) UDT_MODE: Mode (Mobs only) (int) @@ -10114,7 +10113,6 @@ Applicable Data types (available as constants) - UDT_MAXSP: MAX SP (int) UDT_MASTERAID: Master Account ID (for Summons) (int) UDT_MASTERCID: Master Char ID (for Summons) (int) - UDT_MAPIDXY: Warp a Unit to a map. (Val1 = (string) MapName, Val2 = (int) x, Val3 = (int) y) UDT_SPEED: Unit Speed. (int) UDT_MODE: Mode (Mobs only) (int) UDT_AI: Unit AI Type (see doc/constants.md for Unit AI Types) -- cgit v1.2.3-70-g09d2 From 94db964dab27c4572671aa1b486398573e86cce5 Mon Sep 17 00:00:00 2001 From: AnnieRuru Date: Wed, 27 Feb 2019 02:34:07 +0800 Subject: Deprecate UDT_WALKTOXY constant - this constant only used by *setunitdata, now has to use *unitwalk --- db/constants.conf | 5 ++++- doc/script_commands.txt | 1 - 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'doc') diff --git a/db/constants.conf b/db/constants.conf index 6b541c9de..2e379cb14 100644 --- a/db/constants.conf +++ b/db/constants.conf @@ -3857,7 +3857,10 @@ constants_db: { Value: 9 Deprecated: true // for setunitdata use *unitwarp, for getunitdata use *getmapxy } - UDT_WALKTOXY: 10 + UDT_WALKTOXY: { + Value: 10 + Deprecated: true // use *unitwalk + } UDT_SPEED: 11 UDT_MODE: 12 UDT_AI: 13 diff --git a/doc/script_commands.txt b/doc/script_commands.txt index a0fac8f9b..cc8ff6fe5 100644 --- a/doc/script_commands.txt +++ b/doc/script_commands.txt @@ -10048,7 +10048,6 @@ Applicable Data Types (available as constants) - UDT_MAXSP: MAX SP (int) UDT_MASTERAID: Master Account ID (for Summons) (int) UDT_MASTERCID: Master Char ID (for Summons) (int) - UDT_WALKTOXY: Make a unit walk to certain co-ordinates. (Val1 = (int) x, Val2 = (int) y) UDT_SPEED: Unit Speed. (int) UDT_MODE: Mode (Mobs only) (int) UDT_AI: Unit AI Type (see doc/constants.md for Unit AI Types) -- cgit v1.2.3-70-g09d2 From 98ae816147a28ce98676b92a41d42be65365ff31 Mon Sep 17 00:00:00 2001 From: AnnieRuru Date: Thu, 28 Feb 2019 01:16:07 +0800 Subject: * Remove all the (int) in the documentation - once all the strings culprit are out, now only left with int to deal with. - Please make this script command only dealing with ONE INTEGER value --- doc/script_commands.txt | 201 ++++++++++++++++++++++++------------------------ src/map/script.c | 12 ++- 2 files changed, 110 insertions(+), 103 deletions(-) (limited to 'doc') diff --git a/doc/script_commands.txt b/doc/script_commands.txt index cc8ff6fe5..8ec0c76b8 100644 --- a/doc/script_commands.txt +++ b/doc/script_commands.txt @@ -10033,128 +10033,127 @@ Returns the amount of still-available in the shop (on a NST_MARKET tra --------------------------------------- -*setunitdata(, , {,,}) +*setunitdata(, , ) Sets or alters the data in real-time for game objects of the following types - NPCs, Pets, Monsters, Homunuculus', Mercenaries, Elementals. Applicable Data Types (available as constants) - Data Types Description (parameter type) - UDT_SIZE: Unit Size (int) - UDT_LEVEL: Level (int) - UDT_HP: Current HP (int) - UDT_MAXHP: Max HP (int) - UDT_SP: SP (int) - UDT_MAXSP: MAX SP (int) - UDT_MASTERAID: Master Account ID (for Summons) (int) - UDT_MASTERCID: Master Char ID (for Summons) (int) - UDT_SPEED: Unit Speed. (int) - UDT_MODE: Mode (Mobs only) (int) + UDT_SIZE: Unit Size + UDT_LEVEL: Level + UDT_HP: Current HP + UDT_MAXHP: Max HP + UDT_SP: SP + UDT_MAXSP: MAX SP + UDT_MASTERAID: Master Account ID (for Summons) + UDT_MASTERCID: Master Char ID (for Summons) + UDT_SPEED: Unit Speed. + UDT_MODE: Mode (Mobs only) UDT_AI: Unit AI Type (see doc/constants.md for Unit AI Types) UDT_SCOPTION: Status Options. (see doc/constants.md for Unit Option Types) UDT_SEX: Gender of the unit. (see doc/constants.md for Genders) - UDT_CLASS: Class of the unit. (Monster ID) (int) - UDT_HAIRSTYLE: Hair Style ID. (int) - UDT_HAIRCOLOR: Hair Color ID. (int) - UDT_HEADBOTTOM: Headgear Bottom Sprite ID. (int) - UDT_HEADMIDDLE: Headgear Middle Sprite ID. (int) - UDT_HEADTOP: Headgear Top Sprite ID. (int) - UDT_CLOTHCOLOR: Cloth Color ID. (int) - UDT_SHIELD: Shield Sprite ID. (int) - UDT_WEAPON: Weapon Sprite ID. (int) - UDT_LOOKDIR: Face direction. (int) - UDT_CANMOVETICK: Stop a unit from move for n seconds. (int) - UDT_STR: Unit STR. (int) - UDT_AGI: Unit AGI. (int) - UDT_VIT: Unit VIT. (int) - UDT_INT: Unit INT. (int) - UDT_DEX: Unit DEX. (int) - UDT_LUK: Unit LUK. (int) - UDT_ATKRANGE: Attack range of a unit. (int) - UDT_ATKMIN: Min Atk of a unit. (int) - UDT_ATKMAX: Max Atk of a unit. (int) - UDT_MATKMIN: Min MATK of a unit. (int) - UDT_MATKMAX: Max MATK of a unit. (int) - UDT_DEF: DEF. (int) - UDT_MDEF: MDEF. (int) - UDT_HIT: HIT. (int) - UDT_FLEE: FLEE. (int) - UDT_PDODGE: Perfect Dodge. (int) - UDT_CRIT: Critical Rate. (int) - UDT_RACE: Race. (Eg. string constants RC_DemiHuman or Integer 7). - UDT_ELETYPE: Element. (Eg. string constants Ele_Neutral or Integer 0). - UDT_ELELEVEL: Element Level (int). - UDT_AMOTION: AMotion Rate (int). - UDT_ADELAY: ADelay Rate (int). - UDT_DMOTION: DMotion Rate (int). - UDT_HUNGER: Hunger Rate (int) - for summons. - UDT_INTIMACY: Intimacy Rate (int) - for summons. - UDT_LIFETIME: LifeTime (int) - for summons. - UDT_MERC_KILLCOUNT: Kill count for mercenaries (int). - UDT_STATADD: Status Points (int) - for NPCs. + UDT_CLASS: Class of the unit. (Monster ID) + UDT_HAIRSTYLE: Hair Style ID. + UDT_HAIRCOLOR: Hair Color ID. + UDT_HEADBOTTOM: Headgear Bottom Sprite ID. + UDT_HEADMIDDLE: Headgear Middle Sprite ID. + UDT_HEADTOP: Headgear Top Sprite ID. + UDT_CLOTHCOLOR: Cloth Color ID. + UDT_SHIELD: Shield Sprite ID. + UDT_WEAPON: Weapon Sprite ID. + UDT_LOOKDIR: Face direction. + UDT_CANMOVETICK: Stop a unit from move for n seconds. + UDT_STR: Unit STR. + UDT_AGI: Unit AGI. + UDT_VIT: Unit VIT. + UDT_INT: Unit INT. + UDT_DEX: Unit DEX. + UDT_LUK: Unit LUK. + UDT_ATKRANGE: Attack range of a unit. + UDT_ATKMIN: Min Atk of a unit. + UDT_ATKMAX: Max Atk of a unit. + UDT_MATKMIN: Min MATK of a unit. + UDT_MATKMAX: Max MATK of a unit. + UDT_DEF: DEF. + UDT_MDEF: MDEF. + UDT_HIT: HIT. + UDT_FLEE: FLEE. + UDT_PDODGE: Perfect Dodge. + UDT_CRIT: Critical Rate. + UDT_RACE: Race. (Eg. constants RC_DemiHuman or Integer 7). + UDT_ELETYPE: Element. (Eg. constants Ele_Neutral or Integer 0). + UDT_ELELEVEL: Element Level. + UDT_AMOTION: AMotion Rate. + UDT_ADELAY: ADelay Rate. + UDT_DMOTION: DMotion Rate. + UDT_HUNGER: Hunger Rate - for summons. + UDT_INTIMACY: Intimacy Rate - for summons. + UDT_LIFETIME: LifeTime - for summons. + UDT_MERC_KILLCOUNT: Kill count for mercenaries + UDT_STATADD: Status Points - for NPCs. returns 0 if value could not be set, 1 if successful. --------------------------------------- -*getunitdata (,{,}) +*getunitdata (,) -Retrieves real-time data of a game object. For data with multiple return values, -an array variable may be passed to store the data in. +Retrieves real-time data of a game object. Applicable Data types (available as constants) - Data Types Description (return type) - UDT_SIZE: Unit Size (int) - UDT_LEVEL: Level (int) - UDT_HP: Current HP (int) - UDT_MAXHP: Max HP (int) - UDT_SP: SP (int) - UDT_MAXSP: MAX SP (int) - UDT_MASTERAID: Master Account ID (for Summons) (int) - UDT_MASTERCID: Master Char ID (for Summons) (int) - UDT_SPEED: Unit Speed. (int) - UDT_MODE: Mode (Mobs only) (int) + UDT_SIZE: Unit Size + UDT_LEVEL: Level + UDT_HP: Current HP + UDT_MAXHP: Max HP + UDT_SP: SP + UDT_MAXSP: MAX SP + UDT_MASTERAID: Master Account ID (for Summons) + UDT_MASTERCID: Master Char ID (for Summons) + UDT_SPEED: Unit Speed. + UDT_MODE: Mode (Mobs only) UDT_AI: Unit AI Type (see doc/constants.md for Unit AI Types) UDT_SCOPTION: Status Options. (see doc/constants.md for Unit Option Types) UDT_SEX: Gender of the unit. (see doc/constants.md for Genders) - UDT_CLASS: Class of the unit. (Monster ID) (int) - UDT_HAIRSTYLE: Hair Style ID. (int) - UDT_HAIRCOLOR: Hair Color ID. (int) - UDT_HEADBOTTOM: Headgear Bottom Sprite ID. (int) - UDT_HEADMIDDLE: Headgear Middle Sprite ID. (int) - UDT_HEADTOP: Headgear Top Sprite ID. (int) - UDT_CLOTHCOLOR: Cloth Color ID. (int) - UDT_SHIELD: Shield Sprite ID. (int) - UDT_WEAPON: Weapon Sprite ID. (int) - UDT_LOOKDIR: Face direction. (int) - UDT_CANMOVETICK: Stop a unit from move for n seconds. (int) - UDT_STR: Unit STR. (int) - UDT_AGI: Unit AGI. (int) - UDT_VIT: Unit VIT. (int) - UDT_INT: Unit INT. (int) - UDT_DEX: Unit DEX. (int) - UDT_LUK: Unit LUK. (int) - UDT_ATKRANGE: Attack range of a unit. (int) - UDT_ATKMIN: Min Atk of a unit. (int) - UDT_ATKMAX: Max Atk of a unit. (int) - UDT_MATKMIN: Min MATK of a unit. (int) - UDT_MATKMAX: Max MATK of a unit. (int) - UDT_DEF: DEF. (int) - UDT_MDEF: MDEF. (int) - UDT_HIT: HIT. (int) - UDT_FLEE: FLEE. (int) - UDT_PDODGE: Perfect Dodge. (int) - UDT_CRIT: Critical Rate. (int) - UDT_RACE: Race. (Eg. string constants RC_DemiHuman or Integer 7). - UDT_ELETYPE: Element. (Eg. string constants Ele_Neutral or Integer 0). - UDT_ELELEVEL: Element Level (int). - UDT_AMOTION: AMotion Rate (int). - UDT_ADELAY: ADelay Rate (int). - UDT_DMOTION: DMotion Rate (int). - UDT_HUNGER: Hunger Rate (int) - for summons. - UDT_INTIMACY: Intimacy Rate (int) - for summons. - UDT_LIFETIME: LifeTime (int) - for summons. - UDT_MERC_KILLCOUNT: Kill count for mercenaries (int). + UDT_CLASS: Class of the unit. (Monster ID) + UDT_HAIRSTYLE: Hair Style ID. + UDT_HAIRCOLOR: Hair Color ID. + UDT_HEADBOTTOM: Headgear Bottom Sprite ID. + UDT_HEADMIDDLE: Headgear Middle Sprite ID. + UDT_HEADTOP: Headgear Top Sprite ID. + UDT_CLOTHCOLOR: Cloth Color ID. + UDT_SHIELD: Shield Sprite ID. + UDT_WEAPON: Weapon Sprite ID. + UDT_LOOKDIR: Face direction. + UDT_CANMOVETICK: Stop a unit from move for n seconds. + UDT_STR: Unit STR. + UDT_AGI: Unit AGI. + UDT_VIT: Unit VIT. + UDT_INT: Unit INT. + UDT_DEX: Unit DEX. + UDT_LUK: Unit LUK. + UDT_ATKRANGE: Attack range of a unit. + UDT_ATKMIN: Min Atk of a unit. + UDT_ATKMAX: Max Atk of a unit. + UDT_MATKMIN: Min MATK of a unit. + UDT_MATKMAX: Max MATK of a unit. + UDT_DEF: DEF. + UDT_MDEF: MDEF. + UDT_HIT: HIT. + UDT_FLEE: FLEE. + UDT_PDODGE: Perfect Dodge. + UDT_CRIT: Critical Rate. + UDT_RACE: Race. (Eg. constants RC_DemiHuman or Integer 7). + UDT_ELETYPE: Element. (Eg. constants Ele_Neutral or Integer 0). + UDT_ELELEVEL: Element Level. + UDT_AMOTION: AMotion Rate. + UDT_ADELAY: ADelay Rate. + UDT_DMOTION: DMotion Rate. + UDT_HUNGER: Hunger Rate - for summons. + UDT_INTIMACY: Intimacy Rate - for summons. + UDT_LIFETIME: LifeTime - for summons. + UDT_MERC_KILLCOUNT: Kill count for mercenaries. returns 0 if value could not be retrieved. diff --git a/src/map/script.c b/src/map/script.c index 7578fcdcc..02afc0219 100644 --- a/src/map/script.c +++ b/src/map/script.c @@ -18636,6 +18636,10 @@ static BUILDIN(getunittype) * @param4 Value#2 Optional int value to be passed for certain data types. * @param5 Value#3 Optional int value to be passed for certain data types. * @return 1 on success, 0 on failure. + + Note: Please make this script command only modify ONE INTEGER value. + If need to modify string type data, or having multiple arguments, please + introduce a new script command. */ static BUILDIN(setunitdata) { @@ -18661,7 +18665,7 @@ static BUILDIN(setunitdata) return false; } - /* Mandatory Argument 3 */ + /* Mandatory Argument 3. Subject to deprecate. */ if (type == UDT_MAPIDXY) { if (!script_isstringtype(st, 4)) { ShowError("buildin_setunitdata: Invalid data type for argument #3.\n"); @@ -19753,6 +19757,10 @@ static BUILDIN(setunitdata) * @param2 DataType Type of Data to be set for the unit. * @param3 Variable array reference to store data into. (used for UDT_MAPIDXY) * @return 0 on failure, on success + + Note: Please make this script command only return ONE INTEGER value. + If the unit data having multiple arguments, or need to return in array, + please introduce a new script command. */ static BUILDIN(getunitdata) { @@ -19780,7 +19788,7 @@ static BUILDIN(getunitdata) return false; } - /* Argument checks */ + /* Argument checks. Subject to deprecate */ if (type == UDT_MAPIDXY) { if (data == NULL || !data_isreference(data)) { ShowWarning("buildin_getunitdata: Error in argument 3. Please provide a reference variable to store values in.\n"); -- cgit v1.2.3-70-g09d2 From 433fd264ece900b8c563946737bbd4a73933c50a Mon Sep 17 00:00:00 2001 From: AnnieRuru Date: Sat, 2 Mar 2019 17:34:11 +0800 Subject: * Add *mobattached and *killmonstergid script command also fix quests_rachel, now support with *unitemote --- doc/script_commands.txt | 23 +++++++++++++++++++++-- npc/quests/quests_rachel.txt | 2 +- src/map/script.c | 29 +++++++++++++++++++++++++++++ 3 files changed, 51 insertions(+), 3 deletions(-) (limited to 'doc') diff --git a/doc/script_commands.txt b/doc/script_commands.txt index c3cc8a799..a4b9ec717 100644 --- a/doc/script_commands.txt +++ b/doc/script_commands.txt @@ -266,8 +266,8 @@ direction across Y. Walking into that area will trigger the NPC. If no 'OnTouch:' special label is present in the NPC code, the execution will start from the beginning of the script, otherwise, it will start from the 'OnTouch:' label. Monsters can also trigger the NPC, though the label -'OnTouchNPC:' is used in this case. If player left area npc will called -if present label 'OnUnTouch'. +'OnTouchNPC:' is used in this case, and using mobattached() will return +monster GID. If player left the area will trigger the label 'OnUnTouch'. The code part is the script code that will execute whenever the NPC is triggered. It may contain commands and function calls, descriptions of @@ -6505,6 +6505,14 @@ other number for this parameter won't be recognized. --------------------------------------- +*killmonstergid(); + +This command will kill the specific monster GID. The difference between +this command and 'unitkill', is this command does not trigger monster's +event label. + +--------------------------------------- + *strmobinfo(, ) This function will return information about a monster record in the @@ -6593,6 +6601,17 @@ will run as if by donpcevent(). --------------------------------------- +*mobattached() + +This command will return RID of the monster running from 'OnTouchNPC:' label. + + +// Kill any monster entering npc's trigger area +OnTouchNPC: + killmonstergid mobattached(); + +--------------------------------------- + *homevolution() This command will try to evolve the current player's homunculus. diff --git a/npc/quests/quests_rachel.txt b/npc/quests/quests_rachel.txt index 43e4beadb..1cc002d80 100644 --- a/npc/quests/quests_rachel.txt +++ b/npc/quests/quests_rachel.txt @@ -3210,7 +3210,7 @@ OnTouch: OnTouchNPC: emotion e_an; - //emotion e_gg,1; //Emote on monster - unsupported + unitemote mobattached(), e_gg; end; OnMyMobDead: diff --git a/src/map/script.c b/src/map/script.c index 7e6e06376..736b442cc 100644 --- a/src/map/script.c +++ b/src/map/script.c @@ -11095,6 +11095,21 @@ static BUILDIN(killmonsterall) return true; } +static BUILDIN(killmonstergid) +{ + int mobgid = script_getnum(st, 2); + struct mob_data *md = map->id2md(mobgid); + + if (md == NULL) { + ShowWarning("buildin_killmonstergid: Error in finding monster GID '%d' or the target is not a monster.\n", mobgid); + return false; + } + + md->state.npc_killmonster = 1; + status_kill(&md->bl); + return true; +} + /*========================================== * Creates a clone of a player. * clone map, x, y, event, char_id, master_id, mode, flag, duration @@ -11729,6 +11744,18 @@ static BUILDIN(playerattached) return true; } +/*========================================== + * Used by OnTouchNPC: label to return monster GID + *------------------------------------------*/ +static BUILDIN(mobattached) +{ + if (st->rid == 0 || map->id2md(st->rid) == NULL) + script_pushint(st, 0); + else + script_pushint(st, st->rid); + return true; +} + /*========================================== *------------------------------------------*/ static BUILDIN(announce) @@ -25338,6 +25365,7 @@ static void script_parse_builtin(void) BUILDIN_DEF(areamonster,"siiiisii???"), BUILDIN_DEF(killmonster,"ss?"), BUILDIN_DEF(killmonsterall,"s?"), + BUILDIN_DEF(killmonstergid, "i"), BUILDIN_DEF(clone,"siisi????"), BUILDIN_DEF(doevent,"s"), BUILDIN_DEF(donpcevent,"s"), @@ -25354,6 +25382,7 @@ static void script_parse_builtin(void) BUILDIN_DEF(attachnpctimer,"?"), // attached the player id to the npc timer [Celest] BUILDIN_DEF(detachnpctimer,"?"), // detached the player id from the npc timer [Celest] BUILDIN_DEF(playerattached,""), // returns id of the current attached player. [Skotlex] + BUILDIN_DEF(mobattached, ""), BUILDIN_DEF(announce,"si?????"), BUILDIN_DEF(mapannounce,"ssi?????"), BUILDIN_DEF(areaannounce,"siiiisi?????"), -- cgit v1.2.3-70-g09d2 From 3b2fffae9f65bf064f7ab66a697196fd75550127 Mon Sep 17 00:00:00 2001 From: "Hercules.ws" Date: Sat, 2 Mar 2019 20:04:59 +0100 Subject: Constants Documentation Sync Signed-off-by: HerculesWSAPI --- doc/constants.md | 2 ++ 1 file changed, 2 insertions(+) (limited to 'doc') diff --git a/doc/constants.md b/doc/constants.md index 8b3acbfdf..69bb51ea4 100644 --- a/doc/constants.md +++ b/doc/constants.md @@ -3991,6 +3991,8 @@ - `MAX_REFINE`: 20 - `MAX_MENU_OPTIONS`: 255 - `MAX_MENU_LENGTH`: 2048 +- `MOB_CLONE_START`: 4001 +- `MOB_CLONE_END`: 5000 ### status options -- cgit v1.2.3-70-g09d2 From 7893a47d101e6eea5c3bb5abad06190770c65a12 Mon Sep 17 00:00:00 2001 From: AnnieRuru Date: Sun, 3 Mar 2019 19:39:03 +0800 Subject: Fix *needed_status_point not support --- doc/script_commands.txt | 2 +- src/map/script.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'doc') diff --git a/doc/script_commands.txt b/doc/script_commands.txt index c3cc8a799..63aa94315 100644 --- a/doc/script_commands.txt +++ b/doc/script_commands.txt @@ -6074,7 +6074,7 @@ Amount can be negative. See statusup(). --------------------------------------- -*needed_status_point(, , {}); +*needed_status_point(, ); Returns the number of stat points needed to change the specified stat by . If is negative, returns the number of stat points that would be needed to diff --git a/src/map/script.c b/src/map/script.c index 7e6e06376..51d7ebe3b 100644 --- a/src/map/script.c +++ b/src/map/script.c @@ -9720,7 +9720,7 @@ static BUILDIN(statusup2) /*========================================== * Returns the number of stat points needed to change the specified stat by val. -* needed_status_point(,{,}); [secretdataz] +* needed_status_point(,); [secretdataz] *------------------------------------------*/ static BUILDIN(needed_status_point) { @@ -25296,7 +25296,7 @@ static void script_parse_builtin(void) BUILDIN_DEF(downrefitem,"i?"), BUILDIN_DEF(statusup,"i"), BUILDIN_DEF(statusup2,"ii"), - BUILDIN_DEF(needed_status_point,"ii?"), + BUILDIN_DEF(needed_status_point, "ii"), BUILDIN_DEF(bonus,"iv"), BUILDIN_DEF2(bonus,"bonus2","ivi"), BUILDIN_DEF2(bonus,"bonus3","ivii"), -- cgit v1.2.3-70-g09d2 From 6f7ad82c7a804a224fd8ca405a0ebc4b739dc3e4 Mon Sep 17 00:00:00 2001 From: Dastgir Date: Sat, 9 Mar 2019 21:57:11 +0530 Subject: Expanded getinventorylist: * getinventorylist now creates extra variable named @inventorylist_idx, which returns items corresponding inventory index. --- doc/script_commands.txt | 1 + src/map/script.c | 1 + 2 files changed, 2 insertions(+) (limited to 'doc') diff --git a/doc/script_commands.txt b/doc/script_commands.txt index 5eee3a4e5..30103cd5e 100644 --- a/doc/script_commands.txt +++ b/doc/script_commands.txt @@ -3115,6 +3115,7 @@ invoking character has in its inventory, including all the data needed to recreate these items perfectly if they are destroyed. Here's what you get: @inventorylist_id[] - array of item ids. +@inventorylist_idx[] - array of item inventory index. @inventorylist_amount[] - their corresponding item amounts. @inventorylist_equip[] - will return the slot the item is equipped on, if at all. @inventorylist_refine[] - for how much it is refined. diff --git a/src/map/script.c b/src/map/script.c index 24cb8e4f4..b13e2fb76 100644 --- a/src/map/script.c +++ b/src/map/script.c @@ -14830,6 +14830,7 @@ static BUILDIN(getinventorylist) } pc->setreg(sd,reference_uid(script->add_variable("@inventorylist_expire"), j),sd->status.inventory[i].expire_time); pc->setreg(sd,reference_uid(script->add_variable("@inventorylist_bound"), j),sd->status.inventory[i].bound); + pc->setreg(sd, reference_uid(script->add_variable("@inventorylist_idx"), j), i); j++; } } -- cgit v1.2.3-70-g09d2 From 9e860b0bf7eeeed5e20f9d9e8ddb04c93c93a11f Mon Sep 17 00:00:00 2001 From: AnnieRuru Date: Mon, 11 Mar 2019 04:42:10 +0800 Subject: Add constants and MERCINFO_GID to *getmercinfo script command --- doc/script_commands.txt | 23 +++++++------ src/map/script.c | 91 ++++++++++++++++++++++++++++++++----------------- src/map/script.h | 17 +++++++++ 3 files changed, 88 insertions(+), 43 deletions(-) (limited to 'doc') diff --git a/doc/script_commands.txt b/doc/script_commands.txt index c3cc8a799..04dd9b304 100644 --- a/doc/script_commands.txt +++ b/doc/script_commands.txt @@ -9836,17 +9836,18 @@ If char id is given, the information of that character is retrieved instead. Type specifies what information to retrieve and can be one of the following: - 0 - Database ID - 1 - Class - 2 - Name - 3 - Faith value for this mercenary's guild, if any - 4 - Calls value for this mercenary's guild, if any - 5 - Kill count - 6 - Remaining life time in msec - 7 - Level - -If the character does not have a mercenary, the command returns "" -for name and 0 for all other types. + MERCINFO_ID - Mercenary Database ID + MERCINFO_CLASS - Mercenary Class + MERCINFO_NAME - Mercenary Name + MERCINFO_FAITH - Mercenary faith value for this mercenary's guild, if any + MERCINFO_CALLS - Mercenary calls value for this mercenary's guild, if any + MERCINFO_KILLCOUNT - Mercenary kill count + MERCINFO_LIFETIME - Mercenary remaining life time in mili-second + MERCINFO_LEVEL - Mercenary Level + MERCINFO_GID - Mercenary Game ID + +If the character does not have a mercenary, the command returns "" for MERCINFO_NAME +and 0 for all other types. --------------------------------------- //===================================== diff --git a/src/map/script.c b/src/map/script.c index 7e6e06376..1d281b037 100644 --- a/src/map/script.c +++ b/src/map/script.c @@ -15613,20 +15613,15 @@ static BUILDIN(gethominfo) return true; } -/// Retrieves information about character's mercenary -/// getmercinfo [,]; +/* + * Retrieves information about character's mercenary + * getmercinfo {, }; + */ static BUILDIN(getmercinfo) { - int type; - struct map_session_data* sd; - struct mercenary_data* md; - - type = script_getnum(st,2); - - if (script_hasdata(st,3)) { - int char_id = script_getnum(st,3); - - if ((sd = script->charid2sd(st, char_id)) == NULL) { + struct map_session_data *sd; + if (script_hasdata(st, 3)) { + if ((sd = script->charid2sd(st, script_getnum(st, 3))) == NULL) { script_pushnil(st); return true; } @@ -15635,27 +15630,48 @@ static BUILDIN(getmercinfo) return true; } - md = ( sd->status.mer_id && sd->md ) ? sd->md : NULL; + struct mercenary_data *md = (sd->status.mer_id && sd->md)? sd->md : NULL; + int type = script_getnum(st, 2); + if (md == NULL) { + if (type == MERCINFO_NAME) + script_pushconststr(st, ""); + else + script_pushint(st, 0); + return true; + } - switch( type ) - { - case 0: script_pushint(st,md ? md->mercenary.mercenary_id : 0); break; - case 1: script_pushint(st,md ? md->mercenary.class_ : 0); break; - case 2: - if( md ) - script_pushstrcopy(st,md->db->name); - else - script_pushconststr(st,""); - break; - case 3: script_pushint(st,md ? mercenary->get_faith(md) : 0); break; - case 4: script_pushint(st,md ? mercenary->get_calls(md) : 0); break; - case 5: script_pushint(st,md ? md->mercenary.kill_count : 0); break; - case 6: script_pushint(st,md ? mercenary->get_lifetime(md) : 0); break; - case 7: script_pushint(st,md ? md->db->lv : 0); break; - default: - ShowError("buildin_getmercinfo: Invalid type %d (char_id=%d).\n", type, sd->status.char_id); - script_pushnil(st); - return false; + switch (type) { + case MERCINFO_ID: + script_pushint(st, md->mercenary.mercenary_id); + break; + case MERCINFO_CLASS: + script_pushint(st, md->mercenary.class_); + break; + case MERCINFO_NAME: + script_pushstrcopy(st, md->db->name); + break; + case MERCINFO_FAITH: + script_pushint(st, mercenary->get_faith(md)); + break; + case MERCINFO_CALLS: + script_pushint(st, mercenary->get_calls(md)); + break; + case MERCINFO_KILLCOUNT: + script_pushint(st, md->mercenary.kill_count); + break; + case MERCINFO_LIFETIME: + script_pushint(st, mercenary->get_lifetime(md)); + break; + case MERCINFO_LEVEL: + script_pushint(st, md->db->lv); + break; + case MERCINFO_GID: + script_pushint(st, md->bl.id); + break; + default: + ShowError("buildin_getmercinfo: Invalid type %d (char_id=%d).\n", type, sd->status.char_id); + script_pushnil(st); + return false; } return true; @@ -26116,6 +26132,17 @@ static void script_hardcoded_constants(void) script->set_constant("ITEMINFO_VIEWSPRITE", ITEMINFO_VIEWSPRITE, false, false); script->set_constant("ITEMINFO_TRADE", ITEMINFO_TRADE, false, false); + script->constdb_comment("getmercinfo options"); + script->set_constant("MERCINFO_ID,", MERCINFO_ID, false, false); + script->set_constant("MERCINFO_CLASS", MERCINFO_CLASS, false, false); + script->set_constant("MERCINFO_NAME", MERCINFO_NAME, false, false); + script->set_constant("MERCINFO_FAITH", MERCINFO_FAITH, false, false); + script->set_constant("MERCINFO_CALLS", MERCINFO_CALLS, false, false); + script->set_constant("MERCINFO_KILLCOUNT", MERCINFO_KILLCOUNT, false, false); + script->set_constant("MERCINFO_LIFETIME", MERCINFO_LIFETIME, false, false); + script->set_constant("MERCINFO_LEVEL", MERCINFO_LEVEL, false, false); + script->set_constant("MERCINFO_GID", MERCINFO_GID, false, false); + script->constdb_comment("monster skill states"); script->set_constant("MSS_ANY", MSS_ANY, false, false); script->set_constant("MSS_IDLE", MSS_IDLE, false, false); diff --git a/src/map/script.h b/src/map/script.h index 549ad3284..54c5aad2a 100644 --- a/src/map/script.h +++ b/src/map/script.h @@ -460,6 +460,23 @@ enum script_iteminfo_types { ITEMINFO_MAX }; +/** + * Mercenary Info types. + */ +enum script_mercinfo_types { + MERCINFO_ID = 0, + MERCINFO_CLASS, + MERCINFO_NAME, + MERCINFO_FAITH, + MERCINFO_CALLS, + MERCINFO_KILLCOUNT, + MERCINFO_LIFETIME, + MERCINFO_LEVEL, + MERCINFO_GID, + + MERCINFO_MAX +}; + /** * Player blocking actions related flags. */ -- cgit v1.2.3-70-g09d2 From c9bab971082b3dbd059391a699b9e7d3eb25835b Mon Sep 17 00:00:00 2001 From: AnnieRuru Date: Mon, 11 Mar 2019 05:00:47 +0800 Subject: Minor fix a typo in the documentation thanks to https://github.com/rathena/rathena/pull/3951#discussion_r263220245 --- doc/script_commands.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'doc') diff --git a/doc/script_commands.txt b/doc/script_commands.txt index 5eee3a4e5..55f5a9fe7 100644 --- a/doc/script_commands.txt +++ b/doc/script_commands.txt @@ -6334,7 +6334,7 @@ Examples: setpcblock(PCBLOCK_ATTACK|PCBLOCK_SKILL, true); // Re-enables attack, skills and item use - setpcblock(PCBLOCK_ATTACK|PCBLOCK_SKILL|PCBLOCK_ITEM, false); + setpcblock(PCBLOCK_ATTACK|PCBLOCK_SKILL|PCBLOCK_USEITEM, false); // checkpcblock related checks if ((checkpcblock() & PCBLOCK_IMMUNE) != 0) -- cgit v1.2.3-70-g09d2 From ca315dcb6f8ba435beedc9c1a5bff12194bccc72 Mon Sep 17 00:00:00 2001 From: "Hercules.ws" Date: Mon, 11 Mar 2019 00:59:16 +0100 Subject: Constants Documentation Sync Signed-off-by: HerculesWSAPI --- doc/constants.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'doc') diff --git a/doc/constants.md b/doc/constants.md index 69bb51ea4..5a98d18bb 100644 --- a/doc/constants.md +++ b/doc/constants.md @@ -4282,6 +4282,18 @@ - `ITEMINFO_VIEWSPRITE`: 16 - `ITEMINFO_TRADE`: 17 +### getmercinfo options + +- `MERCINFO_ID,`: 0 +- `MERCINFO_CLASS`: 1 +- `MERCINFO_NAME`: 2 +- `MERCINFO_FAITH`: 3 +- `MERCINFO_CALLS`: 4 +- `MERCINFO_KILLCOUNT`: 5 +- `MERCINFO_LIFETIME`: 6 +- `MERCINFO_LEVEL`: 7 +- `MERCINFO_GID`: 8 + ### monster skill states - `MSS_ANY`: -1 -- cgit v1.2.3-70-g09d2 From 7dcd2f45f09513686421aacd90184aca9bcf5854 Mon Sep 17 00:00:00 2001 From: "Hercules.ws" Date: Mon, 11 Mar 2019 03:40:30 +0100 Subject: Constants Documentation Sync Signed-off-by: HerculesWSAPI --- doc/constants.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'doc') diff --git a/doc/constants.md b/doc/constants.md index 5a98d18bb..9225ce924 100644 --- a/doc/constants.md +++ b/doc/constants.md @@ -3773,8 +3773,8 @@ - `UDT_MAXSP`: 6 - `UDT_MASTERAID`: 7 - `UDT_MASTERCID`: 8 -- `UDT_MAPIDXY`: 9 -- `UDT_WALKTOXY`: 10 +- `UDT_MAPIDXY`: 9 **(DEPRECATED)** +- `UDT_WALKTOXY`: 10 **(DEPRECATED)** - `UDT_SPEED`: 11 - `UDT_MODE`: 12 - `UDT_AI`: 13 -- cgit v1.2.3-70-g09d2 From e42d9cb57a747427aee8d5edc15059de52588386 Mon Sep 17 00:00:00 2001 From: AnnieRuru Date: Mon, 11 Mar 2019 18:17:18 +0800 Subject: Deprecate *petstat script command --- db/constants.conf | 27 +++++++++++++++++++++------ doc/script_commands.txt | 7 +++++++ src/map/script.c | 2 +- 3 files changed, 29 insertions(+), 7 deletions(-) (limited to 'doc') diff --git a/db/constants.conf b/db/constants.conf index 2e379cb14..66e0ef066 100644 --- a/db/constants.conf +++ b/db/constants.conf @@ -1483,12 +1483,27 @@ constants_db: { e_panic: 79 e_whisp: 80 - comment__: "petstat" - PET_CLASS: 1 - PET_NAME: 2 - PET_LEVEL: 3 - PET_HUNGRY: 4 - PET_INTIMATE: 5 + comment__: "petstat - deprecated, use *getpetinfo" + PET_CLASS: { + Value: 1 + Deprecated: true + } + PET_NAME: { + Value: 2 + Deprecated: true + } + PET_LEVEL: { + Value: 3 + Deprecated: true + } + PET_HUNGRY: { + Value: 4 + Deprecated: true + } + PET_INTIMATE: { + Value: 5 + Deprecated: true + } comment__: "getmonsterinfo" MOB_NAME: 0 diff --git a/doc/script_commands.txt b/doc/script_commands.txt index 19f189f81..845570efd 100644 --- a/doc/script_commands.txt +++ b/doc/script_commands.txt @@ -3853,6 +3853,10 @@ If the invoking player doesn't own a pet, this command will return *petstat() + @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + @ /!\ This command is deprecated @ + @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + Returns current pet status, all are integers except name. Returns 0 or "" if the player doesn't have pets. @@ -3866,6 +3870,9 @@ PET_INTIMATE Example: .@i = petstat(PET_CLASS); +This command is deprecated and it should not be used in new scripts, as it is +likely to be removed at a later time. Please use 'getpetinfo' instead. + --------------------------------------- *getmonsterinfo(, ) diff --git a/src/map/script.c b/src/map/script.c index bba559df8..d6c7fde73 100644 --- a/src/map/script.c +++ b/src/map/script.c @@ -25598,7 +25598,7 @@ static void script_parse_builtin(void) BUILDIN_DEF(getd,"s"), BUILDIN_DEF(setd,"sv"), // <--- [zBuffer] List of dynamic var commands - BUILDIN_DEF(petstat,"i"), + BUILDIN_DEF_DEPRECATED(petstat, "i"), // Deprecated 2019-03-11 BUILDIN_DEF(callshop,"s?"), // [Skotlex] BUILDIN_DEF(npcshopitem,"sii*"), // [Lance] BUILDIN_DEF(npcshopadditem,"sii*"), -- cgit v1.2.3-70-g09d2 From 7652d647f13ad0755f355ed3d3b6ca1e8ad47d76 Mon Sep 17 00:00:00 2001 From: AnnieRuru Date: Tue, 12 Mar 2019 04:15:42 +0800 Subject: Add constants to *getpetinfo, and add some new fields --- doc/script_commands.txt | 34 ++++++++++-------- src/map/script.c | 95 ++++++++++++++++++++++++++++++++++++++----------- src/map/script.h | 21 +++++++++++ 3 files changed, 114 insertions(+), 36 deletions(-) (limited to 'doc') diff --git a/doc/script_commands.txt b/doc/script_commands.txt index 845570efd..94d3b9b30 100644 --- a/doc/script_commands.txt +++ b/doc/script_commands.txt @@ -3833,21 +3833,25 @@ how many skills a character has. *getpetinfo() -This function will return pet information for the pet the invoking -character currently has active. Valid types are: - - 0 - Unique pet ID number as stored by the char server and distinguishing - it from all other pets the characters actually have. This value is - currently useless, at most you can use it to tell pets apart reliably. - 1 - Pet class number as per 'db/pet_db.txt' - will tell you what kind of - a pet it is. - 2 - Pet name. Will return "null" if there's no pet. - 3 - Pet friendly level (intimacy score). 1000 is full loyalty. - 4 - Pet hungry level. 100 is completely full. - 5 - Pet rename flag. 0 means this pet has not been named yet. - -If the invoking player doesn't own a pet, this command will return -"null" for type 2, and return 0 for other types. +This command will return the currently active pet information of the invoking character. +These fields are associate in 'db/(pre-)re/pet_db.conf'. Valid types are: + + PETINFO_ID - Pet Database ID, stored in `pet` table to distinguish from other pets. + PETINFO_CLASS - Pet class ID. (Id field) + PETINFO_NAME - Pet Name, return "null" if there's no active pet. + PETINFO_INTIMACY - Pet Intimacy level. 1000 is full loyalty. + PETINFO_HUNGRY - Pet hungry level. 100 is completely full. + PETINFO_RENAME - Pet rename flag. 0 means this pet has not been named yet. + PETINFO_GID - Pet Game ID + PETINFO_EGGITEM - Pet EggItem + PETINFO_FOODITEM - Pet FoodItem + PETINFO_ACCESSORYITEM - Pet AccessoryItem + PETINFO_ACCESSORYFLAG - return 1 if the pet currently equipping accessory, return 0 otherwise. + PETINFO_EVO_EGGID - Pet Evolve EggID + PETINFO_AUTOFEED - Pet AutoFeed flag. + +If the invoking player doesn't own a pet, this command will +return "null" for type PETINFO_NAME, and return 0 for other types. --------------------------------------- diff --git a/src/map/script.c b/src/map/script.c index d6c7fde73..48663108d 100644 --- a/src/map/script.c +++ b/src/map/script.c @@ -15573,36 +15573,74 @@ static BUILDIN(recovery) return true; } -/*========================================== - * Get your pet info: getpetinfo(n) - * n -> 0:pet_id 1:pet_class 2:pet_name - * 3:friendly 4:hungry, 5: rename flag. - *------------------------------------------*/ +/* + * Get your current pet information + */ static BUILDIN(getpetinfo) { struct map_session_data *sd = script->rid2sd(st); - struct pet_data *pd; - int type=script_getnum(st,2); + if (sd == NULL) + return true; - if (sd == NULL || sd->pd == NULL) { - if (type == 2) - script_pushconststr(st,"null"); + struct pet_data *pd = sd->pd; + int type = script_getnum(st, 2); + if (pd == NULL) { + if (type == PETINFO_NAME) + script_pushconststr(st, "null"); else - script_pushint(st,0); + script_pushint(st, 0); return true; } - pd = sd->pd; + switch(type) { - case 0: script_pushint(st,pd->pet.pet_id); break; - case 1: script_pushint(st,pd->pet.class_); break; - case 2: script_pushstrcopy(st,pd->pet.name); break; - case 3: script_pushint(st,pd->pet.intimate); break; - case 4: script_pushint(st,pd->pet.hungry); break; - case 5: script_pushint(st,pd->pet.rename_flag); break; - default: - script_pushint(st,0); - break; + case PETINFO_ID: + script_pushint(st, pd->pet.pet_id); + break; + case PETINFO_CLASS: + script_pushint(st, pd->pet.class_); + break; + case PETINFO_NAME: + script_pushstrcopy(st, pd->pet.name); + break; + case PETINFO_INTIMACY: + script_pushint(st, pd->pet.intimate); + break; + case PETINFO_HUNGRY: + script_pushint(st, pd->pet.hungry); + break; + case PETINFO_RENAME: + script_pushint(st, pd->pet.rename_flag); + break; + case PETINFO_GID: + script_pushint(st, pd->bl.id); + break; + case PETINFO_EGGITEM: + script_pushint(st, pd->pet.egg_id); + break; + case PETINFO_FOODITEM: + script_pushint(st, pd->petDB->FoodID); + break; + case PETINFO_ACCESSORYITEM: + script_pushint(st, pd->petDB->AcceID); + break; + case PETINFO_ACCESSORYFLAG: + script_pushint(st, (pd->pet.equip != 0)? 1:0); + break; + case PETINFO_EVO_EGGID: + if (VECTOR_DATA(pd->petDB->evolve_data) != NULL) + script_pushint(st, VECTOR_DATA(pd->petDB->evolve_data)->petEggId); + else + script_pushint(st, 0); + break; + case PETINFO_AUTOFEED: + script_pushint(st, pd->pet.autofeed); + break; + default: + ShowWarning("buildin_getpetinfo: Invalid type %d.\n", type); + script_pushint(st, 0); + return false; } + return true; } @@ -26182,6 +26220,21 @@ static void script_hardcoded_constants(void) script->set_constant("MERCINFO_LEVEL", MERCINFO_LEVEL, false, false); script->set_constant("MERCINFO_GID", MERCINFO_GID, false, false); + script->constdb_comment("getpetinfo options"); + script->set_constant("PETINFO_ID", PETINFO_ID, false, false); + script->set_constant("PETINFO_CLASS", PETINFO_CLASS, false, false); + script->set_constant("PETINFO_NAME", PETINFO_NAME, false, false); + script->set_constant("PETINFO_INTIMACY", PETINFO_INTIMACY, false, false); + script->set_constant("PETINFO_HUNGRY", PETINFO_HUNGRY, false, false); + script->set_constant("PETINFO_RENAME", PETINFO_RENAME, false, false); + script->set_constant("PETINFO_GID", PETINFO_GID, false, false); + script->set_constant("PETINFO_EGGITEM", PETINFO_EGGITEM, false, false); + script->set_constant("PETINFO_FOODITEM", PETINFO_FOODITEM, false, false); + script->set_constant("PETINFO_ACCESSORYITEM", PETINFO_ACCESSORYITEM, false, false); + script->set_constant("PETINFO_ACCESSORYFLAG", PETINFO_ACCESSORYFLAG, false, false); + script->set_constant("PETINFO_EVO_EGGID", PETINFO_EVO_EGGID, false, false); + script->set_constant("PETINFO_AUTOFEED", PETINFO_AUTOFEED, false, false); + script->constdb_comment("monster skill states"); script->set_constant("MSS_ANY", MSS_ANY, false, false); script->set_constant("MSS_IDLE", MSS_IDLE, false, false); diff --git a/src/map/script.h b/src/map/script.h index 54c5aad2a..008da9c3c 100644 --- a/src/map/script.h +++ b/src/map/script.h @@ -477,6 +477,27 @@ enum script_mercinfo_types { MERCINFO_MAX }; +/** + * Pet Info types. + */ +enum script_petinfo_types { + PETINFO_ID = 0, + PETINFO_CLASS, + PETINFO_NAME, + PETINFO_INTIMACY, + PETINFO_HUNGRY, + PETINFO_RENAME, + PETINFO_GID, + PETINFO_EGGITEM, + PETINFO_FOODITEM, + PETINFO_ACCESSORYITEM, + PETINFO_ACCESSORYFLAG, + PETINFO_EVO_EGGID, + PETINFO_AUTOFEED, + + PETINFO_MAX +}; + /** * Player blocking actions related flags. */ -- cgit v1.2.3-70-g09d2 From ae5a425420e3cafd1a9887f02ba60f972cb85ede Mon Sep 17 00:00:00 2001 From: AnnieRuru Date: Sat, 23 Mar 2019 23:27:05 +0800 Subject: Add optional parameter for *gettimestr --- doc/script_commands.txt | 3 ++- src/map/script.c | 16 ++++++++++++++-- 2 files changed, 16 insertions(+), 3 deletions(-) (limited to 'doc') diff --git a/doc/script_commands.txt b/doc/script_commands.txt index 19f189f81..c99f27206 100644 --- a/doc/script_commands.txt +++ b/doc/script_commands.txt @@ -3531,7 +3531,7 @@ Examples : --------------------------------------- -*gettimestr(, ) +*gettimestr(, {, }) This function will return a string containing time data as specified by the format string. @@ -3545,6 +3545,7 @@ Max length is the maximum length of a time string to generate. The example given in Hercules sample scripts works like this: mes(gettimestr("%Y-%m/%d %H:%M:%S", 21)); + mes(gettimestr("%Y-%m/%d %H:%M:%S", 21, getcalendartime(0, 0))); This will print a full date and time like 'YYYY-MM/DD HH:MM:SS'. diff --git a/src/map/script.c b/src/map/script.c index bba559df8..aeaf851b1 100644 --- a/src/map/script.c +++ b/src/map/script.c @@ -10612,11 +10612,23 @@ static BUILDIN(gettimestr) char *tmpstr; const char *fmtstr; int maxlen; - time_t now = time(NULL); + time_t now; fmtstr=script_getstr(st,2); maxlen=script_getnum(st,3); + if (script_hasdata(st, 4)) { + int timestamp = script_getnum(st, 4); + if (timestamp < 0) { + ShowWarning("buildin_gettimestr: UNIX timestamp must be in positive value.\n"); + return false; + } + + now = (time_t)timestamp; + } else { + now = time(NULL); + } + tmpstr=(char *)aMalloc((maxlen+1)*sizeof(char)); strftime(tmpstr,maxlen,fmtstr,localtime(&now)); tmpstr[maxlen]='\0'; @@ -25378,7 +25390,7 @@ static void script_parse_builtin(void) BUILDIN_DEF(savepoint,"sii"), BUILDIN_DEF(gettimetick,"i"), BUILDIN_DEF(gettime,"i"), - BUILDIN_DEF(gettimestr,"si"), + BUILDIN_DEF(gettimestr, "si?"), BUILDIN_DEF(openstorage,""), BUILDIN_DEF(guildopenstorage,""), BUILDIN_DEF(itemskill,"vi?"), -- cgit v1.2.3-70-g09d2 From b478fb0a7373af0d80912641fbe08e9cbb49464e Mon Sep 17 00:00:00 2001 From: AnnieRuru Date: Sat, 23 Mar 2019 23:28:30 +0800 Subject: Fix strftime in the documentation --- doc/script_commands.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'doc') diff --git a/doc/script_commands.txt b/doc/script_commands.txt index c99f27206..2f210bf99 100644 --- a/doc/script_commands.txt +++ b/doc/script_commands.txt @@ -3536,9 +3536,9 @@ Examples : This function will return a string containing time data as specified by the format string. -This uses the C function 'strfmtime', which obeys special format +This uses the C function 'strftime', which obeys special format characters. For a full description see, for example, the description of -'strfmtime' at http://www.delorie.com/gnu/docs/glibc/libc_437.html +'strftime' at http://www.delorie.com/gnu/docs/glibc/libc_437.html All the format characters given in there should properly work. Max length is the maximum length of a time string to generate. -- cgit v1.2.3-70-g09d2 From c90ec16607f6ff4e422e2a5eca465a88af8b0af3 Mon Sep 17 00:00:00 2001 From: AnnieRuru Date: Sat, 30 Mar 2019 03:00:41 +0800 Subject: Add optional parameter for *showscript to send target to SELF only - also remove the useless script_pushint --- doc/script_commands.txt | 5 ++++- src/map/clif.c | 4 ++-- src/map/clif.h | 2 +- src/map/script.c | 14 +++++++------- 4 files changed, 14 insertions(+), 11 deletions(-) (limited to 'doc') diff --git a/doc/script_commands.txt b/doc/script_commands.txt index 19f189f81..077895e2b 100644 --- a/doc/script_commands.txt +++ b/doc/script_commands.txt @@ -4443,11 +4443,14 @@ if field is left out. --------------------------------------- -*showscript(""{, }) +*showscript(""{, {, }}) Makes the attached player or GID, display a message similiar to a chat, this will be seen by everyone near the invoking character but will not be displayed in the chat window. +send_target: (optional) + AREA: show the message to everyone within the view range (default) + SELF: show the message to the given unit GID only --------------------------------------- diff --git a/src/map/clif.c b/src/map/clif.c index a037d3436..4c3c746c4 100644 --- a/src/map/clif.c +++ b/src/map/clif.c @@ -19360,7 +19360,7 @@ static void clif_partytickack(struct map_session_data *sd, bool flag) WFIFOSET(sd->fd, packet_len(0x2c9)); } -static void clif_ShowScript(struct block_list *bl, const char *message) +static void clif_ShowScript(struct block_list *bl, const char *message, enum send_target target) { #if PACKETVER >= 20110111 char buf[256]; @@ -19381,7 +19381,7 @@ static void clif_ShowScript(struct block_list *bl, const char *message) WBUFW(buf,2) = len+8; WBUFL(buf,4) = bl->id; safestrncpy(WBUFP(buf,8),message,len); - clif->send(buf,WBUFW(buf,2),bl,AREA); + clif->send(buf, WBUFW(buf,2), bl, target); #endif } diff --git a/src/map/clif.h b/src/map/clif.h index 6b501477c..6e922bdff 100644 --- a/src/map/clif.h +++ b/src/map/clif.h @@ -1009,7 +1009,7 @@ struct clif_interface { void (*wisexin) (struct map_session_data *sd,int type,int flag); void (*wisall) (struct map_session_data *sd,int type,int flag); void (*PMIgnoreList) (struct map_session_data* sd); - void (*ShowScript) (struct block_list* bl, const char* message); + void (*ShowScript) (struct block_list* bl, const char* message, enum send_target target); /* trade handling */ void (*traderequest) (struct map_session_data* sd, const char* name); void (*tradestart) (struct map_session_data* sd, uint8 type); diff --git a/src/map/script.c b/src/map/script.c index bba559df8..ed8f6b8d2 100644 --- a/src/map/script.c +++ b/src/map/script.c @@ -24377,7 +24377,7 @@ static BUILDIN(showscript) { struct block_list *bl = NULL; const char *msg = script_getstr(st, 2); - int id = 0; + int id = 0, flag = AREA; if (script_hasdata(st, 3)) { id = script_getnum(st, 3); @@ -24389,14 +24389,14 @@ static BUILDIN(showscript) if (!bl) { ShowError("buildin_showscript: Script not attached. (id=%d, rid=%d, oid=%d)\n", id, st->rid, st->oid); - script_pushint(st, 0); return false; } - clif->ShowScript(bl, msg); - - script_pushint(st, 1); - + if (script_hasdata(st, 4)) + if (script_getnum(st, 4) == SELF) + flag = SELF; + + clif->ShowScript(bl, msg, flag); return true; } @@ -25822,7 +25822,7 @@ static void script_parse_builtin(void) BUILDIN_DEF(channelmes, "ss"), BUILDIN_DEF(addchannelhandler, "ss"), BUILDIN_DEF(removechannelhandler, "ss"), - BUILDIN_DEF(showscript, "s?"), + BUILDIN_DEF(showscript, "s??"), BUILDIN_DEF(mergeitem,""), BUILDIN_DEF(getcalendartime, "ii??"), -- cgit v1.2.3-70-g09d2 From dd83aabd6f4d95183371e98689c3456e0456fef7 Mon Sep 17 00:00:00 2001 From: "Hercules.ws" Date: Sun, 7 Apr 2019 20:51:43 +0200 Subject: Constants Documentation Sync Signed-off-by: HerculesWSAPI --- doc/constants.md | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) (limited to 'doc') diff --git a/doc/constants.md b/doc/constants.md index 9225ce924..83d248493 100644 --- a/doc/constants.md +++ b/doc/constants.md @@ -1407,13 +1407,13 @@ - `e_panic`: 79 - `e_whisp`: 80 -### petstat +### petstat - deprecated, use *getpetinfo -- `PET_CLASS`: 1 -- `PET_NAME`: 2 -- `PET_LEVEL`: 3 -- `PET_HUNGRY`: 4 -- `PET_INTIMATE`: 5 +- `PET_CLASS`: 1 **(DEPRECATED)** +- `PET_NAME`: 2 **(DEPRECATED)** +- `PET_LEVEL`: 3 **(DEPRECATED)** +- `PET_HUNGRY`: 4 **(DEPRECATED)** +- `PET_INTIMATE`: 5 **(DEPRECATED)** ### getmonsterinfo @@ -4294,6 +4294,22 @@ - `MERCINFO_LEVEL`: 7 - `MERCINFO_GID`: 8 +### getpetinfo options + +- `PETINFO_ID`: 0 +- `PETINFO_CLASS`: 1 +- `PETINFO_NAME`: 2 +- `PETINFO_INTIMACY`: 3 +- `PETINFO_HUNGRY`: 4 +- `PETINFO_RENAME`: 5 +- `PETINFO_GID`: 6 +- `PETINFO_EGGITEM`: 7 +- `PETINFO_FOODITEM`: 8 +- `PETINFO_ACCESSORYITEM`: 9 +- `PETINFO_ACCESSORYFLAG`: 10 +- `PETINFO_EVO_EGGID`: 11 +- `PETINFO_AUTOFEED`: 12 + ### monster skill states - `MSS_ANY`: -1 -- cgit v1.2.3-70-g09d2 From f89a6da63a50cefa8251d1a84f40d85cf109bd4e Mon Sep 17 00:00:00 2001 From: "Hercules.ws" Date: Sun, 7 Apr 2019 23:20:45 +0200 Subject: Constants Documentation Sync Signed-off-by: HerculesWSAPI --- doc/constants.md | 1 + 1 file changed, 1 insertion(+) (limited to 'doc') diff --git a/doc/constants.md b/doc/constants.md index 83d248493..aedb1755e 100644 --- a/doc/constants.md +++ b/doc/constants.md @@ -3989,6 +3989,7 @@ - `MAX_BG_MEMBERS`: 30 - `MAX_CHAT_USERS`: 20 - `MAX_REFINE`: 20 +- `MAX_ITEM_ID`: 65535 - `MAX_MENU_OPTIONS`: 255 - `MAX_MENU_LENGTH`: 2048 - `MOB_CLONE_START`: 4001 -- cgit v1.2.3-70-g09d2 From 33d403c5b5bfeafc4966589594e8a0647b744b5f Mon Sep 17 00:00:00 2001 From: Emistry Haoyan Date: Tue, 9 Apr 2019 22:32:24 +0800 Subject: Expand *getinventorylist() script command - return an array `@inventorylist_favorite` - indicate whether an item in the inventory are located inside favorite tab or not. --- doc/script_commands.txt | 3 ++- src/map/script.c | 57 +++++++++++++++++++++++++++---------------------- 2 files changed, 34 insertions(+), 26 deletions(-) (limited to 'doc') diff --git a/doc/script_commands.txt b/doc/script_commands.txt index b53dda2f6..fd593f17e 100644 --- a/doc/script_commands.txt +++ b/doc/script_commands.txt @@ -3129,7 +3129,8 @@ recreate these items perfectly if they are destroyed. Here's what you get: made by a specific craftsman. @inventorylist_expire[] - expire time (Unix time stamp). 0 means never expires. -@inventorylist_bound - whether it is an account bounded item or not. +@inventorylist_bound[] - whether it is an account bounded item or not. +@inventorylist_favorite[] - whether it is favorite (inside favorite tab) or not. @inventorylist_count - the number of items in these lists. This could be handy to save/restore a character's inventory, since no diff --git a/src/map/script.c b/src/map/script.c index fe8638ac3..dea94c6a3 100644 --- a/src/map/script.c +++ b/src/map/script.c @@ -14832,48 +14832,55 @@ static BUILDIN(petloot) * Set arrays with info of all sd inventory : * @inventorylist_id, @inventorylist_amount, @inventorylist_equip, * @inventorylist_refine, @inventorylist_identify, @inventorylist_attribute, - * @inventorylist_card(0..3), @inventorylist_expire + * @inventorylist_card(0..3), + * @inventorylist_opt_id(0..MAX_ITEM_OPTIONS), + * @inventorylist_opt_val(0..MAX_ITEM_OPTIONS), + * @inventorylist_opt_param(0..MAX_ITEM_OPTIONS), + * @inventorylist_expire, @inventorylist_bound, @inventorylist_favorite, + * @inventorylist_idx * @inventorylist_count = scalar *------------------------------------------*/ static BUILDIN(getinventorylist) { struct map_session_data *sd = script->rid2sd(st); - char card_var[SCRIPT_VARNAME_LENGTH]; + char script_var[SCRIPT_VARNAME_LENGTH]; + int j = 0, k = 0; - int j=0,k; - if(!sd) return true; + if (sd == NULL) + return true; - for (int i = 0;i < sd->status.inventorySize; i++) { - if(sd->status.inventory[i].nameid > 0 && sd->status.inventory[i].amount > 0) { - pc->setreg(sd,reference_uid(script->add_variable("@inventorylist_id"), j),sd->status.inventory[i].nameid); - pc->setreg(sd,reference_uid(script->add_variable("@inventorylist_amount"), j),sd->status.inventory[i].amount); - if(sd->status.inventory[i].equip) { - pc->setreg(sd,reference_uid(script->add_variable("@inventorylist_equip"), j),pc->equippoint(sd,i)); + for (int i = 0; i < sd->status.inventorySize; i++) { + if (sd->status.inventory[i].nameid > 0 && sd->status.inventory[i].amount > 0) { + pc->setreg(sd, reference_uid(script->add_variable("@inventorylist_id"), j), sd->status.inventory[i].nameid); + pc->setreg(sd, reference_uid(script->add_variable("@inventorylist_amount"), j), sd->status.inventory[i].amount); + if (sd->status.inventory[i].equip != 0) { + pc->setreg(sd, reference_uid(script->add_variable("@inventorylist_equip"), j), pc->equippoint(sd, i)); } else { - pc->setreg(sd,reference_uid(script->add_variable("@inventorylist_equip"), j),0); + pc->setreg(sd, reference_uid(script->add_variable("@inventorylist_equip"), j), 0); } - pc->setreg(sd,reference_uid(script->add_variable("@inventorylist_refine"), j),sd->status.inventory[i].refine); - pc->setreg(sd,reference_uid(script->add_variable("@inventorylist_identify"), j),sd->status.inventory[i].identify); - pc->setreg(sd,reference_uid(script->add_variable("@inventorylist_attribute"), j),sd->status.inventory[i].attribute); + pc->setreg(sd, reference_uid(script->add_variable("@inventorylist_refine"), j), sd->status.inventory[i].refine); + pc->setreg(sd, reference_uid(script->add_variable("@inventorylist_identify"), j), sd->status.inventory[i].identify); + pc->setreg(sd, reference_uid(script->add_variable("@inventorylist_attribute"), j), sd->status.inventory[i].attribute); for (k = 0; k < MAX_SLOTS; k++) { - sprintf(card_var, "@inventorylist_card%d",k+1); - pc->setreg(sd,reference_uid(script->add_variable(card_var), j),sd->status.inventory[i].card[k]); + sprintf(script_var, "@inventorylist_card%d", k + 1); + pc->setreg(sd, reference_uid(script->add_variable(script_var), j), sd->status.inventory[i].card[k]); } for (k = 0; k < MAX_ITEM_OPTIONS; k++) { - sprintf(card_var, "@inventorylist_opt_id%d", k + 1); - pc->setreg(sd, reference_uid(script->add_variable(card_var), j), sd->status.inventory[i].option[k].index); - sprintf(card_var, "@inventorylist_opt_val%d", k + 1); - pc->setreg(sd, reference_uid(script->add_variable(card_var), j), sd->status.inventory[i].option[k].value); - sprintf(card_var, "@inventorylist_opt_param%d", k + 1); - pc->setreg(sd, reference_uid(script->add_variable(card_var), j), sd->status.inventory[i].option[k].param); + sprintf(script_var, "@inventorylist_opt_id%d", k + 1); + pc->setreg(sd, reference_uid(script->add_variable(script_var), j), sd->status.inventory[i].option[k].index); + sprintf(script_var, "@inventorylist_opt_val%d", k + 1); + pc->setreg(sd, reference_uid(script->add_variable(script_var), j), sd->status.inventory[i].option[k].value); + sprintf(script_var, "@inventorylist_opt_param%d", k + 1); + pc->setreg(sd, reference_uid(script->add_variable(script_var), j), sd->status.inventory[i].option[k].param); } - pc->setreg(sd,reference_uid(script->add_variable("@inventorylist_expire"), j),sd->status.inventory[i].expire_time); - pc->setreg(sd,reference_uid(script->add_variable("@inventorylist_bound"), j),sd->status.inventory[i].bound); + pc->setreg(sd, reference_uid(script->add_variable("@inventorylist_expire"), j), sd->status.inventory[i].expire_time); + pc->setreg(sd, reference_uid(script->add_variable("@inventorylist_bound"), j), sd->status.inventory[i].bound); + pc->setreg(sd, reference_uid(script->add_variable("@inventorylist_favorite"), j), sd->status.inventory[i].favorite); pc->setreg(sd, reference_uid(script->add_variable("@inventorylist_idx"), j), i); j++; } } - pc->setreg(sd,script->add_variable("@inventorylist_count"),j); + pc->setreg(sd, script->add_variable("@inventorylist_count"), j); return true; } -- cgit v1.2.3-70-g09d2 From bc7f9019e8ec1ed3802c49baeaa35fdd20be2ab3 Mon Sep 17 00:00:00 2001 From: AnnieRuru Date: Thu, 11 Apr 2019 11:19:09 +0800 Subject: Standardize to "all" in script commands --- doc/script_commands.txt | 2 +- src/map/script.c | 10 ++++++++-- 2 files changed, 9 insertions(+), 3 deletions(-) (limited to 'doc') diff --git a/doc/script_commands.txt b/doc/script_commands.txt index b53dda2f6..8f114fbac 100644 --- a/doc/script_commands.txt +++ b/doc/script_commands.txt @@ -6502,7 +6502,7 @@ This command will kill all monsters that were spawned with monster() or areamonster() and have a specified event label attached to them. Commonly used to get rid of remaining quest monsters once the quest is complete. -If the label is given as "All", all monsters which have their respawn +If the label is given as "all", all monsters which have their respawn times set to -1 (like all the monsters summoned with 'monster' or 'areamonster' script command, and all monsters summoned with GM commands, but no other ones - that is, all non-permanent monsters) on the specified diff --git a/src/map/script.c b/src/map/script.c index fe8638ac3..01245a617 100644 --- a/src/map/script.c +++ b/src/map/script.c @@ -11043,10 +11043,16 @@ static BUILDIN(killmonster) int16 m,allflag=0; mapname=script_getstr(st,2); event=script_getstr(st,3); - if(strcmp(event,"All")==0) + + if (strcmpi(event, "all") == 0) { + if (strcmp(event, "all") != 0) { + ShowWarning("buildin_killmonster: \"%s\" deprecated! Please use \"all\" instead.\n", event); + script->reportsrc(st); + } allflag = 1; - else + } else { script->check_event(st, event); + } if( (m=map->mapname2mapid(mapname))<0 ) return true; -- cgit v1.2.3-70-g09d2 From d34df93e14582b1c2ad43763666d674b7e8440ca Mon Sep 17 00:00:00 2001 From: "Guilherme G. Menaldo" Date: Mon, 1 Oct 2018 13:52:15 -0300 Subject: Added support for mobs to drop items with Random Options --- conf/map/battle/drops.conf | 5 + db/mob_db2.conf | 2 + db/option_drop_groups.conf | 53 +++++++ db/pre-re/mob_db.conf | 2 + db/re/mob_db.conf | 2 + doc/mob_db.txt | 68 +++++++-- doc/option_drop_group.md | 97 ++++++++++++ src/map/battle.c | 1 + src/map/battle.h | 2 + src/map/mob.c | 357 ++++++++++++++++++++++++++++++++++++++++++++- src/map/mob.h | 46 +++++- 11 files changed, 609 insertions(+), 26 deletions(-) create mode 100644 db/option_drop_groups.conf create mode 100644 doc/option_drop_group.md (limited to 'doc') diff --git a/conf/map/battle/drops.conf b/conf/map/battle/drops.conf index eb7d94f13..51280702b 100644 --- a/conf/map/battle/drops.conf +++ b/conf/map/battle/drops.conf @@ -146,3 +146,8 @@ drops_by_luk2: 0 // 1: Only marine spheres drop items. // 2: All alchemist summons drop items. alchemist_summon_reward: 1 + +// The maximum number of full iterations that server can do when dropping an item with options. +// When picking random options for a dropped item, it does lots of iterations to choose the option to be set, +// this value limits the number of iterations to avoid making the server hang in a long loop. +option_drop_max_loop: 10 diff --git a/db/mob_db2.conf b/db/mob_db2.conf index 8d3e67904..e2894a719 100644 --- a/db/mob_db2.conf +++ b/db/mob_db2.conf @@ -89,6 +89,8 @@ mob_db: ( } Drops: { AegisName: chance (string: int) + // or + AegisName: (chance, "Option Drop Group") // ... } }, diff --git a/db/option_drop_groups.conf b/db/option_drop_groups.conf new file mode 100644 index 000000000..b293be19a --- /dev/null +++ b/db/option_drop_groups.conf @@ -0,0 +1,53 @@ +//================= Hercules Database ===================================== +//= _ _ _ +//= | | | | | | +//= | |_| | ___ _ __ ___ _ _| | ___ ___ +//= | _ |/ _ \ '__/ __| | | | |/ _ \/ __| +//= | | | | __/ | | (__| |_| | | __/\__ \ +//= \_| |_/\___|_| \___|\__,_|_|\___||___/ +//================= License =============================================== +//= This file is part of Hercules. +//= http://herc.ws - http://github.com/HerculesWS/Hercules +//= +//= Copyright (C) 2018 Hercules Dev Team +//= +//= Hercules is free software: you can redistribute it and/or modify +//= it under the terms of the GNU General Public License as published by +//= the Free Software Foundation, either version 3 of the License, or +//= (at your option) any later version. +//= +//= This program is distributed in the hope that it will be useful, +//= but WITHOUT ANY WARRANTY; without even the implied warranty of +//= MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +//= GNU General Public License for more details. +//= +//= You should have received a copy of the GNU General Public License +//= along with this program. If not, see . +//========================================================================= +//= Random Option Drop Group Database +//========================================================================= + +option_drop_group_db: ( +{ +/************************************************************************** + ************* Entry structure ******************************************** + ************************************************************************** + : ( + { // Option Slot 1 + Rate: (int) chance of filling option slot 1 (100 = 1%) + + // Possible options for slot 1 + // min/max value : int, defaults to 0 + // chance : int, 100 = 1% if not set, will be 100%/number of possibiltiies + OptionName: value + // or + OptionName: [min value, max value] + // or + OptionName: [min value, max value, chance] + // ... (as many as you want) + }, + // ... (up to MAX_ITEM_OPTION) + ), +**************************************************************************/ +} +) diff --git a/db/pre-re/mob_db.conf b/db/pre-re/mob_db.conf index 40635cd68..553593cea 100644 --- a/db/pre-re/mob_db.conf +++ b/db/pre-re/mob_db.conf @@ -89,6 +89,8 @@ mob_db: ( } Drops: { AegisName: chance (string: int) + // or + AegisName: (chance, "Option Drop Group") // ... } }, diff --git a/db/re/mob_db.conf b/db/re/mob_db.conf index e90b478e7..f787d5478 100644 --- a/db/re/mob_db.conf +++ b/db/re/mob_db.conf @@ -89,6 +89,8 @@ mob_db: ( } Drops: { AegisName: chance (string: int) + // or + AegisName: (chance, "Option Drop Group") // ... } }, diff --git a/doc/mob_db.txt b/doc/mob_db.txt index 29d2ab465..d62181048 100644 --- a/doc/mob_db.txt +++ b/doc/mob_db.txt @@ -63,10 +63,14 @@ mob_db: ( MvpExp: mvp experience (int, defaults to 0) MvpDrops: { AegisName: chance (string: int) + // or + AegisName: (chance, "Option Drop Group") // ... } Drops: { - AegisName: chance (string: int) + AegisName: chance (string: int) + // or + AegisName: (chance, "Option Drop Group") // ... } }, @@ -199,21 +203,55 @@ MvpExp: Base Experience given by the monster to the player who inflict more atta MvpDrops: Sets monster mvp drops list. Requires to have MvpExp to trigger. - Accepted values are AegisName as defined on item_db.conf and a chance. + There are two ways to define a drop: + 1) The first one is used for simple drops and uses the item AegisName + as defined on item_db.conf and a chance. + Format: + AegisName: chance Chance is an integer from 1 to 10000 (10000 = 100%). - Required format: - MvpDrops: { - AegisName: chance - // ... - } - When not specified, becomes false. + + 2) The second way to define a drop allows setting a random option drop + group to be used by this drop. + Format: + AegisName: (chance, "Option Drop Group") + + The item drop chance refers to the chance of dropping this item, same as chance in the first option. + the "Option Drop Group" parameter refers to an entry on option_drop_group database file. The specified + entry will be used when this item is dropped in order to add random options to the dropped equipment. + + A monster drop list may use both format for different items. + Required Format: + Drops: { + AegisName: chance + // or + AegisName: (chance, "Option Drop Group") + } + + When not specified, becomes false (no drops). Drops: Sets monster drops list. - Accepted values are AegisName as defined on item_db.conf and a chance. + There are two ways to define a drop: + 1) The first one is used for simple drops and uses the item AegisName + as defined on item_db.conf and a chance. + Format: + AegisName: chance Chance is an integer from 1 to 10000 (10000 = 100%). - Required format: - Drops: { - AegisName: chance - // ... - } - When not specified, becomes false. + + 2) The second way to define a drop allows setting a random option drop + group to be used by this drop. + Format: + AegisName: (chance, "Option Drop Group") + + The item drop chance refers to the chance of dropping this item, same as chance in the first option. + the "Option Drop Group" parameter refers to an entry on option_drop_group database file. The specified + entry will be used when this item is dropped in order to add random options to the dropped equipment. + + A monster drop list may use both format for different items. + Required Format: + Drops: { + AegisName: chance + // or + AegisName: (chance, "Option Drop Group") + } + + When not specified, becomes false (no drops). diff --git a/doc/option_drop_group.md b/doc/option_drop_group.md new file mode 100644 index 000000000..325cf9fe2 --- /dev/null +++ b/doc/option_drop_group.md @@ -0,0 +1,97 @@ +# Option Drop Group Database + +## Description +Explanation of the `db/option_drop_groups.conf` file and structure. + +This database file allows the creation of groups of random options +that will be added to certain equipments when dropped. After creating +a group in this database file, you may set up drops in `mob_db` to use +it in order to get items with these options. For more information on +adding option drop groups to `mob_db`, check `doc/mob_db.txt` documentation file. + +Each item may have up to `MAX_ITEM_OPTION` options at the same time, +in this document, each of these independent options will be called +`option slot`. One drop group will define the possibilities of random +options for each of these slots. + +## Entries Format + +``` +: ( + { // Option Slot 1 + Rate: (int) chance of filling option slot 1 (100 = 1%) + + // Possible options for slot 1 + // min/max value : int, defaults to 0 + // chance : int, 100 = 1% if not set, will be 100%/number of possibiltiies + OptionName: value + // or + OptionName: [min value, max value] + // or + OptionName: [min value, max value, chance] + // ... (as many as you want) + }, + // ... (up to MAX_ITEM_OPTION) +), +``` + +### `Group Name Constant` +This is the group name, it is how this group is referenced in other files +(e.g. mob_db). It must be globally unique, as it is a server constant, and +must contain only letters, numbers and " _ ". + +### `Rate` +This is the chance of this option slot to drop. In other words, this is the +chance of getting this slot filled with something, where something is given +by the list of `OptionName` that follows. + +Rate is an integer value where 100 means 1%. + +### `OptionName` +Adds `OptionName` as one option that may fill this slot when it drops. + +The details of this option may be specified in one of 3 ways: + +#### `OptionName: value` +The chance of this option being picked is auto calculated (see below), +and if this option is chosen, its value will be `value`. + +#### `OptionName: [min, max]` +The chance of this option being picked is auto calculated (see below), +and if this option is chosen, its value will be a random integer between +`min` and `max` (both included). + +#### `OptionName: [min, max, chance]` +The chance of this option being picked is `chance`, and if this option is chosen, +its value will be a random integer between `min` and `max` (both included). + +#### Auto calculated chances +When chance is not specified in an option, it will be auto calculated by +the server as being `100%/num`, when `num` is the number of possibilities +in this option slot. + +For example, if you specify 3 possible options, all of them without +a `chance` defined, all of them will have 33.33% chance of being +picked (100%/3). If you set the chance of one of them to 50%, you +will have one option with 50% chance, and each of the others with +33.33% chance. + +## Example +``` +MYITEM: ( + { // Option Slot 1 + Rate: 10000 // It has 100% of chance of being filled + + // This slot may have one of the following options: + WEAPON_ATTR_WIND: 5, // WEAPON_ATTR_WIND Lv5 (33.33%) + WEAPON_ATTR_GROUND: [2, 4] // WEAPON_ATTR_GROUND Lv 2~4 (33.33%) + WEAPON_ATTR_POISON: [1, 4, 8000] // WEAPON_ATTR_POISON Lv 1~4 (80%) + }, + { // Option Slot 2 + Rate: 5000 // It has 50% of chance of being filled + + // If filled, may have one of the following options: + WEAPON_ATTR_WATER: 4 // WEAPON_ATTR_WATER Lv4 (100%) + } +) +``` diff --git a/src/map/battle.c b/src/map/battle.c index fe7a64b51..ba7c1130d 100644 --- a/src/map/battle.c +++ b/src/map/battle.c @@ -7417,6 +7417,7 @@ static const struct battle_data { { "features/enable_achievement_system", &battle_config.feature_enable_achievement, 1, 0, 1, }, { "ping_timer_inverval", &battle_config.ping_timer_interval, 30, 0, 99999999, }, { "ping_time", &battle_config.ping_time, 20, 0, 99999999, }, + { "option_drop_max_loop", &battle_config.option_drop_max_loop, 10, 1, 100000, }, }; static bool battle_set_value_sub(int index, int value) diff --git a/src/map/battle.h b/src/map/battle.h index 723a86874..a99e95c86 100644 --- a/src/map/battle.h +++ b/src/map/battle.h @@ -583,6 +583,8 @@ struct Battle_Config { int ping_timer_interval; int ping_time; + + int option_drop_max_loop; }; /* criteria for battle_config.idletime_critera */ diff --git a/src/map/mob.c b/src/map/mob.c index fed4d6c60..a72e3bc42 100644 --- a/src/map/mob.c +++ b/src/map/mob.c @@ -1900,15 +1900,53 @@ static int mob_ai_hard(int tid, int64 tick, int id, intptr_t data) return 0; } +/** + * Adds random options of a given options drop group into item. + * + * @param item : item receiving random options + * @param options : Random Option Drop Group to be used + */ +static void mob_setdropitem_options(struct item *item, struct optdrop_group *options) +{ + nullpo_retv(item); + nullpo_retv(options); + + for (int i = 0; i < options->optslot_count; i++) { + if (rnd() % 10000 >= options->optslot_rate[i]) + continue; + + // count avoids a too long loop that would cause lag. + // if after option_drop_max_loop full iterations (running through all possibilities) + // it still fails to pick one, it'll stop at one random index in the next iteration + int count = battle_config.option_drop_max_loop * options->optslot[i].option_count + (rnd() % options->optslot[i].option_count); + int idx = 0; + while (count > 0 && rnd() % 10000 >= options->optslot[i].options[idx].rate) { + idx = (idx + 1) % options->optslot[i].option_count; + --count; + } + + item->option[i].index = options->optslot[i].options[idx].id; + + int min = options->optslot[i].options[idx].min; + int max = options->optslot[i].options[idx].max; + item->option[i].value = min + (rnd() % (max - min + 1)); + } +} + /*========================================== * Initializes the delay drop structure for mob-dropped items. *------------------------------------------*/ -static struct item_drop *mob_setdropitem(int nameid, int qty, struct item_data *data) +static struct item_drop *mob_setdropitem(int nameid, struct optdrop_group *options, int qty, struct item_data *data) { struct item_drop *drop = ers_alloc(item_drop_ers, struct item_drop); drop->item_data.nameid = nameid; drop->item_data.amount = qty; drop->item_data.identify = data ? itemdb->isidentified2(data) : itemdb->isidentified(nameid); + + // Set item options [KirieZ] + if (options != NULL) + mob->setdropitem_options(&drop->item_data, options); + drop->showdropeffect = true; drop->next = NULL; return drop; @@ -2521,7 +2559,7 @@ static int mob_dead(struct mob_data *md, struct block_list *src, int type) continue; } - ditem = mob->setdropitem(md->db->dropitem[i].nameid, 1, it); + ditem = mob->setdropitem(md->db->dropitem[i].nameid, md->db->dropitem[i].options, 1, it); // Official Drop Announce [Jedzkie] if (mvp_sd != NULL) { @@ -2538,7 +2576,7 @@ static int mob_dead(struct mob_data *md, struct block_list *src, int type) // Ore Discovery [Celest] if (sd == mvp_sd && pc->checkskill(sd,BS_FINDINGORE) > 0) { if( (temp = itemdb->chain_item(itemdb->chain_cache[ECC_ORE],&i)) ) { - ditem = mob->setdropitem(temp, 1, NULL); + ditem = mob->setdropitem(temp, NULL, 1, NULL); mob->item_drop(md, dlist, ditem, 0, i, homkillonly); } } @@ -2570,7 +2608,7 @@ static int mob_dead(struct mob_data *md, struct block_list *src, int type) continue; itemid = (!sd->add_drop[i].is_group) ? sd->add_drop[i].id : itemdb->chain_item(sd->add_drop[i].id, &drop_rate); if( itemid ) - mob->item_drop(md, dlist, mob->setdropitem(itemid,1,NULL), 0, drop_rate, homkillonly); + mob->item_drop(md, dlist, mob->setdropitem(itemid, NULL, 1, NULL), 0, drop_rate, homkillonly); } } @@ -2632,6 +2670,7 @@ static int mob_dead(struct mob_data *md, struct block_list *src, int type) struct { int nameid; int p; + struct optdrop_group *options; } mdrop[MAX_MVP_DROP] = { { 0 } }; for (i = 0; i < MAX_MVP_DROP; i++) { @@ -2644,6 +2683,7 @@ static int mob_dead(struct mob_data *md, struct block_list *src, int type) mdrop[rpos].nameid = md->db->mvpitem[i].nameid; mdrop[rpos].p = md->db->mvpitem[i].p; + mdrop[rpos].options = md->db->mvpitem[i].options; } for (i = 0; i < MAX_MVP_DROP; i++) { @@ -2663,6 +2703,7 @@ static int mob_dead(struct mob_data *md, struct block_list *src, int type) item.nameid = mdrop[i].nameid; item.identify = itemdb->isidentified2(data); + mob->setdropitem_options(&item, mdrop[i].options); clif->mvp_item(mvp_sd, item.nameid); log_mvp[0] = item.nameid; @@ -3860,6 +3901,212 @@ static inline int mob_parse_dbrow_cap_value(int class_, int min, int max, int va return value; } +/** + * Reads one possible option for a option slot in a option drop group + * @param option : Libconfig entry + * @param entry : memory db entry for current slot + * @param idx : index of entry where this option should be inserted at + * @param calc_rate : if rates should be recalculated after reading all entries + * @param slot : option group slot being read (for messages) + * @param group : option group being read (for messages) + * @return true if it successfully read the entry, false otherwise + */ +static bool mob_read_optdrops_option(struct config_setting_t *option, struct optdrop_group_optslot *entry, int *idx, bool *calc_rate, int slot, const char *group) +{ + nullpo_retr(false, option); + nullpo_retr(false, entry); + nullpo_retr(false, idx); + nullpo_retr(false, calc_rate); + nullpo_retr(false, group); + + const char *name = config_setting_name(option); + int opt_id; + + if (strncmp(name, "Rate", 4) == 0) + return true; + + if (script->get_constant(name, &opt_id) == false) { + ShowWarning("mob_read_optdrops_option: Invalid option \"%s\" for option slot %d of %s group, skipping.\n", name, slot, group); + return false; + } + + int min = 0, max = 0, opt_rate = 0; + if (config_setting_is_number(option)) { + // OptionName: value + min = libconfig->setting_get_int(option); + } else if (config_setting_is_array(option)) { + // OptionName: [min, max] + // OptionName: [min, max, rate] + int slen = libconfig->setting_length(option); + + if (slen >= 2) { + // [min, max,...] + min = libconfig->setting_get_int_elem(option, 0); + max = libconfig->setting_get_int_elem(option, 1); + } + + if (slen == 3) { + // [min, max, rate] + opt_rate = libconfig->setting_get_int_elem(option, 2); + } + } else { + ShowWarning("mob_read_optdrops_option: Invalid value \"%s\" for option slot %d of %s group, skipping.\n", name, slot, group); + return false; + } + + if (max < min) + max = min; + + entry->options[*idx].id = opt_id; + entry->options[*idx].min = min; + entry->options[*idx].max = max; + entry->options[*idx].rate = opt_rate; + + if (entry->options[*idx].rate == 0) + *calc_rate = true; + + (*idx)++; + + return true; +} + +/** + * Reads the settings for one random option slot of a random option drop group. + * @param optslot : The slot entry from config file + * @param n : slot index + * @param group_id : Group index + * @param group : group name (used in messages) + * @return true if it succesfully read, false otherwise + */ +static bool mob_read_optdrops_optslot(struct config_setting_t *optslot, int n, int group_id, const char *group) +{ + nullpo_retr(false, optslot); + nullpo_retr(false, group); + Assert_retr(false, group_id >= 0 && group_id < mob->opt_drop_groups_count); + Assert_retr(false, n >= 0 && n < MAX_ITEM_OPTIONS); + + // Structure: + // { + // Rate: chance of option 1 (int) + // OptionName1: value + // OptionName2: [min, max] + // OptionName3: [min, max, rate] + // .... + // } + + int drop_rate; // The rate for this option to be dropped (Rate field) + if (libconfig->setting_lookup_int(optslot, "Rate", &drop_rate) == CONFIG_FALSE) { + ShowWarning("mob_read_optdrops_optslot: Missing option %d rate in group %s, skipping.\n", n, group); + return false; + } + + int count = libconfig->setting_length(optslot); + if (count <= 1) { // 1 = Rate + ShowWarning("mob_read_optdrops_optslot: Option %d of %s group doesn't contain any possible options, skipping.\n", n, group); + return false; + } + + struct optdrop_group_optslot *entry = &(mob->opt_drop_groups[group_id].optslot[n]); + entry->options = aCalloc(sizeof(struct optdrop_group_option), count); + + int idx = 0; + int i = 0; + struct config_setting_t *opt = NULL; + bool calc_rate = false; + while (i < count && (opt = libconfig->setting_get_elem(optslot, i)) != NULL) { + ++i; + mob->read_optdrops_option(opt, entry, &idx, &calc_rate, n, group); + } + entry->option_count = idx; + mob->opt_drop_groups[group_id].optslot_count++; + mob->opt_drop_groups[group_id].optslot_rate[n] = drop_rate; + + // If there're empty rates, calculate them + if (calc_rate == true) { + for (int j = 0; j < idx; ++j) { + if (entry->options[j].rate == 0) + entry->options[j].rate = 10000 / idx; + } + } + + return true; +} + +/** + * Reads one random option drop group. + * @param group : Drop Group entry from config file + * @param n : group index + * @return true if it successfuly read, false otherwise + */ +static bool mob_read_optdrops_group(struct config_setting_t *group, int n) +{ + /* Structure: + : ( + {