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

osci.StarMap.StarMap.precomputeWormholes()   A

Complexity

Conditions 3

Size

Total Lines 32
Code Lines 31

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 31
nop 4
dl 0
loc 32
rs 9.1359
c 0
b 0
f 0
1
# -*- coding: utf-8 -*-
2
#
3
#  Copyright 2001 - 2016 Ludek Smid [http://www.ospace.net/]
4
#
5
#  This file is part of Outer Space.
6
#
7
#  Outer Space is free software; you can redistribute it and/or modify
8
#  it under the terms of the GNU General Public License as published by
9
#  the Free Software Foundation; either version 2 of the License, or
10
#  (at your option) any later version.
11
#
12
#  Outer Space is distributed in the hope that it will be useful,
13
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
14
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
#  GNU General Public License for more details.
16
#
17
#  You should have received a copy of the GNU General Public License
18
#  along with Outer Space; if not, write to the Free Software
19
#  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20
#
21
22
from pygameui import Fonts
23
import ige.ospace.Const as Const
24
from ige.ospace import Rules, Utils
25
import pygame, pygame.draw, pygame.key, pygame.image
26
import gdata, client, res, math, string
27
from ige import log
28
29
buoyColors = [(0xff, 0xff, 0x00), (0x00, 0xff, 0xff), (0xff, 0x00, 0xff), (0xb0, 0xb0, 0xff)]
30
MAX_BOUY_DISPLAY_LEN = 30
31
CONTROLRANGE = 5
32
MAXCONTROLRANGE = 30 #square of CONTROLRANGE + small amount
33
34
class StarMap(object):
35
    MAP_SCANNER1 = 1
36
    MAP_SYSTEMS = 3
37
    MAP_PLANETS = 4
38
    MAP_FLEETS = 5
39
    MAP_FORDERS = 6
40
    MAP_OTHERS = 7
41
    MAP_FREDIRECTS = 8
42
    MAP_GATESYSTEMS = 10
43
    MAP_CONTROLAREA = 11
44
45
    def __init__(self, modes):
46
        self.rect = None # will be set later - rect during init phase is not precise
47
        # map
48
        self._map = {
49
            self.MAP_SCANNER1: [],
50
            self.MAP_SYSTEMS: [],
51
            self.MAP_PLANETS: [],
52
            self.MAP_FLEETS: [],
53
            self.MAP_FORDERS: [],
54
            self.MAP_OTHERS: [],
55
            self.MAP_FREDIRECTS: [],
56
            self.MAP_GATESYSTEMS: [],
57
            self.MAP_CONTROLAREA: {}
58
        }
59
        self._popupInfo = {}
60
        self._fleetRanges = {}
61
        self._fleetTarget = {}
62
        self._fordersTarget = {}
63
        self._actAreas = {}
64
        self._actBuoyAreas = {}
65
        self.currX = 0.0
66
        self.currY = 0.0
67
        self.scale = 50.0
68
        self.textSize = 'normal'
69
        #modes
70
        self.control_modes = modes
71
        # overlay system
72
        self.overlayMode = gdata.OVERLAY_OWNER
73
        self._overlayZone = False
74
75
    def chronicle_draw(self):
76
        galaxy_id = client.getPlayer().galaxy
77
        galaxy = client.get(galaxy_id, noUpdate = 1)
78
        saved_x, saved_y = self.currX, self.currY
79
        self.currX, self.currY = galaxy.x, galaxy.y
80
        surface_side = (galaxy.radius + 2) * 2 * self.scale
81
        new_surf, empty, empty = self.draw(pygame.Surface((surface_side, surface_side)))
82
        self.currX, self.currY = saved_x, saved_y
83
        return new_surf
84
85
86
    def precompute(self):
87
        player_highlight = -1
88
        if gdata.config.game.highlight != None:
89
            player_highlight = gdata.config.game.highlight
90
        self._map = {
91
            self.MAP_SCANNER1: [],
92
            self.MAP_SYSTEMS: [],
93
            self.MAP_PLANETS: [],
94
            self.MAP_FLEETS: [],
95
            self.MAP_FORDERS: [],
96
            self.MAP_OTHERS: [],
97
            self.MAP_FREDIRECTS: [],
98
            self.MAP_GATESYSTEMS: [],
99
            self.MAP_CONTROLAREA: {}
100
        }
101
        self._popupInfo = {}
102
        self._fleetRanges = {}
103
        # find all pirate planets
104
        pirate_systems = self.precomputePirateSystems()
105
        # process objects
106
        self.fleetOrbit = {}
107
        anyX = 0.0
108
        anyY = 0.0
109
        player = client.getPlayer()
110
        for objID in client.db.keys():
111
            if objID < Const.OID_FREESTART:
112
                continue
113
            obj = client.get(objID, noUpdate = 1)
114
            if not hasattr(obj, "type"):
115
                continue
116
            if obj.type == Const.T_PLAYER:
117
                continue
118
            try:
119
                if hasattr(obj, "x"):
120
                    anyX = obj.x
121
                if hasattr(obj, "y"):
122
                    anyY = obj.y
123
            except AttributeError, e:
124
                log.warning('StarMap', 'Cannot render objID = %d' % objID)
125
                continue
126
            if obj.type == Const.T_SYSTEM:
127
                self.precomputeSystems(obj, player, pirate_systems)
128
            elif obj.type == Const.T_WORMHOLE:
129
                self.precomputeWormholes(obj, player, pirate_systems)
130
            elif obj.type == Const.T_PLANET:
131
                self.precomputePlanets(obj, player, pirate_systems)
132
            elif obj.type == Const.T_FLEET:
133
                self.precomputeFleet(obj)
134
            elif obj.type == Const.T_ASTEROID:
135
                self.precomputeAsteroid(obj)
136
            elif obj.type in (Const.T_GALAXY, Const.T_AIPLAYER, Const.T_AIRENPLAYER, Const.T_AIMUTPLAYER, Const.T_AIPIRPLAYER, Const.T_AIEDENPLAYER, Const.T_PIRPLAYER):
137
                pass
138
            elif obj.type == Const.T_UNKNOWN:
139
                # pop up info
140
                info = []
141
                info.append(_('Unknown object [ID: %d]') % obj.oid)
142
                if hasattr(obj, 'scanPwr'):
143
                    info.append(_('Scan pwr: %d') % obj.scanPwr)
144
                self._popupInfo[obj.oid] = info
145
            else:
146
                log.warning('StarMap', 'Unknown object type %d' % obj.type)
147
        # redirections
148
        self.precomputeRedirections()
149
        # set position (typically on first show)
150
        if self.currX == 0.0 and self.currY == 0.0:
151
            self.currX = anyX
152
            self.currY = anyY
153
154
155
    def precomputePirateSystems(self):
156
        pirate_systems = {}
157
        log.debug("Checking pirate planets and wormholes")
158
        for objID in client.db.keys():
159
            if objID < Const.OID_FREESTART:
160
                continue
161
            obj = client.get(objID, noUpdate = 1)
162
            if not hasattr(obj, "type"):
163
                continue
164
            if obj.type == Const.T_WORMHOLE and not hasattr(obj, 'destinationOid'):
165
                obj = client.get(objID, forceUpdate = 1, publicOnly = 1)
166
            if obj.type == Const.T_PLANET and hasattr(obj, "x"):
167
                ownerID = getattr(obj, 'owner', Const.OID_NONE)
168
                if ownerID == Const.OID_NONE:
169
                    continue
170
                owner = client.get(ownerID, publicOnly = 1)
