/*========================================== * チャットルームの持ち主を譲る *------------------------------------------ */ void chat_changechatowner(struct map_session_data *sd, const char *nextownername) { struct chat_data *cd; struct map_session_data *tmp_sd; int i,nextowner; nullpo_retv(sd); cd = map_id2cd(sd->chatID); if(cd == NULL || &sd->bl != (*cd->owner)) return; nextowner = -1; for(i = 1; i < cd->users; i++) { if(strncmp(cd->usersd[i]->status.name, nextownername, 24) == 0) { nextowner = i; break; } } if(nextowner < 0) // そんな人は居ない return; clif_changechatowner(cd,cd->usersd[nextowner]); // 一旦消す clif_clearchat(cd,-1); // userlistの順番変更 (0が所有者なので) if( (tmp_sd = cd->usersd[0]) == NULL ) return; //ありえるのかな? cd->usersd[0] = cd->usersd[nextowner]; cd->usersd[nextowner] = tmp_sd; // 新しい所有者の位置へ変更 cd->bl.x = cd->usersd[0]->bl.x; cd->bl.y = cd->usersd[0]->bl.y; // 再度表示 clif_dispchat(cd,-1); return; }
/// logs item transactions (generic) void log_pick(int id, int16 m, e_log_pick_type type, int amount, struct item* itm) { nullpo_retv(itm); if( ( log_config.enable_logs&type ) == 0 ) {// disabled return; } if( !should_log_item(itm->nameid, amount, itm->refine) ) return; //we skip logging this item set - it doesn't meet our logging conditions [Lupus] if( log_config.sql_logs ) { #ifdef BETA_THREAD_TEST char entry[512]; int e_length = 0; e_length = sprintf(entry, LOG_QUERY " INTO `%s` (`time`, `char_id`, `type`, `nameid`, `amount`, `refine`, `card0`, `card1`, `card2`, `card3`, `map`, `unique_id`, `bound`) VALUES (NOW(), '%d', '%c', '%hu', '%d', '%d', '%hu', '%hu', '%hu', '%hu', '%s', '%"PRIu64"', '%d')", log_config.log_pick, id, log_picktype2char(type), itm->nameid, amount, itm->refine, itm->card[0], itm->card[1], itm->card[2], itm->card[3], map[m].name?map[m].name:"", itm->unique_id, itm->bound); queryThread_log(entry,e_length); #else if( SQL_ERROR == Sql_Query(logmysql_handle, LOG_QUERY " INTO `%s` (`time`, `char_id`, `type`, `nameid`, `amount`, `refine`, `card0`, `card1`, `card2`, `card3`, `map`, `unique_id`, `bound`) VALUES (NOW(), '%d', '%c', '%hu', '%d', '%d', '%hu', '%hu', '%hu', '%hu', '%s', '%"PRIu64"', '%d')", log_config.log_pick, id, log_picktype2char(type), itm->nameid, amount, itm->refine, itm->card[0], itm->card[1], itm->card[2], itm->card[3], map[m].name?map[m].name:"", itm->unique_id, itm->bound) ) { Sql_ShowDebug(logmysql_handle); return; } #endif } else { char timestring[255]; time_t curtime; FILE* logfp; if( ( logfp = fopen(log_config.log_pick, "a") ) == NULL ) return; time(&curtime); strftime(timestring, sizeof(timestring), "%m/%d/%Y %H:%M:%S", localtime(&curtime)); fprintf(logfp,"%s - %d\t%c\t%hu,%d,%d,%hu,%hu,%hu,%hu,%s,'%"PRIu64"',%d\n", timestring, id, log_picktype2char(type), itm->nameid, amount, itm->refine, itm->card[0], itm->card[1], itm->card[2], itm->card[3], map[m].name?map[m].name:"", itm->unique_id, itm->bound); fclose(logfp); } }
/// logs messages passed to script command 'logmes' void log_npc (struct map_session_data *sd, const char *message) { nullpo_retv (sd); if (!log_config.npc) return; if (log_config.sql_logs) { #ifdef BETA_THREAD_TEST char entry[512]; int e_length = 0; e_length = sprintf (entry, LOG_QUERY " INTO `%s` (`npc_date`, `account_id`, `char_id`, `char_name`, `map`, `mes`) VALUES (NOW(), '%d', '%d', '%s', '%s', '%s')", log_config.log_npc, sd->status.account_id, sd->status.char_id, sd->status.name, mapindex_id2name (sd->mapindex), message); queryThread_log (entry, e_length); #else SqlStmt *stmt; stmt = SqlStmt_Malloc (logmysql_handle); if (SQL_SUCCESS != SqlStmt_Prepare (stmt, LOG_QUERY " INTO `%s` (`npc_date`, `account_id`, `char_id`, `char_name`, `map`, `mes`) VALUES (NOW(), '%d', '%d', ?, '%s', ?)", log_config.log_npc, sd->status.account_id, sd->status.char_id, mapindex_id2name (sd->mapindex)) || SQL_SUCCESS != SqlStmt_BindParam (stmt, 0, SQLDT_STRING, sd->status.name, strnlen (sd->status.name, NAME_LENGTH)) || SQL_SUCCESS != SqlStmt_BindParam (stmt, 1, SQLDT_STRING, (char *) message, safestrnlen (message, 255)) || SQL_SUCCESS != SqlStmt_Execute (stmt)) { SqlStmt_ShowDebug (stmt); SqlStmt_Free (stmt); return; } SqlStmt_Free (stmt); #endif } else { char timestring[255]; time_t curtime; FILE *logfp; if ( (logfp = fopen (log_config.log_npc, "a")) == NULL) return; time (&curtime); strftime (timestring, sizeof (timestring), "%m/%d/%Y %H:%M:%S", localtime (&curtime)); fprintf (logfp, "%s - %s[%d]: %s\n", timestring, sd->status.name, sd->status.account_id, message); fclose (logfp); } }
/** * Perform requested action from selected homunculus menu * @param sd * @param type */ void hom_menu(struct map_session_data *sd, int type) { nullpo_retv(sd); if (sd->hd == NULL) return; switch(type) { case 0: break; case 1: hom_food(sd, sd->hd); break; case 2: hom_delete(sd->hd, -1); break; default: ShowError("hom_menu : unknown menu choice : %d\n", type); break; } }
/** * Player request a shop's item list (a player shop) * @param sd : player requestion the list * @param id : vender account id (gid) */ void vending_vendinglistreq(struct map_session_data* sd, int id) { struct map_session_data* vsd; nullpo_retv(sd); if( (vsd = map_id2sd(id)) == NULL ) return; if( !vsd->state.vending ) return; // not vending if (!pc_can_give_items(sd) || !pc_can_give_items(vsd)) //check if both GMs are allowed to trade { // GM is not allowed to trade clif_displaymessage(sd->fd, msg_txt(sd,246)); return; } sd->vended_id = vsd->vender_id; // register vending uid clif_vendinglist(sd, id, vsd->vending); }
/** * Close buying store and clear buying store data from tables * @param sd */ void buyingstore_close(struct map_session_data* sd) { nullpo_retv(sd); if( sd->state.buyingstore ) { if( Sql_Query( mmysql_handle, "DELETE FROM `%s` WHERE buyingstore_id = %d;", buyingstore_items_db, sd->buyer_id ) != SQL_SUCCESS || Sql_Query( mmysql_handle, "DELETE FROM `%s` WHERE `id` = %d;", buyingstores_db, sd->buyer_id ) != SQL_SUCCESS ) { Sql_ShowDebug(mmysql_handle); } sd->state.buyingstore = false; sd->buyer_id = 0; memset(&sd->buyingstore, 0, sizeof(sd->buyingstore)); idb_remove(buyingstore_db, sd->status.char_id); // notify other players clif_buyingstore_disappear_entry(sd); } }
/*========================================== * 取引要請 *------------------------------------------ */ void trade_tradeack(struct map_session_data *sd, unsigned char type) { struct map_session_data *target_sd; nullpo_retv(sd); // possible types: 3: trade ok., 4: trade canceled. if (type != 3 && type != 4) return; if(sd->npc_id != 0) npc_event_dequeue(sd); target_sd = map_id2sd(sd->trade.partner); if(target_sd && target_sd->bl.prev) { if(sd->bl.m != target_sd->bl.m || unit_distance(&sd->bl, &target_sd->bl) > 2) { trade_tradecancel(sd); return; } if(sd->state.storage_flag || target_sd->state.storage_flag) { trade_tradecancel(target_sd); trade_tradecancel(sd); return; } clif_tradestart(target_sd,type); clif_tradestart(sd,type); if(type == 4) { // Cancel sd->state.deal_locked = 0; sd->state.deal_mode = 0; sd->trade.partner = 0; target_sd->state.deal_locked = 0; target_sd->state.deal_mode = 0; target_sd->trade.partner = 0; } else { sd->state.deal_mode = 1; target_sd->state.deal_mode = 1; } } return; }
/*========================================== * 取引要請を相手に送る *------------------------------------------ */ void trade_traderequest(struct map_session_data *sd, int target_id) { struct map_session_data *target_sd; int level; nullpo_retv(sd); if (map[sd->bl.m].flag.notrade) { clif_displaymessage (sd->fd, msg_txt(272)); return; //Can't trade in notrade mapflag maps. } if ((target_sd = map_id2sd(target_id)) != NULL) { if (!battle_config.invite_request_check) { if (target_sd->guild_invite > 0 || target_sd->party_invite > 0) { clif_tradestart(sd, 2); // 相手はPT要請中かGuild要請中 return; } } level = pc_isGM(sd); if ( pc_can_give_items(level) || pc_can_give_items(pc_isGM(target_sd)) ) //check if both GMs are allowed to trade { clif_displaymessage(sd->fd, msg_txt(246)); trade_tradecancel(sd); // GM is not allowed to trade } else if ((target_sd->trade_partner != 0) || (sd->trade_partner != 0)) { trade_tradecancel(sd); // person is in another trade } else { //Fixed. Only real GMs can request trade from far away! [Lupus] if (level < lowest_gm_level && (sd->bl.m != target_sd->bl.m || (sd->bl.x - target_sd->bl.x <= -5 || sd->bl.x - target_sd->bl.x >= 5) || (sd->bl.y - target_sd->bl.y <= -5 || sd->bl.y - target_sd->bl.y >= 5))) { clif_tradestart(sd, 0); // too far } else if (sd != target_sd) { target_sd->trade_partner = sd->status.account_id; sd->trade_partner = target_sd->status.account_id; clif_traderequest(target_sd, sd->status.name); } } } else { clif_tradestart(sd, 1); // character does not exist } }
/** * Get from Storage to the Cart inventory * @param sd : player * @param index : storage index to take the item from * @param amount : number of item to take * @return 0:fail, 1:success */ void storage_storagegettocart(struct map_session_data* sd, int index, int amount) { unsigned char flag; nullpo_retv(sd); if( index < 0 || index >= sd->storage_size ) return; if( sd->status.storage.items[index].nameid <= 0 ) return; //Nothing there. if( amount < 1 || amount > sd->status.storage.items[index].amount ) return; if( (flag = pc_cart_additem(sd,&sd->status.storage.items[index],amount,LOG_TYPE_STORAGE)) == 0 ) storage_delitem(sd,index,amount); else { clif_storageitemremoved(sd,index,0); clif_cart_additem_ack(sd,(flag==1)?ADDITEM_TO_CART_FAIL_WEIGHT:ADDITEM_TO_CART_FAIL_COUNT); } }
/*========================================== * チャットルームから蹴り出す *------------------------------------------ */ void chat_kickchat(struct map_session_data *sd, const char *kickusername) { struct chat_data *cd; int i; nullpo_retv(sd); cd = map_id2cd(sd->chatID); if(cd == NULL || &sd->bl != (*cd->owner)) return; for(i = 0; i < cd->users; i++) { if(strncmp(cd->usersd[i]->status.name, kickusername, 24) == 0) { linkdb_insert(&cd->ban_list, INT2PTR(cd->usersd[i]->status.char_id), INT2PTR(1)); chat_leavechat(cd->usersd[i], 1); break; } } return; }
// 同じマップのパーティメンバー全体に処理をかける // type==0 同じマップ // !=0 画面内 void party_foreachsamemap(std::function<void(dumb_ptr<block_list>)> func, dumb_ptr<map_session_data> sd, int type) { struct party *p; int i; int x0, y0, x1, y1; dumb_ptr<map_session_data> list[MAX_PARTY]; int blockcount = 0; nullpo_retv(sd); if ((p = party_search(sd->status.party_id)) == NULL) return; x0 = sd->bl_x - AREA_SIZE; y0 = sd->bl_y - AREA_SIZE; x1 = sd->bl_x + AREA_SIZE; y1 = sd->bl_y + AREA_SIZE; for (i = 0; i < MAX_PARTY; i++) { struct party_member *m = &p->member[i]; if (m->sd != NULL) { if (sd->bl_m != m->sd->bl_m) continue; if (type != 0 && (m->sd->bl_x < x0 || m->sd->bl_y < y0 || m->sd->bl_x > x1 || m->sd->bl_y > y1)) continue; list[blockcount++] = dumb_ptr<map_session_data>(m->sd); } } MapBlockLock lock; for (i = 0; i < blockcount; i++) if (list[i]->bl_prev) // 有効かどうかチェック func(list[i]); }
/*========================================== * ギルド倉庫へカートから入れる *------------------------------------------ */ void storage_guild_storageaddfromcart(struct map_session_data *sd, int idx, int amount) { struct guild_storage *stor; nullpo_retv(sd); if((stor = (struct guild_storage *)numdb_search(guild_storage_db,sd->status.guild_id)) == NULL) return; if(!stor->storage_status) return; if(idx < 0 || idx >= MAX_CART) return; if(itemdb_isguildstorageable(sd->status.cart[idx].nameid) == 0) return; if(amount < 1 || amount > sd->status.cart[idx].amount) return; if(storage_guild_additem(sd, stor, &sd->status.cart[idx], amount) == 0) pc_cart_delitem(sd, idx, amount, 0); return; }
/*========================================== * アイテム追加完了(ok押し) *------------------------------------------ */ void trade_tradeok(struct map_session_data *sd) { struct map_session_data *target_sd; nullpo_retv(sd); target_sd = map_id2sd(sd->trade.partner); if(target_sd && target_sd->bl.prev) { if (sd->bl.m != target_sd->bl.m || unit_distance(&sd->bl, &target_sd->bl) > 2) { trade_tradecancel(sd); return; } sd->state.deal_locked = 1; clif_tradeitemok(sd,0,0); clif_tradedeal_lock(sd,0); clif_tradedeal_lock(target_sd,1); } else { trade_tradecancel(sd); } return; }
/*========================================== * Adds the specified amount of zeny to the trade window *------------------------------------------*/ void trade_tradeaddzeny (struct map_session_data *sd, int amount) { struct map_session_data *target_sd; nullpo_retv (sd); if (!sd->state.trading || sd->state.deal_locked > 0) return; //Can't add stuff. if ( (target_sd = map_id2sd (sd->trade_partner)) == NULL) { trade_tradecancel (sd); return; } if (amount < 0 || amount > sd->status.zeny || amount > MAX_ZENY - target_sd->status.zeny) { // invalid values, no appropriate packet for it => abort trade_tradecancel (sd); return; } sd->deal.zeny = amount; clif_tradeadditem (sd, target_sd, 0, amount); }
/*========================================== * ギルド倉庫からカートへ出す *------------------------------------------ */ void storage_guild_storagegettocart(struct map_session_data *sd, int idx, int amount) { struct guild_storage *stor; nullpo_retv(sd); if((stor = (struct guild_storage *)numdb_search(guild_storage_db,sd->status.guild_id)) == NULL) return; if(!stor->storage_status) return; if(idx < 0 || idx >= MAX_GUILD_STORAGE) return; if(itemdb_iscartable(stor->store_item[idx].nameid) == 0) // カートへ出せるかチェック return; if(amount < 1 || amount > stor->store_item[idx].amount) return; if(pc_cart_additem(sd, &stor->store_item[idx], amount) == 0) storage_guild_delitem(sd, stor, idx, amount); return; }
/// Set the tick counter. /// If the timer was active, this means stopping and restarting the timer. /// Note: active includes expired. void npc_settimerevent_tick(dumb_ptr<npc_data_script> nd, interval_t newtimer) { nullpo_retv(nd); if (nd->scr.timer_eventv.empty()) return; if (newtimer > nd->scr.timer_eventv.back().timer) newtimer = nd->scr.timer_eventv.back().timer; if (newtimer < interval_t::zero()) newtimer = interval_t::zero(); if (newtimer == nd->scr.timer) return; bool flag = nd->scr.timer_active; if (flag) npc_timerevent_stop(nd); nd->scr.timer = newtimer; npc_timerevent_calc_next(nd); if (flag) npc_timerevent_start(nd); }
void pincode_decrypt(unsigned int userSeed, char* pin) { int i; char tab[10] = {0,1,2,3,4,5,6,7,8,9}; nullpo_retv(pin); for (i = 1; i < 10; i++) { int pos; userSeed = pincode->baseSeed + userSeed * pincode->multiplier; pos = userSeed % (i + 1); if( i != pos ){ tab[i] ^= tab[pos]; tab[pos] ^= tab[i]; tab[i] ^= tab[pos]; } } for( i = 0; i < 4; i++ ){ pin[i] = tab[pin[i] - '0']; } sprintf(pin, "%d%d%d%d", pin[0], pin[1], pin[2], pin[3]); }
/// logs used GM commands void log_atcommand(struct map_session_data* sd, int cmdlvl, const char* message) { nullpo_retv(sd); if( cmdlvl < log_config.gm ) return; #ifndef TXT_ONLY if( log_config.sql_logs ) { SqlStmt* stmt; stmt = SqlStmt_Malloc(logmysql_handle); if( SQL_SUCCESS != SqlStmt_Prepare(stmt, "INSERT DELAYED INTO `%s` (`atcommand_date`, `account_id`, `char_id`, `char_name`, `map`, `command`) VALUES (NOW(), '%d', '%d', ?, '%s', ?)", log_config.log_gm, sd->status.account_id, sd->status.char_id, mapindex_id2name(sd->mapindex) ) || SQL_SUCCESS != SqlStmt_BindParam(stmt, 0, SQLDT_STRING, sd->status.name, strnlen(sd->status.name, NAME_LENGTH)) || SQL_SUCCESS != SqlStmt_BindParam(stmt, 1, SQLDT_STRING, (char*)message, safestrnlen(message, 255)) || SQL_SUCCESS != SqlStmt_Execute(stmt) ) { SqlStmt_ShowDebug(stmt); SqlStmt_Free(stmt); return; } SqlStmt_Free(stmt); } else #endif { char timestring[255]; time_t curtime; FILE* logfp; if( ( logfp = fopen(log_config.log_gm, "a") ) == NULL ) return; time(&curtime); strftime(timestring, sizeof(timestring), "%m/%d/%Y %H:%M:%S", localtime(&curtime)); fprintf(logfp, "%s - %s[%d]: %s\n", timestring, sd->status.name, sd->status.account_id, message); fclose(logfp); } }
/** [Cydh] * Gives item(s) to the player based on item group * @param sd: Player that obtains item from item group * @param group_id: The group ID of item that obtained by player * @param *group: struct s_item_group from itemgroup_db[group_id].random[idx] or itemgroup_db[group_id].must[sub_group][idx] */ static void itemdb_pc_get_itemgroup_sub(struct map_session_data *sd, struct s_item_group_entry *data) { uint16 i; struct item tmp; nullpo_retv(data); memset(&tmp, 0, sizeof(tmp)); tmp.nameid = data->nameid; tmp.amount = (itemdb_isstackable(data->nameid)) ? data->amount : 1; tmp.bound = data->bound; tmp.identify = 1; tmp.expire_time = (data->duration) ? (unsigned int)(time(NULL) + data->duration*60) : 0; if (data->isNamed) { tmp.card[0] = itemdb_isequip(data->nameid) ? CARD0_FORGE : CARD0_CREATE; tmp.card[1] = 0; tmp.card[2] = GetWord(sd->status.char_id, 0); tmp.card[3] = GetWord(sd->status.char_id, 1); } // Do loop for non-stackable item for (i = 0; i < data->amount; i++) { char flag = 0; #ifdef ENABLE_ITEM_GUID tmp.unique_id = data->GUID ? pc_generate_unique_id(sd) : 0; // Generate UID #endif if ((flag = pc_additem(sd, &tmp, tmp.amount, LOG_TYPE_SCRIPT))) clif_additem(sd, 0, 0, flag); else if (!flag && data->isAnnounced) { char output[CHAT_SIZE_MAX]; sprintf(output, msg_txt(NULL, 717), sd->status.name, itemdb_jname(data->nameid), itemdb_jname(sd->itemid)); //! TODO: Move this broadcast to proper packet intif_broadcast(output, strlen(output) + 1, BC_DEFAULT); //clif_broadcast_obtain_special_item(); } if (itemdb_isstackable(data->nameid)) break; } }
/** * Creates a new console command entry. * * @param name The command name. * @param func The command callback. */ void console_parse_create(char *name, CParseFunc func) { int i; char *tok; char sublist[CP_CMD_LENGTH * 5]; struct CParseEntry *cmd; nullpo_retv(name); safestrncpy(sublist, name, CP_CMD_LENGTH * 5); tok = strtok(sublist,":"); ARR_FIND(0, VECTOR_LENGTH(console->input->command_list), i, strcmpi(tok, VECTOR_INDEX(console->input->command_list, i)->cmd) == 0); if (i == VECTOR_LENGTH(console->input->command_list)) { CREATE(cmd, struct CParseEntry, 1); safestrncpy(cmd->cmd, tok, CP_CMD_LENGTH); cmd->type = CPET_UNKNOWN; VECTOR_ENSURE(console->input->commands, 1, 1); VECTOR_PUSH(console->input->commands, cmd); VECTOR_ENSURE(console->input->command_list, 1, 1); VECTOR_PUSH(console->input->command_list, cmd); }
/// logs MVP monster rewards void log_mvpdrop(struct map_session_data* sd, int monster_id, unsigned int* log_mvp) { nullpo_retv(sd); if( !log_config.mvpdrop ) return; if( log_config.sql_logs ) { #ifdef BETA_THREAD_TEST char entry[512]; int e_length = 0; e_length = sprintf(entry, LOG_QUERY " INTO `%s` (`mvp_date`, `kill_char_id`, `monster_id`, `prize`, `mvpexp`, `map`) VALUES (NOW(), '%d', '%d', '%hu', '%u', '%s') ", log_config.log_mvpdrop, sd->status.char_id, monster_id, (unsigned short)log_mvp[0], log_mvp[1], mapindex_id2name(sd->mapindex)); queryThread_log(entry,e_length); #else if( SQL_ERROR == Sql_Query(logmysql_handle, LOG_QUERY " INTO `%s` (`mvp_date`, `kill_char_id`, `monster_id`, `prize`, `mvpexp`, `map`) VALUES (NOW(), '%d', '%d', '%hu', '%u', '%s') ", log_config.log_mvpdrop, sd->status.char_id, monster_id, (unsigned short)log_mvp[0], log_mvp[1], mapindex_id2name(sd->mapindex)) ) { Sql_ShowDebug(logmysql_handle); return; } #endif } else { char timestring[255]; time_t curtime; FILE* logfp; if( ( logfp = fopen(log_config.log_mvpdrop,"a") ) == NULL ) return; time(&curtime); strftime(timestring, sizeof(timestring), "%m/%d/%Y %H:%M:%S", localtime(&curtime)); fprintf(logfp,"%s - %s[%d:%d]\t%d\t%hu,%u\n", timestring, sd->status.name, sd->status.account_id, sd->status.char_id, monster_id, (unsigned short)log_mvp[0], log_mvp[1]); fclose(logfp); } }
/// logs zeny transactions void log_zeny(struct map_session_data* sd, e_log_pick_type type, struct map_session_data* src_sd, int amount) { nullpo_retv(sd); if( !log_config.zeny || ( log_config.zeny != 1 && abs(amount) < log_config.zeny ) ) return; if( log_config.sql_logs ) { #ifdef BETA_THREAD_TEST char entry[512]; int e_length = 0; e_length = sprintf(entry, LOG_QUERY " INTO `%s` (`time`, `char_id`, `src_id`, `type`, `amount`, `map`) VALUES (NOW(), '%d', '%d', '%c', '%d', '%s')", log_config.log_zeny, sd->status.char_id, src_sd->status.char_id, log_picktype2char(type), amount, mapindex_id2name(sd->mapindex)); queryThread_log(entry,e_length); #else if( SQL_ERROR == Sql_Query(logmysql_handle, LOG_QUERY " INTO `%s` (`time`, `char_id`, `src_id`, `type`, `amount`, `map`) VALUES (NOW(), '%d', '%d', '%c', '%d', '%s')", log_config.log_zeny, sd->status.char_id, src_sd->status.char_id, log_picktype2char(type), amount, mapindex_id2name(sd->mapindex)) ) { Sql_ShowDebug(logmysql_handle); return; } #endif } else { char timestring[255]; time_t curtime; FILE* logfp; if( ( logfp = fopen(log_config.log_zeny, "a") ) == NULL ) return; time(&curtime); strftime(timestring, sizeof(timestring), "%m/%d/%Y %H:%M:%S", localtime(&curtime)); fprintf(logfp, "%s - %s[%d]\t%s[%d]\t%d\t\n", timestring, src_sd->status.name, src_sd->status.account_id, sd->status.name, sd->status.account_id, amount); fclose(logfp); } }
/// logs items, that summon monsters void log_branch (struct map_session_data *sd) { nullpo_retv (sd); if (!log_config.branch) return; if (log_config.sql_logs) { SqlStmt *stmt; stmt = SqlStmt_Malloc (logmysql_handle); if (SQL_SUCCESS != SqlStmt_Prepare (stmt, "INSERT DELAYED INTO `%s` (`branch_date`, `account_id`, `char_id`, `char_name`, `map`) VALUES (NOW(), '%d', '%d', ?, '%s')", log_config.log_branch, sd->status.account_id, sd->status.char_id, mapindex_id2name (sd->mapindex)) || SQL_SUCCESS != SqlStmt_BindParam (stmt, 0, SQLDT_STRING, sd->status.name, strnlen (sd->status.name, NAME_LENGTH)) || SQL_SUCCESS != SqlStmt_Execute (stmt)) { SqlStmt_ShowDebug (stmt); SqlStmt_Free (stmt); return; } SqlStmt_Free (stmt); } else { char timestring[255]; time_t curtime; FILE *logfp; if ( (logfp = fopen (log_config.log_branch, "a")) == NULL) return; time (&curtime); strftime (timestring, sizeof (timestring), "%m/%d/%Y %H:%M:%S", localtime (&curtime)); fprintf (logfp, "%s - %s[%d:%d]\t%s\n", timestring, sd->status.name, sd->status.account_id, sd->status.char_id, mapindex_id2name (sd->mapindex)); fclose (logfp); } }
/*========================================== * ステートメントのclose *------------------------------------------ */ void sqldbs_stmt_close(struct sqldbs_stmt *st) { nullpo_retv(st); sqldbs_stmt_free_result(st); mysql_stmt_close(st->stmt); if(st->handle) linkdb_erase(&st->handle->stmt_list, st); if(st->params) { aFree(st->params); } if(st->columns) { aFree(st->columns); } if(st->query) { aFree(st->query); } aFree(st); return; }
/*========================================== * ギルド倉庫から出す *------------------------------------------ */ void storage_guild_storageget(struct map_session_data *sd, int idx, int amount) { struct guild_storage *stor; int flag; nullpo_retv(sd); if((stor = (struct guild_storage *)numdb_search(guild_storage_db,sd->status.guild_id)) == NULL) return; if(!stor->storage_status) return; if(idx < 0 || idx >= MAX_GUILD_STORAGE) return; if(amount < 1 || amount > stor->store_item[idx].amount) return; if((flag = pc_additem(sd,&stor->store_item[idx],amount)) == 0) storage_guild_delitem(sd, stor, idx, amount); else clif_additem(sd,0,0,flag); return; }
/** * Add an item to the storage from the inventory. * @param sd : player * @param index : inventory index to take the item from * @param amount : number of item to take * @return 0:fail, 1:success */ void storage_storageadd(struct map_session_data* sd, int index, int amount) { nullpo_retv(sd); if( sd->status.storage.storage_amount > sd->storage_size ) return; // storage full if( index < 0 || index >= MAX_INVENTORY ) return; if( sd->status.inventory[index].nameid <= 0 ) return; // No item on that spot if( amount < 1 || amount > sd->status.inventory[index].amount ) return; if( storage_additem(sd,&sd->status.inventory[index],amount) == 0 ) pc_delitem(sd,index,amount,0,4,LOG_TYPE_STORAGE); else { clif_storageitemremoved(sd,index,0); clif_dropitem(sd,index,0); } }
/** * Move an item from cart to storage. * @param sd : player * @param index : cart index to take the item from * @param amount : number of item to take * @return 0:fail, 1:success */ void storage_storageaddfromcart(struct map_session_data* sd, int index, int amount) { nullpo_retv(sd); if( sd->status.storage.storage_amount > sd->storage_size ) return; // storage full / storage closed if( index < 0 || index >= MAX_CART ) return; if( sd->status.cart[index].nameid <= 0 ) return; //No item there. if( amount < 1 || amount > sd->status.cart[index].amount ) return; if( storage_additem(sd,&sd->status.cart[index],amount) == 0 ) pc_cart_delitem(sd,index,amount,0,LOG_TYPE_STORAGE); else { clif_storageitemremoved(sd,index,0); clif_dropitem(sd,index,0); } }
/*========================================== * 取引キャンセル *------------------------------------------ */ void trade_tradecancel(struct map_session_data *sd) { struct map_session_data *target_sd; int trade_i; nullpo_retv(sd); if ((target_sd = map_id2sd(sd->trade_partner)) != NULL) { for(trade_i = 0; trade_i < 10; trade_i++) { // give items back (only virtual) if (sd->deal.item[trade_i].amount != 0) { clif_additem(sd, sd->deal.item[trade_i].index, sd->deal.item[trade_i].amount, 0); sd->deal.item[trade_i].index = 0; sd->deal.item[trade_i].amount = 0; } if (target_sd->deal.item[trade_i].amount != 0) { clif_additem(target_sd, target_sd->deal.item[trade_i].index, target_sd->deal.item[trade_i].amount, 0); target_sd->deal.item[trade_i].index = 0; target_sd->deal.item[trade_i].amount = 0; } } if (sd->deal.zeny) { clif_updatestatus(sd, SP_ZENY); sd->deal.zeny = 0; } if (target_sd->deal.zeny) { clif_updatestatus(target_sd, SP_ZENY); target_sd->deal.zeny = 0; } sd->state.deal_locked = 0; sd->trade_partner = 0; sd->state.trading = 0; target_sd->state.deal_locked = 0; target_sd->trade_partner = 0; target_sd->state.trading = 0; clif_tradecancelled(sd); clif_tradecancelled(target_sd); } }
/** [Cydh] * Gives item(s) to the player based on item group * @param sd: Player that obtains item from item group * @param group_id: The group ID of item that obtained by player * @param *group: struct s_item_group from itemgroup_db[group_id].random[idx] or itemgroup_db[group_id].must[sub_group][idx] */ static void itemdb_pc_get_itemgroup_sub(struct map_session_data *sd, struct s_item_group_entry *data) { uint16 i, get_amt = 0; struct item tmp; nullpo_retv(data); memset(&tmp, 0, sizeof(tmp)); tmp.nameid = data->nameid; tmp.bound = data->bound; tmp.identify = 1; tmp.expire_time = (data->duration) ? (unsigned int)(time(NULL) + data->duration*60) : 0; if (data->isNamed) { tmp.card[0] = itemdb_isequip(data->nameid) ? CARD0_FORGE : CARD0_CREATE; tmp.card[1] = 0; tmp.card[2] = GetWord(sd->status.char_id, 0); tmp.card[3] = GetWord(sd->status.char_id, 1); } if (!itemdb_isstackable(data->nameid)) get_amt = 1; else get_amt = data->amount; // Do loop for non-stackable item for (i = 0; i < data->amount; i += get_amt) { char flag = 0; tmp.unique_id = data->GUID ? pc_generate_unique_id(sd) : 0; // Generate GUID if ((flag = pc_additem(sd, &tmp, get_amt, LOG_TYPE_SCRIPT))) { clif_additem(sd, 0, 0, flag); if (pc_candrop(sd, &tmp)) map_addflooritem(&tmp, tmp.amount, sd->bl.m, sd->bl.x,sd->bl.y, 0, 0, 0, 0, 0); } else if (!flag && data->isAnnounced) intif_broadcast_obtain_special_item(sd, data->nameid, sd->itemid, ITEMOBTAIN_TYPE_BOXITEM); } }
void log_npc_shop_sub_sql (struct map_session_data* sd,char * name, struct item* itm , int unit_cost, int amount, int type){ char ip_sd[20], action[5]; struct item_data* idata = itemdb->exists(itm->nameid); nullpo_retv(idata); pc->get_ip(sd,ip_sd); if(!logs->should_log_item(itm->nameid, amount, itm->refine, idata)) return; switch(type){ case LOG_ACTION_GET: strcpy(action,"Buy"); break; case LOG_ACTION_DROP: strcpy(action,"Sell"); break; default: strcpy(action,"Unknown"); break; } if( SQL_ERROR == SQL->Query(logs->mysql_handle, LOG_QUERY " INTO `npcshop_log`" "(`Date`, `Mapname`," "`NPC_Name`,`Player_CharID`,`Player_Name`,`Player_IP`,`Player_PosX`,`Player_PosY`,`Player_Action`," "`ItemID`,`ItemName`,`Amount`,`Unit_Cost`,`Total_Cost`,`ItemSerial`," "`Slots`,`ItemRefiningLevel`)" "VALUES (NOW(),'%s','%s', '%d','%s','%s','%d','%d','%s'," "'%d','%s','%d','%d','%d','%"PRIu64"'," "'%d','%d')", mapindex_id2name(sd->mapindex),name, sd->status.char_id,sd->status.name,ip_sd,sd->bl.x, sd->bl.y,action, itm->nameid,idata->name,amount,unit_cost,amount*unit_cost,itm->unique_id, idata->slot,itm->refine)) { Sql_ShowDebug(logs->mysql_handle); return; } }