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.
|
||||
min_hair_style: 0
|
||||
max_hair_style: 27
|
||||
max_hair_style: 42
|
||||
min_hair_color: 0
|
||||
max_hair_color: 8
|
||||
min_cloth_color: 0
|
||||
max_cloth_color: 4
|
||||
max_cloth_color: 7
|
||||
min_body_style: 0
|
||||
max_body_style: 1
|
||||
|
||||
|
@ -876,7 +876,9 @@
|
||||
|
||||
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
|
||||
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
|
||||
NoAuction: true
|
||||
- Id: 6707
|
||||
AegisName: Jeremy_Beauty_Coupon
|
||||
Name: Jeremy Beauty Coupon
|
||||
AegisName: J_Shop_Coupon
|
||||
Name: Cash Hair Coupon
|
||||
Type: Etc
|
||||
Buy: 10
|
||||
Weight: 10
|
||||
@ -24023,9 +24023,10 @@ Body:
|
||||
Type: Etc
|
||||
Buy: 10
|
||||
- Id: 6959
|
||||
AegisName: aegis_6959
|
||||
Name: Costume Change Ticket
|
||||
AegisName: Costume_Ticket
|
||||
Name: Costume Change Ticket
|
||||
Type: Etc
|
||||
Buy: 0
|
||||
Trade:
|
||||
Override: 100
|
||||
NoDrop: true
|
||||
|
@ -39884,6 +39884,57 @@ Body:
|
||||
NoGuildStorage: true
|
||||
NoMail: 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
|
||||
AegisName: Siege_Map_Teleport_Scroll_Box_10
|
||||
Name: Siege Map Teleport Scroll Box(10)
|
||||
@ -42918,6 +42969,23 @@ Body:
|
||||
NoAuction: true
|
||||
Script: |
|
||||
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
|
||||
AegisName: Holy_Spirit_Scroll
|
||||
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>
|
||||
|
||||
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>)
|
||||
|
||||
This function will count all the items with the specified ID number lying on the
|
||||
|
@ -10655,6 +10655,24 @@ ACMD_FUNC(refineui)
|
||||
#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"
|
||||
|
||||
/**
|
||||
@ -10975,6 +10993,7 @@ void atcommand_basecommands(void) {
|
||||
ACMD_DEF2("completequest", quest),
|
||||
ACMD_DEF2("checkquest", quest),
|
||||
ACMD_DEF(refineui),
|
||||
ACMD_DEFR(stylist, ATCMD_NOCONSOLE|ATCMD_NOAUTOTRADE),
|
||||
};
|
||||
AtCommandInfo* atcommand;
|
||||
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 ){
|
||||
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;
|
||||
|
||||
WFIFOHEAD(fd,packet_len(0xae2));
|
||||
@ -22364,6 +22371,172 @@ void clif_parse_unequipall( int fd, struct map_session_data* sd ){
|
||||
#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
|
||||
*------------------------------------------*/
|
||||
|
@ -1135,6 +1135,7 @@ enum in_ui_type : int8 {
|
||||
};
|
||||
|
||||
enum out_ui_type : int8 {
|
||||
OUT_UI_STYLIST = 1,
|
||||
OUT_UI_ATTENDANCE = 7
|
||||
};
|
||||
|
||||
|
@ -2273,6 +2273,11 @@
|
||||
parseable_packet(0x0980,7,clif_parse_SelectCart,2,6); // CZ_SELECTCART
|
||||
#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
|
||||
#if PACKETVER >= 20160302
|
||||
packet(0x0A51,34);
|
||||
@ -2394,6 +2399,10 @@
|
||||
packet(0x0ADD, 22);
|
||||
#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
|
||||
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 );
|
||||
|
@ -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\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\stylist.yml" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\stylist.yml')" />
|
||||
</Target>
|
||||
</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]
|
||||
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.
|
||||
* @param class_: NPC class ID
|
||||
@ -4785,6 +5050,8 @@ int npc_reload(void) {
|
||||
"\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);
|
||||
|
||||
stylist_db.reload();
|
||||
|
||||
//Re-read the NPC Script Events cache.
|
||||
npc_read_event_script();
|
||||
|
||||
@ -4851,6 +5118,7 @@ void do_final_npc(void) {
|
||||
#if PACKETVER >= 20131223
|
||||
NPCMarketDB->destroy(NPCMarketDB, npc_market_free);
|
||||
#endif
|
||||
stylist_db.clear();
|
||||
ers_destroy(timer_event_ers);
|
||||
ers_destroy(npc_sc_display_ers);
|
||||
npc_clearsrcfile();
|
||||
@ -4936,6 +5204,8 @@ void do_init_npc(void){
|
||||
"\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);
|
||||
|
||||
stylist_db.load();
|
||||
|
||||
// set up the events cache
|
||||
npc_read_event_script();
|
||||
|
||||
|
@ -51,6 +51,40 @@ struct s_npc_buy_list {
|
||||
#pragma pack(pop)
|
||||
#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 {
|
||||
e_questinfo_types icon;
|
||||
e_questinfo_markcolor color;
|
||||
|
@ -222,6 +222,10 @@ struct PACKET_CZ_UNCONFIRMED_RODEX_RETURN{
|
||||
uint32 msgId;
|
||||
} __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
|
||||
#if !defined( sun ) && ( !defined( __NETBSD__ ) || __NetBSD_Version__ >= 600000000 )
|
||||
#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(CZ_NPC_MARKET_PURCHASE, 0x9d6)
|
||||
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(CZ_UNCONFIRMED_TSTATUS_UP, 0x0b24)
|
||||
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 cashshop_open;
|
||||
bool sale_open;
|
||||
bool stylist_open;
|
||||
unsigned int block_action : 10;
|
||||
bool refineui_open;
|
||||
} 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_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 )
|
||||
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
|
||||
#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 )
|
||||
static bool pc_cant_act( struct map_session_data* sd ){
|
||||
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_setchatid(sd,n) ( (sd)->chatID = n )
|
||||
|
@ -25587,6 +25587,23 @@ BUILDIN_FUNC(mob_setidleevent){
|
||||
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"
|
||||
|
||||
// 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(setinstancevar,"rvi"),
|
||||
BUILDIN_DEF(openstylist, "?"),
|
||||
#include "../custom/script_def.inc"
|
||||
|
||||
{NULL,NULL,NULL},
|
||||
|
Loading…
x
Reference in New Issue
Block a user