More methods!

main
Nicholas Hope 2022-10-05 21:32:07 -04:00
parent 607894648c
commit 9331f13786
1 changed files with 125 additions and 138 deletions

View File

@ -28,19 +28,19 @@ class Bind(object):
bindTypes = [] bindTypes = []
instances = {} instances = {}
def __init__(self, key='', fields={}, *, parent=None): def __init__(self, key='', fields={}, /,*, parent=None):
if parent is None: if parent is None:
self.alias = False self.alias = False
self.key = str(key) self.key = str(key)
self.fields = fields self.fields = fields
self.errors = [] self.errors = []
self.warnings = [] self.warnings = []
self.TargetType = None self.TargetType = None
else: else:
self.alias = parent.alias self.alias = parent.alias
self.key = parent.key self.key = parent.key
self.fields = parent.fields self.fields = parent.fields
self.errors = parent.errors self.errors = parent.errors
self.warnings = parent.warnings self.warnings = parent.warnings
# redefined for each unique type, default just verifies key # redefined for each unique type, default just verifies key
@ -72,15 +72,11 @@ class Bind(object):
self.instances[type(self)] = [self] self.instances[type(self)] = [self]
def verify(self): def verify(self):
try: self.alias = self.optional('alias', default=False)
self.alias = self.fields.pop('alias') if not isinstance(self.alias, bool):
if not isinstance(self.alias, bool): self.err(
self.errors.append( f'`alias` should be "yes" or "no", not "{self.alias}"'
f'alias should be "yes" or "no", not "{self.alias}"' )
)
self.alias = False
except popErrors:
self.alias = False
try: try:
typeName, self.key = self.key.split(' ', 1) typeName, self.key = self.key.split(' ', 1)
@ -107,6 +103,21 @@ class Bind(object):
if (not self.alias) and (self.key not in validKeyList): if (not self.alias) and (self.key not in validKeyList):
self.errors.append(f'invalid key name: "{self.key}"') self.errors.append(f'invalid key name: "{self.key}"')
def optional(self, name, /,*, default=None):
try:
return self.fields.pop(name)
except popErrors:
return default
def cmdListFrom(self, name, /,*, default=None):
result = self.fields.pop(name)
if isinstance(result, str):
return result.split(';')
elif isinstance(result, list):
return result
else:
return default
def toTargetType(self): def toTargetType(self):
if self.TargetType is None: if self.TargetType is None:
# do nothing # do nothing
@ -128,21 +139,20 @@ class Bind(object):
class Impulse(Bind): class Impulse(Bind):
def verify(self): def verify(self):
self.command = None self.command: list = None
if not isinstance(self.fields, dict): if not isinstance(self.fields, dict):
self.fields = {'command': self.fields} self.fields = {'command': self.fields}
try: try:
self.command = self.fields.pop('command') self.command = self.cmdListFrom(
if isinstance(self.command, str): 'command',
self.command = self.command.split(';') default=self.fields
elif not isinstance(self.command, list): )
self.err('`command` field must be argument of string or list') if self.command is None:
self.command = None self.err('`command` field must be string or list')
except KeyError: except popErrors:
self.err('requires `command` field') self.err('requires `command` field')
def toTF2(self) -> str: def toTF2(self) -> str:
if self.alias: if self.alias:
bindOrAlias = 'alias' bindOrAlias = 'alias'
@ -167,11 +177,8 @@ class Impulse(Bind):
'secondary': 'slot2', 'secondary': 'slot2',
'melee': 'slot3' 'melee': 'slot3'
} }
try: # if is shortcut, change
cmd = simpleSCs[cmd] cmd = simpleSCs.get(cmd, cmd)
except KeyError:
# not a shortcut
pass
if cmd == 'voice': if cmd == 'voice':
cmd = 'voicemenu' cmd = 'voicemenu'
@ -183,8 +190,8 @@ class Impulse(Bind):
elif cmd == 'loadout' and restOfCmd.isalpha(): elif cmd == 'loadout' and restOfCmd.isalpha():
cmd = 'load_itempreset' cmd = 'load_itempreset'
try: try:
restOfCmd = restOfCmd.lower() loadoutNum = ['a','b','c','d'].index(restOfCmd.lower())
restOfCmd = str(['a','b','c','d'].index(restOfCmd)) restOfCmd = str(loadoutNum)
except ValueError: except ValueError:
# not a load_itempreset shortcut # not a load_itempreset shortcut
pass pass
@ -204,9 +211,9 @@ class Impulse(Bind):
keyword = keyword.lower() keyword = keyword.lower()
allLists = ( allLists = (
('medic', 'thanks', 'go', 'move up', 'go left', 'go right', 'yes', 'no', 'pass to me'), ('medic', 'thanks', 'go', 'move up', 'go left', 'go right', 'yes', 'no', 'pass to me'),
('incoming', 'spy', 'sentry ahead', 'teleporter here', 'dispenser here', 'sentry here', 'activate uber', 'uber ready'), ('incoming', 'spy', 'sentry ahead', 'teleporter here', 'dispenser here', 'sentry here', 'activate uber', 'uber ready'),
('help', 'battle cry', 'cheers', 'jeers', 'positive', 'negative', 'nice shot', 'good job'), ('help', 'battle cry', 'cheers', 'jeers', 'positive', 'negative', 'nice shot', 'good job'),
) )
for menu, voiceList in enumerate(allLists): for menu, voiceList in enumerate(allLists):
@ -221,40 +228,32 @@ class Impulse(Bind):
'exit': '1 1', 'exit': '1 1',
'sentry': '2 0' 'sentry': '2 0'
} }
for shortBuild, num in buildingNums.items(): return buildingNums.get(building, building)
if building == shortBuild:
return num
class Hold(Bind): class Hold(Bind):
def verify(self): def verify(self):
self.press = None self.press: list = None
self.release = None self.release: list = None
if not isinstance(self.fields, dict): if not isinstance(self.fields, dict):
self.fields = {'press': self.fields} self.fields = {'press': self.fields}
# verify press # verify press
try: try:
self.press = self.fields.pop('press') self.press = self.cmdListFrom('press')
if isinstance(self.press, str): if self.press is None:
self.press = self.press.split(';')
elif not isinstance(self.press, list):
self.err('`press` field must be string or list') self.err('`press` field must be string or list')
self.press = None except popErrors:
except KeyError:
self.err('requires `press` field') self.err('requires `press` field')
if self.press is None:
return
# verify release # verify release
try: try:
self.release = self.fields.pop('release') self.release = self.cmdListFrom('release')
if isinstance(self.release, str): if self.release is None:
self.release = self.release.split(';')
elif not isinstance(self.release, list):
self.err('`release` field must be string or list') self.err('`release` field must be string or list')
self.release = None
except popErrors: except popErrors:
if self.press is None:
return
self.warn('has no `release`, creating one') self.warn('has no `release`, creating one')
# no release specified, do -action for each item in press # no release specified, do -action for each item in press
self.release = [] self.release = []
@ -271,11 +270,11 @@ class Hold(Bind):
# Making impulse instances from self.press and .release # Making impulse instances from self.press and .release
# allows them to share the shortcuts # allows them to share the shortcuts
pressObj = Impulse(f'+{holdStr}', self.press) pressObj = Impulse('+' + holdStr, self.press)
pressObj.alias = True pressObj.alias = True
pressStr = pressObj.toTF2() pressStr = pressObj.toTF2()
releaseObj = Impulse(f'-{holdStr}', self.release) releaseObj = Impulse('-' + holdStr, self.release)
releaseObj.alias = True releaseObj.alias = True
releaseStr = releaseObj.toTF2() releaseStr = releaseObj.toTF2()
@ -296,34 +295,29 @@ class Hold(Bind):
class Toggle(Bind): class Toggle(Bind):
def verify(self): def verify(self):
self.on = None self.on : list = None
self.off = None self.off: list = None
if not isinstance(self.fields, dict): if not isinstance(self.fields, dict):
self.fields = {'on': self.fields} self.fields = {'on': self.fields}
# verify on # verify on
try: try:
self.on = self.fields.pop('on') self.on = self.cmdListFrom('on')
if isinstance(self.on, str): if self.on is None:
self.on = self.on.split(';') self.err(f'`on` field must be string or list')
elif not isinstance(self.on, list): except popErrors:
self.err('`on` field must be string or list')
self.on = None
except KeyError:
self.err('requires `on` field') self.err('requires `on` field')
if self.on is None:
return
# verify off # verify off
try: try:
self.off = self.fields.pop('off') self.off = self.cmdListFrom('off')
if isinstance(self.off, str): if self.off is None:
self.off = self.off.split(';') self.err(f'`off` field must be string or list')
elif not isinstance(self.off, list):
self.err('`off` field must be string or list')
except popErrors: except popErrors:
# no off specified, do -action for each item in on # no off specified, do -action for each item in on
self.off = [] self.off = []
if self.on is None:
return
for cmd in self.on: for cmd in self.on:
if cmd[0] == '+': if cmd[0] == '+':
self.off.append('-' + cmd[1:]) self.off.append('-' + cmd[1:])
@ -357,25 +351,20 @@ class Toggle(Bind):
class Double(Bind): class Double(Bind):
defaultDict = {} defaultDict = {}
condDict = {} condDict = {}
bindNames = [] bindNames = []
def verify(self): def verify(self):
self.primary = None self.primStr = f'{self.key}_primary'
self.primStr = f'{self.key}_primary' self.secondStr = f'{self.key}_secondary'
self.isToggle = False
self.secondary = None
self.secondStr = f'{self.key}_secondary'
self.condition = None
self.isToggle = False
# name of a bind type
self.type = None
# either 'released' (default) or 'both'
self.cancelBoth = False self.cancelBoth = False
self.primary: Bind = None
self.secondary: Bind = None
self.condition: str = None
self.type: str = None
# toggler # toggler
try: try:
self.condition = self.fields.pop('condition') self.condition = self.fields.pop('condition')
@ -384,15 +373,12 @@ class Double(Bind):
except popErrors: except popErrors:
self.err('requires `condition` field') self.err('requires `condition` field')
try: self.isToggle = self.optional('toggle', default=False)
self.isToggle = self.fields.pop('toggle') if not isinstance(self.isToggle, bool):
if not isinstance(self.isToggle, bool): self.err(
self.err( '`toggle` field should be "yes" or "no",'
'`toggle` field should be "yes" or "no", ' + f' not "{self.isToggle}"'
+ f'not "{self.isToggle}"' )
)
except popErrors:
self.isToggle = False
# type # type
try: try:
@ -407,56 +393,57 @@ class Double(Bind):
return return
# cancel mode, must happend after type has been inferred # cancel mode, must happend after type has been inferred
try: cancel = self.optional('cancel', default='released')
cancel = self.fields.pop('cancel')
if not isinstance(cancel, str): if not isinstance(cancel, str):
self.err(f'`cancel` field must be "released" or "both"') self.err(f'`cancel` field must be "released" or "both"')
else:
else: if cancel == 'both':
if cancel == 'both': if self.type == 'hold':
if self.type == 'hold': self.cancelBoth = True
self.cancelBoth = True else:
else:
self.err(
'`cancel` field only affects "hold", '
+ f'not "{self.type}"'
)
elif cancel != 'released':
self.err( self.err(
'`cancel` field must be "released" ' '`cancel` field only affects "hold",'
+ f'or "both", not "{cancel}"' + f' not "{self.type}"'
) )
except popErrors: elif cancel == 'released':
cancel = 'released' self.cancelBoth = False
else:
self.err(
'`cancel` field must be "released"'
+ f' or "both", not "{cancel}"'
)
# primary action
try: try:
mainSection = self.fields.pop('primary') self.primary = self.getSection('primary', self.primStr)
mainBind = Bind(f'{self.type} {self.primStr}', mainSection)
mainBind = mainBind.toTargetType()
self.errors.extend(mainBind.errors)
self.warnings.extend(mainBind.warnings)
self.errors.remove(f'invalid key name: "{self.primStr}"')
self.primary = mainBind
except popErrors: except popErrors:
self.err('requires `primary` field') self.primary = None
# secondary action
try: try:
altSection = self.fields.pop('secondary') self.secondary = self.getSection('secondary', self.secondStr)
altBind = Bind(f'{self.type} {self.secondStr}', altSection)
altBind = altBind.toTargetType()
self.errors.extend(altBind.errors)
self.warnings.extend(altBind.warnings)
self.errors.remove(f'invalid key name: "{self.secondStr}"')
self.secondary = altBind
except popErrors: except popErrors:
self.err('requires `secondary` field') self.secondary = None
if self.primary is self.secondary is None:
self.err('has neither primary nor secondary')
def getSection(self, popName, key, /) -> Bind:
section = self.fields.pop(popName)
bind = Bind(f'{self.type} {key}', section)
bind = bind.toTargetType()
bind.errors.remove(f'invalid key name: "{key}"')
self.prettifyList(bind.errors, key)
self.errors.extend(bind.errors)
self.prettifyList(bind.warnings, key)
self.warnings.extend(bind.warnings)
return bind
def prettifyList(self, strList, origStr):
repStr = ' '.join(origStr.split('_', 1))
for i, cmd in enumerate(strList):
strList[i] = cmd.replace(origStr, repStr)
def toTF2(self) -> str: def toTF2(self) -> str:
# Get code for primary and secondary actions. # Get code for primary and secondary actions.