pywargame 0.3.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pywargame/__init__.py +2 -0
- pywargame/common/__init__.py +3 -0
- pywargame/common/collector.py +87 -0
- pywargame/common/dicedraw.py +363 -0
- pywargame/common/drawdice.py +40 -0
- pywargame/common/singleton.py +22 -0
- pywargame/common/test.py +25 -0
- pywargame/common/verbose.py +59 -0
- pywargame/common/verboseguard.py +53 -0
- pywargame/cyberboard/__init__.py +18 -0
- pywargame/cyberboard/archive.py +283 -0
- pywargame/cyberboard/base.py +63 -0
- pywargame/cyberboard/board.py +462 -0
- pywargame/cyberboard/cell.py +200 -0
- pywargame/cyberboard/collect.py +49 -0
- pywargame/cyberboard/collectgbx0pwd.py +30 -0
- pywargame/cyberboard/collectgbxext.py +30 -0
- pywargame/cyberboard/collectgsnexp.py +32 -0
- pywargame/cyberboard/collectgsnext.py +30 -0
- pywargame/cyberboard/draw.py +396 -0
- pywargame/cyberboard/exporter.py +1132 -0
- pywargame/cyberboard/extractor.py +240 -0
- pywargame/cyberboard/features.py +17 -0
- pywargame/cyberboard/gamebox.py +81 -0
- pywargame/cyberboard/gbxexp.py +76 -0
- pywargame/cyberboard/gbxext.py +64 -0
- pywargame/cyberboard/gsnexp.py +147 -0
- pywargame/cyberboard/gsnext.py +59 -0
- pywargame/cyberboard/head.py +111 -0
- pywargame/cyberboard/image.py +76 -0
- pywargame/cyberboard/main.py +47 -0
- pywargame/cyberboard/mark.py +102 -0
- pywargame/cyberboard/palette.py +36 -0
- pywargame/cyberboard/piece.py +169 -0
- pywargame/cyberboard/player.py +36 -0
- pywargame/cyberboard/scenario.py +115 -0
- pywargame/cyberboard/testgrid.py +156 -0
- pywargame/cyberboard/tile.py +121 -0
- pywargame/cyberboard/tray.py +68 -0
- pywargame/cyberboard/windows.py +41 -0
- pywargame/cyberboard/zeropwd.py +45 -0
- pywargame/cyberboard.py +2728 -0
- pywargame/gbx0pwd.py +2776 -0
- pywargame/gbxextract.py +2795 -0
- pywargame/gsnexport.py +16499 -0
- pywargame/gsnextract.py +2790 -0
- pywargame/latex/__init__.py +2 -0
- pywargame/latex/collect.py +34 -0
- pywargame/latex/latexexporter.py +4010 -0
- pywargame/latex/main.py +184 -0
- pywargame/vassal/__init__.py +66 -0
- pywargame/vassal/base.py +139 -0
- pywargame/vassal/board.py +243 -0
- pywargame/vassal/buildfile.py +60 -0
- pywargame/vassal/chart.py +79 -0
- pywargame/vassal/chessclock.py +197 -0
- pywargame/vassal/collect.py +98 -0
- pywargame/vassal/collectpatch.py +28 -0
- pywargame/vassal/command.py +21 -0
- pywargame/vassal/documentation.py +322 -0
- pywargame/vassal/dumpcollect.py +28 -0
- pywargame/vassal/dumpvsav.py +28 -0
- pywargame/vassal/element.py +439 -0
- pywargame/vassal/exporter.py +89 -0
- pywargame/vassal/extension.py +101 -0
- pywargame/vassal/folder.py +103 -0
- pywargame/vassal/game.py +940 -0
- pywargame/vassal/gameelements.py +1091 -0
- pywargame/vassal/globalkey.py +127 -0
- pywargame/vassal/globalproperty.py +433 -0
- pywargame/vassal/grid.py +573 -0
- pywargame/vassal/map.py +1061 -0
- pywargame/vassal/mapelements.py +1020 -0
- pywargame/vassal/merge.py +57 -0
- pywargame/vassal/merger.py +460 -0
- pywargame/vassal/moduledata.py +275 -0
- pywargame/vassal/mrgcollect.py +31 -0
- pywargame/vassal/patch.py +44 -0
- pywargame/vassal/patchcollect.py +28 -0
- pywargame/vassal/player.py +83 -0
- pywargame/vassal/save.py +495 -0
- pywargame/vassal/skel.py +380 -0
- pywargame/vassal/trait.py +224 -0
- pywargame/vassal/traits/__init__.py +36 -0
- pywargame/vassal/traits/area.py +50 -0
- pywargame/vassal/traits/basic.py +35 -0
- pywargame/vassal/traits/calculatedproperty.py +22 -0
- pywargame/vassal/traits/cargo.py +29 -0
- pywargame/vassal/traits/click.py +41 -0
- pywargame/vassal/traits/clone.py +28 -0
- pywargame/vassal/traits/delete.py +24 -0
- pywargame/vassal/traits/deselect.py +32 -0
- pywargame/vassal/traits/dynamicproperty.py +112 -0
- pywargame/vassal/traits/globalcommand.py +55 -0
- pywargame/vassal/traits/globalhotkey.py +26 -0
- pywargame/vassal/traits/globalproperty.py +54 -0
- pywargame/vassal/traits/hide.py +67 -0
- pywargame/vassal/traits/label.py +76 -0
- pywargame/vassal/traits/layer.py +105 -0
- pywargame/vassal/traits/mark.py +20 -0
- pywargame/vassal/traits/mask.py +85 -0
- pywargame/vassal/traits/mat.py +26 -0
- pywargame/vassal/traits/moved.py +35 -0
- pywargame/vassal/traits/movefixed.py +51 -0
- pywargame/vassal/traits/nonrect.py +95 -0
- pywargame/vassal/traits/nostack.py +55 -0
- pywargame/vassal/traits/place.py +104 -0
- pywargame/vassal/traits/prototype.py +20 -0
- pywargame/vassal/traits/report.py +34 -0
- pywargame/vassal/traits/restrictaccess.py +28 -0
- pywargame/vassal/traits/restrictcommand.py +32 -0
- pywargame/vassal/traits/return.py +40 -0
- pywargame/vassal/traits/rotate.py +62 -0
- pywargame/vassal/traits/sendto.py +59 -0
- pywargame/vassal/traits/sheet.py +129 -0
- pywargame/vassal/traits/skel.py +9 -0
- pywargame/vassal/traits/stack.py +28 -0
- pywargame/vassal/traits/submenu.py +27 -0
- pywargame/vassal/traits/trail.py +61 -0
- pywargame/vassal/traits/trigger.py +72 -0
- pywargame/vassal/turn.py +272 -0
- pywargame/vassal/upgrade.py +191 -0
- pywargame/vassal/vmod.py +323 -0
- pywargame/vassal/vsav.py +100 -0
- pywargame/vassal/widget.py +358 -0
- pywargame/vassal/withtraits.py +634 -0
- pywargame/vassal/xml.py +4 -0
- pywargame/vassal/zone.py +399 -0
- pywargame/vassal.py +12500 -0
- pywargame/vmodpatch.py +12548 -0
- pywargame/vsavdump.py +12533 -0
- pywargame/vslmerge.py +13015 -0
- pywargame/wgexport.py +16689 -0
- pywargame/ztexport.py +14351 -0
- pywargame/zuntzu/__init__.py +5 -0
- pywargame/zuntzu/base.py +82 -0
- pywargame/zuntzu/collect.py +38 -0
- pywargame/zuntzu/countersheet.py +250 -0
- pywargame/zuntzu/dicehand.py +48 -0
- pywargame/zuntzu/exporter.py +936 -0
- pywargame/zuntzu/gamebox.py +154 -0
- pywargame/zuntzu/map.py +36 -0
- pywargame/zuntzu/piece.py +37 -0
- pywargame/zuntzu/scenario.py +208 -0
- pywargame/zuntzu/ztexp.py +115 -0
- pywargame-0.3.1.dist-info/METADATA +353 -0
- pywargame-0.3.1.dist-info/RECORD +150 -0
- pywargame-0.3.1.dist-info/WHEEL +5 -0
- pywargame-0.3.1.dist-info/licenses/LICENSE +5 -0
- pywargame-0.3.1.dist-info/top_level.txt +1 -0
pywargame/vassal/skel.py
ADDED
@@ -0,0 +1,380 @@
|
|
1
|
+
## BEGIN_IMPORT
|
2
|
+
from common import VerboseGuard
|
3
|
+
from . base import *
|
4
|
+
from . element import Element
|
5
|
+
## END_IMPORT
|
6
|
+
|
7
|
+
# --------------------------------------------------------------------
|
8
|
+
class GameElement(Element):
|
9
|
+
def __init__(self,game,tag,node=None,**kwargs):
|
10
|
+
super(GameElement,self).__init__(game,tag,node=node,**kwargs)
|
11
|
+
|
12
|
+
def getGame(self):
|
13
|
+
return self.getParent(Game)
|
14
|
+
|
15
|
+
|
16
|
+
# --------------------------------------------------------------------
|
17
|
+
class Notes(GameElement):
|
18
|
+
TAG = Element.MODULE+'NotesWindow'
|
19
|
+
def __init__(self,elem,node=None,
|
20
|
+
name = 'Notes',
|
21
|
+
buttonText = '',
|
22
|
+
hotkey = key('N',ALT),
|
23
|
+
icon = '/images/notes.gif',
|
24
|
+
tooltip = 'Show notes window'):
|
25
|
+
super(Notes,self).__init__(elem,self.TAG,node=node,
|
26
|
+
name = name,
|
27
|
+
buttonText = buttonText,
|
28
|
+
hotkey = hotkey,
|
29
|
+
icon = icon,
|
30
|
+
tooltip = tooltip)
|
31
|
+
def encode(self):
|
32
|
+
return ['NOTES\t\\','PNOTES']
|
33
|
+
|
34
|
+
registerElement(Notes)
|
35
|
+
|
36
|
+
# --------------------------------------------------------------------
|
37
|
+
class PredefinedSetup(GameElement):
|
38
|
+
TAG = Element.MODULE+'PredefinedSetup'
|
39
|
+
def __init__(self,elem,node=None,
|
40
|
+
name = '',
|
41
|
+
file = '',
|
42
|
+
useFile = False,
|
43
|
+
isMenu = False,
|
44
|
+
description = ''):
|
45
|
+
useFile = ((useFile or not isMenu) and
|
46
|
+
(file is not None and len(file) > 0))
|
47
|
+
if file is None: file = ''
|
48
|
+
super(PredefinedSetup,self).__init__(elem,self.TAG,node=node,
|
49
|
+
name = name,
|
50
|
+
file = file,
|
51
|
+
useFile = useFile,
|
52
|
+
isMenu = isMenu,
|
53
|
+
description = description)
|
54
|
+
def addPredefinedSetup(self,**kwargs):
|
55
|
+
'''Add a `PredefinedSetup` element to this
|
56
|
+
|
57
|
+
Parameters
|
58
|
+
----------
|
59
|
+
kwargs : dict
|
60
|
+
Dictionary of attribute key-value pairs
|
61
|
+
Returns
|
62
|
+
-------
|
63
|
+
element : PredefinedSetup
|
64
|
+
The added element
|
65
|
+
'''
|
66
|
+
return self.add(PredefinedSetup,**kwargs)
|
67
|
+
def getPredefinedSetups(self,asdict=True):
|
68
|
+
'''Get all PredefinedSetup element(s) from this
|
69
|
+
|
70
|
+
Parameters
|
71
|
+
----------
|
72
|
+
asdict : bool
|
73
|
+
If `True`, return a dictonary that maps key to `PredefinedSetup` elements. If `False`, return a list of all PredefinedSetup` children.
|
74
|
+
Returns
|
75
|
+
-------
|
76
|
+
children : dict or list
|
77
|
+
Dictionary or list of `PredefinedSetup` children
|
78
|
+
'''
|
79
|
+
return self.getElementsByKey(PredefinedSetup,'name',asdict)
|
80
|
+
|
81
|
+
|
82
|
+
|
83
|
+
|
84
|
+
registerElement(PredefinedSetup)
|
85
|
+
|
86
|
+
# --------------------------------------------------------------------
|
87
|
+
class GlobalTranslatableMessages(GameElement):
|
88
|
+
TAG=Element.MODULE+'properties.GlobalTranslatableMessages'
|
89
|
+
def __init__(self,elem,node=None):
|
90
|
+
'''Translations
|
91
|
+
|
92
|
+
Parameters
|
93
|
+
----------
|
94
|
+
doc : Element
|
95
|
+
Parent
|
96
|
+
node : xml.dom.Element
|
97
|
+
Node to read state from
|
98
|
+
'''
|
99
|
+
super(GlobalTranslatableMessages,self).\
|
100
|
+
__init__(elem,self.TAG,node=node)
|
101
|
+
|
102
|
+
registerElement(GlobalTranslatableMessages)
|
103
|
+
|
104
|
+
# --------------------------------------------------------------------
|
105
|
+
class Language(GameElement):
|
106
|
+
TAG = 'VASSAL.i18n.Language'
|
107
|
+
def __init__(self,elem,node=None,**kwargs):
|
108
|
+
super(Languate,self).__init__(sele,self.TAG,node=none,**kwargs)
|
109
|
+
|
110
|
+
registerElement(Language)
|
111
|
+
|
112
|
+
# --------------------------------------------------------------------
|
113
|
+
class Chatter(GameElement):
|
114
|
+
TAG=Element.MODULE+'Chatter'
|
115
|
+
def __init__(self,elem,node=None,**kwargs):
|
116
|
+
'''Chat
|
117
|
+
|
118
|
+
Parameters
|
119
|
+
----------
|
120
|
+
doc : Element
|
121
|
+
Parent
|
122
|
+
node : xml.dom.Element
|
123
|
+
Node to read state from
|
124
|
+
kwargs : dict
|
125
|
+
Attributes
|
126
|
+
'''
|
127
|
+
super(Chatter,self).__init__(elem,self.TAG,node=node,**kwargs)
|
128
|
+
|
129
|
+
registerElement(Chatter)
|
130
|
+
|
131
|
+
# --------------------------------------------------------------------
|
132
|
+
class KeyNamer(GameElement):
|
133
|
+
TAG=Element.MODULE+'KeyNamer'
|
134
|
+
def __init__(self,elem,node=None,**kwargs):
|
135
|
+
'''Key namer (or help menu)
|
136
|
+
|
137
|
+
Parameters
|
138
|
+
----------
|
139
|
+
doc : Element
|
140
|
+
Parent
|
141
|
+
node : xml.dom.Element
|
142
|
+
Node to read state from
|
143
|
+
kwargs : dict
|
144
|
+
Attributes
|
145
|
+
'''
|
146
|
+
super(KeyNamer,self).__init__(elem,self.TAG,node=node,**kwargs)
|
147
|
+
|
148
|
+
registerElement(KeyNamer)
|
149
|
+
|
150
|
+
# --------------------------------------------------------------------
|
151
|
+
class GlobalOptions(GameElement):
|
152
|
+
TAG = Element.MODULE+'GlobalOptions'
|
153
|
+
def __init__(self,doc,node=None,
|
154
|
+
autoReport = "Use Preferences Setting",
|
155
|
+
centerOnMove = "Use Preferences Setting",
|
156
|
+
chatterHTMLSupport = "Always",
|
157
|
+
hotKeysOnClosedWindows = "Never",
|
158
|
+
inventoryForAll = "Always",
|
159
|
+
nonOwnerUnmaskable = "Use Preferences Setting",
|
160
|
+
playerIdFormat = "$playerName$",
|
161
|
+
promptString = "Opponents can unmask pieces",
|
162
|
+
sendToLocationMoveTrails = "Never"):
|
163
|
+
'''Set global options on the module
|
164
|
+
|
165
|
+
Parameters
|
166
|
+
----------
|
167
|
+
doc : Element
|
168
|
+
Parent
|
169
|
+
node : xml.dom.Element
|
170
|
+
Node to read state from
|
171
|
+
autoReport : str Option
|
172
|
+
centerOnMove : str Option
|
173
|
+
chatterHTMLSupport : str Option
|
174
|
+
hotKeysOnClosedWindows : str Option
|
175
|
+
inventoryForAll : str Option
|
176
|
+
nonOwnerUnmaskable : str Option
|
177
|
+
playerIdFormat : str Option
|
178
|
+
promptString : str Option
|
179
|
+
sendToLocationMoveTrails : str Option
|
180
|
+
'''
|
181
|
+
super(GlobalOptions,self).\
|
182
|
+
__init__(doc,self.TAG,node=node,
|
183
|
+
autoReport = autoReport,
|
184
|
+
centerOnMove = centerOnMove,
|
185
|
+
chatterHTMLSupport = chatterHTMLSupport,
|
186
|
+
hotKeysOnClosedWindows = hotKeysOnClosedWindows,
|
187
|
+
inventoryForAll = inventoryForAll,
|
188
|
+
nonOwnerUnmaskable = nonOwnerUnmaskable,
|
189
|
+
playerIdFormat = playerIdFormat,
|
190
|
+
promptString = promptString,
|
191
|
+
sendToLocationMoveTrails = sendToLocationMoveTrails)
|
192
|
+
|
193
|
+
def addOption(self,**kwargs):
|
194
|
+
'''Add a `Option` element to this
|
195
|
+
|
196
|
+
Parameters
|
197
|
+
----------
|
198
|
+
kwargs : dict
|
199
|
+
Dictionary of attribute key-value pairs
|
200
|
+
Returns
|
201
|
+
-------
|
202
|
+
element : Option
|
203
|
+
The added element
|
204
|
+
'''
|
205
|
+
return self.add(Option,**kwargs)
|
206
|
+
def getOptions(self):
|
207
|
+
return self.getElementsByKey(Option,'name')
|
208
|
+
|
209
|
+
registerElement(GlobalOptions)
|
210
|
+
|
211
|
+
|
212
|
+
# --------------------------------------------------------------------
|
213
|
+
class Option(Element):
|
214
|
+
TAG = 'option'
|
215
|
+
def __init__(self,doc,node=None,name='',value=''):
|
216
|
+
super(Option,self).__init__(doc,node=node,name=name)
|
217
|
+
self._root.addText(self._node,value)
|
218
|
+
|
219
|
+
def getGlobalOptions(self):
|
220
|
+
return self.getParent(GlobalOptions)
|
221
|
+
|
222
|
+
registerElement(Option)
|
223
|
+
|
224
|
+
# --------------------------------------------------------------------
|
225
|
+
# CurrentMap == "Board"
|
226
|
+
class Inventory(GameElement):
|
227
|
+
TAG = Element.MODULE+'Inventory'
|
228
|
+
def __init__(self,doc,node=None,
|
229
|
+
canDisable = False,
|
230
|
+
centerOnPiece = True,
|
231
|
+
disabledIcon = '',
|
232
|
+
drawPieces = True,
|
233
|
+
foldersOnly = False,
|
234
|
+
forwardKeystroke = True,
|
235
|
+
groupBy = '',
|
236
|
+
hotkey = key('I',ALT),
|
237
|
+
icon = '/images/inventory.gif',
|
238
|
+
include = '{}',
|
239
|
+
launchFunction = 'functionHide',
|
240
|
+
leafFormat = '$PieceName$',
|
241
|
+
name = '',
|
242
|
+
nonLeafFormat = '$PropertyValue$',
|
243
|
+
pieceZoom = '0.33',
|
244
|
+
pieceZoom2 = '0.5',
|
245
|
+
pieceZoom3 = '0.6',
|
246
|
+
propertyGate = '',
|
247
|
+
refreshHotkey = key('I',ALT_SHIFT),
|
248
|
+
showMenu = True,
|
249
|
+
sides = '',
|
250
|
+
sortFormat = '$PieceName$',
|
251
|
+
sortPieces = True,
|
252
|
+
sorting = 'alpha',
|
253
|
+
text = '',
|
254
|
+
tooltip = 'Show inventory of all pieces',
|
255
|
+
zoomOn = False):
|
256
|
+
super(Inventory,self).__init__(doc,self.TAG,node=node,
|
257
|
+
canDisable = canDisable,
|
258
|
+
centerOnPiece = centerOnPiece,
|
259
|
+
disabledIcon = disabledIcon,
|
260
|
+
drawPieces = drawPieces,
|
261
|
+
foldersOnly = foldersOnly,
|
262
|
+
forwardKeystroke = forwardKeystroke,
|
263
|
+
groupBy = groupBy,
|
264
|
+
hotkey = hotkey,
|
265
|
+
icon = icon,
|
266
|
+
include = include,
|
267
|
+
launchFunction = launchFunction,
|
268
|
+
leafFormat = leafFormat,
|
269
|
+
name = name,
|
270
|
+
nonLeafFormat = nonLeafFormat,
|
271
|
+
pieceZoom = pieceZoom,
|
272
|
+
pieceZoom2 = pieceZoom2,
|
273
|
+
pieceZoom3 = pieceZoom3,
|
274
|
+
propertyGate = propertyGate,
|
275
|
+
refreshHotkey = refreshHotkey,
|
276
|
+
showMenu = showMenu,
|
277
|
+
sides = sides,
|
278
|
+
sortFormat = sortFormat,
|
279
|
+
sortPieces = sortPieces,
|
280
|
+
sorting = sorting,
|
281
|
+
text = text,
|
282
|
+
tooltip = tooltip,
|
283
|
+
zoomOn = zoomOn)
|
284
|
+
|
285
|
+
registerElement(Inventory)
|
286
|
+
|
287
|
+
# --------------------------------------------------------------------
|
288
|
+
class Prototypes(GameElement):
|
289
|
+
TAG = Element.MODULE+'PrototypesContainer'
|
290
|
+
def __init__(self,game,node=None,**kwargs):
|
291
|
+
super(Prototypes,self).\
|
292
|
+
__init__(game,self.TAG,node=node,**kwargs)
|
293
|
+
|
294
|
+
def addPrototype(self,**kwargs):
|
295
|
+
'''Add a `Prototype` element to this
|
296
|
+
|
297
|
+
Parameters
|
298
|
+
----------
|
299
|
+
kwargs : dict
|
300
|
+
Dictionary of attribute key-value pairs
|
301
|
+
Returns
|
302
|
+
-------
|
303
|
+
element : Prototype
|
304
|
+
The added element
|
305
|
+
'''
|
306
|
+
return self.add(Prototype,**kwargs)
|
307
|
+
def getPrototypes(self,asdict=True):
|
308
|
+
'''Get all Prototype element(s) from this
|
309
|
+
|
310
|
+
Parameters
|
311
|
+
----------
|
312
|
+
asdict : bool
|
313
|
+
If `True`, return a dictonary that maps key to `Prototype` elements. If `False`, return a list of all Prototype` children.
|
314
|
+
Returns
|
315
|
+
-------
|
316
|
+
children : dict or list
|
317
|
+
Dictionary or list of `Prototype` children
|
318
|
+
'''
|
319
|
+
return self.getElementsByKey(Prototype,'name',asdict=asdict)
|
320
|
+
|
321
|
+
|
322
|
+
|
323
|
+
registerElement(Prototypes)
|
324
|
+
|
325
|
+
# --------------------------------------------------------------------
|
326
|
+
class DiceButton(GameElement):
|
327
|
+
TAG=Element.MODULE+'DiceButton'
|
328
|
+
def __init__(self,elem,node=None,
|
329
|
+
addToTotal = 0,
|
330
|
+
canDisable = False,
|
331
|
+
hotkey = key('6',ALT),
|
332
|
+
icon = '/images/die.gif',
|
333
|
+
keepCount = 1,
|
334
|
+
keepDice = False,
|
335
|
+
keepOption = '>',
|
336
|
+
lockAdd = False,
|
337
|
+
lockDice = False,
|
338
|
+
lockPlus = False,
|
339
|
+
lockSides = False,
|
340
|
+
nDice = 1,
|
341
|
+
nSides = 6,
|
342
|
+
name = '1d6',
|
343
|
+
plus = 0,
|
344
|
+
prompt = False,
|
345
|
+
propertyGate = '',
|
346
|
+
reportFormat = '** $name$ = $result$ *** <$PlayerName$>;',
|
347
|
+
reportTotal = False,
|
348
|
+
sortDice = False,
|
349
|
+
text = '1d6',
|
350
|
+
tooltip = 'Roll a 1d6'):
|
351
|
+
super(DiceButton,self).\
|
352
|
+
__init__(elem,self.TAG,node=node,
|
353
|
+
addToTotal = addToTotal,
|
354
|
+
canDisable = canDisable,
|
355
|
+
hotkey = hotkey,
|
356
|
+
icon = icon,
|
357
|
+
keepCount = keepCount,
|
358
|
+
keepDice = keepDice,
|
359
|
+
keepOption = keepOption,
|
360
|
+
lockAdd = lockAdd,
|
361
|
+
lockDice = lockDice,
|
362
|
+
lockPlus = lockPlus,
|
363
|
+
lockSides = lockSides,
|
364
|
+
nDice = nDice,
|
365
|
+
nSides = nSides,
|
366
|
+
name = name,
|
367
|
+
plus = plus,
|
368
|
+
prompt = prompt,
|
369
|
+
propertyGate = propertyGate,
|
370
|
+
reportFormat = reportFormat,
|
371
|
+
reportTotal = reportTotal,
|
372
|
+
sortDice = sortDice,
|
373
|
+
text = text,
|
374
|
+
tooltip = tooltip)
|
375
|
+
|
376
|
+
registerElement(DiceButton)
|
377
|
+
|
378
|
+
#
|
379
|
+
# EOF
|
380
|
+
#
|
@@ -0,0 +1,224 @@
|
|
1
|
+
# ====================================================================
|
2
|
+
class Trait:
|
3
|
+
known_traits = []
|
4
|
+
def __init__(self):
|
5
|
+
'''Base class for trait capture.
|
6
|
+
|
7
|
+
Unlike the Element classes, this actually holds state that
|
8
|
+
isn't reflected elsewhere in the DOM. This means that the
|
9
|
+
data here is local to the object. So when we do
|
10
|
+
|
11
|
+
piece = foo.getPieceSlots()[0]
|
12
|
+
traits = p.getTraits()
|
13
|
+
for trait in traits:
|
14
|
+
if trait.ID == 'piece':
|
15
|
+
trait["gpid"] = newPid
|
16
|
+
trait["lpid"] = newPid
|
17
|
+
|
18
|
+
we do not actually change anything in the DOM. To do that, we
|
19
|
+
must add back _all_ the traits as
|
20
|
+
|
21
|
+
piece.setTraits(traits)
|
22
|
+
|
23
|
+
We can add traits to a piece, like
|
24
|
+
|
25
|
+
piece.addTrait(MarkTrait('Hello','World'))
|
26
|
+
|
27
|
+
But it is not particularly efficient. Better to do
|
28
|
+
(continuing from above)
|
29
|
+
|
30
|
+
traits.append(MarkTrait('Hello','World;)
|
31
|
+
piece.setTraits(traits)
|
32
|
+
|
33
|
+
.. include:: ../../vassal/traits/README.md
|
34
|
+
:parser: myst_parser.sphinx_
|
35
|
+
|
36
|
+
'''
|
37
|
+
self._type = None
|
38
|
+
self._state = None
|
39
|
+
|
40
|
+
def setType(self,**kwargs):
|
41
|
+
'''Set types. Dictionary of names and values. Dictonary keys
|
42
|
+
defines how we access the fields, which is internal here.
|
43
|
+
What matters is the order of the values.
|
44
|
+
|
45
|
+
'''
|
46
|
+
self._type = list(kwargs.values())
|
47
|
+
self._tnames = list(kwargs.keys())
|
48
|
+
|
49
|
+
def setState(self,**kwargs):
|
50
|
+
'''Set states. Dictionary of names and values. Dictonary keys
|
51
|
+
defines how we access the fields, which is internal here.
|
52
|
+
What matters is the order of the values.
|
53
|
+
'''
|
54
|
+
self._state = list(kwargs.values())
|
55
|
+
self._snames = list(kwargs.keys())
|
56
|
+
|
57
|
+
def __getitem__(self,key):
|
58
|
+
'''Look up item in either type or state'''
|
59
|
+
try:
|
60
|
+
return self._type[self._tnames.index(key)]
|
61
|
+
except:
|
62
|
+
pass
|
63
|
+
return self._state[self._snames.index(key)]
|
64
|
+
|
65
|
+
def __setitem__(self,key,value):
|
66
|
+
'''Set item in either type or state'''
|
67
|
+
try:
|
68
|
+
self._type[self._tnames.index(key)] = value
|
69
|
+
return
|
70
|
+
except:
|
71
|
+
pass
|
72
|
+
self._state[self._snames.index(key)] = value
|
73
|
+
|
74
|
+
def encode(self,term=False):
|
75
|
+
'''
|
76
|
+
returns type and state encoded'''
|
77
|
+
t = self.encodeFields(self.ID,*self._type,term=term)
|
78
|
+
s = self.encodeFields(*self._state,term=term)
|
79
|
+
return t,s
|
80
|
+
|
81
|
+
@classmethod
|
82
|
+
def findTrait(cls,traits,ID,key=None,value=None,verbose=False):
|
83
|
+
for trait in traits:
|
84
|
+
if trait.ID != ID:
|
85
|
+
continue
|
86
|
+
if verbose:
|
87
|
+
print(f' {trait.ID}')
|
88
|
+
if key is None or value is None:
|
89
|
+
if verbose:
|
90
|
+
print(f' Return {trait.ID}')
|
91
|
+
return trait
|
92
|
+
if verbose:
|
93
|
+
print(f' Check {key}={value}: {trait[key]}')
|
94
|
+
if trait[key] == value:
|
95
|
+
return trait
|
96
|
+
if verbose:
|
97
|
+
print(f' Trait of type {ID} with {key}={value} not found')
|
98
|
+
return None
|
99
|
+
|
100
|
+
@classmethod
|
101
|
+
def take(cls,iden,t,s):
|
102
|
+
'''If the first part of the string t matches the ID, then take it.
|
103
|
+
|
104
|
+
t and s are lists of strings.
|
105
|
+
'''
|
106
|
+
if iden != cls.ID: return None
|
107
|
+
|
108
|
+
ret = cls()
|
109
|
+
ret._type = t
|
110
|
+
ret._state = s
|
111
|
+
ret.check() # Check if we're reasonable, or raise
|
112
|
+
#print(f'Took {iden} {cls}\n'
|
113
|
+
# f' {ret._tnames}\n'
|
114
|
+
# f' {ret._snames}')
|
115
|
+
return ret
|
116
|
+
|
117
|
+
def check(self):
|
118
|
+
'''Implement if trait should check that all is OK when cloning'''
|
119
|
+
pass
|
120
|
+
|
121
|
+
@classmethod
|
122
|
+
def encodeFields(cls,*args,term=False):
|
123
|
+
return ';'.join([str(e).lower() if isinstance(e,bool) else str(e)
|
124
|
+
for e in args])+(';' if term else '')
|
125
|
+
|
126
|
+
@classmethod
|
127
|
+
def decodeFields(cls,s):
|
128
|
+
from re import split
|
129
|
+
return split(r'(?<!\\);',s)
|
130
|
+
# return s.split(';') # Probably too simple-minded
|
131
|
+
|
132
|
+
@classmethod
|
133
|
+
def encodeKeys(cls,keys,sep=','):
|
134
|
+
return sep.join([k.replace(',','\\'+f'{sep}') for k in keys])
|
135
|
+
|
136
|
+
@classmethod
|
137
|
+
def decodeKeys(cls,keys,sep=','):
|
138
|
+
from re import split
|
139
|
+
ks = split(r'(?<!\\)'+f'{sep}',keys)
|
140
|
+
return [k.replace('\\'+f'{sep}',f'{sep}') for k in ks]
|
141
|
+
|
142
|
+
@classmethod
|
143
|
+
def flatten(cls,traits,game=None,prototypes=None,verbose=False):
|
144
|
+
## BEGIN_IMPORT
|
145
|
+
from . traits import BasicTrait
|
146
|
+
## END_IMPORT
|
147
|
+
if prototypes is None:
|
148
|
+
if game is None:
|
149
|
+
print(f'Warning: Game or prototypes not passed')
|
150
|
+
return None
|
151
|
+
prototypes = game.getPrototypes()[0].getPrototypes()
|
152
|
+
|
153
|
+
if len(traits) < 1: return None
|
154
|
+
|
155
|
+
basic = None
|
156
|
+
if traits[-1].ID == 'piece': # BasicTrait.ID:
|
157
|
+
basic = traits.pop()
|
158
|
+
|
159
|
+
if verbose:
|
160
|
+
print(f'Piece {basic["name"]}')
|
161
|
+
|
162
|
+
ret = cls._flatten(traits,prototypes,' ',verbose)
|
163
|
+
ret.append(basic)
|
164
|
+
|
165
|
+
return ret
|
166
|
+
|
167
|
+
@classmethod
|
168
|
+
def _flatten(cls,traits,prototypes,ind,verbose):
|
169
|
+
## BEGIN_IMPORT
|
170
|
+
from . traits import BasicTrait
|
171
|
+
from . traits import PrototypeTrait
|
172
|
+
## END_IMPORT
|
173
|
+
'''Expand all prototype traits in traits'''
|
174
|
+
ret = []
|
175
|
+
for trait in traits:
|
176
|
+
# Ignore recursive basic traits
|
177
|
+
if trait.ID == BasicTrait.ID:
|
178
|
+
continue
|
179
|
+
# Add normal traits
|
180
|
+
if trait.ID != PrototypeTrait.ID:
|
181
|
+
if verbose:
|
182
|
+
print(f'{ind}Adding trait "{trait.ID}"')
|
183
|
+
|
184
|
+
ret.append(trait)
|
185
|
+
continue
|
186
|
+
|
187
|
+
# Find prototype
|
188
|
+
name = trait['name']
|
189
|
+
proto = prototypes.get(name,None)
|
190
|
+
if proto is None:
|
191
|
+
if name != ' prototype':
|
192
|
+
print(f'{ind}Warning, prototype {name} not found')
|
193
|
+
continue
|
194
|
+
|
195
|
+
if verbose:
|
196
|
+
print(f'{ind}Expanding prototype "{name}"')
|
197
|
+
|
198
|
+
# Recursive call to add prototype traits (and possibly
|
199
|
+
# more recursive calls
|
200
|
+
ret.extend(cls._flatten(proto.getTraits(), prototypes,
|
201
|
+
ind+' ',verbose))
|
202
|
+
|
203
|
+
return ret
|
204
|
+
|
205
|
+
def print(self,file=None):
|
206
|
+
if file is None:
|
207
|
+
from sys import stdout
|
208
|
+
file = stdout
|
209
|
+
|
210
|
+
nt = max([len(i) for i in self._tnames]) if self._tnames else 0
|
211
|
+
ns = max([len(i) for i in self._snames]) if self._snames else 0
|
212
|
+
nw = max(nt,ns)
|
213
|
+
|
214
|
+
print(f'Trait ID={self.ID}',file=file)
|
215
|
+
print(f' Type:', file=file)
|
216
|
+
for n,v in zip(self._tnames,self._type):
|
217
|
+
print(f' {n:<{nw}s}: {v}',file=file)
|
218
|
+
print(f' State:', file=file)
|
219
|
+
for n,v in zip(self._snames,self._state):
|
220
|
+
print(f' {n:<{nw}s}: {v}',file=file)
|
221
|
+
|
222
|
+
#
|
223
|
+
# EOF
|
224
|
+
#
|
@@ -0,0 +1,36 @@
|
|
1
|
+
#
|
2
|
+
from . area import AreaTrait
|
3
|
+
from . basic import BasicTrait
|
4
|
+
from . calculatedproperty import CalculatedTrait
|
5
|
+
from . clone import CloneTrait
|
6
|
+
from . delete import DeleteTrait
|
7
|
+
from . globalcommand import GlobalCommandTrait
|
8
|
+
from . globalhotkey import GlobalHotkeyTrait
|
9
|
+
from . dynamicproperty import *
|
10
|
+
from . nostack import *
|
11
|
+
from . deselect import *
|
12
|
+
from . globalproperty import GlobalPropertyTrait
|
13
|
+
from . label import LabelTraitCodes, LabelTrait
|
14
|
+
from . layer import LayerTrait
|
15
|
+
from . mark import MarkTrait
|
16
|
+
from . mask import MaskTrait
|
17
|
+
from . moved import MovedTrait
|
18
|
+
from . place import PlaceTrait
|
19
|
+
from . prototype import PrototypeTrait
|
20
|
+
from . report import ReportTrait
|
21
|
+
from . restrictaccess import RestrictAccessTrait
|
22
|
+
from . restrictcommand import RestrictCommandsTrait
|
23
|
+
from . rotate import RotateTrait
|
24
|
+
from . sendto import SendtoTrait
|
25
|
+
from . stack import StackTrait
|
26
|
+
from . submenu import SubMenuTrait
|
27
|
+
from . trail import TrailTrait
|
28
|
+
from . trigger import TriggerTrait
|
29
|
+
from . nonrect import NonRectangleTrait
|
30
|
+
from . click import ClickTrait
|
31
|
+
from . mat import MatTrait
|
32
|
+
from . cargo import CargoTrait
|
33
|
+
from . movefixed import MoveFixedTrait
|
34
|
+
from . sheet import SheetTrait
|
35
|
+
from . hide import HideTrait
|
36
|
+
from . return import ReturnTrait
|
@@ -0,0 +1,50 @@
|
|
1
|
+
## BEGIN_IMPORT
|
2
|
+
from common import VerboseGuard
|
3
|
+
from .. trait import Trait
|
4
|
+
from .. base import rgb, key
|
5
|
+
## END_IMPORT
|
6
|
+
|
7
|
+
class AreaTrait(Trait):
|
8
|
+
ID = 'AreaOfEffect'
|
9
|
+
def __init__(self,
|
10
|
+
transparancyColor = rgb(0x77,0x77,0x77),
|
11
|
+
transparancyLevel = 30,
|
12
|
+
radius = 1,
|
13
|
+
alwaysActive = False,
|
14
|
+
activateCommand = 'Toggle area of effect',
|
15
|
+
activateKey = key('A'), # Ctrl-A
|
16
|
+
mapShaderName = '',
|
17
|
+
fixedRadius = True,
|
18
|
+
radiusMarker = '', # Property
|
19
|
+
description = 'Show area of effect',
|
20
|
+
name = 'EffectArea',
|
21
|
+
onMenuText = '', # Show area of effect
|
22
|
+
onKey = '', # key('A')
|
23
|
+
offMenuText = '', # Hide area of effect
|
24
|
+
offKey = '', # key(A,SHIFT)
|
25
|
+
globallyVisible = True):
|
26
|
+
super(AreaTrait,self).__init__()
|
27
|
+
self.setType(
|
28
|
+
transparancyColor = transparancyColor,
|
29
|
+
transparancyLevel = int(transparancyLevel),
|
30
|
+
radius = radius,
|
31
|
+
alwaysActive = alwaysActive,
|
32
|
+
activateCommand = activateCommand,
|
33
|
+
activateKey = activateKey,
|
34
|
+
mapShaderName = mapShaderName,
|
35
|
+
fixedRadius = fixedRadius,
|
36
|
+
radiusMarker = radiusMarker,
|
37
|
+
description = description,
|
38
|
+
name = name,
|
39
|
+
onMenuText = onMenuText,
|
40
|
+
onKey = onKey,
|
41
|
+
offMenuText = offMenuText,
|
42
|
+
offKey = offKey,
|
43
|
+
globallyVisible = globallyVisible
|
44
|
+
)
|
45
|
+
self.setState(active = alwaysActive or not globallyVisible)
|
46
|
+
|
47
|
+
Trait.known_traits.append(AreaTrait)
|
48
|
+
#
|
49
|
+
# EOF
|
50
|
+
#
|