171
                if hasattr(owner, "type") and (owner.type == Const.T_PIRPLAYER or\
172
                                                owner.type == Const.T_AIPIRPLAYER):
173
                    pirate_systems[obj.x, obj.y] = None
174
        return pirate_systems
175
176
    def precomputeSystems(self, obj, player, pirate_systems):
177
        img = res.getSmallStarImg(obj.starClass[1]) # TODO correct me
178
        icons = []
179
        name = getattr(obj, 'name', None)
180
        # TODO compute real relationship
181
        #rel = Const.REL_UNDEF
182
        refuelMax = 0
183
        refuelInc = 0
184
        hasRefuel = False
185
        upgradeShip = 0
186
        repairShip = 0
187
        speedBoost = 0
188
        moraleCount = 0
189
        morale = 200
190
        constPoints = 0
191
        sciPoints = 0
192
        minerals = -1
193
        bio = -1
194
        slots = 0
195
        numPlanets = 0
196
        stratRes = Const.SR_NONE
197
        isGovCentral = False
198
        #owner2 = 0
199
        ownerID = Const.OID_NONE
200
        explored = False
201
        if hasattr(obj, 'planets'):
202
            hasPirate = False
203
            for planetID in obj.planets:
204
                planet = client.get(planetID, noUpdate = 1)
205
                owner = getattr(planet, 'owner', Const.OID_NONE)
206
                if hasattr(planet, "plType") and planet.plType not in ("A", "G"):
207
                    numPlanets += 1
208
                if hasattr(planet, "plMin"):
209
                    minerals = max(minerals,planet.plMin)
210
                if hasattr(planet, "plBio"):
211
                    bio = max(bio,planet.plBio)
212
                if hasattr(planet, "plSlots"):
213
                    slots += planet.plSlots
214
                if hasattr(planet, "plStratRes") and planet.plStratRes != Const.SR_NONE:
215
                    stratRes = planet.plStratRes
216
                    stratRes = planet.plStratRes
217
                    icons.append(res.icons["sr_%d" % planet.plStratRes])
218
                if owner:
219
                    ownerID = owner
220
                    if hasattr(planet, "morale"):
221
                        morale = min(morale,planet.morale)
222
                    if hasattr(planet, "refuelMax"):
223
                        refuelMax = max(refuelMax, planet.refuelMax)
224
                        refuelInc = max(refuelInc, planet.refuelInc)
225
                    if hasattr(planet, "repairShip"):
226
                        upgradeShip += planet.upgradeShip
227
                        repairShip = max(repairShip, planet.repairShip)
228
                    hasRefuel = hasRefuel or getattr(planet, 'hasRefuel', False)
229
                    if hasattr(planet, "fleetSpeedBoost"):
230
                        speedBoost = max(speedBoost, planet.fleetSpeedBoost)
231
                    if hasattr(planet, "effProdProd"):
232
                        constPoints += planet.effProdProd
233
                    if hasattr(planet, "effProdSci"):
234
                        sciPoints += planet.effProdSci
235
                    if hasattr(planet, "slots"):
236
                        for struct in planet.slots:
237
                            tech = Rules.techs[struct[Const.STRUCT_IDX_TECHID]]
238
                            if not tech.govPwr == 0:
239
                                isGovCentral = True
240
                            if not hasattr(planet, "morale"): # ugly way to say "planets of other players"
241
                                # operational status and tech effectivity
242
                                maxTechHP = tech.maxHP
243
                                opStatus = struct[Const.STRUCT_IDX_OPSTATUS]/100.0
244
                                if opStatus != 0:
245
                                    currHP = struct[Const.STRUCT_IDX_HP]
246
                                    techEff = (currHP / opStatus) / maxTechHP
247
                                else:
248
                                    techEff = 0
249
                                # production
250
                                b, m, e, d = tech.prodProdMod
251
                                prodMod = (b * planet.plBio + m * planet.plMin + e * planet.plEn + d * 100) / 100
252
                                constPoints += int(tech.prodProd * prodMod * techEff * opStatus)
253
                                # science
254
                                b, m, e, d = tech.prodSciMod
255
                                prodMod = (b * planet.plBio + m * planet.plMin + e * planet.plEn + d * 100) / 100
256
                                sciPoints += int(tech.prodSci * prodMod * techEff * opStatus)
257
                # uncharted system
258
                if hasattr(planet, 'plBio') and hasattr(planet, 'plEn'):
259
                    explored = True
260
        if not explored and name != None:
261
            name = "[%s]" % (name)
262
        #if moraleCount > 0:
263
        #    morale = morale/moraleCount
264
        if morale==200:
265
            morale = -1
266
        pirProb = self.precomputePiratesProbability(obj, pirate_systems, icons)
267
        if (player.type == Const.T_PIRPLAYER or\
268
                player.type == Const.T_AIPIRPLAYER):
269
            pirateFameCost = self.getPirateFameCost(player.oid,obj.oid,len(player.planets),pirate_systems)
270
        # refuelling
271
        if refuelMax > 0:
272
            if refuelMax >= 87:
273
                icons.append(res.icons["fuel_99"])
274
            elif refuelMax >= 62:
275
                icons.append(res.icons["fuel_75"])
276
            elif refuelMax >= 37:
277
                icons.append(res.icons["fuel_50"])
278
            elif refuelMax >= 12:
279
                icons.append(res.icons["fuel_25"])
280
        elif hasRefuel:
281
            icons.append(res.icons["fuel_-"])
282
        # repair and upgrade
283
        if upgradeShip > 10 and repairShip > 0.02:
284
            icons.append(res.icons["rep_10"])
285
        elif upgradeShip > 0 and repairShip > 0:
286
            icons.append(res.icons["rep_1"])
287
288
        self.precomputeCombat(obj, icons)
289
        self.precomputeMines(obj, icons)
290
        self.precomputeBuoys(obj, player, icons)
291
        # star gates
292
        if speedBoost > 1.0:
293
            icons.append(res.icons["sg_%02d" % round(speedBoost)])
294
            self._map[self.MAP_GATESYSTEMS].append((obj.x, obj.y, speedBoost))
295
        #if owner2 != 0:
296
        #   color = gdata.playerHighlightColor
297
        #else:
298
        #   color = res.getFFColorCode(rel)
299
        if (player.type == Const.T_PIRPLAYER or\
300
                player.type == Const.T_AIPIRPLAYER):
301
            colors = res.getStarmapWidgetSystemColor(ownerID,bio,minerals,slots,numPlanets,speedBoost, refuelInc, upgradeShip, pirProb*100, stratRes, morale, pirateFameCost)
0 ignored issues
show
introduced by
The variable pirateFameCost does not seem to be defined in case player.type == Const.T_P... == Const.T_AIPIRPLAYER on line 267 is False. Are you sure this can never be the case?
Loading history...
302
        else:
303
            colors = res.getStarmapWidgetSystemColor(ownerID,bio,minerals,slots,numPlanets,speedBoost, refuelInc, upgradeShip, pirProb*100, stratRes, morale)
304
        namecolor = res.getPlayerColor(ownerID)
305
        controlcolor = res.getControlColor(ownerID)
306
        if controlcolor:
307
            groupCenterX = int(obj.x)
308
            groupCenterY = int(obj.y)
309
            for rX in range(-CONTROLRANGE,CONTROLRANGE):
310
                for rY in range(-CONTROLRANGE,CONTROLRANGE):
311
                    if rX*rX+rY*rY < MAXCONTROLRANGE:
