* Cleaned up some messy guild code (more to come)

* Cleaned up the mail code, no more pointless dynamic allocation
* Added upgrade_svn11548.sql to convert the mail table to new format
* Updated vs7 and vs6 project files
* Increased the max. send buffer size to 5M since 1M is not enough
* Please complain if something stops working ^^;

git-svn-id: https://svn.code.sf.net/p/rathena/svn/trunk@11571 54d463be-8e91-2dee-dedb-b68131a5f0ec
This commit is contained in:
ultramage 2007-10-24 12:14:18 +00:00
parent 895ee4a0ad
commit d091f1cf05
24 changed files with 642 additions and 644 deletions

View File

@ -3,6 +3,12 @@ Date Added
AS OF SVN REV. 5091, WE ARE NOW USING TRUNK. ALL UNTESTED BUGFIXES/FEATURES GO INTO TRUNK.
IF YOU HAVE A WORKING AND TESTED BUGFIX PUT IT INTO STABLE AS WELL AS TRUNK.
2007/10/24
* Increased the max. send buffer size to 5M since 1M is not enough
* Updated vs7 and vs6 project files
* Added upgrade_svn11548.sql to convert the mail table to new format
* Cleaned up the mail code, no more pointless dynamic allocation
* Cleaned up some messy guild code (more to come) [ultramage]
2007/10/23
* Fixed a compilation bug on linux (FALSE -> false) [Zephyrus]
2007/10/22

View File

@ -146,7 +146,7 @@ char_log_filename: log/char.log
// Allow or not identical name for characters but with a different case (upper/lower):
// example: Test-test-TEST-TesT; Value: 0 not allowed (default), 1 allowed
name_ignoring_case: 0
name_ignoring_case: no
// Manage possible letters/symbol in the name of charater. Control character (0x00-0x1f) are never accepted. Possible values are:
// NOTE: Applies to character, party and guild names.

View File

@ -753,7 +753,6 @@ packet_ver: 18
0x0116,12,dropitem,6:10
0x0190,21,actionrequest,5:20
0x0216,6
//Start mail system?
0x023f,2,mailrefresh,0
0x0240,8
0x0241,6,mailread,2
@ -761,13 +760,9 @@ packet_ver: 18
0x0243,6,maildelete,2
0x0244,6,mailgetattach,2
0x0245,7
//Start writing a mail?
0x0246,4,mailwinopen,2
//Send Item/Zeny
0x0247,8,mailsetattach,2:4
//Message
0x0248,68
//Delivered?
0x0249,3
0x024a,70
0x024b,4

View File

