root/src/map/chat.c @ 6

Revision 1, 8.8 kB (checked in by jinshiro, 17 years ago)
Line 
1// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
2// For more information, see LICENCE in the main folder
3
4#include "../common/cbasetypes.h"
5#include "../common/malloc.h"
6#include "../common/nullpo.h"
7#include "../common/strlib.h"
8#include "atcommand.h" // msg_txt()
9#include "battle.h" // struct battle_config
10#include "clif.h"
11#include "map.h"
12#include "npc.h" // npc_event_do()
13#include "pc.h"
14#include "chat.h"
15
16#include <stdio.h>
17#include <string.h>
18
19
20int chat_triggerevent(struct chat_data *cd); // forward declaration
21
22/// Initializes a chatroom object (common functionality for both pc and npc chatrooms).
23/// Returns a chatroom object on success, or NULL on failure.
24static struct chat_data* chat_createchat(struct block_list* bl, const char* title, const char* pass, int limit, bool pub, int trigger, const char* ev)
25{
26        struct chat_data* cd;
27        nullpo_retr(NULL, bl);
28
29        cd = (struct chat_data *) aMalloc(sizeof(struct chat_data));
30
31        safestrncpy(cd->title, title, sizeof(cd->title));
32        safestrncpy(cd->pass, pass, sizeof(cd->pass));
33        cd->pub = pub;
34        cd->users = 0;
35        cd->limit = min(limit, ARRAYLENGTH(cd->usersd));
36        cd->trigger = trigger;
37        memset(cd->usersd, 0, sizeof(cd->usersd));
38        cd->owner = bl;
39        safestrncpy(cd->npc_event, ev, sizeof(cd->npc_event));
40
41        cd->bl.m    = bl->m;
42        cd->bl.x    = bl->x;
43        cd->bl.y    = bl->y;
44        cd->bl.type = BL_CHAT;
45        cd->bl.next = cd->bl.prev = NULL;
46        cd->bl.id   = map_addobject(&cd->bl);
47
48        if( cd->bl.id == 0 )
49        {
50                aFree(cd);
51                cd = NULL;
52        }
53
54        return cd;
55}
56
57/*==========================================
58 * player chatroom creation
59 *------------------------------------------*/
60int chat_createpcchat(struct map_session_data* sd, const char* title, const char* pass, int limit, bool pub)
61{
62        struct chat_data* cd;
63        nullpo_retr(0, sd);
64
65        if( sd->chatID )
66                return 0; //Prevent people abusing the chat system by creating multiple chats, as pointed out by End of Exam. [Skotlex]
67
68        if( map[sd->bl.m].flag.nochat )
69        {
70                clif_displaymessage(sd->fd, msg_txt(281));
71                return 0; //Can't create chatrooms on this map.
72        }
73
74        if( map_getcell(sd->bl.m,sd->bl.x,sd->bl.y,CELL_CHKNOCHAT) )
75        {
76                clif_displaymessage (sd->fd, "Can't create chat rooms in this Area.");
77                return 0;
78        }
79
80        pc_stop_walking(sd,1);
81
82        cd = chat_createchat(&sd->bl, title, pass, limit, pub, 0, "");
83        if( cd )
84        {
85                cd->users = 1;
86                cd->usersd[0] = sd;
87                pc_setchatid(sd,cd->bl.id);
88                clif_createchat(sd,0);
89                clif_dispchat(cd,0);
90        }
91        else
92                clif_createchat(sd,1);
93
94        return 0;
95}
96
97/*==========================================
98 * join an existing chatroom
99 *------------------------------------------*/
100int chat_joinchat(struct map_session_data* sd, int chatid, const char* pass)
101{
102        struct chat_data* cd;
103
104        nullpo_retr(0, sd);
105        cd = (struct chat_data*)map_id2bl(chatid);
106
107        if( cd == NULL || cd->bl.type != BL_CHAT || cd->bl.m != sd->bl.m || sd->vender_id || sd->chatID || cd->users >= cd->limit )
108        {
109                clif_joinchatfail(sd,0);
110                return 0;
111        }
112
113        if( !cd->pub && strncmp(pass, cd->pass, sizeof(cd->pass)) != 0 && !(battle_config.gm_join_chat && pc_isGM(sd) >= battle_config.gm_join_chat) )
114        {
115                clif_joinchatfail(sd,1);
116                return 0;
117        }
118
119        pc_stop_walking(sd,1);
120        cd->usersd[cd->users] = sd;
121        cd->users++;
122
123        pc_setchatid(sd,cd->bl.id);
124
125        clif_joinchatok(sd,cd); // V‚œ‚ÉŽQ‰Á‚µ‚œl‚ɂ͑Sˆõ‚ÌƒŠƒXƒg
126        clif_addchat(cd,sd);    // Šù‚É’†‚É‹‚œl‚ɂ͒ljÁ‚µ‚œl‚Ì•ñ
127        clif_dispchat(cd,0);    // ŽüˆÍ‚̐l‚ɂ͐l”•ω»•ñ
128
129        chat_triggerevent(cd); // ƒCƒxƒ“ƒg
130       
131        return 0;
132}
133
134
135/*==========================================
136 * leave a chatroom
137 *------------------------------------------*/
138int chat_leavechat(struct map_session_data* sd, bool kicked)
139{
140        struct chat_data* cd;
141        int i;
142        int leavechar;
143
144        nullpo_retr(1, sd);
145
146        cd = (struct chat_data*)map_id2bl(sd->chatID);
147        if( cd == NULL )
148        {
149                pc_setchatid(sd, 0);
150                return 1;
151        }
152
153        ARR_FIND( 0, cd->users, i, cd->usersd[i] == sd );
154        if ( i == cd->users )
155        {       // Not found in the chatroom?
156                pc_setchatid(sd, 0);
157                return -1;
158        }
159
160        clif_leavechat(cd, sd, kicked);
161        pc_setchatid(sd, 0);
162        cd->users--;
163
164        leavechar = i;
165
166        for( i = leavechar; i < cd->users; i++ )
167                cd->usersd[i] = cd->usersd[i+1];
168
169
170        if( cd->users == 0 && cd->owner->type == BL_PC )
171        {       // Delete empty chatroom
172                clif_clearchat(cd, 0);
173                map_delobject(cd->bl.id);
174                return 1;
175        }
176
177        if( leavechar == 0 && cd->owner->type == BL_PC )
178        {       // Set and announce new owner
179                cd->owner = (struct block_list*) cd->usersd[0];
180                clif_changechatowner(cd, cd->usersd[0]);
181                clif_clearchat(cd, 0);
182
183                //Adjust Chat location after owner has been changed.
184                map_delblock( &cd->bl );
185                cd->bl.x=cd->usersd[0]->bl.x;
186                cd->bl.y=cd->usersd[0]->bl.y;
187                map_addblock( &cd->bl );
188
189                clif_dispchat(cd,0);
190        }
191        else
192                clif_dispchat(cd,0); // refresh chatroom
193
194        return 0;
195}
196
197/*==========================================
198 * change a chatroom's owner
199 *------------------------------------------*/
200int chat_changechatowner(struct map_session_data* sd, const char* nextownername)
201{
202        struct chat_data* cd;
203        struct map_session_data* tmpsd;
204        int i;
205
206        nullpo_retr(1, sd);
207
208        cd = (struct chat_data*)map_id2bl(sd->chatID);
209        if( cd == NULL || (struct block_list*) sd != cd->owner )
210                return 1;
211
212        ARR_FIND( 1, cd->users, i, strncmp(cd->usersd[i]->status.name, nextownername, NAME_LENGTH) == 0 );
213        if( i == cd->users )
214                return -1;  // name not found
215
216        // erase temporarily
217        clif_clearchat(cd,0);
218
219        // set new owner
220        cd->owner = (struct block_list*) cd->usersd[i];
221        clif_changechatowner(cd,cd->usersd[i]);
222
223        // swap the old and new owners' positions
224        tmpsd = cd->usersd[i];
225        cd->usersd[i] = cd->usersd[0];
226        cd->usersd[0] = tmpsd;
227
228        // set the new chatroom position
229        map_delblock( &cd->bl );
230        cd->bl.x = cd->owner->x;
231        cd->bl.y = cd->owner->y;
232        map_addblock( &cd->bl );
233
234        // and display again
235        clif_dispchat(cd,0);
236
237        return 0;
238}
239
240/*==========================================
241 * change a chatroom's status (title, etc)
242 *------------------------------------------*/
243int chat_changechatstatus(struct map_session_data* sd, const char* title, const char* pass, int limit, bool pub)
244{
245        struct chat_data* cd;
246
247        nullpo_retr(1, sd);
248
249        cd = (struct chat_data*)map_id2bl(sd->chatID);
250        if( cd==NULL || (struct block_list *)sd != cd->owner )
251                return 1;
252
253        safestrncpy(cd->title, title, CHATROOM_TITLE_SIZE);
254        safestrncpy(cd->pass, pass, CHATROOM_PASS_SIZE);
255        cd->limit = min(limit, ARRAYLENGTH(cd->usersd));
256        cd->pub = pub;
257
258        clif_changechatstatus(cd);
259        clif_dispchat(cd,0);
260
261        return 0;
262}
263
264/*==========================================
265 * kick an user from a chatroom
266 *------------------------------------------*/
267int chat_kickchat(struct map_session_data* sd, const char* kickusername)
268{
269        struct chat_data* cd;
270        int i;
271
272        nullpo_retr(1, sd);
273
274        cd = (struct chat_data *)map_id2bl(sd->chatID);
275       
276        if( cd==NULL || (struct block_list *)sd != cd->owner )
277                return -1;
278
279        ARR_FIND( 0, cd->users, i, strncmp(cd->usersd[i]->status.name, kickusername, NAME_LENGTH) == 0 );
280        if( i == cd->users )
281                return -1;
282
283        if( battle_config.gm_kick_chat && pc_isGM(cd->usersd[i]) >= battle_config.gm_kick_chat )
284                return 0; //gm kick protection [Valaris]
285
286        chat_leavechat(cd->usersd[i],1);
287        return 0;
288}
289
290/// Creates a chat room for the npc.
291int chat_createnpcchat(struct npc_data* nd, const char* title, int limit, bool pub, int trigger, const char* ev)
292{
293        struct chat_data* cd;
294        nullpo_retr(0, nd);
295
296        cd = chat_createchat(&nd->bl, title, "", limit, pub, trigger, ev);
297        if( cd )
298        {
299                nd->chat_id = cd->bl.id;
300                clif_dispchat(cd,0);
301        }
302
303        return 0;
304}
305
306/// Removes the chatroom from the npc.
307int chat_deletenpcchat(struct npc_data* nd)
308{
309        struct chat_data *cd;
310        nullpo_retr(0, nd);
311
312        cd = (struct chat_data*)map_id2bl(nd->chat_id);
313        if( cd == NULL )
314                return 0;
315       
316        chat_npckickall(cd);
317        clif_clearchat(cd, 0);
318        map_delobject(cd->bl.id);       // free‚܂łµ‚Ä‚­‚ê‚é
319        nd->chat_id = 0;
320       
321        return 0;
322}
323
324/*==========================================
325 * ‹K’èl”ˆÈã‚ŃCƒxƒ“ƒg‚ª’è‹`‚³‚ê‚Ä‚é‚È‚çŽÀs
326 *------------------------------------------*/
327int chat_triggerevent(struct chat_data *cd)
328{
329        nullpo_retr(0, cd);
330
331        if( cd->users >= cd->trigger && cd->npc_event[0] )
332                npc_event_do(cd->npc_event);
333        return 0;
334}
335
336/// Enables the event of the chat room.
337/// At most, 127 users are needed to trigger the event.
338int chat_enableevent(struct chat_data* cd)
339{
340        nullpo_retr(0, cd);
341
342        cd->trigger &= 0x7f;
343        chat_triggerevent(cd);
344        return 0;
345}
346
347/// Disables the event of the chat room
348int chat_disableevent(struct chat_data* cd)
349{
350        nullpo_retr(0, cd);
351
352        cd->trigger |= 0x80;
353        return 0;
354}
355
356/// Kicks all the users from the chat room.
357int chat_npckickall(struct chat_data* cd)
358{
359        nullpo_retr(0, cd);
360
361        while( cd->users > 0 )
362                chat_leavechat(cd->usersd[cd->users-1],0);
363
364        return 0;
365}
Note: See TracBrowser for help on using the browser.