Back to Index Page generated: Nov 12, 2024, 11:02:04 PM

Expansion Separated Lasers

Content

Manifest

from Expansion Manager's OXP list from Expansion Manifest
Description Multiple lasers will not heat up faster than single ones if there is at least 30m space between the mount points. Large ships can earn up to 5x firepower on broadsides! Multiple Pulse, Beam and Military Lasers, Eco Lasers with low energy usage and some Laser Cannons are also available in separated form. Press 'i' for more info. Ships with separated laser mounts: Anaconda (aft and sides), Boa II (aft), Caduceus, Cat, DTT War Lance, Ghavial, Hornet, Iguana, Krait, Pitviper II, Stormbrewer, Vector, Wolf I, Wolf II (aft) and more, as defined in Multiple Lasers OXP. Broadsides (5 lasers on sides): DTT Atlas, Heart of Gold, Serpent Class Cruiser. Forward broadsides (5 separated forward lasers): Far Arm Corsair, Far Arm Hunter. Broadsides in all 4 views: Kirin, Maelstrom. Sniper Gun and Heavy Sniper Gun are also separable in SG variants of ships if there is enough space between mounts but Sapper is not separable. Check the wiki for details. Multiple lasers will not heat up faster than single ones if there is at least 30m space between the mount points. Large ships can earn up to 5x firepower on broadsides! Multiple Pulse, Beam and Military Lasers, Eco Lasers with low energy usage and some Laser Cannons are also available in separated form. Press 'i' for more info. Ships with separated laser mounts: Anaconda (aft and sides), Boa II (aft), Caduceus, Cat, DTT War Lance, Ghavial, Hornet, Iguana, Krait, Pitviper II, Stormbrewer, Vector, Wolf I, Wolf II (aft) and more, as defined in Multiple Lasers OXP. Broadsides (5 lasers on sides): DTT Atlas, Heart of Gold, Serpent Class Cruiser. Forward broadsides (5 separated forward lasers): Far Arm Corsair, Far Arm Hunter. Broadsides in all 4 views: Kirin, Maelstrom. Sniper Gun and Heavy Sniper Gun are also separable in SG variants of ships if there is enough space between mounts but Sapper is not separable. Check the wiki for details.
Identifier oolite.oxp.Norby.Separated_Lasers oolite.oxp.Norby.Separated_Lasers
Title Separated Lasers Separated Lasers
Category Weapons Weapons
Author Norby Norby
Version 1.3 1.3
Tags
Required Oolite Version
Maximum Oolite Version
Required Expansions
  • oolite.oxp.Norby.Multiple_Lasers:1.7
  • oolite.oxp.Norby.Multiple_Lasers:1.7
  • Optional Expansions
  • oolite.oxp.Norby.Eco_Lasers:1.0
  • oolite.oxp.Norby.LaserCannons:1.11
  • oolite.oxp.Norby.Sniper_Gun:1.1
  • oolite.oxp.Norby.Eco_Lasers:1.0
  • oolite.oxp.Norby.LaserCannons:1.11
  • oolite.oxp.Norby.Sniper_Gun:1.1
  • Conflict Expansions
    Information URL http://wiki.alioth.net/index.php/Separated_Lasers n/a
    Download URL https://wiki.alioth.net/img_auth.php/3/33/Separated_Lasers_1.3.oxz n/a
    License CC BY-NC-SA 4 CC BY-NC-SA 4
    File Size n/a
    Upload date 1698564600

    Documentation

    Also read http://wiki.alioth.net/index.php/Separated%20Lasers

    Equipment

    Name Visible Cost [deci-credits] Tech-Level
    Dual Beam Laser yes 12000 5+
    Triple Beam Laser yes 13000 5+
    Quad Beam Laser yes 14000 5+
    Broadside Beam Laser yes 15000 5+
    Dual Plasma Ray yes 420000 12+
    Triple Plasma Ray yes 430000 12+
    Quad Plasma Ray yes 440000 12+
    Broadside Plasma Ray yes 450000 12+
    Dual Artillery Cannon yes 520000 12+
    Triple Artillery Cannon yes 530000 12+
    Quad Artillery Cannon yes 540000 12+
    Broadside Artillery Cannon yes 550000 12+
    Dual Twin Artillery Cannon yes 1020000 12+
    Triple Twin Artillery Cannon yes 1030000 12+
    Quad Twin Artillery Cannon yes 1040000 12+
    Broadside Twin Artillery Cannon yes 1050000 12+
    Dual Mini Cannon yes 12000 6+
    Triple Mini Cannon yes 13000 6+
    Quad Mini Cannon yes 14000 6+
    Broadside Mini Cannon yes 15000 6+
    Dual Military Cannon yes 82000 8+
    Triple Military Cannon yes 83000 8+
    Quad Military Cannon yes 84000 8+
    Broadside Military Cannon yes 85000 8+
    Dual Twin Military Cannon yes 102000 8+
    Triple Twin Military Cannon yes 103000 8+
    Quad Twin Military Cannon yes 104000 8+
    Broadside Twin Military Cannon yes 105000 8+
    Dual Vulcan Cannon yes 250000 12+
    Triple Vulcan Cannon yes 260000 12+
    Quad Vulcan Cannon yes 270000 12+
    Broadside Vulcan Cannon yes 280000 12+
    Dual Eco Artillery yes 4200000 14+
    Triple Eco Artillery yes 4300000 14+
    Quad Eco Artillery yes 4400000 14+
    Broadside Eco Artillery yes 4500000 14+
    Dual Eco Cannon yes 402000 10+
    Triple Eco Cannon yes 403000 10+
    Quad Eco Cannon yes 404000 10+
    Broadside Eco Cannon yes 405000 10+
    Dual Heavy Sniper Gun yes 2020000 12+
    Triple Heavy Sniper Gun yes 2030000 12+
    Quad Heavy Sniper Gun yes 2040000 12+
    Broadside Heavy Sniper Gun yes 2050000 12+
    Dual Sniper Gun yes 202000 12+
    Triple Sniper Gun yes 203000 12+
    Quad Sniper Gun yes 204000 12+
    Broadside Sniper Gun yes 205000 12+
    Dual Eco Laser yes 42000 5+
    Triple Eco Laser yes 43000 5+
    Quad Eco Laser yes 44000 5+
    Broadside Eco Laser yes 45000 5+
    Dual Eco Reactor yes 102000 8+
    Triple Eco Reactor yes 103000 8+
    Quad Eco Reactor yes 104000 8+
    Broadside Eco Reactor yes 105000 10+
    Dual Military Laser yes 62000 11+
    Triple Military Laser yes 63000 11+
    Quad Military Laser yes 64000 11+
    Broadside Military Laser yes 65000 11+
    Dual Pulse Laser yes 4200 4+
    Triple Pulse Laser yes 4300 4+
    Quad Pulse Laser yes 4400 4+
    Broadside Pulse Laser yes 4500 4+

    Ships

    This expansion declares no ships.

    Models

    This expansion declares no models.

    Scripts

    Path
    Scripts/separatedlasers-conditions.js
    "use strict";
    this.name	= "separatedlasers-conditions";
    this.author	= "Norby";
    this.copyright	= "2016 Norby";
    this.description= "Lasers will not heat up faster if there is at least 30m space between multiple mounts";
    this.licence	= "CC BY-NC-SA 4.0";
    
    //condition script
    this.allowAwardEquipment = function(equipment, ship, context)
    {
            if( !this.$SL ) { //save worldScript pointers into faster variables
                    this.$SL = worldScripts.separatedlasers; //read once only
                    this.$SG = worldScripts.snipergun;
                    this.$LC = worldScripts.lasercannons;
            }
    
            // OXP hook to allow stations to forbid specific equipment
            if (context == "purchase" && player.ship.dockedStation && player.ship.dockedStation.scriptInfo["oolite-barred-equipment"])
            {
                    if (player.ship.dockedStation.scriptInfo["oolite-barred-equipment"].indexOf(equipment) != -1)
                    {
                            return false;
                    }
            }
    
            // OXP hook to allow ships to forbid specific "available to all" equipment
            if (ship.scriptInfo && ship.scriptInfo["oolite-barred-equipment"] && ship.scriptInfo["oolite-barred-equipment"].indexOf(equipment) != -1)
            {
                    return false;
            }
    
    //      player.consoleMessage( eqKey+" "+ship+" "+context );//debug
            if (context == "scripted") return true;
            if (worldScripts.LMSS_Core && worldScripts.LMSS_Core._switching) return true;
    
            //check for multiple mounts
            var m = this.$SL._getMultiLevel(equipment);
            //chech for a proper multiple mount on this ship
            if( m > 0 && ship.weaponPositionForward.length != m
                    && ship.weaponPositionAft.length != m
                    && ship.weaponPositionPort.length != m
                    && ship.weaponPositionStarboard.length != m ) {
    
                    if( m < 5 ) return false; //dual, triple and quad lasers need exact match in mounts
    
                    if( ship.weaponPositionForward.length < m //allow broadside lasers at and over 5 mounts
                            && ship.weaponPositionAft.length < m
                            && ship.weaponPositionPort.length < m
                            && ship.weaponPositionStarboard.length < m )
                            return false;
            }
            //log(this.name, ship.name+" "+equipment+" "+context+" m="+m); //debug
    
    
            //check if mounts are enough far from each other for separation
            var space = this.$SL._space(equipment);
            var a = this.$SL._Separated_Lasers(ship, this.$SL);
            if( !a || ( a[1] < space && a[2] < space && a[3] < space && a[4] < space ) )
                    return false; //for example mounts on Cobra3 not enough wide for separation
    
    
            //Sniper Gun is checked in its own script (need specific subEntity on the ship)
            if( equipment.indexOf("EQ_WEAPON_CANNON_SNIPER_GUN") > -1
                    || equipment.indexOf("EQ_WEAPON_CANNON_HEAVY_SNIPER_GUN") > -1 ) {
                    var w = this.$SG;
                    if( !w ) return false;
                    return( w._allowAwardSniperGun(equipment, ship, context, w) );
            }
    
            //exclude separated laser cannons when Laser Cannons OXP is not installed
            if( !this.$LC && ( equipment.indexOf("EQ_WEAPON_CANNON_2_") > -1
                    || equipment.indexOf("EQ_WEAPON_CANNON_4_") > -1
                    || equipment.indexOf("EQ_WEAPON_CANNON_5_") > -1
                    || equipment.indexOf("EQ_WEAPON_CANNON_7_") > -1
                    || equipment.indexOf("EQ_WEAPON_CANNON_11_") > -1
                    || equipment.indexOf("EQ_WEAPON_CANNON_12_") > -1  ) )
                    return false;
    
            //Eco Artillery and Twin Cannons need as large ship as an Anaconda
            if( ship.mass < 400000 && equipment.indexOf("EQ_WEAPON_CANNON_EA") > -1
                    || equipment.indexOf("EQ_WEAPON_CANNON_5_") > -1
                    || equipment.indexOf("EQ_WEAPON_CANNON_12_") > -1 ) return false;
    
            //Vulcan Cannon and Plasma Web need as large ship as a Python
            if( ship.mass < 250000 &&
                    (  equipment.indexOf("EQ_WEAPON_CANNON_7_") > -1
                    || equipment.indexOf("EQ_WEAPON_CANNON_9_") > -1 ) ) return false;
    
            //Eco Reactor need a ship like Cobra Mark III
            if( ship.mass < 130000 &&
                    equipment.indexOf("EQ_WEAPON_ECO_REACTOR") > -1 ) return false;
    
            //Eco Laser, Mini Cannon and Mini Plasma Ray fit into escort ships from 30t
            if( ship.mass <= 30000 &&
                    (  equipment.indexOf("EQ_WEAPON_ECO_LASER") > -1
                    || equipment.indexOf("EQ_WEAPON_CANNON_2_") > -1
                    || equipment.indexOf("EQ_WEAPON_CANNON_8_") > -1 ) ) return false;
    
            //Other cannons for large ships only like Cobra Mark III
            if( equipment.indexOf("EQ_WEAPON_CANNON") > -1 && ship.mass < 130000 ) return false;
    
            return true;
    }
    
    Scripts/separatedlasers.js
    "use strict";
    this.name	= "separatedlasers";
    this.author	= "Norby";
    this.copyright	= "2016 Norby";
    this.description= "Lasers will not heat up faster if there is at least 30m space between multiple mounts";
    this.licence	= "CC BY-NC-SA 4.0";
    
    //customizable properties
    this.$Log = false; //log separated laser distances of ships when spawned
    
    //worldscript events
    this.startUpComplete = this.playerBoughtNewShip = function() {
            this._Replace_Lasers(player.ship, this, false); //check and replace lasers to separated if possible
    }
    
    this.shipSpawned = function(ship) {
            this._Replace_Lasers(ship, this, false); //check and replace NPC lasers to separated if possible
    }
    
    this.playerBoughtEquipment = function( equipment ) {
            if( equipment.indexOf("EQ_WEAPON_") > -1 ) { //core lasers, laser cannons and other lasers in the future
                    //check and replace new laser to separated
                    //and replace back to basic laser if bought to not separated side
                    this._Replace_Lasers(player.ship, this, true);
            }
    }
    
    //internal methods
    this._Replace_Lasers = function(ship, w, refund) {  //check and replace lasers to separated if possible
        if( !ship || !ship.isValid ) return 0;
        if( !w ) var w = worldScripts.separatedlasers;
        var a = w._Separated_Lasers(ship, w);
        if( a ) {
            if( w.$Log ) log(w.name, ship.name+" Separated laser distances: fw:"+a[1]
                            +" aft:"+a[2]+" port:"+a[3]+" sb:"+a[4]);
    
    //      log(w.name, equipmentKey+" "+datakey+" "+ship.forwardWeapon+" "
    //              +ship.aftWeapon+" "+ship.portWeapon+" "+ship.starboardWeapon); //debug
    
            var eq, eq1, len, m, multi = false, p = player.ship;
    
            if( !ship.script ) ship.setScript("oolite-default-ship-script.js"); //for sure
            var m = ship.script._cachedMultipleLasers; //read cached variable
            if( !m ) {
                    var shipdata = Ship.shipDataForKey(ship.dataKey);
                    if( shipdata && shipdata["weapon_mount_mode"] == "multiply" ) m = 1;
                    else m = -1; //not multiple
                    ship.script._cachedMultipleLasers = m; //store into a cache variable
            }
            if( m == 1 ) multi = true; //a must for separation
    
            if( ship.scriptInfo ) {
                    var si = parseInt( ship.scriptInfo.separated_lasers );
                    //separation is denied if shipdata contain script_info={separatedlasers=-1;};
                    //separation need an empty side mount if script_info contain separatedlasers=1;
                    if( si == -1 || si == 1 && ship.portWeapon && ship.starboardWeapon
                             //and need both side mounts stay without lasers if separatedlasers=2;
                            || si == 2 && ( ship.portWeapon || ship.starboardWeapon ) ) {
                            multi = false; //deny separation
                    }
            }
    
            //replace back to single laser if bought a separated one to not separated side
            //then replace single lasers to separated versions where there is enough space and money
            //use the laser match to the number of mounts but max.5
            //Dual, Triple, Quad or Broad Separated Pulse, Beam or Military Lasers,
            //Sniper Guns and some Laser Cannons
    
            if( ship.forwardWeapon ) {
                eq = ship.forwardWeapon.equipmentKey;
                if( multi ) len = ship.weaponPositionForward.length; else len = 1;
                //replace back to basic laser if bought to not separated side
                m = w._getMultiLevel(eq);
                if( m > 1 && ( Math.min(5, len) != m || !a[1] || a[1] < w._space(eq) ) ) {
                    eq1 = eq.substr(0, eq.length-2);
                    //replace to single weapon without _2, _3, _4 or _5 at the end
                    if( !EquipmentInfo.infoForKey( eq1 ) ) eq1 = eq; //for sure
                    if( refund && ship == p ) w._refund( eq, eq1, len, true ); //no refund during flight
                    ship.forwardWeapon = eq1;
                    eq = eq1;
                    m = 1;
                }
                //replace single lasers to separated versions where there is enough space and money
                if( m < 2 && len > 1 && a[1] && a[1] >= w._space(eq) ) {
                    eq1 = eq+"_"+Math.min(5, len); //max 5 (broadside)
                    if( EquipmentInfo.infoForKey( eq1 ) ) { //not all weapons are separable
                        if( refund && ship == p ) { 
                            //no refund for NPCs and during flight (Sapper->Sniper Gun)
                            if( w._refund( eq, eq1, len, true ) )
                                ship.forwardWeapon = eq1;
                        } else ship.forwardWeapon = eq1;
                    }
                }
            }
    
            if( ship.aftWeapon ) {
                eq = ship.aftWeapon.equipmentKey;
                if( multi ) len = ship.weaponPositionAft.length; else len = 1;
                //replace back to basic laser if bought to not separated side
                m = w._getMultiLevel(eq);
                if( m > 1 && ( Math.min(5, len) != m || !a[2] || a[2] < w._space(eq) ) ) {
                    eq1 = eq.substr(0, eq.length-2);
                    //replace to single weapon without _2, _3, _4 or _5 at the end
                    if( !EquipmentInfo.infoForKey( eq1 ) ) eq1 = eq; //for sure
                    if( refund && ship == p ) w._refund( eq, eq1, len, true ); //no refund during flight
                    ship.aftWeapon = eq1;
                    eq = eq1;
                    m = 1;
                }
                //replace single lasers to separated versions where there is enough space and money
                if( m < 2 && len > 1 && a[2] && a[2] >= w._space(eq) ) {
                    eq1 = eq+"_"+Math.min(5, len); //max 5 (broadside)
                    if( EquipmentInfo.infoForKey( eq1 ) ) { //not all weapons are separable
                        if( refund && ship == p ) {
                            //no refund for NPCs and during flight (Sapper->Sniper Gun)
                            if( w._refund( eq, eq1, len, true ) )
                                ship.aftWeapon = eq1;
                        } else ship.aftWeapon = eq1;
                    }
                }
            }
    
            if( ship.portWeapon ) {
                eq = ship.portWeapon.equipmentKey;
                if( multi ) len = ship.weaponPositionPort.length; else len = 1;
                //replace back to basic laser if bought to not separated side
                m = w._getMultiLevel(eq);
                if( m > 1 && ( Math.min(5, len) != m || !a[3] || a[3] < w._space(eq) ) ) {
                    eq1 = eq.substr(0, eq.length-2);
                    //replace to single weapon without _2, _3, _4 or _5 at the end
                    if( !EquipmentInfo.infoForKey( eq1 ) ) eq1 = eq; //for sure
                    if( refund && ship == p ) w._refund( eq, eq1, len, true ); //no refund during flight
                    ship.portWeapon = eq1;
                    eq = eq1;
                    m = 1;
                }
                //replace single lasers to separated versions where there is enough space and money
                if( m < 2 && len > 1 && a[3] && a[3] >= w._space(eq) ) {
                    eq1 = eq+"_"+Math.min(5, len); //max 5 (broadside)
                    if( EquipmentInfo.infoForKey( eq1 ) ) { //not all weapons are separable
                        if( refund && ship == p ) {
                            //no refund for NPCs and during flight (Sapper->Sniper Gun)
                            if( w._refund( eq, eq1, len, true ) )
                                ship.portWeapon = eq1;
                        } else ship.portWeapon = eq1;
                    }
                }
            }
    
            if( ship.starboardWeapon ) {
                eq = ship.starboardWeapon.equipmentKey;
                if( multi ) len = ship.weaponPositionStarboard.length; else len = 1;
                //replace back to basic laser if bought to not separated side
                m = w._getMultiLevel(eq);
                if( m > 1 && ( Math.min(5, len) != m || !a[4] || a[4] < w._space(eq) ) ) {
                    eq1 = eq.substr(0, eq.length-2);
                    //replace to single weapon without _2, _3, _4 or _5 at the end
                    if( !EquipmentInfo.infoForKey( eq1 ) ) eq1 = eq; //for sure
                    if( refund && ship == p ) w._refund( eq, eq1, len, true ); //no refund during flight
                    ship.starboardWeapon = eq1;
                    eq = eq1;
                    m = 1;
                }
                //replace single lasers to separated versions where there is enough space and money
                if( m < 2 && len > 1 && a[4] && a[4] >= w._space(eq) ) {
                    eq1 = eq+"_"+Math.min(5, len); //max 5 (broadside)
                    if( EquipmentInfo.infoForKey( eq1 ) ) { //not all weapons are separable
                        if( refund && ship == p ) {
                            //no refund for NPCs and during flight (Sapper->Sniper Gun)
                            if( w._refund( eq, eq1, len, true ) )
                                ship.starboardWeapon = eq1;
                        } else ship.starboardWeapon = eq1;
                    }
                }
            }
        }
    }
    
    this._getMultiLevel = function(equipment) { //get the multiplication level of a given weapon
            var m = 0;
            var end = equipment.substr(-2, 2); //the last two characters of equipmentKey
            if( end == "_2" && equipment != "EQ_WEAPON_CANNON_2" //except single Ingram 3838C8 Mini Cannon
                && equipment != "EQ_WEAPON_GATLING_LASER_2" ) m = 2; //and Gatling 2
            if( end == "_3" && equipment != "EQ_WEAPON_CANNON_3" //except single Hassoni C38 Dual Cannon
                && equipment != "EQ_WEAPON_GATLING_LASER_3" ) m = 3; //and Gatling 3
            if( end == "_4" && equipment != "EQ_WEAPON_CANNON_4" //except single Lance & Ferman Military Cannon
                && equipment != "EQ_WEAPON_GATLING_LASER_4" ) m = 4; //and Gatling 4
            if( end == "_5" && equipment != "EQ_WEAPON_CANNON_5" //except single LF38 Twin Military Cannon
                && equipment != "EQ_WEAPON_GATLING_LASER_5" ) m = 5; //and Gatling 5
            return( m );
    }
    
    this._Separated_Lasers = function(ship, w) {  
            //return false if no separated mount, else return array of sides
            if( !w ) var w = worldScripts.separatedlasers;
            var a = [];
            a[1] = w._is_Separated_Mount(ship, 1, w); //forward
            a[2] = w._is_Separated_Mount(ship, 2, w); //aft
                a[3] = w._is_Separated_Mount(ship, 3, w); //port
            a[4] = w._is_Separated_Mount(ship, 4, w); //starboard
    //      log(w.name, ship.name+" Laser distances: fw:"+a[1]+" aft:"+a[2]+" port:"+a[3]+" sb:"+a[4]);
            if( !a[1] && !a[2] && !a[3] && !a[4] ) return false;
            else return a; //array of min. distances at sides where lasers are separated, false at other sides
    }
    
    this._is_Separated_Mount = function(ship, side, w) { //return false if this side is not separated
            if( !w ) var w = worldScripts.separatedlasers;
            var d = w._mount_Distance(ship, side, w);
            if( d < 30 ) return false;
            else return d; //return min. distance if more than the minimally allowed for separated lasers
    }
    
    this._mount_Distance = function(ship, side, w) { //return 0 if only one mount, min. dist. if more.
            if( !w ) var w = worldScripts.separatedlasers;
            side = Math.floor(side);
            var array;
            if( !side || side <= 1 || side > 4 ) array = ship.weaponPositionForward;
            else if( side == 2 ) array = ship.weaponPositionAft;
            else if( side == 3 ) array = ship.weaponPositionPort;
            else array = ship.weaponPositionStarboard;
            var min = w._min_Distance(array);
            return min;
    }
    
    this._min_Distance = function(array) { //calculate min. dist. in the given array of Vector3Ds
            var min = 0;
            if( array && array.length > 1 ) for(var i = 0; i < array.length; i++) {
                    for(var j = i + 1; j < array.length; j++) { //check against all remaining items
                            var d = 0;
                            if( array[i].distanceTo && array[j].distanceTo )
                                    d = array[i].distanceTo(array[j]);
                            if( d > 0 && min == 0 ) min = d;
                            else if( min > 0 && d < min ) min = d;
    //                      log(this.name, "d:"+d+"min:"+min+" a["+i+"]: "+array[i]+" a["+j+"]:"+array[j]);
                    }
            }
    //      log(this.name, " array: "+array+" min.d:"+min);
            return min;
    }
    
    this._refund = function(eq, eq1, length, msg) { 
            //refund weapon price, length is the size of multiple weapons array
            var f = 1;
            if( player.ship && player.ship.dockedStation ) {
                    var e = player.ship.dockedStation.equipmentPriceFactor;
                    if( e > 0 ) f = e;
            }
            if( 0 < oolite.compareVersion("1.83") ) length = 1; //no multiple weapons before Oolite 1.83
    
            var refund = f * length * (EquipmentInfo.infoForKey( eq ).price
                    - EquipmentInfo.infoForKey( eq1 ).price)/10;
            if( refund < 0 && player.credits < -1 * refund ) {
                    var m = EquipmentInfo.infoForKey( eq ).name 
                            + " is not the best in this mount, but you have not "
                            + (-1*refund) + " credits to buy " 
                            + EquipmentInfo.infoForKey( eq1 ).name+".";
                    if(msg) player.consoleMessage(m, 10);
                    log(this.name, "Replace "+eq+" to "+eq1+" skipped, need "
                            +refund+"cr but you have "+player.credits+"cr only.");
                    return( false );
            }
            player.credits += refund;
            var r = ", "+refund+" credits refunded.";
            if( refund < 0 ) r = " for " + (-1*refund) + " credits.";
            var m = EquipmentInfo.infoForKey( eq ).name 
                    + " is not the best in this mount, replaced to "
                    + EquipmentInfo.infoForKey( eq1 ).name + r;
            if(msg) player.consoleMessage(m, 10);
            log(this.name, "Replace "+eq+" to "+eq1+", refund: "+refund+" cr");
            return( true );
    }
    
    this._space = function(eq) { //how much space need between weapon positions to be separated
    
            if( eq.indexOf("EQ_WEAPON_CANNON_5") > -1 //Twin Military Cannon
                    || eq.indexOf("EQ_WEAPON_CANNON_10") > -1 //Plasma Ray
                    || eq.indexOf("EQ_WEAPON_CANNON_12") > -1 //Twin Artillery Cannon
                    || eq.indexOf("EQ_WEAPON_CANNON_EA") > -1 //Eco Artillery
                    || eq.indexOf("EQ_WEAPON_ECO_REACTOR") > -1 //Eco Reactor
                    || eq.indexOf("EQ_WEAPON_CANNON_SNIPER_GUN") > -1 ) //Sniper Gun
                    return(50); //need 50m
    
            if( eq.indexOf("EQ_WEAPON_CANNON_HEAVY_SNIPER_GUN") > -1 ) //Heavy Sniper Gun
                    return(100); //need 100m
    
            return(30); //all others need 30m
    }