Issues (229)

client/osci/dialog/StructTaskDlg.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
import math
21
22
import pygameui as ui
23
24
from ige import GameException
25
from ige.ospace import Rules
26
import ige.ospace.Const as Const
27
28
from osci import gdata, client, res
29
from TechInfoDlg import TechInfoDlg
30
from ConfirmDlg import ConfirmDlg
31
32
class StructTaskDlg:
33
34
    def __init__(self, app):
35
        self.app = app
36
        self.showStructures = 1
37
        self.showShips = 0
38
        self.showOther = 0
39
        self.techID = 0
40
        self.sort = 'type'
41
        self.showLevels = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
42
        self.techInfoDlg = TechInfoDlg(app)
43
        self.confirmDlg = ConfirmDlg(app)
44
        self.createUI()
45
46
    def display(self, caller, planetID, extraSlot=False, structToDemolish=Const.OID_NONE):
47
        if gdata.config.defaults.reportfinalization != None:
48
            val = gdata.config.defaults.reportfinalization
49
            self.win.vReportFin.checked = val == 'yes'
50
51
        self.caller = caller
52
        self.systemID = caller.systemID
53
        self.planetID = caller.planetID
54
        self.playerID = client.getPlayerID()
55
        self.sourceID = caller.planetID
56
        self.extraSlot = extraSlot
57
        self.maxTechLevel = 0
58
        self.quantity = 1
59
        self.govTransferConfirm = False
60
        self.govTransferData = None
61
        self.structToDemolish = structToDemolish
62
        self.win.vPlanets.selectItem(None)
63
        self.showPlanets()
64
        self.showTechs()
65
        self.win.show()
66
        gdata.updateDlgs.append(self)
67
68
    def hide(self):
69
        self.win.setStatus(_("Ready."))
70
        if self in gdata.updateDlgs:
71
            gdata.updateDlgs.remove(self)
72
        self.win.hide()
73
74
    def update(self):
75
        if self.win.visible:
76
            self.quantity = int(self.win.vQuantity.text)
77
            self.showPlanets()
78
            self.showTechs()
79
80
    def showPlanets(self):
81
        info = []
82
        system = client.get(self.systemID, noUpdate=1)
83
        select = None
84
        playerID = client.getPlayerID()
85
        firstEnabled = None
86
        if hasattr(system, 'planets'):
87
            for planetID in system.planets:
88
                # get planet
89
                planet = client.get(planetID, noUpdate=1)
90
                # only player owned planets can be source planets
91
                enabled = getattr(planet, "owner") == playerID
92
                buttonText = "%s / %s" % (getattr(planet, 'name', res.getUnknownName()), getattr(planet, "effProdProd", "?"))
93
                item = ui.Item(buttonText,
94
                               planetID=planetID,
95
                               enabled=enabled,
96
                               align=ui.ALIGN_NONE)
97
                info.append(item)
98
                # remember first players planet
99
                if enabled and firstEnabled == None:
100
                    firstEnabled = item
101
102
                # select actual planet as source only if player owns it
103
                if planetID == self.sourceID and enabled:
104
                    select = item
105
106
        # set as selected source first players planet
107
        if select == None:
108
            select = firstEnabled
109
            self.sourceID = firstEnabled.planetID
110
111
        self.win.vPlanets.items = info
112
        self.win.vPlanets.itemsChanged()
113
        self.win.vPlanets.selectItem(select)
114
115
    def _filterStructure(self, tech):
116
        return ((self.win.vMilitary.checked and tech.isMilitary)
117
                or (self.win.vBioProduction.checked and (getattr(tech, "prodBio", 0) or getattr(tech, "prodEnv", 0) > 0))
118
                or (self.win.vEnProduction.checked and getattr(tech, "prodEn", 0))
119
                or (self.win.vCPProduction.checked and getattr(tech, "prodProd", 0))
120
                or (self.win.vRPProduction.checked and getattr(tech, "prodSci", 0))
121
                or (self.win.vMorale.checked and getattr(tech, "moraleTrgt", 0)))
122
123
    def _showStructures(self, prodProd):
124
        items = []
125
126
        for techID in client.getPlayer().techs.keys():
127
            tech = client.getTechInfo(techID)
128
            if not tech.isStructure or tech.level not in self.showLevels or \
129
               (tech.isStructure and not self._filterStructure(tech)):
130
                continue
131
132
            if prodProd > 0:
133
                etc = math.ceil(float(tech.buildProd) / prodProd)
134
                if self.sourceID != self.planetID:
135
                    etc *= Rules.buildOnAnotherPlanetMod
136
                etc = res.formatTime(etc)
137
            else:
138
                etc = _("N/A")
139
140
            item = ui.Item(etc,
141
                           techID=techID,
142
                           tIsShip=0,
143
                           name=tech.name,
144
                           tl=tech.level,
145
                           subtype=tech.subtype,
146
                           icons=((res.getTechImg(techID), ui.ALIGN_N),),
147
                           font="small-bold",
148
                           align=ui.ALIGN_S,
149
                           tooltipTitle=_("Details"),
150
                           tooltip="%s, %d %s, %s %d" % (tech.name, tech.buildProd, _("CP"), _("TL"), tech.level),
151
                           statustip="%s, %d %s, %s %d" % (tech.name, tech.buildProd, _("CP"), _("TL"), tech.level))
152
            self.maxTechLevel = max(self.maxTechLevel, tech.level)
153
            items.append(item)
154
        return items
155
156
    def showTechs(self):
157
        sourcePlanet = client.get(self.sourceID, noUpdate=1)
158
        prodProd = getattr(sourcePlanet, "effProdProd", 0)
159
160
        items = self._showStructures(prodProd)
161
162
        # sort methods
163
        if self.sort == 'none': # sort by name
164
            items.sort(key=lambda a: a.name)
165
        elif self.sort == 'tl': # sort by TL, subsort by name
166
            items.sort(key=lambda a: a.name)
167
            items.sort(key=lambda a: a.tl)
168
        elif self.sort == 'type': #sort by subtype, subsort by tl
169
            items.sort(key=lambda a: a.tl)
170
            items.sort(key=lambda a: a.subtype)
171
        self.win.vTechs.items = items
172
        self.win.vTechs.itemsChanged()
173
174
        # filter
175
        for i in xrange(1, 10):
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable xrange does not seem to be defined.
Loading history...
176
            widget = getattr(self.win, 'vLevel%d' % i)
177
            if i in self.showLevels and i <= self.maxTechLevel:
178
                widget.visible = 1
179
                widget.pressed = 1
180
            elif i not in self.showLevels and i <= self.maxTechLevel:
181
                widget.visible = 1
182
                widget.pressed = 0
183
            else:
184
                widget.visible = 0
185
186
        # quantity
187
        self.win.vQuantity.text = str(self.quantity)
188
189
    def onSelectPlanet(self, widget, action, data):
190
        if data == None:
191
            for item in self.win.vPlanets.items:
192
                if self.sourceID == item.planetID:
193
                    self.win.vPlanets.selectItem(item)
194
                    break
195
            return
196
        self.quantity = int(self.win.vQuantity.text)
197
        self.sourceID = data.planetID
198
        self.showTechs()
199
200
    def onToggleLevel(self, widget, action, data):
201
        i = widget.data
202
        if i in self.showLevels:
203
            self.showLevels.remove(i)
204
        else:
205
            self.showLevels.append(i)
206
        self.update()
207
208
    def onCancel(self, widget, action, data):
209
        self.hide()
210
211
    def onGovTransferConfirmed(self):
212
        # we assume player wants to build just one center - in opposite case, he may change quantity in the task itself
213
        self.win.vQuantity.text = str(1)
214
        self.govTransferConfirm = True
215
        self.onConstruct(*self.govTransferData)
216
217
    def onConstruct(self, widget, action, data):
218
        if not data:
219
            self.win.setStatus(_('Select technology to construct.'))
220
            return
221
222
        if not self.sourceID:
223
            self.sourceID = self.planetID
224
225
        try:
226
            self.quantity = int(self.win.vQuantity.text)
227
        except ValueError:
228
            self.win.setStatus(_('Specify quantity (1, 2, 3, ...).'))
229
            return
230
        # government centers have additional query and if confirmed, another round of this function is called
231
        tech = client.getTechInfo(data.techID)
232
        if tech.govPwr and not self.govTransferConfirm:
233
            # confirm dialog doesn't send through parameters, so we have to save them
234
            self.govTransferData = (widget, action, data)
235
            self.confirmDlg.display(_("Do you want to issue relocation of your government?"),
236
                _("Yes"), _("No"), self.onGovTransferConfirmed)
237
        else:
238
            try:
239
                self.win.setStatus(_('Executing START CONSTRUCTION command...'))
240
                planet = client.get(self.sourceID, noUpdate=1)
241
                player = client.getPlayer()
242
                if self.extraSlot:
243
                    # check required special resources, if not available, do not continue
244
                    # (without check, server start slot expansion but not the tech)
245
                    specialResources = player.stratRes
246
                    for sr in tech.buildSRes:
247
                        if specialResources.get(sr, 0) < self.quantity:
248
                            self.win.setStatus(_('You do not own required strategic resource(s)'))
249
                            return
250
                        else:
251
                            specialResources[sr] = specialResources.get(sr, 0) - self.quantity
252
                    for i in range(1, self.quantity + 1):
253
                        # as we need two slots instead of one, check whether is task queue short
254
                        # enough (ie 8 tasks max)
255
                        if len(planet.prodQueue) > 8:
256
                            self.win.setStatus(_('Queue is full'))
257
                            return
258
                        client.cmdProxy.startConstruction(self.sourceID,
259
                            Rules.Tech.ADDSLOT3, 1, self.planetID, False,
260
                            self.win.vReportFin.checked, Const.OID_NONE)
261
                        planet.prodQueue, player.stratRes = client.cmdProxy.startConstruction(self.sourceID,
262
                            data.techID, 1, self.planetID, data.techID < 1000,
263
                            self.win.vReportFin.checked, self.structToDemolish)
264
                else:
265
                        planet.prodQueue, player.stratRes = client.cmdProxy.startConstruction(self.sourceID,
266
                        data.techID, self.quantity, self.planetID, data.techID < 1000,
267
                        self.win.vReportFin.checked, self.structToDemolish)
268
                self.win.setStatus(_('Command has been executed.'))
269
            except GameException, e:
270
                self.win.setStatus(e.args[0])
271
                return
272
273
        self.win.vTechs.selectItem(None)
274
        self.hide()
275
        self.caller.update()
276
277
    def onInfo(self, widget, action, data):
278
        if data:
279
            self.techInfoDlg.display(data.techID)
280
281
    def onFilter(self, widget, action, data):
282
        self.update()
283
284
    def onSort(self, widget, action, data):
285
        self.sort = widget.data
286
        if widget.data == 'none':
287
            self.win.vSortTL.checked = 0
288
            self.win.vSortType.checked = 0
289
        elif widget.data == 'tl':
290
            self.win.vSortNone.checked = 0
291
            self.win.vSortType.checked = 0
292
        elif widget.data == 'type':
293
            self.win.vSortTL.checked = 0
294
            self.win.vSortNone.checked = 0
295
        self.update()
296
297
    def createUI(self):
298
        w, h = gdata.scrnSize
299
        cols = 32
300
        rows = 20
301
        dlgWidth = cols * 20 + 4
302
        dlgHeight = rows * 20 + 4
303
        self.win = ui.Window(self.app,
304
                             modal=1,
305
                             escKeyClose=1,
306
                             movable=0,
307
                             title=_('Select structure to construct'),
308
                             rect=ui.Rect((w - dlgWidth) / 2, (h - dlgHeight) / 2, dlgWidth, dlgHeight),
309
                             layoutManager=ui.SimpleGridLM())
310
        self.win.subscribeAction('*', self)
311
        rows -= 1 # title
312
313
        ui.Title(self.win, layout=(0, 0, cols, 1), text=_('Production planet'),
314
                 align=ui.ALIGN_W, font='normal-bold')
315
        ui.ButtonArray(self.win, layout=(0, 1, cols, 3), id='vPlanets',
316
                       buttonSize=(8, 1), showSlider=0, action='onSelectPlanet')
317
318
        ui.Title(self.win, layout=(0, 4, cols - 10, 1), text=_('Structures to construct'),
319
                 align=ui.ALIGN_W, font='normal-bold')
320
        ui.Title(self.win, layout=(cols - 10, 4, 10, 1), text=_('(right click for technology info)'),
321
                 align=ui.ALIGN_E, font='normal')
322
        ui.ButtonArray(self.win, layout=(0, 5, cols, 9), id='vTechs',
323
                       buttonSize=(2, 3), showSlider=0, action='onConstruct', rmbAction='onInfo')
324
325
        ui.Title(self.win, layout=(0, 14, 18, 1), text=_('Filters'),
326
                 align=ui.ALIGN_W, font='normal-bold')
327
        ui.Label(self.win, layout=(0, 15, 6, 1), text=_('Technology levels:'), align=ui.ALIGN_W)
328
        ui.Button(self.win, layout=(6, 15, 1, 1), text=_('1'), id='vLevel1',
329
                  toggle=1, action='onToggleLevel', data=1)
330
        ui.Button(self.win, layout=(7, 15, 1, 1), text=_('2'), id='vLevel2',
331
                  toggle=1, action='onToggleLevel', data=2)
332
        ui.Button(self.win, layout=(8, 15, 1, 1), text=_('3'), id='vLevel3',
333
                  toggle=1, action='onToggleLevel', data=3)
334
        ui.Button(self.win, layout=(9, 15, 1, 1), text=_('4'), id='vLevel4',
335
                  toggle=1, action='onToggleLevel', data=4)
336
        ui.Button(self.win, layout=(10, 15, 1, 1), text=_('5'), id='vLevel5',
337
                  toggle=1, action='onToggleLevel', data=5)
338
        ui.Button(self.win, layout=(11, 15, 1, 1), text=_('6'), id='vLevel6',
339
                  toggle=1, action='onToggleLevel', data=6)
340
        ui.Button(self.win, layout=(12, 15, 1, 1), text=_('7'), id='vLevel7',
341
                  toggle=1, action='onToggleLevel', data=7)
342
        ui.Button(self.win, layout=(13, 15, 1, 1), text=_('8'), id='vLevel8',
343
                  toggle=1, action='onToggleLevel', data=8)
344
        ui.Button(self.win, layout=(14, 15, 1, 1), text=_('9'), id='vLevel9',
345
                  toggle=1, action='onToggleLevel', data=9)
346
347
        ui.Check(self.win, layout=(0, 16, 6, 1), text=_('Bio production'),
348
                 id='vBioProduction', checked=1, align=ui.ALIGN_W, action='onFilter')
349
        ui.Check(self.win, layout=(0, 17, 6, 1), text=_('En production'),
350
                 id='vEnProduction', checked=1, align=ui.ALIGN_W, action='onFilter')
351
        ui.Check(self.win, layout=(6, 16, 6, 1), text=_('CP production'),
352
                 id='vCPProduction', checked=1, align=ui.ALIGN_W, action='onFilter')
353
        ui.Check(self.win, layout=(6, 17, 6, 1), text=_('RP production'),
354
                 id='vRPProduction', checked=1, align=ui.ALIGN_W, action='onFilter')
355
        ui.Check(self.win, layout=(12, 16, 6, 1), text=_('Military'),
356
                 id='vMilitary', checked=1, align=ui.ALIGN_W, action='onFilter')
357
        ui.Check(self.win, layout=(12, 17, 6, 1), text=_('Morale'),
358
                 id='vMorale', checked=1, align=ui.ALIGN_W, action='onFilter')
359
360
        ui.Title(self.win, layout=(18, 14, 6, 1), text=_('Sort'),
361
                 align=ui.ALIGN_W, font='normal-bold')
362
        ui.Check(self.win, layout=(18, 15, 6, 1), text=_('Type'),
363
                 id='vSortType', checked=1, align=ui.ALIGN_W, action='onSort', data='type')
364
        ui.Check(self.win, layout=(18, 16, 6, 1), text=_('Tech Level'),
365
                 id='vSortTL', checked=0, align=ui.ALIGN_W, action='onSort', data='tl')
366
        ui.Check(self.win, layout=(18, 17, 6, 1), text=_('Name'),
367
                 id='vSortNone', checked=0, align=ui.ALIGN_W, action='onSort', data='none')
368
369
        ui.Title(self.win, layout=(24, 14, 8, 1), text=_('Options'),
370
                 align=ui.ALIGN_W, font='normal-bold')
371
        ui.Label(self.win, layout=(24, 15, 3, 1), text=_('Quantity'), align=ui.ALIGN_W)
372
        ui.Entry(self.win, layout=(27, 15, 5, 1), id='vQuantity', align=ui.ALIGN_E)
373
        ui.Check(self.win, layout=(26, 16, 8, 1), id='vReportFin', text=_('Report finalization'),
374
                 align=ui.ALIGN_W)
375
376
        ui.Title(self.win, layout=(0, rows - 1, cols - 5, 1), align=ui.ALIGN_W)
377
        ui.TitleButton(self.win, layout=(cols - 5, rows - 1, 5, 1), text=_('Cancel'), action='onCancel')
378