Join us at the Oolite Anniversary Party -- London, 7th July 2024, 1pm
More details in this thread.

Split: Deployable subentities

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

Moderators: winston, another_commander

User avatar
Pleb
---- E L I T E ----
---- E L I T E ----
Posts: 908
Joined: Sun Apr 29, 2012 2:23 pm
Location: United Kingdom

Re: Scripters cove

Post by Pleb »

Hi guys,

Is there a way of counting the number of escape capsules a player has scooped? For example, I have a mission where the player has to scoop a certain number of escape capsules before continuing, and although I know I can use the shipWasScooped event handler if the capsule has a cargo type of CARGO_SCRIPTED_ITEM this essentially breaks the escape capsule feature as nothing comes up in the manifest when the capsule is scooped.

Is there a way of getting a script to count the number of scoops into a variable?

Thanks!
Desktop PC: CPU: Intel i7-4790K Quad Core 4.4GHz (Turbo-Charged) GPU: Nvidia GeForce GTX 1080Ti RAM: 32GB DDR3

Laptop PC: CPU: Intel i5-10300H Quad Core 4.5GHz (Turbo-Charged) GPU: Nvidia GeForce GTX 1650 RAM: 32GB DDR4
User avatar
cim
Quite Grand Sub-Admiral
Quite Grand Sub-Admiral
Posts: 4072
Joined: Fri Nov 11, 2011 6:19 pm

Re: Scripters cove

Post by cim »

Try the shipScoopedOther event handler instead - that activates even for normal cargo.
User avatar
cim
Quite Grand Sub-Admiral
Quite Grand Sub-Admiral
Posts: 4072
Joined: Fri Nov 11, 2011 6:19 pm

Re: Scripters cove

Post by cim »

dertien wrote:
Here's as far as I got:
Not related as far as I can tell, but please don't do this - overriding the template entries can cause serious problems. It shouldn't ever be necessary.

Code: Select all

"oolite_template_cobra3" =
	{
		like_ship = "HPCcobramk3_sentinel";
	};
Overriding the other entries is fine.

You have this function. ship should be this.ship here.

Code: Select all

