* Implemented buying store system (aka. reverse vending, purchase shop) together with related skill and items, without NPCs.
- For SQL apply upgrade_svn14713_log.sql to upgrade tables `picklog` and `zenylog`; for TXT no action is necessary. - Requires 2010-04-20aRagexeRE or later and can be disabled in 'conf/battle/feature.conf'. git-svn-id: https://svn.code.sf.net/p/rathena/svn/trunk@14713 54d463be-8e91-2dee-dedb-b68131a5f0ec
This commit is contained in:
parent
5c70e95c79
commit
ce3f78556c
@ -1,5 +1,9 @@
|
||||
Date Added
|
||||
|
||||
2011/02/19
|
||||
* Implemented buying store system (aka. reverse vending, purchase shop) together with related skill and items, without NPCs. [Ai4rei]
|
||||
- For SQL apply upgrade_svn14713_log.sql to upgrade tables `picklog` and `zenylog`; for TXT no action is necessary.
|
||||
- Requires 2010-04-20aRagexeRE or later and can be disabled in 'conf/battle/feature.conf'.
|
||||
2011/02/17
|
||||
* Merged enumeration update from renewal [14699/branches/renewal] for a future commit. [Ai4rei]
|
||||
2011/02/16
|
||||
|
@ -1,5 +1,8 @@
|
||||
Date Added
|
||||
|
||||
2011/02/19
|
||||
* Rev. 14713 Added map-server feature settings file 'battle/feature.conf'. [Ai4rei]
|
||||
- Added setting 'feature.buying_store' to enable/disable the buying store system.
|
||||
2011/02/15
|
||||
* Rev. 14707 Added map-server battle setting 'gm_check_minlevel'. [Ai4rei]
|
||||
2011/02/06
|
||||
|
24
conf/battle/feature.conf
Normal file
24
conf/battle/feature.conf
Normal file
@ -0,0 +1,24 @@
|
||||
// ______ __ __
|
||||
// /\ _ \/\ \__/\ \
|
||||
// __\ \ \L\ \ \ ,_\ \ \___ __ ___ __
|
||||
// /'__`\ \ __ \ \ \/\ \ _ `\ /'__`\/' _ `\ /'__`\
|
||||
///\ __/\ \ \/\ \ \ \_\ \ \ \ \/\ __//\ \/\ \/\ \L\.\_
|
||||
//\ \____\\ \_\ \_\ \__\\ \_\ \_\ \____\ \_\ \_\ \__/.\_\
|
||||
// \/____/ \/_/\/_/\/__/ \/_/\/_/\/____/\/_/\/_/\/__/\/_/
|
||||
// _ _ _ _ _ _ _ _ _ _ _ _ _
|
||||
// / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \
|
||||
//( e | n | g | l | i | s | h ) ( A | t | h | e | n | a )
|
||||
// \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/
|
||||
//
|
||||
//--------------------------------------------------------------
|
||||
// eAthena Feature Configuration File
|
||||
//--------------------------------------------------------------
|
||||
// Note 1: Value is a config switch (on/off, yes/no or 1/0)
|
||||
// Note 2: Value is in percents (100 means 100%)
|
||||
// Note 3: Value is a bit field. If no description is given,
|
||||
// assume unit types (1: Pc, 2: Mob, 4: Pet, 8: Homun)
|
||||
//--------------------------------------------------------------
|
||||
|
||||
// Buying store (Note 1)
|
||||
// Requires: 2010-04-20aRagexeRE or later
|
||||
feature.buying_store: on
|
@ -16,6 +16,7 @@
|
||||
// 2048 - (R) Log items placed/retrieved from storage.
|
||||
// 4096 - (G) Log items placed/retrieved from guild storage.
|
||||
// 8192 - (E) Log mail system transactions.
|
||||
// 16384 - (B) Log buying store transactions
|
||||
// Example: Log trades+vending+script items+created items: 2+4+64+1024 = 1094
|
||||
enable_logs: 1
|
||||
|
||||
|
@ -9,6 +9,12 @@
|
||||
13005 Angelic Wing Dagger: NEED INFO.
|
||||
=======================
|
||||
|
||||
2011/02/19
|
||||
* Rev. 14713 Database updates required by buying store system implementation. [Ai4rei]
|
||||
- Added database of items, that can be sold to a buying store (item_buyingstore.txt).
|
||||
- Added items Buy_Stall_Permit (6377) and Shabby_Purchase_Street_Stall_License (12548).
|
||||
- Updated packet database with buying store related packets.
|
||||
- Added skill 'Open Buying Store' (ALL_BUYING_STORE).
|
||||
2011/02/06
|
||||
* Rev. 14697 Added the missing restricted skills to zone 6 for Endless Tower. (bugreport:4707) [L0ne_W0lf]
|
||||
* Adjusted the rates for item using bAddEffOnSkill bonus.
|
||||
|
1013
db/item_buyingstore.txt
Normal file
1013
db/item_buyingstore.txt
Normal file
File diff suppressed because it is too large
Load Diff
@ -3293,7 +3293,7 @@
|
||||
//6362,Yellow_Wish_Point,Yellow Wish Point,3,100,,5,,,,,,,,,,,,,{},{},{}
|
||||
//6363,Lime_Green_Point,Lime Green Point,3,100,,5,,,,,,,,,,,,,{},{},{}
|
||||
//6376,KVM_Badge
|
||||
//6377,Buy_Stall_Permit,Purchase Street Stall License,3,200,,10,,,,,,,,,,,,,{},{},{}
|
||||
6377,Buy_Stall_Permit,Purchase Street Stall License,3,200,,10,,,,,,,,,,,,,{},{},{}
|
||||
//6378
|
||||
//6379
|
||||
//6380
|
||||
@ -4823,7 +4823,7 @@
|
||||
//12471,LV5_Adrenaline_Scroll,
|
||||
//12472,Convex_Mirror,
|
||||
//12475,Cure_Free,
|
||||
//12548,Shabby_Purchase_Street_Stall_License,
|
||||
12548,Shabby_Purchase_Street_Stall_License,Shabby Purchase Street Stall License,2,500,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ buyingstore 2; },{},{}
|
||||
//12553,Brysingamen_Piece_Box,
|
||||
//12554,Asprika_Piece_Box,
|
||||
//12555,Brynhild_Piece_Box,
|
||||
|
@ -1488,8 +1488,8 @@ packet_ver: 25
|
||||
0x080F,20
|
||||
|
||||
//2010-03-03aRagexeRE
|
||||
//0x0810,3
|
||||
//0x0811,-1
|
||||
0x0810,3
|
||||
0x0811,-1,reqopenbuyingstore,2:4:8:9:89
|
||||
//0x0812,86
|
||||
//0x0813,6
|
||||
//0x0814,6
|
||||
@ -1499,11 +1499,11 @@ packet_ver: 25
|
||||
//0x0819,4
|
||||
|
||||
//2010-03-09aRagexeRE
|
||||
//0x0813,-1
|
||||
0x0813,-1
|
||||
//0x0814,2
|
||||
//0x0815,6
|
||||
//0x0816,6
|
||||
//0x0818,-1
|
||||
0x0816,6
|
||||
0x0818,-1
|
||||
//0x0819,10
|
||||
//0x081A,4
|
||||
//0x081B,4
|
||||
@ -1528,15 +1528,15 @@ packet_ver: 25
|
||||
//0x081B,8
|
||||
|
||||
//2010-04-20aRagexeRE
|
||||
//0x0812,8
|
||||
//0x0814,86
|
||||
//0x0815,2
|
||||
//0x0817,6
|
||||
//0x0819,-1
|
||||
//0x081a,4
|
||||
//0x081b,10
|
||||
//0x081c,10
|
||||
//0x0824,6
|
||||
0x0812,8
|
||||
0x0814,86
|
||||
0x0815,2,reqclosebuyingstore,0
|
||||
0x0817,6,reqclickbuyingstore,2
|
||||
0x0819,-1,reqtradebuyingstore,2:4:8:12
|
||||
0x081a,4
|
||||
0x081b,10
|
||||
0x081c,10
|
||||
0x0824,6
|
||||
|
||||
//2010-06-01aRagexeRE
|
||||
//0x0825,-1
|
||||
|
@ -938,6 +938,9 @@
|
||||
// Episode 13.3
|
||||
//2534,0,0,0,0,0,0,9,0,no,0,0,0,none,0 RETURN_TO_ELDICASTES,
|
||||
|
||||
// Buying Store
|
||||
2535,0,0,4,0,0x1,0,1,0,no,0,0x1,0,none,0, ALL_BUYING_STORE,Open Buying Store
|
||||
|
||||
8001,9,6,4,0,0x1,0,5,1,no,0,0,0,magic,0, HLIF_HEAL,Healing Touch
|
||||
8002,0,6,4,0,0x3,-1,5,1,no,0,0,0,none,0, HLIF_AVOID,Avoid
|
||||
8003,0,0,0,0,0,1,5,0,no,0,0,0,none,0, HLIF_BRAIN,Brain Surgery
|
||||
|
@ -454,6 +454,8 @@
|
||||
1018,0,0,30,0,0,0,99,0,0,none,0,12114,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //SA_ELEMENTFIRE
|
||||
1019,0,0,30,0,0,0,99,0,0,none,0,12117,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //SA_ELEMENTWIND
|
||||
|
||||
2535,0,0,1,0,0,0,99,0,0,none,0,6377,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //ALL_BUYING_STORE#Open Buying Store
|
||||
|
||||
10010,0,0,1,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //GD_BATTLEORDER##
|
||||
10011,0,0,1,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //GD_REGENERATION##
|
||||
10012,0,0,1,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //GD_RESTORE##
|
||||
|
@ -86,6 +86,7 @@
|
||||
5,155,1,0,0,0,0,0,0,0,0,0,0 //MC_LOUD#Crazy Uproar#
|
||||
5,410,1,0,0,0,0,0,0,0,0,0,0 //WE_CALLBABY#Call Baby#
|
||||
5,681,1,0,0,0,0,0,0,0,0,0,0 //ALL_INCCARRY#Enlarge Weight Limit R#
|
||||
5,2535,1,41,1,0,0,0,0,0,0,0,0 //ALL_BUYING_STORE#Open Buying Store#
|
||||
//Thief
|
||||
6,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill#
|
||||
6,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid#
|
||||
@ -240,6 +241,7 @@
|
||||
10,410,1,0,0,0,0,0,0,0,0,0,0 //WE_CALLBABY#Call Baby#
|
||||
10,459,1,111,5,0,0,0,0,0,0,0,0 //BS_ADRENALINE2#Full Adrenaline Rush#
|
||||
10,681,1,0,0,0,0,0,0,0,0,0,0 //ALL_INCCARRY#Enlarge Weight Limit R#
|
||||
10,2535,1,41,1,0,0,0,0,0,0,0,0 //ALL_BUYING_STORE#Open Buying Store#
|
||||
//Hunter
|
||||
11,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill#
|
||||
11,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid#
|
||||
@ -511,6 +513,7 @@
|
||||
18,497,1,228,10,0,0,0,0,0,0,0,0 //AM_TWILIGHT2#Twilight Alchemy 2#
|
||||
18,498,1,228,10,0,0,0,0,0,0,0,0 //AM_TWILIGHT3#Twilight Alchemy 3#
|
||||
18,681,1,0,0,0,0,0,0,0,0,0,0 //ALL_INCCARRY#Enlarge Weight Limit R#
|
||||
18,2535,1,41,1,0,0,0,0,0,0,0,0 //ALL_BUYING_STORE#Open Buying Store#
|
||||
//Bard
|
||||
19,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill#
|
||||
19,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid#
|
||||
@ -668,6 +671,7 @@
|
||||
23,53,1,52,3,0,0,0,0,0,0,0,0 //TF_DETOXIFY#Detoxify#
|
||||
23,410,1,0,0,0,0,0,0,0,0,0,0 //WE_CALLBABY#Call Baby#
|
||||
23,681,1,0,0,0,0,0,0,0,0,0,0 //ALL_INCCARRY#Enlarge Weight Limit R#
|
||||
23,2535,1,41,1,0,0,0,0,0,0,0,0 //ALL_BUYING_STORE#Open Buying Store#
|
||||
//Gunslinger
|
||||
24,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill#
|
||||
24,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid#
|
||||
@ -810,6 +814,7 @@
|
||||
4006,155,1,0,0,0,0,0,0,0,0,0,0 //MC_LOUD#Crazy Uproar#
|
||||
4006,410,1,0,0,0,0,0,0,0,0,0,0 //WE_CALLBABY#Call Baby#
|
||||
4006,681,1,0,0,0,0,0,0,0,0,0,0 //ALL_INCCARRY#Enlarge Weight Limit R#
|
||||
4006,2535,1,41,1,0,0,0,0,0,0,0,0 //ALL_BUYING_STORE#Open Buying Store#
|
||||
//ThiefHigh
|
||||
4007,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill#
|
||||
4007,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid#
|
||||
@ -989,6 +994,7 @@
|
||||
4011,410,1,0,0,0,0,0,0,0,0,0,0 //WE_CALLBABY#Call Baby#
|
||||
4011,459,1,111,5,0,0,0,0,0,0,0,0 //BS_ADRENALINE2#Full Adrenaline Rush#
|
||||
4011,681,1,0,0,0,0,0,0,0,0,0,0 //ALL_INCCARRY#Enlarge Weight Limit R#
|
||||
4011,2535,1,41,1,0,0,0,0,0,0,0,0 //ALL_BUYING_STORE#Open Buying Store#
|
||||
//Sniper
|
||||
4012,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill#
|
||||
4012,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid#
|
||||
@ -1303,6 +1309,7 @@
|
||||
4019,497,1,228,10,0,0,0,0,0,0,0,0 //AM_TWILIGHT2#Twilight Alchemy 2#
|
||||
4019,498,1,228,10,0,0,0,0,0,0,0,0 //AM_TWILIGHT3#Twilight Alchemy 3#
|
||||
4019,681,1,0,0,0,0,0,0,0,0,0,0 //ALL_INCCARRY#Enlarge Weight Limit R#
|
||||
4019,2535,1,41,1,0,0,0,0,0,0,0,0 //ALL_BUYING_STORE#Open Buying Store#
|
||||
//Clown
|
||||
4020,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill#
|
||||
4020,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid#
|
||||
@ -1508,6 +1515,7 @@
|
||||
4028,408,1,0,0,0,0,0,0,0,0,0,0 //WE_BABY#Baby#
|
||||
4028,409,1,0,0,0,0,0,0,0,0,0,0 //WE_CALLPARENT#Call Parent#
|
||||
4028,681,1,0,0,0,0,0,0,0,0,0,0 //ALL_INCCARRY#Enlarge Weight Limit R#
|
||||
4028,2535,1,41,1,0,0,0,0,0,0,0,0 //ALL_BUYING_STORE#Open Buying Store#
|
||||
//Baby Thief
|
||||
4029,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill#
|
||||
4029,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid#
|
||||
@ -1666,6 +1674,7 @@
|
||||
4033,1013,1,0,0,0,0,0,0,0,0,0,0 //BS_GREED#Greed#
|
||||
4033,459,1,111,5,0,0,0,0,0,0,0,0 //BS_ADRENALINE2#Full Adrenaline Rush#
|
||||
4033,681,1,0,0,0,0,0,0,0,0,0,0 //ALL_INCCARRY#Enlarge Weight Limit R#
|
||||
4033,2535,1,41,1,0,0,0,0,0,0,0,0 //ALL_BUYING_STORE#Open Buying Store#
|
||||
//Baby Hunter
|
||||
4034,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill#
|
||||
4034,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid#
|
||||
@ -1945,6 +1954,7 @@
|
||||
4041,497,1,228,10,0,0,0,0,0,0,0,0 //AM_TWILIGHT2#Twilight Alchemy 2#
|
||||
4041,498,1,228,10,0,0,0,0,0,0,0,0 //AM_TWILIGHT3#Twilight Alchemy 3#
|
||||
4041,681,1,0,0,0,0,0,0,0,0,0,0 //ALL_INCCARRY#Enlarge Weight Limit R#
|
||||
4041,2535,1,41,1,0,0,0,0,0,0,0,0 //ALL_BUYING_STORE#Open Buying Store#
|
||||
//Baby Bard
|
||||
4042,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill#
|
||||
4042,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid#
|
||||
@ -2099,6 +2109,7 @@
|
||||
4045,408,1,0,0,0,0,0,0,0,0,0,0 //WE_BABY#Baby#
|
||||
4045,409,1,0,0,0,0,0,0,0,0,0,0 //WE_CALLPARENT#Call Parent#
|
||||
4045,681,1,0,0,0,0,0,0,0,0,0,0 //ALL_INCCARRY#Enlarge Weight Limit R#
|
||||
4045,2535,1,41,1,0,0,0,0,0,0,0,0 //ALL_BUYING_STORE#Open Buying Store#
|
||||
//Taekwon
|
||||
4046,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill#
|
||||
4046,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid#
|
||||
|
@ -4,7 +4,7 @@
|
||||
//= A reference manual for the eAthena scripting language.
|
||||
//= Commands are sorted depending on their functionality.
|
||||
//===== Version ===========================================
|
||||
//= 3.35.20110106
|
||||
//= 3.36.20110219
|
||||
//=========================================================
|
||||
//= 1.0 - First release, filled will as much info as I could
|
||||
//= remember or figure out, most likely there are errors,
|
||||
@ -155,6 +155,8 @@
|
||||
//= Spellcheck. [Ai4rei]
|
||||
//= 3.35.20110106
|
||||
//= Removed bug warning from 'deletearray'. [Ai4rei]
|
||||
//= 3.36.20110219
|
||||
//= Added 'buyingstore' command. [Ai4rei]
|
||||
//=========================================================
|
||||
|
||||
This document is a reference manual for all the scripting commands and functions
|
||||
@ -4423,6 +4425,19 @@ Example(s):
|
||||
//The invoked character will no longer automatically equip a falchion.
|
||||
autoequip 1104,0;
|
||||
|
||||
---------------------------------------
|
||||
|
||||
*buyingstore <slots>;
|
||||
|
||||
Invokes buying store preparation window like the skill 'Open Buying Store',
|
||||
without the item requirement. Amount of slots is limited by the server to
|
||||
a maximum of 5 slots by default.
|
||||
|
||||
Example:
|
||||
|
||||
// Gives the player oppurtunity to buy 4 different kinds of items.
|
||||
buyingstore 4;
|
||||
|
||||
---------------------------------------
|
||||
//
|
||||
4,1.- End of item-related commands
|
||||
|
@ -1,7 +1,7 @@
|
||||
#PickLog types (M)onsters Drop, (P)layers Drop/Take, Mobs Drop (L)oot Drop/Take,
|
||||
# Players (T)rade Give/Take, Players (V)ending Sell/Take, (S)hop Sell/Take, (N)PC Give/Take,
|
||||
# (C)onsumable Items, (A)dministrators Create/Delete, Sto(R)age, (G)uild Storage,
|
||||
# (E)mail attachment
|
||||
# (E)mail attachment,(B)uying Store
|
||||
|
||||
#Database: log
|
||||
#Table: picklog
|
||||
@ -9,7 +9,7 @@ CREATE TABLE `picklog` (
|
||||
`id` int(11) NOT NULL auto_increment,
|
||||
`time` datetime NOT NULL default '0000-00-00 00:00:00',
|
||||
`char_id` int(11) NOT NULL default '0',
|
||||
`type` enum('M','P','L','T','V','S','N','C','A','R','G','E') NOT NULL default 'P',
|
||||
`type` enum('M','P','L','T','V','S','N','C','A','R','G','E','B') NOT NULL default 'P',
|
||||
`nameid` int(11) NOT NULL default '0',
|
||||
`amount` int(11) NOT NULL default '1',
|
||||
`refine` tinyint(3) unsigned NOT NULL default '0',
|
||||
@ -22,7 +22,7 @@ CREATE TABLE `picklog` (
|
||||
INDEX (`type`)
|
||||
) ENGINE=MyISAM AUTO_INCREMENT=1 ;
|
||||
|
||||
#ZenyLog types (M)onsters,(T)rade,(V)ending Sell/Buy,(S)hop Sell/Buy,(N)PC Change amount,(A)dministrators,(E)Mail
|
||||
#ZenyLog types (M)onsters,(T)rade,(V)ending Sell/Buy,(S)hop Sell/Buy,(N)PC Change amount,(A)dministrators,(E)Mail,(B)uying Store
|
||||
#Database: log
|
||||
#Table: zenylog
|
||||
CREATE TABLE `zenylog` (
|
||||
@ -30,7 +30,7 @@ CREATE TABLE `zenylog` (
|
||||
`time` datetime NOT NULL default '0000-00-00 00:00:00',
|
||||
`char_id` int(11) NOT NULL default '0',
|
||||
`src_id` int(11) NOT NULL default '0',
|
||||
`type` enum('M','T','V','S','N','A','E') NOT NULL default 'S',
|
||||
`type` enum('M','T','V','S','N','A','E','B') NOT NULL default 'S',
|
||||
`amount` int(11) NOT NULL default '0',
|
||||
`map` varchar(11) NOT NULL default '',
|
||||
PRIMARY KEY (`id`),
|
||||
|
4
sql-files/upgrade_svn14713_log.sql
Normal file
4
sql-files/upgrade_svn14713_log.sql
Normal file
@ -0,0 +1,4 @@
|
||||
-- Adds 'B' to `type` in `picklog` and `zenylog`
|
||||
|
||||
ALTER TABLE `picklog` MODIFY `type` ENUM('M','P','L','T','V','S','N','C','A','R','G','E','B') NOT NULL DEFAULT 'P';
|
||||
ALTER TABLE `zenylog` MODIFY `type` ENUM('M','T','V','S','N','A','E','B') NOT NULL DEFAULT 'S';
|
@ -84,7 +84,7 @@
|
||||
#define MAX_ZENY 1000000000
|
||||
#define MAX_FAME 1000000000
|
||||
#define MAX_CART 100
|
||||
#define MAX_SKILL 1020
|
||||
#define MAX_SKILL 2536
|
||||
#define GLOBAL_REG_NUM 256
|
||||
#define ACCOUNT_REG_NUM 64
|
||||
#define ACCOUNT_REG2_NUM 16
|
||||
|
@ -17,7 +17,8 @@ MAP_OBJ = map.o chrif.o clif.o pc.o status.o npc.o \
|
||||
npc_chat.o chat.o path.o itemdb.o mob.o script.o \
|
||||
storage.o skill.o atcommand.o battle.o battleground.o \
|
||||
intif.o trade.o party.o vending.o guild.o pet.o \
|
||||
log.o mail.o date.o unit.o homunculus.o mercenary.o quest.o instance.o
|
||||
log.o mail.o date.o unit.o homunculus.o mercenary.o quest.o instance.o \
|
||||
buyingstore.o
|
||||
MAP_TXT_OBJ = $(MAP_OBJ:%=obj_txt/%) \
|
||||
obj_txt/mapreg_txt.o
|
||||
MAP_SQL_OBJ = $(MAP_OBJ:%=obj_sql/%) \
|
||||
@ -26,7 +27,8 @@ MAP_H = map.h chrif.h clif.h pc.h status.h npc.h \
|
||||
chat.h itemdb.h mob.h script.h path.h \
|
||||
storage.h skill.h atcommand.h battle.h battleground.h \
|
||||
intif.h trade.h party.h vending.h guild.h pet.h \
|
||||
log.h mail.h date.h unit.h homunculus.h mercenary.h quest.h instance.h mapreg.h
|
||||
log.h mail.h date.h unit.h homunculus.h mercenary.h quest.h instance.h mapreg.h \
|
||||
buyingstore.h
|
||||
|
||||
HAVE_MYSQL=@HAVE_MYSQL@
|
||||
ifeq ($(HAVE_MYSQL),yes)
|
||||
|
@ -1150,7 +1150,7 @@ ACMD_FUNC(storage)
|
||||
{
|
||||
nullpo_retr(-1, sd);
|
||||
|
||||
if (sd->npc_id || sd->vender_id || sd->state.trading || sd->state.storage_flag)
|
||||
if (sd->npc_id || sd->vender_id || sd->state.buyingstore || sd->state.trading || sd->state.storage_flag)
|
||||
return -1;
|
||||
|
||||
if (storage_storageopen(sd) == 1)
|
||||
@ -1177,7 +1177,7 @@ ACMD_FUNC(guildstorage)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (sd->npc_id || sd->vender_id || sd->state.trading)
|
||||
if (sd->npc_id || sd->vender_id || sd->state.buyingstore || sd->state.trading)
|
||||
return -1;
|
||||
|
||||
if (sd->state.storage_flag == 1) {
|
||||
|
@ -4007,6 +4007,7 @@ static const struct _battle_data {
|
||||
{ "client_reshuffle_dice", &battle_config.client_reshuffle_dice, 0, 0, 1, },
|
||||
{ "client_sort_storage", &battle_config.client_sort_storage, 0, 0, 1, },
|
||||
{ "gm_check_minlevel", &battle_config.gm_check_minlevel, 60, 0, 100, },
|
||||
{ "feature_buying_store", &battle_config.feature_buying_store, 1, 0, 1, },
|
||||
// BattleGround Settings
|
||||
{ "bg_update_interval", &battle_config.bg_update_interval, 1000, 100, INT_MAX, },
|
||||
{ "bg_short_attack_damage_rate", &battle_config.bg_short_damage_rate, 80, 0, INT_MAX, },
|
||||
|
@ -481,6 +481,7 @@ extern struct Battle_Config
|
||||
int client_reshuffle_dice; // Reshuffle /dice
|
||||
int client_sort_storage;
|
||||
int gm_check_minlevel; // min GM level for /check
|
||||
int feature_buying_store;
|
||||
|
||||
// [BattleGround Settings]
|
||||
int bg_update_interval;
|
||||
|
359
src/map/buyingstore.c
Normal file
359
src/map/buyingstore.c
Normal file
@ -0,0 +1,359 @@
|
||||
// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
|
||||
// For more information, see LICENCE in the main folder
|
||||
|
||||
#include "../common/cbasetypes.h"
|
||||
#include "../common/db.h" // ARR_FIND
|
||||
#include "../common/showmsg.h" // ShowWarning
|
||||
#include "../common/socket.h" // RBUF*
|
||||
#include "../common/strlib.h" // safestrncpy
|
||||
#include "atcommand.h" // msg_txt
|
||||
#include "battle.h" // battle_config.*
|
||||
#include "buyingstore.h" // struct s_buyingstore
|
||||
#include "clif.h" // clif_buyingstore_*
|
||||
#include "log.h" // log_pick_pc, log_zeny
|
||||
#include "pc.h" // struct map_session_data
|
||||
|
||||
|
||||
/// constants (client-side restrictions)
|
||||
#define BUYINGSTORE_MAX_PRICE 99990000
|
||||
#define BUYINGSTORE_MAX_AMOUNT 9999
|
||||
|
||||
|
||||
/// failure constants for clif functions
|
||||
enum e_buyingstore_failure
|
||||
{
|
||||
BUYINGSTORE_CREATE = 1, // "Failed to open buying store."
|
||||
BUYINGSTORE_CREATE_OVERWEIGHT = 2, // "Total amount of then possessed items exceeds the weight limit by %d. Please re-enter."
|
||||
BUYINGSTORE_TRADE_BUYER_ZENY = 3, // "All items within the buy limit were purchased."
|
||||
BUYINGSTORE_TRADE_BUYER_NO_ITEMS = 4, // "All items were purchased."
|
||||
BUYINGSTORE_TRADE_SELLER_FAILED = 5, // "The deal has failed."
|
||||
BUYINGSTORE_TRADE_SELLER_COUNT = 6, // "The trade failed, because the entered amount of item %s is higher, than the buyer is willing to buy."
|
||||
BUYINGSTORE_TRADE_SELLER_ZENY = 7, // "The trade failed, because the buyer is lacking required balance."
|
||||
BUYINGSTORE_CREATE_NO_INFO = 8, // "No sale (purchase) information available."
|
||||
};
|
||||
|
||||
|
||||
static unsigned int buyingstore_nextid = 0;
|
||||
|
||||
|
||||
/// Returns unique buying store id
|
||||
static unsigned int buyingstore_getuid(void)
|
||||
{
|
||||
return buyingstore_nextid++;
|
||||
}
|
||||
|
||||
|
||||
bool buyingstore_setup(struct map_session_data* sd, unsigned char slots)
|
||||
{
|
||||
if( !battle_config.feature_buying_store || sd->vender_id || sd->state.buyingstore || sd->state.trading || slots == 0 )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if( slots > MAX_BUYINGSTORE_SLOTS )
|
||||
{
|
||||
ShowWarning("buyingstore_setup: Requested %d slots, but server supports only %d slots.\n", (int)slots, MAX_BUYINGSTORE_SLOTS);
|
||||
slots = MAX_BUYINGSTORE_SLOTS;
|
||||
}
|
||||
|
||||
sd->buyingstore.slots = slots;
|
||||
clif_buyingstore_open(sd);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void buyingstore_create(struct map_session_data* sd, int zenylimit, unsigned char result, const char* storename, const uint8* itemlist, unsigned int count)
|
||||
{
|
||||
unsigned int i, weight, listidx;
|
||||
struct item_data* id;
|
||||
|
||||
if( !result || count == 0 )
|
||||
{// canceled, or no items
|
||||
return;
|
||||
}
|
||||
|
||||
if( !battle_config.feature_buying_store || pc_istrading(sd) || sd->buyingstore.slots == 0 || count > sd->buyingstore.slots || zenylimit <= 0 || zenylimit > sd->status.zeny || !storename[0] )
|
||||
{// disabled or invalid input
|
||||
sd->buyingstore.slots = 0;
|
||||
clif_buyingstore_open_failed(sd, BUYINGSTORE_CREATE, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
if( !pc_can_give_items(pc_isGM(sd)) )
|
||||
{// custom: GM is not allowed to buy (give zeny)
|
||||
sd->buyingstore.slots = 0;
|
||||
clif_displaymessage(sd->fd, msg_txt(246));
|
||||
clif_buyingstore_open_failed(sd, BUYINGSTORE_CREATE, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
weight = sd->weight;
|
||||
|
||||
// check item list
|
||||
for( i = 0; i < count; i++ )
|
||||
{// itemlist: <name id>.W <amount>.W <price>.L
|
||||
unsigned short nameid, amount;
|
||||
int price, idx;
|
||||
|
||||
nameid = RBUFW(itemlist,i*8+0);
|
||||
amount = RBUFW(itemlist,i*8+2);
|
||||
price = RBUFL(itemlist,i*8+4);
|
||||
|
||||
if( ( id = itemdb_exists(nameid) ) == NULL || amount == 0 )
|
||||
{// invalid input
|
||||
break;
|
||||
}
|
||||
|
||||
if( price <= 0 || price > BUYINGSTORE_MAX_PRICE )
|
||||
{// invalid price: unlike vending, items cannot be bought at 0 Zeny
|
||||
break;
|
||||
}
|
||||
|
||||
if( !id->flag.buyingstore || !itemdb_cantrade_sub(id, pc_isGM(sd), pc_isGM(sd)) || ( idx = pc_search_inventory(sd, nameid) ) == -1 )
|
||||
{// restrictions: allowed, no character-bound items and at least one must be owned
|
||||
break;
|
||||
}
|
||||
|
||||
if( sd->status.inventory[idx].amount+amount > BUYINGSTORE_MAX_AMOUNT )
|
||||
{// too many items of same kind
|
||||
break;
|
||||
}
|
||||
|
||||
if( i )
|
||||
{// duplicate check. as the client does this too, only malicious intent should be caught here
|
||||
ARR_FIND( 0, i, listidx, sd->buyingstore.items[i].nameid == nameid );
|
||||
if( listidx != i )
|
||||
{// duplicate
|
||||
ShowWarning("buyingstore_create: Found duplicate item on buying list (nameid=%hu, amount=%hu, account_id=%d, char_id=%d).\n", nameid, amount, sd->status.account_id, sd->status.char_id);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
weight+= id->weight*amount;
|
||||
sd->buyingstore.items[i].nameid = nameid;
|
||||
sd->buyingstore.items[i].amount = amount;
|
||||
sd->buyingstore.items[i].price = price;
|
||||
}
|
||||
|
||||
if( i != count )
|
||||
{// invalid item/amount/price
|
||||
sd->buyingstore.slots = 0;
|
||||
clif_buyingstore_open_failed(sd, BUYINGSTORE_CREATE, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
if( (sd->max_weight*90)/100 < weight )
|
||||
{// not able to carry all wanted items without getting overweight (90%)
|
||||
sd->buyingstore.slots = 0;
|
||||
clif_buyingstore_open_failed(sd, BUYINGSTORE_CREATE_OVERWEIGHT, weight);
|
||||
return;
|
||||
}
|
||||
|
||||
// success
|
||||
sd->state.buyingstore = true;
|
||||
sd->buyer_id = buyingstore_getuid();
|
||||
sd->buyingstore.zenylimit = zenylimit;
|
||||
sd->buyingstore.slots = i; // store actual amount of items
|
||||
safestrncpy(sd->message, storename, sizeof(sd->message));
|
||||
clif_buyingstore_myitemlist(sd);
|
||||
clif_buyingstore_entry(sd);
|
||||
}
|
||||
|
||||
|
||||
void buyingstore_close(struct map_session_data* sd)
|
||||
{
|
||||
if( sd->state.buyingstore )
|
||||
{
|
||||
// invalidate data
|
||||
sd->state.buyingstore = false;
|
||||
memset(&sd->buyingstore, 0, sizeof(sd->buyingstore));
|
||||
|
||||
// notify other players
|
||||
clif_buyingstore_disappear_entry(sd);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void buyingstore_open(struct map_session_data* sd, int account_id)
|
||||
{
|
||||
struct map_session_data* pl_sd;
|
||||
|
||||
if( !battle_config.feature_buying_store || pc_istrading(sd) )
|
||||
{// not allowed to sell
|
||||
return;
|
||||
}
|
||||
|
||||
if( !pc_can_give_items(pc_isGM(sd)) )
|
||||
{// custom: GM is not allowed to sell
|
||||
clif_displaymessage(sd->fd, msg_txt(246));
|
||||
return;
|
||||
}
|
||||
|
||||
if( ( pl_sd = map_id2sd(account_id) ) == NULL || !pl_sd->state.buyingstore )
|
||||
{// not online or not buying
|
||||
return;
|
||||
}
|
||||
|
||||
// success
|
||||
clif_buyingstore_itemlist(sd, pl_sd);
|
||||
}
|
||||
|
||||
|
||||
void buyingstore_trade(struct map_session_data* sd, int account_id, unsigned int buyer_id, const uint8* itemlist, unsigned int count)
|
||||
{
|
||||
short blankslots[MAX_SLOTS]; // used when checking whether or not an item's card slots are blank
|
||||
int zeny = 0;
|
||||
unsigned int i, weight, listidx, k;
|
||||
struct map_session_data* pl_sd;
|
||||
|
||||
if( count == 0 )
|
||||
{// nothing to do
|
||||
return;
|
||||
}
|
||||
|
||||
if( !battle_config.feature_buying_store || pc_istrading(sd) )
|
||||
{// not allowed to sell
|
||||
clif_buyingstore_trade_failed_seller(sd, BUYINGSTORE_TRADE_SELLER_FAILED, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
if( !pc_can_give_items(pc_isGM(sd)) )
|
||||
{// custom: GM is not allowed to sell
|
||||
clif_displaymessage(sd->fd, msg_txt(246));
|
||||
clif_buyingstore_trade_failed_seller(sd, BUYINGSTORE_TRADE_SELLER_FAILED, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
if( ( pl_sd = map_id2sd(account_id) ) == NULL || !pl_sd->state.buyingstore || pl_sd->buyer_id != buyer_id )
|
||||
{// not online, not buying or not same store
|
||||
clif_buyingstore_trade_failed_seller(sd, BUYINGSTORE_TRADE_SELLER_FAILED, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
if( pl_sd->status.zeny < pl_sd->buyingstore.zenylimit )
|
||||
{// buyer lost zeny in the mean time? fix the limit
|
||||
pl_sd->buyingstore.zenylimit = pl_sd->status.zeny;
|
||||
}
|
||||
weight = pl_sd->weight;
|
||||
memset(blankslots, 0, sizeof(blankslots));
|
||||
|
||||
// check item list
|
||||
for( i = 0; i < count; i++ )
|
||||
{// itemlist: <index>.W <name id>.W <amount>.W
|
||||
unsigned short nameid, amount;
|
||||
int index;
|
||||
|
||||
index = RBUFW(itemlist,i*6+0)-2;
|
||||
nameid = RBUFW(itemlist,i*6+2);
|
||||
amount = RBUFW(itemlist,i*6+4);
|
||||
|
||||
if( i )
|
||||
{// duplicate check. as the client does this too, only malicious intent should be caught here
|
||||
ARR_FIND( 0, i, k, RBUFW(itemlist,k*6+0)-2 == index );
|
||||
if( k != i )
|
||||
{// duplicate
|
||||
ShowWarning("buyingstore_trade: Found duplicate item on selling list (prevnameid=%hu, prevamount=%hu, nameid=%hu, amount=%hu, account_id=%d, char_id=%d).\n",
|
||||
RBUFW(itemlist,k*6+2), RBUFW(itemlist,k*6+4), nameid, amount, sd->status.account_id, sd->status.char_id);
|
||||
clif_buyingstore_trade_failed_seller(sd, BUYINGSTORE_TRADE_SELLER_FAILED, nameid);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if( index < 0 || index >= ARRAYLENGTH(sd->status.inventory) || sd->inventory_data[index] == NULL || sd->status.inventory[index].nameid != nameid || sd->status.inventory[index].amount < amount )
|
||||
{// invalid input
|
||||
clif_buyingstore_trade_failed_seller(sd, BUYINGSTORE_TRADE_SELLER_FAILED, nameid);
|
||||
return;
|
||||
}
|
||||
|
||||
if( sd->status.inventory[index].expire_time || !itemdb_cantrade(&sd->status.inventory[index], pc_isGM(sd), pc_isGM(pl_sd)) || memcmp(sd->status.inventory[index].card, blankslots, sizeof(blankslots)) )
|
||||
{// non-tradable item
|
||||
clif_buyingstore_trade_failed_seller(sd, BUYINGSTORE_TRADE_SELLER_FAILED, nameid);
|
||||
return;
|
||||
}
|
||||
|
||||
ARR_FIND( 0, pl_sd->buyingstore.slots, listidx, pl_sd->buyingstore.items[listidx].nameid == nameid );
|
||||
if( listidx == pl_sd->buyingstore.slots || pl_sd->buyingstore.items[listidx].amount == 0 )
|
||||
{// there is no such item or the buyer has already bought all of them
|
||||
clif_buyingstore_trade_failed_seller(sd, BUYINGSTORE_TRADE_SELLER_FAILED, nameid);
|
||||
return;
|
||||
}
|
||||
|
||||
if( pl_sd->buyingstore.items[listidx].amount < amount )
|
||||
{// buyer does not need that much of the item
|
||||
clif_buyingstore_trade_failed_seller(sd, BUYINGSTORE_TRADE_SELLER_COUNT, nameid);
|
||||
return;
|
||||
}
|
||||
|
||||
if( pc_checkadditem(pl_sd, nameid, amount) == ADDITEM_OVERAMOUNT )
|
||||
{// buyer does not have enough space for this item
|
||||
clif_buyingstore_trade_failed_seller(sd, BUYINGSTORE_TRADE_SELLER_FAILED, nameid);
|
||||
return;
|
||||
}
|
||||
|
||||
if( amount*(unsigned int)sd->inventory_data[index]->weight > pl_sd->max_weight-weight )
|
||||
{// normally this is not supposed to happen, as the total weight is
|
||||
// checked upon creation, but the buyer could have gained items
|
||||
clif_buyingstore_trade_failed_seller(sd, BUYINGSTORE_TRADE_SELLER_FAILED, nameid);
|
||||
return;
|
||||
}
|
||||
weight+= amount*sd->inventory_data[index]->weight;
|
||||
|
||||
if( amount*pl_sd->buyingstore.items[listidx].price > pl_sd->buyingstore.zenylimit-zeny )
|
||||
{// buyer does not have enough zeny
|
||||
clif_buyingstore_trade_failed_seller(sd, BUYINGSTORE_TRADE_SELLER_ZENY, nameid);
|
||||
return;
|
||||
}
|
||||
zeny+= amount*pl_sd->buyingstore.items[listidx].price;
|
||||
}
|
||||
|
||||
// process item list
|
||||
for( i = 0; i < count; i++ )
|
||||
{// itemlist: <index>.W <name id>.W <amount>.W
|
||||
unsigned short nameid, amount;
|
||||
int index;
|
||||
|
||||
index = RBUFW(itemlist,i*6+0)-2;
|
||||
nameid = RBUFW(itemlist,i*6+2);
|
||||
amount = RBUFW(itemlist,i*6+4);
|
||||
|
||||
ARR_FIND( 0, pl_sd->buyingstore.slots, listidx, pl_sd->buyingstore.items[listidx].nameid == nameid );
|
||||
zeny = amount*pl_sd->buyingstore.items[listidx].price;
|
||||
|
||||
// log
|
||||
if( log_config.enable_logs&LOG_BUYING_STORE )
|
||||
{
|
||||
log_pick_pc(sd, "B", nameid, -((int)amount), &sd->status.inventory[index]);
|
||||
log_pick_pc(pl_sd, "B", nameid, amount, &sd->status.inventory[index]);
|
||||
}
|
||||
if( log_config.zeny )
|
||||
log_zeny(sd, "B", pl_sd, zeny);
|
||||
|
||||
// move item
|
||||
pc_additem(pl_sd, &sd->status.inventory[index], amount);
|
||||
pc_delitem(sd, index, amount, 1, 0);
|
||||
pl_sd->buyingstore.items[listidx].amount-= amount;
|
||||
|
||||
// pay up
|
||||
pc_payzeny(pl_sd, zeny);
|
||||
pc_getzeny(sd, zeny);
|
||||
pl_sd->buyingstore.zenylimit-= zeny;
|
||||
|
||||
// notify clients
|
||||
clif_buyingstore_delete_item(sd, index, amount, pl_sd->buyingstore.items[listidx].price);
|
||||
clif_buyingstore_update_item(pl_sd, nameid, amount);
|
||||
}
|
||||
|
||||
// check whether or not there is still something to buy
|
||||
ARR_FIND( 0, pl_sd->buyingstore.slots, i, pl_sd->buyingstore.items[i].amount != 0 );
|
||||
if( i == pl_sd->buyingstore.slots )
|
||||
{// everything was bought
|
||||
clif_buyingstore_trade_failed_buyer(pl_sd, BUYINGSTORE_TRADE_BUYER_NO_ITEMS);
|
||||
buyingstore_close(pl_sd);
|
||||
}
|
||||
else if( pl_sd->buyingstore.zenylimit == 0 )
|
||||
{// zeny limit reached
|
||||
clif_buyingstore_trade_failed_buyer(pl_sd, BUYINGSTORE_TRADE_BUYER_ZENY);
|
||||
buyingstore_close(pl_sd);
|
||||
}
|
||||
}
|
29
src/map/buyingstore.h
Normal file
29
src/map/buyingstore.h
Normal file
@ -0,0 +1,29 @@
|
||||
// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
|
||||
// For more information, see LICENCE in the main folder
|
||||
|
||||
#ifndef _BUYINGSTORE_H_
|
||||
#define _BUYINGSTORE_H_
|
||||
|
||||
#define MAX_BUYINGSTORE_SLOTS 5
|
||||
|
||||
struct s_buyingstore_item
|
||||
{
|
||||
int price;
|
||||
unsigned short amount;
|
||||
unsigned short nameid;
|
||||
};
|
||||
|
||||
struct s_buyingstore
|
||||
{
|
||||
struct s_buyingstore_item items[MAX_BUYINGSTORE_SLOTS];
|
||||
int zenylimit;
|
||||
unsigned char slots;
|
||||
};
|
||||
|
||||
bool buyingstore_setup(struct map_session_data* sd, unsigned char slots);
|
||||
void buyingstore_create(struct map_session_data* sd, int zenylimit, unsigned char result, const char* storename, const uint8* itemlist, unsigned int count);
|
||||
void buyingstore_close(struct map_session_data* sd);
|
||||
void buyingstore_open(struct map_session_data* sd, int account_id);
|
||||
void buyingstore_trade(struct map_session_data* sd, int account_id, unsigned int buyer_id, const uint8* itemlist, unsigned int count);
|
||||
|
||||
#endif // _BUYINGSTORE_H_
|
@ -69,6 +69,11 @@ int chat_createpcchat(struct map_session_data* sd, const char* title, const char
|
||||
if( sd->chatID )
|
||||
return 0; //Prevent people abusing the chat system by creating multiple chats, as pointed out by End of Exam. [Skotlex]
|
||||
|
||||
if( sd->vender_id || sd->state.buyingstore )
|
||||
{// not chat, when you already have a store open
|
||||
return 0;
|
||||
}
|
||||
|
||||
if( map[sd->bl.m].flag.nochat )
|
||||
{
|
||||
clif_displaymessage(sd->fd, msg_txt(281));
|
||||
@ -108,7 +113,7 @@ int chat_joinchat(struct map_session_data* sd, int chatid, const char* pass)
|
||||
nullpo_ret(sd);
|
||||
cd = (struct chat_data*)map_id2bl(chatid);
|
||||
|
||||
if( cd == NULL || cd->bl.type != BL_CHAT || cd->bl.m != sd->bl.m || sd->vender_id || sd->chatID || cd->users >= cd->limit )
|
||||
if( cd == NULL || cd->bl.type != BL_CHAT || cd->bl.m != sd->bl.m || sd->vender_id || sd->state.buyingstore || sd->chatID || cd->users >= cd->limit )
|
||||
{
|
||||
clif_joinchatfail(sd,0);
|
||||
return 0;
|
||||
|
323
src/map/clif.c
323
src/map/clif.c
@ -56,7 +56,10 @@ struct Clif_Config {
|
||||
struct s_packet_db packet_db[MAX_PACKET_VER + 1][MAX_PACKET_DB + 1];
|
||||
|
||||
//Converts item type in case of pet eggs.
|
||||
#define itemtype(a) (a == IT_PETEGG)?IT_WEAPON:a
|
||||
inline int itemtype(int type)
|
||||
{
|
||||
return ( type == IT_PETEGG ) ? IT_WEAPON : type;
|
||||
}
|
||||
|
||||
#define WBUFPOS(p,pos,x,y,dir) \
|
||||
do { \
|
||||
@ -3644,6 +3647,9 @@ static void clif_getareachar_pc(struct map_session_data* sd,struct map_session_d
|
||||
if(dstsd->vender_id)
|
||||
clif_showvendingboard(&dstsd->bl,dstsd->message,sd->fd);
|
||||
|
||||
if( dstsd->state.buyingstore )
|
||||
clif_buyingstore_entry_single(sd, dstsd);
|
||||
|
||||
if(dstsd->spiritball > 0)
|
||||
clif_spiritball_single(sd->fd, dstsd);
|
||||
|
||||
@ -4072,6 +4078,8 @@ int clif_outsight(struct block_list *bl,va_list ap)
|
||||
}
|
||||
if(sd->vender_id)
|
||||
clif_closevendingboard(bl,tsd->fd);
|
||||
if( sd->state.buyingstore )
|
||||
clif_buyingstore_disappear_entry_single(tsd, sd);
|
||||
break;
|
||||
case BL_ITEM:
|
||||
clif_clearflooritem((struct flooritem_data*)bl,tsd->fd);
|
||||
@ -12851,7 +12859,7 @@ void clif_Auction_openwindow(struct map_session_data *sd)
|
||||
{
|
||||
int fd = sd->fd;
|
||||
|
||||
if( sd->state.storage_flag || sd->vender_id || sd->state.trading )
|
||||
if( sd->state.storage_flag || sd->vender_id || sd->state.buyingstore || sd->state.trading )
|
||||
return;
|
||||
|
||||
WFIFOHEAD(fd,12);
|
||||
@ -14033,6 +14041,308 @@ void clif_showdigit(struct map_session_data* sd, unsigned char type, int value)
|
||||
WFIFOSET(sd->fd, packet_len(0x1b1));
|
||||
}
|
||||
|
||||
|
||||
/// Buying Store System
|
||||
///
|
||||
|
||||
/// Opens preparation window for buying store (ZC_OPEN_BUYING_STORE)
|
||||
/// 0810 <slots>.B
|
||||
void clif_buyingstore_open(struct map_session_data* sd)
|
||||
{
|
||||
int fd = sd->fd;
|
||||
|
||||
WFIFOHEAD(fd,packet_len(0x810));
|
||||
WFIFOW(fd,0) = 0x810;
|
||||
WFIFOB(fd,2) = sd->buyingstore.slots;
|
||||
WFIFOSET(fd,packet_len(0x810));
|
||||
}
|
||||
|
||||
|
||||
/// Request to create a buying store (CZ_REQ_OPEN_BUYING_STORE)
|
||||
/// 0811 <packet len>.W <limit zeny>.L <result>.B <store name>.80B { <name id>.W <amount>.W <price>.L }*
|
||||
/// result:
|
||||
/// 0 = cancel
|
||||
/// 1 = open
|
||||
static void clif_parse_ReqOpenBuyingStore(int fd, struct map_session_data* sd)
|
||||
{
|
||||
const unsigned int blocksize = 8;
|
||||
uint8* itemlist;
|
||||
char storename[MESSAGE_SIZE];
|
||||
unsigned char result;
|
||||
int zenylimit;
|
||||
unsigned int count, packet_len;
|
||||
struct s_packet_db* info = &packet_db[sd->packet_ver][RFIFOW(fd,0)];
|
||||
|
||||
packet_len = RFIFOW(fd,info->pos[0]);
|
||||
|
||||
// TODO: Make this check global for all variable length packets.
|
||||
if( packet_len < 89 )
|
||||
{// minimum packet length
|
||||
ShowError("clif_parse_ReqOpenBuyingStore: Malformed packet (expected length=%u, length=%u, account_id=%d).\n", 89, packet_len, sd->bl.id);
|
||||
return;
|
||||
}
|
||||
|
||||
zenylimit = RFIFOL(fd,info->pos[1]);
|
||||
result = RFIFOL(fd,info->pos[2]);
|
||||
safestrncpy(storename, (const char*)RFIFOP(fd,info->pos[3]), sizeof(storename));
|
||||
itemlist = RFIFOP(fd,info->pos[4]);
|
||||
|
||||
// so that buyingstore_create knows, how many elements it has access to
|
||||
packet_len-= info->pos[4];
|
||||
|
||||
if( packet_len%blocksize )
|
||||
{
|
||||
ShowError("clif_parse_ReqOpenBuyingStore: Unexpected item list size %u (account_id=%d, block size=%u)\n", packet_len, sd->bl.id, blocksize);
|
||||
return;
|
||||
}
|
||||
count = packet_len/blocksize;
|
||||
|
||||
buyingstore_create(sd, zenylimit, result, storename, itemlist, count);
|
||||
}
|
||||
|
||||
|
||||
/// Notification, that the requested buying store could not be created (ZC_FAILED_OPEN_BUYING_STORE_TO_BUYER)
|
||||
/// 0812 <result>.W <total weight>.L
|
||||
/// result:
|
||||
/// 1 = "Failed to open buying store." (0x6cd, MSI_BUYINGSTORE_OPEN_FAILED)
|
||||
/// 2 = "Total amount of then possessed items exceeds the weight limit by <weight/10-maxweight*90%>. Please re-enter." (0x6ce, MSI_BUYINGSTORE_OVERWEIGHT)
|
||||
/// 8 = "No sale (purchase) information available." (0x705)
|
||||
/// other = nothing
|
||||
void clif_buyingstore_open_failed(struct map_session_data* sd, unsigned short result, unsigned int weight)
|
||||
{
|
||||
int fd = sd->fd;
|
||||
|
||||
WFIFOHEAD(fd,packet_len(0x812));
|
||||
WFIFOW(fd,0) = 0x812;
|
||||
WFIFOW(fd,2) = result;
|
||||
WFIFOL(fd,4) = weight;
|
||||
WFIFOSET(fd,packet_len(0x812));
|
||||
}
|
||||
|
||||
|
||||
/// Notification, that the requested buying store was created (ZC_MYITEMLIST_BUYING_STORE)
|
||||
/// 0813 <packet len>.W <account id>.L <limit zeny>.L { <price>.L <count>.W <type>.B <name id>.W }*
|
||||
void clif_buyingstore_myitemlist(struct map_session_data* sd)
|
||||
{
|
||||
int fd = sd->fd;
|
||||
unsigned int i;
|
||||
|
||||
WFIFOHEAD(fd,12+sd->buyingstore.slots*9);
|
||||
WFIFOW(fd,0) = 0x813;
|
||||
WFIFOW(fd,2) = 12+sd->buyingstore.slots*9;
|
||||
WFIFOL(fd,4) = sd->bl.id;
|
||||
WFIFOL(fd,8) = sd->buyingstore.zenylimit;
|
||||
|
||||
for( i = 0; i < sd->buyingstore.slots; i++ )
|
||||
{
|
||||
WFIFOL(fd,12+i*9) = sd->buyingstore.items[i].price;
|
||||
WFIFOW(fd,16+i*9) = sd->buyingstore.items[i].amount;
|
||||
WFIFOB(fd,18+i*9) = itemtype(itemdb_type(sd->buyingstore.items[i].nameid));
|
||||
WFIFOW(fd,19+i*9) = sd->buyingstore.items[i].nameid;
|
||||
}
|
||||
|
||||
WFIFOSET(fd,WFIFOW(fd,2));
|
||||
}
|
||||
|
||||
|
||||
/// Notifies clients in area of a buying store (ZC_BUYING_STORE_ENTRY)
|
||||
/// 0814 <account id>.L <store name>.80B
|
||||
void clif_buyingstore_entry(struct map_session_data* sd)
|
||||
{
|
||||
uint8 buf[86];
|
||||
|
||||
WBUFW(buf,0) = 0x814;
|
||||
WBUFL(buf,2) = sd->bl.id;
|
||||
memcpy(WBUFP(buf,6), sd->message, MESSAGE_SIZE);
|
||||
|
||||
clif_send(buf, packet_len(0x814), &sd->bl, AREA_WOS);
|
||||
}
|
||||
void clif_buyingstore_entry_single(struct map_session_data* sd, struct map_session_data* pl_sd)
|
||||
{
|
||||
int fd = sd->fd;
|
||||
|
||||
WFIFOHEAD(fd,packet_len(0x814));
|
||||
WFIFOW(fd,0) = 0x814;
|
||||
WFIFOL(fd,2) = pl_sd->bl.id;
|
||||
memcpy(WFIFOP(fd,6), pl_sd->message, MESSAGE_SIZE);
|
||||
WFIFOSET(fd,packet_len(0x814));
|
||||
}
|
||||
|
||||
|
||||
/// Request to close own buying store (CZ_REQ_CLOSE_BUYING_STORE)
|
||||
/// 0815
|
||||
static void clif_parse_ReqCloseBuyingStore(int fd, struct map_session_data* sd)
|
||||
{
|
||||
buyingstore_close(sd);
|
||||
}
|
||||
|
||||
|
||||
/// Notifies clients in area that a buying store was closed (ZC_DISAPPEAR_BUYING_STORE_ENTRY)
|
||||
/// 0816 <account id>.L
|
||||
void clif_buyingstore_disappear_entry(struct map_session_data* sd)
|
||||
{
|
||||
uint8 buf[6];
|
||||
|
||||
WBUFW(buf,0) = 0x816;
|
||||
WBUFL(buf,2) = sd->bl.id;
|
||||
|
||||
clif_send(buf, packet_len(0x816), &sd->bl, AREA_WOS);
|
||||
}
|
||||
void clif_buyingstore_disappear_entry_single(struct map_session_data* sd, struct map_session_data* pl_sd)
|
||||
{
|
||||
int fd = sd->fd;
|
||||
|
||||
WFIFOHEAD(fd,packet_len(0x816));
|
||||
WFIFOW(fd,0) = 0x816;
|
||||
WFIFOL(fd,2) = pl_sd->bl.id;
|
||||
WFIFOSET(fd,packet_len(0x816));
|
||||
}
|
||||
|
||||
|
||||
/// Request to open someone else's buying store (CZ_REQ_CLICK_TO_BUYING_STORE)
|
||||
/// 0817 <account id>.L
|
||||
static void clif_parse_ReqClickBuyingStore(int fd, struct map_session_data* sd)
|
||||
{
|
||||
int account_id;
|
||||
|
||||
account_id = RFIFOL(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[0]);
|
||||
|
||||
buyingstore_open(sd, account_id);
|
||||
}
|
||||
|
||||
|
||||
/// Sends buying store item list (ZC_ACK_ITEMLIST_BUYING_STORE)
|
||||
/// 0818 <packet len>.W <account id>.L <store id>.L <limit zeny>.L { <price>.L <amount>.W <type>.B <name id>.W }*
|
||||
void clif_buyingstore_itemlist(struct map_session_data* sd, struct map_session_data* pl_sd)
|
||||
{
|
||||
int fd = sd->fd;
|
||||
unsigned int i;
|
||||
|
||||
WFIFOHEAD(fd,16+pl_sd->buyingstore.slots*9);
|
||||
WFIFOW(fd,0) = 0x818;
|
||||
WFIFOW(fd,2) = 16+pl_sd->buyingstore.slots*9;
|
||||
WFIFOL(fd,4) = pl_sd->bl.id;
|
||||
WFIFOL(fd,8) = pl_sd->buyer_id;
|
||||
WFIFOL(fd,12) = pl_sd->buyingstore.zenylimit;
|
||||
|
||||
for( i = 0; i < pl_sd->buyingstore.slots; i++ )
|
||||
{
|
||||
WFIFOL(fd,16+i*9) = pl_sd->buyingstore.items[i].price;
|
||||
WFIFOW(fd,20+i*9) = pl_sd->buyingstore.items[i].amount; // TODO: Figure out, if no longer needed items (amount == 0) are listed on official.
|
||||
WFIFOB(fd,22+i*9) = itemtype(itemdb_type(pl_sd->buyingstore.items[i].nameid));
|
||||
WFIFOW(fd,23+i*9) = pl_sd->buyingstore.items[i].nameid;
|
||||
}
|
||||
|
||||
WFIFOSET(fd,WFIFOW(fd,2));
|
||||
}
|
||||
|
||||
|
||||
/// Request to sell items to a buying store (CZ_REQ_TRADE_BUYING_STORE)
|
||||
/// 0819 <packet len>.W <account id>.L <store id>.L { <index>.W <name id>.W <amount>.W }*
|
||||
static void clif_parse_ReqTradeBuyingStore(int fd, struct map_session_data* sd)
|
||||
{
|
||||
const unsigned int blocksize = 6;
|
||||
uint8* itemlist;
|
||||
int account_id;
|
||||
unsigned int count, packet_len, buyer_id;
|
||||
struct s_packet_db* info = &packet_db[sd->packet_ver][RFIFOW(fd,0)];
|
||||
|
||||
packet_len = RFIFOW(fd,info->pos[0]);
|
||||
|
||||
if( packet_len < 12 )
|
||||
{// minimum packet length
|
||||
ShowError("clif_parse_ReqTradeBuyingStore: Malformed packet (expected length=%u, length=%u, account_id=%d).\n", 12, packet_len, sd->bl.id);
|
||||
return;
|
||||
}
|
||||
|
||||
account_id = RFIFOL(fd,info->pos[1]);
|
||||
buyer_id = RFIFOL(fd,info->pos[2]);
|
||||
itemlist = RFIFOP(fd,info->pos[3]);
|
||||
|
||||
// so that buyingstore_trade knows, how many elements it has access to
|
||||
packet_len-= info->pos[3];
|
||||
|
||||
if( packet_len%blocksize )
|
||||
{
|
||||
ShowError("clif_parse_ReqTradeBuyingStore: Unexpected item list size %u (account_id=%d, buyer_id=%d, block size=%u)\n", packet_len, sd->bl.id, account_id, blocksize);
|
||||
return;
|
||||
}
|
||||
count = packet_len/blocksize;
|
||||
|
||||
buyingstore_trade(sd, account_id, buyer_id, itemlist, count);
|
||||
}
|
||||
|
||||
|
||||
/// Notifies the buyer, that the buying store has been closed due to a post-trade condition (ZC_FAILED_TRADE_BUYING_STORE_TO_BUYER)
|
||||
/// 081a <result>.W
|
||||
/// result:
|
||||
/// 3 = "All items within the buy limit were purchased." (0x6cf, MSI_BUYINGSTORE_TRADE_OVERLIMITZENY)
|
||||
/// 4 = "All items were purchased." (0x6d0, MSI_BUYINGSTORE_TRADE_BUYCOMPLETE)
|
||||
/// other = nothing
|
||||
void clif_buyingstore_trade_failed_buyer(struct map_session_data* sd, short result)
|
||||
{
|
||||
int fd = sd->fd;
|
||||
|
||||
WFIFOHEAD(fd,packet_len(0x81a));
|
||||
WFIFOW(fd,0) = 0x81a;
|
||||
WFIFOW(fd,2) = result;
|
||||
WFIFOSET(fd,packet_len(0x81a));
|
||||
}
|
||||
|
||||
|
||||
/// Updates the zeny limit and an item in the buying store item list (ZC_UPDATE_ITEM_FROM_BUYING_STORE)
|
||||
/// 081b <name id>.W <amount>.W <limit zeny>.L
|
||||
void clif_buyingstore_update_item(struct map_session_data* sd, unsigned short nameid, unsigned short amount)
|
||||
{
|
||||
int fd = sd->fd;
|
||||
|
||||
WFIFOHEAD(fd,packet_len(0x81b));
|
||||
WFIFOW(fd,0) = 0x81b;
|
||||
WFIFOW(fd,2) = nameid;
|
||||
WFIFOW(fd,4) = amount; // amount of nameid received
|
||||
WFIFOW(fd,6) = sd->buyingstore.zenylimit;
|
||||
WFIFOSET(fd,packet_len(0x81b));
|
||||
}
|
||||
|
||||
|
||||
/// Deletes item from inventory, that was sold to a buying store (ZC_ITEM_DELETE_BUYING_STORE)
|
||||
/// 081c <index>.W <amount>.W <price>.L
|
||||
/// message:
|
||||
/// "%s (%d) were sold at %dz." (0x6d2, MSI_BUYINGSTORE_TRADE_SELLCOMPLETE)
|
||||
///
|
||||
/// @note This function has to be called _instead_ of clif_delitem/clif_dropitem.
|
||||
void clif_buyingstore_delete_item(struct map_session_data* sd, short index, unsigned short amount, int price)
|
||||
{
|
||||
int fd = sd->fd;
|
||||
|
||||
WFIFOHEAD(fd,packet_len(0x81c));
|
||||
WFIFOW(fd,0) = 0x81c;
|
||||
WFIFOW(fd,2) = index+2;
|
||||
WFIFOW(fd,4) = amount;
|
||||
WFIFOL(fd,6) = price; // price per item, client calculates total Zeny by itself
|
||||
WFIFOSET(fd,packet_len(0x81c));
|
||||
}
|
||||
|
||||
|
||||
/// Notifies the seller, that a buying store trade failed (ZC_FAILED_TRADE_BUYING_STORE_TO_SELLER)
|
||||
/// 0824 <result>.W <name id>.W
|
||||
/// result:
|
||||
/// 5 = "The deal has failed." (0x39, MSI_DEAL_FAIL)
|
||||
/// 6 = "The trade failed, because the entered amount of item %s is higher, than the buyer is willing to buy." (0x6d3, MSI_BUYINGSTORE_TRADE_OVERCOUNT)
|
||||
/// 7 = "The trade failed, because the buyer is lacking required balance." (0x6d1, MSI_BUYINGSTORE_TRADE_LACKBUYERZENY)
|
||||
/// other = nothing
|
||||
void clif_buyingstore_trade_failed_seller(struct map_session_data* sd, short result, unsigned short nameid)
|
||||
{
|
||||
int fd = sd->fd;
|
||||
|
||||
WFIFOHEAD(fd,packet_len(0x824));
|
||||
WFIFOW(fd,0) = 0x824;
|
||||
WFIFOW(fd,2) = result;
|
||||
WFIFOW(fd,4) = nameid;
|
||||
WFIFOSET(fd,packet_len(0x824));
|
||||
}
|
||||
|
||||
|
||||
/*==========================================
|
||||
* ƒpƒPƒbƒgƒfƒoƒbƒO
|
||||
*------------------------------------------*/
|
||||
@ -14435,8 +14745,8 @@ static int packetdb_readdb(void)
|
||||
#else // for Party booking ( PACKETVER >= 20091229 )
|
||||
-1, -1, 18, 4, 8, 6, 2, 4, 14, 50, 18, 6, 2, 3, 14, 20,
|
||||
#endif
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
3, -1, 8, -1, 86, 2, 6, 6, -1, -1, 4, 10, 10, 0, 0, 0,
|
||||
0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
};
|
||||
struct {
|
||||
@ -14628,6 +14938,11 @@ static int packetdb_readdb(void)
|
||||
{clif_parse_PartyBookingDeleteReq,"bookingdelreq"},
|
||||
#endif
|
||||
{clif_parse_PVPInfo,"pvpinfo"},
|
||||
// Buying Store
|
||||
{clif_parse_ReqOpenBuyingStore,"reqopenbuyingstore"},
|
||||
{clif_parse_ReqCloseBuyingStore,"reqclosebuyingstore"},
|
||||
{clif_parse_ReqClickBuyingStore,"reqclickbuyingstore"},
|
||||
{clif_parse_ReqTradeBuyingStore,"reqtradebuyingstore"},
|
||||
{NULL,NULL}
|
||||
};
|
||||
|
||||
|
@ -605,4 +605,18 @@ void clif_PartyBookingInsertNotify(struct map_session_data* sd, struct party_boo
|
||||
|
||||
void clif_showdigit(struct map_session_data* sd, unsigned char type, int value);
|
||||
|
||||
/// Buying Store System
|
||||
void clif_buyingstore_open(struct map_session_data* sd);
|
||||
void clif_buyingstore_open_failed(struct map_session_data* sd, unsigned short result, unsigned int weight);
|
||||
void clif_buyingstore_myitemlist(struct map_session_data* sd);
|
||||
void clif_buyingstore_entry(struct map_session_data* sd);
|
||||
void clif_buyingstore_entry_single(struct map_session_data* sd, struct map_session_data* pl_sd);
|
||||
void clif_buyingstore_disappear_entry(struct map_session_data* sd);
|
||||
void clif_buyingstore_disappear_entry_single(struct map_session_data* sd, struct map_session_data* pl_sd);
|
||||
void clif_buyingstore_itemlist(struct map_session_data* sd, struct map_session_data* pl_sd);
|
||||
void clif_buyingstore_trade_failed_buyer(struct map_session_data* sd, short result);
|
||||
void clif_buyingstore_update_item(struct map_session_data* sd, unsigned short nameid, unsigned short amount);
|
||||
void clif_buyingstore_delete_item(struct map_session_data* sd, short index, unsigned short amount, int price);
|
||||
void clif_buyingstore_trade_failed_seller(struct map_session_data* sd, short result, unsigned short nameid);
|
||||
|
||||
#endif /* _CLIF_H_ */
|
||||
|
@ -663,6 +663,33 @@ static bool itemdb_read_itemdelay(char* str[], int columns, int current)
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/// Reads items allowed to be sold in buying stores
|
||||
static bool itemdb_read_buyingstore(char* fields[], int columns, int current)
|
||||
{// <nameid>
|
||||
int nameid;
|
||||
struct item_data* id;
|
||||
|
||||
nameid = atoi(fields[0]);
|
||||
|
||||
if( ( id = itemdb_exists(nameid) ) == NULL )
|
||||
{
|
||||
ShowWarning("itemdb_read_buyingstore: Invalid item id %d.\n", nameid);
|
||||
return false;
|
||||
}
|
||||
|
||||
if( !itemdb_isstackable2(id) )
|
||||
{
|
||||
ShowWarning("itemdb_read_buyingstore: Non-stackable item id %d cannot be enabled for buying store.\n", nameid);
|
||||
return false;
|
||||
}
|
||||
|
||||
id->flag.buyingstore = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/*======================================
|
||||
* Applies gender restrictions according to settings. [Skotlex]
|
||||
*======================================*/
|
||||
@ -979,6 +1006,7 @@ static void itemdb_read(void)
|
||||
sv_readdb(db_path, "item_noequip.txt", ',', 2, 2, -1, &itemdb_read_noequip);
|
||||
sv_readdb(db_path, "item_trade.txt", ',', 3, 3, -1, &itemdb_read_itemtrade);
|
||||
sv_readdb(db_path, "item_delay.txt", ',', 2, 2, MAX_ITEMDELAYS, &itemdb_read_itemdelay);
|
||||
sv_readdb(db_path, "item_buyingstore.txt", ',', 1, 1, -1, &itemdb_read_buyingstore);
|
||||
}
|
||||
|
||||
/*==========================================
|
||||
|
@ -76,6 +76,7 @@ struct item_data {
|
||||
unsigned delay_consume : 1; // Signifies items that are not consumed immediately upon double-click [Skotlex]
|
||||
unsigned trade_restriction : 7; //Item restrictions mask [Skotlex]
|
||||
unsigned autoequip: 1;
|
||||
unsigned buyingstore : 1;
|
||||
} flag;
|
||||
short gm_lv_trade_override; //GM-level to override trade_restriction
|
||||
};
|
||||
|
@ -36,9 +36,10 @@ typedef enum log_what {
|
||||
LOG_USED_ITEMS = 0x0100, // used by player
|
||||
LOG_MVP_PRIZE = 0x0200,
|
||||
LOG_COMMAND_ITEMS = 0x0400, // created/deleted through @/# commands
|
||||
LOG_STORAGE_ITEMS = 0x0800, // placed/retrieved from storage
|
||||
LOG_GSTORAGE_ITEMS = 0x1000, // placed/retrieved from guild storage
|
||||
LOG_MAILS = 0x2000 // mail system transactions
|
||||
LOG_STORAGE_ITEMS = 0x0800, // placed/retrieved from storage
|
||||
LOG_GSTORAGE_ITEMS = 0x1000, // placed/retrieved from guild storage
|
||||
LOG_MAILS = 0x2000, // mail system transactions
|
||||
LOG_BUYING_STORE = 0x4000, // buying store transactions
|
||||
} log_what;
|
||||
|
||||
extern struct Log_Config {
|
||||
|
@ -162,7 +162,7 @@ int mail_openmail(struct map_session_data *sd)
|
||||
{
|
||||
nullpo_ret(sd);
|
||||
|
||||
if( sd->state.storage_flag || sd->vender_id || sd->state.trading )
|
||||
if( sd->state.storage_flag || sd->vender_id || sd->state.buyingstore || sd->state.trading )
|
||||
return 0;
|
||||
|
||||
clif_Mail_window(sd->fd, 0);
|
||||
|
15
src/map/pc.h
15
src/map/pc.h
@ -7,6 +7,7 @@
|
||||
#include "../common/mmo.h" // JOB_*, MAX_FAME_LIST, struct fame_list, struct mmo_charstatus
|
||||
#include "../common/timer.h" // INVALID_TIMER
|
||||
#include "battle.h" // battle_config
|
||||
#include "buyingstore.h" // struct s_buyingstore
|
||||
#include "itemdb.h" // MAX_ITEMGROUP
|
||||
#include "map.h" // RC_MAX
|
||||
#include "pc.h" // struct map_session_data
|
||||
@ -128,6 +129,7 @@ struct map_session_data {
|
||||
unsigned doridori : 1;
|
||||
unsigned ignoreAll : 1;
|
||||
unsigned debug_remove_map : 1; // temporary state to track double remove_map's [FlavioJS]
|
||||
unsigned buyingstore : 1;
|
||||
unsigned short autoloot;
|
||||
unsigned short autolootid; // [Zephyrus]
|
||||
unsigned noks : 3; // [Zeph Kill Steal Protection]
|
||||
@ -356,6 +358,9 @@ struct map_session_data {
|
||||
char message[MESSAGE_SIZE];
|
||||
struct s_vending vending[MAX_VENDING];
|
||||
|
||||
unsigned int buyer_id; // uid of open buying store
|
||||
struct s_buyingstore buyingstore;
|
||||
|
||||
struct pet_data *pd;
|
||||
struct homun_data *hd; // [blackhole89]
|
||||
struct mercenary_data *md;
|
||||
@ -413,8 +418,8 @@ struct map_session_data {
|
||||
const char* debug_func;
|
||||
};
|
||||
|
||||
//Update this max as necessary. 54 is the value needed for Super Baby currently
|
||||
#define MAX_SKILL_TREE 54
|
||||
//Update this max as necessary. 55 is the value needed for Super Baby currently
|
||||
#define MAX_SKILL_TREE 55
|
||||
//Total number of classes (for data storage)
|
||||
#define CLASS_COUNT (JOB_MAX - JOB_NOVICE_HIGH + JOB_MAX_BASIC)
|
||||
|
||||
@ -515,9 +520,9 @@ extern int duel_count;
|
||||
#define pc_setsit(sd) ( (sd)->state.dead_sit = (sd)->vd.dead_sit = 2 )
|
||||
#define pc_isdead(sd) ( (sd)->state.dead_sit == 1 )
|
||||
#define pc_issit(sd) ( (sd)->vd.dead_sit == 2 )
|
||||
#define pc_isidle(sd) ( (sd)->chatID || (sd)->vender_id || DIFF_TICK(last_tick, (sd)->idletime) >= battle_config.idle_no_share )
|
||||
#define pc_istrading(sd) ( (sd)->npc_id || (sd)->vender_id || (sd)->state.trading )
|
||||
#define pc_cant_act(sd) ( (sd)->npc_id || (sd)->vender_id || (sd)->chatID || (sd)->sc.opt1 || (sd)->state.trading || (sd)->state.storage_flag )
|
||||
#define pc_isidle(sd) ( (sd)->chatID || (sd)->vender_id || (sd)->state.buyingstore || DIFF_TICK(last_tick, (sd)->idletime) >= battle_config.idle_no_share )
|
||||
#define pc_istrading(sd) ( (sd)->npc_id || (sd)->vender_id || (sd)->state.buyingstore || (sd)->state.trading )
|
||||
#define pc_cant_act(sd) ( (sd)->npc_id || (sd)->vender_id || (sd)->state.buyingstore || (sd)->chatID || (sd)->sc.opt1 || (sd)->state.trading || (sd)->state.storage_flag )
|
||||
#define pc_setdir(sd,b,h) ( (sd)->ud.dir = (b) ,(sd)->head_dir = (h) )
|
||||
#define pc_setchatid(sd,n) ( (sd)->chatID = n )
|
||||
#define pc_ishiding(sd) ( (sd)->sc.option&(OPTION_HIDE|OPTION_CLOAK|OPTION_CHASEWALK) )
|
||||
|
@ -14807,6 +14807,23 @@ BUILDIN_FUNC(pushpc)
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/// Invokes buying store preparation window
|
||||
/// buyingstore <slots>;
|
||||
BUILDIN_FUNC(buyingstore)
|
||||
{
|
||||
struct map_session_data* sd;
|
||||
|
||||
if( ( sd = script_rid2sd(st) ) == NULL )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
buyingstore_setup(sd, script_getnum(st,2));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// declarations that were supposed to be exported from npc_chat.c
|
||||
#ifdef PCRE_SUPPORT
|
||||
BUILDIN_FUNC(defpattern);
|
||||
@ -15168,6 +15185,7 @@ struct script_function buildin_func[] = {
|
||||
BUILDIN_DEF(areamobuseskill,"siiiiviiiii"),
|
||||
BUILDIN_DEF(progressbar,"si"),
|
||||
BUILDIN_DEF(pushpc,"ii"),
|
||||
BUILDIN_DEF(buyingstore,"i"),
|
||||
// WoE SE
|
||||
BUILDIN_DEF(agitstart2,""),
|
||||
BUILDIN_DEF(agitend2,""),
|
||||
|
@ -5692,6 +5692,12 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
|
||||
case ALL_WEWISH:
|
||||
clif_skill_nodamage(src,bl,skillid,skilllv,1);
|
||||
break;
|
||||
case ALL_BUYING_STORE:
|
||||
if( sd )
|
||||
{// players only, skill allows 5 buying slots
|
||||
clif_skill_nodamage(src, bl, skillid, skilllv, buyingstore_setup(sd, MAX_BUYINGSTORE_SLOTS));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ShowWarning("skill_castend_nodamage_id: Unknown skill used:%d\n",skillid);
|
||||
clif_skill_nodamage(src,bl,skillid,skilllv,1);
|
||||
|
@ -138,8 +138,8 @@ void trade_tradeack(struct map_session_data *sd, int type)
|
||||
}
|
||||
|
||||
//Check if you can start trade.
|
||||
if (sd->npc_id || sd->vender_id || sd->state.storage_flag ||
|
||||
tsd->npc_id || tsd->vender_id || tsd->state.storage_flag)
|
||||
if (sd->npc_id || sd->vender_id || sd->state.buyingstore || sd->state.storage_flag ||
|
||||
tsd->npc_id || tsd->vender_id || tsd->state.buyingstore || tsd->state.storage_flag)
|
||||
{ //Fail
|
||||
clif_tradestart(sd, 2);
|
||||
clif_tradestart(tsd, 2);
|
||||
|
@ -803,6 +803,7 @@ int unit_can_move(struct block_list *bl)
|
||||
if (sd && (
|
||||
pc_issit(sd) ||
|
||||
sd->vender_id ||
|
||||
sd->state.buyingstore ||
|
||||
sd->state.blockedmove
|
||||
))
|
||||
return 0; //Can't move
|
||||
@ -1872,6 +1873,7 @@ int unit_remove_map_(struct block_list *bl, clr_type clrtype, const char* file,
|
||||
trade_tradecancel(sd);
|
||||
if(sd->vender_id)
|
||||
vending_closevending(sd);
|
||||
buyingstore_close(sd);
|
||||
if(sd->state.storage_flag == 1)
|
||||
storage_storage_quit(sd,0);
|
||||
else if (sd->state.storage_flag == 2)
|
||||
|
@ -146,6 +146,7 @@
|
||||
<ClInclude Include="..\src\map\atcommand.h" />
|
||||
<ClInclude Include="..\src\map\battle.h" />
|
||||
<ClInclude Include="..\src\map\battleground.h" />
|
||||
<ClInclude Include="..\src\map\buyingstore.h" />
|
||||
<ClInclude Include="..\src\map\chat.h" />
|
||||
<ClInclude Include="..\src\map\chrif.h" />
|
||||
<ClInclude Include="..\src\map\clif.h" />
|
||||
@ -195,6 +196,7 @@
|
||||
<ClCompile Include="..\src\map\atcommand.c" />
|
||||
<ClCompile Include="..\src\map\battle.c" />
|
||||
<ClCompile Include="..\src\map\battleground.c" />
|
||||
<ClCompile Include="..\src\map\buyingstore.c" />
|
||||
<ClCompile Include="..\src\map\chat.c" />
|
||||
<ClCompile Include="..\src\map\chrif.c" />
|
||||
<ClCompile Include="..\src\map\clif.c" />
|
||||
|
@ -125,6 +125,7 @@
|
||||
<ClCompile Include="..\src\map\atcommand.c" />
|
||||
<ClCompile Include="..\src\map\battle.c" />
|
||||
<ClCompile Include="..\src\map\battleground.c" />
|
||||
<ClCompile Include="..\src\map\buyingstore.c" />
|
||||
<ClCompile Include="..\src\map\chat.c" />
|
||||
<ClCompile Include="..\src\map\chrif.c" />
|
||||
<ClCompile Include="..\src\map\clif.c" />
|
||||
@ -174,6 +175,7 @@
|
||||
<ClInclude Include="..\src\map\atcommand.h" />
|
||||
<ClInclude Include="..\src\map\battle.h" />
|
||||
<ClInclude Include="..\src\map\battleground.h" />
|
||||
<ClInclude Include="..\src\map\buyingstore.h" />
|
||||
<ClInclude Include="..\src\map\chat.h" />
|
||||
<ClInclude Include="..\src\map\chrif.h" />
|
||||
<ClInclude Include="..\src\map\clif.h" />
|
||||
|
@ -231,6 +231,14 @@ SOURCE=..\src\map\battleground.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\src\map\buyingstore.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\src\map\buyingstore.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\src\map\chat.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
@ -211,6 +211,10 @@ SOURCE=..\src\map\battleground.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\src\map\buyingstore.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\src\map\chat.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
@ -335,6 +339,10 @@ SOURCE=..\src\map\battleground.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\src\map\buyingstore.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\src\map\chat.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
@ -166,6 +166,12 @@
|
||||
<File
|
||||
RelativePath="..\src\map\battleground.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\src\map\buyingstore.c">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\src\map\buyingstore.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\src\map\chat.c">
|
||||
</File>
|
||||
|
@ -166,6 +166,12 @@
|
||||
<File
|
||||
RelativePath="..\src\map\battleground.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\src\map\buyingstore.c">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\src\map\buyingstore.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\src\map\chat.c">
|
||||
</File>
|
||||
|
@ -374,6 +374,13 @@
|
||||
<File
|
||||
RelativePath="..\src\map\battleground.h"
|
||||
>
|
||||
<File
|
||||
RelativePath="..\src\map\buyingstore.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\src\map\buyingstore.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\src\map\chat.c"
|
||||
|
@ -226,6 +226,14 @@
|
||||
RelativePath="..\src\map\battleground.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\src\map\buyingstore.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\src\map\buyingstore.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\src\map\chat.c"
|
||||
>
|
||||
|
@ -374,6 +374,14 @@
|
||||
RelativePath="..\src\map\battleground.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\src\map\buyingstore.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\src\map\buyingstore.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\src\map\chat.c"
|
||||
>
|
||||
|
@ -225,6 +225,14 @@
|
||||
RelativePath="..\src\map\battleground.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\src\map\buyingstore.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\src\map\buyingstore.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\src\map\chat.c"
|
||||
>
|
||||
|
Loading…
x
Reference in New Issue
Block a user