//--------------------------------------------------------- int inter_pet_tosql (int pet_id, struct s_pet *p) { //`pet` (`pet_id`, `class`,`name`,`account_id`,`char_id`,`level`,`egg_id`,`equip`,`intimate`,`hungry`,`rename_flag`,`incuvate`) char esc_name[NAME_LENGTH * 2 + 1]; // escaped pet name Sql_EscapeStringLen (sql_handle, esc_name, p->name, strnlen (p->name, NAME_LENGTH)); p->hungry = cap_value (p->hungry, 0, 100); p->intimate = cap_value (p->intimate, 0, 1000); if (pet_id == -1) { // New pet. if (SQL_ERROR == Sql_Query (sql_handle, "INSERT INTO `%s` " "(`class`,`name`,`account_id`,`char_id`,`level`,`egg_id`,`equip`,`intimate`,`hungry`,`rename_flag`,`incuvate`) " "VALUES ('%d', '%s', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d')", pet_db, p->class_, esc_name, p->account_id, p->char_id, p->level, p->egg_id, p->equip, p->intimate, p->hungry, p->rename_flag, p->incuvate)) { Sql_ShowDebug (sql_handle); return 0; } p->pet_id = (int) Sql_LastInsertId (sql_handle); } else { // Update pet. if (SQL_ERROR == Sql_Query (sql_handle, "UPDATE `%s` SET `class`='%d',`name`='%s',`account_id`='%d',`char_id`='%d',`level`='%d',`egg_id`='%d',`equip`='%d',`intimate`='%d',`hungry`='%d',`rename_flag`='%d',`incuvate`='%d' WHERE `pet_id`='%d'", pet_db, p->class_, esc_name, p->account_id, p->char_id, p->level, p->egg_id, p->equip, p->intimate, p->hungry, p->rename_flag, p->incuvate, p->pet_id)) { Sql_ShowDebug (sql_handle); return 0; } } if (save_log) ShowInfo ("Pet salvo %d - %s.\n", pet_id, p->name); return 1; }
//Exp share and added zeny share [Valaris] int party_exp_share(struct party_data *p, struct block_list *src, unsigned int base_exp, unsigned int job_exp, int zeny) { struct map_session_data *sd[MAX_PARTY]; unsigned int i, c; #ifdef RENEWAL_EXP uint32 base_exp_bonus, job_exp_bonus; #endif nullpo_ret(p); //Count the number of players eligible for exp sharing for (i = c = 0; i < MAX_PARTY; i++) { if ((sd[c] = p->data[i].sd) == NULL || sd[c]->bl.m != src->m || pc_isdead(sd[c]) || (battle_config.idle_no_share && pc_isidle(sd[c]))) continue; c++; } if (c < 1) return 0; base_exp /= c; job_exp /= c; zeny /= c; if (battle_config.party_even_share_bonus && c > 1) { double bonus = 100 + battle_config.party_even_share_bonus * (c - 1); if (base_exp) base_exp = (unsigned int)cap_value(base_exp * bonus / 100, 0, UINT_MAX); if (job_exp) job_exp = (unsigned int)cap_value(job_exp * bonus / 100, 0, UINT_MAX); if (zeny) zeny = (unsigned int)cap_value(zeny * bonus / 100, INT_MIN, INT_MAX); } #ifdef RENEWAL_EXP base_exp_bonus = base_exp; job_exp_bonus = job_exp; #endif for (i = 0; i < c; i++) { #ifdef RENEWAL_EXP if (!(src && src->type == BL_MOB && ((TBL_MOB *)src)->db->mexp)) { TBL_MOB *md = BL_CAST(BL_MOB, src); int rate = 0; if (!md) return 0; rate = pc_level_penalty_mod(sd[i], md->db->lv, md->db->status.class_, 1); base_exp = (unsigned int)cap_value(base_exp_bonus * rate / 100, 1, UINT_MAX); job_exp = (unsigned int)cap_value(job_exp_bonus * rate / 100, 1, UINT_MAX); } #endif pc_gainexp(sd[i], src, base_exp, job_exp, false); if (zeny) //Zeny from mobs [Valaris] pc_getzeny(sd[i],zeny,LOG_TYPE_PICKDROP_MONSTER,NULL); } return 0; }
/** Party EXP and Zeny sharing * @param p Party data * @param src EXP source (for renewal level penalty) * @param base_exp Base EXP gained from killed mob * @param job_exp Job EXP gained from killed mob * @param zeny Zeny gained from killed mob * @author Valaris **/ void party_exp_share(struct party_data* p, struct block_list* src, unsigned int base_exp, unsigned int job_exp, int zeny) { struct map_session_data* sd[MAX_PARTY]; unsigned int i, c; #ifdef RENEWAL_EXP TBL_MOB *md = BL_CAST(BL_MOB, src); if (!md) return; #endif nullpo_retv(p); // count the number of players eligible for exp sharing for (i = c = 0; i < MAX_PARTY; i++) { if( (sd[c] = p->data[i].sd) == NULL || sd[c]->bl.m != src->m || pc_isdead(sd[c]) || (battle_config.idle_no_share && pc_isidle(sd[c])) ) continue; c++; } if (c < 1) return; base_exp/=c; job_exp/=c; zeny/=c; if (battle_config.party_even_share_bonus && c > 1) { double bonus = 100 + battle_config.party_even_share_bonus*(c-1); if (base_exp) base_exp = (unsigned int) cap_value(base_exp * bonus/100, 0, UINT_MAX); if (job_exp) job_exp = (unsigned int) cap_value(job_exp * bonus/100, 0, UINT_MAX); if (zeny) zeny = (unsigned int) cap_value(zeny * bonus/100, INT_MIN, INT_MAX); } for (i = 0; i < c; i++) { #ifdef RENEWAL_EXP uint32 base_gained = base_exp, job_gained = job_exp; if (base_exp || job_exp) { int rate = pc_level_penalty_mod(md->level - sd[i]->status.base_level, md->db->status.class_, md->db->status.mode, 1); if (rate != 100) { if (base_exp) base_gained = (unsigned int)cap_value(apply_rate(base_exp, rate), 1, UINT_MAX); if (job_exp) job_gained = (unsigned int)cap_value(apply_rate(job_exp, rate), 1, UINT_MAX); } } pc_gainexp(sd[i], src, base_gained, job_gained, 0); #else pc_gainexp(sd[i], src, base_exp, job_exp, 0); #endif if (zeny) // zeny from mobs [Valaris] pc_getzeny(sd[i],zeny,LOG_TYPE_PICKDROP_MONSTER,NULL); } }
int inter_pet_fromsql(int pet_id, struct s_pet* p) { char* data; size_t len; #ifdef NOISY ShowInfo("Loading pet (%d)...\n",pet_id); #endif memset(p, 0, sizeof(struct s_pet)); //`pet` (`pet_id`, `class`,`name`,`account_id`,`char_id`,`level`,`egg_id`,`equip`,`intimate`,`hungry`,`rename_flag`,`incuvate`) if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `pet_id`, `class`,`name`,`account_id`,`char_id`,`level`,`egg_id`,`equip`,`intimate`,`hungry`,`rename_flag`,`incuvate` FROM `%s` WHERE `pet_id`='%d'", pet_db, pet_id) ) { Sql_ShowDebug(sql_handle); return 0; } if( SQL_SUCCESS == Sql_NextRow(sql_handle) ) { p->pet_id = pet_id; Sql_GetData(sql_handle, 1, &data, NULL); p->class_ = atoi(data); Sql_GetData(sql_handle, 2, &data, &len); memcpy(p->name, data, min(len, NAME_LENGTH)); Sql_GetData(sql_handle, 3, &data, NULL); p->account_id = atoi(data); Sql_GetData(sql_handle, 4, &data, NULL); p->char_id = atoi(data); Sql_GetData(sql_handle, 5, &data, NULL); p->level = atoi(data); Sql_GetData(sql_handle, 6, &data, NULL); p->egg_id = atoi(data); Sql_GetData(sql_handle, 7, &data, NULL); p->equip = atoi(data); Sql_GetData(sql_handle, 8, &data, NULL); p->intimate = atoi(data); Sql_GetData(sql_handle, 9, &data, NULL); p->hungry = atoi(data); Sql_GetData(sql_handle, 10, &data, NULL); p->rename_flag = atoi(data); Sql_GetData(sql_handle, 11, &data, NULL); p->incuvate = atoi(data); Sql_FreeResult(sql_handle); p->hungry = cap_value(p->hungry, 0, 100); p->intimate = cap_value(p->intimate, 0, 1000); if( save_log ) ShowInfo("Pet loaded (%d - %s).\n", pet_id, p->name); } return 0; }
// exp share and added zeny share [Valaris] int party_exp_share(struct party_data* p, struct block_list* src, unsigned int base_exp, unsigned int job_exp, int zeny) { struct map_session_data* sd[MAX_PARTY]; unsigned int i, c; nullpo_retr(0, p); // count the number of players eligible for exp sharing for( i = c = 0; i < MAX_PARTY; i++ ) { if( (sd[c] = p->data[i].sd) == NULL || sd[c]->bl.m != src->m || pc_isdead(sd[c]) || (battle_config.idle_no_share && pc_isidle(sd[c])) ) continue; c++; } if( c < 1 ) return 0; base_exp /= c; job_exp /= c; zeny /= c; if( battle_config.renewal_system_enable && c > 2 ) { int rbonus = 100 + (10 * (c - 2)); // 10% ~ 100% if( base_exp ) base_exp = (unsigned int) cap_value(base_exp * rbonus/100, 0, UINT_MAX); if( job_exp ) job_exp = (unsigned int) cap_value(job_exp * rbonus/100, 0, UINT_MAX); } if( battle_config.party_even_share_bonus && c > 1 ) { double bonus = 100 + battle_config.party_even_share_bonus*(c-1); if (base_exp) base_exp = (unsigned int) cap_value(base_exp * bonus/100, 0, UINT_MAX); if (job_exp) job_exp = (unsigned int) cap_value(job_exp * bonus/100, 0, UINT_MAX); if (zeny) zeny = (unsigned int) cap_value(zeny * bonus/100, INT_MIN, INT_MAX); } for( i = 0; i < c; i++ ) { pc_gainexp(sd[i],src,base_exp,job_exp,false); if( zeny ) // zeny from mobs [Valaris] pc_getzeny(sd[i],zeny); } return 0; }
int mercenary_set_faith(struct mercenary_data *md, int value) { struct map_session_data *sd; int class_, *faith; if( md == NULL || md->db == NULL || (sd = md->master) == NULL ) return 0; class_ = md->db->class_; if( class_ >= 6017 && class_ <= 6026 ) faith = &sd->status.arch_faith; else if( class_ >= 6027 && class_ <= 6036 ) faith = &sd->status.spear_faith; else if( class_ >= 6037 && class_ <= 6046 ) faith = &sd->status.sword_faith; else return 0; *faith += value; *faith = cap_value(*faith, 0, SHRT_MAX); clif->mercenary_updatestatus(sd, SP_MERCFAITH); return 0; }
CBazaarItemPacket::CBazaarItemPacket(CItem* PItem, uint8 slotID, uint8 tax) { this->type = 0x05; // 0x105 this->size = 0x17; WBUFL(data,(0x04)-4) = PItem->getCharPrice(); WBUFL(data,(0x08)-4) = PItem->getQuantity(); WBUFW(data,(0x0C)-4) = tax; WBUFW(data,(0x0E)-4) = PItem->getID(); WBUFB(data,(0x10)-4) = slotID; if (PItem->getSubType() & ITEM_CHARGED) { uint32 currentTime = CVanaTime::getInstance()->getSysTime() - 1009810800; uint32 nextUseTime = ((CItemUsable*)PItem)->getLastUseTime() + ((CItemUsable*)PItem)->getReuseDelay(); WBUFB(data,(0x11)-4) = 0x01; // флаг ITEM_CHARGED WBUFB(data,(0x12)-4) = ((CItemUsable*)PItem)->getCurrentCharges(); WBUFB(data,(0x14)-4) = (nextUseTime > currentTime ? 0x90 : 0xD0); WBUFL(data,(0x15)-4) = nextUseTime; // таймер следующего использования WBUFL(data,(0x19)-4) = ((CItemUsable*)PItem)->getUseDelay() + currentTime; // таймер задержки использования } memcpy(data+(0x1D)-4, PItem->getSignature(), cap_value(strlen(PItem->getSignature()), 0, 12)); }
bool channel_create(struct map_session_data *sd, const char* name, const char* pass, short type, short color, int op) { struct channel_data *cd; int i = 0; if( !name || strlen(name) < 2 || strlen(name) >= NAME_LENGTH || name[0] != '#' ) { if( sd ) clif_displaymessage(sd->fd, msg_txt(801)); return false; } if( type == CHN_USER && !sd ) return false; // Operator required for user channels if( sd && type == CHN_USER && (i = channel_slot_free(sd)) < 0 ) { clif_displaymessage(sd->fd, msg_txt(800)); return false; } if( (cd = (struct channel_data *)strdb_get(channel_db, name)) != NULL ) { if( sd ) clif_displaymessage(sd->fd, msg_txt(802)); return false; // Already exists } CREATE(cd, struct channel_data, 1); cd->channel_id = ++channel_counter; safestrncpy(cd->name, name, sizeof(cd->name)); safestrncpy(cd->pass, pass, sizeof(cd->pass)); cd->type = type; cd->color = channel_color[cap_value(color,0,38)]; cd->users = 0; cd->op = 0; cd->users_db = idb_alloc(DB_OPT_BASE); if( type == CHN_USER ) { char output[128]; sprintf(output, msg_txt(803), cd->name, sd->status.name); sd->cd[i] = cd; cd->op = sd->bl.id; idb_put(cd->users_db, sd->bl.id, sd); cd->users++; clif_channel_message(cd, output, -1); } else if( type < CHN_USER ) { server_channel[type] = cd; // Quick access to main channels ShowInfo("Channel System : New channel %s created.\n", cd->name); } else cd->op = op; // Server Channel strdb_put(channel_db, cd->name, cd); return true; }
void vsx_widget_controller_slider::command_process_back_queue(vsx_command_s *t) { if (owned && t->cmd == "si") { vsx_widget::command_process_back_queue(t); } else if (t->cmd == "u") { target_value = vsx_string_helper::s2f(t->cmd_data); cap_value(); send_to_server(); k_focus = this; } else vsx_widget_controller_base::command_process_back_queue(t); }
void vsx_widget_controller_slider::event_mouse_move(vsx_widget_distance distance,vsx_widget_coords coords) { VSX_UNUSED(coords); if (controlling) { target_value = (-(((distance.corner.y-handlesize/2)/(size.y-handlesize))-1) * (amp))+ofs; //amp-ofs cap_value(); } send_to_server(); ++mouse_moves; }
// ギルド役職変更 int guild_change_position(int guild_id,int idx, int mode,int exp_mode,const char *name) { struct guild_position p; exp_mode = cap_value(exp_mode, 0, battle_config.guild_exp_limit); //Mode 0x01 <- Invite //Mode 0x10 <- Expel. p.mode=mode&0x11; p.exp_mode=exp_mode; safestrncpy(p.name,name,NAME_LENGTH); return intif_guild_position(guild_id,idx,&p); }
// ギルド役職変更 int guild_change_position(int guild_id,int idx, int mode,int exp_mode,const char *name) { struct guild_position p; exp_mode = cap_value(exp_mode, 0, battle_config.guild_exp_limit); //Mode 0x01 <- Invite //Mode 0x10 <- Expel. p.mode=mode&0x11; p.exp_mode=exp_mode; memcpy(p.name,name,NAME_LENGTH-1); p.name[NAME_LENGTH-1] = '\0'; //Security check... [Skotlex] return intif_guild_position(guild_id,idx,&p); }
int mercenary_kills(struct mercenary_data *md) { md->mercenary.kill_count++; md->mercenary.kill_count = cap_value(md->mercenary.kill_count, 0, INT_MAX); if((md->mercenary.kill_count % 50) == 0) { mercenary_set_faith(md, 1); mercenary_killbonus(md); } if(md->master) clif_mercenary_updatestatus(md->master, SP_MERCKILLS); return 0; }
struct skill_condition elemental_skill_get_requirements(uint16 skill_id, uint16 skill_lv){ struct skill_condition req; uint16 idx = skill_get_index(skill_id); memset(&req,0,sizeof(req)); if( idx == 0 ) // invalid skill id return req; skill_lv = cap_value(skill_lv, 1, MAX_SKILL_LEVEL); req.hp = skill_db[idx]->require.hp[skill_lv-1]; req.sp = skill_db[idx]->require.sp[skill_lv-1]; return req; }
/** * Set Mercenary's calls * @param md Mercenary * @param value **/ void mercenary_set_calls(struct mercenary_data *md, int value) { struct map_session_data *sd; uint16 class_; int *calls; if( md == NULL || md->db == NULL || (sd = md->master) == NULL ) return; class_ = md->db->class_; if( class_ >= 6017 && class_ <= 6026 ) calls = &sd->status.arch_calls; else if( class_ >= 6027 && class_ <= 6036 ) calls = &sd->status.spear_calls; else if( class_ >= 6037 && class_ <= 6046 ) calls = &sd->status.sword_calls; else return; *calls += value; *calls = cap_value(*calls, 0, INT_MAX); }
/*========================================== * Open shop * data := {<index>.w <amount>.w <value>.l}[count] *------------------------------------------*/ void vending_openvending(struct map_session_data* sd, const char* message, const uint8* data, int count) { int i, j; int vending_skill_lvl; nullpo_retv(sd); if ( pc_isdead(sd) || !sd->state.prevend || pc_istrading(sd)) return; // can't open vendings lying dead || didn't use via the skill (wpe/hack) || can't have 2 shops at once vending_skill_lvl = pc->checkskill(sd, MC_VENDING); // skill level and cart check if( !vending_skill_lvl || !pc_iscarton(sd) ) { clif->skill_fail(sd, MC_VENDING, USESKILL_FAIL_LEVEL, 0); return; } // check number of items in shop if( count < 1 || count > MAX_VENDING || count > 2 + vending_skill_lvl ) { // invalid item count clif->skill_fail(sd, MC_VENDING, USESKILL_FAIL_LEVEL, 0); return; } // filter out invalid items i = 0; for( j = 0; j < count; j++ ) { short index = *(uint16*)(data + 8*j + 0); short amount = *(uint16*)(data + 8*j + 2); unsigned int value = *(uint32*)(data + 8*j + 4); index -= 2; // offset adjustment (client says that the first cart position is 2) if( index < 0 || index >= MAX_CART // invalid position || pc->cartitem_amount(sd, index, amount) < 0 // invalid item or insufficient quantity //NOTE: official server does not do any of the following checks! || !sd->status.cart[index].identify // unidentified item || sd->status.cart[index].attribute == 1 // broken item || sd->status.cart[index].expire_time // It should not be in the cart but just in case || !itemdb_cantrade(&sd->status.cart[index], pc->get_group_level(sd), pc->get_group_level(sd)) ) // untradeable item continue; sd->vending[i].index = index; sd->vending[i].amount = amount; sd->vending[i].value = cap_value(value, 0, (unsigned int)battle_config.vending_max_value); i++; // item successfully added } if( i != j ) clif->message (sd->fd, msg_txt(266)); //"Some of your items cannot be vended and were removed from the shop." if( i == 0 ) { // no valid item found clif->skill_fail(sd, MC_VENDING, USESKILL_FAIL_LEVEL, 0); // custom reply packet return; } sd->state.prevend = sd->state.workinprogress = 0; sd->state.vending = true; sd->vender_id = getid(); sd->vend_num = i; safestrncpy(sd->message, message, MESSAGE_SIZE); clif->openvending(sd,sd->bl.id,sd->vending); clif->showvendingboard(&sd->bl,message,0); idb_put(vending->db, sd->status.char_id, sd); }
/* ============================================================== bg_arena (0 EoS | 1 Boss | 2 TI | 3 CTF | 4 TD | 5 SC | 6 CON | 7 RUSH | 8 DOM) bg_result (0 Won | 1 Tie | 2 Lost) ============================================================== */ void bg_team_rewards(int bg_id, int nameid, int amount, int kafrapoints, int quest_id, const char *var, int add_value, int bg_arena, int bg_result) { struct battleground_data *bg; struct map_session_data *sd; struct item_data *id; struct item it; int i, j, flag, fame, get_amount, rank = 0, type; if( amount < 1 || (bg = bg_team_search(bg_id)) == NULL || (id = itemdb_exists(nameid)) == NULL ) return; if( battle_config.bg_reward_rates != 100 ) { // BG Reward Rates amount = amount * battle_config.bg_reward_rates / 100; kafrapoints = kafrapoints * battle_config.bg_reward_rates / 100; } bg_result = cap_value(bg_result,0,2); memset(&it,0,sizeof(it)); if( nameid == 7828 || nameid == 7829 || nameid == 7773 ) { it.nameid = nameid; it.identify = 1; } else nameid = 0; for( j = 0; j < MAX_BG_MEMBERS; j++ ) { if( (sd = bg->members[j].sd) == NULL ) continue; if( battle_config.bg_ranking_bonus ) { rank = 0; ARR_FIND(0,MAX_FAME_LIST,i,bgrank_fame_list[i].id == sd->status.char_id); if( i < MAX_FAME_LIST ) rank = 1; else { ARR_FIND(0,MAX_FAME_LIST,i,bg_fame_list[i].id == sd->status.char_id); if( i < MAX_FAME_LIST ) rank = 1; } } if( quest_id ) quest_add(sd,quest_id); pc_setglobalreg(sd,var,pc_readglobalreg(sd,var) + add_value); if( kafrapoints > 0 ) { get_amount = kafrapoints; if( rank ) get_amount += battle_config.bg_ranking_bonus * get_amount / 100; pc_getcash(sd,0,get_amount); } if( nameid && amount > 0 ) { get_amount = amount; if( rank ) get_amount += battle_config.bg_ranking_bonus * get_amount / 100; if( (flag = pc_additem(sd,&it,get_amount,LOG_TYPE_SCRIPT)) ) clif_additem(sd,0,0,flag); } type = bg->members[j].ranked ? 2 : 3; // Where to Add Fame switch( bg_result ) { case 0: // Won add2limit(sd->status.bgstats.win,1,USHRT_MAX); achievement_validate_bg(sd,ATB_VICTORY,1); fame = 100; if( sd->bmaster_flag ) { add2limit(sd->status.bgstats.leader_win,1,USHRT_MAX); achievement_validate_bg(sd,ATB_LEADER_VICTORY,1); fame += 25; } pc_addfame(sd,fame,type); switch( bg_arena ) { case 0: add2limit(sd->status.bgstats.eos_wins,1,USHRT_MAX); achievement_validate_bg(sd,ATB_EOS_VICTORY,1); break; case 1: add2limit(sd->status.bgstats.boss_wins,1,USHRT_MAX); achievement_validate_bg(sd,ATB_BOSS_VICTORY,1); break; case 2: add2limit(sd->status.bgstats.ti_wins,1,USHRT_MAX); achievement_validate_bg(sd,ATB_TI_VICTORY,1); break; case 3: add2limit(sd->status.bgstats.ctf_wins,1,USHRT_MAX); achievement_validate_bg(sd,ATB_CTF_VICTORY,1); break; case 4: add2limit(sd->status.bgstats.td_wins,1,USHRT_MAX); achievement_validate_bg(sd,ATB_TDM_VICTORY,1); break; case 5: add2limit(sd->status.bgstats.sc_wins,1,USHRT_MAX); achievement_validate_bg(sd,ATB_SC_VICTORY,1); break; case 6: add2limit(sd->status.bgstats.cq_wins,1,USHRT_MAX); achievement_validate_bg(sd,ATB_CON_VICTORY,1); break; case 7: add2limit(sd->status.bgstats.ru_wins,1,USHRT_MAX); achievement_validate_bg(sd,ATB_RU_VICTORY,1); break; case 8: add2limit(sd->status.bgstats.dom_wins,1,USHRT_MAX); achievement_validate_bg(sd,ATB_DOM_VICTORY,1); break; } break; case 1: // Tie add2limit(sd->status.bgstats.tie,1,USHRT_MAX); fame = 75; if( sd->bmaster_flag ) { add2limit(sd->status.bgstats.leader_tie,1,USHRT_MAX); fame += 10; } pc_addfame(sd,fame,type); switch( bg_arena ) { case 0: add2limit(sd->status.bgstats.eos_tie,1,USHRT_MAX); break; case 1: add2limit(sd->status.bgstats.boss_tie,1,USHRT_MAX); break; case 2: add2limit(sd->status.bgstats.ti_tie,1,USHRT_MAX); break; case 3: add2limit(sd->status.bgstats.ctf_tie,1,USHRT_MAX); break; case 4: add2limit(sd->status.bgstats.td_tie,1,USHRT_MAX); break; case 5: add2limit(sd->status.bgstats.sc_tie,1,USHRT_MAX); break; // No Tie for Conquest or Rush case 8: add2limit(sd->status.bgstats.dom_tie,1,USHRT_MAX); break; } break; case 2: // Lost add2limit(sd->status.bgstats.lost,1,USHRT_MAX); achievement_validate_bg(sd,ATB_DEFEAT,1); fame = 50; if( sd->bmaster_flag ) { add2limit(sd->status.bgstats.leader_lost,1,USHRT_MAX); achievement_validate_bg(sd,ATB_LEADER_DEFEAT,1); } pc_addfame(sd,fame,type); switch( bg_arena ) { case 0: add2limit(sd->status.bgstats.eos_lost,1,USHRT_MAX); break; case 1: add2limit(sd->status.bgstats.boss_lost,1,USHRT_MAX); break; case 2: add2limit(sd->status.bgstats.ti_lost,1,USHRT_MAX); break; case 3: add2limit(sd->status.bgstats.ctf_lost,1,USHRT_MAX); break; case 4: add2limit(sd->status.bgstats.td_lost,1,USHRT_MAX); break; case 5: add2limit(sd->status.bgstats.sc_lost,1,USHRT_MAX); break; case 6: add2limit(sd->status.bgstats.cq_lost,1,USHRT_MAX); break; case 7: add2limit(sd->status.bgstats.ru_lost,1,USHRT_MAX); break; case 8: add2limit(sd->status.bgstats.dom_lost,1,USHRT_MAX); break; } break; } } }
/*========================================== * Abrir loja * data := {<index>.w <amount>.w <value>.l}[count] *------------------------------------------*/ void vending_openvending(struct map_session_data* sd, const char* message, const uint8* data, int count) { int i, j; int vending_skill_lvl; nullpo_retv(sd); if ( pc_isdead(sd) || !sd->state.prevend || pc_istrading(sd)) return; // nao pode abrir vendas deitado morto || não usou via habilidade (wpe/hack) || não pode ter 2 lojas ao mesmo tempo vending_skill_lvl = pc->checkskill(sd, MC_VENDING); // check de nivel de habilidade e carrinho if( !vending_skill_lvl || !pc_iscarton(sd) ) { clif->skill_fail(sd, MC_VENDING, USESKILL_FAIL_LEVEL, 0); return; } // checka numero de itens na loja if( count < 1 || count > MAX_VENDING || count > 2 + vending_skill_lvl ) { // contagem de item invalida clif->skill_fail(sd, MC_VENDING, USESKILL_FAIL_LEVEL, 0); return; } // filtrar itens invalidos i = 0; for( j = 0; j < count; j++ ) { short index = *(uint16*)(data + 8*j + 0); short amount = *(uint16*)(data + 8*j + 2); unsigned int value = *(uint32*)(data + 8*j + 4); index -= 2; // ajuste de equilibrio (cliente diz que a posição do primeiro carrinho é 2) if( index < 0 || index >= MAX_CART // posição inválida || pc->cartitem_amount(sd, index, amount) < 0 // item invalido ou quantidade insuficiente //NOT: servidores oficiais não fazem nenhum dos checks abaixo! || !sd->status.cart[index].identify // item não-identficado || sd->status.cart[index].attribute == 1 // item quebrado || sd->status.cart[index].expire_time // Isso não deveria estar no carrinho mas apenas no caso de estar || (sd->status.cart[index].bound && !pc_can_give_bound_items(sd)) // não pode trocar itens de recompensa, permissão w/o || !itemdb_cantrade(&sd->status.cart[index], pc_get_group_level(sd), pc_get_group_level(sd)) ) // Itens não-trocaveis continue; sd->vending[i].index = index; sd->vending[i].amount = amount; sd->vending[i].value = cap_value(value, 0, (unsigned int)battle_config.vending_max_value); i++; // item adicionado com sucesso } if( i != j ) clif->message (sd->fd, msg_txt(266)); //"Alguns dos seus itens não pode ser vendido e foram removidos da loja." if( i == 0 ) { // nenhum item válido encontrado clif->skill_fail(sd, MC_VENDING, USESKILL_FAIL_LEVEL, 0); // packet de resposta personalizada return; } sd->state.prevend = sd->state.workinprogress = 0; sd->state.vending = true; sd->vender_id = getid(); sd->vend_num = i; safestrncpy(sd->message, message, MESSAGE_SIZE); clif->openvending(sd,sd->bl.id,sd->vending); clif->showvendingboard(&sd->bl,message,0); idb_put(vending->db, sd->status.char_id, sd); }
/*========================================== * Open shop * data := {<index>.w <amount>.w <value>.l}[count] *------------------------------------------*/ void vending_openvending(struct map_session_data* sd, const char* message, bool flag, const uint8* data, int count) { int i, j, char_id; int vending_skill_lvl; nullpo_retv(sd); if( !flag ) // cancelled return; // nothing to do if (pc_istrading(sd)) return; // can't have 2 shops at once vending_skill_lvl = pc_checkskill(sd, MC_VENDING); // skill level and cart check if( !vending_skill_lvl || !pc_iscarton(sd) ) { clif_skill_fail(sd, MC_VENDING, 0, 0); return; } // check number of items in shop if( count < 1 || count > MAX_VENDING || count > 2 + vending_skill_lvl ) { // invalid item count clif_skill_fail(sd, MC_VENDING, 0, 0); return; } if((sd->bl.m == map_mapname2mapid("mercadores") && ( ((sd->bl.x != 65) && (sd->bl.x != 74) && (sd->bl.x != 85) && (sd->bl.x != 94) && (sd->bl.x != 34) && (sd->bl.x != 25) && (sd->bl.x != 14) && (sd->bl.x != 5) && (sd->bl.x != 44) && (sd->bl.x != 55)) ))) { clif_displaymessage(sd->fd,"Você não pode abrir lojas no meio da Sala."); return; } // filter out invalid items i = 0; for( j = 0; j < count; j++ ) { short index = *(uint16*)(data + 8*j + 0); short amount = *(uint16*)(data + 8*j + 2); unsigned int value = *(uint32*)(data + 8*j + 4); index -= 2; // offset adjustment (client says that the first cart position is 2) if( index < 0 || index >= MAX_CART // invalid position || pc_cartitem_amount(sd, index, amount) < 0 // invalid item or insufficient quantity //NOTE: official server does not do any of the following checks! || !sd->status.cart[index].identify // unidentified item || sd->status.cart[index].attribute == 1 // broken item || sd->status.cart[index].expire_time // It should not be in the cart but just in case || sd->status.cart[index].bound // Can't Trade Account bound items || ( sd->status.cart[index].card[0] == CARD0_CREATE && (char_id = MakeDWord(sd->status.cart[index].card[2],sd->status.cart[index].card[3])) > 0 && ((battle_config.bg_reserved_char_id && char_id == battle_config.bg_reserved_char_id) || (battle_config.ancient_reserved_char_id && char_id == battle_config.ancient_reserved_char_id)) ) || !itemdb_cantrade(&sd->status.cart[index], pc_isGM(sd), pc_isGM(sd)) ) // untradeable item continue; sd->vending[i].index = index; sd->vending[i].amount = amount; sd->vending[i].value = cap_value(value, 0, (unsigned int)battle_config.vending_max_value); i++; // item successfully added } if( i != j ) clif_displaymessage (sd->fd, msg_txt(266)); //"Some of your items cannot be vended and were removed from the shop." if( i == 0 ) { // no valid item found clif_skill_fail(sd, MC_VENDING, 0, 0); // custom reply packet return; } sd->state.vending = true; sd->vender_id = vending_getuid(); sd->vend_num = i; safestrncpy(sd->message, message, MESSAGE_SIZE); pc_stop_walking(sd,1); clif_openvending(sd,sd->bl.id,sd->vending); clif_showvendingboard(&sd->bl,message,0); if( battle_config.channel_announces&0x10 ) { char chat_message[256]; sprintf(chat_message, msg_txt(820), vending_chat_nick, sd->status.name, sd->message, map[sd->bl.m].name, sd->bl.x, sd->bl.y); clif_channel_message(server_channel[CHN_VENDING], chat_message, 27); } if( map[sd->bl.m].flag.vending_cell ) map_setcell(sd->bl.m, sd->bl.x, sd->bl.y, CELL_NOBOARDS, false); }
// exp share and added zeny share [Valaris] int party_exp_share(struct party_data* p, struct block_list* src, unsigned int base_exp, unsigned int job_exp, int zeny) { struct map_session_data* sd[MAX_PARTY]; unsigned int i, c; nullpo_ret(p); // count the number of players eligible for exp sharing for( i = c = 0; i < MAX_PARTY; i++ ) { if( (sd[c] = p->data[i].sd) == NULL || sd[c]->bl.m != src->m || pc_isdead(sd[c]) || (battle_config.idle_no_share && pc_isidle(sd[c])) ) continue; c++; } if(c < 1) return 0; if (battle_config.renewal_party_exp_nerf) { int nerf; if (c == 2) { nerf = 50; } else if (c == 3) { nerf = 37; } else if (c == 4) { nerf = 30; } else if (c == 5) { nerf = 26; } else if (c == 6) { nerf = 23; } else if (c == 7) { nerf = 21; } else if (c == 8) { nerf = 20; } else if (c == 9) { nerf = 19; } else if (c == 10) { nerf = 18; } else if (c == 11) { nerf = 17; } else if (c == 12) { nerf = 17; } else { nerf = 0; } if (nerf) { base_exp = base_exp * nerf / 100; job_exp = job_exp * nerf / 100; zeny = zeny * nerf / 100; } } else { base_exp /= c; job_exp /= c; zeny /= c; } if( battle_config.party_even_share_bonus && c > 1 ) { double bonus = 100 + battle_config.party_even_share_bonus*(c-1); if (base_exp) base_exp = (unsigned int) cap_value(base_exp * bonus/100, 0, UINT_MAX); if (job_exp) job_exp = (unsigned int) cap_value(job_exp * bonus/100, 0, UINT_MAX); if (zeny) zeny = (unsigned int) cap_value(zeny * bonus/100, INT_MIN, INT_MAX); } for( i = 0; i < c; i++ ) { pc_gainexp(sd[i], src, base_exp, job_exp, false); if( zeny ) // zeny from mobs [Valaris] pc_getzeny(sd[i],zeny); } return 0; }
CCheckPacket::CCheckPacket(CCharEntity* PChar, CCharEntity* PTarget) { this->type = 0xC9; this->size = 0x06; WBUFL(data,(0x04)-4) = PTarget->id; WBUFW(data,(0x08)-4) = PTarget->targid; WBUFB(data,(0x0A)-4) = 0x03; uint8 count = 0; for (int32 i = 0; i < 16; ++i) { if (PTarget->equip[i] != 0) { CItem* PItem = PTarget->getStorage(LOC_INVENTORY)->GetItem(PTarget->equip[i]); if (PItem != NULL) { WBUFW(data,(size*2+0x00)-4) = PItem->getID(); WBUFB(data,(size*2+0x02)-4) = i; if (PItem->getSubType() & ITEM_CHARGED) { uint32 currentTime = CVanaTime::getInstance()->getSysTime() - 1009810800; uint32 nextUseTime = ((CItemUsable*)PItem)->getLastUseTime() + ((CItemUsable*)PItem)->getReuseDelay(); WBUFB(data,(size*2+0x04)-4) = 0x01; WBUFB(data,(size*2+0x05)-4) = ((CItemUsable*)PItem)->getCurrentCharges(); WBUFB(data,(size*2+0x07)-4) = (nextUseTime > currentTime ? 0x90 : 0xD0); WBUFL(data,(size*2+0x08)-4) = nextUseTime; WBUFL(data,(size*2+0x0C)-4) = ((CItemUsable*)PItem)->getUseDelay() + currentTime; } memcpy(data+(size*2+0x10)-4, PItem->getSignature(), cap_value(strlen(PItem->getSignature()), 0, 12)); this->size += 0x0E; count++; if (count == 8) { WBUFB(data,(0x0B)-4) = count; PChar->pushPacket(new CBasicPacket(*this)); this->size = 0x06; memset(data+(0x0B)-4, 0, sizeof(data)-7); } } } } if (count == 0) { this->size = 0x14; PChar->pushPacket(new CBasicPacket(*this)); } else if (count != 8) { WBUFB(data,(0x0B)-4) = (count > 8 ? count - 8 : count); PChar->pushPacket(new CBasicPacket(*this)); } this->size = 0x28; memset(data+(0x0B)-4, 0, sizeof(data)-7); WBUFB(data,(0x0A)-4) = 0x01; if ( (PChar->nameflags.flags & FLAG_GM) || !(PTarget->nameflags.flags & FLAG_ANON)) { WBUFB(data,(0x12)-4) = PTarget->GetMJob(); WBUFB(data,(0x13)-4) = PTarget->GetSJob(); WBUFB(data,(0x23)-4) = PTarget->GetMLevel(); WBUFB(data,(0x24)-4) = PTarget->GetSLevel(); } //Chevron 32 bit Big Endean, starting at 0x2B //WBUFB(data,(0x2C)-4) = 0x00; //Ballista Star next to Chevron count }
// Load an homunculus bool mapif_homunculus_load(int homun_id, struct s_homunculus* hd) { int i; char* data; size_t len; memset(hd, 0, sizeof(*hd)); if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `homun_id`,`char_id`,`class`,`prev_class`,`name`,`level`,`exp`,`intimacy`,`hunger`, `str`, `agi`, `vit`, `int`, `dex`, `luk`, `hp`,`max_hp`,`sp`,`max_sp`,`skill_point`,`rename_flag`, `vaporize` FROM `%s` WHERE `homun_id`='%u'", homunculus_db, homun_id) ) { Sql_ShowDebug(sql_handle); return false; } if( !Sql_NumRows(sql_handle) ) { //No homunculus found. Sql_FreeResult(sql_handle); return false; } if( SQL_SUCCESS != Sql_NextRow(sql_handle) ) { Sql_ShowDebug(sql_handle); Sql_FreeResult(sql_handle); return false; } hd->hom_id = homun_id; Sql_GetData(sql_handle, 1, &data, NULL); hd->char_id = atoi(data); Sql_GetData(sql_handle, 2, &data, NULL); hd->class_ = atoi(data); Sql_GetData(sql_handle, 3, &data, NULL); hd->prev_class = atoi(data); Sql_GetData(sql_handle, 4, &data, &len); safestrncpy(hd->name, data, sizeof(hd->name)); Sql_GetData(sql_handle, 5, &data, NULL); hd->level = atoi(data); Sql_GetData(sql_handle, 6, &data, NULL); hd->exp = atoi(data); Sql_GetData(sql_handle, 7, &data, NULL); hd->intimacy = (unsigned int)strtoul(data, NULL, 10); Sql_GetData(sql_handle, 8, &data, NULL); hd->hunger = atoi(data); Sql_GetData(sql_handle, 9, &data, NULL); hd->str = atoi(data); Sql_GetData(sql_handle, 10, &data, NULL); hd->agi = atoi(data); Sql_GetData(sql_handle, 11, &data, NULL); hd->vit = atoi(data); Sql_GetData(sql_handle, 12, &data, NULL); hd->int_ = atoi(data); Sql_GetData(sql_handle, 13, &data, NULL); hd->dex = atoi(data); Sql_GetData(sql_handle, 14, &data, NULL); hd->luk = atoi(data); Sql_GetData(sql_handle, 15, &data, NULL); hd->hp = atoi(data); Sql_GetData(sql_handle, 16, &data, NULL); hd->max_hp = atoi(data); Sql_GetData(sql_handle, 17, &data, NULL); hd->sp = atoi(data); Sql_GetData(sql_handle, 18, &data, NULL); hd->max_sp = atoi(data); Sql_GetData(sql_handle, 19, &data, NULL); hd->skillpts = atoi(data); Sql_GetData(sql_handle, 20, &data, NULL); hd->rename_flag = atoi(data); Sql_GetData(sql_handle, 21, &data, NULL); hd->vaporize = atoi(data); Sql_FreeResult(sql_handle); hd->intimacy = cap_value(hd->intimacy, 0, 100000); hd->hunger = cap_value(hd->hunger, 0, 100); // Load Homunculus Skill if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `id`,`lv` FROM `%s` WHERE `homun_id`=%d", skill_homunculus_db, homun_id) ) { Sql_ShowDebug(sql_handle); return false; } while( SQL_SUCCESS == Sql_NextRow(sql_handle) ) { // id Sql_GetData(sql_handle, 0, &data, NULL); i = atoi(data); if( i < HM_SKILLBASE || i >= HM_SKILLBASE + MAX_HOMUNSKILL ) continue;// invalid skill id i = i - HM_SKILLBASE; hd->hskill[i].id = (unsigned short)atoi(data); // lv Sql_GetData(sql_handle, 1, &data, NULL); hd->hskill[i].lv = (unsigned char)atoi(data); } Sql_FreeResult(sql_handle); if( save_log ) ShowInfo("Homúnculus carregado (%d - %s).\n", hd->hom_id, hd->name); return true; }
/** Read item group data * Structure: GroupID,ItemID,Rate{,Amount,isMust,isAnnounced,Duration,isNamed,isBound} */ static void itemdb_read_itemgroup_sub(const char* filename) { FILE *fp; int ln = 0, entries = 0; char line[1024]; if( (fp = fopen(filename, "r")) == NULL ) { ShowError("Can't read %s\n", filename); return; } while( fgets(line, sizeof(line), fp) ) { uint16 nameid; int j, group_id, prob = 1, amt = 1, rand_group = 1, announced = 0, dur = 0, named = 0, bound = 0; char *str[3], *p, w1[1024], w2[1024]; bool found = false; struct s_item_group_random *random; ln++; if( line[0] == '/' && line[1] == '/' ) continue; if( strstr(line, "import") ) { if( sscanf(line, "%[^:]: %[^\r\n]", w1, w2) == 2 && strcmpi(w1, "import") == 0 ) { itemdb_read_itemgroup_sub(w2); continue; } } memset(str, 0, sizeof(str)); for( j = 0, p = line; j < 3 && p; j++ ) { str[j] = p; if( j == 2 ) sscanf(str[j], "%d,%d,%d,%d,%d,%d,%d", &prob, &amt, &rand_group, &announced, &dur, &named, &bound); p = strchr(p, ','); if( p ) *p++ = 0; } if( str[0] == NULL ) continue; if( j < 3 ) { if( j > 1 ) //Or else it barks on blank lines... ShowWarning("itemdb_read_itemgroup: Insufficient fields for entry at %s:%d\n", filename, ln); continue; } //Checking group_id trim(str[0]); if( ISDIGIT(str[0][0]) ) group_id = atoi(str[0]); else //Try reads group id by const script_get_constant(trim(str[0]), &group_id); if( group_id < 1 || group_id >= MAX_ITEMGROUP ) { ShowWarning("itemdb_read_itemgroup: Cannot save '%s' because invalid group id or group db is overflow in %s:%d\n", str[0], filename, ln); continue; } //Checking sub group if( rand_group < 0 || rand_group > MAX_ITEMGROUP_RANDGROUP ) { ShowWarning("itemdb_read_itemgroup: Invalid sub group %d for group '%s' in %s:%d\n", rand_group, str[0], filename, ln); continue; } if( rand_group && prob < 1 ) { ShowWarning("itemdb_read_itemgroup: Invalid probaility for group '%s' sub: %d in %s:%d\n", str[0], rand_group, filename, ln); continue; } //Checking item trim(str[1]); if( ISDIGIT(str[1][0]) && itemdb_exists((nameid = atoi(str[1]))) ) found = true; else if( itemdb_searchname(str[1]) ) { found = true; nameid = itemdb_searchname(str[1])->nameid; } if( !found ) { ShowWarning("itemdb_read_itemgroup: Non-existant item '%s' in %s:%d\n", str[1], filename, ln); continue; } amt = cap_value(amt, 1, MAX_AMOUNT); dur = cap_value(dur, 0, UINT16_MAX); bound = cap_value(bound, 0, 4); //Must item (rand_group == 0), place it here if( !rand_group ) { uint16 idx = itemgroup_db[group_id].must_qty; if( !idx ) CREATE(itemgroup_db[group_id].must, struct s_item_group, 1); else RECREATE(itemgroup_db[group_id].must, struct s_item_group, idx + 1); itemgroup_db[group_id].must[idx].nameid = nameid; itemgroup_db[group_id].must[idx].amount = amt; itemgroup_db[group_id].must[idx].isAnnounced = announced; itemgroup_db[group_id].must[idx].duration = dur; itemgroup_db[group_id].must[idx].isNamed = named; itemgroup_db[group_id].must[idx].bound = bound; itemgroup_db[group_id].must_qty++; //If 'must' item isn't set as random item, skip the next process if( !prob ) { entries++; continue; } rand_group = 0; } else
/*========================================== * Open shop * data := {<index>.w <amount>.w <value>.l}[count] *------------------------------------------*/ void vending_openvending(struct map_session_data* sd, const char* message, bool flag, const uint8* data, int count) { int i, j; int vending_skill_lvl; nullpo_retv(sd); if( !flag ) // cancelled return; // nothing to do if (pc_istrading(sd)) return; // can't have 2 shops at once vending_skill_lvl = pc_checkskill(sd, MC_VENDING); // skill level and cart check if( !vending_skill_lvl || !pc_iscarton(sd) ) { clif_skill_fail(sd, MC_VENDING, 0, 0); return; } // check number of items in shop if( count < 1 || count > MAX_VENDING || count > 2 + vending_skill_lvl ) { // invalid item count clif_skill_fail(sd, MC_VENDING, 0, 0); return; } // filter out invalid items i = 0; for( j = 0; j < count; j++ ) { short index = *(uint16*)(data + 8*j + 0); short amount = *(uint16*)(data + 8*j + 2); unsigned int value = *(uint32*)(data + 8*j + 4); index -= 2; // offset adjustment (client says that the first cart position is 2) if( index < 0 || index >= MAX_CART // invalid position || pc_cartitem_amount(sd, index, amount) < 0 // invalid item or insufficient quantity //NOTE: official server does not do any of the following checks! || !sd->status.cart[index].identify // unidentified item || sd->status.cart[index].attribute == 1 // broken item || !itemdb_cantrade(&sd->status.cart[index], pc_isGM(sd), pc_isGM(sd)) ) // untradeable item continue; sd->vending[i].index = index; sd->vending[i].amount = amount; sd->vending[i].value = cap_value(value, 1, (unsigned int)battle_config.vending_max_value); i++; // item successfully added } if( i != j ) clif_displaymessage (sd->fd, msg_txt(266)); //"Some of your items cannot be vended and were removed from the shop." if( i == 0 ) { // no valid item found clif_skill_fail(sd, MC_VENDING, 0, 0); // custom reply packet return; } sd->vender_id = sd->bl.id; sd->vend_num = i; safestrncpy(sd->message, message, MESSAGE_SIZE); pc_stop_walking(sd,1); clif_openvending(sd,sd->vender_id,sd->vending); clif_showvendingboard(&sd->bl,message,0); }
/*========================================== * processes one itemdb entry *------------------------------------------*/ static bool itemdb_parse_dbrow(char** str, const char* source, int line, int scriptopt, char *comboScript) { /* +----+--------------+---------------+------+-----------+------------+--------+--------+---------+-------+-------+------------+-------------+---------------+-----------------+--------------+-------------+------------+------+--------+--------------+----------------+ | 00 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | +----+--------------+---------------+------+-----------+------------+--------+--------+---------+-------+-------+------------+-------------+---------------+-----------------+--------------+-------------+------------+------+--------+--------------+----------------+ | id | name_english | name_japanese | type | price_buy | price_sell | weight | attack | defence | range | slots | equip_jobs | equip_upper | equip_genders | equip_locations | weapon_level | equip_level | refineable | view | script | equip_script | unequip_script | +----+--------------+---------------+------+-----------+------------+--------+--------+---------+-------+-------+------------+-------------+---------------+-----------------+--------------+-------------+------------+------+--------+--------------+----------------+ */ int nameid; struct item_data* id; nameid = atoi(str[0]); if( nameid <= 0 ) { ShowWarning("itemdb_parse_dbrow: Invalid id %d in line %d of \"%s\", skipping.\n", nameid, line, source); return false; } //ID,Name,Jname,Type,Price,Sell,Weight,ATK,DEF,Range,Slot,Job,Job Upper,Gender,Loc,wLV,eLV,refineable,View id = itemdb_load(nameid); safestrncpy(id->name, str[1], sizeof(id->name)); safestrncpy(id->jname, str[2], sizeof(id->jname)); id->type = atoi(str[3]); if( id->type < 0 || id->type == IT_UNKNOWN || id->type == IT_UNKNOWN2 || ( id->type > IT_DELAYCONSUME && id->type < IT_CASH ) || id->type >= IT_MAX ) {// catch invalid item types ShowWarning("itemdb_parse_dbrow: Invalid item type %d for item %d. IT_ETC will be used.\n", id->type, nameid); id->type = IT_ETC; } if (id->type == IT_DELAYCONSUME) { //Items that are consumed only after target confirmation id->type = IT_USABLE; id->flag.delay_consume = 1; } else //In case of an itemdb reload and the item type changed. id->flag.delay_consume = 0; //When a particular price is not given, we should base it off the other one //(it is important to make a distinction between 'no price' and 0z) if ( str[4][0] ) id->value_buy = atoi(str[4]); else id->value_buy = atoi(str[5]) * 2; if ( str[5][0] ) id->value_sell = atoi(str[5]); else id->value_sell = id->value_buy / 2; /* if ( !str[4][0] && !str[5][0]) { ShowWarning("itemdb_parse_dbrow: No buying/selling price defined for item %d (%s), using 20/10z\n", nameid, id->jname); id->value_buy = 20; id->value_sell = 10; } else */ if (id->value_buy/124. < id->value_sell/75.) ShowWarning("itemdb_parse_dbrow: Buying/Selling [%d/%d] price of item %d (%s) allows Zeny making exploit through buying/selling at discounted/overcharged prices!\n", id->value_buy, id->value_sell, nameid, id->jname); id->weight = atoi(str[6]); #ifdef RENEWAL itemdb_re_split_atoi(str[7],&id->atk,&id->matk); #else id->atk = atoi(str[7]); #endif id->def = atoi(str[8]); id->range = atoi(str[9]); id->slot = atoi(str[10]); if (id->slot > MAX_SLOTS) { ShowWarning("itemdb_parse_dbrow: Item %d (%s) specifies %d slots, but the server only supports up to %d. Using %d slots.\n", nameid, id->jname, id->slot, MAX_SLOTS, MAX_SLOTS); id->slot = MAX_SLOTS; } itemdb_jobid2mapid(id->class_base, (unsigned int)strtoul(str[11],NULL,0)); id->class_upper = atoi(str[12]); id->sex = atoi(str[13]); id->equip = atoi(str[14]); if (!id->equip && itemdb_isequip2(id)) { ShowWarning("Item %d (%s) is an equipment with no equip-field! Making it an etc item.\n", nameid, id->jname); id->type = IT_ETC; } id->wlv = cap_value(atoi(str[15]), REFINE_TYPE_ARMOR, REFINE_TYPE_MAX); id->elv = atoi(str[16]); id->flag.no_refine = atoi(str[17]) ? 0 : 1; //FIXME: verify this id->look = atoi(str[18]); id->flag.available = 1; id->view_id = 0; id->sex = itemdb_gendercheck(id); //Apply gender filtering. if (id->script) { script_free_code(id->script); id->script = NULL; } if (id->equip_script) { script_free_code(id->equip_script); id->equip_script = NULL; } if (id->unequip_script) { script_free_code(id->unequip_script); id->unequip_script = NULL; } if (*str[19]) { char *scriptCode = str[19]; if ( comboScript ) { char *script1 = str[19]; while (*script1++ != '{'); scriptCode = (char *)aMalloc(strlen(script1) + strlen(comboScript) + 2); // +2 = {\0 sprintf(scriptCode, "{%s%s", comboScript, script1); } id->script = parse_script(scriptCode, source, line, scriptopt); if( comboScript ) aFree(scriptCode); } else if ( comboScript ) id->script = parse_script(comboScript, source, line, scriptopt); if (*str[20]) id->equip_script = parse_script(str[20], source, line, scriptopt); if (*str[21]) id->unequip_script = parse_script(str[21], source, line, scriptopt); return true; }
/** Read item group data * Structure: GroupID,ItemID,Rate{,Amount,isMust,isAnnounced,Duration,GUID,isBound,isNamed} */ static void itemdb_read_itemgroup_sub(const char* filename, bool silent) { FILE *fp; int ln = 0, entries = 0; char line[1024]; if ((fp=fopen(filename,"r")) == NULL) { if(silent == 0) ShowError("Can't read %s\n", filename); return; } while (fgets(line,sizeof(line),fp)) { DBData data; int group_id = -1; unsigned int j, prob = 1; uint8 rand_group = 1; char *str[10], *p; struct s_item_group_random *random = NULL; struct s_item_group_db *group = NULL; struct s_item_group_entry entry; bool found = false; ln++; if (line[0] == '/' && line[1] == '/') continue; if (strstr(line,"import")) { char w1[16], w2[64]; if (sscanf(line,"%15[^:]: %63[^\r\n]",w1,w2) == 2 && strcmpi(w1,"import") == 0) { itemdb_read_itemgroup_sub(w2, 0); continue; } } memset(str,0,sizeof(str)); for (j = 0, p = line; j < 9 && p;j++) { str[j] = p; p = strchr(p,','); if (p) *p++=0; } if (str[0] == NULL) //Empty Group ID continue; if (j < 3) { if (j > 1) // Or else it barks on blank lines... ShowWarning("itemdb_read_itemgroup: Insufficient fields for entry at %s:%d\n", filename, ln); continue; } memset(&entry, 0, sizeof(entry)); entry.amount = 1; entry.bound = BOUND_NONE; // Checking group_id trim(str[0]); if (ISDIGIT(str[0][0])) group_id = atoi(str[0]); else // Try reads group id by const script_get_constant(trim(str[0]), &group_id); if (group_id < 0) { ShowWarning("itemdb_read_itemgroup: Invalid Group ID '%s' (%s:%d)\n", str[0], filename, ln); continue; } // Remove from DB if (strcmpi(str[1], "clear") == 0 && itemdb_group->remove(itemdb_group, db_ui2key(group_id), &data)) { itemdb_group_free(db_ui2key(group_id), &data, 0); ShowNotice("Item Group '%s' has been cleared.\n", str[0]); continue; } // Checking sub group prob = atoi(str[2]); if (str[4] != NULL) rand_group = atoi(str[4]); if (rand_group < 0 || rand_group > MAX_ITEMGROUP_RANDGROUP) { ShowWarning("itemdb_read_itemgroup: Invalid sub group '%d' for group '%s' in %s:%d\n", rand_group, str[0], filename, ln); continue; } if (rand_group != 0 && prob < 1) { ShowWarning("itemdb_read_itemgroup: Random item must has probability. Group '%s' in %s:%d\n", str[0], filename, ln); continue; } // Checking item trim(str[1]); if (ISDIGIT(str[1][0]) && ISDIGIT(str[1][1]) && itemdb_exists((entry.nameid = atoi(str[1])))) found = true; else { struct item_data *id = itemdb_searchname(str[1]); if (id) { entry.nameid = id->nameid; found = true; } } if (!found) { ShowWarning("itemdb_read_itemgroup: Non-existant item '%s' in %s:%d\n", str[1], filename, ln); continue; } if (str[3] != NULL) entry.amount = cap_value(atoi(str[3]),1,MAX_AMOUNT); if (str[5] != NULL) entry.isAnnounced= atoi(str[5]); if (str[6] != NULL) entry.duration = cap_value(atoi(str[6]),0,UINT16_MAX); #ifdef ENABLE_ITEM_GUID if (str[7] != NULL) entry.GUID = atoi(str[7]); #endif if (str[8] != NULL) entry.bound = cap_value(atoi(str[8]),BOUND_NONE,BOUND_MAX-1); if (str[9] != NULL) entry.isNamed = atoi(str[9]); if (!(group = (struct s_item_group_db *) uidb_get(itemdb_group, group_id))) { CREATE(group, struct s_item_group_db, 1); group->id = group_id; uidb_put(itemdb_group, group->id, group); } // Must item (rand_group == 0), place it here if (!rand_group) { RECREATE(group->must, struct s_item_group_entry, group->must_qty+1); group->must[group->must_qty++] = entry; // If 'must' item isn't set as random item, skip the next process if (!prob) { entries++; continue; } rand_group = 0; }