312
                        ctrlid = "%d:%d" % (groupCenterX+rX,groupCenterY+rY)
313
                        dist = pow(obj.x-(groupCenterX+rX+0.5),2) + pow(obj.y-(groupCenterY+rY+0.5),2)
314
                        if ctrlid in self._map[self.MAP_CONTROLAREA]:
315
                            oldCtrl = self._map[self.MAP_CONTROLAREA][ctrlid]
316
                            if dist > oldCtrl[1]:
317
                                continue
318
                        self._map[self.MAP_CONTROLAREA][ctrlid] = (controlcolor,dist)
319
        self._map[self.MAP_SYSTEMS].append((obj.oid, obj.x, obj.y, name, img, colors, namecolor, False, icons, constPoints, sciPoints, isGovCentral))
320
        # pop up info
321
        info = []
322
        info.append(_('System: %s [ID: %d]') % (name or res.getUnknownName(), obj.oid))
323
        info.append(_('Coordinates: [%.2f, %.2f]') % (obj.x, obj.y))
324
        info.append(_('Scan pwr: %d') % obj.scanPwr)
325
        info.append(_('Star Class: %s') % obj.starClass[1:])
326
        info.append(_('Star Type: %s') % _(gdata.starTypes[obj.starClass[0]]))
327
        if (player.type == Const.T_PIRPLAYER or\
328
                player.type == Const.T_AIPIRPLAYER):
329
            info.append(_('Fame to Colonize: %d') % pirateFameCost)
330
        if refuelMax > 0:
331
            info.append(_("Refuel: %d %%/turn [%d %% max]") % (refuelInc, refuelMax))
332
        if repairShip > 0:
333
            info.append(_("Repair ratio: %d %%/turn") % (repairShip * 100))
334
        if upgradeShip > 0:
335
            info.append(_("Upgrade points: %d/turn") % upgradeShip)
336
        if speedBoost > 0:
337
            info.append(_("Fleet speed: +%d %%") % (speedBoost * 100))
338
        if pirProb > 0.0:
339
            info.append(_("Pirate get fame chance: %d %%") % (pirProb * 100))
340
        self._popupInfo[obj.oid] = info
341
342
    def precomputeAsteroids(self, obj):
343
        owner = getattr(obj, 'owner', Const.OID_NONE)
344
        name = getattr(obj, 'name', None) or res.getUnknownName()
345
        color = (0xff, 0xff, 0xff)
346
        scannerPwr = getattr(obj, 'scannerPwr', 0)
347
        orbit = -1
348
        if obj.orbiting != Const.OID_NONE:
349
            orbit = self.fleetOrbit.get(obj.orbiting, 0)
350
            self.fleetOrbit[obj.orbiting] = orbit + 1
351
        eta = getattr(obj, 'eta', 0)
352
        self._map[self.MAP_FLEETS].append((obj.oid, obj.x, obj.y, obj.oldX, obj.oldY, orbit, res.formatTime(eta), color,
353
            obj.signature / 25, 0))
354
        # pop up info
355
        info = []
356
        info.append(_('Asteroid: %s [ID: %d]') % (name, obj.oid))
357
        if hasattr(obj, 'scanPwr'): info.append(_('Scan pwr: %d') % obj.scanPwr)
358
        info.append(_('Coordinates: [%.2f, %.2f]') % (obj.x, obj.y))
359
        info.append(_('Signature: %d') % obj.signature)
360
        if hasattr(obj, 'asDiameter'): info.append(_('Diameter: %d') % obj.asDiameter)
361
        if hasattr(obj, 'asHP'): info.append(_('HP: %d') % obj.asHP)
362
        if hasattr(obj, 'speed'): info.append(_('Speed: %.2f') % obj.speed)
363
        if eta:
364
            info.append(_('ETA: %s') % res.formatTime(eta))
365
        if owner:
366
            ownerobj = client.get(owner, publicOnly = 1)
367
            info.append(_('Owner: %s [ID: %s]') % (
368
                getattr(ownerobj, 'name', res.getUnknownName()),
369
                getattr(ownerobj, 'oid', '?')
370
            ))
371
        self._popupInfo[obj.oid] = info
372
373
    def precomputeWormholes(self, obj, player, pirate_systems):
374
        log.debug("Displaying wormhole",obj.oid)
375
        img = res.getSmallStarImg(obj.starClass[1])
376
        icons = []
377
        name = getattr(obj, 'name', None)
378
        pirProb = self.precomputePiratesProbability(obj, pirate_systems, icons)
379
        self.precomputeCombat(obj, icons)
380
        self.precomputeMines(obj, icons)
381
        self.precomputeBuoys(obj, player, icons)
382
        color = res.getPlayerColor(Const.OID_NONE)
383
        namecolor = res.getPlayerColor(Const.OID_NONE)
384
        constPoints = 0
385
        sciPoints = 0
386
        isGovCentral = False
387
        self._map[self.MAP_SYSTEMS].append((obj.oid, obj.x, obj.y, name, img, color, namecolor, True, icons, constPoints, sciPoints, isGovCentral))
388
        # pop up info
389
        info = []
390
        info.append(_('Worm hole: %s [ID: %d]') % (name or res.getUnknownName(), obj.oid))
391
        info.append(_('Coordinates: [%.2f, %.2f]') % (obj.x, obj.y))
392
        try:
393
            log.debug("Attempting to get wormhole destination (",obj.destinationOid,") from client.")
394
            whDestObj = client.get(obj.destinationOid, noUpdate = 1) #except if the client doesn't have this in their DB
395
            whDestName = getattr(whDestObj, 'name', None)
396
            info.append(_('Destination: %s [ID: %d]') % (whDestName or res.getUnknownName(), obj.oid))
397
            info.append(_('Dest. Coords: [%.2f, %.2f]') % (whDestObj.x, whDestObj.y))
398
        except:
399
            log.debug("Failed getting wormhole destination from client.")
400
            info.append(_('Destination: ? [ID: ?]'))
401
            info.append(_('Dest. Coords: [?, ?]'))
402
        if pirProb > 0.0:
403
            info.append(_("Pirate get fame chance: %d %%") % (pirProb * 100))
404
        self._popupInfo[obj.oid] = info
405
406
    def precomputePlanets(self, obj, player, pirate_systems):
407
        owner = getattr(obj, 'owner', Const.OID_NONE)
408
        # set up color reference data
409
        biodata = -1
410
        mindata = -1
411
        slotdata = 0
412
        stargatedata = 0
413
        dockrefueldata = 0
414
        dockupgradedata = 0
415
        stratresdata = Const.SR_NONE
416
        moraledata = -1
417
        pirProb = self.precomputePiratesProbability(obj, pirate_systems, False)
418
        famedata = pirProb*100
419
        biodata = getattr(obj, 'plBio', -1)
420
        mindata = getattr(obj, 'plMin', -1)
421
        slotdata = getattr(obj, 'plSlots', 0)
422
        dockrefueldata = getattr(obj, 'refuelInc', 0)
423
        dockupgradedata = getattr(obj, 'upgradeShip', 0)
424
        stargatedata = getattr(obj, 'fleetSpeedBoost', 0)
425
        stratresdata = getattr(obj, 'plStratRes', Const.SR_NONE)
426
        moraledata = getattr(obj, 'morale', -1)
427
        if (player.type == Const.T_PIRPLAYER or\
428
                player.type == Const.T_AIPIRPLAYER):
429
            pirateFameCost = self.getPirateFameCost(player.oid,obj.compOf,len(player.planets),pirate_systems)
