comparison orpg/dieroller/gurps.py @ 0:4385a7d0efd1 grumpy-goblin

Deleted and repushed it with the 'grumpy-goblin' branch. I forgot a y
author sirebral
date Tue, 14 Jul 2009 16:41:58 -0500
parents
children 449a8900f9ac
comparison
equal deleted inserted replaced
-1:000000000000 0:4385a7d0efd1
1 #This program is free software; you can redistribute it and/or
2 #modify it under the terms of the GNU General Public License
3 #as published by the Free Software Foundation; either version 2
4 #of the License, or (at your option) any later version.
5 #
6 #This program is distributed in the hope that it will be useful,
7 #but WITHOUT ANY WARRANTY; without even the implied warranty of
8 #MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9 #GNU General Public License for more details.
10 #
11 #You should have received a copy of the GNU General Public License
12 #along with this program; if not, write to the Free Software
13 #Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
14 # --
15 #
16 # File: gurps.py
17 # Version:
18 # $Id: gurps.py,v 1.3
19 #
20 # Description: Modified Hero System die roller based on DJM and Heroman's Hero
21 # dieroller
22 #
23 # GURPS is a trademark of Steve Jackson Games, and its rules and art are
24 # copyrighted by Steve Jackson Games. All rights are reserved by Steve Jackson
25 # Games. This game aid is the original creation of Naryt with help from Pyrandon
26 # and is released for free distribution, and not for resale, under the
27 # permissions granted in the Steve Jackson Games Online Policy.
28 # http://www.sjgames.com/general/online_policy.html
29 #
30 # Errors should be reported to rpg@ormonds.net
31 #
32 # Changelog:
33 # V 1.3 2007/03/23 Thomas M. Edwards <tmedwards@motoslave.net>
34 # Fixed gurpsskill, gurpsdefaultskill, and gurpssupernatural to correctly
35 # return a normal failure when the roll is 17 and the effective skill is 27+;
36 # previously, they would erroneously return a critical failure. This fix also
37 # corrects the less serious issue whereby rolls of 17 and an effective skill
38 # of 17-26 would report "failure by X" instead of merely "failure", which is
39 # wrong as the only reason the roll failed was because a 17 was rolled, not
40 # because the roll exceeded the effective skill.
41 # V 1.2 29 October 2006, added defaultskill (Rule of 20 [B344]), supernatural
42 # (Rule of 16 [B349]). The frightcheck roll is now the actual Fright Check
43 # (with Rule of 14 [B360]) and a lookup oon the Fright Check Table if needed.
44 # The fightcheckfail roll is the old Fright Check Table lookup.
45 # Removes the Help roller as it was nothing but trouble, see
46 # http://openrpg.wrathof.com/repository/GURPS/GURPS_Roller_1.7.xml for help
47 # in using this roller.
48 # 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
49 # Corrects numerous descriptions
50 # v.1 original gurps release by Naryt 2005/10/17 16:34:00
51
52 from die import *
53 from time import time, clock
54 import random
55
56
57 __version__ = "$Id: gurps.py,v 1.5 2007/05/06 16:42:55 digitalxero Exp $"
58
59 # gurps
60
61 class gurps(std):
62 def __init__(self,source=[]):
63 std.__init__(self,source)
64
65 # these methods return new die objects for specific options
66
67 # Original msk roll renamed to be easier to understand/remember
68 def skill(self,skill,mod):
69 return gurpsskill(self,skill,mod)
70
71 def defaultskill(self,stat,defaultlevel,mod):
72 return gurpsdefaultskill(self,stat,defaultlevel,mod)
73
74 def supernatural(self,skill,resistance,mod):
75 return gurpssupernatural(self,skill,resistance,mod)
76
77 def crit_hit(self):
78 return gurpscrit_hit(self)
79
80 def crit_headblow(self):
81 return gurpscrit_headblow(self)
82
83 def crit_miss(self):
84 return gurpscrit_miss(self)
85
86 def crit_unarm(self):
87 return gurpscrit_unarm(self)
88
89 def spellfail(self):
90 return gurpsspellfail(self)
91
92 def frightcheck(self,level,mod):
93 return gurpsfrightcheck(self,level,mod)
94
95 def frightcheckfail(self,mod):
96 return gurpsfrightcheckfail(self,mod)
97
98 class gurpsskill(std):
99 def __init__(self,source=[],skill=0,mod=0):
100 std.__init__(self,source)
101 self.skill = skill
102 self.mod = mod
103
104 def is_success(self):
105 return (((self.sum()) <= self.skill+self.mod) and (self.sum() < 17))
106
107 def __str__(self):
108 myStr = "[" + str(self.data[0])
109 for a in self.data[1:]:
110 myStr += ","
111 myStr += str(a)
112 myStr +="]"
113 myStr += " = <b>" + str(self.sum()) + "</b>"
114 myStr += " vs <b>(" + str(self.skill+self.mod) + ")</b>"
115
116 Diff = abs((self.skill+self.mod) - self.sum())
117
118 if self.is_success():
119 if self.sum() == 3 or self.sum() == 4:
120 myStr += " or less <font color='#ff0000'><b>Critical Success!</b></font> [B556]"
121 elif self.sum() == 5 and (self.skill+self.mod > 14):
122 myStr += " or less <font color='#ff0000'><b>Critical Success!</b> by " + str(Diff) +" </font> [B556]"
123 elif self.sum() == 6 and (self.skill+self.mod > 15):
124 myStr += " or less <font color='#ff0000'><b>Critical Success!</b> by " + str(Diff) +" </font> [B556]"
125 else:
126 myStr += " or less <font color='#ff0000'><b>Success!</b> by " + str(Diff) +" </font>"
127 else:
128 if self.sum() == 18:
129 myStr += " or less <font color='#ff0000'><b>Critical Failure!</b></font> [B556]"
130 # elif self.sum() == 17 and (self.skill+self.mod < 16):
131 # myStr += " or less <font color='#ff0000'><b>Critical Failure!</b></font> [B556]"
132 elif self.sum() == 17:
133 if (self.skill+self.mod) < 16:
134 myStr += " or less <font color='#ff0000'><b>Critical Failure!</b></font> [B556]"
135 else:
136 myStr += " or less <font color='#ff0000'><b>Failure!</b></font> [B556]"
137 elif Diff > 9:
138 myStr += " or less <font color='#ff0000'><b>Critical Failure!</b> by " + str(Diff) +" </font> [B556]"
139 else:
140 myStr += " or less <font color='#ff0000'><b>Failure!</b> by " + str(Diff) +" </font>"
141
142 return myStr
143
144 class gurpsdefaultskill(std):
145 def __init__(self,source=[],stat=0,defaultlevel=0,mod=0):
146 std.__init__(self,source)
147 self.stat = stat
148 self.defaultlevel = defaultlevel
149 self.mod = mod
150
151 def is_success(self):
152 if self.stat < 21:
153 intSkillVal = self.stat + self.defaultlevel + self.mod
154 else:
155 intSkillVal = 20 + self.defaultlevel + self.mod
156 return (((self.sum()) <= intSkillVal) and (self.sum() < 17))
157
158 def __str__(self):
159 myStr = "[" + str(self.data[0])
160 for a in self.data[1:]:
161 myStr += ","
162 myStr += str(a)
163 myStr +="]"
164 myStr += " = <b>" + str(self.sum()) + "</b>"
165 strRule = ""
166 if self.stat < 21:
167 intSkillVal = self.stat + self.defaultlevel + self.mod
168 else:
169 intSkillVal = 20 + self.defaultlevel + self.mod
170 strRule = "<br />Rule of 20 in effect [B173, B344]"
171
172 myStr += " vs <b>(" + str(intSkillVal) + ")</b>"
173
174 Diff = abs((intSkillVal) - self.sum())
175
176 if self.is_success():
177 if self.sum() == 3 or self.sum() == 4:
178 myStr += " or less <font color='#ff0000'><b>Critical Success!</b></font> [B556]"
179 elif self.sum() == 5 and (intSkillVal > 14):
180 myStr += " or less <font color='#ff0000'><b>Critical Success!</b> by " + str(Diff) +"</font> [B556]"
181 elif self.sum() == 6 and (intSkillVal > 15):
182 myStr += " or less <font color='#ff0000'><b>Critical Success!</b> by " + str(Diff) +"</font> [B556]"
183 else:
184 myStr += " or less <font color='#ff0000'><b>Success!</b> by " + str(Diff) +"</font>"
185 else:
186 if self.sum() == 18:
187 myStr += " or less <font color='#ff0000'><b>Critical Failure!</b></font> [B556]"
188 elif self.sum() == 17:
189 if intSkillVal < 16:
190 myStr += " or less <font color='#ff0000'><b>Critical Failure!</b></font> [B556]"
191 else:
192 myStr += " or less <font color='#ff0000'><b>Failure!</b></font> [B556]"
193 elif Diff > 9:
194 myStr += " or less <font color='#ff0000'><b>Critical Failure!</b> by " + str(Diff) +"</font> [B556]"
195 else:
196 myStr += " or less <font color='#ff0000'><b>Failure!</b> by " + str(Diff) +"</font>"
197
198 myStr += strRule
199 return myStr
200
201 class gurpssupernatural(std):
202 def __init__(self,source=[],skill=0,resistance=0,mod=0):
203 std.__init__(self,source)
204 self.skill = skill
205 self.resistance = resistance
206 self.mod = mod
207
208 def is_success(self):
209 if self.skill+self.mod > 16:
210 if self.resistance > 16:
211 if self.resistance > self.skill+self.mod:
212 newSkill = self.skill+self.mod
213 else:
214 newSkill = self.resistance
215 else:
216 newSkill = 16
217 else:
218 newSkill = self.skill+self.mod
219 return (((self.sum()) <= newSkill) and (self.sum() < 17))
220
221 def __str__(self):
222 myStr = "[" + str(self.data[0])
223 for a in self.data[1:]:
224 myStr += ","
225 myStr += str(a)
226 myStr +="]"
227 myStr += " = <b>" + str(self.sum()) + "</b>"
228 strRule = ""
229 if self.skill+self.mod > 16:
230 if self.resistance > 16:
231 if self.resistance > self.skill+self.mod:
232 newSkill = self.skill+self.mod
233 strRule = "<br />Rule of 16: Subject's Resistance is higher than skill, no change in skill [B349]"
234 else:
235 newSkill = self.resistance
236 strRule = "<br />Rule of 16: Effective skill limited by subject's Resistance [B349]"
237 else:
238 newSkill = 16
239 strRule = "<br />Rule of 16: Effective skill limited to 16 [B349]"
240 else:
241 newSkill = self.skill+self.mod
242 myStr += " vs <b>(" + str(newSkill) + ")</b>"
243
244 Diff = abs((newSkill) - self.sum())
245
246 if self.is_success():
247 if self.sum() == 3 or self.sum() == 4:
248 myStr += " or less <font color='#ff0000'><b>Critical Success!</b></font> [B556]"
249 elif self.sum() == 5 and (newSkill > 14):
250 myStr += " or less <font color='#ff0000'><b>Critical Success!</b> by " + str(Diff) +" </font> [B556]"
251 elif self.sum() == 6 and (newSkill > 15):
252 myStr += " or less <font color='#ff0000'><b>Critical Success!</b> by " + str(Diff) +" </font> [B556]"
253 else:
254 myStr += " or less <font color='#ff0000'><b>Success!</b> by " + str(Diff) +" </font>"
255 else:
256 if self.sum() == 18:
257 myStr += " or less <font color='#ff0000'><b>Critical Failure!</b></font> [B556]"
258 elif self.sum() == 17:
259 if newSkill < 16:
260 myStr += " or less <font color='#ff0000'><b>Critical Failure!</b></font> [B556]"
261 else:
262 myStr += " or less <font color='#ff0000'><b>Failure!</b></font> [B556]"
263 elif Diff > 9:
264 myStr += " or less <font color='#ff0000'><b>Critical Failure!</b> by " + str(Diff) +" </font> [B556]"
265 else:
266 myStr += " or less <font color='#ff0000'><b>Failure!</b> by " + str(Diff) +" </font>"
267
268 myStr += strRule
269 return myStr
270
271 class gurpscrit_hit(std):
272 def __init__(self,source=[],mod=0):
273 std.__init__(self,source)
274
275 def __str__(self):
276 myStr = "[" + str(self.data[0]) #Variable myStr holds text and first we put a [ into it and then adds the first die rolled
277 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.
278 myStr += "," #Adds a comma after each die
279 myStr += str(a) #Adds the value of each die.
280 myStr += "] = " #Adds ] = to the end of the string (note the += means append to whatever is already stored in the variable
281 myStr += str(self.sum()) #Finally we add the actual result of the roll and myStr contains something like [3,2,1] = 6
282
283 if self.sum() > 8 and self.sum() < 12:
284 myStr += " <font color='#ff0000'>The blow inflicts normal damage.</font> [B556]"
285 elif self.sum() == 12:
286 myStr += " <font color='#ff0000'>The blow inflicts normal damage, AND victim drops anything they hold--even if no damage penetrates DR.</font> [B556]"
287 elif self.sum() == 8:
288 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]"
289 elif self.sum() == 13 or self.sum() == 14 or self.sum() == 7:
290 myStr += " <font color='#ff0000'>If any damage penetrates DR, treat as major wound. See [B420] for major wounds.</font> [B556]"
291 elif self.sum() == 6 or self.sum() == 15:
292 myStr += " <font color='#ff0000'>The blow inflicts maximum normal damage.</font> [B556]"
293 elif self.sum() == 5 or self.sum() == 16:
294 myStr += " <font color='#ff0000'>The blow inflicts double damage.</font> [B556]"
295 elif self.sum() == 4 or self.sum() == 17:
296 myStr += " <font color='#ff0000'>The victim's DR protects at half value, rounded down, after applying any armor divisors.</font> [B556]"
297 elif self.sum() == 3 or self.sum() == 18 :
298 myStr += " <font color='#ff0000'>The blow inflicts triple damage.</font> [B556]"
299
300 return myStr
301
302 class gurpscrit_headblow(std):
303 def __init__(self,source=[],mod=0):
304 std.__init__(self,source)
305
306 def __str__(self):
307 myStr = "[" + str(self.data[0]) #Variable myStr holds text and first we put a [ into it and then adds the first die rolled
308 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.
309 myStr += "," #Adds a comma after each die
310 myStr += str(a) #Adds the value of each die.
311 myStr += "] = " #Adds ] = to the end of the string (note the += means append to whatever is already stored in the variable
312 myStr += str(self.sum()) #Finally we add the actual result of the roll and myStr contains something like [3,2,1] = 6
313
314 if self.sum() > 8 and self.sum() < 12:
315 myStr += " <font color='#ff0000'>The blow inflicts normal damage.</font> [B556]"
316 elif self.sum() == 12 or self.sum() == 13:
317 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]"
318 elif self.sum() == 8:
319 myStr += " <font color='#ff0000'>Normal damage to head, but victim knocked off balance: must Do Nothing until next turn (but can defend).</font> [B556]"
320 elif self.sum() == 14:
321 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]"
322 elif self.sum() == 6 or self.sum() == 7:
323 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]"
324 elif self.sum() == 15:
325 myStr += " <font color='#ff0000'>The blow inflicts maximum normal damage.</font> [B556]"
326 elif self.sum() == 16:
327 myStr += " <font color='#ff0000'>The blow inflicts double damage.</font> [B556]"
328 elif self.sum() == 4 or self.sum() == 5:
329 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]"
330 elif self.sum() == 17:
331 myStr += " <font color='#ff0000'>The victim's DR protects at half value, rounded up, after applying any armor divisors.</font> [B556]"
332 elif self.sum() == 3:
333 myStr += " <font color='#ff0000'>The blow inflicts maximum normal damage AND ignores all DR.</font> [B556]"
334 elif self.sum() == 18:
335 myStr += " <font color='#ff0000'>The blow inflicts triple damage.</font> [B556]"
336
337 return myStr
338
339 class gurpscrit_miss(std):
340 def __init__(self,source=[],mod=0):
341 std.__init__(self,source)
342
343 def __str__(self):
344 myStr = "[" + str(self.data[0]) #Variable myStr holds text and first we put a [ into it and then adds the first die rolled
345 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.
346 myStr += "," #Adds a comma after each die
347 myStr += str(a) #Adds the value of each die.
348 myStr += "] = " #Adds ] = to the end of the string (note the += means append to whatever is already stored in the variable
349 myStr += str(self.sum()) #Finally we add the actual result of the roll and myStr contains something like [3,2,1] = 6
350
351 if self.sum() > 8 and self.sum() < 12:
352 myStr += " <font color='#ff0000'>You drop your weapon (& a <i>cheap</i> weapon breaks).</font> [B556]"
353 elif self.sum() == 12 or self.sum() == 8:
354 myStr += " <font color='#ff0000'>Your weapon turns in your hand; must Ready it before it can be used again.</font> [B556]"
355 elif self.sum() == 13 or self.sum() == 7:
356 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]"
357 elif self.sum() == 14:
358 yrdStr = str(int(random.uniform(1,7)))
359 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]"
360 elif self.sum() == 6:
361 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]"
362 elif self.sum() == 15:
363 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]"
364 elif self.sum() == 16:
365 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]"
366 elif self.sum() == 5:
367 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]"
368 elif self.sum() == 4 or self.sum() == 3 or self.sum() == 17 or self.sum() == 18:
369 broke = int(random.uniform(3,19))
370 if broke >=5 and broke <=16:
371 brokestr = "it is dropped."
372 else:
373 brokestr = "the weapon also breaks!"
374 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."
375
376 return myStr
377
378 class gurpscrit_unarm(std):
379 def __init__(self,source=[],mod=0):
380 std.__init__(self,source)
381
382 def __str__(self):
383 myStr = "[" + str(self.data[0]) #Variable myStr holds text and first we put a [ into it and then adds the first die rolled
384 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.
385 myStr += "," #Adds a comma after each die
386 myStr += str(a) #Adds the value of each die.
387 myStr += "] = " #Adds ] = to the end of the string (note the += means append to whatever is already stored in the variable
388 myStr += str(self.sum()) #Finally we add the actual result of the roll and myStr contains something like [3,2,1] = 6
389
390 if self.sum() > 8 and self.sum() < 12:
391 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]"
392 elif self.sum() == 12:
393 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]"
394 elif self.sum() == 8:
395 myStr += " <font color='#ff0000'>You fall down!</font> [B557]"
396 elif self.sum() == 13:
397 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]"
398 elif self.sum() == 7 or self.sum() == 14:
399 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]"
400 elif self.sum() == 15:
401 mslStr = str(int(random.uniform(1,4)))
402 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]"
403 elif self.sum() == 6:
404 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]"
405 elif self.sum() == 5 or self.sum() == 16:
406 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]"
407 elif self.sum() == 4:
408 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]"
409 elif self.sum() == 17:
410 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]"
411 elif self.sum() == 3 or self.sum() == 18 :
412 myStr += " <font color='#ff0000'>You knock yourself out! Roll vs. HT every 30 min. to recover.</font> [B557]"
413
414 return myStr
415
416 class gurpsspellfail(std):
417 def __init__(self,source=[],mod=0):
418 std.__init__(self,source)
419
420 def __str__(self):
421 myStr = "[" + str(self.data[0])
422 for a in self.data[1:]:
423 myStr += ","
424 myStr += str(a)
425 myStr +="]"
426 myStr += " = <b>" + str(self.sum()) + "</b>"
427
428 if self.sum() == 10 or self.sum() == 11:
429 myStr += " <font color='#ff0000'>Spell produces nothing but a loud noise, bright flash, awful odor, etc.</font> [B236]"
430 elif self.sum() == 9:
431 myStr += " <font color='#ff0000'>Spell fails entirely. Caster is stunned (IQ roll to recover).</font> [B236]"
432 elif self.sum() == 12:
433 myStr += " <font color='#ff0000'>Spell produces a weak and useless shadow of the intended effect.</font> [B236]"
434 elif self.sum() == 8:
435 myStr += " <font color='#ff0000'>Spell fails entirely. Caster takes 1 point of damage.</font> [B236]"
436 elif self.sum() == 13:
437 myStr += " <font color='#ff0000'>Spell produces the reverse of the intended effect.</font> [B236]"
438 elif self.sum() == 7:
439 myStr += " <font color='#ff0000'>Spell affects someone or something other than the intended subject.</font> [B236]"
440 elif self.sum() == 14:
441 myStr += " <font color='#ff0000'>Spell seems to work, but it is only a useless illusion.</font> [B236]"
442 elif self.sum() == 5 or self.sum() == 6:
443 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]"
444 elif self.sum() == 15 or self.sum() == 16:
445 myStr += " <font color='#ff0000'>Spell has the reverse of the intended, on the wrong target. Roll randomly.</font> [B236]"
446 elif self.sum() == 4:
447 myStr += " <font color='#ff0000'>Spell is cast on caster (if harmful) or on a random nearby foe (if beneficial).</font> [B236]"
448 elif self.sum() == 17:
449 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]"
450 elif self.sum() == 3:
451 myStr += " <font color='#ff0000'>Spell fails entirely. Caster takes 1d of injury.</font> [B236]"
452 elif self.sum() == 18:
453 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]"
454
455 return myStr
456
457 class gurpsfrightcheck(std):
458 def __init__(self,source=[],skill=0,mod=0):
459 std.__init__(self,source)
460 self.skill = skill
461 self.mod = mod
462
463 def is_success(self):
464 return (((self.sum()) <= self.skill+self.mod) and (self.sum() < 14))
465
466 def __str__(self):
467 myStr = "[" + str(self.data[0])
468 for a in self.data[1:]:
469 myStr += ","
470 myStr += str(a)
471 myStr +="]"
472 myStr += " = <b>" + str(self.sum()) + "</b>"
473
474 if self.skill+self.mod < 14:
475 myStr += " vs <b>(" + str(self.skill+self.mod) + ")</b>"
476 Diff = abs((self.skill+self.mod) - self.sum())
477 else:
478 myStr += " vs <b>(13)</b>"
479 Diff = abs(13 - self.sum())
480
481 if self.is_success():
482 if self.sum() == 3 or self.sum() == 4:
483 myStr += " or less <font color='#ff0000'><b>Critical Success!</b></font> [B556]"
484 else:
485 myStr += " or less <font color='#ff0000'><b>Success!</b> by " + str(Diff) +" </font>"
486 else:
487 myStr += " or less <font color='#ff0000'><b>Failure!</b> by " + str(Diff) +" </font>"
488
489 if self.skill + self.mod > 13:
490 myStr += " Rule of 14 in effect [B360]"
491
492 if not(self.is_success()):
493 intD1 = int(random.uniform(1,7))
494 intD2 = int(random.uniform(1,7))
495 intD3 = int(random.uniform(1,7))
496 intFright = intD1 + intD2 + intD3 + Diff
497 myStr += "<br />Rolling on Fright Check Table<br />[" + str(intD1) + "," + str(intD2) + "," + str(intD3) + "] ==> " + str(intFright - Diff) + " + " + str(Diff) + " = " + str(intFright) + "<br />"
498 if intFright < 6:
499 myStr += "<font color='#ff0000'>Stunned for one second, then recover automatically.</font> [B360]"
500 elif intFright < 8:
501 myStr += "<font color='#ff0000'>Stunned for one second. Every second after that, roll vs. unmodified Will to snap out of it.</font> [B360]"
502 elif intFright < 10:
503 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]"
504 elif intFright == 10:
505 strStun = str(int(random.uniform(1,7)))
506 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]"
507 elif intFright == 11:
508 strStun = str(int(random.uniform(2,13)))
509 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]"
510 elif intFright == 12:
511 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]"
512 elif intFright == 13:
513 myStr += "<font color='#ff0000'>Acquire a new mental quirk.</font> [B361]"
514 elif intFright < 16:
515 strFP = str(int(random.uniform(1,7)))
516 strSeconds = str(int(random.uniform(1,7)))
517 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]"
518 elif intFright == 16:
519 strSeconds = str(int(random.uniform(1,7)))
520 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]"
521 elif intFright == 17:
522 strMinutes = str(int(random.uniform(1,7)))
523 myStr += "<font color='#ff0000'>Faint for " + strMinutes + " minutes. Every minute after that roll vs. HT to recover.</font> [B361]"
524 elif intFright == 18:
525 strMinutes = str(int(random.uniform(1,7)))
526 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]"
527 elif intFright == 19:
528 strMinutes = str(int(random.uniform(2,13)))
529 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]"
530 elif intFright == 20:
531 strMinutes = str(int(random.uniform(4,25)))
532 strFP = str(int(random.uniform(1,7)))
533 myStr += "<font color='#ff0000'>Faint bordering on shock, lastering for " + strMinutes + " minutes. Also, lose " + strFP + " FP.</font> [B361]"
534 elif intFright == 21:
535 strMinutes = str(int(random.uniform(1,7)))
536 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]"
537 elif intFright == 22:
538 myStr += "<font color='#ff0000'>Acquire a new -10-point Delusion (B130).</font> [B361]"
539 elif intFright == 23:
540 myStr += "<font color='#ff0000'>Acquire a new -10-point Phobia (B148) or other -10-point mental disadvantage.</font> [B361]"
541 elif intFright == 24:
542 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]"
543 elif intFright == 25 :
544 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]"
545 elif intFright == 26:
546 strMinutes = str(int(random.uniform(1,7)))
547 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]"
548 elif intFright == 27:
549 strMinutes = str(int(random.uniform(1,7)))
550 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]"
551 elif intFright == 28:
552 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]"
553 elif intFright == 29:
554 strHours = str(int(random.uniform(1,7)))
555 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]"
556 elif intFright == 30:
557 strDays = str(int(random.uniform(1,7)))
558 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]"
559 elif intFright == 31:
560 strMinutes = str(int(random.uniform(1,7)))
561 strFP = str(int(random.uniform(1,7)))
562 strInjury = str(int(random.uniform(1,7)))
563 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]"
564 elif intFright == 32:
565 strInjury = str(int(random.uniform(2,13)))
566 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]"
567 elif intFright == 33:
568 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]"
569 elif intFright == 34:
570 myStr += "<font color='#ff0000'>Acquire a new -15-point Delusion (B130).</font> [B361]"
571 elif intFright == 35:
572 myStr += "<font color='#ff0000'>Acquire a new -15-point Phobia (B148) or other -15-point mental disadvantage.</font> [B361]"
573 elif intFright == 36:
574 myStr += "<font color='#ff0000'>Severe physical effect, set by the GM. (Acquire -20 points worth of physical disadvantages, aging = -3 per year).</font> [B361]"
575 elif intFright == 37:
576 myStr += "<font color='#ff0000'>Severe physical effect, set by the GM. (Acquire -30 points worth of physical disadvantages, aging = -3 per year).</font> [B361]"
577 elif intFright == 39:
578 strHours = str(int(random.uniform(1,7)))
579 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]"
580 elif intFright == 39:
581 strHours = str(int(random.uniform(1,7)))
582 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]"
583 else:
584 strHours = str(int(random.uniform(1,7)))
585 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]"
586 return myStr
587
588 class gurpsfrightcheckfail(std):
589 def __init__(self,source=[],mod=0):
590 std.__init__(self,source)
591 self.mod = mod
592
593 def __str__(self):
594 myStr = "[" + str(self.data[0])
595 for a in self.data[1:]:
596 myStr += ","
597 myStr += str(a)
598 myStr +="] + " + str(self.mod)
599 intFright = self.sum() + self.mod
600 myStr += " = <b>" + str(intFright) + "</b> "
601
602 if intFright < 6:
603 myStr += "<font color='#ff0000'>Stunned for one second, then recover automatically.</font> [B360]"
604 elif intFright < 8:
605 myStr += "<font color='#ff0000'>Stunned for one second. Every second after that, roll vs. unmodified Will to snap out of it.</font> [B360]"
606 elif intFright < 10:
607 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]"
608 elif intFright == 10:
609 strStun = str(int(random.uniform(1,7)))
610 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]"
611 elif intFright == 11:
612 strStun = str(int(random.uniform(2,13)))
613 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]"
614 elif intFright == 12:
615 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]"
616 elif intFright == 13:
617 myStr += "<font color='#ff0000'>Acquire a new mental quirk.</font> [B361]"
618 elif intFright < 16:
619 strFP = str(int(random.uniform(1,7)))
620 strSeconds = str(int(random.uniform(1,7)))
621 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]"
622 elif intFright == 16:
623 strSeconds = str(int(random.uniform(1,7)))
624 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]"
625 elif intFright == 17:
626 strMinutes = str(int(random.uniform(1,7)))
627 myStr += "<font color='#ff0000'>Faint for " + strMinutes + " minutes. Every minute after that roll vs. HT to recover.</font> [B361]"
628 elif intFright == 18:
629 strMinutes = str(int(random.uniform(1,7)))
630 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]"
631 elif intFright == 19:
632 strMinutes = str(int(random.uniform(2,13)))
633 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]"
634 elif intFright == 20:
635 strMinutes = str(int(random.uniform(4,25)))
636 strFP = str(int(random.uniform(1,7)))
637 myStr += "<font color='#ff0000'>Faint bordering on shock, lastering for " + strMinutes + " minutes. Also, lose " + strFP + " FP.</font> [B361]"
638 elif intFright == 21:
639 strMinutes = str(int(random.uniform(1,7)))
640 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]"
641 elif intFright == 22:
642 myStr += "<font color='#ff0000'>Acquire a new -10-point Delusion (B130).</font> [B361]"
643 elif intFright == 23:
644 myStr += "<font color='#ff0000'>Acquire a new -10-point Phobia (B148) or other -10-point mental disadvantage.</font> [B361]"
645 elif intFright == 24:
646 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]"
647 elif intFright == 25 :
648 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]"
649 elif intFright == 26:
650 strMinutes = str(int(random.uniform(1,7)))
651 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]"
652 elif intFright == 27:
653 strMinutes = str(int(random.uniform(1,7)))
654 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]"
655 elif intFright == 28:
656 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]"
657 elif intFright == 29:
658 strHours = str(int(random.uniform(1,7)))
659 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]"
660 elif intFright == 30:
661 strDays = str(int(random.uniform(1,7)))
662 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]"
663 elif intFright == 31:
664 strMinutes = str(int(random.uniform(1,7)))
665 strFP = str(int(random.uniform(1,7)))
666 strInjury = str(int(random.uniform(1,7)))
667 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]"
668 elif intFright == 32:
669 strInjury = str(int(random.uniform(2,13)))
670 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]"
671 elif intFright == 33:
672 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]"
673 elif intFright == 34:
674 myStr += "<font color='#ff0000'>Acquire a new -15-point Delusion (B130).</font> [B361]"
675 elif intFright == 35:
676 myStr += "<font color='#ff0000'>Acquire a new -15-point Phobia (B148) or other -15-point mental disadvantage.</font> [B361]"
677 elif intFright == 36:
678 myStr += "<font color='#ff0000'>Severe physical effect, set by the GM. (Acquire -20 points worth of physical disadvantages, aging = -3 per year).</font> [B361]"
679 elif intFright == 37:
680 myStr += "<font color='#ff0000'>Severe physical effect, set by the GM. (Acquire -30 points worth of physical disadvantages, aging = -3 per year).</font> [B361]"
681 elif intFright == 39:
682 strHours = str(int(random.uniform(1,7)))
683 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]"
684 elif intFright == 39:
685 strHours = str(int(random.uniform(1,7)))
686 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]"
687 else:
688 strHours = str(int(random.uniform(1,7)))
689 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]"
690
691 return myStr