| Back to Index | Page generated: Oct 27, 2025, 5:37:22 AM | 
 Expansion Snark
 Expansion Snark| from Expansion Manager's OXP list | from Expansion Manifest | |
|---|---|---|
| Description | The snark is primarily a slow but powerful fighter, used by escorts, bounty hunters and pirates. For more details, please check the wiki page. | The snark is primarily a slow but powerful fighter, used by escorts, bounty hunters and pirates. For more details, please check the wiki page. | 
| Identifier | oolite.oxp.zzz.Montana05.adck_snark | oolite.oxp.zzz.Montana05.adck_snark | 
| Title | Snark | Snark | 
| Category | Ships | Ships | 
| Author | ADCK, Montana05 | ADCK, Montana05 | 
| Version | 1.11 | 1.11 | 
| Tags | medium fighter | medium fighter | 
| Required Oolite Version | ||
| Maximum Oolite Version | ||
| Required Expansions | ||
| Optional Expansions | ||
| Conflict Expansions | ||
| Information URL | https://wiki.alioth.net/index.php/Snark | n/a | 
| Download URL | https://wiki.alioth.net/img_auth.php/9/95/Oolite.oxp.zzz.Montana05.snark.OXZ | n/a | 
| License | CC BY-NC-SA 4.0 | CC BY-NC-SA 4.0 | 
| File Size | n/a | |
| Upload date | 1658978358 | 
Also read http://wiki.alioth.net/index.php/Snark
The snark is primarily a slow but powerful escort but may turn up as an equally slow (and hence reasonably rare) pirate. She has triple forward beam lasers. You may also see it (ironically enough, given it's name) as a hunter - a role for which she is more than fit, although her lack of cargo space makes unaccompanied hunting a fairly futile exercise for her. This is also the reason I haven't made her into a player ship. If you want to see her straight away, go into the 'AddOns' folder within your main Oolite folder and Either create a subdirectory called Config, or just copy the accompanying Script.plist file into an existing "Config" folder within there. The Snark then appears within scanner range, the next time you exit witchspace (no matter what system you choose). This ship was actually intended as a demonstration of inversion texturing: i.e using a single texture to cover two mirrored objects, and so rreduce memory usage. I had thought this would be difficult, but actually Wings3D makes it trivially easy using the "flip" objects functionality to flip the selected object on, in this case, the x axis. If you dig in the OXP, you'll see there is only one wing texture, but by reverse-mapping it, it serves as the texture for both wings (which are mirror images of each other).
Overview
========
The Snark is primarily a slow but powerful fighter, used by escorts, (ironically enough, given its name) 
bounty hunters and (reasonably rare) pirates. 
While equipped with triple forward lasers the small hull leaves no space for missiles or cargo. 
This is also the reason why no player ship is available. 
History
=======
Originally an experiment of the design department from ADCK Transport Ltd and more a proof of concept than
a design for the market the review of the first prototypes changes the mind of the management. At a time when
mostly single laser mounts were in use the triple forward lasers in a small fighter awoke the interest of
individuals and organizations alike.
Soon the mass-production started and 1,000's of ships were sold. GalCop space police, the Bounty Hunter Guild and
the Space Security Group, all of them ordered the Snark.
Remarks
=======
This ship was actually intended as a demonstration of inversion texturing: i.e using a single texture to cover 
two mirrored objects, and so reduce memory usage. ADCK had thought this would be difficult, but actually 
Wings3D makes it trivially easy using the "flip" objects functionality to flip the selected object on, 
in this case, the x axis. If you dig in the OXP, you'll see there is only one wing texture, but by reverse-mapping it, 
it serves as the texture for both wings (which are mirror images of each other).
Up to V 1.01 a script was included which, every time you exit witchspace, added 2 Snark attackers. Beginning with V 1.10
this script is removed and all ships appear according to their roles only.
At some of the ships the wings could be shot off, resulting in the loss of a laser mount.
Credits
=======
ADCK (author, models, basic textures and basic specifications)
Knotty (model and basic textures of the spacesuit)
Requirements
============
Oolite V 1.88 or higher.
Details
=======
For additional details, please check the wiki-page: https://wiki.alioth.net/index.php/Snark
License
=======
This work is licensed under Creative Commons Attribution Non-Commercial Share Alike 4.0 International (CC BY-NC-SA 4.0).
To view a copy of this license, visit https://creativecommons.org/licenses/by-nc-sa/4.0
Version History
===============
V 1.11 (Montana05, 2022/07/28)
    fixed an issue with flashers on subentities
V 1.10 (Montana05, 2022/07/05)
    converted and overhauled the entire package
    improved the materials and added more textures
    various implementations to adjust to the current standards
V 1.01 (Montana05, 2021/01/27)
    added manifest.plist and shiplibrary.plist
    uploaded the package to the expansion manager
    
V 1.00 (ADCK, 2006/01/26)
    initial release of the Snark OXP
        
                  
        | Path | |
|---|---|
| Scripts/adck_snark.js | this.name			= "adck_snark";
this.author			= "Montana05";
this.description	= "event handler for the ADCK Snark OXP";
this.version		= "1.11";
this.copyright		= "2022 Montana05";
this.licence   		= "CC BY-NC-SA 4.0";
"use strict";
this.shipSpawned = function(ship)
{
	if(ship.dataKey.search(/adck_snark/i) < 0 || ship.hasRole("cargopod") || ship.isSubEntity || ship.isPlayer)
	{
		return;
	}
	else
	{
		var shipType = ship.dataKey;
		var shipRole = ship.primaryRole;
		
		// setup escape pods
		if(ship.hasRole("escape-capsule"))
		{
			let crewName = expandDescription("[nom]");
			let crewDescription = "a fighter pilot";
			let crewRole = "hunter";  // the role is not particular important anymore, all data will be added by the script
			let crewRace = expandDescription("[adck_snark_races_scientific]");  // add a race to the crew members
			let crewRank = "Commander";
			let bhgRank = "Hunter";  // middle rank
			let crewInsurance = this.$getRndInteger(90, 450);
			let crewBounty = 0;
			
			// 1 crew member
			const adck_snark_crew_ranks_array = ["Pilot", "Commander"];
			crewRank = 
			adck_snark_crew_ranks_array[Math.floor(Math.random() * adck_snark_crew_ranks_array.length)];
			
			// ranks for Bounty Hunter Guild taken from Random Hits OXP, all credits to LittleBear
			const adck_snark_bhg_ranks_array = 
			["Outsider", "Recruit", "Vigilante", "Bailiff", "Deputy", "Tracker", "Hunter", "Sheriff", "Provost", "Marshal", "Enforcer", "Executioner", "Judge"];
			bhgRank = 
			adck_snark_bhg_ranks_array[Math.floor(Math.random() * adck_snark_bhg_ranks_array.length)];
			
			switch(shipType) 
			{
				case "adck_snark_escape_suit":
					crewName = ("the " + crewRace + " " + crewRank + " " + expandDescription("[nom]"));
					crewDescription = "a fighter pilot";
					crewRole = "hunter";
					crewInsurance = this.$getRndInteger(90, 450);
					break;
				case "adck_snark_escape_suit_criminal":
					crewName = ("the " + crewRace + " " + expandDescription("[nom]"));
					crewDescription = "a " + expandDescription("[adck_snark_criminals]") +  "wanted by GalCop police";
					crewRole = "pirate";
					crewBounty = crewInsurance + (15 * system.government);  // stable governments pay extra bonus
					crewInsurance = 0;
					break;
				case "adck_snark_escape_suit_pirate":
					crewName = ("the " + crewRace + " " + expandDescription("[adck_snark_pirate_nicknames]") + expandDescription("[nom]"));
					crewDescription = "a " + expandDescription("[adck_snark_criminals]") +  "wanted by GalCop police";
					crewRole = "pirate";
					crewBounty = (crewInsurance * 1.25) + (25 * system.government);  // stable governments pay extra bonus
					crewInsurance = 0;
					break;
					
				case "adck_snark_escape_suit_ssg":
					crewName = ("the " + crewRace + " " + crewRank + " " + expandDescription("[nom]"));
					crewDescription = "a SSG ship crew member";
					crewRole = "hunter";
					crewInsurance = (crewInsurance * 1.25);  // SSG got better insurance conditions
					break;
					
				case "adck_snark_escape_suit_ssg_criminal":
					crewName = ("the " + crewRace + " " + crewRank + " " + expandDescription("[nom]"));
					crewDescription = "a rogue SSG ship crew member";
					crewRole = "pirate";
					crewBounty = (crewInsurance * 1.25) + (15 * system.government);  // stable governments pay extra bonus
					crewInsurance = 0;
					break;
				case "adck_snark_escape_suit_bhg":
					crewName = ("the " + crewRace + " " + bhgRank + " " + expandDescription("[nom]"));
					crewDescription = "a member of the Bounty Hunter Guild";
					crewRole = "hunter";
					crewInsurance = (crewInsurance * 1.10);  // BHG got better insurance conditions
					break;
					
				case "adck_snark_escape_suit_bhg_criminal":
					crewName = ("the " + crewRace + " " + bhgRank + " " + expandDescription("[nom]"));
					crewDescription = "a rogue member of the Bounty Hunter Guild";
					crewRole = "pirate";
					crewBounty = (crewInsurance * 1.10) + (15 * system.government);  // stable governments pay extra bonus
					crewInsurance = 0;
					break;
				case "adck_snark_escape_suit_police":
					const adck_snark_police_ranks_array = ["Space Junior Lieutenant", "Space Lieutenant"];  // 1 crew member
					crewRank = 
					adck_snark_police_ranks_array[Math.floor(Math.random() * adck_snark_police_ranks_array.length)];
					crewName = ("the " + crewRace + " " + crewRank + " " + expandDescription("[nom]"));
					crewDescription = "an officer of GalCop Space Police";
					crewRole = "police";
					crewInsurance = (this.$getRndInteger(90, 450) + (15 * system.government));  // stable governments pay additional reward
					break;
					
				default: 
	
					break;	
			};
			ship.setCrew
			(
				{
					name: crewName,
					short_description: crewDescription,
					role: crewRole,
					species: crewRace,
					insurance: crewInsurance,
					bounty: crewBounty
				}
			);
			// removes individual roles
			ship.primaryRole = "escape-capsule";
		}
		else
		{
			switch(shipRole) 
			{
				case "adck_snark":
				case "adck_snark_ssg":
				
					ship.primaryRole = "escort-medium";
					break;
				case "adck_snark_hunter":
				case "adck_snark_bhg":
				case "adck_snark_ssg_team_01":
				case "adck_snark_bhg_team_01":
					if(ship.primaryRole != "escort")
					{
						ship.primaryRole = "hunter-medium";
					};
					break;
				case "adck_snark_police":
					ship.primaryRole = "police";
					break;
								
				case "adck_snark_pirate":
					ship.primaryRole = "pirate";
					break;
	
				default: 
	
					break;
			};
		};
		
		// if there is an existing script in shipDied time to move it
		ship.script.$adck_snark_shipDied_old = ship.script.shipDied;
		ship.script.shipDied = this.$adck_snark_shipDied;	
	};
};	
this.$adck_snark_shipDied = function $adck_snark_shipDied(whom, why) 
{
	if(this.ship.dataKey.search(/adck_snark/i) < 0 || 
	   this.ship.hasRole("escape-capsule") || this.ship.hasRole("cargopod") || this.ship.isSubEntity || this.ship.isPlayer)
	{
		return;
	}
	else
	{
		this.name = "adck_snark";
		
		let shipType = this.ship.dataKey;
		let shipBounty = this.ship.bounty;
		let shipPos = this.ship.position;
		let criminalCrew = 0;
		let pirateCrew = 0;
		if(shipBounty > 7 && shipBounty < 15)
		{
			criminalCrew = 1;
		};
		if(shipBounty > 14 || this.ship.isPirate)
		{
			pirateCrew = 1;
		};
		switch(shipType) 
		{
			case "adck_snark_ssg":
			case "adck_snark_ssg_team_01":
				if(criminalCrew == 1 || pirateCrew == 1)
				{
					system.addShips("adck_snark_escape_suit_ssg_criminal", 1, shipPos);
				}
				else
				{
					system.addShips("adck_snark_escape_suit_ssg", 1, shipPos);
				};
				break;
			case "adck_snark_bhg":
			case "adck_snark_bhg_team_01":
				
				if(criminalCrew == 1 || pirateCrew == 1)
				{
					system.addShips("adck_snark_escape_suit_bhg_criminal", 1, shipPos);
				}
				else
				{
					system.addShips("adck_snark_escape_suit_bhg", 1, shipPos);
				};
				break;
			
			case "adck_snark_police":
			
				system.addShips("adck_snark_escape_suit_police", 1, shipPos);
				break;
				
			case "adck_snark_pirate":
								
				system.addShips("adck_snark_escape_suit_pirate", 1, shipPos);
				break;
				
			default:
				
				if(criminalCrew == 1)
				{
					system.addShips("adck_snark_escape_suit_criminal", 1, shipPos);
				}
				else if(pirateCrew == 1)
				{
					system.addShips("adck_snark_escape_suit_pirate", 1, shipPos);
				}
				else
				{
					system.addShips("adck_snark_escape_suit", 1, shipPos);
				};
				break;	
		};
	};
	if(this.ship.script.$adck_snark_shipDied_old)
	{
		this.ship.script.$adck_snark_shipDied_old(whom, why);
	};
};
this.$getRndInteger = function(min, max)
{
	return (Math.floor(Math.random() * (max - min + 1) ) + min);
};
 | 
| Scripts/adck_snark_conditions.js | this.name			= "adck_snark_conditions";
this.author			= "Montana05";
this.description	= "condition script for the GalCop Snark";
this.version		= "1.11";
this.copyright		= "2022 Montana05";
this.licence		= "CC BY-NC-SA 4.0";
"use strict";
this.allowSpawnShip = function(shipKey)
{
	var systemGov = system.government;
	
	// only undeveloped systems
	if(system.isInterstellarSpace || system.sun.isGoingNova || system.sun.hasGoneNova || system.techLevel > 6)
	{ 
		return false;
	};
	// Dictators OXP and Commies OXP got their own police force
	if((systemGov == 3 && worldScripts["dictators.js"]) || (systemGov == 4 && worldScripts["communist_population"]))
	{
		return false;
	};
	
	// otherwise available
	return true;
}; | 
| Scripts/adck_snark_subent.js | this.name			= "adck_snark_subent";
this.author			= "Montana05";
this.description	= "handling of subentities for the Snark";
this.version		= "1.11";
this.copyright		= "2022 Montana05";
this.licence   		= "CC BY-NC-SA 4.0";
"use strict";
this.shipDied = function () 
{ 
    this.ship.owner.commsMessage("We are taking damage, one of our lasers is down !");
}; |