430
        # build system
431
        name = getattr(obj, 'name', None) or res.getUnknownName()
432
        singlet = True
433
        if hasattr(obj, "plType") and obj.plType in ("A", "G"):
434
            colors = gdata.sevColors[gdata.DISABLED]
435
        else:
436
            singlet = False
437
            if (player.type == Const.T_PIRPLAYER or\
438
                    player.type == Const.T_AIPIRPLAYER):
439
                colors = res.getStarmapWidgetPlanetColor(owner,biodata,mindata,slotdata,stargatedata, dockrefueldata, dockupgradedata, famedata, stratresdata, moraledata, pirateFameCost)
0 ignored issues
show
introduced by
The variable pirateFameCost does not seem to be defined in case player.type == Const.T_P... == Const.T_AIPIRPLAYER on line 427 is False. Are you sure this can never be the case?
Loading history...
440
            else:
441
                colors = res.getStarmapWidgetPlanetColor(owner,biodata,mindata,slotdata,stargatedata, dockrefueldata, dockupgradedata, famedata, stratresdata, moraledata)
442
        self._map[self.MAP_PLANETS].append((obj.oid, obj.x, obj.y, obj.orbit, colors, singlet))
443
        scannerPwr = getattr(obj, 'scannerPwr', 0)
444
        if scannerPwr:
445
            self._map[self.MAP_SCANNER1].append((obj.x, obj.y, scannerPwr))
446
        # pop up info
447
        info = []
448
        info.append(_('Planet: %s [ID: %d]') % (name, obj.oid))
449
        if hasattr(obj, 'scanPwr'): info.append(_('Scan pwr: %d') % obj.scanPwr)
450
        elif hasattr(obj, 'scannerPwr'): info.append(_('Scanner pwr: %d') % obj.scannerPwr)
451
        plType = gdata.planetTypes[getattr(obj, 'plType', None)]
452
        info.append(_('Type: %s') % _(plType))
453
        if (player.type == Const.T_PIRPLAYER or\
454
                player.type == Const.T_AIPIRPLAYER):
455
            info.append(_('Fame to Colonize: %d') % pirateFameCost)
456
        if hasattr(obj, 'plBio'): info.append(_('Environment: %d') % obj.plBio)
457
        if hasattr(obj, 'plMin'): info.append(_('Minerals: %d') % obj.plMin)
458
        if hasattr(obj, 'plEn'): info.append(_('Energy: %d') % obj.plEn)
459
        if hasattr(obj, 'plSlots'): info.append(_('Slots: %d') % obj.plSlots)
460
        if hasattr(obj, "plStratRes") and obj.plStratRes != Const.SR_NONE:
461
            info.append(_("Strat. resource: %s") % _(gdata.stratRes[obj.plStratRes]))
462
        if owner:
463
            ownerobj = client.get(owner, publicOnly = 1)
464
            info.append(_('Owner: %s [ID: %s]') % (
465
                getattr(ownerobj, 'name', res.getUnknownName()),
466
                getattr(ownerobj, 'oid', '?')
467
            ))
468
        self._popupInfo[obj.oid] = info
469
470
    def getPirateFameCost(self, playerID, systemID, numPiratePlanets, pirate_systems):
471
        mod = 1
472
        system = client.get(systemID, noUpdate = 1)
473
        if hasattr(system,'planets') and system.planets:
474
            for planetID in system.planets:
475
                planet = client.get(planetID, noUpdate = 1)
476
                if getattr(planet, 'owner', Const.OID_NONE) == playerID:
477
                    # minimum reached, don't check rest
478
                    return 0.0
479
                elif getattr(planet, 'plStratRes', None) in (Const.SR_TL3A, Const.SR_TL3B, Const.SR_TL3C):
480
                    mod = min(mod, Rules.pirateTL3StratResColonyCostMod)
481
        dist = 10000
482
        for pirX, pirY in pirate_systems:
483
            dist = min(dist, math.hypot(system.x - pirX, system.y - pirY))
484
        if Rules.pirateGainFamePropability(dist) > 0:
485
            mod = Rules.pirateColonyFameZoneCost(dist)
486
        else:
487
            mod = Rules.pirateColonyPlayerZoneCost(dist)
488
        return mod * numPiratePlanets * Rules.pirateColonyCostMod
489
490
    def precomputeRedirections(self,repaint=False): #also called from Mass Redirector
491
        player = client.getPlayer()
492
        for sourceID in player.shipRedirections:
493
            targetID = player.shipRedirections[sourceID]
494
            source = client.get(sourceID, noUpdate = 1)
495
            target = client.get(targetID, noUpdate = 1)
496
            if hasattr(source, "x") and hasattr(target, "y"):
497
                self._map[self.MAP_FREDIRECTS].append((source.x, source.y, target.x, target.y))
498
499
    def precomputeFleet(self,obj):
500
501
        owner = getattr(obj, 'owner', Const.OID_NONE)
502
        if hasattr(obj,'customname') and obj.customname:
503
            name = obj.customname
504
        else:
505
            name = getattr(obj, 'name', res.getUnknownName())
506
        color = res.getPlayerColor(owner)
507
        # fleet scanner setup
508
        scannerPwr = getattr(obj, 'scannerPwr', 0)
509
        if hasattr(obj, "scannerOn") and not obj.scannerOn:
510
            scannerPwr = 0
511
        if scannerPwr:
512
            self._map[self.MAP_SCANNER1].append((obj.x, obj.y, scannerPwr))
513
        #  get orbital position
514
        orbit = -1
515
        if obj.orbiting != Const.OID_NONE:
516
            orbit = self.fleetOrbit.get(obj.orbiting, 0)
517
            self.fleetOrbit[obj.orbiting] = orbit + 1
518
        # set path and times
519
        eta = getattr(obj, 'eta', 0)
520
        self._map[self.MAP_FLEETS].append((obj.oid, obj.x, obj.y, obj.oldX, obj.oldY, orbit, res.formatTime(eta), color,
521
            obj.signature / 25, getattr(obj, "isMilitary", 1)))
522
        # pop up info
523
        info = []
524
        info.append(_('Fleet: %s [ID: %d]') % (name, obj.oid))
525
        if hasattr(obj, 'scanPwr'):    info.append(_('Scan pwr: %d') % obj.scanPwr)
526
        if hasattr(obj, 'scannerPwr'): info.append(_('Scanner pwr: %d') % obj.scannerPwr)
527
        info.append(_('Coordinates: [%.2f, %.2f]') % (obj.x, obj.y))
528
        info.append(_('Signature: %d') % obj.signature)
529
        if hasattr(obj, 'speed'): info.append(_(u'Speed: %3.2f') % obj.speed)
530
        elif eta:
531
            info.append(_(u'Speed: %3.2f') % (24*((obj.y-obj.oldY)**2+(obj.x-obj.oldX)**2)**.5))
532
        if eta:
533
            info.append(_('ETA: %s') % res.formatTime(eta))
534
        if owner:
535
            ownerobj = client.get(owner, publicOnly = 1)
536
            info.append(_('Owner: %s [ID: %s]') % (
537
                getattr(ownerobj, 'name', res.getUnknownName()),
538
                getattr(ownerobj, 'oid', '?')
539
            ))
540
        if hasattr(obj, 'storEn'):
541
            if obj.maxEn > 0: full = 100 * obj.storEn / obj.maxEn
542
            else: full = 0
543
            info.append(_('Tanks: %d / %d [%d %%]') % (obj.storEn, obj.maxEn, full))
