diff options
-rw-r--r-- | conf/inter-server.conf | 1 | ||||
-rw-r--r-- | conf/messages.conf | 4 | ||||
-rw-r--r-- | doc/script_commands.txt | 41 | ||||
-rw-r--r-- | npc/custom/quests/thq/THQS_TTShop.txt | 638 | ||||
-rw-r--r-- | src/common/mmo.h | 8 | ||||
-rw-r--r-- | src/config/const.h | 8 | ||||
-rw-r--r-- | src/config/renewal.h | 12 | ||||
-rw-r--r-- | src/map/atcommand.c | 4 | ||||
-rw-r--r-- | src/map/clif.c | 21 | ||||
-rw-r--r-- | src/map/clif.h | 18 | ||||
-rw-r--r-- | src/map/map.c | 4 | ||||
-rw-r--r-- | src/map/map.h | 1 | ||||
-rw-r--r-- | src/map/npc.c | 184 | ||||
-rw-r--r-- | src/map/npc.h | 2 | ||||
-rw-r--r-- | src/map/pc.c | 6 | ||||
-rw-r--r-- | src/map/pc.h | 2 | ||||
-rw-r--r-- | src/map/script.c | 11 | ||||
-rw-r--r-- | src/map/status.h | 4 | ||||
-rw-r--r-- | src/plugins/HPMHooking/HPMHooking.Hooks.inc | 24 |
19 files changed, 377 insertions, 616 deletions
diff --git a/conf/inter-server.conf b/conf/inter-server.conf index a3acad9f5..184285cfd 100644 --- a/conf/inter-server.conf +++ b/conf/inter-server.conf @@ -127,6 +127,7 @@ mob_skill_db2_db: mob_skill_db2 mapreg_db: mapreg autotrade_merchants_db: autotrade_merchants autotrade_data_db: autotrade_data +npc_market_data_db: npc_market_data // == SQL item, mob, mob skill databases // ===================================== diff --git a/conf/messages.conf b/conf/messages.conf index 7070b80e0..5c860e501 100644 --- a/conf/messages.conf +++ b/conf/messages.conf @@ -637,8 +637,8 @@ 878: You are no longer the Guild Master. 879: You have become the Guild Master! 880: You have been recovered! - -//881-899 FREE +881: Shop is out of stock! Come again later! +//882-899 FREE //------------------------------------ // More atcommands message diff --git a/doc/script_commands.txt b/doc/script_commands.txt index bb714d856..31574d0a2 100644 --- a/doc/script_commands.txt +++ b/doc/script_commands.txt @@ -299,6 +299,29 @@ type of shop will not allow you to sell items at it, you may only purchase items here. The layout used to define sale items still count, and "<price>" refers to how many points will be spent purchasing the them. +** Define a trader NPC +<map name>,<x>,<y>,<facing>%TAB%trader%TAB%<NPC Name>%TAB%<sprite id>,{<code>} +-%TAB%trader%TAB%<NPC Name>%TAB%-1,{<code>} + +All the standards that are valid to script objects are also valid for trader objects +(see ** Define an NPC object for more information). +This will define a trader NPC, which can cause a shop, cashshop or market window +to come up when clicked or called by other means. Unlike shop/cashshop NPCs this +type will run a code and can change the items that are being sold over time without +other NPC objects. +The types that a trader object can have are the following: +- NST_ZENY (0) Normal Zeny Shop (shop) +- NST_CASH (1) Normal Cash Shop (cashshop) +- 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) +Unless otherwise specified via *tradertype an trader object will be defined as +NST_ZENY. + +Note: NST_MARKET is only available with PACKETVER 20131223 or newer. +See '12 - NPC Trader-Related Commands' and /doc/sample/npc_trader_sample.txt for +more information regarding how to use this NPC type. + ** Define an warp/shop/cashshop/NPC duplicate. warp: <map name>,<x>,<y>{,<facing>}%TAB%duplicate(<label>)%TAB%<NPC Name>%TAB%<spanx>,<spany> @@ -990,7 +1013,8 @@ OnInit will execute every time the scripts loading is complete, including when they are reloaded with @reloadscript command. OnInterIfInit will execute when the map server connects to a char server, OnInterIfInitOnce will only execute once and will not execute if the map server reconnects -to the char server later. +to the char server later. Note that all those events will be executed upon +scripts reloading. OnAgitStart: OnAgitEnd: @@ -1061,6 +1085,21 @@ Only the special labels which are not associated with any script command are listed here. There are other kinds of labels which may be triggered in a similar manner, but they are described with their associated commands. +OnCountFunds: + +This special label is triggered when a player opens a trader NPC object that +is NST_CUSTOM. It is used to define different currency types to the trader via +*setcurrency. Should be used along with OnPayFunds, see /doc/sample/npc_trader_sample.txt +for more information. + +OnPayFunds: + +This special label is triggered when a purchase is made on a trader NPC object +that is NST_CUSTOM. Receives @price, total cost and @points, secondary input +field for cash windows. It is used to remove items that are set as currency. +Should be used along with OnCountFunds, see /doc/sample/npc_trader_sample.txt +for more information. + On<label name>: These special labels are used with Mob scripts mostly, and script commands diff --git a/npc/custom/quests/thq/THQS_TTShop.txt b/npc/custom/quests/thq/THQS_TTShop.txt index dfa83a587..266a20cb5 100644 --- a/npc/custom/quests/thq/THQS_TTShop.txt +++ b/npc/custom/quests/thq/THQS_TTShop.txt @@ -3,7 +3,7 @@ //===== By: ================================================== //= Fredzilla //===== Current Version: ===================================== -//= 1.1 +//= 1.2a //===== Description: ========================================= //= Start for Treasure hunter quests //===== Additional Comments: ================================= @@ -12,503 +12,193 @@ //= 1.0 - Straight conversion of Aegis NPC file //= 1.1 - balanced some prices, fixed 1 missing label //= removed Executioner&Mysteltain swords [Lupus] +//= 1.2 - Optmized and fixed small error [Panikon] +//= 1.2a - Fixed zeny formula [Panikon] //============================================================ prt_in,159,172,0 warp thqwrp 3,3,yuno_in01,123,155 -prt_in,164,174,1 script Treasure Hunter's Shop 1_M_YOUNGKNIGHT,{ - mes "[Ash]"; - mes "Ahh, "+strcharinfo(0)+"! Welcome to the Offical Treasure Hunter's Guild Shop."; - mes "You currently have ^FF0000"+#Treasure_Token+"^000000 treasure tokens!!!"; - next; - menu "How does this place work?",-,"What do you have in stock?",N_Shop,"Nevermind",N_NVM; - mes "[Ash]"; - mes "Well you see here you can exchange your treasure hunter tokens for zeny or rare weapons forged by our blacksmiths."; - mes " "; - mes "Everything has its own price value and the only way you can get the tokens is by completing quests assigned to you,the system normally works like this."; - mes " "; - mes "The harder the mission the more Tokens you will earn. All red quests are worth 4-8 Tokens, and the rest are worth 1-5."; - mes " "; - mes "Hope that solves your problem and questions."; - close; -N_NVM: - close; +// Main configuration object +- script THQS#Configuration -1,{ +OnInit: + // Axes + setarray $THQS_menu_weapons_1[0], Sabbath, Slaughter, Tomahawk, Great_Axe, Guillotine; + setarray $THQS_menu_price_1[0], 160, 160, 180, 200, 200; + // One Handed Swords + setarray $THQS_menu_weapons_2[0], Edge, Solar_Sword, Scissores_Sword, Nagan, Immaterial_Sword, Excalibur, Byeorrun_Gum, Tale_Fing_; + setarray $THQS_menu_price_2[0], 130, 150, 170, 180, 200, 200, 240, 320; + // Two Handed Swords + setarray $THQS_menu_weapons_3[0],Dragon_Slayer, Schweizersabel, Katzbalger, Muramasa, Masamune, Balmung; + setarray $THQS_menu_price_3[0], 140,200,300,300,400,2000; + // Books + setarray $THQS_menu_weapons_4[0],Book_Of_Blazing_Sun, Book_Of_Billows, Book_Of_Gust_Of_Wind, Book_Of_Mother_Earth, Book_Of_The_Apocalypse, Bible, Tablet; + setarray $THQS_menu_price_4[0], 80, 80, 80, 80, 80, 90, 120; + // Bows + setarray $THQS_menu_weapons_5[0], Bow_Of_Rudra, Bow_Of_Roguemaster; + setarray $THQS_menu_price_5[0], 150, 150; + // Katars + setarray $THQS_menu_weapons_6[0], Katar_Of_Cold_Icicle,Katar_Of_Thornbush,Katar_Of_Raging_Blaze,Katar_Of_Piercing_Wind,Ghoul_Leg,Infiltrator; + setarray $THQS_menu_price_6[0],70,70,70,70,125,150; + // Knuckles + setarray $THQS_menu_weapons_7[0],Kaiser_Knuckle,Berserk; + setarray $THQS_menu_price_7[0],75,75; + // Maces + setarray $THQS_menu_weapons_8[0],Spike,Slash,Grand_Cross,Quadrille,Mjolnir; + setarray $THQS_menu_price_8[0],65,90,100,110,1000; + // Whips + setarray $THQS_menu_weapons_9[0],Rapture_Rose,Chemeti; + setarray $THQS_menu_price_9[0],50,65; + // Wands + setarray $THQS_menu_weapons_10[0],Mighty_Staff,Wizardy_Staff,Bone_Wand,Staff_Of_Soul; + setarray $THQS_menu_price_10[0],90,150,110,120; + // Cards + setarray $THQS_menu_cards[0],Poring_Card, Pasana_Card, Dokebi_Card, Sword_Fish_Card, Sand_Man_Card, Drainliar_Card, + Kaho_Card,Mandragora_Card,Vadon_Card,Mummy_Card,Zenorc_Card,Condor_Card, Zombie_Card; + setarray $THQS_menu_price[0],2,420,420,420,420,360,360,360,360,540,240,240,210; end; -N_Shop: -//This is when it gets hard :) - mes "[Ash]"; - mes "Ok here is our Big list of goods."; - mes " "; - mes "(Note T stands for a Treasure Token.)"; - next; - menu "Trade for Zeny",-,"Trade for Weapons",N_BuyWeps,"Trade for Cards",N_BuyCards,"Nevermind",N_NVM; - mes "[Ash]"; - mes "This is what we have to offer."; - next; - menu "1000z - 1T",-,"10000z - 10T",N_10T,"100000z - 100T",N_100T,"Nevermind",N_NVM; - if (#Treasure_Token > 0) goto N_GetZeny1k; - mes "You don't have enough tokens!"; - close; -N_GetZeny1k: - set #Treasure_Token,#Treasure_Token-1; - Zeny += 1000; - close; -N_10T: - if (#Treasure_Token > 9) goto N_GetZeny10k; - mes "You don't have enough tokens!"; - close; -N_GetZeny10k: - set #Treasure_Token,#Treasure_Token-10; - Zeny += 10000; - close; -N_100T: - if (#Treasure_Token > 99) goto N_GetZeny100k; - mes "You don't have enough tokens!"; - close; -N_GetZeny100k: - set #Treasure_Token,#Treasure_Token-100; - Zeny += 100000; - close; - -N_BuyWeps: - mes "[Ash]"; - mes "This is what we have to offer."; - next; - menu "Axe's",-,"1 Handed Swords",N_1HandSword,"2 Handed Swords",N_2HandSword,"Book's",N_Book,"Bow's",N_Bow,"Katar's",N_Katar,"Knuckle's",N_Knuckle,"Mace's",N_Mace,"Whips",N_Whip,"Wands",N_Wand,"Nevermind",N_NVM; - - mes "[Ash]"; - mes "This is what we have to offer."; - next; - menu "Sabbath - 160T",-,"Slaughter - 160T",N_Slau,"Tomahawk - 180T",N_Toma,"Great Axe - 200T",N_GreatA,"Guillotine - 200T",N_Guill,"Nevermind",N_NVM; - - if (#Treasure_Token < 160) goto N_NeedToken; - set #Treasure_Token,#Treasure_Token-160; - getitem 1365,1; - logmes "Treasure Token: Bought a Sabbath"; - close; -N_Slau: - if (#Treasure_Token < 160) goto N_NeedToken; - set #Treasure_Token,#Treasure_Token-160; - getitem 1367,1; - logmes "Treasure Token: Bought a Slaughter"; - close; -N_Toma: - if (#Treasure_Token < 180) goto N_NeedToken; - set #Treasure_Token,#Treasure_Token-180; - getitem 1368,1; - logmes "Treasure Token: Bought a Tomahawk"; - close; -N_GreatA: - if (#Treasure_Token < 200) goto N_NeedToken; - set #Treasure_Token,#Treasure_Token-200; - getitem 1364,1; - logmes "Treasure Token: Bought a Great Axe"; - close; -N_Guill: - if (#Treasure_Token < 200) goto N_NeedToken; - set #Treasure_Token,#Treasure_Token-200; - getitem 1369,1; - logmes "Treasure Token: Bought a Guillotine"; - close; -N_NeedToken: - mes "[Ash]"; - mes "You don't have enough tokens!"; - close; - - -N_1HandSword: - mes "[Ash]"; - mes "This is what we have to offer."; - next; - menu "Edge - 130T",-,"Solar Sword - 150T",N_SolarS,"Caesar's Sword - 170T",N_CaesarS,"Nagan - 180T",N_Nagan,"Immaterial Sword - 200T",N_ImmatS,"Excalibur - 200T",N_Excal,"Byeollungum - 240T",N_Byeoll,"Talefing - 320T",N_Talef,"Nevermind",N_NVM; - - if (#Treasure_Token < 130) goto N_NeedToken; - set #Treasure_Token,#Treasure_Token-130; - getitem 1132,1; - logmes "Treasure Token: Bought a Edge"; - close; -N_SolarS: - if (#Treasure_Token < 150) goto N_NeedToken; - set #Treasure_Token,#Treasure_Token-150; - logmes "Treasure Token: Bought a Solar Sword"; - getitem 1136,1; - close; -N_CaesarS: - if (#Treasure_Token < 170) goto N_NeedToken; - set #Treasure_Token,#Treasure_Token-170; - logmes "Treasure Token: Bought a Caesars Sword"; - getitem 1134,1; - close; -N_Nagan: - if (#Treasure_Token < 180) goto N_NeedToken; - set #Treasure_Token,#Treasure_Token-180; - logmes "Treasure Token: Bought a Nagan"; - getitem 1130,1; - close; -N_ImmatS: - if (#Treasure_Token < 200) goto N_NeedToken; - set #Treasure_Token,#Treasure_Token-200; - logmes "Treasure Token: Bought a Immaterial Sword"; - getitem 1141,1; - close; -N_Excal: - if (#Treasure_Token < 200) goto N_NeedToken; - set #Treasure_Token,#Treasure_Token-200; - logmes "Treasure Token: Bought a Excalibur"; - getitem 1137,1; - close; -N_Byeoll: - if (#Treasure_Token < 240) goto N_NeedToken; - set #Treasure_Token,#Treasure_Token-240; - logmes "Treasure Token: Bought a Byeollungum"; - getitem 1140,1; - close; -N_Talef: - if (#Treasure_Token < 320) goto N_NeedToken; - set #Treasure_Token,#Treasure_Token-320; - logmes "Treasure Token: Bought a Talefing"; - getitem 1139,1; - close; +} +// Trades tokens +// getarg(0) - number of tokens to be traded +function script thqs_trade_token { + @type = getarg(0); + if( @type == 4 ) + close; -N_2HandSword: - mes "[Ash]"; - mes "This is what we have to offer."; - next; - menu "Dragon Slayer - 140T",-,"Schweizersabel - 200T",N_Schwe,"Katzbalger - 300T",N_Katzb,"Muramasa - 300T",N_Murama,"Masamune - 400T",N_Masamu,"Balmung - 2000T",N_Balmu,"Nevermind",N_NVM; + // 10^0, 10^1, 10^2 + @type -= 1; + @price = pow(10, @type); - if (#Treasure_Token < 140) goto N_NeedToken; - set #Treasure_Token,#Treasure_Token-140; - logmes "Treasure Token: Bought a Dragon Slayer"; - getitem 1166,1; - close; -N_Schwe: - if (#Treasure_Token < 200) goto N_NeedToken; - set #Treasure_Token,#Treasure_Token-200; - logmes "Treasure Token: Bought a Schweizersabel"; - getitem 1167,1; - close; -N_Katzb: - if (#Treasure_Token < 300) goto N_NeedToken; - set #Treasure_Token,#Treasure_Token-300; - logmes "Treasure Token: Bought a Katzbalger"; - getitem 1170,1; - close; -N_Murama: - if (#Treasure_Token < 300) goto N_NeedToken; - set #Treasure_Token,#Treasure_Token-300; - logmes "Treasure Token: Bought a Muramasa"; - getitem 1164,1; - close; -N_Masamu: - if (#Treasure_Token < 400) goto N_NeedToken; - set #Treasure_Token,#Treasure_Token-400; - logmes "Treasure Token: Bought a Masamune"; - getitem 1165,1; - close; -N_Balmu: - if (#Treasure_Token < 2000) goto N_NeedToken; - set #Treasure_Token,#Treasure_Token-2000; - logmes "Treasure Token: Bought a Balmung"; - getitem 1161,1; - close; + // 10^3, 10^4, 10^5 + @type += 3; // So we can use pow later to determine the qt of Zeny + @prize = pow(1000, @type); + if( #Treasure_Token < @price ) { + mes "You don't have enough tokens!"; + close; + } -N_Book: - mes "[Ash]"; - mes "This is what we have to offer."; - next; - menu "Book of the Burning Sun - 80T",-,"Book of the Rough Seas - 80T",N_RoughSea,"Book of the Dry Winds - 80T",N_DryWinds,"Book of the Ripe Earth - 80T",N_RipeEarth,"Book of the Revelations - 80T",N_Revela,"Bible - 90T",N_Bible,"Tablet - 120T",N_Tablet,"Nevermind",N_NVM; + if( Zeny == MAX_ZENY ) { + mes "You can't add more zeny to your character"; + close; + } - if (#Treasure_Token < 80) goto N_NeedToken; - set #Treasure_Token,#Treasure_Token-80; - logmes "Treasure Token: Bought a Book of the Burning Sun"; - getitem 1555,1; - close; -N_RoughSea: - if (#Treasure_Token < 80) goto N_NeedToken; - set #Treasure_Token,#Treasure_Token-80; - logmes "Treasure Token: Bought a Book of the Rough Seas"; - getitem 1553,1; - close; -N_DryWinds: - if (#Treasure_Token < 80) goto N_NeedToken; - set #Treasure_Token,#Treasure_Token-80; - logmes "Treasure Token: Bought a Book of the Dry Winds"; - getitem 1556,1; + Zeny += @prize; + #Treasure_Token -= @price; close; -N_RipeEarth: - if (#Treasure_Token < 80) goto N_NeedToken; - set #Treasure_Token,#Treasure_Token-80; - logmes "Treasure Token: Bought a Book of the Ripe Earth"; - getitem 1554,1; - close; -N_Revela: - if (#Treasure_Token < 80) goto N_NeedToken; - set #Treasure_Token,#Treasure_Token-80; - logmes "Treasure Token: Bought a Book of the Revelations"; - getitem 1557,1; - close; -N_Bible: - if (#Treasure_Token < 90) goto N_NeedToken; - set #Treasure_Token,#Treasure_Token-90; - logmes "Treasure Token: Bought a Bible"; - getitem 1551,1; - close; -N_Tablet: - if (#Treasure_Token < 120) goto N_NeedToken; - set #Treasure_Token,#Treasure_Token-120; - logmes "Treasure Token: Bought a Tablet"; - getitem 1552,1; - close; - -N_Bow: - mes "[Ash]"; - mes "This is what we have to offer."; - next; - menu "Rudra's Bow - 150T",-,"Roguemaster's Bow - 150T",N_Rogue,"Nevermind",N_NVM; +} - if (#Treasure_Token < 150) goto N_NeedToken; - set #Treasure_Token,#Treasure_Token-150; - logmes "Treasure Token: Bought a Rudra Bow"; - getitem 1720,1; - close; -N_Rogue: - if (#Treasure_Token < 150) goto N_NeedToken; - set #Treasure_Token,#Treasure_Token-150; - logmes "Treasure Token: Bought a Roguemaster Bow"; - getitem 1719,1; +// Creates a buying menu +// getarg(0) - .@mw$ -> ID +// getarg(1) - .@mp$ -> PRICE +function script thqs_menu_buy { + if( getargcount() != 2 ) { + debugmes "thqs_menu_buy: Wrong number of arguments!!"; + close; + } + + .@mw$ = getarg(0); + .@mp$ = getarg(1); + + if( getarraysize( getd(.@mw$) ) != getarraysize( getd(.@mp$) ) ) { + debugmes "thqs_menu_buy: Missing entries in data!"; + close; + } + + // Dynamic menu + // Uses a dynamic string and then applies it to a *select + .@select_menu$ = ""; + for( .@i = 0; .@i < getarraysize( getd(.@mw$) ); .@i++ ) { + .@price = getd(.@mp$+"["+.@i+"]"); + + if( .@select_menu$ != "") + .@select_menu$ = .@select_menu$+":"+getitemname( getd(.@mw$+"["+.@i+"]") )+" - "+.@price+"T"; + else + .@select_menu$ = getitemname( getd(.@mw$+"["+.@i+"]") )+" - "+.@price+"T"; + } + .@select_menu$ = .@select_menu$ + ":Nevermind"; + select(.@select_menu$); + + if( @menu == (.@i+1) ) + close; + + @index = @menu - 1; // Arrays are 0 indexed while our menu is not + @item_id = getd(.@mw$+"["+@index+"]"); + @price = getd(.@mp$+"["+@index+"]"); + if( #Treasure_Token < @price ) { + mes "You don't have enough tokens!"; + close; + } + #Treasure_Token -= @price; + logmes "Treasure Token: Bought a "+getitemname(@item_id); + getitem @item_id,1; close; +} -N_Katar: +// Creates the first weapon menu +// getarg(0) - @menu +function script ths_menu_weapons { + @first_option = getarg(0); + if( @first_option == 11 ) + close; mes "[Ash]"; - mes "This is what we have to offer."; + mes "This is what we have to offer."+@first_option; next; - menu "Katar of the Blazing Rage - 70T",-,"Katar of the Cold Icicle - 70T",N_ColdIce,"Katar of the Piercing Wind - 70T",N_PiercWind,"Katar of the Dusty Thornbush - 70T",N_DustyT,"Sharpened Legbone of Ghoul - 125T",N_Legbone,"Infiltrator - 150T",N_Infiltra,"Nevermind",N_NVM; + // Array names so they can be used by thqs_menu_buy + .@mw$ = "$THQS_menu_weapons_"+@first_option; + .@mp$ = "$THQS_menu_price_"+@first_option; - if (#Treasure_Token < 70) goto N_NeedToken; - set #Treasure_Token,#Treasure_Token-70; - logmes "Treasure Token: Bought a Katar of the Blazing Rage"; - getitem 1258,1; - close; -N_ColdIce: - if (#Treasure_Token < 70) goto N_NeedToken; - set #Treasure_Token,#Treasure_Token-70; - logmes "Treasure Token: Bought a Katar of the Cold Icicle"; - getitem 1256,1; - close; -N_PiercWind: - if (#Treasure_Token < 70) goto N_NeedToken; - set #Treasure_Token,#Treasure_Token-70; - logmes "Treasure Token: Bought a Katar of the Piercing Wind"; - getitem 1259,1; - close; -N_DustyT: - if (#Treasure_Token < 70) goto N_NeedToken; - set #Treasure_Token,#Treasure_Token-70; - logmes "Treasure Token: Bought a Katar of the Dusty Thornbush"; - getitem 1257,1; - close; -N_Legbone: - if (#Treasure_Token < 125) goto N_NeedToken; - set #Treasure_Token,#Treasure_Token-125; - logmes "Treasure Token: Bought a Sharpened Legbone of Ghoul"; - getitem 1260,1; - close; -N_Infiltra: - if (#Treasure_Token < 150) goto N_NeedToken; - set #Treasure_Token,#Treasure_Token-150; - logmes "Treasure Token: Bought a Infiltrator"; - getitem 1261,1; - close; + thqs_menu_buy(.@mw$,.@mp$); +} -N_Knuckle: +// Main script +prt_in,164,174,1 script Treasure Hunter's Shop 1_M_YOUNGKNIGHT,{ mes "[Ash]"; - mes "This is what we have to offer."; + mes "Ahh, "+strcharinfo(0)+"! Welcome to the Offical Treasure Hunter's Guild Shop."; + mes "You currently have ^FF0000"+#Treasure_Token+"^000000 treasure tokens!!!"; next; - menu "Kaiser Knuckle - 75T",-,"Berserk - 75T",N_Berserk,"Nevermind",N_NVM; + switch( select("How does this place work?","What do you have in stock?","Nevermind") ) { + case 1: + mes "[Ash]"; + mes "Well you see here you can exchange your treasure hunter tokens for zeny or rare weapons forged by our blacksmiths."; + mes " "; + mes "Everything has its own price value and the only way you can get the tokens is by completing quests assigned to you,the system normally works like this."; + mes " "; + mes "The harder the mission the more Tokens you will earn. All red quests are worth 4-8 Tokens, and the rest are worth 1-5."; + mes " "; + mes "Hope that solves your problem and questions."; + close; + case 2: + break; + case 3: + close; + } - if (#Treasure_Token < 75) goto N_NeedToken; - set #Treasure_Token,#Treasure_Token-75; - logmes "Treasure Token: Bought a Kaiser Knuckle"; - getitem 1813,1; - close; -N_Berserk: - if (#Treasure_Token < 75) goto N_NeedToken; - set #Treasure_Token,#Treasure_Token-75; - logmes "Treasure Token: Bought a Berserk"; - getitem 1814,1; - close; - -N_Mace: mes "[Ash]"; - mes "This is what we have to offer."; - next; - menu "Spike - 65T",-,"Slash - 90T",N_Slash,"Grand Cross - 100T",N_GrandC,"Quadrille - 110T",N_Quadr,"Mjolnir - 1000T",N_MJ,"Nevermind",N_NVM; - - if (#Treasure_Token < 65) goto N_NeedToken; - set #Treasure_Token,#Treasure_Token-65; - logmes "Treasure Token: Bought a Spike"; - getitem 1523,1; - close; -N_Slash: - if (#Treasure_Token < 90) goto N_NeedToken; - set #Treasure_Token,#Treasure_Token-90; - logmes "Treasure Token: Bought a Slash"; - getitem 1526,1; - close; -N_GrandC: - if (#Treasure_Token < 100) goto N_NeedToken; - set #Treasure_Token,#Treasure_Token-100; - logmes "Treasure Token: Bought a Grand Cross"; - getitem 1528,1; - close; -N_Quadr: - if (#Treasure_Token < 110) goto N_NeedToken; - set #Treasure_Token,#Treasure_Token-110; - logmes "Treasure Token: Bought a Quadrille"; - getitem 1527,1; - close; -N_MJ: - if (#Treasure_Token < 1000) goto N_NeedToken; - set #Treasure_Token,#Treasure_Token-1000; - logmes "Treasure Token: Bought a Mjolnir"; - getitem 1530,1; - close; - -N_Whip: - mes "[Ash]"; - mes "This is what we have to offer."; + mes "Ok here is our Big list of goods."; + mes " "; + mes "(Note T stands for a Treasure Token.)"; next; - menu "Rapture Rose - 50T",-,"Chemeti - 65T",N_Chemeti,"Nevermind",N_NVM; - - if (#Treasure_Token < 50) goto N_NeedToken; - set #Treasure_Token,#Treasure_Token-50; - logmes "Treasure Token: Bought a Rapture Rose"; - getitem 1963,1; - close; -N_Chemeti: - if (#Treasure_Token < 65) goto N_NeedToken; - set #Treasure_Token,#Treasure_Token-65; - logmes "Treasure Token: Bought a Chemeti"; - getitem 1964,1; - close; - -N_Wand: mes "[Ash]"; mes "This is what we have to offer."; next; - menu "Mighty Staff - 90T",-,"Wizardry Staff - 150T",N_Wizardry,"Bone Wand - 110T",N_BoneW,"Staff of Soul - 120T",N_SOSoul,"Nevermind",N_NVM; - - if (#Treasure_Token < 90) goto N_NeedToken; - set #Treasure_Token,#Treasure_Token-90; - logmes "Treasure Token: Bought a Mighty Staff"; - getitem 1613,1;//Items: Mighty_Staff, - close; -N_Wizardry: - if (#Treasure_Token < 150) goto N_NeedToken; - set #Treasure_Token,#Treasure_Token-150; - logmes "Treasure Token: Bought a Wizardry Staff"; - getitem 1473,1;//Items: Wizardy_Staff, - close; -N_BoneW: - if (#Treasure_Token < 110) goto N_NeedToken; - set #Treasure_Token,#Treasure_Token-110; - logmes "Treasure Token: Bought a Bone Wand"; - getitem 1615,1;//Items: Bone_Wand, - close; -N_SOSoul: - if (#Treasure_Token < 120) goto N_NeedToken; - set #Treasure_Token,#Treasure_Token-120; - logmes "Treasure Token: Bought a Staff of Soul"; - getitem 1472,1;//Items: Staff_of_Soul, - close; - -N_BuyCards: - mes "[Ash]"; - mes "This is what we have to offer. All Cards are 300T"; - next; - menu "Poring Card - 2T",-,"Pasana Card - 420T",N_CPasana,"Dokebi Card - 420T",N_CDok,"Swordfish Card - 420T",N_CSFish, - "Sandman Card - 420T",N_CSMan,"Drainliar Card - 360T",N_CDrain,"Kaho Card - 360T",N_CKaho,"Mandragora Card - 360T",N_CMand, - "Vadon Card - 360T",N_CVadon,"Mummy Card - 540T",N_CMummy,"Zenorc Card - 240T",N_CZeno,"Condor Card - 240T",N_CCond, - "Zombie Card - 210T",N_CZomb,"Nevermind",N_NVM; - - if (#Treasure_Token < 2) goto N_NeedToken; - set #Treasure_Token,#Treasure_Token-2; - logmes "Treasure Token: Bought a Poring Card"; - getitem 4001,1;//Items: Poring_Card, - close; - -N_CPasana: - if (#Treasure_Token < 420) goto N_NeedToken; - set #Treasure_Token,#Treasure_Token-420; - logmes "Treasure Token: Bought a Pasana Card"; - getitem 4099,1;//Items: Pasana_Card, - close; -N_CDok: - if (#Treasure_Token < 420) goto N_NeedToken; - set #Treasure_Token,#Treasure_Token-420; - logmes "Treasure Token: Bought a Dokebi Card"; - getitem 4098,1;//Items: Dokebi_Card, - close; -N_CSFish: - if (#Treasure_Token < 420) goto N_NeedToken; - set #Treasure_Token,#Treasure_Token-420; - logmes "Treasure Token: Bought a Swordfish Card"; - getitem 4089,1;//Items: Sword_Fish_Card, - close; -N_CSMan: - if (#Treasure_Token < 420) goto N_NeedToken; - set #Treasure_Token,#Treasure_Token-420; - logmes "Treasure Token: Bought a Sandman Card"; - getitem 4101,1;//Items: Sand_Man_Card, - close; -N_CDrain: - if (#Treasure_Token < 360) goto N_NeedToken; - set #Treasure_Token,#Treasure_Token-360; - logmes "Treasure Token: Bought a Drainliar Card"; - getitem 4069,1;//Items: Drainliar_Card, - close; -N_CKaho: - if (#Treasure_Token < 360) goto N_NeedToken; - set #Treasure_Token,#Treasure_Token-360; - logmes "Treasure Token: Bought a Kaho Card"; - getitem 4065,1;//Items: Kaho_Card, - close; -N_CMand: - if (#Treasure_Token < 360) goto N_NeedToken; - set #Treasure_Token,#Treasure_Token-360; - logmes "Treasure Token: Bought a Mandragora Card"; - getitem 4030,1;//Items: Mandragora_Card, - close; -N_CVadon: - if (#Treasure_Token < 360) goto N_NeedToken; - set #Treasure_Token,#Treasure_Token-360; - logmes "Treasure Token: Bought a Vadon Card"; - getitem 4049,1;//Items: Vadon_Card, - close; -N_CMummy: - if (#Treasure_Token < 540) goto N_NeedToken; - set #Treasure_Token,#Treasure_Token-540; - logmes "Treasure Token: Bought a Mummy Card"; - getitem 4106,1;//Items: Mummy_Card, - close; -N_CZeno: - if (#Treasure_Token < 240) goto N_NeedToken; - set #Treasure_Token,#Treasure_Token-240; - logmes "Treasure Token: Bought a Zenorc Card"; - getitem 4096,1;//Items: Zenorc_Card, - close; -N_CCond: - if (#Treasure_Token < 240) goto N_NeedToken; - set #Treasure_Token,#Treasure_Token-240; - logmes "Treasure Token: Bought a Condor Card"; - getitem 4015,1;//Items: Condor_Card, - close; -N_CZomb: - if (#Treasure_Token < 210) goto N_NeedToken; - set #Treasure_Token,#Treasure_Token-210; - logmes "Treasure Token: Bought a Zombie Card"; - getitem 4038,1;//Items: Zombie_Card, - close; -} + switch( select("Trade for zeny", "Trade for Weapons", "Trade for Cards", "Nevermind") ) { + case 1: + select("1000z - 1T","10000z - 10T","100000z - 100T","Nevermind"); + thqs_trade_token(@menu); + case 2: + mes "[Ash]"; + mes "This is what we have to offer."; + next; + select("Axe's","1 Handed Swords","2 Handed Swords","Book's","Bow's","Katar's","Knuckle's","Mace's","Whips","Wands","Nevermind"); + ths_menu_weapons(@menu); + case 3: + mes "[Ash]"; + mes "This is what we have to offer."; + next; + thqs_menu_buy("$THQS_menu_cards","$THQS_menu_price"); + case 4: + close; + } + end; +}
\ No newline at end of file diff --git a/src/common/mmo.h b/src/common/mmo.h index 1d826463e..0003aa917 100644 --- a/src/common/mmo.h +++ b/src/common/mmo.h @@ -84,6 +84,14 @@ #endif // 20090603 #endif // 20070227 +/* Feb 1st 2012 */ +#if PACKETVER >= 20120201 +# define NEW_CARTS +# define MAX_CARTS 9 +#else +# define MAX_CARTS 5 +#endif + #define MAX_INVENTORY 100 //Max number of characters per account. Note that changing this setting alone is not enough if the client is not hexed to support more characters as well. #define MAX_CHARS 9 diff --git a/src/config/const.h b/src/config/const.h index f9baa4d7d..ba06d70cb 100644 --- a/src/config/const.h +++ b/src/config/const.h @@ -87,14 +87,6 @@ #define RE_LVL_TMDMOD() #endif -/* Feb 1st 2012 */ -#if PACKETVER >= 20120201 - #define NEW_CARTS - #define MAX_CARTS 9 -#else - #define MAX_CARTS 5 -#endif - // Renewal variable cast time reduction #ifdef RENEWAL_CAST #define VARCAST_REDUCTION(val) do { \ diff --git a/src/config/renewal.h b/src/config/renewal.h index 36bdd3958..1c48b9f8a 100644 --- a/src/config/renewal.h +++ b/src/config/renewal.h @@ -13,8 +13,18 @@ * @INFO: This file holds general-purpose renewal settings, for class-specific ones check /src/config/classes folder **/ +/** + * Renewal full toggle switch. + * + * Uncomment this line to disable all of the below settings at once. + * Note: in UNIX builds, this can be easily done without touching this + * line, by passing --disable-renewal to the configure script: + * ./configure --disable-renewal + */ //#define DISABLE_RENEWAL -#ifndef DISABLE_RENEWAL + + +#ifndef DISABLE_RENEWAL // Do not change this line /// game renewal server mode /// (disable by commenting the line) diff --git a/src/map/atcommand.c b/src/map/atcommand.c index df3be40a5..7a6ad84e4 100644 --- a/src/map/atcommand.c +++ b/src/map/atcommand.c @@ -4,7 +4,7 @@ #define HERCULES_CORE -#include "../config/core.h" // AUTOLOOTITEM_SIZE, AUTOTRADE_PERSISTENCY, MAX_CARTS, MAX_SUGGESTIONS, MOB_FLEE(), MOB_HIT(), RENEWAL, RENEWAL_DROP, RENEWAL_EXP +#include "../config/core.h" // AUTOLOOTITEM_SIZE, AUTOTRADE_PERSISTENCY, MAX_SUGGESTIONS, MOB_FLEE(), MOB_HIT(), RENEWAL, RENEWAL_DROP, RENEWAL_EXP #include "atcommand.h" #include <math.h> @@ -45,7 +45,7 @@ #include "../common/conf.h" #include "../common/core.h" #include "../common/malloc.h" -#include "../common/mmo.h" +#include "../common/mmo.h" // MAX_CARTS #include "../common/nullpo.h" #include "../common/random.h" #include "../common/showmsg.h" diff --git a/src/map/clif.c b/src/map/clif.c index 1da6070e8..068cb1e07 100644 --- a/src/map/clif.c +++ b/src/map/clif.c @@ -4,7 +4,7 @@ #define HERCULES_CORE -#include "../config/core.h" // ANTI_MAYAP_CHEAT, NEW_CARTS, RENEWAL, SECURE_NPCTIMEOUT +#include "../config/core.h" // ANTI_MAYAP_CHEAT, RENEWAL, SECURE_NPCTIMEOUT #include "clif.h" #include <stdio.h> @@ -48,6 +48,7 @@ #include "../common/ers.h" #include "../common/grfio.h" #include "../common/malloc.h" +#include "../common/mmo.h" // NEW_CARTS #include "../common/nullpo.h" #include "../common/random.h" #include "../common/showmsg.h" @@ -8136,7 +8137,7 @@ void clif_disp_message(struct block_list* src, const char* mes, size_t len, enum /// result: /// 0 = failure /// 1 = success -void clif_GM_kickack(struct map_session_data *sd, int id) +void clif_GM_kickack(struct map_session_data *sd, int result) { int fd; @@ -8145,7 +8146,7 @@ void clif_GM_kickack(struct map_session_data *sd, int id) fd = sd->fd; WFIFOHEAD(fd,packet_len(0xcd)); WFIFOW(fd,0) = 0xcd; - WFIFOB(fd,2) = id; // FIXME: this is not account id + WFIFOB(fd,2) = result; WFIFOSET(fd, packet_len(0xcd)); } @@ -8159,7 +8160,7 @@ void clif_GM_kick(struct map_session_data *sd,struct map_session_data *tsd) { map->quit(tsd); if( sd ) - clif->GM_kickack(sd,tsd->status.account_id); + clif->GM_kickack(sd, 1); } @@ -15561,20 +15562,10 @@ void clif_cashshop_show(struct map_session_data *sd, struct npc_data *nd) { WFIFOSET(fd,WFIFOW(fd,2)); } - /// Cashshop Buy Ack (ZC_PC_CASH_POINT_UPDATE). /// 0289 <cash point>.L <error>.W /// 0289 <cash point>.L <kafra point>.L <error>.W (PACKETVER >= 20070711) -/// error: -/// 0 = The deal has successfully completed. (ERROR_TYPE_NONE) -/// 1 = The Purchase has failed because the NPC does not exist. (ERROR_TYPE_NPC) -/// 2 = The Purchase has failed because the Kafra Shop System is not working correctly. (ERROR_TYPE_SYSTEM) -/// 3 = You are over your Weight Limit. (ERROR_TYPE_INVENTORY_WEIGHT) -/// 4 = You cannot purchase items while you are in a trade. (ERROR_TYPE_EXCHANGE) -/// 5 = The Purchase has failed because the Item Information was incorrect. (ERROR_TYPE_ITEM_ID) -/// 6 = You do not have enough Kafra Credit Points. (ERROR_TYPE_MONEY) -/// 7 = You can purchase up to 10 items. -/// 8 = Some items could not be purchased. +/// For error return codes see enum cashshop_error@clif.h void clif_cashshop_ack(struct map_session_data* sd, int error) { struct npc_data *nd; int fd = sd->fd; diff --git a/src/map/clif.h b/src/map/clif.h index f54c4afce..7b27e1fe6 100644 --- a/src/map/clif.h +++ b/src/map/clif.h @@ -349,6 +349,22 @@ enum clif_messages { }; /** + * Used to answer CZ_PC_BUY_CASH_POINT_ITEM (clif_parse_cashshop_buy) + **/ +enum cashshop_error { + ERROR_TYPE_NONE = 0, // The deal has successfully completed. (ERROR_TYPE_NONE) + ERROR_TYPE_NPC, // The Purchase has failed because the NPC does not exist. (ERROR_TYPE_NPC) + ERROR_TYPE_SYSTEM, // The Purchase has failed because the Kafra Shop System is not working correctly. (ERROR_TYPE_SYSTEM) + ERROR_TYPE_INVENTORY_WEIGHT, // You are over your Weight Limit. (ERROR_TYPE_INVENTORY_WEIGHT) + ERROR_TYPE_EXCHANGE, // You cannot purchase items while you are in a trade. (ERROR_TYPE_EXCHANGE) + ERROR_TYPE_ITEM_ID, // The Purchase has failed because the Item Information was incorrect. (ERROR_TYPE_ITEM_ID) + ERROR_TYPE_MONEY, // You do not have enough Kafra Credit Points. (ERROR_TYPE_MONEY) + // Unofficial type names + ERROR_TYPE_QUANTITY, // You can purchase up to 10 items. (ERROR_TYPE_QUANTITY) + ERROR_TYPE_NOT_ALL, // Some items could not be purchased. (ERROR_TYPE_NOT_ALL) +}; + +/** * Color Table **/ enum clif_colors { @@ -910,7 +926,7 @@ struct clif_interface { void (*friendslist_toggle) (struct map_session_data *sd,int account_id, int char_id, int online); void (*friendlist_req) (struct map_session_data* sd, int account_id, int char_id, const char* name); /* gm-related */ - void (*GM_kickack) (struct map_session_data *sd, int id); + void (*GM_kickack) (struct map_session_data *sd, int result); void (*GM_kick) (struct map_session_data *sd,struct map_session_data *tsd); void (*manner_message) (struct map_session_data* sd, uint32 type); void (*GM_silence) (struct map_session_data* sd, struct map_session_data* tsd, uint8 type); diff --git a/src/map/map.c b/src/map/map.c index bccb51d7e..01d3dbb9f 100644 --- a/src/map/map.c +++ b/src/map/map.c @@ -3656,6 +3656,8 @@ int inter_config_read(char *cfgName) { strcpy(map->autotrade_merchants_db, w2); else if(strcmpi(w1,"autotrade_data_db")==0) strcpy(map->autotrade_data_db, w2); + else if(strcmpi(w1,"npc_market_data_db")==0) + strcpy(map->npc_market_data_db, w2); /* sql log db */ else if(strcmpi(w1,"log_db_ip")==0) strcpy(logs->db_ip, w2); @@ -5832,7 +5834,7 @@ int do_init(int argc, char *argv[]) exit(EXIT_SUCCESS); } - npc->event_do_oninit(); // Init npcs (OnInit) + npc->event_do_oninit( false ); // Init npcs (OnInit) npc->market_fromsql(); /* after OnInit */ if (battle_config.pk_mode) diff --git a/src/map/map.h b/src/map/map.h index 8277c7a62..539b02ed8 100644 --- a/src/map/map.h +++ b/src/map/map.h @@ -845,6 +845,7 @@ struct map_interface { char interreg_db[32]; char autotrade_merchants_db[32]; char autotrade_data_db[32]; + char npc_market_data_db[32]; char default_codepage[32]; diff --git a/src/map/npc.c b/src/map/npc.c index 289c42d44..cf509e11f 100644 --- a/src/map/npc.c +++ b/src/map/npc.c @@ -450,14 +450,17 @@ int npc_event_do_clock(int tid, int64 tick, int id, intptr_t data) { return c; } -/*========================================== - * OnInit Event execution (the start of the event and watch) - *------------------------------------------*/ -void npc_event_do_oninit(void) +/** + * OnInit event execution (the start of the event and watch) + * @param reload Is the server reloading? + **/ +void npc_event_do_oninit( bool reload ) { ShowStatus("Event '"CL_WHITE"OnInit"CL_RESET"' executed with '"CL_WHITE"%d"CL_RESET"' NPCs."CL_CLL"\n", npc->event_doall("OnInit")); - timer->add_interval(timer->gettick()+100,npc->event_do_clock,0,0,1000); + // This interval has already been added on startup + if( !reload ) + timer->add_interval(timer->gettick()+100,npc->event_do_clock,0,0,1000); } /*========================================== @@ -1298,23 +1301,23 @@ int npc_cashshop_buylist(struct map_session_data *sd, int points, int count, uns unsigned short shop_size = 0; if( sd->state.trading ) - return 4; + return ERROR_TYPE_EXCHANGE; if( count <= 0 ) - return 5; + return ERROR_TYPE_ITEM_ID; if( points < 0 ) - return 6; + return ERROR_TYPE_MONEY; if( !(nd = (struct npc_data *)map->id2bl(sd->npc_shopid)) ) - return 1; + return ERROR_TYPE_NPC; 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; + return ERROR_TYPE_NPC; } else { shop = nd->u.shop.shop_item; shop_size = nd->u.shop.count; @@ -1330,11 +1333,11 @@ int npc_cashshop_buylist(struct map_session_data *sd, int points, int count, uns amount = item_list[i*2+0]; if( !itemdb->exists(nameid) || amount <= 0 ) - return 5; + return ERROR_TYPE_ITEM_ID; ARR_FIND(0,shop_size,j,shop[j].nameid == nameid); if( j == shop_size || shop[j].value <= 0 ) - return 5; + return ERROR_TYPE_ITEM_ID; if( !itemdb->isstackable(nameid) && amount > 1 ) { ShowWarning("Player %s (%d:%d) sent a hexed packet trying to buy %d of nonstackable item %d!\n", @@ -1347,7 +1350,7 @@ int npc_cashshop_buylist(struct map_session_data *sd, int points, int count, uns new_++; break; case ADDITEM_OVERAMOUNT: - return 3; + return ERROR_TYPE_INVENTORY_WEIGHT; } vt += shop[j].value * amount; @@ -1355,20 +1358,20 @@ int npc_cashshop_buylist(struct map_session_data *sd, int points, int count, uns } if( w + sd->weight > sd->max_weight ) - return 3; + return ERROR_TYPE_INVENTORY_WEIGHT; if( pc->inventoryblank(sd) < new_ ) - return 3; + return ERROR_TYPE_INVENTORY_WEIGHT; if( points > vt ) points = vt; // Payment Process ---------------------------------------------------- if( nd->subtype == SCRIPT && nd->u.scr.shop->type == NST_CUSTOM ) { if( !npc->trader_pay(nd,sd,vt,points) ) - return 6; + return ERROR_TYPE_MONEY; } else { if( sd->kafraPoints < points || sd->cashPoints < (vt - points) ) - return 6; + return ERROR_TYPE_MONEY; pc->paycash(sd,vt,points); } // Delivery Process ---------------------------------------------------- @@ -1387,7 +1390,7 @@ int npc_cashshop_buylist(struct map_session_data *sd, int points, int count, uns } } - return 0; + return ERROR_TYPE_NONE; } //npc_buylist for script-controlled shops. @@ -1423,8 +1426,7 @@ void npc_market_fromsql(void) { 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`") + if ( SQL_ERROR == SQL->StmtPrepare(stmt, "SELECT `name`, `itemid`, `amount` FROM `%s`", map->npc_market_data_db) || SQL_ERROR == SQL->StmtExecute(stmt) ) { SqlStmt_ShowDebug(stmt); @@ -1471,20 +1473,20 @@ void npc_market_fromsql(void) { * 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) ) + if( SQL_ERROR == SQL->Query(map->mysql_handle, "REPLACE INTO `%s` VALUES ('%s','%d','%d')", + map->npc_market_data_db, 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_sub(const char *npcname, 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'", npcname) ) + if( SQL_ERROR == SQL->Query(map->mysql_handle, "DELETE FROM `%s` WHERE `name`='%s'", map->npc_market_data_db, npcname) ) 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", npcname, index) ) + if( SQL_ERROR == SQL->Query(map->mysql_handle, "DELETE FROM `%s` WHERE `name`='%s' AND `itemid`='%d' LIMIT 1", + map->npc_market_data_db, npcname, index) ) Sql_ShowDebug(map->mysql_handle); } } @@ -1517,7 +1519,7 @@ bool npc_trader_open(struct map_session_data *sd, struct npc_data *nd) { /* 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 */ + clif->colormes(sd->fd,COLOR_RED, msg_txt(881)); return false; } @@ -1631,26 +1633,26 @@ int npc_cashshop_buy(struct map_session_data *sd, int nameid, int amount, int po unsigned short shop_size = 0; if( amount <= 0 ) - return 5; + return ERROR_TYPE_ITEM_ID; if( points < 0 ) - return 6; + return ERROR_TYPE_MONEY; if( sd->state.trading ) - return 4; + return ERROR_TYPE_EXCHANGE; if( !(nd = (struct npc_data *)map->id2bl(sd->npc_shopid)) ) - return 1; + return ERROR_TYPE_NPC; if( (item = itemdb->exists(nameid)) == NULL ) - return 5; // Invalid Item + return ERROR_TYPE_ITEM_ID; // Invalid Item 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; + return ERROR_TYPE_NPC; } else { shop = nd->u.shop.shop_item; shop_size = nd->u.shop.count; @@ -1659,10 +1661,10 @@ int npc_cashshop_buy(struct map_session_data *sd, int nameid, int amount, int po ARR_FIND(0, shop_size, i, shop[i].nameid == nameid); if( i == shop_size ) - return 5; + return ERROR_TYPE_ITEM_ID; if( shop[i].value <= 0 ) - return 5; + return ERROR_TYPE_ITEM_ID; if(!itemdb->isstackable(nameid) && amount > 1) { ShowWarning("Player %s (%d:%d) sent a hexed packet trying to buy %d of nonstackable item %d!\n", @@ -1673,15 +1675,15 @@ int npc_cashshop_buy(struct map_session_data *sd, int nameid, int amount, int po switch( pc->checkadditem(sd, nameid, amount) ) { case ADDITEM_NEW: if( pc->inventoryblank(sd) == 0 ) - return 3; + return ERROR_TYPE_INVENTORY_WEIGHT; break; case ADDITEM_OVERAMOUNT: - return 3; + return ERROR_TYPE_INVENTORY_WEIGHT; } w = item->weight * amount; if( w + sd->weight > sd->max_weight ) - return 3; + return ERROR_TYPE_INVENTORY_WEIGHT; if( (double)shop[i].value * amount > INT_MAX ) { ShowWarning("npc_cashshop_buy: Item '%s' (%d) price overflow attempt!\n", item->name, nameid); @@ -1689,7 +1691,7 @@ int npc_cashshop_buy(struct map_session_data *sd, int nameid, int amount, int po 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, shop[i].value, amount); - return 5; + return ERROR_TYPE_ITEM_ID; } price = shop[i].value * amount; @@ -1699,10 +1701,10 @@ int npc_cashshop_buy(struct map_session_data *sd, int nameid, int amount, int po if( nd->subtype == SCRIPT && nd->u.scr.shop->type == NST_CUSTOM ) { if( !npc->trader_pay(nd,sd,price,points) ) - return 6; + return ERROR_TYPE_MONEY; } else { if( (sd->kafraPoints < points) || (sd->cashPoints < price - points) ) - return 6; + return ERROR_TYPE_MONEY; pc->paycash(sd, price, points); } @@ -1716,7 +1718,7 @@ int npc_cashshop_buy(struct map_session_data *sd, int nameid, int amount, int po pc->additem(sd,&item_tmp, amount, LOG_TYPE_NPC); } - return 0; + return ERROR_TYPE_NONE; } /// Player item purchase from npc shop. @@ -2612,7 +2614,7 @@ const char* npc_parse_shop(char* w1, char* w2, char* w3, char* w4, const char* s enum npc_subtype type; if( strcmp(w1,"-") == 0 ) { - // 'floating' shop? + // 'floating' shop x = y = dir = 0; m = -1; } else {// w1=<map name>,<x>,<y>,<facing> @@ -2711,7 +2713,7 @@ const char* npc_parse_shop(char* w1, char* w2, char* w3, char* w4, const char* s nd->dir = dir; if( map->list[nd->bl.m].users ) clif->spawn(&nd->bl); - } else {// 'floating' shop? + } else {// 'floating' shop map->addiddb(&nd->bl); } strdb_put(npc->name_db, nd->exname, nd); @@ -4294,14 +4296,39 @@ int npc_ev_label_db_clear_sub(DBKey key, DBData *data, va_list args) return 0; } +/** + * Main npc file processing + * @param npc_min Minimum npc id - used to know how many NPCs were loaded + **/ +void npc_process_files( int npc_min ) { + struct npc_src_list *file; // Current file + + ShowStatus("Loading NPCs...\r"); + for( file = npc->src_files; file != NULL; file = file->next ) { + ShowStatus("Loading NPC file: %s"CL_CLL"\r", file->name); + if (npc->parsesrcfile(file->name, false) != EXIT_SUCCESS) + map->retval = EXIT_FAILURE; + } + ShowInfo ("Done loading '"CL_WHITE"%d"CL_RESET"' NPCs:"CL_CLL"\n" + "\t-'"CL_WHITE"%d"CL_RESET"' Warps\n" + "\t-'"CL_WHITE"%d"CL_RESET"' Shops\n" + "\t-'"CL_WHITE"%d"CL_RESET"' Scripts\n" + "\t-'"CL_WHITE"%d"CL_RESET"' Spawn sets\n" + "\t-'"CL_WHITE"%d"CL_RESET"' Mobs Cached\n" + "\t-'"CL_WHITE"%d"CL_RESET"' Mobs Not Cached\n", + npc_id - npc_min, npc_warp, npc_shop, npc_script, npc_mob, npc_cache_mob, npc_delay_mob); +} + //Clear then reload npcs files int npc_reload(void) { - struct npc_src_list *nsl; int16 m, i; int npc_new_min = npc_id; struct s_mapiterator* iter; struct block_list* bl; + if (map->retval == EXIT_FAILURE) + map->retval = EXIT_SUCCESS; // Clear return status in case something failed before. + /* clear guild flag cache */ guild->flags_clear(); @@ -4358,46 +4385,35 @@ int npc_reload(void) { // reset mapflags map->flags_init(); - //TODO: the following code is copy-pasted from do_init_npc(); clean it up - // Reloading npcs now - for (nsl = npc->src_files; nsl; nsl = nsl->next) { - ShowStatus("Loading NPC file: %s"CL_CLL"\r", nsl->name); - npc->parsesrcfile(nsl->name,false); - } - ShowInfo ("Done loading '"CL_WHITE"%d"CL_RESET"' NPCs:"CL_CLL"\n" - "\t-'"CL_WHITE"%d"CL_RESET"' Warps\n" - "\t-'"CL_WHITE"%d"CL_RESET"' Shops\n" - "\t-'"CL_WHITE"%d"CL_RESET"' Scripts\n" - "\t-'"CL_WHITE"%d"CL_RESET"' Spawn sets\n" - "\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); - + // Reprocess npc files and reload constants itemdb->name_constants(); - + npc_process_files( npc_new_min ); + instance->reload(); map->zone_init(); - + npc->motd = npc->name2id("HerculesMOTD"); /* [Ind/Hercules] */ - + //Re-read the NPC Script Events cache. npc->read_event_script(); - /* refresh guild castle flags on both woe setups */ - npc->event_doall("OnAgitInit"); - npc->event_doall("OnAgitInit2"); - - //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 main initialisation events + // The correct initialisation order is: + // OnInit -> OnInterIfInit -> OnInterIfInitOnce -> OnAgitInit -> OnAgitInit2 + npc->event_do_oninit( true ); + npc->market_fromsql(); // Execute rest of the startup events if connected to char-server. [Lance] - if(!intif->CheckForCharServer()){ + // Executed when connection is established with char-server in chrif_connectack + if( !intif->CheckForCharServer() ) { ShowStatus("Event '"CL_WHITE"OnInterIfInit"CL_RESET"' executed with '"CL_WHITE"%d"CL_RESET"' NPCs.\n", npc->event_doall("OnInterIfInit")); ShowStatus("Event '"CL_WHITE"OnInterIfInitOnce"CL_RESET"' executed with '"CL_WHITE"%d"CL_RESET"' NPCs.\n", npc->event_doall("OnInterIfInitOnce")); } + // Refresh guild castle flags on both woe setups + // These events are only executed after receiving castle information from char-server + npc->event_doall("OnAgitInit"); + npc->event_doall("OnAgitInit2"); + return 0; } @@ -4479,7 +4495,6 @@ static void npc_debug_warps(void) { * npc initialization *------------------------------------------*/ int do_init_npc(bool minimal) { - struct npc_src_list *file; int i; memset(&npc->base_ud, 0, sizeof( struct unit_data) ); @@ -4508,28 +4523,17 @@ int do_init_npc(bool minimal) { npc_last_npd = NULL; npc_last_path = NULL; npc_last_ref = NULL; - + + // Should be loaded before npc processing, otherwise labels could overwrite constant values + // and lead to undefined behavior [Panikon] + itemdb->name_constants(); + if (!minimal) { npc->timer_event_ers = ers_new(sizeof(struct timer_event_data),"clif.c::timer_event_ers",ERS_OPT_NONE); - // process all npc files - ShowStatus("Loading NPCs...\r"); - for( file = npc->src_files; file != NULL; file = file->next ) { - ShowStatus("Loading NPC file: %s"CL_CLL"\r", file->name); - npc->parsesrcfile(file->name,false); - } - ShowInfo ("Done loading '"CL_WHITE"%d"CL_RESET"' NPCs:"CL_CLL"\n" - "\t-'"CL_WHITE"%d"CL_RESET"' Warps\n" - "\t-'"CL_WHITE"%d"CL_RESET"' Shops\n" - "\t-'"CL_WHITE"%d"CL_RESET"' Scripts\n" - "\t-'"CL_WHITE"%d"CL_RESET"' Spawn sets\n" - "\t-'"CL_WHITE"%d"CL_RESET"' Mobs Cached\n" - "\t-'"CL_WHITE"%d"CL_RESET"' Mobs Not Cached\n", - npc_id - START_NPC_NUM, npc_warp, npc_shop, npc_script, npc_mob, npc_cache_mob, npc_delay_mob); + npc_process_files(START_NPC_NUM); } - itemdb->name_constants(); - if (!minimal) { map->zone_init(); diff --git a/src/map/npc.h b/src/map/npc.h index a277d4968..6e9686d33 100644 --- a/src/map/npc.h +++ b/src/map/npc.h @@ -193,7 +193,7 @@ struct npc_interface { int (*event_doall_id) (const char *name, int rid); int (*event_doall) (const char *name); int (*event_do_clock) (int tid, int64 tick, int id, intptr_t data); - void (*event_do_oninit) (void); + void (*event_do_oninit) ( bool reload ); int (*timerevent_export) (struct npc_data *nd, int i); int (*timerevent) (int tid, int64 tick, int id, intptr_t data); int (*timerevent_start) (struct npc_data *nd, int rid); diff --git a/src/map/pc.c b/src/map/pc.c index 45adfe22a..08ff8baf9 100644 --- a/src/map/pc.c +++ b/src/map/pc.c @@ -4,7 +4,7 @@ #define HERCULES_CORE -#include "../config/core.h" // DBPATH, GP_BOUND_ITEMS, MAX_CARTS, MAX_SPIRITBALL, NEW_CARTS, RENEWAL, RENEWAL_ASPD, RENEWAL_CAST, RENEWAL_DROP, RENEWAL_EXP, SECURE_NPCTIMEOUT +#include "../config/core.h" // DBPATH, GP_BOUND_ITEMS, MAX_SPIRITBALL, RENEWAL, RENEWAL_ASPD, RENEWAL_CAST, RENEWAL_DROP, RENEWAL_EXP, SECURE_NPCTIMEOUT #include "pc.h" #include <stdio.h> @@ -45,7 +45,7 @@ #include "../common/conf.h" #include "../common/core.h" // get_svn_revision() #include "../common/malloc.h" -#include "../common/mmo.h" //NAME_LENGTH +#include "../common/mmo.h" // NAME_LENGTH, MAX_CARTS, NEW_CARTS #include "../common/nullpo.h" #include "../common/random.h" #include "../common/showmsg.h" @@ -8039,7 +8039,7 @@ int pc_setoption(struct map_session_data *sd,int type) *------------------------------------------*/ int pc_setcart(struct map_session_data *sd,int type) { #ifndef NEW_CARTS - int cart[6] = {0x0000,OPTION_CART1,OPTION_CART2,OPTION_CART3,OPTION_CART4,OPTION_CART5}; + int cart[6] = {OPTION_NOTHING,OPTION_CART1,OPTION_CART2,OPTION_CART3,OPTION_CART4,OPTION_CART5}; int option; #endif nullpo_ret(sd); diff --git a/src/map/pc.h b/src/map/pc.h index c4026a48d..5d723fcf8 100644 --- a/src/map/pc.h +++ b/src/map/pc.h @@ -21,7 +21,7 @@ #include "vending.h" // struct s_vending #include "../common/cbasetypes.h" #include "../common/ers.h" // struct eri -#include "../common/mmo.h" // JOB_*, MAX_FAME_LIST, struct fame_list, struct mmo_charstatus +#include "../common/mmo.h" // JOB_*, MAX_FAME_LIST, struct fame_list, struct mmo_charstatus, NEW_CARTS /** * Defines diff --git a/src/map/script.c b/src/map/script.c index e4cf7f227..b432e6720 100644 --- a/src/map/script.c +++ b/src/map/script.c @@ -4,7 +4,7 @@ #define HERCULES_CORE -#include "../config/core.h" // NEW_CARTS, RENEWAL, RENEWAL_ASPD, RENEWAL_CAST, RENEWAL_DROP, RENEWAL_EDP, RENEWAL_EXP, RENEWAL_LVDMG, SCRIPT_CALLFUNC_CHECK, SECURE_NPCTIMEOUT, SECURE_NPCTIMEOUT_INTERVAL +#include "../config/core.h" // RENEWAL, RENEWAL_ASPD, RENEWAL_CAST, RENEWAL_DROP, RENEWAL_EDP, RENEWAL_EXP, RENEWAL_LVDMG, SCRIPT_CALLFUNC_CHECK, SECURE_NPCTIMEOUT, SECURE_NPCTIMEOUT_INTERVAL #include "script.h" #include <math.h> @@ -45,6 +45,7 @@ #include "../common/cbasetypes.h" #include "../common/malloc.h" #include "../common/md5calc.h" +#include "../common/mmo.h" // NEW_CARTS #include "../common/nullpo.h" #include "../common/random.h" #include "../common/showmsg.h" @@ -2914,6 +2915,8 @@ int set_reg(struct script_state* st, TBL_PC* sd, int64 num, const char* name, co return pc_setglobalreg_str(sd, num, str); } } else {// integer variable + // FIXME: This isn't safe, in 32bits systems we're converting a 64bit pointer + // to a 32bit int, this will lead to overflows! [Panikon] int val = (int)__64BPTRSIZE(value); if(script->str_data[script_getvarid(num)].type == C_PARAM) { @@ -2921,7 +2924,11 @@ int set_reg(struct script_state* st, TBL_PC* sd, int64 num, const char* name, co if( st != NULL ) { ShowError("script:set_reg: failed to set param '%s' to %d.\n", name, val); script->reportsrc(st); - st->state = END; + // Instead of just stop the script execution we let the character close + // the window if it was open. + st->state = (sd->state.dialog) ? CLOSE : END; + if( st->state == CLOSE ) + clif->scriptclose(sd, st->oid); } return 0; } diff --git a/src/map/status.h b/src/map/status.h index baa586297..6bb563b0b 100644 --- a/src/map/status.h +++ b/src/map/status.h @@ -5,10 +5,10 @@ #ifndef _MAP_STATUS_H_ #define _MAP_STATUS_H_ -#include "../config/core.h" // defType, NEW_CARTS, RENEWAL, RENEWAL_ASPD +#include "../config/core.h" // defType, RENEWAL, RENEWAL_ASPD #include "../common/cbasetypes.h" -#include "../common/mmo.h" +#include "../common/mmo.h" // NEW_CARTS struct block_list; struct elemental_data; diff --git a/src/plugins/HPMHooking/HPMHooking.Hooks.inc b/src/plugins/HPMHooking/HPMHooking.Hooks.inc index e4f627c81..83af64c07 100644 --- a/src/plugins/HPMHooking/HPMHooking.Hooks.inc +++ b/src/plugins/HPMHooking/HPMHooking.Hooks.inc @@ -14350,14 +14350,14 @@ void HP_clif_friendlist_req(struct map_session_data *sd, int account_id, int cha } return; } -void HP_clif_GM_kickack(struct map_session_data *sd, int id) { +void HP_clif_GM_kickack(struct map_session_data *sd, int result) { int hIndex = 0; if( HPMHooks.count.HP_clif_GM_kickack_pre ) { - void (*preHookFunc) (struct map_session_data *sd, int *id); + void (*preHookFunc) (struct map_session_data *sd, int *result); *HPMforce_return = false; for(hIndex = 0; hIndex < HPMHooks.count.HP_clif_GM_kickack_pre; hIndex++ ) { preHookFunc = HPMHooks.list.HP_clif_GM_kickack_pre[hIndex].func; - preHookFunc(sd, &id); + preHookFunc(sd, &result); } if( *HPMforce_return ) { *HPMforce_return = false; @@ -14365,13 +14365,13 @@ void HP_clif_GM_kickack(struct map_session_data *sd, int id) { } } { - HPMHooks.source.clif.GM_kickack(sd, id); + HPMHooks.source.clif.GM_kickack(sd, result); } if( HPMHooks.count.HP_clif_GM_kickack_post ) { - void (*postHookFunc) (struct map_session_data *sd, int *id); + void (*postHookFunc) (struct map_session_data *sd, int *result); for(hIndex = 0; hIndex < HPMHooks.count.HP_clif_GM_kickack_post; hIndex++ ) { postHookFunc = HPMHooks.list.HP_clif_GM_kickack_post[hIndex].func; - postHookFunc(sd, &id); + postHookFunc(sd, &result); } } return; @@ -43052,14 +43052,14 @@ int HP_npc_event_do_clock(int tid, int64 tick, int id, intptr_t data) { } return retVal___; } -void HP_npc_event_do_oninit(void) { +void HP_npc_event_do_oninit(bool reload) { int hIndex = 0; if( HPMHooks.count.HP_npc_event_do_oninit_pre ) { - void (*preHookFunc) (void); + void (*preHookFunc) (bool *reload); *HPMforce_return = false; for(hIndex = 0; hIndex < HPMHooks.count.HP_npc_event_do_oninit_pre; hIndex++ ) { preHookFunc = HPMHooks.list.HP_npc_event_do_oninit_pre[hIndex].func; - preHookFunc(); + preHookFunc(&reload); } if( *HPMforce_return ) { *HPMforce_return = false; @@ -43067,13 +43067,13 @@ void HP_npc_event_do_oninit(void) { } } { - HPMHooks.source.npc.event_do_oninit(); + HPMHooks.source.npc.event_do_oninit(reload); } if( HPMHooks.count.HP_npc_event_do_oninit_post ) { - void (*postHookFunc) (void); + void (*postHookFunc) (bool *reload); for(hIndex = 0; hIndex < HPMHooks.count.HP_npc_event_do_oninit_post; hIndex++ ) { postHookFunc = HPMHooks.list.HP_npc_event_do_oninit_post[hIndex].func; - postHookFunc(); + postHookFunc(&reload); } } return; |