Issues (229)

client/osci/dialog/NewTaskDlg.py (1 issue)

1
#
2
#  Copyright 2001 - 2016 Ludek Smid [http://www.ospace.net/]
3
#
4
#  This file is part of Outer Space.
5
#
6
#  Outer Space is free software; you can redistribute it and/or modify
7
#  it under the terms of the GNU General Public License as published by
8
#  the Free Software Foundation; either version 2 of the License, or
9
#  (at your option) any later version.
10
#
11
#  Outer Space is distributed in the hope that it will be useful,
12
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
13
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
#  GNU General Public License for more details.
15
#
16
#  You should have received a copy of the GNU General Public License
17
#  along with Outer Space; if not, write to the Free Software
18
#  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19
#
20
21
import math
22
23
import pygameui as ui
24
25
from ige import GameException
26
from ige.ospace import Rules
27
import ige.ospace.Const as Const
28
29
from osci import gdata, client, res
30
from TechInfoDlg import TechInfoDlg
31
from ConstructionDlg import ConstructionDlg
32
from ConfirmDlg import ConfirmDlg
33
import Utils
34
35
36
class NewTaskDlg:
37
38
    def __init__(self, app):
39
        self.app = app
40
        self.showStructures = 1
41
        self.showShips = 0
42
        self.showOther = 0
43
        self.techID = 0
44
        self.showLevels = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 99]
45
        self.techInfoDlg = TechInfoDlg(app)
46
        self.constructionDlg = ConstructionDlg(app)
47
        self.confirmDlg = ConfirmDlg(app)
48
        self.createUI()
49
        self.win.setTagAttr('struct', 'visible', 1)
50
        self.win.setTagAttr('ship', 'visible', 0)
51
        # set default sorting for technologies
52
        self.win.vTechs.setSort("text")
53
54
    def display(self, caller, prodProd, structToDemolish=Const.OID_NONE):
55
        if gdata.config.defaults.reportfinalization != None:
56
            val = gdata.config.defaults.reportfinalization
57
            self.win.vReportFin.checked = val == 'yes'
58
59
        self.caller = caller
60
        self.systemID = caller.systemID
61
        self.planetID = caller.planetID
62
        self.playerID = client.getPlayerID()
63
        self.targetID = caller.planetID
64
        self.maxTechLevel = 0
65
        self.quantity = 1
66
        self.govTransferConfirm = False
67
        self.govTransferData = None
68
        self.prodProd = prodProd
69
        self.structToDemolish = structToDemolish
70
        self.showTechs()
71
        self.showSlots()
72
        self.win.show()
73
        gdata.updateDlgs.append(self)
74
75
    def hide(self):
76
        self.win.setStatus(_("Ready."))
77
        if self in gdata.updateDlgs:
78
            gdata.updateDlgs.remove(self)
79
        self.win.hide()
80
81
    def update(self):
82
        if self.win.visible:
83
            self.quantity = int(self.win.vQuantity.text)
84
            if self.showShips:
85
                self.win.vInfo.enabled = Utils.enableConstruction(client)
86
            self.showTechs()
87
            self.showSlots()
88
89
    def _processNonShips(self, tech):
90
        if self.prodProd > 0:
91
            etc = math.ceil(float(tech.buildProd) / self.prodProd)
92
            if self.targetID != self.planetID:
93
                etc *= Rules.buildOnAnotherPlanetMod
94
            etc = res.formatTime(etc)
95
        else:
96
            etc = _("N/A")
97
98
        item = ui.Item(tech.name,
99
                       tLevel=tech.level,
100
                       tProd=tech.buildProd,
101
                       techID=tech.id,
102
                       tIsShip=0,
103
                       tETC=etc)
104
        self.maxTechLevel = max(self.maxTechLevel, tech.level)
105
106
        return item
107
108
    def _filterStructure(self, tech):
109
        return ((self.win.vMilitary.checked and tech.isMilitary)
110
                or (self.win.vBioProduction.checked and (getattr(tech, "prodBio", 0) or getattr(tech, "prodEnv", 0) > 0))
111
                or (self.win.vEnProduction.checked and getattr(tech, "prodEn", 0))
112
                or (self.win.vCPProduction.checked and getattr(tech, "prodProd", 0))
113
                or (self.win.vRPProduction.checked and getattr(tech, "prodSci", 0))
114
                or (self.win.vMorale.checked and getattr(tech, "moraleTrgt", 0)))