544
            info.append(_('Support (fuel): %d/turn') % (obj.operEn))
545
            info.append(_('Support (const. pts): %d/turn') % (obj.operProd))
546
        if hasattr(obj, 'combatPwr'):
547
            info.append(_('Military power: %d') % obj.combatPwr)
548
        # ranges
549
        if hasattr(obj, 'storEn') and hasattr(obj, 'operEn'):
550
            turns = 100000
551
            if obj.operEn > 0: turns = obj.storEn / obj.operEn
552
            range = turns * obj.speed / Rules.turnsPerDay
553
            self._fleetRanges[obj.oid] = (obj.x, obj.y, range, range  / 2., range / 3., obj.speed * 6 / Rules.turnsPerDay, turns)
554
            info.append(_("Operational time: %s") % res.formatTime(turns))
555
        if hasattr(obj, 'target') and obj.target != Const.OID_NONE:
556
            target = client.get(obj.target, noUpdate=1)
557
            if hasattr(target, "x"):
558
                self._fleetTarget[obj.oid] = (obj.x, obj.y, target.x, target.y)
559
            info.append(_('Target: %s') % getattr(target, "name", res.getUnknownName()))
560
        # pop up info (continued)
561
        if hasattr(obj, 'ships'):
562
            info.append(_('Ships:'))
563
            number = {}
564
            for designID, hp, shield, exp in obj.ships:
565
                tech = client.get(owner).shipDesigns[designID]
566
                level = Rules.shipExpToLevel.get(int(exp / tech.baseExp), Rules.shipDefLevel)
567
                if designID not in number:
568
                    number[designID] = [0, 0, 0, 0, 0]
569
                number[designID][level - 1] += 1
570
            order = number.keys()
571
            order.sort()
572
            for designID in order:
573
                tech = client.get(owner).shipDesigns[designID]
574
                levels = number[designID]
575
                info.append(_('  %d x %s   [%d, %d, %d, %d, %d]') % (
576
                        levels[0] + levels[1] + levels[2] + levels[3] + levels[4],
577
                        tech.name,
578
                        levels[0], levels[1], levels[2], levels[3], levels[4],
579
                    )
580
                )
581
        elif hasattr(obj, 'shipScan'):
582
            info.append(_('Ships:'))
583
            for name, shipClass, isMilitary in obj.shipScan:
584
                if isMilitary:
585
                    sType = _("military")
586
                else:
587
                    sType = _("civilian")
588
                info.append(_("  %d x %s [%s %s ship]") % (
589
                    obj.shipScan[name, shipClass, isMilitary],
590
                    name,
591
                    _(gdata.shipClasses[shipClass]),
592
                    sType
593
                ))
594
        if hasattr(obj, 'actionIndex') and not Utils.isIdleFleet(obj):
595
            action, target, data = obj.actions[obj.actionIndex]
596
            if target != Const.OID_NONE:
597
                targetName = getattr(client.get(target, noUpdate = 1), 'name', res.getUnknownName())
598
            else:
599
                targetName = ""
600
            info.append(_("Command: %s %s") % (
601
                gdata.fleetActions[action],
602
                targetName,
603
            ))
604
        self._popupInfo[obj.oid] = info
605
        # orders
606
        if hasattr(obj, 'actions'):
607
            oldX = obj.x
608
            oldY = obj.y
609
            self._fordersTarget[obj.oid]=[]
610
            for action, target, aData in obj.actions[obj.actionIndex:]:
611
                if target:
612
                    # TODO add action colors
613
                    if action == Const.FLACTION_REFUEL: color = (0x00, 0x90, 0x00)
614
                    elif action == Const.FLACTION_DEPLOY: color = (0x90, 0x90, 0x00)
615
                    elif action == Const.FLACTION_REDIRECT: color = (0x20, 0x20, 0x80)
616
                    else: color = (0x90, 0x90, 0x90)
617
                    trgt = client.get(target, noUpdate = 1)
618
                    if hasattr(trgt, 'x'):
619
                        self._map[self.MAP_FORDERS].append((oldX, oldY, trgt.x, trgt.y, color, getattr(obj, "isMilitary", 0)))
620
                        self._fordersTarget[obj.oid].append((oldX, oldY, trgt.x, trgt.y, color))
621
                        oldX, oldY = trgt.x, trgt.y
622
623
    def precomputePiratesProbability(self, system, pirate_systems, icons = False):
624
        dist = 10000
625
        for pirX, pirY in pirate_systems:
626
            dist = min(dist, math.hypot(system.x - pirX, system.y - pirY))
627
        pirProb = Rules.pirateGainFamePropability(dist)
628
        if icons != False:
629
            if pirProb >= 1.0:
630
                icons.append(res.icons["pir_99"])
631
            elif pirProb > 0.0:
632
                icons.append(res.icons["pir_00"])
633
        return pirProb
634
635
    def precomputeMines(self, system, icons):
636
        if getattr(system, "minefield", False):
637
            # ok, system has our mines - as minefield is identified
638
            icons.append(res.icons["mines_ours"])
639
            if getattr(system, "hasmines", 0) == 2:
640
                # there are also unknown mines!
641
                icons.append(res.icons["mines_unknown"])
642
        elif getattr(system, "hasmines", 0):
643
            # there are only unknown mines
644
            icons.append(res.icons["mines_unknown"])
645
646
647
648
    def precomputeCombat(self, system, icons):
649
        if hasattr(system, "combatCounter") and system.combatCounter > 0:
650
            icons.append(res.icons["combat"])
651
652
    def precomputeBuoys(self, system, player, icons):
653
        if hasattr(player, "buoys") and system.oid in player.buoys:
654
            icons.append(res.icons["buoy_%d" % player.buoys[system.oid][1]])
655
        if hasattr(player, "alliedBuoys") and system.oid in player.alliedBuoys and len(player.alliedBuoys[system.oid]) > 0:
656
            buoyName = "buoy_%d" % player.alliedBuoys[system.oid][0][1]
657
            if len(player.alliedBuoys[system.oid]) > 1:
658
                buoyName = "%s_plus" % buoyName
659
            icons.append(res.icons[buoyName])
660
661
662
    def draw(self, mapSurf):
663
        self._actAreas = {}
664
        # clear active areas for buoy texts
665
        self._actBuoyAreas = {}
666
        mapSurf.fill((0x00, 0x00, 0x00))
667
        ## scanners
668
        # scanner ranges and control areas
669
        if self.control_modes['scanners'] or self.control_modes['control_areas']:
670
            if self.control_modes['control_areas']:
671
                self.drawControlAreas(mapSurf)
672
            else:
673
                self.drawScanners(mapSurf)
674
        # pirate area
675
        if self.control_modes['pirate_areas']:
676
            pass # TODO
677
        # grid
678
        if self.control_modes['map_grid']:
679
            self.drawGrid(mapSurf)
680
        # redirections
681
        if self.control_modes['redirects']:
682
            self.drawRedirects(mapSurf)
683
        # gate systems
684
        if self.control_modes['gate_systems']:
685
            self.drawGateSystems(mapSurf)
686
        # stars
687
        if self.control_modes['systems']:
688
            self.drawSystems(mapSurf)
689
        # planets
690
        if self.control_modes['planets']:
691
            self.drawPlanets(mapSurf)
692
        # fleets
693
        if self.control_modes['fleets']:
694
            self.drawFleets(mapSurf)
695
        self.drawOverlayEffects(mapSurf)
696
        return mapSurf, self._actAreas, self._actBuoyAreas
