summaryrefslogtreecommitdiff
path: root/src/char
diff options
context:
space:
mode:
Diffstat (limited to 'src/char')
-rw-r--r--src/char/Makefile.in9
-rw-r--r--src/char/char.c117
-rw-r--r--src/char/char.h2
-rw-r--r--src/char/int_storage.c78
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;
}