Help with how to use JS to test friendly fire incidents!

Discussion and information relevant to creating special missions, new ships, skins etc.

Moderators: winston, another_commander

Post Reply
User avatar
LittleBear
---- E L I T E ----
---- E L I T E ----
Posts: 2876
Joined: Tue Apr 04, 2006 7:02 pm
Location: On a survey mission for GalCop. Ship: Cobra Corvette: Hidden Dragon Rated: Deadly.

Help with how to use JS to test friendly fire incidents!

Post by LittleBear »

I'm sure there is a way to do this with a combination of JS and AI but I'm stuck! What I want to do is using this.beingAttacked check the role of the attacker. If the attacker role is not "random_hits_spacebar" then the script sends the message "REAL_ATTACKED" to the AI. If the role is "random_hits_spacebar" no message is sent. I then change all the AI "ATTACKED =" to "REAL_ATTACKED", so a response to an attack is only triggerd if the attacker is any ship other than the random_hits_spacebar role. The reason I want to do this is that the bar using its turrets often catches one of its defence ships, which then turns on the bar.

I can't use the whom function because this returns the display name of the ship. Because I've randomised this to "[hunter_first_name] [nom] ([hunter-rank])" there's millions of possible names display name hunters could have (and I need to set the bars to not regard a stray shot by a hunter as an attack as well). Is there a way to check the attacker's role?

BTW On 1.72 on Vista the stdrr file is no longer in the oolite.app directory. I suspect Vista of doing something "helpful" and putting it somewhere else! Do any vista users know where to find it?
OXPS : The Assassins Guild, Asteroid Storm, The Bank of the Black Monks, Random Hits, The Galactic Almanac, Renegade Pirates can be downloaded from the Elite Wiki here.
User avatar
Thargoid
Thargoid
Thargoid
Posts: 5528
Joined: Thu Jun 12, 2008 6:55 pm

Post by Thargoid »

You can use sendScriptMessage within the AI to trigger a script event, and going the other way reactToAIMessage in the script to switch the AI state.

So if you use the first to trigger the script event, the script itself to do the differentiation and then depending on that result use the latter to set the AI state accordingly, you should be able to do what you want.

If you want to see it "in code", have a look in my Drones OXP, where Eric was kind enough to help with this part (amongst others).
User avatar
Eric Walch
Slightly Grand Rear Admiral
Slightly Grand Rear Admiral
Posts: 5536
Joined: Sat Jun 16, 2007 3:48 pm
Location: Netherlands

Post by Eric Walch »

Hello LB,

You should look in the rolelist. I assume all have a common role other than their primaryRole. If yes, than you can use the JS property "indexOf()" to check if your search role is among the list. If not, it returns -1 if yes it returns the position in the array.

Code: Select all

this.shipBeingAttacked  = function(who)
{
    if(who.roles.indexOf("searchRole") == -1)
    { 
         this.ship.reactToAIMessage("HOSTILE_ATTACK");
    }
}
Or just use:

Code: Select all

this.shipBeingAttacked  = function(who)
{
    if(who.primaryRole != "searchRole")
    { 
         this.ship.reactToAIMessage("HOSTILE_ATTACK");
    }
}
When you just want to check for the primary role it was spawned with.

Than rename in your AI the massage name "ATTACKED" by "HOSTILE_ATTACK". The normal attack messages now never reach the AI but the JS will get them. After analysing them it sends a HOSTILE_ATTACK to its own script. This way you filtered friendly fire out.
User avatar
LittleBear
---- E L I T E ----
---- E L I T E ----
Posts: 2876
Joined: Tue Apr 04, 2006 7:02 pm
Location: On a survey mission for GalCop. Ship: Cobra Corvette: Hidden Dragon Rated: Deadly.

Post by LittleBear »

Thanks guys. This simple test script is working to ID the attacker:-

Code: Select all

/*
this.name = "oolite-random-hits-spacebar";
this.author = "LittleBear, Eric Walch & Thargoid";
this.copyright = "November 2008 - But do what you like with it in your OXPs!";
this.description	= "Checks the role of a ship attacking a spacebar to avoid friendly fire incidents between the bar's turret gunners and hunters launched by the bar."
this.version = "2.0";
*/

