comparison plugins/xxinit2.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 5df1340bda13
comparison
equal deleted inserted replaced
-1:000000000000 0:4385a7d0efd1
1 # Copyright (C) 2000-2001 The OpenRPG Project
2 #
3 # openrpg-dev@lists.sourceforge.net
4 #
5 # This program is free software; you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by
7 # the Free Software Foundation; either version 2 of the License, or
8 # (at your option) any later version.
9 #
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU General Public License for more details.
14 #
15 # You should have received a copy of the GNU General Public License
16 # along with this program; if not, write to the Free Software
17 # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 #
19 ##############################################################################
20
21 from string import find, replace
22 import wx
23
24 import os
25 import orpg.dirpath
26 import orpg.orpg_version
27 import orpg.plugindb
28 import orpg.pluginhandler
29 import hashlib
30 import random
31
32 __version__ = "2.2.8"
33
34 class v:
35 init_list = []
36
37 class Plugin(orpg.pluginhandler.PluginHandler):
38 # Initialization subroutine.
39 #
40 # !self : instance of self
41 # !openrpg : instance of the the base openrpg control
42 def __init__(self, plugindb, parent):
43 orpg.pluginhandler.PluginHandler.__init__(self, plugindb, parent)
44
45 self.name = "Initiative Tool " + str(__version__)
46 self.author = "Woody, Darloth, updated by mDuo13, Veggiesama, magoo"
47 self.help = "Type /inittool2 to load a help node into your game tree. Check out\n"
48 self.help += "the readme, and double-click Commands & Help if you want to see examples."
49
50 self.version = __version__
51 self.orpg_min_version="1.7.0"
52
53
54 def plugin_enabled(self):
55 # Setup variables.
56 self.loaded = 0 # 1 = config has been loaded on startup
57 self.init_debug = 0
58 v.init_list = [] # now an array of "Dict" (associative array):
59 # name : name of the effect of character
60 # type : 0 = character; 1 = effect
61 # init : init score
62 # duration : round remaining to the effect
63 # hidden : type 0 = shows up in public list only on init
64 # type 1 = does not print to public remaing rounds of effect
65 # pass : for SR4
66 # rank : when multiple character at same init count, the plugin
67 # use the 'rank' to order them
68 # tag : unique tag assigned to each entry.
69 self.init_round = 1
70 self.init_recording = 1
71 self.init_title = ""
72 self.init_count = 0
73 self.init_pass = 0
74 self.init_listslot = 0
75 self.init_listtag = ""
76 self.init_end = 0
77 self.init_system = "D20" # D20 (default), SR4, RQ
78 self.sandglass_count = 0 # current count of the number of seconds of a character's turn
79 # Well, more or less true, it is a count of the number of time the function
80 # refresh_counter() has been called, which itself is supposed to be call each seconds.
81 self.sandglass_delay = 0 # 0 = off, anything else is the timer delay
82 self.sandglass_status = 0# 0 = running, 1 = pause
83 self.sandglass_skip_interval = 0 # after a number of interval, do a init_next(). 0 = disable
84 self.autosave_delay = 60 # 0 = off, else, will autosave every 'autosave' seconds - VEG 2.2.8 (set to 60)
85 self.autosave_count = 0 # current count of the number of seconds since last autosave
86 self.hide_id = 0 # 1 = do not show IDs to everyone; 0 = show IDs to everyone
87 self.hide_ondeck = 0 # 1 = do not show "on deck" message after every turn; 0 = show it
88 self.hide_justmovement = 0 # [SR4] 1 = do not show "just movement" messages
89 self.message_nowup = "NEXT UP FOR THE KILLING" # customizable "now up" message
90 self.msghand_timer = 0 # 0-60 = cycles the message handler to all players once every 60 seconds - VEG 2.2.6
91 self.msghand_warning = 1 # 1 = manual override, removes the message warning if someone else in room has xxinit2 loaded - VEG 2.2.6
92 self.reroll_type = 0 # 0 = reroll every round (normal), 1 = no reroll and keep last round inits - VEG 2.2.7
93 self.ip_order = 0 # 0 = 1/2/3/4 (normal), 1 = 3/1/4/2 (Serbitar's house rule), 2 = 4/1/3/2 (TinkerGnome's house rule) - VEG 2.2.7
94
95 # Add commands
96 self.plugin_addcommand("/inittool2", self.CMD_inittool2, "Loads the help/example node into your game tree")
97 self.plugin_addcommand("/inittoggle", self.CMD_inittoggle, "Toggles initiative system (D20/SR4/RuneQuest")
98 self.plugin_addcommand("/initdebug", self.CMD_initdebug, "???")
99 self.plugin_addcommand("/initgui", self.CMD_initgui, "???")
100 #self.plugin_addcommand("/initsaveconfig", self.CMD_initsaveconfig, "Saves current configuration") #VEG 2.2.6
101 #self.plugin_addcommand("/initloadconfig", self.CMD_initloadconfig, "Loads a previous configuration") #VEG 2.2.6
102 self.plugin_addcommand("/initdefaultconfig", self.CMD_initdefaultconfig, "Loads the default configuration")
103 self.plugin_addcommand("/initshowconfig", self.CMD_initshowconfig, "Displays current configuration")
104 self.plugin_addcommand("/togglehideid", self.CMD_togglehideid, "Shows IDs in a public list")
105 self.plugin_addcommand("/togglehideondeck", self.CMD_togglehideondeck, "Shows 'On Deck' message after every turn")
106 self.plugin_addcommand("/togglehidejustmovement", self.CMD_togglehidejustmovement, "Shows 'Just Movement' messages in SR4")
107 self.plugin_addcommand("/init", self.CMD_init, "Toggles whether to record typed intiativies and textual initiative commands")
108 self.plugin_addcommand("/clear", self.CMD_clear, "Clears current initiative list")
109 self.plugin_addcommand("/start", self.CMD_start, "Clears current initiative list and prompts players to roll")
110 self.plugin_addcommand("/addfxhidden", self.CMD_addfxhidden, "Adds a hidden effect to the list")
111 self.plugin_addcommand("/addfx", self.CMD_addfx, "Adds an effect to the list")
112 self.plugin_addcommand("/addhidden", self.CMD_addhidden, "Adds a hidden character to the list")
113 self.plugin_addcommand("/add", self.CMD_add, "Adds a character to the list")
114 self.plugin_addcommand("/del", self.CMD_del, "Deletes a character/effect from the list")
115 self.plugin_addcommand("/changepass", self.CMD_changepass, "Changes current initiative pass [SR4-only]")
116 self.plugin_addcommand("/changedur", self.CMD_changedur, "Changes duration of specific effect")
117 #self.plugin_addcommand("/changefx", self.CMD_changefx, "Changes the initiative count of a specific effect")
118 self.plugin_addcommand("/change", self.CMD_change, "Changes the initiative count of a specific character")
119 self.plugin_addcommand("/togglehidden", self.CMD_togglehidden, "Toggles whether to show hidden characters in initiative list or not")
120 self.plugin_addcommand("/initsetslot", self.CMD_initsetslot, "Sets the initiative turn to the designated list slot")
121 self.plugin_addcommand("/rankup", self.CMD_rankup, "Alters turn priority of one character/effect in the same initiative count as other characters/effects (higher)")
122 self.plugin_addcommand("/rankdown", self.CMD_rankdown, "Alters turn priority of one character/effect in the same initiative count as other characters/effects (lower)")
123 self.plugin_addcommand("/initdelaynow", self.CMD_initdelaynow, "???")
124 self.plugin_addcommand("/sandglass", self.CMD_sandglass, "Toggles sandglass functionality and sets duration of timer")
125 self.plugin_addcommand("/sandglasspause", self.CMD_sandglasspause, "Pauses the sandglass")
126 self.plugin_addcommand("/sandglassresume", self.CMD_sandglassresume, "Resumes the sandglass from pause")
127 self.plugin_addcommand("/sandglassforceskip", self.CMD_sandglassforceskip, "Forces the turn to skip after a number of sandglass duration intervals")
128 self.plugin_addcommand("/list", self.CMD_list, "Displays a list of characters, effects, and turn order to yourself")
129 self.plugin_addcommand("/publiclist", self.CMD_publiclist, "Displays a list of characters, effects, and turn order to the room")
130 self.plugin_addcommand("/rnd", self.CMD_rnd, "Displays the current round")
131 self.plugin_addcommand("/pass", self.CMD_pass, "Displays the current pass [SR4-only]")
132 self.plugin_addcommand("/go", self.CMD_go, "Advances the turn order to the next character/effect")
133 self.plugin_addcommand("/initsave", self.CMD_initsave, "Saves current list of initiatives")
134 self.plugin_addcommand("/initload", self.CMD_initload, "Loads previous list of initiatives")
135 self.plugin_addcommand("/initautosave", self.CMD_initautosave, "Toggles autosave")
136 self.plugin_addcommand("/initautoload", self.CMD_initautoload, "Loads previous autosave of initiative")
137 self.plugin_addcommand("/nowupmsg", self.CMD_nowupmsg, "Customize your own Now Up Message")
138 self.plugin_addcommand("/msghandwarning", self.CMD_msghandwarning, "Toggles the message handler warning when multiple xxinit2's are loaded in the room") #VEG 2.2.6
139 self.plugin_addcommand("/toggleroundreroll", self.CMD_toggleroundreroll, "Toggles method of round-by-round initiative in SR4") #VEG 2.2.7
140 self.plugin_addcommand("/toggleiporder", self.CMD_toggleiporder, "Toggles order of IP execution in SR4") #VEG 2.2.7
141
142 # Add message handlers
143 self.plugin_add_msg_handler("xxinit2_checkifloaded", self.received_checkifloaded) #VEG 2.2.6
144 self.plugin_add_msg_handler("xxinit2_returnloaded", self.received_returnloaded) #VEG 2.2.6
145
146 self.init_load(0) #VEG 2.2.8 - auto-loads last autosave at startup (helps if you crash)
147
148 def plugin_disabled(self):
149 self.plugin_removecmd("/inittool2")
150 self.plugin_removecmd("/inittoggle")
151 self.plugin_removecmd("/initdebug")
152 self.plugin_removecmd("/initgui")
153 #self.plugin_removecmd("/initsaveconfig") #VEG 2.2.6
154 #self.plugin_removecmd("/initloadconfig") #VEG 2.2.6
155 self.plugin_removecmd("/initdefaultconfig")
156 self.plugin_removecmd("/initshowconfig")
157 self.plugin_removecmd("/togglehideid")
158 self.plugin_removecmd("/togglehideondeck")
159 self.plugin_removecmd("/togglehidejustmovement")
160 self.plugin_removecmd("/init")
161 self.plugin_removecmd("/clear")
162 self.plugin_removecmd("/start")
163 self.plugin_removecmd("/addfxhidden")
164 self.plugin_removecmd("/addfx")
165 self.plugin_removecmd("/addhidden")
166 self.plugin_removecmd("/add")
167 self.plugin_removecmd("/del")
168 self.plugin_removecmd("/changepass")
169 self.plugin_removecmd("/changedur")
170 #self.plugin_removecmd("/changefx")
171 self.plugin_removecmd("/change")
172 self.plugin_removecmd("/togglehidden")
173 self.plugin_removecmd("/initsetslot")
174 self.plugin_removecmd("/rankup")
175 self.plugin_removecmd("/rankdown")
176 self.plugin_removecmd("/initdelaynow")
177 self.plugin_removecmd("/sandglass")
178 self.plugin_removecmd("/sandglasspause")
179 self.plugin_removecmd("/sandglassresume")
180 self.plugin_removecmd("/sandglassforceskip")
181 self.plugin_removecmd("/list")
182 self.plugin_removecmd("/publiclist")
183 self.plugin_removecmd("/rnd")
184 self.plugin_removecmd("/pass")
185 self.plugin_removecmd("/go")
186 self.plugin_removecmd("/initsave")
187 self.plugin_removecmd("/initload")
188 self.plugin_removecmd("/initautosave")
189 self.plugin_removecmd("/initautoload")
190 self.plugin_removecmd("/nowupmsg")
191 self.plugin_removecmd("/msghandwarning")
192 self.plugin_removecmd("/toggleroundreroll")
193 self.plugin_removecmd("/toggleiporder")
194
195 self.plugin_delete_msg_handler("xxinit2_checkifloaded") #VEG 2.2.6
196 self.plugin_delete_msg_handler("xxinit2_returnloaded") #VEG 2.2.6
197
198 self.loaded = 0
199
200 try:
201 self.frame.Destroy()
202 except:
203 pass
204
205 # Just received a query from another player; returning a "yes, I have xxinit2 loaded" message
206 def received_checkifloaded(self, playerid, data, xml_dom): #VEG 2.2.6
207 #print "receive_checkifloaded called: id=" + str(playerid) + "... data = " + str(data)
208 self.plugin_send_msg(playerid, "<xxinit2_returnloaded/>")
209
210 # Just received the "yes, I have xxinit2 loaded" message; printing a warning message
211 def received_returnloaded(self, playerid, data, xml_dom): #VEG 2.2.6
212 if self.msghand_warning:
213 self.post_syserror("Warning: xxinit2 plugin detected on "
214 + str(self.session.get_player_by_player_id(playerid)[0]) + "'s system. \
215 Having multiple copies of the xxinit2 plugin in the same room is not \
216 advisable, because it may cause problems. It is suggested that only \
217 one person in the room (the GM) have the xxinit2 plugin loaded. Go to \
218 Tools-Plugins and uncheck the Initiative Tool 2.x to unload it. Type \
219 /msghandwarning to simply turn this warning reminder off.")
220
221 def post_msg(self, text, myself):
222 #This is called whenever a message from anyone is about to be posted
223 #to chat; it doesn't affect the copy of the message that gets sent to others
224 #Be careful; system and info messages trigger this too.
225 if self.init_recording:
226 if text.lower().find("showinits") != -1:
227 self.inits_list(1)
228 return text
229 elif text.lower().find("nextinit") != -1:
230 self.init_next()
231 return text
232 # all collected, certain values only valid in following systems:
233 # d20: player, init, effect, duration
234 # sr4: player, init, passes
235 # VEG 2.2.7 - The lines that "won't work with macros" are unable to function properly because of the double-layers
236 # of <font> tags that accompany macro sends. The string parsing gets screwed up. It's probably fixable
237 # without changing the way macros are handled, but it's beyond my skill level. =( =( =(
238 if myself==1:
239 if text.find(" effect ") != -1:
240 effect=text[text.rfind("'>")+2:text.find("[")]
241 duration=text[text.rfind("effect ")+7:text.find("</font>")]
242 init=text[text.rfind("=> ")+3:text.rfind(" effect")]
243 elif text.find(" init") != -1:
244 player=text[:text.find("[")]
245 passes=text[text.find("init ")+5:text.find("</font>")]
246 init=text[text.rfind("(")+1:text.rfind(")")]
247 else:
248 if text.find(" effect ") != -1:
249 effect=text[text.find("</b>: ")+6:text.find("[")]
250 duration=text[text.find("effect ")+7:-7]
251 init=text[text.rfind("=> ")+3:text.rfind(" effect")]
252 elif text.find(" init") != -1:
253 player=text[text.find("</b>: ")+6:text.find("[")]
254 passes=text[text.find("init ")+5:-7]
255 init=text[text.rfind("(")+1:text.rfind(")")]
256 try:
257 if self.isD20() or self.isRQ():
258 if text.find(" effect ") != -1:
259 init=int(init)
260 duration=int(duration)
261 self.init_add([init,duration,effect], 1, 0)
262 elif text.find(" init") != -1:
263 init=int(init)
264 self.init_add([init,player], 0, 0)
265 elif self.isSR4():
266 if text.find(" init ") != -1:
267 init=int(init)
268 passes=int(passes)
269 self.init_add([init,passes,player], 0, 0)
270 except:
271 print("Detected some sort of initiative input... failed!")
272
273 return text
274
275
276 def refresh_counter(self):
277 #This is called once per second. That's all you need to know.
278 # load system config once at startup
279 if not self.loaded:
280 self.loaded = 1
281 self.config_load()
282 self.config_show()
283 self.check_version()
284
285 # do sandglass stuff it has to do
286 if not self.isEnded():
287 self.sandglass()
288
289 # do the autosaving stuff if needed
290 self.autosave()
291
292 # VEG 2.2.6
293 self.msghand_timer += 1
294 if self.msghand_timer >= 60: # cycle playerlist only 1x every 60 sec
295 self.msghand_timer = 0
296 self.plugin_send_msg("all", "<xxinit2_checkifloaded/>")
297
298 ###############################################################
299 #### Command Functions
300 ###############################################################
301
302 def CMD_inittool2(self, cmdargs):
303 f = open(orpg.dirpath.dir_struct["plugins"]+ "inittool2.xml","r")
304 f2 = open(orpg.dirpath.dir_struct["plugins"]+ "inittool2_player.xml","r")
305 self.gametree.insert_xml(f.read())
306 self.gametree.insert_xml(f2.read())
307 f.close()
308 f2.close()
309 return 1
310
311 def CMD_inittoggle(self, cmdargs):
312 if self.isSR4():
313 self.init_system = "RQ"
314 self.init_clear()
315 self.post_sysmsg("Now using <font color='#0000ff'><i>RuneQuest</font></i> system.", 1)
316 elif self.isD20():
317 self.init_system = "SR4"
318 self.init_clear()
319 self.post_sysmsg("Now using <font color='#0000ff'><i>Shadowrun 4th</font></i> system.", 1)
320 elif self.isRQ():
321 self.init_system = "D20"
322 self.init_clear()
323 self.post_sysmsg("Now using <font color='#0000ff'><i>d20</font></i> system.", 1)
324 self.config_save() # VEG 2.2.6
325
326 def CMD_initdebug(self, cmdargs):
327 cmdargs = cmdargs.split(None,-1)
328 if cmdargs[0] == "on":
329 self.init_debug = 1
330 self.post_sysmsg("Init debugging <font color='#0000ff'><i>on</i></font>.",1)
331 elif cmdargs[0] == "off":
332 self.init_debug = 0
333 self.post_sysmsg("Init debugging <font color='#0000ff'><i>off</i></font>.",1)
334
335 #def CMD_initsaveconfig(self, cmdargs):
336 # self.config_save()
337
338 #def CMD_initloadconfig(self, cmdargs):
339 # self.config_load()
340
341 def CMD_initdefaultconfig(self, cmdargs):
342 self.config_default()
343
344 def CMD_initshowconfig(self, cmdargs):
345 self.config_show()
346
347 def CMD_togglehideid(self, cmdargs):
348 self.hide_id = not self.hide_id
349 self.post_sysmsg("Hide IDs: " + str(self.hide_id), 1)
350 self.config_save() # VEG 2.2.6
351
352 def CMD_togglehideondeck(self, cmdargs):
353 self.hide_ondeck = not self.hide_ondeck
354 self.post_sysmsg("Hide 'On Deck': " + str(self.hide_ondeck), 1)
355 self.config_save() # VEG 2.2.6
356
357 def CMD_togglehidejustmovement(self, cmdargs):
358 self.hide_justmovement = not self.hide_justmovement
359 self.post_sysmsg("Hide 'Just Movement' [SR4-only]: " + str(self.hide_justmovement), 1)
360 self.config_save() # VEG 2.2.6
361
362 def CMD_init(self, cmdargs):
363 if self.init_recording:
364 self.init_recording=0
365 self.post_sysmsg("Init recording <font color='#0000ff'><i>off</i></font>.")
366 else:
367 self.init_recording=1
368 self.post_sysmsg("Init recording <font color='#0000ff'><i>on</i></font>.")
369 self.config_save() # VEG 2.2.6
370
371 def CMD_clear(self, cmdargs):
372 self.init_clear()
373 self.post_sysmsg("Clearing Initiative List !", 1)
374
375 def CMD_start(self, cmdargs):
376 self.init_clear()
377 self.post_my_msg("<hr><font color='#ff0000'><b>Starting Round</font> <font color='#0000ff'># <i>1</font> [" + self.init_system + "]</b>", 1)
378 self.post_my_msg("<font color='#0000ff'><b>Roll New Initiatives</b></font><hr>", 1)
379
380 def CMD_addfxhidden(self, cmdargs):
381 cmdargs = cmdargs.split(None,2)
382 if self.isD20() or self.isRQ():
383 self.init_add(cmdargs, 1, 1)
384 else:
385 self.post_syserror("Invalid input. Effects and durations do not work with " + str(self.init_system) + " system.")
386
387 def CMD_addfx(self, cmdargs):
388 cmdargs = cmdargs.split(None,2)
389 if self.isD20() or self.isRQ():
390 self.init_add(cmdargs, 1, 0)
391 else:
392 self.post_syserror("Invalid input. Effects and durations do not work with " + str(self.init_system) + " system.")
393
394 def CMD_addhidden(self, cmdargs):
395 if self.isD20() or self.isRQ():
396 cmdargs = cmdargs.split(None,1)
397 elif self.isSR4():
398 cmdargs = cmdargs.split(None,2)
399 self.init_add(cmdargs, 0, 1)
400
401 def CMD_add(self, cmdargs):
402 if self.isD20() or self.isRQ():
403 cmdargs = cmdargs.split(None,1)
404 elif self.isSR4():
405 cmdargs = cmdargs.split(None,2)
406 self.init_add(cmdargs, 0, 0)
407
408 def CMD_del(self, cmdargs):
409 id = int(cmdargs)
410 self.init_delete(id-1, 1) # subtract 1 because public lists shows with +1
411
412 def CMD_changepass(self, cmdargs):
413 cmdargs = cmdargs.split(None,-1)
414 if self.isSR4():
415 try:
416 id = int(cmdargs[0])-1 # subtract 1 because public lists shows with +1
417 new_pass = int(cmdargs[1])
418 if new_pass < 1 or new_pass > 4:
419 self.post_syserror("Invalid input [" + str(self.init_system) + "]. Passes must be greater than/equal to 1 and less than/equal to 4.")
420 else:
421 v.init_list[id]["passes"] = new_pass
422 self.post_sysmsg("<font color='#0000ff'><i>" + str(v.init_list[id]["name"]) + "</font></i>'s initiative \
423 pass total has been changed to <font color='#0000ff'><i>" + str(new_pass) + "</font></i> passes !", 1)
424 except:
425 self.post_syserror("Invalid input [" + str(self.init_system) + "]. That command only works on passes. Correct command is /changepass init_# new_pass_#")
426
427 else:
428 self.post_syserror("Invalid input. There are no initiative passes in the " + str(self.init_system) + " system. Try SR4 !")
429
430 def CMD_changedur(self, cmdargs):
431 cmdargs = cmdargs.split(None,-1)
432 if self.isD20() or self.isRQ():
433 try:
434 id = int(cmdargs[0])-1 # subtract 1 because public lists shows with +1
435 new_duration = int(cmdargs[1])
436 hidden = v.init_list[id]["hidden"]
437
438 if self.init_debug == 1:
439 print "id : " + str(id)
440 print "new_dur : " + str(new_duration)
441 print "hidden : " + str(hidden)
442
443 if new_duration == 0:
444 self.post_syserror("Invalid input [" + str(self.init_system) + "]. Set duration to '1' if you want the effect to end next time it comes up. \
445 Otherwise, delete the effect with the /del command.", not hidden)
446 return
447 elif new_duration < 0:
448 self.post_syserror("Invalid input [" + str(self.init_system) + "]. New duration must be greater than or equal to 1.", not hidden)
449 return
450
451 if self.isEffect(id):
452 v.init_list[id]["duration"] = new_duration
453 self.post_sysmsg("<font color='#0000ff'><i>" + str(v.init_list[id]["name"]) + "</font></i> has been changed \
454 to last <font color='#0000ff'><i>" + str(new_duration) + "</font></i> round(s) !", not hidden)
455 else:
456 self.post_syserror("Invalid input [" + str(self.init_system) + "]. That command only works on effects. Correct command is /changedur init_# new_duration_#")
457
458 except Exception, e:
459 #print str(e)
460 self.post_syserror("Invalid input [" + str(self.init_system) + "]. That command only works on effects. Correct command is /changedur init_# new_duration_#")
461
462 else:
463 self.post_syserror("Invalid input. Effects and durations do not work with " + str(self.init_system) + ".")
464
465 #def CMD_changefx(self, cmdargs):
466 # cmdargs = cmdargs.split(None,-1)
467 # if self.isD20() or self.isRQ():
468 # self.init_change(cmdargs,1)
469 # else:
470 # self.post_syserror(">Invalid input. Effects and durations do not work with " + str(self.init_system) + ".")
471
472 #def CMD_change(self, cmdargs):
473 # cmdargs = cmdargs.split(None,-1)
474 # self.init_change(cmdargs,0)
475
476 def CMD_change(self, cmdargs): # VEG 2.2.7
477 cmdargs = cmdargs.split(None,-1)
478 id = int(cmdargs[0])-1
479 new_init = int(cmdargs[1])
480 if self.isEffect(id):
481 if self.isD20() or self.isRQ():
482 self.init_change(id, new_init, 1)
483 else:
484 self.post_syserror(">Invalid input. Effects and durations do not work with " + str(self.init_system) + ".")
485 else:
486 self.init_change(id, new_init, 0)
487
488 def CMD_togglehidden(self, cmdargs):
489 id = int(cmdargs) - 1
490 self.toggle_hidden(id)
491
492 def CMD_initsetslot(self, cmdargs):
493 id = int(cmdargs) - 1
494 self.init_set_slot(id)
495
496 def CMD_rankup(self, cmdargs):
497 cmdargs = cmdargs.split(None,-1)
498 id = int(cmdargs[0]) - 1
499 try:
500 cmdargs[1]
501 n = 0 - int(cmdargs[1])
502 except:
503 # default num of steps to move
504 n = -1
505 self.init_move(id, n)
506
507 def CMD_rankdown(self, cmdargs):
508 cmdargs = cmdargs.split(None,-1)
509 id = int(cmdargs[0]) - 1
510 try:
511 cmdargs[1]
512 n = int(cmdargs[1])
513 except:
514 n = 1
515 self.init_move(id, n)
516
517 def CMD_initdelaynow(self, cmdargs):
518 id = int(cmdargs) - 1
519 self.init_delay_now(id)
520
521 def CMD_sandglass(self, cmdargs):
522 try:
523 delay = int(cmdargs)
524 self.set_sandglass(delay)
525 except:
526 self.post_syserror("Invalid input. /sandglass (#_of_secs)")
527
528 def CMD_sandglasspause(self, cmdargs):
529 self.sandglass_pause()
530 self.post_sysmsg("<br><b>Sandglass paused</b>", 1)
531
532 def CMD_sandglassresume(self, cmdargs):
533 self.sandglass_resume()
534 self.post_sysmsg("<br><b>Sandglass resumed</b>", 1)
535
536 def CMD_sandglassforceskip(self, cmdargs):
537 try:
538 interval = int(cmdargs)
539 self.set_sandglass_force_skip(interval)
540 except Exception, e:
541 #self.post_my_msg(str(e))
542 self.post_syserror("Invalid input. /sandglassforceskip (#_of_intervals)")
543
544 def CMD_list(self, cmdargs):
545 self.inits_list(0)
546
547 def CMD_publiclist(self, cmdargs):
548 self.inits_list(1)
549
550 def CMD_rnd(self, cmdargs):
551 try:
552 new_round = int(cmdargs)
553 self.init_round = new_round
554 self.post_sysmsg("Round number has been changed. It is now Round # <font color='#ff0000'>" + str(new_round) + "</font>",1)
555 except:
556 self.post_sysmsg("It is currently Round # <font color='#ff0000'>" + str(self.init_round) + "</font>",1)
557
558 def CMD_pass(self, cmdargs):
559 try:
560 new_pass = int(cmdargs)
561 if self.isSR4() and new_pass >= 1 and new_pass <= 4:
562 self.init_pass = new_pass
563 self.init_count = 0
564 self.init_listslot = 0
565 self.post_sysmsg("Initiative Pass has been changed. It is currently Pass # <font color='#ff0000'>" + str(self.init_pass) + "</font>",1)
566 elif not self.isSR4():
567 self.post_syserror("Invalid input. Initiative system must be set to SR4 for passes to function.")
568 else:
569 self.post_syserror("Invalid input. Passes must be greater than/equal to 1 and less than/equal to 4.")
570 except:
571 if self.isSR4():
572 self.post_sysmsg("It is currently Pass # <font color='#ff0000'>" + str(self.init_pass) + "</font>",1)
573 else:
574 self.post_syserror("Invalid input. Initiative system must be set to SR4 for passes to function.")
575
576 def CMD_go(self, cmdargs):
577 self.init_next()
578
579 def CMD_initsave(self, cmdargs):
580 cmdargs = cmdargs.split(None,1)
581 slot = int(cmdargs[0])
582 try:
583 self.init_title = cmdargs[1]
584 except:
585 self.init_title = "untitled"
586
587 if slot < 1 or slot > 5:
588 self.post_syserror("Invalid input. Slot # must be between 1 and 5.")
589 else:
590 self.init_save(slot, 1)
591
592 def CMD_initload(self, cmdargs):
593 try:
594 slot = int(cmdargs)
595 except:
596 slot = 1
597
598 if slot < 1 or slot > 5:
599 self.post_syserror("Invalid input. Slot # must be between 1 and 5.")
600 else:
601 self.init_load(slot)
602
603 def CMD_initautosave(self, cmdargs):
604 delay = int(cmdargs)
605 self.set_autosave(delay)
606
607 def CMD_initautoload(self, cmdargs):
608 self.init_load(0)
609
610 def CMD_nowupmsg(self, cmdargs):
611 self.message_nowup = str(cmdargs)
612 self.post_my_msg("<b>Now Up Message: </b>" + self.message_nowup)
613 self.config_save() # VEG 2.2.6
614
615 def CMD_msghandwarning(self, cmdargs): # VEG 2.2.6
616 if self.msghand_warning:
617 self.msghand_warning=0
618 self.post_sysmsg("Message handler warning <font color='#0000ff'><i>off</i></font>.")
619 else:
620 self.msghand_warning=1
621 self.post_sysmsg("Message handler warning <font color='#0000ff'><i>on</i></font>.")
622 self.config_save()
623
624 def CMD_toggleroundreroll(self, cmdargs): # VEG 2.2.7
625 if self.reroll_type:
626 self.reroll_type=0
627 self.post_sysmsg("Reroll toggle set to <font color='#0000ff'><i>Reroll Every Round (default)</i></font>.")
628 else:
629 self.reroll_type=1
630 self.post_sysmsg("Reroll toggle set to <font color='#0000ff'><i>Keep Same Inits Every Round (house rule)</i></font>.")
631 self.config_save()
632
633 def CMD_toggleiporder(self, cmdargs): # VEG 2.2.7
634 if self.ip_order == 0: # changes IP order to 3/1/4/2 (Serbitar's house rule)
635 self.ip_order=1
636 self.post_sysmsg("IP order set to <font color='#0000ff'><i>3/1/4/2 (Serbitar's)</i></font>.")
637 elif self.ip_order == 1: # changes IP order to 4/1/3/2 (TinkerGnome's house rule)
638 self.ip_order=2
639 self.post_sysmsg("IP order set to <font color='#0000ff'><i>4/1/3/2 (TinkerGnome's)</i></font>.")
640 elif self.ip_order == 2: # changes IP order to 1/2/3/4
641 self.ip_order=0
642 self.post_sysmsg("IP order set to <font color='#0000ff'><i>1/2/3/4 (normal)</i></font>.")
643 self.config_save()
644
645 ###############################################################
646 #### Base Functions
647 ###############################################################
648
649 def init_clear(self):
650 v.init_list = []
651 self.init_round = 1
652 self.init_count = 0
653 self.init_pass = 0
654 self.init_listslot = 0
655 self.init_listtag = ""
656 self.init_end = 0
657 self.sandglass_count = 0
658 self.sandglass_status = 0
659
660
661 def init_add(self, text, effect, hidden):
662 if (effect==1) and (self.isD20() or self.isRQ()): #d20 effects
663 try:
664 if len(text) == 3:
665 h = {}
666 count = int(text[0]) + 1 # effects only decrement (and end)
667 # before the count in which they
668 # were added on, so add 1
669 h["type"] = 1 # effect
670 h["init"] = count
671 h["name"] = "*" + str(text[2])
672 h["duration"] = int(text[1])
673 h["rank"] = self.get_next_rank(h["init"])
674 h["hidden"] = hidden
675 h["tag"] = self.get_unique_tag(h["name"])
676
677 if hidden == 1:
678 duration_str = "?"
679 else:
680 duration_str = str(h["duration"])
681
682 v.init_list += [h]
683
684 self.post_sysmsg("<i><font color='#0000ff'>" + h["name"] + "</font></i> effect added to list at init count <i><font color='#0000ff'>" + str(h["init"]) + "</font></i>, lasting <font color='#0000ff'><i>" + duration_str + "</i></font> round(s) !", 1)
685 self.init_sort()
686 except:
687 self.post_syserror("Invalid input [" + str(self.init_system) + "]. Correct command is: /addfx init_# duration_# description")
688
689 elif self.isD20(): #d20 characters
690 try:
691 if len(text) == 2:
692 h = {}
693 h["type"] = 0 # character
694 h["init"] = int(text[0])
695 h["name"] = str(text[1])
696 h["rank"] = self.get_next_rank(h["init"])
697 h["hidden"] = hidden
698 h["tag"] = self.get_unique_tag(h["name"])
699
700 v.init_list += [h]
701
702 self.post_sysmsg("<font color='#0000ff'><i>" + h["name"] + "</font></i> added to list at init count <i><font color='#0000ff'>" + str(h["init"]) + "</font></i> !", not hidden)
703 self.init_sort()
704 except:
705 self.post_syserror("Invalid input [" + str(self.init_system) + "]. Correct command is: /add init_# description", not hidden)
706
707 elif self.isSR4(): #SR4 characters
708 try:
709 if len(text) == 3:
710 h = {}
711 h["type"] = 0 # character
712 h["init"] = int(text[0])
713 h["name"] = str(text[2])
714 h["passes"] = int(text[1])
715 h["rank"] = self.get_next_rank(h["init"])
716 h["hidden"] = hidden
717 h["tag"] = self.get_unique_tag(h["name"])
718
719 v.init_list+=[h]
720
721 self.post_sysmsg("<font color='#0000ff'><i>" + h["name"] + "</font></i> added to list at init count \
722 <font color='#0000ff'><i>" + str(h["init"]) + "</font></i> with <font color='#0000ff'><i>" + str(h["passes"])+ "</font></i> \
723 passes !", not hidden)
724
725 self.init_sort()
726
727 except:
728 self.post_syserror("Invalid input [" + str(self.init_system) + "]. Correct command is: /add init_# passes_# description", not hidden)
729
730 elif self.isRQ(): #RQ characters
731 try:
732 if len(text) == 2:
733 h = {}
734 h["type"] = 0 # character
735 h["init"] = int(text[0])
736 h["name"] = str(text[1])
737 h["rank"] = self.get_next_rank(h["init"])
738 h["hidden"] = hidden
739 h["tag"] = self.get_unique_tag(h["name"])
740
741 v.init_list += [h]
742
743 self.post_sysmsg("<font color='#0000ff'><i>" + h["name"] + "</font></i> added to list at Strike Rank \
744 <font color='#0000ff'><i>" + str(h["init"]) + "</font></i> !", not hidden)
745
746 self.init_sort()
747 except:
748 self.post_syserror("Invalid input [" + str(self.init_system) + "]. Correct command is: /add SR description", not hidden)
749
750
751 def init_delete(self, id, public):
752 try:
753 name = v.init_list[id]["name"]
754 is_last = 0
755 is_self = 0
756 is_effect = 0
757 if public == 1:
758 self.post_sysmsg("<font color='#0000ff'><i>" + name + "</font></i> has been removed from the initiative list !", not v.init_list[id]["hidden"])
759 if self.isLast(id):
760 is_last = 1
761 if self.init_listslot == id:
762 is_self = 1
763 if self.isEffect(id):
764 is_effect = 1
765
766 del v.init_list[id]
767
768 if is_effect:
769 self.init_listslot -= 1
770 elif is_last and is_self:
771 self.init_next()
772 elif is_self == 1:
773 self.init_listslot -= 1
774 self.init_next()
775 self.init_sort()
776 except:
777 if public == 1:
778 self.post_syserror("Invalid input [" + str(self.init_system) + "]. Correct command is: /del list_number")
779
780
781 def init_change(self, id, new_init, effect):
782 try:
783 proceed = 0
784 old_name = v.init_list[id]["name"]
785
786 if v.init_list[id]["init"] == new_init:
787 self.post_syserror("Invalid input [" + str(self.init_system) + "]. Already at init count <font color='#0000ff'>" + str(new_init) + "</font>. Try /rankup or /rankdown instead.")
788 return
789
790 if effect == 1 and (self.isD20() or self.isRQ()): #d20 and RQ effects
791 if self.isEffect(id):
792 proceed = 1
793 self.post_sysmsg("<font color='#0000ff'><i>" + old_name + "</font></i> has had its init count changed \
794 to <font color='#0000ff'><i>" + str(new_init) + "</font></i>.", not v.init_list[id]["hidden"])
795 else:
796 self.post_syserror("Invalid input [" + str(self.init_system) + "]. Not an effect. Try /change instead.")
797
798 else: #d20, SR4, RQ characters
799 if self.isEffect(id):
800 self.post_syserror("Invalid input [" + str(self.init_system) + "]. Not a character. Try /changefx instead.")
801 else:
802 proceed = 1
803 self.post_sysmsg("<font color='#0000ff'><i>" + old_name + "</font></i>'s init count has changed to \
804 <font color='#0000ff'><i>" + str(new_init) + "</font></i>.", not v.init_list[id]["hidden"])
805 if proceed==1:
806
807 listslot_as_changed = 0
808 # hacks if currently selected listslot /change's, we select the next tag
809 if not self.isEnded() and id == self.init_listslot:
810 if not self.isLast(id):
811 self.init_listtag = v.init_list[id + 1]["tag"]
812 listslot_as_changed = 1
813 self.sandglass_reset()
814 else:
815 self.init_listtag = v.init_list[self.getLast()]["tag"]
816 self.init_next()
817
818 v.init_list[id]["init"] = new_init
819
820 # set the rank to the lowest rank available...
821 v.init_list[id]["rank"] = self.get_next_rank(v.init_list[id]["init"])
822
823 self.init_sort()
824
825 # tell if listslot as changed
826 if listslot_as_changed == 1:
827 if self.init_count >= v.init_list[id]['init']:
828 self.init_listslot -= 1
829 self.init_count = v.init_list[self.init_listslot]['init']
830 else:
831 self.init_listslot -= 1
832 self.init_next()
833 #self.post_now_up(self.init_listslot, self.message_nowup + ": ")
834 #self.init_next()
835
836 except:
837 if effect == 1:
838 self.post_syserror("Invalid input [" + str(self.init_system) + "]. Correct command is: /changefx list_# new_init_# (example: /change 1 4)")
839 else:
840 self.post_syserror("Invalid input [" + str(self.init_system) + "]. Correct command \
841 is: /change list_# new_init_# (example: /change 1 4)")
842
843
844 def init_sort(self):
845 if self.isD20():
846 self.sort_high()
847 elif self.isSR4():
848 self.sort_high()
849 elif self.isRQ():
850 self.sort_low()
851 else:
852 self.sort_high()
853
854
855 def sort_low(self):
856 v.init_list.sort(self.sort_low_initlist)
857 # this part readjusts the listslot when other objects are
858 # changed, added, moved or deleted from v.init_list
859 #count = self.init_count
860 if self.isEnded():
861 return
862 n = 0
863 last_tag = self.init_listtag
864 last_id = self.init_listslot
865 found = 0
866
867 for m in v.init_list:
868 id = v.init_list.index(m) # first listslot's id
869
870 if v.init_list[id]["tag"] == last_tag:
871 self.init_listslot = id
872 found = 1
873 break
874
875 # if can't find, it got /del'd
876 if found == 0 and self.init_listtag != "":
877 # next slot should've been bumped up, we re selecting it
878 try:
879 self.init_listtag = v.init_list[self.init_listslot]["tag"]
880 except:
881 #we del'd the last one... do nuttin
882 pass
883
884
885 def sort_high(self):
886 v.init_list.sort(self.sort_high_initlist)
887 v.init_list.reverse()
888 # this part readjusts the listslot when other objects are
889 # changed, added, moved or deleted from v.init_list
890 #count = self.init_count
891
892 if self.isEnded():
893 return
894 n = 0
895 last_tag = self.init_listtag
896 last_id = self.init_listslot
897 found = 0
898 for m in v.init_list:
899 id = v.init_list.index(m) # first listslot's id
900 #print "sid : " + str(id)
901 if v.init_list[id]["tag"] == last_tag:
902 self.init_listslot = id
903 found = 1
904 break
905 # if can't find, it got /del'd
906 if found == 0 and self.init_listtag != "":
907 # next slot should've been bumped up, we re selecting it
908 try:
909 self.init_listtag = v.init_list[self.init_listslot]["tag"]
910 except:
911 #we del'd the last one... do nuttin
912 pass
913
914
915 def sort_low_initlist(self, x, y):
916 if x['init'] < y['init']:
917 return -1
918 elif x['init'] > y['init']:
919 return 1
920 elif x['init'] == y['init']:
921 # if same init, we sort by rank
922 if x['rank'] > y['rank']:
923 return -1
924 elif x['rank'] < y['rank']:
925 return 1
926 else:
927 return 0
928 else: # shouldnt enter here
929 return 0
930
931
932 def sort_high_initlist(self, x, y):
933 if x['init'] < y['init']:
934 return -1
935 elif x['init'] > y['init']:
936 return 1
937 elif x['init'] == y['init']:
938 # if same init, we sort by rank
939 if x['rank'] < y['rank']:
940 return -1
941 elif x['rank'] > y['rank']:
942 return 1
943 else:
944 return 0
945 else: # shouldnt enter here
946 return 0
947
948
949 def init_next(self):
950 if self.isD20():
951 self.init_next_D20()
952 elif self.isSR4():
953 self.init_next_SR4()
954 elif self.isRQ():
955 self.init_next_RQ()
956
957
958 def init_next_D20(self):
959
960 if self.isEnded():
961 self.init_listslot = -1 # offsets +1 coming later, starts 0
962 self.init_listtag = ""
963 self.init_end = 1
964
965 if not self.isEnded():
966 try:
967 self.init_listslot += 1 #toldya
968 id = self.init_listslot
969 init = str(v.init_list[id]["init"])
970 name = str(v.init_list[id]["name"])
971 self.init_listtag = v.init_list[id]["tag"]
972 self.init_count = v.init_list[id]["init"]
973
974 if self.isEffect(id):
975 v.init_list[id]["duration"] -= 1 #subtract 1 rnd from duration
976 if self.getRoundsLeftInEffect(id) == 0:
977 self.post_effect(id, "EFFECT ENDING:")
978 self.init_delete(id, 0)
979
980 #nextslot = id #this effect got deleted, so id = former id+1
981
982 # hack if two consecutive effects and this one has ended
983 #if self.isEffect(nextslot):
984 # print "nextslot IS an effect"
985 # self.init_listslot -= 1 # zalarian
986 # id = self.init_listslot # zalarian
987 #else:
988 # print "nextslot IS NOT an effect"
989 # v.init_list[id]["hidden"] = 0
990 # self.post_now_up(id, self.message_nowup + ": ")
991
992 # reset the sandglass for this turn
993 self.sandglass_reset()
994 else:
995 if v.init_list[id]["hidden"] == 1:
996 rounds_left = "?"
997 else:
998 rounds_left = self.getRoundsLeftInEffect(id)
999
1000 if self.hide_id == 0:
1001 str_id = str(id+1) + ":"
1002 else:
1003 str_id = ""
1004
1005 self.post_effect(id, "EFFECT:")
1006
1007 nextslot = id + 1
1008
1009 if self.isEffect(nextslot):
1010 self.init_next_D20()
1011 else: #normal character, not effect
1012 v.init_list[id]["hidden"] = 0
1013
1014 self.post_now_up(id, self.message_nowup + ": ")
1015
1016 # reset the sandglass for this turn
1017 self.sandglass_reset()
1018
1019 except Exception, e:
1020
1021 self.init_end = 0
1022 self.init_round += 1
1023 self.init_count = 0
1024 self.post_sysmsg("<hr><font color='#ff0000'>End of Round<br>Starting Round <font color='#0000ff'><i># " + str(self.init_round) + "</font></i></font><hr>",1)
1025
1026
1027 def init_next_SR4(self, do_not_advance_past_init=0):
1028 if self.isEnded():
1029 self.init_listslot = -1 # offsets +1 coming later, starts 0
1030 self.init_listtag = ""
1031 self.init_end = 1
1032
1033 if not self.isEnded():
1034 if self.init_pass == 0:
1035 self.init_pass +=1
1036 if self.init_pass > 4:
1037 self.init_end = 0
1038 self.init_round += 1
1039 self.init_pass = 0
1040 msg = "<hr><font color='#ff0000'>End of Round<br>Starting Round <font color='#0000ff'><i># " + str(self.init_round) + "</font></i></font><hr>"
1041
1042 if self.reroll_type == 0: # Reroll Every Round (default) - VEG 2.2.7
1043 v.init_list = []
1044 msg += "<font color='#0000ff'>Roll New Initiatives</font><hr>"
1045 else: # Keep Same Inits Every Round - VEG 2.2.7
1046 pass
1047 self.post_sysmsg(msg,1)
1048
1049 else:
1050 try:
1051 valid_char = 0
1052 just_movement = 0
1053 while valid_char != 1:
1054 self.init_listslot += 1 #toldya
1055 id = self.init_listslot
1056 passes = v.init_list[id]["passes"] #exception raised here if noone left
1057
1058 if self.ip_order == 0: # ip order: 1/2/3/4 (normal) - VEG 2.2.7
1059 if passes >= self.init_pass:
1060 valid_char = 1
1061 elif self.hide_justmovement != 1: # not enough passes, but still gain movement
1062 just_movement = 1
1063 valid_char = 1
1064
1065 else: # ip order: 3/1/4/2 (Serbitar's house rule) or 4/1/3/2 (TinkerGnome's house rule) - VEG 2.2.7
1066 if self.init_pass == 1: # first pass: only people with 3+ (S) or 4+ (TG) IPs go
1067 if self.ip_order == 1 and passes >= 3: # ip order: 3/1/4/2
1068 valid_char = 1
1069 elif self.ip_order == 2 and passes >= 4: # ip order: 4/1/3/2
1070 valid_char = 1
1071 elif self.hide_justmovement != 1:
1072 just_movement = 1
1073 valid_char = 1
1074 elif self.init_pass == 2: # second pass: only people with 1+ IPs go
1075 if passes >= 1:
1076 valid_char = 1
1077 elif self.hide_justmovement != 1:
1078 just_movement = 1
1079 valid_char = 1
1080 elif self.init_pass == 3: # third pass: only people with 4+ (S) or 3+ (TG) IPs go
1081 if self.ip_order == 1 and passes >= 4: # ip order: 4/1/4/2
1082 valid_char = 1
1083 elif self.ip_order == 2 and passes >= 3: # ip order: 3/1/3/2
1084 valid_char = 1
1085 elif self.hide_justmovement != 1:
1086 just_movement = 1
1087 valid_char = 1
1088 elif self.init_pass == 4: # fourth pass: only people with 2+ IPs go
1089 if passes >= 2:
1090 valid_char = 1
1091 elif self.hide_justmovement != 1:
1092 just_movement = 1
1093 valid_char = 1
1094
1095 init = str(v.init_list[id]["init"])
1096 name = str(v.init_list[id]["name"])
1097 self.init_listtag = v.init_list[id]["tag"]
1098 self.init_count = v.init_list[id]["init"]
1099 v.init_list[id]["hidden"] = 0 # no more hidden
1100
1101 if just_movement == 0:
1102 self.post_now_up(id, self.message_nowup + ": ")
1103 else:
1104 self.post_movement(id, " JUST MOVEMENT:")
1105
1106 # reset the sandglass for this turn
1107 self.sandglass_reset()
1108
1109 if just_movement==1 and self.isMovement(id + 1) and do_not_advance_past_init==0:
1110 self.init_next_SR4() # for convenience sake, characters who only have movement
1111 # will be grouped together.
1112 # do_not_advance_past_init is a hackfix to avoid some
1113 # problems found with this trick
1114 elif self.sharesInit(id + 1): # rules say characters who share an init take
1115 self.init_next_SR4(1) # actions simultaneously (for the most part)
1116
1117 except:
1118 old_pass = self.init_pass
1119 self.init_pass += 1
1120 self.init_count = 0
1121 self.init_end = 0
1122 if self.init_pass != 5:
1123 self.post_sysmsg("<hr><font color='#ff0000'>End of Pass <font color='#0000ff'><i>#"\
1124 + str(old_pass) + "</font></i><br>Starting New Pass <font color='#0000ff'><i># " \
1125 + str(self.init_pass) + "</font></i></font><hr>", 1)
1126 else:
1127 self.init_next_SR4()
1128
1129
1130 def init_next_RQ(self):
1131 if self.isEnded():
1132 self.init_listslot = -1 # offsets +1 coming later, starts 0
1133 self.init_listtag = ""
1134 self.init_end = 1
1135
1136 if not self.isEnded():
1137 try:
1138 self.init_listslot += 1 #toldya
1139 id = self.init_listslot
1140 init = str(v.init_list[id]["init"])
1141 name = str(v.init_list[id]["name"])
1142 self.init_listtag = v.init_list[id]["tag"]
1143 self.init_count = v.init_list[id]["init"]
1144
1145 if self.isEffect(id):
1146 v.init_list[id]["duration"] -= 1 #subtract 1 rnd from duration
1147 if self.getRoundsLeftInEffect(id) == 0:
1148 self.post_effect(id, "EFFECT ENDING:")
1149 self.init_delete(id, 0)
1150
1151 # hack if two consecutive effects and this one has ended
1152 #if self.isEffect(nextslot):
1153 # self.init_listslot -= 1 # zalarian
1154 # id = self.init_listslot # zalarian
1155 #else:
1156 # v.init_list[id]["hidden"] = 0
1157
1158 # self.post_now_up(id, self.message_nowup + ": ")
1159
1160 # reset the sandglass for this turn
1161 self.sandglass_reset()
1162 else:
1163 if v.init_list[id]["hidden"] == 1:
1164 rounds_left = "?"
1165 else:
1166 rounds_left = self.getRoundsLeftInEffect(id)
1167
1168
1169 if self.hide_id == 0:
1170 str_id = str(id+1) + ":"
1171 else:
1172 str_id = ""
1173
1174 self.post_effect(id, "EFFECT:")
1175
1176 nextslot = id + 1
1177
1178 if self.isEffect(nextslot):
1179 self.init_next_RQ()
1180 else: #normal character, not effect
1181 v.init_list[id]["hidden"] = 0
1182
1183 self.post_now_up(id, self.message_nowup + ": ")
1184
1185 # reset the sandglass for this turn
1186 self.sandglass_reset()
1187
1188 except Exception, e:
1189 self.init_end = 0
1190 self.init_round += 1
1191 self.init_count = 0
1192 self.post_sysmsg("<hr><font color='#ff0000'>End of Round<br>Starting Round <font color='#0000ff'><i># " + str(self.init_round) + "</font></i></font><hr>",1)
1193
1194 def init_set_slot(self, id):
1195 try:
1196 if self.isEnded():
1197 raise
1198 else:
1199 if id == self.init_listslot:
1200 self.post_syserror("Slot <font color='#0000ff'>#" + str(id + 1) + "</font> already selected.")
1201 else:
1202 self.init_listtag = v.init_list[id]["tag"]
1203 self.init_listslot = id
1204 self.sandglass_reset()
1205 self.post_sysmsg("<font color='#0000ff'><i>" + v.init_list[id]["name"] + "</font></i> selected !")
1206
1207 except:
1208 self.post_syserror("Can't select slot <font color='#0000ff'>#" + str(id) + "</font>. Round must be started.")
1209
1210 def init_move(self, id, n):
1211 try:
1212 # how many inits we have so far
1213 list_size = len(v.init_list)
1214
1215 if self.init_debug == 1:
1216 print "list_size : " + str(list_size)
1217 print "id : " + str(id)
1218 print "pre n : " + str(n)
1219
1220 if id >= list_size:
1221 self.post_syserror("Can't move an unknown ID (<font color='#0000ff'>" + str(id+1) + "</font>) !")
1222 return
1223
1224 # are we going UP or DOWN ?
1225 if n > 0:
1226 up = 0
1227 step = 1
1228 # can't move down last object
1229 if self.isLast(id):
1230 self.post_syserror("Can't move <font color='#0000ff'>" + v.init_list[id]["name"] + "</font> this way! (Already at the last init)")
1231 return
1232
1233 max_move = list_size - id # maximum num of moves we could possibly do
1234 # cant move more than max_move position!!
1235 if n > max_move:
1236 n = max_move
1237 elif n < 0:
1238 up = 1
1239 step = -1
1240 #can't move up first object
1241 if self.isFirst(id):
1242 self.post_syserror("Can't move <font color='#0000ff'>" + v.init_list[id]["name"] + "</font> this way ! (Already at the first init)")
1243 return
1244
1245 max_move = id # maximum num of move we could possibly do
1246 # cant move more than max_move position!!
1247 if n > max_move:
1248 n = -max_move
1249 else:
1250 # shouldnt be here
1251 self.post_syserror("Can't move <font color='#0000ff'>" + v.init_list[id]["name"] + "</font> !")
1252 return 1
1253
1254 if self.init_debug == 1:
1255 print "n : " + str(n)
1256 print "step : " + str(step)
1257 print "max_move : " + str(max_move)
1258 print "up : " + str(up)
1259 print "len : " + str(len(range(id , (id + n + step), step)))
1260
1261 # suppose we're not moving, id_n will be the target id we're moving to
1262 id_n = id
1263
1264 # find the last init we can go with 'n' steps and staying on the init count of object 'id'
1265 for k in range(id + step , (id + n + step), step):
1266 #print "k... " + str(k)
1267 if v.init_list[k]["init"] != v.init_list[id]["init"]:
1268 # cant more further than k + step.. go away
1269 break
1270 else:
1271 id_n = k
1272
1273 # we can't move if id_n is the same as id. probably only alone on this init count
1274 if id_n == id:
1275 self.post_syserror("Can't move <font color='#0000ff'>" + v.init_list[id]["name"] + "</font> ! (you may only rankup/rankdown within the same init value)</i>")
1276 return
1277
1278 if self.init_debug == 1:
1279 print "id_n : " + str(id_n)
1280
1281 # now we have to set the rank correctly
1282 if up and self.isFirst(id_n):
1283 # going up and we're moving in first position of all inits
1284 v.init_list[id]["rank"] = v.init_list[id_n]["rank"] + 1
1285 elif not up and self.isLast(id_n):
1286 # going down and we're moving in last position of all inits
1287 v.init_list[id]["rank"] = v.init_list[id_n]["rank"] - 1
1288 elif v.init_list[id_n + step]["init"] != v.init_list[id]["init"]:
1289 # moving in first (up) or last (down) position of the current init count
1290 v.init_list[id]["rank"] = v.init_list[id_n]["rank"] - step
1291 elif up and v.init_list[id_n + step]["init"] == v.init_list[id]["init"]:
1292 # moving up somewhere between multiple id of the same init count
1293 v.init_list[id]["rank"] = v.init_list[id_n]["rank"] - (step * (v.init_list[id_n + step]["rank"] - v.init_list[id_n]["rank"]) / 2.0)
1294 elif not up and v.init_list[id_n + step]["init"] == v.init_list[id]["init"]:
1295 # moving down somewhere between multiple id of the same init count
1296 v.init_list[id]["rank"] = v.init_list[id_n]["rank"] + (step * (v.init_list[id_n + step]["rank"] - v.init_list[id_n]["rank"]) / 2.0)
1297
1298 self.post_sysmsg("<font color='#0000ff'><i>" + v.init_list[id]["name"] + "</font></i> moved !", not v.init_list[id]["hidden"])
1299
1300 # hack, if we're moving the selected slot or at the selected
1301 # slot, we're staying at the same position.
1302 if not self.isEnded():
1303 if id_n == self.init_listslot:
1304 # we're moving AT the selected slot
1305 self.init_listtag = v.init_list[id]["tag"]
1306 self.sandglass_reset()
1307 self.post_now_up(id, self.message_nowup + ": ")
1308 # works fine unless you try to rank by more than one step, so
1309 # currently this section (or the other) is bugged
1310 if id == self.init_listslot:
1311 # we're moving THE selected slot
1312 if up:
1313 self.init_listtag = v.init_list[id-1]["tag"]
1314 else:
1315 self.init_listtag = v.init_list[id+1]["tag"]
1316 self.post_now_up(id_n, self.message_nowup + ": ")
1317 # works fine unless you try to rank by more than one step, so
1318 # currently this section (or the other) is bugged
1319 self.sandglass_reset()
1320
1321
1322 # sort that list again
1323 self.init_sort()
1324
1325 except:
1326 self.post_syserror("Can't move <font color='#0000ff'>" + v.init_list[id]["name"] + "</font> ! (May only rankup/rankdown within the same init value)")
1327
1328
1329 def init_delay_now(self, id):
1330 try:
1331 # can't delay if round ended
1332 if self.isEnded():
1333 self.post_syserror("Can't delay until the round has started.", 0)
1334 return
1335
1336 if self.isD20() or self.isRQ():
1337 # get current tag
1338 tag_current = v.init_list[self.init_listslot]["tag"]
1339 tag_delay = v.init_list[id]["tag"]
1340 name_delay = v.init_list[id]["name"]
1341
1342 # can't delay current listslot
1343 if self.init_listslot == id:
1344 self.post_syserror("Can't delay current selected slot.", 0)
1345 return
1346
1347 # if not on the same init count
1348 if v.init_list[self.init_listslot]["init"] != v.init_list[id]["init"]:
1349 # generate array needed by init_change() as first parameter
1350 tab = [ 0, id + 1, v.init_list[self.init_listslot]["init"]]
1351 self.init_change(tab, v.init_list[id]["type"])
1352 self.init_sort()
1353
1354 #print "name_delay : " + str(name_delay)
1355 #print "tag_delay : " + str(tag_delay)
1356 #print "tag_current : " + str(tag_current)
1357 #print "slot_tag : " + str(v.init_list[self.init_listslot]["tag"])
1358 #print "listslot : " + str(self.init_listslot)
1359
1360 # must rankup if needed (init_change() move at the end of a group if at same init count
1361 if not (v.init_list[self.init_listslot]["tag"] == tag_delay):
1362 # must find where is tag_delay and move it before tag_current
1363 for m in v.init_list:
1364 if m["tag"] == tag_delay:
1365 new_id_delay = v.init_list.index(m)
1366 break
1367
1368 step = (self.init_listslot - new_id_delay)
1369 self.init_move(new_id_delay, step)
1370 #self.init_listtag = tag_delay
1371 self.init_sort()
1372
1373 self.post_now_up(self.init_listslot, "NOW UP FOR THE KILLING (DELAYED ACTION):")
1374
1375 self.sandglass_reset()
1376
1377 else:
1378 self.post_syserror(">Can't delay in " + str(self.init_system) + ".")
1379
1380 except Exception, e:
1381 print str(e)
1382 self.post_syserror("Invalid input [" + str(self.init_system) + "]. Correct command is: /initdelaynow list_number")
1383
1384 ###############################################################
1385 #### Sandglass Functions
1386 ###############################################################
1387
1388 # will send reminder to the chat if needed
1389 def sandglass(self):
1390 try:
1391 if self.sandglass_delay == 0 or self.sandglass_status == 1:
1392 pass
1393 # send reminder except for effect
1394 elif not self.isEnded() and not self.isEffect(self.init_listslot):
1395 self.sandglass_count += 1
1396 if self.sandglass_skip_interval and not (self.sandglass_count % (self.sandglass_delay * self.sandglass_skip_interval)):
1397 uname = v.init_list[self.init_listslot]["name"]
1398 self.post_sysmsg("TIME'S UP <font color='#0000ff'><i>" + uname + "</font></i>!!! (<i>" + str(self.sandglass_count) + " seconds elapsed</i>)", 1)
1399 self.init_next()
1400 elif not (self.sandglass_count % self.sandglass_delay):
1401 self.post_sysmsg("REMINDER to <font color='#0000ff'><i>" + v.init_list[self.init_listslot]["name"] + "</font></i> : IT'S YOUR TURN! (<i>" + str(self.sandglass_count) + " seconds elapsed</i>)", 1)
1402
1403 except:
1404 pass
1405
1406
1407 def sandglass_reset(self):
1408 try:
1409 if self.sandglass_delay > 0:
1410 self.sandglass_count = 0
1411 self.sandglass_resume()
1412 except:
1413 pass
1414
1415
1416 # status : 0 = running
1417 # 1 = pause
1418 def sandglass_pause(self):
1419 try:
1420 if self.sandglass_delay > 0:
1421 self.sandglass_status = 1
1422 except:
1423 pass
1424
1425
1426 def sandglass_resume(self):
1427 try:
1428 if self.sandglass_delay > 0:
1429 self.sandglass_status = 0
1430 except:
1431 pass
1432
1433 def set_sandglass_force_skip(self,interval):
1434 self.sandglass_skip_interval = interval
1435 if interval == 0:
1436 self.post_sysmsg("Sandglass force turn skip is now off.", 1)
1437 else:
1438 self.post_sysmsg("Sandglass force turn skip is now set to " + str(interval) + " interval(s).", 1)
1439 self.config_save() # VEG 2.2.6
1440
1441 def set_sandglass(self, delay):
1442 self.sandglass_delay = delay
1443 if delay == 0:
1444 self.post_sysmsg("Sandglass is now off.", 1)
1445 else:
1446 self.post_sysmsg("Sandglass is now set to " + str(delay) + " seconds.", 1)
1447 self.config_save() # VEG 2.2.6
1448
1449 ###############################################################
1450 #### Config/Save/Load Functions
1451 ###############################################################
1452
1453 def init_save(self, slot, public):
1454 try:
1455 modname = "xxinit2-" + str(slot)
1456
1457 self.plugindb.SetString(modname, "init_recording", str(self.init_recording))
1458 self.plugindb.SetString(modname, "init_round", str(self.init_round))
1459 self.plugindb.SetString(modname, "init_title", str(self.init_title))
1460 self.plugindb.SetString(modname, "init_count", str(self.init_count))
1461 self.plugindb.SetString(modname, "init_pass", str(self.init_pass))
1462 self.plugindb.SetString(modname, "init_listslot", str(self.init_listslot))
1463 self.plugindb.SetString(modname, "init_listtag", str(self.init_listtag))
1464 self.plugindb.SetString(modname, "init_end", str(self.init_end))
1465 self.plugindb.SetString(modname, "init_system", str(self.init_system))
1466 self.plugindb.SetString(modname, "init_list", repr(v.init_list))
1467 self.plugindb.SetString(modname, "sandglass_status", repr(self.sandglass_status))
1468
1469 if self.init_title != "":
1470 title_str = " <i>[" + self.init_title + "]</i>"
1471 else:
1472 title_str = ""
1473
1474 if slot == 0:
1475 #self.post_sysmsg("Initiative list autosaved successfully.", public)
1476 # this is annoying, so i disabled the text output
1477 pass
1478 else:
1479 self.post_sysmsg("Initiative list saved successfully on slot #" + str(slot) + title_str + ".", public)
1480
1481 except Exception, e:
1482 print "err saving : " + str(e)
1483
1484
1485 def init_load(self, slot):
1486 try:
1487 self.init_clear()
1488
1489 modname = "xxinit2-" + str(slot)
1490
1491 self.init_recording = int(self.plugindb.GetString(modname, "init_recording","0"))
1492 self.init_round = int(self.plugindb.GetString(modname, "init_round", "0"))
1493 self.init_title = str(self.plugindb.GetString(modname, "init_title", ""))
1494 self.init_count = int(self.plugindb.GetString(modname, "init_count", "0"))
1495 self.init_pass = int(self.plugindb.GetString(modname, "init_pass", "0"))
1496 self.init_listslot = int(self.plugindb.GetString(modname, "init_listslot", "0"))
1497 self.init_listtag = str(self.plugindb.GetString(modname, "init_listtag", ""))
1498 self.init_end = int(self.plugindb.GetString(modname, "init_end", "0"))
1499 self.init_system = str(self.plugindb.GetString(modname, "init_system", ""))
1500 v.init_list = eval(self.plugindb.GetString(modname, "init_list", ""))
1501 self.sandglass_status = eval(self.plugindb.GetString(modname, "sandglass_status", "0"))
1502
1503 if self.init_title != "":
1504 title_str = " <i>[" + self.init_title + "]</i>"
1505 else:
1506 title_str = ""
1507
1508 if slot == 0:
1509 self.post_sysmsg("Last autosaved initiative list loaded successfully.")
1510 else:
1511 self.post_sysmsg("Initiative list slot #" + str(slot) + title_str + " loaded successfully.")
1512 self.config_save() # VEG 2.2.6
1513
1514 except Exception, e:
1515 #print "err loading: " + e
1516 self.post_syserror("Error loading Initiative list.")
1517
1518
1519 def autosave(self):
1520 try:
1521 slot = 0
1522 if self.autosave_delay != 0:
1523 self.autosave_count += 1
1524 if not (self.autosave_count % self.autosave_delay):
1525 self.autosave_count = 0
1526 self.init_save(slot, 0)
1527
1528 except Exception, e:
1529 print str(e)
1530
1531
1532 def set_autosave(self, delay):
1533
1534 self.autosave_delay = delay
1535
1536 if delay == 0:
1537 self.post_sysmsg("Autosave is now off.")
1538 else:
1539 self.post_sysmsg("Autosave is now done every " + str(delay) + " seconds.")
1540
1541
1542 def config_save(self):
1543 try:
1544 modname = "xxinit2-config"
1545
1546 # don't want python to convert this to the strings "TRUE" or "FALSE"
1547 if self.init_recording == 0:
1548 self.init_recording = 0
1549 else:
1550 self.init_recording = 1
1551
1552 if self.hide_id == 0:
1553 self.hide_id = 0
1554 else:
1555 self.hide_id = 1
1556
1557 if self.hide_ondeck == 0:
1558 self.hide_ondeck = 0
1559 else:
1560 self.hide_ondeck = 1
1561
1562 if self.hide_justmovement == 0:
1563 self.hide_justmovement = 0
1564 else:
1565 self.hide_justmovement = 1
1566
1567 self.plugindb.SetString(modname, "init_recording", str(self.init_recording))
1568 self.plugindb.SetString(modname, "init_system", str(self.init_system))
1569 self.plugindb.SetString(modname, "sandglass_count", str(self.sandglass_count))
1570 self.plugindb.SetString(modname, "sandglass_delay", str(self.sandglass_delay))
1571 self.plugindb.SetString(modname, "sandglass_skip_interval", str(self.sandglass_skip_interval))
1572 self.plugindb.SetString(modname, "autosave_delay", str(self.autosave_delay))
1573 self.plugindb.SetString(modname, "autosave_count", str(self.autosave_count))
1574 self.plugindb.SetString(modname, "hide_id", str(self.hide_id))
1575 self.plugindb.SetString(modname, "hide_ondeck", str(self.hide_ondeck))
1576 self.plugindb.SetString(modname, "hide_justmovement",str(self.hide_justmovement))
1577 self.plugindb.SetString(modname, "message_nowup", str(self.message_nowup))
1578 self.plugindb.SetString(modname, "msghand_timer", str(self.msghand_timer)) # VEG 2.2.6
1579 self.plugindb.SetString(modname, "msghand_warning", str(self.msghand_warning)) # VEG 2.2.6
1580 self.plugindb.SetString(modname, "reroll_type", str(self.reroll_type)) # VEG 2.2.7
1581 self.plugindb.SetString(modname, "ip_order", str(self.ip_order)) # VEG 2.2.7
1582
1583 #self.post_sysmsg("Configuration saved successfully.",0)
1584 print "Initiative configuration saved successfully."
1585
1586 except:
1587 self.post_syserror("Error saving configuration.",0)
1588
1589
1590 def config_load(self):
1591
1592 try:
1593 modname = "xxinit2-config"
1594
1595 self.init_recording = int(self.plugindb.GetString(modname, "init_recording","0"))
1596 self.init_system = str(self.plugindb.GetString(modname, "init_system", ""))
1597 self.sandglass_count = int(self.plugindb.GetString(modname, "sandglass_count", "0"))
1598 self.sandglass_delay = int(self.plugindb.GetString(modname, "sandglass_delay", "0"))
1599 self.sandglass_skip_interval = int(self.plugindb.GetString(modname, "sandglass_skip_interval", "0"))
1600 self.autosave_delay = int(self.plugindb.GetString(modname, "autosave_delay", "0"))
1601 self.autosave_count = int(self.plugindb.GetString(modname, "autosave_count", "0"))
1602 self.hide_id = int(self.plugindb.GetString(modname, "hide_id", "0"))
1603 self.hide_ondeck = int(self.plugindb.GetString(modname, "hide_ondeck", "0"))
1604 self.hide_justmovement = int(self.plugindb.GetString(modname, "hide_justmovement", "0"))
1605 self.message_nowup = str(self.plugindb.GetString(modname, "message_nowup", ""))
1606 self.msghand_timer = int(self.plugindb.GetString(modname, "msghand_timer", "0")) # VEG 2.2.6
1607 self.msghand_warning = int(self.plugindb.GetString(modname, "msghand_warning", "0")) # VEG 2.2.6
1608 self.reroll_type = int(self.plugindb.GetString(modname, "reroll_type", "0")) # VEG 2.2.7
1609 self.ip_order = int(self.plugindb.GetString(modname, "ip_order", "0")) # VEG 2.2.7
1610
1611 # if system blank... no config was loaded
1612 if self.init_system == "":
1613 raise
1614
1615 self.post_sysmsg("Configuration loaded successfully.",0)
1616 self.config_save() # VEG 2.2.6
1617
1618 except:
1619 self.config_default()
1620
1621
1622 def config_default(self):
1623
1624 self.init_recording = 1
1625 self.init_system = "D20"
1626 self.sandglass_count = 0
1627 self.sandglass_delay = 0
1628 self.sandglass_status = 0
1629 self.sandglass_skip_interval = 0
1630 self.autosave_delay = 60
1631 self.autosave_count = 0
1632 self.hide_id = 0
1633 self.hide_ondeck = 0
1634 self.hide_justmovement = 0
1635 self.message_nowup = "NEXT UP FOR THE KILLING"
1636 self.msghand_timer = 0
1637 self.msghand_warning = 1
1638 self.reroll_type = 0
1639 self.ip_order = 0
1640
1641 self.post_sysmsg("Default configuration loaded successfully.",0)
1642 self.config_save() # VEG 2.2.6
1643
1644 def config_show(self):
1645
1646 try:
1647 self.post_sysmsg("<br><u>Init Tool system config v" + str(self.version) + "</u><br>")
1648
1649 if self.init_recording == 0:
1650 buf = "disabled";
1651 else:
1652 buf = "enabled";
1653 self.post_my_msg("<b>Init Recording:</b> " + str(buf))
1654
1655 self.post_my_msg("<b>System:</b> " + str(self.init_system))
1656
1657 if self.sandglass_delay == 0:
1658 buf = "disabled";
1659 else:
1660 buf = str(self.sandglass_delay) + " seconds"
1661 if self.sandglass_status == 1:
1662 buf += str(" [ paused ]")
1663
1664 self.post_my_msg("<b>Sandglass:</b> " + str(buf))
1665
1666 if self.sandglass_skip_interval == 0:
1667 buf = "disabled";
1668 else:
1669 buf = "every " + str(self.sandglass_skip_interval) + " interval(s)."
1670 self.post_my_msg("<b>Sandglass force skip:</b> " + str(buf))
1671
1672 if self.autosave_delay == 0:
1673 buf = "disabled";
1674 else:
1675 buf = str(self.autosave_delay) + " seconds"
1676 self.post_my_msg("<b>Autosave:</b> " + str(buf))
1677
1678 if self.msghand_warning == 0: # VEG 2.2.6
1679 buf = "disabled";
1680 else:
1681 buf = "enabled";
1682 self.post_my_msg("<b>Show Message Handler Warning:</b> " + str(buf))
1683
1684 if self.hide_id == 0:
1685 buf = "disabled";
1686 else:
1687 buf = "enabled";
1688 self.post_my_msg("<b>Hide IDs:</b> " + str(buf))
1689
1690 if self.hide_ondeck == 0:
1691 buf = "disabled";
1692 else:
1693 buf = "enabled";
1694 self.post_my_msg("<b>Hide 'On Deck':</b> " + str(buf))
1695
1696 if self.hide_justmovement == 0:
1697 buf = "disabled";
1698 else:
1699 buf = "enabled";
1700 self.post_my_msg("<b>[SR4-only] Hide 'Just Movement':</b> " + str(buf))
1701
1702 if self.reroll_type == 0: # VEG 2.2.7
1703 buf = "reroll inits every round (normal)";
1704 else:
1705 buf = "keep same inits every round (house rule)";
1706 self.post_my_msg("<b>[SR4-only] Init Reroll?:</b> " + str(buf))
1707
1708 if self.ip_order == 0: # VEG 2.2.7
1709 buf = "1/2/3/4 (normal)";
1710 elif self.ip_order == 1:
1711 buf = "3/1/4/2 (Serbitar's house rule)"
1712 elif self.ip_order == 2:
1713 buf = "4/1/3/2 (TinkerGnome's house rule)";
1714 self.post_my_msg("<b>[SR4-only] IP Order:</b> " + str(buf))
1715
1716 self.post_my_msg("<b>Now Up Message:</b> " + str(self.message_nowup))
1717
1718 except:
1719 self.post_syserror("Error reading configuration.",0)
1720
1721 ###############################################################
1722 #### Display Functions
1723 ###############################################################
1724
1725 def inits_list(self, public):
1726 if self.isD20():
1727 self.inits_list_D20(public)
1728 elif self.isSR4():
1729 self.inits_list_SR4(public)
1730 elif self.isRQ():
1731 self.inits_list_RQ(public)
1732
1733 def inits_list_D20(self, public):
1734
1735 current_count = str(self.init_count)
1736
1737 if self.sandglass_delay == 0:
1738 current_sandglass = "off"
1739 else:
1740 current_sandglass = str(self.sandglass_delay) + " sec."
1741 if self.sandglass_status == 1:
1742 current_sandglass += str(" [ paused ]")
1743
1744 msg = "<br><br><b>Initiatives (Current Count: " + current_count + "; Sandglass: " + current_sandglass + "):</b><br>"
1745 for m in v.init_list:
1746
1747 # dont show public if character (type 0)
1748 if public and m["type"] == 0 and m["hidden"] == 1:
1749 continue
1750
1751 # id in the list appears as 1 to (N+1), in reality it's 0 to N
1752 id = v.init_list.index(m)
1753 idplusone = str(id+1)
1754
1755 if not self.isEnded() and self.init_listslot == id:
1756 msg += "<b>"
1757
1758 # we dont want to show IDs to everyone
1759 if public and self.hide_id:
1760 msg += " "
1761 else:
1762 msg += " <font color='#ff0000'>" + idplusone + ") :</font>"
1763
1764 if self.isEffect(id):
1765 # example
1766 # 5: (*14) <i>Effect: Tlasco's Bless (4)</i>
1767 if public and m["hidden"] == 1:
1768 duration = "?"
1769 else:
1770 duration = m["duration"]
1771 msg += " [" + str(m["init"])+"] "
1772 msg += "<font color='#0000ff'><i>Effect: " + str(m["name"]) + " (" + str(duration) + ")</i>"
1773 else:
1774 # example
1775 # 6: (14) Tlasco
1776 msg+= " ["+str(m["init"])+"] <font color='#0000ff'>" + str(m["name"])
1777 if self.init_debug:
1778 #msg+= " [rank:" + str(m["rank"]) + "; tag: " + str(m["tag"]) + "]</font>"
1779 msg+= " [rank:" + str(m["rank"]) + "; type: " + str(m["type"]) + "]</font>"
1780 #msg+= " [rank:" + str(m["rank"]) + "]</font>"
1781 else:
1782 msg+= "</font>"
1783
1784 if not public and m["hidden"] == 1:
1785 msg += " <i>[H]</i>"
1786
1787 if not self.isEnded() and self.init_listslot == id:
1788 msg += "</b>"
1789
1790 msg += "<br>"
1791 self.post_my_msg(msg,public)
1792
1793
1794 def inits_list_SR4(self, public):
1795
1796 if self.sandglass_delay == 0:
1797 current_sandglass = "off"
1798 else:
1799 current_sandglass = str(self.sandglass_delay) + " sec."
1800 if self.sandglass_status == 1:
1801 current_sandglass += str(" [ paused ]")
1802
1803 if self.ip_order == 0:
1804 current_ip_order = "1/2/3/4 (normal)"
1805 elif self.ip_order == 1:
1806 current_ip_order = "3/1/4/2 (Serbitar's house rule)"
1807 else:
1808 current_ip_order = "4/1/3/2 (TinkerGnome's house rule)"
1809 current_count = str(self.init_count)
1810 current_pass = str(self.init_pass)
1811
1812 msg = "<br><br><b>Initiatives (Current Pass: " + current_pass \
1813 + "; Current Count: " + current_count + "), Sandglass: " \
1814 + current_sandglass + ", IP Order: " + current_ip_order \
1815 + "</b><br>"
1816 msg += "<table border='1'><tr>&nbsp;<th></th>"
1817
1818 if self.init_pass==1:
1819 msg += "<th><b><font color='#ff0000'>Pass 1</font></b></th>"
1820 else:
1821 msg += "<th>Pass 1</th>"
1822
1823 if self.init_pass==2:
1824 msg += "<th><b><font color='#ff0000'>Pass 2</font></b></th>"
1825 else:
1826 msg += "<th>Pass 2</th>"
1827
1828 if self.init_pass==3:
1829 msg += "<th><b><font color='#ff0000'>Pass 3</font></b></th>"
1830 else:
1831 msg += "<th>Pass 3</th>"
1832
1833 if self.init_pass==4:
1834 msg += "<th><b><font color='#ff0000'>Pass 4</font></b></th></tr>"
1835 else:
1836 msg += "<th>Pass 4</th></tr>"
1837
1838 for m in v.init_list:
1839 # id in the list appears as 1 to (N+1), in reality it's 0 to N
1840 id = v.init_list.index(m)
1841 idplusone = str(id+1)
1842 # example
1843 # | Init Pass 1 | Init Pass 2 | etc... | |
1844 # ---------------------------
1845 # 6: Tlasco | 13 | 13 | (blank) | (blank) |
1846
1847 # we dont want to show IDs to everyone
1848 if public and self.hide_id:
1849 msg += " <tr><th>"
1850 else:
1851 msg += " <tr><td><font color='#ff0000'>" + idplusone + ":</font> "
1852
1853 # bold the current player's name
1854 if not self.isEnded() and self.init_listslot == id:
1855 msg += "<b><font color='#0000ff'>" + str(m["name"]) + "</font></b></td>"
1856 else:
1857 msg += "<font color='#0000ff'>" + str(m["name"]) + "</font></td>"
1858
1859 ip = self.ip_order #ip==0 is 1/2/3/4 (normal) - VEG 2.2.7
1860 #ip==1 is 3/1/4/2 (Serbitar's house rule)
1861 #ip==2 is 4/1/3/2 (TinkerGnome's house rule)
1862 passes = m["passes"]
1863 # pass one
1864 if (ip==0 and passes >= 1) or (ip==1 and passes >= 3) or (ip==2 and passes >= 4):
1865 msg += "<td align=center>"+str(m["init"]) + "</td>"
1866 else:
1867 msg += "<td>&nbsp;</td>"
1868 # pass two
1869 if (ip==0 and passes >= 2) or (ip==1 and passes >= 1) or (ip==2 and passes >= 1):
1870 msg += "<td align=center>"+str(m["init"]) + "</td>"
1871 else:
1872 msg += "<td>&nbsp;</td>"
1873 # pass three
1874 if (ip==0 and passes >= 3) or (ip==1 and passes >= 4) or (ip==2 and passes >= 3):
1875 msg += "<td align=center>" + str(m["init"]) + "</td>"
1876 else:
1877 msg += "<td>&nbsp;</td>"
1878 # pass four
1879 if (ip==0 and passes >= 4) or (ip==1 and passes >= 2) or (ip==2 and passes >= 2):
1880 msg += "<td align=center>" + str(m["init"]) + "</td>"
1881 else:
1882 msg += "<td>&nbsp;</td>"
1883
1884 msg += "</tr>"
1885
1886 msg += "</table>"
1887 self.post_my_msg(msg, public)
1888
1889
1890 def inits_list_RQ(self, public):
1891 current_count = str(self.init_count)
1892
1893 if self.sandglass_delay == 0:
1894 current_sandglass = "off"
1895 else:
1896 current_sandglass = str(self.sandglass_delay) + " sec."
1897 if self.sandglass_status == 1:
1898 current_sandglass += str(" [ paused ]")
1899
1900 msg = "<br><br><b>Initiatives (Current Strike Rank: " + current_count + "; Sandglass: " + current_sandglass + "):</b><br>"
1901 for m in v.init_list:
1902
1903 # dont show public if character (type 0)
1904 if public and m["type"] == 0 and m["hidden"] == 1:
1905 continue
1906
1907 # id in the list appears as 1 to (N+1), in reality it's 0 to N
1908 id = v.init_list.index(m)
1909 idplusone = str(id+1)
1910
1911 if not self.isEnded() and self.init_listslot == id:
1912 msg += "<b>"
1913
1914 # we dont want to show IDs to everyone
1915 if public and self.hide_id:
1916 msg += " "
1917 else:
1918 msg += " <font color='#ff0000'>" + idplusone + ") :</font>"
1919
1920 if self.isEffect(id):
1921 # example
1922 # 5: (*14) <i>Effect: Tlasco's Bless (4)</i>
1923 if public and m["hidden"] == 1:
1924 duration = "?"
1925 else:
1926 duration = m["duration"]
1927 msg += " [" + str(m["init"])+"] "
1928 msg += "<font color='#0000ff'><i>Effect: " + str(m["name"]) + " (" + str(duration) + ")</i>"
1929 else:
1930 # example
1931 # 6: (14) Tlasco
1932 msg+= " ["+str(m["init"])+"] <font color='#0000ff'>" + str(m["name"])
1933 if self.init_debug:
1934 #msg+= " [rank:" + str(m["rank"]) + "; tag: " + str(m["tag"]) + "]</font>"
1935 msg+= " [rank:" + str(m["rank"]) + "; type: " + str(m["type"]) + "]</font>"
1936 #msg+= " [rank:" + str(m["rank"]) + "]</font>"
1937 else:
1938 msg+= "</font>"
1939
1940 if not public and m["hidden"] == 1:
1941 msg += " <i>[H]</i>"
1942
1943 if not self.isEnded() and self.init_listslot == id:
1944 msg += "</b>"
1945
1946 msg += "<br>"
1947 self.post_my_msg(msg, public)
1948
1949
1950 def post_now_up(self, id, text):
1951
1952 #if v.init_list[id]["hidden"] == 0:
1953 if self.hide_id == 0:
1954 id_str = "<font color='#000000'><b>" + str(id + 1) + ")</b></font>"
1955 else:
1956 id_str = ""
1957
1958 try:
1959 id_next = self.getNext(id)
1960 str_on_deck = ""
1961 if id_next != -1:
1962 if self.hide_ondeck != 1:
1963 str_on_deck = "<br><i><font color='#000000'>(on deck: [" + str(v.init_list[id_next]["init"]) + "] " + str(v.init_list[id_next]["name"]) + ")</font></i>"
1964
1965 except Exception, e:
1966 print str(e)
1967
1968 self.post_my_msg("<table border=1 width=100% align='center'>\
1969 <tr>\
1970 <td>" + str(id_str) + " <font color='#ff0000'><b><u>" + str(text)\
1971 + "</u></b></font><font color='#0000ff'><b>"\
1972 + " <font color='#000000'></b>[" + str(v.init_list[id]["init"]) + "]<b></font> "\
1973 + str(v.init_list[id]["name"]) + "</b></font> " + str_on_deck + "\
1974 </td>\
1975 </tr>\
1976 </table>", 1)
1977
1978 def post_movement(self, id, text):
1979
1980 #if v.init_list[id]["hidden"] == 0:
1981 if self.hide_id == 0:
1982 id_str = "<font color='#000000'><b>" + str(id + 1) + ")</b></font>"
1983 else:
1984 id_str = ""
1985
1986 self.post_my_msg("<table border=1 width=100% align='center'>\
1987 <tr>\
1988 <td>" + str(id_str) + " <font color='#0000ff'><b><i>" + str(text)\
1989 + "</i></b></font><font color='#0000ff'><b>"\
1990 + " <font color='#000000'></b>[" + str(v.init_list[id]["init"]) + "]<b></font> "\
1991 + str(v.init_list[id]["name"]) + "</b></font> \
1992 </td>\
1993 </tr>\
1994 </table>", 1)
1995
1996 def post_effect(self, id, text):
1997
1998 if self.hide_id == 0:
1999 id_str = "<font color='#000000'><b>" + str(id + 1) + ")</b></font>"
2000 else:
2001 id_str = ""
2002
2003 if v.init_list[id]["hidden"] == 1:
2004 rounds_left = "?"
2005 else:
2006 rounds_left = self.getRoundsLeftInEffect(id)
2007
2008 if(self.getRoundsLeftInEffect(id) > 0):
2009 self.post_my_msg("<table border=1 width=100% align='center'>\
2010 <tr>\
2011 <td>" + str(id_str) + " <font color='#0000ff'><b><i>" + str(text)\
2012 + "</i></b></font><font color='#0000ff'>"\
2013 + " <font color='#000000'>[" + str(v.init_list[id]["init"]) + "]</font> <i>"\
2014 + str(v.init_list[id]["name"]) + "</i></font> : <b>" + str(rounds_left) + "</b> round(s) remaining.\
2015 </td>\
2016 </tr>\
2017 </table>", 1)
2018 else:
2019 self.post_my_msg("<table border=1 width=100% align='center'>\
2020 <tr>\
2021 <td>" + str(id_str) + " <font color='#0000ff'><b><i>" + str(text)\
2022 + "</i></b></font><i>"\
2023 + " [" + str(v.init_list[id]["init"]) + "] <font color='#0000ff'>"\
2024 + str(v.init_list[id]["name"]) + "</font></i>\
2025 </td>\
2026 </tr>\
2027 </table>", 1)
2028
2029
2030 def post_my_msg(self, msg,send=0):
2031 tmp = self.init_recording
2032
2033 # have to disable the tool in order to post or else you get a clone
2034 self.init_recording = 0
2035 self.chat.Post(msg,send)
2036
2037 self.init_recording = tmp
2038
2039
2040 def post_syserror(self, msg, send=0):
2041 self.post_my_msg("<font color='#ff0000'><b><i>" + msg + "</i></b></font>", send)
2042
2043
2044 def post_sysmsg(self, msg,send=0):
2045 self.post_my_msg("<b>" + msg + "</b>", send)
2046
2047
2048 def toggle_hidden(self, id):
2049 try:
2050 #print "id : " + str(id)
2051 v.init_list[id]["hidden"] = not v.init_list[id]["hidden"]
2052 if v.init_list[id]["hidden"] == 1:
2053 tmp = "hidden"
2054 else:
2055 tmp = "visible"
2056 self.post_sysmsg(str(v.init_list[id]["name"]) + " now " + tmp + ".")
2057
2058 except:
2059 self.post_syserror("Invalid format. Correct command is: /togglehidden init_#")
2060
2061 ###############################################################
2062 #### Conditional + Other Functions
2063 ###############################################################
2064
2065 def check_version(self):
2066 if(int(replace(orpg.orpg_version.VERSION, ".", "")) < int(replace(self.orpg_min_version, ".", ""))):
2067 self.post_sysmsg("<br><font color='#ff0000'>WARNING</font>: You are currently using OpenRPG " + str(orpg.orpg_version.VERSION) + " but you need OpenRPG " + str(self.orpg_min_version) + " or greater to run the Initiative Tool " + str(self.version) + "<br>Use it at your own risk!</b><br>")
2068
2069 def isD20(self):
2070 if self.init_system == "D20":
2071 return 1
2072 else:
2073 return 0
2074
2075 def isSR4(self):
2076 if self.init_system == "SR4":
2077 return 1
2078 else:
2079 return 0
2080
2081 def isRQ(self):
2082 if self.init_system == "RQ":
2083 return 1
2084 else:
2085 return 0
2086
2087 def isEnded(self):
2088 if self.init_end == 0:
2089 return 1
2090 else:
2091 return 0
2092
2093 def getFirst(self):
2094 return(0)
2095
2096 def getLast(self):
2097 return(len(v.init_list)-1)
2098
2099 def isEffect(self, id):
2100 # if it's type 1, then it's an effect
2101 try:
2102 if (self.isD20() or self.isRQ()) and v.init_list[id]["type"] == 1:
2103 return 1
2104 else:
2105 return 0
2106 except:
2107 return 0
2108
2109 def getRoundsLeftInEffect(self, id):
2110 rounds_left = v.init_list[id]["duration"]
2111 return rounds_left
2112
2113 def isMovement(self, id): # sr4 only, used to spam movement-only characters
2114 try: # in passes where they receive no actions
2115 passes = v.init_list[id]["passes"]
2116 if self.ip_order == 0: # Normal 1/2/3/4 --- VEG 2.2.7
2117 if passes < self.init_pass:
2118 return 1
2119 else:
2120 return 0
2121 elif self.ip_order == 1: # Serbitar's 3/1/4/2 --- VEG 2.2.7
2122 if (self.init_pass == 1) and (passes < 3):
2123 return 1
2124 elif (self.init_pass == 2) and (passes < 1):
2125 return 1
2126 elif (self.init_pass == 3) and (passes < 4):
2127 return 1
2128 elif (self.init_pass == 4) and (passes < 2):
2129 return 1
2130 else:
2131 return 0
2132 elif self.ip_order == 2: # TinkerGnome's 4/1/3/2 --- VEG 2.2.7
2133 if (self.init_pass == 1) and (passes < 4):
2134 return 1
2135 elif (self.init_pass == 2) and (passes < 1):
2136 return 1
2137 elif (self.init_pass == 3) and (passes < 3):
2138 return 1
2139 elif (self.init_pass == 4) and (passes < 2):
2140 return 1
2141 else:
2142 return 0
2143 except:
2144 return 0
2145
2146 def sharesInit(self,id):
2147 try:
2148 if v.init_list[id]["init"] == v.init_list[self.init_listslot]["init"]:
2149 return 1
2150 else:
2151 return 0
2152 except: # last init will be an error, don't start new round yet
2153 return 0
2154
2155 # get the id of the next (non effect) non-hidden character after the given id
2156 # return -1 : no character is next
2157 def getNext(self, id):
2158 lst_size = len(v.init_list)
2159
2160 # list empty
2161 if lst_size < 2:
2162 return(-1)
2163
2164 lst = []
2165 id_found = -1
2166
2167 # if we'r at the last init, the next one is at the beginning of the list
2168 if self.isLast(id):
2169 for m in v.init_list:
2170 id_m = v.init_list.index(m)
2171 if self.isHidden(id_m) or self.isEffect(id_m):
2172 pass
2173 else:
2174 id_found = id_m
2175 break;
2176 else:
2177 try:
2178 for id_m in range(id+1, self.getLast()+1):
2179 if self.isHidden(id_m) or self.isEffect(id_m):
2180 pass
2181 else:
2182 id_found = id_m
2183 break;
2184
2185 except Exception, e:
2186 return(-1)
2187
2188 # maybe we haven't found yet, must search at the beginning of the list
2189 if id_found == -1 and not self.isFirst(id):
2190 for id_m in range(0, id):
2191 if self.isHidden(id_m) or self.isEffect(id_m):
2192 pass
2193 else:
2194 id_found = id_m
2195 break;
2196
2197 if id_found != id:
2198 return(id_found)
2199 else:
2200 return(-1)
2201
2202 def isHidden(self, id):
2203 try:
2204 if v.init_list[id]["hidden"] == 1:
2205 return(1)
2206 else:
2207 return(0)
2208
2209 except:
2210 return(0)
2211
2212 def isFirst(self, id):
2213 if id == 0:
2214 return 1
2215 else:
2216 return 0
2217
2218 def isLast(self, id):
2219 if id == (len(v.init_list)-1):
2220 return 1
2221 else:
2222 return 0
2223
2224 def get_next_rank(self, init):
2225 # when adding/changing an object, this function is used to get a unique rank of this init count
2226 # new object are added at the end of an init count, so we need a 'rank' lower than the
2227 # other object of the same init count.
2228 rank = 0;
2229 for m in v.init_list:
2230 if m["init"] == init:
2231 x = m["rank"] - 1
2232 if rank > x:
2233 rank = x
2234 return rank
2235
2236 def get_unique_tag(self, name):
2237 m = hashlib.new()
2238 m.update(str(random.random()) + str(name))
2239 return m.hexdigest()
2240
2241 ### VEG 2.2.6
2242 ### Init GUI stuff below
2243
2244 def CMD_initgui(self, cmdargs):
2245 self.frame = InitToolFrame(NULL, -1, "Initiative Tool GUI")
2246 self.frame.Show(true)
2247
2248 class InitToolFrame(wx.Frame):
2249 def __init__(self, parent, ID, title):
2250 wx.Frame.__init__(self, parent, ID, title, size=(400, 300))
2251
2252 self.panel = wx.Panel(self,-1) #, style=wx.SUNKEN_BORDER)
2253
2254 #self.panel.SetBackgroundColour("RED")
2255
2256 self.x_id = 5
2257 self.x_name = 25
2258 self.x_init = 200
2259 self.x_change = 225
2260 self.x_delete = 275
2261 self.y = 0
2262 b = 0
2263
2264 wx.StaticText ( self.panel, -1, "ID", (self.x_id, self.y) )
2265 wx.StaticText ( self.panel, -1, "Name", (self.x_name, self.y) )
2266 wx.StaticText ( self.panel, -1, "Init#", (self.x_init, self.y) )
2267 self.y+=20
2268
2269 var_ID=0
2270 var_Name=0
2271 var_Init=0
2272
2273 for m in v.init_list:
2274 var_ID = str(v.init_list.index(m)+1) + ")"
2275 var_Name = self.strip_html(m["name"])
2276 var_Init = str(m["init"])
2277
2278 wx.StaticText ( self.panel, -1, var_ID, (self.x_id, self.y) )
2279 wx.StaticText ( self.panel, -1, var_Name, (self.x_name, self.y) )
2280 wx.TextCtrl ( self.panel, -1, var_Init, (self.x_init, self.y), (20,20), wx.TE_READONLY)
2281 wx.Button(self.panel, -1, "Change", (self.x_change, self.y), (50,20) )
2282 wx.Button(self.panel, -1, "Delete", (self.x_delete, self.y), (50,20) )
2283 self.y+=20
2284
2285 #for i in range(0,4):
2286 # if i == 0:
2287 # var_ID = str(0)
2288 # var_Name = "Hignar"
2289 # var_Init = str(14)
2290 # elif i == 1:
2291 # var_ID = str(1)
2292 # var_Name = "Aiur"
2293 # var_Init = str(12)
2294 # elif i == 2:
2295 # var_ID = str(2)
2296 # var_Name = "Effect: Tlasco's Bless"
2297 # var_Init = str(4)
2298 # elif i == 3:
2299 # var_ID = str(3)
2300 # var_Name = "Tlasco"
2301 # var_Init = str(3)
2302 # wxStaticText ( self.panel, -1, var_ID, (self.x_id, self.y) )
2303 # wxStaticText ( self.panel, -1, var_Name, (self.x_name, self.y) )
2304 # wxStaticText ( self.panel, -1, var_Init, (self.x_init, self.y) )
2305 # wxButton(self.panel, -1, "Change", (self.x_change, self.y), (50,20) )
2306 # wxButton(self.panel, -1, "Delete", (self.x_delete, self.y), (50,20) )
2307 # self.y+=20
2308
2309 def strip_html(self, text):
2310 finished = 0
2311 while not finished:
2312 finished = 1
2313 # check if there is an open tag left
2314 start = text.find("<")
2315 if start >= 0:
2316 # if there is, check if the tag gets closed
2317 stop = text[start:].find(">")
2318 if stop >= 0:
2319 # if it does, strip it, and continue loop
2320 text = text[:start] + text[start+stop+1:]
2321 finished = 0
2322 return text