Page 1 of 1

Fairly selective missile firing

Posted: Tue Mar 22, 2011 12:28 am
by UK_Eliter
Dear all

I'd like to write a javascript script for an NPC that implements the following algorithm.

(1) Select randomly from the missiles and bombs the NPC has on-board.
(2) Fire/drop the weapon, unless it is a mine (or missile) with a large blast radius - in which latter case, do nothing (or fire one of the other weapons, if any).

Obviously the following is equivalent (equivalent enough).

(1) Select randomly from the missiles and bombs the NPC has on-board, but exclude any with a a large blast radius.
(2) Fire/drop the selected weapon.

Any ideas?

I'm got a script whereby a cloaked ship intercepts other ships, decloaks, fires, and optionally fires a projectile. But I don't want the ship blowing itself up.

The simplest/good enough solution might simply be to put a timer (/delay/fuse) on NPC q-bombs. After all, the PLAYER has a (non-neglibile) timer for theirs.

Any ideas?

Thanks.

Re: Fairly selctive missile firing

Posted: Tue Mar 22, 2011 7:31 am
by Commander McLane
UK_Eliter wrote:
(1) Select randomly from the missiles and bombs the NPC has on-board.
(2) Fire/drop the weapon, unless it is a mine (or missile) with a large blast radius - in which latter case, do nothing (or fire one of the other weapons, if any).
Just firing a missile already randomly selects one of the available missiles. There is, however, a difference between missiles and mines, as they are used under different circumstances. An NPC will never drop a mine when it wants to fire a missile, and it will never fire a missile if it wants to drop a mine.

Firing missiles is not equivalent to dropping mines, neither strategically, nor tactically, nor in scripting terms. So I am not sure whether it would be a sensible thing to do in the first place.
UK_Eliter wrote:
(1) Select randomly from the missiles and bombs the NPC has on-board, but exclude any with a a large blast radius.
(2) Fire/drop the selected weapon.
Randomly selecting one of the pylon-mounted weapons is easy enough.

Code: Select all

{
    var missileSlot = Math.floor(Math.random() * this.ship.missiles.length);
    var selectedMissile = this.ship.missiles[missileSlot];
}
You can even write that in one line var selectedMissile = this.ship.missiles[Math.floor(Math.random() * this.ship.missiles.length)].

I am not sure what you mean by 'large blast radius'. I understand it to the effect of 'can/will kill the dropping ship as well'. This, however, depends on many factors, among them the strength and desired range of the dealing of damage, but also the current energy status of the dropping ship. The former are not known to scripts, I think. Therefore I'd say that you can't exclude a mine based on whether it can/will kill its dropping ship.

Also, as said above, missiles are completely different weapons from mines tactically and strategically. A missile is aimed at one single opponent and won't usually hurt anybody else. A mine is meant to work indiscriminately against more than one ship. If the dropping ship doesn't want to get hurt as well, there is one (and only one) simple solution: run away from it. However, running away doesn't make much sense after firing a missile. In situations where you can't run away fast enough, there is also one (and only one) simple solution: don't drop the mine in the first place, but use another weapon.

