/*========================================== * Search Char trough id on char serv *------------------------------------------*/ int chrif_searchcharid(int char_id) { if( !char_id ) return -1; chrif_check(-1); WFIFOHEAD(char_fd,6); WFIFOW(char_fd,0) = 0x2b08; WFIFOL(char_fd,2) = char_id; WFIFOSET(char_fd,6); return 0; }
void mapif_send_quests(int fd, int char_id, struct quest *tmp_questlog, int num_quests) { WFIFOHEAD(fd,num_quests*sizeof(struct quest)+8); WFIFOW(fd,0) = 0x3860; WFIFOW(fd,2) = num_quests*sizeof(struct quest)+8; WFIFOL(fd,4) = char_id; if (num_quests > 0) { nullpo_retv(tmp_questlog); memcpy(WFIFOP(fd,8), tmp_questlog, sizeof(struct quest)*num_quests); } WFIFOSET(fd,num_quests*sizeof(struct quest)+8); }
/*========================================== * Client Inbox Request *------------------------------------------*/ static void mapif_Mail_sendinbox(int fd, int char_id, unsigned char flag) { 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(md) + 9; WFIFOL(fd,4) = char_id; WFIFOB(fd,8) = flag; memcpy(WFIFOP(fd,9),&md,sizeof(md)); WFIFOSET(fd,WFIFOW(fd,2)); }
/** * Packet send to all char-servers, except one. (wos: without our self) * @param fd: fd to send packet too * @param buf: packet to send in form of an array buffer * @param len: size of packet * @return : the number of map-serv the packet was sent to (O|1) */ int chmapif_send(int fd, unsigned char *buf, unsigned int len){ if (fd >= 0) { int i; ARR_FIND( 0, ARRAYLENGTH(map_server), i, fd == map_server[i].fd ); if( i < ARRAYLENGTH(map_server) ) { WFIFOHEAD(fd,len); memcpy(WFIFOP(fd,0), buf, len); WFIFOSET(fd,len); return 1; } } return 0; }
// sends maps to char-server int chrif_sendmap(int fd) { int i; ShowStatus("Sending maps to char server...\n"); // Sending normal maps, not instances WFIFOHEAD(fd, 4 + instance_start * 4); WFIFOW(fd,0) = 0x2afa; for(i = 0; i < instance_start; i++) WFIFOW(fd,4+i*4) = map[i].index; WFIFOW(fd,2) = 4 + i * 4; WFIFOSET(fd,WFIFOW(fd,2)); return 0; }
// connects to char-server (plaintext) int chrif_connect(int fd) { ShowStatus("Logging in to char server...\n", char_fd); WFIFOHEAD(fd,60); WFIFOW(fd,0) = 0x2af8; memcpy(WFIFOP(fd,2), userid, NAME_LENGTH); memcpy(WFIFOP(fd,26), passwd, NAME_LENGTH); WFIFOL(fd,50) = 0; WFIFOL(fd,54) = htonl(clif_getip()); WFIFOW(fd,58) = htons(clif_getport()); WFIFOSET(fd,60); return 0; }
void chrif_update_ip(int fd) { uint32 new_ip; WFIFOHEAD(fd,6); new_ip = host2ip(char_ip_str); if (new_ip && new_ip != char_ip) char_ip = new_ip; //Update char_ip new_ip = clif_refresh_ip(); if (!new_ip) return; //No change WFIFOW(fd,0) = 0x2736; WFIFOL(fd,2) = htonl(new_ip); WFIFOSET(fd,6); }
/*========================================== * Request sc_data from charserver [Skotlex] *------------------------------------------*/ int chrif_scdata_request(int account_id, int char_id) { #ifdef ENABLE_SC_SAVING chrif_check(-1); WFIFOHEAD(char_fd,10); WFIFOW(char_fd,0) = 0x2afc; WFIFOL(char_fd,2) = account_id; WFIFOL(char_fd,6) = char_id; WFIFOSET(char_fd,10); #endif return 0; }
/** * Map-serv requesting to send the list of sc_data the player has saved * @author [Skotlex] * @param fd: wich fd to parse from * @return : 0 not enough data received, 1 success */ int chmapif_parse_askscdata(int fd){ if (RFIFOREST(fd) < 10) return 0; { #ifdef ENABLE_SC_SAVING int aid, cid; aid = RFIFOL(fd,2); cid = RFIFOL(fd,6); if( SQL_ERROR == Sql_Query(sql_handle, "SELECT type, tick, val1, val2, val3, val4 from `%s` WHERE `account_id` = '%d' AND `char_id`='%d'", schema_config.scdata_db, aid, cid) ) { Sql_ShowDebug(sql_handle); return 1; } if( Sql_NumRows(sql_handle) > 0 ) { struct status_change_data scdata; int count; char* data; WFIFOHEAD(fd,14+50*sizeof(struct status_change_data)); WFIFOW(fd,0) = 0x2b1d; WFIFOL(fd,4) = aid; WFIFOL(fd,8) = cid; for( count = 0; count < 50 && SQL_SUCCESS == Sql_NextRow(sql_handle); ++count ) { Sql_GetData(sql_handle, 0, &data, NULL); scdata.type = atoi(data); Sql_GetData(sql_handle, 1, &data, NULL); scdata.tick = atoi(data); Sql_GetData(sql_handle, 2, &data, NULL); scdata.val1 = atoi(data); Sql_GetData(sql_handle, 3, &data, NULL); scdata.val2 = atoi(data); Sql_GetData(sql_handle, 4, &data, NULL); scdata.val3 = atoi(data); Sql_GetData(sql_handle, 5, &data, NULL); scdata.val4 = atoi(data); memcpy(WFIFOP(fd, 14+count*sizeof(struct status_change_data)), &scdata, sizeof(struct status_change_data)); } if (count >= 50) ShowWarning("Too many status changes for %d:%d, some of them were not loaded.\n", aid, cid); if (count > 0) { WFIFOW(fd,2) = 14 + count*sizeof(struct status_change_data); WFIFOW(fd,12) = count; WFIFOSET(fd,WFIFOW(fd,2)); } } Sql_FreeResult(sql_handle); #endif RFIFOSKIP(fd, 10); } return 1; }
// sends maps to char-server int chrif_sendmap(int fd) { int i; ShowStatus("Enviando mapas para o servidor de personagens...\n"); // Sending normal maps, not instances WFIFOHEAD(fd, 4 + instance_start * 4); WFIFOW(fd,0) = 0x2afa; for(i = 0; i < instance_start; i++) WFIFOW(fd,4+i*4) = map[i].index; WFIFOW(fd,2) = 4 + i * 4; WFIFOSET(fd,WFIFOW(fd,2)); return 0; }
/*========================================== * Delete Mail *------------------------------------------*/ static void mapif_Mail_delete(int fd, int char_id, int mail_id) { bool failed = false; if(SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `id` = '%d'", mail_db, mail_id)) { Sql_ShowDebug(sql_handle); failed = true; } WFIFOHEAD(fd,11); WFIFOW(fd,0) = 0x384b; WFIFOL(fd,2) = char_id; WFIFOL(fd,6) = mail_id; WFIFOB(fd,10) = failed; WFIFOSET(fd,11); }
static void mapif_homunculus_loaded(int fd, int account_id, struct s_homunculus *hd) { WFIFOHEAD(fd, sizeof(struct s_homunculus)+9); WFIFOW(fd,0) = 0x3891; WFIFOW(fd,2) = sizeof(struct s_homunculus)+9; WFIFOL(fd,4) = account_id; if(hd != NULL) { WFIFOB(fd,8) = 1; // success memcpy(WFIFOP(fd,9), hd, sizeof(struct s_homunculus)); } else { WFIFOB(fd,8) = 0; // not found. memset(WFIFOP(fd,9), 0, sizeof(struct s_homunculus)); } WFIFOSET(fd, sizeof(struct s_homunculus)+9); }
/*========================================== * Client Inbox Request *------------------------------------------*/ void mapif_Mail_sendinbox(int fd, uint32 char_id, unsigned char flag, enum mail_inbox_type type) { struct mail_data md; mail_fromsql(char_id, &md); //FIXME: dumping the whole structure like this is unsafe [ultramage] WFIFOHEAD(fd, sizeof(md) + 10); WFIFOW(fd,0) = 0x3848; WFIFOW(fd,2) = sizeof(md) + 10; WFIFOL(fd,4) = char_id; WFIFOB(fd,8) = flag; WFIFOB(fd,9) = type; memcpy(WFIFOP(fd,10),&md,sizeof(md)); WFIFOSET(fd,WFIFOW(fd,2)); }
/** * IZ 0x3857 <size>.W <count>.W <guild_id>.W { <item>.?B }.*MAX_INVENTORY * Send the retrieved guild bound items to map-server, store them to guild storage. * By using this method, stackable items will looks how it should be, and overflowed * item's stack won't disturbs the guild storage table and the leftover items (when * storage is full) will be discarded. * @param fd * @param guild_id * @param items[] * @param count * @author [Cydh] */ void mapif_itembound_store2gstorage(int fd, int guild_id, struct item items[], unsigned short count) { int size = 8 + sizeof(struct item) * MAX_INVENTORY, i; WFIFOHEAD(fd, size); WFIFOW(fd, 0) = 0x3857; WFIFOW(fd, 2) = size; WFIFOW(fd, 6) = guild_id; for (i = 0; i < count && i < MAX_INVENTORY; i++) { if (!&items[i]) continue; memcpy(WFIFOP(fd, 8 + (i * sizeof(struct item))), &items[i], sizeof(struct item)); } WFIFOW(fd, 4) = i; WFIFOSET(fd, size); }
/*------------------------------------------ * Check Player *------------------------------------------*/ void mapif_rodex_checkname(int fd, int reqchar_id, int target_char_id, short target_class, int target_level, char *name) { nullpo_retv(name); Assert_retv(reqchar_id > 0); Assert_retv(target_char_id >= 0); WFIFOHEAD(fd, 16 + NAME_LENGTH); WFIFOW(fd, 0) = 0x3898; WFIFOL(fd, 2) = reqchar_id; WFIFOL(fd, 6) = target_char_id; WFIFOW(fd, 10) = target_class; WFIFOL(fd, 12) = target_level; safestrncpy(WFIFOP(fd, 16), name, NAME_LENGTH); WFIFOSET(fd, 16 + NAME_LENGTH); }
void chrif_send_report(char* buf, int len) { #ifndef STATS_OPT_OUT if( char_fd ) { WFIFOHEAD(char_fd,len + 2); WFIFOW(char_fd,0) = 0x3008; memcpy(WFIFOP(char_fd,2), buf, len); WFIFOSET(char_fd,len + 2); flush_fifo(char_fd); /* ensure it's sent now. */ } #endif }
/** * Client requests an md5key for his session: keys will be generated and sent back. * @param fd: file descriptor to parse from (client) * @param sd: client session * @return 1 success */ static int logclif_parse_reqkey(int fd, struct login_session_data *sd){ RFIFOSKIP(fd,2); { memset(sd->md5key, '\0', sizeof(sd->md5key)); sd->md5keylen = (uint16)(12 + rnd() % 4); MD5_Salt(sd->md5keylen, sd->md5key); WFIFOHEAD(fd,4 + sd->md5keylen); WFIFOW(fd,0) = 0x01dc; WFIFOW(fd,2) = 4 + sd->md5keylen; memcpy(WFIFOP(fd,4), sd->md5key, sd->md5keylen); WFIFOSET(fd,WFIFOW(fd,2)); } return 1; }
/** * Transmit account data to char_server * S 2717 aid.W email.40B exp_time.L group_id.B char_slot.B birthdate.11B pincode.5B pincode_change.L * isvip.1B char_vip.1B max_billing.1B (tot 75) * @return -1 : account not found, 1:sucess */ int logchrif_send_accdata(int fd, uint32 aid) { struct mmo_account acc; time_t expiration_time = 0; char email[40] = ""; int group_id = 0; char birthdate[10+1] = ""; char pincode[PINCODE_LENGTH+1]; char isvip = false; uint8 char_slots = MIN_CHARS, char_vip = 0, char_billing = 0; AccountDB* accounts = login_get_accounts_db(); memset(pincode,0,PINCODE_LENGTH+1); if( !accounts->load_num(accounts, &acc, aid) ) return -1; else { safestrncpy(email, acc.email, sizeof(email)); expiration_time = acc.expiration_time; group_id = acc.group_id; safestrncpy(birthdate, acc.birthdate, sizeof(birthdate)); safestrncpy(pincode, acc.pincode, sizeof(pincode)); #ifdef VIP_ENABLE char_vip = login_config.vip_sys.char_increase; if( acc.vip_time > time(NULL) ) { isvip = true; char_slots = login_config.char_per_account + char_vip; } else char_slots = login_config.char_per_account; char_billing = MAX_CHAR_BILLING; //TODO create a config for this #endif } WFIFOHEAD(fd,75); WFIFOW(fd,0) = 0x2717; WFIFOL(fd,2) = aid; safestrncpy(WFIFOCP(fd,6), email, 40); WFIFOL(fd,46) = (uint32)expiration_time; WFIFOB(fd,50) = (unsigned char)group_id; WFIFOB(fd,51) = char_slots; safestrncpy(WFIFOCP(fd,52), birthdate, 10+1); safestrncpy(WFIFOCP(fd,63), pincode, 4+1 ); WFIFOL(fd,68) = (uint32)acc.pincode_change; WFIFOB(fd,72) = isvip; WFIFOB(fd,73) = char_vip; WFIFOB(fd,74) = char_billing; WFIFOSET(fd,75); return 1; }
int chlogif_parse_reqaccdata(int fd, struct char_session_data* sd){ int u_fd; //user fd if (RFIFOREST(fd) < 79) return 0; // find the authenticated session with this account id ARR_FIND( 0, fd_max, u_fd, session[u_fd] && (sd = (struct char_session_data*)session[u_fd]->session_data) && sd->auth && sd->account_id == RFIFOL(fd,2) ); if( u_fd < fd_max ) { int server_id; memcpy(sd->email, RFIFOP(fd,6), 40); sd->expiration_time = (time_t)RFIFOL(fd,46); sd->group_id = RFIFOB(fd,50); sd->char_slots = RFIFOB(fd,51); if( sd->char_slots > MAX_CHARS ) { ShowError("Account '%d' `character_slots` column is higher than supported MAX_CHARS (%d), update MAX_CHARS in mmo.h! capping to MAX_CHARS...\n",sd->account_id,sd->char_slots); sd->char_slots = MAX_CHARS;/* cap to maximum */ } else if ( !sd->char_slots )/* no value aka 0 in sql */ sd->char_slots = MIN_CHARS;/* cap to minimum */ safestrncpy(sd->birthdate, (const char*)RFIFOP(fd,52), sizeof(sd->birthdate)); safestrncpy(sd->pincode, (const char*)RFIFOP(fd,63), sizeof(sd->pincode)); sd->pincode_change = (time_t)RFIFOL(fd,68); sd->bank_vault = RFIFOL(fd,72); sd->isvip = RFIFOB(fd,76); sd->chars_vip = RFIFOB(fd,77); sd->chars_billing = RFIFOB(fd,78); ARR_FIND( 0, ARRAYLENGTH(map_server), server_id, map_server[server_id].fd > 0 && map_server[server_id].map[0] ); // continued from char_auth_ok... if( server_id == ARRAYLENGTH(map_server) || //server not online, bugreport:2359 (charserv_config.max_connect_user == 0 && sd->group_id != charserv_config.gm_allow_group) || ( charserv_config.max_connect_user > 0 && char_count_users() >= charserv_config.max_connect_user && sd->group_id != charserv_config.gm_allow_group ) ) { // refuse connection (over populated) WFIFOHEAD(u_fd,3); WFIFOW(u_fd,0) = 0x6c; WFIFOW(u_fd,2) = 0; WFIFOSET(u_fd,3); } else { // send characters to player chclif_mmo_char_send(u_fd, sd); if(sd->version >= date2version(20110309)){ ShowInfo("Asking to start pincode\n"); chlogif_pincode_start(u_fd,sd); } } } RFIFOSKIP(fd,79); return 1; }
/*========================================== * Return Mail *------------------------------------------*/ void mapif_Mail_return(int fd, uint32 char_id, int mail_id) { struct mail_message msg; int new_mail = 0; if( mail_loadmessage(mail_id, &msg) ) { if( msg.dest_id != char_id) return; else if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `id` = '%d'", schema_config.mail_db, mail_id) || SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `id` = '%d'", schema_config.mail_attachment_db, mail_id) ) Sql_ShowDebug(sql_handle); // If it was not sent by the server, since we do not want to return mails to the server else if( msg.send_id != 0 ) { char temp_[MAIL_TITLE_LENGTH + 3]; // 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); // set reply message title snprintf(temp_, sizeof(temp_), "RE:%s", msg.title); safestrncpy(msg.title, temp_, sizeof(temp_)); msg.status = MAIL_NEW; msg.type = MAIL_INBOX_RETURNED; msg.timestamp = time(NULL); new_mail = mail_savemessage(&msg); mapif_Mail_new(&msg); } } // Only if the request came from a map-server and was not timer triggered for an offline character if( fd <= 0 ){ return; } WFIFOHEAD(fd,11); WFIFOW(fd,0) = 0x384c; WFIFOL(fd,2) = char_id; WFIFOL(fd,6) = mail_id; WFIFOB(fd,10) = (new_mail == 0); WFIFOSET(fd,11); }
/*========================================== * Change Email *------------------------------------------*/ int chrif_changeemail(int id, const char *actual_email, const char *new_email) { if (battle_config.etc_log) ShowInfo("chrif_changeemail: account: %d, actual_email: '%s', new_email: '%s'.\n", id, actual_email, new_email); chrif_check(-1); WFIFOHEAD(char_fd,86); WFIFOW(char_fd,0) = 0x2b0c; WFIFOL(char_fd,2) = id; memcpy(WFIFOP(char_fd,6), actual_email, 40); memcpy(WFIFOP(char_fd,46), new_email, 40); WFIFOSET(char_fd,86); return 0; }
/*========================================== * GMに変化要求 *------------------------------------------*/ int chrif_changegm(int id, const char *pass, int len) { if (battle_config.etc_log) ShowInfo("chrif_changegm: account: %d, password: '******'.\n", id, pass); chrif_check(-1); WFIFOHEAD(char_fd, len + 8); WFIFOW(char_fd,0) = 0x2b0a; WFIFOW(char_fd,2) = len + 8; WFIFOL(char_fd,4) = id; memcpy(WFIFOP(char_fd,8), pass, len); WFIFOSET(char_fd, len + 8); return 0; }
/** * Packet send to all map-servers, except one. (wos: without our self) attach to ourself * @param sfd: fd to discard sending to * @param buf: packet to send in form of an array buffer * @param len: size of packet * @return : the number of map-serv the packet was sent to */ int chmapif_sendallwos(int sfd, unsigned char *buf, unsigned int len){ int i, c; c = 0; for(i = 0; i < ARRAYLENGTH(map_server); i++) { int fd; if ((fd = map_server[i].fd) > 0 && fd != sfd) { WFIFOHEAD(fd,len); memcpy(WFIFOP(fd,0), buf, len); WFIFOSET(fd,len); c++; } } return c; }
//------------------------------------------------------ int mapif_pet_created(int fd, int account_id, struct s_pet *p) { WFIFOHEAD(fd,12); WFIFOW(fd,0) = 0x3880; WFIFOL(fd,2) = account_id; if( p != NULL ) { WFIFOW(fd,6) = p->class_; WFIFOL(fd,8) = p->pet_id; ShowInfo("int_pet: created pet %d - %s\n", p->pet_id, p->name); } else { WFIFOW(fd,6) = 0; WFIFOL(fd,8) = 0; } WFIFOSET(fd,12); return 0; }
/// @param result /// 0 (0x718): An unknown error has occurred. /// 1: none/success /// 2 (0x71c): Due to system settings can not be deleted. /// 3 (0x719): A database error occurred. /// 4 (0x71d): Deleting not yet possible time. /// 5 (0x71e): Date of birth do not match. /// Any (0x718): An unknown error has occurred. /// HC: <082a>.W <char id>.L <Msg:0-5>.L void chclif_char_delete2_accept_ack(int fd, uint32 char_id, uint32 result) { if(result == 1 ){ struct char_session_data* sd; sd = (struct char_session_data*)session[fd]->session_data; if( sd->version >= date2version(20130000) ){ chclif_mmo_char_send(fd, sd); } } WFIFOHEAD(fd,10); WFIFOW(fd,0) = 0x82a; WFIFOL(fd,2) = char_id; WFIFOL(fd,6) = result; WFIFOSET(fd,10); }
int chrif_save_scdata(struct map_session_data *sd) { //parses the sc_data of the player and sends it to the char-server for saving. [Skotlex] #ifdef ENABLE_SC_SAVING int i, count=0; unsigned int tick; struct status_change_data data; struct status_change *sc = &sd->sc; const struct TimerData *timer; chrif_check(-1); tick = gettick(); WFIFOHEAD(char_fd, 14 + SC_MAX*sizeof(struct status_change_data)); WFIFOW(char_fd,0) = 0x2b1c; WFIFOL(char_fd,4) = sd->status.account_id; WFIFOL(char_fd,8) = sd->status.char_id; for (i = 0; i < SC_MAX; i++) { if (!sc->data[i]) continue; if (sc->data[i]->timer != INVALID_TIMER) { timer = get_timer(sc->data[i]->timer); if (timer == NULL || timer->func != status_change_timer || DIFF_TICK(timer->tick,tick) < 0) continue; data.tick = DIFF_TICK(timer->tick,tick); //Duration that is left before ending. } else data.tick = -1; //Infinite duration data.type = i; data.val1 = sc->data[i]->val1; data.val2 = sc->data[i]->val2; data.val3 = sc->data[i]->val3; data.val4 = sc->data[i]->val4; memcpy(WFIFOP(char_fd,14 +count*sizeof(struct status_change_data)), &data, sizeof(struct status_change_data)); count++; } if (count == 0) return 0; //Nothing to save. WFIFOW(char_fd,12) = count; WFIFOW(char_fd,2) = 14 +count*sizeof(struct status_change_data); //Total packet size WFIFOSET(char_fd,WFIFOW(char_fd,2)); #endif return 0; }
/** * Handles the save request from mapserver for a character's questlog. * * Received quests are saved, and an ack is sent back to the map server. * * @see inter_parse_frommap */ int mapif_parse_quest_save(int fd) { int i, j, k, old_n, new_n = (RFIFOW(fd,2)-8)/sizeof(struct quest); int char_id = RFIFOL(fd,4); struct quest *old_qd = NULL, *new_qd = NULL; bool success = true; if (new_n > 0) new_qd = (struct quest*)RFIFOP(fd,8); old_qd = mapif_quests_fromsql(char_id, &old_n); for (i = 0; i < new_n; i++) { ARR_FIND( 0, old_n, j, new_qd[i].quest_id == old_qd[j].quest_id ); if (j < old_n) { // Update existing quests // Only states and counts are changeable. ARR_FIND( 0, MAX_QUEST_OBJECTIVES, k, new_qd[i].count[k] != old_qd[j].count[k] ); if (k != MAX_QUEST_OBJECTIVES || new_qd[i].state != old_qd[j].state) success &= mapif_quest_update(char_id, new_qd[i]); if (j < (--old_n)) { // Compact array memmove(&old_qd[j],&old_qd[j+1],sizeof(struct quest)*(old_n-j)); memset(&old_qd[old_n], 0, sizeof(struct quest)); } } else { // Add new quests success &= mapif_quest_add(char_id, new_qd[i]); } } for (i = 0; i < old_n; i++) // Quests not in new_qd but in old_qd are to be erased. success &= mapif_quest_delete(char_id, old_qd[i].quest_id); if (old_qd) aFree(old_qd); // Send ack WFIFOHEAD(fd,7); WFIFOW(fd,0) = 0x3861; WFIFOL(fd,2) = char_id; WFIFOB(fd,6) = success?1:0; WFIFOSET(fd,7); return 0; }
//------------------------------------------------------ int mapif_pet_created(int fd, int account_id, struct s_pet *p) { WFIFOHEAD(fd, 12); WFIFOW(fd, 0) = 0x3880; WFIFOL(fd, 2) = account_id; if(p!=NULL){ WFIFOW(fd, 6) = p->class_; WFIFOL(fd, 8) = p->pet_id; ShowInfo("Mascote criado! (PETID:%d | Nome:%s)\n", p->pet_id, p->name); }else{ WFIFOB(fd, 6) = 0; WFIFOL(fd, 8) = 0; } WFIFOSET(fd, 12); return 0; }
/** * Timered function to send all account_id connected to login-serv * @param tid : Timer id * @param tick : Scheduled tick * @param id : GID linked to that timered call * @param data : data transmited for delayed function * @return */ int chlogif_send_acc_tologin(int tid, unsigned int tick, int id, intptr_t data) { if ( chlogif_isconnected() ){ DBMap* online_char_db = char_get_onlinedb(); // send account list to login server int users = online_char_db->size(online_char_db); int i = 0; WFIFOHEAD(login_fd,8+users*4); WFIFOW(login_fd,0) = 0x272d; online_char_db->foreach(online_char_db, chlogif_send_acc_tologin_sub, &i, users); WFIFOW(login_fd,2) = 8+ i*4; WFIFOL(login_fd,4) = i; WFIFOSET(login_fd,WFIFOW(login_fd,2)); return 1; } return 0; }
//Request skillcooldown data 0x2b0a int chmapif_parse_req_skillcooldown(int fd){ if (RFIFOREST(fd) < 10) return 0; else { int aid, cid; aid = RFIFOL(fd,2); cid = RFIFOL(fd,6); RFIFOSKIP(fd, 10); if( SQL_ERROR == Sql_Query(sql_handle, "SELECT skill, tick FROM `%s` WHERE `account_id` = '%d' AND `char_id`='%d'", schema_config.skillcooldown_db, aid, cid) ) { Sql_ShowDebug(sql_handle); return 1; } if( Sql_NumRows(sql_handle) > 0 ) { int count; char* data; struct skill_cooldown_data scd; WFIFOHEAD(fd,14 + MAX_SKILLCOOLDOWN * sizeof(struct skill_cooldown_data)); WFIFOW(fd,0) = 0x2b0b; WFIFOL(fd,4) = aid; WFIFOL(fd,8) = cid; for( count = 0; count < MAX_SKILLCOOLDOWN && SQL_SUCCESS == Sql_NextRow(sql_handle); ++count ) { Sql_GetData(sql_handle, 0, &data, NULL); scd.skill_id = atoi(data); Sql_GetData(sql_handle, 1, &data, NULL); scd.tick = atoi(data); memcpy(WFIFOP(fd,14+count*sizeof(struct skill_cooldown_data)), &scd, sizeof(struct skill_cooldown_data)); } if( count >= MAX_SKILLCOOLDOWN ) ShowWarning("Too many skillcooldowns for %d:%d, some of them were not loaded.\n", aid, cid); if( count > 0 ) { WFIFOW(fd,2) = 14 + count * sizeof(struct skill_cooldown_data); WFIFOW(fd,12) = count; WFIFOSET(fd,WFIFOW(fd,2)); //Clear the data once loaded. if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `account_id` = '%d' AND `char_id`='%d'", schema_config.skillcooldown_db, aid, cid) ) Sql_ShowDebug(sql_handle); } } Sql_FreeResult(sql_handle); } return 1; }