Vega strike Python Modules doc  0.5.1
Documentation of the " Modules " folder of Vega strike
 All Data Structures Namespaces Files Functions Variables
mission_lib.py
Go to the documentation of this file.
1 """ This moduleprovides functions for creating, storing and activating
2 campaign, guild, and fixer missions.
3 """
4 
5 import Director
6 import patrol
7 import cargo_mission
8 import bounty
9 import plunder
10 import defend
11 import escort_mission
12 import vsrandom
13 import universe
14 import faction_ships
15 import VS
16 import PickleTools
17 import adventure
18 import debug
19 
20 players=[]
21 
23  def __init__(self):
24  self.active_missions = []
26  self.hookargs = None
27  self.resetLastMission()
28 
29  def resetLastMission(self):
31  self.last_args ={}
32  self.last_briefing=[{},{}]
33  self.last_briefing_vars=[{},{}]
34  self.lastMission=None
35 
36 def addPlayer(num, reset=True):
37  while len(players)<=num:
38  players.append(PlayerMissionInfo())
39  if reset:
40  players[num] = PlayerMissionInfo()
41 
42 addPlayer(VS.getNumPlayers()-1)
43 
44 # addPlayer(0) #single player -- add 0th player.
45 global_plr = -1
46 
48  # Will allow to hardcode a player number in certain cases.
49  if global_plr >= 0:
50  return global_plr
51  else:
52  return VS.getCurrentPlayer()
53 
54 def setMissionPlayer(plr=-1):
55  global global_plr
56  global_plr = plr
59 
60 def mission_lib_custom(local, cmd, args, id):
61  if args[0] == 'AddNewMission':
62  which = args[1]
63  brief0 = args[2]
64  brief1 = args[3]
65  num_briefing_vars = int(args[4])
66  briefing_vars = {}
67  for i in range(num_briefing_vars):
68  briefing_vars[args[i*2+5]] = args[i*2+6]
69  AddNewMission(which, None, None, brief0, brief1, briefing_vars, briefing_vars)
70  elif args[0] == 'LoadLastMission':
71  which = args[1]
72  LoadLastMission(which)
73  elif args[0] == 'CreateFixerMissions':
74  ret = CreateFixerMissions()
75  vals = [0]
76  for m in ret:
77  if isinstance(m,tuple):
78  vals += m
79  vals[0] += 1
80  return vals
81 
82 import custom
83 custom.add('mission_lib', mission_lib_custom)
84 
86  def __init__(self,amentry):
88  debug.debug("New Mission entry: %s (%s)" % (self.amentry_id,amentry.get('MISSION_SHORTDESC','')))
89  def __del__(self):
91  debug.debug("Mission entry %s destroyed." % self.amentry_id)
92 
94  players[getMissionPlayer()].hookargs = args
95 
96 def AddMissionHooks(director):
97  hookargs = players[getMissionPlayer()].hookargs
98  doMissionHooks=True
99  try:
100  if hasattr(director,'aborted'):
101  if getattr(director,'aborted'):
102  doMissionHooks=False
103  except:
104  import sys
105  debug.debug(sys.exc_info()[0])
106  debug.debug(sys.exc_info()[1])
107  debug.debug("CARGO MISSION ABORTING done")
108  if doMissionHooks:
109  director.mission_hooks___ = missionhook(hookargs)
110 
111 def SetLastMission(which):
112  players[getMissionPlayer()].lastMission = str(which)
113  debug.debug('set last mission to "'+str(which)+'"')
114 
115 def LoadLastMission(which=None):
116  """ Makes a mission an active mission. """
117  print "#given mission argument: ", which
118  plr = getMissionPlayer()
119  if which is None:
120  which = str(players[plr].lastMission)
121  print "#loading mission: ", which
122  if VS.networked():
123  custom.run('mission_lib', ['LoadLastMission',which], None)
124  return
125 
126  last_constructor = players[plr].last_constructor
127  last_args = players[plr].last_args
128  last_briefing_vars = players[plr].last_briefing_vars
129  last_briefing = players[plr].last_briefing
130  ret = True
131  if which in last_constructor and which in last_args:
132  if last_constructor[which]==None:
133  if type(last_args[which])==str:
134  script = "%(args)s"
135  else:
136  script = "%(args)r()"
137  vars = dict(args=last_args[which])
138  else:
139  script = '''#
140 import %(constructor)s
141 temp=%(constructor)s.%(constructor)s%(args)s
142 mission_lib.AddMissionHooks(temp)
143 temp=0
144 '''
145  cons=last_constructor[which]
146  if type(cons)!=str:
147  cons=cons.__name__
148  if type(last_args[which])==str:
149  args = last_args[which]
150  else:
151  args = repr(last_args[which])
152  vars = dict(constructor=cons,args=args)
153  script = script % vars
154  if script[:1] == '#':
155  prescript = '''#
156 import mission_lib
157 mission_lib.SetMissionHookArgs(%(amentry)r)
158 %(postscript)s'''
159  amentry = last_briefing_vars[0].get(which,dict())
160  try:
161  amentry.update(last_briefing_vars[1].get(which,dict()).iteritems())
162  amentry.update([
163  #('MISSION_NAME',which),
164  ('DESCRIPTION',last_briefing[0].get(which,'')),
165  ('ACCEPT_MESSAGE',last_briefing[1].get(which,''))
166  ])
167  except:
168  debug.error("TRACING BACK")
169  import sys
170  debug.error(sys.exc_info()[0])
171  debug.error(sys.exc_info()[1])
172  debug.error("BACKTRACE done")
173  ret = False
174  vars = dict(amentry=amentry,postscript=script)
175  script = prescript % vars
176  debug.debug("Loading mission:\n%s" % script)
177  VS.LoadNamedMissionScript(which, script)
178  else:
179  debug.debug('No last mission with name "'+str(which)+'"')
180  ret = False
181  RemoveLastMission(which)
182  return ret
183 
184 def RemoveLastMission(which=None):
185  plr = getMissionPlayer()
186  if which is None:
187  which=players[plr].lastMission
188 
189  last_constructor = players[plr].last_constructor
190  last_args = players[plr].last_args
191  last_briefing_vars = players[plr].last_briefing_vars
192  last_briefing = players[plr].last_briefing
193  for container in ( last_args,last_constructor,
194  last_briefing[0],last_briefing[1],
195  last_briefing_vars[0],last_briefing_vars[1] ):
196  if which in container:
197  del container[which]
198  players[plr].lastMission=None
199 
201  plr = getMissionPlayer()
202  active_missions = players[plr].active_missions
203  active_missions_nextid = players[plr].active_missions_nextid
204 
205  active_missions.append(entry)
206  active_missions[-1].update([('ENTRY_ID',active_missions_nextid)])
207  active_missions_nextid += 1
208  return active_missions_nextid-1
209 
211  plr = getMissionPlayer()
212  players[plr].active_missions = filter(lambda x:x.get('ENTRY_ID',None)!=entry_id,
213  players[plr].active_missions)
214 
215 def CountMissions(first,prefix):
216  plr = getMissionPlayer()
217  last_briefing = players[plr].last_briefing
218 
219  nummissions = 0
220  for which in last_briefing[first]:
221  if str(which).startswith(prefix):
222  nummissions = nummissions + 1
223  return nummissions
224 
225 def BriefLastMission(whichid,first,textbox=None,template='#DESCRIPTION#'):
226  """ Outputs the briefing from fixer missions on the base screen. """
227  plr = getMissionPlayer()
228  last_briefing = players[plr].last_briefing
229  last_briefing_vars = players[plr].last_briefing_vars
230 
231  # Compare the given mission id with the id stored in the briefing vars
232  # If match is found, retrieve the mission name, which is also the mission key
233  which = None
234  for name in last_briefing_vars[0]:
235  if last_briefing_vars[0][name]['MISSION_ID'] == str(whichid):
236  which = name
237  # Should not happen anymore, but sometimes missions have all the same id,
238  # e.g. 1, and then no missions for id 0 will e found.
239  if which == None:
240  which = last_briefing_vars[0].keys()[0]
241  debug.warn("mission_lib.BriefLastMission couldn't find mission id"+ str(whichid))
242 
243  if first<0 or first>=len(last_briefing):
244  return
245  if (which in last_briefing[first]):
246  # compute variables
247  s_which = str(which).split('/')
248  w_prefix = ''
249  curmission = s_which[len(s_which)-1]
250  if curmission.isdigit():
251  # But for numeric identifiers, convert base-0 to base-1 indices
252  curmission = str(int(curmission)+1)
253  else:
254  # allow non-numeric mission identifiers ( 'Disc_1', anyone? )
255  currmission = str(whichid)
256  for i in s_which[:len(s_which)-1]:
257  w_prefix += str(i) + '/'
258  nummissions = CountMissions(first,w_prefix)
259 
260  # replace variables in template
261  template = template.replace('#MISSION_NUMBER#',str(curmission))
262  template = template.replace('#MISSION_ID#',str(whichid))
263  template = template.replace('#GUILD_NAME#',s_which[0])
264  template = template.replace('#NUM_MISSIONS#',str(nummissions))
265  template = template.replace('#DESCRIPTION#',str(last_briefing[first][which]))
266  template = template.replace('#SHORT_DESCRIPTION#',str(last_briefing_vars[first][which]['MISSION_SHORTDESC']))
267  try:
268  template = template.replace('#MISSION_TYPE#',last_briefing_vars[first][which]['MISSION_TYPE'])
269  except:
270  template = template.replace('#MISSION_TYPE#','')
271 
272  # set text
273  import Base
274  if textbox:
275  Base.SetTextBoxText(Base.GetCurRoom(),textbox, template)
276  else:
277  Base.Message (template)
278  # Remember this mission as the last one being processed.
279  SetLastMission(which)
280 
281 def AddNewMission(which,args,constructor=None,briefing0='',briefing1='',vars0=None,vars1=None):
282  """ Adds a mission to the list of missions stored in playerInfo. """
283  if not isinstance(vars0,dict):
284  vars0 = dict()
285  vars1 = vars0
286  if VS.isserver():
287  lenvars0=len(vars0)
288  sendargs = ["AddNewMission", which, briefing0, briefing1,lenvars0]
289  for key in vars0:
290  sendargs.append(key)
291  sendargs.append(vars0[key])
292  custom.run("mission_lib", sendargs, None)
293 
294  plr = getMissionPlayer()
295  addPlayer(plr, False)
296  playerInfo = players[plr]
297 
298  which = str(which)
299  playerInfo.last_constructor[which] = constructor
300  playerInfo.last_args[which] = args
301  playerInfo.last_briefing[0][which] = briefing0
302  playerInfo.last_briefing[1][which] = briefing1
303  playerInfo.last_briefing_vars[0][which] = vars0
304  playerInfo.last_briefing_vars[1][which] = vars1
305 
306 def GetMissionList(activelist=True):
307  """ Returns a list of missions that were already generated.
308  With the activelist parameter, one can filter the active or
309  all missions.
310  """
311  plr = getMissionPlayer()
312  active_missions = players[plr].active_missions
313  last_briefing_vars = players[plr].last_briefing_vars
314  last_briefing = players[plr].last_briefing
315 
316  if activelist:
317  return active_missions
318  else:
319  return list( dict( list(last_briefing_vars[0][index].iteritems())+
320  [('DESCRIPTION',last_briefing[0][index]),
321  ('ACCEPT_MESSAGE',last_briefing[1][index]),
322  ('MISSION_NAME',index)] )
323  for index in last_briefing[0] )
324 
325 def Jumplist (jumps):
326  if not len(jumps):
327  return 'Your destination is this system.'
328  str="First of all, you will need to fly to the %s jumppoint. "%jumps[0].split('/')[-1]
329  for j in jumps[1:]:
330  str+="Then jump in the %s jumppoint. "%j.split('/')[-1]
331  return str
332 
333 def MakePlunder(which):
334  constructor = plunder.plunder
335  creds=vsrandom.randrange(15,25)*1000
336  args = (creds,'pirates',5,'Contraband',1)
337  briefing0 = 'Arr Matey. We have a target in this system that needs a lil roughin up. We need you to bag a merchant and deliver her cargo into our hands. It\'s worth '+str(creds)+ ' to us. Up to you, ya space pirate.'
338  briefing1 = 'Ahoy! We\'ll be lookin for that cargo mighty soon!'
339  vars = { 'MISSION_TYPE' : 'PIRACY',
340  'MISSION_SHORTDESC' : 'Plunder merchant target for %s' % creds }
341  try:
342  vars['MISSION_ID'] = vars['MISSION_ID']
343  except:
344  vars['MISSION_ID'] = which
345  description = vars['MISSION_SHORTDESC']
346  AddNewMission(description,args,constructor,briefing0,briefing1,vars,vars)
347  return ("bases/fixers/pirate.spr","Talk with the Pirate",which)
348 
349 def MakeContraband(which):
350  constructor = cargo_mission.cargo_mission
351  numsys=vsrandom.randrange(2,5)
352  jumps=universe.getAdjacentSystems(VS.getSystemFile(),numsys)[1]
353  diff=vsrandom.randrange(0,3)
354  creds=numsys*2500+diff*800
355  args = ('pirates', 0, 6, diff,creds, 1, 1200, 'Contraband',jumps)
356  briefing0 = 'We need some...*cough*... cargo delivered to some of our pirates in a nearby system: '+ Jumplist(jumps)+ ' It\'d be preferable if ye kept the ole po\' off yo back durin the run. Will ya do it for '+str(creds)+' creds?'
357  briefing1 = 'Thanks pal; keep it on the d&l if you know my meanin.'
358  vars = { 'MISSION_TYPE' : 'CONTRABAND',
359  'MISSION_SHORTDESC' : 'Deliver contraband to %s for %s' % (Jumplist(jumps),creds) }
360  try:
361  vars['MISSION_ID'] = vars['MISSION_ID']
362  except:
363  vars['MISSION_ID'] = which
364  description = vars['MISSION_SHORTDESC']
365  AddNewMission(description,args,constructor,briefing0,briefing1,vars,vars)
366  return ("bases/fixers/pirate.spr","Talk with the Pirate",which)
367 
368 def CreateRandomMission(whichnum):
369  """ This function gets a random mission and saves the information in
370  an array as the which element. Returns the sprite file and text."""
371  which = str(whichnum)
372  missiontype = vsrandom.random();
373  fac = VS.GetGalaxyFaction(VS.getSystemFile())
374  if fac=="pirates":
375  if (missiontype>.5):
376  return None
377  missiontype*=.2;
378  elif (VS.GetRelation(fac,"pirates")<-.8 and missiontype<.1):
379  missiontype = 0.1 + 0.9 * missiontype
380  plr = getMissionPlayer()
381  if (missiontype<.05):
382  return MakePlunder(which)
383  elif (missiontype<.1):
384  return MakeContraband(which)
385  else:
386  goodlist = []
387  for indx in range(Director.getSaveStringLength(plr, "mission_scripts")):
388  script=Director.getSaveString(plr,"mission_scripts",indx)
389  if script.find("#F#")!=-1:
390  goodlist.append(indx)
391  goodlist.sort()
392  goodlist.reverse()
393  if len(goodlist):
394  i = goodlist[vsrandom.randrange(len(goodlist))]
395  script = Director.getSaveString(plr,"mission_scripts",i)
396  desc = Director.getSaveString(plr,"mission_descriptions",i)
397  vars = PickleTools.decodeMap( Director.getSaveString(plr,"mission_vars",i) )
398  vars.setdefault('MISSION_SHORTDESC',Director.getSaveString(plr, "mission_names",i))
399  Director.eraseSaveString(plr,"misson_scripts",i)
400  Director.eraseSaveString(plr,"misson_descriptions",i)
401  Director.eraseSaveString(plr,"misson_names",i)
402  Director.eraseSaveString(plr,"misson_vars",i)
403  mylist = script.split("#") ###Skip the first two because first is always '' and second is always 'F'
404  try:
405  vars['MISSION_ID'] = vars['MISSION_ID']
406  except:
407  vars['MISSION_ID'] = which
408  description = vars['MISSION_SHORTDESC'].split("/")[1]
409  vars['MISSION_NAME'] = description
410  AddNewMission(description,script,None,desc,mylist[4],vars,vars)
411  return (mylist[2], mylist[3], which, description)
412  else:
413  # It should only get here if no fixer missions were found
414  return None # Fixer code will generate a NoFixer hopefully.
415 
417  """ This function creates missions with ids "0" and "1" for use with the fixers
418  on bases.
419  """
420  rndnum = vsrandom.random()
421  fixers = []
422  if rndnum<0.7:
423  f = CreateRandomMission(0)
424  fixers.append(f)
425  img = None
426  if f:
427  img = f[0]
428  rndnum = vsrandom.random()
429  if rndnum<0.6:
430  i = 0
431  newimg = img
432  while newimg==img and i<10:
433  f = CreateRandomMission(1)
434  if f:
435  newimg = f[0]
436  i += 1
437  if i<10:
438  fixers.append(f)
439  return fixers
440 
441 ###### Unused code -- has old briefings
442 ## if (searchMissionNameStr("patrol")):
443 ## last_briefing[0][which] = 'Confed needs the help of mercs and hunters to keep our air space clean. There are increasing reports of pirate and alien activity in these sectors and we need your sensor data. '+Jumplist(jumps) +' Will you do the patrol in said system for '+str(creds)+' credits?'
444 ## if (searchMissionNameStr("cargo")):
445 ## last_briefing[0][which] = 'Our business needs you to run some legit goods to a base a few systems away. '+ Jumplist(jumps) + ' This is worth '+str(creds)+' to us.'
446 ## if (diff>=2):
447 ## last_briefing[0][which]+=' However, you cannot fail us! There are consequences for your actions in this universe.'
448 ## if (searchMissionNameStr("bounty")):
449 ## last_briefing[0][which] = 'We need you to hit a nearby target. '+Jumplist(jumps)+' Our reward is '+str(creds)+' will you do it?'
450 ## if (searchMissionNameStr("defend")):
451 ## last_briefing[0][which] = 'We need help to secure a nearby strategic point in this system. Eliminate all enemies there. We offer '+str(encred)+' per enemy. Will you do it?'
452 ## if (base):
453 ## last_briefing[0][which] = 'One of our capitol vessels is under attack in this system! We call to the aid of all bounty hunters to defend it. Our reward is '+str(encred)+' per enemy craft destroyed. Will you help us?'
454 
455 def PickRandomMission(goodlist):
456  bounds = 0
457  for mis in goodlist:
458  bounds = bounds + mis[1]
459  if bounds:
460  pos = vsrandom.randrange(bounds)
461  for midx in range(len(goodlist)):
462  if pos>=goodlist[midx][1]:
463  pos = pos - goodlist[midx][1]
464  else:
465  return midx
466  return len(goodlist)-1
467  else:
468  return None
469 
470 # accepttypes is a dictionary that takes mission types as keys, and has
471 # mission frequencies (likelihood of appearing) as values. A special key
472 # is the asterisk ('*'), which is a wildcard key that applies to any other
473 # key. If a mission's type cannot find a matching key (the wildcard matches
474 # all), then it will have frequency 0 (meaning, it will be disallowed).
475 def CreateGuildMissions(guildname,nummissions,accepttypes,prefix="#G#",acceptmsg=''):
476  plr=getMissionPlayer()
477  addPlayer(plr, False)
478 
479  goodlist=[]
480  for indx in range(Director.getSaveStringLength(plr, "mission_scripts")):
481  script=Director.getSaveString(plr,"mission_scripts",indx)
482  if (script.find(prefix)!=-1):
483  missiontype=script[3:script.find('#',3)]
484  freq = 0
485  if (accepttypes==None):
486  freq = 1
487  elif (missiontype in accepttypes):
488  freq = accepttypes[missiontype]
489  elif ('*' in accepttypes):
490  freq = accepttypes['*']
491  if freq:
492  goodlist.append( (indx,freq) )
493  if len(goodlist)<nummissions:
494  nummissions=len(goodlist)
495  delit=[]
496  for missionnum in range(0,nummissions):
497  goodi=PickRandomMission(goodlist)
498  if goodi == None:
499  break
500  i=goodlist[goodi][0]
501  which=guildname+'/'+str(missionnum)
502  script=Director.getSaveString(plr,"mission_scripts",i)
503  desc=Director.getSaveString(plr,"mission_descriptions",i)
504  vars=PickleTools.decodeMap( Director.getSaveString(plr,"mission_vars",i) )
505  vars.setdefault('MISSION_SHORTDESC',Director.getSaveString(plr,"mission_names",i))
506  delit.append(i)
507  AddNewMission(which,script,None,desc,acceptmsg,vars,vars)
508  goodlist.pop(goodi)
509  delit.sort()
510  delit.reverse()
511  for i in delit:
512  Director.eraseSaveString(plr,"mission_scripts",i)
513  Director.eraseSaveString(plr,"mission_descriptions",i)
514  Director.eraseSaveString(plr,"mission_names",i)
515  Director.eraseSaveString(plr,"mission_vars",i)
516  #more reliable... sometimes we run out of good missions,
517  #sometimes we have preexistent missions (!)
518  return CountMissions(0,guildname)