diff options
-rw-r--r-- | db/const.txt | 6 | ||||
-rw-r--r-- | doc/sample/npc_trader_sample.txt | 58 | ||||
-rw-r--r-- | doc/script_commands.txt | 64 | ||||
-rw-r--r-- | npc/merchants/shops.txt | 2240 | ||||
-rw-r--r-- | sql-files/main.sql | 12 | ||||
-rw-r--r-- | sql-files/upgrades/2013-12-24--00-15.sql | 8 | ||||
-rw-r--r-- | sql-files/upgrades/index.txt | 1 | ||||
-rw-r--r-- | src/common/mmo.h | 2 | ||||
-rw-r--r-- | src/map/atcommand.c | 27 | ||||
-rw-r--r-- | src/map/clif.c | 224 | ||||
-rw-r--r-- | src/map/clif.h | 8 | ||||
-rw-r--r-- | src/map/map.c | 3 | ||||
-rw-r--r-- | src/map/npc.c | 566 | ||||
-rw-r--r-- | src/map/npc.h | 46 | ||||
-rw-r--r-- | src/map/packets.h | 43 | ||||
-rw-r--r-- | src/map/packets_struct.h | 44 | ||||
-rw-r--r-- | src/map/script.c | 277 | ||||
-rw-r--r-- | src/map/status.c | 324 | ||||
-rw-r--r-- | src/map/status.h | 51 |
19 files changed, 3500 insertions, 504 deletions
diff --git a/db/const.txt b/db/const.txt index 8e7807695..ab14afca2 100644 --- a/db/const.txt +++ b/db/const.txt @@ -1257,6 +1257,7 @@ SC_MTF_MLEATKED 569 SC_MTF_CRIDAMAGE 570 SC_MOONSTAR 571 SC_SUPER_STAR 572 +SC_OKTOBERFEST 573 e_gasp 0 e_what 1 @@ -3348,3 +3349,8 @@ IOT_GUILD 3 false 0 true 1 + +NST_ZENY 0 +NST_CASH 1 +NST_MARKET 2 +NST_CUSTOM 3 diff --git a/doc/sample/npc_trader_sample.txt b/doc/sample/npc_trader_sample.txt new file mode 100644 index 000000000..abc87f6b4 --- /dev/null +++ b/doc/sample/npc_trader_sample.txt @@ -0,0 +1,58 @@ +//===== Hercules Script ======================================= +//= Sample: NPC Trader +//===== By: ================================================== +//= Hercules Dev Team +//===== Current Version: ===================================== +//= 20131223 +//===== Description: ========================================= +//= Demonstrates NPC Trader. +//============================================================ + +/* ordinary zeny trader */ +prontera,152,151,1 trader TestTrader 952,{ + OnInit: + sellitem 2115; + end; +} +/* ordinary cash trader */ +prontera,152,152,1 trader TestTraderCash 952,{ + OnInit: + tradertype(NST_CASH); + sellitem 2115; + end; +} +/* custom npc trader */ +prontera,153,152,1 trader TestCustom2 952,{ + OnInit: + tradertype(NST_CUSTOM); + sellitem 501,2; + end; + +/* allows currency to be item 501 and 502 */ +OnCountFunds: + setcurrency(countitem(501),countitem(502)); + end; + +/* receives @price (total cost) and @points (the secondary input field for cash windows) */ +OnPayFunds: + dispbottom "Hi: price="+@price+" and points="+@points; + if( countitem(502) < @points || countitem(501) < @price-@points ) + end; + delitem 502,@points; + delitem 501,@price-@points; + purchaseok(); + end; +} +/* demonstrates Market Trader */ +prontera,150,160,6 trader HaiMarket 952,{ +OnInit: + tradertype(NST_MARKET); + sellitem 501,-1,49; + end; + +OnClock0000://resupplies red potions on midnight +OnMyResupply: + if( shopcount(501) < 20 ) + sellitem 501,-1,49; + end; +}
\ No newline at end of file diff --git a/doc/script_commands.txt b/doc/script_commands.txt index 9186ba714..f5f2d7d9c 100644 --- a/doc/script_commands.txt +++ b/doc/script_commands.txt @@ -1120,6 +1120,7 @@ From here on, we will have the commands sorted as follow: 9.- Battleground commands. 10.- Mercenary commands. 11.- Queue commands. +12.- NPC Trader commands ===================== @@ -8471,3 +8472,66 @@ Deletes a queue iterator from memory and returns 1 when it fails, otherwise 0 is returned. --------------------------------------- + +====================== +|12.- NPC Trader Commands.| +====================== +--------------------------------------- +Commands that control NPC Trader Shops +See /doc/sample/npc_trader_sample.txt + +--------------------------------------- + +*openshop({NPC_Name}); + +opens the trader shop from the currently-attached npc unless, +when the optional NPC_Name param is used. + +--------------------------------------- + +*sellitem <Item_ID>{,<price>{,<qty>}}; + +adds (or modifies) <Item_ID> data to the shop, +when <price> is not provided (or when it is -1) itemdb default is used. +qty is only necessary for NST_MARKET trader types. + +when <Item_ID> is already in the shop, +the previous data (price/qty), is overwritten with the new. + +--------------------------------------- + +*stopselling <Item_ID>; + +attempts to remove <Item_ID> from the current shop list. + +--------------------------------------- + +*setcurrency <Val1>{,<Val2>}; + +updates the currently attached player shop funds. + +--------------------------------------- + +*tradertype(<Type>); + +Modifies the npc trader type, item list is cleared upon modifiying the value. +By default, all npcs staart with tradertype(NST_ZENY); + +- NST_ZENY (0) Normal Zeny Shop +- NST_CASH (1) Normal Cash Shop +- NST_MARKET (2) Normal NPC Market Shop (where items have limited availability and need to be refurbished) +- NST_CUSTOM (3) Custom Shop (any currency, item/var/etca, check sample) + +--------------------------------------- + +*purchaseok(); + +Signs that the transaction (on a NST_CUSTOM trader) has been successful. + +--------------------------------------- + +*shopcount(<Item_ID>); + +Returns the amount of still-available <Item_ID> in the shop (on a NST_MARKET trader). + +--------------------------------------- diff --git a/npc/merchants/shops.txt b/npc/merchants/shops.txt index b20874ffb..a1ab894d0 100644 --- a/npc/merchants/shops.txt +++ b/npc/merchants/shops.txt @@ -1,9 +1,7 @@ //===== Hercules Script ====================================== //= Shops -//===== By: ================================================== -//= rAthena Dev Team //===== Current Version: ===================================== -//= 3.4 +//= 3.5 //===== Description: ========================================= //= Town shop NPCs. //===== Additional Comments: ================================= @@ -36,291 +34,2169 @@ //= 3.2 Added Missing Items to the pet Groomers in prontera, payon, and yuno. BugReport:6680[Spre] //= 3.3 Moved more shops to Renewal file. [Euphy] //= 3.4 Moved Izlude shops to pre-re/re paths. [Streusel] +//= 3.5 Converted to trader format [Yommy] //============================================================ //======================================================= // Alberta //======================================================= -alb2trea,87,65,5 shop Tool Dealer#alb 4_M_01,1750:-1,1751:-1,1752:-1,501:-1,502:-1,503:-1,504:-1,506:-1,645:-1,656:-1 -alberta_in,165,96,0 shop Item Collector#alb 1_F_MERCHANT_02,911:-1,528:-1 -alberta_in,182,97,0 shop Tool Dealer#alb2 1_F_MERCHANT_01,1750:-1,611:-1,501:-1,502:-1,503:-1,504:-1,506:-1,645:-1,656:-1,601:-1,602:-1,2243:-1 -alberta_in,180,15,0 shop Armor Dealer#alb 4W_F_01,2101:-1,2103:-1,2401:-1,2403:-1,2405:-1,2501:-1,2503:-1,2505:-1,2203:-1,2201:-1,2205:-1,2226:-1,2301:-1,2303:-1,2305:-1,2321:-1,2328:-1,2332:-1,2307:-1,2309:-1,2312:-1,2314:-1,2628:-1 -alberta_in,188,21,0 shop Weapon Dealer#alb 1_M_03,1750:-1,1751:-1,1101:-1,1104:-1,1107:-1,1201:-1,1204:-1,1207:-1,1601:-1,1701:-1,1301:-1,1351:-1,1354:-1,1357:-1,1360:-1 -alberta_in,175,97,4 shop Weapon Dealer#alb2 4_KID01,1146:-1,1245:-1 -alberta_in,176,81,3 shop Trading Merchant#alb 4_M_HUMERCHANT,13200:-1,13201:-1,13202:-1,13150:-1,13102:-1,13151:-1,13154:-1,13155:-1,13163:-1,13165:-1,13168:-1 +alb2trea,87,65,5 trader Tool Dealer#alb 4_M_01,{ +OnInit: + sellitem Arrow; + sellitem Silver_Arrow; + sellitem Fire_Arrow; + sellitem Red_Potion; + sellitem Orange_Potion; + sellitem Yellow_Potion; + sellitem White_Potion; + sellitem Green_Potion; + sellitem Center_Potion; + sellitem Awakening_Potion; +} + +alberta_in,165,96,0 trader Item Collector#alb 1_F_MERCHANT_02,{ +OnInit: + sellitem Scell; + sellitem Monster's_Feed; +} + +alberta_in,182,97,0 trader Tool Dealer#alb2 1_F_MERCHANT_01,{ +OnInit: + sellitem Arrow; + sellitem Spectacles; + sellitem Red_Potion; + sellitem Orange_Potion; + sellitem Yellow_Potion; + sellitem White_Potion; + sellitem Green_Potion; + sellitem Center_Potion; + sellitem Awakening_Potion; + sellitem Wing_Of_Fly; + sellitem Wing_Of_Butterfly; + sellitem Spinning_Eyes; +} + +alberta_in,180,15,0 trader Armor Dealer#alb 4W_F_01,{ +OnInit: + sellitem Guard; + sellitem Buckler; + sellitem Sandals; + sellitem Shoes; + sellitem Boots; + sellitem Hood; + sellitem Muffler; + sellitem Manteau; + sellitem Glasses; + sellitem Sunglasses; + sellitem Diver's_Goggles; + sellitem Cap; + sellitem Cotton_Shirt; + sellitem Leather_Jacket; + sellitem Adventure_Suit; + sellitem Silk_Robe; + sellitem Wooden_Mail; + sellitem Silver_Robe; + sellitem Mantle; + sellitem Coat; + sellitem Padded_Armor; + sellitem Chain_Mail; + sellitem Novice_Armlet; +} + +alberta_in,188,21,0 trader Weapon Dealer#alb 1_M_03,{ +OnInit: + sellitem Arrow; + sellitem Silver_Arrow; + sellitem Sword; + sellitem Falchion; + sellitem Blade; + sellitem Knife; + sellitem Cutter; + sellitem Main_Gauche; + sellitem Rod; + sellitem Bow; + sellitem Axe; + sellitem Battle_Axe; + sellitem Hammer; + sellitem Buster; + sellitem Two_Handed_Axe; +} + +alberta_in,175,97,4 trader Weapon Dealer#alb2 4_KID01,{ +OnInit: + sellitem Town_Sword; + sellitem Cinquedea; +} + +alberta_in,176,81,3 trader Trading Merchant#alb 4_M_HUMERCHANT,{ +OnInit: + sellitem Bullet; + sellitem Silver_Bullet; + sellitem Shell_Of_Blood; + sellitem Branch; + sellitem Crimson_Bolt; + sellitem The_Cyclone; + sellitem Rolling_Stone; + sellitem Black_Rose; + sellitem Long_Barrel; + sellitem Jungle_Carbine; + sellitem Thunder_P; +} + //======================================================= // Al De Baran //======================================================= -aldeba_in,20,60,0 shop Armor Dealer#alde 4W_F_01,2228:-1,2103:-1,2105:-1,2307:-1,2309:-1,2312:-1,2314:-1,2316:-1,2505:-1,2405:-1,2628:-1,2627:-1 -aldeba_in,28,54,0 shop Weapon Dealer#alde 1_M_03,1201:-1,1204:-1,1207:-1,1210:-1,1213:-1,1216:-1,1219:-1,1222:-1 -aldeba_in,22,47,4 shop Weapon Dealer#alde2 4_M_06,1146:-1,1245:-1 -aldeba_in,94,56,5 shop Tool Dealer#alde 4_M_01,501:-1,502:-1,503:-1,504:-1,506:-1,645:-1,656:-1,601:-1,602:-1,611:-1,610:-1 -alde_alche,38,184,3 shop Material Seller#alche 4_M_SAGE_C,7143:-1,7141:-1,7140:-1,6248:-1,6250:-1,6251:-1,6255:-1,6261:-1,6262:-1,6297:-1 +aldeba_in,20,60,0 trader Armor Dealer#alde 4W_F_01,{ +OnInit: + sellitem Helm; + sellitem Buckler; + sellitem Shield; + sellitem Mantle; + sellitem Coat; + sellitem Padded_Armor; + sellitem Chain_Mail; + sellitem Plate_Armor; + sellitem Manteau; + sellitem Boots; + sellitem Novice_Armlet; + sellitem Belt; +} + +aldeba_in,28,54,0 trader Weapon Dealer#alde 1_M_03,{ +OnInit: + sellitem Knife; + sellitem Cutter; + sellitem Main_Gauche; + sellitem Dirk; + sellitem Dagger; + sellitem Stiletto; + sellitem Gladius; + sellitem Damascus; +} + +aldeba_in,22,47,4 trader Weapon Dealer#alde2 4_M_06,{ +OnInit: + sellitem Town_Sword; + sellitem Cinquedea; +} + +aldeba_in,94,56,5 trader Tool Dealer#alde 4_M_01,{ +OnInit: + sellitem Red_Potion; + sellitem Orange_Potion; + sellitem Yellow_Potion; + sellitem White_Potion; + sellitem Green_Potion; + sellitem Center_Potion; + sellitem Awakening_Potion; + sellitem Wing_Of_Fly; + sellitem Wing_Of_Butterfly; + sellitem Spectacles; + sellitem Leaf_Of_Yggdrasil; +} + +alde_alche,38,184,3 trader Material Seller#alche 4_M_SAGE_C,{ +OnInit: + sellitem Life_Force_Pot; + sellitem Yggdrasilberry_Dew; + sellitem Seed_Of_Life; + sellitem Melange_Pot; + sellitem Cooking_Skewer; + sellitem Black_Charcoal; + sellitem Large_Cookpot; + sellitem Fine_Noodle; + sellitem Cool_Gravy; + sellitem Bottle_To_Throw; +} + //======================================================= // Amatsu //======================================================= -ama_in01,89,28,5 shop Armor Dealer#ama 4_F_JPN2,2211:-1,2401:-1,2403:-1,2501:-1,2503:-1,2101:-1,2103:-1,2305:-1,2321:-1,2332:-1,2328:-1,2627:-1 -ama_in01,102,28,3 shop Weapon Dealer#ama 4_M_JPNOJI,1207:-1,1216:-1,1107:-1,1122:-1,1116:-1,1154:-1,1407:-1,1457:-1,1354:-1,1519:-1 -ama_in01,24,30,5 shop Tool Dealer#ama 4_M_JPN,1750:-1,1770:-1,611:-1,501:-1,502:-1,503:-1,504:-1,506:-1,645:-1,656:-1,601:-1,602:-1,1065:-1 +ama_in01,89,28,5 trader Armor Dealer#ama 4_F_JPN2,{ +OnInit: + sellitem Bandana; + sellitem Sandals; + sellitem Shoes; + sellitem Hood; + sellitem Muffler; + sellitem Guard; + sellitem Buckler; + sellitem Adventure_Suit; + sellitem Silk_Robe; + sellitem Silver_Robe; + sellitem Wooden_Mail; + sellitem Belt; +} + +ama_in01,102,28,3 trader Weapon Dealer#ama 4_M_JPNOJI,{ +OnInit: + sellitem Main_Gauche; + sellitem Stiletto; + sellitem Blade; + sellitem Ring_Pommel_Saber; + sellitem Katana; + sellitem Bastard_Sword; + sellitem Pike; + sellitem Partizan; + sellitem Hammer; + sellitem Chain; +} + +ama_in01,24,30,5 trader Tool Dealer#ama 4_M_JPN,{ +OnInit: + sellitem Arrow; + sellitem Iron_Arrow; + sellitem Spectacles; + sellitem Red_Potion; + sellitem Orange_Potion; + sellitem Yellow_Potion; + sellitem White_Potion; + sellitem Green_Potion; + sellitem Center_Potion; + sellitem Awakening_Potion; + sellitem Wing_Of_Fly; + sellitem Wing_Of_Butterfly; + sellitem Booby_Trap; +} + // Ninja Shops -que_ng,72,31,2 shop Boonji#nin 4_M_01,13250:-1,13251:-1,13252:-1,13253:-1,13254:-1 -que_ng,73,26,5 shop Boonray#nin 4_M_01,2117:-1,7521:-1,7522:-1,7523:-1,7524:-1 +que_ng,72,31,2 trader Boonji#nin 4_M_01,{ +OnInit: + sellitem Shuriken; + sellitem Nimbus_Shuriken; + sellitem Flash_Shuriken; + sellitem Sharp_Leaf_Shuriken; + sellitem Thorn_Needle_Shuriken; +} + +que_ng,73,26,5 trader Boonray#nin 4_M_01,{ +OnInit: + sellitem Arm_Guard; + sellitem Flame_Stone; + sellitem Ice_Stone; + sellitem Wind_Stone; + sellitem Shadow_Orb; +} + //======================================================= // Ayothaya //======================================================= -ayo_in01,18,182,1 shop Tool Dealer#ayo 4_F_THAISHAMAN,1750:-1,1770:-1,611:-1,501:-1,502:-1,503:-1,504:-1,506:-1,645:-1,656:-1,601:-1,602:-1,1065:-1 -ayo_in01,90,192,3 shop Weapon Dealer#ayo 4_M_THAIONGBAK,1207:-1,1216:-1,1107:-1,1122:-1,1116:-1,1154:-1,1407:-1,1457:-1,1354:-1,1519:-1 -ayo_in01,90,160,1 shop Armor Dealer#ayo 4_M_THAIOLD,2211:-1,2401:-1,2403:-1,2501:-1,2503:-1,2101:-1,2103:-1,2305:-1,2321:-1,2332:-1,2328:-1,2627:-1 +ayo_in01,18,182,1 trader Tool Dealer#ayo 4_F_THAISHAMAN,{ +OnInit: + sellitem Arrow; + sellitem Iron_Arrow; + sellitem Spectacles; + sellitem Red_Potion; + sellitem Orange_Potion; + sellitem Yellow_Potion; + sellitem White_Potion; + sellitem Green_Potion; + sellitem Center_Potion; + sellitem Awakening_Potion; + sellitem Wing_Of_Fly; + sellitem Wing_Of_Butterfly; + sellitem Booby_Trap; +} + +ayo_in01,90,192,3 trader Weapon Dealer#ayo 4_M_THAIONGBAK,{ +OnInit: + sellitem Main_Gauche; + sellitem Stiletto; + sellitem Blade; + sellitem Ring_Pommel_Saber; + sellitem Katana; + sellitem Bastard_Sword; + sellitem Pike; + sellitem Partizan; + sellitem Hammer; + sellitem Chain; +} + +ayo_in01,90,160,1 trader Armor Dealer#ayo 4_M_THAIOLD,{ +OnInit: + sellitem Bandana; + sellitem Sandals; + sellitem Shoes; + sellitem Hood; + sellitem Muffler; + sellitem Guard; + sellitem Buckler; + sellitem Adventure_Suit; + sellitem Silk_Robe; + sellitem Silver_Robe; + sellitem Wooden_Mail; + sellitem Belt; +} + //======================================================= // Brasilis //======================================================= -brasilis,252,257,3 shop Tool Dealer#bra 4_F_BRZ_WOMAN,645:-1,656:-1,601:-1,602:-1,611:-1,1065:-1,610:-1 -brasilis,244,243,3 shop Weapon Dealer#bra 4_M_BRZ_MAN2,1407:-1,1457:-1,1354:-1,1519:-1,13003:-1 -brasilis,201,309,3 shop Pet Groomer#bra 4_M_BRZ_MAN1,537:-1,643:-1 -brasilis,221,128,3 shop Fruit Gardener#bra 4_M_BRZ_MAN2,11515:-1,513:-1,11516:-1 +brasilis,252,257,3 trader Tool Dealer#bra 4_F_BRZ_WOMAN,{ +OnInit: + sellitem Center_Potion; + sellitem Awakening_Potion; + sellitem Wing_Of_Fly; + sellitem Wing_Of_Butterfly; + sellitem Spectacles; + sellitem Booby_Trap; + sellitem Leaf_Of_Yggdrasil; +} + +brasilis,244,243,3 trader Weapon Dealer#bra 4_M_BRZ_MAN2,{ +OnInit: + sellitem Pike; + sellitem Partizan; + sellitem Hammer; + sellitem Chain; + sellitem Coward; +} + +brasilis,201,309,3 trader Pet Groomer#bra 4_M_BRZ_MAN1,{ +OnInit: + sellitem Pet_Food; + sellitem Pet_Incubator; +} + +brasilis,221,128,3 trader Fruit Gardener#bra 4_M_BRZ_MAN2,{ +OnInit: + sellitem Coconut; + sellitem Banana; + sellitem Asai_Fruit; +} + //======================================================= // Comodo //======================================================= -cmd_in01,117,165,4 shop Armor Dealer#cmd 4W_F_01,2226:-1,2228:-1,2103:-1,2105:-1,2405:-1,2503:-1,2505:-1,2305:-1,2321:-1,2307:-1,2309:-1,2335:-1,2312:-1,2314:-1,2316:-1 -cmd_in01,128,165,2 shop Weapon Dealer#cmd 1_M_03,1901:-1,1903:-1,1905:-1,1909:-1,1911:-1,1907:-1,1950:-1,1952:-1,1954:-1,1958:-1,1960:-1,1956:-1 -cmd_in01,79,182,5 shop Tool Dealer#cmd 4_M_01,1770:-1,501:-1,502:-1,503:-1,504:-1,645:-1,656:-1,657:-1,601:-1,602:-1,611:-1,1065:-1 -comodo,296,125,4 shop Souvenir Vendor#cmd 4W_F_01,965:-1,964:-1 -cmd_fild07,257,126,5 shop Tool Dealer#cmd2 4_M_01,1770:-1,501:-1,502:-1,503:-1,504:-1,645:-1,656:-1,601:-1,602:-1,611:-1,1065:-1 -cmd_fild07,250,98,2 shop Weapon Dealer#cmd2 1_M_03,1401:-1,1404:-1,1407:-1,1451:-1,1454:-1,1457:-1,1460:-1,1463:-1,1410:-1 -cmd_fild07,277,85,4 shop Armor Dealer#cmd2 4W_F_01,2226:-1,2228:-1,2103:-1,2105:-1,2405:-1,2503:-1,2505:-1,2305:-1,2321:-1,2307:-1,2309:-1,2335:-1,2312:-1,2314:-1,2316:-1 +cmd_in01,117,165,4 trader Armor Dealer#cmd 4W_F_01,{ +OnInit: + sellitem Cap; + sellitem Helm; + sellitem Buckler; + sellitem Shield; + sellitem Boots; + sellitem Muffler; + sellitem Manteau; + sellitem Adventure_Suit; + sellitem Silk_Robe; + sellitem Mantle; + sellitem Coat; + sellitem Thief_Clothes; + sellitem Padded_Armor; + sellitem Chain_Mail; + sellitem Plate_Armor; +} + +cmd_in01,128,165,2 trader Weapon Dealer#cmd 1_M_03,{ +OnInit: + sellitem Violin; + sellitem Mandolin; + sellitem Lute; + sellitem Harp; + sellitem Guh_Moon_Goh; + sellitem Guitar; + sellitem Rope; + sellitem Line; + sellitem Wire; + sellitem Tail; + sellitem Whip; + sellitem Rante; +} + +cmd_in01,79,182,5 trader Tool Dealer#cmd 4_M_01,{ +OnInit: + sellitem Iron_Arrow; + sellitem Red_Potion; + sellitem Orange_Potion; + sellitem Yellow_Potion; + sellitem White_Potion; + sellitem Center_Potion; + sellitem Awakening_Potion; + sellitem Berserk_Potion; + sellitem Wing_Of_Fly; + sellitem Wing_Of_Butterfly; + sellitem Spectacles; + sellitem Booby_Trap; +} + +comodo,296,125,4 trader Souvenir Vendor#cmd 4W_F_01,{ +OnInit: + sellitem Clam_Shell; + sellitem Crap_Shell; +} + +cmd_fild07,257,126,5 trader Tool Dealer#cmd2 4_M_01,{ +OnInit: + sellitem Iron_Arrow; + sellitem Red_Potion; + sellitem Orange_Potion; + sellitem Yellow_Potion; + sellitem White_Potion; + sellitem Center_Potion; + sellitem Awakening_Potion; + sellitem Wing_Of_Fly; + sellitem Wing_Of_Butterfly; + sellitem Spectacles; + sellitem Booby_Trap; +} + +cmd_fild07,250,98,2 trader Weapon Dealer#cmd2 1_M_03,{ +OnInit: + sellitem Javelin; + sellitem Spear; + sellitem Pike; + sellitem Guisarme; + sellitem Glaive; + sellitem Partizan; + sellitem Trident; + sellitem Halberd; + sellitem Lance; +} + +cmd_fild07,277,85,4 trader Armor Dealer#cmd2 4W_F_01,{ +OnInit: + sellitem Cap; + sellitem Helm; + sellitem Buckler; + sellitem Shield; + sellitem Boots; + sellitem Muffler; + sellitem Manteau; + sellitem Adventure_Suit; + sellitem Silk_Robe; + sellitem Mantle; + sellitem Coat; + sellitem Thief_Clothes; + sellitem Padded_Armor; + sellitem Chain_Mail; + sellitem Plate_Armor; +} + //======================================================= // Einbroch //======================================================= -ein_in01,106,27,4 shop One Hand Weapon Dealer 4_F_EINWOMAN,1101:-1,1104:-1,1107:-1,1110:-1,1113:-1,1119:-1,1122:-1,1123:-1,1126:-1,1129:-1,1201:-1,1204:-1,1207:-1,1210:-1,1213:-1,1216:-1,1219:-1,1222:-1,1301:-1,1401:-1,1404:-1,1407:-1,1501:-1,1504:-1,1507:-1,1510:-1,1513:-1,1516:-1,1519:-1,1522:-1,1801:-1,1803:-1,1805:-1,1807:-1,1809:-1,1811:-1 -ein_in01,109,27,4 shop Two Hand Weapon Dealer 4_F_EINWOMAN,1116:-1,1151:-1,1154:-1,1157:-1,1160:-1,1351:-1,1354:-1,1357:-1,1360:-1,1410:-1,1451:-1,1454:-1,1457:-1,1460:-1,1463:-1,1250:-1,1252:-1,1254:-1 -ein_in01,119,26,4 shop Weapon Dealer#ein 4_M_EINMAN,1247:-1,1248:-1,1249:-1,13000:-1 -ein_in01,189,15,1 shop Tool Dealer#ein 4_F_EINWOMAN,1750:-1,1752:-1,1751:-1,611:-1,501:-1,502:-1,503:-1,504:-1,506:-1,645:-1,656:-1,601:-1,602:-1,1065:-1 -einbroch,138,66,4 shop Flu Mask Dealer#ein 4_F_EINWOMAN,5114:-1,2218:-1 -einbroch,82,199,4 shop Paddler#ein 4_M_EINMAN,512:-1,645:-1,1750:-1,501:-1 +ein_in01,106,27,4 trader One Hand Weapon Dealer 4_F_EINWOMAN,{ +OnInit: + sellitem Sword; + sellitem Falchion; + sellitem Blade; + sellitem Lapier; + sellitem Scimiter; + sellitem Tsurugi; + sellitem Ring_Pommel_Saber; + sellitem Haedonggum; + sellitem Saber; + sellitem Flamberge; + sellitem Knife; + sellitem Cutter; + sellitem Main_Gauche; + sellitem Dirk; + sellitem Dagger; + sellitem Stiletto; + sellitem Gladius; + sellitem Damascus; + sellitem Axe; + sellitem Javelin; + sellitem Spear; + sellitem Pike; + sellitem Club; + sellitem Mace; + sellitem Smasher; + sellitem Flail; + sellitem Morning_Star; + sellitem Sword_Mace; + sellitem Chain; + sellitem Stunner; + sellitem Waghnakh; + sellitem Knuckle_Duster; + sellitem Hora; + sellitem Fist; + sellitem Claw; + sellitem Finger; +} + +ein_in01,109,27,4 trader Two Hand Weapon Dealer 4_F_EINWOMAN,{ +OnInit: + sellitem Katana; + sellitem Slayer; + sellitem Bastard_Sword; + sellitem Two_Hand_Sword; + sellitem Broad_Sword; + sellitem Battle_Axe; + sellitem Hammer; + sellitem Buster; + sellitem Two_Handed_Axe; + sellitem Lance; + sellitem Guisarme; + sellitem Glaive; + sellitem Partizan; + sellitem Trident; + sellitem Halberd; + sellitem Jur; + sellitem Katar; + sellitem Jamadhar; +} + +ein_in01,119,26,4 trader Weapon Dealer#ein 4_M_EINMAN,{ +OnInit: + sellitem Kindling_Dagger; + sellitem Obsidian_Dagger; + sellitem Fisherman's_Dagger; + sellitem Jujube_Dagger; +} + +ein_in01,189,15,1 trader Tool Dealer#ein 4_F_EINWOMAN,{ +OnInit: + sellitem Arrow; + sellitem Fire_Arrow; + sellitem Silver_Arrow; + sellitem Spectacles; + sellitem Red_Potion; + sellitem Orange_Potion; + sellitem Yellow_Potion; + sellitem White_Potion; + sellitem Green_Potion; + sellitem Center_Potion; + sellitem Awakening_Potion; + sellitem Wing_Of_Fly; + sellitem Wing_Of_Butterfly; + sellitem Booby_Trap; +} + +einbroch,138,66,4 trader Flu Mask Dealer#ein 4_F_EINWOMAN,{ +OnInit: + sellitem Fedora; + sellitem Flu_Mask; +} + +einbroch,82,199,4 trader Paddler#ein 4_M_EINMAN,{ +OnInit: + sellitem Apple; + sellitem Center_Potion; + sellitem Arrow; + sellitem Red_Potion; +} + //Official Gunslingers shops. -que_ng,179,91,3 shop Chivas Lugal 4_M_HUMERCHANT,13150:-1,13102:-1,13151:-1,13154:-1,13155:-1,13163:-1,13165:-1,13168:-1 -que_ng,180,79,3 shop Johnny Waiker 4_M_HUMERCHANT,13200:-1,13201:-1,13202:-1 +que_ng,179,91,3 trader Chivas Lugal 4_M_HUMERCHANT,{ +OnInit: + sellitem Branch; + sellitem Crimson_Bolt; + sellitem The_Cyclone; + sellitem Rolling_Stone; + sellitem Black_Rose; + sellitem Long_Barrel; + sellitem Jungle_Carbine; + sellitem Thunder_P; +} + +que_ng,180,79,3 trader Johnny Waiker 4_M_HUMERCHANT,{ +OnInit: + sellitem Bullet; + sellitem Silver_Bullet; + sellitem Shell_Of_Blood; +} + //======================================================= // Geffen //======================================================= -geffen_in,26,178,4 shop Armor Dealer#gef 1_F_01,2628:-1,2101:-1,2107:-1,2401:-1,2501:-1,2230:-1,2301:-1,2303:-1,2305:-1,2321:-1,2332:-1 -geffen_in,30,178,4 shop Weapon Dealer#gef2 1_M_01,1750:-1,1751:-1,1101:-1,1701:-1,1201:-1,1204:-1,1207:-1,1210:-1,1213:-1,1216:-1,1601:-1,1604:-1,1607:-1,1610:-1 -geffen_in,22,171,7 shop Weapon Dealer#gef 4_M_02,1146:-1,1245:-1 -geffen_in,74,144,0 shop Trader#gef 1_F_01,911:-1,910:-1,912:-1 -geffen_in,77,167,0 shop Tool Dealer#gef 1_F_03,1750:-1,611:-1,501:-1,502:-1,503:-1,504:-1,506:-1,645:-1,656:-1,601:-1,602:-1,2241:-1 -geffen_in,77,173,0 shop Magical Item Seller#gef 1_M_WIZARD,717:-1,1601:-1,1604:-1,1607:-1,1610:-1,2232:-1,2321:-1,2332:-1 -geffen_in,171,123,4 shop Tool Dealer#gef2 1_M_WIZARD,1092:-1,1093:-1 -geffen,193,152,4 shop Pet Groomer#gef 4_F_TELEPORTER,537:-1,643:-1,10013:-1,10014:-1,554:-1,6113:-1,6114:-1,6115:-1 +geffen_in,26,178,4 trader Armor Dealer#gef 1_F_01,{ +OnInit: + sellitem Novice_Armlet; + sellitem Guard; + sellitem Mirror_Shield; + sellitem Sandals; + sellitem Hood; + sellitem Gemmed_Sallet; + sellitem Cotton_Shirt; + sellitem Leather_Jacket; + sellitem Adventure_Suit; + sellitem Silk_Robe; + sellitem Silver_Robe; +} + +geffen_in,30,178,4 trader Weapon Dealer#gef2 1_M_01,{ +OnInit: + sellitem Arrow; + sellitem Silver_Arrow; + sellitem Sword; + sellitem Bow; + sellitem Knife; + sellitem Cutter; + sellitem Main_Gauche; + sellitem Dirk; + sellitem Dagger; + sellitem Stiletto; + sellitem Rod; + sellitem Wand; + sellitem Staff; + sellitem Arc_Wand; +} + +geffen_in,22,171,7 trader Weapon Dealer#gef 4_M_02,{ +OnInit: + sellitem Town_Sword; + sellitem Cinquedea; +} + +geffen_in,74,144,0 trader Trader#gef 1_F_01,{ +OnInit: + sellitem Scell; + sellitem Garlet; + sellitem Zargon; +} + +geffen_in,77,167,0 trader Tool Dealer#gef 1_F_03,{ +OnInit: + sellitem Arrow; + sellitem Spectacles; + sellitem Red_Potion; + sellitem Orange_Potion; + sellitem Yellow_Potion; + sellitem White_Potion; + sellitem Green_Potion; + sellitem Center_Potion; + sellitem Awakening_Potion; + sellitem Wing_Of_Fly; + sellitem Wing_Of_Butterfly; + sellitem Granpa_Beard; +} + +geffen_in,77,173,0 trader Magical Item Seller#gef 1_M_WIZARD,{ +OnInit: + sellitem Blue_Gemstone; + sellitem Rod; + sellitem Wand; + sellitem Staff; + sellitem Arc_Wand; + sellitem Circlet; + sellitem Silk_Robe; + sellitem Silver_Robe; +} + +geffen_in,171,123,4 trader Tool Dealer#gef2 1_M_WIZARD,{ +OnInit: + sellitem Empty_Cylinder; + sellitem Empty_Potion; +} + +geffen,193,152,4 trader Pet Groomer#gef 4_F_TELEPORTER,{ +OnInit: + sellitem Pet_Food; + sellitem Pet_Incubator; + sellitem Backpack; + sellitem Rocker_Glasses; + sellitem Mojji; + sellitem Vital_Flower_; + sellitem Flame_Gemstone; + sellitem Bun_; +} + //======================================================= // Gonryun //======================================================= -gonryun,147,84,5 shop Tool Dealer#gon 4_M_TWOLDMAN,1750:-1,1770:-1,611:-1,501:-1,502:-1,503:-1,504:-1,506:-1,645:-1,656:-1,601:-1,602:-1,1065:-1 -gonryun,174,101,3 shop Weapon Dealer#gon 4_M_TWBOY,1207:-1,1216:-1,1107:-1,1122:-1,1116:-1,1154:-1,1407:-1,1457:-1,1354:-1,1519:-1 -gonryun,173,84,3 shop Armor Dealer#gon 4_F_TWGIRL,2211:-1,2401:-1,2403:-1,2501:-1,2503:-1,2101:-1,2103:-1,2305:-1,2321:-1,2332:-1,2328:-1,2627:-1 +gonryun,147,84,5 trader Tool Dealer#gon 4_M_TWOLDMAN,{ +OnInit: + sellitem Arrow; + sellitem Iron_Arrow; + sellitem Spectacles; + sellitem Red_Potion; + sellitem Orange_Potion; + sellitem Yellow_Potion; + sellitem White_Potion; + sellitem Green_Potion; + sellitem Center_Potion; + sellitem Awakening_Potion; + sellitem Wing_Of_Fly; + sellitem Wing_Of_Butterfly; + sellitem Booby_Trap; +} + +gonryun,174,101,3 trader Weapon Dealer#gon 4_M_TWBOY,{ +OnInit: + sellitem Main_Gauche; + sellitem Stiletto; + sellitem Blade; + sellitem Ring_Pommel_Saber; + sellitem Katana; + sellitem Bastard_Sword; + sellitem Pike; + sellitem Partizan; + sellitem Hammer; + sellitem Chain; +} + +gonryun,173,84,3 trader Armor Dealer#gon 4_F_TWGIRL,{ +OnInit: + sellitem Bandana; + sellitem Sandals; + sellitem Shoes; + sellitem Hood; + sellitem Muffler; + sellitem Guard; + sellitem Buckler; + sellitem Adventure_Suit; + sellitem Silk_Robe; + sellitem Silver_Robe; + sellitem Wooden_Mail; + sellitem Belt; +} + //======================================================= // Hugel //======================================================= -hugel,105,169,5 shop Vendor from Milk Ranch#h 4_F_01,519:-1 -hugel,77,167,3 shop Vegetable Gardener#hu 4_F_HUGRANMA,522:-1,512:-1,513:-1,515:-1,516:-1,535:-1 -hu_in01,241,368,2 shop Tool Dealer#hu 1_M_INNKEEPER,1750:-1,611:-1,501:-1,502:-1,503:-1,504:-1,506:-1,645:-1,656:-1,601:-1,602:-1,1065:-1 -hu_in01,252,368,3 shop Tool Dealer#hu2 4_F_01,717:-1,2201:-1,910:-1,528:-1 -hu_in01,100,390,3 shop Bow Dealer#hu 4_M_04,1701:-1,1707:-1,1718:-1,1714:-1 -hu_in01,94,390,3 shop Weapon Dealer#hu 4_M_HUMAN_01,1116:-1,1154:-1,1354:-1,1201:-1 -hu_in01,94,313,3 shop Armor Dealer#hu 4_M_04,2224:-1,2232:-1,2226:-1,2101:-1,2103:-1,2401:-1,2501:-1,2307:-1,2105:-1 +hugel,105,169,5 trader Vendor from Milk Ranch#h 4_F_01,{ +OnInit: + sellitem Milk; +} + +hugel,77,167,3 trader Vegetable Gardener#hu 4_F_HUGRANMA,{ +OnInit: + sellitem Fruit_Of_Mastela; + sellitem Apple; + sellitem Banana; + sellitem Carrot; + sellitem Sweet_Potato; + sellitem Pumpkin; +} + +hu_in01,241,368,2 trader Tool Dealer#hu 1_M_INNKEEPER,{ +OnInit: + sellitem Arrow; + sellitem Spectacles; + sellitem Red_Potion; + sellitem Orange_Potion; + sellitem Yellow_Potion; + sellitem White_Potion; + sellitem Green_Potion; + sellitem Center_Potion; + sellitem Awakening_Potion; + sellitem Wing_Of_Fly; + sellitem Wing_Of_Butterfly; + sellitem Booby_Trap; +} + +hu_in01,252,368,3 trader Tool Dealer#hu2 4_F_01,{ +OnInit: + sellitem Blue_Gemstone; + sellitem Sunglasses; + sellitem Garlet; + sellitem Monster's_Feed; +} + +hu_in01,100,390,3 trader Bow Dealer#hu 4_M_04,{ +OnInit: + sellitem Bow; + sellitem Great_Bow; + sellitem Hunter_Bow; + sellitem Kakkung; +} + +hu_in01,94,390,3 trader Weapon Dealer#hu 4_M_HUMAN_01,{ +OnInit: + sellitem Katana; + sellitem Bastard_Sword; + sellitem Hammer; + sellitem Knife; +} + +hu_in01,94,313,3 trader Armor Dealer#hu 4_M_04,{ +OnInit: + sellitem Goggle; + sellitem Circlet; + sellitem Cap; + sellitem Guard; + sellitem Buckler; + sellitem Sandals; + sellitem Hood; + sellitem Mantle; + sellitem Shield; +} + //======================================================= // Izlude //======================================================= -izlude_in,60,127,4 shop Weapon Dealer#iz 1_F_MARIA,1750:-1,1751:-1,1701:-1,1601:-1,1201:-1,1204:-1,1207:-1,1101:-1,1104:-1,1107:-1,1116:-1,1151:-1,1154:-1,1157:-1,1160:-1,1301:-1 -izlude_in,70,127,4 shop Armor Dealer#iz 1_M_SIZ,2103:-1,2105:-1,2403:-1,2405:-1,2503:-1,2505:-1,2226:-1,2228:-1,2303:-1,2305:-1,2328:-1,2307:-1,2309:-1,2312:-1,2314:-1,2316:-1,2628:-1 +izlude_in,60,127,4 trader Weapon Dealer#iz 1_F_MARIA,{ +OnInit: + sellitem Arrow; + sellitem Silver_Arrow; + sellitem Bow; + sellitem Rod; + sellitem Knife; + sellitem Cutter; + sellitem Main_Gauche; + sellitem Sword; + sellitem Falchion; + sellitem Blade; + sellitem Katana; + sellitem Slayer; + sellitem Bastard_Sword; + sellitem Two_Hand_Sword; + sellitem Broad_Sword; + sellitem Axe; +} + +izlude_in,70,127,4 trader Armor Dealer#iz 1_M_SIZ,{ +OnInit: + sellitem Buckler; + sellitem Shield; + sellitem Shoes; + sellitem Boots; + sellitem Muffler; + sellitem Manteau; + sellitem Cap; + sellitem Helm; + sellitem Leather_Jacket; + sellitem Adventure_Suit; + sellitem Wooden_Mail; + sellitem Mantle; + sellitem Coat; + sellitem Padded_Armor; + sellitem Chain_Mail; + sellitem Plate_Armor; + sellitem Novice_Armlet; +} + //======================================================= // Jawaii //======================================================= -jawaii,186,174,3 shop Ice Cream Guy#ja 4_M_03,536:-1,536:-1,536:-1,536:-1,536:-1,536:-1,536:-1 +jawaii,186,174,3 trader Ice Cream Guy#ja 4_M_03,{ +OnInit: + sellitem Ice_Cream; + sellitem Ice_Cream; + sellitem Ice_Cream; + sellitem Ice_Cream; + sellitem Ice_Cream; + sellitem Ice_Cream; + sellitem Ice_Cream; +} + //======================================================= // Juno //======================================================= -yuno,218,97,5 shop Tool Dealer#yuno 4_M_02,1750:-1,611:-1,501:-1,502:-1,503:-1,504:-1,506:-1,645:-1,656:-1,601:-1,602:-1 -yuno,226,107,5 shop Tool Dealer#yuno1 4_M_01,911:-1,910:-1,912:-1 -yuno,197,114,4 shop Pet Groomer#yuno 4_F_TELEPORTER,537:-1,643:-1,10013:-1,10014:-1,6115:-1,554:-1,6114:-1,6113:-1,6110:-1,6115:-1,6100:-1,6098:-1,6112:-1,6104:-1,6108:-1,6111:-1,6095:-1,6099:-1,6096:-1,6097:-1 -yuno,205,103,4 shop Mr. King's Shop#yuno 4_M_TELEPORTER,2340:-1,2341:-1,2411:-1,2222:-1,2230:-1,1721:-1 -yuno,163,187,5 shop Magical Item Seller#yuno 4_F_01,717:-1,1601:-1,1604:-1,1607:-1,1610:-1,2232:-1,2321:-1,2332:-1 -yuno_in01,25,34,5 shop Tool Dealer#yuno2 4_M_01,1750:-1,611:-1,501:-1,502:-1,503:-1,504:-1,506:-1,645:-1,656:-1,601:-1,602:-1 -yuno_in01,103,35,2 shop Weapon Dealer#yuno 1_M_03,1750:-1,1751:-1,1101:-1,1701:-1,1201:-1,1204:-1,1207:-1,1210:-1,1213:-1,1216:-1,1601:-1,1604:-1,1607:-1,1610:-1 -yuno_in01,112,26,4 shop Armor Dealer#yuno 4W_F_01,2628:-1,2101:-1,2107:-1,2401:-1,2501:-1,2230:-1,2301:-1,2303:-1,2305:-1,2321:-1,2332:-1 -yuno_in03,176,22,3 shop Scroll Merchant#yuno03 4_M_ORIENT02,7433:-1 //Temp shop in Yuno that sells Blank Scrolls +yuno,218,97,5 trader Tool Dealer#yuno 4_M_02,{ +OnInit: + sellitem Arrow; + sellitem Spectacles; + sellitem Red_Potion; + sellitem Orange_Potion; + sellitem Yellow_Potion; + sellitem White_Potion; + sellitem Green_Potion; + sellitem Center_Potion; + sellitem Awakening_Potion; + sellitem Wing_Of_Fly; + sellitem Wing_Of_Butterfly; +} + +yuno,226,107,5 trader Tool Dealer#yuno1 4_M_01,{ +OnInit: + sellitem Scell; + sellitem Garlet; + sellitem Zargon; +} + +yuno,197,114,4 trader Pet Groomer#yuno 4_F_TELEPORTER,{ +OnInit: + sellitem Pet_Food; + sellitem Pet_Incubator; + sellitem Backpack; + sellitem Rocker_Glasses; + sellitem Bun_; + sellitem Mojji; + sellitem Flame_Gemstone; + sellitem Vital_Flower_; + sellitem Vital_Flower; + sellitem Bun_; + sellitem Damp_Darkness; + sellitem Small_Snow_Flower; + sellitem Fresh_Plant; + sellitem Big_Cell; + sellitem Apple_Pudding; + sellitem Mystic_Stone; + sellitem Flavored_Alcohol; + sellitem Grilled_Rice_Cake; + sellitem Fish_With_Blue_Back; + sellitem Pumpkin_Pie_; +} + +yuno,205,103,4 trader Mr. King's Shop#yuno 4_M_TELEPORTER,{ +OnInit: + sellitem Novice_Breast; + sellitem Full_Plate_Armor; + sellitem Grave; + sellitem Turban; + sellitem Gemmed_Sallet; + sellitem Repeting_CrossBow; +} + +yuno,163,187,5 trader Magical Item Seller#yuno 4_F_01,{ +OnInit: + sellitem Blue_Gemstone; + sellitem Rod; + sellitem Wand; + sellitem Staff; + sellitem Arc_Wand; + sellitem Circlet; + sellitem Silk_Robe; + sellitem Silver_Robe; +} + +yuno_in01,25,34,5 trader Tool Dealer#yuno2 4_M_01,{ +OnInit: + sellitem Arrow; + sellitem Spectacles; + sellitem Red_Potion; + sellitem Orange_Potion; + sellitem Yellow_Potion; + sellitem White_Potion; + sellitem Green_Potion; + sellitem Center_Potion; + sellitem Awakening_Potion; + sellitem Wing_Of_Fly; + sellitem Wing_Of_Butterfly; +} + +yuno_in01,103,35,2 trader Weapon Dealer#yuno 1_M_03,{ +OnInit: + sellitem Arrow; + sellitem Silver_Arrow; + sellitem Sword; + sellitem Bow; + sellitem Knife; + sellitem Cutter; + sellitem Main_Gauche; + sellitem Dirk; + sellitem Dagger; + sellitem Stiletto; + sellitem Rod; + sellitem Wand; + sellitem Staff; + sellitem Arc_Wand; +} + +yuno_in01,112,26,4 trader Armor Dealer#yuno 4W_F_01,{ +OnInit: + sellitem Novice_Armlet; + sellitem Guard; + sellitem Mirror_Shield; + sellitem Sandals; + sellitem Hood; + sellitem Gemmed_Sallet; + sellitem Cotton_Shirt; + sellitem Leather_Jacket; + sellitem Adventure_Suit; + sellitem Silk_Robe; + sellitem Silver_Robe; +} + +yuno_in03,176,22,3 trader Scroll Merchant#yuno03 4_M_ORIENT02,{ +OnInit: + sellitem Scroll; //Temp shop in Yuno that sells Blank Scrolls +} + //======================================================= // Lighthalzen //======================================================= -lighthalzen,69,75,5 shop Fruit Gardener#lhz 8_F,512:-1,513:-1 -lighthalzen,112,44,0 shop Flower Girl#lhz 4_F_01,712:-1,744:-1,748:-1 -lighthalzen,124,129,0 shop Vegetable Gardener#lhz 4_F_02,515:-1,516:-1,535:-1 -lighthalzen,220,122,3 shop Vendor from Milk Ranch#l 4_F_01,519:-1 -lighthalzen,222,191,4 shop Pet Groomer#lhz 4_M_TELEPORTER,537:-1,643:-1,10013:-1,10014:-1,554:-1,6113:-1,6114:-1,6115:-1 -lhz_in02,286,95,4 shop Beginner's Merchant#lhz 1_M_SIZ,5112:-1,2416:-1,2113:-1,2512:-1 -lhz_in02,271,99,5 shop Armor Dealer#lhz 4_M_REPAIR,2101:-1,2103:-1,2403:-1,2405:-1,2503:-1,2321:-1,2314:-1,2309:-1,2335:-1,2628:-1 -lhz_in02,276,99,4 shop Weapon Dealer#lhz 4_M_REPAIR,1201:-1,1207:-1,1216:-1,1107:-1,1122:-1,1116:-1,1154:-1,1407:-1,1457:-1,1354:-1,1519:-1,13003:-1 -lhz_in02,273,35,4 shop Wand Dealer#lhz 4_M_EINMAN2,1601:-1,1604:-1,1607:-1,1617:-1,1619:-1 -lhz_in02,105,21,3 shop Jeweler#lhz 4_F_02,721:-1,723:-1,726:-1,728:-1,729:-1,730:-1,2613:-1 -lhz_in02,17,220,5 shop Vegetable Gardener#lhz2 4_F_02,515:-1,516:-1,535:-1 -lhz_in02,21,220,5 shop Fruit Gardener#lhz2 8_F,512:-1,513:-1 -lhz_in02,32,219,5 shop Butcher#lhz 1_M_JOBGUIDER,517:-1 -lhz_in02,38,145,5 shop Gift Merchant#lhz 4_F_02,734:-1,735:-1,736:-1,737:-1,746:-1 -lhz_in02,47,148,3 shop Wedding Shop Dealer#lhz 1_F_LIBRARYGIRL,744:-1,745:-1,2338:-1,2206:-1,7170:-1 -lhz_in02,31,145,4 shop Tool Dealer#lhz 4_F_01,611:-1,503:-1,504:-1,506:-1,657:-1,656:-1,601:-1,602:-1,1065:-1,610:-1,1770:-1 -lhz_in02,85,216,5 shop Doll Supplier#lhz 4_F_LGTGIRL,740:-1,741:-1,742:-1 -lhz_in02,87,208,3 shop Toy Supplier#lhz 4_M_PIERROT,2243:-1,2212:-1,2242:-1,2241:-1 -lhz_in03,239,106,5 shop Tool Dealer#lhz2 4_F_EINWOMAN,501:-1,502:-1,506:-1,645:-1,656:-1,601:-1,602:-1,1065:-1,611:-1 -lhz_in03,258,101,3 shop Arrow Merchant#lhz 4_M_EINMAN,1750:-1,1770:-1,1752:-1,1751:-1 -lhz_in03,249,24,4 shop Merchant#lhz 4_M_EINMAN,911:-1,910:-1,912:-1,528:-1 +lighthalzen,69,75,5 trader Fruit Gardener#lhz 8_F,{ +OnInit: + sellitem Apple; + sellitem Banana; +} + +lighthalzen,112,44,0 trader Flower Girl#lhz 4_F_01,{ +OnInit: + sellitem Flower; + sellitem Bunch_Of_Flowers; + sellitem Witherless_Rose; +} + +lighthalzen,124,129,0 trader Vegetable Gardener#lhz 4_F_02,{ +OnInit: + sellitem Carrot; + sellitem Sweet_Potato; + sellitem Pumpkin; +} + +lighthalzen,220,122,3 trader Vendor from Milk Ranch#l 4_F_01,{ +OnInit: + sellitem Milk; +} + +lighthalzen,222,191,4 trader Pet Groomer#lhz 4_M_TELEPORTER,{ +OnInit: + sellitem Pet_Food; + sellitem Pet_Incubator; + sellitem Backpack; + sellitem Rocker_Glasses; + sellitem Mojji; + sellitem Vital_Flower_; + sellitem Flame_Gemstone; + sellitem Bun_; +} + +lhz_in02,286,95,4 trader Beginner's Merchant#lhz 1_M_SIZ,{ +OnInit: + sellitem Super_Novice_Hat; + sellitem Novice_Shoes; + sellitem Novice_Shield; + sellitem Novice_Manteau; +} + +lhz_in02,271,99,5 trader Armor Dealer#lhz 4_M_REPAIR,{ +OnInit: + sellitem Guard; + sellitem Buckler; + sellitem Shoes; + sellitem Boots; + sellitem Muffler; + sellitem Silk_Robe; + sellitem Chain_Mail; + sellitem Coat; + sellitem Thief_Clothes; + sellitem Novice_Armlet; +} + +lhz_in02,276,99,4 trader Weapon Dealer#lhz 4_M_REPAIR,{ +OnInit: + sellitem Knife; + sellitem Main_Gauche; + sellitem Stiletto; + sellitem Blade; + sellitem Ring_Pommel_Saber; + sellitem Katana; + sellitem Bastard_Sword; + sellitem Pike; + sellitem Partizan; + sellitem Hammer; + sellitem Chain; + sellitem Coward; +} + +lhz_in02,273,35,4 trader Wand Dealer#lhz 4_M_EINMAN2,{ +OnInit: + sellitem Rod; + sellitem Wand; + sellitem Staff; + sellitem Survival_Rod; + sellitem Survival_Rod2; +} + +lhz_in02,105,21,3 trader Jeweler#lhz 4_F_02,{ +OnInit: + sellitem Azure_Jewel; + sellitem Cardinal_Jewel; + sellitem Blue_Jewel; + sellitem Golden_Jewel; + sellitem Bluish_Green_Jewel; + sellitem Crystal_Jewel; + sellitem Diamond_Ring; +} + +lhz_in02,17,220,5 trader Vegetable Gardener#lhz2 4_F_02,{ +OnInit: + sellitem Carrot; + sellitem Sweet_Potato; + sellitem Pumpkin; +} + +lhz_in02,21,220,5 trader Fruit Gardener#lhz2 8_F,{ +OnInit: + sellitem Apple; + sellitem Banana; +} + +lhz_in02,32,219,5 trader Butcher#lhz 1_M_JOBGUIDER,{ +OnInit: + sellitem Meat; +} + +lhz_in02,38,145,5 trader Gift Merchant#lhz 4_F_02,{ +OnInit: + sellitem Red_Frame; + sellitem Blue_Porcelain; + sellitem White_Platter; + sellitem Black_Ladle; + sellitem Glass_Bead; +} + +lhz_in02,47,148,3 trader Wedding Shop Dealer#lhz 1_F_LIBRARYGIRL,{ +OnInit: + sellitem Bunch_Of_Flowers; + sellitem Wedding_Bouquet; + sellitem Wedding_Dress; + sellitem Wedding_Veil; + sellitem Tuxedo; +} + +lhz_in02,31,145,4 trader Tool Dealer#lhz 4_F_01,{ +OnInit: + sellitem Spectacles; + sellitem Yellow_Potion; + sellitem White_Potion; + sellitem Green_Potion; + sellitem Berserk_Potion; + sellitem Awakening_Potion; + sellitem Wing_Of_Fly; + sellitem Wing_Of_Butterfly; + sellitem Booby_Trap; + sellitem Leaf_Of_Yggdrasil; + sellitem Iron_Arrow; +} + +lhz_in02,85,216,5 trader Doll Supplier#lhz 4_F_LGTGIRL,{ +OnInit: + sellitem Stuffed_Doll; + sellitem Poring_Doll; + sellitem Chonchon_Doll; +} + +lhz_in02,87,208,3 trader Toy Supplier#lhz 4_M_PIERROT,{ +OnInit: + sellitem Spinning_Eyes; + sellitem Eye_Bandage; + sellitem Luxury_Sunglasses; + sellitem Granpa_Beard; +} + +lhz_in03,239,106,5 trader Tool Dealer#lhz2 4_F_EINWOMAN,{ +OnInit: + sellitem Red_Potion; + sellitem Orange_Potion; + sellitem Green_Potion; + sellitem Center_Potion; + sellitem Awakening_Potion; + sellitem Wing_Of_Fly; + sellitem Wing_Of_Butterfly; + sellitem Booby_Trap; + sellitem Spectacles; +} + +lhz_in03,258,101,3 trader Arrow Merchant#lhz 4_M_EINMAN,{ +OnInit: + sellitem Arrow; + sellitem Iron_Arrow; + sellitem Fire_Arrow; + sellitem Silver_Arrow; +} + +lhz_in03,249,24,4 trader Merchant#lhz 4_M_EINMAN,{ +OnInit: + sellitem Scell; + sellitem Garlet; + sellitem Zargon; + sellitem Monster's_Feed; +} + //======================================================= // Louyang //======================================================= -lou_in02,121,182,5 shop Armor Dealer#lou 4_F_CHNWOMAN,2211:-1,2401:-1,2403:-1,2501:-1,2503:-1,2101:-1,2103:-1,2305:-1,2321:-1,2332:-1,2328:-1,2627:-1 -lou_in02,130,182,5 shop Weapon Dealer#lou 4_M_CHNMAN,1207:-1,1216:-1,1107:-1,1122:-1,1116:-1,1154:-1,1407:-1,1457:-1,1354:-1,1519:-1 -lou_in02,239,176,5 shop Tool Dealer#lou 4_F_CHNWOMAN,1750:-1,1770:-1,611:-1,501:-1,502:-1,503:-1,504:-1,506:-1,645:-1,656:-1,601:-1,602:-1,1065:-1 +lou_in02,121,182,5 trader Armor Dealer#lou 4_F_CHNWOMAN,{ +OnInit: + sellitem Bandana; + sellitem Sandals; + sellitem Shoes; + sellitem Hood; + sellitem Muffler; + sellitem Guard; + sellitem Buckler; + sellitem Adventure_Suit; + sellitem Silk_Robe; + sellitem Silver_Robe; + sellitem Wooden_Mail; + sellitem Belt; +} + +lou_in02,130,182,5 trader Weapon Dealer#lou 4_M_CHNMAN,{ +OnInit: + sellitem Main_Gauche; + sellitem Stiletto; + sellitem Blade; + sellitem Ring_Pommel_Saber; + sellitem Katana; + sellitem Bastard_Sword; + sellitem Pike; + sellitem Partizan; + sellitem Hammer; + sellitem Chain; +} + +lou_in02,239,176,5 trader Tool Dealer#lou 4_F_CHNWOMAN,{ +OnInit: + sellitem Arrow; + sellitem Iron_Arrow; + sellitem Spectacles; + sellitem Red_Potion; + sellitem Orange_Potion; + sellitem Yellow_Potion; + sellitem White_Potion; + sellitem Green_Potion; + sellitem Center_Potion; + sellitem Awakening_Potion; + sellitem Wing_Of_Fly; + sellitem Wing_Of_Butterfly; + sellitem Booby_Trap; +} + //======================================================= // Lutie //======================================================= -xmas_in,40,38,5 shop Tool Dealer#xmas 4_M_01,501:-1,502:-1,503:-1,504:-1,506:-1,645:-1,656:-1,601:-1,602:-1,611:-1,610:-1 -xmas_in,168,104,4 shop Armor Dealer#xmas 4W_F_01,2228:-1,2103:-1,2105:-1,2307:-1,2309:-1,2312:-1,2314:-1,2316:-1,2505:-1,2405:-1 -xmas_in,169,34,2 shop Gift Seller#xmas 4_F_GON,2612:-1,744:-1,748:-1,736:-1,746:-1,740:-1,2613:-1 -xmas_in,174,98,2 shop Weapon Dealer#xmas 1_M_03,1201:-1,1204:-1,1207:-1,1210:-1,1213:-1,1216:-1,1219:-1,1222:-1 +xmas_in,40,38,5 trader Tool Dealer#xmas 4_M_01,{ +OnInit: + sellitem Red_Potion; + sellitem Orange_Potion; + sellitem Yellow_Potion; + sellitem White_Potion; + sellitem Green_Potion; + sellitem Center_Potion; + sellitem Awakening_Potion; + sellitem Wing_Of_Fly; + sellitem Wing_Of_Butterfly; + sellitem Spectacles; + sellitem Leaf_Of_Yggdrasil; +} + +xmas_in,168,104,4 trader Armor Dealer#xmas 4W_F_01,{ +OnInit: + sellitem Helm; + sellitem Buckler; + sellitem Shield; + sellitem Mantle; + sellitem Coat; + sellitem Padded_Armor; + sellitem Chain_Mail; + sellitem Plate_Armor; + sellitem Manteau; + sellitem Boots; +} + +xmas_in,169,34,2 trader Gift Seller#xmas 4_F_GON,{ +OnInit: + sellitem Flower_Ring; + sellitem Bunch_Of_Flowers; + sellitem Witherless_Rose; + sellitem White_Platter; + sellitem Glass_Bead; + sellitem Stuffed_Doll; + sellitem Diamond_Ring; +} + +xmas_in,174,98,2 trader Weapon Dealer#xmas 1_M_03,{ +OnInit: + sellitem Knife; + sellitem Cutter; + sellitem Main_Gauche; + sellitem Dirk; + sellitem Dagger; + sellitem Stiletto; + sellitem Gladius; + sellitem Damascus; +} + //======================================================= // Morroc - Post Ep. 12.1 //======================================================= -in_moc_16,22,20,7 shop Sepulchral Merchant#moc 4_M_MASKMAN,1771:-1 -moc_ruins,91,128,4 shop Tool Dealer#moc1 4_F_04,1750:-1,611:-1,501:-1,502:-1,503:-1,504:-1,506:-1,645:-1,656:-1,601:-1,602:-1,1065:-1 -moc_ruins,114,63,6 shop Tool Dealer#moc2 4W_M_03,1750:-1,611:-1,501:-1,502:-1,503:-1,504:-1,506:-1,645:-1,656:-1,601:-1,602:-1,1065:-1,2242:-1 -moc_ruins,93,53,2 shop Item Collector#moc1 4_M_03,911:-1,528:-1,919:-1,925:-1 -moc_ruins,81,113,0 shop Item Collector#moc2 4_M_03,911:-1,528:-1,919:-1,925:-1 -moc_ruins,110,105,2 shop Jeweler#moc1 8_F,721:-1,723:-1,726:-1,728:-1,729:-1 -moc_ruins,52,85,6 shop Jeweler#moc2 4W_M_03,730:-1,2613:-1 -moc_ruins,113,126,4 shop Trader#moc1 4W_M_03,747:-1 -moc_ruins,131,138,0 shop Trader#moc2 4_F_04,748:-1 -moc_ruins,71,139,5 shop Trader#moc3 4_F_04,2612:-1 -moc_ruins,125,135,6 shop Trader#moc4 4_M_ORIENT02,2609:-1,1516:-1,1522:-1 -moc_ruins,87,109,0 shop Butcher#moc 1_M_MERCHANT,517:-1 -moc_ruins,90,149,6 shop Trader#moc5 4W_M_03,513:-1,513:-1,513:-1,513:-1,513:-1,513:-1 -moc_ruins,118,170,4 shop Pet Groomer#moc 4_M_TELEPORTER,537:-1,643:-1,10013:-1,10014:-1,554:-1,6113:-1,6114:-1,6115:-1 -morocc_in,141,67,0 shop Weapon Dealer#moc1 1_M_MERCHANT,1750:-1,1751:-1,1701:-1,1601:-1,1201:-1,1204:-1,1207:-1,1210:-1,1213:-1,1216:-1,1219:-1,1222:-1,1250:-1,1252:-1,1254:-1 -morocc_in,141,60,0 shop Armor Dealer#moc 1_M_MERCHANT,2101:-1,2103:-1,2401:-1,2403:-1,2405:-1,2501:-1,2503:-1,2218:-1,2301:-1,2303:-1,2305:-1,2321:-1,2328:-1,2332:-1,2307:-1,2309:-1,2335:-1,2628:-1 -morocc_in,132,57,0 shop Weapon Dealer#moc2 4W_M_03,1146:-1,1245:-1 +in_moc_16,22,20,7 trader Sepulchral Merchant#moc 4_M_MASKMAN,{ +OnInit: + sellitem Venom_Knife; +} + +moc_ruins,91,128,4 trader Tool Dealer#moc1 4_F_04,{ +OnInit: + sellitem Arrow; + sellitem Spectacles; + sellitem Red_Potion; + sellitem Orange_Potion; + sellitem Yellow_Potion; + sellitem White_Potion; + sellitem Green_Potion; + sellitem Center_Potion; + sellitem Awakening_Potion; + sellitem Wing_Of_Fly; + sellitem Wing_Of_Butterfly; + sellitem Booby_Trap; +} + +moc_ruins,114,63,6 trader Tool Dealer#moc2 4W_M_03,{ +OnInit: + sellitem Arrow; + sellitem Spectacles; + sellitem Red_Potion; + sellitem Orange_Potion; + sellitem Yellow_Potion; + sellitem White_Potion; + sellitem Green_Potion; + sellitem Center_Potion; + sellitem Awakening_Potion; + sellitem Wing_Of_Fly; + sellitem Wing_Of_Butterfly; + sellitem Booby_Trap; + sellitem Luxury_Sunglasses; +} + +moc_ruins,93,53,2 trader Item Collector#moc1 4_M_03,{ +OnInit: + sellitem Scell; + sellitem Monster's_Feed; + sellitem Animal's_Skin; + sellitem Bill_Of_Birds; +} + +moc_ruins,81,113,0 trader Item Collector#moc2 4_M_03,{ +OnInit: + sellitem Scell; + sellitem Monster's_Feed; + sellitem Animal's_Skin; + sellitem Bill_Of_Birds; +} + +moc_ruins,110,105,2 trader Jeweler#moc1 8_F,{ +OnInit: + sellitem Azure_Jewel; + sellitem Cardinal_Jewel; + sellitem Blue_Jewel; + sellitem Golden_Jewel; + sellitem Bluish_Green_Jewel; +} + +moc_ruins,52,85,6 trader Jeweler#moc2 4W_M_03,{ +OnInit: + sellitem Crystal_Jewel; + sellitem Diamond_Ring; +} + +moc_ruins,113,126,4 trader Trader#moc1 4W_M_03,{ +OnInit: + sellitem Crystal_Mirror; +} + +moc_ruins,131,138,0 trader Trader#moc2 4_F_04,{ +OnInit: + sellitem Witherless_Rose; +} + +moc_ruins,71,139,5 trader Trader#moc3 4_F_04,{ +OnInit: + sellitem Flower_Ring; +} + +moc_ruins,125,135,6 trader Trader#moc4 4_M_ORIENT02,{ +OnInit: + sellitem Skul_Ring; + sellitem Sword_Mace; + sellitem Stunner; +} + +moc_ruins,87,109,0 trader Butcher#moc 1_M_MERCHANT,{ +OnInit: + sellitem Meat; +} + +moc_ruins,90,149,6 trader Trader#moc5 4W_M_03,{ +OnInit: + sellitem Banana; + sellitem Banana; + sellitem Banana; + sellitem Banana; + sellitem Banana; + sellitem Banana; +} + +moc_ruins,118,170,4 trader Pet Groomer#moc 4_M_TELEPORTER,{ +OnInit: + sellitem Pet_Food; + sellitem Pet_Incubator; + sellitem Backpack; + sellitem Rocker_Glasses; + sellitem Mojji; + sellitem Vital_Flower_; + sellitem Flame_Gemstone; + sellitem Bun_; +} + +morocc_in,141,67,0 trader Weapon Dealer#moc1 1_M_MERCHANT,{ +OnInit: + sellitem Arrow; + sellitem Silver_Arrow; + sellitem Bow; + sellitem Rod; + sellitem Knife; + sellitem Cutter; + sellitem Main_Gauche; + sellitem Dirk; + sellitem Dagger; + sellitem Stiletto; + sellitem Gladius; + sellitem Damascus; + sellitem Jur; + sellitem Katar; + sellitem Jamadhar; +} + +morocc_in,141,60,0 trader Armor Dealer#moc 1_M_MERCHANT,{ +OnInit: + sellitem Guard; + sellitem Buckler; + sellitem Sandals; + sellitem Shoes; + sellitem Boots; + sellitem Hood; + sellitem Muffler; + sellitem Flu_Mask; + sellitem Cotton_Shirt; + sellitem Leather_Jacket; + sellitem Adventure_Suit; + sellitem Silk_Robe; + sellitem Wooden_Mail; + sellitem Silver_Robe; + sellitem Mantle; + sellitem Coat; + sellitem Thief_Clothes; + sellitem Novice_Armlet; +} + +morocc_in,132,57,0 trader Weapon Dealer#moc2 4W_M_03,{ +OnInit: + sellitem Town_Sword; + sellitem Cinquedea; +} + //======================================================= // Moscovia //======================================================= -mosk_in,21,254,5 shop Tool Dealer#mosk 4_M_RUSMAN2,611:-1,501:-1,502:-1,503:-1,504:-1,506:-1,645:-1,656:-1,601:-1,602:-1,1065:-1,1750:-1 -mosk_in,31,180,3 shop Weapon Dealer#mosk 4_M_RUSMAN2,1207:-1,1216:-1,1107:-1,1122:-1,1116:-1,1154:-1,1407:-1,1457:-1,1354:-1,1519:-1 -mosk_in,79,178,1 shop Armor Dealer#mosk 4_F_RUSWOMAN3,2211:-1,2401:-1,2403:-1,2501:-1,2503:-1,2101:-1,2103:-1,2305:-1,2321:-1,2332:-1,2328:-1,2627:-1 -moscovia,152,71,4 shop Fruit Gardener#mosk 4_M_RUSMAN2,512:-1,513:-1,515:-1,516:-1 -moscovia,199,110,3 shop Vendor from Milk Ranch#m 4_F_RUSWOMAN1,519:-1 +mosk_in,21,254,5 trader Tool Dealer#mosk 4_M_RUSMAN2,{ +OnInit: + sellitem Spectacles; + sellitem Red_Potion; + sellitem Orange_Potion; + sellitem Yellow_Potion; + sellitem White_Potion; + sellitem Green_Potion; + sellitem Center_Potion; + sellitem Awakening_Potion; + sellitem Wing_Of_Fly; + sellitem Wing_Of_Butterfly; + sellitem Booby_Trap; + sellitem Arrow; +} + +mosk_in,31,180,3 trader Weapon Dealer#mosk 4_M_RUSMAN2,{ +OnInit: + sellitem Main_Gauche; + sellitem Stiletto; + sellitem Blade; + sellitem Ring_Pommel_Saber; + sellitem Katana; + sellitem Bastard_Sword; + sellitem Pike; + sellitem Partizan; + sellitem Hammer; + sellitem Chain; +} + +mosk_in,79,178,1 trader Armor Dealer#mosk 4_F_RUSWOMAN3,{ +OnInit: + sellitem Bandana; + sellitem Sandals; + sellitem Shoes; + sellitem Hood; + sellitem Muffler; + sellitem Guard; + sellitem Buckler; + sellitem Adventure_Suit; + sellitem Silk_Robe; + sellitem Silver_Robe; + sellitem Wooden_Mail; + sellitem Belt; +} + +moscovia,152,71,4 trader Fruit Gardener#mosk 4_M_RUSMAN2,{ +OnInit: + sellitem Apple; + sellitem Banana; + sellitem Carrot; + sellitem Sweet_Potato; +} + +moscovia,199,110,3 trader Vendor from Milk Ranch#m 4_F_RUSWOMAN1,{ +OnInit: + sellitem Milk; +} + //======================================================= // Niflheim //======================================================= -nif_in,37,93,1 shop Axe Dealer#nif 4_NFCOFFIN,1301:-1,1351:-1,1354:-1,1357:-1,1360:-1 -nif_in,37,84,1 shop Armor Dealer#nif 4_NFCOFFIN,2501:-1,2501:-1,2503:-1,2503:-1,2505:-1,2505:-1 -nif_in,145,23,1 shop Tool Dealer#nif 4_NFCOFFIN,535:-1,1062:-1,902:-1,7106:-1,537:-1,7154:-1,1052:-1,934:-1 +nif_in,37,93,1 trader Axe Dealer#nif 4_NFCOFFIN,{ +OnInit: + sellitem Axe; + sellitem Battle_Axe; + sellitem Hammer; + sellitem Buster; + sellitem Two_Handed_Axe; +} + +nif_in,37,84,1 trader Armor Dealer#nif 4_NFCOFFIN,{ +OnInit: + sellitem Hood; + sellitem Hood; + sellitem Muffler; + sellitem Muffler; + sellitem Manteau; + sellitem Manteau; +} + +nif_in,145,23,1 trader Tool Dealer#nif 4_NFCOFFIN,{ +OnInit: + sellitem Pumpkin; + sellitem Pumpkin_Head; + sellitem Tree_Root; + sellitem Goat's_Horn; + sellitem Pet_Food; + sellitem Poison_Powder; + sellitem Single_Cell; + sellitem Mementos; +} + //======================================================= // Payon //======================================================= -payon_in01,15,119,0 shop Weapon Dealer#pay 1_F_ORIENT_03,1750:-1,1751:-1,1101:-1,1104:-1,1107:-1,1201:-1,1204:-1,1207:-1,1601:-1,1701:-1,1704:-1,1707:-1,1710:-1,1713:-1,1714:-1,1718:-1 -payon_in01,5,129,7 shop Weapon Dealer#pay2 4_F_KID2,1146:-1,1245:-1 -payon_in01,7,119,2 shop Armor Dealer#pay 1_F_ORIENT_02,2401:-1,2403:-1,2405:-1,2501:-1,2503:-1,2505:-1,2208:-1,2211:-1,2212:-1,2301:-1,2303:-1,2305:-1,2321:-1,2328:-1,2332:-1,2307:-1,2309:-1,2330:-1,2628:-1 -payon_in01,5,49,7 shop Tool Dealer#pay 4_M_ORIENT01,1750:-1,611:-1,501:-1,502:-1,503:-1,504:-1,506:-1,645:-1,656:-1,601:-1,602:-1,1065:-1 -payon_in02,87,34,0 shop Tool Dealer#pay2 1_F_ORIENT_01,1750:-1,1751:-1,611:-1,501:-1,502:-1,503:-1,504:-1,506:-1,645:-1,656:-1,601:-1,602:-1,1065:-1 -payon,159,96,4 shop Tool Dealer#pay3 4_M_ORIENT01,1750:-1,501:-1,645:-1,601:-1,602:-1 -payon,177,131,4 shop Pet Groomer#pay 4_F_TELEPORTER,537:-1,643:-1,10013:-1,10014:-1,554:-1,6114:-1,6113:-1,6110:-1,6115:-1,6100:-1,6098:-1,6112:-1,6104:-1,6108:-1,6111:-1,6095:-1,6099:-1,6096:-1,6097:-1,6094:-1 +payon_in01,15,119,0 trader Weapon Dealer#pay 1_F_ORIENT_03,{ +OnInit: + sellitem Arrow; + sellitem Silver_Arrow; + sellitem Sword; + sellitem Falchion; + sellitem Blade; + sellitem Knife; + sellitem Cutter; + sellitem Main_Gauche; + sellitem Rod; + sellitem Bow; + sellitem Composite_Bow; + sellitem Great_Bow; + sellitem CrossBow; + sellitem Arbalest; + sellitem Kakkung; + sellitem Hunter_Bow; +} + +payon_in01,5,129,7 trader Weapon Dealer#pay2 4_F_KID2,{ +OnInit: + sellitem Town_Sword; + sellitem Cinquedea; +} + +payon_in01,7,119,2 trader Armor Dealer#pay 1_F_ORIENT_02,{ +OnInit: + sellitem Sandals; + sellitem Shoes; + sellitem Boots; + sellitem Hood; + sellitem Muffler; + sellitem Manteau; + sellitem Ribbon; + sellitem Bandana; + sellitem Eye_Bandage; + sellitem Cotton_Shirt; + sellitem Leather_Jacket; + sellitem Adventure_Suit; + sellitem Silk_Robe; + sellitem Wooden_Mail; + sellitem Silver_Robe; + sellitem Mantle; + sellitem Coat; + sellitem Tights; + sellitem Novice_Armlet; +} + +payon_in01,5,49,7 trader Tool Dealer#pay 4_M_ORIENT01,{ +OnInit: + sellitem Arrow; + sellitem Spectacles; + sellitem Red_Potion; + sellitem Orange_Potion; + sellitem Yellow_Potion; + sellitem White_Potion; + sellitem Green_Potion; + sellitem Center_Potion; + sellitem Awakening_Potion; + sellitem Wing_Of_Fly; + sellitem Wing_Of_Butterfly; + sellitem Booby_Trap; +} + +payon_in02,87,34,0 trader Tool Dealer#pay2 1_F_ORIENT_01,{ +OnInit: + sellitem Arrow; + sellitem Silver_Arrow; + sellitem Spectacles; + sellitem Red_Potion; + sellitem Orange_Potion; + sellitem Yellow_Potion; + sellitem White_Potion; + sellitem Green_Potion; + sellitem Center_Potion; + sellitem Awakening_Potion; + sellitem Wing_Of_Fly; + sellitem Wing_Of_Butterfly; + sellitem Booby_Trap; +} + +payon,159,96,4 trader Tool Dealer#pay3 4_M_ORIENT01,{ +OnInit: + sellitem Arrow; + sellitem Red_Potion; + sellitem Center_Potion; + sellitem Wing_Of_Fly; + sellitem Wing_Of_Butterfly; +} + +payon,177,131,4 trader Pet Groomer#pay 4_F_TELEPORTER,{ +OnInit: + sellitem Pet_Food; + sellitem Pet_Incubator; + sellitem Backpack; + sellitem Rocker_Glasses; + sellitem Mojji; + sellitem Flame_Gemstone; + sellitem Vital_Flower_; + sellitem Vital_Flower; + sellitem Bun_; + sellitem Damp_Darkness; + sellitem Small_Snow_Flower; + sellitem Fresh_Plant; + sellitem Big_Cell; + sellitem Apple_Pudding; + sellitem Mystic_Stone; + sellitem Flavored_Alcohol; + sellitem Grilled_Rice_Cake; + sellitem Fish_With_Blue_Back; + sellitem Pumpkin_Pie_; + sellitem Traditional_Cookie; +} + //======================================================= // Prontera //======================================================= -prontera,73,134,0 shop Vendor from Milk Ranch#p 4_F_01,519:-1 -prontera,104,49,0 shop Fruit Gardener#prt 8_F,512:-1,513:-1 -prontera,64,125,0 shop Butcher#prt 4_M_BARBER,517:-1,528:-1 -prontera,58,182,0 shop Flower Girl#prt 4W_KID,712:-1,744:-1 -prontera,113,42,0 shop Flower Lady#prt 4_F_01,712:-1,744:-1 -prontera,105,87,0 shop Gift Merchant#prt 4_F_02,734:-1,735:-1,736:-1,737:-1,746:-1 -prontera,218,211,4 shop Pet Groomer#prt 4_M_TELEPORTER,537:-1,643:-1,10013:-1,10014:-1,554:-1,6114:-1,6113:-1,6110:-1,6115:-1,6100:-1,6098:-1,6112:-1,6104:-1,6108:-1,6111:-1,6095:-1,6099:-1,6096:-1,6097:-1,6094:-1 -prontera,248,153,0 shop Doll Supplier#prt 4_M_03,740:-1,741:-1,742:-1 -prontera,48,58,0 shop Vegetable Gardener#prt 4_F_02,515:-1,516:-1,535:-1 -prt_church,108,124,4 shop Nun#prt 1_F_PRIEST,2608:-1,2216:-1,5092:-1,2323:-1,2325:-1,1501:-1,1504:-1,1507:-1,1510:-1,1513:-1,1519:-1 -prt_fild05,290,221,2 shop Tool Dealer#prt 4_M_01,1750:-1,611:-1,501:-1,502:-1,506:-1,645:-1,601:-1,602:-1 -prt_in,211,169,0 shop Wedding Shop Dealer#prt 1_F_LIBRARYGIRL,744:-1,745:-1,2338:-1,2206:-1,7170:-1 -prt_in,126,76,0 shop Tool Dealer#prt1 1_M_INNKEEPER,611:-1,1750:-1,501:-1,502:-1,503:-1,504:-1,506:-1,645:-1,656:-1,601:-1,602:-1,1065:-1,2239:-1 -prt_in,172,130,0 shop Weapon Dealer#prt 1_M_JOBGUIDER,1750:-1,1751:-1,1701:-1,1201:-1,1204:-1,1207:-1,1601:-1,1101:-1,1104:-1,1107:-1,1110:-1,1113:-1,1122:-1,1119:-1,1123:-1,1126:-1,1129:-1,1116:-1,1301:-1 -prt_in,172,132,0 shop Armor Dealer#prt 1_M_02,2101:-1,2103:-1,2401:-1,2403:-1,2501:-1,2503:-1,2220:-1,2226:-1,2301:-1,2303:-1,2305:-1,2328:-1,2307:-1,2309:-1,2312:-1,2314:-1,2628:-1,2627:-1 -prt_in,171,140,0 shop Weapon Dealer#prt2 1_M_01,1401:-1,1404:-1,1407:-1,1451:-1,1454:-1,1457:-1,1460:-1,1463:-1,1410:-1 -prt_in,165,140,4 shop Weapon Dealer#prt3 1_F_01,1146:-1,1245:-1 -prt_monk,135,263,5 shop Weapon Dealer#prt4 4_F_JOB_BLACKSMITH,1801:-1,1803:-1,1805:-1 +prontera,73,134,0 trader Vendor from Milk Ranch#p 4_F_01,{ +OnInit: + sellitem Milk; +} + +prontera,104,49,0 trader Fruit Gardener#prt 8_F,{ +OnInit: + sellitem Apple; + sellitem Banana; +} + +prontera,64,125,0 trader Butcher#prt 4_M_BARBER,{ +OnInit: + sellitem Meat; + sellitem Monster's_Feed; +} + +prontera,58,182,0 trader Flower Girl#prt 4W_KID,{ +OnInit: + sellitem Flower; + sellitem Bunch_Of_Flowers; +} + +prontera,113,42,0 trader Flower Lady#prt 4_F_01,{ +OnInit: + sellitem Flower; + sellitem Bunch_Of_Flowers; +} + +prontera,105,87,0 trader Gift Merchant#prt 4_F_02,{ +OnInit: + sellitem Red_Frame; + sellitem Blue_Porcelain; + sellitem White_Platter; + sellitem Black_Ladle; + sellitem Glass_Bead; +} + +prontera,218,211,4 trader Pet Groomer#prt 4_M_TELEPORTER,{ +OnInit: + sellitem Pet_Food; + sellitem Pet_Incubator; + sellitem Backpack; + sellitem Rocker_Glasses; + sellitem Mojji; + sellitem Flame_Gemstone; + sellitem Vital_Flower_; + sellitem Vital_Flower; + sellitem Bun_; + sellitem Damp_Darkness; + sellitem Small_Snow_Flower; + sellitem Fresh_Plant; + sellitem Big_Cell; + sellitem Apple_Pudding; + sellitem Mystic_Stone; + sellitem Flavored_Alcohol; + sellitem Grilled_Rice_Cake; + sellitem Fish_With_Blue_Back; + sellitem Pumpkin_Pie_; + sellitem Traditional_Cookie; +} + +prontera,248,153,0 trader Doll Supplier#prt 4_M_03,{ +OnInit: + sellitem Stuffed_Doll; + sellitem Poring_Doll; + sellitem Chonchon_Doll; +} + +prontera,48,58,0 trader Vegetable Gardener#prt 4_F_02,{ +OnInit: + sellitem Carrot; + sellitem Sweet_Potato; + sellitem Pumpkin; +} + +prt_church,108,124,4 trader Nun#prt 1_F_PRIEST,{ +OnInit: + sellitem Rosary; + sellitem Biretta; + sellitem Blue_Coif; + sellitem Scapulare; + sellitem Saint_Robe; + sellitem Club; + sellitem Mace; + sellitem Smasher; + sellitem Flail; + sellitem Morning_Star; + sellitem Chain; +} + +prt_fild05,290,221,2 trader Tool Dealer#prt 4_M_01,{ +OnInit: + sellitem Arrow; + sellitem Spectacles; + sellitem Red_Potion; + sellitem Orange_Potion; + sellitem Green_Potion; + sellitem Center_Potion; + sellitem Wing_Of_Fly; + sellitem Wing_Of_Butterfly; +} + +prt_in,211,169,0 trader Wedding Shop Dealer#prt 1_F_LIBRARYGIRL,{ +OnInit: + sellitem Bunch_Of_Flowers; + sellitem Wedding_Bouquet; + sellitem Wedding_Dress; + sellitem Wedding_Veil; + sellitem Tuxedo; +} + +prt_in,126,76,0 trader Tool Dealer#prt1 1_M_INNKEEPER,{ +OnInit: + sellitem Spectacles; + sellitem Arrow; + sellitem Red_Potion; + sellitem Orange_Potion; + sellitem Yellow_Potion; + sellitem White_Potion; + sellitem Green_Potion; + sellitem Center_Potion; + sellitem Awakening_Potion; + sellitem Wing_Of_Fly; + sellitem Wing_Of_Butterfly; + sellitem Booby_Trap; + sellitem One_Eyed_Glass; +} + +prt_in,172,130,0 trader Weapon Dealer#prt 1_M_JOBGUIDER,{ +OnInit: + sellitem Arrow; + sellitem Silver_Arrow; + sellitem Bow; + sellitem Knife; + sellitem Cutter; + sellitem Main_Gauche; + sellitem Rod; + sellitem Sword; + sellitem Falchion; + sellitem Blade; + sellitem Lapier; + sellitem Scimiter; + sellitem Ring_Pommel_Saber; + sellitem Tsurugi; + sellitem Haedonggum; + sellitem Saber; + sellitem Flamberge; + sellitem Katana; + sellitem Axe; +} + +prt_in,172,132,0 trader Armor Dealer#prt 1_M_02,{ +OnInit: + sellitem Guard; + sellitem Buckler; + sellitem Sandals; + sellitem Shoes; + sellitem Hood; + sellitem Muffler; + sellitem Hat; + sellitem Cap; + sellitem Cotton_Shirt; + sellitem Leather_Jacket; + sellitem Adventure_Suit; + sellitem Wooden_Mail; + sellitem Mantle; + sellitem Coat; + sellitem Padded_Armor; + sellitem Chain_Mail; + sellitem Novice_Armlet; + sellitem Belt; +} + +prt_in,171,140,0 trader Weapon Dealer#prt2 1_M_01,{ +OnInit: + sellitem Javelin; + sellitem Spear; + sellitem Pike; + sellitem Guisarme; + sellitem Glaive; + sellitem Partizan; + sellitem Trident; + sellitem Halberd; + sellitem Lance; +} + +prt_in,165,140,4 trader Weapon Dealer#prt3 1_F_01,{ +OnInit: + sellitem Town_Sword; + sellitem Cinquedea; +} + +prt_monk,135,263,5 trader Weapon Dealer#prt4 4_F_JOB_BLACKSMITH,{ +OnInit: + sellitem Waghnakh; + sellitem Knuckle_Duster; + sellitem Hora; +} + //======================================================= // Rachel //======================================================= -ra_in01,175,364,3 shop Armor Dealer#ra 4_F_SHABBY,2101:-1,2103:-1,2403:-1,2405:-1,2503:-1,2321:-1,2314:-1,2309:-1,2335:-1,2628:-1 -ra_in01,257,269,3 shop Tool Dealer#ra 4_F_SHABBY,501:-1,502:-1,503:-1,504:-1,506:-1,645:-1,656:-1,601:-1,602:-1,611:-1,1065:-1,610:-1 -ra_in01,176,389,3 shop Weapon Dealer#ra 4_M_RACHMAN1,1201:-1,1207:-1,1216:-1,1107:-1,1122:-1,1116:-1,1154:-1,1407:-1,1457:-1,1354:-1,1519:-1,13003:-1,1601:-1,1604:-1,1607:-1 -ra_in01,254,300,3 shop Fruit Gardener#ra 4_M_RACHMAN1,512:-1,513:-1 -rachel,65,80,1 shop Vegetable Gardener#ra 4_F_SHABBY,515:-1,535:-1,516:-1 +ra_in01,175,364,3 trader Armor Dealer#ra 4_F_SHABBY,{ +OnInit: + sellitem Guard; + sellitem Buckler; + sellitem Shoes; + sellitem Boots; + sellitem Muffler; + sellitem Silk_Robe; + sellitem Chain_Mail; + sellitem Coat; + sellitem Thief_Clothes; + sellitem Novice_Armlet; +} + +ra_in01,257,269,3 trader Tool Dealer#ra 4_F_SHABBY,{ +OnInit: + sellitem Red_Potion; + sellitem Orange_Potion; + sellitem Yellow_Potion; + sellitem White_Potion; + sellitem Green_Potion; + sellitem Center_Potion; + sellitem Awakening_Potion; + sellitem Wing_Of_Fly; + sellitem Wing_Of_Butterfly; + sellitem Spectacles; + sellitem Booby_Trap; + sellitem Leaf_Of_Yggdrasil; +} + +ra_in01,176,389,3 trader Weapon Dealer#ra 4_M_RACHMAN1,{ +OnInit: + sellitem Knife; + sellitem Main_Gauche; + sellitem Stiletto; + sellitem Blade; + sellitem Ring_Pommel_Saber; + sellitem Katana; + sellitem Bastard_Sword; + sellitem Pike; + sellitem Partizan; + sellitem Hammer; + sellitem Chain; + sellitem Coward; + sellitem Rod; + sellitem Wand; + sellitem Staff; +} + +ra_in01,254,300,3 trader Fruit Gardener#ra 4_M_RACHMAN1,{ +OnInit: + sellitem Apple; + sellitem Banana; +} + +rachel,65,80,1 trader Vegetable Gardener#ra 4_F_SHABBY,{ +OnInit: + sellitem Carrot; + sellitem Pumpkin; + sellitem Sweet_Potato; +} + //======================================================= // Turtle Island //======================================================= -tur_dun01,158,54,6 shop Tool Dealer#tu 4W_M_03,1750:-1,501:-1,502:-1,503:-1,504:-1,506:-1,601:-1,602:-1,645:-1,656:-1,2242:-1 +tur_dun01,158,54,6 trader Tool Dealer#tu 4W_M_03,{ +OnInit: + sellitem Arrow; + sellitem Red_Potion; + sellitem Orange_Potion; + sellitem Yellow_Potion; + sellitem White_Potion; + sellitem Green_Potion; + sellitem Wing_Of_Fly; + sellitem Wing_Of_Butterfly; + sellitem Center_Potion; + sellitem Awakening_Potion; + sellitem Luxury_Sunglasses; +} + //======================================================= // Umbala //======================================================= -um_in,104,124,3 shop Tool Dealer#um 4_M_UMOLDMAN,512:-1,515:-1,535:-1,516:-1,513:-1,517:-1,528:-1,537:-1,601:-1,602:-1,645:-1,656:-1,610:-1 -um_in,160,125,3 shop Weapon Dealer#um 4_M_UMSOLDIER,1501:-1,1504:-1,1507:-1,1510:-1,1513:-1,1519:-1,1807:-1,1811:-1,1809:-1 +um_in,104,124,3 trader Tool Dealer#um 4_M_UMOLDMAN,{ +OnInit: + sellitem Apple; + sellitem Carrot; + sellitem Pumpkin; + sellitem Sweet_Potato; + sellitem Banana; + sellitem Meat; + sellitem Monster's_Feed; + sellitem Pet_Food; + sellitem Wing_Of_Fly; + sellitem Wing_Of_Butterfly; + sellitem Center_Potion; + sellitem Awakening_Potion; + sellitem Leaf_Of_Yggdrasil; +} + +um_in,160,125,3 trader Weapon Dealer#um 4_M_UMSOLDIER,{ +OnInit: + sellitem Club; + sellitem Mace; + sellitem Smasher; + sellitem Flail; + sellitem Morning_Star; + sellitem Chain; + sellitem Fist; + sellitem Finger; + sellitem Claw; +} + //======================================================= // Veins //======================================================= -ve_in,386,245,3 shop Weapon Dealer#ve 4_M_RACHMAN1,1201:-1,1207:-1,1216:-1,1107:-1,1122:-1,1116:-1,1154:-1 -ve_in,336,243,3 shop Weapon Dealer#ve2 4_M_RACHMAN1,1407:-1,1457:-1,1354:-1,1519:-1,13003:-1 -ve_in,374,230,3 shop Armor Dealer#ve 4_F_SHABBY,2101:-1,2103:-1,2403:-1,2405:-1,2503:-1,2321:-1,2314:-1,2309:-1,2335:-1,2628:-1 -ve_in,243,303,5 shop Tool Dealer#ve 4_M_DESERT,501:-1,502:-1,503:-1,504:-1,506:-1,645:-1,656:-1,601:-1,602:-1,611:-1,1065:-1,610:-1 -ve_in,253,304,5 shop Fruit Gardener#ve 4_F_DST_CHILD,512:-1,513:-1 -ve_in,252,313,0 shop Magical Item Seller#ve 4_F_DST_GRAND,717:-1,1601:-1,1604:-1,1607:-1,1610:-1,2232:-1,2321:-1,2332:-1 +ve_in,386,245,3 trader Weapon Dealer#ve 4_M_RACHMAN1,{ +OnInit: + sellitem Knife; + sellitem Main_Gauche; + sellitem Stiletto; + sellitem Blade; + sellitem Ring_Pommel_Saber; + sellitem Katana; + sellitem Bastard_Sword; +} + +ve_in,336,243,3 trader Weapon Dealer#ve2 4_M_RACHMAN1,{ +OnInit: + sellitem Pike; + sellitem Partizan; + sellitem Hammer; + sellitem Chain; + sellitem Coward; +} + +ve_in,374,230,3 trader Armor Dealer#ve 4_F_SHABBY,{ +OnInit: + sellitem Guard; + sellitem Buckler; + sellitem Shoes; + sellitem Boots; + sellitem Muffler; + sellitem Silk_Robe; + sellitem Chain_Mail; + sellitem Coat; + sellitem Thief_Clothes; + sellitem Novice_Armlet; +} + +ve_in,243,303,5 trader Tool Dealer#ve 4_M_DESERT,{ +OnInit: + sellitem Red_Potion; + sellitem Orange_Potion; + sellitem Yellow_Potion; + sellitem White_Potion; + sellitem Green_Potion; + sellitem Center_Potion; + sellitem Awakening_Potion; + sellitem Wing_Of_Fly; + sellitem Wing_Of_Butterfly; + sellitem Spectacles; + sellitem Booby_Trap; + sellitem Leaf_Of_Yggdrasil; +} + +ve_in,253,304,5 trader Fruit Gardener#ve 4_F_DST_CHILD,{ +OnInit: + sellitem Apple; + sellitem Banana; +} + +ve_in,252,313,0 trader Magical Item Seller#ve 4_F_DST_GRAND,{ +OnInit: + sellitem Blue_Gemstone; + sellitem Rod; + sellitem Wand; + sellitem Staff; + sellitem Arc_Wand; + sellitem Circlet; + sellitem Silk_Robe; + sellitem Silver_Robe; +} + //======================================================= // Cooking Addition //======================================================= -prontera,156,212,1 shop Chef Assistant#prt 8_F_GIRL,7454:-1,7456:-1,7482:-1,580:-1 -payon,206,119,5 shop Chef Assistant#pay 4_M_ORIENT02,7455:-1 -moc_ruins,115,123,5 shop Chef Assistant#moc 4_M_04,7455:-1,7453:-1,7454:-1,7456:-1,7452:-1 -geffen,196,111,3 shop Chef Assistant#gef 4_M_03,7482:-1 -alberta,167,135,5 shop Chef Assistant#alb 4_M_05,579:-1 -aldebaran,165,107,2 shop Chef Assistant#alde 4W_M_01,7456:-1,7452:-1,580:-1 -comodo,225,164,3 shop Chef Assistant#cmd 4_M_01,7455:-1,7453:-1,7454:-1,579:-1 -umbala,102,154,3 shop Chef Assistant#um 4_M_01,7456:-1,577:-1 -yuno,130,173,3 shop Chef Assistant#yuno 4_M_01,7457:-1,7482:-1 -einbroch,224,207,5 shop Chef Assistant#ein 4_M_01,7457:-1 -lighthalzen,126,126,3 shop Chef Assistant#lhz 4_M_01,7456:-1,7452:-1 -amatsu,206,150,3 shop Chef Assistant#ama 4_M_01,7453:-1,579:-1 -louyang,256,123,5 shop Chef Assistant#lou 4_M_CHNCOOK,7454:-1,577:-1 -gonryun,147,101,5 shop Chef Assistant#gon 4_M_01,7452:-1,580:-1 -ayothaya,203,178,3 shop Chef Assistant#ayo 4_M_01,7455:-1,577:-1 -xmas,152,137,5 shop Chef Assistant#xmas 4_M_01,7457:-1,577:-1 -niflheim,209,180,5 shop Chef Assistant#nif 4_M_01,581:-1 +prontera,156,212,1 trader Chef Assistant#prt 8_F_GIRL,{ +OnInit: + sellitem Plain_Sauce; + sellitem Red_Spice; + sellitem Pot; + sellitem Bread; +} + +payon,206,119,5 trader Chef Assistant#pay 4_M_ORIENT02,{ +OnInit: + sellitem Hot_Sauce; +} + +moc_ruins,115,123,5 trader Chef Assistant#moc 4_M_04,{ +OnInit: + sellitem Hot_Sauce; + sellitem Sweet_Sauce; + sellitem Plain_Sauce; + sellitem Red_Spice; + sellitem Yellow_Spice; +} + +geffen,196,111,3 trader Chef Assistant#gef 4_M_03,{ +OnInit: + sellitem Pot; +} + +alberta,167,135,5 trader Chef Assistant#alb 4_M_05,{ +OnInit: + sellitem Delicious_Fish; +} + +aldebaran,165,107,2 trader Chef Assistant#alde 4W_M_01,{ +OnInit: + sellitem Red_Spice; + sellitem Yellow_Spice; + sellitem Bread; +} + +comodo,225,164,3 trader Chef Assistant#cmd 4_M_01,{ +OnInit: + sellitem Hot_Sauce; + sellitem Sweet_Sauce; + sellitem Plain_Sauce; + sellitem Delicious_Fish; +} + +umbala,102,154,3 trader Chef Assistant#um 4_M_01,{ +OnInit: + sellitem Red_Spice; + sellitem Grain; +} + +yuno,130,173,3 trader Chef Assistant#yuno 4_M_01,{ +OnInit: + sellitem Cooking_Oil; + sellitem Pot; +} + +einbroch,224,207,5 trader Chef Assistant#ein 4_M_01,{ +OnInit: + sellitem Cooking_Oil; +} + +lighthalzen,126,126,3 trader Chef Assistant#lhz 4_M_01,{ +OnInit: + sellitem Red_Spice; + sellitem Yellow_Spice; +} + +amatsu,206,150,3 trader Chef Assistant#ama 4_M_01,{ +OnInit: + sellitem Sweet_Sauce; + sellitem Delicious_Fish; +} + +louyang,256,123,5 trader Chef Assistant#lou 4_M_CHNCOOK,{ +OnInit: + sellitem Plain_Sauce; + sellitem Grain; +} + +gonryun,147,101,5 trader Chef Assistant#gon 4_M_01,{ +OnInit: + sellitem Yellow_Spice; + sellitem Bread; +} + +ayothaya,203,178,3 trader Chef Assistant#ayo 4_M_01,{ +OnInit: + sellitem Hot_Sauce; + sellitem Grain; +} + +xmas,152,137,5 trader Chef Assistant#xmas 4_M_01,{ +OnInit: + sellitem Cooking_Oil; + sellitem Grain; +} + +niflheim,209,180,5 trader Chef Assistant#nif 4_M_01,{ +OnInit: + sellitem Mushroom; +} + //===== Additional Comments(old): ================================= //= swapped shop titles in GONRYUN, thanks to Kashy @@ -364,4 +2240,4 @@ niflheim,209,180,5 shop Chef Assistant#nif 4_M_01,581:-1 //= 1.9a Pet Merchant -> Lighthalzen [erKURITA] //= 1.9b Added items to Chivas Regal //= 1.9c Slight update for Rachel shop: Tool Dealer -> Fruit Gardener [L0ne_W0lf] -//============================================================ +//============================================================
\ No newline at end of file diff --git a/sql-files/main.sql b/sql-files/main.sql index 60b21285d..906c329fa 100644 --- a/sql-files/main.sql +++ b/sql-files/main.sql @@ -671,6 +671,7 @@ INSERT INTO `sql_updates` (`timestamp`) VALUES (1383205740); INSERT INTO `sql_updates` (`timestamp`) VALUES (1383955424); INSERT INTO `sql_updates` (`timestamp`) VALUES (1384545461); INSERT INTO `sql_updates` (`timestamp`) VALUES (1384588175); +INSERT INTO `sql_updates` (`timestamp`) VALUES (1387844126); -- -- Table structure for table `sstatus` @@ -731,3 +732,14 @@ CREATE TABLE IF NOT EXISTS `account_data` ( PRIMARY KEY (`account_id`) ) ENGINE=MyISAM; +-- +-- Table structure for table `npc_market_data` +-- + +CREATE TABLE IF NOT EXISTS `npc_market_data` ( + `name` varchar(24) NOT NULL default '', + `itemid` int(11) unsigned NOT NULL default '0', + `amount` int(11) unsigned NOT NULL default '0', + PRIMARY KEY (`name`,`itemid`) +) ENGINE=MyISAM; + diff --git a/sql-files/upgrades/2013-12-24--00-15.sql b/sql-files/upgrades/2013-12-24--00-15.sql new file mode 100644 index 000000000..b1f8d019d --- /dev/null +++ b/sql-files/upgrades/2013-12-24--00-15.sql @@ -0,0 +1,8 @@ +#1387844126 +CREATE TABLE IF NOT EXISTS `npc_market_data` ( + `name` varchar(24) NOT NULL default '', + `itemid` int(11) unsigned NOT NULL default '0', + `amount` int(11) unsigned NOT NULL default '0', + PRIMARY KEY (`name`,`itemid`) +) ENGINE=MyISAM; +INSERT INTO `sql_updates` (`timestamp`) VALUES (1387844126); diff --git a/sql-files/upgrades/index.txt b/sql-files/upgrades/index.txt index 9b7ad20d8..0c4ac87e5 100644 --- a/sql-files/upgrades/index.txt +++ b/sql-files/upgrades/index.txt @@ -15,3 +15,4 @@ 2013-11-15--19-57.sql 2013-11-16--07-49.sql 2013-11-18--08-23.sql +2013-12-24--00-15.sql
\ No newline at end of file diff --git a/src/common/mmo.h b/src/common/mmo.h index b33b01fa7..bd5da6a9f 100644 --- a/src/common/mmo.h +++ b/src/common/mmo.h @@ -48,7 +48,7 @@ // 20120307 - 2012-03-07aRagexeRE+ - 0x970 #ifndef PACKETVER -#define PACKETVER 20120418 + #define PACKETVER 20131223 #endif // PACKETVER #ifndef DISABLE_PACKETVER_RE diff --git a/src/map/atcommand.c b/src/map/atcommand.c index 953f1a0dc..ce73319e2 100644 --- a/src/map/atcommand.c +++ b/src/map/atcommand.c @@ -9273,17 +9273,28 @@ ACMD(searchstore){ return true; } ACMD(costume){ - const char* names[4] = { + const char* names[] = { "Wedding", "Xmas", "Summer", "Hanbok", +#if PACKETVER >= 20131218 + "Oktoberfest", +#endif + }; + const int name2id[] = { + SC_WEDDING, + SC_XMAS, + SC_SUMMER, + SC_HANBOK, +#if PACKETVER >= 20131218 + SC_OKTOBERFEST, +#endif }; - const int name2id[4] = { SC_WEDDING, SC_XMAS, SC_SUMMER, SC_HANBOK }; - unsigned short k = 0; + unsigned short k = 0, len = ARRAYLENGTH(names); if( !message || !*message ) { - for( k = 0; k < 4; k++ ) { + for( k = 0; k < len; k++ ) { if( sd->sc.data[name2id[k]] ) { sprintf(atcmd_output,msg_txt(1473),names[k]);//Costume '%s' removed. clif->message(sd->fd,atcmd_output); @@ -9293,14 +9304,14 @@ ACMD(costume){ } clif->message(sd->fd,msg_txt(1472)); - for( k = 0; k < 4; k++ ) { + for( k = 0; k < len; k++ ) { sprintf(atcmd_output,msg_txt(1471),names[k]);//-- %s clif->message(sd->fd,atcmd_output); } return false; } - for( k = 0; k < 4; k++ ) { + for( k = 0; k < len; k++ ) { if( sd->sc.data[name2id[k]] ) { sprintf(atcmd_output,msg_txt(1470),names[k]);// You're already with a '%s' costume, type '@costume' to remove it. clif->message(sd->fd,atcmd_output); @@ -9308,11 +9319,11 @@ ACMD(costume){ } } - for( k = 0; k < 4; k++ ) { + for( k = 0; k < len; k++ ) { if( strcmpi(message,names[k]) == 0 ) break; } - if( k == 4 ) { + if( k == len ) { sprintf(atcmd_output,msg_txt(1469),message);// '%s' is not a known costume clif->message(sd->fd,atcmd_output); return false; diff --git a/src/map/clif.c b/src/map/clif.c index 6a55ad344..b442d6279 100644 --- a/src/map/clif.c +++ b/src/map/clif.c @@ -61,7 +61,8 @@ static struct packet_itemlist_equip itemlist_equip; static struct packet_storelist_normal storelist_normal; static struct packet_storelist_equip storelist_equip; static struct packet_viewequip_ack viewequip_list; - +static struct packet_npc_market_result_ack npcmarket_result; +static struct packet_npc_market_open npcmarket_open; //#define DUMP_UNKNOWN_PACKET //#define DUMP_INVALID_PACKET @@ -811,7 +812,7 @@ void clif_clearunit_delayed(struct block_list* bl, clr_type type, int64 tick) { void clif_get_weapon_view(struct map_session_data* sd, unsigned short *rhand, unsigned short *lhand) { - if(sd->sc.option&(OPTION_WEDDING|OPTION_XMAS|OPTION_SUMMER|OPTION_HANBOK)) { + if(sd->sc.option&(OPTION_WEDDING|OPTION_XMAS|OPTION_SUMMER|OPTION_HANBOK|OPTION_OKTOBERFEST)) { *rhand = *lhand = 0; return; } @@ -1743,29 +1744,40 @@ void clif_npcbuysell(struct map_session_data* sd, int id) /// Presents list of items, that can be bought in an NPC shop (ZC_PC_PURCHASE_ITEMLIST). /// 00c6 <packet len>.W { <price>.L <discount price>.L <item type>.B <name id>.W }* -void clif_buylist(struct map_session_data *sd, struct npc_data *nd) -{ +void clif_buylist(struct map_session_data *sd, struct npc_data *nd) { + struct npc_item_list *shop = NULL; + unsigned short shop_size = 0; int fd,i,c; - + nullpo_retv(sd); nullpo_retv(nd); + if( nd->subtype == SCRIPT ) { + shop = nd->u.scr.shop->item; + shop_size = nd->u.scr.shop->items; + } else { + shop = nd->u.shop.shop_item; + shop_size = nd->u.shop.count; + } + fd = sd->fd; - WFIFOHEAD(fd, 4 + nd->u.shop.count * 11); + + WFIFOHEAD(fd, 4 + shop_size * 11); WFIFOW(fd,0) = 0xc6; c = 0; - for( i = 0; i < nd->u.shop.count; i++ ) - { - struct item_data* id = itemdb->exists(nd->u.shop.shop_item[i].nameid); - int val = nd->u.shop.shop_item[i].value; - if( id == NULL ) - continue; - WFIFOL(fd, 4+c*11) = val; - WFIFOL(fd, 8+c*11) = pc->modifybuyvalue(sd,val); - WFIFOB(fd,12+c*11) = itemtype(id->type); - WFIFOW(fd,13+c*11) = ( id->view_id > 0 ) ? id->view_id : id->nameid; - c++; + for( i = 0; i < shop_size; i++ ) { + if( shop[i].nameid ) { + struct item_data* id = itemdb->exists(shop[i].nameid); + int val = shop[i].value; + if( id == NULL ) + continue; + WFIFOL(fd, 4+c*11) = val; + WFIFOL(fd, 8+c*11) = pc->modifybuyvalue(sd,val); + WFIFOB(fd,12+c*11) = itemtype(id->type); + WFIFOW(fd,13+c*11) = ( id->view_id > 0 ) ? id->view_id : id->nameid; + c++; + } } WFIFOW(fd,2) = 4 + c*11; @@ -3170,7 +3182,7 @@ void clif_changelook(struct block_list *bl,int type,int val) case LOOK_BASE: if( !sd ) break; - if( sd->sc.option&(OPTION_WEDDING|OPTION_XMAS|OPTION_SUMMER|OPTION_HANBOK) ) + if( sd->sc.option&(OPTION_WEDDING|OPTION_XMAS|OPTION_SUMMER|OPTION_HANBOK|OPTION_OKTOBERFEST) ) vd->weapon = vd->shield = 0; if( !vd->cloth_color ) @@ -3185,6 +3197,8 @@ void clif_changelook(struct block_list *bl,int type,int val) vd->cloth_color = 0; if( sd->sc.option&OPTION_HANBOK && battle_config.hanbok_ignorepalette ) vd->cloth_color = 0; + if( sd->sc.option&OPTION_OKTOBERFEST /* TODO: config? */ ) + vd->cloth_color = 0; } break; case LOOK_HAIR: @@ -3212,6 +3226,8 @@ void clif_changelook(struct block_list *bl,int type,int val) val = 0; if( sd->sc.option&OPTION_HANBOK && battle_config.hanbok_ignorepalette ) val = 0; + if( sd->sc.option&OPTION_OKTOBERFEST /* TODO: config? */ ) + val = 0; } vd->cloth_color = val; break; @@ -9616,6 +9632,7 @@ void clif_parse_Hotkey(int fd, struct map_session_data *sd) { /// Displays cast-like progress bar (ZC_PROGRESS). /// 02f0 <color>.L <time>.L +/* TODO ZC_PROGRESS_ACTOR <account_id>.L */ void clif_progressbar(struct map_session_data * sd, unsigned int color, unsigned int second) { int fd = sd->fd; @@ -9901,6 +9918,7 @@ void clif_parse_GlobalMessage(int fd, struct map_session_data* sd) WFIFOW(fd,0) = 0x8e; } WFIFOSET(fd, WFIFOW(fd,2)); + #ifdef PCRE_SUPPORT // trigger listening npcs map->foreachinrange(npc_chat->sub, &sd->bl, AREA_SIZE, BL_NPC, text, textlen, &sd->bl); @@ -10058,7 +10076,7 @@ void clif_parse_ActionRequest_sub(struct map_session_data *sd, int action_type, if( pc_cant_act(sd) || sd->sc.option&OPTION_HIDE ) return; - if( sd->sc.option&(OPTION_WEDDING|OPTION_XMAS|OPTION_SUMMER|OPTION_HANBOK) ) + if( sd->sc.option&(OPTION_WEDDING|OPTION_XMAS|OPTION_SUMMER|OPTION_HANBOK|OPTION_OKTOBERFEST) ) return; if( sd->sc.data[SC_BASILICA] || sd->sc.data[SC__SHADOWFORM] ) @@ -11303,7 +11321,7 @@ void clif_parse_UseSkillToId(int fd, struct map_session_data *sd) } } - if( sd->sc.option&(OPTION_WEDDING|OPTION_XMAS|OPTION_SUMMER|OPTION_HANBOK) ) + if( sd->sc.option&(OPTION_WEDDING|OPTION_XMAS|OPTION_SUMMER|OPTION_HANBOK|OPTION_OKTOBERFEST) ) return; if( sd->sc.data[SC_BASILICA] && (skill_id != HP_BASILICA || sd->sc.data[SC_BASILICA]->val4 != sd->bl.id) ) @@ -11395,7 +11413,7 @@ void clif_parse_UseSkillToPosSub(int fd, struct map_session_data *sd, uint16 ski } } - if( sd->sc.option&(OPTION_WEDDING|OPTION_XMAS|OPTION_SUMMER|OPTION_HANBOK) ) + if( sd->sc.option&(OPTION_WEDDING|OPTION_XMAS|OPTION_SUMMER|OPTION_HANBOK|OPTION_OKTOBERFEST) ) return; if( sd->sc.data[SC_BASILICA] && (skill_id != HP_BASILICA || sd->sc.data[SC_BASILICA]->val4 != sd->bl.id) ) @@ -13524,19 +13542,20 @@ void clif_parse_GMRecall2(int fd, struct map_session_data* sd) { /// /item cap_n - capture n monster as pet.(not yet implemented) /// /item agitinvest - reset current global agit investments.(not yet implemented) /// 013f <item/mob name>.24B -void clif_parse_GM_Monster_Item(int fd, struct map_session_data *sd) -{ +/// 09ce <item/mob name>.100B [Ind/Yommy<3] +void clif_parse_GM_Monster_Item(int fd, struct map_session_data *sd) { + struct packet_gm_monster_item *p = P2PTR(fd); int i, count; char *item_monster_name; struct item_data *item_array[10]; struct mob_db *mob_array[10]; - char command[NAME_LENGTH+10]; + char command[256]; - item_monster_name = (char*)RFIFOP(fd,2); - item_monster_name[NAME_LENGTH-1] = '\0'; + item_monster_name = p->str; + item_monster_name[(sizeof(struct packet_gm_monster_item)-2)-1] = '\0'; - if ( (count=itemdb->search_name_array(item_array, 10, item_monster_name, 1)) > 0 ){ - for(i = 0; i < count; i++){ + if ( (count=itemdb->search_name_array(item_array, 10, item_monster_name, 1)) > 0 ) { + for(i = 0; i < count; i++) { if( !item_array[i] ) continue; // It only accepts aegis name @@ -13546,7 +13565,7 @@ void clif_parse_GM_Monster_Item(int fd, struct map_session_data *sd) break; } - if( i < count ){ + if( i < count ) { if( item_array[i]->type == IT_WEAPON || item_array[i]->type == IT_ARMOR ) // nonstackable snprintf(command, sizeof(command)-1, "%citem2 %d 1 0 0 0 0 0 0 0", atcommand->at_symbol, item_array[i]->nameid); else @@ -13562,8 +13581,8 @@ void clif_parse_GM_Monster_Item(int fd, struct map_session_data *sd) return; } - if( (count=mob->db_searchname_array(mob_array, 10, item_monster_name, 1)) > 0){ - for(i = 0; i < count; i++){ + if( (count=mob->db_searchname_array(mob_array, 10, item_monster_name, 1)) > 0) { + for(i = 0; i < count; i++) { if( !mob_array[i] ) continue; // It only accepts sprite name @@ -15402,9 +15421,11 @@ void clif_parse_Auction_buysell(int fd, struct map_session_data* sd) /// List of items offered in a cash shop (ZC_PC_CASH_POINT_ITEMLIST). /// 0287 <packet len>.W <cash point>.L { <sell price>.L <discount price>.L <item type>.B <name id>.W }* /// 0287 <packet len>.W <cash point>.L <kafra point>.L { <sell price>.L <discount price>.L <item type>.B <name id>.W }* (PACKETVER >= 20070711) -void clif_cashshop_show(struct map_session_data *sd, struct npc_data *nd) -{ - int fd,i; +void clif_cashshop_show(struct map_session_data *sd, struct npc_data *nd) { + struct npc_item_list *shop = NULL; + unsigned short shop_size = 0; + int fd,i, c = 0; + int currency[2] = { 0,0 }; #if PACKETVER < 20070711 const int offset = 8; #else @@ -15414,23 +15435,43 @@ void clif_cashshop_show(struct map_session_data *sd, struct npc_data *nd) nullpo_retv(sd); nullpo_retv(nd); + if( nd->subtype == SCRIPT ) { + shop = nd->u.scr.shop->item; + shop_size = nd->u.scr.shop->items; + + npc->trader_count_funds(nd, sd); + + currency[0] = npc->trader_funds[0]; + currency[1] = npc->trader_funds[1]; + } else { + shop = nd->u.shop.shop_item; + shop_size = nd->u.shop.count; + + currency[0] = sd->cashPoints; + currency[1] = sd->kafraPoints; + } + fd = sd->fd; sd->npc_shopid = nd->bl.id; - WFIFOHEAD(fd,offset+nd->u.shop.count*11); + WFIFOHEAD(fd,offset+shop_size*11); WFIFOW(fd,0) = 0x287; - WFIFOW(fd,2) = offset+nd->u.shop.count*11; - WFIFOL(fd,4) = sd->cashPoints; // Cash Points + /* 0x2 = length, set after parsing */ + WFIFOL(fd,4) = currency[0]; // Cash Points #if PACKETVER >= 20070711 - WFIFOL(fd,8) = sd->kafraPoints; // Kafra Points + WFIFOL(fd,8) = currency[1]; // Kafra Points #endif - for( i = 0; i < nd->u.shop.count; i++ ) { - struct item_data* id = itemdb->search(nd->u.shop.shop_item[i].nameid); - WFIFOL(fd,offset+0+i*11) = nd->u.shop.shop_item[i].value; - WFIFOL(fd,offset+4+i*11) = nd->u.shop.shop_item[i].value; // Discount Price - WFIFOB(fd,offset+8+i*11) = itemtype(id->type); - WFIFOW(fd,offset+9+i*11) = ( id->view_id > 0 ) ? id->view_id : id->nameid; + for( i = 0; i < shop_size; i++ ) { + if( shop[i].nameid ) { + struct item_data* id = itemdb->search(shop[i].nameid); + WFIFOL(fd,offset+0+i*11) = shop[i].value; + WFIFOL(fd,offset+4+i*11) = shop[i].value; // Discount Price + WFIFOB(fd,offset+8+i*11) = itemtype(id->type); + WFIFOW(fd,offset+9+i*11) = ( id->view_id > 0 ) ? id->view_id : id->nameid; + c++; + } } + WFIFOW(fd,2) = offset+c*11; WFIFOSET(fd,WFIFOW(fd,2)); } @@ -15449,15 +15490,26 @@ void clif_cashshop_show(struct map_session_data *sd, struct npc_data *nd) /// 7 = You can purchase up to 10 items. /// 8 = Some items could not be purchased. void clif_cashshop_ack(struct map_session_data* sd, int error) { - int fd = sd->fd; + struct npc_data *nd; + int fd = sd->fd; + int currency[2] = { 0,0 }; + + if( (nd = map->id2nd(sd->npc_shopid)) && nd->subtype == SCRIPT ) { + npc->trader_count_funds(nd,sd); + currency[0] = npc->trader_funds[0]; + currency[1] = npc->trader_funds[1]; + } else { + currency[0] = sd->cashPoints; + currency[1] = sd->kafraPoints; + } WFIFOHEAD(fd, packet_len(0x289)); WFIFOW(fd,0) = 0x289; - WFIFOL(fd,2) = sd->cashPoints; + WFIFOL(fd,2) = currency[0]; #if PACKETVER < 20070711 WFIFOW(fd,6) = TOW(error); #else - WFIFOL(fd,6) = sd->kafraPoints; + WFIFOL(fd,6) = currency[1]; WFIFOW(fd,10) = TOW(error); #endif WFIFOSET(fd, packet_len(0x289)); @@ -18048,7 +18100,77 @@ int clif_delay_damage(int64 tick, struct block_list *src, struct block_list *dst return clif->calc_walkdelay(dst,ddelay,type,damage,div); } +/* Thanks to Yommy */ +void clif_parse_NPCShopClosed(int fd, struct map_session_data *sd) { + /* TODO track the state <3~ */ + sd->npc_shopid = 0; +} +/* NPC Market (by Ind after an extensive debugging of the packet, only possible thanks to Yommy <3) */ +void clif_npc_market_open(struct map_session_data *sd, struct npc_data *nd) { + struct npc_item_list *shop = nd->u.scr.shop->item; + unsigned short shop_size = nd->u.scr.shop->items, i, c; + struct item_data *id = NULL; + + npcmarket_open.PacketType = npcmarketopenType; + + for(i = 0, c = 0; i < shop_size; i++) { + if( shop[i].nameid && (id = itemdb->exists(shop[i].nameid)) ) { + npcmarket_open.list[c].nameid = shop[i].nameid; + npcmarket_open.list[c].price = shop[i].value; + npcmarket_open.list[c].qty = shop[i].qty; + npcmarket_open.list[c].type = itemtype(id->type); + npcmarket_open.list[c].view = ( id->view_id > 0 ) ? id->view_id : id->nameid; + c++; + } + } + + npcmarket_open.PacketLength = 4 + ( sizeof(npcmarket_open.list[0]) * c ); + + clif->send(&npcmarket_open,npcmarket_open.PacketLength,&sd->bl,SELF); +} +void clif_parse_NPCMarketClosed(int fd, struct map_session_data *sd) { + /* TODO track the state <3~ */ + sd->npc_shopid = 0; +} +void clif_npc_market_purchase_ack(struct map_session_data *sd, struct packet_npc_market_purchase *req, unsigned char response) { + unsigned short c = 0; + + npcmarket_result.PacketType = npcmarketresultackType; + npcmarket_result.result = response == 0 ? 1 : 0;/* find other values */ + + if( npcmarket_result.result ) { + unsigned short i, list_size = (req->PacketLength - 4) / sizeof(req->list[0]), j; + struct npc_data* nd; + struct npc_item_list *shop = NULL; + unsigned short shop_size = 0; + + nd = map->id2nd(sd->npc_shopid); + shop = nd->u.scr.shop->item; + shop_size = nd->u.scr.shop->items; + + for(i = 0; i < list_size; i++) { + + npcmarket_result.list[i].ITID = req->list[i].ITID; + npcmarket_result.list[i].qty = req->list[i].qty; + + ARR_FIND( 0, shop_size, j, req->list[i].ITID == shop[j].nameid ); + + npcmarket_result.list[i].price = (j != shop_size) ? shop[j].value : 0; + + c++; + } + } + + npcmarket_result.PacketLength = 5 + ( sizeof(npcmarket_result.list[0]) * c );; + + clif->send(&npcmarket_result,npcmarket_result.PacketLength,&sd->bl,SELF); +} +void clif_parse_NPCMarketPurchase(int fd, struct map_session_data *sd) { + struct packet_npc_market_purchase *p = P2PTR(fd); + + clif->npc_market_purchase_ack(sd,p,npc->market_buylist(sd,(p->PacketLength - 4) / sizeof(p->list[0]),p)); +} /* */ unsigned short clif_decrypt_cmd( int cmd, struct map_session_data *sd ) { if( sd ) { @@ -18863,6 +18985,9 @@ void clif_defaults(void) { /* */ clif->delay_damage = clif_delay_damage; clif->delay_damage_sub = clif_delay_damage_sub; + /* NPC Market */ + clif->npc_market_open = clif_npc_market_open; + clif->npc_market_purchase_ack = clif_npc_market_purchase_ack; /*------------------------ *- Parse Incoming Packet *------------------------*/ @@ -19092,4 +19217,9 @@ void clif_defaults(void) { clif->pBankCheck = clif_parse_BankCheck; clif->pBankOpen = clif_parse_BankOpen; clif->pBankClose = clif_parse_BankClose; + /* */ + clif->pNPCShopClosed = clif_parse_NPCShopClosed; + /* NPC Market */ + clif->pNPCMarketClosed = clif_parse_NPCMarketClosed; + clif->pNPCMarketPurchase = clif_parse_NPCMarketPurchase; } diff --git a/src/map/clif.h b/src/map/clif.h index c4088893a..6405bbd3e 100644 --- a/src/map/clif.h +++ b/src/map/clif.h @@ -1034,6 +1034,9 @@ struct clif_interface { /* */ int (*delay_damage) (int64 tick, struct block_list *src, struct block_list *dst, int sdelay, int ddelay, int64 in_damage, short div, unsigned char type); int (*delay_damage_sub) (int tid, int64 tick, int id, intptr_t data); + /* NPC Market */ + void (*npc_market_open) (struct map_session_data *sd, struct npc_data *nd); + void (*npc_market_purchase_ack) (struct map_session_data *sd, struct packet_npc_market_purchase *req, unsigned char response); /*------------------------ *- Parse Incoming Packet *------------------------*/ @@ -1261,6 +1264,11 @@ struct clif_interface { void (*pBankCheck) (int fd, struct map_session_data *sd); void (*pBankOpen) (int fd, struct map_session_data *sd); void (*pBankClose) (int fd, struct map_session_data *sd); + /* */ + void (*pNPCShopClosed) (int fd, struct map_session_data *sd); + /* NPC Market (by Ind after an extensive debugging of the packet, only possible thanks to Yommy <3) */ + void (*pNPCMarketClosed) (int fd, struct map_session_data *sd); + void (*pNPCMarketPurchase) (int fd, struct map_session_data *sd); }; struct clif_interface *clif; diff --git a/src/map/map.c b/src/map/map.c index 7ff4ebcc5..aef34ef00 100644 --- a/src/map/map.c +++ b/src/map/map.c @@ -5630,7 +5630,8 @@ int do_init(int argc, char *argv[]) } npc->event_do_oninit(); // Init npcs (OnInit) - + npc->market_fromsql(); /* after OnInit */ + if (battle_config.pk_mode) ShowNotice("Server is running on '"CL_WHITE"PK Mode"CL_RESET"'.\n"); diff --git a/src/map/npc.c b/src/map/npc.c index 84a2446ad..44df2fe7a 100644 --- a/src/map/npc.c +++ b/src/map/npc.c @@ -56,6 +56,9 @@ struct npc_path_data *npc_last_npd; static struct view_data npc_viewdb[MAX_NPC_CLASS]; static struct view_data npc_viewdb2[MAX_NPC_CLASS2_END-MAX_NPC_CLASS2_START]; +/* for speedup */ +unsigned int npc_market_qty[MAX_INVENTORY]; + static struct script_event_s { //Holds pointers to the commonly executed scripts for speedup. [Skotlex] struct event_data *event[UCHAR_MAX]; @@ -1150,8 +1153,10 @@ int npc_click(struct map_session_data* sd, struct npc_data* nd) } if(!nd) return 1; + if ((nd = npc->checknear(sd,&nd->bl)) == NULL) return 1; + //Hidden/Disabled npc. if (nd->class_ < 0 || nd->option&(OPTION_INVISIBLE|OPTION_HIDE)) return 1; @@ -1164,7 +1169,11 @@ int npc_click(struct map_session_data* sd, struct npc_data* nd) clif->cashshop_show(sd,nd); break; case SCRIPT: - script->run(nd->u.scr.script,0,sd->bl.id,nd->bl.id); + if( nd->u.scr.shop && nd->u.scr.shop->items && nd->u.scr.trader ) { + if( !npc->trader_open(sd,nd) ) + return 1; + } else + script->run(nd->u.scr.script,0,sd->bl.id,nd->bl.id); break; case TOMB: npc->run_tomb(sd,nd); @@ -1231,16 +1240,22 @@ int npc_buysellsel(struct map_session_data* sd, int id, int type) { if ((nd = npc->checknear(sd,map->id2bl(id))) == NULL) return 1; - if (nd->subtype!=SHOP) { - ShowError("no such shop npc : %d\n",id); + if ( nd->subtype != SHOP && !(nd->subtype == SCRIPT && nd->u.scr.shop && nd->u.scr.shop->items) ) { + + if( nd->subtype == SCRIPT ) + ShowError("npc_buysellsel: trader '%s' has no shop list!\n",nd->exname); + else + ShowError("npc_buysellsel: no such shop npc %d (%s)\n",id,nd->exname); + if (sd->npc_id == id) - sd->npc_id=0; + sd->npc_id = 0; return 1; } - if (nd->option & OPTION_INVISIBLE) // can't buy if npc is not visible (hack?) + + if (nd->option & OPTION_INVISIBLE) // can't buy if npc is not visible (hack?) return 1; - if( nd->class_ < 0 && !sd->state.callshop ) - {// not called through a script and is not a visible NPC so an invalid call + + if( nd->class_ < 0 && !sd->state.callshop ) {// not called through a script and is not a visible NPC so an invalid call return 1; } @@ -1253,6 +1268,7 @@ int npc_buysellsel(struct map_session_data* sd, int id, int type) { } else { clif->selllist(sd); } + return 0; } @@ -1261,14 +1277,33 @@ int npc_buysellsel(struct map_session_data* sd, int id, int type) { *------------------------------------------*/ int npc_cashshop_buylist(struct map_session_data *sd, int points, int count, unsigned short* item_list) { int i, j, nameid, amount, new_, w, vt; - struct npc_data *nd = (struct npc_data *)map->id2bl(sd->npc_shopid); - - if( !nd || nd->subtype != CASHSHOP ) - return 1; + struct npc_data *nd = NULL; + struct npc_item_list *shop = NULL; + unsigned short shop_size = 0; if( sd->state.trading ) return 4; + if( count <= 0 ) + return 5; + + if( points < 0 ) + return 6; + + if( !(nd = (struct npc_data *)map->id2bl(sd->npc_shopid)) ) + return 1; + + if( nd->subtype != CASHSHOP ) { + if( nd->subtype == SCRIPT && nd->u.scr.shop && nd->u.scr.shop->type != NST_ZENY && nd->u.scr.shop->type != NST_MARKET ) { + shop = nd->u.scr.shop->item; + shop_size = nd->u.scr.shop->items; + } else + return 1; + } else { + shop = nd->u.shop.shop_item; + shop_size = nd->u.shop.count; + } + new_ = 0; w = 0; vt = 0; // Global Value @@ -1281,12 +1316,13 @@ int npc_cashshop_buylist(struct map_session_data *sd, int points, int count, uns if( !itemdb->exists(nameid) || amount <= 0 ) return 5; - ARR_FIND(0,nd->u.shop.count,j,nd->u.shop.shop_item[j].nameid == nameid); - if( j == nd->u.shop.count || nd->u.shop.shop_item[j].value <= 0 ) + ARR_FIND(0,shop_size,j,shop[j].nameid == nameid); + if( j == shop_size || shop[j].value <= 0 ) return 5; if( !itemdb->isstackable(nameid) && amount > 1 ) { - ShowWarning("Player %s (%d:%d) sent a hexed packet trying to buy %d of nonstackable item %d!\n", sd->status.name, sd->status.account_id, sd->status.char_id, amount, nameid); + ShowWarning("Player %s (%d:%d) sent a hexed packet trying to buy %d of nonstackable item %d!\n", + sd->status.name, sd->status.account_id, sd->status.char_id, amount, nameid); amount = item_list[i*2+0] = 1; } @@ -1298,21 +1334,27 @@ int npc_cashshop_buylist(struct map_session_data *sd, int points, int count, uns return 3; } - vt += nd->u.shop.shop_item[j].value * amount; + vt += shop[j].value * amount; w += itemdb_weight(nameid) * amount; } if( w + sd->weight > sd->max_weight ) return 3; + if( pc->inventoryblank(sd) < new_ ) return 3; + if( points > vt ) points = vt; // Payment Process ---------------------------------------------------- - if( sd->kafraPoints < points || sd->cashPoints < (vt - points) ) - return 6; - pc->paycash(sd,vt,points); - + if( nd->subtype == SCRIPT && nd->u.scr.shop->type == NST_CUSTOM ) { + if( !npc->trader_pay(nd,sd,vt,points) ) + return 6; + } else { + if( sd->kafraPoints < points || sd->cashPoints < (vt - points) ) + return 6; + pc->paycash(sd,vt,points); + } // Delivery Process ---------------------------------------------------- for( i = 0; i < count; i++ ) { struct item item_tmp; @@ -1356,45 +1398,257 @@ int npc_buylist_sub(struct map_session_data* sd, int n, unsigned short* item_lis return 0; } +/** + * Loads persistent NPC Market Data from SQL + **/ +void npc_market_fromsql(void) { + SqlStmt* stmt = SQL->StmtMalloc(map->mysql_handle); + char name[NAME_LENGTH+1]; + int itemid; + int amount; + + /* TODO inter-server.conf npc_market_data */ + if ( SQL_ERROR == SQL->StmtPrepare(stmt, "SELECT `name`, `itemid`, `amount` FROM `npc_market_data`") + || SQL_ERROR == SQL->StmtExecute(stmt) + ) { + SqlStmt_ShowDebug(stmt); + SQL->StmtFree(stmt); + return; + } + + SQL->StmtBindColumn(stmt, 0, SQLDT_STRING, &name[0], sizeof(name), NULL, NULL); + SQL->StmtBindColumn(stmt, 1, SQLDT_INT, &itemid, 0, NULL, NULL); + SQL->StmtBindColumn(stmt, 2, SQLDT_INT, &amount, 0, NULL, NULL); + + while ( SQL_SUCCESS == SQL->StmtNextRow(stmt) ) { + struct npc_data *nd = NULL; + unsigned short i; + + if( !(nd = npc->name2id(name)) ) { + ShowError("npc_market_fromsql: NPC '%s' not found! skipping...\n",name); + continue; + } else if ( nd->subtype != SCRIPT || !nd->u.scr.shop || !nd->u.scr.shop->items || nd->u.scr.shop->type != NST_MARKET ) { + ShowError("npc_market_fromsql: NPC '%s' is not proper for market, skipping...\n",name); + continue; + } + + for(i = 0; i < nd->u.scr.shop->items; i++) { + if( nd->u.scr.shop->item[i].nameid == itemid ) { + nd->u.scr.shop->item[i].qty = amount; + break; + } + } + + if( i == nd->u.scr.shop->items ) { + ShowError("npc_market_fromsql: NPC '%s' does not sell item %d (qty %d), deleting...\n",name,itemid,amount); + /* TODO inter-server.conf npc_market_data */ + if( SQL_ERROR == SQL->Query(map->mysql_handle, "DELETE FROM `npc_market_data` WHERE `name`='%s' AND `itemid`='%d' LIMIT 1", name,itemid) ) + Sql_ShowDebug(map->mysql_handle); + continue; + } + + } + + SQL->StmtFree(stmt); +} +/** + * Saves persistent NPC Market Data into SQL + **/ +void npc_market_tosql(struct npc_data *nd, unsigned short index) { + /* TODO inter-server.conf npc_market_data */ + if( SQL_ERROR == SQL->Query(map->mysql_handle, "REPLACE INTO `npc_market_data` VALUES ('%s','%d','%d')", nd->exname, nd->u.scr.shop->item[index].nameid, nd->u.scr.shop->item[index].qty) ) + Sql_ShowDebug(map->mysql_handle); +} +/** + * Removes persistent NPC Market Data from SQL + **/ +void npc_market_delfromsql(struct npc_data *nd, unsigned short index) { + /* TODO inter-server.conf npc_market_data */ + if( index == USHRT_MAX ) { + if( SQL_ERROR == SQL->Query(map->mysql_handle, "DELETE FROM `npc_market_data` WHERE `name`='%s'", nd->exname) ) + Sql_ShowDebug(map->mysql_handle); + } else { + if( SQL_ERROR == SQL->Query(map->mysql_handle, "DELETE FROM `npc_market_data` WHERE `name`='%s' AND `itemid`='%d' LIMIT 1", nd->exname, nd->u.scr.shop->item[index].nameid) ) + Sql_ShowDebug(map->mysql_handle); + } +} +/** + * Judges whether to allow and spawn a trader's window. + **/ +bool npc_trader_open(struct map_session_data *sd, struct npc_data *nd) { + + if( !nd->u.scr.shop || !nd->u.scr.shop->items ) + return false; + + switch( nd->u.scr.shop->type ) { + case NST_ZENY: + sd->state.callshop = 1; + npc->buysellsel(sd,nd->bl.id,0); + break; + case NST_MARKET: { + unsigned short i; + + for(i = 0; i < nd->u.scr.shop->items; i++) { + if( nd->u.scr.shop->item[i].qty ) + break; + } + + /* nothing to display, no items available */ + if( i == nd->u.scr.shop->items ) { + clif->colormes(sd->fd,COLOR_RED,"Shop is out of stock! Come again later!");/* TODO messages.conf-it */ + return false; + } + clif->npc_market_open(sd,nd); + } + break; + default: + clif->cashshop_show(sd,nd); + break; + } + + sd->npc_shopid = nd->bl.id; + + return true; +} +/** + * Creates (npc_data)->u.scr.shop and updates all duplicates across the server to match the created pointer + * + * @param master id of the original npc + **/ +void npc_trader_update(int master) { + DBIterator* iter; + struct block_list* bl; + struct npc_data *master_nd = map->id2nd(master); + + CREATE(master_nd->u.scr.shop,struct npc_shop_data,1); + + iter = db_iterator(map->id_db); + + for( bl = (struct block_list*)dbi_first(iter); dbi_exists(iter); bl = (struct block_list*)dbi_next(iter) ) { + if( bl->type == BL_NPC ) { + struct npc_data* nd = (struct npc_data*)bl; + + if( nd->src_id == master ) { + nd->u.scr.shop = master_nd->u.scr.shop; + } + } + } + + dbi_destroy(iter); +} +/** + * Tries to issue a CountFunds event to the shop. + * + * @param nd shop + * @param sd player + **/ +void npc_trader_count_funds(struct npc_data *nd, struct map_session_data *sd) { + char evname[EVENT_NAME_LENGTH]; + struct event_data *ev = NULL; + + npc->trader_funds[0] = npc->trader_funds[1] = 0;/* clear */ + + switch( nd->u.scr.shop->type ) { + case NST_CASH: + npc->trader_funds[0] = sd->cashPoints; + npc->trader_funds[1] = sd->kafraPoints; + return; + case NST_CUSTOM: + break; + default: + ShowError("npc_trader_count_funds: unsupported shop type %d\n",nd->u.scr.shop->type); + return; + } + + snprintf(evname, EVENT_NAME_LENGTH, "%s::OnCountFunds",nd->exname); + + if ( (ev = strdb_get(npc->ev_db, evname)) ) + script->run(ev->nd->u.scr.script, ev->pos, sd->bl.id, ev->nd->bl.id); + else + ShowError("npc_trader_count_funds: '%s' event '%s' not found, operation failed\n",nd->exname,evname); + + /* the callee will rely on npc->trader_funds, upon success script->run updates them */ +} +/** + * Tries to issue a payment to the NPC Event capable of handling it + * + * @param nd shop + * @param sd player + * @param price total cost + * @param points the amount input in the shop by the user to use from the secondary currency (if any is being employed) + * + * @return bool whether it was successful (if the script does not respond it will fail) + **/ +bool npc_trader_pay(struct npc_data *nd, struct map_session_data *sd, int price, int points) { + char evname[EVENT_NAME_LENGTH]; + struct event_data *ev = NULL; + + npc->trader_ok = false;/* clear */ + + snprintf(evname, EVENT_NAME_LENGTH, "%s::OnPayFunds",nd->exname); + + if ( (ev = strdb_get(npc->ev_db, evname)) ) { + pc->setreg(sd,script->add_str("@price"),price); + pc->setreg(sd,script->add_str("@points"),points); + + script->run(ev->nd->u.scr.script, ev->pos, sd->bl.id, ev->nd->bl.id); + } else + ShowError("npc_trader_pay: '%s' event '%s' not found, operation failed\n",nd->exname,evname); + + return npc->trader_ok;/* run script will deal with it */ +} /*========================================== * Cash Shop Buy *------------------------------------------*/ int npc_cashshop_buy(struct map_session_data *sd, int nameid, int amount, int points) { - struct npc_data *nd = (struct npc_data *)map->id2bl(sd->npc_shopid); + struct npc_data *nd = NULL; struct item_data *item; + struct npc_item_list *shop = NULL; int i, price, w; - + unsigned short shop_size = 0; + if( amount <= 0 ) return 5; if( points < 0 ) return 6; - if( !nd || nd->subtype != CASHSHOP ) - return 1; - if( sd->state.trading ) return 4; + + if( !(nd = (struct npc_data *)map->id2bl(sd->npc_shopid)) ) + return 1; if( (item = itemdb->exists(nameid)) == NULL ) return 5; // Invalid Item - ARR_FIND(0, nd->u.shop.count, i, nd->u.shop.shop_item[i].nameid == nameid); - if( i == nd->u.shop.count ) + if( nd->subtype != CASHSHOP ) { + if( nd->subtype == SCRIPT && nd->u.scr.shop && nd->u.scr.shop->type != NST_ZENY && nd->u.scr.shop->type != NST_MARKET ) { + shop = nd->u.scr.shop->item; + shop_size = nd->u.scr.shop->items; + } else + return 1; + } else { + shop = nd->u.shop.shop_item; + shop_size = nd->u.shop.count; + } + + ARR_FIND(0, shop_size, i, shop[i].nameid == nameid); + + if( i == shop_size ) return 5; - if( nd->u.shop.shop_item[i].value <= 0 ) + + if( shop[i].value <= 0 ) return 5; - if(!itemdb->isstackable(nameid) && amount > 1) - { + if(!itemdb->isstackable(nameid) && amount > 1) { ShowWarning("Player %s (%d:%d) sent a hexed packet trying to buy %d of nonstackable item %d!\n", sd->status.name, sd->status.account_id, sd->status.char_id, amount, nameid); amount = 1; } - switch( pc->checkadditem(sd, nameid, amount) ) - { + switch( pc->checkadditem(sd, nameid, amount) ) { case ADDITEM_NEW: if( pc->inventoryblank(sd) == 0 ) return 3; @@ -1407,26 +1661,31 @@ int npc_cashshop_buy(struct map_session_data *sd, int nameid, int amount, int po if( w + sd->weight > sd->max_weight ) return 3; - if( (double)nd->u.shop.shop_item[i].value * amount > INT_MAX ) { + if( (double)shop[i].value * amount > INT_MAX ) { ShowWarning("npc_cashshop_buy: Item '%s' (%d) price overflow attempt!\n", item->name, nameid); ShowDebug("(NPC:'%s' (%s,%d,%d), player:'%s' (%d/%d), value:%d, amount:%d)\n", nd->exname, map->list[nd->bl.m].name, nd->bl.x, nd->bl.y, sd->status.name, sd->status.account_id, sd->status.char_id, - nd->u.shop.shop_item[i].value, amount); + shop[i].value, amount); return 5; } - price = nd->u.shop.shop_item[i].value * amount; + price = shop[i].value * amount; + if( points > price ) points = price; - if( (sd->kafraPoints < points) || (sd->cashPoints < price - points) ) - return 6; - - pc->paycash(sd, price, points); + if( nd->subtype == SCRIPT && nd->u.scr.shop->type == NST_CUSTOM ) { + if( !npc->trader_pay(nd,sd,price,points) ) + return 6; + } else { + if( (sd->kafraPoints < points) || (sd->cashPoints < price - points) ) + return 6; + + pc->paycash(sd, price, points); + } - if( !pet->create_egg(sd, nameid) ) - { + if( !pet->create_egg(sd, nameid) ) { struct item item_tmp; memset(&item_tmp, 0, sizeof(struct item)); item_tmp.nameid = nameid; @@ -1444,104 +1703,115 @@ int npc_cashshop_buy(struct map_session_data *sd, int nameid, int amount, int po /// @return result code for clif->parse_NpcBuyListSend int npc_buylist(struct map_session_data* sd, int n, unsigned short* item_list) { struct npc_data* nd; + struct npc_item_list *shop = NULL; double z; int i,j,w,skill_t,new_, idx = skill->get_index(MC_DISCOUNT); - + unsigned short shop_size = 0; + nullpo_retr(3, sd); nullpo_retr(3, item_list); - + nd = npc->checknear(sd,map->id2bl(sd->npc_shopid)); if( nd == NULL ) return 3; - if( nd->subtype != SHOP ) - return 3; - + + if( nd->subtype != SHOP ) { + if( nd->subtype == SCRIPT && nd->u.scr.shop && nd->u.scr.shop->type == NST_ZENY ) { + shop = nd->u.scr.shop->item; + shop_size = nd->u.scr.shop->items; + } else + return 3; + } else { + shop = nd->u.shop.shop_item; + shop_size = nd->u.shop.count; + } + z = 0; w = 0; new_ = 0; // process entries in buy list, one by one for( i = 0; i < n; ++i ) { int nameid, amount, value; - + // find this entry in the shop's sell list - ARR_FIND( 0, nd->u.shop.count, j, - item_list[i*2+1] == nd->u.shop.shop_item[j].nameid || //Normal items - item_list[i*2+1] == itemdb_viewid(nd->u.shop.shop_item[j].nameid) //item_avail replacement - ); - - if( j == nd->u.shop.count ) + ARR_FIND( 0, shop_size, j, + item_list[i*2+1] == shop[j].nameid || //Normal items + item_list[i*2+1] == itemdb_viewid(shop[j].nameid) //item_avail replacement + ); + + if( j == shop_size ) return 3; // no such item in shop - + amount = item_list[i*2+0]; - nameid = item_list[i*2+1] = nd->u.shop.shop_item[j].nameid; //item_avail replacement - value = nd->u.shop.shop_item[j].value; - + nameid = item_list[i*2+1] = shop[j].nameid; //item_avail replacement + value = shop[j].value; + if( !itemdb->exists(nameid) ) return 3; // item no longer in itemdb - + if( !itemdb->isstackable(nameid) && amount > 1 ) { //Exploit? You can't buy more than 1 of equipment types o.O ShowWarning("Player %s (%d:%d) sent a hexed packet trying to buy %d of nonstackable item %d!\n", - sd->status.name, sd->status.account_id, sd->status.char_id, amount, nameid); + sd->status.name, sd->status.account_id, sd->status.char_id, amount, nameid); amount = item_list[i*2+0] = 1; } - + if( nd->master_nd ) { // Script-controlled shops decide by themselves, what can be bought and for what price. continue; } - + switch( pc->checkadditem(sd,nameid,amount) ) { case ADDITEM_EXIST: break; - + case ADDITEM_NEW: new_++; break; - + case ADDITEM_OVERAMOUNT: return 2; } - + value = pc->modifybuyvalue(sd,value); - + z += (double)value * amount; w += itemdb_weight(nameid) * amount; } - + if( nd->master_nd != NULL ) //Script-based shops. return npc->buylist_sub(sd,n,item_list,nd->master_nd); - + if( z > (double)sd->status.zeny ) return 1; // Not enough Zeny if( w + sd->weight > sd->max_weight ) return 2; // Too heavy if( pc->inventoryblank(sd) < new_ ) return 3; // Not enough space to store items - + pc->payzeny(sd,(int)z,LOG_TYPE_NPC, NULL); - + for( i = 0; i < n; ++i ) { int nameid = item_list[i*2+1]; int amount = item_list[i*2+0]; struct item item_tmp; - + if (itemdb_type(nameid) == IT_PETEGG) pet->create_egg(sd, nameid); else { memset(&item_tmp,0,sizeof(item_tmp)); item_tmp.nameid = nameid; item_tmp.identify = 1; - + pc->additem(sd,&item_tmp,amount,LOG_TYPE_NPC); } } - + // custom merchant shop exp bonus if( battle_config.shop_exp > 0 && z > 0 && (skill_t = pc->checkskill2(sd,idx)) > 0 ) { if( sd->status.skill[idx].flag >= SKILL_FLAG_REPLACED_LV_0 ) skill_t = sd->status.skill[idx].flag - SKILL_FLAG_REPLACED_LV_0; - + if( skill_t > 0 ) { z = z * (double)skill_t * (double)battle_config.shop_exp/10000.; if( z < 1 ) @@ -1549,10 +1819,120 @@ int npc_buylist(struct map_session_data* sd, int n, unsigned short* item_list) { pc->gainexp(sd,NULL,0,(int)z, false); } } - + return 0; } +/** + * parses incoming npc market purchase list + **/ +int npc_market_buylist(struct map_session_data* sd, unsigned short list_size, struct packet_npc_market_purchase *p) { + struct npc_data* nd; + struct npc_item_list *shop = NULL; + double z; + int i,j,w,new_; + unsigned short shop_size = 0; + + nullpo_retr(1, sd); + nullpo_retr(1, p); + + nd = npc->checknear(sd,map->id2bl(sd->npc_shopid)); + + if( nd == NULL || nd->subtype != SCRIPT || !list_size || !nd->u.scr.shop || nd->u.scr.shop->type != NST_MARKET ) + return 1; + + shop = nd->u.scr.shop->item; + shop_size = nd->u.scr.shop->items; + + z = 0; + w = 0; + new_ = 0; + + // process entries in buy list, one by one + for( i = 0; i < list_size; ++i ) { + int nameid, amount, value; + + // find this entry in the shop's sell list + ARR_FIND( 0, shop_size, j, + p->list[i].ITID == shop[j].nameid || //Normal items + p->list[i].ITID == itemdb_viewid(shop[j].nameid) //item_avail replacement + ); + + if( j == shop_size ) /* TODO find official response for this */ + return 1; // no such item in shop + + if( p->list[i].qty > shop[j].qty ) + return 1; + + amount = p->list[i].qty; + nameid = p->list[i].ITID = shop[j].nameid; //item_avail replacement + value = shop[j].value; + npc_market_qty[i] = j; + + if( !itemdb->exists(nameid) ) /* TODO find official response for this */ + return 1; // item no longer in itemdb + + if( !itemdb->isstackable(nameid) && amount > 1 ) { + //Exploit? You can't buy more than 1 of equipment types o.O + ShowWarning("Player %s (%d:%d) sent a hexed packet trying to buy %d of nonstackable item %d!\n", + sd->status.name, sd->status.account_id, sd->status.char_id, amount, nameid); + amount = p->list[i].qty = 1; + } + + switch( pc->checkadditem(sd,nameid,amount) ) { + case ADDITEM_EXIST: + break; + + case ADDITEM_NEW: + new_++; + break; + + case ADDITEM_OVERAMOUNT: /* TODO find official response for this */ + return 1; + } + + z += (double)value * amount; + w += itemdb_weight(nameid) * amount; + } + + if( z > (double)sd->status.zeny ) /* TODO find official response for this */ + return 1; // Not enough Zeny + + if( w + sd->weight > sd->max_weight ) /* TODO find official response for this */ + return 1; // Too heavy + + if( pc->inventoryblank(sd) < new_ ) /* TODO find official response for this */ + return 1; // Not enough space to store items + + pc->payzeny(sd,(int)z,LOG_TYPE_NPC, NULL); + + for( i = 0; i < list_size; ++i ) { + int nameid = p->list[i].ITID; + int amount = p->list[i].qty; + struct item item_tmp; + + j = npc_market_qty[i]; + + if( p->list[i].qty > shop[j].qty ) /* wohoo someone tampered with the packet. */ + return 1; + + shop[j].qty -= amount; + + npc->market_tosql(nd,j); + + if (itemdb_type(nameid) == IT_PETEGG) + pet->create_egg(sd, nameid); + else { + memset(&item_tmp,0,sizeof(item_tmp)); + item_tmp.nameid = nameid; + item_tmp.identify = 1; + + pc->additem(sd,&item_tmp,amount,LOG_TYPE_NPC); + } + } + + return 0; +} /// npc_selllist for script-controlled shops int npc_selllist_sub(struct map_session_data* sd, int n, unsigned short* item_list, struct npc_data* nd) @@ -1844,6 +2224,11 @@ int npc_unload(struct npc_data* nd, bool single) { nd->u.scr.label_list = NULL; nd->u.scr.label_list_num = 0; } + if(nd->u.scr.shop) { + if(nd->u.scr.shop->item) + aFree(nd->u.scr.shop->item); + aFree(nd->u.scr.shop); + } } if( nd->u.scr.guild_id ) guild->flag_remove(nd); @@ -2395,7 +2780,7 @@ const char* npc_skip_script(const char* start, const char* buffer, const char* f /// -%TAB%script%TAB%<NPC Name>%TAB%-1,{<code>} /// <map name>,<x>,<y>,<facing>%TAB%script%TAB%<NPC Name>%TAB%<sprite id>,{<code>} /// <map name>,<x>,<y>,<facing>%TAB%script%TAB%<NPC Name>%TAB%<sprite id>,<triggerX>,<triggerY>,{<code>} -const char* npc_parse_script(char* w1, char* w2, char* w3, char* w4, const char* start, const char* buffer, const char* filepath, bool runOnInit) { +const char* npc_parse_script(char* w1, char* w2, char* w3, char* w4, const char* start, const char* buffer, const char* filepath, int options) { int x, y, dir = 0, m, xs = 0, ys = 0; // [Valaris] thanks to fov char mapname[32]; struct script_code *scriptroot; @@ -2466,7 +2851,10 @@ const char* npc_parse_script(char* w1, char* w2, char* w3, char* w4, const char* nd->u.scr.script = scriptroot; nd->u.scr.label_list = label_list; nd->u.scr.label_list_num = label_list_num; - + if( options&NPO_TRADER ) + nd->u.scr.trader = true; + nd->u.scr.shop = NULL; + ++npc_script; nd->bl.type = BL_NPC; nd->subtype = SCRIPT; @@ -2500,7 +2888,7 @@ const char* npc_parse_script(char* w1, char* w2, char* w3, char* w4, const char* nd->u.scr.timerid = INVALID_TIMER; - if( runOnInit ) { + if( options&NPO_ONINIT ) { char evname[EVENT_NAME_LENGTH]; struct event_data *ev; @@ -2604,6 +2992,8 @@ const char* npc_parse_duplicate(char* w1, char* w2, char* w3, char* w4, const ch nd->u.scr.script = dnd->u.scr.script; nd->u.scr.label_list = dnd->u.scr.label_list; nd->u.scr.label_list_num = dnd->u.scr.label_list_num; + nd->u.scr.shop = dnd->u.scr.shop; + nd->u.scr.trader = dnd->u.scr.trader; break; case SHOP: @@ -3656,9 +4046,12 @@ int npc_parsesrcfile(const char* filepath, bool runOnInit) { #ifdef ENABLE_CASE_CHECK if( strcasecmp(w1, "function") == 0 ) DeprecationWarning("npc_parsesrcfile", w1, "function", filepath, strline(buffer, p-buffer)); // TODO #endif // ENABLE_CASE_CHECK - p = npc->parse_script(w1,w2,w3,w4, p, buffer, filepath,runOnInit); + p = npc->parse_script(w1,w2,w3,w4, p, buffer, filepath,runOnInit?NPO_ONINIT:NPO_NONE); } } + else if( strcmp(w2,"trader") == 0 && count > 3 ) { + p = npc->parse_script(w1,w2,w3,w4, p, buffer, filepath,(runOnInit?NPO_ONINIT:NPO_NONE)|NPO_TRADER); + } else if( (i=0, sscanf(w2,"duplicate%n",&i), (i > 0 && w2[i] == '(')) && count > 3 ) { p = npc->parse_duplicate(w1,w2,w3,w4, p, buffer, filepath); @@ -3678,6 +4071,7 @@ int npc_parsesrcfile(const char* filepath, bool runOnInit) { else if( strcasecmp(w2,"shop") == 0 ) { DeprecationWarning("npc_parsesrcfile", w2, "shop", filepath, strline(buffer, p-buffer)); } // TODO else if( strcasecmp(w2,"cashshop") == 0 ) { DeprecationWarning("npc_parsesrcfile", w2, "cashshop", filepath, strline(buffer, p-buffer)); } // TODO else if( strcasecmp(w2, "script") == 0 ) { DeprecationWarning("npc_parsesrcfile", w2, "script", filepath, strline(buffer, p-buffer)); } // TODO + else if( strcasecmp(w2,"trader") == 0 ) DeprecationWarning("npc_parsesrcfile", w2, "trader", filepath, strline(buffer, p-buffer)) // TODO else if( strncasecmp(w2, "duplicate", 9) == 0 ) { char temp[10]; safestrncpy(temp, w2, 10); @@ -3871,7 +4265,7 @@ int npc_reload(void) { "\t-'"CL_WHITE"%d"CL_RESET"' Mobs Cached\n" "\t-'"CL_WHITE"%d"CL_RESET"' Mobs Not Cached\n", npc_id - npc_new_min, npc_warp, npc_shop, npc_script, npc_mob, npc_cache_mob, npc_delay_mob); - + itemdb->name_constants(); instance->reload(); @@ -3890,6 +4284,8 @@ int npc_reload(void) { //Execute the OnInit event for freshly loaded npcs. [Skotlex] ShowStatus("Event '"CL_WHITE"OnInit"CL_RESET"' executed with '"CL_WHITE"%d"CL_RESET"' NPCs.\n",npc->event_doall("OnInit")); + npc->market_fromsql();/* after OnInit */ + // Execute rest of the startup events if connected to char-server. [Lance] if(!intif->CheckForCharServer()){ ShowStatus("Event '"CL_WHITE"OnInterIfInit"CL_RESET"' executed with '"CL_WHITE"%d"CL_RESET"' NPCs.\n", npc->event_doall("OnInterIfInit")); @@ -4024,7 +4420,7 @@ int do_init_npc(bool minimal) { "\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); } - + itemdb->name_constants(); if (!minimal) { @@ -4076,6 +4472,9 @@ void npc_defaults(void) { npc->fake_nd = NULL; npc->src_files = NULL; /* */ + npc->trader_ok = false; + npc->trader_funds[0] = npc->trader_funds[1] = 0; + /* */ npc->init = do_init_npc; npc->final = do_final_npc; /* */ @@ -4165,4 +4564,13 @@ void npc_defaults(void) { npc->debug_warps_sub = npc_debug_warps_sub; npc->debug_warps = npc_debug_warps; npc->secure_timeout_timer = npc_rr_secure_timeout_timer; + /* */ + npc->trader_count_funds = npc_trader_count_funds; + npc->trader_pay = npc_trader_pay; + npc->trader_update = npc_trader_update; + npc->market_buylist = npc_market_buylist; + npc->trader_open = npc_trader_open; + npc->market_fromsql = npc_market_fromsql; + npc->market_tosql = npc_market_tosql; + npc->market_delfromsql = npc_market_delfromsql; } diff --git a/src/map/npc.h b/src/map/npc.h index feee8f203..792d85d59 100644 --- a/src/map/npc.h +++ b/src/map/npc.h @@ -14,6 +14,21 @@ struct block_list; struct npc_data; struct view_data; +enum npc_parse_options { + NPO_NONE = 0x0, + NPO_ONINIT = 0x1, + NPO_TRADER = 0x2, +}; + +enum npc_shop_types { + NST_ZENY,/* default */ + NST_CASH,/* official npc cash shop */ + NST_MARKET,/* official npc market type */ + NST_CUSTOM, + /* */ + NST_MAX, +}; + struct npc_timerevent_list { int timer,pos; }; @@ -22,9 +37,15 @@ struct npc_label_list { int pos; }; struct npc_item_list { - unsigned int nameid,value; + unsigned short nameid; + unsigned int value; + unsigned int qty; +}; +struct npc_shop_data { + unsigned char type;/* what am i */ + struct npc_item_list *item;/* list */ + unsigned short items;/* total */ }; - struct npc_data { struct block_list bl; struct unit_data *ud; @@ -60,10 +81,13 @@ struct npc_data { struct npc_timerevent_list *timer_event; int label_list_num; struct npc_label_list *label_list; + /* */ + struct npc_shop_data *shop; + bool trader; } scr; - struct { + struct { /* TODO duck this as soon as the new shop formatting is deemed stable */ struct npc_item_list* shop_item; - int count; + unsigned short count; } shop; struct { short xs,ys; // OnTouch area radius @@ -143,6 +167,9 @@ struct npc_interface { struct npc_data *fake_nd; struct npc_src_list *src_files; struct unit_data base_ud; + /* npc trader global data, for ease of transition between the script, cleared on every usage */ + bool trader_ok; + int trader_funds[2]; /* */ int (*init) (bool minimal); int (*final) (void); @@ -208,7 +235,7 @@ struct npc_interface { const char* (*parse_shop) (char *w1, char *w2, char *w3, char *w4, const char *start, const char *buffer, const char *filepath); void (*convertlabel_db) (struct npc_label_list *label_list, const char *filepath); const char* (*skip_script) (const char *start, const char *buffer, const char *filepath); - const char* (*parse_script) (char *w1, char *w2, char *w3, char *w4, const char *start, const char *buffer, const char *filepath, bool runOnInit); + const char* (*parse_script) (char *w1, char *w2, char *w3, char *w4, const char *start, const char *buffer, const char *filepath, int options); const char* (*parse_duplicate) (char *w1, char *w2, char *w3, char *w4, const char *start, const char *buffer, const char *filepath); int (*duplicate4instance) (struct npc_data *snd, int16 m); void (*setcells) (struct npc_data *nd); @@ -232,6 +259,15 @@ struct npc_interface { void (*do_clear_npc) (void); void (*debug_warps_sub) (struct npc_data *nd); void (*debug_warps) (void); + /* */ + void (*trader_count_funds) (struct npc_data *nd, struct map_session_data *sd); + bool (*trader_pay) (struct npc_data *nd, struct map_session_data *sd, int price, int points); + void (*trader_update) (int master); + int (*market_buylist) (struct map_session_data* sd, unsigned short list_size, struct packet_npc_market_purchase *p); + bool (*trader_open) (struct map_session_data *sd, struct npc_data *nd); + void (*market_fromsql) (void); + void (*market_tosql) (struct npc_data *nd, unsigned short index); + void (*market_delfromsql) (struct npc_data *nd, unsigned short index); /** * For the Secure NPC Timeout option (check config/Secure.h) [RR] **/ diff --git a/src/map/packets.h b/src/map/packets.h index 08c73fdb0..cea916f6d 100644 --- a/src/map/packets.h +++ b/src/map/packets.h @@ -2453,6 +2453,45 @@ packet(0x020d,-1); packet(0x0887,36,clif->pStoragePassword,0); #endif +// 2013-12-23cRagexe - Yommy +#if PACKETVER >= 20131223 + packet(0x0369,7,clif->pActionRequest,2,6); + packet(0x083C,10,clif->pUseSkillToId,2,4,6); + packet(0x0437,5,clif->pWalkToXY,2); + packet(0x035F,6,clif->pTickSend,2); + packet(0x0202,5,clif->pChangeDir,2,4); + packet(0x07E4,6,clif->pTakeItem,2); + packet(0x0362,6,clif->pDropItem,2,4); + packet(0x07EC,8,clif->pMoveToKafra,2,4); + packet(0x0364,8,clif->pMoveFromKafra,2,4); + packet(0x0438,10,clif->pUseSkillToPos,2,4,6,8); + packet(0x0366,90,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); + packet(0x096A,6,clif->pGetCharNameRequest,2); + packet(0x0368,6,clif->pSolveCharName,2); + packet(0x0838,12,clif->pSearchStoreInfoListItemClick,2,6,10); + packet(0x0835,2,clif->pSearchStoreInfoNextPage,0); + packet(0x0819,-1,clif->pSearchStoreInfo,2,4,5,9,13,14,15); + packet(0x0811,-1,clif->pReqTradeBuyingStore,2,4,8,12); + packet(0x0360,6,clif->pReqClickBuyingStore,2); + packet(0x0817,2,clif->pReqCloseBuyingStore,0); + packet(0x0815,-1,clif->pReqOpenBuyingStore,2,4,8,9,89); + packet(0x0365,18,clif->pPartyBookingRegisterReq,2,4); + // packet(0x0363,8); // CZ_JOIN_BATTLE_FIELD + packet(0x0281,-1,clif->pItemListWindowSelected,2,4,8); + packet(0x022d,19,clif->pWantToConnection,2,6,10,14,18); + packet(0x0802,26,clif->pPartyInvite2,2); + // packet(0x0436,4); // CZ_GANGSI_RANK + packet(0x023B,26,clif->pFriendsListAdd,2); + packet(0x0361,5,clif->pHomMenu,2,4); + packet(0x08A4,36,clif->pStoragePassword,0); + /* New */ + packet(0x09d4,2,clif->pNPCShopClosed); + packet(0x09ce,102,clif->pGM_Monster_Item,2); + /* NPC Market */ + packet(0x09d8,2,clif->pNPCMarketClosed); + packet(0x09d6,-1,clif->pNPCMarketPurchase); +#endif + /* PacketKeys: http://hercules.ws/board/topic/1105-hercules-wpe-free-june-14th-patch/ */ #if PACKETVER >= 20110817 packetKeys(0x053D5CED,0x3DED6DED,0x6DED6DED); /* Thanks to Shakto */ @@ -2646,6 +2685,10 @@ packet(0x020d,-1); packetKeys(0x7E241DE0,0x5E805580,0x3D807D80); /* Thanks to Shakto */ #endif +#if PACKETVER >= 20131223 + packetKeys(0x631C511C, 0x111C111C,0x111C111C); +#endif + #if defined(OBFUSCATIONKEY1) && defined(OBFUSCATIONKEY2) && defined(OBFUSCATIONKEY3) packetKeys(OBFUSCATIONKEY1,OBFUSCATIONKEY2,OBFUSCATIONKEY3); #endif diff --git a/src/map/packets_struct.h b/src/map/packets_struct.h index df90b35a4..8f0989f3d 100644 --- a/src/map/packets_struct.h +++ b/src/map/packets_struct.h @@ -201,6 +201,8 @@ enum packet_headers { notifybindonequip = 0x2d3, monsterhpType = 0x977, maptypeproperty2Type = 0x99b, + npcmarketresultackType = 0x9d7, + npcmarketopenType = 0x9d5, }; #pragma pack(push, 1) @@ -895,6 +897,48 @@ struct packet_damage { #endif } __attribute__((packed)); +struct packet_gm_monster_item { + short PacketType; +#if PACKETVER >= 20131218 + char str[100]; +#else + char str[24]; +#endif +} __attribute__((packed)); + +struct packet_npc_market_purchase { + short PacketType; + short PacketLength; + struct { + unsigned short ITID; + int qty; + } list[MAX_INVENTORY];/* assuming MAX_INVENTORY is max since you can't hold more than MAX_INVENTORY items thus cant buy that many at once. */ +} __attribute__((packed)); + +struct packet_npc_market_result_ack { + short PacketType; + short PacketLength; + unsigned char result; + struct { + unsigned short ITID; + unsigned short qty; + unsigned int price; + } list[MAX_INVENTORY];/* assuming MAX_INVENTORY is max since you can't hold more than MAX_INVENTORY items thus cant buy that many at once. */ +} __attribute__((packed)); + +struct packet_npc_market_open { + short PacketType; + short PacketLength; + /* inner struct figured by Ind after some annoying hour of debugging (data Thanks to Yommy) */ + struct { + unsigned short nameid; + unsigned char type; + unsigned int price; + unsigned int qty; + unsigned short view; + } list[1000];/* TODO: whats the actual max of this? */ +} __attribute__((packed)); + #pragma pack(pop) #endif /* _PACKETS_STRUCT_H_ */ diff --git a/src/map/script.c b/src/map/script.c index 074348ef0..a9ad69954 100644 --- a/src/map/script.c +++ b/src/map/script.c @@ -2072,7 +2072,7 @@ void script_set_constant2(const char *name, int value, bool isparameter) { int n = script->add_str(name); if( ( script->str_data[n].type == C_NAME || script->str_data[n].type == C_PARAM ) && ( script->str_data[n].val != 0 || script->str_data[n].backpatch != -1 ) ) { // existing parameter or constant - ShowNotice("Conflicting item/script var '%s', prioritising the script var\n",name); + ShowNotice("Conflicting var name '%s', prioritising the script var\n",name); return; } @@ -18012,6 +18012,272 @@ BUILDIN(instance_set_respawn) { return true; } +/** + * @call openshop({NPC Name}); + * + * @return 1 on success, 0 otherwise. + **/ +BUILDIN(openshop) { + struct npc_data *nd; + struct map_session_data *sd; + const char *name = NULL; + + if( script_hasdata(st, 2) ) { + name = script_getstr(st, 2); + if( !(nd = npc->name2id(name)) || nd->subtype != SCRIPT ) { + ShowWarning("buildin_openshop(\"%s\"): trying to run without a proper NPC!\n",name); + return false; + } + } else if( !(nd = map->id2nd(st->oid)) ) { + ShowWarning("buildin_openshop: trying to run without a proper NPC!\n"); + return false; + } + if( !( sd = script->rid2sd(st) ) ) { + ShowWarning("buildin_openshop: trying to run without a player attached!\n"); + return false; + } else if ( !nd->u.scr.shop || !nd->u.scr.shop->items ) { + ShowWarning("buildin_openshop: trying to open without any items!\n"); + return false; + } + + if( !npc->trader_open(sd,nd) ) + script_pushint(st, 0); + else + script_pushint(st, 1); + + return true; +} +/** + * @call sellitem <Item_ID>,{,price{,qty}}; + * + * adds <Item_ID> (or modifies if present) to shop + * if price not provided (or -1) uses the item's value_sell + **/ +BUILDIN(sellitem) { + struct npc_data *nd; + struct item_data *it; + int i = 0, id = script_getnum(st,2); + int value = 0; + int qty = 0; + + if( !(nd = map->id2nd(st->oid)) ) { + ShowWarning("buildin_sellitem: trying to run without a proper NPC!\n"); + return false; + } else if ( !(it = itemdb->exists(id)) ) { + ShowWarning("buildin_sellitem: unknown item id '%d'!\n",id); + return false; + } + + value = script_hasdata(st,3) ? script_getnum(st, 3) : it->value_buy; + if( value == -1 ) + value = it->value_buy; + + if( !nd->u.scr.shop ) + npc->trader_update(nd->src_id?nd->src_id:nd->bl.id); + else {/* no need to run this if its empty */ + for( i = 0; i < nd->u.scr.shop->items; i++ ) { + if( nd->u.scr.shop->item[i].nameid == id ) + break; + } + } + + if( nd->u.scr.shop->type == NST_MARKET ) { + if( !script_hasdata(st,4) || ( qty = script_getnum(st, 4) ) <= 0 ) { + ShowError("buildin_sellitem: invalid 'qty' for market-type shop!\n"); + return false; + } + } + + if( ( nd->u.scr.shop->type == NST_ZENY || nd->u.scr.shop->type == NST_MARKET ) && value*0.75 < it->value_sell*1.24 ) { + ShowWarning("buildin_sellitem: Item %s [%d] discounted buying price (%d->%d) is less than overcharged selling price (%d->%d) in NPC %s (%s)\n", + it->name, id, value, (int)(value*0.75), it->value_sell, (int)(it->value_sell*1.24), nd->exname, nd->path); + } + + if( i != nd->u.scr.shop->items ) { + nd->u.scr.shop->item[i].value = value; + nd->u.scr.shop->item[i].qty = qty; + if( nd->u.scr.shop->type == NST_MARKET ) /* has been manually updated, make it reflect on sql */ + npc->market_tosql(nd,i); + } else { + for( i = 0; i < nd->u.scr.shop->items; i++ ) { + if( nd->u.scr.shop->item[i].nameid == 0 ) + break; + } + + if( i == nd->u.scr.shop->items ) { + if( nd->u.scr.shop->items == USHRT_MAX ) { + ShowWarning("buildin_sellitem: Can't add %s (%s/%s), shop list is full!\n", it->name, nd->exname, nd->path); + return false; + } + i = nd->u.scr.shop->items; + RECREATE(nd->u.scr.shop->item, struct npc_item_list, ++nd->u.scr.shop->items); + } + + nd->u.scr.shop->item[i].nameid = it->nameid; + nd->u.scr.shop->item[i].value = value; + nd->u.scr.shop->item[i].qty = qty; + } + + return true; +} +/** + * @call stopselling <Item_ID>; + * + * removes <Item_ID> from the current npc shop + * + * @return 1 on success, 0 otherwise + **/ +BUILDIN(stopselling) { + struct npc_data *nd; + int i, id = script_getnum(st,2); + + if( !(nd = map->id2nd(st->oid)) || !nd->u.scr.shop ) { + ShowWarning("buildin_stopselling: trying to run without a proper NPC!\n"); + return false; + } + + for( i = 0; i < nd->u.scr.shop->items; i++ ) { + if( nd->u.scr.shop->item[i].nameid == id ) + break; + } + + if( i != nd->u.scr.shop->items ) { + int cursor; + + if( nd->u.scr.shop->type == NST_MARKET ) + npc->market_delfromsql(nd,i); + + nd->u.scr.shop->item[i].nameid = 0; + nd->u.scr.shop->item[i].value = 0; + nd->u.scr.shop->item[i].qty = 0; + + for( i = 0, cursor = 0; i < nd->u.scr.shop->items; i++ ) { + if( nd->u.scr.shop->item[i].nameid == 0 ) + continue; + + if( cursor != i ) { + nd->u.scr.shop->item[cursor].nameid = nd->u.scr.shop->item[i].nameid; + nd->u.scr.shop->item[cursor].value = nd->u.scr.shop->item[i].value; + nd->u.scr.shop->item[cursor].qty = nd->u.scr.shop->item[i].qty; + } + + cursor++; + } + + script_pushint(st, 1); + } else + script_pushint(st, 0); + + return true; +} +/** + * @call setcurrency <Val1>{,<Val2>}; + * + * updates currently-attached player shop currency + **/ +/* setcurrency(<Val1>,{<Val2>}) */ +BUILDIN(setcurrency) { + int val1 = script_getnum(st,2), + val2 = script_hasdata(st, 3) ? script_getnum(st,3) : 0; + struct npc_data *nd; + + if( !(nd = map->id2nd(st->oid)) ) { + ShowWarning("buildin_setcurrency: trying to run without a proper NPC!\n"); + return false; + } + + npc->trader_funds[0] = val1; + npc->trader_funds[1] = val2; + + return true; +} +/** + * @call tradertype(<type>); + * + * defaults to 0, so no need to call when you're doing zeny + * check enum npc_shop_types for list + * cleans shop list on use + **/ +BUILDIN(tradertype) { + int type = script_getnum(st, 2); + struct npc_data *nd; + + if( !(nd = map->id2nd(st->oid)) ) { + ShowWarning("buildin_tradertype: trying to run without a proper NPC!\n"); + return false; + } else if ( type < 0 || type > NST_MAX ) { + ShowWarning("buildin_tradertype: invalid type param %d!\n",type); + return false; + } + + if( !nd->u.scr.shop ) + npc->trader_update(nd->src_id?nd->src_id:nd->bl.id); + else {/* clear list */ + int i; + for( i = 0; i < nd->u.scr.shop->items; i++ ) { + nd->u.scr.shop->item[i].nameid = 0; + nd->u.scr.shop->item[i].value = 0; + nd->u.scr.shop->item[i].qty = 0; + } + npc->market_delfromsql(nd,USHRT_MAX); + } + + nd->u.scr.shop->type = type; + + return true; +} +/** + * @call purchaseok(); + * + * signs the transaction can proceed + **/ +BUILDIN(purchaseok) { + struct npc_data *nd; + + if( !(nd = map->id2nd(st->oid)) || !nd->u.scr.shop ) { + ShowWarning("buildin_purchaseok: trying to run without a proper NPC!\n"); + return false; + } + + npc->trader_ok = true; + + return true; +} +/** + * @call shopcount(<Item_ID>); + * + * @return number of available items in the script's attached shop + **/ +BUILDIN(shopcount) { + struct npc_data *nd; + int id = script_getnum(st, 2); + unsigned short i; + + if( !(nd = map->id2nd(st->oid)) ) { + ShowWarning("buildin_shopcount(%d): trying to run without a proper NPC!\n",id); + return false; + } else if ( !nd->u.scr.shop || !nd->u.scr.shop->items ) { + ShowWarning("buildin_shopcount(%d): trying to use without any items!\n",id); + return false; + } else if ( nd->u.scr.shop->type != NST_MARKET ) { + ShowWarning("buildin_shopcount(%d): trying to use on a non-NST_MARKET shop!\n",id); + return false; + } + + /* lookup */ + for(i = 0; i < nd->u.scr.shop->items; i++) { + if( nd->u.scr.shop->item[i].nameid == id ) { + script_pushint(st, nd->u.scr.shop->item[i].qty); + break; + } + } + + /* didn't find it */ + if( i == nd->u.scr.shop->items ) + script_pushint(st, 0); + + return true; +} // declarations that were supposed to be exported from npc_chat.c #ifdef PCRE_SUPPORT @@ -18609,6 +18875,15 @@ void script_parse_builtin(void) { BUILDIN_DEF(bg_create_team,"sii"), BUILDIN_DEF(bg_join_team,"i?"), BUILDIN_DEF(bg_match_over,"s?"), + + /* New Shop Support */ + BUILDIN_DEF(openshop,"?"), + BUILDIN_DEF(sellitem,"i??"), + BUILDIN_DEF(stopselling,"i"), + BUILDIN_DEF(setcurrency,"i?"), + BUILDIN_DEF(tradertype,"i"), + BUILDIN_DEF(purchaseok,""), + BUILDIN_DEF(shopcount, "i"), }; int i, len = ARRAYLENGTH(BUILDIN); RECREATE(script->buildin, char *, script->buildin_count + len); // Pre-alloc to speed up diff --git a/src/map/status.c b/src/map/status.c index f6ca1ff00..7d354718d 100644 --- a/src/map/status.c +++ b/src/map/status.c @@ -6060,6 +6060,8 @@ void status_set_viewdata(struct block_list *bl, int class_) sd->vd.cloth_color = 0; if( sd->sc.option&OPTION_HANBOK && battle_config.hanbok_ignorepalette ) sd->vd.cloth_color = 0; + if( sd->sc.option&OPTION_OKTOBERFEST /* TODO: config? */ ) + sd->vd.cloth_color = 0; } } else if (vd) memcpy(&sd->vd, vd, sizeof(struct view_data)); @@ -7463,6 +7465,7 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val case SC_XMAS: case SC_SUMMER: case SC_HANBOK: + case SC_OKTOBERFEST: if (!vd) return 0; //Store previous values as they could be removed. unit->stop_attack(bl); @@ -8680,6 +8683,7 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val case SC_XMAS: case SC_SUMMER: case SC_HANBOK: + case SC_OKTOBERFEST: if( !vd ) break; clif->changelook(bl,LOOK_BASE,vd->class_); clif->changelook(bl,LOOK_WEAPON,0); @@ -9067,6 +9071,10 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val case SC_FUSION: sc->option |= OPTION_FLYING; break; + case SC_OKTOBERFEST: + sc->option |= OPTION_OKTOBERFEST; + opt_flag |= 0x4; + break; default: opt_flag = 0; } @@ -9768,167 +9776,171 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const opt_flag = 1; switch(type){ - case SC_STONE: - case SC_FREEZE: - case SC_STUN: - case SC_SLEEP: - case SC_DEEP_SLEEP: - case SC_BURNING: - case SC_WHITEIMPRISON: - case SC_COLD: - sc->opt1 = 0; - break; + case SC_STONE: + case SC_FREEZE: + case SC_STUN: + case SC_SLEEP: + case SC_DEEP_SLEEP: + case SC_BURNING: + case SC_WHITEIMPRISON: + case SC_COLD: + sc->opt1 = 0; + break; - case SC_POISON: - case SC_CURSE: - case SC_SILENCE: - case SC_BLIND: - sc->opt2 &= ~(1<<(type-SC_POISON)); - break; - case SC_DPOISON: - sc->opt2 &= ~OPT2_DPOISON; - break; - case SC_CRUCIS: - sc->opt2 &= ~OPT2_SIGNUMCRUCIS; - break; + case SC_POISON: + case SC_CURSE: + case SC_SILENCE: + case SC_BLIND: + sc->opt2 &= ~(1<<(type-SC_POISON)); + break; + case SC_DPOISON: + sc->opt2 &= ~OPT2_DPOISON; + break; + case SC_CRUCIS: + sc->opt2 &= ~OPT2_SIGNUMCRUCIS; + break; - case SC_HIDING: - sc->option &= ~OPTION_HIDE; - opt_flag|= 2|4; //Check for warp trigger + AoE trigger - break; - case SC_CLOAKING: - case SC_CLOAKINGEXCEED: - case SC__INVISIBILITY: - sc->option &= ~OPTION_CLOAK; - case SC_CAMOUFLAGE: - opt_flag|= 2; - break; - case SC_CHASEWALK: - sc->option &= ~(OPTION_CHASEWALK|OPTION_CLOAK); - opt_flag|= 2; - break; - case SC_SIGHT: - sc->option &= ~OPTION_SIGHT; - break; - case SC_WEDDING: - sc->option &= ~OPTION_WEDDING; - opt_flag |= 0x4; - break; - case SC_XMAS: - sc->option &= ~OPTION_XMAS; - opt_flag |= 0x4; - break; - case SC_SUMMER: - sc->option &= ~OPTION_SUMMER; - opt_flag |= 0x4; - break; - case SC_HANBOK: - sc->option &= ~OPTION_HANBOK; - opt_flag |= 0x4; - break; - case SC_ORCISH: - sc->option &= ~OPTION_ORCISH; - break; - case SC_RUWACH: - sc->option &= ~OPTION_RUWACH; - break; - case SC_FUSION: - sc->option &= ~OPTION_FLYING; - break; - //opt3 - case SC_TWOHANDQUICKEN: - case SC_ONEHANDQUICKEN: - case SC_SPEARQUICKEN: - case SC_CONCENTRATION: - case SC_MER_QUICKEN: - sc->opt3 &= ~OPT3_QUICKEN; - opt_flag = 0; - break; - case SC_OVERTHRUST: - case SC_OVERTHRUSTMAX: - case SC_SWOO: - sc->opt3 &= ~OPT3_OVERTHRUST; - if( type == SC_SWOO ) - opt_flag = 8; - else + case SC_HIDING: + sc->option &= ~OPTION_HIDE; + opt_flag|= 2|4; //Check for warp trigger + AoE trigger + break; + case SC_CLOAKING: + case SC_CLOAKINGEXCEED: + case SC__INVISIBILITY: + sc->option &= ~OPTION_CLOAK; + case SC_CAMOUFLAGE: + opt_flag|= 2; + break; + case SC_CHASEWALK: + sc->option &= ~(OPTION_CHASEWALK|OPTION_CLOAK); + opt_flag|= 2; + break; + case SC_SIGHT: + sc->option &= ~OPTION_SIGHT; + break; + case SC_WEDDING: + sc->option &= ~OPTION_WEDDING; + opt_flag |= 0x4; + break; + case SC_XMAS: + sc->option &= ~OPTION_XMAS; + opt_flag |= 0x4; + break; + case SC_SUMMER: + sc->option &= ~OPTION_SUMMER; + opt_flag |= 0x4; + break; + case SC_HANBOK: + sc->option &= ~OPTION_HANBOK; + opt_flag |= 0x4; + break; + case SC_OKTOBERFEST: + sc->option &= ~OPTION_OKTOBERFEST; + opt_flag |= 0x4; + break; + case SC_ORCISH: + sc->option &= ~OPTION_ORCISH; + break; + case SC_RUWACH: + sc->option &= ~OPTION_RUWACH; + break; + case SC_FUSION: + sc->option &= ~OPTION_FLYING; + break; + //opt3 + case SC_TWOHANDQUICKEN: + case SC_ONEHANDQUICKEN: + case SC_SPEARQUICKEN: + case SC_CONCENTRATION: + case SC_MER_QUICKEN: + sc->opt3 &= ~OPT3_QUICKEN; opt_flag = 0; - break; - case SC_ENERGYCOAT: - case SC_SKE: - sc->opt3 &= ~OPT3_ENERGYCOAT; - opt_flag = 0; - break; - case SC_INCATKRATE: //Simulated Explosion spirits effect. - if (bl->type != BL_MOB) - { + break; + case SC_OVERTHRUST: + case SC_OVERTHRUSTMAX: + case SC_SWOO: + sc->opt3 &= ~OPT3_OVERTHRUST; + if( type == SC_SWOO ) + opt_flag = 8; + else + opt_flag = 0; + break; + case SC_ENERGYCOAT: + case SC_SKE: + sc->opt3 &= ~OPT3_ENERGYCOAT; opt_flag = 0; break; - } - case SC_EXPLOSIONSPIRITS: - sc->opt3 &= ~OPT3_EXPLOSIONSPIRITS; - opt_flag = 0; - break; - case SC_STEELBODY: - case SC_SKA: - sc->opt3 &= ~OPT3_STEELBODY; - opt_flag = 0; - break; - case SC_BLADESTOP: - sc->opt3 &= ~OPT3_BLADESTOP; - opt_flag = 0; - break; - case SC_AURABLADE: - sc->opt3 &= ~OPT3_AURABLADE; - opt_flag = 0; - break; - case SC_BERSERK: - opt_flag = 0; - sc->opt3 &= ~OPT3_BERSERK; - break; - // case ???: // doesn't seem to do anything - // sc->opt3 &= ~OPT3_LIGHTBLADE; - // opt_flag = 0; - // break; - case SC_DANCING: - if ((sce->val1&0xFFFF) == CG_MOONLIT) - sc->opt3 &= ~OPT3_MOONLIT; - opt_flag = 0; - break; - case SC_MARIONETTE: - case SC_MARIONETTE_MASTER: - sc->opt3 &= ~OPT3_MARIONETTE; - opt_flag = 0; - break; - case SC_ASSUMPTIO: - sc->opt3 &= ~OPT3_ASSUMPTIO; - opt_flag = 0; - break; - case SC_WARM: //SG skills [Komurka] - sc->opt3 &= ~OPT3_WARM; - opt_flag = 0; - break; - case SC_KAITE: - sc->opt3 &= ~OPT3_KAITE; - opt_flag = 0; - break; - case SC_NJ_BUNSINJYUTSU: - sc->opt3 &= ~OPT3_BUNSIN; - opt_flag = 0; - break; - case SC_SOULLINK: - sc->opt3 &= ~OPT3_SOULLINK; - opt_flag = 0; - break; - case SC_PROPERTYUNDEAD: - sc->opt3 &= ~OPT3_UNDEAD; - opt_flag = 0; - break; - // case ???: // from DA_CONTRACT (looks like biolab mobs aura) - // sc->opt3 &= ~OPT3_CONTRACT; - // opt_flag = 0; - // break; - default: - opt_flag = 0; + case SC_INCATKRATE: //Simulated Explosion spirits effect. + if (bl->type != BL_MOB) + { + opt_flag = 0; + break; + } + case SC_EXPLOSIONSPIRITS: + sc->opt3 &= ~OPT3_EXPLOSIONSPIRITS; + opt_flag = 0; + break; + case SC_STEELBODY: + case SC_SKA: + sc->opt3 &= ~OPT3_STEELBODY; + opt_flag = 0; + break; + case SC_BLADESTOP: + sc->opt3 &= ~OPT3_BLADESTOP; + opt_flag = 0; + break; + case SC_AURABLADE: + sc->opt3 &= ~OPT3_AURABLADE; + opt_flag = 0; + break; + case SC_BERSERK: + opt_flag = 0; + sc->opt3 &= ~OPT3_BERSERK; + break; + // case ???: // doesn't seem to do anything + // sc->opt3 &= ~OPT3_LIGHTBLADE; + // opt_flag = 0; + // break; + case SC_DANCING: + if ((sce->val1&0xFFFF) == CG_MOONLIT) + sc->opt3 &= ~OPT3_MOONLIT; + opt_flag = 0; + break; + case SC_MARIONETTE: + case SC_MARIONETTE_MASTER: + sc->opt3 &= ~OPT3_MARIONETTE; + opt_flag = 0; + break; + case SC_ASSUMPTIO: + sc->opt3 &= ~OPT3_ASSUMPTIO; + opt_flag = 0; + break; + case SC_WARM: //SG skills [Komurka] + sc->opt3 &= ~OPT3_WARM; + opt_flag = 0; + break; + case SC_KAITE: + sc->opt3 &= ~OPT3_KAITE; + opt_flag = 0; + break; + case SC_NJ_BUNSINJYUTSU: + sc->opt3 &= ~OPT3_BUNSIN; + opt_flag = 0; + break; + case SC_SOULLINK: + sc->opt3 &= ~OPT3_SOULLINK; + opt_flag = 0; + break; + case SC_PROPERTYUNDEAD: + sc->opt3 &= ~OPT3_UNDEAD; + opt_flag = 0; + break; + // case ???: // from DA_CONTRACT (looks like biolab mobs aura) + // sc->opt3 &= ~OPT3_CONTRACT; + // opt_flag = 0; + // break; + default: + opt_flag = 0; } if (calc_flag&SCB_DYE) { //Restore DYE color diff --git a/src/map/status.h b/src/map/status.h index cdf3e03d6..1fd354c79 100644 --- a/src/map/status.h +++ b/src/map/status.h @@ -696,6 +696,8 @@ typedef enum sc_type { SC_MOONSTAR, SC_SUPER_STAR, + SC_OKTOBERFEST, + SC_MAX, //Automatically updated max, used in for's to check we are within bounds. } sc_type; // Official status change ids, used to display status icons on the client. @@ -1545,30 +1547,31 @@ enum { }; enum { - OPTION_NOTHING = 0x00000000, - OPTION_SIGHT = 0x00000001, - OPTION_HIDE = 0x00000002, - OPTION_CLOAK = 0x00000004, - OPTION_FALCON = 0x00000010, - OPTION_RIDING = 0x00000020, - OPTION_INVISIBLE = 0x00000040, - OPTION_ORCISH = 0x00000800, - OPTION_WEDDING = 0x00001000, - OPTION_RUWACH = 0x00002000, - OPTION_CHASEWALK = 0x00004000, - OPTION_FLYING = 0x00008000, //Note that clientside Flying and Xmas are 0x8000 for clients prior to 2007. - OPTION_XMAS = 0x00010000, - OPTION_TRANSFORM = 0x00020000, - OPTION_SUMMER = 0x00040000, - OPTION_DRAGON1 = 0x00080000, - OPTION_WUG = 0x00100000, - OPTION_WUGRIDER = 0x00200000, - OPTION_MADOGEAR = 0x00400000, - OPTION_DRAGON2 = 0x00800000, - OPTION_DRAGON3 = 0x01000000, - OPTION_DRAGON4 = 0x02000000, - OPTION_DRAGON5 = 0x04000000, - OPTION_HANBOK = 0x08000000, + OPTION_NOTHING = 0x00000000, + OPTION_SIGHT = 0x00000001, + OPTION_HIDE = 0x00000002, + OPTION_CLOAK = 0x00000004, + OPTION_FALCON = 0x00000010, + OPTION_RIDING = 0x00000020, + OPTION_INVISIBLE = 0x00000040, + OPTION_ORCISH = 0x00000800, + OPTION_WEDDING = 0x00001000, + OPTION_RUWACH = 0x00002000, + OPTION_CHASEWALK = 0x00004000, + OPTION_FLYING = 0x00008000, //Note that clientside Flying and Xmas are 0x8000 for clients prior to 2007. + OPTION_XMAS = 0x00010000, + OPTION_TRANSFORM = 0x00020000, + OPTION_SUMMER = 0x00040000, + OPTION_DRAGON1 = 0x00080000, + OPTION_WUG = 0x00100000, + OPTION_WUGRIDER = 0x00200000, + OPTION_MADOGEAR = 0x00400000, + OPTION_DRAGON2 = 0x00800000, + OPTION_DRAGON3 = 0x01000000, + OPTION_DRAGON4 = 0x02000000, + OPTION_DRAGON5 = 0x04000000, + OPTION_HANBOK = 0x08000000, + OPTION_OKTOBERFEST = 0x10000000, #ifndef NEW_CARTS OPTION_CART1 = 0x00000008, |