Channel System is Expanded! (#1933)
* Many changes on conf/channel.conf! - Now capable of setting default values for channels through the config such as the channel name, channel password, member capacity, chat color, chat delay, and more. * Many new channel script commands! - Added script commands channel_create, channel_setopt channel_setcolor, channel_setpass, channel_setgroup, channel_chat, channel_ban, channel_unban, channel_kick, and channel_delete.
This commit is contained in:
parent
97f989f7d8
commit
c87dba5a52
@ -1,16 +1,5 @@
|
||||
// Channel System Configuration File
|
||||
|
||||
chsys: (
|
||||
{
|
||||
/* Default channels (available to all players) */
|
||||
default_channels: {
|
||||
/* channel_name : channel_messages_color */
|
||||
main: "Yellow"
|
||||
support: "Blue"
|
||||
trade: "Red"
|
||||
chat: "Default"
|
||||
/* Add as many channels as you'd like. */
|
||||
}
|
||||
channel_config: {
|
||||
|
||||
/* Colors available */
|
||||
colors: {
|
||||
@ -21,24 +10,112 @@ chsys: (
|
||||
Cyan: "0x00b89d"
|
||||
Yellow: "0xffff90"
|
||||
Green: "0x28bf00"
|
||||
White: "0xFFFFFF"
|
||||
Purple: "0xD67FFF"
|
||||
LightGreen: "0xB6FF00"
|
||||
Normal: "0x00ff00"
|
||||
/* Add as many colors as you'd like. */
|
||||
}
|
||||
|
||||
/* Allow users to create their own (private) channels through @channel command? */
|
||||
/* (must also allow players to use @channel in groups.conf) */
|
||||
allow_user_channel_creation: true
|
||||
/**
|
||||
* Private channel config
|
||||
* - Always CHAN_TYPE_PUBLIC
|
||||
* - Always displayed in chat log as "#channel_name: <name>: <chat>"
|
||||
* - ID of private channels start at 1000
|
||||
**/
|
||||
private_channel: {
|
||||
allow: true // (bool) Allow player to create their own channel?
|
||||
color: "Default" // (string) Default color, see colors
|
||||
delay: 1000 // (int) Chat delay for each member
|
||||
max_member: 1000 // (int) Max members
|
||||
self_notif: true // (bool) Show message when player enters or leaves the channel
|
||||
join_notif: false // (bool) Show message when player joined the channel
|
||||
leave_notif: false // (bool) Show message when player leaves the channel
|
||||
/* Moderation feature for channel owner, allowed to: */
|
||||
ban: true // (bool) Ban players
|
||||
kick: true // (bool) Kick players
|
||||
color_override: false // (bool) Allow players to change the private channel color to their own
|
||||
change_delay: false // (bool) Allow players to change the private channel delay to their own
|
||||
}
|
||||
|
||||
/* "map_local_channel" is an instanced channel unique to each map. */
|
||||
map_local_channel: false
|
||||
map_local_channel_name: "map"
|
||||
map_local_channel_color: "Yellow"
|
||||
map_local_channel_autojoin: true /* Disable autojoin in specific maps through mapflag 'nomapchannelautojoin'. */
|
||||
/**
|
||||
* Default server channels
|
||||
**/
|
||||
channels: (
|
||||
/**
|
||||
* Structure
|
||||
{
|
||||
name: "#channel" // (string) Channel name
|
||||
password: "" // (string) Channel password
|
||||
alias: "[Channel]" // (string) Message from this that channel will be displayed instead the channel name
|
||||
color: "Default" // (string) Channel color
|
||||
type: "CHAN_TYPE_PUBLIC" // (string) Channel type: CHAN_TYPE_PUBLIC, CHAN_TYPE_ALLY, CHAN_TYPE_MAP
|
||||
autojoin: false // (bool) Players will auto join channel
|
||||
delay: 1000 // (int) Chat delay for each player
|
||||
leave: true // (bool) Player is allowed to leave the channel
|
||||
chat: true // (bool) Player is allowed to chat on this channel
|
||||
color_override: false // (bool) Allow players to change the private channel color to their own
|
||||
self_notif: true // (bool) Show message when player enters or leaves the channel
|
||||
join_notif: false // (bool) Show message when player joined the channel
|
||||
leave_notif: false // (bool) Show message when player leaves the channel
|
||||
groupid: (0,..,99) // (list,int) Only players with valid group IDs are allowed to join. Group with 'channel_admin' can always enter the channel.
|
||||
/// All values above are default settings
|
||||
}, // Use comma if followed by other channel
|
||||
**/
|
||||
{
|
||||
name: "#global"
|
||||
alias: "[Global]"
|
||||
color: "White"
|
||||
type: "CHAN_TYPE_PUBLIC"
|
||||
delay: 1000
|
||||
autojoin: false
|
||||
leave: false
|
||||
},
|
||||
{
|
||||
name: "#support"
|
||||
alias: "[Support]"
|
||||
color: "Blue"
|
||||
type: "CHAN_TYPE_PUBLIC"
|
||||
delay: 1000
|
||||
autojoin: false
|
||||
},
|
||||
{
|
||||
name: "#trade"
|
||||
alias: "[Trade]"
|
||||
color: "LightGreen"
|
||||
type: "CHAN_TYPE_PUBLIC"
|
||||
delay: 1000
|
||||
autojoin: false
|
||||
}
|
||||
)
|
||||
|
||||
/* "ally_channel" is a channel shared by all your guild allies. */
|
||||
ally_channel_enabled: true
|
||||
ally_channel_name: "ally"
|
||||
ally_channel_color: "Green"
|
||||
ally_channel_autojoin: true
|
||||
/**
|
||||
* Channel config for guild alliance
|
||||
* For the structure, see the 'channels' above
|
||||
**/
|
||||
ally: {
|
||||
name: "#ally"
|
||||
alias: "[Ally]"
|
||||
color: "Green"
|
||||
type: "CHAN_TYPE_ALLY" // DO NOT CHANGE THIS VALUE
|
||||
delay: 1000
|
||||
autojoin: false
|
||||
leave: true
|
||||
chat: true
|
||||
}
|
||||
|
||||
/**
|
||||
* Channel config for map channel
|
||||
* For the structure, see the 'channels' above
|
||||
**/
|
||||
map: {
|
||||
name: "#map"
|
||||
alias: "[Map]"
|
||||
color: "Yellow"
|
||||
type: "CHAN_TYPE_MAP" // DO NOT CHANGE THIS VALUE
|
||||
delay: 1000
|
||||
autojoin: false
|
||||
leave: true
|
||||
chat: true
|
||||
}
|
||||
}
|
||||
)
|
||||
|
@ -119,6 +119,9 @@ help_txt: conf/help.txt
|
||||
help2_txt: conf/help2.txt
|
||||
charhelp_txt: conf/charhelp.txt
|
||||
|
||||
// Load channel config from
|
||||
channel_conf: conf/channels.conf
|
||||
|
||||
// Maps:
|
||||
import: conf/maps_athena.conf
|
||||
|
||||
|
@ -812,7 +812,20 @@
|
||||
758: Baby Gunslinger
|
||||
759: Baby Rebellion
|
||||
|
||||
//760-899 free
|
||||
// Channel System
|
||||
760: You cannot join channel '%s'. Limit of %d has been met.
|
||||
761: %s %s has joined.
|
||||
762: You cannot leave channel '%s'.
|
||||
763: %s %s left.
|
||||
764: You cannot change the color for channel '%s'.
|
||||
765: You're not allowed to ban a player.
|
||||
766: You cannot kick a player from channel '%s'.
|
||||
767: You're not allowed to kick a player.
|
||||
768: %s %s has been kicked.
|
||||
769: %s %s has been banned.
|
||||
770: %s %s has been unbanned.
|
||||
|
||||
//771-899 free
|
||||
|
||||
//------------------------------------
|
||||
// More atcommands message
|
||||
|
@ -1,4 +1,4 @@
|
||||
//===== rAthena Documentation ================================
|
||||
//===== rAthena Documentation ================================
|
||||
//= rAthena Script Commands
|
||||
//===== By: ==================================================
|
||||
//= rAthena Dev Team
|
||||
@ -1033,6 +1033,7 @@ From here on, we will have the commands sorted as follow:
|
||||
11.- Homunculus commands.
|
||||
12.- Mercenary commands.
|
||||
13.- Party commands.
|
||||
14.- Channel commands.
|
||||
|
||||
=====================
|
||||
|1.- Basic commands.|
|
||||
@ -9444,3 +9445,159 @@ else false if the leave failed.
|
||||
If <char id> is specified, the specified player is used rather than the attached one.
|
||||
|
||||
---------------------------------------
|
||||
|
||||
========================
|
||||
|14.- Channel commands.|
|
||||
========================
|
||||
---------------------------------------
|
||||
|
||||
*channel_create "<chname>","<alias>"{,"<password>"{<option>{,<delay>{,<color>{,<char_id>}}}}};
|
||||
|
||||
Creates a public channel with <chname> as the channel name. To protect the
|
||||
channel, use <password> or write "null" to create it without a password.
|
||||
Channel name must start with '#' and cannot be the same as the map or ally
|
||||
channel names.
|
||||
|
||||
<alias> will be used to change the channel name when the channel message
|
||||
is displayed.
|
||||
|
||||
<option> values are:
|
||||
CHAN_OPT_BASE - Default option including CHAN_OPT_ANNOUNCE_SELF|CHAN_OPT_MSG_DELAY|CHAN_OPT_CAN_CHAT|CHAN_OPT_CAN_LEAVE
|
||||
CHAN_OPT_ANNOUNCE_SELF - Show info for player itself if player has joined/leaves the channel
|
||||
CHAN_OPT_ANNOUNCE_JOIN - Display message when player is joining the channel
|
||||
CHAN_OPT_ANNOUNCE_LEAVE - Display message when player is leaving the channel
|
||||
CHAN_OPT_MSG_DELAY - Enable chat delay for the channel
|
||||
CHAN_OPT_COLOR_OVERRIDE - Player's unique font color will override channel's color
|
||||
CHAN_OPT_CAN_CHAT - Player can chat in the channel
|
||||
CHAN_OPT_CAN_LEAVE - Player can leave the channel
|
||||
CHAN_OPT_AUTOJOIN - Players will auto join the channel at login
|
||||
|
||||
The <delay> is the minimum chat delay in millisecond for a single player before
|
||||
the player can chat again in the same channel.
|
||||
|
||||
Use <color> hex code to set the color for this channel, if not defined, default
|
||||
channel color will be used.
|
||||
|
||||
If <char_id> is defined, the channel will be a private channel and the player
|
||||
will be the the channel owner.
|
||||
|
||||
Returns 1 on success.
|
||||
|
||||
/**
|
||||
* This example will shows the message on this channel as
|
||||
* [rAthena] Admin : Hello world!
|
||||
* instead of
|
||||
* #rathena Admin : Hello world!
|
||||
**/
|
||||
channel_create("#rathena","[rAthena]");
|
||||
channel_create("#vip","[VIP]","vipmemberonly");
|
||||
|
||||
---------------------------------------
|
||||
|
||||
*channel_setopt "<chname>",<option>,<value>;
|
||||
|
||||
Set option for the channel. Use 1 in <value> to set it, or 0 to unset.
|
||||
The <option> values are the same as the 'channel_create' options.
|
||||
|
||||
For CHAN_OPT_MSG_DELAY, the delay in millisecond must be sent or use 0
|
||||
to remove the delay at <value>.
|
||||
|
||||
Returns 1 on success.
|
||||
|
||||
// Example to set delay
|
||||
channel_setopt("#global",CHAN_OPT_MSG_DELAY,5000);
|
||||
|
||||
Only for public and private channel.
|
||||
|
||||
---------------------------------------
|
||||
|
||||
*channel_setcolor "<chname>",<color>;
|
||||
|
||||
To change channel color.
|
||||
<color> uses hex RGB values.
|
||||
|
||||
Returns 1 on success.
|
||||
|
||||
---------------------------------------
|
||||
|
||||
*channel_setpass "<chname>","<password>";
|
||||
|
||||
To set, unset, or change password of a channel.
|
||||
Use "null" to remove the password.
|
||||
|
||||
Returns 1 on success.
|
||||
Only for public and private channel.
|
||||
|
||||
---------------------------------------
|
||||
|
||||
*channel_setgroup "<chname>",<group_id>{,...,<group_id>};
|
||||
*channel_setgroup2 "<chname>",<array_of_groups>;
|
||||
|
||||
Set group restriction for a channel. Only player with matching <group_id>
|
||||
are allowed to to join the channel.
|
||||
|
||||
By using 0 in the first group channel, the group restriction will be
|
||||
removed from the channel config.
|
||||
|
||||
'channel_setgroup2' receives input for group list as an array.
|
||||
|
||||
Returns 0 on failure, and 1 (or n groups count) on success.
|
||||
|
||||
// Example 1: Remove groups
|
||||
channel_setgroup("#event",0);
|
||||
|
||||
// Example 2: Multiple values
|
||||
channel_setgroup("#vip",2,5);
|
||||
|
||||
// Example 3: Using array
|
||||
setarray .@staffs[0],2,3,4,10,99;
|
||||
channel_setgroup("#staff",.@staffs);
|
||||
|
||||
Only for public and private channel.
|
||||
|
||||
---------------------------------------
|
||||
|
||||
*channel_chat "<chname>","<message>"{,<color>};
|
||||
|
||||
Sends message to the channel.
|
||||
Returns 1 on success.
|
||||
|
||||
// Example if channel doesn't have alias
|
||||
channel_chat(#rathena,"Hello World!"); // #rathena Hello World!
|
||||
|
||||
// Example if channel has alias
|
||||
channel_chat(#rathena,"Hello World!"); // [rAthena] Hello World!
|
||||
|
||||
---------------------------------------
|
||||
|
||||
*channel_ban "<chname>",<char_id>;
|
||||
|
||||
Ban player from a public or private channel.
|
||||
Channel's owner or group with PC_PERM_CHANNEL_ADMIN cannot be banned.
|
||||
Returns 1 on success.
|
||||
|
||||
---------------------------------------
|
||||
|
||||
*channel_unban "<chname>",<char_id>;
|
||||
|
||||
Unban player from a public or private channel.
|
||||
Returns 1 on success.
|
||||
|
||||
---------------------------------------
|
||||
|
||||
*channel_kick "<chname>",<char_id>;
|
||||
*channel_kick "<chname>","<char_name>";
|
||||
|
||||
Kick player from a public or private channel.
|
||||
Channel's owner or group with PC_PERM_CHANNEL_ADMIN cannot be kicked.
|
||||
Returns 1 on success.
|
||||
|
||||
---------------------------------------
|
||||
|
||||
*channel_delete "<chname>";
|
||||
|
||||
Delete an existing public or private channel. Cannot delete ally or
|
||||
local map channel.
|
||||
Returns 0 on success.
|
||||
|
||||
---------------------------------------
|
||||
|
@ -1324,6 +1324,10 @@ int char_check_char_name(char * name, char * esc_name)
|
||||
if( strcmpi(name, charserv_config.wisp_server_name) == 0 )
|
||||
return -1; // nick reserved for internal server messages
|
||||
|
||||
// check for the channel symbol
|
||||
if( name[0] == '#' )
|
||||
return -2;
|
||||
|
||||
// Check Authorised letters/symbols in the name of the character
|
||||
if( charserv_config.char_config.char_name_option == 1 )
|
||||
{ // only letters/symbols in char_name_letters are authorised
|
||||
|
@ -9378,7 +9378,7 @@ static inline void atcmd_channel_help(struct map_session_data *sd, const char *c
|
||||
{
|
||||
int fd = sd->fd;
|
||||
bool can_delete = pc_has_permission(sd, PC_PERM_CHANNEL_ADMIN);
|
||||
bool can_create = (can_delete || channel_config.user_chenable);
|
||||
bool can_create = (can_delete || channel_config.private_channel.allow);
|
||||
clif_displaymessage(fd, msg_txt(sd,1414));// ---- Available options:
|
||||
|
||||
//option create
|
||||
@ -9487,6 +9487,8 @@ ACMD_FUNC(channel) {
|
||||
return channel_pcunbind(sd);
|
||||
} else if ( strcmpi(key,"ban") == 0 ) {
|
||||
return channel_pcban(sd,sub1,sub2,0);
|
||||
} else if ( strcmpi(key,"kick") == 0 ) {
|
||||
return channel_pckick(sd,sub1,sub2);
|
||||
} else if ( strcmpi(key,"banlist") == 0 ) {
|
||||
return channel_pcban(sd,sub1,NULL,3);
|
||||
} else if ( strcmpi(key,"unban") == 0 ) {
|
||||
@ -9497,7 +9499,7 @@ ACMD_FUNC(channel) {
|
||||
char sub3[CHAN_NAME_LENGTH], sub4[CHAN_NAME_LENGTH];
|
||||
sub3[0] = sub4[0] = '\0';
|
||||
sscanf(sub2, "%19s %19s", sub3, sub4);
|
||||
if( strcmpi(key,"create") == 0 && ( channel_config.user_chenable || pc_has_permission(sd, PC_PERM_CHANNEL_ADMIN) ) ) {
|
||||
if( strcmpi(key,"create") == 0 && ( channel_config.private_channel.allow || pc_has_permission(sd, PC_PERM_CHANNEL_ADMIN) ) ) {
|
||||
if (sub4[0] != '\0') {
|
||||
clif_displaymessage(fd, msg_txt(sd, 1408)); // Channel password may not contain spaces.
|
||||
return -1;
|
||||
|
1082
src/map/channel.c
1082
src/map/channel.c
File diff suppressed because it is too large
Load Diff
@ -14,49 +14,79 @@ extern "C" {
|
||||
#define CHAN_MSG_LENGTH 150
|
||||
|
||||
enum Channel_Opt {
|
||||
CHAN_OPT_BASE = 0,
|
||||
CHAN_OPT_ANNOUNCE_JOIN = 1, //display message when join or leave
|
||||
CHAN_OPT_MSG_DELAY = 2,
|
||||
CHAN_OPT_COLOR_OVERRIDE = 3,
|
||||
CHAN_OPT_NONE = 0, ///< None
|
||||
CHAN_OPT_ANNOUNCE_SELF = 0x01, ///< Shows info when player joined/left channel to self
|
||||
CHAN_OPT_ANNOUNCE_JOIN = 0x02, ///< Shows info if player joined the channel
|
||||
CHAN_OPT_ANNOUNCE_LEAVE = 0x04, ///< Shows info if player left the channel
|
||||
CHAN_OPT_MSG_DELAY = 0x08, ///< Enables chat delay
|
||||
CHAN_OPT_COLOR_OVERRIDE = 0x10, ///< Enables color channel be override by player's font color
|
||||
CHAN_OPT_CAN_CHAT = 0x20, ///< Allows player to chat in the channel
|
||||
CHAN_OPT_CAN_LEAVE = 0x40, ///< Allows player to leave the channel
|
||||
CHAN_OPT_AUTOJOIN = 0x80, ///< Player will be autojoined to the channel
|
||||
|
||||
CHAN_OPT_BASE = CHAN_OPT_ANNOUNCE_SELF|CHAN_OPT_MSG_DELAY|CHAN_OPT_CAN_CHAT|CHAN_OPT_CAN_LEAVE,
|
||||
};
|
||||
|
||||
enum Channel_Type {
|
||||
CHAN_TYPE_PUBLIC = 0, //config file made
|
||||
CHAN_TYPE_PRIVATE = 1, //user made
|
||||
CHAN_TYPE_MAP = 2, //made by map
|
||||
CHAN_TYPE_ALLY = 3, //guild
|
||||
CHAN_TYPE_PUBLIC = 0, ///< Config file made
|
||||
CHAN_TYPE_PRIVATE = 1, ///< User's channel
|
||||
CHAN_TYPE_MAP = 2, ///< Local map
|
||||
CHAN_TYPE_ALLY = 3, ///< Guild + its alliance
|
||||
};
|
||||
|
||||
struct Channel {
|
||||
//unsigned short id; ///< Channel ID (unused yet)
|
||||
char name[CHAN_NAME_LENGTH]; ///< Channel Name
|
||||
char pass[CHAN_NAME_LENGTH]; ///< Channe display name
|
||||
char alias[CHAN_NAME_LENGTH]; ///< Password
|
||||
enum Channel_Type type; ///< Channel type @see enum Channel_Type
|
||||
unsigned long color; ///< Channel color in BGR
|
||||
unsigned char opt; ///< Channel options @see enum Channel_Opt
|
||||
unsigned short msg_delay; ///< Chat delay in miliseconds
|
||||
unsigned int char_id; ///< If CHAN_TYPE_PRIVATE, owner is char_id of channel creator
|
||||
uint16 m; ///< If CHAN_TYPE_MAP, owner is map id
|
||||
int gid; ///< If CHAN_TYPE_ALLY, owner is first logged guild_id
|
||||
DBMap *users; ///< List of users
|
||||
DBMap *banned; ///< List of banned chars -> char_id
|
||||
unsigned short group_count; ///< Number of group id
|
||||
unsigned short *groups; ///< List of group id, only these groups can join the channel
|
||||
};
|
||||
|
||||
struct chan_banentry {
|
||||
uint32 char_id;
|
||||
char char_name[NAME_LENGTH];
|
||||
} chan_banentry;
|
||||
|
||||
struct Channel_Config {
|
||||
unsigned long *colors; //color avail int list
|
||||
char **colors_name; //colors avail name list
|
||||
unsigned char colors_count; //color avail count
|
||||
unsigned char map_chcolor, ally_chcolor; //msg color for map, ally
|
||||
bool map_enable, ally_enable, user_chenable; //map, ally, users channels enable ?
|
||||
bool map_autojoin, ally_autojoin; //do user auto join in mapchange, guildjoin ?
|
||||
char map_chname[CHAN_NAME_LENGTH], ally_chname[CHAN_NAME_LENGTH]; //channel name for map and ally
|
||||
bool closing; //server is closing
|
||||
unsigned long *colors; ///< List of available colors
|
||||
char **colors_name; ///< Name list of available colors
|
||||
unsigned char colors_count; ///< Number of available colors
|
||||
|
||||
/// Private channel default configs
|
||||
struct {
|
||||
unsigned char opt; ///< Options @see enum Channel_Opt
|
||||
unsigned long color; ///< Default color
|
||||
unsigned int delay; ///< Message delay
|
||||
unsigned short max_member; ///< Max member for each channel
|
||||
unsigned allow : 1; ///< Allow private channel creation?
|
||||
unsigned ban : 1; ///< Allow player to ban
|
||||
unsigned kick : 1; ///< Allow player to kick
|
||||
unsigned color_override : 1; ///< Owner cannot change the color_override
|
||||
unsigned change_delay : 1; ///< Owner cannot change the delay
|
||||
} private_channel;
|
||||
|
||||
struct Channel map_tmpl; ///< Map channel default config
|
||||
struct Channel ally_tmpl; ///< Alliance channel default config
|
||||
|
||||
bool closing; ///< Server is closing
|
||||
};
|
||||
extern struct Channel_Config channel_config;
|
||||
|
||||
struct Channel {
|
||||
char name[CHAN_NAME_LENGTH]; //channel name
|
||||
char pass[CHAN_NAME_LENGTH]; //channel password
|
||||
unsigned char color; //msg color
|
||||
DBMap *users; //users in channel charid list
|
||||
DBMap *banned; //users banned from channel charid list
|
||||
enum Channel_Opt opt; //flag for some treatement
|
||||
enum Channel_Type type; //type of channel
|
||||
unsigned int owner; //if chan_type private charid of creator
|
||||
uint16 m; //if chan_type map guild_id
|
||||
int gid; //if chan_type guild type guild_id
|
||||
unsigned char msg_delay; //delay in second if opt_msg_delay
|
||||
};
|
||||
|
||||
DBMap* channel_get_db(void);
|
||||
|
||||
struct Channel* channel_create(char *name, char *pass, unsigned char color, enum Channel_Type chantype, int val);
|
||||
int channel_delete(struct Channel *channel);
|
||||
struct Channel* channel_create(struct Channel *tmp_chan);
|
||||
struct Channel* channel_create_simple(char *name, char *pass, enum Channel_Type chantype, unsigned int owner);
|
||||
int channel_delete(struct Channel *channel, bool force);
|
||||
|
||||
int channel_join(struct Channel *channel, struct map_session_data *sd);
|
||||
int channel_mjoin(struct map_session_data *sd);
|
||||
@ -65,6 +95,8 @@ int channel_ajoin(struct guild *g);
|
||||
int channel_clean(struct Channel *channel, struct map_session_data *sd, int flag);
|
||||
int channel_pcquit(struct map_session_data *sd, int type);
|
||||
|
||||
unsigned long channel_getColor(const char *color_str);
|
||||
|
||||
int channel_send(struct Channel *channel, struct map_session_data *sd, const char *msg);
|
||||
void channel_read_config(void);
|
||||
|
||||
@ -75,6 +107,9 @@ int channel_haspcbanned(struct Channel *channel,struct map_session_data *sd);
|
||||
int channel_pc_haschan(struct map_session_data *sd, struct Channel *channel);
|
||||
int channel_display_list(struct map_session_data *sd, char *option);
|
||||
|
||||
void channel_autojoin(struct map_session_data *sd);
|
||||
bool channel_pccheckgroup(struct Channel *channel, int group_id);
|
||||
|
||||
int channel_pccreate(struct map_session_data *sd, char *chname, char *pass);
|
||||
int channel_pcdelete(struct map_session_data *sd, char *chname);
|
||||
int channel_pcjoin(struct map_session_data *sd, char *chname, char *pass);
|
||||
@ -83,6 +118,7 @@ int channel_pccolor(struct map_session_data *sd, char *chname, char *color);
|
||||
int channel_pcbind(struct map_session_data *sd, char *chname);
|
||||
int channel_pcunbind(struct map_session_data *sd);
|
||||
int channel_pcban(struct map_session_data *sd, char *chname, char *pname, int flag);
|
||||
int channel_pckick(struct map_session_data *sd, char *chname, char *pname);
|
||||
int channel_pcsetopt(struct map_session_data *sd, char *chname, const char *option, const char *val);
|
||||
|
||||
void do_init_channel(void);
|
||||
|
@ -6197,31 +6197,35 @@ void clif_broadcast2(struct block_list* bl, const char* mes, int len, unsigned l
|
||||
}
|
||||
|
||||
/*
|
||||
* Display *msg from *sd to all *users in channel
|
||||
* Display *msg to all *users in channel
|
||||
*/
|
||||
void clif_channel_msg(struct Channel *channel, struct map_session_data *sd, char *msg, short color) {
|
||||
void clif_channel_msg(struct Channel *channel, const char *msg, unsigned long color) {
|
||||
DBIterator *iter;
|
||||
struct map_session_data *user;
|
||||
unsigned short msg_len = (unsigned short)(strlen(msg) + 1);
|
||||
unsigned short msg_len = 0, len = 0;
|
||||
unsigned char buf[CHAT_SIZE_MAX];
|
||||
|
||||
WFIFOHEAD(sd->fd,msg_len + 12);
|
||||
WFIFOW(sd->fd,0) = 0x2C1;
|
||||
WFIFOW(sd->fd,2) = msg_len + 12;
|
||||
WFIFOL(sd->fd,4) = 0;
|
||||
WFIFOL(sd->fd,8) = channel_config.colors[color];
|
||||
safestrncpy(WFIFOCP(sd->fd,12), msg, msg_len);
|
||||
if (!channel || !msg)
|
||||
return;
|
||||
|
||||
msg_len = (unsigned short)(strlen(msg) + 1);
|
||||
|
||||
if( msg_len > sizeof(buf)-12 ) {
|
||||
ShowWarning("clif_channel_msg: Truncating too long message '%s' (len=%u).\n", msg, msg_len);
|
||||
msg_len = sizeof(buf)-12;
|
||||
}
|
||||
|
||||
WBUFW(buf,0) = 0x2C1;
|
||||
WBUFW(buf,2) = (len = msg_len + 12);
|
||||
WBUFL(buf,4) = 0;
|
||||
WBUFL(buf,8) = color;
|
||||
safestrncpy(WBUFCP(buf,12), msg, msg_len);
|
||||
|
||||
iter = db_iterator(channel->users);
|
||||
for( user = (struct map_session_data *)dbi_first(iter); dbi_exists(iter); user = (struct map_session_data *)dbi_next(iter) ) {
|
||||
if( user->fd == sd->fd )
|
||||
continue;
|
||||
WFIFOHEAD(user->fd,msg_len + 12);
|
||||
memcpy(WFIFOP(user->fd,0), WFIFOP(sd->fd,0), msg_len + 12);
|
||||
WFIFOSET(user->fd, msg_len + 12);
|
||||
clif_send(buf, len, &user->bl, SELF);
|
||||
}
|
||||
dbi_destroy(iter);
|
||||
|
||||
WFIFOSET(sd->fd, msg_len + 12);
|
||||
}
|
||||
|
||||
/// Displays heal effect.
|
||||
@ -10351,7 +10355,7 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd)
|
||||
#endif
|
||||
|
||||
// Instances do not need their own channels
|
||||
if( channel_config.map_enable && channel_config.map_autojoin && !map[sd->bl.m].flag.chmautojoin && !map[sd->bl.m].instance_id )
|
||||
if( channel_config.map_tmpl.name != NULL && (channel_config.map_tmpl.opt&CHAN_OPT_AUTOJOIN) && !map[sd->bl.m].flag.chmautojoin && !map[sd->bl.m].instance_id )
|
||||
channel_mjoin(sd); //join new map
|
||||
} else if (sd->guild && (battle_config.guild_notice_changemap == 2 || guild_notice))
|
||||
clif_guild_notice(sd); // Displays at end
|
||||
@ -10679,7 +10683,7 @@ void clif_parse_GlobalMessage(int fd, struct map_session_data* sd)
|
||||
if( !clif_process_message(sd, false, name, message, output ) )
|
||||
return;
|
||||
|
||||
if( sd->gcbind ) {
|
||||
if( sd->gcbind && ((sd->gcbind->opt&CHAN_OPT_CAN_CHAT) || pc_has_permission(sd, PC_PERM_CHANNEL_ADMIN)) ) {
|
||||
channel_send(sd->gcbind,sd,message);
|
||||
return;
|
||||
}
|
||||
@ -11035,12 +11039,13 @@ void clif_parse_WisMessage(int fd, struct map_session_data* sd)
|
||||
char* chname = target;
|
||||
|
||||
channel = channel_name2channel(chname,sd,3);
|
||||
if(channel){
|
||||
if(channel && (pc_has_permission(sd, PC_PERM_CHANNEL_ADMIN) || ((channel->opt&CHAN_OPT_CAN_CHAT) && channel_pccheckgroup(channel,sd->group_id)))){
|
||||
if(channel_pc_haschan(sd,channel)>=0){ //we are in the chan
|
||||
channel_send(channel,sd,message);
|
||||
}
|
||||
else if( channel->pass[0] == '\0') { //no pass needed
|
||||
if (channel_join(channel,sd)==0) channel_send(channel,sd,message); //join success
|
||||
if (channel_join(channel,sd)==0)
|
||||
channel_send(channel,sd,message); //join success
|
||||
}
|
||||
else {
|
||||
clif_displaymessage(fd, msg_txt(sd,1402)); //You're not in that channel, type '@join <#channel_name>'
|
||||
|
@ -1003,7 +1003,7 @@ enum clif_colors {
|
||||
};
|
||||
unsigned long color_table[COLOR_MAX];
|
||||
|
||||
void clif_channel_msg(struct Channel *channel, struct map_session_data *sd, char *msg, short color);
|
||||
void clif_channel_msg(struct Channel *channel, const char *msg, unsigned long color);
|
||||
|
||||
#define clif_menuskill_clear(sd) (sd)->menuskill_id = (sd)->menuskill_val = (sd)->menuskill_val2 = 0;
|
||||
|
||||
|
@ -534,7 +534,7 @@ int guild_recv_info(struct guild *sg) {
|
||||
if( sd==NULL )
|
||||
continue;
|
||||
sd->guild = g;
|
||||
if(channel_config.ally_autojoin ) {
|
||||
if(channel_config.ally_tmpl.name && (channel_config.ally_tmpl.opt&CHAN_OPT_AUTOJOIN)) {
|
||||
channel_gjoin(sd,3); //make all member join guildchan+allieschan
|
||||
}
|
||||
|
||||
@ -703,7 +703,7 @@ void guild_member_joined(struct map_session_data *sd) {
|
||||
|
||||
if (g->instance_id != 0)
|
||||
instance_reqinfo(sd, g->instance_id);
|
||||
if( channel_config.ally_enable && channel_config.ally_autojoin ) {
|
||||
if( channel_config.ally_tmpl.name != NULL && (channel_config.ally_tmpl.opt&CHAN_OPT_AUTOJOIN) ) {
|
||||
channel_gjoin(sd,3);
|
||||
}
|
||||
}
|
||||
@ -1745,8 +1745,8 @@ int guild_broken(int guild_id,int flag) {
|
||||
guild_db->foreach(guild_db,guild_broken_sub,guild_id);
|
||||
castle_db->foreach(castle_db,castle_guild_broken_sub,guild_id);
|
||||
storage_guild_delete(guild_id);
|
||||
if( channel_config.ally_enable ) {
|
||||
channel_delete(g->channel);
|
||||
if( channel_config.ally_tmpl.name != NULL ) {
|
||||
channel_delete(g->channel,false);
|
||||
}
|
||||
idb_remove(guild_db,guild_id);
|
||||
return 0;
|
||||
@ -2303,7 +2303,7 @@ void do_final_guild(void) {
|
||||
struct guild *g;
|
||||
|
||||
for( g = (struct guild *)dbi_first(iter); dbi_exists(iter); g = (struct guild *)dbi_next(iter) ) {
|
||||
channel_delete(g->channel);
|
||||
channel_delete(g->channel,false);
|
||||
}
|
||||
dbi_destroy(iter);
|
||||
|
||||
|
@ -155,6 +155,7 @@ char motd_txt[256] = "conf/motd.txt";
|
||||
char help_txt[256] = "conf/help.txt";
|
||||
char help2_txt[256] = "conf/help2.txt";
|
||||
char charhelp_txt[256] = "conf/charhelp.txt";
|
||||
char channel_conf[256] = "conf/channels.conf";
|
||||
|
||||
char wisp_server_name[NAME_LENGTH] = "Server"; // can be modified in char-server configuration file
|
||||
|
||||
@ -3889,6 +3890,8 @@ int map_config_read(char *cfgName)
|
||||
strcpy(help2_txt, w2);
|
||||
else if (strcmpi(w1, "charhelp_txt") == 0)
|
||||
strcpy(charhelp_txt, w2);
|
||||
else if (strcmpi(w1, "channel_conf") == 0)
|
||||
safestrncpy(channel_conf, w2, sizeof(channel_conf));
|
||||
else if(strcmpi(w1,"db_path") == 0)
|
||||
safestrncpy(db_path,w2,ARRAYLENGTH(db_path));
|
||||
else if (strcmpi(w1, "console") == 0) {
|
||||
@ -4404,7 +4407,7 @@ void do_final(void)
|
||||
ShowStatus("Cleaning up maps [%d/%d]: %s..."CL_CLL"\r", i+1, map_num, map[i].name);
|
||||
if (map[i].m >= 0) {
|
||||
map_foreachinmap(cleanup_sub, i, BL_ALL);
|
||||
channel_delete(map[i].channel);
|
||||
channel_delete(map[i].channel,false);
|
||||
}
|
||||
}
|
||||
ShowStatus("Cleaned up %d maps."CL_CLL"\n", map_num);
|
||||
@ -4755,12 +4758,12 @@ int do_init(int argc, char *argv[])
|
||||
do_init_atcommand();
|
||||
do_init_battle();
|
||||
do_init_instance();
|
||||
do_init_channel();
|
||||
do_init_chrif();
|
||||
do_init_clan();
|
||||
do_init_clif();
|
||||
do_init_script();
|
||||
do_init_itemdb();
|
||||
do_init_channel();
|
||||
do_init_cashshop();
|
||||
do_init_skill();
|
||||
do_init_mob();
|
||||
|
@ -758,6 +758,7 @@ extern char motd_txt[];
|
||||
extern char help_txt[];
|
||||
extern char help2_txt[];
|
||||
extern char charhelp_txt[];
|
||||
extern char channel_conf[];
|
||||
|
||||
extern char wisp_server_name[];
|
||||
|
||||
|
@ -1462,6 +1462,8 @@ void pc_reg_received(struct map_session_data *sd)
|
||||
|
||||
clif_changeoption( &sd->bl );
|
||||
}
|
||||
|
||||
channel_autojoin(sd);
|
||||
}
|
||||
|
||||
static int pc_calc_skillpoint(struct map_session_data* sd)
|
||||
|
@ -643,7 +643,7 @@ struct map_session_data {
|
||||
struct Channel *gcbind;
|
||||
bool stealth;
|
||||
unsigned char fontcolor;
|
||||
unsigned int channel_tick;
|
||||
unsigned int *channel_tick;
|
||||
|
||||
/* [Ind] */
|
||||
struct sc_display_entry **sc_display;
|
||||
|
463
src/map/script.c
463
src/map/script.c
@ -49,6 +49,7 @@
|
||||
#include "mail.h"
|
||||
#include "quest.h"
|
||||
#include "elemental.h"
|
||||
#include "channel.h"
|
||||
|
||||
#include <math.h>
|
||||
#include <stdlib.h> // atoi, strtol, strtoll, exit
|
||||
@ -22366,6 +22367,455 @@ BUILDIN_FUNC(openstorage2) {
|
||||
return SCRIPT_CMD_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new channel
|
||||
* channel_create "<chname>","<alias>"{,"<password>"{<option>{,<delay>{,<color>{,<char_id>}}}}};
|
||||
* @author [Cydh]
|
||||
**/
|
||||
BUILDIN_FUNC(channel_create) {
|
||||
struct Channel tmp_chan, *ch = NULL;
|
||||
const char *chname = script_getstr(st,2), *pass = NULL;
|
||||
int i = channel_chk((char*)chname, NULL, 3);
|
||||
TBL_PC *sd = NULL;
|
||||
|
||||
if (i != 0) {
|
||||
ShowError("buildin_channel_create: Channel name '%s' is invalid. Errno %d\n", chname, i);
|
||||
script_pushint(st,i);
|
||||
return SCRIPT_CMD_FAILURE;
|
||||
}
|
||||
|
||||
memset(&tmp_chan, 0, sizeof(struct Channel));
|
||||
|
||||
if (script_hasdata(st,8)) {
|
||||
tmp_chan.char_id = script_getnum(st,8);
|
||||
if (!(sd = map_charid2sd(tmp_chan.char_id))) {
|
||||
ShowError("buildin_channel_create: Player with char id '%d' is not found.\n", tmp_chan.char_id);
|
||||
script_pushint(st,-5);
|
||||
return SCRIPT_CMD_FAILURE;
|
||||
}
|
||||
tmp_chan.type = CHAN_TYPE_PRIVATE;
|
||||
i = 1;
|
||||
}
|
||||
else {
|
||||
tmp_chan.type = CHAN_TYPE_PUBLIC;
|
||||
i = 0;
|
||||
}
|
||||
|
||||
safestrncpy(tmp_chan.name, chname+1, sizeof(tmp_chan.name));
|
||||
safestrncpy(tmp_chan.alias, script_getstr(st,3), sizeof(tmp_chan.alias));
|
||||
if (script_hasdata(st,4) && (pass = script_getstr(st,4)) && strcmpi(pass,"null") != 0)
|
||||
safestrncpy(tmp_chan.pass, pass, sizeof(tmp_chan.pass));
|
||||
if (script_hasdata(st,5))
|
||||
tmp_chan.opt = script_getnum(st,5);
|
||||
else
|
||||
tmp_chan.opt = i ? channel_config.private_channel.opt : CHAN_OPT_BASE;
|
||||
if (script_hasdata(st,6))
|
||||
tmp_chan.msg_delay = script_getnum(st,6);
|
||||
else
|
||||
tmp_chan.msg_delay = i ? channel_config.private_channel.delay : 1000;
|
||||
if (script_hasdata(st,7))
|
||||
tmp_chan.color = script_getnum(st,7);
|
||||
else
|
||||
tmp_chan.color = i ? channel_config.private_channel.color : channel_getColor("Default");
|
||||
|
||||
if (!(ch = channel_create(&tmp_chan))) {
|
||||
ShowError("buildin_channel_create: Cannot create channel '%s'.\n", chname);
|
||||
script_pushint(st,0);
|
||||
return SCRIPT_CMD_FAILURE;
|
||||
}
|
||||
if (tmp_chan.char_id)
|
||||
channel_join(ch, sd);
|
||||
script_pushint(st,1);
|
||||
return SCRIPT_CMD_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set channel option
|
||||
* channel_setopt "<chname>",<option>,<value>;
|
||||
* @author [Cydh]
|
||||
**/
|
||||
BUILDIN_FUNC(channel_setopt) {
|
||||
struct Channel *ch = NULL;
|
||||
const char *chname = script_getstr(st,2);
|
||||
int opt = script_getnum(st,3), value = script_getnum(st,4);
|
||||
|
||||
if (!(ch = channel_name2channel((char *)chname, NULL, 0))) {
|
||||
ShowError("buildin_channel_setopt: Channel name '%s' is invalid.\n", chname);
|
||||
script_pushint(st,0);
|
||||
return SCRIPT_CMD_FAILURE;
|
||||
}
|
||||
|
||||
switch (opt) {
|
||||
case CHAN_OPT_ANNOUNCE_SELF:
|
||||
case CHAN_OPT_ANNOUNCE_JOIN:
|
||||
case CHAN_OPT_ANNOUNCE_LEAVE:
|
||||
case CHAN_OPT_COLOR_OVERRIDE:
|
||||
case CHAN_OPT_CAN_CHAT:
|
||||
case CHAN_OPT_CAN_LEAVE:
|
||||
case CHAN_OPT_AUTOJOIN:
|
||||
if (value)
|
||||
ch->opt |= opt;
|
||||
else
|
||||
ch->opt &= ~opt;
|
||||
break;
|
||||
case CHAN_OPT_MSG_DELAY:
|
||||
ch->msg_delay = value;
|
||||
break;
|
||||
default:
|
||||
ShowError("buildin_channel_setopt: Invalid option %d!\n", opt);
|
||||
script_pushint(st,0);
|
||||
return SCRIPT_CMD_FAILURE;
|
||||
}
|
||||
|
||||
script_pushint(st,1);
|
||||
return SCRIPT_CMD_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set channel color
|
||||
* channel_setcolor "<chname>",<color>;
|
||||
* @author [Cydh]
|
||||
**/
|
||||
BUILDIN_FUNC(channel_setcolor) {
|
||||
struct Channel *ch = NULL;
|
||||
const char *chname = script_getstr(st,2);
|
||||
int color = script_getnum(st,3);
|
||||
|
||||
if (!(ch = channel_name2channel((char *)chname, NULL, 0))) {
|
||||
ShowError("buildin_channel_setcolor: Channel name '%s' is invalid.\n", chname);
|
||||
script_pushint(st,0);
|
||||
return SCRIPT_CMD_FAILURE;
|
||||
}
|
||||
|
||||
ch->color = (color & 0x0000FF) << 16 | (color & 0x00FF00) | (color & 0xFF0000) >> 16;//RGB to BGR
|
||||
|
||||
script_pushint(st,1);
|
||||
return SCRIPT_CMD_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set channel password
|
||||
* channel_setpass "<chname>","<password>";
|
||||
* @author [Cydh]
|
||||
**/
|
||||
BUILDIN_FUNC(channel_setpass) {
|
||||
struct Channel *ch = NULL;
|
||||
const char *chname = script_getstr(st,2), *passwd = script_getstr(st,3);
|
||||
|
||||
if (!(ch = channel_name2channel((char *)chname, NULL, 0))) {
|
||||
ShowError("buildin_channel_setpass: Channel name '%s' is invalid.\n", chname);
|
||||
script_pushint(st,0);
|
||||
return SCRIPT_CMD_FAILURE;
|
||||
}
|
||||
|
||||
if (!passwd || !strcmpi(passwd,"null"))
|
||||
memset(ch->pass, '\0', sizeof(ch->pass));
|
||||
else
|
||||
safestrncpy(ch->pass, passwd, sizeof(ch->pass));
|
||||
script_pushint(st,1);
|
||||
return SCRIPT_CMD_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set authorized groups
|
||||
* channel_setgroup "<chname>",<group_id>{,...,<group_id>};
|
||||
* @author [Cydh]
|
||||
**/
|
||||
BUILDIN_FUNC(channel_setgroup) {
|
||||
struct Channel *ch = NULL;
|
||||
const char *funcname = script_getfuncname(st), *chname = script_getstr(st,2);
|
||||
int i, n = 0, group = 0;
|
||||
|
||||
if (!(ch = channel_name2channel((char *)chname, NULL, 0))) {
|
||||
ShowError("buildin_channel_setgroup: Channel name '%s' is invalid.\n", chname);
|
||||
script_pushint(st,0);
|
||||
return SCRIPT_CMD_FAILURE;
|
||||
}
|
||||
|
||||
if (funcname[strlen(funcname)-1] == '2') {
|
||||
struct script_data *data = script_getdata(st,3);
|
||||
const char *varname = reference_getname(data);
|
||||
int32 id, idx;
|
||||
|
||||
if (varname[strlen(varname)-1] == '$') {
|
||||
ShowError("buildin_channel_setgroup: The array %s is not numeric type.\n", varname);
|
||||
script_pushint(st,0);
|
||||
return SCRIPT_CMD_FAILURE;
|
||||
}
|
||||
|
||||
n = script_array_highest_key(st, NULL, reference_getname(data), reference_getref(data));
|
||||
if (n < 1) {
|
||||
ShowError("buildin_channel_setgroup: No group id listed.\n");
|
||||
script_pushint(st,0);
|
||||
return SCRIPT_CMD_FAILURE;
|
||||
}
|
||||
|
||||
if (ch->groups)
|
||||
aFree(ch->groups);
|
||||
ch->groups = NULL;
|
||||
ch->group_count = 0;
|
||||
|
||||
id = reference_getid(data);
|
||||
idx = reference_getindex(data);
|
||||
for (i = 0; i < n; i++) {
|
||||
group = (int32)__64BPRTSIZE(get_val2(st,reference_uid(id,idx+i),reference_getref(data)));
|
||||
if (group == 0) {
|
||||
script_pushint(st,1);
|
||||
return SCRIPT_CMD_SUCCESS;
|
||||
}
|
||||
RECREATE(ch->groups, unsigned short, ++ch->group_count);
|
||||
ch->groups[ch->group_count-1] = group;
|
||||
ShowInfo("buildin_channel_setgroup: (2) Added group %d. Num: %d\n", ch->groups[ch->group_count-1], ch->group_count);
|
||||
}
|
||||
}
|
||||
else {
|
||||
group = script_getnum(st,3);
|
||||
n = script_lastdata(st)-1;
|
||||
|
||||
if (n < 1) {
|
||||
ShowError("buildin_channel_setgroup: Please input at least 1 group_id.\n");
|
||||
script_pushint(st,0);
|
||||
return SCRIPT_CMD_FAILURE;
|
||||
}
|
||||
|
||||
if (ch->groups)
|
||||
aFree(ch->groups);
|
||||
ch->groups = NULL;
|
||||
ch->group_count = 0;
|
||||
|
||||
if (group == 0) { // Removed group list
|
||||
script_pushint(st,1);
|
||||
return SCRIPT_CMD_SUCCESS;
|
||||
}
|
||||
|
||||
CREATE(ch->groups, unsigned short, n);
|
||||
for (i = 3; i < n+2; i++) {
|
||||
ch->groups[ch->group_count++] = script_getnum(st,i);
|
||||
ShowInfo("buildin_channel_setgroup: (1) Added group %d. Num: %d\n", ch->groups[ch->group_count-1], ch->group_count);
|
||||
}
|
||||
}
|
||||
script_pushint(st,n);
|
||||
return SCRIPT_CMD_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send message on channel
|
||||
* channel_chat "<chname>","<message>"{,<color>};
|
||||
* @author [Cydh]
|
||||
**/
|
||||
BUILDIN_FUNC(channel_chat) {
|
||||
struct Channel *ch = NULL;
|
||||
const char *chname = script_getstr(st,2), *msg = script_getstr(st,3);
|
||||
char output[CHAT_SIZE_MAX+1];
|
||||
unsigned long color = 0;
|
||||
|
||||
// Check also local channels
|
||||
if (chname[0] != '#') { // By Map
|
||||
int m = mapindex_name2id(chname);
|
||||
if (!m || (m = map_mapindex2mapid(m)) < 0) {
|
||||
ShowError("buildin_channel_chat: Invalid map '%s'.\n", chname);
|
||||
script_pushint(st,0);
|
||||
return SCRIPT_CMD_FAILURE;
|
||||
}
|
||||
if (!(ch = map[m].channel)) {
|
||||
ShowDebug("buildin_channel_chat: Map '%s' doesn't have local channel yet.\n", chname);
|
||||
script_pushint(st,0);
|
||||
return SCRIPT_CMD_SUCCESS;
|
||||
}
|
||||
}
|
||||
else if (strcmpi(chname+1,channel_config.map_tmpl.name) == 0) {
|
||||
TBL_NPC *nd = map_id2nd(st->oid);
|
||||
if (!nd || nd->bl.m == -1) {
|
||||
ShowError("buildin_channel_chat: Floating NPC needs map name instead '%s'.\n", chname);
|
||||
script_pushint(st,0);
|
||||
return SCRIPT_CMD_FAILURE;
|
||||
}
|
||||
if (!(ch = map[nd->bl.m].channel)) {
|
||||
ShowDebug("buildin_channel_chat: Map '%s' doesn't have local channel yet.\n", chname);
|
||||
script_pushint(st,0);
|
||||
return SCRIPT_CMD_SUCCESS;
|
||||
}
|
||||
}
|
||||
else if (!(ch = channel_name2channel((char *)chname, NULL, 0))) {
|
||||
ShowError("buildin_channel_chat: Channel name '%s' is invalid.\n", chname);
|
||||
script_pushint(st,0);
|
||||
return SCRIPT_CMD_FAILURE;
|
||||
}
|
||||
|
||||
if (!ch) {
|
||||
script_pushint(st,0);
|
||||
return SCRIPT_CMD_FAILURE;
|
||||
}
|
||||
|
||||
color = ch->color;
|
||||
FETCH(4, color);
|
||||
|
||||
safesnprintf(output, CHAT_SIZE_MAX, "%s %s", ch->alias, msg);
|
||||
clif_channel_msg(ch,output,color);
|
||||
script_pushint(st,1);
|
||||
return SCRIPT_CMD_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ban player from a channel
|
||||
* channel_ban "<chname>",<char_id>;
|
||||
* @author [Cydh]
|
||||
**/
|
||||
BUILDIN_FUNC(channel_ban) {
|
||||
struct Channel *ch = NULL;
|
||||
const char *chname = script_getstr(st,2);
|
||||
unsigned int char_id = script_getnum(st,3);
|
||||
TBL_PC *tsd;
|
||||
|
||||
if (!(ch = channel_name2channel((char *)chname, NULL, 0))) {
|
||||
ShowError("buildin_channel_ban: Channel name '%s' is invalid.\n", chname);
|
||||
script_pushint(st,0);
|
||||
return SCRIPT_CMD_FAILURE;
|
||||
}
|
||||
|
||||
if (ch->char_id == char_id) {
|
||||
script_pushint(st,0);
|
||||
return SCRIPT_CMD_SUCCESS;
|
||||
}
|
||||
|
||||
tsd = map_charid2sd(char_id);
|
||||
if (tsd && pc_has_permission(tsd,PC_PERM_CHANNEL_ADMIN)) {
|
||||
script_pushint(st,0);
|
||||
return SCRIPT_CMD_SUCCESS;
|
||||
}
|
||||
|
||||
if (!idb_exists(ch->banned, char_id)) {
|
||||
struct chan_banentry *cbe;
|
||||
char output[CHAT_SIZE_MAX+1];
|
||||
|
||||
CREATE(cbe, struct chan_banentry, 1);
|
||||
cbe->char_id = char_id;
|
||||
if (tsd) {
|
||||
strcpy(cbe->char_name,tsd->status.name);
|
||||
channel_clean(ch,tsd,0);
|
||||
safesnprintf(output, CHAT_SIZE_MAX, msg_txt(tsd,769), ch->alias, tsd->status.name); // %s %s has been banned.
|
||||
}
|
||||
else
|
||||
safesnprintf(output, CHAT_SIZE_MAX, msg_txt(tsd,769), ch->alias, "****"); // %s %s has been banned.
|
||||
idb_put(ch->banned, char_id, cbe);
|
||||
clif_channel_msg(ch,output,ch->color);
|
||||
}
|
||||
|
||||
script_pushint(st,1);
|
||||
return SCRIPT_CMD_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ban player from a channel
|
||||
* channel_unban "<chname>",<char_id>;
|
||||
* @author [Cydh]
|
||||
**/
|
||||
BUILDIN_FUNC(channel_unban) {
|
||||
struct Channel *ch = NULL;
|
||||
const char *chname = script_getstr(st,2);
|
||||
unsigned int char_id = script_getnum(st,3);
|
||||
|
||||
if (!(ch = channel_name2channel((char *)chname, NULL, 0))) {
|
||||
ShowError("buildin_channel_unban: Channel name '%s' is invalid.\n", chname);
|
||||
script_pushint(st,0);
|
||||
return SCRIPT_CMD_FAILURE;
|
||||
}
|
||||
|
||||
if (ch->char_id == char_id) {
|
||||
script_pushint(st,0);
|
||||
return SCRIPT_CMD_SUCCESS;
|
||||
}
|
||||
|
||||
if (idb_exists(ch->banned, char_id)) {
|
||||
char output[CHAT_SIZE_MAX+1];
|
||||
TBL_PC *tsd = map_charid2sd(char_id);
|
||||
if (tsd)
|
||||
safesnprintf(output, CHAT_SIZE_MAX, msg_txt(tsd,770), ch->alias, tsd->status.name); // %s %s has been unbanned
|
||||
else
|
||||
safesnprintf(output, CHAT_SIZE_MAX, msg_txt(tsd,770), ch->alias, "****"); // %s %s has been unbanned.
|
||||
idb_remove(ch->banned, char_id);
|
||||
clif_channel_msg(ch,output,ch->color);
|
||||
}
|
||||
|
||||
script_pushint(st,1);
|
||||
return SCRIPT_CMD_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Kick player from a channel
|
||||
* channel_kick "<chname>",<char_id>;
|
||||
* channel_kick "<chname>","<char_name>";
|
||||
* @author [Cydh]
|
||||
**/
|
||||
BUILDIN_FUNC(channel_kick) {
|
||||
struct Channel *ch = NULL;
|
||||
const char *chname = script_getstr(st,2);
|
||||
struct script_data *data = script_getdata(st,3);
|
||||
TBL_PC *tsd = NULL;
|
||||
int res = 1;
|
||||
|
||||
get_val(st, data);
|
||||
if (data_isstring(data)) {
|
||||
if (!(tsd = map_nick2sd(conv_str(st,data),false))) {
|
||||
ShowError("buildin_channel_kick: Player with nick '%s' is not online\n", conv_str(st,data));
|
||||
script_pushint(st,0);
|
||||
return SCRIPT_CMD_FAILURE;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!(tsd = map_charid2sd(conv_num(st,data)))) {
|
||||
ShowError("buildin_channel_kick: Player with char_id '%d' is not online\n", conv_num(st,data));
|
||||
script_pushint(st,0);
|
||||
return SCRIPT_CMD_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
if (!(ch = channel_name2channel((char *)chname, tsd, 0))) {
|
||||
ShowError("buildin_channel_kick: Channel name '%s' is invalid.\n", chname);
|
||||
script_pushint(st,0);
|
||||
return SCRIPT_CMD_FAILURE;
|
||||
}
|
||||
|
||||
if (channel_pc_haschan(tsd, ch) < 0 || ch->char_id == tsd->status.char_id || pc_has_permission(tsd,PC_PERM_CHANNEL_ADMIN)) {
|
||||
script_pushint(st,0);
|
||||
return SCRIPT_CMD_SUCCESS;
|
||||
}
|
||||
|
||||
switch(ch->type){
|
||||
case CHAN_TYPE_ALLY: res = channel_pcquit(tsd,3); break;
|
||||
case CHAN_TYPE_MAP: res = channel_pcquit(tsd,4); break;
|
||||
default: res = channel_clean(ch,tsd,0); break;
|
||||
}
|
||||
|
||||
if (res == 0) {
|
||||
char output[CHAT_SIZE_MAX+1];
|
||||
safesnprintf(output, CHAT_SIZE_MAX, msg_txt(tsd,889), ch->alias, tsd->status.name); // "%s %s is kicked"
|
||||
clif_channel_msg(ch,output,ch->color);
|
||||
}
|
||||
|
||||
script_pushint(st,1);
|
||||
return SCRIPT_CMD_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a channel
|
||||
* channel_delete "<chname>";
|
||||
* @author [Cydh]
|
||||
**/
|
||||
BUILDIN_FUNC(channel_delete) {
|
||||
struct Channel *ch = NULL;
|
||||
const char *chname = script_getstr(st,2);
|
||||
|
||||
if (!(ch = channel_name2channel((char *)chname, NULL, 0))) {
|
||||
ShowError("channel_delete: Channel name '%s' is invalid.\n", chname);
|
||||
script_pushint(st,-1);
|
||||
return SCRIPT_CMD_FAILURE;
|
||||
}
|
||||
|
||||
script_pushint(st,channel_delete(ch,true));
|
||||
return SCRIPT_CMD_SUCCESS;
|
||||
}
|
||||
|
||||
#include "../custom/script.inc"
|
||||
|
||||
// declarations that were supposed to be exported from npc_chat.c
|
||||
@ -22974,6 +23424,19 @@ struct script_function buildin_func[] = {
|
||||
BUILDIN_DEF(gvgon3,"s"),
|
||||
BUILDIN_DEF(gvgoff3,"s"),
|
||||
|
||||
// Channel System
|
||||
BUILDIN_DEF(channel_create,"ss?????"),
|
||||
BUILDIN_DEF(channel_setopt,"sii"),
|
||||
BUILDIN_DEF(channel_setcolor,"si"),
|
||||
BUILDIN_DEF(channel_setpass,"ss"),
|
||||
BUILDIN_DEF(channel_setgroup,"si*"),
|
||||
BUILDIN_DEF2(channel_setgroup,"channel_setgroup2","sr"),
|
||||
BUILDIN_DEF(channel_chat,"ss?"),
|
||||
BUILDIN_DEF(channel_ban,"si"),
|
||||
BUILDIN_DEF(channel_unban,"si"),
|
||||
BUILDIN_DEF(channel_kick,"sv"),
|
||||
BUILDIN_DEF(channel_delete,"s"),
|
||||
|
||||
#include "../custom/script_def.inc"
|
||||
|
||||
{NULL,NULL,NULL},
|
||||
|
@ -3229,6 +3229,21 @@
|
||||
export_constant(CARD0_CREATE);
|
||||
export_constant(CARD0_PET);
|
||||
|
||||
/* Channel System */
|
||||
export_constant(CHAN_TYPE_PUBLIC);
|
||||
export_constant(CHAN_TYPE_PRIVATE);
|
||||
export_constant(CHAN_TYPE_MAP);
|
||||
export_constant(CHAN_TYPE_ALLY);
|
||||
export_constant(CHAN_OPT_BASE);
|
||||
export_constant(CHAN_OPT_ANNOUNCE_SELF);
|
||||
export_constant(CHAN_OPT_ANNOUNCE_JOIN);
|
||||
export_constant(CHAN_OPT_ANNOUNCE_LEAVE);
|
||||
export_constant(CHAN_OPT_MSG_DELAY);
|
||||
export_constant(CHAN_OPT_COLOR_OVERRIDE);
|
||||
export_constant(CHAN_OPT_CAN_CHAT);
|
||||
export_constant(CHAN_OPT_CAN_LEAVE);
|
||||
export_constant(CHAN_OPT_AUTOJOIN);
|
||||
|
||||
export_constant(STOR_MODE_NONE);
|
||||
export_constant(STOR_MODE_GET);
|
||||
export_constant(STOR_MODE_PUT);
|
||||
|
Loading…
x
Reference in New Issue
Block a user