2 * roleplay commands for charybdis.
4 * adds NPC, NPCA, and SCENE which allow users to send messages from 'fake'
5 * nicknames. in the case of NPC and NPCA, the nickname will be underlined
6 * to clearly show that it is fake. SCENE is a special case and not underlined.
7 * these commands only work on channels set +N
9 * also adds oper commands FSAY and FACTION, which are like NPC and NPCA
10 * except without the underline.
12 * all of these messages have the hostmask npc.fakeuser.invalid, and their ident
13 * is the nickname of the user running the commands.
25 #include "inline/stringops.h"
32 static const char roleplay_desc
[] =
33 "Adds a roleplaying system that allows faked nicknames to talk in a channel set +N";
35 static void m_scene(struct MsgBuf
*msgbuf_p
, struct Client
*client_p
, struct Client
*source_p
, int parc
, const char *parv
[]);
36 static void m_fsay(struct MsgBuf
*msgbuf_p
, struct Client
*client_p
, struct Client
*source_p
, int parc
, const char *parv
[]);
37 static void m_faction(struct MsgBuf
*msgbuf_p
, struct Client
*client_p
, struct Client
*source_p
, int parc
, const char *parv
[]);
38 static void m_npc(struct MsgBuf
*msgbuf_p
, struct Client
*client_p
, struct Client
*source_p
, int parc
, const char *parv
[]);
39 static void m_npca(struct MsgBuf
*msgbuf_p
, struct Client
*client_p
, struct Client
*source_p
, int parc
, const char *parv
[]);
40 static void m_displaymsg(struct MsgBuf
*msgbuf_p
, struct Client
*source_p
, const char *channel
, int underline
, int action
, const char *nick
, const char *text
);
41 static void me_roleplay(struct MsgBuf
*msgbuf_p
, struct Client
*client_p
, struct Client
*source_p
, int parc
, const char *parv
[]);
42 static unsigned int mymode
;
47 /* initalize the +N cmode */
48 mymode
= cflag_add('N', chm_simple
);
58 /* orphan the +N cmode on modunload */
63 struct Message scene_msgtab
= {
65 {mg_unreg
, {m_scene
, 3}, mg_ignore
, mg_ignore
, mg_ignore
, {m_scene
, 3}}
68 /* this serves as an alias for people who are used to inspircd/unreal m_roleplay */
69 struct Message ambiance_msgtab
= {
70 "AMBIANCE", 0, 0, 0, 0,
71 {mg_unreg
, {m_scene
, 3}, mg_ignore
, mg_ignore
, mg_ignore
, {m_scene
, 3}}
74 struct Message fsay_msgtab
= {
76 {mg_unreg
, {m_npc
, 4}, mg_ignore
, mg_ignore
, mg_ignore
, {m_fsay
, 4}}
79 struct Message faction_msgtab
= {
80 "FACTION", 0, 0, 0, 0,
81 {mg_unreg
, {m_npca
, 4}, mg_ignore
, mg_ignore
, mg_ignore
, {m_faction
, 4}}
84 struct Message npc_msgtab
= {
86 {mg_unreg
, {m_npc
, 4}, mg_ignore
, mg_ignore
, mg_ignore
, {m_npc
, 4}}
89 struct Message npca_msgtab
= {
91 {mg_unreg
, {m_npca
, 4}, mg_ignore
, mg_ignore
, mg_ignore
, {m_npca
, 4}}
94 struct Message roleplay_msgtab
= {
95 "ROLEPLAY", 0, 0, 0, 0,
96 {mg_ignore
, mg_ignore
, mg_ignore
, mg_ignore
, {me_roleplay
, 4}, mg_ignore
}
99 mapi_clist_av1 roleplay_clist
[] = { &scene_msgtab
, &ambiance_msgtab
, &fsay_msgtab
, &faction_msgtab
, &npc_msgtab
, &npca_msgtab
, &roleplay_msgtab
, NULL
};
101 DECLARE_MODULE_AV2(roleplay
, _modinit
, _moddeinit
, roleplay_clist
, NULL
, NULL
, NULL
, NULL
, roleplay_desc
);
104 m_scene(struct MsgBuf
*msgbuf_p
, struct Client
*client_p
, struct Client
*source_p
, int parc
, const char *parv
[])
106 m_displaymsg(msgbuf_p
, source_p
, parv
[1], 0, 0, "=Scene=", parv
[2]);
110 m_fsay(struct MsgBuf
*msgbuf_p
, struct Client
*client_p
, struct Client
*source_p
, int parc
, const char *parv
[])
112 m_displaymsg(msgbuf_p
, source_p
, parv
[1], 0, 0, parv
[2], parv
[3]);
116 m_faction(struct MsgBuf
*msgbuf_p
, struct Client
*client_p
, struct Client
*source_p
, int parc
, const char *parv
[])
118 m_displaymsg(msgbuf_p
, source_p
, parv
[1], 0, 1, parv
[2], parv
[3]);
122 m_npc(struct MsgBuf
*msgbuf_p
, struct Client
*client_p
, struct Client
*source_p
, int parc
, const char *parv
[])
124 m_displaymsg(msgbuf_p
, source_p
, parv
[1], 1, 0, parv
[2], parv
[3]);
128 m_npca(struct MsgBuf
*msgbuf_p
, struct Client
*client_p
, struct Client
*source_p
, int parc
, const char *parv
[])
130 m_displaymsg(msgbuf_p
, source_p
, parv
[1], 1, 1, parv
[2], parv
[3]);
134 m_displaymsg(struct MsgBuf
*msgbuf_p
, struct Client
*source_p
, const char *channel
, int underline
, int action
, const char *nick
, const char *text
)
136 struct Channel
*chptr
;
137 struct membership
*msptr
;
138 char nick2
[NICKLEN
+1];
139 char nick3
[NICKLEN
+1];
143 rb_strlcpy(nick3
, nick
, sizeof nick3
);
145 if(!IsFloodDone(source_p
))
146 flood_endgrace(source_p
);
148 if((chptr
= find_channel(channel
)) == NULL
)
150 sendto_one_numeric(source_p
, ERR_NOSUCHCHANNEL
,
151 form_str(ERR_NOSUCHCHANNEL
), channel
);
155 if(!(msptr
= find_channel_membership(chptr
, source_p
)))
157 sendto_one_numeric(source_p
, ERR_NOTONCHANNEL
,
158 form_str(ERR_NOTONCHANNEL
), chptr
->chname
);
162 if(!(chptr
->mode
.mode
& chmode_flags
['N']))
164 sendto_one_numeric(source_p
, 573, "%s :Roleplay commands are not enabled on this channel.", chptr
->chname
);
168 if(!can_send(chptr
, source_p
, msptr
))
170 sendto_one_numeric(source_p
, 573, "%s :Cannot send to channel.", chptr
->chname
);
174 /* enforce flood stuff on roleplay commands */
175 if(flood_attack_channel(0, source_p
, chptr
, chptr
->chname
))
178 /* enforce target change on roleplay commands */
179 if(!is_chanop_voiced(msptr
) && !IsOper(source_p
) && !add_channel_target(source_p
, chptr
))
181 sendto_one(source_p
, form_str(ERR_TARGCHANGE
),
182 me
.name
, source_p
->name
, chptr
->chname
);
187 snprintf(nick2
, sizeof(nick2
), "\x1F%s\x1F", strip_unprintable(nick3
));
189 snprintf(nick2
, sizeof(nick2
), "%s", strip_unprintable(nick3
));
191 /* don't allow nicks to be empty after stripping
192 * this prevents nastiness like fake factions, etc. */
193 if(EmptyString(nick3
))
195 sendto_one_numeric(source_p
, 573, "%s :No visible non-stripped characters in nick.", chptr
->chname
);
199 snprintf(text3
, sizeof(text3
), "%s (%s)", text
, source_p
->name
);
202 snprintf(text2
, sizeof(text2
), "\1ACTION %s\1", text3
);
204 snprintf(text2
, sizeof(text2
), "%s", text3
);
206 sendto_channel_local(source_p
, ALL_MEMBERS
, chptr
, ":%s!%s@npc.fakeuser.invalid PRIVMSG %s :%s", nick2
, source_p
->name
, channel
, text2
);
207 sendto_match_servs(source_p
, "*", CAP_ENCAP
, NOCAPS
, "ENCAP * ROLEPLAY %s %s :%s",
208 channel
, nick2
, text2
);
212 me_roleplay(struct MsgBuf
*msgbuf_p
, struct Client
*client_p
, struct Client
*source_p
, int parc
, const char *parv
[])
214 struct Channel
*chptr
;
216 /* Don't segfault if we get ROLEPLAY with an invalid channel.
217 * This shouldn't happen but it's best to be on the safe side. */
218 if((chptr
= find_channel(parv
[1])) == NULL
)
221 sendto_channel_local(source_p
, ALL_MEMBERS
, chptr
, ":%s!%s@npc.fakeuser.invalid PRIVMSG %s :%s", parv
[2], source_p
->name
, parv
[1], parv
[3]);