this._findSubEntity = function(key)
{
  for (var i = ship.subEntities.length - 1 ; i >=0 ; --i)
  {
    if (ship.subEntities[i].dataKey == key)
    {
      return ship.SubEntities[i];
In shipDied you have

Code: Select all

   switch(this.ship.primaryRole)
    {
		case "HPC_CO3_LCBhull": // role; not the entry name ! since here they are the same, it doesn't matter
As far as I can tell, subentities don't get roles, since they're added by key, not by role. Try this.ship.dataKey instead

Later on in the shipDied handler you use "lcblight", but that won't necessarily be defined at that point (and definitely won't if you move the bit above into a separate non-subent script). So something like this instead

Code: Select all

{
            this.ship.owner.commsMessage("SYSFAIL - LCB");
			this.ship.spawn("cargopod", (Math.ceil(Math.random() * 6) - 1));
		var lcblight = this._findSubEntity("HPC_CO3_LCBlights")
		if (lcblight)
				{
					lcblight.remove();
				}
            break;
        }
This bit of code isn't inside any event handler. At the moment you're using the same script file for the main ship and for its subentities, which is going to get confusing - give the main Cobra III its own separate ship script (which will need its own copy of the this._findSubEntity function). I'm not entirely sure of the best place to run this code, actually - at ship initialisation (including when reloading a saved game) the subentity will definitely be present.

Code: Select all

if (this._findSubEntity("HPC_CO3_LCBhull") == null)
{
	this.ship.setEquipmentStatus("EQ_CARGO_BAY","EQUIPMENT_DAMAGED");
		var lcblight = this._findSubEntity("HPC_CO3_LCBlights")
		if (lcblight)
			{
				lcblight.remove();
			}
}
Hmm... actually, this is going to be really complicated. When the player starts a game with this ship, they may not have a large cargo bay, so you have to remove the relevant subentities then. Having done that, you then need to restore that subentity and only that subentity when they buy the LCB (which is difficult), and then keep it in sync for damage/restore. Further, the missing LCB subentity will be considered by the game to be a servicing need, so the Maintenance Overhaul will be offered: if the player buys it, it will put the LCB subentity back and you'll have to remove it again ... which will reoffer the Maintenance Overhaul.

I think with sufficient work all of these problems - including the Maintenance Overhaul one - are possible to overcome, but it'll take a lot of time and skill.


As an aside, in this specific case, the Large Cargo Bay cannot be damaged (damage probability 0). You'll need to remove the equipment item completely in this case (which will first require removing any cargo which can't be carried if it is removed - you can't remove it either if it would result in insufficient cargo space). Most other equipment is a little simpler than that.
dertien
---- E L I T E ----
---- E L I T E ----
Posts: 471
Joined: Sun Jan 23, 2011 9:27 pm
Location: Belgium, Monarchy, Feudal, Overtaxed system

Re: Scripters cove

Post by dertien »

Well, I tried out what you said, and still no dice.

There is however 2 parts to this script. I understand that more than likely the NPC's and the player versions will have different scripts, for the issues you pointed out. So I am first struggling with an NPC version that would remove subentities as needed when some are shot off. I know I can do it by adding them as subentities of subentities like you said in your first post, but doing it by scripting looks cleaner.

The original code I used comes from Eric and I thought with a bit of tinkering, I could get it to work for NPC's just like his works perfectly.

The original code with the switch case comes from his oxp, and basically in the shipdata.plist of that file you will see that the shipentries do not have a script="heregoesmyscript.js" , but the script reference is only in the subentities that can be shot off. A small exerpt of the shipdata.plist goes like this:

the ship:

Code: Select all

"Griff_Krait_Wealthy_green" = 
	{
	like_ship = "griff_krait_wealthy_template";
	roles = "pirate(0.2)";	
	model = "griff_krait_main_hull.dat"; 
	name = "Griff Krait";
	materials = 
		{ 
			"griff_krait_blue_diffuse.png" = 
			{ 
			diffuse_map = "griff_krait_green_diffuse.png"; 
			specular_color = ( 0.2, 0.2, 0.2 );  // Applies when specular map is not used (no shaders) 
			shininess = 15; 
			illumination_map = { name = "griff_krait_effects_illum.png"; extract_channel = "a"; }; 
			illumination_color  = (1.0, 1.0, 1.0);			
			}; 
		};
	shaders = 
		{ 
            "griff_krait_blue_diffuse.png" = 
			{ 
                vertex_shader = "griff_krait_generic.vertex"; 
                fragment_shader = "griff_krait_hull_fi.fragment"; 
             
                textures = ("griff_krait_green_diffuse.png",	"griff_krait_effects_illum.png");
           
				uniforms = 
				{ 
				uColorMap = { type = texture; value = 0; };
				uEffectsMap = { type = texture; value = 1; };				
				uTime = "universalTime"; 
				engine_power = "speedFactor"; 
				nearly_dead = "throwingSparks"; 
				hull_heat_level = "hullHeatLevel";				
				}; 				
			}; 
		}; 
	};
as you can see, no reference to a script file here
however, here is one of the subentities in this case the fuel injectors that can be shot off:

Code: Select all

"griff_krait_chrome_fuel_injectors" = 
	{
	ai_type = "nullAI.plist";
	auto_ai = "false";
	model = "griff_krait_fuel_injectors.dat"; 
	name = "Krait";
	roles = "griff_krait_fuel_injectors";
	script = "griff_krait_subent.js";
	forward_weapon_type = "WEAPON_NONE";
	smooth = "true";
	materials = 
		{ 
			"griff_krait_blue_diffuse.png" = 
			{ 
			specular_color = ( 0.2, 0.2, 0.2 );  // Applies when specular map is not used (no shaders) 
			shininess = 15; 	
			illumination_map = { name = "griff_krait_effects_illum.png"; extract_channel = "a"; }; 
			illumination_color  = (1.0, 1.0, 1.0);			
			}; 
		};	
	max_energy = 40;
	shaders = 
		{ 
            "griff_krait_blue_diffuse.png" = 
			{ 
                vertex_shader = "griff_krait_enviromap.vertex"; 
                fragment_shader = "griff_krait_chrome_hull_fi.fragment"; 
             
                textures = ("griff_krait_blue_diffuse.png", "griff_krait_effects_illum.png",
				{name = "griff_enviromentmap1.png"; repeat_s = "yes"; repeat_t = "yes";}); 
				           
				uniforms = 
				{ 
				uColorMap = { type = texture; value = 0; };
				uEffectsMap = { type = texture; value = 1; };
				uEnvMap = { type = texture; value = 2; };				
				uTime = "universalTime"; 
				engine_power = "speedFactor"; 
				nearly_dead = "throwingSparks"; 
				hull_heat_level = "hullHeatLevel";
				}; 
			}; 
		};
	};
Here there is a script file in the shipdata.plist entry.

the complete code of his griff_krait_subent.js is this:

Code: Select all

this.name      = "griff_krait_subent"; 
this.author    = "griff"; 
this.copyright = "� 2008 griff."; 
this.version   = "1.01";

this.shipDied = function () 
{ 
    switch(this.ship.primaryRole)
    {
    case "griff_krait_ecm": 
        {
            this.ship.owner.commsMessage("There goes my ecm.");
            this.ship.owner.removeEquipment("EQ_ECM");
            break;
        }
    case "griff_krait_extra_eu":
        {
            // npc have no extra_eu, remove booster instead.
            // (Or remove the EQ_SHIELD_ENHANCER)
            this.ship.owner.commsMessage("There goes my enery unit.");
            this.ship.owner.removeEquipment("EQ_SHIELD_BOOSTER");
            break;
        }
    case "griff_krait_fuel_injectors": 
        {
            this.ship.owner.commsMessage("There goes my fuel injector.");
            this.ship.owner.removeEquipment("EQ_FUEL_INJECTION");
            break;
        }
    case "griff_krait_fuel_scoop": 
        {
            this.ship.owner.commsMessage("There goes my fuel scoop.");
            this.ship.owner.removeEquipment("EQ_FUEL_SCOOPS");
            break;
        }
    case "griff_krait_laser": 
        {
            this.ship.owner.commsMessage("There goes my laser.");
            // no need to remove something as this subent realy contains the laser.
            break;
        }
        default: break
    }
};
This works perfectly so I thought, hell, why not add a few lines so I can destroy the subents that are part of other subents, and using your code I tried.

No matter what I put in the case switch, it will do everything, except remove the right subentity.

The shipdata.plist script reference however does not work if I attach it to the ship. It works partially by using it in the shipdata.plist of the subents, which is a different oxp folder in my case.

So if I put it like this:

Code: Select all

this.name      = "griff_krait_subent"; 
this.author    = "griff"; 
this.copyright = "griff."; 
this.version   = "1.01";

this.shipDied = function () 
{ 
    switch(this.ship.dataKey)
    {
    case "HPC_CO3_LCBhull": 
        {
            this.ship.owner.commsMessage("SYSFAIL - LCB");
			this.ship.owner.removeEquipment("EQ_FUEL_INJECTION");
				this.ship.spawn("cargopod", (Math.ceil(Math.random() * 6) - 1));
					this._findSubEntity = function(key)
					{
					for (var i = this.ship.subEntities.length - 1 ; i >=0 ; --i)
						{
						if (this.ship.subEntities[i].dataKey == key)
							{
							return this.ship.SubEntities[i];
							}
						}
						return null; // couldn't find it.
					}
					var lcblight = this._findSubEntity("HPC_CO3_LCBlights")
						if (lcblight)
					{
					lcblight.remove();
					}
            break;
        }
        default: break	
    }

};
It will give me the message
release the cargopods
and remove the target ships fuel injectors in this case as a test,

the subent lights however are still present:

Image

I will worry about the scripting for the player versions later.

Code: Select all

"oolite_template_cobra3" =
   {
      like_ship = "HPCcobramk3_sentinel";
   };
And last but not least, I used this code so the default cobra mk 3 do not show up ingame anymore, since I removed it I have still some of Griff's versions flying around, is there another way I can remove them without resorting to the code above ?

Thanks
Alpha Backer of Elite Dangerous
With 250 GBP :D
User avatar
cim
Quite Grand Sub-Admiral
Quite Grand Sub-Admiral
Posts: 4072
Joined: Fri Nov 11, 2011 6:19 pm

Re: Scripters cove

Post by cim »

In this bit

Code: Select all

this._findSubEntity = function(key)
               {
               for (var i = this.ship.subEntities.length - 1 ; i >=0 ; --i)
                  {
                  if (this.ship.subEntities[i].dataKey == key)
                     {
                     return this.ship.SubEntities[i];
                     }
                  }
                  return null; // couldn't find it.
               }
this.ship is the subentity, so you're searching its subentities (which it doesn't have). If you change the function to

Code: Select all

this._findSubEntity = function(key)
               {
               for (var i = this.ship.owner.subEntities.length - 1 ; i >=0 ; --i)
                  {
                  if (this.ship.owner.subEntities[i].dataKey == key)
                     {
                     return this.ship.owner.subEntities[i];
                     }
                  }
                  return null; // couldn't find it.
               }
then it will search the subentities of the main ship, and should work (assuming you don't later add nested subentities).

While it will still work where it is, it'll also be more efficient to move this definition out of the switch/case statement and indeed out of the shipDied function altogether - where you had it previously was better.
dertien
---- E L I T E ----
---- E L I T E ----
Posts: 471
Joined: Sun Jan 23, 2011 9:27 pm
Location: Belgium, Monarchy, Feudal, Overtaxed system

Re: Scripters cove

Post by dertien »

well, I thought that it would certainly be picked up there, instead of all the way up there, but ok, I will put it back on top, since otherwise I will have to repeat it for each case correct ?

let me see what that does.
Alpha Backer of Elite Dangerous
With 250 GBP :D
dertien
---- E L I T E ----
---- E L I T E ----
Posts: 471
Joined: Sun Jan 23, 2011 9:27 pm
Location: Belgium, Monarchy, Feudal, Overtaxed system

Re: Scripters cove

Post by dertien »

Still nothing :( , the lights are still there
Alpha Backer of Elite Dangerous
With 250 GBP :D
User avatar
cim
Quite Grand Sub-Admiral
Quite Grand Sub-Admiral
Posts: 4072
Joined: Fri Nov 11, 2011 6:19 pm

Re: Scripters cove

Post by cim »

Strange - that looks like it should be working. Could you upload what you've got now somewhere and I'll take a closer look. Maybe the problem is somewhere else in the OXP entirely.
dertien
---- E L I T E ----
---- E L I T E ----
Posts: 471
Joined: Sun Jan 23, 2011 9:27 pm
Location: Belgium, Monarchy, Feudal, Overtaxed system

Re: Scripters cove

Post by dertien »

sure, give me a minute
Alpha Backer of Elite Dangerous
With 250 GBP :D
dertien
---- E L I T E ----
---- E L I T E ----
Posts: 471
Joined: Sun Jan 23, 2011 9:27 pm
Location: Belgium, Monarchy, Feudal, Overtaxed system

Re: Scripters cove

Post by dertien »

Alpha Backer of Elite Dangerous
With 250 GBP :D
User avatar
cim
Quite Grand Sub-Admiral
Quite Grand Sub-Admiral
Posts: 4072
Joined: Fri Nov 11, 2011 6:19 pm

Re: Scripters cove

Post by cim »

A few typos in the script file.
1) When you moved the findSubEntity function, the this._findSubEntity = function(key) line got left behind. That needs to be moved also from line 27 to line 5
2) return this.ship.owner.SubEntities[i]; should be return this.ship.owner.subEntities[i]; - the case matters.
3) var lcblight = this._findSubEntity("HPC_CO3_LCBlights") is missing a ; at the end.
dertien
---- E L I T E ----
---- E L I T E ----
Posts: 471
Joined: Sun Jan 23, 2011 9:27 pm
Location: Belgium, Monarchy, Feudal, Overtaxed system

Re: Scripters cove

Post by dertien »

Yepeeeee, it works Cim, it works :))))))

