Advertisement
Guest User

Untitled

a guest
May 11th, 2017
780
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 16.25 KB | None | 0 0
  1. /*
  2. * Farpoint Internet Relay Chat Daemon, src/modules/m_roleplay.c
  3. * (C) 2005 William E. Donges III and the FarpointIRCd Team
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation; either version 1, or (at your option)
  8. * any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program; if not, write to the Free Software
  17. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18. */
  19.  
  20. /* RPG commands originally coded by falerin.
  21. * Conversion to module usable by standard UnrealIRCd daemons by aquanight.
  22. */
  23.  
  24. #include "config.h"
  25. #include "struct.h"
  26. #include "common.h"
  27. #include "sys.h"
  28. #include "numeric.h"
  29. #include "msg.h"
  30. #include "channel.h"
  31. #include <time.h>
  32. #include <sys/stat.h>
  33. #include <stdio.h>
  34. #include <stdlib.h>
  35. #include <string.h>
  36. #ifdef _WIN32
  37. #include <io.h>
  38. #endif
  39. #include <fcntl.h>
  40. #include "h.h"
  41. #ifdef STRIPBADWORDS
  42. #include "badwords.h"
  43. #endif
  44. #include "proto.h"
  45. #ifdef _WIN32
  46. #include "version.h"
  47. #endif
  48.  
  49. DLLFUNC int m_roleplay(aClient *cptr, aClient *sptr, int parc, char *parv[], int notice);
  50. DLLFUNC int m_ambiance(aClient *cptr, aClient *sptr, int parc, char *parv[]);
  51. DLLFUNC int m_npc(aClient *cptr, aClient *sptr, int parc, char *parv[]);
  52. DLLFUNC int m_npca(aClient *cptr, aClient *sptr, int parc, char *parv[]);
  53. DLLFUNC int m_fsay(aClient *cptr, aClient *sptr, int parc, char *parv[]);
  54. DLLFUNC int m_faction(aClient *cptr, aClient *sptr, int parc, char *parv[]);
  55.  
  56. /* Place includes here */
  57. #define MSG_AMBIANCE "AMBIANCE"
  58. #define TOK_AMBIANCE "FA"
  59. #define MSG_NPC "NPC"
  60. #define TOK_NPC "FB"
  61. #define MSG_NPCA "NPCA"
  62. #define TOK_NPCA "FC"
  63. #define MSG_FSAY "FSAY"
  64. #define TOK_FSAY "FD"
  65. #define MSG_FACTION "FACTION"
  66. #define TOK_FACTION "FE"
  67.  
  68. /* #define CanFSay(who) (IsULine((who)) || op_can_override((who)) || IsSAdmin((who))) */
  69. #define CanFSay(who) (IsAnOper((who)))
  70.  
  71. ModuleHeader MOD_HEADER(m_roleplay)
  72. = {
  73. "roleplay",/* Name of module */
  74. "$Id: m_roleplay.c,v 2.1 2006/05/17 17:43:50 falerin/aquanight Exp $", /* Version */
  75. "roleplaying commands", /* Short description of module */
  76. "3.2-b8-1",
  77. NULL
  78. };
  79.  
  80. /* This is called on module init, before Server Ready */
  81. DLLFUNC int MOD_INIT(m_roleplay)(ModuleInfo *modinfo)
  82. {
  83. /*
  84. * We call our add_Command crap here
  85. */
  86. add_CommandX(MSG_AMBIANCE, TOK_AMBIANCE, m_ambiance, 3, M_USER|M_SERVER|M_RESETIDLE);
  87. add_Command(MSG_NPC, TOK_NPC, m_npc, 3);
  88. add_Command(MSG_NPCA, TOK_NPCA, m_npca, 3);
  89. add_Command(MSG_FSAY, TOK_FSAY, m_fsay, 3);
  90. add_Command(MSG_FACTION, TOK_FACTION, m_faction, 3);
  91. return MOD_SUCCESS;
  92.  
  93. }
  94.  
  95. /* Is first run when server is 100% ready */
  96. DLLFUNC int MOD_LOAD(m_roleplay)(int module_load)
  97. {
  98. return MOD_SUCCESS;
  99. }
  100.  
  101. /* Called when module is unloaded */
  102. DLLFUNC int MOD_UNLOAD(m_roleplay)(int module_unload)
  103. {
  104. if (del_Command(MSG_AMBIANCE, TOK_AMBIANCE, m_ambiance) < 0) {
  105. sendto_realops("Failed to delete command ambiance when unloading %s", MOD_HEADER(m_roleplay).name);
  106. }
  107. if (del_Command(MSG_NPC, TOK_NPC, m_npc) < 0) {
  108. sendto_realops("Failed to delete command npc when unloading %s", MOD_HEADER(m_roleplay).name);
  109. }
  110. if (del_Command(MSG_NPCA, TOK_NPCA, m_npca) < 0) {
  111. sendto_realops("Failed to delete command npca when unloading %s", MOD_HEADER(m_roleplay).name);
  112. }
  113. if (del_Command(MSG_FSAY, TOK_FSAY, m_fsay) < 0) {
  114. sendto_realops("Failed to delete command fsay when unloading %s", MOD_HEADER(m_roleplay).name);
  115. }
  116. if (del_Command(MSG_FACTION, TOK_FACTION, m_faction) < 0) {
  117. sendto_realops("Failed to delete command faction when unloading %s", MOD_HEADER(m_roleplay).name);
  118. }
  119. return MOD_SUCCESS;
  120. }
  121.  
  122. static char tcmd[2048];
  123. static char ccmd[2048];
  124. static char xcmd[2048];
  125. static char wcmd[2048];
  126. static int sentalong[MAXCONNECTIONS];
  127. static int sentalong_marker;
  128.  
  129. #define ADD_CRLF(buf, len) { if (len > 510) len = 510; buf[len++] = '\r'; buf[len++] = '\n'; buf[len] = '\0'; } while(0)
  130.  
  131. /* This command handles the roleplaying functions being sent to the channel
  132. * by appropriately converting to the right PRIVMSG format for each command
  133. */
  134. void rpg_sendto_channelprefix_tok(aClient *one, aClient *from, aChannel *chptr, int prefix, char *cmd, char *tok, char *nick, char *npcname, char *text, char do_send_check)
  135. {
  136. Member *lp;
  137. aClient *acptr;
  138. int i;
  139. unsigned int tlen, clen,wlen = 0;
  140. char *p;
  141.  
  142. /* For servers with token capability */
  143. if (!strcmp(cmd, "AMBIANCE"))
  144. p = ircsprintf(tcmd, ":%s %s %s :%s", from->name, tok, nick, text);
  145. else
  146. p = ircsprintf(tcmd, ":%s %s %s %s :%s", from->name, tok, nick, npcname, text);
  147. tlen = (int)(p - tcmd);
  148. ADD_CRLF(tcmd, tlen);
  149.  
  150.  
  151. /* For dumb servers without tokens */
  152. if (!strcmp(cmd, "AMBIANCE"))
  153. p = ircsprintf(ccmd, ":%s %s %s :%s", from->name, cmd, nick, text);
  154. else
  155. p = ircsprintf(ccmd, ":%s %s %s %s :%s", from->name, cmd, nick, npcname, text);
  156. clen = (int)(p - ccmd);
  157. ADD_CRLF(ccmd, clen);
  158.  
  159.  
  160. if (!strcmp(cmd, "NPC")) {
  161. char *chan = strchr(nick, '#'); /* impossible to become NULL? */
  162. if (IsPerson(from))
  163. p = ircsprintf(wcmd, ":\037%s\037!%s@RPG.irc %s %s :%s", npcname, from->name, MSG_PRIVATE, chan, text);
  164. else
  165. p = ircsprintf(wcmd, ":\037%s\037!Internal@RPG.irc %s %s :%s", npcname, MSG_PRIVATE, chan, text);
  166. wlen = (int)(p - wcmd);
  167. ADD_CRLF(wcmd, wlen);
  168. } else if (!strcmp(cmd, "NPCA")) {
  169. char *chan = strchr(nick, '#'); /* impossible to become NULL? */
  170. if (IsPerson(from))
  171. p = ircsprintf(wcmd, ":\037%s\037!%s@RPG.irc %s %s :\1ACTION %s\1", npcname, from->name, MSG_PRIVATE, chan, text);
  172. else
  173. p = ircsprintf(wcmd, ":\037%s\037!Internal@RPG.irc %s %s :\1ACTION %s\1", npcname, MSG_PRIVATE, chan, text);
  174. wlen = (int)(p - wcmd);
  175. ADD_CRLF(wcmd, wlen);
  176. } else if (!strcmp(cmd, "FSAY")) {
  177. char *chan = strchr(nick, '#'); /* impossible to become NULL? */
  178. if (IsPerson(from))
  179. p = ircsprintf(wcmd, ":%s!%s@RPG.irc %s %s :%s", npcname, from->name, MSG_PRIVATE, chan, text);
  180. else
  181. p = ircsprintf(wcmd, ":%s!Internal@RPG.irc %s %s :%s", npcname, MSG_PRIVATE, chan, text);
  182. wlen = (int)(p - wcmd);
  183. ADD_CRLF(wcmd, wlen);
  184. } else if (!strcmp(cmd, "FACTION")) {
  185. char *chan = strchr(nick, '#'); /* impossible to become NULL? */
  186. if (IsPerson(from))
  187. p = ircsprintf(wcmd, ":%s!%s@RPG.irc %s %s :\1ACTION %s\1", npcname, from->name, MSG_PRIVATE, chan, text);
  188. else
  189. p = ircsprintf(wcmd, ":%s!Internal@RPG.irc %s %s :\1ACTION %s\1", npcname, MSG_PRIVATE, chan, text);
  190. wlen = (int)(p - wcmd);
  191. ADD_CRLF(wcmd, wlen);
  192. } else {
  193. char *chan = strchr(nick, '#'); /* impossible to become NULL? */
  194. if (IsPerson(from))
  195. p = ircsprintf(wcmd, ":>Ambiance<!%s@RPG.irc %s %s :%s", from->name, MSG_PRIVATE, chan, text);
  196. else
  197. p = ircsprintf(wcmd, ":>Ambiance<!Internal@RPG.irc %s %s :%s", MSG_PRIVATE, chan, text);
  198. wlen = (int)(p - wcmd);
  199. ADD_CRLF(wcmd, wlen);
  200. }
  201.  
  202.  
  203. ++sentalong_marker;
  204. for (lp = chptr->members; lp; lp = lp->next)
  205. {
  206. acptr = lp->cptr;
  207.  
  208. if (prefix == PREFIX_ALL)
  209. goto good;
  210. if ((prefix & PREFIX_HALFOP) && (lp->flags & CHFL_HALFOP))
  211. goto good;
  212. if ((prefix & PREFIX_VOICE) && (lp->flags & CHFL_VOICE))
  213. goto good;
  214. if ((prefix & PREFIX_OP) && (lp->flags & CHFL_CHANOP))
  215. goto good;
  216. #ifdef PREFIX_AQ
  217. if ((prefix & PREFIX_ADMIN) && (lp->flags & CHFL_CHANPROT))
  218. goto good;
  219. if ((prefix & PREFIX_OWNER) && (lp->flags & CHFL_CHANOWNER))
  220. goto good;
  221. #endif
  222. continue;
  223.  
  224. good:
  225. i = acptr->from->slot;
  226. if (IsDeaf(acptr) && !sendanyways)
  227. continue;
  228. if (MyConnect(acptr) && IsRegisteredUser(acptr)) {
  229. sendbufto_one(acptr, wcmd, wlen);
  230. sentalong[i] = sentalong_marker;
  231. }
  232. else {
  233. /* Now check whether a message has been sent to this
  234. * remote link already */
  235. if (sentalong[i] != sentalong_marker) {
  236. if (IsToken(acptr->from))
  237. sendbufto_one(acptr, tcmd, tlen);
  238. else
  239. sendbufto_one(acptr, ccmd, clen);
  240. sentalong[i] = sentalong_marker;
  241. }
  242. }
  243. }
  244. return;
  245. }
  246.  
  247. /*
  248. ** m_roleplay (used in m_ambiance() and m_npc, m_npca, m_fsay, m_faction)
  249. ** the general function to deliver roleplaying commands
  250. **
  251. ** parv[0] = sender prefix
  252. ** parv[1] = receiver list
  253. ** parv[2] = message text
  254. **
  255. ** massive cleanup
  256. ** rev argv 6/91
  257. **
  258. */
  259. static int recursive_webtv = 0;
  260. DLLFUNC int m_roleplay(aClient *cptr, aClient *sptr, int parc, char *parv[], int notice)
  261. {
  262. aClient *acptr;
  263. char *s;
  264. aChannel *chptr;
  265. char *nick, *npcname, *server, *p, *cmd, *cmdtok, *ctcp, *p2, *pc, *text;
  266. int cansend = 0;
  267. int prefix = 0;
  268. char pfixchan[CHANNELLEN + 32];
  269. int n;
  270.  
  271. if (IsHandshake(sptr))
  272. return 0;
  273.  
  274. if (notice == 1) {
  275. cmd = MSG_NPC;
  276. cmdtok = TOK_NPC;
  277. } else if (notice == 2) {
  278. cmd = MSG_NPCA;
  279. cmdtok = TOK_NPCA;
  280. } else if (notice == 3) {
  281. cmd = MSG_FSAY;
  282. cmdtok = TOK_FSAY;
  283. } else if (notice == 4) {
  284. cmd = MSG_FACTION;
  285. cmdtok = TOK_FACTION;
  286. } else {
  287. cmd = MSG_AMBIANCE;
  288. cmdtok = TOK_AMBIANCE;
  289. }
  290.  
  291. if (parc < 2 || *parv[1] == '\0') {
  292. sendto_one(sptr, err_str(ERR_NORECIPIENT), me.name, parv[0], cmd);
  293. return -1;
  294. }
  295.  
  296. if (parc < 3 || *parv[2] == '\0') {
  297. sendto_one(sptr, err_str(ERR_NOTEXTTOSEND), me.name, parv[0]);
  298. return -1;
  299. }
  300.  
  301. if ((*cmd == 'N' || *cmd == 'F') && (parc < 4 || *parv[3] == '\0')) {
  302. sendto_one(sptr, err_str(ERR_NOTEXTTOSEND), me.name, parv[0]);
  303. return -1;
  304. }
  305.  
  306. if (MyConnect(sptr))
  307. parv[1] = (char *)canonize(parv[1]);
  308.  
  309. for (p = NULL, nick = strtoken(&p, parv[1], ","); nick; nick = strtoken(&p, NULL, ",")) {
  310. /*
  311. ** nickname addressed?
  312. */
  313. /* OK, WHY would someone use an RPG command to target the psuedo IRC(d) clients?!
  314. * Let 'em use PRIVMSG like the rest of us...
  315. */
  316.  
  317. if (*nick != '#') {
  318. sendto_one(sptr, err_str(ERR_NOSUCHCHANNEL), me.name, parv[0], nick);
  319. return -1;
  320. }
  321.  
  322. p2 = (char *)strchr(nick, '#');
  323. prefix = 0;
  324.  
  325. if (p2 && (chptr = find_channel(p2, NullChn))) {
  326. if (p2 != nick) {
  327. int len = 0;
  328. for (pc = nick; pc != p2; pc++) {
  329. #ifdef PREFIX_AQ
  330. #define PREFIX_REST (PREFIX_ADMIN|PREFIX_OWNER)
  331. #else
  332. #define PREFIX_REST (0)
  333. #endif
  334. switch (*pc) {
  335. case '+':
  336. if (!(prefix & PREFIX_VOICE))
  337. prefix |= PREFIX_VOICE | PREFIX_HALFOP | PREFIX_OP | PREFIX_REST;
  338. break;
  339. case '%':
  340. if (!(prefix & PREFIX_HALFOP))
  341. prefix |= PREFIX_HALFOP | PREFIX_OP | PREFIX_REST;
  342. break;
  343. case '@':
  344. #ifndef PREFIX_AQ
  345. case '&':
  346. case '~':
  347. #endif
  348. if (!(prefix & PREFIX_OP))
  349. prefix |= PREFIX_OP | PREFIX_REST;
  350. break;
  351. #ifdef PREFIX_AQ
  352. case '&':
  353. if (!(prefix & PREFIX_ADMIN))
  354. prefix |= PREFIX_ADMIN | PREFIX_OWNER;
  355. break;
  356. case '~':
  357. if (!(prefix & PREFIX_OWNER))
  358. prefix |= PREFIX_OWNER;
  359. break;
  360. #endif
  361. default:
  362. break;/* ignore it :P */
  363. }
  364. }
  365. if (prefix) {
  366. /* Since we're about to later assert that the user is a chanop (or is
  367. * sufficiently privileged enough that he can be one anyway)...
  368. * skip unreal's normal prefix privilege checks.
  369. */
  370. /* Now find out the lowest prefix and use that.. (so @&~#chan becomes @#chan) */
  371. if (prefix & PREFIX_VOICE)
  372. pfixchan[0] = '+';
  373. else if (prefix & PREFIX_HALFOP)
  374. pfixchan[0] = '%';
  375. else if (prefix & PREFIX_OP)
  376. pfixchan[0] = '@';
  377. #ifdef PREFIX_AQ
  378. else if (prefix & PREFIX_ADMIN)
  379. pfixchan[0] = '&';
  380. else if (prefix & PREFIX_OWNER)
  381. pfixchan[0] = '~';
  382. #endif
  383. else
  384. abort();
  385. }
  386. pfixchan[len] = '\0';
  387. strlcat(pfixchan, p2, sizeof(pfixchan));
  388. nick = pfixchan;
  389. }
  390.  
  391. if (!MyClient(sptr) || CanFSay(sptr) || is_chan_op(sptr, chptr) || is_half_op(sptr, chptr)) {
  392. Hook *tmphook;
  393. #ifdef NEWCHFLOODPROT
  394. if (chptr->mode.floodprot && chptr->mode.floodprot->l[FLD_TEXT])
  395. #else
  396. if (chptr->mode.per)
  397. #endif
  398. if (check_for_chan_flood(cptr, sptr, chptr) == 1)
  399. continue;
  400.  
  401. if (!CHANCMDPFX) {
  402. if (cmd == MSG_NPC || cmd == MSG_NPCA || cmd == MSG_FACTION || cmd == MSG_FSAY)
  403. sendanyways = (parv[3][0] == '`' ? 1 : 0);
  404. else
  405. sendanyways = (parv[2][0] == '`' ? 1 : 0);
  406. } else {
  407. if (cmd == MSG_NPC || cmd == MSG_NPCA || cmd == MSG_FACTION || cmd == MSG_FSAY)
  408. sendanyways = (strchr(CHANCMDPFX,parv[3][0]) ? 1 : 0);
  409. else
  410. sendanyways = (strchr(CHANCMDPFX,parv[2][0]) ? 1 : 0);
  411. }
  412.  
  413.  
  414. if (cmd == MSG_NPC || cmd == MSG_NPCA || cmd == MSG_FACTION || cmd == MSG_FSAY)
  415. text = parv[3];
  416. else
  417. text = parv[2];
  418.  
  419. if (cmd == MSG_NPC || cmd == MSG_NPCA || cmd == MSG_FACTION || cmd == MSG_FSAY) {
  420. npcname = parv[2];
  421. if (strchr(npcname, '!') || strchr(npcname, 31) || strchr(npcname, 15) || strchr(npcname, 3) || strchr(npcname, '@')) {
  422. /* Clients get thrown off royally by these. Don't allow them. */
  423. sendto_one(sptr, err_str(ERR_ERRONEUSNICKNAME), me.name, parv[0], npcname, "Illegal character");
  424. return -1;
  425. }
  426. } else
  427. npcname = parv[0];
  428.  
  429.  
  430. if (MyClient(sptr)) {
  431. #if defined(UNREAL_VERSION_GENERATION) && (UNREAL_VERSION_GENERATION > 3 || (UNREAL_VERSION_GENERATION == 3 && defined(UNREAL_VERSION_MAJOR) && (UNREAL_VERSION_MAJOR > 2 || (UNREAL_VERSION_MAJOR == 2 && defined(UNREAL_VERSION_MINOR) && UNREAL_VERSION_MINOR >= 4))))
  432. n = dospamfilter(sptr, text, notice ? SPAMF_CHANNOTICE : SPAMF_CHANMSG, chptr->chname, 0, NULL);
  433. #else
  434. n = dospamfilter(sptr, text, notice ? SPAMF_CHANNOTICE : SPAMF_CHANMSG, chptr->chname);
  435. #endif
  436. if (n < 0)
  437. return n;
  438. }
  439.  
  440. for (tmphook = Hooks[HOOKTYPE_CHANMSG]; tmphook; tmphook = tmphook->next) {
  441. text = (*(tmphook->func.pcharfunc))(cptr, sptr, chptr, text, notice);
  442. if (!text)
  443. break;
  444. }
  445.  
  446.  
  447. if (!text || !npcname)
  448. continue;
  449.  
  450.  
  451. rpg_sendto_channelprefix_tok(cptr, sptr, chptr, prefix, cmd, cmdtok, nick, npcname, text, 1);
  452.  
  453. #ifdef NEWCHFLOODPROT
  454. if (chptr->mode.floodprot && !is_skochanop(sptr, chptr) && !IsULine(sptr) && do_chanflood(chptr->mode.floodprot, FLD_MSG) && MyClient(sptr)) {
  455. do_chanflood_action(chptr, FLD_MSG, "msg/notice");
  456. }
  457.  
  458. if (chptr->mode.floodprot && !is_skochanop(sptr, chptr) && (text[0] == '\001') && strncmp(text+1, "ACTION ", 7) && do_chanflood(chptr->mode.floodprot, FLD_CTCP) && MyClient(sptr)) {
  459. do_chanflood_action(chptr, FLD_CTCP, "CTCP");
  460. }
  461. #endif
  462. sendanyways = 0;
  463. continue;
  464. } else if (MyClient(sptr)) {
  465. sendto_one(sptr, err_str(ERR_CHANOPRIVSNEEDED), me.name, parv[0], chptr->chname);
  466. }
  467. continue;
  468. } else {
  469. sendto_one(sptr, err_str(ERR_NOSUCHCHANNEL), me.name, parv[0], nick);
  470. continue;
  471. }
  472. }
  473. return 0;
  474. }
  475.  
  476. /*
  477. ** m_ambiance
  478. ** parv[0] = sender prefix
  479. ** parv[1] = receiver list
  480. ** parv[2] = message text
  481. */
  482.  
  483. DLLFUNC int m_ambiance(aClient *cptr, aClient *sptr, int parc, char *parv[])
  484. {
  485. return m_roleplay(cptr, sptr, parc, parv, 0);
  486. }
  487.  
  488. /*
  489. ** m_npc
  490. ** parv[0] = sender prefix
  491. ** parv[1] = receiver list
  492. ** parv[2] = notice text
  493. */
  494.  
  495. DLLFUNC int m_npc(aClient *cptr, aClient *sptr, int parc, char *parv[])
  496. {
  497. return m_roleplay(cptr, sptr, parc, parv, 1);
  498. }
  499.  
  500. /*
  501. ** m_npca
  502. ** parv[0] = sender prefix
  503. ** parv[1] = receiver list
  504. ** parv[2] = notice text
  505. */
  506.  
  507.  
  508. DLLFUNC int m_npca(aClient *cptr, aClient *sptr, int parc, char *parv[])
  509. {
  510. return m_roleplay(cptr, sptr, parc, parv, 2);
  511. }
  512.  
  513. /*
  514. ** m_fsay
  515. ** parv[0] = sender prefix
  516. ** parv[1] = receiver list
  517. ** parv[2] = notice text4
  518. */
  519.  
  520. DLLFUNC int m_fsay(aClient *cptr, aClient *sptr, int parc, char *parv[])
  521. {
  522. return m_roleplay(cptr, sptr, parc, parv, (!MyClient(sptr) || CanFSay(sptr)) ? 3 : 1);
  523. }
  524.  
  525. /*
  526. ** m_faction
  527. ** parv[0] = sender prefix
  528. ** parv[1] = receiver list44
  529. ** parv[2] = notice text
  530. */
  531.  
  532.  
  533. DLLFUNC int m_faction(aClient *cptr, aClient *sptr, int parc, char *parv[])
  534. {
  535. return m_roleplay(cptr, sptr, parc, parv, (!MyClient(sptr) || CanFSay(sptr)) ? 4 : 2);
  536. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement