Page 1 of 1

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

Posted: Fri Nov 21, 2008 1:05 pm
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?

Posted: Fri Nov 21, 2008 1:22 pm
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).

Posted: Fri Nov 21, 2008 1:28 pm
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.

Posted: Fri Nov 21, 2008 2:19 pm
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!

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

Posted: Fri Nov 21, 2008 4:58 pm
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.

Posted: Sat Nov 22, 2008 7:35 am
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).

Posted: Sun Nov 23, 2008 11:31 pm
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>

Posted: Mon Nov 24, 2008 11:30 am
by Thargoid
Glad to be of service, and indeed to provide target practice :twisted: Enjoyable battle?

Posted: Mon Nov 24, 2008 11:47 am
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

Posted: Thu Nov 27, 2008 9:12 am
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.