I feel like a kid with both hands in the candyjar.

thanks.

At least now I can start to take care of the NPC's already

Will probably be back for some more pain, when that is done, so keep the mace ready.

Do you know how I could get rid of the griff cobras without resorting to the line

Code: Select all

"oolite_template_cobra3" =
   {
      like_ship = "HPCcobramk3_sentinel";
   };
Alpha Backer of Elite Dangerous
With 250 GBP :D
User avatar
cim
Quite Grand Sub-Admiral
Quite Grand Sub-Admiral
Posts: 4072
Joined: Fri Nov 11, 2011 6:19 pm

Re: Scripters cove

Post by cim »

So long as you override all the real ships - "cobra3-trader", "cobra3-alternate", "cobra3-player" and "cobra3-pirate" - you shouldn't need to touch the template at all.
dertien
---- E L I T E ----
---- E L I T E ----
Posts: 471
Joined: Sun Jan 23, 2011 9:27 pm
Location: Belgium, Monarchy, Feudal, Overtaxed system

Re: Scripters cove

Post by dertien »

Well' I'm back with my next hurdles

I would like to solve the landing gear up and down problem with about the same code as the one I used on the destroyed subentities; So basically I want to show the landing gear subentities when the docking sequence is going on, or when the ship launches, (which shows the landing rear extended or retracted at its place) and remove them and show them in their retracted state when the ship is not in its docking/undocking sequence.