115
116
    def _filterShipSize(self, tech):
117
        return ((self.win.vSmall.checked and tech.combatClass == 0)
118
                or (self.win.vMedium.checked and tech.combatClass == 1)
119
                or (self.win.vLarge.checked and tech.combatClass == 2))
120
121
    def _filterShipMilitary(self, tech):
122
        return ((self.win.vMilShip.checked and tech.isMilitary)
123
                or (self.win.vCivShip.checked and not tech.isMilitary))
124
125
    def _showStructures(self):
126
        items = []
127
128
        for techID in client.getPlayer().techs.keys():
129
            tech = client.getTechInfo(techID)
130
            if not tech.isStructure or tech.level not in self.showLevels or \
131
               (tech.isStructure and not self._filterStructure(tech)):
132
                continue
133
            items.append(self._processNonShips(tech))
134
135
        return items
136
137
    def _showProjects(self):
138
        items = []
139
        for techID in client.getPlayer().techs.keys():
140
            tech = client.getTechInfo(techID)
141
            if tech.level not in self.showLevels or not tech.isProject:
142
                continue
143
            items.append(self._processNonShips(tech))
144
145
        return items
146
147
    def _showShips(self):
148
        items = []
149
        player = client.getPlayer()
150
151
        for designID in player.shipDesigns.keys():
152
            tech = player.shipDesigns[designID]
153
            if not self._filterShipSize(tech) or not self._filterShipMilitary(tech):
154
                continue
155
156
            if tech.upgradeTo != Const.OID_NONE:
157
                # skip ships that are set to upgrade
158
                continue
159
            if self.prodProd > 0:
160
                etc = res.formatTime(math.ceil(float(tech.buildProd) / self.prodProd))
161
            else:
162
                etc = _("N/A")
163
            item = ui.Item(tech.name,
164
                           tLevel=tech.level,
165
                           tProd=tech.buildProd,
166
                           techID=designID,
167
                           tIsShip=1,
168
                           tETC=etc)
169
            items.append(item)
170
        return items
171
172
    def _processTarget(self, planet):
173
        ownerName = res.getUnknownName()
174
        ownerID = Const.OID_NONE
175
        if hasattr(planet, 'owner'):
176
            ownerID = planet.owner
177
            if planet.owner != Const.OID_NONE:
178
                ownerName = client.get(planet.owner, noUpdate=1).name
179
        if planet.plType in ("A", "G"):
180
            color = gdata.sevColors[gdata.DISABLED]
181
        else:
182
            color = res.getPlayerColor(ownerID)
183
        plname = getattr(planet, 'name', res.getUnknownName())
184
        item = ui.Item(plname,
185
                       text_raw=getattr(planet, 'plEn', plname),
186
                       planetID=planet.oid,
187
                       plOwner=ownerName,
188
                       foreground=color)
189
        return item
190
191
    def showTechs(self):
192
        # techs
193
        items = []
194
195
        if self.showStructures:
196
            items += self._showStructures()
197
        if self.showShips:
198
            items += self._showShips()
199
        if self.showOther:
200
            items += self._showProjects()
201
202
        # sort it by level and then by name
203
        items.sort(key=lambda a: (100 - a.tLevel, a.text))
204
        self.win.vTechs.items = items
205
        self.win.vTechs.itemsChanged()
206
        # preserve selection
207
        for item in items:
208
            if self.techID == item.techID:
209
                self.win.vTechs.selectItem(item)
210
                break
211
        # tech level filter
212
        for i in range(1, 7):
213
            widget = getattr(self.win, 'vLevel%d' % i)
214
            if i in self.showLevels and i <= self.maxTechLevel:
215
                widget.visible = 1
216
                widget.pressed = 1
217
            elif i not in self.showLevels and i <= self.maxTechLevel:
218
                widget.visible = 1
219
                widget.pressed = 0
220
            else:
221
                widget.visible = 0
222
        self.win.vStructuresToggle.pressed = self.showStructures
223
        self.win.vShipsToggle.pressed = self.showShips
224
        self.win.vOtherToggle.pressed = self.showOther
225
        # targets
226
        info = []
227
        system = client.get(self.systemID, noUpdate=1)
