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 Const |
21
|
|
|
import Rules |
22
|
|
|
import Utils |
23
|
|
|
|
24
|
|
|
from ige import GameException, log |
25
|
|
|
from ige.IDataHolder import IDataHolder |
26
|
|
|
from ige.IObject import public |
27
|
|
|
|
28
|
|
|
from IFleet import IFleet |
29
|
|
|
|
30
|
|
|
class IAsteroid(IFleet): |
31
|
|
|
|
32
|
|
|
typeID = Const.T_ASTEROID |
33
|
|
|
|
34
|
|
|
def init(self, obj): |
35
|
|
|
IFleet.init(self, obj) |
36
|
|
|
# other attrs |
37
|
|
|
obj.asDiameter = 0 # diameter |
38
|
|
|
obj.asHP = 0 |
39
|
|
|
obj.impactDelay = 0 |
40
|
|
|
obj.target = Const.OID_NONE |
41
|
|
|
|
42
|
|
|
@public(Const.AL_ADMIN) |
43
|
|
|
def create(self, tran, obj, x, y, targetID, speed, hp): |
44
|
|
|
obj.signature = hp / 50 |
45
|
|
|
obj.x = x |
46
|
|
|
obj.y = y |
47
|
|
|
obj.oldX = x |
48
|
|
|
obj.oldY = y |
49
|
|
|
obj.maxSpeed = speed |
50
|
|
|
obj.speed = speed |
51
|
|
|
obj.asDiameter = max(1, hp / 10) |
52
|
|
|
obj.asHP = hp |
53
|
|
|
obj.target = targetID |
54
|
|
|
obj.owner = Const.OID_NATURE |
55
|
|
|
nature = tran.db[Const.OID_NATURE] |
56
|
|
|
nature.fleets.append(obj.oid) |
57
|
|
|
# create name |
58
|
|
|
counter = 1 |
59
|
|
|
fleets = nature.fleets |
60
|
|
|
while fleets: |
61
|
|
|
name = u'Asteroid %d' % counter |
62
|
|
|
counter += 1 |
63
|
|
|
foundSame = 0 |
64
|
|
|
for fleetID in fleets: |
65
|
|
|
if tran.db[fleetID].name == name: |
66
|
|
|
foundSame = 1 |
67
|
|
|
break |
68
|
|
|
if not foundSame: |
69
|
|
|
break |
70
|
|
|
obj.name = name |
|
|
|
|
71
|
|
|
# register with target system |
72
|
|
|
system = tran.db[tran.db[targetID].compOf] |
73
|
|
|
system.closeFleets.append(obj.oid) |
74
|
|
|
obj.closeSystem = system.oid |
75
|
|
|
# create script |
76
|
|
|
self.cmd(obj).addAction(tran, obj, 0, Const.FLACTION_MOVE, targetID, None) |
77
|
|
|
# |
78
|
|
|
log.debug("Asteroid created", x, y, targetID, speed, hp) |
79
|
|
|
|
80
|
|
|
def update(self, tran, obj): |
81
|
|
|
if obj.impactDelay > Rules.asteroidImpactDelay: |
82
|
|
|
# delete me |
83
|
|
|
self.cmd(obj).disbandFleet(tran, obj) |
84
|
|
|
return |
85
|
|
|
# closest system |
86
|
|
|
if not hasattr(obj, "closeSystem") or not tran.db.has_key(obj.closeSystem): |
87
|
|
|
if obj.orbiting == Const.OID_NONE: |
88
|
|
|
log.warning("No close system for asteroid", obj.oid) |
89
|
|
|
# select any system |
90
|
|
|
systemID = tran.db[tran.db[Const.OID_UNIVERSE].galaxies[0]].systems[0] |
91
|
|
|
obj.closeSystem = systemID |
92
|
|
|
else: |
93
|
|
|
obj.closeSystem = obj.orbiting |
94
|
|
|
system = tran.db[obj.closeSystem] |
95
|
|
|
if system.type == Const.T_SYSTEM: |
96
|
|
|
if obj.oid not in system.closeFleets: |
97
|
|
|
system.closeFleets.append(obj.oid) |
98
|
|
|
else: |
99
|
|
|
log.debug("IAsteroid - invalid orbiting", obj.orbiting) |
100
|
|
|
self.cmd(obj).disbandFleet(tran, obj) |
101
|
|
|
return |
102
|
|
|
# verify close system |
103
|
|
|
if tran.db.has_key(obj.closeSystem): |
104
|
|
|
system = tran.db[obj.closeSystem] |
105
|
|
|
if system.type == Const.T_SYSTEM: |
106
|
|
|
if obj.oid not in system.closeFleets: |
107
|
|
|
#@log.debug("Adding fleet", obj.oid, "into closeFleets", system.oid) |
108
|
|
|
system.closeFleets.append(obj.oid) |
109
|
|
|
else: |
110
|
|
|
obj.closeSystem = Const.OID_NONE |
111
|
|
|
else: |
112
|
|
|
obj.closeSystem = Const.OID_NONE |
113
|
|
|
|
114
|
|
|
update.public = 0 |
115
|
|
|
|
116
|
|
|
def recordScanLevel(self, tran, obj, scanPwr, player, contactType): |
117
|
|
|
if obj.owner == player.oid: |
118
|
|
|
log.warning("Scan on own asteroid!", obj.oid) |
119
|
|
|
return |
120
|
|
|
if scanPwr >= Rules.level1InfoScanPwr: |
121
|
|
|
self.cmd(player).addObjectToMap(tran, player, obj, scanPwr, Const.CONTACT_NONE) |
122
|
|
|
|
123
|
|
|
def getScanInfo(self, tran, obj, scanPwr): |
124
|
|
|
result = IDataHolder() |
125
|
|
|
result._type = Const.T_SCAN |
126
|
|
|
result.scanPwr = scanPwr |
127
|
|
|
if scanPwr > Rules.level1InfoScanPwr: |
128
|
|
|
result.oid = obj.oid |
129
|
|
|
result.x = obj.x |
130
|
|
|
result.y = obj.y |
131
|
|
|
result.oldX = obj.oldX |
132
|
|
|
result.oldY = obj.oldY |
133
|
|
|
result.signature = obj.signature |
134
|
|
|
result.type = obj.type |
135
|
|
|
result.orbiting = obj.orbiting |
136
|
|
|
result.speed = obj.speed |
137
|
|
|
result.eta = obj.eta |
138
|
|
|
if scanPwr > Rules.level2InfoScanPwr: |
139
|
|
|
result.name = obj.name |
140
|
|
|
if scanPwr > Rules.level3InfoScanPwr: |
141
|
|
|
result.asDiameter = obj.asDiameter |
142
|
|
|
result.asHP = obj.asHP |
143
|
|
|
if scanPwr > Rules.level4InfoScanPwr: |
144
|
|
|
pass |
145
|
|
|
return result |
146
|
|
|
|
147
|
|
|
@public(Const.AL_ADMIN) |
148
|
|
|
def processACTIONPhase(self, tran, obj, data): |
149
|
|
|
# ACTIONS |
150
|
|
|
if Utils.isIdleFleet(obj): |
151
|
|
|
#@log.debug('IAsteroid', obj.oid, 'idle') |
152
|
|
|
obj.impactDelay += 1 |
153
|
|
|
return |
154
|
|
|
action, target, actionData = obj.actions[obj.actionIndex] |
155
|
|
|
#@log.debug('IAsteroid', obj.oid, 'processing action', action) |
156
|
|
|
if action == Const.FLACTION_MOVE: |
157
|
|
|
if self.cmd(obj).moveToTarget(tran, obj, target): |
158
|
|
|
# we are there |
159
|
|
|
obj.actionIndex += 1 |
160
|
|
|
else: |
161
|
|
|
raise GameException('Unsupported action %d' % action) |
162
|
|
|
|
163
|
|
|
@public(Const.AL_ADMIN) |
164
|
|
|
def processFINALPhase(self, tran, obj, data): |
165
|
|
|
if obj.impactDelay > Rules.asteroidImpactDelay: |
166
|
|
|
# delete me |
167
|
|
|
self.cmd(obj).disbandFleet(tran, obj) |
168
|
|
|
|
169
|
|
|
## |
170
|
|
|
## Combat related functions |
171
|
|
|
## |
172
|
|
|
|
173
|
|
|
def getPreCombatData(self, tran, obj): |
174
|
|
|
if obj.impactDelay > Rules.asteroidImpactDelay: |
175
|
|
|
# modify target's environment and minerals |
176
|
|
|
planet = tran.db[obj.target] |
177
|
|
|
#planet.plBio = max(0, int(planet.plBio + obj.asHP * Rules.asteroidPerHPBioMod)) |
178
|
|
|
#planet.plMin = min(200, int(planet.plMin + obj.asHP * Rules.asteroidPerHPMinMod)) |
179
|
|
|
# special shots from asteroid |
180
|
|
|
hp = obj.asHP |
181
|
|
|
shots = [] |
182
|
|
|
if hp > 1500: |
183
|
|
|
shots.append((Rules.asteroidAttack, Rules.Tech.ASTEROID1000)) |
184
|
|
|
hp = hp % 1000 |
185
|
|
|
if hp > 150: |
186
|
|
|
shots.append((Rules.asteroidAttack, Rules.Tech.ASTEROID100)) |
187
|
|
|
hp = hp % 100 |
188
|
|
|
if hp > 15: |
189
|
|
|
shots.append((Rules.asteroidAttack, Rules.Tech.ASTEROID10)) |
190
|
|
|
hp = hp % 10 |
191
|
|
|
if hp > 1: |
192
|
|
|
shots.append((Rules.asteroidAttack, Rules.Tech.ASTEROID1)) |
193
|
|
|
# destroy asteroid |
194
|
|
|
self.cmd(obj).disbandFleet(tran, obj) |
195
|
|
|
return shots, [0, 0, 0, 1] |
196
|
|
|
else: |
197
|
|
|
obj.impactDelay += 1 |
198
|
|
|
log.debug("Asteroid impact delay", obj.impactDelay) |
199
|
|
|
return [], [0, 0, 0, 1] |
200
|
|
|
|
201
|
|
|
getPreCombatData.public = 0 |
202
|
|
|
|
203
|
|
|
def applyShot(self, tran, obj, attack, weaponID, targetClass, target): |
204
|
|
|
#@log.debug('IAsteroid', 'Apply shot', attack, weaponID, attack, cClass, count) |
205
|
|
|
# compute if asteroid has been hit |
206
|
|
|
weapon = Rules.techs[weaponID] |
207
|
|
|
if weapon.weaponIsMissile: |
208
|
|
|
defense = Rules.asteroidMisDef |
209
|
|
|
else: |
210
|
|
|
defense = Rules.asteroidDef |
211
|
|
|
destroyed = 0 |
212
|
|
|
dmg = 0 |
213
|
|
|
if Utils.rand(1, attack + defense + 1) > defense: |
214
|
|
|
# hit |
215
|
|
|
dmg = Utils.rand(weapon.weaponDmgMin, weapon.weaponDmgMax + 1) |
216
|
|
|
obj.asHP -= dmg |
217
|
|
|
if obj.asHP <= 0: |
218
|
|
|
destroyed = 1 |
219
|
|
|
# destroy asteroid |
220
|
|
|
self.cmd(obj).disbandFleet(tran, obj) |
221
|
|
|
#@log.debug('IAsteroid', 'Shot applied', dmg, destroyed) |
222
|
|
|
return dmg, destroyed, 3 |
223
|
|
|
|
224
|
|
|
applyShot.public = 0 |
225
|
|
|
|
226
|
|
|
def addExp(self, tran, obj, shipTechID, dmg): |
227
|
|
|
pass |
228
|
|
|
|
229
|
|
|
addExp.public = 0 |
230
|
|
|
|
231
|
|
|
def surrenderTo(self, tran, obj, newOwnerID): |
232
|
|
|
# never surrender |
233
|
|
|
return 0 |
234
|
|
|
|
235
|
|
|
surrenderTo.public = 0 |
236
|
|
|
|