this.shipBeingAttacked = function(who)
{
    if(who.primaryRole != "random_hits_patrol") 
    {
player.consoleMessage(this.ship.name+" attacked by a real enemy.", 6);      
		}
    else
    {
    player.consoleMessage(this.ship.name+" attacked by a hunter ship.", 6);
		}
}
I'll add the AI message bit now!
OXPS : The Assassins Guild, Asteroid Storm, The Bank of the Black Monks, Random Hits, The Galactic Almanac, Renegade Pirates can be downloaded from the Elite Wiki here.
User avatar
JensAyton
Grand Admiral Emeritus
Grand Admiral Emeritus
Posts: 6657
Joined: Sat Apr 02, 2005 2:43 pm
Location: Sweden
Contact:

Re: Help with how to use JS to test friendly fire incidents!

Post by JensAyton »

LittleBear wrote:
BTW On 1.72 on Vista the stdrr file is no longer in the oolite.app directory. I suspect Vista of doing something "helpful" and putting it somewhere else! Do any vista users know where to find it?
Release notes wrote:
  • (Non-Mac) Logs are now written to ~/.Oolite/Logs/under Linux and <app directory>\Oolite\Logs\ under Windows. (Oh yes, I intended to change it to GNUstep default locations. Oh well.) OXP verifier logs also end up there, named by OXP.
User avatar
Commander McLane
---- E L I T E ----
---- E L I T E ----
Posts: 9520
Joined: Thu Dec 14, 2006 9:08 am
Location: a Hacker Outpost in a moderately remote area
Contact:

Post by Commander McLane »

BTW: You don't need to put it in this.shipBeingAttacked. You can also start the whole query from the original ATTACKED-state(s) of the AI. Just put a "sendScriptMessage:" in there instead of its usual content, which you can move into a ATTACKED_BY_HOSTILE as Eric suggested. If the test reveals that the attacker is indeed a hostile, you send this message back to the AI; if it doesn't, you send back another message (or none).
User avatar
LittleBear
---- E L I T E ----
---- E L I T E ----
Posts: 2876
Joined: Tue Apr 04, 2006 7:02 pm
Location: On a survey mission for GalCop. Ship: Cobra Corvette: Hidden Dragon Rated: Deadly.

Post by LittleBear »

Really pleased with the effect with this script! Been playtesting (with Thargoid's Second Wave installed :wink: ), spawning a bar and 15 thargoids by the w/p. The Gunners are opening up on the bugs, but stopping fire if they hit a hunter or a clean ship by mistake and the hunters break off if they hit the bar, another clean ship or each other by mistake. By using FRIENDLY_FIRE and ENEMY_FIRE as AI messages, they send curses (but don't attack) if hit by friendly fire or say sorry if they hit friendly ship. Still need to playtest a bit more, but seems to be working.

Script

Code: Select all

/*
this.name = "oolite-random-hits-spacebar";
this.author = "LittleBear, Eric Walch & Thargoid";
this.copyright = "November 2008 - But do what you like with it in your OXPs!";
this.description	= "Checks the role of a ship attacking a spacebar to avoid friendly fire incidents between the bar's turret gunners and hunters launched by the bar."
this.version = "2.0";
*/

this.shipBeingAttacked = function(who)
{
    if(who.primaryRole == "random_hits_patrol") 
    {
this.ship.reactToAIMessage("LAWFUL_ATTACK"); // The AIs of the bars and hunters do not react to the nomal "ATTACKED" message, only the special "ENEMY_ATTACK". They therefore ignore attacks by their own side and the police. The lawful attacker has it's AI set to randomhitsbackoffAI which forces it to off and stop attacking, before being returned to its normalAI.
this.ship.bounty = 0		
		}
	if(who.primaryRole == "police") 
    {
this.ship.reactToAIMessage("LAWFUL_ATTACK");  // Since neither police or hunter ships will deliberatley target a Clean Target - bar is kept clean at all times - The Bar takes attackes by ships with these roles as a friendly fire stray shot and does not fire back.
this.ship.bounty = 0		
		}	
    else
    {
	this.ship.reactToAIMessage("ENEMY_ATTACK"); // Any other attack is met with deadly force! 
	this.ship.bounty = 0
		}
}
SpaceBar's Attack State:-

Code: Select all