228
        for planetID in system.planets:
229
            planet = client.get(planetID, noUpdate=1)
230
            info.append(self._processTarget(planet))
231
        self.win.vTargets.items = info
232
        self.win.vTargets.itemsChanged()
233
        for item in info:
234
            if self.targetID == item.planetID:
235
                self.win.vTargets.selectItem(item)
236
                break
237
        # quantity
238
        self.win.vQuantity.text = str(self.quantity)
239
240 View Code Duplication
    def showSlots(self):
0 ignored issues
show
This code seems to be duplicated in your project.
Loading history...
241
        # techs
242
        items = []
243
        techs = {}
244
        if self.showStructures:
245
            player = client.getPlayer()
246
            target = client.get(self.targetID, noUpdate=1)
247
            if hasattr(target, 'slots') and target.owner == player.oid:
248
                if len(target.slots) < target.plSlots:
249
                    item = ui.Item(_("Free slot"), techID=0)
250
                    items.append(item)
251
                for struct in target.slots:
252
                    if not struct[Const.STRUCT_IDX_TECHID] in techs:
253
                        techs[struct[Const.STRUCT_IDX_TECHID]] = 1
254
                    else:
255
                        techs[struct[Const.STRUCT_IDX_TECHID]] += 1
256
                for tech in techs.keys():
257
                    techInfo = client.getTechInfo(tech)
258
                    item = ui.Item("%s (%d)" % (techInfo.name, techs[tech]), techID=tech)
259
                    items.append(item)
260
261
        self.win.vTSlots.items = items
262
        self.win.vTSlots.itemsChanged()
263
        self.structToDemolish = Const.OID_NONE
264
265
    def onSelectPlanet(self, widget, action, data):
266
        self.quantity = int(self.win.vQuantity.text)
267
        self.targetID = data.planetID
268
        self.showTechs()
269
        self.showSlots()
270
271
    def onSelectSlot(self, widget, action, data):
272
        self.structToDemolish = data.techID
273
274
    def onSelectTech(self, widget, action, data):
275
        self.techID = data.techID
276
277
    def onToggleLevel(self, widget, action, data):
278
        i = widget.data
279
        if i in self.showLevels:
280
            self.showLevels.remove(i)
281
        else:
282
            self.showLevels.append(i)
283
        self.update()
284
285
    def onCancel(self, widget, action, data):
286
        self.hide()
287
288
    def onGovTransferConfirmed(self):
289
        # we assume player wants to build just one center - in opposite case, he may change quantity in the task itself
290
        self.win.vQuantity.text = str(1)
291
        self.govTransferConfirm = True
292
        self.onConstruct(*self.govTransferData)
293
294
    def onConstruct(self, widget, action, data):
295
        planet = client.get(self.planetID, noUpdate=1)
296
        player = client.getPlayer()
297
        if not self.techID:
298
            self.win.setStatus(_('Select technology to construct.'))
299
            return
300
        if not self.targetID:
301
            self.win.setStatus(_('Select planet to construct on.'))
302
            return
303
        try:
304
            self.quantity = int(self.win.vQuantity.text)
305
        except ValueError:
306
            self.win.setStatus(_('Specify quantity (1, 2, 3, ...).'))
307
            return
308
        # government centers have additional query and if confirmed, another round of this function is called
309
        if self.techID < 1000:
310
            tech = player.shipDesigns[self.techID]
311
        else:
312
            tech = client.getTechInfo(self.techID)
313
        if not getattr(tech, 'govPwr', 0) == 0 and not self.govTransferConfirm:
314
            # confirm dialog doesn't send through parameters, so we have to save them
315
            self.govTransferData = (widget, action, data)
316
            self.confirmDlg.display(_("Do you want to issue relocation of your government?"),
317
                _("Yes"), _("No"), self.onGovTransferConfirmed)
318
        else:
319
            try:
320
                self.win.setStatus(_('Executing START CONSTRUCTION command...'))
321
                planet.prodQueue, player.stratRes = client.cmdProxy.startConstruction(self.planetID,
322
                    self.techID, self.quantity, self.targetID, self.techID < 1000,
323
                    self.win.vReportFin.checked, self.structToDemolish)
324
                self.win.setStatus(_('Command has been executed.'))
325
            except GameException, e:
