ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/c_party.C
Revision: 1.20
Committed: Sun Jul 1 05:00:19 2007 UTC (16 years, 10 months ago) by root
Content type: text/plain
Branch: MAIN
CVS Tags: rel-2_2, rel-2_3
Changes since 1.19: +10 -11 lines
Log Message:
- upgrade crossfire trt to the GPL version 3 (hopefully correctly).
- add a single file covered by the GNU Affero General Public License
  (which is not yet released, so I used the current draft, which is
  legally a bit wavy, but its likely better than nothing as it expresses
  direct intent by the authors, and we can upgrade as soon as it has been
  released).
  * this should ensure availability of source code for the server at least
    and hopefully also archetypes and maps even when modified versions
    are not being distributed, in accordance of section 13 of the agplv3.

File Contents

# User Rev Content
1 elmex 1.1 /*
2 root 1.19 * This file is part of Crossfire TRT, the Roguelike Realtime MORPG.
3 pippijn 1.15 *
4 root 1.19 * Copyright (©) 2005,2006,2007 Marc Alexander Lehmann / Robin Redeker / the Crossfire TRT team
5     * Copyright (©) 2002,2007 Mark Wedel & Crossfire Development Team
6     * Copyright (©) 1992,2007 Frank Tore Johansen
7 pippijn 1.15 *
8 root 1.20 * Crossfire TRT is free software: you can redistribute it and/or modify
9     * it under the terms of the GNU General Public License as published by
10     * the Free Software Foundation, either version 3 of the License, or
11     * (at your option) any later version.
12 pippijn 1.15 *
13 root 1.20 * This program is distributed in the hope that it will be useful,
14     * but WITHOUT ANY WARRANTY; without even the implied warranty of
15     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16     * GNU General Public License for more details.
17 pippijn 1.15 *
18 root 1.20 * You should have received a copy of the GNU General Public License
19     * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 root 1.19 *
21     * The authors can be reached via e-mail to <crossfire@schmorp.de>
22 pippijn 1.15 */
23 elmex 1.1
24     #include <global.h>
25 root 1.11 #include <sproto.h>
26 elmex 1.1 #include <spells.h>
27    
28 root 1.4 static partylist *firstparty = NULL; /* Keeps track of first party in list */
29     static partylist *lastparty = NULL; /*Keeps track of last party in list */
30 elmex 1.1
31 root 1.4 partylist *
32     get_firstparty (void)
33 elmex 1.1 {
34 root 1.4 return firstparty;
35 elmex 1.1 }
36    
37 root 1.4 void remove_party (partylist *target_party);
38 elmex 1.1
39     /* Forms the party struct for a party called 'params'. it is the responsibility
40     * of the caller to ensure that the name is unique, and that it is placed in the
41     * main party list correctly */
42 root 1.4 static partylist *
43     form_party (object *op, const char *params)
44     {
45     partylist *newparty;
46    
47     newparty = (partylist *) malloc (sizeof (partylist));
48 root 1.8 newparty->partyname = strdup (params);
49 root 1.4 newparty->total_exp = 0;
50     newparty->kills = 0;
51     newparty->passwd[0] = '\0';
52     newparty->next = NULL;
53 root 1.8 newparty->partyleader = strdup (op->name);
54 root 1.4 new_draw_info_format (NDI_UNIQUE, 0, op, "You have formed party: %s", newparty->partyname);
55     op->contr->party = newparty;
56    
57     return newparty;
58     }
59    
60     void
61     remove_party (partylist *target_party)
62     {
63     partylist *tmpparty;
64     partylist *previousparty;
65     partylist *nextparty;
66    
67     if (firstparty == NULL)
68     {
69     LOG (llevError, "remove_party(): I was asked to remove party %s, but no parties are defined", target_party->partyname);
70     return;
71     }
72 elmex 1.1
73 root 1.10 for_all_players (pl)
74 root 1.4 if (pl->party == target_party)
75     pl->party = NULL;
76 elmex 1.1
77 root 1.4 /* special case-ism for parties at the beginning and end of the list */
78     if (target_party == firstparty)
79     {
80     firstparty = firstparty->next;
81    
82     if (target_party->partyleader)
83     free (target_party->partyleader);
84    
85     if (target_party->partyname)
86     free (target_party->partyname);
87    
88     free (target_party);
89     return;
90 elmex 1.1 }
91 root 1.4 else if (target_party == lastparty)
92     {
93     for (tmpparty = firstparty; tmpparty->next != NULL; tmpparty = tmpparty->next)
94     {
95     if (tmpparty->next == target_party)
96     {
97     lastparty = tmpparty;
98    
99     if (target_party->partyleader)
100     free (target_party->partyleader);
101    
102     if (target_party->partyname)
103     free (target_party->partyname);
104    
105     free (target_party);
106     lastparty->next = NULL;
107     return;
108 root 1.2 }
109     }
110 elmex 1.1 }
111 root 1.4 for (tmpparty = firstparty; tmpparty->next != NULL; tmpparty = tmpparty->next)
112     if (tmpparty->next == target_party)
113     {
114     previousparty = tmpparty;
115     nextparty = tmpparty->next->next;
116     /* this should be safe, because we already dealt with the lastparty case */
117    
118     previousparty->next = nextparty;
119     if (target_party->partyleader)
120     free (target_party->partyleader);
121     if (target_party->partyname)
122     free (target_party->partyname);
123     free (target_party);
124     return;
125     }
126 elmex 1.1 }
127    
128     /* Remove unused parties, this could be made to scale a lot better. */
129 root 1.4 void
130     obsolete_parties (void)
131     {
132     int player_count;
133     partylist *party;
134     partylist *next = NULL;
135    
136     if (!firstparty)
137     return; /* we can't obsolete parties if there aren't any */
138     for (party = firstparty; party != NULL; party = next)
139     {
140     next = party->next;
141     player_count = 0;
142 root 1.10 for_all_players (pl)
143 root 1.4 if (pl->party == party)
144     player_count++;
145     if (player_count == 0)
146     remove_party (party);
147 elmex 1.1 }
148     }
149    
150 root 1.4 void
151 root 1.17 add_kill_to_party (partylist *party, const char *killer, const char *dead, long exp)
152 elmex 1.1 {
153 root 1.4 int i, pos;
154 elmex 1.1
155 root 1.4 if (party == NULL)
156     return;
157 root 1.12
158 root 1.4 if (party->kills >= PARTY_KILL_LOG)
159 elmex 1.1 {
160 root 1.4 pos = PARTY_KILL_LOG - 1;
161     for (i = 0; i < PARTY_KILL_LOG - 1; i++)
162     party->party_kills[i] = party->party_kills[i + 1];
163 elmex 1.1 }
164     else
165 root 1.4 pos = party->kills;
166 root 1.12
167 elmex 1.1 party->kills++;
168 root 1.4 party->total_exp += exp;
169     party->party_kills[pos].exp = exp;
170 root 1.5 assign (party->party_kills[pos].killer, killer);
171     assign (party->party_kills[pos].dead, dead);
172 root 1.4 party->party_kills[pos].killer[MAX_NAME] = 0;
173     party->party_kills[pos].dead[MAX_NAME] = 0;
174 elmex 1.1 }
175    
176 root 1.4 int
177     confirm_party_password (object *op)
178     {
179     partylist *tmppartylist;
180    
181     for (tmppartylist = firstparty; tmppartylist != NULL; tmppartylist = tmppartylist->next)
182     {
183     if (!strcmp (op->contr->party_to_join->partyname, tmppartylist->partyname))
184     {
185     if (strcmp (op->contr->write_buf + 1, tmppartylist->passwd) == 0)
186     return 0;
187     else
188     return 1;
189 root 1.2 }
190 elmex 1.1 }
191 root 1.4 return 1;
192 elmex 1.1 }
193    
194 root 1.4 void
195     receive_party_password (object *op, char k)
196     {
197    
198     if (confirm_party_password (op) == 0)
199     {
200     partylist *joined_party = op->contr->party_to_join;
201     char buf[MAX_BUF];
202    
203     op->contr->party = op->contr->party_to_join;
204     op->contr->party_to_join = NULL;
205     new_draw_info_format (NDI_UNIQUE, 0, op, "You have joined party: %s\n", joined_party->partyname);
206     snprintf (buf, MAX_BUF, "%s joins party %s", &op->name, joined_party->partyname);
207     send_party_message (op, buf);
208 root 1.9 op->contr->ns->state = ST_PLAYING;
209 root 1.4 return;
210     }
211     else
212     {
213     new_draw_info (NDI_UNIQUE, 0, op, "You entered the wrong password");
214     op->contr->party_to_join = NULL;
215 root 1.9 op->contr->ns->state = ST_PLAYING;
216 root 1.4 return;
217     }
218 elmex 1.1 }
219    
220 root 1.4 void
221     send_party_message (object *op, char *msg)
222 elmex 1.1 {
223 root 1.10 for_all_players (pl)
224 root 1.4 if (pl->ob->contr->party == op->contr->party && pl->ob != op)
225     new_draw_info (NDI_WHITE, 0, pl->ob, msg);
226 elmex 1.1 }
227    
228 root 1.4 int
229     command_gsay (object *op, char *params)
230 elmex 1.1 {
231     char party_params[MAX_BUF];
232    
233 root 1.4 if (!params)
234     return 0;
235 root 1.12
236 root 1.4 strcpy (party_params, "say ");
237     strcat (party_params, params);
238     command_party (op, party_params);
239 elmex 1.1 return 0;
240     }
241    
242 root 1.4 int
243     command_party (object *op, char *params)
244 elmex 1.1 {
245     char buf[MAX_BUF];
246 root 1.4 partylist *tmpparty, *oldparty; /* For iterating over linked list */
247     char *currentparty; /* For iterating over linked list */
248 elmex 1.1
249 root 1.4 if (params == NULL)
250     {
251     if (op->contr->party == NULL)
252     {
253     new_draw_info (NDI_UNIQUE, 0, op, "You are not a member of any party.");
254     new_draw_info (NDI_UNIQUE, 0, op, "For help try: party help");
255 elmex 1.1 }
256 root 1.4 else
257     {
258 elmex 1.1 currentparty = op->contr->party->partyname;
259 root 1.4 new_draw_info_format (NDI_UNIQUE, 0, op, "You are a member of party %s.", currentparty);
260 elmex 1.1 }
261 root 1.4 return 1;
262     }
263 root 1.7
264 root 1.4 if (strcmp (params, "help") == 0)
265     {
266     new_draw_info (NDI_UNIQUE, 0, op, "To form a party type: party form <partyname>");
267     new_draw_info (NDI_UNIQUE, 0, op, "To join a party type: party join <partyname>");
268     new_draw_info (NDI_UNIQUE, 0, op, "If the party has a passwd, it will you prompt you for it.");
269     new_draw_info (NDI_UNIQUE, 0, op, "For a list of current parties type: party list");
270     new_draw_info (NDI_UNIQUE, 0, op, "To leave a party type: party leave");
271     new_draw_info (NDI_UNIQUE, 0, op, "To change a passwd for a party type: party passwd <password>");
272     new_draw_info (NDI_UNIQUE, 0, op, "There is an 8 character max");
273     new_draw_info (NDI_UNIQUE, 0, op, "To talk to party members type: party say <msg>");
274     new_draw_info (NDI_UNIQUE, 0, op, "To see who is in your party: party who");
275     new_draw_info (NDI_UNIQUE, 0, op, "To see what you've killed, type: party kills");
276     return 1;
277     }
278 root 1.7
279 root 1.4 if (!strncmp (params, "kills", 5))
280 elmex 1.1 {
281 root 1.4 int i, max;
282 elmex 1.1 char chr;
283     char buffer[80];
284     float exp;
285    
286 root 1.4 if (op->contr->party == NULL)
287 root 1.2 {
288 root 1.4 new_draw_info (NDI_UNIQUE, 0, op, "You are not a member of any party.");
289 root 1.2 return 1;
290     }
291 elmex 1.1 tmpparty = op->contr->party;
292 root 1.4 if (!tmpparty->kills)
293 root 1.2 {
294 root 1.4 new_draw_info (NDI_UNIQUE, 0, op, "You haven't killed anything yet.");
295 root 1.2 return 1;
296     }
297 root 1.4 max = tmpparty->kills - 1;
298     if (max > PARTY_KILL_LOG - 1)
299     max = PARTY_KILL_LOG - 1;
300     new_draw_info (NDI_UNIQUE, 0, op, "Killed | Killer| Exp");
301     new_draw_info (NDI_UNIQUE, 0, op, "----------------+----------------+--------");
302     for (i = 0; i <= max; i++)
303     {
304     exp = tmpparty->party_kills[i].exp;
305     chr = ' ';
306     if (exp > 1000000)
307     {
308     exp /= 1000000;
309     chr = 'M';
310     }
311     else if (exp > 1000)
312     {
313     exp /= 1000;
314     chr = 'k';
315     }
316     sprintf (buffer, "%16s|%16s|%6.1f%c", tmpparty->party_kills[i].dead, tmpparty->party_kills[i].killer, exp, chr);
317     new_draw_info (NDI_UNIQUE, 0, op, buffer);
318     }
319     exp = tmpparty->total_exp;
320     chr = ' ';
321     if (exp > 1000000)
322     {
323     exp /= 1000000;
324     chr = 'M';
325     }
326     else if (exp > 1000)
327     {
328     exp /= 1000;
329     chr = 'k';
330     }
331     new_draw_info (NDI_UNIQUE, 0, op, "----------------+----------------+--------");
332     sprintf (buffer, "Totals: %d kills, %.1f%c exp", tmpparty->kills, exp, chr);
333     new_draw_info (NDI_UNIQUE, 0, op, buffer);
334 elmex 1.1 return 1;
335     }
336 root 1.7
337 root 1.4 if (strncmp (params, "say ", 4) == 0)
338 elmex 1.1 {
339 root 1.4 if (op->contr->party == NULL)
340     {
341     new_draw_info (NDI_UNIQUE, 0, op, "You are not a member of any party.");
342     return 1;
343     }
344     params += 4;
345     currentparty = op->contr->party->partyname;
346     snprintf (buf, MAX_BUF - 1, "[%s] %s says: %s", currentparty, &op->name, params);
347     send_party_message (op, buf);
348 root 1.7 new_draw_info_format (NDI_LT_GREEN | NDI_UNIQUE, 0, op, "[%s] You say: %s", currentparty, params);
349 root 1.4 return 1;
350     }
351    
352     if (strncmp (params, "form ", 5) == 0)
353     {
354     int player_count;
355    
356     params += 5;
357     if (op->contr->party)
358     oldparty = op->contr->party;
359     else
360     oldparty = NULL;
361    
362     if (firstparty)
363     {
364     for (tmpparty = firstparty; tmpparty != NULL; tmpparty = tmpparty->next)
365 elmex 1.1 {
366 root 1.4 if (!strcmp (tmpparty->partyname, params))
367     {
368     new_draw_info_format (NDI_UNIQUE, 0, op, "The party %s already exists, pick another name", params);
369     return 1;
370     }
371 elmex 1.1 }
372 root 1.4 lastparty->next = form_party (op, params);
373     lastparty = lastparty->next;
374     }
375     else
376     {
377     firstparty = form_party (op, params);
378     lastparty = firstparty;
379     }
380     /*
381     * The player might have previously been a member of a party, if so, he will be leaving
382     * it, so check if there are any other members and if not, delete the party
383     */
384     player_count = 0;
385     if (oldparty)
386     {
387 root 1.14 for_all_players (pl)
388     if (pl->party == oldparty)
389     player_count++;
390    
391 root 1.4 if (player_count == 0)
392     remove_party (oldparty);
393 root 1.2 }
394 root 1.14
395 root 1.4 return 0;
396     } /* form */
397    
398     if (strcmp (params, "leave") == 0)
399     {
400     if (op->contr->party == NULL)
401     {
402     new_draw_info (NDI_UNIQUE, 0, op, "You are not a member of any party.");
403     return 1;
404 root 1.2 }
405 root 1.4 currentparty = op->contr->party->partyname;
406     new_draw_info_format (NDI_UNIQUE, 0, op, "You leave party %s.", currentparty);
407     sprintf (buf, "%s leaves party %s.", &op->name, currentparty);
408     send_party_message (op, buf);
409     op->contr->party = NULL;
410     return 1;
411 elmex 1.1 }
412 root 1.7
413 root 1.4 if (strcmp (params, "who") == 0)
414     {
415     tmpparty = op->contr->party;
416     if (op->contr->party == NULL)
417     {
418     new_draw_info (NDI_UNIQUE, 0, op, "You are not a member of any party.");
419     return 1;
420     }
421     new_draw_info_format (NDI_UNIQUE, 0, op, "Members of party: %s.", op->contr->party->partyname);
422 root 1.10 for_all_players (pl)
423 root 1.4 if (pl->ob->contr->party == op->contr->party)
424     {
425     if (settings.set_title == TRUE)
426     {
427     if (pl->ob->contr->own_title[0] != '\0')
428     sprintf (buf, "%3d %s the %s", pl->ob->level, &pl->ob->name, pl->ob->contr->own_title);
429     else
430     sprintf (buf, "%3d %s the %s", pl->ob->level, &pl->ob->name, pl->ob->contr->title);
431     }
432     else
433     sprintf (buf, "%3d %s the %s", pl->ob->level, &pl->ob->name, pl->ob->contr->title);
434     new_draw_info (NDI_UNIQUE, 0, op, buf);
435     }
436 elmex 1.1 return 1;
437 root 1.4 } /* leave */
438 elmex 1.1
439 root 1.4 if (strncmp (params, "passwd ", 7) == 0)
440     {
441     partylist *tmplist;
442 elmex 1.1
443 root 1.4 params += 7;
444 elmex 1.1
445 root 1.4 if (op->contr->party == NULL)
446     {
447     new_draw_info (NDI_UNIQUE, 0, op, "You are not a member of a party");
448     return 1;
449     }
450 elmex 1.1
451 root 1.4 if (strlen (params) > 8)
452     {
453     new_draw_info (NDI_UNIQUE, 0, op, "The password must not exceed 8 characters");
454     return 1;
455     }
456 elmex 1.1
457 root 1.4 tmplist = firstparty;
458     while (tmplist != NULL)
459     {
460     if (tmplist == op->contr->party)
461     {
462     strcpy (tmplist->passwd, params);
463     new_draw_info_format (NDI_UNIQUE, 0, op, "The password for party %s is %s", tmplist->partyname, tmplist->passwd);
464     snprintf (buf, MAX_BUF, "Password for party %s is now %s, changed by %s", tmplist->partyname, tmplist->passwd, &op->name);
465     send_party_message (op, buf);
466     return 0;
467     }
468     tmplist = tmplist->next;
469     }
470     return 0;
471     } /* passwd */
472 elmex 1.1
473 root 1.4 if (strcmp (params, "list") == 0)
474     {
475     partylist *tmplist;
476 elmex 1.1
477 root 1.4 tmplist = firstparty;
478 elmex 1.1
479 root 1.4 if (firstparty == NULL)
480     {
481     new_draw_info (NDI_UNIQUE, 0, op, "There are no parties active right now");
482     return 1;
483     }
484 elmex 1.1
485 root 1.4 new_draw_info (NDI_UNIQUE, 0, op, "Party name Leader");
486     new_draw_info (NDI_UNIQUE, 0, op, "---------- ------");
487 elmex 1.1
488 root 1.4 while (tmplist != NULL)
489     {
490     new_draw_info_format (NDI_UNIQUE, 0, op, "%-32s %s", tmplist->partyname, tmplist->partyleader);
491     tmplist = tmplist->next;
492     }
493     return 0;
494     } /* list */
495 elmex 1.1
496 root 1.4 if (strncmp (params, "join ", 5) == 0)
497     {
498 elmex 1.1
499 root 1.4 params += 5;
500 elmex 1.1
501 root 1.4 /* Can't join a party cause non exist */
502     if (firstparty == NULL)
503     {
504     new_draw_info_format (NDI_UNIQUE, 0, op, "Party: %s does not exist. You must form it first", params);
505 elmex 1.1 return 1;
506     }
507 root 1.4
508     /* Special case if thier is only one party */
509     if (firstparty->next == NULL)
510     {
511     if (strcmp (firstparty->partyname, params) != 0)
512     {
513     new_draw_info_format (NDI_UNIQUE, 0, op, "Party: %s does not exist. You must form it first", params);
514     return 1;
515     }
516     else
517     {
518     if (op->contr->party == firstparty)
519     {
520     new_draw_info_format (NDI_UNIQUE, 0, op, "You are already in party: %s", firstparty->partyname);
521     return 1;
522     }
523     /* found party player wants to join */
524     if (firstparty->passwd[0] == '\0')
525     {
526     op->contr->party = firstparty;
527     new_draw_info_format (NDI_UNIQUE, 0, op, "You have joined party: %s", firstparty->partyname);
528     snprintf (buf, MAX_BUF, "%s joins party %s", &op->name, firstparty->partyname);
529     send_party_message (op, buf);
530     return 0;
531     }
532     else
533     {
534     get_party_password (op, firstparty);
535     return 0;
536     }
537     }
538 elmex 1.1 }
539    
540 root 1.4 tmpparty = firstparty;
541     while (tmpparty != NULL)
542     {
543     if (strcmp (tmpparty->partyname, params) == 0)
544     {
545     if (op->contr->party == tmpparty)
546     {
547     new_draw_info_format (NDI_UNIQUE, 0, op, "You are already a member of party: %s", tmpparty->partyname);
548     return 1;
549     }
550     else
551     {
552     if (tmpparty->passwd[0] == '\0')
553     {
554     new_draw_info_format (NDI_UNIQUE, 0, op, "You have joined party: %s", tmpparty->partyname);
555     op->contr->party = tmpparty;
556     snprintf (buf, MAX_BUF, "%s joins party %s", &op->name, tmpparty->partyname);
557     send_party_message (op, buf);
558     return 0;
559     }
560     else
561     {
562     get_party_password (op, tmpparty);
563     return 0;
564     }
565     }
566     }
567     else
568     tmpparty = tmpparty->next;
569 elmex 1.1 }
570    
571 root 1.4 new_draw_info_format (NDI_UNIQUE, 0, op, "Party %s does not exist. You must form it first.", params);
572     return 1;
573     } /* join */
574    
575     new_draw_info (NDI_UNIQUE, 0, op, "To form a party type: party form <partyname>");
576     new_draw_info (NDI_UNIQUE, 0, op, "To join a party type: party join <partyname>");
577     new_draw_info (NDI_UNIQUE, 0, op, "If the party has a passwd, it will you prompt you for it.");
578     new_draw_info (NDI_UNIQUE, 0, op, "For a list of current parties type: party list");
579     new_draw_info (NDI_UNIQUE, 0, op, "To leave a party type: party leave");
580     new_draw_info (NDI_UNIQUE, 0, op, "To change a passwd for a party type: party passwd <password>");
581     new_draw_info (NDI_UNIQUE, 0, op, "There is an 8 character max");
582     new_draw_info (NDI_UNIQUE, 0, op, "To talk to party members type: party say <msg>");
583     new_draw_info (NDI_UNIQUE, 0, op, "To see who is in your party: party who");
584     new_draw_info (NDI_UNIQUE, 0, op, "To see what you've killed, type: party kills");
585 elmex 1.1 return 1;
586     }