This is why I feel that a script which randomly selects either a missile or a mine, and fires/drops it regardless of the tactical situation, doesn't seem to make much sense.
UK_Eliter wrote:
I'm got a script whereby a cloaked ship intercepts other ships, decloaks, fires, and optionally fires a projectile. But I don't want the ship blowing itself up.
The same as above: a mine is not a projectile. Therefore I don't see why it should be selectable at all in this situation.
UK_Eliter wrote:
The simplest/good enough solution might simply be to put a timer (/delay/fuse) on NPC Q-bombs. After all, the PLAYER has a (non-neglibile) timer for theirs.
Mines do have timers, for instance the Q-mine. The five-second-delay is defined in its own AI. It doesn't matter who drops it. There may be OXP mines which don't have delays defined (I don't know them all). But if the don't have a delay defined, they also have no delay if dropped by the player. In short: who drops a mine has nothing to do with the mine's delay. This depends purely on the type of mine.

Take the mines occasionally dropped by Renegade Pirates as an example. You kill the Renegade, and he leaves a Q-bomb among the debris. Only five seconds later, when you have come close in order to scoop the floating cargo, the whole thing explodes in your face. A classical 'Press Space' moment. That's why it's always a wise decision to run away from killed Renegade Pirates and wait a little. If nothing happens after five seconds, it's safe to return an get the loot.

Re: Fairly selctive missile firing

Posted: Tue Mar 22, 2011 8:49 am
by Eric Walch
UK_Eliter wrote:
(1) Select randomly from the missiles and bombs the NPC has on-board.
(2) Fire/drop the weapon, unless it is a mine (or missile) with a large blast radius - in which latter case, do nothing (or fire one of the other weapons, if any).
One way of getting more control over the missiles used by npc is defining zero missiles in shipdata and max_missiles as the intended maximum. Than in shipSpawned() use code to load specific missiles by repeatedly using:

Code: Select all

this.ship.awardEquipment("foo_MISSILE");
until the bay is full.
"foo_MISSILE" is a random selection from a list of missiles to use. That way you know which to add or to leave out.

Re: Fairly selctive missile firing

Posted: Tue Mar 22, 2011 10:50 am
by Switeck
Missiles fired in large numbers in short succession should generally be the hardhead type, or 1 burst of ECM will destroy them all. I can understand an NPC ship firing every missile rapidly in desperation if at low energy though. Some ships might even fire 1 regular missile "early" before seriously threatened or even hit at all just to test out if the enemy ship has ECM.

Re: Fairly selctive missile firing

Posted: Tue Mar 22, 2011 6:14 pm
by UK_Eliter
Dear all

Thanks for your contributions!

Already my script uses 'fireMissile' to fire a missile randomly picked from the NPC's armoury. What must be happening, I think, is that sometimes the missile is a nuke (I have that OXP installed) or a quirium missile - and that's why I get instantly obliterated. (I have the missile analyser OXP installed, but it doesn't have time, given how my script works, to tell me the missile type). I could check this easily enough, it now occurs to me.

So probably what I need is a way of stopping the script choosing a/the quirium missile or (if I so decide) a nuke. I suppose that I could have the script try to fire (i.e. fire if the ship has one) either a normal missile or a hardhead. To that end I could have this

Code: Select all

{
    var missileSlot = Math.floor(Math.random() * this.ship.missiles.length);
    var selectedMissile = this.ship.missiles[missileSlot];
}
and then fire the missile only if it is a normal one or a hardhead (or perhaps an 'intercept' missile?). If someone could give me the code for THAT, I'd be very grateful. (I don't really know how to deal with complex data structures such as the ones that store missile information.)

Re: Fairly selctive missile firing

Posted: Tue Mar 22, 2011 7:56 pm
by Commander McLane
In this case I'd suggest you follow Eric's suggestion. Instead of waiting until a missile is fired and cancel the firing for specific missiles, why don't you make sure that the ship only has the missiles you want in the first place?

Step by step: in shipdata.plist, set missiles = 0. That way you make sure that the ship is created without any missiles.

Then, in your script, use

Code: Select all

this.shipSpawned = function()
{
    this.ship.awardEquipment("EQ_MISSILE");
    this.ship.awardEquipment("EQ_HARDENED_MISSILE");
    ...
}
You need as many lines of awardEquipment as there are missile slots on your ship, which is the value of max_missiles in shipdata.plist.

For each awardEquipment you can specify one missile of your liking. In my example it's one normal missile and one hardhead. But you can type any missile key you like. Just don't use EQ_RMB_CASCADE_MISSILE if you don't want that one.

As a result your ship will have exactly the missiles specified by you. Whenever one of them is fired, you don't need to care which type it is, because no type you don't like is possible.

You can even randomize the whole thing. Just create an array of all missile keys you like. And then for each awardEquipment take one random entry of the array.

Re: Fairly selective missile firing

Posted: Wed Mar 23, 2011 8:44 am
by Eric Walch
Cmd McLane wrote:
You can even randomize the whole thing. Just create an array of all missile keys you like. And then for each awardEquipment take one random entry of the array.
Yesterday I wrote a small script to implement in one of my own oxp ships:

Code: Select all

this.shipSpawned = function ()
{
    var missilesAvailable = ["EQ_HARDENED_MISSILE", "EQ_HARDENED_MISSILE"];
    if (worldScripts["Missiles & Bombs"])
    {
        // if M&B is installed, use some of that missiles.
        missilesAvailable.push("EQ_RMB_FRAG_MISSILE", "EQ_RMB_OVERRIDE_MISSILE");
    }
    var missileCount = missilesAvailable.length;
    var capacity = this.ship.missileCapacity;
    
    for (var i=0; i < capacity; i++)
    {
        // now fill the bay randomly with above missiles
        this.ship.awardEquipment(missilesAvailable[Math.floor(Math.random() * missileCount)]);
    }
    delete this.shipSpawned;
}
It loads your missile bay with predefined missiles, but in a random order. When missiles and bombs is installed, it also includes two of that missiles.
I also tried to include missiles from nukes,oxp, but that one has no worldScript to query its presence.

Re: Fairly selective missile firing

Posted: Wed Mar 23, 2011 8:59 am
by Commander McLane
Eric Walch wrote:
I also tried to include missiles from nukes,oxp, but that one has no worldScript to query its presence.
Couldn't you query for its equipment info object instead?

Code: Select all

if(EquipmentInfo.infoForKey("EQ_HARPOON_NUKE1_MISSILE"))
Of course this has still the limitation that you can only query for what you know exists. But at least you don't need a world script attached to it.

And if one missile from this OXP exists, you can assume that the others exist as well, and can push them too, if you like.

Re: Fairly selective missile firing

Posted: Fri Mar 25, 2011 12:55 am
by UK_Eliter
Dear all

Thanks. I did want, not to assign a whole set of missiles, but rather just to choose one - or rather choose one within certain limits - for firing at a particular time. And my ignorance (of javascript - which seems counterintuitive to me in its '==' and '&&' etc. - and of how Oolite works) meant I had a terrible time. In the end I settled on this:

Code: Select all

missileTypeChance  = Math.random();
if(this.ship.fireMissile("EQ_HARDENED_MISSILE") && (missileTypeChance > 0.5) ) // if has hardhead, and on a chance
{
	this.ship.fireMissile("EQ_HARDENED_MISSILE");
}
else // otherwise fire a normal missile (if ship has one)
{
	this.ship.fireMissile("EQ_MISSILE");
}
Having changed that, any many other things, I've uploaded another test version of the OXP. In this one the 'pirate king', who should appear when you launch from the station, should, finally, work more or less as he should (though other things are unfinished). I've turned off the debugging messages.

Download location: http://www.box.net/shared/moreq536ht

Re: Fairly selective missile firing

Posted: Fri Mar 25, 2011 7:31 am
by Commander McLane
This is also interesting, but it's a little different from what you originally wanted.

Code: Select all

missileTypeChance  = Math.random();
if(this.ship.fireMissile("EQ_HARDENED_MISSILE") && (missileTypeChance > 0.5) ) // if has hardhead, and on a chance
This line doesn't check whether the ship has a hardhead. Instead it attempts to fire a hardhead. If the attempt is successful, and missileTypeChance > 0.5, the script tries to fire another hardhead:

Code: Select all

{
	this.ship.fireMissile("EQ_HARDENED_MISSILE");
}
If the first attempt of firing a hardhead was unsuccessful, it will attempt to fire a normal missile:

Code: Select all

else // otherwise fire a normal missile (if ship has one)
{
	this.ship.fireMissile("EQ_MISSILE");
}
The general result is therefore:
  • If the ship has two hardheads, half of the time if will fire both in quick succession.
  • The other half of the time it will fire only one of them.
  • If it doesn't have a hardhead, but has a normal missile, it will fire the normal missile.
  • If it is choke full with other missiles, it doesn't fire any of them.
  • Therefore, if for instance the ship has 4 pylons, of which only one contains one of the core missiles, only this single missile will be fired. The rest of the pylons is useless.
  • Or, depending on the ship's AI, the other missiles will be fired anyway by the AI, and the player won't notice a difference to a normal pirate, except for the times when two hardheads are fired together.
This is because the first if-clause doesn't check whether the missile is available, but instead fires it right away. If you want to check whether a missile (or any other kind of equipment) is installed without at the same time using it, you have to check for its equipmentStatus with this.ship.equipmentStatus("EQ_HARDENED_MISSILE", "EQUIPMENT_OK"). This returns true if the missile is present, and false if it isn't. But it doesn't at the same time fire the missile.

Re: Fairly selective missile firing

Posted: Fri Mar 25, 2011 8:24 am
by Eric Walch
UK_Eliter wrote:
Dear all

Thanks. I did want, not to assign a whole set of missiles, but rather just to choose one - or rather choose one within certain limits - for firing at a particular time.
But to choose one, you first must make sure there is something to choose. When you don't write a routine to pre-load the missiles yourselves, Oolite will pre-load them for you on ship creation. Than you always will have 90% of one type and 10% of a random type.

Re: Fairly selective missile firing

Posted: Fri Mar 25, 2011 8:51 am
by UK_Eliter
@McLane: ah. Oops. Thanks for pointing out the mistake. I take it that all I need to do is to change the first line - to this:

Code: Select all

if ( this.ship.equipmentStatus("EQ_HARDENED_MISSILE", "EQUIPMENT_OK") && ( missileTypeChance > 0.5 ) ) // if has hardhead, and on a chance
@Eric: ah. Another oops, perhaps. So my thanks to you too. I didn't know it worked like that (90% of one type and 10% of a random type). Can you give me/point me towards more details, please?

Re: Fairly selective missile firing

Posted: Fri Mar 25, 2011 9:41 am
by Eric Walch
UK_Eliter wrote:
@Eric: ah. Another oops, perhaps. So my thanks to you too. I didn't know it worked like that (90% of one type and 10% of a random type). Can you give me/point me towards more details, please?
In 1.74 the missile handling was changed completely. Before, the ships started with zero missiles and missiles were only created on launch. With 1.74, npc could also have equipment and for scripts to be able to access this equipment, it had to be there on ships creation. The wiki referred partly to the old situation, so I just updated that part as it was confusing.

All ships are pre-loaded with 90% of the type defined in "missile_role" and 10% of a random type. (except for thargoids, who are handled special). Therefor my suggestion to define zero missiles as start and fully load it by script on spawning.

One other way would be to also start with zero but not preload them with a script, but to generate a specific missile on launch. Than you have maximum control over the fired missiles, but you you must add a missile counter in your script to avoid launching an indefinite number of missiles. :twisted:

In my belief is creating a suitable missile on npc missile-launch a kind of cheating (although invisible for a player), so I would preload them on spawning.

Re: Fairly selective missile firing

Posted: Fri Mar 25, 2011 12:35 pm
by UK_Eliter
Right: I've used a version of Eric's code to allocate missiles (instead of the 'shipdata') doing it, and amended my 'short range missiling' routine.

Those things, together with other tweaks and fixes, mean that - though probably there are still bugs - my 'pirate king' is now a truly devious b**** who manages, often, to take me apart (even though I'm flying the same ship as him) - and thus warrants his large kill and capture bounties. Now all I need to do is (1) get my 'hunter' versions sorted out (which will take a while) and (2) check for other bugs. Then I can put this thing on general release!