From 4c5b768b6ac5a561e96b492d66d44042227fb856 Mon Sep 17 00:00:00 2001 From: ai4rei Date: Sat, 19 Feb 2011 12:59:36 +0000 Subject: * Implemented buying store system (aka. reverse vending, purchase shop) together with related skill and items, without NPCs. - For SQL apply upgrade_svn14713_log.sql to upgrade tables `picklog` and `zenylog`; for TXT no action is necessary. - Requires 2010-04-20aRagexeRE or later and can be disabled in 'conf/battle/feature.conf'. git-svn-id: https://rathena.svn.sourceforge.net/svnroot/rathena/trunk@14713 54d463be-8e91-2dee-dedb-b68131a5f0ec --- Changelog-Trunk.txt | 4 + conf/Changelog.txt | 3 + conf/battle/feature.conf | 24 + conf/log_athena.conf | 1 + db/Changelog.txt | 6 + db/item_buyingstore.txt | 1013 ++++++++++++++++++++++++++++++++++++ db/item_db.txt | 4 +- db/packet_db.txt | 28 +- db/skill_db.txt | 3 + db/skill_require_db.txt | 2 + db/skill_tree.txt | 11 + doc/script_commands.txt | 17 +- sql-files/logs.sql | 8 +- sql-files/upgrade_svn14713_log.sql | 4 + src/common/mmo.h | 2 +- src/map/Makefile.in | 6 +- src/map/atcommand.c | 4 +- src/map/battle.c | 1 + src/map/battle.h | 1 + src/map/buyingstore.c | 359 +++++++++++++ src/map/buyingstore.h | 29 ++ src/map/chat.c | 7 +- src/map/clif.c | 323 +++++++++++- src/map/clif.h | 14 + src/map/itemdb.c | 28 + src/map/itemdb.h | 1 + src/map/log.h | 7 +- src/map/mail.c | 2 +- src/map/pc.h | 15 +- src/map/script.c | 18 + src/map/skill.c | 6 + src/map/trade.c | 4 +- src/map/unit.c | 2 + vcproj-10/map-server_sql.vcxproj | 2 + vcproj-10/map-server_txt.vcxproj | 2 + vcproj-6/map-server_sql.dsp | 8 + vcproj-6/map-server_txt.dsp | 8 + vcproj-7.1/map-server_sql.vcproj | 6 + vcproj-7.1/map-server_txt.vcproj | 6 + vcproj-8/map-server_sql.vcproj | 7 + vcproj-8/map-server_txt.vcproj | 8 + vcproj-9/map-server_sql.vcproj | 8 + vcproj-9/map-server_txt.vcproj | 8 + 43 files changed, 1978 insertions(+), 42 deletions(-) create mode 100644 conf/battle/feature.conf create mode 100644 db/item_buyingstore.txt create mode 100644 sql-files/upgrade_svn14713_log.sql create mode 100644 src/map/buyingstore.c create mode 100644 src/map/buyingstore.h diff --git a/Changelog-Trunk.txt b/Changelog-Trunk.txt index b5c9eff4d..8d361025d 100644 --- a/Changelog-Trunk.txt +++ b/Changelog-Trunk.txt @@ -1,5 +1,9 @@ Date Added +2011/02/19 + * Implemented buying store system (aka. reverse vending, purchase shop) together with related skill and items, without NPCs. [Ai4rei] + - For SQL apply upgrade_svn14713_log.sql to upgrade tables `picklog` and `zenylog`; for TXT no action is necessary. + - Requires 2010-04-20aRagexeRE or later and can be disabled in 'conf/battle/feature.conf'. 2011/02/17 * Merged enumeration update from renewal [14699/branches/renewal] for a future commit. [Ai4rei] 2011/02/16 diff --git a/conf/Changelog.txt b/conf/Changelog.txt index 78b261c0f..e7af03e4e 100644 --- a/conf/Changelog.txt +++ b/conf/Changelog.txt @@ -1,5 +1,8 @@ Date Added +2011/02/19 + * Rev. 14713 Added map-server feature settings file 'battle/feature.conf'. [Ai4rei] + - Added setting 'feature.buying_store' to enable/disable the buying store system. 2011/02/15 * Rev. 14707 Added map-server battle setting 'gm_check_minlevel'. [Ai4rei] 2011/02/06 diff --git a/conf/battle/feature.conf b/conf/battle/feature.conf new file mode 100644 index 000000000..934739c0f --- /dev/null +++ b/conf/battle/feature.conf @@ -0,0 +1,24 @@ +// ______ __ __ +// /\ _ \/\ \__/\ \ +// __\ \ \L\ \ \ ,_\ \ \___ __ ___ __ +// /'__`\ \ __ \ \ \/\ \ _ `\ /'__`\/' _ `\ /'__`\ +///\ __/\ \ \/\ \ \ \_\ \ \ \ \/\ __//\ \/\ \/\ \L\.\_ +//\ \____\\ \_\ \_\ \__\\ \_\ \_\ \____\ \_\ \_\ \__/.\_\ +// \/____/ \/_/\/_/\/__/ \/_/\/_/\/____/\/_/\/_/\/__/\/_/ +// _ _ _ _ _ _ _ _ _ _ _ _ _ +// / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ +//( e | n | g | l | i | s | h ) ( A | t | h | e | n | a ) +// \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ +// +//-------------------------------------------------------------- +// eAthena Feature Configuration File +//-------------------------------------------------------------- +// Note 1: Value is a config switch (on/off, yes/no or 1/0) +// Note 2: Value is in percents (100 means 100%) +// Note 3: Value is a bit field. If no description is given, +// assume unit types (1: Pc, 2: Mob, 4: Pet, 8: Homun) +//-------------------------------------------------------------- + +// Buying store (Note 1) +// Requires: 2010-04-20aRagexeRE or later +feature.buying_store: on diff --git a/conf/log_athena.conf b/conf/log_athena.conf index 2f8effd18..0d5378a8f 100644 --- a/conf/log_athena.conf +++ b/conf/log_athena.conf @@ -16,6 +16,7 @@ // 2048 - (R) Log items placed/retrieved from storage. // 4096 - (G) Log items placed/retrieved from guild storage. // 8192 - (E) Log mail system transactions. +// 16384 - (B) Log buying store transactions // Example: Log trades+vending+script items+created items: 2+4+64+1024 = 1094 enable_logs: 1 diff --git a/db/Changelog.txt b/db/Changelog.txt index add99e90d..3f164b3ce 100644 --- a/db/Changelog.txt +++ b/db/Changelog.txt @@ -9,6 +9,12 @@ 13005 Angelic Wing Dagger: NEED INFO. ======================= +2011/02/19 + * Rev. 14713 Database updates required by buying store system implementation. [Ai4rei] + - Added database of items, that can be sold to a buying store (item_buyingstore.txt). + - Added items Buy_Stall_Permit (6377) and Shabby_Purchase_Street_Stall_License (12548). + - Updated packet database with buying store related packets. + - Added skill 'Open Buying Store' (ALL_BUYING_STORE). 2011/02/06 * Rev. 14697 Added the missing restricted skills to zone 6 for Endless Tower. (bugreport:4707) [L0ne_W0lf] * Adjusted the rates for item using bAddEffOnSkill bonus. diff --git a/db/item_buyingstore.txt b/db/item_buyingstore.txt new file mode 100644 index 000000000..ec336c2a1 --- /dev/null +++ b/db/item_buyingstore.txt @@ -0,0 +1,1013 @@ +// Buying Store Item List +// List of items, that can be sold to buying stores. +// Format: +// Example: +// 512 // Apple +// Note: +// Items are in same order as data\buyingstoreitemlist.txt, which +// must be edited as well for the client to accept added items. + +// items from 2010-03-12 update +601 // Wing_Of_Fly +602 // Wing_Of_Butterfly +603 // Old_Blue_Box +604 // Branch_Of_Dead_Tree +605 // Anodyne +606 // Aloebera +607 // Yggdrasilberry +608 // Seed_Of_Yggdrasil +609 // Amulet +610 // Leaf_Of_Yggdrasil +611 // Spectacles +612 // Portable_Furnace +613 // Iron_Hammer +614 // Golden_Hammer +615 // Oridecon_Hammer +616 // Old_Card_Album +617 // Old_Violet_Box +618 // Worn_Out_Scroll +619 // Unripe_Apple +620 // Orange_Juice +621 // Bitter_Herb +622 // Rainbow_Carrot +623 // Earthworm_The_Dude +624 // Rotten_Fish +625 // Lusty_Iron +626 // Monster_Juice +627 // Sweet_Milk +628 // Well_Dried_Bone +629 // Singing_Flower +630 // Dew_Laden_Moss +631 // Deadly_Noxious_Herb +632 // Fatty_Chubby_Earthworm +633 // Baked_Yam +634 // Tropical_Banana +635 // Horror_Of_Tribe +636 // No_Recipient +637 // Old_Broom +638 // Silver_Knife_Of_Chaste +639 // Armlet_Of_Obedience +640 // Shining_Stone +641 // Contracts_In_Shadow +642 // Book_Of_Devil +643 // Pet_Incubator +644 // Gift_Box +645 // Center_Potion +656 // Awakening_Potion +657 // Berserk_Potion +658 // Union_Of_Tribe +659 // Heart_Of_Her +660 // Prohibition_Red_Candle +661 // Sway_Apron +662 // Inspector_Certificate +663 // Korea_Rice_Cake +664 // Gift_Box_1 +665 // Gift_Box_2 +666 // Gift_Box_3 +667 // Gift_Box_4 +668 // Handsei +669 // Rice_Cake_Soup +678 // Poison_Bottle +679 // Gold_Pill +681 // Memory_Of_Wedding +682 // Realgar_Wine +683 // Exorcize_Herb +684 // Durian +686 // Earth_Scroll_1_3 +687 // Earth_Scroll_1_5 +688 // Cold_Scroll_1_3 +689 // Cold_Scroll_1_5 +690 // Fire_Scroll_1_3 +691 // Fire_Scroll_1_5 +692 // Wind_Scroll_1_3 +693 // Wind_Scroll_1_5 +694 // Ghost_Scroll_1_3 +695 // Ghost_Scroll_1_5 +696 // Fire_Scroll_2_1 +697 // Fire_Scroll_2_5 +698 // Fire_Scroll_3_1 +699 // Fire_Scroll_3_5 +700 // Cold_Scroll_2_1 +12000 // Cold_Scroll_2_5 +12001 // Holy_Scroll_1_3 +12002 // Holy_Scroll_1_5 +12003 // Holy_Scroll_2_1 +12004 // Arrow_Container +12005 // Iron_Arrow_Container +12006 // Steel_Arrow_Container +12007 // Ori_Arrow_Container +12008 // Fire_Arrow_Container +12009 // Silver_Arrow_Container +12010 // Wind_Arrow_Container +12011 // Stone_Arrow_Container +12012 // Crystal_Arrow_Container +12013 // Shadow_Arrow_Container +12014 // Imma_Arrow_Container +12015 // Rusty_Arrow_Container +12016 // Speed_Up_Potion +12017 // Slow_Down_Potion +12018 // Fire_Cracker +12020 // Water_Of_Darkness +12027 // Giggling_Box +12028 // Box_Of_Thunder +12029 // Gloomy_Box +12030 // Box_Of_Grudge +12031 // Sleepy_Box +12032 // Box_Of_Storm +12033 // Box_Of_Sunlight +12034 // Painting_Box +12040 // Stone_Of_Intelligence_ +12041 // Str_Dish01 +12042 // Str_Dish02 +12043 // Str_Dish03 +12044 // Str_Dish04 +12045 // Str_Dish05 +12046 // Int_Dish01 +12047 // Int_Dish02 +12048 // Int_Dish03 +12049 // Int_Dish04 +12050 // Int_Dish05 +12051 // Vit_Dish01 +12052 // Vit_Dish02 +12053 // Vit_Dish03 +12054 // Vit_Dish04 +12055 // Vit_Dish05 +12056 // Agi_Dish01 +12057 // Agi_Dish02 +12058 // Agi_Dish03 +12059 // Agi_Dish04 +12060 // Agi_Dish05 +12061 // Dex_Dish01 +12062 // Dex_Dish02 +12063 // Dex_Dish03 +12064 // Dex_Dish04 +12065 // Dex_Dish05 +12066 // Luk_Dish01 +12067 // Luk_Dish02 +12068 // Luk_Dish03 +12069 // Luk_Dish04 +12070 // Luk_Dish05 +12071 // Str_Dish06 +12072 // Str_Dish07 +12073 // Str_Dish08 +12074 // Str_Dish09 +12075 // Str_Dish10 +12076 // Int_Dish06 +12077 // Int_Dish07 +12078 // Int_Dish08 +12079 // Int_Dish09 +12080 // Int_Dish10 +12081 // Vit_Dish06 +12082 // Vit_Dish07 +12083 // Vit_Dish08 +12084 // Vit_Dish09 +12085 // Vit_Dish10 +12086 // Agi_Dish06 +12087 // Agi_Dish07 +12088 // Agi_Dish08 +12089 // Agi_Dish09 +12090 // Agi_Dish10 +12091 // Dex_Dish06 +12092 // Dex_Dish07 +12093 // Dex_Dish08 +12094 // Dex_Dish09 +12095 // Dex_Dish10 +12096 // Luk_Dish06 +12097 // Luk_Dish07 +12098 // Luk_Dish08 +12099 // Luk_Dish09 +12100 // Luk_Dish10 +12101 // Citron +12102 // Meat_Skewer +12103 // Bloody_Dead_Branch +12104 // Random_Quiver +12105 // Set_Of_Taiming_Item +12106 // Accessory_Box +12107 // Wrapped_Mask +12108 // Bundle_Of_Magic_Scroll +12109 // Poring_Box +12110 // First_Aid_Kit +12111 // Food_Package +12112 // Tropical_Sograt +12113 // Vermilion_The_Beach +12114 // Elemental_Fire +12115 // Elemental_Water +12116 // Elemental_Earth +12117 // Elemental_Wind +12118 // Resist_Fire +12119 // Resist_Water +12120 // Resist_Earth +12121 // Resist_Wind +12122 // Sesame_Pastry +12123 // Honey_Pastry +12124 // Rainbow_Cake +12125 // Outdoor_Cooking_Kits +12126 // Indoor_Cooking_Kits +12127 // High_end_Cooking_Kits +12128 // Imperial_Cooking_Kits +12129 // Fantastic_Cooking_Kits +12130 // Cookie_Bag +12132 // Red_Bag +12144 // Sphere_Case_Wind +12145 // Sphere_Case_Darkness +12146 // Sphere_Case_Poison +12147 // Sphere_Case_Water +12148 // Sphere_Case_Fire +12149 // Bullet_Case +12150 // Bullet_Case_Blood +12151 // Bullet_Case_Silver +12183 // Holy_Arrow_Quiver +12184 // Mercenary_Red_Potion +12185 // Mercenary_Blue_Potion +12194 // Hometown_Gift +12195 // Plain_Rice_Cake +12196 // Hearty_Rice_Cake +12197 // Salty_Rice_Cake +12198 // Lucky_Rice_Cake +12241 // M_Center_Potion +12242 // M_Awakening_Potion +12243 // M_Berserk_Potion +12246 // Magic_Card_Album +12260 // Cool_Summer_Outfit +12290 // Mysterious_Can +12291 // Mysterious_PET_Bottle +12292 // Unripe_Fruit +12293 // Dried_Yggdrasilberry +12341 // Special_Alloy_Trap_Box +12346 // Unripe_Acorn +12347 // Acorn_Jelly +12353 // Tiny_Waterbottle +12358 // Fan_Of_Wind +12359 // Very_Soft_Plant +12360 // Very_Red_Juice +12362 // Kuloren +12364 // Staff_Of_Leader +12365 // Charming_Lotus +12366 // Gril_Doll +12367 // Luxury_Whisky_Bottle +12368 // Splendid_Mirror +12369 // Coconut +12371 // Magical_Lithography +12372 // Hell_Contract +12373 // Boy's_Naivety +12374 // Flaming_Ice +12376 // Mysterious_Can2 +12377 // Mysterious_PET_Bottle2 +12379 // Pope's_Cookie +12383 // Vulcan_Bullet_Magazine +12392 // RepairA +12393 // RepairB +12394 // RepairC +12395 // Tantanmen +//12414 +12717 // Poison_Paralysis +12718 // Poison_Leech +12719 // Poison_Oblivion +12720 // Poison_Contamination +12721 // Poison_Numb +12722 // Poison_Fever +12723 // Poison_Laughing +12724 // Poison_Fatigue +12734 // Runstone_Quality +12735 // Runstone_Ancient +12736 // Runstone_Mystic +12737 // Runstone_Ordinary +12738 // Runstone_Rare +506 // Green_Potion +507 // Red_Herb +508 // Yellow_Herb +509 // White_Herb +510 // Blue_Herb +511 // Green_Herb +512 // Apple +513 // Banana +514 // Grape +515 // Carrot +516 // Sweet_Potato +517 // Meat +518 // Honey +519 // Milk +520 // Leaflet_Of_Hinal +521 // Leaflet_Of_Aloe +522 // Fruit_Of_Mastela +523 // Holy_Water +525 // Panacea +526 // Royal_Jelly +528 // Monster's_Feed +529 // Candy +530 // Candy_Striper +531 // Apple_Juice +532 // Banana_Juice +533 // Grape_Juice +534 // Carrot_Juice +535 // Pumpkin +536 // Ice_Cream +537 // Pet_Food +538 // Well_Baked_Cookie +539 // Piece_Of_Cake +544 // Fish_Slice +548 // Cheese +549 // Nice_Sweet_Potato +550 // Popped_Rice +551 // Shusi +553 // Bun +564 // Rice_Ball +566 // Tomyumkung +567 // Prawn +568 // Lemon +569 // Novice_Potion +570 // Lucky_Candy +571 // Lucky_Candy_Cane +572 // Lucky_Cookie +574 // Egg +576 // Prickly_Fruit +577 // Grain +578 // Strawberry +579 // Delicious_Fish +580 // Bread +581 // Mushroom +582 // Orange +584 // Fish_Ball_Soup +587 // Prickly_Fruit_ +591 // Caviar_Pancake +592 // Jam_Pancake +593 // Honey_Pancake +594 // Sour_Cream_Pancake +595 // Mushroom_Pancake +//11513 +11515 // Coconut +11516 // Acai_Fruit +//11517 +701 // Ora_Ora +702 // Animal_Blood +703 // Hinalle +704 // Aloe +705 // Clover +706 // Four_Leaf_Clover +707 // Singing_Plant +708 // Ment +709 // Izidor +710 // Illusion_Flower +711 // Shoot +712 // Flower +713 // Empty_Bottle +715 // Yellow_Gemstone +716 // Red_Gemstone +717 // Blue_Gemstone +718 // Dark_Red_Jewel +719 // Violet_Jewel +720 // Skyblue_Jewel +721 // Azure_Jewel +722 // Scarlet_Jewel +723 // Cardinal_Jewel +724 // Cardinal_Jewel_ +725 // Red_Jewel +726 // Blue_Jewel +727 // White_Jewel +728 // Golden_Jewel +729 // Bluish_Green_Jewel +730 // Crystal_Jewel +731 // Crystal_Jewel_ +732 // Crystal_Jewel__ +733 // Crystal_Jewel___ +734 // Red_Frame +735 // Blue_Porcelain +736 // White_Platter +737 // Black_Ladle +738 // Pencil_Case +739 // Rouge +740 // Stuffed_Doll +741 // Poring_Doll +742 // Chonchon_Doll +743 // Spore_Doll +744 // Bunch_Of_Flowers +745 // Wedding_Bouquet +746 // Glass_Bead +747 // Crystal_Mirror +748 // Witherless_Rose +749 // Frozen_Rose +750 // Baphomet_Doll +751 // Osiris_Doll +752 // Grasshopper_Doll +753 // Monkey_Doll +754 // Raccoondog_Doll +756 // Oridecon_Stone +757 // Elunium_Stone +901 // Danggie +902 // Tree_Root +903 // Reptile_Tongue +904 // Scorpion's_Tail +905 // Stem +906 // Pointed_Scale +907 // Resin +908 // Spawn +909 // Jellopy +910 // Garlet +911 // Scell +912 // Zargon +913 // Tooth_Of_Bat +914 // Fluff +915 // Chrysalis +916 // Feather_Of_Birds +917 // Talon +918 // Sticky_Webfoot +919 // Animal's_Skin +920 // Claw_Of_Wolves +921 // Mushroom_Spore +922 // Orcish_Cuspid +923 // Evil_Horn +924 // Powder_Of_Butterfly +925 // Bill_Of_Birds +926 // Scale_Of_Snakes +928 // Insect_Feeler +929 // Immortal_Heart +930 // Rotten_Bandage +931 // Orcish_Voucher +932 // Skel_Bone +934 // Mementos +935 // Shell +936 // Scales_Shell +937 // Posionous_Canine +938 // Sticky_Mucus +939 // Bee_Sting +940 // Grasshopper's_Leg +941 // Nose_Ring +942 // Yoyo_Tail +943 // Solid_Shell +944 // Horseshoe +945 // Raccoon_Leaf +946 // Snail's_Shell +947 // Horn +948 // Bear's_Foot +949 // Feather +950 // Heart_Of_Mermaid +951 // Fin +952 // Cactus_Needle +953 // Stone_Heart +954 // Shining_Scales +955 // Worm_Peelings +956 // Gill +957 // Decayed_Nail +958 // Horrendous_Mouth +959 // Rotten_Scale +960 // Nipper +961 // Conch +962 // Tentacle +963 // Sharp_Scale +964 // Crap_Shell +965 // Clam_Shell +966 // Flesh_Of_Clam +967 // Turtle_Shell +968 // Voucher_Of_Orcish_Hero +969 // Gold +971 // Detrimindexta +972 // Karvodailnirol +973 // Counteragent +974 // Mixture +975 // Scarlet_Dyestuffs +976 // Lemon_Dyestuffs +978 // Cobaltblue_Dyestuffs +979 // Darkgreen_Dyestuffs +980 // Orange_Dyestuffs +981 // Violet_Dyestuffs +982 // White_Dyestuffs +983 // Black_Dyestuffs +984 // Oridecon +985 // Elunium +986 // Anvil +987 // Oridecon_Anvil +988 // Golden_Anvil +989 // Emperium_Anvil +990 // Boody_Red +991 // Crystal_Blue +992 // Wind_Of_Verdure +993 // Yellow_Live +994 // Flame_Heart +995 // Mistic_Frozen +996 // Rough_Wind +997 // Great_Nature +998 // Iron +999 // Steel +1000 // Star_Crumb +1001 // Sparkling_Dust +1002 // Iron_Ore +1003 // Coal +1004 // Patriotism_Marks +1005 // Hammer_Of_Blacksmith +1006 // Old_Magic_Book +1007 // Penetration +1008 // Frozen_Heart +1009 // Sacred_Marks +1010 // Phracon +1011 // Emveretarcon +1012 // Lizard_Scruff +1013 // Colorful_Shell +1014 // Jaws_Of_Ant +1015 // Thin_N'_Long_Tongue +1016 // Rat_Tail +1017 // Moustache_Of_Mole +1018 // Nail_Of_Mole +1019 // Wooden_Block +1020 // Long_Hair +1021 // Dokkaebi_Horn +1022 // Fox_Tail +1023 // Fish_Tail +1024 // Chinese_Ink +1025 // Spiderweb +1026 // Acorn +1027 // Porcupine_Spike +1028 // Wild_Boar's_Mane +1029 // Tiger's_Skin +1030 // Tiger_Footskin +1031 // Limb_Of_Mantis +1032 // Blossom_Of_Maneater +1033 // Root_Of_Maneater +1034 // Cobold_Hair +1035 // Dragon_Canine +1036 // Dragon_Scale +1037 // Dragon_Train +1038 // Petite_DiablOfs_Horn +1039 // Petite_DiablOfs_Wing +1040 // Elder_Pixie's_Beard +1041 // Lantern +1042 // Short_Leg +1043 // Nail_Of_Orc +1044 // Tooth_Of_ +1045 // Sacred_Masque +1046 // Tweezer +1047 // Head_Of_Medusa +1048 // Slender_Snake +1049 // Skirt_Of_Virgin +1050 // Tendon +1051 // Detonator +1052 // Single_Cell +1053 // Tooth_Of_Ancient_Fish +1054 // Lip_Of_Ancient_Fish +1055 // Earthworm_Peeling +1056 // Grit +1057 // Moth_Dust +1058 // Wing_Of_Moth +1059 // Transparent_Cloth +1060 // Golden_Hair +1061 // Starsand_Of_Witch +1062 // Pumpkin_Head +1063 // Sharpened_Cuspid +1064 // Reins +1065 // Booby_Trap +1066 // Tree_Of_Archer_1 +1067 // Tree_Of_Archer_2 +1068 // Tree_Of_Archer_3 +1088 // Morocc_Potion +1089 // Payon_Potion +1092 // Empty_Cylinder +1093 // Empty_Potion +1094 // Short_Daenggie +1095 // Needle_Of_Alarm +1096 // Round_Shell +1097 // Worn_Out_Page +1098 // Manacles +1099 // Worn_Out_Prison_Uniform +6001 // Essence_Of_Fire +6002 // Token_Of_Apostle +6003 // Soul_Pendant +6004 // Bapho_Doll +6008 // Wood +6010 // Pickaxe +6020 // Fur +6021 // Peaked_Hat +6022 // Hard_Skin +6023 // Mystic_Horn +6032 // Horn_Of_Hilsrion +6033 // Horn_Of_Tendrilion +6073 // Dragon's_Mane +6075 // Crystalized_Teardrop +6086 // Withered_Flower +6087 // Crystal_Of_Soul_01 +6088 // Crystal_Of_Soul_02 +6089 // Piece_Of_Darkness +6090 // Purified_Bradium +6091 // Dark_Red_Scale +6095 // Flavored_Alcohol +6096 // Fish_With_Blue_Back +6097 // Pumpkin_Pie_ +6098 // Small_Snow_Flower +6099 // Grilled_Rice_Cake +6100 // Damp_Darkness +6104 // Big_Cell +6105 // Morning_Dew +6106 // Well_Ripened_Berry +6107 // Sunset_On_The_Rock +6108 // Apple_Pudding +6109 // Plant_Neutrient +6110 // Vital_Flower +6111 // Mystic_Stone +6112 // Fresh_Plant +6113 // Vital_Flower_ +6114 // Flame_Gemstone +6115 // Bun_ +6120 // Face_Paint +6123 // Surface_Paint +6128 // Guillotine_Antidote +6144 // Heartbroken_Tears +6145 // Vulcan_Bullet +6146 // Magic_Gear_Fuel +6147 // Liquid_Condensed_Bullet +6186 // Monkey_Wrench +//6189 +//6190 +//6191 +//6192 +//6193 +//6194 +//6195 +//6196 +//6197 +//6198 +//6199 +//6200 +//6201 +//6202 +//6203 +//6204 +//6205 +//6210 // Seed_Of_Thorny_Plant +//6211 // Bloodsuck_Plant_Seed +//6212 // Bomb_Mushroom_Spore +//6213 // Explosive_Powder +//6214 // Smokes_Powder +//6215 // Tear_Gas +//6216 // Oil_Bottle +//6217 // Mandragora_Flowerpot +6223 // Carnium +6224 // Bradium +//6244 // Dark_Powder +//6245 // Black_Powder +//6246 // Yellow_Powder +//6247 // White_Powder +//6248 // Chowder_Pot +//6249 // Savage_Meat +//6250 // Iron_Cooking_Skewer +//6251 // Black_Charcoal +//6252 // Wolf's_Blood +//6253 // Cold_Ice +//6254 // Seasoned_Tough_Meat +//6255 // Large_Pan +//6256 // Powdered_Ice +//6257 // Ice_Crystal +//6258 // Comodo_Tropical_Fruit +//6259 // Drosera_Feeler +//6260 // Petite_Tail +//6261 // Fine_Noodles +//6262 // Cold_Broth +//6263 // Coconut +//6264 // Melon +//6265 // Pineapple +//6279 // Apple_Bomb_Guidebook +//6280 // Pineapple_Bomb_Guidebook +//6281 // Coconut_Bomb_Guidebook +//6282 // Melon_Bomb_Guidebook +//6283 // Banana_Bomb_Guidebook +//6284 // Plant_Genetic_Cultivation_Guide +//6285 // Improved_Potion_Creation_Manual +6297 // Empty_Potion_Bottle +//6321 // Rake_Helmet +//6322 // Antler_Helmet +//6323 // Two-Horn_Helmet +//6324 // One-Horn_Helmet +//6325 // White_Spider_Legs +//6326 // Queen_Scraba_Shell +//6360 // Scarlet_Point +//6361 // Indigo_Point +//6362 // Yellow_Wish_Point +//6363 // Lime_Green_Point +7001 // Mould_Powder +7002 // Ogre_Tooth +7003 // Anolian_Skin +7004 // Mud_Lump +7005 // Skull +7006 // Wing_Of_Red_Bat +7007 // Claw_Of_Rat +7008 // Stiff_Horn +7009 // Glitter_Shell +7010 // Tail_Of_Steel_Scorpion +7011 // Claw_Of_Monkey +7012 // Tough_Scalelike_Stem +7013 // Coral_Reef +7014 // Old_Portrait +7015 // Bookclip_In_Memory +7016 // Spoon_Stub +7017 // Executioner's_Mitten +7018 // Young_Twig +7019 // Loki's_Whispers +7020 // Mother's_Nightmare +7021 // Foolishness_Of_Blind +7022 // Old_Hilt +7023 // Blade_Lost_In_Darkness +7024 // Bloody_Edge +7026 // Key_Of_Clock_Tower +7027 // Underground_Key +7030 // Claw_Of_Desert_Wolf +7031 // Old_Frying_Pan +7032 // Piece_Of_Egg_Shell +7033 // Poison_Spore +7034 // Red_Socks_With_Holes +7035 // Matchstick +7036 // Fang_Of_Garm +7038 // Yarn +7041 // Fine_Grit +7043 // Fine_Sand +7047 // Alice's_Apron +7048 // Talon_Of_Griffin +7049 // Stone +7053 // Cyfar +7054 // Brigan +7055 // Animal_Pooopoo +7056 // Payroll_Of_Kafra +7057 // Gallar_Horn +7058 // Gullraifnir +7063 // Soft_Feather +7064 // Dragon_Fly_Wing +7065 // Sea_Otter_Leather +7066 // Ice_Piece +7067 // Stone_Piece +7068 // Burn_Tree +7069 // Broken_Armor_Piece +7070 // Broken_Shell +7071 // Tatters_Clothes +7072 // Rust_Suriken +7073 // Jewel_Of_Prayer +7074 // Iron_Glove +7075 // Iron_Maiden +7076 // Mystery_Wheel +7077 // Silver_Fancy +7078 // Anger_Of_Valkurye +7079 // Feather_Of_Angel +7080 // Foot_Step_Of_Cat +7081 // Beard_Of_Women +7082 // Root_Of_Stone +7083 // Soul_Of_Fish +7084 // Saliva_Of_Bird +7085 // Tendon_Of_Bear +7086 // Symbol_Of_Sun +7087 // Breath_Of_Soul +7088 // Crystal_Of_Snow +7089 // Indication_Of_Tempest +7090 // Slilince_Wave +7091 // Rough_Billows +7092 // Air_Stream +7093 // Wheel +7094 // Mystery_Piece +7095 // Broken_Steel_Piece +7096 // Cold_Magma +7097 // Burning_Heart +7098 // Live_Coal +7099 // Old_Magic_Circle +7100 // Sharp_Leaf +7101 // Peco_Wing_Feather +7102 // Hideous_Dream +7103 // Unknown_Liquid_Bottle +7104 // Fake_Angel_Wing +7105 // Fake_Angel_Loop +7106 // Goat's_Horn +7107 // Gaoat's_Skin +7108 // Boroken_Shiled_Piece +7109 // Shine_Spear_Blade +7110 // Vroken_Sword +7111 // Smooth_Paper +7112 // Fright_Paper_Blade +7113 // Broken_Pharaoh_Symbol +7114 // Tutankhamen's_Mask +7115 // Harpy's_Feather +7116 // Harpy's_Claw +7117 // Rent_Spell_Book +7118 // Rent_Scroll +7119 // Spawns +7120 // Burning_Horse_Shoe +7121 // Honey_Jar +7122 // Hot_Hair +7123 // Dragon's_Skin +7124 // Sand_Lump +7125 // Scropion's_Nipper +7126 // Large_Jellopy +7127 // Alcol_Create_Book +7128 // FireBottle_Create_Book +7129 // Acid_Create_Book +7130 // Plant_Create_Book +7131 // Mine_Create_Book +7132 // Coating_Create_Book +7133 // Slim_Potion_Create_Book +7134 // Medicine_Bowl +7140 // Seed_Of_Life +7141 // Yggdrasilberry_Dew +7143 // Life_Force_Pot +7144 // Normal_Potion_Book +7147 // Jasmin +7149 // Yellow_Plate +7150 // Bamboo_Cut +7151 // Oil_Paper +7152 // Glossy_Hair +7153 // Old_Japaness_Clothes +7154 // Poison_Powder +7155 // Poison_Toad's_Skin +7156 // Broken_Shuriken +7157 // Black_Mask +7158 // Broken_Wine_Vessel +7159 // Tengu's_Nose +7160 // Lord's_Passable_Ticket +7161 // Black_Bear's_Skin +7162 // Cloud_Piece +7163 // Sharp_Feeler +7164 // Hard_Peach +7165 // Limpid_Celestial_Robe +7166 // Soft_Silk_Cloth +7167 // Mystery_Iron_Bit +7168 // Great_Wing +7169 // Taegeuk_Plate +7170 // Tuxedo +7171 // Leopard_Skin +7172 // Leopard_Talon +7174 // Packing_Ribbon +7175 // Packing_Paper +7182 // Cacao +7186 // Thin_Stem +7187 // Festival_Mask +7188 // Browny_Root +7189 // Heart_Of_Tree +7190 // Solid_Peeling +7191 // Lamplight +7192 // Blade_Of_Pinwheel +7193 // Germinating_Sprout +7194 // Soft_Leaf +7195 // Air_Rifle +7196 // Shoulder_Protection +7197 // Tough_Vines +7198 // Great_Leaf +7199 // Coupon +7200 // Flexible_String +7201 // Log +7202 // Beetle_Nipper +7203 // Solid_Twig +7204 // Gunpowder +7205 // Piece_Of_Black_Cloth +7206 // Black_Kitty_Doll +7207 // Old_Manteau +7208 // Rusty_Cleaver +7209 // Dullahan's_Helm +7210 // Dullahan_Armor +7211 // Rojerta_Piece +7212 // Hanging_Doll +7213 // Needle_Pouch +7214 // Bat_Cage +7215 // Broken_Needle +7216 // Red_Scarf +7217 // Spool +7218 // Rotten_Rope +7219 // Striped_Socks +7220 // Ectoplasm +7221 // Tangled_Chain +7222 // Tree_Knot +7223 // Distorted_Portrait +7225 // Pumpkin_Bucket +7226 // Pill +7262 // Fan +7263 // Cat_Eyed_Stone +7264 // Dried_Sand +7265 // Dragon_Horn +7266 // Dragon_Fang +7267 // Tiger_Skin_Panties +7268 // Little_Blacky_Ghost +7269 // Bib +7270 // Milk_Bottle +7277 // Munak_Doll +7286 // Chilli +7289 // Olivine +7290 // Phlogopite +7291 // Agate +7292 // Muscovite +7293 // Rose_Quartz +7294 // Turquoise +7295 // Citrine +7296 // Pyroxene +7297 // Biotite +7298 // Leaf_Clothes +7299 // Bamboo_Basket +7300 // Gemstone +7301 // Sword_Accessory +7303 // Bag_Of_Rice +7312 // Jubilee +7315 // Dark_Crystal_Fragment +7316 // Long_Limb +7317 // Screw +7318 // Old_Pick +7319 // Old_Steel_Plate +7320 // Air_Pollutant +7321 // Fragment_Of_Crystal +7322 // Poisonous_Gas +7323 // Battered_Kettle +7325 // Tube +7326 // Fluorescent_Liquid +7327 // Headlamp +7340 // Will_Of_Darkness +7345 // Armlet_Of_Prisoner +7352 // Transparent_Plate01 +7353 // Transparent_Plate02 +7354 // Transparent_Plate03 +7355 // Transparent_Plate04 +7356 // Piece_Of_Crest1 +7357 // Piece_Of_Crest2 +7358 // Piece_Of_Crest3 +7359 // Piece_Of_Crest4 +7419 // Embryo_HandBook +7433 // Scroll +7434 // Elemental_Potion_Book +7435 // Golden_Bracelet +7436 // Piece_Of_Memory_Green +7437 // Piece_Of_Memory_Purple +7438 // Piece_Of_Memory_Blue +7439 // Piece_Of_Memory_Red +7440 // Red_Feather +7441 // Blue_Feather +7442 // Cursed_Seal +7443 // Tri_Headed_Dragon_Head +7444 // Treasure_Box +7445 // Dragonball_Green +7446 // Dragonball_Blue +7447 // Dragonball_Red +7448 // Dragonball_Yellow +7449 // Bloody_Page +7450 // Piece_Of_Bone_Armor +7451 // Scale_Of_Red_Dragon +7452 // Yellow_Spice +7453 // Sweet_Sauce +7454 // Plain_Sauce +7455 // Hot_Sauce +7456 // Red_Spice +7457 // Cooking_Oil +7472 // Cookbook01 +7473 // Cookbook02 +7474 // Cookbook03 +7475 // Cookbook04 +7476 // Cookbook05 +7477 // Cookbook06 +7478 // Cookbook07 +7479 // Cookbook08 +7480 // Cookbook09 +7481 // Cookbook10 +7482 // Pot +7507 // Sturdy_Iron_Piece +7510 // Valhalla_Flower +7511 // Rune_Of_Darkness +7512 // Burnt_Parts +7513 // Pocket_Watch +7521 // Flame_Stone +7522 // Ice_Stone +7523 // Wind_Stone +7524 // Shadow_Orb +7561 // Ice_Heart +7562 // Ice_Scale +7563 // Bloody_Rune +7564 // Rotten_Meat +7565 // Sticky_Poison +7566 // Will_Of_Darkness_ +7567 // Suspicious_Hat +7568 // White_Mask +7574 // Ice_Particle +7751 // Old_White_Cloth +7752 // Clattering_Skull +7753 // Broken_Farming_Utensil +7754 // Broken_Crown +7830 // Goddess_Tear +7831 // Valkyrie_Token +7832 // Brynhild_Armor_Piece +7833 // Hero_Remains +7834 // Andvari_Ring +7835 // Dusk_Glow +7836 // Dawn_Essence +7837 // Cold_Moonlight +7838 // Hazy_Starlight +7931 // Poison_Kit +7932 // Poison_Herb_Nerium +7933 // Poison_Herb_Rantana +7934 // Poison_Herb_Makulata +7935 // Poison_Herb_Seratum +7936 // Poison_Herb_Scopolia +7937 // Poison_Herb_Amoena +7938 // Light_Granule +7939 // Elder_Branch +7940 // Special_Alloy_Trap +11000 // Prontera_Book_01 +11001 // Adventure_Story01 +11002 // Great_Chef_Orleans01 +11003 // Legend_Of_Kafra01 +11004 // Mercenary_Rebellion +11005 // Tyrant_Schmidt +11006 // Blood_Flower01 +11007 // Blood_Flower02 +11008 // Barmund +11009 // Adventure_Story02 +//11020 +//11021 +//11022 // Mix_Cooking_Ingredient_Book_1 +//11023 // Vitality_Boost_Research_Book +//11024 // Energy_Drink_Formula + diff --git a/db/item_db.txt b/db/item_db.txt index e97812060..48b8747e5 100644 --- a/db/item_db.txt +++ b/db/item_db.txt @@ -3293,7 +3293,7 @@ //6362,Yellow_Wish_Point,Yellow Wish Point,3,100,,5,,,,,,,,,,,,,{},{},{} //6363,Lime_Green_Point,Lime Green Point,3,100,,5,,,,,,,,,,,,,{},{},{} //6376,KVM_Badge -//6377,Buy_Stall_Permit,Purchase Street Stall License,3,200,,10,,,,,,,,,,,,,{},{},{} +6377,Buy_Stall_Permit,Purchase Street Stall License,3,200,,10,,,,,,,,,,,,,{},{},{} //6378 //6379 //6380 @@ -4823,7 +4823,7 @@ //12471,LV5_Adrenaline_Scroll, //12472,Convex_Mirror, //12475,Cure_Free, -//12548,Shabby_Purchase_Street_Stall_License, +12548,Shabby_Purchase_Street_Stall_License,Shabby Purchase Street Stall License,2,500,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ buyingstore 2; },{},{} //12553,Brysingamen_Piece_Box, //12554,Asprika_Piece_Box, //12555,Brynhild_Piece_Box, diff --git a/db/packet_db.txt b/db/packet_db.txt index 2bd70e641..26d4773ed 100644 --- a/db/packet_db.txt +++ b/db/packet_db.txt @@ -1488,8 +1488,8 @@ packet_ver: 25 0x080F,20 //2010-03-03aRagexeRE -//0x0810,3 -//0x0811,-1 +0x0810,3 +0x0811,-1,reqopenbuyingstore,2:4:8:9:89 //0x0812,86 //0x0813,6 //0x0814,6 @@ -1499,11 +1499,11 @@ packet_ver: 25 //0x0819,4 //2010-03-09aRagexeRE -//0x0813,-1 +0x0813,-1 //0x0814,2 //0x0815,6 -//0x0816,6 -//0x0818,-1 +0x0816,6 +0x0818,-1 //0x0819,10 //0x081A,4 //0x081B,4 @@ -1528,15 +1528,15 @@ packet_ver: 25 //0x081B,8 //2010-04-20aRagexeRE -//0x0812,8 -//0x0814,86 -//0x0815,2 -//0x0817,6 -//0x0819,-1 -//0x081a,4 -//0x081b,10 -//0x081c,10 -//0x0824,6 +0x0812,8 +0x0814,86 +0x0815,2,reqclosebuyingstore,0 +0x0817,6,reqclickbuyingstore,2 +0x0819,-1,reqtradebuyingstore,2:4:8:12 +0x081a,4 +0x081b,10 +0x081c,10 +0x0824,6 //2010-06-01aRagexeRE //0x0825,-1 diff --git a/db/skill_db.txt b/db/skill_db.txt index b534986c8..2a39740df 100644 --- a/db/skill_db.txt +++ b/db/skill_db.txt @@ -938,6 +938,9 @@ // Episode 13.3 //2534,0,0,0,0,0,0,9,0,no,0,0,0,none,0 RETURN_TO_ELDICASTES, +// Buying Store +2535,0,0,4,0,0x1,0,1,0,no,0,0x1,0,none,0, ALL_BUYING_STORE,Open Buying Store + 8001,9,6,4,0,0x1,0,5,1,no,0,0,0,magic,0, HLIF_HEAL,Healing Touch 8002,0,6,4,0,0x3,-1,5,1,no,0,0,0,none,0, HLIF_AVOID,Avoid 8003,0,0,0,0,0,1,5,0,no,0,0,0,none,0, HLIF_BRAIN,Brain Surgery diff --git a/db/skill_require_db.txt b/db/skill_require_db.txt index 6a81951ff..d9fa49e0e 100644 --- a/db/skill_require_db.txt +++ b/db/skill_require_db.txt @@ -454,6 +454,8 @@ 1018,0,0,30,0,0,0,99,0,0,none,0,12114,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //SA_ELEMENTFIRE 1019,0,0,30,0,0,0,99,0,0,none,0,12117,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //SA_ELEMENTWIND +2535,0,0,1,0,0,0,99,0,0,none,0,6377,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //ALL_BUYING_STORE#Open Buying Store + 10010,0,0,1,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //GD_BATTLEORDER## 10011,0,0,1,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //GD_REGENERATION## 10012,0,0,1,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //GD_RESTORE## diff --git a/db/skill_tree.txt b/db/skill_tree.txt index d64f1fef7..27f616c11 100644 --- a/db/skill_tree.txt +++ b/db/skill_tree.txt @@ -86,6 +86,7 @@ 5,155,1,0,0,0,0,0,0,0,0,0,0 //MC_LOUD#Crazy Uproar# 5,410,1,0,0,0,0,0,0,0,0,0,0 //WE_CALLBABY#Call Baby# 5,681,1,0,0,0,0,0,0,0,0,0,0 //ALL_INCCARRY#Enlarge Weight Limit R# +5,2535,1,41,1,0,0,0,0,0,0,0,0 //ALL_BUYING_STORE#Open Buying Store# //Thief 6,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill# 6,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid# @@ -240,6 +241,7 @@ 10,410,1,0,0,0,0,0,0,0,0,0,0 //WE_CALLBABY#Call Baby# 10,459,1,111,5,0,0,0,0,0,0,0,0 //BS_ADRENALINE2#Full Adrenaline Rush# 10,681,1,0,0,0,0,0,0,0,0,0,0 //ALL_INCCARRY#Enlarge Weight Limit R# +10,2535,1,41,1,0,0,0,0,0,0,0,0 //ALL_BUYING_STORE#Open Buying Store# //Hunter 11,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill# 11,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid# @@ -511,6 +513,7 @@ 18,497,1,228,10,0,0,0,0,0,0,0,0 //AM_TWILIGHT2#Twilight Alchemy 2# 18,498,1,228,10,0,0,0,0,0,0,0,0 //AM_TWILIGHT3#Twilight Alchemy 3# 18,681,1,0,0,0,0,0,0,0,0,0,0 //ALL_INCCARRY#Enlarge Weight Limit R# +18,2535,1,41,1,0,0,0,0,0,0,0,0 //ALL_BUYING_STORE#Open Buying Store# //Bard 19,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill# 19,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid# @@ -668,6 +671,7 @@ 23,53,1,52,3,0,0,0,0,0,0,0,0 //TF_DETOXIFY#Detoxify# 23,410,1,0,0,0,0,0,0,0,0,0,0 //WE_CALLBABY#Call Baby# 23,681,1,0,0,0,0,0,0,0,0,0,0 //ALL_INCCARRY#Enlarge Weight Limit R# +23,2535,1,41,1,0,0,0,0,0,0,0,0 //ALL_BUYING_STORE#Open Buying Store# //Gunslinger 24,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill# 24,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid# @@ -810,6 +814,7 @@ 4006,155,1,0,0,0,0,0,0,0,0,0,0 //MC_LOUD#Crazy Uproar# 4006,410,1,0,0,0,0,0,0,0,0,0,0 //WE_CALLBABY#Call Baby# 4006,681,1,0,0,0,0,0,0,0,0,0,0 //ALL_INCCARRY#Enlarge Weight Limit R# +4006,2535,1,41,1,0,0,0,0,0,0,0,0 //ALL_BUYING_STORE#Open Buying Store# //ThiefHigh 4007,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill# 4007,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid# @@ -989,6 +994,7 @@ 4011,410,1,0,0,0,0,0,0,0,0,0,0 //WE_CALLBABY#Call Baby# 4011,459,1,111,5,0,0,0,0,0,0,0,0 //BS_ADRENALINE2#Full Adrenaline Rush# 4011,681,1,0,0,0,0,0,0,0,0,0,0 //ALL_INCCARRY#Enlarge Weight Limit R# +4011,2535,1,41,1,0,0,0,0,0,0,0,0 //ALL_BUYING_STORE#Open Buying Store# //Sniper 4012,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill# 4012,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid# @@ -1303,6 +1309,7 @@ 4019,497,1,228,10,0,0,0,0,0,0,0,0 //AM_TWILIGHT2#Twilight Alchemy 2# 4019,498,1,228,10,0,0,0,0,0,0,0,0 //AM_TWILIGHT3#Twilight Alchemy 3# 4019,681,1,0,0,0,0,0,0,0,0,0,0 //ALL_INCCARRY#Enlarge Weight Limit R# +4019,2535,1,41,1,0,0,0,0,0,0,0,0 //ALL_BUYING_STORE#Open Buying Store# //Clown 4020,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill# 4020,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid# @@ -1508,6 +1515,7 @@ 4028,408,1,0,0,0,0,0,0,0,0,0,0 //WE_BABY#Baby# 4028,409,1,0,0,0,0,0,0,0,0,0,0 //WE_CALLPARENT#Call Parent# 4028,681,1,0,0,0,0,0,0,0,0,0,0 //ALL_INCCARRY#Enlarge Weight Limit R# +4028,2535,1,41,1,0,0,0,0,0,0,0,0 //ALL_BUYING_STORE#Open Buying Store# //Baby Thief 4029,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill# 4029,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid# @@ -1666,6 +1674,7 @@ 4033,1013,1,0,0,0,0,0,0,0,0,0,0 //BS_GREED#Greed# 4033,459,1,111,5,0,0,0,0,0,0,0,0 //BS_ADRENALINE2#Full Adrenaline Rush# 4033,681,1,0,0,0,0,0,0,0,0,0,0 //ALL_INCCARRY#Enlarge Weight Limit R# +4033,2535,1,41,1,0,0,0,0,0,0,0,0 //ALL_BUYING_STORE#Open Buying Store# //Baby Hunter 4034,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill# 4034,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid# @@ -1945,6 +1954,7 @@ 4041,497,1,228,10,0,0,0,0,0,0,0,0 //AM_TWILIGHT2#Twilight Alchemy 2# 4041,498,1,228,10,0,0,0,0,0,0,0,0 //AM_TWILIGHT3#Twilight Alchemy 3# 4041,681,1,0,0,0,0,0,0,0,0,0,0 //ALL_INCCARRY#Enlarge Weight Limit R# +4041,2535,1,41,1,0,0,0,0,0,0,0,0 //ALL_BUYING_STORE#Open Buying Store# //Baby Bard 4042,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill# 4042,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid# @@ -2099,6 +2109,7 @@ 4045,408,1,0,0,0,0,0,0,0,0,0,0 //WE_BABY#Baby# 4045,409,1,0,0,0,0,0,0,0,0,0,0 //WE_CALLPARENT#Call Parent# 4045,681,1,0,0,0,0,0,0,0,0,0,0 //ALL_INCCARRY#Enlarge Weight Limit R# +4045,2535,1,41,1,0,0,0,0,0,0,0,0 //ALL_BUYING_STORE#Open Buying Store# //Taekwon 4046,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill# 4046,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid# diff --git a/doc/script_commands.txt b/doc/script_commands.txt index 0fa2a0200..8deea8d6c 100644 --- a/doc/script_commands.txt +++ b/doc/script_commands.txt @@ -4,7 +4,7 @@ //= A reference manual for the eAthena scripting language. //= Commands are sorted depending on their functionality. //===== Version =========================================== -//= 3.35.20110106 +//= 3.36.20110219 //========================================================= //= 1.0 - First release, filled will as much info as I could //= remember or figure out, most likely there are errors, @@ -155,6 +155,8 @@ //= Spellcheck. [Ai4rei] //= 3.35.20110106 //= Removed bug warning from 'deletearray'. [Ai4rei] +//= 3.36.20110219 +//= Added 'buyingstore' command. [Ai4rei] //========================================================= This document is a reference manual for all the scripting commands and functions @@ -4423,6 +4425,19 @@ Example(s): //The invoked character will no longer automatically equip a falchion. autoequip 1104,0; +--------------------------------------- + +*buyingstore ; + +Invokes buying store preparation window like the skill 'Open Buying Store', +without the item requirement. Amount of slots is limited by the server to +a maximum of 5 slots by default. + +Example: + + // Gives the player oppurtunity to buy 4 different kinds of items. + buyingstore 4; + --------------------------------------- // 4,1.- End of item-related commands diff --git a/sql-files/logs.sql b/sql-files/logs.sql index 177dee870..6a69e3e1f 100644 --- a/sql-files/logs.sql +++ b/sql-files/logs.sql @@ -1,7 +1,7 @@ #PickLog types (M)onsters Drop, (P)layers Drop/Take, Mobs Drop (L)oot Drop/Take, # Players (T)rade Give/Take, Players (V)ending Sell/Take, (S)hop Sell/Take, (N)PC Give/Take, # (C)onsumable Items, (A)dministrators Create/Delete, Sto(R)age, (G)uild Storage, -# (E)mail attachment +# (E)mail attachment,(B)uying Store #Database: log #Table: picklog @@ -9,7 +9,7 @@ CREATE TABLE `picklog` ( `id` int(11) NOT NULL auto_increment, `time` datetime NOT NULL default '0000-00-00 00:00:00', `char_id` int(11) NOT NULL default '0', - `type` enum('M','P','L','T','V','S','N','C','A','R','G','E') NOT NULL default 'P', + `type` enum('M','P','L','T','V','S','N','C','A','R','G','E','B') NOT NULL default 'P', `nameid` int(11) NOT NULL default '0', `amount` int(11) NOT NULL default '1', `refine` tinyint(3) unsigned NOT NULL default '0', @@ -22,7 +22,7 @@ CREATE TABLE `picklog` ( INDEX (`type`) ) ENGINE=MyISAM AUTO_INCREMENT=1 ; -#ZenyLog types (M)onsters,(T)rade,(V)ending Sell/Buy,(S)hop Sell/Buy,(N)PC Change amount,(A)dministrators,(E)Mail +#ZenyLog types (M)onsters,(T)rade,(V)ending Sell/Buy,(S)hop Sell/Buy,(N)PC Change amount,(A)dministrators,(E)Mail,(B)uying Store #Database: log #Table: zenylog CREATE TABLE `zenylog` ( @@ -30,7 +30,7 @@ CREATE TABLE `zenylog` ( `time` datetime NOT NULL default '0000-00-00 00:00:00', `char_id` int(11) NOT NULL default '0', `src_id` int(11) NOT NULL default '0', - `type` enum('M','T','V','S','N','A','E') NOT NULL default 'S', + `type` enum('M','T','V','S','N','A','E','B') NOT NULL default 'S', `amount` int(11) NOT NULL default '0', `map` varchar(11) NOT NULL default '', PRIMARY KEY (`id`), diff --git a/sql-files/upgrade_svn14713_log.sql b/sql-files/upgrade_svn14713_log.sql new file mode 100644 index 000000000..be4059ebe --- /dev/null +++ b/sql-files/upgrade_svn14713_log.sql @@ -0,0 +1,4 @@ +-- Adds 'B' to `type` in `picklog` and `zenylog` + +ALTER TABLE `picklog` MODIFY `type` ENUM('M','P','L','T','V','S','N','C','A','R','G','E','B') NOT NULL DEFAULT 'P'; +ALTER TABLE `zenylog` MODIFY `type` ENUM('M','T','V','S','N','A','E','B') NOT NULL DEFAULT 'S'; diff --git a/src/common/mmo.h b/src/common/mmo.h index 181f972e5..fa41c99d8 100644 --- a/src/common/mmo.h +++ b/src/common/mmo.h @@ -84,7 +84,7 @@ #define MAX_ZENY 1000000000 #define MAX_FAME 1000000000 #define MAX_CART 100 -#define MAX_SKILL 1020 +#define MAX_SKILL 2536 #define GLOBAL_REG_NUM 256 #define ACCOUNT_REG_NUM 64 #define ACCOUNT_REG2_NUM 16 diff --git a/src/map/Makefile.in b/src/map/Makefile.in index cf6a29d6c..cec75c69b 100644 --- a/src/map/Makefile.in +++ b/src/map/Makefile.in @@ -17,7 +17,8 @@ MAP_OBJ = map.o chrif.o clif.o pc.o status.o npc.o \ npc_chat.o chat.o path.o itemdb.o mob.o script.o \ storage.o skill.o atcommand.o battle.o battleground.o \ intif.o trade.o party.o vending.o guild.o pet.o \ - log.o mail.o date.o unit.o homunculus.o mercenary.o quest.o instance.o + log.o mail.o date.o unit.o homunculus.o mercenary.o quest.o instance.o \ + buyingstore.o MAP_TXT_OBJ = $(MAP_OBJ:%=obj_txt/%) \ obj_txt/mapreg_txt.o MAP_SQL_OBJ = $(MAP_OBJ:%=obj_sql/%) \ @@ -26,7 +27,8 @@ MAP_H = map.h chrif.h clif.h pc.h status.h npc.h \ chat.h itemdb.h mob.h script.h path.h \ storage.h skill.h atcommand.h battle.h battleground.h \ intif.h trade.h party.h vending.h guild.h pet.h \ - log.h mail.h date.h unit.h homunculus.h mercenary.h quest.h instance.h mapreg.h + log.h mail.h date.h unit.h homunculus.h mercenary.h quest.h instance.h mapreg.h \ + buyingstore.h HAVE_MYSQL=@HAVE_MYSQL@ ifeq ($(HAVE_MYSQL),yes) diff --git a/src/map/atcommand.c b/src/map/atcommand.c index 3035487da..6abee5223 100644 --- a/src/map/atcommand.c +++ b/src/map/atcommand.c @@ -1150,7 +1150,7 @@ ACMD_FUNC(storage) { nullpo_retr(-1, sd); - if (sd->npc_id || sd->vender_id || sd->state.trading || sd->state.storage_flag) + if (sd->npc_id || sd->vender_id || sd->state.buyingstore || sd->state.trading || sd->state.storage_flag) return -1; if (storage_storageopen(sd) == 1) @@ -1177,7 +1177,7 @@ ACMD_FUNC(guildstorage) return -1; } - if (sd->npc_id || sd->vender_id || sd->state.trading) + if (sd->npc_id || sd->vender_id || sd->state.buyingstore || sd->state.trading) return -1; if (sd->state.storage_flag == 1) { diff --git a/src/map/battle.c b/src/map/battle.c index fd9bc90d6..aebb93d56 100644 --- a/src/map/battle.c +++ b/src/map/battle.c @@ -4007,6 +4007,7 @@ static const struct _battle_data { { "client_reshuffle_dice", &battle_config.client_reshuffle_dice, 0, 0, 1, }, { "client_sort_storage", &battle_config.client_sort_storage, 0, 0, 1, }, { "gm_check_minlevel", &battle_config.gm_check_minlevel, 60, 0, 100, }, + { "feature_buying_store", &battle_config.feature_buying_store, 1, 0, 1, }, // BattleGround Settings { "bg_update_interval", &battle_config.bg_update_interval, 1000, 100, INT_MAX, }, { "bg_short_attack_damage_rate", &battle_config.bg_short_damage_rate, 80, 0, INT_MAX, }, diff --git a/src/map/battle.h b/src/map/battle.h index a3e35bcee..f11040c8a 100644 --- a/src/map/battle.h +++ b/src/map/battle.h @@ -481,6 +481,7 @@ extern struct Battle_Config int client_reshuffle_dice; // Reshuffle /dice int client_sort_storage; int gm_check_minlevel; // min GM level for /check + int feature_buying_store; // [BattleGround Settings] int bg_update_interval; diff --git a/src/map/buyingstore.c b/src/map/buyingstore.c new file mode 100644 index 000000000..21629e641 --- /dev/null +++ b/src/map/buyingstore.c @@ -0,0 +1,359 @@ +// Copyright (c) Athena Dev Teams - Licensed under GNU GPL +// For more information, see LICENCE in the main folder + +#include "../common/cbasetypes.h" +#include "../common/db.h" // ARR_FIND +#include "../common/showmsg.h" // ShowWarning +#include "../common/socket.h" // RBUF* +#include "../common/strlib.h" // safestrncpy +#include "atcommand.h" // msg_txt +#include "battle.h" // battle_config.* +#include "buyingstore.h" // struct s_buyingstore +#include "clif.h" // clif_buyingstore_* +#include "log.h" // log_pick_pc, log_zeny +#include "pc.h" // struct map_session_data + + +/// constants (client-side restrictions) +#define BUYINGSTORE_MAX_PRICE 99990000 +#define BUYINGSTORE_MAX_AMOUNT 9999 + + +/// failure constants for clif functions +enum e_buyingstore_failure +{ + BUYINGSTORE_CREATE = 1, // "Failed to open buying store." + BUYINGSTORE_CREATE_OVERWEIGHT = 2, // "Total amount of then possessed items exceeds the weight limit by %d. Please re-enter." + BUYINGSTORE_TRADE_BUYER_ZENY = 3, // "All items within the buy limit were purchased." + BUYINGSTORE_TRADE_BUYER_NO_ITEMS = 4, // "All items were purchased." + BUYINGSTORE_TRADE_SELLER_FAILED = 5, // "The deal has failed." + BUYINGSTORE_TRADE_SELLER_COUNT = 6, // "The trade failed, because the entered amount of item %s is higher, than the buyer is willing to buy." + BUYINGSTORE_TRADE_SELLER_ZENY = 7, // "The trade failed, because the buyer is lacking required balance." + BUYINGSTORE_CREATE_NO_INFO = 8, // "No sale (purchase) information available." +}; + + +static unsigned int buyingstore_nextid = 0; + + +/// Returns unique buying store id +static unsigned int buyingstore_getuid(void) +{ + return buyingstore_nextid++; +} + + +bool buyingstore_setup(struct map_session_data* sd, unsigned char slots) +{ + if( !battle_config.feature_buying_store || sd->vender_id || sd->state.buyingstore || sd->state.trading || slots == 0 ) + { + return false; + } + + if( slots > MAX_BUYINGSTORE_SLOTS ) + { + ShowWarning("buyingstore_setup: Requested %d slots, but server supports only %d slots.\n", (int)slots, MAX_BUYINGSTORE_SLOTS); + slots = MAX_BUYINGSTORE_SLOTS; + } + + sd->buyingstore.slots = slots; + clif_buyingstore_open(sd); + + return true; +} + + +void buyingstore_create(struct map_session_data* sd, int zenylimit, unsigned char result, const char* storename, const uint8* itemlist, unsigned int count) +{ + unsigned int i, weight, listidx; + struct item_data* id; + + if( !result || count == 0 ) + {// canceled, or no items + return; + } + + if( !battle_config.feature_buying_store || pc_istrading(sd) || sd->buyingstore.slots == 0 || count > sd->buyingstore.slots || zenylimit <= 0 || zenylimit > sd->status.zeny || !storename[0] ) + {// disabled or invalid input + sd->buyingstore.slots = 0; + clif_buyingstore_open_failed(sd, BUYINGSTORE_CREATE, 0); + return; + } + + if( !pc_can_give_items(pc_isGM(sd)) ) + {// custom: GM is not allowed to buy (give zeny) + sd->buyingstore.slots = 0; + clif_displaymessage(sd->fd, msg_txt(246)); + clif_buyingstore_open_failed(sd, BUYINGSTORE_CREATE, 0); + return; + } + + weight = sd->weight; + + // check item list + for( i = 0; i < count; i++ ) + {// itemlist: .W .W .L + unsigned short nameid, amount; + int price, idx; + + nameid = RBUFW(itemlist,i*8+0); + amount = RBUFW(itemlist,i*8+2); + price = RBUFL(itemlist,i*8+4); + + if( ( id = itemdb_exists(nameid) ) == NULL || amount == 0 ) + {// invalid input + break; + } + + if( price <= 0 || price > BUYINGSTORE_MAX_PRICE ) + {// invalid price: unlike vending, items cannot be bought at 0 Zeny + break; + } + + if( !id->flag.buyingstore || !itemdb_cantrade_sub(id, pc_isGM(sd), pc_isGM(sd)) || ( idx = pc_search_inventory(sd, nameid) ) == -1 ) + {// restrictions: allowed, no character-bound items and at least one must be owned + break; + } + + if( sd->status.inventory[idx].amount+amount > BUYINGSTORE_MAX_AMOUNT ) + {// too many items of same kind + break; + } + + if( i ) + {// duplicate check. as the client does this too, only malicious intent should be caught here + ARR_FIND( 0, i, listidx, sd->buyingstore.items[i].nameid == nameid ); + if( listidx != i ) + {// duplicate + ShowWarning("buyingstore_create: Found duplicate item on buying list (nameid=%hu, amount=%hu, account_id=%d, char_id=%d).\n", nameid, amount, sd->status.account_id, sd->status.char_id); + break; + } + } + + weight+= id->weight*amount; + sd->buyingstore.items[i].nameid = nameid; + sd->buyingstore.items[i].amount = amount; + sd->buyingstore.items[i].price = price; + } + + if( i != count ) + {// invalid item/amount/price + sd->buyingstore.slots = 0; + clif_buyingstore_open_failed(sd, BUYINGSTORE_CREATE, 0); + return; + } + + if( (sd->max_weight*90)/100 < weight ) + {// not able to carry all wanted items without getting overweight (90%) + sd->buyingstore.slots = 0; + clif_buyingstore_open_failed(sd, BUYINGSTORE_CREATE_OVERWEIGHT, weight); + return; + } + + // success + sd->state.buyingstore = true; + sd->buyer_id = buyingstore_getuid(); + sd->buyingstore.zenylimit = zenylimit; + sd->buyingstore.slots = i; // store actual amount of items + safestrncpy(sd->message, storename, sizeof(sd->message)); + clif_buyingstore_myitemlist(sd); + clif_buyingstore_entry(sd); +} + + +void buyingstore_close(struct map_session_data* sd) +{ + if( sd->state.buyingstore ) + { + // invalidate data + sd->state.buyingstore = false; + memset(&sd->buyingstore, 0, sizeof(sd->buyingstore)); + + // notify other players + clif_buyingstore_disappear_entry(sd); + } +} + + +void buyingstore_open(struct map_session_data* sd, int account_id) +{ + struct map_session_data* pl_sd; + + if( !battle_config.feature_buying_store || pc_istrading(sd) ) + {// not allowed to sell + return; + } + + if( !pc_can_give_items(pc_isGM(sd)) ) + {// custom: GM is not allowed to sell + clif_displaymessage(sd->fd, msg_txt(246)); + return; + } + + if( ( pl_sd = map_id2sd(account_id) ) == NULL || !pl_sd->state.buyingstore ) + {// not online or not buying + return; + } + + // success + clif_buyingstore_itemlist(sd, pl_sd); +} + + +void buyingstore_trade(struct map_session_data* sd, int account_id, unsigned int buyer_id, const uint8* itemlist, unsigned int count) +{ + short blankslots[MAX_SLOTS]; // used when checking whether or not an item's card slots are blank + int zeny = 0; + unsigned int i, weight, listidx, k; + struct map_session_data* pl_sd; + + if( count == 0 ) + {// nothing to do + return; + } + + if( !battle_config.feature_buying_store || pc_istrading(sd) ) + {// not allowed to sell + clif_buyingstore_trade_failed_seller(sd, BUYINGSTORE_TRADE_SELLER_FAILED, 0); + return; + } + + if( !pc_can_give_items(pc_isGM(sd)) ) + {// custom: GM is not allowed to sell + clif_displaymessage(sd->fd, msg_txt(246)); + clif_buyingstore_trade_failed_seller(sd, BUYINGSTORE_TRADE_SELLER_FAILED, 0); + return; + } + + if( ( pl_sd = map_id2sd(account_id) ) == NULL || !pl_sd->state.buyingstore || pl_sd->buyer_id != buyer_id ) + {// not online, not buying or not same store + clif_buyingstore_trade_failed_seller(sd, BUYINGSTORE_TRADE_SELLER_FAILED, 0); + return; + } + + if( pl_sd->status.zeny < pl_sd->buyingstore.zenylimit ) + {// buyer lost zeny in the mean time? fix the limit + pl_sd->buyingstore.zenylimit = pl_sd->status.zeny; + } + weight = pl_sd->weight; + memset(blankslots, 0, sizeof(blankslots)); + + // check item list + for( i = 0; i < count; i++ ) + {// itemlist: .W .W .W + unsigned short nameid, amount; + int index; + + index = RBUFW(itemlist,i*6+0)-2; + nameid = RBUFW(itemlist,i*6+2); + amount = RBUFW(itemlist,i*6+4); + + if( i ) + {// duplicate check. as the client does this too, only malicious intent should be caught here + ARR_FIND( 0, i, k, RBUFW(itemlist,k*6+0)-2 == index ); + if( k != i ) + {// duplicate + ShowWarning("buyingstore_trade: Found duplicate item on selling list (prevnameid=%hu, prevamount=%hu, nameid=%hu, amount=%hu, account_id=%d, char_id=%d).\n", + RBUFW(itemlist,k*6+2), RBUFW(itemlist,k*6+4), nameid, amount, sd->status.account_id, sd->status.char_id); + clif_buyingstore_trade_failed_seller(sd, BUYINGSTORE_TRADE_SELLER_FAILED, nameid); + return; + } + } + + if( index < 0 || index >= ARRAYLENGTH(sd->status.inventory) || sd->inventory_data[index] == NULL || sd->status.inventory[index].nameid != nameid || sd->status.inventory[index].amount < amount ) + {// invalid input + clif_buyingstore_trade_failed_seller(sd, BUYINGSTORE_TRADE_SELLER_FAILED, nameid); + return; + } + + if( sd->status.inventory[index].expire_time || !itemdb_cantrade(&sd->status.inventory[index], pc_isGM(sd), pc_isGM(pl_sd)) || memcmp(sd->status.inventory[index].card, blankslots, sizeof(blankslots)) ) + {// non-tradable item + clif_buyingstore_trade_failed_seller(sd, BUYINGSTORE_TRADE_SELLER_FAILED, nameid); + return; + } + + ARR_FIND( 0, pl_sd->buyingstore.slots, listidx, pl_sd->buyingstore.items[listidx].nameid == nameid ); + if( listidx == pl_sd->buyingstore.slots || pl_sd->buyingstore.items[listidx].amount == 0 ) + {// there is no such item or the buyer has already bought all of them + clif_buyingstore_trade_failed_seller(sd, BUYINGSTORE_TRADE_SELLER_FAILED, nameid); + return; + } + + if( pl_sd->buyingstore.items[listidx].amount < amount ) + {// buyer does not need that much of the item + clif_buyingstore_trade_failed_seller(sd, BUYINGSTORE_TRADE_SELLER_COUNT, nameid); + return; + } + + if( pc_checkadditem(pl_sd, nameid, amount) == ADDITEM_OVERAMOUNT ) + {// buyer does not have enough space for this item + clif_buyingstore_trade_failed_seller(sd, BUYINGSTORE_TRADE_SELLER_FAILED, nameid); + return; + } + + if( amount*(unsigned int)sd->inventory_data[index]->weight > pl_sd->max_weight-weight ) + {// normally this is not supposed to happen, as the total weight is + // checked upon creation, but the buyer could have gained items + clif_buyingstore_trade_failed_seller(sd, BUYINGSTORE_TRADE_SELLER_FAILED, nameid); + return; + } + weight+= amount*sd->inventory_data[index]->weight; + + if( amount*pl_sd->buyingstore.items[listidx].price > pl_sd->buyingstore.zenylimit-zeny ) + {// buyer does not have enough zeny + clif_buyingstore_trade_failed_seller(sd, BUYINGSTORE_TRADE_SELLER_ZENY, nameid); + return; + } + zeny+= amount*pl_sd->buyingstore.items[listidx].price; + } + + // process item list + for( i = 0; i < count; i++ ) + {// itemlist: .W .W .W + unsigned short nameid, amount; + int index; + + index = RBUFW(itemlist,i*6+0)-2; + nameid = RBUFW(itemlist,i*6+2); + amount = RBUFW(itemlist,i*6+4); + + ARR_FIND( 0, pl_sd->buyingstore.slots, listidx, pl_sd->buyingstore.items[listidx].nameid == nameid ); + zeny = amount*pl_sd->buyingstore.items[listidx].price; + + // log + if( log_config.enable_logs&LOG_BUYING_STORE ) + { + log_pick_pc(sd, "B", nameid, -((int)amount), &sd->status.inventory[index]); + log_pick_pc(pl_sd, "B", nameid, amount, &sd->status.inventory[index]); + } + if( log_config.zeny ) + log_zeny(sd, "B", pl_sd, zeny); + + // move item + pc_additem(pl_sd, &sd->status.inventory[index], amount); + pc_delitem(sd, index, amount, 1, 0); + pl_sd->buyingstore.items[listidx].amount-= amount; + + // pay up + pc_payzeny(pl_sd, zeny); + pc_getzeny(sd, zeny); + pl_sd->buyingstore.zenylimit-= zeny; + + // notify clients + clif_buyingstore_delete_item(sd, index, amount, pl_sd->buyingstore.items[listidx].price); + clif_buyingstore_update_item(pl_sd, nameid, amount); + } + + // check whether or not there is still something to buy + ARR_FIND( 0, pl_sd->buyingstore.slots, i, pl_sd->buyingstore.items[i].amount != 0 ); + if( i == pl_sd->buyingstore.slots ) + {// everything was bought + clif_buyingstore_trade_failed_buyer(pl_sd, BUYINGSTORE_TRADE_BUYER_NO_ITEMS); + buyingstore_close(pl_sd); + } + else if( pl_sd->buyingstore.zenylimit == 0 ) + {// zeny limit reached + clif_buyingstore_trade_failed_buyer(pl_sd, BUYINGSTORE_TRADE_BUYER_ZENY); + buyingstore_close(pl_sd); + } +} diff --git a/src/map/buyingstore.h b/src/map/buyingstore.h new file mode 100644 index 000000000..473fdb01a --- /dev/null +++ b/src/map/buyingstore.h @@ -0,0 +1,29 @@ +// Copyright (c) Athena Dev Teams - Licensed under GNU GPL +// For more information, see LICENCE in the main folder + +#ifndef _BUYINGSTORE_H_ +#define _BUYINGSTORE_H_ + +#define MAX_BUYINGSTORE_SLOTS 5 + +struct s_buyingstore_item +{ + int price; + unsigned short amount; + unsigned short nameid; +}; + +struct s_buyingstore +{ + struct s_buyingstore_item items[MAX_BUYINGSTORE_SLOTS]; + int zenylimit; + unsigned char slots; +}; + +bool buyingstore_setup(struct map_session_data* sd, unsigned char slots); +void buyingstore_create(struct map_session_data* sd, int zenylimit, unsigned char result, const char* storename, const uint8* itemlist, unsigned int count); +void buyingstore_close(struct map_session_data* sd); +void buyingstore_open(struct map_session_data* sd, int account_id); +void buyingstore_trade(struct map_session_data* sd, int account_id, unsigned int buyer_id, const uint8* itemlist, unsigned int count); + +#endif // _BUYINGSTORE_H_ diff --git a/src/map/chat.c b/src/map/chat.c index 96ec4c20d..4ba784b2e 100644 --- a/src/map/chat.c +++ b/src/map/chat.c @@ -69,6 +69,11 @@ int chat_createpcchat(struct map_session_data* sd, const char* title, const char if( sd->chatID ) return 0; //Prevent people abusing the chat system by creating multiple chats, as pointed out by End of Exam. [Skotlex] + if( sd->vender_id || sd->state.buyingstore ) + {// not chat, when you already have a store open + return 0; + } + if( map[sd->bl.m].flag.nochat ) { clif_displaymessage(sd->fd, msg_txt(281)); @@ -108,7 +113,7 @@ int chat_joinchat(struct map_session_data* sd, int chatid, const char* pass) nullpo_ret(sd); cd = (struct chat_data*)map_id2bl(chatid); - if( cd == NULL || cd->bl.type != BL_CHAT || cd->bl.m != sd->bl.m || sd->vender_id || sd->chatID || cd->users >= cd->limit ) + if( cd == NULL || cd->bl.type != BL_CHAT || cd->bl.m != sd->bl.m || sd->vender_id || sd->state.buyingstore || sd->chatID || cd->users >= cd->limit ) { clif_joinchatfail(sd,0); return 0; diff --git a/src/map/clif.c b/src/map/clif.c index 59693d235..1bf87aec5 100644 --- a/src/map/clif.c +++ b/src/map/clif.c @@ -56,7 +56,10 @@ struct Clif_Config { struct s_packet_db packet_db[MAX_PACKET_VER + 1][MAX_PACKET_DB + 1]; //Converts item type in case of pet eggs. -#define itemtype(a) (a == IT_PETEGG)?IT_WEAPON:a +inline int itemtype(int type) +{ + return ( type == IT_PETEGG ) ? IT_WEAPON : type; +} #define WBUFPOS(p,pos,x,y,dir) \ do { \ @@ -3644,6 +3647,9 @@ static void clif_getareachar_pc(struct map_session_data* sd,struct map_session_d if(dstsd->vender_id) clif_showvendingboard(&dstsd->bl,dstsd->message,sd->fd); + if( dstsd->state.buyingstore ) + clif_buyingstore_entry_single(sd, dstsd); + if(dstsd->spiritball > 0) clif_spiritball_single(sd->fd, dstsd); @@ -4072,6 +4078,8 @@ int clif_outsight(struct block_list *bl,va_list ap) } if(sd->vender_id) clif_closevendingboard(bl,tsd->fd); + if( sd->state.buyingstore ) + clif_buyingstore_disappear_entry_single(tsd, sd); break; case BL_ITEM: clif_clearflooritem((struct flooritem_data*)bl,tsd->fd); @@ -12851,7 +12859,7 @@ void clif_Auction_openwindow(struct map_session_data *sd) { int fd = sd->fd; - if( sd->state.storage_flag || sd->vender_id || sd->state.trading ) + if( sd->state.storage_flag || sd->vender_id || sd->state.buyingstore || sd->state.trading ) return; WFIFOHEAD(fd,12); @@ -14033,6 +14041,308 @@ void clif_showdigit(struct map_session_data* sd, unsigned char type, int value) WFIFOSET(sd->fd, packet_len(0x1b1)); } + +/// Buying Store System +/// + +/// Opens preparation window for buying store (ZC_OPEN_BUYING_STORE) +/// 0810 .B +void clif_buyingstore_open(struct map_session_data* sd) +{ + int fd = sd->fd; + + WFIFOHEAD(fd,packet_len(0x810)); + WFIFOW(fd,0) = 0x810; + WFIFOB(fd,2) = sd->buyingstore.slots; + WFIFOSET(fd,packet_len(0x810)); +} + + +/// Request to create a buying store (CZ_REQ_OPEN_BUYING_STORE) +/// 0811 .W .L .B .80B { .W .W .L }* +/// result: +/// 0 = cancel +/// 1 = open +static void clif_parse_ReqOpenBuyingStore(int fd, struct map_session_data* sd) +{ + const unsigned int blocksize = 8; + uint8* itemlist; + char storename[MESSAGE_SIZE]; + unsigned char result; + int zenylimit; + unsigned int count, packet_len; + struct s_packet_db* info = &packet_db[sd->packet_ver][RFIFOW(fd,0)]; + + packet_len = RFIFOW(fd,info->pos[0]); + + // TODO: Make this check global for all variable length packets. + if( packet_len < 89 ) + {// minimum packet length + ShowError("clif_parse_ReqOpenBuyingStore: Malformed packet (expected length=%u, length=%u, account_id=%d).\n", 89, packet_len, sd->bl.id); + return; + } + + zenylimit = RFIFOL(fd,info->pos[1]); + result = RFIFOL(fd,info->pos[2]); + safestrncpy(storename, (const char*)RFIFOP(fd,info->pos[3]), sizeof(storename)); + itemlist = RFIFOP(fd,info->pos[4]); + + // so that buyingstore_create knows, how many elements it has access to + packet_len-= info->pos[4]; + + if( packet_len%blocksize ) + { + ShowError("clif_parse_ReqOpenBuyingStore: Unexpected item list size %u (account_id=%d, block size=%u)\n", packet_len, sd->bl.id, blocksize); + return; + } + count = packet_len/blocksize; + + buyingstore_create(sd, zenylimit, result, storename, itemlist, count); +} + + +/// Notification, that the requested buying store could not be created (ZC_FAILED_OPEN_BUYING_STORE_TO_BUYER) +/// 0812 .W .L +/// result: +/// 1 = "Failed to open buying store." (0x6cd, MSI_BUYINGSTORE_OPEN_FAILED) +/// 2 = "Total amount of then possessed items exceeds the weight limit by . Please re-enter." (0x6ce, MSI_BUYINGSTORE_OVERWEIGHT) +/// 8 = "No sale (purchase) information available." (0x705) +/// other = nothing +void clif_buyingstore_open_failed(struct map_session_data* sd, unsigned short result, unsigned int weight) +{ + int fd = sd->fd; + + WFIFOHEAD(fd,packet_len(0x812)); + WFIFOW(fd,0) = 0x812; + WFIFOW(fd,2) = result; + WFIFOL(fd,4) = weight; + WFIFOSET(fd,packet_len(0x812)); +} + + +/// Notification, that the requested buying store was created (ZC_MYITEMLIST_BUYING_STORE) +/// 0813 .W .L .L { .L .W .B .W }* +void clif_buyingstore_myitemlist(struct map_session_data* sd) +{ + int fd = sd->fd; + unsigned int i; + + WFIFOHEAD(fd,12+sd->buyingstore.slots*9); + WFIFOW(fd,0) = 0x813; + WFIFOW(fd,2) = 12+sd->buyingstore.slots*9; + WFIFOL(fd,4) = sd->bl.id; + WFIFOL(fd,8) = sd->buyingstore.zenylimit; + + for( i = 0; i < sd->buyingstore.slots; i++ ) + { + WFIFOL(fd,12+i*9) = sd->buyingstore.items[i].price; + WFIFOW(fd,16+i*9) = sd->buyingstore.items[i].amount; + WFIFOB(fd,18+i*9) = itemtype(itemdb_type(sd->buyingstore.items[i].nameid)); + WFIFOW(fd,19+i*9) = sd->buyingstore.items[i].nameid; + } + + WFIFOSET(fd,WFIFOW(fd,2)); +} + + +/// Notifies clients in area of a buying store (ZC_BUYING_STORE_ENTRY) +/// 0814 .L .80B +void clif_buyingstore_entry(struct map_session_data* sd) +{ + uint8 buf[86]; + + WBUFW(buf,0) = 0x814; + WBUFL(buf,2) = sd->bl.id; + memcpy(WBUFP(buf,6), sd->message, MESSAGE_SIZE); + + clif_send(buf, packet_len(0x814), &sd->bl, AREA_WOS); +} +void clif_buyingstore_entry_single(struct map_session_data* sd, struct map_session_data* pl_sd) +{ + int fd = sd->fd; + + WFIFOHEAD(fd,packet_len(0x814)); + WFIFOW(fd,0) = 0x814; + WFIFOL(fd,2) = pl_sd->bl.id; + memcpy(WFIFOP(fd,6), pl_sd->message, MESSAGE_SIZE); + WFIFOSET(fd,packet_len(0x814)); +} + + +/// Request to close own buying store (CZ_REQ_CLOSE_BUYING_STORE) +/// 0815 +static void clif_parse_ReqCloseBuyingStore(int fd, struct map_session_data* sd) +{ + buyingstore_close(sd); +} + + +/// Notifies clients in area that a buying store was closed (ZC_DISAPPEAR_BUYING_STORE_ENTRY) +/// 0816 .L +void clif_buyingstore_disappear_entry(struct map_session_data* sd) +{ + uint8 buf[6]; + + WBUFW(buf,0) = 0x816; + WBUFL(buf,2) = sd->bl.id; + + clif_send(buf, packet_len(0x816), &sd->bl, AREA_WOS); +} +void clif_buyingstore_disappear_entry_single(struct map_session_data* sd, struct map_session_data* pl_sd) +{ + int fd = sd->fd; + + WFIFOHEAD(fd,packet_len(0x816)); + WFIFOW(fd,0) = 0x816; + WFIFOL(fd,2) = pl_sd->bl.id; + WFIFOSET(fd,packet_len(0x816)); +} + + +/// Request to open someone else's buying store (CZ_REQ_CLICK_TO_BUYING_STORE) +/// 0817 .L +static void clif_parse_ReqClickBuyingStore(int fd, struct map_session_data* sd) +{ + int account_id; + + account_id = RFIFOL(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[0]); + + buyingstore_open(sd, account_id); +} + + +/// Sends buying store item list (ZC_ACK_ITEMLIST_BUYING_STORE) +/// 0818 .W .L .L .L { .L .W .B .W }* +void clif_buyingstore_itemlist(struct map_session_data* sd, struct map_session_data* pl_sd) +{ + int fd = sd->fd; + unsigned int i; + + WFIFOHEAD(fd,16+pl_sd->buyingstore.slots*9); + WFIFOW(fd,0) = 0x818; + WFIFOW(fd,2) = 16+pl_sd->buyingstore.slots*9; + WFIFOL(fd,4) = pl_sd->bl.id; + WFIFOL(fd,8) = pl_sd->buyer_id; + WFIFOL(fd,12) = pl_sd->buyingstore.zenylimit; + + for( i = 0; i < pl_sd->buyingstore.slots; i++ ) + { + WFIFOL(fd,16+i*9) = pl_sd->buyingstore.items[i].price; + WFIFOW(fd,20+i*9) = pl_sd->buyingstore.items[i].amount; // TODO: Figure out, if no longer needed items (amount == 0) are listed on official. + WFIFOB(fd,22+i*9) = itemtype(itemdb_type(pl_sd->buyingstore.items[i].nameid)); + WFIFOW(fd,23+i*9) = pl_sd->buyingstore.items[i].nameid; + } + + WFIFOSET(fd,WFIFOW(fd,2)); +} + + +/// Request to sell items to a buying store (CZ_REQ_TRADE_BUYING_STORE) +/// 0819 .W .L .L { .W .W .W }* +static void clif_parse_ReqTradeBuyingStore(int fd, struct map_session_data* sd) +{ + const unsigned int blocksize = 6; + uint8* itemlist; + int account_id; + unsigned int count, packet_len, buyer_id; + struct s_packet_db* info = &packet_db[sd->packet_ver][RFIFOW(fd,0)]; + + packet_len = RFIFOW(fd,info->pos[0]); + + if( packet_len < 12 ) + {// minimum packet length + ShowError("clif_parse_ReqTradeBuyingStore: Malformed packet (expected length=%u, length=%u, account_id=%d).\n", 12, packet_len, sd->bl.id); + return; + } + + account_id = RFIFOL(fd,info->pos[1]); + buyer_id = RFIFOL(fd,info->pos[2]); + itemlist = RFIFOP(fd,info->pos[3]); + + // so that buyingstore_trade knows, how many elements it has access to + packet_len-= info->pos[3]; + + if( packet_len%blocksize ) + { + ShowError("clif_parse_ReqTradeBuyingStore: Unexpected item list size %u (account_id=%d, buyer_id=%d, block size=%u)\n", packet_len, sd->bl.id, account_id, blocksize); + return; + } + count = packet_len/blocksize; + + buyingstore_trade(sd, account_id, buyer_id, itemlist, count); +} + + +/// Notifies the buyer, that the buying store has been closed due to a post-trade condition (ZC_FAILED_TRADE_BUYING_STORE_TO_BUYER) +/// 081a .W +/// result: +/// 3 = "All items within the buy limit were purchased." (0x6cf, MSI_BUYINGSTORE_TRADE_OVERLIMITZENY) +/// 4 = "All items were purchased." (0x6d0, MSI_BUYINGSTORE_TRADE_BUYCOMPLETE) +/// other = nothing +void clif_buyingstore_trade_failed_buyer(struct map_session_data* sd, short result) +{ + int fd = sd->fd; + + WFIFOHEAD(fd,packet_len(0x81a)); + WFIFOW(fd,0) = 0x81a; + WFIFOW(fd,2) = result; + WFIFOSET(fd,packet_len(0x81a)); +} + + +/// Updates the zeny limit and an item in the buying store item list (ZC_UPDATE_ITEM_FROM_BUYING_STORE) +/// 081b .W .W .L +void clif_buyingstore_update_item(struct map_session_data* sd, unsigned short nameid, unsigned short amount) +{ + int fd = sd->fd; + + WFIFOHEAD(fd,packet_len(0x81b)); + WFIFOW(fd,0) = 0x81b; + WFIFOW(fd,2) = nameid; + WFIFOW(fd,4) = amount; // amount of nameid received + WFIFOW(fd,6) = sd->buyingstore.zenylimit; + WFIFOSET(fd,packet_len(0x81b)); +} + + +/// Deletes item from inventory, that was sold to a buying store (ZC_ITEM_DELETE_BUYING_STORE) +/// 081c .W .W .L +/// message: +/// "%s (%d) were sold at %dz." (0x6d2, MSI_BUYINGSTORE_TRADE_SELLCOMPLETE) +/// +/// @note This function has to be called _instead_ of clif_delitem/clif_dropitem. +void clif_buyingstore_delete_item(struct map_session_data* sd, short index, unsigned short amount, int price) +{ + int fd = sd->fd; + + WFIFOHEAD(fd,packet_len(0x81c)); + WFIFOW(fd,0) = 0x81c; + WFIFOW(fd,2) = index+2; + WFIFOW(fd,4) = amount; + WFIFOL(fd,6) = price; // price per item, client calculates total Zeny by itself + WFIFOSET(fd,packet_len(0x81c)); +} + + +/// Notifies the seller, that a buying store trade failed (ZC_FAILED_TRADE_BUYING_STORE_TO_SELLER) +/// 0824 .W .W +/// result: +/// 5 = "The deal has failed." (0x39, MSI_DEAL_FAIL) +/// 6 = "The trade failed, because the entered amount of item %s is higher, than the buyer is willing to buy." (0x6d3, MSI_BUYINGSTORE_TRADE_OVERCOUNT) +/// 7 = "The trade failed, because the buyer is lacking required balance." (0x6d1, MSI_BUYINGSTORE_TRADE_LACKBUYERZENY) +/// other = nothing +void clif_buyingstore_trade_failed_seller(struct map_session_data* sd, short result, unsigned short nameid) +{ + int fd = sd->fd; + + WFIFOHEAD(fd,packet_len(0x824)); + WFIFOW(fd,0) = 0x824; + WFIFOW(fd,2) = result; + WFIFOW(fd,4) = nameid; + WFIFOSET(fd,packet_len(0x824)); +} + + /*========================================== * パケットデバッグ *------------------------------------------*/ @@ -14435,8 +14745,8 @@ static int packetdb_readdb(void) #else // for Party booking ( PACKETVER >= 20091229 ) -1, -1, 18, 4, 8, 6, 2, 4, 14, 50, 18, 6, 2, 3, 14, 20, #endif - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 3, -1, 8, -1, 86, 2, 6, 6, -1, -1, 4, 10, 10, 0, 0, 0, + 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; struct { @@ -14628,6 +14938,11 @@ static int packetdb_readdb(void) {clif_parse_PartyBookingDeleteReq,"bookingdelreq"}, #endif {clif_parse_PVPInfo,"pvpinfo"}, + // Buying Store + {clif_parse_ReqOpenBuyingStore,"reqopenbuyingstore"}, + {clif_parse_ReqCloseBuyingStore,"reqclosebuyingstore"}, + {clif_parse_ReqClickBuyingStore,"reqclickbuyingstore"}, + {clif_parse_ReqTradeBuyingStore,"reqtradebuyingstore"}, {NULL,NULL} }; diff --git a/src/map/clif.h b/src/map/clif.h index 50dc76c72..67516e538 100644 --- a/src/map/clif.h +++ b/src/map/clif.h @@ -605,4 +605,18 @@ void clif_PartyBookingInsertNotify(struct map_session_data* sd, struct party_boo void clif_showdigit(struct map_session_data* sd, unsigned char type, int value); +/// Buying Store System +void clif_buyingstore_open(struct map_session_data* sd); +void clif_buyingstore_open_failed(struct map_session_data* sd, unsigned short result, unsigned int weight); +void clif_buyingstore_myitemlist(struct map_session_data* sd); +void clif_buyingstore_entry(struct map_session_data* sd); +void clif_buyingstore_entry_single(struct map_session_data* sd, struct map_session_data* pl_sd); +void clif_buyingstore_disappear_entry(struct map_session_data* sd); +void clif_buyingstore_disappear_entry_single(struct map_session_data* sd, struct map_session_data* pl_sd); +void clif_buyingstore_itemlist(struct map_session_data* sd, struct map_session_data* pl_sd); +void clif_buyingstore_trade_failed_buyer(struct map_session_data* sd, short result); +void clif_buyingstore_update_item(struct map_session_data* sd, unsigned short nameid, unsigned short amount); +void clif_buyingstore_delete_item(struct map_session_data* sd, short index, unsigned short amount, int price); +void clif_buyingstore_trade_failed_seller(struct map_session_data* sd, short result, unsigned short nameid); + #endif /* _CLIF_H_ */ diff --git a/src/map/itemdb.c b/src/map/itemdb.c index 98f9a90d1..d8a8bb2cc 100644 --- a/src/map/itemdb.c +++ b/src/map/itemdb.c @@ -663,6 +663,33 @@ static bool itemdb_read_itemdelay(char* str[], int columns, int current) return true; } + +/// Reads items allowed to be sold in buying stores +static bool itemdb_read_buyingstore(char* fields[], int columns, int current) +{// + int nameid; + struct item_data* id; + + nameid = atoi(fields[0]); + + if( ( id = itemdb_exists(nameid) ) == NULL ) + { + ShowWarning("itemdb_read_buyingstore: Invalid item id %d.\n", nameid); + return false; + } + + if( !itemdb_isstackable2(id) ) + { + ShowWarning("itemdb_read_buyingstore: Non-stackable item id %d cannot be enabled for buying store.\n", nameid); + return false; + } + + id->flag.buyingstore = true; + + return true; +} + + /*====================================== * Applies gender restrictions according to settings. [Skotlex] *======================================*/ @@ -979,6 +1006,7 @@ static void itemdb_read(void) sv_readdb(db_path, "item_noequip.txt", ',', 2, 2, -1, &itemdb_read_noequip); sv_readdb(db_path, "item_trade.txt", ',', 3, 3, -1, &itemdb_read_itemtrade); sv_readdb(db_path, "item_delay.txt", ',', 2, 2, MAX_ITEMDELAYS, &itemdb_read_itemdelay); + sv_readdb(db_path, "item_buyingstore.txt", ',', 1, 1, -1, &itemdb_read_buyingstore); } /*========================================== diff --git a/src/map/itemdb.h b/src/map/itemdb.h index b5bcb84ea..463061175 100644 --- a/src/map/itemdb.h +++ b/src/map/itemdb.h @@ -76,6 +76,7 @@ struct item_data { unsigned delay_consume : 1; // Signifies items that are not consumed immediately upon double-click [Skotlex] unsigned trade_restriction : 7; //Item restrictions mask [Skotlex] unsigned autoequip: 1; + unsigned buyingstore : 1; } flag; short gm_lv_trade_override; //GM-level to override trade_restriction }; diff --git a/src/map/log.h b/src/map/log.h index 9dfc0c0ea..f88236489 100644 --- a/src/map/log.h +++ b/src/map/log.h @@ -36,9 +36,10 @@ typedef enum log_what { LOG_USED_ITEMS = 0x0100, // used by player LOG_MVP_PRIZE = 0x0200, LOG_COMMAND_ITEMS = 0x0400, // created/deleted through @/# commands - LOG_STORAGE_ITEMS = 0x0800, // placed/retrieved from storage - LOG_GSTORAGE_ITEMS = 0x1000, // placed/retrieved from guild storage - LOG_MAILS = 0x2000 // mail system transactions + LOG_STORAGE_ITEMS = 0x0800, // placed/retrieved from storage + LOG_GSTORAGE_ITEMS = 0x1000, // placed/retrieved from guild storage + LOG_MAILS = 0x2000, // mail system transactions + LOG_BUYING_STORE = 0x4000, // buying store transactions } log_what; extern struct Log_Config { diff --git a/src/map/mail.c b/src/map/mail.c index f0869185a..c866bfb60 100644 --- a/src/map/mail.c +++ b/src/map/mail.c @@ -162,7 +162,7 @@ int mail_openmail(struct map_session_data *sd) { nullpo_ret(sd); - if( sd->state.storage_flag || sd->vender_id || sd->state.trading ) + if( sd->state.storage_flag || sd->vender_id || sd->state.buyingstore || sd->state.trading ) return 0; clif_Mail_window(sd->fd, 0); diff --git a/src/map/pc.h b/src/map/pc.h index c48defbf5..328e43047 100644 --- a/src/map/pc.h +++ b/src/map/pc.h @@ -7,6 +7,7 @@ #include "../common/mmo.h" // JOB_*, MAX_FAME_LIST, struct fame_list, struct mmo_charstatus #include "../common/timer.h" // INVALID_TIMER #include "battle.h" // battle_config +#include "buyingstore.h" // struct s_buyingstore #include "itemdb.h" // MAX_ITEMGROUP #include "map.h" // RC_MAX #include "pc.h" // struct map_session_data @@ -128,6 +129,7 @@ struct map_session_data { unsigned doridori : 1; unsigned ignoreAll : 1; unsigned debug_remove_map : 1; // temporary state to track double remove_map's [FlavioJS] + unsigned buyingstore : 1; unsigned short autoloot; unsigned short autolootid; // [Zephyrus] unsigned noks : 3; // [Zeph Kill Steal Protection] @@ -356,6 +358,9 @@ struct map_session_data { char message[MESSAGE_SIZE]; struct s_vending vending[MAX_VENDING]; + unsigned int buyer_id; // uid of open buying store + struct s_buyingstore buyingstore; + struct pet_data *pd; struct homun_data *hd; // [blackhole89] struct mercenary_data *md; @@ -413,8 +418,8 @@ struct map_session_data { const char* debug_func; }; -//Update this max as necessary. 54 is the value needed for Super Baby currently -#define MAX_SKILL_TREE 54 +//Update this max as necessary. 55 is the value needed for Super Baby currently +#define MAX_SKILL_TREE 55 //Total number of classes (for data storage) #define CLASS_COUNT (JOB_MAX - JOB_NOVICE_HIGH + JOB_MAX_BASIC) @@ -515,9 +520,9 @@ extern int duel_count; #define pc_setsit(sd) ( (sd)->state.dead_sit = (sd)->vd.dead_sit = 2 ) #define pc_isdead(sd) ( (sd)->state.dead_sit == 1 ) #define pc_issit(sd) ( (sd)->vd.dead_sit == 2 ) -#define pc_isidle(sd) ( (sd)->chatID || (sd)->vender_id || DIFF_TICK(last_tick, (sd)->idletime) >= battle_config.idle_no_share ) -#define pc_istrading(sd) ( (sd)->npc_id || (sd)->vender_id || (sd)->state.trading ) -#define pc_cant_act(sd) ( (sd)->npc_id || (sd)->vender_id || (sd)->chatID || (sd)->sc.opt1 || (sd)->state.trading || (sd)->state.storage_flag ) +#define pc_isidle(sd) ( (sd)->chatID || (sd)->vender_id || (sd)->state.buyingstore || DIFF_TICK(last_tick, (sd)->idletime) >= battle_config.idle_no_share ) +#define pc_istrading(sd) ( (sd)->npc_id || (sd)->vender_id || (sd)->state.buyingstore || (sd)->state.trading ) +#define pc_cant_act(sd) ( (sd)->npc_id || (sd)->vender_id || (sd)->state.buyingstore || (sd)->chatID || (sd)->sc.opt1 || (sd)->state.trading || (sd)->state.storage_flag ) #define pc_setdir(sd,b,h) ( (sd)->ud.dir = (b) ,(sd)->head_dir = (h) ) #define pc_setchatid(sd,n) ( (sd)->chatID = n ) #define pc_ishiding(sd) ( (sd)->sc.option&(OPTION_HIDE|OPTION_CLOAK|OPTION_CHASEWALK) ) diff --git a/src/map/script.c b/src/map/script.c index bbb0041de..d66edcd84 100644 --- a/src/map/script.c +++ b/src/map/script.c @@ -14807,6 +14807,23 @@ BUILDIN_FUNC(pushpc) return 0; } + +/// Invokes buying store preparation window +/// buyingstore ; +BUILDIN_FUNC(buyingstore) +{ + struct map_session_data* sd; + + if( ( sd = script_rid2sd(st) ) == NULL ) + { + return 0; + } + + buyingstore_setup(sd, script_getnum(st,2)); + return 0; +} + + // declarations that were supposed to be exported from npc_chat.c #ifdef PCRE_SUPPORT BUILDIN_FUNC(defpattern); @@ -15168,6 +15185,7 @@ struct script_function buildin_func[] = { BUILDIN_DEF(areamobuseskill,"siiiiviiiii"), BUILDIN_DEF(progressbar,"si"), BUILDIN_DEF(pushpc,"ii"), + BUILDIN_DEF(buyingstore,"i"), // WoE SE BUILDIN_DEF(agitstart2,""), BUILDIN_DEF(agitend2,""), diff --git a/src/map/skill.c b/src/map/skill.c index ffb5a1826..160beeaef 100644 --- a/src/map/skill.c +++ b/src/map/skill.c @@ -5692,6 +5692,12 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in case ALL_WEWISH: clif_skill_nodamage(src,bl,skillid,skilllv,1); break; + case ALL_BUYING_STORE: + if( sd ) + {// players only, skill allows 5 buying slots + clif_skill_nodamage(src, bl, skillid, skilllv, buyingstore_setup(sd, MAX_BUYINGSTORE_SLOTS)); + } + break; default: ShowWarning("skill_castend_nodamage_id: Unknown skill used:%d\n",skillid); clif_skill_nodamage(src,bl,skillid,skilllv,1); diff --git a/src/map/trade.c b/src/map/trade.c index ba01826f2..bedbb9451 100644 --- a/src/map/trade.c +++ b/src/map/trade.c @@ -138,8 +138,8 @@ void trade_tradeack(struct map_session_data *sd, int type) } //Check if you can start trade. - if (sd->npc_id || sd->vender_id || sd->state.storage_flag || - tsd->npc_id || tsd->vender_id || tsd->state.storage_flag) + if (sd->npc_id || sd->vender_id || sd->state.buyingstore || sd->state.storage_flag || + tsd->npc_id || tsd->vender_id || tsd->state.buyingstore || tsd->state.storage_flag) { //Fail clif_tradestart(sd, 2); clif_tradestart(tsd, 2); diff --git a/src/map/unit.c b/src/map/unit.c index 7abfde12b..3f2b2094f 100644 --- a/src/map/unit.c +++ b/src/map/unit.c @@ -803,6 +803,7 @@ int unit_can_move(struct block_list *bl) if (sd && ( pc_issit(sd) || sd->vender_id || + sd->state.buyingstore || sd->state.blockedmove )) return 0; //Can't move @@ -1872,6 +1873,7 @@ int unit_remove_map_(struct block_list *bl, clr_type clrtype, const char* file, trade_tradecancel(sd); if(sd->vender_id) vending_closevending(sd); + buyingstore_close(sd); if(sd->state.storage_flag == 1) storage_storage_quit(sd,0); else if (sd->state.storage_flag == 2) diff --git a/vcproj-10/map-server_sql.vcxproj b/vcproj-10/map-server_sql.vcxproj index d8a35698e..201c0bfb6 100644 --- a/vcproj-10/map-server_sql.vcxproj +++ b/vcproj-10/map-server_sql.vcxproj @@ -146,6 +146,7 @@ + @@ -195,6 +196,7 @@ + diff --git a/vcproj-10/map-server_txt.vcxproj b/vcproj-10/map-server_txt.vcxproj index 3efded728..5c1847a0e 100644 --- a/vcproj-10/map-server_txt.vcxproj +++ b/vcproj-10/map-server_txt.vcxproj @@ -125,6 +125,7 @@ + @@ -174,6 +175,7 @@ + diff --git a/vcproj-6/map-server_sql.dsp b/vcproj-6/map-server_sql.dsp index 629fe4639..afc259bc7 100644 --- a/vcproj-6/map-server_sql.dsp +++ b/vcproj-6/map-server_sql.dsp @@ -231,6 +231,14 @@ SOURCE=..\src\map\battleground.h # End Source File # Begin Source File +SOURCE=..\src\map\buyingstore.c +# End Source File +# Begin Source File + +SOURCE=..\src\map\buyingstore.h +# End Source File +# Begin Source File + SOURCE=..\src\map\chat.c # End Source File # Begin Source File diff --git a/vcproj-6/map-server_txt.dsp b/vcproj-6/map-server_txt.dsp index 1359adc15..404af83ab 100644 --- a/vcproj-6/map-server_txt.dsp +++ b/vcproj-6/map-server_txt.dsp @@ -211,6 +211,10 @@ SOURCE=..\src\map\battleground.c # End Source File # Begin Source File +SOURCE=..\src\map\buyingstore.c +# End Source File +# Begin Source File + SOURCE=..\src\map\chat.c # End Source File # Begin Source File @@ -335,6 +339,10 @@ SOURCE=..\src\map\battleground.h # End Source File # Begin Source File +SOURCE=..\src\map\buyingstore.h +# End Source File +# Begin Source File + SOURCE=..\src\map\chat.h # End Source File # Begin Source File diff --git a/vcproj-7.1/map-server_sql.vcproj b/vcproj-7.1/map-server_sql.vcproj index de441773c..e820ec563 100644 --- a/vcproj-7.1/map-server_sql.vcproj +++ b/vcproj-7.1/map-server_sql.vcproj @@ -166,6 +166,12 @@ + + + + diff --git a/vcproj-7.1/map-server_txt.vcproj b/vcproj-7.1/map-server_txt.vcproj index f91248859..998f5b916 100644 --- a/vcproj-7.1/map-server_txt.vcproj +++ b/vcproj-7.1/map-server_txt.vcproj @@ -166,6 +166,12 @@ + + + + diff --git a/vcproj-8/map-server_sql.vcproj b/vcproj-8/map-server_sql.vcproj index f1b1b6cd6..2a29782de 100644 --- a/vcproj-8/map-server_sql.vcproj +++ b/vcproj-8/map-server_sql.vcproj @@ -374,6 +374,13 @@ + + + + + + + diff --git a/vcproj-9/map-server_sql.vcproj b/vcproj-9/map-server_sql.vcproj index e147ca137..0dd152f88 100644 --- a/vcproj-9/map-server_sql.vcproj +++ b/vcproj-9/map-server_sql.vcproj @@ -374,6 +374,14 @@ RelativePath="..\src\map\battleground.c" > + + + + diff --git a/vcproj-9/map-server_txt.vcproj b/vcproj-9/map-server_txt.vcproj index d4ea93a89..14daabc20 100644 --- a/vcproj-9/map-server_txt.vcproj +++ b/vcproj-9/map-server_txt.vcproj @@ -225,6 +225,14 @@ RelativePath="..\src\map\battleground.h" > + + + + -- cgit v1.2.3-60-g2f50