Initial release of stylist UI (#6446)
Fixes #3037 Thanks to @Balferian and @aleos89 Co-authored-by: Aleos <aleos89@users.noreply.github.com>
This commit is contained in:
parent
4bc9e24b4e
commit
c22ef3f547
@ -15,11 +15,11 @@ min_chat_delay: 0
|
|||||||
|
|
||||||
// Valid range of dyes and styles on the client.
|
// Valid range of dyes and styles on the client.
|
||||||
min_hair_style: 0
|
min_hair_style: 0
|
||||||
max_hair_style: 27
|
max_hair_style: 42
|
||||||
min_hair_color: 0
|
min_hair_color: 0
|
||||||
max_hair_color: 8
|
max_hair_color: 8
|
||||||
min_cloth_color: 0
|
min_cloth_color: 0
|
||||||
max_cloth_color: 4
|
max_cloth_color: 7
|
||||||
min_body_style: 0
|
min_body_style: 0
|
||||||
max_body_style: 1
|
max_body_style: 1
|
||||||
|
|
||||||
|
@ -876,7 +876,9 @@
|
|||||||
|
|
||||||
797: This command is unavailable to non-4th class.
|
797: This command is unavailable to non-4th class.
|
||||||
|
|
||||||
//798-799 free
|
// @stylist
|
||||||
|
798: This command requires packet version 2015-11-04 or newer.
|
||||||
|
799: You have already opened the stylist UI.
|
||||||
|
|
||||||
800: Dragon Knight
|
800: Dragon Knight
|
||||||
801: Meister
|
801: Meister
|
||||||
|
41
db/import-tmpl/stylist.yml
Normal file
41
db/import-tmpl/stylist.yml
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
# This file is a part of rAthena.
|
||||||
|
# Copyright(C) 2022 rAthena Development Team
|
||||||
|
# https://rathena.org - https://github.com/rathena
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
###########################################################################
|
||||||
|
# Stylist Database
|
||||||
|
###########################################################################
|
||||||
|
#
|
||||||
|
# Stylist Settings
|
||||||
|
#
|
||||||
|
###########################################################################
|
||||||
|
# - Look Look that will be changed.
|
||||||
|
# Options Possible options to select from.
|
||||||
|
# - Index Client side index of the option.
|
||||||
|
# Value Value of the look (can also be an item name).
|
||||||
|
# CostsHuman: Costs for human players.
|
||||||
|
# Price Required zeny. (Default: 0)
|
||||||
|
# RequiredItem Required item. (Default: None)
|
||||||
|
# RequiredItemBox Required item box. (Default: None)
|
||||||
|
# CostsDoram: Costs for doram players.
|
||||||
|
# Price Required zeny. (Default: 0)
|
||||||
|
# RequiredItem Required item. (Default: None)
|
||||||
|
# RequiredItemBox Required item box. (Default: None)
|
||||||
|
###########################################################################
|
||||||
|
|
||||||
|
Header:
|
||||||
|
Type: STYLIST_DB
|
||||||
|
Version: 1
|
@ -21686,8 +21686,8 @@ Body:
|
|||||||
NoMail: true
|
NoMail: true
|
||||||
NoAuction: true
|
NoAuction: true
|
||||||
- Id: 6707
|
- Id: 6707
|
||||||
AegisName: Jeremy_Beauty_Coupon
|
AegisName: J_Shop_Coupon
|
||||||
Name: Jeremy Beauty Coupon
|
Name: Cash Hair Coupon
|
||||||
Type: Etc
|
Type: Etc
|
||||||
Buy: 10
|
Buy: 10
|
||||||
Weight: 10
|
Weight: 10
|
||||||
@ -24023,9 +24023,10 @@ Body:
|
|||||||
Type: Etc
|
Type: Etc
|
||||||
Buy: 10
|
Buy: 10
|
||||||
- Id: 6959
|
- Id: 6959
|
||||||
AegisName: aegis_6959
|
AegisName: Costume_Ticket
|
||||||
Name: Costume Change Ticket
|
Name: Costume Change Ticket
|
||||||
Type: Etc
|
Type: Etc
|
||||||
|
Buy: 0
|
||||||
Trade:
|
Trade:
|
||||||
Override: 100
|
Override: 100
|
||||||
NoDrop: true
|
NoDrop: true
|
||||||
|
@ -39884,6 +39884,57 @@ Body:
|
|||||||
NoGuildStorage: true
|
NoGuildStorage: true
|
||||||
NoMail: true
|
NoMail: true
|
||||||
NoAuction: true
|
NoAuction: true
|
||||||
|
- Id: 16843
|
||||||
|
AegisName: C_New_Style_Box
|
||||||
|
Name: Beauty Gift Box
|
||||||
|
Type: Cash
|
||||||
|
Buy: 20
|
||||||
|
Weight: 10
|
||||||
|
Trade:
|
||||||
|
Override: 100
|
||||||
|
NoDrop: true
|
||||||
|
NoTrade: true
|
||||||
|
NoSell: true
|
||||||
|
NoCart: true
|
||||||
|
NoGuildStorage: true
|
||||||
|
NoMail: true
|
||||||
|
NoAuction: true
|
||||||
|
Script: |
|
||||||
|
getitem 7622,1;
|
||||||
|
- Id: 16854
|
||||||
|
AegisName: CCloth_Dye_Coupon_Box
|
||||||
|
Name: Clothing Dye Box
|
||||||
|
Type: Cash
|
||||||
|
Buy: 20
|
||||||
|
Weight: 10
|
||||||
|
Trade:
|
||||||
|
Override: 100
|
||||||
|
NoDrop: true
|
||||||
|
NoTrade: true
|
||||||
|
NoSell: true
|
||||||
|
NoCart: true
|
||||||
|
NoGuildStorage: true
|
||||||
|
NoMail: true
|
||||||
|
NoAuction: true
|
||||||
|
Script: |
|
||||||
|
getitem 6046,1;
|
||||||
|
- Id: 16855
|
||||||
|
AegisName: CCloth_Dye_Coupon2_Box
|
||||||
|
Name: Clothing Dye Orig Box
|
||||||
|
Type: Cash
|
||||||
|
Buy: 20
|
||||||
|
Weight: 10
|
||||||
|
Trade:
|
||||||
|
Override: 100
|
||||||
|
NoDrop: true
|
||||||
|
NoTrade: true
|
||||||
|
NoSell: true
|
||||||
|
NoCart: true
|
||||||
|
NoGuildStorage: true
|
||||||
|
NoMail: true
|
||||||
|
NoAuction: true
|
||||||
|
Script: |
|
||||||
|
getitem 6047,1;
|
||||||
- Id: 16864
|
- Id: 16864
|
||||||
AegisName: Siege_Map_Teleport_Scroll_Box_10
|
AegisName: Siege_Map_Teleport_Scroll_Box_10
|
||||||
Name: Siege Map Teleport Scroll Box(10)
|
Name: Siege Map Teleport Scroll Box(10)
|
||||||
@ -42918,6 +42969,23 @@ Body:
|
|||||||
NoAuction: true
|
NoAuction: true
|
||||||
Script: |
|
Script: |
|
||||||
getgroupitem(IG_Event_Almighty_Box_100);
|
getgroupitem(IG_Event_Almighty_Box_100);
|
||||||
|
- Id: 17336
|
||||||
|
AegisName: J_Shop_Coupon_Box
|
||||||
|
Name: Cash Hair Coupon Box
|
||||||
|
Type: Cash
|
||||||
|
Buy: 20
|
||||||
|
Weight: 10
|
||||||
|
Trade:
|
||||||
|
Override: 100
|
||||||
|
NoDrop: true
|
||||||
|
NoTrade: true
|
||||||
|
NoSell: true
|
||||||
|
NoCart: true
|
||||||
|
NoGuildStorage: true
|
||||||
|
NoMail: true
|
||||||
|
NoAuction: true
|
||||||
|
Script: |
|
||||||
|
getitem 6707,1;
|
||||||
- Id: 17337
|
- Id: 17337
|
||||||
AegisName: Holy_Spirit_Scroll
|
AegisName: Holy_Spirit_Scroll
|
||||||
Name: Holy Spirit Egg
|
Name: Holy Spirit Egg
|
||||||
|
429
db/re/stylist.yml
Normal file
429
db/re/stylist.yml
Normal file
@ -0,0 +1,429 @@
|
|||||||
|
# This file is a part of rAthena.
|
||||||
|
# Copyright(C) 2022 rAthena Development Team
|
||||||
|
# https://rathena.org - https://github.com/rathena
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
###########################################################################
|
||||||
|
# Stylist Database
|
||||||
|
###########################################################################
|
||||||
|
#
|
||||||
|
# Stylist Settings
|
||||||
|
#
|
||||||
|
###########################################################################
|
||||||
|
# - Look Look that will be changed.
|
||||||
|
# Options Possible options to select from.
|
||||||
|
# - Index Client side index of the option.
|
||||||
|
# Value Value of the look (can also be an item name).
|
||||||
|
# CostsHuman: Costs for human players.
|
||||||
|
# Price Required zeny. (Default: 0)
|
||||||
|
# RequiredItem Required item. (Default: None)
|
||||||
|
# RequiredItemBox Required item box. (Default: None)
|
||||||
|
# CostsDoram: Costs for doram players.
|
||||||
|
# Price Required zeny. (Default: 0)
|
||||||
|
# RequiredItem Required item. (Default: None)
|
||||||
|
# RequiredItemBox Required item box. (Default: None)
|
||||||
|
###########################################################################
|
||||||
|
|
||||||
|
Header:
|
||||||
|
Type: STYLIST_DB
|
||||||
|
Version: 1
|
||||||
|
|
||||||
|
Body:
|
||||||
|
- Look: Hair_Color
|
||||||
|
Options:
|
||||||
|
- Index: -1
|
||||||
|
Value: 0
|
||||||
|
CostsHuman:
|
||||||
|
Price: 0
|
||||||
|
CostsDoram:
|
||||||
|
Price: 0
|
||||||
|
- Index: 1
|
||||||
|
Value: 1
|
||||||
|
CostsHuman:
|
||||||
|
Price: 100000
|
||||||
|
CostsDoram:
|
||||||
|
Price: 100000
|
||||||
|
- Index: 2
|
||||||
|
Value: 2
|
||||||
|
CostsHuman:
|
||||||
|
Price: 100000
|
||||||
|
CostsDoram:
|
||||||
|
Price: 100000
|
||||||
|
- Index: 3
|
||||||
|
Value: 3
|
||||||
|
CostsHuman:
|
||||||
|
Price: 100000
|
||||||
|
CostsDoram:
|
||||||
|
Price: 100000
|
||||||
|
- Index: 4
|
||||||
|
Value: 4
|
||||||
|
CostsHuman:
|
||||||
|
Price: 100000
|
||||||
|
CostsDoram:
|
||||||
|
Price: 100000
|
||||||
|
- Index: 5
|
||||||
|
Value: 5
|
||||||
|
CostsHuman:
|
||||||
|
Price: 100000
|
||||||
|
CostsDoram:
|
||||||
|
Price: 100000
|
||||||
|
- Index: 6
|
||||||
|
Value: 6
|
||||||
|
CostsHuman:
|
||||||
|
Price: 100000
|
||||||
|
CostsDoram:
|
||||||
|
Price: 100000
|
||||||
|
- Index: 7
|
||||||
|
Value: 7
|
||||||
|
CostsHuman:
|
||||||
|
Price: 100000
|
||||||
|
CostsDoram:
|
||||||
|
Price: 100000
|
||||||
|
- Index: 8
|
||||||
|
Value: 8
|
||||||
|
CostsHuman:
|
||||||
|
Price: 100000
|
||||||
|
CostsDoram:
|
||||||
|
Price: 100000
|
||||||
|
- Look: Hair
|
||||||
|
Options:
|
||||||
|
- Index: 1
|
||||||
|
Value: 1
|
||||||
|
CostsHuman:
|
||||||
|
Price: 100000
|
||||||
|
CostsDoram:
|
||||||
|
Price: 100000
|
||||||
|
- Index: 2
|
||||||
|
Value: 2
|
||||||
|
CostsHuman:
|
||||||
|
Price: 100000
|
||||||
|
CostsDoram:
|
||||||
|
Price: 100000
|
||||||
|
- Index: 3
|
||||||
|
Value: 3
|
||||||
|
CostsHuman:
|
||||||
|
Price: 100000
|
||||||
|
CostsDoram:
|
||||||
|
Price: 100000
|
||||||
|
- Index: 4
|
||||||
|
Value: 4
|
||||||
|
CostsHuman:
|
||||||
|
Price: 100000
|
||||||
|
CostsDoram:
|
||||||
|
Price: 100000
|
||||||
|
- Index: 5
|
||||||
|
Value: 5
|
||||||
|
CostsHuman:
|
||||||
|
Price: 100000
|
||||||
|
CostsDoram:
|
||||||
|
Price: 100000
|
||||||
|
- Index: 6
|
||||||
|
Value: 6
|
||||||
|
CostsHuman:
|
||||||
|
Price: 100000
|
||||||
|
CostsDoram:
|
||||||
|
Price: 100000
|
||||||
|
- Index: 7
|
||||||
|
Value: 7
|
||||||
|
CostsHuman:
|
||||||
|
Price: 100000
|
||||||
|
CostDoram:
|
||||||
|
RequiredItem: J_Shop_Coupon2
|
||||||
|
RequiredItemBox: J_Shop_Coupon2
|
||||||
|
- Index: 8
|
||||||
|
Value: 8
|
||||||
|
CostsHuman:
|
||||||
|
Price: 100000
|
||||||
|
CostDoram:
|
||||||
|
RequiredItem: J_Shop_Coupon2
|
||||||
|
RequiredItemBox: J_Shop_Coupon2
|
||||||
|
- Index: 9
|
||||||
|
Value: 9
|
||||||
|
CostsHuman:
|
||||||
|
Price: 100000
|
||||||
|
CostDoram:
|
||||||
|
RequiredItem: J_Shop_Coupon2
|
||||||
|
RequiredItemBox: J_Shop_Coupon2
|
||||||
|
- Index: 10
|
||||||
|
Value: 10
|
||||||
|
CostsHuman:
|
||||||
|
Price: 100000
|
||||||
|
CostDoram:
|
||||||
|
RequiredItem: J_Shop_Coupon2
|
||||||
|
RequiredItemBox: J_Shop_Coupon2
|
||||||
|
- Index: 11
|
||||||
|
Value: 11
|
||||||
|
CostsHuman:
|
||||||
|
Price: 100000
|
||||||
|
- Index: 12
|
||||||
|
Value: 12
|
||||||
|
CostsHuman:
|
||||||
|
Price: 100000
|
||||||
|
- Index: 13
|
||||||
|
Value: 13
|
||||||
|
CostsHuman:
|
||||||
|
Price: 100000
|
||||||
|
- Index: 14
|
||||||
|
Value: 14
|
||||||
|
CostsHuman:
|
||||||
|
Price: 100000
|
||||||
|
- Index: 15
|
||||||
|
Value: 15
|
||||||
|
CostsHuman:
|
||||||
|
Price: 100000
|
||||||
|
- Index: 16
|
||||||
|
Value: 16
|
||||||
|
CostsHuman:
|
||||||
|
Price: 100000
|
||||||
|
- Index: 17
|
||||||
|
Value: 17
|
||||||
|
CostsHuman:
|
||||||
|
Price: 100000
|
||||||
|
- Index: 18
|
||||||
|
Value: 18
|
||||||
|
CostsHuman:
|
||||||
|
Price: 100000
|
||||||
|
- Index: 19
|
||||||
|
Value: 19
|
||||||
|
CostsHuman:
|
||||||
|
Price: 100000
|
||||||
|
- Index: 20
|
||||||
|
Value: 20
|
||||||
|
CostsHuman:
|
||||||
|
Price: 100000
|
||||||
|
- Index: 21
|
||||||
|
Value: 21
|
||||||
|
CostsHuman:
|
||||||
|
Price: 100000
|
||||||
|
- Index: 22
|
||||||
|
Value: 22
|
||||||
|
CostsHuman:
|
||||||
|
Price: 100000
|
||||||
|
- Index: 23
|
||||||
|
Value: 23
|
||||||
|
CostsHuman:
|
||||||
|
Price: 100000
|
||||||
|
- Index: 24
|
||||||
|
Value: 24
|
||||||
|
CostsHuman:
|
||||||
|
RequiredItem: New_Style_Coupon
|
||||||
|
RequiredItemBox: C_New_Style_Box
|
||||||
|
- Index: 25
|
||||||
|
Value: 25
|
||||||
|
CostsHuman:
|
||||||
|
RequiredItem: New_Style_Coupon
|
||||||
|
RequiredItemBox: C_New_Style_Box
|
||||||
|
- Index: 26
|
||||||
|
Value: 26
|
||||||
|
CostsHuman:
|
||||||
|
RequiredItem: New_Style_Coupon
|
||||||
|
RequiredItemBox: C_New_Style_Box
|
||||||
|
- Index: 27
|
||||||
|
Value: 27
|
||||||
|
CostsHuman:
|
||||||
|
RequiredItem: New_Style_Coupon
|
||||||
|
RequiredItemBox: C_New_Style_Box
|
||||||
|
- Index: 28
|
||||||
|
Value: 28
|
||||||
|
CostsHuman:
|
||||||
|
RequiredItem: J_Shop_Coupon
|
||||||
|
RequiredItemBox: J_Shop_Coupon_Box
|
||||||
|
- Index: 29
|
||||||
|
Value: 29
|
||||||
|
CostsHuman:
|
||||||
|
RequiredItem: J_Shop_Coupon
|
||||||
|
RequiredItemBox: J_Shop_Coupon_Box
|
||||||
|
- Index: 30
|
||||||
|
Value: 30
|
||||||
|
CostsHuman:
|
||||||
|
RequiredItem: J_Shop_Coupon2
|
||||||
|
RequiredItemBox: J_Shop_Coupon2
|
||||||
|
- Index: 31
|
||||||
|
Value: 31
|
||||||
|
CostsHuman:
|
||||||
|
RequiredItem: J_Shop_Coupon2
|
||||||
|
RequiredItemBox: J_Shop_Coupon2
|
||||||
|
- Index: 32
|
||||||
|
Value: 32
|
||||||
|
CostsHuman:
|
||||||
|
Price: 100000
|
||||||
|
- Index: 33
|
||||||
|
Value: 33
|
||||||
|
CostsHuman:
|
||||||
|
Price: 3000000
|
||||||
|
- Index: 34
|
||||||
|
Value: 34
|
||||||
|
CostsHuman:
|
||||||
|
Price: 3000000
|
||||||
|
- Index: 35
|
||||||
|
Value: 35
|
||||||
|
CostsHuman:
|
||||||
|
Price: 3000000
|
||||||
|
- Index: 36
|
||||||
|
Value: 36
|
||||||
|
CostsHuman:
|
||||||
|
Price: 3000000
|
||||||
|
- Index: 37
|
||||||
|
Value: 37
|
||||||
|
CostsHuman:
|
||||||
|
Price: 3000000
|
||||||
|
- Index: 38
|
||||||
|
Value: 38
|
||||||
|
CostsHuman:
|
||||||
|
Price: 3000000
|
||||||
|
- Index: 39
|
||||||
|
Value: 39
|
||||||
|
CostsHuman:
|
||||||
|
Price: 3000000
|
||||||
|
- Index: 40
|
||||||
|
Value: 40
|
||||||
|
CostsHuman:
|
||||||
|
Price: 3000000
|
||||||
|
- Index: 41
|
||||||
|
Value: 41
|
||||||
|
CostsHuman:
|
||||||
|
Price: 3000000
|
||||||
|
- Index: 42
|
||||||
|
Value: 42
|
||||||
|
CostsHuman:
|
||||||
|
Price: 3000000
|
||||||
|
- Look: Clothes_Color
|
||||||
|
Options:
|
||||||
|
- Index: 1
|
||||||
|
Value: 0
|
||||||
|
CostsHuman:
|
||||||
|
RequiredItem: Clothing_Dye_Coupon_II
|
||||||
|
RequiredItemBox: CCloth_Dye_Coupon2_Box
|
||||||
|
CostsDoram:
|
||||||
|
RequiredItem: Clothing_Dye_Coupon_II
|
||||||
|
RequiredItemBox: CCloth_Dye_Coupon2_Box
|
||||||
|
- Index: 2
|
||||||
|
Value: 2
|
||||||
|
CostsHuman:
|
||||||
|
RequiredItem: Clothing_Dye_Coupon
|
||||||
|
RequiredItemBox: CCloth_Dye_Coupon_Box
|
||||||
|
CostsDoram:
|
||||||
|
RequiredItem: Clothing_Dye_Coupon
|
||||||
|
RequiredItemBox: CCloth_Dye_Coupon_Box
|
||||||
|
- Index: 3
|
||||||
|
Value: 3
|
||||||
|
CostsHuman:
|
||||||
|
RequiredItem: Clothing_Dye_Coupon
|
||||||
|
RequiredItemBox: CCloth_Dye_Coupon_Box
|
||||||
|
CostsDoram:
|
||||||
|
RequiredItem: Clothing_Dye_Coupon
|
||||||
|
RequiredItemBox: CCloth_Dye_Coupon_Box
|
||||||
|
- Index: 4
|
||||||
|
Value: 4
|
||||||
|
CostsHuman:
|
||||||
|
RequiredItem: Clothing_Dye_Coupon
|
||||||
|
RequiredItemBox: CCloth_Dye_Coupon_Box
|
||||||
|
- Index: 5
|
||||||
|
Value: 5
|
||||||
|
CostsHuman:
|
||||||
|
RequiredItem: Clothing_Dye_Coupon
|
||||||
|
RequiredItemBox: CCloth_Dye_Coupon_Box
|
||||||
|
- Index: 6
|
||||||
|
Value: 6
|
||||||
|
CostsHuman:
|
||||||
|
RequiredItem: Clothing_Dye_Coupon
|
||||||
|
RequiredItemBox: CCloth_Dye_Coupon_Box
|
||||||
|
- Index: 7
|
||||||
|
Value: 7
|
||||||
|
CostsHuman:
|
||||||
|
RequiredItem: Clothing_Dye_Coupon
|
||||||
|
RequiredItemBox: CCloth_Dye_Coupon_Box
|
||||||
|
- Look: Head_Top
|
||||||
|
Options:
|
||||||
|
- Index: 1
|
||||||
|
Value: Hat
|
||||||
|
CostsHuman:
|
||||||
|
Price: 1000
|
||||||
|
CostsDoram:
|
||||||
|
Price: 1000
|
||||||
|
- Index: 2
|
||||||
|
Value: Ribbon
|
||||||
|
CostsHuman:
|
||||||
|
Price: 800
|
||||||
|
CostsDoram:
|
||||||
|
Price: 800
|
||||||
|
- Index: 3
|
||||||
|
Value: Bandana
|
||||||
|
CostsHuman:
|
||||||
|
Price: 400
|
||||||
|
CostsDoram:
|
||||||
|
Price: 400
|
||||||
|
- Look: Head_Mid
|
||||||
|
Options:
|
||||||
|
- Index: 1
|
||||||
|
Value: One_Eyed_Glass
|
||||||
|
CostsHuman:
|
||||||
|
Price: 10000
|
||||||
|
CostsDoram:
|
||||||
|
Price: 10000
|
||||||
|
- Index: 2
|
||||||
|
Value: Sunglasses
|
||||||
|
CostsHuman:
|
||||||
|
Price: 5000
|
||||||
|
CostsDoram:
|
||||||
|
Price: 5000
|
||||||
|
- Index: 3
|
||||||
|
Value: Luxury_Sunglasses
|
||||||
|
CostsHuman:
|
||||||
|
Price: 24000
|
||||||
|
CostsDoram:
|
||||||
|
Price: 24000
|
||||||
|
- Index: 4
|
||||||
|
Value: Spinning_Eyes
|
||||||
|
CostsHuman:
|
||||||
|
Price: 20000
|
||||||
|
CostsDoram:
|
||||||
|
Price: 20000
|
||||||
|
- Index: 5
|
||||||
|
Value: Diver's_Goggles
|
||||||
|
CostsHuman:
|
||||||
|
Price: 3500
|
||||||
|
CostsDoram:
|
||||||
|
Price: 3500
|
||||||
|
- Index: 6
|
||||||
|
Value: Glasses
|
||||||
|
CostsHuman:
|
||||||
|
Price: 4000
|
||||||
|
CostsDoram:
|
||||||
|
Price: 4000
|
||||||
|
- Index: 7
|
||||||
|
Value: Eye_Bandage
|
||||||
|
CostsHuman:
|
||||||
|
Price: 1000
|
||||||
|
CostsDoram:
|
||||||
|
Price: 1000
|
||||||
|
- Look: Head_Bottom
|
||||||
|
Options:
|
||||||
|
- Index: 1
|
||||||
|
Value: Granpa_Beard
|
||||||
|
CostsHuman:
|
||||||
|
Price: 5000
|
||||||
|
CostsDoram:
|
||||||
|
Price: 5000
|
||||||
|
- Look: Body2
|
||||||
|
Options:
|
||||||
|
- Index: 1
|
||||||
|
Value: 0
|
||||||
|
CostsHuman:
|
||||||
|
RequiredItem: Costume_Ticket
|
||||||
|
- Index: 2
|
||||||
|
Value: 1
|
||||||
|
CostsHuman:
|
||||||
|
RequiredItem: Costume_Ticket
|
47
db/stylist.yml
Normal file
47
db/stylist.yml
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
# This file is a part of rAthena.
|
||||||
|
# Copyright(C) 2022 rAthena Development Team
|
||||||
|
# https://rathena.org - https://github.com/rathena
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
###########################################################################
|
||||||
|
# Stylist Database
|
||||||
|
###########################################################################
|
||||||
|
#
|
||||||
|
# Stylist Settings
|
||||||
|
#
|
||||||
|
###########################################################################
|
||||||
|
# - Look Look that will be changed.
|
||||||
|
# Options Possible options to select from.
|
||||||
|
# - Index Client side index of the option.
|
||||||
|
# Value Value of the look (can also be an item name).
|
||||||
|
# CostsHuman: Costs for human players.
|
||||||
|
# Price Required zeny. (Default: 0)
|
||||||
|
# RequiredItem Required item. (Default: None)
|
||||||
|
# RequiredItemBox Required item box. (Default: None)
|
||||||
|
# CostsDoram: Costs for doram players.
|
||||||
|
# Price Required zeny. (Default: 0)
|
||||||
|
# RequiredItem Required item. (Default: None)
|
||||||
|
# RequiredItemBox Required item box. (Default: None)
|
||||||
|
###########################################################################
|
||||||
|
|
||||||
|
Header:
|
||||||
|
Type: STYLIST_DB
|
||||||
|
Version: 1
|
||||||
|
|
||||||
|
Footer:
|
||||||
|
Imports:
|
||||||
|
- Path: db/re/stylist.yml
|
||||||
|
Mode: Renewal
|
||||||
|
- Path: db/import/stylist.yml
|
@ -1237,6 +1237,14 @@ Note: This command requires packet version 2016-10-12 or newer.
|
|||||||
|
|
||||||
---------------------------------------
|
---------------------------------------
|
||||||
|
|
||||||
|
@stylist
|
||||||
|
|
||||||
|
Opens the stylist user interface.
|
||||||
|
|
||||||
|
Note: This command requires packet version 2015-11-04 or newer.
|
||||||
|
|
||||||
|
---------------------------------------
|
||||||
|
|
||||||
@request <message>
|
@request <message>
|
||||||
|
|
||||||
Sends a message to all connected GMs (via the GM whisper system).
|
Sends a message to all connected GMs (via the GM whisper system).
|
||||||
|
@ -2897,6 +2897,14 @@ This feature requires 2016-10-12aRagexeRE or newer.
|
|||||||
|
|
||||||
---------------------------------------
|
---------------------------------------
|
||||||
|
|
||||||
|
*openstylist({<char id>})
|
||||||
|
|
||||||
|
Opens the stylist UI for the attached player or the given character id.
|
||||||
|
|
||||||
|
This feature requires packet version 2015-11-04 or newer.
|
||||||
|
|
||||||
|
---------------------------------------
|
||||||
|
|
||||||
*getareadropitem("<map name>",<x1>,<y1>,<x2>,<y2>,<item>)
|
*getareadropitem("<map name>",<x1>,<y1>,<x2>,<y2>,<item>)
|
||||||
|
|
||||||
This function will count all the items with the specified ID number lying on the
|
This function will count all the items with the specified ID number lying on the
|
||||||
|
@ -10655,6 +10655,24 @@ ACMD_FUNC(refineui)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ACMD_FUNC( stylist ){
|
||||||
|
nullpo_retr(-1, sd);
|
||||||
|
|
||||||
|
#if PACKETVER < 20151104
|
||||||
|
clif_displaymessage( fd, msg_txt( sd, 798 ) ); // This command requires packet version 2015-11-04 or newer.
|
||||||
|
return -1;
|
||||||
|
#else
|
||||||
|
|
||||||
|
if( sd->state.stylist_open ){
|
||||||
|
clif_displaymessage( fd, msg_txt( sd, 799 ) ); // You have already opened the stylist UI.
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
clif_ui_open( sd, OUT_UI_STYLIST, 0 );
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
#include "../custom/atcommand.inc"
|
#include "../custom/atcommand.inc"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -10975,6 +10993,7 @@ void atcommand_basecommands(void) {
|
|||||||
ACMD_DEF2("completequest", quest),
|
ACMD_DEF2("completequest", quest),
|
||||||
ACMD_DEF2("checkquest", quest),
|
ACMD_DEF2("checkquest", quest),
|
||||||
ACMD_DEF(refineui),
|
ACMD_DEF(refineui),
|
||||||
|
ACMD_DEFR(stylist, ATCMD_NOCONSOLE|ATCMD_NOAUTOTRADE),
|
||||||
};
|
};
|
||||||
AtCommandInfo* atcommand;
|
AtCommandInfo* atcommand;
|
||||||
int i;
|
int i;
|
||||||
|
173
src/map/clif.cpp
173
src/map/clif.cpp
@ -21509,6 +21509,13 @@ void clif_parse_changedress( int fd, struct map_session_data* sd ){
|
|||||||
void clif_ui_open( struct map_session_data *sd, enum out_ui_type ui_type, int32 data ){
|
void clif_ui_open( struct map_session_data *sd, enum out_ui_type ui_type, int32 data ){
|
||||||
nullpo_retv(sd);
|
nullpo_retv(sd);
|
||||||
|
|
||||||
|
// If the UI requires state tracking
|
||||||
|
switch( ui_type ){
|
||||||
|
case OUT_UI_STYLIST:
|
||||||
|
sd->state.stylist_open = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
int fd = sd->fd;
|
int fd = sd->fd;
|
||||||
|
|
||||||
WFIFOHEAD(fd,packet_len(0xae2));
|
WFIFOHEAD(fd,packet_len(0xae2));
|
||||||
@ -22364,6 +22371,172 @@ void clif_parse_unequipall( int fd, struct map_session_data* sd ){
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void clif_stylist_response( struct map_session_data* sd, bool failed ){
|
||||||
|
#if PACKETVER >= 20151104
|
||||||
|
struct PACKET_ZC_STYLE_CHANGE_RES p = {};
|
||||||
|
|
||||||
|
p.PacketType = HEADER_ZC_STYLE_CHANGE_RES;
|
||||||
|
p.flag = failed;
|
||||||
|
|
||||||
|
clif_send( &p, sizeof( p ), &sd->bl, SELF );
|
||||||
|
|
||||||
|
if( !failed ){
|
||||||
|
sd->state.stylist_open = false;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
bool clif_parse_stylist_buy_sub( struct map_session_data* sd, _look look, int16 index ){
|
||||||
|
std::shared_ptr<s_stylist_list> list = stylist_db.find( look );
|
||||||
|
|
||||||
|
if( list == nullptr ){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<s_stylist_entry> entry = util::umap_find( list->entries, index );
|
||||||
|
|
||||||
|
if( entry == nullptr ){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<s_stylist_costs> costs;
|
||||||
|
|
||||||
|
if( ( sd->class_ & MAPID_BASEMASK ) == MAPID_SUMMONER ){
|
||||||
|
costs = entry->doram;
|
||||||
|
}else{
|
||||||
|
costs = entry->human;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( costs == nullptr ){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( sd->status.zeny < costs->price ){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int16 inventoryIndex = -1;
|
||||||
|
|
||||||
|
if( costs->requiredItem != 0 ){
|
||||||
|
inventoryIndex = pc_search_inventory( sd, costs->requiredItem );
|
||||||
|
|
||||||
|
if( inventoryIndex < 0 ){
|
||||||
|
// No other option
|
||||||
|
if( costs->requiredItemBox == 0 ){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the box that contains the item is in the inventory
|
||||||
|
inventoryIndex = pc_search_inventory( sd, costs->requiredItemBox );
|
||||||
|
|
||||||
|
// The box containing the item also does not exist
|
||||||
|
if( inventoryIndex < 0 ){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}else if( costs->requiredItemBox != 0 ){
|
||||||
|
inventoryIndex = pc_search_inventory( sd, costs->requiredItem );
|
||||||
|
|
||||||
|
if( inventoryIndex < 0 ){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( inventoryIndex >= 0 && pc_delitem( sd, inventoryIndex, 1, 0, 0, LOG_TYPE_OTHER ) != 0 ){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( costs->price > 0 && pc_payzeny( sd, costs->price, LOG_TYPE_OTHER, nullptr ) != 0 ){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch( look ){
|
||||||
|
case LOOK_HAIR:
|
||||||
|
case LOOK_HAIR_COLOR:
|
||||||
|
case LOOK_CLOTHES_COLOR:
|
||||||
|
case LOOK_BODY2:
|
||||||
|
pc_changelook( sd, look, entry->value );
|
||||||
|
break;
|
||||||
|
case LOOK_HEAD_BOTTOM:
|
||||||
|
case LOOK_HEAD_MID:
|
||||||
|
case LOOK_HEAD_TOP: {
|
||||||
|
struct mail_message msg = {};
|
||||||
|
|
||||||
|
msg.dest_id = sd->status.char_id;
|
||||||
|
safestrncpy( msg.send_name, "Styling Shop", NAME_LENGTH );
|
||||||
|
safestrncpy( msg.title, "<MSG>2949</MSG>", MAIL_TITLE_LENGTH );
|
||||||
|
safestrncpy( msg.body, "<MSG>2950</MSG>", MAIL_BODY_LENGTH );
|
||||||
|
|
||||||
|
msg.item[0].nameid = entry->value;
|
||||||
|
msg.item[0].identify = 1;
|
||||||
|
msg.item[0].amount = 1;
|
||||||
|
|
||||||
|
msg.status = MAIL_NEW;
|
||||||
|
msg.type = MAIL_INBOX_NORMAL;
|
||||||
|
msg.timestamp = time( nullptr );
|
||||||
|
|
||||||
|
intif_Mail_send( 0, &msg );
|
||||||
|
|
||||||
|
} break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void clif_parse_stylist_buy( int fd, struct map_session_data* sd ){
|
||||||
|
#if PACKETVER >= 20151104
|
||||||
|
#if PACKETVER >= 20180516
|
||||||
|
struct PACKET_CZ_REQ_STYLE_CHANGE2* p = (struct PACKET_CZ_REQ_STYLE_CHANGE2*)RFIFOP( fd, 0 );
|
||||||
|
#else
|
||||||
|
struct PACKET_CZ_REQ_STYLE_CHANGE* p = (struct PACKET_CZ_REQ_STYLE_CHANGE*)RFIFOP( fd, 0 );
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
if( p->HeadPalette != 0 && !clif_parse_stylist_buy_sub( sd, LOOK_HAIR_COLOR, p->HeadPalette ) ){
|
||||||
|
clif_stylist_response( sd, true );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( p->HeadStyle != 0 && !clif_parse_stylist_buy_sub( sd, LOOK_HAIR, p->HeadStyle ) ){
|
||||||
|
clif_stylist_response( sd, true );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( p->BodyPalette != 0 && !clif_parse_stylist_buy_sub( sd, LOOK_CLOTHES_COLOR, p->BodyPalette ) ){
|
||||||
|
clif_stylist_response( sd, true );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( p->TopAccessory != 0 && !clif_parse_stylist_buy_sub( sd, LOOK_HEAD_TOP, p->TopAccessory ) ){
|
||||||
|
clif_stylist_response( sd, true );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( p->MidAccessory != 0 && !clif_parse_stylist_buy_sub( sd, LOOK_HEAD_MID, p->MidAccessory ) ){
|
||||||
|
clif_stylist_response( sd, true );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( p->BottomAccessory != 0 && !clif_parse_stylist_buy_sub( sd, LOOK_HEAD_BOTTOM, p->BottomAccessory ) ){
|
||||||
|
clif_stylist_response( sd, true );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if PACKETVER >= 20180516
|
||||||
|
if( p->BodyStyle != 0 && ( sd->class_ & JOBL_THIRD ) != 0 && ( sd->class_ & JOBL_FOURTH ) == 0 && !clif_parse_stylist_buy_sub( sd, LOOK_BODY2, p->BodyStyle ) ){
|
||||||
|
clif_stylist_response( sd, true );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
clif_stylist_response( sd, false );
|
||||||
|
}
|
||||||
|
|
||||||
|
void clif_parse_stylist_close( int fd, struct map_session_data* sd ){
|
||||||
|
#if PACKETVER >= 20151104
|
||||||
|
sd->state.stylist_open = false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
/*==========================================
|
/*==========================================
|
||||||
* Main client packet processing function
|
* Main client packet processing function
|
||||||
*------------------------------------------*/
|
*------------------------------------------*/
|
||||||
|
@ -1135,6 +1135,7 @@ enum in_ui_type : int8 {
|
|||||||
};
|
};
|
||||||
|
|
||||||
enum out_ui_type : int8 {
|
enum out_ui_type : int8 {
|
||||||
|
OUT_UI_STYLIST = 1,
|
||||||
OUT_UI_ATTENDANCE = 7
|
OUT_UI_ATTENDANCE = 7
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -2273,6 +2273,11 @@
|
|||||||
parseable_packet(0x0980,7,clif_parse_SelectCart,2,6); // CZ_SELECTCART
|
parseable_packet(0x0980,7,clif_parse_SelectCart,2,6); // CZ_SELECTCART
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if PACKETVER >= 20151104
|
||||||
|
parseable_packet( HEADER_CZ_REQ_STYLE_CHANGE, sizeof( PACKET_CZ_REQ_STYLE_CHANGE ), clif_parse_stylist_buy, 0 );
|
||||||
|
parseable_packet( HEADER_CZ_REQ_STYLE_CLOSE, sizeof( PACKET_CZ_REQ_STYLE_CLOSE ), clif_parse_stylist_close, 0 );
|
||||||
|
#endif
|
||||||
|
|
||||||
// 2016-03-02bRagexe
|
// 2016-03-02bRagexe
|
||||||
#if PACKETVER >= 20160302
|
#if PACKETVER >= 20160302
|
||||||
packet(0x0A51,34);
|
packet(0x0A51,34);
|
||||||
@ -2394,6 +2399,10 @@
|
|||||||
packet(0x0ADD, 22);
|
packet(0x0ADD, 22);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if PACKETVER >= 20180516
|
||||||
|
parseable_packet( HEADER_CZ_REQ_STYLE_CHANGE2, sizeof( PACKET_CZ_REQ_STYLE_CHANGE2 ), clif_parse_stylist_buy, 0 );
|
||||||
|
#endif
|
||||||
|
|
||||||
#if PACKETVER_MAIN_NUM >= 20181002 || PACKETVER_RE_NUM >= 20181002 || PACKETVER_ZERO_NUM >= 20181010
|
#if PACKETVER_MAIN_NUM >= 20181002 || PACKETVER_RE_NUM >= 20181002 || PACKETVER_ZERO_NUM >= 20181010
|
||||||
parseable_packet( 0x0B10, sizeof( struct PACKET_CZ_START_USE_SKILL ), clif_parse_StartUseSkillToId, 0 );
|
parseable_packet( 0x0B10, sizeof( struct PACKET_CZ_START_USE_SKILL ), clif_parse_StartUseSkillToId, 0 );
|
||||||
parseable_packet( 0x0B11, sizeof( struct PACKET_CZ_STOP_USE_SKILL ), clif_parse_StopUseSkillToId, 0 );
|
parseable_packet( 0x0B11, sizeof( struct PACKET_CZ_STOP_USE_SKILL ), clif_parse_StopUseSkillToId, 0 );
|
||||||
|
@ -343,5 +343,6 @@
|
|||||||
<Copy SourceFiles="$(SolutionDir)db\import-tmpl\spellbook_db.yml" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\spellbook_db.yml')" />
|
<Copy SourceFiles="$(SolutionDir)db\import-tmpl\spellbook_db.yml" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\spellbook_db.yml')" />
|
||||||
<Copy SourceFiles="$(SolutionDir)db\import-tmpl\statpoint.yml" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\statpoint.yml')" />
|
<Copy SourceFiles="$(SolutionDir)db\import-tmpl\statpoint.yml" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\statpoint.yml')" />
|
||||||
<Copy SourceFiles="$(SolutionDir)db\import-tmpl\status_disabled.txt" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\status_disabled.txt')" />
|
<Copy SourceFiles="$(SolutionDir)db\import-tmpl\status_disabled.txt" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\status_disabled.txt')" />
|
||||||
|
<Copy SourceFiles="$(SolutionDir)db\import-tmpl\stylist.yml" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\stylist.yml')" />
|
||||||
</Target>
|
</Target>
|
||||||
</Project>
|
</Project>
|
||||||
|
270
src/map/npc.cpp
270
src/map/npc.cpp
@ -121,6 +121,271 @@ struct script_event_s{
|
|||||||
// Holds pointers to the commonly executed scripts for speedup. [Skotlex]
|
// Holds pointers to the commonly executed scripts for speedup. [Skotlex]
|
||||||
std::map<enum npce_event, std::vector<struct script_event_s>> script_event;
|
std::map<enum npce_event, std::vector<struct script_event_s>> script_event;
|
||||||
|
|
||||||
|
const std::string StylistDatabase::getDefaultLocation(){
|
||||||
|
return std::string(db_path) + "/stylist.yml";
|
||||||
|
}
|
||||||
|
|
||||||
|
bool StylistDatabase::parseCostNode( std::shared_ptr<s_stylist_entry> entry, bool doram, const YAML::Node& node ){
|
||||||
|
std::shared_ptr<s_stylist_costs> costs = doram ? entry->doram : entry->human;
|
||||||
|
bool costs_exists = costs != nullptr;
|
||||||
|
|
||||||
|
if( !costs_exists ){
|
||||||
|
costs = std::make_shared<s_stylist_costs>();
|
||||||
|
}
|
||||||
|
|
||||||
|
if( this->nodeExists( node, "Price" ) ){
|
||||||
|
uint32 price;
|
||||||
|
|
||||||
|
if( !this->asUInt32( node, "Price", price ) ){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( price > MAX_ZENY ){
|
||||||
|
this->invalidWarning( node["Price"], "stylist_parseCostNode: Price %u is too high, capping to MAX_ZENY...\n", price );
|
||||||
|
price = MAX_ZENY;
|
||||||
|
}
|
||||||
|
|
||||||
|
costs->price = price;
|
||||||
|
}else{
|
||||||
|
if( !costs_exists ){
|
||||||
|
costs->price = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( this->nodeExists( node, "RequiredItem" ) ){
|
||||||
|
std::string item;
|
||||||
|
|
||||||
|
if( !this->asString( node, "RequiredItem", item ) ){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<item_data> id = item_db.search_aegisname( item.c_str() );
|
||||||
|
|
||||||
|
if( id == nullptr ){
|
||||||
|
this->invalidWarning( node["RequiredItem"], "stylist_parseCostNode: Unknown item \"%s\"...\n", item.c_str() );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
costs->requiredItem = id->nameid;
|
||||||
|
}else{
|
||||||
|
if( !costs_exists ){
|
||||||
|
costs->requiredItem = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( this->nodeExists( node, "RequiredItemBox" ) ){
|
||||||
|
std::string item;
|
||||||
|
|
||||||
|
if( !this->asString( node, "RequiredItemBox", item ) ){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<item_data> id = item_db.search_aegisname( item.c_str() );
|
||||||
|
|
||||||
|
if( id == nullptr ){
|
||||||
|
this->invalidWarning( node["RequiredItemBox"], "stylist_parseCostNode: Unknown item \"%s\"...\n", item.c_str() );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
costs->requiredItemBox = id->nameid;
|
||||||
|
}else{
|
||||||
|
if( !costs_exists ){
|
||||||
|
costs->requiredItemBox = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( !costs_exists ){
|
||||||
|
if( doram ){
|
||||||
|
entry->doram = costs;
|
||||||
|
}else{
|
||||||
|
entry->human = costs;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64 StylistDatabase::parseBodyNode( const YAML::Node &node ){
|
||||||
|
if( !this->nodesExist( node, { "Look", "Options" } ) ){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string look_str;
|
||||||
|
|
||||||
|
if( !this->asString( node, "Look", look_str ) ){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int64 constant;
|
||||||
|
|
||||||
|
if( !script_get_constant( ( "LOOK_" + look_str ).c_str(), &constant ) ){
|
||||||
|
this->invalidWarning( node["Look"], "stylist_parseBodyNode: Invalid look %s.\n", look_str.c_str() );
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch( constant ){
|
||||||
|
case LOOK_HEAD_TOP:
|
||||||
|
case LOOK_HEAD_MID:
|
||||||
|
case LOOK_HEAD_BOTTOM:
|
||||||
|
case LOOK_HAIR:
|
||||||
|
case LOOK_HAIR_COLOR:
|
||||||
|
case LOOK_CLOTHES_COLOR:
|
||||||
|
case LOOK_BODY2:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
this->invalidWarning( node["Look"], "stylist_parseBodyNode: Unsupported look value \"%s\"...\n", look_str.c_str() );
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<s_stylist_list> list = this->find( (uint32)constant );
|
||||||
|
bool exists = list != nullptr;
|
||||||
|
uint64 count = 0;
|
||||||
|
|
||||||
|
if( !exists ){
|
||||||
|
list = std::make_shared<s_stylist_list>();
|
||||||
|
list->look = (uint16)constant;
|
||||||
|
}
|
||||||
|
|
||||||
|
for( const YAML::Node& optionNode : node["Options"] ){
|
||||||
|
int16 index;
|
||||||
|
|
||||||
|
if( !this->asInt16( optionNode, "Index", index ) ){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( index == 0 ){
|
||||||
|
this->invalidWarning( optionNode["Index"], "stylist_parseBodyNode: Unsupported index value \"%hd\"...\n", index );
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<s_stylist_entry> entry = util::umap_find( list->entries, index );
|
||||||
|
bool entry_exists = entry != nullptr;
|
||||||
|
|
||||||
|
if( !entry_exists ){
|
||||||
|
entry = std::make_shared<s_stylist_entry>();
|
||||||
|
entry->look = list->look;
|
||||||
|
entry->index = index;
|
||||||
|
|
||||||
|
if( !this->nodesExist( optionNode, { "Value" } ) ){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( this->nodeExists( optionNode, "Value" ) ){
|
||||||
|
uint32 value;
|
||||||
|
|
||||||
|
switch( list->look ){
|
||||||
|
case LOOK_HEAD_TOP:
|
||||||
|
case LOOK_HEAD_MID:
|
||||||
|
case LOOK_HEAD_BOTTOM: {
|
||||||
|
std::string item;
|
||||||
|
|
||||||
|
if( !this->asString( optionNode, "Value", item ) ){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<item_data> id = item_db.search_aegisname( item.c_str() );
|
||||||
|
|
||||||
|
if( id == nullptr ){
|
||||||
|
this->invalidWarning( optionNode["Value"], "stylist_parseBodyNode: Unknown item \"%s\"...\n", item.c_str() );
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
value = id->nameid;
|
||||||
|
} break;
|
||||||
|
case LOOK_HAIR:
|
||||||
|
if( !this->asUInt32( optionNode, "Value", value ) ){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( value < MIN_HAIR_STYLE ){
|
||||||
|
this->invalidWarning( optionNode["Value"], "stylist_parseBodyNode: hair style \"%u\" is too low...\n", value );
|
||||||
|
return 0;
|
||||||
|
}else if( value > MAX_HAIR_STYLE ){
|
||||||
|
this->invalidWarning( optionNode["Value"], "stylist_parseBodyNode: hair style \"%u\" is too high...\n", value );
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case LOOK_HAIR_COLOR:
|
||||||
|
if( !this->asUInt32( optionNode, "Value", value ) ){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( value < MIN_HAIR_COLOR ){
|
||||||
|
this->invalidWarning( optionNode["Value"], "stylist_parseBodyNode: hair color \"%u\" is too low...\n", value );
|
||||||
|
return 0;
|
||||||
|
}else if( value > MAX_HAIR_COLOR ){
|
||||||
|
this->invalidWarning( optionNode["Value"], "stylist_parseBodyNode: hair color \"%u\" is too high...\n", value );
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case LOOK_CLOTHES_COLOR:
|
||||||
|
if( !this->asUInt32( optionNode, "Value", value ) ){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( value < MIN_CLOTH_COLOR ){
|
||||||
|
this->invalidWarning( optionNode["Value"], "stylist_parseBodyNode: cloth color \"%u\" is too low...\n", value );
|
||||||
|
return 0;
|
||||||
|
}else if( value > MAX_CLOTH_COLOR ){
|
||||||
|
this->invalidWarning( optionNode["Value"], "stylist_parseBodyNode: cloth color \"%u\" is too high...\n", value );
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case LOOK_BODY2:
|
||||||
|
if( !this->asUInt32( optionNode, "Value", value ) ){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( value < MIN_BODY_STYLE ){
|
||||||
|
this->invalidWarning( optionNode["Value"], "stylist_parseBodyNode: body style \"%u\" is too low...\n", value );
|
||||||
|
return 0;
|
||||||
|
}else if( value > MAX_BODY_STYLE ){
|
||||||
|
this->invalidWarning( optionNode["Value"], "stylist_parseBodyNode: body style \"%u\" is too high...\n", value );
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
entry->value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( this->nodeExists( optionNode, "CostsHuman" ) ) {
|
||||||
|
if( !this->parseCostNode( entry, false, optionNode["CostsHuman"] ) ){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
if( !entry_exists ){
|
||||||
|
entry->human = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( this->nodeExists( optionNode, "CostsDoram" ) ) {
|
||||||
|
if( !this->parseCostNode( entry, true, optionNode["CostsDoram"] ) ){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
if( !entry_exists ){
|
||||||
|
entry->doram = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( !entry_exists ){
|
||||||
|
list->entries[index] = entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( !exists ){
|
||||||
|
this->put( (uint32)constant, list );
|
||||||
|
}
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
StylistDatabase stylist_db;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the viewdata for normal NPC classes.
|
* Returns the viewdata for normal NPC classes.
|
||||||
* @param class_: NPC class ID
|
* @param class_: NPC class ID
|
||||||
@ -4785,6 +5050,8 @@ int npc_reload(void) {
|
|||||||
"\t-'" CL_WHITE "%d" CL_RESET "' Mobs Not Cached\n",
|
"\t-'" CL_WHITE "%d" CL_RESET "' Mobs Not Cached\n",
|
||||||
npc_id - npc_new_min, npc_warp, npc_shop, npc_script, npc_mob, npc_cache_mob, npc_delay_mob);
|
npc_id - npc_new_min, npc_warp, npc_shop, npc_script, npc_mob, npc_cache_mob, npc_delay_mob);
|
||||||
|
|
||||||
|
stylist_db.reload();
|
||||||
|
|
||||||
//Re-read the NPC Script Events cache.
|
//Re-read the NPC Script Events cache.
|
||||||
npc_read_event_script();
|
npc_read_event_script();
|
||||||
|
|
||||||
@ -4851,6 +5118,7 @@ void do_final_npc(void) {
|
|||||||
#if PACKETVER >= 20131223
|
#if PACKETVER >= 20131223
|
||||||
NPCMarketDB->destroy(NPCMarketDB, npc_market_free);
|
NPCMarketDB->destroy(NPCMarketDB, npc_market_free);
|
||||||
#endif
|
#endif
|
||||||
|
stylist_db.clear();
|
||||||
ers_destroy(timer_event_ers);
|
ers_destroy(timer_event_ers);
|
||||||
ers_destroy(npc_sc_display_ers);
|
ers_destroy(npc_sc_display_ers);
|
||||||
npc_clearsrcfile();
|
npc_clearsrcfile();
|
||||||
@ -4936,6 +5204,8 @@ void do_init_npc(void){
|
|||||||
"\t-'" CL_WHITE "%d" CL_RESET "' Mobs Not Cached\n",
|
"\t-'" CL_WHITE "%d" CL_RESET "' Mobs Not Cached\n",
|
||||||
npc_id - START_NPC_NUM, npc_warp, npc_shop, npc_script, npc_mob, npc_cache_mob, npc_delay_mob);
|
npc_id - START_NPC_NUM, npc_warp, npc_shop, npc_script, npc_mob, npc_cache_mob, npc_delay_mob);
|
||||||
|
|
||||||
|
stylist_db.load();
|
||||||
|
|
||||||
// set up the events cache
|
// set up the events cache
|
||||||
npc_read_event_script();
|
npc_read_event_script();
|
||||||
|
|
||||||
|
@ -51,6 +51,40 @@ struct s_npc_buy_list {
|
|||||||
#pragma pack(pop)
|
#pragma pack(pop)
|
||||||
#endif // not NetBSD < 6 / Solaris
|
#endif // not NetBSD < 6 / Solaris
|
||||||
|
|
||||||
|
struct s_stylist_costs{
|
||||||
|
uint32 price;
|
||||||
|
t_itemid requiredItem;
|
||||||
|
t_itemid requiredItemBox;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct s_stylist_entry{
|
||||||
|
uint16 look;
|
||||||
|
int16 index;
|
||||||
|
uint32 value;
|
||||||
|
std::shared_ptr<s_stylist_costs> human;
|
||||||
|
std::shared_ptr<s_stylist_costs> doram;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct s_stylist_list{
|
||||||
|
uint16 look;
|
||||||
|
std::unordered_map<int16, std::shared_ptr<s_stylist_entry>> entries;
|
||||||
|
};
|
||||||
|
|
||||||
|
class StylistDatabase : public TypesafeYamlDatabase<uint32, s_stylist_list>{
|
||||||
|
private:
|
||||||
|
bool parseCostNode( std::shared_ptr<s_stylist_entry> entry, bool doram, const YAML::Node& node );
|
||||||
|
|
||||||
|
public:
|
||||||
|
StylistDatabase() : TypesafeYamlDatabase( "STYLIST_DB", 1 ){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string getDefaultLocation();
|
||||||
|
uint64 parseBodyNode( const YAML::Node& node );
|
||||||
|
};
|
||||||
|
|
||||||
|
extern StylistDatabase stylist_db;
|
||||||
|
|
||||||
struct s_questinfo {
|
struct s_questinfo {
|
||||||
e_questinfo_types icon;
|
e_questinfo_types icon;
|
||||||
e_questinfo_markcolor color;
|
e_questinfo_markcolor color;
|
||||||
|
@ -222,6 +222,10 @@ struct PACKET_CZ_UNCONFIRMED_RODEX_RETURN{
|
|||||||
uint32 msgId;
|
uint32 msgId;
|
||||||
} __attribute__((packed));
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
struct PACKET_CZ_REQ_STYLE_CLOSE{
|
||||||
|
int16 packetType;
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
// NetBSD 5 and Solaris don't like pragma pack but accept the packed attribute
|
// NetBSD 5 and Solaris don't like pragma pack but accept the packed attribute
|
||||||
#if !defined( sun ) && ( !defined( __NETBSD__ ) || __NetBSD_Version__ >= 600000000 )
|
#if !defined( sun ) && ( !defined( __NETBSD__ ) || __NetBSD_Version__ >= 600000000 )
|
||||||
#pragma pack( pop )
|
#pragma pack( pop )
|
||||||
@ -275,6 +279,10 @@ DEFINE_PACKET_HEADER(ZC_ACK_COUNT_BARGAIN_SALE_ITEM, 0x9c4)
|
|||||||
DEFINE_PACKET_HEADER(ZC_ACK_GUILDSTORAGE_LOG, 0x9da)
|
DEFINE_PACKET_HEADER(ZC_ACK_GUILDSTORAGE_LOG, 0x9da)
|
||||||
DEFINE_PACKET_HEADER(CZ_NPC_MARKET_PURCHASE, 0x9d6)
|
DEFINE_PACKET_HEADER(CZ_NPC_MARKET_PURCHASE, 0x9d6)
|
||||||
DEFINE_PACKET_HEADER(CZ_REQ_APPLY_BARGAIN_SALE_ITEM2, 0xa3d)
|
DEFINE_PACKET_HEADER(CZ_REQ_APPLY_BARGAIN_SALE_ITEM2, 0xa3d)
|
||||||
|
DEFINE_PACKET_HEADER(CZ_REQ_STYLE_CHANGE, 0xa46)
|
||||||
|
DEFINE_PACKET_HEADER(ZC_STYLE_CHANGE_RES, 0xa47)
|
||||||
|
DEFINE_PACKET_HEADER(CZ_REQ_STYLE_CLOSE, 0xa48)
|
||||||
|
DEFINE_PACKET_HEADER(CZ_REQ_STYLE_CHANGE2, 0xafc)
|
||||||
DEFINE_PACKET_HEADER(ZC_REMOVE_EFFECT, 0x0b0d)
|
DEFINE_PACKET_HEADER(ZC_REMOVE_EFFECT, 0x0b0d)
|
||||||
DEFINE_PACKET_HEADER(CZ_UNCONFIRMED_TSTATUS_UP, 0x0b24)
|
DEFINE_PACKET_HEADER(CZ_UNCONFIRMED_TSTATUS_UP, 0x0b24)
|
||||||
DEFINE_PACKET_HEADER(CZ_GUILD_EMBLEM_CHANGE2, 0x0b46)
|
DEFINE_PACKET_HEADER(CZ_GUILD_EMBLEM_CHANGE2, 0x0b46)
|
||||||
|
@ -382,6 +382,7 @@ struct map_session_data {
|
|||||||
bool mail_writing; // Whether the player is currently writing a mail in RODEX or not
|
bool mail_writing; // Whether the player is currently writing a mail in RODEX or not
|
||||||
bool cashshop_open;
|
bool cashshop_open;
|
||||||
bool sale_open;
|
bool sale_open;
|
||||||
|
bool stylist_open;
|
||||||
unsigned int block_action : 10;
|
unsigned int block_action : 10;
|
||||||
bool refineui_open;
|
bool refineui_open;
|
||||||
} state;
|
} state;
|
||||||
@ -1049,9 +1050,15 @@ extern JobDatabase job_db;
|
|||||||
#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_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_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_istrading(sd) ( (sd)->npc_id || (sd)->state.vending || (sd)->state.buyingstore || (sd)->state.trading )
|
||||||
|
static bool pc_cant_act2( struct map_session_data* sd ){
|
||||||
|
return sd->state.vending || sd->state.buyingstore || (sd->sc.opt1 && sd->sc.opt1 != OPT1_BURNING)
|
||||||
|
|| sd->state.trading || sd->state.storage_flag || sd->state.prevend || sd->state.refineui_open
|
||||||
|
|| sd->state.stylist_open;
|
||||||
|
}
|
||||||
// equals pc_cant_act2 and additionally checks for chat rooms and npcs
|
// 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) ) )
|
static bool pc_cant_act( struct map_session_data* 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 )
|
return sd->npc_id || sd->chatID || pc_cant_act2( sd );
|
||||||
|
}
|
||||||
|
|
||||||
#define pc_setdir(sd,b,h) ( (sd)->ud.dir = (b) ,(sd)->head_dir = (h) )
|
#define pc_setdir(sd,b,h) ( (sd)->ud.dir = (b) ,(sd)->head_dir = (h) )
|
||||||
#define pc_setchatid(sd,n) ( (sd)->chatID = n )
|
#define pc_setchatid(sd,n) ( (sd)->chatID = n )
|
||||||
|
@ -25587,6 +25587,23 @@ BUILDIN_FUNC(mob_setidleevent){
|
|||||||
return SCRIPT_CMD_SUCCESS;
|
return SCRIPT_CMD_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BUILDIN_FUNC( openstylist ){
|
||||||
|
#if PACKETVER >= 20151104
|
||||||
|
struct map_session_data* sd;
|
||||||
|
|
||||||
|
if( !script_charid2sd( 2, sd ) ){
|
||||||
|
return SCRIPT_CMD_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
clif_ui_open( sd, OUT_UI_STYLIST, 0 );
|
||||||
|
|
||||||
|
return SCRIPT_CMD_SUCCESS;
|
||||||
|
#else
|
||||||
|
ShowError( "buildin_openstylist: This command requires packet version 2015-11-04 or newer.\n" );
|
||||||
|
return SCRIPT_CMD_FAILURE;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
#include "../custom/script.inc"
|
#include "../custom/script.inc"
|
||||||
|
|
||||||
// declarations that were supposed to be exported from npc_chat.cpp
|
// declarations that were supposed to be exported from npc_chat.cpp
|
||||||
@ -26291,6 +26308,7 @@ struct script_function buildin_func[] = {
|
|||||||
BUILDIN_DEF(mob_setidleevent, "is"),
|
BUILDIN_DEF(mob_setidleevent, "is"),
|
||||||
|
|
||||||
BUILDIN_DEF(setinstancevar,"rvi"),
|
BUILDIN_DEF(setinstancevar,"rvi"),
|
||||||
|
BUILDIN_DEF(openstylist, "?"),
|
||||||
#include "../custom/script_def.inc"
|
#include "../custom/script_def.inc"
|
||||||
|
|
||||||
{NULL,NULL,NULL},
|
{NULL,NULL,NULL},
|
||||||
|
Loading…
x
Reference in New Issue
Block a user