summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--conf/inter-server.conf1
-rw-r--r--conf/messages.conf4
-rw-r--r--doc/script_commands.txt41
-rw-r--r--npc/custom/quests/thq/THQS_TTShop.txt638
-rw-r--r--src/common/mmo.h8
-rw-r--r--src/config/const.h8
-rw-r--r--src/config/renewal.h12
-rw-r--r--src/map/atcommand.c4
-rw-r--r--src/map/clif.c21
-rw-r--r--src/map/clif.h18
-rw-r--r--src/map/map.c4
-rw-r--r--src/map/map.h1
-rw-r--r--src/map/npc.c184
-rw-r--r--src/map/npc.h2
-rw-r--r--src/map/pc.c6
-rw-r--r--src/map/pc.h2
-rw-r--r--src/map/script.c11
-rw-r--r--src/map/status.h4
-rw-r--r--src/plugins/HPMHooking/HPMHooking.Hooks.inc24
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;