[WIP] Reduce Weapons Damage v0.10
Moderators: winston, another_commander
[WIP] Reduce Weapons Damage v0.10
https://bb.oolite.space/viewtopic.php?f=4&t=16925
In that thread i started work on an oxp that would reduce laser damage to player ship to compensate for the much stronger npc ships in 1.80.
I've thought about that idea, checked test results for combat related changes for 1.18 and come to the conclusion
reducing laser damage for both player and npc has a good chance of increasing player survival chance without making game easier.
This oxp will not function through an equipment item, but always have effect if installed.
For the time being both npc & player get the same damage reduction.
In that thread i started work on an oxp that would reduce laser damage to player ship to compensate for the much stronger npc ships in 1.80.
I've thought about that idea, checked test results for combat related changes for 1.18 and come to the conclusion
reducing laser damage for both player and npc has a good chance of increasing player survival chance without making game easier.
This oxp will not function through an equipment item, but always have effect if installed.
For the time being both npc & player get the same damage reduction.
Last edited by Lone_Wolf on Fri Nov 07, 2014 2:53 pm, edited 4 times in total.
OS : Arch Linux 64-bit - rolling release
OXPs : My user page
Retired, reachable at [email protected]
OXPs : My user page
Retired, reachable at [email protected]
- Norby
- ---- E L I T E ----
- Posts: 2577
- Joined: Mon May 20, 2013 9:53 pm
- Location: Budapest, Hungary (Mainly Agricultural Democracy, TL10)
- Contact:
Re: [WIP] Reduce Weapons Damage
My suggestions:
The first line help on ships without script, the second allow to use a much faster pointer in ship script:
Code: Select all
if ( !ship.script ) ship.setScript("oolite-default-ship-script.js");
ship.script._RWD = this; // = worldScripts["Reduce Weapon Damage"]
Code: Select all
player.ship.forwardShield += this._RWD._rwd_player_reduction;
//this._RWD is set to worldScripts["Reduce Weapon Damage"] in shipSpawned
Re: [WIP] Reduce Weapons Damage
Interesting change, norby.Norby wrote:My suggestions:The first line help on ships without script, the second allow to use a much faster pointer in ship script:Code: Select all
if ( !ship.script ) ship.setScript("oolite-default-ship-script.js"); ship.script._RWD = this; // = worldScripts["Reduce Weapon Damage"]
Code: Select all
player.ship.forwardShield += this._RWD._rwd_player_reduction; //this._RWD is set to worldScripts["Reduce Weapon Damage"] in shipSpawned
I'll do my best to understand how it works.
I also found a flaw in the method i use :
It does seem shipSpawned is only called for non-player ships, so i'll have to rethink how to set things up.
OS : Arch Linux 64-bit - rolling release
OXPs : My user page
Retired, reachable at [email protected]
OXPs : My user page
Retired, reachable at [email protected]
- Tricky
- ---- E L I T E ----
- Posts: 821
- Joined: Sun May 13, 2012 11:12 pm
- Location: Bradford, UK. (Anarchic)
Re: [WIP] Reduce Weapons Damage
You could always try...Lone_Wolf wrote:I also found a flaw in the method i use :
It does seem shipSpawned is only called for non-player ships, so i'll have to rethink how to set things up.
Code: Select all
this.shipSpawned(player.ship);
this.startUpComplete
in the world script.You also have a logging bug here...
Code: Select all
log(this.name,this.ship,"no ship script attached, oxp won't work);
Needs to be something like...
Code: Select all
log(this.name,ship + " - no ship script attached, oxp won't work");
Re: [WIP] Reduce Weapons Damage
calling shipSpawned from startupComplete works great, thanks for the tip tricky.
The typos are because i was to eager to post, hadn't tested it.
New code (down to 1 script):
The typos are because i was to eager to post, hadn't tested it.
New code (down to 1 script):
Code: Select all
// Each ship in game will have a separate instance of this script
// using separate values for player / npc for flexibility .
this._rwd_player_reduction = 8;
this._rwd_npc_reduction = 8;
this.startUpComplete = function()
{
// this.shipSpawned is called by game for all non-player ships, but not for player.ship
this.shipSpawned(player.ship);
};
this.shipSpawned = function(ship)
{
if ( !ship || !ship.isPiloted || ship.isThargoid || ship.isStation ) { return };
if ( !ship.script ) { ship.setScript("oolite-default-ship-script.js"); };
if ( ship.script.shipTakingDamage )
{
// there is already a shipTakingDamage handler, store it
ship.script._rwd_oldShipTakingDamage = ship.script.shipTakingDamage;
};
if ( ship.isPlayer )
{ ship.script._rwd_reduction = worldScripts["Reduce Weapon Damage"]._rwd_player_reduction; }
else
{ ship.script._rwd_reduction = worldScripts["Reduce Weapon Damage"]._rwd_npc_reduction; };
var new_std = function(amount, whom, type)
{
amount = worldScripts["Reduce Weapon Damage"]._rwd_ShipTakingDamage(this.ship, amount, whom, type);
if ( ship.script._rwd_oldShipTakingDamage )
{
ship.script._rwd_oldShipTakingDamage(amount, whom, type); //call the original function
};
};
ship.script.shipTakingDamage = new_std;
};
this._rwd_ShipTakingDamage = function (whoami, amount, whom, type)
{
if ( type != "energy damage" ) { return amount; }; // only act upon laser / missile damage
if ( !whoami.isPlayer )
{
// npc ship, all that's needed is reducing damage amount
amount -= whoami.script._rwd_reduction;
}
else
{
/* if shields have absorbed hit, amount == 0
* this means there's no direct way to determine the strength of the hit
* simplest solution to reduce damage is to increase shield strength
*/
if ( amount ==0 )
{
// try to determine whether forward or aft shield is hit
if( whom && whom.isValid && ( player.ship.vectorForward.dot(player.ship.position.subtract(whom.position) ) > 0 ) )
{
// forward shield hit
player.ship.forwardShield += whoami.script._rwd_reduction;
}
else
{
// aft hit
player.ship.aftShield += whoami.script._rwd_reduction;
};
};
};
return amount;
};
OS : Arch Linux 64-bit - rolling release
OXPs : My user page
Retired, reachable at [email protected]
OXPs : My user page
Retired, reachable at [email protected]
- Norby
- ---- E L I T E ----
- Posts: 2577
- Joined: Mon May 20, 2013 9:53 pm
- Location: Budapest, Hungary (Mainly Agricultural Democracy, TL10)
- Contact:
Re: [WIP] Reduce Weapons Damage
Within shipSpawned the "this" keyword is equal with worldScripts["Reduce Weapon Damage"] and much faster so you can write this:
In this way you make a copy of the reduction variable into all ship script, which can go out of sync if the value will change in the main storage in your worldScript. Not a problem in your case but in general I recommend to copy the pointer only and store the value in one place as I suggested in my previous post.
Code: Select all
ship.script._rwd_reduction = this._rwd_player_reduction;
Re: [WIP] Reduce Weapons Damage
Norby, i do understand what you mean but have reasons why i decided not to do it that way.
In javascript the context a function runs in depends on where it is called from, not where it is declared.
the
i see the following calling paths in this oxp :
(rwd == worldscripts["Reduce Weapon Damage"] to shorten text )
worldscript initialization > rwd.startUpComplete > rwd.shipSpawned (player ship)
populator > non-player shipSpawned handler > rwd.shipSpawned (all other ships)
player ship gets hit > player shipTakingDamage handler > rwd._rwd_ShipTakingDamage
non-player ship gets hit > non-player shipTakingDamage handler > rwd._rwd_ShipTakingDamage
This indicates that there are FOUR different calling contexts, each has their own
The calling context is determined by the oolite gamecode, even if the 4 contexts are the same in 1.80, will they stay the same in other versions ?
about speed :
shipSpawned only gets called once per ship, while shipTakingDamage could be called thousands of times in a play sesssion.
shipscripts are attached to a specific ship.
I copied the reduction values into the shipscript as i assume this is faster then looking up a pointer to a different object.
In javascript the context a function runs in depends on where it is called from, not where it is declared.
the
this
value is inherited from the calling function, which has inherited it's this
from it's caller.i see the following calling paths in this oxp :
(rwd == worldscripts["Reduce Weapon Damage"] to shorten text )
worldscript initialization > rwd.startUpComplete > rwd.shipSpawned (player ship)
populator > non-player shipSpawned handler > rwd.shipSpawned (all other ships)
player ship gets hit > player shipTakingDamage handler > rwd._rwd_ShipTakingDamage
non-player ship gets hit > non-player shipTakingDamage handler > rwd._rwd_ShipTakingDamage
This indicates that there are FOUR different calling contexts, each has their own
this
value.The calling context is determined by the oolite gamecode, even if the 4 contexts are the same in 1.80, will they stay the same in other versions ?
about speed :
shipSpawned only gets called once per ship, while shipTakingDamage could be called thousands of times in a play sesssion.
shipscripts are attached to a specific ship.
I copied the reduction values into the shipscript as i assume this is faster then looking up a pointer to a different object.
OS : Arch Linux 64-bit - rolling release
OXPs : My user page
Retired, reachable at [email protected]
OXPs : My user page
Retired, reachable at [email protected]
- Norby
- ---- E L I T E ----
- Posts: 2577
- Joined: Mon May 20, 2013 9:53 pm
- Location: Budapest, Hungary (Mainly Agricultural Democracy, TL10)
- Contact:
Re: [WIP] Reduce Weapons Damage
No problem, my polishments comes from my style what you can ignore, I just want to say a bit more to proof my statemets.
I do not think this will change anytime due to the dev team do not want to break the existing OXPs, except with a good reason. Before any drastical change we always get more warnings and enough time to react.
In ship scripts you must use a pointer to reach your worldScript, so within your new_std function you must use "rwd", but if you insert this pointer into a ship.script._RWD variable in shipSpawed then you must not seek after in every shipTakingDamage which save some processing time.
For example if you want to decrease the reduction when the rank of the player step up a level then for an instant effect you need cycle through all ship scripts to change all values, else the values in the existing ships stay at the old value. Not a big problem so you can ignore, just an approach which maybe save some bug hunting time later.
These two are the same. You can try if you put a log(this.name, this); both into startUpComplete and shipSpawned, you will see the same in the log. In these places you can use "this" instad of "rwd" safely.Lone_Wolf wrote:worldscript initialization > rwd.startUpComplete > rwd.shipSpawned (player ship)
populator > non-player shipSpawned handler > rwd.shipSpawned (all other ships)
I do not think this will change anytime due to the dev team do not want to break the existing OXPs, except with a good reason. Before any drastical change we always get more warnings and enough time to react.
In ship scripts you must use a pointer to reach your worldScript, so within your new_std function you must use "rwd", but if you insert this pointer into a ship.script._RWD variable in shipSpawed then you must not seek after in every shipTakingDamage which save some processing time.
I think this is true and I assumed that you choosed your way due to this reason so I warned you about a possible drawback.Lone_Wolf wrote:I copied the reduction values into the shipscript as i assume this is faster then looking up a pointer to a different object.
For example if you want to decrease the reduction when the rank of the player step up a level then for an instant effect you need cycle through all ship scripts to change all values, else the values in the existing ships stay at the old value. Not a big problem so you can ignore, just an approach which maybe save some bug hunting time later.
Re: [WIP] Reduce Weapons Damage
Normally this works reasonably well in a "do what I mean" way.Lone_Wolf wrote:In javascript the context a function runs in depends on where it is called from, not where it is declared.
In Oolite, the 'this' for a function - unless you're using a callback initiated by the Oolite core (timers, frame callbacks, mission screen callbacks, a few others) should always be the script which runs it, with one exception which I'll note afterwards.Lone_Wolf wrote:thethis
value is inherited from the calling function, which has inherited it'sthis
from it's caller.
rwd.shipSpawned will always run in the context of this == rwd
rwd._rwd_ShipTakingDamage will also always run in that context.
The one that's slightly complicated is this one.
Code: Select all
var new_std = function(amount, whom, type)
{
amount = worldScripts["Reduce Weapon Damage"]._rwd_ShipTakingDamage(this.ship, amount, whom, type);
if ( ship.script._rwd_oldShipTakingDamage )
{
ship.script._rwd_oldShipTakingDamage(amount, whom, type); //call the original function
};
};
ship.script.shipTakingDamage = new_std;
Yes. Changing that would break far too much.Lone_Wolf wrote:The calling context is determined by the oolite gamecode, even if the 4 contexts are the same in 1.80, will they stay the same in other versions ?
Yes, although that sort of low-level optimisation is rarely necessary.Lone_Wolf wrote:I copied the reduction values into the shipscript as i assume this is faster then looking up a pointer to a different object.
In this case, faster would be to not copy it, and to have
Code: Select all
amount -= this._rwd_reduction;
_rwd_ShipTakingDamage
method.Even faster - and probably by quite a bit more than the above - use
_rwd_ShipTakingDamage
for the NPCs only, and take out all the isPlayer paths and checks in that code. Define a separate this.shipTakingDamage
handler in RWD and use that to handle the rather different isPlayer case. (Remember, all world scripts also get any player ship script event - it's usually much easier to use world scripts for player events than it is the player ship script)Right, the exception. Javascript has a number of methods - bind(), apply(), etc. - for telling a function to run with 'this' other than its default context. This is used in the PriorityAI library to force all the condition, behaviour and configuration routines to run in the context of the PriorityAI Controller, rather than a mix of the AI script and the AI Controller.
Code: Select all
var boundfn = function (a,b) { ... }.bind(worldScripts["Reduce Weapon Damage"];
Generally you don't need to do this, and if you're concerned about speed/memory use you shouldn't unless you already know it's necessary.
Re: [WIP] Reduce Weapons Damage
script which runs it points exactly to the issue, it's determined at run-time and the code has no idea whatcim wrote:In Oolite, the 'this' for a function - unless you're using a callback initiated by the Oolite core (timers, frame callbacks, mission screen callbacks, a few others) should always be the script which runs it, with one exception which I'll note afterwards.
this
will be, until it's run (except in cases where it's defined clearly by oolite gamecode).personally I don't like this method, but npc_shields / hardships / customshields all use it.cim wrote:The one that's slightly complicated is this one.
<snip>
You've defined this in the context of the worldscript, and specifically inside a function in that worldscript. This means that it has access to the variables that worldscript function call does, including 'ship'. When the function is called by the ship script, however, the 'this' variable - in the call to _rwd_ShipTakingDamage - will be the ship script itself, not the RWD world script.
I haven't found another way to replace the oolite default handler for shipTakingDamage (or any other handler).
Do you know a better / cleaner way ?
i will look into splitting the npc & player std handlers.
-------------------------
summary about calling context in the above code :
this.shipSpawned this == worldscripts["Reduce Weapon Damage"]
this._rwd_ShipTakingDamage :
in the declaration (var new-std) this == worldscripts["Reduce Weapon Damage"] .
When being called by oolite default shipTakingDamage handler, this == ship.script
--------------------------------------
Noted, i'll look into doing that to make the code more futureproofnorby wrote:I think this is true and I assumed that you choosed your way due to this reason so I warned you about a possible drawback.Lone_Wolf wrote:I copied the reduction values into the shipscript as i assume this is faster then looking up a pointer to a different object.
For example if you want to decrease the reduction when the rank of the player step up a level then for an instant effect you need cycle through all ship scripts to change all values, else the values in the existing ships stay at the old value. Not a big problem so you can ignore, just an approach which maybe save some bug hunting time later.
OS : Arch Linux 64-bit - rolling release
OXPs : My user page
Retired, reachable at [email protected]
OXPs : My user page
Retired, reachable at [email protected]
Re: [WIP] Reduce Weapons Damage
No, not so. (Or, at least, it is clearly defined by the oolite gamecode and the JS language syntax in almost all cases) - the behaviour ofLone_Wolf wrote:script which runs it points exactly to the issue, it's determined at run-time and the code has no idea whatthis
will be, until it's run (except in cases where it's defined clearly by oolite gamecode).
this
in Javascript is fairly complicated, but unless you define your own object types and constructors, in Oolite most of that complexity can be ignored.The script which runs the code is the script that it belongs to. If you say
Code: Select all
{script}.method = function() { ... }
bind()
or apply()
it, its this
will be the script you attached it to.The reason this works is that scripts in Oolite are themselves JS objects. If you ask Oolite to load a JS script file, what you get is an object (of JS type Script and Oolite core type OOJSScript). This object then has a bunch of properties, some of which are functions, based on the definitions in the script file (and can also have them attached at run-time later).
When you then do
{script}.method()
you're asking that Script object to run the method - that's what I meant by "the script which runs it", which I could have been clearer about - and as with any JS object method call, this
points to the owning object by default.The exceptions - timers and other callbacks - happen because you don't want those to run in the context of their owning object (which is an internal implementation detail to Oolite) - so Oolite tries to be helpful by setting
this
to be what looks like the creating Script object. It doesn't always get it right, which is why you should explicitly bind()
callbacks when you create them.So if I define in my shipscript:
Code: Select all
this._help = function() { this.ship.broadcastDistressMessage(); }
this.ship
will always refer to the ship that instance of the ship script is attached to.So when you define this line in
new_std
Code: Select all
amount = worldScripts["Reduce Weapon Damage"]._rwd_ShipTakingDamage(this.ship, amount, whom, type);
new_std(a,w,t);
then this
refers to the world script (and this.ship
is undefined). Having assigned the function to the ship script with ship.script.shipTakingDamage = new_std;
then this
- when that copy of the function runs later on the ship script event - refers to the ship script, and this.ship
is the script.Both, however, will call
worldScripts["Reduce Weapon Damage"]._rwd_ShipTakingDamage
and when this function runs, it is run by the worldscript object regardless of where it gets called from. You don't currently use this
in that function, but if it did, it would point to the worldscript object.No, that's about it for NPCs. (It fails in the case where the ship changes its ship script after creation, but that's rare). Generally you should try to avoid making global changes by editing ship scripts, but sometimes it's the only option to get a particular effect.Lone_Wolf wrote:Do you know a better / cleaner way ?
Incidentally, out of politeness to other OXPers, you should probably check that the ship has
ship.autoWeapons == true
before modifying its script, or you might break things.Re: [WIP] Reduce Weapons Damage
ok, calling context in oolite js is making more sense now.
A somewhat related question :
suppose i have references to equipment condtion scripts & equiment scripts in equipment.plist .
also some shipscripts in shipdata.plist .
If those scripts are not listed in worldscripts.plist , where does oolite look for them ?
A somewhat related question :
suppose i have references to equipment condtion scripts & equiment scripts in equipment.plist .
also some shipscripts in shipdata.plist .
If those scripts are not listed in worldscripts.plist , where does oolite look for them ?
looked up that property, and i'll implement a check for it.cim wrote:Incidentally, out of politeness to other OXPers, you should probably check that the ship has ship.autoWeapons == true before modifying its script, or you might break things.
OS : Arch Linux 64-bit - rolling release
OXPs : My user page
Retired, reachable at [email protected]
OXPs : My user page
Retired, reachable at [email protected]
Re: [WIP] Reduce Weapons Damage
All scripts regardless of type are loaded from the Scripts folder. Unlike a worldscript, however, there's no global object containing a reference to the other script types.Lone_Wolf wrote:suppose i have references to equipment condtion scripts & equiment scripts in equipment.plist .
also some shipscripts in shipdata.plist .
If those scripts are not listed in worldscripts.plist , where does oolite look for them ?
Re: [WIP] Reduce Weapons Damage
Latest code, a test-release may be coming soon.
Code: Select all
"use strict";
this.name = "Reduce Weapon Damage";
this.author = "Lone_Wolf";
this.copyright = "(C) 2014 Lone_Wolf.";
this.licence = "CC-by-SA 4.0";
this.description = "Reduce laser/missile damage for ships";
this.version = "0.10";
// Each ship in game will have a separate instance of this script
// using separate values for player / npc for flexibility .
this._rwd_player_reduction = 8;
this._rwd_npc_reduction = 8;
this.startUpComplete = function()
{
// setup handler for player.ship . npc-ships are dealt with by this.shipSpawned handler
if ( !player.ship.script ) { player.ship.setScript("oolite-default-ship-script.js"); }; // just in case
if ( player.ship.script.shipTakingDamage )
{
// there is already a shipTakingDamage handler, store it
player.ship.script._rwd_player_oldShipTakingDamage = ship.script.shipTakingDamage;
};
player.ship.script._RWD = this; // setup pointer
var new_std = function(amount, whom, type)
{
worldScripts["Reduce Weapon Damage"]._rwd_player_ShipTakingDamage(this.ship, amount, whom, type);
if ( player.ship.script._rwd_player_oldShipTakingDamage )
{
player.ship.script._rwd_oldShipTakingDamage(amount, whom, type); //call the original function
};
};
player.ship.script.shipTakingDamage = new_std;
};
this._rwd_player_ShipTakingDamage = function (whoami, amount, whom, type)
{
if ( type != "energy damage" ) { return; }; // only act upon laser / missile damage
if ( amount !=0 ) { return; }; // if hit penetrated shields, do nothing
/* shields have absorbed hit, there is no known way to determine the strength of the hit
* simplest solution to reduce damage is to increase shield strength
*/
// try to determine whether forward or aft shield is hit
if( whom && whom.isValid && ( player.ship.vectorForward.dot(player.ship.position.subtract(whom.position) ) > 0 ) )
{
// forward shield hit
player.ship.forwardShield += player.ship.script._RWD._rwd_player_reduction;
}
else
{
// aft hit
player.ship.aftShield += player.ship.script._RWD._rwd_player_reduction;
};
};
this.shipSpawned = function(ship)
{
// called for non-player ships only
if ( !ship || !ship.isPiloted || ship.isThargoid || ship.isStation ) { return; }; // only change npc-ships
if ( !ship.autoWeapons ) {return; }; // ship properties are not supposed to be altered
if ( !ship.script ) { ship.setScript("oolite-default-ship-script.js"); }; // just in case
if ( ship.script.shipTakingDamage )
{
// there is already a shipTakingDamage handler, store it
ship.script._rwd_npc_oldShipTakingDamage = ship.script.shipTakingDamage;
};
ship.script._RWD = this;
var new_std = function(amount, whom, type)
{
amount = worldScripts["Reduce Weapon Damage"]._rwd_npc_ShipTakingDamage(this.ship, amount, whom, type);
if ( ship.script._rwd_npc_oldShipTakingDamage )
{
ship.script._rwd_npc_oldShipTakingDamage(amount, whom, type); //call the original function
};
};
ship.script.shipTakingDamage = new_std;
};
this._rwd_npc_ShipTakingDamage = function (whoami, amount, whom, type)
{
if ( type != "energy damage" ) { return amount; }; // only act upon laser / missile damage
// npc ship, all that's needed is reducing damage amount
amount -= whoami.script._RWD._rwd_npc_reduction;
return amount;
};
OS : Arch Linux 64-bit - rolling release
OXPs : My user page
Retired, reachable at [email protected]
OXPs : My user page
Retired, reachable at [email protected]
Re: [WIP] Reduce Weapons Damage
Code is working well in my playtesting, i feel it's time to discuss the concept.
NOTE : this oxp is intended for 1.80.x oolite only, as 1.81+ already has changes to improve combat balance.
1. auto_weapons
In play testing i noticed that the oolite_template_viper doesn't have an auto_weapons entry, so it defaults to false.
Also auto_weapons was introduced in oolite 1.79, so all ships from oxps before 1.79 will have auto_weapons = false also.
In short, if i only allow the new shipTakingDamage handler for npc-ships with auto_weapons = yes , older npc-ships will NOT have the increased resistance to attacks.
This will make them weaker against player ship AND against newer npc-ships (including most core ships) with auto_weapons = yes.
My gut feeling is that this is an undesired side effect.
2. effect of attacker/defender strength and/or quality
if we want to vary the reduction based on those, i see some possibilities :
defender :
defenses ( shields / energy banks ) stronger defense > lower reduction.
pilot skill (kill count / accuracy ): better pilot > lower reduction
Attacker :
weapons ( military laser, aft laser, side lasers ) : better weapons > increase reduction
pilot skill (kill count /accuracy ) : more likely to score hits, increase reduction ?
NOTE : this oxp is intended for 1.80.x oolite only, as 1.81+ already has changes to improve combat balance.
1. auto_weapons
In play testing i noticed that the oolite_template_viper doesn't have an auto_weapons entry, so it defaults to false.
Also auto_weapons was introduced in oolite 1.79, so all ships from oxps before 1.79 will have auto_weapons = false also.
In short, if i only allow the new shipTakingDamage handler for npc-ships with auto_weapons = yes , older npc-ships will NOT have the increased resistance to attacks.
This will make them weaker against player ship AND against newer npc-ships (including most core ships) with auto_weapons = yes.
My gut feeling is that this is an undesired side effect.
2. effect of attacker/defender strength and/or quality
if we want to vary the reduction based on those, i see some possibilities :
defender :
defenses ( shields / energy banks ) stronger defense > lower reduction.
pilot skill (kill count / accuracy ): better pilot > lower reduction
Attacker :
weapons ( military laser, aft laser, side lasers ) : better weapons > increase reduction
pilot skill (kill count /accuracy ) : more likely to score hits, increase reduction ?
OS : Arch Linux 64-bit - rolling release
OXPs : My user page
Retired, reachable at [email protected]
OXPs : My user page
Retired, reachable at [email protected]