1 /* cmd_funcmds_bomb.c - NeonServ v5.6
2 * Copyright (C) 2011-2012 Philipp Kreil (pk910)
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 static void funcmd_bomb_plant(struct funcmd_header_info *header, struct Event *event, char **argv, int argc, int kick_bomb);
19 static USERAUTH_CALLBACK(funcmd_bomb_plant_nick_lookup);
20 static void funcmd_bomb_plant_async1(struct funcmd_header_info *header, struct Event *event, struct UserNode *user, int wires, int kick_bomb);
21 static void funcmd_bomb_plant_async2(struct funcmd_header_info *header, struct Event *event, struct UserNode *user, int wires, int kick_bomb);
22 static void funcmd_bomb_defuse(struct funcmd_header_info *header, struct Event *event, char **argv, int argc);
23 static void funcmd_bomb_return(struct funcmd_header_info *header, struct Event *event, char **argv, int argc);
24 static TIMEQ_CALLBACK(funcmd_bomb_timeout);
26 struct funcmd_bomb_plant_cache {
27 struct funcmd_header_info header;
33 struct funcmd_bomb_bomb {
34 struct funcmd_header_info header;
35 struct UserNode *owner, *target;
36 struct timeq_entry *timer;
37 char wires[FUNCMD_BOMB_WIRES_MAX];
40 struct funcmd_bomb_bomb *next;
43 static struct funcmd_bomb_bomb *funcmd_bomb_bombs = NULL;
45 static int funcmd_bomb_freeuser(struct UserNode *user) {
46 struct funcmd_bomb_bomb *bomb, *next_bomb, *prev_bomb = NULL;
47 for(bomb = funcmd_bomb_bombs; bomb; bomb = next_bomb) {
48 next_bomb = bomb->next;
49 if(bomb->owner == user)
51 if(bomb->target == user) {
52 timeq_del(bomb->timer);
55 prev_bomb->next = next_bomb;
57 funcmd_bomb_bombs = next_bomb;
64 static int funcmd_bomb_freechan(struct ChanNode *chan) {
65 struct funcmd_bomb_bomb *bomb, *next_bomb, *prev_bomb = NULL;
66 for(bomb = funcmd_bomb_bombs; bomb; bomb = next_bomb) {
67 next_bomb = bomb->next;
68 if(bomb->header.chan == chan) {
69 timeq_del(bomb->timer);
72 prev_bomb->next = next_bomb;
74 funcmd_bomb_bombs = next_bomb;
81 static void funcmd_bomb_freeclient(struct ClientSocket *client) {
82 struct funcmd_bomb_bomb *bomb, *next_bomb, *prev_bomb = NULL;
83 for(bomb = funcmd_bomb_bombs; bomb; bomb = next_bomb) {
84 next_bomb = bomb->next;
85 if(bomb->header.client == client) {
86 timeq_del(bomb->timer);
89 prev_bomb->next = next_bomb;
91 funcmd_bomb_bombs = next_bomb;
97 CMD_BIND(funcmd_bomb) {
100 char *subcmd = argv[0];
103 if(!stricmp(subcmd, "plant"))
104 funcmd_bomb_plant(header, event, argv, argc, 0);
105 else if(!stricmp(subcmd, "kplant"))
106 funcmd_bomb_plant(header, event, argv, argc, 1);
107 else if(!stricmp(subcmd, "defuse"))
108 funcmd_bomb_defuse(header, event, argv, argc);
109 else if(!stricmp(subcmd, "return"))
110 funcmd_bomb_return(header, event, argv, argc);
113 sprintf(tmp, "%s %s", event->command->cmd, subcmd);
114 reply(header->client, header->user, "MODCMD_UNKNOWN", tmp);
117 reply(header->client, header->user, "FUN_BOMB_MENU");
118 reply(header->client, header->user, "FUN_BOMB_MENU_PLANT", event->command->cmd, FUNCMD_BOMB_WIRES_DEFAULT);
119 reply(header->client, header->user, "FUN_BOMB_MENU_KPLANT", event->command->cmd, FUNCMD_BOMB_WIRES_DEFAULT);
120 reply(header->client, header->user, "FUN_BOMB_MENU_DEFUSE", event->command->cmd);
121 //reply(header->client, header->user, "FUN_BOMB_MENU_RETURN", event->command->cmd);
126 static void funcmd_bomb_plant(struct funcmd_header_info *header, struct Event *event, char **argv, int argc, int kick_bomb) {
128 reply(header->client, header->user, "MODCMD_LESS_PARAM_COUNT");
131 struct UserNode *user;
132 int wires = FUNCMD_BOMB_WIRES_DEFAULT;
133 if(!(user = getUserByNick(argv[0]))) {
134 reply(header->client, header->user, "NS_USER_UNKNOWN", argv[0]);
137 if(isNetworkService(user)) {
138 reply(header->client, header->user, "FUN_BOMB_PLANT_SERVICE");
141 if(user == header->user) {
142 reply(header->client, header->user, "FUN_BOMB_SELF");
146 wires = atoi(argv[1]);
147 if(wires < FUNCMD_BOMB_WIRES_MIN || wires > FUNCMD_BOMB_WIRES_MAX) {
148 reply(header->client, header->user, "FUN_BOMB_PLANT_MAXWIRES", FUNCMD_BOMB_WIRES_MIN, FUNCMD_BOMB_WIRES_MAX);
152 if(kick_bomb == 1) { /* protect shit... */
153 if(user->flags & USERFLAG_ISAUTHED) {
154 funcmd_bomb_plant_async1(header, event, user, wires, kick_bomb);
156 struct funcmd_bomb_plant_cache *cache = malloc(sizeof(*cache));
157 memcpy(&cache->header, header, sizeof(*header));
158 cache->event = event;
159 cache->wires = wires;
160 cache->kick_bomb = kick_bomb;
161 get_userauth(user, module_id, funcmd_bomb_plant_nick_lookup, cache);
164 funcmd_bomb_plant_async2(header, event, user, wires, kick_bomb);
167 static USERAUTH_CALLBACK(funcmd_bomb_plant_nick_lookup) {
168 struct funcmd_bomb_plant_cache *cache = data;
170 reply(cache->header.client, cache->header.user, "NS_USER_UNKNOWN", "*");
172 funcmd_bomb_plant_async1(&cache->header, cache->event, user, cache->wires, cache->kick_bomb);
177 static void funcmd_bomb_plant_async1(struct funcmd_header_info *header, struct Event *event, struct UserNode *user, int wires, int kick_bomb) {
178 if(kick_bomb == 1) { /* protect shit... */
179 if(isUserProtected(header->chan, user, header->user)) {
180 reply(header->client, header->user, "FUN_BOMB_PLANT_PROTECTED");
184 funcmd_bomb_plant_async2(header, event, user, wires, kick_bomb);
187 static void funcmd_bomb_defuse_strip_color(char *buffer) {
190 for(i = 0; buffer[i]; i++) {
191 if(buffer[i] == '\003') {
193 if(!buffer[i]) break;
194 if(isdigit(buffer[i])) {
196 if(!buffer[i]) break;
198 if(isdigit(buffer[i])) {
200 if(!buffer[i]) break;
203 buffer[j++] = buffer[i];
208 static int funcmd_bomb_defuse_get_wire_id(char *wire, struct UserNode *user) {
209 char *wires = get_language_string(user, "FUN_BOMB_WIRES");
212 int found = 0, cindex = 0;
214 wires = strchr(cwire, '|');
220 funcmd_bomb_defuse_strip_color(tmp);
221 if(!stricmp(wire, tmp))
228 } while(!found && cwire);
232 static int funcmd_bomb_defuse_get_wire_name(int wire_id, char *buffer, char *wires, struct UserNode *user) {
234 wires = get_language_string(user, "FUN_BOMB_WIRES");
236 int cindex = 0, chars = 0;
239 wires = strchr(cwire, '|');
244 if(cindex == wire_id)
245 chars = sprintf(buffer, "%s", cwire);
250 } while(!chars && cwire);
254 static void funcmd_bomb_plant_async2(struct funcmd_header_info *header, struct Event *event, struct UserNode *user, int wires, int kick_bomb) {
255 //everything should be checked now... plant the bomb :)
256 struct funcmd_bomb_bomb *bomb;
257 for(bomb = funcmd_bomb_bombs; bomb; bomb = bomb->next) {
258 if(bomb->target == user) {
259 reply(header->client, header->user, "FUN_BOMB_TARGET_ACTIVE", user->nick);
262 if(bomb->owner == header->user) {
263 reply(header->client, header->user, "FUN_BOMB_OWNER_ACTIVE");
267 bomb = malloc(sizeof(*bomb));
268 memcpy(&bomb->header, header, sizeof(*header));
270 bomb->owner = header->user;
271 bomb->kick_bomb = kick_bomb;
272 bomb->timer = timeq_add(FUNCMD_BOMB_TIME, module_id, funcmd_bomb_timeout, bomb);
273 bomb->next = funcmd_bomb_bombs;
274 funcmd_bomb_bombs = bomb;
276 int pool[FUNCMD_BOMB_WIRES_MAX+1];
277 for(i = 0; i < FUNCMD_BOMB_WIRES_MAX; i++) {
281 for(i = 0; i < FUNCMD_BOMB_WIRES_MAX; i++) {
283 j = (rand() % (FUNCMD_BOMB_WIRES_MAX - i));
284 bomb->wires[i] = pool[j];
286 for(k = 0; k < (FUNCMD_BOMB_WIRES_MAX - i); k++) {
294 bomb->right_wire = bomb->wires[(rand() % wires)];
295 char *wires_lang_str_a = get_language_string(header->user, "FUN_BOMB_WIRES");
296 char *wires_lang_str_b = get_language_string(user, "FUN_BOMB_WIRES");
297 if(!header->send_notice && wires_lang_str_a != wires_lang_str_b) {
298 wires_lang_str_a = get_language_string(NULL, "FUN_BOMB_WIRES");
299 header->null_language = 1;
300 bomb->header.null_language = 1;
302 char wires_str[MAXLEN];
304 for(i = 0; i < wires; i++) {
306 wires_str[j++] = ',';
307 wires_str[j++] = ' ';
309 j += funcmd_bomb_defuse_get_wire_name(bomb->wires[i], wires_str+j, wires_lang_str_a, NULL);
312 if(header->send_notice) {
313 reply(header->client, header->user, (kick_bomb ? "FUN_BOMB_KPLANTED" : "FUN_BOMB_PLANTED"), header->user->nick, user->nick, FUNCMD_BOMB_TIME, wires_str, event->command->cmd);
315 for(i = 0; i < wires; i++) {
317 wires_str[j++] = ',';
318 wires_str[j++] = ' ';
320 j += funcmd_bomb_defuse_get_wire_name(bomb->wires[i], wires_str+j, wires_lang_str_b, NULL);
323 reply(header->client, user, (kick_bomb ? "FUN_BOMB_KPLANTED" : "FUN_BOMB_PLANTED"), header->user->nick, user->nick, FUNCMD_BOMB_TIME, wires_str, event->command->cmd);
325 funcmd_reply(header, (kick_bomb ? "FUN_BOMB_KPLANTED" : "FUN_BOMB_PLANTED"), REPLYTYPE_NORMAL, header->user->nick, user->nick, FUNCMD_BOMB_TIME, wires_str, event->command->cmd);
328 static void funcmd_bomb_detonate(struct funcmd_bomb_bomb *bomb) {
330 int user_count = ((ptr = getSetting(bomb->target, bomb->header.chan, "bombs")) ? atoi(ptr) : 0);
331 int total_count = ((ptr = getSetting(bomb->target, NULL, "bombs")) ? atoi(ptr) : 0);
332 int detonated_count = ((ptr = getSetting(bomb->target, NULL, "bombs_detonated")) ? atoi(ptr) : 0);
337 sprintf(buf, "%d", user_count);
338 setSetting(bomb->target, bomb->header.chan, "bombs", buf);
339 sprintf(buf, "%d", total_count);
340 setSetting(bomb->target, NULL, "bombs", buf);
341 sprintf(buf, "%d", detonated_count);
342 setSetting(bomb->target, NULL, "bombs_detonated", buf);
343 char *wires = get_language_string(NULL, "FUN_BOMB_WIRES");
349 wires = strchr(cwire, '|');
354 if(cindex == bomb->right_wire)
361 } while(!tmp[0] && cwire);
362 if(bomb->header.send_notice)
363 reply(bomb->header.client, bomb->owner, "FUN_BOMB_DETONATED", REPLYTYPE_NORMAL, bomb->target->nick, tmp, total_count, user_count);
364 funcmd_reply(&bomb->header, "FUN_BOMB_DETONATED", REPLYTYPE_NORMAL, bomb->target->nick, tmp, total_count, user_count);
365 if(bomb->kick_bomb) {
366 putsock(bomb->header.client, "KICK %s %s :[BOMB] *BOOOOOOM*", bomb->header.chan->name, bomb->target->nick);
370 static void funcmd_bomb_defuse(struct funcmd_header_info *header, struct Event *event, char **argv, int argc) {
372 reply(header->client, header->user, "MODCMD_LESS_PARAM_COUNT");
375 struct funcmd_bomb_bomb *bomb, *prev_bomb = NULL;
376 for(bomb = funcmd_bomb_bombs; bomb; bomb = bomb->next) {
377 if(bomb->target == header->user)
383 reply(header->client, header->user, "FUN_BOMB_NOBOMB");
386 funcmd_bomb_defuse_strip_color(argv[0]);
387 int cut_wire = funcmd_bomb_defuse_get_wire_id(argv[0], header->user);
389 cut_wire = funcmd_bomb_defuse_get_wire_id(argv[0], NULL);
391 reply(header->client, header->user, "FUN_BOMB_UNKNOWN_WIRE", argv[0]);
394 if(bomb->right_wire == cut_wire) {
396 int user_count = ((tmp = getSetting(header->user, header->chan, "bombs")) ? atoi(tmp) : 0);
397 int total_count = ((tmp = getSetting(header->user, NULL, "bombs")) ? atoi(tmp) : 0);
398 int defused_count = ((tmp = getSetting(header->user, NULL, "bombs_defused")) ? atoi(tmp) : 0);
403 sprintf(buf, "%d", user_count);
404 setSetting(header->user, header->chan, "bombs", buf);
405 sprintf(buf, "%d", total_count);
406 setSetting(header->user, NULL, "bombs", buf);
407 sprintf(buf, "%d", defused_count);
408 setSetting(header->user, NULL, "bombs_defused", buf);
410 if(header->send_notice)
411 reply(header->client, bomb->owner, "FUN_BOMB_DEFUSED", REPLYTYPE_NORMAL, header->user->nick, total_count, user_count, defused_count);
412 funcmd_reply(header, "FUN_BOMB_DEFUSED", REPLYTYPE_NORMAL, header->user->nick, total_count, user_count, defused_count);
414 funcmd_bomb_detonate(bomb);
416 timeq_del(bomb->timer);
418 prev_bomb->next = bomb->next;
420 funcmd_bomb_bombs = bomb->next;
424 static void funcmd_bomb_return(struct funcmd_header_info *header, struct Event *event, char **argv, int argc) {
426 reply(header->client, header->user, "MODCMD_LESS_PARAM_COUNT");
432 static TIMEQ_CALLBACK(funcmd_bomb_timeout) {
433 struct funcmd_bomb_bomb *cbomb = data;
434 struct funcmd_bomb_bomb *bomb, *prev_bomb = NULL;
435 for(bomb = funcmd_bomb_bombs; bomb; bomb = bomb->next) {
443 funcmd_bomb_detonate(bomb);
445 prev_bomb->next = bomb->next;
447 funcmd_bomb_bombs = bomb->next;