"ATTACK" = {
 "ENEMY_ATTACK" = (setTargetToFoundTarget, "sendTargetCommsMessage: [spacebar-warning]", "markTargetForOffence: 51", increaseAlertLevel, groupAttackTarget);
 "LAWFUL_ATTACK" = (setTargetToFoundTarget, "safeScriptActionOnTarget: setAITo: randomhitsbreakoffAI.plist", setTargetToSystemStation, "setStateTo: SCAN_FOR_CRIMINAL_PLAYER");
 "OFFENCE_COMMITTED" = (setTargetToFoundTarget, "markTargetForOffence: 15", increaseAlertLevel, "sendTargetCommsMessage: [spacebar-warning]", groupAttackTarget); 
 "ACCEPT_DISTRESS_CALL" = (setTargetToFoundTarget, increaseAlertLevel, "launchShipWithRole: random_hits_patrol", groupAttackTarget);
 "ENTER" = ("launchShipWithRole: random_hits_patrol", checkTargetLegalStatus, increaseAlertLevel);
 "EXIT" =();
 "INCOMING_MISSILE" = (fireECM, setTargetToFoundTarget, "sendTargetCommsMessage: [spacebar-warning]", "markTargetForOffence: 51", increaseAlertLevel);
 "NO_TARGET" = (setTargetToSystemStation, "setStateTo: SCAN_FOR_CRIMINAL_PLAYER");
 "RED_ALERT" = ("launchShipWithRole: random_hits_patrol");
 "CONDITION_GREEN" = (setTargetToSystemStation, "setStateTo: SCAN_FOR_CRIMINAL_PLAYER");
 "TARGET_DESTROYED" = (setTargetToSystemStation, "setStateTo: SCAN_FOR_CRIMINAL_PLAYER");
 "TARGET_LOST" = (setTargetToSystemStation, "setStateTo: SCAN_FOR_CRIMINAL_PLAYER");
 "TARGET_CLEAN" = ("sendTargetCommsMessage: [random_hits_sorry_for_friendly_fire]", setTargetToSystemStation, "setStateTo: SCAN_FOR_CRIMINAL_PLAYER");
 "UPDATE" = ("pauseAI: 1.0", checkTargetLegalStatus, decreaseAlertLevel, performAttack);    };
Hunter's Attack States :-

Code: Select all

"ATTACK_ATTACKING_SHIP" = {
        ENTER = (performAttack); 
        "ENEMY_ATTACK" = (setTargetToFoundTarget, "markTargetForOffence: 15", performAttack);
        "FRIENDLY_FIRE" = ( "setStateTo: FRIENDLY_FIRE_INCIDENT"); 
        "ENERGY_LOW" = (setTargetToFoundTarget, performAttack); 
        "INCOMING_MISSILE" = (fightOrFleeMissile, setTargetToFoundTarget, "markTargetForOffence: 15", performAttack);
        "TARGET_DESTROYED" = (setTargetToSystemStation, "setStateTo: RANGE_CHECK"); 
        "TARGET_LOST" = (setTargetToSystemStation, "setStateTo: RANGE_CHECK");
        "FRUSTRATED" = (performAttack);
        EXIT = (); 
	  UPDATE = (); 
     };

"ATTACK_SELECTED_TARGET" = {
        ENTER = (checkTargetLegalStatus); 
        "ENEMY_ATTACK" = (setTargetToFoundTarget, "markTargetForOffence: 15", "setStateTo: ATTACK_ATTACKING_SHIP"); 
        "ENERGY_LOW" = (setTargetToFoundTarget, performAttack); 
        "INCOMING_MISSILE" = (fightOrFleeMissile, "markTargetForOffence: 15", performAttack);
        "TARGET_DESTROYED" = (setTargetToSystemStation, "setStateTo: RANGE_CHECK"); 
        "TARGET_LOST" = (setTargetToSystemStation, "setStateTo: SCAN_FOR_CRIMINAL_TRADERS");
        "TARGET_CLEAN" = ("setStateTo: SORRY_FOR_FRIENDLY_FIRE_INCIDENT");
        "FRIENDLY_FIRE" = ("setStateTo: FRIENDLY_FIRE_INCIDENT");
        "FRUSTRATED" = (performAttack);
        EXIT = (); 
	  UPDATE = (checkTargetLegalStatus, performAttack); 
     };

"FRIENDLY_FIRE_INCIDENT" = {
	ENTER = ("commsMessage: [random_hits_friendly_fire]", setTargetToFoundTarget, "addFuel: 3", "setSpeedFactorTo: 2.0", "setDesiredRangeTo: 2500", performFlee);
	"ENERGY_LOW" = ();
	"INCOMING_MISSILE" = (setTargetToFoundTarget, fightOrFleeMissile, performFlee); 
	"ENEMY_ATTACK" = (setTargetToFoundTarget, "setStateTo: ATTACK_ATTACKING_SHIP"); 
	"TARGET_LOST" = (performIdle, "addFuel: -3", setTargetToSystemStation, "setStateTo: FRIENDLY_FIRE_INCIDENT_PAUSE"); 
	"TARGET_DESTROYED" = (performIdle, "addFuel: -3", setTargetToSystemStation, "setStateTo: FRIENDLY_FIRE_INCIDENT_PAUSE"); 
	EXIT = ();  
	"REACHED_SAFETY" = (performIdle, "addFuel: -3", setTargetToSystemStation, "setStateTo: FRIENDLY_FIRE_INCIDENT_PAUSE");
	"DESIRED_RANGE_ACHIEVED" = (performIdle, "addFuel: -3", setTargetToSystemStation, "setStateTo: FRIENDLY_FIRE_INCIDENT_PAUSE");
	UPDATE = ();     };

