62 Commits
Author SHA1 Message Date
Auto Bot 7079e203a8 Patched in whois support, for use with voicenonbots.pm 2011-04-23 11:49:50 +04:00
Matthew Barksdale 727062b14b Merge branch 'indev' of github.com:Xelhua/Auto into indev 2011-04-23 01:39:19 -04:00
Matthew Barksdale df31622f82 What is this I don't even.. 2011-04-23 01:39:11 -04:00
Elijah Perrault 76d2c03281 Werewolf 1.07: Various improvements. 2011-04-22 15:50:08 -06:00
Elijah Perrault 303e03f4ee Merge branch 'indev' of github.com:Xelhua/Auto into indev 2011-04-22 02:25:16 -06:00
Elijah Perrault 99bb0721ba Fixing Matt's fails. 2011-04-22 02:25:00 -06:00
Matthew Barksdale 6f9e6f0d5d Apparently these aren't needed 2011-04-21 23:27:30 -04:00
Matthew Barksdale ccab5e9ab9 Fixed a bug with MODE parsing 2011-04-21 23:24:40 -04:00
Elijah Perrault 03c1616364 Maybe I should include the actual changes... 2011-04-21 21:00:32 -06:00
Elijah Perrault 193461abf4 Updated Core::IRC::Users to be more efficient. 2011-04-21 21:00:13 -06:00
Elijah Perrault f1a9b91a30 Oops. 2011-04-21 20:58:48 -06:00
Elijah Perrault f3ad8e0e38 Use M::Werewolf, not ourselves. 2011-04-21 20:57:36 -06:00
Elijah Perrault 81ff64ba4f Slight errors. 2011-04-21 20:43:24 -06:00
Elijah Perrault 33b50a651a Added a WerewolfAdmin module for administering the Werewolf IRC game. 2011-04-21 20:39:55 -06:00
Elijah Perrault fdfc249ba8 Updated. 2011-04-21 20:39:21 -06:00
Elijah Perrault f68646d155 Small bug fix. 2011-04-21 18:51:23 -06:00
Elijah Perrault 6357c54574 Various other state bugs. 2011-04-21 15:48:26 -06:00
Elijah Perrault a8ea3f0e64 Fixed significant state mismatched data bugs. 2011-04-21 14:08:47 -06:00
Elijah Perrault 3fdf7dcaf5 What is this I don't even... 2011-04-21 14:02:34 -06:00
Elijah Perrault 105e83699d Added API::IRC::ison for checking if a user is on a channel. 2011-04-21 02:08:37 -06:00
Elijah Perrault 338551b44c Werewolf: Fixed a bug in harlot staying home. 2011-04-20 22:18:56 -06:00
Elijah Perrault 412261f478 Werewolf: Various bug fixes. 2011-04-20 21:36:11 -06:00
Elijah Perrault 988e93a6f1 Lets try this... 2011-04-20 21:27:46 -06:00
Elijah Perrault 6c4ff75a03 Here as well. 2011-04-20 20:56:21 -06:00
Elijah Perrault 362310b863 Regex is a bad idea for this. 2011-04-20 20:56:02 -06:00
Elijah Perrault a2002882d6 Oops. 2011-04-20 20:48:04 -06:00
Elijah Perrault 3ebe82ec28 Werewolf 1.06: Fixed an annoyance and added traitor transformation. 2011-04-20 20:44:59 -06:00
Elijah Perrault 42faabeef5 Updated. 2011-04-20 20:37:49 -06:00
Elijah Perrault 21fb5d4974 Commands now work with prefixes even in PM. 2011-04-20 20:37:31 -06:00
Elijah Perrault 8147e9e32a We're alpha11. 2011-04-20 20:25:04 -06:00
Elijah Perrault 0864f549d1 Ping: Determines end by numeric 315 instead of a 3-second timer now. 2011-04-20 20:20:58 -06:00
Elijah Perrault ba5de67e4a Werewolf: Fixed a GUARD issue and made it possible to VISIT yourself. 2011-04-19 20:23:37 -06:00
Elijah Perrault 3bd8e9369d Possibly fixed a rare fatal error. 2011-04-19 11:09:19 -06:00
Elijah Perrault e33fd1df8d Werewolf: Rewrote WAIT to be more decent. 2011-04-19 02:04:31 -06:00
Elijah Perrault 3ef78078c4 Werewolf: Wounded villagers are now excluded from winning villager count. 2011-04-18 17:35:36 -06:00
Elijah Perrault a1beabe76a Werewolf: Bold lynched nick. 2011-04-18 16:18:31 -06:00
Elijah Perrault f12b7ef527 Werewolf: Dynamic lynch and no victim messages. 2011-04-18 16:11:19 -06:00
Elijah Perrault ed56d53f1e Werewolf 1.05: Added WAIT command. 2011-04-18 15:35:23 -06:00
Elijah Perrault e590c0dee3 Werewolf: Improved STATS to be smart. 2011-04-18 14:23:58 -06:00
Elijah Perrault 9fca160de5 Drunks = villagers. 2011-04-16 23:40:11 -06:00
Elijah Perrault 28e29f2dba *sigh* 2011-04-16 22:11:32 -06:00
Elijah Perrault c30f300b24 Removed the "villager gunner" role. 2011-04-16 22:05:05 -06:00
Elijah Perrault 0d9a714c4a Oops. 2011-04-16 21:55:03 -06:00
Elijah Perrault 87ff93945f Fixed slight issue. 2011-04-16 21:43:50 -06:00
Elijah Perrault c13a4e2ffe Werewolf 1.04: Added village drunks and fixed other issues. 2011-04-16 21:39:01 -06:00
Elijah Perrault 42fcac5cc0 Err... 2011-04-16 19:38:28 -06:00
Elijah Perrault 01a432f023 Updated. 2011-04-16 19:14:57 -06:00
Elijah Perrault a47211763c Fixed various annoyances in Werewolf. 2011-04-16 19:13:50 -06:00
Elijah Perrault 8cddc69209 Been writing too much Python today. 2011-04-16 02:14:18 -06:00
Elijah Perrault b6eb0c17cc Whoops. 2011-04-16 02:09:49 -06:00
Elijah Perrault 38b3e4c3d8 Werewolf: Fixed a nasty lynch nick exploit. 2011-04-16 02:08:15 -06:00
Elijah Perrault 503a7ed990 Fixed spelling failures. 2011-04-15 22:40:37 -06:00
Elijah Perrault 579485776d Moved bolds a bit. 2011-04-15 22:19:27 -06:00
Elijah Perrault f5db549052 Improvements. 2011-04-15 18:06:15 -06:00
Elijah Perrault 72006a8e7e Fixed an issue in HELP. 2011-04-14 19:26:48 -06:00
Elijah Perrault 2ca0885741 Added a Ping module. 2011-04-14 18:43:48 -06:00
Elijah Perrault 6c6b8604bc Merge branch 'indev' of github.com:Xelhua/Auto into indev 2011-04-14 18:37:27 -06:00
Elijah Perrault da28c54652 Moved Werewolf back to stable. 2011-04-14 18:32:08 -06:00
Matthew Barksdale f0b49acbd0 Added cleaning up inconsistencies in modules to TODO 2011-04-14 03:53:19 -04:00
Matthew Barksdale 58447eb40a Added more French translations 2011-04-14 03:41:40 -04:00
Matthew Barksdale 363a724ed3 Added french help translation 2011-04-14 03:34:27 -04:00
Matthew Barksdale a122977644 Added deoper subroutine to deoper Auto on a server 2011-04-14 03:27:58 -04:00
21 changed files with 910 additions and 203 deletions

No files matched your search