326
                self.win.setStatus(e.args[0])
327
                return
328
        self.hide()
329
        self.caller.update()
330
331
    def onToggleStructures(self, widget, action, data):
332
        self.showStructures = 1
333
        self.showShips = 0
334
        self.showOther = 0
335
        self.win.setTagAttr('struct', 'visible', 1)
336
        self.win.setTagAttr('ship', 'visible', 0)
337
        self.update()
338
339
    def onToggleShips(self, widget, action, data):
340
        self.showStructures = 0
341
        self.showShips = 1
342
        self.showOther = 0
343
        self.win.setTagAttr('struct', 'visible', 0)
344
        self.win.setTagAttr('ship', 'visible', 1)
345
        self.update()
346
347
    def onToggleOther(self, widget, action, data):
348
        self.showStructures = 0
349
        self.showShips = 0
350
        self.showOther = 1
351
        self.win.setTagAttr('struct', 'visible', 0)
352
        self.win.setTagAttr('ship', 'visible', 0)
353
        self.update()
354
355
    def onInfo(self, widget, action, data):
356
        if len(self.win.vTechs.selection) == 0:
357
            return
358
        task = self.win.vTechs.selection[0]
359
        if not task.tIsShip:
360
            self.techInfoDlg.display(task.techID)
361
        else:
362
            self.constructionDlg.selectedDesignID = task.techID;
363
            self.constructionDlg.display()
364
365
    def onFilter(self, widget, action, data):
366
        self.update()
367
368
    def createUI(self):
369
        w, h = gdata.scrnSize
370
        cols = 38
371
        rows = 24 #was 23
372
        dlgWidth = cols * 20 + 4
373
        dlgHeight = rows * 20 + 4
374
        self.win = ui.Window(self.app,
375
                             modal=1,
376
                             escKeyClose=1,
377
                             movable=0,
378
                             title=_('Select new task'),
379
                             rect=ui.Rect((w - dlgWidth) / 2, (h - dlgHeight) / 2, dlgWidth, dlgHeight),
380
                             layoutManager=ui.SimpleGridLM(),
381
                             tabChange=True)
382
        self.win.subscribeAction('*', self)
383
        ui.Title(self.win, layout=(0, 0, 22, 1), text=_('Technology'),
384
                 align=ui.ALIGN_W, font='normal-bold')
385
        ui.Listbox(self.win, layout=(0, 1, 22, 19), id='vTechs',
386
                   columns=((_('Name'), 'text', 13, ui.ALIGN_W), (_('Lvl'), 'tLevel', 2, ui.ALIGN_E),
387
                   (_('Constr'), 'tProd', 3, ui.ALIGN_E), (_('ETC'), 'tETC', 3, ui.ALIGN_E)),
388
                   columnLabels=1, action='onSelectTech')
389
        # filter
390
        ui.Button(self.win, layout=(0, 20, 3, 1), text=_('Stucts'), toggle=1,
391
                  id='vStructuresToggle', action='onToggleStructures')
392
        ui.Button(self.win, layout=(3, 20, 3, 1), text=_('Ships'), toggle=1,
393
                  id='vShipsToggle', action='onToggleShips')
394
        ui.Button(self.win, layout=(6, 20, 3, 1), text=_('Misc'), toggle=1,
395
                  id='vOtherToggle', action='onToggleOther')
396
        ui.Button(self.win, layout=(9, 20, 1, 1), text=_('1'), id='vLevel1',
397
                  toggle=1, action='onToggleLevel', data=1)
398
        ui.Button(self.win, layout=(10, 20, 1, 1), text=_('2'), id='vLevel2',
399
                  toggle=1, action='onToggleLevel', data=2)
400
        ui.Button(self.win, layout=(11, 20, 1, 1), text=_('3'), id='vLevel3',
401
                  toggle=1, action='onToggleLevel', data=3)
402
        ui.Button(self.win, layout=(12, 20, 1, 1), text=_('4'), id='vLevel4',
403
                  toggle=1, action='onToggleLevel', data=4)
404
        ui.Button(self.win, layout=(13, 20, 1, 1), text=_('5'), id='vLevel5',
405
                  toggle=1, action='onToggleLevel', data=5)
406
        ui.Button(self.win, layout=(14, 20, 1, 1), text=_('6'), id='vLevel6',
407
                  toggle=1, action='onToggleLevel', data=6)