"SORRY_FOR_FRIENDLY_FIRE_INCIDENT" = {
	ENTER = ("commsMessage: [random_hits_sorry_for_friendly_fire]", setTargetToFoundTarget, "addFuel: 3", "setSpeedFactorTo: 2.0", "setDesiredRangeTo: 2500", performFlee);
	"ENERGY_LOW" = ();
	"INCOMING_MISSILE" = (setTargetToFoundTarget, fightOrFleeMissile, performFlee); 
	"ENEMY_ATTACK" = (setTargetToFoundTarget, "setStateTo: ATTACK_ATTACKING_SHIP"); 
	"TARGET_LOST" = (performIdle, "addFuel: -3", setTargetToSystemStation, "setStateTo: FRIENDLY_FIRE_INCIDENT_PAUSE"); 
	"TARGET_DESTROYED" = (performIdle, "addFuel: -3", setTargetToSystemStation, "setStateTo: FRIENDLY_FIRE_INCIDENT_PAUSE"); 
	EXIT = ();  
	"REACHED_SAFETY" = (performIdle, "addFuel: -3", setTargetToSystemStation, "setStateTo: FRIENDLY_FIRE_INCIDENT_PAUSE");
	"DESIRED_RANGE_ACHIEVED" = (performIdle, "addFuel: -3", setTargetToSystemStation, "setStateTo: FRIENDLY_FIRE_INCIDENT_PAUSE");
	UPDATE = ();     };

"FRIENDLY_FIRE_INCIDENT_PAUSE" = {
	ENTER = (setTargetToSystemStation, "setSpeedFactorTo: 1.0", performIdle, "pauseAI: 1.0");
	"ENERGY_LOW" = ();
	"INCOMING_MISSILE" = (setTargetToFoundTarget, fightOrFleeMissile, "setStateTo: ATTACK_ATTACKING_SHIP"); 
	"ENEMY_ATTACK" = (setTargetToFoundTarget, "setStateTo: ATTACK_ATTACKING_SHIP"); 
	EXIT = ();  
	UPDATE = ("setStateTo: RANGE_CHECK");     };
BreakOffAI to force the Lawful Attacker to stop attacking and back off:-

Code: Select all

{

"GLOBAL" = {
ENTER = ("commsMessage: [random_hits_sorry_for_friendly_fire]", "setStateTo: BREAK_OFF_ATTACK"); 
EXIT = ();  
UPDATE = ();     };

"BREAK_OFF_ATTACK" = {
	ENTER = ("addFuel: 3", "setSpeedFactorTo: 2.0", "setDesiredRangeTo: 5500", performFlee);
	"ENERGY_LOW" = ();
	"INCOMING_MISSILE" = (setTargetToFoundTarget, performFlee);  
	"TARGET_LOST" = (performIdle, "addFuel: -3", setTargetToSystemStation, "setStateTo: BREAK_OFF_ATTACK_PAUSE"); 
	"TARGET_DESTROYED" = (performIdle, "addFuel: -3", setTargetToSystemStation, "setStateTo: BREAK_OFF_ATTACK_PAUSE"); 
	EXIT = ();  
	"REACHED_SAFETY" = (performIdle, "addFuel: -3", setTargetToSystemStation, "setStateTo: BREAK_OFF_ATTACK_PAUSE");
	"DESIRED_RANGE_ACHIEVED" = (performIdle, "addFuel: -3", setTargetToSystemStation, "setStateTo: BREAK_OFF_ATTACK_PAUSE");
	UPDATE = ();     };

"BREAK_OFF_ATTACK_PAUSE" = {
	ENTER = ("setSpeedFactorTo: 1.0", performIdle);
	"ENERGY_LOW" = ();
	EXIT = ();  
	UPDATE = ("pauseAI: 1.0", setTargetToSystemStation, exitAI);     };


}
And some entries in descriptions for some curses / applogies. If anybody wants to post some more I'll C&P them in! :-