@ -1,232 +1,233 @@
//===== eAthena Script =======================================
//= Advanced Refiner
//===== By: ==================================================
//= L0ne_W0lf
//===== Current Version: =====================================
//= 1.0
//===== Compatible With: =====================================
//= Eathena SVN
//===== Description: =========================================
//= [Aegis Conversion]
//= Refiner that uses Enriched ores to increase upgrade success.
//= After a conversation with Doddler, it's been established that
//= the advanced refiner works similar the the "Bubble Gum" item.
//= The success percentage is not "increased" however, if it fails
//= You get a second try. This tries twice at the same time,
//= effectively giving you a re-roll on your attempt.
//= - Dialog is only partly official to iRO.
//= - Uses the iRO position for this NPC.
//===== Additional Comments: =================================
//= 1.0 First Version. [L0ne_W0lf]
//============================================================
payon,174,138,0 script Suhnbi#cash 85,{
mes "[Suhnbi]";
mes "I am the Armsith";
mes "I can refine all kinds of weapons,";
mes "armor and equipment, so let me";
mes "know what you want to refine.";
next;
set .@strRetPart1$,getequipname(1);
set .@strRetPart2$,getequipname(2);
set .@strRetPart3$,getequipname(3);
set .@strRetPart4$,getequipname(4);
set .@strRetPart5$,getequipname(5);
set .@strRetPart6$,getequipname(6);
set .@strRetPart7$,getequipname(7);
set .@strRetPart8$,getequipname(8);
set .@strRetPart9$,getequipname(9);
set .@strRetPart10$,getequipname(10);
set .@menu$,.@strRetPart1$+":"+.@strRetPart2$+":"+.@strRetPart3$+":"+.@strRetPart4$+":"+.@strRetPart5$+":"+.@strRetPart6$+":"+.@strRetPart7$+":"+.@strRetPart8$+":"+.@strRetPart9$+":"+.@strRetPart10$;
switch(select(.@menu$)) {
case 1:
set .@part,1;
if (getequipisequiped(1) == 0) {
mes "[Suhnbi]";
mes "Do you want me to refine your skull?";
close;
}
break;
case 2:
set .@part,2;
if (getequipisequiped(2) == 0) {
mes "[Suhnbi]";
mes "I'll refine your torso with my own passionate body!";
close;
}
break;
case 3:
set .@part,3;
if (getequipisequiped(3) == 0) {
mes "[Suhnbi]";
mes "Sorry, there ain't any technology yet to put rockets on your left hand...";
close;
}
break;
case 4:
set .@part,4;
if (getequipisequiped(4) == 0) {
mes "[Suhnbi]";
mes "Sorry, there ain't any technology yet to put rockets on your right hand...";
close;
}
break;
case 5:
set .@part,5;
if (getequipisequiped(5) == 0) {
mes "[Suhnbi]";
mes "You're not even wearing a garment? Are you?";
close;
}
break;
case 6:
set .@part,6;
if (getequipisequiped(6) == 0) {
mes "[Suhnbi]";
mes "What do I look like, a makeover artist? I can't refine your bare feet!";
close;
}
break;
case 7:
set .@part,7;
if (getequipisequiped(7) == 0) {
mes "[Suhnbi]";
mes "Um... You're not wearing an Accessory.";
close;
}
break;
case 8:
set .@part,8;
if (getequipisequiped(8) == 0) {
mes "[Suhnbi]";
mes "Accessory? You're not wearing one of those.";
close;
}
break;
case 9:
set .@part,9;
if (getequipisequiped(9) == 0) {
mes "[Suhnbi]";
mes "I refine equipment. I don't give hair cuts.";
close;
}
break;
case 10:
set .@part,10;
if (getequipisequiped(10) == 0) {
mes "[Suhnbi]";
mes "What am I, your personal hairstylist?. Go to the salon if you want work done on your precious hair.";
close2;
}
break;
}
if (getequipisenableref(.@part) == 0) {
mes "[Suhnbi]";
mes "I don't think I can refine this item at all.";
close;
}
if (getequipisidentify(.@part) == 0) {
mes "[Suhnbi]";
mes "This is has not been identified. So, it can't be refined...";
close;
}
if (getequiprefinerycnt(.@part) >= 10) {
mes "[Suhnbi]";
mes "This item cannot be refined because it has already reached its maximum level...";
close;
}
// Make sure you have the neccessary items and Zeny to refine your items
// Determines chance of failure and verifies that you want to continue.
switch(getequipweaponlv(.@part)) {
case 1: callsub S_RefineValidate,1,7620,50,.@part; break;
case 2: callsub S_RefineValidate,2,7620,200,.@part; break;
case 3: callsub S_RefineValidate,3,7620,5000,.@part; break;
case 4: callsub S_RefineValidate,4,7620,20000,.@part; break;
default: callsub S_RefineValidate,0,7619,2000,.@part; break;
}
if (getequippercentrefinery(.@part) > rand(100) || getequippercentrefinery(.@part) > rand(100)) {
mes "[Suhnbi]";
mes "Clink! Clank! Clunk!";
SuccessRefItem .@part;
next;
Emotion e_no1;
mes "[Suhnbi]";
mes "Here you are! It's done.";
mes "It's been a while since I've made such a fine weapon. You must be happy because it has become stronger!";
close;
}
else {
mes "[Suhnbi]";
mes "Clink! Clank! Clunk!";
FailedRefItem .@part;
next;
if (rand(5) == 1)
Emotion e_cash;
else
Emotion e_omg;
mes "[Suhnbi]";
mes "Cough!!!!";
next;
mes "[Suhnbi]";
mes "Cough...Cough..";
mes "What a shame...";
mes "Your equipment broke during hte refining process. I had told you earlier this might happen!";
close;
}
S_RefineValidate:
mes "[Suhnbi]";
if (getarg(0))
mes "A level "+getarg(0)+" weapon...";
mes "To refine this I need one ^ff9999"+getitemname(getarg(1))+"^000000 and a service fee of "+getarg(2)+" Zeny.";
mes "Do you wish to continue?";
next;
if (select("Yes:No") == 1) {
if (getequippercentrefinery(getarg(3)) < 100) {
mes "[Suhnbi]";
mes "Wow!!";
mes "This weapon, probably";
mes "looks like it's been refined...";
mes "many times...";
mes "It may break if";
mes "you refine it again.";
next;
mes "And if it breaks,";
mes "you can't use it anymore!";
mes "All the cards in it and the";
mes "properties";
mes "^ff0000will be lost^000000!!";
mes "^ff0000 besides, the equipment will break!^000000";
mes " ";
mes "Are you sure you still want to continue?";
next;
if (select("Yes:No") == 2) {
mes "[Suhnbi]";
mes "I completely agree...";
mes "I might be a great refiner, but something even I make mistakes.";
close;
}
}
if (countitem(getarg(1)) > 0 && Zeny > getarg(2)) {
delitem getarg(1),1;
set zeny,zeny-getarg(2);
return;
}
else {
mes "[Suhnbi]";
mes "You don't seem to have enough Zeny or "+getitemname(getarg(1))+"...";
mes "Go get some more. I'll be here ll day if you need me.";
close;
}
}
else {
mes "[Suhnbi]";
mes "Yeah... There's no need to rush.";
mes "Take your time.";
close;
}
}
//===== eAthena Script =======================================
//= Advanced Refiner
//===== By: ==================================================
//= L0ne_W0lf
//===== Current Version: =====================================
//= 1.0
//===== Compatible With: =====================================
//= Eathena SVN
//===== Description: =========================================
//= [Aegis Conversion]
//= Refiner that uses Enriched ores to increase upgrade
success.
//= After a conversation with Doddler, it's been established that
//= the advanced refiner works similar the the "Bubble Gum" item.
//= The success percentage is not "increased" however, if it fails
//= You get a second try. This tries twice at the same time,
//= effectively giving you a re-roll on your attempt.
//= - Dialog is only partly official to iRO.
//= - Uses the iRO position for this NPC.
//===== Additional Comments: =================================
//= 1.0 First Version. [L0ne_W0lf]
//============================================================
payon,174,138,0 script Suhnbi#cash 85,{
mes "[Suhnbi]";
mes "I am the Armsith";
mes "I can refine all kinds of weapons,";
mes "armor and equipment, so let me";
mes "know what you want to refine.";
next;
set .@strRetPart1$,getequipname(1);
set .@strRetPart2$,getequipname(2);
set .@strRetPart3$,getequipname(3);
set .@strRetPart4$,getequipname(4);
set .@strRetPart5$,getequipname(5);
set .@strRetPart6$,getequipname(6);
set .@strRetPart7$,getequipname(7);
set .@strRetPart8$,getequipname(8);
set .@strRetPart9$,getequipname(9);
set .@strRetPart10$,getequipname(10);
set .@menu$,.@strRetPart1$+":"+.@strRetPart2$+":"+.@strRetPart3$+":"+.@strRetPart4$+":"+.@strRetPart5$+":"+.@strRetPart6$+":"+.@strRetPart7$+":"+.@strRetPart8$+":"+.@strRetPart9$+":"+.@strRetPart10$;
switch(select(.@menu$)) {
case 1:
set .@part,1;
if (getequipisequiped(1) == 0) {
mes "[Suhnbi]";
mes "Do you want me to refine your skull?";
close;
}
break;
case 2:
set .@part,2;
if (getequipisequiped(2) == 0) {
mes "[Suhnbi]";
mes "I'll refine your torso with my own passionate body!";
close;
}
break;
case 3:
set .@part,3;
if (getequipisequiped(3) == 0) {
mes "[Suhnbi]";
mes "Sorry, there ain't any technology yet to put rockets on your left hand...";
close;
}
break;
case 4:
set .@part,4;
if (getequipisequiped(4) == 0) {
mes "[Suhnbi]";
mes "Sorry, there ain't any technology yet to put rockets on your right hand...";
close;
}
break;
case 5:
set .@part,5;
if (getequipisequiped(5) == 0) {
mes "[Suhnbi]";
mes "You're not even wearing a garment? Are you?";
close;
}
break;
case 6:
set .@part,6;
if (getequipisequiped(6) == 0) {
mes "[Suhnbi]";
mes "What do I look like, a makeover artist? I can't refine your bare feet!";
close;
}
break;
case 7:
set .@part,7;
if (getequipisequiped(7) == 0) {
mes "[Suhnbi]";
mes "Um... You're not wearing an Accessory.";
close;
}
break;
case 8:
set .@part,8;
if (getequipisequiped(8) == 0) {
mes "[Suhnbi]";
mes "Accessory? You're not wearing one of those.";
close;
}
break;
case 9:
set .@part,9;
if (getequipisequiped(9) == 0) {
mes "[Suhnbi]";
mes "I refine equipment. I don't give hair cuts.";
close;
}
break;
case 10:
set .@part,10;
if (getequipisequiped(10) == 0) {
mes "[Suhnbi]";
mes "What am I, your personal hairstylist?. Go to the salon if you want work done on your precious hair.";
close2;
}
break;
}
if (getequipisenableref(.@part) == 0) {
mes "[Suhnbi]";
mes "I don't think I can refine this item at all.";
close;
}
if (getequipisidentify(.@part) == 0) {
mes "[Suhnbi]";
mes "This is has not been identified. So, it can't be refined...";
close;
}
if (getequiprefinerycnt(.@part) >= 10) {
mes "[Suhnbi]";
mes "This item cannot be refined because it has already reached its maximum level...";
close;
}
// Make sure you have the neccessary items and Zeny to refine your items
// Determines chance of failure and verifies that you want to continue.
switch(getequipweaponlv(.@part)) {
case 1: callsub S_RefineValidate,1,7620,50,.@part; break;
case 2: callsub S_RefineValidate,2,7620,200,.@part; break;
case 3: callsub S_RefineValidate,3,7620,5000,.@part; break;
case 4: callsub S_RefineValidate,4,7620,20000,.@part; break;
default: callsub S_RefineValidate,0,7619,2000,.@part; break;
}
if (getequippercentrefinery(.@part) > rand(100) || getequippercentrefinery(.@part) > rand(100)) {
mes "[Suhnbi]";
mes "Clink! Clank! Clunk!";
SuccessRefItem .@part;
next;
Emotion e_no1;
mes "[Suhnbi]";
mes "Here you are! It's done.";
mes "It's been a while since I've made such a fine weapon. You must be happy because it has become stronger!";
close;
}
else {
mes "[Suhnbi]";
mes "Clink! Clank! Clunk!";
FailedRefItem .@part;
next;
if (rand(5) == 1)
Emotion e_cash;
else
Emotion e_omg;
mes "[Suhnbi]";
mes "Cough!!!!";
next;
mes "[Suhnbi]";
mes "Cough...Cough..";
mes "What a shame...";
mes "Your equipment broke during hte refining process. I had told you earlier this might happen!";
close;
}
S_RefineValidate:
mes "[Suhnbi]";
if (getarg(0))
mes "A level "+getarg(0)+" weapon...";
mes "To refine this I need one ^ff9999"+getitemname(getarg(1))+"^000000 and a service fee of "+getarg(2)+" Zeny.";
mes "Do you wish to continue?";
next;
if (select("Yes:No") == 1) {
if (getequippercentrefinery(getarg(3)) < 100) {
mes "[Suhnbi]";
mes "Wow!!";
mes "This weapon, probably";
mes "looks like it's been refined...";
mes "many times...";
mes "It may break if";
mes "you refine it again.";
next;
mes "And if it breaks,";
mes "you can't use it anymore!";
mes "All the cards in it and the";
mes "properties";
mes "^ff0000will be lost^000000!!";
mes "^ff0000 besides, the equipment will break!^000000";
mes " ";
mes "Are you sure you still want to continue?";
next;
if (select("Yes:No") == 2) {
mes "[Suhnbi]";
mes "I completely agree...";
mes "I might be a great refiner, but something even I make mistakes.";
close;
}
}
if (countitem(getarg(1)) > 0 && Zeny > getarg(2)) {
delitem getarg(1),1;
set zeny,zeny-getarg(2);
return;
}
else {
mes "[Suhnbi]";
mes "You don't seem to have enough Zeny or "+getitemname(getarg(1))+"...";
mes "Go get some more. I'll be here ll day if you need me.";
close;
}
}
else {
mes "[Suhnbi]";
mes "Yeah... There's no need to rush.";
mes "Take your time.";
close;
}
}

View File

@ -1,5 +1,5 @@
ALTER TABLE `atcommandlog` CHANGE `command` `command` VARCHAR( 255 ) NOT NULL;
ALTER TABLE `atcommandlog` CHANGE `char_name` `char_name` VARCHAR( 25 ) NOT NULL;
ALTER TABLE `branchlog` CHANGE `char_name` `char_name` VARCHAR( 25 ) NOT NULL;
ALTER TABLE `npclog` CHANGE `char_name` `char_name` VARCHAR( 25 ) NOT NULL;
ALTER TABLE `atcommandlog` CHANGE `command` `command` VARCHAR( 255 ) NOT NULL;
ALTER TABLE `atcommandlog` CHANGE `char_name` `char_name` VARCHAR( 25 ) NOT NULL;
ALTER TABLE `branchlog` CHANGE `char_name` `char_name` VARCHAR( 25 ) NOT NULL;
ALTER TABLE `npclog` CHANGE `char_name` `char_name` VARCHAR( 25 ) NOT NULL;

View File

