diff options
Diffstat (limited to 'src/char/char.c')
-rw-r--r-- | src/char/char.c | 117 |
1 files changed, 101 insertions, 16 deletions
diff --git a/src/char/char.c b/src/char/char.c index 0d96d40cb..60ef11397 100644 --- a/src/char/char.c +++ b/src/char/char.c @@ -15,6 +15,7 @@ #include <sys/types.h> #include <time.h> +#include "HPMchar.h" #include "int_elemental.h" #include "int_guild.h" #include "int_homun.h" @@ -750,6 +751,7 @@ int memitemdata_to_sql(const struct item items[], int max, int id, int tableswit return 1; } + memset(&item, 0, sizeof(item)); SQL->StmtBindColumn(stmt, 0, SQLDT_INT, &item.id, 0, NULL, NULL); SQL->StmtBindColumn(stmt, 1, SQLDT_SHORT, &item.nameid, 0, NULL, NULL); SQL->StmtBindColumn(stmt, 2, SQLDT_SHORT, &item.amount, 0, NULL, NULL); @@ -893,6 +895,7 @@ int inventory_to_sql(const struct item items[], int max, int id) { return 1; } + memset(&item, 0, sizeof(item)); SQL->StmtBindColumn(stmt, 0, SQLDT_INT, &item.id, 0, NULL, NULL); SQL->StmtBindColumn(stmt, 1, SQLDT_SHORT, &item.nameid, 0, NULL, NULL); SQL->StmtBindColumn(stmt, 2, SQLDT_SHORT, &item.amount, 0, NULL, NULL); @@ -1009,6 +1012,7 @@ int mmo_chars_fromsql(struct char_session_data* sd, uint8* buf) int j = 0, i; char last_map[MAP_NAME_LENGTH_EXT]; time_t unban_time = 0; + char sex[2]; stmt = SQL->StmtMalloc(sql_handle); if( stmt == NULL ) { @@ -1028,7 +1032,7 @@ int mmo_chars_fromsql(struct char_session_data* sd, uint8* buf) "`str`,`agi`,`vit`,`int`,`dex`,`luk`,`max_hp`,`hp`,`max_sp`,`sp`," "`status_point`,`skill_point`,`option`,`karma`,`manner`,`hair`,`hair_color`," "`clothes_color`,`weapon`,`shield`,`head_top`,`head_mid`,`head_bottom`,`last_map`,`rename`,`delete_date`," - "`robe`,`slotchange`,`unban_time`" + "`robe`,`slotchange`,`unban_time`,`sex`" " FROM `%s` WHERE `account_id`='%d' AND `char_num` < '%d'", char_db, sd->account_id, MAX_CHARS) || SQL_ERROR == SQL->StmtExecute(stmt) || SQL_ERROR == SQL->StmtBindColumn(stmt, 0, SQLDT_INT, &p.char_id, 0, NULL, NULL) @@ -1069,6 +1073,7 @@ int mmo_chars_fromsql(struct char_session_data* sd, uint8* buf) || SQL_ERROR == SQL->StmtBindColumn(stmt, 35, SQLDT_SHORT, &p.robe, 0, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 36, SQLDT_USHORT, &p.slotchange, 0, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 37, SQLDT_LONG, &unban_time, 0, NULL, NULL) + || SQL_ERROR == SQL->StmtBindColumn(stmt, 38, SQLDT_ENUM, &sex, sizeof(sex), NULL, NULL) ) { SqlStmt_ShowDebug(stmt); @@ -1080,6 +1085,18 @@ int mmo_chars_fromsql(struct char_session_data* sd, uint8* buf) p.last_point.map = mapindex->name2id(last_map); sd->found_char[p.slot] = p.char_id; sd->unban_time[p.slot] = unban_time; + switch( sex[0] ) { + case 'M': + p.sex = 1; + break; + case 'F': + p.sex = 0; + break; + case 'U': + default: + p.sex = 99; + break; + } j += mmo_char_tobuf(WBUFP(buf, j), &p); } @@ -1110,6 +1127,7 @@ int mmo_char_fromsql(int char_id, struct mmo_charstatus* p, bool load_everything #endif unsigned int opt; int account_id; + char sex[2]; memset(p, 0, sizeof(struct mmo_charstatus)); @@ -1129,7 +1147,7 @@ int mmo_char_fromsql(int char_id, struct mmo_charstatus* p, bool load_everything "`status_point`,`skill_point`,`option`,`karma`,`manner`,`party_id`,`guild_id`,`pet_id`,`homun_id`,`elemental_id`,`hair`," "`hair_color`,`clothes_color`,`weapon`,`shield`,`head_top`,`head_mid`,`head_bottom`,`last_map`,`last_x`,`last_y`," "`save_map`,`save_x`,`save_y`,`partner_id`,`father`,`mother`,`child`,`fame`,`rename`,`delete_date`,`robe`,`slotchange`," - "`char_opt`,`font`,`uniqueitem_counter`" + "`char_opt`,`font`,`uniqueitem_counter`,`sex`" " FROM `%s` WHERE `char_id`=? LIMIT 1", char_db) || SQL_ERROR == SQL->StmtBindParam(stmt, 0, SQLDT_INT, &char_id, 0) || SQL_ERROR == SQL->StmtExecute(stmt) @@ -1189,6 +1207,7 @@ int mmo_char_fromsql(int char_id, struct mmo_charstatus* p, bool load_everything || SQL_ERROR == SQL->StmtBindColumn(stmt, 53, SQLDT_UINT, &opt, 0, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 54, SQLDT_UCHAR, &p->font, 0, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 55, SQLDT_UINT, &p->uniqueitem_counter, 0, NULL, NULL) + || SQL_ERROR == SQL->StmtBindColumn(stmt, 56, SQLDT_ENUM, &sex, sizeof(sex), NULL, NULL) ) { SqlStmt_ShowDebug(stmt); @@ -1202,6 +1221,19 @@ int mmo_char_fromsql(int char_id, struct mmo_charstatus* p, bool load_everything return 0; } + switch( sex[0] ) { + case 'M': + p->sex = 1; + break; + case 'F': + p->sex = 0; + break; + case 'U': + default: + p->sex = 99; + break; + } + account_id = p->account_id; p->last_point.map = mapindex->name2id(last_map); @@ -1229,6 +1261,7 @@ int mmo_char_fromsql(int char_id, struct mmo_charstatus* p, bool load_everything //read memo data //`memo` (`memo_id`,`char_id`,`map`,`x`,`y`) + memset(&tmp_point, 0, sizeof(tmp_point)); if( SQL_ERROR == SQL->StmtPrepare(stmt, "SELECT `map`,`x`,`y` FROM `%s` WHERE `char_id`=? ORDER by `memo_id` LIMIT %d", memo_db, MAX_MEMOPOINTS) || SQL_ERROR == SQL->StmtBindParam(stmt, 0, SQLDT_INT, &char_id, 0) || SQL_ERROR == SQL->StmtExecute(stmt) @@ -1251,6 +1284,7 @@ int mmo_char_fromsql(int char_id, struct mmo_charstatus* p, bool load_everything StrBuf->Printf(&buf, ", `card%d`", i); StrBuf->Printf(&buf, " FROM `%s` WHERE `char_id`=? LIMIT %d", inventory_db, MAX_INVENTORY); + memset(&tmp_item, 0, sizeof(tmp_item)); if( SQL_ERROR == SQL->StmtPrepareStr(stmt, StrBuf->Value(&buf)) || SQL_ERROR == SQL->StmtBindParam(stmt, 0, SQLDT_INT, &char_id, 0) || SQL_ERROR == SQL->StmtExecute(stmt) @@ -1312,6 +1346,7 @@ int mmo_char_fromsql(int char_id, struct mmo_charstatus* p, bool load_everything //read skill //`skill` (`char_id`, `id`, `lv`) + memset(&tmp_skill, 0, sizeof(tmp_skill)); if( SQL_ERROR == SQL->StmtPrepare(stmt, "SELECT `id`, `lv`,`flag` FROM `%s` WHERE `char_id`=? LIMIT %d", skill_db, MAX_SKILL) || SQL_ERROR == SQL->StmtBindParam(stmt, 0, SQLDT_INT, &char_id, 0) || SQL_ERROR == SQL->StmtExecute(stmt) @@ -1333,6 +1368,7 @@ int mmo_char_fromsql(int char_id, struct mmo_charstatus* p, bool load_everything //read friends //`friends` (`char_id`, `friend_account`, `friend_id`) + memset(&tmp_friend, 0, sizeof(tmp_friend)); if( SQL_ERROR == SQL->StmtPrepare(stmt, "SELECT c.`account_id`, c.`char_id`, c.`name` FROM `%s` c LEFT JOIN `%s` f ON f.`friend_account` = c.`account_id` AND f.`friend_id` = c.`char_id` WHERE f.`char_id`=? LIMIT %d", char_db, friend_db, MAX_FRIENDS) || SQL_ERROR == SQL->StmtBindParam(stmt, 0, SQLDT_INT, &char_id, 0) || SQL_ERROR == SQL->StmtExecute(stmt) @@ -1348,6 +1384,7 @@ int mmo_char_fromsql(int char_id, struct mmo_charstatus* p, bool load_everything #ifdef HOTKEY_SAVING //read hotkeys //`hotkey` (`char_id`, `hotkey`, `type`, `itemskill_id`, `skill_lvl` + memset(&tmp_hotkey, 0, sizeof(tmp_hotkey)); if( SQL_ERROR == SQL->StmtPrepare(stmt, "SELECT `hotkey`, `type`, `itemskill_id`, `skill_lvl` FROM `%s` WHERE `char_id`=?", hotkey_db) || SQL_ERROR == SQL->StmtBindParam(stmt, 0, SQLDT_INT, &char_id, 0) || SQL_ERROR == SQL->StmtExecute(stmt) @@ -1892,7 +1929,7 @@ int count_users(void) // Writes char data to the buffer in the format used by the client. // Used in packets 0x6b (chars info) and 0x6d (new char info) // Returns the size -#define MAX_CHAR_BUF 144 //Max size (for WFIFOHEAD calls) +#define MAX_CHAR_BUF 150 //Max size (for WFIFOHEAD calls) int mmo_char_tobuf(uint8* buffer, struct mmo_charstatus* p) { unsigned short offset = 0; uint8* buf; @@ -1927,9 +1964,16 @@ int mmo_char_tobuf(uint8* buffer, struct mmo_charstatus* p) { WBUFW(buf,52) = p->class_; WBUFW(buf,54) = p->hair; +#if PACKETVER >= 20141022 + //When the weapon is sent and your option is riding, the client crashes on login!? + WBUFL(buf,56) = p->option&(0x20|0x80000|0x100000|0x200000|0x400000|0x800000|0x1000000|0x2000000|0x4000000|0x8000000) ? 0 : p->weapon; + offset+=2; + buf = WBUFP(buffer,offset); +#else //When the weapon is sent and your option is riding, the client crashes on login!? WBUFW(buf,56) = p->option&(0x20|0x80000|0x100000|0x200000|0x400000|0x800000|0x1000000|0x2000000|0x4000000|0x8000000) ? 0 : p->weapon; - +#endif + WBUFW(buf,58) = p->base_level; WBUFW(buf,60) = min(p->skill_point, INT16_MAX); WBUFW(buf,62) = p->head_bottom; @@ -1964,13 +2008,17 @@ int mmo_char_tobuf(uint8* buffer, struct mmo_charstatus* p) { #endif #if PACKETVER != 20111116 //2011-11-16 wants 136, ask gravity. #if PACKETVER >= 20110928 - WBUFL(buf,132) = ( p->slotchange > 0 ) ? 1 : 0; // change slot feature (0 = disabled, otherwise enabled) + WBUFL(buf,132) = ( p->slotchange > 0 ) ? 1 : 0; // change slot feature (0 = disabled, otherwise enabled) offset += 4; #endif #if PACKETVER >= 20111025 WBUFL(buf,136) = ( p->rename > 0 ) ? 1 : 0; // (0 = disabled, otherwise displays "Add-Ons" sidebar) offset += 4; #endif + #if PACKETVER >= 20141016 + WBUFB(buf,140) = p->sex;// sex - (0 = female, 1 = male, 99 = logindefined) + offset += 1; + #endif #endif return 106+offset; @@ -2037,8 +2085,8 @@ void mmo_char_send082d(int fd, struct char_session_data* sd) { WFIFOB(fd,8) = sd->char_slots; memset(WFIFOP(fd,9), 0, 20); // unused bytes WFIFOSET(fd,29); - mmo_char_send006b(fd,sd); + mmo_char_send006b(fd,sd); } //---------------------------------------- // Function to send characters to a player @@ -2239,7 +2287,7 @@ void loginif_on_ready(void) send_accounts_tologin(INVALID_TIMER, timer->gettick(), 0, 0); // if no map-server already connected, display a message... - ARR_FIND( 0, ARRAYLENGTH(server), i, server[i].fd > 0 && server[i].map[0] ); + ARR_FIND( 0, ARRAYLENGTH(server), i, server[i].fd > 0 && server[i].map ); if( i == ARRAYLENGTH(server) ) ShowStatus("Awaiting maps from map-server.\n"); } @@ -3061,6 +3109,7 @@ int parse_frommap(int fd) int count; char* data; + memset(&scdata, 0, sizeof(scdata)); WFIFOHEAD(fd,14+50*sizeof(struct status_change_data)); WFIFOW(fd,0) = 0x2b1d; WFIFOL(fd,4) = aid; @@ -3232,7 +3281,6 @@ int parse_frommap(int fd) { int map_id, map_fd = -1; struct mmo_charstatus* char_data; - struct mmo_charstatus char_dat; map_id = search_mapserver(RFIFOW(fd,18), ntohl(RFIFOL(fd,24)), ntohs(RFIFOW(fd,28))); //Locate mapserver by ip and port. if (map_id >= 0) @@ -3240,6 +3288,7 @@ int parse_frommap(int fd) //Char should just had been saved before this packet, so this should be safe. [Skotlex] char_data = (struct mmo_charstatus*)uidb_get(char_db_,RFIFOL(fd,14)); if (char_data == NULL) { //Really shouldn't happen. + struct mmo_charstatus char_dat; mmo_char_fromsql(RFIFOL(fd,14), &char_dat, true); char_data = (struct mmo_charstatus*)uidb_get(char_db_,RFIFOL(fd,14)); } @@ -3690,11 +3739,12 @@ int parse_frommap(int fd) node != NULL && node->account_id == account_id && node->char_id == char_id && - node->login_id1 == login_id1 && - node->sex == sex /*&& + node->login_id1 == login_id1 /*&& + node->sex == sex && node->ip == ip*/ ) {// auth ok - cd->sex = sex; + if( cd->sex == 99 ) + cd->sex = sex; WFIFOHEAD(fd,25 + sizeof(struct mmo_charstatus)); WFIFOW(fd,0) = 0x2afd; @@ -4279,7 +4329,7 @@ int parse_char(int fd) } #endif - ARR_FIND( 0, ARRAYLENGTH(server), server_id, server[server_id].fd > 0 && server[server_id].map[0] ); + ARR_FIND( 0, ARRAYLENGTH(server), server_id, server[server_id].fd > 0 && server[server_id].map ); /* not available, tell it to wait (client wont close; char select will respawn). * magic response found by Ind thanks to Yommy <3 */ if( server_id == ARRAYLENGTH(server) ) { @@ -4330,7 +4380,8 @@ int parse_char(int fd) //Have to switch over to the DB instance otherwise data won't propagate [Kevin] cd = (struct mmo_charstatus *)idb_get(char_db_, char_id); - cd->sex = sd->sex; + if( cd->sex == 99 ) + cd->sex = sd->sex; if (log_char) { char esc_name[NAME_LENGTH*2+1]; @@ -4350,7 +4401,7 @@ int parse_char(int fd) if (i < 0 || !cd->last_point.map) { unsigned short j; //First check that there's actually a map server online. - ARR_FIND( 0, ARRAYLENGTH(server), j, server[j].fd >= 0 && server[j].map[0] ); + ARR_FIND( 0, ARRAYLENGTH(server), j, server[j].fd >= 0 && server[j].map ); if (j == ARRAYLENGTH(server)) { ShowInfo("Connection Closed. No map servers available.\n"); WFIFOHEAD(fd,3); @@ -4787,6 +4838,12 @@ int parse_char(int fd) RFIFOSKIP(fd,10); break; + case 0x9a1: + FIFOSD_CHECK(2); + mmo_char_send099d(fd, sd); + RFIFOSKIP(fd,2); + break; + /* 0x8d4 <from>.W <to>.W <unused>.W (2+2+2+2) */ case 0x8d4: FIFOSD_CHECK(8); @@ -5367,6 +5424,8 @@ int do_final(void) { char_fd = -1; } + HPM_char_do_final(); + SQL->Free(sql_handle); mapindex->final(); @@ -5374,6 +5433,8 @@ int do_final(void) { if( server[i].map ) aFree(server[i].map); + HPM->event(HPET_POST_FINAL); + ShowStatus("Finished.\n"); return EXIT_SUCCESS; } @@ -5408,6 +5469,9 @@ void do_shutdown(void) } } +void char_hp_symbols(void) { + HPM->share(sql_handle,"sql_handle"); +} int do_init(int argc, char **argv) { int i; @@ -5418,6 +5482,29 @@ int do_init(int argc, char **argv) { mapindex_defaults(); pincode_defaults(); + + HPM_char_do_init(); + HPM->symbol_defaults_sub = char_hp_symbols; +#if 0 + /* TODO: Move to common code */ + for( i = 1; i < argc; i++ ) { + const char* arg = argv[i]; + if( strcmp(arg, "--load-plugin") == 0 ) { + if( map->arg_next_value(arg, i, argc, true) ) { + RECREATE(load_extras, char *, ++load_extras_count); + load_extras[load_extras_count-1] = argv[++i]; + } + } + } + HPM->config_read((const char * const *)load_extras, load_extras_count); + if (load_extras) { + aFree(load_extras); + load_extras = NULL; + load_extras_count = 0; + } +#endif + HPM->config_read(NULL, 0); + HPM->event(HPET_PRE_INIT); //Read map indexes mapindex->init(); @@ -5438,8 +5525,6 @@ int do_init(int argc, char **argv) { auth_db = idb_alloc(DB_OPT_RELEASE_DATA); online_char_db = idb_alloc(DB_OPT_RELEASE_DATA); - HPM->share(sql_handle,"sql_handle"); - HPM->config_read(NULL, 0); HPM->event(HPET_INIT); mmo_char_sql_init(); |