+class Offset(object):
+ """Provide an offset to a bullet's initial position."""
+
+ VALID_TYPES = ["relative", "absolute"]
+
+ def __init__(self, type, x, y):
+ if type not in self.VALID_TYPES:
+ raise ValueError("invalid type %r" % type)
+ self.type = type
+ self.x = x
+ self.y = y
+
+ def __getstate__(self):
+ state = [('type', self.type)]
+ if self.x:
+ state.append(('x', self.x.expr))
+ if self.y:
+ state.append(('y', self.y.expr))
+ return state
+
+ def __setstate__(self, state):
+ state = dict(state)
+ self.__init__(state["type"], state.get("x"), state.get("y"))
+
+ @classmethod
+ def FromXML(cls, doc, element):
+ """Construct using an ElementTree-style element."""
+ type = element.get("type", "relative")
+ x = None
+ y = None
+ for subelem in element:
+ tag = realtag(subelem)
+ if tag == "x":
+ x = NumberDef(subelem.text)
+ elif tag == "y":
+ y = NumberDef(subelem.text)
+ return cls(type, x, y)
+
+ def __call__(self, params, rank):
+ return (self.x(params, rank) if self.x else 0,
+ self.y(params, rank) if self.y else 0)
+