Skip to content

Commit

Permalink
Add support for @spellcaster(X) directive
Browse files Browse the repository at this point in the history
  • Loading branch information
zzahos-kg committed Aug 12, 2017
1 parent 981bd33 commit fbe28da
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 45 deletions.
107 changes: 62 additions & 45 deletions Libs/AIBIN.py
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,7 @@ def __init__(self, bwscript=None, units=None, upgrades=None, techs=None, stat_tx
else:
self.techdat = DAT.TechDAT(self.tbl)
self.techdat.load_file(techs)
self._casters = None # Used during interpreting
self.parameters = [
[self.ai_address], # goto
[self.ai_unit,self.ai_address], # notowns_jump
Expand Down Expand Up @@ -802,39 +803,43 @@ def ai_ggmilitary(self, data, stage=0):
v = self.ai_military(data, stage)
if stage == 3:
subunit = self.unitsdat.get_value(v[1],'Subunit1')
if self.unitsdat.get_value(v[1],'GroundWeapon') == 130 and not self.unitsdat.get_value(v[1],'AttackUnit') in [53,59] and \
(subunit in [None,228] or (self.unitsdat.get_value(subunit,'GroundWeapon') == 130 and not self.unitsdat.get_value(subunit,'AttackUnit') in [53,59])):
raise PyMSWarning('Parameter','Unit has no ground weapon', extra=v, level=1)
if self.unitsdat.get_value(v[1],'GroundWeapon') == 130 and not self.unitsdat.get_value(v[1],'AttackUnit') in [53,59] \
and (subunit in [None,228] or (self.unitsdat.get_value(subunit,'GroundWeapon') == 130 and not self.unitsdat.get_value(subunit,'AttackUnit') in [53,59])) \
and (not self._casters or not v[1] in self._casters):
raise PyMSWarning('Parameter','Unit has no ground weapon, and is not marked as a @spellcaster', extra=v, level=1)
return v

def ai_agmilitary(self, data, stage=0):
"""ag_military - Same as Military type, but only for defending against an enemy Air unit attacking your Ground unit"""
v = self.ai_military(data, stage)
if stage == 3:
subunit = self.unitsdat.get_value(v[1],'Subunit1')
if self.unitsdat.get_value(v[1],'AirWeapon') == 130 and self.unitsdat.get_value(v[1],'AttackUnit') != 53 and \
(subunit in [None,228] or (self.unitsdat.get_value(subunit,'AirWeapon') == 130 and self.unitsdat.get_value(subunit,'AttackUnit') != 53)):
raise PyMSWarning('Parameter','Unit has no air weapon', extra=v, level=1)
if self.unitsdat.get_value(v[1],'AirWeapon') == 130 and self.unitsdat.get_value(v[1],'AttackUnit') != 53 \
and (subunit in [None,228] or (self.unitsdat.get_value(subunit,'AirWeapon') == 130 and self.unitsdat.get_value(subunit,'AttackUnit') != 53)) \
and (not self._casters or not v[1] in self._casters):
raise PyMSWarning('Parameter','Unit has no air weapon, and is not marked as a @spellcaster', extra=v, level=1)
return v

def ai_gamilitary(self, data, stage=0):
"""ga_military - Same as Military type, but only for defending against an enemy Ground unit attacking your Air unit"""
v = self.ai_military(data, stage)
if stage == 3:
subunit = self.unitsdat.get_value(v[1],'Subunit1')
if self.unitsdat.get_value(v[1],'GroundWeapon') == 130 and not self.unitsdat.get_value(v[1],'AttackUnit') in [53,59] and \
(subunit in [None,228] or (self.unitsdat.get_value(subunit,'GroundWeapon') == 130 and not self.unitsdat.get_value(subunit,'AttackUnit') in [53,59])):
raise PyMSWarning('Parameter','Unit has no ground weapon', extra=v, level=1)
if self.unitsdat.get_value(v[1],'GroundWeapon') == 130 and not self.unitsdat.get_value(v[1],'AttackUnit') in [53,59] \
and (subunit in [None,228] or (self.unitsdat.get_value(subunit,'GroundWeapon') == 130 and not self.unitsdat.get_value(subunit,'AttackUnit') in [53,59])) \
and (not self._casters or not v[1] in self._casters):
raise PyMSWarning('Parameter','Unit has no ground weapon, and is not marked as a @spellcaster', extra=v, level=1)
return v

def ai_aamilitary(self, data, stage=0):
"""aa_military - Same as Military type, but only for defending against an enemy Air unit attacking your Air unit"""
v = self.ai_military(data, stage)
if stage == 3:
subunit = self.unitsdat.get_value(v[1],'Subunit1')
if self.unitsdat.get_value(v[1],'AirWeapon') == 130 and self.unitsdat.get_value(v[1],'AttackUnit') != 53 and \
(subunit in [None,228] or (self.unitsdat.get_value(subunit,'AirWeapon') == 130 and not self.unitsdat.get_value(subunit,'AttackUnit') != 53)):
raise PyMSWarning('Parameter','Unit has no air weapon', extra=v, level=1)
if self.unitsdat.get_value(v[1],'AirWeapon') == 130 and self.unitsdat.get_value(v[1],'AttackUnit') != 53 \
and (subunit in [None,228] or (self.unitsdat.get_value(subunit,'AirWeapon') == 130 and not self.unitsdat.get_value(subunit,'AttackUnit') != 53)) \
and (not self._casters or not v[1] in self._casters):
raise PyMSWarning('Parameter','Unit has no air weapon, and is not marked as a @spellcaster', extra=v, level=1)
return v

def ai_upgrade(self, data, stage=0):
Expand Down Expand Up @@ -951,6 +956,38 @@ def interpret(self, files, defs=None, extra=False):
multiline = False
lastmulti = [None,None]
loaded = []
self._casters = []
def parse_param(p,d,n=None,line=None):
try:
var = None
da = d
if d.lower() in variables:
for pt in self.typescanbe[p.__doc__.split(' ',1)[0]]:
if pt in variables[d.lower()][0]:
da = variables[d.lower()][1]
break
else:
raise PyMSError('Variable',"Incorrect type on varaible '%s'. Excpected '%s' but got '%s'" % (d.lower(), p.__doc__.split(' ',1)[0], variables[d.lower()][0][0].__doc__.split(' ',1)[0]),n,line, warnings=warnings)
var = PyMSWarning('Variable',"The variable '%s' of type '%s' was set to '%s'" % (d, variables[d.lower()][0][0].__doc__.split(' ',1)[0], variables[d.lower()][1]))
return p(da,3)
except PyMSWarning, w:
w.line = n + 1
w.code = line
warnings.append(w)
if var:
var.warning += ' when the above warning happened'
warnings.append(var)
return w.extra
except PyMSError, e:
e.line = n + 1
e.code = line
e.warnings = warnings
if var:
var.warning += ' when the above error happened'
e.warnings.append(var)
raise e
except:
raise PyMSError('Parameter',"Invalid parameter data '%s', looking for type '%s'" % (d,p.__doc__.split(' ',1)[0]),n,line, warnings=warnings)
def load_defs(defname):
try:
deffile = os.path.join(os.path.dirname(files[0]),defname)
Expand All @@ -968,6 +1005,13 @@ def load_defs(defname):
if len(l) > 1:
line = l.strip().split('#',1)[0]
if line:
match = re.match(r'\A@spellcaster\(\s*(\S+?)\s*\)\s*\Z', line)
print match
if match:
v = parse_param(self.ai_military, match.group(1))
print '@spellcaster(%d)' % v[1]
self._casters.append(v[1])
continue
match = re.match('\\A(\\S+)\\s+(.+)\\s+=\\s+(.+?)(?:\\s*\\{(.+)\\})?\\Z', line)
if match:
t,name,dat,vinfo = match.groups()
Expand Down Expand Up @@ -1248,39 +1292,9 @@ def load_defs(defname):
unused[(id,d)] = False
curinfo[id][2].append(d)
else:
try:
var = None
da = d
if d.lower() in variables:
for pt in self.typescanbe[p.__doc__.split(' ',1)[0]]:
if pt in variables[d.lower()][0]:
da = variables[d.lower()][1]
break
else:
raise PyMSError('Variable',"Incorrect type on varaible '%s'. Excpected '%s' but got '%s'" % (d.lower(), p.__doc__.split(' ',1)[0], variables[d.lower()][0][0].__doc__.split(' ',1)[0]),n,line, warnings=warnings)
var = PyMSWarning('Variable',"The variable '%s' of type '%s' was set to '%s'" % (d, variables[d.lower()][0][0].__doc__.split(' ',1)[0], variables[d.lower()][1]))
cs = p(da,3)
ai[4][-1].append(cs[1])
aisize += cs[0]
except PyMSWarning, w:
ai[4][-1].append(w.extra[1])
aisize += w.extra[0]
w.line = n + 1
w.code = line
warnings.append(w)
if var:
var.warning += ' when the above warning happened'
warnings.append(var)
except PyMSError, e:
e.line = n + 1
e.code = line
e.warnings = warnings
if var:
var.warning += ' when the above error happened'
e.warnings.append(var)
raise e
except:
raise PyMSError('Parameter',"Invalid parameter data '%s', looking for type '%s'" % (d,p.__doc__.split(' ',1)[0]),n,line, warnings=warnings)
cs = parse_param(p, d, n, line)
ai[4][-1].append(cs[1])
aisize += cs[0]
if cmd != 'wait' and cmd in self.separate:
notused = (n,line)
if cmd.lower() in self.separate:
Expand Down Expand Up @@ -1534,6 +1548,9 @@ def decompile(self, file, defs=None, ref=False, shortlabel=True, scripts=None):
if len(l) > 1:
line = l.strip().split('#',1)[0]
if line:
match = re.match(r'\A@spellcaster\(\s*(\S+?)\s*\)\s*\Z', line)
if match:
continue
match = re.match('\\A(\\S+)\\s+(.+)\\s+=\\s+(.+?)(?:\\s*\\{(.+)\\})?\\Z', line)
if match:
t,name,dat,vinfo = match.groups()
Expand Down
6 changes: 6 additions & 0 deletions unitdef.txt
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,13 @@ military goliath = 3
military siege_tank = 5
military wraith = 8
military science_vessel = 9
@spellcaster(science_vessel)
military dropship = 11
military battlecruiser = 12
military nuclear_missile = 14
military firebat = 32
military medic = 34
@spellcaster(medic)
military valkyrie = 58

# Zerg military units
Expand All @@ -32,7 +34,9 @@ military ultralisk = 39
military mutalisk = 43
military guardian = 44
military queen = 45
@spellcaster(queen)
military defiler = 46
@spellcaster(defiler)
military scourge = 47
military infested_terran = 50
military devourer = 62
Expand All @@ -42,9 +46,11 @@ military lurker = 103
military corsair = 60
military dark_templar = 61
military dark_archon = 63
@spellcaster(dark_archon)
military zealot = 65
military dragoon = 66
military high_templar = 67
@spellcaster(high_templar)
military archon = 68
military shuttle = 69
military scout = 70
Expand Down

0 comments on commit fbe28da

Please sign in to comment.