Add project files.

This commit is contained in:
2025-09-12 19:42:46 -06:00
parent 0ffd916805
commit a4ff18076a
37 changed files with 6089 additions and 0 deletions

57
IdleRPG.sln Normal file
View File

@@ -0,0 +1,57 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.14.36414.22 d17.14
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "bot.v3.1.2", "bot.v3.1.2", "{02EA681E-C7D8-13C7-8484-4AC65E1B71E8}"
ProjectSection(SolutionItems) = preProject
bot.v3.1.2\.irpg.conf = bot.v3.1.2\.irpg.conf
bot.v3.1.2\bot.v3.1.2.pl = bot.v3.1.2\bot.v3.1.2.pl
bot.v3.1.2\ChangeLog.txt = bot.v3.1.2\ChangeLog.txt
bot.v3.1.2\events.txt = bot.v3.1.2\events.txt
bot.v3.1.2\irpgdbtool = bot.v3.1.2\irpgdbtool
bot.v3.1.2\modifiers.txt = bot.v3.1.2\modifiers.txt
bot.v3.1.2\questinfo.txt = bot.v3.1.2\questinfo.txt
bot.v3.1.2\README = bot.v3.1.2\README
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "irpg", "irpg", "{440DEC4B-57C9-4361-9949-7CF55F9CFED8}"
ProjectSection(SolutionItems) = preProject
irpg\admincomms.txt = irpg\admincomms.txt
irpg\ChangeLog = irpg\ChangeLog
irpg\commonfunctions.php = irpg\commonfunctions.php
irpg\config.php = irpg\config.php
irpg\contact.php = irpg\contact.php
irpg\db.php = irpg\db.php
irpg\down.png = irpg\down.png
irpg\dump.php = irpg\dump.php
irpg\footer.php = irpg\footer.php
irpg\g7.css = irpg\g7.css
irpg\head.png = irpg\head.png
irpg\header.php = irpg\header.php
irpg\hits.db = irpg\hits.db
irpg\idlerpg-adv.txt = irpg\idlerpg-adv.txt
irpg\index.php = irpg\index.php
irpg\makemap.php = irpg\makemap.php
irpg\makequestmap.php = irpg\makequestmap.php
irpg\makeworldmap.php = irpg\makeworldmap.php
irpg\maperror.png = irpg\maperror.png
irpg\newmap.png = irpg\newmap.png
irpg\players.php = irpg\players.php
irpg\playerview.php = irpg\playerview.php
irpg\quest.php = irpg\quest.php
irpg\README = irpg\README
irpg\tablegrad.gif = irpg\tablegrad.gif
irpg\up.png = irpg\up.png
irpg\worldmap.php = irpg\worldmap.php
irpg\xml.php = irpg\xml.php
EndProjectSection
EndProject
Global
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {8C959837-E00F-4F71-9966-96BB12DA3FC4}
EndGlobalSection
EndGlobal

241
bot.v3.1.2/.irpg.conf Normal file
View File

@@ -0,0 +1,241 @@
# Configuration file for IRPG bot. Prefix comments with a #. Line must start
# with a # to be a comment (no leading spaces and no comments starting in the
# middle of a line).
#
# If you don't personally know your admins, or you're just not the trusting
# type, you may want to look at the ownerpevalonly, owneraddonly, and
# ownerdelonly options. ownerpevalonly prevents non-owner accounts from using
# the PEVAL command, which can allow admins to execute arbitrary code under the
# username that the bot runs as. owneraddonly prevents non-owner accounts from
# assigning admin status to users. ownerdelonly prevents non-owner accounts from
# removing admin status from users
#
# 'disablepeval' option was renamed to 'ownerpevalonly'
#
# Command line options override options in this file.
# remove or comment out this line so the bot knows that you edited the config
# file
die
# local hostname or address to bind to. leave blank or comment out if you don't
# want to use a vhost
#localaddr myvhost.domain.com
# server name:port, enter as many as you like
server miami.fl.us.irc-network.org:6667
server dallas.tx.us.irc-network.org:7000
server brussels.be.eu.irc-network.org:6660
# bot's nickname
botnick bot
# bot's username
botuser bot
# real name field
botrlnm http://www.slashnet.org/~bot/
# channel name (followed by key, if your channel uses a key
botchan #irpg s3cr3t.p4ss
# (identify) command to send upon successful connect. if using a privmsg
# command, you must begin the text of the message with a ":" -- see below
botident PRIVMSG NickServ :identify ilovedink
# modes to set bot upon successful connect
botmodes +ix
# command to send upon joining channel. %botnick% will evaluate to the bot's
# current nickname, so you don't have to worry about opping the wrong person. if
# using a privmsg command, you must begin the text of the message with a ":" --
# see below
botopcmd PRIVMSG ChanServ :op #idlerpg %botnick%
# command sent to recover nick if bot's primary nickname is in use if using a
# privmsg command, you must begin the text of the message with a ":" -- see
# below
botghostcmd PRIVMSG NickServ :ghost bot ilovedink
# URL to send users to for help
helpurl http://idlerpg.net/
# admin commands list (for admin help)
admincommurl http://idlerpg.net/admincomms.txt
# base time to level up, 600 = 10 minutes
rpbase 600
# time to next level = rpbase * (rpstep ** CURRENT_LEVEL)
rpstep 1.16
# penalty time = penalty * (rppenstep ** CURRENT_LEVEL)
rppenstep 1.14
# player database file
dbfile irpg.db
# where quests/godsends/calamities are stored
eventsfile events.txt
# debug mode on/off flag, merely prints what text was received, what queue
# number outgoing text is given, and what text is sent to server (to the
# debug file, no longer to STDOUT)
debug off
# choose filename to send debug output to. text is appended to this file
# while the bot is in debug mode, in lieu of STDOUT
debugfile debug.txt
# Use URL-type banning for non-logged-in users that have been on the channel
# less than 90 seconds?
doban on
# URLs containing these terms will not be banned by the 'http:'
# advertisement ban (if you have it turned on). enter as many as you like
okurl ultrazone.org
okurl idlerpg.net
# modes of silence. in mode 0, bot sends all privmsgs. in mode 1, only
# chanmsg() is disabled. in mode 2, only privmsg() to non-channels is
# disabled. in mode 3, privmsgs to users and channels are disabled
silentmode 0
# write quest info file? all this file does is give outside programs info
# about the active quests, its participants, their positions, and time to
# completion
writequestfile on
# filename for the above-mentioned file
questfilename questinfo.txt
# voice users on login (and register)? if you like, you can set your channel
# +m, then +v clients as they login, cutting down on spam. however, if your
# users generally bring in a second client to chat with, that client won't
# be able to speak in the channel
voiceonlogin on
# disallow usernames and character classes with control codes (bold, color,
# underline, bell, etc)?
noccodes on
# disallow usernames and character classes that contain "non-printable"
# characters? it's a good idea to leave this option on, as I have had
# problems in the past with using binary hash keys
nononp on
# URL where users can reach the online quest map, if available. if not
# offering a map to users, leave this blank
mapurl http://idlerpg.net/quest.php
# allow a STATUS command for users? this is a p0 command to view information
# on an irpg user. useful if you don't have a website where users can view
# their stats
statuscmd off
# filename to write our PID to. leave blank or comment out if pidfile is
# unnecessary to you
pidfile .irpg.pid
# attempt to reconnect if disconnected?
reconnect on
# seconds to wait before attempting to reconnect? don't hammer your irc
# network, please; 90+ seconds is suggested
reconnect_wait 120
# this is what the bot considers to be an "internal clock" of sorts. some
# examples of where this is used: $freemessages lines of text from the
# message queue are sent every self_clock seconds; every self_clock seconds,
# the players move on the map (self_clock times to simulate movement every
# second); HOGs, calamities, godsends, etc. are given a chance to occur
# every self_clock seconds; and the list goes on. if you have problems with
# the bot flooding off, try increasing this number to 4 or 5. if your bot
# appears to 'lag' because it is queueing too much text, you can set this
# as low as 1. this must be an integral value (no fractions), and it must be a
# factor of 60 (or certain events will not occur, like database rewrites)
self_clock 3
# file into which character modifier texts are appended
modsfile modifiers.txt
# disallow the registration of usernames already existing in a different
# case? ie, jon == Jon == JON
casematters on
# allow rudimentary netsplit detection, and a) give no penalty and b) log
# them back in upon return? I always suggest to users that they switch to
# the server that the bot is on, but this has been a frequent request, so.
# will pick up quit messages that match /^\S+\.\S+ \S+\.\S+$/. if your
# network does not prefix quit messages with "Quit: " (or something other
# string), then users can cheat this at their whim
detectsplits on
# time to wait for netsplit users to return? in seconds. 900 = 15 minutes, good
# for large nets
splitwait 900
# allow non-admin users some information on the bot, such as the server it
# is connected to and the nicknames of online admins via a p0 INFO command?
allowuserinfo on
# ignore the new scaling features and use the old method for calculating the
# odds of events occurring? if you have a very large game and were
# comfortable with the speed that HoGs, Godsends, Calamities, etc. were
# occurring, you may want to set this
noscale off
# allow bot to access http://jotun.ultrazone.org/g7/count.php?new=1 each
# time someone registers a new username? it only takes a second, and I'd
# really like to be able to keep up with the total player count :^)
phonehome on
# username of the bot's owner. this account cannot be DELADMINed and has access
# to PEVAL even if it is disabled
owner jotun
# disable the PEVAL command for non-owner accounts? this command allows the
# execution of arbitrary Perl code by bot admins, effectively giving them
# complete control of the account under which the bot runs. I prefer to leave
# this command available and choose my admins with care, but, whatever :^)
ownerpevalonly off
# only owner account can use the MKADMIN command to assign admin status to
# users?
owneraddonly on
# only owner account can use the DELADMIN command to remove admin status from
# users?
ownerdelonly on
# check for newer versions each time the bot starts up? this will access the
# URL http://jotun.ultrazone.org/g7/version.php?version=$version and report on
# any updated versions and what features there are/bugs have been fixed
checkupdates on
# send list of usernames that are automatically logged back in when we restart
# (iff that list is < 1 k)? this should, hopefully, no longer cause the bot to
# flood off. the function that sends text to the server will no longer send more
# than 768 bytes to the server every self_clock seconds. the old function would
# send as much as 5 * 512b or 2.5k each self_clock seconds, and as this was
# usually the feature that caused such a large amount of text to be sent at
# once, if your channel had a large amount of users, this would cause it to
# flood off. so, though I think the bug is fixed, I offer the option to turn
# this off
senduserlist on
# limit maximum amount of penalty for one event? this will prevent a user from
# being penalized more than <X> seconds for one event: part, privmsg, notice,
# kick, etc. set to 0 if you want to disable limiting.
# 604800 == 7 * 86400 == 1 week
limitpen 604800
# if you would like a custom-sized map, define the width of your map here:
mapx 500
# if you would like a custom-sized map, define the length of your map here:
mapy 500
# specify modes / line. the bot will override this from what it grabs from the
# server's 005 numeric, though, if anything. used only for auto-login voicing
modesperline 3

651
bot.v3.1.2/ChangeLog.txt Normal file
View File

