From b0be3f023a024a4f8cc9903d52add7c81961303a Mon Sep 17 00:00:00 2001 From: "Guilherme G. Menaldo" Date: Mon, 1 Oct 2018 13:48:10 -0300 Subject: Added option to make hunter traps invisible --- db/pre-re/skill_db.conf | 1 + db/re/skill_db.conf | 9 +++++++++ 2 files changed, 10 insertions(+) (limited to 'db') diff --git a/db/pre-re/skill_db.conf b/db/pre-re/skill_db.conf index 4873012aa..92a3b76bb 100644 --- a/db/pre-re/skill_db.conf +++ b/db/pre-re/skill_db.conf @@ -75,6 +75,7 @@ Works like FreeCastReduced, but not reduce speed. ShowSkillScale: true/false (boolean, defaults to false) AllowReproduce: true/false (boolean, defaults to false) + HiddenTrap: true/false (boolean, defaults to false) } AttackType: "Attack Type" (string, defaults to "None") Types: "None", "Weapon", "Magic" or "Misc" diff --git a/db/re/skill_db.conf b/db/re/skill_db.conf index 4863e4051..842a50143 100644 --- a/db/re/skill_db.conf +++ b/db/re/skill_db.conf @@ -75,6 +75,7 @@ Works like FreeCastReduced, but not reduce speed. ShowSkillScale: true/false (boolean, defaults to false) AllowReproduce: true/false (boolean, defaults to false) + HiddenTrap: true/false (boolean, defaults to false) } AttackType: "Attack Type" (string, defaults to "None") Types: "None", "Weapon", "Magic" or "Misc" @@ -4110,6 +4111,7 @@ skill_db: ( } SkillInfo: { Trap: true + HiddenTrap: true } AttackType: "Misc" DamageType: { @@ -4170,6 +4172,7 @@ skill_db: ( SkillInfo: { Trap: true AllowReproduce: true + HiddenTrap: true } AttackType: "Misc" Element: "Ele_Earth" @@ -4222,6 +4225,7 @@ skill_db: ( } SkillInfo: { Trap: true + HiddenTrap: true } AttackType: "Misc" DamageType: { @@ -4281,6 +4285,7 @@ skill_db: ( } SkillInfo: { Trap: true + HiddenTrap: true } AttackType: "Misc" DamageType: { @@ -4329,6 +4334,7 @@ skill_db: ( } SkillInfo: { Trap: true + HiddenTrap: true } AttackType: "Misc" DamageType: { @@ -4390,6 +4396,7 @@ skill_db: ( } SkillInfo: { Trap: true + HiddenTrap: true } AttackType: "Misc" DamageType: { @@ -4452,6 +4459,7 @@ skill_db: ( SkillInfo: { Trap: true AllowReproduce: true + HiddenTrap: true } AttackType: "Weapon" Element: "Ele_Water" @@ -4636,6 +4644,7 @@ skill_db: ( } SkillInfo: { Trap: true + HiddenTrap: true } AttackType: "Misc" DamageType: { -- cgit v1.2.3-70-g09d2 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() --- db/constants.conf | 2 ++ doc/constants.md | 2 ++ doc/permissions.md | 1 + doc/script_commands.txt | 9 +++++++++ src/map/atcommand.c | 15 +++++++++++++-- src/map/map.c | 26 ++++++++++++++++++++++++++ src/map/map.h | 2 ++ src/map/npc.c | 4 ++++ src/map/pc_groups.c | 1 + src/map/pc_groups.h | 1 + src/map/script.c | 19 +++++++++++++++++++ src/map/script.h | 4 +++- 12 files changed, 83 insertions(+), 3 deletions(-) (limited to 'db') diff --git a/db/constants.conf b/db/constants.conf index 08dc63b40..a6c74d56d 100644 --- a/db/constants.conf +++ b/db/constants.conf @@ -424,6 +424,8 @@ constants_db: { mf_noviewid: 56 mf_pairship_startable: 57 mf_pairship_endable: 58 + mf_nostorage: 59 + mf_nogstorage: 60 comment__: "Cell Properties" cell_walkable: 0 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: diff --git a/src/map/atcommand.c b/src/map/atcommand.c index 6cfa86163..b8a2670ec 100644 --- a/src/map/atcommand.c +++ b/src/map/atcommand.c @@ -871,6 +871,11 @@ ACMD(storage) if (sd->npc_id || sd->state.vending || sd->state.buyingstore || sd->state.trading || sd->state.storage_flag) return false; + if (!pc_has_permission(sd, PC_PERM_BYPASS_NOSTORAGE) && (map->list[sd->bl.m].flag.nostorage & 1)) { // mapflag nostorage already defined? can't open :c + clif->message(fd, msg_fd(fd, 1161)); // You currently cannot open your storage. + return false; + } + if (storage->open(sd) == 1) { //Already open. clif->message(fd, msg_fd(fd,250)); // You have already opened your storage. Close it first. return false; @@ -904,6 +909,11 @@ ACMD(guildstorage) return false; } + if (!pc_has_permission(sd, PC_PERM_BYPASS_NOSTORAGE) && (map->list[sd->bl.m].flag.nogstorage & 1)) { // mapflag nogstorage already defined? can't open :c + clif->message(fd, msg_fd(fd, 1161)); // You currently cannot open your storage. (there is no other messages...) + return false; + } + if( gstorage->open(sd) ) { clif->message(fd, msg_fd(fd,1201)); // Your guild's storage has already been opened by another member, try again later. return false; @@ -7739,6 +7749,7 @@ ACMD(mapflag) CHECKFLAG(nodrop); CHECKFLAG(novending); CHECKFLAG(loadevent); CHECKFLAG(nochat); CHECKFLAG(partylock); CHECKFLAG(guildlock); CHECKFLAG(src4instance); CHECKFLAG(notomb); CHECKFLAG(nocashshop); CHECKFLAG(noviewid); CHECKFLAG(town); + CHECKFLAG(nostorage); CHECKFLAG(nogstorage); clif->message(sd->fd," "); clif->message(sd->fd,msg_fd(fd,1312)); // Usage: "@mapflag monster_noteleport 1" (0=Off | 1=On) clif->message(sd->fd,msg_fd(fd,1313)); // Type "@mapflag available" to list the available mapflags. @@ -7780,7 +7791,7 @@ ACMD(mapflag) SETFLAG(nomvploot); SETFLAG(nightenabled); SETFLAG(nodrop); SETFLAG(novending); SETFLAG(loadevent); SETFLAG(nochat); SETFLAG(partylock); SETFLAG(guildlock); SETFLAG(src4instance); SETFLAG(notomb); SETFLAG(nocashshop); SETFLAG(noviewid); - SETFLAG(town); + SETFLAG(town); SETFLAG(nostorage); SETFLAG(nogstorage); clif->message(sd->fd, msg_fd(fd, 1314)); // Invalid flag name or flag. @@ -7793,7 +7804,7 @@ ACMD(mapflag) clif->message(sd->fd, "nozenypenalty, notrade, noskill, nowarp, nowarpto, noicewall, snow, clouds, clouds2,"); clif->message(sd->fd, "fog, fireworks, sakura, leaves, nobaseexp, nojobexp, nomobloot,"); clif->message(sd->fd, "nomvploot, nightenabled, nodrop, novending, loadevent, nochat, partylock,"); - clif->message(sd->fd, "guildlock, src4instance, notomb, nocashshop, noviewid"); + clif->message(sd->fd, "guildlock, src4instance, notomb, nocashshop, noviewid, nostorage, nogstorage"); #undef CHECKFLAG #undef SETFLAG diff --git a/src/map/map.c b/src/map/map.c index 93e86f80b..a0ac8cd95 100644 --- a/src/map/map.c +++ b/src/map/map.c @@ -5425,6 +5425,32 @@ static bool map_zone_mf_cache(int m, char *flag, char *params) else if( map->list[m].flag.nocashshop ) map_zone_mf_cache_add(m,"nocashshop"); } + } else if (strcmpi(flag, "nostorage") == 0) { + if (!state) { + if (map->list[m].flag.nostorage != 0) { + sprintf(rflag, "nostorage\t%d", map->list[m].flag.nostorage); + map_zone_mf_cache_add(m, rflag); + } + } + if (sscanf(params, "%d", &state) == 1) { + if (state != map->list[m].flag.nostorage) { + sprintf(rflag, "nostorage\t%d", state); + map_zone_mf_cache_add(m, rflag); + } + } + } else if (strcmpi(flag, "nogstorage") == 0) { + if (!state) { + if (map->list[m].flag.nogstorage != 0) { + sprintf(rflag, "nogstorage\t%d", map->list[m].flag.nogstorage); + map_zone_mf_cache_add(m, rflag); + } + } + if (sscanf(params, "%d", &state) == 1) { + if (state != map->list[m].flag.nogstorage) { + sprintf(rflag, "nogstorage\t%d", state); + map_zone_mf_cache_add(m, rflag); + } + } } return false; diff --git a/src/map/map.h b/src/map/map.h index 4267c2c88..25ff63edc 100644 --- a/src/map/map.h +++ b/src/map/map.h @@ -899,6 +899,8 @@ struct map_data { unsigned noautoloot : 1; unsigned pairship_startable : 1; unsigned pairship_endable : 1; + unsigned nostorage : 2; + unsigned nogstorage : 2; uint32 noviewid; ///< noviewid (bitmask - @see enum equip_pos) } flag; struct point save; diff --git a/src/map/npc.c b/src/map/npc.c index 7f57a9c50..fa277f382 100644 --- a/src/map/npc.c +++ b/src/map/npc.c @@ -4555,6 +4555,10 @@ static const char *npc_parse_mapflag(const char *w1, const char *w2, const char map->list[m].flag.pairship_startable = (state) ? 1 : 0; } else if (!strcmpi(w3, "pairship_endable")) { map->list[m].flag.pairship_endable = (state) ? 1 : 0; + } else if (!strcmpi(w3, "nostorage")) { + map->list[m].flag.nostorage = (state) ? cap_value(atoi(w4), 1, 3) : 0; + } else if (!strcmpi(w3, "nogstorage")) { + map->list[m].flag.nogstorage = (state) ? cap_value(atoi(w4), 1, 3) : 0; } else { npc->parse_unknown_mapflag(mapname, w3, w4, start, buffer, filepath, retval); } diff --git a/src/map/pc_groups.c b/src/map/pc_groups.c index 887c946e3..8d55897b8 100644 --- a/src/map/pc_groups.c +++ b/src/map/pc_groups.c @@ -449,6 +449,7 @@ static void do_init_pc_groups(void) { "disable_store", PC_PERM_DISABLE_STORE }, { "disable_exp", PC_PERM_DISABLE_EXP }, { "disable_skill_usage", PC_PERM_DISABLE_SKILL_USAGE }, + { "bypass_nostorage", PC_PERM_BYPASS_NOSTORAGE }, }; unsigned char i, len = ARRAYLENGTH(pc_g_defaults); diff --git a/src/map/pc_groups.h b/src/map/pc_groups.h index 6070809e0..f3994b9c4 100644 --- a/src/map/pc_groups.h +++ b/src/map/pc_groups.h @@ -57,6 +57,7 @@ enum e_pc_permission { PC_PERM_DISABLE_STORE = 0x1000000, PC_PERM_DISABLE_EXP = 0x2000000, PC_PERM_DISABLE_SKILL_USAGE = 0x4000000, + PC_PERM_BYPASS_NOSTORAGE = 0x8000000, }; // Cached config settings for quick lookup diff --git a/src/map/script.c b/src/map/script.c index 41f21cd72..e92c4c227 100644 --- a/src/map/script.c +++ b/src/map/script.c @@ -10561,6 +10561,12 @@ static BUILDIN(openstorage) return false; } + // Mapflag preventing from openstorage here + if (!pc_has_permission(sd, PC_PERM_BYPASS_NOSTORAGE) && (map->list[sd->bl.m].flag.nostorage & 2)) { + script_pushint(st, 0); + return true; + } + storage->open(sd); script_pushint(st, 1); // success flag. @@ -10574,6 +10580,12 @@ static BUILDIN(guildopenstorage) if (sd == NULL) return true; + // Mapflag preventing from openstorage here + if (!pc_has_permission(sd, PC_PERM_BYPASS_NOSTORAGE) && (map->list[sd->bl.m].flag.nogstorage & 2)) { + script_pushint(st, 1); + return true; + } + ret = gstorage->open(sd); script_pushint(st,ret); return true; @@ -13064,6 +13076,8 @@ static BUILDIN(getmapflag) case MF_NOVIEWID: script_pushint(st, map->list[m].flag.noviewid); break; case MF_PAIRSHIP_STARTABLE: script_pushint(st, map->list[m].flag.pairship_startable); break; case MF_PAIRSHIP_ENDABLE: script_pushint(st, map->list[m].flag.pairship_endable); break; + case MF_NOSTORAGE: script_pushint(st, map->list[m].flag.nostorage); break; + case MF_NOGSTORAGE: script_pushint(st, map->list[m].flag.nogstorage); break; } } @@ -13194,6 +13208,8 @@ static BUILDIN(setmapflag) case MF_NOVIEWID: map->list[m].flag.noviewid = (val <= 0) ? EQP_NONE : val; break; case MF_PAIRSHIP_STARTABLE: map->list[m].flag.pairship_startable = 1; break; case MF_PAIRSHIP_ENDABLE: map->list[m].flag.pairship_endable = 1; break; + case MF_NOSTORAGE: map->list[m].flag.nostorage = cap_value(val, 0, 3); break; + case MF_NOGSTORAGE: map->list[m].flag.nogstorage = cap_value(val, 0, 3); break; } } @@ -13285,6 +13301,8 @@ static BUILDIN(removemapflag) case MF_NOCASHSHOP: map->list[m].flag.nocashshop = 0; break; case MF_NOAUTOLOOT: map->list[m].flag.noautoloot = 0; break; case MF_NOVIEWID: map->list[m].flag.noviewid = EQP_NONE; break; + case MF_NOSTORAGE: map->list[m].flag.nostorage = 0; break; + case MF_NOGSTORAGE: map->list[m].flag.nogstorage = 0; break; } } @@ -25755,6 +25773,7 @@ static void script_hardcoded_constants(void) script->set_constant("PERM_DISABLE_STORE", PC_PERM_DISABLE_STORE, false, false); script->set_constant("PERM_DISABLE_EXP", PC_PERM_DISABLE_EXP, false, false); script->set_constant("PERM_DISABLE_SKILL_USAGE", PC_PERM_DISABLE_SKILL_USAGE, false, false); + script->set_constant("PERM_BYPASS_NOSTORAGE", PC_PERM_BYPASS_NOSTORAGE, false, false); script->constdb_comment("Data types"); script->set_constant("DATATYPE_NIL", DATATYPE_NIL, false, false); diff --git a/src/map/script.h b/src/map/script.h index 549ad3284..e577867ba 100644 --- a/src/map/script.h +++ b/src/map/script.h @@ -343,7 +343,9 @@ enum { MF_NOAUTOLOOT, MF_NOVIEWID, MF_PAIRSHIP_STARTABLE, - MF_PAIRSHIP_ENDABLE + MF_PAIRSHIP_ENDABLE, + MF_NOSTORAGE, + MF_NOGSTORAGE }; enum navigation_service { -- 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 'db') 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 'db') 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 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 'db') 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 8b68128d64cb6f19ced4e81afc6f67cd05fadd3c Mon Sep 17 00:00:00 2001 From: Emistry Haoyan Date: Sun, 14 Apr 2019 20:52:37 +0800 Subject: Update item combo db, fix issue #1982 - update missing item_combo_db --- db/re/item_combo_db.txt | 1 + 1 file changed, 1 insertion(+) (limited to 'db') diff --git a/db/re/item_combo_db.txt b/db/re/item_combo_db.txt index 739be9a65..3cbaef807 100644 --- a/db/re/item_combo_db.txt +++ b/db/re/item_combo_db.txt @@ -436,3 +436,4 @@ 24238:24239,{ bonus bAtk,5; if(getequiprefinerycnt(EQI_SHADOW_ACC_R) + getequiprefinerycnt(EQI_SHADOW_ACC_L) >=15) { bonus2 bAddSize,Size_Small,1; } } 24240:24241:24242,{ bonus bUseSPrate,-1; .@refine = getequiprefinerycnt(EQI_SHADOW_SHIELD)+getequiprefinerycnt(EQI_SHADOW_ARMOR)+getequiprefinerycnt(EQI_SHADOW_SHOES); bonus bVariableCastrate,(.@refine)/5; if(.@refine)>=25 { bonus bUseSPrate,-1; } } 24243:24244:24245,{ bonus bDelayrate,-1; if (getequiprefinerycnt(EQI_SHADOW_SHIELD)+getequiprefinerycnt(EQI_SHADOW_ARMOR)+getequiprefinerycnt(EQI_SHADOW_SHOES) >= 25) bonus bDelayrate,-5; } +2161:1646,{ .@r = (getequiprefinerycnt(EQI_HAND_L)*4); bonus2 bVariableCastrate,"WZ_STORMGUST",-.@r; bonus2 bVariableCastrate,"WL_FROSTMISTY",-.@r; bonus2 bVariableCastrate,"WL_JACKFROST",-.@r; } -- 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 'db') 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: + : ( + {