So what I have to work with is this:

Code: Select all

this.name      = "landing_gear"; 
this.author    = "griff"; 
this.copyright = "� 2008 griff."; 
this.version   = "1.01";


this._findSubEntity = function(key)
					{
					for (var i = this.ship.subEntities.length - 1 ; i >=0 ; --i)
						{
						if (this.ship.subEntities[i].dataKey == key)
							{
							return this.ship.subEntities[i];
							}
						}
						return null; // couldn't find it.
					}

// landing gear is down 					
this.shipLaunchedFromStation = function(station)
{
  if(this.ship.isValid)
    {
	this.ship.commsMessage("Hello world");
	this.ship.dataKey;
	var actuators = this._findSubEntity("HPC_actuatorR"); //make actuator visible during  station launch sequence
					if (actuators)
					{
						actuators.add();
					}
	var reargearextendPRT = this._findSubEntity("HPC_reargearPRT"); 
						if (reargearextendPRT)
					{
					reargearextendPRT.remove();
					}
	var reargearextendSTB = this._findSubEntity("HPC_reargearSTB"); 
						if (reargearextendSTB)
					{
					reargearextendSTB.remove();
					}
	
    }
	else
	var actuators = this._findSubEntity("HPC_actuatorR"); //make actuator visible during  station launch sequence
					if (actuators)
					{
						actuators.remove();
					}
	var reargearextendPRT = this._findSubEntity("HPC_reargearPRT"); // remove subentity "rear gear up PRT"
						if (reargearextendPRT)
					{
					reargearextendPRT.add();
					}
	var reargearextendSTB = this._findSubEntity("HPC_reargearSTB"); // remove subentity "rear gear up PRT" 
						if (reargearextendSTB)
					{
					reargearextendSTB.add();
					}
	
}



