Mercurial > traipse_dev
annotate orpg/dieroller/runequest.py @ 164:d263c8ff4d7c beta
Traipse Beta 'OpenRPG' {091202-00}
Traipse is a distribution of OpenRPG that is designed to be easy to
setup and go. Traipse also makes it easy for developers to work on code
without fear of sacrifice. 'Ornery-Orc' continues the trend of 'Grumpy'
and adds fixes to the code. 'Ornery-Orc's main goal is to offer more
advanced features and enhance the productivity of the user.
Update Summary (Beta)
New Features:
Added Bookmarks
Added 'boot' command to remote admin
Added confirmation window for sent nodes
Minor changes to allow for portability to an OpenSUSE linux OS
Miniatures Layer pop up box allows users to turn off Mini labels, from
FlexiRPG
Zoom Mouse plugin added
Images added to Plugin UI
Switching to Element Tree
Map efficiency, from FlexiRPG
Added Status Bar to Update Manager
New TrueDebug Class in orpg_log (See documentation for usage)
Portable Mercurial
Tip of the Day added, from Core and community
New Reference Syntax added for custom PC sheets
New Child Reference for gametree
New Gametree Recursion method, mapping, context sensitivity, and
effeciency..
New Features node with bonus nodes and Node Referencing help added
Added 7th Sea die roller method; ie [7k3] =
[7d10.takeHighest(3).open(10)]
New 'Mythos' System die roller added
Added new vs. die roller method for WoD; ie [3v3] = [3d10.vs(3)].
Includes support for Mythos roller.
Fixes:
Fix to Text based Server
Fix to Remote Admin Commands
Fix to Pretty Print, from Core
Fix to Splitter Nodes not being created
Fix to massive amounts of images loading, from Core
Fix to Map from gametree not showing to all clients
Fix to gametree about menus
Fix to Password Manager check on startup
Fix to PC Sheets from tool nodes. They now use the tabber_panel
Fixed Whiteboard ID to prevent random line or text deleting.
Modified ID's to prevent non updated clients from ruining the fix.
default_manifest.xml renamed to default_upmana.xml
Fix to Update Manager; cleaner clode for saved repositories
Fixes made to Settings Panel and no reactive settings when Ok is
pressed.
author | sirebral |
---|---|
date | Wed, 02 Dec 2009 21:21:34 -0600 |
parents | 3b6888bb53b5 |
children |
rev | line source |
---|---|
156 | 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 __version__ = "$Id: runequest.py,v 1.4 2006/11/15 12:11:22 digitalxero Exp $" | |
65 | |
66 # rq stands for "Runequest" | |
67 | |
68 class runequest(std): | |
69 | |
70 def __init__(self,source=[]): | |
71 std.__init__(self,source) | |
72 | |
73 # these methods return new die objects for specific options | |
74 | |
75 | |
76 def skill(self,sk,mod,ma): | |
77 return rqskill(self,sk,mod,ma) | |
78 | |
79 | |
80 def parry(self,sk,mod,ma,AP): | |
81 return rqparry(self,sk,mod,ma,AP) | |
82 | |
83 | |
84 def dodge(self,sk,mod,ma): | |
85 return rqdodge(self,sk,mod,ma) | |
86 | |
87 | |
88 def attack(self,sk,mod,ma,mindam,maxdam,bondam,trueswd): | |
89 return rqattack(self,sk,mod,ma,mindam,maxdam,bondam,trueswd) | |
90 | |
91 | |
92 def sorcery(self,sk,mod,pow,cer,int,acc,mlt): | |
93 return rqsorcery(self,sk,mod,pow,cer,int,acc,mlt) | |
94 | |
95 | |
96 def trainskill(self,initial,final): | |
97 return rqtrainskill(self,initial,final) | |
98 | |
99 | |
100 def trainskillcost(self,cost,sk): | |
101 return rqtrainskillcost(self,cost,sk) | |
102 | |
103 | |
104 def trainskilltime(self,time,sk): | |
105 return rqtrainskilltime(self,time,sk) | |
106 | |
107 # RQ Skill Training Cost/Time unlimited | |
108 # | |
109 # [1d100.trainskill(10,20)] | |
110 # initial skill%, final skill% | |
111 # | |
112 # sk = skill % | |
113 # | |
114 # | |
115 class rqtrainskill(std): | |
116 | |
117 def __init__(self,source=[],initial=11,final=0): | |
118 std.__init__(self,source) | |
119 self.s = initial | |
120 self.f = final | |
121 | |
122 | |
123 def __str__(self): | |
124 myStr = "Unrestricted Training" | |
125 | |
126 if self.s == 0: | |
127 myStr = "Initial training completed for Cost(50) Time(20) Skill(1 + modifier)" | |
128 else: | |
129 cost = 0 | |
130 time = 0 | |
131 myStr = "Training: " | |
132 | |
133 while self.s < self.f and self.s < 75: | |
134 cost += self.s * 5 | |
135 time += self.s * 1 | |
136 self.s += random.uniform(1,4) + 1 | |
137 | |
138 myStr = "Training completed:\n" | |
139 myStr += "\tCost(" + str(int(cost)) + ")\n" | |
140 myStr += "\tTime(" + str(int(time)) + ")\n" | |
141 myStr += "\tSkill(" + str(int(self.s)) + ")" | |
142 | |
143 return myStr | |
144 | |
145 | |
146 # RQ Skill Training Cost Limited | |
147 # | |
148 # [1d100.trainskillcost(50,0)] | |
149 # cost, skill% | |
150 # | |
151 # cost = cash for training | |
152 # sk = skill % | |
153 # | |
154 # | |
155 class rqtrainskillcost(std): | |
156 | |
157 def __init__(self,source=[],cost=11,sk=0): | |
158 std.__init__(self,source) | |
159 self.cost = cost | |
160 self.sk = sk | |
161 | |
162 | |
163 def __str__(self): | |
164 myStr = "" | |
165 | |
166 if self.sk == 0 and self.cost >= 50: | |
167 myStr = "Initial training completed for Cost(50), Time(50), Skill(1 + modifier)" | |
168 else: | |
169 cost = 0 | |
170 time = 0 | |
171 icost = self.sk * 5 | |
172 | |
173 myStr = "Training: " | |
174 | |
175 while (cost + icost) < self.cost: | |
176 if self.sk >= 75: | |
177 break | |
178 | |
179 cost += icost | |
180 time += self.sk * 1 | |
181 self.sk += random.uniform(1,4) + 1 | |
182 icost = self.sk * 5 | |
183 | |
184 myStr = "Training completed: " | |
185 myStr += "Cost(" + str(int(cost)) + ") " | |
186 myStr += "Time(" + str(int(time)) + ") " | |
187 myStr += "Skill(" + str(int(self.sk)) + ")" | |
188 | |
189 return myStr | |
190 | |
191 | |
192 # RQ Skill Training Time Limited | |
193 # | |
194 # [1d100.trainskilltime(50,0)] | |
195 # time, skill% | |
196 # | |
197 # time = time for training | |
198 # sk = skill % | |
199 # | |
200 # | |
201 class rqtrainskilltime(std): | |
202 | |
203 def __init__(self,source=[],time=11,sk=0): | |
204 std.__init__(self,source) | |
205 self.time = time | |
206 self.sk = sk | |
207 | |
208 | |
209 def __str__(self): | |
210 myStr = "" | |
211 | |
212 if self.sk == 0 and self.time >= 20: | |
213 myStr = "Initial training completed for Cost(50), Time(50), Skill(1 + modifier)" | |
214 else: | |
215 cost = 0 | |
216 time = 0 | |
217 itime = self.sk * 1 | |
218 | |
219 myStr = "Trainingsss: " | |
220 | |
221 while (time + itime) < self.time: | |
222 if self.sk >= 75: | |
223 break | |
224 | |
225 cost += self.sk * 5 | |
226 time += itime | |
227 self.sk += random.uniform(1,4) + 1 | |
228 itime = self.sk * 5 | |
229 | |
230 myStr = "Training completed: " | |
231 myStr += "Cost(" + str(int(cost)) + ") " | |
232 myStr += "Time(" + str(int(time)) + ") " | |
233 myStr += "Skill(" + str(int(self.sk)) + ")" | |
234 | |
235 return myStr | |
236 | |
237 # RQ Skill Roll | |
238 # | |
239 # [1d100.skill(50,0,0)] | |
240 # skill%, modifer, ma% | |
241 # | |
242 # sk = skill % | |
243 # mod = modifier % | |
244 # ma = martial arts % | |
245 # skill = sk + mod | |
246 # | |
247 # success roll <= skill | |
248 # | |
249 # failure roll > skill | |
250 # | |
251 # crit | |
252 # push( @{$::Cre{Weapons}{$weap_cnt}}, POSIX::floor( skill/20 ) ); | |
253 # | |
254 # special | |
255 # push( @{$::Cre{Weapons}{$weap_cnt}}, POSIX::floor( $skill/5 ) ); | |
256 # | |
257 # fumble: if ( $skill > 100 ) { $fum = 0; } else { $fum = 100 - $skill; } | |
258 # $fum = 100 - POSIX::floor( $fum/20 ); | |
259 # if ( $fum == 100 ) { $fum = '00'; }; | |
260 # | |
261 class rqskill(std): | |
262 | |
263 def __init__(self,source=[],sk=11,mod=0,ma=0): | |
264 std.__init__(self,source) | |
265 self.sk = sk | |
266 self.mod = mod | |
267 self.ma = ma | |
268 | |
269 | |
270 def is_success(self): | |
271 return (((self.sum() <= (self.sk + self.mod)) or (self.sum() <= 5)) and (self.sum() <= 95)) | |
272 | |
273 | |
274 def is_ma(self): | |
275 return (self.sum() <= self.ma) | |
276 | |
277 | |
278 def is_special(self): | |
279 return (self.sum() <= int(floor((self.sk + self.mod)/5))) | |
280 | |
281 | |
282 def is_critical(self): | |
283 return (self.sum() <= int(floor((self.sk + self.mod) / 20))) | |
284 | |
285 | |
286 def is_fumble(self): | |
287 if ( self.sk >= 100 ): | |
288 fum = 0 | |
289 else: | |
290 fum = (100 - self.sk ) | |
291 final_fum = ( 100 - int( floor( fum/20 ) ) ) | |
292 return ( self.sum() >= final_fum ) | |
293 | |
294 | |
295 def __str__(self): | |
296 strAdd="+" | |
297 swapmod= self.mod | |
298 if self.mod < 0: | |
299 strAdd= "-" | |
300 swapmod= -self.mod | |
301 modSum = self.sum() | |
302 # build output string | |
303 myStr = " (" + str(modSum) + ")" | |
304 myStr += " vs [" + str(self.sk) + strAdd + str(swapmod) + "]" | |
305 | |
306 if self.is_fumble(): myStr += " <b><font color=red>Fumble!</font></b>" | |
307 elif self.is_critical(): myStr += " <b><font color=green>Critical!</font></b>" | |
308 elif self.is_special(): myStr += " <i><font color=green>Special!</font></i>" | |
309 elif self.is_success() and self.is_ma(): myStr += " <i><font color=green>Special!</font></i>" | |
310 elif self.is_success(): myStr += " <font color=blue>Success!</font>" | |
311 else: myStr += " <font color=red>Failure!</font>" | |
312 | |
313 Diff = self.sk - modSum | |
314 myStr += " </font>" | |
315 | |
71
449a8900f9ac
Code refining almost completed, for this round. Some included files are still in need of some clean up, but this is test worthy.
sirebral
parents:
0
diff
changeset
|
316 return myStr |
156 | 317 |
318 # | |
319 # RQ Parry Roll | |
320 # | |
321 # same as skill but with fumble dice and armor points | |
322 # | |
323 # [1d100.parry(50,0,0,12)] | |
324 # skill%, modifer, ma%, Weapon AP | |
325 # | |
326 | |
327 class rqparry(std): | |
328 | |
329 def __init__(self,source=[],sk=11,mod=0,ma=0,AP=0): | |
330 std.__init__(self,source) | |
331 self.sk = sk | |
332 self.mod = mod | |
333 self.ma = ma | |
334 self.AP = AP | |
335 | |
336 | |
337 def is_success(self): | |
338 return (((self.sum() <= (self.sk + self.mod)) or (self.sum() <= 5)) and (self.sum() <= 95)) | |
339 | |
340 | |
341 def is_special(self): | |
342 return (self.sum() <= int(floor((self.sk + self.mod) / 5))) | |
343 | |
344 | |
345 def is_ma(self): | |
346 return (self.sum() <= self.ma) | |
347 | |
348 | |
349 def is_riposte(self): | |
350 return (self.sum() <= (self.ma / 5)) | |
351 | |
352 | |
353 def is_critical(self): | |
354 return ( ( self.sum() <= int( floor( ( self.sk + self.mod )/20 ) ) ) ) | |
355 | |
356 | |
357 def is_fumble(self): | |
358 if ( self.sk >= 100 ): | |
359 fum = 0 | |
360 else: | |
361 fum = (100 - self.sk ) | |
362 final_fum = ( 100 - int( floor( fum/20 ) ) ) | |
363 return ( self.sum() >= final_fum ) | |
364 | |
365 | |
366 def __str__(self): | |
367 | |
368 # get fumble roll result in case needed | |
369 fum_roll = random.randint(1,100) | |
370 | |
371 # get special AP | |
372 spec_AP = int( floor ( self.AP * 1.5 ) ) | |
373 | |
374 # figure out +/- for modifer | |
375 strAdd="+" | |
376 swapmod= self.mod | |
377 if self.mod < 0: | |
378 strAdd= "-" | |
379 swapmod= -self.mod | |
380 modSum = self.sum() | |
381 | |
382 # build output string | |
383 myStr = " (" + str(modSum) + ")" | |
384 myStr += " vs [" + str(self.sk) + strAdd + str(swapmod) + "]" | |
385 | |
386 if self.is_fumble(): | |
387 myStr += " <b><font color=red>Fumble!</font> See Fumble Chart [" + str(fum_roll) + "]</b>" | |
388 elif self.is_critical() and self.is_riposte(): | |
389 myStr += " <b><font color=green>Critical!</font> All damage blocked!</b>" | |
390 myStr += " Riposte next SR" | |
391 elif self.is_critical(): | |
392 myStr += " <b><font color=green>Critical!</font> All damage blocked!</b>" | |
393 elif self.is_special and self.is_riposte(): | |
394 myStr += " <i><font color=green>Special!</font> Weapon/Shield AP [" + str(spec_AP) + "]</i>" | |
395 myStr += " Riposte next SR" | |
396 elif self.is_special(): | |
397 myStr += " <i><font color=green>Special!</font> Weapon/Shield AP [" + str(spec_AP) + "]</i>" | |
398 elif self.is_success() and self.is_ma(): | |
399 myStr += " <i><font color=green>Special!</font> Weapon/Shield AP [" + str(spec_AP) + "]</i>" | |
400 elif self.is_success(): | |
401 myStr += " <font color=blue>Success!</font> Weapon/Shield AP [" + str(self.AP) + "]" | |
402 else: | |
403 myStr += " <font color=red>Failure!</font>" | |
404 | |
405 Diff = self.sk - modSum | |
406 myStr += " </font>" | |
407 | |
408 return myStr | |
409 | |
410 # RQ Dodge Roll | |
411 # | |
412 # same as skill but with fumble dice and armor points | |
413 # | |
414 # [1d100.parry(50,0,0)] | |
415 # skill%, modifer, ma% | |
416 # | |
417 | |
418 class rqdodge(std): | |
419 | |
420 def __init__(self,source=[],sk=11,mod=0,ma=0,AP=0): | |
421 std.__init__(self,source) | |
422 self.sk = sk | |
423 self.mod = mod | |
424 self.ma = ma | |
425 self.AP = AP | |
426 | |
427 | |
428 def is_success(self): | |
429 return (((self.sum() <= (self.sk + self.mod)) or (self.sum() <= 5)) and (self.sum() <= 95)) | |
430 | |
431 | |
432 def is_special(self): | |
433 return (self.sum() <= int(floor((self.sk + self.mod) / 5))) | |
434 | |
435 | |
436 def is_ma(self): | |
437 return (self.sum() <= self.ma) | |
438 | |
439 | |
440 def is_riposte(self): | |
441 return (self.sum() <= (self.ma / 5)) | |
442 | |
443 | |
444 def is_critical(self): | |
445 return ( ( self.sum() <= int( floor( ( self.sk + self.mod )/20 ) ) ) ) | |
446 | |
447 | |
448 def is_fumble(self): | |
449 if ( self.sk >= 100 ): | |
450 fum = 0 | |
451 else: | |
452 fum = (100 - self.sk ) | |
453 final_fum = ( 100 - int( floor( fum/20 ) ) ) | |
454 return ( self.sum() >= final_fum ) | |
455 | |
456 | |
457 def __str__(self): | |
458 | |
459 # get fumble roll result in case needed | |
460 fum_roll = random.randint(1,100) | |
461 | |
462 # get special AP | |
463 spec_AP = int( floor ( self.AP * 1.5 ) ) | |
464 | |
465 # figure out +/- for modifer | |
466 strAdd="+" | |
467 swapmod= self.mod | |
468 if self.mod < 0: | |
469 strAdd= "-" | |
470 swapmod= -self.mod | |
471 modSum = self.sum() | |
472 | |
473 # build output string | |
474 myStr = " (" + str(modSum) + ")" | |
475 myStr += " vs [" + str(self.sk) + strAdd + str(swapmod) + "]" | |
476 | |
477 if self.is_fumble(): | |
478 myStr += " <b><font color=red>Fumble!</font> See Fumble Chart [" + str(fum_roll) + "]</b>" | |
479 elif self.is_critical() and self.is_riposte(): | |
480 myStr += " <b><font color=green>Critical!</font> All damage dodged!</b>" | |
481 myStr += " Riposte on next SR" | |
482 elif self.is_critical(): | |
483 myStr += " <b><font color=green>Critical!</font> All damage dodged!</b>" | |
484 elif self.is_special and self.is_riposte(): | |
485 myStr += " <i><font color=green>Special!</font> Damage dodged</b>" | |
486 myStr += " Riposte on next SR" | |
487 elif self.is_special(): | |
488 myStr += " <i><font color=green>Special!</font> Damage dodged</b>" | |
489 elif self.is_success() and self.is_ma(): | |
490 myStr += " <i><font color=green>Special!</font> Damage dodged</b>" | |
491 elif self.is_success(): | |
492 myStr += " <font color=blue>Success!</font> Damage dodged</b>" | |
493 else: | |
494 myStr += " <font color=red>Failure!</font>" | |
495 | |
496 Diff = self.sk - modSum | |
497 myStr += " </font>" | |
498 | |
499 return myStr | |
500 | |
501 | |
502 | |
503 # | |
504 # RQ Attack Roll | |
505 # | |
506 # same as skill but with fumble dice and armor points | |
507 # | |
508 # [1d100.attack(50,0,0,2,9,3,1)] | |
509 # skill%, modifer, ma%, min weap dam, max weap dam, dam bonus, truesword_enabled | |
510 # | |
511 class rqattack(std): | |
512 | |
513 def __init__(self,source=[],sk=11,mod=0,ma=0,mindam=0,maxdam=0,bondam=0,trueswd=0): | |
514 std.__init__(self,source) | |
515 self.sk = sk | |
516 self.mod = mod | |
517 self.ma = ma | |
518 self.mindam = mindam | |
519 self.maxdam = maxdam | |
520 self.bondam = bondam | |
521 self.trueswd = trueswd | |
522 | |
523 | |
524 def is_success(self): | |
525 return (((self.sum() <= (self.sk + self.mod)) or (self.sum() <= 5)) and (self.sum() <= 95)) | |
526 | |
527 | |
528 def is_ma(self): | |
529 return (self.sum() <= self.ma) | |
530 | |
531 | |
532 def is_special(self): | |
533 return (self.sum() <= int(floor((self.sk + self.mod) / 5))) | |
534 | |
535 | |
536 def is_critical(self): | |
537 return ((self.sum() <= int(floor((self.sk + self.mod) / 20)))) | |
538 | |
539 | |
540 def is_supercritical(self): | |
541 return (self.sum() == 1) | |
542 | |
543 | |
544 def is_fumble(self): | |
545 if ( self.sk >= 100 ): | |
546 fum = 0 | |
547 else: | |
548 fum = (100 - self.sk ) | |
549 final_fum = ( 100 - int( floor( fum/20 ) ) ) | |
550 return ( self.sum() >= final_fum ) | |
551 | |
552 | |
553 def __str__(self): | |
554 | |
555 # get fumble roll result in case needed | |
556 fum_roll = random.randint(1,100) | |
557 | |
558 # get hit location roll result in case needed | |
559 location = random.randint(1,20) | |
560 myStr = " to the ["+ str(location) + "] " | |
561 if location < 5: | |
562 myStr += "<B>Right Leg</B>" | |
563 elif location < 9: | |
564 myStr += "<B>Left Leg</B>" | |
565 elif location < 12: | |
566 myStr += "<B>Abdomen</B>" | |
567 elif location < 13: | |
568 myStr += "<B>Chest</B>" | |
569 elif location < 16: | |
570 myStr += "<B>Right Arm</B>" | |
571 elif location < 19: | |
572 myStr += "<B>Left Arm</B>" | |
573 else: | |
574 myStr += "<B>Head</B>" | |
575 hit_loc = myStr | |
576 | |
577 | |
578 # get normal damage in case needed | |
579 norm_damage = random.randint(self.mindam*(self.trueswd+1),self.maxdam*(self.trueswd+1)) + self.bondam | |
580 norm_damage_string = "{" + str( self.mindam*(self.trueswd+1) ) + "-" | |
581 norm_damage_string += str(self.maxdam*(self.trueswd+1)) + "+" + str(self.bondam) | |
582 norm_damage_string += "}[" + str(norm_damage) + "] " | |
583 | |
584 # get special/critical damage in case needed | |
585 crit_damage = random.randint( self.mindam*(self.trueswd+2), self.maxdam*(self.trueswd+2) ) + self.bondam | |
586 crit_damage_string = "{" + str( self.mindam*(self.trueswd+2) ) + "-" + str(self.maxdam*(self.trueswd+2)) + "+" + str(self.bondam) + "}[" + str(crit_damage) + "] " | |
587 | |
588 # get supercritical damage in case needed | |
589 super_damage = norm_damage + self.maxdam | |
590 super_damage_string = "{" + str( self.mindam*(self.trueswd+1) ) + "-" | |
591 super_damage_string += str(self.maxdam*(self.trueswd+1)) + "+" + str(self.maxdam) | |
592 super_damage_string += "+" + str(self.bondam) + "}[" + str(super_damage) + "] " | |
593 | |
594 # figure out +/- for modifer | |
595 strAdd="+" | |
596 swapmod= self.mod | |
597 if self.mod < 0: | |
598 strAdd= "-" | |
599 swapmod= -self.mod | |
600 modSum = self.sum() | |
601 | |
602 # build output string | |
603 myStr = " (" + str(modSum) + ")" | |
604 myStr += " vs [" + str(self.sk) + strAdd + str(swapmod) + "]" | |
605 | |
606 if self.is_fumble(): | |
607 myStr += " <b><font color=red>Fumble!</font> See Fumble Chart [" + str(fum_roll) + "]</b>" | |
608 elif (self.is_supercritical() and self.is_success()): | |
609 myStr += " <b><font color=green>Super Critical!</font></b> Damage: " + str(super_damage_string) + "<u>No Armor Stops</u>" + str(hit_loc) | |
610 elif (self.is_critical() and self.is_success()): | |
611 myStr += " <b><font color=green>Critical!</font></b> Damage: " + str(crit_damage_string) + "<u>No Armor Stops</u>" + str(hit_loc) | |
612 elif ( self.is_special() and self.is_success() ): | |
613 myStr += " <i><font color=green>Special!</font></i> Damage: " + str(crit_damage_string) + str(hit_loc) | |
614 elif (self.is_success() and self.is_ma()): | |
615 myStr += " <i><font color=green>Special!</font></i> Damage: " + str(crit_damage_string) + str(hit_loc) | |
616 elif self.is_success(): | |
617 myStr += " <font color=blue>Success!</font> Damage: " + str(norm_damage_string) + str(hit_loc) | |
618 else: | |
619 myStr += " <font color=red>Failure!</font>" | |
620 | |
621 return myStr | |
622 | |
623 # | |
624 # | |
625 # Sorcery Roll: [1d100.sorcery(90, 10, 5, 4, 3, 2, 1)] | |
626 # (sk, mod, pow, cer, int, acc, mlt) | |
627 # | |
628 # Ceremony: (+1d6% per strike rank spent on ceremony) | |
629 # Intensity: (-3% per point of Intensity) | |
630 # Duration: (-4% per point of Duration) | |
631 # Range: (-5% per point of Range) | |
632 # Multispell: (-10% per each spell over 1) | |
633 # Acceleration: (-5% per point of Acceleration) | |
634 # Hold: (-2% per point in spell Held) | |
635 # | |
636 class rqsorcery(std): | |
637 | |
638 def __init__(self,source=[],sk=11,mod=0,pow=0,cer=0,int=0,acc=0,mlt=0): | |
639 std.__init__(self,source) | |
640 self.sk = sk # sorcery skill | |
641 self.mod = mod # additional modifier ( from duration, range, etc ) | |
642 self.pow = pow # boost pow and additional pow ( from duration, range, etc ) | |
643 self.cer = cer # ceremony d6 | |
644 self.int = int # intensity ( -3% ) | |
645 self.acc = acc # accelerate ( -5% ) | |
646 self.mlt = mlt # multispell ( -10% ) | |
647 | |
648 | |
649 def is_success(self): | |
650 return (((self.sum() <= (self.sk + self.mod)) or (self.sum() <= 5)) and (self.sum() <= 95)) | |
651 | |
652 | |
653 def is_special(self): | |
654 return ( ( self.sum() <= int( floor( ( self.sk + self.mod )/5 ) ) ) ) | |
655 | |
656 | |
657 def is_critical(self): | |
658 return ( ( self.sum() <= int( floor( ( self.sk + self.mod )/20 ) ) ) ) | |
659 | |
660 | |
661 def is_fumble(self): | |
662 if ( self.sk >= 100 ): | |
663 fum = 0 | |
664 else: | |
665 fum = (100 - self.sk ) | |
666 final_fum = ( 100 - int( floor( fum/20 ) ) ) | |
667 return ( self.sum() >= final_fum ) | |
668 | |
669 | |
670 def __str__(self): | |
671 | |
672 # get fumble roll result in case needed | |
673 fum_roll = random.randint(2,12) | |
674 if fum_roll == 12 : | |
675 fum_string = "<br /><font color=purple>Caster temporarily forgets spell. Make an INTx5 roll each day to remember.</font>" | |
676 if fum_roll == 11 : | |
677 fum_string = "<br /><font color=purple>Caster temporarily forgets spell. Make an INTx5 roll each hour to remember. </font>" | |
678 if fum_roll == 10 : | |
679 fum_string = "<br /><font color=purple>Spell produces reverse of the intended effect. </font>" | |
680 if fum_roll == 9 : | |
681 fum_string = "<br /><font color=purple>Caster is Stunned. Roll INTx3 to recover at SR 10 each round. </font>" | |
682 if fum_roll == 8 : | |
683 fum_string = "<br /><font color=purple>Caster takes 2D6 Damage to THP </font>" | |
684 if fum_roll == 7 : | |
685 fum_string = "<br /><font color=purple>Spell produces reverse of the intended effect at 2x Intensity. </font>" | |
686 if fum_roll == 6 : | |
687 fum_string = "<br /><font color=purple>Spell is cast on companions (if harmful) or on random nearby foes (if beneficial) </font>" | |
688 if fum_roll == 5 : | |
689 fum_string = "<br /><font color=purple>Caster takes 1d6 Damage to Head </font>" | |
690 if fum_roll == 4 : | |
691 fum_string = "<br /><font color=purple>Spell is cast on caster (if harmful) or on random nearby foe (if beneficial) </font>" | |
692 if fum_roll == 3 : | |
693 fum_string = "<br /><font color=purple>Caster takes 1d6 Damage to THP </font>" | |
694 if fum_roll == 2 : | |
695 fum_string = "<br /><font color=purple>Caster takes 1 point of Damage to Head </font>" | |
696 | |
697 # roll ceremony | |
698 ceremony_roll = random.randint( self.cer, (self.cer*6) ) | |
699 | |
700 # subtract manipulations | |
701 extra_mod = self.mod | |
702 self.mod += ceremony_roll - self.int*3 - self.acc*5 - self.mlt*10 | |
703 | |
704 # add up power cost | |
705 extra_pow = self.pow | |
706 self.pow += self.int + self.mlt + self.acc | |
707 special_pow = int( floor( ( self.pow )/2 ) ) | |
708 | |
709 # figure out +/- for modifer | |
710 strAdd="+" | |
711 swapmod= self.mod | |
712 if self.mod < 0: | |
713 strAdd= "-" | |
714 swapmod= -self.mod | |
715 modSum = self.sum() | |
716 | |
717 # build output string | |
718 myStr = " (" + str(modSum) + ")" | |
719 myStr += " vs [" + str(self.sk) + strAdd + str(swapmod) + "]" | |
720 | |
721 if self.is_fumble(): | |
722 myStr += " <b><font color=red>Fumble!</font> POW Cost: [" + str(self.pow) + "],</b> " + fum_string | |
723 elif self.is_critical(): | |
724 myStr += " <b><font color=green>Critical!</font></b> POW Cost: [1] " | |
725 elif self.is_special(): | |
726 myStr += " <i><font color=green>Special!</font></i> POW Cost: [" + str(special_pow) + "] " | |
727 elif self.is_success(): | |
728 myStr += " <font color=blue>Success!</font> POW Cost: [" + str(self.pow) + "] " | |
729 else: | |
730 myStr += " <font color=red>Failure!</font> POW Cost: [1]" | |
731 | |
732 # print spell details | |
733 myStr += "<br /> --- Other Modifiers:[" + str( extra_mod ) + "], " | |
734 myStr += "Extra POW:[" + str( extra_pow ) + "], " | |
735 myStr += "Ceremony:[+" + str( ceremony_roll ) + "%], " | |
736 myStr += "Intensity(-3):[" + str( self.int ) + "], " | |
737 myStr += "Accelerate(-5):[" + str( self.acc ) + "], " | |
738 myStr += "Multispell(-10):[" + str( self.mlt ) + "] ---" | |
739 | |
740 return myStr |