/** * Make a player leave a type of channel * @param sd: Player data * @param type: Quit type (1 - Quit guild channel, 2 - Quit ally channel, 4 - Quit map channel, 8 - Quit all users in channel) * @return * 0: Success * -1: Invalid player */ int channel_pcquit(struct map_session_data *sd, int type){ int i; //On closing state we could have clean all chan by sd but pcquit is more used to free unit when //he quit a map_server, not call in map_quit cause we need to cleanup when we switch map-server as well if(!sd) return -1; // Leave all chat channels. if(type&(1|2) && channel_config.ally_tmpl.name != NULL && sd->guild){ //quit guild and ally chan struct guild *g = sd->guild; if(type&1 && channel_haspc(g->channel,sd)==1){ channel_clean(g->channel,sd,0); //leave guild chan } if(type&2){ for (i = 0; i < MAX_GUILDALLIANCE; i++) { //leave all alliance chan struct guild *ag; //allied guild if( g->alliance[i].guild_id && (ag = guild_search(g->alliance[i].guild_id) ) ) { if(channel_haspc(ag->channel,sd) == 1) channel_clean(ag->channel,sd,0); break; } } } } if(type&4 && channel_config.map_tmpl.name != NULL && channel_haspc(map[sd->bl.m].channel,sd)==1){ //quit map chan channel_clean(map[sd->bl.m].channel,sd,0); } if(type&8 && sd->channel_count ) { //quit all chan uint8 count = sd->channel_count; for( i = count-1; i >= 0; i--) { //going backward to avoid shifting channel_clean(sd->channels[i],sd,0); } } return 0; }
/** * A player is attempting to join a channel * @param sd: Player data * @param chname: Channel name * @param pass: Channel password * @return 0 on success or -1 on failure */ int channel_pcjoin(struct map_session_data *sd, char *chname, char *pass){ struct Channel *channel; char output[CHAT_SIZE_MAX]; if(!sd || !chname) return 0; if( channel_chk(chname,NULL,1) ) { clif_displaymessage(sd->fd, msg_txt(sd,1405));// Channel name must start with '#'. return -1; } channel = channel_name2channel(chname,sd,1); if(channel){ if (!pc_has_permission(sd, PC_PERM_CHANNEL_ADMIN) && !channel_pccheckgroup(channel, sd->group_id)) { sprintf(output, msg_txt(sd,1407), chname); // Channel '%s' is not available. clif_displaymessage(sd->fd, output); return -1; } if(channel_haspc(channel,sd)==1) { sprintf(output, msg_txt(sd,1434),chname); // You're already in the '%s' channel. clif_displaymessage(sd->fd, output); return -1; } else if( channel->pass[0] != '\0') { //chan has a pass if(strcmp(channel->pass,pass) != 0){ //wrong pass entry if( pc_has_permission(sd, PC_PERM_CHANNEL_ADMIN) ) { sd->stealth = true; } else { sprintf(output, msg_txt(sd,1401),chname,"@join"); // Channel '%s' is password-protected (usage: %s <#channel_name> <password>). clif_displaymessage(sd->fd, output); return -1; } } } } else { sprintf(output, msg_txt(sd,1400),chname,"@join"); // Unknown channel '%s' (usage: %s <#channel_name>). clif_displaymessage(sd->fd, output); return -1; } switch(channel->type){ case CHAN_TYPE_ALLY: channel_gjoin(sd,3); break; case CHAN_TYPE_MAP: channel_mjoin(sd); break; default: //private and public atm if (channel_join(channel,sd) != 0) return -1; } if( ( channel->opt & CHAN_OPT_ANNOUNCE_SELF ) ) { sprintf(output, msg_txt(sd,1403),chname); // You're now in the '%s' channel. clif_displaymessage(sd->fd, output); } return 0; }
/** * Make a player join a channel * - Add player to channel user list * - Add channel to user channel list * @param channel: Channel data * @param sd: Player data * @return * 0: Success * -1: Invalid channel or player * -2: Player already in channel * -3: Player banned * -4: Reached max limit */ int channel_join(struct Channel *channel, struct map_session_data *sd) { if(!channel || !sd) return -1; if(sd->state.autotrade) return 0; // fake success if(channel_haspc(channel,sd)==1) return -2; if (!pc_has_permission(sd, PC_PERM_CHANNEL_ADMIN) && !channel_pccheckgroup(channel, sd->group_id)) return -2; if(channel_haspcbanned(channel,sd)==1){ char output[CHAT_SIZE_MAX]; sprintf(output, msg_txt(sd,1438),channel->name); //You're currently banned from the '%s' channel. clif_displaymessage(sd->fd, output); return -3; } if (channel->type == CHAN_TYPE_PRIVATE && db_size(channel->users) >= channel_config.private_channel.max_member) { char output[CHAT_SIZE_MAX]; sprintf(output, msg_txt(sd,760), channel->name, channel_config.private_channel.max_member); // You cannot join channel '%s'. Limit of %d has been met. clif_displaymessage(sd->fd, output); return -4; } RECREATE(sd->channels, struct Channel *, ++sd->channel_count); sd->channels[ sd->channel_count - 1 ] = channel; idb_put(channel->users, sd->status.char_id, sd); RECREATE(sd->channel_tick, t_tick, sd->channel_count); sd->channel_tick[sd->channel_count-1] = 0; if( sd->stealth ) { sd->stealth = false; } else if( channel->opt & CHAN_OPT_ANNOUNCE_JOIN ) { char output[CHAT_SIZE_MAX]; safesnprintf(output, CHAT_SIZE_MAX, msg_txt(sd,761), channel->alias, sd->status.name); // %s %s has joined. clif_channel_msg(channel,output,channel->color); } /* someone is cheating, we kindly disconnect the bastard */ if( sd->channel_count > 200 ) { set_eof(sd->fd); } return 0; }
/** * Make all ally members of a guild join the guild channel * - They only join if they are in their own guild channel (if not they probably left it) * @param g: Guild data * @return * 0: Success * -1: Invalid guild or no channel for guild */ int channel_ajoin(struct guild *g){ int i, j; struct map_session_data *pl_sd; if(!g || !g->channel) return -1; for (i = 0; i < MAX_GUILDALLIANCE; i++){ struct guild *ag; //allied guld struct guild_alliance *ga = &g->alliance[i]; //guild alliance if(ga->guild_id && (ga->opposition==0) && (ag=guild_search(ga->guild_id))){ for (j = 0; j < ag->max_member; j++){ //load all guildmember pl_sd = ag->member[j].sd; if(channel_haspc(ag->channel,pl_sd)==1) //only if they are in their own guildchan channel_join(g->channel,pl_sd); } } } return 0; }