// Landing gear is up
this.shipWillDockWithStation = function(station)
{
  if(this.ship.isValid)
    {
	this.ship.commsMessage("Bye for now");
    }
}

The hello world message shows nicely, but the subentities keep eluding me.

Again, missing basic scripting knowledge is holding me back from solving this. The other script is now completely done, and works fine; thank you again Cim.

This script is attached to the ship, and not the subenitities this time, mind you.
Last edited by dertien on Thu Aug 14, 2014 9:19 pm, edited 2 times in total.
Alpha Backer of Elite Dangerous
With 250 GBP :D
dertien
---- E L I T E ----
---- E L I T E ----
Posts: 471
Joined: Sun Jan 23, 2011 9:27 pm
Location: Belgium, Monarchy, Feudal, Overtaxed system

Re: Scripters cove

Post by dertien »

Another question I have is this,

I have 4 different weapon models (nozzles) as subentities, that carry the 4 different weapons.

And they seem to work fine, meaning they fire as they should. So basically, the ship entry has no weapons whatsoever

Code: Select all

forward_weapon_type = "WEAPON_NONE";
but the subentity installed on it has. What I would like to do is to be able to set a lasercolor for every different weapon type.

So Pulselasers red, Beamlasers orange, Mining lasers yellow and Military lasers cyan.
However, when setting up the laser_color in the subentity like this for testing with a different color, the beam still remains red.

Pulselaser subentity example:

Code: Select all

"HPC_pulselaser" = 
	{
			ai_type = "nullAI.plist";
			forward_weapon_type = "WEAPON_PULSE_LASER";
			laser_color = "cyanColor";
			frangible = yes;
			max_energy = 30;
			energy_recharge_rate = 2;
				materials =
				{
				"bbs_global_diffuse.png" =
					{
					diffuse_map = "bbs_global_diffuse.png"; 
					specular_color = ( 0.2, 0.2, 0.2 );
					shininess = 5; 
					emission_map = { name = "bbs_global_diffuse.png"; extract_channel = "a"; }; 
					emission_modulate_color = (0.9926, 0.9686, 0.7325);
					}
				};
			model = "pulselaser.dat"; 
			name = "Cobra Mark III";
			roles = "HPC_pulselaser";
			script = "hpc_subent.js";
			shaders = 
			{ 
				"bbs_global_diffuse.png" = 
				{ 
					vertex_shader = "bbs_normalmap_ships.vertex"; 
					fragment_shader = "bbs_stripes_npcs.fragment"; 
					textures = 
							(
								"bbs_global_diffuse.png", 
								"bbs_global_effects.png"
							);
					uniforms =
							{
								uColorMap = { type = texture; value = 0; };
								uEffectsMap = { type = texture; value = 1; };
								uTime = "universalTime";
								nearly_dead = "throwingSparks";	
								isHostile = "hasHostileTarget";
								hull_heat_level = "hullHeatLevel";
								engine_power = "speedFactor"; 
								laser_heat_level = "laserHeatLevel";							
								PaintColor1 = {type = "randomUnitVector"; scale = 0.8;};
								PaintColor2 = {type = "randomUnitVector"; scale = 0.8;};								
							}; 	
				};	
			};
			smooth = "false";
			weapon_facings = 1;
			weapon_position_forward = "-5.85 -0.16 32.72";
			rotational_velocity = "0.707 0.0 0.0 0.707";
	};
Am I doing something wrong ?
Alpha Backer of Elite Dangerous
With 250 GBP :D
Post Reply