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

```
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

#Weap is defined as a dictionary of dictionaries. Each weapon goes by its name
#(all lowercase) as the externak key, and its content is a dictionary including
#all these:
# comment=A string comment that can be printed on request
#
#       on how to compute the damage decrease.
#
# acctime=time before acceleration
#
# in this case dmg is computed for distances[0].

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])
                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)

#def model_spread(angle,radius):
#    ff=

#def read_in_weapons(filename):