/*========================================== * Saves character data. * Flag = 1: Character is quitting * Flag = 2: Character is changing map-servers *------------------------------------------*/ int chrif_save(struct map_session_data *sd, int flag) { nullpo_retr(-1, sd); pc_makesavestatus(sd); if (flag && sd->state.active) //Store player data which is quitting. { //FIXME: SC are lost if there's no connection at save-time because of the way its related data is cleared immediately after this function. [Skotlex] if (chrif_isconnected()) chrif_save_scdata(sd); if (!chrif_auth_logout(sd, flag==1?ST_LOGOUT:ST_MAPCHANGE)) ShowError("chrif_save: Falha em configurar personagem %d:%d para sair adequadamente!\n", sd->status.account_id, sd->status.char_id); } if(!chrif_isconnected()) return -1; //Character is saved on reconnect. //For data sync if (sd->state.storage_flag == 2) storage_guild_storagesave(sd->status.account_id, sd->status.guild_id, flag); if (flag) sd->state.storage_flag = 0; //Force close it. //Saving of registry values. if (sd->state.reg_dirty&4) intif_saveregistry(sd, 3); //Save char regs if (sd->state.reg_dirty&2) intif_saveregistry(sd, 2); //Save account regs if (sd->state.reg_dirty&1) intif_saveregistry(sd, 1); //Save account2 regs WFIFOHEAD(char_fd, sizeof(sd->status) + 13); WFIFOW(char_fd,0) = 0x2b01; WFIFOW(char_fd,2) = sizeof(sd->status) + 13; WFIFOL(char_fd,4) = sd->status.account_id; WFIFOL(char_fd,8) = sd->status.char_id; WFIFOB(char_fd,12) = (flag==1)?1:0; //Flag to tell char-server this character is quitting. memcpy(WFIFOP(char_fd,13), &sd->status, sizeof(sd->status)); WFIFOSET(char_fd, WFIFOW(char_fd,2)); if( sd->status.pet_id > 0 && sd->pd ) intif_save_petdata(sd->status.account_id,&sd->pd->pet); if( sd->hd && merc_is_hom_active(sd->hd) ) merc_save(sd->hd); if( sd->md && mercenary_get_lifetime(sd->md) > 0 ) mercenary_save(sd->md); #ifndef TXT_ONLY if( sd->save_quest ) intif_quest_save(sd); #endif return 0; }
/*========================================== * Saves character data. * Flag = 1: Character is quitting * Flag = 2: Character is changing map-servers *------------------------------------------*/ int chrif_save(struct map_session_data *sd, int flag) { nullpo_retr(-1, sd); if (!flag) //The flag check is needed to prevent 'nosave' taking effect when a jailed player logs out. pc_makesavestatus(sd); if (flag && sd->state.active) //Store player data which is quitting. { //FIXME: SC are lost if there's no connection at save-time because of the way its related data is cleared immediately after this function. [Skotlex] if (chrif_isconnected()) chrif_save_scdata(sd); if (!chrif_auth_logout(sd, flag==1?ST_LOGOUT:ST_MAPCHANGE)) ShowError("chrif_save: Failed to set up player %d:%d for proper quitting!\n", sd->status.account_id, sd->status.char_id); } if(!chrif_isconnected()) return -1; //Character is saved on reconnect. //For data sync if (sd->state.storage_flag == 1) storage_storage_save(sd->status.account_id, flag); else if (sd->state.storage_flag == 2) storage_guild_storagesave(sd->status.account_id, sd->status.guild_id, flag); if (flag) sd->state.storage_flag = 0; //Force close it. //Saving of registry values. if (sd->state.reg_dirty&4) intif_saveregistry(sd, 3); //Save char regs if (sd->state.reg_dirty&2) intif_saveregistry(sd, 2); //Save account regs if (sd->state.reg_dirty&1) intif_saveregistry(sd, 1); //Save account2 regs WFIFOHEAD(char_fd, sizeof(sd->status) + 13); WFIFOW(char_fd,0) = 0x2b01; WFIFOW(char_fd,2) = sizeof(sd->status) + 13; WFIFOL(char_fd,4) = sd->status.account_id; WFIFOL(char_fd,8) = sd->status.char_id; WFIFOB(char_fd,12) = (flag==1)?1:0; //Flag to tell char-server this character is quitting. memcpy(WFIFOP(char_fd,13), &sd->status, sizeof(sd->status)); WFIFOSET(char_fd, WFIFOW(char_fd,2)); if(sd->status.pet_id > 0 && sd->pd) intif_save_petdata(sd->status.account_id,&sd->pd->pet); if (sd->hd && merc_is_hom_active(sd->hd)) merc_save(sd->hd); return 0; }
/** * Begin hatching a pet. * @param sd : player requesting * @param pet : pet requesting */ int pet_birth_process(struct map_session_data *sd, struct s_pet *pet) { nullpo_retr(1, sd); Assert((sd->status.pet_id == 0 || sd->pd == 0) || sd->pd->master == sd); if(sd->status.pet_id && pet->incubate == 1) { sd->status.pet_id = 0; return 1; } pet->incubate = 0; pet->account_id = sd->status.account_id; pet->char_id = sd->status.char_id; sd->status.pet_id = pet->pet_id; if(pet_data_init(sd, pet)) { sd->status.pet_id = 0; return 1; } intif_save_petdata(sd->status.account_id,pet); if (save_settings&8) chrif_save(sd,0); //is it REALLY Needed to save the char for hatching a pet? [Skotlex] if(sd->bl.prev != NULL) { if(map_addblock(&sd->pd->bl)) return 1; clif_spawn(&sd->pd->bl); clif_send_petdata(sd,sd->pd, 0,0); clif_send_petdata(sd,sd->pd, 5,battle_config.pet_hair_style); clif_pet_equip_area(sd->pd); clif_send_petstatus(sd); } Assert((sd->status.pet_id == 0 || sd->pd == 0) || sd->pd->master == sd); return 0; }
int pet_birth_process(struct map_session_data *sd, struct s_pet *pet) { char pet_output[1024]; // Declaracion de char para Invocacion Pet's [Tab] nullpo_retr(1, sd); Assert((sd->status.pet_id == 0 || sd->pd == 0) || sd->pd->msd == sd); if(sd->status.pet_id && pet->incuvate == 1) { sd->status.pet_id = 0; return 1; } pet->incuvate = 0; pet->account_id = sd->status.account_id; pet->char_id = sd->status.char_id; sd->status.pet_id = pet->pet_id; if(pet_data_init(sd, pet)) { sd->status.pet_id = 0; return 1; } intif_save_petdata(sd->status.account_id,pet); if (save_settings&8) chrif_save(sd,0); //is it REALLY Needed to save the char for hatching a pet? [Skotlex] if(sd->bl.prev != NULL) { map_addblock(&sd->pd->bl); clif_spawn(&sd->pd->bl); clif_send_petdata(sd,sd->pd, 0,0); clif_send_petdata(sd,sd->pd, 5,battle_config.pet_hair_style); clif_pet_equip_area(sd->pd); clif_send_petstatus(sd); } Assert((sd->status.pet_id == 0 || sd->pd == 0) || sd->pd->msd == sd); clif_misceffect(&sd->pd->bl, 0); // Efecto 1 de nacimiento [Tab] clif_misceffect(&sd->pd->bl, 344); // Efecto 2 de nacimiento [Tab] sprintf(pet_output,"Get Out %s... NOW!",pet->name); // Cuidado aca con el nombre del pet clif_displaymessage(sd->fd, pet_output); // Frase nacimiento [Tab] return 0; }
int pet_data_init(struct map_session_data *sd, struct s_pet *pet) { struct pet_data *pd; int i = 0, interval = 0; nullpo_retr(1,sd); Assert((sd->status.pet_id == 0 || sd->pd == NULL) || sd->pd->master == sd); if(sd->status.account_id != pet->account_id || sd->status.char_id != pet->char_id) { sd->status.pet_id = 0; return 1; } if(sd->status.pet_id != pet->pet_id) { if(sd->status.pet_id) { //Wrong pet?? Set incubate to no and send it back for saving pet->incubate = 1; intif_save_petdata(sd->status.account_id,pet); sd->status.pet_id = 0; return 1; } //The pet_id value was lost? Odd, restore it sd->status.pet_id = pet->pet_id; } i = search_petDB_index(pet->class_,PET_CLASS); if(i < 0) { sd->status.pet_id = 0; return 1; } sd->pd = pd = (struct pet_data *)aCalloc(1,sizeof(struct pet_data)); pd->bl.type = BL_PET; pd->bl.id = npc_get_new_npc_id(); pd->master = sd; pd->petDB = &pet_db[i]; pd->db = mob_db(pet->class_); memcpy(&pd->pet,pet,sizeof(struct s_pet)); status_set_viewdata(&pd->bl,pet->class_); unit_dataset(&pd->bl); pd->ud.dir = sd->ud.dir; pd->bl.m = sd->bl.m; pd->bl.x = sd->bl.x; pd->bl.y = sd->bl.y; unit_calc_pos(&pd->bl,sd->bl.x,sd->bl.y,sd->ud.dir); pd->bl.x = pd->ud.to_x; pd->bl.y = pd->ud.to_y; map_addiddb(&pd->bl); status_calc_pet(pd,SCO_FIRST); pd->last_thinktime = gettick(); pd->state.skillbonus = 0; if(battle_config.pet_status_support) run_script(pet_db[i].pet_script,0,sd->bl.id,0); if(pd->petDB) { if(pd->petDB->pet_friendly_script) status_calc_pc(sd,SCO_NONE); if(battle_config.pet_hungry_delay_rate != 100) interval = pd->petDB->hungry_delay * battle_config.pet_hungry_delay_rate / 100; else interval = pd->petDB->hungry_delay; } if(interval <= 0) interval = 1; pd->pet_hungry_timer = add_timer(gettick() + interval,pet_hungry,sd->bl.id,0); pd->masterteleport_timer = INVALID_TIMER; return 0; }
/*========================================== * PCのquit処理 map.c内分 * * quit処理の主体が違うような気もしてきた *------------------------------------------ */ int map_quit(struct map_session_data *sd) { if(sd->chatID) // チャットから出る chat_leavechat(sd); if(sd->trade_partner) // 取引を中断する trade_tradecancel(sd); if(sd->party_invite>0) // パーティ勧誘を拒否する party_reply_invite(sd,sd->party_invite_account,0); if(sd->guild_invite>0) // ギルド勧誘を拒否する guild_reply_invite(sd,sd->guild_invite,0); if(sd->guild_alliance>0) // ギルド同盟勧誘を拒否する guild_reply_reqalliance(sd,sd->guild_alliance_account,0); party_send_logout(sd); // パーティのログアウトメッセージ送信 guild_send_memberinfoshort(sd,0); // ギルドのログアウトメッセージ送信 pc_cleareventtimer(sd); // イベントタイマを破棄する storage_storage_quit(sd); // 倉庫を開いてるなら保存する skill_castcancel(&sd->bl,0); // 詠唱を中断する skill_status_change_clear(&sd->bl); // ステータス異常を解除する skill_clear_unitgroup(&sd->bl); // スキルユニットグループの削除 skill_cleartimerskill(&sd->bl); pc_stop_walking(sd,0); pc_stopattack(sd); pc_delinvincibletimer(sd); pc_delspiritball(sd,sd->spiritball,1); skill_gangsterparadise(sd,0); pc_calcstatus(sd,4); clif_clearchar_area(&sd->bl,2); if(sd->status.pet_id && sd->pd) { pet_remove_map(sd); if(sd->pet.intimate <= 0) { intif_delete_petdata(sd->status.pet_id); sd->status.pet_id = 0; sd->pd = NULL; sd->petDB = NULL; } else intif_save_petdata(sd->status.account_id,&sd->pet); } if(pc_isdead(sd)) pc_setrestartvalue(sd,2); pc_makesavestatus(sd); chrif_save(sd); storage_storage_save(sd); map_delblock(&sd->bl); numdb_erase(id_db,sd->bl.id); strdb_erase(nick_db,sd->status.name); return 0; }
/*========================================== * Saves character data. * Flag = 1: Character is quitting * Flag = 2: Character is changing map-servers *------------------------------------------*/ int chrif_save(struct map_session_data *sd, int flag) { nullpo_retr(-1, sd); pc_makesavestatus(sd); if (flag && sd->state.active) { //Store player data which is quitting //FIXME: SC are lost if there's no connection at save-time because of the way its related data is cleared immediately after this function. [Skotlex] if ( chrif_isconnected() ) chrif_save_scdata(sd); if ( !chrif_auth_logout(sd,flag == 1 ? ST_LOGOUT : ST_MAPCHANGE) ) ShowError("chrif_save: Failed to set up player %d:%d for proper quitting!\n", sd->status.account_id, sd->status.char_id); } chrif_check(-1); //Character is saved on reconnect. //For data sync if (sd->state.storage_flag == 2) storage_guild_storagesave(sd->status.account_id, sd->status.guild_id, flag); if (flag) sd->state.storage_flag = 0; //Force close it. //Saving of registry values. if (sd->state.reg_dirty&4) intif_saveregistry(sd, 3); //Save char regs if (sd->state.reg_dirty&2) intif_saveregistry(sd, 2); //Save account regs if (sd->state.reg_dirty&1) intif_saveregistry(sd, 1); //Save account2 regs WFIFOHEAD(char_fd, sizeof(sd->status) + 13); WFIFOW(char_fd,0) = 0x2b01; WFIFOW(char_fd,2) = sizeof(sd->status) + 13; WFIFOL(char_fd,4) = sd->status.account_id; WFIFOL(char_fd,8) = sd->status.char_id; WFIFOB(char_fd,12) = (flag==1)?1:0; //Flag to tell char-server this character is quitting. // If the user is on a instance map, we have to fake his current position if( map[sd->bl.m].instance_id ){ struct mmo_charstatus status; // Copy the whole status memcpy( &status, &sd->status, sizeof( struct mmo_charstatus ) ); // Change his current position to his savepoint memcpy( &status.last_point, &status.save_point, sizeof( struct point ) ); // Copy the copied status into the packet memcpy( WFIFOP( char_fd, 13 ), &status, sizeof( struct mmo_charstatus ) ); } else { // Copy the whole status into the packet memcpy( WFIFOP( char_fd, 13 ), &sd->status, sizeof( struct mmo_charstatus ) ); } WFIFOSET(char_fd, WFIFOW(char_fd,2)); if( sd->status.pet_id > 0 && sd->pd ) intif_save_petdata(sd->status.account_id,&sd->pd->pet); if( sd->hd && merc_is_hom_active(sd->hd) ) merc_save(sd->hd); if( sd->md && mercenary_get_lifetime(sd->md) > 0 ) mercenary_save(sd->md); if( sd->ed && elemental_get_lifetime(sd->ed) > 0 ) elemental_save(sd->ed); if( sd->save_quest ) intif_quest_save(sd); return 0; }