@ -0,0 +1,29 @@
-- this will covert the old `mail` table to new format, convert columns and fill in default values --
-- change structure --
ALTER TABLE `mail` CHANGE `message_id` `id` bigint(20) unsigned NOT NULL auto_increment;
ALTER TABLE `mail` CHANGE `from_char_name` `send_name` varchar(30) NOT NULL default '' AFTER `id`;
ALTER TABLE `mail` CHANGE `from_account_id` `send_id` int(11) unsigned NOT NULL default 0 AFTER `send_name`;
ALTER TABLE `mail` CHANGE `to_char_name` `dest_name` varchar(30) NOT NULL default '' AFTER `send_id`;
ALTER TABLE `mail` CHANGE `to_account_id` `dest_id` int(11) unsigned NOT NULL default 0 AFTER `dest_name`;
ALTER TABLE `mail` ADD `title` varchar(45) NOT NULL default '' AFTER `dest_id`;
ALTER TABLE `mail` CHANGE `message` `message` varchar(255) NOT NULL default '' AFTER `title`;
ALTER TABLE `mail` ADD `time` int(11) unsigned NOT NULL default 0 AFTER `message`;
ALTER TABLE `mail` CHANGE `read_flag` `read_flag` tinyint(1) NOT NULL default 0 AFTER `time`;
ALTER TABLE `mail` ADD `zeny` int(11) unsigned NOT NULL default 0 AFTER `read_flag`;
ALTER TABLE `mail` ADD `nameid` int(11) unsigned NOT NULL default 0 AFTER `zeny`;
ALTER TABLE `mail` ADD `amount` int(11) unsigned NOT NULL default 0 AFTER `nameid`;
ALTER TABLE `mail` ADD `refine` tinyint(3) unsigned NOT NULL default 0 AFTER `amount`;
ALTER TABLE `mail` ADD `attribute` tinyint(4) unsigned NOT NULL default 0 AFTER `refine`;
ALTER TABLE `mail` ADD `identify` smallint(6) NOT NULL default 0 AFTER `attribute`;
ALTER TABLE `mail` ADD `card0` smallint(11) NOT NULL default 0 AFTER `identify`;
ALTER TABLE `mail` ADD `card1` smallint(11) NOT NULL default 0 AFTER `card0`;
ALTER TABLE `mail` ADD `card2` smallint(11) NOT NULL default 0 AFTER `card1`;
ALTER TABLE `mail` ADD `card3` smallint(11) NOT NULL default 0 AFTER `card2`;
ALTER TABLE `mail` DROP `priority`;
ALTER TABLE `mail` DROP `check_flag`;
-- correct values in some columns --
UPDATE `mail` SET `time` = UNIX_TIMESTAMP(NOW());
UPDATE `mail` SET `send_id` = (SELECT `char_id` FROM `char` WHERE `name` = `send_name`);
UPDATE `mail` SET `dest_id` = (SELECT `char_id` FROM `char` WHERE `name` = `dest_name`);

View File

