Back to Index Page generated: Dec 1, 2024, 3:15:25 AM

Expansion NeoCaduceus

Content

Manifest

from Expansion Manager's OXP list from Expansion Manifest
Description The very expensive (and deadly) Caduceus The very expensive (and deadly) Caduceus
Identifier oolite.oxp.ClymAngus.NeoCaduceus oolite.oxp.ClymAngus.NeoCaduceus
Title NeoCaduceus NeoCaduceus
Category Ships Ships
Author ClymAngus ClymAngus
Version 1.01 1.01
Tags
Required Oolite Version
Maximum Oolite Version
Required Expansions
Optional Expansions
Conflict Expansions
Information URL http://wiki.alioth.net/index.php/Caduceus n/a
Download URL https://wiki.alioth.net/img_auth.php/4/4e/NeoCaduceus.oxz n/a
License CC-BY-NC-SA 4.0 CC-BY-NC-SA 4.0
File Size n/a
Upload date 1626940523

Documentation

Also read http://wiki.alioth.net/index.php/NeoCaduceus

readme.txt

Overview 
"Piss one of those things off the last thing your going to see is a sea of plasma green" Sector chief besieged navy sector station 4-994. 

There are many rare things in the 8 galaxies, the natural phenomena and then the sentient made from monuments to orbital grave yards. There are one or two oddities that fall into both categories, the Caduceus being one of them. 

It is believed (according to several well read yet unofficial dossiers) that the Caduceus was the brain child of Udian Foraga Shulth, the youngest (and arguably most talented) son of the bio-maniac Mirias Shulth. Whilst several thousand books, personal testimonies, holo-recordings and overly sentimental documentaries have been penned as to the exploits of his father. Little is known about the informative years of Udian (most official records having been lost in the first great shard bio-purge). He does surface as a young adult embroiled in the new genesis war as something of an unlikely hero. Saving several sub-core trading systems from the gene-menace through the unlikely unification of celltec and nano-mechanics. 

One of the few quotes directly attributable to Udian is also probably the most telling: "I don't build ships, I birth them. They are my children and like any good father I watch over them." Indeed most traders, pirates (who survive) or military personnel who happen to see a Caduceus, concur that there is something distinctly biological about its construction. They tend to be encountered cross station side of industrial planets, dropping in and out of the atmosphere delivering god knows what, to god knows where, for god knows who. 

Few cast iron facts are known about these ships capabilities outside military circles, although this hasn't stopped the intergalactic rumor mill from churning, fueled by chance encounters and the odd station landing. Whilst sifting through this mass of conjecture, has been likened to digging through boobian bug guts looking for a nega-mass gem stone, certain "facts" appear more widely independently replicated and therefore believable. 

Notable features 
It would appear that these ships tend to be above average in most respects, lower top end in most categories. A speed 0.5 shy of half light, quickish turning circles, pitch and yaw, good shields and an apparent ability (as reported by station engineers) to successfully utilize a patch work quilt of non standard upgrades. So far 10 separate ships have been documented; 

Arc Of Radiance 
Apex Of Reason 
Shard Of Destiny 
Point Of Action (destroyed) 
Edge Of Infinity 
Circle Of Time 
Crucible Of Destruction 
Vortex Of Hate 
Annulus Of Deceit 
Digon Of Truth 

Leaked military records recently reported at least one Caduceus has been confirmed destroyed (see above). This event occurred several cycles ago during a fierce Thargoid insurgency. It appears that the battle not only engaged the military, but also many reservists and privateers who were caught in the cross fire. Details are sketchy (the documents are heavily censored) but the battle appears to have taken place some where along the outer edge of galaxy 4. The ship in question seems to have purposefully maneuvered in between several invading warships then proceeded to deliver a barrage of devastating broadsides, to both ships simultaneously. A tactic repeated several times until it was eventually overwhelmed by robot fighters. Although not pivotal to the subsequent rout of the invading fleet, the Caduceus's actions "significantly influenced the tempo of the battle" (Vice Admiral Mineemer). 

