Initial release of the refine UI (#2494)

Overhaul of the refine database
Added blacksmith blessing to existing NPCs.

Thanks to @Atemo, @aleos89, @cydh and everyone who tested it.

Co-authored-by: Atemo <capucrath@gmail.com>
This commit is contained in:
Lemongrass3110 2021-04-11 00:05:15 +02:00 committed by GitHub
parent 04d1f1f526
commit 1a8cfbffc0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
34 changed files with 4553 additions and 1206 deletions

View File

@ -71,6 +71,10 @@ feature.roulette: on
// Requires: 2015-05-13aRagexe or later
feature.achievement: on
// Refine UI (Note 1)
// Requires: 2016-10-12aRagexeRE or later
feature.refineui: on
// Equipment Switch (Note 1)
// Requires: 2017-02-08bRagexeRE or later
feature.equipswitch: on

View File

@ -115,11 +115,6 @@ default_bind_on_equip: 4
// 0x8 = Only Guild Leader can sell BOUND_GUILD items to Shops or Itemshops (if 0x1 or 0x4 set)
allow_bound_sell: 0x0
// Turn on event refine chance (see db/{pre-}re/refine_db.yml)
// no = normal refine chances in effect (official/default value)
// yes = event refine chances in effect
event_refine_chance: no
// Hide n last characters of player's name with asterisk (*) when the player
// obtained an item with special broadcast flag.
// Note: Players with short names can be fully converted to asterisks if this

View File

@ -836,7 +836,10 @@
// Achievements
772: Achievements are disabled.
//773-775 reserved for refine UI
// @refineui
773: This command requires packet version 2016-10-12 or newer.
774: This command is disabled via configuration.
775: You have already opened the refine UI.
//776-781 reserved for tax system
782: Star Emperor

391
db/import-tmpl/refine.yml Normal file
View File

@ -0,0 +1,391 @@
# This file is a part of rAthena++.
# Copyright(C) 2021 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/>.
#
###########################################################################
# Refine Database
###########################################################################
#
# Refine Settings
#
###########################################################################
# - Group Refine item type.
# Levels: Refinement settings per item level. (Default: null)
# - Level Item level.
# RefineLevels: Refinement settings per refine level. (Default: null)
# - Level Refine level.
# Bonus Refinement bonus. (Default: 0)
# RandomBonus Extra refinement bonus of 0~RandomBonus stacked on Bonus. (Default: 0)
# BlacksmithBlessingAmount Amount of Blacksmith Blessing required. (Default: 0)
# Chances: Success chance based on cost type. (Default: null)
# - Type Refinement cost type based on ore used.
# Rate Chance of success out of 0~100. (Default: 0)
# Price Amount of zeny required to refine. (Default: 0)
# Material Ore item required to refine. (Default: 0)
# BreakingRate Chance of item breaking out of 0~100. (Default: 0)
# DowngradeAmount Number of refine levels reduced on failure. (Default: 0)
###########################################################################
Header:
Type: REFINE_DB
Version: 1
###########################################################################
# Event Refine Rates
###########################################################################
#Body:
# - Group: Armor
# Levels:
# - Level: 1
# RefineLevels:
# - Level: 5
# Chances:
# - Type: Enriched
# Rate: 9500
# - Level: 6
# Chances:
# - Type: Enriched
# Rate: 8000
# - Level: 7
# Chances:
# - Type: Enriched
# Rate: 8000
# - Level: 8
# Chances:
# - Type: Enriched
# Rate: 5000
# - Level: 9
# Chances:
# - Type: Enriched
# Rate: 5000
# - Level: 10
# Chances:
# - Type: Enriched
# Rate: 3500
# - Level: 11
# Chances:
# - Type: Normal
# Rate: 2000
# - Level: 12
# Chances:
# - Type: Normal
# Rate: 2000
# - Level: 13
# Chances:
# - Type: Normal
# Rate: 1600
# - Level: 14
# Chances:
# - Type: Normal
# Rate: 1600
# - Level: 15
# Chances:
# - Type: Normal
# Rate: 1500
# - Level: 16
# Chances:
# - Type: Normal
# Rate: 1500
# - Level: 17
# Chances:
# - Type: Normal
# Rate: 1400
# - Level: 18
# Chances:
# - Type: Normal
# Rate: 1400
# - Level: 19
# Chances:
# - Type: Normal
# Rate: 1000
# - Level: 20
# Chances:
# - Type: Normal
# Rate: 1000
# - Group: Weapon
# Levels:
# - Level: 1
# RefineLevels:
# - Level: 8
# Chances:
# - Type: Enriched
# Rate: 9500
# - Level: 9
# Chances:
# - Type: Enriched
# Rate: 8500
# - Level: 10
# Chances:
# - Type: Enriched
# Rate: 5500
# - Level: 11
# Chances:
# - Type: Normal
# Rate: 4000
# - Level: 12
# Chances:
# - Type: Normal
# Rate: 4000
# - Level: 13
# Chances:
# - Type: Normal
# Rate: 3500
# - Level: 14
# Chances:
# - Type: Normal
# Rate: 3500
# - Level: 15
# Chances:
# - Type: Normal
# Rate: 3000
# - Level: 16
# Chances:
# - Type: Normal
# Rate: 3000
# - Level: 17
# Chances:
# - Type: Normal
# Rate: 2000
# - Level: 18
# Chances:
# - Type: Normal
# Rate: 2000
# - Level: 2
# RefineLevels:
# - Level: 7
# Chances:
# - Type: Enriched
# Rate: 9500
# - Level: 8
# Chances:
# - Type: Enriched
# Rate: 8500
# - Level: 9
# Chances:
# - Type: Enriched
# Rate: 6000
# - Level: 10
# Chances:
# - Type: Enriched
# Rate: 4500
# - Level: 11
# Chances:
# - Type: Normal
# Rate: 4000
# - Level: 12
# Chances:
# - Type: Normal
# Rate: 4000
# - Level: 13
# Chances:
# - Type: Normal
# Rate: 3500
# - Level: 14
# Chances:
# - Type: Normal
# Rate: 3500
# - Level: 15
# Chances:
# - Type: Normal
# Rate: 3000
# - Level: 16
# Chances:
# - Type: Normal
# Rate: 3000
# - Level: 17
# Chances:
# - Type: Normal
# Rate: 2000
# - Level: 18
# Chances:
# - Type: Normal
# Rate: 2000
# - Level: 3
# RefineLevels:
# - Level: 6
# Chances:
# - Type: Enriched
# Rate: 9500
# - Level: 7
# Chances:
# - Type: Enriched
# Rate: 9000
# - Level: 8
# Chances:
# - Type: Enriched
# Rate: 7000
# - Level: 9
# Chances:
# - Type: Enriched
# Rate: 6000
# - Level: 10
# Chances:
# - Type: Enriched
# Rate: 4500
# - Level: 11
# Chances:
# - Type: Normal
# Rate: 4000
# - Level: 12
# Chances:
# - Type: Normal
# Rate: 4000
# - Level: 13
# Chances:
# - Type: Normal
# Rate: 3500
# - Level: 14
# Chances:
# - Type: Normal
# Rate: 3500
# - Level: 15
# Chances:
# - Type: Normal
# Rate: 3000
# - Level: 16
# Chances:
# - Type: Normal
# Rate: 3000
# - Level: 17
# Chances:
# - Type: Normal
# Rate: 2000
# - Level: 18
# Chances:
# - Type: Normal
# Rate: 2000
# - Level: 4
# RefineLevels:
# - Level: 5
# Chances:
# - Type: Enriched
# Rate: 9500
# - Level: 6
# Chances:
# - Type: Enriched
# Rate: 8000
# - Level: 7
# Chances:
# - Type: Enriched
# Rate: 8000
# - Level: 8
# Chances:
# - Type: Enriched
# Rate: 6000
# - Level: 9
# Chances:
# - Type: Enriched
# Rate: 5000
# - Level: 10
# Chances:
# - Type: Enriched
# Rate: 3500
# - Level: 11
# Chances:
# - Type: Normal
# Rate: 2000
# - Level: 12
# Chances:
# - Type: Normal
# Rate: 2000
# - Level: 13
# Chances:
# - Type: Normal
# Rate: 1600
# - Level: 14
# Chances:
# - Type: Normal
# Rate: 1600
# - Level: 15
# Chances:
# - Type: Normal
# Rate: 1500
# - Level: 16
# Chances:
# - Type: Normal
# Rate: 1500
# - Level: 17
# Chances:
# - Type: Normal
# Rate: 1400
# - Level: 18
# Chances:
# - Type: Normal
# Rate: 1400
# - Level: 19
# Chances:
# - Type: Normal
# Rate: 1000
# - Level: 20
# Chances:
# - Type: Normal
# Rate: 1000
# - Group: Shadow_Armor
# Levels:
# - Level: 1
# RefineLevels:
# - Level: 5
# Chances:
# - Type: Enriched
# Rate: 9500
# - Level: 6
# Chances:
# - Type: Enriched
# Rate: 8000
# - Level: 7
# Chances:
# - Type: Enriched
# Rate: 8000
# - Level: 8
# Chances:
# - Type: Enriched
# Rate: 5000
# - Level: 9
# Chances:
# - Type: Enriched
# Rate: 5000
# - Level: 10
# Chances:
# - Type: Enriched
# Rate: 3500
# - Group: Shadow_Weapon
# Levels:
# - Level: 1
# RefineLevels:
# - Level: 5
# Chances:
# - Type: Enriched
# Rate: 9500
# - Level: 6
# Chances:
# - Type: Enriched
# Rate: 8000
# - Level: 7
# Chances:
# - Type: Enriched
# Rate: 8000
# - Level: 8
# Chances:
# - Type: Enriched
# Rate: 5000
# - Level: 9
# Chances:
# - Type: Enriched
# Rate: 5000
# - Level: 10
# Chances:
# - Type: Enriched
# Rate: 3500

View File

@ -1,20 +0,0 @@
# This file is a part of rAthena++.
# Copyright(C) 2021 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/>.
#
###########################################################################
# Custom Refine Database
###########################################################################

924
db/pre-re/refine.yml Normal file
View File

@ -0,0 +1,924 @@
# This file is a part of rAthena++.
# Copyright(C) 2021 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/>.
#
###########################################################################
# Refine Database
###########################################################################
#
# Refine Settings
#
###########################################################################
# - Group Refine item type.
# Levels: Refinement settings per item level. (Default: null)
# - Level Item level.
# RefineLevels: Refinement settings per refine level. (Default: null)
# - Level Refine level.
# Bonus Refinement bonus. (Default: 0)
# RandomBonus Extra refinement bonus of 0~RandomBonus stacked on Bonus. (Default: 0)
# BlacksmithBlessingAmount Amount of Blacksmith Blessing required. (Default: 0)
# Chances: Success chance based on cost type. (Default: null)
# - Type Refinement cost type based on ore used.
# Rate Chance of success out of 0~100. (Default: 0)
# Price Amount of zeny required to refine. (Default: 0)
# Material Ore item required to refine. (Default: 0)
# BreakingRate Chance of item breaking out of 0~100. (Default: 0)
# DowngradeAmount Number of refine levels reduced on failure. (Default: 0)
###########################################################################
Header:
Type: REFINE_DB
Version: 1
Body:
- Group: Armor
Levels:
- Level: 1
RefineLevels:
- Level: 1
Bonus: 66
Chances:
- Type: Normal
Rate: 10000
Price: 2000
Material: Elunium
- Type: Enriched
Rate: 10000
Price: 2000
Material: Enriched_Elunium
- Level: 2
Bonus: 132
Chances:
- Type: Normal
Rate: 10000
Price: 2000
Material: Elunium
- Type: Enriched
Rate: 10000
Price: 2000
Material: Enriched_Elunium
- Level: 3
Bonus: 198
Chances:
- Type: Normal
Rate: 10000
Price: 2000
Material: Elunium
- Type: Enriched
Rate: 10000
Price: 2000
Material: Enriched_Elunium
- Level: 4
Bonus: 264
Chances:
- Type: Normal
Rate: 10000
Price: 2000
Material: Elunium
- Type: Enriched
Rate: 10000
Price: 2000
Material: Enriched_Elunium
- Level: 5
Bonus: 330
Chances:
- Type: Normal
Rate: 6000
Price: 2000
Material: Elunium
BreakingRate: 10000
- Type: Enriched
Rate: 9000
Price: 2000
Material: Enriched_Elunium
BreakingRate: 10000
- Level: 6
Bonus: 396
Chances:
- Type: Normal
Rate: 4000
Price: 2000
Material: Elunium
BreakingRate: 10000
- Type: Enriched
Rate: 7000
Price: 2000
Material: Enriched_Elunium
BreakingRate: 10000
- Level: 7
Bonus: 462
Chances:
- Type: Normal
Rate: 4000
Price: 2000
Material: Elunium
BreakingRate: 10000
- Type: Enriched
Rate: 7000
Price: 2000
Material: Enriched_Elunium
BreakingRate: 10000
- Level: 8
Bonus: 528
BlacksmithBlessingAmount: 1
Chances:
- Type: Normal
Rate: 2000
Price: 2000
Material: Elunium
BreakingRate: 10000
- Type: Enriched
Rate: 4000
Price: 2000
Material: Enriched_Elunium
BreakingRate: 10000
- Level: 9
Bonus: 594
BlacksmithBlessingAmount: 2
Chances:
- Type: Normal
Rate: 2000
Price: 2000
Material: Elunium
BreakingRate: 10000
- Type: Enriched
Rate: 4000
Price: 2000
Material: Enriched_Elunium
BreakingRate: 10000
- Level: 10
Bonus: 660
BlacksmithBlessingAmount: 4
Chances:
- Type: Normal
Rate: 900
Price: 2000
Material: Elunium
BreakingRate: 10000
- Type: Enriched
Rate: 2000
Price: 2000
Material: Enriched_Elunium
BreakingRate: 10000
- Group: Weapon
Levels:
- Level: 1
RefineLevels:
- Level: 1
Bonus: 200
Chances:
- Type: Normal
Rate: 10000
Price: 50
Material: Phracon
- Type: Enriched
Rate: 10000
Price: 2000
Material: Enriched_Oridecon
- Level: 2
Bonus: 400
Chances:
- Type: Normal
Rate: 10000
Price: 50
Material: Phracon
- Type: Enriched
Rate: 10000
Price: 2000
Material: Enriched_Oridecon
- Level: 3
Bonus: 600
Chances:
- Type: Normal
Rate: 10000
Price: 50
Material: Phracon
- Type: Enriched
Rate: 10000
Price: 2000
Material: Enriched_Oridecon
- Level: 4
Bonus: 800
Chances:
- Type: Normal
Rate: 10000
Price: 50
Material: Phracon
- Type: Enriched
Rate: 10000
Price: 2000
Material: Enriched_Oridecon
- Level: 5
Bonus: 1000
Chances:
- Type: Normal
Rate: 10000
Price: 50
Material: Phracon
- Type: Enriched
Rate: 10000
Price: 2000
Material: Enriched_Oridecon
- Level: 6
Bonus: 1200
Chances:
- Type: Normal
Rate: 10000
Price: 50
Material: Phracon
- Type: Enriched
Rate: 10000
Price: 2000
Material: Enriched_Oridecon
- Level: 7
Bonus: 1400
Chances:
- Type: Normal
Rate: 10000
Price: 50
Material: Phracon
- Type: Enriched
Rate: 10000
Price: 2000
Material: Enriched_Oridecon
- Level: 8
Bonus: 1600
RandomBonus: 300
BlacksmithBlessingAmount: 1
Chances:
- Type: Normal
Rate: 6000
Price: 50
Material: Phracon
BreakingRate: 10000
- Type: Enriched
Rate: 9000
Price: 2000
Material: Enriched_Oridecon
BreakingRate: 10000
- Level: 9
Bonus: 1800
RandomBonus: 600
BlacksmithBlessingAmount: 2
Chances:
- Type: Normal
Rate: 4000
Price: 50
Material: Phracon
BreakingRate: 10000
- Type: Enriched
Rate: 7000
Price: 2000
Material: Enriched_Oridecon
BreakingRate: 10000
- Level: 10
Bonus: 2000
RandomBonus: 900
BlacksmithBlessingAmount: 4
Chances:
- Type: Normal
Rate: 1900
Price: 50
Material: Phracon
BreakingRate: 10000
- Type: Enriched
Rate: 3000
Price: 2000
Material: Enriched_Oridecon
BreakingRate: 10000
- Level: 2
RefineLevels:
- Level: 1
Bonus: 300
Chances:
- Type: Normal
Rate: 10000
Price: 200
Material: Emveretarcon
- Type: Enriched
Rate: 10000
Price: 2000
Material: Enriched_Oridecon
- Level: 2
Bonus: 600
Chances:
- Type: Normal
Rate: 10000
Price: 200
Material: Emveretarcon
- Type: Enriched
Rate: 10000
Price: 2000
Material: Enriched_Oridecon
- Level: 3
Bonus: 900
Chances:
- Type: Normal
Rate: 10000
Price: 200
Material: Emveretarcon
- Type: Enriched
Rate: 10000
Price: 2000
Material: Enriched_Oridecon
- Level: 4
Bonus: 1200
Chances:
- Type: Normal
Rate: 10000
Price: 200
Material: Emveretarcon
- Type: Enriched
Rate: 10000
Price: 2000
Material: Enriched_Oridecon
- Level: 5
Bonus: 1500
Chances:
- Type: Normal
Rate: 10000
Price: 200
Material: Emveretarcon
- Type: Enriched
Rate: 10000
Price: 2000
Material: Enriched_Oridecon
- Level: 6
Bonus: 1800
Chances:
- Type: Normal
Rate: 10000
Price: 200
Material: Emveretarcon
- Type: Enriched
Rate: 10000
Price: 2000
Material: Enriched_Oridecon
- Level: 7
Bonus: 2100
RandomBonus: 500
Chances:
- Type: Normal
Rate: 6000
Price: 200
Material: Emveretarcon
BreakingRate: 10000
- Type: Enriched
Rate: 9000
Price: 2000
Material: Enriched_Oridecon
BreakingRate: 10000
- Level: 8
Bonus: 2400
RandomBonus: 1000
BlacksmithBlessingAmount: 1
Chances:
- Type: Normal
Rate: 4000
Price: 200
Material: Emveretarcon
BreakingRate: 10000
- Type: Enriched
Rate: 7000
Price: 2000
Material: Enriched_Oridecon
BreakingRate: 10000
- Level: 9
Bonus: 2700
RandomBonus: 1500
BlacksmithBlessingAmount: 2
Chances:
- Type: Normal
Rate: 2000
Price: 200
Material: Emveretarcon
BreakingRate: 10000
- Type: Enriched
Rate: 4000
Price: 2000
Material: Enriched_Oridecon
BreakingRate: 10000
- Level: 10
Bonus: 3000
RandomBonus: 2000
BlacksmithBlessingAmount: 4
Chances:
- Type: Normal
Rate: 1900
Price: 200
Material: Emveretarcon
BreakingRate: 10000
- Type: Enriched
Rate: 3000
Price: 2000
Material: Enriched_Oridecon
BreakingRate: 10000
- Level: 3
RefineLevels:
- Level: 1
Bonus: 500
Chances:
- Type: Normal
Rate: 10000
Price: 5000
Material: Oridecon
- Type: Enriched
Rate: 10000
Price: 2000
Material: Enriched_Oridecon
- Level: 2
Bonus: 1000
Chances:
- Type: Normal
Rate: 10000
Price: 5000
Material: Oridecon
- Type: Enriched
Rate: 10000
Price: 2000
Material: Enriched_Oridecon
- Level: 3
Bonus: 1500
Chances:
- Type: Normal
Rate: 10000
Price: 5000
Material: Oridecon
- Type: Enriched
Rate: 10000
Price: 2000
Material: Enriched_Oridecon
- Level: 4
Bonus: 2000
Chances:
- Type: Normal
Rate: 10000
Price: 5000
Material: Oridecon
- Type: Enriched
Rate: 10000
Price: 2000
Material: Enriched_Oridecon
- Level: 5
Bonus: 2500
Chances:
- Type: Normal
Rate: 10000
Price: 5000
Material: Oridecon
- Type: Enriched
Rate: 10000
Price: 2000
Material: Enriched_Oridecon
- Level: 6
Bonus: 3000
RandomBonus: 800
Chances:
- Type: Normal
Rate: 6000
Price: 5000
Material: Oridecon
BreakingRate: 10000
- Type: Enriched
Rate: 9000
Price: 2000
Material: Enriched_Oridecon
BreakingRate: 10000
- Level: 7
Bonus: 3500
RandomBonus: 1600
Chances:
- Type: Normal
Rate: 5000
Price: 5000
Material: Oridecon
BreakingRate: 10000
- Type: Enriched
Rate: 8000
Price: 2000
Material: Enriched_Oridecon
BreakingRate: 10000
- Level: 8
Bonus: 4000
RandomBonus: 2400
BlacksmithBlessingAmount: 1
Chances:
- Type: Normal
Rate: 2000
Price: 5000
Material: Oridecon
BreakingRate: 10000
- Type: Enriched
Rate: 4000
Price: 2000
Material: Enriched_Oridecon
BreakingRate: 10000
- Level: 9
Bonus: 4500
RandomBonus: 3200
BlacksmithBlessingAmount: 2
Chances:
- Type: Normal
Rate: 2000
Price: 5000
Material: Oridecon
BreakingRate: 10000
- Type: Enriched
Rate: 4000
Price: 2000
Material: Enriched_Oridecon
BreakingRate: 10000
- Level: 10
Bonus: 5000
RandomBonus: 4000
BlacksmithBlessingAmount: 4
Chances:
- Type: Normal
Rate: 1900
Price: 5000
Material: Oridecon
BreakingRate: 10000
- Type: Enriched
Rate: 3000
Price: 2000
Material: Enriched_Oridecon
BreakingRate: 10000
- Level: 4
RefineLevels:
- Level: 1
Bonus: 700
Chances:
- Type: Normal
Rate: 10000
Price: 20000
Material: Oridecon
- Type: Enriched
Rate: 10000
Price: 2000
Material: Enriched_Oridecon
- Level: 2
Bonus: 1400
Chances:
- Type: Normal
Rate: 10000
Price: 20000
Material: Oridecon
- Type: Enriched
Rate: 10000
Price: 2000
Material: Enriched_Oridecon
- Level: 3
Bonus: 2100
Chances:
- Type: Normal
Rate: 10000
Price: 20000
Material: Oridecon
- Type: Enriched
Rate: 10000
Price: 2000
Material: Enriched_Oridecon
- Level: 4
Bonus: 2800
Chances:
- Type: Normal
Rate: 10000
Price: 20000
Material: Oridecon
- Type: Enriched
Rate: 10000
Price: 2000
Material: Enriched_Oridecon
- Level: 5
Bonus: 3500
RandomBonus: 1300
Chances:
- Type: Normal
Rate: 6000
Price: 20000
Material: Oridecon
BreakingRate: 10000
- Type: Enriched
Rate: 9000
Price: 2000
Material: Enriched_Oridecon
BreakingRate: 10000
- Level: 6
Bonus: 4200
RandomBonus: 2600
Chances:
- Type: Normal
Rate: 4000
Price: 20000
Material: Oridecon
BreakingRate: 10000
- Type: Enriched
Rate: 7000
Price: 2000
Material: Enriched_Oridecon
BreakingRate: 10000
- Level: 7
Bonus: 4900
RandomBonus: 3900
Chances:
- Type: Normal
Rate: 4000
Price: 20000
Material: Oridecon
BreakingRate: 10000
- Type: Enriched
Rate: 7000
Price: 2000
Material: Enriched_Oridecon
BreakingRate: 10000
- Level: 8
Bonus: 5600
RandomBonus: 5200
BlacksmithBlessingAmount: 1
Chances:
- Type: Normal
Rate: 2000
Price: 20000
Material: Oridecon
BreakingRate: 10000
- Type: Enriched
Rate: 4000
Price: 2000
Material: Enriched_Oridecon
BreakingRate: 10000
- Level: 9
Bonus: 6300
RandomBonus: 6500
BlacksmithBlessingAmount: 2
Chances:
- Type: Normal
Rate: 2000
Price: 20000
Material: Oridecon
BreakingRate: 10000
- Type: Enriched
Rate: 4000
Price: 2000
Material: Enriched_Oridecon
BreakingRate: 10000
- Level: 10
Bonus: 7000
RandomBonus: 7800
BlacksmithBlessingAmount: 4
Chances:
- Type: Normal
Rate: 900
Price: 20000
Material: Oridecon
BreakingRate: 10000
- Type: Enriched
Rate: 2000
Price: 2000
Material: Enriched_Oridecon
BreakingRate: 10000
- Group: Shadow_Armor
Levels:
- Level: 1
RefineLevels:
- Level: 1
Chances:
- Type: Normal
Rate: 10000
Price: 10000
Material: Elunium
- Type: Enriched
Rate: 10000
Price: 10000
Material: Enriched_Elunium
- Level: 2
Chances:
- Type: Normal
Rate: 10000
Price: 10000
Material: Elunium
- Type: Enriched
Rate: 10000
Price: 10000
Material: Enriched_Elunium
- Level: 3
Chances:
- Type: Normal
Rate: 10000
Price: 10000
Material: Elunium
- Type: Enriched
Rate: 10000
Price: 10000
Material: Enriched_Elunium
- Level: 4
Chances:
- Type: Normal
Rate: 10000
Price: 10000
Material: Elunium
- Type: Enriched
Rate: 10000
Price: 10000
Material: Enriched_Elunium
- Level: 5
Chances:
- Type: Normal
Rate: 6000
Price: 10000
Material: Elunium
BreakingRate: 10000
- Type: Enriched
Rate: 9000
Price: 10000
Material: Enriched_Elunium
BreakingRate: 10000
- Level: 6
Chances:
- Type: Normal
Rate: 4000
Price: 10000
Material: Elunium
BreakingRate: 10000
- Type: Enriched
Rate: 7000
Price: 10000
Material: Enriched_Elunium
BreakingRate: 10000
- Level: 7
Chances:
- Type: Normal
Rate: 4000
Price: 10000
Material: Elunium
BreakingRate: 10000
- Type: Enriched
Rate: 7000
Price: 10000
Material: Enriched_Elunium
BreakingRate: 10000
- Level: 8
Chances:
- Type: Normal
Rate: 2000
Price: 10000
Material: Elunium
BreakingRate: 10000
- Type: Enriched
Rate: 4000
Price: 10000
Material: Enriched_Elunium
BreakingRate: 10000
- Level: 9
Chances:
- Type: Normal
Rate: 2000
Price: 10000
Material: Elunium
BreakingRate: 10000
- Type: Enriched
Rate: 4000
Price: 10000
Material: Enriched_Elunium
BreakingRate: 10000
- Level: 10
Chances:
- Type: Normal
Rate: 900
Price: 10000
Material: Elunium
BreakingRate: 10000
- Type: Enriched
Rate: 2000
Price: 10000
Material: Enriched_Elunium
BreakingRate: 10000
- Group: Shadow_Weapon
Levels:
- Level: 1
RefineLevels:
- Level: 1
Chances:
- Type: Normal
Rate: 10000
Price: 10000
Material: Oridecon
- Type: Enriched
Rate: 10000
Price: 10000
Material: Enriched_Oridecon
- Level: 2
Chances:
- Type: Normal
Rate: 10000
Price: 10000
Material: Oridecon
- Type: Enriched
Rate: 10000
Price: 10000
Material: Enriched_Oridecon
- Level: 3
Chances:
- Type: Normal
Rate: 10000
Price: 10000
Material: Oridecon
- Type: Enriched
Rate: 10000
Price: 10000
Material: Enriched_Oridecon
- Level: 4
Chances:
- Type: Normal
Rate: 10000
Price: 10000
Material: Oridecon
- Type: Enriched
Rate: 10000
Price: 10000
Material: Enriched_Oridecon
- Level: 5
Chances:
- Type: Normal
Rate: 6000
Price: 10000
Material: Oridecon
BreakingRate: 10000
- Type: Enriched
Rate: 9000
Price: 10000
Material: Enriched_Oridecon
BreakingRate: 10000
- Level: 6
Chances:
- Type: Normal
Rate: 4000
Price: 10000
Material: Oridecon
BreakingRate: 10000
- Type: Enriched
Rate: 7000
Price: 10000
Material: Enriched_Oridecon
BreakingRate: 10000
- Level: 7
Chances:
- Type: Normal
Rate: 4000
Price: 10000
Material: Oridecon
BreakingRate: 10000
- Type: Enriched
Rate: 7000
Price: 10000
Material: Enriched_Oridecon
BreakingRate: 10000
- Level: 8
Chances:
- Type: Normal
Rate: 2000
Price: 10000
Material: Oridecon
BreakingRate: 10000
- Type: Enriched
Rate: 4000
Price: 10000
Material: Enriched_Oridecon
BreakingRate: 10000
- Level: 9
Chances:
- Type: Normal
Rate: 2000
Price: 10000
Material: Oridecon
BreakingRate: 10000
- Type: Enriched
Rate: 4000
Price: 10000
Material: Enriched_Oridecon
BreakingRate: 10000
- Level: 10
Chances:
- Type: Normal
Rate: 900
Price: 10000
Material: Oridecon
BreakingRate: 10000
- Type: Enriched
Rate: 2000
Price: 10000
Material: Enriched_Oridecon
BreakingRate: 10000

View File

@ -1,235 +0,0 @@
# This file is a part of rAthena++.
# Copyright(C) 2021 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/>.
#
###########################################################################
# Pre-Renewal Refine Database
###########################################################################
Armor:
StatsPerLevel: 66
RandomBonusStartLevel: 0
RandomBonusValue: 0
Costs:
- Type: REFINE_COST_NORMAL
Price: 2000
Material: 985
- Type: REFINE_COST_ENRICHED
Price: 2000
Material: 7619
Rates:
- Level: 5
NormalChance: 60
EnrichedChance: 90
EventNormalChance: 60
EventEnrichedChance: 95
- Level: 6
NormalChance: 40
EnrichedChance: 70
EventNormalChance: 40
EventEnrichedChance: 80
- Level: 7
NormalChance: 40
EnrichedChance: 70
EventNormalChance: 40
EventEnrichedChance: 80
- Level: 8
NormalChance: 20
EnrichedChance: 40
EventNormalChance: 20
EventEnrichedChance: 50
- Level: 9
NormalChance: 20
EnrichedChance: 40
EventNormalChance: 20
EventEnrichedChance: 50
- Level: 10
NormalChance: 9
EnrichedChance: 20
EventNormalChance: 9
EventEnrichedChance: 35
WeaponLv1:
StatsPerLevel: 200
RandomBonusStartLevel: 8
RandomBonusValue: 300
Costs:
- Type: REFINE_COST_NORMAL
Price: 50
Material: 1010
- Type: REFINE_COST_ENRICHED
Price: 2000
Material: 7620
Rates:
- Level: 8
NormalChance: 60
EnrichedChance: 90
EventNormalChance: 60
EventEnrichedChance: 95
- Level: 9
NormalChance: 40
EnrichedChance: 70
EventNormalChance: 40
EventEnrichedChance: 85
- Level: 10
NormalChance: 19
EnrichedChance: 30
EventNormalChance: 19
EventEnrichedChance: 55
WeaponLv2:
StatsPerLevel: 300
RandomBonusStartLevel: 7
RandomBonusValue: 500
Costs:
- Type: REFINE_COST_NORMAL
Price: 200
Material: 1011
- Type: REFINE_COST_ENRICHED
Price: 2000
Material: 7620
Rates:
- Level: 7
NormalChance: 60
EnrichedChance: 90
EventNormalChance: 60
EventEnrichedChance: 95
- Level: 8
NormalChance: 40
EnrichedChance: 70
EventNormalChance: 40
EventEnrichedChance: 85
- Level: 9
NormalChance: 20
EnrichedChance: 40
EventNormalChance: 20
EventEnrichedChance: 60
- Level: 10
NormalChance: 19
EnrichedChance: 30
EventNormalChance: 19
EventEnrichedChance: 45
WeaponLv3:
StatsPerLevel: 500
RandomBonusStartLevel: 6
RandomBonusValue: 800
Costs:
- Type: REFINE_COST_NORMAL
Price: 5000
Material: 984
- Type: REFINE_COST_ENRICHED
Price: 2000
Material: 7620
Rates:
- Level: 6
NormalChance: 60
EnrichedChance: 90
EventNormalChance: 60
EventEnrichedChance: 95
- Level: 7
NormalChance: 50
EnrichedChance: 80
EventNormalChance: 50
EventEnrichedChance: 90
- Level: 8
NormalChance: 20
EnrichedChance: 40
EventNormalChance: 20
EventEnrichedChance: 70
- Level: 9
NormalChance: 20
EnrichedChance: 40
EventNormalChance: 20
EventEnrichedChance: 60
- Level: 10
NormalChance: 19
EnrichedChance: 30
EventNormalChance: 19
EventEnrichedChance: 45
WeaponLv4:
StatsPerLevel: 700
RandomBonusStartLevel: 5
RandomBonusValue: 1300
Costs:
- Type: REFINE_COST_NORMAL
Price: 20000
Material: 984
- Type: REFINE_COST_ENRICHED
Price: 2000
Material: 7620
Rates:
- Level: 5
NormalChance: 60
EnrichedChance: 90
EventNormalChance: 60
EventEnrichedChance: 95
- Level: 6
NormalChance: 40
EnrichedChance: 70
EventNormalChance: 40
EventEnrichedChance: 80
- Level: 7
NormalChance: 40
EnrichedChance: 70
EventNormalChance: 40
EventEnrichedChance: 80
- Level: 8
NormalChance: 20
EnrichedChance: 40
EventNormalChance: 20
EventEnrichedChance: 60
- Level: 9
NormalChance: 20
EnrichedChance: 40
EventNormalChance: 20
EventEnrichedChance: 50
- Level: 10
NormalChance: 9
EnrichedChance: 20
EventNormalChance: 9
EventEnrichedChance: 35
Shadow:
StatsPerLevel: 0
RandomBonusStartLevel: 0
RandomBonusValue: 0
Rates:
- Level: 5
NormalChance: 60
EnrichedChance: 90
EventNormalChance: 60
EventEnrichedChance: 95
- Level: 6
NormalChance: 40
EnrichedChance: 70
EventNormalChance: 40
EventEnrichedChance: 80
- Level: 7
NormalChance: 40
EnrichedChance: 70
EventNormalChance: 40
EventEnrichedChance: 80
- Level: 8
NormalChance: 20
EnrichedChance: 40
EventNormalChance: 20
EventEnrichedChance: 50
- Level: 9
NormalChance: 20
EnrichedChance: 40
EventNormalChance: 20
EventEnrichedChance: 50
- Level: 10
NormalChance: 9
EnrichedChance: 20
EventNormalChance: 9
EventEnrichedChance: 35

1999
db/re/refine.yml Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,614 +0,0 @@
# This file is a part of rAthena++.
# Copyright(C) 2021 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/>.
#
###########################################################################
# Renewal Refine Database
###########################################################################
Armor:
StatsPerLevel: 0
RandomBonusStartLevel: 0
RandomBonusValue: 0
Costs:
- Type: REFINE_COST_NORMAL
Price: 2000
Material: 985
- Type: REFINE_COST_OVER10
Price: 100000
Material: 6223
- Type: REFINE_COST_HD
Price: 20000
Material: 6241
- Type: REFINE_COST_ENRICHED
Price: 2000
Material: 7619
- Type: REFINE_COST_OVER10_HD
Price: 100000
Material: 6225
- Type: REFINE_COST_HOLINK
Price: 15000
Material: 7619
- Type: REFINE_COST_WAGJAK
Price: 20000
Material: 985
Rates:
- Level: 1
Bonus: 100
- Level: 2
Bonus: 100
- Level: 3
Bonus: 100
- Level: 4
Bonus: 100
- Level: 5
NormalChance: 60
EnrichedChance: 90
EventNormalChance: 60
EventEnrichedChance: 95
Bonus: 200
- Level: 6
NormalChance: 40
EnrichedChance: 70
EventNormalChance: 40
EventEnrichedChance: 80
Bonus: 200
- Level: 7
NormalChance: 40
EnrichedChance: 70
EventNormalChance: 40
EventEnrichedChance: 80
Bonus: 200
- Level: 8
NormalChance: 20
EnrichedChance: 40
EventNormalChance: 20
EventEnrichedChance: 50
Bonus: 200
- Level: 9
NormalChance: 20
EnrichedChance: 40
EventNormalChance: 20
EventEnrichedChance: 50
Bonus: 300
- Level: 10
NormalChance: 9
EnrichedChance: 20
EventNormalChance: 9
EventEnrichedChance: 35
Bonus: 300
- Level: 11
NormalChance: 8
EnrichedChance: 8
EventNormalChance: 20
EventEnrichedChance: 20
Bonus: 300
- Level: 12
NormalChance: 8
EnrichedChance: 8
EventNormalChance: 20
EventEnrichedChance: 20
Bonus: 300
- Level: 13
NormalChance: 8
EnrichedChance: 8
EventNormalChance: 16
EventEnrichedChance: 16
Bonus: 400
- Level: 14
NormalChance: 8
EnrichedChance: 8
EventNormalChance: 16
EventEnrichedChance: 16
Bonus: 400
- Level: 15
NormalChance: 7
EnrichedChance: 7
EventNormalChance: 15
EventEnrichedChance: 15
Bonus: 400
- Level: 16
NormalChance: 7
EnrichedChance: 7
EventNormalChance: 15
EventEnrichedChance: 15
Bonus: 400
- Level: 17
NormalChance: 7
EnrichedChance: 7
EventNormalChance: 14
EventEnrichedChance: 14
Bonus: 500
- Level: 18
NormalChance: 7
EnrichedChance: 7
EventNormalChance: 14
EventEnrichedChance: 14
Bonus: 500
- Level: 19
NormalChance: 5
EnrichedChance: 5
EventNormalChance: 10
EventEnrichedChance: 10
Bonus: 500
- Level: 20
NormalChance: 5
EnrichedChance: 5
EventNormalChance: 10
EventEnrichedChance: 10
Bonus: 500
WeaponLv1:
StatsPerLevel: 200
RandomBonusStartLevel: 8
RandomBonusValue: 300
Costs:
- Type: REFINE_COST_NORMAL
Price: 50
Material: 1010
- Type: REFINE_COST_OVER10
Price: 100000
Material: 6224
- Type: REFINE_COST_HD
Price: 20000
Material: 6240
- Type: REFINE_COST_ENRICHED
Price: 2000
Material: 7620
- Type: REFINE_COST_OVER10_HD
Price: 100000
Material: 6226
- Type: REFINE_COST_HOLINK
Price: 500
Material: 7620
- Type: REFINE_COST_WAGJAK
Price: 1000
Material: 1010
Rates:
- Level: 8
NormalChance: 60
EnrichedChance: 90
EventNormalChance: 60
EventEnrichedChance: 95
- Level: 9
NormalChance: 40
EnrichedChance: 70
EventNormalChance: 40
EventEnrichedChance: 85
- Level: 10
NormalChance: 19
EnrichedChance: 30
EventNormalChance: 19
EventEnrichedChance: 55
- Level: 11
NormalChance: 18
EnrichedChance: 18
EventNormalChance: 40
EventEnrichedChance: 40
- Level: 12
NormalChance: 18
EnrichedChance: 18
EventNormalChance: 40
EventEnrichedChance: 40
- Level: 13
NormalChance: 18
EnrichedChance: 18
EventNormalChance: 35
EventEnrichedChance: 35
- Level: 14
NormalChance: 18
EnrichedChance: 18
EventNormalChance: 35
EventEnrichedChance: 35
- Level: 15
NormalChance: 18
EnrichedChance: 18
EventNormalChance: 30
EventEnrichedChance: 30
- Level: 16
NormalChance: 17
EnrichedChance: 17
EventNormalChance: 30
EventEnrichedChance: 30
Bonus: 300
- Level: 17
NormalChance: 17
EnrichedChance: 17
EventNormalChance: 20
EventEnrichedChance: 20
Bonus: 300
- Level: 18
NormalChance: 17
EnrichedChance: 17
EventNormalChance: 20
EventEnrichedChance: 20
Bonus: 300
- Level: 19
NormalChance: 15
EnrichedChance: 15
EventNormalChance: 15
EventEnrichedChance: 15
Bonus: 300
- Level: 20
NormalChance: 15
EnrichedChance: 15
EventNormalChance: 15
EventEnrichedChance: 15
Bonus: 300
WeaponLv2:
StatsPerLevel: 300
RandomBonusStartLevel: 7
RandomBonusValue: 500
Costs:
- Type: REFINE_COST_NORMAL
Price: 200
Material: 1011
- Type: REFINE_COST_OVER10
Price: 100000
Material: 6224
- Type: REFINE_COST_HD
Price: 20000
Material: 6240
- Type: REFINE_COST_ENRICHED
Price: 2000
Material: 7620
- Type: REFINE_COST_OVER10_HD
Price: 100000
Material: 6226
- Type: REFINE_COST_HOLINK
Price: 2000
Material: 7620
- Type: REFINE_COST_WAGJAK
Price: 2000
Material: 1011
Rates:
- Level: 7
NormalChance: 60
EnrichedChance: 90
EventNormalChance: 60
EventEnrichedChance: 95
- Level: 8
NormalChance: 40
EnrichedChance: 70
EventNormalChance: 40
EventEnrichedChance: 85
- Level: 9
NormalChance: 20
EnrichedChance: 40
EventNormalChance: 20
EventEnrichedChance: 60
- Level: 10
NormalChance: 19
EnrichedChance: 30
EventNormalChance: 19
EventEnrichedChance: 45
- Level: 11
NormalChance: 18
EnrichedChance: 18
EventNormalChance: 40
EventEnrichedChance: 40
- Level: 12
NormalChance: 18
EnrichedChance: 18
EventNormalChance: 40
EventEnrichedChance: 40
- Level: 13
NormalChance: 18
EnrichedChance: 18
EventNormalChance: 35
EventEnrichedChance: 35
- Level: 14
NormalChance: 18
EnrichedChance: 18
EventNormalChance: 35
EventEnrichedChance: 35
- Level: 15
NormalChance: 18
EnrichedChance: 18
EventNormalChance: 30
EventEnrichedChance: 30
- Level: 16
NormalChance: 17
EnrichedChance: 17
EventNormalChance: 30
EventEnrichedChance: 30
Bonus: 600
- Level: 17
NormalChance: 17
EnrichedChance: 17
EventNormalChance: 20
EventEnrichedChance: 20
Bonus: 600
- Level: 18
NormalChance: 17
EnrichedChance: 17
EventNormalChance: 20
EventEnrichedChance: 20
Bonus: 600
- Level: 19
NormalChance: 15
EnrichedChance: 15
EventNormalChance: 15
EventEnrichedChance: 15
Bonus: 600
- Level: 20
NormalChance: 15
EnrichedChance: 15
EventNormalChance: 15
EventEnrichedChance: 15
Bonus: 600
WeaponLv3:
StatsPerLevel: 500
RandomBonusStartLevel: 6
RandomBonusValue: 800
Costs:
- Type: REFINE_COST_NORMAL
Price: 5000
Material: 984
- Type: REFINE_COST_OVER10
Price: 100000
Material: 6224
- Type: REFINE_COST_HD
Price: 20000
Material: 6240
- Type: REFINE_COST_ENRICHED
Price: 2000
Material: 7620
- Type: REFINE_COST_OVER10_HD
Price: 100000
Material: 6226
- Type: REFINE_COST_HOLINK
Price: 20000
Material: 7620
- Type: REFINE_COST_WAGJAK
Price: 10000
Material: 984
Rates:
- Level: 6
NormalChance: 60
EnrichedChance: 90
EventNormalChance: 60
EventEnrichedChance: 95
- Level: 7
NormalChance: 50
EnrichedChance: 80
EventNormalChance: 50
EventEnrichedChance: 90
- Level: 8
NormalChance: 20
EnrichedChance: 40
EventNormalChance: 20
EventEnrichedChance: 70
- Level: 9
NormalChance: 20
EnrichedChance: 40
EventNormalChance: 20
EventEnrichedChance: 60
- Level: 10
NormalChance: 19
EnrichedChance: 30
EventNormalChance: 19
EventEnrichedChance: 45
- Level: 11
NormalChance: 18
EnrichedChance: 18
EventNormalChance: 40
EventEnrichedChance: 40
- Level: 12
NormalChance: 18
EnrichedChance: 18
EventNormalChance: 40
EventEnrichedChance: 40
- Level: 13
NormalChance: 18
EnrichedChance: 18
EventNormalChance: 35
EventEnrichedChance: 35
- Level: 14
NormalChance: 18
EnrichedChance: 18
EventNormalChance: 35
EventEnrichedChance: 35
- Level: 15
NormalChance: 18
EnrichedChance: 18
EventNormalChance: 30
EventEnrichedChance: 30
- Level: 16
NormalChance: 17
EnrichedChance: 17
EventNormalChance: 30
EventEnrichedChance: 30
Bonus: 900
- Level: 17
NormalChance: 17
EnrichedChance: 17
EventNormalChance: 20
EventEnrichedChance: 20
Bonus: 900
- Level: 18
NormalChance: 17
EnrichedChance: 17
EventNormalChance: 20
EventEnrichedChance: 20
Bonus: 900
- Level: 19
NormalChance: 15
EnrichedChance: 15
EventNormalChance: 15
EventEnrichedChance: 15
Bonus: 900
- Level: 20
NormalChance: 15
EnrichedChance: 15
EventNormalChance: 15
EventEnrichedChance: 15
Bonus: 900
WeaponLv4:
StatsPerLevel: 700
RandomBonusStartLevel: 5
RandomBonusValue: 1400
Costs:
- Type: REFINE_COST_NORMAL
Price: 20000
Material: 984
- Type: REFINE_COST_OVER10
Price: 100000
Material: 6224
- Type: REFINE_COST_HD
Price: 20000
Material: 6240
- Type: REFINE_COST_ENRICHED
Price: 2000
Material: 7620
- Type: REFINE_COST_OVER10_HD
Price: 100000
Material: 6226
- Type: REFINE_COST_HOLINK
Price: 50000
Material: 7620
- Type: REFINE_COST_WAGJAK
Price: 20000
Material: 984
Rates:
- Level: 5
NormalChance: 60
EnrichedChance: 90
EventNormalChance: 60
EventEnrichedChance: 95
- Level: 6
NormalChance: 40
EnrichedChance: 70
EventNormalChance: 40
EventEnrichedChance: 80
- Level: 7
NormalChance: 40
EnrichedChance: 70
EventNormalChance: 40
EventEnrichedChance: 80
- Level: 8
NormalChance: 20
EnrichedChance: 40
EventNormalChance: 20
EventEnrichedChance: 60
- Level: 9
NormalChance: 20
EnrichedChance: 40
EventNormalChance: 20
EventEnrichedChance: 50
- Level: 10
NormalChance: 9
EnrichedChance: 20
EventNormalChance: 9
EventEnrichedChance: 35
- Level: 11
NormalChance: 8
EnrichedChance: 8
EventNormalChance: 20
EventEnrichedChance: 20
- Level: 12
NormalChance: 8
EnrichedChance: 8
EventNormalChance: 20
EventEnrichedChance: 20
- Level: 13
NormalChance: 8
EnrichedChance: 8
EventNormalChance: 16
EventEnrichedChance: 16
- Level: 14
NormalChance: 8
EnrichedChance: 8
EventNormalChance: 16
EventEnrichedChance: 16
- Level: 15
NormalChance: 7
EnrichedChance: 7
EventNormalChance: 15
EventEnrichedChance: 15
- Level: 16
NormalChance: 7
EnrichedChance: 7
EventNormalChance: 15
EventEnrichedChance: 15
Bonus: 1200
- Level: 17
NormalChance: 7
EnrichedChance: 7
EventNormalChance: 14
EventEnrichedChance: 14
Bonus: 1200
- Level: 18
NormalChance: 7
EnrichedChance: 7
EventNormalChance: 14
EventEnrichedChance: 14
Bonus: 1200
- Level: 19
NormalChance: 5
EnrichedChance: 5
EventNormalChance: 10
EventEnrichedChance: 10
Bonus: 1200
- Level: 20
NormalChance: 5
EnrichedChance: 5
EventNormalChance: 10
EventEnrichedChance: 10
Bonus: 1200
Shadow:
StatsPerLevel: 0
RandomBonusStartLevel: 0
RandomBonusValue: 0
Costs:
- Type: REFINE_COST_NORMAL
Price: 20000
Material: 985
- Type: REFINE_COST_HD
Price: 20000
Material: 6241
- Type: REFINE_COST_ENRICHED
Price: 20000
Material: 7619
Rates:
- Level: 5
NormalChance: 60
EnrichedChance: 90
EventNormalChance: 60
EventEnrichedChance: 95
- Level: 6
NormalChance: 40
EnrichedChance: 70
EventNormalChance: 40
EventEnrichedChance: 80
- Level: 7
NormalChance: 40
EnrichedChance: 70
EventNormalChance: 40
EventEnrichedChance: 80
- Level: 8
NormalChance: 20
EnrichedChance: 40
EventNormalChance: 20
EventEnrichedChance: 50
- Level: 9
NormalChance: 20
EnrichedChance: 40
EventNormalChance: 20
EventEnrichedChance: 50
- Level: 10
NormalChance: 9
EnrichedChance: 20
EventNormalChance: 9
EventEnrichedChance: 35

52
db/refine.yml Normal file
View File

@ -0,0 +1,52 @@
# This file is a part of rAthena.
# Copyright(C) 2021 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/>.
#
###########################################################################
# Refine Database
###########################################################################
#
# Refine Settings
#
###########################################################################
# - Group Refine item type.
# Levels: Refinement settings per item level. (Default: null)
# - Level Item level.
# RefineLevels: Refinement settings per refine level. (Default: null)
# - Level Refine level.
# Bonus Refinement bonus. (Default: 0)
# RandomBonus Extra refinement bonus of 0~RandomBonus stacked on Bonus. (Default: 0)
# BlacksmithBlessingAmount Amount of Blacksmith Blessing required. (Default: 0)
# Chances: Success chance based on cost type. (Default: null)
# - Type Refinement cost type based on ore used.
# Rate Chance of success out of 0~100. (Default: 0)
# Price Amount of zeny required to refine. (Default: 0)
# Material Ore item required to refine. (Default: 0)
# BreakingRate Chance of item breaking out of 0~100. (Default: 0)
# DowngradeAmount Number of refine levels reduced on failure. (Default: 0)
###########################################################################
Header:
Type: REFINE_DB
Version: 1
Footer:
Imports:
- Path: db/pre-re/refine.yml
Mode: Prerenewal
- Path: db/re/refine.yml
Mode: Renewal
- Path: db/import/refine.yml

View File

@ -1229,6 +1229,14 @@ Adopts the specified player with the attached character as one of the parents.
---------------------------------------
@refineui
Opens the refine user interface.
Note: This command requires packet version 2016-10-12 or newer.
---------------------------------------
@request <message>
Sends a message to all connected GMs (via the GM whisper system).

View File

@ -2852,12 +2852,8 @@ passed arguments <type> and <information>.
Valid cost types are:
REFINE_COST_NORMAL - For normal refining
REFINE_COST_OVER10 - For refining over +10
REFINE_COST_HD - For refining with HD ores
REFINE_COST_ENRICHED - For refining with enriched ores
REFINE_COST_OVER10_HD - For refining over +10 with HD ores
REFINE_COST_HOLINK - For refining at Holink in Malangdo
REFINE_COST_WAGJAK - For refining at Refining Machine Wagjak in the Novice Academy
This function will return required cost for refining based on <information> argument.
@ -2867,7 +2863,15 @@ REFINE_ZENY_COST - Zeny
REFINE_MATERIAL_ID - Material Item ID
This function will return -1 on failure. The function fails if the cost type
is invalid or if there is no item in the equipment slot.
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.
---------------------------------------

View File

@ -16,6 +16,7 @@
//= 3.2a Added 'disable_items' command. [Euphy]
//= 3.3 Some official script updates. [Euphy]
//= 3.4 Added VIP features. [Euphy]
//= 3.5 Added Refine UI [Atemo, Lemongrass]
//============================================================
// Christopher: Geffen Blacksmith
@ -522,33 +523,102 @@ ein_in01,38,29,0 script Paul Spanner 63,{
// Weapon/Armor Refiners
//============================================================
prt_in,63,60,0 script Hollgrehenn 85,{
callfunc "refinemain","Hollgrehenn",0;
end;
prt_in,63,60,0 script Hollgrehenn 4_M_03,{
if( getbattleflag( "feature.refineui" ) ){
mes "[Hollgrehenn]";
mes "I'm a blacksmith who can refine weapons and equipment.";
mes "Do you have any items that you'd like to refine?";
close2;
refineui();
end;
}else{
callfunc "refinemain","Hollgrehenn",0;
end;
}
}
morocc_in,73,38,6 script Aragham 99,{
callfunc "refinemain","Aragham",0;
end;
morocc_in,73,38,6 script Aragham 4W_M_03,{
if( getbattleflag( "feature.refineui" ) ){
mes "[Aragham]";
mes "De~ sert~ Blacksmith~";
mes "Aragham Ssaleh~ who can refine anything Ssaleh~";
mes "Let me see what you'd like to refine~";
close2;
refineui();
end;
}else{
callfunc "refinemain","Aragham",0;
end;
}
}
payon,144,173,5 script Antonio 88,{
callfunc "refinemain","Antonio",0;
end;
payon,144,173,5 script Antonio 4_M_ORIENT01,{
if( getbattleflag( "feature.refineui" ) ){
mes "[Antonio]";
mes "Stop nagging and get me the equipment you want to refine.";
close2;
refineui();
end;
}else{
callfunc "refinemain","Antonio",0;
end;
}
}
alberta_in,28,58,0 script Fredrik 85,{
callfunc "refinemain","Fredrik",0;
end;
alberta_in,28,58,0 script Fredrik 4_M_03,{
if( getbattleflag( "feature.refineui" ) ){
mes "[Fredrik Hermanthorn]";
mes "I am a blacksmith who can refine your weapon or equipment.";
mes "Do you have anything that you'd like to refine?";
close2;
refineui();
end;
}else{
callfunc "refinemain","Fredrik",0;
end;
}
}
yuno_in01,171,21,4 script Lambert 88,{
callfunc "refinemain","Lambert",0;
end;
yuno_in01,171,21,4 script Lambert 4_M_ORIENT01,{
if( getbattleflag( "feature.refineui" ) ){
mes "[Lambert]";
mes "Wel...come... This is... the best... smithy... in Juno.";
close2;
refineui();
end;
}else{
callfunc "refinemain","Lambert",0;
end;
}
}
ein_in01,24,87,5 script Manthasman 826,{
callfunc "refinemain","Manthasman Pruhag",0;
end;
ein_in01,24,87,5 script Manthasman 4_M_DWARF,{
if( getbattleflag( "feature.refineui" ) ){
mes "[Manthasman Pruhag]";
mes "Hahaha, you already knew it. So you'd like to refine something?";
mes "Let's try something risky today!";
close2;
refineui();
end;
}else{
callfunc "refinemain","Manthasman Pruhag",0;
end;
}
}
lhz_in02,282,20,7 script Fulerr 869,{
callfunc "refinemain","Fulerr",0;
end;
lhz_in02,282,20,7 script Fulerr 4_M_LGTMAN,{
if( getbattleflag( "feature.refineui" ) ){
mes "[Fulerr]";
mes "Hehe... You wanna refine?";
mes "Hehe.. Consider it done..";
mes "Hehe....";
close2;
refineui();
end;
}else{
callfunc "refinemain","Fulerr",0;
end;
}
}
//============================================================

View File

@ -12871,13 +12871,33 @@ izlude_d,153,126,1 duplicate(Refinery Owner Han#iz) Refinery Owner Han#iz_d 4_M_
}
}
.@price = getequiprefinecost(.@part, REFINE_COST_WAGJAK, REFINE_ZENY_COST);
.@material = getequiprefinecost(.@part, REFINE_COST_WAGJAK, REFINE_MATERIAL_ID);
// Wagjak has different hardcoded prices
// .@price = getequiprefinecost(.@part, REFINE_COST_NORMAL, REFINE_ZENY_COST);
.@material = getequiprefinecost(.@part, REFINE_COST_NORMAL, REFINE_MATERIAL_ID);
if ((getequipweaponlv(.@part) >= 1) && (getequipweaponlv(.@part) <= 4))
.@type$ = "Level " + getequipweaponlv(.@part) + " weapon";
else
switch(getequipweaponlv(.@part)) {
default:
case 0: // Armor
.@price = 20000;
.@type$ = "Armor";
break;
case 1: // Level 1 Weapon
.@price = 1000;
.@type$ = "Level 1 weapon";
break;
case 2: // Level 2 Weapon
.@price = 2000;
.@type$ = "Level 2 weapon";
break;
case 3: // Level 3 Weapon
.@price = 10000;
.@type$ = "Level 3 weapon";
break;
case 4: // Level 4 Weapon
.@price = 20000;
.@type$ = "Level 4 weapon";
break;
}
mes "[Refining Machine Wagjak]";
mes "Type : "+ .@type$ +"";

View File

@ -73,29 +73,35 @@ malangdo,221,174,6 script Holink#mal_cash 559,{
.@refineitemid = getequipid(.@part); // save id of the item
.@refinerycnt = getequiprefinerycnt(.@part); //save refinery count
setarray .@card[0], getequipcardid(.@part,0), getequipcardid(.@part,1), getequipcardid(.@part,2), getequipcardid(.@part,3);
.@price = getequiprefinecost(.@part, REFINE_COST_HOLINK, REFINE_ZENY_COST);
.@material = getequiprefinecost(.@part, REFINE_COST_HOLINK, REFINE_MATERIAL_ID);
// Holink has different hardcoded prices
// .@price = getequiprefinecost(.@part, REFINE_COST_NORMAL, REFINE_ZENY_COST);
.@material = getequiprefinecost(.@part, REFINE_COST_NORMAL, REFINE_MATERIAL_ID);
switch(getequipweaponlv(.@part)) {
default:
case 0: // Armor
.@type$ = "armor";
.@price = 15000;
mes "You have chosen an armor, meow~";
break;
case 1: // Level 1 Weapon
.@type$ = "weapon";
.@price = 500;
mes "A level 1 weapon...?";
break;
case 2: // Level 2 Weapon
.@type$ = "weapon";
.@price = 2000;
mes "Meow, a level 2 weapon...?";
break;
case 3: // Level 3 Weapon
.@type$ = "weapon";
.@price = 20000;
mes "Meow Meow~~ A level 3 weapon~~";
break;
case 4: // Level 4 Weapon
.@type$ = "weapon";
.@price = 50000;
mes "Me-Meow!... A level 4 weapon...!";
mes "I've only seen it twice while";
mes "learning from Aragam... Me-Meow!!";

View File

@ -1,4 +1,4 @@
//===== rAthena Script =======================================
//===== rAthena Script =======================================
//= HD Refiners
//===== Description: =========================================
//= [Official Conversion]
@ -28,9 +28,9 @@
mes "So lets kick this into overdrive, what d' ya say? What item do you want to refine?";
next;
setarray .@indices[1], EQI_HEAD_TOP, EQI_ARMOR, EQI_HAND_L, EQI_HAND_R, EQI_GARMENT, EQI_SHOES, EQI_ACC_L, EQI_ACC_R, EQI_HEAD_MID, EQI_HEAD_LOW;
for(set .@i,1; .@i<=10; set .@i,.@i+1)
set .@menu$, .@menu$ + ( getequipisequiped(.@indices[.@i]) ? getequipname(.@indices[.@i]) : F_getpositionname(.@indices[.@i]) +"-[Not equipped]" ) +":";
set .@part, .@indices[ select(.@menu$) ];
for ( .@i = 1; .@i <= 10; ++.@i )
.@menu$ = .@menu$ + ( getequipisequiped(.@indices[.@i]) ? getequipname(.@indices[.@i]) : F_getpositionname(.@indices[.@i]) + "-[Not equipped]" ) + ":";
.@part = .@indices[ select(.@menu$) ];
if (!getequipisequiped(.@part)) {
mes "[Blacksmith Mighty Hammer]";
switch(.@part) {
@ -68,23 +68,33 @@
mes "This item can't be refined.";
close;
}
if (getequiprefinerycnt(.@part) < 7 || getequiprefinerycnt(.@part) > 9) {
switch( getequiprefinerycnt(.@part) ) {
case 7:
.@blacksmith_blessing_count = 1;
break;
case 8:
.@blacksmith_blessing_count = 2;
break;
case 9:
.@blacksmith_blessing_count = 4;
break;
default:
mes "[Blacksmith Mighty Hammer]";
mes "I only handle items with refine levels from +7 to +9.";
close;
}
.@refineitemid = getequipid(.@part); // save id of the item
.@refinerycnt = getequiprefinerycnt(.@part); //save refinery count
setarray .@card[0], getequipcardid(.@part,0), getequipcardid(.@part,1), getequipcardid(.@part,2), getequipcardid(.@part,3);
.@price = getequiprefinecost(.@part, REFINE_COST_HD, REFINE_ZENY_COST);
.@material = getequiprefinecost(.@part, REFINE_COST_HD, REFINE_MATERIAL_ID);
mes "[Blacksmith Mighty Hammer]";
mes "In order to refine the gear you selected you need ^ff9999"+getitemname(.@material)+"^000000 and 20,000 zeny as a fee.";
mes "In order to refine the gear you selected you need ^ff9999" + getitemname(.@material) + "^000000 and 20,000 zeny as a fee.";
mes "Do you have them ready?";
next;
if(select("Yes:No") == 2) {
if (select("Yes:No") == 2) {
mes "[Blacksmith Mighty Hammer]";
mes "I will wait until you are ready.";
close;
@ -95,19 +105,43 @@
mes "Well, even if it fails, it only decreases by 1 refine level.";
mes "Would you like to continue refining?";
next;
if(select("Yes:No") == 2) {
if (countitem(6635) < .@blacksmith_blessing_count)
setarray .@menu$[1], "Yes", "Not yet";
else {
mes "[Blacksmith Mighty Hammer]";
mes "Ah! Is it the ^0000ffBlacksmith Blessing^000000?";
mes "With the Blacksmith Blessing, the equipment won't vanish if the refine fails!";
next;
mes "[Blacksmith Mighty Hammer]";
.@weapon_lvl = getequipweaponlv(.@part);
if (.@weapon_lvl < 1 || .@weapon_lvl > 4)
mes "For +" + getequiprefinerycnt(.@part) + " equipment, refine with^316AC5 " + .@blacksmith_blessing_count + " unit(s) Blacksmith Blessing^000000 can prevent the equipment from vanishing. Do you want use it to refine?";
else
mes "For +" + getequiprefinerycnt(.@part) + " weapon, refine with^316AC5 " + .@blacksmith_blessing_count + " unit(s) Blacksmith Blessing^000000 can prevent the equipment from vanishing. Do you want use it to refine?";
next;
setarray .@menu$[0], "Use it to refine", "Refine directly without it", "Don't refine yet";
}
switch( select(.@menu$[0], .@menu$[1], .@menu$[2]) ) {
case 1:
.@bless_who = 1;
break;
case 2:
break;
case 3:
mes "[Blacksmith Mighty Hammer]";
mes "Only those who overcome fear of failure will obtain a masterpiece.";
close;
}
}
if (countitem(.@material) == 0 || Zeny < .@price) {
if ((.@bless_who && countitem(6635) < .@blacksmith_blessing_count) || countitem(.@material) == 0 || Zeny < .@price) {
mes "[Blacksmith Mighty Hammer]";
mes "Didn't you just say you had everything ready?";
close;
}
if (.@bless_who)
delitem 6635, .@blacksmith_blessing_count;
delitem .@material,1;
set Zeny, Zeny-.@price;
Zeny = Zeny - .@price;
// anti-hack
if (callfunc("F_IsEquipIDHack", .@part, .@refineitemid) || callfunc("F_IsEquipCardHack", .@part, .@card[0], .@card[1], .@card[2], .@card[3]) ||
@ -131,6 +165,17 @@
mes "Here, have it. Refine succeeded flawlessly!";
close;
}
if (.@bless_who == 1) {
specialeffect EF_HOLYHIT;
next;
emotion ET_HUK;
mes "[Blacksmith Mighty Hammer]";
mes "What?!!";
next;
mes "[Blacksmith Mighty Hammer]";
mes "Aiya! I am faceless now. HmHm.";
close;
}
downrefitem .@part;
next;
emotion ET_HUK;
@ -141,16 +186,16 @@
mes "I am sure a person like you would never blame me for a decrease in refine level by 1. Hmm.";
close;
}
prt_in,59,54,3 duplicate(MightyHammer) Mighty Hammer#prt 826
morocc_in,65,30,3 duplicate(MightyHammer) Mighty Hammer#morocc 826
payon,148,176,3 duplicate(MightyHammer) Mighty Hammer#pay 826
alberta_in,16,56,3 duplicate(MightyHammer) Mighty Hammer#alb 826
yuno_in01,171,18,3 duplicate(MightyHammer) Mighty Hammer#yuno 826
ein_in01,22,82,3 duplicate(MightyHammer) Mighty Hammer#ein 826
lhz_in02,280,19,3 duplicate(MightyHammer) Mighty Hammer#lhz 826
prt_in,59,54,3 duplicate(MightyHammer) Mighty Hammer#prt 4_M_DWARF
morocc_in,65,30,3 duplicate(MightyHammer) Mighty Hammer#morocc 4_M_DWARF
payon,148,176,3 duplicate(MightyHammer) Mighty Hammer#pay 4_M_DWARF
alberta_in,16,56,3 duplicate(MightyHammer) Mighty Hammer#alb 4_M_DWARF
yuno_in01,171,18,3 duplicate(MightyHammer) Mighty Hammer#yuno 4_M_DWARF
ein_in01,22,82,3 duplicate(MightyHammer) Mighty Hammer#ein 4_M_DWARF
lhz_in02,280,19,3 duplicate(MightyHammer) Mighty Hammer#lhz 4_M_DWARF
// iRO NPC locations:
// payon,174,133,4 duplicate(MightyHammer) Mighty Hammer#im 826
// payon,174,133,4 duplicate(MightyHammer) Mighty Hammer#im 4_M_DWARF
// Basta (+10 and up) :: cash_smelting
//============================================================
@ -165,9 +210,9 @@ lhz_in02,280,19,3 duplicate(MightyHammer) Mighty Hammer#lhz 826
mes "Which equipment do you want to refine?";
next;
setarray .@indices[1], EQI_HEAD_TOP, EQI_ARMOR, EQI_HAND_L, EQI_HAND_R, EQI_GARMENT, EQI_SHOES, EQI_ACC_L, EQI_ACC_R, EQI_HEAD_MID, EQI_HEAD_LOW;
for(set .@i,1; .@i<=10; set .@i,.@i+1)
set .@menu$, .@menu$ + ( getequipisequiped(.@indices[.@i]) ? getequipname(.@indices[.@i]) : F_getpositionname(.@indices[.@i]) +"-[Unequipped]" ) +":";
set .@part, .@indices[ select(.@menu$) ];
for ( .@i = 1; .@i <= 10; ++.@i )
.@menu$ = .@menu$ + ( getequipisequiped(.@indices[.@i]) ? getequipname(.@indices[.@i]) : F_getpositionname(.@indices[.@i]) + "-[Unequipped]" ) + ":";
.@part = .@indices[ select(.@menu$) ];
if (!getequipisequiped(.@part)) {
mes "[Basta]";
switch(.@part) {
@ -205,12 +250,17 @@ lhz_in02,280,19,3 duplicate(MightyHammer) Mighty Hammer#lhz 826
mes "Even I cannot refine this item. There's no way.";
close;
}
if (getequiprefinerycnt(.@part) < 10) {
.@refine_count = getequiprefinerycnt(.@part);
if (.@refine_count < 10) {
mes "[Basta]";
mes "Haven't I told you? I only refine equipments that are +10 and above.";
close;
}
if (getequiprefinerycnt(.@part) == 20) {
else if (.@refine_count == 10)
.@blacksmith_blessing_count = 7;
else if (.@refine_count == 11)
.@blacksmith_blessing_count = 11;
else if (.@refine_count == 20) {
mes "[Basta]";
mes "This weapon is perfect, no need to refine it anymore~";
close;
@ -218,33 +268,27 @@ lhz_in02,280,19,3 duplicate(MightyHammer) Mighty Hammer#lhz 826
.@refineitemid = getequipid(.@part); // save id of the item
.@refinerycnt = getequiprefinerycnt(.@part); //save refinery count
setarray .@card[0], getequipcardid(.@part,0), getequipcardid(.@part,1), getequipcardid(.@part,2), getequipcardid(.@part,3);
.@price = getequiprefinecost(.@part, REFINE_COST_OVER10_HD, REFINE_ZENY_COST);
.@material = getequiprefinecost(.@part, REFINE_COST_OVER10_HD, REFINE_MATERIAL_ID);
switch(getequipweaponlv(.@part)) {
default:
case 0:
set .@type$,"armor";
break;
case 1:
case 2:
case 3:
case 4:
set .@type$,"weapon";
break;
}
.@price = getequiprefinecost(.@part, REFINE_COST_HD, REFINE_ZENY_COST);
.@material = getequiprefinecost(.@part, REFINE_COST_HD, REFINE_MATERIAL_ID);
.@weapon_lvl = getequipweaponlv(.@part);
if (.@weapon_lvl < 1 || .@weapon_lvl > 4)
.@type$ = "armor";
else
.@type$ = "weapon";
mes "[Basta]";
mes "Hmm... is this the one you want to refine?";
mes "To refine this equipment, I need 1 ^ff9999"+getitemname(.@material)+"^000000 and " + callfunc("F_InsertComma",.@price) + " zeny as a fee.";
mes "To refine this equipment, I need 1 ^ff9999" + getitemname(.@material) + "^000000 and " + callfunc("F_InsertComma",.@price) + " zeny as a fee.";
mes "Do you really want to refine this?";
next;
if(select("Yes:No") == 2) {
if (select("Yes:No") == 2) {
mes "[Basta]";
mes "Okay. If that's what you want...";
close;
}
if (getequippercentrefinery(.@part, true) < 100) {
mes "[Basta]";
mes "This "+.@type$+" has already been refined pretty high.";
mes "This " + .@type$ + " has already been refined pretty high.";
mes "If you try to refine it more, the refine level could decrease.";
next;
mes "[Basta]";
@ -252,25 +296,45 @@ lhz_in02,280,19,3 duplicate(MightyHammer) Mighty Hammer#lhz 826
mes "It is impossible that the refine level will drop by, say, 3 or 4... that sounds scary.";
mes "Here it can only decrease by 1 level.";
next;
mes "[Basta]";
mes "Compared to other blacksmiths, the risk is smaller.";
mes "I've given all precautions. Do you want to try it?";
next;
if(select("Yes:No") == 2) {
if (.@blacksmith_blessing_count == 0 || countitem(6635) < .@blacksmith_blessing_count) {
mes "[Basta]";
mes "Compared to other blacksmiths, the risk is smaller.";
mes "I've given all precautions. Do you want to try it?";
next;
setarray .@menu$[1], "Yes", "No";
}
else {
mes "[Basta]";
mes "Woah~ Is it the ^316AC5Blacksmith Blessing^000000? It is difficult to get~ But, you have it!";
next;
mes "[Basta]";
mes "For +" + .@refine_count + " " + .@type$ + " need ^316AC5" + .@blacksmith_blessing_count + " unit(s) Blacksmith Blessing^000000 can prevent the equipment from vanishing. Do you want to refine with Blacksmith Blessing?";
next;
setarray .@menu$[0], "Refine with Blacksmith Blessing", "Refine without Blacksmith Blessing", "Don't refine yet";
}
switch( select(.@menu$[0], .@menu$[1], .@menu$[2]) ) {
case 1:
.@bless_who = 1;
break;
case 2:
break;
case 3:
mes "[Basta]";
mes "Well~";
mes "Not challenging at all could also be a kind of wisdom in life.";
close;
}
}
if (countitem(.@material) == 0 || Zeny < .@price) {
if ((.@bless_who && countitem(6635) < .@blacksmith_blessing_count) || countitem(.@material) == 0 || Zeny < .@price) {
mes "[Basta]";
mes "Hmm... You didn't bring all the materials needed.";
mes "Come back when you have them all.";
close;
}
if (.@bless_who)
delitem 6635, .@blacksmith_blessing_count;
delitem .@material,1;
set Zeny, Zeny-.@price;
Zeny = Zeny - .@price;
// anti-hack
if (callfunc("F_IsEquipIDHack", .@part, .@refineitemid) || callfunc("F_IsEquipCardHack", .@part, .@card[0], .@card[1], .@card[2], .@card[3]) ||
@ -293,26 +357,52 @@ lhz_in02,280,19,3 duplicate(MightyHammer) Mighty Hammer#lhz 826
mes "I really am the best blacksmith in the whole wide world!";
close;
}
downrefitem .@part;
next;
emotion (!rand(5))?ET_MONEY:ET_HUK;
mes "[Basta]";
mes "Aaaaaaaaaaak!!!";
next;
mes "[Basta]";
mes "Damn it!";
mes "Refining failed and refine level has decreased!";
mes "Even the best blacksmith in the world doesn't guarantee 100% success!";
if (.@bless_who == 1) {
specialeffect EF_HOLYHIT;
next;
emotion (!rand(5))?ET_MONEY:ET_HUK;
mes "[Basta]";
mes "Aaaaaaaaaaak!!!";
next;
mes "[Basta]";
mes "Refining has failed!";
mes "The best blacksmith in the world like me...";
mes "doesn't guarantee 100% success~";
}
else {
downrefitem .@part;
next;
emotion (!rand(5))?ET_MONEY:ET_HUK;
mes "[Basta]";
mes "Aaaaaaaaaaak!!!";
next;
mes "[Basta]";
mes "Damn it!";
mes "Refining has failed and refine level has decreased!";
mes "Even the best blacksmith in the world doesn't guarantee 100% success!";
}
mes "Too bad.";
next;
mes "[Basta]";
mes "I'll do better next time! Don't worry!";
close;
}
prt_in,57,54,3 duplicate(Basta) Basta#prt 826
morocc_in,68,30,3 duplicate(Basta) Basta#morocc 826
payon,148,174,3 duplicate(Basta) Basta#payon 826
alberta_in,18,56,3 duplicate(Basta) Basta#alberta 826
yuno_in01,173,18,3 duplicate(Basta) Basta#yuno 826
ein_in01,24,82,3 duplicate(Basta) Basta#einbroch 826
lhz_in02,280,17,3 duplicate(Basta) Basta#lighthalzen 826
prt_in,57,54,3 duplicate(Basta) Basta#prt 4_M_DWARF
morocc_in,68,30,3 duplicate(Basta) Basta#morocc 4_M_DWARF
payon,148,174,3 duplicate(Basta) Basta#payon 4_M_DWARF
alberta_in,18,56,3 duplicate(Basta) Basta#alberta 4_M_DWARF
yuno_in01,173,18,3 duplicate(Basta) Basta#yuno 4_M_DWARF
ein_in01,24,82,3 duplicate(Basta) Basta#einbroch 4_M_DWARF
lhz_in02,280,17,3 duplicate(Basta) Basta#lighthalzen 4_M_DWARF
// Refine UI makes these NPCs useless
- script RefineUI_Init -1,{
end;
OnInit:
if (getbattleflag("feature.refineui")) {
unloadnpc "Basta";
unloadnpc "MightyHammer";
}
end;
}

View File

@ -16,23 +16,27 @@
//= The safe/multiple refine feature is now functional. [Euphy]
//= 1.3 Updated to match the latest official script. [Euphy]
//= 1.4 Added correct safe refines. [Haruna]
//= 1.5 Added Refine UI [Atemo, Lemongrass]
//============================================================
// +11 and above Refiners
//============================================================
prt_in,90,72,5 script Vestri#prt 826,{
callfunc "refinenew","Vestri",0;
end;
}
morocc_in,64,41,5 script Vestri#moc 826,{
callfunc "refinenew","Vestri",0;
end;
}
payon_in01,18,132,3 script Vestri#pay 826,{
callfunc "refinenew","Vestri",0;
end;
prt_in,90,72,5 script Vestri#prt 4_M_DWARF,{
if( getbattleflag( "feature.refineui" ) ){
mes "[Vestri]";
mes "I'm the most skillful blacksmith!";
close2;
refineui();
end;
}else{
callfunc "refinenew","Vestri",0;
end;
}
}
morocc_in,64,41,5 duplicate(Vestri#prt) Vestri#moc 4_M_DWARF
payon_in01,18,132,3 duplicate(Vestri#prt) Vestri#pay 4_M_DWARF
//============================================================
// +11 and above Refiner Function
//============================================================
@ -101,8 +105,8 @@ function script refinenew {
}
.@refineitemid = getequipid(.@part); // save id of the item
setarray .@card[0], getequipcardid(.@part,0), getequipcardid(.@part,1), getequipcardid(.@part,2), getequipcardid(.@part,3);
.@price = getequiprefinecost(.@part, REFINE_COST_OVER10, REFINE_ZENY_COST);
.@material = getequiprefinecost(.@part, REFINE_COST_OVER10, REFINE_MATERIAL_ID);
.@price = getequiprefinecost(.@part, REFINE_COST_NORMAL, REFINE_ZENY_COST);
.@material = getequiprefinecost(.@part, REFINE_COST_NORMAL, REFINE_MATERIAL_ID);
.@safe = 10;
if (getequipweaponlv(.@part) >= 1 && getequipweaponlv(.@part) <= 4) {

View File

@ -7,8 +7,16 @@
//= 1.0 First version [Aleos]
//= 1.1 Removed re-roll behavior and fetch materials from db
//= [Secret]
//= 1.2 Added Refine UI [Atemo, Lemongrass]
//============================================================
- script ::ShadowBlacksmith -1,{
if( getbattleflag( "feature.refineui" ) ){
mes "[Shadow Blacksmith]";
mes "Now Basta is in charge of refinement for shadow items.";
mes "If you'd like to refine a shadow item, please visit him.";
close;
}
.@zeny_cost = 200000; // Zeny cost is 200,000 according to official script [Secret]
disable_items;
mes "[Shadow Blacksmith]";

View File

@ -88,6 +88,14 @@ typedef uint32 t_itemid;
#define MAX_CLAN 500
#define MAX_CLANALLIANCE 6
#ifdef RENEWAL
#define MAX_WEAPON_LEVEL 5
#define MAX_ARMOR_LEVEL 2
#else
#define MAX_WEAPON_LEVEL 4
#define MAX_ARMOR_LEVEL 1
#endif
// for produce
#define MIN_ATTRIBUTE 0
#define MAX_ATTRIBUTE 4

View File

@ -10342,6 +10342,33 @@ ACMD_FUNC(quest) {
return 0;
}
/**
* Opens the refineUI
* Usage: @refineui
*/
ACMD_FUNC(refineui)
{
nullpo_retr(-1, sd);
#if PACKETVER < 20161012
clif_displaymessage(fd, msg_txt(sd, 773)); // This command requires packet version 2016-10-12 or newer.
return -1;
#else
if( !battle_config.feature_refineui ){
clif_displaymessage(fd, msg_txt(sd, 774)); // This command is disabled via configuration.
return -1;
}
if( sd->state.refineui_open ){
clif_displaymessage(fd, msg_txt(sd, 775)); // You have already opened the refine UI.
return -1;
}
clif_refineui_open(sd);
return 0;
#endif
}
#include "../custom/atcommand.inc"
/**
@ -10650,6 +10677,7 @@ void atcommand_basecommands(void) {
ACMD_DEF2("erasequest", quest),
ACMD_DEF2("completequest", quest),
ACMD_DEF2("checkquest", quest),
ACMD_DEF(refineui),
};
AtCommandInfo* atcommand;
int i;

View File

@ -9115,7 +9115,6 @@ static const struct _battle_data {
{ "guild_alliance_onlygm", &battle_config.guild_alliance_onlygm, 0, 0, 1, },
{ "feature.achievement", &battle_config.feature_achievement, 1, 0, 1, },
{ "allow_bound_sell", &battle_config.allow_bound_sell, 0, 0, 0xF, },
{ "event_refine_chance", &battle_config.event_refine_chance, 0, 0, 1, },
{ "autoloot_adjust", &battle_config.autoloot_adjust, 0, 0, 1, },
{ "feature.petevolution", &battle_config.feature_petevolution, 1, 0, 1, },
{ "feature.petautofeed", &battle_config.feature_pet_autofeed, 1, 0, 1, },
@ -9161,6 +9160,7 @@ static const struct _battle_data {
{ "mercenary_autoloot", &battle_config.mercenary_autoloot, 0, 0, 1, },
{ "mer_idle_no_share" , &battle_config.mer_idle_no_share, 0, 0, INT_MAX, },
{ "idletime_mer_option", &battle_config.idletime_mer_option, 0x1F, 0x1, 0xFFF, },
{ "feature.refineui", &battle_config.feature_refineui, 1, 0, 1, },
#include "../custom/battle_config_init.inc"
};
@ -9310,6 +9310,13 @@ void battle_adjust_conf()
}
#endif
#if PACKETVER < 20161012
if (battle_config.feature_refineui) {
ShowWarning("conf/battle/feature.conf refine UI is enabled but it requires PACKETVER 2016-10-12 or newer, disabling...\n");
battle_config.feature_refineui = 0;
}
#endif
#if PACKETVER < 20170208
if (battle_config.feature_equipswitch) {
ShowWarning("conf/battle/feature.conf equip switch is enabled but it requires PACKETVER 2017-02-08 or newer, disabling...\n");

View File

@ -646,7 +646,6 @@ struct Battle_Config
int guild_alliance_onlygm;
int feature_achievement;
int allow_bound_sell;
int event_refine_chance;
int autoloot_adjust;
int feature_petevolution;
int feature_pet_autofeed;
@ -692,6 +691,7 @@ struct Battle_Config
int mercenary_autoloot;
int mer_idle_no_share;
int idletime_mer_option;
int feature_refineui;
#include "../custom/battle_config_struct.inc"
};

View File

@ -20980,7 +20980,7 @@ void clif_parse_sale_remove( int fd, struct map_session_data* sd ){
/**
* Sends all achievement data to the client (ZC_ALL_ACH_LIST).
* 0a23 <packetType>.W <packetLength>.W <ACHCount>.L <ACHPoint>.L
* 0a23 <packetLength>.W <ACHCount>.L <ACHPoint>.L
*/
void clif_achievement_list_all(struct map_session_data *sd)
{
@ -21022,7 +21022,7 @@ void clif_achievement_list_all(struct map_session_data *sd)
/**
* Sends a single achievement's data to the client (ZC_ACH_UPDATE).
* 0a24 <packetType>.W <ACHPoint>.L
* 0a24 <ACHPoint>.L
*/
void clif_achievement_update(struct map_session_data *sd, struct achievement *ach, int count)
{
@ -21056,7 +21056,7 @@ void clif_achievement_update(struct map_session_data *sd, struct achievement *ac
/**
* Checks if an achievement reward can be rewarded (CZ_REQ_ACH_REWARD).
* 0a25 <packetType>.W <achievementID>.L
* 0a25 <achievementID>.L
*/
void clif_parse_AchievementCheckReward(int fd, struct map_session_data *sd)
{
@ -21070,7 +21070,7 @@ void clif_parse_AchievementCheckReward(int fd, struct map_session_data *sd)
/**
* Returns the result of achievement_check_reward (ZC_REQ_ACH_REWARD_ACK).
* 0a26 <packetType>.W <result>.W <achievementID>.L
* 0a26 <result>.W <achievementID>.L
*/
void clif_achievement_reward_ack(int fd, unsigned char result, int achievement_id)
{
@ -21670,6 +21670,286 @@ TIMER_FUNC( clif_ping_timer ){
return 0;
}
/**
* Opens the refine UI on the designated client.
* 0aa0
*/
void clif_refineui_open( struct map_session_data* sd ){
#if PACKETVER >= 20161012
nullpo_retv( sd );
struct PACKET_ZC_REFINE_OPEN_WINDOW p;
p.packetType = HEADER_ZC_REFINE_OPEN_WINDOW;
clif_send( &p, sizeof( p ), &sd->bl, SELF );
sd->state.refineui_open = true;
#endif
}
/**
* Parses cancel/close of the refine UI on client side.
* 0aa4
*/
void clif_parse_refineui_close( int fd, struct map_session_data* sd ){
#if PACKETVER >= 20161012
sd->state.refineui_open = false;
#endif
}
/**
* Adds the selected item into the refine UI and sends the possible materials
* to the client.
* 0aa2 <length>.W <index>.W <catalyst count>.B { <material>.W <chance>.B <price>.L }*
*/
void clif_refineui_info( struct map_session_data* sd, uint16 index ){
int fd = sd->fd;
// Get the item db reference
struct item_data* id = sd->inventory_data[index];
// No item data was found
if( id == NULL ){
return;
}
// Check the inventory
struct item* item = &sd->inventory.u.items_inventory[index];
// No item was found at the given index
if( item == NULL ){
return;
}
// Check if the item is identified
if( !item->identify ){
return;
}
// Check if the item is broken
if( item->attribute ){
return;
}
std::shared_ptr<s_refine_level_info> info = refine_db.findLevelInfo( *id, *item );
// No refine possible
if( info == nullptr ){
return;
}
// No possibilities were found
if( info->costs.empty() ){
return;
}
uint16 length = (uint16)( sizeof( struct PACKET_ZC_REFINE_ADD_ITEM ) + REFINE_COST_MAX * sizeof( struct PACKET_ZC_REFINE_ADD_ITEM_SUB ) );
// Preallocate the size
WFIFOHEAD( fd, length );
struct PACKET_ZC_REFINE_ADD_ITEM* p = (struct PACKET_ZC_REFINE_ADD_ITEM*)WFIFOP( fd, 0 );
p->packetType = HEADER_ZC_REFINE_ADD_ITEM;
p->itemIndex = client_index( index );
p->blacksmithBlessing = (uint8)info->blessing_amount;
uint16 count = 0;
for( uint16 i = REFINE_COST_NORMAL; i < REFINE_COST_MAX; i++ ){
std::shared_ptr<s_refine_cost> cost = util::umap_find( info->costs, i );
if( cost != nullptr ){
p->req[count].itemId = client_nameid( cost->nameid );
p->req[count].chance = (uint8)( cost->chance / 100 );
p->req[count].zeny = cost->zeny;
count++;
}
}
p->packtLength = (uint16)( sizeof( struct PACKET_ZC_REFINE_ADD_ITEM ) + count * sizeof( struct PACKET_ZC_REFINE_ADD_ITEM_SUB ) );
WFIFOSET( fd, p->packtLength );
}
/**
* Client request to add an item to the refine UI.
* 0aa1 <index>.W
*/
void clif_parse_refineui_add( int fd, struct map_session_data* sd ){
#if PACKETVER >= 20161012
struct PACKET_CZ_REFINE_ADD_ITEM* p = (struct PACKET_CZ_REFINE_ADD_ITEM*)RFIFOP( fd, 0 );
uint16 index = server_index( p->index );
// Check if the refine UI is open
if( !sd->state.refineui_open ){
return;
}
// Check if the index is valid
if( index >= MAX_INVENTORY ){
return;
}
// Send out the requirements for the refine process
clif_refineui_info( sd, index );
#endif
}
/**
* Client requests to try to refine an item.
* 0aa3 <index>.W <material>.W <catalyst>.B
*/
void clif_parse_refineui_refine( int fd, struct map_session_data* sd ){
#if PACKETVER >= 20161012
struct PACKET_CZ_REFINE_ITEM_REQUEST* p = (struct PACKET_CZ_REFINE_ITEM_REQUEST*)RFIFOP( fd, 0 );
uint16 index = server_index( p->index );
t_itemid material = p->itemId;
int16 j;
// Check if the refine UI is open
if( !sd->state.refineui_open ){
return;
}
// Check if the index is valid
if( index >= MAX_INVENTORY ){
return;
}
// Get the item db reference
struct item_data* id = sd->inventory_data[index];
// No item data was found
if( id == NULL ){
return;
}
// Check the inventory
struct item* item = &sd->inventory.u.items_inventory[index];
// No item was found at the given index
if( item == NULL ){
return;
}
// Check if the item is identified
if( !item->identify ){
return;
}
// Check if the item is broken
if( item->attribute ){
return;
}
std::shared_ptr<s_refine_level_info> info = refine_db.findLevelInfo( *id, *item );
// No refine possible
if( info == nullptr ){
return;
}
// No possibilities were found
if( info->costs.empty() ){
return;
}
// Check if the player has the selected material
if( ( j = pc_search_inventory( sd, material ) ) < 0 ){
return;
}
int16 blacksmith_index = -1;
uint16 blacksmith_amount = 0;
// Check if the player has enough blacksmith blessings
if( p->blacksmithBlessing != 0 ){
blacksmith_amount = info->blessing_amount;
// Player tried to use blacksmith blessing on a refine level, where it is not available
if( blacksmith_amount == 0 ){
return;
}
// Check if the player has blacksmith blessings
if( ( blacksmith_index = pc_search_inventory( sd, ITEMID_BLACKSMITH_BLESSING ) ) < 0 ){
return;
}
// Check if the player has enough blacksmith blessings
if( sd->inventory.u.items_inventory[blacksmith_index].amount < blacksmith_amount ){
return;
}
}
std::shared_ptr<s_refine_cost> cost = nullptr;
for( const auto& pair : info->costs ){
if( pair.second->nameid == material ){
cost = pair.second;
break;
}
}
// The material was not in the list of possible materials
if( cost == nullptr ){
return;
}
// Try to pay for the refine
if( pc_payzeny( sd, cost->zeny, LOG_TYPE_CONSUME, NULL ) ){
clif_npc_buy_result( sd, 1 ); // "You do not have enough zeny."
return;
}
// Delete the required material
if( pc_delitem( sd, j, 1, 0, 0, LOG_TYPE_CONSUME ) ){
return;
}
// Delete the required blacksmith blessings
if( blacksmith_amount > 0 && pc_delitem( sd, blacksmith_index, blacksmith_amount, 0, 0, LOG_TYPE_CONSUME ) ){
return;
}
// Try to refine the item
if( cost->chance >= ( rnd() % 10000 ) ){
// Success
item->refine = cap_value( item->refine + 1, 0, MAX_REFINE );
clif_misceffect( &sd->bl, 3 );
clif_refine( fd, 0, index, item->refine );
achievement_update_objective( sd, AG_ENCHANT_SUCCESS, 2, id->wlv, item->refine );
clif_refineui_info( sd, index );
}else{
// Failure
// Blacksmith blessings were used to prevent breaking and downgrading
if( blacksmith_amount > 0 ){
clif_refine( fd, 3, index, item->refine );
// Delete the item if it is breakable
}else if( cost->breaking_rate > 0 && ( rnd() % 10000 ) < cost->breaking_rate ){
clif_refine( fd, 1, index, item->refine );
pc_delitem( sd, index, 1, 0, 0, LOG_TYPE_CONSUME );
// Downgrade the item if necessary
}else if( cost->downgrade_amount > 0 ){
item->refine = cap_value( item->refine - cost->downgrade_amount, 0, MAX_REFINE );
clif_refine( fd, 2, index, item->refine );
clif_refineui_info(sd, index);
// Only show failure, but dont do anything
}else{
clif_refine( fd, 3, index, item->refine );
}
clif_misceffect( &sd->bl, 2 );
achievement_update_objective( sd, AG_ENCHANT_FAIL, 1, 1 );
}
#endif
}
/*==========================================
* Main client packet processing function
*------------------------------------------*/

View File

@ -1077,6 +1077,9 @@ void clif_sale_end(struct sale_item_data* sale_item, struct block_list* bl, enum
void clif_sale_amount(struct sale_item_data* sale_item, struct block_list* bl, enum send_target target);
void clif_sale_open(struct map_session_data* sd);
// Refine UI
void clif_refineui_open( struct map_session_data* sd );
/**
* Color Table
**/

View File

@ -2299,6 +2299,15 @@
packet(0x0A84,94);
#endif
// 2016-10-12aRagexeRE
#if PACKETVER >= 20161012
packet( HEADER_ZC_REFINE_OPEN_WINDOW, sizeof( struct PACKET_ZC_REFINE_OPEN_WINDOW ) );
parseable_packet( HEADER_CZ_REFINE_ADD_ITEM, sizeof( struct PACKET_CZ_REFINE_ADD_ITEM ), clif_parse_refineui_add, 0 );
packet( HEADER_ZC_REFINE_ADD_ITEM, -1 );
parseable_packet( HEADER_CZ_REFINE_ITEM_REQUEST, sizeof( struct PACKET_CZ_REFINE_ITEM_REQUEST ), clif_parse_refineui_refine, 0 );
parseable_packet( HEADER_CZ_REFINE_WINDOW_CLOSE, sizeof( struct PACKET_CZ_REFINE_WINDOW_CLOSE ), clif_parse_refineui_close, 0 );
#endif
// 2016-10-26bRagexeRE
#if PACKETVER >= 20161026
packet(0x0AA5,-1);

View File

@ -430,7 +430,7 @@ uint64 ItemDatabase::parseBodyNode(const YAML::Node &node) {
if (!this->asUInt16(node, "WeaponLevel", lv))
return 0;
if (lv >= REFINE_TYPE_SHADOW) {
if (lv > MAX_WEAPON_LEVEL) {
this->invalidWarning(node["WeaponLevel"], "Invalid weapon level %d, defaulting to 0.\n", lv);
lv = REFINE_TYPE_ARMOR;
}

View File

@ -89,6 +89,7 @@ enum item_itemid : t_itemid
ITEMID_MAGIC_GEAR_FUEL = 6146,
ITEMID_NEW_INSURANCE = 6413,
ITEMID_STRANGE_EMBRYO = 6415,
ITEMID_BLACKSMITH_BLESSING = 6635,
ITEMID_STONE = 7049,
ITEMID_FIRE_BOTTLE = 7135,
ITEMID_ACID_BOTTLE = 7136,

View File

@ -351,7 +351,7 @@
<Copy SourceFiles="$(SolutionDir)db\import-tmpl\pet_db.yml" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\pet_db.yml')" />
<Copy SourceFiles="$(SolutionDir)db\import-tmpl\produce_db.txt" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\produce_db.txt')" />
<Copy SourceFiles="$(SolutionDir)db\import-tmpl\quest_db.yml" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\quest_db.yml')" />
<Copy SourceFiles="$(SolutionDir)db\import-tmpl\refine_db.yml" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\refine_db.yml')" />
<Copy SourceFiles="$(SolutionDir)db\import-tmpl\refine.yml" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\refine.yml')" />
<Copy SourceFiles="$(SolutionDir)db\import-tmpl\size_fix.yml" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\size_fix.yml')" />
<Copy SourceFiles="$(SolutionDir)db\import-tmpl\skill_changematerial_db.txt" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\skill_changematerial_db.txt')" />
<Copy SourceFiles="$(SolutionDir)db\import-tmpl\skill_damage_db.txt" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\skill_damage_db.txt')" />

View File

@ -341,6 +341,7 @@ struct map_session_data {
bool cashshop_open;
bool sale_open;
unsigned int block_action : 10;
bool refineui_open;
} state;
struct {
unsigned char no_weapon_damage, no_magic_damage, no_misc_damage;
@ -976,10 +977,9 @@ extern struct s_job_info job_info[CLASS_COUNT];
#define pc_isidle_hom(sd) ( (sd)->hd && ( (sd)->chatID || (sd)->state.vending || (sd)->state.buyingstore || DIFF_TICK(last_tick, (sd)->idletime_hom) >= battle_config.hom_idle_no_share ) )
#define pc_isidle_mer(sd) ( (sd)->md && ( (sd)->chatID || (sd)->state.vending || (sd)->state.buyingstore || DIFF_TICK(last_tick, (sd)->idletime_mer) >= battle_config.mer_idle_no_share ) )
#define pc_istrading(sd) ( (sd)->npc_id || (sd)->state.vending || (sd)->state.buyingstore || (sd)->state.trading )
#define pc_cant_act(sd) ( (sd)->npc_id || (sd)->state.vending || (sd)->state.buyingstore || (sd)->chatID || ((sd)->sc.opt1 && (sd)->sc.opt1 != OPT1_BURNING) || (sd)->state.trading || (sd)->state.storage_flag || (sd)->state.prevend )
/* equals pc_cant_act except it doesn't check for chat rooms or npcs */
#define pc_cant_act2(sd) ( (sd)->state.vending || (sd)->state.buyingstore || ((sd)->sc.opt1 && (sd)->sc.opt1 != OPT1_BURNING) || (sd)->state.trading || (sd)->state.storage_flag || (sd)->state.prevend )
// equals pc_cant_act2 and additionally checks for chat rooms and npcs
#define pc_cant_act(sd) ( (sd)->npc_id || (sd)->chatID || pc_cant_act2( (sd) ) )
#define pc_cant_act2(sd) ( (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 )
#define pc_setdir(sd,b,h) ( (sd)->ud.dir = (b) ,(sd)->head_dir = (h) )
#define pc_setchatid(sd,n) ( (sd)->chatID = n )

View File

@ -9200,11 +9200,22 @@ BUILDIN_FUNC(getequippercentrefinery)
if (equip_index_check(num))
i = pc_checkequip(sd,equip_bitmask[num]);
if (i >= 0 && sd->inventory.u.items_inventory[i].nameid && sd->inventory.u.items_inventory[i].refine < MAX_REFINE) {
enum refine_type type = REFINE_TYPE_SHADOW;
if (sd->inventory_data[i]->type != IT_SHADOWGEAR)
type = (enum refine_type)sd->inventory_data[i]->wlv;
script_pushint(st, status_get_refine_chance(type, (int)sd->inventory.u.items_inventory[i].refine, enriched));
if (i >= 0 && sd->inventory.u.items_inventory[i].nameid) {
std::shared_ptr<s_refine_level_info> info = refine_db.findLevelInfo( *sd->inventory_data[i], sd->inventory.u.items_inventory[i] );
if( info == nullptr ){
script_pushint( st, 0 );
return SCRIPT_CMD_SUCCESS;
}
std::shared_ptr<s_refine_cost> cost = util::umap_find( info->costs, (uint16)( enriched ? REFINE_COST_ENRICHED : REFINE_COST_NORMAL ) );
if( cost == nullptr ){
script_pushint( st, 0 );
return SCRIPT_CMD_SUCCESS;
}
script_pushint( st, cost->chance / 100 );
}
else
script_pushint(st,0);
@ -24364,15 +24375,36 @@ BUILDIN_FUNC(getequiprefinecost) {
return SCRIPT_CMD_SUCCESS;
}
int weapon_lv = sd->inventory_data[i]->wlv;
if (sd->inventory_data[i]->type == IT_SHADOWGEAR) {
if (sd->inventory_data[i]->equip == EQP_SHADOW_WEAPON)
weapon_lv = REFINE_TYPE_WEAPON4;
else
weapon_lv = REFINE_TYPE_SHADOW;
if( sd->inventory_data[i] == nullptr ){
script_pushint( st, -1 );
return SCRIPT_CMD_SUCCESS;
}
script_pushint(st, status_get_refine_cost(weapon_lv, type, info != 0));
std::shared_ptr<s_refine_level_info> level_info = refine_db.findLevelInfo( *sd->inventory_data[i], sd->inventory.u.items_inventory[i] );
if( level_info == nullptr ){
script_pushint( st, -1 );
return SCRIPT_CMD_SUCCESS;
}
std::shared_ptr<s_refine_cost> cost = util::umap_find( level_info->costs, (uint16)type );
if( cost == nullptr ){
script_pushint( st, -1 );
return SCRIPT_CMD_SUCCESS;
}
switch( info ){
case REFINE_MATERIAL_ID:
script_pushint( st, cost->nameid );
break;
case REFINE_ZENY_COST:
script_pushint( st, cost->zeny );
break;
default:
script_pushint( st, -1 );
return SCRIPT_CMD_FAILURE;
}
return SCRIPT_CMD_SUCCESS;
}
@ -24993,6 +25025,30 @@ BUILDIN_FUNC(isnpccloaked)
return SCRIPT_CMD_SUCCESS;
}
BUILDIN_FUNC(refineui){
#if PACKETVER < 20161012
ShowError( "buildin_refineui: This command requires packet version 2016-10-12 or newer.\n" );
return SCRIPT_CMD_FAILURE;
#else
struct map_session_data* sd;
if( !script_charid2sd(2,sd) ){
return SCRIPT_CMD_FAILURE;
}
if( !battle_config.feature_refineui ){
ShowError( "buildin_refineui: This command is disabled via configuration.\n" );
return SCRIPT_CMD_FAILURE;
}
if( !sd->state.refineui_open ){
clif_refineui_open(sd);
}
return SCRIPT_CMD_SUCCESS;
#endif
}
#include "../custom/script.inc"
// declarations that were supposed to be exported from npc_chat.cpp
@ -25657,8 +25713,9 @@ struct script_function buildin_func[] = {
BUILDIN_DEF(achievementexists,"i?"),
BUILDIN_DEF(achievementupdate,"iii?"),
BUILDIN_DEF(getequiprefinecost,"iii?"),
BUILDIN_DEF(refineui,"?"),
BUILDIN_DEF2(round, "round", "ii"),
BUILDIN_DEF2(round, "ceil", "ii"),
BUILDIN_DEF2(round, "floor", "ii"),

View File

@ -5254,17 +5254,18 @@
/* refine cost types */
export_constant(REFINE_COST_NORMAL);
export_constant(REFINE_COST_OVER10);
export_deprecated_constant3("REFINE_COST_OVER10", REFINE_COST_NORMAL, "REFINE_COST_NORMAL");
export_constant(REFINE_COST_HD);
export_constant(REFINE_COST_ENRICHED);
export_constant(REFINE_COST_OVER10_HD);
export_constant(REFINE_COST_HOLINK);
export_constant(REFINE_COST_WAGJAK);
export_deprecated_constant3("REFINE_COST_OVER10_HD", REFINE_COST_HD, "REFINE_COST_HD");
// These two have been re-hardcoded, but better default to normal than provide nothing
export_deprecated_constant3("REFINE_COST_HOLINK", REFINE_COST_NORMAL, "REFINE_COST_NORMAL");
export_deprecated_constant3("REFINE_COST_WAGJAK", REFINE_COST_NORMAL, "REFINE_COST_NORMAL");
export_constant(REFINE_COST_MAX);
/* refine information types */
script_set_constant("REFINE_MATERIAL_ID", 0, false, false);
script_set_constant("REFINE_ZENY_COST", 1, false, false);
export_constant(REFINE_MATERIAL_ID);
export_constant(REFINE_ZENY_COST);
/* NPC view ids */
// Special macro to strip the prefix 'JT_'
@ -8093,6 +8094,12 @@
export_constant(ITEMINFO_ID);
export_constant(ITEMINFO_AEGISNAME);
/* refine types */
export_constant(REFINE_TYPE_ARMOR);
export_constant(REFINE_TYPE_WEAPON);
export_constant(REFINE_TYPE_SHADOW_ARMOR);
export_constant(REFINE_TYPE_SHADOW_WEAPON);
#undef export_constant
#undef export_constant2
#undef export_parameter

View File

@ -17694,7 +17694,27 @@ void skill_weaponrefine(struct map_session_data *sd, int idx)
clif_upgrademessage(sd, 3, material[ditem->wlv]);
return;
}
per = status_get_refine_chance(static_cast<refine_type>(ditem->wlv), (int)item->refine, false);
std::shared_ptr<s_refine_level_info> info = refine_db.findLevelInfo( *ditem, *item );
if( info == nullptr ){
clif_skill_fail( sd, sd->menuskill_id, USESKILL_FAIL_LEVEL, 0 );
return;
}
std::shared_ptr<s_refine_cost> cost = util::umap_find( info->costs, (uint16)REFINE_COST_NORMAL );
if( cost == nullptr ){
clif_skill_fail( sd, sd->menuskill_id, USESKILL_FAIL_LEVEL, 0 );
return;
}
if( cost->nameid != material[ditem->wlv] ){
clif_skill_fail( sd, sd->menuskill_id, USESKILL_FAIL_LEVEL, 0 );
return;
}
per = ( cost->chance / 100 );
if( sd->class_&JOBL_THIRD )
per += 10;
else

View File

@ -48,14 +48,6 @@ enum e_regen {
RGN_SSP = 0x08,
};
// Bonus values and upgrade chances for refining equipment
static struct {
int chance[REFINE_CHANCE_TYPE_MAX][MAX_REFINE]; /// Success chance
int bonus[MAX_REFINE]; /// Cumulative fixed bonus damage
int randombonus_max[MAX_REFINE]; /// Cumulative maximum random bonus damage
struct refine_cost cost[REFINE_COST_MAX];
} refine_info[REFINE_TYPE_MAX];
static struct eri *sc_data_ers; /// For sc_data entries
static struct status_data dummy_status;
@ -115,6 +107,324 @@ static int status_get_sc_interval(enum sc_type type);
static bool status_change_isDisabledOnMap_(sc_type type, bool mapIsVS, bool mapIsPVP, bool mapIsGVG, bool mapIsBG, unsigned int mapZone, bool mapIsTE);
#define status_change_isDisabledOnMap(type, m) ( status_change_isDisabledOnMap_((type), mapdata_flag_vs2((m)), m->flag[MF_PVP] != 0, mapdata_flag_gvg2_no_te((m)), m->flag[MF_BATTLEGROUND] != 0, (m->zone << 3) != 0, mapdata_flag_gvg2_te((m))) )
const std::string RefineDatabase::getDefaultLocation(){
return std::string( db_path ) + "/refine.yml";
}
uint64 RefineDatabase::parseBodyNode( const YAML::Node& node ){
std::string group_name;
if( !this->asString( node, "Group", group_name ) ){
return 0;
}
std::string group_name_constant = "REFINE_TYPE_" + group_name;
int64 constant;
if( !script_get_constant( group_name_constant.c_str(), &constant ) ){
this->invalidWarning(node["Group"], "Unknown refine group %s, skipping.\n", group_name.c_str() );
return 0;
}
uint16 group_id = static_cast<uint16>( constant );
std::shared_ptr<s_refine_info> info = this->find( group_id );
bool exists = info != nullptr;
if( !exists ){
info = std::make_shared<s_refine_info>();
}
if( this->nodeExists( node, "Levels" ) ){
for( const YAML::Node& levelNode : node["Levels"] ){
uint16 level;
if( !this->asUInt16( levelNode, "Level", level ) ){
return 0;
}
std::shared_ptr<s_refine_levels_info> levels_info = util::umap_find( info->levels, level );
bool levels_exists = levels_info != nullptr;
if( !levels_exists ){
levels_info = std::make_shared<s_refine_levels_info>();
levels_info->level = level;
}
if( this->nodeExists( levelNode, "RefineLevels" ) ){
for( const YAML::Node& refineLevelNode : levelNode["RefineLevels"] ){
uint16 refine_level;
if( !this->asUInt16( refineLevelNode, "Level", refine_level ) ){
return 0;
}
if( refine_level == 0 || refine_level > MAX_REFINE ){
this->invalidWarning( refineLevelNode["Level"], "Refine level %hu is invalid, skipping.\n", refine_level );
return 0;
}
// Database is 1 based, code is 0 based
refine_level -= 1;
std::shared_ptr<s_refine_level_info> level_info = util::umap_find( levels_info->levels, refine_level );
bool level_exists = level_info != nullptr;
if( !level_exists ){
level_info = std::make_shared<s_refine_level_info>();
level_info->level = refine_level;
}
if( this->nodeExists( refineLevelNode, "Bonus" ) ){
uint32 bonus;
if( !this->asUInt32( refineLevelNode, "Bonus", bonus ) ){
return 0;
}
level_info->bonus = bonus;
}else{
if( !level_exists ){
level_info->bonus = 0;
}
}
if( this->nodeExists( refineLevelNode, "RandomBonus" ) ){
uint32 bonus;
if( !this->asUInt32( refineLevelNode, "RandomBonus", bonus ) ){
return 0;
}
level_info->randombonus_max = bonus;
}else{
if( !level_exists ){
level_info->randombonus_max = 0;
}
}
if( this->nodeExists( refineLevelNode, "BlacksmithBlessingAmount" ) ){
uint16 amount;
if( !this->asUInt16( refineLevelNode, "BlacksmithBlessingAmount", amount ) ){
return 0;
}
if( amount > MAX_AMOUNT ){
this->invalidWarning( refineLevelNode["BlacksmithBlessingAmount"], "Blacksmith Blessing amount %hu too high, capping to MAX_AMOUNT.\n", amount );
amount = MAX_AMOUNT;
}
level_info->blessing_amount = amount;
}else{
if( !level_exists ){
level_info->blessing_amount = 0;
}
}
if( this->nodeExists( refineLevelNode, "Chances" ) ){
for( const YAML::Node& chanceNode : refineLevelNode["Chances"] ){
std::string cost_name;
if( !this->asString( chanceNode, "Type", cost_name ) ){
return 0;
}
std::string cost_name_constant = "REFINE_COST_" + cost_name;
if( !script_get_constant( cost_name_constant.c_str(), &constant ) ){
this->invalidWarning( chanceNode["Type"], "Unknown refine cost type %s, skipping.\n", cost_name.c_str() );
return 0;
}
if( constant >= REFINE_COST_MAX ){
this->invalidWarning( chanceNode["Type"], "Refine cost type %s is unsupported, skipping.\n", cost_name.c_str() );
return 0;
}
uint16 index = (uint16)constant;
std::shared_ptr<s_refine_cost> cost = util::umap_find( level_info->costs, index );
bool cost_exists = cost != nullptr;
if( !cost_exists ){
cost = std::make_shared<s_refine_cost>();
cost->index = index;
}
if( this->nodeExists( chanceNode, "Rate" ) ){
uint16 rate;
if( !this->asUInt16Rate( chanceNode, "Rate", rate ) ){
return 0;
}
cost->chance = rate;
}else{
if( !cost_exists ){
cost->chance = 0;
}
}
if( this->nodeExists( chanceNode, "Price" ) ){
uint32 price;
if( !this->asUInt32( chanceNode, "Price", price ) ){
return 0;
}
if( price > MAX_ZENY ){
this->invalidWarning( chanceNode["Price"], "Price is above MAX_ZENY, capping...\n" );
price = MAX_ZENY;
}
cost->zeny = price;
}else{
if( !cost_exists ){
cost->zeny = 0;
}
}
if( this->nodeExists( chanceNode, "Material" ) ){
std::string item_name;
if( !this->asString( chanceNode, "Material", item_name ) ){
return 0;
}
struct item_data* id = itemdb_search_aegisname( item_name.c_str() );
if( id == nullptr ){
this->invalidWarning( chanceNode["Material"], "Unknown refine material %s, skipping.\n", item_name.c_str() );
return 0;
}
cost->nameid = id->nameid;
}else{
if( !cost_exists ){
cost->nameid = 0;
}
}
if( this->nodeExists( chanceNode, "BreakingRate" ) ){
uint16 breaking_rate;
if( !this->asUInt16Rate( chanceNode, "BreakingRate", breaking_rate ) ){
return 0;
}
cost->breaking_rate = breaking_rate;
}else{
if( !cost_exists ){
cost->breaking_rate = 0;
}
}
if( this->nodeExists( chanceNode, "DowngradeAmount" ) ){
uint16 downgrade_amount;
if( !this->asUInt16( chanceNode, "DowngradeAmount", downgrade_amount ) ){
return 0;
}
if( downgrade_amount > MAX_REFINE ){
this->invalidWarning( chanceNode["DowngradeAmount"], "Downgrade amount %hu is invalid, skipping.\n", downgrade_amount );
return 0;
}
cost->downgrade_amount = downgrade_amount;
}else{
if( !cost_exists ){
cost->downgrade_amount = 0;
}
}
if( !cost_exists ){
level_info->costs[index] = cost;
}
}
}
if( !level_exists ){
levels_info->levels[refine_level] = level_info;
}
}
}
if( !levels_exists ){
info->levels[level] = levels_info;
}
}
}
if( !exists ){
this->put( group_id, info );
}
return 1;
}
std::shared_ptr<s_refine_level_info> RefineDatabase::findLevelInfo( const struct item_data& data, struct item& item ){
// Check if the item can be refined
if( data.flag.no_refine ){
return nullptr;
}
// Check the current refine level
if( item.refine >= MAX_REFINE ){
return nullptr;
}
e_refine_type type;
uint16 level;
if( !this->calculate_refine_info( data, type, level ) ){
return nullptr;
}
std::shared_ptr<s_refine_info> info = this->find( type );
if( info == nullptr ){
return nullptr;
}
std::shared_ptr<s_refine_levels_info> levels_info = util::umap_find( info->levels, level );
if( levels_info == nullptr ){
return nullptr;
}
return util::umap_find( levels_info->levels, (uint16)item.refine );
}
bool RefineDatabase::calculate_refine_info( const struct item_data& data, e_refine_type& refine_type, uint16& level ){
if( data.type == IT_WEAPON ){
refine_type = REFINE_TYPE_WEAPON;
level = data.wlv;
return true;
}else if( data.type == IT_ARMOR ){
refine_type = REFINE_TYPE_ARMOR;
// TODO: implement when armor level is supported
level = 1;
return true;
}else if( data.type == IT_SHADOWGEAR ){
if( data.equip == EQP_SHADOW_WEAPON ){
refine_type = REFINE_TYPE_SHADOW_WEAPON;
}else{
refine_type = REFINE_TYPE_SHADOW_ARMOR;
}
level = 1;
return true;
}else{
return false;
}
}
RefineDatabase refine_db;
const std::string SizeFixDatabase::getDefaultLocation() {
return std::string(db_path) + "/size_fix.yml";
}
@ -3951,9 +4261,15 @@ int status_calc_pc_sub(struct map_session_data* sd, enum e_status_calc_opt opt)
int r = sd->inventory.u.items_inventory[index].refine, wlv = sd->inventory_data[index]->wlv;
struct weapon_data *wd;
struct weapon_atk *wa;
std::shared_ptr<s_refine_level_info> info = nullptr;
if(wlv >= MAX_WEAPON_LEVEL)
wlv = MAX_WEAPON_LEVEL;
if( r ){
info = refine_db.findLevelInfo( *sd->inventory_data[index], sd->inventory.u.items_inventory[index] );
}
if(wlv >= REFINE_TYPE_MAX)
wlv = REFINE_TYPE_MAX - 1;
if(i == EQI_HAND_L && sd->inventory.u.items_inventory[index].equip == EQP_HAND_L) {
wd = &sd->left_weapon; // Left-hand weapon
wa = &base_status->lhw;
@ -3962,18 +4278,24 @@ int status_calc_pc_sub(struct map_session_data* sd, enum e_status_calc_opt opt)
wa = &base_status->rhw;
}
wa->atk += sd->inventory_data[index]->atk;
if(r)
wa->atk2 += refine_info[wlv].bonus[r-1] / 100;
if( info != nullptr ){
wa->atk2 += info->bonus / 100;
}
#ifdef RENEWAL
if (sd->bonus.weapon_atk_rate)
wa->atk = wa->atk * sd->bonus.weapon_atk_rate / 100;
wa->matk += sd->inventory_data[index]->matk;
wa->wlv = wlv;
if(r && sd->weapontype1 != W_BOW) // Renewal magic attack refine bonus
wa->matk += refine_info[wlv].bonus[r-1] / 100;
// Renewal magic attack refine bonus
if( info != nullptr && sd->weapontype1 != W_BOW ){
wa->matk += info->bonus / 100;
}
#endif
if(r) // Overrefine bonus.
wd->overrefine = refine_info[wlv].randombonus_max[r-1] / 100;
// Overrefine bonus.
if( info != nullptr ){
wd->overrefine = info->randombonus_max / 100;
}
wa->range += sd->inventory_data[index]->range;
if(sd->inventory_data[index]->script && (pc_has_permission(sd,PC_PERM_USE_ALL_EQUIPMENT) || !itemdb_isNoEquip(sd->inventory_data[index],sd->bl.m))) {
if (wd == &sd->left_weapon) {
@ -3998,10 +4320,16 @@ int status_calc_pc_sub(struct map_session_data* sd, enum e_status_calc_opt opt)
wa->ele = (sd->inventory.u.items_inventory[index].card[1]&0x0f);
}
} else if(sd->inventory_data[index]->type == IT_ARMOR) {
int r;
int r = sd->inventory.u.items_inventory[index].refine;
if( r ){
std::shared_ptr<s_refine_level_info> info = refine_db.findLevelInfo( *sd->inventory_data[index], sd->inventory.u.items_inventory[index] );
if( info != nullptr ){
refinedef += info->bonus;
}
}
if ( (r = sd->inventory.u.items_inventory[index].refine) )
refinedef += refine_info[REFINE_TYPE_ARMOR].bonus[r-1];
if(sd->inventory_data[index]->script && (pc_has_permission(sd,PC_PERM_USE_ALL_EQUIPMENT) || !itemdb_isNoEquip(sd->inventory_data[index],sd->bl.m))) {
if( i == EQI_HAND_L ) // Shield
sd->state.lr_flag = 3;
@ -15499,24 +15827,6 @@ static TIMER_FUNC(status_natural_heal_timer){
return 0;
}
/**
* Get the chance to upgrade a piece of equipment
* @param wlv: The weapon type of the item to refine (see see enum refine_type)
* @param refine: The target's refine level
* @return The chance to refine the item, in percent (0~100)
*/
int status_get_refine_chance(enum refine_type wlv, int refine, bool enriched)
{
if ( refine < 0 || refine >= MAX_REFINE)
return 0;
int type = enriched ? 1 : 0;
if (battle_config.event_refine_chance)
type |= 2;
return refine_info[wlv].chance[type][refine];
}
/**
* Check if status is disabled on a map
* @param type: Status Change data
@ -15601,123 +15911,6 @@ static bool status_readdb_status_disabled(char **str, int columns, int current)
return true;
}
/**
* Reads and parses an entry from the refine_db
* @param node: The YAML node containing the entry
* @param refine_info_index: The sequential index of the current entry
* @param file_name: File name for displaying only
* @return True on success or false on failure
*/
static bool status_yaml_readdb_refine_sub(const YAML::Node &node, int refine_info_index, const std::string &file_name) {
if (refine_info_index < 0 || refine_info_index >= REFINE_TYPE_MAX)
return false;
int bonus_per_level = node["StatsPerLevel"].as<int>();
int random_bonus_start_level = node["RandomBonusStartLevel"].as<int>();
int random_bonus = node["RandomBonusValue"].as<int>();
if (file_name.find("import") != std::string::npos) { // Import file, reset refine bonus before calculation
for (int refine_level = 0; refine_level < MAX_REFINE; ++refine_level)
refine_info[refine_info_index].bonus[refine_level] = 0;
}
const YAML::Node &costs = node["Costs"];
for (const auto costit : costs) {
int64 idx_tmp = 0;
const YAML::Node &type = costit;
int idx = 0, price;
t_itemid material;
const std::string keys[] = { "Type", "Price", "Material" };
for (int i = 0; i < ARRAYLENGTH(keys); i++) {
if (!type[keys[i]].IsDefined())
ShowWarning("status_yaml_readdb_refine_sub: Invalid refine cost with undefined " CL_WHITE "%s" CL_RESET "in file" CL_WHITE "%s" CL_RESET ".\n", keys[i].c_str(), file_name.c_str());
}
std::string refine_cost_const = type["Type"].as<std::string>();
if (ISDIGIT(refine_cost_const[0]))
idx = atoi(refine_cost_const.c_str());
else {
script_get_constant(refine_cost_const.c_str(), &idx_tmp);
idx = static_cast<int>(idx_tmp);
}
price = type["Price"].as<int>();
// TODO: item id verification
material = type["Material"].as<t_itemid>();
refine_info[refine_info_index].cost[idx].nameid = material;
refine_info[refine_info_index].cost[idx].zeny = price;
}
const YAML::Node &rates = node["Rates"];
for (const auto rateit : rates) {
const YAML::Node &level = rateit;
int refine_level = level["Level"].as<int>() - 1;
if (refine_level >= MAX_REFINE)
continue;
if (level["NormalChance"].IsDefined())
refine_info[refine_info_index].chance[REFINE_CHANCE_NORMAL][refine_level] = level["NormalChance"].as<int>();
if (level["EnrichedChance"].IsDefined())
refine_info[refine_info_index].chance[REFINE_CHANCE_ENRICHED][refine_level] = level["EnrichedChance"].as<int>();
if (level["EventNormalChance"].IsDefined())
refine_info[refine_info_index].chance[REFINE_CHANCE_EVENT_NORMAL][refine_level] = level["EventNormalChance"].as<int>();
if (level["EventEnrichedChance"].IsDefined())
refine_info[refine_info_index].chance[REFINE_CHANCE_EVENT_ENRICHED][refine_level] = level["EventEnrichedChance"].as<int>();
if (level["Bonus"].IsDefined())
refine_info[refine_info_index].bonus[refine_level] = level["Bonus"].as<int>();
if (refine_level >= random_bonus_start_level - 1)
refine_info[refine_info_index].randombonus_max[refine_level] = random_bonus * (refine_level - random_bonus_start_level + 2);
}
for (int refine_level = 0; refine_level < MAX_REFINE; ++refine_level)
refine_info[refine_info_index].bonus[refine_level] += bonus_per_level + (refine_level > 0 ? refine_info[refine_info_index].bonus[refine_level - 1] : 0);
return true;
}
/**
* Loads refine values from the refine_db
* @param directory: Location of refine_db file
* @param file: File name
*/
static void status_yaml_readdb_refine(const std::string &directory, const std::string &file) {
int count = 0;
const std::string labels[] = { "Armor", "WeaponLv1", "WeaponLv2", "WeaponLv3", "WeaponLv4", "Shadow" };
const std::string current_file = directory + "/" + file;
YAML::Node config;
try {
config = YAML::LoadFile(current_file);
}
catch (...) {
ShowError("Failed to read '" CL_WHITE "%s" CL_RESET "'.\n", current_file.c_str());
return;
}
for (int i = 0; i < ARRAYLENGTH(labels); i++) {
const YAML::Node &node = config[labels[i]];
if (node.IsDefined() && status_yaml_readdb_refine_sub(node, i, current_file))
count++;
}
ShowStatus("Done reading '" CL_WHITE "%d" CL_RESET "' entries in '" CL_WHITE "%s" CL_RESET "'.\n", count, current_file.c_str());
}
/**
* Returns refine cost (zeny or item) for a weapon level.
* @param weapon_lv Weapon level
* @param type Refine type (can be retrieved from refine_cost_type enum)
* @param what true = returns zeny, false = returns item id
* @return Refine cost for a weapon level
*/
int status_get_refine_cost(int weapon_lv, int type, bool what) {
return what ? refine_info[weapon_lv].cost[type].zeny : refine_info[weapon_lv].cost[type].nameid;
}
/**
* Read attribute fix database for attack calculations
* Function stores information in the attr_fix_table
@ -15790,21 +15983,10 @@ int status_readdb(void)
"/" DBIMPORT,
//add other path here
};
// Initialize databases to default
// Initialize databases to default
memset(SCDisabled, 0, sizeof(SCDisabled));
// refine_db.yml
for(i=0;i<ARRAYLENGTH(refine_info);i++)
{
memset(refine_info[i].cost, 0, sizeof(struct refine_cost));
for(j = 0; j < REFINE_CHANCE_TYPE_MAX; j++)
for(k=0;k<MAX_REFINE; k++)
{
refine_info[i].chance[j][k] = 100;
refine_info[i].bonus[k] = 0;
refine_info[i].randombonus_max[k] = 0;
}
}
// attr_fix.txt
for(i=0;i<MAX_ELE_LEVEL;i++)
for(j=0;j<ELE_ALL;j++)
@ -15831,12 +16013,12 @@ int status_readdb(void)
status_readdb_attrfix(dbsubpath2,i > 0); // !TODO use sv_readdb ?
sv_readdb(dbsubpath1, "status_disabled.txt", ',', 2, 2, -1, &status_readdb_status_disabled, i > 0);
status_yaml_readdb_refine(dbsubpath2, "refine_db.yml");
aFree(dbsubpath1);
aFree(dbsubpath2);
}
size_fix_db.load();
refine_db.load();
return 0;
}

View File

@ -31,36 +31,72 @@ struct status_change;
#endif
/// Refine type
enum refine_type {
REFINE_TYPE_ARMOR = 0,
REFINE_TYPE_WEAPON1 = 1,
REFINE_TYPE_WEAPON2 = 2,
REFINE_TYPE_WEAPON3 = 3,
REFINE_TYPE_WEAPON4 = 4,
REFINE_TYPE_SHADOW = 5,
REFINE_TYPE_MAX = 6
enum e_refine_type : uint16{
REFINE_TYPE_ARMOR = 0,
REFINE_TYPE_WEAPON,
REFINE_TYPE_SHADOW_ARMOR,
REFINE_TYPE_SHADOW_WEAPON,
REFINE_TYPE_MAX
};
/// Refine cost type
enum refine_cost_type {
enum e_refine_cost_type : uint16{
REFINE_COST_NORMAL = 0,
REFINE_COST_OVER10,
REFINE_COST_HD,
REFINE_COST_ENRICHED,
REFINE_COST_OVER10_HD,
REFINE_COST_HOLINK,
REFINE_COST_WAGJAK,
REFINE_COST_MAX
};
struct refine_cost {
t_itemid nameid;
int zeny;
/// Refine script parameters
enum e_refine_parameter{
REFINE_MATERIAL_ID = 0,
REFINE_ZENY_COST
};
/// Get refine chance
int status_get_refine_chance(enum refine_type wlv, int refine, bool enriched);
int status_get_refine_cost(int weapon_lv, int type, bool what);
struct s_refine_cost{
uint16 index;
t_itemid nameid;
uint16 chance;
uint32 zeny;
uint16 breaking_rate;
uint16 downgrade_amount;
};
struct s_refine_level_info{
uint16 level;
uint32 bonus;
uint32 randombonus_max;
uint16 blessing_amount;
std::unordered_map<uint16, std::shared_ptr<s_refine_cost>> costs;
};
struct s_refine_levels_info{
uint16 level;
std::unordered_map<uint16, std::shared_ptr<s_refine_level_info>> levels;
};
struct s_refine_info{
uint16 groupId;
std::unordered_map<uint16, std::shared_ptr<s_refine_levels_info>> levels;
};
class RefineDatabase : public TypesafeYamlDatabase<uint16, s_refine_info>{
private:
bool calculate_refine_info( const struct item_data& data, e_refine_type& refine_type, uint16& level );
public:
RefineDatabase() : TypesafeYamlDatabase( "REFINE_DB", 1 ){
}
const std::string getDefaultLocation();
uint64 parseBodyNode( const YAML::Node& node );
// Additional
std::shared_ptr<s_refine_level_info> findLevelInfo( const struct item_data& data, struct item& item );
};
extern RefineDatabase refine_db;
/// Weapon attack modification for size
struct s_sizefix_db {