Initial implementation of enchantgrade UI (#6913)
Includes walkscript conversion of kRO scripts Thanks to @Asheraf, @Balferian, @JohnnyPlayy, @aleos89, @Atemo, @eppc0330 and @Pokye. Co-authored-by: JohnnyPlayy <lenon32@gmail.com> Co-authored-by: Asheraf <Asheraf@users.noreply.github.com> Co-authored-by: Balferian <balfear@yandex.ru> Co-authored-by: Aleos <aleos89@users.noreply.github.com> Co-authored-by: Atemo <Atemo@users.noreply.github.com>
This commit is contained in:
parent
24cfdc68de
commit
001981cf66
@ -1010,6 +1010,9 @@ Body:
|
||||
Aliases:
|
||||
- famepoint
|
||||
- famepoints
|
||||
- Command: enchantgradeui
|
||||
Help: |
|
||||
Opens the enchantgrade UI.
|
||||
|
||||
Footer:
|
||||
Imports:
|
||||
|
@ -8,37 +8,40 @@
|
||||
//--------------------------------------------------------------
|
||||
|
||||
// Enable Logs? (Note 3)
|
||||
// 0x0000000 - Don't log at all
|
||||
// 0x0000001 - (T) Log trades
|
||||
// 0x0000002 - (V) Log vending transactions
|
||||
// 0x0000004 - (P) Log items drop/picked by players
|
||||
// 0x0000008 - (L) Log items drop/looted by monsters
|
||||
// 0x0000010 - (S) Log NPC transactions (buy/sell)
|
||||
// 0x0000020 - (N) Log Script transactions (items deleted/acquired through quests)
|
||||
// 0x0000040 - (D) Log items stolen from mobs (Steal/Gank)
|
||||
// 0x0000080 - (C) Log player-used items (consumables/pet&hom&merc food/items used for skills&attacks)
|
||||
// 0x0000100 - (O) Log produced/ingredient items
|
||||
// 0x0000200 - (U) Log MVP prize items
|
||||
// 0x0000400 - (A) Log player created/deleted items (through @/# commands)
|
||||
// 0x0000800 - (R) Log items placed/retrieved from storage.
|
||||
// 0x0001000 - (G) Log items placed/retrieved from guild storage.
|
||||
// 0x0002000 - (E) Log mail system transactions.
|
||||
// 0x0004000 - (I) Log auction system transactions.
|
||||
// 0x0008000 - (B) Log buying store transactions
|
||||
// 0x0010000 - (X) Log all other transactions (rentals expiring/inserting cards/items removed by item_check/
|
||||
// 0x00000000 - Don't log at all
|
||||
// 0x00000001 - (T) Log trades
|
||||
// 0x00000002 - (V) Log vending transactions
|
||||
// 0x00000004 - (P) Log items drop/picked by players
|
||||
// 0x00000008 - (L) Log items drop/looted by monsters
|
||||
// 0x00000010 - (S) Log NPC transactions (buy/sell)
|
||||
// 0x00000020 - (N) Log Script transactions (items deleted/acquired through quests)
|
||||
// 0x00000040 - (D) Log items stolen from mobs (Steal/Gank)
|
||||
// 0x00000080 - (C) Log player-used items (consumables/pet&hom&merc food/items used for skills&attacks)
|
||||
// 0x00000100 - (O) Log produced/ingredient items
|
||||
// 0x00000200 - (U) Log MVP prize items
|
||||
// 0x00000400 - (A) Log player created/deleted items (through @/# commands)
|
||||
// 0x00000800 - (R) Log items placed/retrieved from storage.
|
||||
// 0x00001000 - (G) Log items placed/retrieved from guild storage.
|
||||
// 0x00002000 - (E) Log mail system transactions.
|
||||
// 0x00004000 - (I) Log auction system transactions.
|
||||
// 0x00008000 - (B) Log buying store transactions
|
||||
// 0x00010000 - (X) Log all other transactions (rentals expiring/inserting cards/items removed by item_check/
|
||||
// rings deleted by divorce/pet egg (un)hatching/pet armor (un)equipping/Weapon Refine skill/Remove Trap skill/Stylist)
|
||||
// 0x0020000 - ($) Log cash transactions
|
||||
// 0x0040000 - (K) Log account bank transactions
|
||||
// 0x0080000 - (F) Removed bound items when guild/party is broken
|
||||
// 0x0100000 - (Y) Log Roulette Lottery
|
||||
// 0x0200000 - (Z) Merged items from item mergers process.
|
||||
// 0x0400000 - (Q) Log items given from quest-granted drops.
|
||||
// 0x0800000 - (H) Log items consumed by Private Airship system
|
||||
// 0x1000000 - (J) Log Barter Shop transactions
|
||||
// 0x2000000 - (W) Log Laphine system transactions
|
||||
// 0x00020000 - ($) Log cash transactions
|
||||
// 0x00040000 - (K) Log account bank transactions
|
||||
// 0x00080000 - (F) Removed bound items when guild/party is broken
|
||||
// 0x00100000 - (Y) Log Roulette Lottery
|
||||
// 0x00200000 - (Z) Merged items from item mergers process.
|
||||
// 0x00400000 - (Q) Log items given from quest-granted drops.
|
||||
// 0x00800000 - (H) Log items consumed by Private Airship system
|
||||
// 0x01000000 - (J) Log Barter Shop transactions
|
||||
// 0x02000000 - (W) Log Laphine system transactions
|
||||
// 0x04000000 - (0) Enchantgrade UI
|
||||
// 0x08000000 - (1) Reform UI
|
||||
// 0x10000000 - (2) Enchant UI
|
||||
// Example: Log trades+vending+script items+created items: 1+2+32+1024 = 1059
|
||||
// Please note that moving items from inventory to cart and back is not logged by design.
|
||||
enable_logs: 0xFFFFFFF
|
||||
enable_logs: 0xFFFFFFFF
|
||||
|
||||
// Use MySQL Logs? (Note 1)
|
||||
sql_logs: yes
|
||||
|
@ -921,7 +921,10 @@
|
||||
// @mobinfo RES/MRES
|
||||
827: RES:%d MRES:%d
|
||||
|
||||
//828-899 free
|
||||
// General packet version check messages
|
||||
828: This command requires packet version %s or newer.
|
||||
|
||||
//829-899 free
|
||||
|
||||
//------------------------------------
|
||||
// More atcommands message
|
||||
|
58
db/enchantgrade.yml
Normal file
58
db/enchantgrade.yml
Normal file
@ -0,0 +1,58 @@
|
||||
# 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/>.
|
||||
#
|
||||
###########################################################################
|
||||
# Enchantgrade Database
|
||||
###########################################################################
|
||||
#
|
||||
# Enchantgrade Settings
|
||||
#
|
||||
###########################################################################
|
||||
# - Type Item type.
|
||||
# Levels: Enchantgrade settings per item level.
|
||||
# - Level Item level.
|
||||
# Grades: Enchantgrade settings per grade level.
|
||||
# - Grade Enchantgrade level.
|
||||
# Refine Required refine level.
|
||||
# Chance Base chance of success out of 0~10000.
|
||||
# Bonus Enchantgrade bonus. (Default: 0)
|
||||
# Announce Announce if someone tries to increase the enchantgrade. (Default: true)
|
||||
# Catalyst: Catalyst item to increase chance of success.
|
||||
# Item The item that can be used.
|
||||
# AmountPerStep Amount of Item needed.
|
||||
# Set to 0 to disable the catalyst.
|
||||
# MaximumSteps Maximum amount of times Item can be used.
|
||||
# ChanceIncrease Amount at which the chance increases for each Item used.
|
||||
# Options: Success chance based on cost type.
|
||||
# - Option Index of the client option.
|
||||
# Item Required item.
|
||||
# Amount Amount of required item. (Default: 1)
|
||||
# Set to 0 to remove an option.
|
||||
# Price Amount of zeny required. (Default: 0)
|
||||
# BreakingRate Chance of item breaking out of 0~10000. (Default: 0)
|
||||
# DowngradeAmount Number of refine levels reduced on failure. (Default: 0)
|
||||
###########################################################################
|
||||
|
||||
Header:
|
||||
Type: ENCHANTGRADE_DB
|
||||
Version: 1
|
||||
|
||||
Footer:
|
||||
Imports:
|
||||
- Path: db/re/enchantgrade.yml
|
||||
Mode: Renewal
|
||||
- Path: db/import/enchantgrade.yml
|
52
db/import-tmpl/enchantgrade.yml
Normal file
52
db/import-tmpl/enchantgrade.yml
Normal file
@ -0,0 +1,52 @@
|
||||
# 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/>.
|
||||
#
|
||||
###########################################################################
|
||||
# Enchantgrade Database
|
||||
###########################################################################
|
||||
#
|
||||
# Enchantgrade Settings
|
||||
#
|
||||
###########################################################################
|
||||
# - Type Item type.
|
||||
# Levels: Enchantgrade settings per item level.
|
||||
# - Level Item level.
|
||||
# Grades: Enchantgrade settings per grade level.
|
||||
# - Grade Enchantgrade level.
|
||||
# Refine Required refine level.
|
||||
# Chance Base chance of success out of 0~10000.
|
||||
# Bonus Enchantgrade bonus. (Default: 0)
|
||||
# Announce Announce if someone tries to increase the enchantgrade. (Default: true)
|
||||
# Catalyst: Catalyst item to increase chance of success.
|
||||
# Item The item that can be used.
|
||||
# AmountPerStep Amount of Item needed.
|
||||
# Set to 0 to disable the catalyst.
|
||||
# MaximumSteps Maximum amount of times Item can be used.
|
||||
# ChanceIncrease Amount at which the chance increases for each Item used.
|
||||
# Options: Success chance based on cost type.
|
||||
# - Option Index of the client option.
|
||||
# Item Required item.
|
||||
# Amount Amount of required item. (Default: 1)
|
||||
# Set to 0 to remove an option.
|
||||
# Price Amount of zeny required. (Default: 0)
|
||||
# BreakingRate Chance of item breaking out of 0~10000. (Default: 0)
|
||||
# DowngradeAmount Number of refine levels reduced on failure. (Default: 0)
|
||||
###########################################################################
|
||||
|
||||
Header:
|
||||
Type: ENCHANTGRADE_DB
|
||||
Version: 1
|
214
db/re/enchantgrade.yml
Normal file
214
db/re/enchantgrade.yml
Normal file
@ -0,0 +1,214 @@
|
||||
# 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/>.
|
||||
#
|
||||
###########################################################################
|
||||
# Enchantgrade Database
|
||||
###########################################################################
|
||||
#
|
||||
# Enchantgrade Settings
|
||||
#
|
||||
###########################################################################
|
||||
# - Type Item type.
|
||||
# Levels: Enchantgrade settings per item level.
|
||||
# - Level Item level.
|
||||
# Grades: Enchantgrade settings per grade level.
|
||||
# - Grade Enchantgrade level.
|
||||
# Refine Required refine level.
|
||||
# Chance Base chance of success out of 0~10000.
|
||||
# Bonus Enchantgrade bonus. (Default: 0)
|
||||
# Announce Announce if someone tries to increase the enchantgrade. (Default: true)
|
||||
# Catalyst: Catalyst item to increase chance of success.
|
||||
# Item The item that can be used.
|
||||
# AmountPerStep Amount of Item needed.
|
||||
# Set to 0 to disable the catalyst.
|
||||
# MaximumSteps Maximum amount of times Item can be used.
|
||||
# ChanceIncrease Amount at which the chance increases for each Item used.
|
||||
# Options: Success chance based on cost type.
|
||||
# - Option Index of the client option.
|
||||
# Item Required item.
|
||||
# Amount Amount of required item. (Default: 1)
|
||||
# Set to 0 to remove an option.
|
||||
# Price Amount of zeny required. (Default: 0)
|
||||
# BreakingRate Chance of item breaking out of 0~10000. (Default: 0)
|
||||
# DowngradeAmount Number of refine levels reduced on failure. (Default: 0)
|
||||
###########################################################################
|
||||
|
||||
Header:
|
||||
Type: ENCHANTGRADE_DB
|
||||
Version: 1
|
||||
|
||||
Body:
|
||||
- Type: Armor
|
||||
Levels:
|
||||
- Level: 2
|
||||
Grades:
|
||||
- Grade: None
|
||||
Refine: 11
|
||||
Chance: 7000
|
||||
Bonus: 10
|
||||
Catalyst:
|
||||
Item: Blessed_Etel_Dust
|
||||
AmountPerStep: 1
|
||||
MaximumSteps: 10
|
||||
ChanceIncrease: 100
|
||||
Options:
|
||||
- Option: 0
|
||||
Item: Etel_Skyblue_Jewel
|
||||
Amount: 1
|
||||
Zeny: 175000
|
||||
BreakingRate: 10000
|
||||
- Option: 1
|
||||
Item: Etel_Skyblue_Jewel
|
||||
Amount: 5
|
||||
Zeny: 875000
|
||||
- Grade: D
|
||||
Refine: 11
|
||||
Chance: 6000
|
||||
Bonus: 30
|
||||
Catalyst:
|
||||
Item: Blessed_Etel_Dust
|
||||
AmountPerStep: 3
|
||||
MaximumSteps: 10
|
||||
ChanceIncrease: 100
|
||||
Options:
|
||||
- Option: 0
|
||||
Item: Etel_Topaz
|
||||
Amount: 1
|
||||
Zeny: 175000
|
||||
BreakingRate: 10000
|
||||
- Option: 1
|
||||
Item: Etel_Topaz
|
||||
Amount: 5
|
||||
Zeny: 875000
|
||||
- Grade: C
|
||||
Refine: 11
|
||||
Chance: 5000
|
||||
Bonus: 50
|
||||
Catalyst:
|
||||
Item: Blessed_Etel_Dust
|
||||
AmountPerStep: 5
|
||||
MaximumSteps: 10
|
||||
ChanceIncrease: 100
|
||||
Options:
|
||||
- Option: 0
|
||||
Item: Etel_Violet_Jewel
|
||||
Amount: 1
|
||||
Zeny: 175000
|
||||
BreakingRate: 10000
|
||||
- Option: 1
|
||||
Item: Etel_Violet_Jewel
|
||||
Amount: 5
|
||||
Zeny: 875000
|
||||
- Grade: B
|
||||
Refine: 11
|
||||
Chance: 4000
|
||||
Bonus: 100
|
||||
Catalyst:
|
||||
Item: Blessed_Etel_Dust
|
||||
AmountPerStep: 7
|
||||
MaximumSteps: 10
|
||||
ChanceIncrease: 100
|
||||
Options:
|
||||
- Option: 0
|
||||
Item: Etel_Amber
|
||||
Amount: 2
|
||||
Zeny: 175000
|
||||
BreakingRate: 10000
|
||||
- Option: 1
|
||||
Item: Etel_Amber
|
||||
Amount: 10
|
||||
Zeny: 875000
|
||||
- Type: Weapon
|
||||
Levels:
|
||||
- Level: 5
|
||||
Grades:
|
||||
- Grade: None
|
||||
Refine: 11
|
||||
Chance: 7000
|
||||
Bonus: 10
|
||||
Catalyst:
|
||||
Item: Blessed_Etel_Dust
|
||||
AmountPerStep: 1
|
||||
MaximumSteps: 10
|
||||
ChanceIncrease: 100
|
||||
Options:
|
||||
- Option: 0
|
||||
Item: Etel_Skyblue_Jewel
|
||||
Amount: 1
|
||||
Zeny: 175000
|
||||
BreakingRate: 10000
|
||||
- Option: 1
|
||||
Item: Etel_Skyblue_Jewel
|
||||
Amount: 5
|
||||
Zeny: 875000
|
||||
- Grade: D
|
||||
Refine: 11
|
||||
Chance: 6000
|
||||
Bonus: 30
|
||||
Catalyst:
|
||||
Item: Blessed_Etel_Dust
|
||||
AmountPerStep: 3
|
||||
MaximumSteps: 10
|
||||
ChanceIncrease: 100
|
||||
Options:
|
||||
- Option: 0
|
||||
Item: Etel_Topaz
|
||||
Amount: 1
|
||||
Zeny: 175000
|
||||
BreakingRate: 10000
|
||||
- Option: 1
|
||||
Item: Etel_Topaz
|
||||
Amount: 5
|
||||
Zeny: 875000
|
||||
- Grade: C
|
||||
Refine: 11
|
||||
Chance: 5000
|
||||
Bonus: 50
|
||||
Catalyst:
|
||||
Item: Blessed_Etel_Dust
|
||||
AmountPerStep: 5
|
||||
MaximumSteps: 10
|
||||
ChanceIncrease: 100
|
||||
Options:
|
||||
- Option: 0
|
||||
Item: Etel_Violet_Jewel
|
||||
Amount: 1
|
||||
Zeny: 175000
|
||||
BreakingRate: 10000
|
||||
- Option: 1
|
||||
Item: Etel_Violet_Jewel
|
||||
Amount: 5
|
||||
Zeny: 875000
|
||||
- Grade: B
|
||||
Refine: 11
|
||||
Chance: 4000
|
||||
Bonus: 100
|
||||
Catalyst:
|
||||
Item: Blessed_Etel_Dust
|
||||
AmountPerStep: 7
|
||||
MaximumSteps: 10
|
||||
ChanceIncrease: 100
|
||||
Options:
|
||||
- Option: 0
|
||||
Item: Etel_Amber
|
||||
Amount: 2
|
||||
Zeny: 175000
|
||||
BreakingRate: 10000
|
||||
- Option: 1
|
||||
Item: Etel_Amber
|
||||
Amount: 10
|
||||
Zeny: 875000
|
@ -61756,6 +61756,7 @@ Body:
|
||||
AegisName: Amber
|
||||
Name: Amber
|
||||
Type: Etc
|
||||
Buy: 45000
|
||||
Weight: 100
|
||||
- Id: 1000322
|
||||
AegisName: Etel_Dust
|
||||
|
@ -1178,6 +1178,12 @@ If args are given, sets camera position.
|
||||
|
||||
---------------------------------------
|
||||
|
||||
@enchantgradeui
|
||||
|
||||
Opens the enchantgrade UI.
|
||||
|
||||
---------------------------------------
|
||||
|
||||
==============================
|
||||
| 5. Administrative Commands |
|
||||
==============================
|
||||
|
@ -8164,7 +8164,15 @@ This function is intended for use in item scripts.
|
||||
|
||||
Opens the Bank UI for the attached player or the given character ID.
|
||||
|
||||
This command requires packet version 2015-01-28 or newer.
|
||||
This command requires packet version 2015-12-02 or newer.
|
||||
|
||||
---------------------------------------
|
||||
|
||||
*enchantgradeui {<char id>};
|
||||
|
||||
Opens the enchantgrade UI for the attached character or the player given by the char ID parameter.
|
||||
|
||||
This command requires packet version 2020-07-24 or newer.
|
||||
|
||||
---------------------------------------
|
||||
\\
|
||||
@ -9784,6 +9792,8 @@ QMARK_PURPLE - Purple Marker
|
||||
Opens the quest UI for the attached player or the given character ID.
|
||||
Use 0 as the quest ID to open the main quest UI. If the quest ID is not 0 then the quest UI is opened to the given quest. If the quest data is not populated in the client LUB then a message will be displayed saying the quest doesn't exist.
|
||||
|
||||
This command requires packet version 2015-12-02 or newer.
|
||||
|
||||
---------------------------------------
|
||||
|
||||
============================
|
||||
|
@ -52,3 +52,4 @@ Footer:
|
||||
- Path: npc/re/merchants/barters/quests_16_2.yml
|
||||
- Path: npc/re/merchants/barters/quests_17_1.yml
|
||||
- Path: npc/re/merchants/barters/refine.yml
|
||||
- Path: npc/re/merchants/barters/enchantgrade.yml
|
||||
|
110
npc/re/merchants/barters/enchantgrade.yml
Normal file
110
npc/re/merchants/barters/enchantgrade.yml
Normal file
@ -0,0 +1,110 @@
|
||||
# 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/>.
|
||||
#
|
||||
###########################################################################
|
||||
# Barter Database
|
||||
###########################################################################
|
||||
#
|
||||
# Barter Settings
|
||||
#
|
||||
###########################################################################
|
||||
# - Name NPC name.
|
||||
# Map Map name. (Default: not on a map)
|
||||
# X Map x coordinate. (Default: 0)
|
||||
# Y Map y coordinate. (Default: 0)
|
||||
# Direction Direction the NPC is looking. (Default: North)
|
||||
# Sprite Sprite name of the NPC. (Default: FakeNpc)
|
||||
# Items: List of sold items.
|
||||
# - Index Index of the item inside the shop. (0-...)
|
||||
# Maximum index depends on client.
|
||||
# Item Aegis name of the item.
|
||||
# Stock Amount of item in stock. 0 means unlimited. (Default: 0)
|
||||
# Zeny Cost of them item in Zeny. (Default: 0)
|
||||
# RequiredItems: List of required items (Optional)
|
||||
# - Index Index of the required item. (0-4)
|
||||
# Item Aegis name of required item.
|
||||
# Amount Amount of required item. (Default: 1)
|
||||
# Refine Refine level of required item. (Default: 0)
|
||||
###########################################################################
|
||||
|
||||
Header:
|
||||
Type: BARTER_DB
|
||||
Version: 1
|
||||
|
||||
Body:
|
||||
###########################################################################
|
||||
##= Enchant Grade Exchange
|
||||
###########################################################################
|
||||
- Name: EnchantGradeExchange
|
||||
Items:
|
||||
- Index: 0
|
||||
Item: Etel_Stone
|
||||
Zeny: 100000
|
||||
RequiredItems:
|
||||
- Index: 0
|
||||
Item: Etel_Dust
|
||||
Amount: 5
|
||||
- Index: 1
|
||||
Item: Blessed_Etel_Dust
|
||||
Zeny: 100000
|
||||
RequiredItems:
|
||||
- Index: 0
|
||||
Item: Etel_Dust
|
||||
Amount: 5
|
||||
- Index: 1
|
||||
Item: Blacksmith_Blessing
|
||||
Amount: 1
|
||||
- Index: 2
|
||||
Item: Etel_Skyblue_Jewel
|
||||
Zeny: 100000
|
||||
RequiredItems:
|
||||
- Index: 0
|
||||
Item: Etel_Stone
|
||||
Amount: 3
|
||||
- Index: 1
|
||||
Item: Skyblue_Jewel
|
||||
Amount: 1
|
||||
- Index: 3
|
||||
Item: Etel_Topaz
|
||||
Zeny: 200000
|
||||
RequiredItems:
|
||||
- Index: 0
|
||||
Item: Etel_Stone
|
||||
Amount: 6
|
||||
- Index: 1
|
||||
Item: Golden_Jewel
|
||||
Amount: 1
|
||||
- Index: 4
|
||||
Item: Etel_Violet_Jewel
|
||||
Zeny: 300000
|
||||
RequiredItems:
|
||||
- Index: 0
|
||||
Item: Etel_Stone
|
||||
Amount: 10
|
||||
- Index: 1
|
||||
Item: Violet_Jewel
|
||||
Amount: 1
|
||||
- Index: 5
|
||||
Item: Etel_Amber
|
||||
Zeny: 300000
|
||||
RequiredItems:
|
||||
- Index: 0
|
||||
Item: Etel_Stone
|
||||
Amount: 15
|
||||
- Index: 1
|
||||
Item: Amber
|
||||
Amount: 1
|
131
npc/re/merchants/enchantgrade.txt
Normal file
131
npc/re/merchants/enchantgrade.txt
Normal file
@ -0,0 +1,131 @@
|
||||
//===== rAthena Script =======================================
|
||||
//= Enchant Grade
|
||||
//===== Changelogs: ==========================================
|
||||
//= 1.0 First Version. [JohnnyPlayy]
|
||||
//= 1.1 Fixed small issues. [Lemongrass]
|
||||
//= 1.2 Added translation. [Asheraf]
|
||||
//= 1.3 Added paramarket NPC and warps. [Balfear]
|
||||
//= 1.4 Translated paramarket NPC. [Lemongrass]
|
||||
//============================================================
|
||||
|
||||
grademk,34,184,4 script Sratos#sratos 4_JP_GARM_H,{
|
||||
mes "[Sratos]";
|
||||
mes "Hello, dear customer who walked in, let's hope for a miracle today.";
|
||||
mes "How can I help you?";
|
||||
next;
|
||||
switch( select( "Enhance the equipment's grade.", "Exchange Etel items", "What is Grade Enhancement?" ) ){
|
||||
case 1:
|
||||
mes "[Sratos]";
|
||||
mes "Our customer. You want to enhance the grade of equipment.";
|
||||
mes "It is not easy to move the magical power of jewels.";
|
||||
next;
|
||||
mes "[Sratos]";
|
||||
mes "Magical power can explode on the spot.";
|
||||
mes "Then the weapon that will inherit the magical power also explodes!";
|
||||
next;
|
||||
switch( select( "I'll still do it!", "I'll think about it." ) ){
|
||||
case 1:
|
||||
mes "[Sratos]";
|
||||
mes "I wish good luck to our courageous customers!";
|
||||
close2;
|
||||
enchantgradeui();
|
||||
end;
|
||||
case 2:
|
||||
mes "[Sratos]";
|
||||
mes "Whenever you have the courage to challenge, please come back.";
|
||||
close;
|
||||
}
|
||||
case 2:
|
||||
mes "[Sratos]";
|
||||
mes "These are jewels used to enhance grades.";
|
||||
mes "Etel Dust, the jewels that will be the base, and if you give me a small fee I'll exchange it for Etel jewels.";
|
||||
close2;
|
||||
callshop "EnchantGradeExchange";
|
||||
end;
|
||||
|
||||
case 3:
|
||||
mes "[Sratos]";
|
||||
mes "Occasionally, unstable jewels with a lot of pure magical power are found.";
|
||||
mes "We call these etheric gems, right?";
|
||||
next;
|
||||
mes "[Sratos]";
|
||||
mes "You can transfer the magical power of the etheric gem to other weapons, but of course there is some risk.";
|
||||
mes "It's delicate, so if you aren't careful, pop! It will explode.";
|
||||
next;
|
||||
mes "[Sratos]";
|
||||
mes "Anyway, if you use this etheric gem, you can enhance the weapon you are using.";
|
||||
mes "Performance gets better. We call this grade enhancement.";
|
||||
next;
|
||||
mes "[Sratos]";
|
||||
mes "You too, wouldn't you be happy if the weapons you love grow one step further?";
|
||||
mes "We are the people who assist it. It's a bit risky, though. ahahaha.";
|
||||
close;
|
||||
}
|
||||
|
||||
OnInit:
|
||||
setunittitle(getnpcid(0), "<Grade Enhancer>");
|
||||
end;
|
||||
}
|
||||
|
||||
paramk,34,184,4 script Suribell#suribell 4_F_FRUIT,{
|
||||
mes "[Suribell]";
|
||||
mes "May good luck always be with you!";
|
||||
mes "Welcome to Paramarket's Grade Enhancement Center~";
|
||||
next;
|
||||
switch( select( "Enhance the equipment's grade.", "Exchange Etel items", "What is Grade Enhancement?" )) {
|
||||
case 1:
|
||||
mes "[Suribell]";
|
||||
mes "Do you want to unlock the potential of your favorite equipment?";
|
||||
mes "Explosions may also occur in the process of dealing with magical powers.";
|
||||
next;
|
||||
mes "[Suribell]";
|
||||
mes "Still, if you're trying to enhance your grade... !";
|
||||
mes "I, Suribell, will do my best!";
|
||||
next;
|
||||
switch( select( "I'll still do it!", "I'll think about it." ) ){
|
||||
case 1:
|
||||
mes "[Suribell]";
|
||||
mes "Let's hold hands and have faith! Try clenching your teeth!";
|
||||
close2;
|
||||
enchantgradeui();
|
||||
end;
|
||||
case 2:
|
||||
mes "[Suribell]";
|
||||
mes "Okay! Let's drink a glass of cold water!";
|
||||
close;
|
||||
}
|
||||
case 2:
|
||||
mes "[Suribell]";
|
||||
mes "You need etheric gems to enhance grades!";
|
||||
mes "If you combine Etel Dust and jewels to make it, it is fine! An Etel jewel for adventurers is complete!";
|
||||
mes "Would you like to combine jewels and Etel Dust?";
|
||||
close2;
|
||||
callshop "EnchantGradeExchange";
|
||||
end;
|
||||
case 3:
|
||||
mes "[Suribell]";
|
||||
mes "Occasionally, unstable jewels with a lot of pure magical power are found.";
|
||||
mes "I decided to call such gems etheric gems.";
|
||||
mes "Who? I am Suribell!";
|
||||
next;
|
||||
mes "[Suribell]";
|
||||
mes "The magical power of etheric gems sometimes awakens the hidden potential of equipment.";
|
||||
mes "We call it grade enhancement because it goes up one tier!";
|
||||
next;
|
||||
mes "[Suribell]";
|
||||
mes "The adventurer may have a potential that is unknown to him.";
|
||||
mes "There is a risk that it can be destroyed if done wrong, but try it with faith!";
|
||||
close;
|
||||
}
|
||||
|
||||
OnInit:
|
||||
setunittitle(getnpcid(0), "<Grade Enhancer>");
|
||||
end;
|
||||
}
|
||||
|
||||
// = Portals
|
||||
//============================================================
|
||||
prontera,50,293,0 warp Grademk_Int 1,1,grademk,13,172
|
||||
grademk,9,172,0 warp Grademk_Out 1,1,prontera,50,290
|
||||
paramk,8,171,0 warp grade_in 1,1,paramk,141,64
|
||||
paramk,145,64,0 warp grade_out 1,1,paramk,11,171
|
@ -125,7 +125,7 @@ morocc,154,55,6 shop Jeweler#moc3 99,730:-1,2613:-1
|
||||
morocc,171,103,4 shop Item Collector#moc3 85,911:-1,528:-1,919:-1,925:-1
|
||||
morocc,205,247,2 shop Item Collector#moc4 85,911:-1,528:-1,919:-1,925:-1
|
||||
morocc,140,90,6 shop Trader#moc6 99,513:-1,513:-1,513:-1,513:-1,513:-1,513:-1
|
||||
morocc,166,54,2 shop Jeweler#moc4 102,721:-1,723:-1,726:-1,728:-1,729:-1
|
||||
morocc,166,54,2 shop Jeweler#moc4 102,721:-1,723:-1,726:-1,728:-1,729:-1,1000321:-1
|
||||
morocc,34,68,0 shop Trader#moc7 93,748:-1
|
||||
morocc,269,193,4 shop Trader#moc8 89,2609:-1,1516:-1,1522:-1
|
||||
morocc,256,191,5 shop Trader#moc9 93,2612:-1
|
||||
|
@ -126,6 +126,7 @@ npc: npc/re/merchants/enchan_mal.txt
|
||||
npc: npc/re/merchants/enchan_mora.txt
|
||||
npc: npc/re/merchants/enchan_rockridge.txt
|
||||
npc: npc/re/merchants/enchan_verus.txt
|
||||
npc: npc/re/merchants/enchantgrade.txt
|
||||
npc: npc/re/merchants/Extended_Ammunition.txt
|
||||
npc: npc/re/merchants/Extended_Stylist.txt
|
||||
npc: npc/re/merchants/flute.txt
|
||||
|
@ -169,12 +169,15 @@ CREATE TABLE IF NOT EXISTS `npclog` (
|
||||
# Private Airs(H)ip
|
||||
# Barter Shop (J)
|
||||
# Laphine systems (W)
|
||||
# Enchantgrade UI (0)
|
||||
# Reform UI (1)
|
||||
# Enchant UI (2)
|
||||
|
||||
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','W') 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','0','1','2') 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',
|
||||
@ -224,13 +227,15 @@ CREATE TABLE IF NOT EXISTS `picklog` (
|
||||
# Ban(K) Transactions
|
||||
# Barter Shop (J)
|
||||
# (X) Other
|
||||
# Enchantgrade UI (0)
|
||||
# Enchant UI (2)
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `zenylog` (
|
||||
`id` int(11) NOT NULL auto_increment,
|
||||
`time` datetime NOT NULL,
|
||||
`char_id` int(11) NOT NULL default '0',
|
||||
`src_id` int(11) NOT NULL default '0',
|
||||
`type` enum('T','V','P','M','S','N','D','C','A','E','I','B','K','J','X') NOT NULL default 'S',
|
||||
`type` enum('T','V','P','M','S','N','D','C','A','E','I','B','K','J','X','0','2') NOT NULL default 'S',
|
||||
`amount` int(11) NOT NULL default '0',
|
||||
`map` varchar(11) NOT NULL default '',
|
||||
PRIMARY KEY (`id`),
|
||||
|
7
sql-files/upgrades/upgrade_20220607_logs.sql
Normal file
7
sql-files/upgrades/upgrade_20220607_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','W','0','1','2') NOT NULL default 'P'
|
||||
;
|
||||
|
||||
ALTER TABLE `zenylog`
|
||||
MODIFY `type` enum('T','V','P','M','S','N','D','C','A','E','I','B','K','J','X','0','2') NOT NULL default 'S'
|
||||
;
|
@ -111,12 +111,22 @@ typedef uint32 t_itemid;
|
||||
#define MAX_BARTER_REQUIREMENTS 5
|
||||
#endif
|
||||
|
||||
enum e_enchantgrade : uint16{
|
||||
ENCHANTGRADE_NONE = 0,
|
||||
ENCHANTGRADE_D,
|
||||
ENCHANTGRADE_C,
|
||||
ENCHANTGRADE_B,
|
||||
ENCHANTGRADE_A
|
||||
};
|
||||
|
||||
#ifdef RENEWAL
|
||||
#define MAX_WEAPON_LEVEL 5
|
||||
#define MAX_ARMOR_LEVEL 2
|
||||
#define MAX_ENCHANTGRADE ENCHANTGRADE_A
|
||||
#else
|
||||
#define MAX_WEAPON_LEVEL 4
|
||||
#define MAX_ARMOR_LEVEL 1
|
||||
#define MAX_ENCHANTGRADE ENCHANTGRADE_NONE
|
||||
#endif
|
||||
|
||||
// for produce
|
||||
|
@ -10662,7 +10662,7 @@ ACMD_FUNC( stylist ){
|
||||
return -1;
|
||||
}
|
||||
|
||||
clif_ui_open( sd, OUT_UI_STYLIST, 0 );
|
||||
clif_ui_open( *sd, OUT_UI_STYLIST, 0 );
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
@ -10697,6 +10697,23 @@ ACMD_FUNC(addfame)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens the enchantgrade UI
|
||||
* Usage: @enchantgradeui
|
||||
*/
|
||||
ACMD_FUNC( enchantgradeui ){
|
||||
nullpo_retr( -1, sd );
|
||||
|
||||
#if !( PACKETVER_MAIN_NUM >= 20200916 || PACKETVER_RE_NUM >= 20200724 )
|
||||
sprintf( atcmd_output, msg_txt( sd, 798 ), "2020-07-24" ); // This command requires packet version %s or newer.
|
||||
clif_displaymessage( fd, atcmd_output );
|
||||
return -1;
|
||||
#else
|
||||
clif_ui_open( *sd, OUT_UI_ENCHANTGRADE, 0 );
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
#include "../custom/atcommand.inc"
|
||||
|
||||
/**
|
||||
@ -11019,6 +11036,7 @@ void atcommand_basecommands(void) {
|
||||
ACMD_DEF(refineui),
|
||||
ACMD_DEFR(stylist, ATCMD_NOCONSOLE|ATCMD_NOAUTOTRADE),
|
||||
ACMD_DEF(addfame),
|
||||
ACMD_DEFR(enchantgradeui, ATCMD_NOCONSOLE|ATCMD_NOAUTOTRADE),
|
||||
};
|
||||
AtCommandInfo* atcommand;
|
||||
int i;
|
||||
|
363
src/map/clif.cpp
363
src/map/clif.cpp
@ -21551,23 +21551,32 @@ void clif_parse_changedress( int fd, struct map_session_data* sd ){
|
||||
|
||||
/// Opens an UI window of the given type and initializes it with the given data
|
||||
/// 0AE2 <type>.B <data>.L
|
||||
void clif_ui_open( struct map_session_data *sd, enum out_ui_type ui_type, int32 data ){
|
||||
nullpo_retv(sd);
|
||||
|
||||
void clif_ui_open( struct map_session_data& sd, enum out_ui_type ui_type, int32 data ){
|
||||
#if PACKETVER >= 20151202
|
||||
// If the UI requires state tracking
|
||||
switch( ui_type ){
|
||||
case OUT_UI_STYLIST:
|
||||
sd->state.stylist_open = true;
|
||||
sd.state.stylist_open = true;
|
||||
break;
|
||||
case OUT_UI_ENCHANTGRADE:
|
||||
#if PACKETVER_MAIN_NUM >= 20200916 || PACKETVER_RE_NUM >= 20200724
|
||||
sd.state.enchantgrade_open = true;
|
||||
break;
|
||||
#else
|
||||
return;
|
||||
#endif
|
||||
}
|
||||
|
||||
int fd = sd->fd;
|
||||
struct PACKET_ZC_UI_OPEN p = {};
|
||||
|
||||
WFIFOHEAD(fd,packet_len(0xae2));
|
||||
WFIFOW(fd,0) = 0xae2;
|
||||
WFIFOB(fd,2) = ui_type;
|
||||
WFIFOL(fd,3) = data;
|
||||
WFIFOSET(fd,packet_len(0xae2));
|
||||
p.PacketType = HEADER_ZC_UI_OPEN;
|
||||
p.UIType = ui_type;
|
||||
#if PACKETVER >= 20171122
|
||||
p.data = data;
|
||||
#endif
|
||||
|
||||
clif_send( &p, sizeof( p ), &sd.bl, SELF );
|
||||
#endif
|
||||
}
|
||||
|
||||
/// Request to open an UI window of the given type
|
||||
@ -21578,7 +21587,7 @@ void clif_parse_open_ui( int fd, struct map_session_data* sd ){
|
||||
if( !pc_has_permission( sd, PC_PERM_ATTENDANCE ) ){
|
||||
clif_messagecolor( &sd->bl, color_table[COLOR_RED], msg_txt( sd, 791 ), false, SELF ); // You are not allowed to use the attendance system.
|
||||
}else if( pc_attendance_enabled() ){
|
||||
clif_ui_open( sd, OUT_UI_ATTENDANCE, pc_attendance_counter( sd ) );
|
||||
clif_ui_open( *sd, OUT_UI_ATTENDANCE, pc_attendance_counter( sd ) );
|
||||
}else{
|
||||
clif_msg_color( sd, MSG_ATTENDANCE_DISABLED, color_table[COLOR_RED] );
|
||||
}
|
||||
@ -23454,6 +23463,338 @@ void clif_parse_laphine_upgrade( int fd, struct map_session_data* sd ){
|
||||
#endif
|
||||
}
|
||||
|
||||
void clif_enchantgrade_add( struct map_session_data& sd, uint16 index = UINT16_MAX, std::shared_ptr<s_enchantgradelevel> gradeLevel = nullptr ){
|
||||
#if PACKETVER_MAIN_NUM >= 20200916 || PACKETVER_RE_NUM >= 20200724
|
||||
struct PACKET_ZC_GRADE_ENCHANT_MATERIAL_LIST* p = (struct PACKET_ZC_GRADE_ENCHANT_MATERIAL_LIST*)packet_buffer;
|
||||
|
||||
p->PacketType = HEADER_ZC_GRADE_ENCHANT_MATERIAL_LIST;
|
||||
p->PacketLength = sizeof( struct PACKET_ZC_GRADE_ENCHANT_MATERIAL_LIST );
|
||||
|
||||
if( index < UINT16_MAX ){
|
||||
p->index = client_index( index );
|
||||
if( sd.inventory.u.items_inventory[index].refine >= gradeLevel->refine ){
|
||||
p->success_chance = gradeLevel->chance / 100;
|
||||
}else{
|
||||
p->success_chance = 0;
|
||||
}
|
||||
p->blessing_info.id = client_nameid( gradeLevel->catalyst.item );
|
||||
p->blessing_info.amount = gradeLevel->catalyst.amountPerStep;
|
||||
p->blessing_info.max_blessing = gradeLevel->catalyst.maximumSteps;
|
||||
p->blessing_info.bonus = gradeLevel->catalyst.chanceIncrease / 100;
|
||||
// Not displayed by client
|
||||
p->protect_itemid = 0;
|
||||
p->protect_amount = 0;
|
||||
|
||||
int i = 0;
|
||||
for( const auto& pair : gradeLevel->options ){
|
||||
std::shared_ptr<s_enchantgradeoption> option = pair.second;
|
||||
|
||||
p->material_info[i].nameid = client_nameid( option->item );
|
||||
p->material_info[i].amount = option->amount;
|
||||
p->material_info[i].price = option->zeny;
|
||||
p->material_info[i].downgrade = option->downgrade_amount > 0;
|
||||
p->material_info[i].breakable = option->breaking_rate > 0;
|
||||
|
||||
p->PacketLength += sizeof( struct GRADE_ENCHANT_MATERIAL );
|
||||
i++;
|
||||
}
|
||||
}else{
|
||||
p->index = -1;
|
||||
p->success_chance = 0;
|
||||
p->blessing_info.id = 0;
|
||||
p->blessing_info.amount = 0;
|
||||
p->blessing_info.max_blessing = 0;
|
||||
p->blessing_info.bonus = 0;
|
||||
p->protect_itemid = 0;
|
||||
p->protect_amount = 0;
|
||||
}
|
||||
|
||||
clif_send( p, p->PacketLength, &sd.bl, SELF );
|
||||
#endif
|
||||
}
|
||||
|
||||
void clif_parse_enchantgrade_add( int fd, struct map_session_data* sd ){
|
||||
#if PACKETVER_MAIN_NUM >= 20200916 || PACKETVER_RE_NUM >= 20200724
|
||||
nullpo_retv( sd );
|
||||
|
||||
if( !sd->state.enchantgrade_open ){
|
||||
return;
|
||||
}
|
||||
|
||||
struct PACKET_CZ_GRADE_ENCHANT_SELECT_EQUIPMENT* p = (struct PACKET_CZ_GRADE_ENCHANT_SELECT_EQUIPMENT*)RFIFOP( fd, 0 );
|
||||
|
||||
uint16 index = server_index( p->index );
|
||||
|
||||
if( index >= MAX_INVENTORY || sd->inventory_data[index] == nullptr ){
|
||||
return;
|
||||
}
|
||||
|
||||
std::shared_ptr<s_enchantgrade> enchantgrade = enchantgrade_db.find( sd->inventory_data[index]->type );
|
||||
|
||||
// Unsupported item type - no answer, because client should have actually prevented this request
|
||||
if( enchantgrade == nullptr ){
|
||||
return;
|
||||
}
|
||||
|
||||
uint16 level = 0;
|
||||
|
||||
if( sd->inventory_data[index]->type == IT_WEAPON ){
|
||||
level = sd->inventory_data[index]->weapon_level;
|
||||
}else if( sd->inventory_data[index]->type == IT_ARMOR ){
|
||||
level = sd->inventory_data[index]->armor_level;
|
||||
}
|
||||
|
||||
const auto& enchantgradelevels = enchantgrade->levels.find( level );
|
||||
|
||||
// Cannot upgrade this weapon or armor level
|
||||
if( enchantgradelevels == enchantgrade->levels.end() ){
|
||||
clif_enchantgrade_add( *sd );
|
||||
return;
|
||||
}
|
||||
|
||||
std::shared_ptr<s_enchantgradelevel> enchantgradelevel = util::map_find( enchantgradelevels->second, (e_enchantgrade)sd->inventory.u.items_inventory[index].enchantgrade );
|
||||
|
||||
// Cannot increase enchantgrade any further - no answer, because client should have actually prevented this request
|
||||
if( enchantgradelevel == nullptr ){
|
||||
return;
|
||||
}
|
||||
|
||||
clif_enchantgrade_add( *sd, index, enchantgradelevel );
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sends the result for trying to enchant an item
|
||||
/// </summary>
|
||||
/// <param name="sd">The player session</param>
|
||||
/// <param name="index">The target item</param>
|
||||
/// <param name="result">
|
||||
/// 0= The grade has been successfully upgraded.
|
||||
/// 1= Refinement failed.
|
||||
/// 2= The refine level has decreased.
|
||||
/// 3= Equipment destroyed.
|
||||
/// 4= The equipment is protected.
|
||||
/// </param>
|
||||
void clif_enchantgrade_result( struct map_session_data& sd, uint16 index, e_enchantgrade_result result ){
|
||||
#if PACKETVER_MAIN_NUM >= 20200916 || PACKETVER_RE_NUM >= 20200724
|
||||
struct PACKET_ZC_GRADE_ENCHANT_ACK p = {};
|
||||
|
||||
p.PacketType = HEADER_ZC_GRADE_ENCHANT_ACK;
|
||||
p.index = client_index( index );
|
||||
p.enchantgrade = sd.inventory.u.items_inventory[index].enchantgrade;
|
||||
p.result = result;
|
||||
|
||||
clif_send( &p, sizeof( p ), &sd.bl, SELF );
|
||||
#endif
|
||||
}
|
||||
|
||||
void clif_enchantgrade_announce( struct map_session_data& sd, struct item& item, bool success ){
|
||||
#if PACKETVER_MAIN_NUM >= 20200916 || PACKETVER_RE_NUM >= 20200724
|
||||
struct PACKET_ZC_GRADE_ENCHANT_BROADCAST_RESULT p = {};
|
||||
|
||||
p.packetType = HEADER_ZC_GRADE_ENCHANT_BROADCAST_RESULT;
|
||||
safestrncpy( p.name, sd.status.name, sizeof( p.name ) );
|
||||
p.itemId = client_nameid( item.nameid );
|
||||
p.enchantgrade = item.enchantgrade;
|
||||
p.status = success;
|
||||
|
||||
clif_send( &p, sizeof( p ), nullptr, ALL_CLIENT );
|
||||
#endif
|
||||
}
|
||||
|
||||
void clif_parse_enchantgrade_start( int fd, struct map_session_data* sd ){
|
||||
#if PACKETVER_MAIN_NUM >= 20200916 || PACKETVER_RE_NUM >= 20200724
|
||||
nullpo_retv( sd );
|
||||
|
||||
if( !sd->state.enchantgrade_open ){
|
||||
return;
|
||||
}
|
||||
|
||||
struct PACKET_CZ_GRADE_ENCHANT_REQUEST* p = (struct PACKET_CZ_GRADE_ENCHANT_REQUEST*)RFIFOP( fd, 0 );
|
||||
|
||||
uint16 index = server_index( p->index );
|
||||
|
||||
if( index >= MAX_INVENTORY || sd->inventory_data[index] == nullptr ){
|
||||
return;
|
||||
}
|
||||
|
||||
std::shared_ptr<s_enchantgrade> enchantgrade = enchantgrade_db.find( sd->inventory_data[index]->type );
|
||||
|
||||
// Unsupported item type - no answer
|
||||
if( enchantgrade == nullptr ){
|
||||
return;
|
||||
}
|
||||
|
||||
uint16 level = 0;
|
||||
|
||||
if( sd->inventory_data[index]->type == IT_WEAPON ){
|
||||
level = sd->inventory_data[index]->weapon_level;
|
||||
}else if( sd->inventory_data[index]->type == IT_ARMOR ){
|
||||
level = sd->inventory_data[index]->armor_level;
|
||||
}
|
||||
|
||||
const auto& enchantgradelevels = enchantgrade->levels.find( level );
|
||||
|
||||
// Cannot upgrade this weapon or armor level - no answer
|
||||
if( enchantgradelevels == enchantgrade->levels.end() ){
|
||||
return;
|
||||
}
|
||||
|
||||
std::shared_ptr<s_enchantgradelevel> enchantgradelevel = util::map_find( enchantgradelevels->second, (e_enchantgrade)sd->inventory.u.items_inventory[index].enchantgrade );
|
||||
|
||||
// Cannot increase enchantgrade any further - no answer
|
||||
if( enchantgradelevel == nullptr ){
|
||||
return;
|
||||
}
|
||||
|
||||
// Not refined enough
|
||||
if( sd->inventory.u.items_inventory[index].refine < enchantgradelevel->refine ){
|
||||
return;
|
||||
}
|
||||
|
||||
std::shared_ptr<s_enchantgradeoption> option = util::map_find( enchantgradelevel->options, (uint16)p->material_index );
|
||||
|
||||
// Unknown option id - no answer
|
||||
if( option == nullptr ){
|
||||
return;
|
||||
}
|
||||
|
||||
// Not enough zeny
|
||||
if( sd->status.zeny < option->zeny ){
|
||||
return;
|
||||
}
|
||||
|
||||
uint16 totalChance = enchantgradelevel->chance;
|
||||
uint16 steps = min( p->blessing_amount, enchantgradelevel->catalyst.maximumSteps );
|
||||
std::unordered_map<uint16, uint16> requiredItems;
|
||||
|
||||
if( p->blessing_flag ){
|
||||
// If the catalysator item is the same as the option item build the sum of amounts
|
||||
if( enchantgradelevel->catalyst.item == option->item ){
|
||||
uint16 amount = enchantgradelevel->catalyst.amountPerStep * steps + option->amount;
|
||||
|
||||
int16 index = pc_search_inventory( sd, enchantgradelevel->catalyst.item );
|
||||
|
||||
if( index < 0 ){
|
||||
return;
|
||||
}
|
||||
|
||||
if( sd->inventory.u.items_inventory[index].amount < amount ){
|
||||
return;
|
||||
}
|
||||
|
||||
requiredItems[index] = amount;
|
||||
}else{
|
||||
uint16 amount = enchantgradelevel->catalyst.amountPerStep * steps;
|
||||
|
||||
// Check catalysator item
|
||||
int16 index = pc_search_inventory( sd, enchantgradelevel->catalyst.item );
|
||||
|
||||
if( index < 0 ){
|
||||
return;
|
||||
}
|
||||
|
||||
if( sd->inventory.u.items_inventory[index].amount < amount ){
|
||||
return;
|
||||
}
|
||||
|
||||
requiredItems[index] = amount;
|
||||
|
||||
// Check option item
|
||||
index = pc_search_inventory( sd, option->item );
|
||||
|
||||
if( index < 0 ){
|
||||
return;
|
||||
}
|
||||
|
||||
if( sd->inventory.u.items_inventory[index].amount < option->amount ){
|
||||
return;
|
||||
}
|
||||
|
||||
requiredItems[index] = option->amount;
|
||||
}
|
||||
|
||||
totalChance += steps * enchantgradelevel->catalyst.chanceIncrease;
|
||||
}else{
|
||||
// Check option item
|
||||
int16 index = pc_search_inventory( sd, option->item );
|
||||
|
||||
if( index < 0 ){
|
||||
return;
|
||||
}
|
||||
|
||||
if( sd->inventory.u.items_inventory[index].amount < option->amount ){
|
||||
return;
|
||||
}
|
||||
|
||||
requiredItems[index] = option->amount;
|
||||
}
|
||||
|
||||
// All items should be there, start deleting
|
||||
for( const auto& pair : requiredItems ){
|
||||
if( pc_delitem( sd, pair.first, pair.second, 0, 0, LOG_TYPE_ENCHANTGRADE ) != 0 ){
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if( pc_payzeny( sd, option->zeny, LOG_TYPE_ENCHANTGRADE, nullptr ) > 0 ){
|
||||
return;
|
||||
}
|
||||
|
||||
if( rnd()%10000 < totalChance ){
|
||||
// Log removal of item
|
||||
log_pick_pc( sd, LOG_TYPE_ENCHANTGRADE, -1, &sd->inventory.u.items_inventory[index] );
|
||||
// Increase enchantgrade
|
||||
sd->inventory.u.items_inventory[index].enchantgrade = min( sd->inventory.u.items_inventory[index].enchantgrade + 1, MAX_ENCHANTGRADE );
|
||||
// On successful enchantgrade increase the refine is reset
|
||||
sd->inventory.u.items_inventory[index].refine = 0;
|
||||
// Log retrieving the item again -> with the new refine and enchantgrade
|
||||
log_pick_pc( sd, LOG_TYPE_ENCHANTGRADE, 1, &sd->inventory.u.items_inventory[index] );
|
||||
// Show success
|
||||
clif_enchantgrade_result( *sd, index, ENCHANTGRADE_UPGRADE_SUCCESS );
|
||||
|
||||
// Check if it has to be announced
|
||||
if( enchantgradelevel->announce ){
|
||||
clif_enchantgrade_announce( *sd, sd->inventory.u.items_inventory[index], true );
|
||||
}
|
||||
}else{
|
||||
// Check if it has to be announced (has to be done before deleting the item from inventory)
|
||||
if( enchantgradelevel->announce ){
|
||||
clif_enchantgrade_announce( *sd, sd->inventory.u.items_inventory[index], false );
|
||||
}
|
||||
|
||||
// Delete the item if it is breakable
|
||||
if( option->breaking_rate > 0 && ( rnd() % 10000 ) < option->breaking_rate ){
|
||||
// Delete the item
|
||||
pc_delitem( sd, index, 1, 0, 0, LOG_TYPE_ENCHANTGRADE );
|
||||
// Show failure
|
||||
clif_enchantgrade_result( *sd, index, ENCHANTGRADE_UPGRADE_BREAK );
|
||||
// Downgrade the item if necessary
|
||||
}else if( option->downgrade_amount > 0 ){
|
||||
// Log removal of item
|
||||
log_pick_pc( sd, LOG_TYPE_ENCHANTGRADE, -1, &sd->inventory.u.items_inventory[index] );
|
||||
// Decrease refine level
|
||||
sd->inventory.u.items_inventory[index].refine = cap_value( sd->inventory.u.items_inventory[index].refine - option->downgrade_amount, 0, MAX_REFINE );
|
||||
// Log retrieving the item again -> with the new refine
|
||||
log_pick_pc( sd, LOG_TYPE_ENCHANTGRADE, 1, &sd->inventory.u.items_inventory[index] );
|
||||
// Show downgrade
|
||||
clif_enchantgrade_result( *sd, index, ENCHANTGRADE_UPGRADE_DOWNGRADE );
|
||||
// Only show failure, but dont do anything
|
||||
}else{
|
||||
clif_enchantgrade_result( *sd, index, ENCHANTGRADE_UPGRADE_FAILED );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void clif_parse_enchantgrade_close( int fd, struct map_session_data* sd ){
|
||||
#if PACKETVER_MAIN_NUM >= 20200916 || PACKETVER_RE_NUM >= 20200724
|
||||
nullpo_retv( sd );
|
||||
|
||||
sd->state.enchantgrade_open = false;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*==========================================
|
||||
* Main client packet processing function
|
||||
*------------------------------------------*/
|
||||
|
@ -1162,10 +1162,11 @@ enum out_ui_type : int8 {
|
||||
OUT_UI_BANK = 0,
|
||||
OUT_UI_STYLIST,
|
||||
OUT_UI_QUEST = 6,
|
||||
OUT_UI_ATTENDANCE = 7
|
||||
OUT_UI_ATTENDANCE,
|
||||
OUT_UI_ENCHANTGRADE,
|
||||
};
|
||||
|
||||
void clif_ui_open( struct map_session_data *sd, enum out_ui_type ui_type, int32 data );
|
||||
void clif_ui_open( struct map_session_data& sd, enum out_ui_type ui_type, int32 data );
|
||||
void clif_attendence_response( struct map_session_data *sd, int32 data );
|
||||
|
||||
void clif_weight_limit( struct map_session_data* sd );
|
||||
|
@ -2375,7 +2375,6 @@
|
||||
// 2018-03-07bRagexeRE
|
||||
#if PACKETVER >= 20180307
|
||||
parseable_packet(0x0A68,3,clif_parse_open_ui,2);
|
||||
packet(0x0AE2,7);
|
||||
parseable_packet(0x0AEF,2,clif_parse_attendance_request,0);
|
||||
packet(0x0AF0,10);
|
||||
#endif
|
||||
@ -2447,6 +2446,9 @@
|
||||
|
||||
#if PACKETVER_MAIN_NUM >= 20200916 || PACKETVER_RE_NUM >= 20200724
|
||||
parseable_packet( HEADER_CZ_UNCONFIRMED_TSTATUS_UP, sizeof( PACKET_CZ_UNCONFIRMED_TSTATUS_UP ), clif_parse_traitstatus_up, 0 );
|
||||
parseable_packet( HEADER_CZ_GRADE_ENCHANT_SELECT_EQUIPMENT, sizeof( struct PACKET_CZ_GRADE_ENCHANT_SELECT_EQUIPMENT ), clif_parse_enchantgrade_add, 0 );
|
||||
parseable_packet( HEADER_CZ_GRADE_ENCHANT_REQUEST, sizeof( struct PACKET_CZ_GRADE_ENCHANT_REQUEST ), clif_parse_enchantgrade_start, 0 );
|
||||
parseable_packet( HEADER_CZ_GRADE_ENCHANT_CLOSE_UI, sizeof( struct PACKET_CZ_GRADE_ENCHANT_CLOSE_UI ), clif_parse_enchantgrade_close, 0 );
|
||||
#endif
|
||||
|
||||
#if PACKETVER_RE_NUM >= 20211103 || PACKETVER_ZERO_NUM >= 20210818
|
||||
|
@ -86,7 +86,10 @@ 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
|
||||
case LOG_TYPE_LAPHINE: return 'W'; // Laphine UI
|
||||
case LOG_TYPE_ENCHANTGRADE: return '0'; // Enchantgrade UI
|
||||
case LOG_TYPE_REFORM: return '1'; // Reform UI
|
||||
case LOG_TYPE_ENCHANT: return '2'; // Echant UI
|
||||
}
|
||||
|
||||
// should not get here, fallback
|
||||
|
@ -26,37 +26,40 @@ enum e_log_chat_type : uint8
|
||||
|
||||
enum e_log_pick_type : uint32
|
||||
{
|
||||
LOG_TYPE_NONE = 0x0000000,
|
||||
LOG_TYPE_TRADE = 0x0000001,
|
||||
LOG_TYPE_VENDING = 0x0000002,
|
||||
LOG_TYPE_PICKDROP_PLAYER = 0x0000004,
|
||||
LOG_TYPE_PICKDROP_MONSTER = 0x0000008,
|
||||
LOG_TYPE_NPC = 0x0000010,
|
||||
LOG_TYPE_SCRIPT = 0x0000020,
|
||||
LOG_TYPE_STEAL = 0x0000040,
|
||||
LOG_TYPE_CONSUME = 0x0000080,
|
||||
LOG_TYPE_PRODUCE = 0x0000100,
|
||||
LOG_TYPE_MVP = 0x0000200,
|
||||
LOG_TYPE_COMMAND = 0x0000400,
|
||||
LOG_TYPE_STORAGE = 0x0000800,
|
||||
LOG_TYPE_GSTORAGE = 0x0001000,
|
||||
LOG_TYPE_MAIL = 0x0002000,
|
||||
LOG_TYPE_AUCTION = 0x0004000,
|
||||
LOG_TYPE_BUYING_STORE = 0x0008000,
|
||||
LOG_TYPE_OTHER = 0x0010000,
|
||||
LOG_TYPE_CASH = 0x0020000,
|
||||
LOG_TYPE_BANK = 0x0040000,
|
||||
LOG_TYPE_BOUND_REMOVAL = 0x0080000,
|
||||
LOG_TYPE_ROULETTE = 0x0100000,
|
||||
LOG_TYPE_MERGE_ITEM = 0x0200000,
|
||||
LOG_TYPE_QUEST = 0x0400000,
|
||||
LOG_TYPE_PRIVATE_AIRSHIP = 0x0800000,
|
||||
LOG_TYPE_BARTER = 0x1000000,
|
||||
LOG_TYPE_LAPHINE = 0x2000000,
|
||||
LOG_TYPE_NONE = 0x00000000,
|
||||
LOG_TYPE_TRADE = 0x00000001,
|
||||
LOG_TYPE_VENDING = 0x00000002,
|
||||
LOG_TYPE_PICKDROP_PLAYER = 0x00000004,
|
||||
LOG_TYPE_PICKDROP_MONSTER = 0x00000008,
|
||||
LOG_TYPE_NPC = 0x00000010,
|
||||
LOG_TYPE_SCRIPT = 0x00000020,
|
||||
LOG_TYPE_STEAL = 0x00000040,
|
||||
LOG_TYPE_CONSUME = 0x00000080,
|
||||
LOG_TYPE_PRODUCE = 0x00000100,
|
||||
LOG_TYPE_MVP = 0x00000200,
|
||||
LOG_TYPE_COMMAND = 0x00000400,
|
||||
LOG_TYPE_STORAGE = 0x00000800,
|
||||
LOG_TYPE_GSTORAGE = 0x00001000,
|
||||
LOG_TYPE_MAIL = 0x00002000,
|
||||
LOG_TYPE_AUCTION = 0x00004000,
|
||||
LOG_TYPE_BUYING_STORE = 0x00008000,
|
||||
LOG_TYPE_OTHER = 0x00010000,
|
||||
LOG_TYPE_CASH = 0x00020000,
|
||||
LOG_TYPE_BANK = 0x00040000,
|
||||
LOG_TYPE_BOUND_REMOVAL = 0x00080000,
|
||||
LOG_TYPE_ROULETTE = 0x00100000,
|
||||
LOG_TYPE_MERGE_ITEM = 0x00200000,
|
||||
LOG_TYPE_QUEST = 0x00400000,
|
||||
LOG_TYPE_PRIVATE_AIRSHIP = 0x00800000,
|
||||
LOG_TYPE_BARTER = 0x01000000,
|
||||
LOG_TYPE_LAPHINE = 0x02000000,
|
||||
LOG_TYPE_ENCHANTGRADE = 0x04000000,
|
||||
LOG_TYPE_REFORM = 0x08000000,
|
||||
LOG_TYPE_ENCHANT = 0x10000000,
|
||||
// combinations
|
||||
LOG_TYPE_LOOT = LOG_TYPE_PICKDROP_MONSTER|LOG_TYPE_CONSUME,
|
||||
// all
|
||||
LOG_TYPE_ALL = 0xFFFFFFF,
|
||||
LOG_TYPE_ALL = 0xFFFFFFFF,
|
||||
};
|
||||
|
||||
enum e_log_cash_type : uint8
|
||||
|
@ -322,6 +322,7 @@
|
||||
<Copy SourceFiles="$(SolutionDir)db\import-tmpl\const.yml" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\const.yml')" />
|
||||
<Copy SourceFiles="$(SolutionDir)db\import-tmpl\create_arrow_db.yml" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\create_arrow_db.yml')" />
|
||||
<Copy SourceFiles="$(SolutionDir)db\import-tmpl\elemental_db.yml" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\elemental_db.yml')" />
|
||||
<Copy SourceFiles="$(SolutionDir)db\import-tmpl\enchantgrade.yml" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\enchantgrade.yml')" />
|
||||
<Copy SourceFiles="$(SolutionDir)db\import-tmpl\exp_homun.yml" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\exp_homun.yml')" />
|
||||
<Copy SourceFiles="$(SolutionDir)db\import-tmpl\exp_guild.yml" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\exp_guild.yml')" />
|
||||
<Copy SourceFiles="$(SolutionDir)db\import-tmpl\guild_skill_tree.yml" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\guild_skill_tree.yml')" />
|
||||
|
@ -5340,7 +5340,7 @@ DEFINE_PACKET_HEADER(CZ_GRADE_ENCHANT_CLOSE_UI, 0x0b5c);
|
||||
struct PACKET_ZC_GRADE_ENCHANT_ACK {
|
||||
int16 PacketType;
|
||||
int16 index;
|
||||
int16 grade;
|
||||
int16 enchantgrade;
|
||||
int result;
|
||||
} __attribute__((packed));
|
||||
DEFINE_PACKET_HEADER(ZC_GRADE_ENCHANT_ACK, 0x0b5d);
|
||||
@ -5351,7 +5351,7 @@ struct PACKET_ZC_GRADE_ENCHANT_BROADCAST_RESULT {
|
||||
int16 packetType;
|
||||
char name[NAME_LENGTH];
|
||||
uint32 itemId;
|
||||
int16 grade;
|
||||
int16 enchantgrade;
|
||||
int8 status;
|
||||
} __attribute__((packed));
|
||||
DEFINE_PACKET_HEADER(ZC_GRADE_ENCHANT_BROADCAST_RESULT, 0x0b5e);
|
||||
|
@ -13995,7 +13995,7 @@ void pc_scdata_received(struct map_session_data *sd) {
|
||||
clif_weight_limit( sd );
|
||||
|
||||
if( pc_has_permission( sd, PC_PERM_ATTENDANCE ) && pc_attendance_enabled() && !pc_attendance_rewarded_today( sd ) ){
|
||||
clif_ui_open( sd, OUT_UI_ATTENDANCE, pc_attendance_counter( sd ) );
|
||||
clif_ui_open( *sd, OUT_UI_ATTENDANCE, pc_attendance_counter( sd ) );
|
||||
}
|
||||
|
||||
sd->state.pc_loaded = true;
|
||||
|
@ -387,6 +387,7 @@ struct map_session_data {
|
||||
bool stylist_open;
|
||||
bool barter_open;
|
||||
bool barter_extended_open;
|
||||
bool enchantgrade_open; // Whether the enchantgrade window is open or not
|
||||
unsigned int block_action : 10;
|
||||
bool refineui_open;
|
||||
t_itemid inventory_expansion_confirmation;
|
||||
@ -1067,7 +1068,7 @@ static bool pc_cant_act2( struct map_session_data* sd ){
|
||||
|| sd->state.stylist_open || sd->state.inventory_expansion_confirmation || sd->npc_shopid
|
||||
|| sd->state.barter_open || sd->state.barter_extended_open
|
||||
|| sd->state.laphine_synthesis || sd->state.laphine_upgrade
|
||||
|| sd->state.roulette_open;
|
||||
|| sd->state.roulette_open || sd->state.enchantgrade_open;
|
||||
}
|
||||
// equals pc_cant_act2 and additionally checks for chat rooms and npcs
|
||||
static bool pc_cant_act( struct map_session_data* sd ){
|
||||
|
@ -25739,7 +25739,7 @@ BUILDIN_FUNC( openstylist ){
|
||||
return SCRIPT_CMD_FAILURE;
|
||||
}
|
||||
|
||||
clif_ui_open( sd, OUT_UI_STYLIST, 0 );
|
||||
clif_ui_open( *sd, OUT_UI_STYLIST, 0 );
|
||||
|
||||
return SCRIPT_CMD_SUCCESS;
|
||||
#else
|
||||
@ -25860,6 +25860,10 @@ BUILDIN_FUNC(randomoptgroup)
|
||||
}
|
||||
|
||||
BUILDIN_FUNC( open_quest_ui ){
|
||||
#if PACKETVER < 20151202
|
||||
ShowError( "buildin_open_quest_ui: This command requires PACKETVER 20151202 or newer.\n" );
|
||||
return SCRIPT_CMD_FAILURE;
|
||||
#else
|
||||
struct map_session_data* sd;
|
||||
|
||||
if (!script_charid2sd(3, sd))
|
||||
@ -25874,14 +25878,15 @@ BUILDIN_FUNC( open_quest_ui ){
|
||||
ShowWarning("buildin_open_quest_ui: Character %d doesn't have quest %d.\n", sd->status.char_id, quest_id);
|
||||
}
|
||||
|
||||
clif_ui_open( sd, OUT_UI_QUEST, quest_id );
|
||||
clif_ui_open( *sd, OUT_UI_QUEST, quest_id );
|
||||
|
||||
return SCRIPT_CMD_SUCCESS;
|
||||
#endif
|
||||
}
|
||||
|
||||
BUILDIN_FUNC(openbank){
|
||||
#if PACKETVER < 20150128
|
||||
ShowError( "buildin_openbank: This command requires PACKETVER 20150128 or newer.\n" );
|
||||
#if PACKETVER < 20151202
|
||||
ShowError( "buildin_openbank: This command requires PACKETVER 20151202 or newer.\n" );
|
||||
return SCRIPT_CMD_FAILURE;
|
||||
#else
|
||||
struct map_session_data* sd = nullptr;
|
||||
@ -25895,7 +25900,7 @@ BUILDIN_FUNC(openbank){
|
||||
return SCRIPT_CMD_FAILURE;
|
||||
}
|
||||
|
||||
clif_ui_open( sd, OUT_UI_BANK, 0 );
|
||||
clif_ui_open( *sd, OUT_UI_BANK, 0 );
|
||||
return SCRIPT_CMD_SUCCESS;
|
||||
#endif
|
||||
}
|
||||
@ -25994,6 +25999,23 @@ BUILDIN_FUNC(getjobexp_ratio){
|
||||
return SCRIPT_CMD_SUCCESS;
|
||||
}
|
||||
|
||||
BUILDIN_FUNC( enchantgradeui ){
|
||||
#if PACKETVER_MAIN_NUM >= 20200916 || PACKETVER_RE_NUM >= 20200724
|
||||
struct map_session_data* sd;
|
||||
|
||||
if( !script_charid2sd( 2, sd ) ){
|
||||
return SCRIPT_CMD_FAILURE;
|
||||
}
|
||||
|
||||
clif_ui_open( *sd, OUT_UI_ENCHANTGRADE, 0 );
|
||||
|
||||
return SCRIPT_CMD_SUCCESS;
|
||||
#else
|
||||
ShowError( "buildin_enchantgradeui: This command requires PACKETVER 2020-07-24 or newer.\n" );
|
||||
return SCRIPT_CMD_FAILURE;
|
||||
#endif
|
||||
}
|
||||
|
||||
#include "../custom/script.inc"
|
||||
|
||||
// declarations that were supposed to be exported from npc_chat.cpp
|
||||
@ -26713,6 +26735,8 @@ struct script_function buildin_func[] = {
|
||||
BUILDIN_DEF(openbank,"?"),
|
||||
BUILDIN_DEF(getbaseexp_ratio, "i??"),
|
||||
BUILDIN_DEF(getjobexp_ratio, "i??"),
|
||||
BUILDIN_DEF(enchantgradeui, "?" ),
|
||||
|
||||
#include "../custom/script_def.inc"
|
||||
|
||||
{NULL,NULL,NULL},
|
||||
|
@ -8996,6 +8996,14 @@
|
||||
export_constant(SCF_REMOVEONUNEQUIPWEAPON);
|
||||
export_constant(SCF_REMOVEONUNEQUIPARMOR);
|
||||
|
||||
/* enchantgrades */
|
||||
export_constant(ENCHANTGRADE_NONE);
|
||||
export_constant(ENCHANTGRADE_D);
|
||||
export_constant(ENCHANTGRADE_C);
|
||||
export_constant(ENCHANTGRADE_B);
|
||||
export_constant(ENCHANTGRADE_A);
|
||||
export_constant(MAX_ENCHANTGRADE);
|
||||
|
||||
#undef export_constant
|
||||
#undef export_constant2
|
||||
#undef export_parameter
|
||||
|
@ -544,6 +544,399 @@ uint64 SizeFixDatabase::parseBodyNode(const ryml::NodeRef& node) {
|
||||
|
||||
SizeFixDatabase size_fix_db;
|
||||
|
||||
const std::string EnchantgradeDatabase::getDefaultLocation(){
|
||||
return std::string(db_path) + "/enchantgrade.yml";
|
||||
}
|
||||
|
||||
uint64 EnchantgradeDatabase::parseBodyNode( const ryml::NodeRef& node ){
|
||||
if( !this->nodesExist( node, { "Type", "Levels" } ) ){
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::string itemtype_constant;
|
||||
|
||||
if( !this->asString( node, "Type", itemtype_constant ) ){
|
||||
return 0;
|
||||
}
|
||||
|
||||
int64 constant_value;
|
||||
|
||||
if( !script_get_constant( ( "IT_" + itemtype_constant ).c_str(), &constant_value ) ){
|
||||
this->invalidWarning( node["Type"], "Unknown item type \"%s\".\n", itemtype_constant.c_str() );
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint16 itemtype = static_cast<uint16>( constant_value );
|
||||
uint16 itemtype_maxlevel;
|
||||
|
||||
if( itemtype == IT_WEAPON ){
|
||||
itemtype_maxlevel = MAX_WEAPON_LEVEL;
|
||||
}else if( itemtype == IT_ARMOR ){
|
||||
itemtype_maxlevel = MAX_ARMOR_LEVEL;
|
||||
}else{
|
||||
this->invalidWarning( node["Type"], "Item type \"%s\" is not supported.\n", itemtype_constant.c_str() );
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::shared_ptr<s_enchantgrade> enchantgrade = this->find( itemtype );
|
||||
bool exists = enchantgrade != nullptr;
|
||||
|
||||
if( !exists ){
|
||||
enchantgrade = std::make_shared<s_enchantgrade>();
|
||||
enchantgrade->itemtype = itemtype;
|
||||
}
|
||||
|
||||
for( const ryml::NodeRef& levelNode : node["Levels"] ){
|
||||
if( !this->nodesExist( levelNode, { "Level", "Grades" } ) ){
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint16 level;
|
||||
|
||||
if( !this->asUInt16( levelNode, "Level", level ) ){
|
||||
return 0;
|
||||
}
|
||||
|
||||
if( level == 0 || level > itemtype_maxlevel ){
|
||||
this->invalidWarning( levelNode["Level"], "Level %hu is invalid for item type %s[1~%hu].\n", level, itemtype_constant.c_str(), itemtype_maxlevel );
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::map<e_enchantgrade, std::shared_ptr<s_enchantgradelevel>>& grades = enchantgrade->levels[level];
|
||||
|
||||
for( const ryml::NodeRef& gradeNode : levelNode["Grades"] ){
|
||||
std::string gradeConstant;
|
||||
|
||||
if( !this->asString( gradeNode, "Grade", gradeConstant ) ){
|
||||
return 0;
|
||||
}
|
||||
|
||||
if( !script_get_constant( ( "ENCHANTGRADE_" + gradeConstant ).c_str(), &constant_value ) ){
|
||||
this->invalidWarning( node["Grade"], "Unknown grade \"%s\".\n", gradeConstant.c_str() );
|
||||
return 0;
|
||||
}
|
||||
|
||||
if( constant_value >= MAX_ENCHANTGRADE ){
|
||||
this->invalidWarning( gradeNode["Grade"], "Grade %" PRId64 " is too high. Maximum: %hu.\n", constant_value, MAX_ENCHANTGRADE - 1 );
|
||||
return 0;
|
||||
}
|
||||
|
||||
e_enchantgrade gradeLevel = (e_enchantgrade)constant_value;
|
||||
|
||||
std::shared_ptr<s_enchantgradelevel> grade = util::map_find( grades, gradeLevel );
|
||||
bool gradeExists = grade != nullptr;
|
||||
|
||||
if( !gradeExists ){
|
||||
grade = std::make_shared<s_enchantgradelevel>();
|
||||
grade->grade = gradeLevel;
|
||||
|
||||
if( !this->nodesExist( gradeNode, { "Refine", "Chance", "Options" } ) ){
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if( this->nodeExists( gradeNode, "Refine" ) ){
|
||||
uint16 refine;
|
||||
|
||||
if( !this->asUInt16( gradeNode, "Refine", refine ) ){
|
||||
return 0;
|
||||
}
|
||||
|
||||
if( refine > MAX_REFINE ){
|
||||
this->invalidWarning( gradeNode["Refine"], "Refine %hu is too high, capping to %hu...\n", refine, MAX_REFINE );
|
||||
refine = MAX_REFINE;
|
||||
}
|
||||
|
||||
grade->refine = refine;
|
||||
}
|
||||
|
||||
if( this->nodeExists( gradeNode, "Chance" ) ){
|
||||
uint16 chance;
|
||||
|
||||
if( !this->asUInt16Rate( gradeNode, "Chance", chance ) ){
|
||||
return 0;
|
||||
}
|
||||
|
||||
grade->chance = chance;
|
||||
}
|
||||
|
||||
if( this->nodeExists( gradeNode, "Bonus" ) ){
|
||||
uint16 bonus;
|
||||
|
||||
if( !this->asUInt16( gradeNode, "Bonus", bonus ) ){
|
||||
return 0;
|
||||
}
|
||||
|
||||
grade->bonus = bonus;
|
||||
}else{
|
||||
if( !gradeExists ){
|
||||
grade->bonus = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if( this->nodeExists( gradeNode, "Announce" ) ){
|
||||
bool announce;
|
||||
|
||||
if( !this->asBool( gradeNode, "Announce", announce ) ){
|
||||
return 0;
|
||||
}
|
||||
|
||||
grade->announce = announce;
|
||||
}else{
|
||||
if( !gradeExists ){
|
||||
grade->announce = true;
|
||||
}
|
||||
}
|
||||
|
||||
if( this->nodeExists( gradeNode, "Catalyst") ){
|
||||
const ryml::NodeRef& catalystNode = gradeNode["Catalyst"];
|
||||
|
||||
if( this->nodeExists( catalystNode, "Item" ) ){
|
||||
std::string itemName;
|
||||
|
||||
if( !this->asString( catalystNode, "Item", itemName ) ){
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::shared_ptr<item_data> id = item_db.search_aegisname( itemName.c_str() );
|
||||
|
||||
if( id == nullptr ){
|
||||
this->invalidWarning( catalystNode["Item"], "Unknown item \"%s\".\n", itemName.c_str() );
|
||||
return 0;
|
||||
}
|
||||
|
||||
grade->catalyst.item = id->nameid;
|
||||
}else{
|
||||
if( !gradeExists ){
|
||||
grade->catalyst.item = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if( this->nodeExists( catalystNode, "AmountPerStep" ) ){
|
||||
uint16 amountPerStep;
|
||||
|
||||
if( !this->asUInt16( catalystNode, "AmountPerStep", amountPerStep ) ){
|
||||
return 0;
|
||||
}
|
||||
|
||||
grade->catalyst.amountPerStep = amountPerStep;
|
||||
}else{
|
||||
if( !gradeExists ){
|
||||
grade->catalyst.amountPerStep = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if( this->nodeExists( catalystNode, "MaximumSteps" ) ){
|
||||
uint16 maximumSteps;
|
||||
|
||||
if( !this->asUInt16( catalystNode, "MaximumSteps", maximumSteps ) ){
|
||||
return 0;
|
||||
}
|
||||
|
||||
grade->catalyst.maximumSteps = maximumSteps;
|
||||
}else{
|
||||
if( !gradeExists ){
|
||||
grade->catalyst.maximumSteps = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if( this->nodeExists( catalystNode, "ChanceIncrease" ) ){
|
||||
uint16 chanceIncrease;
|
||||
|
||||
if( !this->asUInt16Rate( catalystNode, "ChanceIncrease", chanceIncrease ) ){
|
||||
return 0;
|
||||
}
|
||||
|
||||
grade->catalyst.chanceIncrease = chanceIncrease;
|
||||
}else{
|
||||
if( !gradeExists ){
|
||||
grade->catalyst.chanceIncrease = 0;
|
||||
}
|
||||
}
|
||||
}else{
|
||||
if( !gradeExists ){
|
||||
grade->catalyst.item = 0;
|
||||
grade->catalyst.amountPerStep = 0;
|
||||
grade->catalyst.maximumSteps = 0;
|
||||
grade->catalyst.chanceIncrease = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if( this->nodeExists( gradeNode, "Options" ) ){
|
||||
for( const ryml::NodeRef& optionNode : gradeNode["Options"] ){
|
||||
uint16 optionIndex;
|
||||
|
||||
if( !this->asUInt16( optionNode, "Option", optionIndex ) ){
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::shared_ptr<s_enchantgradeoption> option = util::map_find( grade->options, optionIndex );
|
||||
bool optionExists = option != nullptr;
|
||||
|
||||
if( !optionExists ){
|
||||
option = std::make_shared<s_enchantgradeoption>();
|
||||
option->id = optionIndex;
|
||||
}
|
||||
|
||||
if( this->nodeExists( optionNode, "Amount" ) ){
|
||||
uint16 amount;
|
||||
|
||||
if( !this->asUInt16( optionNode, "Amount", amount ) ){
|
||||
return 0;
|
||||
}
|
||||
|
||||
if( amount > MAX_AMOUNT ){
|
||||
this->invalidWarning( optionNode["Amount"], "Amount %hu is too high, capping to %hu...\n", amount, MAX_AMOUNT );
|
||||
amount = MAX_AMOUNT;
|
||||
}
|
||||
|
||||
if( amount == 0 ){
|
||||
if( grade->options.erase( optionIndex ) > 0 ){
|
||||
continue;
|
||||
}else{
|
||||
this->invalidWarning( optionNode["Amount"], "Trying to remove invalid option %hu...\n", optionIndex );
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
option->amount = amount;
|
||||
}else{
|
||||
if( !optionExists ){
|
||||
option->amount = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if( this->nodeExists( optionNode, "Item" ) ){
|
||||
std::string itemName;
|
||||
|
||||
if( !this->asString( optionNode, "Item", itemName ) ){
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::shared_ptr<item_data> id = item_db.search_aegisname( itemName.c_str() );
|
||||
|
||||
if( id == nullptr ){
|
||||
this->invalidWarning( optionNode["Item"], "Unknown item \"%s\".\n", itemName.c_str() );
|
||||
return 0;
|
||||
}
|
||||
|
||||
option->item = id->nameid;
|
||||
}else{
|
||||
if( !optionExists ){
|
||||
option->item = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if( this->nodeExists( optionNode, "Zeny" ) ){
|
||||
uint32 zeny;
|
||||
|
||||
if( !this->asUInt32( optionNode, "Zeny", zeny ) ){
|
||||
return 0;
|
||||
}
|
||||
|
||||
option->zeny = zeny;
|
||||
}else{
|
||||
if( !optionExists ){
|
||||
option->zeny = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if( this->nodeExists( optionNode, "BreakingRate" ) ){
|
||||
uint16 breaking_rate;
|
||||
|
||||
if( !this->asUInt16Rate( optionNode, "BreakingRate", breaking_rate ) ){
|
||||
return 0;
|
||||
}
|
||||
|
||||
option->breaking_rate = breaking_rate;
|
||||
}else{
|
||||
if( !optionExists ){
|
||||
option->breaking_rate = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if( this->nodeExists( optionNode, "DowngradeAmount" ) ){
|
||||
uint16 downgrade_amount;
|
||||
|
||||
if( !this->asUInt16( optionNode, "DowngradeAmount", downgrade_amount ) ){
|
||||
return 0;
|
||||
}
|
||||
|
||||
if( downgrade_amount > MAX_REFINE ){
|
||||
this->invalidWarning( optionNode["DowngradeAmount"], "Downgrade amount %hu is invalid, skipping.\n", downgrade_amount );
|
||||
return 0;
|
||||
}
|
||||
|
||||
option->downgrade_amount = downgrade_amount;
|
||||
}else{
|
||||
if( !optionExists ){
|
||||
option->downgrade_amount = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if( !optionExists ){
|
||||
grade->options[optionIndex] = option;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( !gradeExists ){
|
||||
grades[gradeLevel] = grade;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( !exists ){
|
||||
this->put( itemtype, enchantgrade );
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::shared_ptr<s_enchantgradelevel> EnchantgradeDatabase::findCurrentLevelInfo( const struct item_data& data, struct item& item ){
|
||||
std::shared_ptr<s_enchantgrade> enchantgrade = enchantgrade_db.find( data.type );
|
||||
|
||||
// Unsupported item type - no answer
|
||||
if( enchantgrade == nullptr ){
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
uint16 level = 0;
|
||||
|
||||
if( data.type == IT_WEAPON ){
|
||||
level = data.weapon_level;
|
||||
}else if( data.type == IT_ARMOR ){
|
||||
level = data.armor_level;
|
||||
}
|
||||
|
||||
const auto& enchantgradelevels = enchantgrade->levels.find( level );
|
||||
|
||||
// Cannot upgrade this weapon or armor level - no answer
|
||||
if( enchantgradelevels == enchantgrade->levels.end() ){
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return util::map_find( enchantgradelevels->second, (e_enchantgrade)( item.enchantgrade - 1 ) );
|
||||
}
|
||||
|
||||
void EnchantgradeDatabase::loadingFinished(){
|
||||
for( const auto& it_itemTypes : *this ){
|
||||
for( const auto& it_itemLevels : it_itemTypes.second->levels ){
|
||||
for( const auto& it_enchantgrades : it_itemLevels.second ){
|
||||
std::shared_ptr<s_enchantgradelevel> enchantgradelevel = it_enchantgrades.second;
|
||||
|
||||
if( enchantgradelevel->catalyst.amountPerStep == 0 ){
|
||||
enchantgradelevel->catalyst.item = 0;
|
||||
enchantgradelevel->catalyst.chanceIncrease = 0;
|
||||
enchantgradelevel->catalyst.maximumSteps = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
EnchantgradeDatabase enchantgrade_db;
|
||||
|
||||
/**
|
||||
* Get icon ID of SC
|
||||
* @param type: SC type
|
||||
@ -3256,6 +3649,13 @@ int status_calc_pc_sub(struct map_session_data* sd, uint8 opt)
|
||||
sd->inventory.u.items_inventory[index].refine = MAX_REFINE;
|
||||
|
||||
std::shared_ptr<s_refine_level_info> info = refine_db.findCurrentLevelInfo( *sd->inventory_data[index], sd->inventory.u.items_inventory[index] );
|
||||
#ifdef RENEWAL
|
||||
std::shared_ptr<s_enchantgradelevel> enchantgrade_info = nullptr;
|
||||
|
||||
if( sd->inventory.u.items_inventory[index].enchantgrade > 0 ){
|
||||
enchantgrade_info = enchantgrade_db.findCurrentLevelInfo( *sd->inventory_data[index], sd->inventory.u.items_inventory[index] );
|
||||
}
|
||||
#endif
|
||||
|
||||
if (sd->inventory_data[index]->type == IT_WEAPON) {
|
||||
int wlv = sd->inventory_data[index]->weapon_level;
|
||||
@ -3277,7 +3677,9 @@ int status_calc_pc_sub(struct map_session_data* sd, uint8 opt)
|
||||
wa->atk2 += info->bonus / 100;
|
||||
|
||||
#ifdef RENEWAL
|
||||
// TODO: additional grade bonus
|
||||
if( enchantgrade_info != nullptr ){
|
||||
wa->atk2 += ( ( ( info->bonus / 100 ) * enchantgrade_info->bonus ) / 100 );
|
||||
}
|
||||
|
||||
if( wlv == 5 ){
|
||||
base_status->patk += sd->inventory.u.items_inventory[index].refine * 2;
|
||||
@ -3294,7 +3696,9 @@ int status_calc_pc_sub(struct map_session_data* sd, uint8 opt)
|
||||
if( info != nullptr && sd->weapontype1 != W_BOW ){
|
||||
wa->matk += info->bonus / 100;
|
||||
|
||||
// TODO: additional grade bonus
|
||||
if( enchantgrade_info != nullptr ){
|
||||
wa->matk += ( ( ( info->bonus / 100 ) * enchantgrade_info->bonus ) / 100 );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
// Overrefine bonus.
|
||||
@ -15184,10 +15588,12 @@ void status_readdb( bool reload ){
|
||||
size_fix_db.reload();
|
||||
refine_db.reload();
|
||||
status_db.reload();
|
||||
enchantgrade_db.reload();
|
||||
}else{
|
||||
size_fix_db.load();
|
||||
refine_db.load();
|
||||
status_db.load();
|
||||
enchantgrade_db.load();
|
||||
}
|
||||
elemental_attribute_db.load();
|
||||
}
|
||||
@ -15211,6 +15617,7 @@ void do_init_status(void) {
|
||||
/** Destroy status data */
|
||||
void do_final_status(void) {
|
||||
ers_destroy(sc_data_ers);
|
||||
enchantgrade_db.clear();
|
||||
size_fix_db.clear();
|
||||
refine_db.clear();
|
||||
status_db.clear();
|
||||
|
@ -144,6 +144,59 @@ public:
|
||||
|
||||
extern AttributeDatabase elemental_attribute_db;
|
||||
|
||||
enum e_enchantgrade_result{
|
||||
ENCHANTGRADE_UPGRADE_SUCCESS,
|
||||
ENCHANTGRADE_UPGRADE_FAILED,
|
||||
ENCHANTGRADE_UPGRADE_DOWNGRADE,
|
||||
ENCHANTGRADE_UPGRADE_BREAK,
|
||||
ENCHANTGRADE_UPGRADE_PROTECTED,
|
||||
};
|
||||
|
||||
struct s_enchantgradeoption{
|
||||
uint16 id;
|
||||
t_itemid item;
|
||||
uint16 amount;
|
||||
uint32 zeny;
|
||||
uint16 breaking_rate;
|
||||
uint16 downgrade_amount;
|
||||
};
|
||||
|
||||
struct s_enchantgradelevel{
|
||||
e_enchantgrade grade;
|
||||
uint16 refine;
|
||||
uint16 chance;
|
||||
uint16 bonus;
|
||||
bool announce;
|
||||
struct{
|
||||
t_itemid item;
|
||||
uint16 amountPerStep;
|
||||
uint16 maximumSteps;
|
||||
uint16 chanceIncrease;
|
||||
}catalyst;
|
||||
std::map<uint16,std::shared_ptr<s_enchantgradeoption>> options;
|
||||
};
|
||||
|
||||
struct s_enchantgrade{
|
||||
uint16 itemtype;
|
||||
std::map<uint16,std::map<e_enchantgrade,std::shared_ptr<s_enchantgradelevel>>> levels;
|
||||
};
|
||||
|
||||
class EnchantgradeDatabase : public TypesafeYamlDatabase<uint16, s_enchantgrade>{
|
||||
public:
|
||||
EnchantgradeDatabase() : TypesafeYamlDatabase( "ENCHANTGRADE_DB", 1 ){
|
||||
|
||||
}
|
||||
|
||||
const std::string getDefaultLocation() override;
|
||||
uint64 parseBodyNode( const ryml::NodeRef& node ) override;
|
||||
void loadingFinished() override;
|
||||
|
||||
// Additional
|
||||
std::shared_ptr<s_enchantgradelevel> findCurrentLevelInfo( const struct item_data& data, struct item& item );
|
||||
};
|
||||
|
||||
extern EnchantgradeDatabase enchantgrade_db;
|
||||
|
||||
/// Status changes listing. These code are for use by the server.
|
||||
enum sc_type : int16 {
|
||||
SC_NONE = -1,
|
||||
|
Loading…
x
Reference in New Issue
Block a user