Controversy 
The real eye opener for the military was the subsequent annihilation of the remaining Thargoid ships involved in the conflict 5 days later, and the complete sterilization of all Thargoid held worlds within a 15 light year radius of the fleet. This count included two heavily defended system hatcheries. 

Dispatches from Naval HQ indicates it is involved in "sporadic but ongoing negotiations" with the Shulth family regarding the acquisition of hyper-biomechancial ship building technology and any other advanced tech which may help secure victory in the on-going war. It is extremely rare to find one of these ships not in the hands of a Shulth or one of their associates. Still these ships occasionally appear for sale, always stripped down and curiously enough never in the hands of pirates. 

Given the multi-generational reputation of its pilots and masters, the mere reporting of a Caduceus in system has been known to empty orbit stations soft-bars of pirate informants, hackers and one shot cargo ejectors. Oh and if you see a ship bay on station that appears to be empty but the dock manifest indicates it's paid for three times over, best not try and park in it eh? 

Stats: 
Speed - .400LS
Thrust - 45
Pitch/Yaw - 0.8
Roll - 1.8
Energy - 8 banks (512)
Recharge - 5.8


Alpha:
The Alpha trades side laser mounts and top/bottom heavy turrets for cargo 
space.
Cargo - 25
Expanded - 40
Missiles - 8

Omega:
The Omega trades cargo space for the heavy turrets and side lasers. 
Cargo - 20
Expanded - 30
Missiles - 10

The Caduceus also contains a certain piece of specialized kit the Damage Control Node.
Based off Thargoid's repair bot mines, the Damage Control Node is a nanoforge that interfaces with the Caddy's AI and biosystems, and assists the crew in inflight repairs, manufacturing replacement components as they're needed.
The DCN manages repairs slowly over time, repairing more equipment than the 
Repair Mine, and often with a better chance of success. Yet it doesn't always repair a piece of kit the first time it tries, and sometimes takes two or more tries to repair a device. The AI will tell you if they fail to fix a device. Nor can it repair every piece of kit on the market, though most common devices and some rare ones are within it's capabilities.
And if the DCN gets damaged? Repairs are halted if the DCN takes a hit, but it heals itself! Priority is given to healing a damaged DCN, and healing a DCN happens fairly quickly. Repairs resume soon after the DCN heals.

Acknowledgments 
Cmdr Wyvern for helping fix my broken ass code.
another_commander for helping fix my broken ass shader code 
Eric Walch from pointing out how to trouble shoot code so I don't end up accidentally publishing another beta.

Equipment

Name Visible Cost [deci-credits] Tech-Level
Damage Control Node yes 70000 1+

Ships

Name
caduceus-alpha
Caduceus Alpha
caduceus-omega
Caduceus Omega
caduceusturret
Caduceus Turret
Caduceus Engine
Caduceus Engine
Caduceus mount
zeroturret
Zero Turret

Models

This expansion declares no models.

Scripts

Path
Config/script.js
"use strict";
this.name = "Caduceus Damage Control Node";
this.author = "Thargoid";
this.copyright = "Creative Commons Attribution - Non-Commercial - Share Alike 3.0 license";
this.description = "Damage Control system based on repair bots";
this.version = "2.0";

this.equipmentDamaged = function (equipment) {
	if (player.ship.equipmentStatus("EQ_DCN") == "EQUIPMENT_UNAVAILABLE") {
		return;
	}

	if (equipment == "EQ_DCN") {
		if (this.damageControlTimer && this.damageControlTimer.isRunning) {
			this.damageControlTimer.stop();
			delete this.damageControlTimer;
		}
		var repairTime = 60 + Math.ceil(Math.random() * 120);
		player.consoleMessage("DCN offline - entering self-repair mode", 6);
		this.selfRepairTimer = new Timer(this, this.selfRepair, repairTime);
	} else {
		if (!this.damageControlTimer || !this.damageControlTimer.isRunning) {
			var repairTime = 120 + Math.ceil(Math.random() * 180);
			player.consoleMessage("DCN activated", 6);
			this.damageControlTimer = new Timer(this, this.repairSystems, repairTime);
		}
	}
}