@ -1516,9 +1516,7 @@ int mapif_parse_GuildMasterChange(int fd, int guild_id, const char* name, int le
g->member[pos].position = g->member[0].position;
g->member[0].position = 0; //Position 0: guild Master.
strncpy(g->master, name, len);
if (len < NAME_LENGTH)
g->master[len] = '\0';
safestrncpy(g->master, name, NAME_LENGTH);
ShowInfo("int_guild: Guildmaster Changed to %s (Guild %d - %s)\n",name, guild_id, g->name);
return mapif_guild_master_changed(g, g->member[0].account_id, g->member[0].char_id);

View File

@ -53,12 +53,12 @@ int inter_recv_packet_length[]={
6,-1, 0, 0, 0, 0, 0, 0, 10,-1, 0, 0, 0, 0, 0, 0, //0x3010-0x301f
-1, 6,-1,14, 14,19, 6,-1, 14,14, 0, 0, 0, 0, 0, 0, //0x3020-0x302f
-1, 6,-1,-1, 55,19, 6,-1, 14,-1,-1,-1, 14,19,186,-1, //0x3030-0x303f
5, 9, 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, 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,
5, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //0x3040-0x304f
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //0x3050-0x305f
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //0x3060-0x306f
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //0x3070-0x307f
48,14,-1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //0x3080-0x308f
-1,10,-1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x3090 - 0x309f Homunculus packets [albator]
-1,10,-1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //0x3090-0x309f Homunculus packets [albator]
};
struct WisData {

View File

@ -3205,13 +3205,13 @@ int mapif_send(int fd, unsigned char *buf, unsigned int len)
int i;
if (fd >= 0) {
for(i = 0; i < MAX_MAP_SERVERS; i++) {
if (fd == server_fd[i]) {
WFIFOHEAD(fd,len);
memcpy(WFIFOP(fd,0), buf, len);
WFIFOSET(fd,len);
return 1;
}
ARR_FIND( 0, MAX_MAP_SERVERS, i, fd == server_fd[i] );
if( i < MAX_MAP_SERVERS )
{
WFIFOHEAD(fd,len);
memcpy(WFIFOP(fd,0), buf, len);
WFIFOSET(fd,len);
return 1;
}
}
return 0;

View File

@ -14,15 +14,14 @@
#include <string.h>
#include <stdlib.h>
struct mail_data *mail_data_pt = NULL;
time_t calc_times(void)
static time_t calc_times(void)
{
time_t temp = time(NULL);
return mktime(localtime(&temp));
}
int mail_fromsql(int char_id, struct mail_data *md)
static int mail_fromsql(int char_id, struct mail_data* md)
{
int i, j;
struct mail_message *msg;
@ -80,11 +79,11 @@ int mail_fromsql(int char_id, struct mail_data *md)
Sql_FreeResult(sql_handle);
md->unchecked = 0;
md->unreaded = 0;
md->unread = 0;
for (i = 0; i < md->amount; i++)
{
msg = &md->msg[i];
if (!msg->read)
if( msg->read == 0 )
{
if ( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `read_flag` = '1' WHERE `id` = '%d'", mail_db, msg->id) )
Sql_ShowDebug(sql_handle);
@ -92,7 +91,7 @@ int mail_fromsql(int char_id, struct mail_data *md)
md->unchecked++;
}
else if ( msg->read == 1 )
md->unreaded++;
md->unread++;
msg->read = (msg->read < 2)?0:1;
}
@ -101,151 +100,144 @@ int mail_fromsql(int char_id, struct mail_data *md)
return 1;
}
int mail_savemessage(struct mail_message *msg)
/// Stores a single message in the database.
/// Returns the message's ID if successful (or 0 if it fails).
static int mail_savemessage(struct mail_message* msg)
{
StringBuf buf;
SqlStmt* stmt;
int j;
char esc_send_name[NAME_LENGTH*2+1], esc_dest_name[NAME_LENGTH*2+1];
char esc_title[MAIL_TITLE_LENGTH*2+1], esc_body[MAIL_BODY_LENGTH*2+1];
if (!msg)
return 0;
Sql_EscapeStringLen(sql_handle, esc_send_name, msg->send_name, strnlen(msg->send_name, NAME_LENGTH));
Sql_EscapeStringLen(sql_handle, esc_dest_name, msg->dest_name, strnlen(msg->dest_name, NAME_LENGTH));
Sql_EscapeStringLen(sql_handle, esc_title, msg->title, strnlen(msg->title, MAIL_TITLE_LENGTH));
Sql_EscapeStringLen(sql_handle, esc_body, msg->body, strnlen(msg->body, MAIL_BODY_LENGTH));
// build message save query
StringBuf_Init(&buf);
StringBuf_Printf(&buf, "INSERT INTO `%s` (`send_name`, `send_id`, `dest_name`, `dest_id`, `title`, `message`, `time`, `read_flag`, `zeny`, `amount`, `nameid`, `refine`, `attribute`, `identify`", mail_db);
for (j = 0; j < MAX_SLOTS; j++)
StringBuf_Printf(&buf, ", `card%d`", j);
StringBuf_Printf(&buf, ") VALUES ('%s', '%d', '%s', '%d', '%s', '%s', '%d', '0', '%d', '%d', '%d', '%d', '%d', '%d'",
esc_send_name, msg->send_id, esc_dest_name, msg->dest_id, esc_title, esc_body, msg->timestamp, msg->zeny, msg->item.amount, msg->item.nameid, msg->item.refine, msg->item.attribute, msg->item.identify);
StringBuf_Printf(&buf, ") VALUES (?, '%d', ?, '%d', ?, ?, '%d', '0', '%d', '%d', '%d', '%d', '%d', '%d'",
msg->send_id, msg->dest_id, msg->timestamp, msg->zeny, msg->item.amount, msg->item.nameid, msg->item.refine, msg->item.attribute, msg->item.identify);
for (j = 0; j < MAX_SLOTS; j++)
StringBuf_Printf(&buf, ", '%d'", msg->item.card[j]);
StringBuf_AppendStr(&buf, ")");
if( SQL_ERROR == Sql_QueryStr(sql_handle, StringBuf_Value(&buf)) )
// prepare and execute query
stmt = SqlStmt_Malloc(sql_handle);
if( SQL_SUCCESS != SqlStmt_PrepareStr(stmt, StringBuf_Value(&buf))
|| SQL_SUCCESS != SqlStmt_BindParam(stmt, 0, SQLDT_STRING, msg->send_name, strnlen(msg->send_name, NAME_LENGTH))
|| SQL_SUCCESS != SqlStmt_BindParam(stmt, 1, SQLDT_STRING, msg->dest_name, strnlen(msg->dest_name, NAME_LENGTH))
|| SQL_SUCCESS != SqlStmt_BindParam(stmt, 2, SQLDT_STRING, msg->title, strnlen(msg->title, NAME_LENGTH))
|| SQL_SUCCESS != SqlStmt_BindParam(stmt, 3, SQLDT_STRING, msg->body, strnlen(msg->body, NAME_LENGTH))
|| SQL_SUCCESS != SqlStmt_Execute(stmt) )
{
Sql_ShowDebug(sql_handle);
j = 0;
}
else
} else
j = (int)Sql_LastInsertId(sql_handle);
StringBuf_Destroy(&buf);
// return the ID of the new mail
return j;
}
int mail_loadmessage(int char_id, int mail_id, struct mail_message *message, short flag)
/// Retrieves a single message from the database.
/// Returns true if the operation succeeds (or false if it fails).
static bool mail_loadmessage(int char_id, int mail_id, struct mail_message* msg)
{
char *data;
struct item *item;
int j = 0;
int j;
StringBuf buf;
StringBuf_Init(&buf);
StringBuf_AppendStr(&buf, "SELECT `id`,`send_name`,`send_id`,`dest_name`,`dest_id`,`title`,`message`,`time`,`read_flag`,"
"`zeny`,`amount`,`nameid`,`refine`,`attribute`,`identify`");
for (j = 0; j < MAX_SLOTS; j++)
for( j = 0; j < MAX_SLOTS; j++ )
StringBuf_Printf(&buf, ",`card%d`", j);
StringBuf_Printf(&buf, " FROM `%s` WHERE `dest_id` = '%d' AND `id` = '%d'", mail_db, char_id, mail_id);
if( SQL_ERROR == Sql_Query(sql_handle, StringBuf_Value(&buf)) )
if( SQL_ERROR == Sql_Query(sql_handle, StringBuf_Value(&buf))
|| SQL_SUCCESS != Sql_NextRow(sql_handle) )
{
Sql_ShowDebug(sql_handle);
else if( Sql_NumRows(sql_handle) == 0 )
ShowWarning("Char %d trying to read an invalid mail.\n", char_id);
Sql_FreeResult(sql_handle);
StringBuf_Destroy(&buf);
return false;
}
else
{
Sql_NextRow(sql_handle);
char* data;
Sql_GetData(sql_handle, 0, &data, NULL); message->id = atoi(data);
Sql_GetData(sql_handle, 1, &data, NULL); safestrncpy(message->send_name, data, NAME_LENGTH);
Sql_GetData(sql_handle, 2, &data, NULL); message->send_id = atoi(data);
Sql_GetData(sql_handle, 3, &data, NULL); safestrncpy(message->dest_name, data, NAME_LENGTH);
Sql_GetData(sql_handle, 4, &data, NULL); message->dest_id = atoi(data);
Sql_GetData(sql_handle, 5, &data, NULL); safestrncpy(message->title, data, MAIL_TITLE_LENGTH);
Sql_GetData(sql_handle, 6, &data, NULL); safestrncpy(message->body, data, MAIL_BODY_LENGTH);
Sql_GetData(sql_handle, 7, &data, NULL); message->timestamp = atoi(data);
Sql_GetData(sql_handle, 8, &data, NULL); message->read = atoi(data);
Sql_GetData(sql_handle, 9, &data, NULL); message->zeny = atoi(data);
item = &message->item;
Sql_GetData(sql_handle,10, &data, NULL); item->amount = (short)atoi(data);
Sql_GetData(sql_handle,11, &data, NULL); item->nameid = atoi(data);
Sql_GetData(sql_handle,12, &data, NULL); item->refine = atoi(data);
Sql_GetData(sql_handle,13, &data, NULL); item->attribute = atoi(data);
Sql_GetData(sql_handle,14, &data, NULL); item->identify = atoi(data);
for (j = 0; j < MAX_SLOTS; j++)
Sql_GetData(sql_handle, 0, &data, NULL); msg->id = atoi(data);
Sql_GetData(sql_handle, 1, &data, NULL); safestrncpy(msg->send_name, data, NAME_LENGTH);
Sql_GetData(sql_handle, 2, &data, NULL); msg->send_id = atoi(data);
Sql_GetData(sql_handle, 3, &data, NULL); safestrncpy(msg->dest_name, data, NAME_LENGTH);
Sql_GetData(sql_handle, 4, &data, NULL); msg->dest_id = atoi(data);
Sql_GetData(sql_handle, 5, &data, NULL); safestrncpy(msg->title, data, MAIL_TITLE_LENGTH);
Sql_GetData(sql_handle, 6, &data, NULL); safestrncpy(msg->body, data, MAIL_BODY_LENGTH);
Sql_GetData(sql_handle, 7, &data, NULL); msg->timestamp = atoi(data);
Sql_GetData(sql_handle, 8, &data, NULL); msg->read = atoi(data);
Sql_GetData(sql_handle, 9, &data, NULL); msg->zeny = atoi(data);
Sql_GetData(sql_handle,10, &data, NULL); msg->item.amount = (short)atoi(data);
Sql_GetData(sql_handle,11, &data, NULL); msg->item.nameid = atoi(data);
Sql_GetData(sql_handle,12, &data, NULL); msg->item.refine = atoi(data);
Sql_GetData(sql_handle,13, &data, NULL); msg->item.attribute = atoi(data);
Sql_GetData(sql_handle,14, &data, NULL); msg->item.identify = atoi(data);
for( j = 0; j < MAX_SLOTS; j++ )
{
Sql_GetData(sql_handle,15 + j, &data, NULL);
item->card[j] = atoi(data);
msg->item.card[j] = atoi(data);
}
j = 1;
}
StringBuf_Destroy(&buf);
Sql_FreeResult(sql_handle);
if (message->read == 1)
ShowDebug("Loaded message (had read flag %d)\n", msg->read);
if (msg->read == 1)
{
message->read = 0;
if (flag)
if ( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `read_flag` = '2' WHERE `id` = '%d'", mail_db, message->id) )
Sql_ShowDebug(sql_handle);
msg->read = 0;
}
else
message->read = 1;
msg->read = 1;
return j;
return true;
}
/*==========================================
* Client Inbox Request
*------------------------------------------*/
int mapif_Mail_sendinbox(int fd, int char_id, unsigned char flag)
static void mapif_Mail_sendinbox(int fd, int char_id, unsigned char flag)
{
WFIFOHEAD(fd, sizeof(struct mail_data) + 9);
mail_fromsql(char_id, mail_data_pt);
struct mail_data md;
mail_fromsql(char_id, &md);
//FIXME: dumping the whole structure like this is unsafe [ultramage]
WFIFOHEAD(fd, sizeof(md) + 9);
WFIFOW(fd,0) = 0x3848;
WFIFOW(fd,2) = sizeof(struct mail_data) + 9;
WFIFOW(fd,2) = sizeof(md) + 9;
WFIFOL(fd,4) = char_id;
WFIFOB(fd,8) = flag;
memcpy(WFIFOP(fd,9),mail_data_pt,sizeof(struct mail_data));
memcpy(WFIFOP(fd,9),&md,sizeof(md));
WFIFOSET(fd,WFIFOW(fd,2));
return 0;
}
int mapif_parse_Mail_requestinbox(int fd)
static void mapif_parse_Mail_requestinbox(int fd)
{
RFIFOHEAD(fd);
mapif_Mail_sendinbox(fd, RFIFOL(fd,2), RFIFOB(fd,6));
return 0;
}
/*==========================================
* Mail Readed Mark
* 'Mail read' Mark
*------------------------------------------*/
int mapif_parse_Mail_read(int fd)
static void mapif_parse_Mail_read(int fd)
{
int mail_id;
RFIFOHEAD(fd);
mail_id = RFIFOL(fd,2);
int mail_id = RFIFOL(fd,2);
if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `read_flag` = '2' WHERE `id` = '%d'", mail_db, mail_id) )
Sql_ShowDebug(sql_handle);
return 0;
}
/*==========================================
* Client Attachment Request
*------------------------------------------*/
int mail_DeleteAttach(int mail_id)
static bool mail_DeleteAttach(int mail_id)
{
StringBuf buf;
int i;
@ -261,86 +253,74 @@ int mail_DeleteAttach(int mail_id)
Sql_ShowDebug(sql_handle);
StringBuf_Destroy(&buf);
return 0;
return false;
}
StringBuf_Destroy(&buf);
return 1;
return true;
}
int mapif_Mail_getattach(int fd, int char_id, int mail_id)
static void mapif_Mail_getattach(int fd, int char_id, int mail_id)
{
struct mail_message *message = (struct mail_message*)aCalloc(sizeof(struct mail_message), 1);
struct mail_message msg;
if( mail_loadmessage(char_id, mail_id, message, 0) )
{
if( (message->item.nameid < 1 || message->item.amount < 1) && message->zeny < 1 )
{
aFree(message);
return 0; // No Attachment
}
if( !mail_loadmessage(char_id, mail_id, &msg) )
return;
if( mail_DeleteAttach(mail_id) )
{
WFIFOHEAD(fd, sizeof(struct item) + 12);
WFIFOW(fd,0) = 0x384a;
WFIFOW(fd,2) = sizeof(struct item) + 12;
WFIFOL(fd,4) = char_id;
WFIFOL(fd,8) = (message->zeny > 0)?message->zeny:0;
memcpy(WFIFOP(fd,12), &message->item, sizeof(struct item));
WFIFOSET(fd,WFIFOW(fd,2));
}
}
if( (msg.item.nameid < 1 || msg.item.amount < 1) && msg.zeny < 1 )
return; // No Attachment
aFree(message);
return 0;
if( !mail_DeleteAttach(mail_id) )
return;
WFIFOHEAD(fd, sizeof(struct item) + 12);
WFIFOW(fd,0) = 0x384a;
WFIFOW(fd,2) = sizeof(struct item) + 12;
WFIFOL(fd,4) = char_id;
WFIFOL(fd,8) = (msg.zeny > 0)?msg.zeny:0;
memcpy(WFIFOP(fd,12), &msg.item, sizeof(struct item));
WFIFOSET(fd,WFIFOW(fd,2));
}
int mapif_parse_Mail_getattach(int fd)
static void mapif_parse_Mail_getattach(int fd)
{
RFIFOHEAD(fd);
mapif_Mail_getattach(fd, RFIFOL(fd,2), RFIFOL(fd,6));
return 0;
}
/*==========================================
* Delete Mail
*------------------------------------------*/
int mapif_Mail_delete(int fd, int char_id, int mail_id)
static void mapif_Mail_delete(int fd, int char_id, int mail_id)
{
short flag = 0;
bool failed = false;
if ( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `id` = '%d'", mail_db, mail_id) )
{
Sql_ShowDebug(sql_handle);
flag = 1;
failed = true;
}
WFIFOHEAD(fd,11);
WFIFOW(fd,0) = 0x384b;
WFIFOL(fd,2) = char_id;
WFIFOL(fd,6) = mail_id;
WFIFOW(fd,10) = flag;
WFIFOSET(fd,12);
return 0;
WFIFOB(fd,10) = failed;
WFIFOSET(fd,11);
}
int mapif_parse_Mail_delete(int fd)
static void mapif_parse_Mail_delete(int fd)
{
RFIFOHEAD(fd);
mapif_Mail_delete(fd, RFIFOL(fd,2), RFIFOL(fd,6));
return 0;
}
/*==========================================
* Return Mail
*------------------------------------------*/
int mapif_Mail_return(int fd, int char_id, int mail_id)
static void mapif_Mail_return(int fd, int char_id, int mail_id)
{
struct mail_message *msg = (struct mail_message*)aCalloc(sizeof(struct mail_message), 1);
struct mail_message msg;
int new_mail = 0;
if( mail_loadmessage(char_id, mail_id, msg, 0) )
if( mail_loadmessage(char_id, mail_id, &msg) )
{
if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `id` = '%d'", mail_db, mail_id) )
Sql_ShowDebug(sql_handle);
@ -348,97 +328,88 @@ int mapif_Mail_return(int fd, int char_id, int mail_id)
{
char temp_[MAIL_TITLE_LENGTH];
swap(msg->send_id, msg->dest_id);
safestrncpy(temp_, msg->send_name, NAME_LENGTH);
safestrncpy(msg->send_name, msg->dest_name, NAME_LENGTH);
safestrncpy(msg->dest_name, temp_, NAME_LENGTH);
// swap sender and receiver
swap(msg.send_id, msg.dest_id);
safestrncpy(temp_, msg.send_name, NAME_LENGTH);
safestrncpy(msg.send_name, msg.dest_name, NAME_LENGTH);
safestrncpy(msg.dest_name, temp_, NAME_LENGTH);
snprintf(temp_, MAIL_TITLE_LENGTH, "RE:%s", msg->title);
safestrncpy(msg->title, temp_, MAIL_TITLE_LENGTH);
msg->timestamp = (unsigned int)calc_times();
// set reply message title
snprintf(temp_, MAIL_TITLE_LENGTH, "RE:%s", msg.title);
safestrncpy(msg.title, temp_, MAIL_TITLE_LENGTH);
new_mail = mail_savemessage(msg);
msg.timestamp = (unsigned int)calc_times();
new_mail = mail_savemessage(&msg);
}
}
aFree(msg);
WFIFOHEAD(fd,14);
WFIFOW(fd,0) = 0x384c;
WFIFOL(fd,2) = char_id;
WFIFOL(fd,6) = mail_id;
WFIFOL(fd,10) = new_mail;
WFIFOSET(fd,14);
return 0;
}
int mapif_parse_Mail_return(int fd)
static void mapif_parse_Mail_return(int fd)
{
RFIFOHEAD(fd);
mapif_Mail_return(fd, RFIFOL(fd,2), RFIFOL(fd,6));
return 0;
}
int mapif_Mail_send(int fd, struct mail_message *msg)
static void mapif_Mail_send(int fd, struct mail_message* msg)
{
int len = strlen(msg->title) + 16;
int len = strlen(msg->title);
WFIFOHEAD(fd,len);
WFIFOW(fd,0) = 0x384d;
WFIFOW(fd,2) = len;
WFIFOW(fd,2) = len + 16;
WFIFOL(fd,4) = msg->send_id;
WFIFOL(fd,8) = msg->id;
WFIFOL(fd,12) = msg->dest_id;
memcpy(WFIFOP(fd,16), msg->title, strlen(msg->title));
WFIFOSET(fd,len);
return 0;
safestrncpy((char*)WFIFOP(fd,16), msg->title, len);
WFIFOSET(fd,WFIFOW(fd,2));
}
int mapif_parse_Mail_send(int fd)
static void mapif_parse_Mail_send(int fd)
{
struct mail_message *msg;
struct mail_message msg;
int mail_id = 0, account_id = 0;
if(RFIFOW(fd,2) != 8 + sizeof(struct mail_message))
return 0;
return;
msg = (struct mail_message*)aCalloc(sizeof(struct mail_message), 1);
memcpy(msg, RFIFOP(fd,8), sizeof(struct mail_message));
memcpy(&msg, RFIFOP(fd,8), sizeof(struct mail_message));
account_id = RFIFOL(fd,4);
if( !msg->dest_id )
if( !msg.dest_id )
{
// Try to find the Dest Char by Name
char esc_name[NAME_LENGTH*2+1];
Sql_EscapeStringLen(sql_handle, esc_name, msg->dest_name, strnlen(msg->dest_name, NAME_LENGTH));
Sql_EscapeStringLen(sql_handle, esc_name, msg.dest_name, strnlen(msg.dest_name, NAME_LENGTH));
if ( SQL_ERROR == Sql_Query(sql_handle, "SELECT `account_id`, `char_id` FROM `%s` WHERE `name` = '%s'", char_db, esc_name) )
Sql_ShowDebug(sql_handle);
else if ( Sql_NumRows(sql_handle) > 0 )
else
if ( SQL_SUCCESS == Sql_NextRow(sql_handle) )
{
char *data;
Sql_NextRow(sql_handle);
Sql_GetData(sql_handle, 0, &data, NULL);
if (atoi(data) != account_id)
{ // Cannot sends mail to char in the same account
{ // Cannot send mail to char in the same account
Sql_GetData(sql_handle, 1, &data, NULL);
msg->dest_id = atoi(data);
msg.dest_id = atoi(data);
}
}
Sql_FreeResult(sql_handle);
}
if( msg->dest_id > 0 )
mail_id = mail_savemessage(msg);
if( msg.dest_id > 0 )
mail_id = mail_savemessage(&msg);
msg->id = mail_id;
mapif_Mail_send(fd, msg);
aFree(msg);
return 0;
msg.id = mail_id;
mapif_Mail_send(fd, &msg);
}
/*==========================================
@ -462,12 +433,10 @@ int inter_mail_parse_frommap(int fd)
int inter_mail_sql_init(void)
{
mail_data_pt = (struct mail_data*)aCalloc(sizeof(struct mail_data), 1);
return 1;
}
void inter_mail_sql_final(void)
{
if (mail_data_pt) aFree(mail_data_pt);
return;
}

View File

@ -1,12 +1,12 @@
// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
// For more information, see LICENCE in the main folder
#ifndef _INT_MAIL_SQL_H_
#define _INT_MAIL_SQL_H_
int inter_mail_parse_frommap(int fd);
int inter_mail_sql_init(void);
void inter_mail_sql_final(void);
#endif /* _INT_MAIL_SQL_H_ */
// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
// For more information, see LICENCE in the main folder
#ifndef _INT_MAIL_SQL_H_
#define _INT_MAIL_SQL_H_
int inter_mail_parse_frommap(int fd);
int inter_mail_sql_init(void);
void inter_mail_sql_final(void);
#endif /* _INT_MAIL_SQL_H_ */

View File

@ -28,7 +28,7 @@
// Whether to use Athena's built-in Memory Manager (enabled by default)
// To disable just comment the following line
#if !defined(DMALLOC) && !defined(BCHECK)
#define USE_MEMMGR
//#define USE_MEMMGR
#endif
// Whether to enable Memory Manager's logging
#define LOG_MEMMGR

View File

@ -132,7 +132,7 @@ struct skill {
struct global_reg {
char str[32];
char value[256]; // [zBuffer]
char value[256];
};
//Holds array of global registries, used by the char server and converter.
@ -247,12 +247,11 @@ struct mail_message {
char send_name[NAME_LENGTH];
int dest_id;
char dest_name[NAME_LENGTH];
char title[MAIL_TITLE_LENGTH];
char body[MAIL_BODY_LENGTH];
unsigned char read;
unsigned int timestamp;
unsigned int timestamp; // marks when the message was sent
int zeny;
struct item item;
@ -261,10 +260,8 @@ struct mail_message {
struct mail_data {
short amount;
bool changed, full;
short unchecked, unread;
struct mail_message msg[MAIL_MAX_INBOX];
short unchecked, unreaded;
};
struct registry {
@ -292,8 +289,6 @@ struct guild_storage {
struct item storage_[MAX_GUILD_STORAGE];
};
struct map_session_data;
struct gm_account {
int account_id;
int level;
@ -319,6 +314,7 @@ struct party {
struct party_member member[MAX_PARTY];
};
struct map_session_data;
struct guild_member {
int account_id, char_id;
short hair,hair_color,gender,class_,lv;

View File

@ -452,7 +452,7 @@ int realloc_writefifo(int fd, size_t addition)
return 0;
// crash prevention for bugs that cause the send queue to fill up in an infinite loop
if( newsize > 1*1024*1024 ) // 1 megabyte is way beyond reasonable
if( newsize > 5*1024*1024 ) // 5 MB is way beyond reasonable
{
ShowError("realloc_writefifo: session #%d's send buffer was overloaded! Disconnecting...\n", fd);
// drop all data (but the space will still be available)

View File

@ -151,15 +151,15 @@ int chat_leavechat(struct map_session_data* sd, bool kicked)
return -1;
}
leavechar = i;
clif_leavechat(cd, sd, kicked);
pc_setchatid(sd, 0);
cd->users--;
leavechar = i;
for( i = leavechar; i < cd->users; i++ )
cd->usersd[i] = cd->usersd[i+1];
pc_setchatid(sd, 0);
cd->users--;
if( cd->users == 0 && cd->owner->type == BL_PC )
{ // Delete empty chatroom

View File

@ -7964,9 +7964,8 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd)
if(map_flag_gvg(sd->bl.m))
clif_set0199(fd,3);
map_foreachinarea(clif_getareachar, sd->bl.m,
sd->bl.x-AREA_SIZE, sd->bl.y-AREA_SIZE, sd->bl.x+AREA_SIZE, sd->bl.y+AREA_SIZE,
BL_ALL, sd);
// info about nearby objects
map_foreachinrange(clif_getareachar, &sd->bl, AREA_SIZE, BL_ALL, sd);
// pet
if(sd->pd) {
@ -11296,11 +11295,12 @@ void clif_parse_AutoRevive(int fd, struct map_session_data *sd)
}
#ifndef TXT_ONLY
/*==========================================
* MAIL SYSTEM
* By Zephyrus
*------------------------------------------
*==========================================*/
/*------------------------------------------
* Opens Mail Window on Client
*------------------------------------------*/
void clif_Mail_openmail(int fd)
@ -11310,6 +11310,7 @@ void clif_Mail_openmail(int fd)
WFIFOL(fd,2) = 0;
WFIFOSET(fd,packet_len(0x260));
}
/*------------------------------------------
* Send Inbox Data to Client
*------------------------------------------*/
@ -11368,7 +11369,12 @@ void clif_Mail_read(struct map_session_data *sd, int mail_id)
int i, fd = sd->fd;
ARR_FIND(0, MAIL_MAX_INBOX, i, sd->mail.inbox.msg[i].id == mail_id);
if (i < MAIL_MAX_INBOX)
if( i == MAIL_MAX_INBOX )
{
ShowWarning("clif_parse_Mail_read: account %d trying to read a message not the inbox.\n", sd->status.account_id);
return;
}
else
{
struct mail_message *msg = &sd->mail.inbox.msg[i];
struct item *item = &msg->item;
@ -11416,8 +11422,7 @@ void clif_Mail_read(struct map_session_data *sd, int mail_id)
WFIFOW(fd,95) = item->card[2];
WFIFOW(fd,97) = item->card[3];
WFIFOB(fd,99) = (unsigned char)msg_len;
memcpy(WFIFOP(fd,100), msg->body, msg_len);
WFIFOB(fd,len - 1) = 0x00;
safestrncpy((char*)WFIFOP(fd,100), msg->body, msg_len);
WFIFOSET(fd,len);
if (!msg->read) {
@ -11426,8 +11431,6 @@ void clif_Mail_read(struct map_session_data *sd, int mail_id)
clif_parse_Mail_refreshinbox(fd, sd);
}
}
else
ShowWarning("clif_parse_Mail_read: account %d trying to read a message not the inbox.\n", sd->status.account_id);
}
void clif_parse_Mail_read(int fd, struct map_session_data *sd)
@ -11445,44 +11448,45 @@ void clif_parse_Mail_getattach(int fd, struct map_session_data *sd)
nullpo_retv(sd);
ARR_FIND(0, MAIL_MAX_INBOX, i, sd->mail.inbox.msg[i].id == mail_id);
if (i < MAIL_MAX_INBOX)
if( i == MAIL_MAX_INBOX )
return;
if( sd->mail.inbox.msg[i].zeny < 1 && (sd->mail.inbox.msg[i].item.nameid < 1 || sd->mail.inbox.msg[i].item.amount < 1) )
return;
if( sd->mail.inbox.msg[i].item.nameid > 0 )
{
if (sd->mail.inbox.msg[i].zeny < 1 && (sd->mail.inbox.msg[i].item.nameid < 1 || sd->mail.inbox.msg[i].item.amount < 1))
struct item_data *data;
unsigned int weight;
if ((data = itemdb_search(sd->mail.inbox.msg[i].item.nameid)) == NULL)
return;
if (sd->mail.inbox.msg[i].item.nameid > 0)
weight = data->weight * sd->mail.inbox.msg[i].item.amount;
if (weight > sd->max_weight - sd->weight)
{
struct item_data *data;
unsigned int weight;
if ((data = itemdb_search(sd->mail.inbox.msg[i].item.nameid)) == NULL)
return;
weight = data->weight * sd->mail.inbox.msg[i].item.amount;
if (weight > sd->max_weight - sd->weight)
{
clif_displaymessage(fd, "Attachment to heavy for you...");
return;
}
clif_displaymessage(fd, "Attachment to heavy for you...");
return;
}
sd->mail.inbox.msg[i].zeny = 0;
memset(&sd->mail.inbox.msg[i].item, 0, sizeof(struct item));
clif_Mail_read(sd, mail_id);
// Send the request for Char Server to delete the attachment
// If it is done, the client will receive it.
intif_Mail_getattach(sd->status.char_id, mail_id);
}
sd->mail.inbox.msg[i].zeny = 0;
memset(&sd->mail.inbox.msg[i].item, 0, sizeof(struct item));
clif_Mail_read(sd, mail_id);
// Send the request for Char Server to delete the attachment
// If it is done, the client will receive it.
intif_Mail_getattach(sd->status.char_id, mail_id);
}
/*------------------------------------------
* Delete Message
*------------------------------------------*/
void clif_Mail_delete(struct map_session_data *sd, int mail_id, short flag)
void clif_Mail_delete(struct map_session_data *sd, int mail_id, bool failed)
{
int fd = sd->fd;
if (!flag)
if( !failed )
{
int i;
ARR_FIND(0, MAIL_MAX_INBOX, i, sd->mail.inbox.msg[i].id == mail_id);
@ -11491,16 +11495,16 @@ void clif_Mail_delete(struct map_session_data *sd, int mail_id, short flag)
memset(&sd->mail.inbox.msg[i], 0, sizeof(struct mail_message));
sd->mail.inbox.amount--;
}
if( sd->mail.inbox.full )
intif_Mail_requestinbox(sd->status.char_id, 1); // Reload the Mail Inbox
}
WFIFOHEAD(fd, packet_len(0x257));
WFIFOW(fd,0) = 0x257;
WFIFOL(fd,2) = mail_id;
WFIFOW(fd,6) = flag;
WFIFOW(fd,6) = failed;
WFIFOSET(fd, packet_len(0x257));
if( !flag && sd->mail.inbox.full )
intif_Mail_requestinbox(sd->status.char_id, 1); // Reload the Mail Inbox
}
void clif_parse_Mail_delete(int fd, struct map_session_data *sd)
@ -11585,7 +11589,8 @@ void clif_Mail_return(struct map_session_data *sd, int mail_id, int new_mail)
*------------------------------------------*/
void clif_parse_Mail_setattach(int fd, struct map_session_data *sd)
{
int idx = RFIFOW(fd,2), amount = RFIFOL(fd,4);
int idx = RFIFOW(fd,2);
int amount = RFIFOL(fd,4);
char flag;
nullpo_retv(sd);
@ -11610,9 +11615,9 @@ void clif_parse_Mail_winopen(int fd, struct map_session_data *sd)
int flag = RFIFOW(fd,2);
nullpo_retv(sd);
if (!flag || flag == 1)
if (flag == 0 || flag == 1)
mail_removeitem(sd, 0);
if (!flag || flag == 2)
if (flag == 0 || flag == 2)
mail_removezeny(sd, 0);
}
@ -11627,10 +11632,11 @@ void clif_Mail_send(int fd, unsigned char flag)
WFIFOSET(fd,packet_len(0x249));
}
/// S 0248 <packet len>.w <nick>.24B <title>.40B <body len>.B <message>.?B
void clif_parse_Mail_send(int fd, struct map_session_data *sd)
{
struct map_session_data *rd;
struct mail_message *msg;
struct mail_message msg;
int body_len;
nullpo_retv(sd);
@ -11659,41 +11665,36 @@ void clif_parse_Mail_send(int fd, struct map_session_data *sd)
if (body_len > MAIL_BODY_LENGTH)
body_len = MAIL_BODY_LENGTH;
msg = (struct mail_message*)aCalloc(sizeof(struct mail_message), 1);
if (mail_getattach(sd, msg))
{
msg->send_id = sd->status.char_id;
safestrncpy(msg->send_name, sd->status.name, NAME_LENGTH);
if (rd) {
msg->dest_id = rd->status.char_id;
safestrncpy(msg->dest_name, rd->status.name, NAME_LENGTH);
} else {
msg->dest_id = 0;
safestrncpy(msg->dest_name, RFIFOP(fd,4), NAME_LENGTH);
}
memcpy(msg->title, RFIFOP(fd,28), MAIL_TITLE_LENGTH);
if (body_len)
memcpy(msg->body, RFIFOP(fd,69), body_len);
else
memset(msg->body, 0x00, MAIL_BODY_LENGTH);
msg->timestamp = (int)mail_calctimes();
intif_Mail_send(sd->status.account_id, msg);
sd->cansendmail_tick = gettick() + 1000; // 5 Seconds flood Protection
}
else
if( !mail_getattach(sd, &msg) )
{
clif_Mail_send(sd->fd, 1); // Fail
mail_removeitem(sd,0);
mail_removezeny(sd,0);
clif_Mail_send(sd->fd, 1); // Fail
return;
}
aFree(msg);
msg.send_id = sd->status.char_id;
safestrncpy(msg.send_name, sd->status.name, NAME_LENGTH);
if (rd) {
msg.dest_id = rd->status.char_id;
safestrncpy(msg.dest_name, rd->status.name, NAME_LENGTH);
} else {
msg.dest_id = 0;
safestrncpy(msg.dest_name, (char*)RFIFOP(fd,4), NAME_LENGTH);
}
safestrncpy(msg.title, (char*)RFIFOP(fd,28), MAIL_TITLE_LENGTH);
if (body_len)
memcpy(msg.body, RFIFOP(fd,69), body_len);
else
memset(msg.body, 0x00, MAIL_BODY_LENGTH);
msg.timestamp = (int)mail_calctimes();
intif_Mail_send(sd->status.account_id, &msg);
sd->cansendmail_tick = gettick() + 1000; // 5 Seconds flood Protection
}
#endif

View File

@ -386,7 +386,7 @@ int do_init_clif(void);
// MAIL SYSTEM
void clif_Mail_openmail(int fd);
void clif_Mail_read(struct map_session_data *sd, int mail_id);
void clif_Mail_delete(struct map_session_data *sd, int mail_id, short flag);
void clif_Mail_delete(struct map_session_data *sd, int mail_id, bool failed);
void clif_Mail_return(struct map_session_data *sd, int mail_id, int new_mail);
void clif_Mail_send(int fd, unsigned char flag);
void clif_Mail_new(int fd, int mail_id, const char *sender, const char *title);

View File

@ -475,21 +475,23 @@ int guild_request_info(int guild_id)
// ƒCƒxƒ“ƒg•t«<E2809A>î•ñ—v<76>
int guild_npc_request_info(int guild_id,const char *event)
{
struct eventlist *ev;
if( guild_search(guild_id) ){
if(event && *event)
if( guild_search(guild_id) )
{
if( event && *event )
npc_event_do(event);
return 0;
}
if(event==NULL || *event==0)
return guild_request_info(guild_id);
if( event && *event )
{
struct eventlist* ev;
ev=(struct eventlist *)aCalloc(sizeof(struct eventlist),1);
memcpy(ev->name,event,strlen(event));
//The one in the db becomes the next event from this.
ev->next=idb_put(guild_infoevent_db,guild_id,ev);
}
ev=(struct eventlist *)aCalloc(sizeof(struct eventlist),1);
memcpy(ev->name,event,strlen(event));
//The one in the db becomes the next event from this.
ev->next=idb_put(guild_infoevent_db,guild_id,ev);
return guild_request_info(guild_id);
}
@ -1723,8 +1725,8 @@ int guild_castledataloadack(int castle_id,int index,int value)
switch(index){
case 1:
gc->guild_id = value;
if (value && guild_search(value)==NULL) //Request guild data which will be required for spawned guardians. [Skotlex]
guild_request_info(value);
if (gc->guild_id && guild_search(gc->guild_id)==NULL) //Request guild data which will be required for spawned guardians. [Skotlex]
guild_request_info(gc->guild_id);
break;
case 2: gc->economy = value; break;
case 3: gc->defense = value; break;
@ -1826,34 +1828,39 @@ int guild_castledatasaveack(int castle_id,int index,int value)
int guild_castlealldataload(int len,struct guild_castle *gc)
{
int i;
int n = (len-4) / sizeof(struct guild_castle), ev = -1;
int n = (len-4) / sizeof(struct guild_castle);
int ev;
nullpo_retr(0, gc);
//Last owned castle in the list invokes ::OnAgitinit
for(i = 0; i < n; i++) {
if ((gc + i)->guild_id)
ev = i;
}
for( i = n-1; i >= 0 && !(gc[i].guild_id); --i );
ev = i; // offset of castle or -1
// 城データ格納とギルド情報要求
for(i = 0; i < n; i++, gc++) {
// load received castles into memory, one by one
for( i = 0; i < n; i++, gc++ )
{
struct guild_castle *c = guild_castle_search(gc->castle_id);
if (!c) {
ShowError("guild_castlealldataload Castle id=%d not found.\n", gc->castle_id);
continue;
}
memcpy(&c->guild_id,&gc->guild_id,
sizeof(struct guild_castle) - ((int)&c->guild_id - (int)c) );
if( c->guild_id ){
if(i!=ev)
// update mapserver castle data with new info
memcpy(&c->guild_id, &gc->guild_id, sizeof(struct guild_castle) - ((int)&c->guild_id - (int)c));
if( c->guild_id )
{
if( i != ev )
guild_request_info(c->guild_id);
else
else // last owned one
guild_npc_request_info(c->guild_id, "::OnAgitInit");
}
}
if (ev == -1) //No castles owned, invoke OnAgitInit as it is.
if( ev < 0 ) //No castles owned, invoke OnAgitInit as it is.
npc_event_doall("OnAgitInit");
return 0;
}

View File

@ -6,6 +6,7 @@
#include "../common/timer.h"
#include "../common/nullpo.h"
#include "../common/malloc.h"
#include "../common/strlib.h"
#include "map.h"
#include "battle.h"
#include "chrif.h"
@ -33,7 +34,7 @@ static const int packet_len_table[]={
-1, 7, 0, 0, 0, 0, 0, 0, -1,11, 0, 0, 0, 0, 0, 0, //0x3810
39,-1,15,15, 14,19, 7,-1, 0, 0, 0, 0, 0, 0, 0, 0, //0x3820
10,-1,15, 0, 79,19, 7,-1, 0,-1,-1,-1, 14,67,186,-1, //0x3830
9, 9,-1,14, 0, 0, 0, 0, -1, 0,-1,12, 14,-1, 0, 0, //0x3840
9, 9,-1,14, 0, 0, 0, 0, -1, 0,-1,11, 14,-1, 0, 0, //0x3840
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,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
@ -259,6 +260,7 @@ int intif_saveregistry(struct map_session_data *sd, int type)
{
struct global_reg *reg;
int count;
int i, p;
if (CheckForCharServer())
return -1;
@ -289,18 +291,13 @@ int intif_saveregistry(struct map_session_data *sd, int type)
WFIFOL(inter_fd,4)=sd->status.account_id;
WFIFOL(inter_fd,8)=sd->status.char_id;
WFIFOB(inter_fd,12)=type;
if(count ==0){
WFIFOW(inter_fd,2)=13;
}else{
int i,p;
for (p=13,i = 0; i < count; i++) {
if (reg[i].str[0] && reg[i].value != 0) {
p+= sprintf((char*)WFIFOP(inter_fd,p), "%s", reg[i].str)+1; //We add 1 to consider the '\0' in place.
p+= sprintf((char*)WFIFOP(inter_fd,p), "%s", reg[i].value)+1;
}
for( p = 13, i = 0; i < count; i++ ) {
if (reg[i].str[0] && reg[i].value != 0) {
p+= sprintf((char*)WFIFOP(inter_fd,p), "%s", reg[i].str)+1; //We add 1 to consider the '\0' in place.
p+= sprintf((char*)WFIFOP(inter_fd,p), "%s", reg[i].value)+1;
}
WFIFOW(inter_fd,2)=p;
}
WFIFOW(inter_fd,2)=p;
WFIFOSET(inter_fd,WFIFOW(inter_fd,2));
return 0;
}
@ -853,8 +850,7 @@ int intif_parse_WisMessage(int fd)
id=RFIFOL(fd,4);
memcpy(name, RFIFOP(fd,32), NAME_LENGTH);
name[NAME_LENGTH-1] = '\0'; //In case name arrived without it's terminator. [Skotlex]
safestrncpy(name, (char*)RFIFOP(fd,32), NAME_LENGTH);
sd = map_nick2sd(name);
if(sd == NULL || strcmp(sd->status.name, name) != 0)
{ //Not found
@ -923,10 +919,8 @@ int mapif_parse_WisToGM(int fd)
message = (char *) (mes_len >= 255 ? (char *) aMallocA(mes_len) : mbuf);
min_gm_level = (int)RFIFOW(fd,28);
memcpy(Wisp_name, RFIFOP(fd,4), NAME_LENGTH);
Wisp_name[NAME_LENGTH-1] = '\0';
memcpy(message, RFIFOP(fd,30), mes_len);
message[mes_len-1] = '\0';
safestrncpy(Wisp_name, (char*)RFIFOP(fd,4), NAME_LENGTH);
safestrncpy(message, (char*)RFIFOP(fd,30), mes_len);
// information is sended to all online GM
clif_foreachclient(mapif_parse_WisToGM_sub, min_gm_level, Wisp_name, message, mes_len);
@ -1216,70 +1210,59 @@ int intif_parse_GuildBroken(int fd)
return 0;
}
// ギルド基本情報変更通知
// basic guild info change notice
// 0x3839 <packet len>.w <guild id>.l <type>.w <data>.?b
int intif_parse_GuildBasicInfoChanged(int fd)
{
int type, guild_id;
unsigned int dd;
void *data;
struct guild *g;
short dw;
type=RFIFOW(fd,8);
guild_id=RFIFOL(fd,4);
data=RFIFOP(fd,10);
g=guild_search(guild_id);
dw=*((short *)data);
dd=*((unsigned int *)data);
if( g==NULL )
//int len = RFIFOW(fd,2) - 10;
int guild_id = RFIFOL(fd,4);
int type = RFIFOW(fd,8);
//void* data = RFIFOP(fd,10);
struct guild* g = guild_search(guild_id);
if( g == NULL )
return 0;
switch(type){
case GBI_EXP: g->exp=dd; break;
case GBI_GUILDLV: g->guild_lv=dw; break;
case GBI_SKILLPOINT: g->skill_point=dd; break;
switch(type) {
case GBI_EXP: g->exp = RFIFOL(fd,10); break;
case GBI_GUILDLV: g->guild_lv = RFIFOW(fd,10); break;
case GBI_SKILLPOINT: g->skill_point = RFIFOL(fd,10); break;
}
return 0;
}
// ギルドメンバ情報変更通知
// guild member info change notice
// 0x383a <packet len>.w <guild id>.l <account id>.l <char id>.l <type>.w <data>.?b
int intif_parse_GuildMemberInfoChanged(int fd)
{
int type, guild_id, account_id, char_id, idx, dd;
void* data;
struct guild *g;
type=RFIFOW(fd,16);
guild_id=RFIFOL(fd,4);
account_id=RFIFOL(fd,8);
char_id=RFIFOL(fd,12);
data=RFIFOP(fd,18);
g=guild_search(guild_id);
dd=*((int *)data);
if( g==NULL )
//int len = RFIFOW(fd,2) - 18;
int guild_id = RFIFOL(fd,4);
int account_id = RFIFOL(fd,8);
int char_id = RFIFOL(fd,12);
int type = RFIFOW(fd,16);
void* data = RFIFOP(fd,18);
int dd = *((int *)data);
struct guild* g;
int idx;
g = guild_search(guild_id);
if( g == NULL )
return 0;
idx=guild_getindex(g,account_id,char_id);
if (idx == -1)
idx = guild_getindex(g,account_id,char_id);
if( idx == -1 )
return 0;
switch(type){
case GMI_POSITION:
g->member[idx].position=dd;
guild_memberposition_changed(g,idx,dd);
break;
case GMI_EXP:
g->member[idx].exp=dd;
break;
case GMI_HAIR:
g->member[idx].hair=dd;
break;
case GMI_HAIR_COLOR:
g->member[idx].hair_color=dd;
break;
case GMI_GENDER:
g->member[idx].gender=dd;
break;
case GMI_CLASS:
g->member[idx].class_=dd;
break;
case GMI_LEVEL:
g->member[idx].lv=dd;
break;
switch( type ) {
case GMI_POSITION: g->member[idx].position = dd; guild_memberposition_changed(g,idx,dd); break;
case GMI_EXP: g->member[idx].exp = dd; break;
case GMI_HAIR: g->member[idx].hair = dd; break;
case GMI_HAIR_COLOR: g->member[idx].hair_color = dd; break;
case GMI_GENDER: g->member[idx].gender = dd; break;
case GMI_CLASS: g->member[idx].class_ = dd; break;
case GMI_LEVEL: g->member[idx].lv = dd; break;
}
return 0;
}
@ -1303,8 +1286,7 @@ int intif_parse_GuildSkillUp(int fd)
// ギルド同盟/敵対通知
int intif_parse_GuildAlliance(int fd)
{
guild_allianceack(RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10),RFIFOL(fd,14),
RFIFOB(fd,18),(char *) RFIFOP(fd,19),(char *) RFIFOP(fd,43));
guild_allianceack(RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10),RFIFOL(fd,14),RFIFOB(fd,18),(char *) RFIFOP(fd,19),(char *) RFIFOP(fd,43));
return 0;
}
// ギルド告知変更通知
@ -1460,15 +1442,16 @@ int intif_parse_DeleteHomunculusOk(int fd)
return 0;
}
#ifndef TXT_ONLY
/*==========================================
* MAIL SYSTEM
* By Zephyrus
*------------------------------------------
*==========================================*/
/*------------------------------------------
* Inbox Request
* flag: 0 Update Inbox | 1 OpenMail
*------------------------------------------*/
#ifndef TXT_ONLY
int intif_Mail_requestinbox(int char_id, unsigned char flag)
{
if (CheckForCharServer())
@ -1488,7 +1471,7 @@ int intif_parse_Mail_inboxreceived(int fd)
struct map_session_data *sd;
unsigned char flag = RFIFOB(fd,8);
sd = map_charid2sd( RFIFOL(fd,4) );
sd = map_charid2sd(RFIFOL(fd,4));
if (sd == NULL)
{
@ -1507,7 +1490,7 @@ int intif_parse_Mail_inboxreceived(int fd)
return 1;
}
memset(&sd->mail.inbox, 0, sizeof(struct mail_data));
//FIXME: this operation is not safe [ultramage]
memcpy(&sd->mail.inbox, RFIFOP(fd,9), sizeof(struct mail_data));
if (flag)
@ -1515,7 +1498,7 @@ int intif_parse_Mail_inboxreceived(int fd)
else
{
char output[128];
sprintf(output, "You have %d new emails (%d unreaded)", sd->mail.inbox.unchecked, sd->mail.inbox.unreaded + sd->mail.inbox.unchecked);
sprintf(output, "You have %d new emails (%d unread)", sd->mail.inbox.unchecked, sd->mail.inbox.unread + sd->mail.inbox.unchecked);
clif_disp_onlyself(sd, output, strlen(output));
}
return 0;
@ -1611,21 +1594,22 @@ int intif_Mail_delete(int char_id, int mail_id)
int intif_parse_Mail_delete(int fd)
{
struct map_session_data *sd = map_charid2sd(RFIFOL(fd,2));
int char_id = RFIFOL(fd,2);
int mail_id = RFIFOL(fd,6);
short flag = RFIFOW(fd,10);
bool failed = RFIFOB(fd,10);
struct map_session_data *sd = map_charid2sd(char_id);
if (sd == NULL)
{
if (battle_config.error_log)
ShowError("intif_parse_Mail_delete: char not found %d\n",RFIFOL(fd,2));
ShowError("intif_parse_Mail_delete: char not found %d\n", char_id);
return 1;
}
if (sd->state.finalsave)
return 1;
clif_Mail_delete(sd, mail_id, flag);
clif_Mail_delete(sd, mail_id, failed);
return 0;
}
/*------------------------------------------

View File

@ -337,19 +337,16 @@ int npc_event_do_clock(int tid, unsigned int tick, int id, int data)
memcpy(&ev_tm_b,t,sizeof(ev_tm_b));
return c;
}
/*==========================================
* OnInitイベント実行(&)
*------------------------------------------*/
int npc_event_do_oninit(void)
void npc_event_do_oninit(void)
{
// int c = npc_event_doall("OnInit");
ShowStatus("Event '"CL_WHITE"OnInit"CL_RESET"' executed with '"
CL_WHITE"%d"CL_RESET"' NPCs.\n",npc_event_doall("OnInit"));
int count = npc_event_doall("OnInit");
ShowStatus("Event '"CL_WHITE"OnInit"CL_RESET"' executed with '"CL_WHITE"%d"CL_RESET"' NPCs."CL_CLL"\n", count);
add_timer_interval(gettick()+100,
npc_event_do_clock,0,0,1000);
return 0;
add_timer_interval(gettick()+100,npc_event_do_clock,0,0,1000);
}
/*==========================================

View File

@ -69,7 +69,7 @@ void npc_delsrcfile(const char* name);
void npc_parsesrcfile(const char* filepath);
int do_final_npc(void);
int do_init_npc(void);
int npc_event_do_oninit(void);
void npc_event_do_oninit(void);
int npc_do_ontimer(int npc_id, int option);
int npc_event_doall(const char* name);

View File

@ -7399,15 +7399,17 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns
int count=0;
int x = bl->x, y = bl->y;
//If target isn't knocked back it should hit every 20ms [Playtester]
while (count++ < SKILLUNITTIMER_INTERVAL/sg->interval && x == bl->x && y == bl->y && !status_isdead(bl)){
if (bl->type==BL_PC)
while( count++ < SKILLUNITTIMER_INTERVAL/sg->interval && x == bl->x && y == bl->y && !status_isdead(bl) )
{
if( bl->type == BL_PC )
status_zap(bl, 0, 15); //Only damage SP [Skotlex]
else if (!status_charge(ss, 0, 2)){ //should end when out of sp.
sg->limit=DIFF_TICK(tick,sg->tick);
else // mobs
if( status_charge(ss, 0, 2) ) // costs 2 SP per hit
skill_attack(BF_WEAPON,ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick+count*20,0);
else { //should end when out of sp.
sg->limit = DIFF_TICK(tick,sg->tick);
break;
}
else
skill_attack(BF_WEAPON,ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick+count*20,0);
}
}
break;
@ -8020,8 +8022,7 @@ int skill_check_pc_partner (struct map_session_data *sd, short skill_id, short*
//Else: new search for partners.
c = 0;
memset (p_sd, 0, sizeof(p_sd));
i = map_foreachinrange(skill_check_condition_char_sub, &sd->bl,
range, BL_PC, &sd->bl, &c, &p_sd, skill_id);
i = map_foreachinrange(skill_check_condition_char_sub, &sd->bl, range, BL_PC, &sd->bl, &c, &p_sd, skill_id);
if (skill_id != PR_BENEDICTIO) //Apply the average lv to encore skills.
*skill_lv = (i+(*skill_lv))/(c+1); //I know c should be one, but this shows how it could be used for the average of n partners.

View File

@ -211,6 +211,14 @@ SOURCE=..\src\char_sql\int_homun.h
# End Source File
# Begin Source File
SOURCE=..\src\char_sql\int_mail.c
# End Source File
# Begin Source File
SOURCE=..\src\char_sql\int_mail.h
# End Source File
# Begin Source File
SOURCE=..\src\char_sql\int_party.c
# End Source File
# Begin Source File

View File

@ -161,6 +161,12 @@
<File
RelativePath="..\src\char_sql\int_homun.h">
</File>
<File
RelativePath="..\src\char_sql\int_mail.c">
</File>
<File
RelativePath="..\src\char_sql\int_mail.h">
</File>
<File
RelativePath="..\src\char_sql\int_party.c">
</File>