Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7079e203a8 | ||
|
|
727062b14b | ||
|
|
df31622f82 | ||
|
|
76d2c03281 | ||
|
|
303e03f4ee | ||
|
|
99bb0721ba | ||
|
|
6f9e6f0d5d | ||
|
|
ccab5e9ab9 | ||
|
|
03c1616364 | ||
|
|
193461abf4 | ||
|
|
f1a9b91a30 | ||
|
|
f3ad8e0e38 | ||
|
|
81ff64ba4f | ||
|
|
33b50a651a | ||
|
|
fdfc249ba8 | ||
|
|
f68646d155 | ||
|
|
6357c54574 | ||
|
|
a8ea3f0e64 | ||
|
|
3fdf7dcaf5 | ||
|
|
105e83699d | ||
|
|
338551b44c | ||
|
|
412261f478 | ||
|
|
988e93a6f1 | ||
|
|
6c4ff75a03 | ||
|
|
362310b863 | ||
|
|
a2002882d6 | ||
|
|
3ebe82ec28 | ||
|
|
42faabeef5 | ||
|
|
21fb5d4974 | ||
|
|
8147e9e32a | ||
|
|
0864f549d1 | ||
|
|
ba5de67e4a | ||
|
|
3bd8e9369d | ||
|
|
e33fd1df8d | ||
|
|
3ef78078c4 | ||
|
|
a1beabe76a | ||
|
|
f12b7ef527 | ||
|
|
ed56d53f1e | ||
|
|
e590c0dee3 | ||
|
|
9fca160de5 | ||
|
|
28e29f2dba | ||
|
|
c30f300b24 | ||
|
|
0d9a714c4a | ||
|
|
87ff93945f | ||
|
|
c13a4e2ffe | ||
|
|
42fcac5cc0 | ||
|
|
01a432f023 | ||
|
|
a47211763c | ||
|
|
8cddc69209 | ||
|
|
b6eb0c17cc | ||
|
|
38b3e4c3d8 | ||
|
|
503a7ed990 | ||
|
|
579485776d | ||
|
|
f5db549052 | ||
|
|
72006a8e7e | ||
|
|
2ca0885741 | ||
|
|
6c6b8604bc | ||
|
|
da28c54652 | ||
|
|
f0b49acbd0 | ||
|
|
58447eb40a | ||
|
|
363a724ed3 | ||
|
|
a122977644 |
No files matched your search
@@ -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!
|
||||
@@ -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
@@ -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
|
||||
===============================================================================
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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.
|
||||
|
||||
@@ -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
@@ -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) {
|
||||
|
||||
@@ -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} }
|
||||
|
||||
@@ -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
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
@@ -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
@@ -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:
|
||||
@@ -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.
|
||||
|
||||
@@ -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:
|
||||
Reference in new issue
Block a user