+6 -14
View File
@@ -10,23 +10,15 @@
The future of IRC bots is here! Xelhua gives to you, Auto 3.0, a new version of
the popular Auto IRC bot.
In this alpha10 release, we have added:
In this alpha11 release, we have added:
* German translation for AUR command help.
* German translation for Bitly command help.
* German translation for Calc command help.
* German translation for Dictionary command help.
* German translation for EightBall command help.
* German translation for Eval command help.
* German translation for FML command help.
* German translation for Greet command help.
* Aliases now work in PM's to the bot too.
* Ping: Speed improvements.
* An advanced IRC version of the popular party game Werewolf (AKA Mafia).
* Commands with prefixes now work in PM's too.
Bug fixes:
* Fixed parsing of host masks with a / in them.
* Security exploit (causes fatal error) in the HELP command.
* Security exploit (wide characters) in plaintext socket management.
* Fixed significant state mismatched data bugs.
Incompatibilities:
@@ -40,4 +32,4 @@ created by anyone and uploaded there for everyone to use.
Auto's goal is to create an efficient, stable and highly customizable IRC bot
in Perl. To offer an alternative to other platforms.
Enjoy Auto 3.0.0 Alpha 10!
Enjoy Auto 3.0.0 Alpha 11!
+15 -13
View File
@@ -481,19 +481,21 @@ if (conf_get('aliases:alias')) {
while (1) {
# Timer check.
foreach my $tk (keys %TIMERS) {
if ($TIMERS{$tk}{time} <= time) {
&{ $TIMERS{$tk}{sub} }();
if ($TIMERS{$tk}{type} == 1) {
# If it's type 1, delete from memory.
delete $TIMERS{$tk};
}
elsif ($TIMERS{$tk}{type} == 2) {
# If it's type 2, reset timer.
$TIMERS{$tk}{time} = time + $TIMERS{$tk}{secs};
}
else {
# This should never happen.
delete $TIMERS{$tk};
if (exists $TIMERS{$tk}) {
if ($TIMERS{$tk}{time} <= time) {
&{ $TIMERS{$tk}{sub} }();
if ($TIMERS{$tk}{type} == 1) {
# If it's type 1, delete from memory.
delete $TIMERS{$tk};
}
elsif ($TIMERS{$tk}{type} == 2) {
# If it's type 2, reset timer.
$TIMERS{$tk}{time} = time + $TIMERS{$tk}{secs};
}
else {
# This should never happen.
delete $TIMERS{$tk};
}
}
}
}
+23 -1
View File
@@ -3,7 +3,29 @@ Auto IRC Bot 3.0: Change Log
3.0 Indev
===============================================================================
* Werewolf 1.07: Various improvements.
* Updated Core::IRC::Users to be more efficient.
* Added a WerewolfAdmin module for administering the Werewolf IRC game.
* Fixed significant state mismatched data bugs.
* Added API::IRC::ison for checking if a user is on a channel.
* Werewolf: Fixed a bug in harlot staying home.
* Werewolf: Various bug fixes.
* Werewolf 1.06: Fixed an annoyance and added traitor transformation.
* Commands now work with prefixes even in PM.
* Ping: Determines end by numeric 315 instead of a 3-second timer now.
* Werewolf: Fixed a GUARD issue and made it possible to VISIT yourself.
* Possibly fixed a rare fatal error.
* Werewolf: Rewrote WAIT to be more decent.
* Werewolf: Wounded villagers are now excluded from winning villager count.
* Werewolf: Dynamic lynch and no victim messages.
* Werewolf 1.05: Added WAIT command.
* Werewolf: Improved STATS to be smart.
* Werewolf 1.04: Added village drunks and fixed other issues.
* Werewolf: Fixed various annoyances. Also raised chance of gun hitting.
* Werewolf: Fixed a nasty lynch nick exploit.
* Fixed an issue in HELP.
* Added a Ping module.
* Moved Werewolf back to stable.
3.0 Alpha 10
===============================================================================
+1
View File
@@ -10,6 +10,7 @@ Legend:
[ ] Cleanup
[ ] Replace println with Perl 5.10's say.
[ ] Fix inconsistencies in official modules
[X] Language
[X] Create method of translation.
+22 -1
View File
@@ -9,7 +9,7 @@ use Exporter;
use base qw(Exporter);
our @EXPORT_OK = qw(ban cjoin cpart cmode umode kick privmsg notice quit nick names
topic who usrc match_mask);
topic who whois usrc match_mask ison);
# Create the on_disconnect event.
API::Std::event_add('on_disconnect');
@@ -130,6 +130,18 @@ sub act {
return 1;
}
# Check if a given nickname is on a channel.
sub ison {
my ($svr, $chan, $nick) = @_;
$chan = lc $chan;
if (!exists $State::IRC::chanusers{$svr}) { return }
if (!exists $State::IRC::chanusers{$svr}{$chan}) { return }
if (!exists $State::IRC::chanusers{$svr}{$chan}{lc $nick}) { return }
return 1;
}
# Change bot nickname.
sub nick {
my ($svr, $newnick) = @_;
@@ -194,6 +206,15 @@ sub who {
return 1;
}
# Send a WHOIS.
sub whois {
my ($svr, $nick) = @_;
Auto::socksnd($svr, "WHOIS $nick");
return 1;
}
# Get nick, ident and host from a <nick>!<ident>@<host>
sub usrc {
my ($ex) = @_;
+1 -1
View File
@@ -26,7 +26,7 @@ sub mod_init {
if (keys %Auto::SOCKET) { API::Log::slog('MODULES: Attempting to load '.$name.' (version '.$version.') by '.$author.'...') }
# Check if this module is compatible with this version of Auto.
if ($autover !~ m/^3\.0\.0a(7|8|9|10)$/xsm) {
if ($autover !~ m/^3\.0\.0a(7|8|9|10|11)$/xsm) {
API::Log::dbug('MODULES: Failed to load '.$name.': Incompatible with your version of Auto.');
API::Log::alog('MODULES: Failed to load '.$name.': Incompatible with your version of Auto.');
if (keys %Auto::SOCKET) { API::Log::slog('MODULES: Failed to load '.$name.': Incompatible with your version of Auto.') }
+30 -25
View File
@@ -265,41 +265,46 @@ sub cmd_help
# Help for a specific command was requested. Lets get it.
my $rcm = uc($argv[0]);
if (exists $API::Std::CMDS{$rcm}{help}) {
# If there is help for this command.
# Check for necessary privileges.
if ($API::Std::CMDS{$rcm}{priv}) {
if (!has_priv(match_user(%$src), $API::Std::CMDS{$rcm}{priv})) {
notice($src->{svr}, $src->{nick}, trans("Access denied").".");
return;
# If there is help for this command.
if (exists $API::Std::CMDS{$rcm}) {
if (exists $API::Std::CMDS{$rcm}{help}) {
# Check for necessary privileges.
if ($API::Std::CMDS{$rcm}{priv}) {
if (!has_priv(match_user(%$src), $API::Std::CMDS{$rcm}{priv})) {
notice($src->{svr}, $src->{nick}, trans("Access denied").".");
return;
}
}
}
if ($API::Std::CMDS{$rcm}{help}) {
# If there is valid help for this command.
if ($API::Std::CMDS{$rcm}{help}) {
# If there is valid help for this command.
# Get the language.
my ($lang, undef) = split('_', $Auto::LOCALE);
# Get the language.
my ($lang, undef) = split('_', $Auto::LOCALE);
if (exists ${ $API::Std::CMDS{$rcm}{help} }{$lang}) {
# If help for this command is available in the configured language.
notice($src->{svr}, $src->{nick}, "Help for \002".$rcm."\002: ".${ $API::Std::CMDS{$rcm}{help} }{$lang});
}
else {
# If it isn't, default to English.
if (exists ${ $API::Std::CMDS{$rcm}{help} }{en}) {
# If help for this command is available in English.
notice($src->{svr}, $src->{nick}, "Help for \002".$rcm."\002: ".${ $API::Std::CMDS{$rcm}{help} }{en});
if (exists ${ $API::Std::CMDS{$rcm}{help} }{$lang}) {
# If help for this command is available in the configured language.
notice($src->{svr}, $src->{nick}, "Help for \002".$rcm."\002: ".${ $API::Std::CMDS{$rcm}{help} }{$lang});
}
else {
# If it isn't, no help.
notice($src->{svr}, $src->{nick}, "No help for \002".$rcm."\002 available.");
# If it isn't, default to English.
if (exists ${ $API::Std::CMDS{$rcm}{help} }{en}) {
# If help for this command is available in English.
notice($src->{svr}, $src->{nick}, "Help for \002".$rcm."\002: ".${ $API::Std::CMDS{$rcm}{help} }{en});
}
else {
# If it isn't, no help.
notice($src->{svr}, $src->{nick}, "No help for \002".$rcm."\002 available.");
}
}
}
else {
# If it isn't valid, no help.
notice($src->{svr}, $src->{nick}, "No help for \002".$rcm."\002 available.");
}
}
else {
# If it isn't valid, no help.
# If there is no help, don't give any.
notice($src->{svr}, $src->{nick}, "No help for \002".$rcm."\002 available.");
}
}
+4 -3
View File
@@ -64,6 +64,8 @@ hook_add('on_cprivmsg', 'irc.commands.aliases', sub {
# Command alias parsing for private messages.
hook_add('on_uprivmsg', 'irc.commands.aliases', sub {
my (($src, ($cmd, @args))) = @_;
my $cprefix = (conf_get('fantasy_pf'))[0][0];
if (substr($cmd, 0, 1) eq $cprefix) { $cmd = substr $cmd, 1 }
# Check for an alias.
if (defined $API::Std::ALIASES{uc $cmd}) {
@@ -95,7 +97,7 @@ hook_add("on_quit", "quit_update_chanusers", sub {
# Delete the user from all channels.
foreach my $ccu (keys %{ $State::IRC::chanusers{$src{svr}}}) {
if (defined $State::IRC::chanusers{$src{svr}}{$ccu}{$src{nick}}) { delete $State::IRC::chanusers{$src{svr}}{$ccu}{$src{nick}} }
if (defined $State::IRC::chanusers{$src{svr}}{$ccu}{lc $src{nick}}) { delete $State::IRC::chanusers{$src{svr}}{$ccu}{lc $src{nick}} }
}
return 1;
@@ -233,8 +235,7 @@ hook_add('on_isupport', 'core.prefixchanmode.getdata', sub {
return 1;
});
sub clear_usercmd_timer
{
sub clear_usercmd_timer {
# If ratelimit is set to 1 in config, add this timer.
if ((conf_get('ratelimit'))[0][0] eq 1) {
# Clear usercmd hash every X seconds.
+2 -8
View File
@@ -28,14 +28,8 @@ hook_add('on_rcjoin', 'ircusers.onjoin', sub {
hook_add('on_namesreply', 'ircusers.names', sub {
my ($svr, $chan, undef) = @_;
# Iterate through the users for this channel.
foreach (keys %{$State::IRC::chanusers{$svr}{$chan}}) {
# Check if the user already exists.
if (!$users{$svr}{$_}) {
# They do not; WHO them.
API::IRC::who($svr, $_);
}
}
# WHO the channel.
API::IRC::who($svr, $chan);
return 1;
});
+17 -15
View File
@@ -359,7 +359,7 @@ sub cjoin {
}
else {
# It isn't. Update chanusers and trigger on_rcjoin.
$State::IRC::chanusers{$svr}{lc $chan}{$src{nick}} = 1;
$State::IRC::chanusers{$svr}{lc $chan}{lc $src{nick}} = 1;
$src{svr} = $svr;
API::Std::event_run("on_rcjoin", (\%src, $chan));
}
@@ -374,9 +374,6 @@ sub kick {
my %src = API::IRC::usrc(substr($ex[0], 1));
$src{svr} = $svr;
# Update chanusers.
delete $State::IRC::chanusers{$svr}{$ex[2]}{$ex[3]} if defined $State::IRC::chanusers{$svr}{$ex[2]}{$ex[3]};
# Set $msg to the kick message.
my $msg = 0;
if (defined $ex[4]) {
@@ -393,7 +390,7 @@ sub kick {
# We were kicked!
# Delete channel from botchans.
delete $botchans{$svr}{$ex[2]};
delete $botchans{$svr}{lc $ex[2]};
# Log this horrible act.
API::Log::alog("I was kicked from ".$svr."/".$ex[2]." by ".$src{nick}."! Reason: ".$msg);
@@ -410,7 +407,7 @@ sub kick {
}
else {
# We weren't. Update chanusers and trigger on_kick.
if (defined $State::IRC::chanusers{$svr}{$ex[2]}{$ex[3]}) { delete $State::IRC::chanusers{$svr}{$ex[2]}{$ex[3]} }
if (defined $State::IRC::chanusers{$svr}{lc $ex[2]}{lc $ex[3]}) { delete $State::IRC::chanusers{$svr}{lc $ex[2]}{lc $ex[3]} }
API::Std::event_run("on_kick", (\%src, $ex[2], $ex[3], $msg));
}
@@ -423,7 +420,7 @@ sub mode {
if ($ex[2] ne $State::IRC::botinfo{$svr}{nick}) {
# Set data we'll need later.
my $chan = $ex[2];
my $chan = lc $ex[2];
$ex[3] =~ s/^://xsm;
my $modes = $ex[3];
my $fmodes = join ' ', @ex[3..$#ex];
@@ -467,10 +464,11 @@ sub mode {
if ($nnt) {
# It is a status mode, lets parse changes.
my $user = shift(@ex);
my $user = lc shift @ex;
if (defined $State::IRC::chanusers{$svr}{$chan}{$user}) {
if ($op == 1) {
return if $State::IRC::chanusers{$svr}{$chan}{$user} =~ m/$maf/xsm;
if ($State::IRC::chanusers{$svr}{$chan}{$user} eq 1) {
$State::IRC::chanusers{$svr}{$chan}{$user} = $maf;
}
@@ -531,9 +529,9 @@ sub nick {
else {
# It isn't. Update chanusers and trigger on_nick.
foreach my $chk (keys %{ $State::IRC::chanusers{$svr} }) {
if (defined $State::IRC::chanusers{$svr}{$chk}{$src{nick}}) {
$State::IRC::chanusers{$svr}{$chk}{$nex} = $State::IRC::chanusers{$svr}{$chk}{$src{nick}};
delete $State::IRC::chanusers{$svr}{$chk}{$src{nick}};
if (defined $State::IRC::chanusers{$svr}{$chk}{lc $src{nick}}) {
$State::IRC::chanusers{$svr}{$chk}{lc $nex} = $State::IRC::chanusers{$svr}{$chk}{lc $src{nick}};
delete $State::IRC::chanusers{$svr}{$chk}{lc $src{nick}};
}
}
API::Std::event_run("on_nick", (\%src, $nex));
@@ -572,13 +570,13 @@ sub part {
# Check if it's from us or someone else.
if ($src{nick} eq $State::IRC::botinfo{$svr}{nick}) {
# Delete this channel from botchans.
if ($botchans{$svr}{$ex[2]}) { delete $botchans{$svr}{$ex[2]} }
if ($botchans{$svr}{lc $ex[2]}) { delete $botchans{$svr}{lc $ex[2]} }
# Trigger on_upart.
API::Std::event_run('on_upart', ($svr, $ex[2]));
}
else {
# Delete them from chanusers.
delete $State::IRC::chanusers{$svr}{$ex[2]}{$src{nick}} if defined $State::IRC::chanusers{$svr}{$ex[2]}{$src{nick}};
delete $State::IRC::chanusers{$svr}{lc $ex[2]}{lc $src{nick}} if defined $State::IRC::chanusers{$svr}{lc $ex[2]}{lc $src{nick}};
# Set $msg to the part message.
my $msg = 0;
@@ -624,9 +622,13 @@ sub privmsg {
if (lc($ex[2]) eq lc($State::IRC::botinfo{$svr}{nick})) {
# It is coming to us in a private message.
# Check for a prefix.
$cprefix = (conf_get('fantasy_pf'))[0][0];
# Ensure it's a valid length.
if (length($ex[3]) > 1) {
$cmd = uc(substr($ex[3], 1));
if (length($ex[3]) > 2) {
$cmd = uc substr $ex[3], 1;
if (substr($cmd, 0, 1) eq $cprefix) { $cmd = substr $cmd, 1 }
if (defined $API::Std::CMDS{$cmd}) {
# If this is indeed a command, continue.
if ($API::Std::CMDS{$cmd}{lvl} == 1 or $API::Std::CMDS{$cmd}{lvl} == 2) {
+1
View File
@@ -10,6 +10,7 @@ our (%chanusers, %botinfo);
# Create on_namesreply hook.
hook_add('on_namesreply', 'state.irc.names', sub {
my ($svr, $chan, @data) = @_;
$chan = lc $chan;
# Delete the old chanusers hash if it exists.
if (defined $chanusers{$svr}{$chan}) { delete $chanusers{$svr}{$chan} }
+1
View File
@@ -30,6 +30,7 @@ sub _void {
our %HELP_AUR = (
en => "This command allows you to lookup a module in the Arch Linux AUR. \2Syntax:\2 AUR <module>",
de => "Dieser Befehl ermoeglicht du auf nachschlagst ein Modul in der Arch Linux AUR. \2Syntax:\2 AUR <module>",
fr => "Cette commande vous permet de rechercher un module dans le Arch Linux AUR. \2Syntaxe:\2 AUR <module>",
);
# Callback for AUR command.
+2 -2
View File
@@ -13,8 +13,8 @@ use URI::Escape;
sub _init
{
# Check for required configuration values.
if (!(conf_get('bitly:user'))[0][0] or !(conf_get('bitly:key'))[0][0]) {
err(2, 'Please verify that you have bitly_user and bitly_key defined in your configuration file.', 0);
if (!conf_get('bitly:user') or !conf_get('bitly:key')) {
err(2, 'Bitly: Please verify that you have bitly_user and bitly_key defined in your configuration file.', 0);
return;
}
# Create the SHORTEN and REVERSE commands.
+1
View File
@@ -30,6 +30,7 @@ sub _void {
our %HELP_EVAL = (
en => "This command allows you to eval Perl code. USE WITH CAUTION. \2Syntax:\2 EVAL <expression>",
de => "Dieser Befehl ermoeglicht du auf bewertst Perl Code. GEBRAUCH MIT VORSICHT. \2Syntax:\2 EVAL <expression>",
fr => "Cette commande vous permet d'évaluer du code Perl. UTILISER AVEC PRUDENCE. \2Syntaxe:\2 EVAL <expression>",
);
# Callback for EVAL command.
+1
View File
@@ -31,6 +31,7 @@ sub _void
# Help hashes.
our %HELP_ISITUP = (
'en' => "This command will check if a website appears up or down to the bot. \002Syntax:\002 ISITUP <url>",
'fr' => "Cette commande va vérifier si un site Web semble être vers le haut ou vers le bas pour le bot. \002Syntaxe:\002 ISITUP <url>",
);
# Callback for ISITUP command.
+1
View File
@@ -27,6 +27,7 @@ sub _void {
# Help for LOLCAT.
our %HELP_LOLCAT = (
en => "This command will translate English to LOLCAT speak. \2Syntax:\2 LOLCAT <text>",
fr => "Cette commande va traduire l'anglais vers LOLCAT parler. \2Syntaxe:\2 LOLCAT <texte",
);
# Callback for LOLCAT command.
+10 -1
View File
@@ -13,7 +13,7 @@ sub _init
# Add a hook for when we join a channel.
hook_add('on_connect', 'Oper.onconnect', \&M::Oper::on_connect) or return;
# Add a hook for when we get numeric 491 (ERR_NOOPERHOST)
rchook_add('491', 'Oper.on381', \&M::Oper::on_num491) or return;
rchook_add('491', 'Oper.on491', \&M::Oper::on_num491) or return;
return 1;
}
@@ -70,6 +70,15 @@ sub oper {
return 1;
}
# Deopers Auto on the specified server.
sub deoper {
my ($svr) = @_;
Auto::socksnd($svr, "MODE $State::IRC::botinfo{$svr}{nick} -o");
return 1;
}
# End of the API
# Start initialization.
API::Std::mod_init('Oper', 'Xelhua', '1.01', '3.0.0a10');
# build: perl=5.010000
+136
View File
@@ -0,0 +1,136 @@
# Module: Ping. See below for documentation.
# Copyright (C) 2010-2011 Xelhua Development Group, et al.
# This program is free software; rights to this code are stated in doc/LICENSE.
package M::Ping;
use strict;
use warnings;
use API::Std qw(cmd_add cmd_del hook_add hook_del rchook_add rchook_del);
use API::IRC qw(privmsg notice who);
my (@PING, $STATE);
my $LAST = 0;
# Initialization subroutine.
sub _init {
# Create the PING command.
cmd_add('PING', 0, 'cmd.ping', \%M::Ping::HELP_PING, \&M::Ping::cmd_ping) or return;
# Create the on_whoreply hook.
hook_add('on_whoreply', 'ping.who', \&M::Ping::on_whoreply) or return;
# Hook onto numeric 315.
rchook_add('315', 'ping.eow', \&M::Ping::ping) or return;
# Success.
return 1;
}
# Void subroutine.
sub _void {
# Delete the PING command.
cmd_del('PING') or return;
# Delete the on_whoreply hook.
hook_del('on_whoreply', 'ping.who') or return;
# Delete 315 hook.
rchook_del('315', 'ping.eow') or return;
# Success.
return 1;
}
# Help for PING.
our %HELP_PING = (
en => "This command will ping all non-/away users in the channel. \2Syntax:\2 PING",
);
# Callback for PING command.
sub cmd_ping {
my ($src, @argv) = @_;
# Check ratelimit (once every five minutes).
if ((time - $LAST) < 300) {
notice($src->{svr}, $src->{nick}, 'This command is ratelimited. Please wait a while before using it again.');
return;
}
# Set last used time to current time.
$LAST = time;
# Set state.
$STATE = $src->{svr}.'::'.$src->{chan};
# Ship off a WHO.
who($src->{svr}, $src->{chan});
return 1;
}
# Callback for WHO reply.
sub on_whoreply {
my ($svr, $nick, $target, undef, undef, undef, $status, undef, undef) = @_;
# If it's us, just return.
if ($nick eq $State::IRC::botinfo{$svr}{nick}) { return 1 }
# Check if we're doing a ping right now.
if ($STATE) {
# Check if this is the target channel.
if ($STATE eq $svr.'::'.$target) {
# If their status is not away, push to ping array.
if ($status !~ m/G/xsm) {
push @PING, $nick;
}
}
}
return 1;
}
# Ping!
sub ping {
if ($STATE) {
my ($svr, $chan) = split '::', $STATE, 2;
privmsg($svr, $chan, 'PING! '.join(' ', @PING));
@PING = ();
$STATE = 0;
}
return 1;
}
# Start initialization.
API::Std::mod_init('Ping', 'Xelhua', '1.01', '3.0.0a11');
# build: perl=5.010000
__END__
=head1 NAME
Ping - A module for pinging a channel.
=head1 VERSION
1.01
=head1 SYNOPSIS
<Hermione> .ping
<howlbot> PING! `A` tdubellz Hermione Oakfeather LightToagac shadowm_goat kitten starcoder2 Suiseiseki metabill theknife Trashlord Cam HardDisk_WP nerdshark2 MJ94 JonathanD Julius2 CensoredBiscuit LordVoldemort e36freak alyx mth starcoder
=head1 DESCRIPTION
This merely creates the PING command, which will highlight everyone in the
channel, excluding the bot itself and those who are /away.
=head1 AUTHOR
This module was written by Elijah Perrault.
This module is maintained by Xelhua Development Group.
=head1 LICENSE AND COPYRIGHT
This module is Copyright 2010-2011 Xelhua Development Group. All rights
reserved.
This module is released under the same licensing terms as Auto itself.
=cut
# vim: set ai et ts=4 sw=4:
+1
View File
@@ -32,6 +32,7 @@ sub _void
# Help hashes.
our %HELP_WEATHER = (
'en' => "This command will retrieve the weather via Wunderground for the specified location. \002Syntax:\002 WEATHER <location>",
'fr' => "Cette commande permet de récupérer la météo via Wunderground pour l'emplacement spécifié. \002Syntaxe:\002 WEATHER <emplacement>",
);
# Callback for Weather command.
@@ -7,7 +7,8 @@ use warnings;
use feature qw(switch);
use API::Std qw(cmd_add cmd_del trans hook_add hook_del timer_add timer_del trans conf_get has_priv match_user);
use API::IRC qw(privmsg notice cmode);
my ($GAME, $PGAME, $GAMECHAN, $GAMETIME, %PLAYERS, %NICKS, @STATIC, $PHASE, $SEEN, $VISIT, $GUARD, %KILL, %WKILL, %LYNCH, %SPOKE, %WARN, $LVOTEN, @SHOT, $BULLETS, $DETECTED);
our ($GAME, $PGAME, $GAMECHAN, $GAMETIME, %PLAYERS, %NICKS, @STATIC, $PHASE, $SEEN, $VISIT, $GUARD, %KILL, %WKILL, %LYNCH, %SPOKE, %WARN, $LVOTEN, @SHOT,
$BULLETS, $DETECTED, $WAIT, $WAITED, $FM);
my $FCHAR = (conf_get('fantasy_pf'))[0][0];
# Initialization subroutine.
@@ -64,6 +65,7 @@ sub _void {
# Commands hash.
my %COMMANDS = (
'join' => 'wolf join',
'wait' => 'wolf wait',
'start' => 'wolf start',
'see' => 'wolf see <nick>',
'visit' => 'wolf visit <nick>',
@@ -74,9 +76,24 @@ my %COMMANDS = (
'id' => 'wolf id <nick>',
);
# No villagers dead messages.
my @NOVICTIM = (
'A pool of blood and wolf paw prints are found.',
'The body of a young penguin pet is found.',
'Traces of wolf fur are found.',
);
# Lynch messages.
my @LYNCHMSG = (
"The villagers, after much debate, finally decide on lynching \2%s\2, who turned out to be... a \2%s\2.",
"Under a lot of noise, the pitchfork-bearing villagers lynch \2%s\2, who turned out to be... a \2%s\2.",
"The mob drags a protesting \2%s\2 to the hanging tree. He/She succumbs to the will of the horde, and is hanged. It is discovered (s)he was a \2%s\2.",
"Resigned to his/her fate, \2%s\2 is led to the gallows. After death, it is discovered (s)he was a \2%s\2.",
);
# Help hash for the WOLF command.
our %HELP_WOLF = (
en => "This command allows you to perform various actions in a game of Werewolf (A.K.A. Mafia). \2Syntax:\2 WOLF (JOIN|START|LYNCH|RETRACT|SHOOT|QUIT|KICK|VOTES|STATS / SEE|ID|VISIT|GUARD|KILL) [parameters]",
en => "This command allows you to perform various actions in a game of Werewolf (A.K.A. Mafia). \2Syntax:\2 WOLF (JOIN|WAIT|START|LYNCH|RETRACT|SHOOT|QUIT|VOTES|STATS / SEE|ID|VISIT|GUARD|KILL) [parameters]",
);
# Callback for the WOLF command.
@@ -113,10 +130,16 @@ sub cmd_wolf {
$PLAYERS{lc $src->{nick}} = 0;
$NICKS{lc $src->{nick}} = $src->{nick};
$GAMETIME = time;
$WAIT = 60;
$WAITED = 0;
# Start wait timer.
timer_add('werewolf.joinwait', 2, 1, sub {
if ($M::Werewolf::WAIT) { $M::Werewolf::WAIT-- }
});
# Game started.
cmode($src->{svr}, $src->{chan}, "+v $src->{nick}");
privmsg($src->{svr}, $src->{chan}, "\2$src->{nick}\2 has started a game of Werewolf. Type \"".$FCHAR.$COMMANDS{'join'}.'" to join. Type "'.$FCHAR.$COMMANDS{start}.'" to start the game.');
privmsg($src->{svr}, $src->{chan}, "\2$src->{nick}\2 has started a game of Werewolf. Type \"".$FCHAR.$COMMANDS{'join'}.'" to join. Type "'.$FCHAR.$COMMANDS{start}.'" to start the game. Type "'.$FCHAR.$COMMANDS{wait}.'" to increase join wait time.');
}
elsif ($GAME) {
notice($src->{svr}, $src->{nick}, 'Sorry, but the game is already running. Try again next time.');
@@ -150,6 +173,45 @@ sub cmd_wolf {
privmsg($gsvr, $gchan, "\2$src->{nick}\2 joined the game.");
}
}
when (/^(WAIT|W)$/) {
# WOLF WAIT
# Check if a game is running.
if (!$PGAME) {
if (!$GAME) {
notice($src->{svr}, $src->{nick}, 'No game is currently running.');
return;
}
else {
notice($src->{svr}, $src->{nick}, 'Werewolf is already in play.');
return;
}
}
# Check if this is the game channel.
if ($src->{svr}.'/'.$src->{chan} ne $GAMECHAN) {
notice($src->{svr}, $src->{nick}, "Werewolf is currently running in \2$GAMECHAN\2.");
return;
}
# Make sure they're playing.
if (!defined $PLAYERS{lc $src->{nick}}) {
notice($src->{svr}, $src->{nick}, 'You\'re not currently playing.');
return;
}
# Check if we're already waiting a while.
if ($WAITED >= 2) {
privmsg($src->{svr}, $src->{chan}, "$src->{nick}: Already waiting 100 seconds.");
return;
}
# Increase WAIT.
$WAIT += 20;
# And WAITED.
$WAITED++;
privmsg($src->{svr}, $src->{chan}, "\2$src->{nick}\2 increased join wait time by 20 seconds.");
}
when ('START') {
# WOLF START
@@ -177,11 +239,9 @@ sub cmd_wolf {
return;
}
# Check join timeout.
if ((time - $GAMETIME) < 60) {
my $time = time - $GAMETIME;
$time = 60 - $time;
privmsg($src->{svr}, $src->{chan}, "$src->{nick}: Please wait at least \2$time\2 more seconds.");
# Check join wait time.
if ($WAIT) {
privmsg($src->{svr}, $src->{chan}, "$src->{nick}: Please wait at least \2$WAIT\2 more seconds.");
return;
}
@@ -195,8 +255,9 @@ sub cmd_wolf {
my $cwolves = POSIX::ceil(keys(%PLAYERS) * .14);
# Only one seer, harlot, guardian angel, traitor and detective.
my $cseers = 1;
my $charlots = my $cangels = my $ctraitors = my $cdetectives = 0;
my $charlots = my $cdrunks = my $cangels = my $ctraitors = my $cdetectives = 0;
if (keys %PLAYERS >= 6) { $charlots++ unless conf_get('werewolf:rated-g') }
if (keys %PLAYERS >= 7) { $cdrunks++ unless conf_get('werewolf:rated-g') }
if (keys %PLAYERS >= 9) { $cangels++ unless conf_get('werewolf:no-angels') }
if (keys %PLAYERS >= 12 and conf_get('werewolf:traitors')) { $ctraitors++ }
if (keys %PLAYERS >= 16 and conf_get('werewolf:detectives')) { $cdetectives++ }
@@ -234,6 +295,14 @@ sub cmd_wolf {
$STATIC[2] = "\2$NICKS{$rpi}\2";
}
}
# Set drunks.
while ($cdrunks > 0) {
my $rpi = $plyrs[int rand scalar @plyrs];
if ($PLAYERS{$rpi} =~ m/v/xsm) {
$PLAYERS{$rpi} = 'vi';
$cdrunks--;
}
}
# Set guardian angels.
while ($cangels > 0) {
my $rpi = $plyrs[int rand scalar @plyrs];
@@ -262,14 +331,16 @@ sub cmd_wolf {
}
}
# If there's 6 or more players, give one of them a gun.
if (keys %PLAYERS >= 6) {
# If there's 8 or more players, give one of them a gun.
if (keys %PLAYERS >= 8) {
my $rpi = $plyrs[int rand scalar @plyrs];
while ($PLAYERS{$rpi} =~ m/w/xsm || $PLAYERS{$rpi} =~ m/t/xsm) { $rpi = $plyrs[int rand scalar @plyrs] }
$PLAYERS{$rpi} .= 'b';
# And give them PLAYER COUNT * .12 bullets rounded up.
$BULLETS = POSIX::ceil(keys(%PLAYERS) * .12);
if ($PLAYERS{$rpi} =~ m/i/xsm) { $BULLETS = $BULLETS * 3 }
}
# Set variables.
@@ -283,6 +354,8 @@ sub cmd_wolf {
my ($gsvr, $gchan) = split '/', $GAMECHAN;
privmsg($gsvr, $gchan, 'Game is now starting.');
cmode($gsvr, $gchan, '+m');
# Delete waiting timer.
timer_del('werewolf.joinwait');
# Start timer for bed checking.
timer_add('werewolf.chkbed', 2, 5, \&M::Werewolf::_chkbed);
# Initialize the nighttime.
@@ -497,44 +570,54 @@ sub cmd_wolf {
# All good, lets go!
my $real = $NICKS{lc $argv[1]};
# Massive randomizing here. 5 = 3-kill, 1-miss, 1-suicide
my $myr = int rand 6;
# Massive randomizing here. 7 = 5-hit, 1-miss, 1-suicide
my $myr = int rand 8;
given ($myr) {
when (4) { # It's a miss.
privmsg($src->{svr}, $src->{chan}, "\2$src->{nick}\2 is a lousy shooter. He/She missed!");
}
when (5) { # Gun explodes = suicide.
privmsg($src->{svr}, $src->{chan}, "\2$src->{nick}\2 should clean his/her weapons more often. The gun exploded and killed him/her!");
if (_getrole(lc $src->{nick}, 2) ne 'villager') { privmsg($src->{svr}, $src->{chan}, "Appears s(he) was a \2"._getrole(lc $src->{nick}, 2)."\2."); }
if (_getrole(lc $src->{nick}, 2) ne 'villager') { privmsg($src->{svr}, $src->{chan}, "Appears (s)he was a \2"._getrole(lc $src->{nick}, 2)."\2."); }
_player_del(lc $src->{nick});
return 1;
}
default { # It's a hit.
privmsg($src->{svr}, $src->{chan}, "\2$src->{nick}\2 shot \2$real\2 with a silver bullet!");
# Check if the target is a wolf or a villager.
if ($PLAYERS{lc $argv[1]} =~ m/w/xsm) { # Wolf.
privmsg($src->{svr}, $src->{chan}, "\2$real\2 is a wolf, and is dying from the silver bullet.");
_player_del(lc $argv[1]);
# Or not!
if ($PLAYERS{lc $src->{nick}} =~ m/i/xsm and $_ =~ m/^[1-3]$/xsm) {
privmsg($src->{svr}, $src->{chan}, "\2$src->{nick}\2 is a lousy shooter. He/She missed!");
}
else { # Villager.
# So, there's a 1/5 chance of a villager dying.
my $rint = int rand 6;
given ($rint) {
when (5) { # Killed.
privmsg($src->{svr}, $src->{chan}, "\2$real\2 is a villager, but \2$src->{nick}\2 accidentally shot them in the head and they are now dying.");
if (_getrole(lc $real, 2) ne 'villager') { privmsg($src->{svr}, $src->{chan}, "Appears s(he) was a \2"._getrole(lc $real, 2)."\2."); }
# Kill them.
_player_del(lc $real);
}
default { # Only hurt.
privmsg($src->{svr}, $src->{chan}, "\2$real\2 is a villager, and is hurt but will have a full recovery. He/She will be resting for the day.");
push @SHOT, lc $real;
# Delete any votes they might've made today.
foreach my $plyr (keys %LYNCH) {
if (exists $LYNCH{$plyr}{lc $real}) { delete $LYNCH{$plyr}{lc $real} }
else {
privmsg($src->{svr}, $src->{chan}, "\2$src->{nick}\2 shot \2$real\2 with a silver bullet!");
# Check if the target is a wolf or a villager.
if ($PLAYERS{lc $argv[1]} =~ m/w/xsm) { # Wolf.
privmsg($src->{svr}, $src->{chan}, "\2$real\2 is a wolf, and is dying from the silver bullet.");
_player_del(lc $argv[1]);
}
else { # Villager.
# So, there's a 1/5 chance of a villager dying.
my $rint = int rand 6;
given ($rint) {
when (5) { # Killed.
privmsg($src->{svr}, $src->{chan}, "\2$real\2 is a villager, but \2$src->{nick}\2 accidentally shot them in the head and they are now dying.");
if (_getrole(lc $real, 2) ne 'villager') { privmsg($src->{svr}, $src->{chan}, "Appears (s)he was a \2"._getrole(lc $real, 2)."\2."); }
# Kill them.
_player_del(lc $real);
}
default { # Only hurt.
privmsg($src->{svr}, $src->{chan}, "\2$real\2 is a villager, and is hurt but will have a full recovery. He/She will be resting for the day.");
push @SHOT, lc $real;
# Delete any votes they might've made today.
foreach my $plyr (keys %LYNCH) {
if (exists $LYNCH{$plyr}{lc $real}) { delete $LYNCH{$plyr}{lc $real} }
}
# Set number of votes required to lynch.
_calclvn();
# Check for winning conditions.
_chkwin();
}
$LVOTEN--;
}
}
}
@@ -574,6 +657,7 @@ sub cmd_wolf {
privmsg($src->{svr}, $src->{chan}, "$src->{nick}: \2".keys(%PLAYERS)."\2 players: $str");
# If all roles have been assigned, return the count of each.
if ($GAME) {
# Get a count of all roles.
my $cwolves = my $cseers = my $charlots = my $cangels = my $ctraitors = my $cdetectives = 0;
foreach my $flags (values %PLAYERS) {
if ($flags =~ m/w/xsm) { $cwolves++ }
@@ -583,41 +667,23 @@ sub cmd_wolf {
if ($flags =~ m/t/xsm) { $ctraitors++ }
if ($flags =~ m/d/xsm) { $cdetectives++ }
}
privmsg($src->{svr}, $src->{chan}, "$src->{nick}: There are \2$cwolves\2 wolves, \2$cseers\2 seers, ".
"\2$charlots\2 ".((conf_get('werewolf:rated-g')) ? '<removed>' : 'harlots').", \2$ctraitors\2 traitors, \2$cdetectives\2 detectives, ".
"and \2$cangels\2 guardian angels.");
}
}
when (/^(KICK|K)$/) {
# WOLF KICK
# Prepare an array of data.
my @data;
push @data, "\2$cwolves\2 wolves";
push @data, "\2$cseers\2 seers";
# Check if a game is running.
if (!$GAME and !$PGAME) {
notice($src->{svr}, $src->{nick}, 'No game is currently running.');
return;
}
# Check if this is the game channel.
if ($src->{svr}.'/'.$src->{chan} ne $GAMECHAN) {
notice($src->{svr}, $src->{nick}, "Werewolf is currently running in \2$GAMECHAN\2.");
return;
}
# Push extra roles.
if (!conf_get('werewolf:rated-g')) { push @data, "\2$charlots\2 harlots" }
if (!conf_get('werewolf:no-angels')) { push @data, "\2$cangels\2 guardian angels" }
if (conf_get('werewolf:traitors')) { push @data, "\2$ctraitors\2 traitors" }
if (conf_get('werewolf:detectives')) { push @data, "\2$cdetectives\2 detectives" }
# Prepare message.
my $msg = "$src->{nick}: There are ".join(', ', @data[0..$#data-1]);
$msg .= ", and $data[$#data].";
# Check for the werewolf.admin privilege.
if (!has_priv(match_user(%{$src}), 'werewolf.admin')) {
notice($src->{svr}, $src->{nick}, trans('Permission denied').q{.});
return;
privmsg($src->{svr}, $src->{chan}, $msg);
}
# Requires an extra parameter.
if (!defined $argv[1]) {
notice($src->{svr}, $src->{nick}, trans('Not enough parameters').q{.});
return;
}
# Kill the target.
privmsg($src->{svr}, $src->{chan}, "\2$argv[1]\2 died of an unknown disease. He/She was a \2"._getrole(lc $argv[1], 2)."\2.");
_player_del(lc $argv[1]);
}
when (/^(QUIT|Q)$/) {
# WOLF QUIT
@@ -790,7 +856,7 @@ sub cmd_wolf {
# They can only protect one person per round.
if ($GUARD) {
privmsg($src->{svr}, $src->{nick}, "You are already protecting \2$NICKS{$VISIT}\2.");
privmsg($src->{svr}, $src->{nick}, "You are already protecting \2$NICKS{$GUARD}\2.");
return;
}
@@ -848,7 +914,10 @@ sub cmd_wolf {
# They can only visit one person per round.
if ($VISIT) {
privmsg($src->{svr}, $src->{nick}, "You are already spending the night with \2$NICKS{$VISIT}\2!");
my $friend;
if ($VISIT eq 1) { $friend = 'at home' }
else { $friend = "with $NICKS{$VISIT}" }
privmsg($src->{svr}, $src->{nick}, "You are already spending the night \2$friend\2!");
return;
}
@@ -864,10 +933,12 @@ sub cmd_wolf {
return;
}
# They can't sleep with themselves.
# Check if they've selected themselves.
if (lc $argv[1] eq lc $src->{nick}) {
privmsg($src->{svr}, $src->{nick}, 'You cannot sleep with yourself!');
return;
privmsg($src->{svr}, $src->{nick}, 'You have chosen to stay home for the night.');
$VISIT = 1;
_chknight();
return 1;
}
# All good, set variables and stuff.
@@ -929,7 +1000,9 @@ sub cmd_wolf {
}
# If they're changing their selection, reverse the old victim's data.
if ($WKILL{lc $src->{nick}}) { $KILL{lc $WKILL{lc $src->{nick}}}-- }
if ($WKILL{lc $src->{nick}}) {
$KILL{lc $WKILL{lc $src->{nick}}}--;
}
# All good, proceed.
$KILL{lc $argv[1]}++;
@@ -961,7 +1034,7 @@ sub _init_night {
$erole = 'wolf';
$msg = "It is your job to kill all the villagers. Use \"$COMMANDS{kill}\" to kill a villager. Also, if you send a PM to me, it will be relayed to all other wolves.\n&pi&";
my $cwolves = 0;
for (values %PLAYERS) { if (m/w/xsm) { $cwolves++ } }
for (values %PLAYERS) { if (m/(w|t)/xsm) { $cwolves++ } }
if ($cwolves > 1) { $msg .= "\nAlso, please consider using PM's or a channel to speak with your fellow wolves rather than my relay, to prevent from me lagging." }
}
# For harlots.
@@ -1017,9 +1090,14 @@ sub _init_night {
}
# Check if they have the gun.
if ($role =~ m/b/xsm and $BULLETS) {
privmsg($gsvr, $NICKS{$plyr}, 'You hold a special gun. You may only use it during the day. If you shoot a wolf, (s)he will die instantly, if you shoot a villager, they will likely live. You get '.$BULLETS.' shot(s).');
privmsg($gsvr, $NICKS{$plyr}, 'You hold a gun with special silver bullet(s). You may only use it during the day. If you shoot a wolf, (s)he will die instantly, if you shoot a villager, they will likely live. You get '.$BULLETS.' shot(s).');
privmsg($gsvr, $NICKS{$plyr}, 'To shoot someone, type "'.$FCHAR.$COMMANDS{shoot}.'" in the channel during the day.');
}
# And for drunks.
if ($role =~ m/i/xsm and $role !~ m/a/xsm) {
privmsg($gsvr, $NICKS{$plyr}, 'You have been drinking too much! You are the village drunk.');
$PLAYERS{$plyr} .= 'a';
}
}
# It is now nighttime.
@@ -1071,12 +1149,12 @@ sub _init_day {
}
}
# Now check if the harlot spent the night with a wolf last night.
if (!$harlotd and $VISIT) {
if (!$harlotd and $VISIT) { if (exists $PLAYERS{$VISIT}) {
if ($PLAYERS{$VISIT} =~ m/w/xsm) {
# Ouch! He/She did, gotta kill them. :(
$harlotd = 2;
}
}
} }
# Last check; lets find out if the guardian angel protected a wolf last night.
my $angeld;
@@ -1093,10 +1171,10 @@ sub _init_day {
}
# Finally, check if the harlot was targeted and wasn't home.
if (_getrole($victim, 2) eq 'harlot' and $VISIT) {
if (_getrole($victim, 2) eq 'harlot' and $VISIT) { if ($VISIT ne 1) {
privmsg($gsvr, $gchan, 'The wolves attempted to attack the harlot last night, but (s)he wasn\'t home...');
$victim = 0;
}
} }
# Set phase to day.
$PHASE = 'd';
@@ -1104,7 +1182,7 @@ sub _init_day {
# Cool, all data should be ready for shipment. Lets go!
my $continue = 1;
my $msg = 'It is now daytime. The villagers awake, thankful for surviving the night, and search the village...';
if (!$victim) { privmsg($gsvr, $gchan, "$msg The body of a young penguin pet is found. All villagers however, have survived.") }
if (!$victim) { privmsg($gsvr, $gchan, "$msg ".$NOVICTIM[int rand scalar @NOVICTIM]." All villagers however, have survived.") }
elsif ($victim eq 1) {
privmsg($gsvr, $gchan, "$msg \2$NICKS{$GUARD}\2 was attacked by the wolves last night, but luckily, the guardian angel protected them.");
}
@@ -1143,8 +1221,7 @@ sub _init_day {
if (!$continue) { return 1 }
# Set number of votes required to lynch.
$LVOTEN = int(scalar(keys(%PLAYERS)) / 2);
$LVOTEN++;
_calclvn();
privmsg($gsvr, $gchan, 'The villagers must now vote for who to lynch. Use "'.$FCHAR.$COMMANDS{lynch}.'" to cast your vote. '.$LVOTEN.' votes are required to lynch.');
# Clear variables.
@@ -1203,7 +1280,7 @@ sub _judgment {
# Kill him/her!
my ($gsvr, $gchan) = split '/', $GAMECHAN;
privmsg($gsvr, $gchan, "The villagers, after much debate, finally decide on lynching \2$NICKS{$nick}\2, who turned out to be... a \2"._getrole($nick, 2)."\2.");
privmsg($gsvr, $gchan, sprintf($LYNCHMSG[int rand scalar @LYNCHMSG], $NICKS{$nick}, _getrole($nick, 2)));
my $ri = _player_del($nick, 1);
# Initialize nighttime.
@@ -1212,6 +1289,15 @@ sub _judgment {
return 1;
}
# Subroutine for re-calculating LVOTEN.
sub _calclvn {
my $pc = keys %PLAYERS;
$pc -= scalar @SHOT;
$LVOTEN = int($pc / 2) + 1;
return 1;
}
# Subroutine for checking who is in bed and who is not.
sub _chkbed {
my ($gsvr, $gchan) = split '/', $GAMECHAN, 2;
@@ -1237,7 +1323,7 @@ sub _chkbed {
# Send out any warnings.
if (scalar @warn) {
privmsg($gsvr, $gchan, join(', ', @warn).': You have been idling for a while. Please remember to say something soon or you might be declared dead.')
privmsg($gsvr, $gchan, join(', ', @warn).": \2You have been idling for a while. Please remember to say something soon or you might be declared dead.\2")
}
return 1;
@@ -1257,6 +1343,7 @@ sub _getrole {
elsif ($PLAYERS{$plyr} =~ m/h/xsm) { $role = 'harlot' }
elsif ($PLAYERS{$plyr} =~ m/g/xsm) { $role = 'guardian angel' }
elsif ($PLAYERS{$plyr} =~ m/d/xsm) { $role = 'detective' }
elsif ($PLAYERS{$plyr} =~ m/i/xsm) { $role = 'village drunk' }
elsif ($PLAYERS{$plyr} =~ m/(v|t)/xsm) { $role = 'villager' }
}
elsif ($lev == 2) {
@@ -1266,6 +1353,7 @@ sub _getrole {
elsif ($PLAYERS{$plyr} =~ m/g/xsm) { $role = 'guardian angel' }
elsif ($PLAYERS{$plyr} =~ m/d/xsm) { $role = 'detective' }
elsif ($PLAYERS{$plyr} =~ m/t/xsm) { $role = 'traitor' }
elsif ($PLAYERS{$plyr} =~ m/i/xsm) { $role = 'village drunk' }
elsif ($PLAYERS{$plyr} =~ m/v/xsm) { $role = 'villager' }
}
}
@@ -1304,28 +1392,33 @@ sub _player_del {
}
}
if ($SEEN) { if ($SEEN eq $player) { $SEEN = 0 } }
# If there are no more wolves, check if we have a traitor.
my $cwolves;
for (values %PLAYERS) { if (m/w/xsm) { $cwolves++ } }
if (!$cwolves) {
my $traitor;
while (my ($tp, $tv) = each %PLAYERS) { if ($tv =~ m/t/xsm) { $traitor = $tp } }
# Now if we have a traitor...
if ($traitor) {
# Transform them into a wolf.
$PLAYERS{$traitor} = 'w';
privmsg($gsvr, $NICKS{$traitor}, 'HOOOOOOOOOWL. You have become... a wolf! It is up to you to avenge your fallen leaders!');
privmsg($gsvr, $gchan, "\2The villagers, during their celebrations, are frightened as they hear a loud howl. The wolves are not gone!\2");
}
}
# Update LVOTEN.
if ($LVOTEN) { $LVOTEN-- }
if ($LVOTEN) { _calclvn() }
# Check for winning conditions.
if (!_chkwin()) { return }
# Call lynch management IF judgment did not call us.
if ($PHASE and !$judgment) {
if ($PHASE eq 'd') { _lynchmng() }
}
# Check for winning conditions.
if (!$PGAME) {
my $wolves;
for (values %PLAYERS) { if (m/w/xsm) { $wolves++ } }
if (!$wolves) { _gameover('v'); return }
my $villagers;
for (values %PLAYERS) { if (m/(v|s|g|h|d)/xsm) { $villagers++ } }
if ($villagers <= $wolves) { _gameover('w'); return }
}
else {
# Check if there's any more players.
if (!keys %PLAYERS) { _gameover('n') }
}
# Check if nighttime should end, given we are night.
if ($PHASE) { if ($PHASE eq 'n') { _chknight() } }
@@ -1350,6 +1443,25 @@ sub _lynchmng {
return 1;
}
# Subroutine for checking if we have a winner.
sub _chkwin {
if (!$PGAME) {
my $wolves;
for (values %PLAYERS) { if (m/w/xsm) { $wolves++ } }
if (!$wolves) { _gameover('v'); return }
my $villagers;
for (values %PLAYERS) { if (m/(v|s|g|h|d)/xsm) { $villagers++ } }
$villagers -= scalar @SHOT;
if ($villagers <= $wolves) { _gameover('w'); return }
}
else {
# Check if there's any more players.
if (!keys %PLAYERS) { _gameover('n') }
}
return 1;
}
# Handling the end of the game.
sub _gameover {
my ($winner) = @_;
@@ -1391,7 +1503,8 @@ sub _gameover {
# Clear all variables.
if ($PHASE) { if ($PHASE eq 'n') { timer_del('werewolf.goto_daytime') } }
timer_del('werewolf.chkbed');
$GAME = $PGAME = $GAMECHAN = $GAMETIME = $PHASE = $SEEN = $VISIT = $GUARD = $LVOTEN = $BULLETS = $DETECTED = 0;
timer_del('werewolf.joinwait');
$GAME = $PGAME = $GAMECHAN = $GAMETIME = $PHASE = $SEEN = $VISIT = $GUARD = $LVOTEN = $BULLETS = $DETECTED = $WAIT = $WAITED = 0;
%PLAYERS = ();
%NICKS = ();
%KILL = ();
@@ -1439,12 +1552,24 @@ sub on_uprivmsg {
if ($PLAYERS{lc $src->{nick}} =~ m/w/xsm or $PLAYERS{lc $src->{nick}} =~ m/t/xsm) {
# Get wolf count.
my $cwolves = 0;
foreach my $flags (values %PLAYERS) { if ($flags =~ m/w/xsm) { $cwolves++ } }
foreach my $flags (values %PLAYERS) { if ($flags =~ m/(w|t)/xsm) { $cwolves++ } }
# If there's more than one wolf, relay this message to the others.
if ($cwolves > 1) {
while ((my $plyr, my $flags) = each %PLAYERS) {
if ($plyr ne lc $src->{nick} and $flags =~ m/w/xsm or $flags =~ m/t/xsm) {
privmsg($src->{svr}, $NICKS{$plyr}, "\2$src->{nick}\2 says: ".join(q{ }, @msg))
# Also, lets try to ignore simulations.
if (uc(join(q{ }, @msg)) =~ m/^WOLF\sKILL/xsmi and
$COMMANDS{kill} !~ m/^WOLF\sKILL/xsmi) { return 1 }
# All good.
if ($msg[0] =~ m/^\001ACTION/xsm) {
shift @msg;
$msg[$#msg] =~ s/\001$//xsm;
privmsg($src->{svr}, $NICKS{$plyr}, "* \2$src->{nick}\2 ".join(q{ }, @msg));
}
else {
privmsg($src->{svr}, $NICKS{$plyr}, "\2$src->{nick}\2 says: ".join(q{ }, @msg));
}
}
}
}
@@ -1497,10 +1622,13 @@ sub on_nick {
$LYNCH{$new} = $LYNCH{lc $src->{nick}};
delete $LYNCH{lc $src->{nick}};
}
while (my ($accu, $ser) = each %LYNCH) {
if ($ser eq lc $src->{nick}) {
$LYNCH{$accu}{$new} = 1;
delete $LYNCH{$accu}{$ser};
foreach my $accu (keys %LYNCH) {
my %sers = %{$LYNCH{$accu}};
foreach my $ser (keys %sers) {
if ($ser eq lc $src->{nick}) {
$LYNCH{$accu}{$new} = 1;
delete $LYNCH{$accu}{$ser};
}
}
}
# That should be everything.
@@ -1582,7 +1710,7 @@ sub on_rehash {
}
# Start initialization.
API::Std::mod_init('Werewolf', 'Xelhua', '1.03', '3.0.0a10');
API::Std::mod_init('Werewolf', 'Xelhua', '1.07', '3.0.0a11');
# build: perl=5.010000
__END__
@@ -1593,7 +1721,7 @@ Werewolf - IRC version of the Werewolf detective/social party game
=head1 VERSION
1.03
1.07
=head1 SYNOPSIS
@@ -1625,7 +1753,7 @@ Internet Relay Chat.
It, obviously, is a complete module for Auto, and has absolutely no extra
dependencies.
It includes a whopping eight player roles, four of which are optional. See the
It includes a whopping nine player roles, five of which are optional. See the
ROLES section for more information on them.
If you want the best out of Werewolf, please be sure to read over CONFIGURATION.
@@ -1649,13 +1777,13 @@ and use aliases.
Here is a list of channel commands:
WOLF JOIN|J - Start/Join a game.
WOLF WAIT|W - Increases join wait time by 20 seconds.
WOLF START - Start the game play.
WOLF LYNCH|L - Cast vote for who to lynch.
WOLF RETRACT|R - Retract lynch vote.
WOLF VOTES|V - Return current votes.
WOLF SHOOT - Shoot someone with the gun.
WOLF STATS|S - Return current player statistics.
WOLF KICK|K - Kick a player from the game.
WOLF QUIT|Q - Leave the game.
Here is a list of private commands:
@@ -1666,8 +1794,6 @@ Here is a list of private commands:
WOLF GUARD - Guard a player.
WOLF ID - Investigate a player.
The WOLF KICK command requires the werewolf.admin privilege.
=head1 RULES
Since the rules for this particular version of Werewolf differ from the
@@ -1686,7 +1812,6 @@ Typing "!wolf join" in a channel starts a game, and a 60 second timer. Others
can join the game with "!wolf join". "!wolf start" starts play.
START will fail if the 60 second timer has not stopped and there is less than
the maximum amount of players.
The bot moderates the channel (it voices all players).
@@ -1814,25 +1939,38 @@ off UP, not normal mathematical rounding.
=item Villager (gun holder)
If a game has 6+ players, one villager (can also be seer/harlot/etc., but not
If a game has 8+ players, one villager (can also be seer/harlot/etc., but not
wolves or traitors.), will be given a gun with a certain amount special silver
bullets. To be exact, <PLAYER COUNT> * .12 rounded off UP.
During the day, (s)he can use "!wolf shoot <nick>" to shoot someone with that
gun, and the effect varies widely. Lets go over those.
* 1/5 chance - Miss. - Person misses. But at least they're confirmed safe, as
* 1/7 chance - Miss. - Person misses. But at least they're confirmed safe, as
wolves and traitors don't get to have guns.
* 1/5 chance - Unclean gun. - Gun explodes, in turn killing the shooter. Bummer!
* 1/7 chance - Unclean gun. - Gun explodes, in turn killing the shooter. Bummer!
* 3/5 chance - Hit. - If it hits a wolf, they die instantly (and are revealed
* 5/7 chance - Hit. - If it hits a wolf, they die instantly (and are revealed
to be a wolf.). If it hits a villager, 4/5 chance it'll just wound them and
make them unable to vote for the day. 1/5 chance it kills them. Oops!
So, obviously no matter what the case might be, the gun holder will always
reveal the innocence of at least someone.
=item Villager (drunk)
ATTENTION: Xelhua does NOT endorse drinking, especially underage, thus the
village drunk might be considered NSFW and can be disabled with
werewolf:rated-g. See CONFIGURATION.
If a game has 7+ players, one villager will be made the "drunk". Basically,
this is mostly just a name. But, if they also get the gun, there's extras:
* Person's bullet count gets tripled.
* Higher chance of missing when shooting.
=item Seer
The seer is like a villager, but gets a special ability, the ability of
@@ -1947,6 +2085,9 @@ AS SOON AS POSSIBLE.
A single traitor is assigned to a game if it has twelve or more players.
Oh and one more thing, if all wolves die yet the traitor remains, the traitor
is transformed into a wolf.
=item Detective
NOTE: Some people think that detectives make the game less interesting, or even
@@ -2002,6 +2143,8 @@ required. Also, it is case-sensitive.
*DEFINING* this configuration option will disable harlots (A.K.A. prostitutes),
because you might consider them to be inappropriate for your target audience.
It will also disable the village drunk, because they're also NSFW.
NOTE: Defining it disables harlots, regardless of the actual value. Remove it
to re-enable harlots.
+373
View File
@@ -0,0 +1,373 @@
# Module: WerewolfAdmin. See below for documentation.
# Copyright (C) 2010-2011 Xelhua Development Group, et al.
# This program is free software; rights to this code are stated in doc/LICENSE.
package M::WerewolfAdmin;
use strict;
use warnings;
use feature qw(switch);
use API::Std qw(cmd_add cmd_del timer_add timer_del trans conf_get);
use API::IRC qw(privmsg notice cmode ison);
# Initialization subroutine.
sub _init {
# Create the WOLFA command.
cmd_add('WOLFA', 0, 'werewolf.admin', \%M::WerewolfAdmin::HELP_WOLFA, \&M::WerewolfAdmin::cmd_wolfa) or return;
# Success.
return 1;
}
# Void subroutine.
sub _void {
# Delete the WOLFA command.
cmd_del('WOLFA') or return;
# Success.
return 1;
}
# Help hash for the WOLFA command.
our %HELP_WOLFA = (
en => "This command allows you to perform various administrative actions in a game of Werewolf (A.K.A. Mafia). \2Syntax:\2 WOLFA (JOIN|WAIT|START|KICK|STOP) [parameters]",
);
# Callback for the WOLFA command.
sub cmd_wolfa {
my ($src, @argv) = @_;
# We require at least one parameter.
if (!defined $argv[0]) {
notice($src->{svr}, $src->{nick}, trans('Not enough parameters').q{.});
return;
}
# Iterate the parameter.
given (uc $argv[0]) {
when (/^(JOIN|J)$/) {
# WOLFA JOIN
# Requires an extra parameter.
if (!defined $argv[1]) {
notice($src->{svr}, $src->{nick}, trans('Not enough parameters').q{.});
return;
}
# Check if a game is running.
if (!$M::Werewolf::PGAME and !$M::Werewolf::GAME) {
notice($src->{svr}, $src->{nick}, 'No game is currently running.');
}
elsif ($M::Werewolf::GAME) {
notice($src->{svr}, $src->{nick}, 'Sorry, but the game is already running. Try again next time.');
}
else {
# Check if this is the game channel.
if ($src->{svr}.'/'.$src->{chan} ne $M::Werewolf::GAMECHAN) {
notice($src->{svr}, $src->{nick}, "Werewolf is currently running in \2$M::Werewolf::GAMECHAN\2.");
return;
}
# Check if this user exists in channel.
if (!ison($src->{svr}, $src->{chan}, lc $argv[1])) {
notice($src->{svr}, $src->{nick}, "No such user \2$argv[1]\2 is on the channel.");
return;
}
# Make sure they're not already playing.
if (exists $M::Werewolf::PLAYERS{lc $argv[1]}) {
notice($src->{svr}, $src->{nick}, 'They\'re already playing!');
return;
}
# Set variables.
$M::Werewolf::PLAYERS{lc $argv[1]} = 0;
my $nick = $M::Werewolf::NICKS{lc $argv[1]} = $Core::IRC::Users::users{$src->{svr}}{lc $argv[1]};
# Send message.
my ($gsvr, $gchan) = split '/', $M::Werewolf::GAMECHAN, 2;
cmode($gsvr, $gchan, "+v $nick");
privmsg($gsvr, $gchan, "\2$nick\2 was forced to join the game by \2$src->{nick}\2.");
}
}
when (/^(WAIT|W)$/) {
# WOLFA WAIT
# Check if a game is running.
if (!$M::Werewolf::PGAME) {
if (!$M::Werewolf::GAME) {
notice($src->{svr}, $src->{nick}, 'No game is currently running.');
return;
}
else {
notice($src->{svr}, $src->{nick}, 'Werewolf is already in play.');
return;
}
}
# Check if this is the game channel.
if ($src->{svr}.'/'.$src->{chan} ne $M::Werewolf::GAMECHAN) {
notice($src->{svr}, $src->{nick}, "Werewolf is currently running in \2$M::Werewolf::GAMECHAN\2.");
return;
}
# Increase WAIT.
$M::Werewolf::WAIT += 20;
# And WAITED.
$M::Werewolf::WAITED++;
privmsg($src->{svr}, $src->{chan}, "\2$src->{nick}\2 forcibly increased join wait time by 20 seconds.");
}
when ('START') {
# WOLFA START
# Check if a game is running.
if (!$M::Werewolf::PGAME) {
if (!$M::Werewolf::GAME) {
notice($src->{svr}, $src->{nick}, 'No game is currently running.');
return;
}
else {
notice($src->{svr}, $src->{nick}, 'Werewolf is already in play.');
return;
}
}
# Check if this is the game channel.
if ($src->{svr}.'/'.$src->{chan} ne $M::Werewolf::GAMECHAN) {
notice($src->{svr}, $src->{nick}, "Werewolf is currently running in \2$M::Werewolf::GAMECHAN\2.");
return;
}
# Need four or more players.
if (keys %M::Werewolf::PLAYERS < 4) {
privmsg($src->{svr}, $src->{chan}, "$src->{nick}: Four or more players are required to play.");
return;
}
# First, determine how many players to declare a wolf.
my $cwolves = POSIX::ceil(keys(%M::Werewolf::PLAYERS) * .14);
# Only one seer, harlot, guardian angel, traitor and detective.
my $cseers = 1;
my $charlots = my $cdrunks = my $cangels = my $ctraitors = my $cdetectives = 0;
if (keys %M::Werewolf::PLAYERS >= 6) { $charlots++ unless conf_get('werewolf:rated-g') }
if (keys %M::Werewolf::PLAYERS >= 7) { $cdrunks++ unless conf_get('werewolf:rated-g') }
if (keys %M::Werewolf::PLAYERS >= 9) { $cangels++ unless conf_get('werewolf:no-angels') }
if (keys %M::Werewolf::PLAYERS >= 12 and conf_get('werewolf:traitors')) { $ctraitors++ }
if (keys %M::Werewolf::PLAYERS >= 16 and conf_get('werewolf:detectives')) { $cdetectives++ }
# Give all players a role.
foreach my $plyr (keys %M::Werewolf::PLAYERS) { $M::Werewolf::PLAYERS{$plyr} = 'v' }
# Push players into a temporary array.
my @plyrs = keys %M::Werewolf::PLAYERS;
# Set wolves.
while ($cwolves > 0) {
my $rpi = $plyrs[int rand scalar @plyrs];
if ($M::Werewolf::PLAYERS{$rpi} !~ m/^(w|s|g|h|d|t)$/xsm) {
$M::Werewolf::PLAYERS{$rpi} = 'w';
$cwolves--;
$M::Werewolf::STATIC[0] .= ", \2$M::Werewolf::NICKS{$rpi}\2";
}
}
$M::Werewolf::STATIC[0] = substr $M::Werewolf::STATIC[0], 2;
# Set seers.
while ($cseers > 0) {
my $rpi = $plyrs[int rand scalar @plyrs];
if ($M::Werewolf::PLAYERS{$rpi} !~ m/^(w|g|h|d|t)$/xsm) {
$M::Werewolf::PLAYERS{$rpi} = 's';
$cseers--;
$M::Werewolf::STATIC[1] = "\2$M::Werewolf::NICKS{$rpi}\2";
}
}
# Set harlots.
while ($charlots > 0) {
my $rpi = $plyrs[int rand scalar @plyrs];
if ($M::Werewolf::PLAYERS{$rpi} !~ m/^(w|g|s|d|t)$/xsm) {
$M::Werewolf::PLAYERS{$rpi} = 'h';
$charlots--;
$M::Werewolf::STATIC[2] = "\2$M::Werewolf::NICKS{$rpi}\2";
}
}
# Set drunks.
while ($cdrunks > 0) {
my $rpi = $plyrs[int rand scalar @plyrs];
if ($M::Werewolf::PLAYERS{$rpi} =~ m/v/xsm) {
$M::Werewolf::PLAYERS{$rpi} = 'vi';
$cdrunks--;
}
}
# Set guardian angels.
while ($cangels > 0) {
my $rpi = $plyrs[int rand scalar @plyrs];
if ($M::Werewolf::PLAYERS{$rpi} !~ m/^(w|h|s|d|t)$/xsm) {
$M::Werewolf::PLAYERS{$rpi} = 'g';
$cangels--;
$M::Werewolf::STATIC[3] = "\2$M::Werewolf::NICKS{$rpi}\2";
}
}
# Set traitors.
while ($ctraitors > 0) {
my $rpi = $plyrs[int rand scalar @plyrs];
if ($M::Werewolf::PLAYERS{$rpi} !~ m/^(w|h|s|d|g)$/xsm) {
$M::Werewolf::PLAYERS{$rpi} = 't';
$ctraitors--;
$M::Werewolf::STATIC[4] = "\2$M::Werewolf::NICKS{$rpi}\2";
}
}
# Set detectives.
while ($cdetectives > 0) {
my $rpi = $plyrs[int rand scalar @plyrs];
if ($M::Werewolf::PLAYERS{$rpi} !~ m/^(w|h|s|g|t)$/xsm) {
$M::Werewolf::PLAYERS{$rpi} = 'd';
$cdetectives--;
$M::Werewolf::STATIC[5] = "\2$M::Werewolf::NICKS{$rpi}\2";
}
}
# If there's 8 or more players, give one of them a gun.
if (keys %M::Werewolf::PLAYERS >= 8) {
my $rpi = $plyrs[int rand scalar @plyrs];
while ($M::Werewolf::PLAYERS{$rpi} =~ m/w/xsm || $M::Werewolf::PLAYERS{$rpi} =~ m/t/xsm) { $rpi = $plyrs[int rand scalar @plyrs] }
$M::Werewolf::PLAYERS{$rpi} .= 'b';
# And give them PLAYER COUNT * .12 bullets rounded up.
$M::Werewolf::BULLETS = POSIX::ceil(keys(%M::Werewolf::PLAYERS) * .12);
if ($M::Werewolf::PLAYERS{$rpi} =~ m/i/xsm) { $M::Werewolf::BULLETS = $M::Werewolf::BULLETS * 3 }
}
# Set variables.
$M::Werewolf::GAME = 1;
$M::Werewolf::PGAME = 0;
# Set spoke variables.
foreach (keys %M::Werewolf::PLAYERS) { $M::Werewolf::SPOKE{$_} = time }
# All players have their role, so lets begin the game!
my ($gsvr, $gchan) = split '/', $M::Werewolf::GAMECHAN, 2;
privmsg($gsvr, $gchan, "Game is now starting. (forced start by \2$src->{nick}\2)");
cmode($gsvr, $gchan, '+m');
# Delete waiting timer.
timer_del('werewolf.joinwait');
# Start timer for bed checking.
timer_add('werewolf.chkbed', 2, 5, \&M::Werewolf::_chkbed);
# Initialize the nighttime.
M::Werewolf::_init_night();
}
when (/^(KICK|K)$/) {
# WOLFA KICK
# Check if a game is running.
if (!$M::Werewolf::GAME and !$M::Werewolf::PGAME) {
notice($src->{svr}, $src->{nick}, 'No game is currently running.');
return;
}
# Check if this is the game channel.
if ($src->{svr}.'/'.$src->{chan} ne $M::Werewolf::GAMECHAN) {
notice($src->{svr}, $src->{nick}, "Werewolf is currently running in \2$M::Werewolf::GAMECHAN\2.");
return;
}
# Requires an extra parameter.
if (!defined $argv[1]) {
notice($src->{svr}, $src->{nick}, trans('Not enough parameters').q{.});
return;
}
# Check if the target is playing.
if (!exists $M::Werewolf::PLAYERS{lc $argv[1]}) {
notice($src->{svr}, $src->{nick}, "\2$argv[1]\2 is not currently playing.");
return;
}
# Kill the target.
privmsg($src->{svr}, $src->{chan}, "\2$argv[1]\2 died of an unknown disease. He/She was a \2".M::Werewolf::_getrole(lc $argv[1], 2)."\2.");
M::Werewolf::_player_del(lc $argv[1]);
}
when ('STOP') {
# WOLFA STOP
# Check if a game is running.
if (!$M::Werewolf::GAME and !$M::Werewolf::PGAME) {
notice($src->{svr}, $src->{nick}, 'No game is currently running.');
return;
}
# Check if this is the game channel.
if ($src->{svr}.'/'.$src->{chan} ne $M::Werewolf::GAMECHAN) {
notice($src->{svr}, $src->{nick}, "Werewolf is currently running in \2$M::Werewolf::GAMECHAN\2.");
return;
}
# End the game.
my ($gsvr, $gchan) = split '/', $M::Werewolf::GAMECHAN, 2;
privmsg($gsvr, $gchan, "\2$src->{nick}\2 is forcing the game to end...");
M::Werewolf::_gameover('n');
}
default { notice($src->{svr}, $src->{nick}, trans('Unknown action', $_).q{.}) }
}
return 1;
}
# Start initialization.
API::Std::mod_init('WerewolfAdmin', 'Xelhua', '1.00', '3.0.0a11');
# build: perl=5.010000
__END__
=head1 NAME
WerewolfAdmin - Administrative functions for Werewolf
=head1 VERSION
1.00
=head1 SYNOPSIS
None
=head1 DESCRIPTION
This module allows one to administer the Werewolf IRC game, provided by the
Werewolf module.
It provides the following commands:
WOLFA JOIN|J - Force join.
WOLFA WAIT - Force wait.
WOLFA START - Force start.
WOLFA KICK|K - Kick a player.
WOLFA STOP - Stop a game forcibly.
And requires the werewolf.admin privilege.
=head1 DEPENDENCIES
This module depends on the following Auto module(s):
=over
=item Werewolf
The Werewolf module provides the game that this module provides administrative
commands for. Using this module without Werewolf will likely cause a fatal
error.
=back
=head1 AUTHOR
This module was written by Elijah Perrault.
This module is maintained by Xelhua Development Group.
=head1 LICENSE AND COPYRIGHT
This module is Copyright (C) 2010-2011, Xelhua Development Group.
This module is released under the same terms as Auto itself.
=cut
# vim: set ai et ts=4 sw=4: