Completed
Pull Request — master (#192)
by Marek
01:39
created

osci.dialog.TechInfoDlg.structWeapons2Text()   A

Complexity

Conditions 5

Size

Total Lines 15
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
eloc 15
nop 1
dl 0
loc 15
rs 9.1832
c 0
b 0
f 0
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 pygameui as ui
22
from osci import gdata, res, client
23
import ige.ospace.Const as Const
24
from ige.ospace import Rules, Utils
25
import string
26
27
def cclass2Text(cclass):
28
    return [_("small"), _("medium"), _("large"), _("planet")][cclass]
29
30
def structWeapons2Text(array):
31
    string = ''
32
    i = 0
33
    j = 0
34
    for weaponNum in array:
35
        if i>3:
36
            break
37
        if weaponNum > 0:
38
            if j > 0:
39
                string += _(', ')
40
            string += _('%d') % ( weaponNum )
41
            string += [_("S"), _("M"), _("L"), _("P"), _("?"),_("?"),_("?"),_("?"),_("?"),_("?")][i]
42
            j+=1
43
        i+=1
44
    return string
45
46
def bool2Text(value):
47
    if value:
48
        return _("Yes")
49
    else:
50
        return _("No")
51
52
def perc2Text(value):
53
    string = _('%d%%') % (value * 100)
54
    return string
55
56
def percBase1_2Text(value):
57
    value = value-1
58
    string = _('%+d%%') % (value * 100)
59
    return string
60
61
def perc100_2Text(value):
62
    string = _('%d%%') % (value)
63
    return string
64
65
def getTechName(techid):
66
    try:
67
        tech = client.getFullTechInfo(techid)
68
        return tech.name
69
    except:
70
        return _('Unknown')
71
72
def getTechShortname(techid):
73
    try:
74
        tech = client.getFullTechInfo(techid)
75
        if (tech.shortname != ''):
76
            return tech.shortname
77
        return tech.name
78
    except:
79
        return _('Unknown')
80
81
def getRateName(rate):
82
    string = _('%d Turns') % (int(rate))
83
    return string
84
85
V_NONE = 0x00
86
V_STRUCT = 0x01
87
V_HULL = 0x02
88
V_SEQUIP = 0x04
89
V_PROJECT = 0x08
90
V_EFF = 0x10 # attr * techEff
91
V_EFF_REV = 0x20 # attr / techEff
92
V_ALL = V_STRUCT|V_HULL|V_SEQUIP|V_PROJECT
93
94
techAttrs = {}
95
96
defaultAttr = (_('Not specified'), V_NONE, True, None, int)
97
98
def addAttr(attr, descr, props, showIfDefault, default = 0, convertor = int):
99
    global techAttrs
100
    techAttrs[attr] = (descr, props, showIfDefault, default, convertor)
101
102
103
addAttr('buildProd', _('Constr. reqs - construction points'), V_ALL, 0)
104
105
addAttr('operBio', _('Operational reqs - biomatter'), V_ALL, 0)
106
addAttr('operMin', _('Operational reqs - minerals'), V_ALL, 0)
107
addAttr('operEn', _('Operational reqs - energy'), V_ALL, 0)
108
addAttr('operWorkers', _('Operational reqs - workers'), V_ALL, 0)
109
110
addAttr('prodBio', _('Production - biomatter'), V_STRUCT|V_EFF, 0)
111
addAttr('prodMin', _('Production - minerals'), V_STRUCT|V_EFF, 0)
112
addAttr('prodEn', _('Production - energy'), V_STRUCT|V_EFF, 0)
113
addAttr('prodPop', _('Production - population'), V_STRUCT|V_EFF, 0)
114
addAttr('prodProd', _('Production - constr. points'), V_STRUCT|V_PROJECT|V_EFF, 0)
115
addAttr('prodSci', _('Production - research points'), V_STRUCT|V_PROJECT|V_EFF, 0)
116
addAttr('prodEnv', _('Production - env. effect'), V_STRUCT|V_EFF, 0)
117
118
addAttr('solarMod', _('Orbital Shift Effect'), V_STRUCT|V_EFF, 0)
119
120
addAttr('storBio', _('Storage - biomatter'), V_STRUCT|V_EFF, 0)
121
addAttr('storMin', _('Storage - minerals'), V_STRUCT|V_EFF, 0)
122
addAttr('storEn', _('Storage - energy'), V_ALL|V_EFF, 0)
123
addAttr('storPop', _('Accommodate population'), V_STRUCT|V_EFF, 0)
124
125
addAttr('revoltThr', _('Lowers revolt threshold by'), V_STRUCT|V_PROJECT|V_EFF, 0)
126
addAttr('moraleTrgt', _('Increases max morale by'), V_STRUCT|V_PROJECT|V_EFF, 0)
127
addAttr('govPwr', _('Government power'), V_STRUCT|V_EFF, 0)
128
addAttr('maxHP', _('Hit points'), V_STRUCT|V_HULL|V_SEQUIP|V_EFF, 0)
129
130
addAttr('scannerPwr', _('Scanner power'), V_STRUCT|V_SEQUIP|V_EFF, 0)
131
addAttr('planetShield',_('Planetary shield'), V_STRUCT|V_EFF, 0)
132
addAttr('systemAtt',_('Fleet attack (bonus)'), V_STRUCT|V_EFF, 0)
133
addAttr('systemDef',_('Fleet defense (bonus)'), V_STRUCT|V_EFF, 0)
134
addAttr('refuelMax', _('Maximum refuel percent'), V_STRUCT|V_EFF, 0, convertor = perc100_2Text)
135
addAttr('refuelInc', _('Refuel increase percent'), V_STRUCT|V_EFF, 0, convertor = perc100_2Text)
136
addAttr('trainShipInc', _('Exp. points per turn'), V_STRUCT|V_EFF, 0, convertor = float)
137
addAttr('trainShipMax', _('Exp. cap (base exp multiple)'), V_STRUCT|V_EFF, 0)
138
addAttr('fleetSpeedBoost', _('Boost speed of fleets'), V_STRUCT|V_EFF, 0, convertor = float)
139
addAttr('structWeapons', _('Weapons'), V_STRUCT, 0, convertor = structWeapons2Text)
140
141
addAttr('weaponClass', _('Target class'), V_SEQUIP, True, convertor = cclass2Text)
142
addAttr('weaponDmgMin', _('Weapon minimum damage'), V_SEQUIP|V_EFF, 0)
143
addAttr('weaponDmgMax', _('Weapon maximum damage'), V_SEQUIP|V_EFF, 0)
144
addAttr('weaponIsMissile', _('Missile weapon (ECM counts)'), V_SEQUIP|V_HULL, 0, convertor = bool2Text)
145
addAttr('weaponIgnoreShield', _('Weapon ignore shield'), V_SEQUIP|V_HULL, 0, convertor = bool2Text)
146
addAttr('weaponAtt', _('Weapon attack'), V_SEQUIP|V_EFF, 0)
147
addAttr('weaponROF', _('Weapon Rate Of Fire'), V_SEQUIP, 0, convertor = float)
148
149
addAttr('mineclass', _('Mine Class Deployed'), V_STRUCT, 0, convertor = getTechShortname)
150
addAttr('minenum', _('Maximum Supported Mines'), V_STRUCT|V_EFF, 0, convertor = int)
151
addAttr('minerate', _('Mine Rate of Deploy'), V_STRUCT|V_EFF_REV, 0, convertor = getRateName)
152
153
addAttr('minHull', _('Minimum required hull'), V_SEQUIP|V_HULL, 0, convertor = cclass2Text)
154
addAttr('weight', _('Weight'), V_SEQUIP|V_HULL, 0)
155
addAttr('slots', _('Slots'), V_SEQUIP|V_HULL, 0)
156
addAttr('maxWeight', _('Maximum payload'), V_HULL, 0)
157
addAttr('engPwr', _('Engine power'), V_SEQUIP|V_EFF, 0)
158
159
addAttr('signature', _('Scan signature'), V_SEQUIP|V_HULL, 0)
160
addAttr('signatureCloak', _('Signature visibility'), V_SEQUIP|V_HULL, 0)
161
addAttr('signatureDecloak', _('Signature visibility'), V_SEQUIP|V_HULL, 0)
162
addAttr('minSignature', _('Min. signature'), V_SEQUIP|V_HULL, 0)
163
164
addAttr('combatDef', _('Combat defence'), V_SEQUIP|V_HULL|V_EFF, 0)
165
addAttr('combatAtt', _('Combat attack'), V_SEQUIP|V_HULL|V_EFF, 0)
166
addAttr('missileDef', _('Missile defence'), V_SEQUIP|V_EFF, 0)
167
addAttr('combatAttPerc', _('Combat defense (extra)'), V_SEQUIP|V_HULL|V_EFF, 0, default=1, convertor = percBase1_2Text)
168
addAttr('combatDefPerc', _('Combat attack (extra)'), V_SEQUIP|V_HULL|V_EFF, 0, default=1, convertor = percBase1_2Text)
169
addAttr('missileDefPerc', _('Missile defence (extra)'), V_SEQUIP|V_EFF, 0, default=1, convertor = percBase1_2Text)
170
171
addAttr('shieldPerc', _('Shield strength'), V_SEQUIP|V_HULL|V_EFF, 0, convertor = perc2Text)
172
addAttr('shieldRechargeFix', _('Shield recharge fixed'), V_SEQUIP|V_HULL|V_EFF, 0)
173
addAttr('shieldRechargePerc', _('Shield recharge percent'), V_SEQUIP|V_HULL|V_EFF, 0, convertor = perc2Text)
174
addAttr('damageAbsorb', _('Armor damage absorbstion'), V_SEQUIP|V_HULL, 0)
175
176
addAttr('addMP', _('Device MP'), V_SEQUIP|V_HULL, 0)
177
178
179
class TechInfoDlg:
180
181
    def __init__(self, app):
182
        self.app = app
183
        self.techType = V_NONE
184
        self.createUI()
185
186
    def display(self, techID):
187
        self.techID = techID
188
        self.show()
189
        self.win.show()
190
        # register for updates
191
        if self not in gdata.updateDlgs:
192
            gdata.updateDlgs.append(self)
193
194
    def hide(self):
195
        self.win.setStatus(_("Ready."))
196
        self.win.hide()
197
        # unregister updates
198
        if self in gdata.updateDlgs:
199
            gdata.updateDlgs.remove(self)
200
201
    def update(self):
202
        self.show()
203
204
    def show(self):
205
        tech = client.getTechInfo(self.techID)
206
        player = client.getPlayer()
207
        techEff = Rules.techImprEff[player.techs.get(self.techID, Rules.techBaseImprovement)]
208
        self.win.title = _('Technology: %s (TL%d)') % (tech.name, tech.level)
209
        # fill data
210
        # fill description
211
        descr = []
212
        improvement = player.techs.get(self.techID, 0)
213
        if hasattr(tech, 'researchMod'):
214
            if improvement == 0:
215
                descr.append(_('Research costs: %d') % Utils.getTechRCost(player, self.techID))
216
                descr.append('')
217
            elif improvement < Rules.techMaxImprovement:
218
                descr.append(_('Improvement costs: %d') % Utils.getTechRCost(player, self.techID))
219
                descr.append('')
220
        # requires
221
        if tech.researchRequires and improvement == 0:
222
            descr.append(_('Research requires:'))
223
            for tmpTechID, improvement in tech.researchRequires:
224
                tmpTech = client.getTechInfo(tmpTechID)
225
                descr.append(_(' - %s improvement %d (TL%d)') % (tmpTech.name, improvement, tmpTech.level))
226
            if hasattr(tech, "researchReqSRes"):
227
                for stratRes in tech.researchReqSRes:
228
                    descr.append(_(" - %s (strategic resource)") % (gdata.stratRes[stratRes]))
229
            descr.append('')
230
        if hasattr(tech, "researchDisables") and tech.researchDisables:
231
            descr.append(_("Research disables:"))
232
            for tmpTechID in tech.researchDisables:
233
                tmpTech = client.getTechInfo(tmpTechID)
234
                descr.append(_(" - %s (TL%d)") % (tmpTech.name, tmpTech.level))
235
            descr.append('')
236
        if hasattr(tech, 'partialData') and hasattr(tech, 'textPreRsrch'):
237
            # preresearch info
238
            descr.append(_('Estimated use:'))
239
            descr.extend(tech.textPreRsrch.split('\n'))
240
            descr.append('')
241
        elif not hasattr(tech, 'partialData'):
242
            tmp = []
243
            for improvement in range(1, 6):
244
                for tmpTechID in tech.researchEnables[improvement]:
245
                    tmpTech = client.getTechInfo(tmpTechID)
246
                    racesDispl = ""
247
                    raceChoosen = None
248
                    if player.techLevel == 1:
249
                        for techID in player.techs.keys():
250
                            if techID in (1990, 1991, 1992):
251
                                raceChoosen = client.getTechInfo(techID).data
252
                    else:
253
                        raceChoosen = player.race
254
                    if len(tmpTech.researchRaces) > 0 and len(tmpTech.researchRaces) < 3 and not raceChoosen:
255
                        racesDispl = _(", only for %s") % tmpTech.researchRaces
256
                    if not raceChoosen or len(tmpTech.researchRaces) == 0 or raceChoosen in tmpTech.researchRaces:
257
                        tmp.append(_(' - %s (with improvement %d, on TL%d%s)') % (tmpTech.name, improvement, tmpTech.level, racesDispl))
258
            if tmp:
259
                descr.append(_('Research/Improvement enables:'))
260
                descr.extend(tmp)
261
                descr.append('')
262
            # production dependency
263
            if tech.prodBioMod != [0, 0, 0, 0] and tech.prodBioMod != [0, 0, 0, 1]:
264
                descr.append(_("Bio production depends:"))
265
                if tech.prodBioMod[0]: descr.append(_(" - %d %% on planet's environment") % (tech.prodBioMod[0] * 100))
266
                if tech.prodBioMod[1]: descr.append(_(" - %d %% on planet's min. abundance") % (tech.prodBioMod[1] * 100))
267
                if tech.prodBioMod[2]: descr.append(_(" - %d %% on planet's en. abundance") % (tech.prodBioMod[2] * 100))
268
                if tech.prodBioMod[3]: descr.append(_(" - %d %% is not dependent on any planet's attribute") % (tech.prodBioMod[3] * 100))
269
                descr.append("")
270
            if tech.prodEnMod != [0, 0, 0, 0] and tech.prodEnMod != [0, 0, 0, 1]:
271
                descr.append(_("Energy production depends:"))
272
                if tech.prodEnMod[0]: descr.append(_(" - %d %% on planet's environment") % (tech.prodEnMod[0] * 100))
273
                if tech.prodEnMod[1]: descr.append(_(" - %d %% on planet's min. abundance") % (tech.prodEnMod[1] * 100))
274
                if tech.prodEnMod[2]: descr.append(_(" - %d %% on planet's en. abundance") % (tech.prodEnMod[2] * 100))
275
                if tech.prodEnMod[3]: descr.append(_(" - %d %% is not dependent on any planet's attribute") % (tech.prodEnMod[3] * 100))
276
                descr.append("")
277
            if tech.prodProdMod != [0, 0, 0, 0] and tech.prodProdMod != [0, 0, 0, 1]:
278
                descr.append(_("Constr. points production depends:"))
279
                if tech.prodProdMod[0]: descr.append(_(" - %d %% on planet's environment") % (tech.prodProdMod[0] * 100))
280
                if tech.prodProdMod[1]: descr.append(_(" - %d %% on planet's min. abundance") % (tech.prodProdMod[1] * 100))
281
                if tech.prodProdMod[2]: descr.append(_(" - %d %% on planet's en. abundance") % (tech.prodProdMod[2] * 100))
282
                if tech.prodProdMod[3]: descr.append(_(" - %d %% is not dependent on any planet's attribute") % (tech.prodProdMod[3] * 100))
283
                descr.append("")
284
            if tech.prodSciMod != [0, 0, 0, 0] and tech.prodSciMod != [0, 0, 0, 1]:
285
                descr.append(_("Research points production depends:"))
286
                if tech.prodSciMod[0]: descr.append(_(" - %d %% on planet's environment") % (tech.prodSciMod[0] * 100))
287
                if tech.prodSciMod[1]: descr.append(_(" - %d %% on planet's min. abundance") % (tech.prodSciMod[1] * 100))
288
                if tech.prodSciMod[2]: descr.append(_(" - %d %% on planet's en. abundance") % (tech.prodSciMod[2] * 100))
289
                if tech.prodSciMod[3]: descr.append(_(" - %d %% is not dependent on any planet's attribute") % (tech.prodSciMod[3] * 100))
290
                descr.append("")
291
292
            requiredStrategicResourcesForBuilding = self.getStrategicResourcesText(tech, "buildSRes")
293
            requiredStrategicResourcesForResearch = self.getStrategicResourcesText(tech, "researchReqSRes")
294
            if len(requiredStrategicResourcesForBuilding) > 0 or len(requiredStrategicResourcesForResearch) > 0:
295
                descr.append(_("Required strategic resources:"))
296
                if len(requiredStrategicResourcesForBuilding) > 0:
297
                    descr.append(_(" - for building: %s") % requiredStrategicResourcesForBuilding)
298
                if len(requiredStrategicResourcesForResearch) > 0:
299
                    descr.append(_(" - for research: %s") % requiredStrategicResourcesForResearch)
300
301
                descr.append("")
302
303
            # decription
304
            descr.append(_('Description:'))
305
            if tech.textDescr != u'Not specified':
306
                descr.extend(tech.textDescr.split('\n'))
307
            else:
308
                descr.extend(tech.textPreRsrch.split('\n'))
309
            descr.append('')
310
            # flavor
311
            descr.append(_('Rumours:'))
312
            descr.extend(tech.textFlavor.split('\n'))
313
            descr.append('')
314
        if not len(descr):
315
            descr.append(_('No information available'))
316
        #
317
        self.win.vDescr.text = descr
318
        # re-set techType if neccessary
319
        self.techType = self.techType & (
320
            getattr(tech ,'isStructure', 0) * V_STRUCT |
321
            getattr(tech ,'isShipHull', 0) * V_HULL |
322
            getattr(tech ,'isShipEquip', 0) * V_SEQUIP |
323
            getattr(tech ,'isProject', 0) * V_PROJECT
324
        )
325
        if self.techType == V_NONE:
326
            if getattr(tech ,'isStructure', 0): self.techType = V_STRUCT
327
            elif getattr(tech ,'isShipHull', 0): self.techType = V_HULL
328
            elif getattr(tech ,'isShipEquip', 0): self.techType = V_SEQUIP
329
            elif getattr(tech ,'isProject', 0): self.techType = V_PROJECT
330
        # set type buttons
331
        self.win.vStruct.pressed = self.techType == V_STRUCT
332
        self.win.vStruct.enabled = getattr(tech ,'isStructure', 0)
333
        self.win.vHull.pressed = self.techType == V_HULL
334
        self.win.vHull.enabled = getattr(tech, 'isShipHull', 0)
335
        self.win.vSEquip.pressed = self.techType == V_SEQUIP
336
        self.win.vSEquip.enabled = getattr(tech, 'isShipEquip', 0)
337
        self.win.vProject.pressed = self.techType == V_PROJECT
338
        self.win.vProject.enabled = getattr(tech, 'isProject', 0)
339
        # fill data
340
        items = []
341
        for attr in dir(tech):
342
            value = getattr(tech, attr)
343
            descr, props, showIfDef, default, convertor = techAttrs.get(attr, defaultAttr)
344
            if self.techType & props and (value != default or showIfDef):
345
                item = ui.Item(descr, tValue = convertor(value))
346
                if V_EFF & props:
347
                    item.font = 'normal-bold'
348
                    item.tValue = convertor(value * techEff)
349
                if V_EFF_REV & props:
350
                    item.font = 'normal-bold'
351
                    item.tValue = convertor(value / techEff)
352
                items.append(item)
353
354
        self.win.vData.items = items
355
        self.win.vData.itemsChanged()
356
357
    def getStrategicResourcesText(self, tech, attr):
358
        try:
359
            resourceDict = getattr(tech, attr)
360
        except AttributeError:
361
            return ""
362
        requiredStrategicResources = []
363
        for res in resourceDict:
364
            try:
365
                amount = resourceDict[res] / float(Rules.stratResAmountBig)
366
            except IndexError:
367
                # this is case of research resources - it's pure list, not a dictionary
368
                requiredStrategicResources += [gdata.stratRes[res]]
369
            else:
370
                # continuation of build resources
371
                requiredStrategicResources += ['{0} ({1})'.format(gdata.stratRes[res], amount)]
372
        return ', '.join(requiredStrategicResources)
373
374
    def onShowType(self, widget, action, data):
375
        self.techType = widget.data
376
        self.update()
377
378
    def onCancel(self, widget, action, data):
379
        self.hide()
380
381
    def onClose(self, widget, action, data):
382
        self.hide()
383
384
    def createUI(self):
385
        w, h = gdata.scrnSize
386
        self.win = ui.Window(self.app,
387
            modal = 1,
388
            escKeyClose = 1,
389
            titleOnly = w == 800 and h == 600,
390
            movable = 0,
391
            title = _('Split Fleet'),
392
            rect = ui.Rect((w - 800 - 4 * (w != 800)) / 2, (h - 600 - 4 * (h != 600)) / 2, 800 + 4 * (w != 800), 580 + 4 * (h != 600)),
393
            layoutManager = ui.SimpleGridLM(),
394
        )
395
        self.win.subscribeAction('*', self)
396
        # tech data
397
        ui.Title(self.win, layout = (0, 0, 18, 1), text = _('Data'),
398
            align = ui.ALIGN_W, font = 'normal-bold')
399
        ui.Listbox(self.win, layout = (0, 1, 18, 25), id = 'vData',
400
            columns = ((_('Property'), 'text', 11, ui.ALIGN_W),
401
            (_('Value'), 'tValue', 7, ui.ALIGN_E)),
402
            columnLabels = 0)
403
        ui.Button(self.win, layout = (1, 26, 4, 1), text = _('Structure'),
404
            id = 'vStruct', toggle = 1, action = 'onShowType', data = V_STRUCT)
405
        ui.Button(self.win, layout = (5, 26, 4, 1), text = _('Ship Hull'),
406
            id = 'vHull', toggle = 1, action = 'onShowType', data = V_HULL)
407
        ui.Button(self.win, layout = (9, 26, 4, 1), text = _('Ship Eq.'),
408
            id = 'vSEquip', toggle = 1, action = 'onShowType', data = V_SEQUIP)
409
        ui.Button(self.win, layout = (13, 26, 4, 1), text = _('Project'),
410
            id = 'vProject', toggle = 1, action = 'onShowType', data = V_PROJECT)
411
        ui.Button(self.win, layout = (17, 26, 1, 1), text = '',
412
            id = 'vEmpty1', toggle = 0)
413
        ui.Button(self.win, layout = (0, 26, 1, 1), text = '',
414
            id = 'vEmpty2', toggle = 0)
415
        # text field
416
        ui.Title(self.win, layout = (18, 0, 22, 1), text = _('Description'),
417
            align = ui.ALIGN_W, font = 'normal-bold')
418
        s = ui.Scrollbar(self.win, layout = (39, 1, 1, 26))
419
        t = ui.Text(self.win, layout = (18, 1, 21, 26), id = 'vDescr', editable = 0)
420
        t.attachVScrollbar(s)
421
        # status bar + submit/cancel
422
        ui.TitleButton(self.win, layout = (35, 27, 5, 1), text = _('Close'), action = 'onClose')
423
        ui.Title(self.win, id = 'vStatusBar', layout = (0, 27, 35, 1), align = ui.ALIGN_W)
424
        #@self.win.statusBar = self.win.vStatusBar
425