171
|
1 # (at your option) any later version.
|
|
2 #
|
|
3 # This program is distributed in the hope that it will be useful,
|
|
4 # but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
5 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
6 # GNU General Public License for more details.
|
|
7 #
|
|
8 # You should have received a copy of the GNU General Public License
|
|
9 # along with this program; if not, write to the Free Software
|
|
10 # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
11 #
|
|
12 #-------------------------------------------------------------------------
|
|
13 #
|
|
14 # Usage:
|
|
15 #
|
|
16 # Die Roller: /dieroller rq
|
|
17 #
|
|
18 # Skill Roll: [1d100.skill(50,0,0)] # ( skill%, modifer, MA% )
|
|
19 #
|
|
20 # Parry Roll: [1d100.parry(50,0,0,12)] # ( skill%, modifer, MA%, Weapon/Shield AP )
|
|
21 #
|
|
22 # Dodge Roll: [1d100.parry(50,0,0)] # ( skill%, modifer, MA% )
|
|
23 #
|
|
24 # Attack Roll: [1d100.attack(50,0,0,2,9,3,0)]
|
|
25 # ( skill%, modifer, MA%, min weap dam, max weap dam, dam bonus, truesword )
|
|
26 #
|
|
27 # Sorcery Roll: [1d100.sorcery(90, 0, 3, 6, 1, 1, 1)]
|
|
28 # (sk, mod, pow, cer, int, acc, mlt)
|
|
29 #
|
|
30 #
|
|
31 #
|
|
32 # Skill Training Unlimited Roll: [1d100.trainskill(30,75)] # (starting skill%, desired skill%)
|
|
33 # Skill Training Cost Limited: [1d100.trainskillcost(1000, 50) # (payment, starting skill%)
|
|
34 # Skill Training Time Limited: [1d100.trainskilltime(150, 50) # (time, strting skill%)
|
|
35 #
|
|
36 #-------------------------------------------------------------------------
|
|
37 # --
|
|
38 #
|
|
39 # File: rq.py
|
|
40 # Version:
|
|
41 # $Id: rq.py,v .1 pelwer
|
|
42 #
|
|
43 # Description: Runequest die roller originally based on Heroman's Hero Dieroller
|
|
44 #
|
|
45 #
|
|
46 # v.1 - pelwer - 2/5/2005
|
|
47 # o Original release
|
|
48 # v.2 - pelwer - 10/30/2006
|
|
49 # o Ported to openrpg+ by removing dependance on whrandom
|
|
50 # o Fixed Riposte spelling
|
|
51 # o Deleted sorcalc - never used
|
|
52 # o Added Sorcery Fumble table to sorcery spell roller
|
|
53 #
|
|
54
|
|
55 __version__ = "$Id: runequest.py,v 1.4 2006/11/15 12:11:22 digitalxero Exp $"
|
|
56
|
|
57 from time import time, clock
|
|
58 import random
|
|
59 from math import floor
|
|
60
|
|
61 from std import std
|
|
62 from orpg.dieroller.base import *
|
|
63
|
|
64 # rq stands for "Runequest"
|
|
65
|
|
66 class runequest(std):
|
|
67 name = "runequest"
|
|
68 def __init__(self,source=[]):
|
|
69 std.__init__(self,source)
|
|
70
|
|
71 # these methods return new die objects for specific options
|
|
72
|
|
73 def skill(self,sk,mod,ma):
|
|
74 return rqskill(self,sk,mod,ma)
|
|
75
|
|
76 def parry(self,sk,mod,ma,AP):
|
|
77 return rqparry(self,sk,mod,ma,AP)
|
|
78
|
|
79 def dodge(self,sk,mod,ma):
|
|
80 return rqdodge(self,sk,mod,ma)
|
|
81
|
|
82 def attack(self,sk,mod,ma,mindam,maxdam,bondam,trueswd):
|
|
83 return rqattack(self,sk,mod,ma,mindam,maxdam,bondam,trueswd)
|
|
84
|
|
85 def sorcery(self,sk,mod,pow,cer,int,acc,mlt):
|
|
86 return rqsorcery(self,sk,mod,pow,cer,int,acc,mlt)
|
|
87
|
|
88 def trainskill(self,initial,final):
|
|
89 return rqtrainskill(self,initial,final)
|
|
90
|
|
91 def trainskillcost(self,cost,sk):
|
|
92 return rqtrainskillcost(self,cost,sk)
|
|
93
|
|
94 def trainskilltime(self,time,sk):
|
|
95 return rqtrainskilltime(self,time,sk)
|
|
96
|
|
97 die_rollers.register(runequest)
|
|
98
|
|
99 # RQ Skill Training Cost/Time unlimited
|
|
100 #
|
|
101 # [1d100.trainskill(10,20)]
|
|
102 # initial skill%, final skill%
|
|
103 #
|
|
104 # sk = skill %
|
|
105 #
|
|
106 #
|
|
107 class rqtrainskill(std):
|
|
108 def __init__(self,source=[],initial=11,final=0):
|
|
109 std.__init__(self,source)
|
|
110 self.s = initial
|
|
111 self.f = final
|
|
112
|
|
113 def __str__(self):
|
|
114 myStr = "Unrestricted Training"
|
|
115
|
|
116 if self.s == 0:
|
|
117 myStr = "Initial training completed for Cost(50) Time(20) Skill(1 + modifier)"
|
|
118 else:
|
|
119 cost = 0
|
|
120 time = 0
|
|
121 myStr = "Training: "
|
|
122
|
|
123 while self.s < self.f and self.s < 75:
|
|
124 cost += self.s * 5
|
|
125 time += self.s * 1
|
|
126 self.s += random.uniform(1,4) + 1
|
|
127
|
|
128 myStr = "Training completed:\n"
|
|
129 myStr += "\tCost(" + str(int(cost)) + ")\n"
|
|
130 myStr += "\tTime(" + str(int(time)) + ")\n"
|
|
131 myStr += "\tSkill(" + str(int(self.s)) + ")"
|
|
132
|
|
133 return myStr
|
|
134
|
|
135
|
|
136 # RQ Skill Training Cost Limited
|
|
137 #
|
|
138 # [1d100.trainskillcost(50,0)]
|
|
139 # cost, skill%
|
|
140 #
|
|
141 # cost = cash for training
|
|
142 # sk = skill %
|
|
143 #
|
|
144 #
|
|
145 class rqtrainskillcost(std):
|
|
146 def __init__(self,source=[],cost=11,sk=0):
|
|
147 std.__init__(self,source)
|
|
148 self.cost = cost
|
|
149 self.sk = sk
|
|
150
|
|
151 def __str__(self):
|
|
152 myStr = ""
|
|
153
|
|
154 if self.sk == 0 and self.cost >= 50:
|
|
155 myStr = "Initial training completed for Cost(50), Time(50), Skill(1 + modifier)"
|
|
156 else:
|
|
157 cost = 0
|
|
158 time = 0
|
|
159 icost = self.sk * 5
|
|
160
|
|
161 myStr = "Training: "
|
|
162
|
|
163 while (cost + icost) < self.cost:
|
|
164 if self.sk >= 75:
|
|
165 break
|
|
166
|
|
167 cost += icost
|
|
168 time += self.sk * 1
|
|
169 self.sk += random.uniform(1,4) + 1
|
|
170 icost = self.sk * 5
|
|
171
|
|
172 myStr = "Training completed: "
|
|
173 myStr += "Cost(" + str(int(cost)) + ") "
|
|
174 myStr += "Time(" + str(int(time)) + ") "
|
|
175 myStr += "Skill(" + str(int(self.sk)) + ")"
|
|
176
|
|
177 return myStr
|
|
178
|
|
179
|
|
180 # RQ Skill Training Time Limited
|
|
181 #
|
|
182 # [1d100.trainskilltime(50,0)]
|
|
183 # time, skill%
|
|
184 #
|
|
185 # time = time for training
|
|
186 # sk = skill %
|
|
187 #
|
|
188 #
|
|
189 class rqtrainskilltime(std):
|
|
190 def __init__(self,source=[],time=11,sk=0):
|
|
191 std.__init__(self,source)
|
|
192 self.time = time
|
|
193 self.sk = sk
|
|
194
|
|
195 def __str__(self):
|
|
196 myStr = ""
|
|
197
|
|
198 if self.sk == 0 and self.time >= 20:
|
|
199 myStr = "Initial training completed for Cost(50), Time(50), Skill(1 + modifier)"
|
|
200 else:
|
|
201 cost = 0
|
|
202 time = 0
|
|
203 itime = self.sk * 1
|
|
204
|
|
205 myStr = "Trainingsss: "
|
|
206
|
|
207 while (time + itime) < self.time:
|
|
208 if self.sk >= 75:
|
|
209 break
|
|
210
|
|
211 cost += self.sk * 5
|
|
212 time += itime
|
|
213 self.sk += random.uniform(1,4) + 1
|
|
214 itime = self.sk * 5
|
|
215
|
|
216 myStr = "Training completed: "
|
|
217 myStr += "Cost(" + str(int(cost)) + ") "
|
|
218 myStr += "Time(" + str(int(time)) + ") "
|
|
219 myStr += "Skill(" + str(int(self.sk)) + ")"
|
|
220
|
|
221 return myStr
|
|
222
|
|
223 # RQ Skill Roll
|
|
224 #
|
|
225 # [1d100.skill(50,0,0)]
|
|
226 # skill%, modifer, ma%
|
|
227 #
|
|
228 # sk = skill %
|
|
229 # mod = modifier %
|
|
230 # ma = martial arts %
|
|
231 # skill = sk + mod
|
|
232 #
|
|
233 # success roll <= skill
|
|
234 #
|
|
235 # failure roll > skill
|
|
236 #
|
|
237 # crit
|
|
238 # push( @{$::Cre{Weapons}{$weap_cnt}}, POSIX::floor( skill/20 ) );
|
|
239 #
|
|
240 # special
|
|
241 # push( @{$::Cre{Weapons}{$weap_cnt}}, POSIX::floor( $skill/5 ) );
|
|
242 #
|
|
243 # fumble: if ( $skill > 100 ) { $fum = 0; } else { $fum = 100 - $skill; }
|
|
244 # $fum = 100 - POSIX::floor( $fum/20 );
|
|
245 # if ( $fum == 100 ) { $fum = '00'; };
|
|
246 #
|
|
247 class rqskill(std):
|
|
248 def __init__(self,source=[],sk=11,mod=0,ma=0):
|
|
249 std.__init__(self,source)
|
|
250 self.sk = sk
|
|
251 self.mod = mod
|
|
252 self.ma = ma
|
|
253
|
|
254 def is_success(self):
|
|
255 return (((self.sum() <= (self.sk + self.mod)) or (self.sum() <= 5)) and (self.sum() <= 95))
|
|
256
|
|
257 def is_ma(self):
|
|
258 return (self.sum() <= self.ma)
|
|
259
|
|
260 def is_special(self):
|
|
261 return (self.sum() <= int(floor((self.sk + self.mod)/5)))
|
|
262
|
|
263 def is_critical(self):
|
|
264 return (self.sum() <= int(floor((self.sk + self.mod) / 20)))
|
|
265
|
|
266 def is_fumble(self):
|
|
267 if ( self.sk >= 100 ):
|
|
268 fum = 0
|
|
269 else:
|
|
270 fum = (100 - self.sk )
|
|
271 final_fum = ( 100 - int( floor( fum/20 ) ) )
|
|
272 return ( self.sum() >= final_fum )
|
|
273
|
|
274 def __str__(self):
|
|
275 strAdd="+"
|
|
276 swapmod= self.mod
|
|
277 if self.mod < 0:
|
|
278 strAdd= "-"
|
|
279 swapmod= -self.mod
|
|
280 modSum = self.sum()
|
|
281 # build output string
|
|
282 myStr = " (" + str(modSum) + ")"
|
|
283 myStr += " vs [" + str(self.sk) + strAdd + str(swapmod) + "]"
|
|
284
|
|
285 if self.is_fumble():
|
|
286 myStr += " <b><font color=red>Fumble!</font></b>"
|
|
287 elif self.is_critical():
|
|
288 myStr += " <b><font color=green>Critical!</font></b>"
|
|
289 elif self.is_special():
|
|
290 myStr += " <i><font color=green>Special!</font></i>"
|
|
291 elif self.is_success() and self.is_ma():
|
|
292 myStr += " <i><font color=green>Special!</font></i>"
|
|
293 elif self.is_success():
|
|
294 myStr += " <font color=blue>Success!</font>"
|
|
295 else:
|
|
296 myStr += " <font color=red>Failure!</font>"
|
|
297
|
|
298 Diff = self.sk - modSum
|
|
299 myStr += " </font>"
|
|
300
|
|
301 return myStr
|
|
302
|
|
303 #
|
|
304 # RQ Parry Roll
|
|
305 #
|
|
306 # same as skill but with fumble dice and armor points
|
|
307 #
|
|
308 # [1d100.parry(50,0,0,12)]
|
|
309 # skill%, modifer, ma%, Weapon AP
|
|
310 #
|
|
311
|
|
312 class rqparry(std):
|
|
313 def __init__(self,source=[],sk=11,mod=0,ma=0,AP=0):
|
|
314 std.__init__(self,source)
|
|
315 self.sk = sk
|
|
316 self.mod = mod
|
|
317 self.ma = ma
|
|
318 self.AP = AP
|
|
319
|
|
320 def is_success(self):
|
|
321 return (((self.sum() <= (self.sk + self.mod)) or (self.sum() <= 5)) and (self.sum() <= 95))
|
|
322
|
|
323 def is_special(self):
|
|
324 return (self.sum() <= int(floor((self.sk + self.mod) / 5)))
|
|
325
|
|
326 def is_ma(self):
|
|
327 return (self.sum() <= self.ma)
|
|
328
|
|
329 def is_riposte(self):
|
|
330 return (self.sum() <= (self.ma / 5))
|
|
331
|
|
332 def is_critical(self):
|
|
333 return ( ( self.sum() <= int( floor( ( self.sk + self.mod )/20 ) ) ) )
|
|
334
|
|
335 def is_fumble(self):
|
|
336 if ( self.sk >= 100 ):
|
|
337 fum = 0
|
|
338 else:
|
|
339 fum = (100 - self.sk )
|
|
340 final_fum = ( 100 - int( floor( fum/20 ) ) )
|
|
341 return ( self.sum() >= final_fum )
|
|
342
|
|
343 def __str__(self):
|
|
344
|
|
345 # get fumble roll result in case needed
|
|
346 fum_roll = random.randint(1,100)
|
|
347
|
|
348 # get special AP
|
|
349 spec_AP = int( floor ( self.AP * 1.5 ) )
|
|
350
|
|
351 # figure out +/- for modifer
|
|
352 strAdd="+"
|
|
353 swapmod= self.mod
|
|
354 if self.mod < 0:
|
|
355 strAdd= "-"
|
|
356 swapmod= -self.mod
|
|
357 modSum = self.sum()
|
|
358
|
|
359 # build output string
|
|
360 myStr = " (" + str(modSum) + ")"
|
|
361 myStr += " vs [" + str(self.sk) + strAdd + str(swapmod) + "]"
|
|
362
|
|
363 if self.is_fumble():
|
|
364 myStr += " <b><font color=red>Fumble!</font> See Fumble Chart [" + str(fum_roll) + "]</b>"
|
|
365 elif self.is_critical() and self.is_riposte():
|
|
366 myStr += " <b><font color=green>Critical!</font> All damage blocked!</b>"
|
|
367 myStr += " Riposte next SR"
|
|
368 elif self.is_critical():
|
|
369 myStr += " <b><font color=green>Critical!</font> All damage blocked!</b>"
|
|
370 elif self.is_special and self.is_riposte():
|
|
371 myStr += " <i><font color=green>Special!</font> Weapon/Shield AP [" + str(spec_AP) + "]</i>"
|
|
372 myStr += " Riposte next SR"
|
|
373 elif self.is_special():
|
|
374 myStr += " <i><font color=green>Special!</font> Weapon/Shield AP [" + str(spec_AP) + "]</i>"
|
|
375 elif self.is_success() and self.is_ma():
|
|
376 myStr += " <i><font color=green>Special!</font> Weapon/Shield AP [" + str(spec_AP) + "]</i>"
|
|
377 elif self.is_success():
|
|
378 myStr += " <font color=blue>Success!</font> Weapon/Shield AP [" + str(self.AP) + "]"
|
|
379 else:
|
|
380 myStr += " <font color=red>Failure!</font>"
|
|
381
|
|
382 Diff = self.sk - modSum
|
|
383 myStr += " </font>"
|
|
384
|
|
385 return myStr
|
|
386
|
|
387 # RQ Dodge Roll
|
|
388 #
|
|
389 # same as skill but with fumble dice and armor points
|
|
390 #
|
|
391 # [1d100.parry(50,0,0)]
|
|
392 # skill%, modifer, ma%
|
|
393 #
|
|
394
|
|
395 class rqdodge(std):
|
|
396 def __init__(self,source=[],sk=11,mod=0,ma=0,AP=0):
|
|
397 std.__init__(self,source)
|
|
398 self.sk = sk
|
|
399 self.mod = mod
|
|
400 self.ma = ma
|
|
401 self.AP = AP
|
|
402
|
|
403 def is_success(self):
|
|
404 return (((self.sum() <= (self.sk + self.mod)) or (self.sum() <= 5)) and (self.sum() <= 95))
|
|
405
|
|
406 def is_special(self):
|
|
407 return (self.sum() <= int(floor((self.sk + self.mod) / 5)))
|
|
408
|
|
409 def is_ma(self):
|
|
410 return (self.sum() <= self.ma)
|
|
411
|
|
412 def is_riposte(self):
|
|
413 return (self.sum() <= (self.ma / 5))
|
|
414
|
|
415 def is_critical(self):
|
|
416 return ( ( self.sum() <= int( floor( ( self.sk + self.mod )/20 ) ) ) )
|
|
417
|
|
418 def is_fumble(self):
|
|
419 if ( self.sk >= 100 ):
|
|
420 fum = 0
|
|
421 else:
|
|
422 fum = (100 - self.sk )
|
|
423 final_fum = ( 100 - int( floor( fum/20 ) ) )
|
|
424 return ( self.sum() >= final_fum )
|
|
425
|
|
426 def __str__(self):
|
|
427
|
|
428 # get fumble roll result in case needed
|
|
429 fum_roll = random.randint(1,100)
|
|
430
|
|
431 # get special AP
|
|
432 spec_AP = int( floor ( self.AP * 1.5 ) )
|
|
433
|
|
434 # figure out +/- for modifer
|
|
435 strAdd="+"
|
|
436 swapmod= self.mod
|
|
437 if self.mod < 0:
|
|
438 strAdd= "-"
|
|
439 swapmod= -self.mod
|
|
440 modSum = self.sum()
|
|
441
|
|
442 # build output string
|
|
443 myStr = " (" + str(modSum) + ")"
|
|
444 myStr += " vs [" + str(self.sk) + strAdd + str(swapmod) + "]"
|
|
445
|
|
446 if self.is_fumble():
|
|
447 myStr += " <b><font color=red>Fumble!</font> See Fumble Chart [" + str(fum_roll) + "]</b>"
|
|
448 elif self.is_critical() and self.is_riposte():
|
|
449 myStr += " <b><font color=green>Critical!</font> All damage dodged!</b>"
|
|
450 myStr += " Riposte on next SR"
|
|
451 elif self.is_critical():
|
|
452 myStr += " <b><font color=green>Critical!</font> All damage dodged!</b>"
|
|
453 elif self.is_special and self.is_riposte():
|
|
454 myStr += " <i><font color=green>Special!</font> Damage dodged</b>"
|
|
455 myStr += " Riposte on next SR"
|
|
456 elif self.is_special():
|
|
457 myStr += " <i><font color=green>Special!</font> Damage dodged</b>"
|
|
458 elif self.is_success() and self.is_ma():
|
|
459 myStr += " <i><font color=green>Special!</font> Damage dodged</b>"
|
|
460 elif self.is_success():
|
|
461 myStr += " <font color=blue>Success!</font> Damage dodged</b>"
|
|
462 else:
|
|
463 myStr += " <font color=red>Failure!</font>"
|
|
464
|
|
465 Diff = self.sk - modSum
|
|
466 myStr += " </font>"
|
|
467
|
|
468 return myStr
|
|
469
|
|
470
|
|
471
|
|
472 #
|
|
473 # RQ Attack Roll
|
|
474 #
|
|
475 # same as skill but with fumble dice and armor points
|
|
476 #
|
|
477 # [1d100.attack(50,0,0,2,9,3,1)]
|
|
478 # skill%, modifer, ma%, min weap dam, max weap dam, dam bonus, truesword_enabled
|
|
479 #
|
|
480 class rqattack(std):
|
|
481 def __init__(self,source=[],sk=11,mod=0,ma=0,mindam=0,maxdam=0,bondam=0,trueswd=0):
|
|
482 std.__init__(self,source)
|
|
483 self.sk = sk
|
|
484 self.mod = mod
|
|
485 self.ma = ma
|
|
486 self.mindam = mindam
|
|
487 self.maxdam = maxdam
|
|
488 self.bondam = bondam
|
|
489 self.trueswd = trueswd
|
|
490
|
|
491 def is_success(self):
|
|
492 return (((self.sum() <= (self.sk + self.mod)) or (self.sum() <= 5)) and (self.sum() <= 95))
|
|
493
|
|
494 def is_ma(self):
|
|
495 return (self.sum() <= self.ma)
|
|
496
|
|
497 def is_special(self):
|
|
498 return (self.sum() <= int(floor((self.sk + self.mod) / 5)))
|
|
499
|
|
500 def is_critical(self):
|
|
501 return ((self.sum() <= int(floor((self.sk + self.mod) / 20))))
|
|
502
|
|
503 def is_supercritical(self):
|
|
504 return (self.sum() == 1)
|
|
505
|
|
506 def is_fumble(self):
|
|
507 if ( self.sk >= 100 ):
|
|
508 fum = 0
|
|
509 else:
|
|
510 fum = (100 - self.sk )
|
|
511 final_fum = ( 100 - int( floor( fum/20 ) ) )
|
|
512 return ( self.sum() >= final_fum )
|
|
513
|
|
514 def __str__(self):
|
|
515
|
|
516 # get fumble roll result in case needed
|
|
517 fum_roll = random.randint(1,100)
|
|
518
|
|
519 # get hit location roll result in case needed
|
|
520 location = random.randint(1,20)
|
|
521 myStr = " to the ["+ str(location) + "] "
|
|
522 if location < 5:
|
|
523 myStr += "<B>Right Leg</B>"
|
|
524 elif location < 9:
|
|
525 myStr += "<B>Left Leg</B>"
|
|
526 elif location < 12:
|
|
527 myStr += "<B>Abdomen</B>"
|
|
528 elif location < 13:
|
|
529 myStr += "<B>Chest</B>"
|
|
530 elif location < 16:
|
|
531 myStr += "<B>Right Arm</B>"
|
|
532 elif location < 19:
|
|
533 myStr += "<B>Left Arm</B>"
|
|
534 else:
|
|
535 myStr += "<B>Head</B>"
|
|
536 hit_loc = myStr
|
|
537
|
|
538
|
|
539 # get normal damage in case needed
|
|
540 norm_damage = random.randint(self.mindam*(self.trueswd+1),self.maxdam*(self.trueswd+1)) + self.bondam
|
|
541 norm_damage_string = "{" + str( self.mindam*(self.trueswd+1) ) + "-"
|
|
542 norm_damage_string += str(self.maxdam*(self.trueswd+1)) + "+" + str(self.bondam)
|
|
543 norm_damage_string += "}[" + str(norm_damage) + "] "
|
|
544
|
|
545 # get special/critical damage in case needed
|
|
546 crit_damage = random.randint( self.mindam*(self.trueswd+2), self.maxdam*(self.trueswd+2) ) + self.bondam
|
|
547 crit_damage_string = "{" + str( self.mindam*(self.trueswd+2) ) + "-" + str(self.maxdam*(self.trueswd+2)) + "+" + str(self.bondam) + "}[" + str(crit_damage) + "] "
|
|
548
|
|
549 # get supercritical damage in case needed
|
|
550 super_damage = norm_damage + self.maxdam
|
|
551 super_damage_string = "{" + str( self.mindam*(self.trueswd+1) ) + "-"
|
|
552 super_damage_string += str(self.maxdam*(self.trueswd+1)) + "+" + str(self.maxdam)
|
|
553 super_damage_string += "+" + str(self.bondam) + "}[" + str(super_damage) + "] "
|
|
554
|
|
555 # figure out +/- for modifer
|
|
556 strAdd="+"
|
|
557 swapmod= self.mod
|
|
558 if self.mod < 0:
|
|
559 strAdd= "-"
|
|
560 swapmod= -self.mod
|
|
561 modSum = self.sum()
|
|
562
|
|
563 # build output string
|
|
564 myStr = " (" + str(modSum) + ")"
|
|
565 myStr += " vs [" + str(self.sk) + strAdd + str(swapmod) + "]"
|
|
566
|
|
567 if self.is_fumble():
|
|
568 myStr += " <b><font color=red>Fumble!</font> See Fumble Chart [" + str(fum_roll) + "]</b>"
|
|
569 elif (self.is_supercritical() and self.is_success()):
|
|
570 myStr += " <b><font color=green>Super Critical!</font></b> Damage: " + str(super_damage_string) + "<u>No Armor Stops</u>" + str(hit_loc)
|
|
571 elif (self.is_critical() and self.is_success()):
|
|
572 myStr += " <b><font color=green>Critical!</font></b> Damage: " + str(crit_damage_string) + "<u>No Armor Stops</u>" + str(hit_loc)
|
|
573 elif ( self.is_special() and self.is_success() ):
|
|
574 myStr += " <i><font color=green>Special!</font></i> Damage: " + str(crit_damage_string) + str(hit_loc)
|
|
575 elif (self.is_success() and self.is_ma()):
|
|
576 myStr += " <i><font color=green>Special!</font></i> Damage: " + str(crit_damage_string) + str(hit_loc)
|
|
577 elif self.is_success():
|
|
578 myStr += " <font color=blue>Success!</font> Damage: " + str(norm_damage_string) + str(hit_loc)
|
|
579 else:
|
|
580 myStr += " <font color=red>Failure!</font>"
|
|
581
|
|
582 return myStr
|
|
583
|
|
584 #
|
|
585 #
|
|
586 # Sorcery Roll: [1d100.sorcery(90, 10, 5, 4, 3, 2, 1)]
|
|
587 # (sk, mod, pow, cer, int, acc, mlt)
|
|
588 #
|
|
589 # Ceremony: (+1d6% per strike rank spent on ceremony)
|
|
590 # Intensity: (-3% per point of Intensity)
|
|
591 # Duration: (-4% per point of Duration)
|
|
592 # Range: (-5% per point of Range)
|
|
593 # Multispell: (-10% per each spell over 1)
|
|
594 # Acceleration: (-5% per point of Acceleration)
|
|
595 # Hold: (-2% per point in spell Held)
|
|
596 #
|
|
597 class rqsorcery(std):
|
|
598 def __init__(self,source=[],sk=11,mod=0,pow=0,cer=0,int=0,acc=0,mlt=0):
|
|
599 std.__init__(self,source)
|
|
600 self.sk = sk # sorcery skill
|
|
601 self.mod = mod # additional modifier ( from duration, range, etc )
|
|
602 self.pow = pow # boost pow and additional pow ( from duration, range, etc )
|
|
603 self.cer = cer # ceremony d6
|
|
604 self.int = int # intensity ( -3% )
|
|
605 self.acc = acc # accelerate ( -5% )
|
|
606 self.mlt = mlt # multispell ( -10% )
|
|
607
|
|
608 def is_success(self):
|
|
609 return (((self.sum() <= (self.sk + self.mod)) or (self.sum() <= 5)) and (self.sum() <= 95))
|
|
610
|
|
611 def is_special(self):
|
|
612 return ( ( self.sum() <= int( floor( ( self.sk + self.mod )/5 ) ) ) )
|
|
613
|
|
614 def is_critical(self):
|
|
615 return ( ( self.sum() <= int( floor( ( self.sk + self.mod )/20 ) ) ) )
|
|
616
|
|
617 def is_fumble(self):
|
|
618 if ( self.sk >= 100 ):
|
|
619 fum = 0
|
|
620 else:
|
|
621 fum = (100 - self.sk )
|
|
622 final_fum = ( 100 - int( floor( fum/20 ) ) )
|
|
623 return ( self.sum() >= final_fum )
|
|
624
|
|
625 def __str__(self):
|
|
626
|
|
627 # get fumble roll result in case needed
|
|
628 fum_roll = random.randint(2,12)
|
|
629 if fum_roll == 12 :
|
|
630 fum_string = "<br /><font color=purple>Caster temporarily forgets spell. Make an INTx5 roll each day to remember.</font>"
|
|
631 if fum_roll == 11 :
|
|
632 fum_string = "<br /><font color=purple>Caster temporarily forgets spell. Make an INTx5 roll each hour to remember. </font>"
|
|
633 if fum_roll == 10 :
|
|
634 fum_string = "<br /><font color=purple>Spell produces reverse of the intended effect. </font>"
|
|
635 if fum_roll == 9 :
|
|
636 fum_string = "<br /><font color=purple>Caster is Stunned. Roll INTx3 to recover at SR 10 each round. </font>"
|
|
637 if fum_roll == 8 :
|
|
638 fum_string = "<br /><font color=purple>Caster takes 2D6 Damage to THP </font>"
|
|
639 if fum_roll == 7 :
|
|
640 fum_string = "<br /><font color=purple>Spell produces reverse of the intended effect at 2x Intensity. </font>"
|
|
641 if fum_roll == 6 :
|
|
642 fum_string = "<br /><font color=purple>Spell is cast on companions (if harmful) or on random nearby foes (if beneficial) </font>"
|
|
643 if fum_roll == 5 :
|
|
644 fum_string = "<br /><font color=purple>Caster takes 1d6 Damage to Head </font>"
|
|
645 if fum_roll == 4 :
|
|
646 fum_string = "<br /><font color=purple>Spell is cast on caster (if harmful) or on random nearby foe (if beneficial) </font>"
|
|
647 if fum_roll == 3 :
|
|
648 fum_string = "<br /><font color=purple>Caster takes 1d6 Damage to THP </font>"
|
|
649 if fum_roll == 2 :
|
|
650 fum_string = "<br /><font color=purple>Caster takes 1 point of Damage to Head </font>"
|
|
651
|
|
652 # roll ceremony
|
|
653 ceremony_roll = random.randint( self.cer, (self.cer*6) )
|
|
654
|
|
655 # subtract manipulations
|
|
656 extra_mod = self.mod
|
|
657 self.mod += ceremony_roll - self.int*3 - self.acc*5 - self.mlt*10
|
|
658
|
|
659 # add up power cost
|
|
660 extra_pow = self.pow
|
|
661 self.pow += self.int + self.mlt + self.acc
|
|
662 special_pow = int( floor( ( self.pow )/2 ) )
|
|
663
|
|
664 # figure out +/- for modifer
|
|
665 strAdd="+"
|
|
666 swapmod= self.mod
|
|
667 if self.mod < 0:
|
|
668 strAdd= "-"
|
|
669 swapmod= -self.mod
|
|
670 modSum = self.sum()
|
|
671
|
|
672 # build output string
|
|
673 myStr = " (" + str(modSum) + ")"
|
|
674 myStr += " vs [" + str(self.sk) + strAdd + str(swapmod) + "]"
|
|
675
|
|
676 if self.is_fumble():
|
|
677 myStr += " <b><font color=red>Fumble!</font> POW Cost: [" + str(self.pow) + "],</b> " + fum_string
|
|
678 elif self.is_critical():
|
|
679 myStr += " <b><font color=green>Critical!</font></b> POW Cost: [1] "
|
|
680 elif self.is_special():
|
|
681 myStr += " <i><font color=green>Special!</font></i> POW Cost: [" + str(special_pow) + "] "
|
|
682 elif self.is_success():
|
|
683 myStr += " <font color=blue>Success!</font> POW Cost: [" + str(self.pow) + "] "
|
|
684 else:
|
|
685 myStr += " <font color=red>Failure!</font> POW Cost: [1]"
|
|
686
|
|
687 # print spell details
|
|
688 myStr += "<br /> --- Other Modifiers:[" + str( extra_mod ) + "], "
|
|
689 myStr += "Extra POW:[" + str( extra_pow ) + "], "
|
|
690 myStr += "Ceremony:[+" + str( ceremony_roll ) + "%], "
|
|
691 myStr += "Intensity(-3):[" + str( self.int ) + "], "
|
|
692 myStr += "Accelerate(-5):[" + str( self.acc ) + "], "
|
|
693 myStr += "Multispell(-10):[" + str( self.mlt ) + "] ---"
|
|
694
|
|
695 return myStr
|
|
696
|