408
        ui.Button(self.win, layout=(18, 20, 4, 1), text=_('Info'), action='onInfo',
409
                  id='vInfo')
410
        # targets
411
        ui.Title(self.win, layout=(22, 0, 16, 1), text=_('Target planet'),
412
                 align=ui.ALIGN_W, font='normal-bold')
413
        ui.Listbox(self.win, layout=(22, 1, 16, 10), id='vTargets',
414
                   columns=((_('Planet'), 'text', 10, ui.ALIGN_W), (_('Owner'), 'plOwner', 5, ui.ALIGN_W)), columnLabels=1,
415
                   action='onSelectPlanet')
416
        ui.Listbox(self.win, layout=(22, 11, 16, 7), id='vTSlots',
417
                   columns=((_('Target slots'), 'text', 15, ui.ALIGN_W), ), columnLabels=1,
418
                   action='onSelectSlot')
419
        # prod types
420
        ui.Check(self.win, layout=(0, 21, 6, 1), text=_('Bio production'), tags=['struct'],
421
                 id='vBioProduction', checked=1, align=ui.ALIGN_W, action='onFilter')
422
        ui.Check(self.win, layout=(6, 21, 6, 1), text=_('En production'), tags=['struct'],
423
                 id='vEnProduction', checked=1, align=ui.ALIGN_W, action='onFilter')
424
        ui.Check(self.win, layout=(12, 21, 6, 1), text=_('CP production'), tags=['struct'],
425
                 id='vCPProduction', checked=1, align=ui.ALIGN_W, action='onFilter')
426
        ui.Check(self.win, layout=(18, 21, 6, 1), text=_('RP production'), tags=['struct'],
427
                 id='vRPProduction', checked=1, align=ui.ALIGN_W, action='onFilter')
428
        ui.Check(self.win, layout=(24, 21, 6, 1), text=_('Military'), tags=['struct'],
429
                 id='vMilitary', checked=1, align=ui.ALIGN_W, action='onFilter')
430
        ui.Check(self.win, layout=(30, 21, 6, 1), text=_('Morale'), tags=['struct'],
431
                 id='vMorale', checked=1, align=ui.ALIGN_W, action='onFilter')
432
        # ship types
433
        ui.Check(self.win, layout=(0, 21, 6, 1), text=_('Small'), tags=['ship'],
434
                 id='vSmall', checked=1, align=ui.ALIGN_W, action='onFilter')
435
        ui.Check(self.win, layout=(6, 21, 6, 1), text=_('Medium'), tags=['ship'],
436
                 id='vMedium', checked=1, align=ui.ALIGN_W, action='onFilter')
437
        ui.Check(self.win, layout=(12, 21, 6, 1), text=_('Large'), tags=['ship'],
438
                 id='vLarge', checked=1, align=ui.ALIGN_W, action='onFilter')
439
        ui.Check(self.win, layout=(18, 21, 6, 1), text=_('Civilian'), tags=['ship'],
440
                 id='vCivShip', checked=1, align=ui.ALIGN_W, action='onFilter')
441
        ui.Check(self.win, layout=(24, 21, 6, 1), text=_('Military'), tags=['ship'],
442
                 id='vMilShip', checked=1, align=ui.ALIGN_W, action='onFilter')
443
        # build
444
        ui.Title(self.win, layout=(22, 18, 16, 1), text=_('Options'),
445
                 align=ui.ALIGN_W, font='normal-bold')
446
        ui.Label(self.win, layout=(22, 19, 10, 1), text=_('Quantity'), align=ui.ALIGN_W)
447
        ui.Entry(self.win, layout=(33, 19, 5, 1), id='vQuantity', align=ui.ALIGN_E, orderNo=1)
448
        ui.Check(self.win, layout=(31, 20, 7, 1), id='vReportFin', text=_('Report finalization'))
449
        ui.Title(self.win, layout=(0, 22, 28, 1), id='vStatusBar', align=ui.ALIGN_W)
450
        ui.TitleButton(self.win, layout=(28, 22, 5, 1), text=_('Cancel'), action='onCancel')
451
        ui.TitleButton(self.win, layout=(33, 22, 5, 1), text=_('Construct'), action='onConstruct')
452