Mercurial > traipse_dev
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 |