/*========================================== * timer関数 * 今このmap鯖に繋がっているクライアント人数をchar鯖へ送る *------------------------------------------*/ int send_users_tochar(void) { int users = 0, i = 0; struct map_session_data* sd; struct s_mapiterator* iter; chrif_check(-1); // get user count (TODO: improve this) iter = mapit_getallusers(); for( mapit_first(iter); mapit_exists(iter); mapit_next(iter) ) users++; mapit_free(iter); // build the packet WFIFOHEAD(char_fd, 6+8*users); WFIFOW(char_fd,0) = 0x2aff; iter = mapit_getallusers(); for( sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); sd = (TBL_PC*)mapit_next(iter) ) { WFIFOL(char_fd,6+8*i) = sd->status.account_id; WFIFOL(char_fd,6+8*i+4) = sd->status.char_id; i++; } mapit_free(iter); WFIFOW(char_fd,2) = 6 + 8*users; WFIFOW(char_fd,4) = users; WFIFOSET(char_fd, 6+8*users); return 0; }
// 所属キャラの確認 int guild_check_member(struct guild *g) { int i; struct map_session_data *sd; struct s_mapiterator* iter; nullpo_ret(g); iter = mapit_getallusers(); for( sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); sd = (TBL_PC*)mapit_next(iter) ) { if( sd->status.guild_id != g->guild_id ) continue; i = guild_getindex(g,sd->status.account_id,sd->status.char_id); if (i < 0) { sd->status.guild_id=0; sd->guild_emblem_id=0; ShowWarning("guild: check_member %d[%s] is not member\n",sd->status.account_id,sd->status.name); } } mapit_free(iter); return 0; }
/// Checks if each char having a party actually belongs to that party. /// If check fails, the char gets marked as 'not in a party'. int party_check_member(struct party *p) { int i; struct map_session_data *sd; struct s_mapiterator* iter; nullpo_retr(0, p); iter = mapit_getallusers(); for( sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); sd = (TBL_PC*)mapit_next(iter) ) { if( sd->status.party_id != p->party_id ) continue; ARR_FIND( 0, MAX_PARTY, i, p->member[i].account_id == sd->status.account_id && p->member[i].char_id == sd->status.char_id ); if( i == MAX_PARTY ) { ShowWarning("party_check_member: '%s' (acc:%d) is not member of party '%s' (id:%d)\n",sd->status.name,sd->status.account_id,p->name,p->party_id); sd->status.party_id = 0; } } mapit_free(iter); return 0; }
void itemdb_reload(void) { struct s_mapiterator* iter; struct map_session_data* sd; int i; itemdb_save_serials(); // Store lastest serials // clear the previous itemdb data for( i = 0; i < ARRAYLENGTH(itemdb_array); ++i ) if( itemdb_array[i] ) destroy_item_data(itemdb_array[i], 1); itemdb_other->clear(itemdb_other, itemdb_final_sub); memset(itemdb_array, 0, sizeof(itemdb_array)); // read new data itemdb_read(); // readjust itemdb pointer cache for each player iter = mapit_geteachpc(); for( sd = (struct map_session_data*)mapit_first(iter); mapit_exists(iter); sd = (struct map_session_data*)mapit_next(iter) ) { memset(sd->item_delay, 0, sizeof(sd->item_delay)); // reset item delays pc_setinventorydata(sd); } mapit_free(iter); }
void itemdb_reload(void) { struct s_mapiterator* iter; struct map_session_data* sd; int i,d,k; // clear the previous itemdb data for( i = 0; i < ARRAYLENGTH(itemdb_array); ++i ) if( itemdb_array[i] ) destroy_item_data(itemdb_array[i], 1); itemdb_other->clear(itemdb_other, itemdb_final_sub); memset(itemdb_array, 0, sizeof(itemdb_array)); // read new data itemdb_read(); //Epoque's awesome @reloaditemdb fix - thanks! [Ind] //- Fixes the need of a @reloadmobdb after a @reloaditemdb to re-link monster drop data for( i = 0; i < MAX_MOB_DB; i++ ) { struct mob_db *entry; if( !((i < 1324 || i > 1363) && (i < 1938 || i > 1946)) ) continue; entry = mob_db(i); for(d = 0; d < MAX_MOB_DROP; d++) { struct item_data *id; if( !entry->dropitem[d].nameid ) continue; id = itemdb_search(entry->dropitem[d].nameid); for (k = 0; k < MAX_SEARCH; k++) { if (id->mob[k].chance <= entry->dropitem[d].p) break; } if (k == MAX_SEARCH) continue; if (id->mob[k].id != i) memmove(&id->mob[k+1], &id->mob[k], (MAX_SEARCH-k-1)*sizeof(id->mob[0])); id->mob[k].chance = entry->dropitem[d].p; id->mob[k].id = i; } } // readjust itemdb pointer cache for each player iter = mapit_geteachpc(); for( sd = (struct map_session_data*)mapit_first(iter); mapit_exists(iter); sd = (struct map_session_data*)mapit_next(iter) ) { memset(sd->item_delay, 0, sizeof(sd->item_delay)); // reset item delays pc_setinventorydata(sd); } mapit_free(iter); }
/** * Reload PC Groups * Used in @reloadatcommand * @public */ void pc_groups_reload(void) { struct map_session_data* sd = NULL; struct s_mapiterator* iter; do_final_pc_groups(); do_init_pc_groups(); /* refresh online users permissions */ iter = mapit_getallusers(); for (sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); sd = (TBL_PC*)mapit_next(iter)) { pc_group_pc_load(sd); } mapit_free(iter); }
// 情報所得失敗(そのIDのキャラを全部未所属にする) int guild_recv_noinfo(int guild_id) { struct map_session_data *sd; struct s_mapiterator* iter; iter = mapit_getallusers(); for( sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); sd = (TBL_PC*)mapit_next(iter) ) { if( sd->status.guild_id == guild_id ) sd->status.guild_id = 0; // erase guild } mapit_free(iter); return 0; }
// unused int send_usercount_tochar(int tid, unsigned int tick, int id, int data) { int count = 0; struct s_mapiterator* iter; chrif_check(-1); iter = mapit_getallusers(); for( mapit_first(iter); mapit_exists(iter); mapit_next(iter) ) count++; mapit_free(iter); WFIFOHEAD(char_fd,4); WFIFOW(char_fd,0) = 0x2afe; WFIFOW(char_fd,2) = count; WFIFOSET(char_fd,4); return 0; }
int battleground_countlogin(struct map_session_data *sd, bool check_bat_room) { int c = 0, m = map_mapname2mapid("bat_room"); struct map_session_data* pl_sd; struct s_mapiterator* iter; nullpo_ret(sd); iter = mapit_getallusers(); for( pl_sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); pl_sd = (TBL_PC*)mapit_next(iter) ) { if( !(pl_sd->qd || map[pl_sd->bl.m].flag.battleground || (check_bat_room && pl_sd->bl.m == m)) ) continue; if( session[sd->fd]->client_addr == session[pl_sd->fd]->client_addr ) c++; } mapit_free(iter); return c; }
/*========================================== * Reloads the instance in runtime (reloadscript) *------------------------------------------*/ void do_reload_instance(void) { struct instance_data *im; struct instance_db *db; struct s_mapiterator* iter; struct map_session_data *sd; int i; for( i = 1; i < MAX_INSTANCE_DATA; i++ ) { im = &instance_data[i]; if(!im->cnt_map) continue; else { // First we load the NPCs again instance_addnpc(im); // Create new keep timer if((db = instance_searchtype_db(im->type)) != NULL) im->keep_limit = (unsigned int)time(NULL) + db->limit; } } // Reset player to instance beginning iter = mapit_getallusers(); for( sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); sd = (TBL_PC*)mapit_next(iter) ) if(sd && map[sd->bl.m].instance_id) { struct party_data *p; if(!(p = party_search(sd->status.party_id)) || p->instance_id != map[sd->bl.m].instance_id) // Someone not in party is on instance map continue; im = &instance_data[p->instance_id]; if((db = instance_searchtype_db(im->type)) != NULL && !instance_enter(sd,db->name)) { // All good clif_displaymessage(sd->fd, msg_txt(sd,515)); // Instance has been reloaded instance_reqinfo(sd,p->instance_id); } else // Something went wrong ShowError("do_reload_instance: Error setting character at instance start: character_id=%d instance=%s.\n",sd->status.char_id,db->name); } mapit_free(iter); }
// ギルドエンブレム変更通知 int guild_emblem_changed(int len,int guild_id,int emblem_id,const char *data) { int i; struct map_session_data *sd; struct guild *g=guild_search(guild_id); if(g==NULL) return 0; memcpy(g->emblem_data,data,len); g->emblem_len=len; g->emblem_id=emblem_id; for(i=0;i<g->max_member;i++){ if((sd=g->member[i].sd)!=NULL){ sd->guild_emblem_id=emblem_id; clif_guild_belonginfo(sd,g); clif_guild_emblem(sd,g); clif_guild_emblem_area(&sd->bl); } } {// update guardians (mobs) DBIterator* iter = db_iterator(castle_db); struct guild_castle* gc; for( gc = (struct guild_castle*)dbi_first(iter) ; dbi_exists(iter); gc = (struct guild_castle*)dbi_next(iter) ) { if( gc->guild_id != guild_id ) continue; // update permanent guardians for( i = 0; i < ARRAYLENGTH(gc->guardian); ++i ) { TBL_MOB* md = (gc->guardian[i].id ? map_id2md(gc->guardian[i].id) : NULL); if( md == NULL || md->guardian_data == NULL ) continue; md->guardian_data->emblem_id = emblem_id; clif_guild_emblem_area(&md->bl); } // update temporary guardians for( i = 0; i < gc->temp_guardians_max; ++i ) { TBL_MOB* md = (gc->temp_guardians[i] ? map_id2md(gc->temp_guardians[i]) : NULL); if( md == NULL || md->guardian_data == NULL ) continue; md->guardian_data->emblem_id = emblem_id; clif_guild_emblem_area(&md->bl); } } dbi_destroy(iter); } {// update npcs (flags or other npcs that used flagemblem to attach to this guild) // TODO this is not efficient [FlavioJS] struct s_mapiterator* iter = mapit_geteachnpc(); TBL_NPC* nd; for( nd = (TBL_NPC*)mapit_first(iter) ; mapit_exists(iter); nd = (TBL_NPC*)mapit_next(iter) ) { if( nd->subtype != SCRIPT || nd->u.scr.guild_id != guild_id ) continue; clif_guild_emblem_area(&nd->bl); } mapit_free(iter); } return 0; }
void channel_message(struct map_session_data *sd, const char* channel, const char* message) { struct channel_data *cd; char output[CHAT_SIZE_MAX]; struct map_session_data *p_sd; if( !sd || !message || !*message || strlen(message) < 1 ) return; if( (cd = (struct channel_data *)strdb_get(channel_db, channel)) == NULL ) { clif_displaymessage(sd->fd, msg_txt(805)); clif_displaymessage(sd->fd, msg_txt(815)); return; } if( channel_slot_get(sd,cd) < 0 ) { clif_displaymessage(sd->fd, msg_txt(816)); return; } if( message[0] == '|' && strlen(message) >= 4 && message[3] == '.' ) message += 3; if( message[0] == '.' ) { // Channel commands size_t len = strlen(message); char* option_text; if( !strncasecmp(message, ".item ", 6) && len > 0 && cd->type == CHN_VENDING && server_channel[CHN_VENDING] && vendingbot_timer < gettick() ) { struct map_session_data *pl_sd, *b_sd[MAX_SEARCH]; struct s_mapiterator* iter; struct item_data *item_array[MAX_SEARCH]; int total[MAX_SEARCH], amount[MAX_SEARCH]; unsigned int MinPrice[MAX_SEARCH], MaxPrice[MAX_SEARCH]; int i, j, count = 1; option_text = (char *)message + 6; if( (item_array[0] = itemdb_exists(atoi(option_text))) == NULL ) count = itemdb_searchname_array(item_array, MAX_SEARCH, option_text); if( count < 1 ) { clif_displaymessage(sd->fd, msg_txt(19)); return; } if( count > MAX_SEARCH ) count = MAX_SEARCH; for( i = 0; i < MAX_SEARCH; i++ ) { total[i] = amount[i] = MaxPrice[i] = 0; MinPrice[i] = battle_config.vending_max_value + 1; b_sd[i] = NULL; } iter = mapit_getallusers(); for( pl_sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); pl_sd = (TBL_PC*)mapit_next(iter) ) { if( !pl_sd->vender_id ) continue; for( i = 0; i < pl_sd->vend_num; i++ ) { // Searching in the Vending List for( j = 0; j < count; j++ ) { // Compares with each search result if( pl_sd->status.cart[pl_sd->vending[i].index].nameid != item_array[j]->nameid ) continue; amount[j] += pl_sd->vending[i].amount; total[j]++; if( pl_sd->vending[i].value < MinPrice[j] ) { // Best Price MinPrice[j] = pl_sd->vending[i].value; b_sd[j] = pl_sd; } if( pl_sd->vending[i].value > MaxPrice[j] ) MaxPrice[j] = pl_sd->vending[i].value; } } } mapit_free(iter); for( i = 0; i < count; i++ ) { if( total[i] > 0 && b_sd[i] != NULL ) { sprintf(output, msg_txt(829), server_channel[CHN_VENDING]->name, item_array[i]->jname, MinPrice[i], b_sd[i]->status.name, map[b_sd[i]->bl.m].name, b_sd[i]->bl.x, b_sd[i]->bl.y, MaxPrice[i], total[i], amount[i]); clif_channel_message(cd, output, -1); } } vendingbot_timer = gettick() + 5000; // 5 Seconds Protection from flood } else if( !strncasecmp(message, ".exit", 5) ) channel_leave(sd, cd->name, true); else if( cd->op != sd->bl.id && pc_has_permission(sd,PC_PERM_CHANNEL_OPERATOR) ) return; else if( !strncasecmp(message, ".invite ", 8) && len > 11 ) { // Invite a User to the Channel option_text = (char *)message + 8; if( (p_sd = map_nick2sd(option_text)) == NULL ) clif_displaymessage(sd->fd, msg_txt(893)); else if( p_sd == sd ) clif_displaymessage(sd->fd, msg_txt(894)); else if( p_sd->state.noask ) clif_displaymessage(sd->fd, msg_txt(700)); else if( channel_slot_get(p_sd, cd) >= 0 ) clif_displaymessage(sd->fd, msg_txt(895)); else if( p_sd->channel_invite_timer != INVALID_TIMER ) clif_displaymessage(sd->fd, msg_txt(897)); else { sprintf(output, msg_txt(896), cd->name, sd->status.name, p_sd->status.name); clif_channel_message(cd, output, -1); // Notify about the invitation to the Channel sprintf(output, msg_txt(898), sd->status.name, cd->name); clif_disp_onlyself(p_sd, output, strlen(output)); // Notify Player p_sd->channel_invite_timer = add_timer(gettick() + 30000, channel_invite_timer, p_sd->bl.id, (intptr_t)aStrdup(cd->name)); } } else if( !strncasecmp(message, ".kick ", 6) && len > 9 ) { // Kick Users option_text = (char *)message + 6; if( (p_sd = map_nick2sd(option_text)) == NULL || channel_slot_get(p_sd, cd) < 0 ) clif_displaymessage(sd->fd, msg_txt(817)); else if( p_sd == sd ) clif_displaymessage(sd->fd, msg_txt(818)); else { channel_leave(p_sd, cd->name, false); sprintf(output, msg_txt(819), cd->name, p_sd->status.name); clif_channel_message(cd, output, -1); p_sd->canjoinchn_tick = gettick() + 10000; } } else if( !strncasecmp(message, ".color ", 7) && len > 7 ) { // Set Chat Room Color short color = atoi(message + 7); if( color < 1 || color > 39 ) clif_displaymessage(sd->fd, msg_txt(830)); else { cd->color = channel_color[color - 1]; sprintf(output, msg_txt(831), cd->name); clif_channel_message(cd, output, -1); } } else if( !strncasecmp(message, ".op ", 4) && len > 7 ) { option_text = (char *)message + 4; if( cd->type != CHN_USER ) clif_displaymessage(sd->fd, msg_txt(875)); else if( (p_sd = map_nick2sd(option_text)) == NULL || channel_slot_get(p_sd, cd) < 0 ) clif_displaymessage(sd->fd, msg_txt(817)); else if( p_sd == sd ) clif_displaymessage(sd->fd, msg_txt(832)); else { cd->op = p_sd->bl.id; sprintf(output, msg_txt(833), cd->name, p_sd->status.name); clif_channel_message(cd, output, -1); } } else if( !strncasecmp(message, ".pass ", 6) && len > 6 ) { option_text = trim((char *)message + 6); if( cd->type != CHN_USER ) clif_displaymessage(sd->fd, msg_txt(875)); else if( !strcmpi(option_text, "off") ) { memset(cd->pass, '\0', sizeof(cd->pass)); sprintf(output, msg_txt(834), cd->name); clif_channel_message(cd, output, -1); } else if( strlen(option_text) > 1 && strlen(option_text) < NAME_LENGTH ) { safestrncpy(cd->pass, option_text, sizeof(cd->pass)); sprintf(output, msg_txt(835), cd->name); clif_channel_message(cd, output, -1); } else clif_displaymessage(sd->fd, msg_txt(836)); } else if( !strncasecmp(message, ".close", 6) ) { if( cd->type != CHN_USER ) clif_displaymessage(sd->fd, msg_txt(875)); else channel_close(cd); } else if( !strncasecmp(message, ".list", 6) ) { DBIterator* iter = db_iterator(cd->users_db); clif_displaymessage(sd->fd, msg_txt(837)); for( p_sd = (struct map_session_data *)dbi_first(iter); dbi_exists(iter); p_sd = (struct map_session_data *)dbi_next(iter) ) clif_displaymessage(sd->fd, p_sd->status.name); dbi_destroy(iter); clif_displaymessage(sd->fd, msg_txt(838)); } else if( !strncasecmp(message, ".help", 5) ) { // Command List clif_displaymessage(sd->fd, msg_txt(839)); clif_displaymessage(sd->fd, msg_txt(840)); clif_displaymessage(sd->fd, msg_txt(841)); clif_displaymessage(sd->fd, msg_txt(842)); clif_displaymessage(sd->fd, msg_txt(843)); clif_displaymessage(sd->fd, msg_txt(844)); clif_displaymessage(sd->fd, msg_txt(845)); clif_displaymessage(sd->fd, msg_txt(846)); } else clif_displaymessage(sd->fd, msg_txt(847)); return; } snprintf(output, sizeof(output), "%s : [%s] %s", cd->name, sd->status.name, message); clif_channel_message(cd, output, -1); }
void searchstore_query(struct map_session_data* sd, unsigned char type, unsigned int min_price, unsigned int max_price, const unsigned short* itemlist, unsigned int item_count, const unsigned short* cardlist, unsigned int card_count) { unsigned int i; struct map_session_data* pl_sd; struct s_mapiterator* iter; struct s_search_store_search s; searchstore_searchall_t store_searchall; time_t querytime; if( !battle_config.feature_search_stores ) { return; } if( !sd->searchstore.open ) { return; } if( ( store_searchall = searchstore_getsearchallfunc(type) ) == NULL ) { ShowError("searchstore_query: Unknown search type %u (account_id=%d).\n", (unsigned int)type, sd->bl.id); return; } time(&querytime); if( sd->searchstore.nextquerytime > querytime ) { clif_search_store_info_failed(sd, SSI_FAILED_LIMIT_SEARCH_TIME); return; } if( !sd->searchstore.uses ) { clif_search_store_info_failed(sd, SSI_FAILED_SEARCH_CNT); return; } // validate lists for( i = 0; i < item_count; i++ ) { if( !itemdb_exists(itemlist[i]) ) { ShowWarning("searchstore_query: Client resolved item %hu is not known.\n", itemlist[i]); clif_search_store_info_failed(sd, SSI_FAILED_NOTHING_SEARCH_ITEM); return; } } for( i = 0; i < card_count; i++ ) { if( !itemdb_exists(cardlist[i]) ) { ShowWarning("searchstore_query: Client resolved card %hu is not known.\n", cardlist[i]); clif_search_store_info_failed(sd, SSI_FAILED_NOTHING_SEARCH_ITEM); return; } } if( max_price < min_price ) { swap(min_price, max_price); } sd->searchstore.uses--; sd->searchstore.type = type; sd->searchstore.nextquerytime = querytime+battle_config.searchstore_querydelay; // drop previous results searchstore_clear(sd); // allocate max. amount of results sd->searchstore.items = (struct s_search_store_info_item*)aMalloc(sizeof(struct s_search_store_info_item)*battle_config.searchstore_maxresults); // search s.search_sd = sd; s.itemlist = itemlist; s.cardlist = cardlist; s.item_count = item_count; s.card_count = card_count; s.min_price = min_price; s.max_price = max_price; iter = mapit_geteachpc(); for( pl_sd = (struct map_session_data*)mapit_first(iter); mapit_exists(iter); pl_sd = (struct map_session_data*)mapit_next(iter) ) { if( sd == pl_sd ) {// skip own shop, if any continue; } if( !store_searchall(pl_sd, &s) ) {// exceeded result size clif_search_store_info_failed(sd, SSI_FAILED_OVER_MAXCOUNT); break; } } mapit_free(iter); if( sd->searchstore.count ) { // reclaim unused memory sd->searchstore.items = (struct s_search_store_info_item*)aRealloc(sd->searchstore.items, sizeof(struct s_search_store_info_item)*sd->searchstore.count); // present results clif_search_store_info_ack(sd); // one page displayed sd->searchstore.pages++; } else { // cleanup searchstore_clear(sd); // update uses clif_search_store_info_ack(sd); // notify of failure clif_search_store_info_failed(sd, SSI_FAILED_NOTHING_SEARCH_ITEM); } }