697
698
    def drawScanners(self, mapSurf):
699
        # default scanner ranges (inner and outer circles)
700
        scanner1range = 1.0/10
701
        scanner2range = 1.0/16
702
        # coordinates
703
        centerX, centerY = mapSurf.get_rect().center
704
        maxX = mapSurf.get_rect().width
705
        maxY = mapSurf.get_rect().height
706
        currX = self.currX
707
        currY = self.currY
708
        scale = self.scale
709
        scannerCalced = []
710
        # draw
711
        for x, y, scan_range in self._map[self.MAP_SCANNER1]:
712
            sx = int((x - currX) * scale) + centerX
713
            sy = maxY - (int((y - currY) * scale) + centerY)
714
            currRange = int(scan_range * scale * scanner1range + 2)
715
            range1 = int(scan_range * scale * scanner1range)
716
            range2 = int(scan_range * scale * scanner2range)
717
            if sx+currRange > 0 and sx-currRange < maxX and sy+currRange > 0 and sy-currRange < maxY:
718
                pygame.draw.circle(mapSurf, (0x00, 0x00, 0x60), (sx, sy), currRange, 2)
719
                scannerCalced.append((sx,sy,range1,range2))
720
        for sx, sy, range1, range2 in scannerCalced:
721
            pygame.draw.circle(mapSurf, (0x00, 0x00, 0x30), (sx, sy), range1, 0)
722
        for sx, sy, range1, range2 in scannerCalced:
723
            pygame.draw.circle(mapSurf, (0x00, 0x00, 0x40), (sx, sy), range2, 0)
724
#        log.debug("Total scanner circles:",len(self._map[self.MAP_SCANNER1]))
725
#        log.debug("Drawn scanner circles:",len(scannerCalced))
726
727
    def drawControlAreas(self, mapSurf):
728
        centerX, centerY = mapSurf.get_rect().center
729
        maxY = mapSurf.get_rect().height
730
        currX = self.currX
731
        currY = self.currY
732
        scale = self.scale
733
        first = True
734
        for xy in self._map[self.MAP_CONTROLAREA].keys():
735
            x,y = xy.split(':',2)
736
            sx = int((int(x) - currX) * scale) + centerX + 1
737
            sy = maxY - (int((int(y) + 1 - currY) * scale) + centerY) # use y+1 because we have to draw from top down rather than bottom up
738
            if sy > centerY: sy += 1 #fix a bug with the draw system
739
            dx = scale
740
            dy = scale
741
            mapSurf.fill(self._map[self.MAP_CONTROLAREA][xy][0], pygame.Rect(sx, sy, dx, dy), 0)
742
743
    def drawRedirects(self, mapSurf):
744
        # coordinates
745
        centerX, centerY = mapSurf.get_rect().center
746
        maxY = mapSurf.get_rect().height
747
        currX = self.currX
748
        currY = self.currY
749
        scale = self.scale
750
        for sx, sy, tx, ty in self._map[self.MAP_FREDIRECTS]:
751
            sx = int((sx - currX) * scale) + centerX
752
            sy = maxY - (int((sy - currY) * scale) + centerY)
753
            tx = int((tx - currX) * scale) + centerX
754
            ty = maxY - (int((ty - currY) * scale) + centerY)
755
            # TODO: change do polygon (triangle), but needs to start
756
            # perpendicular to the redirect
757
            #pygame.draw.polygon(mapSurf, (0x20, 0x20, 0x80), [(sx+2, sy), (sx-2, sy), (tx, ty)])
758
            pygame.draw.line(mapSurf, (0x20, 0x20, 0x80), (sx, sy), (tx, ty), 1)
759
            pygame.draw.line(mapSurf, (0x20, 0x20, 0x80), (sx + 1, sy), (tx, ty), 1)
760
            pygame.draw.line(mapSurf, (0x20, 0x20, 0x80), (sx - 1, sy), (tx, ty), 1)
761
            pygame.draw.line(mapSurf, (0x20, 0x20, 0x80), (sx, sy + 1), (tx, ty), 1)
762
            pygame.draw.line(mapSurf, (0x20, 0x20, 0x80), (sx, sy - 1), (tx, ty), 1)
763
            pygame.draw.line(mapSurf, (0x20, 0x20, 0x80), (sx + 1, sy + 1), (tx, ty), 1)
764
            pygame.draw.line(mapSurf, (0x20, 0x20, 0x80), (sx + 1, sy - 1), (tx, ty), 1)
765
            pygame.draw.line(mapSurf, (0x20, 0x20, 0x80), (sx - 1, sy + 1), (tx, ty), 1)
766
            pygame.draw.line(mapSurf, (0x20, 0x20, 0x80), (sx - 1, sy - 1), (tx, ty), 1)
767
            pygame.draw.line(mapSurf, (0x20, 0x20, 0x80), (sx + 2, sy), (tx, ty), 1)
768
            pygame.draw.line(mapSurf, (0x20, 0x20, 0x80), (sx - 2, sy), (tx, ty), 1)
769
            pygame.draw.line(mapSurf, (0x20, 0x20, 0x80), (sx, sy + 2), (tx, ty), 1)
770
            pygame.draw.line(mapSurf, (0x20, 0x20, 0x80), (sx, sy - 2), (tx, ty), 1)
771
772
    def drawSystems(self, mapSurf):
773
        # coordinates
774
        centerX, centerY = mapSurf.get_rect().center
775
        maxY = mapSurf.get_rect().height
776
        currX = self.currX
777
        currY = self.currY
778
        scale = self.scale
779
        namecolor = res.getPlayerColor(Const.OID_NONE)
780
        if scale >= 30:
781
            for objID, x, y, name, img, color, namecolor, singlet, icons, constPoints, sciPoints, isGovCentral in self._map[self.MAP_SYSTEMS]:
782
                sx = int((x - currX) * scale) + centerX
783
                sy = maxY - (int((y - currY) * scale) + centerY)
784
                w, h = img.get_size()
785
                x = sx - w / 2
786
                y = sy - h / 2
787
                mapSurf.blit(img, (x, y))
788
                # images are now smaller - TODO fix images of stars
789
                w = 22
790
                h = 22
791
                if name:
792
                    if self.overlayMode != gdata.OVERLAY_OWNER:
793
                        namecolor = res.fadeColor(namecolor)
794
                    img = Fonts.renderText(self.textSize, name, 1, namecolor)
795
                    mapSurf.blit(img, (sx - img.get_width() / 2, sy + h / 2))
796
                buoy = self.getBuoy(objID)
797
                if buoy != None and not self.control_modes['alternative_mode']:
798
                    if not name: #if name not set and there is a bouy, set "?" as the name
799
                        if self.overlayMode != gdata.OVERLAY_OWNER:
800
                            namecolor = res.fadeColor(namecolor)
801
                        img = Fonts.renderText(self.textSize, '[ ? ]', 1, namecolor)
802
                        mapSurf.blit(img, (sx - img.get_width() / 2, sy + h / 2))
803
                        nSy = sy + h / 2 + img.get_height()
804
                    nSy = sy + h / 2 + img.get_height()
805
                    lines = buoy[0].split("\n")
806
                    maxW = 0
807
                    hh = 0
808
                    for line in lines:
809
                        if len(line) == 0:
810
                            break
811
                        if len(line) > MAX_BOUY_DISPLAY_LEN:
812
                            line = u"%s..." % line[:MAX_BOUY_DISPLAY_LEN]
813
                        if self.overlayMode == gdata.OVERLAY_OWNER:
