comparison orpg/dieroller/rollers/savage.py @ 167:5c9a118476b2 alpha

Traipse Alpha 'OpenRPG' {091210-00} Traipse is a distribution of OpenRPG that is designed to be easy to setup and go. Traipse also makes it easy for developers to work on code without fear of sacrifice. 'Ornery-Orc' continues the trend of 'Grumpy' and adds fixes to the code. 'Ornery-Orc's main goal is to offer more advanced features and enhance the productivity of the user. Update Summary (Keeping up with Beta) New Features: Added Bookmarks Added 'boot' command to remote admin Added confirmation window for sent nodes Minor changes to allow for portability to an OpenSUSE linux OS Miniatures Layer pop up box allows users to turn off Mini labels, from FlexiRPG Zoom Mouse plugin added Images added to Plugin UI Switching to Element Tree Map efficiency, from FlexiRPG Added Status Bar to Update Manager New TrueDebug Class in orpg_log (See documentation for usage) Portable Mercurial Tip of the Day added, from Core and community New Reference Syntax added for custom PC sheets New Child Reference for gametree New Parent Reference for gametree New Gametree Recursion method, mapping, context sensitivity, and effeciency.. New Features node with bonus nodes and Node Referencing help added Dieroller structure from Core Added 7th Sea die roller method; ie [7k3] = [7d10.takeHighest(3).open(10)] New 'Mythos' System die roller added Added new vs. die roller method for WoD; ie [3v3] = [3d10.vs(3)]. Includes support for Mythos roller Fixes: Fix to Text based Server Fix to Remote Admin Commands Fix to Pretty Print, from Core Fix to Splitter Nodes not being created Fix to massive amounts of images loading, from Core Fix to Map from gametree not showing to all clients Fix to gametree about menus Fix to Password Manager check on startup Fix to PC Sheets from tool nodes. They now use the tabber_panel Fixed Whiteboard ID to prevent random line or text deleting. Modified ID's to prevent non updated clients from ruining the fix. default_manifest.xml renamed to default_upmana.xml Fix to Update Manager; cleaner clode for saved repositories Fixes made to Settings Panel and no reactive settings when Ok is pressed Fixes to Alternity roller's attack roll. Uses a simple Tuple instead of a Splice
author sirebral
date Thu, 10 Dec 2009 10:53:33 -0600
parents
children dcae32e219f1
comparison
equal deleted inserted replaced
166:eef2463cd441 167:5c9a118476b2
1 # (at your option) any later version.
2 # # This program is distributed in the hope that it will be useful,
3 # but WITHOUT ANY WARRANTY; without even the implied warranty of
4 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
5 # GNU General Public License for more details.
6 #
7 # You should have received a copy of the GNU General Public License
8 # along with this program; if not, write to the Free Software
9 # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
10 # --
11 #
12 # File: savage.py
13 # Authors: Rich Finder
14 # : Alexandre Major
15 # Maintainer:
16 # Version: 0.2
17 #
18 # Description: Savage Worlds die roller
19 # Permission was granted by Pinnacle to reprint the result descriptions from their tables on Apr 20, 2006 by Simon Lucas
20 #
21
22 __version__ = "$Id: savage.py,v 1.2 2007/05/06 16:42:55 digitalxero Exp $"
23
24 import string
25 from random import *
26
27 from std import std
28 from orpg.dieroller.base import *
29
30 # Savage, as in Savage Worlds
31 class sw(std):
32 #def __init__(self,source=[], wnd=1, loc="rnd", chmod=0):
33 def __init__(self,source=[],fmod=0):
34 std.__init__(self,source)
35
36 # these methods return new die objects for specific options
37
38 def fright(self,fearmod=0):
39 return fright(self,fearmod=0)
40
41 def kob(self,wnd,loc):
42 return kob(self,wnd=1,loc="rnd")
43
44 def ooc(self):
45 return ooc(self)
46
47 def ract(self,chmod=0):
48 return ract(self,chmod=0)
49
50 def vcrit(self):
51 return vcrit(self)
52
53 def fortune(self):
54 return fortune(self)
55
56 def freak(self):
57 return freak(self)
58
59 def swdhelps(self):
60 return swdhelps(self)
61
62 die_rollers.register(sw)
63
64 class fright(std):
65 #-----------------The Fright Table
66 # Rolls on the Fright - which is a 1d20 roll modified by the fear level of a monster. This function automatically generates
67 # The appropriate random number and then adds the fear modifier to the rol and displays the result of the roll with the effect
68 # of that roll.
69 # Usage: [fright()]
70 # [fright(6)] - if the fear modifier of the monster was 6
71 #-----------------
72 def __init__(self,fmod=0):
73 global fear
74 std.__init__(self)
75 fear=fmod
76
77 #def sum(self):
78
79 def __str__(self):
80 global fear
81 iroll = randint(1,20)
82 froll = iroll + fear
83 if froll >= 1 and froll <=4:
84 fresult = "Adrenaline Rush"
85 fdescription = "The hero's \"fight\" response takes over. He adds +2 to all Trait and damage rolls on his next action."
86 elif froll >= 5 and froll <=8:
87 fresult = "Shaken"
88 fdescription = "The character is Shaken."
89 elif froll >=9 and froll <=12:
90 fresult = "Pankicked"
91 fdescription = "The character immediately moves his full Pace plus running die away from the danger and is Shaken."
92 elif froll >=13 and froll <=16:
93 fresult = "Minor Phobia"
94 fdescription = "The character gains a Minor Phobia Hindrance somehow associated with the trauma."
95 elif froll >=17 and froll <=18:
96 fresult = "Major Phobia"
97 fdescription = "The character gains a Major Phobia Hindrance."
98 elif froll >=19 and froll <= 20:
99 fresult = "The Mark of Fear"
100 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."
101 else:
102 fresult = "Heart Attack"
103 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."
104 myStr = "[" + str(iroll) + "+"+str(fear)+"="+str(froll)+"] ==> " + fresult +": "+ fdescription
105 return myStr
106
107 class kob(std):
108 #-------------------The Knockout Blow Table
109 # This table used when a character has sustained more than 3 wounds. The number wounds taken that sends a character to the
110 # Knockout Blow Table is what gets sent with the kob command - not the total number of wounds the character currently has.
111 # 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
112 # 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
113 # table.
114 #
115 # It is also important to note that if a called shot to particular area was made, that information should be sent with the "roll"
116 # as well, because the KOB Table may need to determine some dramatic effects for permanent injuries, etc. If a hit location was sent
117 # the function will use that information.
118 # Valid Hit Locations are: h (head), g (guts), la (left arm), ra (right arm), rl (right leg), ll (left leg), c (crotch)
119 # Usage = [kob(3)] - If 3 wounds were received that sent the player to the Knockout Blow Table - no called shot
120 # [kob(3,"h") - If 3 wounds were received that sent the player to the Knockout Blow Table with a called shot to the head
121 #---------------------
122 global wound, loca
123 def __init__(self, wnd, loc="rnd"):
124 global wound, loca
125 std.__init__(self, wnd)
126 #Need to check to make sure that wnd is a number
127 if (int(wnd)):
128 wound = wnd
129 loca = loc
130 else:
131 mystr = "You need to supply a number for the wound."
132 return mystr
133
134 def __str__(self):
135 global wound, loca
136 itbl = "no"
137 if wound == 1:
138 wtype = "Battered and Bruised"
139 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."
140 elif wound == 2: #Need to roll on the Injury table as well
141 wtype = "Incapacitated"
142 wdescription = "Your hero is beaten badly enough to take him out of this fight. He's Incapacitated and must roll on the Injury Table."
143 itbl = "yes"
144 elif wound == 3:
145 wtype = "Bleeding Out"
146 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."
147 itbl = "yes"
148 elif wound < 1:
149 wtype = "No Wounds?"
150 wdescription = "The Number of wounds specified was less than one...why are you consulting this chart?"
151 else:
152 wtype = "Mortal Wound"
153 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."
154 itbl = "yes"
155
156 if itbl == "yes":
157 #Determine if a Hit location was specified already
158 if loca.lower() == "h":
159 iroll = 11
160 elif loca.lower() == "g":
161 iroll = 5
162 elif loca.lower() == "ra":
163 iroll = 3
164 aroll = 2
165 elif loca.lower() == "la":
166 iroll = 3
167 aroll = 1
168 elif loca.lower() == "rl":
169 iroll = 10
170 lroll = 2
171 elif loca.lower() == "ll":
172 iroll = 10
173 lroll = 1
174 elif loca.lower() == "c":
175 iroll = 2
176 else: #none of the above were provided...wo will need to determine randomly
177 iroll = randint(2,12)
178 #resolve the injury table stuff...
179 if iroll == 2:
180 iloc = "Unmentionables"
181 idescription = "The hero suffers an embarrassing and painful wound to the groin."
182 elif iroll == 3 or iroll == 4:
183 if loca != "ra" and loca != "la": # If a hit location was not specified (or not recognized) already, determine randomly
184 aroll = randint(1,2)
185 if aroll == 1:
186 warm = "Left"
187 else:
188 warm = "Right"
189 iloc = warm + " Arm"
190 idescription = "The arm is rendered useless."
191 elif iroll >= 5 and iroll <= 9: #will need to make another random roll
192 iloc = "Guts"
193 idescription = "Your hero catches one somewhere between the crotch and the chin."
194 groll = randint(1,6)
195 if groll == 1 or groll == 2:
196 #idescription += " <b>Broken (" + str(groll) + ")</b> His Agility is reduced by a die type (min dr)."
197 idescription += " <b>Broken (" + str(groll) + ")</b> His Agility is reduced by a die type (min d4)."
198 elif groll == 3 or groll == 4:
199 idescription += " <b>Battered (" + str(groll) + ")</b> His Vigor is reduced by a die type (min d4)."
200 else:
201 idescription += " <b>Busted (" + str(groll) + ")</b> His Strength is reduced by a die type (min d4)."
202 elif iroll == 10:
203 if loca != "ll" and loca != "rl": # If a hit location was not specified (or not recognized) already, determine randomly
204 lroll = randint(1,2)
205 if lroll == 1:
206 wleg = "Left"
207 else:
208 wleg = "Right"
209 iloc = wleg + " Leg"
210 idescription = "The character's leg is crushed, broken, or mangled. His Pace is reduced by 1."
211 else: #Will need to make another random roll for this one.
212 iloc = "Head"
213 idescription = "Your hero has suffered a grievous injury to his head."
214 hroll = randint(1,6) #determine how the head is impacted by the wound
215 if hroll == 1 or hroll ==2:
216 idescription += "<b>Hideous Scar (" + str(hroll) + ")</b>Your hero now has the Ugly Hindrance."
217 elif hroll == 3 or hroll == 4:
218 idescription += "<b>Blinded (" + str(hroll) + ")</b> One or both of your hero's eyes was damaged. He gains the Bad Eyes Hindrance."
219 else:
220 idescription += "<b>Brain Damage (" + str(hroll) + ")</b> Your hero suffers massive trauma to the head. His Smarts is reduced one die type (min d4)."
221 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."
222 if iroll == 2:
223 idescription +=" If the injury is permanent, reproduction is out of the question without miracle surgery or magic."
224 if loca != "h" and loca != "g" and loca != "c" and loca != "rl" and loca != "ll" and loca != "ra" and loca != "la":
225 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>"
226 myStr = "[" + wtype + "] ==>" + wdescription + "<br><br><b>Injury Table Result ("+ str(iroll) +"): </b> [" + iloc + "] ==> " + idescription
227 else:
228 myStr = "[" + wtype + "] ==>" + wdescription
229 return myStr
230
231 class ract(std):
232 #----------------------The Reaction Table
233 # This is used to randomly determine the general mood of NPCs toward the player characters. This simulates a 2d6 roll
234 # and displays the reaction. This roll can be modified by the Charisma of the player(s).
235 # Usage: [ract()] - No Charisma modifier
236 # [ract(2)] - A +2 Charisma modifier
237 # [ract(-2)] - A -2 Charisma modifier
238 #----------------------
239 global charisma
240 def __init__(self,chmod=0):
241 global charisma
242 std.__init__(self)
243 charisma = chmod
244
245 def __str__(self):
246 global charisma
247 r1roll = randint(2,12)
248 rroll = r1roll + charisma
249 if rroll == 2:
250 reaction = "Hostile"
251 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."
252 elif rroll >=3 and rroll <=4:
253 reaction = "Unfriendly"
254 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."
255 elif rroll >=5 and rroll <=9:
256 reaction = "Neutral"
257 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."
258 elif rroll >=10 and rroll <=11:
259 reaction = "Friendly"
260 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."
261 else:
262 reaction = "Helpful"
263 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."
264 #myStr = "[" + reaction + "(" + str(r1roll) + "+Charisma Mods("+str(charisma)+")="+str(rroll)+")] ==> " + rdescription
265 myStr = "["+str(r1roll)+"+"+str(charisma)+"(charisma modifier)="+str(rroll)+"] ==> "+reaction+": "+rdescription
266 return myStr
267
268 class ooc(std):
269 #--------------------The Out of Control Vehicle Table
270 # This table is used when a vehicle is injured during combat and must determine what happens to the vehicle. This is a 2d6
271 # roll and displays the results of the roll. This will also display altitude information for flying vehicles.
272 # Usage: [ooc()]
273 #--------------------
274 def __init__(self):
275 std.__init__(self)
276
277 def __str__(self):
278 ooroll = randint(2,12)
279 oodescripton = "Something"
280 if ooroll == 2:
281 ooeffect = "Roll Over"
282 rroll = randint(1,6)
283 oodescription = "The vehicle performs a Slip and rolls over "+ str(rroll)+ " time"
284 if rroll < 2:
285 oodescription +="s"
286 oodescription += " in that direction. Roll collision damage for the vehicle and everyone inside. Any exterior-mounted weapons or accessories are ruined."
287 elif ooroll == 3 or ooroll == 4:
288 ooeffect = "Spin"
289 sroll = randint(1,6)
290 froll = randint(1,12)
291 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."
292 elif ooroll >= 5 and ooroll <= 9:
293 ooeffect = "Skid"
294 sroll = randint(1,4)
295 oodescription = "Move the vehicle "+str(sroll)+"\" left or right (in the direction of a failed maneuver, or away from a damaging attack)."
296 elif ooroll == 10 or ooroll == 11:
297 ooeffect = "Slip"
298 sroll = randint(1,6)
299 oodescription = "Move the vehicle "+str(sroll)+"\" left or right (in the direction of a failed maneuver, or away from a damaging attack)."
300 else:
301 ooeffect = "Flip"
302 froll = randint(1,4)
303 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. "
304 shroll = randint(1,2)
305 if shroll == 1:
306 oodescription += "<br><br><b>Note:</b> If the vehicle is slow and/or heavy (such as a tank) it Slips instead: "
307 sroll = randint(1,6)
308 oodescription += "Move the vehicle "+str(sroll)+"\" left or right (in the direction of a failed maneuver, or away from a damaging attack)."
309 else:
310 oodescription += "<br><br><b>Note (GM's discretion):</b> If the vehicle is slow and/or heavy (such as a tank) it Skids instead: "
311 sroll = randint(1,4)
312 oodescription += "Move the vehicle "+str(sroll)+"\" left or right (in the direction of a failed maneuver, or away from a damaging attack)."
313
314 oodescription += "<br><br>For flying vehicles conducting combat in the air, the vehicle"
315 altchange = randint(2,12)
316 if altchange == 2:
317 dwn = randint(2,20)
318 oodescription += " loses "+str(dwn)+"\" of altitude."
319 elif altchange == 3 or altchange == 4:
320 dwn = randint(1,10)
321 oodescription += " loses "+str(dwn)+"\" of altitude."
322 elif altchange >= 5 and altchange <= 9:
323 oodescription += " has no change in altitude."
324 else:
325 altup = randint(1,10)
326 oodescription += " gains "+str(altup)+"\" of altitude."
327 myStr = "[" + ooeffect + "(" + str(ooroll) + ")] ==> " + oodescription
328 return myStr
329
330 class vcrit(std):
331 #----------------The Critical Hit Vehicle Table
332 # This table generates a 2d6 roll to determine the Critical Hit results every time a vehicle takes a wound. There are no
333 # modifiers to this roll
334 # Usage [vcrit()]
335 #----------------
336 def __init__(self):
337 std.__init__(self)
338
339 def __str__(self):
340 chitroll = randint(2,12)
341 if chitroll == 2:
342 cheffect = "Scratch and Dent"
343 chdescription = "The attack merely scratches the paint. There's no permanent damage."
344 elif chitroll == 3:
345 cheffect = "Engine"
346 chdescription = "The engine is hit. Oil leaks, pistons misfire, etc. Acceleration is halved (round down). This does not affect deceleration, however."
347 elif chitroll == 4:
348 cheffect = "Locomotion"
349 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."
350 elif chitroll == 5: #Need to make an additional roll to see what direction the vehicle can turn...
351 cheffect = "Controls"
352 troll = randint(1,2)
353 if troll == 1:
354 aturn = "left"
355 else:
356 aturn = "right"
357 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."
358 elif chitroll >= 6 and chitroll <=8:
359 cheffect = "Chassis"
360 chdescription = "The vehicle suffers a hit in the body with no special effects."
361 elif chitroll == 9 or chitroll == 10:
362 cheffect = "Crew"
363 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."
364 elif chitroll == 11:
365 cheffect = "Weapon"
366 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)."
367 else:
368 cheffect = "Wrecked"
369 chdescription = "The vehicle is wrecked and automatically goes Out of Control.<br><br><b>[Out of Control]</b> ==>"+str(ooc())
370 myStr = "["+cheffect+" ("+str(chitroll)+")] ==> "+chdescription
371 return myStr
372
373 def ooc(self):
374 return vcritooc(self)
375
376 class swdhelps(std):
377 #Display help information for this die roller - it will list all the available commands, and how to use them
378 def __init__(self):
379 std.__init__(self)
380
381 def __str__(self):
382 myStr = "<table border='1' valign='top'>\
383 <tr>\
384 <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>\
385 </tr>\
386 <tr>\
387 <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>\
388 </tr>\
389 <tr>\
390 <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>\
391 </tr>\
392 <tr>\
393 <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>\
394 <ul>\
395 <li>h = head</li>\
396 <li>g = guts/other vital areas</li>\
397 <li>c = crotch/groin</li>\
398 <li>la = left arm</li>\
399 <li>ra = right arm</li>\
400 <li>ll = left leg</li>\
401 <li>rl = right leg</li>\
402 </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>\
403 </tr>\
404 <tr>\
405 <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>\
406 </tr>\
407 <tr>\
408 <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>\
409 </tr>\
410 <tr>\
411 <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>\
412 </tr>\
413 <tr>\
414 <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>\
415 </tr>\
416 <tr>\
417 <td><b>[freak()]</b></td><td>Rolls on the <b>Freak Event Table</b>.</td><td>[freak()]</td>\
418 </tr>\
419 <tr>\
420 <td><b>[swdhelps()]</b></td><td>Displays this help list.</td><td>[swdhelps()]</td>\
421 </tr>\
422 </table>"
423 return myStr
424
425 class fortune(std):
426 def __init___(self):
427 std.__init__(self)
428
429 def __str__(self):
430 forroll = randint(2,12)
431 if forroll == 2 or forroll == 12: #Need to roll on Freak Event Table
432 fortune = "Freak Event!"
433 fdescription = "Roll on the Freak Event Table.<br><br><b>[Freak Event Table]</b> ==> "+str(freak())
434 elif forroll == 3:
435 fortune = "Twist of Fate"
436 fdescription = "Take a benny from your opponent. If he does not have one, he must immediately remove any one Extra from play."
437 elif forroll == 4:
438 fortune = "The Quick and the Dead"
439 fdescription = "Swap one of your opponent's cards for any one of yours."
440 elif forroll == 5:
441 fortune = "Rally"
442 fdescription = "Pick any one unit on the board with Shaken figures. All those figures recover automatically."
443 elif forroll >= 6 and forroll <= 8:
444 fortune = "Hand of Fate"
445 fdescription = "Gain one extra benny."
446 elif forroll == 9:
447 fortune = "Close Call"
448 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."
449 elif forroll == 10:
450 fortune = "Teamwork"
451 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."
452 else:
453 fortune = "Out of Ammo"
454 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."
455 myStr = "["+fortune+" ("+str(forroll)+")] ==>"+fdescription
456 return myStr
457
458 def freak(self):
459 return fortunefreak(self)
460
461 class freak(std):
462 def __init__(self):
463 std.__init__(self)
464
465 def __str__(self):
466 feroll = randint(1,10)
467 if feroll == 1:
468 fevent = "Storm"
469 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."
470 elif feroll == 2:
471 fevent = "Fire!"
472 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."
473 elif feroll == 3:
474 fevent = "Blood Ties"
475 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."
476 elif feroll == 4:
477 fevent = "Death of a Hero"
478 inspireroll = randint(1,2)
479 if inspireroll == 1:
480 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."
481 else:
482 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."
483 elif feroll == 5:
484 fevent = "Fickle Fate"
485 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."
486 elif feroll == 6:
487 fevent = "Back from the Dead"
488 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."
489 elif feroll == 7:
490 fevent = "Bitter Cold/Heat"
491 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."
492 elif feroll == 8:
493 fevent = "Battle Tested"
494 fedescription = "Any one of your units improves any one skill or attribute a die type immediately."
495 elif feroll == 9:
496 fevent = "The Fog"
497 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)."
498 else:
499 fevent = "Reinforcements"
500 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."
501 myStr = "["+fevent+"("+str(feroll)+")] ==> "+fedescription
502 return myStr
503
504 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.
505 def __init__(self):
506 std.__init__(self)
507
508 def __str__(self):
509 return myStr