changeset 524:e07d25a45736

Add an old_rollers plugin that will load up all the rollers I dont wana convert
author digitalxero
date Mon, 22 Mar 2010 14:55:37 -0600
parents 9045ef54e8e7
children 9cc87beb6dbd
files plugins/old_rollers/__init__.py plugins/old_rollers/gurps.py plugins/old_rollers/hero.py plugins/old_rollers/runequest.py plugins/old_rollers/savage.py plugins/old_rollers/sr4.py plugins/xxold_rollers.py
diffstat 7 files changed, 2395 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/old_rollers/__init__.py	Mon Mar 22 14:55:37 2010 -0600
@@ -0,0 +1,8 @@
+import os, os.path
+
+rollers = 'plugins.old_rollers'
+rollers_path = __import__(rollers, {}, {}, [rollers.split('.')[-1]]).__path__
+
+for roller in os.listdir(os.path.abspath(os.path.dirname(__file__))):
+    if roller.endswith('.py') and not roller.startswith('_'):
+        __import__("%s.%s" % (rollers, roller.split('.')[0]))
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/old_rollers/gurps.py	Mon Mar 22 14:55:37 2010 -0600
@@ -0,0 +1,697 @@
+#This program is free software; you can redistribute it and/or
+#modify it under the terms of the GNU General Public License
+#as published by the Free Software Foundation; either version 2
+#of the License, or (at your option) any later version.
+#
+#This program is distributed in the hope that it will be useful,
+#but WITHOUT ANY WARRANTY; without even the implied warranty of
+#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#GNU General Public License for more details.
+#
+#You should have received a copy of the GNU General Public License
+#along with this program; if not, write to the Free Software
+#Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+# --
+#
+# File: gurps.py
+# Version:
+#   $Id: gurps.py,v 1.3
+#
+# Description: Modified Hero System die roller based on DJM and Heroman's Hero
+# dieroller
+#
+# GURPS is a trademark of Steve Jackson Games, and its rules and art are
+# copyrighted by Steve Jackson Games. All rights are reserved by Steve Jackson
+# Games. This game aid is the original creation of Naryt with help from Pyrandon
+# and is released for free distribution, and not for resale, under the
+# permissions granted in the Steve Jackson Games Online Policy.
+# http://www.sjgames.com/general/online_policy.html
+#
+# Errors should be reported to rpg@ormonds.net
+#
+# Changelog:
+# V 1.3  2007/03/23  Thomas M. Edwards <tmedwards@motoslave.net>
+#   Fixed gurpsskill, gurpsdefaultskill, and gurpssupernatural to correctly
+#   return a normal failure when the roll is 17 and the effective skill is 27+;
+#   previously, they would erroneously return a critical failure.  This fix also
+#   corrects the less serious issue whereby rolls of 17 and an effective skill
+#   of 17-26 would report "failure by X" instead of merely "failure", which is
+#   wrong as the only reason the roll failed was because a 17 was rolled, not
+#   because the roll exceeded the effective skill.
+# V 1.2 29 October 2006, added defaultskill (Rule of 20 [B344]), supernatural
+#   (Rule of 16 [B349]).  The frightcheck roll is now the actual Fright Check
+#   (with Rule of 14 [B360]) and a lookup oon the Fright Check Table if needed.
+#   The fightcheckfail roll is the old Fright Check Table lookup.
+#   Removes the Help roller as it was nothing but trouble, see
+#   http://openrpg.wrathof.com/repository/GURPS/GURPS_Roller_1.7.xml for help
+#   in using this roller.
+# V 1 Original gurps release 2006/05/28 00:00:00, modified crit_hit, crit_headblow, crit_miss, crit_unarm, spellfail, frightcheck and help_me
+#       Corrects numerous descriptions
+# v.1 original gurps release by Naryt 2005/10/17 16:34:00
+
+from time import time, clock
+import random
+
+from std import std
+from orpg.dieroller.base import *
+
+
+__version__ = "$Id: gurps.py,v 1.5 2007/05/06 16:42:55 digitalxero Exp $"
+
+# gurps
+
+class gurps(std):
+    name = "gurps"
+
+    def __init__(self,source=[]):
+        std.__init__(self,source)
+
+# these methods return new die objects for specific options
+
+# Original msk roll renamed to be easier to understand/remember
+    def skill(self,skill,mod):
+        return gurpsskill(self,skill,mod)
+
+    def defaultskill(self,stat,defaultlevel,mod):
+        return gurpsdefaultskill(self,stat,defaultlevel,mod)
+
+    def supernatural(self,skill,resistance,mod):
+        return gurpssupernatural(self,skill,resistance,mod)
+
+    def crit_hit(self):
+        return gurpscrit_hit(self)
+
+    def crit_headblow(self):
+        return gurpscrit_headblow(self)
+
+    def crit_miss(self):
+        return gurpscrit_miss(self)
+
+    def crit_unarm(self):
+        return gurpscrit_unarm(self)
+
+    def spellfail(self):
+        return gurpsspellfail(self)
+
+    def frightcheck(self,level,mod):
+        return gurpsfrightcheck(self,level,mod)
+
+    def frightcheckfail(self,mod):
+        return gurpsfrightcheckfail(self,mod)
+
+die_rollers.register(gurps)
+
+class gurpsskill(std):
+    def __init__(self,source=[],skill=0,mod=0):
+        std.__init__(self,source)
+        self.skill = skill
+        self.mod = mod
+
+    def is_success(self):
+        return (((self.sum()) <= self.skill+self.mod) and (self.sum() < 17))
+
+    def __str__(self):
+        myStr = "[" + str(self.data[0])
+        for a in self.data[1:]:
+            myStr += ","
+            myStr += str(a)
+        myStr +="]"
+        myStr += " = <b>" + str(self.sum()) + "</b>"
+        myStr += " vs <b>(" + str(self.skill+self.mod) + ")</b>"
+
+        Diff = abs((self.skill+self.mod) - self.sum())
+
+        if self.is_success():
+            if self.sum() == 3 or self.sum() == 4:
+                myStr += " or less <font color='#ff0000'><b>Critical Success!</b></font> [B556]"
+            elif self.sum() == 5 and (self.skill+self.mod > 14):
+                myStr += " or less <font color='#ff0000'><b>Critical Success!</b> by " + str(Diff) +" </font> [B556]"
+            elif self.sum() == 6 and (self.skill+self.mod > 15):
+                myStr += " or less <font color='#ff0000'><b>Critical Success!</b> by " + str(Diff) +" </font> [B556]"
+            else:
+                myStr += " or less <font color='#ff0000'><b>Success!</b> by " + str(Diff) +" </font>"
+        else:
+            if self.sum() == 18:
+                myStr += " or less <font color='#ff0000'><b>Critical Failure!</b></font> [B556]"
+#            elif self.sum() == 17 and (self.skill+self.mod < 16):
+#                myStr += " or less <font color='#ff0000'><b>Critical Failure!</b></font> [B556]"
+            elif self.sum() == 17:
+                if (self.skill+self.mod) < 16:
+                    myStr += " or less <font color='#ff0000'><b>Critical Failure!</b></font> [B556]"
+                else:
+                    myStr += " or less <font color='#ff0000'><b>Failure!</b></font> [B556]"
+            elif  Diff > 9:
+                myStr += " or less <font color='#ff0000'><b>Critical Failure!</b> by " + str(Diff) +" </font> [B556]"
+            else:
+                myStr += " or less <font color='#ff0000'><b>Failure!</b> by " + str(Diff) +" </font>"
+
+        return myStr
+
+class gurpsdefaultskill(std):
+    def __init__(self,source=[],stat=0,defaultlevel=0,mod=0):
+        std.__init__(self,source)
+        self.stat = stat
+        self.defaultlevel = defaultlevel
+        self.mod = mod
+
+    def is_success(self):
+        if self.stat < 21:
+            intSkillVal = self.stat + self.defaultlevel + self.mod
+        else:
+            intSkillVal = 20 + self.defaultlevel + self.mod
+        return (((self.sum()) <= intSkillVal) and (self.sum() < 17))
+
+    def __str__(self):
+        myStr = "[" + str(self.data[0])
+        for a in self.data[1:]:
+            myStr += ","
+            myStr += str(a)
+        myStr +="]"
+        myStr += " = <b>" + str(self.sum()) + "</b>"
+        strRule = ""
+        if self.stat < 21:
+            intSkillVal = self.stat + self.defaultlevel + self.mod
+        else:
+            intSkillVal = 20 + self.defaultlevel + self.mod
+            strRule = "<br />Rule of 20 in effect [B173, B344]"
+
+        myStr += " vs <b>(" + str(intSkillVal) + ")</b>"
+
+        Diff = abs((intSkillVal) - self.sum())
+
+        if self.is_success():
+            if self.sum() == 3 or self.sum() == 4:
+                myStr += " or less <font color='#ff0000'><b>Critical Success!</b></font> [B556]"
+            elif self.sum() == 5 and (intSkillVal > 14):
+                myStr += " or less <font color='#ff0000'><b>Critical Success!</b> by " + str(Diff) +"</font> [B556]"
+            elif self.sum() == 6 and (intSkillVal > 15):
+                myStr += " or less <font color='#ff0000'><b>Critical Success!</b> by " + str(Diff) +"</font> [B556]"
+            else:
+                myStr += " or less <font color='#ff0000'><b>Success!</b> by " + str(Diff) +"</font>"
+        else:
+            if self.sum() == 18:
+                myStr += " or less <font color='#ff0000'><b>Critical Failure!</b></font> [B556]"
+            elif self.sum() == 17:
+                if intSkillVal < 16:
+                    myStr += " or less <font color='#ff0000'><b>Critical Failure!</b></font> [B556]"
+                else:
+                    myStr += " or less <font color='#ff0000'><b>Failure!</b></font> [B556]"
+            elif  Diff > 9:
+                myStr += " or less <font color='#ff0000'><b>Critical Failure!</b> by " + str(Diff) +"</font> [B556]"
+            else:
+                myStr += " or less <font color='#ff0000'><b>Failure!</b> by " + str(Diff) +"</font>"
+
+        myStr += strRule
+        return myStr
+
+class gurpssupernatural(std):
+    def __init__(self,source=[],skill=0,resistance=0,mod=0):
+        std.__init__(self,source)
+        self.skill = skill
+        self.resistance = resistance
+        self.mod = mod
+
+    def is_success(self):
+        if self.skill+self.mod > 16:
+            if self.resistance > 16:
+                if self.resistance > self.skill+self.mod:
+                    newSkill = self.skill+self.mod
+                else:
+                    newSkill = self.resistance
+            else:
+                newSkill = 16
+        else:
+            newSkill = self.skill+self.mod
+        return (((self.sum()) <= newSkill) and (self.sum() < 17))
+
+    def __str__(self):
+        myStr = "[" + str(self.data[0])
+        for a in self.data[1:]:
+            myStr += ","
+            myStr += str(a)
+        myStr +="]"
+        myStr += " = <b>" + str(self.sum()) + "</b>"
+        strRule = ""
+        if self.skill+self.mod > 16:
+            if self.resistance > 16:
+                if self.resistance > self.skill+self.mod:
+                    newSkill = self.skill+self.mod
+                    strRule = "<br />Rule of 16:  Subject's Resistance is higher than skill, no change in skill [B349]"
+                else:
+                    newSkill = self.resistance
+                    strRule = "<br />Rule of 16:  Effective skill limited by subject's Resistance [B349]"
+            else:
+                newSkill = 16
+                strRule = "<br />Rule of 16:  Effective skill limited to 16 [B349]"
+        else:
+            newSkill = self.skill+self.mod
+        myStr += " vs <b>(" + str(newSkill) + ")</b>"
+
+        Diff = abs((newSkill) - self.sum())
+
+        if self.is_success():
+            if self.sum() == 3 or self.sum() == 4:
+                myStr += " or less <font color='#ff0000'><b>Critical Success!</b></font> [B556]"
+            elif self.sum() == 5 and (newSkill > 14):
+                myStr += " or less <font color='#ff0000'><b>Critical Success!</b> by " + str(Diff) +" </font> [B556]"
+            elif self.sum() == 6 and (newSkill > 15):
+                myStr += " or less <font color='#ff0000'><b>Critical Success!</b> by " + str(Diff) +" </font> [B556]"
+            else:
+                myStr += " or less <font color='#ff0000'><b>Success!</b> by " + str(Diff) +" </font>"
+        else:
+            if self.sum() == 18:
+                myStr += " or less <font color='#ff0000'><b>Critical Failure!</b></font> [B556]"
+            elif self.sum() == 17:
+                if newSkill < 16:
+                    myStr += " or less <font color='#ff0000'><b>Critical Failure!</b></font> [B556]"
+                else:
+                    myStr += " or less <font color='#ff0000'><b>Failure!</b></font> [B556]"
+            elif  Diff > 9:
+                myStr += " or less <font color='#ff0000'><b>Critical Failure!</b> by " + str(Diff) +" </font> [B556]"
+            else:
+                myStr += " or less <font color='#ff0000'><b>Failure!</b> by " + str(Diff) +" </font>"
+
+        myStr += strRule
+        return myStr
+
+class gurpscrit_hit(std):
+    def __init__(self,source=[],mod=0):
+        std.__init__(self,source)
+
+    def __str__(self):
+        myStr = "[" + str(self.data[0]) #Variable myStr holds text and first we put a [ into it and then adds the first die rolled
+        for a in self.data[1:]:             #This is a for loop.  It will do the next two lines of code for every die (except the first die which we handled in the line above) in the roll.
+            myStr += ","                  #Adds a comma after each die
+            myStr += str(a)           #Adds the value of each die.
+        myStr += "] = "                 #Adds ] = to the end of the string (note the += means append to whatever is already stored in the variable
+        myStr += str(self.sum())          #Finally we add the actual result of the roll and myStr contains something like [3,2,1] = 6
+
+        if self.sum() > 8 and self.sum() < 12:
+            myStr += " <font color='#ff0000'>The blow inflicts normal damage.</font> [B556]"
+        elif self.sum() == 12:
+            myStr += " <font color='#ff0000'>The blow inflicts normal damage, AND victim drops anything they hold--even if no damage penetrates DR.</font> [B556]"
+        elif self.sum() == 8:
+            myStr += " <font color='#ff0000'>Damage penetrating DR does double shock (-8 max) AND if it hits the victim's limb, it's crippled for 16-HT seconds (unless wound is enough to cripple permanently!).</font> [B556]"
+        elif self.sum() == 13 or self.sum() == 14 or self.sum() == 7:
+            myStr += " <font color='#ff0000'>If any damage penetrates DR, treat as major wound. See [B420] for major wounds.</font> [B556]"
+        elif self.sum() == 6 or self.sum() == 15:
+            myStr += " <font color='#ff0000'>The blow inflicts maximum normal damage.</font> [B556]"
+        elif self.sum() == 5 or self.sum() == 16:
+            myStr += " <font color='#ff0000'>The blow inflicts double damage.</font> [B556]"
+        elif self.sum() == 4 or self.sum() == 17:
+            myStr += " <font color='#ff0000'>The victim's DR protects at half value, rounded down, after applying any armor divisors.</font> [B556]"
+        elif self.sum() == 3 or self.sum() == 18 :
+            myStr += " <font color='#ff0000'>The blow inflicts triple damage.</font> [B556]"
+
+        return myStr
+
+class gurpscrit_headblow(std):
+    def __init__(self,source=[],mod=0):
+        std.__init__(self,source)
+
+    def __str__(self):
+        myStr = "[" + str(self.data[0]) #Variable myStr holds text and first we put a [ into it and then adds the first die rolled
+        for a in self.data[1:]:             #This is a for loop.  It will do the next two lines of code for every die (except the first die which we handled in the line above) in the roll.
+            myStr += ","                  #Adds a comma after each die
+            myStr += str(a)           #Adds the value of each die.
+        myStr += "] = "                 #Adds ] = to the end of the string (note the += means append to whatever is already stored in the variable
+        myStr += str(self.sum())          #Finally we add the actual result of the roll and myStr contains something like [3,2,1] = 6
+
+        if self.sum() > 8 and self.sum() < 12:
+            myStr += " <font color='#ff0000'>The blow inflicts normal damage.</font> [B556]"
+        elif self.sum() == 12 or self.sum() == 13:
+            myStr += " <font color='#ff0000'>Normal damage to the head, BUT if any penetrates DR victim is scarred (-1 to appearance, -2 if burning or corrosive attacks) OR, if <i>crushing</i> then victim deafened [see B422 for duration].</font> [B556]"
+        elif self.sum() == 8:
+            myStr += " <font color='#ff0000'>Normal damage to head, but victim knocked off balance: must Do Nothing until next turn (but can defend).</font> [B556]"
+        elif self.sum() == 14:
+            myStr += " <font color='#ff0000'>Normal damage to head, but victim drops their weapon.  If holding two weapons, roll randomly for which one is dropped.</font> [B556]"
+        elif self.sum() == 6 or self.sum() == 7:
+            myStr += " <font color='#ff0000'>If you aimed for face or skull, you hit an eye [B399];  otherwise, DR only half effective & if even 1 point damage penetrates it's a major wound [B420].  If you hit an eye and that should be impossible, treat as if a <b>4</b> were rolled, see [B556].</font> [B556]"
+        elif self.sum() == 15:
+            myStr += " <font color='#ff0000'>The blow inflicts maximum normal damage.</font> [B556]"
+        elif self.sum() == 16:
+            myStr += " <font color='#ff0000'>The blow inflicts double damage.</font> [B556]"
+        elif self.sum() == 4 or self.sum() == 5:
+            myStr += " <font color='#ff0000'>The victim's DR protects at half value, rounded up, after applying armor divisors AND if even 1 point penetrates it's a major wound [B420].</font> [B556]"
+        elif self.sum() == 17:
+            myStr += " <font color='#ff0000'>The victim's DR protects at half value, rounded up, after applying any armor divisors.</font> [B556]"
+        elif self.sum() == 3:
+            myStr += " <font color='#ff0000'>The blow inflicts maximum normal damage AND ignores all DR.</font> [B556]"
+        elif self.sum() == 18:
+            myStr += " <font color='#ff0000'>The blow inflicts triple damage.</font> [B556]"
+
+        return myStr
+
+class gurpscrit_miss(std):
+    def __init__(self,source=[],mod=0):
+        std.__init__(self,source)
+
+    def __str__(self):
+        myStr = "[" + str(self.data[0]) #Variable myStr holds text and first we put a [ into it and then adds the first die rolled
+        for a in self.data[1:]:             #This is a for loop.  It will do the next two lines of code for every die (except the first die which we handled in the line above) in the roll.
+            myStr += ","                  #Adds a comma after each die
+            myStr += str(a)           #Adds the value of each die.
+        myStr += "] = "                 #Adds ] = to the end of the string (note the += means append to whatever is already stored in the variable
+        myStr += str(self.sum())          #Finally we add the actual result of the roll and myStr contains something like [3,2,1] = 6
+
+        if self.sum() > 8 and self.sum() < 12:
+            myStr += " <font color='#ff0000'>You drop your weapon (& a <i>cheap</i> weapon breaks).</font> [B556]"
+        elif self.sum() == 12 or self.sum() == 8:
+            myStr += " <font color='#ff0000'>Your weapon turns in your hand;  must Ready it before it can be used again.</font> [B556]"
+        elif self.sum() == 13 or self.sum() == 7:
+            myStr += " <font color='#ff0000'>You lose your balance & can do nothing else (not even free actions) until next turn;  all defenses -2 until next turn.</font> [B556]"
+        elif self.sum() == 14:
+            yrdStr = str(int(random.uniform(1,7)))
+            myStr += " <font color='#ff0000'>A <i>swung</i> weapon flies from hand " + yrdStr + " yards (50% chance straight forward/backward) anyone on the target of the flying weapon makes a DX roll or takes half-damage; a <i>thrust</i> or <i>ranged</i> weapon is dropped (& a <i>cheap</i> weapon breaks).</font> [B556]"
+        elif self.sum() == 6:
+            myStr += " <font color='#ff0000'>You hit yourself in arm or leg (50/50 chance), doing half damage;  if impaling, piercing, or ranged attack, then roll again (if you hit yourself again then use that result).</font> [B556]"
+        elif self.sum() == 15:
+            myStr += " <font color='#ff0000'>You strain your shoulder!  Weapon arm crippled for 30 min;  do not drop weapon, but that arm is useless.</font> [B557]"
+        elif self.sum() == 16:
+            myStr += " <font color='#ff0000'>If <i>melee attack,</i>  you fall down!  If <i>ranged attack,</i> you lose your balance & can do nothing until next turn & all defenses -2 until next turn.</font> [B557]"
+        elif self.sum() == 5:
+            myStr += " <font color='#ff0000'>You hit yourself in the arm or leg (50/50 chance), doing normal damage;  if impaling, piercing, or ranged attack, then roll again (if you hit yourself again then use that result).</font> [B556]"
+        elif self.sum() == 4 or self.sum() == 3 or self.sum() == 17 or self.sum() == 18:
+            broke = int(random.uniform(3,19))
+            if broke >=5 and broke <=16:
+                brokestr = "it is dropped."
+            else:
+                brokestr = "the weapon also breaks!"
+            myStr += " <font color='#ff0000'>A normal weapon breaks [B485];  if solid crushing weapon OR fine, very fine, or magical weapon " + brokestr + "</font> [B556] Note, second for roll non-normal weapons already fingured into this result."
+
+        return myStr
+
+class gurpscrit_unarm(std):
+    def __init__(self,source=[],mod=0):
+        std.__init__(self,source)
+
+    def __str__(self):
+        myStr = "[" + str(self.data[0]) #Variable myStr holds text and first we put a [ into it and then adds the first die rolled
+        for a in self.data[1:]:             #This is a for loop.  It will do the next two lines of code for every die (except the first die which we handled in the line above) in the roll.
+            myStr += ","                  #Adds a comma after each die
+            myStr += str(a)           #Adds the value of each die.
+        myStr += "] = "                 #Adds ] = to the end of the string (note the += means append to whatever is already stored in the variable
+        myStr += str(self.sum())          #Finally we add the actual result of the roll and myStr contains something like [3,2,1] = 6
+
+        if self.sum() > 8 and self.sum() < 12:
+            myStr += " <font color='#ff0000'>You lose your balance;  you can do nothing else (not even free actions) until next turn, and all defenses -2 until next turn.</font> [B557]"
+        elif self.sum() == 12:
+            myStr += " <font color='#ff0000'>You trip; make a DX roll to avoid falling at -4 if kicking or twice the normal penatly for a technique that normally requires a DX to avoid injury on even a normal failure (e.g., Jump Kick).</font> [B557]"
+        elif self.sum() == 8:
+            myStr += " <font color='#ff0000'>You fall down!</font> [B557]"
+        elif self.sum() == 13:
+            myStr += " <font color='#ff0000'>You drop your guard:  all defenses -2 for the next turn & any Evaluate bonus or Feint penalties against you are doubled.  This is obvious to those around you.</font> [B557]"
+        elif self.sum() == 7 or self.sum() == 14:
+            myStr += " <font color='#ff0000'>You stumble:  <i>If attacking,</i> you advance one yard past opponent with them behind you (you are facing away); <i>if parrying</i> you fall down!</font> [B557]"
+        elif self.sum() == 15:
+            mslStr = str(int(random.uniform(1,4)))
+            myStr += " <font color='#ff0000'>You tear a muscle; " + mslStr + " HT damage to the limb used to attack (to one limb if two used to attack), & -3 to use it (-1 w/high pain thresh); also all atacks & defenses -1 until next turn.  If neck was injured -3 (-1 w/high pain thresh) applies to ALL actions.</font> [B557]"
+        elif self.sum() == 6:
+            myStr += " <font color='#ff0000'>You hit a solid object (wall, floor, etc.) & take crushing damage equalt to 1/2 of (your thrusting damage - your DR) (<i>EXCEPTION:</i> If attacking with natural weapons, such as claws or teeth, they <i>break</i> -1 damage on future attacks until you heal (for recovery, B422).</font> [B557]"
+        elif self.sum() == 5 or self.sum() == 16:
+            myStr += " <font color='#ff0000'>You hit a solid object (wall, floor, etc.) & take crushing damage = your thrusting damage - your DR (<i>EXCEPTION:</i> if opponent using impaling weapon, you fall on it & take damage based on your ST).  If attacking an opponent who is using an impaling weapon, you fall on <i>his weapon</i>.  You suffer the weapon's normal damage based on <i>your</i> <b>ST</b>.</font> [B557]"
+        elif self.sum() == 4:
+            myStr += " <font color='#ff0000'>If attacking or parrying with a limb, you strain the limb:  1 HP damage & it's crippled for 30 min. If biting, butting, etc., have moderate neck pain (B428) for next 20-HT min minimum of 1 minute.</font> [B557]"
+        elif self.sum() == 17:
+            myStr += " <font color='#ff0000'>If attacking or parrying with a limb, you strain the limb:  1 HP damage & it's crippled for 30 min. If IQ 3-5 animal, it loses its nerve & flees on next turn or surrenders if cornered.</font> [B557]"
+        elif self.sum() == 3 or self.sum() == 18 :
+            myStr += " <font color='#ff0000'>You knock yourself out!  Roll vs. HT every 30 min. to recover.</font> [B557]"
+
+        return myStr
+
+class gurpsspellfail(std):
+    def __init__(self,source=[],mod=0):
+        std.__init__(self,source)
+
+    def __str__(self):
+        myStr = "[" + str(self.data[0])
+        for a in self.data[1:]:
+            myStr += ","
+            myStr += str(a)
+        myStr +="]"
+        myStr += " = <b>" + str(self.sum()) + "</b>"
+
+        if self.sum() == 10 or self.sum() == 11:
+            myStr += " <font color='#ff0000'>Spell produces nothing but a loud noise, bright flash, awful odor, etc.</font> [B236]"
+        elif self.sum() == 9:
+            myStr += " <font color='#ff0000'>Spell fails entirely.  Caster is stunned (IQ roll to recover).</font> [B236]"
+        elif self.sum() == 12:
+            myStr += " <font color='#ff0000'>Spell produces a weak and useless shadow of the intended effect.</font> [B236]"
+        elif self.sum() == 8:
+            myStr += " <font color='#ff0000'>Spell fails entirely.  Caster takes 1 point of damage.</font> [B236]"
+        elif self.sum() == 13:
+            myStr += " <font color='#ff0000'>Spell produces the reverse of the intended effect.</font> [B236]"
+        elif self.sum() == 7:
+            myStr += " <font color='#ff0000'>Spell affects someone or something other than the intended subject.</font> [B236]"
+        elif self.sum() == 14:
+            myStr += " <font color='#ff0000'>Spell seems to work, but it is only a useless illusion.</font> [B236]"
+        elif self.sum() == 5 or self.sum() == 6:
+            myStr += " <font color='#ff0000'>Spell is cast on one of the caster's companions (if harmful) or a random nearby foe (if beneficial).</font> [B236]"
+        elif self.sum() == 15 or self.sum() == 16:
+            myStr += " <font color='#ff0000'>Spell has the reverse of the intended, on the wrong target.  Roll randomly.</font> [B236]"
+        elif self.sum() == 4:
+            myStr += " <font color='#ff0000'>Spell is cast on caster (if harmful) or on a random nearby foe (if beneficial).</font> [B236]"
+        elif self.sum() == 17:
+            myStr += " <font color='#ff0000'>Spell fails entirely.  Caster temporarily forgets the spell.  Make a weekly IQ roll (after a week passes) until the spell is remembered.</font> [B236]"
+        elif self.sum() == 3:
+            myStr += " <font color='#ff0000'>Spell fails entirely.  Caster takes 1d of injury.</font> [B236]"
+        elif self.sum() == 18:
+            myStr += " <font color='#ff0000'>Spell fails entirely.  A demon or other malign entity appears and attacks the caster.  (GM may waive this if the caster and spell were both lily-white, pure good in intent.)</font> [B236]"
+
+        return myStr
+
+class gurpsfrightcheck(std):
+    def __init__(self,source=[],skill=0,mod=0):
+        std.__init__(self,source)
+        self.skill = skill
+        self.mod = mod
+
+    def is_success(self):
+        return (((self.sum()) <= self.skill+self.mod) and (self.sum() < 14))
+
+    def __str__(self):
+        myStr = "[" + str(self.data[0])
+        for a in self.data[1:]:
+            myStr += ","
+            myStr += str(a)
+        myStr +="]"
+        myStr += " = <b>" + str(self.sum()) + "</b>"
+
+        if self.skill+self.mod < 14:
+            myStr += " vs <b>(" + str(self.skill+self.mod) + ")</b>"
+            Diff = abs((self.skill+self.mod) - self.sum())
+        else:
+            myStr += " vs <b>(13)</b>"
+            Diff = abs(13 - self.sum())
+
+        if self.is_success():
+            if self.sum() == 3 or self.sum() == 4:
+                myStr += " or less <font color='#ff0000'><b>Critical Success!</b></font> [B556]"
+            else:
+                myStr += " or less <font color='#ff0000'><b>Success!</b> by " + str(Diff) +" </font>"
+        else:
+            myStr += " or less <font color='#ff0000'><b>Failure!</b> by " + str(Diff) +" </font>"
+
+        if self.skill + self.mod > 13:
+            myStr += " Rule of 14 in effect [B360]"
+
+        if not(self.is_success()):
+            intD1 = int(random.uniform(1,7))
+            intD2 = int(random.uniform(1,7))
+            intD3 = int(random.uniform(1,7))
+            intFright = intD1 + intD2 + intD3 + Diff
+            myStr += "<br />Rolling on Fright Check Table<br />[" + str(intD1) + "," + str(intD2) + "," + str(intD3) + "] ==> " + str(intFright - Diff) + " +  " + str(Diff) + " = " + str(intFright) + "<br />"
+            if intFright < 6:
+                myStr += "<font color='#ff0000'>Stunned for one second, then recover automatically.</font> [B360]"
+            elif intFright < 8:
+                myStr += "<font color='#ff0000'>Stunned for one second.  Every second after that, roll vs. unmodified Will to snap out of it.</font> [B360]"
+            elif intFright < 10:
+                myStr += "<font color='#ff0000'>Stunned for one second.  Every second after that, roll vs. Will, plus whatever bonuses or penalties you had on your original roll, to snap out of it.</font> [B360]"
+            elif intFright == 10:
+                strStun = str(int(random.uniform(1,7)))
+                myStr += "<font color='#ff0000'>Stunned for " + strStun + " seconds.  Every second after that, roll vs. Will, plus whatever bonuses or penalties you had on your original roll, to snap out of it.</font> [B360]"
+            elif intFright == 11:
+                strStun = str(int(random.uniform(2,13)))
+                myStr += "<font color='#ff0000'>Stunned for " + strStun + " seconds.  Every second after that, roll vs. Will, plus whatever bonuses or penalties you had on your original roll, to snap out of it.</font> [B361]"
+            elif intFright == 12:
+                myStr += "<font color='#ff0000'>Lose your lunch.  Treat this as retching for (25-HT) seconds, and then roll vs. HT each second to recover [B428].</font> [B361]"
+            elif intFright == 13:
+                myStr += "<font color='#ff0000'>Acquire a new mental quirk.</font> [B361]"
+            elif intFright < 16:
+                strFP = str(int(random.uniform(1,7)))
+                strSeconds = str(int(random.uniform(1,7)))
+                myStr += "<font color='#ff0000'>Lose " + strFP + " FP, and stunned for " + strSeconds + " seconds.  Every second after that, roll vs. Will, plus whatever bonuses or penalties you had on your original roll, to snap out of it.</font> [B361]"
+            elif intFright == 16:
+                strSeconds = str(int(random.uniform(1,7)))
+                myStr += "<font color='#ff0000'>Stunned for " + strSeconds + " seconds.  Every second after that, roll vs. Will, plus whatever bonuses or penalties you had on your original roll, to snap out of it.  Acquire a new mental quirk.</font> [B361]"
+            elif intFright == 17:
+                strMinutes = str(int(random.uniform(1,7)))
+                myStr += "<font color='#ff0000'>Faint for " + strMinutes + " minutes.  Every minute after that roll vs. HT to recover.</font> [B361]"
+            elif intFright == 18:
+                strMinutes = str(int(random.uniform(1,7)))
+                myStr += "<font color='#ff0000'>Faint for " + strMinutes + " minutes and roll vs. HT immediately.  On a failed roll, take 1 HP of injury as you collapse.  Every minute after that roll vs. HT to recover.</font> [B361]"
+            elif intFright == 19:
+                strMinutes = str(int(random.uniform(2,13)))
+                myStr += "<font color='#ff0000'>Severe faint, lasting for " + strMinutes + " minutes.  Every minute after that roll vs. HT to recover.  Take 1 HP of injury.</font> [B361]"
+            elif intFright == 20:
+                strMinutes = str(int(random.uniform(4,25)))
+                strFP = str(int(random.uniform(1,7)))
+                myStr += "<font color='#ff0000'>Faint bordering on shock, lastering for " + strMinutes + " minutes.  Also, lose " + strFP + " FP.</font> [B361]"
+            elif intFright == 21:
+                strMinutes = str(int(random.uniform(1,7)))
+                myStr += "<font color='#ff0000'>Panic.  You run around screaming, sit down and cry, or do something else equally pointless for " + strMinutes + " minutes.  Every minute after that, roll vs. unmodified Will to snap out of it.</font> [B361]"
+            elif intFright == 22:
+                myStr += "<font color='#ff0000'>Acquire a new -10-point Delusion (B130).</font> [B361]"
+            elif intFright == 23:
+                myStr += "<font color='#ff0000'>Acquire a new -10-point Phobia (B148) or other -10-point mental disadvantage.</font> [B361]"
+            elif intFright == 24:
+                myStr += "<font color='#ff0000'>Major physical effect, set by the GM: hair turns white, age five years overnight, go partially deaf, etc.  (Acquire -15 points worth of physical disadvantages.  Each year of aging = -3 points.)</font> [B361]"
+            elif intFright == 25 :
+                myStr += "<font color='#ff0000'>If you already have a Phobia or other mental disadvantage that is logically related to the frightening incident, your self-control number becomes one step worse.  If not, or if your self-control number is already 6, add a new -10-point Phobia or other -10-point mental disadvantage.</font> [B361]"
+            elif intFright == 26:
+                strMinutes = str(int(random.uniform(1,7)))
+                myStr += "<font color='#ff0000'>Faint for " + strMinutes + " minutes and roll vs. HT immediately.  On a failed roll, take 1 HP of injury as you collapse.  Every minute after that roll vs. HT to recover.  Also acquire a new -10-point Delusion (B130).</font> [B361]"
+            elif intFright == 27:
+                strMinutes = str(int(random.uniform(1,7)))
+                myStr += "<font color='#ff0000'>Faint for " + strMinutes + " minutes and roll vs. HT immediately.  On a failed roll, take 1 HP of injury as you collapse.  Every minute after that roll vs. HT to recover.  Also acquire a new -10-point Phobia (B148) or other -10-point mental disadvantage.</font> [B361]"
+            elif intFright == 28:
+                myStr += "<font color='#ff0000'>Light coma.  You fall unconscious, rolling vs. HT every 30 minutes to recover.  For 6 hours after you come to, all skill rolls and attribute checks are at -2.</font> [B361]"
+            elif intFright == 29:
+                strHours = str(int(random.uniform(1,7)))
+                myStr += "<font color='#ff0000'>Coma.  You fall unconcious for " + strHours + " hours.  At the end of the " + strHours + " hours, roll vs. HT to recover.  Continue to roll every " + strHours + " hours until you recover.</font> [B361]"
+            elif intFright == 30:
+                strDays = str(int(random.uniform(1,7)))
+                myStr += "<font color='#ff0000'>Catatonia.  Stare into space for " + strDays + " days.  Then roll vs. HT.  On a failed roll, remain catatonic for another " + strDays + " days, and so on.  If you have no medical care, lose 1 HP the first day, 2 HP the second day and so on.  If you survive and awaken, all skill rolls and attribute checks are at -2 for as many days as the catatonia lasted.</font> [B361]"
+            elif intFright == 31:
+                strMinutes = str(int(random.uniform(1,7)))
+                strFP = str(int(random.uniform(1,7)))
+                strInjury = str(int(random.uniform(1,7)))
+                myStr += "<font color='#ff0000'>Seizure.  You lose control of your body and fall to the ground in a fit lasting " + strMinutes + " minutes and costing " + strFP + " FP.  Also, roll vs. HT.  On a failure, take " + strInjury + " HP of injury.  On a critical failure, you also lose 1 HT <i>permanently</i>.</font> [B361]"
+            elif intFright == 32:
+                strInjury = str(int(random.uniform(2,13)))
+                myStr += "<font color='#ff0000'>Stricken.  You fall to the ground, taking " + strInjury + " HP of injury in the form of a mild heart attack or stroke.</font> [B361]"
+            elif intFright == 33:
+                myStr += "<font color='#ff0000'>Total panic.  You are out of control; you might do anything (GM rolls 3d: the higher the roll, the more useless your reaction).  For instance, you might jump off a cliff to avoid the monster.  If you survive your first reaction, roll vs. Will to come out of the panic.  If you fail, the GM rolls again for another panic reaction, and so on!</font> [B361]"
+            elif intFright == 34:
+                myStr += "<font color='#ff0000'>Acquire a new -15-point Delusion (B130).</font> [B361]"
+            elif intFright == 35:
+                myStr += "<font color='#ff0000'>Acquire a new -15-point Phobia (B148) or other -15-point mental disadvantage.</font> [B361]"
+            elif intFright == 36:
+                myStr += "<font color='#ff0000'>Severe physical effect, set by the GM.  (Acquire -20 points worth of physical disadvantages, aging = -3 per year).</font> [B361]"
+            elif intFright == 37:
+                myStr += "<font color='#ff0000'>Severe physical effect, set by the GM.  (Acquire -30 points worth of physical disadvantages, aging = -3 per year).</font> [B361]"
+            elif intFright == 39:
+                strHours = str(int(random.uniform(1,7)))
+                myStr += "<font color='#ff0000'>Coma.  You fall unconcious for " + strHours + " hours.  At the end of the " + strHours + " hours, roll vs. HT to recover.  Continue to roll every " + strHours + " hours until you recover.  Also acquire a new -15-point Delusion (B130).</font> [B361]"
+            elif intFright == 39:
+                strHours = str(int(random.uniform(1,7)))
+                myStr += "<font color='#ff0000'>Coma.  You fall unconcious for " + strHours + " hours.  At the end of the " + strHours + " hours, roll vs. HT to recover.  Continue to roll every " + strHours + " hours until you recover.  Also acquire a new -15-point Phobia (B148) or other -15-point mental disadvantage.</font> [B361]"
+            else:
+                strHours = str(int(random.uniform(1,7)))
+                myStr += "<font color='#ff0000'>Coma.  You fall unconcious for " + strHours + " hours.  At the end of the " + strHours + " hours, roll vs. HT to recover.  Continue to roll every " + strHours + " hours until you recover.  Also acquire a new -15-point Phobia (B148) or other -15-point mental disadvantage.  Also lose 1 point of IQ <i>permanently</i>.  This automatically reduces all IQ-based skill, including magic spells, by 1.</font> [B361]"
+        return myStr
+
+class gurpsfrightcheckfail(std):
+    def __init__(self,source=[],mod=0):
+        std.__init__(self,source)
+        self.mod = mod
+
+    def __str__(self):
+        myStr = "[" + str(self.data[0])
+        for a in self.data[1:]:
+            myStr += ","
+            myStr += str(a)
+        myStr +="] + " + str(self.mod)
+        intFright = self.sum() + self.mod
+        myStr += " = <b>" + str(intFright) + "</b> "
+
+        if intFright < 6:
+            myStr += "<font color='#ff0000'>Stunned for one second, then recover automatically.</font> [B360]"
+        elif intFright < 8:
+            myStr += "<font color='#ff0000'>Stunned for one second.  Every second after that, roll vs. unmodified Will to snap out of it.</font> [B360]"
+        elif intFright < 10:
+            myStr += "<font color='#ff0000'>Stunned for one second.  Every second after that, roll vs. Will, plus whatever bonuses or penalties you had on your original roll, to snap out of it.</font> [B360]"
+        elif intFright == 10:
+            strStun = str(int(random.uniform(1,7)))
+            myStr += "<font color='#ff0000'>Stunned for " + strStun + " seconds.  Every second after that, roll vs. Will, plus whatever bonuses or penalties you had on your original roll, to snap out of it.</font> [B360]"
+        elif intFright == 11:
+            strStun = str(int(random.uniform(2,13)))
+            myStr += "<font color='#ff0000'>Stunned for " + strStun + " seconds.  Every second after that, roll vs. Will, plus whatever bonuses or penalties you had on your original roll, to snap out of it.</font> [B361]"
+        elif intFright == 12:
+            myStr += "<font color='#ff0000'>Lose your lunch.  Treat this as retching for (25-HT) seconds, and then roll vs. HT each second to recover [B428].</font> [B361]"
+        elif intFright == 13:
+            myStr += "<font color='#ff0000'>Acquire a new mental quirk.</font> [B361]"
+        elif intFright < 16:
+            strFP = str(int(random.uniform(1,7)))
+            strSeconds = str(int(random.uniform(1,7)))
+            myStr += "<font color='#ff0000'>Lose " + strFP + " FP, and stunned for " + strSeconds + " seconds.  Every second after that, roll vs. Will, plus whatever bonuses or penalties you had on your original roll, to snap out of it.</font> [B361]"
+        elif intFright == 16:
+            strSeconds = str(int(random.uniform(1,7)))
+            myStr += "<font color='#ff0000'>Stunned for " + strSeconds + " seconds.  Every second after that, roll vs. Will, plus whatever bonuses or penalties you had on your original roll, to snap out of it.  Acquire a new mental quirk.</font> [B361]"
+        elif intFright == 17:
+            strMinutes = str(int(random.uniform(1,7)))
+            myStr += "<font color='#ff0000'>Faint for " + strMinutes + " minutes.  Every minute after that roll vs. HT to recover.</font> [B361]"
+        elif intFright == 18:
+            strMinutes = str(int(random.uniform(1,7)))
+            myStr += "<font color='#ff0000'>Faint for " + strMinutes + " minutes and roll vs. HT immediately.  On a failed roll, take 1 HP of injury as you collapse.  Every minute after that roll vs. HT to recover.</font> [B361]"
+        elif intFright == 19:
+            strMinutes = str(int(random.uniform(2,13)))
+            myStr += "<font color='#ff0000'>Severe faint, lasting for " + strMinutes + " minutes.  Every minute after that roll vs. HT to recover.  Take 1 HP of injury.</font> [B361]"
+        elif intFright == 20:
+            strMinutes = str(int(random.uniform(4,25)))
+            strFP = str(int(random.uniform(1,7)))
+            myStr += "<font color='#ff0000'>Faint bordering on shock, lastering for " + strMinutes + " minutes.  Also, lose " + strFP + " FP.</font> [B361]"
+        elif intFright == 21:
+            strMinutes = str(int(random.uniform(1,7)))
+            myStr += "<font color='#ff0000'>Panic.  You run around screaming, sit down and cry, or do something else equally pointless for " + strMinutes + " minutes.  Every minute after that, roll vs. unmodified Will to snap out of it.</font> [B361]"
+        elif intFright == 22:
+            myStr += "<font color='#ff0000'>Acquire a new -10-point Delusion (B130).</font> [B361]"
+        elif intFright == 23:
+            myStr += "<font color='#ff0000'>Acquire a new -10-point Phobia (B148) or other -10-point mental disadvantage.</font> [B361]"
+        elif intFright == 24:
+            myStr += "<font color='#ff0000'>Major physical effect, set by the GM: hair turns white, age five years overnight, go partially deaf, etc.  (Acquire -15 points worth of physical disadvantages.  Each year of aging = -3 points.)</font> [B361]"
+        elif intFright == 25 :
+            myStr += "<font color='#ff0000'>If you already have a Phobia or other mental disadvantage that is logically related to the frightening incident, your self-control number becomes one step worse.  If not, or if your self-control number is already 6, add a new -10-point Phobia or other -10-point mental disadvantage.</font> [B361]"
+        elif intFright == 26:
+            strMinutes = str(int(random.uniform(1,7)))
+            myStr += "<font color='#ff0000'>Faint for " + strMinutes + " minutes and roll vs. HT immediately.  On a failed roll, take 1 HP of injury as you collapse.  Every minute after that roll vs. HT to recover.  Also acquire a new -10-point Delusion (B130).</font> [B361]"
+        elif intFright == 27:
+            strMinutes = str(int(random.uniform(1,7)))
+            myStr += "<font color='#ff0000'>Faint for " + strMinutes + " minutes and roll vs. HT immediately.  On a failed roll, take 1 HP of injury as you collapse.  Every minute after that roll vs. HT to recover.  Also acquire a new -10-point Phobia (B148) or other -10-point mental disadvantage.</font> [B361]"
+        elif intFright == 28:
+            myStr += "<font color='#ff0000'>Light coma.  You fall unconscious, rolling vs. HT every 30 minutes to recover.  For 6 hours after you come to, all skill rolls and attribute checks are at -2.</font> [B361]"
+        elif intFright == 29:
+            strHours = str(int(random.uniform(1,7)))
+            myStr += "<font color='#ff0000'>Coma.  You fall unconcious for " + strHours + " hours.  At the end of the " + strHours + " hours, roll vs. HT to recover.  Continue to roll every " + strHours + " hours until you recover.</font> [B361]"
+        elif intFright == 30:
+            strDays = str(int(random.uniform(1,7)))
+            myStr += "<font color='#ff0000'>Catatonia.  Stare into space for " + strDays + " days.  Then roll vs. HT.  On a failed roll, remain catatonic for another " + strDays + " days, and so on.  If you have no medical care, lose 1 HP the first day, 2 HP the second day and so on.  If you survive and awaken, all skill rolls and attribute checks are at -2 for as many days as the catatonia lasted.</font> [B361]"
+        elif intFright == 31:
+            strMinutes = str(int(random.uniform(1,7)))
+            strFP = str(int(random.uniform(1,7)))
+            strInjury = str(int(random.uniform(1,7)))
+            myStr += "<font color='#ff0000'>Seizure.  You lose control of your body and fall to the ground in a fit lasting " + strMinutes + " minutes and costing " + strFP + " FP.  Also, roll vs. HT.  On a failure, take " + strInjury + " HP of injury.  On a critical failure, you also lose 1 HT <i>permanently</i>.</font> [B361]"
+        elif intFright == 32:
+            strInjury = str(int(random.uniform(2,13)))
+            myStr += "<font color='#ff0000'>Stricken.  You fall to the ground, taking " + strInjury + " HP of injury in the form of a mild heart attack or stroke.</font> [B361]"
+        elif intFright == 33:
+            myStr += "<font color='#ff0000'>Total panic.  You are out of control; you might do anything (GM rolls 3d: the higher the roll, the more useless your reaction).  For instance, you might jump off a cliff to avoid the monster.  If you survive your first reaction, roll vs. Will to come out of the panic.  If you fail, the GM rolls again for another panic reaction, and so on!</font> [B361]"
+        elif intFright == 34:
+            myStr += "<font color='#ff0000'>Acquire a new -15-point Delusion (B130).</font> [B361]"
+        elif intFright == 35:
+            myStr += "<font color='#ff0000'>Acquire a new -15-point Phobia (B148) or other -15-point mental disadvantage.</font> [B361]"
+        elif intFright == 36:
+            myStr += "<font color='#ff0000'>Severe physical effect, set by the GM.  (Acquire -20 points worth of physical disadvantages, aging = -3 per year).</font> [B361]"
+        elif intFright == 37:
+            myStr += "<font color='#ff0000'>Severe physical effect, set by the GM.  (Acquire -30 points worth of physical disadvantages, aging = -3 per year).</font> [B361]"
+        elif intFright == 39:
+            strHours = str(int(random.uniform(1,7)))
+            myStr += "<font color='#ff0000'>Coma.  You fall unconcious for " + strHours + " hours.  At the end of the " + strHours + " hours, roll vs. HT to recover.  Continue to roll every " + strHours + " hours until you recover.  Also acquire a new -15-point Delusion (B130).</font> [B361]"
+        elif intFright == 39:
+            strHours = str(int(random.uniform(1,7)))
+            myStr += "<font color='#ff0000'>Coma.  You fall unconcious for " + strHours + " hours.  At the end of the " + strHours + " hours, roll vs. HT to recover.  Continue to roll every " + strHours + " hours until you recover.  Also acquire a new -15-point Phobia (B148) or other -15-point mental disadvantage.</font> [B361]"
+        else:
+            strHours = str(int(random.uniform(1,7)))
+            myStr += "<font color='#ff0000'>Coma.  You fall unconcious for " + strHours + " hours.  At the end of the " + strHours + " hours, roll vs. HT to recover.  Continue to roll every " + strHours + " hours until you recover.  Also acquire a new -15-point Phobia (B148) or other -15-point mental disadvantage.  Also lose 1 point of IQ <i>permanently</i>.  This automatically reduces all IQ-based skill, including magic spells, by 1.</font> [B361]"
+
+        return myStr
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/old_rollers/hero.py	Mon Mar 22 14:55:37 2010 -0600
@@ -0,0 +1,232 @@
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+# --
+#
+# File: Hero.py
+# Version:
+#   $Id: Hero.py,v .3 DJM & Heroman
+#
+# Description: Hero System die roller originally based on Posterboy's D20 Dieroller
+#
+# Changelog:
+# v.3 by Heroman
+# Added hl() to show hit location (+side), and hk() for Hit Location killing damage
+# (No random stun multiplier)
+# v.2 DJM
+# Removed useless modifiers from the Normal damage roller
+# Changed Combat Value roller and SKill roller so that positive numbers are bonuses,
+# negative numbers are penalties
+# Changed Killing damage roller to correct stun multiplier bug
+# Handled new rounding issues
+#
+# v.1 original release DJM
+
+__version__ = "$Id: hero.py,v 1.15 2006/11/04 21:24:19 digitalxero Exp $"
+
+from time import time, clock
+import random
+
+from std import std
+from orpg.dieroller.base import *
+
+# Hero stands for "Hero system" not 20 sided die :)
+
+class hero(std):
+    name = "hero"
+
+    def __init__(self,source=[]):
+        std.__init__(self,source)
+
+# these methods return new die objects for specific options
+
+    def k(self,mod):
+        return herok(self,mod)
+
+    def hl(self):
+        return herohl(self)
+
+    def hk(self):
+        return herohk(self)
+
+    def n(self):
+        return heron(self)
+
+    def cv(self,cv,mod):
+        return herocv(self,cv,mod)
+
+    def sk(self,sk,mod):
+        return herosk(self,sk,mod)
+
+die_rollers.register(hero)
+
+class herocv(std):
+    def __init__(self,source=[],cv=10,mod=0):
+        std.__init__(self,source)
+        self.cv = cv
+        self.mod = mod
+
+
+    def __str__(self):
+        myStr = "[" + str(self.data[0])
+        for a in self.data[1:]:
+            myStr += ","
+            myStr += str(a)
+        myStr += "] = (" + str(self.sum()) + ")"
+
+        myStr += " with a CV of " + str(self.cv)
+        myStr += " and a modifier of " + str(self.mod)
+        cvhit = 11 + self.cv - self.sum() + self.mod
+        myStr += " hits up to <b>DCV <font color='#ff0000'>" + str(cvhit) + "</font></b>"
+        return myStr
+
+class herosk(std):
+    def __init__(self,source=[],sk=11,mod=0):
+        std.__init__(self,source)
+        self.sk = sk
+        self.mod = mod
+
+    def is_success(self):
+        return (((self.sum()-self.mod) <= self.sk))
+
+    def __str__(self):
+        myStr = "[" + str(self.data[0])
+        for a in self.data[1:]:
+            myStr += ","
+            myStr += str(a)
+        strAdd="] - "
+        swapmod=self.mod
+        if self.mod < 0:
+            strAdd= "] + "
+            swapmod= -self.mod
+        myStr += strAdd + str(swapmod)
+        modSum = self.sum()-self.mod
+        myStr += " = (" + str(modSum) + ")"
+        myStr += " vs " + str(self.sk)
+
+        if self.is_success():
+            myStr += " or less <font color='#ff0000'>Success!"
+        else:
+            myStr += " or less <font color='#ff0000'>Failure!"
+
+        Diff = self.sk - modSum
+        myStr += " by " + str(Diff) +" </font>"
+
+        return myStr
+
+class herok(std):
+    def __init__(self,source=[],mod=0):
+        std.__init__(self,source)
+        self.mod = mod
+
+    def __str__(self):
+        myStr = "[" + str(self.data[0])
+        for a in self.data[1:]:
+            myStr += ","
+            myStr += str(a)
+        myStr += "] = (<font color='#ff0000'><b>" + str(int(round(self.sum()))) + "</b></font>)"
+        stunx = random.randint(1,6)-1
+        if stunx <= 1:
+            stunx = 1
+        myStr += " <b>Body</b> and a stunx of (" + str(stunx)
+        stunx = stunx + self.mod
+        myStr += " + " + str(self.mod)
+        stunsum = round(self.sum()) * stunx
+        myStr += ") for a total of (<font color='#ff0000'><b>" + str(int(stunsum)) + "</b></font>) <b>Stun</b>"
+        return myStr
+
+class herohl(std):
+    def __init__(self,source=[],mod=0):
+        std.__init__(self,source)
+        self.mod = mod
+
+    def __str__(self):
+        myStr = "[" + str(self.data[0])
+        side = random.randint(1,6)
+        sidestr = "Left "
+        if side >=4:
+            sidestr = "Right "
+        for a in self.data[1:]:
+            myStr += ","
+            myStr += str(a)
+        myStr += "] = (<font color='#ff0000'><b>" + str(int(round(self.sum()))) + "</b></font>) "
+        location = int(round(self.sum()))
+        if location <= 5:
+            myStr += "Location: <B>Head</B>, StunX:<B>x5</B>, NStun:<B>x2</B>, Bodyx:<B>x2</B>"
+        elif location == 6:
+            myStr += "Location: <B>" + sidestr + "Hand</B>, StunX:<B>x1</B>, NStun:<B>x1/2</B>, Bodyx:<B>x1/2</B>"
+        elif location == 7:
+            myStr += "Location: <B>" + sidestr + "Arm</B>, StunX:<B>x2</B>, NStun:<B>x1/2</B>, Bodyx:<B>x1/2</B>"
+        elif location == 8:
+            myStr += "Location: <B>" + sidestr + "Arm</B>, StunX:<B>x2</B>, NStun:<B>x1/2</B>, Bodyx:<B>x1/2</B>"
+        elif location == 9:
+            myStr += "Location: <B>" + sidestr + "Shoulder</B>, StunX:<B>x3</B>, NStun:<B>x1</B>, Bodyx:<B>x1</B>"
+        elif location == 10:
+            myStr += "Location: <B>Chest</B>, StunX:<B>x3</B>, NStun:<B>x1</B>, Bodyx:<B>x1</B>"
+        elif location == 11:
+            myStr += "Location: <B>Chest</B>, StunX:<B>x3</B>, NStun:<B>x1</B>, Bodyx:<B>x1</B>"
+        elif location == 12:
+            myStr += "Location: <B>Stomach</B>, StunX:<B>x4</B>, NStun:<B>x1 1/2</B>, Bodyx:<B>x1</B>"
+        elif location == 13:
+            myStr += "Location: <B>Vitals</B>, StunX:<B>x4</B>, NStun:<B>x1 1/2</B>, Bodyx:<B>x2</B>"
+        elif location == 14:
+            myStr += "Location: <B>" + sidestr + "Thigh</B>, StunX:<B>x2</B>, NStun:<B>x1</B>, Bodyx:<B>x1</B>"
+        elif location == 15:
+            myStr += "Location: <B>" + sidestr + "Leg</B>, StunX:<B>x2</B>, NStun:<B>x1/2</B>, Bodyx:<B>x1/2</B>"
+        elif location == 16:
+            myStr += "Location: <B>" + sidestr + "Leg</B>, StunX:<B>x2</B>, NStun:<B>x1/2</B>, Bodyx:<B>x1/2</B>"
+        elif location >= 17:
+            myStr += "Location: <B>" + sidestr + "Foot</B>, StunX:<B>x1</B>, NStun:<B>x1/2</B>, Bodyx:<B>x1/2</B>"
+        return myStr
+
+class herohk(std):
+    def __init__(self,source=[],mod=0):
+        std.__init__(self,source)
+        self.mod = mod
+
+    def __str__(self):
+        myStr = "[" + str(self.data[0])
+        for a in self.data[1:]:
+            myStr += ","
+            myStr += str(a)
+        myStr += "] = (<font color='#ff0000'><b>" + str(int(round(self.sum()))) + "</b></font>)"
+        stunx = 1
+        myStr += " <b>Body</b> "
+        stunx = stunx + self.mod
+        stunsum = round(self.sum()) * stunx
+        myStr += " for a total of (<font color='#ff0000'><b>" + str(int(stunsum)) + "</b></font>) <b>Stun</b>"
+        return myStr
+
+class heron(std):
+    def __init__(self,source=[],mod=0):
+        std.__init__(self,source)
+        self.bodtot=0
+
+    def __str__(self):
+        myStr = "[" + str(self.data[0])
+        if self.data[0] == 6:
+            self.bodtot=self.bodtot+2
+        else:
+            self.bodtot=self.bodtot+1
+        if self.data[0] <= 1:
+            self.bodtot=self.bodtot-1
+        for a in self.data[1:]:
+            myStr += ","
+            myStr += str(a)
+            if a == 6:
+                self.bodtot=self.bodtot+2
+            else:
+                self.bodtot=self.bodtot+1
+            if a <= 1:
+                self.bodtot=self.bodtot-1
+        myStr += "] = (<font color='#ff0000'><b>" + str(self.bodtot) + "</b></font>)"
+        myStr += " <b>Body</b> and "
+        myStr += "(<font color='#ff0000'><b>" + str(int(round(self.sum()))) + "</b></font>) <b>Stun</b>"
+        return myStr
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/old_rollers/runequest.py	Mon Mar 22 14:55:37 2010 -0600
@@ -0,0 +1,696 @@
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+#-------------------------------------------------------------------------
+#
+#  Usage:
+#
+#   Die  Roller: /dieroller rq
+#
+#   Skill  Roll: [1d100.skill(50,0,0)]         # ( skill%, modifer, MA% )
+#
+#   Parry  Roll: [1d100.parry(50,0,0,12)]      # ( skill%, modifer, MA%, Weapon/Shield AP )
+#
+#   Dodge  Roll: [1d100.parry(50,0,0)]         # ( skill%, modifer, MA% )
+#
+#   Attack Roll: [1d100.attack(50,0,0,2,9,3,0)]
+#       ( skill%, modifer, MA%, min weap dam, max weap dam, dam bonus, truesword )
+#
+#   Sorcery Roll: [1d100.sorcery(90,   0,   3,   6,   1,   1,    1)]
+#                               (sk, mod, pow, cer, int,  acc, mlt)
+#
+#
+#
+#   Skill Training Unlimited Roll: [1d100.trainskill(30,75)]       # (starting skill%, desired skill%)
+#   Skill Training Cost Limited:   [1d100.trainskillcost(1000, 50) # (payment, starting skill%)
+#   Skill Training Time Limited:   [1d100.trainskilltime(150, 50)  # (time, strting skill%)
+#
+#-------------------------------------------------------------------------
+# --
+#
+# File: rq.py
+# Version:
+#   $Id: rq.py,v .1 pelwer
+#
+# Description: Runequest die roller originally based on Heroman's Hero Dieroller
+#
+#
+# v.1 - pelwer - 2/5/2005
+#  o Original release
+# v.2 - pelwer - 10/30/2006
+#  o Ported to openrpg+ by removing dependance on whrandom
+#  o Fixed Riposte spelling
+#  o Deleted sorcalc - never used
+#  o Added Sorcery Fumble table to sorcery spell roller
+#
+
+__version__ = "$Id: runequest.py,v 1.4 2006/11/15 12:11:22 digitalxero Exp $"
+
+from time import time, clock
+import random
+from math import floor
+
+from std import std
+from orpg.dieroller.base import *
+
+# rq stands for "Runequest"
+
+class runequest(std):
+    name = "runequest"
+    def __init__(self,source=[]):
+        std.__init__(self,source)
+
+# these methods return new die objects for specific options
+
+    def skill(self,sk,mod,ma):
+        return rqskill(self,sk,mod,ma)
+
+    def parry(self,sk,mod,ma,AP):
+        return rqparry(self,sk,mod,ma,AP)
+
+    def dodge(self,sk,mod,ma):
+        return rqdodge(self,sk,mod,ma)
+
+    def attack(self,sk,mod,ma,mindam,maxdam,bondam,trueswd):
+        return rqattack(self,sk,mod,ma,mindam,maxdam,bondam,trueswd)
+
+    def sorcery(self,sk,mod,pow,cer,int,acc,mlt):
+        return rqsorcery(self,sk,mod,pow,cer,int,acc,mlt)
+
+    def trainskill(self,initial,final):
+        return rqtrainskill(self,initial,final)
+
+    def trainskillcost(self,cost,sk):
+        return rqtrainskillcost(self,cost,sk)
+
+    def trainskilltime(self,time,sk):
+        return rqtrainskilltime(self,time,sk)
+
+die_rollers.register(runequest)
+
+#  RQ Skill Training Cost/Time unlimited
+#
+# [1d100.trainskill(10,20)]
+#          initial skill%, final skill%
+#
+# sk    = skill %
+#
+#
+class rqtrainskill(std):
+    def __init__(self,source=[],initial=11,final=0):
+        std.__init__(self,source)
+        self.s = initial
+        self.f = final
+
+    def __str__(self):
+        myStr = "Unrestricted Training"
+
+        if self.s == 0:
+            myStr = "Initial training completed for Cost(50) Time(20) Skill(1 + modifier)"
+        else:
+            cost  = 0
+            time  = 0
+            myStr = "Training: "
+
+            while self.s < self.f and self.s < 75:
+                cost   += self.s * 5
+                time   += self.s * 1
+                self.s += random.uniform(1,4) + 1
+
+            myStr  = "Training completed:\n"
+            myStr += "\tCost(" + str(int(cost)) + ")\n"
+            myStr += "\tTime(" + str(int(time)) + ")\n"
+            myStr += "\tSkill(" + str(int(self.s)) + ")"
+
+        return myStr
+
+
+#  RQ Skill Training Cost Limited
+#
+# [1d100.trainskillcost(50,0)]
+#          cost, skill%
+#
+# cost  = cash for training
+# sk    = skill %
+#
+#
+class rqtrainskillcost(std):
+    def __init__(self,source=[],cost=11,sk=0):
+        std.__init__(self,source)
+        self.cost = cost
+        self.sk   = sk
+
+    def __str__(self):
+        myStr = ""
+
+        if self.sk == 0 and self.cost >= 50:
+            myStr = "Initial training completed for Cost(50), Time(50), Skill(1 + modifier)"
+        else:
+            cost  = 0
+            time  = 0
+            icost = self.sk * 5
+
+            myStr = "Training: "
+
+            while (cost + icost) < self.cost:
+                if self.sk >= 75:
+                    break
+
+                cost += icost
+                time += self.sk * 1
+                self.sk += random.uniform(1,4) + 1
+                icost = self.sk * 5
+
+            myStr  = "Training completed: "
+            myStr += "Cost(" + str(int(cost)) + ") "
+            myStr += "Time(" + str(int(time)) + ") "
+            myStr += "Skill(" + str(int(self.sk)) + ")"
+
+        return myStr
+
+
+#  RQ Skill Training Time Limited
+#
+# [1d100.trainskilltime(50,0)]
+#          time, skill%
+#
+# time  = time for training
+# sk    = skill %
+#
+#
+class rqtrainskilltime(std):
+    def __init__(self,source=[],time=11,sk=0):
+        std.__init__(self,source)
+        self.time = time
+        self.sk   = sk
+
+    def __str__(self):
+        myStr = ""
+
+        if self.sk == 0 and self.time >= 20:
+            myStr = "Initial training completed for Cost(50), Time(50), Skill(1 + modifier)"
+        else:
+            cost  = 0
+            time  = 0
+            itime = self.sk * 1
+
+            myStr = "Trainingsss: "
+
+            while (time + itime) < self.time:
+                if self.sk >= 75:
+                    break
+
+                cost += self.sk * 5
+                time += itime
+                self.sk += random.uniform(1,4) + 1
+                itime = self.sk * 5
+
+            myStr  = "Training completed: "
+            myStr += "Cost(" + str(int(cost)) + ") "
+            myStr += "Time(" + str(int(time)) + ") "
+            myStr += "Skill(" + str(int(self.sk)) + ")"
+
+        return myStr
+
+#  RQ Skill Roll
+#
+# [1d100.skill(50,0,0)]
+#          skill%, modifer, ma%
+#
+# sk    = skill %
+# mod   = modifier %
+# ma    = martial arts %
+# skill = sk + mod
+#
+# success   roll <= skill
+#
+# failure   roll > skill
+#
+# crit
+#     push( @{$::Cre{Weapons}{$weap_cnt}}, POSIX::floor( skill/20 ) );
+#
+# special
+#     push( @{$::Cre{Weapons}{$weap_cnt}}, POSIX::floor( $skill/5 ) );
+#
+# fumble: if ( $skill > 100 ) { $fum = 0; } else { $fum = 100 - $skill; }
+#             $fum = 100 - POSIX::floor( $fum/20 );
+#             if ( $fum == 100 ) { $fum = '00'; };
+#
+class rqskill(std):
+    def __init__(self,source=[],sk=11,mod=0,ma=0):
+        std.__init__(self,source)
+        self.sk  = sk
+        self.mod = mod
+        self.ma  = ma
+
+    def is_success(self):
+        return (((self.sum() <= (self.sk + self.mod)) or (self.sum() <= 5)) and (self.sum() <= 95))
+
+    def is_ma(self):
+        return (self.sum() <= self.ma)
+
+    def is_special(self):
+        return (self.sum() <= int(floor((self.sk + self.mod)/5)))
+
+    def is_critical(self):
+        return (self.sum() <= int(floor((self.sk + self.mod) / 20)))
+
+    def is_fumble(self):
+        if ( self.sk >= 100 ):
+            fum = 0
+        else:
+            fum = (100 - self.sk )
+        final_fum = ( 100 - int( floor( fum/20  ) ) )
+        return (  self.sum() >= final_fum )
+
+    def __str__(self):
+        strAdd="+"
+        swapmod= self.mod
+        if self.mod < 0:
+            strAdd= "-"
+            swapmod= -self.mod
+        modSum = self.sum()
+        # build output string
+        myStr = " (" + str(modSum) + ")"
+        myStr += " vs [" + str(self.sk) + strAdd + str(swapmod) + "]"
+
+        if self.is_fumble():
+            myStr += " <b><font color=red>Fumble!</font></b>"
+        elif self.is_critical():
+            myStr += " <b><font color=green>Critical!</font></b>"
+        elif self.is_special():
+            myStr += " <i><font color=green>Special!</font></i>"
+        elif self.is_success() and self.is_ma():
+            myStr += " <i><font color=green>Special!</font></i>"
+        elif self.is_success():
+            myStr += " <font color=blue>Success!</font>"
+        else:
+            myStr += " <font color=red>Failure!</font>"
+
+        Diff = self.sk - modSum
+        myStr += " </font>"
+
+        return myStr
+
+#
+# RQ Parry Roll
+#
+# same as skill but with fumble dice and armor points
+#
+# [1d100.parry(50,0,0,12)]
+#             skill%, modifer, ma%, Weapon AP
+#
+
+class rqparry(std):
+    def __init__(self,source=[],sk=11,mod=0,ma=0,AP=0):
+        std.__init__(self,source)
+        self.sk = sk
+        self.mod = mod
+        self.ma  = ma
+        self.AP = AP
+
+    def is_success(self):
+        return (((self.sum() <= (self.sk + self.mod)) or (self.sum() <= 5)) and (self.sum() <= 95))
+
+    def is_special(self):
+        return (self.sum() <= int(floor((self.sk + self.mod) / 5)))
+
+    def is_ma(self):
+        return (self.sum() <= self.ma)
+
+    def is_riposte(self):
+        return (self.sum() <= (self.ma / 5))
+
+    def is_critical(self):
+        return ( (  self.sum() <= int( floor( ( self.sk + self.mod  )/20 ) ) ) )
+
+    def is_fumble(self):
+        if ( self.sk >= 100 ):
+            fum = 0
+        else:
+            fum = (100 - self.sk )
+        final_fum = ( 100 - int( floor( fum/20  ) ) )
+        return (  self.sum() >= final_fum )
+
+    def __str__(self):
+
+        # get fumble roll result in case needed
+        fum_roll = random.randint(1,100)
+
+        # get special AP
+        spec_AP = int( floor ( self.AP * 1.5 ) )
+
+        # figure out +/- for modifer
+        strAdd="+"
+        swapmod= self.mod
+        if self.mod < 0:
+            strAdd= "-"
+            swapmod= -self.mod
+        modSum = self.sum()
+
+        # build output string
+        myStr = " (" + str(modSum) + ")"
+        myStr += " vs [" + str(self.sk) + strAdd + str(swapmod) + "]"
+
+        if self.is_fumble():
+            myStr += " <b><font color=red>Fumble!</font>  See Fumble Chart [" + str(fum_roll) + "]</b>"
+        elif self.is_critical() and self.is_riposte():
+            myStr += " <b><font color=green>Critical!</font> All damage blocked!</b>"
+            myStr += " Riposte next SR"
+        elif self.is_critical():
+            myStr += " <b><font color=green>Critical!</font> All damage blocked!</b>"
+        elif self.is_special and self.is_riposte():
+            myStr += " <i><font color=green>Special!</font> Weapon/Shield AP [" + str(spec_AP) + "]</i>"
+            myStr += " Riposte next SR"
+        elif self.is_special():
+            myStr += " <i><font color=green>Special!</font> Weapon/Shield AP [" + str(spec_AP) + "]</i>"
+        elif self.is_success() and self.is_ma():
+            myStr += " <i><font color=green>Special!</font> Weapon/Shield AP [" + str(spec_AP) + "]</i>"
+        elif self.is_success():
+            myStr += " <font color=blue>Success!</font> Weapon/Shield AP [" + str(self.AP) + "]"
+        else:
+            myStr += " <font color=red>Failure!</font>"
+
+        Diff = self.sk - modSum
+        myStr += " </font>"
+
+        return myStr
+
+# RQ Dodge Roll
+#
+# same as skill but with fumble dice and armor points
+#
+# [1d100.parry(50,0,0)]
+#             skill%, modifer, ma%
+#
+
+class rqdodge(std):
+    def __init__(self,source=[],sk=11,mod=0,ma=0,AP=0):
+        std.__init__(self,source)
+        self.sk = sk
+        self.mod = mod
+        self.ma  = ma
+        self.AP = AP
+
+    def is_success(self):
+        return (((self.sum() <= (self.sk + self.mod)) or (self.sum() <= 5)) and (self.sum() <= 95))
+
+    def is_special(self):
+        return (self.sum() <= int(floor((self.sk + self.mod) / 5)))
+
+    def is_ma(self):
+        return (self.sum() <= self.ma)
+
+    def is_riposte(self):
+        return (self.sum() <= (self.ma / 5))
+
+    def is_critical(self):
+        return ( (  self.sum() <= int( floor( ( self.sk + self.mod  )/20 ) ) ) )
+
+    def is_fumble(self):
+        if ( self.sk >= 100 ):
+            fum = 0
+        else:
+            fum = (100 - self.sk )
+        final_fum = ( 100 - int( floor( fum/20  ) ) )
+        return (  self.sum() >= final_fum )
+
+    def __str__(self):
+
+        # get fumble roll result in case needed
+        fum_roll = random.randint(1,100)
+
+        # get special AP
+        spec_AP = int( floor ( self.AP * 1.5 ) )
+
+        # figure out +/- for modifer
+        strAdd="+"
+        swapmod= self.mod
+        if self.mod < 0:
+            strAdd= "-"
+            swapmod= -self.mod
+        modSum = self.sum()
+
+        # build output string
+        myStr = " (" + str(modSum) + ")"
+        myStr += " vs [" + str(self.sk) + strAdd + str(swapmod) + "]"
+
+        if self.is_fumble():
+            myStr += " <b><font color=red>Fumble!</font>  See Fumble Chart [" + str(fum_roll) + "]</b>"
+        elif self.is_critical() and self.is_riposte():
+            myStr += " <b><font color=green>Critical!</font> All damage dodged!</b>"
+            myStr += " Riposte on next SR"
+        elif self.is_critical():
+            myStr += " <b><font color=green>Critical!</font> All damage dodged!</b>"
+        elif self.is_special and self.is_riposte():
+            myStr += " <i><font color=green>Special!</font> Damage dodged</b>"
+            myStr += " Riposte on next SR"
+        elif self.is_special():
+            myStr += " <i><font color=green>Special!</font> Damage dodged</b>"
+        elif self.is_success() and self.is_ma():
+            myStr += " <i><font color=green>Special!</font> Damage dodged</b>"
+        elif self.is_success():
+            myStr += " <font color=blue>Success!</font> Damage dodged</b>"
+        else:
+            myStr += " <font color=red>Failure!</font>"
+
+        Diff = self.sk - modSum
+        myStr += " </font>"
+
+        return myStr
+
+
+
+#
+# RQ Attack Roll
+#
+# same as skill but with fumble dice and armor points
+#
+# [1d100.attack(50,0,0,2,9,3,1)]
+#             skill%, modifer, ma%, min weap dam, max weap dam, dam bonus, truesword_enabled
+#
+class rqattack(std):
+    def __init__(self,source=[],sk=11,mod=0,ma=0,mindam=0,maxdam=0,bondam=0,trueswd=0):
+        std.__init__(self,source)
+        self.sk = sk
+        self.mod = mod
+        self.ma  = ma
+        self.mindam = mindam
+        self.maxdam = maxdam
+        self.bondam = bondam
+        self.trueswd = trueswd
+
+    def is_success(self):
+        return (((self.sum() <= (self.sk + self.mod)) or (self.sum() <= 5)) and (self.sum() <= 95))
+
+    def is_ma(self):
+        return (self.sum() <= self.ma)
+
+    def is_special(self):
+        return (self.sum() <= int(floor((self.sk + self.mod) / 5)))
+
+    def is_critical(self):
+        return ((self.sum() <= int(floor((self.sk + self.mod) / 20))))
+
+    def is_supercritical(self):
+        return (self.sum() == 1)
+
+    def is_fumble(self):
+        if ( self.sk >= 100 ):
+            fum = 0
+        else:
+            fum = (100 - self.sk )
+        final_fum = ( 100 - int( floor( fum/20  ) ) )
+        return (  self.sum() >= final_fum )
+
+    def __str__(self):
+
+        # get fumble roll result in case needed
+        fum_roll = random.randint(1,100)
+
+        # get hit location roll result in case needed
+        location = random.randint(1,20)
+        myStr = " to the ["+ str(location) + "] "
+        if location < 5:
+            myStr += "<B>Right Leg</B>"
+        elif location < 9:
+            myStr += "<B>Left Leg</B>"
+        elif location < 12:
+            myStr += "<B>Abdomen</B>"
+        elif location < 13:
+            myStr += "<B>Chest</B>"
+        elif location < 16:
+            myStr += "<B>Right Arm</B>"
+        elif location < 19:
+            myStr += "<B>Left Arm</B>"
+        else:
+            myStr += "<B>Head</B>"
+        hit_loc = myStr
+
+
+        # get normal damage in case needed
+        norm_damage = random.randint(self.mindam*(self.trueswd+1),self.maxdam*(self.trueswd+1)) + self.bondam
+        norm_damage_string  = "{" + str( self.mindam*(self.trueswd+1) ) + "-"
+        norm_damage_string += str(self.maxdam*(self.trueswd+1)) + "+" + str(self.bondam)
+        norm_damage_string += "}[" + str(norm_damage) + "] "
+
+        # get special/critical damage in case needed
+        crit_damage = random.randint( self.mindam*(self.trueswd+2), self.maxdam*(self.trueswd+2) ) + self.bondam
+        crit_damage_string = "{" + str( self.mindam*(self.trueswd+2) ) + "-" + str(self.maxdam*(self.trueswd+2)) + "+" + str(self.bondam) + "}[" + str(crit_damage) + "] "
+
+        # get supercritical damage in case needed
+        super_damage = norm_damage + self.maxdam
+        super_damage_string  = "{" + str( self.mindam*(self.trueswd+1) ) + "-"
+        super_damage_string += str(self.maxdam*(self.trueswd+1)) + "+" + str(self.maxdam)
+        super_damage_string += "+" + str(self.bondam) + "}[" + str(super_damage) + "] "
+
+        # figure out +/- for modifer
+        strAdd="+"
+        swapmod= self.mod
+        if self.mod < 0:
+            strAdd= "-"
+            swapmod= -self.mod
+        modSum = self.sum()
+
+        # build output string
+        myStr = " (" + str(modSum) + ")"
+        myStr += " vs [" + str(self.sk) + strAdd + str(swapmod) + "]"
+
+        if self.is_fumble():
+            myStr += " <b><font color=red>Fumble!</font>  See Fumble Chart [" + str(fum_roll) + "]</b>"
+        elif (self.is_supercritical() and self.is_success()):
+            myStr += " <b><font color=green>Super Critical!</font></b> Damage: " + str(super_damage_string) + "<u>No Armor Stops</u>" + str(hit_loc)
+        elif (self.is_critical() and self.is_success()):
+            myStr += " <b><font color=green>Critical!</font></b> Damage: " + str(crit_damage_string) + "<u>No Armor Stops</u>" + str(hit_loc)
+        elif ( self.is_special() and self.is_success() ):
+            myStr += " <i><font color=green>Special!</font></i> Damage: " + str(crit_damage_string) + str(hit_loc)
+        elif (self.is_success() and self.is_ma()):
+            myStr += " <i><font color=green>Special!</font></i> Damage: " + str(crit_damage_string) + str(hit_loc)
+        elif self.is_success():
+            myStr += " <font color=blue>Success!</font> Damage: " + str(norm_damage_string) + str(hit_loc)
+        else:
+            myStr += " <font color=red>Failure!</font>"
+
+        return myStr
+
+#
+#
+#   Sorcery Roll: [1d100.sorcery(90,   10,  5,   4,   3,   2,    1)]
+#                               (sk, mod, pow, cer, int,  acc, mlt)
+#
+# Ceremony: (+1d6% per strike rank spent on ceremony)
+# Intensity: (-3% per point of Intensity)
+# Duration: (-4% per point of Duration)
+# Range: (-5% per point of Range)
+# Multispell: (-10% per each spell over 1)
+# Acceleration: (-5% per point of Acceleration)
+# Hold: (-2% per point in spell Held)
+#
+class rqsorcery(std):
+    def __init__(self,source=[],sk=11,mod=0,pow=0,cer=0,int=0,acc=0,mlt=0):
+        std.__init__(self,source)
+        self.sk  = sk   # sorcery skill
+        self.mod = mod  # additional modifier ( from duration, range, etc )
+        self.pow = pow  # boost pow and additional pow ( from duration, range, etc )
+        self.cer = cer  # ceremony d6
+        self.int = int  # intensity ( -3% )
+        self.acc = acc  # accelerate ( -5% )
+        self.mlt = mlt  # multispell ( -10% )
+
+    def is_success(self):
+        return (((self.sum() <= (self.sk + self.mod)) or (self.sum() <= 5)) and (self.sum() <= 95))
+
+    def is_special(self):
+        return ( (  self.sum() <= int( floor( ( self.sk + self.mod  )/5  ) ) ) )
+
+    def is_critical(self):
+        return ( (  self.sum() <= int( floor( ( self.sk + self.mod  )/20 ) ) ) )
+
+    def is_fumble(self):
+        if ( self.sk >= 100 ):
+            fum = 0
+        else:
+            fum = (100 - self.sk )
+        final_fum = ( 100 - int( floor( fum/20  ) ) )
+        return (  self.sum() >= final_fum )
+
+    def __str__(self):
+
+        # get fumble roll result in case needed
+        fum_roll = random.randint(2,12)
+        if fum_roll == 12 :
+            fum_string = "<br /><font color=purple>Caster temporarily forgets spell. Make an INTx5 roll each day to remember.</font>"
+        if fum_roll == 11 :
+            fum_string = "<br /><font color=purple>Caster temporarily forgets spell. Make an INTx5 roll each hour to remember.  </font>"
+        if fum_roll == 10 :
+            fum_string = "<br /><font color=purple>Spell produces reverse of the intended effect.  </font>"
+        if fum_roll == 9 :
+            fum_string = "<br /><font color=purple>Caster is Stunned. Roll INTx3 to recover at SR 10 each round.  </font>"
+        if fum_roll == 8 :
+            fum_string = "<br /><font color=purple>Caster takes 2D6 Damage to THP  </font>"
+        if fum_roll == 7 :
+            fum_string = "<br /><font color=purple>Spell produces reverse of the intended effect at 2x Intensity.  </font>"
+        if fum_roll == 6 :
+            fum_string = "<br /><font color=purple>Spell is cast on companions (if harmful) or on random nearby foes (if beneficial)  </font>"
+        if fum_roll == 5 :
+            fum_string = "<br /><font color=purple>Caster takes 1d6 Damage to Head  </font>"
+        if fum_roll == 4 :
+            fum_string = "<br /><font color=purple>Spell is cast on caster (if harmful) or on random nearby foe (if beneficial)  </font>"
+        if fum_roll == 3 :
+            fum_string = "<br /><font color=purple>Caster takes 1d6 Damage to THP  </font>"
+        if fum_roll == 2 :
+            fum_string = "<br /><font color=purple>Caster takes 1 point of Damage to Head  </font>"
+
+            # roll ceremony
+        ceremony_roll = random.randint( self.cer, (self.cer*6) )
+
+        # subtract manipulations
+        extra_mod = self.mod
+        self.mod += ceremony_roll - self.int*3 - self.acc*5 - self.mlt*10
+
+        # add up power cost
+        extra_pow = self.pow
+        self.pow += self.int + self.mlt + self.acc
+        special_pow = int( floor( ( self.pow )/2  ) )
+
+        # figure out +/- for modifer
+        strAdd="+"
+        swapmod= self.mod
+        if self.mod < 0:
+            strAdd= "-"
+            swapmod= -self.mod
+        modSum = self.sum()
+
+        # build output string
+        myStr = " (" + str(modSum) + ")"
+        myStr += " vs [" + str(self.sk) + strAdd + str(swapmod) + "]"
+
+        if self.is_fumble():
+            myStr += " <b><font color=red>Fumble!</font>  POW Cost: [" + str(self.pow) + "],</b> " + fum_string
+        elif self.is_critical():
+            myStr += " <b><font color=green>Critical!</font></b> POW Cost: [1] "
+        elif self.is_special():
+            myStr += " <i><font color=green>Special!</font></i> POW Cost: [" + str(special_pow) + "] "
+        elif self.is_success():
+            myStr += " <font color=blue>Success!</font> POW Cost: [" + str(self.pow) + "] "
+        else:
+            myStr += " <font color=red>Failure!</font> POW Cost: [1]"
+
+        # print spell details
+        myStr += "<br /> --- Other Modifiers:["    + str( extra_mod     ) + "], "
+        myStr += "Extra POW:[" + str( extra_pow     ) + "], "
+        myStr += "Ceremony:[+"          + str( ceremony_roll ) + "%], "
+        myStr += "Intensity(-3):["      + str( self.int      ) + "], "
+        myStr += "Accelerate(-5):["     + str( self.acc      ) + "], "
+        myStr += "Multispell(-10):["    + str( self.mlt      ) + "] ---"
+
+        return myStr
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/old_rollers/savage.py	Mon Mar 22 14:55:37 2010 -0600
@@ -0,0 +1,509 @@
+# (at your option) any later version.
+# # This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+# --
+#
+# File: savage.py
+# Authors: Rich Finder
+#        : Alexandre Major
+# Maintainer:
+# Version: 0.2
+#
+# Description: Savage Worlds die roller
+# Permission was granted by Pinnacle to reprint the result descriptions from their tables on Apr 20, 2006 by Simon Lucas
+#
+
+__version__ = "$Id: savage.py,v 1.2 2007/05/06 16:42:55 digitalxero Exp $"
+
+import string
+from random import *
+
+from std import std
+from orpg.dieroller.base import *
+
+# Savage, as in Savage Worlds
+class sw(std):
+    #def __init__(self,source=[], wnd=1, loc="rnd", chmod=0):
+    def __init__(self,source=[],fmod=0):
+        std.__init__(self,source)
+
+# these methods return new die objects for specific options
+
+    def fright(self,fearmod=0):
+        return fright(self,fearmod=0)
+
+    def kob(self,wnd,loc):
+        return kob(self,wnd=1,loc="rnd")
+
+    def ooc(self):
+        return ooc(self)
+
+    def ract(self,chmod=0):
+        return ract(self,chmod=0)
+
+    def vcrit(self):
+        return vcrit(self)
+
+    def fortune(self):
+        return fortune(self)
+
+    def freak(self):
+        return freak(self)
+
+    def swdhelps(self):
+        return swdhelps(self)
+
+die_rollers.register(sw)
+
+class fright(std):
+    #-----------------The Fright Table
+    #  Rolls on the Fright - which is a 1d20 roll modified by the fear level of a monster.  This function automatically generates
+    #  The appropriate random number and then adds the fear modifier to the rol and displays the result of the roll with the effect
+    #  of that roll.
+    #  Usage:  [fright()]
+    #          [fright(6)] - if the fear modifier of the monster was 6
+    #-----------------
+    def __init__(self,fmod=0):
+        global fear
+        std.__init__(self)
+        fear=fmod
+
+    #def sum(self):
+
+    def __str__(self):
+        global fear
+        iroll = randint(1,20)
+        froll = iroll + fear
+        if froll >= 1 and froll <=4:
+            fresult = "Adrenaline Rush"
+            fdescription = "The hero's \"fight\" response takes over.  He adds +2 to all Trait and damage rolls on his next action."
+        elif froll >= 5 and froll <=8:
+            fresult = "Shaken"
+            fdescription = "The character is Shaken."
+        elif froll >=9 and froll <=12:
+            fresult = "Pankicked"
+            fdescription = "The character immediately moves his full Pace plus running die away from the danger and is Shaken."
+        elif froll >=13 and froll <=16:
+            fresult = "Minor Phobia"
+            fdescription = "The character gains a Minor Phobia Hindrance somehow associated with the trauma."
+        elif froll >=17 and froll <=18:
+            fresult = "Major Phobia"
+            fdescription = "The character gains a Major Phobia Hindrance."
+        elif froll >=19 and froll <= 20:
+            fresult = "The Mark of Fear"
+            fdescription = "The hero is Shaken and also suffers some cosmetic, physical alteration -- a white streak forms in the hero's hair, his eyes twitch constantly, or some other minor physical alteration.  This reduces his Charisma by 1."
+        else:
+            fresult = "Heart Attack"
+            fdescription = "The hero is so overwhelmed with fear that his heart stutters.  He becomes Incapacitated and must make a Vigor roll at -2.  If Successful, he's Shaken and can't attempt to recover for 1d4 rounds.  If he fails, he dies in 2d6 rounds.  A Healing roll at -4 saves the victim's life, but he remains Incapacitated."
+        myStr = "[" + str(iroll) + "+"+str(fear)+"="+str(froll)+"] ==> " + fresult +":  "+ fdescription
+        return myStr
+
+class kob(std):
+    #-------------------The Knockout Blow Table
+    #  This table used when a character has sustained more than 3 wounds.  The number wounds taken that sends a character to the
+    #  Knockout Blow Table is what gets sent with the kob command - not the total number of wounds the character currently has.
+    #  For example - a character has 2 wounds and is hit takes 2 more wounds, this will result in a total of 4 wounds, but the
+    #  number that gets sent to the kob roll is 2, because that is the number of wounds sustained that sent the character to the kob
+    #  table.
+    #
+    #  It is also important to note that if a called shot to particular area was made, that information should be sent with the "roll"
+    #  as well, because the KOB Table may need to determine some dramatic effects for permanent injuries, etc.  If a hit location was sent
+    #  the function will use that information.
+    #  Valid Hit Locations are:  h (head), g (guts), la (left arm), ra (right arm), rl (right leg), ll (left leg), c (crotch)
+    #  Usage = [kob(3)] - If 3 wounds were received that sent the player to the Knockout Blow Table - no called shot
+    #          [kob(3,"h") - If 3 wounds were received that sent the player to the Knockout Blow Table with a called shot to the head
+    #---------------------
+    global wound, loca
+    def __init__(self, wnd, loc="rnd"):
+        global wound, loca
+        std.__init__(self, wnd)
+        #Need to check to make sure that wnd is a number
+        if (int(wnd)):
+            wound = wnd
+            loca = loc
+        else:
+            mystr = "You need to supply a number for the wound."
+            return mystr
+
+    def __str__(self):
+        global wound, loca
+        itbl = "no"
+        if wound == 1:
+            wtype = "Battered and Bruised"
+            wdescription = "If your hero was previously Incapacitated, this result has no further effect. Otherwise, your hero's had the wind knocked out of him. Make a Spirit roll at the beginning of each round. If the roll is successful, he becomes Shaken and can return to the fight."
+        elif wound == 2:  #Need to roll on the Injury table as well
+            wtype = "Incapacitated"
+            wdescription = "Your hero is beaten badly enough to take him out of this fight. He's Incapacitated and must roll on the Injury Table."
+            itbl = "yes"
+        elif wound == 3:
+            wtype = "Bleeding Out"
+            wdescription = "Your hero is bleeding out and Incapacitated. Roll on the Injury Table and make a Vigor roll at the start of each combat round. A failure means the hero has lost too much blood and becomes mortally Wounded (see below; begin rolling for the Mortal Wound in the next round). With a success, he keeps bleeding and must roll again next round. With a raise, or a successful Healing roll, he stops bleeding and is Incapacitated."
+            itbl = "yes"
+        elif wound < 1:
+            wtype = "No Wounds?"
+            wdescription = "The Number of wounds specified was less than one...why are you consulting this chart?"
+        else:
+            wtype = "Mortal Wound"
+            wdescription = "Your hero has suffered a life-threatening wound and will not recover without aid. He is Incapacitated and must roll on the Injury Table. He must also make a Vigor roll at the start of each round. If the roll is failed, he passes on. A Healing roll stabilizes the victim but leaves him Incapacitated."
+            itbl = "yes"
+
+        if itbl == "yes":
+            #Determine if a Hit location was specified already
+            if loca.lower() == "h":
+                iroll = 11
+            elif loca.lower() == "g":
+                iroll = 5
+            elif loca.lower() == "ra":
+                iroll = 3
+                aroll = 2
+            elif loca.lower() == "la":
+                iroll = 3
+                aroll = 1
+            elif loca.lower() == "rl":
+                iroll = 10
+                lroll = 2
+            elif loca.lower() == "ll":
+                iroll = 10
+                lroll = 1
+            elif loca.lower() == "c":
+                iroll = 2
+            else:  #none of the above were provided...wo will need to determine randomly
+                iroll = randint(2,12)
+            #resolve the injury table stuff...
+            if iroll == 2:
+                iloc = "Unmentionables"
+                idescription = "The hero suffers an embarrassing and painful wound to the groin."
+            elif iroll == 3 or iroll == 4:
+                if loca != "ra" and loca != "la":  #  If a hit location was not specified (or not recognized) already, determine randomly
+                    aroll = randint(1,2)
+                if aroll == 1:
+                    warm = "Left"
+                else:
+                    warm = "Right"
+                iloc = warm + " Arm"
+                idescription = "The arm is rendered useless."
+            elif iroll >= 5 and iroll <= 9:  #will need to make another random roll
+                iloc = "Guts"
+                idescription = "Your hero catches one somewhere between the crotch and the chin."
+                groll = randint(1,6)
+                if groll == 1 or groll == 2:
+                    #idescription += " <b>Broken (" + str(groll) + ")</b> His Agility is reduced by a die type (min dr)."
+                    idescription += " <b>Broken (" + str(groll) + ")</b> His Agility is reduced by a die type (min d4)."
+                elif groll == 3 or groll == 4:
+                    idescription += " <b>Battered (" + str(groll) + ")</b> His Vigor is reduced by a die type (min d4)."
+                else:
+                    idescription += " <b>Busted (" + str(groll) + ")</b> His Strength is reduced by a die type (min d4)."
+            elif iroll == 10:
+                if loca != "ll" and loca != "rl":  #  If a hit location was not specified (or not recognized) already, determine randomly
+                    lroll = randint(1,2)
+                if lroll == 1:
+                    wleg = "Left"
+                else:
+                    wleg = "Right"
+                iloc = wleg + " Leg"
+                idescription = "The character's leg is crushed, broken, or mangled. His Pace is reduced by 1."
+            else:  #Will need to make another random roll for this one.
+                iloc = "Head"
+                idescription = "Your hero has suffered a grievous injury to his head."
+                hroll = randint(1,6)  #determine how the head is impacted by the wound
+                if hroll == 1 or hroll ==2:
+                    idescription += "<b>Hideous Scar (" + str(hroll) + ")</b>Your hero now has the Ugly Hindrance."
+                elif hroll == 3 or hroll == 4:
+                    idescription += "<b>Blinded (" + str(hroll) + ")</b> One or both of your hero's eyes was damaged. He gains the Bad Eyes Hindrance."
+                else:
+                    idescription += "<b>Brain Damage (" + str(hroll) + ")</b> Your hero suffers massive trauma to the head. His Smarts is reduced one die type (min d4)."
+            idescription += " Make a Vigor roll applying any wound modifiers. If the Vigor roll is failed, the injury is permanent regardless of healing. If the roll is successful, the effect goes away when all wounds are healed."
+            if iroll == 2:
+                idescription +=" If the injury is permanent, reproduction is out of the question without miracle surgery or magic."
+            if loca != "h" and loca != "g" and loca != "c" and loca != "rl" and loca != "ll" and loca != "ra" and loca != "la":
+                idescription +="<br><br><b>***If the attack that caused the Injury was directed at a specific body part, use that location instead of rolling randomly.***</b>"
+            myStr = "[" + wtype + "] ==>" + wdescription + "<br><br><b>Injury Table Result ("+ str(iroll) +"): </b> [" + iloc + "] ==> " + idescription
+        else:
+            myStr = "[" + wtype + "] ==>" + wdescription
+        return myStr
+
+class ract(std):
+    #----------------------The Reaction Table
+    #  This is used to randomly determine the general mood of NPCs toward the player characters.  This simulates a 2d6 roll
+    #  and displays the reaction.  This roll can be modified by the Charisma of the player(s).
+    #  Usage:  [ract()] - No Charisma modifier
+    #          [ract(2)] - A +2 Charisma modifier
+    #          [ract(-2)] - A -2 Charisma modifier
+    #----------------------
+    global charisma
+    def __init__(self,chmod=0):
+        global charisma
+        std.__init__(self)
+        charisma = chmod
+
+    def __str__(self):
+        global charisma
+        r1roll = randint(2,12)
+        rroll = r1roll + charisma
+        if rroll == 2:
+            reaction = "Hostile"
+            rdescription = "The NPC is openly hostile and does his best to stand in the hero's way. He won't help without an overwhelming reward or payment of some kind."
+        elif rroll >=3 and rroll <=4:
+            reaction = "Unfriendly"
+            rdescription = "The NPC is openly hostile and does his best to stand in the hero's way. He won't help without an overwhelming reward or payment of some kind."
+        elif rroll >=5 and rroll <=9:
+            reaction = "Neutral"
+            rdescription = "The NPC has no particular attitude, and will help for little reward if the task at hand is very easy. If the task is difficult, he'll require substantial payment of some kind."
+        elif rroll >=10 and rroll <=11:
+            reaction = "Friendly"
+            rdescription = "The NPC will go out of his way for the hero. He'll likely do easy tasks for free (or very little), and is willing to do more dangerous tasks for fair pay or other favors."
+        else:
+            reaction = "Helpful"
+            rdescription = "The NPC is anxious to help the hero, and will probably do so for little or no pay depending on the nature of the task."
+        #myStr = "[" + reaction + "(" + str(r1roll) + "+Charisma Mods("+str(charisma)+")="+str(rroll)+")] ==> " + rdescription
+        myStr = "["+str(r1roll)+"+"+str(charisma)+"(charisma modifier)="+str(rroll)+"] ==> "+reaction+":  "+rdescription
+        return myStr
+
+class ooc(std):
+    #--------------------The Out of Control Vehicle Table
+    #  This table is used when a vehicle is injured during combat and must determine what happens to the vehicle.  This is a 2d6
+    #  roll and displays the results of the roll.  This will also display altitude information for flying vehicles.
+    #  Usage:  [ooc()]
+    #--------------------
+    def __init__(self):
+        std.__init__(self)
+
+    def __str__(self):
+        ooroll = randint(2,12)
+        oodescripton = "Something"
+        if ooroll == 2:
+            ooeffect = "Roll Over"
+            rroll = randint(1,6)
+            oodescription = "The vehicle performs a Slip and rolls over "+ str(rroll)+ " time"
+            if rroll < 2:
+                oodescription +="s"
+            oodescription += " in that direction. Roll collision damage for the vehicle and everyone inside. Any exterior-mounted weapons or accessories are ruined."
+        elif ooroll == 3 or ooroll == 4:
+            ooeffect = "Spin"
+            sroll = randint(1,6)
+            froll = randint(1,12)
+            oodescription = "Move the vehicle "+str(sroll)+"\" in the direction of the maneuver, or "+str(sroll)+"\" away from a damaging blow. At the end of the Spin,the vehicle is facing is "+str(froll)+" o'clock."
+        elif ooroll >= 5 and ooroll <= 9:
+            ooeffect = "Skid"
+            sroll = randint(1,4)
+            oodescription = "Move the vehicle "+str(sroll)+"\" left or right (in the direction of a failed maneuver, or away from a damaging attack)."
+        elif ooroll == 10 or ooroll == 11:
+            ooeffect = "Slip"
+            sroll = randint(1,6)
+            oodescription = "Move the vehicle "+str(sroll)+"\" left or right (in the direction of a failed maneuver, or away from a damaging attack)."
+        else:
+            ooeffect = "Flip"
+            froll = randint(1,4)
+            oodescription = "The vehicle flips end over end "+str(froll)+" times. Move it forward that many increments of its own length. Roll collision damage for the vehicle, its passengers, and anything it hits. "
+            shroll = randint(1,2)
+            if shroll == 1:
+                oodescription += "<br><br><b>Note:</b> If the vehicle is slow and/or heavy (such as a tank) it Slips instead: "
+                sroll = randint(1,6)
+                oodescription += "Move the vehicle "+str(sroll)+"\" left or right (in the direction of a failed maneuver, or away from a damaging attack)."
+            else:
+                oodescription += "<br><br><b>Note (GM's discretion):</b> If the vehicle is slow and/or heavy (such as a tank) it Skids instead: "
+                sroll = randint(1,4)
+                oodescription += "Move the vehicle "+str(sroll)+"\" left or right (in the direction of a failed maneuver, or away from a damaging attack)."
+
+        oodescription += "<br><br>For flying vehicles conducting combat in the air, the vehicle"
+        altchange = randint(2,12)
+        if altchange == 2:
+            dwn = randint(2,20)
+            oodescription += " loses "+str(dwn)+"\" of altitude."
+        elif altchange == 3 or altchange == 4:
+            dwn = randint(1,10)
+            oodescription += " loses "+str(dwn)+"\" of altitude."
+        elif altchange >= 5 and altchange <= 9:
+            oodescription += " has no change in altitude."
+        else:
+            altup = randint(1,10)
+            oodescription += " gains "+str(altup)+"\" of altitude."
+        myStr = "[" + ooeffect + "(" + str(ooroll) + ")] ==> " + oodescription
+        return myStr
+
+class vcrit(std):
+    #----------------The Critical Hit Vehicle Table
+    #  This table generates a 2d6 roll to determine the Critical Hit results every time a vehicle takes a wound.  There are no
+    #  modifiers to this roll
+    #  Usage [vcrit()]
+    #----------------
+    def __init__(self):
+        std.__init__(self)
+
+    def __str__(self):
+        chitroll = randint(2,12)
+        if chitroll == 2:
+            cheffect = "Scratch and Dent"
+            chdescription = "The attack merely scratches the paint. There's no permanent damage."
+        elif chitroll == 3:
+            cheffect = "Engine"
+            chdescription = "The engine is hit. Oil leaks, pistons misfire, etc. Acceleration is halved (round down). This does not affect deceleration, however."
+        elif chitroll == 4:
+            cheffect = "Locomotion"
+            chdescription = "The wheels, tracks, or whatever have been hit. Halve the vehicle's Top Speed immediately. If the vehicle is pulled by animals, the shot hits one of them instead."
+        elif chitroll == 5:  #Need to make an additional roll to see what direction the vehicle can turn...
+            cheffect = "Controls"
+            troll = randint(1,2)
+            if troll == 1:
+                aturn = "left"
+            else:
+                aturn = "right"
+            chdescription = "The control system is hit. Until a Repair roll is made, the vehicle can only perform turns to the "+str(aturn)+". This may prohibit certain maneuvers as well."
+        elif chitroll >= 6 and chitroll <=8:
+            cheffect = "Chassis"
+            chdescription = "The vehicle suffers a hit in the body with no special effects."
+        elif chitroll == 9 or chitroll == 10:
+            cheffect = "Crew"
+            chdescription = "A random crew member is hit. The damage from the attack is rerolled. If the character is inside the vehicle, subtract the vehicle's Armor from the damage. Damage caused by an explosion affects all passengers in the vehicle."
+        elif chitroll == 11:
+            cheffect = "Weapon"
+            chdescription = "A random weapon on the side of the vehicle that was hit is destroyed and may no longer be used. If there is no weapon, this is a Chassis hit instead (The vehicle suffers a hit in the body with no special effects)."
+        else:
+            cheffect = "Wrecked"
+            chdescription = "The vehicle is wrecked and automatically goes Out of Control.<br><br><b>[Out of Control]</b> ==>"+str(ooc())
+        myStr = "["+cheffect+" ("+str(chitroll)+")] ==> "+chdescription
+        return myStr
+
+    def ooc(self):
+        return vcritooc(self)
+
+class swdhelps(std):
+    #Display help information for this die roller - it will list all the available commands, and how to use them
+    def __init__(self):
+        std.__init__(self)
+
+    def __str__(self):
+        myStr = "<table border='1' valign='top'>\
+        <tr>\
+            <td colspan='3'>This chart will show you the various commands you can use and what is required, etc.  The <i><b>italicized text</b></i> are optional variables.  Any text that is not italicized and is within parentheses is required.  About the only roll that has a required element is the Knockout Blow roll (kob).</td>\
+        </tr>\
+        <tr>\
+            <td align='center'><b>Die Command</b></td><td align='center' width='55%'><b>Description</b></td><td align='center'width='30%'><b>Example</b></td>\
+        </tr>\
+        <tr>\
+            <td><b>[fright(<i>monster's fear modifier</i>)]</b></td><td>Rolls on the <b>Fright Table</b>.  This command generates a number between 1 and 20 and displays the corresponding entry from the Fright Table.</td><td>[fright()]<br>[fright(6)]</td>\
+        </tr>\
+        <tr>\
+            <td><b>[kob(#ofWounds,<i>hitLocation</i>)]</b></td><td>Rolls on the <b>Knockout Blow Table</b> as well as the <b>Injury Table</b> if necessary.  The number of wounds must be specified, however, the location only needs to be specified if a particular body part was targeted.  If a hit location was targeted, then the following codes should be used:<br>\
+                <ul>\
+                    <li>h = head</li>\
+                    <li>g = guts/other vital areas</li>\
+                    <li>c = crotch/groin</li>\
+                    <li>la = left arm</li>\
+                    <li>ra = right arm</li>\
+                    <li>ll = left leg</li>\
+                    <li>rl = right leg</li>\
+                </ul><br>If no hit location is specified, the hit location will be determined when the roll on the Injury Table is necessary.  When specifiying a hit locations, the code must be entered within double quotes.</td><td><b>3 wounds, no called shot</b><br>[kob(3)]<br><b>2 wounds to the head</b><br>[kob(2,\"h\")]</td>\
+        </tr>\
+        <tr>\
+            <td><b>[ract(<i>Charisma Mods</i>)]</b></td><td>Rolls on the <b>Reaction Table</b>.  Will generate the initial reaction to the PCs.  If the Charisma modifiers are supplied, they will be taken into account as well.  Remember that this table is generally only consulted when the reaction of the NPC is comlpetely unknown to the GM.</td><td><b>Reaction no Charisma Mods</b><br>[ract()]<br><b>Reaction with +2 Charisma Mods</b><br>[ract(2)]</td>\
+        </tr>\
+        <tr>\
+            <td><b>[vcrit()]</b></td><td>Rolls on the <b>Critical Hit Table</b> for vehicles.  If a roll on the Out of Control Chart is necessary, it will automatically roll on that table as well.</td><td>[vcrit()]</td>\
+        </tr>\
+        <tr>\
+            <td><b>[ooc()]</b></td><td>Rolls on the <b>Out of Controll Table</b> for vehicles.  This roll will automatically determine any directions/movement rolls as well.</td><td>[ooc()]</td>\
+        </tr>\
+        <tr>\
+            <td><b>[fortune()]</b></td><td>Rolls on the <b>Fortune Table</b> for the Showdown Skirmish rules.  This roll will automatically roll on the <b>Freak Event Table</b> if necessary</td><td>[fortune()]</td>\
+        </tr>\
+        <tr>\
+            <td><b>[freak()]</b></td><td>Rolls on the <b>Freak Event Table</b>.</td><td>[freak()]</td>\
+        </tr>\
+        <tr>\
+            <td><b>[swdhelps()]</b></td><td>Displays this help list.</td><td>[swdhelps()]</td>\
+        </tr>\
+        </table>"
+        return myStr
+
+class fortune(std):
+    def __init___(self):
+        std.__init__(self)
+
+    def __str__(self):
+        forroll = randint(2,12)
+        if forroll == 2 or forroll == 12: #Need to roll on Freak Event Table
+            fortune = "Freak Event!"
+            fdescription = "Roll on the Freak Event Table.<br><br><b>[Freak Event Table]</b> ==> "+str(freak())
+        elif forroll == 3:
+            fortune = "Twist of Fate"
+            fdescription = "Take a benny from your opponent. If he does not have one, he must immediately remove any one Extra from play."
+        elif forroll == 4:
+            fortune = "The Quick and the Dead"
+            fdescription = "Swap one of your opponent's cards for any one of yours."
+        elif forroll == 5:
+            fortune = "Rally"
+            fdescription = "Pick any one unit on the board with Shaken figures. All those figures recover automatically."
+        elif forroll >= 6 and forroll <= 8:
+            fortune = "Hand of Fate"
+            fdescription = "Gain one extra benny."
+        elif forroll == 9:
+            fortune = "Close Call"
+            fdescription = "Any one of your opponent's units stumbles, becomes confused, or is otherwise disrupted. All its members suffer -2 to their trait rolls this round."
+        elif forroll == 10:
+            fortune = "Teamwork"
+            fdescription = "Pick any one other unit within 12\" of this one. Discard its Action Card. It acts on the Joker along with this unit, and gains the usual bonuses as well."
+        else:
+            fortune = "Out of Ammo"
+            fdescription = "Pick any one enemy unit. It's out of ammo or Power Points (your choice). If this result cannot be applied, you gain a benny instead."
+        myStr = "["+fortune+" ("+str(forroll)+")] ==>"+fdescription
+        return myStr
+
+    def freak(self):
+        return fortunefreak(self)
+
+class freak(std):
+    def __init__(self):
+        std.__init__(self)
+
+    def __str__(self):
+        feroll = randint(1,10)
+        if feroll == 1:
+            fevent = "Storm"
+            fedescription = "A sudden storm rolls in. Rain begins to pour and visibility is limited to 12\". All attack rolls are at -1, and black powder weapons don't work at all. The round after this event, all streams become impassable, even at fords. Only bridges remain."
+        elif feroll == 2:
+            fevent = "Fire!"
+            fedescription = "Fire breaks out on the board! Roll randomly among each occupied building, patch of trees, or other flammable terrain type. If none of these are occupied, roll randomly among all flammable terrain pieces. The entire building or forest catches fire this round and causes 2d6 damage to everything within. The fire continues for the rest of the game--unless a storm comes, which quenches it immediately.<br><br>At the beginning of each turn thereafter, roll 1d6 for each flammable structure within 4\" (adjacent buildings, another patch of forest, etc.). On a 4-6, that structure catches fire as well. Check to see if these new fires spread in the following rounds."
+        elif feroll == 3:
+            fevent = "Blood Ties"
+            fedescription = "One of the Wild Cards on the other side is related or has some other special bond with one of your heroes (a Wild Card of your choice). For the rest of the battle, these two won't attack each other directly unless there are no other targets on the board."
+        elif feroll == 4:
+            fevent = "Death of a Hero"
+            inspireroll = randint(1,2)
+            if inspireroll == 1:
+                fedescription ="The next time one of your Wild Cards dies, his noble sacrifice triggers new resolve in his companions.  When your next Wild Card is Incapacitated the rest of your force is inspired by his legacy and adds +1 to all their rolls until another of your Wild Cards is killed."
+            else:
+                fedescription = "The next time one of your Wild Cards dies, his noble sacrifice triggers bone-chilling dread in his companions. When your next Wild Card is Incapacitated the rest of your force is filled with dread. They subtract -1 from all their rolls for the rest of the game until an <i>enemy</i> Wild Card is slain."
+        elif feroll == 5:
+            fevent = "Fickle Fate"
+            fedescription = "Fate favors the underdog. The side with the fewest bennies draws until it has the same number as their foe. Place these in the common pool."
+        elif feroll == 6:
+            fevent = "Back from the Dead"
+            fedescription = "One of your dead was just knocked unconscious. He returns in the spot where he fell. If this is a Wild Card, he returns with but a single wound."
+        elif feroll == 7:
+            fevent = "Bitter Cold/Heat"
+            fedescription = "The weather heats up or cools down, depending on your environment. All troops become tired or bogged down and reduce their running rolls by half for the rest of the game."
+        elif feroll == 8:
+            fevent = "Battle Tested"
+            fedescription = "Any one of your units improves any one skill or attribute a die type immediately."
+        elif feroll == 9:
+            fevent = "The Fog"
+            fedescription = "Dense fog, mist, or smoke rolls drifts over the battlefield. Place two connected Large Burst Templates at the center of one randomly determined board edge. The fog drifts 2d6\" each round in a random direction (roll a d12 and read it like a clock facing). The fog \"bounces\" if it hits an edge in a random direction (so that it never leaves the field)."
+        else:
+            fevent = "Reinforcements"
+            fedescription = "A group of your most common currently-fielded troop type arrives on the field of battle! Place these troops in your deployment area. They act on the Joker this round and are dealt in normally hereafter."
+        myStr = "["+fevent+"("+str(feroll)+")] ==> "+fedescription
+        return myStr
+
+class rdm(std):  #If I get the time and the inspiration - I may try to incorporate a Random Table roller...  I need to think about this one.
+    def __init__(self):
+        std.__init__(self)
+
+    def __str__(self):
+        return myStr
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/old_rollers/sr4.py	Mon Mar 22 14:55:37 2010 -0600
@@ -0,0 +1,237 @@
+## a vs die roller as used by WOD games
+#!/usr/bin/env python
+# Copyright (C) 2000-2001 The OpenRPG Project
+#
+#   openrpg-dev@lists.sourceforge.net
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+# --
+#
+# File: sr4.py
+# Author: Veggiesama, ripped straight from Michael Edwards (AKA akoman)
+# Maintainer:
+# Version: 1.1
+#
+# 1.1: Now with glitch and critical glitch detection!
+# 1.1: Cleaned up some of the output to make it simpler.
+#
+# Description: Modified from the original Shadowrun dieroller by akoman,
+#              but altered to follow the new Shadowrun 4th Ed dice system.
+#
+#              SR4 VS
+#              Typing [Xd6.vs(Y)] will roll X dice, checking each die
+#              roll against the MIN_TARGET_NUMBER (default: 5). If it
+#              meets or beats it, it counts as a hit. If the total hits
+#              meet or beat the Y value (threshold), there's a success.
+#
+#              SR4 EDGE VS
+#              Identical to the above function, except it looks like
+#              [Xd6.edge(Y)] and follows the "Rule of Six". That rule
+#              states any roll of 6 is counted as a hit and rerolled
+#              with a potential to score more hits. The "Edge" bonus
+#              dice must be included into X.
+#
+#              SR4 INIT
+#              Typing [Xd6.init(Y)] will roll X dice, checking each
+#              die for a hit. All hits are added to Y (the init attrib
+#              of the player), to give an Init Score for the combat.
+#
+#              SR4 EDGE INIT
+#              Typing [Xd6.initedge(Y)] or [Xd6.edgeinit(Y)] will do
+#              as above, except adding the possibility of Edge dice.
+#
+#              Note about non-traditional uses:
+#              - D6's are not required. This script will work with any
+#                die possible, and the "Rule of Six" will only trigger
+#                on the highest die roll possible. Not throughly tested.
+#              - If you want to alter the minimum target number (ex.
+#                score a hit on a 4, 5, or 6), scroll down and change
+#                the global value MIN_TARGET_NUMBER to your liking.
+
+__version__ = "1.1"
+
+from std import std
+from orpg.dieroller.base import *
+
+MIN_TARGET_NUMBER = 5
+GLITCH_NUMBER = 1
+
+class sr4(std):
+    name = "sr4"
+
+    def __init__(self,source=[]):
+        std.__init__(self,source)
+        self.threshold = None
+        self.init_attrib = None
+
+    def vs(self,threshold=0):
+        return sr4vs(self, threshold)
+
+    def edge(self,threshold=0):
+        return sr4vs(self, threshold, 1)
+
+    def init(self,init_attrib=0):
+        return sr4init(self, init_attrib)
+
+    def initedge(self,init_attrib=0):
+        return sr4init(self, init_attrib, 1)
+    def edgeinit(self,init_attrib=0):
+        return sr4init(self, init_attrib, 1)
+
+    def countEdge(self,num):
+        if num <= 1:
+            self
+        done = 1
+        for i in range(len(self.data)):
+            if (self.data[i].lastroll() >= num):
+                # counts every rerolled 6 as a hit
+                self.hits += 1
+                self.data[i].extraroll()
+                self.total += 1
+                done = 0
+            elif (self.data[i].lastroll() <= GLITCH_NUMBER):
+                self.ones += 1
+            self.total += 1
+        if done:
+            return self
+        else:
+            return self.countEdge(num)
+
+    def countHits(self,num):
+        for i in range(len(self.data)):
+            if (self.data[i].lastroll() >= MIN_TARGET_NUMBER):
+                # (Rule of Six taken into account in countEdge(), not here)
+                self.hits += 1
+            elif (self.data[i].lastroll() <= GLITCH_NUMBER):
+                self.ones += 1
+            self.total += 1
+
+    def __str__(self):
+        if len(self.data) > 0:
+            self.hits = 0
+            self.ones = 0
+            self.total = 0
+            for i in range(len(self.data)):
+                if (self.data[i].lastroll() >= MIN_TARGET_NUMBER):
+                    self.hits += 1
+                elif (self.data[i].lastroll() <= GLITCH_NUMBER):
+                    self.ones += 1
+                self.total += 1
+            firstpass = 0
+            myStr = "["
+            for a in self.data[0:]:
+                if firstpass != 0:
+                    myStr += ","
+                firstpass = 1
+                if a >= MIN_TARGET_NUMBER:
+                    myStr += "<B>" + str(a) + "</B>"
+                elif a <= GLITCH_NUMBER:
+                    myStr += "<i>" + str(a) + "</i>"
+                else:
+                    myStr += str(a)
+            myStr += "] " + CheckIfGlitch(self.ones, self.hits, self.total)
+            myStr += "Hits: (" + str(self.hits) + ")"
+        else:
+            myStr = "[] = (0)"
+        return myStr
+
+die_rollers.register(sr4)
+
+class sr4init(sr4):
+    def __init__(self,source=[],init_attrib=1,edge=0):
+        std.__init__(self,source)
+        if init_attrib < 2:
+            self.init_attrib = 2
+        else:
+            self.init_attrib = init_attrib
+        self.dicesides = self[0].sides
+        self.hits = 0
+        self.ones = 0
+        self.total = 0
+        if edge:
+            self.countEdge(self.dicesides)
+        self.countHits(self.dicesides)
+
+    def __str__(self):
+        if len(self.data) > 0:
+            firstpass = 0
+            myStr = "["
+            for a in self.data[0:]:
+                if firstpass != 0:
+                    myStr += ","
+                firstpass = 1
+                if a >= MIN_TARGET_NUMBER:
+                    myStr += "<B>" + str(a) + "</B>"
+                elif a <= GLITCH_NUMBER:
+                    myStr += "<i>" + str(a) + "</i>"
+                else:
+                    myStr += str(a)
+            myStr += "] " + CheckIfGlitch(self.ones, self.hits, self.total)
+            init_score = str(self.init_attrib + self.hits)
+            myStr += "InitScore: " + str(self.init_attrib) + "+"
+            myStr += str(self.hits) + " = (" + init_score + ")"
+        else:
+            myStr = "[] = (0)"
+        return myStr
+
+class sr4vs(sr4):
+    def __init__(self,source=[], threshold=1, edge=0):
+        std.__init__(self, source)
+        if threshold < 0:
+            self.threshold = 0
+        else:
+            self.threshold = threshold
+        self.dicesides = self[0].sides
+        self.hits = 0
+        self.ones = 0
+        self.total = 0
+        if edge:
+            self.countEdge(self.dicesides)
+        self.countHits(self.dicesides)
+
+    def __str__(self):
+        if len(self.data) > 0:
+            firstpass = 0
+            myStr = "["
+            for a in self.data[0:]:
+                if firstpass != 0:
+                    myStr += ","
+                firstpass = 1
+                if a >= MIN_TARGET_NUMBER:
+                    myStr += "<B>" + str(a) + "</B>"
+                elif a <= GLITCH_NUMBER:
+                    myStr += "<i>" + str(a) + "</i>"
+                else:
+                    myStr += str(a)
+            #myStr += "] Threshold=" + str(self.threshold)
+            myStr += "] vs " + str(self.threshold) + " "
+            myStr += CheckIfGlitch(self.ones, self.hits, self.total)
+            if self.hits >= self.threshold:
+                myStr += "*SUCCESS* "
+            else:
+                myStr += "*FAILURE* "
+            myStr += "Hits: (" + str(self.hits) + ")"
+        else:
+            myStr = "[] = (0)"
+        return myStr
+
+def CheckIfGlitch(ones, hits, total_dice):
+    if (ones * 2) >= total_dice:
+        if hits >= 1:
+            return "*GLITCH* "
+        else:
+            return "*CRITICAL GLITCH* "
+    else:
+        return ""
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/xxold_rollers.py	Mon Mar 22 14:55:37 2010 -0600
@@ -0,0 +1,16 @@
+import os
+import orpg.pluginhandler
+
+class Plugin(orpg.pluginhandler.PluginHandler):
+    def __init__(self, plugindb, parent):
+        orpg.pluginhandler.PluginHandler.__init__(self, plugindb, parent)
+
+        # The Following code should be edited to contain the proper information
+        self.name = 'Old Rollers'
+        self.author = 'Dj Gilcrease'
+        self.help = 'A group of old style rollers that have or will not be converted to the new system'
+
+    def plugin_enabled(self):
+        import plugins.old_rollers
+
+    def plugin_disabled(self): pass