this.selfRepair = function () {
	if (player.ship.equipmentStatus("EQ_DCN") == "EQUIPMENT_UNAVAILABLE") {
		return;
	}

	if (Math.random() < 0.75) // 75% chance of self-repair
	{
		player.ship.setEquipmentStatus("EQ_DCN", "EQUIPMENT_OK");
		this.checkSystems();
		if (this.playerDamagedList.length > 0) {
			player.consoleMessage("DCN online and activated", 6);
			var repairTime = 120 + Math.ceil(Math.random() * 180);
			this.damageControlTimer = new Timer(this, this.repairSystems, repairTime);
		} else {
			player.consoleMessage("DCN online and in standby mode", 6);
		}
	} else {
		if (player.ship.equipmentStatus("EQ_DCN") == "EQUIPMENT_DAMAGED") // just in case it was repaired in the meantime
		{
			var repairTime = 60 + Math.ceil(Math.random() * 120);
			player.consoleMessage("DCN offline - self-repair continuing", 6);
			this.selfRepairTimer = new Timer(this, this.selfRepair, repairTime);
		}
	}
}

this.equipmentDestroyed = function (equipment) {
	if (equipment == "EQ_DCN") {
		this.stopTimers();
	}
}

this.stopTimers = this.shipWillDockWithStation = this.shipDied = function () {
	if (this.damageControlTimer && this.damageControlTimer.isRunning) {
		this.damageControlTimer.stop();
		delete this.damageControlTimer;
	}
	if (this.selfRepairTimer && this.selfRepairTimer.isRunning) {
		player.ship.setEquipmentStatus("EQ_DCN", "EQUIPMENT_OK");
		this.selfRepairTimer.stop();
		delete this.selfRepairTimer;
	}
}

this.shipWillLaunchFromStation = function () {
	if (player.ship.equipmentStatus("EQ_DCN") == "EQUIPMENT_OK") {
		this.checkSystems();
		if (this.playerDamagedList.length > 0) {
			var repairTime = 120 + Math.ceil(Math.random() * 180);
			player.consoleMessage("Repair system reactivated", 6);
			this.damageControlTimer = new Timer(this, this.repairSystems, repairTime);
		}
	} else {
		if (player.ship.equipmentStatus("EQ_DCN") == "EQUIPMENT_DAMAGED") {
			this.selfRepair();
			return;
		}
	}
}

this.checkSystems = function () //new, faster one from http://aegidian.org/bb/viewtopic.php?f=4&t=10842&start=30#p163024
{
	this.playerDamagedList = [];
	var equipment = player.ship.equipment
	var listCounter = 0; // reset the counter
	for (listCounter = 0; listCounter < equipment.length; listCounter++) {
		if (player.ship.equipmentStatus(equipment[listCounter].equipmentKey) !== "EQUIPMENT_DAMAGED") {
			continue
		}
		var scriptEqInfo = EquipmentInfo.infoForKey(equipment[listCounter].equipmentKey).scriptInfo;
		if ((scriptEqInfo.thargoidRepairBotChance === undefined ||
				isNaN(scriptEqInfo.thargoidRepairBotChance)) ||
			(!isNaN(scriptEqInfo.thargoidRepairBotChance) &&
				scriptEqInfo.thargoidRepairBotChance > 0)) {
			this.playerDamagedList.push(equipment[listCounter].equipmentKey); // if it's broke and fixable, add it to the list.
		}
	}
}

