Initial release of item enchant UI (#7186)

Thanks to @aleos89, @Atemo @idk-whoami
This commit is contained in:
Lemongrass3110
2022-09-05 00:52:37 +02:00
committed by GitHub
parent 3c43669425
commit 8629c6445a
15 changed files with 19481 additions and 3 deletions

View File

@@ -24056,6 +24056,532 @@ void clif_parse_item_reform_start( int fd, struct map_session_data* sd ){
#endif
}
void clif_enchantwindow_open( struct map_session_data& sd, uint64 clientLuaIndex ){
#if PACKETVER_RE_NUM >= 20211103
// Hardcoded clientside check
if( sd.weight > ( ( sd.max_weight * 70 ) / 100 ) ){
clif_msg_color( &sd, C_ENCHANT_OVERWEIGHT, color_table[COLOR_RED] );
sd.state.item_enchant_index = 0;
return;
}
struct PACKET_ZC_UI_OPEN_V3 p = {};
p.packetType = HEADER_ZC_UI_OPEN_V3;
p.type = OUT_UI_ENCHANT;
p.data = clientLuaIndex;
clif_send( &p, sizeof( p ), &sd.bl, SELF );
sd.state.item_enchant_index = clientLuaIndex;
#endif
}
void clif_enchantwindow_result( struct map_session_data& sd, bool success, t_itemid enchant = 0 ){
#if PACKETVER_RE_NUM >= 20211103
struct PACKET_ZC_RESPONSE_ENCHANT p = {};
p.packetType = HEADER_ZC_RESPONSE_ENCHANT;
if( success ){
p.messageId = C_ENCHANT_SUCCESS;
}else{
p.messageId = C_ENCHANT_FAILURE;
}
p.enchantItemId = enchant;
clif_send( &p, sizeof( p ), &sd.bl, SELF );
sd.state.item_enchant_index = 0;
#endif
}
bool clif_parse_enchant_basecheck( struct item& selected_item, std::shared_ptr<s_item_enchant> enchant ){
if( selected_item.equip != 0 ){
return false;
}
if( selected_item.equipSwitch != 0 ){
return false;
}
if( selected_item.attribute != 0 ){
return false;
}
if( !util::vector_exists( enchant->target_item_ids, selected_item.nameid ) ){
return false;
}
if( selected_item.refine < enchant->minimumRefine ){
return false;
}
if( selected_item.enchantgrade < enchant->minimumEnchantgrade ){
return false;
}
if( !enchant->allowRandomOptions ){
for( const s_item_randomoption& option : selected_item.option ){
if( option.id != 0 ){
return false;
}
}
}
return true;
}
void clif_parse_enchantwindow_general( int fd, struct map_session_data* sd ){
#if PACKETVER_RE_NUM >= 20211103
struct PACKET_CZ_REQUEST_RANDOM_ENCHANT *p = (struct PACKET_CZ_REQUEST_RANDOM_ENCHANT*)RFIFOP( fd, 0 );
if( sd->state.item_enchant_index != p->clientLuaIndex ){
return;
}
uint16 index = server_index( p->index );
if( index >= MAX_INVENTORY ){
return;
}
if( sd->inventory_data[index] == nullptr ){
return;
}
struct item& selected_item = sd->inventory.u.items_inventory[index];
std::shared_ptr<s_item_enchant> enchant = item_enchant_db.find( p->clientLuaIndex );
if( enchant == nullptr ){
return;
}
if( !clif_parse_enchant_basecheck( selected_item, enchant ) ){
return;
}
uint16 slot = MAX_SLOTS;
for( uint16 nextSlot : enchant->order ){
if( selected_item.card[nextSlot] == 0 ){
slot = nextSlot;
break;
}
}
if( slot == MAX_SLOTS ){
return;
}
if( slot < sd->inventory_data[index]->slots ){
return;
}
std::shared_ptr<s_item_enchant_slot> enchant_slot = util::umap_find( enchant->slots, slot );
if( enchant_slot == nullptr ){
return;
}
std::shared_ptr<s_item_enchant_normal> enchants_for_enchantgrade = util::umap_find( enchant_slot->normal.enchants, (uint16)selected_item.enchantgrade );
if( enchants_for_enchantgrade == nullptr ){
clif_messagecolor( &sd->bl, color_table[COLOR_RED], msg_txt( sd, 829 ), false, SELF); // Enchanting is not possible for your item's enchant grade.
clif_enchantwindow_result( *sd, false );
return;
}
if( sd->status.zeny < enchant_slot->normal.zeny ){
return;
}
std::unordered_map<uint16, uint16> materials;
for( const auto& entry : enchant_slot->normal.materials ){
int16 idx = pc_search_inventory( sd, entry.first );
if( idx < 0 ){
return;
}
if( sd->inventory.u.items_inventory[idx].amount < entry.second ){
return;
}
materials[idx] = entry.second;
}
if( pc_payzeny( sd, enchant_slot->normal.zeny, LOG_TYPE_ENCHANT, nullptr ) != 0 ){
return;
}
for( const auto& entry : materials ){
if( pc_delitem( sd, entry.first, entry.second, 0, 0, LOG_TYPE_ENCHANT ) != 0 ){
return;
}
}
uint32 chance = enchant_slot->normal.chance;
for( int i = 0; i <= MAX_ENCHANTGRADE; i++ ){
chance += enchant_slot->normal.enchantgradeChanceIncrease[i];
}
if( chance < 100000 && rnd_value( 0, 100000 ) > chance ){
clif_enchantwindow_result( *sd, false );
return;
}
// Log removal of item
log_pick_pc( sd, LOG_TYPE_ENCHANT, -1, &selected_item );
size_t maximum = 3 * enchant_slot->normal.enchants.size();
bool enchanted = false;
for( int i = 0; i < maximum; i++ ){
std::shared_ptr<s_item_enchant_normal_sub> normal_enchant = util::umap_random( enchants_for_enchantgrade->enchants );
if( rnd_value( 0, 10000 ) < normal_enchant->chance ){
selected_item.card[slot] = normal_enchant->item_id;
enchanted = true;
break;
}
}
if( !enchanted ){
std::shared_ptr<s_item_enchant_normal_sub> normal_enchant = util::umap_random( enchants_for_enchantgrade->enchants );
selected_item.card[slot] = normal_enchant->item_id;
}
// Log retrieving the item again -> with the new enchant
log_pick_pc( sd, LOG_TYPE_ENCHANT, 1, &selected_item );
clif_enchantwindow_result( *sd, true, selected_item.card[slot] );
#endif
}
void clif_parse_enchantwindow_perfect( int fd, struct map_session_data* sd ){
#if PACKETVER_RE_NUM >= 20211103
struct PACKET_CZ_REQUEST_PERFECT_ENCHANT *p = (struct PACKET_CZ_REQUEST_PERFECT_ENCHANT*)RFIFOP( fd, 0 );
if( sd->state.item_enchant_index != p->clientLuaIndex ){
return;
}
uint16 index = server_index( p->index );
if( index >= MAX_INVENTORY ){
return;
}
if( sd->inventory_data[index] == nullptr ){
return;
}
struct item& selected_item = sd->inventory.u.items_inventory[index];
std::shared_ptr<s_item_enchant> enchant = item_enchant_db.find( p->clientLuaIndex );
if( enchant == nullptr ){
return;
}
if( !clif_parse_enchant_basecheck( selected_item, enchant ) ){
return;
}
uint16 slot = MAX_SLOTS;
for( uint16 nextSlot : enchant->order ){
if( selected_item.card[nextSlot] == 0 ){
slot = nextSlot;
break;
}
}
if( slot == MAX_SLOTS ){
return;
}
if( slot < sd->inventory_data[index]->slots ){
return;
}
std::shared_ptr<s_item_enchant_slot> enchant_slot = util::umap_find( enchant->slots, slot );
if( enchant_slot == nullptr ){
return;
}
std::shared_ptr<s_item_enchant_perfect> perfect_enchant = util::umap_find( enchant_slot->perfect.enchants, p->itemId );
if( perfect_enchant == nullptr ){
return;
}
if( sd->status.zeny < perfect_enchant->zeny ){
return;
}
std::unordered_map<uint16, uint16> materials;
for( const auto& entry : perfect_enchant->materials ){
int16 idx = pc_search_inventory( sd, entry.first );
if( idx < 0 ){
return;
}
if( sd->inventory.u.items_inventory[idx].amount < entry.second ){
return;
}
materials[idx] = entry.second;
}
if( pc_payzeny( sd, perfect_enchant->zeny, LOG_TYPE_ENCHANT, nullptr ) != 0 ){
return;
}
for( const auto& entry : materials ){
if( pc_delitem( sd, entry.first, entry.second, 0, 0, LOG_TYPE_ENCHANT ) != 0 ){
return;
}
}
// Log removal of item
log_pick_pc( sd, LOG_TYPE_ENCHANT, -1, &selected_item );
selected_item.card[slot] = perfect_enchant->item_id;
// Log retrieving the item again -> with the new enchant
log_pick_pc( sd, LOG_TYPE_ENCHANT, 1, &selected_item );
clif_enchantwindow_result( *sd, true, selected_item.card[slot] );
#endif
}
void clif_parse_enchantwindow_upgrade( int fd, struct map_session_data* sd ){
#if PACKETVER_RE_NUM >= 20211103
struct PACKET_CZ_REQUEST_UPGRADE_ENCHANT *p = (struct PACKET_CZ_REQUEST_UPGRADE_ENCHANT*)RFIFOP( fd, 0 );
if( sd->state.item_enchant_index != p->clientLuaIndex ){
return;
}
uint16 index = server_index( p->index );
if( index >= MAX_INVENTORY ){
return;
}
if( sd->inventory_data[index] == nullptr ){
return;
}
struct item& selected_item = sd->inventory.u.items_inventory[index];
std::shared_ptr<s_item_enchant> enchant = item_enchant_db.find( p->clientLuaIndex );
if( enchant == nullptr ){
return;
}
if( !clif_parse_enchant_basecheck( selected_item, enchant ) ){
return;
}
uint16 slot = p->slot;
if( slot >= MAX_SLOTS ){
return;
}
if( slot < sd->inventory_data[index]->slots ){
return;
}
if( selected_item.card[slot] == 0 ){
return;
}
std::shared_ptr<s_item_enchant_slot> enchant_slot = util::umap_find( enchant->slots, slot );
if( enchant_slot == nullptr ){
return;
}
std::shared_ptr<s_item_enchant_upgrade> upgrade = util::umap_find( enchant_slot->upgrade.enchants, selected_item.card[slot] );
if( upgrade == nullptr ){
return;
}
if( sd->status.zeny < upgrade->zeny ){
return;
}
std::unordered_map<uint16, uint16> materials;
for( const auto& entry : upgrade->materials ){
int16 idx = pc_search_inventory( sd, entry.first );
if( idx < 0 ){
return;
}
if( sd->inventory.u.items_inventory[idx].amount < entry.second ){
return;
}
materials[idx] = entry.second;
}
if( pc_payzeny( sd, upgrade->zeny, LOG_TYPE_ENCHANT, nullptr ) != 0 ){
return;
}
for( const auto& entry : materials ){
if( pc_delitem( sd, entry.first, entry.second, 0, 0, LOG_TYPE_ENCHANT ) != 0 ){
return;
}
}
// Log removal of item
log_pick_pc( sd, LOG_TYPE_ENCHANT, -1, &selected_item );
selected_item.card[slot] = upgrade->upgrade_item_id;
// Log retrieving the item again -> with the new enchant
log_pick_pc( sd, LOG_TYPE_ENCHANT, 1, &selected_item );
clif_enchantwindow_result( *sd, true, selected_item.card[slot] );
#endif
}
void clif_parse_enchantwindow_reset( int fd, struct map_session_data* sd ){
#if PACKETVER_RE_NUM >= 20211103
struct PACKET_CZ_REQUEST_RESET_ENCHANT *p = (struct PACKET_CZ_REQUEST_RESET_ENCHANT*)RFIFOP( fd, 0 );
if( sd->state.item_enchant_index != p->clientLuaIndex ){
return;
}
uint16 index = server_index( p->index );
if( index >= MAX_INVENTORY ){
return;
}
if( sd->inventory_data[index] == nullptr ){
return;
}
struct item& selected_item = sd->inventory.u.items_inventory[index];
if( selected_item.equip != 0 ){
return;
}
if( selected_item.equipSwitch != 0 ){
return;
}
if( selected_item.attribute != 0 ){
return;
}
std::shared_ptr<s_item_enchant> enchant = item_enchant_db.find( p->clientLuaIndex );
if( enchant == nullptr ){
return;
}
if( !util::vector_exists( enchant->target_item_ids, selected_item.nameid ) ){
return;
}
if( selected_item.refine < enchant->minimumRefine ){
return;
}
if( selected_item.enchantgrade < enchant->minimumEnchantgrade ){
return;
}
bool is_enchanted = false;
for( int i = sd->inventory_data[index]->slots; i < MAX_SLOTS; i++ ){
if( selected_item.card[i] != 0 ){
is_enchanted = true;
break;
}
}
if( !is_enchanted ){
return;
}
if( sd->status.zeny < enchant->reset.zeny ){
return;
}
std::unordered_map<uint16, uint16> materials;
for( const auto& entry : enchant->reset.materials ){
int16 idx = pc_search_inventory( sd, entry.first );
if( idx < 0 ){
return;
}
if( sd->inventory.u.items_inventory[idx].amount < entry.second ){
return;
}
materials[idx] = entry.second;
}
if( pc_payzeny( sd, enchant->reset.zeny, LOG_TYPE_ENCHANT, nullptr ) != 0 ){
return;
}
for( const auto& entry : materials ){
if( pc_delitem( sd, entry.first, entry.second, 0, 0, LOG_TYPE_ENCHANT ) != 0 ){
return;
}
}
uint32 chance = enchant->reset.chance;
if( chance == 0 ){
return;
}
if( chance < 100000 && rnd_value( 0, 100000 ) > chance ){
clif_enchantwindow_result( *sd, false );
return;
}
// Log removal of item
log_pick_pc( sd, LOG_TYPE_ENCHANT, -1, &selected_item );
for( int i = sd->inventory_data[index]->slots; i < MAX_SLOTS; i++ ){
selected_item.card[i] = 0;
}
// Log retrieving the item again -> with the new enchant
log_pick_pc( sd, LOG_TYPE_ENCHANT, 1, &selected_item );
clif_enchantwindow_result( *sd, true );
#endif
}
void clif_parse_enchantwindow_close( int fd, struct map_session_data* sd ){
#if PACKETVER_RE_NUM >= 20211103
sd->state.item_enchant_index = 0;
#endif
}
/*==========================================
* Main client packet processing function
*------------------------------------------*/