Atrinik Server  4.0
party.c
Go to the documentation of this file.
1 /*************************************************************************
2  * Atrinik, a Multiplayer Online Role Playing Game *
3  * *
4  * Copyright (C) 2009-2014 Alex Tokar and Atrinik Development Team *
5  * *
6  * Fork from Crossfire (Multiplayer game for X-windows). *
7  * *
8  * This program 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 2 of the License, or *
11  * (at your option) any later version. *
12  * *
13  * 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  * *
18  * You should have received a copy of the GNU General Public License *
19  * along with this program; if not, write to the Free Software *
20  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
21  * *
22  * The author can be reached at admin@atrinik.org *
23  ************************************************************************/
24 
32 #include <global.h>
33 #include <toolkit/packet.h>
34 #include <toolkit/string.h>
35 #include <player.h>
36 #include <object.h>
37 
39 void command_party(object *op, const char *command, char *params)
40 {
41  char buf[MAX_BUF];
42 
43  if (!params) {
44  if (!CONTR(op)->party) {
45  draw_info(COLOR_WHITE, op, "You are not a member of any party.");
46  draw_info(COLOR_WHITE, op, "For help try: /party help");
47  } else {
48  draw_info_format(COLOR_WHITE, op, "You are a member of party %s (leader: %s).", CONTR(op)->party->name, CONTR(op)->party->leader);
49  }
50  } else if (!strcmp(params, "help")) {
51  draw_info(COLOR_WHITE, op, "To form a party type: /party form <partyname>");
52  draw_info(COLOR_WHITE, op, "To join a party type: /party join <partyname>");
53  draw_info(COLOR_WHITE, op, "If the party has a password, it will prompt you for it.");
54  draw_info(COLOR_WHITE, op, "For a list of current parties type: /party list");
55  draw_info(COLOR_WHITE, op, "To leave a party type: /party leave");
56  draw_info(COLOR_WHITE, op, "To change a password for a party type: /party password <password>");
57  draw_info(COLOR_WHITE, op, "There is a 8 character max for password.");
58  draw_info(COLOR_WHITE, op, "To talk to party members type: /party say <msg> or /gsay <msg>");
59  draw_info(COLOR_WHITE, op, "To see who is in your party: /party who");
60  draw_info(COLOR_WHITE, op, "To change the party's looting mode: /party loot mode");
61  draw_info(COLOR_WHITE, op, "To kick another player from your party: /party kick <name>");
62  draw_info(COLOR_WHITE, op, "To change party leader: /party leader <name>");
63  } else if (!strncmp(params, "say ", 4)) {
64  if (!CONTR(op)->party) {
65  draw_info(COLOR_WHITE, op, "You are not a member of any party.");
66  return;
67  }
68 
69  params = player_sanitize_input(params + 4);
70 
71  if (!params) {
72  return;
73  }
74 
75  snprintf(buf, sizeof(buf), "[%s] %s says: %s", CONTR(op)->party->name, op->name, params);
76  send_party_message(CONTR(op)->party, buf, PARTY_MESSAGE_CHAT, op, NULL);
77  LOG(CHAT, "[PARTY] [%s] [%s] %s", op->name, CONTR(op)->party->name, params);
78  } else if (!strcmp(params, "leave")) {
79  if (!CONTR(op)->party) {
80  draw_info(COLOR_WHITE, op, "You are not a member of any party.");
81  return;
82  }
83 
84  draw_info_format(COLOR_WHITE, op, "You leave party %s.", CONTR(op)->party->name);
85  snprintf(buf, sizeof(buf), "%s leaves party %s.", op->name, CONTR(op)->party->name);
86  send_party_message(CONTR(op)->party, buf, PARTY_MESSAGE_STATUS, op, op);
87 
88  remove_party_member(CONTR(op)->party, op);
89  } else if (!strncmp(params, "password ", 9)) {
90  if (!CONTR(op)->party) {
91  draw_info(COLOR_RED, op, "You are not a member of any party.");
92  return;
93  }
94 
95  if (CONTR(op)->party->leader != op->name) {
96  draw_info(COLOR_RED, op, "Only the party's leader can change the password.");
97  return;
98  }
99 
100  strncpy(CONTR(op)->party->passwd, params + 9, sizeof(CONTR(op)->party->passwd) - 1);
101  snprintf(buf, sizeof(buf), "The password for party %s changed to '%s'.", CONTR(op)->party->name, CONTR(op)->party->passwd);
102  send_party_message(CONTR(op)->party, buf, PARTY_MESSAGE_STATUS, op, NULL);
103  } else if (!strncmp(params, "form ", 5)) {
104  params = player_sanitize_input(params + 5);
105 
106  if (!params) {
107  draw_info(COLOR_RED, op, "Invalid party name to form.");
108  return;
109  }
110 
111  if (CONTR(op)->party) {
112  draw_info(COLOR_RED, op, "You must leave your current party before forming a new one.");
113  return;
114  }
115 
116  if (find_party(params)) {
117  draw_info_format(COLOR_WHITE, op, "The party %s already exists, pick another name.", params);
118  return;
119  }
120 
121  form_party(op, params);
122  } else if (!strncmp(params, "loot", 4)) {
123  size_t i;
124 
125  if (!CONTR(op)->party) {
126  draw_info(COLOR_RED, op, "You are not a member of any party.");
127  return;
128  }
129 
130  params = player_sanitize_input(params + 4);
131 
132  if (!params) {
133  draw_info_format(COLOR_WHITE, op, "Current looting mode: [green]%s[/green].", party_loot_modes[CONTR(op)->party->loot]);
134  return;
135  }
136 
137  if (CONTR(op)->party->leader != op->name) {
138  draw_info(COLOR_RED, op, "Only the party's leader can change the looting mode.");
139  return;
140  }
141 
142  for (i = 0; i < PARTY_LOOT_MAX; i++) {
143  if (!strcmp(params, party_loot_modes[i])) {
144  CONTR(op)->party->loot = i;
145  snprintf(buf, sizeof(buf), "Party looting mode changed to '%s'.", party_loot_modes[i]);
146  send_party_message(CONTR(op)->party, buf, PARTY_MESSAGE_STATUS, op, NULL);
147  return;
148  }
149  }
150 
151  draw_info(COLOR_WHITE, op, "Invalid looting mode. Valid modes are:");
152 
153  for (i = 0; i < PARTY_LOOT_MAX; i++) {
154  draw_info_format(COLOR_WHITE, op, "[green]%s[/green]: %s.", party_loot_modes[i], party_loot_modes_help[i]);
155  }
156  } else if (!strncmp(params, "kick", 4)) {
157  objectlink *ol;
158 
159  if (!CONTR(op)->party) {
160  draw_info(COLOR_RED, op, "You are not a member of any party.");
161  return;
162  }
163 
164  if (CONTR(op)->party->leader != op->name) {
165  draw_info(COLOR_RED, op, "Only the party's leader can kick other members of the party.");
166  return;
167  }
168 
169  params = player_sanitize_input(params + 4);
170 
171  if (!params) {
172  draw_info(COLOR_WHITE, op, "Whom do you want to kick from the party?");
173  return;
174  }
175 
176  if (strcasecmp(op->name, params) == 0) {
177  draw_info(COLOR_RED, op, "You cannot kick yourself.");
178  return;
179  }
180 
181  for (ol = CONTR(op)->party->members; ol; ol = ol->next) {
182  if (strcasecmp(ol->objlink.ob->name, params) == 0) {
183  remove_party_member(CONTR(op)->party, ol->objlink.ob);
184  snprintf(buf, sizeof(buf), "%s has been kicked from the party.", ol->objlink.ob->name);
185  send_party_message(CONTR(op)->party, buf, PARTY_MESSAGE_STATUS, op, NULL);
186  draw_info_format(COLOR_RED, ol->objlink.ob, "You have been kicked from the party '%s'.", CONTR(op)->party->name);
187  return;
188  }
189  }
190 
191  draw_info(COLOR_RED, op, "There's no player with that name in your party.");
192  } else if (!strncmp(params, "leader ", 7)) {
193  player *pl;
194 
195  if (!CONTR(op)->party) {
196  draw_info(COLOR_RED, op, "You are not a member of any party.");
197  return;
198  }
199 
200  if (CONTR(op)->party->leader != op->name) {
201  draw_info(COLOR_RED, op, "Only the party's leader can change the leader.");
202  return;
203  }
204 
205  pl = find_player(params + 7);
206 
207  if (!pl) {
208  draw_info(COLOR_RED, op, "No such player.");
209  return;
210  }
211 
212  if (pl->ob == op) {
213  draw_info(COLOR_RED, op, "You are already the party leader.");
214  return;
215  }
216 
217  if (!pl->party || pl->party != CONTR(op)->party) {
218  draw_info(COLOR_RED, op, "That player is not a member of your party.");
219  return;
220  }
221 
223  draw_info_format(COLOR_WHITE, pl->ob, "You are the new leader of party %s!", pl->party->name);
224  draw_info_format(COLOR_GREEN, op, "%s is the new leader of your party.", pl->ob->name);
225  } else {
226  packet_struct *packet;
227  party_struct *party;
228 
229  if (!strcmp(params, "list")) {
230  packet = packet_new(CLIENT_CMD_PARTY, 128, 256);
231  packet_debug_data(packet, 0, "Party command type");
232  packet_append_uint8(packet, CMD_PARTY_LIST);
233 
234  for (party = first_party; party; party = party->next) {
235  packet_debug_data(packet, 0, "\nParty name");
236  packet_append_string_terminated(packet, party->name);
237  packet_debug_data(packet, 0, "Leader");
238  packet_append_string_terminated(packet, party->leader);
239  }
240 
241  socket_send_packet(CONTR(op)->cs, packet);
242  } else if (!strcmp(params, "who")) {
243  objectlink *ol;
244 
245  if (!CONTR(op)->party) {
246  draw_info(COLOR_RED, op, "You are not a member of any party.");
247  return;
248  }
249 
250  packet = packet_new(CLIENT_CMD_PARTY, 128, 256);
251  packet_debug_data(packet, 0, "Party command type");
252  packet_append_uint8(packet, CMD_PARTY_WHO);
253 
254  for (ol = CONTR(op)->party->members; ol; ol = ol->next) {
255  packet_debug_data(packet, 0, "\nMember name");
256  packet_append_string_terminated(packet, ol->objlink.ob->name);
257  packet_debug_data(packet, 0, "Health");
258  packet_append_uint8(packet, MAX(1, MIN(
259  (double) ol->objlink.ob->stats.hp /
260  ol->objlink.ob->stats.maxhp * 100.0f, 100)));
261  packet_debug_data(packet, 0, "Mana");
262  packet_append_uint8(packet, MAX(1, MIN(
263  (double) ol->objlink.ob->stats.sp /
264  ol->objlink.ob->stats.maxsp * 100.0f, 100)));
265  }
266 
267  socket_send_packet(CONTR(op)->cs, packet);
268  } else if (!strncmp(params, "join ", 5)) {
269  char *cps[2];
270 
271  if (CONTR(op)->party) {
272  draw_info(COLOR_WHITE, op, "You must leave your current party before joining another.");
273  return;
274  }
275 
276  string_split(params + 5, cps, arraysize(cps), '\t');
277 
278  if (!cps[0] || !(party = find_party(cps[0]))) {
279  draw_info(COLOR_WHITE, op, "No such party.");
280  return;
281  }
282 
283  /* If party password is not set or they've typed correct password...
284  * */
285  if (party->passwd[0] == '\0' || (cps[1] && strcmp(party->passwd, cps[1]) == 0)) {
286  add_party_member(party, op);
287  CONTR(op)->stat_joined_party++;
288  draw_info_format(COLOR_GREEN, op, "You have joined party: %s.", party->name);
289  snprintf(buf, sizeof(buf), "%s joined party %s.", op->name, party->name);
290  send_party_message(party, buf, PARTY_MESSAGE_STATUS, op, op);
291  return;
292  } else if (cps[1]) {
293  /* Party password was typed but it wasn't correct. */
294  draw_info(COLOR_RED, op, "Incorrect party password.");
295  return;
296  } else {
297  /* Otherwise ask them to type the password */
298  draw_info(COLOR_YELLOW, op, "That party requires a password. Type it now, or press ESC to cancel joining.");
299  packet = packet_new(CLIENT_CMD_PARTY, 64, 64);
300  packet_debug_data(packet, 0, "Party command type");
301  packet_append_uint8(packet, CMD_PARTY_PASSWORD);
302  packet_debug_data(packet, 0, "Party name");
303  packet_append_string_terminated(packet, party->name);
304  socket_send_packet(CONTR(op)->cs, packet);
305  }
306  }
307  }
308 }
#define FREE_AND_ADD_REF_HASH(_sv_, _nv_)
Definition: global.h:116
party_struct * first_party
Definition: party.c:54
void remove_party_member(party_struct *party, object *op)
Definition: party.c:114
Definition: object.h:488
player * find_player(const char *plname)
Definition: player.c:96
object * ob
Definition: player.h:185
#define CMD_PARTY_LIST
Definition: party.h:127
void send_party_message(party_struct *party, const char *msg, int flag, object *op, object *except)
Definition: party.c:470
int16_t sp
Definition: living.h:78
int16_t maxsp
Definition: living.h:81
int32_t hp
Definition: living.h:72
object * ob
Definition: object.h:496
int32_t maxhp
Definition: living.h:75
struct party_struct * next
Definition: party.h:117
char * player_sanitize_input(char *str)
Definition: player.c:1311
const char *const party_loot_modes_help[PARTY_LOOT_MAX]
Definition: party.c:45
const char * name
Definition: object.h:168
union oblnk::@3 objlink
#define CMD_PARTY_WHO
Definition: party.h:131
void command_party(object *op, const char *command, char *params)
Definition: party.c:39
living stats
Definition: object.h:481
void form_party(object *op, const char *name)
Definition: party.c:191
struct oblnk * next
Definition: object.h:500
#define PARTY_MESSAGE_STATUS
Definition: party.h:41
#define PARTY_MESSAGE_CHAT
Definition: party.h:45
party_struct * party
Definition: player.h:555
shstr * leader
Definition: party.h:87
party_struct * find_party(const char *name)
Definition: party.c:208
const char *const party_loot_modes[PARTY_LOOT_MAX]
Definition: party.c:38
objectlink * members
Definition: party.h:112
shstr * name
Definition: party.h:92
#define CMD_PARTY_PASSWORD
Definition: party.h:139
void add_party_member(party_struct *party, object *op)
Definition: party.c:84
char passwd[9]
Definition: party.h:97