814
                            bouycolor = buoyColors[buoy[1] - 1]
815
                        else:
816
                            bouycolor = res.fadeColor(buoyColors[buoy[1] - 1])
817
                        img = Fonts.renderText(self.textSize, line, 1, bouycolor)
818
                        maxW = max(img.get_width(), maxW)
819
                        mapSurf.blit(img, (sx - img.get_width() / 2, nSy + hh))
820
                        hh += img.get_height()
821
                    if maxW > 0:
822
                        actRect = pygame.Rect(sx - maxW / 2, nSy, maxW, hh)
823
                        actRect.move_ip(self.rect.left, self.rect.top)
824
                        self._actBuoyAreas[objID] = actRect
825
                elif self.control_modes['alternative_mode']:
826
                    alternative = name
827
                    nSy = sy + h / 2 + img.get_height()
828
                    if constPoints != 0 or sciPoints != 0:
829
                        img = Fonts.renderText(self.textSize, u"CP: %d RP: %d" % (constPoints, sciPoints), 1, namecolor)
830
                        mapSurf.blit(img, (sx - img.get_width() / 2, nSy))
831
                    if isGovCentral:
832
                        img = Fonts.renderText(self.textSize, u"Central system", 1, (255, 255, 255))
833
                        mapSurf.blit(img, (sx - img.get_width() / 2, nSy + img.get_height()))
834
                for icon in icons:
835
                    mapSurf.blit(icon, (x, y))
836
                    x += icon.get_width() + 1
837
                # active rectangle
838
                actRect = pygame.Rect(sx - w / 2, sy - h / 2, w, h)
839
                actRect.move_ip(self.rect.left, self.rect.top)
840
                self._actAreas[objID] = actRect
841
        else:
842
            for objID, x, y, name, img, color, namecolor, singlet, icons, constPoints, sciPoints, isGovCentral in self._map[self.MAP_SYSTEMS]:
843
                if not singlet:
844
                    color = color[self.overlayMode]
845
                sx = int((x - currX) * scale) + centerX
846
                sy = maxY - (int((y - currY) * scale) + centerY)
847
                pygame.draw.circle(mapSurf, color, (sx, sy), 5, 1)
848
                pygame.draw.circle(mapSurf, color, (sx, sy), 4, 0)
849
                if name and scale > 15:
850
                    if self.overlayMode != gdata.OVERLAY_OWNER:
851
                        namecolor = res.fadeColor(namecolor)
852
                    img = Fonts.renderText(self.textSize, name, 1, namecolor)
853
                    mapSurf.blit(img, (sx - img.get_width() / 2, sy + 6 / 2))
854
                    buoy = self.getBuoy(objID)
855
                    if buoy != None:
856
                        lines = buoy[0].split("\n")
857
                        nSy = sy + 6 / 2 + img.get_height()
858
                        maxW = 0
859
                        hh = 0
860
                        for line in lines:
861
                            if len(line) == 0:
862
                                break
863
                            img = Fonts.renderText(self.textSize, line, 1, buoyColors[buoy[1] - 1])
864
                            maxW = max(img.get_width(), maxW)
865
                            mapSurf.blit(img, (sx - img.get_width() / 2, nSy + hh))
866
                            hh += img.get_height()
867
                        if maxW > 0:
868
                            actRect = pygame.Rect(sx - maxW / 2, nSy, maxW, hh)
869
                            actRect.move_ip(self.rect.left, self.rect.top)
870
                            self._actBuoyAreas[objID] = actRect
871
                # active rectangle
872
                actRect = pygame.Rect(sx - 6 / 2, sy - 6 / 2, 6, 6)
873
                actRect.move_ip(self.rect.left, self.rect.top)
874
                self._actAreas[objID] = actRect
875
876
    def drawGateSystems(self, mapSurf):
877
        # coordinates
878
        centerX, centerY = mapSurf.get_rect().center
879
        maxY = mapSurf.get_rect().height
880
        currX = self.currX
881
        currY = self.currY
882
        scale = self.scale
883
        minRadius = 8
884
        radiusMult = 3
885
        if scale < 30:
886
            for x, y, speed in self._map[self.MAP_GATESYSTEMS]:
887
                sx = int((x - currX) * scale) + centerX
888
                sy = maxY - (int((y - currY) * scale) + centerY)
889
                for curSpeed in range(1,int(speed+1)):
890
                    radius = (curSpeed-1)* radiusMult + minRadius
891
                    color = res.getStargateColorCode(curSpeed)
892
                    pygame.draw.circle(mapSurf, color, (sx, sy), radius, 1)
893
894
    def drawPlanets(self, mapSurf):
895
        # coordinates
896
        centerX, centerY = mapSurf.get_rect().center
897
        maxY = mapSurf.get_rect().height
898
        currX = self.currX
899
        currY = self.currY
900
        scale = self.scale
901
        if scale >= 30:
902
            rectSize = max(int(gdata.config.defaults.minplanetsymbolsize), math.floor(scale/6))
903
            if not int(gdata.config.defaults.maxplanetsymbolsize) == 0:
904
                rectSize = min(int(gdata.config.defaults.maxplanetsymbolsize), rectSize)
905
            rectSpace = rectSize + math.floor(rectSize/5)
906
            for objID, x, y, orbit, color, singlet in self._map[self.MAP_PLANETS]:
907
                if not singlet:
908
                    color = color[self.overlayMode]
909
                sx = int((x - currX) * scale) + centerX
910
                sy = maxY - (int((y - currY) * scale) + centerY)
911
                orbit -= 1
912
                actRect = pygame.Rect(sx + (orbit % 8) * rectSpace + 13, sy + 6 * (orbit / 8) - rectSize , rectSize, rectSize)
913
914
                mapSurf.fill(color, actRect)
915
                actRect.move_ip(self.rect.left, self.rect.top)
916
                self._actAreas[objID] = actRect
917
        elif scale > 20:
918
            for objID, x, y, orbit, color, singlet in self._map[self.MAP_PLANETS]:
919
                if not singlet:
920
                    color = color[self.overlayMode]
921
                sx = int((x - currX) * scale) + centerX
922
                sy = maxY - (int((y - currY) * scale) + centerY)
923
                orbit -= 1
924
                actRect = pygame.Rect(sx + (orbit % 8) * 3 + 7, sy - 3 * (orbit / 8) - 1, 2, 2)
925
                mapSurf.fill(color, actRect)
926
                actRect.move_ip(self.rect.left, self.rect.top)
927
                self._actAreas[objID] = actRect
928
929
    def drawFleets(self, mapSurf):
930
        # coordinates
931
        centerX, centerY = mapSurf.get_rect().center
932
        maxY = mapSurf.get_rect().height
933
        currX = self.currX
934
        currY = self.currY
935
        scale = self.scale
936
        minSize = int(gdata.config.defaults.minfleetsymbolsize)
937
        rectSize = max(minSize, math.floor(scale / 7) - math.floor(scale / 7) % 2)
938
        if not int(gdata.config.defaults.maxfleetsymbolsize) == 0:
939
            rectSize = min(int(gdata.config.defaults.maxfleetsymbolsize), rectSize)
940
        rectSpace = rectSize + math.floor(rectSize/5)
941
        # draw orders lines
942
        if self.control_modes['fleet_lines']:
943
            for x1, y1, x2, y2, color, military in self._map[self.MAP_FORDERS]:
944
                if not self.control_modes['civilian_fleets'] and not military:
945
                    continue
946
                sx1 = int((x1 - currX) * scale) + centerX
