Crossfire Server, Branches 1.12  R18729
c_party.c
Go to the documentation of this file.
1 /*
2  * static char *rcsid_c_party_c =
3  * "$Id: c_party.c 11876 2009-06-14 19:42:19Z akirschbaum $";
4  */
5 
6 /*
7  CrossFire, A Multiplayer game for X-windows
8 
9  Copyright (C) 2002 Mark Wedel & Crossfire Development Team
10  Copyright (C) 1992 Frank Tore Johansen
11 
12  This program is free software; you can redistribute it and/or modify
13  it under the terms of the GNU General Public License as published by
14  the Free Software Foundation; either version 2 of the License, or
15  (at your option) any later version.
16 
17  This program is distributed in the hope that it will be useful,
18  but WITHOUT ANY WARRANTY; without even the implied warranty of
19  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20  GNU General Public License for more details.
21 
22  You should have received a copy of the GNU General Public License
23  along with this program; if not, write to the Free Software
24  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 
26  The authors can be reached via e-mail at crossfire-devel@real-time.com
27 */
28 
34 #include <global.h>
35 #ifndef __CEXTRACT__
36 #include <sproto.h>
37 #endif
38 #include <spells.h>
39 
40 static partylist *firstparty = NULL;
41 static partylist *lastparty = NULL;
49  return firstparty;
50 }
51 
52 void remove_party(partylist *target_party);
53 
65 partylist *form_party(object *op, const char *params) {
66  partylist *newparty;
67 
68  if (op->contr->party != NULL) {
69  char buf[MAX_BUF];
70 
71  snprintf(buf, sizeof(buf), "%s leaves party %s.", op->name, op->contr->party->partyname);
72  send_party_message(op, buf);
73  }
74  newparty = (partylist *)malloc(sizeof(partylist));
75  newparty->partyname = strdup_local(params);
77  newparty->total_exp = 0;
78  newparty->kills = 0;
79  newparty->passwd[0] = '\0';
80  newparty->next = NULL;
81  newparty->partyleader = strdup_local(op->name);
83  "You have formed party: %s",
84  "You have formed party: %s",
85  newparty->partyname);
86  op->contr->party = newparty;
87 
88  if (lastparty) {
89  lastparty->next = newparty;
90  lastparty = lastparty->next;
91  } else {
92  firstparty = newparty;
93  lastparty = firstparty;
94  }
95 
96  return newparty;
97 }
98 
106 void remove_party(partylist *target_party) {
107  partylist *tmpparty;
108  partylist *previousparty;
109  partylist *nextparty;
110  player *pl;
111 
112  if (firstparty == NULL) {
113  LOG(llevError, "remove_party(): I was asked to remove party %s, but no parties are defined\n",
114  target_party->partyname);
115  return;
116  }
117  for (pl = first_player; pl != NULL; pl = pl->next)
118  if (pl->party == target_party)
119  pl->party = NULL;
120 
121  /* special case-ism for parties at the beginning and end of the list */
122  if (target_party == firstparty) {
123  if (lastparty == target_party)
124  lastparty = NULL;
125  firstparty = firstparty->next;
126  if (target_party->partyleader)
127  free(target_party->partyleader);
128  if (target_party->partyname)
129  free(target_party->partyname);
130  free(target_party);
131  return;
132  } else if (target_party == lastparty) {
133  for (tmpparty = firstparty; tmpparty->next != NULL; tmpparty = tmpparty->next) {
134  if (tmpparty->next == target_party) {
135  lastparty = tmpparty;
136  if (target_party->partyleader)
137  free(target_party->partyleader);
138  if (target_party->partyname)
139  free(target_party->partyname);
140  free(target_party);
141  lastparty->next = NULL;
142  return;
143  }
144  }
145  }
146  for (tmpparty = firstparty; tmpparty->next != NULL; tmpparty = tmpparty->next)
147  if (tmpparty->next == target_party) {
148  previousparty = tmpparty;
149  nextparty = tmpparty->next->next;
150  /* this should be safe, because we already dealt with the lastparty case */
151 
152  previousparty->next = nextparty;
153  if (target_party->partyleader)
154  free(target_party->partyleader);
155  if (target_party->partyname)
156  free(target_party->partyname);
157  free(target_party);
158  return;
159  }
160 }
161 
165 void obsolete_parties(void) {
166  int player_count;
167  player *pl;
168  partylist *party;
169  partylist *next = NULL;
170 
171  if (!firstparty)
172  return; /* we can't obsolete parties if there aren't any */
173  for (party = firstparty; party != NULL; party = next) {
174  next = party->next;
175  player_count = 0;
176  for (pl = first_player; pl != NULL; pl = pl->next)
177  if (pl->party == party)
178  player_count++;
179  if (player_count == 0)
180  remove_party(party);
181  }
182 }
183 
184 #ifdef PARTY_KILL_LOG
185 
197 void add_kill_to_party(partylist *party, const char *killer, const char *dead, long exp) {
198  int i, pos;
199 
200  if (party == NULL)
201  return;
202  if (party->kills >= PARTY_KILL_LOG) {
203  pos = PARTY_KILL_LOG-1;
204  for (i = 0; i < PARTY_KILL_LOG-1; i++)
205  memcpy(&(party->party_kills[i]), &(party->party_kills[i+1]), sizeof(party->party_kills[0]));
206  } else
207  pos = party->kills;
208  party->kills++;
209  party->total_exp += exp;
210  party->party_kills[pos].exp = exp;
211  strncpy(party->party_kills[pos].killer, killer, MAX_NAME);
212  strncpy(party->party_kills[pos].dead, dead, MAX_NAME);
213  party->party_kills[pos].killer[MAX_NAME] = 0;
214  party->party_kills[pos].dead[MAX_NAME] = 0;
215 }
216 #endif
217 
228 int confirm_party_password(object *op) {
229  partylist *tmppartylist;
230 
231  for (tmppartylist = firstparty; tmppartylist != NULL; tmppartylist = tmppartylist->next) {
232  if (!strcmp(op->contr->party_to_join->partyname, tmppartylist->partyname)) {
233  if (strcmp(op->contr->write_buf+1, tmppartylist->passwd) == 0)
234  return 0;
235  else
236  return 1;
237  }
238  }
239  return 1;
240 }
241 
248 void receive_party_password(object *op) {
249 
250  if (confirm_party_password(op) == 0) {
251  partylist *joined_party = op->contr->party_to_join;
252  char buf[MAX_BUF];
253 
254  if (op->contr->party != NULL) {
255  snprintf(buf, sizeof(buf), "%s leaves party %s.", op->name, op->contr->party->partyname);
256  send_party_message(op, buf);
257  }
258  op->contr->party = op->contr->party_to_join;
259  op->contr->party_to_join = NULL;
261  "You have joined party: %s\n",
262  "You have joined party: %s\n",
263  joined_party->partyname);
264  snprintf(buf, MAX_BUF, "%s joins party %s", op->name, joined_party->partyname);
265  send_party_message(op, buf);
266  op->contr->state = ST_PLAYING;
267  return;
268  } else {
270  "You entered the wrong password", NULL);
271  op->contr->party_to_join = NULL;
272  op->contr->state = ST_PLAYING;
273  return;
274  }
275 }
276 
285 void send_party_message(object *op, char *msg) {
286  player *pl;
287 
288  for (pl = first_player; pl != NULL; pl = pl->next)
289  if (pl->ob->contr->party == op->contr->party && pl->ob != op)
291  msg, NULL);
292 }
293 
304 int command_gsay(object *op, char *params) {
305  char party_params[MAX_BUF];
306 
307  if (!params) {
309  return 0;
310  }
311  strcpy(party_params, "say ");
312  strcat(party_params, params);
313  command_party(op, party_params);
314  return 0;
315 }
316 
323 static void party_help(object *op) {
325  "To form a party type: party form <partyname>. "
326  "To join a party type: party join <partyname> "
327  "If the party has a passwd, it will you prompt you for it. "
328  "For a list of current parties type: party list. "
329  "To leave a party type: party leave "
330  "To change a passwd for a party type: party passwd <password> "
331  "There is an 8 character maximum password length. "
332  "To talk to party members type: party say <msg> "
333  "To see who is in your party: party who "
334 #ifdef PARTY_KILL_LOG
335  "To see what you've killed, type: party kills"
336 #endif
337  , NULL);
338 }
339 
350 int command_party(object *op, char *params) {
351  char buf[MAX_BUF];
352  partylist *tmpparty, *oldparty; /* For iterating over linked list */
353  char *currentparty; /* For iterating over linked list */
354 
355  if (params == NULL) {
356  if (op->contr->party == NULL) {
358  "You are not a member of any party. "
359  "For help try: party help", NULL);
360  } else {
361  currentparty = op->contr->party->partyname;
363  "You are a member of party %s.",
364  "You are a member of party %s.",
365  currentparty);
366  }
367  return 1;
368  }
369  if (strcmp(params, "help") == 0) {
370  party_help(op);
371  return 1;
372  }
373 #ifdef PARTY_KILL_LOG
374  if (!strncmp(params, "kills", 5)) {
375  int i, max;
376  char chr;
377  char buffer[80];
378  float exp;
379 
380  if (op->contr->party == NULL) {
382  "You are not a member of any party.", NULL);
383  return 1;
384  }
385  tmpparty = op->contr->party;
386  if (!tmpparty->kills) {
388  "You haven't killed anything yet.", NULL);
389  return 1;
390  }
391  max = tmpparty->kills-1;
392  if (max > PARTY_KILL_LOG-1)
393  max = PARTY_KILL_LOG-1;
395  "[fixed]Killed | Killer| Exp\n----------------+----------------+--------"
396  "Killed | Killer| Exp\n----------------+----------------+--------",
397  NULL);
398 
399 
400  for (i = 0; i <= max; i++) {
401  exp = tmpparty->party_kills[i].exp;
402  chr = ' ';
403  if (exp > 1000000) {
404  exp /= 1000000;
405  chr = 'M';
406  } else if (exp > 1000) {
407  exp /= 1000;
408  chr = 'k';
409  }
410 
412  "[fixed]%16s|%16s|%6.1f%c",
413  "%16s|%16s|%6.1f%c",
414  tmpparty->party_kills[i].dead,
415  tmpparty->party_kills[i].killer, exp, chr);
416 
417  }
418  exp = tmpparty->total_exp;
419  chr = ' ';
420  if (exp > 1000000) {
421  exp /= 1000000;
422  chr = 'M';
423  } else if (exp > 1000) {
424  exp /= 1000;
425  chr = 'k';
426  }
427 
429  "[fixed]----------------+----------------+--------",
430  "----------------+----------------+--------");
432  "Totals: %d kills, %.1f%c exp", tmpparty->kills,
433  "Totals: %d kills, %.1f%c exp", tmpparty->kills,
434  exp, chr);
435  return 1;
436  }
437 #endif /* PARTY_KILL_LOG */
438  if (strncmp(params, "say ", 4) == 0) {
439  if (op->contr->party == NULL) {
441  "You are not a member of any party.", NULL);
442  return 1;
443  }
444  params += 4;
445  currentparty = op->contr->party->partyname;
446  snprintf(buf, MAX_BUF-1, "<%s> %s says: %s", currentparty, op->name, params);
447  send_party_message(op, buf);
449  "<%s> You say: %s",
450  "<%s> You say: %s",
451  currentparty, params);
452  return 1;
453  }
454 
455  if (strncmp(params, "form ", 5) == 0) {
456  int player_count;
457  player *pl;
458 
459  params += 5;
460  if (op->contr->party)
461  oldparty = op->contr->party;
462  else
463  oldparty = NULL;
464 
465  if (firstparty) {
466  for (tmpparty = firstparty; tmpparty != NULL; tmpparty = tmpparty->next) {
467  if (!strcmp(tmpparty->partyname, params)) {
469  "The party %s already exists, pick another name",
470  "The party %s already exists, pick another name",
471  params);
472  return 1;
473  }
474  }
475  form_party(op, params);
476  } else {
477  form_party(op, params);
478  }
479  /*
480  * The player might have previously been a member of a party, if so, he will be leaving
481  * it, so check if there are any other members and if not, delete the party
482  */
483  player_count = 0;
484  if (oldparty) {
485  for (pl = first_player; pl->next != NULL; pl = pl->next) {
486  if (pl->party == oldparty)
487  player_count++;
488  }
489  if (player_count == 0)
490  remove_party(oldparty);
491  }
492  return 0;
493  } /* form */
494 
495  if (strcmp(params, "leave") == 0) {
496  if (op->contr->party == NULL) {
498  "You are not a member of any party.", NULL);
499  return 1;
500  }
501  currentparty = op->contr->party->partyname;
503  "You leave party %s.",
504  "You leave party %s.",
505  currentparty);
506  snprintf(buf, sizeof(buf), "%s leaves party %s.", op->name, currentparty);
507  send_party_message(op, buf);
508  op->contr->party = NULL;
509  return 1;
510  }
511  if (strcmp(params, "who") == 0) {
512  if (op->contr->party == NULL) {
514  "You are not a member of any party.", NULL);
515  return 1;
516  }
517  list_players(op, NULL, op->contr->party);
518  return 1;
519  } /* leave */
520 
521  if (strncmp(params, "passwd ", 7) == 0) {
522  partylist *tmplist;
523 
524  params += 7;
525 
526  if (op->contr->party == NULL) {
528  "You are not a member of a party", NULL);
529  return 1;
530  }
531 
532  if (strlen(params) > 8) {
534  "The password must not exceed 8 characters", NULL);
535  return 1;
536  }
537 
538  tmplist = firstparty;
539  while (tmplist != NULL) {
540  if (tmplist == op->contr->party) {
541  strcpy(tmplist->passwd, params);
544  "The password for party %s is %s",
545  "The password for party %s is %s",
546  tmplist->partyname, tmplist->passwd);
547 
548  snprintf(buf, MAX_BUF, "Password for party %s is now %s, changed by %s",
549  tmplist->partyname, tmplist->passwd, op->name);
550  send_party_message(op, buf);
551  return 0;
552  }
553  tmplist = tmplist->next;
554  }
555  return 0;
556  } /* passwd */
557 
558  if (strcmp(params, "list") == 0) {
559  partylist *tmplist;
560 
561  tmplist = firstparty;
562 
563  if (firstparty == NULL) {
565  "There are no parties active right now", NULL);
566  return 1;
567  }
568 
570  "[fixed]Party name Leader\n---------- ------",
571  "Party name Leader\n---------- ------");
572 
573  while (tmplist != NULL) {
575  "[fixed]%-32s %s",
576  "%-32s %s",
577  tmplist->partyname, tmplist->partyleader);
578  tmplist = tmplist->next;
579  }
580  return 0;
581  } /* list */
582 
583  if (strncmp(params, "join ", 5) == 0) {
584  params += 5;
585 
586  /* Can't join a party cause non exist */
587  if (firstparty == NULL) {
589  "Party: %s does not exist. You must form it first",
590  "Party: %s does not exist. You must form it first",
591  params);
592  return 1;
593  }
594 
595  /* Special case if thier is only one party */
596  if (firstparty->next == NULL) {
597  if (strcmp(firstparty->partyname, params) != 0) {
599  "Party: %s does not exist. You must form it first",
600  "Party: %s does not exist. You must form it first",
601  params);
602  return 1;
603  } else {
604  if (op->contr->party == firstparty) {
606  "You are already in party: %s",
607  "You are already in party: %s",
608  firstparty->partyname);
609  return 1;
610  }
611  /* found party player wants to join */
612  if (firstparty->passwd[0] == '\0') {
613  op->contr->party = firstparty;
615  "You have joined party: %s",
616  "You have joined party: %s",
617  firstparty->partyname);
618  snprintf(buf, MAX_BUF, "%s joins party %s", op->name, firstparty->partyname);
619  send_party_message(op, buf);
620  return 0;
621  } else {
622  get_party_password(op, firstparty);
623  return 0;
624  }
625  }
626  }
627 
628  tmpparty = firstparty;
629  while (tmpparty != NULL) {
630  if (strcmp(tmpparty->partyname, params) == 0) {
631  if (op->contr->party == tmpparty) {
633  "You are already a member of party: %s",
634  "You are already a member of party: %s",
635  tmpparty->partyname);
636  return 1;
637  } else {
638  if (tmpparty->passwd[0] == '\0') {
639  if (op->contr->party != NULL) {
640  snprintf(buf, sizeof(buf), "%s leaves party %s.", op->name, op->contr->party->partyname);
641  send_party_message(op, buf);
642  }
644  "You have joined party: %s",
645  "You have joined party: %s",
646  tmpparty->partyname);
647  op->contr->party = tmpparty;
648  snprintf(buf, MAX_BUF, "%s joins party %s", op->name, tmpparty->partyname);
649  send_party_message(op, buf);
650  return 0;
651  } else {
652  get_party_password(op, tmpparty);
653  return 0;
654  }
655  }
656  } else
657  tmpparty = tmpparty->next;
658  }
659 
661  "Party %s does not exist. You must form it first.",
662  "Party %s does not exist. You must form it first.",
663  params);
664  return 1;
665  } /* join */
666 
667  party_help(op);
668  return 1;
669 }
670 
672 static const char *rejoin_modes[] = {
673  "no",
674  "if_exists",
675  "always",
676  NULL
677 };
678 
688 int command_party_rejoin(object *op, char *params) {
689  int mode;
690 
691  if (!params) {
693  "party rejoin: %s", NULL, rejoin_modes[op->contr->rejoin_party]);
694  return 1;
695  }
696  for (mode = 0; rejoin_modes[mode] != NULL; mode++) {
697  if (strcmp(rejoin_modes[mode], params) == 0) {
698  op->contr->rejoin_party = mode;
700  "party rejoin is now: %s", NULL, rejoin_modes[op->contr->rejoin_party]);
701  return 1;
702  }
703  }
704  if (strlen(params) > 50)
705  params[50] = '\0';
707  "invalid mode: %s", NULL, params);
708  return 1;
709 }
Definition: player.h:146
#define NDI_WHITE
Definition: newclient.h:196
#define MSG_TYPE_COMMUNICATION_PARTY
Definition: newclient.h:542
void receive_party_password(object *op)
Definition: c_party.c:248
#define MSG_TYPE_COMMAND_SUCCESS
Definition: newclient.h:448
#define MSG_TYPE_COMMAND_HELP
Definition: newclient.h:452
static const char * rejoin_modes[]
Definition: c_party.c:672
void draw_ext_info(int flags, int pri, const object *pl, uint8 type, uint8 subtype, const char *message, const char *oldmessage)
Definition: standalone.c:171
void remove_party(partylist *target_party)
Definition: c_party.c:106
void get_party_password(object *op, partylist *party)
Definition: player.c:891
void draw_ext_info_format(int flags, int pri, const object *pl, uint8 type, uint8 subtype, const char *new_format, const char *old_format,...)
Definition: standalone.c:175
char * partyname
Definition: player.h:124
#define ST_PLAYING
Definition: define.h:886
void obsolete_parties(void)
Definition: c_party.c:165
partylist * party
Definition: player.h:237
static void party_help(object *op)
Definition: c_party.c:323
struct party_struct * next
Definition: player.h:123
int command_party_rejoin(object *op, char *params)
Definition: c_party.c:688
partylist * form_party(object *op, const char *params)
Definition: c_party.c:65
const char * name
Definition: object.h:167
uint8 state
Definition: player.h:172
struct pl * contr
Definition: object.h:134
char * strdup_local(const char *str)
Definition: porting.c:310
party_rejoin_mode rejoin_party
Definition: player.h:242
#define MAX_BUF
Definition: define.h:81
uint32 kills
Definition: player.h:133
void replace_unprintable_chars(char *buf)
Definition: utils.c:516
sint64 total_exp
Definition: player.h:132
object * ob
Definition: player.h:207
int snprintf(char *dest, int max, const char *format,...)
Definition: porting.c:498
int confirm_party_password(object *op)
Definition: c_party.c:228
#define MSG_TYPE_COMMUNICATION
Definition: newclient.h:332
char * partyleader
Definition: player.h:121
static partylist * lastparty
Definition: c_party.c:41
int command_party(object *op, char *params)
Definition: c_party.c:350
#define MSG_TYPE_COMMAND
Definition: newclient.h:326
void list_players(object *op, region *reg, partylist *party)
Definition: c_misc.c:550
partylist * get_firstparty(void)
Definition: c_party.c:48
EXTERN player * first_player
Definition: global.h:190
struct pl * next
Definition: player.h:147
#define NDI_UNIQUE
Definition: newclient.h:219
void LOG(LogLevel logLevel, const char *format,...)
Definition: logger.c:63
#define MAX_NAME
Definition: define.h:87
char write_buf[MAX_BUF]
Definition: player.h:225
void send_party_message(object *op, char *msg)
Definition: c_party.c:285
partylist * party_to_join
Definition: player.h:238
int command_gsay(object *op, char *params)
Definition: c_party.c:304
#define MSG_TYPE_COMMAND_ERROR
Definition: newclient.h:447
static partylist * firstparty
Definition: c_party.c:40
char passwd[9]
Definition: player.h:122