@@ -0,0 +1,651 @@
This is the changelog for the Idle RPG bot by jotun, jotun@idlerpg.net,
http://idlerpg.net. Entries are written backwards. That is, items at the bottom
of the file were added first, and each subsequent addition is placed on a line
before it. Don't ask me why I do it that way: I do not know.
Thanks for your interest in the Idle RPG! Feel free to contact me with ideas and
comments, or post them in the forum on the website for public view.
--------------------------------------------------------------------------------
v3.1.2: released 6/6/04
--------------------------------------------------------------------------------
- applied a user-submitted patch to fix a sprintf() bug (anonymous @ forum)
- quest() now calls writequestfile() when it completes
- loaddb() now calls backup() before it starts
--------------------------------------------------------------------------------
v3.1.1: released 6/3/04
--------------------------------------------------------------------------------
- fixed 2 typos having to deal with die() messages when reading the config
file (meij, et al)
- quest() now calls writequestfile() when it completes so that it is
immediately available
- loaddb() now calls backup() before it starts so you always have an
up-to-date backup if your bot mangles your db
- readconfig() now strips out \r and \n (meij, kylemson, et al)
--------------------------------------------------------------------------------
v3.1.0: released 6/2/04
--------------------------------------------------------------------------------
- added a config file so you don't have to re-setup configuration options
everytime you upgrade. added a function readconfig() to read this file or
die() if it cannot be found
- SIGHUP will now call readconfig()
- added a DELADMIN command to remove admin status from a username. format:
/msg bot DELADMIN <account>
owner account cannot be DELADMINed. DELADMIN may be limited to owner account
depending on configuration (TGS)
- added an 'owner' account option. owner cannot be DELADMINed, among other
things
- added an 'owneraddonly' option. if set, only owner account can MKADMIN
- added an 'ownerdelonly' option. if set, only owner account can DELADMIN
- renamed disablepeval to ownerpevalonly. if set, only owner account can PEVAL
- added missing command line options for %opts options
- fq() will limit itself to either 1 message or <= 768 bytes output per call,
regardless of $freemessages
- added an option to turn off the sending of the list of users automatically
logged back in on a bot restart, even if the list < 1 k
- added an option to limit the penalty a single event can incur, 'limitpen'.
set to 0 to disable the feature, otherwise is taken to be an integral number
of seconds
- Win32 no longer tries to turn terminal echo on/off via "stty"
- tarball now unpacks files to their own directory instead of .
- removed unused $v, $debug variables
- auto-login would not voice users that it logged in even if voiceonlogin was
set, fixed (wogi, et al)
- fixed a comment having to do with auto login
- $rpreport should not have been adjusted by $curtime, but by
$opts{self_clock} to keep it reliable. this may have caused some loss of
data as the bot neglected to properly backup its database. so sorry! should
now be fixed (many)
- item godsend was removing 10% of item's value instead of adding it. another
copy/paste error. sorry! (Jim Dew)
- fixed a bug that resulted in users that caused quests to fail not being
penalized, as they were set as 'offline' before the bot had a chance to
penalize them (Jim Dew)
- added options to define the size of your IRPG grid, 'mapx' and 'mapy' (Rick)
- team battle now shows roll/sum like other battles (anonymous @ forum)
- added REHASH command to call readconfig()
- added an option to define the number of modes per line to use when voicing
users after an auto login. this variable may be overriden by the server's
directive (Rick)
--------------------------------------------------------------------------------
v3.0.2: released 5/30/04
--------------------------------------------------------------------------------
- calls evilness() and goodness() should have been checking against the number
of online evil users and good users respectively, not the total number of
online users (SickMind)
- changed max length of auto-login text to 1k before bot will refuse to send
- fixed a problem with the bot penalizing the kicker instead of the kickee
when someone was kicked (Preston, anonymous, Soc @ idlerpg.net forum)
--------------------------------------------------------------------------------
v3.0.1: released 5/29/04
--------------------------------------------------------------------------------
- forgot to add some sort of mechanism for setting up admins for new bots.
whoops. bot will now prompt for an owner's account details if it cannot find
$opts{dbfile} (Secret, anonymous @ idlerpg.net forum)
- fixed a typo in the ChangeLog ;)
- Vayanla noted that there was STILL a time discrepancy for very large games
(or very slow computers). many thanks to him for his help! this is now
fixed
--------------------------------------------------------------------------------
v3.0: released 5/29/04
--------------------------------------------------------------------------------
- fixed a bug causing RESTART not to work unless the bot's filename happened
to be the same as its nickname
- item modifiers as well as time modifiers are now stored in the modifiers
file. changed name of tlog sub to clog (time -> character)
- changed database write to every minute instead of every $opts{self_clock}.
to lower the chance of lost stats, the bot calls writedb() if you request a
DIE, JUMP, or RESTART. this should cut down on much of the cpu usage
- added a function writedb() which writes out the bot's db from memory so it
can be done outside of rpcheck()
- the team battle code would choose 6 random users to participate in a team
battle, but would not then randomize these users as far as teams go. that
is, if a username generally appeared at the end of a keys(%rps) list, and
made it into the list of 6 random users, that user would always defend
instead of attacking, as he would be at the end of the list. the list of 6
users is now shuffled using a Fisher-Yates shuffle, code from The Perl
Cookbook (by O'Reilly. a really great read!) (Peter Beentje)
- added a "user alignment" feature. users may align with good, neutral, or
evil. 'good' users have a 10% boost to their item sum for battles, and a
1/12 chance each day that they, along with a 'good' friend, will have the
light of their god shine upon them, accelerating them 5-12% toward their
next level. 'evil' users have a 10% detriment to their item sum for battles
(ever forsaken in their time of most need...), but have a 1/8 chance each
day that they will either a) attempt to steal an item from a 'good' user
(whom they cannot help but hate) or b) be forsaken (for 1-5% of their TTL)
by their evil god. after all, we all know that crime doesn't pay. also,
'good' users have only a 1/50 chance of landing a critical strike when
battling, while 'evil' users (who always fight dirty) have a 1/20 chance.
neutral users haven't had anything changed, and all users start off as
neutral. to change your alignment:
/msg bot ALIGN <good|neutral|evil>
I haven't run the numbers to see which alignment it is better to follow, so
the stats for this feature may change in the future (FishyTowel @
idlerpg.net forum)
- added new item, Juliet's Glorious Ring of Sparkliness, item level 50-74,
required user level 25+, chance 1/40, tag 'h'
- rather than error when PEVAL produces > 15 lines of output, PEVAL will now
queue its text if lines of output created >= 4 or size of text > 1k
- LOGIN command now responds via notice rather than privmsg
- added "named items," meaning that unique items have a letter appended to
them, saying which unique item they are. Mattt's Omniscience Grand Crown is
"a," Res0's Protectorate Plate Mail is "b," Dwyn's Storm Magic Amulet is
"c," Jotun's Fury Colossal Sword is "d," Drdink's Cane of Blind Rage is "e,"
Mrquick's Magical Boots of Swiftness is "f," and Jeff's Cluehammer of Doom
is "g"
- changed split() on incoming data to split on /\s/ instead of / /; users
could otherwise register usernames or classes containing tabs, which would
cause the bot to die when reading the (tab-delimited) database (chris young)
- changed the SIGHUP handler from '0' to 'sub { };'. should eliminate the
"Signal handler '0' not defined" warning (too many to list)
- added an item calamity and an item godsend. if you are calamitized, you have
a 10% chance of one of your amulet, charm, weapon, tunic, set of leggings,
or shield losing 10% of its item value. if you are godsent, you have a 10%
chance that one of the above items will gain 10% of its item value (carl
wyles @ idlerpg.net forum)
- %botnick% in $opts{botopcmd} will be evaluated to the bot's current nickname
to avoid opping another, more evil user when the bot's nickname is in use
- added an option to give non-admin users limited access to the INFO command.
when enabled, non-admin users can use the INFO command to learn to which
server the bot is connected and the nicknames of online admins (mike @
idlerpg.net forum)
- added an option to disallow the registration of usernames and classes
containing "non-printable" characters. it's a good idea to leave this option
on, as I have had problems in the past with using binary hash keys (TGS)
- whenever a non-admin players walks over an admin player on the map, he/she
has a 1% chance to bow ;) (mike stewart)
- changed sending of WHO and $opts{botopcmd} from numeric 001 to receipt of
bot's JOIN
- added an option to disable the PEVAL command for users that want to have
less than trustworthy admins ;^) (TGS)
- Run noted that (undernet?) servers allow you a certain number of "free"
messages before output should be limited to 1 message / 2 seconds. fq() now
sends as many of these "free" messages as it can, rather than sending only
one message per call (Run)
- removed some odd sts("MODE $opts{botchan}"); -- not sure why i put that in
- added rudimentary netsplit detection, which a) gives no penalty and b) logs
users in upon return. will pick up quit messages that match
/^\S+\.\S+ \S+\.\S+$/. if your network (or server) does not prefix quit
messages with "Quit: " (or some other string), or otherwise disallows faked
netsplit quit messages, then users can cheat this at their whim. added
option to turn netsplit detection on or off. added option of how long to
wait before automatically logging split users out and forgetting they ever
existed. added sub checksplits() which will iterate over the list of split
nick!user@hosts, remove those which have expired ($opts{splitwait}), and log
the user out. would love input on this feature, as i expect bugs
- HELP command for non-admins is now less helpful. generates one line of text
containing URL for help
- attempting to PUSH a user more than their TTL now sets their TTL to 0 as
well as generating a notice to the admin. successful PUSH now only
chanmsg()s instead of chanmsg()ing and privmsg()ing the admin
- $arg[3] changed to lowercased, leading-:-stripped $arg[3] in privmsg block
- cleaned up more code. changed (most) elses elsifs where appropriate. cleaned
up some logic. dropped all uses of next(). attempted to add () to function
calls wherever it was missing
- private messages and notices to the bot no longer penalize you (mrChewie)
- changed ha() to find access by username instead of nickname
- added a finduser() sub to return a logged-in username matching a given
nickname.
- changed case of $arg[1] after PONG rather than lc()ing it for every
comparison (mrChewie)
- at least 15% of all online players must be level 45+ for the hourly battle
of a level 45+ player to occur (anonymous @ idlerpg.net forum)
- fixed a serious bug with the bot not tracking changes to its nick (ie, by
NickServ or PEVAL) -- this caused all messages sent to the bot to be
penalized (TGS)
- added $opts{casematters}, which, when set, will not allow the registration
of usernames that already exist in a different case (MeBeHere)
- changed db backup, top players report to every 10 hours
- added $opts{modsfile}, which is where Time Modifier texts are appended.
also, tlog() now debug()s and chanmsg()s an error message if it cannot open
the file (MeBeHere)
- HOG was only 5-74%, corrected to 5-75% of TTL
- added an option $opts{self_clock} which is rather like the old $alrmint var,
except this probably works without exploding if you change it. calamities,
godsends, etc. should take this number into account when calculating odds
- added a server list rather than static server. bot should try each server in
the server list twice before giving up (meij)
- added a PID filename option, to which the bot will write its PID (meij)
- added a few more cattle-themed calamities (anonymous @ idlerpg.net forum)
- added a trailing '!' to godsend() text instead of the drab old '.'
- added some new quests/calamities/godsends contributed by users. edited some
old calamities/quests/godsends. please feel free to post your ideas for more
to http://idlerpg.net/forum.php! (anonymous, Afbc0m, anjira, jv, mrChewie,
W8TVI, et al)
- attempted to scale occurences of HOGs, godsends, calamities, and team
battles. HOGs should occur about 1/user/20 days, calamities 1/user/8 days,
godsends 1/user/4 days, team battles 1/user/4 days. does this by calculating
the odds of a HOG as rand(20*86400/clock) < NUMBER_ONLINE_PLAYERS, odds of
calamities as rand(8*86400/clock) < NUMBER_ONLINE_PLAYERS, etc. this appears
to work great with at least 10 clients (tested up to 300), but doesn't seem
to work as well below that. would appreciate input
- debug information is now written to a file instead of STDOUT. bot now
daemonizes even though it is in debug mode. added sub debug() which takes an
argument of text to write to the debug file (yeoj)
- added new item, Jeff's Cluehammer of Doom, item level 300-350, required user
level 52+, chance 1/40
- bot will try to regain primary nickname if he sees it come open through a
/nick or /quit
- DELOLD command will removed non-logged-in accounts that have not been logged
into in more than N days. format is:
/msg bot DELOLD <N days>
DELOLD is a p0, admin command (DinTn)
- added option to enable a STATUS command. this p0 command gives information
on a user, such as level, class, time to level, item sum, etc. useful for
those IRPGs that lack a website. format is:
/msg bot STATUS [username]
if username argument is not passed, returns information on the user issuing
command. must be logged in to use STATUS (TGS)
- possibly added option to choose which local address/hostname and local port
to bind to. let me know if this does/doesn't work (DARKutz, Brad)
- added security note to head of file
- will not send auto-login user list if text > 2048 bytes
- added $opts{botmodes} which will set the bot's usermode to given string on
connect
- removed reset of last login time on auto-login; last login should be when
user last logged in, not when the bot logged them back in
- levels after level 60 have a next time to level of (time to level @ 60) +
(1 day) * (level - 60). levels below 60 have not changed. the exponential
code was getting a little too heavy by itself (TGS)
- RELOADDB would log all players out; fixed
- sts() & fq() check state of socket before attempting write. if cannot write,
outgoing queue is cleared
- added new item, Mrquick's Magical Boots of Swiftness, item level 250-300,
required user level 48+, chance 1/40
- debug messages are now timestamped. added a few extra debug messages, mostly
for fun
- top player report no longer occurs immediately after startup, but every 6
hours from then on
- added option to disallow registration of usernames/character classes
containing ctrl codes (Skill0)
- changed auto-login code from list to hash. would take several minutes to
synch to a channel with hundreds of users. now takes < 1s (Vayanla et al)
- removed the hard-coded "#G7" from the top players list.. whoops :^) that's
been there for some time now, can't believe no one ever noticed (HaRRo)
- added option to voice users on login/register. if you +m your channel, this
will cut down on spam, but won't allow non-logged-in or devoiced/deopped
clients to talk (pingh, wishes, aphade, et al)
- added a penalize() sub to make penalties a little cleaner
- added %quest hash to keep up with active quest info
- added option to write active quest info to file; this makes it readable by
outside programs
- can now specify multiple words for the advertisement ban, or turn feature
off entirely
- removed all alarm() code, should now run on any system supporting select(2)
(including, but not limited to, Win32). should also fix a nasty, terrible
time drift bug; with the amount of processing done in rpcheck(), the next
alarm() would come later than expected, awarding the user with idling less
than he had actually idled. it's a small amount, but adds up to about 205
seconds difference in the clocks after ~9.25 hours (in my tests; will differ
from machine to machine). MANY thanks to this bug's reporter, Ville
Luolajan-Mikkola
- added CLEARQ command, will clear all items in outgoing message queue
- INFO shows outgoing queue status, registrations this period, and total users
- cleaned up options section a little bit, made a few other code clean-ups
- created this file, ChangeLog.txt. the bot's code was getting too long
- registrations are now limited to 1 / sec. this should keep floodbots from
registering hundreds of accounts
- removed ALERT command
- removed $opts{admin} array, there is now a field in the db to mark this.
there is also a MKADMIN command to set an account as having admin access.
syntax is:
/msg bot MKADMIN <username>
there is no way to remove an account's administrator privileges, save from
editing the database by hand (well, there is PEVAL). so, don't assign this
lightly. admins have full access to the account under which you run the bot
- die() call if could not write irpg.db is now a chanmsg() instead
- added an outgoing message queue. all messages are now output at 1 message /
second, unless a non-zero $skipq flag is passed to sts(). privmsg(),
notice(), and chanmsg() calls pass their $force flag as a $skipq flag.
PONGs pass a $skipq of 1 (LexCyber)
- fixed a rather huge bug that someone on slashnet noticed. registering
\001PING\001 (or any other ctcp) would send that CTCP to the channel, then
penalize any who responded. usernames may no longer include a \001
- godsends, calamities, and quests were all moved to one file,
$opts{eventsfile}. quests are prefixed with a Q1 or Q2, depending on their
type; calamities with a C; and godsends with a G. quests are also prefixed
by their required coordinates if the quest type is 2
- fixed a typo in the Dwyn's Storm text
- changed code indentation to four spaces. reworked a lot of code to fit <= 80
columns
- changed QUEST command and quest() output to be a little more grammar-
friendly
- item stealing! if you are level >= 20, and you win a battle against a
player, you have a slightly less than 2% chance of stealing an item from
them. the 2% comes from a) you have a 1/25 chance to attempt to steal an
item and b) you have a 50% chance that your item (type is random) is lower
than theirs. the reason it's 'slightly less than' 2% is because you cannot
both Critical Strike a user and steal an item, so it's (2 - (1/35))%. you
cannot steal an item of lower level than your current item (Afbc0m)
- fixed duration() to show 1 day without trailing 's'
- re-added report of TTL after battle and after critical strike
- quest() function now chanmsg()s an error if it cannot open the
$opts{eventsfile} file
- INFO command now uses privmsg() force flag
- added grid! thanks to Joakim @ orkut for this great idea. within the irpg
world are all of the players on a 500x500 "grid" or map. every second, your
character has an equal chance to step left, right, or neither, and an equal
chance to step up, down, or neither. if your character encounters another
player, you have a 1/(# of online players) chance to battle. also, some
quests require all characters to reach some point on the map. quest
penalties and awards have not changed
- added REMOVEME command for users. if you are logged in,
/msg bot REMOVEME
will delete your account. this is a p0 command :^)
- added NEWPASS command for users. if you are logged in,
/msg bot NEWPASS <new password>
will set a new password. this is a p0 command
--------------------------------------------------------------------------------
v2.4.1: unreleased
--------------------------------------------------------------------------------
- PEVAL will now error and refuse to send output > 15 lines. this is to avoid
my own errors
--------------------------------------------------------------------------------
v2.4+fixes: released 2/20/04
--------------------------------------------------------------------------------
- items are set to 0 on account creation; they were previous undefined
- bug with QUEST command fixed; would say no active quest even when a quest
was active
--------------------------------------------------------------------------------
v2.4: released 10/13/03
--------------------------------------------------------------------------------
- updated privmsg() function to avoid annoying substr()/uninitialized value
warnings
- few small bugs in battling bot fixed. a win against bot awards you with 20%
of your TTL removed. a loss to bot adds 10% of your TTL to your clock
- bot's item sum is now the highest item sum of all users + 1 (mumkin)
- fixed RESTART command to clear alarm() before trying to exec()
- WHOAMI displays class, TTL (Minhiriath)
- CALC command removed
- added notice() function which mirrors the operation of privmsg()
- SILENT command allows admin to switch bot between 4 modes of silence. in
mode 0, bot sends all privmsgs. in mode 1, only chanmsg() is disabled. in
mode 2, only privmsg()/notice() to non-channels is disabled. in mode 3,
privmsgs/notices to users and channels are disabled. silent mode is also
configurable as $opts{'silentmode'}, so you can setup a bot in any channel
without it interrupting the channel with its privmsgs (???)
- third parameter added to privmsg()/notice(); force flag ignores $silentmode
- hard-coded check for OKish URLs to bot's 'http:'-style banning now
configurable (sean)
- JUMP command no longer penalizes if required argument is left blank
- BACKUP admin command tells bot to copy $opts{'dbfile'} to
.dbbackup/$opts{'dbfile'}TIMESTAMP; added backup() function to handle this
- RELOADDB command allows admin to force bot to reload player database file,
rewriting all memory. RELOADDB can only be used while in pause mode
- PAUSE command allows admin to place bot into pause mode. in pause mode, bot
will update player stats, but will not write database. combined with
RELOADDB, very effective for updating all players stats through external
script without taking bot offline. new accounts cannot be registered
while in pause mode
- QUEST command (p0) tells the active quest, its participants, and its time
left to completion
- ban message for 'http:'-type bans now makes unban-time more clear
- things have been sped up a bit. random battles for users level 45+ now occur
every hour. random chance for HOG, Godsends, Calamities, and Team Battles
were increased by a factor of 5
- time between quests upped to 12 hours. level requirement for quests upped to
40+. in addition, must have been online for at least 10 hours to be selected
for quests. number of persons on quest lowered to 4. quest penalty is now a
p15 instead of 2% of your TTL. this makes more sense, as users who were very
close to leveling were penalized almost nothing (inkblot et al)
- fixed spelling of 'caffeinated' (sean)
- botchan variable now shows how to join channel with key (Dan)
--------------------------------------------------------------------------------
v2.3.1: released 9/20/03
--------------------------------------------------------------------------------
- fixed bug with item finding; bad logic sometimes resulted in user not
finding any item (thanks mumkin!)
--------------------------------------------------------------------------------
v2.3: released 8/29/03
--------------------------------------------------------------------------------
- Jotun's Fury max level dropped back to 174
- added the Drdink's Cane of Blind Rage with item level 175-200
- all time modifiers (battles, HoG, etc) are now written to modifiers.txt
- function tlog() logs a string to modifiers.txt and returns the string
- changed WHOAMI to not use $_
- fixed another bug where changing your nick would prevent you from being a
candidate for auto-login
- LOGOUT command added as a p20
- you may now only be logged in under one character at a time. this will help
protect the bot from being flooded when a single user signs on under 10
accounts, then is penalized and warned 10 times. attempts to login under two
names are not penalized
- fixed a bug where all of your accounts were automatically logged on so long
as they shared the same host as you, regardless of whether they were online
before (on bot restart)
- there is a 1/20,000 chance of a calamity occuring every 5 seconds. the
calamity() function chooses a random user, then smites them with bad luck.
the penalty for a calamity is a random 5-12% of next TTL. users are only
chosen from the pool of online players
- there is a 1/10,000 chance of a godsend occuring every 5 seconds. the
godsend() function chooses a random user, then betters their luck. the
award for a godsend is a random 5-12% of next TTL. users are only chosen
from the pool of online players
- there are now 'quests' -- six level 30+ users are chosen to go on a quest
at a time. if all six users make it to the quest's end, all questers are
awarded by removing 25% of their TTL (ie, their TTL at quest's end). to
complete a quest, no user can be penalized until the quest's end. quests
last a random time between 12 and 24 hours. if the quest is not completed,
ALL online users are penalized 2% of their time as punishment. users are
only chosen from the pool of online players (original idea from Nerje; quest
ideas from Tristan, brt)
- quests are read from file 'quests.txt' every time quest() is called. this
allows you to add or remove quests while the bot is still running. quests
are not picked in order, but chosen at random from the file
- fixed bug in PUSH, allowing to push into negative TTL
- db times changed to ctime format in lieu of scalar localtime() (now
sortable)
- added db fields for total time idled; total times penalized for privmsg,
nick change, part, kick, LOGOUT, quest, and quit; and time account created
- REGISTER no longer penalizes if you are already logged in and the command
fails
- fixed 'http:' checking to only look at message text, not entire string
- messages passed through privmsg() are split into 450-byte chunks and then
passed to their target
- bans put into place by the 'http:' method are now removed after 1 hour to
prevent filling the banlist. bans are stored in @bans, which will hold at
most 12 bans to prevent the bot from flooding on unban. after 12, bans are
still set, but not stored
- 'license' in header slightly changed
- battle results now include item sums and the random number rolled for each
player. format is [roll/sum]
- bot will try to regain his nickname every 30 mins if it is in use at
sign-on. added vars $primnick and $opts{'botghostcmd'}. $primnick is set
to $opts{'botnick'} (which may change) on load, and $opts{'botghostcmd'}
is a nickserv ghost command string
- the bot's nick ($opts{'botnick'} and $primnick) cannot be registered as
character names
- bot is now a fightable player. his item sum is random 250-650. (someone;
mail me if this was your idea). chances of fighting him are equal to
fighting any other player
- bot now daemonizes when starting (jwbozzy)
- fixed duration code to use the correct secs/day (drdink/inkblot)
- added a penalty to Team Battle. players will now receive or lose 20% of the
lowest team member's TTL (drdink)
- changed battling to award tie to challenger, not challengee. random number
is also, now, an integer, not a float
- every 3.5 hours, a level 45+, online player will battle; this will make it
easier for high-level users to level
- added function itemsum() to return item sum for supplied username
- battle results written to battles.txt are now timestamped (Juliet)
--------------------------------------------------------------------------------
v2.2.2 (schmolli): released 7/18/03
--------------------------------------------------------------------------------
* The changes in this version are based almost completely on a patch sent to
me by Ed Schmollinger, schmolli@IRC. Many thanks to him for his help! Here
are his changes:
- SECURITY: added subroutine mksalt to generate random salt for passwds
- CLEANUP: added subroutines chanmsg and privmsg to send messages to
bot's channel and to a specified user, respectively
- FEATURE: added command line argument processing and removed TEST_MODE
(TEST_MODE is no longer necessary.) Part of this includes moving most
of the variables into %opts.
- FIX: added check for number of existing players when printing top 3
- CLEANUP: changed "in:" and "out:" debug message to "<-" and "->"
- CLEANUP: indented concatenated lines
--------------------------------------------------------------------------------
v2.2.1: released 7/16/03
--------------------------------------------------------------------------------
- fixed a bug in item finding; if unique item was better than helm, not
better than its class, you would get the item (emad)
--------------------------------------------------------------------------------
v2.2
--------------------------------------------------------------------------------
- added 1/20000 chance of 'team battle' every 5 seconds. team battle is 3
players versus 3 other players. if the first three players win, their time
is lowered by 20% of the lowest of the three's TTL. if they lose, no time is
removed from any players. there is no chance for critical strike in a team
battle (Asterax)
- max level of Jotun's Fury Colossal Sword changed to 175
- fixed 'kick' bug; users that were kicked were not logged out
- kick added as a p250
- bot now only bans those non-logged in users that say 'http:' that've been in
the channel < 90 seconds
- bot won't ban for #G7-type URLs
- bot now shows nick of user when new account is registered
- forgot to close filehandle in loaddb(); fixed
- added a db backup every 6 hours
--------------------------------------------------------------------------------
v2.1.3
--------------------------------------------------------------------------------
- fixed bug where users changing their nick would not be candidates for
auto-login on a bot restart
- changed some messages to make them more friendly to female players (LapCat)
--------------------------------------------------------------------------------
v2.1.2
--------------------------------------------------------------------------------
- HoG can now carry or displace a player 5 - 75% toward the next level
- fixed CTCP version bug
- battling was changed from all users within 7 levels of you to all online
users
- added "unique" items, or a chance starting at level 25 to roll
higher-than-normal items
--------------------------------------------------------------------------------
v2.1.1
--------------------------------------------------------------------------------
- DIE, JUMP, RESTART, INFO, and PEVAL now send warnings to users that don't
have access to tell them so. they are still penalized
- bot will now penalize users without the proper access that try to use an
admin command
- add commands CHCLASS, CHUSER, and PUSH to adjust class names, usernames,
and next time to level, respectively
- HoG could occur for offline users; this is no longer the case
- bot now responds to CTCP version requests (drdink)
--------------------------------------------------------------------------------
v2.1
--------------------------------------------------------------------------------
- bot bans non-logged-in users that say 'http:'
- INFO did not check ha(); fixed
- bot will automagically log you back in if you were logged in before a bot
restart, and if you haven't changed your nick!user@host since then
- removed logging
- dropped functions relating to old database in favor of the new one
- changed level up report from seconds to duration()
- changed item/userinfo db's to one file; battles still in battles.txt
- changed challenge report from seconds to duration()
- changed penalty text to display duration() instead of seconds
- added critical strike, 1/35 chance upon winning battle to cause opponent to
lose time (dwyn)
- changed summon text for HoG (res0)
- changed access to base off of irpg username in lieu of host
- changed top player report to every 6 hours
- changed positive HoG text (res0)
- changed random HoG chance to 1/20000 every 5 seconds
--------------------------------------------------------------------------------
v2.0.3
--------------------------------------------------------------------------------
- dropped top players back to 3
- removed STATUS; TTL available through website.
- battle history added to website; added logging of battles to battles.txt
- peval did not next(); fixed.
- added HOG command, randomly chooses someone, then randomly raises/lowers
their TTL (20% raise, 80% lower). HOG is, of course, an abbreviation for
Hand of God
- added a 1/7500 random HoG into rpcheck()
--------------------------------------------------------------------------------
v2.0.2
--------------------------------------------------------------------------------
- STATUS would log you out; fixed.
- could STATUS if not online; fixed.
- added DEL command to remove accounts
- added ALERT command to make channel alerts
- changed admin HELP command text to display website
--------------------------------------------------------------------------------
v2.0.1
--------------------------------------------------------------------------------
- fixed self-battle bug
- changed chance to battle from 20% to 25% if level < 25, 100% if >= 25
- setup companion website
- updated HELP command to reflect website
- changed battle gain to (max(7,opplevel/4)/100)*your_next_ttl
- added battle loss of (max(7,opplevel/7)/100)*your_next_ttl
--------------------------------------------------------------------------------
v2.0
--------------------------------------------------------------------------------
- added item finding and battling
- added penalties for QUIT, PART, instead of resetting time to the beginning
of that level
--------------------------------------------------------------------------------
v1.0
--------------------------------------------------------------------------------
- initial version

62
bot.v3.1.2/README Normal file
View File

@@ -0,0 +1,62 @@
--------------------------------------------------------------------------------
First-time users:
--------------------------------------------------------------------------------
1. Using your favorite text editor, open the bot's source. Read the file header.
If you don't agree with the license, please delete the source and remove
each of your brain cells associated with it. Kthx.
2. Open the file .irpg.conf and edit the bot's options to suit you. You must
also move this file into the same directory where the bot resides.
3. Run it with: perl bot.filename.pl
4. If you have problems, try running it in debug mode:
perl bot.filename.pl --debug
If you cannot diagnose the problem, post to http://idlerpg.net/forum.php
5. Thanks for your interest in Idle RPG!
--------------------------------------------------------------------------------
IRPG 3.0 users looking to upgrade:
--------------------------------------------------------------------------------
1. Using your favorite text editor, open the bot's source. Read the file header.
If you don't agree with the license, please delete the source and remove
each of your brain cells associated with it. Kthx.
2. Open the file .irpg.conf and edit the bot's options to suit you. You must
also move this file into the same directory where the bot resides.
3. Replace your old bot source with the new one, ie, rm -f that old, buggy crap.
4. Run it with: perl bot.filename.pl
5. If you have problems, try running it in debug mode:
perl bot.filename.pl --debug
If you cannot diagnose the problem, post to http://idlerpg.net/forum.php
6. Thanks for your interest in Idle RPG!
--------------------------------------------------------------------------------
IRPG 2.4 users looking to upgrade:
--------------------------------------------------------------------------------
1. Using your favorite text editor, open the bot's source. Read the file header.
If you don't agree with the license, please delete the source and remove
each of your brain cells associated with it. Kthx.
2. Run the db conversion tool: perl irpgdbtool
3. Answer the questions to suit you.
4. Open the file .irpg.conf and edit the bot's options to suit you. You must
also move this file into the same directory where the bot resides.
5. Run it with: perl bot.filename.pl
6. If you have problems, try running it in debug mode:
perl bot.filename.pl --debug
If you cannot diagnose the problem, post to http://idlerpg.net/forum.php
7. Thanks for your interest in Idle RPG!
--------------------------------------------------------------------------------
Pre-2.4 users looking to upgrade:
--------------------------------------------------------------------------------
1. Using your favorite text editor, open the bot's source. Read the file header.
If you don't agree with the license, please delete the source and remove
each of your brain cells associated with it. Kthx.
2. I don't think the irpgdbtool will help you unless you're comfortable with
Perl, sorry. :/ If you are, though, you can pull the loaddb() sub from the
bot that you're currently using instead of using the loaddb() supplied in
irpgdbtool. You'll also need to add code to add in the other missing fields
that exist in v2.4.

2352
bot.v3.1.2/bot.v3.1.2.pl Normal file

File diff suppressed because it is too large Load Diff

71
bot.v3.1.2/events.txt Normal file
View File

@@ -0,0 +1,71 @@
C was bitten by drdink
C fell into a hole
C bit their tongue
C set themself on fire
C ate a poisonous fruit
C lost their mind
C died, temporarily..
C was caught in a terrible snowstorm
C EXPLODED, somewhat..
C got knifed in a dark alley
C saw an episode of Ally McBeal
C got turned INSIDE OUT, practically
C ate a very disagreeable fruit, getting a terrible case of heartburn
C met up with a mob hitman for not paying his bills
C has fallen ill with the black plague
C was struck by lightning
C was attacked by a rabid cow
C was attacked by a rabid wolverine
C was set on fire
C was decapitated, temporarily..
C was tipped by a cow
C was bucked from a horse
C was bitten by a m<><6D>se
C was sat on by a giant
C ate a plate of discounted, day-old sushi
C got harassed by peer
C got lost in the woods
C misplaced his map
C broke his compass
C lost his glasses
C walked face-first into a tree
G found a pair of Nikes
G caught a unicorn
G discovered a secret, underground passage
G was taught to run quickly by a secret tribe of pygmies that know how to, among other things, run quickly
G discovered caffeinated coffee
G grew an extra leg
G was visited by a very pretty nymph
G found kitten
G learned Perl
G found an exploit in the IRPG code
G tamed a wild horse
G found a one-time-use spell of quickness
G bought a faster computer
G bribed the local IRPG administrator
G stopped using dial-up
G invented the wheel
G gained a sixth sense
G got a kiss from drwiii
G had his clothes laundered by a passing fairy
G was rejuvenated by drinking from a magic stream
G was bitten by a radioactive spider
G hit it off with a drunk sorority chick named Jenny
G was accepted into Pi Beta Phi
Q2 225 415 280 460 lay waste to the Towers of Ankh-Allor, wherein lies the terrible sorceror Croocq
Q1 locate the centuries-lost tomes of the grim prophet Haplashak Mhadhu
Q2 400 475 480 380 explore and chart the dark lands of T'rnalvph
Q1 locate the ancient writings of Ahmo, prophet of the blind god Io, namely his last and hidden work, Time as Deity, thought to answer all of mankind's greater wonders
Q2 290 65 325 270 slay the great and horrible troll, Dokt'r Wiii
Q2 480 415 325 270 return the stolen relics of Iao-Sabao to the city of Velvragh, quieting the religious riot that has sprung up from their loss
Q2 70 315 325 270 guard the secret passage to Bharash until the full moon has passed, and the evil returned to its resting place
Q2 50 350 325 270 destroy the bandits terrorizing the roads passing through the Great Shahlil mountains
Q1 locate and destroy the immensely powerful Eyeless Amulet of the evil sorceress, Ankh B'loht
Q2 167 458 325 270 rescue the beautiful princess Juliet from the grasp of the beast Grabthul
Q1 locate the herbs and brew the elixir to rid the realm of the Normonic Plague
Q2 160 480 160 380 hunt down the over-abundance of mountain wolves that are slaying the regions' cows
Q2 35 40 325 270 assassinate the general, Ronald Ashur, of the invading army of Denmark
Q2 235 125 430 60 setup a trade route through the mountains to the neighboring land of Qwok and arrange correspondence with their leader, Cuincey-Love Vikk'l
Q2 155 155 325 270 live among and learn the ancient magick of the tribe of pygmie people, the Jow Botzi
Q2 70 125 170 100 kill the resurrected Jow Botzian zombies produced by a young wizard's wayward spell
Q1 worship the sacred Cow until such time as she is satiated

469
bot.v3.1.2/irpgdbtool Normal file
View File

@@ -0,0 +1,469 @@
# IRPG db conversion tool; converts db version 2.4 -> 3.0
# Jon Honeycutt, jotun@idlerpg.net, http://idlerpg.net
# Free for all use, public and private, with retention of copyright notice.
use strict;
use IO::Socket;
my %rps = ();
my $temp;
$|=1;
print "\nIRPG db conversion tool; version 2.4 -> 3.0\n\n";
do {
print "Read from file [irpg.db]: ";
chomp($temp=<STDIN>);
$temp ||= "irpg.db";
if (! -e $temp) { print "Error: No such file\n"; }
} until (-e $temp);
loaddb($temp);
print "Loaded ".scalar(keys(%rps))." accounts from $temp.\n";
do {
print "\nBackup old irpg.db file? [yes]: ";
chomp($temp=<STDIN>);
$temp||="yes";
$temp=lc($temp);
} until ($temp eq "yes" || $temp eq "no");
if ($temp eq "yes") {
do {
print "\nBackup filename [irpg.db.old]: ";
chomp($temp=<STDIN>);
$temp||="irpg.db.old";
} until (defined($temp));
open(RPS,">$temp") or die("Cannot write $temp: $!");
print RPS "# username\tpass\tlevel\tclass\tnext\tnick\tuserhost\tonline\t".
"idled\tpen_mesg\tpen_nick\tpen_part\tpen_kick\tpen_quit\t".
"pen_quest\tpen_logout\tcreated\tlast login\tamulet\tcharm\t".
"helm\tboots\tgloves\tring\tleggings\tshield\ttunic\tweapon\n";
for my $k (keys %rps) {
print RPS join("\t",
$k,
$rps{$k}{pass},
$rps{$k}{level},
$rps{$k}{class},
$rps{$k}{next},
$rps{$k}{nick}||"",
$rps{$k}{userhost}||"",
$rps{$k}{online}||0,
$rps{$k}{idled}||0,
$rps{$k}{pen_mesg}||0,
$rps{$k}{pen_nick}||0,
$rps{$k}{pen_part}||0,
$rps{$k}{pen_kick}||0,
$rps{$k}{pen_quit}||0,
$rps{$k}{pen_quest}||0,
$rps{$k}{pen_logout}||0,
$rps{$k}{created},
$rps{$k}{lastlogin},
$rps{$k}{item}{amulet}||0,
$rps{$k}{item}{charm}||0,
$rps{$k}{item}{helm}||0,
$rps{$k}{item}{"pair of boots"}||0,
$rps{$k}{item}{"pair of gloves"}||0,
$rps{$k}{item}{ring}||0,
$rps{$k}{item}{"set of leggings"}||0,
$rps{$k}{item}{shield}||0,
$rps{$k}{item}{tunic}||0,
$rps{$k}{item}{weapon}||0)."\n";
}
close(RPS);
print "Wrote $temp.\n";
}
do {
print "\nReset all user levels to 0, all times to level to 0, all items ".
"to 0, all penalties to 0, all online flags to 0, all idled times ".
"to 0, all creation dates and last login times to today (i.e., ".
"reset game)? [no]: ";
chomp($temp=<STDIN>);
$temp||="no";
$temp=lc($temp);
} until ($temp eq "yes" || $temp eq "no");
if ($temp eq "yes") {
for my $k (keys(%rps)) {
$rps{$k}{next}=0;
$rps{$k}{level}=0;
$rps{$k}{online}=0;
$rps{$k}{idled}=0;
$rps{$k}{item}{amulet}=0;
$rps{$k}{item}{charm}=0;
$rps{$k}{item}{helm}=0;
$rps{$k}{item}{"pair of boots"}=0;
$rps{$k}{item}{"pair of gloves"}=0;
$rps{$k}{item}{ring}=0;
$rps{$k}{item}{"set of leggings"}=0;
$rps{$k}{item}{shield}=0;
$rps{$k}{item}{tunic}=0;
$rps{$k}{item}{weapon}=0;
$rps{$k}{pen_mesg}=0;
$rps{$k}{pen_nick}=0;
$rps{$k}{pen_part}=0;
$rps{$k}{pen_kick}=0;
$rps{$k}{pen_quit}=0;
$rps{$k}{pen_quest}=0;
$rps{$k}{pen_logout}=0;
$rps{$k}{created}=time();
$rps{$k}{lastlogin}=time();
}
print "Game reset.\n";
}
do {
print "\nStrip all control codes from character names and classes? [no]: ";
chomp($temp=<STDIN>);
$temp ||="no";
$temp=lc($temp);
} until ($temp eq "yes" || $temp eq "no");
if ($temp eq "yes") {
my(@usernames,@classes);
for my $k (keys(%rps)) {
if ($k =~ /[[:cntrl:]]/) {
my $newusername = $k;
$newusername =~ s/[[:cntrl:]]//g;
if (exists($rps{$newusername}) || !defined($newusername) ||
!length($newusername)) {
print "\nError: While trying to strip control codes from $k, ".
"found stripped version ($newusername) already exists ".
"in database or is undefined. Skipping this user, so ".
"sorry.\n";
}
else {
$rps{$newusername}=delete($rps{$k});
push(@usernames,"$k is now: $newusername");
$k = $newusername;
}
}
if ($rps{$k}{class} =~ /[[:cntrl:]]/) {
$rps{$k}{class} =~ s/[[:cntrl:]]//g;
push(@classes,"$k is now: $rps{$k}{class}");
}
}
if (@usernames) {
print "\nUsernames changed (would be good to alert these users):\n";
print "User $_\n" for @usernames;
print "\n";
}
if (@classes) {
print "\nClass names changed (might be good to alert these users):\n";
print "User $_\n" for @classes;
print "\n";
}
}
do {
print "\nStrip all non-printable characters from character names and ".
"classes? [no]: ";
chomp($temp=<STDIN>);
$temp ||="no";
$temp=lc($temp);
} until ($temp eq "yes" || $temp eq "no");
if ($temp eq "yes") {
my(@usernames,@classes);
for my $k (keys(%rps)) {
if ($k =~ /[[:^print:]]/) {
my $newusername = $k;
$newusername =~ s/[[:^print:]]//g;
if (exists($rps{$newusername}) || !defined($newusername) ||
!length($newusername)) {
print "\nError: While trying to strip non-printable chars ".
"from $k, found stripped version ($newusername) already ".
"exists in database or is undefined. Skipping this ".
"user, so sorry.\n";
}
else {
$rps{$newusername}=delete($rps{$k});
push(@usernames,"$k is now: $newusername");
$k = $newusername;
}
}
if ($rps{$k}{class} =~ /[[:^print:]]/) {
$rps{$k}{class} =~ s/[[:^print:]]//g;
push(@classes,"$k\'s class is now: $rps{$k}{class}");
}
}
if (@usernames) {
print "\nUsernames changed (would be good to alert these users):\n";
print "User $_\n" for @usernames;
print "\n";
}
if (@classes) {
print "\nClass names changed (might be good to alert these users):\n";
print "User $_\n" for @classes;
print "\n";
}
}
do {
print "\nVersion 3.0 supports 'named items,' or a method of marking ".
"unique items as being unique. Attempt to name existing items that ".
"are known uniques? [yes]: ";
chomp($temp=<STDIN>);
$temp ||="yes";
$temp=lc($temp);
} until ($temp eq "yes" || $temp eq "no");
if ($temp eq "yes") {
for my $k (keys(%rps)) {
for my $item (keys(%{$rps{$k}{item}})) {
if ($rps{$k}{item}{$item} > int(1.5*$rps{$k}{level})) {
if ($item eq "helm") {
print "$k\'s $item named as Mattt's Omniscience.\n";
$rps{$k}{item}{$item} .= "a";
}
elsif ($item eq "tunic") {
print "$k\'s $item named as Res0's Protectorate.\n";
$rps{$k}{item}{$item} .= "b";
}
elsif ($item eq "amulet") {
print "$k\'s $item named as Dwyn's Storm.\n";
$rps{$k}{item}{$item} .= "c";
}
elsif ($item eq "weapon" && $rps{$k}{item}{$item} < 175) {
print "$k\'s $item named as Jotun's Fury.\n";
$rps{$k}{item}{$item} .= "d";
}
elsif ($item eq "weapon" && $rps{$k}{item}{$item} > 175 &&
$rps{$k}{item}{$item} < 201) {
print "$k\'s $item named as Drdink's Cane of Blind Rage.\n";
$rps{$k}{item}{$item} .= "e";
}
else {
print "$k has unknown unique of level ".
"$rps{$k}{item}{$item}.\n";
}
}
}
}
}
do {
print "\nThere exist new items in version 3.0 that some of your clients ".
"may already have had the chance to find. I.E., there is a new item ".
"with a required level of 48. Simulate an item find for all users ".
"above 48 for this and other new items to make the game fair for ".
"older users? [yes]: ";
chomp($temp=<STDIN>);
$temp ||="yes";
$temp=lc($temp);
} until ($temp eq "yes" || $temp eq "no");
if ($temp eq "yes") {
for my $k (keys(%rps)) {
if ($rps{$k}{level} >= 48) {
for (48..$rps{$k}{level}) {
# approximately equal to normal item find, i believe
if (rand(100) < 2.25) {
my $ulevel = 250+int(rand(51));
if ($ulevel > int($rps{$k}{item}{"pair of boots"})) {
print "$k found level $ulevel Mrquick's Magical Boots ".
"of Swiftness.\n";
$rps{$k}{item}{"pair of boots"} = $ulevel."f";
}
}
}
}
if ($rps{$k}{level} >= 52) {
for (52..$rps{$k}{level}) {
# approximately equal to normal item find, i believe
if (rand(100) < 2.15) {
my $ulevel = 300+int(rand(51));
if ($ulevel > int($rps{$k}{item}{weapon})) {
print "$k found level $ulevel Jeff's Cluehammer of ".
"Doom.\n";
$rps{$k}{item}{weapon} = $ulevel."g";
}
}
}
}
if ($rps{$k}{level} >= 25) {
for (25..$rps{$k}{level}) {
# approximately equal to normal item find, i believe
if (rand(100) < 2.43) {
my $ulevel = 50+int(rand(25));
if ($ulevel > int($rps{$k}{item}{ring})) {
print "$k found level $ulevel Juliet's Glorious Ring ".
"of Sparkliness.\n";
$rps{$k}{item}{ring} = $ulevel."h";
}
}
}
}
}
}
for my $k (keys(%rps)) {
$rps{$k}{x} = int(rand(500));
$rps{$k}{y} = int(rand(500));
$rps{$k}{isadmin}=0;
$rps{$k}{alignment}="n";
}
print "\nUsernames that you would like to have admin status (separate with ".
"commas, use proper CaSe): ";
chomp($temp=<STDIN>);
$temp =~ s/\s//g;
for my $k (split(/,/,$temp)) {
if (!exists($rps{$k})) {
print "\nError: Account name '$k' does not exist. Remember that ".
"account names are case sensitive. Skipping this username. Edit ".
"the database manually, or use the MKADMIN command after the ".
"bot connects to add this user.\n\n";
}
else {
print "$k is now admin.\n";
$rps{$k}{isadmin}=1;
}
}
print "\nYou can add more admins later with the MKADMIN command.\n";
do {
print "\nWrite to new db file [irpg.db]: ";
chomp($temp=<STDIN>);
$temp ||= "irpg.db";
} until (defined($temp));
open(RPS,">$temp") or die "Cannot open $temp: $!";
print RPS join("\t","# username",
"pass",
"is admin",
"level",
"class",
"next ttl",
"nick",
"userhost",
"online",
"idled",
"x pos",
"y pos",
"pen_mesg",
"pen_nick",
"pen_part",
"pen_kick",
"pen_quit",
"pen_quest",
"pen_logout",
"created",
"last login",
"amulet",
"charm",
"helm",
"boots",
"gloves",
"ring",
"leggings",
"shield",
"tunic",
"weapon",
"alignment")."\n";
for my $k (keys(%rps)) {
print RPS join("\t",
$k,
$rps{$k}{pass},
$rps{$k}{isadmin},
$rps{$k}{level},
$rps{$k}{class},
$rps{$k}{next},
$rps{$k}{nick},
$rps{$k}{userhost},
$rps{$k}{online},
$rps{$k}{idled},
$rps{$k}{x},
$rps{$k}{y},
$rps{$k}{pen_mesg},
$rps{$k}{pen_nick},
$rps{$k}{pen_part},
$rps{$k}{pen_kick},
$rps{$k}{pen_quit},
$rps{$k}{pen_quest},
$rps{$k}{pen_logout},
$rps{$k}{created},
$rps{$k}{lastlogin},
$rps{$k}{item}{amulet},
$rps{$k}{item}{charm},
$rps{$k}{item}{helm},
$rps{$k}{item}{"pair of boots"},
$rps{$k}{item}{"pair of gloves"},
$rps{$k}{item}{ring},
$rps{$k}{item}{"set of leggings"},
$rps{$k}{item}{shield},
$rps{$k}{item}{tunic},
$rps{$k}{item}{weapon},
$rps{$k}{alignment})."\n";
}
close(RPS);
do {
print "\nDone writing $temp! Thanks for your interest in the Idle RPG. May ".
"I send an (anonymous) user count to idlerpg.net? jotun is ".
"interested in knowing how many people play his game :^) [yes]: ";
chomp($temp=<STDIN>);
$temp||="yes";
$temp=lc($temp);
} until ($temp eq "yes" || $temp eq "no");
if ($temp eq "yes") {
print "Sending...\n";
my $sock = IO::Socket::INET->new(PeerAddr=>"jotun.ultrazone.org:80");
if ($sock) {
print $sock "GET /g7/count.php?converted=".scalar(keys(%rps)).
" HTTP/1.1\r\n".
"Host: jotun.ultrazone.org:80\r\n\r\n";
1 while <$sock>;
}
print "\nDone! Thanks a million! Enjoy Idle RPG. :^)\n";
}
else {
print "\nI'm setting your chance of evil HoG to 100%, then. Just kidding. ".
"Thanks anyway.\n";
}
sub loaddb { # load the players database
open(RPS,shift(@_)) or die("loaddb() failed: $!");
while (my $l=<RPS>) {
chomp $l;
next if $l =~ /^#/; # skip comments
my @i = split("\t",$l);
print Dumper @i if @i != 28;
die("Anomaly in loaddb(); line $. of database has wrong fields (".
scalar(@i).")") if @i != 28;
($rps{$i[0]}{pass},
$rps{$i[0]}{level},
$rps{$i[0]}{class},
$rps{$i[0]}{next},
$rps{$i[0]}{nick},
$rps{$i[0]}{userhost},
$rps{$i[0]}{online},
$rps{$i[0]}{idled},
$rps{$i[0]}{pen_mesg},
$rps{$i[0]}{pen_nick},
$rps{$i[0]}{pen_part},
$rps{$i[0]}{pen_kick},
$rps{$i[0]}{pen_quit},
$rps{$i[0]}{pen_quest},
$rps{$i[0]}{pen_logout},
$rps{$i[0]}{created},
$rps{$i[0]}{lastlogin},
$rps{$i[0]}{item}{amulet},
$rps{$i[0]}{item}{charm},
$rps{$i[0]}{item}{helm},
$rps{$i[0]}{item}{"pair of boots"},
$rps{$i[0]}{item}{"pair of gloves"},
$rps{$i[0]}{item}{ring},
$rps{$i[0]}{item}{"set of leggings"},
$rps{$i[0]}{item}{shield},
$rps{$i[0]}{item}{tunic},
$rps{$i[0]}{item}{weapon}) = (@i[1..$#i]);
}
close RPS;
}

0
bot.v3.1.2/modifiers.txt Normal file
View File

0
bot.v3.1.2/questinfo.txt Normal file
View File

108
irpg/ChangeLog Normal file
View File

@@ -0,0 +1,108 @@
This is the ChangeLog for the Idle RPG Website Code. I'm not as religious about
making sure my updates make it here as I am about changes to the IRPG code
making it into that ChangeLog, so there may be changes between versions that you
don't see listed here.
Also, please note that any use of "incowrect" or other cow-related "typos" are
NOT typos. I like cattle. A lot. Please stop fixing them :^)
2004-07-17 Jon Honeycutt <jotun@idlerpg.net>
* huge modification of the entire source by the original coder, res0
<bk@slashnet.org>. res0 has really helped this project through his many
contributions; it wouldn't be where it is today without him. thanks, res0!
* New site layout (valid XHTML 1.1 strict) using CSS
* Cleaned up PHP
* User maps do not display unless visitor clicks 'display' link
* changed fgets() calls to add the optional second parameter (for old PHPs)
* removed incorrect header() in makequestmap() (mikegrb)
* checked to make sure key $_SESSION['time'] was set before attempting to
reference it (HarK0nNeN)
* db.php's table tag now specifies the number of rows and columns to make
drawing faster in browsers that pay attention to it (res0)
* header("Location: ") directives now give full URIs
* made better use of htmlentities() and urlencode()s as relates to display
of usernames and classes
* users on quest and world maps are now clickable, leading to their player
info page (John Nielsen)
2004-05-31 Jon Honeycutt <jotun@idlerpg.net>
* changed players.php to show offline users as gray, this style is in
header.php, patch from Chewie <chewie@f2o.org>
* changed map-drawing PHP scripts to draw a transparent image which is then
overlayed (using CSS) over the static newmap.png image. changed the map
drawing frequency to 1/user/20s as I think this greatly decreases CPU
usage. changed the maperror.png to something more appropriate. $mapx
and $mapy in config.php describe the dimensions of your map file (Rick)
* fixed quest.php to show proper coordinates; another evil c/p error (Rick)
2004-05-23 Jon Honeycutt <jotun@idlerpg.net>
* changed most everything to make sense with the new database
* edited dump.php to display data in the same format, despite the new
database format.
* added an xml.php page that takes a 'player' argument and displays
information on that user in xml 1.0 format. should allow a better API
as far as compatibility with newer dbs goes
* changed playerview.php to use fgets() to read from modifiers.txt.
hopefully this is much faster
* edited playerview.php to show map and XML data link
* changed the counter in footer.php to strip the leading path information
from $_SERVER['PHP_SELF'] before using it to identify the page
* removed some unused $i variable from players.php
* created quest.php which shows active quest info
* created makequestmap.php which draws a quest map if quest type is 2,
redirects otherwise
* created worldmap.php which shows the active state of the irpg world
* created makeworldmap.php which draws the world map
* created makemap.php which takes a 'player' argument and draws them on the
map
* commonfunctions.php now has functions to sort by isadmin flag and player
alignment
* index.php updated with information on the new game features
* changed titles on several pages to use $irpg_chan instead of hard-coded
#G7
* updated header.php to link to new pages and idlerpg.net forum
* changed 'time modifiers' to 'character modifiers' as item modifiers are
now stored, also
2004-05-23 Alexander Hirzel <chewie@f2o.org>
* submitted a series of patches to correct, among other things, the horrible
use of <td> where <th> was more appropriate
2004-04-22 Jon Honeycutt <jotun@idlerpg.net>
* if $_GET['alltime'] wasn't set, < and > in time modifiers were not
translated to &lt; and &gt; (thanks DinTx)
* attempted to fix playerview.php from showing others' stats, traded
stristr() for strstr() matching either "^name ", " name ", or "^name's "
2004-04-23 Jonathan Attwell <caffeen@caffeen.org>
* created README, detailing how users are to install and what to edit.
* created config.php, which holds all the setup variables.
* cleaned up some of the php coding.
2004-04-15 Jon Honeycutt <jotun@ultrazone.org>
* we now stripslashes() on $_GET['player'] for players.php,
playerview.php, dump.php (thanks Diab)
2004-04-05 Jon Honeycutt <jotun@ultrazone.org>
* removed some of parallax's tabs :^)
* edited players.php to forward requests for specific players to the proper
playerview.php
* changed links in sitesource.php to be fully-qualified
* removed preg_grep in playerview.php, which insecurely used tainted
data. switched to stristr. (thanks mike@ethernal.org)
* stripped < and > from modifiers.txt output (thanks mike@ethernal.org)
* changed link to idlerpg-adv.txt in players.php to be fully-qualified.
(thanks daxxar)
* may've made other changes, not sure.
2004-02-15 Jon Honeycutt <jotun@ultrazone.org>
* edited source.php to provide fully-qualified URLs to source files;
easier for users to follow license.
* playerview.php's 'View all Time Modifiers' link now displays the
number of time modifiers.
* contact.php now sends a From: field in its headers parameter.
2004-01-31 Titus Barik <titus@barik.net>
* created ChangeLog, following Debian ChangeLog format.
* modified header.php to be location independent via $BASE_URL var.
* players.php and playerview.php are now separate files.

42
irpg/README Normal file
View File

@@ -0,0 +1,42 @@
------------------------------------------
IRPG Website Code README v1.1 (2004-06-27)
------------------------------------------
-----------
Notes
-----------
Homepage: http://idlerpg.net
License : Public Domain
-----------
Versions
-----------
Site: v0.5 [current/changes courtesy of res0], Released July 17th, 2004.
Bot : v3.1.2 [current], Released June 6th, 2004.
------------
Installation
------------
1. Make sure you have the bot functional and running.
2. Copy all the files here to your public_html or some folder.
3. Edit config.php with your favorite editor.
4. chmod 644 * && chmod 666 hits.db
5. If you change the default settings in the IRPG bot (for example, if you turn
off the option to write quest info to file, you'll have to manually edit
some scripts to take this into account. If you disable the INFO command,
you might want to remove it from the index.php page.
6. Some code in this package requires that your system have GD 2.0+ (or have it
enabled in your php.ini, on Win32). If you don't want this functionality to
be available, edit the script playerview.php to remove the use of the map
and header.php to remove the links to the world map and the quest info page.
You can also delete the worldmap.php, makeworldmap.php, makemap.php,
quest.php, and makequestmap.php scripts.
7. Edit the website ANY WAY you see fit. You don't have to keep all of the links
to me, I just thought they might be useful or interesting to users :^)
8. The best way to receive support for these scripts is to post to the Help
section of the forum, http://idlerpg.net/forum.php, not via e-mail or IRC.
If you notice a bug, however, you may use any method to contact me.
Thanks :^)

65
irpg/admincomms.txt Normal file
View File

@@ -0,0 +1,65 @@
This is not the full list of commands for the Idle RPG bot, but only the list
of admin commands. For more information on the Idle RPG bot, visit
http://idlerpg.net/
INFO, retrieve some fairly useless stats about the bot.
DIE, kills the bot.
HOG, summon the Hand of God spell. See the main help file.
RESTART, restarts the bot.
CHPASS <char name> <new password>, change a character's pass in the IRPG.
CHCLASS <char name> <new class name>, change a character's class in the IRPG.
CHUSER <char name> <new char name>, change a character's username in the IRPG.
Please only use in very special circumstances; otherwise, have them form
a new player and DEL the old one. This should not let you overwrite an
existing account, but is untested.
PUSH <char name> <seconds>, push a player toward his goal by subtracting time
from his next time to level. Please use this only if bot has mistakenly
penalized someone. You could also use this to punish a user by setting
the number of seconds to a negative number. Don't do that.
DEL <char name>, remove a user's account.
JUMP <server[:port]>, move the bot to another server.
SILENT <mode>, switch bot between 4 modes of silence.
- mode 0, bot sends all privmsgs.
- mode 1, only chanmsg() is disabled.
- mode 2, only privmsg()/notice() to non-channels is disabled.
- mode 3, privmsgs/notices to users and channels are disabled.
BACKUP, tell bot to copy $opts{'dbfile'} to .dbbackup/$opts{'dbfile'}TIMESTAMP
RELOADDB, force bot to reload player database file, rewriting all memory.
RELOADDB can only be used while in pause mode.
PAUSE, toggle pause mode.
PEVAL <code>, execute arbitrary argument as Perl code. Queues output > 3 lines
or >1k of text. Some useful PEVAL commands:
- Delete all accounts not logged in in 4 weeks (See also: DELOLD):
/msg bot PEVAL delete $rps{$_} for grep { time()-$rps{$_}{lastlogin} > 3600*24*7*4 && !$rps{$_}{online} } keys %rps;
- Remove one hour from everyone's clocks:
/msg bot PEVAL $rps{$_}{next} -= 3600 for keys %rps;
- List all online users, separated by commas:
/msg bot PEVAL join(', ',grep { $rps{$_}{online} } keys %rps);
- View contents of a file on remote host:
/msg bot peval `cat file`
- Turn on debug mode:
/msg bot peval $opts{debug}=1;
- Force write-out of database:
/msg bot peval writedb();
DELOLD <days>, remove all non-logged-in accounts inactive in the last <days>
days.
CLEARQ, clear the outgoing message queue. Useful to use if someone floods the
bot with a lot of text that it plans to respond to.
MKADMIN <username>, set the isadmin flag for a given username.

94
irpg/commonfunctions.php Normal file
View File

@@ -0,0 +1,94 @@
<?php
function duration($s) {
$s = abs(intval($s));
if ($s == 0) return "None";
return sprintf("%d day%s, %02d:%02d:%02d",
$s/86400,intval($s/86400)==1?"":"s",
($s%86400)/3600,($s%3600)/60,$s%60);
}
function cmp_level_asc($a,$b) { return cmp_level_desc($b,$a); }
function cmp_level_desc($a,$b) {
list(,,,$level1,,$time1)=explode("\t",trim($a));
list(,,,$level2,,$time2)=explode("\t",trim($b));
if ($level1 == $level2) return ($time1 <= $time2) ? -1 : 1;
return ($level1 > $level2) ? -1 : 1;
}
function cmp_alignment_asc($a,$b) { return cmp_alignment_desc($b,$a); }
function cmp_alignment_desc($a,$b) {
list(,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,$a1)=explode("\t",trim($a));
list(,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,$a2)=explode("\t",trim($b));
if ($a1 == "g" || $a2 == "e") return -1;
if ($a1 == "e" || $a2 == "g") return 1;
return 0;
}
function cmp_isadmin_asc($a,$b) { return cmp_isadmin_desc($b,$a); }
function cmp_isadmin_desc($a,$b) {
list(,,$o1)=explode("\t",trim($a));
list(,,$o2)=explode("\t",trim($b));
return ($o1 > $o2) ? -1 : 1;
}
function cmp_ttl_asc($a,$b) { return cmp_ttl_desc($b,$a); }
function cmp_ttl_desc($a,$b) {
list(,,,,,$time1)=explode("\t",trim($a));
list(,,,,,$time2)=explode("\t",trim($b));
return ($time2 < $time1) ? -1 : 1;
}
function cmp_user_asc($a,$b) { return cmp_user_desc($b,$a); }
function cmp_user_desc($a,$b) {
list($u1)=explode("\t",trim($a));
list($u2)=explode("\t",trim($b));
return (strtolower($u1) > strtolower($u2)) ? -1 : 1;
}
function cmp_online_asc($a,$b) { return cmp_online_desc($b,$a); }
function cmp_online_desc($a,$b) {
list(,,,,,,,,$o1)=explode("\t",trim($a));
list(,,,,,,,,$o2)=explode("\t",trim($b));
return ($o1 > $o2) ? -1 : 1;
}
function cmp_idled_asc($a,$b) { return cmp_idled_desc($b,$a); }
function cmp_idled_desc($a,$b) {
list(,,,,,,,,,$i1)=explode("\t",trim($a));
list(,,,,,,,,,$i2)=explode("\t",trim($b));
return ($i1 > $i2) ? -1 : 1;
}
function cmp_created_asc($a,$b) { return cmp_created_desc($b,$a); }
function cmp_created_desc($a,$b) {
list(,,,,,,,,,,,,,,,,,,,$i1)=explode("\t",trim($a));
list(,,,,,,,,,,,,,,,,,,,$i2)=explode("\t",trim($b));
return ($i1 > $i2) ? -1 : 1;
}
function cmp_lastlogin_asc($a,$b) { return cmp_lastlogin_desc($b,$a); }
function cmp_lastlogin_desc($a,$b) {
list(,,,,,,,,,,,,,,,,,,,,$i1)=explode("\t",trim($a));
list(,,,,,,,,,,,,,,,,,,,,$i2)=explode("\t",trim($b));
return ($i1 > $i2) ? -1 : 1;
}
function cmp_uhost_asc($a,$b) { return cmp_uhost_desc($b,$a); }
function cmp_uhost_desc($a,$b) {
list(,,,,,,,$u1)=explode("\t",trim($a));
list(,,,,,,,$u2)=explode("\t",trim($b));
return (strtolower($u1) > strtolower($u2)) ? -1 : 1;
}
function cmp_pen_asc($a,$b) { return cmp_pen_desc($b,$a); }
function cmp_pen_desc($a,$b) {
list(,,,,,,,,,,,,$p1[0],$p1[1],$p1[2],$p1[3],$p1[4],$p1[5],
$p1[6])=explode("\t",trim($a));
list(,,,,,,,,,,,,$p2[0],$p2[1],$p2[2],$p2[3],$p2[4],$p2[5],
$p2[6])=explode("\t",trim($b));
$s1 = $s2 = 0;
foreach ($p1 as $pen) $s1 += $pen;
foreach ($p2 as $pen) $s2 += $pen;
return ($s1 > $s2) ? -1 : 1;
}
function cmp_sum_asc($a,$b) { return cmp_sum_desc($b,$a); }
function cmp_sum_desc($a,$b) {
list(,,,,,,,,,,,,,,,,,,,,,$i1[0],$i1[1],$i1[2],$i1[3],$i1[4],$i1[5],
$i1[6],$i1[7],$i1[8],$i1[9])=explode("\t",trim($a));
list(,,,,,,,,,,,,,,,,,,,,,$i2[0],$i2[1],$i2[2],$i2[3],$i2[4],$i2[5],
$i2[6],$i2[7],$i2[8],$i2[9])=explode("\t",trim($b));
$s1 = $s2 = 0;
foreach ($i1 as $item) { $s1 += $item; }
foreach ($i2 as $item) $s2 += $item;
return ($s1 > $s2) ? -1 : 1;
}
?>

39
irpg/config.php Normal file
View File

@@ -0,0 +1,39 @@
<?php
$admin_email="you@host.com";
$admin_nick="HiASL";
// nickname of your bot
$irpg_bot="bot";
// your game's server
$irpg_network="irc.mynet.org";
// your game's channel
$irpg_chan="#G7";
// full or relative pathname to the DBs:
// character database
$irpg_db="/home/jotun/irpg.db";
// time modifiers file
$irpg_mod="/home/jotun/modifiers.txt";
// active quest info file
$irpg_qfile="/home/jotun/questinfo.txt";
// image to use for the top logo
$irpg_logo="idlerpg.png";
// directory in which your site is located from the root directory. my site
// is http://jotun.ultrazone.org/g7/, so it's "/g7/"
$BASEURL="/g7/";
// width-wise dimension of your map file
$mapx = 500;
// length-wise dimension of your map file
$mapy = 500;
?>

47
irpg/contact.php Normal file
View File

@@ -0,0 +1,47 @@
<?php
include("config.php");
$irpg_page_title = "Contact";
include("header.php");
echo "<h1>Contact</h1>";
if ($_POST['from'] && $_POST['text']) {
mail($admin_email,"IRPG: ".$_POST['from'],
"Name: ".$_POST['name']."\nE-mail: ".$_POST['from']."\n\n".
$_POST['text'],"From: ".$_POST['from']."\r\n");
echo(' <blockquote>Thanks for your submission.</blockquote>');
}
else {
echo('
<form method="post" action="contact.php">
<table border="0">
<tr>
<th align="left"><label for="from">Your e-mail address</label>:</th>
<td align="right">
<input type="text" size="20" maxlength="50" name="from" id="from" />
</td>
</tr>
<tr>
<th align="left"><label for="name">Your name</label>:</th>
<td align="right">
<input type="text" size="20" maxlength="50" name="name" id="name" />
</td>
</tr>
<tr>
<td colspan="2">
<textarea name="text" rows="6" cols="44"></textarea><br />
</td>
</tr>
<tr>
<td colspan="2" align="right">
<input type="submit" value="Send" />
</td>
</tr>
</table>
</form>
');
}
include("footer.php");
?>

257
irpg/db.php Normal file
View File

@@ -0,0 +1,257 @@
<?php
include("config.php");
$irpg_page_title = "DB-style Player Listing";
include("header.php");
include("commonfunctions.php");
$file = file($irpg_db);
unset($file[0]);
if (!$_GET['sort'] ||
(($_GET['sort'] != "cmp_level_asc") &&
($_GET['sort'] != "cmp_level_desc") &&
($_GET['sort'] != "cmp_isadmin_asc") &&
($_GET['sort'] != "cmp_isadmin_desc") &&
($_GET['sort'] != "cmp_alignment_asc") &&
($_GET['sort'] != "cmp_alignment_desc") &&
($_GET['sort'] != "cmp_ttl_asc") &&
($_GET['sort'] != "cmp_ttl_desc") &&
($_GET['sort'] != "cmp_pen_asc") &&
($_GET['sort'] != "cmp_pen_desc") &&
($_GET['sort'] != "cmp_lastlogin_asc") &&
($_GET['sort'] != "cmp_lastlogin_desc") &&
($_GET['sort'] != "cmp_created_asc") &&
($_GET['sort'] != "cmp_created_desc") &&
($_GET['sort'] != "cmp_idled_asc") &&
($_GET['sort'] != "cmp_idled_desc") &&
($_GET['sort'] != "cmp_user_asc") &&
($_GET['sort'] != "cmp_user_desc") &&
($_GET['sort'] != "cmp_online_asc") &&
($_GET['sort'] != "cmp_online_desc") &&
($_GET['sort'] != "cmp_uhost_asc") &&
($_GET['sort'] != "cmp_uhost_desc") &&
($_GET['sort'] != "cmp_sum_asc") &&
($_GET['sort'] != "cmp_sum_desc"))) $_GET['sort'] = "cmp_level_desc";
usort($file,$_GET['sort']);
?>
<table border=1 cellpadding=2 cellspacing=2 cols="32" rows="<?php print count($file); ?>">
<tr>
<th NOWRAP>
User
(<a href="db.php?sort=cmp_user_asc">
<img src="up.png" border="0">
</a>
/
<a href="db.php?sort=cmp_user_desc">
<img src="down.png" border="0">
</a>)
</th>
<th NOWRAP>
Level
(<a href="db.php?sort=cmp_level_asc">
<img src="up.png" border="0">
</a>
/
<a href="db.php?sort=cmp_level_desc">
<img src="down.png" border="0">
</a>)
</th>
<th NOWRAP>
Admin
(<a href="db.php?sort=cmp_isadmin_asc">
<img src="up.png" border="0">
</a>
/
<a href="db.php?sort=cmp_isadmin_desc">
<img src="down.png" border="0">
</a>)
</th>
<th NOWRAP>Class</th>
<th NOWRAP>
TTL
(<a href="db.php?sort=cmp_ttl_asc">
<img src="up.png" border="0">
</a>
/
<a href="db.php?sort=cmp_ttl_desc">
<img src="down.png" border="0">
</a>)
</th>
<th NOWRAP>
Nick!User@Host
(<a href="db.php?sort=cmp_uhost_asc">
<img src="up.png" border="0">
</a>
/
<a href="db.php?sort=cmp_uhost_desc">
<img src="down.png" border="0">
</a>)
</th>
<th NOWRAP>
Online
(<a href="db.php?sort=cmp_online_asc">
<img src="up.png" border="0">
</a>
/
<a href="db.php?sort=cmp_online_desc">
<img src="down.png" border="0">
</a>)
</th>
<th NOWRAP>
Total Time Idled
(<a href="db.php?sort=cmp_idled_asc">
<img src="up.png" border="0">
</a>
/
<a href="db.php?sort=cmp_idled_desc">
<img src="down.png" border="0">
</a>)
</th>
<th NOWRAP>X Pos</th>
<th NOWRAP>Y Pos</th>
<th NOWRAP>Mesg Pen.</th>
<th NOWRAP>Nick Pen.</th>
<th NOWRAP>Part Pen.</th>
<th NOWRAP>Kick Pen.</th>
<th NOWRAP>Quit Pen.</th>
<th NOWRAP>Quest Pen.</th>
<th NOWRAP>LOGOUT Pen.</th>
<th NOWRAP>
Total Pen.
(<a href="db.php?sort=cmp_pen_asc">
<img src="up.png" border="0">
</a>
/
<a href="db.php?sort=cmp_pen_desc">
<img src="down.png" border="0">
</a>)
</th>
<th NOWRAP>
Acct. Created
(<a href="db.php?sort=cmp_created_asc">
<img src="up.png" border="0">
</a>
/
<a href="db.php?sort=cmp_created_desc">
<img src="down.png" border="0">
</a>)
</th>
<th NOWRAP>
Last Login
(<a href="db.php?sort=cmp_lastlogin_asc">
<img src="up.png" border="0">
</a>
/
<a href="db.php?sort=cmp_lastlogin_desc">
<img src="down.png" border="0">
</a>)
</th>
<th NOWRAP>Amulet</th>
<th NOWRAP>Charm</th>
<th NOWRAP>Helm</th>
<th NOWRAP>Boots</th>
<th NOWRAP>Gloves</th>
<th NOWRAP>Ring</th>
<th NOWRAP>Leggings</th>
<th NOWRAP>Shield</th>
<th NOWRAP>Tunic</th>
<th NOWRAP>Weapon</th>
<th NOWRAP>
Sum
(<a href="db.php?sort=cmp_sum_asc">
<img src="up.png" border="0">
</a>
/
<a href="db.php?sort=cmp_sum_desc">
<img src="down.png" border="0">
</a>)
</th>
<th NOWRAP>
Alignment
(<a href="db.php?sort=cmp_alignment_asc">
<img src="up.png" border="0">
</a>
/
<a href="db.php?sort=cmp_alignment_desc">
<img src="down.png" border="0">
</a>)
</th>
</tr>
<?php
foreach ($file as $line) {
list($user,,$isadmin,$level,$class,$secs,,$uhost,$online,$idled,$x,$y,
$pen['mesg'],
$pen['nick'],
$pen['part'],
$pen['kick'],
$pen['quit'],
$pen['quest'],
$pen['logout'],
$created,
$lastlogin,
$item['amulet'],
$item['charm'],
$item['helm'],
$item['boots'],
$item['gloves'],
$item['ring'],
$item['leggings'],
$item['shield'],
$item['tunic'],
$item['weapon'],
$alignment,
) = explode("\t",trim($line));
$class = str_replace("<","&lt;",$class);
$user = str_replace("<","&lt;",$user);
$class = str_replace(">","&gt;",$class);
$user = str_replace(">","&gt;",$user);
$sum = 0;
foreach ($item as $k => $v) $sum += $v;
$pentot = 0;
foreach ($pen as $k => $v) $pentot += $v;
echo " <tr>\n".
" <td nowrap>$user</td>\n".
" <td>$level</td>\n".
" <td>".($isadmin?"Yes":"No")."</td>\n".
" <td nowrap>$class</td>\n".
" <td nowrap>".duration($secs)."</td>\n".
" <td nowrap>$uhost</td>\n".
" <td>".(($online == 1) ? "Yes" : "No")."</td>\n".
" <td nowrap>".duration($idled)."</td>\n".
" <td nowrap>$x</td>\n".
" <td nowrap>$y</td>\n".
" <td nowrap>".duration($pen['mesg'])."</td>\n".
" <td nowrap>".duration($pen['nick'])."</td>\n".
" <td nowrap>".duration($pen['part'])."</td>\n".
" <td nowrap>".duration($pen['kick'])."</td>\n".
" <td nowrap>".duration($pen['quit'])."</td>\n".
" <td nowrap>".duration($pen['quest'])."</td>\n".
" <td nowrap>".duration($pen['logout'])."</td>\n".
" <td nowrap>".duration($pentot)."</td>\n".
" <td nowrap>".date("D M j H:i:s Y",$created)."</td>\n".
" <td nowrap>".date("D M j H:i:s Y",$lastlogin)."</td>\n".
" <td>".$item['amulet']."</td>\n".
" <td>".$item['charm']."</td>\n".
" <td>".$item['helm']."</td>\n".
" <td>".$item['boots']."</td>\n".
" <td>".$item['gloves']."</td>\n".
" <td>".$item['ring']."</td>\n".
" <td>".$item['leggings']."</td>\n".
" <td>".$item['shield']."</td>\n".
" <td>".$item['tunic']."</td>\n".
" <td>".$item['weapon']."</td>\n".
" <td>$sum</td>\n".
" <td>".($alignment=='e'?"Evil":($alignment=='n'?"Neutral":"Good"))."</td>\n".
" </tr>\n";
}
echo('
</table>
<br><br>
* Accounts created before Aug 29, 2003 may have incowrect data fields.
');
include("footer.php");
?>

BIN
irpg/down.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 86 B

118
irpg/dump.php Normal file
View File

@@ -0,0 +1,118 @@
<?php
// this file has been edited to produce its output in the same format as
// it has with previous versions, despite the new database format. coders
// should use the new xml.php to glean player info, which is much more
// suited to db changes.
header('Content-Type: text/plain');
include("commonfunctions.php");
include("config.php");
$file = file($irpg_db);
$header = explode("\t",$file[0]);
unset($header[1]); // password
unset($header[2]); // isadmin
unset($header[6]); // nickname
unset($header[10]); // x pos
unset($header[11]); // y pos
unset($header[31]); // alignment
echo join("\t",$header)."\n";
unset($file[0]);
/* specific character requested */
if ($_GET['player']) {
foreach ($file as $line) {
list($user) = explode("\t",trim($line));
if ($user == $_GET['player']) {
list($user,,,
$level,$class,$secs,,$uhost,$online,$idled,,,
$pen['mesg'],
$pen['nick'],
$pen['part'],
$pen['kick'],
$pen['quit'],
$pen['quest'],
$pen['logout'],
$created,
$lastlogin,
$item['amulet'],
$item['charm'],
$item['helm'],
$item['boots'],
$item['gloves'],
$item['ring'],
$item['leggings'],
$item['shield'],
$item['tunic'],
$item['weapon'],
) = explode("\t",trim($line));
echo join("\t",
array($user,$level,$class,$secs,$uhost,$online,$idled,
$pen['mesg'],
$pen['nick'],
$pen['part'],
$pen['kick'],
$pen['quit'],
$pen['quest'],
$pen['logout'],
$created,
$lastlogin,
$item['amulet'],
$item['charm'],
$item['helm'],
$item['boots'],
$item['gloves'],
$item['ring'],
$item['leggings'],
$item['shield'],
$item['tunic'],
$item['weapon']))."\n";
}
}
exit(0);
}
/* no specific character requested; list all */
usort($file,"cmp_level_desc");
foreach ($file as $line) {
list($user,,,
$level,$class,$secs,,$uhost,$online,$idled,,,
$pen['mesg'],
$pen['nick'],
$pen['part'],
$pen['kick'],
$pen['quit'],
$pen['quest'],
$pen['logout'],
$created,
$lastlogin,
$item['amulet'],
$item['charm'],
$item['helm'],
$item['boots'],
$item['gloves'],
$item['ring'],
$item['leggings'],
$item['shield'],
$item['tunic'],
$item['weapon'],
) = explode("\t",trim($line));
echo join("\t",
array($user,$level,$class,$secs,$uhost,$online,$idled,
$pen['mesg'],
$pen['nick'],
$pen['part'],
$pen['kick'],
$pen['quit'],
$pen['quest'],
$pen['logout'],
$created,
$lastlogin,
$item['amulet'],
$item['charm'],
$item['helm'],
$item['boots'],
$item['gloves'],
$item['ring'],
$item['leggings'],
$item['shield'],
$item['tunic'],
$item['weapon']))."\n";
}
?>

35
irpg/footer.php Normal file
View File

@@ -0,0 +1,35 @@
</div>
<div class="footer">
<p class="small">
Questions? Comments? Suggestions? Bugs? Naked pics?
<a href="contact.php"><?php print $admin_email?></a> or <?php print $admin_nick?>@IRC.
<?php
$hits = file("hits.db");
$fp = fopen("hits.db", "w");
$thispage = explode("/",$_SERVER['PHP_SELF']);
$thispage = array_pop($thispage);
if ($fp == false) {
echo "Error: could not open file hits.db.";
}
foreach ($hits as $line) {
list($page,$numhits,$date) = explode("\t",trim($line));
if ($page == $thispage) {
++$numhits;
echo " $numhits hits since $date";
$found = 1;
}
if ($fp) {
fwrite($fp,"$page\t$numhits\t$date\n");
}
}
if (!$found && $fp) {
echo " 1 hit since ".date("M j, Y",time());
fwrite($fp,$thispage."\t1\t".date("M j, Y",time())."\n");
}
fclose($fp);
?>
</p>
</div>
</body>
</html>

111
irpg/g7.css Normal file
View File

@@ -0,0 +1,111 @@
body {
font-family: "Trebuchet MS", Arial, Helvetica, sans-serif;
background-color: #FFFFF0;
color: black;
margin: 10px;
text-align: justify;
}
h1 { margin-bottom: 0px; margin-top: 0px; }
h2 { margin-bottom: 0px; }
p.small { margin: 0px; font-size: smaller; }
a { text-decoration: none; color: #C69500; }
a:hover { text-decoration: underline; color: black; }
div.head {
border: 1px solid #c0c0c0;
text-align: left;
width: 100%;
margin-bottom: 10px;
background: #FFFFFF;
}
div.menu {
width: 120px;
position: relative;
float: left;
border: 1px solid #c0c0c0;
background: #FFFFFF;
}
div#menu a.home { color: #000000; background: #c0c0c0; border: 1px solid #000000; }
div#menu a.home:hover { background: #c0c0c0; border: 1px solid #000000; }
div#menu a {
text-align: center;
width: 118px;
margin: 0px;
display: block;
border: 1px solid #FFFFFF
}
div#menu a:hover { border: 1px solid #000000; background: #c0c0c0; text-decoration: none; }
div.content {
border: 1px solid #c0c0c0;
margin-left: 130px;
margin-top: 0px;
padding: 10px;
background: #FFFFFF;
}
div.footer {
border: 1px solid #c0c0c0;
margin-left: 130px;
margin-top: 10px;
padding: 10px;
background: #FFFFFF;
}
table.uniques {
border: 1px solid #c0c0c0;
padding: 5px;
text-align: left;
}
table.uniques td {
padding-left: 10px;
}
table.penalty {
border: 1px solid #c0c0c0;
padding: 5px;
text-align: left;
}
table.penalty th {
text-align: right;
}
table.penalty td {
}
/* Styles for the userlist */
li.online { font-weight: bold; }
li.offline { color: #c0c0c0; }
a.offline { color: #707070; }
#map {
width: 500px;
height: 500px;
background-image: url(newmap.png);
}
table.forum {
border: 1px solid #c0c0c0;
table-layout: fixed;
overflow: auto;
}
table.forum td,tr,caption,thead,tfoot,th {
padding-left: 10px;
padding-right: 10px;
}
.tdblue { background-color: #ffffdf; }
.tdgray { background-color: #eeeee0; }
.tdred {
border: 1px solid red;
background-color: #FFCCCC;
}
.smallest {
font-size: 11px;
}

BIN
irpg/head.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

47
irpg/header.php Normal file
View File

@@ -0,0 +1,47 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1 Strict//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html>
<head>
<title><?echo $irpg_chan;?> Idle RPG: <?echo $irpg_page_title;?></title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<link rel="stylesheet" type="text/css" href="g7.css" />
</head>
<body>
<!-- Idle RPG Logo -->
<div class="head">
<?php
echo(' <img src="'. $irpg_logo .'" alt="'. $irpg_chan .' Idle RPG" title="'. $irpg_chan .' Idle RPG" width="338" height="115" />');
?>
</div>
<div id="menu" class="menu">
<?php
$topbarurl = array(
'Game Info' => $BASEURL . 'index.php',
'Player Info' => $BASEURL . 'players.php',
'Contact' => $BASEURL . 'contact.php',
'Source' => 'http://idlerpg.net/source.php',
'Other IRPGs' => 'http://idlerpg.net/others.php',
'Site Source' => 'http://idlerpg.net/sitesource.php',
'World Map' => $BASEURL . 'worldmap.php',
'Quest Info' => $BASEURL . 'quest.php',
'Forum' => 'http://idlerpg.net/forum.php',
'moo.' => 'http://cowcult.org',
);
foreach ($topbarurl as $key => $value) {
if ($topbarurl[$key] == $_SERVER['PHP_SELF']) {
echo " <a class=\"home\" href=\"$value\">$key</a>\n";
}
else {
echo " <a href=\"$value\">$key</a>\n";
}
}
?>
</div>
<div class="content">

16
irpg/hits.db Normal file
View File

@@ -0,0 +1,16 @@
contact.php 3992 Apr 22, 2003
db.php 5869 Jun 13, 2003
index.php 66845 Apr 22, 2003
playerview.php 144029 Apr 5, 2004
players.php 51366 Apr 5, 2004
source.php 13036 Apr 5, 2004
sitesource.php 7956 Apr 5, 2004
others.php 13649 Apr 5, 2004
donate.php 1333 Apr 5, 2004
donated.php 4 Apr 6, 2004
forum.php 1799 Jul 13, 2004
quest.php 242 Jul 13, 2004
worldmap.php 235 Jul 13, 2004
1 Jul 15, 2004
g7.css 1 Jul 15, 2004
idlerpg.png 1 Jul 15, 2004

142
irpg/idlerpg-adv.txt Normal file
View File

@@ -0,0 +1,142 @@
#!/usr/bin/perl -w
# idlerpg-adv (11-22-2003) by daxxar (http://mental.mine.nu)
# Usage: ./idlerpg-adv.pl [playernames]
#
# Call this script from the command line, or your login profile.
use strict;
use LWP::Simple;
# Use cookies:
# %user - username, %class - class, %level - level,
# %next - time to next level, %status - online status,
# %uhost - nick!ident@host, %ca - created at,
# %llo - last logged on, %ti - total idletime,
# %items - list of items, %penalties - list of penalties (special; multiline)
#
# Each comma-separated element is printed with a newline at the end :)
my @string = (
'[User] %user', '[Class] %class', '[Level] %level', '[Next level] %next',
'[Status] %status', '[User@host] %uhost', '[Created at] %ca',
'[Last logged on] %llo', '[Total idle] %ti', '[Items] %items',
'[Penalties] %penalties'
);
### No need to change below ###
# For printing things in a columnized view
# print_col(\@list_of_entries, \@value_of_entries, $number_per_line)
sub make_col {
my $entryname = shift;
my $entryvalue = shift;
my $count = shift;
my @len;
my $ret;
# Find maximum length for each of the $count columns
for my $x (0 .. $#{$entryvalue}) {
my $col = $x % $count;
if (!defined($len[$col]) || $len[$col] < length($entryvalue->[$x] . $entryname->[$x])) {
$len[$col] = length("$entryvalue->[$x]"."$entryname->[$x]");
}
}
for my $t (0 .. $#$entryvalue) {
if (!($t % $count)) { $ret .= "\n "; }
$ret .= "$entryname->[$t]\($entryvalue->[$t]\)";
$ret .= ' ' x ($len[$t % $count] - length($entryname->[$t] . $entryvalue->[$t]) + 1);
}
return $ret;
}
sub time_to {
my @timeunits = ('yr', 'month', 'week', 'day', 'hr', 'min', 'sec');
my @timecalc = (31104000, 2592000, 604800, 86400, 3600, 60, 1);
my $seconds = shift; my $output;
if ($seconds == 0) { return "0 seconds"; }
for my $x (0 .. $#timecalc) {
my $y = int($seconds / $timecalc[$x]);
if ($y != 0 && $seconds != 0 && $seconds >= $timecalc[$x]) {
$seconds = ($seconds % $timecalc[$x]);
$output .= "$y $timeunits[$x]";
$output .= 's' unless $y == 1;
if ($seconds == 0) { last; }
$output .= ', ' if $x < $#timecalc - 1 && ($seconds % $timecalc[$x+1]) && $seconds != 0;
$output .= ' and ' if !($seconds % $timecalc[$x+1]);
}
}
return $output;
}
sub time_from {
my $seconds = shift;
my ($sec, $min, $hr, $day, $mo, $yr, $wday) = localtime($seconds);
$mo = ('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Oct', 'Sep', 'Nov', 'Dec')[$mo];
$wday = ('Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat')[$wday];
$yr += 1900;
if ($hr < 10) { $hr = "0$hr"; }
if ($min < 10) { $min = "0$min"; }
if ($sec < 10) { $sec = "0$sec"; }
if ($day < 10) { $day .= ' '; }
return "$wday $mo $day $hr:$min:$sec $yr";
}
die "Usage: $0 <playernames>\n" .
"Example: $0 daxxar cyb\n" if @ARGV == 0;
start:
my $username = shift(@ARGV);
my $page = get "http://jotun.ultrazone.org/g7/dump.php?player=$username";
# Only line is commented if there is no such user
if ($page =~ /^#[^\n]+$/) { print "$username: no such user\n"; exit 1; }
($page) = ($page =~ /\n([^#].*)/); # Remove the comment
# @ent = entries on page, \t separated.
my @ent = split(/\t/, $page);
# Assign each tab-separated entry to its hash-key
my %values = (
'user' => $ent[0], 'level' => $ent[1],
'class' => $ent[2], 'next' => $ent[3],
'host' => $ent[4], 'status' => $ent[5],
'totalidle'=> $ent[6], 'created'=> $ent[14],
'lastlog' => $ent[15],
'penaltynames' => [ qw(msg nick part kick quit quest logout) ],
'penaltytimes' => [ @ent[7 .. 13] ],
'itemnames' => [ qw(amulet charm helm boots gloves ring leggings shield tunic weapon sum) ],
'itemlvls' => [ @ent[16 .. 25] ]
);
$values{'next'} = time_to ($values{'next'});
$values{'totalidle'} = time_to ($values{'totalidle'});
$values{'lastlog'} = time_from($values{'lastlog'});
$values{'created'} = time_from($values{'created'});
if ($values{'status'}) {$values{'status'} = 'Online'}
else {$values{'status'} = 'Offline'}
foreach my $str (@{[ @string ]}) {
$str =~ s/%user/$values{'user'}/g;
$str =~ s/%class/$values{'class'}/g;
$str =~ s/%level/$values{'level'}/g;
$str =~ s/%next/$values{'next'}/g;
$str =~ s/%status/$values{'status'}/g;
$str =~ s/%uhost/$values{'host'}/g;
$str =~ s/%ca/$values{'created'}/g;
$str =~ s/%llo/$values{'lastlog'}/g;
$str =~ s/%ti/$values{'totalidle'}/g;
if ($str =~ /%penalties/) {
my @penaltyname = qw(msg nick part kick quit quest logout);
my @penaltytime = @ent[7 .. 13];
for my $t (0 .. $#penaltytime) { $penaltytime[$t] = time_to($penaltytime[$t]); }
my $cols = make_col(\@penaltyname, \@penaltytime, 3);
$str =~ s/%penalties/$cols/g;
}
if ($str =~ /%items/) {
my @itemname = qw(amulet charm helm boots gloves ring leggings shield tunic weapon sum);
my @itemlvls = @ent[16 .. 25];
# Yay, lets get a nice sum(sum) in output! :D
my $sum; map($sum += $_, @itemlvls);
my $cols = make_col(\@itemname, [ @itemlvls, $sum ], 3);
$str =~ s/%items/$cols/g;
}
$str =~ s///g;
$str =~ s///g;
print "$str\n";
}
print "\n" if @ARGV != 0;
goto start if @ARGV != 0;

480
irpg/index.php Normal file
View File

@@ -0,0 +1,480 @@
<?php
include("config.php");
$irpg_page_title = "Game Info";
include("header.php");
?>
<h1>Game Info</h1>
<p>The Idle RPG is just what it sounds like: an RPG in which the players
idle. In addition to merely gaining levels, players can find items and
battle other players. However, this is all done for you; you just idle.
There are no set classes; you can name your character anything you like, and
have its class be anything you like, as well.</p>
<h2>Location</h2>
<p>
The Idle RPG can be played on the
<a href="http://www.slashnet.org/">SlashNET IRC Network</a> in the
channel #G7. See <a href="http://www.slashnet.org/servers/">this</a>
link for a list of servers.
</p>
<h2>Registering</h2>
<p>To register, simply:</p>
<code>
/msg <?echo $irpg_bot;?> REGISTER &lt;char name&gt; &lt;password&gt;
&lt;char class&gt;
</code>
<p>Where 'char name' can be up to 16 chars long, 'password' can be up
to 8 characters, and 'char class' can be up to 30 chars.</p>
<h2>Logging In</h2>
<p>To login, simply:</p>
<code>
/msg <?echo $irpg_bot;?> LOGIN &lt;char name&gt; &lt;password&gt;
</code>
<p>This is a p0 (see <a href="#penalties">Penalties</a>) command.</p>
<h2>Logging Out</h2>
<p>To logout, simply:</p>
<code>
/msg <?echo $irpg_bot;?> LOGOUT
</code>
<p>This is a p20 (see <a href="#penalties">Penalties</a>) command.</p>
<h2>Changing Your Password</h2>
<p>To change your password, simply:</p>
<code>
/msg <?echo $irpg_bot;?> NEWPASS &lt;new password&gt;
</code>
<p>This is a p0 (see <a href="#penalties">Penalties</a>) command.</p>
<p>If you have forgotten your password, please use the <a href="#info">
INFO</a> command to find an online admin to help you. If your
administrator does not have the INFO command enabled, then just message
an op in the channel. They can probably help you.</p>
<h2>Removing Your Account</h2>
<p>To remove your account, simply:</p>
<code>
/msg <?echo $irpg_bot;?> REMOVEME
</code>
<p>This is a p0 (see <a href="#penalties">Penalties</a>) command :^)</p>
<h2>Changing Your Alignment</h2>
<p>To change your alignment, simply:</p>
<code>
/msg <?echo $irpg_bot;?> ALIGN &lt;good|neutral|evil&gt;
</code>
<p>This is a p0 (see <a href="#penalties">Penalties</a>) command.</p>
<p>Your alignment can affect certain aspects of the game. You may align
with good, neutral, or evil. 'Good' users have a 10% boost to their item
sum for battles, and a 1/12 chance each day that they, along with a
'good' friend, will have the light of their god shine upon them,
accelerating them 5-12% toward their next level. 'Evil' users have a 10%
detriment to their item sum for battles (ever forsaken in their time of
most need...), but have a 1/8 chance each day that they will either a)
attempt to steal an item from a 'good' user (whom they cannot help but
hate) or b) be forsaken (for 1-5% of their TTL) by their evil god. After
all, we all know that crime doesn't pay. Also, 'good' users have only a
1/50 chance of landing a <a href="#critstrike">Critical Strike</a> when
battling, while 'evil' users (who always fight dirty) have a 1/20
chance. Neutral users haven't had anything changed, and all users start
off as neutral.</p>
<p>I haven't run the numbers to see which alignment it is better to
follow, so the stats for this feature may change in the future.</p>
<a name="info"></a><h2>Obtaining Bot Info</h2>
<p>To see some simple information on the bot, simply:</p>
<code>
/msg <?echo $irpg_bot;?> INFO
</code>
<p>This is a p0 (see <a href="#penalties">Penalties</a>) command.</p>
<p>This command gives info such as to which server the bot is connected
and the nicknames of online bot admins.</p>
<p>This command is optional, and may be disabled by your bot admin.</p>
<h2>Levelling</h2>
<p>To gain levels, you must only be logged in and idle. The time
between levels is based on your character level, and is calculated
by the formula:</p>
600*(1.16^YOUR_LEVEL)
<p>Where ^ represents the exponentiation operator.</p>
<p>Very high levels are calculated differently as of version 3.0. Levels
after level 60 have a next time to level of:</p>
(time to level @ 60) + ((1 day) * (level - 60))
<p>The exponent method code had simply gotten to that point that levels
were taking too long to complete.</p>
<h2>Checking the Active Quest</h2>
<p>To see the active quest, its users, and its time left to
completion:</p>
<code>
/msg <?echo $irpg_bot;?> QUEST
</code>
<p>This is a p0 (see <a href="#penalties">Penalties</a>) command.</p>
<h2>Checking Your Online Status</h2>
<p>To see whether you are logged on, simply:</p>
<code>
/msg <?echo $irpg_bot;?> WHOAMI
</code>
<p>This is a p0 (see <a href="#penalties">Penalties</a>) command.</p>
<a name="penalties"></a><h2>Penalties</h2>
<p>If you do something other than idle, like part, quit, talk in the
channel, change your nick, or notice the channel, you are
penalized. The penalties are time, in seconds, added to your next
time to level and are based on your character level. The formulae
are as follows:</p>
<table id="penalty" class="penalty">
<tr>
<th>Nick change</th>
<td>30*(1.14^(YOUR_LEVEL))</td>
</tr>
<tr>
<th>Part</th>
<td>200*(1.14^(YOUR_LEVEL))</td>
</tr>
<tr>
<th>Quit</th>
<td>20*(1.14^(YOUR_LEVEL))</td>
</tr>
<tr>
<th>LOGOUT command</th>
<td>20*(1.14^(YOUR_LEVEL))</td>
</tr>
<tr>
<th>Being Kicked</th>
<td>250*(1.14^(YOUR_LEVEL))</td>
</tr>
<tr>
<th>Channel privmsg</th>
<td>[message_length]*(1.14^(YOUR_LEVEL))</td>
</tr>
<tr>
<th>Channel notice</th>
<td>[message_length]*(1.14^(YOUR_LEVEL))</td>
</tr>
</table>
<br />
<p>So, a level 25 character changing their nick would be penalized
20*(1.14^25)=793 seconds towards their next level.</p>
<p>Penalty shorthand is p[num]. So, a nick change is a p30 event,
parting the channel is a p200 event, and quitting IRC is a p20 event.
Messages and notices are p[length of message in characters].</p>
<h2>Items</h2>
<p>Each time you level, you find an item. You can find an item as
high as 1.5*YOUR_LEVEL (unless you find a <a href="#uniqueitems">
unique item</a>). There are 10 types of items: rings,
amulets, charms, weapons, helms, tunics, gloves, leggings,
shields, and boots. You can find one of each type. When you find
an item with a level higher than the level of the item you already
have, you toss the old item and start using the new one. As of version
3.0, there is an optional, p0 STATUS command that your admin may have
enabled, but you cannot see which items you have over IRC (only your
total item sum). You can, however, see which items you have on the web
<a href="players.php">here</a>.</p>
<p>As you may guess, you have a higher chance of rolling an item of a
lower value than you do of rolling one of a higher value level. The exact
formula is as follows:</p>
for each 'number' from 1 to YOUR_LEVEL*1.5<br />
&nbsp;&nbsp;you have a 1 / ((1.4)^number) chance to find an
item at this level<br />
end for
<p>As for item type, you have an equal chance to roll any type.</p>
<h2>Battle</h2>
<p>Each time you level, if your level is less than 25, you have a 25%
chance to challenge someone to combat. If your level is greater than or
equal to 25, you have a 100% chance to challenge someone. A pool of
opponents is chosen of all online players, and one is chosen randomly. If
there are no other online players, you fight no one. However, if you do
challenge someone, this is how the victor is decided:</p>
<ul>
<li>Your item levels are summed.</li>
<li>Their item levels are summed.</li>
<li>A random number between zero and your sum is taken.</li>
<li>A random number between zero and their sum is taken.</li>
<li>If your roll is larger than theirs, you win.</li>
</ul>
<p>If you win, your time towards your next level is lowered. The amount
that it is lowered is based on your opponent's level. The formula is:</p>
((the larger number of (OPPONENT_LEVEL/4) and 7) / 100) *
YOUR_NEXT_TIME_TO_LEVEL
<p>This means that you lose no less than 7% from your next time to level.
If you win, your opponent is not penalized any time, unless you land a
<a href="#critstrike">Critical Strike</a>.</p>
<p>If you lose, you will be penalized time. The penalty is calculated
using the formula:</p>
((the larger number of (OPPONENT_LEVEL/7) and 7) / 100) *
YOUR_NEXT_TIME_TO_LEVEL
<p>This means that you gain no less than 7% of your next time to level.
If you lose, your opponent is not awarded any time.</p>
<p>Battling the IRPG bot is a special case. The bot has an item sum of
1+[highest item sum of all players]. The percent awarded if you win is a
constant 20%, and the percent penalized if you lose is a constant 10%.</p>
<p>As of version 3.0, if more than 15% of online players are level 45 or
higher, then a random level 45+ user will battle another random player
every hour. This is to speed up levelling among higher level players.</p>
<p>Also as of version 3.0, there is a grid system. The grid is a 500 x 500
area in which players may walk. If you encounter another player on the
grid, you have a 1 / (NUMBER_OF_ONLINE_PLAYERS) chance to battle them.
Battle awards are calculated using the above formulae. More information
on the grid system is available <a href="#grid">here</a>.</p>
<p>Also as of version 3.0, a successful battle may result an item being
<a href="#stealing">stolen</a>.</p>
<a name="uniqueitems"></a><h2>Unique Items</h2>
<p>As of v2.1.2, after level 25, you have a chance to roll items
significantly higher than items you would normally find at that level.
These are unique items, and have the following stats:</p>
<table id="uniques" class="uniques">
<tr>
<th>Name</th>
<th>Item Level Range</th>
<th>Required User Level</th>
<th>Chance to Roll</th>
</tr>
<tr>
<th>Mattt's Omniscience Grand Crown</th>
<td>50-74</td>
<td>25 or greater</td>
<td>1 / 40</td>
</tr>
<tr>
<th>Juliet's Glorious Ring of Sparkliness</th>
<td>50-74</td>
<td>25 or greater</td>
<td>1 / 40</td>
</tr>
<tr>
<th>Res0's Protectorate Plate Mail</th>
<td>75-99</td>
<td>30 or greater</td>
<td>1 / 40</td>
</tr>
<tr>
<th>Dwyn's Storm Magic Amulet</th>
<td>100-124</td>
<td>35 or greater</td>
<td>1 / 40</td>
</tr>
<tr>
<th>Jotun's Fury Colossal Sword</th>
<td>150-174</td>
<td>40 or greater</td>
<td>1 / 40</td>
</tr>
<tr>
<th>Drdink's Cane of Blind Rage</th>
<td>175-200</td>
<td>45 or greater</td>
<td>1 / 40</td>
</tr>
<tr>
<th>Mrquick's Magical Boots of Swiftness</th>
<td>250-300</td>
<td>48 or greater</td>
<td>1 / 40</td>
</tr>
<tr>
<th>Jeff's Cluehammer of Doom</th>
<td>300-350</td>
<td>52 or greater</td>
<td>1 / 40</td>
</tr>
</table>
<h2>The Hand of God</h2>
<p>As of v3.0, every online user has a (roughly) 1/20 chance per day
of a "Hand of God" affecting them. A HoG can help or hurt your character
by carrying it between 5 and 75 percent towards or away from its next time
to level. The odds are in your favor, however, with an 80% chance to help
your character, and only a 20% chance of your character being smitten.</p>
<p>In addition to occurring randomly, admins may summon the HoG at their
whim.</p>
<a name="critstrike"></a><h2>Critical Strike</h2>
<p>As of v2.0.4, if a challenger beats his opponent in battle, he has a
1/35 chance of landing a Critical Strike. If this occurs, his opponent
is penalized time towards his next time to level. This amount is
calculated by the formula:</p>
((random number from 5 to 25) / 100) * OPPONENT'S_NEXT_TIME_TO_LEVEL
<p>Meaning he gains no less than 5% and no more than 25% of his next time
to level.</p>
<h2>Team Battles</h2>
<p>As of v3.0, every online user has (roughly) 1/4 chance per day of
being involved in a 'team battle.' Team battles pit three online
players against three other online players. Each side's items are summed,
and a winner is chosen as in regular battling. If the first group bests
the second group in combat, 20% of the lowest of the three's TTL is
removed from their clocks. If the first group loses, 20% of their lowest
member's TTL is added to their TTL.</p>
<h2>Calamities</h2>
<p>As of v3.0, every online user has a (roughly) 1/8 chance per day of a
calamity occurring to them. A calamity is a bit of extremely bad luck that
either:<br />
a) slows a player 5-12% of their next time to level<br />
b) lowers one of their item's value by 10%
</p>
<h2>Godsends</h2>
<p>As of v3.0, every online user has a (roughly) 1/8 chance per day of a
godsend occurring to them. A godsend is a bit of extremely good luck that
either:<br />
a) accelerates a player 5-12% of their next time to level<br />
b) increases one of their item's value by 10%
</p>
<h2>Quests</h2>
<p>As of v2.3, there are Quests. Four level 40+ users that have been
online for more than ten hours are chosen to represent and assist the
Realm by going on a quest. If all four users make it to the quest's end,
all questers are awarded by removing 25% of their TTL (ie, their TTL at
quest's end). To complete a quest, no user can be penalized until the
quest's end. As of v3.0, there are two kinds of quests: grid-based quests
and time-based quests. Time-based quests last a random time between 12 and
24 hours. Grid-based quests are based on the <a href="#grid">grid
system</a> and do not have a set time to completion. Rather, the questers
must reach certain points on the map for their quest to be complete. If
the quest is not completed, ALL online users are penalized a p15 as
punishment.</p>
<a name="grid"></a><h2>Grid System</h2>
<p>As of v3.0, the IRPG has a grid system. The grid can be considered
a 500 x 500 point map on which the players may walk. Every second, each
player has an equal chance to step up, down, or neither, and an equal
chance to step left, right, or neither. If a user encounters another
player, there is a 1/(NUMBER_OF_ONLINE_PLAYERS) chance that they will
battle one another. Normal battling rules apply.</p>
<p>Some quests require that users walk to certain points on the map. In
the spirit of IRPG, of course, the trek is made for you. Your character
will automatically walk in the direction that it is supposed to, although
at a much slower than normal pace (to avoid accidents, of course. you
don't want to fall down and risk a Realm-wide p15!).</p>
<a name="stealing"></a><h2>Item Stealing</h2>
<p>As of v3.0, the IRPG has item stealing. After each battle, if the
challenger wins, he has a slightly less than 2% chance of stealing an
item from the challengee. Only items of a higher value are stolen, and
the challenger's old item is given to the challengee in a moment of pity.
</p>
<h2>Credits</h2>
<p>Many thanks to version 3.0's map creators, res0 and Jeb! The game
wouldn't be the same without you.</p>
<p>
The IRPG would not be possible without help from a lot of people.
To jwbozzy, yawnwraith, Tosirap, res0, dwyn, Parallax, protomek,
Bert, clavicle, drdink, jeff, rasher, Sticks, Nerje, Asterax,
emad, inkblot(!), schmolli, mikegrb, mumkin, sean, Minhiriath,
and Dan, I give many thanks. Unfortunately, this list has grown too
large to maintain. More user contributions can be seen in the
<a href="http://idlerpg.net/ChangeLog.txt">ChangeLog</a>.
</p>
<?include("footer.php");?>

60
irpg/makemap.php Normal file
View File

@@ -0,0 +1,60 @@
<?
include("config.php");
session_start(); // sessions to generate only one map / person / 20s
if (isset($_SESSION['time']) && time()-$_SESSION['time'] < 20) {
header("Location: maperror.png");
exit(0);
}
$_SESSION['time']=time();
$map = imageCreate(500,500);
$user = substr($_GET['player'],0,30);
$stringx=$stringy=-1;
$file = file($irpg_db);
unset($file[0]);
foreach ($file as $line) {
list($username,,,,,,,,,,$x,$y) = explode("\t",trim($line));
if ($username == $user) {
$stringx = $x;
$stringy = $y;
break;
}
}
if ($stringx == $stringy && $stringx == -1) {
imageString($map,5,200,245,"NO SUCH USER",imagecolorallocate($map,255,0,0));
}
else {
$width = imageFontWidth(5);
$height = imageFontHeight(5);
if ($x+((strlen($user)+1)*$width) > 500) {
$stringx = $x - ((strlen($user)+1)*$width)-12;
}
if ($y+$height > 500) {
$stringy = $y - ($height/2)-2;
}
$magenta = imageColorAllocate($map,255,0,255);
imageColorTransparent($map,$magenta);
$brown = imagecolorallocate($map, 102, 51, 0);
$parchment = imagecolorallocate($map, 255, 255, 204);
// Avoid drawing a brown dot on a brown area
$rgb = imageColorAt($map, $x, $y);
if ($rgb > 0) { // $rgb is 0 on our parchment-colored areas
$temp = $brown;
$brown = $parchment;
$parchment = $temp;
}
// YOU ARE HERE
imageFilledEllipse($map, $x, $y, 6, 6, $brown);
// background for text
imageFilledRectangle($map,$stringx+6,$stringy-($height/2),$stringx+6+$width*(strlen($user)+1),$stringy+($height/2),$brown);
// text itself
imageString($map,5,$stringx+7+($width/2),$stringy-($height/2)-1,$user,$parchment);
}
header("Content-type: image/png");
imagePNG($map);
imageDestroy($map);
?>

79
irpg/makequestmap.php Normal file
View File

@@ -0,0 +1,79 @@
<?
include("config.php");
$file = fopen($irpg_db,"r");
fgets($file,1024);
session_start(); // sessions to generate only one map / person / 20s
if (isset($_SESSION['time']) && time()-$_SESSION['time'] < 20) {
header("Location: maperror.png");
exit(0);
}
$_SESSION['time']=time();
$file = fopen($irpg_qfile,"r");
$type=0;
while ($line=fgets($file,1024)) {
$arg = explode(" ",trim($line));
if ($arg[0] == "Y") {
$type = $arg[1];
}
elseif ($arg[0] == "P") {
$p1[0] = $arg[1];
$p1[1] = $arg[2];
$p2[0] = $arg[3];
$p2[1] = $arg[4];
}
elseif ($arg[0] == "S") {
if ($type == 1) $time = $arg[1];
elseif ($type == 2) $stage = $arg[1];
}
elseif ($arg[0] == "P1") {
$player[1]['name'] = $arg[1];
if ($type == 2) {
$player[1]['x'] = $arg[2];
$player[1]['y'] = $arg[3];
}
}
elseif ($arg[0] == "P2") {
$player[2]['name'] = $arg[1];
if ($type == 2) {
$player[2]['x'] = $arg[2];
$player[2]['y'] = $arg[3];
}
}
elseif ($arg[0] == "P3") {
$player[3]['name'] = $arg[1];
if ($type == 2) {
$player[3]['x'] = $arg[2];
$player[3]['y'] = $arg[3];
}
}
elseif ($arg[0] == "P4") {
$player[4]['name'] = $arg[1];
if ($type == 2) {
$player[4]['x'] = $arg[2];
$player[4]['y'] = $arg[3];
}
}
}
if ($type != 2) {
header("Location: maperror.png");
exit(0);
}
$map = imageCreate(500,500);
$magenta = imageColorAllocate($map, 255, 0, 255);
imageColorTransparent($map,$magenta);
$blue = imageColorAllocate($map, 0, 128, 255);
$red = imageColorAllocate($map, 255, 0, 0);
imageFilledEllipse($map, $player[1]['x'], $player[1]['y'], 6, 6, $blue);
imageFilledEllipse($map, $player[2]['x'], $player[2]['y'], 6, 6, $blue);
imageFilledEllipse($map, $player[3]['x'], $player[3]['y'], 6, 6, $blue);
imageFilledEllipse($map, $player[4]['x'], $player[4]['y'], 6, 6, $blue);
if ($stage == 1) imageFilledEllipse($map, $p1[0], $p1[1], 8, 8, $red);
else imageFilledEllipse($map, $p2[0], $p2[1], 9, 9, $red);
header("Content-type: image/png");
imagePNG($map);
imageDestroy($map);
?>

26
irpg/makeworldmap.php Normal file
View File

@@ -0,0 +1,26 @@
<?
include("config.php");
$file = fopen($irpg_db,"r");
fgets($file);
session_start(); // sessions to generate only one map / person / 20s
if (isset($_SESSION['time']) && time()-$_SESSION['time'] < 20) {
header("Location: maperror.png");
exit(0);
}
$_SESSION['time']=time();
$map = imageCreate(500,500);
$magenta = ImageColorAllocate($map, 255, 0, 255);
$blue = imageColorAllocate($map, 0, 128, 255);
$red = imageColorAllocate($map, 211, 0, 0);
ImageColorTransparent($map, $magenta);
while ($line=fgets($file)) {
list(,,,,,,,,$online,,$x,$y) = explode("\t",trim($line));
if ($online == 1) imageFilledEllipse($map, $x, $y, 3, 3, $blue);
else imageFilledEllipse($map, $x, $y, 3, 3, $red);
}
header("Content-type: image/png");
imagePNG($map);
imageDestroy($map);
?>

BIN
irpg/maperror.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

BIN
irpg/newmap.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

37
irpg/players.php Normal file
View File

@@ -0,0 +1,37 @@
<?
include("config.php");
include("commonfunctions.php");
$irpg_page_title = "Player Info";
include("header.php");
?>
<h1>Players</h1>
<h2>Pick a player to view</h2>
<p class="small">[gray=offline]</p>
<ol>
<?php
$file = file($irpg_db);
unset($file[0]);
usort($file, 'cmp_level_desc');
foreach ($file as $line) {
list($user,,,$level,$class,$secs,,,$online) = explode("\t",trim($line));
$class = htmlentities($class);
$next_level = duration($secs);
print " <li".(!$online?" class=\"offline\"":"")."><a".
(!$online?" class=\"offline\"":"").
" href=\"playerview.php?player=".urlencode($user).
"\">".htmlentities($user).
"</a>, the level $level $class. Next level in $next_level.</li>\n";
}
?>
</ol>
<p>For a script to view player stats from a terminal, try <a
href="idlerpg-adv.txt">this</a> perl script by
<a href="mailto:daxxar@mental.mine.nu">daxxar</a>.</p>
<p>See player stats in <a href="db.php">table format</a>.</p>
<?include("footer.php")?>

156
irpg/playerview.php Normal file
View File

@@ -0,0 +1,156 @@
<?php
include("config.php");
$_GET['player'] = substr($_GET['player'],0,30);
/* Determine if a Player was entered. If not, redirect. */
if ($_GET['player']=="") header('Location: http://'.$_SERVER['SERVER_NAME'].
($_SERVER['SERVER_PORT']!=80?':'.$_SERVER['SERVER_PORT']:'').$BASEURL.
'players.php');
$irpg_page_title = "Player Info: " . htmlentities($_GET['player']);
$showmap = $_GET['showmap'];
include("header.php");
include("commonfunctions.php");
echo "<h1>Player Info</h1>";
$file = fopen($irpg_db,"r");
fgets($file,1024); // skip top comment
$found=0;
while ($line=fgets($file,1024)) {
if (substr($line,0,strlen($_GET['player'])+1) == $_GET['player']."\t") {
list($user,,$isadmin,$level,$class,$secs,,$uhost,$online,$idled,
$x,$y,
$pen['mesg'],
$pen['nick'],
$pen['part'],
$pen['kick'],
$pen['quit'],
$pen['quest'],
$pen['logout'],
$created,
$lastlogin,
$item['amulet'],
$item['charm'],
$item['helm'],
$item['boots'],
$item['gloves'],
$item['ring'],
$item['leggings'],
$item['shield'],
$item['tunic'],
$item['weapon'],
$alignment,
) = explode("\t",trim($line));
$found=1;
break;
}
}
if (!$found) echo "<h1>Error</h1><p><b>No such user.</b></p>\n";
else {
$class=htmlentities($class);
/* if we htmlentities($user), then we cannot use links with it. */
echo " <p><b>User:</b> ".htmlentities($user)."<br />\n".
" <b>Class:</b> $class<br />\n".
" <b>Admin?:</b> ".($isadmin?"Yes":"No")."<br />\n".
" <b>Level:</b> $level<br />\n".
" <b>Next level:</b> ".duration($secs)."<br />\n".
" <b>Status:</b> O".($online?"n":"ff")."line<br />\n".
" <b>Host:</b> ".($uhost?$uhost:"Unknown")."<br />\n".
" <b>Account Created:</b> ".date("D M j H:i:s Y",$created)."<br />\n".
" <b>Last login:</b> ".date("D M j H:i:s Y",$lastlogin)."<br />\n".
" <b>Total time idled:</b> ".duration($idled)."<br />\n".
" <b>Current position:</b> [$x,$y]<br />\n".
" <b>Alignment:</b> ".($alignment=='e'?"Evil":($alignment=='n'?"Neutral":"Good"))."<br />\n".
" <b>XML:</b> [<a href=\"xml.php?player=".urlencode($user)."\">link</a>]</p>\n".
" <h2>Map</h2>\n".
" ".($showmap?"<div id=\"map\"><img src=\"makemap.php?player=".urlencode($user)."\"></div>\n\n":"<p><a href=\"?player=".urlencode($user)."&showmap=1\">Show map</a></p>\n\n")."".
" <h2>Items</h2>\n<p>";
ksort($item);
$sum = 0;
foreach ($item as $key => $val) {
$uniquecolor="#be9256";
if ($key == "helm" && substr($val,-1,1) == "a") {
$val = intval($val)." [<font color=\"$uniquecolor\">Mattt's Omniscience Grand Crown</font>]";
}
if ($key == "tunic" && substr($val,-1,1) == "b") {
$val = intval($val)." [<font color=\"$uniquecolor\">Res0's Protectorate Plate Mail</font>]";
}
if ($key == "amulet" && substr($val,-1,1) == "c") {
$val = intval($val)." [<font color=\"$uniquecolor\">Dwyn's Storm Magic Amulet</font>]";
}
if ($key == "weapon" && substr($val,-1,1) == "d") {
$val = intval($val)." [<font color=\"$uniquecolor\">Jotun's Fury Colossal Sword</font>]";
}
if ($key == "weapon" && substr($val,-1,1) == "e") {
$val = intval($val)." [<font color=\"$uniquecolor\">Drdink's Cane of Blind Rage</font>]";
}
if ($key == "boots" && substr($val,-1,1) == "f") {
$val = intval($val)." [<font color=\"$uniquecolor\">Mrquick's Magical Boots of Swiftness</font>]";
}
if ($key == "weapon" && substr($val,-1,1) == "g") {
$val = intval($val)." [<font color=\"$uniquecolor\">Jeff's Cluehammer of Doom</font>]";
}
if ($key == "ring" && substr($val,-1,1) == "h") {
$val = intval($val)." [<font color=\"$uniquecolor\">Juliet's Glorious Ring of Sparkliness</font>]";
}
echo " $key: $val<br />\n";
$sum += $val;
}
echo " <br />\n sum: $sum<br />\n".
" </p>".
" <h2>Penalties</h2>\n".
" <p>\n";
ksort($pen);
$sum = 0;
foreach ($pen as $key => $val) {
echo " $key: ".duration($val)."<br />\n";
$sum += $val;
}
echo " <br />\n total: ".duration($sum)."</p>\n";
$file = fopen($irpg_mod,"r");
$temp = array();
while ($line=fgets($file,1024)) {
if (strstr($line," ".$_GET['player']." ") ||
strstr($line," ".$_GET['player'].", ") ||
substr($line,0,strlen($_GET['player'])+1) ==
$_GET['player']." " ||
substr($line,0,strlen($_GET['player'])+3) ==
$_GET['player']."'s ") {
array_push($temp,$line);
}
}
fclose($file);
if (!is_null($temp) && count($temp)) {
echo('<h2>');
echo $_GET['allmods']!=1?"Recent ":"";
echo('Character Modifiers</h2><p>');
if ($_GET['allmods'] == 1 || count($temp) < 6) {
foreach ($temp as $line) {
$line=htmlentities(trim($line));
echo " $line<br />\n";
}
echo " <br />\n";
}
else {
end($temp);
for ($i=0;$i<4;++$i) prev($temp);
for ($line=trim(current($temp));$line;$line=trim(next($temp))) {
$line=htmlentities(trim($line));
echo " $line<br />\n";
}
}
}
if ($_GET['allmods'] != 1 && count($temp) > 5) {
?>
<br />
[<a href="<?php echo $_SERVER['PHP_SELF']."?player=".urlencode($user);?>&amp;allmods=1">View all Character Modifiers</a> (<?=count($temp)?>)]
</p>
<?php
}
}
include("footer.php");
?>

118
irpg/quest.php Normal file
View File

@@ -0,0 +1,118 @@
<?php
include("config.php");
$irpg_page_title = "Quest Info";
include("header.php");
echo " <h1>Current Quest</h1>\n";
include("commonfunctions.php");
$file = fopen($irpg_qfile,"r");
$type=0;
while ($line=fgets($file,1024)) {
$arg = explode(" ",trim($line));
if ($arg[0] == "T") {
unset($arg[0]);
$text = implode(" ",$arg);
}
elseif ($arg[0] == "Y") {
$type = $arg[1];
}
elseif ($arg[0] == "P") {
$p1[0] = $arg[1];
$p1[1] = $arg[2];
$p2[0] = $arg[3];
$p2[1] = $arg[4];
}
elseif ($arg[0] == "S") {
if ($type == 1) $time = $arg[1];
elseif ($type == 2) $stage = $arg[1];
}
elseif ($arg[0] == "P1") {
$player[1]['name'] = $arg[1];
if ($type == 2) {
$player[1]['x'] = $arg[2];
$player[1]['y'] = $arg[3];
}
}
elseif ($arg[0] == "P2") {
$player[2]['name'] = $arg[1];
if ($type == 2) {
$player[2]['x'] = $arg[2];
$player[2]['y'] = $arg[3];
}
}
elseif ($arg[0] == "P3") {
$player[3]['name'] = $arg[1];
if ($type == 2) {
$player[3]['x'] = $arg[2];
$player[3]['y'] = $arg[3];
}
}
elseif ($arg[0] == "P4") {
$player[4]['name'] = $arg[1];
if ($type == 2) {
$player[4]['x'] = $arg[2];
$player[4]['y'] = $arg[3];
}
}
}
if (!$type) {
echo " <p>Sorry, there is no active quest.</p>\n";
}
else {
echo " <p><b>Quest:</b> To $text.</p>\n";
if ($type == 1) {
echo " <p><b>Time to completion:</b> ".duration($time-time()).
"</p>\n";
}
elseif ($type == 2) {
if ($stage == 1) {
echo " <p><b>Current goal:</b> [$p1[0],$p1[1]]</p>\n";
}
else {
echo " <p><b>Current goal:</b> [$p2[0],$p2[1]]</p>>\n";
}
}
echo " <p><b>Participant 1:</b> <a href=\"playerview.php?player=".
urlencode($player[1]['name'])."\">".htmlentities($player[1]['name']).
"</a><br />\n";
if ($type == 2) {
echo " <b>Position:</b> [".$player[1]['x'].",".$player[1]['y']."]</p>\n";
}
else echo "<br />\n";
echo " <p><b>Participant 2:</b> <a href=\"playerview.php?player=".
urlencode($player[2]['name'])."\">".htmlentities($player[2]['name']).
"</a><br />\n";
if ($type == 2) {
echo " <b>Position:</b> [".$player[2]['x'].",".$player[2]['y']."]</p>\n";
}
else echo "<br />\n";
echo " <p><b>Participant 3:</b> <a href=\"playerview.php?player=".
urlencode($player[3]['name'])."\">".htmlentities($player[3]['name']).
"</a><br />\n";
if ($type == 2) {
echo " <b>Position:</b> [".$player[3]['x'].",".$player[3]['y']."]</p>\n";
}
else echo "<br />\n";
echo " <p><b>Participant 4:</b> <a href=\"playerview.php?player=".
urlencode($player[4]['name'])."\">".htmlentities($player[4]['name']).
"</a><br />\n";
if ($type == 2) {
echo " <b>Position:</b> [".$player[4]['x'].",".$player[4]['y']."]</p>\n".
" <h2>Quest Map:</h2>\n".
" <p>[Questers are shown in blue, current goal in red]</p>\n".
" <div id=\"map\"><img src=\"makequestmap.php\" alt=\"Idle RPG Quest Map\" usemap=\"#quest\" border=\"0\" /></div>\n".
" <map id=\"quest\" name=\"quest\">\n".
" <area shape=\"circle\" coords=\"".$player[1]['x'].",".$player[1]['y'].",6\" alt=\"".htmlentities($player[1]['name']).
"\" href=\"playerview.php?player=".urlencode($player[1]['name'])."\" title=\"".htmlentities($player[1]['name'])."\" />\n".
" <area shape=\"circle\" coords=\"".$player[2]['x'].",".$player[2]['y'].",6\" alt=\"".htmlentities($player[2]['name']).
"\" href=\"playerview.php?player=".urlencode($player[2]['name'])."\" title=\"".htmlentities($player[2]['name'])."\" />\n".
" <area shape=\"circle\" coords=\"".$player[3]['x'].",".$player[3]['y'].",6\" alt=\"".htmlentities($player[3]['name']).
"\" href=\"playerview.php?player=".urlencode($player[3]['name'])."\" title=\"".htmlentities($player[3]['name'])."\" />\n".
" <area shape=\"circle\" coords=\"".$player[4]['x'].",".$player[4]['y'].",6\" alt=\"".htmlentities($player[4]['name']).
"\" href=\"playerview.php?player=".urlencode($player[4]['name'])."\" title=\"".htmlentities($player[4]['name'])."\" />\n".
" </map>\n";
}
else echo "<br />\n";
}
echo " <br />\n";
include("footer.php");
?>

BIN
irpg/tablegrad.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 829 B

BIN
irpg/up.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 88 B

27
irpg/worldmap.php Normal file
View File

@@ -0,0 +1,27 @@
<?
include("config.php");
$irpg_page_title = "World Map";
include("header.php");
?>
<h1>World Map</h1>
<p>[offline users are red, online users are blue]</p>
<div id="map">
<img src="makeworldmap.php" alt="IdleRPG World Map" title="IdleRPG World Map" usemap="#world" border="0" />
<map id="world" name="world">
<?
$file = fopen($irpg_db,"r");
fgets($file);
while($location=fgets($file)) {
list($who,,,,,,,,,,$x,$y) = explode("\t",trim($location));
print " <area shape=\"circle\" coords=\"".$x.",".$y.",4\" alt=\"".htmlentities($who).
"\" href=\"playerview.php?player=".urlencode($who)."\" title=\"".htmlentities($who)."\" />\n";
}
fclose($file);
?>
</map>
</div>
<?include("footer.php");?>

82
irpg/xml.php Normal file
View File

@@ -0,0 +1,82 @@
<?php
header("Content-Type: text/xml");
header("Pragma: no-cache");
include("config.php");
$_GET['player'] = substr($_GET['player'],0,30);
/* Determine if a Player was entered. If not, redirect. */
if ($_GET['player']=="") header('Location: http://'.$_SERVER['SERVER_NAME'].
($_SERVER['SERVER_PORT']!=80?':'.$_SERVER['SERVER_PORT']:'').$BASEURL.
'players.php');
$file = fopen($irpg_db,"r");
fgets($file,1024); // skip top comment
while ($line=fgets($file,1024)) {
if (substr($line,0,strlen($_GET['player'])+1) == $_GET['player']."\t") {
list($user,,$isadmin,$level,$class,$secs,,$uhost,$online,$idled,
$x,$y,
$pen['mesg'],
$pen['nick'],
$pen['part'],
$pen['kick'],
$pen['quit'],
$pen['quest'],
$pen['logout'],
$created,
$lastlogin,
$item['amulet'],
$item['charm'],
$item['helm'],
$item['boots'],
$item['gloves'],
$item['ring'],
$item['leggings'],
$item['shield'],
$item['tunic'],
$item['weapon'],
$alignment,
) = explode("\t",trim($line));
break;
}
}
fclose($file);
echo "<?xml version=\"1.0\"?>";
?>
<player>
<username><?php print $user?></username>
<isadmin><?php print $isadmin?></isadmin>
<level><?php print $level?></level>
<class><?php print $class?></class>
<ttl><?php print $secs?></ttl>
<userhost><?php print $uhost?></userhost>
<online><?php print $online?></online>
<totalidled><?php print $idled?></totalidled>
<xpos><?php print $x?></xpos>
<ypos><?php print $y?></ypos>
<alignment><?php print $alignment?></alignment>
<penalties>
<?php
$sum=0;
foreach ($pen as $key => $val) {
echo " <$key>$val</$key>\n";
$sum += $val;
}
echo " <total>$sum</total>\n";
?>
</penalties>
<items>
<?php
$sum=0;
foreach ($item as $key => $val) {
echo " <$key>$val</$key>\n";
$sum += $val;
}
echo " <total>$sum</total>\n";
?>
</items>
</player>