diff options
Diffstat (limited to 'src/char')
-rw-r--r-- | src/char/Makefile.in | 9 | ||||
-rw-r--r-- | src/char/char.c | 117 | ||||
-rw-r--r-- | src/char/char.h | 2 | ||||
-rw-r--r-- | src/char/int_storage.c | 78 |
4 files changed, 144 insertions, 62 deletions
diff --git a/src/char/Makefile.in b/src/char/Makefile.in index ab1e7c234..ecaad3602 100644 --- a/src/char/Makefile.in +++ b/src/char/Makefile.in @@ -1,9 +1,12 @@ +# Copyright (c) Hercules Dev Team, licensed under GNU GPL. +# See the LICENSE file CONFIG_D = ../config CONFIG_H = $(wildcard $(CONFIG_D)/*.h) $(wildcard $(CONFIG_D)/*/*.h) COMMON_D = ../common COMMON_H = $(wildcard $(COMMON_D)/*.h) +SYSINFO_INC = $(COMMON_D)/sysinfo.inc LIBCONFIG_D = ../../3rdparty/libconfig LIBCONFIG_OBJ = $(addprefix $(LIBCONFIG_D)/, libconfig.o grammar.o scanctx.o \ @@ -27,7 +30,7 @@ CHAR_H = char.h inter.h int_auction.h int_elemental.h int_guild.h int_homun.h \ HAVE_MYSQL=@HAVE_MYSQL@ ifeq ($(HAVE_MYSQL),yes) - CHAR_SERVER_SQL_DEPENDS=$(CHAR_OBJ) $(COMMON_D)/obj_sql/common_sql.a $(COMMON_D)/obj_all/common.a $(MT19937AR_OBJ) $(LIBCONFIG_OBJ) + CHAR_SERVER_SQL_DEPENDS=$(CHAR_OBJ) $(COMMON_D)/obj_sql/common_sql.a $(COMMON_D)/obj_all/common.a $(MT19937AR_OBJ) $(LIBCONFIG_OBJ) $(SYSINFO_INC) else CHAR_SERVER_SQL_DEPENDS=needs_mysql endif @@ -66,6 +69,10 @@ help: Makefile: Makefile.in @$(MAKE) -C ../.. src/char/Makefile +$(SYSINFO_INC): $(CHAR_C) $(CHAR_H) $(COMMON_H) $(CONFIG_H) $(MT19937AR_H) $(LIBCONFIG_H) + @echo " MAKE $@" + @$(MAKE) -C ../.. sysinfo + needs_mysql: @echo "MySQL not found or disabled by the configure script" @exit 1 diff --git a/src/char/char.c b/src/char/char.c index a4bc9cef9..cf961fd93 100644 --- a/src/char/char.c +++ b/src/char/char.c @@ -2419,71 +2419,82 @@ int parse_fromlogin(int fd) { { unsigned char buf[7]; + int char_id[MAX_CHARS]; + int class_[MAX_CHARS]; + int guild_id[MAX_CHARS]; + int num; + int i; + char* data; + struct auth_node* node; + int acc = RFIFOL(fd,2); int sex = RFIFOB(fd,6); + RFIFOSKIP(fd,7); - if( acc > 0 ) - {// TODO: Is this even possible? - int char_id[MAX_CHARS]; - int class_[MAX_CHARS]; - int guild_id[MAX_CHARS]; - int num; - int i; - char* data; + // This should _never_ happen + if( acc <= 0 ) { + ShowError("Received invalid account id from login server! (aid: %d)\n", acc); + return 0; + } - struct auth_node* node = (struct auth_node*)idb_get(auth_db, acc); - if( node != NULL ) - node->sex = sex; + node = (struct auth_node*)idb_get(auth_db, acc); + if( node != NULL ) + node->sex = sex; - // get characters - if( SQL_ERROR == SQL->Query(sql_handle, "SELECT `char_id`,`class`,`guild_id` FROM `%s` WHERE `account_id` = '%d'", char_db, acc) ) - Sql_ShowDebug(sql_handle); - for( i = 0; i < MAX_CHARS && SQL_SUCCESS == SQL->NextRow(sql_handle); ++i ) + // get characters + if( SQL_ERROR == SQL->Query(sql_handle, "SELECT `char_id`,`class`,`guild_id` FROM `%s` WHERE `account_id` = '%d'", char_db, acc) ) + Sql_ShowDebug(sql_handle); + for( i = 0; i < MAX_CHARS && SQL_SUCCESS == SQL->NextRow(sql_handle); ++i ) + { + SQL->GetData(sql_handle, 0, &data, NULL); char_id[i] = atoi(data); + SQL->GetData(sql_handle, 1, &data, NULL); class_[i] = atoi(data); + SQL->GetData(sql_handle, 2, &data, NULL); guild_id[i] = atoi(data); + } + num = i; + for( i = 0; i < num; ++i ) + { + if( class_[i] == JOB_BARD || class_[i] == JOB_DANCER || + class_[i] == JOB_CLOWN || class_[i] == JOB_GYPSY || + class_[i] == JOB_BABY_BARD || class_[i] == JOB_BABY_DANCER || + class_[i] == JOB_MINSTREL || class_[i] == JOB_WANDERER || + class_[i] == JOB_MINSTREL_T || class_[i] == JOB_WANDERER_T || + class_[i] == JOB_BABY_MINSTREL || class_[i] == JOB_BABY_WANDERER || + class_[i] == JOB_KAGEROU || class_[i] == JOB_OBORO ) { - SQL->GetData(sql_handle, 0, &data, NULL); char_id[i] = atoi(data); - SQL->GetData(sql_handle, 1, &data, NULL); class_[i] = atoi(data); - SQL->GetData(sql_handle, 2, &data, NULL); guild_id[i] = atoi(data); + // job modification + if( class_[i] == JOB_BARD || class_[i] == JOB_DANCER ) + class_[i] = (sex ? JOB_BARD : JOB_DANCER); + else if( class_[i] == JOB_CLOWN || class_[i] == JOB_GYPSY ) + class_[i] = (sex ? JOB_CLOWN : JOB_GYPSY); + else if( class_[i] == JOB_BABY_BARD || class_[i] == JOB_BABY_DANCER ) + class_[i] = (sex ? JOB_BABY_BARD : JOB_BABY_DANCER); + else if( class_[i] == JOB_MINSTREL || class_[i] == JOB_WANDERER ) + class_[i] = (sex ? JOB_MINSTREL : JOB_WANDERER); + else if( class_[i] == JOB_MINSTREL_T || class_[i] == JOB_WANDERER_T ) + class_[i] = (sex ? JOB_MINSTREL_T : JOB_WANDERER_T); + else if( class_[i] == JOB_BABY_MINSTREL || class_[i] == JOB_BABY_WANDERER ) + class_[i] = (sex ? JOB_BABY_MINSTREL : JOB_BABY_WANDERER); + else if( class_[i] == JOB_KAGEROU || class_[i] == JOB_OBORO ) + class_[i] = (sex ? JOB_KAGEROU : JOB_OBORO); } - num = i; - for( i = 0; i < num; ++i ) - { - if( class_[i] == JOB_BARD || class_[i] == JOB_DANCER || - class_[i] == JOB_CLOWN || class_[i] == JOB_GYPSY || - class_[i] == JOB_BABY_BARD || class_[i] == JOB_BABY_DANCER || - class_[i] == JOB_MINSTREL || class_[i] == JOB_WANDERER || - class_[i] == JOB_MINSTREL_T || class_[i] == JOB_WANDERER_T || - class_[i] == JOB_BABY_MINSTREL || class_[i] == JOB_BABY_WANDERER || - class_[i] == JOB_KAGEROU || class_[i] == JOB_OBORO ) - { - // job modification - if( class_[i] == JOB_BARD || class_[i] == JOB_DANCER ) - class_[i] = (sex ? JOB_BARD : JOB_DANCER); - else if( class_[i] == JOB_CLOWN || class_[i] == JOB_GYPSY ) - class_[i] = (sex ? JOB_CLOWN : JOB_GYPSY); - else if( class_[i] == JOB_BABY_BARD || class_[i] == JOB_BABY_DANCER ) - class_[i] = (sex ? JOB_BABY_BARD : JOB_BABY_DANCER); - else if( class_[i] == JOB_MINSTREL || class_[i] == JOB_WANDERER ) - class_[i] = (sex ? JOB_MINSTREL : JOB_WANDERER); - else if( class_[i] == JOB_MINSTREL_T || class_[i] == JOB_WANDERER_T ) - class_[i] = (sex ? JOB_MINSTREL_T : JOB_WANDERER_T); - else if( class_[i] == JOB_BABY_MINSTREL || class_[i] == JOB_BABY_WANDERER ) - class_[i] = (sex ? JOB_BABY_MINSTREL : JOB_BABY_WANDERER); - else if( class_[i] == JOB_KAGEROU || class_[i] == JOB_OBORO ) - class_[i] = (sex ? JOB_KAGEROU : JOB_OBORO); - } - if( SQL_ERROR == SQL->Query(sql_handle, "UPDATE `%s` SET `class`='%d', `weapon`='0', `shield`='0', `head_top`='0', `head_mid`='0', `head_bottom`='0' WHERE `char_id`='%d'", char_db, class_[i], char_id[i]) ) - Sql_ShowDebug(sql_handle); + if( SQL_ERROR == SQL->Query(sql_handle, "UPDATE `%s` SET `equip`='0' WHERE `char_id`='%d'", inventory_db, char_id[i]) ) + Sql_ShowDebug(sql_handle); - if( guild_id[i] )// If there is a guild, update the guild_member data [Skotlex] - inter_guild_sex_changed(guild_id[i], acc, char_id[i], sex); - } - SQL->FreeResult(sql_handle); + if( SQL_ERROR == SQL->Query(sql_handle, + "UPDATE `%s` SET `class`='%d', `weapon`='0', `shield`='0', `head_top`='0', `head_mid`='0', " + "`head_bottom`='0' WHERE `char_id`='%d'", + char_db, class_[i], char_id[i]) ) + Sql_ShowDebug(sql_handle); - // disconnect player if online on char-server - disconnect_player(acc); + if( guild_id[i] )// If there is a guild, update the guild_member data [Skotlex] + inter_guild_sex_changed(guild_id[i], acc, char_id[i], sex); } + SQL->FreeResult(sql_handle); + + // disconnect player if online on char-server + disconnect_player(acc); // notify all mapservers about this change WBUFW(buf,0) = 0x2b0d; diff --git a/src/char/char.h b/src/char/char.h index 372af91f7..2928929de 100644 --- a/src/char/char.h +++ b/src/char/char.h @@ -65,6 +65,8 @@ int mapif_sendallwos(int fd,unsigned char *buf,unsigned int len); int mapif_send(int fd,unsigned char *buf,unsigned int len); void mapif_on_parse_accinfo(int account_id,int u_fd, int aid, int castergroup, int map_fd); +void disconnect_player(int account_id); + int char_married(int pl1,int pl2); int char_child(int parent_id, int child_id); int char_family(int pl1,int pl2,int pl3); diff --git a/src/char/int_storage.c b/src/char/int_storage.c index 0313f2a41..966e61bb3 100644 --- a/src/char/int_storage.c +++ b/src/char/int_storage.c @@ -258,8 +258,9 @@ int mapif_parse_ItemBoundRetrieve_sub(int fd) StringBuf buf; SqlStmt* stmt; struct item item; - int j, i=0, s; + int j, i=0, s=0, bound_qt=0; struct item items[MAX_INVENTORY]; + unsigned int bound_item[MAX_INVENTORY] = {0}; int char_id = RFIFOL(fd,2); int aid = RFIFOL(fd,6); int guild_id = RFIFOW(fd,10); @@ -313,6 +314,20 @@ int mapif_parse_ItemBoundRetrieve_sub(int fd) StrBuf->AppendStr(&buf, " OR"); StrBuf->Printf(&buf, " `id`=%d",items[j].id); + + if( items[j].bound && items[j].equip ) { + // Only the items that are also stored in `char` `equip` + if( items[j].equip&EQP_HAND_R + || items[j].equip&EQP_HAND_L + || items[j].equip&EQP_HEAD_TOP + || items[j].equip&EQP_HEAD_MID + || items[j].equip&EQP_HEAD_LOW + || items[j].equip&EQP_GARMENT + ) { + bound_item[bound_qt] = items[j].equip; + bound_qt++; + } + } } if( SQL_ERROR == SQL->StmtPrepareStr(stmt, StrBuf->Value(&buf)) @@ -324,19 +339,63 @@ int mapif_parse_ItemBoundRetrieve_sub(int fd) return 1; } + // Removes any view id that was set by an item that was removed + if( bound_qt ) { + +#define CHECK_REMOVE(var,mask,token) do { /* Verifies equip bitmasks (see item.equip) and handles the sql statement */ \ + if ((var)&(mask)) { \ + if ((var) != (mask) && s) StrBuf->AppendStr(&buf, ","); \ + StrBuf->AppendStr(&buf,"`"#token"`='0'"); \ + (var) &= ~(mask); \ + s++; \ + } \ +} while(0) + + StrBuf->Clear(&buf); + StrBuf->Printf(&buf, "UPDATE `%s` SET ", char_db); + for( j = 0; j < bound_qt; j++ ) { + // Equips can be at more than one slot at the same time + CHECK_REMOVE(bound_item[j],EQP_HAND_R,weapon); + CHECK_REMOVE(bound_item[j],EQP_HAND_L,shield); + CHECK_REMOVE(bound_item[j],EQP_HEAD_TOP,head_top); + CHECK_REMOVE(bound_item[j],EQP_HEAD_MID,head_mid); + CHECK_REMOVE(bound_item[j],EQP_HEAD_LOW,head_bottom); + CHECK_REMOVE(bound_item[j],EQP_GARMENT,robe); + } + StrBuf->Printf(&buf, " WHERE `char_id`='%d'", char_id); + + if( SQL_ERROR == SQL->StmtPrepareStr(stmt, StrBuf->Value(&buf)) + || SQL_ERROR == SQL->StmtExecute(stmt) ) + { + Sql_ShowDebug(sql_handle); + SQL->StmtFree(stmt); + StrBuf->Destroy(&buf); + return 1; + } +#undef CHECK_REMOVE + } + //Now let's update the guild storage with those deleted items + /// TODO/FIXME: + /// This approach is basically the same as the one from memitemdata_to_sql, but + /// the latter compares current database values and this is not needed in this case + /// maybe sometime separate memitemdata_to_sql into different methods in order to use + /// call that function here as well [Panikon] StrBuf->Clear(&buf); - StrBuf->Printf(&buf, "INSERT INTO `%s` (`guild_id`, `nameid`, `amount`, `identify`, `refine`, `attribute`, `expire_time`, `bound`, `unique_id`", guild_storage_db); - for( j = 0; j < MAX_SLOTS; ++j ) - StrBuf->Printf(&buf, ", `card%d`", j); - StrBuf->AppendStr(&buf, ") VALUES "); - + StrBuf->Printf(&buf,"INSERT INTO `%s` (`guild_id`,`nameid`,`amount`,`equip`,`identify`,`refine`," + "`attribute`,`expire_time`,`bound`,`unique_id`", + guild_storage_db); + for( s = 0; s < MAX_SLOTS; ++s ) + StrBuf->Printf(&buf, ", `card%d`", s); + StrBuf->AppendStr(&buf," ) VALUES "); + for( j = 0; j < i; ++j ) { if( j ) StrBuf->AppendStr(&buf, ","); - StrBuf->Printf(&buf, "('%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d'", - guild_id, items[j].nameid, items[j].amount, items[j].identify, items[j].refine, items[j].attribute, items[j].expire_time, items[j].bound, items[j].unique_id); + StrBuf->Printf(&buf, "('%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d'", + guild_id, items[j].nameid, items[j].amount, items[j].equip, items[j].identify, items[j].refine, + items[j].attribute, items[j].expire_time, items[j].bound, items[j].unique_id); for( s = 0; s < MAX_SLOTS; ++s ) StrBuf->Printf(&buf, ", '%d'", items[j].card[s]); StrBuf->AppendStr(&buf, ")"); @@ -356,6 +415,9 @@ int mapif_parse_ItemBoundRetrieve_sub(int fd) //Finally reload storage and tell map we're done mapif_load_guild_storage(fd,aid,guild_id,0); + + // If character is logged in char, disconnect + disconnect_player(aid); #endif return 0; } |