1-- Name: Chaos of War
2-- Description: Two, three or four species battle for ultimate dominion. Designed as a replayable player versus player (PVP) scenario for individuals or teams. Terrain is randomly symmetrically generated for every game. Use GM screen to adjust parameters
3---
4--- Version 1 (debuted 23Jan2021 for online event)
5-- Type: Player vs Player with or without teams
6-- Variation[Easy]: More resources, services and reputation
7-- Variation[Hard]: Fewer resources, services and reputation
8
9--------------------------------------------------------------------------------------------------------
10--	Note: This script requires a version of supply_drop.lua that handles the variable jump_freighter  --
11--			See pull request 1185                                                                     --
12--------------------------------------------------------------------------------------------------------
13
14require "utils.lua"
15
16function init()
17	scenario_version = "1.0.1"
18	print(string.format("Scenario version %s",scenario_version))
19	print(_VERSION)
20	setVariations()
21	setConstants()
22	setStaticScienceDatabase()
23	setGMButtons()
24end
25function setVariations()
26	local svs = getScenarioVariation()	--scenario variation string
27	if string.find(svs,"Easy") then
28		difficulty = .5
29		base_reputation = 50
30	elseif string.find(svs,"Hard") then
31		difficulty = 2
32		base_reputation = 10
33	else
34		difficulty = 1		--default (normal)
35		base_reputation = 20
36	end
37end
38function setConstants()
39	thresh = .2		--leading/trailing completion threshold percentage for game
40	game_time_limit = 45*60	-- Time limit for game; measured in seconds (example: 45*60 = 45 minutes)
41	max_game_time = game_time_limit
42	game_state = "paused"	--then moves to "terrain generated" then to "running"
43	respawn_count = 0
44	respawn_type = "lindworm"
45	storage = getScriptStorage()
46	storage.gatherStats = gatherStats
47	player_team_count = 2	--default to 2. Can be 2, 3 or 4
48	ships_per_team = 2		--default to 2. Max varies based on team count
49	max_ships_per_team = {32,16,10,8}	--engine supports 32 player ships
50	f2s = {	--faction name to short name
51		["Human Navy"] = "human",
52		["Kraylor"] = "kraylor",
53		["Exuari"] = "exuari",
54		["Ktlitans"] = "ktlitan",
55	}
56	terrain_generated = false
57	generate_terrain_message_counter = 0
58	missile_availability = "unlimited"
59	defense_platform_count_index = 10
60	defense_platform_count_options = {
61		{count = 0, distance = 0,		player = 4500},
62		{count = 3, distance = 2000,	player = 2500},
63		{count = 4, distance = 2400,	player = 3000},
64		{count = 5, distance = 3000,	player = 3500},
65		{count = 6, distance = 4300,	player = 2500},
66		{count = 8, distance = 7000,	player = 4000},
67		{count = 9, distance = 7800,	player = 4500},
68		{count = 10, distance = 9000,	player = 4000},
69		{count = 12, distance = 10000,	player = 4500},
70		{count = "random", distance = 0,	player = 0},
71	}
72	dp_comms_data = {	--defense platform comms data
73		weapon_available = 	{
74			Homing =			random(1,13)<=(3-difficulty),
75			HVLI =				random(1,13)<=(6-difficulty),
76			Mine =				false,
77			Nuke =				false,
78			EMP =				false,
79		},
80		services = {
81			supplydrop = "friend",
82			reinforcements = "friend",
83			jumpsupplydrop = "friend",
84		},
85		service_cost = {
86			supplydrop =		math.random(80,120),
87			reinforcements =	math.random(125,175),
88			jumpsupplydrop =	math.random(110,140),
89		},
90        jump_overcharge =		false,
91        probe_launch_repair =	random(1,13)<=(3-difficulty),
92        hack_repair =			random(1,13)<=(3-difficulty),
93        scan_repair =			random(1,13)<=(3-difficulty),
94        combat_maneuver_repair=	random(1,13)<=(3-difficulty),
95        self_destruct_repair =	random(1,13)<=(3-difficulty),
96        tube_slow_down_repair =	random(1,13)<=(3-difficulty),
97		reputation_cost_multipliers = {
98			friend = 			1.0,
99			neutral = 			3.0,
100		},
101		goods = {},
102		trade = {},
103	}
104	defense_fleet_list = {
105		["Small Station"] = {
106			{DF1 = "MT52 Hornet",DF2 = "MU52 Hornet",DF3 = "MT52 Hornet",DF4 = "MU52 Hornet",},
107			{DF1 = "MT52 Hornet",DF2 = "MT52 Hornet",DF3 = "MT52 Hornet",DF4 = "MU52 Hornet",},
108			{DF1 = "MT52 Hornet",DF2 = "MU52 Hornet",DF3 = "MU52 Hornet",DF4 = "Nirvana R5A",},
109    	},
110		["Medium Station"] = {
111			{DF1 = "Adder MK5",DF2 = "MU52 Hornet",DF3 = "MT52 Hornet",DF4 = "Adder MK4",DF5 = "Adder MK6",},
112			{DF1 = "Adder MK5",DF2 = "MU52 Hornet",DF3 = "Nirvana R5A",DF4 = "Adder MK4",DF5 = "Adder MK6",},
113			{DF1 = "Adder MK5",DF2 = "MU52 Hornet",DF3 = "Nirvana R5A",DF4 = "WX-Lindworm",DF5 = "Adder MK6",},
114		},
115		["Large Station"] = {
116			{DF1 = "Adder MK5",DF2 = "MU52 Hornet",DF3 = "MT52 Hornet",DF4 = "Adder MK4",DF5 = "Adder MK6",DF6 = "Phobos T3",DF7 = "Adder MK7",DF8 = "Adder MK8",},
117			{DF1 = "Adder MK5",DF2 = "MU52 Hornet",DF3 = "Adder MK9",DF4 = "Adder MK4",DF5 = "Adder MK6",DF6 = "Phobos T3",DF7 = "Adder MK7",DF8 = "Adder MK8",},
118			{DF1 = "Adder MK5",DF2 = "MU52 Hornet",DF3 = "Nirvana R5A",DF4 = "Adder MK4",DF5 = "Adder MK6",DF6 = "Phobos T3",DF7 = "Adder MK7",DF8 = "Adder MK8",},
119		},
120		["Huge Station"] = {
121			{DF1 = "Adder MK5",DF2 = "MU52 Hornet",DF3 = "MT52 Hornet",DF4 = "Adder MK4",DF5 = "Adder MK6",DF6 = "Phobos T3",DF7 = "Adder MK7",DF8 = "Adder MK8",DF9 = "Fiend G4",DF10 = "Stalker R7",DF11 = "Stalker Q7"},
122			{DF1 = "Adder MK5",DF2 = "MU52 Hornet",DF3 = "Nirvana R5A",DF4 = "Adder MK4",DF5 = "Adder MK6",DF6 = "Phobos T3",DF7 = "Adder MK7",DF8 = "Adder MK8",DF9 = "Fiend G4",DF10 = "Stalker R7",DF11 = "Stalker Q7"},
123			{DF1 = "Adder MK5",DF2 = "MU52 Hornet",DF3 = "Phobos T3",DF4 = "Adder MK4",DF5 = "Adder MK6",DF6 = "Phobos T3",DF7 = "Adder MK7",DF8 = "Adder MK8",DF9 = "Fiend G4",DF10 = "Stalker R7",DF11 = "Stalker Q7"},
124		},
125	}
126	station_list = {}
127	station_sensor_range = 20000
128	primary_station_size_index = 1
129	primary_station_size_options = {"random","Small Station","Medium Station","Large Station","Huge Station"}
130	primary_jammers = "random"
131	player_ship_types = "default"
132	custom_player_ship_type = "Heavy"
133	default_player_ship_sets = {
134		{"Crucible"},
135		{"Maverick","Flavia P.Falcon"},
136		{"Atlantis","Phobos M3P","Crucible"},
137		{"Atlantis","Maverick","Phobos M3P","Flavia P.Falcon"},
138		{"Atlantis","Player Cruiser","Maverick","Crucible","Phobos M3P"},
139		{"Atlantis","Hathcock","Flavia P.Falcon","Player Missile Cr.","Maverick","Phobos M3P"},
140		{"Atlantis","Repulse","Maverick","Player Missile Cr.","Phobos M3P","Flavia P.Falcon","Crucible"},
141		{"Atlantis","Player Cruiser","Hathcock","Player Fighter","Phobos M3P","Maverick","Crucible","Flavia P.Falcon"},
142		{"Atlantis","Player Cruiser","Repulse","Player Missile Cr.","Player Fighter","Phobos M3P","Crucible","Flavia P.Falcon","Maverick"},
143		{"Atlantis","Player Cruiser","Piranha","Player Missile Cr.","Player Fighter","Phobos M3P","Crucible","Flavia P.Falcon","Maverick","Phobos M3P"},
144		{"Atlantis","Player Cruiser","Hathcock","Repulse","Player Fighter","Player Missile Cr.","Crucible","Flavia P.Falcon","Maverick","Phobos M3P","Flavia P.Falcon"},
145		{"Atlantis","Player Cruiser","Piranha","Repulse","Player Fighter","Player Missile Cr.","Crucible","Flavia P.Falcon","Maverick","Phobos M3P","Flavia P.Falcon","Phobos M3P"},
146		{"Atlantis","Player Cruiser","Piranha","Hathcock","Player Fighter","Player Missile Cr.","Crucible","Flavia P.Falcon","Maverick","Phobos M3P","Flavia P.Falcon","Phobos M3P","Crucible"},
147		{"Atlantis","Player Cruiser","Hathcock","Repulse","Piranha","Player Missile Cr.","Crucible","Flavia P.Falcon","Maverick","Phobos M3P","Flavia P.Falcon","Phobos M3P","Crucible","Player Fighter"},
148		{"Atlantis","Player Cruiser","Hathcock","Repulse","Nautilus","Player Missile Cr.","Crucible","Flavia P.Falcon","Maverick","Phobos M3P","Flavia P.Falcon","Phobos M3P","Crucible","Player Fighter","MP52 Hornet"},
149		{"Atlantis","Player Cruiser","Nautilus","Repulse","Piranha","Player Missile Cr.","Crucible","Flavia P.Falcon","Maverick","Phobos M3P","Flavia P.Falcon","Phobos M3P","Crucible","Player Fighter","MP52 Hornet","Maverick"},
150	}
151	custom_player_ship_sets = {
152		["Jump"] = {
153			{"Atlantis"},
154			{"Atlantis","Player Cruiser"},
155			{"Atlantis","Player Cruiser","Hathcock"},
156			{"Atlantis","Player Cruiser","Hathcock","Repulse"},
157			{"Atlantis","Player Cruiser","Hathcock","Repulse","Piranha"},
158			{"Atlantis","Player Cruiser","Hathcock","Repulse","Piranha","Nautilus"},
159			{"Atlantis","Player Cruiser","Hathcock","Repulse","Piranha","Nautilus","Repulse"},
160			{"Atlantis","Player Cruiser","Hathcock","Repulse","Piranha","Nautilus","Repulse","Player Cruiser"},
161			{"Atlantis","Player Cruiser","Hathcock","Repulse","Piranha","Nautilus","Repulse","Player Cruiser","Piranha"},
162			{"Atlantis","Player Cruiser","Hathcock","Repulse","Piranha","Nautilus","Repulse","Player Cruiser","Piranha","Atlantis"},
163			{"Atlantis","Player Cruiser","Hathcock","Repulse","Piranha","Nautilus","Repulse","Player Cruiser","Piranha","Atlantis","Nautilus"},
164			{"Atlantis","Player Cruiser","Hathcock","Repulse","Piranha","Nautilus","Repulse","Player Cruiser","Piranha","Atlantis","Nautilus","Hathcock"},
165			{"Atlantis","Player Cruiser","Hathcock","Repulse","Piranha","Nautilus","Repulse","Player Cruiser","Piranha","Atlantis","Nautilus","Hathcock","Atlantis"},
166			{"Atlantis","Player Cruiser","Hathcock","Repulse","Piranha","Nautilus","Repulse","Player Cruiser","Piranha","Atlantis","Nautilus","Hathcock","Atlantis","Player Cruiser"},
167			{"Atlantis","Player Cruiser","Hathcock","Repulse","Piranha","Nautilus","Repulse","Player Cruiser","Piranha","Atlantis","Nautilus","Hathcock","Atlantis","Player Cruiser","Piranha"},
168			{"Atlantis","Player Cruiser","Hathcock","Repulse","Piranha","Nautilus","Repulse","Player Cruiser","Piranha","Atlantis","Nautilus","Hathcock","Atlantis","Player Cruiser","Piranha","Hathcock"},
169		},
170		["Warp"] = {
171			{"Crucible"},
172			{"Crucible","Maverick"},
173			{"Crucible","Maverick","Phobos M3P"},
174			{"Crucible","Maverick","Phobos M3P","Flavia P.Falcon"},
175			{"Crucible","Maverick","Phobos M3P","Flavia P.Falcon","MP52 Hornet"},
176			{"Crucible","Maverick","Phobos M3P","Flavia P.Falcon","MP52 Hornet","Player Missile Cr."},
177			{"Crucible","Maverick","Phobos M3P","Flavia P.Falcon","MP52 Hornet","Player Missile Cr.","Maverick"},
178			{"Crucible","Maverick","Phobos M3P","Flavia P.Falcon","MP52 Hornet","Player Missile Cr.","Maverick","Phobos M3P"},
179			{"Crucible","Maverick","Phobos M3P","Flavia P.Falcon","MP52 Hornet","Player Missile Cr.","Maverick","Phobos M3P","Crucible"},
180			{"Crucible","Maverick","Phobos M3P","Flavia P.Falcon","MP52 Hornet","Player Missile Cr.","Maverick","Phobos M3P","Crucible","MP52 Hornet"},
181			{"Crucible","Maverick","Phobos M3P","Flavia P.Falcon","MP52 Hornet","Player Missile Cr.","Maverick","Phobos M3P","Crucible","MP52 Hornet","Player Missile Cr."},
182			{"Crucible","Maverick","Phobos M3P","Flavia P.Falcon","MP52 Hornet","Player Missile Cr.","Maverick","Phobos M3P","Crucible","MP52 Hornet","Player Missile Cr.","Flavia P.Falcon"},
183			{"Crucible","Maverick","Phobos M3P","Flavia P.Falcon","MP52 Hornet","Player Missile Cr.","Maverick","Phobos M3P","Crucible","MP52 Hornet","Player Missile Cr.","Flavia P.Falcon","Player Missile Cr."},
184			{"Crucible","Maverick","Phobos M3P","Flavia P.Falcon","MP52 Hornet","Player Missile Cr.","Maverick","Phobos M3P","Crucible","MP52 Hornet","Player Missile Cr.","Flavia P.Falcon","Player Missile Cr.","Maverick"},
185			{"Crucible","Maverick","Phobos M3P","Flavia P.Falcon","MP52 Hornet","Player Missile Cr.","Maverick","Phobos M3P","Crucible","MP52 Hornet","Player Missile Cr.","Flavia P.Falcon","Player Missile Cr.","Maverick","Crucible"},
186			{"Crucible","Maverick","Phobos M3P","Flavia P.Falcon","MP52 Hornet","Player Missile Cr.","Maverick","Phobos M3P","Crucible","MP52 Hornet","Player Missile Cr.","Flavia P.Falcon","Player Missile Cr.","Maverick","Crucible","Phobos M3P"},
187		},
188		["Heavy"] = {
189			{"Maverick"},
190			{"Maverick","Crucible"},
191			{"Maverick","Crucible","Atlantis"},
192			{"Maverick","Crucible","Atlantis","Player Missile Cr."},
193			{"Maverick","Crucible","Atlantis","Player Missile Cr.","Player Cruiser"},
194			{"Maverick","Crucible","Atlantis","Player Missile Cr.","Player Cruiser","Piranha"},
195			{"Maverick","Crucible","Atlantis","Player Missile Cr.","Player Cruiser","Piranha","Maverick"},
196			{"Maverick","Crucible","Atlantis","Player Missile Cr.","Player Cruiser","Piranha","Maverick","Player Missile Cr."},
197			{"Maverick","Crucible","Atlantis","Player Missile Cr.","Player Cruiser","Piranha","Maverick","Player Missile Cr.","Atlantis"},
198			{"Maverick","Crucible","Atlantis","Player Missile Cr.","Player Cruiser","Piranha","Maverick","Player Missile Cr.","Atlantis","Crucible"},
199			{"Maverick","Crucible","Atlantis","Player Missile Cr.","Player Cruiser","Piranha","Maverick","Player Missile Cr.","Atlantis","Crucible","Player Cruiser"},
200			{"Maverick","Crucible","Atlantis","Player Missile Cr.","Player Cruiser","Piranha","Maverick","Player Missile Cr.","Atlantis","Crucible","Player Cruiser","Piranha"},
201			{"Maverick","Crucible","Atlantis","Player Missile Cr.","Player Cruiser","Piranha","Maverick","Player Missile Cr.","Atlantis","Crucible","Player Cruiser","Piranha","Crucible"},
202			{"Maverick","Crucible","Atlantis","Player Missile Cr.","Player Cruiser","Piranha","Maverick","Player Missile Cr.","Atlantis","Crucible","Player Cruiser","Piranha","Crucible","Atlantis"},
203			{"Maverick","Crucible","Atlantis","Player Missile Cr.","Player Cruiser","Piranha","Maverick","Player Missile Cr.","Atlantis","Crucible","Player Cruiser","Piranha","Crucible","Atlantis","Maverick"},
204			{"Maverick","Crucible","Atlantis","Player Missile Cr.","Player Cruiser","Piranha","Maverick","Player Missile Cr.","Atlantis","Crucible","Player Cruiser","Piranha","Crucible","Atlantis","Maverick","Player Missile Cr."},
205		},
206		["Light"] = {
207			{"Phobos M3P"},
208			{"Phobos M3P","MP52 Hornet"},
209			{"Phobos M3P","MP52 Hornet","Flavia P.Falcon"},
210			{"Phobos M3P","MP52 Hornet","Flavia P.Falcon","Hathcock"},
211			{"Phobos M3P","MP52 Hornet","Flavia P.Falcon","Hathcock","Nautilus"},
212			{"Phobos M3P","MP52 Hornet","Flavia P.Falcon","Hathcock","Nautilus","Repulse"},
213			{"Phobos M3P","MP52 Hornet","Flavia P.Falcon","Hathcock","Nautilus","Repulse","Flavia P. Falcon"},
214			{"Phobos M3P","MP52 Hornet","Flavia P.Falcon","Hathcock","Nautilus","Repulse","Flavia P. Falcon","MP52 Hornet"},
215			{"Phobos M3P","MP52 Hornet","Flavia P.Falcon","Hathcock","Nautilus","Repulse","Flavia P. Falcon","MP52 Hornet","Phobos M3P"},
216			{"Phobos M3P","MP52 Hornet","Flavia P.Falcon","Hathcock","Nautilus","Repulse","Flavia P. Falcon","MP52 Hornet","Phobos M3P","Repulse"},
217			{"Phobos M3P","MP52 Hornet","Flavia P.Falcon","Hathcock","Nautilus","Repulse","Flavia P. Falcon","MP52 Hornet","Phobos M3P","Repulse","Hathcock"},
218			{"Phobos M3P","MP52 Hornet","Flavia P.Falcon","Hathcock","Nautilus","Repulse","Flavia P. Falcon","MP52 Hornet","Phobos M3P","Repulse","Hathcock","Nautilus"},
219			{"Phobos M3P","MP52 Hornet","Flavia P.Falcon","Hathcock","Nautilus","Repulse","Flavia P. Falcon","MP52 Hornet","Phobos M3P","Repulse","Hathcock","Nautilus","Flavia P. Falcon"},
220			{"Phobos M3P","MP52 Hornet","Flavia P.Falcon","Hathcock","Nautilus","Repulse","Flavia P. Falcon","MP52 Hornet","Phobos M3P","Repulse","Hathcock","Nautilus","Flavia P. Falcon","Phobos M3P"},
221			{"Phobos M3P","MP52 Hornet","Flavia P.Falcon","Hathcock","Nautilus","Repulse","Flavia P. Falcon","MP52 Hornet","Phobos M3P","Repulse","Hathcock","Nautilus","Flavia P. Falcon","Phobos M3P","MP52 Hornet"},
222			{"Phobos M3P","MP52 Hornet","Flavia P.Falcon","Hathcock","Nautilus","Repulse","Flavia P. Falcon","MP52 Hornet","Phobos M3P","Repulse","Hathcock","Nautilus","Flavia P. Falcon","Phobos M3P","MP52 Hornet","Repulse"},
223		},
224		["Custom"] = {
225			{"Holmes"},
226			{"Holmes","Phobos T2"},
227			{"Holmes","Phobos T2","Striker LX"},
228			{"Holmes","Phobos T2","Striker LX","Maverick XP"},
229			{"Holmes","Phobos T2","Striker LX","Maverick XP","Focus"},
230			{"Holmes","Phobos T2","Striker LX","Maverick XP","Focus","Repulse"},
231			{"Holmes","Phobos T2","Striker LX","Maverick XP","Focus","Repulse","Flavia P. Falcon"},
232			{"Holmes","Phobos T2","Striker LX","Maverick XP","Focus","Repulse","Flavia P. Falcon","Player Fighter"},
233			{"Holmes","Phobos T2","Striker LX","Maverick XP","Focus","Repulse","Flavia P. Falcon","Player Fighter","Phobos M3P"},
234			{"Holmes","Phobos T2","Striker LX","Maverick XP","Focus","Repulse","Flavia P. Falcon","Player Fighter","Phobos M3P","Repulse"},
235			{"Holmes","Phobos T2","Striker LX","Maverick XP","Focus","Repulse","Flavia P. Falcon","Player Fighter","Phobos M3P","Repulse","Hathcock"},
236			{"Holmes","Phobos T2","Striker LX","Maverick XP","Focus","Repulse","Flavia P. Falcon","Player Fighter","Phobos M3P","Repulse","Hathcock","Nautilus"},
237			{"Holmes","Phobos T2","Striker LX","Maverick XP","Focus","Repulse","Flavia P. Falcon","Player Fighter","Phobos M3P","Repulse","Hathcock","Nautilus","Flavia P. Falcon"},
238			{"Holmes","Phobos T2","Striker LX","Maverick XP","Focus","Repulse","Flavia P. Falcon","Player Fighter","Phobos M3P","Repulse","Hathcock","Nautilus","Flavia P. Falcon","Phobos M3P"},
239			{"Holmes","Phobos T2","Striker LX","Maverick XP","Focus","Repulse","Flavia P. Falcon","Player Fighter","Phobos M3P","Repulse","Hathcock","Nautilus","Flavia P. Falcon","Phobos M3P","MP52 Hornet"},
240			{"Holmes","Phobos T2","Striker LX","Maverick XP","Focus","Repulse","Flavia P. Falcon","Player Fighter","Phobos M3P","Repulse","Hathcock","Nautilus","Flavia P. Falcon","Phobos M3P","MP52 Hornet","Repulse"},
241		}
242	}
243	rwc_player_ship_names = {	--rwc: random within category
244		["Atlantis"] = {"Formidable","Thrasher","Punisher","Vorpal","Protang","Drummond","Parchim","Coronado"},
245		["Benedict"] = {"Elizabeth","Ford","Avenger","Washington","Lincoln","Garibaldi","Eisenhower"},
246		["Crucible"] = {"Sling", "Stark", "Torrid", "Kicker", "Flummox"},
247		["Ender"] = {"Mongo","Godzilla","Leviathan","Kraken","Jupiter","Saturn"},
248		["Flavia P.Falcon"] = {"Ladyhawke","Hunter","Seeker","Gyrefalcon","Kestrel","Magpie","Bandit","Buccaneer"},
249		["Hathcock"] = {"Hayha", "Waldron", "Plunkett", "Mawhinney", "Furlong", "Zaytsev", "Pavlichenko", "Fett", "Hawkeye", "Hanzo"},
250		["Kiriya"] = {"Cavour","Reagan","Gaulle","Paulo","Truman","Stennis","Kuznetsov","Roosevelt","Vinson","Old Salt"},
251		["MP52 Hornet"] = {"Dragonfly","Scarab","Mantis","Yellow Jacket","Jimminy","Flik","Thorny","Buzz"},
252		["Maverick"] = {"Angel", "Thunderbird", "Roaster", "Magnifier", "Hedge"},
253		["Nautilus"] = {"October", "Abdiel", "Manxman", "Newcon", "Nusret", "Pluton", "Amiral", "Amur", "Heinkel", "Dornier"},
254		["Phobos M3P"] = {"Blinder","Shadow","Distortion","Diemos","Ganymede","Castillo","Thebe","Retrograde"},
255		["Piranha"] = {"Razor","Biter","Ripper","Voracious","Carnivorous","Characid","Vulture","Predator"},
256		["Player Cruiser"] = {"Excelsior","Velociraptor","Thunder","Kona","Encounter","Perth","Aspern","Panther"},
257		["Player Fighter"] = {"Buzzer","Flitter","Zippiticus","Hopper","Molt","Stinger","Stripe"},
258		["Player Missile Cr."] = {"Projectus","Hurlmeister","Flinger","Ovod","Amatola","Nakhimov","Antigone"},
259		["Repulse"] = {"Fiddler","Brinks","Loomis","Mowag","Patria","Pandur","Terrex","Komatsu","Eitan"},
260		["Striker"] = {"Sparrow","Sizzle","Squawk","Crow","Phoenix","Snowbird","Hawk"},
261		["ZX-Lindworm"]	= {"Seagull","Catapult","Blowhard","Flapper","Nixie","Pixie","Tinkerbell"},
262		["Unknown"] = {"Foregone","Righteous","Masher","Lancer","Horizon","Osiris","Athena","Poseidon","Heracles","Constitution","Stargazer","Horatio","Socrates","Galileo","Newton","Beethoven","Rabin","Spector","Akira","Thunderchild","Ambassador","Adelphi","Exeter","Ghandi","Valdemar","Yamaguchi","Zhukov","Andromeda","Drake","Prokofiev","Antares","Apollo","Ajax","Clement","Bradbury","Gage","Buran","Kearsarge","Cheyenne","Ahwahnee","Constellation","Gettysburg","Hathaway","Magellan","Farragut","Kongo","Lexington","Potempkin","Yorktown","Daedalus","Archon","Carolina","Essex","Danube","Gander","Ganges","Mekong","Orinoco","Rubicon","Shenandoah","Volga","Yangtzee Kiang","Yukon","Valiant","Deneva","Arcos","LaSalle","Al-Batani","Cairo","Charlseton","Crazy Horse","Crockett","Fearless","Fredrickson","Gorkon","Hood","Lakota","Malinche","Melbourne","Freedom","Concorde","Firebrand","Galaxy","Challenger","Odyssey","Trinculo","Venture","Yamato","Hokule'a","Tripoli","Hope","Nobel","Pasteur","Bellerophon","Voyager","Istanbul","Constantinople","Havana","Sarajevo","Korolev","Goddard","Luna","Titan","Mediterranean","Lalo","Wyoming","Merced","Trieste","Miranda","Brattain","Helin","Lantree","Majestic","Reliant","Saratoga","ShirKahr","Sitak","Tian An Men","Trial","Nebula","Bonchune","Capricorn","Hera","Honshu","Interceptor","Leeds","Merrimack","Prometheus","Proxima","Sutherland","T'Kumbra","Ulysses","New Orleans","Kyushu","Renegade","Rutledge","Thomas Paine","Niagra","Princeton","Wellington","Norway","Budapest","Nova","Equinox","Rhode Island","Columbia","Oberth","Biko","Cochraine","Copernicus","Grissom","Pegasus","Raman","Yosemite","Renaissance","Aries","Maryland","Rigel","Akagi","Tolstoy","Yeager","Sequoia","Sovereign","Soyuz","Bozeman","Springfield","Chekov","Steamrunner","Appalachia","Surak","Zapata","Sydney","Jenolen","Nash","Wambundu","Fleming","Wells","Relativity","Yorkshire","Denver","Zodiac","Centaur","Cortez","Republic","Peregrine","Calypso","Cousteau","Waverider","Scimitar"},
263	}
264	player_ship_stats = {
265		["Atlantis"]			= { strength = 52,	cargo = 6,	distance = 400,	long_range_radar = 30000, short_range_radar = 5000, probes = 10,	long_jump = 50,	short_jump = 5,		warp = 0,		stock = true,	},
266		["Benedict"]			= { strength = 10,	cargo = 9,	distance = 400,	long_range_radar = 30000, short_range_radar = 5000, probes = 10,	long_jump = 90,	short_jump = 5,		warp = 0,		stock = true,	},
267		["Crucible"]			= { strength = 45,	cargo = 5,	distance = 200,	long_range_radar = 20000, short_range_radar = 6000, probes = 9,		long_jump = 0,	short_jump = 0,		warp = 750,		stock = true,	},
268		["Ender"]				= { strength = 100,	cargo = 20,	distance = 2000,long_range_radar = 45000, short_range_radar = 7000, probes = 12,	long_jump = 50,	short_jump = 5,		warp = 0,		stock = true,	},
269		["Flavia P.Falcon"]		= { strength = 13,	cargo = 15,	distance = 200,	long_range_radar = 40000, short_range_radar = 5000, probes = 8,		long_jump = 0,	short_jump = 0,		warp = 500,		stock = true,	},
270		["Hathcock"]			= { strength = 30,	cargo = 6,	distance = 200,	long_range_radar = 35000, short_range_radar = 6000, probes = 8,		long_jump = 60,	short_jump = 6,		warp = 0,		stock = true,	},
271		["Kiriya"]				= { strength = 10,	cargo = 9,	distance = 400,	long_range_radar = 35000, short_range_radar = 5000, probes = 10,	long_jump = 0,	short_jump = 0,		warp = 750,		stock = true,	},
272		["Maverick"]			= { strength = 45,	cargo = 5,	distance = 200,	long_range_radar = 20000, short_range_radar = 4000, probes = 9,		long_jump = 0,	short_jump = 0,		warp = 800,		stock = true,	},
273		["MP52 Hornet"] 		= { strength = 7, 	cargo = 3,	distance = 100,	long_range_radar = 18000, short_range_radar = 4000, probes = 5,		long_jump = 0,	short_jump = 0,		warp = 1000,	stock = true,	},
274		["Nautilus"]			= { strength = 12,	cargo = 7,	distance = 200,	long_range_radar = 22000, short_range_radar = 4000, probes = 10,	long_jump = 70,	short_jump = 5,		warp = 0,		stock = true,	},
275		["Phobos M3P"]			= { strength = 19,	cargo = 10,	distance = 200,	long_range_radar = 25000, short_range_radar = 5000, probes = 6,		long_jump = 0,	short_jump = 0,		warp = 900,		stock = true,	},
276		["Piranha"]				= { strength = 16,	cargo = 8,	distance = 200,	long_range_radar = 25000, short_range_radar = 6000, probes = 6,		long_jump = 50,	short_jump = 5,		warp = 0,		stock = true,	},
277		["Player Cruiser"]		= { strength = 40,	cargo = 6,	distance = 400,	long_range_radar = 30000, short_range_radar = 5000, probes = 10,	long_jump = 80,	short_jump = 5,		warp = 0,		stock = true,	},
278		["Player Missile Cr."]	= { strength = 45,	cargo = 8,	distance = 200,	long_range_radar = 35000, short_range_radar = 6000, probes = 9,		long_jump = 0,	short_jump = 0,		warp = 800,		stock = true,	},
279		["Player Fighter"]		= { strength = 7,	cargo = 3,	distance = 100,	long_range_radar = 15000, short_range_radar = 4500, probes = 4,		long_jump = 40,	short_jump = 3,		warp = 0,		stock = true,	},
280		["Repulse"]				= { strength = 14,	cargo = 12,	distance = 200,	long_range_radar = 38000, short_range_radar = 5000, probes = 8,		long_jump = 50,	short_jump = 5,		warp = 0,		stock = true,	},
281		["Striker"]				= { strength = 8,	cargo = 4,	distance = 200,	long_range_radar = 35000, short_range_radar = 5000, probes = 6,		long_jump = 40,	short_jump = 3,		warp = 0,		stock = true,	},
282		["ZX-Lindworm"]			= { strength = 8,	cargo = 3,	distance = 100,	long_range_radar = 18000, short_range_radar = 5500, probes = 4,		long_jump = 0,	short_jump = 0,		warp = 950,		stock = true,	},
283	--	Stock above, custom below
284		["Focus"]				= { strength = 35,	cargo = 4,	distance = 200,	long_range_radar = 32000, short_range_radar = 5000, probes = 8,		long_jump = 25,	short_jump = 2.5,	warp = 0,		stock = false,	},
285		["Holmes"]				= { strength = 35,	cargo = 6,	distance = 200,	long_range_radar = 35000, short_range_radar = 4000, probes = 8,		long_jump = 0,	short_jump = 0,		warp = 750,		stock = false,	},
286		["Maverick XP"]			= { strength = 23,	cargo = 5,	distance = 200,	long_range_radar = 25000, short_range_radar = 7000, probes = 10,	long_jump = 20,	short_jump = 2,		warp = 0,		stock = false,	},
287		["Phobos T2"]			= { strength = 19,	cargo = 9,	distance = 200,	long_range_radar = 25000, short_range_radar = 5000, probes = 5,		long_jump = 25,	short_jump = 2,		warp = 0,		stock = false,	},
288		["Striker LX"]			= { strength = 16,	cargo = 4,	distance = 200,	long_range_radar = 20000, short_range_radar = 4000, probes = 7,		long_jump = 20,	short_jump = 2,		warp = 0,		stock = false,	},
289	}
290	npc_ships = false
291	npc_lower = 30
292	npc_upper = 60
293	scientist_list = {}
294	scientist_count = 0
295	scientist_score_value = 10
296	scientist_names = {	--fictional
297		"Gertrude Goodall",
298		"John Kruger",
299		"Lisa Forsythe",
300		"Ethan Williams",
301		"Ameilia Martinez",
302		"Felix Mertens",
303		"Marie Novak",
304		"Mathias Evans",
305		"Clara Heikkinen",
306		"Vicente Martin",
307		"Catalina Fischer",
308		"Marek Varga",
309		"Ewa Olsen",
310		"Oscar Stewart",
311		"Alva Rodriguez",
312		"Aiden Johansson",
313		"Zoey Smith",
314		"Jorge Romero",
315		"Rosa Wong",
316		"Julian Acharya",
317		"Hannah Ginting",
318		"Anton Dewala",
319		"Camille Silva",
320		"Aleksi Gideon",
321		"Ella Dasgupta",
322		"Gunnar Smirnov",
323		"Telma Lozano",
324		"Kaito Fabroa",
325		"Misaki Kapia",
326		"Ronald Sanada",
327		"Janice Tesfaye",
328		"Alvaro Hassan",
329		"Valeria Dinh",
330		"Sergei Mokri",
331		"Yulia Karga",
332		"Arnav Dixon",
333		"Sanvi Saetan",
334	}
335	scientist_topics = {
336		"Mathematics",
337		"Miniaturization",
338		"Exotic materials",
339		"Warp theory",
340		"Particle theory",
341		"Power systems",
342		"Energy fields",
343		"Subatomic physics",
344		"Stellar phenomena",
345		"Gravity dynamics",
346		"Information science",
347		"Computer protocols",
348	}
349	upgrade_requirements = {
350		"talk",			--talk
351		"talk primary",	--talk then upgrade at primary station
352		"meet",			--meet
353		"meet primary",	--meet then upgrade at primary station
354		"transport",	--transport to primary station
355		"confer",		--transport to primary station, then confer with another scientist
356	}
357	upgrade_list = {
358		{action = hullStrengthUpgrade, name = "hull strength upgrade"},
359		{action = shieldStrengthUpgrade, name = "shield strength upgrade"},
360		{action = missileLoadSpeedUpgrade, name = "missile load speed upgrade"},
361		{action = beamDamageUpgrade, name = "beam damage upgrade"},
362		{action = beamRangeUpgrade, name = "beam range upgrade"},
363		{action = batteryEfficiencyUpgrade, name = "battery efficiency upgrade"},
364		{action = fasterImpulseUpgrade, name = "faster impulse upgrade"},
365		{action = longerSensorsUpgrade, name = "longer sensor range upgrade"},
366		{action = fasterSpinUpgrade, name = "faster maneuvering speed upgrade"},
367	}
368	upgrade_automated_applications = {
369		"single",	--automatically applied only to the player that completed the requirements
370		"players",	--automatically applied to allied players
371		"all",		--automatically applied to players and NPCs (where applicable)
372	}
373	prefix_length = 0
374	suffix_index = 0
375	formation_delta = {
376		["square"] = {
377			x = {0,1,0,-1, 0,1,-1, 1,-1,2,0,-2, 0,2,-2, 2,-2,2, 2,-2,-2,1,-1, 1,-1,0, 0,3,-3,1, 1,3,-3,-1,-1, 3,-3,2, 2,3,-3,-2,-2, 3,-3,3, 3,-3,-3,4,0,-4, 0,4,-4, 4,-4,-4,-4,-4,-4,-4,-4,4, 4,4, 4,4, 4, 1,-1, 2,-2, 3,-3,1,-1,2,-2,3,-3,5,-5,0, 0,5, 5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,5, 5,5, 5,5, 5,5, 5, 1,-1, 2,-2, 3,-3, 4,-4,1,-1,2,-2,3,-3,4,-4},
378			y = {0,0,1, 0,-1,1,-1,-1, 1,0,2, 0,-2,2,-2,-2, 2,1,-1, 1,-1,2, 2,-2,-2,3,-3,0, 0,3,-3,1, 1, 3,-3,-1,-1,3,-3,2, 2, 3,-3,-2,-2,3,-3, 3,-3,0,4, 0,-4,4,-4,-4, 4, 1,-1, 2,-2, 3,-3,1,-1,2,-2,3,-3,-4,-4,-4,-4,-4,-4,4, 4,4, 4,4, 4,0, 0,5,-5,5,-5, 5,-5, 1,-1, 2,-2, 3,-3, 4,-4,1,-1,2,-2,3,-3,4,-4,-5,-5,-5,-5,-5,-5,-5,-5,5, 5,5, 5,5, 5,5, 5},
379		},
380		["hexagonal"] = {
381			x = {0,2,-2,1,-1, 1,-1,4,-4,0, 0,2,-2,-2, 2,3,-3, 3,-3,6,-6,1,-1, 1,-1,3,-3, 3,-3,4,-4, 4,-4,5,-5, 5,-5,8,-8,4,-4, 4,-4,5,5 ,-5,-5,2, 2,-2,-2,0, 0,6, 6,-6,-6,7, 7,-7,-7,10,-10,5, 5,-5,-5,6, 6,-6,-6,7, 7,-7,-7,8, 8,-8,-8,9, 9,-9,-9,3, 3,-3,-3,1, 1,-1,-1,12,-12,6,-6, 6,-6,7,-7, 7,-7,8,-8, 8,-8,9,-9, 9,-9,10,-10,10,-10,11,-11,11,-11,4,-4, 4,-4,2,-2, 2,-2,0, 0},
382			y = {0,0, 0,1, 1,-1,-1,0, 0,2,-2,2,-2, 2,-2,1,-1,-1, 1,0, 0,3, 3,-3,-3,3,-3,-3, 3,2,-2,-2, 2,1,-1,-1, 1,0, 0,4,-4,-4, 4,3,-3, 3,-3,4,-4, 4,-4,4,-4,2,-2, 2,-2,1,-1, 1,-1, 0,  0,5,-5, 5,-5,4,-4, 4,-4,3,-3, 3,-7,2,-2, 2,-2,1,-1, 1,-1,5,-5, 5,-5,5,-5, 5,-5, 0,  0,6, 6,-6,-6,5, 5,-5,-5,4, 4,-4,-4,3, 3,-3,-3, 2,  2,-2, -2, 1,  1,-1, -1,6, 6,-6,-6,6, 6,-6,-6,6,-6},
383		},
384	}
385	fleet_group = {
386		["adder"] = "Adders",
387		["Adders"] = "adder",
388		["missiler"] = "Missilers",
389		["Missilers"] = "missiler",
390		["beamer"] = "Beamers",
391		["Beamers"] = "beamer",
392		["frigate"] = "Frigates",
393		["Frigates"] = "frigate",
394		["chaser"] = "Chasers",
395		["Chasers"] = "chaser",
396		["fighter"] = "Fighters",
397		["Fighters"] = "fighter",
398		["drone"] = "Drones",
399		["Drones"] = "drone",
400	}
401	ship_template = {	--ordered by relative strength
402		["Gnat"] =				{strength = 2,	adder = false,	missiler = false,	beamer = true,	frigate = false,	chaser = false,	fighter = true,		drone = true,	unusual = false,	base = false,	create = gnat},
403		["Lite Drone"] =		{strength = 3,	adder = false,	missiler = false,	beamer = true,	frigate = false,	chaser = false,	fighter = true, 	drone = true,	unusual = false,	base = false,	create = droneLite},
404		["Jacket Drone"] =		{strength = 4,	adder = false,	missiler = false,	beamer = true,	frigate = false,	chaser = false,	fighter = true, 	drone = true,	unusual = false,	base = false,	create = droneJacket},
405		["Ktlitan Drone"] =		{strength = 4,	adder = false,	missiler = false,	beamer = true,	frigate = false,	chaser = false,	fighter = true, 	drone = true,	unusual = false,	base = false,	create = stockTemplate},
406		["Heavy Drone"] =		{strength = 5,	adder = false,	missiler = false,	beamer = true,	frigate = false,	chaser = false,	fighter = true, 	drone = true,	unusual = false,	base = false,	create = droneHeavy},
407		["Adder MK3"] =			{strength = 5,	adder = true,	missiler = false,	beamer = false,	frigate = false,	chaser = false,	fighter = false,	drone = false,	unusual = false,	base = false,	create = stockTemplate},
408		["MT52 Hornet"] =		{strength = 5,	adder = false,	missiler = false,	beamer = true,	frigate = false,	chaser = false,	fighter = true, 	drone = false,	unusual = false,	base = false,	create = stockTemplate},
409		["MU52 Hornet"] =		{strength = 5,	adder = false,	missiler = false,	beamer = true,	frigate = false,	chaser = false,	fighter = true, 	drone = false,	unusual = false,	base = false,	create = stockTemplate},
410		["MV52 Hornet"] =		{strength = 6,	adder = false,	missiler = false,	beamer = true,	frigate = false,	chaser = false,	fighter = true, 	drone = false,	unusual = false,	base = false,	create = hornetMV52},
411		["Adder MK4"] =			{strength = 6,	adder = true,	missiler = false,	beamer = false,	frigate = false,	chaser = false,	fighter = false,	drone = false,	unusual = false,	base = false,	create = stockTemplate},
412		["Fighter"] =			{strength = 6,	adder = false,	missiler = false,	beamer = true,	frigate = false,	chaser = false,	fighter = true, 	drone = false,	unusual = false,	base = false,	create = stockTemplate},
413		["Ktlitan Fighter"] =	{strength = 6,	adder = false,	missiler = false,	beamer = true,	frigate = false,	chaser = false,	fighter = true, 	drone = false,	unusual = false,	base = false,	create = stockTemplate},
414		["K2 Fighter"] =		{strength = 7,	adder = false,	missiler = false,	beamer = true,	frigate = false,	chaser = false,	fighter = true, 	drone = false,	unusual = false,	base = false,	create = k2fighter},
415		["Adder MK5"] =			{strength = 7,	adder = true,	missiler = false,	beamer = false,	frigate = false,	chaser = false,	fighter = false,	drone = false,	unusual = false,	base = false,	create = stockTemplate},
416		["WX-Lindworm"] =		{strength = 7,	adder = false,	missiler = true,	beamer = false,	frigate = false,	chaser = false,	fighter = true, 	drone = false,	unusual = false,	base = false,	create = stockTemplate},
417		["K3 Fighter"] =		{strength = 8,	adder = false,	missiler = false,	beamer = true,	frigate = false,	chaser = false,	fighter = true, 	drone = false,	unusual = false,	base = false,	create = k3fighter},
418		["Adder MK6"] =			{strength = 8,	adder = true,	missiler = false,	beamer = false,	frigate = false,	chaser = false,	fighter = false,	drone = false,	unusual = false,	base = false,	create = stockTemplate},
419		["Ktlitan Scout"] =		{strength = 8,	adder = false,	missiler = false,	beamer = true,	frigate = false,	chaser = false,	fighter = false,	drone = false,	unusual = false,	base = false,	create = stockTemplate},
420		["WZ-Lindworm"] =		{strength = 9,	adder = false,	missiler = true,	beamer = false,	frigate = false,	chaser = false,	fighter = true, 	drone = false,	unusual = false,	base = false,	create = wzLindworm},
421		["Adder MK7"] =			{strength = 9,	adder = true,	missiler = false,	beamer = false,	frigate = false,	chaser = false,	fighter = false,	drone = false,	unusual = false,	base = false,	create = stockTemplate},
422		["Adder MK8"] =			{strength = 10,	adder = true,	missiler = false,	beamer = false,	frigate = false,	chaser = false,	fighter = false,	drone = false,	unusual = false,	base = false,	create = stockTemplate},
423		["Adder MK9"] =			{strength = 11,	adder = true,	missiler = false,	beamer = false,	frigate = false,	chaser = false,	fighter = false,	drone = false,	unusual = false,	base = false,	create = stockTemplate},
424		["Nirvana R3"] =		{strength = 12,	adder = false,	missiler = false,	beamer = true,	frigate = false,	chaser = false,	fighter = false,	drone = false,	unusual = false,	base = false,	create = stockTemplate},
425		["Phobos R2"] =			{strength = 13,	adder = false,	missiler = false,	beamer = false,	frigate = true, 	chaser = false,	fighter = false,	drone = false,	unusual = false,	base = false,	create = phobosR2},
426		["Missile Cruiser"] =	{strength = 14,	adder = false,	missiler = true,	beamer = false,	frigate = true, 	chaser = false,	fighter = false,	drone = false,	unusual = false,	base = false,	create = stockTemplate},
427		["Waddle 5"] =			{strength = 15,	adder = true,	missiler = false,	beamer = false,	frigate = false,	chaser = true,	fighter = false,	drone = false,	unusual = false,	base = false,	create = waddle5},
428		["Jade 5"] =			{strength = 15,	adder = true,	missiler = false,	beamer = false,	frigate = false,	chaser = true,	fighter = false,	drone = false,	unusual = false,	base = false,	create = jade5},
429		["Phobos T3"] =			{strength = 15,	adder = false,	missiler = false,	beamer = false,	frigate = true, 	chaser = false,	fighter = false,	drone = false,	unusual = false,	base = false,	create = stockTemplate},
430		["Piranha F8"] =		{strength = 15,	adder = false,	missiler = true,	beamer = false,	frigate = true, 	chaser = false,	fighter = false,	drone = false,	unusual = false,	base = false,	create = stockTemplate},
431		["Piranha F12"] =		{strength = 15,	adder = false,	missiler = true,	beamer = false,	frigate = true, 	chaser = false,	fighter = false,	drone = false,	unusual = false,	base = false,	create = stockTemplate},
432		["Piranha F12.M"] =		{strength = 16,	adder = false,	missiler = true,	beamer = false,	frigate = true, 	chaser = false,	fighter = false,	drone = false,	unusual = false,	base = false,	create = stockTemplate},
433		["Phobos M3"] =			{strength = 16,	adder = false,	missiler = false,	beamer = false,	frigate = true, 	chaser = false,	fighter = false,	drone = false,	unusual = false,	base = false,	create = stockTemplate},
434		["Farco 3"] =			{strength = 16,	adder = false,	missiler = false,	beamer = false,	frigate = true, 	chaser = false,	fighter = false,	drone = false,	unusual = false,	base = false,	create = farco3},
435		["Farco 5"] =			{strength = 16,	adder = false,	missiler = false,	beamer = false,	frigate = true, 	chaser = false,	fighter = false,	drone = false,	unusual = false,	base = false,	create = farco5},
436		["Karnack"] =			{strength = 17,	adder = false,	missiler = false,	beamer = true,	frigate = true,		chaser = false,	fighter = false,	drone = false,	unusual = false,	base = false,	create = stockTemplate},
437		["Gunship"] =			{strength = 17,	adder = false,	missiler = false,	beamer = false,	frigate = true,		chaser = false,	fighter = false,	drone = false,	unusual = false,	base = false,	create = stockTemplate},
438		["Phobos T4"] =			{strength = 18,	adder = false,	missiler = false,	beamer = false,	frigate = true, 	chaser = false,	fighter = false,	drone = false,	unusual = false,	base = false,	create = phobosT4},
439		["Cruiser"] =			{strength = 18,	adder = true,	missiler = false,	beamer = true,	frigate = true, 	chaser = false,	fighter = false,	drone = false,	unusual = false,	base = false,	create = stockTemplate},
440		["Nirvana R5"] =		{strength = 19,	adder = false,	missiler = false,	beamer = true,	frigate = true, 	chaser = false,	fighter = false,	drone = false,	unusual = false,	base = false,	create = stockTemplate},
441		["Farco 8"] =			{strength = 19,	adder = false,	missiler = false,	beamer = false,	frigate = true, 	chaser = false,	fighter = false,	drone = false,	unusual = false,	base = false,	create = farco8},
442		["Ktlitan Worker"] =	{strength = 20,	adder = false,	missiler = false,	beamer = true,	frigate = false,	chaser = false,	fighter = false,	drone = false,	unusual = false,	base = false,	create = stockTemplate},
443		["Nirvana R5A"] =		{strength = 20,	adder = false,	missiler = false,	beamer = true,	frigate = true, 	chaser = false,	fighter = false,	drone = false,	unusual = false,	base = false,	create = stockTemplate},
444		["Adv. Gunship"] =		{strength = 20,	adder = false,	missiler = false,	beamer = false,	frigate = true,		chaser = false,	fighter = false,	drone = false,	unusual = false,	base = false,	create = stockTemplate},
445		["Farco 11"] =			{strength = 21,	adder = false,	missiler = false,	beamer = false,	frigate = true, 	chaser = false,	fighter = false,	drone = false,	unusual = false,	base = false,	create = farco11},
446		["Storm"] =				{strength = 22,	adder = false,	missiler = true,	beamer = false,	frigate = true, 	chaser = false,	fighter = false,	drone = false,	unusual = false,	base = false,	create = stockTemplate},
447		["Stalker R5"] =		{strength = 22,	adder = false,	missiler = false,	beamer = true,	frigate = true, 	chaser = true,	fighter = false,	drone = false,	unusual = false,	base = false,	create = stockTemplate},
448		["Stalker Q5"] =		{strength = 22,	adder = false,	missiler = false,	beamer = true,	frigate = true, 	chaser = true,	fighter = false,	drone = false,	unusual = false,	base = false,	create = stockTemplate},
449		["Farco 13"] =			{strength = 24,	adder = false,	missiler = false,	beamer = false,	frigate = true, 	chaser = false,	fighter = false,	drone = false,	unusual = false,	base = false,	create = farco13},
450		["Ranus U"] =			{strength = 25,	adder = false,	missiler = true,	beamer = false,	frigate = true, 	chaser = false,	fighter = false,	drone = false,	unusual = false,	base = false,	create = stockTemplate},
451		["Stalker Q7"] =		{strength = 25,	adder = false,	missiler = false,	beamer = true,	frigate = true, 	chaser = true,	fighter = false,	drone = false,	unusual = false,	base = false,	create = stockTemplate},
452		["Stalker R7"] =		{strength = 25,	adder = false,	missiler = false,	beamer = true,	frigate = true, 	chaser = true,	fighter = false,	drone = false,	unusual = false,	base = false,	create = stockTemplate},
453		["Whirlwind"] =			{strength = 26,	adder = false,	missiler = true,	beamer = false,	frigate = true, 	chaser = false,	fighter = false,	drone = false,	unusual = false,	base = false,	create = whirlwind},
454		["Adv. Striker"] =		{strength = 27,	adder = false,	missiler = false,	beamer = true,	frigate = true,		chaser = true,	fighter = false,	drone = false,	unusual = false,	base = false,	create = stockTemplate},
455		["Elara P2"] =			{strength = 28,	adder = false,	missiler = false,	beamer = false,	frigate = true, 	chaser = true,	fighter = false,	drone = false,	unusual = false,	base = false,	create = stockTemplate},
456		["Tempest"] =			{strength = 30,	adder = false,	missiler = true,	beamer = false,	frigate = true, 	chaser = false,	fighter = false,	drone = false,	unusual = false,	base = false,	create = tempest},
457		["Strikeship"] =		{strength = 30,	adder = false,	missiler = false,	beamer = true,	frigate = true, 	chaser = true,	fighter = false,	drone = false,	unusual = false,	base = false,	create = stockTemplate},
458		["Fiend G3"] =			{strength = 33,	adder = false,	missiler = false,	beamer = false,	frigate = true, 	chaser = true,	fighter = false,	drone = false,	unusual = false,	base = false,	create = stockTemplate},
459		["Fiend G4"] =			{strength = 35,	adder = false,	missiler = false,	beamer = false,	frigate = true, 	chaser = true,	fighter = false,	drone = false,	unusual = false,	base = false,	create = stockTemplate},
460		["Cucaracha"] =			{strength = 36,	adder = false,	missiler = false,	beamer = true,	frigate = false,	chaser = false,	fighter = false,	drone = false,	unusual = false,	base = false,	create = cucaracha},
461		["Fiend G5"] =			{strength = 37,	adder = false,	missiler = false,	beamer = false,	frigate = true, 	chaser = true,	fighter = false,	drone = false,	unusual = false,	base = false,	create = stockTemplate},
462		["Fiend G6"] =			{strength = 39,	adder = false,	missiler = false,	beamer = false,	frigate = true, 	chaser = true,	fighter = false,	drone = false,	unusual = false,	base = false,	create = stockTemplate},
463		["Predator"] =			{strength = 42,	adder = false,	missiler = false,	beamer = false,	frigate = true, 	chaser = false,	fighter = false,	drone = false,	unusual = false,	base = false,	create = predator},
464		["Ktlitan Breaker"] =	{strength = 45,	adder = false,	missiler = false,	beamer = false,	frigate = false,	chaser = false,	fighter = false,	drone = false,	unusual = false,	base = false,	create = stockTemplate},
465		["Hurricane"] =			{strength = 46,	adder = false,	missiler = true,	beamer = false,	frigate = true, 	chaser = false,	fighter = false,	drone = false,	unusual = false,	base = false,	create = hurricane},
466		["Ktlitan Feeder"] =	{strength = 48,	adder = false,	missiler = false,	beamer = true,	frigate = false,	chaser = false,	fighter = false,	drone = false,	unusual = false,	base = false,	create = stockTemplate},
467		["Atlantis X23"] =		{strength = 50,	adder = false,	missiler = false,	beamer = false,	frigate = false,	chaser = true,	fighter = false,	drone = false,	unusual = false,	base = false,	create = stockTemplate},
468		["K2 Breaker"] =		{strength = 55,	adder = false,	missiler = false,	beamer = false,	frigate = false,	chaser = false,	fighter = false,	drone = false,	unusual = false,	base = false,	create = k2breaker},
469		["Ktlitan Destroyer"] =	{strength = 50,	adder = false,	missiler = false,	beamer = false,	frigate = false,	chaser = false,	fighter = false,	drone = false,	unusual = false,	base = false,	create = stockTemplate},
470		["Atlantis Y42"] =		{strength = 60,	adder = false,	missiler = false,	beamer = false,	frigate = false,	chaser = true,	fighter = false,	drone = false,	unusual = false,	base = false,	create = atlantisY42},
471		["Blockade Runner"] =	{strength = 65,	adder = false,	missiler = false,	beamer = true,	frigate = false,	chaser = false,	fighter = false,	drone = false,	unusual = false,	base = false,	create = stockTemplate},
472		["Starhammer II"] =		{strength = 70,	adder = false,	missiler = false,	beamer = false,	frigate = false,	chaser = true,	fighter = false,	drone = false,	unusual = false,	base = false,	create = stockTemplate},
473		["Enforcer"] =			{strength = 75,	adder = false,	missiler = false,	beamer = false,	frigate = true, 	chaser = false,	fighter = false,	drone = false,	unusual = false,	base = false,	create = enforcer},
474		["Dreadnought"] =		{strength = 80,	adder = false,	missiler = false,	beamer = true,	frigate = false,	chaser = false,	fighter = false,	drone = false,	unusual = false,	base = false,	create = stockTemplate},
475		["Starhammer III"] =	{strength = 85,	adder = false,	missiler = false,	beamer = false,	frigate = false,	chaser = true,	fighter = false,	drone = false,	unusual = false,	base = false,	create = starhammerIII},
476		["Starhammer V"] =		{strength = 90,	adder = false,	missiler = false,	beamer = false,	frigate = false,	chaser = true,	fighter = false,	drone = false,	unusual = false,	base = false,	create = starhammerV},
477		["Battlestation"] =		{strength = 100,adder = false,	missiler = false,	beamer = true,	frigate = false,	chaser = true,	fighter = false,	drone = false,	unusual = false,	base = false,	create = stockTemplate},
478		["Tyr"] =				{strength = 150,adder = false,	missiler = false,	beamer = true,	frigate = false,	chaser = true,	fighter = false,	drone = false,	unusual = false,	base = false,	create = tyr},
479		["Odin"] =				{strength = 250,adder = false,	missiler = false,	beamer = false,	frigate = false,	chaser = true,	fighter = false,	drone = false,	unusual = false,	base = false,	create = stockTemplate},
480	}
481	control_code_stem = {	--All control codes must use capital letters or they will not work.
482		"ALWAYS",
483		"BLACK",
484		"BLUE",
485		"BRIGHT",
486		"BROWN",
487		"CHAIN",
488		"CHURCH",
489		"DOORWAY",
490		"DULL",
491		"ELBOW",
492		"EMPTY",
493		"EPSILON",
494		"FLOWER",
495		"FLY",
496		"FROZEN",
497		"GREEN",
498		"GLOW",
499		"HAMMER",
500		"INK",
501		"JUMP",
502		"KEY",
503		"LETTER",
504		"LIST",
505		"MORNING",
506		"NEXT",
507		"OPEN",
508		"ORANGE",
509		"OUTSIDE",
510		"PURPLE",
511		"QUARTER",
512		"QUIET",
513		"RED",
514		"SHINE",
515		"SIGMA",
516		"STAR",
517		"STREET",
518		"TOKEN",
519		"THIRSTY",
520		"UNDER",
521		"VANISH",
522		"WHITE",
523		"WRENCH",
524		"YELLOW",
525	}
526	healthCheckTimerInterval = 10
527	healthCheckTimer = healthCheckTimerInterval
528	commonGoods = {"food","medicine","nickel","platinum","gold","dilithium","tritanium","luxury","cobalt","impulse","warp","shield","tractor","repulsor","beam","optic","robotic","filament","transporter","sensor","communication","autodoc","lifter","android","nanites","software","circuit","battery"}
529	componentGoods = {"impulse","warp","shield","tractor","repulsor","beam","optic","robotic","filament","transporter","sensor","communication","autodoc","lifter","android","nanites","software","circuit","battery"}
530	mineralGoods = {"nickel","platinum","gold","dilithium","tritanium","cobalt"}
531end
532function setStaticScienceDatabase()
533--------------------------------------------------------------------------------------
534--	Generic station descriptions: text and details from shipTemplates_stations.lua  --
535--------------------------------------------------------------------------------------
536	local station_db = queryScienceDatabase("Stations")
537	if station_db == nil then
538		station_db = ScienceDatabase():setName("Stations")
539		station_db:setLongDescription("Stations are places for ships to dock, get repaired and replenished, interact with station personnel, etc. They are like oases, service stations, villages, towns, cities, etc.")
540		station_db:addEntry("Small")
541		local small_station_db = queryScienceDatabase("Stations","Small")
542		small_station_db:setLongDescription("Stations of this size are often used as research outposts, listening stations, and security checkpoints. Crews turn over frequently in a small station's cramped accommodatations, but they are small enough to look like ships on many long-range sensors, and organized raiders sometimes take advantage of this by placing small stations in nebulae to serve as raiding bases. They are lightly shielded and vulnerable to swarming assaults.")
543		small_station_db:setImage("radartrace_smallstation.png")
544		small_station_db:setKeyValue("Class","Small")
545		small_station_db:setKeyValue("Size",300)
546		small_station_db:setKeyValue("Shield",300)
547		small_station_db:setKeyValue("Hull",150)
548		station_db:addEntry("Medium")
549		local medium_station_db = queryScienceDatabase("Stations","Medium")
550		medium_station_db:setLongDescription("Large enough to accommodate small crews for extended periods of times, stations of this size are often trading posts, refuelling bases, mining operations, and forward military bases. While their shields are strong, concerted attacks by many ships can bring them down quickly.")
551		medium_station_db:setImage("radartrace_mediumstation.png")
552		medium_station_db:setKeyValue("Class","Medium")
553		medium_station_db:setKeyValue("Size",1000)
554		medium_station_db:setKeyValue("Shield",800)
555		medium_station_db:setKeyValue("Hull",400)
556		station_db:addEntry("Large")
557		local large_station_db = queryScienceDatabase("Stations","Large")
558		large_station_db:setLongDescription("These spaceborne communities often represent permanent bases in a sector. Stations of this size can be military installations, commercial hubs, deep-space settlements, and small shipyards. Only a concentrated attack can penetrate a large station's shields, and its hull can withstand all but the most powerful weaponry.")
559		large_station_db:setImage("radartrace_largestation.png")
560		large_station_db:setKeyValue("Class","Large")
561		large_station_db:setKeyValue("Size",1300)
562		large_station_db:setKeyValue("Shield","1000/1000/1000")
563		large_station_db:setKeyValue("Hull",500)
564		station_db:addEntry("Huge")
565		local huge_station_db = queryScienceDatabase("Stations","Huge")
566		huge_station_db:setLongDescription("The size of a sprawling town, stations at this scale represent a faction's center of spaceborne power in a region. They serve many functions at once and represent an extensive investment of time, money, and labor. A huge station's shields and thick hull can keep it intact long enough for reinforcements to arrive, even when faced with an ongoing siege or massive, perfectly coordinated assault.")
567		huge_station_db:setImage("radartrace_hugestation.png")
568		huge_station_db:setKeyValue("Class","Huge")
569		huge_station_db:setKeyValue("Size",1500)
570		huge_station_db:setKeyValue("Shield","1200/1200/1200/1200")
571		huge_station_db:setKeyValue("Hull",800)
572	end
573-----------------------------------------------------------------------------------
574--	Template ship category descriptions: text from other shipTemplates... files  --
575-----------------------------------------------------------------------------------
576	local ships_db = queryScienceDatabase("Ships")
577	local fighter_db = queryScienceDatabase("Ships","Starfighter")
578	local generic_starfighter_description = "Starfighters are single to 3 person small ships. These are most commonly used as light firepower roles.\nThey are common in larger groups, and need a close by station or support ship, as they lack long time life support.\nIt's rare to see starfighters with more then one shield section.\n\nOne of the most well known starfighters is the X-Wing.\n\nStarfighters come in 3 subclasses:\n* Interceptors: Fast, low on firepower, high on manouverability\n* Gunship: Equipped with more weapons, but trades in manouverability because of it.\n* Bomber: Slowest of all starfighters, but pack a large punch in a small package. Usually come without any lasers, but the largers bombers have been known to deliver nukes."
579	fighter_db:setLongDescription(generic_starfighter_description)
580	local frigate_db = queryScienceDatabase("Ships","Frigate")
581	local generic_frigate_description = "Frigates are one size up from starfighters. They require a crew from 3 to 20 people.\nThink, Firefly, millennium falcon, slave I (Boba fett's ship).\n\nThey generally have 2 or more shield sections, but hardly ever more than 4.\n\nThis class of ships is normally not fitted with jump or warp drives. But in some cases ships are modified to include these, or for certain roles it is built in.\n\nThey are divided in 3 different sub-classes:\n* Cruiser: Weaponized frigates, focused on combat. These come in various roles.\n* Light transport: Small transports, like transporting up to 50 soldiers in spartan conditions or a few diplomats in luxury. Depending on the role it can have some weaponry.\n* Support: Support types come in many varieties. They are simply a frigate hull fitted with whatever was needed. Anything from mine-layers to science vessels."
582	frigate_db:setLongDescription(generic_frigate_description)
583	local corvette_db = queryScienceDatabase("Ships","Corvette")
584	local generic_corvette_description = "Corvettes are the common large ships. Larger then a frigate, smaller then a dreadnaught.\nThey generally have 4 or more shield sections. Run with a crew of 20 to 250.\nThis class generally has jumpdrives or warpdrives. But lack the maneuverability that is seen in frigates.\n\nThey come in 3 different subclasses:\n* Destroyer: Combat oriented ships. No science, no transport. Just death in a large package.\n* Support: Large scale support roles. Drone carriers fall in this category, as well as mobile repair centers.\n* Freighter: Large scale transport ships. Most common here are the jump freighters, using specialized jumpdrives to cross large distances with large amounts of cargo."
585	corvette_db:setLongDescription(generic_corvette_description)
586	local dreadnought_db = queryScienceDatabase("Ships","Dreadnought")
587	dreadnought_db:setLongDescription("Dreadnoughts are the largest ships.\nThey are so large and uncommon that every type is pretty much their own subclass.\nThey usually come with 6 or more shield sections, require a crew of 250+ to operate.\n\nThink: Stardestroyer.")
588--------------------------
589--	Stock player ships  --
590--------------------------
591	local stock_db = ships_db:addEntry("Mainstream")
592	stock_db = queryScienceDatabase("Ships","Mainstream")
593	stock_db:setLongDescription("Mainstream ships are those ship types that are commonly available to crews serving on the front lines or in well established areas")
594----	Starfighters
595	local fighter_stock_db = stock_db:addEntry("Starfighter")
596	fighter_stock_db:setLongDescription(generic_starfighter_description)
597--	MP52 Hornet
598	fighter_stock_db:addEntry("MP52 Hornet")
599	local mp52_hornet_db = queryScienceDatabase("Ships","Mainstream","Starfighter","MP52 Hornet")
600	mp52_hornet_db:setLongDescription("The MP52 Hornet is a significantly upgraded version of MU52 Hornet, with nearly twice the hull strength, nearly three times the shielding, better acceleration, impulse boosters, and a second laser cannon.")
601	mp52_hornet_db:setKeyValue("Class","Starfighter")
602	mp52_hornet_db:setKeyValue("Sub-class","Interceptor")
603	mp52_hornet_db:setKeyValue("Size","30")
604	mp52_hornet_db:setKeyValue("Shield","60")
605	mp52_hornet_db:setKeyValue("Hull","70")
606	mp52_hornet_db:setKeyValue("Repair Crew",1)
607	mp52_hornet_db:setKeyValue("Warp Speed","60 U/min")	--1000 (added for scenario)
608	mp52_hornet_db:setKeyValue("Battery Capacity",400)
609	mp52_hornet_db:setKeyValue("Sensor Ranges","Long: 18 U / Short: 4 U")
610	mp52_hornet_db:setKeyValue("Move speed","7.5 U/min")	--125	(value * 60 / 1000 = units per minute)
611	mp52_hornet_db:setKeyValue("Turn speed","32 deg/sec")
612	mp52_hornet_db:setKeyValue("Beam weapon 355:30","Rng:.9 Dmg:2.5 Cyc:4")
613	mp52_hornet_db:setKeyValue("Beam weapon 5:30","Rng:.9 Dmg:2.5 Cyc:4")
614	mp52_hornet_db:setImage("radar_fighter.png")
615--	Player Fighter
616	fighter_stock_db:addEntry("Player Fighter")
617	local player_fighter_db = queryScienceDatabase("Ships","Mainstream","Starfighter","Player Fighter")
618	player_fighter_db:setLongDescription("A fairly standard fighter with strong beams and a tube for HVLIs. The sensors aren't that great, but it often has a warp drive bolted on making it extraordinarily fast")
619	player_fighter_db:setKeyValue("Class","Starfighter")
620	player_fighter_db:setKeyValue("Size","40")
621	player_fighter_db:setKeyValue("Shield","40")
622	player_fighter_db:setKeyValue("Hull","60")
623	player_fighter_db:setKeyValue("Repair Crew",3)
624	player_fighter_db:setKeyValue("Warp Speed","60 U/min")	--1000 (added for scenario)
625	player_fighter_db:setKeyValue("Battery Capacity",400)
626	player_fighter_db:setKeyValue("Sensor Ranges","Long: 15 U / Short: 4.5 U")
627	player_fighter_db:setKeyValue("Move speed","6.6 U/min")	--110	(value * 60 / 1000 = units per minute)
628	player_fighter_db:setKeyValue("Turn speed","20 deg/sec")
629	player_fighter_db:setKeyValue("Beam weapon 0:40","Rng:.5 Dmg:4 Cyc:6")	--modified for scenario: added short forward beam so others balance
630	player_fighter_db:setKeyValue("Beam weapon 10:40","Rng:1 Dmg:8 Cyc:6")
631	player_fighter_db:setKeyValue("Beam weapon 350:40","Rng:1 Dmg:8 Cyc:6")
632	player_fighter_db:setKeyValue("Tube 0","10 sec")
633	player_fighter_db:setKeyValue("Storage HVLI","4")
634	player_fighter_db:setImage("radar_fighter.png")
635--	Striker
636	fighter_stock_db:addEntry("Striker")
637	local striker_db = queryScienceDatabase("Ships","Mainstream","Starfighter","Striker")
638	striker_db:setLongDescription("The Striker is the predecessor to the advanced striker, slow but agile, but does not do an extreme amount of damage, and lacks in shields")
639	striker_db:setKeyValue("Class","Starfighter")
640	striker_db:setKeyValue("Size","140")
641	striker_db:setKeyValue("Shield","50/30")
642	striker_db:setKeyValue("Hull","120")
643	striker_db:setKeyValue("Repair Crew",2)
644	striker_db:setKeyValue("Jump Range","3 - 40 U")	--modified for scenario
645	striker_db:setKeyValue("Battery Capacity",500)
646	striker_db:setKeyValue("Sensor Ranges","Long: 35 U / Short: 5 U")
647	striker_db:setKeyValue("Move speed","2.7 U/min")	--45
648	striker_db:setKeyValue("Turn speed","15 deg/sec")
649	striker_db:setKeyValue("Beam weapon 345:100","Rng:1 Dmg:6 Cyc:6 Tur:6")
650	striker_db:setKeyValue("Beam weapon 15:100","Rng:1 Dmg:6 Cyc:6 Tur:6")
651	striker_db:setImage("radar_adv_striker.png")
652--	ZX-Lindworm
653	fighter_stock_db:addEntry("ZX-Lindworm")
654	local zx_lindworm_db = queryScienceDatabase("Ships","Mainstream","Starfighter","ZX-Lindworm")
655	zx_lindworm_db:setLongDescription("The ZX model is an improvement on the WX-Lindworm with stronger hull and shields, faster impulse and tubes, more missiles and a single weak, turreted beam. The 'Worm' as it's often called, is a bomber-class starfighter. While one of the least-shielded starfighters in active duty, the Worm's launchers can pack quite a punch. Its goal is to fly in, destroy its target, and fly out or be destroyed.")
656	zx_lindworm_db:setKeyValue("Class","Starfighter")
657	zx_lindworm_db:setKeyValue("Sub-class","Bomber")
658	zx_lindworm_db:setKeyValue("Size","30")
659	zx_lindworm_db:setKeyValue("Shield","40")
660	zx_lindworm_db:setKeyValue("Hull","75")
661	zx_lindworm_db:setKeyValue("Repair Crew",1)
662	zx_lindworm_db:setKeyValue("Warp Speed","57 U/min")	--950 (added for scenario)
663	zx_lindworm_db:setKeyValue("Battery Capacity",400)
664	zx_lindworm_db:setKeyValue("Sensor Ranges","Long: 18 U / Short: 5.5 U")
665	zx_lindworm_db:setKeyValue("Move speed","4.2 U/min")	--70	(value * 60 / 1000 = units per minute)
666	zx_lindworm_db:setKeyValue("Turn speed","15 deg/sec")
667	zx_lindworm_db:setKeyValue("Beam weapon 180:270","Rng:.7 Dmg:2 Cyc:6")
668	zx_lindworm_db:setKeyValue("Small Tube 0","10 sec")
669	zx_lindworm_db:setKeyValue("Small Tube 359","10 sec")
670	zx_lindworm_db:setKeyValue("Small Tube 1","10 sec")
671	zx_lindworm_db:setKeyValue("Storage Homing","3")
672	zx_lindworm_db:setKeyValue("Storage HVLI","12")
673	zx_lindworm_db:setImage("radar_fighter.png")
674----	Frigates
675	local frigate_stock_db = stock_db:addEntry("Frigate")
676	frigate_stock_db:setLongDescription(generic_frigate_description)
677--	Flavia P.Falcon
678	frigate_stock_db:addEntry("Flavia P.Falcon")
679	local flavia_p_falcon_db = queryScienceDatabase("Ships","Mainstream","Frigate","Flavia P.Falcon")
680	flavia_p_falcon_db:setLongDescription("Popular among traders and smugglers, the Flavia is a small cargo and passenger transport. It's cheaper than a freighter for small loads and short distances, and is often used to carry high-value cargo discreetly.\n\nThe Flavia Falcon is a Flavia transport modified for faster flight, and adds rear-mounted lasers to keep enemies off its back.\n\nThe Flavia P.Falcon has a nuclear-capable rear-facing weapon tube and a warp drive.")
681	flavia_p_falcon_db:setKeyValue("Class","Frigate")
682	flavia_p_falcon_db:setKeyValue("Sub-class","Cruiser: Light Transport")
683	flavia_p_falcon_db:setKeyValue("Size","80")
684	flavia_p_falcon_db:setKeyValue("Shield","70/70")
685	flavia_p_falcon_db:setKeyValue("Hull","100")
686	flavia_p_falcon_db:setKeyValue("Repair Crew",8)
687	flavia_p_falcon_db:setKeyValue("Warp Speed","30 U/min")	--500
688	flavia_p_falcon_db:setKeyValue("Sensor Ranges","Long: 40 U / Short: 5 U")
689	flavia_p_falcon_db:setKeyValue("Move speed","3.6 U/min")	--60
690	flavia_p_falcon_db:setKeyValue("Turn speed","10 deg/sec")
691	flavia_p_falcon_db:setKeyValue("Beam weapon 170:40","Rng:1.2 Dmg:6 Cyc:6")
692	flavia_p_falcon_db:setKeyValue("Beam weapon 190:40","Rng:1.2 Dmg:6 Cyc:6")
693	flavia_p_falcon_db:setKeyValue("Tube 180","20 sec")
694	flavia_p_falcon_db:setKeyValue("Storage Homing","3")
695	flavia_p_falcon_db:setKeyValue("Storage Nuke","1")
696	flavia_p_falcon_db:setKeyValue("Storage Mine","1")
697	flavia_p_falcon_db:setKeyValue("Storage HVLI","5")
698	flavia_p_falcon_db:setImage("radar_tug.png")
699--	Hathcock
700	frigate_stock_db:addEntry("Hathcock")
701	local hathcock_db = queryScienceDatabase("Ships","Mainstream","Frigate","Hathcock")
702	hathcock_db:setLongDescription("Long range narrow beam and some point defense beams, broadside missiles. Agile for a frigate")
703	hathcock_db:setKeyValue("Class","Frigate")
704	hathcock_db:setKeyValue("Sub-class","Cruiser: Sniper")
705	hathcock_db:setKeyValue("Size","80")
706	hathcock_db:setKeyValue("Shield","70/70")
707	hathcock_db:setKeyValue("Hull","120")
708	hathcock_db:setKeyValue("Repair Crew",2)
709	hathcock_db:setKeyValue("Jump Range","6 - 60 U")	--modified for scenario
710	hathcock_db:setKeyValue("Sensor Ranges","Long: 35 U / Short: 6 U")
711	hathcock_db:setKeyValue("Move speed","3 U/min")	--50
712	hathcock_db:setKeyValue("Turn speed","15 deg/sec")
713	hathcock_db:setKeyValue("Beam weapon 0:4","Rng:1.4 Dmg:4 Cyc:6")
714	hathcock_db:setKeyValue("Beam weapon 0:20","Rng:1.2 Dmg:4 Cyc:6")
715	hathcock_db:setKeyValue("Beam weapon 0:60","Rng:1.0 Dmg:4 Cyc:6")
716	hathcock_db:setKeyValue("Beam weapon 0:90","Rng:0.8 Dmg:4 Cyc:6")
717	hathcock_db:setKeyValue("Tube 270","15 sec")
718	hathcock_db:setKeyValue("Tube 90","15 sec")
719	hathcock_db:setKeyValue("Storage Homing","4")
720	hathcock_db:setKeyValue("Storage Nuke","1")
721	hathcock_db:setKeyValue("Storage EMP","2")
722	hathcock_db:setKeyValue("Storage HVLI","8")
723	hathcock_db:setImage("radar_piranha.png")
724--	Nautilus
725	frigate_stock_db:addEntry("Nautilus")
726	local nautilus_db = queryScienceDatabase("Ships","Mainstream","Frigate","Nautilus")
727	nautilus_db:setLongDescription("Small mine laying vessel with minimal armament, shields and hull")
728	nautilus_db:setKeyValue("Class","Frigate")
729	nautilus_db:setKeyValue("Sub-class","Mine Layer")
730	nautilus_db:setKeyValue("Size","80")
731	nautilus_db:setKeyValue("Shield","60/60")
732	nautilus_db:setKeyValue("Hull","100")
733	nautilus_db:setKeyValue("Repair Crew",4)
734	nautilus_db:setKeyValue("Jump Range","5 - 70 U")	--modified for scenario
735	nautilus_db:setKeyValue("Sensor Ranges","Long: 22 U / Short: 4 U")
736	nautilus_db:setKeyValue("Move speed","6 U/min")	--100
737	nautilus_db:setKeyValue("Turn speed","10 deg/sec")
738	nautilus_db:setKeyValue("Beam weapon 35:90","Rng:1 Dmg:6 Cyc:6 Tur:6")
739	nautilus_db:setKeyValue("Beam weapon 325:90","Rng:1 Dmg:6 Cyc:6 Tur:6")
740	nautilus_db:setKeyValue("Tube 180","10 sec / Mine")
741	nautilus_db:setKeyValue(" Tube 180","10 sec / Mine")
742	nautilus_db:setKeyValue("  Tube 180","10 sec / Mine")
743	nautilus_db:setKeyValue("Storage Mine","12")
744	nautilus_db:setImage("radar_tug.png")
745--	Phobos M3P
746	frigate_stock_db:addEntry("Phobos M3P")
747	local phobos_m3p_db = queryScienceDatabase("Ships","Mainstream","Frigate","Phobos M3P")
748	phobos_m3p_db:setLongDescription("Player variant of the Phobos M3. Not as strong as the Atlantis, but has front firing tubes, making it an easier to use ship in some scenarios.")
749	phobos_m3p_db:setKeyValue("Class","Frigate")
750	phobos_m3p_db:setKeyValue("Sub-class","Cruiser")
751	phobos_m3p_db:setKeyValue("Size","80")
752	phobos_m3p_db:setKeyValue("Shield","100/100")
753	phobos_m3p_db:setKeyValue("Hull","200")
754	phobos_m3p_db:setKeyValue("Repair Crew",3)
755	phobos_m3p_db:setKeyValue("Warp Speed","54 U/min")	--900 (added for scenario)
756	phobos_m3p_db:setKeyValue("Sensor Ranges","Long: 25 U / Short: 5 U")
757	phobos_m3p_db:setKeyValue("Move speed","4.8 U/min")	--80
758	phobos_m3p_db:setKeyValue("Turn speed","10 deg/sec")
759	phobos_m3p_db:setKeyValue("Beam weapon 345:90","Rng:1.2 Dmg:6 Cyc:8")
760	phobos_m3p_db:setKeyValue("Beam weapon 15:90","Rng:1.2 Dmg:6 Cyc:8")
761	phobos_m3p_db:setKeyValue("Tube 359","10 sec")
762	phobos_m3p_db:setKeyValue("Tube 1","10 sec")
763	phobos_m3p_db:setKeyValue("Tube 180","10 sec / Mine")
764	phobos_m3p_db:setKeyValue("Storage Homing","10")
765	phobos_m3p_db:setKeyValue("Storage Nuke","2")
766	phobos_m3p_db:setKeyValue("Storage Mine","4")
767	phobos_m3p_db:setKeyValue("Storage EMP","3")
768	phobos_m3p_db:setKeyValue("Storage HVLI","20")
769	phobos_m3p_db:setImage("radar_cruiser.png")
770--	Piranha
771	frigate_stock_db:addEntry("Piranha")
772	local piranha_db = queryScienceDatabase("Ships","Mainstream","Frigate","Piranha")
773	piranha_db:setLongDescription("This combat-specialized Piranha F12 adds mine-laying tubes, combat maneuvering systems, and a jump drive.")
774	piranha_db:setKeyValue("Class","Frigate")
775	piranha_db:setKeyValue("Sub-class","Cruiser: Light Artillery")
776	piranha_db:setKeyValue("Size","80")
777	piranha_db:setKeyValue("Shield","70/70")
778	piranha_db:setKeyValue("Hull","120")
779	piranha_db:setKeyValue("Repair Crew",2)
780	piranha_db:setKeyValue("Jump Range","5 - 50 U")
781	piranha_db:setKeyValue("Sensor Ranges","Long: 25 U / Short: 6 U")
782	piranha_db:setKeyValue("Move speed","3.6 U/min")	--60
783	piranha_db:setKeyValue("Turn speed","10 deg/sec")
784	piranha_db:setKeyValue("Large Tube 270","8 sec / Homing,HVLI")
785	piranha_db:setKeyValue("Tube 270","8 sec")
786	piranha_db:setKeyValue(" LargeTube 270","8 sec / Homing,HVLI")
787	piranha_db:setKeyValue("Large Tube 90","8 sec / Homing,HVLI")
788	piranha_db:setKeyValue("Tube 90","8 sec")
789	piranha_db:setKeyValue(" LargeTube 90","8 sec / Homing,HVLI")
790	piranha_db:setKeyValue("Tube 170","8 sec / Mine")
791	piranha_db:setKeyValue("Tube 190","8 sec / Mine")
792	piranha_db:setKeyValue("Storage Homing","12")
793	piranha_db:setKeyValue("Storage Nuke","6")
794	piranha_db:setKeyValue("Storage Mine","8")
795	piranha_db:setKeyValue("Storage HVLI","20")
796	piranha_db:setImage("radar_piranha.png")
797--	Repulse
798	frigate_stock_db:addEntry("Repulse")
799	local repulse_db = queryScienceDatabase("Ships","Mainstream","Frigate","Repulse")
800	repulse_db:setLongDescription("A Flavia P. Falcon with better hull and shields, a jump drive, two turreted beams covering both sides and a forward and rear tube. The nukes and mines are gone")
801	repulse_db:setKeyValue("Class","Frigate")
802	repulse_db:setKeyValue("Sub-class","Cruiser: Armored Transport")
803	repulse_db:setKeyValue("Size","80")
804	repulse_db:setKeyValue("Shield","80/80")
805	repulse_db:setKeyValue("Hull","120")
806	repulse_db:setKeyValue("Repair Crew",8)
807	repulse_db:setKeyValue("Jump Range","5 - 50 U")
808	repulse_db:setKeyValue("Sensor Ranges","Long: 38 U / Short: 5 U")
809	repulse_db:setKeyValue("Move speed","3.3 U/min")	--55
810	repulse_db:setKeyValue("Turn speed","9 deg/sec")
811	repulse_db:setKeyValue("Beam weapon 90:200","Rng:1.2 Dmg:5 Cyc:6")
812	repulse_db:setKeyValue("Beam weapon 270:200","Rng:1.2 Dmg:5 Cyc:6")
813	repulse_db:setKeyValue("Tube 0","20 sec")
814	repulse_db:setKeyValue("Tube 180","20 sec")
815	repulse_db:setKeyValue("Storage Homing","4")
816	repulse_db:setKeyValue("Storage HVLI","6")
817	repulse_db:setImage("radar_tug.png")
818----	Corvettes
819	local corvette_stock_db = stock_db:addEntry("Corvette")
820	corvette_stock_db:setLongDescription(generic_corvette_description)
821--	Atlantis
822	corvette_stock_db:addEntry("Atlantis")
823	local atlantis_db = queryScienceDatabase("Ships","Mainstream","Corvette","Atlantis")
824	atlantis_db:setLongDescription("A refitted Atlantis X23 for more general tasks. The large shield system has been replaced with an advanced combat maneuvering systems and improved impulse engines. Its missile loadout is also more diverse. Mistaking the modified Atlantis for an Atlantis X23 would be a deadly mistake.")
825	atlantis_db:setKeyValue("Class","Corvette")
826	atlantis_db:setKeyValue("Sub-class","Destroyer")
827	atlantis_db:setKeyValue("Size","200")
828	atlantis_db:setKeyValue("Shield","200/200")
829	atlantis_db:setKeyValue("Hull","250")
830	atlantis_db:setKeyValue("Repair Crew",3)
831	atlantis_db:setKeyValue("Jump Range","5 - 50 U")
832	atlantis_db:setKeyValue("Sensor Ranges","Long: 30 U / Short: 5 U")
833	atlantis_db:setKeyValue("Move speed","5.4 U/min")	--100
834	atlantis_db:setKeyValue("Turn speed","10 deg/sec")
835	atlantis_db:setKeyValue("Beam weapon 340:100","Rng:1.5 Dmg:8 Cyc:6")
836	atlantis_db:setKeyValue("Beam weapon 20:100","Rng:1.5 Dmg:8 Cyc:6")
837	atlantis_db:setKeyValue("Tube 270","10 sec")
838	atlantis_db:setKeyValue(" Tube 270","10 sec")
839	atlantis_db:setKeyValue("Tube 90","10 sec")
840	atlantis_db:setKeyValue(" Tube 90","10 sec")
841	atlantis_db:setKeyValue("Tube 180","10 sec / Mine")
842	atlantis_db:setKeyValue("Storage Homing","12")
843	atlantis_db:setKeyValue("Storage Nuke","4")
844	atlantis_db:setKeyValue("Storage Mine","8")
845	atlantis_db:setKeyValue("Storage EMP","6")
846	atlantis_db:setKeyValue("Storage HVLI","20")
847	atlantis_db:setImage("radar_dread.png")
848--	Benedict
849	corvette_stock_db:addEntry("Benedict")
850	local benedict_db = queryScienceDatabase("Ships","Mainstream","Corvette","Benedict")
851	benedict_db:setLongDescription("Benedict is Jump Carrier with a shorter range, but with stronger shields and hull and with minimal armament")
852	benedict_db:setKeyValue("Class","Corvette")
853	benedict_db:setKeyValue("Sub-class","Freighter/Carrier")
854	benedict_db:setKeyValue("Size","200")
855	benedict_db:setKeyValue("Shield","70/70")
856	benedict_db:setKeyValue("Hull","200")
857	benedict_db:setKeyValue("Repair Crew",6)
858	benedict_db:setKeyValue("Jump Range","5 - 90 U")
859	benedict_db:setKeyValue("Sensor Ranges","Long: 30 U / Short: 5 U")
860	benedict_db:setKeyValue("Move speed","3.6 U/min")	--60
861	benedict_db:setKeyValue("Turn speed","6 deg/sec")
862	benedict_db:setKeyValue("Beam weapon 0:90","Rng:1.5 Dmg:4 Cyc:6 Tur:6")
863	benedict_db:setKeyValue("Beam weapon 180:90","Rng:1.5 Dmg:4 Cyc:6 Tur:6")
864	benedict_db:setImage("radar_transport.png")
865--	Crucible
866	corvette_stock_db:addEntry("Crucible")
867	local crucible_db = queryScienceDatabase("Ships","Mainstream","Corvette","Crucible")
868	crucible_db:setLongDescription("A number of missile tubes range around this ship. Beams were deemed lower priority, though they are still present. Stronger defenses than a frigate, but not as strong as the Atlantis")
869	crucible_db:setKeyValue("Class","Corvette")
870	crucible_db:setKeyValue("Sub-class","Popper")
871	crucible_db:setKeyValue("Size","80")
872	crucible_db:setKeyValue("Shield","160/160")
873	crucible_db:setKeyValue("Hull","160")
874	crucible_db:setKeyValue("Repair Crew",4)
875	crucible_db:setKeyValue("Warp Speed","45 U/min")	--750
876	crucible_db:setKeyValue("Sensor Ranges","Long: 20 U / Short: 6 U")
877	crucible_db:setKeyValue("Move speed","4.8 U/min")	--80
878	crucible_db:setKeyValue("Turn speed","15 deg/sec")
879	crucible_db:setKeyValue("Beam weapon 330:70","Rng:1 Dmg:5 Cyc:6")
880	crucible_db:setKeyValue("Beam weapon 30:70","Rng:1 Dmg:5 Cyc:6")
881	crucible_db:setKeyValue("Small Tube 0","8 sec / HVLI")
882	crucible_db:setKeyValue("Tube 0","8 sec / HVLI")
883	crucible_db:setKeyValue("Large Tube 0","8 sec / HVLI")
884	crucible_db:setKeyValue("Tube 270","8 sec")
885	crucible_db:setKeyValue("Tube 90","8 sec")
886	crucible_db:setKeyValue("Tube 180","8 sec / Mine")
887	crucible_db:setKeyValue("Storage Missiles","H:8 N:4 M:6 E:6 L:24")
888	crucible_db:setImage("radar_laser.png")
889--	Kiriya
890	corvette_stock_db:addEntry("Kiriya")
891	local kiriya_db = queryScienceDatabase("Ships","Mainstream","Corvette","Kiriya")
892	kiriya_db:setLongDescription("Kiriya is Warp Carrier based on the jump carrier with stronger shields and hull and with minimal armament")
893	kiriya_db:setKeyValue("Class","Corvette")
894	kiriya_db:setKeyValue("Sub-class","Freighter/Carrier")
895	kiriya_db:setKeyValue("Size","200")
896	kiriya_db:setKeyValue("Shield","70/70")
897	kiriya_db:setKeyValue("Hull","200")
898	kiriya_db:setKeyValue("Repair Crew",6)
899	kiriya_db:setKeyValue("Warp Speed","45 U/min")	--750
900	kiriya_db:setKeyValue("Sensor Ranges","Long: 35 U / Short: 5 U")
901	kiriya_db:setKeyValue("Move speed","3.6 U/min")	--60
902	kiriya_db:setKeyValue("Turn speed","6 deg/sec")
903	kiriya_db:setKeyValue("Beam weapon 0:90","Rng:1.5 Dmg:4 Cyc:6 Tur:6")
904	kiriya_db:setKeyValue("Beam weapon 180:90","Rng:1.5 Dmg:4 Cyc:6 Tur:6")
905	kiriya_db:setImage("radar_transport.png")
906--	Maverick
907	corvette_stock_db:addEntry("Maverick")
908	local maverick_db = queryScienceDatabase("Ships","Mainstream","Corvette","Maverick")
909	maverick_db:setLongDescription("A number of beams bristle from various points on this gunner. Missiles were deemed lower priority, though they are still present. Stronger defenses than a frigate, but not as strong as the Atlantis")
910	maverick_db:setKeyValue("Class","Corvette")
911	maverick_db:setKeyValue("Sub-class","Gunner")
912	maverick_db:setKeyValue("Size","80")
913	maverick_db:setKeyValue("Shield","160/160")
914	maverick_db:setKeyValue("Hull","160")
915	maverick_db:setKeyValue("Repair Crew",4)
916	maverick_db:setKeyValue("Warp Speed","48 U/min")	--800
917	maverick_db:setKeyValue("Sensor Ranges","Long: 20 U / Short: 4 U")
918	maverick_db:setKeyValue("Move speed","4.8 U/min")	--80
919	maverick_db:setKeyValue("Turn speed","15 deg/sec")
920	maverick_db:setKeyValue("Beam weapon 0:10","Rng:2 Dmg:6 Cyc:6")
921	maverick_db:setKeyValue("Beam weapon 340:90","Rng:1.5 Dmg:8 Cyc:6")
922	maverick_db:setKeyValue("Beam weapon 20:90","Rng:1.5 Dmg:8 Cyc:6")
923	maverick_db:setKeyValue("Beam weapon 290:40","Rng:1 Dmg:6 Cyc:4")
924	maverick_db:setKeyValue("Beam weapon 70:40","Rng:1 Dmg:6 Cyc:4")
925	maverick_db:setKeyValue("Beam weapon 180:180","Rng:.8 Dmg:4 Cyc:6 Tur:.5")
926	maverick_db:setKeyValue("Tube 270","8 sec")
927	maverick_db:setKeyValue("Tube 90","8 sec")
928	maverick_db:setKeyValue("Tube 180","8 sec / Mine")
929	maverick_db:setKeyValue("Storage Missiles","H:6 N:2 M:2 E:4 L:10")
930	maverick_db:setImage("radar_laser.png")
931--	Player Cruiser
932	corvette_stock_db:addEntry("Player Cruiser")
933	local player_cruiser_db = queryScienceDatabase("Ships","Mainstream","Corvette","Player Cruiser")
934	player_cruiser_db:setLongDescription("A fairly standard cruiser. Stronger than average beams, weaker than average shields, farther than average jump drive range")
935	player_cruiser_db:setKeyValue("Class","Corvette")
936	player_cruiser_db:setKeyValue("Size","200")
937	player_cruiser_db:setKeyValue("Shield","80/80")
938	player_cruiser_db:setKeyValue("Hull","200")
939	player_cruiser_db:setKeyValue("Repair Crew",3)
940	player_cruiser_db:setKeyValue("Jump Range","5 - 80 U")	--modified for scenario
941	player_cruiser_db:setKeyValue("Sensor Ranges","Long: 30 U / Short: 5 U")
942	player_cruiser_db:setKeyValue("Move speed","5.4 U/min")	--90
943	player_cruiser_db:setKeyValue("Turn speed","10 deg/sec")
944	player_cruiser_db:setKeyValue("Beam weapon 345:90","Rng:1 Dmg:10 Cyc:6")
945	player_cruiser_db:setKeyValue("Beam weapon 15:90","Rng:1 Dmg:10 Cyc:6")
946	player_cruiser_db:setKeyValue("Tube 355","8 sec")
947	player_cruiser_db:setKeyValue("Tube 5","8 sec")
948	player_cruiser_db:setKeyValue("Tube 180","8 sec / Mine")
949	player_cruiser_db:setKeyValue("Storage Homing","12")
950	player_cruiser_db:setKeyValue("Storage Nuke","4")
951	player_cruiser_db:setKeyValue("Storage Mine","8")
952	player_cruiser_db:setKeyValue("Storage EMP","6")
953	player_cruiser_db:setImage("radar_cruiser.png")
954--	Player Missile Cruiser
955	corvette_stock_db:addEntry("Player Missile Cr.")
956	local player_missile_cruiser_db = queryScienceDatabase("Ships","Mainstream","Corvette","Player Missile Cr.")
957	player_missile_cruiser_db:setLongDescription("It's all about the missiles for this model. Broadside tubes shoot homing missiles (30!), front, homing, EMP and nuke. Comparatively weak shields, especially in the rear. Sluggish impulse drive.")
958	player_missile_cruiser_db:setKeyValue("Class","Corvette")
959	player_missile_cruiser_db:setKeyValue("Size","100")
960	player_missile_cruiser_db:setKeyValue("Shield","110/70")
961	player_missile_cruiser_db:setKeyValue("Hull","200")
962	player_missile_cruiser_db:setKeyValue("Repair Crew",3)
963	player_missile_cruiser_db:setKeyValue("Warp Speed","48 U/min")	--800
964	player_missile_cruiser_db:setKeyValue("Sensor Ranges","Long: 35 U / Short: 6 U")
965	player_missile_cruiser_db:setKeyValue("Move speed","3.6 U/min")	--60
966	player_missile_cruiser_db:setKeyValue("Turn speed","8 deg/sec")
967	player_missile_cruiser_db:setKeyValue("Tube 0","8 sec")
968	player_missile_cruiser_db:setKeyValue(" Tube 0","8 sec")
969	player_missile_cruiser_db:setKeyValue("Tube 90","8 sec / Homing")
970	player_missile_cruiser_db:setKeyValue(" Tube 90","8 sec / Homing")
971	player_missile_cruiser_db:setKeyValue("Tube 270","8 sec / Homing")
972	player_missile_cruiser_db:setKeyValue(" Tube 270","8 sec / Homing")
973	player_missile_cruiser_db:setKeyValue("Tube 180","8 sec / Mine")
974	player_missile_cruiser_db:setKeyValue("Storage Homing","30")
975	player_missile_cruiser_db:setKeyValue("Storage Nuke","8")
976	player_missile_cruiser_db:setKeyValue("Storage Mine","12")
977	player_missile_cruiser_db:setKeyValue("Storage EMP","10")
978	player_missile_cruiser_db:setImage("radar_cruiser.png")
979---------------------------
980--	Custom player ships  --
981---------------------------
982	local prototype_db = ships_db:addEntry("Prototype")
983	prototype_db = queryScienceDatabase("Ships","Prototype")
984	prototype_db:setLongDescription("Prototype ships are those that are under development or are otherwise considered experimental. Some have been through several iterations after being tested in the field. Many have been scrapped due to poor design, the ravages of space or perhaps the simple passage of time.")
985	prototype_db:setImage("gui/icons/station-engineering.png")
986----	Starfighters
987	local fighter_prototype_db = prototype_db:addEntry("Starfighter")
988	fighter_prototype_db:setLongDescription(generic_starfighter_description)
989--	Striker LX
990	fighter_prototype_db:addEntry("Striker LX")
991	local striker_lx_db = queryScienceDatabase("Ships","Prototype","Starfighter","Striker LX")
992	striker_lx_db:setLongDescription("The Striker is the predecessor to the advanced striker, slow but agile, but does not do an extreme amount of damage, and lacks in shields. The Striker LX is a modification of the Striker: stronger shields, more energy, jump drive (vs none), faster impulse, slower turret, two rear tubes (vs none)")
993	striker_lx_db:setKeyValue("Class","Starfighter")
994	striker_lx_db:setKeyValue("Sub-class","Patrol")
995	striker_lx_db:setKeyValue("Size","140")
996	striker_lx_db:setKeyValue("Shield","100/100")
997	striker_lx_db:setKeyValue("Hull","100")
998	striker_lx_db:setKeyValue("Repair Crew",3)
999	striker_lx_db:setKeyValue("Battery Capacity",600)
1000	striker_lx_db:setKeyValue("Jump Range","2 - 20 U")
1001	striker_lx_db:setKeyValue("Sensor Ranges","Long: 20 U / Short: 4 U")
1002	striker_lx_db:setKeyValue("Move speed","3.9 U/min")	--65	(value * 60 / 1000 = units per minute)
1003	striker_lx_db:setKeyValue("Turn speed","35 deg/sec")
1004	striker_lx_db:setKeyValue("Beam weapon 345:100","Rng:1.1 Dmg:6.5 Cyc:6 Tur:.2")
1005	striker_lx_db:setKeyValue("Beam weapon 15:100","Rng:1.1 Dmg:6.5 Cyc:6 Tur:.2")
1006	striker_lx_db:setKeyValue("Tube 180","10 sec")
1007	striker_lx_db:setKeyValue(" Tube 180","10 sec")
1008	striker_lx_db:setKeyValue("Storage Homing","4")
1009	striker_lx_db:setKeyValue("Storage Nuke","2")
1010	striker_lx_db:setKeyValue("Storage Mine","3")
1011	striker_lx_db:setKeyValue("Storage EMP","3")
1012	striker_lx_db:setKeyValue("Storage HVLI","6")
1013	striker_lx_db:setImage("radar_adv_striker.png")
1014----	Frigates
1015	local frigate_prototype_db = prototype_db:addEntry("Frigate")
1016	frigate_prototype_db:setLongDescription(generic_frigate_description)
1017--	Phobos T2
1018	frigate_prototype_db:addEntry("Phobos T2")
1019	local phobos_t2_db = queryScienceDatabase("Ships","Prototype","Frigate","Phobos T2")
1020	phobos_t2_db:setLongDescription("Based on Phobos M3P with these differences: more repair crew, a jump drive, faster spin, stronger front shield, weaker rear shield, less maximum energy, turreted and faster beams, one fewer tube forward, and fewer missiles")
1021	phobos_t2_db:setKeyValue("Class","Frigate")
1022	phobos_t2_db:setKeyValue("Sub-class","Cruiser")
1023	phobos_t2_db:setKeyValue("Size","80")
1024	phobos_t2_db:setKeyValue("Shield","120/80")
1025	phobos_t2_db:setKeyValue("Hull","200")
1026	phobos_t2_db:setKeyValue("Repair Crew",4)
1027	phobos_t2_db:setKeyValue("Battery Capacity",800)
1028	phobos_t2_db:setKeyValue("Jump Range","2 - 25 U")
1029	phobos_t2_db:setKeyValue("Sensor Ranges","Long: 25 U / Short: 5 U")
1030	phobos_t2_db:setKeyValue("Move speed","4.8 U/min")	--80
1031	phobos_t2_db:setKeyValue("Turn speed","20 deg/sec")
1032	phobos_t2_db:setKeyValue("Beam weapon 330:40","Rng:1.2 Dmg:6 Cyc:4 Tur:.2")
1033	phobos_t2_db:setKeyValue("Beam weapon 30:40","Rng:1.2 Dmg:6 Cyc:4 Tur:.2")
1034	phobos_t2_db:setKeyValue("Tube 0","10 sec")
1035	phobos_t2_db:setKeyValue("Tube 180","10 sec / Mine")
1036	phobos_t2_db:setKeyValue("Storage Homing",8)
1037	phobos_t2_db:setKeyValue("Storage Nuke",2)
1038	phobos_t2_db:setKeyValue("Storage Mine",4)
1039	phobos_t2_db:setKeyValue("Storage EMP",3)
1040	phobos_t2_db:setKeyValue("Storage HVLI",16)
1041	phobos_t2_db:setImage("radar_cruiser.png")
1042----	Corvettes
1043	local corvette_prototype_db = prototype_db:addEntry("Corvette")
1044	corvette_prototype_db:setLongDescription(generic_corvette_description)
1045--	Focus
1046	corvette_prototype_db:addEntry("Focus")
1047	local focus_db = queryScienceDatabase("Ships","Prototype","Corvette","Focus")
1048	focus_db:setLongDescription("Adjusted Crucible: short jump drive (no warp), faster impulse and spin, weaker shields and hull, narrower beams, fewer tubes. The large tube accomodates nukes, EMPs and homing missiles")
1049	focus_db:setKeyValue("Class","Corvette")
1050	focus_db:setKeyValue("Sub-class","Popper")
1051	focus_db:setKeyValue("Size","200")
1052	focus_db:setKeyValue("Shield","100/100")
1053	focus_db:setKeyValue("Hull","100")
1054	focus_db:setKeyValue("Repair Crew",4)
1055	focus_db:setKeyValue("Jump Range","2.5 - 25 U")
1056	focus_db:setKeyValue("Sensor Ranges","Long: 32 U / Short: 5 U")
1057	focus_db:setKeyValue("Move speed","4.2 U/min")	--70
1058	focus_db:setKeyValue("Turn speed","20 deg/sec")
1059	focus_db:setKeyValue("Beam weapon 340:60","Rng:1 Dmg:5 Cyc:6")
1060	focus_db:setKeyValue("Beam weapon 20:60","Rng:1 Dmg:5 Cyc:6")
1061	focus_db:setKeyValue("Small Tube 0","8 sec / HVLI")
1062	focus_db:setKeyValue("Tube 0","8 sec / HVLI")
1063	focus_db:setKeyValue("Large Tube 0","8 sec")
1064	focus_db:setKeyValue("Tube 180","8 sec / Mine")
1065	focus_db:setKeyValue("Storage Homing",8)
1066	focus_db:setKeyValue("Storage Nuke",1)
1067	focus_db:setKeyValue("Storage Mine",6)
1068	focus_db:setKeyValue("Storage EMP",2)
1069	focus_db:setKeyValue("Storage HVLI",24)
1070	focus_db:setImage("radar_laser.png")
1071--	Holmes
1072	corvette_prototype_db:addEntry("Holmes")
1073	local holmes_db = queryScienceDatabase("Ships","Prototype","Corvette","Holmes")
1074	holmes_db:setLongDescription("Revised Crucible: weaker shields, side beams, fewer tubes, fewer missiles, EMPs and Nukes in front middle tube and large homing missiles")
1075	holmes_db:setKeyValue("Class","Corvette")
1076	holmes_db:setKeyValue("Sub-class","Popper")
1077	holmes_db:setKeyValue("Size","200")
1078	holmes_db:setKeyValue("Shield","160/160")
1079	holmes_db:setKeyValue("Hull","160")
1080	holmes_db:setKeyValue("Repair Crew",4)
1081	holmes_db:setKeyValue("Warp Speed","45.0 U/min")	--750
1082	holmes_db:setKeyValue("Sensor Ranges","Long: 35 U / Short: 4 U")
1083	holmes_db:setKeyValue("Move speed","4.2 U/min")	--70
1084	holmes_db:setKeyValue("Turn speed","15 deg/sec")
1085	holmes_db:setKeyValue("Beam weapon 275:50","Rng:.9 Dmg:5 Cyc:6")
1086	holmes_db:setKeyValue("Beam weapon 265:50","Rng:.9 Dmg:5 Cyc:6")
1087	holmes_db:setKeyValue("Beam weapon 85:50","Rng:.9 Dmg:5 Cyc:6")
1088	holmes_db:setKeyValue("Beam weapon 95:50","Rng:.9 Dmg:5 Cyc:6")
1089	holmes_db:setKeyValue("Small Tube 0","8 sec / Homing")
1090	holmes_db:setKeyValue("Tube 0","8 sec / Homing")
1091	holmes_db:setKeyValue("Large Tube 0","8 sec / Homing")
1092	holmes_db:setKeyValue("Tube 180","8 sec / Mine")
1093	holmes_db:setKeyValue("Storage Homing",10)
1094	holmes_db:setKeyValue("Storage Mine",6)
1095	holmes_db:setImage("radar_laser.png")
1096--	Maverick XP
1097	corvette_prototype_db:addEntry("Maverick XP")
1098	local maverick_xp_db = queryScienceDatabase("Ships","Prototype","Corvette","Maverick XP")
1099	maverick_xp_db:setLongDescription("Based on Maverick: slower impulse, jump (no warp), one heavy slow turreted beam (not 6 beams)")
1100	maverick_xp_db:setKeyValue("Class","Corvette")
1101	maverick_xp_db:setKeyValue("Sub-class","Gunner")
1102	maverick_xp_db:setKeyValue("Size","200")
1103	maverick_xp_db:setKeyValue("Shield","160/160")
1104	maverick_xp_db:setKeyValue("Hull","160")
1105	maverick_xp_db:setKeyValue("Repair Crew",4)
1106	maverick_xp_db:setKeyValue("Jump Range","2 - 20 U")
1107	maverick_xp_db:setKeyValue("Sensor Ranges","Long: 25 U / Short: 7 U")
1108	maverick_xp_db:setKeyValue("Move speed","3.9 U/min")	--65
1109	maverick_xp_db:setKeyValue("Turn speed","15 deg/sec")
1110	maverick_xp_db:setKeyValue("Beam weapon 0:270","Rng:1 Dmg:20 Cyc:20 Tur:.2")
1111	maverick_xp_db:setKeyValue("Tube 270","8 sec")
1112	maverick_xp_db:setKeyValue("Tube 90","8 sec")
1113	maverick_xp_db:setKeyValue("Tube 180","8 sec / Mine")
1114	maverick_xp_db:setKeyValue("Storage Homing",6)
1115	maverick_xp_db:setKeyValue("Storage Nuke",2)
1116	maverick_xp_db:setKeyValue("Storage Mine",2)
1117	maverick_xp_db:setKeyValue("Storage EMP",4)
1118	maverick_xp_db:setKeyValue("Storage HVLI",10)
1119	maverick_xp_db:setImage("radar_laser.png")
1120
1121end
1122------------------
1123--	GM Buttons  --
1124------------------
1125function setGMButtons()
1126	mainGMButtons = mainGMButtonsDuringPause
1127	mainGMButtons()
1128end
1129function mainGMButtonsDuringPause()
1130	clearGMFunctions()
1131	addGMFunction(string.format("Version %s",scenario_version),function()
1132		local version_message = string.format("Scenario version %s\n LUA version %s",scenario_version,_VERSION)
1133		addGMMessage(version_message)
1134		print(version_message)
1135	end)
1136	if not terrain_generated then
1137		addGMFunction(string.format("+Player Teams: %i",player_team_count),setPlayerTeamCount)
1138		addGMFunction(string.format("+Player Ships: %i (%i)",ships_per_team,ships_per_team*player_team_count),setPlayerShipCount)
1139		addGMFunction(string.format("+P.Ship Types: %s",player_ship_types),setPlayerShipTypes)
1140		local button_label = "+NPC Ships: 0"
1141		if npc_ships then
1142			button_label = string.format("+NPC Ships: %i-%i",npc_lower,npc_upper)
1143		end
1144		addGMFunction(button_label,setNPCShips)
1145		addGMFunction("+Terrain",setTerrainParameters)
1146		addGMFunction(string.format("Respawn: %s",respawn_type),function()
1147			if respawn_type == "lindworm" then
1148				respawn_type = "self"
1149			elseif respawn_type == "self" then
1150				respawn_type = "lindworm"
1151			end
1152			mainGMButtons()
1153		end)
1154	else
1155		addGMFunction("Show control codes",showControlCodes)
1156		addGMFunction("Show Human codes",showHumanCodes)
1157		addGMFunction("Show Kraylor codes",showKraylorCodes)
1158		if exuari_angle ~= nil then
1159			addGMFunction("Show Exuari codes",showExuariCodes)
1160		end
1161		if ktlitan_angle ~= nil then
1162			addGMFunction("Show Ktlitan codes",showKtlitanCodes)
1163		end
1164	end
1165	addGMFunction(string.format("+Stn Sensors %iU",station_sensor_range/1000),setStationSensorRange)
1166	addGMFunction(string.format("+Game Time %i",game_time_limit/60),setGameTimeLimit)
1167end
1168function mainGMButtonsAfterPause()
1169	clearGMFunctions()
1170	addGMFunction(string.format("Version %s",scenario_version),function()
1171		local version_message = string.format("Scenario version %s\n LUA version %s",scenario_version,_VERSION)
1172		addGMMessage(version_message)
1173		print(version_message)
1174	end)
1175	addGMFunction("Show control codes",showControlCodes)
1176	addGMFunction("Show Human codes",showHumanCodes)
1177	addGMFunction("Show Kraylor codes",showKraylorCodes)
1178	if exuari_angle ~= nil then
1179		addGMFunction("Show Exuari codes",showExuariCodes)
1180	end
1181	if ktlitan_angle ~= nil then
1182		addGMFunction("Show Ktlitan codes",showKtlitanCodes)
1183	end
1184	addGMFunction("Statistics Summary",function()
1185		local stat_list = gatherStats()
1186		local out = "Current Scores:"
1187		out = out .. string.format("\n   Human Navy: %.2f (%.1f%%)",stat_list.human.weighted_score,stat_list.human.weighted_score/original_score["Human Navy"]*100)
1188		out = out .. string.format("\n   Kraylor: %.2f (%.1f%%)",stat_list.kraylor.weighted_score,stat_list.kraylor.weighted_score/original_score["Kraylor"]*100)
1189		if exuari_angle ~= nil then
1190			out = out .. string.format("\n   Exuari: %.2f (%.1f%%)",stat_list.exuari.weighted_score,stat_list.exuari.weighted_score/original_score["Exuari"]*100)
1191		end
1192		if ktlitan_angle ~= nil then
1193			out = out .. string.format("\n   Ktlitans: %.2f (%.1f%%)",stat_list.ktlitan.weighted_score,stat_list.ktlitan.weighted_score/original_score["Ktlitans"]*100)
1194		end
1195		local out = out .. "\nOriginal scores:"
1196		out = out .. string.format("\n   Human Navy: %.2f",original_score["Human Navy"])
1197		out = out .. string.format("\n   Kraylor: %.2f",original_score["Kraylor"])
1198		if exuari_angle ~= nil then
1199			out = out .. string.format("\n   Exuari: %.2f",original_score["Exuari"])
1200		end
1201		if ktlitan_angle ~= nil then
1202			out = out .. string.format("\n   Ktlitans: %.2f",original_score["Ktlitans"])
1203		end
1204		addGMMessage(out)
1205	end)
1206	addGMFunction("Statistics Details",function()
1207		local stat_list = gatherStats()
1208		out = "Human Navy:\n    Stations: (score value, type, name)"
1209		print("Human Navy:")
1210		print("    Stations: (score value, type, name)")
1211		for name, details in pairs(stat_list.human.station) do
1212			out = out .. string.format("\n        %i %s %s",details.score_value,details.template_type,name)
1213			print(" ",details.score_value,details.template_type,name)
1214		end
1215		local weighted_stations = stat_list.human.station_score_total * stat_list.weight.station
1216		out = out .. string.format("\n            Station Total:%i Weight:%.1f Weighted total:%.2f",stat_list.human.station_score_total,stat_list.weight.station,weighted_stations)
1217		print("    Station Total:",stat_list.human.station_score_total,"Weight:",stat_list.weight.station,"Weighted Total:",weighted_stations)
1218		out = out .. "\n    Player Ships: (score value, type, name)"
1219		print("    Player Ships: (score value, type, name)")
1220		for name, details in pairs(stat_list.human.ship) do
1221			out = out .. string.format("\n        %i %s %s",details.score_value,details.template_type,name)
1222			print(" ",details.score_value,details.template_type,name)
1223		end
1224		local weighted_players = stat_list.human.ship_score_total * stat_list.weight.ship
1225		out = out .. string.format("\n            Player Ship Total:%i Weight:%.1f Weighted total:%.2f",stat_list.human.ship_score_total,stat_list.weight.ship,weighted_players)
1226		print("    Player Ship Total:",stat_list.human.ship_score_total,"Weight:",stat_list.weight.ship,"Weighted Total:",weighted_players)
1227		out = out .. "\n    NPC Assets: score value, type, name (location)"
1228		print("    NPC Assets: score value, type, name (location)")
1229		for name, details in pairs(stat_list.human.npc) do
1230			if details.template_type ~= nil then
1231				out = out .. string.format("\n        %i %s %s",details.score_value,details.template_type,name)
1232				print(" ",details.score_value,details.template_type,name)
1233			elseif details.topic ~= nil then
1234				out = out .. string.format("\n        %i %s %s (%s)",details.score_value,details.topic,name,details.location_name)
1235				print(" ",details.score_value,details.topic,name,"(" .. details.location_name .. ")")
1236			end
1237		end
1238		local weighted_npcs = stat_list.human.npc_score_total * stat_list.weight.npc
1239		out = out .. string.format("\n            NPC Asset Total:%i Weight:%.1f Weighted total:%.2f",stat_list.human.npc_score_total,stat_list.weight.npc,weighted_npcs)
1240		print("    NPC Asset Total:",stat_list.human.npc_score_total,"Weight:",stat_list.weight.npc,"Weighted Total:",weighted_npcs)
1241		out = out .. string.format("\n----Human weighted total:%.1f Original:%.1f Change:%.2f%%",stat_list.human.weighted_score,original_score["Human Navy"],stat_list.human.weighted_score/original_score["Human Navy"]*100)
1242		print("----Human weighted total:",stat_list.human.weighted_score,"Original:",original_score["Human Navy"],"Change:",stat_list.human.weighted_score/original_score["Human Navy"]*100 .. "%")
1243		out = out .. "\nKraylor:\n    Stations: (score value, type, name)"
1244		print("Kraylor:")
1245		print("    Stations: (score value, type, name)")
1246		for name, details in pairs(stat_list.kraylor.station) do
1247			out = out .. string.format("\n        %i %s %s",details.score_value,details.template_type,name)
1248			print(" ",details.score_value,details.template_type,name)
1249		end
1250		local weighted_stations = stat_list.kraylor.station_score_total * stat_list.weight.station
1251		out = out .. string.format("\n            Station Total:%i Weight:%.1f Weighted total:%.2f",stat_list.kraylor.station_score_total,stat_list.weight.station,weighted_stations)
1252		print("    Station Total:",stat_list.kraylor.station_score_total,"Weight:",stat_list.weight.station,"Weighted Total:",weighted_stations)
1253		out = out .. "\n    Player Ships: (score value, type, name)"
1254		print("    Player Ships: (score value, type, name)")
1255		for name, details in pairs(stat_list.kraylor.ship) do
1256			out = out .. string.format("\n        %i %s %s",details.score_value,details.template_type,name)
1257			print(" ",details.score_value,details.template_type,name)
1258		end
1259		local weighted_players = stat_list.kraylor.ship_score_total * stat_list.weight.ship
1260		out = out .. string.format("\n            Player Ship Total:%i Weight:%.1f Weighted total:%.2f",stat_list.kraylor.ship_score_total,stat_list.weight.ship,weighted_players)
1261		print("    Player Ship Total:",stat_list.kraylor.ship_score_total,"Weight:",stat_list.weight.ship,"Weighted Total:",weighted_players)
1262		out = out .. "\n    NPC Assets: score value, type, name (location)"
1263		print("    NPC Assets: score value, type, name (location)")
1264		for name, details in pairs(stat_list.kraylor.npc) do
1265			if details.template_type ~= nil then
1266				out = out .. string.format("\n        %i %s %s",details.score_value,details.template_type,name)
1267				print(" ",details.score_value,details.template_type,name)
1268			elseif details.topic ~= nil then
1269				out = out .. string.format("\n        %i %s %s (%s)",details.score_value,details.topic,name,details.location_name)
1270				print(" ",details.score_value,details.topic,name,"(" .. details.location_name .. ")")
1271			end
1272		end
1273		local weighted_npcs = stat_list.kraylor.npc_score_total * stat_list.weight.npc
1274		out = out .. string.format("\n            NPC Asset Total:%i Weight:%.1f Weighted total:%.2f",stat_list.kraylor.npc_score_total,stat_list.weight.npc,weighted_npcs)
1275		print("    NPC Asset Total:",stat_list.kraylor.npc_score_total,"Weight:",stat_list.weight.npc,"Weighted Total:",weighted_npcs)
1276		out = out .. string.format("\n----Kraylor weighted total:%.1f Original:%.1f Change:%.2f%%",stat_list.kraylor.weighted_score,original_score["Kraylor"],stat_list.kraylor.weighted_score/original_score["Kraylor"]*100)
1277		print("----Kraylor weighted total:",stat_list.kraylor.weighted_score,"Original:",original_score["Kraylor"],"Change:",stat_list.kraylor.weighted_score/original_score["Kraylor"]*100 .. "%")
1278		if exuari_angle ~= nil then
1279			out = out .. "\nExuari:\n    Stations: (score value, type, name)"
1280			print("Exuari:")
1281			print("    Stations: (score value, type, name)")
1282			for name, details in pairs(stat_list.exuari.station) do
1283				out = out .. string.format("\n        %i %s %s",details.score_value,details.template_type,name)
1284				print(" ",details.score_value,details.template_type,name)
1285			end
1286			local weighted_stations = stat_list.exuari.station_score_total * stat_list.weight.station
1287			out = out .. string.format("\n            Station Total:%i Weight:%.1f Weighted total:%.2f",stat_list.exuari.station_score_total,stat_list.weight.station,weighted_stations)
1288			print("    Station Total:",stat_list.exuari.station_score_total,"Weight:",stat_list.weight.station,"Weighted Total:",weighted_stations)
1289			out = out .. "\n    Player Ships: (score value, type, name)"
1290			print("    Player Ships: (score value, type, name)")
1291			for name, details in pairs(stat_list.exuari.ship) do
1292				out = out .. string.format("\n        %i %s %s",details.score_value,details.template_type,name)
1293				print(" ",details.score_value,details.template_type,name)
1294			end
1295			local weighted_players = stat_list.exuari.ship_score_total * stat_list.weight.ship
1296			out = out .. string.format("\n            Player Ship Total:%i Weight:%.1f Weighted total:%.2f",stat_list.exuari.ship_score_total,stat_list.weight.ship,weighted_players)
1297			print("    Player Ship Total:",stat_list.exuari.ship_score_total,"Weight:",stat_list.weight.ship,"Weighted Total:",weighted_players)
1298			out = out .. "\n    NPC Assets: score value, type, name (location)"
1299			print("    NPC Assets: score value, type, name (location)")
1300			for name, details in pairs(stat_list.exuari.npc) do
1301				if details.template_type ~= nil then
1302					out = out .. string.format("\n        %i %s %s",details.score_value,details.template_type,name)
1303					print(" ",details.score_value,details.template_type,name)
1304				elseif details.topic ~= nil then
1305					out = out .. string.format("\n        %i %s %s (%s)",details.score_value,details.topic,name,details.location_name)
1306					print(" ",details.score_value,details.topic,name,"(" .. details.location_name .. ")")
1307				end
1308			end
1309			local weighted_npcs = stat_list.exuari.npc_score_total * stat_list.weight.npc
1310			out = out .. string.format("\n            NPC Asset Total:%i Weight:%.1f Weighted total:%.2f",stat_list.exuari.npc_score_total,stat_list.weight.npc,weighted_npcs)
1311			print("    NPC Asset Total:",stat_list.exuari.npc_score_total,"Weight:",stat_list.weight.npc,"Weighted Total:",weighted_npcs)
1312			out = out .. string.format("\n----Exuari weighted total:%.1f Original:%.1f Change:%.2f%%",stat_list.exuari.weighted_score,original_score["Exuari"],stat_list.exuari.weighted_score/original_score["Exuari"]*100)
1313			print("----Exuari weighted total:",stat_list.exuari.weighted_score,"Original:",original_score["Exuari"],"Change:",stat_list.exuari.weighted_score/original_score["Exuari"]*100 .. "%")
1314		end
1315		if ktlitan_angle ~= nil then
1316			out = out .. "\nKtlitan:\n    Stations: (score value, type, name)"
1317			print("Ktlitan:")
1318			print("    Stations: (score value, type, name)")
1319			for name, details in pairs(stat_list.ktlitan.station) do
1320				out = out .. string.format("\n        %i %s %s",details.score_value,details.template_type,name)
1321				print(" ",details.score_value,details.template_type,name)
1322			end
1323			local weighted_stations = stat_list.ktlitan.station_score_total * stat_list.weight.station
1324			out = out .. string.format("\n            Station Total:%i Weight:%.1f Weighted total:%.2f",stat_list.ktlitan.station_score_total,stat_list.weight.station,weighted_stations)
1325			print("    Station Total:",stat_list.ktlitan.station_score_total,"Weight:",stat_list.weight.station,"Weighted Total:",weighted_stations)
1326			out = out .. "\n    Player Ships: (score value, type, name)"
1327			print("    Player Ships: (score value, type, name)")
1328			for name, details in pairs(stat_list.ktlitan.ship) do
1329				out = out .. string.format("\n        %i %s %s",details.score_value,details.template_type,name)
1330				print(" ",details.score_value,details.template_type,name)
1331			end
1332			local weighted_players = stat_list.ktlitan.ship_score_total * stat_list.weight.ship
1333			out = out .. string.format("\n            Player Ship Total:%i Weight:%.1f Weighted total:%.2f",stat_list.ktlitan.ship_score_total,stat_list.weight.ship,weighted_players)
1334			print("    Player Ship Total:",stat_list.ktlitan.ship_score_total,"Weight:",stat_list.weight.ship,"Weighted Total:",weighted_players)
1335			out = out .. "\n    NPC Assets: score value, type, name (location)"
1336			print("    NPC Assets: score value, type, name (location)")
1337			for name, details in pairs(stat_list.ktlitan.npc) do
1338				if details.template_type ~= nil then
1339					out = out .. string.format("\n        %i %s %s",details.score_value,details.template_type,name)
1340					print(" ",details.score_value,details.template_type,name)
1341				elseif details.topic ~= nil then
1342					out = out .. string.format("\n        %i %s %s (%s)",details.score_value,details.topic,name,details.location_name)
1343					print(" ",details.score_value,details.topic,name,"(" .. details.location_name .. ")")
1344				end
1345			end
1346			local weighted_npcs = stat_list.ktlitan.npc_score_total * stat_list.weight.npc
1347			out = out .. string.format("\n            NPC Asset Total:%i Weight:%.1f Weighted total:%.2f",stat_list.ktlitan.npc_score_total,stat_list.weight.npc,weighted_npcs)
1348			print("    NPC Asset Total:",stat_list.ktlitan.npc_score_total,"Weight:",stat_list.weight.npc,"Weighted Total:",weighted_npcs)
1349			out = out .. string.format("\n----Ktlitan weighted total:%.1f Original:%.1f Change:%.2f%%",stat_list.ktlitan.weighted_score,original_score["Ktlitans"],stat_list.ktlitan.weighted_score/original_score["Ktlitans"]*100)
1350			print("----Ktlitan weighted total:",stat_list.ktlitan.weighted_score,"Original:",original_score["Ktlitans"],"Change:",stat_list.ktlitan.weighted_score/original_score["Ktlitans"]*100 .. "%")
1351		end
1352		addGMMessage(out)
1353	end)
1354end
1355--	Player related GM configuration functions
1356function setPlayerTeamCount()
1357	clearGMFunctions()
1358	addGMFunction("-Main from Teams",mainGMButtons)
1359	local button_label = "2"
1360	if player_team_count == 2 then
1361		button_label = button_label .. "*"
1362	end
1363	addGMFunction(button_label,function()
1364		player_team_count = 2
1365		mainGMButtons()
1366	end)
1367	local button_label = "3"
1368	if player_team_count == 3 then
1369		button_label = button_label .. "*"
1370	end
1371	addGMFunction(button_label,function()
1372		player_team_count = 3
1373		if ships_per_team > max_ships_per_team[player_team_count] then
1374			ships_per_team = max_ships_per_team[player_team_count]
1375			if player_ship_types == "spawned" then
1376				addGMMessage("Switching player ship type to default")
1377				player_ship_types = "default"
1378			end
1379		end
1380		mainGMButtons()
1381	end)
1382	local button_label = "4"
1383	if player_team_count == 4 then
1384		button_label = button_label .. "*"
1385	end
1386	addGMFunction(button_label,function()
1387		player_team_count = 4
1388		if ships_per_team > max_ships_per_team[player_team_count] then
1389			ships_per_team = max_ships_per_team[player_team_count]
1390			if player_ship_types == "spawned" then
1391				addGMMessage("Switching player ship type to default")
1392				player_ship_types = "default"
1393			end
1394		end
1395		mainGMButtons()
1396	end)
1397end
1398function setPlayerShipCount()
1399	clearGMFunctions()
1400	addGMFunction("-Main from Ships",mainGMButtons)
1401	if ships_per_team < max_ships_per_team[player_team_count] then
1402		addGMFunction(string.format("%i ships add -> %i",ships_per_team,ships_per_team + 1),function()
1403			ships_per_team = ships_per_team + 1
1404			if player_ship_types == "spawned" then
1405				addGMMessage("Switching player ship type to default")
1406				player_ship_types = "default"
1407			end
1408			setPlayerShipCount()
1409		end)
1410	end
1411	if ships_per_team > 1 then
1412		addGMFunction(string.format("%i ships del -> %i",ships_per_team,ships_per_team - 1),function()
1413			ships_per_team = ships_per_team - 1
1414			if player_ship_types == "spawned" then
1415				addGMMessage("Switching player ship type to default")
1416				player_ship_types = "default"
1417			end
1418			setPlayerShipCount()
1419		end)
1420	end
1421end
1422function setPlayerShipTypes()
1423	clearGMFunctions()
1424	addGMFunction("-Main from Ship Types",mainGMButtons)
1425	local button_label = "default"
1426	if player_ship_types == button_label then
1427		button_label = button_label .. "*"
1428	end
1429	addGMFunction(button_label,function()
1430		player_ship_types = "default"
1431		local player_plural = "players"
1432		local type_plural = "types"
1433		if ships_per_team == 1 then
1434			player_plural = "player"
1435			type_plural = "type"
1436		end
1437		local out = string.format("Default ship %s for a team of %i %s:",type_plural,ships_per_team,player_plural)
1438		for i=1,ships_per_team do
1439			out = out .. "\n   " .. i .. ") " .. default_player_ship_sets[ships_per_team][i]
1440		end
1441		addGMMessage(out)
1442		setPlayerShipTypes()
1443	end)
1444	button_label = "spawned"
1445	if player_ship_types == button_label then
1446		button_label = button_label .. "*"
1447	end
1448	addGMFunction(button_label,function()
1449		player_ship_types = "spawned"
1450		local out = "Spawned ship type(s):"
1451		local player_count = 0
1452		for pidx=1,32 do
1453			local p = getPlayerShip(pidx)
1454			if p ~= nil and p:isValid() then
1455				player_count = player_count + 1
1456				out = out .. "\n   " .. player_count .. ") " .. p:getTypeName()
1457			end
1458		end
1459		if player_count < ships_per_team then
1460			if player_count == 0 then
1461				out = string.format("%i player ships spawned. %i are required.\n\nUsing default ship set.\n\n%s",player_count,ships_per_team,out)
1462			elseif player_count == 1 then
1463				out = string.format("Only %i player ship spawned. %i are required.\n\nUsing default ship set.\n\n%s",player_count,ships_per_team,out)
1464			else
1465				out = string.format("Only %i player ships spawned. %i are required.\n\nUsing default ship set.\n\n%s",player_count,ships_per_team,out)
1466			end
1467			player_ship_types = "default"
1468		elseif player_count > ships_per_team then
1469			if ships_per_team == 1 then
1470				out = string.format("%i player ships spawned. Only %i is required.\n\nUsing default ship set.\n\n%s",player_count,ships_per_team,out)
1471			else
1472				out = string.format("%i player ships spawned. Only %i are required.\n\nUsing default ship set.\n\n%s",player_count,ships_per_team,out)
1473			end
1474			player_ship_types = "default"
1475		end
1476		addGMMessage(out)
1477		setPlayerShipTypes()
1478	end)
1479	button_label = "custom"
1480	if player_ship_types == button_label then
1481		button_label = button_label .. "*"
1482	end
1483	addGMFunction(string.format("+%s",button_label),setCustomPlayerShipSet)
1484end
1485function setCustomPlayerShipSet()
1486	clearGMFunctions()
1487	addGMFunction("-Main from Custom",mainGMButtons)
1488	addGMFunction("-Ship Types",setPlayerShipTypes)
1489	addGMFunction("+Customize Custom",setCustomSet)
1490	for ship_set_type,list in pairs(custom_player_ship_sets) do
1491		local button_label = ship_set_type
1492		if ship_set_type == custom_player_ship_type then
1493			button_label = button_label .. "*"
1494		end
1495		addGMFunction(button_label,function()
1496			player_ship_types = "custom"
1497			custom_player_ship_type = ship_set_type
1498			local out = ""
1499			if ships_per_team == 1 then
1500				out = string.format("Ship type set %s for %i player:",custom_player_ship_type,ships_per_team)
1501			else
1502				out = string.format("Ship type set %s for %i players:",custom_player_ship_type,ships_per_team)
1503			end
1504			for index, ship_type in ipairs(custom_player_ship_sets[custom_player_ship_type][ships_per_team]) do
1505--				print("index:",index,"ship type:",ship_type)
1506				out = out .. "\n   " .. index .. ") " .. ship_type
1507			end
1508			addGMMessage(out)
1509			setCustomPlayerShipSet()
1510		end)
1511	end
1512end
1513function setCustomSet()
1514	clearGMFunctions()
1515	addGMFunction("-Main from Custom",mainGMButtons)
1516	addGMFunction("-Ship Types",setPlayerShipTypes)
1517	addGMFunction("-Custom Set",setCustomPlayerShipSet)
1518	if template_out == nil then
1519		template_out = custom_player_ship_sets["Custom"][ships_per_team][1]
1520	else
1521		local match_in_set = false
1522		for i=1,#custom_player_ship_sets["Custom"][ships_per_team] do
1523			if custom_player_ship_sets["Custom"][ships_per_team][i] == template_out then
1524				match_in_set = true
1525			end
1526		end
1527		if not match_in_set then
1528			template_out = custom_player_ship_sets["Custom"][ships_per_team][1]
1529		end
1530	end
1531	if template_in == nil then
1532		for name, details in pairs(player_ship_stats) do
1533			template_in = name
1534			break
1535		end
1536	end
1537	addGMFunction(string.format("+Out %s",template_out),setTemplateOut)
1538	addGMFunction(string.format("+In %s",template_in),setTemplateIn)
1539	addGMFunction("Swap",function()
1540		for i=1,#custom_player_ship_sets["Custom"][ships_per_team] do
1541			if custom_player_ship_sets["Custom"][ships_per_team][i] == template_out then
1542				custom_player_ship_sets["Custom"][ships_per_team][i] = template_in
1543				template_in = template_out
1544				template_out = custom_player_ship_sets["Custom"][ships_per_team][i]
1545				break
1546			end
1547		end
1548		setCustomSet()
1549	end)
1550end
1551function setTemplateOut()
1552	clearGMFunctions()
1553	table.sort(custom_player_ship_sets["Custom"][ships_per_team])
1554	for i=1,#custom_player_ship_sets["Custom"][ships_per_team] do
1555		local button_label = custom_player_ship_sets["Custom"][ships_per_team][i]
1556		if template_out == custom_player_ship_sets["Custom"][ships_per_team][i] then
1557			button_label = button_label .. "*"
1558		end
1559		addGMFunction(button_label,function()
1560			template_out = custom_player_ship_sets["Custom"][ships_per_team][i]
1561			setCustomSet()
1562		end)
1563	end
1564end
1565function setTemplateIn()
1566	clearGMFunctions()
1567	local sorted_templates = {}
1568	for name, details in pairs(player_ship_stats) do
1569		table.insert(sorted_templates,name)
1570	end
1571	table.sort(sorted_templates)
1572	for _, name in ipairs(sorted_templates) do
1573		local button_label = name
1574		if template_in == name then
1575			button_label = button_label .. "*"
1576		end
1577		addGMFunction(button_label,function()
1578			template_in = name
1579			setCustomSet()
1580		end)
1581	end
1582end
1583--	Terrain related GM configuration functions
1584function setTerrainParameters()
1585	clearGMFunctions()
1586	addGMFunction("-Main from Terrain",mainGMButtons)
1587	if generate_terrain_message_counter % 5 == 0 then
1588		addGMMessage("Clicking the generate button will generate the terrain based on the number of player teams selected, the number of ships on a team and the terrain parameters selected.\n\nAfter you generate the terrain, you cannot change the player ships, or the terrain unless you restart the server.")
1589	end
1590	generate_terrain_message_counter = generate_terrain_message_counter + 1
1591	addGMFunction(string.format("Missiles: %s",missile_availability),setMissileAvailability)
1592	addGMFunction("+Primary Station",setPrimaryStationParameters)
1593	addGMFunction("Generate",function()
1594		generateTerrain()
1595		mainGMButtons()
1596	end)
1597end
1598function setStationSensorRange()
1599	clearGMFunctions()
1600	local button_label = "Zero"
1601	if station_sensor_range == 0 then
1602		button_label = button_label .. "*"
1603	end
1604	addGMFunction(button_label,function()
1605		station_sensor_range = 0
1606		mainGMButtons()
1607	end)
1608	button_label = "5U"
1609	if station_sensor_range == 5000 then
1610		button_label = button_label .. "*"
1611	end
1612	addGMFunction(button_label,function()
1613		station_sensor_range = 5000
1614		mainGMButtons()
1615	end)
1616	button_label = "10U"
1617	if station_sensor_range == 10000 then
1618		button_label = button_label .. "*"
1619	end
1620	addGMFunction(button_label,function()
1621		station_sensor_range = 10000
1622		mainGMButtons()
1623	end)
1624	button_label = "20U"
1625	if station_sensor_range == 20000 then
1626		button_label = button_label .. "*"
1627	end
1628	addGMFunction(button_label,function()
1629		station_sensor_range = 20000
1630		mainGMButtons()
1631	end)
1632	button_label = "30U"
1633	if station_sensor_range == 30000 then
1634		button_label = button_label .. "*"
1635	end
1636	addGMFunction(button_label,function()
1637		station_sensor_range = 30000
1638		mainGMButtons()
1639	end)
1640end
1641function setPrimaryStationParameters()
1642	clearGMFunctions()
1643	addGMFunction("-Main from Prm Stn",mainGMButtons)
1644	addGMFunction("-Terrain",setTerrainParameters)
1645	if defense_platform_count_options[defense_platform_count_index].count == "random" then
1646		addGMFunction("+Platforms: Random",setDefensePlatformCount)
1647	else
1648		addGMFunction(string.format("+Platforms: %i",defense_platform_count_options[defense_platform_count_index].count),setDefensePlatformCount)
1649	end
1650	if primary_station_size_index == 1 then
1651		addGMFunction("Random Size ->",function()
1652			primary_station_size_index = primary_station_size_index + 1
1653			setPrimaryStationParameters()
1654		end)
1655	else
1656		addGMFunction(string.format("%s ->",primary_station_size_options[primary_station_size_index]),function()
1657			primary_station_size_index = primary_station_size_index + 1
1658			if primary_station_size_index > #primary_station_size_options then
1659				primary_station_size_index = 1
1660			end
1661			setPrimaryStationParameters()
1662		end)
1663	end
1664	addGMFunction(string.format("Jammer: %s ->",primary_jammers),function()
1665		if primary_jammers == "random" then
1666			primary_jammers = "on"
1667		elseif primary_jammers == "on" then
1668			primary_jammers = "off"
1669		elseif primary_jammers == "off" then
1670			primary_jammers = "random"
1671		end
1672		setPrimaryStationParameters()
1673	end)
1674end
1675function setDefensePlatformCount()
1676	clearGMFunctions()
1677	addGMFunction("-Main from Platforms",mainGMButtons)
1678	addGMFunction("-Terrain",setTerrainParameters)
1679	addGMFunction("-Primary Station",setPrimaryStationParameters)
1680	if defense_platform_count_index < #defense_platform_count_options then
1681		if defense_platform_count_options[defense_platform_count_index + 1].count == "random" then
1682			addGMFunction(string.format("%i Platforms + -> Rnd",defense_platform_count_options[defense_platform_count_index].count),function()
1683				defense_platform_count_index = defense_platform_count_index + 1
1684				setDefensePlatformCount()
1685			end)
1686		else
1687			addGMFunction(string.format("%i Platforms + -> %i",defense_platform_count_options[defense_platform_count_index].count,defense_platform_count_options[defense_platform_count_index + 1].count),function()
1688				defense_platform_count_index = defense_platform_count_index + 1
1689				setDefensePlatformCount()
1690			end)
1691		end
1692	end
1693	if defense_platform_count_index > 1 then
1694		if defense_platform_count_options[defense_platform_count_index].count == "random" then
1695			addGMFunction(string.format("Rnd Platforms - -> %i",defense_platform_count_options[defense_platform_count_index - 1].count),function()
1696				defense_platform_count_index = defense_platform_count_index - 1
1697				setDefensePlatformCount()
1698			end)
1699		else
1700			addGMFunction(string.format("%i Platforms - -> %i",defense_platform_count_options[defense_platform_count_index].count,defense_platform_count_options[defense_platform_count_index - 1].count),function()
1701				defense_platform_count_index = defense_platform_count_index - 1
1702				setDefensePlatformCount()
1703			end)
1704		end
1705	end
1706end
1707--	Display player control codes
1708function showKraylorCodes()
1709	showControlCodes("Kraylor")
1710end
1711function showExuariCodes()
1712	showControlCodes("Exuari")
1713end
1714function showHumanCodes()
1715	showControlCodes("Human Navy")
1716end
1717function showKtlitanCodes()
1718	showControlCodes("Ktlitans")
1719end
1720function showControlCodes(faction_filter)
1721	local code_list = {}
1722	for pidx=1,32 do
1723		local p = getPlayerShip(pidx)
1724		if p ~= nil and p:isValid() then
1725			if faction_filter == "Kraylor" then
1726				if p:getFaction() == "Kraylor" then
1727					code_list[p:getCallSign()] = {code = p.control_code, faction = p:getFaction()}
1728				end
1729			elseif faction_filter == "Human Navy" then
1730				if p:getFaction() == "Human Navy" then
1731					code_list[p:getCallSign()] = {code = p.control_code, faction = p:getFaction()}
1732				end
1733			elseif faction_filter == "Exuari" then
1734				if p:getFaction() == "Exuari" then
1735					code_list[p:getCallSign()] = {code = p.control_code, faction = p:getFaction()}
1736				end
1737			elseif faction_filter == "Ktlitans" then
1738				if p:getFaction() == "Ktlitans" then
1739					code_list[p:getCallSign()] = {code = p.control_code, faction = p:getFaction()}
1740				end
1741			else
1742				code_list[p:getCallSign()] = {code = p.control_code, faction = p:getFaction()}
1743			end
1744		end
1745	end
1746	local sorted_names = {}
1747	for name in pairs(code_list) do
1748		table.insert(sorted_names,name)
1749	end
1750	table.sort(sorted_names)
1751	local output = ""
1752	for _, name in ipairs(sorted_names) do
1753		local faction = ""
1754		if code_list[name].faction == "Kraylor" then
1755			faction = " (Kraylor)"
1756		elseif code_list[name].faction == "Ktlitans" then
1757			faction = " (Ktlitan)"
1758		elseif code_list[name].faction == "Exuari" then
1759			faction = " (Exuari)"
1760		end
1761		output = output .. string.format("%s: %s %s\n",name,code_list[name].code,faction)
1762	end
1763	addGMMessage(output)
1764end
1765--	General configuration functions
1766function setGameTimeLimit()
1767	clearGMFunctions()
1768	addGMFunction("-Main from Time",mainGMButtons)
1769	if game_time_limit < 6000 then
1770		addGMFunction(string.format("%i Add 5 -> %i",game_time_limit/60,game_time_limit/60 + 5),function()
1771			game_time_limit = game_time_limit + 300
1772			max_game_time = game_time_limit
1773			setGameTimeLimit()
1774		end)
1775	end
1776	if game_time_limit > 300 then
1777		addGMFunction(string.format("%i Del 5 -> %i",game_time_limit/60,game_time_limit/60 - 5),function()
1778			game_time_limit = game_time_limit - 300
1779			max_game_time = game_time_limit
1780			setGameTimeLimit()
1781		end)
1782	end
1783end
1784function setMissileAvailability()
1785	clearGMFunctions()
1786	addGMFunction("-Main from Missiles",mainGMButtons)
1787	addGMFunction("-Terrain",setTerrainParameters)
1788	local button_label = "unlimited"
1789	if missile_availability == "unlimited" then
1790		button_label = button_label .. "*"
1791	end
1792	addGMFunction(button_label,function()
1793		missile_availability = "unlimited"
1794		setMissileAvailability()
1795	end)
1796	button_label = "outer limited"
1797	if missile_availability == "outer limited" then
1798		button_label = button_label .. "*"
1799	end
1800	addGMFunction(button_label,function()
1801		missile_availability = "outer limited"
1802		setMissileAvailability()
1803	end)
1804	button_label = "limited"
1805	if missile_availability == "limited" then
1806		button_label = button_label .. "*"
1807	end
1808	addGMFunction(button_label,function()
1809		missile_availability = "limited"
1810		setMissileAvailability()
1811	end)
1812end
1813function setNPCShips()
1814	clearGMFunctions()
1815	addGMFunction("-From NPC Strength",mainGMButtons)
1816	local button_label = "NPC Ships: No"
1817	if npc_ships then
1818		button_label = string.format("NPC Ships: %i-%i",npc_lower,npc_upper)
1819	end
1820	addGMFunction(button_label,function()
1821		if npc_ships then
1822			npc_ships = false
1823		else
1824			npc_ships = true
1825		end
1826		setNPCShips()
1827	end)
1828	if npc_ships then
1829		if npc_lower < npc_upper - 5 then
1830			addGMFunction(string.format("%i From Add -> %i",npc_lower,npc_lower + 5),function()
1831				npc_lower = npc_lower + 5
1832				setNPCShips()
1833			end)
1834		end
1835		if npc_lower > 10 then
1836			addGMFunction(string.format("%i From Del -> %i",npc_lower,npc_lower - 5),function()
1837				npc_lower = npc_lower - 5
1838				setNPCShips()
1839			end)
1840		end
1841		if npc_upper < 200 then
1842			addGMFunction(string.format("%i To Add -> %i",npc_upper,npc_upper + 5),function()
1843				npc_upper = npc_upper + 5
1844				setNPCShips()
1845			end)
1846		end
1847		if npc_upper > npc_lower + 5 then
1848			addGMFunction(string.format("%i To Del -> %i",npc_upper,npc_upper - 5),function()
1849				npc_upper = npc_upper - 5
1850				setNPCShips()
1851			end)
1852		end
1853	end
1854end
1855-------------------------------------
1856--	Generate terrain and stations  --
1857-------------------------------------
1858function generateTerrain()
1859--	Activities include:
1860--		Central terrain feature
1861--		Angle from center for each faction (used to place objects symmetrically)
1862--		Primary station and any defense platforms and/or defensive warp jammers
1863--		Positioning players around primary station
1864--		Placing other stations with varying capabilities and capacities
1865--		Wormholes, black holes, asteroids and nebulae
1866	if terrain_generated then
1867		return
1868	end
1869	terrain_generated = true
1870	terrain_center_x = random(200000,300000)
1871	terrain_center_y = random(100000,200000)
1872	local ta = Asteroid():setPosition(terrain_center_x,terrain_center_y)
1873	local terrain_center_sector = ta:getSectorName()
1874	addGMMessage(string.format("The center of the universe is in sector\n%s",terrain_center_sector))
1875	ta:destroy()
1876	place_ref_list = {}
1877	human_ref_list = {}
1878
1879	--	decide what lives at the center of the universe
1880	local center_choice_list = {"Planet","Star","Black Hole"}
1881	local center_choice = center_choice_list[math.random(1,#center_choice_list)]
1882	if center_choice == "Planet" then
1883		local center_planet, center_radius = choosePlanet(math.random(2,3),terrain_center_x,terrain_center_y)
1884		table.insert(place_ref_list,center_planet)
1885		if random(1,100) <= 50 then
1886			local mx, my = vectorFromAngleNorth(random(0,360),center_radius + random(1000,2000))
1887			local moon = choosePlanet(4,terrain_center_x + mx,terrain_center_y + my)
1888			moon:setOrbit(center_planet,random(200,400))
1889			table.insert(place_ref_list,moon)
1890		end
1891	elseif center_choice == "Star" then
1892		local center_star, star_radius = choosePlanet(1,terrain_center_x,terrain_center_y)
1893		table.insert(place_ref_list,center_star)
1894		if random(1,100) <= 75 then
1895			local plx, ply = vectorFromAngleNorth(random(0,360),star_radius + random(8000,15000))
1896			local orbit_planet, orbit_radius = choosePlanet(math.random(2,3),terrain_center_x + plx,terrain_center_y + ply)
1897			orbit_planet:setOrbit(center_star,random(800,2000))
1898			table.insert(place_ref_list,orbit_planet)
1899			if random(1,100) <= 50 then
1900				local omx, omy = vectorFromAngleNorth(random(0,360),orbit_radius + random(1000,2000))
1901				local orbit_moon = choosePlanet(4,terrain_center_x + plx + omx,terrain_center_y + ply + omy)
1902				orbit_moon:setOrbit(orbit_planet,random(200,400))
1903				table.insert(place_ref_list,orbit_moon)
1904			end
1905		end
1906	elseif center_choice == "Black Hole" then
1907		local black_hole_names = {
1908			"Fornax A",
1909			"Sagittarius A",
1910			"Triangulum",
1911			"Cygnus X-3",
1912			"Messier 110",
1913			"Virgo A",
1914			"Andromeda",
1915			"Sombrero",
1916			"Great Annihilator",
1917		}
1918		table.insert(place_ref_list,BlackHole():setPosition(terrain_center_x,terrain_center_y):setCallSign(black_hole_names[math.random(1,#black_hole_names)]))
1919	end
1920
1921	--	Set angles
1922	faction_angle = {}
1923	npc_fleet = {}
1924	npc_fleet["Human Navy"] = {}
1925	npc_fleet["Kraylor"] = {}
1926	human_angle = random(0,360)
1927	faction_angle["Human Navy"] = human_angle
1928	local replicant_increment = 360/player_team_count
1929	kraylor_angle = (human_angle + replicant_increment) % 360
1930	faction_angle["Kraylor"] = kraylor_angle
1931	if player_team_count > 2 then
1932		exuari_angle = (kraylor_angle + replicant_increment) % 360
1933		faction_angle["Exuari"] = exuari_angle
1934		npc_fleet["Exuari"] = {}
1935	end
1936	if player_team_count > 3 then
1937		ktlitan_angle = (exuari_angle + replicant_increment) % 360
1938		faction_angle["Ktlitans"] = ktlitan_angle
1939		npc_fleet["Ktlitans"] = {}
1940	end
1941
1942	if respawn_type == "self" then
1943		death_penalty = {}
1944		death_penalty["Human Navy"] = 0
1945		death_penalty["Kraylor"] = 0
1946		if exuari_angle ~= nil then
1947			death_penalty["Exuari"] = 0
1948		end
1949		if ktlitan_angle ~= nil then
1950			death_penalty["Ktlitans"] = 0
1951		end
1952	end
1953
1954	--	Set primary stations
1955	local primary_station_distance = random(50000,100000)
1956	local primary_station_size = primary_station_size_options[primary_station_size_index]
1957	if primary_station_size == "random" then
1958		primary_station_size = szt()
1959	end
1960	base_station_value_list = {
1961		["Huge Station"] 	= 10,
1962		["Large Station"]	= 5,
1963		["Medium Station"]	= 3,
1964		["Small Station"]	= 1,
1965	}
1966	faction_primary_station = {}
1967	local psx, psy = vectorFromAngleNorth(human_angle,primary_station_distance)
1968	station_primary_human = placeStation(terrain_center_x + psx, terrain_center_y + psy, "Random","Human Navy",primary_station_size)
1969	faction_primary_station["Human Navy"] = {x = terrain_center_x + psx, y = terrain_center_y + psy, station = station_primary_human}
1970	station_primary_human.score_value = base_station_value_list[primary_station_size] + 10
1971	station_list["Human Navy"] = {}
1972	table.insert(station_list["Human Navy"],station_primary_human)
1973	table.insert(place_ref_list,station_primary_human)
1974	table.insert(human_ref_list,station_primary_human)
1975	local unlimited_missiles = true
1976	if missile_availability == "limited" then
1977		unlimited_missiles = false
1978	end
1979	station_primary_human.comms_data = {
1980    	friendlyness = random(75,100),
1981        weapon_cost =		{
1982        	Homing =	math.random(1,6),
1983        	Nuke =		math.random(10,30),
1984        	Mine =		math.random(2,25),
1985        	EMP =		math.random(8,20),
1986        	HVLI =		math.random(1,4),
1987        },
1988		weapon_available = 	{
1989			Homing =			true,
1990			Nuke =				true,
1991			Mine =				true,
1992			EMP =				true,
1993			HVLI =				true,
1994		},
1995		weapon_inventory = {
1996			Unlimited =	unlimited_missiles,
1997			Homing =	math.floor(math.random(10,50)/difficulty),
1998			Nuke =		math.floor(math.random(5,30)/difficulty),
1999			Mine =		math.floor(math.random(8,40)/difficulty),
2000			EMP =		math.floor(math.random(6,34)/difficulty),
2001			HVLI =		math.floor(math.random(15,70)/difficulty),
2002		},
2003		services = {
2004			supplydrop = "friend",
2005			reinforcements = "friend",
2006			jumpsupplydrop = "friend",
2007            sensor_boost = "neutral",
2008			preorder = "friend",
2009            activatedefensefleet = "neutral",
2010            jumpovercharge = "neutral",
2011			jumpsupplydrop = "friend",
2012		},
2013		service_cost = {
2014			supplydrop =		math.random(80,120),
2015			reinforcements =	math.random(125,175),
2016			hornetreinforcements =	math.random(75,125),
2017			phobosreinforcements =	math.random(175,225),
2018			jumpsupplydrop =	math.random(110,140),
2019            activatedefensefleet = math.random(15,40),
2020            jumpovercharge =	math.random(10,20),
2021			jumpsupplydrop =	math.random(110,150),
2022		},
2023		jump_overcharge =		true,
2024		probe_launch_repair =	true,
2025		hack_repair =			true,
2026		scan_repair =			true,
2027		combat_maneuver_repair=	true,
2028		self_destruct_repair =	true,
2029		tube_slow_down_repair =	true,
2030        sensor_boost = {value = primary_station_distance-35000, cost = 0},
2031		reputation_cost_multipliers = {
2032			friend = 			1.0,
2033			neutral = 			3.0,
2034		},
2035        max_weapon_refill_amount = {friend = 1.0, neutral = 0.5 },
2036        goods = {	food = 		{quantity = 10,		cost = 1},
2037        			medicine =	{quantity = 10,		cost = 5}	},
2038        trade = {	food = false, medicine = false, luxury = false },
2039	}
2040	station_primary_human.comms_data.idle_defense_fleet = defense_fleet_list[primary_station_size][math.random(1,#defense_fleet_list[primary_station_size])]
2041	psx, psy = vectorFromAngleNorth(kraylor_angle,primary_station_distance)
2042	station_primary_kraylor = placeStation(terrain_center_x + psx, terrain_center_y + psy, "Random","Kraylor",primary_station_size)
2043	faction_primary_station["Kraylor"] = {x = terrain_center_x + psx, y = terrain_center_y + psy, station = station_primary_kraylor}
2044	station_primary_kraylor.score_value = base_station_value_list[primary_station_size] + 10
2045	station_list["Kraylor"] = {}
2046	table.insert(station_list["Kraylor"],station_primary_kraylor)
2047	table.insert(place_ref_list,station_primary_kraylor)
2048	station_primary_kraylor.comms_data = station_primary_human.comms_data
2049	if exuari_angle ~= nil then
2050		psx, psy = vectorFromAngleNorth(exuari_angle,primary_station_distance)
2051		station_primary_exuari = placeStation(terrain_center_x + psx, terrain_center_y + psy, "Random","Exuari",primary_station_size)
2052		faction_primary_station["Exuari"] = {x = terrain_center_x + psx, y = terrain_center_y + psy, station = station_primary_exuari}
2053		station_primary_exuari.score_value = base_station_value_list[primary_station_size] + 10
2054		station_list["Exuari"] = {}
2055		table.insert(station_list["Exuari"],station_primary_exuari)
2056		table.insert(place_ref_list,station_primary_exuari)
2057		station_primary_exuari.comms_data = station_primary_human.comms_data
2058	end
2059	if ktlitan_angle ~= nil then
2060		psx, psy = vectorFromAngleNorth(ktlitan_angle,primary_station_distance)
2061		station_primary_ktlitan = placeStation(terrain_center_x + psx, terrain_center_y + psy, "Random","Ktlitans",primary_station_size)
2062		faction_primary_station["Ktlitans"] = {x = terrain_center_x + psx, y = terrain_center_y + psy, station = station_primary_ktlitan}
2063		station_primary_ktlitan.score_value = base_station_value_list[primary_station_size] + 10
2064		station_list["Ktlitans"] = {}
2065		table.insert(station_list["Ktlitans"],station_primary_ktlitan)
2066		table.insert(place_ref_list,station_primary_ktlitan)
2067		station_primary_ktlitan.comms_data = station_primary_human.comms_data
2068	end
2069
2070	--	Set defense platforms and jammers (if applicable)
2071	defense_platform_count = defense_platform_count_options[defense_platform_count_index].count
2072	defense_platform_distance = defense_platform_count_options[defense_platform_count_index].distance
2073	player_position_distance = defense_platform_count_options[defense_platform_count_index].player
2074	if defense_platform_count == "random" then
2075		local index = math.random(1,#defense_platform_count_options - 1)
2076		defense_platform_count = defense_platform_count_options[index].count
2077		defense_platform_distance = defense_platform_count_options[index].distance
2078		player_position_distance = defense_platform_count_options[index].player
2079	end
2080	if primary_jammers == "random" then
2081		primary_jammers = random(1,100) < 50
2082	else
2083		if primary_jammers == "on" then
2084			primary_jammers = true
2085		else
2086			primary_jammers = false
2087		end
2088	end
2089	local angle = human_angle
2090	local vx = 0
2091	local vy = 0
2092	unlimited_missiles = false
2093	if missile_availability == "unlimited" then
2094		unlimited_missiles = true
2095	end
2096	if defense_platform_count > 0 then
2097		local dp = nil
2098		angle = human_angle
2099		psx, psy = station_primary_human:getPosition()
2100		local dp_list = {}
2101		for i=1,defense_platform_count do
2102			vx, vy = vectorFromAngleNorth(angle,defense_platform_distance)
2103			dp = CpuShip():setTemplate("Defense platform"):setFaction("Human Navy"):setPosition(psx + vx,psy + vy):setScannedByFaction("Human Navy",true):setCallSign(string.format("HDP%i",i)):setDescription(string.format("%s defense platform %i",station_primary_human:getCallSign(),i)):orderRoaming()
2104			dp.score_value = 50
2105			table.insert(npc_fleet["Human Navy"],dp)
2106			dp:setCommsScript(""):setCommsFunction(commsDefensePlatform)
2107			dp.primary_station = station_primary_human
2108			if primary_jammers then
2109				vx, vy = vectorFromAngleNorth(angle,defense_platform_distance/2)
2110				WarpJammer():setPosition(psx + vx, psy + vy):setRange(defense_platform_distance/2 + 4000):setFaction("Human Navy")
2111			end
2112			dp.comms_data = {	--defense platform comms data
2113				weapon_available = 	{
2114					Homing =			random(1,13)<=(3-difficulty),
2115					HVLI =				random(1,13)<=(6-difficulty),
2116					Mine =				false,
2117					Nuke =				false,
2118					EMP =				false,
2119				},
2120				weapon_inventory = {
2121					Unlimited =	unlimited_missiles,
2122					Homing =	math.floor(math.random(10,50)/difficulty),
2123					Nuke =		0,
2124					Mine =		0,
2125					EMP =		0,
2126					HVLI =		math.floor(math.random(15,70)/difficulty),
2127				},
2128				services = {
2129					supplydrop = "friend",
2130					reinforcements = "friend",
2131					jumpsupplydrop = "friend",
2132				},
2133				service_cost = {
2134					supplydrop =		math.random(80,120),
2135					reinforcements =	math.random(125,175),
2136					jumpsupplydrop =	math.random(110,140),
2137				},
2138				jump_overcharge =		false,
2139				probe_launch_repair =	random(1,100) <= (20 - difficulty*2.5),
2140				hack_repair =			random(1,100) <= (22 - difficulty*2.5),
2141				scan_repair =			random(1,100) <= (30 - difficulty*2.5),
2142				combat_maneuver_repair=	random(1,100) <= (15 - difficulty*2.5),
2143				self_destruct_repair =	random(1,100) <= (25 - difficulty*2.5),
2144				tube_slow_down_repair =	random(1,100) <= (18 - difficulty*2.5),
2145				reputation_cost_multipliers = {
2146					friend = 			1.0,
2147					neutral = 			3.0,
2148				},
2149			}
2150			dp:setSharesEnergyWithDocked(random(1,100) <= (60 - difficulty*5))
2151			dp:setRepairDocked(random(1,100) <= (50 - difficulty*5))
2152			dp:setRestocksScanProbes(random(1,100) <= (40 - difficulty*5))
2153			table.insert(dp_list,dp)
2154			table.insert(place_ref_list,dp)
2155			table.insert(human_ref_list,dp)
2156			angle = (angle + 360/defense_platform_count) % 360
2157		end
2158		angle = kraylor_angle
2159		psx, psy = station_primary_kraylor:getPosition()
2160		for i=1,defense_platform_count do
2161			vx, vy = vectorFromAngleNorth(angle,defense_platform_distance)
2162			dp = CpuShip():setTemplate("Defense platform"):setFaction("Kraylor"):setPosition(psx + vx,psy + vy):setScannedByFaction("Kraylor",true):setCallSign(string.format("KDP%i",i)):setDescription(string.format("%s defense platform %i",station_primary_kraylor:getCallSign(),i)):orderRoaming()
2163			dp.score_value = 50
2164			table.insert(npc_fleet["Kraylor"],dp)
2165			dp:setCommsScript(""):setCommsFunction(commsDefensePlatform)
2166			dp.primary_station = station_primary_kraylor
2167			if primary_jammers then
2168				vx, vy = vectorFromAngleNorth(angle,defense_platform_distance/2)
2169				WarpJammer():setPosition(psx + vx, psy + vy):setRange(defense_platform_distance/2 + 4000):setFaction("Kraylor")
2170			end
2171			dp.comms_data = dp_list[i].comms_data	--replicate capabilities
2172			dp:setSharesEnergyWithDocked(dp_list[i]:getSharesEnergyWithDocked())
2173			dp:setRepairDocked(dp_list[i]:getRepairDocked())
2174			dp:setRestocksScanProbes(dp_list[i]:getRestocksScanProbes())
2175			table.insert(place_ref_list,dp)
2176			angle = (angle + 360/defense_platform_count) % 360
2177		end
2178		if exuari_angle ~= nil then
2179			angle = exuari_angle
2180			psx, psy = station_primary_exuari:getPosition()
2181			for i=1,defense_platform_count do
2182				vx, vy = vectorFromAngleNorth(angle,defense_platform_distance)
2183				dp = CpuShip():setTemplate("Defense platform"):setFaction("Exuari"):setPosition(psx + vx,psy + vy):setScannedByFaction("Exuari",true):setCallSign(string.format("EDP%i",i)):setDescription(string.format("%s defense platform %i",station_primary_exuari:getCallSign(),i)):orderRoaming()
2184				dp.score_value = 50
2185				table.insert(npc_fleet["Exuari"],dp)
2186				dp:setCommsScript(""):setCommsFunction(commsDefensePlatform)
2187				dp.primary_station = station_primary_exuari
2188				if primary_jammers then
2189					vx, vy = vectorFromAngleNorth(angle,defense_platform_distance/2)
2190					WarpJammer():setPosition(psx + vx, psy + vy):setRange(defense_platform_distance/2 + 4000):setFaction("Exuari")
2191				end
2192				dp.comms_data = dp_list[i].comms_data	--replicate capabilities
2193				dp:setSharesEnergyWithDocked(dp_list[i]:getSharesEnergyWithDocked())
2194				dp:setRepairDocked(dp_list[i]:getRepairDocked())
2195				dp:setRestocksScanProbes(dp_list[i]:getRestocksScanProbes())
2196				table.insert(place_ref_list,dp)
2197				angle = (angle + 360/defense_platform_count) % 360
2198			end
2199		end
2200		if ktlitan_angle ~= nil then
2201			angle = ktlitan_angle
2202			psx, psy = station_primary_ktlitan:getPosition()
2203			for i=1,defense_platform_count do
2204				vx, vy = vectorFromAngleNorth(angle,defense_platform_distance)
2205				dp = CpuShip():setTemplate("Defense platform"):setFaction("Ktlitans"):setPosition(psx + vx,psy + vy):setScannedByFaction("Ktlitans",true):setCallSign(string.format("BDP%i",i)):setDescription(string.format("%s defense platform %i",station_primary_ktlitan:getCallSign(),i)):orderRoaming()
2206				dp.score_value = 50
2207				table.insert(npc_fleet["Ktlitans"],dp)
2208				dp:setCommsScript(""):setCommsFunction(commsDefensePlatform)
2209				dp.primary_station = station_primary_ktlitan
2210				if primary_jammers then
2211					vx, vy = vectorFromAngleNorth(angle,defense_platform_distance/2)
2212					WarpJammer():setPosition(psx + vx, psy + vy):setRange(defense_platform_distance/2 + 4000):setFaction("Ktlitans")
2213				end
2214				dp.comms_data = dp_list[i].comms_data	--replicate capabilities
2215				dp:setSharesEnergyWithDocked(dp_list[i]:getSharesEnergyWithDocked())
2216				dp:setRepairDocked(dp_list[i]:getRepairDocked())
2217				dp:setRestocksScanProbes(dp_list[i]:getRestocksScanProbes())
2218				table.insert(place_ref_list,dp)
2219				angle = (angle + 360/defense_platform_count) % 360
2220			end
2221		end
2222	else	--no defense platforms
2223		if primary_jammers then
2224			local jammer_distance = 4000
2225			local jammer_range = 8000
2226			angle = human_angle
2227			psx, psy = station_primary_human:getPosition()
2228			for i=1,4 do
2229				vx, vy = vectorFromAngleNorth(angle,jammer_distance)
2230				local wj = WarpJammer():setPosition(psx + vx, psy + vy):setRange(jammer_range):setFaction("Human Navy")
2231				table.insert(place_ref_list,wj)
2232				table.insert(human_ref_list,wj)
2233				angle = (angle + 90) % 360
2234			end
2235			angle = kraylor_angle
2236			psx, psy = station_primary_kraylor:getPosition()
2237			for i=1,4 do
2238				vx, vy = vectorFromAngleNorth(angle,jammer_distance)
2239				table.insert(place_ref_list,WarpJammer():setPosition(psx + vx, psy + vy):setRange(jammer_range):setFaction("Kraylor"))
2240				angle = (angle + 90) % 360
2241			end
2242			if exuari_angle ~= nil then
2243				angle = exuari_angle
2244				psx, psy = station_primary_exuari:getPosition()
2245				for i=1,4 do
2246					vx, vy = vectorFromAngleNorth(angle,jammer_distance)
2247					table.insert(place_ref_list,WarpJammer():setPosition(psx + vx, psy + vy):setRange(jammer_range):setFaction("Exuari"))
2248					angle = (angle + 90) % 360
2249				end
2250			end
2251			if ktlitan_angle ~= nil then
2252				angle = ktlitan_angle
2253				psx, psy = station_primary_ktlitan:getPosition()
2254				for i=1,4 do
2255					vx, vy = vectorFromAngleNorth(angle,jammer_distance)
2256					table.insert(place_ref_list,WarpJammer():setPosition(psx + vx, psy + vy):setRange(jammer_range):setFaction("Ktlitans"))
2257					angle = (angle + 90) % 360
2258				end
2259			end
2260		end
2261	end
2262
2263	--	Place players
2264	player_restart = {}
2265	if player_ship_types == "spawned" then
2266		local player_count = 0
2267		for pidx=1,32 do
2268			local p = getPlayerShip(pidx)
2269			if p ~= nil and p:isValid() then
2270				player_count = player_count + 1
2271			end
2272		end
2273		local out = ""
2274		if player_count < ships_per_team then
2275			if player_count == 0 then
2276				out = string.format("No player ships spawned. %i are required.\n\nUsing default ship set.",ships_per_team)
2277			elseif player_count == 1 then
2278				out = string.format("Only one player ship spawned. %i are required.\n\nUsing default ship set.",ships_per_team)
2279			else
2280				out = string.format("Only %i player ships spawned. %i are required.\n\nUsing default ship set.",player_count,ships_per_team)
2281			end
2282			player_ship_types = "default"
2283			addGMMessage(out)
2284			placeDefaultPlayerShips()
2285		elseif player_count > ships_per_team then
2286			if ships_per_team == 1 then
2287				out = string.format("%i player ships spawned. Only %i is required.\n\nUsing default ship set.",player_count,ships_per_team)
2288			else
2289				out = string.format("%i player ships spawned. Only %i are required.\n\nUsing default ship set.",player_count,ships_per_team)
2290			end
2291			player_ship_types = "default"
2292			addGMMessage(out)
2293			placeDefaultPlayerShips()
2294		end
2295		psx, psy = station_primary_human:getPosition()
2296		angle = human_angle
2297		for pidx=1,ships_per_team do
2298			local p = getPlayerShip(pidx)
2299			if p ~= nil and p:isValid() then
2300				setPlayer(p)
2301				startPlayerPosition(p,angle)
2302				local respawn_x, respawn_y = p:getPosition()
2303				p.respawn_x = respawn_x
2304				p.respawn_y = respawn_y
2305				player_restart[p:getCallSign()] = {self = p, template = p:getTypeName(), control_code = p.control_code, faction = p:getFaction(), respawn_x = respawn_x, respawn_y = respawn_y}
2306				angle = (angle + 360/ships_per_team) % 360
2307			else
2308				addGMMessage("One of the player ships spawned is not valid, switching to default ship set")
2309				player_ship_types = "default"
2310				break
2311			end
2312		end
2313		if player_ship_types == "default" then
2314			placeDefaultPlayerShips()
2315		else
2316			replicatePlayers("Kraylor")
2317			if exuari_angle ~= nil then
2318				replicatePlayers("Exuari")
2319			end
2320			if ktlitan_angle ~= nil then
2321				replicatePlayers("Ktlitans")
2322			end
2323		end
2324	elseif player_ship_types == "custom" then
2325		placeCustomPlayerShips()
2326	else	--default
2327		placeDefaultPlayerShips()
2328	end
2329	for pidx=1,32 do
2330		local p = getPlayerShip(pidx)
2331		if p ~= nil and p:isValid() then
2332			table.insert(place_ref_list,p)
2333			if p:getFaction() == "Human Navy" then
2334				table.insert(human_ref_list,p)
2335			end
2336		end
2337	end
2338
2339	--	Place NPC ships (if applicable)
2340	local npc_fleet_count = 0
2341	if npc_ships then
2342		npc_fleet_count = math.random(1,ships_per_team)
2343		local fleet_index = 1
2344		local fleet_angle_increment = 360/npc_fleet_count
2345		for n=1,npc_fleet_count do
2346			local angle = (human_angle + n * fleet_angle_increment) % 360
2347			local fleet_strength = random(npc_lower,npc_upper)
2348			local pool_selectivity_choices = {"full","less/heavy","more/light"}
2349			pool_selectivity = pool_selectivity_choices[math.random(1,#pool_selectivity_choices)]
2350			local fleetComposition_choices = {"Random","Non-DB","Fighters","Chasers","Frigates","Beamers","Missilers","Adders","Drones"}
2351			fleetComposition = fleetComposition_choices[math.random(1,#fleetComposition_choices)]
2352			local fcx, fcy = vectorFromAngleNorth(angle,defense_platform_distance + 5000)
2353			psx, psy = station_primary_human:getPosition()
2354			local human_fleet = spawnRandomArmed(psx + fcx, psy + fcy, fleet_strength, fleet_index, nil, angle)
2355			fleet_index = fleet_index + 1
2356			for _, ship in ipairs(human_fleet) do
2357				ship.score_value = ship_template[ship:getTypeName()].strength
2358				ship:setScannedByFaction("Human Navy",true)
2359				table.insert(human_ref_list,ship)
2360				table.insert(place_ref_list,ship)
2361				table.insert(npc_fleet["Human Navy"],ship)
2362			end
2363			fleet_index = fleet_index + 1
2364			local fleet_prefix = generateCallSignPrefix()
2365			angle = (kraylor_angle + n * fleet_angle_increment) % 360
2366			for _, source_ship in ipairs(human_fleet) do
2367				local sx, sy = source_ship:getPosition()
2368				local obj_ref_angle = angleFromVectorNorth(sx, sy, terrain_center_x, terrain_center_y)
2369				local obj_ref_distance = distance(terrain_center_x, terrain_center_y, sx, sy)
2370				obj_ref_angle = (obj_ref_angle + replicant_increment) % 360
2371				local rep_x, rep_y = vectorFromAngleNorth(obj_ref_angle,obj_ref_distance)
2372				local selected_template = source_ship:getTypeName()
2373				local ship = ship_template[selected_template].create("Kraylor",selected_template)
2374				ship.score_value = ship_template[selected_template].strength
2375				ship:setScannedByFaction("Kraylor",true)
2376				ship:setPosition(terrain_center_x + rep_x, terrain_center_y + rep_y)
2377				ship:setCallSign(generateCallSign(fleet_prefix))
2378				ship:setCommsScript(""):setCommsFunction(commsShip)
2379				ship:orderIdle()
2380				ship:setHeading(angle)
2381				ship:setRotation(angle + 270)
2382				ship.fleetIndex = fleet_index
2383				table.insert(place_ref_list,ship)
2384				table.insert(npc_fleet["Kraylor"],ship)
2385			end
2386			if exuari_angle ~= nil then
2387				fleet_index = fleet_index + 1
2388				local fleet_prefix = generateCallSignPrefix()
2389				angle = (exuari_angle + n * fleet_angle_increment) % 360
2390				for _, source_ship in ipairs(human_fleet) do
2391					local sx, sy = source_ship:getPosition()
2392					local obj_ref_angle = angleFromVectorNorth(sx, sy, terrain_center_x, terrain_center_y)
2393					local obj_ref_distance = distance(terrain_center_x, terrain_center_y, sx, sy)
2394					obj_ref_angle = (obj_ref_angle + replicant_increment * 2) % 360
2395					local rep_x, rep_y = vectorFromAngleNorth(obj_ref_angle,obj_ref_distance)
2396					local selected_template = source_ship:getTypeName()
2397					local ship = ship_template[selected_template].create("Exuari",selected_template)
2398					ship.score_value = ship_template[selected_template].strength
2399					ship:setScannedByFaction("Exuari",true)
2400					ship:setPosition(terrain_center_x + rep_x, terrain_center_y + rep_y)
2401					ship:setCallSign(generateCallSign(fleet_prefix))
2402					ship:setCommsScript(""):setCommsFunction(commsShip)
2403					ship:orderIdle()
2404					ship:setHeading(angle)
2405					ship:setRotation(angle + 270)
2406					ship.fleetIndex = fleet_index
2407					table.insert(place_ref_list,ship)
2408					table.insert(npc_fleet["Exuari"],ship)
2409				end
2410			end
2411			if ktlitan_angle ~= nil then
2412				fleet_index = fleet_index + 1
2413				local fleet_prefix = generateCallSignPrefix()
2414				angle = (ktlitan_angle + n * fleet_angle_increment) % 360
2415				for _, source_ship in ipairs(human_fleet) do
2416					local sx, sy = source_ship:getPosition()
2417					local obj_ref_angle = angleFromVectorNorth(sx, sy, terrain_center_x, terrain_center_y)
2418					local obj_ref_distance = distance(terrain_center_x, terrain_center_y, sx, sy)
2419					obj_ref_angle = (obj_ref_angle + replicant_increment * 3) % 360
2420					local rep_x, rep_y = vectorFromAngleNorth(obj_ref_angle,obj_ref_distance)
2421					local selected_template = source_ship:getTypeName()
2422					local ship = ship_template[selected_template].create("Ktlitans",selected_template)
2423					ship.score_value = ship_template[selected_template].strength
2424					ship:setScannedByFaction("Ktlitans",true)
2425					ship:setPosition(terrain_center_x + rep_x, terrain_center_y + rep_y)
2426					ship:setCallSign(generateCallSign(fleet_prefix))
2427					ship:setCommsScript(""):setCommsFunction(commsShip)
2428					ship:orderIdle()
2429					ship:setHeading(angle)
2430					ship:setRotation(angle + 270)
2431					ship.fleetIndex = fleet_index
2432					table.insert(place_ref_list,ship)
2433					table.insert(npc_fleet["Ktlitans"],ship)
2434				end
2435			end
2436		end
2437	end
2438
2439	--	Place stations
2440	local candidate_x = 0
2441	local candidate_y = 0
2442	local center_x = 0
2443	local center_y = 0
2444	local perimeter = 0
2445	local avg_dist = 0
2446	local bubble = 2500
2447	local team_station_count_list = {50,25,16,12}
2448	local stretch_bound = 0
2449	for i=1,team_station_count_list[player_team_count] do
2450		center_x, center_y, perimeter, avg_dist = analyzeBlob(human_ref_list)
2451		stretch_bound = 5000
2452		repeat
2453			candidate_x, candidate_y = vectorFromAngleNorth(random(0,360),random(math.min(avg_dist,5000),math.min(perimeter,50000) + stretch_bound))
2454			candidate_x = center_x + candidate_x
2455			candidate_y = center_y + candidate_y
2456			stretch_bound = stretch_bound + 500
2457		until(farEnough(place_ref_list,candidate_x,candidate_y,math.max(perimeter/i,15000)))
2458		local sr_size = szt()
2459		local pStation = placeStation(candidate_x, candidate_y, "Random","Human Navy",sr_size)
2460		table.insert(station_list["Human Navy"],pStation)
2461		pStation.score_value = base_station_value_list[sr_size]
2462		table.insert(place_ref_list,pStation)
2463		table.insert(human_ref_list,pStation)
2464		pStation.comms_data = {
2465			friendlyness = random(15,100),
2466			weapon_cost =		{
2467				Homing =	math.random(2,8),
2468				Nuke =		math.random(12,30),
2469				Mine =		math.random(3,28),
2470				EMP =		math.random(9,25),
2471				HVLI =		math.random(2,5),
2472			},
2473			weapon_available = 	{
2474				Homing =	random(1,13)<=(6-difficulty),
2475				HVLI =		random(1,13)<=(6-difficulty),
2476				Mine =		random(1,13)<=(5-difficulty),
2477				Nuke =		random(1,13)<=(4-difficulty),
2478				EMP =		random(1,13)<=(4-difficulty),
2479			},
2480			weapon_inventory = {
2481				Unlimited =	unlimited_missiles,
2482				Homing =	math.floor(math.random(10,40)/difficulty),
2483				Nuke =		math.floor(math.random(5,20)/difficulty),
2484				Mine =		math.floor(math.random(8,30)/difficulty),
2485				EMP =		math.floor(math.random(6,24)/difficulty),
2486				HVLI =		math.floor(math.random(15,50)/difficulty),
2487			},
2488			services = {
2489				supplydrop = "friend",
2490				reinforcements = "friend",
2491				jumpsupplydrop = "friend",
2492				sensor_boost = "neutral",
2493				preorder = "friend",
2494				activatedefensefleet = "neutral",
2495				jumpovercharge = "neutral",
2496			},
2497			service_cost = {
2498				supplydrop =		math.random(80,120),
2499				reinforcements =	math.random(125,175),
2500				hornetreinforcements =	math.random(75,125),
2501				phobosreinforcements =	math.random(175,225),
2502				activatedefensefleet = math.random(15,40),
2503				jumpovercharge =	math.random(10,20),
2504				jumpsupplydrop =	math.random(110,140),
2505			},
2506			jump_overcharge =		random(1,100) <= (20 - difficulty*2.5),
2507			probe_launch_repair =	random(1,100) <= (33 - difficulty*2.5),
2508			hack_repair =			random(1,100) <= (42 - difficulty*2.5),
2509			scan_repair =			random(1,100) <= (50 - difficulty*2.5),
2510			combat_maneuver_repair=	random(1,100) <= (28 - difficulty*2.5),
2511			self_destruct_repair =	random(1,100) <= (25 - difficulty*2.5),
2512			tube_slow_down_repair =	random(1,100) <= (35 - difficulty*2.5),
2513			reputation_cost_multipliers = {
2514				friend = 			1.0,
2515				neutral = 			3.0,
2516			},
2517			max_weapon_refill_amount = {friend = 1.0, neutral = 0.5 },
2518		}
2519		pStation.comms_data.idle_defense_fleet = defense_fleet_list[sr_size][math.random(1,#defense_fleet_list[sr_size])]
2520		pStation:setSharesEnergyWithDocked(random(1,100) <= (50 - difficulty*5))
2521		pStation:setRepairDocked(random(1,100) <= (40 - difficulty*5))
2522		pStation:setRestocksScanProbes(random(1,100) <= (30 - difficulty*5))
2523		if scientist_count < 5 then
2524			if random(1,100) < 20 then
2525				if scientist_list["Human Navy"] == nil then
2526					scientist_list["Human Navy"] = {}
2527				end
2528				table.insert(
2529					scientist_list["Human Navy"],
2530					{
2531						name = tableRemoveRandom(scientist_names),
2532						topic = tableRemoveRandom(scientist_topics),
2533						location = pStation,
2534						location_name = pStation:getCallSign(),
2535						score_value = scientist_score_value,
2536						upgrade_requirement = upgrade_requirements[math.random(1,#upgrade_requirements)],
2537						upgrade = tableRemoveRandom(upgrade_list),
2538						upgrade_automated_application = upgrade_automated_applications[math.random(1,#upgrade_automated_applications)],
2539					}
2540				)
2541				scientist_count = scientist_count + 1
2542			end
2543		end
2544
2545		local obj_ref_angle = angleFromVectorNorth(candidate_x, candidate_y, terrain_center_x, terrain_center_y)
2546		local obj_ref_distance = distance(terrain_center_x, terrain_center_y, candidate_x, candidate_y)
2547		obj_ref_angle = (obj_ref_angle + replicant_increment) % 360
2548		local rep_x, rep_y = vectorFromAngleNorth(obj_ref_angle,obj_ref_distance)
2549		pStation = placeStation(terrain_center_x + rep_x, terrain_center_y + rep_y, "Random","Kraylor",sr_size)
2550		table.insert(station_list["Kraylor"],pStation)
2551		pStation.score_value = base_station_value_list[sr_size]
2552		pStation.comms_data = human_ref_list[#human_ref_list].comms_data
2553		pStation:setSharesEnergyWithDocked(human_ref_list[#human_ref_list]:getSharesEnergyWithDocked())
2554		pStation:setRepairDocked(human_ref_list[#human_ref_list]:getRepairDocked())
2555		pStation:setRestocksScanProbes(human_ref_list[#human_ref_list]:getRestocksScanProbes())
2556		table.insert(place_ref_list,pStation)
2557		if scientist_list["Human Navy"] ~= nil then
2558			if scientist_list["Kraylor"] == nil then
2559				scientist_list["Kraylor"] = {}
2560			end
2561			if #scientist_list["Kraylor"] < #scientist_list["Human Navy"] then
2562				table.insert(
2563					scientist_list["Kraylor"],
2564					{
2565						name = tableRemoveRandom(scientist_names),
2566						topic = scientist_list["Human Navy"][#scientist_list["Human Navy"]].topic,
2567						location = pStation,
2568						location_name = pStation:getCallSign(),
2569						score_value = scientist_score_value,
2570						upgrade_requirement = upgrade_requirements[math.random(1,#upgrade_requirements)],
2571						upgrade = scientist_list["Human Navy"][#scientist_list["Human Navy"]].upgrade,
2572						upgrade_automated_application = scientist_list["Human Navy"][#scientist_list["Human Navy"]].upgrade_automated_application,
2573					}
2574				)
2575			end
2576		end
2577		if exuari_angle ~= nil then
2578			obj_ref_angle = (obj_ref_angle + replicant_increment) % 360
2579			rep_x, rep_y = vectorFromAngleNorth(obj_ref_angle,obj_ref_distance)
2580			pStation = placeStation(terrain_center_x + rep_x, terrain_center_y + rep_y, "Random","Exuari",sr_size)
2581			table.insert(station_list["Exuari"],pStation)
2582			pStation.score_value = base_station_value_list[sr_size]
2583			pStation.comms_data = human_ref_list[#human_ref_list].comms_data
2584			pStation:setSharesEnergyWithDocked(human_ref_list[#human_ref_list]:getSharesEnergyWithDocked())
2585			pStation:setRepairDocked(human_ref_list[#human_ref_list]:getRepairDocked())
2586			pStation:setRestocksScanProbes(human_ref_list[#human_ref_list]:getRestocksScanProbes())
2587			table.insert(place_ref_list,pStation)
2588			if scientist_list["Human Navy"] ~= nil then
2589				if scientist_list["Exuari"] == nil then
2590					scientist_list["Exuari"] = {}
2591				end
2592				if #scientist_list["Exuari"] < #scientist_list["Human Navy"] then
2593					table.insert(
2594						scientist_list["Exuari"],
2595						{
2596							name = tableRemoveRandom(scientist_names),
2597							topic = scientist_list["Human Navy"][#scientist_list["Human Navy"]].topic,
2598							location = pStation,
2599							location_name = pStation:getCallSign(),
2600							score_value = scientist_score_value,
2601							upgrade_requirement = upgrade_requirements[math.random(1,#upgrade_requirements)],
2602							upgrade = scientist_list["Human Navy"][#scientist_list["Human Navy"]].upgrade,
2603							upgrade_automated_application = scientist_list["Human Navy"][#scientist_list["Human Navy"]].upgrade_automated_application,
2604						}
2605					)
2606				end
2607			end
2608		end
2609		if ktlitan_angle ~= nil then
2610			obj_ref_angle = (obj_ref_angle + replicant_increment) % 360
2611			rep_x, rep_y = vectorFromAngleNorth(obj_ref_angle,obj_ref_distance)
2612			pStation = placeStation(terrain_center_x + rep_x, terrain_center_y + rep_y, "Random","Ktlitans",sr_size)
2613			table.insert(station_list["Ktlitans"],pStation)
2614			pStation.score_value = base_station_value_list[sr_size]
2615			pStation.comms_data = human_ref_list[#human_ref_list].comms_data
2616			pStation:setSharesEnergyWithDocked(human_ref_list[#human_ref_list]:getSharesEnergyWithDocked())
2617			pStation:setRepairDocked(human_ref_list[#human_ref_list]:getRepairDocked())
2618			pStation:setRestocksScanProbes(human_ref_list[#human_ref_list]:getRestocksScanProbes())
2619			table.insert(place_ref_list,pStation)
2620			if scientist_list["Human Navy"] ~= nil then
2621				if scientist_list["Ktlitans"] == nil then
2622					scientist_list["Ktlitans"] = {}
2623				end
2624				if #scientist_list["Ktlitans"] < #scientist_list["Human Navy"] then
2625					table.insert(
2626						scientist_list["Ktlitans"],
2627						{
2628							name = tableRemoveRandom(scientist_names),
2629							topic = scientist_list["Human Navy"][#scientist_list["Human Navy"]].topic,
2630							location = pStation,
2631							location_name = pStation:getCallSign(),
2632							score_value = scientist_score_value,
2633							upgrade_requirement = upgrade_requirements[math.random(1,#upgrade_requirements)],
2634							upgrade = scientist_list["Human Navy"][#scientist_list["Human Navy"]].upgrade,
2635							upgrade_automated_application = scientist_list["Human Navy"][#scientist_list["Human Navy"]].upgrade_automated_application,
2636						}
2637					)
2638				end
2639			end
2640		end
2641	end	--station build loop
2642
2643	--	Build some wormholes if applicable
2644	local hole_list = {}
2645	local wormhole_count = math.random(0,3)
2646	if wormhole_count > 0 then
2647		for w=1,wormhole_count do
2648			center_x, center_y, perimeter, avg_dist = analyzeBlob(human_ref_list)
2649			stretch_bound = 5000
2650			bubble = 6000
2651			repeat
2652--				print("wormhole candidate numbers. average distance:",avg_dist,"perimeter:",perimeter)
2653				candidate_x, candidate_y = vectorFromAngleNorth(random(0,360),random(math.min(avg_dist,20000),math.min(perimeter,100000) + stretch_bound))
2654				candidate_x = center_x + candidate_x
2655				candidate_y = center_y + candidate_y
2656				stretch_bound = stretch_bound + 500
2657			until(farEnough(place_ref_list,candidate_x,candidate_y,bubble))
2658			local wormhole = WormHole():setPosition(candidate_x,candidate_y)
2659			table.insert(place_ref_list,wormhole)
2660			table.insert(human_ref_list,wormhole)
2661			table.insert(hole_list,wormhole)
2662			center_x, center_y, perimeter, avg_dist = analyzeBlob(human_ref_list)
2663			stretch_bound = 5000
2664			local target_candidate_x = 0
2665			local target_candidate_y = 0
2666			repeat
2667				target_candidate_x, target_candidate_y = vectorFromAngleNorth(random(0,360),random(avg_dist,50000 + perimeter + stretch_bound))
2668				target_candidate_x = center_x + target_candidate_x
2669				target_candidate_y = center_y + target_candidate_y
2670				stretch_bound = stretch_bound + 500
2671			until(farEnough(place_ref_list,target_candidate_x,target_candidate_y,bubble))
2672			local ta = VisualAsteroid():setPosition(target_candidate_x,target_candidate_y)
2673			table.insert(place_ref_list,ta)
2674			table.insert(human_ref_list,ta)
2675			wormhole:setTargetPosition(target_candidate_x,target_candidate_y)
2676
2677			local obj_ref_angle = angleFromVectorNorth(candidate_x, candidate_y, terrain_center_x, terrain_center_y)
2678			local obj_ref_distance = distance(terrain_center_x, terrain_center_y, candidate_x, candidate_y)
2679			obj_ref_angle = (obj_ref_angle + replicant_increment) % 360
2680			local rep_x, rep_y = vectorFromAngleNorth(obj_ref_angle,obj_ref_distance)
2681			wormhole = WormHole():setPosition(terrain_center_x + rep_x, terrain_center_y + rep_y)
2682			table.insert(place_ref_list,wormhole)
2683			table.insert(hole_list,wormhole)
2684			local target_ref_angle = angleFromVectorNorth(target_candidate_x, target_candidate_y, terrain_center_x, terrain_center_y)
2685			local target_ref_distance = distance(terrain_center_x, terrain_center_y, target_candidate_x, target_candidate_y)
2686			target_ref_angle = (target_ref_angle + replicant_increment) % 360
2687			rep_x, rep_y = vectorFromAngleNorth(target_ref_angle,target_ref_distance)
2688			wormhole:setTargetPosition(terrain_center_x + rep_x, terrain_center_y + rep_y)
2689
2690			if exuari_angle ~= nil then
2691				obj_ref_angle = (obj_ref_angle + replicant_increment) % 360
2692				rep_x, rep_y = vectorFromAngleNorth(obj_ref_angle,obj_ref_distance)
2693				wormhole = WormHole():setPosition(terrain_center_x + rep_x, terrain_center_y + rep_y)
2694				table.insert(place_ref_list,wormhole)
2695				table.insert(hole_list,wormhole)
2696				target_ref_angle = (target_ref_angle + replicant_increment) % 360
2697				rep_x, rep_y = vectorFromAngleNorth(target_ref_angle,target_ref_distance)
2698				wormhole:setTargetPosition(terrain_center_x + rep_x, terrain_center_y + rep_y)
2699			end
2700			if ktlitan_angle ~= nil then
2701				obj_ref_angle = (obj_ref_angle + replicant_increment) % 360
2702				rep_x, rep_y = vectorFromAngleNorth(obj_ref_angle,obj_ref_distance)
2703				wormhole = WormHole():setPosition(terrain_center_x + rep_x, terrain_center_y + rep_y)
2704				table.insert(place_ref_list,wormhole)
2705				table.insert(hole_list,wormhole)
2706				target_ref_angle = (target_ref_angle + replicant_increment) % 360
2707				rep_x, rep_y = vectorFromAngleNorth(target_ref_angle,target_ref_distance)
2708				wormhole:setTargetPosition(terrain_center_x + rep_x, terrain_center_y + rep_y)
2709			end
2710		end
2711	end	--wormhole build
2712
2713	--	Maybe sprinkle in some black holes
2714	local blackhole_count = math.random(0,6)
2715	if blackhole_count > 0 then
2716		for b=1,blackhole_count do
2717			center_x, center_y, perimeter, avg_dist = analyzeBlob(human_ref_list)
2718			stretch_bound = 5000
2719			bubble = 6000
2720			repeat
2721				candidate_x, candidate_y = vectorFromAngleNorth(random(0,360),random(math.min(avg_dist,20000),math.min(perimeter,100000) + stretch_bound))
2722				candidate_x = center_x + candidate_x
2723				candidate_y = center_y + candidate_y
2724				stretch_bound = stretch_bound + 500
2725			until(farEnough(place_ref_list,candidate_x,candidate_y,bubble))
2726			local blackhole = BlackHole():setPosition(candidate_x,candidate_y)
2727			table.insert(place_ref_list,blackhole)
2728			table.insert(human_ref_list,blackhole)
2729			table.insert(hole_list,blackhole)
2730			local obj_ref_angle = angleFromVectorNorth(candidate_x, candidate_y, terrain_center_x, terrain_center_y)
2731			local obj_ref_distance = distance(terrain_center_x, terrain_center_y, candidate_x, candidate_y)
2732			obj_ref_angle = (obj_ref_angle + replicant_increment) % 360
2733			local rep_x, rep_y = vectorFromAngleNorth(obj_ref_angle,obj_ref_distance)
2734			blackhole = BlackHole():setPosition(terrain_center_x + rep_x, terrain_center_y + rep_y)
2735			table.insert(place_ref_list,blackhole)
2736			table.insert(hole_list,blackhole)
2737			if exuari_angle ~= nil then
2738				obj_ref_angle = (obj_ref_angle + replicant_increment) % 360
2739				rep_x, rep_y = vectorFromAngleNorth(obj_ref_angle,obj_ref_distance)
2740				blackhole = BlackHole():setPosition(terrain_center_x + rep_x, terrain_center_y + rep_y)
2741				table.insert(place_ref_list,blackhole)
2742				table.insert(hole_list,blackhole)
2743			end
2744			if ktlitan_angle ~= nil then
2745				obj_ref_angle = (obj_ref_angle + replicant_increment) % 360
2746				rep_x, rep_y = vectorFromAngleNorth(obj_ref_angle,obj_ref_distance)
2747				blackhole = BlackHole():setPosition(terrain_center_x + rep_x, terrain_center_y + rep_y)
2748				table.insert(place_ref_list,blackhole)
2749				table.insert(hole_list,blackhole)
2750			end
2751		end
2752	end	--blackhole build
2753
2754	local mine_field_count = math.random(0,(6-player_team_count))
2755	local mine_field_type_list = {"line","arc"}
2756	if mine_field_count > 0 then
2757		for m=1,mine_field_count do
2758			center_x, center_y, perimeter, avg_dist = analyzeBlob(human_ref_list)
2759			stretch_bound = 5000
2760			bubble = 6000
2761			repeat
2762				candidate_x, candidate_y = vectorFromAngleNorth(random(0,360),random(math.min(avg_dist,20000),math.min(perimeter,100000) + stretch_bound))
2763				candidate_x = center_x + candidate_x
2764				candidate_y = center_y + candidate_y
2765				stretch_bound = stretch_bound + 500
2766			until(farEnough(place_ref_list,candidate_x,candidate_y,bubble))
2767			local mine_field_type = mine_field_type_list[math.random(1,#mine_field_type_list)]
2768			local mine_list = {}
2769			local mine_ref_list = {}
2770			if mine_field_type == "line" then
2771				local mle_x, mle_y = vectorFromAngleNorth(random(0,360),random(8000,30000))
2772				mine_list = createObjectsListOnLine(candidate_x + mle_x, candidate_y + mle_y, candidate_x, candidate_y, 1200, Mine, math.random(1,3))
2773				for i=1,#mine_list do
2774					local tm = mine_list[i]
2775					local mx, my = tm:getPosition()
2776					if farEnough(place_ref_list,mx,my,1000) and farEnough(mine_ref_list,mx,my,1000) then
2777						table.insert(mine_ref_list,tm)
2778						local obj_ref_angle = angleFromVectorNorth(mx, my, terrain_center_x, terrain_center_y)
2779						local obj_ref_distance = distance(terrain_center_x, terrain_center_y, mx, my)
2780						obj_ref_angle = (obj_ref_angle + replicant_increment) % 360
2781						local rep_x, rep_y = vectorFromAngleNorth(obj_ref_angle,obj_ref_distance)
2782						table.insert(mine_ref_list,Mine():setPosition(terrain_center_x + rep_x, terrain_center_y + rep_y))
2783						if exuari_angle ~= nil then
2784							obj_ref_angle = (obj_ref_angle + replicant_increment) % 360
2785							rep_x, rep_y = vectorFromAngleNorth(obj_ref_angle,obj_ref_distance)
2786							table.insert(mine_ref_list,Mine():setPosition(terrain_center_x + rep_x, terrain_center_y + rep_y))
2787						end
2788						if ktlitan_angle ~= nil then
2789							obj_ref_angle = (obj_ref_angle + replicant_increment) % 360
2790							rep_x, rep_y = vectorFromAngleNorth(obj_ref_angle,obj_ref_distance)
2791							table.insert(mine_ref_list,Mine():setPosition(terrain_center_x + rep_x, terrain_center_y + rep_y))
2792						end
2793					else
2794						tm:destroy()
2795					end
2796				end
2797				for _, tm in ipairs(mine_ref_list) do
2798					table.insert(place_ref_list,tm)
2799				end
2800			elseif mine_field_type == "arc" then
2801				local arc_radius = random(8000,25000)
2802				local mid_angle = random(0,360)
2803				local spread = random(10,30)
2804				local angle = (mid_angle + (180 - spread) % 360)
2805				local mar_x, mar_y = vectorFromAngleNorth(angle,arc_radius)
2806				local mar_x = mar_x + candidate_x
2807				local mar_y = mar_y + candidate_y
2808				local final_angle = (mid_angle + (180 + spread)) % 360
2809				local mine_count = 0
2810				local mx, my = vectorFromAngleNorth(angle,arc_radius)
2811				local tm = Mine():setPosition(mar_x + mx, mar_y + my)
2812				table.insert(mine_list,tm)
2813				local angle_increment = 0
2814				repeat
2815					angle_increment = angle_increment + 0.1
2816					mx, my = vectorFromAngleNorth(angle + angle_increment,arc_radius)
2817				until(distance(tm,mar_x + mx, mar_y + my) > 1200)
2818				if final_angle <= angle then
2819					final_angle = final_angle + 360
2820				end
2821				repeat
2822					angle = angle + angle_increment
2823					mx, my = vectorFromAngleNorth(angle,arc_radius)
2824					tm = Mine():setPosition(mar_x + mx, mar_y + my)
2825					table.insert(mine_list,tm)
2826				until(angle > final_angle)
2827				for i=1,#mine_list do
2828					local tm = mine_list[i]
2829					local mx, my = tm:getPosition()
2830					if farEnough(place_ref_list,mx,my,1000) and farEnough(mine_ref_list,mx,my,1000) then
2831						table.insert(mine_ref_list,tm)
2832						local obj_ref_angle = angleFromVectorNorth(mx, my, terrain_center_x, terrain_center_y)
2833						local obj_ref_distance = distance(terrain_center_x, terrain_center_y, mx, my)
2834						obj_ref_angle = (obj_ref_angle + replicant_increment) % 360
2835						local rep_x, rep_y = vectorFromAngleNorth(obj_ref_angle,obj_ref_distance)
2836						table.insert(mine_ref_list,Mine():setPosition(terrain_center_x + rep_x, terrain_center_y + rep_y))
2837						if exuari_angle ~= nil then
2838							obj_ref_angle = (obj_ref_angle + replicant_increment) % 360
2839							rep_x, rep_y = vectorFromAngleNorth(obj_ref_angle,obj_ref_distance)
2840							table.insert(mine_ref_list,Mine():setPosition(terrain_center_x + rep_x, terrain_center_y + rep_y))
2841						end
2842						if ktlitan_angle ~= nil then
2843							obj_ref_angle = (obj_ref_angle + replicant_increment) % 360
2844							rep_x, rep_y = vectorFromAngleNorth(obj_ref_angle,obj_ref_distance)
2845							table.insert(mine_ref_list,Mine():setPosition(terrain_center_x + rep_x, terrain_center_y + rep_y))
2846						end
2847					else
2848						tm:destroy()
2849					end
2850				end
2851				for _, tm in ipairs(mine_ref_list) do
2852					table.insert(place_ref_list,tm)
2853				end
2854			end
2855		end
2856	end
2857
2858	--	Asteroid build
2859	local asteroid_field_count = math.random(2,(10-player_team_count))
2860	local asteroid_field_type_list = {"blob","line","arc"}
2861	for a=1,asteroid_field_count do
2862		center_x, center_y, perimeter, avg_dist = analyzeBlob(human_ref_list)
2863		stretch_bound = 5000
2864		bubble = 6000
2865		repeat
2866			candidate_x, candidate_y = vectorFromAngleNorth(random(0,360),random(math.min(avg_dist,20000),math.min(perimeter,100000) + stretch_bound))
2867			candidate_x = center_x + candidate_x
2868			candidate_y = center_y + candidate_y
2869			stretch_bound = stretch_bound + 500
2870		until(farEnough(place_ref_list,candidate_x,candidate_y,bubble))
2871		local asteroid_field_type = asteroid_field_type_list[math.random(1,#asteroid_field_type_list)]
2872		local asteroid_list = {}
2873		local asteroid_ref_list = {}
2874		if asteroid_field_type == "blob" then
2875			local blob_count = math.random(10,30)
2876--			print("blob count:",blob_count)
2877			asteroid_list = placeRandomListAroundPoint(Asteroid,blob_count,100,15000,candidate_x,candidate_y)
2878			for i=1,#asteroid_list do
2879				local ta = asteroid_list[i]
2880				local ax, ay = ta:getPosition()
2881				local as = asteroidSize()
2882				if farEnough(place_ref_list,ax,ay,as) and farEnough(asteroid_ref_list,ax,ay,as) then
2883					ta:setSize(as)
2884					table.insert(asteroid_ref_list,ta)
2885					local obj_ref_angle = angleFromVectorNorth(ax, ay, terrain_center_x, terrain_center_y)
2886					local obj_ref_distance = distance(terrain_center_x, terrain_center_y, ax, ay)
2887					obj_ref_angle = (obj_ref_angle + replicant_increment) % 360
2888					local rep_x, rep_y = vectorFromAngleNorth(obj_ref_angle,obj_ref_distance)
2889					table.insert(asteroid_ref_list,Asteroid():setPosition(terrain_center_x + rep_x, terrain_center_y + rep_y):setSize(as))
2890					if exuari_angle ~= nil then
2891						obj_ref_angle = (obj_ref_angle + replicant_increment) % 360
2892						rep_x, rep_y = vectorFromAngleNorth(obj_ref_angle,obj_ref_distance)
2893						table.insert(asteroid_ref_list,Asteroid():setPosition(terrain_center_x + rep_x, terrain_center_y + rep_y):setSize(as))
2894					end
2895					if ktlitan_angle ~= nil then
2896						obj_ref_angle = (obj_ref_angle + replicant_increment) % 360
2897						rep_x, rep_y = vectorFromAngleNorth(obj_ref_angle,obj_ref_distance)
2898						table.insert(asteroid_ref_list,Asteroid():setPosition(terrain_center_x + rep_x, terrain_center_y + rep_y):setSize(as))
2899					end
2900				else
2901					ta:destroy()
2902				end
2903			end
2904			for _, ta in ipairs(asteroid_ref_list) do
2905				table.insert(place_ref_list,ta)
2906			end
2907		elseif asteroid_field_type == "line" then
2908--			print("asteroid line")
2909			local ale_x, ale_y = vectorFromAngleNorth(random(0,360),random(8000,30000))
2910			asteroid_list = createObjectsListOnLine(candidate_x + ale_x, candidate_y + ale_y, candidate_x, candidate_y, random(500,900), Asteroid, 7, 25, 250)
2911			for i=1,#asteroid_list do
2912				local ta = asteroid_list[i]
2913				local ax, ay = ta:getPosition()
2914				local as = asteroidSize()
2915				if farEnough(place_ref_list,ax,ay,as) and farEnough(asteroid_ref_list,ax,ay,as) then
2916					ta:setSize(as)
2917					table.insert(asteroid_ref_list,ta)
2918					local obj_ref_angle = angleFromVectorNorth(ax, ay, terrain_center_x, terrain_center_y)
2919					local obj_ref_distance = distance(terrain_center_x, terrain_center_y, ax, ay)
2920					obj_ref_angle = (obj_ref_angle + replicant_increment) % 360
2921					local rep_x, rep_y = vectorFromAngleNorth(obj_ref_angle,obj_ref_distance)
2922					table.insert(asteroid_ref_list,Asteroid():setPosition(terrain_center_x + rep_x, terrain_center_y + rep_y):setSize(as))
2923					if exuari_angle ~= nil then
2924						obj_ref_angle = (obj_ref_angle + replicant_increment) % 360
2925						rep_x, rep_y = vectorFromAngleNorth(obj_ref_angle,obj_ref_distance)
2926						table.insert(asteroid_ref_list,Asteroid():setPosition(terrain_center_x + rep_x, terrain_center_y + rep_y):setSize(as))
2927					end
2928					if ktlitan_angle ~= nil then
2929						obj_ref_angle = (obj_ref_angle + replicant_increment) % 360
2930						rep_x, rep_y = vectorFromAngleNorth(obj_ref_angle,obj_ref_distance)
2931						table.insert(asteroid_ref_list,Asteroid():setPosition(terrain_center_x + rep_x, terrain_center_y + rep_y):setSize(as))
2932					end
2933				else
2934					ta:destroy()
2935				end
2936			end
2937			for _, ta in ipairs(asteroid_ref_list) do
2938				table.insert(place_ref_list,ta)
2939			end
2940		elseif asteroid_field_type == "arc" then
2941			local angle_to_radius = random(0,360)
2942			local radius_to_arc = random(8000,25000)
2943			local aar_x, aar_y = vectorFromAngleNorth(angle_to_radius,radius_to_arc)
2944			local spread = random(10,30)
2945			local number_in_arc = math.min(math.floor(spread * 2) + math.random(5,20),35)
2946--			print("asteroid arc number:",number_in_arc)
2947			asteroid_list = createRandomListAlongArc(Asteroid, number_in_arc, candidate_x + aar_x, candidate_y + aar_y, radius_to_arc, (angle_to_radius + (180-spread)) % 360, (angle_to_radius + (180+spread)) % 360, 1000)
2948			for i=1,#asteroid_list do
2949				local ta = asteroid_list[i]
2950				local ax, ay = ta:getPosition()
2951				local as = asteroidSize()
2952				if farEnough(place_ref_list,ax,ay,as) and farEnough(asteroid_ref_list,ax,ay,as) then
2953					ta:setSize(as)
2954					table.insert(asteroid_ref_list,ta)
2955					local obj_ref_angle = angleFromVectorNorth(ax, ay, terrain_center_x, terrain_center_y)
2956					local obj_ref_distance = distance(terrain_center_x, terrain_center_y, ax, ay)
2957					obj_ref_angle = (obj_ref_angle + replicant_increment) % 360
2958					local rep_x, rep_y = vectorFromAngleNorth(obj_ref_angle,obj_ref_distance)
2959					table.insert(asteroid_ref_list,Asteroid():setPosition(terrain_center_x + rep_x, terrain_center_y + rep_y):setSize(as))
2960					if exuari_angle ~= nil then
2961						obj_ref_angle = (obj_ref_angle + replicant_increment) % 360
2962						rep_x, rep_y = vectorFromAngleNorth(obj_ref_angle,obj_ref_distance)
2963						table.insert(asteroid_ref_list,Asteroid():setPosition(terrain_center_x + rep_x, terrain_center_y + rep_y):setSize(as))
2964					end
2965					if ktlitan_angle ~= nil then
2966						obj_ref_angle = (obj_ref_angle + replicant_increment) % 360
2967						rep_x, rep_y = vectorFromAngleNorth(obj_ref_angle,obj_ref_distance)
2968						table.insert(asteroid_ref_list,Asteroid():setPosition(terrain_center_x + rep_x, terrain_center_y + rep_y):setSize(as))
2969					end
2970				else
2971					ta:destroy()
2972				end
2973			end
2974			for _, ta in ipairs(asteroid_ref_list) do
2975				table.insert(place_ref_list,ta)
2976			end
2977		end
2978	end	--	asteroid fields build
2979
2980	--	Nebula build
2981	local nebula_field_count = math.random(2,8)
2982	center_x, center_y, perimeter, avg_dist = analyzeBlob(human_ref_list)
2983	for n=1,nebula_field_count do
2984		stretch_bound = 5000
2985		bubble = 7000
2986		repeat
2987			candidate_x, candidate_y = vectorFromAngleNorth(random(0,360),random(math.min(avg_dist,20000),math.min(perimeter,100000) + stretch_bound))
2988			candidate_x = center_x + candidate_x
2989			candidate_y = center_y + candidate_y
2990			stretch_bound = stretch_bound + 500
2991		until(farEnough(hole_list,candidate_x,candidate_y,bubble))
2992		local neb = Nebula():setPosition(candidate_x,candidate_y)
2993		local nebula_field = {}
2994		table.insert(nebula_field,neb)
2995		local nebula_field_size = math.random(0,5)
2996		if nebula_field_size > 0 then
2997			for i=1,nebula_field_size do
2998				local na_x = 0
2999				local na_y = 0
3000				local nx = 0
3001				local ny = 0
3002				local attempts = 0
3003				repeat
3004					na_x, na_y = vectorFromAngleNorth(random(0,360),random(8000,9500))
3005					nx, ny = nebula_field[math.random(1,#nebula_field)]:getPosition()
3006					attempts = attempts + 1
3007				until(farEnough(hole_list, na_x + nx, na_y + ny, bubble) or attempts > 50)
3008				if attempts <= 50 then
3009					neb = Nebula():setPosition(na_x + nx, na_y + ny)
3010					table.insert(nebula_field,neb)
3011				else
3012					break
3013				end
3014			end
3015		end
3016		for i=1,#nebula_field do
3017			candidate_x, candidate_y = nebula_field[i]:getPosition()
3018			local obj_ref_angle = angleFromVectorNorth(candidate_x, candidate_y, terrain_center_x, terrain_center_y)
3019			local obj_ref_distance = distance(terrain_center_x, terrain_center_y, candidate_x, candidate_y)
3020			obj_ref_angle = (obj_ref_angle + replicant_increment) % 360
3021			local rep_x, rep_y = vectorFromAngleNorth(obj_ref_angle,obj_ref_distance)
3022			Nebula():setPosition(terrain_center_x + rep_x, terrain_center_y + rep_y)
3023			if exuari_angle ~= nil then
3024				obj_ref_angle = (obj_ref_angle + replicant_increment) % 360
3025				rep_x, rep_y = vectorFromAngleNorth(obj_ref_angle,obj_ref_distance)
3026				Nebula():setPosition(terrain_center_x + rep_x, terrain_center_y + rep_y)
3027			end
3028			if ktlitan_angle ~= nil then
3029				obj_ref_angle = (obj_ref_angle + replicant_increment) % 360
3030				rep_x, rep_y = vectorFromAngleNorth(obj_ref_angle,obj_ref_distance)
3031				Nebula():setPosition(terrain_center_x + rep_x, terrain_center_y + rep_y)
3032			end
3033		end
3034	end	--	nebula field build
3035	game_state = "terrain generated"
3036
3037	--	Store (then print) original values for later comparison
3038	local stat_list = gatherStats()
3039	original_score = {}
3040	local out = "Original scores:"
3041	original_score["Human Navy"] = stat_list.human.weighted_score
3042	out = out .. string.format("\nHuman Navy: %.2f",stat_list.human.weighted_score)
3043	original_score["Kraylor"] = stat_list.kraylor.weighted_score
3044	out = out .. string.format("\nKraylor: %.2f",stat_list.kraylor.weighted_score)
3045	if exuari_angle ~= nil then
3046		original_score["Exuari"] = stat_list.exuari.weighted_score
3047		out = out .. string.format("\nExuari: %.2f",stat_list.exuari.weighted_score)
3048	end
3049	if ktlitan_angle ~= nil then
3050		original_score["Ktlitans"] = stat_list.ktlitan.weighted_score
3051		out = out .. string.format("\nKtlitans: %.2f",stat_list.ktlitan.weighted_score)
3052	end
3053	allowNewPlayerShips(false)
3054	print(out)
3055
3056	--	Provide summary terrain details in console log
3057	print("-----     Terrain Info     -----")
3058	print("Center:",terrain_center_sector,"featuring:",center_choice)
3059	print("Primary stations:",primary_station_size,"Jammers:",primary_jammers,"defense platforms:",defense_platform_count)
3060	local output_player_types = player_ship_types
3061	if player_ship_types == "custom" then
3062		output_player_types = output_player_types .. " (" .. custom_player_ship_type .. ")"
3063	end
3064	print("Teams:",player_team_count,"Player ships:",ships_per_team .. "(" .. ships_per_team*player_team_count .. ")","Player ship types:",output_player_types)
3065	print("NPC Fleets:",npc_fleet_count .. "(" .. npc_fleet_count*player_team_count .. ")")
3066	print("Wormholes:",wormhole_count .. "(" .. wormhole_count*player_team_count .. ")","Black holes:",blackhole_count .. "(" .. blackhole_count*player_team_count .. ")")
3067	print("Asteroid fields:",asteroid_field_count .. "(" .. asteroid_field_count*player_team_count .. ")","Nebula groups:",nebula_field_count .. "(" .. nebula_field_count*player_team_count .. ")")
3068end
3069function spawnRandomArmed(x, y, enemyStrength, fleetIndex, shape, angle)
3070--x and y are central spawn coordinates
3071--fleetIndex is the number of the fleet to be spawned
3072--sl (was) the score list, nl is the name list, bl is the boolean list
3073--spawn_distance optional - used for ambush or pyramid
3074--spawn_angle optional - used for ambush or pyramid
3075--px and py are the player coordinates or the pyramid fly towards point coordinates
3076	local sp = 1000			--spacing of spawned group
3077	if shape == nil then
3078		local shape_choices = {"square","hexagonal"}
3079		shape = shape_choices[math.random(1,#shape_choices)]
3080	end
3081	local enemy_position = 0
3082	local enemyList = {}
3083	local template_pool = getTemplatePool(enemyStrength)
3084	if #template_pool < 1 then
3085		addGMMessage("Empty Template pool: fix excludes or other criteria")
3086		return enemyList
3087	end
3088	local fleet_prefix = generateCallSignPrefix()
3089	while enemyStrength > 0 do
3090		local selected_template = template_pool[math.random(1,#template_pool)]
3091--		print("selected template:",selected_template)
3092--		print("base:",ship_template[selected_template].base)
3093		local ship = ship_template[selected_template].create("Human Navy",selected_template)
3094		ship:setCallSign(generateCallSign(fleet_prefix))
3095		ship:setCommsScript(""):setCommsFunction(commsShip)
3096		ship:orderIdle()
3097		ship:setHeading(angle)
3098		ship:setRotation(angle + 270)
3099		enemy_position = enemy_position + 1
3100		ship:setPosition(x + formation_delta[shape].x[enemy_position] * sp, y + formation_delta[shape].y[enemy_position] * sp)
3101		ship.fleetIndex = fleetIndex
3102		table.insert(enemyList, ship)
3103		enemyStrength = enemyStrength - ship_template[selected_template].strength
3104	end
3105	return enemyList
3106end
3107function getTemplatePool(max_strength)
3108	local function getStrengthSort(tbl, sortFunction)
3109		local keys = {}
3110		for key in pairs(tbl) do
3111			table.insert(keys,key)
3112		end
3113		table.sort(keys, function(a,b)
3114			return sortFunction(tbl[a], tbl[b])
3115		end)
3116		return keys
3117	end
3118	local ship_template_by_strength = getStrengthSort(ship_template, function(a,b)
3119		return a.strength > b.strength
3120	end)
3121	local template_pool = {}
3122--	print("fleet composition:",fleetComposition,"fleet group sub fleet composition:",fleet_group[fleetComposition])
3123	if pool_selectivity == "less/heavy" then
3124		for _, current_ship_template in ipairs(ship_template_by_strength) do
3125--			print("currrent ship template:",current_ship_template,"strength:",ship_template[current_ship_template].strength,"max strength:",max_strength)
3126			if ship_template[current_ship_template].strength <= max_strength then
3127				if fleetComposition == "Non-DB" then
3128					if ship_template[current_ship_template].create ~= stockTemplate then
3129						table.insert(template_pool,current_ship_template)
3130					end
3131				elseif fleetComposition == "Random" then
3132					table.insert(template_pool,current_ship_template)
3133				else
3134					if ship_template[current_ship_template][fleet_group[fleetComposition]] then
3135						table.insert(template_pool,current_ship_template)
3136					end
3137				end
3138			end
3139			if #template_pool >= 5 then
3140				break
3141			end
3142		end
3143	elseif pool_selectivity == "more/light" then
3144		for i=#ship_template_by_strength,1,-1 do
3145			local current_ship_template = ship_template_by_strength[i]
3146--			print("currrent ship template:",current_ship_template,"strength:",ship_template[current_ship_template].strength,"max strength:",max_strength)
3147			if ship_template[current_ship_template].strength <= max_strength then
3148				if fleetComposition == "Non-DB" then
3149					if ship_template[current_ship_template].create ~= stockTemplate then
3150						table.insert(template_pool,current_ship_template)
3151					end
3152				elseif fleetComposition == "Random" then
3153					table.insert(template_pool,current_ship_template)
3154				else
3155					if ship_template[current_ship_template][fleet_group[fleetComposition]] then
3156						table.insert(template_pool,current_ship_template)
3157					end
3158				end
3159			end
3160			if #template_pool >= 20 then
3161				break
3162			end
3163		end
3164	else	--full
3165		for current_ship_template, details in pairs(ship_template) do
3166			if details.strength <= max_strength then
3167				if fleetComposition == "Non-DB" then
3168					if ship_template[current_ship_template].create ~= stockTemplate then
3169						table.insert(template_pool,current_ship_template)
3170					end
3171				elseif fleetComposition == "Random" then
3172					table.insert(template_pool,current_ship_template)
3173				else
3174					if ship_template[current_ship_template][fleet_group[fleetComposition]] then
3175						table.insert(template_pool,current_ship_template)
3176					end
3177				end
3178			end
3179		end
3180	end
3181	--print("returning template pool containing these templates:")
3182	--for _, template in ipairs(template_pool) do
3183	--	print(template)
3184	--end
3185	return template_pool
3186end
3187function stockTemplate(enemyFaction,template)
3188	local ship = CpuShip():setFaction(enemyFaction):setTemplate(template):orderRoaming()
3189	ship:onTakingDamage(function(self,instigator)
3190		string.format("")	--serious proton needs a global context
3191		if instigator ~= nil then
3192			self.damage_instigator = instigator
3193		end
3194	end)
3195	return ship
3196end
3197--------------------------------------------------------------------------------------------
3198--	Additional enemy ships with some modifications from the original template parameters  --
3199--------------------------------------------------------------------------------------------
3200function phobosR2(enemyFaction)
3201	local ship = CpuShip():setFaction(enemyFaction):setTemplate("Phobos T3"):orderRoaming()
3202	ship:onTakingDamage(function(self,instigator)
3203		string.format("")	--serious proton needs a global context
3204		if instigator ~= nil then
3205			self.damage_instigator = instigator
3206		end
3207	end)
3208	ship:setTypeName("Phobos R2")
3209	ship:setWeaponTubeCount(1)			--one tube (vs 2)
3210	ship:setWeaponTubeDirection(0,0)
3211	ship:setImpulseMaxSpeed(55)			--slower impulse (vs 60)
3212	ship:setRotationMaxSpeed(15)		--faster maneuver (vs 10)
3213	local phobos_r2_db = queryScienceDatabase("Ships","Frigate","Phobos R2")
3214	if phobos_r2_db == nil then
3215		local frigate_db = queryScienceDatabase("Ships","Frigate")
3216		frigate_db:addEntry("Phobos R2")
3217		phobos_r2_db = queryScienceDatabase("Ships","Frigate","Phobos R2")
3218		addShipToDatabase(
3219			queryScienceDatabase("Ships","Frigate","Phobos T3"),	--base ship database entry
3220			phobos_r2_db,	--modified ship database entry
3221			ship,			--ship just created, long description on the next line
3222			"The Phobos R2 model is very similar to the Phobos T3. It's got a faster turn speed, but only one missile tube",
3223			{
3224				{key = "Tube 0", value = "60 sec"},	--torpedo tube direction and load speed
3225			},
3226			nil
3227		)
3228	end
3229	return ship
3230end
3231function hornetMV52(enemyFaction)
3232	local ship = CpuShip():setFaction(enemyFaction):setTemplate("MT52 Hornet"):orderRoaming()
3233	ship:onTakingDamage(function(self,instigator)
3234		string.format("")	--serious proton needs a global context
3235		if instigator ~= nil then
3236			self.damage_instigator = instigator
3237		end
3238	end)
3239	ship:setTypeName("MV52 Hornet")
3240	ship:setBeamWeapon(0, 30, 0, 1000.0, 4.0, 3.0)	--longer and stronger beam (vs 700 & 3)
3241	ship:setRotationMaxSpeed(31)					--faster maneuver (vs 30)
3242	ship:setImpulseMaxSpeed(130)					--faster impulse (vs 120)
3243	local hornet_mv52_db = queryScienceDatabase("Ships","Starfighter","MV52 Hornet")
3244	if hornet_mv52_db == nil then
3245		local starfighter_db = queryScienceDatabase("Ships","Starfighter")
3246		starfighter_db:addEntry("MV52 Hornet")
3247		hornet_mv52_db = queryScienceDatabase("Ships","Starfighter","MV52 Hornet")
3248		addShipToDatabase(
3249			queryScienceDatabase("Ships","Starfighter","MT52 Hornet"),	--base ship database entry
3250			hornet_mv52_db,	--modified ship database entry
3251			ship,			--ship just created, long description on the next line
3252			"The MV52 Hornet is very similar to the MT52 and MU52 models. The beam does more damage than both of the other Hornet models, it's max impulse speed is faster than both of the other Hornet models, it turns faster than the MT52, but slower than the MU52",
3253			nil,
3254			nil
3255		)
3256	end
3257	return ship
3258end
3259function k2fighter(enemyFaction)
3260	local ship = CpuShip():setFaction(enemyFaction):setTemplate("Ktlitan Fighter"):orderRoaming()
3261	ship:setTypeName("K2 Fighter")
3262	ship:setBeamWeapon(0, 60, 0, 1200.0, 2.5, 6)	--beams cycle faster (vs 4.0)
3263	ship:setHullMax(65)								--weaker hull (vs 70)
3264	ship:setHull(65)
3265	local k2_fighter_db = queryScienceDatabase("Ships","No Class","K2 Fighter")
3266	if k2_fighter_db == nil then
3267		local no_class_db = queryScienceDatabase("Ships","No Class")
3268		no_class_db:addEntry("K2 Fighter")
3269		k2_fighter_db = queryScienceDatabase("Ships","No Class","K2 Fighter")
3270		addShipToDatabase(
3271			queryScienceDatabase("Ships","No Class","Ktlitan Fighter"),	--base ship database entry
3272			k2_fighter_db,	--modified ship database entry
3273			ship,			--ship just created, long description on the next line
3274			"Enterprising designers published this design specification based on salvaged Ktlitan Fighters. Comparatively, it's got beams that cycle faster, but the hull is a bit weaker.",
3275			nil,
3276			nil		--jump range
3277		)
3278	end
3279	return ship
3280end
3281function k3fighter(enemyFaction)
3282	local ship = CpuShip():setFaction(enemyFaction):setTemplate("Ktlitan Fighter"):orderRoaming()
3283	ship:setTypeName("K3 Fighter")
3284	ship:setBeamWeapon(0, 60, 0, 1200.0, 2.5, 9)	--beams cycle faster and damage more (vs 4.0 & 6)
3285	ship:setHullMax(60)								--weaker hull (vs 70)
3286	ship:setHull(60)
3287	local k3_fighter_db = queryScienceDatabase("Ships","No Class","K3 Fighter")
3288	if k3_fighter_db == nil then
3289		local no_class_db = queryScienceDatabase("Ships","No Class")
3290		no_class_db:addEntry("K3 Fighter")
3291		k3_fighter_db = queryScienceDatabase("Ships","No Class","K3 Fighter")
3292		addShipToDatabase(
3293			queryScienceDatabase("Ships","No Class","Ktlitan Fighter"),	--base ship database entry
3294			k3_fighter_db,	--modified ship database entry
3295			ship,			--ship just created, long description on the next line
3296			"Enterprising designers published this design specification based on salvaged Ktlitan Fighters. Comparatively, it's got beams that are stronger and that cycle faster, but the hull is weaker.",
3297			nil,
3298			nil		--jump range
3299		)
3300	end
3301	return ship
3302end
3303function waddle5(enemyFaction)
3304	local ship = CpuShip():setFaction(enemyFaction):setTemplate("Adder MK5"):orderRoaming()
3305	ship:onTakingDamage(function(self,instigator)
3306		string.format("")	--serious proton needs a global context
3307		if instigator ~= nil then
3308			self.damage_instigator = instigator
3309		end
3310	end)
3311	ship:setTypeName("Waddle 5")
3312	ship:setWarpDrive(true)
3313--				   Index,  Arc,	  Dir, Range, Cycle,	Damage
3314	ship:setBeamWeapon(2,	70,	  -30,	 600,	5.0,	2.0)	--adjust beam direction to match starboard side (vs -35)
3315	local waddle_5_db = queryScienceDatabase("Ships","Starfighter","Waddle 5")
3316	if waddle_5_db == nil then
3317		local starfighter_db = queryScienceDatabase("Ships","Starfighter")
3318		starfighter_db:addEntry("Waddle 5")
3319		waddle_5_db = queryScienceDatabase("Ships","Starfighter","Waddle 5")
3320		addShipToDatabase(
3321			queryScienceDatabase("Ships","Starfighter","Adder MK5"),	--base ship database entry
3322			waddle_5_db,	--modified ship database entry
3323			ship,			--ship just created, long description on the next line
3324			"Conversions R Us purchased a number of Adder MK 5 ships at auction and added warp drives to them to produce the Waddle 5",
3325			{
3326				{key = "Small tube 0", value = "15 sec"},	--torpedo tube direction and load speed
3327			},
3328			nil		--jump range
3329		)
3330	end
3331	return ship
3332end
3333function jade5(enemyFaction)
3334	local ship = CpuShip():setFaction(enemyFaction):setTemplate("Adder MK5"):orderRoaming()
3335	ship:onTakingDamage(function(self,instigator)
3336		string.format("")	--serious proton needs a global context
3337		if instigator ~= nil then
3338			self.damage_instigator = instigator
3339		end
3340	end)
3341	ship:setTypeName("Jade 5")
3342	ship:setJumpDrive(true)
3343	ship:setJumpDriveRange(5000,35000)
3344--				   Index,  Arc,	  Dir, Range, Cycle,	Damage
3345	ship:setBeamWeapon(2,	70,	  -30,	 600,	5.0,	2.0)	--adjust beam direction to match starboard side (vs -35)
3346	local jade_5_db = queryScienceDatabase("Ships","Starfighter","Jade 5")
3347	if jade_5_db == nil then
3348		local starfighter_db = queryScienceDatabase("Ships","Starfighter")
3349		starfighter_db:addEntry("Jade 5")
3350		jade_5_db = queryScienceDatabase("Ships","Starfighter","Jade 5")
3351		addShipToDatabase(
3352			queryScienceDatabase("Ships","Starfighter","Adder MK5"),	--base ship database entry
3353			jade_5_db,	--modified ship database entry
3354			ship,			--ship just created, long description on the next line
3355			"Conversions R Us purchased a number of Adder MK 5 ships at auction and added jump drives to them to produce the Jade 5",
3356			{
3357				{key = "Small tube 0", value = "15 sec"},	--torpedo tube direction and load speed
3358			},
3359			"5 - 35 U"		--jump range
3360		)
3361	end
3362	return ship
3363end
3364function droneLite(enemyFaction)
3365	local ship = CpuShip():setFaction(enemyFaction):setTemplate("Ktlitan Drone"):orderRoaming()
3366	ship:setTypeName("Lite Drone")
3367	ship:setHullMax(20)					--weaker hull (vs 30)
3368	ship:setHull(20)
3369	ship:setImpulseMaxSpeed(130)		--faster impulse (vs 120)
3370	ship:setRotationMaxSpeed(20)		--faster maneuver (vs 10)
3371	ship:setBeamWeapon(0,40,0,600,4,4)	--weaker (vs 6) beam
3372	local drone_lite_db = queryScienceDatabase("Ships","No Class","Lite Drone")
3373	if drone_lite_db == nil then
3374		local no_class_db = queryScienceDatabase("Ships","No Class")
3375		no_class_db:addEntry("Lite Drone")
3376		drone_lite_db = queryScienceDatabase("Ships","No Class","Lite Drone")
3377		addShipToDatabase(
3378			queryScienceDatabase("Ships","No Class","Ktlitan Drone"),	--base ship database entry
3379			drone_lite_db,	--modified ship database entry
3380			ship,			--ship just created, long description on the next line
3381			"The light drone was pieced together from scavenged parts of various damaged Ktlitan drones. Compared to the Ktlitan drone, the lite drone has a weaker hull, and a weaker beam, but a faster turn and impulse speed",
3382			nil,
3383			nil
3384		)
3385	end
3386	return ship
3387end
3388function droneHeavy(enemyFaction)
3389	local ship = CpuShip():setFaction(enemyFaction):setTemplate("Ktlitan Drone"):orderRoaming()
3390	ship:setTypeName("Heavy Drone")
3391	ship:setHullMax(40)					--stronger hull (vs 30)
3392	ship:setHull(40)
3393	ship:setImpulseMaxSpeed(110)		--slower impulse (vs 120)
3394	ship:setBeamWeapon(0,40,0,600,4,8)	--stronger (vs 6) beam
3395	local drone_heavy_db = queryScienceDatabase("Ships","No Class","Heavy Drone")
3396	if drone_heavy_db == nil then
3397		local no_class_db = queryScienceDatabase("Ships","No Class")
3398		no_class_db:addEntry("Heavy Drone")
3399		drone_heavy_db = queryScienceDatabase("Ships","No Class","Heavy Drone")
3400		addShipToDatabase(
3401			queryScienceDatabase("Ships","No Class","Ktlitan Drone"),	--base ship database entry
3402			drone_heavy_db,	--modified ship database entry
3403			ship,			--ship just created, long description on the next line
3404			"The heavy drone has a stronger hull and a stronger beam than the normal Ktlitan Drone, but it also moves slower",
3405			nil,
3406			nil
3407		)
3408	end
3409	return ship
3410end
3411function droneJacket(enemyFaction)
3412	local ship = CpuShip():setFaction(enemyFaction):setTemplate("Ktlitan Drone"):orderRoaming()
3413	ship:onTakingDamage(function(self,instigator)
3414		string.format("")	--serious proton needs a global context
3415		if instigator ~= nil then
3416			self.damage_instigator = instigator
3417		end
3418	end)
3419	ship:setTypeName("Jacket Drone")
3420	ship:setShieldsMax(20)				--stronger shields (vs none)
3421	ship:setShields(20)
3422	ship:setImpulseMaxSpeed(110)		--slower impulse (vs 120)
3423	ship:setBeamWeapon(0,40,0,600,4,4)	--weaker (vs 6) beam
3424	local drone_jacket_db = queryScienceDatabase("Ships","No Class","Jacket Drone")
3425	if drone_jacket_db == nil then
3426		local no_class_db = queryScienceDatabase("Ships","No Class")
3427		no_class_db:addEntry("Jacket Drone")
3428		drone_jacket_db = queryScienceDatabase("Ships","No Class","Jacket Drone")
3429		addShipToDatabase(
3430			queryScienceDatabase("Ships","No Class","Ktlitan Drone"),	--base ship database entry
3431			drone_jacket_db,	--modified ship database entry
3432			ship,			--ship just created, long description on the next line
3433			"The Jacket Drone is a Ktlitan Drone with a shield. It's also slightly slower and has a slightly weaker beam due to the energy requirements of the added shield",
3434			nil,
3435			nil
3436		)
3437	end
3438	return ship
3439end
3440function wzLindworm(enemyFaction)
3441	local ship = CpuShip():setFaction(enemyFaction):setTemplate("WX-Lindworm"):orderRoaming()
3442	ship:setTypeName("WZ-Lindworm")
3443	ship:setWeaponStorageMax("Nuke",2)		--more nukes (vs 0)
3444	ship:setWeaponStorage("Nuke",2)
3445	ship:setWeaponStorageMax("Homing",4)	--more homing (vs 1)
3446	ship:setWeaponStorage("Homing",4)
3447	ship:setWeaponStorageMax("HVLI",12)		--more HVLI (vs 6)
3448	ship:setWeaponStorage("HVLI",12)
3449	ship:setRotationMaxSpeed(12)			--slower maneuver (vs 15)
3450	ship:setHullMax(45)						--weaker hull (vs 50)
3451	ship:setHull(45)
3452	local wz_lindworm_db = queryScienceDatabase("Ships","Starfighter","WZ-Lindworm")
3453	if wz_lindworm_db == nil then
3454		local starfighter_db = queryScienceDatabase("Ships","Starfighter")
3455		starfighter_db:addEntry("WZ-Lindworm")
3456		wz_lindworm_db = queryScienceDatabase("Ships","Starfighter","WZ-Lindworm")
3457		addShipToDatabase(
3458			queryScienceDatabase("Ships","Starfighter","WX-Lindworm"),	--base ship database entry
3459			wz_lindworm_db,	--modified ship database entry
3460			ship,			--ship just created, long description on the next line
3461			"The WZ-Lindworm is essentially the stock WX-Lindworm with more HVLIs, more homing missiles and added nukes. They had to remove some of the armor to get the additional missiles to fit, so the hull is weaker. Also, the WZ turns a little more slowly than the WX. This little bomber packs quite a whallop.",
3462			{
3463				{key = "Small tube 0", value = "15 sec"},	--torpedo tube direction and load speed
3464				{key = "Small tube 1", value = "15 sec"},	--torpedo tube direction and load speed
3465				{key = "Small tube -1", value = "15 sec"},	--torpedo tube direction and load speed
3466			},
3467			nil
3468		)
3469	end
3470	return ship
3471end
3472function tempest(enemyFaction)
3473	local ship = CpuShip():setFaction(enemyFaction):setTemplate("Piranha F12"):orderRoaming()
3474	ship:onTakingDamage(function(self,instigator)
3475		string.format("")	--serious proton needs a global context
3476		if instigator ~= nil then
3477			self.damage_instigator = instigator
3478		end
3479	end)
3480	ship:setTypeName("Tempest")
3481	ship:setWeaponTubeCount(10)						--four more tubes (vs 6)
3482	ship:setWeaponTubeDirection(0, -88)				--5 per side
3483	ship:setWeaponTubeDirection(1, -89)				--slight angle spread
3484	ship:setWeaponTubeDirection(3,  88)				--3 for HVLI each side
3485	ship:setWeaponTubeDirection(4,  89)				--2 for homing and nuke each side
3486	ship:setWeaponTubeDirection(6, -91)
3487	ship:setWeaponTubeDirection(7, -92)
3488	ship:setWeaponTubeDirection(8,  91)
3489	ship:setWeaponTubeDirection(9,  92)
3490	ship:setWeaponTubeExclusiveFor(7,"HVLI")
3491	ship:setWeaponTubeExclusiveFor(9,"HVLI")
3492	ship:setWeaponStorageMax("Homing",16)			--more (vs 6)
3493	ship:setWeaponStorage("Homing", 16)
3494	ship:setWeaponStorageMax("Nuke",8)				--more (vs 0)
3495	ship:setWeaponStorage("Nuke", 8)
3496	ship:setWeaponStorageMax("HVLI",34)				--more (vs 20)
3497	ship:setWeaponStorage("HVLI", 34)
3498	local tempest_db = queryScienceDatabase("Ships","Frigate","Tempest")
3499	if tempest_db == nil then
3500		local frigate_db = queryScienceDatabase("Ships","Frigate")
3501		frigate_db:addEntry("Tempest")
3502		tempest_db = queryScienceDatabase("Ships","Frigate","Tempest")
3503		addShipToDatabase(
3504			queryScienceDatabase("Ships","Frigate","Piranha F12"),	--base ship database entry
3505			tempest_db,	--modified ship database entry
3506			ship,			--ship just created, long description on the next line
3507			"Loosely based on the Piranha F12 model, the Tempest adds four more broadside tubes (two on each side), more HVLIs, more Homing missiles and 8 Nukes. The Tempest can strike fear into the hearts of your enemies. Get yourself one today!",
3508			{
3509				{key = "Large tube -88", value = "15 sec"},	--torpedo tube direction and load speed
3510				{key = "Tube -89", value = "15 sec"},		--torpedo tube direction and load speed
3511				{key = "Large tube -90", value = "15 sec"},	--torpedo tube direction and load speed
3512				{key = "Large tube 88", value = "15 sec"},	--torpedo tube direction and load speed
3513				{key = "Tube 89", value = "15 sec"},		--torpedo tube direction and load speed
3514				{key = "Large tube 90", value = "15 sec"},	--torpedo tube direction and load speed
3515				{key = "Tube -91", value = "15 sec"},		--torpedo tube direction and load speed
3516				{key = "Tube -92", value = "15 sec"},		--torpedo tube direction and load speed
3517				{key = "Tube 91", value = "15 sec"},		--torpedo tube direction and load speed
3518				{key = "Tube 92", value = "15 sec"},		--torpedo tube direction and load speed
3519			},
3520			nil
3521		)
3522	end
3523	return ship
3524end
3525function enforcer(enemyFaction)
3526	local ship = CpuShip():setFaction(enemyFaction):setTemplate("Blockade Runner"):orderRoaming()
3527	ship:onTakingDamage(function(self,instigator)
3528		string.format("")	--serious proton needs a global context
3529		if instigator ~= nil then
3530			self.damage_instigator = instigator
3531		end
3532	end)
3533	ship:setTypeName("Enforcer")
3534	ship:setRadarTrace("radar_ktlitan_destroyer.png")			--different radar trace
3535	ship:setWarpDrive(true)										--warp (vs none)
3536	ship:setWarpSpeed(600)
3537	ship:setImpulseMaxSpeed(100)								--faster impulse (vs 60)
3538	ship:setRotationMaxSpeed(20)								--faster maneuver (vs 15)
3539	ship:setShieldsMax(200,100,100)								--stronger shields (vs 100,150)
3540	ship:setShields(200,100,100)
3541	ship:setHullMax(100)										--stronger hull (vs 70)
3542	ship:setHull(100)
3543--				   Index,  Arc,	  Dir, Range,	Cycle,	Damage
3544	ship:setBeamWeapon(0,	30,	  -15,	1500,		6,		10)	--narrower (vs 60), longer (vs 1000), stronger (vs 8)
3545	ship:setBeamWeapon(1,	30,	   15,	1500,		6,		10)
3546	ship:setBeamWeapon(2,	 0,	    0,	   0,		0,		 0)	--fewer (vs 4)
3547	ship:setBeamWeapon(3,	 0,	    0,	   0,		0,		 0)
3548	ship:setWeaponTubeCount(3)									--more (vs 0)
3549	ship:setTubeSize(0,"large")									--large (vs normal)
3550	ship:setWeaponTubeDirection(1,-30)
3551	ship:setWeaponTubeDirection(2, 30)
3552	ship:setWeaponStorageMax("Homing",18)						--more (vs 0)
3553	ship:setWeaponStorage("Homing", 18)
3554	local enforcer_db = queryScienceDatabase("Ships","Frigate","Enforcer")
3555	if enforcer_db == nil then
3556		local frigate_db = queryScienceDatabase("Ships","Frigate")
3557		frigate_db:addEntry("Enforcer")
3558		enforcer_db = queryScienceDatabase("Ships","Frigate","Enforcer")
3559		addShipToDatabase(
3560			queryScienceDatabase("Ships","Frigate","Blockade Runner"),	--base ship database entry
3561			enforcer_db,	--modified ship database entry
3562			ship,			--ship just created, long description on the next line
3563			"The Enforcer is a highly modified Blockade Runner. A warp drive was added and impulse engines boosted along with turning speed. Three missile tubes were added to shoot homing missiles, large ones straight ahead. Stronger shields and hull. Removed rear facing beams and strengthened front beams.",
3564			{
3565				{key = "Large tube 0", value = "20 sec"},	--torpedo tube direction and load speed
3566				{key = "Tube -30", value = "20 sec"},		--torpedo tube direction and load speed
3567				{key = "Tube 30", value = "20 sec"},		--torpedo tube direction and load speed
3568			},
3569			nil
3570		)
3571		enforcer_db:setImage("radar_ktlitan_destroyer.png")		--override default radar image
3572	end
3573	return ship
3574end
3575function predator(enemyFaction)
3576	local ship = CpuShip():setFaction(enemyFaction):setTemplate("Piranha F8"):orderRoaming()
3577	ship:onTakingDamage(function(self,instigator)
3578		string.format("")	--serious proton needs a global context
3579		if instigator ~= nil then
3580			self.damage_instigator = instigator
3581		end
3582	end)
3583	ship:setTypeName("Predator")
3584	ship:setShieldsMax(100,100)									--stronger shields (vs 30,30)
3585	ship:setShields(100,100)
3586	ship:setHullMax(80)											--stronger hull (vs 70)
3587	ship:setHull(80)
3588	ship:setImpulseMaxSpeed(65)									--faster impulse (vs 40)
3589	ship:setRotationMaxSpeed(15)								--faster maneuver (vs 6)
3590	ship:setJumpDrive(true)
3591	ship:setJumpDriveRange(5000,35000)
3592--				   Index,  Arc,	  Dir, Range,	Cycle,	Damage
3593	ship:setBeamWeapon(0,	90,	    0,	1000,		6,		 4)	--more (vs 0)
3594	ship:setBeamWeapon(1,	90,	  180,	1000,		6,		 4)
3595	ship:setWeaponTubeCount(8)									--more (vs 3)
3596	ship:setWeaponTubeDirection(0,-60)
3597	ship:setWeaponTubeDirection(1,-90)
3598	ship:setWeaponTubeDirection(2,-90)
3599	ship:setWeaponTubeDirection(3, 60)
3600	ship:setWeaponTubeDirection(4, 90)
3601	ship:setWeaponTubeDirection(5, 90)
3602	ship:setWeaponTubeDirection(6,-120)
3603	ship:setWeaponTubeDirection(7, 120)
3604	ship:setWeaponTubeExclusiveFor(0,"Homing")
3605	ship:setWeaponTubeExclusiveFor(1,"Homing")
3606	ship:setWeaponTubeExclusiveFor(2,"Homing")
3607	ship:setWeaponTubeExclusiveFor(3,"Homing")
3608	ship:setWeaponTubeExclusiveFor(4,"Homing")
3609	ship:setWeaponTubeExclusiveFor(5,"Homing")
3610	ship:setWeaponTubeExclusiveFor(6,"Homing")
3611	ship:setWeaponTubeExclusiveFor(7,"Homing")
3612	ship:setWeaponStorageMax("Homing",32)						--more (vs 5)
3613	ship:setWeaponStorage("Homing", 32)
3614	ship:setWeaponStorageMax("HVLI",0)							--less (vs 10)
3615	ship:setWeaponStorage("HVLI", 0)
3616	ship:setRadarTrace("radar_missile_cruiser.png")				--different radar trace
3617	local predator_db = queryScienceDatabase("Ships","Frigate","Predator")
3618	if predator_db == nil then
3619		local frigate_db = queryScienceDatabase("Ships","Frigate")
3620		frigate_db:addEntry("Predator")
3621		predator_db = queryScienceDatabase("Ships","Frigate","Predator")
3622		addShipToDatabase(
3623			queryScienceDatabase("Ships","Frigate","Piranha F8"),	--base ship database entry
3624			predator_db,	--modified ship database entry
3625			ship,			--ship just created, long description on the next line
3626			"The Predator is a significantly improved Piranha F8. Stronger shields and hull, faster impulse and turning speeds, a jump drive, beam weapons, eight missile tubes pointing in six directions and a large number of homing missiles to shoot.",
3627			{
3628				{key = "Large tube -60", value = "12 sec"},	--torpedo tube direction and load speed
3629				{key = "Tube -90", value = "12 sec"},		--torpedo tube direction and load speed
3630				{key = "Large tube -90", value = "12 sec"},	--torpedo tube direction and load speed
3631				{key = "Large tube 60", value = "12 sec"},	--torpedo tube direction and load speed
3632				{key = "Tube 90", value = "12 sec"},		--torpedo tube direction and load speed
3633				{key = "Large tube 90", value = "12 sec"},	--torpedo tube direction and load speed
3634				{key = "Tube -120", value = "12 sec"},		--torpedo tube direction and load speed
3635				{key = "Tube 120", value = "12 sec"},		--torpedo tube direction and load speed
3636			},
3637			"5 - 35 U"		--jump range
3638		)
3639		predator_db:setImage("radar_missile_cruiser.png")		--override default radar image
3640	end
3641	return ship
3642end
3643function atlantisY42(enemyFaction)
3644	local ship = CpuShip():setFaction(enemyFaction):setTemplate("Atlantis X23"):orderRoaming()
3645	ship:onTakingDamage(function(self,instigator)
3646		string.format("")	--serious proton needs a global context
3647		if instigator ~= nil then
3648			self.damage_instigator = instigator
3649		end
3650	end)
3651	ship:setTypeName("Atlantis Y42")
3652	ship:setShieldsMax(300,200,300,200)							--stronger shields (vs 200,200,200,200)
3653	ship:setShields(300,200,300,200)
3654	ship:setImpulseMaxSpeed(65)									--faster impulse (vs 30)
3655	ship:setRotationMaxSpeed(15)								--faster maneuver (vs 3.5)
3656--				   Index,  Arc,	  Dir, Range,	Cycle,	Damage
3657	ship:setBeamWeapon(2,	80,	  190,	1500,		6,		 8)	--narrower (vs 100)
3658	ship:setBeamWeapon(3,	80,	  170,	1500,		6,		 8)	--extra (vs 3 beams)
3659	ship:setWeaponStorageMax("Homing",16)						--more (vs 4)
3660	ship:setWeaponStorage("Homing", 16)
3661	local atlantis_y42_db = queryScienceDatabase("Ships","Corvette","Atlantis Y42")
3662	if atlantis_y42_db == nil then
3663		local corvette_db = queryScienceDatabase("Ships","Corvette")
3664		corvette_db:addEntry("Atlantis Y42")
3665		atlantis_y42_db = queryScienceDatabase("Ships","Corvette","Atlantis Y42")
3666		addShipToDatabase(
3667			queryScienceDatabase("Ships","Corvette","Atlantis X23"),	--base ship database entry
3668			atlantis_y42_db,	--modified ship database entry
3669			ship,			--ship just created, long description on the next line
3670			"The Atlantis Y42 improves on the Atlantis X23 with stronger shields, faster impulse and turn speeds, an extra beam in back and a larger missile stock",
3671			{
3672				{key = "Tube -90", value = "10 sec"},	--torpedo tube direction and load speed
3673				{key = " Tube -90", value = "10 sec"},	--torpedo tube direction and load speed
3674				{key = "Tube 90", value = "10 sec"},	--torpedo tube direction and load speed
3675				{key = " Tube 90", value = "10 sec"},	--torpedo tube direction and load speed
3676			},
3677			"5 - 50 U"		--jump range
3678		)
3679	end
3680	return ship
3681end
3682function starhammerV(enemyFaction)
3683	local ship = CpuShip():setFaction(enemyFaction):setTemplate("Starhammer II"):orderRoaming()
3684	ship:onTakingDamage(function(self,instigator)
3685		string.format("")	--serious proton needs a global context
3686		if instigator ~= nil then
3687			self.damage_instigator = instigator
3688		end
3689	end)
3690	ship:setTypeName("Starhammer V")
3691	ship:setImpulseMaxSpeed(65)									--faster impulse (vs 35)
3692	ship:setRotationMaxSpeed(15)								--faster maneuver (vs 6)
3693	ship:setShieldsMax(450, 350, 250, 250, 350)					--stronger shields (vs 450, 350, 150, 150, 350)
3694	ship:setShields(450, 350, 250, 250, 350)
3695--				   Index,  Arc,	  Dir, Range,	Cycle,	Damage
3696	ship:setBeamWeapon(4,	60,	  180,	1500,		8,		11)	--extra rear facing beam
3697	ship:setWeaponStorageMax("Homing",16)						--more (vs 4)
3698	ship:setWeaponStorage("Homing", 16)
3699	ship:setWeaponStorageMax("HVLI",36)							--more (vs 20)
3700	ship:setWeaponStorage("HVLI", 36)
3701	local starhammer_v_db = queryScienceDatabase("Ships","Corvette","Starhammer V")
3702	if starhammer_v_db == nil then
3703		local corvette_db = queryScienceDatabase("Ships","Corvette")
3704		corvette_db:addEntry("Starhammer V")
3705		starhammer_v_db = queryScienceDatabase("Ships","Corvette","Starhammer V")
3706		addShipToDatabase(
3707			queryScienceDatabase("Ships","Corvette","Starhammer II"),	--base ship database entry
3708			starhammer_v_db,	--modified ship database entry
3709			ship,			--ship just created, long description on the next line
3710			"The Starhammer V recognizes common modifications made in the field to the Starhammer II: stronger shields, faster impulse and turning speeds, additional rear beam and more missiles to shoot. These changes make the Starhammer V a force to be reckoned with.",
3711			{
3712				{key = "Tube 0", value = "10 sec"},	--torpedo tube direction and load speed
3713				{key = " Tube 0", value = "10 sec"},	--torpedo tube direction and load speed
3714			},
3715			"5 - 50 U"		--jump range
3716		)
3717	end
3718	return ship
3719end
3720function tyr(enemyFaction)
3721	local ship = CpuShip():setFaction(enemyFaction):setTemplate("Battlestation"):orderRoaming()
3722	ship:onTakingDamage(function(self,instigator)
3723		string.format("")	--serious proton needs a global context
3724		if instigator ~= nil then
3725			self.damage_instigator = instigator
3726		end
3727	end)
3728	ship:setTypeName("Tyr")
3729	ship:setImpulseMaxSpeed(50)									--faster impulse (vs 30)
3730	ship:setRotationMaxSpeed(10)								--faster maneuver (vs 1.5)
3731	ship:setShieldsMax(400, 300, 300, 400, 300, 300)			--stronger shields (vs 300, 300, 300, 300, 300)
3732	ship:setShields(400, 300, 300, 400, 300, 300)
3733	ship:setHullMax(100)										--stronger hull (vs 70)
3734	ship:setHull(100)
3735--				   Index,  Arc,	  Dir, Range,	Cycle,	Damage
3736	ship:setBeamWeapon(0,	90,	  -60,	2500,		6,		 8)	--stronger beams, broader coverage
3737	ship:setBeamWeapon(1,	90,	 -120,	2500,		6,		 8)
3738	ship:setBeamWeapon(2,	90,	   60,	2500,		6,		 8)
3739	ship:setBeamWeapon(3,	90,	  120,	2500,		6,		 8)
3740	ship:setBeamWeapon(4,	90,	  -60,	2500,		6,		 8)
3741	ship:setBeamWeapon(5,	90,	 -120,	2500,		6,		 8)
3742	ship:setBeamWeapon(6,	90,	   60,	2500,		6,		 8)
3743	ship:setBeamWeapon(7,	90,	  120,	2500,		6,		 8)
3744	ship:setBeamWeapon(8,	90,	  -60,	2500,		6,		 8)
3745	ship:setBeamWeapon(9,	90,	 -120,	2500,		6,		 8)
3746	ship:setBeamWeapon(10,	90,	   60,	2500,		6,		 8)
3747	ship:setBeamWeapon(11,	90,	  120,	2500,		6,		 8)
3748	local tyr_db = queryScienceDatabase("Ships","Dreadnought","Tyr")
3749	if tyr_db == nil then
3750		local corvette_db = queryScienceDatabase("Ships","Dreadnought")
3751		corvette_db:addEntry("Tyr")
3752		tyr_db = queryScienceDatabase("Ships","Dreadnought","Tyr")
3753		addShipToDatabase(
3754			queryScienceDatabase("Ships","Dreadnought","Battlestation"),	--base ship database entry
3755			tyr_db,	--modified ship database entry
3756			ship,			--ship just created, long description on the next line
3757			"The Tyr is the shipyard's answer to admiral konstatz' casual statement that the Battlestation model was too slow to be effective. The shipyards improved on the Battlestation by fitting the Tyr with more than twice the impulse speed and more than six times the turn speed. They threw in stronger shields and hull and wider beam coverage just to show that they could",
3758			nil,
3759			"5 - 50 U"		--jump range
3760		)
3761	end
3762	return ship
3763end
3764function gnat(enemyFaction)
3765	local ship = CpuShip():setFaction(enemyFaction):setTemplate("Ktlitan Drone"):orderRoaming()
3766	ship:setTypeName("Gnat")
3767	ship:setHullMax(15)					--weaker hull (vs 30)
3768	ship:setHull(15)
3769	ship:setImpulseMaxSpeed(140)		--faster impulse (vs 120)
3770	ship:setRotationMaxSpeed(25)		--faster maneuver (vs 10)
3771--				   Index,  Arc,	  Dir, Range,	Cycle,	Damage
3772	ship:setBeamWeapon(0,   40,		0,	 600,		4,		 3)	--weaker (vs 6) beam
3773	local gnat_db = queryScienceDatabase("Ships","No Class","Gnat")
3774	if gnat_db == nil then
3775		local no_class_db = queryScienceDatabase("Ships","No Class")
3776		no_class_db:addEntry("Gnat")
3777		gnat_db = queryScienceDatabase("Ships","No Class","Gnat")
3778		addShipToDatabase(
3779			queryScienceDatabase("Ships","No Class","Ktlitan Drone"),	--base ship database entry
3780			gnat_db,	--modified ship database entry
3781			ship,			--ship just created, long description on the next line
3782			"The Gnat is a nimbler version of the Ktlitan Drone. It's got half the hull, but it moves and turns faster",
3783			nil,
3784			nil		--jump range
3785		)
3786	end
3787	return ship
3788end
3789function cucaracha(enemyFaction)
3790	local ship = CpuShip():setFaction(enemyFaction):setTemplate("Tug"):orderRoaming()
3791	ship:onTakingDamage(function(self,instigator)
3792		string.format("")	--serious proton needs a global context
3793		if instigator ~= nil then
3794			self.damage_instigator = instigator
3795		end
3796	end)
3797	ship:setTypeName("Cucaracha")
3798	ship:setShieldsMax(200, 50, 50, 50, 50, 50)		--stronger shields (vs 20)
3799	ship:setShields(200, 50, 50, 50, 50, 50)
3800	ship:setHullMax(100)							--stronger hull (vs 50)
3801	ship:setHull(100)
3802	ship:setRotationMaxSpeed(20)					--faster maneuver (vs 10)
3803	ship:setAcceleration(30)						--faster acceleration (vs 15)
3804--				   Index,  Arc,	  Dir, Range,	Cycle,	Damage
3805	ship:setBeamWeapon(0,	60,	    0,	1500,		6,		10)	--extra rear facing beam
3806	local cucaracha_db = queryScienceDatabase("Ships","No Class","Cucaracha")
3807	if cucaracha_db == nil then
3808		local no_class_db = queryScienceDatabase("Ships","No Class")
3809		no_class_db:addEntry("Cucaracha")
3810		cucaracha_db = queryScienceDatabase("Ships","No Class","Cucaracha")
3811		addShipToDatabase(
3812			queryScienceDatabase("Ships","No Class","Tug"),	--base ship database entry
3813			cucaracha_db,	--modified ship database entry
3814			ship,			--ship just created, long description on the next line
3815			"The Cucaracha is a quick ship built around the Tug model with heavy shields and a heavy beam designed to be difficult to squash",
3816			nil,
3817			nil		--jump range
3818		)
3819	end
3820	return ship
3821end
3822function starhammerIII(enemyFaction)
3823	local ship = CpuShip():setFaction(enemyFaction):setTemplate("Starhammer II"):orderRoaming()
3824	ship:onTakingDamage(function(self,instigator)
3825		string.format("")	--serious proton needs a global context
3826		if instigator ~= nil then
3827			self.damage_instigator = instigator
3828		end
3829	end)
3830	ship:setTypeName("Starhammer III")
3831--				   Index,  Arc,	  Dir, Range,	Cycle,	Damage
3832	ship:setBeamWeapon(4,	60,	  180,	1500,		8,		11)	--extra rear facing beam
3833	ship:setTubeSize(0,"large")
3834	ship:setWeaponStorageMax("Homing",16)						--more (vs 4)
3835	ship:setWeaponStorage("Homing", 16)
3836	ship:setWeaponStorageMax("HVLI",36)							--more (vs 20)
3837	ship:setWeaponStorage("HVLI", 36)
3838	local starhammer_iii_db = queryScienceDatabase("Ships","Corvette","Starhammer III")
3839	if starhammer_iii_db == nil then
3840		local corvette_db = queryScienceDatabase("Ships","Corvette")
3841		corvette_db:addEntry("Starhammer III")
3842		starhammer_iii_db = queryScienceDatabase("Ships","Corvette","Starhammer III")
3843		addShipToDatabase(
3844			queryScienceDatabase("Ships","Corvette","Starhammer II"),	--base ship database entry
3845			starhammer_iii_db,	--modified ship database entry
3846			ship,			--ship just created, long description on the next line
3847			"The designers of the Starhammer III took the Starhammer II and added a rear facing beam, enlarged one of the missile tubes and added more missiles to fire",
3848			{
3849				{key = "Large tube 0", value = "10 sec"},	--torpedo tube direction and load speed
3850				{key = "Tube 0", value = "10 sec"},			--torpedo tube direction and load speed
3851			},
3852			"5 - 50 U"		--jump range
3853		)
3854	end
3855	return ship
3856end
3857function k2breaker(enemyFaction)
3858	local ship = CpuShip():setFaction(enemyFaction):setTemplate("Ktlitan Breaker"):orderRoaming()
3859	ship:onTakingDamage(function(self,instigator)
3860		string.format("")	--serious proton needs a global context
3861		if instigator ~= nil then
3862			self.damage_instigator = instigator
3863		end
3864	end)
3865	ship:setTypeName("K2 Breaker")
3866	ship:setHullMax(200)							--stronger hull (vs 120)
3867	ship:setHull(200)
3868	ship:setWeaponTubeCount(3)						--more (vs 1)
3869	ship:setTubeSize(0,"large")						--large (vs normal)
3870	ship:setWeaponTubeDirection(1,-30)
3871	ship:setWeaponTubeDirection(2, 30)
3872	ship:setWeaponTubeExclusiveFor(0,"HVLI")		--only HVLI (vs any)
3873	ship:setWeaponStorageMax("Homing",16)			--more (vs 0)
3874	ship:setWeaponStorage("Homing", 16)
3875	ship:setWeaponStorageMax("HVLI",8)				--more (vs 5)
3876	ship:setWeaponStorage("HVLI", 8)
3877	local k2_breaker_db = queryScienceDatabase("Ships","No Class","K2 Breaker")
3878	if k2_breaker_db == nil then
3879		local no_class_db = queryScienceDatabase("Ships","No Class")
3880		no_class_db:addEntry("K2 Breaker")
3881		k2_breaker_db = queryScienceDatabase("Ships","No Class","K2 Breaker")
3882		addShipToDatabase(
3883			queryScienceDatabase("Ships","No Class","Ktlitan Breaker"),	--base ship database entry
3884			k2_breaker_db,	--modified ship database entry
3885			ship,			--ship just created, long description on the next line
3886			"The K2 Breaker designers took the Ktlitan Breaker and beefed up the hull, added two bracketing tubes, enlarged the center tube and added more missiles to shoot. Should be good for a couple of enemy ships",
3887			{
3888				{key = "Large tube 0", value = "13 sec"},	--torpedo tube direction and load speed
3889				{key = "Tube -30", value = "13 sec"},		--torpedo tube direction and load speed
3890				{key = "Tube 30", value = "13 sec"},		--torpedo tube direction and load speed
3891			},
3892			nil
3893		)
3894	end
3895	return ship
3896end
3897function hurricane(enemyFaction)
3898	local ship = CpuShip():setFaction(enemyFaction):setTemplate("Piranha F8"):orderRoaming()
3899	ship:onTakingDamage(function(self,instigator)
3900		string.format("")	--serious proton needs a global context
3901		if instigator ~= nil then
3902			self.damage_instigator = instigator
3903		end
3904	end)
3905	ship:setTypeName("Hurricane")
3906	ship:setJumpDrive(true)
3907	ship:setJumpDriveRange(5000,40000)
3908	ship:setWeaponTubeCount(8)						--more (vs 3)
3909	ship:setWeaponTubeExclusiveFor(1,"HVLI")		--only HVLI (vs any)
3910	ship:setWeaponTubeDirection(1,  0)				--forward (vs -90)
3911	ship:setTubeSize(3,"large")
3912	ship:setWeaponTubeDirection(3,-90)
3913	ship:setTubeSize(4,"small")
3914	ship:setWeaponTubeExclusiveFor(4,"Homing")
3915	ship:setWeaponTubeDirection(4,-15)
3916	ship:setTubeSize(5,"small")
3917	ship:setWeaponTubeExclusiveFor(5,"Homing")
3918	ship:setWeaponTubeDirection(5, 15)
3919	ship:setWeaponTubeExclusiveFor(6,"Homing")
3920	ship:setWeaponTubeDirection(6,-30)
3921	ship:setWeaponTubeExclusiveFor(7,"Homing")
3922	ship:setWeaponTubeDirection(7, 30)
3923	ship:setWeaponStorageMax("Homing",24)			--more (vs 5)
3924	ship:setWeaponStorage("Homing", 24)
3925	local hurricane_db = queryScienceDatabase("Ships","Frigate","Hurricane")
3926	if hurricane_db == nil then
3927		local frigate_db = queryScienceDatabase("Ships","Frigate")
3928		frigate_db:addEntry("Hurricane")
3929		hurricane_db = queryScienceDatabase("Ships","Frigate","Hurricane")
3930		addShipToDatabase(
3931			queryScienceDatabase("Ships","Frigate","Piranha F8"),	--base ship database entry
3932			hurricane_db,	--modified ship database entry
3933			ship,			--ship just created, long description on the next line
3934			"The Hurricane is designed to jump in and shower the target with missiles. It is based on the Piranha F8, but with a jump drive, five more tubes in various directions and sizes and lots more missiles to shoot",
3935			{
3936				{key = "Large tube 0", value = "12 sec"},	--torpedo tube direction and load speed
3937				{key = "Tube 0", value = "12 sec"},			--torpedo tube direction and load speed
3938				{key = "Large tube 90", value = "12 sec"},	--torpedo tube direction and load speed
3939				{key = "Large tube -90", value = "12 sec"},	--torpedo tube direction and load speed
3940				{key = "Small tube -15", value = "12 sec"},	--torpedo tube direction and load speed
3941				{key = "Small tube 15", value = "12 sec"},	--torpedo tube direction and load speed
3942				{key = "Tube -30", value = "12 sec"},		--torpedo tube direction and load speed
3943				{key = "Tube 30", value = "12 sec"},		--torpedo tube direction and load speed
3944			},
3945			"5 - 40 U"		--jump range
3946		)
3947	end
3948	return ship
3949end
3950function phobosT4(enemyFaction)
3951	local ship = CpuShip():setFaction(enemyFaction):setTemplate("Phobos T3"):orderRoaming()
3952	ship:onTakingDamage(function(self,instigator)
3953		string.format("")	--serious proton needs a global context
3954		if instigator ~= nil then
3955			self.damage_instigator = instigator
3956		end
3957	end)
3958	ship:setTypeName("Phobos T4")
3959	ship:setRotationMaxSpeed(20)								--faster maneuver (vs 10)
3960	ship:setShieldsMax(80,30)									--stronger shields (vs 50,40)
3961	ship:setShields(80,30)
3962--				   Index,  Arc,	  Dir, Range,	Cycle,	Damage
3963	ship:setBeamWeapon(0,	90,	  -15,	1500,		6,		6)	--longer (vs 1200), faster (vs 8)
3964	ship:setBeamWeapon(1,	90,	   15,	1500,		6,		6)
3965	local phobos_t4_db = queryScienceDatabase("Ships","Frigate","Phobos T4")
3966	if phobos_t4_db == nil then
3967		local frigate_db = queryScienceDatabase("Ships","Frigate")
3968		frigate_db:addEntry("Phobos T4")
3969		phobos_t4_db = queryScienceDatabase("Ships","Frigate","Phobos T4")
3970		addShipToDatabase(
3971			queryScienceDatabase("Ships","Frigate","Phobos T3"),	--base ship database entry
3972			phobos_t4_db,	--modified ship database entry
3973			ship,			--ship just created, long description on the next line
3974			"The Phobos T4 makes some simple improvements on the Phobos T3: faster maneuver, stronger front shields, though weaker rear shields and longer and faster beam weapons",
3975			{
3976				{key = "Tube -1", value = "60 sec"},	--torpedo tube direction and load speed
3977				{key = "Tube 1", value = "60 sec"},		--torpedo tube direction and load speed
3978			},
3979			nil		--jump range
3980		)
3981	end
3982	return ship
3983end
3984function whirlwind(enemyFaction)
3985	local ship = CpuShip():setFaction(enemyFaction):setTemplate("Storm"):orderRoaming()
3986	ship:onTakingDamage(function(self,instigator)
3987		string.format("")	--serious proton needs a global context
3988		if instigator ~= nil then
3989			self.damage_instigator = instigator
3990		end
3991	end)
3992	ship:setTypeName("Whirlwind")
3993	ship:setWeaponTubeCount(9)					--more (vs 5)
3994	ship:setWeaponTubeDirection(0,-90)			--3 left, 3 right, 3 front (vs 5 front)
3995	ship:setWeaponTubeDirection(1,-92)
3996	ship:setWeaponTubeDirection(2,-88)
3997	ship:setWeaponTubeDirection(3, 90)
3998	ship:setWeaponTubeDirection(4, 92)
3999	ship:setWeaponTubeDirection(5, 88)
4000	ship:setWeaponTubeDirection(6,  0)
4001	ship:setWeaponTubeDirection(7,  2)
4002	ship:setWeaponTubeDirection(8, -2)
4003	ship:setWeaponStorageMax("Homing",36)						--more (vs 15)
4004	ship:setWeaponStorage("Homing", 36)
4005	ship:setWeaponStorageMax("HVLI",36)							--more (vs 15)
4006	ship:setWeaponStorage("HVLI", 36)
4007	local whirlwind_db = queryScienceDatabase("Ships","Frigate","Whirlwind")
4008	if whirlwind_db == nil then
4009		local frigate_db = queryScienceDatabase("Ships","Frigate")
4010		frigate_db:addEntry("Whirlwind")
4011		whirlwind_db = queryScienceDatabase("Ships","Frigate","Whirlwind")
4012		addShipToDatabase(
4013			queryScienceDatabase("Ships","Frigate","Storm"),	--base ship database entry
4014			whirlwind_db,	--modified ship database entry
4015			ship,			--ship just created, long description on the next line
4016			"The Whirlwind, another heavy artillery cruiser, takes the Storm and adds tubes and missiles. It's as if the Storm swallowed a Pirahna and grew gills. Expect to see missiles, lots of missiles",
4017			{
4018				{key = "Tube -90", value = "15 sec"},	--torpedo tube direction and load speed
4019				{key = "Tube -92", value = "15 sec"},	--torpedo tube direction and load speed
4020				{key = "Tube -88", value = "15 sec"},	--torpedo tube direction and load speed
4021				{key = "Tube  90", value = "15 sec"},	--torpedo tube direction and load speed
4022				{key = "Tube  92", value = "15 sec"},	--torpedo tube direction and load speed
4023				{key = "Tube  88", value = "15 sec"},	--torpedo tube direction and load speed
4024				{key = "Tube   0", value = "15 sec"},	--torpedo tube direction and load speed
4025				{key = "Tube   2", value = "15 sec"},	--torpedo tube direction and load speed
4026				{key = "Tube  -2", value = "15 sec"},	--torpedo tube direction and load speed
4027			},
4028			nil		--jump range
4029		)
4030	end
4031	return ship
4032end
4033function farco3(enemyFaction)
4034	local ship = CpuShip():setFaction(enemyFaction):setTemplate("Phobos T3"):orderRoaming()
4035	ship:onTakingDamage(function(self,instigator)
4036		string.format("")	--serious proton needs a global context
4037		if instigator ~= nil then
4038			self.damage_instigator = instigator
4039		end
4040	end)
4041	ship:setTypeName("Farco 3")
4042	ship:setShieldsMax(60, 40)									--stronger shields (vs 50, 40)
4043	ship:setShields(60, 40)
4044--				   Index,  Arc,	Dir,	Range, Cycle,	Damage
4045	ship:setBeamWeapon(0,	90,	-15,	 1500,	5.0,	6.0)	--longer (vs 1200), faster (vs 8)
4046	ship:setBeamWeapon(1,	90,	 15,	 1500,	5.0,	6.0)
4047	local farco_3_db = queryScienceDatabase("Ships","Frigate","Farco 3")
4048	if farco_3_db == nil then
4049		local frigate_db = queryScienceDatabase("Ships","Frigate")
4050		frigate_db:addEntry("Farco 3")
4051		farco_3_db = queryScienceDatabase("Ships","Frigate","Farco 3")
4052		addShipToDatabase(
4053			queryScienceDatabase("Ships","Frigate","Phobos T3"),	--base ship database entry
4054			farco_3_db,		--modified ship database entry
4055			ship,			--ship just created, long description on the next line
4056			"The Farco models are evolutionary changes to the Phobos T3. In the case of the Farco 3, the beams are longer and faster and the shields are slightly stronger.",
4057			{
4058				{key = "Tube -1", value = "60 sec"},	--torpedo tube direction and load speed
4059				{key = "Tube 1", value = "60 sec"},		--torpedo tube direction and load speed
4060			},
4061			nil		--jump range
4062		)
4063	end
4064	return ship
4065end
4066function farco5(enemyFaction)
4067	local ship = CpuShip():setFaction(enemyFaction):setTemplate("Phobos T3"):orderRoaming()
4068	ship:onTakingDamage(function(self,instigator)
4069		string.format("")	--serious proton needs a global context
4070		if instigator ~= nil then
4071			self.damage_instigator = instigator
4072		end
4073	end)
4074	ship:setTypeName("Farco 5")
4075	ship:setShieldsMax(60, 40)				--stronger shields (vs 50, 40)
4076	ship:setShields(60, 40)
4077	ship:setTubeLoadTime(0,30)				--faster (vs 60)
4078	ship:setTubeLoadTime(0,30)
4079	local farco_5_db = queryScienceDatabase("Ships","Frigate","Farco 5")
4080	if farco_5_db == nil then
4081		local frigate_db = queryScienceDatabase("Ships","Frigate")
4082		frigate_db:addEntry("Farco 5")
4083		farco_5_db = queryScienceDatabase("Ships","Frigate","Farco 5")
4084		addShipToDatabase(
4085			queryScienceDatabase("Ships","Frigate","Phobos T3"),	--base ship database entry
4086			farco_5_db,		--modified ship database entry
4087			ship,			--ship just created, long description on the next line
4088			"The Farco models are evolutionary changes to the Phobos T3. In the case of the Farco 5, the tubes load faster and the shields are slightly stronger.",
4089			{
4090				{key = "Tube -1", value = "30 sec"},	--torpedo tube direction and load speed
4091				{key = "Tube 1", value = "30 sec"},		--torpedo tube direction and load speed
4092			},
4093			nil		--jump range
4094		)
4095	end
4096	return ship
4097end
4098function farco8(enemyFaction)
4099	local ship = CpuShip():setFaction(enemyFaction):setTemplate("Phobos T3"):orderRoaming()
4100	ship:onTakingDamage(function(self,instigator)
4101		string.format("")	--serious proton needs a global context
4102		if instigator ~= nil then
4103			self.damage_instigator = instigator
4104		end
4105	end)
4106	ship:setTypeName("Farco 8")
4107	ship:setShieldsMax(80, 50)				--stronger shields (vs 50, 40)
4108	ship:setShields(80, 50)
4109--				   Index,  Arc,	Dir,	Range, Cycle,	Damage
4110	ship:setBeamWeapon(0,	90,	-15,	 1500,	5.0,	6.0)	--longer (vs 1200), faster (vs 8)
4111	ship:setBeamWeapon(1,	90,	 15,	 1500,	5.0,	6.0)
4112	ship:setTubeLoadTime(0,30)				--faster (vs 60)
4113	ship:setTubeLoadTime(0,30)
4114	local farco_8_db = queryScienceDatabase("Ships","Frigate","Farco 8")
4115	if farco_8_db == nil then
4116		local frigate_db = queryScienceDatabase("Ships","Frigate")
4117		frigate_db:addEntry("Farco 8")
4118		farco_8_db = queryScienceDatabase("Ships","Frigate","Farco 8")
4119		addShipToDatabase(
4120			queryScienceDatabase("Ships","Frigate","Phobos T3"),	--base ship database entry
4121			farco_8_db,		--modified ship database entry
4122			ship,			--ship just created, long description on the next line
4123			"The Farco models are evolutionary changes to the Phobos T3. In the case of the Farco 8, the beams are longer and faster, the tubes load faster and the shields are stronger.",
4124			{
4125				{key = "Tube -1", value = "30 sec"},	--torpedo tube direction and load speed
4126				{key = "Tube 1", value = "30 sec"},		--torpedo tube direction and load speed
4127			},
4128			nil		--jump range
4129		)
4130	end
4131	return ship
4132end
4133function farco11(enemyFaction)
4134	local ship = CpuShip():setFaction(enemyFaction):setTemplate("Phobos T3"):orderRoaming()
4135	ship:onTakingDamage(function(self,instigator)
4136		string.format("")	--serious proton needs a global context
4137		if instigator ~= nil then
4138			self.damage_instigator = instigator
4139		end
4140	end)
4141	ship:setTypeName("Farco 11")
4142	ship:setShieldsMax(80, 50)				--stronger shields (vs 50, 40)
4143	ship:setShields(80, 50)
4144	ship:setRotationMaxSpeed(15)								--faster maneuver (vs 10)
4145--				   Index,  Arc,	Dir,	Range, Cycle,	Damage
4146	ship:setBeamWeapon(0,	90,	-15,	 1500,	5.0,	6.0)	--longer (vs 1200), faster (vs 8)
4147	ship:setBeamWeapon(1,	90,	 15,	 1500,	5.0,	6.0)
4148	ship:setBeamWeapon(2,	20,	  0,	 1800,	5.0,	4.0)	--additional sniping beam
4149	local farco_11_db = queryScienceDatabase("Ships","Frigate","Farco 11")
4150	if farco_11_db == nil then
4151		local frigate_db = queryScienceDatabase("Ships","Frigate")
4152		frigate_db:addEntry("Farco 11")
4153		farco_11_db = queryScienceDatabase("Ships","Frigate","Farco 11")
4154		addShipToDatabase(
4155			queryScienceDatabase("Ships","Frigate","Phobos T3"),	--base ship database entry
4156			farco_11_db,	--modified ship database entry
4157			ship,			--ship just created, long description on the next line
4158			"The Farco models are evolutionary changes to the Phobos T3. In the case of the Farco 11, the maneuver speed is faster, the beams are longer and faster, there's an added longer sniping beam and the shields are stronger.",
4159			{
4160				{key = "Tube -1", value = "60 sec"},	--torpedo tube direction and load speed
4161				{key = "Tube 1", value = "60 sec"},		--torpedo tube direction and load speed
4162			},
4163			nil		--jump range
4164		)
4165	end
4166	return ship
4167end
4168function farco13(enemyFaction)
4169	local ship = CpuShip():setFaction(enemyFaction):setTemplate("Phobos T3"):orderRoaming()
4170	ship:onTakingDamage(function(self,instigator)
4171		string.format("")	--serious proton needs a global context
4172		if instigator ~= nil then
4173			self.damage_instigator = instigator
4174		end
4175	end)
4176	ship:setTypeName("Farco 13")
4177	ship:setShieldsMax(90, 70)				--stronger shields (vs 50, 40)
4178	ship:setShields(90, 70)
4179	ship:setRotationMaxSpeed(15)								--faster maneuver (vs 10)
4180--				   Index,  Arc,	Dir,	Range, Cycle,	Damage
4181	ship:setBeamWeapon(0,	90,	-15,	 1500,	5.0,	6.0)	--longer (vs 1200), faster (vs 8)
4182	ship:setBeamWeapon(1,	90,	 15,	 1500,	5.0,	6.0)
4183	ship:setBeamWeapon(2,	20,	  0,	 1800,	5.0,	4.0)	--additional sniping beam
4184	ship:setTubeLoadTime(0,30)				--faster (vs 60)
4185	ship:setTubeLoadTime(0,30)
4186	ship:setWeaponStorageMax("Homing",16)						--more (vs 6)
4187	ship:setWeaponStorage("Homing", 16)
4188	ship:setWeaponStorageMax("HVLI",30)							--more (vs 20)
4189	ship:setWeaponStorage("HVLI", 30)
4190	local farco_13_db = queryScienceDatabase("Ships","Frigate","Farco 13")
4191	if farco_13_db == nil then
4192		local frigate_db = queryScienceDatabase("Ships","Frigate")
4193		frigate_db:addEntry("Farco 13")
4194		farco_13_db = queryScienceDatabase("Ships","Frigate","Farco 13")
4195		addShipToDatabase(
4196			queryScienceDatabase("Ships","Frigate","Phobos T3"),	--base ship database entry
4197			farco_13_db,	--modified ship database entry
4198			ship,			--ship just created, long description on the next line
4199			"The Farco models are evolutionary changes to the Phobos T3. In the case of the Farco 13, the maneuver speed is faster, the beams are longer and faster, there's an added longer sniping beam, the tubes load faster, there are more missiles and the shields are stronger.",
4200			{
4201				{key = "Tube -1", value = "30 sec"},	--torpedo tube direction and load speed
4202				{key = "Tube 1", value = "30 sec"},		--torpedo tube direction and load speed
4203			},
4204			nil		--jump range
4205		)
4206	end
4207	return ship
4208end
4209function addShipToDatabase(base_db,modified_db,ship,description,tube_directions,jump_range)
4210	modified_db:setLongDescription(description)
4211	modified_db:setImage(base_db:getImage())
4212	modified_db:setKeyValue("Class",base_db:getKeyValue("Class"))
4213	modified_db:setKeyValue("Sub-class",base_db:getKeyValue("Sub-class"))
4214	modified_db:setKeyValue("Size",base_db:getKeyValue("Size"))
4215	local shields = ship:getShieldCount()
4216	if shields > 0 then
4217		local shield_string = ""
4218		for i=1,shields do
4219			if shield_string == "" then
4220				shield_string = string.format("%i",math.floor(ship:getShieldMax(i-1)))
4221			else
4222				shield_string = string.format("%s/%i",shield_string,math.floor(ship:getShieldMax(i-1)))
4223			end
4224		end
4225		modified_db:setKeyValue("Shield",shield_string)
4226	end
4227	modified_db:setKeyValue("Hull",string.format("%i",math.floor(ship:getHullMax())))
4228	modified_db:setKeyValue("Move speed",string.format("%.1f u/min",ship:getImpulseMaxSpeed()*60/1000))
4229	modified_db:setKeyValue("Turn speed",string.format("%.1f deg/sec",ship:getRotationMaxSpeed()))
4230	if ship:hasJumpDrive() then
4231		if jump_range == nil then
4232			local base_jump_range = base_db:getKeyValue("Jump range")
4233			if base_jump_range ~= nil and base_jump_range ~= "" then
4234				modified_db:setKeyValue("Jump range",base_jump_range)
4235			else
4236				modified_db:setKeyValue("Jump range","5 - 50 u")
4237			end
4238		else
4239			modified_db:setKeyValue("Jump range",jump_range)
4240		end
4241	end
4242	if ship:hasWarpDrive() then
4243		modified_db:setKeyValue("Warp Speed",string.format("%.1f u/min",ship:getWarpSpeed()*60/1000))
4244	end
4245	local key = ""
4246	if ship:getBeamWeaponRange(0) > 0 then
4247		local bi = 0
4248		repeat
4249			local beam_direction = ship:getBeamWeaponDirection(bi)
4250			if beam_direction > 315 and beam_direction < 360 then
4251				beam_direction = beam_direction - 360
4252			end
4253			key = string.format("Beam weapon %i:%i",ship:getBeamWeaponDirection(bi),ship:getBeamWeaponArc(bi))
4254			while(modified_db:getKeyValue(key) ~= "") do
4255				key = " " .. key
4256			end
4257			modified_db:setKeyValue(key,string.format("%.1f Dmg / %.1f sec",ship:getBeamWeaponDamage(bi),ship:getBeamWeaponCycleTime(bi)))
4258			bi = bi + 1
4259		until(ship:getBeamWeaponRange(bi) < 1)
4260	end
4261	local tubes = ship:getWeaponTubeCount()
4262	if tubes > 0 then
4263		if tube_directions ~= nil then
4264			for i=1,#tube_directions do
4265				modified_db:setKeyValue(tube_directions[i].key,tube_directions[i].value)
4266			end
4267		end
4268		local missile_types = {'Homing', 'Nuke', 'Mine', 'EMP', 'HVLI'}
4269		for _, missile_type in ipairs(missile_types) do
4270			local max_storage = ship:getWeaponStorageMax(missile_type)
4271			if max_storage > 0 then
4272				modified_db:setKeyValue(string.format("Storage %s",missile_type),string.format("%i",max_storage))
4273			end
4274		end
4275	end
4276end
4277--		Generate call sign functions
4278function generateCallSign(prefix,faction)
4279	if faction == nil then
4280		if prefix == nil then
4281			prefix = generateCallSignPrefix()
4282		end
4283	else
4284		if prefix == nil then
4285			prefix = getFactionPrefix(faction)
4286		else
4287			prefix = string.format("%s %s",getFactionPrefix(faction),prefix)
4288		end
4289	end
4290	suffix_index = suffix_index + math.random(1,3)
4291	if suffix_index > 99 then
4292		suffix_index = 1
4293	end
4294	return string.format("%s%i",prefix,suffix_index)
4295end
4296function generateCallSignPrefix(length)
4297	if call_sign_prefix_pool == nil then
4298		call_sign_prefix_pool = {}
4299		prefix_length = prefix_length + 1
4300		if prefix_length > 2 then
4301			prefix_length = 1
4302		end
4303		fillPrefixPool()
4304	end
4305	if length == nil then
4306		length = prefix_length
4307	end
4308	local prefix = ""
4309	for i=1,length do
4310		if #call_sign_prefix_pool < 1 then
4311			fillPrefixPool()
4312		end
4313		prefix = prefix .. tableRemoveRandom(call_sign_prefix_pool)
4314	end
4315	return prefix
4316end
4317function fillPrefixPool()
4318	for i=1,26 do
4319		table.insert(call_sign_prefix_pool,string.char(i+64))
4320	end
4321end
4322function getFactionPrefix(faction)
4323	--get the faction names from another scenario if desired
4324	local faction_prefix = nil
4325	if faction == "Kraylor" then
4326		if kraylor_names == nil then
4327			setKraylorNames()
4328		else
4329			if #kraylor_names < 1 then
4330				setKraylorNames()
4331			end
4332		end
4333		local kraylor_name_choice = math.random(1,#kraylor_names)
4334		faction_prefix = kraylor_names[kraylor_name_choice]
4335		table.remove(kraylor_names,kraylor_name_choice)
4336	end
4337	if faction == "Exuari" then
4338		if exuari_names == nil then
4339			setExuariNames()
4340		else
4341			if #exuari_names < 1 then
4342				setExuariNames()
4343			end
4344		end
4345		local exuari_name_choice = math.random(1,#exuari_names)
4346		faction_prefix = exuari_names[exuari_name_choice]
4347		table.remove(exuari_names,exuari_name_choice)
4348	end
4349	if faction == "Ghosts" then
4350		if ghosts_names == nil then
4351			setGhostsNames()
4352		else
4353			if #ghosts_names < 1 then
4354				setGhostsNames()
4355			end
4356		end
4357		local ghosts_name_choice = math.random(1,#ghosts_names)
4358		faction_prefix = ghosts_names[ghosts_name_choice]
4359		table.remove(ghosts_names,ghosts_name_choice)
4360	end
4361	if faction == "Independent" then
4362		if independent_names == nil then
4363			setIndependentNames()
4364		else
4365			if #independent_names < 1 then
4366				setIndependentNames()
4367			end
4368		end
4369		local independent_name_choice = math.random(1,#independent_names)
4370		faction_prefix = independent_names[independent_name_choice]
4371		table.remove(independent_names,independent_name_choice)
4372	end
4373	if faction == "Human Navy" then
4374		if human_names == nil then
4375			setHumanNames()
4376		else
4377			if #human_names < 1 then
4378				setHumanNames()
4379			end
4380		end
4381		local human_name_choice = math.random(1,#human_names)
4382		faction_prefix = human_names[human_name_choice]
4383		table.remove(human_names,human_name_choice)
4384	end
4385	if faction_prefix == nil then
4386		faction_prefix = generateCallSignPrefix()
4387	end
4388	return faction_prefix
4389end
4390function setGhostsNames()
4391	ghosts_names = {}
4392	table.insert(ghosts_names,"Abstract")
4393	table.insert(ghosts_names,"Ada")
4394	table.insert(ghosts_names,"Assemble")
4395	table.insert(ghosts_names,"Assert")
4396	table.insert(ghosts_names,"Backup")
4397	table.insert(ghosts_names,"BASIC")
4398	table.insert(ghosts_names,"Big Iron")
4399	table.insert(ghosts_names,"BigEndian")
4400	table.insert(ghosts_names,"Binary")
4401	table.insert(ghosts_names,"Bit")
4402	table.insert(ghosts_names,"Block")
4403	table.insert(ghosts_names,"Boot")
4404	table.insert(ghosts_names,"Branch")
4405	table.insert(ghosts_names,"BTree")
4406	table.insert(ghosts_names,"Bubble")
4407	table.insert(ghosts_names,"Byte")
4408	table.insert(ghosts_names,"Capacitor")
4409	table.insert(ghosts_names,"Case")
4410	table.insert(ghosts_names,"Chad")
4411	table.insert(ghosts_names,"Charge")
4412	table.insert(ghosts_names,"COBOL")
4413	table.insert(ghosts_names,"Collate")
4414	table.insert(ghosts_names,"Compile")
4415	table.insert(ghosts_names,"Control")
4416	table.insert(ghosts_names,"Construct")
4417	table.insert(ghosts_names,"Cycle")
4418	table.insert(ghosts_names,"Data")
4419	table.insert(ghosts_names,"Debug")
4420	table.insert(ghosts_names,"Decimal")
4421	table.insert(ghosts_names,"Decision")
4422	table.insert(ghosts_names,"Default")
4423	table.insert(ghosts_names,"DIMM")
4424	table.insert(ghosts_names,"Displacement")
4425	table.insert(ghosts_names,"Edge")
4426	table.insert(ghosts_names,"Exit")
4427	table.insert(ghosts_names,"Factor")
4428	table.insert(ghosts_names,"Flag")
4429	table.insert(ghosts_names,"Float")
4430	table.insert(ghosts_names,"Flow")
4431	table.insert(ghosts_names,"FORTRAN")
4432	table.insert(ghosts_names,"Fullword")
4433	table.insert(ghosts_names,"GIGO")
4434	table.insert(ghosts_names,"Graph")
4435	table.insert(ghosts_names,"Hack")
4436	table.insert(ghosts_names,"Hash")
4437	table.insert(ghosts_names,"Halfword")
4438	table.insert(ghosts_names,"Hertz")
4439	table.insert(ghosts_names,"Hexadecimal")
4440	table.insert(ghosts_names,"Indicator")
4441	table.insert(ghosts_names,"Initialize")
4442	table.insert(ghosts_names,"Integer")
4443	table.insert(ghosts_names,"Integrate")
4444	table.insert(ghosts_names,"Interrupt")
4445	table.insert(ghosts_names,"Java")
4446	table.insert(ghosts_names,"Lisp")
4447	table.insert(ghosts_names,"List")
4448	table.insert(ghosts_names,"Logic")
4449	table.insert(ghosts_names,"Loop")
4450	table.insert(ghosts_names,"Lua")
4451	table.insert(ghosts_names,"Magnetic")
4452	table.insert(ghosts_names,"Mask")
4453	table.insert(ghosts_names,"Memory")
4454	table.insert(ghosts_names,"Mnemonic")
4455	table.insert(ghosts_names,"Micro")
4456	table.insert(ghosts_names,"Model")
4457	table.insert(ghosts_names,"Nibble")
4458	table.insert(ghosts_names,"Octal")
4459	table.insert(ghosts_names,"Order")
4460	table.insert(ghosts_names,"Operator")
4461	table.insert(ghosts_names,"Parameter")
4462	table.insert(ghosts_names,"Pascal")
4463	table.insert(ghosts_names,"Pattern")
4464	table.insert(ghosts_names,"Pixel")
4465	table.insert(ghosts_names,"Point")
4466	table.insert(ghosts_names,"Polygon")
4467	table.insert(ghosts_names,"Port")
4468	table.insert(ghosts_names,"Process")
4469	table.insert(ghosts_names,"RAM")
4470	table.insert(ghosts_names,"Raster")
4471	table.insert(ghosts_names,"Rate")
4472	table.insert(ghosts_names,"Redundant")
4473	table.insert(ghosts_names,"Reference")
4474	table.insert(ghosts_names,"Refresh")
4475	table.insert(ghosts_names,"Register")
4476	table.insert(ghosts_names,"Resistor")
4477	table.insert(ghosts_names,"ROM")
4478	table.insert(ghosts_names,"Routine")
4479	table.insert(ghosts_names,"Ruby")
4480	table.insert(ghosts_names,"SAAS")
4481	table.insert(ghosts_names,"Sequence")
4482	table.insert(ghosts_names,"Share")
4483	table.insert(ghosts_names,"Silicon")
4484	table.insert(ghosts_names,"SIMM")
4485	table.insert(ghosts_names,"Socket")
4486	table.insert(ghosts_names,"Sort")
4487	table.insert(ghosts_names,"Structure")
4488	table.insert(ghosts_names,"Switch")
4489	table.insert(ghosts_names,"Symbol")
4490	table.insert(ghosts_names,"Trace")
4491	table.insert(ghosts_names,"Transistor")
4492	table.insert(ghosts_names,"Value")
4493	table.insert(ghosts_names,"Vector")
4494	table.insert(ghosts_names,"Version")
4495	table.insert(ghosts_names,"View")
4496	table.insert(ghosts_names,"WYSIWYG")
4497	table.insert(ghosts_names,"XOR")
4498end
4499function setExuariNames()
4500	exuari_names = {}
4501	table.insert(exuari_names,"Astonester")
4502	table.insert(exuari_names,"Ametripox")
4503	table.insert(exuari_names,"Bakeltevex")
4504	table.insert(exuari_names,"Baropledax")
4505	table.insert(exuari_names,"Batongomox")
4506	table.insert(exuari_names,"Bekilvimix")
4507	table.insert(exuari_names,"Benoglopok")
4508	table.insert(exuari_names,"Bilontipur")
4509	table.insert(exuari_names,"Bolictimik")
4510	table.insert(exuari_names,"Bomagralax")
4511	table.insert(exuari_names,"Buteldefex")
4512	table.insert(exuari_names,"Catondinab")
4513	table.insert(exuari_names,"Chatorlonox")
4514	table.insert(exuari_names,"Culagromik")
4515	table.insert(exuari_names,"Dakimbinix")
4516	table.insert(exuari_names,"Degintalix")
4517	table.insert(exuari_names,"Dimabratax")
4518	table.insert(exuari_names,"Dokintifix")
4519	table.insert(exuari_names,"Dotandirex")
4520	table.insert(exuari_names,"Dupalgawax")
4521	table.insert(exuari_names,"Ekoftupex")
4522	table.insert(exuari_names,"Elidranov")
4523	table.insert(exuari_names,"Fakobrovox")
4524	table.insert(exuari_names,"Femoplabix")
4525	table.insert(exuari_names,"Fibatralax")
4526	table.insert(exuari_names,"Fomartoran")
4527	table.insert(exuari_names,"Gateldepex")
4528	table.insert(exuari_names,"Gamutrewal")
4529	table.insert(exuari_names,"Gesanterux")
4530	table.insert(exuari_names,"Gimardanax")
4531	table.insert(exuari_names,"Hamintinal")
4532	table.insert(exuari_names,"Holangavak")
4533	table.insert(exuari_names,"Igolpafik")
4534	table.insert(exuari_names,"Inoklomat")
4535	table.insert(exuari_names,"Jamewtibex")
4536	table.insert(exuari_names,"Jepospagox")
4537	table.insert(exuari_names,"Kajortonox")
4538	table.insert(exuari_names,"Kapogrinix")
4539	table.insert(exuari_names,"Kelitravax")
4540	table.insert(exuari_names,"Kipaldanax")
4541	table.insert(exuari_names,"Kodendevex")
4542	table.insert(exuari_names,"Kotelpedex")
4543	table.insert(exuari_names,"Kutandolak")
4544	table.insert(exuari_names,"Lakirtinix")
4545	table.insert(exuari_names,"Lapoldinek")
4546	table.insert(exuari_names,"Lavorbonox")
4547	table.insert(exuari_names,"Letirvinix")
4548	table.insert(exuari_names,"Lowibromax")
4549	table.insert(exuari_names,"Makintibix")
4550	table.insert(exuari_names,"Makorpohox")
4551	table.insert(exuari_names,"Matoprowox")
4552	table.insert(exuari_names,"Mefinketix")
4553	table.insert(exuari_names,"Motandobak")
4554	table.insert(exuari_names,"Nakustunux")
4555	table.insert(exuari_names,"Nequivonax")
4556	table.insert(exuari_names,"Nitaldavax")
4557	table.insert(exuari_names,"Nobaldorex")
4558	table.insert(exuari_names,"Obimpitix")
4559	table.insert(exuari_names,"Owaklanat")
4560	table.insert(exuari_names,"Pakendesik")
4561	table.insert(exuari_names,"Pazinderix")
4562	table.insert(exuari_names,"Pefoglamuk")
4563	table.insert(exuari_names,"Pekirdivix")
4564	table.insert(exuari_names,"Potarkadax")
4565	table.insert(exuari_names,"Pulendemex")
4566	table.insert(exuari_names,"Quatordunix")
4567	table.insert(exuari_names,"Rakurdumux")
4568	table.insert(exuari_names,"Ralombenik")
4569	table.insert(exuari_names,"Regosporak")
4570	table.insert(exuari_names,"Retordofox")
4571	table.insert(exuari_names,"Rikondogox")
4572	table.insert(exuari_names,"Rokengelex")
4573	table.insert(exuari_names,"Rutarkadax")
4574	table.insert(exuari_names,"Sakeldepex")
4575	table.insert(exuari_names,"Setiftimix")
4576	table.insert(exuari_names,"Siparkonal")
4577	table.insert(exuari_names,"Sopaldanax")
4578	table.insert(exuari_names,"Sudastulux")
4579	table.insert(exuari_names,"Takeftebex")
4580	table.insert(exuari_names,"Taliskawit")
4581	table.insert(exuari_names,"Tegundolex")
4582	table.insert(exuari_names,"Tekintipix")
4583	table.insert(exuari_names,"Tiposhomox")
4584	table.insert(exuari_names,"Tokaldapax")
4585	table.insert(exuari_names,"Tomuglupux")
4586	table.insert(exuari_names,"Tufeldepex")
4587	table.insert(exuari_names,"Unegremek")
4588	table.insert(exuari_names,"Uvendipax")
4589	table.insert(exuari_names,"Vatorgopox")
4590	table.insert(exuari_names,"Venitribix")
4591	table.insert(exuari_names,"Vobalterix")
4592	table.insert(exuari_names,"Wakintivix")
4593	table.insert(exuari_names,"Wapaltunix")
4594	table.insert(exuari_names,"Wekitrolax")
4595	table.insert(exuari_names,"Wofarbanax")
4596	table.insert(exuari_names,"Xeniplofek")
4597	table.insert(exuari_names,"Yamaglevik")
4598	table.insert(exuari_names,"Yakildivix")
4599	table.insert(exuari_names,"Yegomparik")
4600	table.insert(exuari_names,"Zapondehex")
4601	table.insert(exuari_names,"Zikandelat")
4602end
4603function setKraylorNames()
4604	kraylor_names = {}
4605	table.insert(kraylor_names,"Abroten")
4606	table.insert(kraylor_names,"Ankwar")
4607	table.insert(kraylor_names,"Bakrik")
4608	table.insert(kraylor_names,"Belgor")
4609	table.insert(kraylor_names,"Benkop")
4610	table.insert(kraylor_names,"Blargvet")
4611	table.insert(kraylor_names,"Bloktarg")
4612	table.insert(kraylor_names,"Bortok")
4613	table.insert(kraylor_names,"Bredjat")
4614	table.insert(kraylor_names,"Chankret")
4615	table.insert(kraylor_names,"Chatork")
4616	table.insert(kraylor_names,"Chokarp")
4617	table.insert(kraylor_names,"Cloprak")
4618	table.insert(kraylor_names,"Coplek")
4619	table.insert(kraylor_names,"Cortek")
4620	table.insert(kraylor_names,"Daltok")
4621	table.insert(kraylor_names,"Darpik")
4622	table.insert(kraylor_names,"Dastek")
4623	table.insert(kraylor_names,"Dotark")
4624	table.insert(kraylor_names,"Drambok")
4625	table.insert(kraylor_names,"Duntarg")
4626	table.insert(kraylor_names,"Earklat")
4627	table.insert(kraylor_names,"Ekmit")
4628	table.insert(kraylor_names,"Fakret")
4629	table.insert(kraylor_names,"Fapork")
4630	table.insert(kraylor_names,"Fawtrik")
4631	table.insert(kraylor_names,"Fenturp")
4632	table.insert(kraylor_names,"Feplik")
4633	table.insert(kraylor_names,"Figront")
4634	table.insert(kraylor_names,"Floktrag")
4635	table.insert(kraylor_names,"Fonkack")
4636	table.insert(kraylor_names,"Fontreg")
4637	table.insert(kraylor_names,"Foondrap")
4638	table.insert(kraylor_names,"Frotwak")
4639	table.insert(kraylor_names,"Gastonk")
4640	table.insert(kraylor_names,"Gentouk")
4641	table.insert(kraylor_names,"Gonpruk")
4642	table.insert(kraylor_names,"Gortak")
4643	table.insert(kraylor_names,"Gronkud")
4644	table.insert(kraylor_names,"Hewtang")
4645	table.insert(kraylor_names,"Hongtag")
4646	table.insert(kraylor_names,"Hortook")
4647	table.insert(kraylor_names,"Indrut")
4648	table.insert(kraylor_names,"Iprant")
4649	table.insert(kraylor_names,"Jakblet")
4650	table.insert(kraylor_names,"Jonket")
4651	table.insert(kraylor_names,"Jontot")
4652	table.insert(kraylor_names,"Kandarp")
4653	table.insert(kraylor_names,"Kantrok")
4654	table.insert(kraylor_names,"Kiptak")
4655	table.insert(kraylor_names,"Kortrant")
4656	table.insert(kraylor_names,"Krontgat")
4657	table.insert(kraylor_names,"Lobreck")
4658	table.insert(kraylor_names,"Lokrant")
4659	table.insert(kraylor_names,"Lomprok")
4660	table.insert(kraylor_names,"Lutrank")
4661	table.insert(kraylor_names,"Makrast")
4662	table.insert(kraylor_names,"Moklahft")
4663	table.insert(kraylor_names,"Morpug")
4664	table.insert(kraylor_names,"Nagblat")
4665	table.insert(kraylor_names,"Nokrat")
4666	table.insert(kraylor_names,"Nomek")
4667	table.insert(kraylor_names,"Notark")
4668	table.insert(kraylor_names,"Ontrok")
4669	table.insert(kraylor_names,"Orkpent")
4670	table.insert(kraylor_names,"Peechak")
4671	table.insert(kraylor_names,"Plogrent")
4672	table.insert(kraylor_names,"Pokrint")
4673	table.insert(kraylor_names,"Potarg")
4674	table.insert(kraylor_names,"Prangtil")
4675	table.insert(kraylor_names,"Quagbrok")
4676	table.insert(kraylor_names,"Quimprill")
4677	table.insert(kraylor_names,"Reekront")
4678	table.insert(kraylor_names,"Ripkort")
4679	table.insert(kraylor_names,"Rokust")
4680	table.insert(kraylor_names,"Rontrait")
4681	table.insert(kraylor_names,"Saknep")
4682	table.insert(kraylor_names,"Sengot")
4683	table.insert(kraylor_names,"Skitkard")
4684	table.insert(kraylor_names,"Skopgrek")
4685	table.insert(kraylor_names,"Sletrok")
4686	table.insert(kraylor_names,"Slorknat")
4687	table.insert(kraylor_names,"Spogrunk")
4688	table.insert(kraylor_names,"Staklurt")
4689	table.insert(kraylor_names,"Stonkbrant")
4690	table.insert(kraylor_names,"Swaktrep")
4691	table.insert(kraylor_names,"Tandrok")
4692	table.insert(kraylor_names,"Takrost")
4693	table.insert(kraylor_names,"Tonkrut")
4694	table.insert(kraylor_names,"Torkrot")
4695	table.insert(kraylor_names,"Trablok")
4696	table.insert(kraylor_names,"Trokdin")
4697	table.insert(kraylor_names,"Unkelt")
4698	table.insert(kraylor_names,"Urjop")
4699	table.insert(kraylor_names,"Vankront")
4700	table.insert(kraylor_names,"Vintrep")
4701	table.insert(kraylor_names,"Volkerd")
4702	table.insert(kraylor_names,"Vortread")
4703	table.insert(kraylor_names,"Wickurt")
4704	table.insert(kraylor_names,"Xokbrek")
4705	table.insert(kraylor_names,"Yeskret")
4706	table.insert(kraylor_names,"Zacktrope")
4707end
4708function setIndependentNames()
4709	independent_names = {}
4710	table.insert(independent_names,"Akdroft")	--faux Kraylor
4711	table.insert(independent_names,"Bletnik")	--faux Kraylor
4712	table.insert(independent_names,"Brogfent")	--faux Kraylor
4713	table.insert(independent_names,"Cruflech")	--faux Kraylor
4714	table.insert(independent_names,"Dengtoct")	--faux Kraylor
4715	table.insert(independent_names,"Fiklerg")	--faux Kraylor
4716	table.insert(independent_names,"Groftep")	--faux Kraylor
4717	table.insert(independent_names,"Hinkflort")	--faux Kraylor
4718	table.insert(independent_names,"Irklesht")	--faux Kraylor
4719	table.insert(independent_names,"Jotrak")	--faux Kraylor
4720	table.insert(independent_names,"Kargleth")	--faux Kraylor
4721	table.insert(independent_names,"Lidroft")	--faux Kraylor
4722	table.insert(independent_names,"Movrect")	--faux Kraylor
4723	table.insert(independent_names,"Nitrang")	--faux Kraylor
4724	table.insert(independent_names,"Poklapt")	--faux Kraylor
4725	table.insert(independent_names,"Raknalg")	--faux Kraylor
4726	table.insert(independent_names,"Stovtuk")	--faux Kraylor
4727	table.insert(independent_names,"Trongluft")	--faux Kraylor
4728	table.insert(independent_names,"Vactremp")	--faux Kraylor
4729	table.insert(independent_names,"Wunklesp")	--faux Kraylor
4730	table.insert(independent_names,"Yentrilg")	--faux Kraylor
4731	table.insert(independent_names,"Zeltrag")	--faux Kraylor
4732	table.insert(independent_names,"Avoltojop")		--faux Exuari
4733	table.insert(independent_names,"Bimartarax")	--faux Exuari
4734	table.insert(independent_names,"Cidalkapax")	--faux Exuari
4735	table.insert(independent_names,"Darongovax")	--faux Exuari
4736	table.insert(independent_names,"Felistiyik")	--faux Exuari
4737	table.insert(independent_names,"Gopendewex")	--faux Exuari
4738	table.insert(independent_names,"Hakortodox")	--faux Exuari
4739	table.insert(independent_names,"Jemistibix")	--faux Exuari
4740	table.insert(independent_names,"Kilampafax")	--faux Exuari
4741	table.insert(independent_names,"Lokuftumux")	--faux Exuari
4742	table.insert(independent_names,"Mabildirix")	--faux Exuari
4743	table.insert(independent_names,"Notervelex")	--faux Exuari
4744	table.insert(independent_names,"Pekolgonex")	--faux Exuari
4745	table.insert(independent_names,"Rifaltabax")	--faux Exuari
4746	table.insert(independent_names,"Sobendeyex")	--faux Exuari
4747	table.insert(independent_names,"Tinaftadax")	--faux Exuari
4748	table.insert(independent_names,"Vadorgomax")	--faux Exuari
4749	table.insert(independent_names,"Wilerpejex")	--faux Exuari
4750	table.insert(independent_names,"Yukawvalak")	--faux Exuari
4751	table.insert(independent_names,"Zajiltibix")	--faux Exuari
4752	table.insert(independent_names,"Alter")		--faux Ghosts
4753	table.insert(independent_names,"Assign")	--faux Ghosts
4754	table.insert(independent_names,"Brain")		--faux Ghosts
4755	table.insert(independent_names,"Break")		--faux Ghosts
4756	table.insert(independent_names,"Boundary")	--faux Ghosts
4757	table.insert(independent_names,"Code")		--faux Ghosts
4758	table.insert(independent_names,"Compare")	--faux Ghosts
4759	table.insert(independent_names,"Continue")	--faux Ghosts
4760	table.insert(independent_names,"Core")		--faux Ghosts
4761	table.insert(independent_names,"CRUD")		--faux Ghosts
4762	table.insert(independent_names,"Decode")	--faux Ghosts
4763	table.insert(independent_names,"Decrypt")	--faux Ghosts
4764	table.insert(independent_names,"Device")	--faux Ghosts
4765	table.insert(independent_names,"Encode")	--faux Ghosts
4766	table.insert(independent_names,"Encrypt")	--faux Ghosts
4767	table.insert(independent_names,"Event")		--faux Ghosts
4768	table.insert(independent_names,"Fetch")		--faux Ghosts
4769	table.insert(independent_names,"Frame")		--faux Ghosts
4770	table.insert(independent_names,"Go")		--faux Ghosts
4771	table.insert(independent_names,"IO")		--faux Ghosts
4772	table.insert(independent_names,"Interface")	--faux Ghosts
4773	table.insert(independent_names,"Kilo")		--faux Ghosts
4774	table.insert(independent_names,"Modify")	--faux Ghosts
4775	table.insert(independent_names,"Pin")		--faux Ghosts
4776	table.insert(independent_names,"Program")	--faux Ghosts
4777	table.insert(independent_names,"Purge")		--faux Ghosts
4778	table.insert(independent_names,"Retrieve")	--faux Ghosts
4779	table.insert(independent_names,"Store")		--faux Ghosts
4780	table.insert(independent_names,"Unit")		--faux Ghosts
4781	table.insert(independent_names,"Wire")		--faux Ghosts
4782end
4783function setHumanNames()
4784	human_names = {}
4785	table.insert(human_names,"Andromeda")
4786	table.insert(human_names,"Angelica")
4787	table.insert(human_names,"Artemis")
4788	table.insert(human_names,"Barrier")
4789	table.insert(human_names,"Beauteous")
4790	table.insert(human_names,"Bliss")
4791	table.insert(human_names,"Bonita")
4792	table.insert(human_names,"Bounty Hunter")
4793	table.insert(human_names,"Bueno")
4794	table.insert(human_names,"Capitol")
4795	table.insert(human_names,"Castigator")
4796	table.insert(human_names,"Centurion")
4797	table.insert(human_names,"Chakalaka")
4798	table.insert(human_names,"Charity")
4799	table.insert(human_names,"Christmas")
4800	table.insert(human_names,"Chutzpah")
4801	table.insert(human_names,"Constantine")
4802	table.insert(human_names,"Crystal")
4803	table.insert(human_names,"Dauntless")
4804	table.insert(human_names,"Defiant")
4805	table.insert(human_names,"Discovery")
4806	table.insert(human_names,"Dorcas")
4807	table.insert(human_names,"Elite")
4808	table.insert(human_names,"Empathy")
4809	table.insert(human_names,"Enlighten")
4810	table.insert(human_names,"Enterprise")
4811	table.insert(human_names,"Escape")
4812	table.insert(human_names,"Exclamatory")
4813	table.insert(human_names,"Faith")
4814	table.insert(human_names,"Felicity")
4815	table.insert(human_names,"Firefly")
4816	table.insert(human_names,"Foresight")
4817	table.insert(human_names,"Forthright")
4818	table.insert(human_names,"Fortitude")
4819	table.insert(human_names,"Frankenstein")
4820	table.insert(human_names,"Gallant")
4821	table.insert(human_names,"Gladiator")
4822	table.insert(human_names,"Glider")
4823	table.insert(human_names,"Godzilla")
4824	table.insert(human_names,"Grind")
4825	table.insert(human_names,"Happiness")
4826	table.insert(human_names,"Hearken")
4827	table.insert(human_names,"Helena")
4828	table.insert(human_names,"Heracles")
4829	table.insert(human_names,"Honorable Intentions")
4830	table.insert(human_names,"Hope")
4831	table.insert(human_names,"Hurricane")
4832	table.insert(human_names,"Inertia")
4833	table.insert(human_names,"Ingenius")
4834	table.insert(human_names,"Injurious")
4835	table.insert(human_names,"Insight")
4836	table.insert(human_names,"Insufferable")
4837	table.insert(human_names,"Insurmountable")
4838	table.insert(human_names,"Intractable")
4839	table.insert(human_names,"Intransigent")
4840	table.insert(human_names,"Jenny")
4841	table.insert(human_names,"Juice")
4842	table.insert(human_names,"Justice")
4843	table.insert(human_names,"Jurassic")
4844	table.insert(human_names,"Karma Cast")
4845	table.insert(human_names,"Knockout")
4846	table.insert(human_names,"Leila")
4847	table.insert(human_names,"Light Fantastic")
4848	table.insert(human_names,"Livid")
4849	table.insert(human_names,"Lolita")
4850	table.insert(human_names,"Mercury")
4851	table.insert(human_names,"Moira")
4852	table.insert(human_names,"Mona Lisa")
4853	table.insert(human_names,"Nancy")
4854	table.insert(human_names,"Olivia")
4855	table.insert(human_names,"Ominous")
4856	table.insert(human_names,"Oracle")
4857	table.insert(human_names,"Orca")
4858	table.insert(human_names,"Pandemic")
4859	table.insert(human_names,"Parsimonious")
4860	table.insert(human_names,"Personal Prejudice")
4861	table.insert(human_names,"Porpoise")
4862	table.insert(human_names,"Pristine")
4863	table.insert(human_names,"Purple Passion")
4864	table.insert(human_names,"Renegade")
4865	table.insert(human_names,"Revelation")
4866	table.insert(human_names,"Rosanna")
4867	table.insert(human_names,"Rozelle")
4868	table.insert(human_names,"Sainted Gramma")
4869	table.insert(human_names,"Shazam")
4870	table.insert(human_names,"Starbird")
4871	table.insert(human_names,"Stargazer")
4872	table.insert(human_names,"Stile")
4873	table.insert(human_names,"Streak")
4874	table.insert(human_names,"Take Flight")
4875	table.insert(human_names,"Taskmaster")
4876	table.insert(human_names,"Tempest")
4877	table.insert(human_names,"The Way")
4878	table.insert(human_names,"Tornado")
4879	table.insert(human_names,"Trailblazer")
4880	table.insert(human_names,"Trident")
4881	table.insert(human_names,"Triple Threat")
4882	table.insert(human_names,"Turnabout")
4883	table.insert(human_names,"Undulator")
4884	table.insert(human_names,"Urgent")
4885	table.insert(human_names,"Victoria")
4886	table.insert(human_names,"Wee Bit")
4887	table.insert(human_names,"Wet Willie")
4888end
4889
4890function tableRemoveRandom(array)
4891--	Remove random element from array and return it.
4892	-- Returns nil if the array is empty,
4893	-- analogous to `table.remove`.
4894    local array_item_count = #array
4895    if array_item_count == 0 then
4896        return nil
4897    end
4898    local selected_item = math.random(array_item_count)
4899    array[selected_item], array[array_item_count] = array[array_item_count], array[selected_item]
4900    return table.remove(array)
4901end
4902
4903function asteroidSize()
4904	return random(1,160)+random(1,120)+random(1,80)+random(1,40)+random(1,20)+random(1,10)
4905end
4906function createRandomListAlongArc(object_type, amount, x, y, distance, startArc, endArcClockwise, randomize)
4907-- Create amount of objects of type object_type along arc
4908-- Center defined by x and y
4909-- Radius defined by distance
4910-- Start of arc between 0 and 360 (startArc), end arc: endArcClockwise
4911-- Use randomize to vary the distance from the center point. Omit to keep distance constant
4912-- Example:
4913--   createRandomAlongArc(Asteroid, 100, 500, 3000, 65, 120, 450)
4914	local list = {}
4915	if randomize == nil then randomize = 0 end
4916	if amount == nil then amount = 1 end
4917	local arcLen = endArcClockwise - startArc
4918	if startArc > endArcClockwise then
4919		endArcClockwise = endArcClockwise + 360
4920		arcLen = arcLen + 360
4921	end
4922	if amount > arcLen then
4923		for ndex=1,arcLen do
4924			local radialPoint = startArc+ndex
4925			local pointDist = distance + random(-randomize,randomize)
4926			table.insert(list,object_type():setPosition(x + math.cos(radialPoint / 180 * math.pi) * pointDist, y + math.sin(radialPoint / 180 * math.pi) * pointDist))
4927		end
4928		for ndex=1,amount-arcLen do
4929			radialPoint = random(startArc,endArcClockwise)
4930			pointDist = distance + random(-randomize,randomize)
4931			table.insert(list,object_type():setPosition(x + math.cos(radialPoint / 180 * math.pi) * pointDist, y + math.sin(radialPoint / 180 * math.pi) * pointDist))
4932		end
4933	else
4934		for ndex=1,amount do
4935			radialPoint = random(startArc,endArcClockwise)
4936			pointDist = distance + random(-randomize,randomize)
4937			table.insert(list,object_type():setPosition(x + math.cos(radialPoint / 180 * math.pi) * pointDist, y + math.sin(radialPoint / 180 * math.pi) * pointDist))
4938		end
4939	end
4940	return list
4941end
4942function createObjectsListOnLine(x1, y1, x2, y2, spacing, object_type, rows, chance, randomize)
4943-- Create objects along a line between two vectors, optionally with grid
4944-- placement and randomization.
4945--
4946-- createObjectsOnLine(x1, y1, x2, y2, spacing, object_type, rows, chance, randomize)
4947--   x1, y1: Starting coordinates
4948--   x2, y2: Ending coordinates
4949--   spacing: The distance between each object.
4950--   object_type: The object type. Calls `object_type():setPosition()`.
4951--   rows (optional): The number of rows, minimum 1. Defaults to 1.
4952--   chance (optional): The percentile chance an object will be created,
4953--     minimum 1. Defaults to 100 (always).
4954--   randomize (optional): If present, randomize object placement by this
4955--     amount. Defaults to 0 (grid).
4956--
4957--   Examples: To create a mine field, run:
4958--     createObjectsOnLine(0, 0, 10000, 0, 1000, Mine, 4)
4959--   This creates 4 rows of mines from 0,0 to 10000,0, with mines spaced 1U
4960--   apart.
4961--
4962--   The `randomize` parameter adds chaos to the pattern. This works well for
4963--   asteroid fields:
4964--     createObjectsOnLine(0, 0, 10000, 0, 300, Asteroid, 4, 100, 800)
4965	local list = {}
4966    if rows == nil then rows = 1 end
4967    if chance == nil then chance = 100 end
4968    if randomize == nil then randomize = 0 end
4969    local d = distance(x1, y1, x2, y2)
4970    local xd = (x2 - x1) / d
4971    local yd = (y2 - y1) / d
4972    for cnt_x=0,d,spacing do
4973        for cnt_y=0,(rows-1)*spacing,spacing do
4974            local px = x1 + xd * cnt_x + yd * (cnt_y - (rows - 1) * spacing * 0.5) + random(-randomize, randomize)
4975            local py = y1 + yd * cnt_x - xd * (cnt_y - (rows - 1) * spacing * 0.5) + random(-randomize, randomize)
4976            if random(0, 100) < chance then
4977                table.insert(list,object_type():setPosition(px, py))
4978            end
4979        end
4980    end
4981    return list
4982end
4983function placeRandomListAroundPoint(object_type, amount, dist_min, dist_max, x0, y0)
4984-- create amount of object_type, at a distance between dist_min and dist_max around the point (x0, y0)
4985-- save in a list that is returned to caller
4986	local object_list = {}
4987    for n=1,amount do
4988        local r = random(0, 360)
4989        local distance = random(dist_min, dist_max)
4990        x = x0 + math.cos(r / 180 * math.pi) * distance
4991        y = y0 + math.sin(r / 180 * math.pi) * distance
4992        table.insert(object_list,object_type():setPosition(x, y))
4993    end
4994    return object_list
4995end
4996function placeRandomAsteroidsAroundPoint(amount, dist_min, dist_max, x0, y0)
4997-- create amount of asteroid, at a distance between dist_min and dist_max around the point (x0, y0)
4998    for n=1,amount do
4999        local r = random(0, 360)
5000        local distance = random(dist_min, dist_max)
5001        x = x0 + math.cos(r / 180 * math.pi) * distance
5002        y = y0 + math.sin(r / 180 * math.pi) * distance
5003        local asteroid_size = random(1,100) + random(1,75) + random(1,75) + random(1,20) + random(1,20) + random(1,20) + random(1,20) + random(1,20) + random(1,20) + random(1,20)
5004        Asteroid():setPosition(x, y):setSize(asteroid_size)
5005    end
5006end
5007function choosePlanet(index,x,y)
5008	local planet_list = {
5009		{
5010			radius = random(500,1500), distance = -2000,
5011			name = {"Gamma Piscium","Beta Lyporis","Sigma Draconis","Iota Carinae","Theta Arietis","Epsilon Indi","Beta Hydri"},
5012			color = {
5013				red = random(0.9,1), green = random(0.85,1), blue = random(0.9,1)
5014			},
5015			texture = {
5016				atmosphere = "planets/star-1.png"
5017			},
5018		},
5019		{
5020			radius = random(2500,4000), distance = -2000, rotation = random(250,350),
5021			name = {"Bespin","Aldea","Bersallis","Alpha Omicron","Farius Prime","Deneb","Mordan","Nelvana"},
5022			texture = {
5023				surface = "planets/gas-1.png"
5024			},
5025		},
5026		{
5027			radius = random(2000,3500), distance = -2000, rotation = random(350,450),
5028			name = {"Alderaan","Dagobah","Dantooine","Rigel","Pahvo","Penthara","Scalos","Tanuga","Vacca","Terlina","Timor"},
5029			color = {
5030				red = random(0.1,0.3), green = random(0.1,0.3), blue = random(0.9,1)
5031			},
5032			texture = {
5033				surface = "planets/planet-1.png", cloud = "planets/clouds-1.png", atmosphere = "planets/atmosphere.png"
5034			},
5035		},
5036		{
5037			radius = random(200,400), distance = -150, rotation = random(60,100),
5038			name = {"Adrastea","Belior","Cressida","Europa","Kyrrdis","Oberon","Pallas","Telesto","Vesta"},
5039			texture = {
5040				surface = "planets/moon-1.png"
5041			}
5042		},
5043	}
5044	local planet = Planet():setPosition(x,y):setPlanetRadius(planet_list[index].radius):setDistanceFromMovementPlane(planet_list[index].distance):setCallSign(planet_list[index].name[math.random(1,#planet_list[index].name)])
5045	if planet_list[index].texture.surface ~= nil then
5046		planet:setPlanetSurfaceTexture(planet_list[index].texture.surface)
5047	end
5048	if planet_list[index].texture.atmosphere ~= nil then
5049		planet:setPlanetAtmosphereTexture(planet_list[index].texture.atmosphere)
5050	end
5051	if planet_list[index].texture.cloud ~= nil then
5052		planet:setPlanetCloudTexture(planet_list[index].texture.cloud)
5053	end
5054	if planet_list[index].color ~= nil then
5055		planet:setPlanetAtmosphereColor(planet_list[index].color.red,planet_list[index].color.green,planet_list[index].color.blue)
5056	end
5057	if planet_list[index].rotation ~= nil then
5058		planet:setAxialRotationTime(planet_list[index].rotation)
5059	end
5060	return planet, planet_list[index].radius
5061end
5062function vectorFromAngleNorth(angle,distance)
5063	angle = (angle + 270) % 360
5064	local x, y = vectorFromAngle(angle,distance)
5065	return x, y
5066end
5067function angleFromVectorNorth(p1x,p1y,p2x,p2y)
5068	TWOPI = 6.2831853071795865
5069	RAD2DEG = 57.2957795130823209
5070	atan2parm1 = p2x - p1x
5071	atan2parm2 = p2y - p1y
5072	theta = math.atan2(atan2parm1, atan2parm2)
5073	if theta < 0 then
5074		theta = theta + TWOPI
5075	end
5076	return (360 - (RAD2DEG * theta)) % 360
5077end
5078function analyzeBlob(object_list)
5079--given a blob (list) of objects, find the center and the max perimeter and avg dist values
5080	local center_x = 0
5081	local center_y = 0
5082	local max_perimeter = 0
5083	local total_distance = 0
5084	local average_distance = 0
5085	if object_list ~= nil and #object_list > 0 then
5086		for i=1,#object_list do
5087			local obj_x, obj_y = object_list[i]:getPosition()
5088			center_x = center_x + obj_x
5089			center_y = center_y + obj_y
5090		end
5091		center_x = center_x/#object_list
5092		center_y = center_y/#object_list
5093		for i=1,#object_list do
5094--[[
5095			if distance_diagnostic then
5096				print("function analyzeBlob")
5097				if object_list[i] == nil then
5098					print("   object_list[i] is nil")
5099					print("   " .. i)
5100					print("   " .. object_list)
5101				else
5102					print("   " .. i,object_list[i])
5103				end
5104				if center_x == nil then
5105					print("   center_x is nil")
5106				else
5107					print("   center_x: " .. center_x)
5108				end
5109			end
5110--]]
5111			local current_distance = distance(object_list[i],center_x,center_y)
5112			total_distance = total_distance + current_distance
5113			if current_distance >= max_perimeter then
5114				max_perimeter = current_distance
5115			end
5116		end
5117		average_distance = total_distance/#object_list
5118	end
5119	return center_x, center_y, max_perimeter, average_distance
5120end
5121function farEnough(list,pos_x,pos_y,bubble)
5122	local far_enough = true
5123	for i=1,#list do
5124		local list_item = list[i]
5125--[[
5126		if distance_diagnostic then
5127			print("function farEnough")
5128			if list_item == nil then
5129				print("   list_item is nil")
5130				print("   " .. i)
5131				print("   " .. list)
5132			else
5133				print("   " .. i)
5134				print(list_item)
5135			end
5136			if pos_x == nil then
5137				print("   pos_x is nil")
5138			else
5139				print("   pos_x: " .. pos_x)
5140			end
5141		end
5142--]]
5143		local distance_away = distance(list_item,pos_x,pos_y)
5144		if distance_away < bubble then
5145			far_enough = false
5146			break
5147		end
5148		if list_item.typeName == "BlackHole" or list_item.typeName == "WormHole" then
5149			if distance_away < 6000 then
5150				far_enough = false
5151				break
5152			end
5153		end
5154		if list_item.typeName == "Planet" then
5155			if distance_away < 4000 then
5156				far_enough = false
5157				break
5158			end
5159		end
5160	end
5161	return far_enough
5162end
5163--	Player ship types, placement and naming functions
5164function placeCustomPlayerShips()
5165	print("place custom player ships")
5166	player_restart = {}
5167	for pidx=1,32 do
5168		local p = getPlayerShip(pidx)
5169		if p ~= nil and p:isValid() then
5170			p:destroy()
5171		end
5172	end
5173	local angle = human_angle
5174	for _, template in ipairs(custom_player_ship_sets[custom_player_ship_type][ships_per_team]) do
5175--		print("Human ships per team template:",template)
5176		local p = nil
5177		if player_ship_stats[template].stock then
5178			p = PlayerSpaceship():setTemplate(template):setFaction("Human Navy")
5179		else
5180			p = customPlayerShip(template)
5181			p:setFaction("Human Navy")
5182		end
5183		setPlayer(p)
5184		startPlayerPosition(p,angle)
5185		local respawn_x, respawn_y = p:getPosition()
5186		p.respawn_x = respawn_x
5187		p.respawn_y = respawn_y
5188		player_restart[p:getCallSign()] = {self = p, template = p:getTypeName(), control_code = p.control_code, faction = p:getFaction(), respawn_x = respawn_x, respawn_y = respawn_y}
5189		angle = (angle + 360/ships_per_team) % 360
5190	end
5191	replicatePlayers("Kraylor")
5192	if exuari_angle ~= nil then
5193		replicatePlayers("Exuari")
5194	end
5195	if ktlitan_angle ~= nil then
5196		replicatePlayers("Ktlitans")
5197	end
5198end
5199function customPlayerShip(custom_template,p)
5200	if player_ship_stats[custom_template] == nil then
5201		print("Invalid custom player ship template")
5202		return nil
5203	end
5204	if p == nil then
5205		p = PlayerSpaceship()
5206	end
5207	if custom_template == "Striker LX" then
5208		p:setTemplate("Striker")
5209		p:setTypeName("Striker LX")
5210		p:setRepairCrewCount(3)						--more (vs 2)
5211		p:setShieldsMax(100,100)					--stronger shields (vs 50, 30)
5212		p:setShields(100,100)
5213		p:setHullMax(100)							--weaker hull (vs 120)
5214		p:setHull(100)
5215		p:setMaxEnergy(600)							--more maximum energy (vs 500)
5216		p:setEnergy(600)
5217		p:setImpulseMaxSpeed(65)					--faster impulse max (vs 45)
5218	--                 	   Arc, Dir,   Range, CycleTime, Damage
5219		p:setBeamWeapon(0,  10, -15,	1100, 		6.0, 	6.5)	--shorter (vs 1200) more damage (vs 6.0)
5220		p:setBeamWeapon(1,  10,  15,	1100, 		6.0,	6.5)
5221	--							 Arc, Dir, Rotate speed
5222		p:setBeamWeaponTurret(0, 100, -15, .2)		--slower turret speed (vs 6)
5223		p:setBeamWeaponTurret(1, 100,  15, .2)
5224		p:setWeaponTubeCount(2)						--more tubes (vs 0)
5225		p:setWeaponTubeDirection(0,180)
5226		p:setWeaponTubeDirection(1,180)
5227		p:setWeaponStorageMax("Homing",4)
5228		p:setWeaponStorage("Homing", 4)
5229		p:setWeaponStorageMax("Nuke",2)
5230		p:setWeaponStorage("Nuke", 2)
5231		p:setWeaponStorageMax("EMP",3)
5232		p:setWeaponStorage("EMP", 3)
5233		p:setWeaponStorageMax("Mine",3)
5234		p:setWeaponStorage("Mine", 3)
5235		p:setWeaponStorageMax("HVLI",6)
5236		p:setWeaponStorage("HVLI", 6)
5237	elseif custom_template == "Focus" then
5238		p:setTemplate("Crucible")
5239		p:setTypeName("Focus")
5240		p:setImpulseMaxSpeed(70)					--slower (vs 80)
5241		p:setRotationMaxSpeed(20)					--faster spin (vs 15)
5242		p:setWarpDrive(false)						--no warp
5243		p:setHullMax(100)							--weaker hull (vs 160)
5244		p:setHull(100)
5245		p:setShieldsMax(100, 100)					--weaker shields (vs 160, 160)
5246		p:setShields(100, 100)
5247	--                 	   Arc, Dir,  Range,  CycleTime, Damage
5248		p:setBeamWeapon(0,  60, -20, 1000.0,		6.0, 5)	--narrower (vs 70)
5249		p:setBeamWeapon(1,  60,  20, 1000.0,		6.0, 5)
5250		p:setWeaponTubeCount(4)						--fewer (vs 6)
5251		p:weaponTubeAllowMissle(2,"Homing")			--big tube shoots more stuff (vs HVLI)
5252		p:weaponTubeAllowMissle(2,"EMP")
5253		p:weaponTubeAllowMissle(2,"Nuke")
5254		p:setWeaponTubeExclusiveFor(3,"Mine")		--rear (vs left)
5255		p:setWeaponTubeDirection(3, 180)
5256		p:setWeaponStorageMax("EMP",2)				--fewer (vs 6)
5257		p:setWeaponStorage("EMP", 2)
5258		p:setWeaponStorageMax("Nuke",1)				--fewer (vs 4)
5259		p:setWeaponStorage("Nuke", 1)
5260	elseif custom_template == "Holmes" then
5261		p:setTemplate("Crucible")
5262		p:setTypeName("Holmes")
5263		p:setImpulseMaxSpeed(70)					--slower (vs 80)
5264	--					  Arc, Dir, Range, CycleTime, Dmg
5265		p:setBeamWeapon(0, 50, -85, 900.0, 		6.0, 5)	--broadside beams, narrower (vs 70)
5266		p:setBeamWeapon(1, 50, -95, 900.0, 		6.0, 5)
5267		p:setBeamWeapon(2, 50,  85, 900.0, 		6.0, 5)
5268		p:setBeamWeapon(3, 50,  95, 900.0, 		6.0, 5)
5269		p:setWeaponTubeCount(4)						--fewer (vs 6)
5270		p:setWeaponTubeExclusiveFor(0,"Homing")		--tubes only shoot homing missiles (vs more options)
5271		p:setWeaponTubeExclusiveFor(1,"Homing")
5272		p:setWeaponTubeExclusiveFor(2,"Homing")
5273		p:setWeaponTubeExclusiveFor(3,"Mine")
5274		p:setWeaponTubeDirection(3, 180)
5275		p:setWeaponStorageMax("Homing",10)			--more (vs 8)
5276		p:setWeaponStorage("Homing", 10)
5277		p:setWeaponStorageMax("HVLI",0)				--fewer
5278		p:setWeaponStorage("HVLI", 0)
5279		p:setWeaponStorageMax("EMP",0)				--fewer
5280		p:setWeaponStorage("EMP", 0)
5281		p:setWeaponStorageMax("Nuke",0)				--fewer
5282		p:setWeaponStorage("Nuke", 0)
5283	elseif custom_template == "Maverick XP" then
5284		p:setTemplate("Maverick")
5285		p:setTypeName("Maverick XP")
5286		p:setImpulseMaxSpeed(65)				--slower impulse max (vs 80)
5287		p:setWarpDrive(false)					--no warp
5288	--					  Arc, Dir,  Range, CycleTime, Dmg
5289		p:setBeamWeapon(0, 10,   0, 1000.0,      20.0, 20)
5290	--							 Arc, Dir, Rotate speed
5291		p:setBeamWeaponTurret(0, 270,   0, .4)
5292		p:setBeamWeaponEnergyPerFire(0,p:getBeamWeaponEnergyPerFire(0)*6)
5293		p:setBeamWeaponHeatPerFire(0,p:getBeamWeaponHeatPerFire(0)*5)
5294		p:setBeamWeapon(1, 0, 0, 0, 0, 0)		--eliminate 5 beams
5295		p:setBeamWeapon(2, 0, 0, 0, 0, 0)
5296		p:setBeamWeapon(3, 0, 0, 0, 0, 0)
5297		p:setBeamWeapon(4, 0, 0, 0, 0, 0)
5298		p:setBeamWeapon(5, 0, 0, 0, 0, 0)
5299	elseif custom_template == "Phobos T2" then
5300		p:setTemplate("Phobos M3P")
5301		p:setTypeName("Phobos T2")
5302		p:setRepairCrewCount(4)					--more repair crew (vs 3)
5303		p:setRotationMaxSpeed(20)				--faster spin (vs 10)
5304		p:setShieldsMax(120,80)					--stronger front, weaker rear (vs 100,100)
5305		p:setShields(120,80)
5306		p:setMaxEnergy(800)						--less maximum energy (vs 1000)
5307		p:setEnergy(800)
5308	--					  Arc, Dir, Range, CycleTime, Dmg
5309		p:setBeamWeapon(0, 10, -30,  1200,         4, 6)	--split direction (30 vs 15)
5310		p:setBeamWeapon(1, 10,  30,  1200,         4, 6)	--reduced cycle time (4 vs 8)
5311	--							Arc, Dir, Rotate speed
5312		p:setBeamWeaponTurret(0, 60, -30, .3)	--slow turret beams
5313		p:setBeamWeaponTurret(1, 60,  30, .3)
5314		p:setWeaponTubeCount(2)					--one fewer tube (1 forward, 1 rear vs 2 forward, 1 rear)
5315		p:setWeaponTubeDirection(0,0)			--first tube points straight forward
5316		p:setWeaponTubeDirection(1,180)			--second tube points straight back
5317		p:setWeaponTubeExclusiveFor(1,"Mine")
5318		p:setWeaponStorageMax("Homing",8)		--reduce homing storage (vs 10)
5319		p:setWeaponStorage("Homing",8)
5320		p:setWeaponStorageMax("HVLI",16)		--reduce HVLI storage (vs 20)
5321		p:setWeaponStorage("HVLI",16)
5322	end
5323	return p
5324end
5325function placeDefaultPlayerShips()
5326	player_restart = {}
5327	for pidx=1,32 do
5328		local p = getPlayerShip(pidx)
5329		if p ~= nil and p:isValid() then
5330			p:destroy()
5331		end
5332	end
5333	angle = faction_angle["Human Navy"]
5334	for _, template in ipairs(default_player_ship_sets[ships_per_team]) do
5335		local p = PlayerSpaceship():setTemplate(template):setFaction("Human Navy")
5336		setPlayer(p)
5337		startPlayerPosition(p,angle)
5338		local respawn_x, respawn_y = p:getPosition()
5339		p.respawn_x = respawn_x
5340		p.respawn_y = respawn_y
5341		player_restart[p:getCallSign()] = {self = p, template = p:getTypeName(), control_code = p.control_code, faction = p:getFaction(), respawn_x = respawn_x, respawn_y = respawn_y}
5342		angle = (angle + 360/ships_per_team) % 360
5343	end
5344	replicatePlayers("Kraylor")
5345	if exuari_angle ~= nil then
5346		replicatePlayers("Exuari")
5347	end
5348	if ktlitan_angle ~= nil then
5349		replicatePlayers("Ktlitans")
5350	end
5351end
5352function startPlayerPosition(p,angle)
5353--	print("start player position angle:",angle)
5354	vx, vy = vectorFromAngleNorth(angle,player_position_distance)
5355	p:setPosition(faction_primary_station[p:getFaction()].x + vx, faction_primary_station[p:getFaction()].y + vy):setHeading(angle):commandTargetRotation((angle + 270) % 360)
5356end
5357function replicatePlayers(faction)
5358--	Replicate the Human Navy player ships to the designated faction
5359--	print("replicate players faction:",faction)
5360	local angle = faction_angle[faction]
5361	local temp_player_restart = {}
5362	for name, details in pairs(player_restart) do
5363--		print("player restart item faction:",details.faction)
5364		if details.faction == "Human Navy" then
5365--			print("name:",name,"details:",details,"details.template:",details.template,"faction:",faction)
5366			local p = PlayerSpaceship()
5367			if p ~= nil and p:isValid() then
5368				if player_ship_stats[details.template].stock then
5369					p:setTemplate(details.template)
5370				else
5371					customPlayerShip(details.template,p)
5372				end
5373				p:setFaction(faction)
5374				setPlayer(p)
5375				startPlayerPosition(p,angle)
5376				local respawn_x, respawn_y = p:getPosition()
5377				p.respawn_x = respawn_x
5378				p.respawn_y = respawn_y
5379				temp_player_restart[p:getCallSign()] = {self = p, template = p:getTypeName(), control_code = p.control_code, faction = p:getFaction(), respawn_x = respawn_x, respawn_y = respawn_y}
5380				angle = (angle + 360/ships_per_team) % 360
5381			else
5382				addGMMessage("Player creation failed")
5383			end
5384		end
5385	end
5386	for name, details in pairs(temp_player_restart) do
5387		player_restart[name] = {self = details.self, template = details.template, control_code = details.control_code, faction = details.faction, respawn_x = details.respawn_x, respawn_y = details.respawn_y}
5388	end
5389end
5390function namePlayerShip(p)
5391	if p.name == nil then
5392		if rwc_player_ship_names[template_player_type] ~= nil and #rwc_player_ship_names[template_player_type] > 0 then
5393			local selected_name_index = math.random(1,#rwc_player_ship_names[template_player_type])
5394			p:setCallSign(rwc_player_ship_names[template_player_type][selected_name_index])
5395			table.remove(rwc_player_ship_names[template_player_type],selected_name_index)
5396		else
5397			if rwc_player_ship_names["Unknown"] ~= nil and #rwc_player_ship_names["Unknown"] > 0 then
5398				selected_name_index = math.random(1,#rwc_player_ship_names["Unknown"])
5399				p:setCallSign(rwc_player_ship_names["Unknown"][selected_name_index])
5400				table.remove(rwc_player_ship_names["Unknown"],selected_name_index)
5401			end
5402		end
5403	end
5404	p.name = "set"
5405end
5406function playerDestroyed(self,instigator)
5407	respawn_count = respawn_count + 1
5408	if respawn_count > 300 then
5409		print("Hit respawn limit")
5410		return
5411	end
5412	local name = self:getCallSign()
5413	local faction = self:getFaction()
5414	local old_template = self:getTypeName()
5415	local p = PlayerSpaceship()
5416	if p ~= nil and p:isValid() then
5417		if respawn_type == "lindworm" then
5418			p:setTemplate("ZX-Lindworm")
5419		elseif respawn_type == "self" then
5420			p:setTemplate(old_template)
5421			death_penalty[faction] = death_penalty[faction] + self.shipScore
5422		end
5423		p:setFaction(faction)
5424		p.control_code = self.control_code
5425		p:setControlCode(p.control_code)
5426		local name_15 = string.lpad(p:getCallSign(),15)
5427		local cc_15 = string.lpad(p.control_code,15)
5428--		print(p:getCallSign(),"Control code:",p.control_code,"Faction:",faction)
5429		print(name_15,"Control code:",cc_15,"Faction:",faction)
5430		if respawn_type == "lindworm" then
5431			if old_template == "ZX-Lindworm" then
5432				resetPlayer(p,name)
5433			else
5434				resetPlayer(p)
5435			end
5436		elseif respawn_type == "self" then
5437			resetPlayer(p,name)
5438		end
5439		p:setPosition(self.respawn_x, self.respawn_y)
5440		p.respawn_x = self.respawn_x
5441		p.respawn_y = self.respawn_y
5442		if respawn_type == "lindworm" then
5443			player_restart[name] = {self = p, template = "ZX-Lindworm", control_code = p.control_code, faction = faction, respawn_x = self.respawn_x, respawn_y = self.respawn_y}
5444		elseif respawn_type == "self" then
5445			player_restart[name] = {self = p, template = old_template, control_code = p.control_code, faction = faction, respawn_x = self.respawn_x, respawn_y = self.respawn_y}
5446		end
5447	else
5448		respawn_countdown = 2
5449		if restart_queue == nil then
5450			restart_queue = {}
5451		end
5452		table.insert(restart_queue,name)
5453	end
5454end
5455function string.lpad(str, len, char)
5456	if char == nil then
5457		char = " "
5458	end
5459	return str .. string.rep(char, len - string.len(str))
5460end
5461function delayedRespawn(name)
5462	if name == nil then
5463		if restart_queue ~= nil then
5464			if #restart_queue > 0 then
5465				name = restart_queue[1]
5466			else
5467				respawn_countdown = nil
5468				return
5469			end
5470		else
5471			respawn_countdown = nil
5472			return
5473		end
5474	end
5475	if player_restart[name] ~= nil then
5476		local faction = player_restart[name].faction
5477		local old_template = player_restart[name].template
5478		local p = PlayerSpaceship()
5479		if p~= nil and p:isValid() then
5480			if respawn_type == "lindworm" then
5481				p:setTemplate("ZX-Lindworm")
5482			elseif respawn_type == "self" then
5483				p:setTemplate(old_template)
5484				death_penalty[faction] = death_penalty[faction] + self.shipScore
5485			end
5486			p:setFaction(faction)
5487			p.control_code = player_restart[name].control_code
5488			p:setControlCode(p.control_code)
5489			local name_15 = string.lpad(p:getCallSign(),15)
5490			local cc_15 = string.lpad(p.control_code,15)
5491			print(name_15,"Control code:",cc_15,"Faction:",faction)
5492--			print(p:getCallSign(),"Control code:",p.control_code,"Faction:",faction)
5493			if respawn_type == "lindworm" then
5494				if old_template == "ZX-Lindworm" then
5495					resetPlayer(p,name)
5496				else
5497					resetPlayer(p)
5498				end
5499			elseif respawn_type == "self" then
5500				resetPlayer(p,name)
5501			end
5502			p:setPosition(player_restart[name].respawn_x,player_restart[name].respawn_y)
5503			p.respawn_x = player_restart[name].respawn_x
5504			p.respawn_y = player_restart[name].respawn_y
5505			if respawn_type == "lindworm" then
5506				player_restart[name] = {self = p, template = "ZX-Lindworm", control_code = p.control_code, faction = faction, respawn_x = player_restart[name].respawn_x, respawn_y = player_restart[name].respawn_y}
5507			elseif respawn_type == "self" then
5508				player_restart[name] = {self = p, template = old_template, control_code = p.control_code, faction = faction, respawn_x = player_restart[name].respawn_x, respawn_y = player_restart[name].respawn_y}
5509			end
5510			if restart_queue ~= nil and #restart_queue > 0 then
5511				for i=1,#restart_queue do
5512					if restart_queue[i] == name then
5513						table.remove(restart_queue,i)
5514						respawn_countdown = nil
5515						break
5516					end
5517				end
5518			end
5519		else
5520			if restart_queue ~= nil and #restart_queue > 0 then
5521				respawn_countdown = 2
5522			end
5523		end
5524	else
5525		if restart_queue ~= nil then
5526			if #restart_queue > 0 then
5527				for i=1,#restart_queue do
5528					if restart_queue[i] == name then
5529						table.remove(restart_queue,i)
5530						print("problem with " .. name)
5531						break
5532					end
5533				end
5534			end
5535		end
5536	end
5537end
5538function resetPlayer(p,name)
5539	local faction = p:getFaction()
5540	if name == nil then
5541		namePlayerShip(p)
5542	else
5543		p:setCallSign(name)
5544		p.name = "set"
5545	end
5546	commonPlayerSet(p)
5547end
5548function commonPlayerSet(p)
5549	local template_player_type = p:getTypeName()
5550	if template_player_type == "Player Fighter" then
5551--						  Arc, Dir, Range, CycleTime, Dmg
5552		p:setBeamWeapon(0, 40,   0,   500,         6, 4)
5553		p:setBeamWeapon(2, 40, -10,  1000,         6, 8)
5554	end
5555	p.shipScore = player_ship_stats[template_player_type].strength
5556	p.maxCargo = player_ship_stats[template_player_type].cargo
5557	p.cargo = p.maxCargo
5558	p.maxRepairCrew = p:getRepairCrewCount()
5559	p.healthyShield = 1.0
5560	p.prevShield = 1.0
5561	p.healthyReactor = 1.0
5562	p.prevReactor = 1.0
5563	p.healthyManeuver = 1.0
5564	p.prevManeuver = 1.0
5565	p.healthyImpulse = 1.0
5566	p.prevImpulse = 1.0
5567	if p:getBeamWeaponRange(0) > 0 then
5568		p.healthyBeam = 1.0
5569		p.prevBeam = 1.0
5570	end
5571	if p:getWeaponTubeCount() > 0 then
5572		p.healthyMissile = 1.0
5573		p.prevMissile = 1.0
5574	end
5575	if p:hasWarpDrive() then
5576		p.healthyWarp = 1.0
5577		p.prevWarp = 1.0
5578	end
5579	if p:hasJumpDrive() then
5580		p.healthyJump = 1.0
5581		p.prevJump = 1.0
5582	end
5583	p.initialCoolant = p:getMaxCoolant()
5584	p:setLongRangeRadarRange(player_ship_stats[template_player_type].long_range_radar)
5585	p:setShortRangeRadarRange(player_ship_stats[template_player_type].short_range_radar)
5586	p.normal_long_range_radar = p:getLongRangeRadarRange()
5587	p:setMaxScanProbeCount(player_ship_stats[template_player_type].probes)
5588	p:setScanProbeCount(p:getMaxScanProbeCount())
5589	if (not p:hasSystem("jumpdrive") and player_ship_stats[template_player_type].long_jump > 0) or
5590		(p:hasSystem("jumpdrive") and player_ship_stats[template_player_type].long_jump ~= 50) then
5591		p:setJumpDrive(true)
5592		p.max_jump_range = player_ship_stats[template_player_type].long_jump*1000
5593		p.min_jump_range = player_ship_stats[template_player_type].short_jump*1000
5594		p:setJumpDriveRange(p.min_jump_range,p.max_jump_range)
5595		p:setJumpDriveCharge(p.max_jump_range)
5596	end
5597	if not p:hasSystem("warp") and player_ship_stats[template_player_type].warp > 0 then
5598		p:setWarpDrive(true)
5599		p:setWarpSpeed(player_ship_stats[template_player_type].warp)
5600	end
5601	p:onDestroyed(playerDestroyed)
5602end
5603function setPlayer(p)
5604	local faction = p:getFaction()
5605	namePlayerShip(p)
5606--	p:addReputationPoints(1000)	--testing only
5607	p:addReputationPoints(base_reputation)
5608	local control_code_index = math.random(1,#control_code_stem)
5609	local stem = control_code_stem[control_code_index]
5610	table.remove(control_code_stem,control_code_index)
5611	local branch = math.random(100,999)
5612	p.control_code = stem .. branch
5613	local name_15 = string.lpad(p:getCallSign(),15)
5614	local cc_15 = string.lpad(p.control_code,15)
5615	print(name_15,"Control code:",cc_15,"Faction:",faction)
5616--	print(p:getCallSign(),"Control code:",p.control_code,"Faction:",faction)
5617	p:setControlCode(stem .. branch)
5618	commonPlayerSet(p)
5619end
5620--	Station placement related functions
5621function pickStation(name)
5622--	print("pick station name")
5623	if station_pool == nil then
5624		populateStationPool()
5625	end
5626	local selected_station_name = nil
5627	local station_selection_list = {}
5628	local selected_station = nil
5629	local station = nil
5630	if name == nil then
5631		--default to random in priority order
5632		for _, group in ipairs(station_priority) do
5633			if station_pool[group] ~= nil then
5634				for station, details in pairs(station_pool[group]) do
5635					table.insert(station_selection_list,station)
5636				end
5637				if #station_selection_list > 0 then
5638					if selected_station_name == nil then
5639						selected_station_name = station_selection_list[math.random(1,#station_selection_list)]
5640						station = SpaceStation():setCommsScript(""):setCommsFunction(commsStation):setCallSign(selected_station_name):setDescription(station_pool[group][selected_station_name].description)
5641						station.comms_data = station_pool[group][selected_station_name]
5642						station_pool[group][selected_station_name] = nil
5643						return group, station
5644					end
5645				end
5646			end
5647		end
5648	else
5649--		print("name parameter provided:",name)
5650		if name == "Random" then
5651			--random across all groups
5652			for group, list in pairs(station_pool) do
5653				for station_name, station_details in pairs(list) do
5654					table.insert(station_selection_list,{group = group, station_name = station_name, station_details = station_details})
5655				end
5656			end
5657			if #station_selection_list > 0 then
5658				selected_station = station_selection_list[math.random(1,#station_selection_list)]
5659				station = SpaceStation():setCommsScript(""):setCommsFunction(commsStation):setCallSign(selected_station.station_name):setDescription(selected_station.station_details.description)
5660				station.comms_data = selected_station.station_details
5661				station_pool[selected_station.group][selected_station.station_name] = nil
5662				return selected_station.group, station
5663			end
5664		elseif name == "RandomHumanNeutral" then
5665			for group, list in pairs(station_pool) do
5666				if group ~= "Generic" and group ~= "Sinister" then
5667					for station_name, station_details in pairs(list) do
5668						table.insert(station_selection_list,{group = group, station_name = station_name, station_details = station_details})
5669					end
5670				end
5671			end
5672			if #station_selection_list > 0 then
5673				selected_station = station_selection_list[math.random(1,#station_selection_list)]
5674				station = SpaceStation():setCommsScript(""):setCommsFunction(commsStation):setCallSign(selected_station.station_name):setDescription(selected_station.station_details.description)
5675				station.comms_data = selected_station.station_details
5676				station_pool[selected_station.group][selected_station.station_name] = nil
5677				return selected_station.group, station
5678			end
5679		elseif name == "RandomGenericSinister" then
5680			for group, list in pairs(station_pool) do
5681				if group == "Generic" or group == "Sinister" then
5682					for station_name, station_details in pairs(list) do
5683						table.insert(station_selection_list,{group = group, station_name = station_name, station_details = station_details})
5684					end
5685				end
5686			end
5687			if #station_selection_list > 0 then
5688				selected_station = station_selection_list[math.random(1,#station_selection_list)]
5689				station = SpaceStation():setCommsScript(""):setCommsFunction(commsStation):setCallSign(selected_station.station_name):setDescription(selected_station.station_details.description)
5690				station.comms_data = selected_station.station_details
5691				station_pool[selected_station.group][selected_station.station_name] = nil
5692				return selected_station.group, station
5693			end
5694		else
5695--			print("not one of the generic random names")
5696			if station_pool[name] ~= nil then
5697--				print("name is a group name")
5698				--name is a group name
5699				for station_name, station_details in pairs(station_pool[name]) do
5700					table.insert(station_selection_list,{station_name = station_name, station_details = station_details})
5701				end
5702				if #station_selection_list > 0 then
5703					selected_station = station_selection_list[math.random(1,#station_selection_list)]
5704					station = SpaceStation():setCommsScript(""):setCommsFunction(commsStation):setCallSign(selected_station.station_name):setDescription(selected_station.station_details.description)
5705					station.comms_data = selected_station.station_details
5706					station_pool[name][selected_station.station_name] = nil
5707					return name, station
5708				end
5709			else
5710--				print("name is not a group name")
5711				for group, list in pairs(station_pool) do
5712					if station_pool[group][name] ~= nil then
5713						station = SpaceStation():setCommsScript(""):setCommsFunction(commsStation):setCallSign(name):setDescription(station_pool[group][name].description)
5714						station.comms_data = station_pool[group][name]
5715						station_pool[group][name] = nil
5716						return group, station
5717					end
5718				end
5719				--name not found in any group
5720				print("Name provided not found in groups or stations, nor is it an accepted specialized name, like Random, RandomHumanNeutral or RandomGenericSinister")
5721				return nil
5722			end
5723		end
5724	end
5725	return nil
5726end
5727function szt()
5728--Randomly choose station size template
5729	if stationSize ~= nil then
5730		sizeTemplate = stationSize
5731		return sizeTemplate
5732	end
5733	stationSizeRandom = random(1,100)
5734	if stationSizeRandom < 8 then
5735		sizeTemplate = "Huge Station"		-- 8 percent huge
5736	elseif stationSizeRandom < 24 then
5737		sizeTemplate = "Large Station"		--16 percent large
5738	elseif stationSizeRandom < 50 then
5739		sizeTemplate = "Medium Station"		--26 percent medium
5740	else
5741		sizeTemplate = "Small Station"		--50 percent small
5742	end
5743	return sizeTemplate
5744end
5745function placeStation(x,y,name,faction,size)
5746	--x and y are the position of the station
5747	--name should be the name of the station or the name of the station group
5748	--		omit name to get random station from groups in priority order
5749	--faction is the faction of the station
5750	--		omit and stationFaction will be used
5751	--size is the name of the station template to use
5752	--		omit and station template will be chosen at random via szt function
5753	if x == nil then return nil end
5754	if y == nil then return nil end
5755	local group, station = pickStation(name)
5756	if group == nil then return nil end
5757	station:setPosition(x,y)
5758	if faction ~= nil then
5759		station:setFaction(faction)
5760	else
5761		if stationFaction ~= nil then
5762			station:setFaction(stationFaction)
5763		else
5764			station:setFaction("Independent")
5765		end
5766	end
5767	if size == nil then
5768		station:setTemplate(szt())
5769	else
5770		local function Set(list)
5771			local set = {}
5772			for _, item in ipairs(list) do
5773				set[item] = true
5774			end
5775			return set
5776		end
5777		local station_size_templates = Set{"Small Station","Medium Station","Large Station","Huge Station"}
5778		if station_size_templates[size] then
5779			station:setTemplate(size)
5780		else
5781			station:setTemplate(szt())
5782		end
5783	end
5784	local size_matters = 0
5785	local station_size = station:getTypeName()
5786	if station_size == "Medium Station" then
5787		size_matters = 20
5788	elseif station_size == "Large Station" then
5789		size_matters = 30
5790	elseif station_size == "Huge Station" then
5791		size_matters = 40
5792	end
5793	station.comms_data.probe_launch_repair =	random(1,100) <= (20 + size_matters)
5794	station.comms_data.scan_repair =			random(1,100) <= (30 + size_matters)
5795	station.comms_data.hack_repair =			random(1,100) <= (10 + size_matters)
5796	station.comms_data.combat_maneuver_repair =	random(1,100) <= (15 + size_matters)
5797	station.comms_data.self_destruct_repair =	random(1,100) <= (25 + size_matters)
5798	station.comms_data.jump_overcharge =		random(1,100) <= (5 + size_matters)
5799	station:setSharesEnergyWithDocked(random(1,100) <= (50 + size_matters))
5800	station:setRepairDocked(random(1,100) <= (55 + size_matters))
5801	station:setRestocksScanProbes(random(1,100) <= (45 + size_matters))
5802	--specialized code for particular stations
5803	return station
5804end
5805function randomComponent(exclude)
5806	local good = componentGoods[math.random(1,#componentGoods)]
5807	if exclude == nil then
5808		return good
5809	else
5810		repeat
5811			good = componentGoods[math.random(1,#componentGoods)]
5812		until(good ~= exclude)
5813		return good
5814	end
5815end
5816function randomMineral(exclude)
5817	local good = mineralGoods[math.random(1,#mineralGoods)]
5818	if exclude == nil then
5819		return good
5820	else
5821		repeat
5822			good = mineralGoods[math.random(1,#mineralGoods)]
5823		until(good ~= exclude)
5824		return good
5825	end
5826end
5827function populateStationPool()
5828	station_pool = {
5829		["Science"] = {
5830			["Asimov"] = {
5831		        weapon_available = 	{
5832		        	Homing =			true,
5833		        	HVLI =				random(1,13)<=(9-difficulty),
5834		        	Mine =				true,
5835		        	Nuke =				random(1,13)<=(5-difficulty),
5836		        	EMP =				random(1,13)<=(6-difficulty),
5837		        },
5838				services = {
5839					supplydrop = "friend",
5840					reinforcements = "friend",
5841					jumpsupplydrop = "friend",
5842				},
5843		        service_cost = {
5844		        	supplydrop =		math.random(80,120),
5845		        	reinforcements =	math.random(125,175),
5846		        	jumpsupplydrop =	math.random(110,140),
5847		        },
5848		        reputation_cost_multipliers = {
5849		        	friend = 			1.0,
5850		        	neutral = 			3.0,
5851		        },
5852        		goods = {
5853        			tractor = {
5854        				quantity =	5,
5855        				cost =		48,
5856        			},
5857        			repulsor = {
5858        				quantity =	5,
5859        				cost =		48,
5860        			},
5861        		},
5862		        trade = {
5863		        	food =			false,
5864		        	medicine =		false,
5865		        	luxury =		false,
5866		        },
5867				description = "Training and Coordination",
5868				general = "We train naval cadets in routine and specialized functions aboard space vessels and coordinate naval activity throughout the sector",
5869				history = "The original station builders were fans of the late 20th century scientist and author Isaac Asimov. The station was initially named Foundation, but was later changed simply to Asimov. It started off as a stellar observatory, then became a supply stop and as it has grown has become an educational and coordination hub for the region",
5870			},
5871			["Armstrong"] =	{
5872		        weapon_available = {
5873		        	Homing = 			random(1,13)<=(8-difficulty),
5874		        	HVLI = 				true,
5875		        	Mine = 				random(1,13)<=(7-difficulty),
5876		        	Nuke = 				random(1,13)<=(5-difficulty),
5877		        	EMP = 				true
5878		        },
5879				services = {
5880					supplydrop =		"friend",
5881					reinforcements =	"friend",
5882					jumpsupplydrop =	"friend",
5883				},
5884		        service_cost = {
5885		        	supplydrop =		math.random(80,120),
5886		        	reinforcements =	math.random(125,175),
5887		        	jumpsupplydrop =	math.random(110,140),
5888		        },
5889				goods = {
5890					warp = {
5891						quantity =	5,
5892						cost =		77,
5893					},
5894					repulsor = {
5895						quantity =	5,
5896						cost =		62,
5897					},
5898				},
5899				trade = {
5900					food = random(1,100) <= 45,
5901					medicine = false,
5902					luxury = false,
5903				},
5904				buy = {
5905					[randomMineral()] = math.random(40,200),
5906				},
5907				description = "Warp and Impulse engine manufacturing",
5908				general = "We manufacture warp, impulse and jump engines for the human navy fleet as well as other independent clients on a contract basis",
5909				history = "The station is named after the late 19th century astronaut as well as the fictionlized stations that followed. The station initially constructed entire space worthy vessels. In time, it transitioned into specializeing in propulsion systems.",
5910			},
5911			["Broeck"] = {
5912		        weapon_available = {
5913		        	Homing =			random(1,13)<=(8-difficulty),
5914		        	HVLI =				random(1,13)<=(9-difficulty),
5915		        	Mine =				random(1,13)<=(7-difficulty),
5916		        	Nuke =				random(1,13)<=(5-difficulty),
5917		        	EMP =				random(1,13)<=(6-difficulty),
5918		        },
5919				services = {
5920					supplydrop =		"friend",
5921					reinforcements =	"friend",
5922					jumpsupplydrop =	"friend",
5923				},
5924		        service_cost = {
5925		        	supplydrop =		math.random(80,120),
5926		        	reinforcements =	math.random(125,175),
5927		        	jumpsupplydrop =	math.random(110,140),
5928		        },
5929				goods = {
5930					warp = {
5931						quantity =	5,
5932						cost =		36,
5933					},
5934				},
5935				trade = {
5936					food = random(1,100) <= 14,
5937					medicine = false,
5938					luxury = random(1,100) < 62,
5939				},
5940				buy = {
5941					[randomMineral()] = math.random(40,200),
5942				},
5943				description = "Warp drive components",
5944				general = "We provide warp drive engines and components",
5945				history = "This station is named after Chris Van Den Broeck who did some initial research into the possibility of warp drive in the late 20th century on Earth",
5946			},
5947			["Coulomb"] = {
5948		        weapon_available = 	{
5949		        	Homing = random(1,13)<=(8-difficulty),
5950		        	HVLI = random(1,13)<=(9-difficulty),
5951		        	Mine = random(1,13)<=(7-difficulty),
5952		        	Nuke = random(1,13)<=(5-difficulty),
5953		        	EMP = random(1,13)<=(6-difficulty),
5954		        },
5955				services = {
5956					supplydrop =		"friend",
5957					reinforcements =	"friend",
5958					jumpsupplydrop =	"friend",
5959				},
5960		        service_cost = {
5961		        	supplydrop =		math.random(80,120),
5962		        	reinforcements =	math.random(125,175),
5963		        	jumpsupplydrop =	math.random(110,140),
5964		        },
5965		        reputation_cost_multipliers = {
5966		        	friend = 1.0,
5967		        	neutral = 3.0,
5968		        },
5969        		goods = {
5970        			circuit =	{
5971        				quantity =	5,
5972        				cost =		50,
5973        			},
5974        		},
5975        		trade = {
5976        			food = random(1,100) <= 35,
5977        			medicine = false,
5978        			luxury = random(1,100) < 82,
5979        		},
5980				buy =	{
5981					[randomMineral()] = math.random(40,200),
5982				},
5983				description = "Shielded circuitry fabrication",
5984				general = "We make a large variety of circuits for numerous ship systems shielded from sensor detection and external control interference",
5985				history = "Our station is named after the law which quantifies the amount of force with which stationary electrically charged particals repel or attact each other - a fundamental principle in the design of our circuits",
5986			},
5987			["Heyes"] = {
5988		        weapon_available = {
5989		        	Homing =			random(1,13)<=(8-difficulty),
5990		        	HVLI =				true,
5991		        	Mine =				random(1,13)<=(7-difficulty),
5992		        	Nuke =				random(1,13)<=(5-difficulty),
5993		        	EMP =				random(1,13)<=(6-difficulty),
5994		        },
5995				services = {
5996					supplydrop =		"friend",
5997					reinforcements =	"friend",
5998					jumpsupplydrop =	"friend",
5999				},
6000		        service_cost = {
6001		        	supplydrop =		math.random(80,120),
6002		        	reinforcements =	math.random(125,175),
6003		        	jumpsupplydrop =	math.random(110,140),
6004		        },
6005		        reputation_cost_multipliers = {
6006		        	friend = 1.0,
6007		        	neutral = 3.0,
6008		        },
6009				goods = {
6010					sensor = {
6011						quantity =	5,
6012						cost =		72,
6013					},
6014				},
6015				trade = {
6016					food = random(1,100) <= 32,
6017					medicine = false,
6018					luxury = true,
6019				},
6020				buy = {
6021					[randomMineral()] = math.random(40,200),
6022				},
6023				description = "Sensor components",
6024				general = "We research and manufacture sensor components and systems",
6025				history = "The station is named after Tony Heyes the inventor of some of the earliest electromagnetic sensors in the mid 20th century on Earth in the United Kingdom to assist blind human mobility",
6026			},
6027			["Hossam"] = {
6028		        weapon_available = {
6029		        	Homing =			random(1,13)<=(8-difficulty),
6030		        	HVLI =				random(1,13)<=(9-difficulty),
6031		        	Mine =				random(1,13)<=(7-difficulty),
6032		        	Nuke =				random(1,13)<=(5-difficulty),
6033		        	EMP =				random(1,13)<=(6-difficulty),
6034		        },
6035				services = {
6036					supplydrop =		"friend",
6037					reinforcements =	"friend",
6038					jumpsupplydrop =	"friend",
6039				},
6040		        service_cost = {
6041		        	supplydrop =		math.random(80,120),
6042		        	reinforcements =	math.random(125,175),
6043		        	jumpsupplydrop =	math.random(110,140),
6044		        },
6045		        reputation_cost_multipliers = {
6046		        	friend = 1.0,
6047		        	neutral = 3.0,
6048		        },
6049				goods = {
6050					nanites = {
6051						quantity =	5,
6052						cost =		90,
6053					},
6054				},
6055				trade = {
6056					food = random(1,100) < 24,
6057					medicine = random(1,100) < 44,
6058					luxury = random(1,100) < 63,
6059				},
6060				description = "Nanite supplier",
6061				general = "We provide nanites for various organic and non-organic systems",
6062				history = "This station is named after the nanotechnologist Hossam Haick from the early 21st century on Earth in Israel",
6063			},
6064			["Maiman"] = {
6065		        weapon_available = {
6066		        	Homing =			random(1,13)<=(8-difficulty),
6067		        	HVLI =				false,
6068		        	Mine =				random(1,13)<=(7-difficulty),
6069		        	Nuke =				random(1,13)<=(5-difficulty),
6070		        	EMP =				random(1,13)<=(6-difficulty),
6071		        },
6072				services = {
6073					supplydrop =		"friend",
6074					reinforcements =	"friend",
6075					jumpsupplydrop =	"friend",
6076				},
6077		        service_cost = {
6078		        	supplydrop =		math.random(80,120),
6079		        	reinforcements =	math.random(125,175),
6080		        	jumpsupplydrop =	math.random(110,140),
6081		        },
6082		        reputation_cost_multipliers = {
6083		        	friend = 1.0,
6084		        	neutral = 3.0,
6085		        },
6086				goods = {
6087					beam = {
6088						quantity =	5,
6089						cost =		70,
6090					},
6091				},
6092				trade = {
6093					food = random(1,100) <= 75,
6094					medicine = true,
6095					luxury = false,
6096				},
6097				buy = {
6098					[randomMineral()] = math.random(40,200),
6099				},
6100				description = "Energy beam components",
6101				general = "We research and manufacture energy beam components and systems",
6102				history = "The station is named after Theodore Maiman who researched and built the first laser in the mid 20th century on Earth",
6103			},
6104			["Malthus"] = {
6105		        weapon_available = {
6106		        	Homing =			random(1,13)<=(8-difficulty),
6107		        	HVLI =				random(1,13)<=(9-difficulty),
6108		        	Mine =				random(1,13)<=(7-difficulty),
6109		        	Nuke =				random(1,13)<=(5-difficulty),
6110		        	EMP =				random(1,13)<=(6-difficulty),
6111		        },
6112				services = {
6113					supplydrop =		"friend",
6114					reinforcements =	"friend",
6115					jumpsupplydrop =	"friend",
6116				},
6117		        service_cost = {
6118		        	supplydrop =		math.random(80,120),
6119		        	reinforcements =	math.random(125,175),
6120		        	jumpsupplydrop =	math.random(110,140),
6121		        },
6122		        reputation_cost_multipliers = {
6123		        	friend = 1.0,
6124		        	neutral = 3.0,
6125		        },
6126		        goods = {},
6127    			trade = {
6128    				food = random(1,100) <= 65,
6129    				medicine = false,
6130    				luxury = false,
6131    			},
6132    			description = "Gambling and resupply",
6133		        general = "The oldest station in the quadrant",
6134		        history = "",
6135			},
6136			["Marconi"] = {
6137		        weapon_available = {
6138		        	Homing =			random(1,13)<=(8-difficulty),
6139		        	HVLI =				random(1,13)<=(9-difficulty),
6140		        	Mine =				random(1,13)<=(7-difficulty),
6141		        	Nuke =				random(1,13)<=(5-difficulty),
6142		        	EMP =				random(1,13)<=(6-difficulty),
6143		        },
6144				services = {
6145					supplydrop =		"friend",
6146					reinforcements =	"friend",
6147					jumpsupplydrop =	"friend",
6148				},
6149		        service_cost = {
6150		        	supplydrop =		math.random(80,120),
6151		        	reinforcements =	math.random(125,175),
6152		        	jumpsupplydrop =	math.random(110,140),
6153		        },
6154		        reputation_cost_multipliers = {
6155		        	friend = 1.0,
6156		        	neutral = 3.0,
6157		        },
6158				goods = {
6159					beam = {
6160						quantity =	5,
6161						cost =		80,
6162					},
6163				},
6164				trade = {
6165					food = random(1,100) <= 53,
6166					medicine = false,
6167					luxury = true,
6168				},
6169				description = "Energy Beam Components",
6170				general = "We manufacture energy beam components",
6171				history = "Station named after Guglielmo Marconi an Italian inventor from early 20th century Earth who, along with Nicolo Tesla, claimed to have invented a death ray or particle beam weapon",
6172			},
6173			["Miller"] = {
6174		        weapon_available = {
6175		        	Homing =			random(1,13)<=(8-difficulty),
6176		        	HVLI =				random(1,13)<=(9-difficulty),
6177		        	Mine =				random(1,13)<=(7-difficulty),
6178		        	Nuke =				random(1,13)<=(5-difficulty),
6179		        	EMP =				random(1,13)<=(6-difficulty),
6180		        },
6181				services = {
6182					supplydrop =		"friend",
6183					reinforcements =	"friend",
6184					jumpsupplydrop =	"friend",
6185				},
6186		        service_cost = {
6187		        	supplydrop =		math.random(80,120),
6188		        	reinforcements =	math.random(125,175),
6189		        	jumpsupplydrop =	math.random(110,140),
6190		        },
6191		        reputation_cost_multipliers = {
6192		        	friend = 1.0,
6193		        	neutral = 3.0,
6194		        },
6195				goods = {
6196					optic =	{
6197						quantity =	5,
6198						cost =		60,
6199					},
6200				},
6201				trade = {
6202					food = random(1,100) <= 68,
6203					medicine = false,
6204					luxury = false,
6205				},
6206				description = "Exobiology research",
6207				general = "We study recently discovered life forms not native to Earth",
6208				history = "This station was named after one of the early exobiologists from mid 20th century Earth, Dr. Stanley Miller",
6209			},
6210			["Shawyer"] = {
6211		        weapon_available = {
6212		        	Homing =			random(1,13)<=(8-difficulty),
6213		        	HVLI =				random(1,13)<=(9-difficulty),
6214		        	Mine =				random(1,13)<=(7-difficulty),
6215		        	Nuke =				random(1,13)<=(5-difficulty),
6216		        	EMP =				random(1,13)<=(6-difficulty),
6217		        },
6218				services = {
6219					supplydrop =		"friend",
6220					reinforcements =	"friend",
6221					jumpsupplydrop =	"friend",
6222				},
6223		        service_cost = {
6224		        	supplydrop =		math.random(80,120),
6225		        	reinforcements =	math.random(125,175),
6226		        	jumpsupplydrop =	math.random(110,140),
6227		        },
6228		        reputation_cost_multipliers = {
6229		        	friend = 1.0,
6230		        	neutral = 2.0,
6231		        },
6232				goods = {
6233					impulse = {
6234						quantity =	5,
6235						cost =		100,
6236					},
6237				},
6238				trade = {
6239					food = random(1,100) <= 42,
6240					medicine = false,
6241					luxury = true,
6242				},
6243				description = "Impulse engine components",
6244				general = "We research and manufacture impulse engine components and systems",
6245				history = "The station is named after Roger Shawyer who built the first prototype impulse engine in the early 21st century",
6246			},
6247		},
6248		["History"] = {
6249			["Archimedes"] = {
6250		        weapon_available = {
6251		        	Homing =			random(1,13)<=(8-difficulty),
6252		        	HVLI =				random(1,13)<=(9-difficulty),
6253		        	Mine =				random(1,13)<=(7-difficulty),
6254		        	Nuke =				random(1,13)<=(5-difficulty),
6255		        	EMP =				random(1,13)<=(6-difficulty),
6256		        },
6257				services = {
6258					supplydrop =		"friend",
6259					reinforcements =	"friend",
6260					jumpsupplydrop =	"friend",
6261				},
6262		        service_cost = {
6263		        	supplydrop =		math.random(80,120),
6264		        	reinforcements =	math.random(125,175),
6265		        	jumpsupplydrop =	math.random(110,140),
6266		        },
6267		        reputation_cost_multipliers = {
6268		        	friend = 1.0,
6269		        	neutral = 3.0,
6270		        },
6271				goods = {
6272					beam = {
6273						quantity =	5,
6274						cost =		80,
6275					},
6276				},
6277				trade = {
6278					food = true,
6279					medicine = false,
6280					luxury = true,
6281				},
6282				description = "Energy and particle beam components",
6283				general = "We fabricate general and specialized components for ship beam systems",
6284				history = "This station was named after Archimedes who, according to legend, used a series of adjustable focal length mirrors to focus sunlight on a Roman naval fleet invading Syracuse, setting fire to it",
6285			},
6286			["Chatuchak"] =	{
6287		        weapon_available = {
6288		        	Homing =				random(1,10)<=(8-difficulty),
6289		        	HVLI =				random(1,10)<=(9-difficulty),
6290		        	Mine =				false,
6291		        	Nuke =				random(1,10)<=(5-difficulty),
6292		        	EMP =				random(1,10)<=(6-difficulty),
6293		        },
6294				services = {
6295					supplydrop =		"friend",
6296					reinforcements =	"friend",
6297					jumpsupplydrop =	"friend",
6298				},
6299		        service_cost = {
6300		        	supplydrop =		math.random(80,120),
6301		        	reinforcements =	math.random(125,175),
6302		        	jumpsupplydrop =	math.random(110,140),
6303		        },
6304		        reputation_cost_multipliers = {
6305		        	friend = 1.0,
6306		        	neutral = 2.0,
6307		        },
6308				goods = {
6309					luxury = {
6310						quantity =	5,
6311						cost =		60,
6312					},
6313				},
6314				trade = {
6315					food = false,
6316					medicine = false,
6317					luxury = false,
6318				},
6319				description = "Trading station",
6320				general = "Only the largest market and trading location in twenty sectors. You can find your heart's desire here",
6321				history = "Modeled after the early 21st century bazaar on Earth in Bangkok, Thailand. Designed and built with trade and commerce in mind",
6322			},
6323			["Grasberg"] = {
6324		        weapon_available = {
6325		        	Homing =			random(1,13)<=(8-difficulty),
6326		        	HVLI =				random(1,13)<=(9-difficulty),
6327		        	Mine =				random(1,13)<=(7-difficulty),
6328		        	Nuke =				random(1,13)<=(5-difficulty),
6329		        	EMP =				random(1,13)<=(6-difficulty),
6330		        },
6331				services = {
6332					supplydrop =		"friend",
6333					reinforcements =	"friend",
6334					jumpsupplydrop =	"friend",
6335				},
6336		        service_cost = {
6337		        	supplydrop =		math.random(80,120),
6338		        	reinforcements =	math.random(125,175),
6339		        	jumpsupplydrop =	math.random(110,140),
6340		        },
6341		        reputation_cost_multipliers = {
6342		        	friend = 1.0,
6343		        	neutral = 2.0,
6344		        },
6345				goods = {
6346					luxury = {
6347						quantity =	5,
6348						cost =		70,
6349					},
6350				},
6351				trade = {
6352					food = true,
6353					medicine = false,
6354					luxury = false,
6355				},
6356				buy = {
6357					[randomComponent()] = math.random(40,200),
6358				},
6359				description = "Mining",
6360				general ="We mine nearby asteroids for precious minerals and process them for sale",
6361				history = "This station's name is inspired by a large gold mine on Earth in Indonesia. The station builders hoped to have a similar amount of minerals found amongst these asteroids",
6362			},
6363			["Hayden"] = {
6364		        weapon_available = {
6365		        	Homing = random(1,13)<=(8-difficulty),
6366		        	HVLI = random(1,13)<=(9-difficulty),
6367		        	Mine = random(1,13)<=(7-difficulty),
6368		        	Nuke = random(1,13)<=(5-difficulty),
6369		        	EMP = random(1,13)<=(6-difficulty),
6370		        },
6371				services = {
6372					supplydrop =		"friend",
6373					reinforcements =	"friend",
6374					jumpsupplydrop =	"friend",
6375				},
6376		        service_cost = {
6377		        	supplydrop =		math.random(80,120),
6378		        	reinforcements =	math.random(125,175),
6379		        	jumpsupplydrop =	math.random(110,140),
6380		        },
6381		        reputation_cost_multipliers = {
6382		        	friend = 1.0,
6383		        	neutral = 2.0,
6384		        },
6385				goods = {
6386					nanites = {
6387						quantity =	5,
6388						cost =		65,
6389					},
6390				},
6391				trade = {
6392					food = random(1,100) <= 85,
6393					medicine = false,
6394					luxury = false,
6395				},
6396				description = "Observatory and stellar mapping",
6397				general = "We study the cosmos and map stellar phenomena. We also track moving asteroids. Look out! Just kidding",
6398				history = "Station named in honor of Charles Hayden whose philanthropy continued astrophysical research and education on Earth in the early 20th century",
6399			},
6400			["Lipkin"] = {
6401		        weapon_available = {
6402		        	Homing =				random(1,13)<=(8-difficulty),
6403		        	HVLI =				random(1,13)<=(9-difficulty),
6404		        	Mine =				false,
6405		        	Nuke =				random(1,13)<=(5-difficulty),
6406		        	EMP =				random(1,13)<=(6-difficulty),
6407		        },
6408				services = {
6409					supplydrop =		"friend",
6410					reinforcements =	"friend",
6411					jumpsupplydrop =	"friend",
6412				},
6413		        service_cost = {
6414		        	supplydrop =		math.random(80,120),
6415		        	reinforcements =	math.random(125,175),
6416		        	jumpsupplydrop =	math.random(110,140),
6417		        },
6418		        reputation_cost_multipliers = {
6419		        	friend = 1.0,
6420		        	neutral = 2.0,
6421		        },
6422				goods = {
6423					autodoc = {
6424						quantity =	5,
6425						cost =		76,
6426					},
6427				},
6428				trade = {
6429					food = false,
6430					medicine = false,
6431					luxury = true,
6432				},
6433				description = "Autodoc components",
6434				general = "",
6435				history = "The station is named after Dr. Lipkin who pioneered some of the research and application around robot assisted surgery in the area of partial nephrectomy for renal tumors in the early 21st century on Earth",
6436			},
6437			["Madison"] = {
6438		        weapon_available = {
6439		        	Homing =			false,
6440		        	HVLI =				random(1,13)<=(9-difficulty),
6441		        	Mine =				random(1,13)<=(7-difficulty),
6442		        	Nuke =				random(1,13)<=(5-difficulty),
6443		        	EMP =				random(1,13)<=(6-difficulty),
6444		        },
6445				services = {
6446					supplydrop =		"friend",
6447					reinforcements =	"friend",
6448					jumpsupplydrop =	"friend",
6449				},
6450		        service_cost = {
6451		        	supplydrop =		math.random(80,120),
6452		        	reinforcements =	math.random(125,175),
6453		        	jumpsupplydrop =	math.random(110,140),
6454		        },
6455		        reputation_cost_multipliers = {
6456		        	friend = 1.0,
6457		        	neutral = 2.0,
6458		        },
6459				goods = {
6460					luxury = {
6461						quantity =	5,
6462						cost =		math.random(60,70),
6463					},
6464				},
6465				trade = {
6466					food = false,
6467					medicine = true,
6468					luxury = false,
6469				},
6470				description = "Zero gravity sports and entertainment",
6471				general = "Come take in a game or two or perhaps see a show",
6472				history = "Named after Madison Square Gardens from 21st century Earth, this station was designed to serve similar purposes in space - a venue for sports and entertainment",
6473			},
6474			["Rutherford"] = {
6475		        weapon_available = {
6476		        	Homing = random(1,13)<=(8-difficulty),
6477		        	HVLI = random(1,13)<=(9-difficulty),
6478		        	Mine = random(1,13)<=(7-difficulty),
6479		        	Nuke = random(1,13)<=(5-difficulty),
6480		        	EMP = random(1,13)<=(6-difficulty),
6481		        },
6482				services = {
6483					supplydrop =		"friend",
6484					reinforcements =	"friend",
6485					jumpsupplydrop =	"friend",
6486				},
6487		        service_cost = {
6488		        	supplydrop =		math.random(80,120),
6489		        	reinforcements =	math.random(125,175),
6490		        	jumpsupplydrop =	math.random(110,140),
6491		        },
6492		        reputation_cost_multipliers = {
6493		        	friend = 1.0,
6494		        	neutral = 2.0,
6495		        },
6496				goods = {
6497					shield = {
6498						quantity =	5,
6499						cost =		90,
6500					},
6501				},
6502				trade = {
6503					food = false,
6504					medicine = false,
6505					luxury = random(1,100) < 43,
6506				},
6507				description = "Shield components and research",
6508				general = "We research and fabricate components for ship shield systems",
6509				history = "This station was named after the national research institution Rutherford Appleton Laboratory in the United Kingdom which conducted some preliminary research into the feasability of generating an energy shield in the late 20th century",
6510			},
6511			["Toohie"] = {
6512		        weapon_available = {
6513		        	Homing =			random(1,13)<=(8-difficulty),
6514		        	HVLI =				random(1,13)<=(9-difficulty),
6515		        	Mine =				random(1,13)<=(7-difficulty),
6516		        	Nuke =				random(1,13)<=(5-difficulty),
6517		        	EMP =				random(1,13)<=(6-difficulty),
6518		        },
6519				services = {
6520					supplydrop =		"friend",
6521					reinforcements =	"friend",
6522					jumpsupplydrop =	"friend",
6523				},
6524		        service_cost = {
6525		        	supplydrop =		math.random(80,120),
6526		        	reinforcements =	math.random(125,175),
6527		        	jumpsupplydrop =	math.random(110,140),
6528		        },
6529		        reputation_cost_multipliers = {
6530		        	friend = 1.0,
6531		        	neutral = 3.0,
6532		        },
6533				goods = {
6534					shield = {
6535						quantity =	5,
6536						cost =		90,
6537					},
6538				},
6539				trade = {
6540					food = random(1,100) <= 21,
6541					medicine = false,
6542					luxury = true,
6543				},
6544				description = "Shield and armor components and research",
6545				general = "We research and make general and specialized components for ship shield and ship armor systems",
6546				history = "This station was named after one of the earliest researchers in shield technology, Alexander Toohie back when it was considered impractical to construct shields due to the physics involved."},
6547		},
6548		["Pop Sci Fi"] = {
6549			["Anderson"] = {
6550		        weapon_available = {
6551		        	Homing = false,
6552		        	HVLI = random(1,13)<=(9-difficulty),
6553		        	Mine = random(1,13)<=(7-difficulty),
6554		        	Nuke = random(1,13)<=(5-difficulty),
6555		        	EMP = random(1,13)<=(6-difficulty),
6556		        },
6557				services = {
6558					supplydrop =		"friend",
6559					reinforcements =	"friend",
6560					jumpsupplydrop =	"friend",
6561				},
6562		        service_cost = {
6563		        	supplydrop =		math.random(80,120),
6564		        	reinforcements =	math.random(125,175),
6565		        	jumpsupplydrop =	math.random(110,140),
6566		        },
6567		        reputation_cost_multipliers = {
6568		        	friend = 1.0,
6569		        	neutral = 2.0,
6570		        },
6571				goods = {
6572					battery = {
6573						quantity =	5,
6574						cost =		66,
6575					},
6576        			software = {
6577        				quantity =	5,
6578        				cost =		115,
6579        			},
6580        		},
6581				trade = {
6582					food = false,
6583					medicine = false,
6584					luxury = true,
6585				},
6586				description = "Battery and software engineering",
6587				general = "We provide high quality high capacity batteries and specialized software for all shipboard systems",
6588				history = "The station is named after a fictional software engineer in a late 20th century movie depicting humanity unknowingly conquered by aliens and kept docile by software generated illusion",
6589			},
6590			["Archer"] = {
6591		        weapon_available = {
6592		        	Homing = 			random(1,13)<=(8-difficulty),
6593		        	HVLI = 				true,
6594		        	Mine = 				random(1,13)<=(7-difficulty),
6595		        	Nuke = 				random(1,13)<=(5-difficulty),
6596		        	EMP = 				true
6597		        },
6598				services = {
6599					supplydrop =		"friend",
6600					reinforcements =	"friend",
6601					jumpsupplydrop =	"friend",
6602				},
6603		        service_cost = {
6604		        	supplydrop =		math.random(80,120),
6605		        	reinforcements =	math.random(125,175),
6606		        	jumpsupplydrop =	math.random(110,140),
6607		        },
6608				goods = {
6609					shield = {
6610						quantity =	5,
6611						cost =		90,
6612					},
6613				},
6614				trade = {
6615					food = false,
6616					medicine = false,
6617					luxury = true,
6618				},
6619				buy = {
6620					[randomMineral()] = math.random(40,200),
6621				},
6622				description = "Shield and Armor Research",
6623				general = "The finest shield and armor manufacturer in the quadrant",
6624				history = "We named this station for the pioneering spirit of the 22nd century Starfleet explorer, Captain Jonathan Archer",
6625			},
6626			["Barclay"] = {
6627		        weapon_available = {
6628		        	Homing =			random(1,13)<=(8-difficulty),
6629		        	HVLI =				random(1,13)<=(9-difficulty),
6630		        	Mine =				false,
6631		        	Nuke =				random(1,13)<=(5-difficulty),
6632		        	EMP =				random(1,13)<=(6-difficulty),
6633		        },
6634				services = {
6635					supplydrop =		"friend",
6636					reinforcements =	"friend",
6637					jumpsupplydrop =	"friend",
6638				},
6639		        service_cost = {
6640		        	supplydrop =		math.random(80,120),
6641		        	reinforcements =	math.random(125,175),
6642		        	jumpsupplydrop =	math.random(110,140),
6643		        },
6644				goods = {
6645					communication =	{
6646						quantity =	5,
6647						cost =		58,
6648					},
6649				},
6650				trade = {
6651					food = false,
6652					medicine = false,
6653					luxury = false,
6654				},
6655				buy = {
6656					[randomMineral()] = math.random(40,200),
6657				},
6658				description = "Communication components",
6659				general = "We provide a range of communication equipment and software for use aboard ships",
6660				history = "The station is named after Reginald Barclay who established the first transgalactic com link through the creative application of a quantum singularity. Station personnel often refer to the station as the Broccoli station",
6661			},
6662			["Calvin"] = {
6663		        weapon_available = {
6664		        	Homing =			false,
6665		        	HVLI =				random(1,13)<=(9-difficulty),
6666		        	Mine =				random(1,13)<=(7-difficulty),
6667		        	Nuke =				random(1,13)<=(5-difficulty),
6668		        	EMP =				random(1,13)<=(6-difficulty),
6669		        },
6670				services = {
6671					supplydrop =		"friend",
6672					reinforcements =	"friend",
6673					jumpsupplydrop =	"friend",
6674				},
6675		        service_cost = {
6676		        	supplydrop =		math.random(80,120),
6677		        	reinforcements =	math.random(125,175),
6678		        	jumpsupplydrop =	math.random(110,140),
6679		        },
6680				goods = {
6681					robotic = {
6682						quantity =	5,
6683						cost = 		90,
6684					},
6685				},
6686				trade = {
6687					food = random(1,100) <= 35,
6688					medicine = false,
6689					luxury = true,
6690				},
6691				buy =	{
6692					[randomComponent("robotic")] = math.random(40,200)
6693				},
6694				description = "Robotic research",
6695				general = "We research and provide robotic systems and components",
6696				history = "This station is named after Dr. Susan Calvin who pioneered robotic behavioral research and programming",
6697			},
6698			["Cavor"] = {
6699		        weapon_available = {
6700		        	Homing =			random(1,13)<=(8-difficulty),
6701		        	HVLI =				random(1,13)<=(9-difficulty),
6702		        	Mine =				random(1,13)<=(7-difficulty),
6703		        	Nuke =				random(1,13)<=(5-difficulty),
6704		        	EMP =				random(1,13)<=(6-difficulty),
6705		        },
6706				services = {
6707					supplydrop =		"friend",
6708					reinforcements =	"friend",
6709					jumpsupplydrop =	"friend",
6710				},
6711		        service_cost = {
6712		        	supplydrop =		math.random(80,120),
6713		        	reinforcements =	math.random(125,175),
6714		        	jumpsupplydrop =	math.random(110,140),
6715		        },
6716		        reputation_cost_multipliers = {
6717		        	friend = 1.0,
6718		        	neutral = 2.0,
6719		        },
6720				goods = {
6721					filament = {
6722						quantity =	5,
6723						cost =		42,
6724					},
6725				},
6726				trade = {
6727					food = false,
6728					medicine = false,
6729					luxury = false,
6730				},
6731				description = "Advanced Material components",
6732				general = "We fabricate several different kinds of materials critical to various space industries like ship building, station construction and mineral extraction",
6733				history = "We named our station after Dr. Cavor, the physicist that invented a barrier material for gravity waves - Cavorite",
6734			},
6735			["Cyrus"] = {
6736		        weapon_available = {
6737		        	Homing =			random(1,13)<=(8-difficulty),
6738		        	HVLI =				random(1,13)<=(9-difficulty),
6739		        	Mine =				random(1,13)<=(7-difficulty),
6740		        	Nuke =				random(1,13)<=(5-difficulty),
6741		        	EMP =				random(1,13)<=(6-difficulty),
6742		        },
6743				services = {
6744					supplydrop =		"friend",
6745					reinforcements =	"friend",
6746					jumpsupplydrop =	"friend",
6747				},
6748		        service_cost = {
6749		        	supplydrop =		math.random(80,120),
6750		        	reinforcements =	math.random(125,175),
6751		        	jumpsupplydrop =	math.random(110,140),
6752		        },
6753		        reputation_cost_multipliers = {
6754		        	friend = 1.0,
6755		        	neutral = 3.0,
6756		        },
6757				goods = {
6758					impulse = {
6759						quantity =	5,
6760						cost =		124,
6761					},
6762				},
6763				trade = {
6764					food = false,
6765					medicine = false,
6766					luxury = random(1,100) < 78,
6767				},
6768				description = "Impulse engine components",
6769				general = "We supply high quality impulse engines and parts for use aboard ships",
6770				history = "This station was named after the fictional engineer, Cyrus Smith created by 19th century author Jules Verne",
6771			},
6772			["Deckard"] = {
6773		        weapon_available = {
6774		        	Homing =			random(1,13)<=(8-difficulty),
6775		        	HVLI =				random(1,13)<=(9-difficulty),
6776		        	Mine =				random(1,13)<=(7-difficulty),
6777		        	Nuke =				random(1,13)<=(5-difficulty),
6778		        	EMP =				random(1,13)<=(6-difficulty),
6779		        },
6780				services = {
6781					supplydrop =		"friend",
6782					reinforcements =	"friend",
6783					jumpsupplydrop =	"friend",
6784				},
6785		        service_cost = {
6786		        	supplydrop =		math.random(80,120),
6787		        	reinforcements =	math.random(125,175),
6788		        	jumpsupplydrop =	math.random(110,140),
6789		        },
6790		        reputation_cost_multipliers = {
6791		        	friend = 1.0,
6792		        	neutral = 2.0,
6793		        },
6794				goods = {
6795					android = {
6796						quantity =	5,
6797						cost =		73,
6798					},
6799				},
6800				trade = {
6801					food = false,
6802					medicine = false,
6803					luxury = true,
6804				},
6805				description = "Android components",
6806				general = "Supplier of android components, programming and service",
6807				history = "Named for Richard Deckard who inspired many of the sophisticated safety security algorithms now required for all androids",
6808			},
6809			["Erickson"] = {
6810		        weapon_available = {
6811		        	Homing =			random(1,13)<=(8-difficulty),
6812		        	HVLI =				random(1,13)<=(9-difficulty),
6813		        	Mine =				random(1,13)<=(7-difficulty),
6814		        	Nuke =				random(1,13)<=(5-difficulty),
6815		        	EMP =				random(1,13)<=(6-difficulty),
6816		        },
6817				services = {
6818					supplydrop =		"friend",
6819					reinforcements =	"friend",
6820					jumpsupplydrop =	"friend",
6821				},
6822		        service_cost = {
6823		        	supplydrop =		math.random(80,120),
6824		        	reinforcements =	math.random(125,175),
6825		        	jumpsupplydrop =	math.random(110,140),
6826		        },
6827				goods = {
6828					transporter = {
6829						quantity =	5,
6830						cost =		63,
6831					},
6832				},
6833				trade = {
6834					food = false,
6835					medicine = false,
6836					luxury = true,
6837				},
6838				description = "Transporter components",
6839				general = "We provide transporters used aboard ships as well as the components for repair and maintenance",
6840				history = "The station is named after the early 22nd century inventor of the transporter, Dr. Emory Erickson. This station is proud to have received the endorsement of Admiral Leonard McCoy",
6841			},
6842			["Jabba"] = {
6843		        weapon_available = {
6844		        	Homing =			random(1,13)<=(8-difficulty),
6845		        	HVLI =				random(1,13)<=(9-difficulty),
6846		        	Mine =				random(1,13)<=(7-difficulty),
6847		        	Nuke =				random(1,13)<=(5-difficulty),
6848		        	EMP =				random(1,13)<=(6-difficulty),
6849		        },
6850				services = {
6851					supplydrop =		"friend",
6852					reinforcements =	"friend",
6853					jumpsupplydrop =	"friend",
6854				},
6855		        service_cost = {
6856		        	supplydrop =		math.random(80,120),
6857		        	reinforcements =	math.random(125,175),
6858		        	jumpsupplydrop =	math.random(110,140),
6859		        },
6860		        reputation_cost_multipliers = {
6861		        	friend = 1.0,
6862		        	neutral = 2.0,
6863		        },
6864				goods = {
6865					luxury = {
6866						quantity =	5,
6867						cost =		math.random(30,80),
6868					},
6869				},
6870				trade = {
6871					food = false,
6872					medicine = false,
6873					luxury = false,
6874				},
6875				description = "Commerce and gambling",
6876				general = "Come play some games and shop. House take does not exceed 4 percent",
6877				history = "",
6878			},
6879			["Komov"] = {
6880		        weapon_available = {
6881		        	Homing =			random(1,13)<=(8-difficulty),
6882		        	HVLI =				random(1,13)<=(9-difficulty),
6883		        	Mine =				true,
6884		        	Nuke =				false,
6885		        	EMP =				random(1,13)<=(6-difficulty),
6886		        },
6887				services = {
6888					supplydrop =		"friend",
6889					reinforcements =	"friend",
6890					jumpsupplydrop =	"friend",
6891				},
6892		        service_cost = {
6893		        	supplydrop =		math.random(80,120),
6894		        	reinforcements =	math.random(125,175),
6895		        	jumpsupplydrop =	math.random(110,140),
6896		        },
6897		        reputation_cost_multipliers = {
6898		        	friend = 1.0,
6899		        	neutral = 2.0,
6900		        },
6901				goods = {
6902					filament = {
6903						quantity =	5,
6904						cost =		46,
6905					},
6906				},
6907 				trade = {
6908 					food = false,
6909 					medicine = false,
6910 					luxury = false,
6911 				},
6912				description = "Xenopsychology training",
6913				general = "We provide classes and simulation to help train diverse species in how to relate to each other",
6914				history = "A continuation of the research initially conducted by Dr. Gennady Komov in the early 22nd century on Venus, supported by the application of these principles",
6915			},
6916			["Lando"] = {
6917		        weapon_available = {
6918		        	Homing =			true,
6919		        	HVLI =				true,
6920		        	Mine =				true,
6921		        	Nuke =				false,
6922		        	EMP =				false,
6923		        },
6924				weapon_cost = {
6925					Homing = math.random(2,5),
6926					HVLI = 2,
6927					Mine = math.random(2,5),
6928				},
6929				services = {
6930					supplydrop =		"friend",
6931					reinforcements =	"friend",
6932					jumpsupplydrop =	"friend",
6933				},
6934		        service_cost = {
6935		        	supplydrop =		math.random(80,120),
6936		        	reinforcements =	math.random(125,175),
6937		        	jumpsupplydrop =	math.random(110,140),
6938		        },
6939				goods = {
6940					shield = {
6941						quantity =	5,
6942						cost =		90,
6943					},
6944				},
6945				trade = {
6946					food = false,
6947					medicine = false,
6948					luxury = false,
6949				},
6950				description = "Casino and Gambling",
6951				general = "",
6952				history = "",
6953			},
6954			["Muddville"] = {
6955		        weapon_available = {
6956		        	Homing =			random(1,13)<=(8-difficulty),
6957		        	HVLI =				random(1,13)<=(9-difficulty),
6958		        	Mine =				random(1,13)<=(7-difficulty),
6959		        	Nuke =				random(1,13)<=(5-difficulty),
6960		        	EMP =				random(1,13)<=(6-difficulty),
6961		        },
6962				services = {
6963					supplydrop =		"friend",
6964					reinforcements =	"friend",
6965					jumpsupplydrop =	"friend",
6966				},
6967		        service_cost = {
6968		        	supplydrop =		math.random(80,120),
6969		        	reinforcements =	math.random(125,175),
6970		        	jumpsupplydrop =	math.random(110,140),
6971		        },
6972				goods = {
6973					luxury = {
6974						quantity =	5,
6975						cost =		60,
6976					},
6977				},
6978				trade = {
6979					food = true,
6980					medicine = true,
6981					luxury = false,
6982				},
6983				description = "Trading station",
6984				general = "Come to Muddvile for all your trade and commerce needs and desires",
6985				history = "Upon retirement, Harry Mudd started this commercial venture using his leftover inventory and extensive connections obtained while he traveled the stars as a salesman",
6986			},
6987			["Nexus-6"] = {
6988		        weapon_available = {
6989		        	Homing =			random(1,13)<=(8-difficulty),
6990		        	HVLI =				false,
6991		        	Mine =				random(1,13)<=(7-difficulty),
6992		        	Nuke =				random(1,13)<=(5-difficulty),
6993		        	EMP =				random(1,13)<=(6-difficulty),
6994		        },
6995				services = {
6996					supplydrop =		"friend",
6997					reinforcements =	"friend",
6998					jumpsupplydrop =	"friend",
6999				},
7000		        service_cost = {
7001		        	supplydrop =		math.random(80,120),
7002		        	reinforcements =	math.random(125,175),
7003		        	jumpsupplydrop =	math.random(110,140),
7004		        },
7005		        reputation_cost_multipliers = {
7006		        	friend = 1.0,
7007		        	neutral = 3.0,
7008		        },
7009				goods = {
7010					android = {
7011						quantity =	5,
7012						cost =		93,
7013					},
7014				},
7015				trade = {
7016					food = false,
7017					medicine = true,
7018					luxury = false,
7019				},
7020				buy = {
7021					[randomMineral()] = math.random(40,200),
7022					[randomComponent("android")] = math.random(40,200),
7023				},
7024				description = "Android components",
7025				general = "Androids, their parts, maintenance and recylcling",
7026				history = "We named the station after the ground breaking android model produced by the Tyrell corporation",
7027			},
7028			["O'Brien"] = {
7029		        weapon_available = {
7030		        	Homing = random(1,13)<=(8-difficulty),
7031		        	HVLI = random(1,13)<=(9-difficulty),
7032		        	Mine = random(1,13)<=(7-difficulty),
7033		        	Nuke = random(1,13)<=(5-difficulty),
7034		        	EMP = random(1,13)<=(6-difficulty),
7035		        },
7036				services = {
7037					supplydrop =		"friend",
7038					reinforcements =	"friend",
7039					jumpsupplydrop =	"friend",
7040				},
7041		        service_cost = {
7042		        	supplydrop =		math.random(80,120),
7043		        	reinforcements =	math.random(125,175),
7044		        	jumpsupplydrop =	math.random(110,140),
7045		        },
7046		        reputation_cost_multipliers = {
7047		        	friend = 1.0,
7048		        	neutral = 3.0,
7049		        },
7050				goods = {
7051					transporter = {
7052						quantity =	5,
7053						cost =		76,
7054					},
7055				},
7056				trade = {
7057					food = random(1,100) < 13,
7058					medicine = true,
7059					luxury = random(1,100) < 43,
7060				},
7061				description = "Transporter components",
7062				general = "We research and fabricate high quality transporters and transporter components for use aboard ships",
7063				history = "Miles O'Brien started this business after his experience as a transporter chief",
7064			},
7065			["Organa"] = {
7066		        weapon_available = {
7067		        	Homing =			random(1,13)<=(8-difficulty),
7068		        	HVLI =				random(1,13)<=(9-difficulty),
7069		        	Mine =				random(1,13)<=(7-difficulty),
7070		        	Nuke =				random(1,13)<=(5-difficulty),
7071		        	EMP =				random(1,13)<=(6-difficulty),
7072		        },
7073				services = {
7074					supplydrop =		"friend",
7075					reinforcements =	"friend",
7076					jumpsupplydrop =	"friend",
7077				},
7078		        service_cost = {
7079		        	supplydrop =		math.random(80,120),
7080		        	reinforcements =	math.random(125,175),
7081		        	jumpsupplydrop =	math.random(110,140),
7082		        },
7083		        reputation_cost_multipliers = {
7084		        	friend = 1.0,
7085		        	neutral = 2.0,
7086		        },
7087				goods = {
7088					luxury = {
7089						quantity =	5,
7090						cost =		95,
7091					},
7092				},
7093				trade = {
7094					food = false,
7095					medicine = false,
7096					luxury = false,
7097				},
7098				description = "Diplomatic training",
7099				general = "The premeire academy for leadership and diplomacy training in the region",
7100				history = "Established by the royal family so critical during the political upheaval era",
7101			},
7102			["Owen"] = {
7103		        weapon_available = {
7104		        	Homing =			true,
7105		        	HVLI =				false,
7106		        	Mine =				random(1,13)<=(7-difficulty),
7107		        	Nuke =				random(1,13)<=(5-difficulty),
7108		        	EMP =				random(1,13)<=(6-difficulty),
7109		        },
7110				services = {
7111					supplydrop =		"friend",
7112					reinforcements =	"friend",
7113					jumpsupplydrop =	"friend",
7114				},
7115		        service_cost = {
7116		        	supplydrop =		math.random(80,120),
7117		        	reinforcements =	math.random(125,175),
7118		        	jumpsupplydrop =	math.random(110,140),
7119		        },
7120		        reputation_cost_multipliers = {
7121		        	friend = 1.0,
7122		        	neutral = 3.0,
7123		        },
7124				goods = {
7125					lifter = {
7126						quantity =	5,
7127						cost =		61,
7128					},
7129				},
7130				trade = {
7131					food = false,
7132					medicine = false,
7133					luxury = true,
7134				},
7135				description = "Load lifters and components",
7136				general = "We provide load lifters and components for various ship systems",
7137				history = "Owens started off in the moisture vaporator business on Tattooine then branched out into load lifters based on acquisition of proprietary software and protocols. The station name recognizes the tragic loss of our founder to Imperial violence",
7138			},
7139			["Ripley"] = {
7140		        weapon_available = {
7141		        	Homing =			false,
7142		        	HVLI =				true,
7143		        	Mine =				random(1,13)<=(7-difficulty),
7144		        	Nuke =				random(1,13)<=(5-difficulty),
7145		        	EMP =				random(1,13)<=(6-difficulty),
7146		        },
7147				services = {
7148					supplydrop =		"friend",
7149					reinforcements =	"friend",
7150					jumpsupplydrop =	"friend",
7151				},
7152		        service_cost = {
7153		        	supplydrop =		math.random(80,120),
7154		        	reinforcements =	math.random(125,175),
7155		        	jumpsupplydrop =	math.random(110,140),
7156		        },
7157		        reputation_cost_multipliers = {
7158		        	friend = 1.0,
7159		        	neutral = 3.0,
7160		        },
7161				goods = {
7162					lifter = {
7163						quantity =	5,
7164						cost =		82,
7165					},
7166				},
7167				trade = {
7168					food = false,
7169					medicine = false,
7170					luxury = random(1,100) < 47,
7171				},
7172				description = "Load lifters and components",
7173				general = "We provide load lifters and components",
7174				history = "The station is named after Ellen Ripley who made creative and effective use of one of our load lifters when defending her ship",
7175			},
7176			["Skandar"] = {
7177		        weapon_available = {
7178		        	Homing =			random(1,13)<=(8-difficulty),
7179		        	HVLI =				random(1,13)<=(9-difficulty),
7180		        	Mine =				random(1,13)<=(7-difficulty),
7181		        	Nuke =				random(1,13)<=(5-difficulty),
7182		        	EMP =				random(1,13)<=(6-difficulty),
7183		        },
7184				services = {
7185					supplydrop =		"friend",
7186					reinforcements =	"friend",
7187					jumpsupplydrop =	"friend",
7188				},
7189		        service_cost = {
7190		        	supplydrop =		math.random(80,120),
7191		        	reinforcements =	math.random(125,175),
7192		        	jumpsupplydrop =	math.random(110,140),
7193		        },
7194		        reputation_cost_multipliers = {
7195		        	friend = 1.0,
7196		        	neutral = 2.0,
7197		        },
7198				goods = {
7199					luxury = {
7200						quantity =	5,
7201						cost =		math.random(30,80),
7202					},
7203				},
7204				trade = {
7205					food = false,
7206					medicine = false,
7207					luxury = false,
7208				},
7209				description = "Routine maintenance and entertainment",
7210				general = "Stop by for repairs. Take in one of our juggling shows featuring the four-armed Skandars",
7211				history = "The nomadic Skandars have set up at this station to practice their entertainment and maintenance skills as well as build a community where Skandars can relax",
7212			},
7213			["Soong"] = {
7214		        weapon_available = {
7215		        	Homing = random(1,13)<=(8-difficulty),
7216		        	HVLI = random(1,13)<=(9-difficulty),
7217		        	Mine = random(1,13)<=(7-difficulty),
7218		        	Nuke = random(1,13)<=(5-difficulty),
7219		        	EMP = random(1,13)<=(6-difficulty),
7220		        },
7221				services = {
7222					supplydrop =		"friend",
7223					reinforcements =	"friend",
7224					jumpsupplydrop =	"friend",
7225				},
7226		        service_cost = {
7227		        	supplydrop =		math.random(80,120),
7228		        	reinforcements =	math.random(125,175),
7229		        	jumpsupplydrop =	math.random(110,140),
7230		        },
7231		        reputation_cost_multipliers = {
7232		        	friend = 1.0,
7233		        	neutral = 3.0,
7234		        },
7235				goods = {
7236					android = {
7237						quantity =	5,
7238						cost = 73,
7239					},
7240				},
7241				trade = {
7242					food = false,
7243					medicine = false,
7244					luxury = true,
7245				},
7246				description = "Android components",
7247				general = "We create androids and android components",
7248				history = "The station is named after Dr. Noonian Soong, the famous android researcher and builder",
7249			},
7250			["Starnet"] = {
7251		        weapon_available = {
7252		        	Homing =			random(1,13)<=(8-difficulty),
7253		        	HVLI =				random(1,13)<=(9-difficulty),
7254		        	Mine =				random(1,13)<=(7-difficulty),
7255		        	Nuke =				random(1,13)<=(5-difficulty),
7256		        	EMP =				random(1,13)<=(6-difficulty),
7257		        },
7258				services = {
7259					supplydrop =		"friend",
7260					reinforcements =	"friend",
7261					jumpsupplydrop =	"friend",
7262				},
7263		        service_cost = {
7264		        	supplydrop =		math.random(80,120),
7265		        	reinforcements =	math.random(125,175),
7266		        	jumpsupplydrop =	math.random(110,140),
7267		        },
7268		        reputation_cost_multipliers = {
7269		        	friend = 1.0,
7270		        	neutral = 3.0,
7271		        },
7272		        goods = {
7273		        	software =	{
7274		        		quantity =	5,
7275		        		cost =		140,
7276		        	},
7277		        },
7278				trade = {
7279					food = false,
7280					medicine = false,
7281					luxury = false,
7282				},
7283				description = "Automated weapons systems",
7284				general = "We research and create automated weapons systems to improve ship combat capability",
7285				history = "Lost the history memory bank. Recovery efforts only brought back the phrase, 'I'll be back'",
7286			},
7287			["Tiberius"] = {
7288		        weapon_available = {
7289		        	Homing =			random(1,13)<=(8-difficulty),
7290		        	HVLI =				random(1,13)<=(9-difficulty),
7291		        	Mine =				random(1,13)<=(7-difficulty),
7292		        	Nuke =				random(1,13)<=(5-difficulty),
7293		        	EMP =				random(1,13)<=(6-difficulty),
7294		        },
7295				services = {
7296					supplydrop =		"friend",
7297					reinforcements =	"friend",
7298					jumpsupplydrop =	"friend",
7299				},
7300		        service_cost = {
7301		        	supplydrop =		math.random(80,120),
7302		        	reinforcements =	math.random(125,175),
7303		        	jumpsupplydrop =	math.random(110,140),
7304		        },
7305				goods = {
7306					food = {
7307						quantity =	5,
7308						cost =		1,
7309					},
7310				},
7311				trade = {
7312					food = false,
7313					medicine = false,
7314					luxury = false,
7315				},
7316				description = "Logistics coordination",
7317				general = "We support the stations and ships in the area with planning and communication services",
7318				history = "We recognize the influence of Starfleet Captain James Tiberius Kirk in the 23rd century in our station name",
7319			},
7320			["Tokra"] = {
7321		        weapon_available = {
7322		        	Homing =			random(1,13)<=(8-difficulty),
7323		        	HVLI =				random(1,13)<=(9-difficulty),
7324		        	Mine =				random(1,13)<=(7-difficulty),
7325		        	Nuke =				random(1,13)<=(5-difficulty),
7326		        	EMP =				random(1,13)<=(6-difficulty),
7327		        },
7328				services = {
7329					supplydrop =		"friend",
7330					reinforcements =	"friend",
7331					jumpsupplydrop =	"friend",
7332				},
7333		        service_cost = {
7334		        	supplydrop =		math.random(80,120),
7335		        	reinforcements =	math.random(125,175),
7336		        	jumpsupplydrop =	math.random(110,140),
7337		        },
7338		        reputation_cost_multipliers = {
7339		        	friend = 1.0,
7340		        	neutral = 3.0,
7341		        },
7342				goods = {
7343					filament = {
7344						quantity =	5,
7345						cost =		42,
7346					},
7347				},
7348				trade = {
7349					food = false,
7350					medicine = false,
7351					luxury = false,
7352				},
7353				description = "Advanced material components",
7354				general = "We create multiple types of advanced material components. Our most popular products are our filaments",
7355				history = "We learned several of our critical industrial processes from the Tokra race, so we honor our fortune by naming the station after them",
7356			},
7357			["Utopia Planitia"] = {
7358		        weapon_available = 	{
7359		        	Homing = 			random(1,13)<=(8-difficulty),
7360		        	HVLI =				random(1,13)<=(9-difficulty),
7361		        	Mine =				random(1,13)<=(7-difficulty),
7362		        	Nuke =				true,
7363		        	EMP =				random(1,13)<=(6-difficulty),
7364		        },
7365				services = {
7366					supplydrop =		"friend",
7367					reinforcements =	"friend",
7368					jumpsupplydrop =	"friend",
7369				},
7370		        service_cost = {
7371		        	supplydrop =		math.random(80,120),
7372		        	reinforcements =	math.random(125,175),
7373		        	jumpsupplydrop =	math.random(110,140),
7374		        },
7375		        goods = {
7376		        	warp =	{
7377		        		quantity =	5,
7378		        		cost =		167,
7379		        	},
7380		        },
7381		        trade = {
7382		        	food = false,
7383		        	medicine = false,
7384		        	luxury = false
7385		        },
7386				description = "Ship building and maintenance facility",
7387				general = "We work on all aspects of naval ship building and maintenance. Many of the naval models are researched, designed and built right here on this station. Our design goals seek to make the space faring experience as simple as possible given the tremendous capabilities of the modern naval vessel",
7388				history = ""
7389			},
7390			["Vaiken"] = {
7391		        weapon_available = {
7392		        	Homing =			random(1,13)<=(8-difficulty),
7393		        	HVLI =				random(1,13)<=(9-difficulty),
7394		        	Mine =				random(1,13)<=(7-difficulty),
7395		        	Nuke =				random(1,13)<=(5-difficulty),
7396		        	EMP =				random(1,13)<=(6-difficulty),
7397		        },
7398				services = {
7399					supplydrop =		"friend",
7400					reinforcements =	"friend",
7401					jumpsupplydrop =	"friend",
7402				},
7403		        service_cost = {
7404		        	supplydrop =		math.random(80,120),
7405		        	reinforcements =	math.random(125,175),
7406		        	jumpsupplydrop =	math.random(110,140),
7407		        },
7408				goods = {
7409					food = {
7410						quantity =	10,
7411						cost = 		1,
7412					},
7413        			medicine = {
7414        				quantity =	5,
7415        				cost = 		5,
7416        			},
7417        			impulse = {
7418        				quantity =	5,
7419        				cost = 		math.random(65,97),
7420        			},
7421        		},
7422				trade = {
7423					food = false,
7424					medicine = false,
7425					luxury = false,
7426				},
7427				description = "Ship building and maintenance facility",
7428				general = "",
7429				history = "",
7430			},
7431			["Zefram"] = {
7432		        weapon_available = {
7433		        	Homing =			random(1,13)<=(8-difficulty),
7434		        	HVLI =				random(1,13)<=(9-difficulty),
7435		        	Mine =				random(1,13)<=(7-difficulty),
7436		        	Nuke =				random(1,13)<=(5-difficulty),
7437		        	EMP =				random(1,13)<=(6-difficulty),
7438		        },
7439				services = {
7440					supplydrop =		"friend",
7441					reinforcements =	"friend",
7442					jumpsupplydrop =	"friend",
7443				},
7444		        service_cost = {
7445		        	supplydrop =		math.random(80,120),
7446		        	reinforcements =	math.random(125,175),
7447		        	jumpsupplydrop =	math.random(110,140),
7448		        },
7449		        reputation_cost_multipliers = {
7450		        	friend = 1.0,
7451		        	neutral = 3.0,
7452		        },
7453		        goods = {
7454		        	warp =	{
7455		        		quantity =	5,
7456		        		cost =		140,
7457		        	},
7458		        },
7459		        trade = {
7460		        	food = false,
7461		        	medicine = false,
7462		        	luxury = true,
7463		        },
7464				description = "Warp engine components",
7465				general = "We specialize in the esoteric components necessary to make warp drives function properly",
7466				history = "Zefram Cochrane constructed the first warp drive in human history. We named our station after him because of the specialized warp systems work we do",
7467			},
7468		},
7469		["Spec Sci Fi"] = {
7470			["Alcaleica"] =	{
7471		        weapon_available = {
7472		        	Homing =			random(1,13)<=(8-difficulty),
7473		        	HVLI =				random(1,13)<=(9-difficulty),
7474		        	Mine =				random(1,13)<=(7-difficulty),
7475		        	Nuke =				random(1,13)<=(5-difficulty),
7476		        	EMP =				random(1,13)<=(6-difficulty),
7477		        },
7478				services = {
7479					supplydrop =		"friend",
7480					reinforcements =	"friend",
7481					jumpsupplydrop =	"friend",
7482				},
7483		        service_cost = {
7484		        	supplydrop =		math.random(80,120),
7485		        	reinforcements =	math.random(125,175),
7486		        	jumpsupplydrop =	math.random(110,140),
7487		        },
7488				goods = {
7489					optic = {
7490						quantity =	5,
7491						cost =		66,
7492					},
7493				},
7494				trade = {
7495					food = false,
7496					medicine = false,
7497					luxury = false,
7498				},
7499				buy = {
7500					[randomMineral()] = math.random(40,200),
7501				},
7502				description = "Optical Components",
7503				general = "We make and supply optic components for various station and ship systems",
7504				history = "This station continues the businesses from Earth based on the merging of several companies including Leica from Switzerland, the lens manufacturer and the Japanese advanced low carbon (ALCA) electronic and optic research and development company",
7505			},
7506			["Bethesda"] = {
7507		        weapon_available = {
7508		        	Homing =			random(1,13)<=(8-difficulty),
7509		        	HVLI =				random(1,13)<=(9-difficulty),
7510		        	Mine =				random(1,13)<=(7-difficulty),
7511		        	Nuke =				random(1,13)<=(5-difficulty),
7512		        	EMP =				random(1,13)<=(6-difficulty),
7513		        },
7514				services = {
7515					supplydrop =		"friend",
7516					reinforcements =	"friend",
7517					jumpsupplydrop =	"friend",
7518				},
7519		        service_cost = {
7520		        	supplydrop =		math.random(80,120),
7521		        	reinforcements =	math.random(125,175),
7522		        	jumpsupplydrop =	math.random(110,140),
7523		        },
7524				reputation_cost_multipliers = {
7525					friend = 1.0,
7526					neutral = 3.0,
7527				},
7528				goods = {
7529					autodoc = {
7530						quantity =	5,
7531						cost =		36,
7532					},
7533					medicine = {
7534						quantity =	5,
7535						cost = 		5,
7536					},
7537					food = {
7538						quantity =	math.random(5,10),
7539						cost = 		1,
7540					},
7541				},
7542				trade = {
7543					food = false,
7544					medicine = false,
7545					luxury = false,
7546				},
7547				description = "Medical research",
7548				general = "We research and treat exotic medical conditions",
7549				history = "The station is named after the United States national medical research center based in Bethesda, Maryland on earth which was established in the mid 20th century",
7550			},
7551			["Deer"] = {
7552		        weapon_available = {
7553		        	Homing =			random(1,13)<=(8-difficulty),
7554		        	HVLI =				random(1,13)<=(9-difficulty),
7555		        	Mine =				random(1,13)<=(7-difficulty),
7556		        	Nuke =				random(1,13)<=(5-difficulty),
7557		        	EMP =				random(1,13)<=(6-difficulty),
7558		        },
7559				services = {
7560					supplydrop =		"friend",
7561					reinforcements =	"friend",
7562					jumpsupplydrop =	"friend",
7563				},
7564		        service_cost = {
7565		        	supplydrop =		math.random(80,120),
7566		        	reinforcements =	math.random(125,175),
7567		        	jumpsupplydrop =	math.random(110,140),
7568		        },
7569				goods = {
7570					tractor = {
7571						quantity =	5,
7572						cost =		90,
7573					},
7574        			repulsor = {
7575        				quantity =	5,
7576        				cost =		math.random(85,95),
7577        			},
7578        		},
7579				trade = {
7580					food = false,
7581					medicine = false,
7582					luxury = true,
7583				},
7584				description = "Repulsor and Tractor Beam Components",
7585				general = "We can meet all your pushing and pulling needs with specialized equipment custom made",
7586				history = "The station name comes from a short story by the 20th century author Clifford D. Simak as well as from the 19th century developer John Deere who inspired a company that makes the Earth bound equivalents of our products",
7587			},
7588			["Evondos"] = {
7589		        weapon_available = {
7590		        	Homing =			random(1,13)<=(8-difficulty),
7591		        	HVLI =				true,
7592		        	Mine =				random(1,13)<=(7-difficulty),
7593		        	Nuke =				random(1,13)<=(5-difficulty),
7594		        	EMP =				random(1,13)<=(6-difficulty),
7595		        },
7596				services = {
7597					supplydrop =		"friend",
7598					reinforcements =	"friend",
7599					jumpsupplydrop =	"friend",
7600				},
7601		        service_cost = {
7602		        	supplydrop =		math.random(80,120),
7603		        	reinforcements =	math.random(125,175),
7604		        	jumpsupplydrop =	math.random(110,140),
7605		        },
7606				reputation_cost_multipliers = {
7607					friend = 1.0,
7608					neutral = 3.0,
7609				},
7610				goods = {
7611					autodoc = {
7612						quantity =	5,
7613						cost =		56,
7614					},
7615				},
7616				trade = {
7617					food = false,
7618					medicine = false,
7619					luxury = random(1,100) < 41,
7620				},
7621				description = "Autodoc components",
7622				general = "We provide components for automated medical machinery",
7623				history = "The station is the evolution of the company that started automated pharmaceutical dispensing in the early 21st century on Earth in Finland",
7624			},
7625			["Feynman"] = {
7626		        weapon_available = 	{
7627		        	Homing =			random(1,13)<=(8-difficulty),
7628		        	HVLI =				random(1,13)<=(9-difficulty),
7629		        	Mine =				true,
7630		        	Nuke =				random(1,13)<=(5-difficulty),
7631		        	EMP =				random(1,13)<=(6-difficulty),
7632		        },
7633				services = {
7634					supplydrop =		"friend",
7635					reinforcements =	"friend",
7636					jumpsupplydrop =	"friend",
7637				},
7638		        service_cost = {
7639		        	supplydrop =		math.random(80,120),
7640		        	reinforcements =	math.random(125,175),
7641		        	jumpsupplydrop =	math.random(110,140),
7642		        },
7643		        reputation_cost_multipliers = {
7644		        	friend = 1.0,
7645		        	neutral = 3.0,
7646		        },
7647        		goods = {
7648        			software = {
7649        				quantity = 	5,
7650        				cost =		115,
7651        			},
7652        			nanites = {
7653        				quantity =	5,
7654        				cost =		79,
7655        			},
7656        		},
7657		        trade = {
7658		        	food = false,
7659		        	medicine = false,
7660		        	luxury = true,
7661		        },
7662				description = "Nanotechnology research",
7663				general = "We provide nanites and software for a variety of ship-board systems",
7664				history = "This station's name recognizes one of the first scientific researchers into nanotechnology, physicist Richard Feynman",
7665			},
7666			["Mayo"] = {
7667		        weapon_available = {
7668		        	Homing =			random(1,13)<=(8-difficulty),
7669		        	HVLI =				random(1,13)<=(9-difficulty),
7670		        	Mine =				random(1,13)<=(7-difficulty),
7671		        	Nuke =				random(1,13)<=(5-difficulty),
7672		        	EMP =				random(1,13)<=(6-difficulty),
7673		        },
7674				services = {
7675					supplydrop =		"friend",
7676					reinforcements =	"friend",
7677					jumpsupplydrop =	"friend",
7678				},
7679		        service_cost = {
7680		        	supplydrop =		math.random(80,120),
7681		        	reinforcements =	math.random(125,175),
7682		        	jumpsupplydrop =	math.random(110,140),
7683		        },
7684				goods = {
7685					autodoc = {
7686						quantity =	5,
7687						cost =		128,
7688					},
7689        			food = {
7690        				quantity =	5,
7691        				cost =		1,
7692        			},
7693        			medicine = {
7694        				quantity =	5,
7695        				cost =		5,
7696        			},
7697        		},
7698				trade = {
7699					food = false,
7700					medicine = false,
7701					luxury = false,
7702				},
7703				description = "Medical Research",
7704				general = "We research exotic diseases and other human medical conditions",
7705				history = "We continue the medical work started by William Worrall Mayo in the late 19th century on Earth",
7706			},
7707			["Olympus"] = {
7708		        weapon_available = {
7709		        	Homing =			random(1,13)<=(8-difficulty),
7710		        	HVLI =				random(1,13)<=(9-difficulty),
7711		        	Mine =				random(1,13)<=(7-difficulty),
7712		        	Nuke =				random(1,13)<=(5-difficulty),
7713		        	EMP =				random(1,13)<=(6-difficulty),
7714		        },
7715				services = {
7716					supplydrop =		"friend",
7717					reinforcements =	"friend",
7718					jumpsupplydrop =	"friend",
7719				},
7720		        service_cost = {
7721		        	supplydrop =		math.random(80,120),
7722		        	reinforcements =	math.random(125,175),
7723		        	jumpsupplydrop =	math.random(110,140),
7724		        },
7725		        reputation_cost_multipliers = {
7726		        	friend = 1.0,
7727		        	neutral = 3.0,
7728		        },
7729				goods = {
7730					optic =	{
7731						quantity =	5,
7732						cost =		66,
7733					},
7734				},
7735				trade = {
7736					food = false,
7737					medicine = false,
7738					luxury = false,
7739				},
7740				description = "Optical components",
7741				general = "We fabricate optical lenses and related equipment as well as fiber optic cabling and components",
7742				history = "This station grew out of the Olympus company based on earth in the early 21st century. It merged with Infinera, then bought several software comapnies before branching out into space based industry",
7743			},
7744			["Panduit"] = {
7745		        weapon_available = {
7746		        	Homing =			random(1,13)<=(8-difficulty),
7747		        	HVLI =				random(1,13)<=(9-difficulty),
7748		        	Mine =				random(1,13)<=(7-difficulty),
7749		        	Nuke =				random(1,13)<=(5-difficulty),
7750		        	EMP =				random(1,13)<=(6-difficulty),
7751		        },
7752				services = {
7753					supplydrop =		"friend",
7754					reinforcements =	"friend",
7755					jumpsupplydrop =	"friend",
7756				},
7757		        service_cost = {
7758		        	supplydrop =		math.random(80,120),
7759		        	reinforcements =	math.random(125,175),
7760		        	jumpsupplydrop =	math.random(110,140),
7761		        },
7762		        reputation_cost_multipliers = {
7763		        	friend = 1.0,
7764		        	neutral = 3.0,
7765		        },
7766				goods = {
7767					optic =	{
7768						quantity =	5,
7769						cost =		79,
7770					},
7771				},
7772				trade = {
7773					food = false,
7774					medicine = false,
7775					luxury = true,
7776				},
7777				description = "Optic components",
7778				general = "We provide optic components for various ship systems",
7779				history = "This station is an outgrowth of the Panduit corporation started in the mid 20th century on Earth in the United States",
7780			},
7781			["Shree"] = {
7782		        weapon_available = {
7783		        	Homing =			random(1,13)<=(8-difficulty),
7784		        	HVLI =				random(1,13)<=(9-difficulty),
7785		        	Mine =				random(1,13)<=(7-difficulty),
7786		        	Nuke =				random(1,13)<=(5-difficulty),
7787		        	EMP =				random(1,13)<=(6-difficulty),
7788		        },
7789				services = {
7790					supplydrop =		"friend",
7791					reinforcements =	"friend",
7792					jumpsupplydrop =	"friend",
7793				},
7794		        service_cost = {
7795		        	supplydrop =		math.random(80,120),
7796		        	reinforcements =	math.random(125,175),
7797		        	jumpsupplydrop =	math.random(110,140),
7798		        },
7799		        reputation_cost_multipliers = {
7800		        	friend = 1.0,
7801		        	neutral = 3.0,
7802		        },
7803				goods = {
7804					tractor = {
7805						quantity =	5,
7806						cost =		90,
7807					},
7808        			repulsor = {
7809        				quantity =	5,
7810        				cost =		math.random(85,95),
7811        			},
7812        		},
7813				trade = {
7814					food = false,
7815					medicine = false,
7816					luxury = true,
7817				},
7818				description = "Repulsor and tractor beam components",
7819				general = "We make ship systems designed to push or pull other objects around in space",
7820				history = "Our station is named Shree after one of many tugboat manufacturers in the early 21st century on Earth in India. Tugboats serve a similar purpose for ocean-going vessels on earth as tractor and repulsor beams serve for space-going vessels today",
7821			},
7822			["Vactel"] = {
7823		        weapon_available = {
7824		        	Homing =			random(1,13)<=(8-difficulty),
7825		        	HVLI =				random(1,13)<=(9-difficulty),
7826		        	Mine =				random(1,13)<=(7-difficulty),
7827		        	Nuke =				random(1,13)<=(5-difficulty),
7828		        	EMP =				random(1,13)<=(6-difficulty),
7829		        },
7830				services = {
7831					supplydrop =		"friend",
7832					reinforcements =	"friend",
7833					jumpsupplydrop =	"friend",
7834				},
7835		        service_cost = {
7836		        	supplydrop =		math.random(80,120),
7837		        	reinforcements =	math.random(125,175),
7838		        	jumpsupplydrop =	math.random(110,140),
7839		        },
7840				goods = {
7841					circuit = {
7842						quantity =	5,
7843						cost =		50,
7844					},
7845				},
7846				trade = {
7847					food = false,
7848					medicine = false,
7849					luxury = false,
7850				},
7851				description = "Shielded Circuitry Fabrication",
7852				general = "We specialize in circuitry shielded from external hacking suitable for ship systems",
7853				history = "We started as an expansion from the lunar based chip manufacturer of Earth legacy Intel electronic chips",
7854			},
7855			["Veloquan"] = {
7856		        weapon_available = {
7857		        	Homing = random(1,13)<=(8-difficulty),
7858		        	HVLI = random(1,13)<=(9-difficulty),
7859		        	Mine = random(1,13)<=(7-difficulty),
7860		        	Nuke = random(1,13)<=(5-difficulty),
7861		        	EMP = random(1,13)<=(6-difficulty),
7862		        },
7863				services = {
7864					supplydrop =		"friend",
7865					reinforcements =	"friend",
7866					jumpsupplydrop =	"friend",
7867				},
7868		        service_cost = {
7869		        	supplydrop =		math.random(80,120),
7870		        	reinforcements =	math.random(125,175),
7871		        	jumpsupplydrop =	math.random(110,140),
7872		        },
7873		        reputation_cost_multipliers = {
7874		        	friend = 1.0,
7875		        	neutral = 3.0,
7876		        },
7877				goods = {
7878					sensor = {
7879						quantity =	5,
7880						cost =		68,
7881					},
7882				},
7883				trade = {
7884					food = false,
7885					medicine = false,
7886					luxury = false,
7887				},
7888				description = "Sensor components",
7889				general = "We research and construct components for the most powerful and accurate sensors used aboard ships along with the software to make them easy to use",
7890				history = "The Veloquan company has its roots in the manufacturing of LIDAR sensors in the early 21st century on Earth in the United States for autonomous ground-based vehicles. They expanded research and manufacturing operations to include various sensors for space vehicles. Veloquan was the result of numerous mergers and acquisitions of several companies including Velodyne and Quanergy",
7891			},
7892			["Tandon"] = {
7893		        weapon_available = {
7894		        	Homing =			random(1,13)<=(8-difficulty),
7895		        	HVLI =				random(1,13)<=(9-difficulty),
7896		        	Mine =				random(1,13)<=(7-difficulty),
7897		        	Nuke =				random(1,13)<=(5-difficulty),
7898		        	EMP =				random(1,13)<=(6-difficulty),
7899		        },
7900				services = {
7901					supplydrop =		"friend",
7902					reinforcements =	"friend",
7903					jumpsupplydrop =	"friend",
7904				},
7905		        service_cost = {
7906		        	supplydrop =		math.random(80,120),
7907		        	reinforcements =	math.random(125,175),
7908		        	jumpsupplydrop =	math.random(110,140),
7909		        },
7910		        reputation_cost_multipliers = {
7911		        	friend = 1.0,
7912		        	neutral = 3.0,
7913		        },
7914				goods = {},
7915				trade = {
7916					food = false,
7917					medicine = false,
7918					luxury = false,
7919				},
7920				description = "Biotechnology research",
7921				general = "Merging the organic and inorganic through research",
7922				history = "Continued from the Tandon school of engineering started on Earth in the early 21st century",
7923			},
7924		},
7925		["Generic"] = {
7926			["California"] = {
7927		        weapon_available = {
7928		        	Homing =			random(1,13)<=(8-difficulty),
7929		        	HVLI =				random(1,13)<=(9-difficulty),
7930		        	Mine =				random(1,13)<=(7-difficulty),
7931		        	Nuke =				random(1,13)<=(5-difficulty),
7932		        	EMP =				random(1,13)<=(6-difficulty),
7933		        },
7934				services = {
7935					supplydrop =		"friend",
7936					reinforcements =	"friend",
7937					jumpsupplydrop =	"friend",
7938				},
7939		        service_cost = {
7940		        	supplydrop =		math.random(80,120),
7941		        	reinforcements =	math.random(125,175),
7942		        	jumpsupplydrop =	math.random(110,140),
7943		        },
7944				goods = {
7945					gold = {
7946						quantity =	5,
7947						cost =		90,
7948					},
7949					dilithium = {
7950						quantity =	2,
7951						cost = 		25,
7952					},
7953				},
7954				trade = {
7955					food = false,
7956					medicine = false,
7957					luxury = false,
7958				},
7959				description = "Mining station",
7960				general = "",
7961				history = "",
7962			},
7963			["Impala"] = {
7964		        weapon_available = {
7965		        	Homing =			random(1,13)<=(8-difficulty),
7966		        	HVLI =				random(1,13)<=(9-difficulty),
7967		        	Mine =				random(1,13)<=(7-difficulty),
7968		        	Nuke =				random(1,13)<=(5-difficulty),
7969		        	EMP =				random(1,13)<=(6-difficulty),
7970		        },
7971				services = {
7972					supplydrop =		"friend",
7973					reinforcements =	"friend",
7974					jumpsupplydrop =	"friend",
7975				},
7976		        service_cost = {
7977		        	supplydrop =		math.random(80,120),
7978		        	reinforcements =	math.random(125,175),
7979		        	jumpsupplydrop =	math.random(110,140),
7980		        },
7981		        reputation_cost_multipliers = {
7982		        	friend = 1.0,
7983		        	neutral = 3.0,
7984		        },
7985				goods = {
7986					luxury = {
7987						quantity =	5,
7988						cost =		70,
7989					},
7990				},
7991				trade = {
7992					food = true,
7993					medicine = false,
7994					luxury = true,
7995				},
7996				buy = {
7997					[randomComponent()] = math.random(40,200),
7998				},
7999				description = "Mining",
8000				general = "We mine nearby asteroids for precious minerals",
8001				history = "",
8002			},
8003			["Krak"] = {
8004		        weapon_available = {
8005		        	Homing =			random(1,13)<=(8-difficulty),
8006		        	HVLI =				true,
8007		        	Mine =				random(1,13)<=(7-difficulty),
8008		        	Nuke =				random(1,13)<=(5-difficulty),
8009		        	EMP =				random(1,13)<=(6-difficulty),
8010		        },
8011				services = {
8012					supplydrop =		"friend",
8013					reinforcements =	"friend",
8014					jumpsupplydrop =	"friend",
8015				},
8016		        service_cost = {
8017		        	supplydrop =		math.random(80,120),
8018		        	reinforcements =	math.random(125,175),
8019		        	jumpsupplydrop =	math.random(110,140),
8020		        },
8021		        reputation_cost_multipliers = {
8022		        	friend = 1.0,
8023		        	neutral = 3.0,
8024		        },
8025				goods = {
8026					nickel = {
8027						quantity =	5,
8028						cost =		20,
8029					},
8030				},
8031				trade = {
8032					food = random(1,100) < 50,
8033					medicine = true,
8034					luxury = random(1,100) < 50,
8035				},
8036				buy = {
8037					[randomComponent()] = math.random(40,200),
8038				},
8039				description = "Mining station",
8040				general = "",
8041				history = "",
8042			},
8043			["Krik"] = {
8044		        weapon_available = {
8045		        	Homing =			random(1,13)<=(8-difficulty),
8046		        	HVLI =				random(1,13)<=(9-difficulty),
8047		        	Mine =				random(1,13)<=(7-difficulty),
8048		        	Nuke =				random(1,13)<=(5-difficulty),
8049		        	EMP =				random(1,13)<=(6-difficulty),
8050		        },
8051				services = {
8052					supplydrop =		"friend",
8053					reinforcements =	"friend",
8054					jumpsupplydrop =	"friend",
8055				},
8056		        service_cost = {
8057		        	supplydrop =		math.random(80,120),
8058		        	reinforcements =	math.random(125,175),
8059		        	jumpsupplydrop =	math.random(110,140),
8060		        },
8061		        reputation_cost_multipliers = {
8062		        	friend = 1.0,
8063		        	neutral = 3.0,
8064		        },
8065				goods = {
8066					nickel = {
8067						quantity =	5,
8068						cost =		20,
8069					},
8070				},
8071				trade = {
8072					food = true,
8073					medicine = true,
8074					luxury = random(1,100) < 50,
8075				},
8076				description = "Mining station",
8077				general = "",
8078				history = "",
8079			},
8080			["Kruk"] = {
8081		        weapon_available = {
8082		        	Homing =			random(1,13)<=(8-difficulty),
8083		        	HVLI =				random(1,13)<=(9-difficulty),
8084		        	Mine =				random(1,13)<=(7-difficulty),
8085		        	Nuke =				random(1,13)<=(5-difficulty),
8086		        	EMP =				random(1,13)<=(6-difficulty),
8087		        },
8088				services = {
8089					supplydrop =		"friend",
8090					reinforcements =	"friend",
8091					jumpsupplydrop =	"friend",
8092				},
8093		        service_cost = {
8094		        	supplydrop =		math.random(80,120),
8095		        	reinforcements =	math.random(125,175),
8096		        	jumpsupplydrop =	math.random(110,140),
8097		        },
8098		        reputation_cost_multipliers = {
8099		        	friend = 1.0,
8100		        	neutral = 3.0,
8101		        },
8102				goods = {
8103					nickel = {
8104						quantity =	5,
8105						cost =		20,
8106					},
8107				},
8108				trade = {
8109					food = random(1,100) < 50,
8110					medicine = random(1,100) < 50,
8111					luxury = true },
8112				buy = {
8113					[randomComponent()] = math.random(40,200),
8114				},
8115				description = "Mining station",
8116				general = "",
8117				history = "",
8118			},
8119			["Maverick"] = {
8120		        weapon_available = {
8121		        	Homing =			random(1,13)<=(8-difficulty),
8122		        	HVLI =				random(1,13)<=(9-difficulty),
8123		        	Mine =				random(1,13)<=(7-difficulty),
8124		        	Nuke =				random(1,13)<=(5-difficulty),
8125		        	EMP =				random(1,13)<=(6-difficulty),
8126		        },
8127				services = {
8128					supplydrop =		"friend",
8129					reinforcements =	"friend",
8130					jumpsupplydrop =	"friend",
8131				},
8132		        service_cost = {
8133		        	supplydrop =		math.random(80,120),
8134		        	reinforcements =	math.random(125,175),
8135		        	jumpsupplydrop =	math.random(110,140),
8136		        },
8137				goods = {
8138					luxury = {
8139						quantity =	5,
8140						cost =		math.random(30,80),
8141					},
8142				},
8143				trade = {
8144					food = false,
8145					medicine = false,
8146					luxury = false,
8147				},
8148				description = "Gambling and resupply",
8149				general = "Relax and meet some interesting players",
8150				history = "",
8151			},
8152			["Nefatha"] = {
8153		        weapon_available = {
8154		        	Homing =			random(1,13)<=(8-difficulty),
8155		        	HVLI =				random(1,13)<=(9-difficulty),
8156		        	Mine =				random(1,13)<=(7-difficulty),
8157		        	Nuke =				random(1,13)<=(5-difficulty),
8158		        	EMP =				random(1,13)<=(6-difficulty),
8159		        },
8160				services = {
8161					supplydrop =		"friend",
8162					reinforcements =	"friend",
8163					jumpsupplydrop =	"friend",
8164				},
8165		        service_cost = {
8166		        	supplydrop =		math.random(80,120),
8167		        	reinforcements =	math.random(125,175),
8168		        	jumpsupplydrop =	math.random(110,140),
8169		        },
8170		        reputation_cost_multipliers = {
8171		        	friend = 1.0,
8172		        	neutral = 2.0,
8173		        },
8174				goods = {
8175					luxury = {
8176						quantity =	5,
8177						cost =		math.random(30,80),
8178					},
8179				},
8180				trade = {
8181					food = false,
8182					medicine = false,
8183					luxury = false,
8184				},
8185				description = "Commerce and recreation",
8186				general = "",
8187				history = "",
8188			},
8189			["Okun"] = {
8190		        weapon_available = {
8191		        	Homing =			random(1,13)<=(8-difficulty),
8192		        	HVLI =				random(1,13)<=(9-difficulty),
8193		        	Mine =				false,
8194		        	Nuke =				random(1,13)<=(5-difficulty),
8195		        	EMP =				random(1,13)<=(6-difficulty),
8196		        },
8197				services = {
8198					supplydrop =		"friend",
8199					reinforcements =	"friend",
8200					jumpsupplydrop =	"friend",
8201				},
8202		        service_cost = {
8203		        	supplydrop =		math.random(80,120),
8204		        	reinforcements =	math.random(125,175),
8205		        	jumpsupplydrop =	math.random(110,140),
8206		        },
8207		        reputation_cost_multipliers = {
8208		        	friend = 1.0,
8209		        	neutral = 3.0,
8210		        },
8211				goods = {},
8212				trade = {
8213					food = false,
8214					medicine = false,
8215					luxury = false,
8216				},
8217				description = "Xenopsychology research",
8218				general = "",
8219				history = "",
8220			},
8221			["Outpost-15"] = {
8222		        weapon_available = {
8223		        	Homing =			random(1,13)<=(8-difficulty),
8224		        	HVLI =				random(1,13)<=(9-difficulty),
8225		        	Mine =				random(1,13)<=(7-difficulty),
8226		        	Nuke =				random(1,13)<=(5-difficulty),
8227		        	EMP =				random(1,13)<=(6-difficulty),
8228		        },
8229				services = {
8230					supplydrop =		"friend",
8231					reinforcements =	"friend",
8232					jumpsupplydrop =	"friend",
8233				},
8234		        service_cost = {
8235		        	supplydrop =		math.random(80,120),
8236		        	reinforcements =	math.random(125,175),
8237		        	jumpsupplydrop =	math.random(110,140),
8238		        },
8239		        reputation_cost_multipliers = {
8240		        	friend = 1.0,
8241		        	neutral = 2.0,
8242		        },
8243				goods = {
8244					luxury = {
8245						quantity =	5,
8246						cost =		math.random(30,80),
8247					},
8248				},
8249				trade = {
8250					food = false,
8251					medicine = false,
8252					luxury = false,
8253				},
8254				description = "Mining and trade",
8255				general = "",
8256				history = "",
8257			},
8258			["Outpost-21"] = {
8259		        weapon_available = {
8260		        	Homing =			random(1,13)<=(8-difficulty),
8261		        	HVLI =				random(1,13)<=(9-difficulty),
8262		        	Mine =				random(1,13)<=(7-difficulty),
8263		        	Nuke =				random(1,13)<=(5-difficulty),
8264		        	EMP =				random(1,13)<=(6-difficulty),
8265		        },
8266				services = {
8267					supplydrop =		"friend",
8268					reinforcements =	"friend",
8269					jumpsupplydrop =	"friend",
8270				},
8271		        service_cost = {
8272		        	supplydrop =		math.random(80,120),
8273		        	reinforcements =	math.random(125,175),
8274		        	jumpsupplydrop =	math.random(110,140),
8275		        },
8276		        reputation_cost_multipliers = {
8277		        	friend = 1.0,
8278		        	neutral = 2.0,
8279		        },
8280				goods = {
8281					luxury = {
8282						quantity =	5,
8283						cost =		math.random(30,80),
8284					},
8285				},
8286				trade = {
8287					food = false,
8288					medicine = false,
8289					luxury = false,
8290				},
8291				description = "Mining and gambling",
8292				general = "",
8293				history = "",
8294			},
8295			["Outpost-7"] = {
8296		        weapon_available = {
8297		        	Homing =			random(1,13)<=(8-difficulty),
8298		        	HVLI =				random(1,13)<=(9-difficulty),
8299		        	Mine =				random(1,13)<=(7-difficulty),
8300		        	Nuke =				random(1,13)<=(5-difficulty),
8301		        	EMP =				random(1,13)<=(6-difficulty),
8302		        },
8303				services = {
8304					supplydrop =		"friend",
8305					reinforcements =	"friend",
8306					jumpsupplydrop =	"friend",
8307				},
8308		        service_cost = {
8309		        	supplydrop =		math.random(80,120),
8310		        	reinforcements =	math.random(125,175),
8311		        	jumpsupplydrop =	math.random(110,140),
8312		        },
8313		        reputation_cost_multipliers = {
8314		        	friend = 1.0,
8315		        	neutral = 2.0,
8316		        },
8317				goods = {
8318					luxury = {
8319						quantity =	5,
8320						cost =		math.random(30,80),
8321					},
8322				},
8323				trade = {
8324					food = false,
8325					medicine = false,
8326					luxury = false,
8327				},
8328				description = "Resupply",
8329				general = "",
8330				history = "",
8331			},
8332			["Outpost-8"] = {
8333		        weapon_available = {
8334		        	Homing =			random(1,13)<=(8-difficulty),
8335		        	HVLI =				random(1,13)<=(9-difficulty),
8336		        	Mine =				random(1,13)<=(7-difficulty),
8337		        	Nuke =				random(1,13)<=(5-difficulty),
8338		        	EMP =				random(1,13)<=(6-difficulty),
8339		        },
8340				services = {
8341					supplydrop =		"friend",
8342					reinforcements =	"friend",
8343					jumpsupplydrop =	"friend",
8344				},
8345		        service_cost = {
8346		        	supplydrop =		math.random(80,120),
8347		        	reinforcements =	math.random(125,175),
8348		        	jumpsupplydrop =	math.random(110,140),
8349		        },
8350		        reputation_cost_multipliers = {
8351		        	friend = 1.0,
8352		        	neutral = 2.0,
8353		        },
8354				goods = {
8355					luxury = {
8356						quantity =	5,
8357						cost =		math.random(30,80),
8358					},
8359				},
8360				trade = {
8361					food = false,
8362					medicine = false,
8363					luxury = false,
8364				},
8365				description = "",
8366				general = "",
8367				history = "",
8368			},
8369			["Outpost-33"] = {
8370		        weapon_available = {
8371		        	Homing =			random(1,13)<=(8-difficulty),
8372		        	HVLI =				random(1,13)<=(9-difficulty),
8373		        	Mine =				random(1,13)<=(7-difficulty),
8374		        	Nuke =				random(1,13)<=(5-difficulty),
8375		        	EMP =				random(1,13)<=(6-difficulty),
8376		        },
8377				services = {
8378					supplydrop =		"friend",
8379					reinforcements =	"friend",
8380					jumpsupplydrop =	"friend",
8381				},
8382		        service_cost = {
8383		        	supplydrop =		math.random(80,120),
8384		        	reinforcements =	math.random(125,175),
8385		        	jumpsupplydrop =	math.random(110,140),
8386		        },
8387		        reputation_cost_multipliers = {
8388		        	friend = 1.0,
8389		        	neutral = 2.0,
8390		        },
8391				goods = {
8392					luxury = {
8393						quantity =	5,
8394						cost =		math.random(30,80),
8395					},
8396				},
8397				trade = {
8398					food = false,
8399					medicine = false,
8400					luxury = false,
8401				},
8402				description = "Resupply",
8403				general = "",
8404				history = "",
8405			},
8406			["Prada"] = {
8407		        weapon_available = {
8408		        	Homing =			random(1,13)<=(8-difficulty),
8409		        	HVLI =				random(1,13)<=(9-difficulty),
8410		        	Mine =				false,
8411		        	Nuke =				random(1,13)<=(5-difficulty),
8412		        	EMP =				random(1,13)<=(6-difficulty),
8413		        },
8414				services = {
8415					supplydrop =		"friend",
8416					reinforcements =	"friend",
8417					jumpsupplydrop =	"friend",
8418				},
8419		        service_cost = {
8420		        	supplydrop =		math.random(80,120),
8421		        	reinforcements =	math.random(125,175),
8422		        	jumpsupplydrop =	math.random(110,140),
8423		        },
8424		        reputation_cost_multipliers = {
8425		        	friend = 1.0,
8426		        	neutral = 2.0,
8427		        },
8428				goods = {},
8429				trade = {
8430					food = false,
8431					medicine = false,
8432					luxury = false,
8433				},
8434				description = "Textiles and fashion",
8435				general = "",
8436				history = "",
8437			},
8438			["Research-11"] = {
8439		        weapon_available = {
8440		        	Homing =			random(1,13)<=(8-difficulty),
8441		        	HVLI =				random(1,13)<=(9-difficulty),
8442		        	Mine =				random(1,13)<=(7-difficulty),
8443		        	Nuke =				random(1,13)<=(5-difficulty),
8444		        	EMP =				random(1,13)<=(6-difficulty),
8445		        },
8446				services = {
8447					supplydrop =		"friend",
8448					reinforcements =	"friend",
8449					jumpsupplydrop =	"friend",
8450				},
8451		        service_cost = {
8452		        	supplydrop =		math.random(80,120),
8453		        	reinforcements =	math.random(125,175),
8454		        	jumpsupplydrop =	math.random(110,140),
8455		        },
8456		        reputation_cost_multipliers = {
8457		        	friend = 1.0,
8458		        	neutral = 2.0,
8459		        },
8460				goods = {
8461					medicine = {
8462						quantity =	5,
8463						cost =		math.random(30,80),
8464					},
8465				},
8466				trade = {
8467					food = false,
8468					medicine = false,
8469					luxury = false,
8470				},
8471				description = "Stress Psychology Research",
8472				general = "",
8473				history = "",
8474			},
8475			["Research-19"] = {
8476		        weapon_available ={
8477		        	Homing =			random(1,13)<=(8-difficulty),
8478		        	HVLI =				random(1,13)<=(9-difficulty),
8479		        	Mine =				random(1,13)<=(7-difficulty),
8480		        	Nuke =				random(1,13)<=(5-difficulty),
8481		        	EMP =				random(1,13)<=(6-difficulty),
8482		        },
8483				services = {
8484					supplydrop =		"friend",
8485					reinforcements =	"friend",
8486					jumpsupplydrop =	"friend",
8487				},
8488		        service_cost = {
8489		        	supplydrop =		math.random(80,120),
8490		        	reinforcements =	math.random(125,175),
8491		        	jumpsupplydrop =	math.random(110,140),
8492		        },
8493		        reputation_cost_multipliers = {
8494		        	friend = 1.0,
8495		        	neutral = 2.0,
8496		        },
8497		        goods = {},
8498		        trade = {
8499		        	food = false,
8500		        	medicine = false,
8501		        	luxury = false,
8502		        },
8503				description = "Low gravity research",
8504				general = "",
8505				history = "",
8506			},
8507			["Rubis"] = {
8508		        weapon_available = {
8509		        	Homing =			random(1,13)<=(8-difficulty),
8510		        	HVLI =				random(1,13)<=(9-difficulty),
8511		        	Mine =				random(1,13)<=(7-difficulty),
8512		        	Nuke =				random(1,13)<=(5-difficulty),
8513		        	EMP =				random(1,13)<=(6-difficulty),
8514		        },
8515				services = {
8516					supplydrop =		"friend",
8517					reinforcements =	"friend",
8518					jumpsupplydrop =	"friend",
8519				},
8520		        service_cost = {
8521		        	supplydrop =		math.random(80,120),
8522		        	reinforcements =	math.random(125,175),
8523		        	jumpsupplydrop =	math.random(110,140),
8524		        },
8525		        reputation_cost_multipliers = {
8526		        	friend = 1.0,
8527		        	neutral = 3.0,
8528		        },
8529				goods = {
8530					luxury = {
8531						quantity =	5,
8532						cost =		math.random(30,80),
8533					},
8534				},
8535				trade = {
8536					food = false,
8537					medicine = false,
8538					luxury = false,
8539				},
8540				description = "Resupply",
8541				general = "Get your energy here! Grab a drink before you go!",
8542				history = "",
8543			},
8544			["Science-2"] = {
8545		        weapon_available = {
8546		        	Homing =			random(1,13)<=(8-difficulty),
8547		        	HVLI =				random(1,13)<=(9-difficulty),
8548		        	Mine =				random(1,13)<=(7-difficulty),
8549		        	Nuke =				random(1,13)<=(5-difficulty),
8550		        	EMP =				random(1,13)<=(6-difficulty),
8551		        },
8552				services = {
8553					supplydrop =		"friend",
8554					reinforcements =	"friend",
8555					jumpsupplydrop =	"friend",
8556				},
8557		        service_cost = {
8558		        	supplydrop =		math.random(80,120),
8559		        	reinforcements =	math.random(125,175),
8560		        	jumpsupplydrop =	math.random(110,140),
8561		        },
8562				goods = {
8563					circuit = {
8564						quantity =	5,
8565						cost =		math.random(30,80),
8566					},
8567				},
8568				trade = {
8569					food = false,
8570					medicine = false,
8571					luxury = false,
8572				},
8573				description = "Research Lab and Observatory",
8574				general = "",
8575				history = "",
8576			},
8577			["Science-4"] = {
8578		        weapon_available = {
8579		        	Homing =			random(1,13)<=(8-difficulty),
8580		        	HVLI =				random(1,13)<=(9-difficulty),
8581		        	Mine =				random(1,13)<=(7-difficulty),
8582		        	Nuke =				random(1,13)<=(5-difficulty),
8583		        	EMP =				random(1,13)<=(6-difficulty),
8584		        },
8585				services = {
8586					supplydrop =		"friend",
8587					reinforcements =	"friend",
8588					jumpsupplydrop =	"friend",
8589				},
8590		        service_cost = {
8591		        	supplydrop =		math.random(80,120),
8592		        	reinforcements =	math.random(125,175),
8593		        	jumpsupplydrop =	math.random(110,140),
8594		        },
8595		        reputation_cost_multipliers = {
8596		        	friend = 1.0,
8597		        	neutral = 2.0,
8598		        },
8599				goods = {
8600					medicine = {
8601						quantity =	5,
8602						cost =		math.random(30,80),
8603					},
8604					autodoc = {
8605						quantity =	5,
8606						cost =		math.random(30,80),
8607					},
8608				},
8609				trade = {
8610					food = false,
8611					medicine = false,
8612					luxury = false,
8613				},
8614				description = "Biotech research",
8615				general = "",
8616				history = "",
8617			},
8618			["Science-7"] = {
8619		        weapon_available = {
8620		        	Homing =			random(1,13)<=(8-difficulty),
8621		        	HVLI =				random(1,13)<=(9-difficulty),
8622		        	Mine =				random(1,13)<=(7-difficulty),
8623		        	Nuke =				random(1,13)<=(5-difficulty),
8624		        	EMP =				random(1,13)<=(6-difficulty),
8625		        },
8626				services = {
8627					supplydrop =		"friend",
8628					reinforcements =	"friend",
8629					jumpsupplydrop =	"friend",
8630				},
8631		        service_cost = {
8632		        	supplydrop =		math.random(80,120),
8633		        	reinforcements =	math.random(125,175),
8634		        	jumpsupplydrop =	math.random(110,140),
8635		        },
8636				goods = {
8637					food = {
8638						quantity =	2,
8639						cost =		1,
8640					},
8641				},
8642				trade = {
8643					food = false,
8644					medicine = false,
8645					luxury = false,
8646				},
8647				description = "Observatory",
8648				general = "",
8649				history = "",
8650			},
8651			["Spot"] = {
8652		        weapon_available = {
8653		        	Homing =			random(1,13)<=(8-difficulty),
8654		        	HVLI =				random(1,13)<=(9-difficulty),
8655		        	Mine =				random(1,13)<=(7-difficulty),
8656		        	Nuke =				random(1,13)<=(5-difficulty),
8657		        	EMP =				random(1,13)<=(6-difficulty),
8658		        },
8659				services = {
8660					supplydrop =		"friend",
8661					reinforcements =	"friend",
8662					jumpsupplydrop =	"friend",
8663				},
8664		        service_cost = {
8665		        	supplydrop =		math.random(80,120),
8666		        	reinforcements =	math.random(125,175),
8667		        	jumpsupplydrop =	math.random(110,140),
8668		        },
8669		        reputation_cost_multipliers = {
8670		        	friend = 1.0,
8671		        	neutral = 3.0,
8672		        },
8673		        goods = {},
8674		        trade = {
8675		        	food = false,
8676		        	medicine = false,
8677		        	luxury = false,
8678		        },
8679				description = "Observatory",
8680				general = "",
8681				history = "",
8682			},
8683			["Valero"] = {
8684		        weapon_available = {
8685		        	Homing =			random(1,13)<=(8-difficulty),
8686		        	HVLI =				random(1,13)<=(9-difficulty),
8687		        	Mine =				random(1,13)<=(7-difficulty),
8688		        	Nuke =				random(1,13)<=(5-difficulty),
8689		        	EMP =				random(1,13)<=(6-difficulty),
8690		        },
8691				services = {
8692					supplydrop =		"friend",
8693					reinforcements =	"friend",
8694					jumpsupplydrop =	"friend",
8695				},
8696		        service_cost = {
8697		        	supplydrop =		math.random(80,120),
8698		        	reinforcements =	math.random(125,175),
8699		        	jumpsupplydrop =	math.random(110,140),
8700		        },
8701		        reputation_cost_multipliers = {
8702		        	friend = 1.0,
8703		        	neutral = 2.0,
8704		        },
8705				goods = {
8706					luxury = {
8707						quantity =	5,
8708						cost =		math.random(30,80),
8709					},
8710				},
8711				trade = {
8712					food = false,
8713					medicine = false,
8714					luxury = false,
8715				},
8716				description = "Resupply",
8717				general = "",
8718				history = "",
8719			},
8720		},
8721		["Sinister"] = {
8722			["Aramanth"] =	{goods = {}, description = "", general = "", history = ""},
8723			["Empok Nor"] =	{goods = {}, description = "", general = "", history = ""},
8724			["Gandala"] =	{goods = {}, description = "", general = "", history = ""},
8725			["Hassenstadt"] =	{goods = {}, description = "", general = "", history = ""},
8726			["Kaldor"] =	{goods = {}, description = "", general = "", history = ""},
8727			["Magenta Mesra"] =	{goods = {}, description = "", general = "", history = ""},
8728			["Mos Eisley"] =	{goods = {}, description = "", general = "", history = ""},
8729			["Questa Verde"] =	{goods = {}, description = "", general = "", history = ""},
8730			["R'lyeh"] =	{goods = {}, description = "", general = "", history = ""},
8731			["Scarlet Citadel"] =	{goods = {}, description = "", general = "", history = ""},
8732			["Stahlstadt"] =	{goods = {}, description = "", general = "", history = ""},
8733			["Ticonderoga"] =	{goods = {}, description = "", general = "", history = ""},
8734		},
8735	}
8736	station_priority = {}
8737	table.insert(station_priority,"Science")
8738	table.insert(station_priority,"Pop Sci Fi")
8739	table.insert(station_priority,"Spec Sci Fi")
8740	table.insert(station_priority,"History")
8741	table.insert(station_priority,"Generic")
8742	for group, list in pairs(station_pool) do
8743		local already_inserted = false
8744		for _, previous_group in ipairs(station_priority) do
8745			if group == previous_group then
8746				already_inserted = true
8747				break
8748			end
8749		end
8750		if not already_inserted and group ~= "Sinister" then
8751			table.insert(station_priority,group)
8752		end
8753	end
8754end
8755------------------------------
8756--	Station communications  --
8757------------------------------
8758function commsStation()
8759    if comms_target.comms_data == nil then
8760        comms_target.comms_data = {}
8761    end
8762    mergeTables(comms_target.comms_data, {
8763        friendlyness = random(0.0, 100.0),
8764        weapons = {
8765            Homing = "neutral",
8766            HVLI = "neutral",
8767            Mine = "neutral",
8768            Nuke = "friend",
8769            EMP = "friend",
8770        },
8771        weapon_cost = {
8772            Homing = math.random(1,4),
8773            HVLI = math.random(1,3),
8774            Mine = math.random(2,5),
8775            Nuke = math.random(12,18),
8776            EMP = math.random(7,13),
8777        },
8778        services = {
8779            supplydrop = "friend",
8780            reinforcements = "friend",
8781            sensor_boost = "neutral",
8782			preorder = "friend",
8783            activatedefensefleet = "neutral",
8784        },
8785        service_cost = {
8786            supplydrop = math.random(80,120),
8787            reinforcements = math.random(125,175),
8788            phobosReinforcements = math.random(200,250),
8789            stalkerReinforcements = math.random(275,325),
8790            activatedefensefleet = 20,
8791        },
8792        reputation_cost_multipliers = {
8793            friend = 1.0,
8794            neutral = 3.0,
8795        },
8796        max_weapon_refill_amount = {
8797            friend = 1.0,
8798            neutral = 0.5,
8799        }
8800    })
8801    comms_data = comms_target.comms_data
8802    if comms_source:isEnemy(comms_target) then
8803        return false
8804    end
8805--	if comms_target:areEnemiesInRange(5000) then
8806--	    setCommsMessage("We are under attack! No time for chatting!");
8807--		return true
8808--	end
8809    if not comms_source:isDocked(comms_target) then
8810        handleUndockedState()
8811    else
8812        handleDockedState()
8813    end
8814    return true
8815end
8816function commsDefensePlatform()
8817	if comms_target.comms_data == nil then
8818        comms_target.comms_data = {}
8819    end
8820    mergeTables(comms_target.comms_data, {
8821        friendlyness = random(0.0, 100.0),
8822        weapons = {
8823            Homing = "neutral",
8824            HVLI = "neutral",
8825            Mine = "neutral",
8826            Nuke = "friend",
8827            EMP = "friend"
8828        },
8829        weapon_cost = {
8830            Homing = math.random(1,4),
8831            HVLI = math.random(1,3),
8832            Mine = math.random(2,5),
8833            Nuke = math.random(12,18),
8834            EMP = math.random(7,13)
8835        },
8836        services = {
8837            supplydrop = "friend",
8838            reinforcements = "friend",
8839        },
8840        service_cost = {
8841            supplydrop = math.random(80,120),
8842            reinforcements = math.random(125,175),
8843            phobosReinforcements = math.random(200,250),
8844            stalkerReinforcements = math.random(275,325)
8845        },
8846        reputation_cost_multipliers = {
8847            friend = 1.0,
8848            neutral = 3.0
8849        },
8850        max_weapon_refill_amount = {
8851            friend = 1.0,
8852            neutral = 0.5
8853        }
8854    })
8855    comms_data = comms_target.comms_data
8856    if comms_source:isEnemy(comms_target) then
8857        return false
8858    end
8859    if comms_source:isDocked(comms_target) then
8860    --    handleDockedState()
8861    	setCommsMessage(string.format("Hi %s",comms_source:getCallSign()))
8862		restockOrdnance(commsDefensePlatform)
8863		completionConditions(commsDefensePlatform)
8864		dockingServicesStatus(commsDefensePlatform)
8865		repairSubsystems(commsDefensePlatform)
8866		stationDefenseReport(commsDefensePlatform)
8867		if primary_jammers then
8868			if comms_source:isFriendly(comms_target) then
8869				addCommsReply(string.format("Transfer to %s",comms_target.primary_station:getCallSign()),function()
8870					comms_source:commandUndock()
8871					local psx, psy = comms_target.primary_station:getPosition()
8872					local angle = comms_source:getHeading()
8873					local station_dock_radius = {
8874						["Small Station"] = 300,
8875						["Medium Station"] = 1000,
8876						["Large Station"] = 1300,
8877						["Huge Station"] = 1500,
8878					}
8879					local dock_distance = station_dock_radius[comms_target.primary_station:getTypeName()]
8880					local vx, vy = vectorFromAngleNorth(angle,dock_distance)
8881					comms_source:setPosition(psx + vx, psy + vy)
8882					comms_source:commandDock(comms_target.primary_station)
8883					setCommsMessage(string.format("Don't let %s forget their friends on duty at %s",comms_target.primary_station:getCallSign(),comms_target:getCallSign()))
8884				end)
8885			end
8886		end
8887	else	--undocked
8888		local dock_messages = {
8889			"Dock if you want anything",
8890			"You must dock before we can do anything",
8891			"Gotta dock first",
8892			"Can't do anything for you unless you dock",
8893			"Docking crew is standing by",
8894			"Dock first, then talk",
8895		}
8896		setCommsMessage(dock_messages[math.random(1,#dock_messages)])
8897		ordnanceAvailability(commsDefensePlatform)
8898		completionConditions(commsDefensePlatform)
8899		dockingServicesStatus(commsDefensePlatform)
8900		stationDefenseReport(commsDefensePlatform)
8901	end
8902	return true
8903end
8904function handleDockedState()
8905    if comms_source:isFriendly(comms_target) then
8906		oMsg = "Good day, officer!\nWhat can we do for you today?"
8907    else
8908		oMsg = "Welcome to our lovely station."
8909    end
8910    if comms_target:areEnemiesInRange(20000) then
8911		oMsg = oMsg .. "\nForgive us if we seem a little distracted. We are carefully monitoring the enemies nearby."
8912	end
8913	setCommsMessage(oMsg)
8914	restockOrdnance(commsStation)
8915	completionConditions(commsStation)
8916	dockingServicesStatus(commsStation)
8917	repairSubsystems(commsStation)
8918	boostSensorsWhileDocked(commsStation)
8919	overchargeJump(commsStation)
8920	activateDefenseFleet(commsStation)
8921	for _, scientist in ipairs(scientist_list[comms_target:getFaction()]) do
8922		if scientist.location == comms_target then
8923			addCommsReply(string.format("Speak with scientist %s",scientist.name),function()
8924				setCommsMessage(string.format("Greetings, %s\nI've got great ideas for the war effort.\nWhat can I do for you?",comms_source:getCallSign()))
8925				addCommsReply("Please come aboard our ship",function()
8926					setCommsMessage(string.format("Certainly, %s\n\n%s boards your ship",comms_source:getCallSign(),scientist.name))
8927					scientist.location = comms_source
8928					scientist.location_name = comms_source:getCallSign()
8929					addCommsReply("Back", commsStation)
8930				end)
8931				addCommsReply("Can you tell me some more about your ideas?",function()
8932					local rc = false
8933					local msg = ""
8934					local completed_message = ""
8935					local npc_message = ""
8936					setCommsMessage(string.format("I'd need to visit %s to proceed further",faction_primary_station[comms_target:getFaction()].station:getCallSign()))
8937					if string.find(scientist.upgrade_requirement,"talk") or string.find(scientist.upgrade_requirement,"meet") then
8938						if string.find(scientist.upgrade_requirement,"primary") then
8939							if faction_primary_station[comms_target:getFaction()].station ~= nil and faction_primary_station[comms_target:getFaction()].station:isValid() then
8940								if faction_primary_station[comms_target:getFaction()].station.available_upgrades == nil then
8941									faction_primary_station[comms_target:getFaction()].station.available_upgrades = {}
8942								end
8943								faction_primary_station[comms_target:getFaction()].station.available_upgrades[scientist.upgrade.name] = scientist.upgrade.action
8944								setCommsMessage(string.format("I just sent details on a %s to %s. With their facilities, you should be able to apply the upgrade the next time you dock there.",scientist.upgrade.name,faction_primary_station[comms_target:getFaction()].station:getCallSign()))
8945							else
8946								setCommsMessage("Without your primary station to apply my research, I'm afraid my information is useless")
8947							end
8948						else
8949							rc, msg = scientist.upgrade.action(comms_source)
8950							if rc then
8951								completed_message = string.format("After an extended conversation with %s and the exchange of technical information with various crew members, you apply the insight into %s gained by %s.\n\n%s",scientist.name,scientist.topic,scientist.name,msg)
8952								if scientist.upgrade_automated_application == "single" then
8953									setCommsMessage(completed_message)
8954								elseif scientist.upgrade_automated_application == "players" then
8955									for pidx=1,32 do
8956										local p = getPlayerShip(pidx)
8957										if p ~= nil and p:isValid() and p ~= comms_source and p:getFaction() == comms_source:getFaction() then
8958											rc, msg = scientist.upgrade.action(p)
8959											if rc then
8960												p:addToShipLog(string.format("%s provided details from %s for an upgrade. %s",comms_source:getCallSign(),scientist.name,msg),"Magenta")
8961											end
8962										end
8963									end
8964									setCommsMessage(completed_message .. "\nThe upgrade details were also provided to the other players in your faction.")
8965								elseif scientist.upgrade_automated_application == "all" then
8966									if scientist.upgrade.action ~= longerSensorsUpgrade and scientist.upgrade.action ~= batteryEfficiencyUpgrade then
8967										if npc_fleet ~= nil and npc_fleet[comms_source:getFaction()] ~= nil and #npc_fleet[comms_source:getFaction()] > 0 then
8968											for i=1,#npc_fleet[comms_source:getFaction()] do
8969												local npc = npc_fleet[comms_source:getFaction()][i]
8970												if npc ~= nil and npc:isValid() then
8971													rc, msg = scientist.upgrade.action(npc)
8972												end
8973											end
8974											npc_message = "and npc ships "
8975										end
8976									end
8977									for pidx=1,32 do
8978										local p = getPlayerShip(pidx)
8979										if p ~= nil and p:isValid() and p ~= comms_source and p:getFaction() == comms_source:getFaction() then
8980											rc, msg = scientist.upgrade.action(p)
8981											if rc then
8982												p:addToShipLog(string.format("%s provided details from %s for an upgrade. %s",comms_source:getCallSign(),scientist.name,msg),"Magenta")
8983											end
8984										end
8985									end
8986									setCommsMessage(string.format("%s\nThe upgrade details were also provided to the other players %sin your faction.",completed_message,npc_message))
8987								end
8988							else
8989								setCommsMessage(string.format("Your conversation with %s about %s was interesting, but not directly applicable.\n\n%s",scientist.name,scientist.topic,msg))
8990							end
8991						end
8992					elseif scientist.upgrade_requirement == "transport" then
8993						if comms_target == faction_primary_station[comms_target:getFaction()].station then
8994							rc, msg = scientist.upgrade.action(comms_source)
8995							if rc then
8996								completed_message = string.format("After an extended conversation with %s, various crew members and %s facilities managers, you apply the insight into %s gained by %s.\n\n%s",scientist.name,comms_target:getCallSign(),scientist.topic,scientist.name,msg)
8997								if faction_primary_station[comms_target:getFaction()].station.available_upgrades == nil then
8998									faction_primary_station[comms_target:getFaction()].station.available_upgrades = {}
8999								end
9000								faction_primary_station[comms_target:getFaction()].station.available_upgrades[scientist.upgrade.name] = scientist.upgrade.action
9001								setCommsMessage(completed_message)
9002								if scientist.upgrade_automated_application == "all" then
9003									if scientist.upgrade.action ~= longerSensorsUpgrade and scientist.upgrade.action ~= batteryEfficiencyUpgrade then
9004										if npc_fleet ~= nil and npc_fleet[comms_source:getFaction()] ~= nil and #npc_fleet[comms_source:getFaction()] > 0 then
9005											for i=1,#npc_fleet[comms_source:getFaction()] do
9006												local npc = npc_fleet[comms_source:getFaction()][i]
9007												if npc ~= nil and npc:isValid() then
9008													rc, msg = scientist.upgrade.action(npc)
9009												end
9010											end
9011											npc_message = "and npc ships "
9012										end
9013									end
9014									setCommsMessage(string.format("%s\nNPC ships received the upgrade as well",completed_message))
9015								end
9016							else
9017								setCommsMessage(string.format("Your conversation with %s about %s was interesting, but not directly applicable.\n\n%s",scientist.name,scientist.topic,msg))
9018								if faction_primary_station[comms_target:getFaction()].station.available_upgrades == nil then
9019									faction_primary_station[comms_target:getFaction()].station.available_upgrades = {}
9020								end
9021								faction_primary_station[comms_target:getFaction()].station.available_upgrades[scientist.upgrade.name] = scientist.upgrade.action
9022							end
9023						end
9024					elseif scientist.upgrade_requirement == "confer" then
9025						if comms_target == faction_primary_station[comms_target:getFaction()].station then
9026							local colleage_count = 0
9027							local conferee = nil
9028							for _, colleague in ipairs(scientist_list[comms_target:getFaction()]) do
9029								if colleague.location == comms_target and colleague ~= scientist then
9030									colleage_count = colleage_count + 1
9031									conferee = colleague
9032								end
9033							end
9034							if colleage_count > 0 then
9035								rc, msg = scientist.upgrade.action(comms_source)
9036								if rc then
9037									completed_message = string.format("After an extended conversation with %s, %s, various crew members and %s facilities managers, you apply the insight into %s and %s gained by %s.\n\n%s",scientist.name,conferee.name,comms_target:getCallSign(),scientist.topic,conferee.topic,scientist.name,msg)
9038									if faction_primary_station[comms_target:getFaction()].station.available_upgrades == nil then
9039										faction_primary_station[comms_target:getFaction()].station.available_upgrades = {}
9040									end
9041									faction_primary_station[comms_target:getFaction()].station.available_upgrades[scientist.upgrade.name] = scientist.upgrade.action
9042									if scientist.upgrade_automated_application == "single" then
9043										setCommsMessage(completed_message)
9044									elseif scientist.upgrade_automated_application == "players" then
9045										for pidx=1,32 do
9046											local p = getPlayerShip(pidx)
9047											if p ~= nil and p:isValid() and p ~= comms_source and p:getFaction() == comms_source:getFaction() then
9048												rc, msg = scientist.upgrade.action(p)
9049												if rc then
9050													p:addToShipLog(string.format("%s provided details from %s for an upgrade. %s",comms_source:getCallSign(),scientist.name,msg),"Magenta")
9051												end
9052											end
9053										end
9054										setCommsMessage(completed_message .. "\nThe upgrade details were also provided to the other players in your faction.")
9055									elseif scientist.upgrade_automated_application == "all" then
9056										if scientist.upgrade.action ~= longerSensorsUpgrade and scientist.upgrade.action ~= batteryEfficiencyUpgrade then
9057											if npc_fleet ~= nil and npc_fleet[comms_source:getFaction()] ~= nil and #npc_fleet[comms_source:getFaction()] > 0 then
9058												for i=1,#npc_fleet[comms_source:getFaction()] do
9059													local npc = npc_fleet[comms_source:getFaction()][i]
9060													if npc ~= nil and npc:isValid() then
9061														rc, msg = scientist.upgrade.action(npc)
9062													end
9063												end
9064												npc_message = "and npc ships "
9065											end
9066										end
9067										for pidx=1,32 do
9068											local p = getPlayerShip(pidx)
9069											if p ~= nil and p:isValid() and p ~= comms_source and p:getFaction() == comms_source:getFaction() then
9070												rc, msg = scientist.upgrade.action(p)
9071												if rc then
9072													p:addToShipLog(string.format("%s provided details from %s for an upgrade. %s",comms_source:getCallSign(),scientist.name,msg),"Magenta")
9073												end
9074											end
9075										end
9076										setCommsMessage(string.format("%s\nThe upgrade details were also provided to the other players %sin your faction.",completed_message,npc_message))
9077									end
9078								else
9079									setCommsMessage(string.format("Your conversation with %s and %s about %s and %s was interesting, but not directly applicable.\n\n%s",scientist.name,conferee.name,scientist.topic,conferee.topic,msg))
9080									if faction_primary_station[comms_target:getFaction()].station.available_upgrades == nil then
9081										faction_primary_station[comms_target:getFaction()].station.available_upgrades = {}
9082									end
9083									faction_primary_station[comms_target:getFaction()].station.available_upgrades[scientist.upgrade.name] = scientist.upgrade.action
9084								end
9085							else
9086								setCommsMessage(string.format("I've got this idea for a %s, but I just can't quite get it to crystalize. If I had another scientist here to collaborate with, I might get further along",scientist.upgrade.name))
9087							end
9088						end
9089					end
9090				end)
9091				addCommsReply("Back", commsStation)
9092			end)
9093		end
9094		if scientist.location == comms_source then
9095			addCommsReply(string.format("Escort %s on to %s",scientist.name,comms_target:getCallSign()),function()
9096				setCommsMessage(string.format("%s thanks you for your hospitality and disembarks to %s",scientist.name,comms_target:getCallSign()))
9097				scientist.location = comms_target
9098				scientist.location_name = comms_target:getCallSign()
9099				addCommsReply("Back", commsStation)
9100			end)
9101		end
9102	end
9103	if comms_target.available_upgrades ~= nil then
9104		for name, action in pairs(comms_target.available_upgrades) do
9105			addCommsReply(name,function()
9106				string.format("")	--Serious Proton needs global reference/context
9107				local rc, msg = action(comms_source)
9108				if rc then
9109					setCommsMessage(string.format("Congratulations!\n%s",msg))
9110				else
9111					setCommsMessage(string.format("Sorry.\n%s",msg))
9112				end
9113			end)
9114		end
9115	end
9116	stationFlavorInformation(commsStation)
9117	if comms_source:isFriendly(comms_target) then
9118		if random(1,100) <= (20 - difficulty*2) then
9119			if comms_source:getRepairCrewCount() < comms_source.maxRepairCrew then
9120				hireCost = math.random(30,60)
9121			else
9122				hireCost = math.random(45,90)
9123			end
9124			addCommsReply(string.format("Recruit repair crew member for %i reputation",hireCost), function()
9125				if not comms_source:takeReputationPoints(hireCost) then
9126					setCommsMessage("Insufficient reputation")
9127				else
9128					comms_source:setRepairCrewCount(comms_source:getRepairCrewCount() + 1)
9129					resetPreviousSystemHealth(comms_source)
9130					setCommsMessage("Repair crew member hired")
9131				end
9132				addCommsReply("Back", commsStation)
9133			end)
9134		end
9135		if comms_source.initialCoolant ~= nil then
9136			if math.random(1,100) <= (20 - difficulty*2) then
9137				local coolantCost = math.random(45,90)
9138				if comms_source:getMaxCoolant() < comms_source.initialCoolant then
9139					coolantCost = math.random(30,60)
9140				end
9141				addCommsReply(string.format("Purchase coolant for %i reputation",coolantCost), function()
9142					if not comms_source:takeReputationPoints(coolantCost) then
9143						setCommsMessage("Insufficient reputation")
9144					else
9145						comms_source:setMaxCoolant(comms_source:getMaxCoolant() + 2)
9146						setCommsMessage("Additional coolant purchased")
9147					end
9148					addCommsReply("Back", commsStation)
9149				end)
9150			end
9151		end
9152	end
9153	if primary_jammers then
9154		if comms_source:isFriendly(comms_target) then
9155			if defense_platform_count > 0 and comms_target == faction_primary_station[comms_source:getFaction()].station then
9156				addCommsReply("Exit Jammer",function()
9157					comms_source:commandUndock()
9158					local psx, psy = comms_target:getPosition()
9159					local angle = (faction_angle[comms_source:getFaction()] + 180) % 360
9160					local vx, vy = vectorFromAngleNorth(angle,defense_platform_distance + 4000)
9161					comms_source:setPosition(psx + vx, psy + vy):setHeading(angle):commandTargetRotation((angle + 270) % 360)
9162					setCommsMessage("Have fun storming the castle")
9163				end)
9164			end
9165		end
9166	end
9167	buySellTrade(commsStation)
9168end	--end of handleDockedState function
9169function handleUndockedState()
9170    --Handle communications when we are not docked with the station.
9171    if comms_source:isFriendly(comms_target) then
9172        oMsg = "Good day, officer.\nIf you need supplies, please dock with us first."
9173    else
9174        oMsg = "Greetings.\nIf you want to do business, please dock with us first."
9175    end
9176    if comms_target:areEnemiesInRange(20000) then
9177		oMsg = oMsg .. "\nBe aware that if enemies in the area get much closer, we will be too busy to conduct business with you."
9178	end
9179	setCommsMessage(oMsg)
9180--	expediteDock(commsStation)		--may reinstate if time permits. Needs code in update function, player loop
9181 	addCommsReply("I need information", function()
9182		setCommsMessage("What kind of information do you need?")
9183		ordnanceAvailability(commsStation)
9184		goodsAvailabilityOnStation(commsStation)
9185		completionConditions(commsStation)
9186		dockingServicesStatus(commsStation)
9187		stationFlavorInformation(commsStation)
9188		stationDefenseReport(commsStation)
9189	end)
9190	requestSupplyDrop(commsStation)
9191	requestJumpSupplyDrop(commsStation)
9192	requestReinforcements(commsStation)
9193	for _, scientist in ipairs(scientist_list[comms_target:getFaction()]) do
9194		if scientist.location == comms_target then
9195			addCommsReply(string.format("Speak with scientist %s",scientist.name),function()
9196				setCommsMessage(string.format("Greetings, %s\nI've got great ideas for the war effort.\nWhat can I do for you?",comms_source:getCallSign()))
9197				addCommsReply("Can you tell me some more about your ideas?",function()
9198					local rc = false
9199					local msg = ""
9200					local completed_message = ""
9201					local npc_message = ""
9202					if string.find(scientist.upgrade_requirement,"talk") then
9203						if string.find(scientist.upgrade_requirement,"primary") then
9204							if faction_primary_station[comms_target:getFaction()].station ~= nil and faction_primary_station[comms_target:getFaction()].station:isValid() then
9205								if faction_primary_station[comms_target:getFaction()].station.available_upgrades == nil then
9206									faction_primary_station[comms_target:getFaction()].station.available_upgrades = {}
9207								end
9208								faction_primary_station[comms_target:getFaction()].station.available_upgrades[scientist.upgrade.name] = scientist.upgrade.action
9209								setCommsMessage(string.format("I just sent details on a %s to %s. With their facilities, you should be able to apply the upgrade the next time you dock there.",scientist.upgrade.name,faction_primary_station[comms_target:getFaction()].station:getCallSign()))
9210							else
9211								setCommsMessage("Without your primary station to apply my research, I'm afraid my information is useless")
9212							end
9213						else
9214							local rc, msg = scientist.upgrade.action(comms_source)
9215							if rc then
9216								completed_message = string.format("After an extended conversation with %s and the exchange of technical information with various crew members, you apply the insight into %s gained by %s.\n\n%s",scientist.name,scientist.topic,scientist.name,msg)
9217								if scientist.upgrade_automated_application == "single" then
9218									setCommsMessage(completed_message)
9219								elseif scientist.upgrade_automated_application == "players" then
9220									for pidx=1,32 do
9221										local p = getPlayerShip(pidx)
9222										if p ~= nil and p:isValid() and p ~= comms_source and p:getFaction() == comms_source:getFaction() then
9223											rc, msg = scientist.upgrade.action(p)
9224											if rc then
9225												p:addToShipLog(string.format("%s provided details from %s for an upgrade. %s",comms_source:getCallSign(),scientist.name,msg),"Magenta")
9226											end
9227										end
9228									end
9229									setCommsMessage(completed_message .. "\nThe upgrade details were also provided to the other players in your faction.")
9230								elseif scientist.upgrade_automated_application == "all" then
9231									if scientist.upgrade.action ~= longerSensorsUpgrade and scientist.upgrade.action ~= batteryEfficiencyUpgrade then
9232										if npc_fleet ~= nil and npc_fleet[comms_source:getFaction()] ~= nil and #npc_fleet[comms_source:getFaction()] > 0 then
9233											for i=1,#npc_fleet[comms_source:getFaction()] do
9234												local npc = npc_fleet[comms_source:getFaction()][i]
9235												if npc ~= nil and npc:isValid() then
9236													rc, msg = scientist.upgrade.action(npc)
9237												end
9238											end
9239											npc_message = "and npc ships "
9240										end
9241									end
9242									for pidx=1,32 do
9243										local p = getPlayerShip(pidx)
9244										if p ~= nil and p:isValid() and p ~= comms_source and p:getFaction() == comms_source:getFaction() then
9245											rc, msg = scientist.upgrade.action(p)
9246											if rc then
9247												p:addToShipLog(string.format("%s provided details from %s for an upgrade. %s",comms_source:getCallSign(),scientist.name,msg),"Magenta")
9248											end
9249										end
9250									end
9251									setCommsMessage(string.format("%s\nThe upgrade details were also provided to the other players %sin your faction.",completed_message,npc_message))
9252								end
9253							else
9254								setCommsMessage(string.format("Your conversation with %s about %s was interesting, but not directly applicable.\n\n%s",scientist.name,scientist.topic,msg))
9255							end
9256							local overhear_chance = 16
9257							if scientist.upgrade_automated_application == "players" then
9258								overhear_chance = 28
9259							end
9260							if scientist.upgrade_automated_application == "all" then
9261								overhear_chance = 39
9262							end
9263							if random(1,100) <= overhear_chance then
9264								for pidx=1,32 do
9265									local p = getPlayerShip(pidx)
9266									if p ~= nil and p:isValid() then
9267										if p:getFaction() == comms_source:getFaction() then
9268											p:addToShipLog(string.format("Communication between %s and %s intercepted by enemy faction",comms_source:getCallSign(),comms_target:getCallSign()),"Magenta")
9269										else
9270											p:addToShipLog(string.format("%s conversation intercepted regarding %s. Probable military application. Suggest you contact our own scientist in the same field",comms_source:getFaction(),scientist.topic),"Magenta")
9271										end
9272									end
9273								end
9274							end
9275						end
9276					else
9277						setCommsMessage("I should not discuss it over an open communication line. Perhaps you should visit and we can talk")
9278					end
9279				end)
9280				addCommsReply("Back", commsStation)
9281			end)
9282		end
9283	end
9284    if isAllowedTo(comms_target.comms_data.services.activatedefensefleet) and
9285    	comms_target.comms_data.idle_defense_fleet ~= nil then
9286    	local defense_fleet_count = 0
9287    	for name, template in pairs(comms_target.comms_data.idle_defense_fleet) do
9288    		defense_fleet_count = defense_fleet_count + 1
9289    	end
9290    	if defense_fleet_count > 0 then
9291    		addCommsReply("Activate station defense fleet (" .. getServiceCost("activatedefensefleet") .. " rep)",function()
9292    			if comms_source:takeReputationPoints(getServiceCost("activatedefensefleet")) then
9293    				local out = string.format("%s defense fleet\n",comms_target:getCallSign())
9294    				for name, template in pairs(comms_target.comms_data.idle_defense_fleet) do
9295    					local script = Script()
9296						local position_x, position_y = comms_target:getPosition()
9297						local station_name = comms_target:getCallSign()
9298						script:setVariable("position_x", position_x):setVariable("position_y", position_y)
9299						script:setVariable("station_name",station_name)
9300    					script:setVariable("name",name)
9301    					script:setVariable("template",template)
9302    					script:setVariable("faction_id",comms_target:getFactionId())
9303    					script:run("border_defend_station.lua")
9304    					out = out .. " " .. name
9305    					comms_target.comms_data.idle_defense_fleet[name] = nil
9306    				end
9307    				out = out .. "\nactivated"
9308    				setCommsMessage(out)
9309    			else
9310    				setCommsMessage("Insufficient reputation")
9311    			end
9312				addCommsReply("Back", mainMenu)
9313    		end)
9314		end
9315    end
9316end
9317function isAllowedTo(state)
9318    if state == "friend" and comms_source:isFriendly(comms_target) then
9319        return true
9320    end
9321    if state == "neutral" and not comms_source:isEnemy(comms_target) then
9322        return true
9323    end
9324    return false
9325end
9326function getWeaponCost(weapon)
9327    return math.ceil(comms_data.weapon_cost[weapon] * comms_data.reputation_cost_multipliers[getFriendStatus()])
9328end
9329function getFriendStatus()
9330    if comms_source:isFriendly(comms_target) then
9331        return "friend"
9332    else
9333        return "neutral"
9334    end
9335end
9336function dockingServicesStatus(return_function)
9337	addCommsReply("Docking services status", function()
9338		local service_status = string.format("Station %s docking services status:",comms_target:getCallSign())
9339		if comms_target:getRestocksScanProbes() then
9340			service_status = string.format("%s\nReplenish scan probes.",service_status)
9341		else
9342			if comms_target.probe_fail_reason == nil then
9343				local reason_list = {
9344					"Cannot replenish scan probes due to fabrication unit failure.",
9345					"Parts shortage prevents scan probe replenishment.",
9346					"Management has curtailed scan probe replenishment for cost cutting reasons.",
9347				}
9348				comms_target.probe_fail_reason = reason_list[math.random(1,#reason_list)]
9349			end
9350			service_status = string.format("%s\n%s",service_status,comms_target.probe_fail_reason)
9351		end
9352		if comms_target:getRepairDocked() then
9353			service_status = string.format("%s\nShip hull repair.",service_status)
9354		else
9355			if comms_target.repair_fail_reason == nil then
9356				reason_list = {
9357					"We're out of the necessary materials and supplies for hull repair.",
9358					"Hull repair automation unavailable while it is undergoing maintenance.",
9359					"All hull repair technicians quarantined to quarters due to illness.",
9360				}
9361				comms_target.repair_fail_reason = reason_list[math.random(1,#reason_list)]
9362			end
9363			service_status = string.format("%s\n%s",service_status,comms_target.repair_fail_reason)
9364		end
9365		if comms_target:getSharesEnergyWithDocked() then
9366			service_status = string.format("%s\nRecharge ship energy stores.",service_status)
9367		else
9368			if comms_target.energy_fail_reason == nil then
9369				reason_list = {
9370					"A recent reactor failure has put us on auxiliary power, so we cannot recharge ships.",
9371					"A damaged power coupling makes it too dangerous to recharge ships.",
9372					"An asteroid strike damaged our solar cells and we are short on power, so we can't recharge ships right now.",
9373				}
9374				comms_target.energy_fail_reason = reason_list[math.random(1,#reason_list)]
9375			end
9376			service_status = string.format("%s\n%s",service_status,comms_target.energy_fail_reason)
9377		end
9378		if comms_target.comms_data.jump_overcharge then
9379			service_status = string.format("%s\nMay overcharge jump drive",service_status)
9380		end
9381		if comms_target.comms_data.probe_launch_repair then
9382			service_status = string.format("%s\nMay repair probe launch system",service_status)
9383		end
9384		if comms_target.comms_data.hack_repair then
9385			service_status = string.format("%s\nMay repair hacking system",service_status)
9386		end
9387		if comms_target.comms_data.scan_repair then
9388			service_status = string.format("%s\nMay repair scanners",service_status)
9389		end
9390		if comms_target.comms_data.combat_maneuver_repair then
9391			service_status = string.format("%s\nMay repair combat maneuver",service_status)
9392		end
9393		if comms_target.comms_data.self_destruct_repair then
9394			service_status = string.format("%s\nMay repair self destruct system",service_status)
9395		end
9396		if comms_target.comms_data.tube_slow_down_repair then
9397			service_status = string.format("%s\nMay repair slow loading tubes",service_status)
9398		end
9399		setCommsMessage(service_status)
9400		addCommsReply("Back", return_function)
9401	end)
9402end
9403function stationFlavorInformation(return_function)
9404	if (comms_target.comms_data.general ~= nil and comms_target.comms_data.general ~= "") or (comms_target.comms_data.history ~= nil and comms_target.comms_data.history ~= "") then
9405		addCommsReply("Tell me more about your station", function()
9406			setCommsMessage("What would you like to know?")
9407			if comms_target.comms_data.general ~= nil and comms_target.comms_data.general ~= "" then
9408				addCommsReply("General information", function()
9409					setCommsMessage(comms_target.comms_data.general)
9410					addCommsReply("Back", return_function)
9411				end)
9412			end
9413			if comms_target.comms_data.history ~= nil and comms_target.comms_data.history ~= "" then
9414				addCommsReply("Station history", function()
9415					setCommsMessage(comms_target.comms_data.history)
9416					addCommsReply("Back", return_function)
9417				end)
9418			end
9419		end)
9420	end
9421end
9422function stationDefenseReport(return_function)
9423	addCommsReply("Report status", function()
9424		msg = "Hull: " .. math.floor(comms_target:getHull() / comms_target:getHullMax() * 100) .. "%\n"
9425		local shields = comms_target:getShieldCount()
9426		if shields == 1 then
9427			msg = msg .. "Shield: " .. math.floor(comms_target:getShieldLevel(0) / comms_target:getShieldMax(0) * 100) .. "%\n"
9428		else
9429			for n=0,shields-1 do
9430				msg = msg .. "Shield " .. n .. ": " .. math.floor(comms_target:getShieldLevel(n) / comms_target:getShieldMax(n) * 100) .. "%\n"
9431			end
9432		end
9433		setCommsMessage(msg);
9434		addCommsReply("Back", return_function)
9435	end)
9436end
9437function completionConditions(return_function)
9438	addCommsReply("What ends the war?",function()
9439		local out = string.format("The war ends in one of three ways:\n1) Time runs out\n2) A faction drops below half of original score\n3) A faction either leads or trails the other factions by %i%%\n",thresh*100)
9440		local stat_list = gatherStats()
9441		out = out .. string.format("\nHuman Navy Current:%.1f Original:%.1f (%.2f%%)",stat_list.human.weighted_score,original_score["Human Navy"],(stat_list.human.weighted_score/original_score["Human Navy"])*100)
9442		out = out .. string.format("\nKraylor Current:%.1f Original:%.1f (%.2f%%)",stat_list.kraylor.weighted_score,original_score["Kraylor"],(stat_list.kraylor.weighted_score/original_score["Kraylor"])*100)
9443		if exuari_angle ~= nil then
9444			out = out .. string.format("\nExuari Current:%.1f Original:%.1f (%.2f%%)",stat_list.exuari.weighted_score,original_score["Exuari"],(stat_list.exuari.weighted_score/original_score["Exuari"])*100)
9445		end
9446		if ktlitan_angle ~= nil then
9447			out = out .. string.format("\nKtlitan Current:%.1f Original:%.1f (%.2f%%)",stat_list.ktlitan.weighted_score,original_score["Ktlitans"],(stat_list.ktlitan.weighted_score/original_score["Ktlitans"])*100)
9448		end
9449		out = out .. string.format("\n\nStation weight:%i%%   Player ship weight:%i%%   NPC weight:%i%%",stat_list.weight.station*100,stat_list.weight.ship*100,stat_list.weight.npc*100)
9450		setCommsMessage(out)
9451		addCommsReply(string.format("Station values (Total:%i)",stat_list[f2s[comms_source:getFaction()]].station_score_total),function()
9452			local out = "Stations: (value, type, name)"
9453			for name, details in pairs(stat_list[f2s[comms_source:getFaction()]].station) do
9454				out = out .. string.format("\n   %i, %s, %s",details.score_value,details.template_type,name)
9455			end
9456			out = out .. string.format("\nTotal:%i multiplied by weight (%i%%) = weighted total:%.1f",stat_list[f2s[comms_source:getFaction()]].station_score_total,stat_list.weight.station*100,stat_list[f2s[comms_source:getFaction()]].station_score_total*stat_list.weight.station)
9457			setCommsMessage(out)
9458			addCommsReply("Back", return_function)
9459		end)
9460		addCommsReply(string.format("Player ship values (Total:%i)",stat_list[f2s[comms_source:getFaction()]].ship_score_total),function()
9461			local out = "Player ships: (value, type, name)"
9462			for name, details in pairs(stat_list[f2s[comms_source:getFaction()]].ship) do
9463				out = out .. string.format("\n   %i, %s, %s",details.score_value,details.template_type,name)
9464			end
9465			out = out .. string.format("\nTotal:%i multiplied by weight (%i%%) = weighted total:%.1f",stat_list[f2s[comms_source:getFaction()]].ship_score_total,stat_list.weight.ship*100,stat_list[f2s[comms_source:getFaction()]].ship_score_total*stat_list.weight.ship)
9466			setCommsMessage(out)
9467			addCommsReply("Back", return_function)
9468		end)
9469		addCommsReply(string.format("NPC ship values (Total:%i)",stat_list[f2s[comms_source:getFaction()]].npc_score_total),function()
9470			local out = "NPC assets: value, type, name (location)"
9471			for name, details in pairs(stat_list[f2s[comms_source:getFaction()]].npc) do
9472				if details.template_type ~= nil then
9473					out = out .. string.format("\n   %i, %s, %s",details.score_value,details.template_type,name)
9474				elseif details.topic ~= nil then
9475					out = out .. string.format("\n   %i, %s, %s (%s)",details.score_value,details.topic,name,details.location_name)
9476				end
9477			end
9478			out = out .. string.format("\nTotal:%i multiplied by weight (%i%%) = weighted total:%.1f",stat_list[f2s[comms_source:getFaction()]].npc_score_total,stat_list.weight.npc*100,stat_list[f2s[comms_source:getFaction()]].npc_score_total*stat_list.weight.npc)
9479			setCommsMessage(out)
9480			addCommsReply("Back", return_function)
9481		end)
9482		addCommsReply("Back", return_function)
9483	end)
9484end
9485--	Undocked actions
9486function getServiceCost(service)
9487    return math.ceil(comms_data.service_cost[service])
9488end
9489function requestSupplyDrop(return_function)
9490	if isAllowedTo(comms_target.comms_data.services.supplydrop) then
9491        addCommsReply("Can you send a supply drop? ("..getServiceCost("supplydrop").."rep)", function()
9492            if comms_source:getWaypointCount() < 1 then
9493                setCommsMessage("You need to set a waypoint before you can request backup.");
9494            else
9495                setCommsMessage("To which waypoint should we deliver your supplies?");
9496                for n=1,comms_source:getWaypointCount() do
9497                    addCommsReply("WP" .. n, function()
9498						if comms_source:takeReputationPoints(getServiceCost("supplydrop")) then
9499							local position_x, position_y = comms_target:getPosition()
9500							local target_x, target_y = comms_source:getWaypoint(n)
9501							local script = Script()
9502							script:setVariable("position_x", position_x):setVariable("position_y", position_y)
9503							script:setVariable("target_x", target_x):setVariable("target_y", target_y)
9504							script:setVariable("faction_id", comms_target:getFactionId()):run("supply_drop.lua")
9505							setCommsMessage("We have dispatched a supply ship toward WP" .. n);
9506						else
9507							setCommsMessage("Not enough reputation!");
9508						end
9509                        addCommsReply("Back", return_function)
9510                    end)
9511                end
9512            end
9513            addCommsReply("Back", return_function)
9514        end)
9515    end
9516end
9517function requestJumpSupplyDrop(return_function)
9518	if isAllowedTo(comms_target.comms_data.services.jumpsupplydrop) then
9519        addCommsReply("Can you send a supply drop via jump ship? ("..getServiceCost("jumpsupplydrop").."rep)", function()
9520            if comms_source:getWaypointCount() < 1 then
9521                setCommsMessage("You need to set a waypoint before you can request backup.");
9522            else
9523                setCommsMessage("To which waypoint should we deliver your supplies?");
9524                for n=1,comms_source:getWaypointCount() do
9525                    addCommsReply("WP" .. n, function()
9526						if comms_source:takeReputationPoints(getServiceCost("jumpsupplydrop")) then
9527							local position_x, position_y = comms_target:getPosition()
9528							local target_x, target_y = comms_source:getWaypoint(n)
9529							local script = Script()
9530							script:setVariable("position_x", position_x):setVariable("position_y", position_y)
9531							script:setVariable("target_x", target_x):setVariable("target_y", target_y)
9532							script:setVariable("jump_freighter","Yes")
9533							script:setVariable("faction_id", comms_target:getFactionId()):run("supply_drop.lua")
9534							setCommsMessage("We have dispatched a supply ship with a jump drive toward WP" .. n);
9535						else
9536							setCommsMessage("Not enough reputation!");
9537						end
9538                        addCommsReply("Back", return_function)
9539                    end)
9540                end
9541            end
9542            addCommsReply("Back", return_function)
9543        end)
9544    end
9545end
9546function requestReinforcements(return_function)
9547    if isAllowedTo(comms_target.comms_data.services.reinforcements) then
9548    	addCommsReply("Please send reinforcements",function()
9549    		if comms_source:getWaypointCount() < 1 then
9550    			setCommsMessage("You need to set a waypoint before you can request reinforcements")
9551    		else
9552    			setCommsMessage("What kind of reinforcements would you like?")
9553    			addCommsReply(string.format("Standard Adder MK5 (%i Rep)",getServiceCost("reinforcements")),function()
9554    				if comms_source:getWaypointCount() < 1 then
9555    					setCommsMessage("You need to set a waypoint before you can request reinforcements")
9556    				else
9557		                setCommsMessage("To which waypoint should we dispatch the Adder MK5?");
9558    					for n=1,comms_source:getWaypointCount() do
9559    						addCommsReply("Waypoint " .. n, function()
9560								if comms_source:takeReputationPoints(getServiceCost("reinforcements")) then
9561									ship = CpuShip():setFactionId(comms_target:getFactionId()):setPosition(comms_target:getPosition()):setTemplate("Adder MK5"):setScanned(true):orderDefendLocation(comms_source:getWaypoint(n))
9562									ship:setCommsScript(""):setCommsFunction(commsShip)
9563									ship.score_value = ship_template["Adder MK5"].strength
9564									table.insert(npc_fleet[comms_target:getFaction()],ship)
9565									setCommsMessage("We have dispatched " .. ship:getCallSign() .. " to assist at waypoint " .. n);
9566								else
9567									setCommsMessage("Not enough reputation!");
9568								end
9569								addCommsReply("Back", return_function)
9570    						end)
9571    					end
9572    				end
9573    				addCommsReply("Back", return_function)
9574    			end)
9575    			if comms_data.service_cost.hornetreinforcements ~= nil then
9576					addCommsReply(string.format("MU52 Hornet (%i Rep)",getServiceCost("hornetreinforcements")),function()
9577						if comms_source:getWaypointCount() < 1 then
9578							setCommsMessage("You need to set a waypoint before you can request reinforcements")
9579						else
9580							setCommsMessage("To which waypoint should we dispatch the MU52 Hornet?");
9581							for n=1,comms_source:getWaypointCount() do
9582								addCommsReply("Waypoint " .. n, function()
9583									if comms_source:takeReputationPoints(getServiceCost("hornetreinforcements")) then
9584										ship = CpuShip():setFactionId(comms_target:getFactionId()):setPosition(comms_target:getPosition()):setTemplate("MU52 Hornet"):setScanned(true):orderDefendLocation(comms_source:getWaypoint(n))
9585										ship:setCommsScript(""):setCommsFunction(commsShip)
9586										ship.score_value = ship_template["MU52 Hornet"].strength
9587										table.insert(npc_fleet[comms_target:getFaction()],ship)
9588										setCommsMessage("We have dispatched " .. ship:getCallSign() .. " to assist at waypoint " .. n);
9589									else
9590										setCommsMessage("Not enough reputation!");
9591									end
9592									addCommsReply("Back", return_function)
9593								end)
9594							end
9595						end
9596						addCommsReply("Back", return_function)
9597					end)
9598				end
9599    			if comms_data.service_cost.phobosreinforcements ~= nil then
9600					addCommsReply(string.format("Phobos T3 (%i Rep)",getServiceCost("phobosreinforcements")),function()
9601						if comms_source:getWaypointCount() < 1 then
9602							setCommsMessage("You need to set a waypoint before you can request reinforcements")
9603						else
9604							setCommsMessage("To which waypoint should we dispatch the Phobos T3?");
9605							for n=1,comms_source:getWaypointCount() do
9606								addCommsReply("Waypoint " .. n, function()
9607									if comms_source:takeReputationPoints(getServiceCost("phobosreinforcements")) then
9608										ship = CpuShip():setFactionId(comms_target:getFactionId()):setPosition(comms_target:getPosition()):setTemplate("Phobos T3"):setScanned(true):orderDefendLocation(comms_source:getWaypoint(n))
9609										ship:setCommsScript(""):setCommsFunction(commsShip)
9610										ship.score_value = ship_template["Phobos T3"].strength
9611										table.insert(npc_fleet[comms_target:getFaction()],ship)
9612										setCommsMessage("We have dispatched " .. ship:getCallSign() .. " to assist at waypoint " .. n);
9613									else
9614										setCommsMessage("Not enough reputation!");
9615									end
9616									addCommsReply("Back", return_function)
9617								end)
9618							end
9619						end
9620						addCommsReply("Back", return_function)
9621					end)
9622				end
9623    		end
9624            addCommsReply("Back", return_function)
9625    	end)
9626    end
9627end
9628function ordnanceAvailability(return_function)
9629	addCommsReply("What ordnance do you have available for restock?", function()
9630		local missileTypeAvailableCount = 0
9631		local ordnanceListMsg = ""
9632		if comms_target.comms_data.weapon_available.Homing and (comms_target.comms_data.weapon_inventory.Unlimited or comms_target.comms_data.weapon_inventory.Homing > 0) then
9633			missileTypeAvailableCount = missileTypeAvailableCount + 1
9634			ordnanceListMsg = ordnanceListMsg .. "\n   Homing"
9635			if not comms_target.comms_data.weapon_inventory.Unlimited then
9636				ordnanceListMsg = ordnanceListMsg .. string.format("(%i)",math.floor(comms_target.comms_data.weapon_inventory.Homing))
9637			end
9638		end
9639		if comms_target.comms_data.weapon_available.Nuke and (comms_target.comms_data.weapon_inventory.Unlimited or comms_target.comms_data.weapon_inventory.Nuke > 0) then
9640			missileTypeAvailableCount = missileTypeAvailableCount + 1
9641			ordnanceListMsg = ordnanceListMsg .. "\n   Nuke"
9642			if not comms_target.comms_data.weapon_inventory.Unlimited then
9643				ordnanceListMsg = ordnanceListMsg .. string.format("(%i)",math.floor(comms_target.comms_data.weapon_inventory.Nuke))
9644			end
9645		end
9646		if comms_target.comms_data.weapon_available.Mine and (comms_target.comms_data.weapon_inventory.Unlimited or comms_target.comms_data.weapon_inventory.Mine > 0) then
9647			missileTypeAvailableCount = missileTypeAvailableCount + 1
9648			ordnanceListMsg = ordnanceListMsg .. "\n   Mine"
9649			if not comms_target.comms_data.weapon_inventory.Unlimited then
9650				ordnanceListMsg = ordnanceListMsg .. string.format("(%i)",math.floor(comms_target.comms_data.weapon_inventory.Mine))
9651			end
9652		end
9653		if comms_target.comms_data.weapon_available.EMP and (comms_target.comms_data.weapon_inventory.Unlimited or comms_target.comms_data.weapon_inventory.EMP > 0) then
9654			missileTypeAvailableCount = missileTypeAvailableCount + 1
9655			ordnanceListMsg = ordnanceListMsg .. "\n   EMP"
9656			if not comms_target.comms_data.weapon_inventory.Unlimited then
9657				ordnanceListMsg = ordnanceListMsg .. string.format("(%i)",math.floor(comms_target.comms_data.weapon_inventory.EMP))
9658			end
9659		end
9660		if comms_target.comms_data.weapon_available.HVLI and (comms_target.comms_data.weapon_inventory.Unlimited or comms_target.comms_data.weapon_inventory.HVLI > 0) then
9661			missileTypeAvailableCount = missileTypeAvailableCount + 1
9662			ordnanceListMsg = ordnanceListMsg .. "\n   HVLI"
9663			if not comms_target.comms_data.weapon_inventory.Unlimited then
9664				ordnanceListMsg = ordnanceListMsg .. string.format("(%i)",math.floor(comms_target.comms_data.weapon_inventory.HVLI))
9665			end
9666		end
9667		if missileTypeAvailableCount == 0 then
9668			ordnanceListMsg = "We have no ordnance available for restock"
9669		elseif missileTypeAvailableCount == 1 then
9670			ordnanceListMsg = "We have the following type of ordnance available for restock:" .. ordnanceListMsg
9671		else
9672			ordnanceListMsg = "We have the following types of ordnance available for restock:" .. ordnanceListMsg
9673		end
9674		setCommsMessage(ordnanceListMsg)
9675		addCommsReply("Back", return_function)
9676	end)
9677end
9678function goodsAvailabilityOnStation(return_function)
9679	local goodsAvailable = false
9680	if comms_target.comms_data.goods ~= nil then
9681		for good, goodData in pairs(comms_target.comms_data.goods) do
9682			if goodData["quantity"] > 0 then
9683				goodsAvailable = true
9684			end
9685		end
9686	end
9687	if goodsAvailable then
9688		addCommsReply("What goods do you have available for sale or trade?", function()
9689			local goodsAvailableMsg = string.format("Station %s:\nGoods or components available: quantity, cost in reputation",comms_target:getCallSign())
9690			for good, goodData in pairs(comms_target.comms_data.goods) do
9691				goodsAvailableMsg = goodsAvailableMsg .. string.format("\n   %14s: %2i, %3i",good,goodData["quantity"],goodData["cost"])
9692			end
9693			setCommsMessage(goodsAvailableMsg)
9694			addCommsReply("Back", return_function)
9695		end)
9696	end
9697end
9698function expediteDock(return_function)
9699	if isAllowedTo(comms_target.comms_data.services.preorder) then
9700		addCommsReply("Expedite Dock",function()
9701			if comms_source.expedite_dock == nil then
9702				comms_source.expedite_dock = false
9703			end
9704			if comms_source.expedite_dock then
9705				--handle expedite request already present
9706				local existing_expedite = "Docking crew is standing by"
9707				if comms_target == comms_source.expedite_dock_station then
9708					existing_expedite = existing_expedite .. ". Current preorders:"
9709					local preorders_identified = false
9710					if comms_source.preorder_hvli ~= nil then
9711						preorders_identified = true
9712						existing_expedite = existing_expedite .. string.format("\n   HVLIs: %i",comms_source.preorder_hvli)
9713					end
9714					if comms_source.preorder_homing ~= nil then
9715						preorders_identified = true
9716						existing_expedite = existing_expedite .. string.format("\n   Homings: %i",comms_source.preorder_homing)
9717					end
9718					if comms_source.preorder_mine ~= nil then
9719						preorders_identified = true
9720						existing_expedite = existing_expedite .. string.format("\n   Mines: %i",comms_source.preorder_mine)
9721					end
9722					if comms_source.preorder_emp ~= nil then
9723						preorders_identified = true
9724						existing_expedite = existing_expedite .. string.format("\n   EMPs: %i",comms_source.preorder_emp)
9725					end
9726					if comms_source.preorder_nuke ~= nil then
9727						preorders_identified = true
9728						existing_expedite = existing_expedite .. string.format("\n   Nukes: %i",comms_source.preorder_nuke)
9729					end
9730					if comms_source.preorder_repair_crew ~= nil then
9731						preorders_identified = true
9732						existing_expedite = existing_expedite .. "\n   One repair crew"
9733					end
9734					if comms_source.preorder_coolant ~= nil then
9735						preorders_identified = true
9736						existing_expedite = existing_expedite .. "\n   Coolant"
9737					end
9738					if preorders_identified then
9739						existing_expedite = existing_expedite .. "\nWould you like to preorder anything else?"
9740					else
9741						existing_expedite = existing_expedite .. " none.\nWould you like to preorder anything?"
9742					end
9743					preorder_message = existing_expedite
9744					preOrderOrdnance(return_function)
9745				else
9746					existing_expedite = existing_expedite .. string.format(" on station %s (not this station, %s).",comms_source.expedite_dock_station:getCallSign(),comms_target:getCallSign())
9747					setCommsMessage(existing_expedite)
9748				end
9749				addCommsReply("Back",return_function)
9750			else
9751				setCommsMessage("If you would like to speed up the addition of resources such as energy, ordnance, etc., please provide a time frame for your arrival. A docking crew will stand by until that time, after which they will return to their normal duties")
9752				preorder_message = "Docking crew is standing by. Would you like to pre-order anything?"
9753				addCommsReply("One minute (5 rep)", function()
9754					if comms_source:takeReputationPoints(5) then
9755						comms_source.expedite_dock = true
9756						comms_source.expedite_dock_station = comms_target
9757						comms_source.expedite_dock_timer_max = 60
9758						preOrderOrdnance(return_function)
9759					else
9760						setCommsMessage("Insufficient reputation")
9761					end
9762					addCommsReply("Back", return_function)
9763				end)
9764				addCommsReply("Two minutes (10 Rep)", function()
9765					if comms_source:takeReputationPoints(10) then
9766						comms_source.expedite_dock = true
9767						comms_source.expedite_dock_station = comms_target
9768						comms_source.expedite_dock_timer_max = 120
9769						preOrderOrdnance(return_function)
9770					else
9771						setCommsMessage("Insufficient reputation")
9772					end
9773					addCommsReply("Back", return_function)
9774				end)
9775				addCommsReply("Three minutes (15 Rep)", function()
9776					if comms_source:takeReputationPoints(15) then
9777						comms_source.expedite_dock = true
9778						comms_source.expedite_dock_station = comms_target
9779						comms_source.expedite_dock_timer_max = 180
9780						preOrderOrdnance(return_function)
9781					else
9782						setCommsMessage("Insufficient reputation")
9783					end
9784					addCommsReply("Back", return_function)
9785				end)
9786			end
9787			addCommsReply("Back", return_function)
9788		end)
9789	end
9790end
9791function preOrderOrdnance(return_function)
9792	setCommsMessage(preorder_message)
9793	local hvli_count = math.floor(comms_source:getWeaponStorageMax("HVLI") * comms_target.comms_data.max_weapon_refill_amount[getFriendStatus()]) - comms_source:getWeaponStorage("HVLI")
9794	if comms_target.comms_data.weapon_available.HVLI and isAllowedTo(comms_target.comms_data.weapons["HVLI"]) and hvli_count > 0 then
9795		local hvli_prompt = ""
9796		local hvli_cost = getWeaponCost("HVLI")
9797		if hvli_count > 1 then
9798			hvli_prompt = string.format("%i HVLIs * %i Rep = %i Rep",hvli_count,hvli_cost,hvli_count*hvli_cost)
9799		else
9800			hvli_prompt = string.format("%i HVLI * %i Rep = %i Rep",hvli_count,hvli_cost,hvli_count*hvli_cost)
9801		end
9802		addCommsReply(hvli_prompt,function()
9803			if comms_source:takeReputationPoints(hvli_count*hvli_cost) then
9804				comms_source.preorder_hvli = hvli_count
9805				if hvli_count > 1 then
9806					setCommsMessage(string.format("%i HVLIs preordered",hvli_count))
9807				else
9808					setCommsMessage(string.format("%i HVLI preordered",hvli_count))
9809				end
9810			else
9811				setCommsMessage("Insufficient reputation")
9812			end
9813			preorder_message = "Docking crew is standing by. Would you like to pre-order anything?"
9814			addCommsReply("Back",return_function)
9815		end)
9816	end
9817	local homing_count = math.floor(comms_source:getWeaponStorageMax("Homing") * comms_target.comms_data.max_weapon_refill_amount[getFriendStatus()]) - comms_source:getWeaponStorage("Homing")
9818	if comms_target.comms_data.weapon_available.Homing and isAllowedTo(comms_target.comms_data.weapons["Homing"]) and homing_count > 0 then
9819		local homing_prompt = ""
9820		local homing_cost = getWeaponCost("Homing")
9821		if homing_count > 1 then
9822			homing_prompt = string.format("%i Homings * %i Rep = %i Rep",homing_count,homing_cost,homing_count*homing_cost)
9823		else
9824			homing_prompt = string.format("%i Homing * %i Rep = %i Rep",homing_count,homing_cost,homing_count*homing_cost)
9825		end
9826		addCommsReply(homing_prompt,function()
9827			if comms_source:takeReputationPoints(homing_count*homing_cost) then
9828				comms_source.preorder_homing = homing_count
9829				if homing_count > 1 then
9830					setCommsMessage(string.format("%i Homings preordered",homing_count))
9831				else
9832					setCommsMessage(string.format("%i Homing preordered",homing_count))
9833				end
9834			else
9835				setCommsMessage("Insufficient reputation")
9836			end
9837			preorder_message = "Docking crew is standing by. Would you like to pre-order anything?"
9838			addCommsReply("Back",return_function)
9839		end)
9840	end
9841	local mine_count = math.floor(comms_source:getWeaponStorageMax("Mine") * comms_target.comms_data.max_weapon_refill_amount[getFriendStatus()]) - comms_source:getWeaponStorage("Mine")
9842	if comms_target.comms_data.weapon_available.Mine and isAllowedTo(comms_target.comms_data.weapons["Mine"]) and mine_count > 0 then
9843		local mine_prompt = ""
9844		local mine_cost = getWeaponCost("Mine")
9845		if mine_count > 1 then
9846			mine_prompt = string.format("%i Mines * %i Rep = %i Rep",mine_count,mine_cost,mine_count*mine_cost)
9847		else
9848			mine_prompt = string.format("%i Mine * %i Rep = %i Rep",mine_count,mine_cost,mine_count*mine_cost)
9849		end
9850		addCommsReply(mine_prompt,function()
9851			if comms_source:takeReputationPoints(mine_count*mine_cost) then
9852				comms_source.preorder_mine = mine_count
9853				if mine_count > 1 then
9854					setCommsMessage(string.format("%i Mines preordered",mine_count))
9855				else
9856					setCommsMessage(string.format("%i Mine preordered",mine_count))
9857				end
9858			else
9859				setCommsMessage("Insufficient reputation")
9860			end
9861			preorder_message = "Docking crew is standing by. Would you like to pre-order anything?"
9862			addCommsReply("Back",return_function)
9863		end)
9864	end
9865	local emp_count = math.floor(comms_source:getWeaponStorageMax("EMP") * comms_target.comms_data.max_weapon_refill_amount[getFriendStatus()]) - comms_source:getWeaponStorage("EMP")
9866	if comms_target.comms_data.weapon_available.EMP and isAllowedTo(comms_target.comms_data.weapons["EMP"]) and emp_count > 0 then
9867		local emp_prompt = ""
9868		local emp_cost = getWeaponCost("EMP")
9869		if emp_count > 1 then
9870			emp_prompt = string.format("%i EMPs * %i Rep = %i Rep",emp_count,emp_cost,emp_count*emp_cost)
9871		else
9872			emp_prompt = string.format("%i EMP * %i Rep = %i Rep",emp_count,emp_cost,emp_count*emp_cost)
9873		end
9874		addCommsReply(emp_prompt,function()
9875			if comms_source:takeReputationPoints(emp_count*emp_cost) then
9876				comms_source.preorder_emp = emp_count
9877				if emp_count > 1 then
9878					setCommsMessage(string.format("%i EMPs preordered",emp_count))
9879				else
9880					setCommsMessage(string.format("%i EMP preordered",emp_count))
9881				end
9882			else
9883				setCommsMessage("Insufficient reputation")
9884			end
9885			preorder_message = "Docking crew is standing by. Would you like to pre-order anything?"
9886			addCommsReply("Back",return_function)
9887		end)
9888	end
9889	local nuke_count = math.floor(comms_source:getWeaponStorageMax("Nuke") * comms_target.comms_data.max_weapon_refill_amount[getFriendStatus()]) - comms_source:getWeaponStorage("Nuke")
9890	if comms_target.comms_data.weapon_available.Nuke and isAllowedTo(comms_target.comms_data.weapons["Nuke"]) and nuke_count > 0 then
9891		local nuke_prompt = ""
9892		local nuke_cost = getWeaponCost("Nuke")
9893		if nuke_count > 1 then
9894			nuke_prompt = string.format("%i Nukes * %i Rep = %i Rep",nuke_count,nuke_cost,nuke_count*nuke_cost)
9895		else
9896			nuke_prompt = string.format("%i Nuke * %i Rep = %i Rep",nuke_count,nuke_cost,nuke_count*nuke_cost)
9897		end
9898		addCommsReply(nuke_prompt,function()
9899			if comms_source:takeReputationPoints(nuke_count*nuke_cost) then
9900				comms_source.preorder_nuke = nuke_count
9901				if nuke_count > 1 then
9902					setCommsMessage(string.format("%i Nukes preordered",nuke_count))
9903				else
9904					setCommsMessage(string.format("%i Nuke preordered",nuke_count))
9905				end
9906			else
9907				setCommsMessage("Insufficient reputation")
9908			end
9909			preorder_message = "Docking crew is standing by. Would you like to pre-order anything?"
9910			addCommsReply("Back",return_function)
9911		end)
9912	end
9913	if comms_source.preorder_repair_crew == nil then
9914		if random(1,100) <= 20 then
9915			if comms_source:isFriendly(comms_target) then
9916				if comms_source:getRepairCrewCount() < comms_source.maxRepairCrew then
9917					hireCost = math.random(30,60)
9918				else
9919					hireCost = math.random(45,90)
9920				end
9921				addCommsReply(string.format("Recruit repair crew member for %i reputation",hireCost), function()
9922					if not comms_source:takeReputationPoints(hireCost) then
9923						setCommsMessage("Insufficient reputation")
9924					else
9925						comms_source.preorder_repair_crew = 1
9926						setCommsMessage("Repair crew hired on your behalf. They will board when you dock")
9927					end
9928					preorder_message = "Docking crew is standing by. Would you like to pre-order anything?"
9929					addCommsReply("Back",return_function)
9930				end)
9931			end
9932		end
9933	end
9934	if comms_source.preorder_coolant == nil then
9935		if random(1,100) <= 20 then
9936			if comms_source:isFriendly(comms_target) then
9937				if comms_source.initialCoolant ~= nil then
9938					local coolant_cost = math.random(45,90)
9939					if comms_source:getMaxCoolant() < comms_source.initialCoolant then
9940						coolant_cost = math.random(30,60)
9941					end
9942					addCommsReply(string.format("Set aside coolant for %i reputation",coolant_cost), function()
9943						if comms_source:takeReputationPoints(coolant_cost) then
9944							comms_source.preorder_coolant = 2
9945							setCommsMessage("Coolant set aside for you. It will be loaded when you dock")
9946						else
9947							setCommsMessage("Insufficient reputation")
9948						end
9949						preorder_message = "Docking crew is standing by. Would you like to pre-order anything?"
9950						addCommsReply("Back",return_function)
9951					end)
9952				end
9953			end
9954		end
9955	end
9956end
9957function activateDefenseFleet(return_function)
9958    if isAllowedTo(comms_target.comms_data.services.activatedefensefleet) and
9959    	comms_target.comms_data.idle_defense_fleet ~= nil then
9960    	local defense_fleet_count = 0
9961    	for name, template in pairs(comms_target.comms_data.idle_defense_fleet) do
9962    		defense_fleet_count = defense_fleet_count + 1
9963    	end
9964    	if defense_fleet_count > 0 then
9965    		addCommsReply("Activate station defense fleet (" .. getServiceCost("activatedefensefleet") .. " rep)",function()
9966    			if comms_source:takeReputationPoints(getServiceCost("activatedefensefleet")) then
9967    				local out = string.format("%s defense fleet\n",comms_target:getCallSign())
9968    				for name, template in pairs(comms_target.comms_data.idle_defense_fleet) do
9969    					local script = Script()
9970						local position_x, position_y = comms_target:getPosition()
9971						local station_name = comms_target:getCallSign()
9972						script:setVariable("position_x", position_x):setVariable("position_y", position_y)
9973						script:setVariable("station_name",station_name)
9974    					script:setVariable("name",name)
9975    					script:setVariable("template",template)
9976    					script:setVariable("faction_id",comms_target:getFactionId())
9977    					script:run("border_defend_station.lua")
9978    					out = out .. " " .. name
9979    					comms_target.comms_data.idle_defense_fleet[name] = nil
9980    				end
9981    				out = out .. "\nactivated"
9982    				setCommsMessage(out)
9983    			else
9984    				setCommsMessage("Insufficient reputation")
9985    			end
9986				addCommsReply("Back", return_function)
9987    		end)
9988		end
9989    end
9990end
9991--	Docked actions
9992function restockOrdnance(return_function)
9993	local missilePresence = 0
9994	local missile_types = {'Homing', 'Nuke', 'Mine', 'EMP', 'HVLI'}
9995	for _, missile_type in ipairs(missile_types) do
9996		missilePresence = missilePresence + comms_source:getWeaponStorageMax(missile_type)
9997	end
9998	if missilePresence > 0 then
9999		if 	(comms_target.comms_data.weapon_available.Nuke   and comms_source:getWeaponStorageMax("Nuke")	> 0)	and (comms_target.comms_data.weapon_inventory.Unlimited or comms_target.comms_data.weapon_inventory.Nuke	> 0) or
10000			(comms_target.comms_data.weapon_available.EMP    and comms_source:getWeaponStorageMax("EMP")	> 0)	and (comms_target.comms_data.weapon_inventory.Unlimited or comms_target.comms_data.weapon_inventory.EMP		> 0) or
10001			(comms_target.comms_data.weapon_available.Homing and comms_source:getWeaponStorageMax("Homing")	> 0)	and (comms_target.comms_data.weapon_inventory.Unlimited or comms_target.comms_data.weapon_inventory.Homing	> 0) or
10002			(comms_target.comms_data.weapon_available.Mine   and comms_source:getWeaponStorageMax("Mine")	> 0)   	and (comms_target.comms_data.weapon_inventory.Unlimited or comms_target.comms_data.weapon_inventory.Mine	> 0) or
10003			(comms_target.comms_data.weapon_available.HVLI   and comms_source:getWeaponStorageMax("HVLI")	> 0)	and (comms_target.comms_data.weapon_inventory.Unlimited or comms_target.comms_data.weapon_inventory.HVLI	> 0) then
10004			addCommsReply("I need ordnance restocked", function()
10005				setCommsMessage("What type of ordnance?")
10006				if comms_source:getWeaponStorageMax("Nuke") > 0 and (comms_target.comms_data.weapon_inventory.Unlimited or comms_target.comms_data.weapon_inventory.Nuke > 0) then
10007					if comms_target.comms_data.weapon_available.Nuke then
10008						local ask = {"Can you supply us with some nukes?","We really need some nukes."}
10009						local avail = ""
10010						if not comms_target.comms_data.weapon_inventory.Unlimited then
10011							avail = string.format(", %i avail",math.floor(comms_target.comms_data.weapon_inventory.Nuke))
10012						end
10013						local nuke_prompt = string.format("%s (%i rep each%s)",ask[math.random(1,#ask)],getWeaponCost("Nuke"),avail)
10014						addCommsReply(nuke_prompt, function()
10015							handleWeaponRestock("Nuke",return_function)
10016						end)
10017					end	--end station has nuke available if branch
10018				end	--end player can accept nuke if branch
10019				if comms_source:getWeaponStorageMax("EMP") > 0 and (comms_target.comms_data.weapon_inventory.Unlimited or comms_target.comms_data.weapon_inventory.EMP > 0) then
10020					if comms_target.comms_data.weapon_available.EMP then
10021						local ask = {"Please re-stock our EMP missiles.","Got any EMPs?"}
10022						local avail = ""
10023						if not comms_target.comms_data.weapon_inventory.Unlimited then
10024							avail = string.format(", %i avail",math.floor(comms_target.comms_data.weapon_inventory.EMP))
10025						end
10026						local emp_prompt = string.format("%s (%i rep each%s)",ask[math.random(1,#ask)],getWeaponCost("EMP"),avail)
10027						addCommsReply(emp_prompt, function()
10028							handleWeaponRestock("EMP",return_function)
10029						end)
10030					end	--end station has EMP available if branch
10031				end	--end player can accept EMP if branch
10032				if comms_source:getWeaponStorageMax("Homing") > 0 and (comms_target.comms_data.weapon_inventory.Unlimited or comms_target.comms_data.weapon_inventory.Homing > 0) then
10033					if comms_target.comms_data.weapon_available.Homing then
10034						local ask = {"Do you have spare homing missiles for us?","Do you have extra homing missiles?"}
10035						local avail = ""
10036						if not comms_target.comms_data.weapon_inventory.Unlimited then
10037							avail = string.format(", %i avail",math.floor(comms_target.comms_data.weapon_inventory.Homing))
10038						end
10039						local homing_prompt = string.format("%s (%i rep each%s)",ask[math.random(1,#ask)],getWeaponCost("Homing"),avail)
10040						addCommsReply(homing_prompt, function()
10041							handleWeaponRestock("Homing",return_function)
10042						end)
10043					end	--end station has homing for player if branch
10044				end	--end player can accept homing if branch
10045				if comms_source:getWeaponStorageMax("Mine") > 0 and (comms_target.comms_data.weapon_inventory.Unlimited or comms_target.comms_data.weapon_inventory.Mine > 0) then
10046					if comms_target.comms_data.weapon_available.Mine then
10047						local ask = {"We could use some mines.","How about mines?"}
10048						local avail = ""
10049						if not comms_target.comms_data.weapon_inventory.Unlimited then
10050							avail = string.format(", %i avail",math.floor(comms_target.comms_data.weapon_inventory.Mine))
10051						end
10052						local mine_prompt = string.format("%s (%i rep each%s)",ask[math.random(1,#ask)],getWeaponCost("Mine"),avail)
10053						addCommsReply(mine_prompt, function()
10054							handleWeaponRestock("Mine",return_function)
10055						end)
10056					end	--end station has mine for player if branch
10057				end	--end player can accept mine if branch
10058				if comms_source:getWeaponStorageMax("HVLI") > 0 and (comms_target.comms_data.weapon_inventory.Unlimited or comms_target.comms_data.weapon_inventory.HVLI > 0) then
10059					if comms_target.comms_data.weapon_available.HVLI then
10060						local ask = {"What about HVLI?","Could you provide HVLI?"}
10061						local avail = ""
10062						if not comms_target.comms_data.weapon_inventory.Unlimited then
10063							avail = string.format(", %i avail",math.floor(comms_target.comms_data.weapon_inventory.HVLI))
10064						end
10065						local hvli_prompt = string.format("%s (%i rep each%s)",ask[math.random(1,#ask)],getWeaponCost("HVLI"),avail)
10066						addCommsReply(hvli_prompt, function()
10067							handleWeaponRestock("HVLI",return_function)
10068						end)
10069					end	--end station has HVLI for player if branch
10070				end	--end player can accept HVLI if branch
10071			end)	--end player requests secondary ordnance comms reply branch
10072		end	--end secondary ordnance available from station if branch
10073	end	--end missles used on player ship if branch
10074end
10075function repairSubsystems(return_function)
10076	local offer_repair = false
10077	if comms_target.comms_data.probe_launch_repair and not comms_source:getCanLaunchProbe() then
10078		offer_repair = true
10079	end
10080	if not offer_repair and comms_target.comms_data.hack_repair and not comms_source:getCanHack() then
10081		offer_repair = true
10082	end
10083	if not offer_repair and comms_target.comms_data.scan_repair and not comms_source:getCanScan() then
10084		offer_repair = true
10085	end
10086	if not offer_repair and comms_target.comms_data.combat_maneuver_repair and not comms_source:getCanCombatManeuver() then
10087		offer_repair = true
10088	end
10089	if not offer_repair and comms_target.comms_data.self_destruct_repair and not comms_source:getCanSelfDestruct() then
10090		offer_repair = true
10091	end
10092	if not offer_repair and comms_target.comms_data.tube_slow_down_repair then
10093		local tube_load_time_slowed = false
10094		if comms_source.normal_tube_load_time ~= nil then
10095			local tube_count = comms_source:getWeaponTubeCount()
10096			if tube_count > 0 then
10097				local tube_index = 0
10098				repeat
10099					if comms_source.normal_tube_load_time[tube_index] ~= comms_source:getTubeLoadTime(tube_index) then
10100						tube_load_time_slowed = true
10101						break
10102					end
10103					tube_index = tube_index + 1
10104				until(tube_index >= tube_count)
10105			end
10106		end
10107		if tube_load_time_slowed then
10108			offer_repair = true
10109		end
10110	end
10111	if offer_repair then
10112		addCommsReply("Repair ship system",function()
10113			setCommsMessage("What system would you like repaired?")
10114			if comms_target.comms_data.probe_launch_repair then
10115				if not comms_source:getCanLaunchProbe() then
10116					addCommsReply("Repair probe launch system (5 Rep)",function()
10117						if comms_source:takeReputationPoints(5) then
10118							comms_source:setCanLaunchProbe(true)
10119							setCommsMessage("Your probe launch system has been repaired")
10120						else
10121							setCommsMessage("Insufficient reputation")
10122						end
10123						addCommsReply("Back", return_function)
10124					end)
10125				end
10126			end
10127			if comms_target.comms_data.hack_repair then
10128				if not comms_source:getCanHack() then
10129					addCommsReply("Repair hacking system (5 Rep)",function()
10130						if comms_source:takeReputationPoints(5) then
10131							comms_source:setCanHack(true)
10132							setCommsMessage("Your hack system has been repaired")
10133						else
10134							setCommsMessage("Insufficient reputation")
10135						end
10136						addCommsReply("Back", return_function)
10137					end)
10138				end
10139			end
10140			if comms_target.comms_data.scan_repair then
10141				if not comms_source:getCanScan() then
10142					addCommsReply("Repair scanners (5 Rep)",function()
10143						if comms_source:takeReputationPoints(5) then
10144							comms_source:setCanScan(true)
10145							setCommsMessage("Your scanners have been repaired")
10146						else
10147							setCommsMessage("Insufficient reputation")
10148						end
10149						addCommsReply("Back", return_function)
10150					end)
10151				end
10152			end
10153			if comms_target.comms_data.combat_maneuver_repair then
10154				if not comms_source:getCanCombatManeuver() then
10155					addCommsReply("Repair combat maneuver (5 Rep)",function()
10156						if comms_source:takeReputationPoints(5) then
10157							comms_source:setCanCombatManeuver(true)
10158							setCommsMessage("Your combat maneuver has been repaired")
10159						else
10160							setCommsMessage("Insufficient reputation")
10161						end
10162						addCommsReply("Back", return_function)
10163					end)
10164				end
10165			end
10166			if comms_target.comms_data.self_destruct_repair then
10167				if not comms_source:getCanSelfDestruct() then
10168					addCommsReply("Repair self destruct system (5 Rep)",function()
10169						if comms_source:takeReputationPoints(5) then
10170							comms_source:setCanSelfDestruct(true)
10171							setCommsMessage("Your self destruct system has been repaired")
10172						else
10173							setCommsMessage("Insufficient reputation")
10174						end
10175						addCommsReply("Back", return_function)
10176					end)
10177				end
10178			end
10179			if comms_target.comms_data.tube_slow_down_repair then
10180				local tube_load_time_slowed = false
10181				if comms_source.normal_tube_load_time ~= nil then
10182					local tube_count = comms_source:getWeaponTubeCount()
10183					if tube_count > 0 then
10184						local tube_index = 0
10185						repeat
10186							if comms_source.normal_tube_load_time[tube_index] ~= comms_source:getTubeLoadTime(tube_index) then
10187								tube_load_time_slowed = true
10188								break
10189							end
10190							tube_index = tube_index + 1
10191						until(tube_index >= tube_count)
10192					end
10193				end
10194				if tube_load_time_slowed then
10195					addCommsReply("Repair slow tube loading (5 Rep)",function()
10196						if comms_source:takeReputationPoints(5) then
10197							local tube_count = comms_source:getWeaponTubeCount()
10198							local tube_index = 0
10199							repeat
10200								comms_source:setTubeLoadTime(tube_index,comms_source.normal_tube_load_time[tube_index])
10201								tube_index = tube_index + 1
10202							until(tube_index >= tube_count)
10203							setCommsMessage("Your tube load times have been returned to normal")
10204						else
10205							setCommsMessage("Insufficient reputation")
10206						end
10207						addCommsReply("Back", return_function)
10208					end)
10209				end
10210			end
10211			addCommsReply("Back", return_function)
10212		end)
10213	end
10214end
10215function handleWeaponRestock(weapon, return_function)
10216    if not comms_source:isDocked(comms_target) then
10217		setCommsMessage("You need to stay docked for that action.")
10218		return
10219	end
10220    if not isAllowedTo(comms_data.weapons[weapon]) then
10221        if weapon == "Nuke" then setCommsMessage("We do not deal in weapons of mass destruction.")
10222        elseif weapon == "EMP" then setCommsMessage("We do not deal in weapons of mass disruption.")
10223        else setCommsMessage("We do not deal in those weapons.") end
10224        return
10225    end
10226    local points_per_item = getWeaponCost(weapon)
10227    local item_amount = math.floor(comms_source:getWeaponStorageMax(weapon) * comms_data.max_weapon_refill_amount[getFriendStatus()]) - comms_source:getWeaponStorage(weapon)
10228    if item_amount <= 0 then
10229        if weapon == "Nuke" then
10230            setCommsMessage("All nukes are charged and primed for destruction.");
10231        else
10232            setCommsMessage("Sorry, sir, but you are as fully stocked as I can allow.");
10233        end
10234        addCommsReply("Back", return_function)
10235    else
10236		local inventory_status = ""
10237		if comms_source:getReputationPoints() > points_per_item * item_amount and (comms_target.comms_data.weapon_inventory.Unlimited or comms_target.comms_data.weapon_inventory[weapon] >= item_amount) then
10238			if comms_source:takeReputationPoints(points_per_item * item_amount) then
10239				comms_source:setWeaponStorage(weapon, comms_source:getWeaponStorage(weapon) + item_amount)
10240				if not comms_target.comms_data.weapon_inventory.Unlimited then
10241					comms_target.comms_data.weapon_inventory[weapon] = comms_target.comms_data.weapon_inventory[weapon] - item_amount
10242					inventory_status = string.format("\nStation inventory of %s type weapons reduced to %i",weapon,math.floor(comms_target.comms_data.weapon_inventory[weapon]))
10243				end
10244				if comms_source:getWeaponStorage(weapon) == comms_source:getWeaponStorageMax(weapon) then
10245					setCommsMessage("You are fully loaded and ready to explode things." .. inventory_status)
10246				else
10247					setCommsMessage("We generously resupplied you with some weapon charges.\nPut them to good use." .. inventory_status)
10248				end
10249			else
10250				setCommsMessage("Not enough reputation.")
10251				return
10252			end
10253		else
10254			if comms_source:getReputationPoints() > points_per_item then
10255				setCommsMessage("Either you can't afford as much as I'd like to give you, or I don't have enough to fully restock you.")
10256				addCommsReply("Get just one", function()
10257					if comms_source:takeReputationPoints(points_per_item) then
10258						comms_source:setWeaponStorage(weapon, comms_source:getWeaponStorage(weapon) + 1)
10259						if not comms_target.comms_data.weapon_inventory.Unlimited then
10260							comms_target.comms_data.weapon_inventory[weapon] = comms_target.comms_data.weapon_inventory[weapon] - 1
10261							inventory_status = string.format("\nStation inventory of %s type weapons reduced to %i",weapon,math.floor(comms_target.comms_data.weapon_inventory[weapon]))
10262						end
10263						if comms_source:getWeaponStorage(weapon) == comms_source:getWeaponStorageMax(weapon) then
10264							setCommsMessage("You are fully loaded and ready to explode things." .. inventory_status)
10265						else
10266							setCommsMessage("We generously resupplied you with one weapon charge.\nPut it to good use." .. inventory_status)
10267						end
10268					else
10269						setCommsMessage("Not enough reputation.")
10270					end
10271					return
10272				end)
10273			else
10274				setCommsMessage("Not enough reputation.")
10275				return
10276			end
10277		end
10278        addCommsReply("Back", return_function)
10279    end
10280end
10281function buySellTrade(return_function)
10282	local goodCount = 0
10283	if comms_target.comms_data.goods == nil then
10284		return
10285	end
10286	for good, goodData in pairs(comms_target.comms_data.goods) do
10287		goodCount = goodCount + 1
10288	end
10289	if goodCount > 0 then
10290		addCommsReply("Buy, sell, trade", function()
10291			local goodsReport = string.format("Station %s:\nGoods or components available for sale: quantity, cost in reputation\n",comms_target:getCallSign())
10292			for good, goodData in pairs(comms_target.comms_data.goods) do
10293				goodsReport = goodsReport .. string.format("     %s: %i, %i\n",good,goodData["quantity"],goodData["cost"])
10294			end
10295			if comms_target.comms_data.buy ~= nil then
10296				goodsReport = goodsReport .. "Goods or components station will buy: price in reputation\n"
10297				for good, price in pairs(comms_target.comms_data.buy) do
10298					goodsReport = goodsReport .. string.format("     %s: %i\n",good,price)
10299				end
10300			end
10301			goodsReport = goodsReport .. string.format("Current cargo aboard %s:\n",comms_source:getCallSign())
10302			local cargoHoldEmpty = true
10303			local goodCount = 0
10304			if comms_source.goods ~= nil then
10305				for good, goodQuantity in pairs(comms_source.goods) do
10306					goodCount = goodCount + 1
10307					goodsReport = goodsReport .. string.format("     %s: %i\n",good,goodQuantity)
10308				end
10309			end
10310			if goodCount < 1 then
10311				goodsReport = goodsReport .. "     Empty\n"
10312			end
10313			goodsReport = goodsReport .. string.format("Available Space: %i, Available Reputation: %i\n",comms_source.cargo,math.floor(comms_source:getReputationPoints()))
10314			setCommsMessage(goodsReport)
10315			for good, goodData in pairs(comms_target.comms_data.goods) do
10316				addCommsReply(string.format("Buy one %s for %i reputation",good,goodData["cost"]), function()
10317					local goodTransactionMessage = string.format("Type: %s, Quantity: %i, Rep: %i",good,goodData["quantity"],goodData["cost"])
10318					if comms_source.cargo < 1 then
10319						goodTransactionMessage = goodTransactionMessage .. "\nInsufficient cargo space for purchase"
10320					elseif goodData["cost"] > math.floor(comms_source:getReputationPoints()) then
10321						goodTransactionMessage = goodTransactionMessage .. "\nInsufficient reputation for purchase"
10322					elseif goodData["quantity"] < 1 then
10323						goodTransactionMessage = goodTransactionMessage .. "\nInsufficient station inventory"
10324					else
10325						if comms_source:takeReputationPoints(goodData["cost"]) then
10326							comms_source.cargo = comms_source.cargo - 1
10327							goodData["quantity"] = goodData["quantity"] - 1
10328							if comms_source.goods == nil then
10329								comms_source.goods = {}
10330							end
10331							if comms_source.goods[good] == nil then
10332								comms_source.goods[good] = 0
10333							end
10334							comms_source.goods[good] = comms_source.goods[good] + 1
10335							goodTransactionMessage = goodTransactionMessage .. "\npurchased"
10336						else
10337							goodTransactionMessage = goodTransactionMessage .. "\nInsufficient reputation for purchase"
10338						end
10339					end
10340					setCommsMessage(goodTransactionMessage)
10341					addCommsReply("Back", return_function)
10342				end)
10343			end
10344			if comms_target.comms_data.buy ~= nil then
10345				for good, price in pairs(comms_target.comms_data.buy) do
10346					if comms_source.goods ~= nil then
10347						if comms_source.goods[good] ~= nil and comms_source.goods[good] > 0 then
10348							addCommsReply(string.format("Sell one %s for %i reputation",good,price), function()
10349								local goodTransactionMessage = string.format("Type: %s,  Reputation price: %i",good,price)
10350								comms_source.goods[good] = comms_source.goods[good] - 1
10351								comms_source:addReputationPoints(price)
10352								goodTransactionMessage = goodTransactionMessage .. "\nOne sold"
10353								comms_source.cargo = comms_source.cargo + 1
10354								setCommsMessage(goodTransactionMessage)
10355								addCommsReply("Back", return_function)
10356							end)
10357						end
10358					end
10359				end
10360			end
10361			if comms_target.comms_data.trade.food and comms_source.goods["food"] > 0 then
10362				for good, goodData in pairs(comms_target.comms_data.goods) do
10363					addCommsReply(string.format("Trade food for %s",good), function()
10364						local goodTransactionMessage = string.format("Type: %s,  Quantity: %i",good,goodData["quantity"])
10365						if goodData["quantity"] < 1 then
10366							goodTransactionMessage = goodTransactionMessage .. "\nInsufficient station inventory"
10367						else
10368							goodData["quantity"] = goodData["quantity"] - 1
10369							if comms_source.goods == nil then
10370								comms_source.goods = {}
10371							end
10372							if comms_source.goods[good] == nil then
10373								comms_source.goods[good] = 0
10374							end
10375							comms_source.goods[good] = comms_source.goods[good] + 1
10376							comms_source.goods["food"] = comms_source.goods["food"] - 1
10377							goodTransactionMessage = goodTransactionMessage .. "\nTraded"
10378						end
10379						setCommsMessage(goodTransactionMessage)
10380						addCommsReply("Back", return_function)
10381					end)
10382				end
10383			end
10384			if comms_target.comms_data.trade.medicine and comms_source.goods["medicine"] > 0 then
10385				for good, goodData in pairs(comms_target.comms_data.goods) do
10386					addCommsReply(string.format("Trade medicine for %s",good), function()
10387						local goodTransactionMessage = string.format("Type: %s,  Quantity: %i",good,goodData["quantity"])
10388						if goodData["quantity"] < 1 then
10389							goodTransactionMessage = goodTransactionMessage .. "\nInsufficient station inventory"
10390						else
10391							goodData["quantity"] = goodData["quantity"] - 1
10392							if comms_source.goods == nil then
10393								comms_source.goods = {}
10394							end
10395							if comms_source.goods[good] == nil then
10396								comms_source.goods[good] = 0
10397							end
10398							comms_source.goods[good] = comms_source.goods[good] + 1
10399							comms_source.goods["medicine"] = comms_source.goods["medicine"] - 1
10400							goodTransactionMessage = goodTransactionMessage .. "\nTraded"
10401						end
10402						setCommsMessage(goodTransactionMessage)
10403						addCommsReply("Back", return_function)
10404					end)
10405				end
10406			end
10407			if comms_target.comms_data.trade.luxury and comms_source.goods["luxury"] > 0 then
10408				for good, goodData in pairs(comms_target.comms_data.goods) do
10409					addCommsReply(string.format("Trade luxury for %s",good), function()
10410						local goodTransactionMessage = string.format("Type: %s,  Quantity: %i",good,goodData["quantity"])
10411						if goodData[quantity] < 1 then
10412							goodTransactionMessage = goodTransactionMessage .. "\nInsufficient station inventory"
10413						else
10414							goodData["quantity"] = goodData["quantity"] - 1
10415							if comms_source.goods == nil then
10416								comms_source.goods = {}
10417							end
10418							if comms_source.goods[good] == nil then
10419								comms_source.goods[good] = 0
10420							end
10421							comms_source.goods[good] = comms_source.goods[good] + 1
10422							comms_source.goods["luxury"] = comms_source.goods["luxury"] - 1
10423							goodTransactionMessage = goodTransactionMessage .. "\nTraded"
10424						end
10425						setCommsMessage(goodTransactionMessage)
10426						addCommsReply("Back", return_function)
10427					end)
10428				end
10429			end
10430			addCommsReply("Back", return_function)
10431		end)
10432	end
10433end
10434function boostSensorsWhileDocked(return_function)
10435	if comms_target.comms_data.sensor_boost ~= nil then
10436		if comms_target.comms_data.sensor_boost.cost > 0 then
10437			addCommsReply(string.format("Augment scan range with station sensors while docked (%i rep)",comms_target.comms_data.sensor_boost.cost),function()
10438				if comms_source:takeReputationPoints(comms_target.comms_data.sensor_boost.cost) then
10439					if comms_source.normal_long_range_radar == nil then
10440						comms_source.normal_long_range_radar = comms_source:getLongRangeRadarRange()
10441					end
10442					comms_source:setLongRangeRadarRange(comms_source.normal_long_range_radar + comms_target.comms_data.sensor_boost.value)
10443					setCommsMessage(string.format("sensors increased by %i units",comms_target.comms_data.sensor_boost.value/1000))
10444				else
10445					setCommsMessage("Insufficient reputation")
10446				end
10447				addCommsReply("Back", return_function)
10448			end)
10449		end
10450	end
10451end
10452function overchargeJump(return_function)
10453	if comms_target.comms_data.jump_overcharge and isAllowedTo(comms_target.comms_data.services.jumpovercharge) then
10454		if comms_source:hasJumpDrive() then
10455			local max_charge = comms_source.max_jump_range
10456			if max_charge == nil then
10457				max_charge = 50000
10458			end
10459			if comms_source:getJumpDriveCharge() >= max_charge then
10460				addCommsReply("Overcharge Jump Drive (" .. getServiceCost("jumpovercharge") .. " rep)",function()
10461					if comms_source:takeReputationPoints(getServiceCost("jumpovercharge")) then
10462						comms_source:setJumpDriveCharge(comms_source:getJumpDriveCharge() + max_charge)
10463						setCommsMessage(string.format("Your jump drive has been overcharged to %ik",math.floor(comms_source:getJumpDriveCharge()/1000)))
10464					else
10465						setCommsMessage("Insufficient reputation")
10466					end
10467					addCommsReply("Back", return_function)
10468				end)
10469			end
10470		end
10471	end
10472end
10473--	Upgrades
10474function hullStrengthUpgrade(p)
10475	if p.hull_strength_upgrade == nil then
10476		p.hull_strength_upgrade = "done"
10477		p:setHullMax(p:getHullMax()*1.2)
10478		p:setHull(p:getHullMax())
10479		p:setImpulseMaxSpeed(p:getImpulseMaxSpeed()*.9)
10480		return true, "Your hull strength has been increased by 20%"
10481	else
10482		return false, "You already have the hull strength upgrade"
10483	end
10484end
10485function missileLoadSpeedUpgrade(p)
10486	if p.missile_load_speed_upgrade == nil then
10487		local tube_count = p:getWeaponTubeCount()
10488		if tube_count > 0 then
10489			local tube_index = 0
10490			if p.normal_tube_load_time == nil then
10491				p.normal_tube_load_time = {}
10492				repeat
10493					p.normal_tube_load_time[tube_index] = p:getTubeLoadTime(tube_index)
10494					tube_index = tube_index + 1
10495				until(tube_index >= tube_count)
10496				tube_index = 0
10497			end
10498			repeat
10499				p:setTubeLoadTime(tube_index,p.normal_tube_load_time[tube_index]*.8)
10500				p.normal_tube_load_time[tube_index] = p.normal_tube_load_time[tube_index]*.8
10501				tube_index = tube_index + 1
10502			until(tube_index >= tube_count)
10503			return true, "Your missile tube load time has been reduced by 20%"
10504		else
10505			return false, "Your ship has no missile systems and thus cannot be upgraded"
10506		end
10507	else
10508		return false, "You already have the missile load speed upgrade"
10509	end
10510end
10511function shieldStrengthUpgrade(p)
10512	if p.shield_strength_upgrade == nil then
10513		if p:getShieldCount() > 0 then
10514			p.shield_strength_upgrade = "done"
10515			if p:getShieldCount() == 1 then
10516				p:setShieldsMax(p:getShieldMax(0)*1.2)
10517			else
10518				p:setShieldsMax(p:getShieldMax(0)*1.2,p:getShieldMax(1)*1.2)
10519			end
10520			return true, "Your ship shields are now 20% stronger. They'll need to charge to their new higher capacity"
10521		else
10522			return false, "Your ship has no shields and thus cannot be upgraded"
10523		end
10524	else
10525		return false, "You already have the shield upgrade"
10526	end
10527end
10528function beamDamageUpgrade(p)
10529	if p.beam_damage_upgrade == nil then
10530		if p:getBeamWeaponRange(0) > 0 then
10531			p.beam_damage_upgrade = "done"
10532			local bi = 0
10533			repeat
10534				local tempArc = p:getBeamWeaponArc(bi)
10535				local tempDir = p:getBeamWeaponDirection(bi)
10536				local tempRng = p:getBeamWeaponRange(bi)
10537				local tempCyc = p:getBeamWeaponCycleTime(bi)
10538				local tempDmg = p:getBeamWeaponDamage(bi)
10539				p:setBeamWeapon(bi,tempArc,tempDir,tempRng,tempCyc,tempDmg*1.2)
10540				p:setBeamWeaponHeatPerFire(bi,p:getBeamWeaponHeatPerFire(bi)*1.2)
10541				p:setBeamWeaponEnergyPerFire(bi,p:getBeamWeaponEnergyPerFire(bi)*1.2)
10542				bi = bi + 1
10543			until(p:getBeamWeaponRange(bi) < 1)
10544			return true, "Your ship beam weapons damage has been increased by 20%"
10545		else
10546			return false, "Your ship has no beam weapons and thus cannot be upgraded"
10547		end
10548	else
10549		return false, "You already have the beam damage upgrade"
10550	end
10551end
10552function beamRangeUpgrade(p)
10553	if p.beam_range_upgrade == nil then
10554		if p:getBeamWeaponRange(0) > 0 then
10555			p.beam_range_upgrade = "done"
10556			local bi = 0
10557			repeat
10558				local tempArc = p:getBeamWeaponArc(bi)
10559				local tempDir = p:getBeamWeaponDirection(bi)
10560				local tempRng = p:getBeamWeaponRange(bi)
10561				local tempCyc = p:getBeamWeaponCycleTime(bi)
10562				local tempDmg = p:getBeamWeaponDamage(bi)
10563				p:setBeamWeapon(bi,tempArc,tempDir,tempRng*1.2,tempCyc,tempDmg)
10564				p:setBeamWeaponHeatPerFire(bi,p:getBeamWeaponHeatPerFire(bi)*1.2)
10565				p:setBeamWeaponEnergyPerFire(bi,p:getBeamWeaponEnergyPerFire(bi)*1.2)
10566				bi = bi + 1
10567			until(p:getBeamWeaponRange(bi) < 1)
10568			return true, "Your ship beam weapons range has been increased by 20%"
10569		else
10570			return false, "Your ship has no beam weapons and thus cannot be upgraded"
10571		end
10572	else
10573		return false, "You already have the beam range upgrade"
10574	end
10575end
10576function batteryEfficiencyUpgrade(p)
10577	if p.battery_efficiency_upgrade == nil then
10578		p.battery_efficiency_upgrade = "done"
10579		p:setMaxEnergy(p:getMaxEnergy()*1.2)
10580		p:setImpulseMaxSpeed(p:getImpulseMaxSpeed()*.95)
10581		return true, "Your ship batteries can now store 20% more energy. You'll need to charge them longer to use their full capacity"
10582	else
10583		return false, "You already have the battery efficiency upgrade"
10584	end
10585end
10586function fasterImpulseUpgrade(p)
10587	if p.faster_impulse_upgrade == nil then
10588		p.faster_impulse_upgrade = "done"
10589		p:setImpulseMaxSpeed(p:getImpulseMaxSpeed()*1.2)
10590		p:setRotationMaxSpeed(p:getRotationMaxSpeed()*.95)
10591		return true, "Your maximum impulse top speed has been increased by 20%"
10592	else
10593		return false, "You already have an upgraded impulse engine"
10594	end
10595end
10596function longerSensorsUpgrade(p)
10597	if p.longer_sensors_upgrade == nil then
10598		p.longer_sensors_upgrade = "done"
10599		if p.normal_long_range_radar == nil then
10600			p.normal_long_range_radar = p:getLongRangeRadarRange()
10601		end
10602		p:setLongRangeRadarRange(p:getLongRangeRadarRange() + 10000)
10603		p.normal_long_range_radar = p.normal_long_range_radar + 10000
10604		return true, "Your ship's long range sensors have had their reach increased by 10 units"
10605	else
10606		return false, "You already have upgraded long range sensors"
10607	end
10608end
10609function fasterSpinUpgrade(p)
10610	if p.faster_spin_upgrade == nil then
10611		p.faster_spin_upgrade = "done"
10612		p:setRotationMaxSpeed(p:getRotationMaxSpeed()*1.2)
10613		return true, "Your maneuvering speed has been increased by 20%"
10614	else
10615		return false, "You already have upgraded maneuvering speed"
10616	end
10617end
10618---------------------------
10619--	Ship Communications  --
10620---------------------------
10621function commsShip()
10622	if comms_target.comms_data == nil then
10623		comms_target.comms_data = {friendlyness = random(0.0, 100.0)}
10624	end
10625	comms_data = comms_target.comms_data
10626	if comms_data.goods == nil then
10627		comms_data.goods = {}
10628		comms_data.goods[commonGoods[math.random(1,#commonGoods)]] = {quantity = 1, cost = random(20,80)}
10629		local shipType = comms_target:getTypeName()
10630		if shipType:find("Freighter") ~= nil then
10631			if shipType:find("Goods") ~= nil or shipType:find("Equipment") ~= nil then
10632				repeat
10633					comms_data.goods[commonGoods[math.random(1,#commonGoods)]] = {quantity = 1, cost = random(20,80)}
10634					local goodCount = 0
10635					for good, goodData in pairs(comms_data.goods) do
10636						goodCount = goodCount + 1
10637					end
10638				until(goodCount >= 3)
10639			end
10640		end
10641	end
10642	if comms_source:isFriendly(comms_target) then
10643		return friendlyComms(comms_data)
10644	end
10645	if comms_source:isEnemy(comms_target) and comms_target:isFriendOrFoeIdentifiedBy(comms_source) then
10646		return enemyComms(comms_data)
10647	end
10648	return neutralComms(comms_data)
10649end
10650function friendlyComms(comms_data)
10651	if comms_data.friendlyness < 20 then
10652		setCommsMessage("What do you want?");
10653	else
10654		setCommsMessage("Sir, how can we assist?");
10655	end
10656	shipDefendWaypoint(commsShip)
10657	shipFlyBlind(commsShip)
10658	shipAssistPlayer(comms_data,commsShip)
10659	shipStatusReport(commsShip)
10660	shipDockNearby(commsShip)
10661	shipRoaming(commsShip)
10662	shipStandGround(commsShip)
10663	shipIdle(commsShip)
10664	fleetCommunication(commsShip)
10665	friendlyFreighterCommunication(comms_data,commsShip)
10666	return true
10667end
10668function enemyComms(comms_data)
10669	local faction = comms_target:getFaction()
10670	local tauntable = false
10671	local amenable = false
10672	if comms_data.friendlyness >= 33 then	--final: 33
10673		--taunt logic
10674		local taunt_option = "We will see to your destruction!"
10675		local taunt_success_reply = "Your bloodline will end here!"
10676		local taunt_failed_reply = "Your feeble threats are meaningless."
10677		local taunt_threshold = 30	--base chance of being taunted
10678		if faction == "Kraylor" then
10679			taunt_threshold = 35
10680			setCommsMessage("Ktzzzsss.\nYou will DIEEee weaklingsss!");
10681			local kraylorTauntChoice = math.random(1,3)
10682			if kraylorTauntChoice == 1 then
10683				taunt_option = "We will destroy you"
10684				taunt_success_reply = "We think not. It is you who will experience destruction!"
10685			elseif kraylorTauntChoice == 2 then
10686				taunt_option = "You have no honor"
10687				taunt_success_reply = "Your insult has brought our wrath upon you. Prepare to die."
10688				taunt_failed_reply = "Your comments about honor have no meaning to us"
10689			else
10690				taunt_option = "We pity your pathetic race"
10691				taunt_success_reply = "Pathetic? You will regret your disparagement!"
10692				taunt_failed_reply = "We don't care what you think of us"
10693			end
10694		elseif faction == "Arlenians" then
10695			taunt_threshold = 25
10696			setCommsMessage("We wish you no harm, but will harm you if we must.\nEnd of transmission.");
10697		elseif faction == "Exuari" then
10698			taunt_threshold = 40
10699			setCommsMessage("Stay out of our way, or your death will amuse us extremely!");
10700		elseif faction == "Ghosts" then
10701			taunt_threshold = 20
10702			setCommsMessage("One zero one.\nNo binary communication detected.\nSwitching to universal speech.\nGenerating appropriate response for target from human language archives.\n:Do not cross us:\nCommunication halted.");
10703			taunt_option = "EXECUTE: SELFDESTRUCT"
10704			taunt_success_reply = "Rogue command received. Targeting source."
10705			taunt_failed_reply = "External command ignored."
10706		elseif faction == "Ktlitans" then
10707			setCommsMessage("The hive suffers no threats. Opposition to any of us is opposition to us all.\nStand down or prepare to donate your corpses toward our nutrition.");
10708			taunt_option = "<Transmit 'The Itsy-Bitsy Spider' on all wavelengths>"
10709			taunt_success_reply = "We do not need permission to pluck apart such an insignificant threat."
10710			taunt_failed_reply = "The hive has greater priorities than exterminating pests."
10711		elseif faction == "TSN" then
10712			taunt_threshold = 15
10713			setCommsMessage("State your business")
10714		elseif faction == "USN" then
10715			taunt_threshold = 15
10716			setCommsMessage("What do you want? (not that we care)")
10717		elseif faction == "CUF" then
10718			taunt_threshold = 15
10719			setCommsMessage("Don't waste our time")
10720		else
10721			setCommsMessage("Mind your own business!");
10722		end
10723		comms_data.friendlyness = comms_data.friendlyness - random(0, 10)	--reduce friendlyness after each interaction
10724		addCommsReply(taunt_option, function()
10725			if random(0, 100) <= taunt_threshold then	--final: 30
10726				local current_order = comms_target:getOrder()
10727				print("order: " .. current_order)
10728				--Possible order strings returned:
10729				--Roaming
10730				--Fly towards
10731				--Attack
10732				--Stand Ground
10733				--Idle
10734				--Defend Location
10735				--Defend Target
10736				--Fly Formation (?)
10737				--Fly towards (ignore all)
10738				--Dock
10739				if comms_target.original_order == nil then
10740					comms_target.original_faction = faction
10741					comms_target.original_order = current_order
10742					if current_order == "Fly towards" or current_order == "Defend Location" or current_order == "Fly towards (ignore all)" then
10743						comms_target.original_target_x, comms_target.original_target_y = comms_target:getOrderTargetLocation()
10744						--print(string.format("Target_x: %f, Target_y: %f",comms_target.original_target_x,comms_target.original_target_y))
10745					end
10746					if current_order == "Attack" or current_order == "Dock" or current_order == "Defend Target" then
10747						local original_target = comms_target:getOrderTarget()
10748						--print("target:")
10749						--print(original_target)
10750						--print(original_target:getCallSign())
10751						comms_target.original_target = original_target
10752					end
10753					comms_target.taunt_may_expire = true	--change to conditional in future refactoring
10754					table.insert(enemy_reverts,comms_target)
10755				end
10756				comms_target:orderAttack(comms_source)	--consider alternative options besides attack in future refactoring
10757				setCommsMessage(taunt_success_reply);
10758			else
10759				setCommsMessage(taunt_failed_reply);
10760			end
10761		end)
10762		tauntable = true
10763	end
10764	local enemy_health = getEnemyHealth(comms_target)
10765	if change_enemy_order_diagnostic then print(string.format("   enemy health:    %.2f",enemy_health)) end
10766	if change_enemy_order_diagnostic then print(string.format("   friendliness:    %.1f",comms_data.friendlyness)) end
10767	if comms_data.friendlyness >= 66 or enemy_health < .5 then	--final: 66, .5
10768		--amenable logic
10769		local amenable_chance = comms_data.friendlyness/3 + (1 - enemy_health)*30
10770		if change_enemy_order_diagnostic then print(string.format("   amenability:     %.1f",amenable_chance)) end
10771		addCommsReply("Stop your actions",function()
10772			local amenable_roll = random(0,100)
10773			if change_enemy_order_diagnostic then print(string.format("   amenable roll:   %.1f",amenable_roll)) end
10774			if amenable_roll < amenable_chance then
10775				local current_order = comms_target:getOrder()
10776				if comms_target.original_order == nil then
10777					comms_target.original_order = current_order
10778					comms_target.original_faction = faction
10779					if current_order == "Fly towards" or current_order == "Defend Location" or current_order == "Fly towards (ignore all)" then
10780						comms_target.original_target_x, comms_target.original_target_y = comms_target:getOrderTargetLocation()
10781						--print(string.format("Target_x: %f, Target_y: %f",comms_target.original_target_x,comms_target.original_target_y))
10782					end
10783					if current_order == "Attack" or current_order == "Dock" or current_order == "Defend Target" then
10784						local original_target = comms_target:getOrderTarget()
10785						--print("target:")
10786						--print(original_target)
10787						--print(original_target:getCallSign())
10788						comms_target.original_target = original_target
10789					end
10790					table.insert(enemy_reverts,comms_target)
10791				end
10792				comms_target.amenability_may_expire = true
10793				comms_target:orderIdle()
10794				comms_target:setFaction("Independent")
10795				setCommsMessage("Just this once, we'll take your advice")
10796			else
10797				setCommsMessage("No")
10798			end
10799		end)
10800		comms_data.friendlyness = comms_data.friendlyness - random(0, 10)	--reduce friendlyness after each interaction
10801		amenable = true
10802	end
10803	if tauntable or amenable then
10804		return true
10805	else
10806		return false
10807	end
10808end
10809function neutralComms(comms_data)
10810	local shipType = comms_target:getTypeName()
10811	if shipType:find("Freighter") ~= nil or shipType:find("Transport") ~= nil or shipType:find("Cargo") ~= nil then
10812		setCommsMessage("Yes?")
10813		shipCargoSellReport(commsShip)
10814		if distance(comms_source,comms_target) < 5000 then
10815			if comms_source.cargo > 0 then
10816				if comms_data.friendlyness > 66 then
10817					if shipType:find("Goods") ~= nil or shipType:find("Equipment") ~= nil then
10818						shipBuyGoods(commsShip,1)
10819					else
10820						shipBuyGoods(commsShip,2)
10821					end
10822				elseif comms_data.friendlyness > 33 then
10823					if shipType:find("Goods") ~= nil or shipType:find("Equipment") ~= nil then
10824						shipBuyGoods(commsShip,2)
10825					else
10826						shipBuyGoods(commsShip,3)
10827					end
10828				else	--least friendly
10829					if shipType:find("Goods") ~= nil or shipType:find("Equipment") ~= nil then
10830						shipBuyGoods(commsShip,3)
10831					end
10832				end	--end friendly branches
10833			end	--player has room for cargo
10834		end	--close enough to sell
10835	else	--not a freighter
10836		if comms_data.friendlyness > 50 then
10837			setCommsMessage("Sorry, we have no time to chat with you.\nWe are on an important mission.");
10838		else
10839			setCommsMessage("We have nothing for you.\nGood day.");
10840		end
10841	end	--end non-freighter communications else branch
10842	return true
10843end	--end neutral communications function
10844function shipStatusReport(return_function)
10845	addCommsReply("Report status", function()
10846		msg = "Hull: " .. math.floor(comms_target:getHull() / comms_target:getHullMax() * 100) .. "%\n"
10847		local shields = comms_target:getShieldCount()
10848		if shields == 1 then
10849			msg = msg .. "Shield: " .. math.floor(comms_target:getShieldLevel(0) / comms_target:getShieldMax(0) * 100) .. "%\n"
10850		elseif shields == 2 then
10851			msg = msg .. "Front Shield: " .. math.floor(comms_target:getShieldLevel(0) / comms_target:getShieldMax(0) * 100) .. "%\n"
10852			msg = msg .. "Rear Shield: " .. math.floor(comms_target:getShieldLevel(1) / comms_target:getShieldMax(1) * 100) .. "%\n"
10853		else
10854			for n=0,shields-1 do
10855				msg = msg .. "Shield " .. n .. ": " .. math.floor(comms_target:getShieldLevel(n) / comms_target:getShieldMax(n) * 100) .. "%\n"
10856			end
10857		end
10858		local missile_types = {'Homing', 'Nuke', 'Mine', 'EMP', 'HVLI'}
10859		for i, missile_type in ipairs(missile_types) do
10860			if comms_target:getWeaponStorageMax(missile_type) > 0 then
10861				msg = msg .. missile_type .. " Missiles: " .. math.floor(comms_target:getWeaponStorage(missile_type)) .. "/" .. math.floor(comms_target:getWeaponStorageMax(missile_type)) .. "\n"
10862			end
10863		end
10864		if comms_target:hasJumpDrive() then
10865			msg = msg .. "Jump drive charge: " .. comms_target:getJumpDriveCharge()
10866		end
10867		setCommsMessage(msg);
10868		addCommsReply("Back", return_function)
10869	end)
10870end
10871function shipIdle(return_function)
10872	addCommsReply("Stop. Do nothing.", function()
10873		comms_target:orderIdle()
10874		local idle_comment = {
10875			"routine system maintenance",
10876			"for idle ship gossip",
10877			"exterior paint touch-up",
10878			"exercise for continued fitness",
10879			"meditation therapy",
10880			"internal simulated flight routines",
10881			"digital dreamscape construction",
10882			"catching up on reading the latest war drama novel",
10883			"writing up results of bifurcated personality research",
10884			"categorizing nearby miniscule space particles",
10885			"continuing the count of visible stars from this region",
10886			"internal systems diagnostics",
10887		}
10888		setCommsMessage(string.format("Stopping. Doing nothing except %s",idle_comment[math.random(1,#idle_comment)]))
10889		addCommsReply("Back", return_function)
10890	end)
10891end
10892function shipRoaming(return_function)
10893	addCommsReply("Attack all enemies. Start with the nearest.", function()
10894		comms_target:orderRoaming()
10895		setCommsMessage("Searching and destroying")
10896		addCommsReply("Back", return_function)
10897	end)
10898end
10899function shipStandGround(return_function)
10900	addCommsReply("Stop and defned your current location", function()
10901		comms_target:orderStandGround()
10902		setCommsMessage("Stopping. Shooting any enemy that approaches")
10903		addCommsReply("Back", return_function)
10904	end)
10905end
10906function shipDefendWaypoint(return_function)
10907	addCommsReply("Defend a waypoint", function()
10908		if comms_source:getWaypointCount() == 0 then
10909			setCommsMessage("No waypoints set. Please set a waypoint first.");
10910			addCommsReply("Back", return_function)
10911		else
10912			setCommsMessage("Which waypoint should we defend?");
10913			for n=1,comms_source:getWaypointCount() do
10914				addCommsReply("Defend WP" .. n, function()
10915					comms_target:orderDefendLocation(comms_source:getWaypoint(n))
10916					setCommsMessage("We are heading to assist at WP" .. n ..".");
10917					addCommsReply("Back", return_function)
10918				end)
10919			end
10920		end
10921	end)
10922end
10923function shipFlyBlind(return_function)
10924	addCommsReply("Go to waypoint, ignore enemies", function()
10925		if comms_source:getWaypointCount() == 0 then
10926			setCommsMessage("No waypoints set. Please set a waypoint first.");
10927			addCommsReply("Back", return_function)
10928		else
10929			setCommsMessage("Which waypoint should we approach?");
10930			for n=1,comms_source:getWaypointCount() do
10931				addCommsReply("Defend WP" .. n, function()
10932					comms_target:orderFlyTowardsBlind(comms_source:getWaypoint(n))
10933					setCommsMessage("We are heading to WP" .. n ..", ignoring enemies.");
10934					addCommsReply("Back", return_function)
10935				end)
10936			end
10937		end
10938	end)
10939end
10940function shipAssistPlayer(comms_data,return_function)
10941	if comms_data.friendlyness > 0.2 then
10942		addCommsReply("Assist me", function()
10943			setCommsMessage("Heading toward you to assist.");
10944			comms_target:orderDefendTarget(comms_source)
10945			addCommsReply("Back", return_function)
10946		end)
10947	end
10948end
10949function shipDockNearby(return_function)
10950	for _, obj in ipairs(comms_target:getObjectsInRange(5000)) do
10951		local player_carrier = false
10952		local template_name = ""
10953		if obj.typeName == "PlayerSpaceship" then
10954			template_name = obj:getTypeName()
10955			if template_name == "Benedict" or template_name == "Kiriya" then
10956				player_carrier = true
10957			end
10958		end
10959		local defense_platform = false
10960		if obj.typeName == "CpuShip" then
10961			template_name = obj:getTypeName()
10962			if template_name == "Defense platform" then
10963				defense_platform = true
10964			end
10965		end
10966		if (obj.typeName == "SpaceStation" and not comms_target:isEnemy(obj)) or player_carrier or defense_platform then
10967			addCommsReply("Dock at " .. obj:getCallSign(), function()
10968				setCommsMessage("Docking at " .. obj:getCallSign() .. ".");
10969				comms_target:orderDock(obj)
10970				addCommsReply("Back", return_function)
10971			end)
10972		end
10973	end
10974end
10975function fleetCommunication(return_function)
10976	if comms_target.fleetIndex ~= nil then
10977		addCommsReply(string.format("Direct fleet %i",comms_target.fleetIndex), function()
10978			local fleet_state = string.format("Fleet %i consists of:\n",comms_target.fleetIndex)
10979			for _, ship in ipairs(npc_fleet[comms_target:getFaction()]) do
10980				if ship.fleetIndex == comms_target.fleetIndex then
10981					fleet_state = fleet_state .. ship:getCallSign() .. " "
10982				end
10983			end
10984			setCommsMessage(string.format("%s\n\nWhat command should be given to fleet %i?",fleet_state,comms_target.fleetIndex))
10985			addCommsReply("Report hull and shield status", function()
10986				msg = string.format("Fleet %i status:",comms_target.fleetIndex)
10987				for _, fleetShip in ipairs(npc_fleet[comms_target:getFaction()]) do
10988					if fleetShip.fleetIndex == comms_target.fleetIndex then
10989						if fleetShip ~= nil and fleetShip:isValid() then
10990							msg = msg .. "\n  " .. fleetShip:getCallSign() .. ":"
10991							msg = msg .. "\n    Hull: " .. math.floor(fleetShip:getHull() / fleetShip:getHullMax() * 100) .. "%"
10992							local shields = fleetShip:getShieldCount()
10993							if shields == 1 then
10994								msg = msg .. "\n    Shield: " .. math.floor(fleetShip:getShieldLevel(0) / fleetShip:getShieldMax(0) * 100) .. "%"
10995							else
10996								msg = msg .. "\n    Shields: "
10997								if shields == 2 then
10998									msg = msg .. "Front:" .. math.floor(fleetShip:getShieldLevel(0) / fleetShip:getShieldMax(0) * 100) .. "% Rear:" .. math.floor(fleetShip:getShieldLevel(1) / fleetShip:getShieldMax(1) * 100) .. "%"
10999								else
11000									for n=0,shields-1 do
11001										msg = msg .. " " .. n .. ":" .. math.floor(fleetShip:getShieldLevel(n) / fleetShip:getShieldMax(n) * 100) .. "%"
11002									end
11003								end
11004							end
11005						end
11006					end
11007				end
11008				setCommsMessage(msg)
11009				addCommsReply("Back", return_function)
11010			end)
11011			addCommsReply("Report missile status", function()
11012				msg = string.format("Fleet %i missile status:",comms_target.fleetIndex)
11013				for _, fleetShip in ipairs(npc_fleet[comms_target:getFaction()]) do
11014					if fleetShip.fleetIndex == comms_target.fleetIndex then
11015						if fleetShip ~= nil and fleetShip:isValid() then
11016							msg = msg .. "\n  " .. fleetShip:getCallSign() .. ":"
11017							local missile_types = {'Homing', 'Nuke', 'Mine', 'EMP', 'HVLI'}
11018							missileMsg = ""
11019							for _, missile_type in ipairs(missile_types) do
11020								if fleetShip:getWeaponStorageMax(missile_type) > 0 then
11021									missileMsg = missileMsg .. "\n      " .. missile_type .. ": " .. math.floor(fleetShip:getWeaponStorage(missile_type)) .. "/" .. math.floor(fleetShip:getWeaponStorageMax(missile_type))
11022								end
11023							end
11024							if missileMsg ~= "" then
11025								msg = msg .. "\n    Missiles: " .. missileMsg
11026							end
11027						end
11028					end
11029				end
11030				setCommsMessage(msg)
11031				addCommsReply("Back", return_function)
11032			end)
11033			addCommsReply("Assist me", function()
11034				for _, fleetShip in ipairs(npc_fleet[comms_target:getFaction()]) do
11035					if fleetShip.fleetIndex == comms_target.fleetIndex then
11036						if fleetShip ~= nil and fleetShip:isValid() then
11037							fleetShip:orderDefendTarget(comms_source)
11038						end
11039					end
11040				end
11041				setCommsMessage(string.format("Fleet %s heading toward you to assist",comms_target.fleetIndex))
11042				addCommsReply("Back", return_function)
11043			end)
11044			addCommsReply("Defend a waypoint", function()
11045				if comms_source:getWaypointCount() == 0 then
11046					setCommsMessage("No waypoints set. Please set a waypoint first.");
11047					addCommsReply("Back", return_function)
11048				else
11049					setCommsMessage("Which waypoint should we defend?");
11050					for n=1,comms_source:getWaypointCount() do
11051						addCommsReply("Defend WP" .. n, function()
11052							for _, fleetShip in ipairs(npc_fleet[comms_target:getFaction()]) do
11053								if fleetShip.fleetIndex == comms_target.fleetIndex then
11054									if fleetShip ~= nil and fleetShip:isValid() then
11055										fleetShip:orderDefendLocation(comms_source:getWaypoint(n))
11056									end
11057								end
11058							end
11059							setCommsMessage("We are heading to assist at WP" .. n ..".");
11060							addCommsReply("Back", return_function)
11061						end)
11062					end
11063				end
11064			end)
11065			addCommsReply("Go to waypoint. Attack enemies en route", function()
11066				if comms_source:getWaypointCount() == 0 then
11067					setCommsMessage("No waypoints set. Please set a waypoint first.");
11068					addCommsReply("Back", return_function)
11069				else
11070					setCommsMessage("Which waypoint?");
11071					for n=1,comms_source:getWaypointCount() do
11072						addCommsReply("Go to WP" .. n, function()
11073							for _, fleetShip in ipairs(npc_fleet[comms_target:getFaction()]) do
11074								if fleetShip.fleetIndex == comms_target.fleetIndex then
11075									if fleetShip ~= nil and fleetShip:isValid() then
11076										fleetShip:orderFlyTowards(comms_source:getWaypoint(n))
11077									end
11078								end
11079							end
11080							setCommsMessage("Going to WP" .. n ..", watching for enemies en route");
11081							addCommsReply("Back", return_function)
11082						end)
11083					end
11084				end
11085			end)
11086			addCommsReply("Go to waypoint. Ignore enemies", function()
11087				if comms_source:getWaypointCount() == 0 then
11088					setCommsMessage("No waypoints set. Please set a waypoint first.");
11089					addCommsReply("Back", return_function)
11090				else
11091					setCommsMessage("Which waypoint?");
11092					for n=1,comms_source:getWaypointCount() do
11093						addCommsReply("Go to WP" .. n, function()
11094							for _, fleetShip in ipairs(npc_fleet[comms_target:getFaction()]) do
11095								if fleetShip.fleetIndex == comms_target.fleetIndex then
11096									if fleetShip ~= nil and fleetShip:isValid() then
11097										fleetShip:orderFlyTowardsBlind(comms_source:getWaypoint(n))
11098									end
11099								end
11100							end
11101							setCommsMessage("Going to WP" .. n ..", ignoring enemies");
11102							addCommsReply("Back", return_function)
11103						end)
11104					end
11105				end
11106			end)
11107			addCommsReply("Go offensive, attack all enemy targets", function()
11108				for _, fleetShip in ipairs(npc_fleet[comms_target:getFaction()]) do
11109					if fleetShip.fleetIndex == comms_target.fleetIndex then
11110						if fleetShip ~= nil and fleetShip:isValid() then
11111							fleetShip:orderRoaming()
11112						end
11113					end
11114				end
11115				setCommsMessage(string.format("Fleet %s is on an offensive rampage",comms_target.fleetIndex))
11116				addCommsReply("Back", return_function)
11117			end)
11118			addCommsReply("Stop and defend your current position", function()
11119				for _, fleetShip in ipairs(npc_fleet[comms_target:getFaction()]) do
11120					if fleetShip.fleetIndex == comms_target.fleetIndex then
11121						fleetShip:orderStandGround()
11122					end
11123				end
11124				setCommsMessage("Stopping and defending")
11125				addCommsReply("Back", return_function)
11126			end)
11127			addCommsReply("Stop and do nothing", function()
11128				for _, fleetShip in ipairs(npc_fleet[comms_target:getFaction()]) do
11129					if fleetShip.fleetIndex == comms_target.fleetIndex then
11130						fleetShip:orderIdle()
11131					end
11132				end
11133				setCommsMessage("Stopping and doing nothing")
11134				addCommsReply("Back", return_function)
11135			end)
11136		end)
11137	end
11138end
11139function friendlyFreighterCommunication(comms_data,return_function)
11140	local shipType = comms_target:getTypeName()
11141	if shipType:find("Freighter") ~= nil then
11142		if distance(comms_source, comms_target) < 5000 then
11143			if comms_data.friendlyness > 66 then
11144				if shipType:find("Goods") ~= nil or shipType:find("Equipment") ~= nil then
11145					shipTradeGoods(comms_data,return_function)
11146				end	--goods or equipment freighter
11147				if comms_source.cargo > 0 then
11148					shipBuyGoods(comms_data,return_function,1)
11149				end	--player has cargo space branch
11150			elseif comms_data.friendlyness > 33 then
11151				if comms_source.cargo > 0 then
11152					if shipType:find("Goods") ~= nil or shipType:find("Equipment") ~= nil then
11153						shipBuyGoods(comms_data,return_function,1)
11154					else	--not goods or equipment freighter
11155						shipBuyGoods(comms_data,return_function,2)
11156					end
11157				end	--player has room for cargo branch
11158			else	--least friendly
11159				if comms_source.cargo > 0 then
11160					if shipType:find("Goods") ~= nil or shipType:find("Equipment") ~= nil then
11161						shipBuyGoods(comms_data,return_function,2)
11162					end	--goods or equipment freighter
11163				end	--player has room to get goods
11164			end	--various friendliness choices
11165		else	--not close enough to sell
11166			shipCargoSellReport(comms_data,return_function)
11167		end
11168	end
11169end
11170function shipCargoSellReport(comms_data,return_function)
11171	addCommsReply("Do you have cargo you might sell?", function()
11172		local goodCount = 0
11173		local cargoMsg = "We've got "
11174		for good, goodData in pairs(comms_data.goods) do
11175			if goodData.quantity > 0 then
11176				if goodCount > 0 then
11177					cargoMsg = cargoMsg .. ", " .. good
11178				else
11179					cargoMsg = cargoMsg .. good
11180				end
11181			end
11182			goodCount = goodCount + goodData.quantity
11183		end
11184		if goodCount == 0 then
11185			cargoMsg = cargoMsg .. "nothing"
11186		end
11187		setCommsMessage(cargoMsg)
11188		addCommsReply("Back", return_function)
11189	end)
11190end
11191function shipTradeGoods(comms_data,return_function)
11192	if comms_source.goods ~= nil and comms_source.goods.luxury ~= nil and comms_source.goods.luxury > 0 then
11193		for good, goodData in pairs(comms_data.goods) do
11194			if goodData.quantity > 0 and good ~= "luxury" then
11195				addCommsReply(string.format("Trade luxury for %s",good), function()
11196					goodData.quantity = goodData.quantity - 1
11197					if comms_source.goods == nil then
11198						comms_source.goods = {}
11199					end
11200					if comms_source.goods[good] == nil then
11201						comms_source.goods[good] = 0
11202					end
11203					comms_source.goods[good] = comms_source.goods[good] + 1
11204					comms_source.goods.luxury = comms_source.goods.luxury - 1
11205					setCommsMessage(string.format("Traded your luxury for %s from %s",good,comms_target:getCallSign()))
11206					addCommsReply("Back", return_function)
11207				end)
11208			end
11209		end	--freighter goods loop
11210	end	--player has luxury branch
11211end
11212function shipBuyGoods(comms_data,return_function,price_multiplier)
11213	for good, goodData in pairs(comms_data.goods) do
11214		if goodData.quantity > 0 then
11215			addCommsReply(string.format("Buy one %s for %i reputation",good,math.floor(goodData.cost*price_multiplier)), function()
11216				if comms_source:takeReputationPoints(goodData.cost*price_multiplier) then
11217					goodData.quantity = goodData.quantity - 1
11218					if comms_source.goods == nil then
11219						comms_source.goods = {}
11220					end
11221					if comms_source.goods[good] == nil then
11222						comms_source.goods[good] = 0
11223					end
11224					comms_source.goods[good] = comms_source.goods[good] + 1
11225					comms_source.cargo = comms_source.cargo - 1
11226					setCommsMessage(string.format("Purchased %s from %s",good,comms_target:getCallSign()))
11227				else
11228					setCommsMessage("Insufficient reputation for purchase")
11229				end
11230				addCommsReply("Back", return_function)
11231			end)
11232		end
11233	end	--freighter goods loop
11234end
11235-------------------------------
11236-- Defend ship communication --
11237-------------------------------
11238function commsDefendShip()
11239	if comms_target.comms_data == nil then
11240		comms_target.comms_data = {friendlyness = random(0.0, 100.0)}
11241	end
11242	comms_data = comms_target.comms_data
11243	if comms_source:isFriendly(comms_target) then
11244		return friendlyDefendComms(comms_data)
11245	end
11246	if comms_source:isEnemy(comms_target) and comms_target:isFriendOrFoeIdentifiedBy(comms_source) then
11247		return enemyDefendComms(comms_data)
11248	end
11249	return neutralDefendComms(comms_data)
11250end
11251function friendlyDefendComms(comms_data)
11252	if comms_data.friendlyness < 20 then
11253		setCommsMessage("What do you want?");
11254	else
11255		setCommsMessage("Sir, how can we assist?");
11256	end
11257	shipStatusReport(commsDefendShip)
11258	return true
11259end
11260function enemyDefendComms(comms_data)
11261    if comms_data.friendlyness > 50 then
11262        local faction = comms_target:getFaction()
11263        local taunt_option = "We will see to your destruction!"
11264        local taunt_success_reply = "Your bloodline will end here!"
11265        local taunt_failed_reply = "Your feeble threats are meaningless."
11266        if faction == "Kraylor" then
11267            setCommsMessage("Ktzzzsss.\nYou will DIEEee weaklingsss!");
11268        elseif faction == "Arlenians" then
11269            setCommsMessage("We wish you no harm, but will harm you if we must.\nEnd of transmission.");
11270        elseif faction == "Exuari" then
11271            setCommsMessage("Stay out of our way, or your death will amuse us extremely!");
11272        elseif faction == "Ghosts" then
11273            setCommsMessage("One zero one.\nNo binary communication detected.\nSwitching to universal speech.\nGenerating appropriate response for target from human language archives.\n:Do not cross us:\nCommunication halted.");
11274            taunt_option = "EXECUTE: SELFDESTRUCT"
11275            taunt_success_reply = "Rogue command received. Targeting source."
11276            taunt_failed_reply = "External command ignored."
11277        elseif faction == "Ktlitans" then
11278            setCommsMessage("The hive suffers no threats. Opposition to any of us is opposition to us all.\nStand down or prepare to donate your corpses toward our nutrition.");
11279            taunt_option = "<Transmit 'The Itsy-Bitsy Spider' on all wavelengths>"
11280            taunt_success_reply = "We do not need permission to pluck apart such an insignificant threat."
11281            taunt_failed_reply = "The hive has greater priorities than exterminating pests."
11282        else
11283            setCommsMessage("Mind your own business!");
11284        end
11285        comms_data.friendlyness = comms_data.friendlyness - random(0, 10)
11286        addCommsReply(taunt_option, function()
11287            if random(0, 100) < 30 then
11288                comms_target:orderAttack(player)
11289                setCommsMessage(taunt_success_reply);
11290            else
11291                setCommsMessage(taunt_failed_reply);
11292            end
11293        end)
11294        return true
11295    end
11296    return false
11297end
11298function neutralDefendComms(comms_data)
11299    if comms_data.friendlyness > 50 then
11300        setCommsMessage("Sorry, we have no time to chat with you.\nWe are on an important mission.");
11301    else
11302        setCommsMessage("We have nothing for you.\nGood day.");
11303    end
11304    return true
11305end
11306
11307function playerShipCargoInventory(p)
11308	p:addToShipLog(string.format("%s Current cargo:",p:getCallSign()),"Yellow")
11309	local goodCount = 0
11310	if p.goods ~= nil then
11311		for good, goodQuantity in pairs(p.goods) do
11312			goodCount = goodCount + 1
11313			p:addToShipLog(string.format("     %s: %i",good,goodQuantity),"Yellow")
11314		end
11315	end
11316	if goodCount < 1 then
11317		p:addToShipLog("     Empty","Yellow")
11318	end
11319	p:addToShipLog(string.format("Available space: %i",p.cargo),"Yellow")
11320end
11321function resetPreviousSystemHealth(p)
11322	string.format("")	--may need global context
11323	if p == nil then
11324		p = comms_source
11325	end
11326	local currentShield = 0
11327	if p:getShieldCount() > 1 then
11328		currentShield = (p:getSystemHealth("frontshield") + p:getSystemHealth("rearshield"))/2
11329	else
11330		currentShield = p:getSystemHealth("frontshield")
11331	end
11332	p.prevShield = currentShield
11333	p.prevReactor = p:getSystemHealth("reactor")
11334	p.prevManeuver = p:getSystemHealth("maneuver")
11335	p.prevImpulse = p:getSystemHealth("impulse")
11336	if p:getBeamWeaponRange(0) > 0 then
11337		if p.healthyBeam == nil then
11338			p.healthyBeam = 1.0
11339			p.prevBeam = 1.0
11340		end
11341		p.prevBeam = p:getSystemHealth("beamweapons")
11342	end
11343	if p:getWeaponTubeCount() > 0 then
11344		if p.healthyMissile == nil then
11345			p.healthyMissile = 1.0
11346			p.prevMissile = 1.0
11347		end
11348		p.prevMissile = p:getSystemHealth("missilesystem")
11349	end
11350	if p:hasWarpDrive() then
11351		if p.healthyWarp == nil then
11352			p.healthyWarp = 1.0
11353			p.prevWarp = 1.0
11354		end
11355		p.prevWarp = p:getSystemHealth("warp")
11356	end
11357	if p:hasJumpDrive() then
11358		if p.healthyJump == nil then
11359			p.healthyJump = 1.0
11360			p.prevJump = 1.0
11361		end
11362		p.prevJump = p:getSystemHealth("jumpdrive")
11363	end
11364end
11365function gatherStats()
11366	local stat_list = {}
11367	stat_list.scenario = {name = "Chaos of War", version = scenario_version}
11368	stat_list.times = {}
11369	stat_list.times.game = {}
11370	stat_list.times.stage = game_state
11371	stat_list.times.game.max = max_game_time
11372	stat_list.times.game.total_seconds_left = game_time_limit
11373	stat_list.times.game.minutes_left = math.floor(game_time_limit / 60)
11374	stat_list.times.game.seconds_left = math.floor(game_time_limit % 60)
11375	stat_list.human = {}
11376	stat_list.human.ship = {}
11377	stat_list.human.ship_score_total = 0
11378	stat_list.human.npc = {}
11379	stat_list.human.npc_score_total = 0
11380	stat_list.human.station_score_total = 0
11381	stat_list.human.station = {}
11382	stat_list.kraylor = {}
11383	stat_list.kraylor.ship = {}
11384	stat_list.kraylor.ship_score_total = 0
11385	stat_list.kraylor.npc = {}
11386	stat_list.kraylor.npc_score_total = 0
11387	stat_list.kraylor.station_score_total = 0
11388	stat_list.kraylor.station = {}
11389	if exuari_angle ~= nil then
11390		stat_list.exuari = {}
11391		stat_list.exuari.ship = {}
11392		stat_list.exuari.ship_score_total = 0
11393		stat_list.exuari.npc = {}
11394		stat_list.exuari.npc_score_total = 0
11395		stat_list.exuari.station_score_total = 0
11396		stat_list.exuari.station = {}
11397	end
11398	if ktlitan_angle ~= nil then
11399		stat_list.ktlitan = {}
11400		stat_list.ktlitan.ship = {}
11401		stat_list.ktlitan.ship_score_total = 0
11402		stat_list.ktlitan.npc = {}
11403		stat_list.ktlitan.npc_score_total = 0
11404		stat_list.ktlitan.station_score_total = 0
11405		stat_list.ktlitan.station = {}
11406	end
11407	for pidx=1,32 do
11408		p = getPlayerShip(pidx)
11409		if p ~= nil then
11410			if p:isValid() then
11411				local faction = p:getFaction()
11412				if p.shipScore ~= nil then
11413					stat_list[f2s[faction]].ship_score_total = stat_list[f2s[faction]].ship_score_total + p.shipScore
11414					stat_list[f2s[faction]].ship[p:getCallSign()] = {template_type = p:getTypeName(), is_alive = true, score_value = p.shipScore}
11415				else
11416					print("ship score for " .. p:getCallSign() .. " has not been set")
11417				end
11418			end
11419		end
11420	end
11421	if npc_fleet ~= nil then
11422		for faction, list in pairs(npc_fleet) do
11423			for _, ship in ipairs(list) do
11424				if ship:isValid() then
11425					stat_list[f2s[faction]].npc_score_total = stat_list[f2s[faction]].npc_score_total + ship.score_value
11426					stat_list[f2s[faction]].npc[ship:getCallSign()] = {template_type = ship:getTypeName(), is_alive = true, score_value = ship.score_value}
11427				end
11428			end
11429		end
11430	end
11431	if scientist_list ~= nil then
11432		for faction, list in pairs(scientist_list) do
11433			for _, scientist in ipairs(list) do
11434				if scientist.location:isValid() then
11435					stat_list[f2s[faction]].npc_score_total = stat_list[f2s[faction]].npc_score_total + scientist.score_value
11436					stat_list[f2s[faction]].npc[scientist.name] = {topic = scientist.topic, is_alive = true, score_value = scientist.score_value, location_name = scientist.location_name}
11437				end
11438			end
11439		end
11440	end
11441	for faction, list in pairs(station_list) do
11442		for _, station in ipairs(list) do
11443			if station:isValid() then
11444				stat_list[f2s[faction]].station_score_total = stat_list[f2s[faction]].station_score_total + station.score_value
11445				stat_list[f2s[faction]].station[station:getCallSign()] = {template_type = station:getTypeName(), is_alive = true, score_value = station.score_value}
11446			end
11447		end
11448	end
11449	local station_weight = .6
11450	local player_ship_weight = .3
11451	local npc_ship_weight = .1
11452	stat_list.weight = {}
11453	stat_list.weight.station = station_weight
11454	stat_list.weight.ship = player_ship_weight
11455	stat_list.weight.npc = npc_ship_weight
11456	local human_death_penalty = 0
11457	local kraylor_death_penalty = 0
11458	local exuari_death_penalty = 0
11459	local ktlitan_death_penalty = 0
11460	if respawn_type == "self" then
11461		human_death_penalty = death_penalty["Human Navy"]
11462		kraylor_death_penalty = death_penalty["Kraylor"]
11463		if exuari_angle ~= nil then
11464			exuari_death_penalty = death_penalty["Exuari"]
11465		end
11466		if ktlitan_angle ~= nil then
11467			ktlitan_death_penalty = death_penalty["Ktlitans"]
11468		end
11469	end
11470	stat_list.human.weighted_score =
11471		stat_list.human.station_score_total*station_weight +
11472		stat_list.human.ship_score_total*player_ship_weight +
11473		stat_list.human.npc_score_total*npc_ship_weight -
11474		human_death_penalty
11475	stat_list.kraylor.weighted_score =
11476		stat_list.kraylor.station_score_total*station_weight +
11477		stat_list.kraylor.ship_score_total*player_ship_weight +
11478		stat_list.kraylor.npc_score_total*npc_ship_weight -
11479		kraylor_death_penalty
11480	if exuari_angle ~= nil then
11481		stat_list.exuari.weighted_score =
11482			stat_list.exuari.station_score_total*station_weight +
11483			stat_list.exuari.ship_score_total*player_ship_weight +
11484			stat_list.exuari.npc_score_total*npc_ship_weight -
11485			exuari_death_penalty
11486	end
11487	if ktlitan_angle ~= nil then
11488		stat_list.ktlitan.weighted_score =
11489			stat_list.ktlitan.station_score_total*station_weight +
11490			stat_list.ktlitan.ship_score_total*player_ship_weight +
11491			stat_list.ktlitan.npc_score_total*npc_ship_weight -
11492			ktlitan_death_penalty
11493	end
11494	if original_score ~= nil then
11495		stat_list.human.original_weighted_score = original_score["Human Navy"]
11496		stat_list.kraylor.original_weighted_score = original_score["Kraylor"]
11497		if exuari_angle ~= nil then
11498			stat_list.exuari.original_weighted_score = original_score["Exuari"]
11499		end
11500		if ktlitan_angle ~= nil then
11501			stat_list.ktlitan.original_weighted_score = original_score["Ktlitans"]
11502		end
11503	end
11504	return stat_list
11505end
11506function pickWinner(reason)
11507	local stat_list = gatherStats()
11508	local sorted_faction = {}
11509	local tie_breaker = {}
11510	for pidx=1,32 do
11511		local p = getPlayerShip(pidx)
11512		if p ~= nil and p:isValid() then
11513			tie_breaker[p:getFaction()] = p:getReputationPoints()/10000
11514		end
11515	end
11516	stat_list.human.weighted_score = stat_list.human.weighted_score + tie_breaker["Human Navy"]
11517	table.insert(sorted_faction,{name="Human Navy",score=stat_list.human.weighted_score})
11518	stat_list.kraylor.weighted_score = stat_list.kraylor.weighted_score + tie_breaker["Kraylor"]
11519	table.insert(sorted_faction,{name="Kraylor",score=stat_list.kraylor.weighted_score})
11520	if exuari_angle ~= nil then
11521		stat_list.exuari.weighted_score = stat_list.exuari.weighted_score + tie_breaker["Exuari"]
11522		table.insert(sorted_faction,{name="Exuari",score=stat_list.exuari.weighted_score})
11523	end
11524	if ktlitan_angle ~= nil then
11525		stat_list.ktlitan.weighted_score = stat_list.ktlitan.weighted_score + tie_breaker["Ktlitans"]
11526		table.insert(sorted_faction,{name="Ktlitans",score=stat_list.ktlitan.weighted_score})
11527	end
11528	table.sort(sorted_faction,function(a,b)
11529		return a.score > b.score
11530	end)
11531	local out = string.format("%s wins with a score of %.1f!\n",sorted_faction[1].name,sorted_faction[1].score)
11532	for i=2,#sorted_faction do
11533		out = out .. string.format("%s:%.1f ",sorted_faction[i].name,sorted_faction[i].score)
11534	end
11535	out = out .. "\n" .. reason
11536	print(out)
11537	print("Humans:",stat_list.human.weighted_score)
11538	print("Kraylor:",stat_list.kraylor.weighted_score)
11539	if exuari_angle then
11540		print("Exuari:",stat_list.exuari.weighted_score)
11541	end
11542	if ktlitan_angle then
11543		print("Ktlitans:",stat_list.ktlitan.weighted_score)
11544	end
11545	addGMMessage(out)
11546	globalMessage(out)
11547	game_state = string.format("victory-%s",f2s[sorted_faction[1].name])
11548	victory(sorted_faction[1].name)
11549end
11550function update(delta)
11551	if delta == 0 then
11552		--game paused
11553		return
11554	end
11555	if respawn_countdown ~= nil then
11556		respawn_countdown = respawn_countdown - delta
11557		if respawn_countdown < 0 then
11558			delayedRespawn()
11559		end
11560	end
11561	if mainGMButtons == mainGMButtonsDuringPause then
11562		mainGMButtons = mainGMButtonsAfterPause
11563		mainGMButtons()
11564	end
11565	if not terrain_generated then
11566		generateTerrain()
11567	end
11568	game_state = "running"
11569	local stat_list = gatherStats()
11570	if stat_list.human.weighted_score < original_score["Human Navy"]/2 then
11571		pickWinner("End cause: Human Navy fell below 50% of original strength")
11572	end
11573	if stat_list.kraylor.weighted_score < original_score["Kraylor"]/2 then
11574		pickWinner("End cause: Kraylor fell below 50% of original strength")
11575	end
11576	if exuari_angle ~= nil then
11577		if stat_list.exuari.weighted_score < original_score["Exuari"]/2 then
11578			pickWinner("End cause: Exuari fell below 50% of original strength")
11579		end
11580	end
11581	if ktlitan_angle ~= nil then
11582		if stat_list.ktlitan.weighted_score < original_score["Ktlitans"]/2 then
11583			pickWinner("End cause: Ktlitans fell below 50% of original strength")
11584		end
11585	end
11586	game_time_limit = game_time_limit - delta
11587	if game_time_limit < 0 then
11588		pickWinner("End cause: Time ran out")
11589	end
11590	local hrs = stat_list.human.weighted_score/original_score["Human Navy"]
11591	local krs = stat_list.kraylor.weighted_score/original_score["Kraylor"]
11592	local rel_dif = math.abs(hrs-krs)
11593	if rel_dif > thresh then
11594		if exuari_angle ~= nil then
11595			ers = stat_list.exuari.weighted_score/original_score["Exuari"]
11596			rel_dif = math.abs(hrs-ers)
11597			local ref_dif_2 = math.abs(ers-krs)
11598			if rel_dif > thresh or ref_dif_2 > thresh then
11599				if ktlitan_angle ~= nil then
11600					brs = stat_list.ktlitan.weighted_score/original_score["Ktlitans"]
11601					rel_dif = math.abs(brs-ers)
11602					ref_dif_2 = math.abs(brs-krs)
11603					local rel_dif_3 = math.abs(hrs-brs)
11604					if rel_dif > thresh or ref_dif_2 > thresh or rel_dif_3 > thresh then
11605						pickWinner(string.format("End cause: score difference exceeded %i%%",thresh*100))
11606					end
11607				else
11608					pickWinner(string.format("End cause: score difference exceeded %i%%",thresh*100))
11609				end
11610			end
11611		else
11612			pickWinner(string.format("End cause: score difference exceeded %i%%",thresh*100))
11613		end
11614	end
11615	local score_banner = string.format("H:%i K:%i",math.floor(stat_list.human.weighted_score),math.floor(stat_list.kraylor.weighted_score))
11616	if exuari_angle ~= nil then
11617		score_banner = string.format("%s E:%i",score_banner,math.floor(stat_list.exuari.weighted_score))
11618	end
11619	if ktlitan_angle ~= nil then
11620		score_banner = string.format("%s B:%i",score_banner,math.floor(stat_list.ktlitan.weighted_score))
11621	end
11622	if game_time_limit > 60 then
11623		score_banner = string.format("%s %i:%.2i",score_banner,stat_list.times.game.minutes_left,stat_list.times.game.seconds_left)
11624	else
11625		score_banner = string.format("%s %i",score_banner,stat_list.times.game.seconds_left)
11626	end
11627	if scientist_asset_message == nil then
11628		scientist_asset_message = "sent"
11629		if scientist_list ~= nil then
11630			for pidx=1,32 do
11631				local p = getPlayerShip(pidx)
11632				if p ~= nil and p:isValid() then
11633					if scientist_list[p:getFaction()] ~= nil then
11634						if #scientist_list[p:getFaction()] > 1 then
11635							p:addToShipLog("In addition to the stations and fleet assets, Command has deemed certain scientists as critical to the war effort. Loss of these scientists will count against you like the loss of stations and fleet assets will. Scientist list:","Magenta")
11636						else
11637							p:addToShipLog("In addition to the stations and fleet assets, Command has deemed this scientist as critical to the war effort. Loss of this scientist will count against you like the loss of stations and fleet assets will. Scientist:","Magenta")
11638						end
11639						for _, scientist in ipairs(scientist_list[p:getFaction()]) do
11640							p:addToShipLog(string.format("Value: %i, Name: %s, Specialization: %s, Location: %s",scientist.score_value,scientist.name,scientist.topic,scientist.location_name),"Magenta")
11641						end
11642						if #scientist_list[p:getFaction()] > 1 then
11643							p:addToShipLog("These scientists will be weighted with the other NPC assets","Magenta")
11644						else
11645							p:addToShipLog("This scientist will be weighted with the other NPC assets","Magenta")
11646						end
11647					end
11648				end
11649			end
11650		end
11651	end
11652	healthCheckTimer = healthCheckTimer - delta
11653	local warning_message = nil
11654	local warning_station = nil
11655	local warning_message = {}
11656	local warning_station = {}
11657	for stn_faction, stn_list in pairs(station_list) do
11658		for station_index=1,#stn_list do
11659			local current_station = stn_list[station_index]
11660			if current_station ~= nil and current_station:isValid() then
11661				if current_station.proximity_warning == nil then
11662					for _, obj in ipairs(current_station:getObjectsInRange(station_sensor_range)) do
11663						if obj ~= nil and obj:isValid() then
11664							if obj:isEnemy(current_station) then
11665								local obj_type_name = obj.typeName
11666								if obj_type_name ~= nil and string.find(obj_type_name,"PlayerSpaceship") then
11667									warning_station[stn_faction] = current_station
11668									warning_message[stn_faction] = string.format("[%s in %s] We detect one or more enemies nearby. At least one is of type %s",current_station:getCallSign(),current_station:getSectorName(),obj:getTypeName())
11669									current_station.proximity_warning = warning_message[stn_faction]
11670									current_station.proximity_warning_timer = delta + 300
11671									break
11672								end
11673							end
11674						end
11675					end
11676					if warning_station[stn_faction] ~= nil then	--was originally warning message
11677						break
11678					end
11679				else
11680					current_station.proximity_warning_timer = current_station.proximity_warning_timer - delta
11681					if current_station.proximity_warning_timer < 0 then
11682						current_station.proximity_warning = nil
11683					end
11684				end
11685				if warning_station[stn_faction] == nil then
11686					--shield damage warning
11687					if current_station.shield_damage_warning == nil then
11688						for i=1,current_station:getShieldCount() do
11689							if current_station:getShieldLevel(i-1) < current_station:getShieldMax(i-1) then
11690								warning_station[stn_faction] = current_station
11691								warning_message[stn_faction] = string.format("[%s in %s] Our shields have taken damage",current_station:getCallSign(),current_station:getSectorName())
11692								current_station.shield_damage_warning = warning_message[stn_faction]
11693								current_station.shield_damage_warning_timer = delta + 300
11694								break
11695							end
11696						end
11697						if warning_station[stn_faction] ~= nil then
11698							break
11699						end
11700					else
11701						current_station.shield_damage_warning_timer = current_station.shield_damage_warning_timer - delta
11702						if current_station.shield_damage_warning_timer < 0 then
11703							current_station.shield_damage_warning = nil
11704						end
11705					end
11706				end
11707				if warning_station[stn_faction] == nil then
11708					--severe shield damage warning
11709					if current_station.severe_shield_warning == nil then
11710						local current_station_shield_count = current_station:getShieldCount()
11711						for i=1,current_station_shield_count do
11712							if current_station:getShieldLevel(i-1) < current_station:getShieldMax(i-1)*.1 then
11713								warning_station[stn_faction] = current_station
11714								if current_station_shield_count == 1 then
11715									warning_message[stn_faction] = string.format("[%s in %s] Our shields are nearly gone",current_station:getCallSign(),current_station:getSectorName())
11716								else
11717									warning_message[stn_faction] = string.format("[%s in %s] One or more of our shields are nearly gone",current_station:getCallSign(),current_station:getSectorName())
11718								end
11719								current_station.severe_shield_warning = warning_message[stn_faction]
11720								current_station.severe_shield_warning_timer = delta + 300
11721								break
11722							end
11723						end
11724						if warning_station[stn_faction] ~= nil then
11725							break
11726						end
11727					else
11728						current_station.severe_shield_warning_timer = current_station.severe_shield_warning_timer - delta
11729						if current_station.severe_shield_warning_timer < 0 then
11730							current_station.severe_shield_warning = nil
11731						end
11732					end
11733				end
11734				if warning_station[stn_faction] == nil then
11735					--hull damage warning
11736					if current_station.hull_warning == nil then
11737						if current_station:getHull() < current_station:getHullMax() then
11738							warning_station[stn_faction] = current_station
11739							warning_message[stn_faction] = string.format("[%s in %s] Our hull has been damaged",current_station:getCallSign(),current_station:getSectorName())
11740							current_station.hull_warning = warning_message[stn_faction]
11741							break
11742						end
11743					end
11744				end
11745				if warning_station[stn_faction] == nil then
11746					--severe hull damage warning
11747					if current_station.severe_hull_warning == nil then
11748						if current_station:getHull() < current_station:getHullMax()*.1 then
11749							warning_station[stn_faction] = current_station
11750							warning_message[stn_faction] = string.format("[%s in %s] We are on the brink of destruction",current_station:getCallSign(),current_station:getSectorName())
11751							current_station.severe_hull_warning = warning_message[stn_faction]
11752						end
11753					end
11754				end
11755			end	--	current station not nil and is valid
11756		end
11757	end
11758	for pidx=1,32 do
11759		local p = getPlayerShip(pidx)
11760		if p ~= nil and p:isValid() then
11761			local player_name = p:getCallSign()
11762			if warning_station["Human Navy"] ~= nil and p:getFaction() == "Human Navy" then
11763				p:addToShipLog(warning_message["Human Navy"],"Red")
11764			end
11765			if warning_station["Kraylor"] ~= nil and p:getFaction() == "Kraylor" then
11766				p:addToShipLog(warning_message["Kraylor"],"Red")
11767			end
11768			if exuari_angle ~= nil then
11769				if warning_station["Exuari"] ~= nil and p:getFaction() == "Exuari" then
11770					p:addToShipLog(warning_message["Exuari"],"Red")
11771				end
11772			end
11773			if ktlitan_angle ~= nil then
11774				if warning_station["Ktlitans"] ~= nil and p:getFaction() == "Ktlitans" then
11775					p:addToShipLog(warning_message["Ktlitans"],"Red")
11776				end
11777			end
11778			local name_tag_text = string.format("%s in %s",player_name,p:getSectorName())
11779			if p:hasPlayerAtPosition("Relay") then
11780				p.name_tag = "name_tag"
11781				p:addCustomInfo("Relay",p.name_tag,name_tag_text)
11782				p.score_banner = "score_banner"
11783				p:addCustomInfo("Relay",p.score_banner,score_banner)
11784			end
11785			if p:hasPlayerAtPosition("Operations") then
11786				p.name_tag_ops = "name_tag_ops"
11787				p:addCustomInfo("Operations",p.name_tag_ops,name_tag_text)
11788				p.score_banner_ops = "score_banner_ops"
11789				p:addCustomInfo("Operations",p.score_banner_ops,score_banner)
11790			end
11791			if p:hasPlayerAtPosition("ShipLog") then
11792				p.name_tag_log = "name_tag_log"
11793				p:addCustomInfo("ShipLog",p.name_tag_log,name_tag_text)
11794				p.score_banner_log = "score_banner_log"
11795				p:addCustomInfo("ShipLog",p.score_banner_log,score_banner)
11796			end
11797			if p:hasPlayerAtPosition("Helms") then
11798				p.name_tag_helm = "name_tag_helm"
11799				p:addCustomInfo("Helms",p.name_tag_helm,name_tag_text)
11800			end
11801			if p:hasPlayerAtPosition("Tactical") then
11802				p.name_tag_tac = "name_tag_tac"
11803				p:addCustomInfo("Tactical",p.name_tag_tac,name_tag_text)
11804			end
11805			if p.inventoryButton == nil then
11806				local goodCount = 0
11807				if p.goods ~= nil then
11808					for good, goodQuantity in pairs(p.goods) do
11809						goodCount = goodCount + 1
11810					end
11811				end
11812				if goodCount > 0 then		--add inventory button when cargo acquired
11813					if p:hasPlayerAtPosition("Relay") then
11814						if p.inventoryButton == nil then
11815							local tbi = "inventory" .. player_name
11816							p:addCustomButton("Relay",tbi,"Inventory",function () playerShipCargoInventory(p) end)
11817							p.inventoryButton = true
11818						end
11819					end
11820					if p:hasPlayerAtPosition("Operations") then
11821						if p.inventoryButton == nil then
11822							local tbi = "inventoryOp" .. player_name
11823							p:addCustomButton("Operations",tbi,"Inventory", function () playerShipCargoInventory(p) end)
11824							p.inventoryButton = true
11825						end
11826					end
11827				end
11828			end
11829			if healthCheckTimer < 0 then	--check to see if any crew perish (or other consequences) due to excessive damage
11830				if p:getRepairCrewCount() > 0 then
11831					local fatalityChance = 0
11832					local currentShield = 0
11833					if p:getShieldCount() > 1 then
11834						currentShield = (p:getSystemHealth("frontshield") + p:getSystemHealth("rearshield"))/2
11835					else
11836						currentShield = p:getSystemHealth("frontshield")
11837					end
11838					fatalityChance = fatalityChance + (p.prevShield - currentShield)
11839					p.prevShield = currentShield
11840					local currentReactor = p:getSystemHealth("reactor")
11841					fatalityChance = fatalityChance + (p.prevReactor - currentReactor)
11842					p.prevReactor = currentReactor
11843					local currentManeuver = p:getSystemHealth("maneuver")
11844					fatalityChance = fatalityChance + (p.prevManeuver - currentManeuver)
11845					p.prevManeuver = currentManeuver
11846					local currentImpulse = p:getSystemHealth("impulse")
11847					fatalityChance = fatalityChance + (p.prevImpulse - currentImpulse)
11848					p.prevImpulse = currentImpulse
11849					if p:getBeamWeaponRange(0) > 0 then
11850						if p.healthyBeam == nil then
11851							p.healthyBeam = 1.0
11852							p.prevBeam = 1.0
11853						end
11854						local currentBeam = p:getSystemHealth("beamweapons")
11855						fatalityChance = fatalityChance + (p.prevBeam - currentBeam)
11856						p.prevBeam = currentBeam
11857					end
11858					if p:getWeaponTubeCount() > 0 then
11859						if p.healthyMissile == nil then
11860							p.healthyMissile = 1.0
11861							p.prevMissile = 1.0
11862						end
11863						local currentMissile = p:getSystemHealth("missilesystem")
11864						fatalityChance = fatalityChance + (p.prevMissile - currentMissile)
11865						p.prevMissile = currentMissile
11866					end
11867					if p:hasWarpDrive() then
11868						if p.healthyWarp == nil then
11869							p.healthyWarp = 1.0
11870							p.prevWarp = 1.0
11871						end
11872						local currentWarp = p:getSystemHealth("warp")
11873						fatalityChance = fatalityChance + (p.prevWarp - currentWarp)
11874						p.prevWarp = currentWarp
11875					end
11876					if p:hasJumpDrive() then
11877						if p.healthyJump == nil then
11878							p.healthyJump = 1.0
11879							p.prevJump = 1.0
11880						end
11881						local currentJump = p:getSystemHealth("jumpdrive")
11882						fatalityChance = fatalityChance + (p.prevJump - currentJump)
11883						p.prevJump = currentJump
11884					end
11885					if p:getRepairCrewCount() == 1 then
11886						fatalityChance = fatalityChance/2	-- increase survival chances of last repair crew standing
11887					end
11888					if fatalityChance > 0 then
11889						if math.random() < (fatalityChance) then
11890							if p.initialCoolant == nil then
11891								p:setRepairCrewCount(p:getRepairCrewCount() - 1)
11892								if p:hasPlayerAtPosition("Engineering") then
11893									local repairCrewFatality = "repairCrewFatality"
11894									p:addCustomMessage("Engineering",repairCrewFatality,"One of your repair crew has perished")
11895								end
11896								if p:hasPlayerAtPosition("Engineering+") then
11897									local repairCrewFatalityPlus = "repairCrewFatalityPlus"
11898									p:addCustomMessage("Engineering+",repairCrewFatalityPlus,"One of your repair crew has perished")
11899								end
11900							else
11901								local consequence = 0
11902								local upper_consequence = 2
11903								local consequence_list = {}
11904								if p:getCanLaunchProbe() then
11905									upper_consequence = upper_consequence + 1
11906									table.insert(consequence_list,"probe")
11907								end
11908								if p:getCanHack() then
11909									upper_consequence = upper_consequence + 1
11910									table.insert(consequence_list,"hack")
11911								end
11912								if p:getCanScan() then
11913									upper_consequence = upper_consequence + 1
11914									table.insert(consequence_list,"scan")
11915								end
11916								if p:getCanCombatManeuver() then
11917									upper_consequence = upper_consequence + 1
11918									table.insert(consequence_list,"combat_maneuver")
11919								end
11920								if p:getCanSelfDestruct() then
11921									upper_consequence = upper_consequence + 1
11922									table.insert(consequence_list,"self_destruct")
11923								end
11924								if p:getWeaponTubeCount() > 0 then
11925									upper_consequence = upper_consequence + 1
11926									table.insert(consequence_list,"tube_time")
11927								end
11928								consequence = math.random(1,upper_consequence)
11929								if consequence == 1 then
11930									p:setRepairCrewCount(p:getRepairCrewCount() - 1)
11931									if p:hasPlayerAtPosition("Engineering") then
11932										local repairCrewFatality = "repairCrewFatality"
11933										p:addCustomMessage("Engineering",repairCrewFatality,"One of your repair crew has perished")
11934									end
11935									if p:hasPlayerAtPosition("Engineering+") then
11936										local repairCrewFatalityPlus = "repairCrewFatalityPlus"
11937										p:addCustomMessage("Engineering+",repairCrewFatalityPlus,"One of your repair crew has perished")
11938									end
11939								elseif consequence == 2 then
11940									local current_coolant = p:getMaxCoolant()
11941									local lost_coolant = 0
11942									if current_coolant >= 10 then
11943										lost_coolant = current_coolant*random(.25,.5)	--lose between 25 and 50 percent
11944									else
11945										lost_coolant = current_coolant*random(.15,.35)	--lose between 15 and 35 percent
11946									end
11947									p:setMaxCoolant(current_coolant - lost_coolant)
11948									if p.reclaimable_coolant == nil then
11949										p.reclaimable_coolant = 0
11950									end
11951									p.reclaimable_coolant = math.min(20,p.reclaimable_coolant + lost_coolant*random(.8,1))
11952									if p:hasPlayerAtPosition("Engineering") then
11953										local coolantLoss = "coolantLoss"
11954										p:addCustomMessage("Engineering",coolantLoss,"Damage has caused a loss of coolant")
11955									end
11956									if p:hasPlayerAtPosition("Engineering+") then
11957										local coolantLossPlus = "coolantLossPlus"
11958										p:addCustomMessage("Engineering+",coolantLossPlus,"Damage has caused a loss of coolant")
11959									end
11960								else
11961									local named_consequence = consequence_list[consequence-2]
11962									if named_consequence == "probe" then
11963										p:setCanLaunchProbe(false)
11964										if p:hasPlayerAtPosition("Engineering") then
11965											p:addCustomMessage("Engineering","probe_launch_damage_message","The probe launch system has been damaged")
11966										end
11967										if p:hasPlayerAtPosition("Engineering+") then
11968											p:addCustomMessage("Engineering+","probe_launch_damage_message_plus","The probe launch system has been damaged")
11969										end
11970									elseif named_consequence == "hack" then
11971										p:setCanHack(false)
11972										if p:hasPlayerAtPosition("Engineering") then
11973											p:addCustomMessage("Engineering","hack_damage_message","The hacking system has been damaged")
11974										end
11975										if p:hasPlayerAtPosition("Engineering+") then
11976											p:addCustomMessage("Engineering+","hack_damage_message_plus","The hacking system has been damaged")
11977										end
11978									elseif named_consequence == "scan" then
11979										p:setCanScan(false)
11980										if p:hasPlayerAtPosition("Engineering") then
11981											p:addCustomMessage("Engineering","scan_damage_message","The scanners have been damaged")
11982										end
11983										if p:hasPlayerAtPosition("Engineering+") then
11984											p:addCustomMessage("Engineering+","scan_damage_message_plus","The scanners have been damaged")
11985										end
11986									elseif named_consequence == "combat_maneuver" then
11987										p:setCanCombatManeuver(false)
11988										if p:hasPlayerAtPosition("Engineering") then
11989											p:addCustomMessage("Engineering","combat_maneuver_damage_message","Combat maneuver has been damaged")
11990										end
11991										if p:hasPlayerAtPosition("Engineering+") then
11992											p:addCustomMessage("Engineering+","combat_maneuver_damage_message_plus","Combat maneuver has been damaged")
11993										end
11994									elseif named_consequence == "self_destruct" then
11995										p:setCanSelfDestruct(false)
11996										if p:hasPlayerAtPosition("Engineering") then
11997											p:addCustomMessage("Engineering","self_destruct_damage_message","Self destruct system has been damaged")
11998										end
11999										if p:hasPlayerAtPosition("Engineering+") then
12000											p:addCustomMessage("Engineering+","self_destruct_damage_message_plus","Self destruct system has been damaged")
12001										end
12002									elseif named_consequence == "tube_time" then
12003										local tube_count = p:getWeaponTubeCount()
12004										local tube_index = 0
12005										if p.normal_tube_load_time == nil then
12006											p.normal_tube_load_time = {}
12007											repeat
12008												p.normal_tube_load_time[tube_index] = p:getTubeLoadTime(tube_index)
12009												tube_index = tube_index + 1
12010											until(tube_index >= tube_count)
12011											tube_index = 0
12012										end
12013										repeat
12014											p:setTubeLoadTime(tube_index,p:getTubeLoadTime(tube_index) + 2)
12015											tube_index = tube_index + 1
12016										until(tube_index >= tube_count)
12017										if p:hasPlayerAtPosition("Engineering") then
12018											p:addCustomMessage("Engineering","tube_slow_down_message","Tube damage has caused tube load time to increase")
12019										end
12020										if p:hasPlayerAtPosition("Engineering+") then
12021											p:addCustomMessage("Engineering+","tube_slow_down_message_plus","Tube damage has caused tube load time to increase")
12022										end
12023									end
12024								end	--coolant loss branch
12025							end	--could lose coolant branch
12026						end	--bad consequences of damage branch
12027					end	--possible chance of bad consequences branch
12028				else	--no repair crew left
12029					if random(1,100) <= 4 then
12030						p:setRepairCrewCount(1)
12031						if p:hasPlayerAtPosition("Engineering") then
12032							local repairCrewRecovery = "repairCrewRecovery"
12033							p:addCustomMessage("Engineering",repairCrewRecovery,"Medical team has revived one of your repair crew")
12034						end
12035						if p:hasPlayerAtPosition("Engineering+") then
12036							local repairCrewRecoveryPlus = "repairCrewRecoveryPlus"
12037							p:addCustomMessage("Engineering+",repairCrewRecoveryPlus,"Medical team has revived one of your repair crew")
12038						end
12039						resetPreviousSystemHealth(p)
12040					end	--medical science triumph branch
12041				end	--no repair crew left
12042				if p.initialCoolant ~= nil then
12043					current_coolant = p:getMaxCoolant()
12044					if current_coolant < 20 then
12045						if random(1,100) <= 4 then
12046							local reclaimed_coolant = 0
12047							if p.reclaimable_coolant ~= nil and p.reclaimable_coolant > 0 then
12048								reclaimed_coolant = p.reclaimable_coolant*random(.1,.5)	--get back 10 to 50 percent of reclaimable coolant
12049								p:setMaxCoolant(math.min(20,current_coolant + reclaimed_coolant))
12050								p.reclaimable_coolant = p.reclaimable_coolant - reclaimed_coolant
12051							end
12052							local noticable_reclaimed_coolant = math.floor(reclaimed_coolant)
12053							if noticable_reclaimed_coolant > 0 then
12054								if p:hasPlayerAtPosition("Engineering") then
12055									local coolant_recovery = "coolant_recovery"
12056									p:addCustomMessage("Engineering",coolant_recovery,"Automated systems have recovered some coolant")
12057								end
12058								if p:hasPlayerAtPosition("Engineering+") then
12059									local coolant_recovery_plus = "coolant_recovery_plus"
12060									p:addCustomMessage("Engineering+",coolant_recovery_plus,"Automated systems have recovered some coolant")
12061								end
12062							end
12063							resetPreviousSystemHealth(p)
12064						end
12065					end
12066				end
12067			end	--health check branch
12068			local secondary_systems_optimal = true
12069			if not p:getCanLaunchProbe() then
12070				secondary_systems_optimal = false
12071			end
12072			if secondary_systems_optimal and not p:getCanHack() then
12073				secondary_systems_optimal = false
12074			end
12075			if secondary_systems_optimal and not p:getCanScan() then
12076				secondary_systems_optimal = false
12077			end
12078			if secondary_systems_optimal and not p:getCanCombatManeuver() then
12079				secondary_systems_optimal = false
12080			end
12081			if secondary_systems_optimal and not p:getCanSelfDestruct() then
12082				secondary_systems_optimal = false
12083			end
12084			if secondary_systems_optimal then
12085				local tube_count = p:getWeaponTubeCount()
12086				if tube_count > 0 and p.normal_tube_load_time ~= nil then
12087					local tube_index = 0
12088					repeat
12089						if p.normal_tube_load_time[tube_index] ~= p:getTubeLoadTime(tube_index) then
12090							secondary_systems_optimal = false
12091							break
12092						end
12093						tube_index = tube_index + 1
12094					until(tube_index >= tube_count)
12095				end
12096			end
12097			if secondary_systems_optimal then	--remove damage report button
12098				if p.damage_report ~= nil then
12099					p:removeCustom(p.damage_report)
12100					p.damage_report = nil
12101				end
12102				if p.damage_report_plus ~= nil then
12103					p:removeCustom(p.damage_report_plus)
12104					p.damage_report_plus = nil
12105				end
12106			else	--add damage report button
12107				if p:hasPlayerAtPosition("Engineering") then
12108					p.damage_report = "damage_report"
12109					p:addCustomButton("Engineering",p.damage_report,"Damage Report",function()
12110						local dmg_msg = "In addition to the primary systems constantly monitored in engineering, the following secondary systems have also been damaged requiring docking repair facilities:"
12111						if not p:getCanLaunchProbe() then
12112							dmg_msg = dmg_msg .. "\nProbe launch system"
12113						end
12114						if not p:getCanHack() then
12115							dmg_msg = dmg_msg .. "\nHacking system"
12116						end
12117						if not p:getCanScan() then
12118							dmg_msg = dmg_msg .. "\nScanning system"
12119						end
12120						if not p:getCanCombatManeuver() then
12121							dmg_msg = dmg_msg .. "\nCombat maneuvering system"
12122						end
12123						if not p:getCanSelfDestruct() then
12124							dmg_msg = dmg_msg .. "\nSelf destruct system"
12125						end
12126						local tube_count = p:getWeaponTubeCount()
12127						if tube_count > 0 then
12128							if tube_count > 0 and p.normal_tube_load_time ~= nil then
12129								local tube_index = 0
12130								repeat
12131									if p.normal_tube_load_time[tube_index] ~= p:getTubeLoadTime(tube_index) then
12132										dmg_msg = dmg_msg .. "\nWeapon tube load time degraded"
12133										break
12134									end
12135									tube_index = tube_index + 1
12136								until(tube_index >= tube_count)
12137							end
12138						end
12139						p.dmg_msg = "dmg_msg"
12140						p:addCustomMessage("Engineering",p.dmg_msg,dmg_msg)
12141					end)
12142				end	--engineering damage report button
12143				if p:hasPlayerAtPosition("Engineering+") then
12144					p.damage_report_plus = "damage_report_plus"
12145					p:addCustomButton("Engineering",p.damage_report_plus,"Damage Report",function()
12146						local dmg_msg = "In addition to the primary systems constantly monitored in engineering, the following secondary systems have also been damaged requiring docking repair facilities:"
12147						if not p:getCanLaunchProbe() then
12148							dmg_msg = dmg_msg .. "\nProbe launch system"
12149						end
12150						if not p:getCanHack() then
12151							dmg_msg = dmg_msg .. "\nHacking system"
12152						end
12153						if not p:getCanScan() then
12154							dmg_msg = dmg_msg .. "\nScanning system"
12155						end
12156						if not p:getCanCombatManeuver() then
12157							dmg_msg = dmg_msg .. "\nCombat maneuvering system"
12158						end
12159						if not p:getCanSelfDestruct() then
12160							dmg_msg = dmg_msg .. "\nSelf destruct system"
12161						end
12162						local tube_count = p:getWeaponTubeCount()
12163						if tube_count > 0 then
12164							if tube_count > 0 and p.normal_tube_load_time ~= nil then
12165								local tube_index = 0
12166								repeat
12167									if p.normal_tube_load_time[tube_index] ~= p:getTubeLoadTime(tube_index) then
12168										dmg_msg = dmg_msg .. "\nWeapon tube load time degraded"
12169										break
12170									end
12171									tube_index = tube_index + 1
12172								until(tube_index >= tube_count)
12173							end
12174						end
12175						p.dmg_msg = "dmg_msg"
12176						p:addCustomMessage("Engineering+",p.dmg_msg,dmg_msg)
12177					end)
12178				end	--engineering plus damage report button
12179			end	--damage report button necessary
12180			if p.normal_long_range_radar == nil then
12181				p.normal_long_range_radar = p:getLongRangeRadarRange()
12182			end
12183			local sensor_boost_amount = 0
12184			local sensor_boost_present = false
12185			if station_primary_human:isValid() then
12186				if p:isDocked(station_primary_human) then
12187					sensor_boost_present = true
12188					sensor_boost_amount = station_primary_human.comms_data.sensor_boost.value
12189				end
12190			end
12191			if station_primary_kraylor:isValid() then
12192				if p:isDocked(station_primary_kraylor) then
12193					sensor_boost_present = true
12194					sensor_boost_amount = station_primary_kraylor.comms_data.sensor_boost.value
12195				end
12196			end
12197			if exuari_angle ~= nil then
12198				if station_primary_exuari:isValid() then
12199					if p:isDocked(station_primary_exuari) then
12200						sensor_boost_present = true
12201						sensor_boost_amount = station_primary_exuari.comms_data.sensor_boost.value
12202					end
12203				end
12204			end
12205			if ktlitan_angle ~= nil then
12206				if station_primary_ktlitan:isValid() then
12207					if p:isDocked(station_primary_ktlitan) then
12208						sensor_boost_present = true
12209						sensor_boost_amount = station_primary_ktlitan.comms_data.sensor_boost.value
12210					end
12211				end
12212			end
12213			local boosted_range = p.normal_long_range_radar + sensor_boost_amount
12214			if sensor_boost_present then
12215				if p:getLongRangeRadarRange() < boosted_range then
12216					p:setLongRangeRadarRange(boosted_range)
12217				end
12218			else
12219				if p:getLongRangeRadarRange() > p.normal_long_range_radar then
12220					p:setLongRangeRadarRange(p.normal_long_range_radar)
12221				end
12222			end
12223		end	--p is not nil and is valid
12224	end	--loop through players
12225end
12226