int pet_get_egg(int account_id,int pet_id,int flag) { //This function is invoked when a new pet has been created, and at no other time! struct map_session_data *sd; struct item tmp_item; int i=0,ret=0; if(flag) return 0; sd = map_id2sd(account_id); if(sd == NULL) return 0; i = search_petDB_index(sd->catch_target_class,PET_CLASS); sd->catch_target_class = -1; if(i < 0) { intif_delete_petdata(pet_id); return 0; } memset(&tmp_item,0,sizeof(tmp_item)); tmp_item.nameid = pet_db[i].EggID; tmp_item.identify = 1; tmp_item.card[0] = CARD0_PET; tmp_item.card[1] = GetWord(pet_id,0); tmp_item.card[2] = GetWord(pet_id,1); tmp_item.card[3] = 0; //New pets are not named. if((ret = pc_additem(sd,&tmp_item,1,LOG_TYPE_PICKDROP_PLAYER))) { clif_additem(sd,0,0,ret); map_addflooritem(&tmp_item,1,sd->bl.m,sd->bl.x,sd->bl.y,0,0,0,0); } return 1; }
/** * Begin the actual catching process of a monster. * @param sd : player requesting * @param target_id : monster ID of pet to catch * @return 0:success, 1:failure */ int pet_catch_process2(struct map_session_data* sd, int target_id) { struct mob_data* md; int i = 0, pet_catch_rate = 0; nullpo_retr(1, sd); md = (struct mob_data*)map_id2bl(target_id); if(!md || md->bl.type != BL_MOB || md->bl.prev == NULL) { // Invalid inputs/state, abort capture. clif_pet_roulette(sd,0); sd->catch_target_class = -1; sd->itemid = sd->itemindex = -1; return 1; } //FIXME: delete taming item here, if this was an item-invoked capture and the item was flagged as delay-consume [ultramage] i = search_petDB_index(md->mob_id,PET_CLASS); //catch_target_class == 0 is used for universal lures (except bosses for now). [Skotlex] if (sd->catch_target_class == 0 && !status_has_mode(&md->status,MD_STATUS_IMMUNE)) sd->catch_target_class = md->mob_id; if(i < 0 || sd->catch_target_class != md->mob_id) { clif_emotion(&md->bl, E_AG); //mob will do /ag if wrong lure is used on them. clif_pet_roulette(sd,0); sd->catch_target_class = -1; return 1; } pet_catch_rate = (pet_db[i].capture + (sd->status.base_level - md->level)*30 + sd->battle_status.luk*20)*(200 - get_percentage(md->status.hp, md->status.max_hp))/100; if(pet_catch_rate < 1) pet_catch_rate = 1; if(battle_config.pet_catch_rate != 100) pet_catch_rate = (pet_catch_rate*battle_config.pet_catch_rate)/100; if(rnd()%10000 < pet_catch_rate) { unit_remove_map(&md->bl,CLR_OUTSIGHT); status_kill(&md->bl); clif_pet_roulette(sd,1); intif_create_pet(sd->status.account_id,sd->status.char_id,pet_db[i].class_,mob_db(pet_db[i].class_)->lv, pet_db[i].EggID,0,pet_db[i].intimate,100,0,1,pet_db[i].jname); } else { clif_pet_roulette(sd,0); sd->catch_target_class = -1; } return 0; }
int pet_create_egg(struct map_session_data *sd, int item_id) { int pet_id = search_petDB_index(item_id, PET_EGG); if (pet_id < 0) return 0; //No pet egg here. sd->catch_target_class = pet_db[pet_id].class_; intif_create_pet(sd->status.account_id, sd->status.char_id, (short)pet_db[pet_id].class_, (short)mob_db(pet_db[pet_id].class_)->lv, (short)pet_db[pet_id].EggID, 0, (short)pet_db[pet_id].intimate, 100, 0, 1, pet_db[pet_id].jname); return 1; }
/** * Is invoked _only_ when a new pet has been created is a product of packet 0x3880 * see mapif_pet_created@int_pet.c for more information. * Handles new pet data from inter-server and prepares item information to add pet egg. * @param account_id : account ID of owner * @param pet_class : class of pet * @param pet_id : pet ID otherwise means failure * @return true : success, false : failure **/ bool pet_get_egg(int account_id, short pet_class, int pet_id ) { struct map_session_data *sd; struct item tmp_item; int i = 0, ret = 0; if( pet_id == 0 || pet_class == 0 ) return false; sd = map_id2sd(account_id); if( sd == NULL ) return false; // i = pet_search_petDB_index(sd->catch_target_class,PET_CLASS); // issue: 8150 // Before this change in cases where more than one pet egg were requested in a short // period of time it wasn't possible to know which kind of egg was being requested after // the first request. [Panikon] i = search_petDB_index(pet_class,PET_CLASS); sd->catch_target_class = -1; if(i < 0) { intif_delete_petdata(pet_id); return false; } memset(&tmp_item,0,sizeof(tmp_item)); tmp_item.nameid = pet_db[i].EggID; tmp_item.identify = 1; tmp_item.card[0] = CARD0_PET; tmp_item.card[1] = GetWord(pet_id,0); tmp_item.card[2] = GetWord(pet_id,1); tmp_item.card[3] = 0; //New pets are not named. if((ret = pc_additem(sd,&tmp_item,1,LOG_TYPE_PICKDROP_PLAYER))) { clif_additem(sd,0,0,ret); map_addflooritem(&tmp_item,1,sd->bl.m,sd->bl.x,sd->bl.y,0,0,0,0,0); } return true; }
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; }
int pet_catch_process2(struct map_session_data *sd,int target_id) { struct mob_data *md; int i=0,pet_catch_rate=0; nullpo_retr(1, sd); md=(struct mob_data*)map_id2bl(target_id); if(!md || md->bl.type != BL_MOB || md->bl.prev == NULL){ //Abort capture. sd->catch_target_class = -1; sd->itemid = sd->itemindex = -1; return 1; } if (sd->menuskill_id != SA_TAMINGMONSTER) { //Exploit? clif_pet_rulet(sd,0); sd->catch_target_class = -1; return 1; } if (sd->menuskill_lv > 0) { //Consume the pet lure [Skotlex] i=pc_search_inventory(sd,sd->menuskill_lv); if (i < 0) { //they tried an exploit? clif_pet_rulet(sd,0); sd->catch_target_class = -1; return 1; } //Delete the item if (sd->itemid == sd->menuskill_lv) sd->itemid = sd->itemindex = -1; sd->menuskill_id = sd->menuskill_lv = 0; pc_delitem(sd,i,1,0); } i = search_petDB_index(md->class_,PET_CLASS); //catch_target_class == 0 is used for universal lures. [Skotlex] //for now universal lures do not include bosses. if (sd->catch_target_class == 0 && !(md->status.mode&MD_BOSS)) sd->catch_target_class = md->class_; if(i < 0 || sd->catch_target_class != md->class_) { clif_emotion(&md->bl, 7); //mob will do /ag if wrong lure is used on them. clif_pet_rulet(sd,0); sd->catch_target_class = -1; return 1; } pet_catch_rate = (pet_db[i].capture + (sd->status.base_level - md->level)*30 + sd->battle_status.luk*20)*(200 - md->status.hp*100/md->status.max_hp)/100; if(pet_catch_rate < 1) pet_catch_rate = 1; if(battle_config.pet_catch_rate != 100) pet_catch_rate = (pet_catch_rate*battle_config.pet_catch_rate)/100; if(rand()%10000 < pet_catch_rate) { unit_remove_map(&md->bl,0); status_kill(&md->bl); clif_pet_rulet(sd,1); // if(battle_config.etc_log) // printf("rulet success %d\n",target_id); intif_create_pet(sd->status.account_id,sd->status.char_id,pet_db[i].class_,mob_db(pet_db[i].class_)->lv, pet_db[i].EggID,0,pet_db[i].intimate,100,0,1,pet_db[i].jname); } else { sd->catch_target_class = -1; clif_pet_rulet(sd,0); } 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 == 0) || sd->pd->msd == 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 incuvate to no and send it back for saving. pet->incuvate = 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->msd = sd; pd->petDB = &pet_db[i]; pd->db = mob_db(pet->class_); memcpy(&pd->pet, pet, sizeof(struct s_pet)); iStatus->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; iMap->addiddb(&pd->bl); status_calc_pet(pd,1); pd->last_thinktime = iTimer->gettick(); pd->state.skillbonus = 0; if( battle_config.pet_status_support ) script->run(pet_db[i].pet_script,0,sd->bl.id,0); if( pd->petDB && pd->petDB->equip_script ) status_calc_pc(sd,0); 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 = iTimer->add_timer(iTimer->gettick() + interval, pet_hungry, sd->bl.id, 0); return 0; }