War Robots Wiki:Compute Damage Source Code

The compute_damage source code follows. Copy it entirely into a text editor and save it as computedamage.py in a directory of your choice.

Code Status
Fully up to date for v. 4.0. Check the version when you compute the damage for a weapon! (see Updates)

Source Code
# # # import numpy as np import matplotlib.pyplot as pl import re def wdatabase: global wea #class listing all weapons as a dictionary wea={} #Aphid comm='--' dmg=(np.array([0,0,0,0,1230,1350,1480,1630,1790,1970,2170,2380], dtype='float64')) wea['aphid']=({'dmg':dmg,'clip':8,'rwf':False,'accel':False,'rof':8,       'rel':10,'dist':False,'version':4.0,'comm':comm}) #Arbalest comm=('Source: pixo. Same system as Trebuchet, has 10 charges,'+          '\nrecharges 1 per second after a 1s cooldown, hence 11s recharge.'+           '\nHere considering only full charge shot. Rel=10 to account for'+           '\n1s to unload, to get to the real 11s total (fire is almost'+ '\ninstantaneous).') dmg = (np.array([2520,2760,3000,3240,3600,3960,4320,4800,5280,5760,6360, 6960],dtype='float64')) wea['arbalest']=({'dmg':dmg,'clip':1,'rwf':False,'accel':False,'rof':1,       'rel':10,'dist':False,'version':4.0,'comm':comm}) #Avenger comm=("Acceleration after 3s assumed instantaneous, not clear"+          "\nif this is the case. Added in 4.0") dmg = (np.array([320,350,380,420,460,510,560,610,670,740,810,885], dtype='float64')) wea['avenger']=({'dmg':dmg,'clip':440,'rwf':False,'accel':True,'rof':20.,       'rel':10,'dist':False,'accfact':1.5,'acctime':3,'version':4.0,        'comm':comm}) #Ballista comm=('Source: pixo. Same system as Trebuchet, has 10 charges,'+          '\nrecharges 1 per second after a 12s cooldown, hence 12s recharge.'+           '\nHere considering only full charge shot. As for Arbalest, 1s'+           '\nis subtracted from reload to account for firing.') dmg = (np.array([3500,3900,4300,4700,5200,5700,6300,6900,7600,8300,9100, 10000],dtype='float64')) wea['ballista']=({'dmg':dmg,'clip':1,'rwf':False,'accel':False,'rof':1,       'rel':11,'dist':False,'version':4.0,'comm':comm}) #Chimera comm=('Fire rate from Wiki (5.2s per 9 missiles)') dmg = (np.array([1150,1260,1390,1530,1680,1850,2030,2230,2450,2690,2960, 3250 ],dtype='float64')) wea['chimera']=({'dmg':dmg,'clip':9,'rwf':False,'accel':False,'rof':1.73,       'rel':12,'dist':False,'version':4.0,'comm':comm}) #Dragoon comm=('source: Pixo. Pixo declares recharge 3s per shot, 1 shot per'+          '\nsecond,live server confirms') dmg = (np.array([3010,3310,3640,4000,4400,4830,5310,5830,6410,7040,7740, 8500],dtype='float64')) wea['dragoon']=({'dmg':dmg,'clip':4,'rwf':True,'accel':False,'rof':1,       'rel':12,'dist':False,'version':4.0,'comm':comm}) #Ember comm=('The damage is per SECOND in the wiki table, so since the Ember'+          '\nconsumes 30 l/s and has 300l of fuel, I divided dmg per second'+           '\nby 30 to get the per-liter damage. Values from Pixonic higher,'+           '\nwiki has lower and is LIKELY correct, so I use Wiki') dmg = (np.array([170, 190, 210, 230, 250, 280, 310, 340, 370, 410, 450, 490],dtype='float64')) wea['ember']=({'dmg':dmg,'clip':300,'rwf':False,'accel':False,'rof':30,       'rel':5,'dist':False,'version':4.0,'comm':comm}) #Flux comm=('Numbers on Pixo site and wiki do not add up:'+          '\ndamage "per particle" is in fact per SECOND, while 1.1s is the'+           '\ntime to reload one of the 10 charges. From a video provided by'+           '\nJ.Khoo I derive a burst time of 5s, full cycle 15s, from that I'+           '\nreverse engineer the fire rate.') dmg = (np.array([2380,2620,2880,3160,3470,3810,4190,4600,5050,5550,6100,6700] ,dtype='float64')) #the next is because the damage as listed is per SECOND dmg=dmg/2.8 wea['flux']=({'dmg':dmg,'clip':10,'rwf':True,'accel':False,'rof':2.8,       'rel':11,'dist':False,'version':4.0,'comm':comm}) #Gekko comm=('Numbers are a tweaked version of what is on the new Pixo website:'+    '\n-number per particle divided by 10 (it was evidently per second).'+     '\nThis reproduces the burst duration, and is'+     '\ncoherent with the damage in the wiki, whch SEEMS to be computed '+     '\nwithout taking into accout RWF (@ 20180201)') dmg = (np.array([0,0,0,0,157.0,172.0,189.0,208.0,229.0,252.0,277.0,304.0] ,dtype='float64')) wea['gekko']=({'dmg':dmg,'clip':30,'rwf':True,'accel':False,'rof':10.,       'rel':11,'dist':False,'version':4.0,'comm':comm}) #Gust comm='Damage listed is for all four pellets. 10% increase in 3.7.' dmg = (np.array([1948,2140,2352,2588,2844,3124,3432,3772,4144,4556,5004, 5500],dtype='float64')) wea['gust']=({'dmg':dmg,'clip':9,'rwf':True,'accel':False,'rof':2,'rel':9.,       'dist':False,'version':4.0,'comm':comm}) #Hydra comm=('Source: Pixo site for 1.25 rps, old & wiki says 1.5 L11 '+          '\& 12 dam 10 higer on wiki.') dmg = (np.array([930,1020,1120,1230,1350,1480,1630,1790,1970,2170,2380, 2620],dtype='float64')) wea['hydra']=({'dmg':dmg,'clip':6,'rwf':False,'accel':False,'rof':1.25,       'rel':12,'dist':False,'version':4.0,'comm':comm}) #Ion comm='Numbers from Warrobots.net' dmg = (np.array([4480,4920,5410,5940,6530,7180,7890,8670,9530,10470, 11510,12650],dtype='float64')) wea['ion']=({'dmg':dmg,'clip':1,'rwf':False,'accel':False,'rof':1,'rel':5,       'dist':False,'version':4.0,'comm':comm}) #Kang-Dae comm='--' dmg = (np.array([0,0,0,0,7480,8220 ,9030 ,9920 ,10900,11980,13160,14465], dtype='float64')) wea['kang-dae']=({'dmg':dmg,'clip':1,'rwf':False,'accel':False,'rof':1,       'rel':15,'dist':False,'version':4.0,'comm':comm}) #Magnum comm=('Pixo site indicates slight decrease in fire rate 2.0 --> 1.82,'+          '\nnot reported by wiki, but confirmed by testing.') dmg = (np.array([720,790,870,960,1060,1160,1270,1400,1540,1690,1860,2040] ,dtype='float64')) wea['magnum']=({'dmg':dmg,'clip':1,'rwf':False,'accel':False,'rof':1.82,       'rel':0,'dist':False,'version':4.0,'comm':comm}) #Molot comm=('Pixo site reports fire rate 4.65 not 4.2, but it is '+          '\nincompatible with burst duration.') dmg = (np.array([253,275,297,330,363,396,440,484,528,583,638,704], dtype='float64')) wea['molot']=({'dmg':dmg,'clip':70,'rwf':False,'accel':True,'rof':4.2,       'rel':10,'dist':False,'accfact':1.5,'acctime':3,'version':4.0,        'comm':comm}) #Molot T    comm=('Pixo site reports fire rate 4.65 not 4.2, but it is '+          '\nincompatible with burst duration') dmg = (np.array([380,420 ,460 ,500 ,550 ,600 ,660 ,730 ,800 ,880 ,970 , 1070],dtype='float64')) wea['molot_t']=({'dmg':dmg,'clip':70,'rwf':False,'accel':True,'rof':4.2,       'rel':10,'dist':False,'accfact':1.5,'acctime':3,'version':4.0,        'comm':comm}) #Nashorn comm='--' dmg = (np.array([0,0,4300,4720,5190,5700,6260,6880,7560,8310,9130,10038], dtype='float64')) wea['nashorn']=({'dmg':dmg,'clip':1,'rwf':False,'accel':False,'rof':1.,       'rel':9,'dist':False,'version':4.0,'comm':comm}) #Noricum comm=('ROF updated to 20 as per warrobots.net. min. damage 609, '+          '\nagain wr.net, wiki says 210.') dmg = np.array([0,0,0,0,609,670,736,809,889,977,1073,1180],dtype='float64') wea['noricum']=({'dmg':dmg,'clip':14,'rwf':False,'accel':False,'rof':20,       'rel':15,'dist':False,'version':4.0,'comm':comm}) #Orkan comm='--' dmg = (np.array([0,0,0,0,970,1070,1180,1300,1430,1570,1720, 1890],dtype='float64')) wea['orkan']=({'dmg':dmg,'clip':32,'rwf':True,'accel':False,'rof':8.3,       'rel':23,'dist':False,'version':4.0,'comm':comm}) #Pin comm="Pixo site writes wrongly 1.5s to unload: it's 2." dmg = (np.array([0,0,0,0,1420,1560,1710,1880,2070,2280,2510,2760], dtype='float64')) wea['pin']=({'dmg':dmg,'clip':4,'rwf':True,'accel':False,'rof':2,'rel':12,       'dist':False,'version':4.0,'comm':comm}) #Piñata comm="--" dmg = (np.array([0,0,0,0,760,830,910,1000,1100,1210,1330,1460], dtype='float64')) wea['pinata']=({'dmg':dmg,'clip':17,'rwf':True,'accel':False,'rof':8.3,       'rel':15,'dist':False,'version':4.0,'comm':comm}) #Punisher comm=("Acceleration after 3s assumed instantaneous, not clear"+          "\nif this is the case") dmg = (np.array([160,180,200,220,240,260,290,320,350,390,430,470], dtype='float64')) wea['punisher']=({'dmg':dmg,'clip':220,'rwf':False,'accel':True,'rof':8.3,       'rel':10,'dist':False,'accfact':1.5,'acctime':3,'version':4.0,        'comm':comm}) #Punisher T    comm=("Acceleration after 3s assumed instantaneous, not clear"+           "\nif this is the case") dmg = (np.array([260,290,320,350,390,430,470,520,570,630,690,760], dtype='float64')) wea['punisher_t']=({'dmg':dmg,'clip':220,'rwf':False,'accel':True,       'rof':8.3,'rel':10,'dist':False,'accfact':1.5,'acctime':3,        'version':4.0,'comm':comm}) #Redeemer comm=("source: wiki (corresponds w. Pixo)."+    "\nalways fires two blobs together. Damage in Pixo site is per blob,"+     "\n10 total blobs, 1.5 seconds btw. every pair. So one can fire 6 actual"+     "\ncharges, So I use clip 6, rof 0.6667, and two-blob damage in dmg.") dmg = (np.array([ 6020, 6620,  7280,  8000,  8800,  9660, 10620, 11660, 12820,14080, 15480, 17000],dtype='float64')) wea['redeemer']=({'dmg':dmg,'clip':6,'rwf':False,'accel':False,       'rof':0.6667,'rel':5.,'dist':False,'version':4.0,'comm':comm}) #Scourge comm=("warrobots.net calls it 'damage per particle',"+          "\nbut it is actually per second.") dmg = (np.array([179,197,217,238,261,287,315,346,380,418,459,504], dtype='float64')) wea['scourge']=({'dmg':dmg,'clip':100,'rwf':False,'accel':False,'rof':10,       'rel':5,'dist':True,'distances':[400,600],'distance_values':[504.,126.],        'version':4.0,'comm':comm}) #Shocktrain comm=("source: wiki (corresponds w. Pixo). Using full charge, i.e."+          "\ngiving rof 1, rel 9 and clip 1, and the damage per 7 charges.") dmg = (np.array([5530, 6090,  6720,  7350,  8050,  8820, 9660, 10640, 11690,12880, 14140, 15505],dtype='float64')) wea['shocktrain']=({'dmg':dmg,'clip':1,'rwf':False,'accel':False,'rof':1,       'rel':9.,'dist':False,'version':4.0,'comm':comm}) #Spiral comm='ROF changed to 5 to match warrobots.net' dmg = (np.array([920,1010,1110,1220,1340,1470,1610,1770,1940,2130,2340, 2570],dtype='float64')) wea['spiral']=({'dmg':dmg,'clip':3,'rwf':False,'accel':False,'rof':5,       'rel':12,'dist':False,'version':4.0,'comm':comm}) #Storm comm='Source: wiki (corresponds w. pixo)' dmg = (np.array([3440,3784,4152,4568,5024,5520,6064,6664,7320,8040,8848, 9712],dtype='float64')) wea['storm']=({'dmg':dmg,'clip':8,'rwf':True,'accel':False,'rof':1.4,       'rel':11.,'dist':False,'version':4.0,'comm':comm}) #Taran comm=('WR.net says firerate is 4.13 but it does not seem to be the case'+          '\nfrom the burst length. Keeping 3.33 for now.') dmg = (np.array([910 ,1000 ,1100 ,1210 ,1330 ,1460 ,1600 ,1760 ,1930 , 2120 ,2330 ,2560 ],dtype='float64')) wea['taran']=({'dmg':dmg,'clip':32,'rwf':False,'accel':False,'rof':3.33,       'rel':3.33,'dist':False,'version':4.0,'comm':comm}) #Tempest comm=('As for other kinetic weaps. wr.net seems to indicate'+          '\na weird fire rate. Wiki one kept.') dmg = (np.array([600,660 ,720 ,790 ,870 ,960 ,1060,1170,1290,1420,1560, 1710],dtype='float64')) wea['tempest']=({'dmg':dmg,'clip':70,'rwf':False,'accel':True,'rof':4.2,       'rel':10,'dist':False,'accfact':1.5,'acctime':3,        'version':4.0,'comm':comm}) #Thermite comm='--' dmg=(np.array([3390,3730,4100,4510,4960,5450,5990,6580,7230,7950,8740,9600], dtype='float64')) wea['thermite']=({'dmg':dmg,'clip':4,'rwf':False,'accel':False,'rof':4,       'rel':10,'dist':False,'version':4.0,'comm':comm}) #Thunder comm=('Listing (as per wiki) the damage per shot, NOT per pellet,'+          '\nas in wr.net. Thunder shots 16 pellets, numbers correspond.') dmg = (np.array([0,0,0,0,7600,8352 ,9184 ,10096,11088,12192,13392,14720] ,dtype='float64')) wea['thunder']=({'dmg':dmg,'clip':5,'rwf':True,'accel':False,'rof':1.,       'rel':10.,'dist':False,'version':4.0,'comm':comm}) #Trebuchet comm=('Damage listed is for fully recharged weapon. Wr.net reports the'+          '\ndamage "per particle, assuming 20 charges. Numbers match.'+           '\nI use rel=22 to account for 1s for firing')     dmg = (np.array([7000,7600 ,8400 ,9200 ,10000,11000,12000,13200,14600,                      16000,17600,19320],dtype='float64'))     wea['trebuchet']=({'dmg':dmg,'clip':1,'rwf':False,'accel':False,'rof':1,        'rel':22,'dist':False,'version':4.0,'comm':comm})     #Trident     comm=('Data on firing speed and reload speed are a little unclear.'+           '\nTrident fires 2 rounds per second as per wr.net, bu the actual'+           '\nreload has a slight delay, hinted at in the wiki. Included it in'+           '\nthe reload time' )     dmg = (np.array([2550,2800,3080,3380,3710,4080,4480,4920,5410,5950,6540,                      7190],dtype='float64'))     wea['trident']=({'dmg':dmg,'clip':3,'rwf':False,'accel':False,'rof':2., 'rel':12,'dist':False,'version':4.0,'comm':comm})    #Tulumbas     comm='--'     dmg = (np.array([0,0,0,0,1350,1480,1630,1790,1970,2170,2380,2610]     ,dtype='float64'))     wea['tulumbas']=({'dmg':dmg,'clip':8,'rwf':True,'accel':False,'rof':4.3, 'rel':18,'dist':False,'version':4.0,'comm':comm})    #Vortex     comm=('Assuming burst length is 1s but has to be tested')     dmg = (np.array([1680,1850,2030,2230,2450,2690,2960,3250,3570,3920,4310,                      4740],dtype='float64'))     wea['vortex']={'dmg':dmg,'clip':6,'rwf':False,'accel':False,'rof':6,        'rel':10.,'dist':False,'version':4.0,'comm':comm}     #Zenit     comm='1rps is averaged, Zenit fires couples of rockets close together'     dmg = (np.array([0,0,0,0,1344,1476,1622,1783,1959,2153,2366,2600],                     dtype='float64'))     wea['zenit']=({'dmg':dmg,'clip':18,'rwf':False,'accel':False,'rof':1, 'rel':15,'dist':False,'version':4.0,'comm':comm})    #Zeus     comm='--'     dmg = (np.array([0,0,0,0,8486,9326 ,10248,11261,12375,13599,14944,16422],                     dtype='float64'))     wea['zeus']=({'dmg':dmg,'clip':1,'rwf':False,'accel':False,'rof':1,'rel':5, 'dist':False,'version':4.0,'comm':comm}) def compute_damage(wname,at_distance=-1.,multip=1.,comm=False):    """     Computes damage for all levels of weapon wname     (as named in the weap structure, so 'pin', 'taran'...)     If the weapon has distance dependence, at_distance=xxx (meters)     computes damage for that distance. Otherwise, for distance dependent     weapons, damage at minimum distance is computed).     If multip=XXX the weapon damage is computedmultiplied by thet given factor,     useful when buffs/nerfs are announced.     E.g. "Thunder will ve buffed 5%" ==> multip=1.05     if comm=True comments are printed     """ global wea wdatabase if wname not in list(wea.keys): raise ValueError('Weapon not in the database: ',wname) else: w=wea[wname] #if we request a distance for a distance-dependent weapoon we scale #the damage there if w['dist']: variation_per_meter=(w['distance_values'][1]-w['distance_values'][0])/(w['distances'][1]-w['distances'][0]) if at_distance > 0.: if w['dist']: w['distance_values']=np.float64(w['distance_values']) w['distances']=np.float64(w['distances']) w['dmg']=w['dmg']+((w['distance_values'][1]-w['distance_values'][0])/w['distance_values'][0])*((at_distance-w['distances'][0])/(w['distances'][1]-w['distances'][0]))*w['dmg'] else: raise ValueError('This weapon has no distance dependence') #If a buff/nerf is applied if multip != 1.: print("A damage modificator has been applied:",multip) w['dmg']=w['dmg']*multip #Now we can begin computing the damage #notice that now a weapon is either RWF, or ACCEL, or neither. #this is because at the moment there is no "mixed" case, if        #one were introduced the following if structure would have to be altered. if w['rwf']: #how many ammos reloaded per second reloads_per_sec=np.float64(w['clip'])/np.float64(w['rel']) #for RWF weapons, reload begins only after the 1st shot is fired. #so I compute how much time is lost to the reload process because of this reload_wait_loss=reloads_per_sec/np.float64(w['rof']) #actual burst length accounting for rwf, reload wait loss and partial reloads. actual_burst=(np.float64(w['clip'])-reload_wait_loss)/(np.float64(w['rof'])-reloads_per_sec) #how many shots are actually fired in a burst (more than clip for RWF weapons) actual_shots=np.floor(actual_burst*np.float64(w['rof'])) #partial reload during burst will not be fired but will shorten reload time act_rf = actual_burst * reloads_per_sec - np.floor(actual_burst * reloads_per_sec) rtreload=np.float64(w['clip'])-act_rf #how many are really to be reloaded after burst ends actual_reload_time=rtreload/reloads_per_sec cycle_time=actual_reload_time+actual_burst cycle_dps=w['dmg']*actual_shots/cycle_time dam_per_salvo=w['dmg']*actual_shots reload_time=actual_reload_time burst_time=actual_burst elif w['accel']: #accelerating weapons shot at base ROF for some seconds then accelerate, #so I need to estimate how many bullets are left in the clip for the #accelerated part: shots_before=np.float64(w['rof'])*np.float64(w['acctime']) time_after=(np.float64(w['clip'])-shots_before)/(np.float64(w['rof'])*np.float64(w['accfact'])) total_burst_time=np.float64(w['acctime'])+time_after cycle_time=total_burst_time+np.float64(w['rel']) reload_time=np.float64(w['rel']) cycle_dps=w['dmg']*np.float64(w['clip'])/cycle_time dam_per_salvo=w['dmg']*np.float64(w['clip']) burst_time=total_burst_time else: #NON-RWF weapons burst_time=np.float64(w['clip'])/np.float64(w['rof']) #length of a burst actual_shots=np.float64(w['clip']) cycle_time=np.float64(w['rel'])+burst_time dam_per_salvo=w['dmg']*np.float64(w['clip']) cycle_dps=dam_per_salvo/cycle_time reload_time=np.float64(w['rel']) #all quantities are computed we can go for printout: print('\n--') print('{0:10s} version {1:4.1f}'.format(wname,w['version'])) print('--') print('Input stats:') print('Base rate of fire {0:6.2f}'.format(np.float64(w['rof']))) print('Shots in the clip {0:4d}'.format(w['clip'])) print('Base burst time {0:4.1f}'.format(w['clip']/np.float64(w['rof']))) print('Base reload time {0:4.1f}'.format(np.float64(w['rel']))) pp=w['clip']/np.float64(w['rof'])+np.float64(w['rel']) print('Base cycle time {0:4.1f}'.format(pp)) if w['rwf']: print("Weapon reloads while firing:") print('Actual shots in the burst {0:3d}'.format(int(actual_shots))) print('Actual burst time {0:4.1f}'.format(burst_time)) print('Actual reload time {0:4.1f}'.format(actual_reload_time)) print('Actual cycle time {0:4.1f}'.format(cycle_time)) if w['accel']: print("Weapon accelerates {0:3.1f} times after {1:1d} seconds".format(np.float64(w['accfact']),w['acctime'])) print('Shots fired before acceleration {0:3d}'.format(int(shots_before))) print('Time after acceleration {0:4.2f}'.format(time_after)) print('Actual burst time {0:4.1f}'.format(burst_time)) print('Actual cycle time {0:4.1f}'.format(cycle_time)) if w['dist']: print('Weapon has distance dependence, L12 damage {0:6d},{1:6d} at distance {2:4d},{3:4d}'.format(int(w['distance_values'][0]),int(w['distance_values'][1]),int(w['distances'][0]),int(w['distances'][1]))) print('For a variation of {0:7.1f}HP per 100m'.format(variation_per_meter*100.)) if at_distance > 0.: print('Damage computed for distance ',at_distance) else: print('Damage computed for minimum distance') print('--') print('L  dmg   BDMG    BDPS    CDPS') for dd in range(12): print('{0:2d} {1:5d} {2:6d} {3:7.1f} {4:7.1f}'.format(dd+1,int(w['dmg'][dd]),int(dam_per_salvo[dd]),np.float64(dam_per_salvo[dd])/burst_time,cycle_dps[dd])) print('--') print('--') if comm: print(w['comm']) def compute_all(with_comments=False): """Does computation for all weapons""" global wea wdatabase for this in wea.keys: compute_damage(this,comm=with_comments)
 * 1) !/usr/bin/env python3
 * 2) -*- coding: utf-8 -*-
 * 1) Weap is defined as a dictionary of dictionaries. Each weapon goes by its name
 * 2) (all lowercase) as the externak key, and its content is a dictionary including
 * 3) all these:
 * 4) dmg=damage per shot at each level
 * 5) clip=number of shots per clip
 * 6) rwf=Reloads while firing? (boolean)
 * 7) accel=Accelerated firing? (boolean)
 * 8) rof=rate of fire (shots/s, non accelerated)
 * 9) rel=reload time (s)
 * 10) dist=is the damage distance dependent? (Boolean)
 * 11) comment=A string comment that can be printed on request
 * 1) NOTE: Distance dependence is applied only for weapons where it is explicitely
 * 2)       documented, e.g. Scourge, so that there is a way to compute it.
 * 3)       So for instance, Punisher has 'dist'=False because there are no data
 * 4)       on how to compute the damage decrease.
 * 1) IF some of the booleans are true it might contain the needed info:
 * 2) if accel==True
 * 3) accfact=acceleration factor
 * 4) acctime=time before acceleration
 * 1) if dist==True
 * 2) distances=min and max distance at which damage is computed
 * 3) distance_values=damage at min and max distances, @L12
 * 4) in this case dmg is computed for distances[0].
 * 1) def model_spread(angle,radius):
 * 2)    """Computes the exact fraction of bullets that should hit a circular
 * 3)    area of given radius (m) at different distances, assuming a conical spread
 * 4)    of given aperture (deg)"""
 * 5)    tana=np.tan(np.deg2rad(angle))
 * 6)    dists=np.array(range(0,810,10),dtype='float64')
 * 7)    targ_area=np.pi*radius**2.
 * 8)    spread_area=np.pi*(dists*tana)**2.
 * 9)    area_ratio=targ_area/spread_area
 * 10)    whr=(area_ratio>1)
 * 11)    area_ratio[whr]=1.
 * 12)    ff=
 * 1) def read_in_weapons(filename):
 * 2)    """reads in weapon data from a properly formatted ASCII file"""
 * 3)    global wea
 * 4)    with open(filename) as wfi