Code: Select all

<!-- Strings used for hunters' complaints / appologies over friendly fire incidents! -->

	<key>random_hits_friendly_fire</key>
	<array>
	<string>[random_hits_friendly_fire1] [assassination_board_insult]! [random_hits_friendly_fire2]</string>
	</array>

	<key>random_hits_friendly_fire1</key>
	<array>
	<string>Blue on Blue</string>
	<string>I'm on your side</string>
	<string>Watch your fire</string>
	</array>

	<key>random_hits_friendly_fire2</key>
	<array>
	<string>Stop it!</string>
	<string>Cease your attack!</string>
	<string>Be more careful!</string>
	<string>Check your targets!</string>
	<string>Are you blind?</string>
	<string>Do I look like a [spacebar-warning2]?</string>
	</array>

	<key>random_hits_sorry_for_friendly_fire</key>
	<array>
	<string>[random_hits_sorry_for_friendly_fire1] [random_hits_sorry_for_friendly_fire2]. [random_hits_sorry_for_friendly_fire3]!</string>
	</array>

	<key>random_hits_sorry_for_friendly_fire1</key>
	<array>
	<string>Sorry</string>
	<string>My appologies</string>
	<string>I beg your pardon</string>
	</array>

	<key>random_hits_sorry_for_friendly_fire2</key>
	<array>
	<string>dude</string>
	<string>buddy</string>
	<string>mate</string>
	</array>

	<key>random_hits_sorry_for_friendly_fire3</key>
	<array>
	<string>There are trumbles in my targeting computer</string>
	<string>My mistake</string>
	<string>I thought you were a [spacebar-warning2]</string>
	</array>
OXPS : The Assassins Guild, Asteroid Storm, The Bank of the Black Monks, Random Hits, The Galactic Almanac, Renegade Pirates can be downloaded from the Elite Wiki here.
User avatar
Thargoid
Thargoid
Thargoid
Posts: 5528
Joined: Thu Jun 12, 2008 6:55 pm

Post by Thargoid »

Glad to be of service, and indeed to provide target practice :twisted: Enjoyable battle?
User avatar
LittleBear
---- E L I T E ----
---- E L I T E ----
Posts: 2876
Joined: Tue Apr 04, 2006 7:02 pm
Location: On a survey mission for GalCop. Ship: Cobra Corvette: Hidden Dragon Rated: Deadly.

Post by LittleBear »

Parked up some distance away with my cloak up (purley in the interests of testing of course). Fierce battle fought though, the bugs even taking out the witchspace beacon. A GRS tug still bravely ran the gauntlet to bring in a replacement :-

Image
OXPS : The Assassins Guild, Asteroid Storm, The Bank of the Black Monks, Random Hits, The Galactic Almanac, Renegade Pirates can be downloaded from the Elite Wiki here.
User avatar
Commander McLane
---- E L I T E ----
---- E L I T E ----
Posts: 9520
Joined: Thu Dec 14, 2006 9:08 am
Location: a Hacker Outpost in a moderately remote area
Contact:

Post by Commander McLane »

Just to emphasize that friendly-fire handling has to be improved generally, here's a report I got just now from our correspondent in the Lausmaes system in Galaxy 5 (but it could happen anywhere, anytime):

I am just watching an epic fight on my screen. I arrived late, so I don't know how it started.

Anyway, the opponents are a military leviathan and some police-vipers with role wingman. So I suppose they escorted a police ship that was blasted into oblivion by the Leviathan's party. (Yet they are still in state FLYING_ESCORT, although they don't have an owner anymore. Therefore they are easy prey for Military Hydras!) Some other, independent, police ships are also involved.

The notable thing is that the Leviathan, its escorts, and some of its defense ships all have a bounty of 64 cr on their heads. I guess as a result of a friendly fire incident.

However, some of its defense ships are clean (probably the ones that were launched later? or the ones that were launched earlier, if defense ships inherit their owner's bounty?).

So now I am watching a clean Military Hydra (defense ship of the Leviathan) attacking a fugitive Military Hydra (also defense ship of the same Leviathan), which was attempting to dock again with their mother. Meanwhile, however, said fugitive Hydra has switched to its interceptAI, still with the mother as its target, and is therefore attacking its mother instead of docking with it, I guess.

What a mess!

:shock: :shock: :shock: :shock: :shock:

I think this is what we get because of the missing friendly-fire handling.
Post Reply