comparison orpg/dieroller/runequest.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
2
3
4
5 # (at your option) any later version.
6 #
7 # This program is distributed in the hope that it will be useful,
8 # but WITHOUT ANY WARRANTY; without even the implied warranty of
9 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 # GNU General Public License for more details.
11 #
12 # You should have received a copy of the GNU General Public License
13 # along with this program; if not, write to the Free Software
14 # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
15 #
16 #-------------------------------------------------------------------------
17 #
18 # Usage:
19 #
20 # Die Roller: /dieroller rq
21 #
22 # Skill Roll: [1d100.skill(50,0,0)] # ( skill%, modifer, MA% )
23 #
24 # Parry Roll: [1d100.parry(50,0,0,12)] # ( skill%, modifer, MA%, Weapon/Shield AP )
25 #
26 # Dodge Roll: [1d100.parry(50,0,0)] # ( skill%, modifer, MA% )
27 #
28 # Attack Roll: [1d100.attack(50,0,0,2,9,3,0)]
29 # ( skill%, modifer, MA%, min weap dam, max weap dam, dam bonus, truesword )
30 #
31 # Sorcery Roll: [1d100.sorcery(90, 0, 3, 6, 1, 1, 1)]
32 # (sk, mod, pow, cer, int, acc, mlt)
33 #
34 #
35 #
36 # Skill Training Unlimited Roll: [1d100.trainskill(30,75)] # (starting skill%, desired skill%)
37 # Skill Training Cost Limited: [1d100.trainskillcost(1000, 50) # (payment, starting skill%)
38 # Skill Training Time Limited: [1d100.trainskilltime(150, 50) # (time, strting skill%)
39 #
40 #-------------------------------------------------------------------------
41 # --
42 #
43 # File: rq.py
44 # Version:
45 # $Id: rq.py,v .1 pelwer
46 #
47 # Description: Runequest die roller originally based on Heroman's Hero Dieroller
48 #
49 #
50 # v.1 - pelwer - 2/5/2005
51 # o Original release
52 # v.2 - pelwer - 10/30/2006
53 # o Ported to openrpg+ by removing dependance on whrandom
54 # o Fixed Riposte spelling
55 # o Deleted sorcalc - never used
56 # o Added Sorcery Fumble table to sorcery spell roller
57 #
58
59 from die import *
60 from time import time, clock
61 import random
62 from math import floor
63
64
65 __version__ = "$Id: runequest.py,v 1.4 2006/11/15 12:11:22 digitalxero Exp $"
66
67 # rq stands for "Runequest"
68
69 class runequest(std):
70 def __init__(self,source=[]):
71 std.__init__(self,source)
72
73 # these methods return new die objects for specific options
74
75 def skill(self,sk,mod,ma):
76 return rqskill(self,sk,mod,ma)
77
78 def parry(self,sk,mod,ma,AP):
79 return rqparry(self,sk,mod,ma,AP)
80
81 def dodge(self,sk,mod,ma):
82 return rqdodge(self,sk,mod,ma)
83
84 def attack(self,sk,mod,ma,mindam,maxdam,bondam,trueswd):
85 return rqattack(self,sk,mod,ma,mindam,maxdam,bondam,trueswd)
86
87 def sorcery(self,sk,mod,pow,cer,int,acc,mlt):
88 return rqsorcery(self,sk,mod,pow,cer,int,acc,mlt)
89
90 def trainskill(self,initial,final):
91 return rqtrainskill(self,initial,final)
92
93 def trainskillcost(self,cost,sk):
94 return rqtrainskillcost(self,cost,sk)
95
96 def trainskilltime(self,time,sk):
97 return rqtrainskilltime(self,time,sk)
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