947
                sy1 = maxY - (int((y1 - currY) * scale) + centerY)
948
                sx2 = int((x2 - currX) * scale) + centerX
949
                sy2 = maxY - (int((y2 - currY) * scale) + centerY)
950
                pygame.draw.line(mapSurf, color, (sx1, sy1), (sx2, sy2), 1)
951
        # draw fleet symbol
952
        for objID, x, y, oldX, oldY, orbit, eta, color, size, military in self._map[self.MAP_FLEETS]:
953
            if not self.control_modes['civilian_fleets'] and not military:
954
                continue
955
            if self.overlayMode != gdata.OVERLAY_OWNER:
956
                color = res.fadeColor(color)
957
            sx = int((x - currX) * scale) + centerX
958
            sy = maxY - (int((y - currY) * scale) + centerY)
959
            if orbit >= 0 and scale >= 30:
960
                actRect = pygame.Rect(sx + (orbit % 7) * rectSpace + 13 + 2 * (orbit % 7), sy + scale/6 * (orbit / 7) + 6, rectSize, rectSize)
961
                # TODO this is a workaround - fix it when pygame gets fixed
962
                # pygame.draw.polygon(mapSurf, color,
963
                #    (actRect.midleft, actRect.midtop, actRect.midright, actRect.midbottom), 1)
964
                pygame.draw.polygon(mapSurf, color,
965
                    (actRect.midleft, actRect.midtop, actRect.midright, actRect.midbottom), 0)
966
                actRect.move_ip(self.rect.left, self.rect.top)
967
                self._actAreas[objID] = actRect
968
            elif orbit < 0:
969
                rectSizeFlying = rectSize+2
970
                sox = int((oldX - currX) * scale) + centerX
971
                soy = maxY - (int((oldY - currY) * scale) + centerY)
972
                actRect = pygame.Rect(sx - rectSizeFlying / 2, sy - rectSizeFlying / 2, rectSizeFlying , rectSizeFlying)
973
                if military:
974
                    mColor = color
975
                else:
976
                    mColor = (0xff, 0xff, 0xff)
977
                pygame.draw.line(mapSurf, mColor, (sx, sy), (sox, soy), size + 1)
978
                # TODO rotate triangle
979
                pygame.draw.polygon(mapSurf, color,
980
                    (actRect.midleft, actRect.midtop, actRect.midright, actRect.midbottom), 1)
981
                pygame.draw.polygon(mapSurf, color,
982
                    (actRect.midleft, actRect.midtop, actRect.midright, actRect.midbottom), 0)
983
                if eta and scale > 15:
984
                    img = Fonts.renderText(self.textSize, eta, 1, color)
985
                    mapSurf.blit(img, actRect.topright)
986
                actRect.move_ip(self.rect.left, self.rect.top)
987
                self._actAreas[objID] = actRect
988
989
    def drawOverlayEffects(self, mapSurf):
990
        # coordinates
991
        centerX, centerY = mapSurf.get_rect().center
992
        maxY = mapSurf.get_rect().height
993
        currX = self.currX
994
        currY = self.currY
995
        scale = self.scale
996
        # draw overlay specific features, coloring itself is applied in drawPlanets etc.
997
        if self.overlayMode == gdata.OVERLAY_MORALE:
998
            player = client.getPlayer()
999
            if hasattr(player, "planets"):
1000
                centralPlanet = client.get(player.planets[0])
1001
                govPCR = player.govPwrCtrlRange
1002
                player.stats.storPop, player.govPwr
1003
                maxMorale = int(Rules.maxMorale)
1004
                minAchievedMorale = int(max(Rules.minMoraleTrgt - 1, 107.5 - 37.5 * player.stats.storPop / player.govPwr))
1005
                for step in xrange(maxMorale, minAchievedMorale - 1 , -10):
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable xrange does not seem to be defined.
Loading history...
1006
                    moraleColor = res.getMoraleColors(step)
1007
                    centralX = int((centralPlanet.x - currX) * scale) + centerX
1008
                    centralY = maxY - (int((centralPlanet.y - currY) * scale) + centerY)
1009
                    radius = int((107.5 - step) * govPCR / 37.5 * scale)
1010
                    pygame.draw.circle(mapSurf, moraleColor, (centralX, centralY), radius, 1)
1011
                    text = Fonts.renderText(self.textSize, step, 1, moraleColor)
1012
                    #maxW = max(text.get_width(), maxW)
1013
                    mapSurf.blit(text, (centralX + radius, centralY))
1014
1015
1016
1017
1018
1019
    def drawGrid(self, mapSurf):
1020
        rect = mapSurf.get_rect()
1021
        centerX, centerY = rect.center
1022
        maxY = rect.height
1023
        currX = self.currX
1024
        currY = self.currY
1025
        scale = self.scale
1026
        left = int((int(currX) - currX) * scale) + centerX - int(rect.width / scale / 2) * scale
1027
        x = left
1028
        while x < left + rect.width + scale:
1029
            value =  math.floor((x - centerX) / scale + currX)
1030
            if value % 5 == 0:
1031
                pygame.draw.line(mapSurf, (0x00, 0x00, 0x90),
1032
                    (x, rect.top), (x, rect.bottom), 1)
1033
                if self.control_modes['map_grid_coords']:
1034
                    textSrfc = Fonts.renderText(self.textSize, int(value), 1, (0x70, 0x70, 0x80))
1035
                    mapSurf.blit(textSrfc, (x + 2, rect.height - textSrfc.get_height()))
1036
            else:
1037
                pygame.draw.line(mapSurf, (0x33, 0x33, 0x66),
1038
                    (x, rect.top), (x, rect.bottom), 1)
1039
            x += scale
1040
        top = int((int(currY) - currY) * scale) + centerY - int(rect.height / scale / 2) * scale
1041
        y = top
1042
        while y < top + rect.height + scale:
1043
            yScrn = maxY - y
1044
            value =  math.floor(((maxY - yScrn) - centerY) / scale + currY)
1045
            if value % 5 == 0:
1046
                pygame.draw.line(mapSurf, (0x00, 0x00, 0x90),
1047
                    (rect.left, yScrn), (rect.right, yScrn), 1)
1048
                textSrfc = Fonts.renderText(self.textSize, int(value), 1, (0x70, 0x70, 0x80))
1049
                mapSurf.blit(textSrfc, (0, yScrn))
1050
            else:
1051
                pygame.draw.line(mapSurf, (0x33, 0x33, 0x66),
1052
                    (rect.left, yScrn), (rect.right, yScrn), 1)
1053
            y += scale
1054
1055
1056
    def getBuoy(self, objID):
1057
        player = client.getPlayer()
1058
        if hasattr(player, "buoys") and objID in player.buoys:
1059
            lines = player.buoys[objID][0].split("\n")
1060
            if len(lines) > 2:
1061
                return (u"%s\n%s" % (lines[0], lines[1]), player.buoys[objID][1])
1062
            else:
1063
                return player.buoys[objID]
1064
        else:
1065
            if hasattr(player, "alliedBuoys") and objID in player.alliedBuoys:
1066
                if len(player.alliedBuoys[objID]) > 0:
1067
                    lines = player.alliedBuoys[objID][0][0].split("\n")
1068
                    if len(lines) > 2:
1069
                        return (u"%s\n%s" % (lines[0], lines[1]), player.alliedBuoys[objID][0][1])
1070
                    else:
1071
                        return player.alliedBuoys[objID][0]
1072
                else:
1073
                    return None
1074
            else:
1075
                return None
1076
1077