summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/common/HPMDataCheck.h1
-rw-r--r--src/map/atcommand.c8
-rw-r--r--src/map/clif.c157
-rw-r--r--src/map/clif.h21
-rw-r--r--src/map/itemdb.c64
-rw-r--r--src/map/itemdb.h3
-rw-r--r--src/map/npc.c23
-rw-r--r--src/map/packets.h2
-rw-r--r--src/map/pc.c7
-rw-r--r--src/map/script.c44
-rw-r--r--src/map/skill.c2
-rw-r--r--src/map/status.c5
-rw-r--r--src/map/storage.c4
-rw-r--r--src/plugins/HPMHooking/HPMHooking_map.HPMHooksCore.inc16
-rw-r--r--src/plugins/HPMHooking/HPMHooking_map.HookingPoints.inc4
-rw-r--r--src/plugins/HPMHooking/HPMHooking_map.Hooks.inc105
-rw-r--r--src/plugins/db2sql.c6
17 files changed, 428 insertions, 44 deletions
diff --git a/src/common/HPMDataCheck.h b/src/common/HPMDataCheck.h
index 43dc9ee5c..be798ceb5 100644
--- a/src/common/HPMDataCheck.h
+++ b/src/common/HPMDataCheck.h
@@ -301,6 +301,7 @@ HPExport const struct s_HPMDataCheck HPMDataCheck[] = {
{ "cdelayed_damage", sizeof(struct cdelayed_damage), SERVER_TYPE_MAP },
{ "clif_interface", sizeof(struct clif_interface), SERVER_TYPE_MAP },
{ "hCSData", sizeof(struct hCSData), SERVER_TYPE_MAP },
+ { "merge_item", sizeof(struct merge_item), SERVER_TYPE_MAP },
{ "s_packet_db", sizeof(struct s_packet_db), SERVER_TYPE_MAP },
#else
#define MAP_CLIF_H
diff --git a/src/map/atcommand.c b/src/map/atcommand.c
index 1e915de3d..2be990025 100644
--- a/src/map/atcommand.c
+++ b/src/map/atcommand.c
@@ -7805,13 +7805,15 @@ ACMD(cash)
if( !battle_config.cashshop_show_points ){
sprintf(output, msg_fd(fd,505), ret, sd->cashPoints);
clif_disp_onlyself(sd, output, strlen(output));
+ clif->message(fd, output);
}
} else
clif->message(fd, msg_fd(fd,149)); // Unable to decrease the number/value.
} else {
if( (ret=pc->paycash(sd, -value, 0)) >= 0){
sprintf(output, msg_fd(fd,410), ret, sd->cashPoints);
- clif_disp_onlyself(sd, output, strlen(output));
+ clif_disp_onlyself(sd, output, strlen(output));
+ clif->message(fd, output);
} else
clif->message(fd, msg_fd(fd,41)); // Unable to decrease the number/value.
}
@@ -7822,13 +7824,15 @@ ACMD(cash)
if( !battle_config.cashshop_show_points ){
sprintf(output, msg_fd(fd,506), ret, sd->kafraPoints);
clif_disp_onlyself(sd, output, strlen(output));
+ clif->message(fd, output);
}
} else
clif->message(fd, msg_fd(fd,149)); // Unable to decrease the number/value.
} else {
if( (ret=pc->paycash(sd, -value, -value)) >= 0){
sprintf(output, msg_fd(fd,411), ret, sd->kafraPoints);
- clif_disp_onlyself(sd, output, strlen(output));
+ clif_disp_onlyself(sd, output, strlen(output));
+ clif->message(fd, output);
} else
clif->message(fd, msg_fd(fd,41)); // Unable to decrease the number/value.
}
diff --git a/src/map/clif.c b/src/map/clif.c
index d9b20e570..f01b59fda 100644
--- a/src/map/clif.c
+++ b/src/map/clif.c
@@ -18123,6 +18123,157 @@ void clif_roulette_generate_ack(struct map_session_data *sd, unsigned char resul
clif->send(&p,sizeof(p), &sd->bl, SELF);
}
+/**
+* Stackable items merger
+**/
+void clif_openmergeitem(int fd, struct map_session_data *sd)
+{
+ int i = 0, n = 0, j = 0;
+ struct merge_item merge_items[MAX_INVENTORY];
+ struct merge_item *merge_items_[MAX_INVENTORY] = {0};
+
+ memset(&merge_items,'\0',sizeof(merge_items));
+
+ for (i = 0; i < MAX_INVENTORY; i++) {
+ struct item *item_data = &sd->status.inventory[i];
+
+ if (item_data->nameid == 0 || !itemdb->isstackable(item_data->nameid))
+ continue;
+
+ merge_items[n].nameid = item_data->nameid;
+ merge_items[n].position = i + 2;
+ n++;
+
+
+ }
+
+ qsort(merge_items,n,sizeof(struct merge_item),clif->comparemergeitem);
+
+ for (i = 0, j = 0; i < n; i++) {
+ if (i > 0 && merge_items[i].nameid == merge_items[i-1].nameid)
+ {
+ merge_items_[j] = &merge_items[i];
+ j++;
+ continue;
+ }
+
+ if (i < n - 1 && merge_items[i].nameid == merge_items[i+1].nameid)
+ {
+ merge_items_[j] = &merge_items[i];
+ j++;
+ continue;
+ }
+ }
+
+ WFIFOHEAD(fd,2*j+4);
+ WFIFOW(fd,0) = 0x96d;
+ WFIFOW(fd,2) = 2*j+4;
+ for ( i = 0; i < j; i++ )
+ WFIFOW(fd,i*2+4) = merge_items_[i]->position;
+ WFIFOSET(fd,2*j+4);
+}
+
+int clif_comparemergeitem(const void *a, const void *b)
+{
+ const struct merge_item *a_ = a;
+ const struct merge_item *b_ = b;
+
+ if (a_->nameid == b_->nameid)
+ return 0;
+ return a_->nameid > b_->nameid ? -1 : 1;
+}
+
+void clif_ackmergeitems(int fd, struct map_session_data *sd)
+{
+ int i = 0, n = 0, length = 0, count = 0;
+ int16 nameid = 0, indexes[MAX_INVENTORY] = {0}, amounts[MAX_INVENTORY] = {0};
+ struct item item_data;
+
+ length = (RFIFOW(fd,2) - 4)/2;
+
+ if (length >= MAX_INVENTORY || length < 2) {
+ WFIFOHEAD(fd,7);
+ WFIFOW(fd,0) = 0x96f;
+ WFIFOW(fd,2) = 0;
+ WFIFOW(fd,4) = 0;
+ WFIFOB(fd,6) = MERGEITEM_FAILD;
+ WFIFOSET(fd,7);
+ return;
+ }
+
+ for (i = 0, n = 0; i < length; i++) {
+ int16 idx = RFIFOW(fd,i*2+4) - 2;
+ struct item *it = NULL;
+
+ if (idx < 0 || idx >= MAX_INVENTORY)
+ continue;
+
+ it = &sd->status.inventory[idx];
+
+ if (it->nameid == 0 || !itemdb->isstackable(it->nameid))
+ continue;
+
+ if (nameid == 0)
+ nameid = it->nameid;
+
+ if (nameid != it->nameid)
+ continue;
+
+ count += it->amount;
+ indexes[n] = idx;
+ amounts[n] = it->amount;
+ n++;
+ }
+
+
+ if (n < 2 || count == 0) {
+ WFIFOHEAD(fd,7);
+ WFIFOW(fd,0) = 0x96f;
+ WFIFOW(fd,2) = 0;
+ WFIFOW(fd,4) = 0;
+ WFIFOB(fd,6) = MERGEITEM_FAILD;
+ WFIFOSET(fd,7);
+ return;
+ }
+
+ if (count > MAX_AMOUNT) {
+ WFIFOHEAD(fd,7);
+ WFIFOW(fd,0) = 0x96f;
+ WFIFOW(fd,2) = 0;
+ WFIFOW(fd,4) = 0;
+ WFIFOB(fd,6) = MERGEITEM_MAXCOUNTFAILD;
+ WFIFOSET(fd,7);
+ return;
+ }
+
+ for (i = 0; i < n; i++)
+ pc->delitem(sd,indexes[i],amounts[i],0,DELITEM_NORMAL,LOG_TYPE_NPC);
+
+
+ memset(&item_data,'\0',sizeof(item_data));
+
+ item_data.nameid = nameid;
+ item_data.identify = 1;
+ item_data.unique_id = itemdb->unique_id(sd);
+ pc->additem(sd,&item_data,count,LOG_TYPE_NPC);
+
+ ARR_FIND(0,MAX_INVENTORY,i,item_data.unique_id == sd->status.inventory[i].unique_id);
+
+ WFIFOHEAD(fd,7);
+ WFIFOW(fd,0) = 0x96f;
+ WFIFOW(fd,2) = i+2;
+ WFIFOW(fd,4) = count;
+ WFIFOB(fd,6) = MERGEITEM_SUCCESS;
+ WFIFOSET(fd,7);
+
+}
+
+void clif_cancelmergeitem (int fd, struct map_session_data *sd)
+{
+ //Track The merge item cancelation ?
+ return;
+}
+
/* */
unsigned short clif_decrypt_cmd( int cmd, struct map_session_data *sd ) {
if( sd ) {
@@ -18912,6 +19063,12 @@ void clif_defaults(void) {
/* */
clif->parse_roulette_db = clif_parse_roulette_db;
clif->roulette_generate_ack = clif_roulette_generate_ack;
+ /* Merge Items */
+ clif->openmergeitem = clif_openmergeitem;
+ clif->cancelmergeitem = clif_cancelmergeitem;
+ clif->comparemergeitem = clif_comparemergeitem;
+ clif->ackmergeitems = clif_ackmergeitems;
+
/*------------------------
*- Parse Incoming Packet
*------------------------*/
diff --git a/src/map/clif.h b/src/map/clif.h
index 66dd13304..c827406ca 100644
--- a/src/map/clif.h
+++ b/src/map/clif.h
@@ -522,6 +522,16 @@ enum delitem_reason {
DELITEM_ANALYSIS = 7, /// Consumed by Four Spirit Analysis (SO_EL_ANALYSIS) skill
};
+/*
+* Merge items reasons
+*/
+
+enum mergeitem_reason {
+ MERGEITEM_SUCCESS = 0x0,
+ MERGEITEM_FAILD = 0x1,
+ MERGEITEM_MAXCOUNTFAILD = 0x2,
+};
+
/**
* Structures
**/
@@ -542,6 +552,11 @@ struct cdelayed_damage {
struct block_list bl;
};
+struct merge_item {
+ int16 position;
+ int16 nameid;
+};
+
/**
* Vars
**/
@@ -1062,6 +1077,12 @@ struct clif_interface {
/* */
bool (*parse_roulette_db) (void);
void (*roulette_generate_ack) (struct map_session_data *sd, unsigned char result, short stage, short prizeIdx, short bonusItemID);
+ /* Merge Items */
+ void (*openmergeitem) (int fd, struct map_session_data *sd);
+ void (*cancelmergeitem) (int fd, struct map_session_data *sd);
+ int (*comparemergeitem) (const void *a, const void *b);
+ void (*ackmergeitems) (int fd, struct map_session_data *sd);
+
/*------------------------
*- Parse Incoming Packet
*------------------------*/
diff --git a/src/map/itemdb.c b/src/map/itemdb.c
index b02da1e0d..4ebe282a2 100644
--- a/src/map/itemdb.c
+++ b/src/map/itemdb.c
@@ -199,6 +199,9 @@ void itemdb_package_item(struct map_session_data *sd, struct item_package *packa
if( package->must_items[i].announce )
clif->package_announce(sd,package->must_items[i].id,package->id);
+ if ( package->must_items[i].force_serial )
+ it.unique_id = itemdb->unique_id(sd);
+
get_count = itemdb->isstackable(package->must_items[i].id) ? package->must_items[i].qty : 1;
it.amount = get_count == 1 ? 1 : get_count;
@@ -719,7 +722,7 @@ void itemdb_write_cached_packages(const char *config_filename) {
//now we loop into must
for(c = 0; c < must_qty; c++) {
struct item_package_must_entry *entry = &itemdb->packages[i].must_items[c];
- unsigned char announce = entry->announce == 1 ? 1 : 0, named = entry->named == 1 ? 1 : 0;
+ unsigned char announce = entry->announce == 1 ? 1 : 0, named = entry->named == 1 ? 1 : 0, force_serial = entry->force_serial == 1 ? 1 : 0;
//first 2 byte = item id
hwrite(&entry->id,sizeof(entry->id),1,file);
//next 2 byte = qty
@@ -729,7 +732,9 @@ void itemdb_write_cached_packages(const char *config_filename) {
//next 1 byte = announce (1:0)
hwrite(&announce,sizeof(announce),1,file);
//next 1 byte = named (1:0)
- hwrite(&named,sizeof(announce),1,file);
+ hwrite(&named,sizeof(named),1,file);
+ //next 1 byte = ForceSerial (1:0)
+ hwrite(&force_serial,sizeof(force_serial),1,file);
}
//now we loop into random groups
for(c = 0; c < random_qty; c++) {
@@ -741,7 +746,7 @@ void itemdb_write_cached_packages(const char *config_filename) {
//now we loop into the group's list
for(h = 0; h < group_qty; h++) {
struct item_package_rand_entry *entry = &itemdb->packages[i].random_groups[c].random_list[h];
- unsigned char announce = entry->announce == 1 ? 1 : 0, named = entry->named == 1 ? 1 : 0;
+ unsigned char announce = entry->announce == 1 ? 1 : 0, named = entry->named == 1 ? 1 : 0, force_serial = entry->force_serial == 1 ? 1 : 0;
//first 2 byte = item id
hwrite(&entry->id,sizeof(entry->id),1,file);
//next 2 byte = qty
@@ -753,7 +758,9 @@ void itemdb_write_cached_packages(const char *config_filename) {
//next 1 byte = announce (1:0)
hwrite(&announce,sizeof(announce),1,file);
//next 1 byte = named (1:0)
- hwrite(&named,sizeof(announce),1,file);
+ hwrite(&named,sizeof(named),1,file);
+ //next 1 byte = ForceSerial (1:0)
+ hwrite(&force_serial,sizeof(force_serial),1,file);
}
}
}
@@ -807,7 +814,7 @@ bool itemdb_read_cached_packages(const char *config_filename) {
for(c = 0; c < package->must_qty; c++) {
struct item_package_must_entry *entry = &itemdb->packages[i].must_items[c];
unsigned short mid = 0, qty = 0, hours = 0;
- unsigned char announce = 0, named = 0;
+ unsigned char announce = 0, named = 0, force_serial = 0;
struct item_data *data;
//first 2 byte = item id
hread(&mid,sizeof(mid),1,file);
@@ -818,8 +825,10 @@ bool itemdb_read_cached_packages(const char *config_filename) {
//next 1 byte = announce (1:0)
hread(&announce,sizeof(announce),1,file);
//next 1 byte = named (1:0)
- hread(&named,sizeof(announce),1,file);
-
+ hread(&named,sizeof(named),1,file);
+ //next 1 byte = ForceSerial (1:0)
+ hread(&force_serial,sizeof(force_serial),1,file);
+
if( !(data = itemdb->exists(mid)) )
ShowWarning("itemdb_read_cached_packages: unknown item '%d' in package '%s'!\n",mid,itemdb_name(package->id));
@@ -828,6 +837,7 @@ bool itemdb_read_cached_packages(const char *config_filename) {
entry->qty = qty;
entry->announce = announce ? 1 : 0;
entry->named = named ? 1 : 0;
+ entry->force_serial = force_serial ? 1 : 0;
}
}
if( package->random_qty ) {
@@ -847,7 +857,7 @@ bool itemdb_read_cached_packages(const char *config_filename) {
for(h = 0; h < group_qty; h++) {
struct item_package_rand_entry *entry = &itemdb->packages[i].random_groups[c].random_list[h];
unsigned short mid = 0, qty = 0, hours = 0, rate = 0;
- unsigned char announce = 0, named = 0;
+ unsigned char announce = 0, named = 0, force_serial = 0;
struct item_data *data;
if( prev ) prev->next = entry;
@@ -863,8 +873,10 @@ bool itemdb_read_cached_packages(const char *config_filename) {
//next 1 byte = announce (1:0)
hread(&announce,sizeof(announce),1,file);
//next 1 byte = named (1:0)
- hread(&named,sizeof(announce),1,file);
-
+ hread(&named,sizeof(named),1,file);
+ //next 1 byte = ForceSerial (1:0)
+ hread(&force_serial,sizeof(force_serial),1,file);
+
if( !(data = itemdb->exists(mid)) )
ShowWarning("itemdb_read_cached_packages: unknown item '%d' in package '%s'!\n",mid,itemdb_name(package->id));
@@ -874,7 +886,7 @@ bool itemdb_read_cached_packages(const char *config_filename) {
entry->qty = qty;
entry->announce = announce ? 1 : 0;
entry->named = named ? 1 : 0;
-
+ entry->force_serial = force_serial ? 1 : 0;
prev = entry;
}
if( prev )
@@ -1020,7 +1032,7 @@ void itemdb_read_packages(void) {
c = 0;
while( (it = libconfig->setting_get_elem(itg,c++)) ) {
int icount = 1, expire = 0, rate = 10000, gid = 0;
- bool announce = false, named = false;
+ bool announce = false, named = false, force_serial = false;
itname = config_setting_name(it);
@@ -1049,6 +1061,9 @@ void itemdb_read_packages(void) {
if( ( t = libconfig->setting_get_member(it, "Named")) && libconfig->setting_get_bool(t) )
named = true;
+ if( ( t = libconfig->setting_get_member(it, "ForceSerial")) && libconfig->setting_get_bool(t) )
+ force_serial = true;
+
if( !( t = libconfig->setting_get_member(it, "Random") ) ) {
ShowWarning("itemdb_read_packages: missing 'Random' field for item '%s' in package '%s', defaulting to must!\n",itname,config_setting_name(itg));
gid = 0;
@@ -1061,6 +1076,7 @@ void itemdb_read_packages(void) {
itemdb->packages[count].must_items[m].hours = expire;
itemdb->packages[count].must_items[m].announce = announce == true ? 1 : 0;
itemdb->packages[count].must_items[m].named = named == true ? 1 : 0;
+ itemdb->packages[count].must_items[m].force_serial = force_serial == true ? 1 : 0;
m++;
} else {
int gidx = gid - 1;
@@ -1078,6 +1094,7 @@ void itemdb_read_packages(void) {
itemdb->packages[count].random_groups[gidx].random_list[r].hours = expire;
itemdb->packages[count].random_groups[gidx].random_list[r].announce = announce == true ? 1 : 0;
itemdb->packages[count].random_groups[gidx].random_list[r].named = named == true ? 1 : 0;
+ itemdb->packages[count].random_groups[gidx].random_list[r].force_serial = force_serial == true ? 1 : 0;
itemdb->packages[count].random_groups[gidx].random_qty += 1;
prev[gidx] = &itemdb->packages[count].random_groups[gidx].random_list[r];
@@ -1583,14 +1600,15 @@ int itemdb_readdb_sql_sub(Sql *handle, int n, const char *source) {
SQL->GetData(handle, 19, &data, NULL); id.flag.no_refine = data && atoi(data) ? 0 : 1;
SQL->GetData(handle, 20, &data, NULL); id.look = data ? atoi(data) : 0;
SQL->GetData(handle, 21, &data, NULL); id.flag.bindonequip = data && atoi(data) ? 1 : 0;
- SQL->GetData(handle, 22, &data, NULL); id.flag.buyingstore = data && atoi(data) ? 1 : 0;
- SQL->GetData(handle, 23, &data, NULL); id.delay = data ? atoi(data) : 0;
- SQL->GetData(handle, 24, &data, NULL); id.flag.trade_restriction = data ? atoi(data) : ITR_NONE;
- SQL->GetData(handle, 25, &data, NULL); id.gm_lv_trade_override = data ? atoi(data) : 0;
- SQL->GetData(handle, 26, &data, NULL); id.item_usage.flag = data ? atoi(data) : INR_NONE;
- SQL->GetData(handle, 27, &data, NULL); id.item_usage.override = data ? atoi(data) : 0;
- SQL->GetData(handle, 28, &data, NULL); id.stack.amount = data ? atoi(data) : 0;
- SQL->GetData(handle, 29, &data, NULL);
+ SQL->GetData(handle, 22, &data, NULL); id.flag.force_serial = data && atoi(data) ? 1 : 0;
+ SQL->GetData(handle, 23, &data, NULL); id.flag.buyingstore = data && atoi(data) ? 1 : 0;
+ SQL->GetData(handle, 24, &data, NULL); id.delay = data ? atoi(data) : 0;
+ SQL->GetData(handle, 25, &data, NULL); id.flag.trade_restriction = data ? atoi(data) : ITR_NONE;
+ SQL->GetData(handle, 26, &data, NULL); id.gm_lv_trade_override = data ? atoi(data) : 0;
+ SQL->GetData(handle, 27, &data, NULL); id.item_usage.flag = data ? atoi(data) : INR_NONE;
+ SQL->GetData(handle, 28, &data, NULL); id.item_usage.override = data ? atoi(data) : 0;
+ SQL->GetData(handle, 29, &data, NULL); id.stack.amount = data ? atoi(data) : 0;
+ SQL->GetData(handle, 30, &data, NULL);
if (data) {
int stack_flag = atoi(data);
id.stack.inventory = (stack_flag&1)!=0;
@@ -1657,6 +1675,7 @@ int itemdb_readdb_libconfig_sub(config_setting_t *it, int n, const char *source)
* BindOnEquip: (true or false)
* BuyingStore: (true or false)
* Delay: Delay to use item
+ * ForceSerial: (true or false)
* Trade: {
* override: Group to override
* nodrop: (true or false)
@@ -1790,6 +1809,9 @@ int itemdb_readdb_libconfig_sub(config_setting_t *it, int n, const char *source)
if( (t = libconfig->setting_get_member(it, "BindOnEquip")) )
id.flag.bindonequip = libconfig->setting_get_bool(t) ? 1 : 0;
+
+ if( (t = libconfig->setting_get_member(it, "ForceSerial")) )
+ id.flag.force_serial = libconfig->setting_get_bool(t) ? 1 : 0;
if ( (t = libconfig->setting_get_member(it, "BuyingStore")) )
id.flag.buyingstore = libconfig->setting_get_bool(t) ? 1 : 0;
@@ -1992,7 +2014,7 @@ int itemdb_readdb_sql(const char *tablename) {
" `matk`, `defence`, `range`, `slots`,"
" `equip_jobs`, `equip_upper`, `equip_genders`, `equip_locations`,"
" `weapon_level`, `equip_level_min`, `equip_level_max`, `refineable`,"
- " `view`, `bindonequip`, `buyingstore`, `delay`,"
+ " `view`, `bindonequip`, `forceserial`, `buyingstore`, `delay`,"
" `trade_flag`, `trade_group`, `nouse_flag`, `nouse_group`,"
" `stack_amount`, `stack_flag`, `sprite`, `script`,"
" `equip_script`, `unequip_script`"
diff --git a/src/map/itemdb.h b/src/map/itemdb.h
index 624080c3a..e50ebfd3d 100644
--- a/src/map/itemdb.h
+++ b/src/map/itemdb.h
@@ -398,6 +398,7 @@ struct item_package_rand_entry {
unsigned short hours;
unsigned int announce : 1;
unsigned int named : 1;
+ unsigned int force_serial: 1;
struct item_package_rand_entry *next;
};
@@ -407,6 +408,7 @@ struct item_package_must_entry {
unsigned short hours;
unsigned int announce : 1;
unsigned int named : 1;
+ unsigned int force_serial : 1;
};
struct item_package_rand_group {
@@ -466,6 +468,7 @@ struct item_data {
unsigned buyingstore : 1;
unsigned bindonequip : 1;
unsigned keepafteruse : 1;
+ unsigned force_serial : 1;
} flag;
struct {// item stacking limitation
unsigned short amount;
diff --git a/src/map/npc.c b/src/map/npc.c
index 8114cacaa..a79062c77 100644
--- a/src/map/npc.c
+++ b/src/map/npc.c
@@ -2057,19 +2057,18 @@ int npc_selllist_sub(struct map_session_data* sd, int n, unsigned short* item_li
script->setarray_pc(sd, "@sold_nameid", i, (void*)(intptr_t)sd->status.inventory[idx].nameid, &key_nameid);
script->setarray_pc(sd, "@sold_quantity", i, (void*)(intptr_t)item_list[i*2+1], &key_amount);
-
- if (itemdb->isequip(sd->status.inventory[idx].nameid)) {
- // process equipment based information into the arrays
- script->setarray_pc(sd, "@sold_refine", i, (void*)(intptr_t)sd->status.inventory[idx].refine, &key_refine);
- script->setarray_pc(sd, "@sold_attribute", i, (void*)(intptr_t)sd->status.inventory[idx].attribute, &key_attribute);
- script->setarray_pc(sd, "@sold_identify", i, (void*)(intptr_t)sd->status.inventory[idx].identify, &key_identify);
-
- for (j = 0; j < MAX_SLOTS; j++) {
- // store each of the cards from the equipment in the array
- snprintf(card_slot, sizeof(card_slot), "@sold_card%d", j + 1);
- script->setarray_pc(sd, card_slot, i, (void*)(intptr_t)sd->status.inventory[idx].card[j], &key_card[j]);
- }
+
+ // process item based information into the arrays
+ script->setarray_pc(sd, "@sold_refine", i, (void*)(intptr_t)sd->status.inventory[idx].refine, &key_refine);
+ script->setarray_pc(sd, "@sold_attribute", i, (void*)(intptr_t)sd->status.inventory[idx].attribute, &key_attribute);
+ script->setarray_pc(sd, "@sold_identify", i, (void*)(intptr_t)sd->status.inventory[idx].identify, &key_identify);
+
+ for (j = 0; j < MAX_SLOTS; j++) {
+ // store each of the cards/special info from the item in the array
+ snprintf(card_slot, sizeof(card_slot), "@sold_card%d", j + 1);
+ script->setarray_pc(sd, card_slot, i, (void*)(intptr_t)sd->status.inventory[idx].card[j], &key_card[j]);
}
+
}
// invoke event
diff --git a/src/map/packets.h b/src/map/packets.h
index 53278f66e..6623c091c 100644
--- a/src/map/packets.h
+++ b/src/map/packets.h
@@ -448,6 +448,8 @@ packet(0x020a,10);
//packet(0x020b,-1);
//packet(0x020c,-1);
packet(0x020d,-1);
+packet(0x974,2,clif->cancelmergeitem);
+packet(0x96e,-1,clif->ackmergeitems);
//2004-07-05aSakexe
#if PACKETVER >= 20040705
diff --git a/src/map/pc.c b/src/map/pc.c
index 9e9f993d0..4dac559e2 100644
--- a/src/map/pc.c
+++ b/src/map/pc.c
@@ -4448,6 +4448,7 @@ int pc_additem(struct map_session_data *sd,struct item *item_data,int amount,e_l
if( sd->status.inventory[i].nameid == item_data->nameid &&
sd->status.inventory[i].bound == item_data->bound &&
sd->status.inventory[i].expire_time == 0 &&
+ sd->status.inventory[i].unique_id == item_data->unique_id &&
memcmp(&sd->status.inventory[i].card, &item_data->card, sizeof(item_data->card)) == 0 ) {
if( amount > MAX_AMOUNT - sd->status.inventory[i].amount || ( data->stack.inventory && amount > data->stack.amount - sd->status.inventory[i].amount ) )
return 5;
@@ -4475,8 +4476,8 @@ int pc_additem(struct map_session_data *sd,struct item *item_data,int amount,e_l
clif->additem(sd,i,amount,0);
}
- if( !itemdb->isstackable2(data) && !item_data->unique_id )
- sd->status.inventory[i].unique_id = itemdb->unique_id(sd);
+ if( ( !itemdb->isstackable2(data) || data->flag.force_serial || data->type == IT_CASH) && !item_data->unique_id )
+ sd->status.inventory[i].unique_id = itemdb->unique_id(sd);
logs->pick_pc(sd, log_type, amount, &sd->status.inventory[i],sd->inventory_data[i]);
@@ -5028,7 +5029,7 @@ int pc_cart_additem(struct map_session_data *sd,struct item *item_data,int amoun
sd->status.cart[i].card[2] == item_data->card[2] && sd->status.cart[i].card[3] == item_data->card[3] );
};
- if( i < MAX_CART )
+ if( i < MAX_CART && item_data->unique_id == sd->status.cart[i].unique_id)
{// item already in cart, stack it
if( amount > MAX_AMOUNT - sd->status.cart[i].amount || ( data->stack.cart && amount > data->stack.amount - sd->status.cart[i].amount ) )
return 2; // no room
diff --git a/src/map/script.c b/src/map/script.c
index 87762f44e..f2fce3a8f 100644
--- a/src/map/script.c
+++ b/src/map/script.c
@@ -19660,6 +19660,48 @@ BUILDIN(channelmes)
return true;
}
+
+/** By Cydh
+Display script message
+showscript "<message>"{,<GID>};
+*/
+BUILDIN(showscript) {
+ struct block_list *bl = NULL;
+ const char *msg = script_getstr(st, 2);
+ int id = 0;
+
+ if (script_hasdata(st, 3)) {
+ id = script_getnum(st, 3);
+ bl = map->id2bl(id);
+ }
+ else {
+ bl = st->rid ? map->id2bl(st->rid) : map->id2bl(st->oid);
+ }
+
+ if (!bl) {
+ ShowError("buildin_showscript: Script not attached. (id=%d, rid=%d, oid=%d)\n", id, st->rid, st->oid);
+ script_pushint(st, 0);
+ return false;
+ }
+
+ clif->ShowScript(bl, msg);
+
+ script_pushint(st, 1);
+
+ return true;
+}
+
+BUILDIN(mergeitem)
+{
+ struct map_session_data *sd = script->rid2sd(st);
+
+ if (sd == NULL)
+ return true;
+
+ clif->openmergeitem(sd->fd, sd);
+
+ return true;
+}
/** place holder for the translation macro **/
BUILDIN(_) {
return true;
@@ -20297,6 +20339,8 @@ void script_parse_builtin(void) {
BUILDIN_DEF(shopcount, "i"),
BUILDIN_DEF(channelmes, "ss"),
+ BUILDIN_DEF(showscript, "s?"),
+ BUILDIN_DEF(mergeitem,""),
BUILDIN_DEF(_,"s"),
};
int i, len = ARRAYLENGTH(BUILDIN);
diff --git a/src/map/skill.c b/src/map/skill.c
index c6233c31d..13cdeede3 100644
--- a/src/map/skill.c
+++ b/src/map/skill.c
@@ -15495,7 +15495,6 @@ int skill_graffitiremover (struct block_list *bl, va_list ap) {
struct skill_unit *su=NULL;
nullpo_ret(bl);
- nullpo_ret(ap);
if(bl->type != BL_SKILL)
return 0;
@@ -15526,7 +15525,6 @@ int skill_detonator(struct block_list *bl, va_list ap) {
int unit_id;
nullpo_ret(bl);
- nullpo_ret(ap);
src = va_arg(ap,struct block_list *);
if( bl->type != BL_SKILL )
diff --git a/src/map/status.c b/src/map/status.c
index 1136b4fec..dc4813055 100644
--- a/src/map/status.c
+++ b/src/map/status.c
@@ -7322,7 +7322,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
status_change_end(bl, SC_FOOD_LUK, INVALID_TIMER);
break;
case SC_ENDURE:
- if( val4 )
+ if( val4 == 1 )
status_change_end(bl, SC_LKCONCENTRATION, INVALID_TIMER);
break;
case SC_FIGHTINGSPIRIT:
@@ -10067,7 +10067,8 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const
}
break;
case SC_LKCONCENTRATION:
- status_change_end(bl, SC_ENDURE, INVALID_TIMER);
+ if (sc->data[SC_ENDURE] && sc->data[SC_ENDURE]->val4 != 2)
+ status_change_end(bl, SC_ENDURE, INVALID_TIMER);
break;
/**
* 3rd Stuff
diff --git a/src/map/storage.c b/src/map/storage.c
index 0a22b9ec6..95194bc47 100644
--- a/src/map/storage.c
+++ b/src/map/storage.c
@@ -109,7 +109,8 @@ int compare_item(struct item *a, struct item *b)
a->refine == b->refine &&
a->attribute == b->attribute &&
a->expire_time == b->expire_time &&
- a->bound == b->bound )
+ a->bound == b->bound &&
+ a->unique_id == b->unique_id)
{
int i;
for (i = 0; i < MAX_SLOTS && (a->card[i] == b->card[i]); i++);
@@ -155,6 +156,7 @@ int storage_additem(struct map_session_data* sd, struct item* item_data, int amo
{// existing items found, stack them
if( amount > MAX_AMOUNT - stor->items[i].amount || ( data->stack.storage && amount > data->stack.amount - stor->items[i].amount ) )
return 1;
+
stor->items[i].amount += amount;
clif->storageitemadded(sd,&stor->items[i],i,amount);
return 0;
diff --git a/src/plugins/HPMHooking/HPMHooking_map.HPMHooksCore.inc b/src/plugins/HPMHooking/HPMHooking_map.HPMHooksCore.inc
index 09f33bff6..e35a4c81c 100644
--- a/src/plugins/HPMHooking/HPMHooking_map.HPMHooksCore.inc
+++ b/src/plugins/HPMHooking/HPMHooking_map.HPMHooksCore.inc
@@ -1345,6 +1345,14 @@ struct {
struct HPMHookPoint *HP_clif_parse_roulette_db_post;
struct HPMHookPoint *HP_clif_roulette_generate_ack_pre;
struct HPMHookPoint *HP_clif_roulette_generate_ack_post;
+ struct HPMHookPoint *HP_clif_openmergeitem_pre;
+ struct HPMHookPoint *HP_clif_openmergeitem_post;
+ struct HPMHookPoint *HP_clif_cancelmergeitem_pre;
+ struct HPMHookPoint *HP_clif_cancelmergeitem_post;
+ struct HPMHookPoint *HP_clif_comparemergeitem_pre;
+ struct HPMHookPoint *HP_clif_comparemergeitem_post;
+ struct HPMHookPoint *HP_clif_ackmergeitems_pre;
+ struct HPMHookPoint *HP_clif_ackmergeitems_post;
struct HPMHookPoint *HP_clif_pWantToConnection_pre;
struct HPMHookPoint *HP_clif_pWantToConnection_post;
struct HPMHookPoint *HP_clif_pLoadEndAck_pre;
@@ -6552,6 +6560,14 @@ struct {
int HP_clif_parse_roulette_db_post;
int HP_clif_roulette_generate_ack_pre;
int HP_clif_roulette_generate_ack_post;
+ int HP_clif_openmergeitem_pre;
+ int HP_clif_openmergeitem_post;
+ int HP_clif_cancelmergeitem_pre;
+ int HP_clif_cancelmergeitem_post;
+ int HP_clif_comparemergeitem_pre;
+ int HP_clif_comparemergeitem_post;
+ int HP_clif_ackmergeitems_pre;
+ int HP_clif_ackmergeitems_post;
int HP_clif_pWantToConnection_pre;
int HP_clif_pWantToConnection_post;
int HP_clif_pLoadEndAck_pre;
diff --git a/src/plugins/HPMHooking/HPMHooking_map.HookingPoints.inc b/src/plugins/HPMHooking/HPMHooking_map.HookingPoints.inc
index 8c1456412..6501c0943 100644
--- a/src/plugins/HPMHooking/HPMHooking_map.HookingPoints.inc
+++ b/src/plugins/HPMHooking/HPMHooking_map.HookingPoints.inc
@@ -683,6 +683,10 @@ struct HookingPointData HookingPoints[] = {
{ HP_POP(clif->npc_market_purchase_ack, HP_clif_npc_market_purchase_ack) },
{ HP_POP(clif->parse_roulette_db, HP_clif_parse_roulette_db) },
{ HP_POP(clif->roulette_generate_ack, HP_clif_roulette_generate_ack) },
+ { HP_POP(clif->openmergeitem, HP_clif_openmergeitem) },
+ { HP_POP(clif->cancelmergeitem, HP_clif_cancelmergeitem) },
+ { HP_POP(clif->comparemergeitem, HP_clif_comparemergeitem) },
+ { HP_POP(clif->ackmergeitems, HP_clif_ackmergeitems) },
{ HP_POP(clif->pWantToConnection, HP_clif_pWantToConnection) },
{ HP_POP(clif->pLoadEndAck, HP_clif_pLoadEndAck) },
{ HP_POP(clif->pTickSend, HP_clif_pTickSend) },
diff --git a/src/plugins/HPMHooking/HPMHooking_map.Hooks.inc b/src/plugins/HPMHooking/HPMHooking_map.Hooks.inc
index c623747aa..04f31aea5 100644
--- a/src/plugins/HPMHooking/HPMHooking_map.Hooks.inc
+++ b/src/plugins/HPMHooking/HPMHooking_map.Hooks.inc
@@ -17751,6 +17751,111 @@ void HP_clif_roulette_generate_ack(struct map_session_data *sd, unsigned char re
}
return;
}
+void HP_clif_openmergeitem(int fd, struct map_session_data *sd) {
+ int hIndex = 0;
+ if( HPMHooks.count.HP_clif_openmergeitem_pre ) {
+ void (*preHookFunc) (int *fd, struct map_session_data *sd);
+ *HPMforce_return = false;
+ for(hIndex = 0; hIndex < HPMHooks.count.HP_clif_openmergeitem_pre; hIndex++ ) {
+ preHookFunc = HPMHooks.list.HP_clif_openmergeitem_pre[hIndex].func;
+ preHookFunc(&fd, sd);
+ }
+ if( *HPMforce_return ) {
+ *HPMforce_return = false;
+ return;
+ }
+ }
+ {
+ HPMHooks.source.clif.openmergeitem(fd, sd);
+ }
+ if( HPMHooks.count.HP_clif_openmergeitem_post ) {
+ void (*postHookFunc) (int *fd, struct map_session_data *sd);
+ for(hIndex = 0; hIndex < HPMHooks.count.HP_clif_openmergeitem_post; hIndex++ ) {
+ postHookFunc = HPMHooks.list.HP_clif_openmergeitem_post[hIndex].func;
+ postHookFunc(&fd, sd);
+ }
+ }
+ return;
+}
+void HP_clif_cancelmergeitem(int fd, struct map_session_data *sd) {
+ int hIndex = 0;
+ if( HPMHooks.count.HP_clif_cancelmergeitem_pre ) {
+ void (*preHookFunc) (int *fd, struct map_session_data *sd);
+ *HPMforce_return = false;
+ for(hIndex = 0; hIndex < HPMHooks.count.HP_clif_cancelmergeitem_pre; hIndex++ ) {
+ preHookFunc = HPMHooks.list.HP_clif_cancelmergeitem_pre[hIndex].func;
+ preHookFunc(&fd, sd);
+ }
+ if( *HPMforce_return ) {
+ *HPMforce_return = false;
+ return;
+ }
+ }
+ {
+ HPMHooks.source.clif.cancelmergeitem(fd, sd);
+ }
+ if( HPMHooks.count.HP_clif_cancelmergeitem_post ) {
+ void (*postHookFunc) (int *fd, struct map_session_data *sd);
+ for(hIndex = 0; hIndex < HPMHooks.count.HP_clif_cancelmergeitem_post; hIndex++ ) {
+ postHookFunc = HPMHooks.list.HP_clif_cancelmergeitem_post[hIndex].func;
+ postHookFunc(&fd, sd);
+ }
+ }
+ return;
+}
+int HP_clif_comparemergeitem(const void *a, const void *b) {
+ int hIndex = 0;
+ int retVal___ = 0;
+ if( HPMHooks.count.HP_clif_comparemergeitem_pre ) {
+ int (*preHookFunc) (const void *a, const void *b);
+ *HPMforce_return = false;
+ for(hIndex = 0; hIndex < HPMHooks.count.HP_clif_comparemergeitem_pre; hIndex++ ) {
+ preHookFunc = HPMHooks.list.HP_clif_comparemergeitem_pre[hIndex].func;
+ retVal___ = preHookFunc(a, b);
+ }
+ if( *HPMforce_return ) {
+ *HPMforce_return = false;
+ return retVal___;
+ }
+ }
+ {
+ retVal___ = HPMHooks.source.clif.comparemergeitem(a, b);
+ }
+ if( HPMHooks.count.HP_clif_comparemergeitem_post ) {
+ int (*postHookFunc) (int retVal___, const void *a, const void *b);
+ for(hIndex = 0; hIndex < HPMHooks.count.HP_clif_comparemergeitem_post; hIndex++ ) {
+ postHookFunc = HPMHooks.list.HP_clif_comparemergeitem_post[hIndex].func;
+ retVal___ = postHookFunc(retVal___, a, b);
+ }
+ }
+ return retVal___;
+}
+void HP_clif_ackmergeitems(int fd, struct map_session_data *sd) {
+ int hIndex = 0;
+ if( HPMHooks.count.HP_clif_ackmergeitems_pre ) {
+ void (*preHookFunc) (int *fd, struct map_session_data *sd);
+ *HPMforce_return = false;
+ for(hIndex = 0; hIndex < HPMHooks.count.HP_clif_ackmergeitems_pre; hIndex++ ) {
+ preHookFunc = HPMHooks.list.HP_clif_ackmergeitems_pre[hIndex].func;
+ preHookFunc(&fd, sd);
+ }
+ if( *HPMforce_return ) {
+ *HPMforce_return = false;
+ return;
+ }
+ }
+ {
+ HPMHooks.source.clif.ackmergeitems(fd, sd);
+ }
+ if( HPMHooks.count.HP_clif_ackmergeitems_post ) {
+ void (*postHookFunc) (int *fd, struct map_session_data *sd);
+ for(hIndex = 0; hIndex < HPMHooks.count.HP_clif_ackmergeitems_post; hIndex++ ) {
+ postHookFunc = HPMHooks.list.HP_clif_ackmergeitems_post[hIndex].func;
+ postHookFunc(&fd, sd);
+ }
+ }
+ return;
+}
void HP_clif_pWantToConnection(int fd, struct map_session_data *sd) {
int hIndex = 0;
if( HPMHooks.count.HP_clif_pWantToConnection_pre ) {
diff --git a/src/plugins/db2sql.c b/src/plugins/db2sql.c
index 7cef173d2..2741ce468 100644
--- a/src/plugins/db2sql.c
+++ b/src/plugins/db2sql.c
@@ -139,7 +139,10 @@ int db2sql(config_setting_t *entry, int n, const char *source) {
// bindonequip
StrBuf->Printf(&buf, "'%u',", it->flag.bindonequip?1:0);
-
+
+ // forceserial
+ StrBuf->Printf(&buf, "'%u',", it->flag.force_serial?1:0);
+
// buyingstore
StrBuf->Printf(&buf, "'%u',", it->flag.buyingstore?1:0);
@@ -269,6 +272,7 @@ void totable(void) {
" `refineable` tinyint(1) UNSIGNED DEFAULT NULL,\n"
" `view` smallint(3) UNSIGNED DEFAULT NULL,\n"
" `bindonequip` tinyint(1) UNSIGNED DEFAULT NULL,\n"
+ " `forceserial` tinyint(1) UNSIGNED DEFAULT NULL,\n"
" `buyingstore` tinyint(1) UNSIGNED DEFAULT NULL,\n"
" `delay` mediumint(9) UNSIGNED DEFAULT NULL,\n"
" `trade_flag` smallint(4) UNSIGNED DEFAULT NULL,\n"