this.repairSystems = function () {
	this.checkSystems();
	if (this.playerDamagedList.length == 0) {
		player.consoleMessage("All systems nominal - DCN entering standby mode", 5);
		return;
	} else {
		var damagedEquipment = Math.floor(Math.random() * this.playerDamagedList.length); // pick a random element from the list...
		this.fixedItem = this.playerDamagedList[damagedEquipment]; // ...define the item...
		this.damagedItem = this.fixedItem + "_DAMAGED"; //...and it's damaged version
		this.fixedName = EquipmentInfo.infoForKey(this.fixedItem).name; // define it's screen name
		this.fixedTech = EquipmentInfo.infoForKey(this.fixedItem).effectiveTechLevel // tech level of the item
		if (EquipmentInfo.infoForKey(this.fixedItem).scriptInfo.thargoidRepairBotChance !== undefined && !isNaN(EquipmentInfo.infoForKey(this.fixedItem).scriptInfo.thargoidRepairBotChance)) {
			this.fixChance = EquipmentInfo.infoForKey(this.fixedItem).scriptInfo.thargoidRepairBotChance;
		} else {
			this.fixChance = 0.6;
		}
	}

	if (Math.random() < this.fixChance) {
		this.fixItem();
	} else {
		var repairTime = 120 + Math.ceil(Math.random() * 180);
		player.consoleMessage(this.fixedName + " is still offline - work continuing.", 5);
		this.damageControlTimer = new Timer(this, this.repairSystems, repairTime);
	}
}


this.fixItem = function () {
	player.ship.setEquipmentStatus(this.fixedItem, "EQUIPMENT_OK"); // and actually fix the thing!
	player.consoleMessage(this.fixedName + " regenerated and operational", 5)
	switch (this.fixedItem) // specific OXP equipment which need rebooting after fixing, or have other issues.
	{
		case "EQ_FRAME_FUEL_COLLECTOR": {
			if (worldScripts["Fuel Collector"]) {
				worldScripts["Fuel Collector"].shipLaunchedFromStation(); // restart the timers in it's world script
				break;
			}
		}
		case "EQ_FRAME_BOUNTY_SCANNER": {
			if (worldScripts["Bounty Scanner"]) {
				worldScripts["Bounty Scanner"].shipLaunchedFromStation(); // restart the timers in it's world script
				break;
			}
		}
		case "EQ_EEU": {
			if (worldScripts["Emergency Energy Unit"]) {
				worldScripts["Emergency Energy Unit"].shipLaunchedFromStation(); // restart the timers in it's world script
				break;
			}
		}
		case "EQ_ROCKHERMIT_SCANNER": {
			if (worldScripts["rockHermit_Locator"]) {
				if (worldScripts["rockHermit_Locator"].version == "1.2.3") {
					worldScripts["rockHermit_Locator"].shipLaunchedFromStation() // use the inbuild scripting of the OXP to restart it.
				} else {
					this.beacons = system.shipsWithPrimaryRole("rockbeacof"); // list the inactive beacons (no lights or "R" on compass) 
					if (this.beacons.length > 0) {
						for (let i = 0; i < this.beacons.length; i++) {
							if (oolite.compareVersion('1.73') <= 0) {
								this.beacons[i].position = this.beacons[i].position.multiply(100); //throw the rockbeacof into space... 
							} else {
								this.beacons[i].setPosition(this.beacons[i].position.multiply(100)); //throw the rockbeacof into space... 
							}

							this.beacons[i].explode(); //...and blow it up. 
						}
					}
					worldScripts["rockHermit_Locator"].buoy = "rockbeacon"
					worldScripts["rockHermit_Locator"].addBuoys() // no inactive beacons, so use original code to add active beacons. 
				}
				break;
			}
		}
	}
	if (this.playerDamagedList.length > 1) {
		var repairTime = 120 + Math.ceil(Math.random() * 180);
		player.consoleMessage("Repairs ongoing", 6);
		this.damageControlTimer = new Timer(this, this.repairSystems, repairTime);
	}

}
Scripts/neocaduceus_conditions.js
"use strict";
this.name        = "NeoCaduceus_Conditions";
this.author      = "phkb";
this.copyright   = "2021 phkb";
this.description = "Condition script for ships";
this.licence     = "CC BY-NC-SA 3.0";

//-------------------------------------------------------------------------------------------------------------
this.allowSpawnShip = function(shipKey) {
    if (system.government > 3 && system.techLevel > 7) return true;
    return false;
}

//-------------------------------------------------------------------------------------------------------------
this.allowAwardEquipment = function(equipment, ship, context) {
    if (context === "scripted") return true;
    return false;
}