From: pk910 Date: Fri, 7 Sep 2012 12:21:09 +0000 (+0200) Subject: added bomb funcmd X-Git-Url: http://git.pk910.de/?p=NeonServV5.git;a=commitdiff_plain;h=6a396ce22d80a3df950e7c809ac08cd101ee8543 added bomb funcmd --- diff --git a/src/IRCEvents.c b/src/IRCEvents.c index 83428c9..9728502 100644 --- a/src/IRCEvents.c +++ b/src/IRCEvents.c @@ -233,4 +233,4 @@ FUNC_EVENT(reload, reload_func_t, BIND_TYPE_RELOAD, (int initialization), (initi FUNC_BIND(freeclient, freeclient_func_t, BIND_TYPE_FREECLIENT) FUNC_UNBIND(freeclient, freeclient_func_t, BIND_TYPE_FREECLIENT) -FUNC_EVENT(freeclient, freeclient_func_t, BIND_TYPE_FREECLIENT, (struct ClientNode *client), (client)) +FUNC_EVENT(freeclient, freeclient_func_t, BIND_TYPE_FREECLIENT, (struct ClientSocket *client), (client)) diff --git a/src/IRCEvents.h b/src/IRCEvents.h index f78ed91..7a7ac3e 100644 --- a/src/IRCEvents.h +++ b/src/IRCEvents.h @@ -163,11 +163,11 @@ typedef int reload_func_t(int initialization); int event_reload(int initialization); #endif -typedef void freeclient_func_t(struct ClientNode *client); +typedef void freeclient_func_t(struct ClientSocket *client); #ifndef DND_FUNCTIONS /* MODULAR ACCESSIBLE */ int bind_freeclient(freeclient_func_t *func, int module_id); /* MODULAR ACCESSIBLE */ void unbind_freeclient(freeclient_func_t *func); -int event_freeclient(struct ClientNode *chan); +int event_freeclient(struct ClientSocket *chan); #endif #endif diff --git a/src/modules/funcmd.mod/cmd_funcmds.c b/src/modules/funcmd.mod/cmd_funcmds.c index bae54d1..56a7eab 100644 --- a/src/modules/funcmd.mod/cmd_funcmds.c +++ b/src/modules/funcmd.mod/cmd_funcmds.c @@ -25,6 +25,10 @@ #include "../../lang.h" #include "../../tools.h" #include "../../DBHelper.h" +#include "../../IRCEvents.h" +#include "../../timeq.h" +#include "../../WHOHandler.h" +#include "../../EventLogger.h" static const struct default_language_entry msgtab[] = { {"FUN_DICE", "$b%s$b: A $b%d$b shows on the %d-sided die."}, /* {ARGS: "TestUser", 5, 6} */ @@ -32,12 +36,42 @@ static const struct default_language_entry msgtab[] = { {"FUN_8BALL", "$b%s$b: %s"}, /* {ARGS: "TestUser", "Not a chance."} */ {"FUN_8BALL_REPLIES", "Not a chance.|In your dreams.|Absolutely!|Could be, could be.|No!"}, {"FUN_COOKIE", "gives %1$s a very big chocolate cookie. %1$s has got %2$d cookies until now (%3$d in this channel)."}, /* {ARGS: "TestUser", 20, 50} */ + {"FUN_BOMB_MENU", "There are the following commands:"}, + {"FUN_BOMB_MENU_PLANT", "$b%s plant [wires] $b Plant a bomb in front of another users feet ([wires] is the number of wires - default: %d)"}, /* {ARGS: "bomb", 3} */ + {"FUN_BOMB_MENU_KPLANT", "$b%s kplant [wires]$b Plant a kick-bomb in front of another users feet ([wires] is the number of wires - default: %d) (OP only)"}, /* {ARGS: "bomb", 3} */ + {"FUN_BOMB_MENU_DEFUSE", "$b%s defuse $b Defuses a bomb (maybe :D)"}, /* {ARGS: "bomb"} */ + {"FUN_BOMB_MENU_RETURN", "$b%s return $b Pushes a bomb planted infront of you back to the owner ($k4WARNING$k: There is a highly chance that the bomb detonates)"}, /* {ARGS: "bomb"} */ + {"FUN_BOMB_SELF", "You can not plant a bomb in front of yourself..."}, + {"FUN_BOMB_TARGET_ACTIVE", "%s has already an active bomb..."}, + {"FUN_BOMB_OWNER_ACTIVE", "You have already planted another bomb..."}, + {"FUN_BOMB_PLANTED", "%1$s planted a bomb in front of %2$s's feet. %2$s, you have $b%3$d seconds$b to defuse the bomb by cutting one of the following wires: %4$s ($uuse:$u %5$s defuse )"}, /* {ARGS: "TestUser", "TestTarget", 30, "blue, red, green", "bomb"} */ + {"FUN_BOMB_KPLANTED", "%1$s planted a kick-bomb in front of %2$s's feet. %2$s, you have $b%3$d seconds$b to defuse the bomb by cutting one of the following wires: %4$s ($uuse:$u %5$s defuse )"}, /* {ARGS: "TestUser", "TestTarget", 30, "blue, red, green", "bomb"} */ + {"FUN_BOMB_PLANT_SERVICE", "You can't plant a bomb in front of this user (bot)..."}, + {"FUN_BOMB_PLANT_PROTECTED", "You can't plant a bomb in front of this user (protect)..."}, + {"FUN_BOMB_PLANT_MAXWIRES", "A bomb can only have %d-%d wires!"}, /* {ARGS: 2, 8} */ + {"FUN_BOMB_WIRES", "$k4red$k|$k3green$k|$k8yellow$k|$k12blue$k|$k1black$k|$k6purple$k|$k7orange$k|$k11aqua$k"}, + {"FUN_BOMB_NOBOMB", "There is no bomb you could defuse..."}, + {"FUN_BOMB_UNKNOWN_WIRE", "%s is an unknown wire..."}, /* {ARGS: "white"} */ + {"FUN_BOMB_DEFUSED", "%1$s has successfully defused the bomb! %1$s got %2$d bombs (%3$d in this channel) and has defused %4$d of them."}, /* {ARGS: "TestUser", 20, 10, 5} */ + {"FUN_BOMB_DETONATED", "*BOOOOOOM* The bomb explodes in front of %1$s!!! %2$s was the right wire. %1$s got %3$d bombs (%4$d in this channel)"}, /* {ARGS: "TestUser", "white", 20, 10} */ {NULL, NULL} }; +#define FUNCMD_BOMB_WIRES_DEFAULT 3 +#define FUNCMD_BOMB_WIRES_MIN 2 +#define FUNCMD_BOMB_WIRES_MAX 8 +#define FUNCMD_BOMB_TIME 30 + +static int funcmd_bomb_freeuser(struct UserNode *user); +static int funcmd_bomb_freechan(struct ChanNode *chan); +static void funcmd_bomb_freeclient(struct ClientSocket *client); + void init_funcmds() { register_default_language_table(msgtab); srand(time(NULL)); + bind_freeuser(funcmd_bomb_freeuser, module_id); + bind_freechan(funcmd_bomb_freechan, module_id); + bind_freeclient(funcmd_bomb_freeclient, module_id); } void register_commands() { @@ -51,22 +85,24 @@ void register_commands() { USER_COMMAND("dice", funcmd_dice, 1, CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_FUNCMD); USER_COMMAND("8ball", funcmd_8ball, 1, CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_FUNCMD); USER_COMMAND("cookie", funcmd_cookie, 0, CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_FUNCMD); + USER_COMMAND("bomb", funcmd_bomb, 0, CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_FUNCMD); #undef USER_COMMAND } -struct current_funcmd_header { +struct funcmd_header_info { struct ClientSocket *client; struct UserNode *user; struct ChanNode *chan; char send_notice; + char null_language; }; -static struct current_funcmd_header current_funcmd; - #define FUNCMD_HEADER \ -current_funcmd.client = textclient; \ -current_funcmd.user = user; \ -current_funcmd.chan = chan; \ +struct funcmd_header_info *header = malloc(sizeof(*header)); \ +header->client = textclient; \ +header->user = user; \ +header->chan = chan; \ +header->null_language = 0; \ {\ MYSQL_RES *res; \ MYSQL_ROW row; \ @@ -77,29 +113,33 @@ current_funcmd.chan = chan; \ reply(textclient, user, "NS_FUN_DISABLED", chan->name); \ return; \ } else if(!strcmp(row[0], "1")) \ - current_funcmd.send_notice = 1; \ + header->send_notice = 1; \ else \ - current_funcmd.send_notice = 0; \ + header->send_notice = 0; \ } -#define REPLYTYPE_NORMAL 0 -#define REPLYTYPE_ACTION 1 -static void funcmd_reply(const char *text, int type, ...) { - if (!(current_funcmd.client->flags & SOCKET_FLAG_CONNECTED)) return; - const char *reply_format = get_language_string(current_funcmd.user, text); +#define FUNCMD_FOOTER \ +free(header); + +#define REPLYTYPE_NORMAL 0x01 +#define REPLYTYPE_ACTION 0x02 +#define REPLYTYPE_NOTICE 0x04 +static void funcmd_reply(struct funcmd_header_info *header, const char *text, int type, ...) { + if (!(header->client->flags & SOCKET_FLAG_CONNECTED)) return; + const char *reply_format = get_language_string((header->null_language ? NULL : header->user), text); if(reply_format) text = reply_format; char formatBuf[MAXLEN]; - if(current_funcmd.send_notice) { - if(type == REPLYTYPE_ACTION) - sprintf(formatBuf, "NOTICE %s :%s %s", current_funcmd.user->nick, current_funcmd.client->user->nick, text); + if(header->send_notice || (type & REPLYTYPE_NOTICE)) { + if(type & REPLYTYPE_ACTION) + sprintf(formatBuf, "NOTICE %s :%s %s", header->user->nick, header->client->user->nick, text); else - sprintf(formatBuf, "NOTICE %s :%s", current_funcmd.user->nick, text); + sprintf(formatBuf, "NOTICE %s :%s", header->user->nick, text); } else { - if(type == REPLYTYPE_ACTION) - sprintf(formatBuf, "PRIVMSG %s :\001ACTION %s\001", current_funcmd.chan->name, text); + if(type & REPLYTYPE_ACTION) + sprintf(formatBuf, "PRIVMSG %s :\001ACTION %s\001", header->chan->name, text); else - sprintf(formatBuf, "PRIVMSG %s :%s", current_funcmd.chan->name, text); + sprintf(formatBuf, "PRIVMSG %s :%s", header->chan->name, text); } va_list arg_list; char sendBuf[MAXLEN]; @@ -111,7 +151,7 @@ static void funcmd_reply(const char *text, int type, ...) { if (pos < 0 || pos > (MAXLEN - 2)) pos = MAXLEN - 2; sendBuf[pos] = '\n'; sendBuf[pos+1] = '\0'; - write_socket(current_funcmd.client, sendBuf, pos+1); + write_socket(header->client, sendBuf, pos+1); } static char* getSetting(struct UserNode *user, struct ChanNode *chan, const char *setting) { @@ -157,14 +197,19 @@ static void setSetting(struct UserNode *user, struct ChanNode *chan, const char printf_mysql_query("INSERT INTO `fundata` (`user`, `cid`, `name`, `value`) VALUES ('%s', '%d', '%s', '%s')", escape_string(uname), cid, escape_string(setting), escape_string(value)); } +#include "cmd_funcmds_bomb.c" + + CMD_BIND(funcmd_ping) { FUNCMD_HEADER; - funcmd_reply("\002%s\002: Pong!", REPLYTYPE_NORMAL, user->nick); + funcmd_reply(header, "\002%s\002: Pong!", REPLYTYPE_NORMAL, user->nick); + FUNCMD_FOOTER; } CMD_BIND(funcmd_pong) { FUNCMD_HEADER; - funcmd_reply("\002%s\002: Ping!", REPLYTYPE_NORMAL, user->nick); + funcmd_reply(header, "\002%s\002: Ping!", REPLYTYPE_NORMAL, user->nick); + FUNCMD_FOOTER; } CMD_BIND(funcmd_dice) { @@ -172,15 +217,16 @@ CMD_BIND(funcmd_dice) { int max = atoi(argv[0]); if(max > 1) { int val = (rand() % max) + 1; - funcmd_reply("FUN_DICE", REPLYTYPE_NORMAL, user->nick, val, max); + funcmd_reply(header, "FUN_DICE", REPLYTYPE_NORMAL, user->nick, val, max); } else - funcmd_reply("FUN_DICE_NUM", REPLYTYPE_NORMAL, argv[0]); + funcmd_reply(header, "FUN_DICE_NUM", REPLYTYPE_NORMAL, argv[0]); + FUNCMD_FOOTER; } CMD_BIND(funcmd_8ball) { FUNCMD_HEADER; char *message = merge_argv(argv, 0, argc); - const char *const_replies = get_language_string(current_funcmd.user, "FUN_8BALL_REPLIES"); + const char *const_replies = get_language_string(header->user, "FUN_8BALL_REPLIES"); char replies[MAXLEN]; int i, reply_count = 1; for(i = 0; const_replies[i]; i++) { @@ -206,15 +252,17 @@ CMD_BIND(funcmd_8ball) { } } if(creply) { - funcmd_reply("FUN_8BALL", REPLYTYPE_NORMAL, user->nick, creply); + funcmd_reply(header, "FUN_8BALL", REPLYTYPE_NORMAL, user->nick, creply); } + FUNCMD_FOOTER; } CMD_BIND(funcmd_cookie) { FUNCMD_HEADER; if(argc) { if(!(user = getUserByNick(argv[0]))) { - reply(current_funcmd.client, current_funcmd.user, "NS_USER_UNKNOWN", argv[0]); + reply(header->client, header->user, "NS_USER_UNKNOWN", argv[0]); + FUNCMD_FOOTER; return; } } @@ -228,5 +276,6 @@ CMD_BIND(funcmd_cookie) { setSetting(user, chan, "cookies", buf); sprintf(buf, "%d", total_count); setSetting(user, NULL, "cookies", buf); - funcmd_reply("FUN_COOKIE", REPLYTYPE_ACTION, user->nick, total_count, user_count); + funcmd_reply(header, "FUN_COOKIE", REPLYTYPE_ACTION, user->nick, total_count, user_count); + FUNCMD_FOOTER; } diff --git a/src/modules/funcmd.mod/cmd_funcmds.h b/src/modules/funcmd.mod/cmd_funcmds.h index 5a4080d..d8e5423 100644 --- a/src/modules/funcmd.mod/cmd_funcmds.h +++ b/src/modules/funcmd.mod/cmd_funcmds.h @@ -28,5 +28,6 @@ CMD_BIND(funcmd_pong); CMD_BIND(funcmd_dice); CMD_BIND(funcmd_8ball); CMD_BIND(funcmd_cookie); +CMD_BIND(funcmd_bomb); #endif \ No newline at end of file diff --git a/src/modules/funcmd.mod/cmd_funcmds_bomb.c b/src/modules/funcmd.mod/cmd_funcmds_bomb.c new file mode 100644 index 0000000..b6a9061 --- /dev/null +++ b/src/modules/funcmd.mod/cmd_funcmds_bomb.c @@ -0,0 +1,449 @@ +/* cmd_funcmds_bomb.c - NeonServ v5.6 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +static void funcmd_bomb_plant(struct funcmd_header_info *header, struct Event *event, char **argv, int argc, int kick_bomb); +static USERAUTH_CALLBACK(funcmd_bomb_plant_nick_lookup); +static void funcmd_bomb_plant_async1(struct funcmd_header_info *header, struct Event *event, struct UserNode *user, int wires, int kick_bomb); +static void funcmd_bomb_plant_async2(struct funcmd_header_info *header, struct Event *event, struct UserNode *user, int wires, int kick_bomb); +static void funcmd_bomb_defuse(struct funcmd_header_info *header, struct Event *event, char **argv, int argc); +static void funcmd_bomb_return(struct funcmd_header_info *header, struct Event *event, char **argv, int argc); +static TIMEQ_CALLBACK(funcmd_bomb_timeout); + +struct funcmd_bomb_plant_cache { + struct funcmd_header_info header; + struct Event *event; + int wires : 4; + int kick_bomb : 4; +}; + +struct funcmd_bomb_bomb { + struct funcmd_header_info header; + struct UserNode *owner, *target; + struct timeq_entry *timer; + char wires[FUNCMD_BOMB_WIRES_MAX]; + int right_wire : 4; + int kick_bomb : 4; + struct funcmd_bomb_bomb *next; +}; + +static struct funcmd_bomb_bomb *funcmd_bomb_bombs = NULL; + +static int funcmd_bomb_freeuser(struct UserNode *user) { + struct funcmd_bomb_bomb *bomb, *next_bomb, *prev_bomb = NULL; + for(bomb = funcmd_bomb_bombs; bomb; bomb = next_bomb) { + next_bomb = bomb->next; + if(bomb->owner == user) + bomb->owner = NULL; + if(bomb->target == user) { + timeq_del(bomb->timer); + free(bomb); + if(prev_bomb) + prev_bomb->next = next_bomb; + else + funcmd_bomb_bombs = next_bomb; + } else + prev_bomb = bomb; + } + return 1; +} + +static int funcmd_bomb_freechan(struct ChanNode *chan) { + struct funcmd_bomb_bomb *bomb, *next_bomb, *prev_bomb = NULL; + for(bomb = funcmd_bomb_bombs; bomb; bomb = next_bomb) { + next_bomb = bomb->next; + if(bomb->header.chan == chan) { + timeq_del(bomb->timer); + free(bomb); + if(prev_bomb) + prev_bomb->next = next_bomb; + else + funcmd_bomb_bombs = next_bomb; + } else + prev_bomb = bomb; + } + return 1; +} + +static void funcmd_bomb_freeclient(struct ClientSocket *client) { + struct funcmd_bomb_bomb *bomb, *next_bomb, *prev_bomb = NULL; + for(bomb = funcmd_bomb_bombs; bomb; bomb = next_bomb) { + next_bomb = bomb->next; + if(bomb->header.client == client) { + timeq_del(bomb->timer); + free(bomb); + if(prev_bomb) + prev_bomb->next = next_bomb; + else + funcmd_bomb_bombs = next_bomb; + } else + prev_bomb = bomb; + } +} + +CMD_BIND(funcmd_bomb) { + FUNCMD_HEADER; + if(argc) { + char *subcmd = argv[0]; + argv++; + argc--; + if(!stricmp(subcmd, "plant")) + funcmd_bomb_plant(header, event, argv, argc, 0); + else if(!stricmp(subcmd, "kplant")) + funcmd_bomb_plant(header, event, argv, argc, 1); + else if(!stricmp(subcmd, "defuse")) + funcmd_bomb_defuse(header, event, argv, argc); + //else if(!stricmp(subcmd, "return")) + // funcmd_bomb_return(header, event, argv, argc); + else { + char tmp[MAXLEN]; + sprintf(tmp, "%s %s", event->command->cmd, subcmd); + reply(header->client, header->user, "MODCMD_UNKNOWN", tmp); + } + } else { + reply(header->client, header->user, "FUN_BOMB_MENU"); + reply(header->client, header->user, "FUN_BOMB_MENU_PLANT", event->command->cmd, FUNCMD_BOMB_WIRES_DEFAULT); + reply(header->client, header->user, "FUN_BOMB_MENU_KPLANT", event->command->cmd, FUNCMD_BOMB_WIRES_DEFAULT); + reply(header->client, header->user, "FUN_BOMB_MENU_DEFUSE", event->command->cmd); + //reply(header->client, header->user, "FUN_BOMB_MENU_RETURN", event->command->cmd); + } + FUNCMD_FOOTER; +} + +static void funcmd_bomb_plant(struct funcmd_header_info *header, struct Event *event, char **argv, int argc, int kick_bomb) { + if(!argc) { + reply(header->client, header->user, "MODCMD_LESS_PARAM_COUNT"); + return; + } + struct UserNode *user; + int wires = FUNCMD_BOMB_WIRES_DEFAULT; + if(!(user = getUserByNick(argv[0]))) { + reply(header->client, header->user, "NS_USER_UNKNOWN", argv[0]); + return; + } + if(isNetworkService(user)) { + reply(header->client, header->user, "FUN_BOMB_PLANT_SERVICE"); + return; + } + if(user == header->user) { + reply(header->client, header->user, "FUN_BOMB_SELF"); + return; + } + if(argc > 1) { + wires = atoi(argv[1]); + if(wires < FUNCMD_BOMB_WIRES_MIN || wires > FUNCMD_BOMB_WIRES_MAX) { + reply(header->client, header->user, "FUN_BOMB_PLANT_MAXWIRES", FUNCMD_BOMB_WIRES_MIN, FUNCMD_BOMB_WIRES_MAX); + return; + } + } + if(kick_bomb == 1) { /* protect shit... */ + if(user->flags & USERFLAG_ISAUTHED) { + funcmd_bomb_plant_async1(header, event, user, wires, kick_bomb); + } else { + struct funcmd_bomb_plant_cache *cache = malloc(sizeof(*cache)); + memcpy(&cache->header, header, sizeof(*header)); + cache->event = event; + cache->wires = wires; + cache->kick_bomb = kick_bomb; + get_userauth(user, module_id, funcmd_bomb_plant_nick_lookup, cache); + } + } else + funcmd_bomb_plant_async2(header, event, user, wires, kick_bomb); +} + +static USERAUTH_CALLBACK(funcmd_bomb_plant_nick_lookup) { + struct funcmd_bomb_plant_cache *cache = data; + if(!user) { + reply(cache->header.client, cache->header.user, "NS_USER_UNKNOWN", "*"); + } else { + funcmd_bomb_plant_async1(&cache->header, cache->event, user, cache->wires, cache->kick_bomb); + } + free(cache); +} + +static void funcmd_bomb_plant_async1(struct funcmd_header_info *header, struct Event *event, struct UserNode *user, int wires, int kick_bomb) { + if(kick_bomb == 1) { /* protect shit... */ + if(isUserProtected(header->chan, user, header->user)) { + reply(header->client, header->user, "FUN_BOMB_PLANT_PROTECTED"); + return; + } + } + funcmd_bomb_plant_async2(header, event, user, wires, kick_bomb); +} + +static void funcmd_bomb_defuse_strip_color(char *buffer) { + int i, j; + j = 0; + for(i = 0; buffer[i]; i++) { + if(buffer[i] == '\003') { + i++; + if(!buffer[i]) break; + if(isdigit(buffer[i])) { + i++; + if(!buffer[i]) break; + } + if(isdigit(buffer[i])) { + i++; + if(!buffer[i]) break; + } + } + buffer[j++] = buffer[i]; + } + buffer[j] = 0; +} + +static int funcmd_bomb_defuse_get_wire_id(char *wire, struct UserNode *user) { + char *wires = get_language_string(user, "FUN_BOMB_WIRES"); + char *cwire = wires; + char tmp[MAXLEN]; + int found = 0, cindex = 0; + do { + wires = strchr(cwire, '|'); + if(wires) { + *wires = '\0'; + } + cindex++; + strcpy(tmp, cwire); + funcmd_bomb_defuse_strip_color(tmp); + if(!stricmp(wire, tmp)) + found = cindex; + if(wires) { + *wires = '|'; + cwire = wires + 1; + } else + cwire = NULL; + } while(!found && cwire); + return found; +} + +static int funcmd_bomb_defuse_get_wire_name(int wire_id, char *buffer, char *wires, struct UserNode *user) { + if(!wires) + wires = get_language_string(user, "FUN_BOMB_WIRES"); + char *cwire = wires; + int cindex = 0, chars = 0; + buffer[0] = 0; + do { + wires = strchr(cwire, '|'); + if(wires) { + *wires = '\0'; + } + cindex++; + if(cindex == wire_id) + chars = sprintf(buffer, "%s", cwire); + if(wires) { + *wires = '|'; + cwire = wires + 1; + } + } while(!chars && cwire); + return chars; +} + +static void funcmd_bomb_plant_async2(struct funcmd_header_info *header, struct Event *event, struct UserNode *user, int wires, int kick_bomb) { + //everything should be checked now... plant the bomb :) + struct funcmd_bomb_bomb *bomb; + for(bomb = funcmd_bomb_bombs; bomb; bomb = bomb->next) { + if(bomb->target == user) { + reply(header->client, header->user, "FUN_BOMB_TARGET_ACTIVE", user->nick); + return; + } + if(bomb->owner == header->user) { + reply(header->client, header->user, "FUN_BOMB_OWNER_ACTIVE"); + return; + } + } + bomb = malloc(sizeof(*bomb)); + memcpy(&bomb->header, header, sizeof(*header)); + bomb->target = user; + bomb->owner = header->user; + bomb->kick_bomb = kick_bomb; + bomb->timer = timeq_add(FUNCMD_BOMB_TIME, module_id, funcmd_bomb_timeout, bomb); + bomb->next = funcmd_bomb_bombs; + funcmd_bomb_bombs = bomb; + int i, j, k, l; + int pool[FUNCMD_BOMB_WIRES_MAX+1]; + for(i = 0; i < FUNCMD_BOMB_WIRES_MAX; i++) { + pool[i] = i+1; + } + pool[i] = 0; + for(i = 0; i < FUNCMD_BOMB_WIRES_MAX; i++) { + if(i < wires) { + j = (rand() % (FUNCMD_BOMB_WIRES_MAX - i)); + bomb->wires[i] = pool[j]; + l = 0; + for(k = 0; k < (FUNCMD_BOMB_WIRES_MAX - i); k++) { + if(k == j) + l = 1; + pool[k] = pool[k+l]; + } + } else + bomb->wires[i] = 0; + } + bomb->right_wire = bomb->wires[(rand() % wires)]; + char *wires_lang_str_a = get_language_string(header->user, "FUN_BOMB_WIRES"); + char *wires_lang_str_b = get_language_string(user, "FUN_BOMB_WIRES"); + if(!header->send_notice && wires_lang_str_a != wires_lang_str_b) { + wires_lang_str_a = get_language_string(NULL, "FUN_BOMB_WIRES"); + header->null_language = 1; + bomb->header.null_language = 1; + } + char wires_str[MAXLEN]; + j = 0; + for(i = 0; i < wires; i++) { + if(i) { + wires_str[j++] = ','; + wires_str[j++] = ' '; + } + j += funcmd_bomb_defuse_get_wire_name(bomb->wires[i], wires_str+j, wires_lang_str_a, NULL); + } + wires_str[j] = '\0'; + if(header->send_notice) { + 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); + j = 0; + for(i = 0; i < wires; i++) { + if(i) { + wires_str[j++] = ','; + wires_str[j++] = ' '; + } + j += funcmd_bomb_defuse_get_wire_name(bomb->wires[i], wires_str+j, wires_lang_str_b, NULL); + } + wires_str[j] = '\0'; + 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); + } else + 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); +} + +static void funcmd_bomb_detonate(struct funcmd_bomb_bomb *bomb) { + char *ptr; + int user_count = ((ptr = getSetting(bomb->target, bomb->header.chan, "bombs")) ? atoi(ptr) : 0); + int total_count = ((ptr = getSetting(bomb->target, NULL, "bombs")) ? atoi(ptr) : 0); + int detonated_count = ((ptr = getSetting(bomb->target, NULL, "bombs_detonated")) ? atoi(ptr) : 0); + user_count++; + total_count++; + detonated_count++; + char buf[10]; + sprintf(buf, "%d", user_count); + setSetting(bomb->target, bomb->header.chan, "bombs", buf); + sprintf(buf, "%d", total_count); + setSetting(bomb->target, NULL, "bombs", buf); + sprintf(buf, "%d", detonated_count); + setSetting(bomb->target, NULL, "bombs_detonated", buf); + char *wires = get_language_string(NULL, "FUN_BOMB_WIRES"); + char *cwire = wires; + char tmp[MAXLEN]; + int cindex = 0; + tmp[0] = 0; + do { + wires = strchr(cwire, '|'); + if(wires) { + *wires = '\0'; + } + cindex++; + if(cindex == bomb->right_wire) + strcpy(tmp, cwire); + if(wires) { + *wires = '|'; + cwire = wires + 1; + } else + cwire = NULL; + } while(!tmp[0] && cwire); + if(bomb->header.send_notice) + reply(bomb->header.client, bomb->owner, "FUN_BOMB_DETONATED", REPLYTYPE_NORMAL, bomb->target->nick, tmp, total_count, user_count); + funcmd_reply(&bomb->header, "FUN_BOMB_DETONATED", REPLYTYPE_NORMAL, bomb->target->nick, tmp, total_count, user_count); + if(bomb->kick_bomb) { + putsock(bomb->header.client, "KICK %s %s :[BOMB] *BOOOOOOM*", bomb->header.chan->name, bomb->target->nick); + } +} + +static void funcmd_bomb_defuse(struct funcmd_header_info *header, struct Event *event, char **argv, int argc) { + if(!argc) { + reply(header->client, header->user, "MODCMD_LESS_PARAM_COUNT"); + return; + } + struct funcmd_bomb_bomb *bomb, *prev_bomb = NULL; + for(bomb = funcmd_bomb_bombs; bomb; bomb = bomb->next) { + if(bomb->target == header->user) + break; + else + prev_bomb = bomb; + } + if(!bomb) { + reply(header->client, header->user, "FUN_BOMB_NOBOMB"); + return; + } + funcmd_bomb_defuse_strip_color(argv[0]); + int cut_wire = funcmd_bomb_defuse_get_wire_id(argv[0], header->user); + if(!cut_wire) + cut_wire = funcmd_bomb_defuse_get_wire_id(argv[0], NULL); + if(!cut_wire) { + reply(header->client, header->user, "FUN_BOMB_UNKNOWN_WIRE", argv[0]); + return; + } + if(bomb->right_wire == cut_wire) { + char *tmp; + int user_count = ((tmp = getSetting(header->user, header->chan, "bombs")) ? atoi(tmp) : 0); + int total_count = ((tmp = getSetting(header->user, NULL, "bombs")) ? atoi(tmp) : 0); + int defused_count = ((tmp = getSetting(header->user, NULL, "bombs_defused")) ? atoi(tmp) : 0); + user_count++; + total_count++; + defused_count++; + char buf[10]; + sprintf(buf, "%d", user_count); + setSetting(header->user, header->chan, "bombs", buf); + sprintf(buf, "%d", total_count); + setSetting(header->user, NULL, "bombs", buf); + sprintf(buf, "%d", defused_count); + setSetting(header->user, NULL, "bombs_defused", buf); + + if(header->send_notice) + reply(header->client, bomb->owner, "FUN_BOMB_DEFUSED", REPLYTYPE_NORMAL, header->user->nick, total_count, user_count, defused_count); + funcmd_reply(header, "FUN_BOMB_DEFUSED", REPLYTYPE_NORMAL, header->user->nick, total_count, user_count, defused_count); + } else { + funcmd_bomb_detonate(bomb); + } + timeq_del(bomb->timer); + if(prev_bomb) + prev_bomb->next = bomb->next; + else + funcmd_bomb_bombs = bomb->next; + free(bomb); +} + +static void funcmd_bomb_return(struct funcmd_header_info *header, struct Event *event, char **argv, int argc) { + if(!argc) { + reply(header->client, header->user, "MODCMD_LESS_PARAM_COUNT"); + return; + } + //following ;) +} + +static TIMEQ_CALLBACK(funcmd_bomb_timeout) { + struct funcmd_bomb_bomb *cbomb = data; + struct funcmd_bomb_bomb *bomb, *prev_bomb = NULL; + for(bomb = funcmd_bomb_bombs; bomb; bomb = bomb->next) { + if(cbomb == bomb) { + cbomb = NULL; + break; + } else + prev_bomb = bomb; + } + if(cbomb) return; + funcmd_bomb_detonate(bomb); + if(prev_bomb) + prev_bomb->next = bomb->next; + else + funcmd_bomb_bombs = bomb->next; + free(bomb); +}