Revamped Laphine UIs (#6625)
Fixes #3302 Closes #4348 Thanks for the initial release by @Cydh in #4348 and everyone that contributed to it. All existing data was migrated and cleaned up where necessary. Thanks to @Everade for his help here. Laphine UIs are now fully yamlified and not dependent on the script engine. They make use of new item group features and of the already existing random option group feature. This way they will be far easier to be maintained, even though they are a little less customize able. Thanks to @limitro, @CairoLee, @dimasshotta and everyone else who contributed! Co-authored-by: Cydh <cydh.ramdh@gmail.com> Co-authored-by: Everade <Everade@users.noreply.github.com> Co-authored-by: Aleos <aleos89@users.noreply.github.com>
This commit is contained in:
parent
5227167716
commit
08192a35bc
@ -35,10 +35,13 @@
|
||||
# Stacked Whether stackable items are given stacked or not. (Default: true)
|
||||
# Named Inscribes the item with the obtainer's name. (Default: false)
|
||||
# Bound Binds the obtained item. (Default: None)
|
||||
# RandomOptionGroup Applies random options of this group to all equipable items (Default: None)
|
||||
# RefineMinimum Applies at least this refine level to all equipable items (Default: 0)
|
||||
# RefineMaximum Applies at most this refine level to all equipable items (Default: 0)
|
||||
# Clear Remove the given item. (Optional)
|
||||
# Clear Remove the given SubGroup. (Optional)
|
||||
###########################################################################
|
||||
|
||||
Header:
|
||||
Type: ITEM_GROUP_DB
|
||||
Version: 1
|
||||
Version: 2
|
||||
|
37
db/import-tmpl/laphine_synthesis.yml
Normal file
37
db/import-tmpl/laphine_synthesis.yml
Normal file
@ -0,0 +1,37 @@
|
||||
# This file is a part of rAthena.
|
||||
# Copyright(C) 2022 rAthena Development Team
|
||||
# https://rathena.org - https://github.com/rathena
|
||||
#
|
||||
# This program 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 <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
###########################################################################
|
||||
# Laphine Synthesis Database
|
||||
###########################################################################
|
||||
#
|
||||
# Laphine Synthesis Settings
|
||||
#
|
||||
###########################################################################
|
||||
# - Item Item that triggers Laphine Synthesis.
|
||||
# RewardGroup Item Group that will be given out as a reward.
|
||||
# RequiredRequirementsCount Amount of requirements that have to be fulfilled. (Default: 1)
|
||||
# MinimumRefine Minimum refine level of the required items. (Default: 0)
|
||||
# MaximumRefine Maximum refine level of the required items. (Default: MAX_REFINE)
|
||||
# Requirements: List of possible requirement items.
|
||||
# - Item Item name of the required item
|
||||
# Amount Amount of specific required item. (Default: 1)
|
||||
###########################################################################
|
||||
|
||||
Header:
|
||||
Type: LAPHINE_SYNTHESIS_DB
|
||||
Version: 1
|
40
db/import-tmpl/laphine_upgrade.yml
Normal file
40
db/import-tmpl/laphine_upgrade.yml
Normal file
@ -0,0 +1,40 @@
|
||||
# This file is a part of rAthena.
|
||||
# Copyright(C) 2022 rAthena Development Team
|
||||
# https://rathena.org - https://github.com/rathena
|
||||
#
|
||||
# This program 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 <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
###########################################################################
|
||||
# Laphine Upgrade Database
|
||||
###########################################################################
|
||||
#
|
||||
# Laphine Upgrade Settings
|
||||
#
|
||||
###########################################################################
|
||||
# - Item Item that triggers Laphine Upgrade.
|
||||
# RandomOptionGroup Name of the random option group that will be applied. (Default: none)
|
||||
# ResultRefine Absolute refine level after the upgrade. (Default: none)
|
||||
# ResultRefineMinimum Minimum refine level after the upgrade. (Default: none)
|
||||
# ResultRefineMaximum Maximum refine level after the upgrade. (Default: none)
|
||||
# MinimumRefine Minimum refine level of the required items. (Default: 0)
|
||||
# MaximumRefine Maximum refine level of the required items. (Default: MAX_REFINE)
|
||||
# RequiredRandomOptions How many random options have to be in the item? (Default: 0)
|
||||
# CardsAllowed Are cards allowed in the target item? (Default: no)
|
||||
# TargetItems: List of possible target item(s)
|
||||
# - Item Item name of the possible target item
|
||||
###########################################################################
|
||||
|
||||
Header:
|
||||
Type: LAPHINE_UPGRADE_DB
|
||||
Version: 1
|
@ -35,13 +35,16 @@
|
||||
# Stacked Whether stackable items are given stacked or not. (Default: true)
|
||||
# Named Inscribes the item with the obtainer's name. (Default: false)
|
||||
# Bound Binds the obtained item. (Default: None)
|
||||
# RandomOptionGroup Applies random options of this group to all equipable items (Default: None)
|
||||
# RefineMinimum Applies at least this refine level to all equipable items (Default: 0)
|
||||
# RefineMaximum Applies at most this refine level to all equipable items (Default: 0)
|
||||
# Clear Remove the given item. (Optional)
|
||||
# Clear Remove the given SubGroup. (Optional)
|
||||
###########################################################################
|
||||
|
||||
Header:
|
||||
Type: ITEM_GROUP_DB
|
||||
Version: 1
|
||||
Version: 2
|
||||
|
||||
Footer:
|
||||
Imports:
|
||||
|
43
db/laphine_synthesis.yml
Normal file
43
db/laphine_synthesis.yml
Normal file
@ -0,0 +1,43 @@
|
||||
# This file is a part of rAthena.
|
||||
# Copyright(C) 2022 rAthena Development Team
|
||||
# https://rathena.org - https://github.com/rathena
|
||||
#
|
||||
# This program 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 <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
###########################################################################
|
||||
# Laphine Synthesis Database
|
||||
###########################################################################
|
||||
#
|
||||
# Laphine Synthesis Settings
|
||||
#
|
||||
###########################################################################
|
||||
# - Item Item that triggers Laphine Synthesis.
|
||||
# RewardGroup Item Group that will be given out as a reward.
|
||||
# RequiredRequirementsCount Amount of requirements that have to be fulfilled. (Default: 1)
|
||||
# MinimumRefine Minimum refine level of the required items. (Default: 0)
|
||||
# MaximumRefine Maximum refine level of the required items. (Default: MAX_REFINE)
|
||||
# Requirements: List of possible requirement items.
|
||||
# - Item Item name of the required item
|
||||
# Amount Amount of specific required item. (Default: 1)
|
||||
###########################################################################
|
||||
|
||||
Header:
|
||||
Type: LAPHINE_SYNTHESIS_DB
|
||||
Version: 1
|
||||
|
||||
Footer:
|
||||
Imports:
|
||||
- Path: db/re/laphine_synthesis.yml
|
||||
Mode: Renewal
|
||||
- Path: db/import/laphine_synthesis.yml
|
46
db/laphine_upgrade.yml
Normal file
46
db/laphine_upgrade.yml
Normal file
@ -0,0 +1,46 @@
|
||||
# This file is a part of rAthena.
|
||||
# Copyright(C) 2022 rAthena Development Team
|
||||
# https://rathena.org - https://github.com/rathena
|
||||
#
|
||||
# This program 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 <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
###########################################################################
|
||||
# Laphine Upgrade Database
|
||||
###########################################################################
|
||||
#
|
||||
# Laphine Upgrade Settings
|
||||
#
|
||||
###########################################################################
|
||||
# - Item Item that triggers Laphine Upgrade.
|
||||
# RandomOptionGroup Name of the random option group that will be applied. (Default: none)
|
||||
# ResultRefine Absolute refine level after the upgrade. (Default: none)
|
||||
# ResultRefineMinimum Minimum refine level after the upgrade. (Default: none)
|
||||
# ResultRefineMaximum Maximum refine level after the upgrade. (Default: none)
|
||||
# MinimumRefine Minimum refine level of the required items. (Default: 0)
|
||||
# MaximumRefine Maximum refine level of the required items. (Default: MAX_REFINE)
|
||||
# RequiredRandomOptions How many random options have to be in the item? (Default: 0)
|
||||
# CardsAllowed Are cards allowed in the target item? (Default: no)
|
||||
# TargetItems: List of possible target item(s)
|
||||
# - Item Item name of the possible target item
|
||||
###########################################################################
|
||||
|
||||
Header:
|
||||
Type: LAPHINE_UPGRADE_DB
|
||||
Version: 1
|
||||
|
||||
Footer:
|
||||
Imports:
|
||||
- Path: db/re/laphine_upgrade.yml
|
||||
Mode: Renewal
|
||||
- Path: db/import/laphine_upgrade.yml
|
@ -35,13 +35,16 @@
|
||||
# Stacked Whether stackable items are given stacked or not. (Default: true)
|
||||
# Named Inscribes the item with the obtainer's name. (Default: false)
|
||||
# Bound Binds the obtained item. (Default: None)
|
||||
# RandomOptionGroup Applies random options of this group to all equipable items (Default: None)
|
||||
# RefineMinimum Applies at least this refine level to all equipable items (Default: 0)
|
||||
# RefineMaximum Applies at most this refine level to all equipable items (Default: 0)
|
||||
# Clear Remove the given item. (Optional)
|
||||
# Clear Remove the given SubGroup. (Optional)
|
||||
###########################################################################
|
||||
|
||||
Header:
|
||||
Type: ITEM_GROUP_DB
|
||||
Version: 1
|
||||
Version: 2
|
||||
|
||||
Body:
|
||||
- Group: ACCESORY
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
4492
db/re/laphine_synthesis.yml
Normal file
4492
db/re/laphine_synthesis.yml
Normal file
File diff suppressed because it is too large
Load Diff
5065
db/re/laphine_upgrade.yml
Normal file
5065
db/re/laphine_upgrade.yml
Normal file
File diff suppressed because it is too large
Load Diff
@ -2896,22 +2896,6 @@ is invalid or if there is no item in the equipment slot.
|
||||
|
||||
---------------------------------------
|
||||
|
||||
*refineui({<char id>})
|
||||
|
||||
Opens the refine UI for the attached player or the given character id.
|
||||
|
||||
This feature requires 2016-10-12aRagexeRE or newer.
|
||||
|
||||
---------------------------------------
|
||||
|
||||
*openstylist({<char id>})
|
||||
|
||||
Opens the stylist UI for the attached player or the given character id.
|
||||
|
||||
This feature requires packet version 2015-11-04 or newer.
|
||||
|
||||
---------------------------------------
|
||||
|
||||
*getareadropitem("<map name>",<x1>,<y1>,<x2>,<y2>,<item>)
|
||||
|
||||
This function will count all the items with the specified ID number lying on the
|
||||
@ -8079,6 +8063,42 @@ The values given will be divided by 100 and transmitted as floating-point number
|
||||
Default: -50000 (-50.0)
|
||||
Maximum: -75000 (-75.0)
|
||||
|
||||
---------------------------------------
|
||||
|
||||
*refineui({<char id>})
|
||||
|
||||
Opens the refine UI for the attached player or the given character id.
|
||||
|
||||
This feature requires 2016-10-12aRagexeRE or newer.
|
||||
|
||||
---------------------------------------
|
||||
|
||||
*openstylist({<char id>})
|
||||
|
||||
Opens the stylist UI for the attached player or the given character id.
|
||||
|
||||
This feature requires packet version 2015-11-04 or newer.
|
||||
|
||||
---------------------------------------
|
||||
|
||||
*laphine_synthesis()
|
||||
|
||||
Opens the laphine synthesis UI for the attached player.
|
||||
|
||||
This feature requires packet version 2016-06-01 or newer.
|
||||
|
||||
This function is intended for use in item scripts.
|
||||
|
||||
---------------------------------------
|
||||
|
||||
*laphine_upgrade()
|
||||
|
||||
Opens the laphine upgrade UI for the attached player.
|
||||
|
||||
This feature requires packet version 2017-07-26 or newer.
|
||||
|
||||
This function is intended for use in item scripts.
|
||||
|
||||
---------------------------------------
|
||||
\\
|
||||
6,1.- Unit-related commands
|
||||
|
@ -18,6 +18,9 @@
|
||||
# Stacked Whether stackable items are given stacked or not. (Default: true)
|
||||
# Named Inscribes the item with the obtainer's name. (Default: false)
|
||||
# Bound Binds the obtained item. (Default: None)
|
||||
# RandomOptionGroup Applies random options of this group to all equipable items (Default: None)
|
||||
# RefineMinimum Applies at least this refine level to all equipable items (Default: 0)
|
||||
# RefineMaximum Applies at most this refine level to all equipable items (Default: 0)
|
||||
# Clear Remove the given item. (Optional)
|
||||
# Clear Remove the given SubGroup. (Optional)
|
||||
###########################################################################
|
||||
|
@ -167,12 +167,13 @@ CREATE TABLE IF NOT EXISTS `npclog` (
|
||||
# (Q)uest
|
||||
# Private Airs(H)ip
|
||||
# Barter Shop (J)
|
||||
# Laphine systems (W)
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `picklog` (
|
||||
`id` int(11) NOT NULL auto_increment,
|
||||
`time` datetime NOT NULL,
|
||||
`char_id` int(11) NOT NULL default '0',
|
||||
`type` enum('M','P','L','T','V','S','N','C','A','R','G','E','B','O','I','X','D','U','$','F','Y','Z','Q','H','J') NOT NULL default 'P',
|
||||
`type` enum('M','P','L','T','V','S','N','C','A','R','G','E','B','O','I','X','D','U','$','F','Y','Z','Q','H','J','W') NOT NULL default 'P',
|
||||
`nameid` int(10) unsigned NOT NULL default '0',
|
||||
`amount` int(11) NOT NULL default '1',
|
||||
`refine` tinyint(3) unsigned NOT NULL default '0',
|
||||
|
7
sql-files/upgrades/upgrade_20220222_logs.sql
Normal file
7
sql-files/upgrades/upgrade_20220222_logs.sql
Normal file
@ -0,0 +1,7 @@
|
||||
ALTER TABLE `picklog`
|
||||
MODIFY `type` enum('M','P','L','T','V','S','N','C','A','R','G','E','B','O','I','X','D','U','$','F','Y','Z','Q','H','J') NOT NULL default 'P'
|
||||
;
|
||||
|
||||
ALTER TABLE `zenylog`
|
||||
MODIFY `type` enum('T','V','P','M','S','N','D','C','A','E','I','B','K','J') NOT NULL default 'S'
|
||||
;
|
339
src/map/clif.cpp
339
src/map/clif.cpp
@ -23085,6 +23085,345 @@ void clif_summon_hp_bar(struct mob_data& md) {
|
||||
#endif
|
||||
}
|
||||
|
||||
void clif_laphine_synthesis_open( struct map_session_data *sd, std::shared_ptr<s_laphine_synthesis> synthesis ){
|
||||
#if PACKETVER_MAIN_NUM >= 20160601 || PACKETVER_RE_NUM >= 20160525 || defined(PACKETVER_ZERO)
|
||||
nullpo_retv( sd );
|
||||
|
||||
sd->state.laphine_synthesis = synthesis->item_id;
|
||||
|
||||
struct PACKET_ZC_LAPINEDDUKDDAK_OPEN p = {};
|
||||
|
||||
p.packetType = HEADER_ZC_LAPINEDDUKDDAK_OPEN;
|
||||
p.itemId = client_nameid( synthesis->item_id );
|
||||
|
||||
clif_send( &p, sizeof( p ), &sd->bl, SELF );
|
||||
#endif
|
||||
}
|
||||
|
||||
void clif_parse_laphine_synthesis_close( int fd, struct map_session_data* sd ){
|
||||
#if PACKETVER_MAIN_NUM >= 20160601 || PACKETVER_RE_NUM >= 20160525 || defined(PACKETVER_ZERO)
|
||||
sd->state.laphine_synthesis = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
enum e_laphine_synthesis_result : int16{
|
||||
LAPHINE_SYNTHESIS_SUCCESS = 0,
|
||||
LAPHINE_SYNTHESIS_AMOUNT = 5,
|
||||
LAPHINE_SYNTHESIS_ITEM = 7
|
||||
};
|
||||
|
||||
void clif_laphine_synthesis_result( struct map_session_data* sd, enum e_laphine_synthesis_result result ){
|
||||
#if PACKETVER_MAIN_NUM >= 20160601 || PACKETVER_RE_NUM >= 20160525 || defined(PACKETVER_ZERO)
|
||||
nullpo_retv( sd );
|
||||
|
||||
struct PACKET_ZC_LAPINEDDUKDDAK_RESULT p = {};
|
||||
|
||||
p.packetType = HEADER_ZC_LAPINEDDUKDDAK_RESULT;
|
||||
p.result = result;
|
||||
|
||||
clif_send( &p, sizeof( p ), &sd->bl, SELF );
|
||||
#endif
|
||||
}
|
||||
|
||||
void clif_parse_laphine_synthesis( int fd, struct map_session_data* sd ){
|
||||
#if PACKETVER_MAIN_NUM >= 20160601 || PACKETVER_RE_NUM >= 20160525 || defined(PACKETVER_ZERO)
|
||||
if( sd->state.laphine_synthesis == 0 ){
|
||||
return;
|
||||
}
|
||||
|
||||
struct PACKET_CZ_LAPINEDDUKDDAK_ACK* p = (struct PACKET_CZ_LAPINEDDUKDDAK_ACK*)RFIFOP( fd, 0 );
|
||||
|
||||
if( sd->state.laphine_synthesis != p->itemId ){
|
||||
return;
|
||||
}
|
||||
|
||||
std::shared_ptr<s_laphine_synthesis> synthesis = laphine_synthesis_db.find( sd->state.laphine_synthesis );
|
||||
|
||||
if( synthesis == nullptr ){
|
||||
return;
|
||||
}
|
||||
|
||||
size_t count = ( p->packetLength - sizeof( struct PACKET_CZ_LAPINEDDUKDDAK_ACK ) ) / sizeof( struct PACKET_CZ_LAPINEDDUKDDAK_ACK_sub );
|
||||
|
||||
// Player sent more or less than actually required
|
||||
if( count != synthesis->requiredRequirements ){
|
||||
return;
|
||||
}
|
||||
|
||||
// Check for duplicates
|
||||
for( size_t i = 0; i < count; i++ ){
|
||||
for( size_t j = i + 1; j < count; j++ ){
|
||||
if( p->items[i].index == p->items[j].index ){
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for( size_t i = 0; i < count; i++ ){
|
||||
int16 index = server_index( p->items[i].index );
|
||||
|
||||
if( index >= MAX_INVENTORY ){
|
||||
return;
|
||||
}
|
||||
|
||||
if( sd->inventory_data[i] == nullptr ){
|
||||
return;
|
||||
}
|
||||
|
||||
struct item* item = &sd->inventory.u.items_inventory[index];
|
||||
|
||||
std::shared_ptr<s_laphine_synthesis_requirement> requirement = util::umap_find( synthesis->requirements, item->nameid );
|
||||
|
||||
if( requirement == nullptr ){
|
||||
clif_laphine_synthesis_result( sd, LAPHINE_SYNTHESIS_ITEM );
|
||||
return;
|
||||
}
|
||||
|
||||
if( p->items[i].count != requirement->amount ){
|
||||
clif_laphine_synthesis_result( sd, LAPHINE_SYNTHESIS_AMOUNT );
|
||||
return;
|
||||
}
|
||||
|
||||
if( item->amount < requirement->amount ){
|
||||
clif_laphine_synthesis_result( sd, LAPHINE_SYNTHESIS_AMOUNT );
|
||||
return;
|
||||
}
|
||||
|
||||
if( item->refine < synthesis->minimumRefine ){
|
||||
clif_laphine_synthesis_result( sd, LAPHINE_SYNTHESIS_ITEM );
|
||||
return;
|
||||
}
|
||||
|
||||
if( item->refine > synthesis->maximumRefine ){
|
||||
clif_laphine_synthesis_result( sd, LAPHINE_SYNTHESIS_ITEM );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
int16 index = pc_search_inventory( sd, sd->state.laphine_synthesis );
|
||||
|
||||
if( index < 0 ){
|
||||
clif_laphine_synthesis_result( sd, LAPHINE_SYNTHESIS_ITEM );
|
||||
return;
|
||||
}
|
||||
|
||||
if( ( sd->inventory_data[index]->flag.delay_consume & DELAYCONSUME_NOCONSUME ) == 0 ){
|
||||
if( pc_delitem( sd, index, 1, 0, 0, LOG_TYPE_CONSUME ) != 0 ){
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
for( size_t i = 0; i < count; i++ ){
|
||||
index = server_index( p->items[i].index );
|
||||
|
||||
if( pc_delitem( sd, index, p->items[i].count, 0, 0, LOG_TYPE_LAPHINE ) != 0 ){
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
itemdb_group.pc_get_itemgroup( synthesis->rewardGroupId, true, sd );
|
||||
|
||||
clif_laphine_synthesis_result( sd, LAPHINE_SYNTHESIS_SUCCESS );
|
||||
#endif
|
||||
}
|
||||
|
||||
void clif_laphine_upgrade_open( struct map_session_data* sd, std::shared_ptr<s_laphine_upgrade> upgrade ){
|
||||
#if PACKETVER_MAIN_NUM >= 20170726 || PACKETVER_RE_NUM >= 20170621 || defined(PACKETVER_ZERO)
|
||||
nullpo_retv( sd );
|
||||
|
||||
sd->state.laphine_upgrade = upgrade->item_id;
|
||||
|
||||
struct PACKET_ZC_LAPINEUPGRADE_OPEN p = {};
|
||||
|
||||
p.packetType = HEADER_ZC_LAPINEUPGRADE_OPEN;
|
||||
p.itemId = client_nameid( upgrade->item_id );
|
||||
|
||||
clif_send( &p, sizeof( p ), &sd->bl, SELF );
|
||||
#endif
|
||||
}
|
||||
|
||||
void clif_parse_laphine_upgrade_close( int fd, struct map_session_data* sd ){
|
||||
#if PACKETVER_MAIN_NUM >= 20170726 || PACKETVER_RE_NUM >= 20170621 || defined(PACKETVER_ZERO)
|
||||
sd->state.laphine_upgrade = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
void clif_laphine_upgrade_result( struct map_session_data *sd, bool failed ){
|
||||
#if PACKETVER_MAIN_NUM >= 20170726 || PACKETVER_RE_NUM >= 20170621 || defined(PACKETVER_ZERO)
|
||||
struct PACKET_ZC_LAPINEUPGRADE_RESULT p = {};
|
||||
|
||||
p.packetType = HEADER_ZC_LAPINEUPGRADE_RESULT;
|
||||
p.result = failed;
|
||||
|
||||
clif_send( &p, sizeof( p ), &sd->bl, SELF );
|
||||
#endif
|
||||
}
|
||||
|
||||
static void clif_item_preview( struct map_session_data *sd, int16 index ){
|
||||
#if PACKETVER_MAIN_NUM >= 20170726 || PACKETVER_RE_NUM >= 20170621 || defined(PACKETVER_ZERO)
|
||||
nullpo_retv( sd );
|
||||
|
||||
struct item* item = &sd->inventory.u.items_inventory[index];
|
||||
|
||||
struct PACKET_ZC_ITEM_PREVIEW p = {};
|
||||
|
||||
p.packetType = HEADER_ZC_ITEM_PREVIEW;
|
||||
p.index = client_index( index );
|
||||
#if PACKETVER_MAIN_NUM >= 20181017 || PACKETVER_RE_NUM >= 20181017 || PACKETVER_ZERO_NUM >= 20181024
|
||||
p.isDamaged = item->attribute != 0;
|
||||
#endif
|
||||
p.refiningLevel = item->refine;
|
||||
#if PACKETVER_MAIN_NUM >= 20200916 || PACKETVER_RE_NUM >= 20200723
|
||||
p.enchantgrade = item->enchantgrade;
|
||||
#endif
|
||||
clif_addcards( &p.slot, item );
|
||||
clif_add_random_options( p.option_data, item );
|
||||
|
||||
clif_send( &p, sizeof( p ), &sd->bl, SELF );
|
||||
#endif
|
||||
}
|
||||
|
||||
void clif_parse_laphine_upgrade( int fd, struct map_session_data* sd ){
|
||||
#if PACKETVER_MAIN_NUM >= 20170726 || PACKETVER_RE_NUM >= 20170621 || defined(PACKETVER_ZERO)
|
||||
if( sd->state.laphine_upgrade == 0 ){
|
||||
return;
|
||||
}
|
||||
|
||||
struct PACKET_CZ_LAPINEUPGRADE_MAKE_ITEM* p = (struct PACKET_CZ_LAPINEUPGRADE_MAKE_ITEM*)RFIFOP( fd, 0 );
|
||||
|
||||
if( sd->state.laphine_upgrade != p->itemId ){
|
||||
return;
|
||||
}
|
||||
|
||||
std::shared_ptr<s_laphine_upgrade> upgrade = laphine_upgrade_db.find( sd->state.laphine_upgrade );
|
||||
|
||||
if( upgrade == nullptr ){
|
||||
return;
|
||||
}
|
||||
|
||||
uint16 index = server_index( p->index );
|
||||
|
||||
if( index >= MAX_INVENTORY ){
|
||||
return;
|
||||
}
|
||||
|
||||
if( sd->inventory_data[index] == nullptr ){
|
||||
return;
|
||||
}
|
||||
|
||||
struct item* item = &sd->inventory.u.items_inventory[index];
|
||||
|
||||
// Not a valid target item
|
||||
if( !util::vector_exists( upgrade->target_item_ids, item->nameid ) ){
|
||||
clif_laphine_upgrade_result( sd, true );
|
||||
return;
|
||||
}
|
||||
|
||||
// If target item is not identified
|
||||
if( item->identify == 0 ){
|
||||
clif_laphine_upgrade_result( sd, true );
|
||||
return;
|
||||
}
|
||||
|
||||
// If target item is equipped
|
||||
if( item->equip != 0 ){
|
||||
clif_laphine_upgrade_result( sd, true );
|
||||
return;
|
||||
}
|
||||
|
||||
// Check minimum refine requirement
|
||||
if( item->refine < upgrade->minimumRefine ){
|
||||
clif_laphine_upgrade_result( sd, true );
|
||||
return;
|
||||
}
|
||||
|
||||
// Check maximum refine requirement
|
||||
if( item->refine > upgrade->maximumRefine ){
|
||||
clif_laphine_upgrade_result( sd, true );
|
||||
return;
|
||||
}
|
||||
|
||||
// If no cards are allowed
|
||||
if( !upgrade->cardsAllowed ){
|
||||
for( int i = 0; i < MAX_SLOTS; i++ ){
|
||||
if( item->card[i] != 0 ){
|
||||
clif_laphine_upgrade_result( sd, true );
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If random options are required
|
||||
if( upgrade->requiredRandomOptions > 0 ){
|
||||
int i;
|
||||
|
||||
for( i = MAX_ITEM_RDM_OPT - 1; i >= 0; i-- ){
|
||||
if( item->option[i].id != 0 ){
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if( ( i + 1 ) < upgrade->requiredRandomOptions ){
|
||||
clif_laphine_upgrade_result( sd, true );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
int16 index2 = pc_search_inventory( sd, sd->state.laphine_upgrade );
|
||||
|
||||
if( index2 < 0 ){
|
||||
clif_laphine_upgrade_result( sd, true );
|
||||
return;
|
||||
}
|
||||
|
||||
if( ( sd->inventory_data[index2]->flag.delay_consume & DELAYCONSUME_NOCONSUME ) == 0 ){
|
||||
if( pc_delitem( sd, index2, 1, 0, 0, LOG_TYPE_CONSUME ) != 0 ){
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Log removal of item
|
||||
log_pick_pc( sd, LOG_TYPE_LAPHINE, -1, item );
|
||||
|
||||
// Visually remove it from the client
|
||||
clif_delitem( sd, index, 1, 0 );
|
||||
|
||||
// Apply the random options
|
||||
if( upgrade->randomOptionGroup != nullptr ){
|
||||
upgrade->randomOptionGroup->apply( *item );
|
||||
}
|
||||
|
||||
// Change the refine rate if needed
|
||||
if( upgrade->resultRefine > 0 ){
|
||||
// Absolute refine level change
|
||||
item->refine = max( item->refine, upgrade->resultRefine );
|
||||
}else if( upgrade->resultRefineMaximum > 0 ){
|
||||
// If a minimum is specified it can also downgrade
|
||||
if( upgrade->resultRefineMinimum ){
|
||||
item->refine = rnd_value( upgrade->resultRefineMinimum, upgrade->resultRefineMaximum );
|
||||
}else{
|
||||
// Otherwise it can only be upgraded until the maximum, but not downgraded
|
||||
item->refine = rnd_value( item->refine, upgrade->resultRefineMaximum );
|
||||
}
|
||||
}else if( upgrade->resultRefineMinimum > 0 ){
|
||||
// No maximum has been specified, so it can be anything between minimum and MAX_REFINE
|
||||
item->refine = rnd_value( upgrade->resultRefineMinimum, MAX_REFINE );
|
||||
}
|
||||
|
||||
// Log retrieving the item again -> with the new options
|
||||
log_pick_pc( sd, LOG_TYPE_LAPHINE, 1, item );
|
||||
|
||||
// Make it visible for the client again
|
||||
clif_additem( sd, index, 1, 0 );
|
||||
|
||||
// Open a preview of the item
|
||||
clif_item_preview( sd, index );
|
||||
|
||||
// Tell the client we are done
|
||||
clif_laphine_upgrade_result( sd, false );
|
||||
#endif
|
||||
}
|
||||
|
||||
/*==========================================
|
||||
* Main client packet processing function
|
||||
*------------------------------------------*/
|
||||
|
@ -45,6 +45,8 @@ struct guild_log_entry;
|
||||
enum e_guild_storage_log : uint16;
|
||||
enum e_bg_queue_apply_ack : uint16;
|
||||
enum e_instance_notify : uint8;
|
||||
struct s_laphine_synthesis;
|
||||
struct s_laphine_upgrade;
|
||||
|
||||
enum e_PacketDBVersion { // packet DB
|
||||
MIN_PACKET_DB = 0x064,
|
||||
@ -1190,4 +1192,8 @@ void clif_barter_extended_open( struct map_session_data& sd, struct npc_data& nd
|
||||
void clif_summon_init(struct mob_data& md);
|
||||
void clif_summon_hp_bar(struct mob_data& md);
|
||||
|
||||
// Laphine System
|
||||
void clif_laphine_synthesis_open( struct map_session_data *sd, std::shared_ptr<s_laphine_synthesis> synthesis );
|
||||
void clif_laphine_upgrade_open( struct map_session_data* sd, std::shared_ptr<s_laphine_upgrade> upgrade );
|
||||
|
||||
#endif /* CLIF_HPP */
|
||||
|
@ -2292,6 +2292,11 @@
|
||||
packet(0x0A7D,-1);
|
||||
#endif
|
||||
|
||||
#if PACKETVER_MAIN_NUM >= 20160601 || PACKETVER_RE_NUM >= 20160525 || defined(PACKETVER_ZERO)
|
||||
parseable_packet( HEADER_CZ_LAPINEDDUKDDAK_CLOSE, sizeof( struct PACKET_CZ_LAPINEDDUKDDAK_CLOSE ), clif_parse_laphine_synthesis_close, 0 );
|
||||
parseable_packet( HEADER_CZ_LAPINEDDUKDDAK_ACK, -1, clif_parse_laphine_synthesis, 0 );
|
||||
#endif
|
||||
|
||||
// 2016-06-22aRagexeRE
|
||||
#if PACKETVER >= 20160622
|
||||
packet(0x0A84,94);
|
||||
@ -2344,6 +2349,11 @@
|
||||
parseable_packet(0x0ACE,4,clif_parse_equipswitch_request_single,0);
|
||||
#endif
|
||||
|
||||
#if PACKETVER_MAIN_NUM >= 20170726 || PACKETVER_RE_NUM >= 20170621 || defined(PACKETVER_ZERO)
|
||||
parseable_packet( HEADER_CZ_LAPINEUPGRADE_CLOSE, sizeof( struct PACKET_CZ_LAPINEUPGRADE_CLOSE ), clif_parse_laphine_upgrade_close, 0 );
|
||||
parseable_packet( HEADER_CZ_LAPINEUPGRADE_MAKE_ITEM, sizeof( struct PACKET_CZ_LAPINEUPGRADE_MAKE_ITEM ), clif_parse_laphine_upgrade, 0 );
|
||||
#endif
|
||||
|
||||
// 2017-08-30bRagexeRE
|
||||
#if PACKETVER >= 20170830
|
||||
packet(0x0ACB,12);
|
||||
|
@ -1259,6 +1259,392 @@ int16 ItemGroupDatabase::item_exists_pc(map_session_data *sd, uint16 group_id)
|
||||
return -1;
|
||||
}
|
||||
|
||||
const std::string LaphineSynthesisDatabase::getDefaultLocation(){
|
||||
return std::string( db_path ) + "/laphine_synthesis.yml";
|
||||
}
|
||||
|
||||
uint64 LaphineSynthesisDatabase::parseBodyNode( const YAML::Node& node ){
|
||||
t_itemid item_id;
|
||||
|
||||
{
|
||||
std::string name;
|
||||
|
||||
if( !this->asString( node, "Item", name ) ){
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::shared_ptr<item_data> id = item_db.search_aegisname( name.c_str() );
|
||||
|
||||
if( id == nullptr ){
|
||||
this->invalidWarning( node["Item"], "Unknown item \"%s\".\n", name.c_str() );
|
||||
return 0;
|
||||
}
|
||||
|
||||
item_id = id->nameid;
|
||||
}
|
||||
|
||||
std::shared_ptr<s_laphine_synthesis> entry = this->find( item_id );
|
||||
bool exists = entry != nullptr;
|
||||
|
||||
if( !exists ){
|
||||
if( !this->nodesExist( node, { "RewardGroup", "Requirements" } ) ){
|
||||
return 0;
|
||||
}
|
||||
|
||||
entry = std::make_shared<s_laphine_synthesis>();
|
||||
entry->item_id = item_id;
|
||||
}
|
||||
|
||||
if( this->nodeExists( node, "RewardGroup" ) ){
|
||||
std::string name;
|
||||
|
||||
if( !this->asString( node, "RewardGroup", name ) ){
|
||||
return 0;
|
||||
}
|
||||
|
||||
int64 constant;
|
||||
|
||||
if( !script_get_constant( ( "IG_" + name ).c_str(), &constant ) ){
|
||||
this->invalidWarning( node["RewardGroup"], "Unknown reward group \"%s\".\n", name.c_str() );
|
||||
return 0;
|
||||
}
|
||||
|
||||
if( !itemdb_group.exists( (uint16)constant ) ){
|
||||
this->invalidWarning( node["RewardGroup"], "Unknown reward group ID \"%" PRId64 "\".\n", constant );
|
||||
return 0;
|
||||
}
|
||||
|
||||
entry->rewardGroupId = (uint16)constant;
|
||||
}else{
|
||||
if( !exists ){
|
||||
entry->rewardGroupId = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if( this->nodeExists( node, "RequiredRequirementsCount" ) ){
|
||||
uint16 amount;
|
||||
|
||||
if( !this->asUInt16( node, "RequiredRequirementsCount", amount ) ){
|
||||
return 0;
|
||||
}
|
||||
|
||||
entry->requiredRequirements = amount;
|
||||
}else{
|
||||
if( !exists ){
|
||||
entry->requiredRequirements = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if( this->nodeExists( node, "Requirements" ) ){
|
||||
for( const YAML::Node& requirementNode : node["Requirements"] ){
|
||||
std::string name;
|
||||
|
||||
if( !this->asString( requirementNode, "Item", name ) ){
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::shared_ptr<item_data> id = item_db.search_aegisname( name.c_str() );
|
||||
|
||||
if( id == nullptr ){
|
||||
this->invalidWarning( requirementNode["Item"], "Unknown item \"%s\".\n", name.c_str() );
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::shared_ptr<s_laphine_synthesis_requirement> requirement = util::umap_find( entry->requirements, id->nameid );
|
||||
bool requirement_exists = requirement != nullptr;
|
||||
|
||||
if( !requirement_exists ){
|
||||
requirement = std::make_shared<s_laphine_synthesis_requirement>();
|
||||
requirement->item_id = id->nameid;
|
||||
}
|
||||
|
||||
if( this->nodeExists( requirementNode, "Amount" ) ){
|
||||
uint16 amount;
|
||||
|
||||
if( !this->asUInt16( requirementNode, "Amount", amount ) ){
|
||||
return 0;
|
||||
}
|
||||
|
||||
if( amount > MAX_AMOUNT ){
|
||||
this->invalidWarning( requirementNode["Amount"], "Amount %hu is too high, capping to MAX_AMOUNT...\n", amount );
|
||||
amount = MAX_AMOUNT;
|
||||
}
|
||||
|
||||
requirement->amount = amount;
|
||||
}else{
|
||||
if( !requirement_exists ){
|
||||
requirement->amount = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if( !requirement_exists ){
|
||||
entry->requirements[id->nameid] = requirement;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( this->nodeExists( node, "MinimumRefine" ) ){
|
||||
uint16 refine;
|
||||
|
||||
if( !this->asUInt16( node, "MinimumRefine", refine ) ){
|
||||
return 0;
|
||||
}
|
||||
|
||||
if( refine > MAX_REFINE ){
|
||||
this->invalidWarning( node["MinimumRefine"], "Minimum refine %hu is too high, capping to MAX_REFINE...\n", refine );
|
||||
refine = MAX_REFINE;
|
||||
}
|
||||
|
||||
entry->minimumRefine = refine;
|
||||
}else{
|
||||
if( !exists ){
|
||||
entry->minimumRefine = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if( this->nodeExists( node, "MaximumRefine" ) ){
|
||||
uint16 refine;
|
||||
|
||||
if( !this->asUInt16( node, "MaximumRefine", refine ) ){
|
||||
return 0;
|
||||
}
|
||||
|
||||
if( refine > MAX_REFINE ){
|
||||
this->invalidWarning( node["MaximumRefine"], "Maximum refine %hu is too high, capping to MAX_REFINE...\n", refine );
|
||||
refine = MAX_REFINE;
|
||||
}
|
||||
|
||||
entry->maximumRefine = refine;
|
||||
}else{
|
||||
if( !exists ){
|
||||
entry->maximumRefine = MAX_REFINE;
|
||||
}
|
||||
}
|
||||
|
||||
if( !exists ){
|
||||
this->put( entry->item_id, entry );
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
LaphineSynthesisDatabase laphine_synthesis_db;
|
||||
|
||||
const std::string LaphineUpgradeDatabase::getDefaultLocation(){
|
||||
return std::string( db_path ) + "/laphine_upgrade.yml";
|
||||
}
|
||||
|
||||
uint64 LaphineUpgradeDatabase::parseBodyNode( const YAML::Node& node ){
|
||||
t_itemid item_id;
|
||||
|
||||
{
|
||||
std::string name;
|
||||
|
||||
if( !this->asString( node, "Item", name ) ){
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::shared_ptr<item_data> id = item_db.search_aegisname( name.c_str() );
|
||||
|
||||
if( id == nullptr ){
|
||||
this->invalidWarning( node["Item"], "Unknown item \"%s\".\n", name.c_str() );
|
||||
return 0;
|
||||
}
|
||||
|
||||
item_id = id->nameid;
|
||||
}
|
||||
|
||||
std::shared_ptr<s_laphine_upgrade> entry = this->find( item_id );
|
||||
bool exists = entry != nullptr;
|
||||
|
||||
if( !exists ){
|
||||
if( !this->nodesExist( node, { "TargetItems" } ) ){
|
||||
return 0;
|
||||
}
|
||||
|
||||
entry = std::make_shared<s_laphine_upgrade>();
|
||||
entry->item_id = item_id;
|
||||
}
|
||||
|
||||
if( this->nodeExists( node, "RandomOptionGroup" ) ){
|
||||
std::string name;
|
||||
|
||||
if( !this->asString( node, "RandomOptionGroup", name ) ){
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint16 id;
|
||||
|
||||
if( !random_option_group.option_get_id( name, id ) ){
|
||||
this->invalidWarning( node["RandomOptionGroup"], "Unknown random option group \"%s\".\n", name.c_str() );
|
||||
return 0;
|
||||
}
|
||||
|
||||
entry->randomOptionGroup = random_option_group.find( id );
|
||||
}else{
|
||||
if( !exists ){
|
||||
entry->randomOptionGroup = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
if( this->nodeExists( node, "TargetItems" ) ){
|
||||
for( const YAML::Node& targetNode : node["TargetItems"] ){
|
||||
std::string name;
|
||||
|
||||
if( !this->asString( targetNode, "Item", name ) ){
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::shared_ptr<item_data> id = item_db.search_aegisname( name.c_str() );
|
||||
|
||||
if( id == nullptr ){
|
||||
this->invalidWarning( targetNode["Item"], "Unknown item \"%s\".\n", name.c_str() );
|
||||
return 0;
|
||||
}
|
||||
|
||||
if( !util::vector_exists( entry->target_item_ids, id->nameid ) ){
|
||||
entry->target_item_ids.push_back( id->nameid );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( this->nodeExists( node, "MinimumRefine" ) ){
|
||||
uint16 refine;
|
||||
|
||||
if( !this->asUInt16( node, "MinimumRefine", refine ) ){
|
||||
return 0;
|
||||
}
|
||||
|
||||
if( refine > MAX_REFINE ){
|
||||
this->invalidWarning( node["MinimumRefine"], "Minimum refine %hu is too high, capping to MAX_REFINE...\n", refine );
|
||||
refine = MAX_REFINE;
|
||||
}
|
||||
|
||||
entry->minimumRefine = refine;
|
||||
}else{
|
||||
if( !exists ){
|
||||
entry->minimumRefine = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if( this->nodeExists( node, "MaximumRefine" ) ){
|
||||
uint16 refine;
|
||||
|
||||
if( !this->asUInt16( node, "MaximumRefine", refine ) ){
|
||||
return 0;
|
||||
}
|
||||
|
||||
if( refine > MAX_REFINE ){
|
||||
this->invalidWarning( node["MaximumRefine"], "Maximum refine %hu is too high, capping to MAX_REFINE...\n", refine );
|
||||
refine = MAX_REFINE;
|
||||
}
|
||||
|
||||
entry->maximumRefine = refine;
|
||||
}else{
|
||||
if( !exists ){
|
||||
entry->maximumRefine = MAX_REFINE;
|
||||
}
|
||||
}
|
||||
|
||||
if( this->nodeExists( node, "RequiredRandomOptions" ) ){
|
||||
uint16 amount;
|
||||
|
||||
if( !this->asUInt16( node, "RequiredRandomOptions", amount ) ){
|
||||
return 0;
|
||||
}
|
||||
|
||||
if( amount > MAX_ITEM_RDM_OPT ){
|
||||
this->invalidWarning( node["RequiredRandomOptions"], "Required random option amount %hu is too high, capping to MAX_ITEM_RDM_OPT...\n", amount );
|
||||
amount = MAX_ITEM_RDM_OPT;
|
||||
}
|
||||
|
||||
entry->requiredRandomOptions = amount;
|
||||
}else{
|
||||
if( !exists ){
|
||||
entry->requiredRandomOptions = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if( this->nodeExists( node, "CardsAllowed" ) ){
|
||||
bool allowed;
|
||||
|
||||
if( !this->asBool( node, "CardsAllowed", allowed ) ){
|
||||
return 0;
|
||||
}
|
||||
|
||||
entry->cardsAllowed = true;
|
||||
}else{
|
||||
if( !exists ){
|
||||
entry->cardsAllowed = false;
|
||||
}
|
||||
}
|
||||
|
||||
if( this->nodeExists( node, "ResultRefine" ) ){
|
||||
uint16 refine;
|
||||
|
||||
if( !this->asUInt16( node, "ResultRefine", refine ) ){
|
||||
return 0;
|
||||
}
|
||||
|
||||
if( refine > MAX_REFINE ){
|
||||
this->invalidWarning( node["ResultRefine"], "Result refine %hu is too high, capping to MAX_REFINE...\n", refine );
|
||||
refine = MAX_REFINE;
|
||||
}
|
||||
|
||||
entry->resultRefine = refine;
|
||||
}else{
|
||||
if( !exists ){
|
||||
entry->resultRefine = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if( this->nodeExists( node, "ResultRefineMinimum" ) ){
|
||||
uint16 refine;
|
||||
|
||||
if( !this->asUInt16( node, "ResultRefineMinimum", refine ) ){
|
||||
return 0;
|
||||
}
|
||||
|
||||
if( refine > MAX_REFINE ){
|
||||
this->invalidWarning( node["ResultRefineMinimum"], "Result refine minimum %hu is too high, capping to MAX_REFINE...\n", refine );
|
||||
refine = MAX_REFINE;
|
||||
}
|
||||
|
||||
entry->resultRefineMinimum = refine;
|
||||
}else{
|
||||
if( !exists ){
|
||||
entry->resultRefineMinimum = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if( this->nodeExists( node, "ResultRefineMaximum" ) ){
|
||||
uint16 refine;
|
||||
|
||||
if( !this->asUInt16( node, "ResultRefineMaximum", refine ) ){
|
||||
return 0;
|
||||
}
|
||||
|
||||
if( refine > MAX_REFINE ){
|
||||
this->invalidWarning( node["ResultRefineMaximum"], "Result refine maximum %hu is too high, capping to MAX_REFINE...\n", refine );
|
||||
refine = MAX_REFINE;
|
||||
}
|
||||
|
||||
entry->resultRefineMaximum = refine;
|
||||
}else{
|
||||
if( !exists ){
|
||||
entry->resultRefineMaximum = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if( !exists ){
|
||||
this->put( entry->item_id, entry );
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
LaphineUpgradeDatabase laphine_upgrade_db;
|
||||
|
||||
/*==========================================
|
||||
* Return item data from item name. (lookup)
|
||||
* @param str Item Name
|
||||
@ -1392,6 +1778,25 @@ static void itemdb_pc_get_itemgroup_sub(map_session_data *sd, bool identify, std
|
||||
for (uint16 i = 0; i < data->amount; i += get_amt) {
|
||||
char flag = 0;
|
||||
tmp.unique_id = data->GUID ? pc_generate_unique_id(sd) : 0; // Generate GUID
|
||||
|
||||
if( itemdb_isequip( data->nameid ) ){
|
||||
if( data->refineMinimum > 0 && data->refineMaximum > 0 ){
|
||||
tmp.refine = rnd_value( data->refineMinimum, data->refineMaximum );
|
||||
}else if( data->refineMinimum > 0 ){
|
||||
tmp.refine = rnd_value( data->refineMinimum, MAX_REFINE );
|
||||
}else if( data->refineMaximum > 0 ){
|
||||
tmp.refine = rnd_value( 1, data->refineMaximum );
|
||||
}else{
|
||||
tmp.refine = 0;
|
||||
}
|
||||
|
||||
if( data->randomOptionGroup != nullptr ){
|
||||
memset( tmp.option, 0, sizeof( tmp.option ) );
|
||||
|
||||
data->randomOptionGroup->apply( tmp );
|
||||
}
|
||||
}
|
||||
|
||||
if ((flag = pc_additem(sd, &tmp, get_amt, LOG_TYPE_SCRIPT))) {
|
||||
clif_additem(sd, 0, 0, flag);
|
||||
if (pc_candrop(sd, &tmp))
|
||||
@ -1877,6 +2282,65 @@ uint64 ItemGroupDatabase::parseBodyNode(const YAML::Node &node) {
|
||||
if (!entry_exists)
|
||||
entry->bound = BOUND_NONE;
|
||||
}
|
||||
|
||||
if( this->nodeExists( listit, "RandomOptionGroup" ) ){
|
||||
std::string name;
|
||||
|
||||
if( !this->asString( listit, "RandomOptionGroup", name ) ){
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint16 id;
|
||||
|
||||
if( !random_option_group.option_get_id( name, id ) ){
|
||||
this->invalidWarning( listit["RandomOptionGroup"], "Unknown random option group \"%s\".\n", name.c_str() );
|
||||
return 0;
|
||||
}
|
||||
|
||||
entry->randomOptionGroup = random_option_group.find( id );
|
||||
}else{
|
||||
if( !entry_exists ){
|
||||
entry->randomOptionGroup = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
if( this->nodeExists( listit, "RefineMinimum" ) ){
|
||||
uint16 refine;
|
||||
|
||||
if( !this->asUInt16( listit, "RefineMinimum", refine ) ){
|
||||
return 0;
|
||||
}
|
||||
|
||||
if( refine > MAX_REFINE ){
|
||||
this->invalidWarning( listit["RefineMinimum"], "Minimum refine % hu is too high, capping to MAX_REFINE...\n", refine );
|
||||
refine = MAX_REFINE;
|
||||
}
|
||||
|
||||
entry->refineMinimum = refine;
|
||||
}else{
|
||||
if( !exists ){
|
||||
entry->refineMinimum = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if( this->nodeExists( listit, "RefineMaximum" ) ){
|
||||
uint16 refine;
|
||||
|
||||
if( !this->asUInt16( listit, "RefineMaximum", refine ) ){
|
||||
return 0;
|
||||
}
|
||||
|
||||
if( refine > MAX_REFINE ){
|
||||
this->invalidWarning( listit["RefineMaximum"], "Maximum refine %hu is too high, capping to MAX_REFINE...\n", refine );
|
||||
refine = MAX_REFINE;
|
||||
}
|
||||
|
||||
entry->refineMaximum = refine;
|
||||
}else{
|
||||
if( !exists ){
|
||||
entry->refineMaximum = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2734,6 +3198,51 @@ bool RandomOptionGroupDatabase::add_option(const YAML::Node &node, std::shared_p
|
||||
return true;
|
||||
}
|
||||
|
||||
void s_random_opt_group::apply( struct item& item ){
|
||||
auto apply_sub = []( s_item_randomoption& item_option, const std::shared_ptr<s_random_opt_group_entry>& option ){
|
||||
item_option.id = option->id;
|
||||
item_option.value = rnd_value( option->min_value, option->max_value );
|
||||
item_option.param = option->param;
|
||||
};
|
||||
|
||||
// Apply Must options
|
||||
for( size_t i = 0; i < this->slots.size(); i++ ){
|
||||
// Try to apply an entry
|
||||
for( size_t j = 0, max = this->slots[static_cast<uint16>(i)].size() * 3; j < max; j++ ){
|
||||
std::shared_ptr<s_random_opt_group_entry> option = util::vector_random( this->slots[static_cast<uint16>(i)] );
|
||||
|
||||
if( rnd() % 10000 < option->chance ){
|
||||
apply_sub( item.option[i], option );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// If no entry was applied, assign one
|
||||
if( item.option[i].id == 0 ){
|
||||
std::shared_ptr<s_random_opt_group_entry> option = util::vector_random( this->slots[static_cast<uint16>(i)] );
|
||||
|
||||
// Apply an entry without checking the chance
|
||||
apply_sub( item.option[i], option );
|
||||
}
|
||||
}
|
||||
|
||||
// Apply Random options (if available)
|
||||
if( this->max_random > 0 ){
|
||||
for( size_t i = 0; i < min( this->max_random, MAX_ITEM_RDM_OPT ); i++ ){
|
||||
// If item already has an option in this slot, skip it
|
||||
if( item.option[i].id > 0 ){
|
||||
continue;
|
||||
}
|
||||
|
||||
std::shared_ptr<s_random_opt_group_entry> option = util::vector_random( this->random_options );
|
||||
|
||||
if( rnd() % 10000 < option->chance ){
|
||||
apply_sub( item.option[i], option );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads and parses an entry from the item_randomopt_group.
|
||||
* @param node: YAML node containing the entry.
|
||||
@ -2906,10 +3415,15 @@ static void itemdb_read(void) {
|
||||
aFree(dbsubpath2);
|
||||
}
|
||||
|
||||
itemdb_group.load();
|
||||
itemdb_combo.load();
|
||||
random_option_db.load();
|
||||
random_option_group.load();
|
||||
itemdb_group.load();
|
||||
itemdb_combo.load();
|
||||
laphine_synthesis_db.load();
|
||||
laphine_upgrade_db.load();
|
||||
|
||||
if (battle_config.feature_roulette)
|
||||
itemdb_parse_roulette_db();
|
||||
}
|
||||
|
||||
/*==========================================
|
||||
@ -2941,21 +3455,12 @@ void itemdb_reload(void) {
|
||||
struct s_mapiterator* iter;
|
||||
struct map_session_data* sd;
|
||||
|
||||
item_db.clear();
|
||||
itemdb_combo.clear();
|
||||
itemdb_group.clear();
|
||||
random_option_db.clear();
|
||||
random_option_group.clear();
|
||||
if (battle_config.feature_roulette)
|
||||
itemdb_roulette_free();
|
||||
do_final_itemdb();
|
||||
|
||||
// read new data
|
||||
itemdb_read();
|
||||
cashshop_reloaddb();
|
||||
|
||||
if (battle_config.feature_roulette)
|
||||
itemdb_parse_roulette_db();
|
||||
|
||||
mob_reload_itemmob_data();
|
||||
|
||||
// readjust itemdb pointer cache for each player
|
||||
@ -2980,6 +3485,8 @@ void do_final_itemdb(void) {
|
||||
itemdb_group.clear();
|
||||
random_option_db.clear();
|
||||
random_option_group.clear();
|
||||
laphine_synthesis_db.clear();
|
||||
laphine_upgrade_db.clear();
|
||||
if (battle_config.feature_roulette)
|
||||
itemdb_roulette_free();
|
||||
}
|
||||
@ -2989,7 +3496,4 @@ void do_final_itemdb(void) {
|
||||
*/
|
||||
void do_init_itemdb(void) {
|
||||
itemdb_read();
|
||||
|
||||
if (battle_config.feature_roulette)
|
||||
itemdb_parse_roulette_db();
|
||||
}
|
||||
|
@ -778,6 +778,118 @@ enum e_random_item_group {
|
||||
IG_THIRD_JOB_STONE_MIDDLE_BOX2,
|
||||
IG_THIRD_JOB_STONE_BOTTOM_BOX,
|
||||
IG_THIRD_JOB_STONE_BOTTOM_BOX2,
|
||||
IG_SHADOW_EXCHANGE_BOX,
|
||||
IG_DROOPING_GUNSLINGER_SCROLL,
|
||||
IG_ENCHANTSTONE_RECIPE,
|
||||
IG_PET_EGG_BOX,
|
||||
IG_COSTUME_EXCHANGE_BOX,
|
||||
IG_FAN_MODIFICATION_KIT,
|
||||
IG_UNIFORM_REPAIR_KIT,
|
||||
IG_SCROLL_OF_FALLEN_ANGEL_WINGS,
|
||||
IG_CLASS_SHADOW_BOX_WEAPON,
|
||||
IG_CLASS_SHADOW_BOX_ARMOR,
|
||||
IG_CLASS_SHADOW_BOX_SHOES,
|
||||
IG_CLASS_SHADOW_BOX_SHIELD,
|
||||
IG_CLASS_SHADOW_BOX_PENDANT,
|
||||
IG_CLASS_SHADOW_BOX_EARRING,
|
||||
IG_STATUSSHADOW_MIX,
|
||||
IG_GEMSTONESHADOW_MIX,
|
||||
IG_BEARERSSHADOW_MIX,
|
||||
IG_COMPOSESHADOW_MIX,
|
||||
IG_RACESHADOW_MIX,
|
||||
IG_CANDY_POUCH_BLESSING_SCROLL_MELEE,
|
||||
IG_CANDY_POUCH_BLESSING_SCROLL_RANGE,
|
||||
IG_CANDY_POUCH_BLESSING_SCROLL_MAGIC,
|
||||
IG_MAGICAL_BOOSTER_AMPLIFIER,
|
||||
IG_MAGIC_CAT_HAND_SCROLL,
|
||||
IG_INFINITYSHADOW_MIX,
|
||||
IG_SILVER_STATUE,
|
||||
IG_PHYSICALMAGICAL_MIX,
|
||||
IG_IMMUNEDATHENA_MIX,
|
||||
IG_HARDCHAMPTION_MIX,
|
||||
IG_KINGBIRDANCIENT_MIX,
|
||||
IG_CRITICALHIT_MIX,
|
||||
IG_BS_ITEM_M_S_2,
|
||||
IG_BS_ITEM_M_S_8,
|
||||
IG_BS_ITEM_M_S_10,
|
||||
IG_BS_ITEM_M_S_11,
|
||||
IG_BS_ITEM_M_S_34,
|
||||
IG_BS_ITEM_M_S_41,
|
||||
IG_BS_ITEM_M_S_42,
|
||||
IG_BS_ITEM_M_S_43,
|
||||
IG_BS_ITEM_M_S_44,
|
||||
IG_BS_SHA_M_S_1,
|
||||
IG_BS_SHA_M_S_17,
|
||||
IG_BS_SHA_M_S_18,
|
||||
IG_BS_SHA_M_S_19,
|
||||
IG_BS_SHA_M_S_20,
|
||||
IG_BS_ITEM_M_S_4,
|
||||
IG_BS_ITEM_M_S_6,
|
||||
IG_BS_ITEM_M_S_7,
|
||||
IG_BS_ITEM_M_S_12,
|
||||
IG_BS_ITEM_M_S_13,
|
||||
IG_BS_ITEM_M_S_15,
|
||||
IG_BS_ITEM_M_S_28,
|
||||
IG_BS_ITEM_M_S_29,
|
||||
IG_BS_ITEM_M_S_31,
|
||||
IG_BS_ITEM_M_S_32,
|
||||
IG_BS_ITEM_M_S_33,
|
||||
IG_BS_ITEM_M_S_36,
|
||||
IG_BS_ITEM_M_S_37,
|
||||
IG_BS_ITEM_M_S_38,
|
||||
IG_BS_ITEM_M_S_39,
|
||||
IG_BS_ITEM_M_S_40,
|
||||
IG_BS_ITEM_M_S_45,
|
||||
IG_BS_ITEM_M_S_46,
|
||||
IG_BS_ITEM_M_S_47,
|
||||
IG_BS_ITEM_M_S_48,
|
||||
IG_BS_ITEM_M_S_49,
|
||||
IG_BS_ITEM_M_S_50,
|
||||
IG_BS_SHA_M_S_5,
|
||||
IG_BS_SHA_M_S_6,
|
||||
IG_BS_SHA_M_S_7,
|
||||
IG_BS_SHA_M_S_8,
|
||||
IG_BS_SHA_M_S_13,
|
||||
IG_BS_SHA_M_S_15,
|
||||
IG_BS_SHA_M_S_16,
|
||||
IG_BS_SHA_M_S_23,
|
||||
IG_BS_ITEM_M_S_5,
|
||||
IG_BS_ITEM_M_S_9,
|
||||
IG_BS_ITEM_M_S_14,
|
||||
IG_BS_ITEM_M_S_16,
|
||||
IG_BS_ITEM_M_S_17,
|
||||
IG_BS_ITEM_M_S_19,
|
||||
IG_BS_ITEM_M_S_27,
|
||||
IG_BS_ITEM_M_S_35,
|
||||
IG_BS_SHA_M_S_9,
|
||||
IG_BS_SHA_M_S_10,
|
||||
IG_BS_SHA_M_S_11,
|
||||
IG_BS_SHA_M_S_21,
|
||||
IG_BS_ITEM_M_S_1,
|
||||
IG_BS_ITEM_M_S_3,
|
||||
IG_BS_ITEM_M_S_18,
|
||||
IG_BS_ITEM_M_S_20,
|
||||
IG_BS_ITEM_M_S_21,
|
||||
IG_BS_ITEM_M_S_22,
|
||||
IG_BS_ITEM_M_S_23,
|
||||
IG_BS_ITEM_M_S_24,
|
||||
IG_BS_ITEM_M_S_25,
|
||||
IG_BS_ITEM_M_S_26,
|
||||
IG_BS_ITEM_M_S_30,
|
||||
IG_BS_SHA_M_S_3,
|
||||
IG_BS_SHA_M_S_4,
|
||||
IG_BS_SHA_M_S_12,
|
||||
IG_BS_SHA_M_S_14,
|
||||
IG_BS_SHA_M_S_24,
|
||||
IG_BS_SHA_M_S_25,
|
||||
IG_BS_ITEM_M_S_51,
|
||||
IG_ENCHANTSTONE_RECIPE_9M,
|
||||
IG_IDTEST_SPECIAL,
|
||||
IG_PERFECTSIZE_MIX,
|
||||
IG_MAGICPIERCING_MIX,
|
||||
IG_PIERCING_MIX,
|
||||
IG_HASTY_MIX,
|
||||
IG_ENCHANTSTONE_RECIPE_4M,
|
||||
|
||||
IG_MAX,
|
||||
};
|
||||
@ -866,6 +978,73 @@ public:
|
||||
|
||||
extern ComboDatabase itemdb_combo;
|
||||
|
||||
// Struct for item random option [Secret]
|
||||
struct s_random_opt_data
|
||||
{
|
||||
uint16 id;
|
||||
std::string name;
|
||||
script_code *script;
|
||||
|
||||
~s_random_opt_data() {
|
||||
if (script)
|
||||
script_free_code(script);
|
||||
}
|
||||
};
|
||||
|
||||
/// Struct for random option group entry
|
||||
struct s_random_opt_group_entry {
|
||||
uint16 id;
|
||||
int16 min_value, max_value;
|
||||
int8 param;
|
||||
uint16 chance;
|
||||
};
|
||||
|
||||
/// Struct for Random Option Group
|
||||
struct s_random_opt_group {
|
||||
uint16 id;
|
||||
std::string name;
|
||||
std::map<uint16, std::vector<std::shared_ptr<s_random_opt_group_entry>>> slots;
|
||||
uint16 max_random;
|
||||
std::vector<std::shared_ptr<s_random_opt_group_entry>> random_options;
|
||||
|
||||
public:
|
||||
void apply( struct item& item );
|
||||
};
|
||||
|
||||
class RandomOptionDatabase : public TypesafeYamlDatabase<uint16, s_random_opt_data> {
|
||||
public:
|
||||
RandomOptionDatabase() : TypesafeYamlDatabase("RANDOM_OPTION_DB", 1) {
|
||||
|
||||
}
|
||||
|
||||
const std::string getDefaultLocation() override;
|
||||
uint64 parseBodyNode(const YAML::Node &node) override;
|
||||
void loadingFinished() override;
|
||||
|
||||
// Additional
|
||||
bool option_exists(std::string name);
|
||||
bool option_get_id(std::string name, uint16 &id);
|
||||
};
|
||||
|
||||
extern RandomOptionDatabase random_option_db;
|
||||
|
||||
class RandomOptionGroupDatabase : public TypesafeYamlDatabase<uint16, s_random_opt_group> {
|
||||
public:
|
||||
RandomOptionGroupDatabase() : TypesafeYamlDatabase("RANDOM_OPTION_GROUP", 1) {
|
||||
|
||||
}
|
||||
|
||||
const std::string getDefaultLocation() override;
|
||||
uint64 parseBodyNode(const YAML::Node &node) override;
|
||||
|
||||
// Additional
|
||||
bool add_option(const YAML::Node &node, std::shared_ptr<s_random_opt_group_entry> &entry);
|
||||
bool option_exists(std::string name);
|
||||
bool option_get_id(std::string name, uint16 &id);
|
||||
};
|
||||
|
||||
extern RandomOptionGroupDatabase random_option_group;
|
||||
|
||||
/// Struct of item group entry
|
||||
struct s_item_group_entry
|
||||
{
|
||||
@ -878,6 +1057,9 @@ struct s_item_group_entry
|
||||
isStacked, /// Whether stackable items are given stacked
|
||||
isNamed; /// Named the item (if possible)
|
||||
uint8 bound; /// Makes the item as bound item (according to bound type)
|
||||
std::shared_ptr<s_random_opt_group> randomOptionGroup;
|
||||
uint16 refineMinimum;
|
||||
uint16 refineMaximum;
|
||||
};
|
||||
|
||||
/// Struct of random group
|
||||
@ -999,70 +1181,6 @@ struct item_data
|
||||
int inventorySlotNeeded(int quantity);
|
||||
};
|
||||
|
||||
// Struct for item random option [Secret]
|
||||
struct s_random_opt_data
|
||||
{
|
||||
uint16 id;
|
||||
std::string name;
|
||||
script_code *script;
|
||||
|
||||
~s_random_opt_data() {
|
||||
if (script)
|
||||
script_free_code(script);
|
||||
}
|
||||
};
|
||||
|
||||
/// Struct for random option group entry
|
||||
struct s_random_opt_group_entry {
|
||||
uint16 id;
|
||||
int16 min_value, max_value;
|
||||
int8 param;
|
||||
uint16 chance;
|
||||
};
|
||||
|
||||
/// Struct for Random Option Group
|
||||
struct s_random_opt_group {
|
||||
uint16 id;
|
||||
std::string name;
|
||||
std::map<uint16, std::vector<std::shared_ptr<s_random_opt_group_entry>>> slots;
|
||||
uint16 max_random;
|
||||
std::vector<std::shared_ptr<s_random_opt_group_entry>> random_options;
|
||||
};
|
||||
|
||||
class RandomOptionDatabase : public TypesafeYamlDatabase<uint16, s_random_opt_data> {
|
||||
public:
|
||||
RandomOptionDatabase() : TypesafeYamlDatabase("RANDOM_OPTION_DB", 1) {
|
||||
|
||||
}
|
||||
|
||||
const std::string getDefaultLocation() override;
|
||||
uint64 parseBodyNode(const YAML::Node &node) override;
|
||||
void loadingFinished() override;
|
||||
|
||||
// Additional
|
||||
bool option_exists(std::string name);
|
||||
bool option_get_id(std::string name, uint16 &id);
|
||||
};
|
||||
|
||||
extern RandomOptionDatabase random_option_db;
|
||||
|
||||
class RandomOptionGroupDatabase : public TypesafeYamlDatabase<uint16, s_random_opt_group> {
|
||||
public:
|
||||
RandomOptionGroupDatabase() : TypesafeYamlDatabase("RANDOM_OPTION_GROUP", 1) {
|
||||
|
||||
}
|
||||
|
||||
const std::string getDefaultLocation() override;
|
||||
uint64 parseBodyNode(const YAML::Node &node) override;
|
||||
|
||||
// Additional
|
||||
bool add_option(const YAML::Node &node, std::shared_ptr<s_random_opt_group_entry> &entry);
|
||||
bool option_exists(std::string name);
|
||||
bool option_get_id(std::string name, uint16 &id);
|
||||
};
|
||||
|
||||
extern RandomOptionGroupDatabase random_option_group;
|
||||
|
||||
class ItemDatabase : public TypesafeCachedYamlDatabase<t_itemid, item_data> {
|
||||
private:
|
||||
std::unordered_map<std::string, std::shared_ptr<item_data>> nameToItemDataMap;
|
||||
@ -1094,7 +1212,7 @@ extern ItemDatabase item_db;
|
||||
|
||||
class ItemGroupDatabase : public TypesafeCachedYamlDatabase<uint16, s_item_group_db> {
|
||||
public:
|
||||
ItemGroupDatabase() : TypesafeCachedYamlDatabase("ITEM_GROUP_DB", 1) {
|
||||
ItemGroupDatabase() : TypesafeCachedYamlDatabase("ITEM_GROUP_DB", 2, 1) {
|
||||
|
||||
}
|
||||
|
||||
@ -1112,6 +1230,57 @@ public:
|
||||
|
||||
extern ItemGroupDatabase itemdb_group;
|
||||
|
||||
struct s_laphine_synthesis_requirement{
|
||||
t_itemid item_id;
|
||||
uint16 amount;
|
||||
};
|
||||
|
||||
struct s_laphine_synthesis{
|
||||
t_itemid item_id;
|
||||
uint16 minimumRefine;
|
||||
uint16 maximumRefine;
|
||||
uint16 requiredRequirements;
|
||||
std::unordered_map<t_itemid, std::shared_ptr<s_laphine_synthesis_requirement>> requirements;
|
||||
uint16 rewardGroupId;
|
||||
};
|
||||
|
||||
class LaphineSynthesisDatabase : public TypesafeYamlDatabase<t_itemid, s_laphine_synthesis>{
|
||||
public:
|
||||
LaphineSynthesisDatabase() : TypesafeYamlDatabase( "LAPHINE_SYNTHESIS_DB", 1 ){
|
||||
|
||||
}
|
||||
|
||||
const std::string getDefaultLocation();
|
||||
uint64 parseBodyNode( const YAML::Node& node );
|
||||
};
|
||||
|
||||
extern LaphineSynthesisDatabase laphine_synthesis_db;
|
||||
|
||||
struct s_laphine_upgrade{
|
||||
t_itemid item_id;
|
||||
std::vector<t_itemid> target_item_ids;
|
||||
uint16 minimumRefine;
|
||||
uint16 maximumRefine;
|
||||
uint16 requiredRandomOptions;
|
||||
bool cardsAllowed;
|
||||
std::shared_ptr<s_random_opt_group> randomOptionGroup;
|
||||
uint16 resultRefine;
|
||||
uint16 resultRefineMinimum;
|
||||
uint16 resultRefineMaximum;
|
||||
};
|
||||
|
||||
class LaphineUpgradeDatabase : public TypesafeYamlDatabase<t_itemid, s_laphine_upgrade>{
|
||||
public:
|
||||
LaphineUpgradeDatabase() : TypesafeYamlDatabase( "LAPHINE_UPGRADE_DB", 1 ){
|
||||
|
||||
}
|
||||
|
||||
const std::string getDefaultLocation();
|
||||
uint64 parseBodyNode( const YAML::Node& node );
|
||||
};
|
||||
|
||||
extern LaphineUpgradeDatabase laphine_upgrade_db;
|
||||
|
||||
int itemdb_searchname_array(struct item_data** data, int size, const char *str);
|
||||
struct item_data* itemdb_search(t_itemid nameid);
|
||||
struct item_data* itemdb_exists(t_itemid nameid);
|
||||
|
@ -86,6 +86,7 @@ static char log_picktype2char(e_log_pick_type type)
|
||||
case LOG_TYPE_QUEST: return 'Q'; // (Q)uest Item
|
||||
case LOG_TYPE_PRIVATE_AIRSHIP: return 'H'; // Private Airs(H)ip
|
||||
case LOG_TYPE_BARTER: return 'J'; // Barter Shop
|
||||
case LOG_TYPE_LAPHINE: return 'W'; // Laphine UI
|
||||
}
|
||||
|
||||
// should not get here, fallback
|
||||
|
@ -52,6 +52,7 @@ enum e_log_pick_type : uint32
|
||||
LOG_TYPE_QUEST = 0x0400000,
|
||||
LOG_TYPE_PRIVATE_AIRSHIP = 0x0800000,
|
||||
LOG_TYPE_BARTER = 0x1000000,
|
||||
LOG_TYPE_LAPHINE = 0x2000000,
|
||||
// combinations
|
||||
LOG_TYPE_LOOT = LOG_TYPE_PICKDROP_MONSTER|LOG_TYPE_CONSUME,
|
||||
// all
|
||||
|
@ -319,6 +319,8 @@
|
||||
<Copy SourceFiles="$(SolutionDir)db\import-tmpl\item_randomopt_group.yml" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\item_randomopt_group.yml')" />
|
||||
<Copy SourceFiles="$(SolutionDir)db\import-tmpl\job_noenter_map.txt" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\job_noenter_map.txt')" />
|
||||
<Copy SourceFiles="$(SolutionDir)db\import-tmpl\job_stats.yml" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\job_stats.yml')" />
|
||||
<Copy SourceFiles="$(SolutionDir)db\import-tmpl\laphine_synthesis.yml" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\laphine_synthesis.yml')" />
|
||||
<Copy SourceFiles="$(SolutionDir)db\import-tmpl\laphine_upgrade.yml" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\laphine_upgrade.yml')" />
|
||||
<Copy SourceFiles="$(SolutionDir)db\import-tmpl\level_penalty.yml" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\level_penalty.yml')" />
|
||||
<Copy SourceFiles="$(SolutionDir)db\import-tmpl\magicmushroom_db.yml" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\magicmushroom_db.yml')" />
|
||||
<Copy SourceFiles="$(SolutionDir)db\import-tmpl\map_cache.dat" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\map_cache.dat')" />
|
||||
|
@ -2102,17 +2102,6 @@ static TIMER_FUNC(mob_ai_hard){
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assign random option values to an item
|
||||
* @param item_option: Random option on the item
|
||||
* @param option: Options to assign
|
||||
*/
|
||||
void mob_setitem_option(s_item_randomoption &item_option, const std::shared_ptr<s_random_opt_group_entry> &option) {
|
||||
item_option.id = option->id;
|
||||
item_option.value = rnd_value(option->min_value, option->max_value);
|
||||
item_option.param = option->param;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set random option for item when dropped from monster
|
||||
* @param item: Item data
|
||||
@ -2126,40 +2115,7 @@ void mob_setdropitem_option(item *item, s_mob_drop *mobdrop) {
|
||||
std::shared_ptr<s_random_opt_group> group = random_option_group.find(mobdrop->randomopt_group);
|
||||
|
||||
if (group != nullptr) {
|
||||
// Apply Must options
|
||||
for (size_t i = 0; i < group->slots.size(); i++) {
|
||||
// Try to apply an entry
|
||||
for (size_t j = 0, max = group->slots[static_cast<uint16>(i)].size() * 3; j < max; j++) {
|
||||
std::shared_ptr<s_random_opt_group_entry> option = util::vector_random(group->slots[static_cast<uint16>(i)]);
|
||||
|
||||
if (rnd() % 10000 < option->chance) {
|
||||
mob_setitem_option(item->option[i], option);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// If no entry was applied, assign one
|
||||
if (item->option[i].id == 0) {
|
||||
std::shared_ptr<s_random_opt_group_entry> option = util::vector_random(group->slots[static_cast<uint16>(i)]);
|
||||
|
||||
// Apply an entry without checking the chance
|
||||
mob_setitem_option(item->option[i], option);
|
||||
}
|
||||
}
|
||||
|
||||
// Apply Random options (if available)
|
||||
if (group->max_random > 0) {
|
||||
for (size_t i = 0; i < min(group->max_random, MAX_ITEM_RDM_OPT); i++) {
|
||||
// If item already has an option in this slot, skip it
|
||||
if (item->option[i].id > 0)
|
||||
continue;
|
||||
|
||||
std::shared_ptr<s_random_opt_group_entry> option = util::vector_random(group->random_options);
|
||||
|
||||
if (rnd() % 10000 < option->chance)
|
||||
mob_setitem_option(item->option[i], option);
|
||||
}
|
||||
}
|
||||
group->apply( *item );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -389,6 +389,8 @@ struct map_session_data {
|
||||
bool refineui_open;
|
||||
t_itemid inventory_expansion_confirmation;
|
||||
uint16 inventory_expansion_amount;
|
||||
t_itemid laphine_synthesis;
|
||||
t_itemid laphine_upgrade;
|
||||
} state;
|
||||
struct {
|
||||
unsigned char no_weapon_damage, no_magic_damage, no_misc_damage;
|
||||
@ -1058,7 +1060,8 @@ static bool pc_cant_act2( struct map_session_data* sd ){
|
||||
return sd->state.vending || sd->state.buyingstore || (sd->sc.opt1 && sd->sc.opt1 != OPT1_BURNING)
|
||||
|| sd->state.trading || sd->state.storage_flag || sd->state.prevend || sd->state.refineui_open
|
||||
|| sd->state.stylist_open || sd->state.inventory_expansion_confirmation || sd->npc_shopid
|
||||
|| sd->state.barter_open || sd->state.barter_extended_open;
|
||||
|| sd->state.barter_open || sd->state.barter_extended_open
|
||||
|| sd->state.laphine_synthesis || sd->state.laphine_upgrade;
|
||||
}
|
||||
// equals pc_cant_act2 and additionally checks for chat rooms and npcs
|
||||
static bool pc_cant_act( struct map_session_data* sd ){
|
||||
|
@ -25755,6 +25755,74 @@ BUILDIN_FUNC(getitempos) {
|
||||
return SCRIPT_CMD_SUCCESS;
|
||||
}
|
||||
|
||||
BUILDIN_FUNC( laphine_synthesis ){
|
||||
struct map_session_data* sd;
|
||||
|
||||
if( !script_rid2sd( sd ) ){
|
||||
return SCRIPT_CMD_FAILURE;
|
||||
}
|
||||
|
||||
if( sd->itemid == 0 ){
|
||||
ShowError( "buildin_laphine_synthesis: Called outside of an item script without item id.\n" );
|
||||
return SCRIPT_CMD_FAILURE;
|
||||
}
|
||||
|
||||
if( sd->inventory_data[sd->itemindex]->flag.delay_consume == 0 ){
|
||||
ShowError( "buildin_laphine_synthesis: Called from item %u, which is not a consumed delayed.\n", sd->itemid );
|
||||
return SCRIPT_CMD_FAILURE;
|
||||
}
|
||||
|
||||
if( sd->state.laphine_synthesis != 0 ){
|
||||
ShowError( "buildin_laphine_synthesis: Laphine Synthesis window was already open. Player %s (AID: %u, CID: %u) with item id %u.\n", sd->status.name, sd->status.account_id, sd->status.char_id, sd->itemid );
|
||||
return SCRIPT_CMD_FAILURE;
|
||||
}
|
||||
|
||||
std::shared_ptr<s_laphine_synthesis> synthesis = laphine_synthesis_db.find( sd->itemid );
|
||||
|
||||
if( synthesis == nullptr ){
|
||||
ShowError( "buildin_laphine_synthesis: %u is not a valid Laphine Synthesis item.\n", sd->itemid );
|
||||
return SCRIPT_CMD_FAILURE;
|
||||
}
|
||||
|
||||
clif_laphine_synthesis_open( sd, synthesis );
|
||||
|
||||
return SCRIPT_CMD_SUCCESS;
|
||||
}
|
||||
|
||||
BUILDIN_FUNC( laphine_upgrade ){
|
||||
struct map_session_data* sd;
|
||||
|
||||
if( !script_rid2sd( sd ) ){
|
||||
return SCRIPT_CMD_FAILURE;
|
||||
}
|
||||
|
||||
if( sd->itemid == 0 ){
|
||||
ShowError( "buildin_laphine_upgrade: Called outside of an item script without item id.\n" );
|
||||
return SCRIPT_CMD_FAILURE;
|
||||
}
|
||||
|
||||
if( sd->inventory_data[sd->itemindex]->flag.delay_consume == 0 ){
|
||||
ShowError( "buildin_laphine_upgrade: Called from item %u, which is not a consumed delayed.\n", sd->itemid );
|
||||
return SCRIPT_CMD_FAILURE;
|
||||
}
|
||||
|
||||
if( sd->state.laphine_upgrade != 0 ){
|
||||
ShowError( "buildin_laphine_upgrade: Laphine Upgrade window was already open. Player %s (AID: %u, CID: %u) with item id %u.\n", sd->status.name, sd->status.account_id, sd->status.char_id, sd->itemid );
|
||||
return SCRIPT_CMD_FAILURE;
|
||||
}
|
||||
|
||||
std::shared_ptr<s_laphine_upgrade> upgrade = laphine_upgrade_db.find( sd->itemid );
|
||||
|
||||
if( upgrade == nullptr ){
|
||||
ShowError( "buildin_laphine_upgrade: %u is not a valid Laphine Upgrade item.\n", sd->itemid );
|
||||
return SCRIPT_CMD_FAILURE;
|
||||
}
|
||||
|
||||
clif_laphine_upgrade_open( sd, upgrade );
|
||||
|
||||
return SCRIPT_CMD_SUCCESS;
|
||||
}
|
||||
|
||||
#include "../custom/script.inc"
|
||||
|
||||
// declarations that were supposed to be exported from npc_chat.cpp
|
||||
@ -26464,6 +26532,8 @@ struct script_function buildin_func[] = {
|
||||
BUILDIN_DEF(openstylist, "?"),
|
||||
|
||||
BUILDIN_DEF(getitempos,""),
|
||||
BUILDIN_DEF(laphine_synthesis, ""),
|
||||
BUILDIN_DEF(laphine_upgrade, ""),
|
||||
#include "../custom/script_def.inc"
|
||||
|
||||
{NULL,NULL,NULL},
|
||||
|
@ -5526,6 +5526,118 @@
|
||||
export_constant(IG_THIRD_JOB_STONE_MIDDLE_BOX2);
|
||||
export_constant(IG_THIRD_JOB_STONE_BOTTOM_BOX);
|
||||
export_constant(IG_THIRD_JOB_STONE_BOTTOM_BOX2);
|
||||
export_constant(IG_SHADOW_EXCHANGE_BOX);
|
||||
export_constant(IG_DROOPING_GUNSLINGER_SCROLL);
|
||||
export_constant(IG_ENCHANTSTONE_RECIPE);
|
||||
export_constant(IG_PET_EGG_BOX);
|
||||
export_constant(IG_COSTUME_EXCHANGE_BOX);
|
||||
export_constant(IG_FAN_MODIFICATION_KIT);
|
||||
export_constant(IG_UNIFORM_REPAIR_KIT);
|
||||
export_constant(IG_SCROLL_OF_FALLEN_ANGEL_WINGS);
|
||||
export_constant(IG_CLASS_SHADOW_BOX_WEAPON);
|
||||
export_constant(IG_CLASS_SHADOW_BOX_ARMOR);
|
||||
export_constant(IG_CLASS_SHADOW_BOX_SHOES);
|
||||
export_constant(IG_CLASS_SHADOW_BOX_SHIELD);
|
||||
export_constant(IG_CLASS_SHADOW_BOX_PENDANT);
|
||||
export_constant(IG_CLASS_SHADOW_BOX_EARRING);
|
||||
export_constant(IG_STATUSSHADOW_MIX);
|
||||
export_constant(IG_GEMSTONESHADOW_MIX);
|
||||
export_constant(IG_BEARERSSHADOW_MIX);
|
||||
export_constant(IG_COMPOSESHADOW_MIX);
|
||||
export_constant(IG_RACESHADOW_MIX);
|
||||
export_constant(IG_CANDY_POUCH_BLESSING_SCROLL_MELEE);
|
||||
export_constant(IG_CANDY_POUCH_BLESSING_SCROLL_RANGE);
|
||||
export_constant(IG_CANDY_POUCH_BLESSING_SCROLL_MAGIC);
|
||||
export_constant(IG_MAGICAL_BOOSTER_AMPLIFIER);
|
||||
export_constant(IG_MAGIC_CAT_HAND_SCROLL);
|
||||
export_constant(IG_INFINITYSHADOW_MIX);
|
||||
export_constant(IG_SILVER_STATUE);
|
||||
export_constant(IG_PHYSICALMAGICAL_MIX);
|
||||
export_constant(IG_IMMUNEDATHENA_MIX);
|
||||
export_constant(IG_HARDCHAMPTION_MIX);
|
||||
export_constant(IG_KINGBIRDANCIENT_MIX);
|
||||
export_constant(IG_CRITICALHIT_MIX);
|
||||
export_constant(IG_BS_ITEM_M_S_2);
|
||||
export_constant(IG_BS_ITEM_M_S_8);
|
||||
export_constant(IG_BS_ITEM_M_S_10);
|
||||
export_constant(IG_BS_ITEM_M_S_11);
|
||||
export_constant(IG_BS_ITEM_M_S_34);
|
||||
export_constant(IG_BS_ITEM_M_S_41);
|
||||
export_constant(IG_BS_ITEM_M_S_42);
|
||||
export_constant(IG_BS_ITEM_M_S_43);
|
||||
export_constant(IG_BS_ITEM_M_S_44);
|
||||
export_constant(IG_BS_SHA_M_S_1);
|
||||
export_constant(IG_BS_SHA_M_S_17);
|
||||
export_constant(IG_BS_SHA_M_S_18);
|
||||
export_constant(IG_BS_SHA_M_S_19);
|
||||
export_constant(IG_BS_SHA_M_S_20);
|
||||
export_constant(IG_BS_ITEM_M_S_4);
|
||||
export_constant(IG_BS_ITEM_M_S_6);
|
||||
export_constant(IG_BS_ITEM_M_S_7);
|
||||
export_constant(IG_BS_ITEM_M_S_12);
|
||||
export_constant(IG_BS_ITEM_M_S_13);
|
||||
export_constant(IG_BS_ITEM_M_S_15);
|
||||
export_constant(IG_BS_ITEM_M_S_28);
|
||||
export_constant(IG_BS_ITEM_M_S_29);
|
||||
export_constant(IG_BS_ITEM_M_S_31);
|
||||
export_constant(IG_BS_ITEM_M_S_32);
|
||||
export_constant(IG_BS_ITEM_M_S_33);
|
||||
export_constant(IG_BS_ITEM_M_S_36);
|
||||
export_constant(IG_BS_ITEM_M_S_37);
|
||||
export_constant(IG_BS_ITEM_M_S_38);
|
||||
export_constant(IG_BS_ITEM_M_S_39);
|
||||
export_constant(IG_BS_ITEM_M_S_40);
|
||||
export_constant(IG_BS_ITEM_M_S_45);
|
||||
export_constant(IG_BS_ITEM_M_S_46);
|
||||
export_constant(IG_BS_ITEM_M_S_47);
|
||||
export_constant(IG_BS_ITEM_M_S_48);
|
||||
export_constant(IG_BS_ITEM_M_S_49);
|
||||
export_constant(IG_BS_ITEM_M_S_50);
|
||||
export_constant(IG_BS_SHA_M_S_5);
|
||||
export_constant(IG_BS_SHA_M_S_6);
|
||||
export_constant(IG_BS_SHA_M_S_7);
|
||||
export_constant(IG_BS_SHA_M_S_8);
|
||||
export_constant(IG_BS_SHA_M_S_13);
|
||||
export_constant(IG_BS_SHA_M_S_15);
|
||||
export_constant(IG_BS_SHA_M_S_16);
|
||||
export_constant(IG_BS_SHA_M_S_23);
|
||||
export_constant(IG_BS_ITEM_M_S_5);
|
||||
export_constant(IG_BS_ITEM_M_S_9);
|
||||
export_constant(IG_BS_ITEM_M_S_14);
|
||||
export_constant(IG_BS_ITEM_M_S_16);
|
||||
export_constant(IG_BS_ITEM_M_S_17);
|
||||
export_constant(IG_BS_ITEM_M_S_19);
|
||||
export_constant(IG_BS_ITEM_M_S_27);
|
||||
export_constant(IG_BS_ITEM_M_S_35);
|
||||
export_constant(IG_BS_SHA_M_S_9);
|
||||
export_constant(IG_BS_SHA_M_S_10);
|
||||
export_constant(IG_BS_SHA_M_S_11);
|
||||
export_constant(IG_BS_SHA_M_S_21);
|
||||
export_constant(IG_BS_ITEM_M_S_1);
|
||||
export_constant(IG_BS_ITEM_M_S_3);
|
||||
export_constant(IG_BS_ITEM_M_S_18);
|
||||
export_constant(IG_BS_ITEM_M_S_20);
|
||||
export_constant(IG_BS_ITEM_M_S_21);
|
||||
export_constant(IG_BS_ITEM_M_S_22);
|
||||
export_constant(IG_BS_ITEM_M_S_23);
|
||||
export_constant(IG_BS_ITEM_M_S_24);
|
||||
export_constant(IG_BS_ITEM_M_S_25);
|
||||
export_constant(IG_BS_ITEM_M_S_26);
|
||||
export_constant(IG_BS_ITEM_M_S_30);
|
||||
export_constant(IG_BS_SHA_M_S_3);
|
||||
export_constant(IG_BS_SHA_M_S_4);
|
||||
export_constant(IG_BS_SHA_M_S_12);
|
||||
export_constant(IG_BS_SHA_M_S_14);
|
||||
export_constant(IG_BS_SHA_M_S_24);
|
||||
export_constant(IG_BS_SHA_M_S_25);
|
||||
export_constant(IG_BS_ITEM_M_S_51);
|
||||
export_constant(IG_ENCHANTSTONE_RECIPE_9M);
|
||||
export_constant(IG_IDTEST_SPECIAL);
|
||||
export_constant(IG_PERFECTSIZE_MIX);
|
||||
export_constant(IG_MAGICPIERCING_MIX);
|
||||
export_constant(IG_PIERCING_MIX);
|
||||
export_constant(IG_HASTY_MIX);
|
||||
export_constant(IG_ENCHANTSTONE_RECIPE_4M);
|
||||
|
||||
/* unit stop walking */
|
||||
export_constant(USW_NONE);
|
||||
|
@ -427,14 +427,14 @@ int do_init( int argc, char** argv ){
|
||||
}
|
||||
|
||||
item_group_txt_data(path_db_mode, path_db);
|
||||
if (!process("ITEM_GROUP_DB", 1, { path_db_mode }, "item_group_db", [](const std::string &path, const std::string &name_ext) -> bool {
|
||||
if (!process("ITEM_GROUP_DB", 2, { path_db_mode }, "item_group_db", [](const std::string &path, const std::string &name_ext) -> bool {
|
||||
return itemdb_read_group_yaml();
|
||||
})) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
item_group_txt_data(path_db_import, path_db_import);
|
||||
if (!process("ITEM_GROUP_DB", 1, { path_db_import }, "item_group_db", [](const std::string &path, const std::string &name_ext) -> bool {
|
||||
if (!process("ITEM_GROUP_DB", 2, { path_db_import }, "item_group_db", [](const std::string &path, const std::string &name_ext) -> bool {
|
||||
return itemdb_read_group_yaml();
|
||||
})) {
|
||||
return 0;
|
||||
|
Loading…
x
Reference in New Issue
Block a user