NovaBryan/EVE_Dump
Log | Files | 📦 下载最新源码 (.zip) | Refs | README

svc_poser.py (32529B)


      1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\eve\devtools\script\svc_poser.py
      2 import os
      3 from math import sqrt
      4 import evetypes
      5 import blue
      6 import triui
      7 from carbon.common.script.sys.service import Service
      8 from carbon.common.script.sys.serviceConst import SERVICE_RUNNING, SERVICE_START_PENDING, ROLE_WORLDMOD
      9 from carbonui import uiconst
     10 from carbonui.control.combo import Combo
     11 from carbonui.control.singlelineedits.singleLineEditInteger import SingleLineEditInteger
     12 from carbonui.primitives.container import Container
     13 from carbonui.primitives.line import Line
     14 from controltowerresources.data import get_control_tower_resources
     15 from eve.client.script.ui.control import eveLabel, eveScroll
     16 from carbonui.button.group import ButtonGroup
     17 from carbonui.control.buttonIcon import ButtonIcon
     18 from carbonui.control.button import Button
     19 from eve.client.script.ui.control.entries.checkbox import CheckboxEntry
     20 from eve.client.script.ui.control.entries.util import GetFromClass
     21 from carbonui.control.window import Window
     22 from player_messaging.client.ui_message import prompt_player
     23 from eve.client.script.ui.util import utilWindows
     24 from eve.client.script.util import eveMisc
     25 from eve.common.script.sys import idCheckers
     26 from eveexceptions import UserError
     27 from player_messaging import IGNORE_TO_TOP
     28 Slash = lambda x: sm.RemoteSvc('slash').SlashCmd(x)
     29 Progress = lambda title, text, current, total: sm.GetService('loading').ProgressWnd(title, text, current, total)
     30 PURPOSE_ONLINE = 1
     31 PURPOSE_POWER = 2
     32 PURPOSE_CPU = 3
     33 PURPOSE_REINFORCED = 4
     34 ORIENTATION = 1
     35 
     36 class Structure():
     37     __guid__ = 'poser.Structure'
     38 
     39     def __init__(self, starbase, typeID, options = None):
     40         self.starbase = starbase
     41         self.typeID = typeID
     42         self.itemID = None
     43         self.quantity = 1
     44         self.name = evetypes.GetName(typeID)
     45         self.options = options or {}
     46         self.godma = sm.GetService('godma')
     47         self.attr = self.godma.GetType(typeID)
     48         groupID = evetypes.GetGroupID(typeID)
     49         self.isControlTower = groupID == const.groupControlTower
     50         self.isWeapon = self.attr.AttributeExists('chargeGroup1')
     51         self.isRenameable = groupID in (const.groupMobileLaboratory, const.groupAssemblyArray)
     52 
     53     def Create(self):
     54         if not self.itemID:
     55             self.itemID = Slash('/createitem %s' % self.typeID)
     56         else:
     57             raise RuntimeError('Instance of poser.Structure already bound to an item')
     58 
     59     def Position(self, x, y, z):
     60         self.x = self.x_ + x
     61         self.y = self.y_ + y
     62         self.z = self.z_ + z
     63         Slash('/tr %s %s %s %s' % (self.itemID,
     64          self.x,
     65          self.y,
     66          self.z))
     67 
     68     def Anchor(self):
     69         try:
     70             Slash('/pos anchor %s' % self.itemID)
     71         except:
     72             raise
     73 
     74         if 'name' in self.options and self.isRenameable:
     75             cfg.evelocations.Prime([self.itemID])
     76             sm.GetService('invCache').GetInventoryMgr().SetLabel(self.itemID, self.options['name'])
     77             sm.ScatterEvent('OnItemNameChange', self.itemID)
     78 
     79     def Online(self):
     80         if 'offline' not in self.options or self.isControlTower:
     81             Slash('/pos online %s' % self.itemID)
     82 
     83     def Arm(self):
     84         a = self.attr
     85         ammo = sm.GetService(SERVICENAME).GetAmmo()
     86         if a.AttributeExists('damageMultiplier'):
     87             for ammoType in ammo[a.chargeGroup1]:
     88                 if ammoType.chargeSize == a.chargeSize:
     89                     break
     90 
     91         else:
     92             for ammoType in ammo[a.chargeGroup1]:
     93                 break
     94 
     95         units = int(a.capacity / ammoType.volume)
     96         itemID = Slash('/createitem %s %s' % (ammoType.typeID, units))
     97         inv = sm.GetService('invCache').GetInventoryFromId(self.itemID)
     98         inv.Add(itemID, session.shipid, qty=units)
     99 
    100     def GetCapacity(self):
    101         if self.isControlTower:
    102             ctinv = sm.GetService('invCache').GetInventoryFromId(self.itemID)
    103             try:
    104                 row = ctinv.GetCapacity(const.flagNone)
    105                 capacity = row.capacity
    106                 used = row.used
    107             except:
    108                 capacity = sm.GetService('godma').GetType(self.typeID).capacity
    109                 used = 0.0
    110 
    111             return (capacity, used)
    112         raise RuntimeError('this only works on towers')
    113 
    114     def Requirements(self):
    115         if self.isControlTower:
    116             return (self.attr.cpuOutput, self.attr.powerOutput)
    117         else:
    118             return (self.attr.cpu, self.attr.power)
    119 
    120     def Distance(self, this):
    121         dx = this.x - self.x
    122         dy = this.y - self.y
    123         dz = this.z - self.z
    124         return sqrt(dx * dx + dy * dy + dz * dz) - this.radius
    125 
    126     def MoveTo(self):
    127         self.starbase.MoveTo(self)
    128 
    129     def Approach(self):
    130         Slash('/tr me %s' % self.itemID)
    131 
    132     def Hug(self):
    133         Slash('/tr me pos=%s,%s,%s' % (self.x + 700, self.y, self.z + 700))
    134 
    135 
    136 class Starbase():
    137     __guid__ = 'poser.Starbase'
    138 
    139     def MoveTo(self, structure):
    140         structure.Approach()
    141         distance = 1501
    142         i = 600
    143         ball = self.bp.GetBall(structure.itemID)
    144         while distance > 1500:
    145             if not i:
    146                 raise RuntimeError('Shit happened')
    147             i -= 1
    148             blue.pyos.synchro.SleepSim(100)
    149             distance = structure.Distance(self.ship) - ball.radius
    150 
    151     def Step(self, s = None, a = 0, title = 'Poser - Starbase Assembly<br>Stage %d of %d'):
    152         bp = self.bp = sm.GetService('michelle').GetBallpark()
    153         if not bp:
    154             return
    155         ship = self.ship = bp.GetBall(session.shipid)
    156         if not ship:
    157             return
    158         if s is None:
    159             Progress(self.title, self.info, 1, 1)
    160             return
    161         if type(s) == type(0):
    162             self.maxsteps = s
    163             self.maxamount = a
    164             self.step = 0
    165             self.title_ = title
    166             return
    167         self.step += 1
    168         if self.maxsteps:
    169             self.title = self.title_ % (self.step, self.maxsteps)
    170         else:
    171             self.title = self.title_
    172         self.info = s
    173         self.done = 0
    174         self.Update()
    175 
    176     def Update(self, maxamount = 0):
    177         if not maxamount:
    178             maxamount = self.maxamount
    179         Progress(self.title, self.info, self.done * 1000, maxamount * 1000 + 1)
    180         self.done += 1
    181 
    182     def ImportFromEnvironment(self):
    183         bp = self.bp = sm.GetService('michelle').GetBallpark()
    184         if not bp:
    185             return
    186         ship = self.ship = bp.GetBall(session.shipid)
    187         if not ship:
    188             return
    189         ct = None
    190         structs = []
    191         self.Step(0, 16, 'Poser - Starbase Scan')
    192         self.Step('Scanning Area...')
    193         i = 1
    194         for ballID in bp.balls.iterkeys():
    195             blue.pyos.BeNice()
    196             i += 1
    197             self.Update(i & 15)
    198             if ballID:
    199                 ball = bp.GetBall(ballID)
    200                 item = bp.GetInvItem(ballID)
    201                 if ball and item and item.categoryID == const.categoryStarbase:
    202                     if item.groupID == const.groupControlTower:
    203                         ct = ballID
    204                     else:
    205                         structs.append(ballID)
    206 
    207         if not ct:
    208             info = 'No control tower found.'
    209             raise UserError('CustomInfo', {'info': info})
    210         structs.insert(0, ct)
    211         self.structures = []
    212         ownerID = bp.GetInvItem(ct).ownerID
    213         for ballID in structs:
    214             item = bp.GetInvItem(ballID)
    215             if item.ownerID == ownerID:
    216                 options = {}
    217                 ball = bp.GetBall(ballID)
    218                 if not sm.GetService('pwn').GetStructureState(item)[0] == 'online':
    219                     options['offline'] = True
    220                 s = Structure(self, item.typeID, options)
    221                 s.x = ball.x
    222                 s.y = ball.y
    223                 s.z = ball.z
    224                 s.itemID = ballID
    225                 if s.isRenameable:
    226                     cfg.evelocations.Prime([ballID])
    227                     name = cfg.evelocations.Get(ballID).name
    228                     if name != evetypes.GetName(item.typeID):
    229                         options['name'] = name
    230                 self.structures.append(s)
    231                 if s.isControlTower:
    232                     self.controltower = ct = s
    233                 s.x_ = int(s.x + 0.5) - int(ct.x + 0.5)
    234                 s.y_ = int(s.y + 0.5) - int(ct.y + 0.5)
    235                 s.z_ = int(s.z + 0.5) - int(ct.z + 0.5)
    236 
    237         self.Assemble = self.NoAssemble
    238         return self
    239 
    240     def ImportFromFile(self, filename):
    241         fh = open(filename, 'r')
    242         stuff = fh.read().replace('\r', '').split('\n')
    243         fh.close()
    244         self.structures = []
    245         self.controltower = None
    246         notFound = {}
    247         amount = len(stuff)
    248         for i in xrange(amount):
    249             line = stuff[i]
    250             if line.strip() != '':
    251                 coords, name = line.split('=', 1)
    252                 coords = coords.strip()
    253                 name = name.strip()
    254                 optionsDict = {}
    255                 if name.find(':') > -1:
    256                     name, options = name.split(':', 1)
    257                     name = name.strip()
    258                     for option in options.split(':'):
    259                         if '=' in option:
    260                             k, v = option.split('=', 1)
    261                             v = v.strip()
    262                         else:
    263                             k, v = option, True
    264                         optionsDict[k.strip().lower()] = v
    265 
    266                 x, y, z = coords.split()
    267                 if name.isdigit():
    268                     typeID = name
    269                 else:
    270                     typeID = sm.GetService('poser').FindTypeID(name)
    271                 typeID = int(typeID)
    272                 if not typeID:
    273                     notFound[name] = True
    274                 else:
    275                     s = Structure(self, typeID, optionsDict)
    276                     s.x_ = float(x)
    277                     s.y_ = float(y)
    278                     s.z_ = float(z)
    279                     self.structures.append(s)
    280                     if s.isControlTower:
    281                         self.controltower = s
    282                     blue.pyos.BeNice()
    283 
    284         Progress('Poser - Loading', 'Done!', 1, 1)
    285         if notFound:
    286             prompt_player('The following structures were not found:<br><font color="#FF0000">%s</font><br><br>It is possible these types have been deleted or had their name changed. Edit the .pos file and try again' % '<br>'.join(notFound.keys()), 'Unknown Structures', options=uiconst.OK, icon=triui.WARNING)
    287             raise UserError(IGNORE_TO_TOP)
    288         return self
    289 
    290     def ExportAsTriText(self):
    291         lines = []
    292         for s in self.structures:
    293             options = ''
    294             for k, v in s.options.iteritems():
    295                 if v == True:
    296                     options += ':' + k
    297                 else:
    298                     options += ':%s=%s' % (k, v)
    299 
    300             line = '% 6d % 6d % 6d = %s' % (s.x_,
    301              s.y_,
    302              s.z_,
    303              s.typeID)
    304             lines.append(line)
    305 
    306         return '<br>'.join(lines)
    307 
    308     def ExportAsFile(self, filename):
    309         crud = self.ExportAsTriText().replace('<br>', '\r\n')
    310         fh = open(filename, 'wb')
    311         fh.write(crud)
    312         fh.close()
    313 
    314     def NoAssemble(self):
    315         raise RuntimeError('Cannot Assemble from a live configuration')
    316 
    317     def Assemble(self, stepSelection = {}):
    318         bp = self.bp = sm.GetService('michelle').GetBallpark()
    319         if not bp:
    320             return
    321         amount = len(self.structures)
    322         self.Step(8, amount)
    323         self.Step('Creating structures...')
    324         x, y, z = self.ship.x, self.ship.y, self.ship.z
    325         for s in self.structures:
    326             self.Update()
    327             s.Create()
    328 
    329         self.Step('Launching structures...')
    330         sm.RemoteSvc('slash').SlashCmd('/tr me offset=32000,0,0')
    331         eveMisc.LaunchFromShip(self.structures, session.corpid)
    332         blue.pyos.synchro.SleepSim(2000)
    333         self.Step('Positioning structures...')
    334         for s in self.structures:
    335             self.Update()
    336             s.Position(x, y, z)
    337 
    338         if stepSelection.get('TowerAnchor', True):
    339             self.controltower.Anchor()
    340         if stepSelection.get('TowerFuel', True):
    341             self.Fuel(1, [PURPOSE_ONLINE])
    342         if stepSelection.get('TowerOnline', True):
    343             self.controltower.Online()
    344         if stepSelection.get('StructAnchor', True):
    345             self.Anchor()
    346         if stepSelection.get('StructFuel', True):
    347             self.Fuel()
    348         if stepSelection.get('StructOnline', True):
    349             self.Online()
    350         if stepSelection.get('ArmWeapons', True):
    351             self.Arm()
    352         self.Assemble = self.NoAssemble
    353         Progress('Poser - Complete', 'All done!', 1, 1)
    354 
    355     def GetLoad(self):
    356         cpu = 0
    357         power = 0
    358         for s in self.structures:
    359             if not s.isControlTower:
    360                 if 'offline' not in s.options:
    361                     c, p = s.Requirements()
    362                     cpu += c
    363                     power += p
    364 
    365         ccpu, cpower = self.controltower.Requirements()
    366         if ccpu:
    367             fcpu = float(min(cpu, ccpu))
    368             cpu = fcpu / ccpu
    369         else:
    370             cpu = 0
    371         if cpower:
    372             fpower = float(min(power, cpower))
    373             power = fpower / cpower
    374         else:
    375             power = 0
    376         return (cpu, power)
    377 
    378     def GetFuelInfo(self, filter = ()):
    379         fcpu, fpower = self.GetLoad()
    380         secStatus = sm.GetService('map').securityInfo[session.solarsystemid]
    381         factionID = sm.GetService('map').GetItem(session.solarsystemid).factionID
    382         fuel = {PURPOSE_ONLINE: [],
    383          PURPOSE_POWER: [],
    384          PURPOSE_CPU: [],
    385          PURPOSE_REINFORCED: [],
    386          'all': [],
    387          'filter': []}
    388         volumePerCycle = {PURPOSE_ONLINE: 0.0,
    389          PURPOSE_POWER: 0.0,
    390          PURPOSE_CPU: 0.0,
    391          PURPOSE_REINFORCED: 0.0,
    392          'all': 0.0,
    393          'filter': 0.0}
    394 
    395         def _add(r, x, v):
    396             fuel[r.purpose].append(x)
    397             volumePerCycle[r.purpose] += v
    398             fuel['all'].append(x)
    399             volumePerCycle['all'] += v
    400             if r.purpose in filter:
    401                 fuel['filter'].append(x)
    402                 volumePerCycle['filter'] += v
    403 
    404         resources = get_control_tower_resources(self.controltower.typeID)
    405         for resource in resources:
    406             info = sm.GetService('godma').GetType(resource.resourceTypeID)
    407             volume = info.volume
    408             if info.groupID == const.groupLease:
    409                 if secStatus >= resource.minSecurityLevel:
    410                     if factionID == resource.factionID:
    411                         _add(resource, (resource.resourceTypeID, 1), volume)
    412                 continue
    413             if resource.purpose == PURPOSE_CPU:
    414                 factor = fcpu
    415             elif resource.purpose == PURPOSE_POWER:
    416                 factor = fpower
    417             else:
    418                 factor = 1.0
    419             qty = int(factor * resource.quantity + 0.5)
    420             _add(resource, (resource.resourceTypeID, qty), volume * qty)
    421 
    422         return (volumePerCycle, fuel)
    423 
    424     def Fuel(self, desiredCycles = 2147483647, what = (PURPOSE_ONLINE, PURPOSE_POWER, PURPOSE_CPU)):
    425         self.Step('Fueling Control Tower...')
    426         ct = self.controltower
    427         v, fuel = self.GetFuelInfo(filter=what)
    428         if v['filter'] > 0.0:
    429             ct.MoveTo()
    430             capacity, used = ct.GetCapacity()
    431             ctinv = sm.GetService('invCache').GetInventoryFromId(ct.itemID)
    432             free = capacity - used
    433             cycles = min(int(free / v['filter']), desiredCycles)
    434             for typeID, qty in fuel['filter']:
    435                 if qty:
    436                     self.Update(len(fuel['filter']))
    437                     itemID = Slash('/createitem %s %s' % (typeID, qty * cycles))
    438                     ctinv.Add(itemID, session.shipid, flag=const.flagNone)
    439 
    440         self.Step()
    441 
    442     def Anchor(self):
    443         self.Step('Anchoring Structures...')
    444         for s in self.structures:
    445             self.Update()
    446             if not s.isControlTower:
    447                 s.Anchor()
    448 
    449         blue.pyos.synchro.SleepWallclock(1000)
    450         self.Step()
    451 
    452     def Online(self):
    453         self.Step('Onlining Structures...')
    454         for s in self.structures:
    455             self.Update()
    456             if not s.isControlTower:
    457                 s.Online()
    458 
    459         self.Step()
    460 
    461     def Arm(self):
    462         self.Step('Arming Weapon Batteries...')
    463         for s in self.structures:
    464             self.Update()
    465             if s.isWeapon:
    466                 s.MoveTo()
    467                 s.Arm()
    468 
    469         self.Step()
    470 
    471 
    472 class FuelWindow(Window):
    473     __guid__ = 'form.FuelWindow'
    474     default_windowID = 'FuelWindow'
    475 
    476     def ApplyAttributes(self, attributes):
    477         Window.ApplyAttributes(self, attributes)
    478         self.SetCaption('Fuel Starbase')
    479         self.SetMinSize([350, 250], 1)
    480         self.MakeUnResizeable()
    481         y = const.defaultPadding + 10
    482         self.cycles_online = SingleLineEditInteger(name='cycles_online', parent=self.sr.main, setvalue=0, minValue=0, maxvalue=99999, left=90, width=100, top=y)
    483         self.cycles_cpupow = SingleLineEditInteger(name='cycles_cpupow', parent=self.sr.main, setvalue=0, minValue=0, maxvalue=99999, left=90, width=100, top=y + 40)
    484         self.cycles_reinf = SingleLineEditInteger(name='cycles_reinf', parent=self.sr.main, setvalue=0, minValue=0, maxvalue=99999, left=90, width=100, top=y + 80)
    485         eveLabel.Label(text='Add number of cycles fuel for...', parent=self.sr.main, width=400, left=const.defaultPadding, top=y - 12, fontsize=9, letterspace=2, uppercase=1, state=uiconst.UI_NORMAL)
    486         y += 4
    487         eveLabel.Label(text='Online:', parent=self.sr.main, width=100, left=2 * const.defaultPadding, top=y, fontsize=9, letterspace=2, uppercase=1, state=uiconst.UI_NORMAL)
    488         eveLabel.Label(text='CPU/Power:', parent=self.sr.main, width=100, left=2 * const.defaultPadding, top=y + 40, fontsize=9, letterspace=2, uppercase=1, state=uiconst.UI_NORMAL)
    489         eveLabel.Label(text='Reinforced:', parent=self.sr.main, width=100, left=2 * const.defaultPadding, top=y + 80, fontsize=9, letterspace=2, uppercase=1, state=uiconst.UI_NORMAL)
    490         Button(parent=self.sr.main, label='Auto', pos=(204,
    491          y + 5,
    492          0,
    493          0), func=self.Auto)
    494         y += 4
    495         Line(parent=self.sr.main, align=uiconst.RELATIVE, color=(1.0, 1.0, 1.0, 0.5), left=194, top=y, width=4, height=1)
    496         Line(parent=self.sr.main, align=uiconst.RELATIVE, color=(1.0, 1.0, 1.0, 0.5), left=194, top=y + 40, width=4, height=1)
    497         Line(parent=self.sr.main, align=uiconst.RELATIVE, color=(1.0, 1.0, 1.0, 0.5), left=198, top=y, width=1, height=41)
    498         Line(parent=self.sr.main, align=uiconst.RELATIVE, color=(1.0, 1.0, 1.0, 0.5), left=199, top=y + 20, width=4, height=1)
    499         buttons = [['Fuel',
    500           self.Fuel,
    501           None,
    502           81], ['Cancel',
    503           self.Cancel,
    504           None,
    505           81]]
    506         self.sr.main.children.insert(0, ButtonGroup(btns=buttons))
    507 
    508     def Cancel(self, *args):
    509         self.Close()
    510 
    511     def _prep(self):
    512         try:
    513             s = self.starbase
    514         except AttributeError:
    515             s = self.starbase = Starbase().ImportFromEnvironment()
    516             s.controltower.MoveTo()
    517             capacity, used = s.controltower.GetCapacity()
    518             self.free = capacity - used
    519             self.vol, self.fuel = s.GetFuelInfo(filter=(PURPOSE_ONLINE, PURPOSE_CPU, PURPOSE_POWER))
    520 
    521     def Auto(self, *args):
    522         self._prep()
    523         free = self.free - self.cycles_reinf.GetValue() * self.vol[PURPOSE_REINFORCED]
    524         cycles = max(int(self.free / self.vol['filter']), 0)
    525         self.cycles_online.SetValue(cycles)
    526         self.cycles_cpupow.SetValue(cycles)
    527 
    528     def Fuel(self, *args):
    529         o = self.cycles_online.GetValue()
    530         c = self.cycles_cpupow.GetValue()
    531         r = self.cycles_reinf.GetValue()
    532         self._prep()
    533         self.state = uiconst.UI_HIDDEN
    534         x = 0
    535         self.starbase.controltower.MoveTo()
    536         ctinv = sm.GetService('invCache').GetInventoryFromId(self.starbase.controltower.itemID)
    537         for cycles, purpose in [(o, PURPOSE_ONLINE),
    538          (c, PURPOSE_CPU),
    539          (c, PURPOSE_POWER),
    540          (r, PURPOSE_REINFORCED)]:
    541             if cycles:
    542                 Progress('Adding Fuel...', 'Hold on!', x, 4)
    543                 for fuel in self.fuel[purpose]:
    544                     if fuel[1]:
    545                         itemID = Slash('/createitem %s %s' % (fuel[0], cycles * fuel[1]))
    546                         if fuel[0] != const.typeStrontiumClathrates:
    547                             ctinv.Add(itemID, session.shipid, flag=const.flagNone)
    548                         else:
    549                             ctinv.Add(itemID, session.shipid, flag=const.flagSecondaryStorage)
    550 
    551             x += 1
    552 
    553         Progress('Adding Fuel...', 'Done!', 1, 1)
    554         self.Close()
    555 
    556 
    557 class AssembleWindow(Window):
    558     __guid__ = 'form.AssembleWindow'
    559     default_windowID = 'AssembleWindow'
    560 
    561     def ApplyAttributes(self, attributes):
    562         Window.ApplyAttributes(self, attributes)
    563         fileList = attributes.fileList
    564         self.selected = fileList[0][0] + '.pos'
    565         self.SetCaption('Assemble Starbase')
    566         self.MakeUnResizeable()
    567         self.SetMinSize([256, 256], 1)
    568         guts = Container(parent=self.sr.main, pos=(const.defaultPadding,
    569          const.defaultPadding,
    570          const.defaultPadding,
    571          const.defaultPadding), align=uiconst.TOALL)
    572         Combo(label='Select POS file', parent=guts, options=fileList, name='fileselect', select=0, align=uiconst.TOTOP, pos=(0, 20, 0, 0), width=200, callback=self.OnComboChange)
    573         scroll = eveScroll.Scroll(parent=guts, padding=(0,
    574          const.defaultPadding,
    575          0,
    576          const.defaultPadding))
    577         scrolllist = []
    578         for cfgname, var, label, group in [['posTowerAnchor',
    579           'TowerAnchor',
    580           'Anchor Control Tower',
    581           None],
    582          ['posTowerFuel',
    583           'TowerFuel',
    584           'Fuel Control Tower (for onlining)',
    585           None],
    586          ['posTowerOnline',
    587           'TowerOnline',
    588           'Online Control Tower',
    589           None],
    590          ['posStructAnchor',
    591           'StructAnchor',
    592           'Anchor All Structures',
    593           None],
    594          ['posStructFuel',
    595           'StructFuel',
    596           'Fuel Control Tower (for structures)',
    597           None],
    598          ['posStructOnline',
    599           'StructOnline',
    600           'Online All Structures',
    601           None],
    602          ['posArmWeapons',
    603           'ArmWeapons',
    604           'Arm Weapon Batteries',
    605           None]]:
    606             le = GetFromClass(CheckboxEntry, {'label': label,
    607              'checked': True,
    608              'cfgname': cfgname,
    609              'retval': var,
    610              'group': group,
    611              'OnChange': self.CheckBoxChange})
    612             scrolllist.append(le)
    613             setattr(self, var, True)
    614             setattr(self, var + 'LE', le)
    615 
    616         scroll.Load(contentList=scrolllist)
    617         buttons = [['Execute',
    618           self.Execute,
    619           None,
    620           81], ['Cancel',
    621           self.Cancel,
    622           None,
    623           81]]
    624         self.sr.main.children.insert(0, ButtonGroup(btns=buttons))
    625 
    626     def Cancel(self, *args):
    627         self.Close()
    628 
    629     def Execute(self, *args):
    630         INSIDERDIR = sm.GetService('insider').GetInsiderDir()
    631         TARGET = os.path.join(INSIDERDIR, self.selected)
    632         Starbase().ImportFromFile(TARGET).Assemble(stepSelection=self.__dict__)
    633         AssembleWindow.CloseIfOpen()
    634 
    635     def Set(self, state, list):
    636         for x in list:
    637             le = getattr(self, x + 'LE')
    638             p = le.panel
    639             if p:
    640                 p.sr.checkbox.SetChecked(state)
    641             le.checked = state
    642 
    643     def CheckBoxChange(self, checkbox, node, *args):
    644         name = node.retval
    645         setattr(self, name, checkbox.checked)
    646         if name == 'TowerAnchor':
    647             if not checkbox.checked:
    648                 self.Set(False, ['TowerFuel',
    649                  'TowerOnline',
    650                  'StructAnchor',
    651                  'StructFuel',
    652                  'StructOnline',
    653                  'ArmWeapons'])
    654         elif name == 'TowerFuel':
    655             if checkbox.checked:
    656                 self.Set(True, ['TowerAnchor'])
    657             else:
    658                 self.Set(False, ['TowerOnline',
    659                  'StructAnchor',
    660                  'StructFuel',
    661                  'StructOnline',
    662                  'ArmWeapons'])
    663         elif name == 'TowerOnline':
    664             if checkbox.checked:
    665                 self.Set(True, ['TowerAnchor', 'TowerFuel'])
    666             else:
    667                 self.Set(False, ['StructAnchor',
    668                  'StructFuel',
    669                  'StructOnline',
    670                  'ArmWeapons'])
    671         elif name == 'StructAnchor':
    672             if checkbox.checked:
    673                 self.Set(True, ['TowerAnchor', 'TowerFuel', 'TowerOnline'])
    674             else:
    675                 self.Set(False, ['StructFuel', 'StructOnline', 'ArmWeapons'])
    676         elif name == 'StructFuel':
    677             if checkbox.checked:
    678                 self.Set(True, ['TowerAnchor',
    679                  'TowerFuel',
    680                  'TowerOnline',
    681                  'StructAnchor'])
    682             else:
    683                 self.Set(False, ['StructOnline', 'ArmWeapons'])
    684         elif name == 'StructOnline':
    685             if checkbox.checked:
    686                 self.Set(True, ['TowerAnchor',
    687                  'TowerFuel',
    688                  'TowerOnline',
    689                  'StructAnchor',
    690                  'StructFuel'])
    691             else:
    692                 self.Set(False, ['ArmWeapons'])
    693         elif name == 'ArmWeapons':
    694             if checkbox.checked:
    695                 self.Set(True, ['TowerAnchor',
    696                  'TowerFuel',
    697                  'TowerOnline',
    698                  'StructAnchor',
    699                  'StructFuel',
    700                  'StructOnline'])
    701 
    702     def OnComboChange(self, combo, header, value, *args):
    703         self.selected = header + '.pos'
    704 
    705 
    706 SERVICENAME = 'poser'
    707 
    708 class PoserService(Service):
    709     __module__ = __name__
    710     __doc__ = 'Ultimate starbase setup tool'
    711     __exportedcalls__ = {'Show': []}
    712     __notifyevents__ = ['ProcessRestartUI']
    713     __dependencies__ = []
    714     __guid__ = 'svc.poser'
    715     __servicename__ = SERVICENAME
    716     __displayname__ = SERVICENAME.capitalize()
    717 
    718     def Run(self, *args):
    719         self.wnd = None
    720         self.state = SERVICE_START_PENDING
    721         godma = sm.GetService('godma')
    722         self.structureTypeID = {}
    723         self.ammo = {}
    724         for typeID in evetypes.Iterate():
    725             categoryID = evetypes.GetCategoryID(typeID)
    726             if categoryID == const.categoryStarbase:
    727                 self.structureTypeID[evetypes.GetName(typeID).lower().replace(' ', '')] = typeID
    728             elif categoryID == const.categoryCharge:
    729                 groupID = evetypes.GetGroupID(typeID)
    730                 if groupID in self.ammo:
    731                     self.ammo[groupID].append(godma.GetType(typeID))
    732                 else:
    733                     self.ammo[groupID] = [godma.GetType(typeID)]
    734 
    735         blue.pyos.BeNice()
    736         self.state = SERVICE_RUNNING
    737 
    738     def RoleCheck(self, *roleSets):
    739         for roleNames in roleSets:
    740             flags = 0
    741             for roleName in roleNames:
    742                 flags += globals()[roleName]
    743 
    744             if session.role & flags == flags:
    745                 return True
    746 
    747         summary = []
    748         for roleNames in roleSets:
    749             summary.append('<br>- '.join(roleNames))
    750 
    751         prompt_player(title='Missing Roles', text='You require the following role(s) to use this function:<br>-  %s' % '<br><br>Or the following role(s):<br>- '.join(summary), options=uiconst.OK, icon=uiconst.INFO)
    752 
    753     def FindTypeID(self, name):
    754         return self.structureTypeID.get(name.lower().replace(' ', ''), None)
    755 
    756     def GetAmmo(self):
    757         return self.ammo
    758 
    759     def Show(self):
    760         if self.wnd and not self.wnd.destroyed:
    761             self.wnd.Maximize()
    762             return
    763 
    764         def MakeButton1(where, x, y, map, size, function, label, hint = None):
    765             return ButtonIcon(name=label, parent=where, align=uiconst.TOPLEFT, pos=(x,
    766              y,
    767              size,
    768              size), texturePath=map, iconSize=size, hint=hint, func=function, args=())
    769 
    770         self.wnd = wnd = Window.Open(windowID=SERVICENAME)
    771         wnd._OnClose = self.Hide
    772         wnd.sr.main = wnd.GetChild('main')
    773         wnd.SetCaption('Poser')
    774         x = const.defaultPadding
    775         y = const.defaultPadding
    776         size = 32
    777         labelwidth = 128
    778         for icon, label, func in [['res:/UI/Texture/Icons/41_64_2.png', 'Assemble Starbase', self.Assemble],
    779          ['res:/UI/Texture/Icons/57_64_14.png', 'Store Starbase', self.Store],
    780          ['res:/UI/Texture/Icons/24_64_5.png', 'Fuel Tower - Cycles', self.Fuel],
    781          ['res:/UI/Texture/Icons/24_64_5.png', 'Fuel Tower - Full', lambda : sm.GetService('slash').SlashCmd('/pos fuel')],
    782          ['res:/UI/Texture/Icons/56_64_2.png', 'Nuke Structures', lambda : sm.GetService('gridutils').NukeStructures()],
    783          ['res:/UI/Texture/Icons/58_64_2.png', 'Anchor All', lambda : sm.GetService('slash').SlashCmd('/pos anchor all')],
    784          ['res:/UI/Texture/Icons/58_64_15.png', 'Unanchor All', lambda : sm.GetService('slash').SlashCmd('/pos unanchor all')],
    785          ['res:/UI/Texture/Icons/41_64_10.png', 'Online All', lambda : sm.GetService('slash').SlashCmd('/pos online all')],
    786          ['res:/UI/Texture/Icons/41_64_11.png', 'Offline All', lambda : sm.GetService('slash').SlashCmd('/pos offline all')],
    787          ['res:/UI/Texture/Icons/23_64_3.png', 'Reinforce', lambda : sm.GetService('slash').SlashCmd('/pos reinforce all')],
    788          ['res:/UI/Texture/Icons/56_64_10.png', 'Interrupt', lambda : sm.GetService('slash').SlashCmd('/pos interrupt all')]]:
    789             MakeButton1(wnd.sr.main, x, y, icon, size, func, label, label)
    790             if ORIENTATION == 0:
    791                 eveLabel.Label(text=label, parent=wnd.sr.main, width=200, left=x + size + 6, top=y + size / 2 - 6, color=None, state=uiconst.UI_DISABLED)
    792                 y += size
    793             else:
    794                 x += size
    795 
    796         if ORIENTATION == 0:
    797             width = 40 + const.defaultPadding + size - 1 + labelwidth + const.defaultPadding
    798             height = 60 + const.defaultPadding + y + const.defaultPadding
    799         else:
    800             width = 20 + const.defaultPadding + x - 1 + const.defaultPadding
    801             height = 60 + const.defaultPadding + size + const.defaultPadding
    802         wnd.SetMinSize([width, height])
    803         wnd.SetFixedWidth(width)
    804         wnd.SetFixedHeight(height)
    805         wnd.MakeUnResizeable()
    806         wnd.Maximize(1)
    807 
    808     def Hide(self, *args):
    809         if self.wnd:
    810             self.wnd.Close()
    811             self.wnd = None
    812 
    813     def ProcessRestartUI(self):
    814         if self.wnd:
    815             self.Hide()
    816             self.Show()
    817 
    818     def Assemble(self, *args):
    819         INSIDERDIR = sm.GetService('insider').GetInsiderDir()
    820         if idCheckers.IsNPC(session.corpid):
    821             info = "You can't be in an NPC corporation and expect to use POS's"
    822             raise UserError('CustomInfo', {'info': info})
    823             return
    824         if not self.RoleCheck(['ROLE_WORLDMOD']):
    825             return
    826         fileList = []
    827         if os.path.exists(INSIDERDIR) == False:
    828             os.mkdir(INSIDERDIR)
    829         else:
    830             files = os.listdir(INSIDERDIR)
    831             for fileName in files:
    832                 if fileName[-4:] == '.pos':
    833                     fileList.append((fileName[:-4], fileName))
    834 
    835         if not fileList:
    836             info = "No '.pos' file found. POSer files must be located in:<br>'%s...'" % INSIDERDIR
    837             raise UserError('CustomInfo', {'info': info})
    838             return
    839         wnd = AssembleWindow.Open(fileList=fileList)
    840         wnd.ShowModal()
    841 
    842     def Store(self, *args):
    843         insiderDir = sm.GetService('insider').GetInsiderDir()
    844         s = Starbase()
    845         s.ImportFromEnvironment()
    846         filename = utilWindows.NamePopup(caption='Store Starbase', label='Enter filename:', setvalue='', maxLength=32)
    847         if not filename:
    848             return
    849         filename = os.path.join(insiderDir, filename)
    850         if not filename:
    851             return
    852         if filename[:4].lower() != '.pos':
    853             filename += '.pos'
    854         s.ExportAsFile(filename)
    855 
    856     def Fuel(self, *args):
    857         wnd = FuelWindow.Open()
    858         wnd.ShowModal()