1-- Name: Capture the Flag
2-- Description: Capture opposing team's "flag" before they capture yours
3---
4--- The region consists of two halves divided by a line of nebulae and/or markers. The first 5 minutes (configurable) each side decides where to place their flag. The ships closest to the referee station determine the team's flag location during the initial phase. Crossing to the other side during this phase will result in ship destruction. The weapons officer will mark the flag coordinates when the ship reaches the flag location. After the flag hide timer expires, an artifact will be placed at the location representing the team's flag. If no place has been marked, the ship's current location will be used. If the location is outside the game boundaries, the flag will be placed at the nearest in bounds location
5---
6--- Once the flags are placed, the hunt is on. Ships may cross the border in search of the other team's flag, but while they are in the other team's territory they may be tagged by an opponent ship within 0.75U. Being tagged sends you back to your own region with damage to your warp/jump drive. Each flag must be scanned before it can be retrived. Retrieval occurs by getting within 1U of the flag. Being tagged while in posession of the flag drops the flag at the location of the tag event. Cross back to your side with the flag to claim victory
7---
8--- Current version designed for post pandemic event, but the pandemic lasted longer than anticipated. Event was held 23Jan2021 with 14 player ships participating. Enjoy this scenario in your own multiple player ship event.
9-- Author: Xansta & Kilted-Klingon
10-- Type: Player ship vs. player ship, teams up to 16 ships per side
11-- Variation[Easy]: Easy enemies, told which opposing team ship picked up flag
12-- Variation[Hard]: Hard enemies, told nothing when opposing team picks up flag
13-- Variation[Small]: Smaller region: 50U, told when opposing team picks up flag
14-- Variation[Large]: Larger region: 200U, told when opposing team picks up flag
15-- Variation[Easy Small]: Easy enemies, smaller region: 50U, told which opposing team ship picked up flag
16-- Variation[Easy Large]: Easy enemies, larger region: 200U, told which opposing team ship picked up flag
17-- Variation[Hard Small]: Hard enemies, smaller region: 50U, told nothing when opposing team picks up flag
18-- Variation[Hard Large]: Hard enemies, larger region: 200U, told nothing when opposing team picks up flag
19
20require("utils.lua")
21
22function init()
23	scenario_version = "1.31.4"
24	print(string.format("     -----     Scenario: Capture the Flag     -----     Version %s     -----",scenario_version))
25	print(_VERSION)
26
27------------------------
28--	Global variables  --
29------------------------
30-- Variables that may be modified before game start to adjust game play
31	--[[
32	--If you insert a custom ship_name here, be sure to remove it from the pool of random names
33	preset_players = {}
34	--1st ship spawned: Maverick
35	table.insert(preset_players,
36		{
37			xo = "Starry",				--1st choice
38			ship_name = "Phoenix",
39			faction = "Human Navy",
40			ship_pref_1 = "Maverick",	--pref 2
41			ship_pref_2 = "Nautilus",	--pref 1
42			ship_pref_3 = "Player Cruiser",
43		}
44	)
45	table.insert(preset_players,
46		{
47			xo = "Aldric",				--3rd choice
48			faction = "Kraylor",
49			ship_name = "Durance",
50			ship_pref_1 = "Maverick",	--pref 2
51			ship_pref_2 = "Atlantis",	--pref 1
52			ship_pref_3 = "Crucible",
53			ship_pref_4 = "Piranha",
54			ship_pref_5 = "Player Cruiser",
55			ship_pref_6 = "Player Missile Cr.",
56		}
57	)
58	--2nd ship spawned: Atlantis
59	table.insert(preset_players,
60		{
61			xo = "Larry",
62			ship_name = "Mondo",
63			faction = "Human Navy",
64		}
65	)
66	table.insert(preset_players,
67		{
68			xo = "Epeac",				--2nd choice
69			faction = "Kraylor",
70			ship_name = "Dauntless",
71			ship_pref_1 = "Atlantis",
72			ship_pref_2 = "Maverick",
73			ship_pref_3 = "Crucible",
74		}
75	)
76	--3rd ship spawned: Phobos M3P
77	table.insert(preset_players,
78		{
79			xo = "Lupus",				--5th choice
80			faction = "Human Navy",
81			ship_name = "Harbinger",
82			ship_pref_1 = "PhobosM3P",		--Lupus prefers warp
83			ship_pref_4 = "Atlantis",		--Theta pref 1
84			ship_pref_2 = "Crucible",
85			ship_pref_3 = "Maverick",
86		}
87	)
88	table.insert(preset_players,
89		{
90			xo = "Daid",
91			faction = "Kraylor",
92			ship_name = "UltiShiptastic",
93		}
94	)
95	--4th ship spawned: Crucible
96	table.insert(preset_players,
97		{
98			xo = "Mo",
99			ship_name = "Shotgun",
100			faction = "Human Navy",
101		}
102	)
103	table.insert(preset_players,
104		{
105			xo = "Theta",				--4th choice
106			faction = "Kraylor",
107			ship_name = "Prokop",
108			ship_pref_1 = "Crucible",	--pref 2
109			ship_pref_2 = "Atlantis",	--pref 1
110			ship_pref_3 = "Maverick",
111			ship_pref_4 = "Phobos M3P",
112		}
113	)
114	--5th ship spawned: Flavia P.Falcon
115	table.insert(preset_players,
116		{
117			xo = "Curly",
118			ship_name = "Jayhawk",
119			faction = "Human Navy",
120		}
121	)
122	table.insert(preset_players,
123		{
124			xo = "AJ",
125			ship_name = "Roc",
126			faction = "Kraylor",
127		}
128	)
129	--6th ship spawned: Repulse
130	table.insert(preset_players,
131		{
132			xo = "Shemp",
133			ship_name = "Lizard",
134			faction = "Human Navy",
135		}
136	)
137	table.insert(preset_players,
138		{
139			xo = "Hemmond",
140			faction = "Kraylor",
141			ship_name = "Sentinel",
142		}
143	)
144	--7th ship spawned: Player Missile Cr.
145	table.insert(preset_players,
146		{
147			xo = "Ted",
148			ship_name = "Cremator",
149			faction = "Human Navy",
150		}
151	)
152	table.insert(preset_players,
153		{
154			xo = "Hermann",
155			ship_name = "Charger",
156			faction = "Kraylor",
157		}
158	)
159	--]]
160	diagnostic = false 			-- See GM button. A boolean for printing debug data to the console during development; turn to "false" during game play
161	timeDivision = "paused"
162	gameTimeLimit = 45*60		-- See GM button. Time limit for game; this is measured in real time seconds (example: 45*60 = 45 minutes)
163	hideFlagTime = 300			-- See GM button. Time given to hide flag; this is measured in real time seconds; (300 secs or 5 mins is the normal setting; 60 for certain tests)
164	maxGameTime = gameTimeLimit	-- See GM Button.
165	-- intial player placement locations; note that these locations are intended to be generally consistent and independent of the environment option chosen
166		--player side   		  Hum   Kra    Hum   Kra    Hum    Kra    Hum   Kra    Hum    Kra    Hum   Kra	  Hum	 Kra    Hum    Kra    Hum    Kra    Hum    Kra    Hum    Kra    Hum    Kra    Hum    Kra    Hum    Kra    Hum    Kra    Hum    Kra
167		--player index   		   1     2      3     4      5      6      7     8      9     10     11    12	  13	 14     15     16     17     18     19     20     21     22     23     24     25     26     27     28     29     30     31     32
168		playerStartX = 			{-1000, 1000, -1000, 1000, -1000,  1000, -2000, 2000, -2000,  2000, -2000, 2000, -3000,  3000, -1000,  1000, -1000,  1000, -2000,  2000, -2000,  2000, -3000,  3000, -3000,  3000, -3000,  3000, -3000,  3000, -4000,  4000}
169		playerStartY =			{    0,    0, -1000, 1000,  1000, -1000,     0,    0,  1000, -1000, -1000, 1000,	 0,     0, -2000,  2000,  2000, -2000, -2000,  2000,  2000, -2000, -1000,  1000,  1000, -1000, -2000,  2000,  2000, -2000,     0,     0}
170		player_tag_relocate_x = {-1000, 1000, -1000, 1000, -1000,  1000, -2000, 2000, -2000,  2000, -2000, 2000, -3000,	 3000, -1000,  1000, -1000,  1000, -2000,  2000, -2000,  2000, -3000,  3000, -3000,  3000, -3000,  3000, -3000,  3000, -4000,  4000}	--may override in terrain section
171		player_tag_relocate_y =	{    0,    0, -1000, 1000,  1000, -1000,     0,    0,  1000, -1000, -1000, 1000,     0,     0, -2000,  2000,  2000, -2000, -2000,  2000,  2000, -2000, -1000,  1000,  1000, -1000, -2000,  2000,  2000, -2000,     0,     0}
172		player_start_heading = 	{  270,   90,   270,   90,   270,    90,   270,   90,   270,    90,   270,   90,   270,    90,   270,    90,   270,    90,   270,    90,   270,    90,   270,    90,   270,    90,   270,    90,   270,    90,   270,    90}	--set both heading and rotation to avoid initial rotation upon game start
173		player_start_rotation =	{  180,    0,   180,    0,   180,     0,   180,    0,   180,     0,   180,    0,   180,     0,   180,     0,   180,     0,   180,     0,   180,     0,   180,     0,   180,     0,   180,     0,   180,     0,   180,     0}	--rotation points 90 degrees counter-clockwise of heading
174	player_wing_names = {
175		[2] = {
176			"Alpha","Red",
177		},
178		[4] = {
179			"Alpha",	"Red",
180			"Bravo",	"Blue",
181		},
182		[6] = {
183			"Alpha",	"Red",
184			"Bravo",	"Blue",
185			"Charlie",	"Green",
186		},
187		[8] = {
188			"Alpha 1",	"Red 1",
189			"Alpha 2",	"Red 2",
190			"Bravo 1",	"Blue 1",
191			"Bravo 2",	"Blue 2",
192		},
193		[10] = {
194			"Alpha 1",	"Red 1",
195			"Alpha 2",	"Red 2",
196			"Bravo 1",	"Blue 1",
197			"Bravo 2",	"Blue 2",
198			"Charlie",	"Green",
199		},
200		[12] = {
201			"Alpha 1",		"Red 1",
202			"Alpha 2",		"Red 2",
203			"Bravo 1",		"Blue 1",
204			"Bravo 2",		"Blue 2",
205			"Charlie 1",	"Green 1",
206			"Charlie 2",	"Green 2",
207		},
208		[14] = {
209			"Alpha 1",		"Red 1",
210			"Alpha 2",		"Red 2",
211			"Alpha 3",		"Red 3",
212			"Bravo 1",		"Blue 1",
213			"Bravo 2",		"Blue 2",
214			"Charlie 1",	"Green 1",
215			"Charlie 2",	"Green 2",
216		},
217		[16] = {
218			"Alpha 1",		"Red 1",
219			"Alpha 2",		"Red 2",
220			"Alpha 3",		"Red 3",
221			"Bravo 1",		"Blue 1",
222			"Bravo 2",		"Blue 2",
223			"Bravo 3",		"Blue 3",
224			"Charlie 1",	"Green 1",
225			"Charlie 2",	"Green 2",
226		},
227		[18] = {
228			"Alpha 1",		"Red 1",
229			"Alpha 2",		"Red 2",
230			"Alpha 3",		"Red 3",
231			"Bravo 1",		"Blue 1",
232			"Bravo 2",		"Blue 2",
233			"Bravo 3",		"Blue 3",
234			"Charlie 1",	"Green 1",
235			"Charlie 2",	"Green 2",
236			"Charlie 3",	"Green 3",
237		},
238		[20] = {
239			"Alpha 1",		"Red 1",
240			"Alpha 2",		"Red 2",
241			"Alpha 3",		"Red 3",
242			"Bravo 1",		"Blue 1",
243			"Bravo 2",		"Blue 2",
244			"Bravo 3",		"Blue 3",
245			"Charlie 1",	"Green 1",
246			"Charlie 2",	"Green 2",
247			"Delta 1",		"Yellow 1",
248			"Delta 2",		"Yellow 2",
249		},
250		[22] = {
251			"Alpha 1",		"Red 1",
252			"Alpha 2",		"Red 2",
253			"Alpha 3",		"Red 3",
254			"Bravo 1",		"Blue 1",
255			"Bravo 2",		"Blue 2",
256			"Bravo 3",		"Blue 3",
257			"Charlie 1",	"Green 1",
258			"Charlie 2",	"Green 2",
259			"Charlie 3",	"Green 3",
260			"Delta 1",		"Yellow 1",
261			"Delta 2",		"Yellow 2",
262		},
263		[24] = {
264			"Alpha 1",		"Red 1",
265			"Alpha 2",		"Red 2",
266			"Alpha 3",		"Red 3",
267			"Bravo 1",		"Blue 1",
268			"Bravo 2",		"Blue 2",
269			"Bravo 3",		"Blue 3",
270			"Charlie 1",	"Green 1",
271			"Charlie 2",	"Green 2",
272			"Charlie 3",	"Green 3",
273			"Delta 1",		"Yellow 1",
274			"Delta 2",		"Yellow 2",
275			"Delta 3",		"Yellow 3",
276		},
277		[26] = {
278			"Alpha 1",		"Red 1",
279			"Alpha 2",		"Red 2",
280			"Alpha 3",		"Red 3",
281			"Alpha 4",		"Red 4",
282			"Bravo 1",		"Blue 1",
283			"Bravo 2",		"Blue 2",
284			"Bravo 3",		"Blue 3",
285			"Charlie 1",	"Green 1",
286			"Charlie 2",	"Green 2",
287			"Charlie 3",	"Green 3",
288			"Delta 1",		"Yellow 1",
289			"Delta 2",		"Yellow 2",
290			"Delta 3",		"Yellow 3",
291		},
292		[28] = {
293			"Alpha 1",		"Red 1",
294			"Alpha 2",		"Red 2",
295			"Alpha 3",		"Red 3",
296			"Alpha 4",		"Red 4",
297			"Bravo 1",		"Blue 1",
298			"Bravo 2",		"Blue 2",
299			"Bravo 3",		"Blue 3",
300			"Bravo 4",		"Blue 4",
301			"Charlie 1",	"Green 1",
302			"Charlie 2",	"Green 2",
303			"Charlie 3",	"Green 3",
304			"Delta 1",		"Yellow 1",
305			"Delta 2",		"Yellow 2",
306			"Delta 3",		"Yellow 3",
307		},
308		[30] = {
309			"Alpha 1",		"Red 1",
310			"Alpha 2",		"Red 2",
311			"Alpha 3",		"Red 3",
312			"Alpha 4",		"Red 4",
313			"Bravo 1",		"Blue 1",
314			"Bravo 2",		"Blue 2",
315			"Bravo 3",		"Blue 3",
316			"Bravo 4",		"Blue 4",
317			"Charlie 1",	"Green 1",
318			"Charlie 2",	"Green 2",
319			"Charlie 3",	"Green 3",
320			"Charlie 4",	"Green 4",
321			"Delta 1",		"Yellow 1",
322			"Delta 2",		"Yellow 2",
323			"Delta 3",		"Yellow 3",
324		},
325		[32] = {
326			"Alpha 1",		"Red 1",
327			"Alpha 2",		"Red 2",
328			"Alpha 3",		"Red 3",
329			"Alpha 4",		"Red 4",
330			"Bravo 1",		"Blue 1",
331			"Bravo 2",		"Blue 2",
332			"Bravo 3",		"Blue 3",
333			"Bravo 4",		"Blue 4",
334			"Charlie 1",	"Green 1",
335			"Charlie 2",	"Green 2",
336			"Charlie 3",	"Green 3",
337			"Charlie 4",	"Green 4",
338			"Delta 1",		"Yellow 1",
339			"Delta 2",		"Yellow 2",
340			"Delta 3",		"Yellow 3",
341			"Delta 4",		"Yellow 4",
342		},
343	}
344	wingSquadronNames = false	-- See GM button. Set to true to name ships alpha/bravo/charlie vs. red/blue/green etc.; set to false to use randomized names from a list
345	player_ship_stats = {
346		["MP52 Hornet"] 		= { strength = 7, 	cargo = 3,	distance = 100,	long_range_radar = 18000, short_range_radar = 4000, probes = 10,	},
347		["Piranha"]				= { strength = 16,	cargo = 8,	distance = 200,	long_range_radar = 25000, short_range_radar = 6000, probes = 15,	},
348		["Flavia P.Falcon"]		= { strength = 13,	cargo = 15,	distance = 200,	long_range_radar = 40000, short_range_radar = 5000, probes = 27	,	},
349		["Phobos M3P"]			= { strength = 19,	cargo = 10,	distance = 200,	long_range_radar = 25000, short_range_radar = 5000, probes = 15,	},
350		["Atlantis"]			= { strength = 52,	cargo = 6,	distance = 400,	long_range_radar = 30000, short_range_radar = 5000, probes = 25,	},
351		["Player Cruiser"]		= { strength = 40,	cargo = 6,	distance = 400,	long_range_radar = 30000, short_range_radar = 5000, probes = 22,	},
352		["Player Missile Cr."]	= { strength = 45,	cargo = 8,	distance = 200,	long_range_radar = 35000, short_range_radar = 6000, probes = 26,	},
353		["Player Fighter"]		= { strength = 7,	cargo = 3,	distance = 100,	long_range_radar = 15000, short_range_radar = 4500, probes = 11,	},
354		["Benedict"]			= { strength = 10,	cargo = 9,	distance = 400,	long_range_radar = 30000, short_range_radar = 5000, probes = 20,	},
355		["Kiriya"]				= { strength = 10,	cargo = 9,	distance = 400,	long_range_radar = 35000, short_range_radar = 5000, probes = 20,	},
356		["Striker"]				= { strength = 8,	cargo = 4,	distance = 200,	long_range_radar = 35000, short_range_radar = 5000, probes = 17,	},
357		["ZX-Lindworm"]			= { strength = 8,	cargo = 3,	distance = 100,	long_range_radar = 18000, short_range_radar = 5500, probes = 12,	},
358		["Repulse"]				= { strength = 14,	cargo = 12,	distance = 200,	long_range_radar = 38000, short_range_radar = 5000, probes = 35,	},
359		["Ender"]				= { strength = 100,	cargo = 20,	distance = 2000,long_range_radar = 45000, short_range_radar = 7000, probes = 24,	},
360		["Nautilus"]			= { strength = 12,	cargo = 7,	distance = 200,	long_range_radar = 22000, short_range_radar = 4000, probes = 23,	},
361		["Hathcock"]			= { strength = 30,	cargo = 6,	distance = 200,	long_range_radar = 35000, short_range_radar = 6000, probes = 20,	},
362		["Maverick"]			= { strength = 45,	cargo = 5,	distance = 200,	long_range_radar = 20000, short_range_radar = 4000, probes = 18,	},
363		["Crucible"]			= { strength = 45,	cargo = 5,	distance = 200,	long_range_radar = 20000, short_range_radar = 6000, probes = 20,	},
364	}
365	tagDamage = 1.25			-- See GM button. Amount to subtract from jump/warp drive when tagged. Full health = 1
366	tag_distance = 750			-- See GM button. How far away to be considered tagged and returned to other side
367	hard_flag_reveal = true		-- See GM button. On hard difficulty, will a flag pick up be revealed on main screen or not
368	side_destroyed_ends_game = true		-- See GM button. If one side completely destroyed, will game end immediately or not (if not, set game time remaining to 60 seconds)
369	autoEnemies = false			-- See GM button. Boolean default value for whether or not marauders spawn
370	interWave = 600				-- See GM button. Number of seconds between marauding enemy spawn waves, if that option is chosen
371	dynamicTerrain = nil		-- this is a placeholder variable that needs to be set to a function call in the terrain setup function; see below
372	-- Choose the environment terrain!  Uncomment the terrain type you wish to use and comment out the other(s).
373	-- !! Be sure the setup function sets the value of 'dynamicTerrain' to the function that takes terrain action
374		--terrainType = emptyTerrain -- for easy/testing purposes
375		--terrainType = defaultTerrain
376		--terrainType = justPassingBy
377		terrainType = randomSymmetric
378		terrain_type_name = "Symmetric"
379	terrain_choices = {
380		["Empty"] =		emptyTerrain,
381		["Default"] =	defaultTerrain,
382		["Passing"] =	justPassingBy,
383		["Symmetric"] =	randomSymmetric,
384		["Rabbit"] =	downTheRabbitHole
385	}
386	-- Drone related global variables
387		dronesAreAllowed = true 				-- See GM button. The base boolean to turn on/off drone usage within the scenarios
388		uniform_drone_carrying_capacity = 50	-- See GM button. This is the max number of drones that can be carried by a playership; for the initial implementations, all player ships will have equal capacity
389		drone_name_type = "squad-num of size"	-- See GM button. Valid values are "default" (use EE), "squad-num/size" (K), "short" (X preferred), "squad-num of size" (X alternate)
390		drone_modified_from_template =  true 	-- See GM button. Boolean governing whether drone properties will be modified from their original template values
391		drone_hull_strength = 25	-- See GM button. Original: 30  drones do not have shields and only have their hull strength for defense; reasonable values should be from 25-75; obviously the higher the stronger
392		drone_impulse_speed = 120	-- See GM button. Original: 120 drones only have impulse engines, and usually tend to be faster because they are lighter and no living pilots required; reasonable values should be from 100-150
393		drone_beam_range = 700 		-- See Gm button. Original: 600 the distance at which the drone can hit its target; reasonable values should be from 500-1000
394		drone_beam_damage = 8 		-- See Gm button. Original: 6   drones have a single forward facing beam weapon; this sets the damage done by the beam; reasonable values should be from 5-10
395		drone_beam_cycle_time = 5	-- See Gm button. Original: 4   this is the number of seconds it takes for the beam weapon to recharge and to be able to fire again; reasonable values should be from 3-8
396		drone_flag_check_interval = 5		-- See GM button. How many seconds between each drone flag detection cycle
397		drone_message_reset_count = 8		-- See GM button. How many flag check intervals to wait before sending another message about a possible flag being detected
398		drone_formation_spacing = 5000		-- See GM button. How far apart drones travel when in formation (1000 = 1 unit)
399		drone_scan_range_for_flags = 7500	-- See GM button. How far away drones can "see" potential flags. Standard sensor range (aka sensor bubble) is 5 units (5000)
400	revisedPlayerShipProbeCount = 20  -- See GM button. The standard count of 8 just is not quite enough for this game, so we need to have an easy way to modify; all player ships will have this amount at game start
401	control_code_stem = {	--All control codes must use capital letters or they will not work.
402		"ALWAYS",
403		"ASTRO",
404		"BLACK",
405		"BLANK",
406		"BLUE",
407		"BRIGHT",
408		"BROWN",
409		"CHAIN",
410		"CHURCH",
411		"CORNER",
412		"DARK",
413		"DOORWAY",
414		"DOUBLE",
415		"DULL",
416		"ELBOW",
417		"EMPTY",
418		"EPSILON",
419		"FAST",
420		"FLOWER",
421		"FLY",
422		"FROZEN",
423		"GIG",
424		"GREEN",
425		"GLOW",
426		"HAND",
427		"HAMMER",
428		"INK",
429		"INTEL",
430		"JOUST",
431		"JUMP",
432		"KEY",
433		"KINDLE",
434		"LAP",
435		"LETTER",
436		"LIST",
437		"MORNING",
438		"NEXT",
439		"OPEN",
440		"ORANGE",
441		"OUTSIDE",
442		"PURPLE",
443		"QUARTER",
444		"QUIET",
445		"RED",
446		"SHINE",
447		"SIGMA",
448		"STAR",
449		"STREET",
450		"TOKEN",
451		"THIRSTY",
452		"UNDER",
453		"VANISH",
454		"WHITE",
455		"WRENCH",
456		"YELLOW",
457	}
458
459
460-- Variables and structures that *!MUST NOT!* be modified; these are necessary for managing game play
461	p1FlagDrop = false
462	p2FlagDrop = false
463	plotH = healthCheck
464	healthCheckTimer = 5
465	healthCheckTimerInterval = 5
466	plotW = marauderWaves
467	waveTimer = interWave
468	terrain_objects = {}
469	humanStationList = {}
470	kraylorStationList = {}
471	neutralStationList = {}
472	stationList = {}
473	human_player_names = {}
474	kraylor_player_names = {}
475	all_squad_count = 0
476	human_flags = {}
477	kraylor_flags = {}
478	-- 'stationZebra' is placed at position 0,0 and is present for all environment setups
479		stationZebra = SpaceStation():setTemplate("Small Station"):setFaction("Independent"):setCommsScript(""):setCommsFunction(commsStation):setPosition(0,0):setCallSign("Zebra"):setDescription("Referee")
480		table.insert(stationList,stationZebra)
481	-- the following tables are used for enemy marauding ships; the tables help plot arrival points for the marauding ships
482		-- square grid deployment
483		fleetPosDelta1x = {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}
484		fleetPosDelta1y = {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}
485		-- rough hexagonal deployment
486		fleetPosDelta2x = {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}
487		fleetPosDelta2y = {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}
488	missile_types = {'Homing', 'Nuke', 'Mine', 'EMP', 'HVLI'}  -- am not sure why this has to be set but it was included so keeping it for now
489	-- the following are part of Xansta's larger overall bartering/crafting setup
490		goods = {}			--overall tracking of goods;
491		tradeFood = {}		--stations that will trade food for other goods;
492		tradeLuxury = {}	--stations that will trade luxury for other goods;
493		tradeMedicine = {}	--stations that will trade medicine for other goods;
494	-- convenience table for accessing drones
495		droneFleets = {}
496	boundary_beam_string = {
497		"beam_blue.png",
498		"beam_purple.png",
499		"beam_green.png"
500	}
501
502	boundary_marker = "buoys"
503	-- Initialization checklist by function
504	setVariations()
505	initializeDroneButtonFunctionTables()
506	setGMButtons()
507	setupTailoredShipAttributes()  -- part of Xansta's larger overall script core for randomized stations and NPC ships
508	setupBarteringGoods() -- part of Xansta's larger overall bartering/crafting setup
509	setupPlacementRandomizationFunctions()
510	terrainType()  -- sets up the environment terrain according to the choice above
511	plotTeamDemarcationLine()
512	plotFlagPlacementBoundaries()
513
514	storage = getScriptStorage()
515	storage.gatherStats = gatherStats
516
517	-- Print initialization items to console
518	wfv = "end of init"
519	print("  Initial Configuration:")
520	print("    Flag hiding time limit:  " .. hideFlagTime/60 .. " minutes")
521	print("    Game Time Limit:  " .. gameTimeLimit/60 .. " minutes")
522	-- print("    Terrain type: " .. tostring(terrainType))
523	print("    Scan probes allocated per ship:  " .. revisedPlayerShipProbeCount)
524	print("    Are drones allowed? " .. tostring(dronesAreAllowed))
525	print("    (Uniform) Drone carrying capacity for player ships: " .. uniform_drone_carrying_capacity)
526	print("    Drone scanning range for flags/decoys:  " .. drone_scan_range_for_flags)
527	print("  ")
528	print("-----     All of the above initial configuration settings may be adjusted by GM button. ")
529	print("-----     So don't count on these values to remain accurate")
530
531end
532------------------
533--	GM Buttons  --
534------------------
535function setGMButtons()
536	mainGMButtons = mainGMButtonsDuringPause
537	mainGMButtons()
538end
539function mainGMButtonsDuringPause()
540	clearGMFunctions()
541	addGMFunction(string.format("Version %s",scenario_version),function()
542		local version_message = string.format("Scenario version %s\n LUA version %s",scenario_version,_VERSION)
543		addGMMessage(version_message)
544		print(version_message)
545	end)
546	local button_label = "Turn on Diagnostic"
547	if diagnostic then
548		button_label = "Turn off Diagnostic"
549	end
550	addGMFunction(button_label,function()
551		if diagnostic then
552			diagnostic = false
553		else
554			diagnostic = true
555		end
556		mainGMButtons()
557	end)
558	addGMFunction(string.format("+Terrain: %s",terrain_type_name),setTerrain)
559	addGMFunction("+Player Config",playerConfig)
560	button_label = "Enable Auto-Enemies"
561	if autoEnemies then
562		button_label = "Disable Auto-Enemies"
563	end
564	addGMFunction(button_label,function()
565		if autoEnemies then
566			autoEnemies = false
567		else
568			autoEnemies = true
569		end
570		mainGMButtons()
571	end)
572	if autoEnemies then
573		addGMFunction(string.format("+Times G%i H%i E%i",gameTimeLimit/60,hideFlagTime/60,interWave/60),setGameTimeLimit)
574	else
575		addGMFunction(string.format("+Times G%i H%i",gameTimeLimit/60,hideFlagTime/60),setGameTimeLimit)
576	end
577	addGMFunction(string.format("Level: %s ->Next",difficulty_text),function()
578		if difficulty_text == "normal" then
579			difficulty_text = "hard"
580			difficulty = 2
581			flagScanDepth = math.random(1,3)		--number of times to scan
582			flagScanComplexity = math.random(3,4)	--number of bars in scan
583		elseif difficulty_text == "hard" then
584			difficulty_text = "easy"
585			difficulty = .5
586			flagScanDepth = 1						--number of times to scan
587			flagScanComplexity = math.random(1,2)	--number of bars in scan
588		elseif difficulty_text == "easy" then
589			difficulty_text = "normal"
590			difficulty = 1
591			flagScanDepth = math.random(2,3)		--number of times to scan
592			flagScanComplexity = 2					--number of bars in scan
593		end
594		mainGMButtons()
595	end)
596	if difficulty > 1 then
597		button_label = "Show Pick Up Off"
598		if hard_flag_reveal then
599			button_label = "Show Pick Up On"
600		end
601		addGMFunction(button_label,function()
602			if hard_flag_reveal then
603				hard_flag_reveal = false
604			else
605				hard_flag_reveal = true
606			end
607			mainGMButtons()
608		end)
609	end
610	button_label = "Destroy = end off"
611	if side_destroyed_ends_game then
612		button_label = "Destroy = end on"
613	end
614	addGMFunction(button_label,function()
615		if side_destroyed_ends_game then
616			side_destroyed_ends_game = false
617		else
618			side_destroyed_ends_game = true
619		end
620		mainGMButtons()
621	end)
622	addGMFunction(string.format("Marker: %s ->Next",boundary_marker),function()
623		if boundary_marker == "stars" then
624			boundary_marker = "buoys"
625		elseif boundary_marker == "buoys" then
626			boundary_marker = "none"
627		elseif boundary_marker == "none" then
628			boundary_marker = "stars"
629		end
630		plotTeamDemarcationLine()
631		plotFlagPlacementBoundaries()
632		mainGMButtons()
633	end)
634	addGMFunction("Player Prefs",function()
635		local out_message = "Remaining player preferences:"
636		print(out_message)
637		for i=1,#preset_players do
638			local item = preset_players[i]
639			local out = string.format("XO:%s",item.xo)
640			print(out)
641			out_message = out_message .. "\n" .. out
642			if item.faction ~= nil then
643				out = string.format("    Faction:%s",item.faction)
644				print(out)
645				out_message = out_message .. "\n" .. out
646			end
647			if item.ship_name ~= nil then
648				out = string.format("    Ship name:%s",item.ship_name)
649				print(out)
650				out_message = out_message .. "\n" .. out
651			end
652			if item.ship_pref_1 ~= nil then
653				out = string.format("    Ship preference 1:%s",item.ship_pref_1)
654				print(out)
655				out_message = out_message .. "\n" .. out
656			end
657			if item.ship_pref_2 ~= nil then
658				out = string.format("    Ship preference 2:%s",item.ship_pref_2)
659				print(out)
660				out_message = out_message .. "\n" .. out
661			end
662			if item.ship_pref_3 ~= nil then
663				out = string.format("    Ship preference 3:%s",item.ship_pref_3)
664				print(out)
665				out_message = out_message .. "\n" .. out
666			end
667			if item.ship_pref_4 ~= nil then
668				out = string.format("    Ship preference 4:%s",item.ship_pref_4)
669				print(out)
670				out_message = out_message .. "\n" .. out
671			end
672			if item.ship_pref_5 ~= nil then
673				out = string.format("    Ship preference 5:%s",item.ship_pref_5)
674				print(out)
675				out_message = out_message .. "\n" .. out
676			end
677			if item.ship_pref_6 ~= nil then
678				out = string.format("    Ship preference 6:%s",item.ship_pref_6)
679				print(out)
680				out_message = out_message .. "\n" .. out
681			end
682		end
683		addGMMessage(out_message)
684	end)
685end
686function setTerrain()
687	clearGMFunctions()
688	addGMFunction("-from Terrain",mainGMButtons)
689	addGMFunction(string.format("Size: %s -> Next",terrain_size),function()
690		if terrain_size == "medium" then
691			terrain_size = "large"
692			boundary = 200000
693		elseif terrain_size == "large" then
694			terrain_size = "small"
695			boundary = 50000
696		elseif terrain_size == "small" then
697			terrain_size = "medium"
698			boundary = 100000
699		end
700		if terrain_objects ~= nil and #terrain_objects > 0 then
701			for _, obj in pairs(terrain_objects) do
702				obj:destroy()
703			end
704			terrain_objects = {}
705		end
706		stationList = {}
707		humanStationList = {}
708		kraylorStationList = {}
709		neutralStationList = {}
710		setupPlacementRandomizationFunctions()
711		terrainType()
712		setTerrain()
713		plotFlagPlacementBoundaries()
714	end)
715	for name, terrain in pairs(terrain_choices) do
716		local button_name = name
717		if button_name == terrain_type_name then
718			button_name = button_name .. "*"
719		end
720		addGMFunction(button_name,function()
721			if terrain_objects ~= nil and #terrain_objects > 0 then
722				for _, obj in pairs(terrain_objects) do
723					obj:destroy()
724				end
725				terrain_objects = {}
726			end
727			terrain_type_name = name
728			terrainType = terrain
729			stationList = {}
730			humanStationList = {}
731			kraylorStationList = {}
732			neutralStationList = {}
733			setupPlacementRandomizationFunctions()
734			terrainType()
735			setTerrain()
736		end)
737	end
738end
739function plotTeamDemarcationLine()
740	if boundary_items == nil then
741		boundary_items = {}
742	else
743		if #boundary_items > 0 then
744			for _, item in ipairs(boundary_items) do
745				item:destroy()
746			end
747			boundary_items = {}
748		end
749	end
750	if boundary_marker == "stars" then
751		local demarcation_x_position = 0
752		local demarcation_y_position = 2500
753		local star = nil
754		for index=1,40 do
755			star = Planet():setPosition(demarcation_x_position, demarcation_y_position)
756				:setPlanetRadius(150)
757				:setDistanceFromMovementPlane(0)
758				:setPlanetSurfaceTexture("planets/star-1.png")
759				--:setPlanetAtmosphereTexture("planets/star-1.png")
760				:setPlanetAtmosphereColor(1.0,1.0,1.0)
761				:setAxialRotationTime(100)
762			table.insert(boundary_items,star)
763			demarcation_y_position = demarcation_y_position * -1
764			star = Planet():setPosition(demarcation_x_position, demarcation_y_position)
765				:setPlanetRadius(150)
766				:setDistanceFromMovementPlane(0)
767				:setPlanetSurfaceTexture("planets/star-1.png")
768				--:setPlanetAtmosphereTexture("planets/star-1.png")
769				:setPlanetAtmosphereColor(1.0,1.0,1.0)
770				:setAxialRotationTime(100)
771			table.insert(boundary_items,star)
772			demarcation_y_position = demarcation_y_position * -1
773			demarcation_y_position = demarcation_y_position + 5000
774		end
775		demarcation_y_position = 5000
776		for index=1,40 do
777			star = Planet():setPosition(demarcation_x_position, demarcation_y_position)
778				:setPlanetRadius(150)
779				:setDistanceFromMovementPlane(0)
780				:setPlanetSurfaceTexture("planets/planet-2.png")
781				:setPlanetAtmosphereColor(0.5,0,0)
782				:setAxialRotationTime(100)
783			table.insert(boundary_items,star)
784			demarcation_y_position = demarcation_y_position * -1
785			star = Planet():setPosition(demarcation_x_position, demarcation_y_position)
786				:setPlanetRadius(150)
787				:setDistanceFromMovementPlane(0)
788				:setPlanetSurfaceTexture("planets/planet-2.png")
789				:setPlanetAtmosphereColor(1.0,0,0)
790				:setAxialRotationTime(100)
791			table.insert(boundary_items,star)
792			demarcation_y_position = demarcation_y_position * -1
793			demarcation_y_position = demarcation_y_position + 5000
794		end
795	elseif boundary_marker == "buoys" then
796		buoy_beam_interval = 2
797		buoy_beam_timer = buoy_beam_interval
798		buoy_beam_count = 0
799		for i=1,80 do
800			table.insert(boundary_items,Artifact():allowPickup(false):setPosition(0,i*2500):setModel("SensorBuoyMKIII"):setRotation(90):setSpin(100):setCallSign("Marker Buoy"):setDescriptions("Territory boundary marker","A buoy placed on the line marking the boundary between Human and Kraylor territory"):setScanningParameters(1,1):setRadarSignatureInfo(.5,1,0))
801			table.insert(boundary_items,Artifact():allowPickup(false):setPosition(0,i*-2500):setModel("SensorBuoyMKIII"):setRotation(90):setSpin(100):setCallSign("Marker Buoy"):setDescriptions("Territory boundary marker","A buoy placed on the line marking the boundary between Human and Kraylor territory"):setScanningParameters(1,1):setRadarSignatureInfo(0,.5,1))
802		end
803	end
804end
805function plotFlagPlacementBoundaries()
806	if flag_area_boundary_items == nil then
807		flag_area_boundary_items = {}
808	else
809		if #flag_area_boundary_items > 0 then
810			for _, item in ipairs(flag_area_boundary_items) do
811				item:destroy()
812			end
813			flag_area_boundary_items = {}
814		end
815	end
816	if boundary_marker == "stars" or boundary_marker == "buoys" then
817		local index = 0
818		repeat
819			local temp_marker = nil
820			if index == 0 then
821				temp_marker = createBoundaryMarker(index,boundary/2)	--middle of southern edge
822				table.insert(flag_area_boundary_items,temp_marker)
823				temp_marker = createBoundaryMarker(index,-boundary/2)	--middle of northern edge
824				table.insert(flag_area_boundary_items,temp_marker)
825				temp_marker = createBoundaryMarker(boundary,index)		--middle of eastern edge
826				table.insert(flag_area_boundary_items,temp_marker)
827				temp_marker = createBoundaryMarker(-boundary,index)		--middle of western edge
828				table.insert(flag_area_boundary_items,temp_marker)
829			elseif index == boundary then
830				temp_marker = createBoundaryMarker(index,boundary/2)	--southeast corner
831				table.insert(flag_area_boundary_items,temp_marker)
832				temp_marker = createBoundaryMarker(-index,-boundary/2)	--northwest corner
833				table.insert(flag_area_boundary_items,temp_marker)
834				temp_marker = createBoundaryMarker(index,-boundary/2)	--northeast corner
835				table.insert(flag_area_boundary_items,temp_marker)
836				temp_marker = createBoundaryMarker(-index,boundary/2)	--southwest corner
837				table.insert(flag_area_boundary_items,temp_marker)
838			else
839				temp_marker = createBoundaryMarker(index,boundary/2)	--eastern part of southern line
840				table.insert(flag_area_boundary_items,temp_marker)
841				temp_marker = createBoundaryMarker(-index,-boundary/2)	--western part of northern line
842				table.insert(flag_area_boundary_items,temp_marker)
843				temp_marker = createBoundaryMarker(index,-boundary/2)	--eastern part of northern line
844				table.insert(flag_area_boundary_items,temp_marker)
845				temp_marker = createBoundaryMarker(-index,boundary/2)	--western part of southern line
846				table.insert(flag_area_boundary_items,temp_marker)
847				if index < boundary/2 then
848					temp_marker = createBoundaryMarker(boundary,index)	--southern part of eastern line
849					table.insert(flag_area_boundary_items,temp_marker)
850					temp_marker = createBoundaryMarker(boundary,-index)	--northern part of eastern line
851					table.insert(flag_area_boundary_items,temp_marker)
852					temp_marker = createBoundaryMarker(-boundary,-index)--northern part of western line
853					table.insert(flag_area_boundary_items,temp_marker)
854					temp_marker = createBoundaryMarker(-boundary,index)	--southern part of western line
855					table.insert(flag_area_boundary_items,temp_marker)
856				end
857			end
858			index = index + 2500
859		until(index >= boundary)
860	end
861end
862function createBoundaryMarker(position_x, position_y)
863	local temp_marker = nil
864	if boundary_marker == "stars" then
865		temp_marker = Planet():setPosition(position_x, position_y)
866			:setPlanetRadius(200)
867			:setDistanceFromMovementPlane(0)
868			:setPlanetSurfaceTexture("planets/star-1.png")
869			:setPlanetAtmosphereColor(1.0,1.0,1.0)
870	elseif boundary_marker == "buoys" then
871		temp_marker = Artifact():allowPickup(false):setPosition(position_x,position_y):setModel("SensorBuoyMKIII"):setRotation(90):setSpin(50):setDescriptions("Flag hiding territory boundary marker","A temporary buoy placed on the edge of the territory where a flag or decoy may be hidden"):setScanningParameters(1,1):setRadarSignatureInfo(.3,.5,0)
872	end
873	return temp_marker
874end
875
876function playerConfig()
877	clearGMFunctions()
878	addGMFunction("-from Player Config",mainGMButtons)
879	addGMFunction("Show control codes",showControlCodes)
880	addGMFunction("Show Kraylor codes",showKraylorCodes)
881	addGMFunction("Show Human codes",showHumanCodes)
882	local button_label = "Wing Names Off"
883	if wingSquadronNames then
884		button_label = "Wing Names On"
885	end
886	addGMFunction(button_label,function()
887		if wingSquadronNames then
888			local p = getPlayerShip(-1)
889			if p ~= nil then
890				addGMMessage("Cannot disable wing names now that player ships have been spawned.\nClose the server and restart if you *really* don't want the wing names")
891			else
892				wingSquadronNames = false
893			end
894		else
895			wingSquadronNames = true
896		end
897		playerConfig()
898	end)
899	addGMFunction(string.format("+Tags %.2f, %.1fU",tagDamage,tag_distance/1000),setTagValues)
900	button_label = "+Drones Off"
901	if dronesAreAllowed then
902		button_label = "+Drones On"
903	end
904	addGMFunction(button_label,configureDrones)
905	--[[
906	local p = getPlayerShip(-1)
907	if p == nil then
908		addGMFunction(string.format("+Probes %i",revisedPlayerShipProbeCount),setPlayerProbes)
909	end
910	--]]
911end
912function setGameTimeLimit()
913	clearGMFunctions()
914	addGMFunction("-Main from times",mainGMButtons)
915	addGMFunction(string.format("Game %i Add 5 -> %i",gameTimeLimit/60,gameTimeLimit/60 + 5),function()
916		gameTimeLimit = gameTimeLimit + 300
917		maxGameTime = gameTimeLimit
918		setGameTimeLimit()
919	end)
920	if gameTimeLimit > (hideFlagTime + 300) then
921		addGMFunction(string.format("Game %i Del 5 -> %i",gameTimeLimit/60,gameTimeLimit/60 - 5),function()
922			gameTimeLimit = gameTimeLimit - 300
923			maxGameTime = gameTimeLimit
924			setGameTimeLimit()
925		end)
926	end
927	if hideFlagTime < (gameTimeLimit - 300) then
928		addGMFunction(string.format("Hide Flag %i Add 5 -> %i",hideFlagTime/60,hideFlagTime/60 + 5),function()
929			hideFlagTime = hideFlagTime + 300
930			setGameTimeLimit()
931		end)
932	end
933	if hideFlagTime > 300 then
934		addGMFunction(string.format("Hide Flag %i Del 5 -> %i",hideFlagTime/60,hideFlagTime/60 - 5),function()
935			hideFlagTime = hideFlagTime - 300
936			setGameTimeLimit()
937		end)
938	elseif hideFlagTime > 60 then
939		addGMFunction(string.format("Hide Flag %i Del 4 -> %i",hideFlagTime/60,hideFlagTime/60 - 4),function()
940			hideFlagTime = hideFlagTime - 240
941			setGameTimeLimit()
942		end)
943	end
944	if autoEnemies then
945		if interWave < 1200 then
946			addGMFunction(string.format("Enemy %i Add 1 -> %i",interWave/60,(interWave + 60)/60),function()
947				interWave = interWave + 60
948				setGameTimeLimit()
949			end)
950		end
951		if interWave > 120 then
952			addGMFunction(string.format("Enemy %i Del 1 -> %i",interWave/60,(interWave - 60)/60),function()
953				interWave = interWave - 60
954				setGameTimeLimit()
955			end)
956		end
957	end
958end
959function setTagValues()
960	clearGMFunctions()
961	addGMFunction("-Main from Tag",mainGMButtons)
962	addGMFunction("-Player Config",playerConfig)
963	addGMFunction(string.format("+Tag distance %.1fU",tag_distance/1000),setTagDistance)
964	addGMFunction(string.format("+Tag damage %.2f",tagDamage),setTagDamage)
965end
966function configureDrones()
967	clearGMFunctions()
968	addGMFunction("-From Drones",playerConfig)
969	local button_label = "Drones Off"
970	if dronesAreAllowed then
971		button_label = "Drones On"
972	end
973	addGMFunction(button_label,function()
974		if dronesAreAllowed then
975			dronesAreAllowed = false
976		else
977			dronesAreAllowed = true
978		end
979		configureDrones()
980	end)
981	if dronesAreAllowed then
982		addGMFunction(string.format("+Capacity %i",uniform_drone_carrying_capacity),setDroneCarryingCapacity)
983		addGMFunction(string.format("Name %s",drone_name_type),function()
984			if drone_name_type == "squad-num of size" then
985				drone_name_type = "default"
986			elseif drone_name_type == "default" then
987				drone_name_type = "squad-num/size"
988			elseif drone_name_type == "squad-num/size" then
989				drone_name_type = "short"
990			elseif drone_name_type == "short" then
991				drone_name_type = "squad-num of size"
992			end
993			configureDrones()
994		end)
995		addGMFunction(string.format("+Flag I%i M%i",drone_flag_check_interval,drone_message_reset_count),setDroneFlagValues)
996		addGMFunction(string.format("+Distance F%.1fU S%.1fU",drone_formation_spacing/1000,drone_scan_range_for_flags/1000),setDroneDistances)
997		button_label = "Template Mod Off"
998		if drone_modified_from_template then
999			button_label = "Template Mod On"
1000		end
1001		addGMFunction(button_label,function()
1002			if drone_modified_from_template then
1003				drone_modified_from_template = false
1004			else
1005				drone_modified_from_template = true
1006			end
1007			configureDrones()
1008		end)
1009		if drone_modified_from_template then
1010			addGMFunction(string.format("+Hull %i",drone_hull_strength),setDroneHull)
1011			addGMFunction(string.format("+Impulse %i",drone_impulse_speed),setDroneImpulseSpeed)
1012			addGMFunction(string.format("+Beam R%.1fU D%.1f C%.1f",drone_beam_range/1000,drone_beam_damage,drone_beam_cycle_time),setDroneBeam)
1013		end
1014	end
1015end
1016function setPlayerProbes()
1017	clearGMFunctions()
1018	addGMFunction("-Main from Probes",mainGMButtons)
1019	addGMFunction("-Player Config",playerConfig)
1020	if revisedPlayerShipProbeCount < 50 then
1021		addGMFunction(string.format("Probes %i Add 1 -> %i",revisedPlayerShipProbeCount,revisedPlayerShipProbeCount + 1),function()
1022			local p = getPlayerShip(-1)
1023			if p == nil then
1024				revisedPlayerShipProbeCount = revisedPlayerShipProbeCount + 1
1025				setPlayerProbes()
1026			else
1027				playerConfig()
1028			end
1029		end)
1030	end
1031	if revisedPlayerShipProbeCount > 1 then
1032		addGMFunction(string.format("Probes %i Del 1 -> %i",revisedPlayerShipProbeCount,revisedPlayerShipProbeCount - 1),function()
1033			local p = getPlayerShip(-1)
1034			if p == nil then
1035				revisedPlayerShipProbeCount = revisedPlayerShipProbeCount - 1
1036				setPlayerProbes()
1037			else
1038				playerConfig()
1039			end
1040		end)
1041	end
1042end
1043function setTagDistance()
1044	clearGMFunctions()
1045	addGMFunction("-Main from Tag",mainGMButtons)
1046	addGMFunction("-Player Config",playerConfig)
1047	addGMFunction("-From Tag Distance",setTagValues)
1048	if tag_distance < 5000 then
1049		addGMFunction(string.format("%.1fU Add .1 -> %.1fU",tag_distance/1000,(tag_distance + 100)/1000),function()
1050			tag_distance = tag_distance + 100
1051			setTagDistance()
1052		end)
1053	end
1054	if tag_distance > 500 then
1055		addGMFunction(string.format("%.1fU Del .1 -> %.1fU",tag_distance/1000,(tag_distance - 100)/1000),function()
1056			tag_distance = tag_distance - 100
1057			setTagDistance()
1058		end)
1059	end
1060end
1061function setTagDamage()
1062	clearGMFunctions()
1063	addGMFunction("-Main from Tag",mainGMButtons)
1064	addGMFunction("-Player Config",playerConfig)
1065	addGMFunction("-From Tag Dmg",setTagValues)
1066	if tagDamage < 2 then
1067		addGMFunction(string.format("%.2f Add .25 -> %.2f",tagDamage,tagDamage + .25),function()
1068			tagDamage = tagDamage + .25
1069			setTagDamage()
1070		end)
1071	end
1072	if tagDamage > .25 then
1073		addGMFunction(string.format("%.2f Del .25 -> %.2f",tagDamage,tagDamage - .25),function()
1074			tagDamage = tagDamage - .25
1075			setTagDamage()
1076		end)
1077	end
1078end
1079--	Drone related GM button functions
1080function setDroneCarryingCapacity()
1081	clearGMFunctions()
1082	addGMFunction("-Main",mainGMButtons)
1083	addGMFunction("-Player Config",playerConfig)
1084	addGMFunction("-From Capacity",configureDrones)
1085	if uniform_drone_carrying_capacity < 100 then
1086		addGMFunction(string.format("%i Add 10 -> %i",uniform_drone_carrying_capacity,uniform_drone_carrying_capacity + 10),function()
1087			uniform_drone_carrying_capacity = uniform_drone_carrying_capacity + 10
1088			setDroneCarryingCapacity()
1089		end)
1090	end
1091	if uniform_drone_carrying_capacity > 10 then
1092		addGMFunction(string.format("%i Del 10 -> %i",uniform_drone_carrying_capacity,uniform_drone_carrying_capacity - 10),function()
1093			uniform_drone_carrying_capacity = uniform_drone_carrying_capacity - 10
1094			setDroneCarryingCapacity()
1095		end)
1096	end
1097end
1098function setDroneFlagValues()
1099	clearGMFunctions()
1100	addGMFunction("-Main",mainGMButtons)
1101	addGMFunction("-Player Config",playerConfig)
1102	addGMFunction("-From Drone Flag",configureDrones)
1103	if drone_flag_check_interval < 20 then
1104		addGMFunction(string.format("Interval %i Add 1 -> %i",drone_flag_check_interval,drone_flag_check_interval + 1),function()
1105			drone_flag_check_interval = drone_flag_check_interval + 1
1106			setDroneFlagValues()
1107		end)
1108	end
1109	if drone_flag_check_interval > 1 then
1110		addGMFunction(string.format("Interval %i Del 1 -> %i",drone_flag_check_interval,drone_flag_check_interval - 1),function()
1111			drone_flag_check_interval = drone_flag_check_interval - 1
1112			setDroneFlagValues()
1113		end)
1114	end
1115	if drone_message_reset_count < 20 then
1116		addGMFunction(string.format("Msg Reset %i Add 1 -> %i",drone_message_reset_count,drone_message_reset_count + 1),function()
1117			drone_message_reset_count = drone_message_reset_count + 1
1118			setDroneFlagValues()
1119		end)
1120	end
1121	if drone_message_reset_count > 2 then
1122		addGMFunction(string.format("Msg Reset %i Del 1 -> %i",drone_message_reset_count,drone_message_reset_count - 1),function()
1123			drone_message_reset_count = drone_message_reset_count - 1
1124			setDroneFlagValues()
1125		end)
1126	end
1127end
1128function setDroneDistances()
1129	clearGMFunctions()
1130	addGMFunction("-Main",mainGMButtons)
1131	addGMFunction("-Player Config",playerConfig)
1132	addGMFunction("-From Drone Distance",configureDrones)
1133	if drone_formation_spacing < 9000 then
1134		addGMFunction(string.format("Form %.1fU Add .1 -> %.1fU",drone_formation_spacing/1000,(drone_formation_spacing + 100)/1000),function()
1135			drone_formation_spacing = drone_formation_spacing + 100
1136			setDroneDistances()
1137		end)
1138	end
1139	if drone_formation_spacing > 1000 then
1140		addGMFunction(string.format("Form %.1fU Del .1 -> %.1fU",drone_formation_spacing/1000,(drone_formation_spacing - 100)/1000),function()
1141			drone_formation_spacing = drone_formation_spacing - 100
1142			setDroneDistances()
1143		end)
1144	end
1145	if drone_scan_range_for_flags < 9000 then
1146		addGMFunction(string.format("Scan %.1fU Add .1 -> %.1fU",drone_scan_range_for_flags/1000,(drone_scan_range_for_flags + 100)/1000),function()
1147			drone_scan_range_for_flags = drone_scan_range_for_flags + 100
1148			setDroneDistances()
1149		end)
1150	end
1151	if drone_scan_range_for_flags > 3000 then
1152		addGMFunction(string.format("Scan %.1fU Del .1 -> %.1fU",drone_scan_range_for_flags/1000,(drone_scan_range_for_flags - 100)/1000),function()
1153			drone_scan_range_for_flags = drone_scan_range_for_flags - 100
1154			setDroneDistances()
1155		end)
1156	end
1157end
1158function setDroneHull()
1159	clearGMFunctions()
1160	addGMFunction("-Main",mainGMButtons)
1161	addGMFunction("-Player Config",playerConfig)
1162	addGMFunction("-From Drone Hull",configureDrones)
1163	if drone_hull_strength < 200 then
1164		addGMFunction(string.format("%i Add 10 -> %i",drone_hull_strength,drone_hull_strength + 10),function()
1165			drone_hull_strength = drone_hull_strength + 10
1166			setDroneHull()
1167		end)
1168	end
1169	if drone_hull_strength > 10 then
1170		addGMFunction(string.format("%i Del 10 -> %i",drone_hull_strength,drone_hull_strength - 10),function()
1171			drone_hull_strength = drone_hull_strength - 10
1172			setDroneHull()
1173		end)
1174	end
1175end
1176function setDroneImpulseSpeed()
1177	clearGMFunctions()
1178	addGMFunction("-Main",mainGMButtons)
1179	addGMFunction("-Player Config",playerConfig)
1180	addGMFunction("-From Drone Impulse",configureDrones)
1181	if drone_impulse_speed < 150 then
1182		addGMFunction(string.format("%i Add 5 -> %i",drone_impulse_speed,drone_impulse_speed + 5),function()
1183			drone_impulse_speed = drone_impulse_speed + 5
1184			setDroneImpulseSpeed()
1185		end)
1186	end
1187	if drone_impulse_speed > 50 then
1188		addGMFunction(string.format("%i Del 5 -> %i",drone_impulse_speed,drone_impulse_speed - 5),function()
1189			drone_impulse_speed = drone_impulse_speed - 5
1190			setDroneImpulseSpeed()
1191		end)
1192	end
1193end
1194function setDroneBeam()
1195	clearGMFunctions()
1196	addGMFunction("-Main",mainGMButtons)
1197	addGMFunction("-Player Config",playerConfig)
1198	addGMFunction("-From Drone Beam",configureDrones)
1199	if drone_beam_range < 2000 then
1200		addGMFunction(string.format("Rng %.1fU Add .1 -> %.1fU",drone_beam_range/1000,(drone_beam_range + 100)/1000),function()
1201			drone_beam_range = drone_beam_range + 100
1202			setDroneBeam()
1203		end)
1204	end
1205	if drone_beam_range > 300 then
1206		addGMFunction(string.format("Rng %.1fU Del .1 -> %.1fU",drone_beam_range/1000,(drone_beam_range - 100)/1000),function()
1207			drone_beam_range = drone_beam_range - 100
1208			setDroneBeam()
1209		end)
1210	end
1211	if drone_beam_damage < 20 then
1212		addGMFunction(string.format("Dmg %.1f Add .5 -> %.1f",drone_beam_damage,drone_beam_damage + .5),function()
1213			drone_beam_damage = drone_beam_damage + .5
1214			setDroneBeam()
1215		end)
1216	end
1217	if drone_beam_damage > 1 then
1218		addGMFunction(string.format("Dmg %.1f Del .5 -> %.1f",drone_beam_damage,drone_beam_damage - .5),function()
1219			drone_beam_damage = drone_beam_damage - .5
1220			setDroneBeam()
1221		end)
1222	end
1223	if drone_beam_cycle_time < 20 then
1224		addGMFunction(string.format("Cycle %.1f Add .5 -> %.1f",drone_beam_cycle_time,drone_beam_cycle_time + .5),function()
1225			drone_beam_cycle_time = drone_beam_cycle_time + .5
1226			setDroneBeam()
1227		end)
1228	end
1229	if drone_beam_cycle_time > 1 then
1230		addGMFunction(string.format("Cycle %.1f Del .5 -> %.1f",drone_beam_cycle_time,drone_beam_cycle_time - .5),function()
1231			drone_beam_cycle_time = drone_beam_cycle_time - .5
1232			setDroneBeam()
1233		end)
1234	end
1235end
1236
1237function mainGMButtonsAfterPause()
1238	clearGMFunctions()
1239	addGMFunction(string.format("Version %s",scenario_version),function()
1240		local version_message = string.format("Scenario version %s\n LUA version %s",scenario_version,_VERSION)
1241		addGMMessage(version_message)
1242		print(version_message)
1243	end)
1244	addGMFunction("Show control codes",showControlCodes)
1245	addGMFunction("Show Kraylor codes",showKraylorCodes)
1246	addGMFunction("Show Ktlitan codes",showKtlitanCodes)
1247	addGMFunction("Show Human codes",showHumanCodes)
1248	local button_label = "Enable Auto-Enemies"
1249	if autoEnemies then
1250		button_label = "Disable Auto-Enemies"
1251	end
1252	addGMFunction(button_label,function()
1253		if autoEnemies then
1254			autoEnemies = false
1255		else
1256			autoEnemies = true
1257		end
1258		mainGMButtons()
1259	end)
1260	button_label = "Turn on Diagnostic"
1261	if diagnostic then
1262		button_label = "Turn off Diagnostic"
1263	end
1264	addGMFunction(button_label,function()
1265		if diagnostic then
1266			diagnostic = false
1267		else
1268			diagnostic = true
1269		end
1270		mainGMButtons()
1271	end)
1272	addGMFunction("Current Stats", currentStats)
1273	if dronesAreAllowed then
1274		addGMFunction("Detailed Drone Report", detailedDroneReport)
1275	end
1276	if gameTimeLimit < (maxGameTime - hideFlagTime) then
1277		addGMFunction("Intelligent Bugger",intelligentBugger)
1278	end
1279end
1280function showKraylorCodes()
1281	showControlCodes("Kraylor")
1282end
1283function showHumanCodes()
1284	showControlCodes("Human Navy")
1285end
1286function showKtlitanCodes()
1287	showControlCodes("Ktlitans")
1288end
1289function showControlCodes(faction_filter)
1290	local code_list = {}
1291	for pidx=1,32 do
1292		local p = getPlayerShip(pidx)
1293		if p ~= nil and p:isValid() then
1294			if faction_filter == "Kraylor" then
1295				if p:getFaction() == "Kraylor" then
1296					code_list[p:getCallSign()] = {code = p.control_code, faction = p:getFaction()}
1297				end
1298			elseif faction_filter == "Human Navy" then
1299				if p:getFaction() == "Human Navy" then
1300					code_list[p:getCallSign()] = {code = p.control_code, faction = p:getFaction()}
1301				end
1302			elseif faction_filter == "Ktlitans" then
1303				if p:getFaction() == "Ktlitans" then
1304					code_list[p:getCallSign()] = {code = p.control_code, faction = p:getFaction()}
1305				end
1306			else
1307				code_list[p:getCallSign()] = {code = p.control_code, faction = p:getFaction()}
1308			end
1309		end
1310	end
1311	local sorted_names = {}
1312	for name in pairs(code_list) do
1313		table.insert(sorted_names,name)
1314	end
1315	table.sort(sorted_names)
1316	local output = ""
1317	for _, name in ipairs(sorted_names) do
1318		local faction = ""
1319		if code_list[name].faction == "Kraylor" then
1320			faction = " (Kraylor)"
1321		elseif code_list[name].faction == "Ktlitans" then
1322			faction = " (Ktlitan)"
1323		end
1324		output = output .. string.format("%s: %s %s\n",name,code_list[name].code,faction)
1325	end
1326	addGMMessage(output)
1327end
1328function intelligentBugger()
1329	-- Spawn a player ship not affiliated with either team for harassment purposes
1330	spawnBugger()
1331	if buggerResupply == nil then
1332		buggerResupply = SpaceStation():setFaction("Ktlitans"):setTemplate("Medium Station"):setPosition(0,boundary/2 + 2000):setCommsScript(""):setCommsFunction(resupplyStation)
1333	else
1334		if not buggerResupply:isValid() then
1335			buggerResupply = SpaceStation():setFaction("Ktlitans"):setTemplate("Medium Station"):setPosition(0,boundary/2 + 2000):setCommsScript(""):setCommsFunction(resupplyStation)
1336		end
1337	end
1338end
1339function spawnBugger()
1340	local bugger = PlayerSpaceship():setFaction("Ktlitans"):setPosition(0,boundary/2):addReputationPoints(100)
1341	bugger:setTemplate("ZX-Lindworm"):setWarpDrive(true):setWarpSpeed(950)
1342	bugger.template_type = "ZX-Lindworm"
1343	namePlayer(bugger,"Lindworm")
1344	local control_code_index = math.random(1,#control_code_stem)
1345	local stem = control_code_stem[control_code_index]
1346	table.remove(control_code_stem,control_code_index)
1347	local branch = math.random(100,999)
1348	bugger.control_code = stem .. branch
1349	bugger:setControlCode(stem .. branch)
1350	if bugger_player_names == nil then
1351		bugger_player_names = {}
1352	end
1353	bugger_player_names[bugger:getCallSign()] = bugger
1354	addGMMessage(string.format("New Bugger ship: %s\nControl code: %s",bugger:getCallSign(),bugger.control_code))
1355	print("Control Code for bugger " .. bugger:getCallSign(), bugger.control_code)
1356end
1357function gatherStats()
1358	local stat_list = {}
1359	stat_list.scenario = {name = "Capture the Flag", version = scenario_version}
1360	stat_list.human = {}
1361	stat_list.kraylor = {}
1362	stat_list.bugger = {}
1363	stat_list.human.ship = {}
1364	stat_list.kraylor.ship = {}
1365	stat_list.bugger.ship = {}
1366	stat_list.human.active_ship_count = 0
1367	stat_list.human.destroyed_ship_count = 0
1368	stat_list.kraylor.active_ship_count = 0
1369	stat_list.kraylor.destroyed_ship_count = 0
1370	stat_list.bugger.active_ship_count = 0
1371	stat_list.bugger.destroyed_ship_count = 0
1372	stat_list.human.active_drone_count = 0
1373	stat_list.human.destroyed_drone_count = 0
1374	stat_list.kraylor.active_drone_count = 0
1375	stat_list.kraylor.destroyed_drone_count = 0
1376	stat_list.times = {}
1377	stat_list.times.game = {}
1378	stat_list.times.hide_flag = {}
1379	stat_list.times.stage = timeDivision
1380	stat_list.times.game.max = maxGameTime
1381	stat_list.times.game.total_seconds_left = gameTimeLimit
1382	stat_list.times.game.minutes_left = math.floor(gameTimeLimit / 60)
1383	stat_list.times.game.seconds_left = math.floor(gameTimeLimit % 60)
1384	stat_list.times.hide_flag.max = hideFlagTime
1385	stat_list.times.hide_flag.total_seconds_left = gameTimeLimit - (maxGameTime - hideFlagTime)
1386	stat_list.times.hide_flag.minutes_left = math.floor((gameTimeLimit - (maxGameTime - hideFlagTime)) / 60)
1387	stat_list.times.hide_flag.seconds_left = math.floor((gameTimeLimit - (maxGameTime - hideFlagTime)) % 60)
1388	for pidx=1,32 do
1389		p = getPlayerShip(pidx)
1390		if p ~= nil then
1391			if p:isValid() then
1392				local faction = p:getFaction()
1393				local flag = false
1394				local drone_info = {}
1395				local squad_count = 0
1396				local squad_list = {}
1397				local active_drone_count = 0
1398				local destroyed_drone_count = 0
1399				if faction == "Ktlitans" then
1400					stat_list.bugger.active_ship_count = stat_list.bugger.active_ship_count + 1
1401					stat_list.bugger.ship[p:getCallSign()] = {template_type = p:getTypeName(), is_alive = true}
1402				elseif faction == "Kraylor" then
1403					if p.droneSquads ~= nil then
1404						for squadName, droneList in pairs(p.droneSquads) do
1405							if squadName ~= nil then
1406								squad_count = squad_count + 1
1407								squad_list[squadName] = {active_count = 0, destroyed_count = 0, max = #droneList}
1408								for i=1,#droneList do
1409									if droneList[i]:isValid() then
1410										squad_list[squadName].active_count = squad_list[squadName].active_count + 1
1411										active_drone_count = active_drone_count + 1
1412									else
1413										squad_list[squadName].destroyed_count = squad_list[squadName].destroyed_count + 1
1414										destroyed_drone_count = destroyed_drone_count + 1
1415									end
1416								end
1417							end
1418						end
1419					end
1420					stat_list.kraylor.active_ship_count = stat_list.kraylor.active_ship_count + 1
1421					if p.flag then
1422						flag = true
1423					end
1424					drone_info = {uniform_drone_carrying_capacity = uniform_drone_carrying_capacity, squad_count = squad_count, squad_list = squad_list, active_drone_count = active_drone_count, destroyed_drone_count = destroyed_drone_count}
1425					stat_list.kraylor.ship[p:getCallSign()] = {template_type = p:getTypeName(), is_alive = true, has_flag = flag, pick_up_count = p.pick_up_count, tagged_count = p.tagged_count, drone_info = drone_info}
1426				elseif faction == "Human Navy" then
1427					if p.droneSquads ~= nil then
1428						for squadName, droneList in pairs(p.droneSquads) do
1429							if squadName ~= nil then
1430								squad_count = squad_count + 1
1431								squad_list[squadName] = {active_count = 0, destroyed_count = 0, max = #droneList}
1432								for i=1,#droneList do
1433									if droneList[i]:isValid() then
1434										squad_list[squadName].active_count = squad_list[squadName].active_count + 1
1435										active_drone_count = active_drone_count + 1
1436									else
1437										squad_list[squadName].destroyed_count = squad_list[squadName].destroyed_count + 1
1438										destroyed_drone_count = destroyed_drone_count + 1
1439									end
1440								end
1441							end
1442						end
1443					end
1444					stat_list.human.active_ship_count = stat_list.human.active_ship_count + 1
1445					if p.flag then
1446						flag = true
1447					end
1448					drone_info = {uniform_drone_carrying_capacity = uniform_drone_carrying_capacity, squad_count = squad_count, squad_list = squad_list, active_drone_count = active_drone_count, destroyed_drone_count = destroyed_drone_count}
1449					stat_list.human.ship[p:getCallSign()] = {template_type = p:getTypeName(), is_alive = true, has_flag = flag, pick_up_count = p.pick_up_count, tagged_count = p.tagged_count, drone_info = drone_info}
1450				end
1451			end
1452			if pidx %2 == 0 then	--kraylor
1453				if p.droneSquads ~= nil then
1454					for squadName, droneList in pairs(p.droneSquads) do
1455						for i=1,#droneList do
1456							if droneList[i]:isValid() then
1457								stat_list.kraylor.active_drone_count = stat_list.kraylor.active_drone_count + 1
1458							else
1459								stat_list.kraylor.destroyed_drone_count = stat_list.kraylor.destroyed_drone_count + 1
1460							end
1461						end
1462					end
1463				end
1464			else	--human
1465				if p.droneSquads ~= nil then
1466					for squadName, droneList in pairs(p.droneSquads) do
1467						for i=1,#droneList do
1468							if droneList[i]:isValid() then
1469								stat_list.human.active_drone_count = stat_list.human.active_drone_count + 1
1470							else
1471								stat_list.human.destroyed_drone_count = stat_list.human.destroyed_drone_count + 1
1472							end
1473						end
1474					end
1475				end
1476			end
1477		end
1478	end
1479	for pName, p in pairs(human_player_names) do
1480		if not p:isValid() then
1481			local drone_info = {}
1482			local squad_count = 0
1483			local squad_list = {}
1484			local active_drone_count = 0
1485			local destroyed_drone_count = 0
1486			if p.droneSquads ~= nil then
1487				for squadName, droneList in pairs(p.droneSquads) do
1488					if squadName ~= nil then
1489						squad_count = squad_count + 1
1490						squad_list[squadName] = {active_count = 0, destroyed_count = 0, max = #droneList}
1491						for i=1,#droneList do
1492							if droneList[i]:isValid() then
1493								squad_list[squadName].active_count = squad_list[squadName].active_count + 1
1494								active_drone_count = active_drone_count + 1
1495							else
1496								squad_list[squadName].destroyed_count = squad_list[squadName].destroyed_count + 1
1497								destroyed_drone_count = destroyed_drone_count + 1
1498							end
1499						end
1500					end
1501				end
1502			end
1503			drone_info = {uniform_drone_carrying_capacity = uniform_drone_carrying_capacity, squad_count = squad_count, squad_list = squad_list, active_drone_count = active_drone_count, destroyed_drone_count = destroyed_drone_count}
1504			stat_list.human.destroyed_ship_count = stat_list.human.destroyed_ship_count + 1
1505			stat_list.human.ship[pName] = {template_type = p.template_type, is_alive = false, has_flag = false, pick_up_count = p.pick_up_count, tagged_count = p.tagged_count, drone_info = drone_info}
1506		end
1507	end
1508	for pName, p in pairs(kraylor_player_names) do
1509		if not p:isValid() then
1510			local drone_info = {}
1511			local squad_count = 0
1512			local squad_list = {}
1513			local active_drone_count = 0
1514			local destroyed_drone_count = 0
1515			if p.droneSquads ~= nil then
1516				for squadName, droneList in pairs(p.droneSquads) do
1517					if squadName ~= nil then
1518						squad_count = squad_count + 1
1519						squad_list[squadName] = {active_count = 0, destroyed_count = 0, max = #droneList}
1520						for i=1,#droneList do
1521							if droneList[i]:isValid() then
1522								squad_list[squadName].active_count = squad_list[squadName].active_count + 1
1523								active_drone_count = active_drone_count + 1
1524							else
1525								squad_list[squadName].destroyed_count = squad_list[squadName].destroyed_count + 1
1526								destroyed_drone_count = destroyed_drone_count + 1
1527							end
1528						end
1529					end
1530				end
1531			end
1532			drone_info = {uniform_drone_carrying_capacity = uniform_drone_carrying_capacity, squad_count = squad_count, squad_list = squad_list, active_drone_count = active_drone_count, destroyed_drone_count = destroyed_drone_count}
1533			stat_list.kraylor.destroyed_ship_count = stat_list.kraylor.destroyed_ship_count + 1
1534			stat_list.kraylor.ship[pName] = {template_type = p.template_type, is_alive = false, has_flag = false, pick_up_count = p.pick_up_count, tagged_count = p.tagged_count, drone_info = drone_info}
1535		end
1536	end
1537	if bugger_player_names ~= nil then
1538		for pName, p in pairs(bugger_player_names) do
1539			if not p:isValid() then
1540				stat_list.bugger.destroyed_ship_count = stat_list.bugger.destroyed_ship_count + 1
1541				stat_list.bugger.ship[pName] = {template_type = p.template_type, is_alive = false}
1542			end
1543		end
1544	end
1545	--[[sort
1546	local sorted_ships = {}
1547	for ship, details in pairs(stat_list.human.ship) do
1548		table.insert(sorted_ships,{name=ship,details=details})
1549	end
1550	table.sort(sorted_ships, function(a,b)
1551		return a.name < b.name
1552	end)
1553	stat_list.human.sorted_ships = sorted_ships
1554	sorted_ships = {}
1555	for ship, details in pairs(stat_list.kraylor.ship) do
1556		table.insert(sorted_ships,{name=ship,details=details})
1557	end
1558	table.sort(sorted_ships, function(a,b)
1559		return a.name < b.name
1560	end)
1561	stat_list.kraylor.sorted_ships = sorted_ships
1562	--]]
1563	storage.stats = stat_list
1564	return stat_list
1565end
1566function currentStats()
1567	local stats = gatherStats()
1568	print(" ")
1569	print("----------CURRENT SUMMARY STATS-----------")
1570	print("  Humans:")
1571	print("    Number of active ships:  " .. stats.human.active_ship_count)
1572	print("    Number of destroyed ships:  " .. stats.human.destroyed_ship_count)
1573	if dronesAreAllowed then
1574		print("    Total number of active drones:  " .. stats.human.active_drone_count)
1575		print("    Total number of destroyed drones:  " .. stats.human.destroyed_drone_count)
1576	end
1577	print("  Kraylor:")
1578	print("    Number of active ships:  " .. stats.kraylor.active_ship_count)
1579	print("    Number of destroyed ships:  " .. stats.kraylor.destroyed_ship_count)
1580	if dronesAreAllowed then
1581		print("    Total number of active drones:  " .. stats.kraylor.active_drone_count)
1582		print("    Total number of destroyed drones:  " .. stats.kraylor.destroyed_drone_count)
1583	end
1584	if stats.bugger.active_ship_count > 0 then
1585		print("Active buggers:  " .. stats.bugger.active_ship_count)
1586	end
1587	print("-----------------END STATS-----------------")
1588	local gm_out = "Human:"
1589	gm_out = gm_out .. "\n   Number of active ships: " .. stats.human.active_ship_count
1590	gm_out = gm_out .. "\n   Number of destroyed ships: " .. stats.human.destroyed_ship_count
1591	if dronesAreAllowed then
1592		gm_out = gm_out .. "\n   Total number of active drones: " .. stats.human.active_drone_count
1593		gm_out = gm_out .. "\n   Total number of destroyed drones: " .. stats.human.destroyed_drone_count
1594	end
1595	gm_out = gm_out .. "\nKraylor:"
1596	gm_out = gm_out .. "\n   Number of active ships: " .. stats.kraylor.active_ship_count
1597	gm_out = gm_out .. "\n   Number of destroyed ships: " .. stats.kraylor.destroyed_ship_count
1598	if dronesAreAllowed then
1599		gm_out = gm_out .. "\n   Total number of active drones: " .. stats.kraylor.active_drone_count
1600		gm_out = gm_out .. "\n   Total number of destroyed drones: " .. stats.kraylor.destroyed_drone_count
1601	end
1602	if stats.bugger.active_ship_count > 0 then
1603		gm_out = gm_out .. "\nActive buggers: " .. stats.bugger.active_ship_count
1604	end
1605	addGMMessage(gm_out)
1606end
1607function detailedDroneReport()
1608	print(" ")
1609	print(">>>>>>>>>>>>>>>BEGIN DETAILED DRONE REPORT<<<<<<<<<<<<<")
1610	local drone_disposition = nil
1611	for index=1,32 do
1612		local player_ship = getPlayerShip(index)
1613		if player_ship ~= nil and player_ship:isValid() then
1614			local faction = player_ship:getFaction()
1615			if faction ~= "Exuari" then
1616				print("  Player ship " .. index .. ": " .. faction)
1617				print("    Call Sign:  " .. player_ship:getCallSign())
1618				print("    Current # of stored drones:  " .. player_ship.dronePool)
1619				local player_drone_squad_count = 0
1620				local active_drone_count = 0
1621				if player_ship.droneSquads ~= nil then
1622					for squadName, droneList in pairs(player_ship.droneSquads) do
1623						player_drone_squad_count = player_drone_squad_count + 1
1624						print("    Drone Squad: " .. squadName)
1625						for i=1,#droneList do
1626							if droneList[i]:isValid() then
1627								print("        Drone " .. i .. " (" .. droneList[i]:getCallSign() .. ") Active")
1628								active_drone_count = active_drone_count + 1
1629							else
1630								print("        Drone " .. i .. " Destroyed")
1631							end
1632						end
1633					end
1634				end
1635				print("    Number of deloyed drone squadrons:  " .. player_drone_squad_count)
1636				print("    Current number of live deployed drones:  " .. active_drone_count)
1637				print("  ---")
1638			end
1639		end
1640	end
1641	print(">>>>>>>>>>>>>>>>>END DETAILED REPORT<<<<<<<<<<<<<<<<<<<")
1642end
1643----------------------------------------
1644--	Initialization support functions  --
1645----------------------------------------
1646function setVariations()
1647	if string.find(getScenarioVariation(),"Easy") then		--will be told which opposing team ship picked up flag
1648		difficulty = .5
1649		difficulty_text = "easy"
1650		flagScanDepth = 1						--number of times to scan
1651		flagScanComplexity = math.random(1,2)	--number of bars in scan
1652	elseif string.find(getScenarioVariation(),"Hard") then	--won't be told when opposing team picks up flag
1653		difficulty = 2
1654		difficulty_text = "hard"
1655		flagScanDepth = math.random(1,3)		--number of times to scan
1656		flagScanComplexity = math.random(3,4)	--number of bars in scan
1657	else													--will be told that opposing team picked up flag
1658		difficulty = 1		--default (normal)
1659		difficulty_text = "normal"
1660		flagScanDepth = math.random(2,3)		--number of times to scan
1661		flagScanComplexity = 2					--number of bars in scan
1662	end
1663	if string.find(getScenarioVariation(),"Small") then
1664		terrain_size = "small"
1665		boundary = 50000
1666	elseif string.find(getScenarioVariation(),"Large") then
1667		boundary = 200000
1668		terrain_size = "large"
1669	else
1670		boundary = 100000
1671		terrain_size = "medium"
1672	end
1673end
1674function initializeDroneButtonFunctionTables()
1675	drop_decoy_functions = {
1676		{p1DropDecoy,p1DropDecoy2,p1DropDecoy3},
1677		{p2DropDecoy,p2DropDecoy2,p2DropDecoy3},
1678		{p3DropDecoy,p3DropDecoy2,p3DropDecoy3},
1679		{p4DropDecoy,p4DropDecoy2,p4DropDecoy3},
1680		{	nil		,p5DropDecoy ,p5DropDecoy3},
1681		{	nil		,p6DropDecoy ,p6DropDecoy3},
1682		{	nil		,	nil		 ,p7DropDecoy},
1683		{	nil		,	nil		 ,p8DropDecoy},
1684	}
1685end
1686--[[
1687function namePlayer(pobj,player_type)
1688	if #playerShipNamesFor[player_type] > 0 then
1689		pobj:setCallSign(tableRemoveRandom(playerShipNamesFor[player_type]))
1690	else
1691		pobj:setCallSign(tableRemoveRandom(playerShipNamesFor["Leftovers"]))
1692	end
1693end
1694--]]
1695function namePlayer(p,player_type)
1696	if p.name == nil then
1697--		print("template:",player_type)
1698		if preset_players ~= nil then
1699--			print("preset players exist")
1700			if #preset_players > 0 then
1701--				print("preset players remain:",#preset_players)
1702				for i=1,#preset_players do
1703--					print("Checking item number:",i,"XO:",preset_players[i].xo)
1704					if preset_players[i].ship_pref_1 ~= nil then	--preference
1705--						print("has ship preference:",preset_players[i].ship_pref_1,"current template:",player_type)
1706						if preset_players[i].ship_pref_1 == player_type then
1707--							print("ship preference matches")
1708							if preset_players[i].faction ~= nil then
1709--								print("has preferred faction:",preset_players[i].faction)
1710								if preset_players[i].faction == p:getFaction() then
1711--									print("faction matches")
1712									if preset_players[i].ship_name ~= nil then	--preference, faction, name
1713										p:setCallSign(preset_players[i].ship_name)
1714										p.name = "preset"
1715										print(string.format("XO: %s, Faction: %s, Ship Type: %s, Ship Name: %s",preset_players[i].xo,p:getFaction(),player_type,p:getCallSign()))
1716										table.remove(preset_players,i)
1717									else	--preference, faction, no name
1718										namePlayerShipRandomly(p,player_type)
1719										p.name = "preset"
1720										print(string.format("XO: %s, Faction: %s, Ship Type: %s, Ship Name: %s",preset_players[i].xo,p:getFaction(),player_type,p:getCallSign()))
1721										table.remove(preset_players,i)
1722									end
1723								end
1724								--preference matched, but faction did not
1725							else
1726								if preset_players[i].ship_name ~= nil then	--preference, no faction, name
1727									p:setCallSign(preset_players[i].ship_name)
1728									p.name = "preset"
1729									print(string.format("XO: %s, Faction: %s, Ship Type: %s, Ship Name: %s",preset_players[i].xo,p:getFaction(),player_type,p:getCallSign()))
1730									table.remove(preset_players,i)
1731								else	--preference, no faction, no name
1732									namePlayerShipRandomly(p,player_type)
1733									p.name = "preset"
1734									print(string.format("XO: %s, Faction: %s, Ship Type: %s, Ship Name: %s",preset_players[i].xo,p:getFaction(),player_type,p:getCallSign()))
1735									table.remove(preset_players,i)
1736								end
1737							end
1738						end
1739					elseif preset_players[i].ship_name ~= nil then	--name
1740--						print("has ship name:",preset_players[i].ship_name)
1741						if preset_players[i].faction ~= nil then
1742							if preset_players[i].faction == p:getFaction() then	--name, faction, no preference
1743								p:setCallSign(preset_players[i].ship_name)
1744								p.name = "preset"
1745								print(string.format("XO: %s, Faction: %s, Ship Type: %s, Ship Name: %s",preset_players[i].xo,p:getFaction(),player_type,p:getCallSign()))
1746								table.remove(preset_players,i)
1747							end
1748							--faction did not match
1749						else	--name, no faction, no preference
1750							p:setCallSign(preset_players[i].ship_name)
1751							p.name = "preset"
1752							print(string.format("XO: %s, Faction: %s, Ship Type: %s, Ship Name: %s",preset_players[i].xo,p:getFaction(),player_type,p:getCallSign()))
1753							table.remove(preset_players,i)
1754						end
1755					elseif preset_players[i].faction ~= nil then
1756						if preset_players[i].faction == p:getFaction() then
1757							namePlayerShipRandomly(p,player_type)
1758							p.name = "preset"
1759							print(string.format("XO: %s, Faction: %s, Ship Type: %s, Ship Name: %s",preset_players[i].xo,p:getFaction(),player_type,p:getCallSign()))
1760							table.remove(preset_players,i)
1761						end
1762					end
1763					if p.name ~= nil then
1764						break
1765					end
1766				end
1767			end
1768		end
1769		if p.name == nil then
1770			namePlayerShipRandomly(p)
1771		end
1772	end
1773end
1774function namePlayerShipRandomly(p,player_type)
1775	if #playerShipNamesFor[player_type] > 0 then
1776		p:setCallSign(tableRemoveRandom(playerShipNamesFor[player_type]))
1777	else
1778		p:setCallSign(tableRemoveRandom(playerShipNamesFor["Leftovers"]))
1779	end
1780	p.name = "set"
1781end
1782
1783
1784function setPlayer(pobj,playerIndex)
1785	goods[pobj] = goodsList
1786	pobj:addReputationPoints(150)
1787	pobj.nameAssigned = true
1788	tempPlayerType = pobj:getTypeName()
1789	if player_ship_stats[tempPlayerType] ~= nil then
1790		pobj.shipScore = player_ship_stats[tempPlayerType].strength
1791		pobj.maxCargo = player_ship_stats[tempPlayerType].cargo
1792	end
1793	pobj.template_type = tempPlayerType
1794	if tempPlayerType == "Atlantis" then
1795		namePlayer(pobj,"Atlantis")
1796	elseif tempPlayerType == "Benedict" then
1797		namePlayer(pobj,"Benedict")
1798	elseif tempPlayerType == "Crucible" then
1799		namePlayer(pobj,"Crucible")
1800	elseif tempPlayerType == "Ender" then
1801		namePlayer(pobj,"Ender")
1802	elseif tempPlayerType == "Flavia P.Falcon" then
1803		namePlayer(pobj,"FlaviaPFalcon")
1804	elseif tempPlayerType == "Hathcock" then
1805		namePlayer(pobj,"Hathcock")
1806		pobj.max_jump_range = 60000
1807		pobj.min_jump_range = 6000
1808		pobj:setJumpDriveRange(pobj.min_jump_range,pobj.max_jump_range)
1809		pobj:setJumpDriveCharge(pobj.max_jump_range)
1810	elseif tempPlayerType == "Kiriya" then
1811		namePlayer(pobj,"Kiriya")
1812	elseif tempPlayerType == "MP52 Hornet" then
1813		namePlayer(pobj,"MP52Hornet")
1814		pobj.autoCoolant = false
1815		pobj:setWarpDrive(true)
1816	elseif tempPlayerType == "Maverick" then
1817		namePlayer(pobj,"Maverick")
1818	elseif tempPlayerType == "Nautilus" then
1819		namePlayer(pobj,"Nautilus")
1820		pobj.max_jump_range = 70000
1821		pobj.min_jump_range = 5000
1822		pobj:setJumpDriveRange(pobj.min_jump_range,pobj.max_jump_range)
1823		pobj:setJumpDriveCharge(pobj.max_jump_range)
1824	elseif tempPlayerType == "Phobos M3P" then
1825		namePlayer(pobj,"PhobosM3P")
1826		pobj:setWarpDrive(true)
1827		pobj:setWarpSpeed(900)
1828	elseif tempPlayerType == "Piranha" then
1829		namePlayer(pobj,"Piranha")
1830	elseif tempPlayerType == "Player Cruiser" then
1831		namePlayer(pobj,"Cruiser")
1832		pobj.max_jump_range = 80000
1833		pobj.min_jump_range = 5000
1834		pobj:setJumpDriveRange(pobj.min_jump_range,pobj.max_jump_range)
1835		pobj:setJumpDriveCharge(pobj.max_jump_range)
1836	elseif tempPlayerType == "Player Fighter" then
1837		namePlayer(pobj,"Fighter")
1838		pobj.autoCoolant = false
1839		pobj:setJumpDrive(true)
1840		pobj.max_jump_range = 40000
1841		pobj.min_jump_range = 3000
1842		pobj:setJumpDriveRange(pobj.min_jump_range,pobj.max_jump_range)
1843		pobj:setJumpDriveCharge(pobj.max_jump_range)
1844	elseif tempPlayerType == "Player Missile Cr." then
1845		namePlayer(pobj,"MissileCruiser")
1846	elseif tempPlayerType == "Repulse" then
1847		namePlayer(pobj,"Repulse")
1848	elseif tempPlayerType == "Striker" then
1849		namePlayer(pobj,"Striker")
1850		pobj:setJumpDrive(true)
1851		pobj.max_jump_range = 40000
1852		pobj.min_jump_range = 3000
1853		pobj:setJumpDriveRange(pobj.min_jump_range,pobj.max_jump_range)
1854		pobj:setJumpDriveCharge(pobj.max_jump_range)
1855	elseif tempPlayerType == "ZX-Lindworm" then
1856		namePlayer(pobj,"Lindworm")
1857		pobj.autoCoolant = false
1858		pobj:setWarpDrive(true)
1859		pobj:setWarpSpeed(950)
1860	else
1861		namePlayer(pobj,"Leftovers")
1862		pobj.shipScore = 24
1863		pobj.maxCargo = 5
1864		if not pobj:hasSystem("warp") and not pobj:hasSystem("jumpdrive") then
1865			pobj:setWarpDrive(true)
1866		end
1867	end
1868	if dronesAreAllowed then
1869		pobj.deploy_drone = function(pidx,droneNumber)
1870			local p = getPlayerShip(pidx)
1871			local px, py = p:getPosition()
1872			local droneList = {}
1873			if p.droneSquads == nil then
1874				p.droneSquads = {}
1875				p.squadCount = 0
1876			end
1877			local squadIndex = p.squadCount + 1
1878			local pName = p:getCallSign()
1879			local squadName = string.format("%s-Sq%i",pName,squadIndex)
1880			all_squad_count = all_squad_count + 1
1881			for i=1,droneNumber do
1882				local vx, vy = vectorFromAngle(360/droneNumber*i,800)
1883				local drone = CpuShip():setPosition(px+vx,py+vy):setFaction(p:getFaction()):setTemplate("Ktlitan Drone"):setScanned(true):setCommsScript(""):setCommsFunction(commsShip):setHeading(360/droneNumber*i+90)
1884				if drone_name_type == "squad-num/size" then
1885					drone:setCallSign(string.format("%s-#%i/%i",squadName,i,droneNumber))
1886				elseif drone_name_type == "squad-num of size" then
1887					drone:setCallSign(string.format("%s-%i of %i",squadName,i,droneNumber))
1888				elseif drone_name_type == "short" then
1889					--string.char(math.random(65,90)) --random letter A-Z
1890					local squad_letter_id = string.char(all_squad_count%26+64)
1891					if all_squad_count > 26 then
1892						squad_letter_id = squad_letter_id .. string.char(math.floor(all_squad_count/26)+64)
1893						if all_squad_count > 676 then
1894							squad_letter_id = squad_letter_id .. string.char(math.floor(all_squad_count/676)+64)
1895						end
1896					end
1897					drone:setCallSign(string.format("%s%i/%i",squad_letter_id,i,droneNumber))
1898				end
1899				if drone_modified_from_template then
1900					drone:setHullMax(drone_hull_strength):setHull(drone_hull_strength):setImpulseMaxSpeed(drone_impulse_speed)
1901					--       index from 0, arc, direction,            range,            cycle time,            damage
1902					drone:setBeamWeapon(0,  40,         0, drone_beam_range, drone_beam_cycle_time, drone_beam_damage)
1903				end
1904				drone.squadName = squadName
1905				drone.deployer = p
1906				drone.drone = true
1907				drone:onDestruction(droneDestructionManagement)
1908				table.insert(droneList,drone)
1909			end
1910			p.squadCount = p.squadCount + 1
1911			p.dronePool = p.dronePool - droneNumber
1912			p.droneSquads[squadName] = droneList
1913			if p:hasPlayerAtPosition("Weapons") then
1914				if droneNumber > 1 then
1915					p:addCustomMessage("Weapons","drone_launch_confirm_message_weapons",string.format("%i drones launched",droneNumber))
1916				else
1917					p:addCustomMessage("Weapons","drone_launch_confirm_message_weapons",string.format("%i drone launched",droneNumber))
1918				end
1919			end
1920			if p:hasPlayerAtPosition("Tactical") then
1921				if droneNumber > 1 then
1922					p:addCustomMessage("Tactical","drone_launch_confirm_message_tactical",string.format("%i drones launched",droneNumber))
1923				else
1924					p:addCustomMessage("Tactical","drone_launch_confirm_message_tactical",string.format("%i drone launched",droneNumber))
1925				end
1926			end
1927			if droneNumber > 1 then
1928				p:addToShipLog(string.format("Deployed %i drones as squadron %s",droneNumber,squadName),"White")
1929			else
1930				p:addToShipLog(string.format("Deployed %i drone as squadron %s",droneNumber,squadName),"White")
1931			end
1932		end
1933		pobj.count_drones = function(pidx)
1934			local p = getPlayerShip(pidx)
1935			local msgLabel = string.format("weaponsDroneCount%s",p:getCallSign())
1936			p:addCustomMessage("Weapons",msgLabel,string.format("You have %i drones to deploy",p.dronePool))
1937			msgLabel = string.format("tacticalDroneCount%s",p:getCallSign())
1938			p:addCustomMessage("Tactical",msgLabel,string.format("You have %i drones to deploy",p.dronePool))
1939		end
1940		pobj.drone_hull_status = function(pidx)
1941			local player_ship = getPlayerShip(pidx)
1942			local drone_report_message = "> > > > > > > > Drone Hull Status Report: < < < < < < < <"
1943			--drone_report_message = drone_report_message .. "\n    Current number of stored drones:  " .. player_ship.dronePool
1944			local player_drone_squad_count = 0
1945			local active_drone_count = 0
1946			if player_ship.droneSquads ~= nil then
1947				for squadName, droneList in pairs(player_ship.droneSquads) do
1948					player_drone_squad_count = player_drone_squad_count + 1
1949					drone_report_message = drone_report_message .. "\n        Drone Squad: " .. squadName
1950					local active_drone_in_squad_count = 0
1951					local squad_report = ""
1952					for i=1,#droneList do
1953						local drone = droneList[i]
1954						if drone:isValid() then
1955							squad_report = squad_report .. string.format("\n            Drone %i (%s) Hull: %i/%i",
1956								i,
1957								drone:getCallSign(),
1958								math.floor(drone:getHull()),
1959								math.floor(drone:getHullMax()))
1960							active_drone_count = active_drone_count + 1
1961							active_drone_in_squad_count = active_drone_in_squad_count + 1
1962						else
1963							squad_report = squad_report .. string.format("\n            Drone %i --Destroyed--",i)
1964						end
1965					end
1966					if active_drone_in_squad_count > 0 then
1967						drone_report_message = drone_report_message .. squad_report
1968					else
1969						drone_report_message = drone_report_message .. " --Destroyed--"
1970					end
1971				end
1972			end
1973			drone_report_message = drone_report_message .. "\n    Number of deployed drone squadrons: " .. player_drone_squad_count
1974			drone_report_message = drone_report_message .. "\n    Current number of live deployed drones: " .. active_drone_count
1975			local p_name = player_ship:getCallSign()
1976			if player_ship:hasPlayerAtPosition("Engineering") then
1977				player_ship:addCustomMessage("Engineering",string.format("%sengineeringdronesstatus",p_name),drone_report_message)
1978			end
1979			if player_ship:hasPlayerAtPosition("Engineering+") then
1980				player_ship:addCustomMessage("Engineering+",string.format("%sengineeringplusdronesstatus",p_name),drone_report_message)
1981			end
1982		end
1983		pobj.drone_locations = function(pidx)
1984			local player_ship = getPlayerShip(pidx)
1985			local drone_report_message = "> > > > > > > > Drone Location Report: < < < < < < < <"
1986			--drone_report_message = drone_report_message .. "\n    Current number of stored drones:  " .. player_ship.dronePool
1987			local player_drone_squad_count = 0
1988			local active_drone_count = 0
1989			if player_ship.droneSquads ~= nil then
1990				for squadName, droneList in pairs(player_ship.droneSquads) do
1991					player_drone_squad_count = player_drone_squad_count + 1
1992					drone_report_message = drone_report_message .. "\n        Drone Squad: " .. squadName
1993					local active_drone_in_squad_count = 0
1994					local squad_report = ""
1995					for i=1,#droneList do
1996						local drone = droneList[i]
1997						if drone:isValid() then
1998							local drone_x, drone_y = drone:getPosition()
1999							squad_report = squad_report .. string.format("\n            Drone %i (%s) Sector %s, X: %7.0f, Y: %7.0f",
2000								i,
2001								drone:getCallSign(),
2002								drone:getSectorName(),
2003								drone_x,
2004								drone_y)
2005							active_drone_count = active_drone_count + 1
2006							active_drone_in_squad_count = active_drone_in_squad_count + 1
2007						else
2008							squad_report = squad_report .. string.format("\n            Drone %i --Destroyed--",i)
2009						end
2010					end
2011					if active_drone_in_squad_count > 0 then
2012						drone_report_message = drone_report_message .. squad_report
2013					else
2014						drone_report_message = drone_report_message .. " --Destroyed--"
2015					end
2016				end
2017			end
2018			drone_report_message = drone_report_message .. "\n    Number of deployed drone squadrons: " .. player_drone_squad_count
2019			drone_report_message = drone_report_message .. "\n    Current number of live deployed drones: " .. active_drone_count
2020			local p_name = player_ship:getCallSign()
2021			if player_ship:hasPlayerAtPosition("Helms") then
2022				player_ship:addCustomMessage("Helms",string.format("%shelmdroneslocation",p_name),drone_report_message)
2023			end
2024			if player_ship:hasPlayerAtPosition("Tactical") then
2025				player_ship:addCustomMessage("Tactical",string.format("%stacticaldroneslocation",p_name),drone_report_message)
2026			end
2027		end
2028		local pName = pobj:getCallSign()
2029		--local button_name = ""
2030		if pobj.droneButton == nil then
2031			pobj.droneButton = true
2032			pobj.dronePool = uniform_drone_carrying_capacity
2033			pobj:addCustomButton("Weapons",string.format("%sdeploy5weapons",pName),"5 Drones",function()
2034				string.format("")	--global context for SeriousProton
2035				pobj.deploy_drone(playerIndex,5)
2036			end)
2037			pobj:addCustomButton("Tactical",string.format("%sdeploy5tactical",pName),"5 Drones",function()
2038				string.format("")	--global context for SeriousProton
2039				pobj.deploy_drone(playerIndex,5)
2040			end)
2041			pobj:addCustomButton("Weapons",string.format("%sdeploy10weapons",pName),"10 Drones",function()
2042				string.format("")	--global context for SeriousProton
2043				pobj.deploy_drone(playerIndex,10)
2044			end)
2045			pobj:addCustomButton("Tactical",string.format("%sdeploy10tactical",pName),"10 Drones",function()
2046				string.format("")	--global context for SeriousProton
2047				pobj.deploy_drone(playerIndex,10)
2048			end)
2049			pobj:addCustomButton("Weapons",string.format("%scountWeapons",pName),"Count Drones",function()
2050				string.format("")	--global context for SeriousProton
2051				pobj.count_drones(playerIndex)
2052			end)
2053			pobj:addCustomButton("Tactical",string.format("%scountTactical",pName),"Count Drones",function()
2054				string.format("")	--global context for SeriousProton
2055				pobj.count_drones(playerIndex)
2056			end)
2057			pobj:addCustomButton("Engineering",string.format("%shullEngineering",pName),"Drone Hulls",function()
2058				string.format("")	--global context for SeriousProton
2059				pobj.drone_hull_status(playerIndex)
2060			end)
2061			pobj:addCustomButton("Engineering+",string.format("%shullEngineeringPlus",pName),"Drone Hulls",function()
2062				string.format("")	--global context for SeriousProton
2063				pobj.drone_hull_status(playerIndex)
2064			end)
2065			pobj:addCustomButton("Helms",string.format("%slocationHelm",pName),"Drone Locations",function()
2066				string.format("")	--global context for SeriousProton
2067				pobj.drone_locations(playerIndex)
2068			end)
2069			pobj:addCustomButton("Tactical",string.format("%slocationTactical",pName),"Drone Locations",function()
2070				string.format("")	--global context for SeriousProton
2071				pobj.drone_locations(playerIndex)
2072			end)
2073		end
2074	end
2075	pobj.cargo = pobj.maxCargo
2076	pobj.maxRepairCrew = pobj:getRepairCrewCount()
2077	pobj.healthyShield = 1.0
2078	pobj.prevShield = 1.0
2079	pobj.healthyReactor = 1.0
2080	pobj.prevReactor = 1.0
2081	pobj.healthyManeuver = 1.0
2082	pobj.prevManeuver = 1.0
2083	pobj.healthyImpulse = 1.0
2084	pobj.prevImpulse = 1.0
2085	if pobj:getBeamWeaponRange(0) > 0 then
2086		pobj.healthyBeam = 1.0
2087		pobj.prevBeam = 1.0
2088	end
2089	if pobj:getWeaponTubeCount() > 0 then
2090		pobj.healthyMissile = 1.0
2091		pobj.prevMissile = 1.0
2092	end
2093	if pobj:hasWarpDrive() then
2094		pobj.healthyWarp = 1.0
2095		pobj.prevWarp = 1.0
2096	end
2097	if pobj:hasJumpDrive() then
2098		pobj.healthyJump = 1.0
2099		pobj.prevJump = 1.0
2100	end
2101	local control_code_index = math.random(1,#control_code_stem)
2102	local stem = control_code_stem[control_code_index]
2103	table.remove(control_code_stem,control_code_index)
2104	local branch = math.random(100,999)
2105	pobj.control_code = stem .. branch
2106	pobj:setControlCode(stem .. branch)
2107	print("Control Code for " .. pobj:getCallSign(), pobj.control_code)
2108	pobj.tagged_count = 0
2109	pobj.pick_up_count = 0
2110	pobj.drop_count = 0
2111	pobj:setMaxScanProbeCount(player_ship_stats[tempPlayerType].probes)
2112	pobj:setScanProbeCount(player_ship_stats[tempPlayerType].probes)
2113	pobj:onDestroyed(function(self)
2114		self.point_of_destruction_x, self.point_of_destruction_y = self:getPosition()
2115		if self.flag then			--destroyed ship carrying flag
2116			self.flag = false		--drop flag
2117			self.drop_count = self.drop_count + 1
2118			local my_faction = self:getFaction()
2119			local px, py = self:getPosition()
2120			if my_faction == "Kraylor" then
2121				p1Flag = Artifact():setPosition(px,py):setModel("artifact5"):allowPickup(false)
2122				table.insert(human_flags,p1Flag)
2123				p1Flag:setDescriptions("Flag","Human Navy Flag"):setRadarSignatureInfo(15,10,5):setScanningParameters(flagScanComplexity,flagScanDepth)
2124				if difficulty < 2 then
2125					p1Flag:setScannedByFaction("Kraylor",true)
2126					if difficulty < 1 then
2127						globalMessage(string.format("%s dropped Human Navy flag",self:getCallSign()))
2128					else
2129						globalMessage("Human Navy flag dropped")
2130					end
2131				else
2132					if hard_flag_reveal then
2133						globalMessage("Flag dropped")
2134					end
2135				end
2136			elseif my_faction == "Human Navy" then
2137				p2Flag = Artifact():setPosition(px,py):setModel("artifact5"):allowPickup(false)
2138				table.insert(kraylor_flags,p2Flag)
2139				p2Flag:setDescriptions("Flag","Kraylor Flag"):setRadarSignatureInfo(15,10,5):setScanningParameters(flagScanComplexity,flagScanDepth)
2140				if difficulty < 2 then
2141					p2Flag:setScannedByFaction("Human Navy",true)
2142					if difficulty < 1 then
2143						globalMessage(string.format("%s dropped Kraylor flag",p:getCallSign()))
2144					else
2145						globalMessage("Kraylor flag dropped")
2146					end
2147				else
2148					if hard_flag_reveal then
2149						globalMessage("Flag dropped")
2150					end
2151				end
2152			end
2153		end
2154	end)
2155end
2156
2157-----------------
2158--	Utilities  --
2159-----------------
2160function tableRemoveRandom(array)
2161--	Remove random element from array and return it.
2162	-- Returns nil if the array is empty,
2163	-- analogous to `table.remove`.
2164    local array_item_count = #array
2165    if array_item_count == 0 then
2166        return nil
2167    end
2168    local selected_item = math.random(array_item_count)
2169    array[selected_item], array[array_item_count] = array[array_item_count], array[selected_item]
2170    return table.remove(array)
2171end
2172function placeRandomAroundPointList(object_type, amount, dist_min, dist_max, x0, y0)
2173	local pointList = {}
2174    for n=1,amount do
2175        local r = random(0, 360)
2176        local distance = random(dist_min, dist_max)
2177        x = x0 + math.cos(r / 180 * math.pi) * distance
2178        y = y0 + math.sin(r / 180 * math.pi) * distance
2179        pointObj = object_type():setPosition(x, y)
2180		table.insert(pointList,pointObj)
2181    end
2182	return pointList
2183end
2184function createRandomAlongArc(object_type, amount, x, y, distance, startArc, endArcClockwise, randomize)
2185	-- Create amount of objects of type object_type along arc
2186	-- Center defined by x and y
2187	-- Radius defined by distance
2188	-- Start of arc between 0 and 360 (startArc), end arc: endArcClockwise
2189	-- Use randomize to vary the distance from the center point. Omit to keep distance constant
2190	-- Example:
2191	--   createRandomAlongArc(Asteroid, 100, 500, 3000, 65, 120, 450)
2192	arcObjects = {}
2193	if randomize == nil then randomize = 0 end
2194	if amount == nil then amount = 1 end
2195	arcLen = endArcClockwise - startArc
2196	if startArc > endArcClockwise then
2197		endArcClockwise = endArcClockwise + 360
2198		arcLen = arcLen + 360
2199	end
2200	if amount > arcLen then
2201		for ndex=1,arcLen do
2202			radialPoint = startArc+ndex
2203			pointDist = distance + random(-randomize,randomize)
2204			arcObj = object_type():setPosition(x + math.cos(radialPoint / 180 * math.pi) * pointDist, y + math.sin(radialPoint / 180 * math.pi) * pointDist)
2205			table.insert(arcObjects,arcObj)
2206		end
2207		for ndex=1,amount-arcLen do
2208			radialPoint = random(startArc,endArcClockwise)
2209			pointDist = distance + random(-randomize,randomize)
2210			arcObj = object_type():setPosition(x + math.cos(radialPoint / 180 * math.pi) * pointDist, y + math.sin(radialPoint / 180 * math.pi) * pointDist)
2211			table.insert(arcObjects,arcObj)
2212		end
2213	else
2214		for ndex=1,amount do
2215			radialPoint = random(startArc,endArcClockwise)
2216			pointDist = distance + random(-randomize,randomize)
2217			arcObj = object_type():setPosition(x + math.cos(radialPoint / 180 * math.pi) * pointDist, y + math.sin(radialPoint / 180 * math.pi) * pointDist)
2218			table.insert(arcObjects,arcObj)
2219		end
2220	end
2221	return arcObjects
2222end
2223--	Mortal repair crew
2224function healthCheck(delta)
2225	if healthCheckTimer < 0 then
2226		for pidx=1,32 do
2227			p = getPlayerShip(pidx)
2228			if p ~= nil and p:isValid() then
2229				if p:getRepairCrewCount() > 0 then
2230					fatalityChance = 0
2231					if p:getShieldCount() > 1 then
2232						cShield = (p:getSystemHealth("frontshield") + p:getSystemHealth("rearshield"))/2
2233					else
2234						cShield = p:getSystemHealth("frontshield")
2235					end
2236					fatalityChance = fatalityChance + (p.prevShield - cShield)
2237					p.prevShield = cShield
2238					fatalityChance = fatalityChance + (p.prevReactor - p:getSystemHealth("reactor"))
2239					p.prevReactor = p:getSystemHealth("reactor")
2240					fatalityChance = fatalityChance + (p.prevManeuver - p:getSystemHealth("maneuver"))
2241					p.prevManeuver = p:getSystemHealth("maneuver")
2242					fatalityChance = fatalityChance + (p.prevImpulse - p:getSystemHealth("impulse"))
2243					p.prevImpulse = p:getSystemHealth("impulse")
2244					if pobj:getBeamWeaponRange(0) > 0 then
2245						if p.healthyBeam == nil then
2246							p.healthyBeam = 1.0
2247							p.prevBeam = 1.0
2248						end
2249						fatalityChance = fatalityChance + (p.prevBeam - p:getSystemHealth("beamweapons"))
2250						p.prevBeam = p:getSystemHealth("beamweapons")
2251					end
2252					if p:getWeaponTubeCount() > 0 then
2253						if p.healthyMissile == nil then
2254							p.healthyMissile = 1.0
2255							p.prevMissile = 1.0
2256						end
2257						fatalityChance = fatalityChance + (p.prevMissile - p:getSystemHealth("missilesystem"))
2258						p.prevMissile = p:getSystemHealth("missilesystem")
2259					end
2260					if p:hasWarpDrive() then
2261						if p.healthyWarp == nil then
2262							p.healthyWarp = 1.0
2263							p.prevWarp = 1.0
2264						end
2265						fatalityChance = fatalityChance + (p.prevWarp - p:getSystemHealth("warp"))
2266						p.prevWarp = p:getSystemHealth("warp")
2267					end
2268					if p:hasJumpDrive() then
2269						if p.healthyJump == nil then
2270							p.healthyJump = 1.0
2271							p.prevJump = 1.0
2272						end
2273						fatalityChance = fatalityChance + (p.prevJump - p:getSystemHealth("jumpdrive"))
2274						p.prevJump = p:getSystemHealth("jumpdrive")
2275					end
2276					if p:getRepairCrewCount() == 1 then
2277						fatalityChance = fatalityChance/2	-- increase chances of last repair crew standing
2278					end
2279					if fatalityChance > 0 then
2280						crewFate(p,fatalityChance)
2281					end
2282				else
2283					if random(1,100) <= 4 then
2284						p:setRepairCrewCount(1)
2285						if p:hasPlayerAtPosition("Engineering") then
2286							local repairCrewRecovery = "repairCrewRecovery"
2287							p:addCustomMessage("Engineering",repairCrewRecovery,"Medical team has revived one of your repair crew")
2288						end
2289						if p:hasPlayerAtPosition("Engineering+") then
2290							local repairCrewRecoveryPlus = "repairCrewRecoveryPlus"
2291							p:addCustomMessage("Engineering+",repairCrewRecoveryPlus,"Medical team has revived one of your repair crew")
2292						end
2293						resetPreviousSystemHealth(p)
2294					end
2295				end
2296			end
2297		end
2298		healthCheckTimer = delta + healthCheckTimerInterval
2299	end
2300end
2301function crewFate(p, fatalityChance)
2302	if math.random() < (fatalityChance) then
2303		p:setRepairCrewCount(p:getRepairCrewCount() - 1)
2304		if p:hasPlayerAtPosition("Engineering") then
2305			repairCrewFatality = "repairCrewFatality"
2306			p:addCustomMessage("Engineering",repairCrewFatality,"One of your repair crew has perished")
2307		end
2308		if p:hasPlayerAtPosition("Engineering+") then
2309			repairCrewFatalityPlus = "repairCrewFatalityPlus"
2310			p:addCustomMessage("Engineering+",repairCrewFatalityPlus,"One of your repair crew has perished")
2311		end
2312	end
2313end
2314function resetPreviousSystemHealth(p)
2315	string.format("")	--may need global context
2316	if p == nil then
2317		p = comms_source
2318	end
2319	local currentShield = 0
2320	if p:getShieldCount() > 1 then
2321		currentShield = (p:getSystemHealth("frontshield") + p:getSystemHealth("rearshield"))/2
2322	else
2323		currentShield = p:getSystemHealth("frontshield")
2324	end
2325	p.prevShield = currentShield
2326	p.prevReactor = p:getSystemHealth("reactor")
2327	p.prevManeuver = p:getSystemHealth("maneuver")
2328	p.prevImpulse = p:getSystemHealth("impulse")
2329	if p:getBeamWeaponRange(0) > 0 then
2330		if p.healthyBeam == nil then
2331			p.healthyBeam = 1.0
2332			p.prevBeam = 1.0
2333		end
2334		p.prevBeam = p:getSystemHealth("beamweapons")
2335	end
2336	if p:getWeaponTubeCount() > 0 then
2337		if p.healthyMissile == nil then
2338			p.healthyMissile = 1.0
2339			p.prevMissile = 1.0
2340		end
2341		p.prevMissile = p:getSystemHealth("missilesystem")
2342	end
2343	if p:hasWarpDrive() then
2344		if p.healthyWarp == nil then
2345			p.healthyWarp = 1.0
2346			p.prevWarp = 1.0
2347		end
2348		p.prevWarp = p:getSystemHealth("warp")
2349	end
2350	if p:hasJumpDrive() then
2351		if p.healthyJump == nil then
2352			p.healthyJump = 1.0
2353			p.prevJump = 1.0
2354		end
2355		p.prevJump = p:getSystemHealth("jumpdrive")
2356	end
2357end
2358
2359--	Marauding enemies
2360function marauderWaves(delta)
2361	waveTimer = waveTimer - delta
2362	if waveTimer < 0 then
2363		if autoEnemies then
2364			waveTimer = delta + interWave + random(1,60)
2365			if dangerValue == nil then
2366				if difficulty < 1 then
2367					dangerValue = .5
2368					dangerIncrement = .1
2369				elseif difficulty > 1 then
2370					dangerValue = 1
2371					dangerIncrement = .5
2372				else
2373					dangerValue = .8
2374					dangerIncrement = .2
2375				end
2376			end
2377			marauderStart = math.random(1,3)
2378			mhsx = -1*boundary				--all marauder human start points are on the left boundary
2379			mksx = boundary					--all marauder kraylor start points are on the right boundary
2380			if marauderStart == 1 then		--upper left and lower right
2381				mhsy = -1*boundary/2		--marauder human start y
2382				mksy = boundary/2			--marauder kraylor start y
2383				if math.random(1,2) == 1 then
2384					mhex = playerStartX[1]	--marauder human end x
2385					mhey = playerStartY[1]	--marauder human end y
2386					mkex = playerStartX[2]	--marauder kraylor end x
2387					mkey = playerStartY[2]	--marauder kraylor end y
2388				else
2389					mhex = 0				--marauder human end x
2390					mhey = boundary/2		--marauder human end y
2391					mkex = 0				--marauder kraylor end x
2392					mkey = -1*boundary/2	--marauder kraylor end y
2393				end
2394			elseif marauderStart == 2 then	--mid left and mid right
2395				mhsy = 0
2396				mksy = 0
2397				marauderEnd = math.random(1,3)
2398				if marauderEnd == 1 then
2399					mhex = 0
2400					mhey = -1*boundary/2
2401					mkex = 0
2402					mkey = boundary/2
2403				elseif marauderEnd == 2 then
2404					mhex = 0
2405					mhey = boundary/2
2406					mkex = 0
2407					mkey = -1*boundary/2
2408				else
2409					mhex = playerStartX[1]	--marauder human end x
2410					mhey = playerStartY[1]	--marauder human end y
2411					mkex = playerStartX[2]	--marauder kraylor end x
2412					mkey = playerStartY[2]	--marauder kraylor end y
2413				end
2414			else							--lower left and upper right
2415				mhsy = boundary/2
2416				mksy = -1*boundary/2
2417				if math.random(1,2) == 1 then
2418					mhex = playerStartX[1]	--marauder human end x
2419					mhey = playerStartY[1]	--marauder human end y
2420					mkex = playerStartX[2]	--marauder kraylor end x
2421					mkey = playerStartY[2]	--marauder kraylor end y
2422				else
2423					mhex = 0				--marauder human end x
2424					mhey = -1*boundary/2	--marauder human end y
2425					mkex = 0				--marauder kraylor end x
2426					mkey = boundary/2		--marauder kraylor end y
2427				end
2428			end
2429			hmf = spawnEnemies(mhsx,mhsy,dangerValue,"Exuari")
2430			for _, enemy in ipairs(hmf) do
2431				enemy:orderFlyTowards(mhex,mhey)
2432			end
2433			kmf = spawnEnemies(mksx,mksy,dangerValue,"Exuari")
2434			for _, enemy in ipairs(kmf) do
2435				enemy:orderFlyTowards(mkex,mkey)
2436			end
2437			wakeList = getObjectsInRadius(playerStartX[1],playerStartY[1],500)
2438			for _, obj in ipairs(wakeList) do
2439				if obj:getFaction() == "Exuari" then
2440					obj:orderRoaming()
2441				end
2442			end
2443			wakeList = getObjectsInRadius(playerStartX[2],playerStartY[2],500)
2444			for _, obj in ipairs(wakeList) do
2445				if obj:getFaction() == "Exuari" then
2446					obj:orderRoaming()
2447				end
2448			end
2449			wakeList = getObjectsInRadius(0,-1*boundary/2,500)
2450			for _, obj in ipairs(wakeList) do
2451				if obj:getFaction() == "Exuari" then
2452					obj:orderRoaming()
2453				end
2454			end
2455			wakeList = getObjectsInRadius(0,boundary/2,500)
2456			for _, obj in ipairs(wakeList) do
2457				if obj:getFaction() == "Exuari" then
2458					obj:orderRoaming()
2459				end
2460			end
2461			dangerValue = dangerValue + dangerIncrement
2462		end
2463	end
2464end
2465function spawnEnemies(xOrigin, yOrigin, danger, enemyFaction)
2466	if enemyFaction == nil then
2467		enemyFaction = "Kraylor"
2468	end
2469	if danger == nil then
2470		danger = 1
2471	end
2472	enemyStrength = math.max(danger * difficulty * playerPower(),5)
2473	enemyPosition = 0
2474	sp = irandom(300,500)			--random spacing of spawned group
2475	deployConfig = random(1,100)	--randomly choose between squarish formation and hexagonish formation
2476	enemyList = {}
2477	-- Reminder: stsl and stnl are ship template score and name list
2478	while enemyStrength > 0 do
2479		shipTemplateType = irandom(1,#stsl)
2480		while stsl[shipTemplateType] > enemyStrength * 1.1 + 5 do
2481			shipTemplateType = irandom(1,#stsl)
2482		end
2483		ship = CpuShip():setFaction(enemyFaction):setTemplate(stnl[shipTemplateType]):orderRoaming()
2484		enemyPosition = enemyPosition + 1
2485		if deployConfig < 50 then
2486			ship:setPosition(xOrigin+fleetPosDelta1x[enemyPosition]*sp,yOrigin+fleetPosDelta1y[enemyPosition]*sp)
2487		else
2488			ship:setPosition(xOrigin+fleetPosDelta2x[enemyPosition]*sp,yOrigin+fleetPosDelta2y[enemyPosition]*sp)
2489		end
2490		table.insert(enemyList, ship)
2491		enemyStrength = enemyStrength - stsl[shipTemplateType]
2492	end
2493	return enemyList
2494end
2495function playerPower()
2496	--evaluate the players for enemy strength and size spawning purposes
2497	playerShipScore = 0
2498	for p5idx=1,32 do
2499		p5obj = getPlayerShip(p5idx)
2500		if p5obj ~= nil and p5obj:isValid() then
2501			if p5obj.shipScore == nil then
2502				playerShipScore = playerShipScore + 24
2503			else
2504				playerShipScore = playerShipScore + p5obj.shipScore
2505			end
2506		end
2507	end
2508	return playerShipScore
2509end
2510
2511-----------------------------------
2512--	Different terrain functions  --
2513-----------------------------------
2514function emptyTerrain()
2515	-- there is no terrain except for the center 'Zebra Station'
2516	dynamicTerrain = nil
2517end
2518--  Default terrain: Asymetric. Creation order: friendlies, planet, neutrals, black hole, generic enemies, leading enemies
2519function defaultTerrain()
2520	gbLow = 1		--grid boundary low
2521	gbHigh = 500	--grid boundary high
2522	grid = {}		--grid - positional model
2523	for i=gbLow,gbHigh do
2524		grid[i] = {}
2525	end
2526	gx = gbHigh/2	--grid coordinate x
2527	gy = gbHigh/2	--grid coordinate y
2528	gp = 1			--grid position list index
2529	gSize = random(6000,8000)	--grid cell size in positional units
2530	sPool = #placeStation		--starting station pool size (friendly and neutral)
2531	adjList = {}				--adjacent space on grid location list
2532	grid[gx][gy] = gp
2533	grid[gx][gy+1] = gp
2534	grid[gx][gy-1] = gp
2535	grid[gx+1][gy] = gp
2536	grid[gx-1][gy] = gp
2537	grid[gx+1][gy+1] = gp
2538	grid[gx+1][gy-1] = gp
2539	grid[gx-1][gy+1] = gp
2540	grid[gx-1][gy-1] = gp
2541	adjList = getAdjacentGridLocations(gx,gy)
2542	gp = 2
2543	rn = math.random(1,#adjList)
2544	gx = adjList[rn][1]
2545	gy = adjList[rn][2]
2546	neutralZoneDistance = 3000
2547	--place stations
2548	for j=1,40 do
2549		tSize = math.random(2,5)		--tack on region size
2550		grid[gy][gy] = gp				--set current grid location to grid position list index
2551		gRegion = {}					--grow region
2552		table.insert(gRegion,{gx,gy})	--store current coordinates in grow region
2553		for i=1,tSize do
2554			adjList = getAdjacentGridLocations(gx,gy)
2555			if #adjList < 1 then		--exit loop if no more adjacent spaces
2556				break
2557			end
2558			rd = math.random(1,#adjList)	--random direction in which to grow
2559			grid[adjList[rd][1]][adjList[rd][2]] = gp
2560			table.insert(gRegion,{adjList[rd][1],adjList[rd][2]})
2561		end
2562		--get adjacent list after done growing region
2563		adjList = getAdjacentGridLocations(gx,gy)
2564		if #adjList < 1 then
2565			adjList = getAllAdjacentGridLocations(gx,gy)
2566		else
2567			if random(1,5) >= 2 then
2568				adjList = getAllAdjacentGridLocations(gx,gy)
2569			end
2570		end
2571		sri = math.random(1,#gRegion)				--select station random region index
2572		psx = (gRegion[sri][1] - (gbHigh/2))*gSize + random(-gSize/2*.95,gSize/2*.95)	--place station x coordinate
2573		psy = (gRegion[sri][2] - (gbHigh/2))*gSize + random(-gSize/2*.95,gSize/2*.95)	--place station y coordinate
2574		if psx < -1*neutralZoneDistance then		--left stations
2575			stationFaction = "Human Navy"			--human
2576		elseif psx > neutralZoneDistance then		--right stations
2577			stationFaction = "Kraylor"				--kraylor
2578		else										--near the middle
2579			stationFaction = "Independent"			--independent
2580		end
2581		if stationFaction == "Independent" and random(1,5) >= 20 and #placeGenericStation > 1 then
2582			si = math.random(1,#placeGenericStation)	--station index
2583			pStation = placeGenericStation[si]()		--place selected station
2584			table.remove(placeGenericStation,si)		--remove station from placement list
2585		else
2586			si = math.random(1,#placeStation)			--station index
2587			pStation = placeStation[si]()				--place selected station
2588			table.remove(placeStation,si)				--remove station from placement list
2589		end
2590		table.insert(terrain_objects,pStation)
2591		if psx < -1*neutralZoneDistance then
2592			table.insert(humanStationList,pStation)
2593		elseif psx > neutralZoneDistance then
2594			table.insert(kraylorStationList,pStation)
2595		else
2596			table.insert(neutralStationList,pStation)
2597		end
2598		gp = gp + 1
2599		rn = math.random(1,#adjList)	--random next station start location
2600		gx = adjList[rn][1]
2601		gy = adjList[rn][2]
2602	end
2603	if not diagnostic then
2604		local nebula_list = placeRandomAroundPointList(Nebula,math.random(10,30),1,150000,0,0)
2605		for _, nebula in ipairs(nebula_list) do
2606			table.insert(terrain_objects,nebula)
2607		end
2608		local tn = Nebula():setPosition(0,0)
2609		table.insert(terrain_objects,tn)
2610		for i=9000,boundary,9000 do	--nebula dividing line
2611			tn = Nebula():setPosition(0,i)
2612			table.insert(terrain_objects,tn)
2613			tn = Nebula():setPosition(0,-1*i)
2614			table.insert(terrain_objects,tn)
2615		end
2616		dynamicTerrain = moveDefaultTerrain
2617		nebLine0h = Nebula():setPosition(0,0)	--nebula line zero human
2618		table.insert(terrain_objects,nebLine0h)
2619		nebLine0k = Nebula():setPosition(0,0)	--nebula line zero kraylor
2620		table.insert(terrain_objects,nebLine0k)
2621		nebLine0Travel = random(5,20)			--nebula line zero travel distance per update
2622		nebLine0Direction = "out"				--nebula line zero direction of travel
2623	end
2624end
2625function moveDefaultTerrain(delta)
2626	nx, ny = nebLine0h:getPosition()
2627	if nebLine0Direction == "out" then		--out from center?
2628		if nx < -1*boundary then			--beyond boundary?
2629			nebLine0Direction = "in"		--change direction to in
2630			nebLine0Travel = random(5,20)	--randomize travel speed
2631		else								--within boundary, normal out movement
2632			nebLine0h:setPosition(nx - nebLine0Travel,ny)
2633		end
2634	else									--in from edge
2635		if nx > 0 then						--beyond boundary?
2636			nebLine0Direction = "out"		--change direction to out
2637			nebLine0Travel = random(5,20)	--randomize travel speed
2638		else								--within boundary, normal in movement
2639			nebLine0h:setPosition(nx + nebLine0Travel, ny)
2640		end
2641	end
2642	nx, ny = nebLine0k:getPosition()		--other nebula mirrors movement
2643	if nebLine0Direction == "out" then
2644		nebLine0k:setPosition(nx + nebLine0Travel, ny)
2645	else
2646		nebLine0k:setPosition(nx - nebLine0Travel, ny)
2647	end
2648	if nebLine20hPos == nil then			--built second set of nebulae yet?
2649		tnx, tny = nebLine0k:getPosition()	--get trigger nebula position
2650		if tnx > 20000 then					--trigger beyond 20k mark?
2651			nebLine20hPos = Nebula():setPosition(0,20000)	--nebula line 20 human positive
2652			nebLine20hNeg = Nebula():setPosition(0,-20000)	--nebula line 20 human negative
2653			nebLine20kPos = Nebula():setPosition(0,20000)	--nebula line 20 kraylor positive
2654			nebLine20kNeg = Nebula():setPosition(0,-20000)	--nebula line 20 kraylor negative
2655			nebLine20Travel = random(7,25)					--nebula line 20 travel distance
2656			nebLine20Direction = "out"						--nebula line 20 direction of travel
2657		end
2658	else									--second set of nebulae built
2659		nx, ny = nebLine20hPos:getPosition()
2660		if nebLine20Direction == "out" then		--out from center?
2661			if nx < -1*boundary then			--beyond boundary?
2662				nebLine20Direction = "in"		--change direction to in
2663				nebLine20Travel = random(7,25)	--randomize travel speed
2664			else								--within boundary, normal out movement
2665				nebLine20hPos:setPosition(nx - nebLine20Travel, ny)
2666			end
2667		else									--in from edge
2668			if nx > 0 then						--beyond boundary?
2669				nebLine20Direction = "out"		--change direction to out
2670				nebLine20Travel = random(7,25)	--randomize travel speed
2671			else								--within boundary, normal in movement
2672				nebLine20hPos:setPosition(nx + nebLine20Travel, ny)
2673			end
2674		end
2675		if nebLine20Direction == "out" then		--other nebulae mirror movement
2676			nx, ny = nebLine20hNeg:getPosition()
2677			nebLine20hNeg:setPosition(nx - nebLine20Travel, ny)
2678			nx, ny = nebLine20kPos:getPosition()
2679			nebLine20kPos:setPosition(nx + nebLine20Travel, ny)
2680			nx, ny = nebLine20kNeg:getPosition()
2681			nebLine20kNeg:setPosition(nx + nebLine20Travel, ny)
2682		else
2683			nx, ny = nebLine20hNeg:getPosition()
2684			nebLine20hNeg:setPosition(nx + nebLine20Travel, ny)
2685			nx, ny = nebLine20kPos:getPosition()
2686			nebLine20kPos:setPosition(nx - nebLine20Travel, ny)
2687			nx, ny = nebLine20kNeg:getPosition()
2688			nebLine20kNeg:setPosition(nx - nebLine20Travel, ny)
2689		end
2690	end
2691	if nebLine40hPos == nil then	--third set built?
2692		tnx, tny = nebLine0k:getPosition()
2693		if tnx > 40000 then
2694			nebLine40hPos = Nebula():setPosition(0,40000)
2695			nebLine40hNeg = Nebula():setPosition(0,-40000)
2696			nebLine40kPos = Nebula():setPosition(0,40000)
2697			nebLine40kNeg = Nebula():setPosition(0,-40000)
2698			nebLine40Travel = random(10,30)
2699			nebLine40Direction = "out"
2700		end
2701	else
2702		nx, ny = nebLine40hPos:getPosition()
2703		if nebLine40Direction == "out" then
2704			if nx < -1*boundary then
2705				nebLine40Direction = "in"
2706				nebLine40Travel = random(10,30)
2707			else
2708				nebLine40hPos:setPosition(nx - nebLine40Travel, ny)
2709			end
2710		else
2711			if nx > 0 then
2712				nebLine40Direction = "out"
2713				nebLine40Travel = random(10,30)
2714			else
2715				nebLine40hPos:setPosition(nx + nebLine40Travel, ny)
2716			end
2717		end
2718		if nebLine40Direction == "out" then
2719			nx, ny = nebLine40hNeg:getPosition()
2720			nebLine40hNeg:setPosition(nx - nebLine40Travel, ny)
2721			nx, ny = nebLine40kPos:getPosition()
2722			nebLine40kPos:setPosition(nx + nebLine40Travel, ny)
2723			nx, ny = nebLine40kNeg:getPosition()
2724			nebLine40kNeg:setPosition(nx + nebLine40Travel, ny)
2725		else
2726			nx, ny = nebLine40hNeg:getPosition()
2727			nebLine40hNeg:setPosition(nx + nebLine40Travel, ny)
2728			nx, ny = nebLine40kPos:getPosition()
2729			nebLine40kPos:setPosition(nx - nebLine40Travel, ny)
2730			nx, ny = nebLine40kNeg:getPosition()
2731			nebLine40kNeg:setPosition(nx - nebLine40Travel, ny)
2732		end
2733	end
2734end
2735function getAllAdjacentGridLocations(lx,ly)
2736	--adjacent empty grid locations around all occupied locations
2737	tempGrid = {}
2738	for i=gbLow,gbHigh do
2739		tempGrid[i] = {}
2740	end
2741	tempGrid[lx][ly] = 1
2742	ol = {}
2743	-- check left
2744	if lx-1 >= gbLow then
2745		if tempGrid[lx-1][ly] == nil then
2746			tempGrid[lx-1][ly] = 1
2747			if grid[lx-1][ly] == nil then
2748				table.insert(ol,{lx-1,ly})
2749			else
2750				--case 1: traveling left, skip right check
2751				getAllAdjacentGridLocationsSkip(1,lx-1,ly)
2752			end
2753		end
2754	end
2755	--check up
2756	if ly-1 >= gbLow then
2757		if tempGrid[lx][ly-1] == nil then
2758			tempGrid[lx][ly-1] = 1
2759			if grid[lx][ly-1] == nil then
2760				table.insert(ol,{lx,ly-1})
2761			else
2762				--case 2: traveling up, skip down check
2763				getAllAdjacentGridLocationsSkip(2,lx,ly-1)
2764			end
2765		end
2766	end
2767	--check right
2768	if lx+1 <= gbHigh then
2769		if tempGrid[lx+1][ly] == nil then
2770			tempGrid[lx+1][ly] = 1
2771			if grid[lx+1][ly] == nil then
2772				table.insert(ol,{lx+1,ly})
2773			else
2774				--case 3: traveling right, skip left check
2775				getAllAdjacentGridLocationsSkip(3,lx+1,ly)
2776			end
2777		end
2778	end
2779	--check down
2780	if ly+1 <= gbHigh then
2781		if tempGrid[lx][ly+1] == nil then
2782			tempGrid[lx][ly+1] = 1
2783			if grid[lx][ly+1] == nil then
2784				table.insert(ol,{lx,ly+1})
2785			else
2786				--case 4: traveling down, skip up check
2787				getAllAdjacentGridLocationsSkip(4,lx,ly+1)
2788			end
2789		end
2790	end
2791	return ol
2792end
2793function getAllAdjacentGridLocationsSkip(dSkip,lx,ly)
2794		--adjacent empty grid locations around all occupied locations, skip as requested
2795	tempGrid[lx][ly] = 1
2796	if dSkip ~= 3 then
2797		--check left
2798		if lx-1 >= gbLow then
2799			if tempGrid[lx-1][ly] == nil then
2800				tempGrid[lx-1][ly] = 1
2801				if grid[lx-1][ly] == nil then
2802					table.insert(ol,{lx-1,ly})
2803				else
2804					--case 1: traveling left, skip right check
2805					getAllAdjacentGridLocationsSkip(1,lx-1,ly)
2806				end
2807			end
2808		end
2809	end
2810	if dSkip ~= 4 then
2811		--check up
2812		if ly-1 >= gbLow then
2813			if tempGrid[lx][ly-1] == nil then
2814				tempGrid[lx][ly-1] = 1
2815				if grid[lx][ly-1] == nil then
2816					table.insert(ol,{lx,ly-1})
2817				else
2818					--case 2: traveling up, skip down check
2819					getAllAdjacentGridLocationsSkip(2,lx,ly-1)
2820				end
2821			end
2822		end
2823	end
2824	if dSkip ~= 1 then
2825		--check right
2826		if lx+1 <= gbHigh then
2827			if tempGrid[lx+1][ly] == nil then
2828				tempGrid[lx+1][ly] = 1
2829				if grid[lx+1][ly] == nil then
2830					table.insert(ol,{lx+1,ly})
2831				else
2832					--case 3: traveling right, skip left check
2833					getAllAdjacentGridLocationsSkip(3,lx+1,ly)
2834				end
2835			end
2836		end
2837	end
2838	if dSkip ~= 2 then
2839		--check down
2840		if ly+1 <= gbHigh then
2841			if tempGrid[lx][ly+1] == nil then
2842				tempGrid[lx][ly+1] = 1
2843				if grid[lx][ly+1] == nil then
2844					table.insert(ol,{lx,ly+1})
2845				else
2846					--case 4: traveling down, skip up check
2847					getAllAdjacentGridLocationsSkip(4,lx,ly+1)
2848				end
2849			end
2850		end
2851	end
2852end
2853function getAdjacentGridLocations(lx,ly)
2854	--adjacent empty grid locations around the most recently placed item
2855	tempGrid = {}
2856	for i=gbLow,gbHigh do
2857		tempGrid[i] = {}
2858	end
2859	tempGrid[lx][ly] = 1
2860	ol = {}
2861	-- check left
2862	if lx-1 >= gbLow then
2863		if tempGrid[lx-1][ly] == nil then
2864			tempGrid[lx-1][ly] = 1
2865			if grid[lx-1][ly] == nil then
2866				table.insert(ol,{lx-1,ly})
2867			elseif grid[lx-1][ly] == gp then
2868				--case 1: traveling left, skip right check
2869				getAdjacentGridLocationsSkip(1,lx-1,ly)
2870			end
2871		end
2872	end
2873	--check up
2874	if ly-1 >= gbLow then
2875		if tempGrid[lx][ly-1] == nil then
2876			tempGrid[lx][ly-1] = 1
2877			if grid[lx][ly-1] == nil then
2878				table.insert(ol,{lx,ly-1})
2879			elseif grid[lx][ly-1] == gp then
2880				--case 2: traveling up, skip down check
2881				getAdjacentGridLocationsSkip(2,lx,ly-1)
2882			end
2883		end
2884	end
2885	--check right
2886	if lx+1 <= gbHigh then
2887		if tempGrid[lx+1][ly] == nil then
2888			tempGrid[lx+1][ly] = 1
2889			if grid[lx+1][ly] == nil then
2890				table.insert(ol,{lx+1,ly})
2891			elseif grid[lx+1][ly] == gp then
2892				--case 3: traveling right, skip left check
2893				getAdjacentGridLocationsSkip(3,lx+1,ly)
2894			end
2895		end
2896	end
2897	--check down
2898	if ly+1 <= gbHigh then
2899		if tempGrid[lx][ly+1] == nil then
2900			tempGrid[lx][ly+1] = 1
2901			if grid[lx][ly+1] == nil then
2902				table.insert(ol,{lx,ly+1})
2903			elseif grid[lx][ly+1] == gp then
2904				--case 4: traveling down, skip up check
2905				getAdjacentGridLocationsSkip(4,lx,ly+1)
2906			end
2907		end
2908	end
2909	return ol
2910end
2911function getAdjacentGridLocationsSkip(dSkip,lx,ly)
2912	--adjacent empty grid locations around the most recently placed item, skip as requested
2913	tempGrid[lx][ly] = 1
2914	if dSkip ~= 3 then
2915		--check left
2916		if lx-1 >= gbLow then
2917			if tempGrid[lx-1][ly] == nil then
2918				tempGrid[lx-1][ly] = 1
2919				if grid[lx-1][ly] == nil then
2920					table.insert(ol,{lx-1,ly})
2921				elseif grid[lx-1][ly] == gp then
2922					--case 1: traveling left, skip right check
2923					getAdjacentGridLocationsSkip(1,lx-1,ly)
2924				end
2925			end
2926		end
2927	end
2928	if dSkip ~= 4 then
2929		--check up
2930		if ly-1 >= gbLow then
2931			if tempGrid[lx][ly-1] == nil then
2932				tempGrid[lx][ly-1] = 1
2933				if grid[lx][ly-1] == nil then
2934					table.insert(ol,{lx,ly-1})
2935				elseif grid[lx][ly-1] == gp then
2936					--case 2: traveling up, skip down check
2937					getAdjacentGridLocationsSkip(2,lx,ly-1)
2938				end
2939			end
2940		end
2941	end
2942	if dSkip ~= 1 then
2943		--check right
2944		if lx+1 <= gbHigh then
2945			if tempGrid[lx+1][ly] == nil then
2946				tempGrid[lx+1][ly] = 1
2947				if grid[lx+1][ly] == nil then
2948					table.insert(ol,{lx+1,ly})
2949				elseif grid[lx+1][ly] == gp then
2950					--case 3: traveling right, skip left check
2951					getAdjacentGridLocationsSkip(3,lx+1,ly)
2952				end
2953			end
2954		end
2955	end
2956	if dSkip ~= 2 then
2957		--check down
2958		if ly+1 <= gbHigh then
2959			if tempGrid[lx][ly+1] == nil then
2960				tempGrid[lx][ly+1] = 1
2961				if grid[lx][ly+1] == nil then
2962					table.insert(ol,{lx,ly+1})
2963				elseif grid[lx][ly+1] == gp then
2964					--case 4: traveling down, skip up check
2965					getAdjacentGridLocationsSkip(4,lx,ly+1)
2966				end
2967			end
2968		end
2969	end
2970end
2971function szt()
2972	--Randomly choose station size template
2973	if stationSize ~= nil then
2974		return stationSize
2975	end
2976	stationSizeRandom = random(1,100)
2977	if stationSizeRandom <= 8 then
2978		sizeTemplate = "Huge Station"		-- 8 percent huge
2979	elseif stationSizeRandom <= 24 then
2980		sizeTemplate = "Large Station"		--16 percent large
2981	elseif stationSizeRandom <= 50 then
2982		sizeTemplate = "Medium Station"		--26 percent medium
2983	else
2984		sizeTemplate = "Small Station"		--50 percent small
2985	end
2986	return sizeTemplate
2987end
2988--	Random symmetric terrain
2989function mirrorKrikAsteroids()
2990	local ax = nil
2991	local ay = nil
2992	for _, obj in ipairs(krikList1) do
2993		ax, ay = obj:getPosition()
2994		table.insert(terrain_objects,Asteroid():setPosition(-ax,-ay))
2995	end
2996	for _, obj in ipairs(krikList2) do
2997		ax, ay = obj:getPosition()
2998		table.insert(terrain_objects,Asteroid():setPosition(-ax,-ay))
2999	end
3000	mirrorKrik = false
3001end
3002function mirrorAsteroids()
3003	for _, obj in ipairs(mirror_station.asteroid_list) do
3004		local ax, ay = obj:getPosition()
3005		table.insert(terrain_objects,Asteroid():setPosition(-ax,-ay))
3006	end
3007	mirror_asteroids = false
3008end
3009function randomSymmetric()
3010	local mirror_asteroids = false
3011	psx, psy = vectorFromAngle(random(135,225),4000)
3012	stationSize = "Small Station"
3013	stationFaction = "Human Navy"
3014	si = math.random(1,#placeGenericStation)
3015	pStation = placeGenericStation[si]()
3016	table.insert(terrain_objects,pStation)
3017	table.remove(placeGenericStation,si)
3018	table.insert(stationList,pStation)
3019	table.insert(humanStationList,pStation)
3020	local station_name = pStation:getCallSign()
3021	if pStation.asteroid_list ~= nil then
3022		mirror_station = pStation
3023	else
3024		mirror_station = nil
3025	end
3026	psx = -psx
3027	psy = -psy
3028	stationFaction = "Kraylor"
3029	si = math.random(1,#placeGenericStation)
3030	pStation = placeGenericStation[si]()
3031	table.insert(terrain_objects,pStation)
3032	table.remove(placeGenericStation,si)
3033	table.insert(stationList,pStation)
3034	table.insert(kraylorStationList,pStation)
3035	if mirror_station ~= nil then
3036		mirrorAsteroids()
3037		mirror_station = nil
3038	end
3039	if pStation.asteroid_list ~= nil then
3040		mirror_station = pStation
3041	else
3042		mirror_station = nil
3043	end
3044	for spi=1,9 do
3045		repeat
3046			rx, ry = stationList[math.random(1,#stationList)]:getPosition()
3047			vx, vy = vectorFromAngle(random(0,360),random(5000,50000))
3048			psx = rx+vx
3049			psy = ry+vy
3050			closestStationDistance = 999999
3051			for si=1,#stationList do
3052				curDist = distance(stationList[si],psx,psy)
3053				if curDist < closestStationDistance then
3054					closestStationDistance = curDist
3055				end
3056			end
3057		until(psx < 0 and closestStationDistance > 4000)
3058		stationSize = nil
3059		if psx > -1000 then
3060			stationFaction = "Independent"
3061		else
3062			stationFaction = "Human Navy"
3063		end
3064		si = math.random(1,#placeGenericStation)
3065		pStation = placeGenericStation[si]()
3066		table.insert(terrain_objects,pStation)
3067		table.remove(placeGenericStation,si)
3068		table.insert(stationList,pStation)
3069		if stationFaction == "Human Navy" then
3070			table.insert(humanStationList,pStation)
3071		end
3072		if mirror_station ~= nil then
3073			mirrorAsteroids()
3074			mirror_station = nil
3075		end
3076		if pStation.asteroid_list ~= nil then
3077			mirror_station = pStation
3078		else
3079			mirror_station = nil
3080		end
3081		stationSize = sizeTemplate
3082		psx = -psx
3083		psy = -psy
3084		if stationFaction ~= "Independent" then
3085			stationFaction = "Kraylor"
3086		end
3087		si = math.random(1,#placeGenericStation)
3088		pStation = placeGenericStation[si]()
3089		table.insert(terrain_objects,pStation)
3090		table.remove(placeGenericStation,si)
3091		table.insert(stationList,pStation)
3092		if stationFaction == "Kraylor" then
3093			table.insert(kraylorStationList,pStation)
3094		end
3095		if mirror_station ~= nil then
3096			mirrorAsteroids()
3097			mirror_station = nil
3098		end
3099		if pStation.asteroid_list ~= nil then
3100			mirror_station = pStation
3101		else
3102			mirror_station = nil
3103		end
3104	end
3105	if mirror_station ~= nil then
3106		mirrorAsteroids()
3107		mirror_station = nil
3108	end
3109	if not diagnostic then
3110		nebList = placeRandomAroundPointList(Nebula,math.random(5,15),1,150000,0,0)
3111		for _, obj in ipairs(nebList) do
3112			table.insert(terrain_objects,obj)
3113			nx, ny = obj:getPosition()
3114			table.insert(terrain_objects,Nebula():setPosition(-nx,-ny))
3115		end
3116		table.insert(terrain_objects,Nebula():setPosition(0,0))
3117		for i=9000,boundary,9000 do	--nebula dividing line
3118			table.insert(terrain_objects,Nebula():setPosition(0,i))
3119			table.insert(terrain_objects,Nebula():setPosition(0,-1*i))
3120		end
3121		dynamicTerrain = moveDefaultTerrain		-- THIS IS VERY IMPORTANT SO THE SCRIPT CALLS THE CORRECT ROUTINE TO MOVE ENVIRONMENT OBJECTS
3122		nebLine0h = Nebula():setPosition(0,0)	--nebula line zero human
3123		table.insert(terrain_objects,nebLine0h)
3124		nebLine0k = Nebula():setPosition(0,0)	--nebula line zero kraylor
3125		table.insert(terrain_objects,nebLine0k)
3126		nebLine0Travel = random(5,20)			--nebula line zero travel distance per update
3127		nebLine0Direction = "out"				--nebula line zero direction of travel
3128	end
3129end
3130--	Just passing by terrain
3131function justPassingBy()
3132	dynamicTerrain = moveJustPassingBy
3133	-- this environment design places a black hole to the rear of each startup area and has large bands of nebula and some asteroids orbiting the black holes in opposite directions
3134	-- NOTE that whereas the initial placement of the left and right black holes are made through variables, the subsequent movement updates of all bodies are done via
3135	-- finding the location of the blackhole; this is done so that it is possible to move the black hole and thus cause the entire orbital system around the blackhole
3136	-- to move with it, should that variation be used within the script
3137
3138	-- first build the left side
3139		left_bh_x_coord = -100000
3140		left_bh_y_coord = 60000
3141		left_blackhole = BlackHole():setPosition(left_bh_x_coord, left_bh_y_coord)
3142		table.insert(terrain_objects,left_blackhole)
3143
3144		-- there will be 3 bands of orbiting stuff:  inner nebula moving quickest, middle asteroids with maybe a planet moving slower, outer nebula moving slowest
3145		-- the inner band will be clumps of nebula orbiting clockwise (orbit rate is set by variable, but initially 1 orbit in 2min)
3146			left_blackhole_inner_band = {}
3147			-- each band will be a nested table (multi-dimensional array)
3148			  -- 1st position on the inner array will be the nebula object
3149			  -- 2nd position on the inner array will be the current angle of the nebula in relation to the blackhole center
3150			  -- there is no need to keep track of the speed in this case as it is uniform for all nebula in this band
3151			left_bh_inner_band_radius = 40000
3152			left_bh_inner_band_orbit_speed = 360/(60 * 120) -- this equates to the number of degrees traversed for each update call if one complete orbit takes 120 seconds; uniform for all nebula
3153			-- because in this design we want the nebula more "clumpy" with gaps inbetween the clumps, there will be 4 clumps of nebula, one starting in each quadrant, centered on the 45
3154			-- degree angle of that quadrant, spanning a variable degree of arc; make the number of nebula in each clump a variable so we can easily modify how thick each clump will be
3155			left_bh_inner_band_clump_density = 8  -- the number of nebula in a clump
3156			left_bh_inner_band_clump_spread = 40  -- the number of degrees of arc for the clump spread of the quandrant bisecting angle
3157			local array_index = 1
3158			-- first clump
3159				begin_spread_angle = 45 - (left_bh_inner_band_clump_spread/2)
3160				spread_angle_end = 45 + (left_bh_inner_band_clump_spread/2)
3161				for i=1,left_bh_inner_band_clump_density do
3162					left_blackhole_inner_band[array_index] = {}
3163					left_blackhole_inner_band[array_index][1] = Nebula()
3164					table.insert(terrain_objects,left_blackhole_inner_band[array_index][1])
3165					left_blackhole_inner_band[array_index][2] = math.random(begin_spread_angle, spread_angle_end)
3166					-- setCirclePos(obj, x, y, angle, distance)
3167					--   obj: An object.
3168					--   x, y: Origin coordinates.
3169					--   angle, distance: Relative heading and distance from the origin.
3170					setCirclePos(left_blackhole_inner_band[array_index][1], left_bh_x_coord, left_bh_y_coord, left_blackhole_inner_band[array_index][2], left_bh_inner_band_radius)
3171					array_index = array_index + 1
3172				end
3173			-- second clump
3174				begin_spread_angle = 135 - (left_bh_inner_band_clump_spread/2)
3175				spread_angle_end = 135 + (left_bh_inner_band_clump_spread/2)
3176				for i=1,left_bh_inner_band_clump_density do
3177					left_blackhole_inner_band[array_index] = {}
3178					left_blackhole_inner_band[array_index][1] = Nebula()
3179					table.insert(terrain_objects,left_blackhole_inner_band[array_index][1])
3180					left_blackhole_inner_band[array_index][2] = math.random(begin_spread_angle, spread_angle_end)
3181					-- setCirclePos(obj, x, y, angle, distance)
3182					--   obj: An object.
3183					--   x, y: Origin coordinates.
3184					--   angle, distance: Relative heading and distance from the origin.
3185					setCirclePos(left_blackhole_inner_band[array_index][1], left_bh_x_coord, left_bh_y_coord, left_blackhole_inner_band[array_index][2], left_bh_inner_band_radius)
3186					array_index = array_index + 1
3187				end
3188			-- third clump
3189				begin_spread_angle = 225 - (left_bh_inner_band_clump_spread/2)
3190				spread_angle_end = 225 + (left_bh_inner_band_clump_spread/2)
3191				for i=1,left_bh_inner_band_clump_density do
3192					left_blackhole_inner_band[array_index] = {}
3193					left_blackhole_inner_band[array_index][1] = Nebula()
3194					table.insert(terrain_objects,left_blackhole_inner_band[array_index][1])
3195					left_blackhole_inner_band[array_index][2] = math.random(begin_spread_angle, spread_angle_end)
3196					-- setCirclePos(obj, x, y, angle, distance)
3197					--   obj: An object.
3198					--   x, y: Origin coordinates.
3199					--   angle, distance: Relative heading and distance from the origin.
3200					setCirclePos(left_blackhole_inner_band[array_index][1], left_bh_x_coord, left_bh_y_coord, left_blackhole_inner_band[array_index][2], left_bh_inner_band_radius)
3201					array_index = array_index + 1
3202				end
3203			-- fourth clump
3204				begin_spread_angle = 315 - (left_bh_inner_band_clump_spread/2)
3205				spread_angle_end = 315 + (left_bh_inner_band_clump_spread/2)
3206				for i=1,left_bh_inner_band_clump_density do
3207					left_blackhole_inner_band[array_index] = {}
3208					left_blackhole_inner_band[array_index][1] = Nebula()
3209					table.insert(terrain_objects,left_blackhole_inner_band[array_index][1])
3210					left_blackhole_inner_band[array_index][2] = math.random(begin_spread_angle, spread_angle_end)
3211					-- setCirclePos(obj, x, y, angle, distance)
3212					--   obj: An object.
3213					--   x, y: Origin coordinates.
3214					--   angle, distance: Relative heading and distance from the origin.
3215					setCirclePos(left_blackhole_inner_band[array_index][1], left_bh_x_coord, left_bh_y_coord, left_blackhole_inner_band[array_index][2], left_bh_inner_band_radius)
3216					array_index = array_index + 1
3217				end
3218
3219		-- the middle band will be a random number of asteroids orbiting counter-clockwise at a randomly determined rate
3220			left_blackhole_middle_band = {}
3221			left_bh_middle_band_min_radius = 55000
3222			left_bh_middle_band_max_radius = 65000
3223
3224			-- the middle band will not have clumps like the first and will just have a random placement of asteroids within the allowable band range, all with randomly set speeds
3225			left_bh_mimdle_band_number_of_asteroids = 100
3226			left_bh_middle_band_min_orbit_speed = 360/(60 * 240) -- this equates to the number of degrees traversed for each update call if one complete orbit takes 240 seconds
3227			left_bh_middle_band_max_orbit_speed = 360/(60 * 150) -- this equates to the number of degrees traversed for each update call if one complete orbit takes 150 seconds
3228
3229			for i=1,left_bh_mimdle_band_number_of_asteroids do
3230				-- each band will be a nested table (multi-dimensional array)
3231				  -- 1st position on the inner array will be the asteroid object
3232				  -- 2nd position on the inner array will be the radius distance from the blackhole center, randomly generated in a band range
3233				  -- 3rd position on the inner array will be the current angle of the asteroid in relation to the blackhole center
3234				  -- 4th position on the inner array will be the orbital speed of the asteroid, expressed as a delta of angle change per update cycle, randomly generated
3235				left_blackhole_middle_band[i]= {}
3236				left_blackhole_middle_band[i][1] = Asteroid()
3237				table.insert(terrain_objects,left_blackhole_middle_band[i][1])
3238				left_blackhole_middle_band[i][2] = math.random(left_bh_middle_band_min_radius, left_bh_middle_band_max_radius)
3239				left_blackhole_middle_band[i][3] = math.random(1, 360)
3240				left_blackhole_middle_band[i][4] = random(left_bh_middle_band_min_orbit_speed, left_bh_middle_band_max_orbit_speed)
3241				-- setCirclePos(obj, x, y, angle, distance)
3242				  --   obj: An object.
3243				  --   x, y: Origin coordinates.
3244				  --   angle, distance: Relative heading and distance from the origin.
3245				setCirclePos(left_blackhole_middle_band[i][1], left_bh_x_coord, left_bh_y_coord, left_blackhole_middle_band[i][3], left_blackhole_middle_band[i][2])
3246			end
3247
3248		-- the outer band will be clumps of nebula orbiting clockwise (orbit rate is set by variable, but initially 1 orbit in 8min)
3249			left_blackhole_outer_band = {}
3250			-- each band will be a nested table (multi-dimensional array)
3251			  -- 1st position on the inner array will be the nebula object
3252			  -- 2nd position on the inner array will be the current angle of the nebula in relation to the blackhole center
3253			  -- there is no need to keep track of the speed in this case as it is uniform for all nebula in this band
3254			left_bh_outer_band_radius = 80000
3255			left_bh_outer_band_orbit_speed = 360/(60 * 360) -- this equates to the number of degrees traversed for each update call if one complete orbit takes 480 seconds; uniform for all nebula
3256			-- because in this design we want the nebula more "clumpy" with gaps inbetween the clumps, there will be 4 clumps of nebula, one starting in each quadrant, centered on the 45
3257			-- degree angle of that quadrant, spanning a variable degree of arc; make the number of nebula in each clump a variable so we can easily modify how thick each clump will be
3258			left_bh_outer_band_clump_density = 10  -- the number of nebula in a clump
3259			left_bh_outer_band_clump_spread = 60  -- the number of degrees of arc for the clump spread of the quandrant bisecting angle
3260			local array_index = 1
3261			-- first clump
3262				begin_spread_angle = 45 - (left_bh_outer_band_clump_spread/2)
3263				spread_angle_end = 45 + (left_bh_outer_band_clump_spread/2)
3264				for i=1,left_bh_outer_band_clump_density do
3265					left_blackhole_outer_band[array_index] = {}
3266					left_blackhole_outer_band[array_index][1] = Nebula()
3267					table.insert(terrain_objects,left_blackhole_outer_band[array_index][1])
3268					left_blackhole_outer_band[array_index][2] = math.random(begin_spread_angle, spread_angle_end)
3269					-- setCirclePos(obj, x, y, angle, distance)
3270					--   obj: An object.
3271					--   x, y: Origin coordinates.
3272					--   angle, distance: Relative heading and distance from the origin.
3273					setCirclePos(left_blackhole_outer_band[array_index][1], left_bh_x_coord, left_bh_y_coord, left_blackhole_outer_band[array_index][2], left_bh_outer_band_radius)
3274					array_index = array_index + 1
3275				end
3276			-- second clump
3277				begin_spread_angle = 135 - (left_bh_outer_band_clump_spread/2)
3278				spread_angle_end = 135 + (left_bh_outer_band_clump_spread/2)
3279				for i=1,left_bh_outer_band_clump_density do
3280					left_blackhole_outer_band[array_index] = {}
3281					left_blackhole_outer_band[array_index][1] = Nebula()
3282					table.insert(terrain_objects,left_blackhole_outer_band[array_index][1])
3283					left_blackhole_outer_band[array_index][2] = math.random(begin_spread_angle, spread_angle_end)
3284					-- setCirclePos(obj, x, y, angle, distance)
3285					--   obj: An object.
3286					--   x, y: Origin coordinates.
3287					--   angle, distance: Relative heading and distance from the origin.
3288					setCirclePos(left_blackhole_outer_band[array_index][1], left_bh_x_coord, left_bh_y_coord, left_blackhole_outer_band[array_index][2], left_bh_outer_band_radius)
3289					array_index = array_index + 1
3290				end
3291			-- third clump
3292				begin_spread_angle = 225 - (left_bh_outer_band_clump_spread/2)
3293				spread_angle_end = 225 + (left_bh_outer_band_clump_spread/2)
3294				for i=1,left_bh_inner_band_clump_density do
3295					left_blackhole_outer_band[array_index] = {}
3296					left_blackhole_outer_band[array_index][1] = Nebula()
3297					table.insert(terrain_objects,left_blackhole_outer_band[array_index][1])
3298					left_blackhole_outer_band[array_index][2] = math.random(begin_spread_angle, spread_angle_end)
3299					-- setCirclePos(obj, x, y, angle, distance)
3300					--   obj: An object.
3301					--   x, y: Origin coordinates.
3302					--   angle, distance: Relative heading and distance from the origin.
3303					setCirclePos(left_blackhole_outer_band[array_index][1], left_bh_x_coord, left_bh_y_coord, left_blackhole_outer_band[array_index][2], left_bh_outer_band_radius)
3304					array_index = array_index + 1
3305				end
3306			-- fourth clump
3307				begin_spread_angle = 315 - (left_bh_outer_band_clump_spread/2)
3308				spread_angle_end = 315 + (left_bh_outer_band_clump_spread/2)
3309				for i=1,left_bh_outer_band_clump_density do
3310					left_blackhole_outer_band[array_index] = {}
3311					left_blackhole_outer_band[array_index][1] = Nebula()
3312					table.insert(terrain_objects,left_blackhole_outer_band[array_index][1])
3313					left_blackhole_outer_band[array_index][2] = math.random(begin_spread_angle, spread_angle_end)
3314					-- setCirclePos(obj, x, y, angle, distance)
3315					--   obj: An object.
3316					--   x, y: Origin coordinates.
3317					--   angle, distance: Relative heading and distance from the origin.
3318					setCirclePos(left_blackhole_outer_band[array_index][1], left_bh_x_coord, left_bh_y_coord, left_blackhole_outer_band[array_index][2], left_bh_outer_band_radius)
3319					array_index = array_index + 1
3320				end
3321
3322	-- second build the right side (essentially a duplicate of the left side set up diametrically opposed position)
3323	-- note that if you change an establishing variable in the left side, you'll need to make the same change for the right side if you want to keep them balanced
3324		right_bh_x_coord = 100000
3325		right_bh_y_coord = -60000
3326		right_blackhole = BlackHole():setPosition(right_bh_x_coord, right_bh_y_coord)
3327		table.insert(terrain_objects,right_blackhole)
3328
3329		-- there will be 3 bands of orbiting stuff:  inner nebula moving quickest, middle asteroids with maybe a planet moving slower, outer nebula moving slowest
3330		-- the inner band will be clumps of nebula orbiting clockwise (orbit rate is set by variable, but initially 1 orbit in 2min)
3331			right_blackhole_inner_band = {}
3332			-- each band will be a nested table (multi-dimensional array)
3333			  -- 1st position on the inner array will be the nebula object
3334			  -- 2nd position on the inner array will be the current angle of the nebula in relation to the blackhole center
3335			  -- there is no need to keep track of the speed in this case as it is uniform for all nebula in this band
3336			right_bh_inner_band_radius = 40000
3337			right_bh_inner_band_orbit_speed = 360/(60 * 120) -- this equates to the number of degrees traversed for each update call if one complete orbit takes 120 seconds; uniform for all nebula
3338			-- because in this design we want the nebula more "clumpy" with gaps inbetween the clumps, there will be 4 clumps of nebula, one starting in each quadrant, centered on the 45
3339			-- degree angle of that quadrant, spanning a variable degree of arc; make the number of nebula in each clump a variable so we can easily modify how thick each clump will be
3340			right_bh_inner_band_clump_density = 8  -- the number of nebula in a clump
3341			right_bh_inner_band_clump_spread = 40  -- the number of degrees of arc for the clump spread of the quandrant bisecting angle
3342			local array_index = 1
3343			-- first clump
3344				begin_spread_angle = 45 - (right_bh_inner_band_clump_spread/2)
3345				spread_angle_end = 45 + (right_bh_inner_band_clump_spread/2)
3346				for i=1,right_bh_inner_band_clump_density do
3347					right_blackhole_inner_band[array_index] = {}
3348					right_blackhole_inner_band[array_index][1] = Nebula()
3349					table.insert(terrain_objects,right_blackhole_inner_band[array_index][1])
3350					right_blackhole_inner_band[array_index][2] = math.random(begin_spread_angle, spread_angle_end)
3351					-- setCirclePos(obj, x, y, angle, distance)
3352					--   obj: An object.
3353					--   x, y: Origin coordinates.
3354					--   angle, distance: Relative heading and distance from the origin.
3355					setCirclePos(right_blackhole_inner_band[array_index][1], right_bh_x_coord, right_bh_y_coord, right_blackhole_inner_band[array_index][2], right_bh_inner_band_radius)
3356					array_index = array_index + 1
3357				end
3358			-- second clump
3359				begin_spread_angle = 135 - (right_bh_inner_band_clump_spread/2)
3360				spread_angle_end = 135 + (right_bh_inner_band_clump_spread/2)
3361				for i=1,right_bh_inner_band_clump_density do
3362					right_blackhole_inner_band[array_index] = {}
3363					right_blackhole_inner_band[array_index][1] = Nebula()
3364					table.insert(terrain_objects,right_blackhole_inner_band[array_index][1])
3365					right_blackhole_inner_band[array_index][2] = math.random(begin_spread_angle, spread_angle_end)
3366					-- setCirclePos(obj, x, y, angle, distance)
3367					--   obj: An object.
3368					--   x, y: Origin coordinates.
3369					--   angle, distance: Relative heading and distance from the origin.
3370					setCirclePos(right_blackhole_inner_band[array_index][1], right_bh_x_coord, right_bh_y_coord, right_blackhole_inner_band[array_index][2], right_bh_inner_band_radius)
3371					array_index = array_index + 1
3372				end
3373			-- third clump
3374				begin_spread_angle = 225 - (right_bh_inner_band_clump_spread/2)
3375				spread_angle_end = 225 + (right_bh_inner_band_clump_spread/2)
3376				for i=1,right_bh_inner_band_clump_density do
3377					right_blackhole_inner_band[array_index] = {}
3378					right_blackhole_inner_band[array_index][1] = Nebula()
3379					table.insert(terrain_objects,right_blackhole_inner_band[array_index][1])
3380					right_blackhole_inner_band[array_index][2] = math.random(begin_spread_angle, spread_angle_end)
3381					-- setCirclePos(obj, x, y, angle, distance)
3382					--   obj: An object.
3383					--   x, y: Origin coordinates.
3384					--   angle, distance: Relative heading and distance from the origin.
3385					setCirclePos(right_blackhole_inner_band[array_index][1], right_bh_x_coord, right_bh_y_coord, right_blackhole_inner_band[array_index][2], right_bh_inner_band_radius)
3386					array_index = array_index + 1
3387				end
3388			-- fourth clump
3389				begin_spread_angle = 315 - (right_bh_inner_band_clump_spread/2)
3390				spread_angle_end = 315 + (right_bh_inner_band_clump_spread/2)
3391				for i=1,right_bh_inner_band_clump_density do
3392					right_blackhole_inner_band[array_index] = {}
3393					right_blackhole_inner_band[array_index][1] = Nebula()
3394					table.insert(terrain_objects,right_blackhole_inner_band[array_index][1])
3395					right_blackhole_inner_band[array_index][2] = math.random(begin_spread_angle, spread_angle_end)
3396					-- setCirclePos(obj, x, y, angle, distance)
3397					--   obj: An object.
3398					--   x, y: Origin coordinates.
3399					--   angle, distance: Relative heading and distance from the origin.
3400					setCirclePos(right_blackhole_inner_band[array_index][1], right_bh_x_coord, right_bh_y_coord, right_blackhole_inner_band[array_index][2], right_bh_inner_band_radius)
3401					array_index = array_index + 1
3402				end
3403
3404		-- the middle band will be a random number of asteroids orbiting counter-clockwise at a randomly determined rate
3405			right_blackhole_middle_band = {}
3406			right_bh_middle_band_min_radius = 55000
3407			right_bh_middle_band_max_radius = 65000
3408
3409			-- the middle band will not have clumps like the first and will just have a random placement of asteroids within the allowable band range, all with randomly set speeds
3410			right_bh_mimdle_band_number_of_asteroids = 100
3411			right_bh_middle_band_min_orbit_speed = 360/(60 * 240) -- this equates to the number of degrees traversed for each update call if one complete orbit takes 240 seconds
3412			right_bh_middle_band_max_orbit_speed = 360/(60 * 150) -- this equates to the number of degrees traversed for each update call if one complete orbit takes 150 seconds
3413
3414			for i=1,right_bh_mimdle_band_number_of_asteroids do
3415				-- each band will be a nested table (multi-dimensional array)
3416				  -- 1st position on the inner array will be the asteroid object
3417				  -- 2nd position on the inner array will be the radius distance from the blackhole center, randomly generated in a band range
3418				  -- 3rd position on the inner array will be the current angle of the asteroid in relation to the blackhole center
3419				  -- 4th position on the inner array will be the orbital speed of the asteroid, expressed as a delta of angle change per update cycle, randomly generated
3420				right_blackhole_middle_band[i]= {}
3421				right_blackhole_middle_band[i][1] = Asteroid()
3422				table.insert(terrain_objects,right_blackhole_middle_band[i][1])
3423				right_blackhole_middle_band[i][2] = math.random(right_bh_middle_band_min_radius, right_bh_middle_band_max_radius)
3424				right_blackhole_middle_band[i][3] = math.random(1, 360)
3425				right_blackhole_middle_band[i][4] = random(right_bh_middle_band_min_orbit_speed, right_bh_middle_band_max_orbit_speed)
3426				-- setCirclePos(obj, x, y, angle, distance)
3427				  --   obj: An object.
3428				  --   x, y: Origin coordinates.
3429				  --   angle, distance: Relative heading and distance from the origin.
3430				setCirclePos(right_blackhole_middle_band[i][1], right_bh_x_coord, right_bh_y_coord, right_blackhole_middle_band[i][3], right_blackhole_middle_band[i][2])
3431			end
3432
3433		-- the outer band will be clumps of nebula orbiting clockwise (orbit rate is set by variable, but initially 1 orbit in 8min)
3434			right_blackhole_outer_band = {}
3435			-- each band will be a nested table (multi-dimensional array)
3436			  -- 1st position on the inner array will be the nebula object
3437			  -- 2nd position on the inner array will be the current angle of the nebula in relation to the blackhole center
3438			  -- there is no need to keep track of the speed in this case as it is uniform for all nebula in this band
3439			right_bh_outer_band_radius = 80000
3440			right_bh_outer_band_orbit_speed = 360/(60 * 360) -- this equates to the number of degrees traversed for each update call if one complete orbit takes 360 seconds; uniform for all nebula
3441			-- because in this design we want the nebula more "clumpy" with gaps inbetween the clumps, there will be 4 clumps of nebula, one starting in each quadrant, centered on the 45
3442			-- degree angle of that quadrant, spanning a variable degree of arc; make the number of nebula in each clump a variable so we can easily modify how thick each clump will be
3443			right_bh_outer_band_clump_density = 10  -- the number of nebula in a clump
3444			right_bh_outer_band_clump_spread = 60  -- the number of degrees of arc for the clump spread of the quandrant bisecting angle
3445			local array_index = 1
3446			-- first clump
3447				begin_spread_angle = 45 - (right_bh_outer_band_clump_spread/2)
3448				spread_angle_end = 45 + (right_bh_outer_band_clump_spread/2)
3449				for i=1,right_bh_outer_band_clump_density do
3450					right_blackhole_outer_band[array_index] = {}
3451					right_blackhole_outer_band[array_index][1] = Nebula()
3452					table.insert(terrain_objects,right_blackhole_outer_band[array_index][1])
3453					right_blackhole_outer_band[array_index][2] = math.random(begin_spread_angle, spread_angle_end)
3454					-- setCirclePos(obj, x, y, angle, distance)
3455					--   obj: An object.
3456					--   x, y: Origin coordinates.
3457					--   angle, distance: Relative heading and distance from the origin.
3458					setCirclePos(right_blackhole_outer_band[array_index][1], right_bh_x_coord, right_bh_y_coord, right_blackhole_outer_band[array_index][2], right_bh_outer_band_radius)
3459					array_index = array_index + 1
3460				end
3461			-- second clump
3462				begin_spread_angle = 135 - (right_bh_outer_band_clump_spread/2)
3463				spread_angle_end = 135 + (right_bh_outer_band_clump_spread/2)
3464				for i=1,right_bh_outer_band_clump_density do
3465					right_blackhole_outer_band[array_index] = {}
3466					right_blackhole_outer_band[array_index][1] = Nebula()
3467					table.insert(terrain_objects,right_blackhole_outer_band[array_index][1])
3468					right_blackhole_outer_band[array_index][2] = math.random(begin_spread_angle, spread_angle_end)
3469					-- setCirclePos(obj, x, y, angle, distance)
3470					--   obj: An object.
3471					--   x, y: Origin coordinates.
3472					--   angle, distance: Relative heading and distance from the origin.
3473					setCirclePos(right_blackhole_outer_band[array_index][1], right_bh_x_coord, right_bh_y_coord, right_blackhole_outer_band[array_index][2], right_bh_outer_band_radius)
3474					array_index = array_index + 1
3475				end
3476			-- third clump
3477				begin_spread_angle = 225 - (right_bh_outer_band_clump_spread/2)
3478				spread_angle_end = 225 + (right_bh_outer_band_clump_spread/2)
3479				for i=1,right_bh_inner_band_clump_density do
3480					right_blackhole_outer_band[array_index] = {}
3481					right_blackhole_outer_band[array_index][1] = Nebula()
3482					table.insert(terrain_objects,right_blackhole_outer_band[array_index][1])
3483					right_blackhole_outer_band[array_index][2] = math.random(begin_spread_angle, spread_angle_end)
3484					-- setCirclePos(obj, x, y, angle, distance)
3485					--   obj: An object.
3486					--   x, y: Origin coordinates.
3487					--   angle, distance: Relative heading and distance from the origin.
3488					setCirclePos(right_blackhole_outer_band[array_index][1], right_bh_x_coord, right_bh_y_coord, right_blackhole_outer_band[array_index][2], right_bh_outer_band_radius)
3489					array_index = array_index + 1
3490				end
3491			-- fourth clump
3492				begin_spread_angle = 315 - (right_bh_outer_band_clump_spread/2)
3493				spread_angle_end = 315 + (right_bh_outer_band_clump_spread/2)
3494				for i=1,right_bh_outer_band_clump_density do
3495					right_blackhole_outer_band[array_index] = {}
3496					right_blackhole_outer_band[array_index][1] = Nebula()
3497					table.insert(terrain_objects,right_blackhole_outer_band[array_index][1])
3498					right_blackhole_outer_band[array_index][2] = math.random(begin_spread_angle, spread_angle_end)
3499					-- setCirclePos(obj, x, y, angle, distance)
3500					--   obj: An object.
3501					--   x, y: Origin coordinates.
3502					--   angle, distance: Relative heading and distance from the origin.
3503					setCirclePos(right_blackhole_outer_band[array_index][1], right_bh_x_coord, right_bh_y_coord, right_blackhole_outer_band[array_index][2], right_bh_outer_band_radius)
3504					array_index = array_index + 1
3505				end
3506
3507	-- if desired, the blackholes can orbit the entire playing area by using the center as the origin
3508	-- note that in order to do this, the blackholes need to be equidistant from the origin along the x axis;
3509	-- this routine will auto set the right blackhole x value to be opposite of the left blackhole x value
3510	-- take care that the black holes are not going to sweep through the initial boundary area, thereby sucking up stations or flags!
3511
3512		-- set the radius
3513		orbital_radius = left_bh_x_coord * -1
3514		-- set the initial angles of the blackholes relative to the origin
3515		left_bh_angle_to_origin = 180
3516		right_bh_angle_to_origin = 0
3517		-- set the blackhole orbital velocity to complete 1 full orbit in ...
3518		-- orbital_velocity = 0.003  -- the complete game time of 30 mins ?
3519		-- orbital_velocity = 0.006  -- 15 mins ?
3520		-- orbital_velocity = 0.009  -- 10 mins ?
3521		-- orbital_velocity = 0.03  -- 3 mins ?
3522		orbital_velocity = 0.3  -- 3 mins ?
3523
3524	orbital_movement = false
3525	blackhole_movement = false
3526
3527	addGMFunction("Orbit Toggle",
3528		function()
3529			if orbital_movement then
3530				orbital_movement = false
3531			else
3532				orbital_movement = true
3533			end
3534		end
3535	)
3536
3537	addGMFunction("Move Toggle",
3538		function()
3539			if blackhole_movement then
3540				blackhole_movement = false
3541			else
3542				blackhole_movement = true
3543			end
3544		end
3545	)
3546
3547end	--justPassingBy
3548function moveJustPassingBy(delta)
3549
3550	-- if desired, the blackholes can orbit the entire playing area by using the center as the origin
3551	-- use this section if you want to do this, comment out if you don't
3552	-- note that once underway, 'left' and 'right' refer to the original configurations as their positions will change (duh....)
3553		--[[
3554		-- update the angular positions around the origin and adjust for 360
3555		left_bh_angle_to_origin = left_bh_angle_to_origin + orbital_velocity
3556		if left_bh_angle_to_origin > 360 then
3557			left_bh_angle_to_origin = left_bh_angle_to_origin - 360
3558		end
3559		right_bh_angle_to_origin = right_bh_angle_to_origin + orbital_velocity
3560		if right_bh_angle_to_origin > 360 then
3561			right_bh_angle_to_origin = right_bh_angle_to_origin - 360
3562		end
3563
3564		-- set the new blackhole positions before updating all their orbiting bodies
3565		-- setCirclePos(obj, x, y, angle, distance)
3566			--   obj: An object.
3567			--   x, y: Origin coordinates.
3568			--   angle, distance: Relative heading and distance from the origin.
3569		setCirclePos(left_blackhole, 0, 0, left_bh_angle_to_origin, orbital_radius)
3570		setCirclePos(right_blackhole, 0, 0, right_bh_angle_to_origin, orbital_radius)
3571		--]]
3572
3573	-- first do the left side
3574		left_bh_center_x, left_bh_center_y = left_blackhole:getPosition()
3575		-- if desired, move the left blackhole linearly to the right little by little....
3576		-- a rate of x = +/- 5 seems to move the bh 20U in 1.5 min, a rate of +/- 2.5 will move the entire 200U distance in about 30 min (i.e., full game time)
3577		if blackhole_movement then
3578			left_blackhole:setPosition(left_bh_center_x + 2.5, left_bh_center_y)
3579		end
3580
3581		if orbital_movement then
3582			for i,nebula_table in ipairs(left_blackhole_inner_band) do
3583				--increment the angle according to the predetermined velocity (change in arc per cycle)
3584				nebula_table[2] = nebula_table[2] + left_bh_inner_band_orbit_speed
3585				if nebula_table[2] > 360 then
3586					nebula_table[2] = nebula_table[2] - 360
3587				end
3588				setCirclePos(nebula_table[1], left_bh_center_x, left_bh_center_y, nebula_table[2], left_bh_inner_band_radius)
3589			end
3590
3591			for i,asteroid_table in ipairs(left_blackhole_middle_band) do
3592				-- DEcrement the angle (go counter-clockwise) according to the previously randomized velocity in the table (change in arc per cycle)
3593				asteroid_table[3] = asteroid_table[3] - asteroid_table[4]
3594				if asteroid_table[3] < 0 then
3595					asteroid_table[3] = asteroid_table[3] + 360
3596				end
3597				setCirclePos(left_blackhole_middle_band[i][1], left_bh_center_x, left_bh_center_y, left_blackhole_middle_band[i][3], left_blackhole_middle_band[i][2])
3598			end
3599
3600			for i,nebula_table in ipairs(left_blackhole_outer_band) do
3601				--increment the angle according to the predetermined velocity (change in arc per cycle)
3602				nebula_table[2] = nebula_table[2] + left_bh_outer_band_orbit_speed
3603				if nebula_table[2] > 360 then
3604					nebula_table[2] = nebula_table[2] - 360
3605				end
3606				setCirclePos(nebula_table[1], left_bh_center_x, left_bh_center_y, nebula_table[2], left_bh_outer_band_radius)
3607			end
3608		end
3609
3610	-- second do the right side
3611		right_bh_center_x, right_bh_center_y = right_blackhole:getPosition()
3612		-- if desired, move the right blackhole to the right little by little....
3613		-- a rate of x = +/- 5 seems to move the bh 20U in 1.5 min, a rate of +/- 2.5 will move the entire 200U distance in about 30 min (i.e., full game time)
3614		if blackhole_movement then
3615			right_blackhole:setPosition(right_bh_center_x - 2.5, right_bh_center_y)
3616		end
3617
3618		if orbital_movement then
3619			for i,nebula_table in ipairs(right_blackhole_inner_band) do
3620				--increment the angle according to the predetermined velocity (change in arc per cycle)
3621				nebula_table[2] = nebula_table[2] + right_bh_inner_band_orbit_speed
3622				if nebula_table[2] > 360 then
3623					nebula_table[2] = nebula_table[2] - 360
3624				end
3625				setCirclePos(nebula_table[1], right_bh_center_x, right_bh_center_y, nebula_table[2], right_bh_inner_band_radius)
3626			end
3627
3628			for i,asteroid_table in ipairs(right_blackhole_middle_band) do
3629				-- DEcrement the angle (go counter-clockwise) according to the previously randomized velocity in the table (change in arc per cycle)
3630				asteroid_table[3] = asteroid_table[3] - asteroid_table[4]
3631				if asteroid_table[3] < 0 then
3632					asteroid_table[3] = asteroid_table[3] + 360
3633				end
3634				setCirclePos(right_blackhole_middle_band[i][1], right_bh_center_x, right_bh_center_y, right_blackhole_middle_band[i][3], right_blackhole_middle_band[i][2])
3635			end
3636
3637			for i,nebula_table in ipairs(right_blackhole_outer_band) do
3638				--increment the angle according to the predetermined velocity (change in arc per cycle)
3639				nebula_table[2] = nebula_table[2] + right_bh_outer_band_orbit_speed
3640				if nebula_table[2] > 360 then
3641					nebula_table[2] = nebula_table[2] - 360
3642				end
3643				setCirclePos(nebula_table[1], right_bh_center_x, right_bh_center_y, nebula_table[2], right_bh_outer_band_radius)
3644			end
3645		end
3646
3647end	--moveJustPassingBy
3648--	Down The Rabbit Hole Terrain  --
3649function downTheRabbitHole()
3650	-- This terrain is a collection of interconnected worm holes that connect the interiors of the opposing sides; in effect, it creates a "multi-front" because now the opposing team can come from the
3651	-- rear as well as the front; this will no doubt cause a great deal of consternation... ha
3652
3653	-- player tagged relocation override is located at the end of this function; it's at the end because the values depend on "terrain" variables calculated in the middle of the function
3654
3655	dynamicTerrain = moveDownTheRabbitHole
3656	show_nebula = true
3657
3658	-- WORM HOLES
3659		worm_hole_list = {}
3660		local worm_hole_coordinates = {
3661		--	human side
3662			{x = -180057	,y =	462		,target_x =	175945	,target_y =	-56		},
3663			{x = -129765	,y =	49780	,target_x =	126325	,target_y =	-47942	},
3664			{x = -50428		,y =	29117	,target_x =	46238	,target_y =	-28454	},
3665			{x = -51402		,y =	-29753	,target_x =	45106	,target_y =	26256	},
3666			{x = -130545	,y =	-50220	,target_x =	124937	,target_y =	46904	},
3667		--	kraylor side
3668			{x = 48792		,y =	28337	,target_x =	-48201	,target_y =	-27799	},
3669			{x = 48403		,y =	-30337	,target_x =	-47101	,target_y =	26969	},
3670			{x = 130665		,y =	-49904	,target_x =	-125248	,target_y =	47945	},
3671			{x = 128938		,y =	48560	,target_x =	-126058	,target_y =	-48404	},
3672			{x = 179994		,y =	0		,target_x =	-176025	,target_y =	-172	},
3673		}
3674		for i=1,#worm_hole_coordinates do
3675			local worm = WormHole():setPosition(worm_hole_coordinates[i].x,worm_hole_coordinates[i].y)
3676			worm.final_target_x = worm_hole_coordinates[i].target_x
3677			worm.final_target_y = worm_hole_coordinates[i].target_y
3678			local vx, vy = vectorFromAngle(random(0,360),3000)
3679			worm:setTargetPosition(worm_hole_coordinates[i].x + vx,worm_hole_coordinates[i].y + vy)
3680			worm:onTeleportation(function(self,teleportee)
3681				local teleportee_type = teleportee.typeName
3682				if gameTimeLimit < (maxGameTime - hideFlagTime - 1) then
3683					if teleportee_type == "PlayerSpaceship" then
3684						if teleportee:hasSystem("warp") then
3685							teleportee:setSystemHealth("warp",teleportee:getSystemHealth("warp")*.9)
3686						end
3687						if teleportee:hasSystem("jumpdrive") then
3688							teleportee:setSystemHealth("jumpdrive",teleportee:getSystemHealth("jumpdrive")*.9)
3689						end
3690					end
3691				else
3692					local wx, wy = self:getPosition()
3693					local vx, vy = vectorFromAngle(random(0,360),3000)
3694					self:setTargetPosition(wx + vx, wy + vy)
3695					if teleportee_type == "PlayerSpaceship" then
3696						if teleportee:hasPlayerAtPosition("Helms") then
3697							teleportee.worm_hole_target_message = "worm_hole_target_message"
3698							teleportee:addCustomMessage("Helms",teleportee.worm_hole_target_message,"Worm hole teleportation destination will change after the flag hiding time expires")
3699						end
3700						if teleportee:hasPlayerAtPosition("Tactical") then
3701							teleportee.worm_hole_target_message_tac = "worm_hole_target_message_tac"
3702							teleportee:addCustomMessage("Tactical",teleportee.worm_hole_target_message_tac,"Worm hole teleportation destination will change after the flag hiding time expires")
3703						end
3704					end
3705				end
3706			end)
3707			table.insert(worm_hole_list,worm)
3708			table.insert(terrain_objects,worm)
3709		end
3710
3711	-- PLANETS/RING OF ASTEROIDS WITH MINES
3712		-- applies to both sides
3713			main_planet_center_x_distance = 100000
3714			main_planet_center_y_distance = 0
3715			main_planet_radius = 10000
3716
3717			number_of_asteroids_in_ring = 100
3718			asteroid_min_orbit_speed = 360/(60 * 240) -- this equates to the number of degrees traversed for each update call if one complete orbit takes 240 seconds
3719			asteroid_max_orbit_speed = 360/(60 * 150) -- this equates to the number of degrees traversed for each update call if one complete orbit takes 150 seconds
3720
3721			number_of_mines_in_ring = 20
3722			mine_min_orbit_speed = 360/(60 * 240) -- this equates to the number of degrees traversed for each update call if one complete orbit takes 240 seconds
3723			mine_max_orbit_speed = 360/(60 * 150) -- this equates to the number of degrees traversed for each update call if one complete orbit takes 150 seconds
3724
3725		-- human side
3726			human_planet_center_x = -1 * main_planet_center_x_distance
3727			human_planet_center_y = main_planet_center_y_distance
3728			human_planet_radius = main_planet_radius
3729			human_planet_gas_giant = Planet()
3730				:setPosition(human_planet_center_x,human_planet_center_y)
3731				:setPlanetRadius(human_planet_radius)
3732				:setDistanceFromMovementPlane(0)
3733				:setPlanetSurfaceTexture("planets/gas-1.png")
3734				:setPlanetAtmosphereColor(0,0.8,0.2)
3735				:setAxialRotationTime(120)
3736			table.insert(terrain_objects,human_planet_gas_giant)
3737
3738			human_moon_1_radius = 1000
3739			human_moon_1_orbit_distance = 5000
3740			human_moon_1_orbit_time = 300  -- measured in near-real-time seconds I believe
3741			human_moon_1_center_x = human_planet_center_x
3742			human_moon_1_center_y = human_planet_center_y + human_planet_radius + human_moon_1_orbit_distance + human_moon_1_radius
3743			human_moon_1 = Planet()
3744				:setPosition(human_moon_1_center_x,human_moon_1_center_y)
3745				:setPlanetRadius(human_moon_1_radius)
3746				:setDistanceFromMovementPlane(0)
3747				:setPlanetSurfaceTexture("planets/moon-1.png")
3748				:setPlanetAtmosphereColor(0.2,0.2,0.2)
3749				:setAxialRotationTime(120)
3750				:setOrbit(human_planet_gas_giant, human_moon_1_orbit_time)
3751			table.insert(terrain_objects,human_moon_1)
3752
3753			human_moon_2_radius = 2500
3754			human_moon_2_orbit_distance = human_moon_1_orbit_distance + 12500
3755			human_moon_2_orbit_time = 900  -- measured in near-real-time seconds I believe
3756			human_moon_2_center_x = human_planet_center_x
3757			human_moon_2_center_y = human_planet_center_y + human_planet_radius + human_moon_2_orbit_distance + human_moon_2_radius
3758			human_moon_2 = Planet()
3759				:setPosition(human_moon_2_center_x,human_moon_2_center_y)
3760				:setPlanetRadius(human_moon_2_radius)
3761				:setDistanceFromMovementPlane(0)
3762				:setPlanetSurfaceTexture("planets/planet-1.png")
3763				:setPlanetCloudTexture("planets/clouds-1.png")
3764				:setPlanetAtmosphereTexture("planets/atmosphere.png")
3765				:setPlanetAtmosphereColor(0.2,0.2,1.0)
3766				:setAxialRotationTime(120)
3767				:setOrbit(human_planet_gas_giant, human_moon_2_orbit_time)
3768			table.insert(terrain_objects,human_moon_2)
3769
3770			human_asteroid_ring_min_radius = human_moon_1_center_y + human_moon_1_radius + 1000
3771			human_asteroid_ring_max_radius = human_moon_2_center_y - human_moon_2_radius - 1000
3772			human_asteroid_ring = {}
3773
3774			for i=1,number_of_asteroids_in_ring do
3775				human_asteroid_ring[i] = Asteroid()
3776				human_asteroid_ring[i].angle = math.random(1, 360)  -- the current angle of the asteroid in relation to the planet center
3777				human_asteroid_ring[i].radius = math.random(human_asteroid_ring_min_radius, human_asteroid_ring_max_radius) -- the radius distance of the asteroid from the planet center, randomly generated in a band range
3778				human_asteroid_ring[i].speed = random(asteroid_min_orbit_speed, asteroid_max_orbit_speed) -- the orbital speed of the asteroid, expressed as a delta of angle change per update cycle, randomly generated
3779				setCirclePos(human_asteroid_ring[i],
3780					human_planet_center_x,
3781					human_planet_center_y,
3782					human_asteroid_ring[i].angle,
3783					human_asteroid_ring[i].radius)
3784				table.insert(terrain_objects,human_asteroid_ring[i])
3785			end
3786
3787			human_mine_ring = {}  -- these are actually interspersed in the ring of asteroids, but they have their own table for update purposes
3788
3789			for i=1,number_of_mines_in_ring do
3790				human_mine_ring[i] = Mine()
3791				human_mine_ring[i].angle = math.random(1, 360)  -- the current angle of the mine in relation to the planet center
3792				human_mine_ring[i].radius = math.random(human_asteroid_ring_min_radius, human_asteroid_ring_max_radius) -- the radius distance of the mine from the planet center, randomly generated in a band range
3793				human_mine_ring[i].speed = random(mine_min_orbit_speed, mine_max_orbit_speed) -- the orbital speed of the asteroid, expressed as a delta of angle change per update cycle, randomly generated
3794				setCirclePos(human_mine_ring[i],
3795					human_planet_center_x,
3796					human_planet_center_y,
3797					human_mine_ring[i].angle,
3798					human_mine_ring[i].radius)
3799				table.insert(terrain_objects,human_mine_ring[i])
3800			end
3801
3802		-- kraylor side
3803			kraylor_planet_center_x = main_planet_center_x_distance
3804			kraylor_planet_center_y = main_planet_center_y_distance
3805			kraylor_planet_radius = main_planet_radius
3806			kraylor_planet_molten_giant = Planet()
3807				:setPosition(kraylor_planet_center_x,kraylor_planet_center_y)
3808				:setPlanetRadius(kraylor_planet_radius)
3809				:setDistanceFromMovementPlane(0)
3810				:setPlanetSurfaceTexture("planets/planet-2.png")
3811				:setPlanetAtmosphereColor(0.8,0,0)
3812				:setAxialRotationTime(120)
3813			table.insert(terrain_objects,kraylor_planet_molten_giant)
3814
3815			kraylor_moon_1_radius = 1000
3816			kraylor_moon_1_orbit_distance = 5000
3817			kraylor_moon_1_orbit_time = 300  -- measured in near-real-time seconds I believe
3818			kraylor_moon_1_center_x = kraylor_planet_center_x
3819			kraylor_moon_1_center_y = kraylor_planet_center_y + kraylor_planet_radius + kraylor_moon_1_orbit_distance + kraylor_moon_1_radius
3820			kraylor_moon_1 = Planet()
3821				:setPosition(kraylor_moon_1_center_x,kraylor_moon_1_center_y)
3822				:setPlanetRadius(kraylor_moon_1_radius)
3823				:setDistanceFromMovementPlane(0)
3824				:setPlanetSurfaceTexture("planets/moon-1.png")
3825				:setPlanetAtmosphereColor(0.2,0.2,0.2)
3826				:setAxialRotationTime(120)
3827				:setOrbit(kraylor_planet_molten_giant, kraylor_moon_1_orbit_time)
3828			table.insert(terrain_objects,kraylor_moon_1)
3829
3830			kraylor_moon_2_radius = 2500
3831			kraylor_moon_2_orbit_distance = kraylor_moon_1_orbit_distance + 12500
3832			kraylor_moon_2_orbit_time = 900  -- measured in near-real-time seconds I believe
3833			kraylor_moon_2_center_x = kraylor_planet_center_x
3834			kraylor_moon_2_center_y = kraylor_planet_center_y + kraylor_planet_radius + kraylor_moon_2_orbit_distance + kraylor_moon_2_radius
3835			kraylor_moon_2 = Planet()
3836				:setPosition(kraylor_moon_2_center_x,kraylor_moon_2_center_y)
3837				:setPlanetRadius(kraylor_moon_2_radius)
3838				:setDistanceFromMovementPlane(0)
3839				:setPlanetSurfaceTexture("planets/planet-1.png")
3840				:setPlanetCloudTexture("planets/clouds-1.png")
3841				:setPlanetAtmosphereTexture("planets/atmosphere.png")
3842				:setPlanetAtmosphereColor(0.2,0.2,1.0)
3843				:setAxialRotationTime(120)
3844				:setOrbit(kraylor_planet_molten_giant, kraylor_moon_2_orbit_time)
3845			table.insert(terrain_objects,kraylor_moon_2)
3846
3847			kraylor_asteroid_ring_min_radius = kraylor_moon_1_center_y + kraylor_moon_1_radius + 1000
3848			kraylor_asteroid_ring_max_radius = kraylor_moon_2_center_y - kraylor_moon_2_radius - 1000
3849			kraylor_asteroid_ring = {}
3850
3851			for i=1,number_of_asteroids_in_ring do
3852				kraylor_asteroid_ring[i] = Asteroid()
3853				kraylor_asteroid_ring[i].angle = math.random(1, 360)  -- the current angle of the asteroid in relation to the planet center
3854				kraylor_asteroid_ring[i].radius = math.random(kraylor_asteroid_ring_min_radius, kraylor_asteroid_ring_max_radius) -- the radius distance of the asteroid from the planet center, randomly generated in a band range
3855				kraylor_asteroid_ring[i].speed = random(asteroid_min_orbit_speed, asteroid_max_orbit_speed) -- the orbital speed of the asteroid, expressed as a delta of angle change per update cycle, randomly generated
3856				setCirclePos(kraylor_asteroid_ring[i],
3857					kraylor_planet_center_x,
3858					kraylor_planet_center_y,
3859					kraylor_asteroid_ring[i].angle,
3860					kraylor_asteroid_ring[i].radius)
3861				table.insert(terrain_objects,kraylor_asteroid_ring[i])
3862			end
3863
3864			kraylor_mine_ring = {}  -- these are actually interspersed in the ring of asteroids, but they have their own table for update purposes
3865
3866			for i=1,number_of_mines_in_ring do
3867				kraylor_mine_ring[i] = Mine()
3868				kraylor_mine_ring[i].angle = math.random(1, 360)  -- the current angle of the mine in relation to the planet center
3869				kraylor_mine_ring[i].radius = math.random(kraylor_asteroid_ring_min_radius, kraylor_asteroid_ring_max_radius) -- the radius distance of the mine from the planet center, randomly generated in a band range
3870				kraylor_mine_ring[i].speed = random(mine_min_orbit_speed, mine_max_orbit_speed) -- the orbital speed of the asteroid, expressed as a delta of angle change per update cycle, randomly generated
3871				setCirclePos(kraylor_mine_ring[i],
3872					kraylor_planet_center_x,
3873					kraylor_planet_center_y,
3874					kraylor_mine_ring[i].angle,
3875					kraylor_mine_ring[i].radius)
3876				table.insert(terrain_objects,kraylor_mine_ring[i])
3877			end
3878
3879	-- STATIONS
3880		-- human side
3881			human_orbital_station_1 = SpaceStation()
3882				:setTemplate("Small Station")
3883				:setFaction("Human Navy")
3884				:setCallSign("DS845")
3885			table.insert(terrain_objects,human_orbital_station_1)
3886			human_orbital_station_1.angle = 270
3887			human_orbital_station_1.speed = 360/(60 * (human_moon_1_orbit_time + (human_moon_1_orbit_time * 0.05))) -- this is supposed to equate to the same time it takes for human moon 1 to orbit the planet... maybe...
3888			human_orbital_station_1.distance = human_moon_1_center_y
3889			setCirclePos(human_orbital_station_1,
3890				human_planet_center_x,
3891				human_planet_center_y,
3892				human_orbital_station_1.angle,
3893				human_orbital_station_1.distance)
3894
3895			human_orbital_station_2 = SpaceStation()
3896				:setTemplate("Huge Station")
3897				:setFaction("Human Navy")
3898				:setCallSign("DS10246")
3899			table.insert(terrain_objects,human_orbital_station_2)
3900			human_orbital_station_2.angle = 0
3901			human_orbital_station_2.speed = 360/(60 * 1800) -- this equates to the number of degrees traversed for each update call if one complete orbit takes 1800 seconds
3902			human_orbital_station_2.distance = human_moon_2_center_y + human_moon_2_radius + 10000
3903			setCirclePos(human_orbital_station_2,
3904				human_planet_center_x,
3905				human_planet_center_y,
3906				human_orbital_station_2.angle,
3907				human_orbital_station_2.distance)
3908
3909			human_orbital_station_3 = SpaceStation()
3910				:setTemplate("Medium Station")
3911				:setFaction("Human Navy")
3912				:setCallSign("DS1038")
3913			table.insert(terrain_objects,human_orbital_station_3)
3914			human_orbital_station_3.angle = 180
3915			human_orbital_station_3.speed = 360/(60 * 1800) -- this equates to the number of degrees traversed for each update call if one complete orbit takes 1800 seconds
3916			human_orbital_station_3.distance = human_moon_2_center_y + human_moon_2_radius + 10000
3917			setCirclePos(human_orbital_station_3,
3918				human_planet_center_x,
3919				human_planet_center_y,
3920				human_orbital_station_3.angle,
3921				human_orbital_station_3.distance)
3922
3923			human_orbital_station_4 = SpaceStation()
3924				:setTemplate("Medium Station")
3925				:setFaction("Independent")
3926				:setCallSign("DS2639")
3927			table.insert(terrain_objects,human_orbital_station_4)
3928			human_orbital_station_4.angle = 90
3929			human_orbital_station_4.speed = 360/(60 * 1800) -- this equates to the number of degrees traversed for each update call if one complete orbit takes 1800 seconds
3930			human_orbital_station_4.distance = human_moon_2_center_y + human_moon_2_radius + 10000
3931			setCirclePos(human_orbital_station_4,
3932				human_planet_center_x,
3933				human_planet_center_y,
3934				human_orbital_station_4.angle,
3935				human_orbital_station_4.distance)
3936
3937			human_orbital_station_5 = SpaceStation()
3938				:setTemplate("Medium Station")
3939				:setFaction("Independent")
3940				:setCallSign("DS317")
3941			table.insert(terrain_objects,human_orbital_station_5)
3942			human_orbital_station_5.angle = 270
3943			human_orbital_station_5.speed = 360/(60 * 1800) -- this equates to the number of degrees traversed for each update call if one complete orbit takes 1800 seconds
3944			human_orbital_station_5.distance = human_moon_2_center_y + human_moon_2_radius + 10000
3945			setCirclePos(human_orbital_station_5,
3946				human_planet_center_x,
3947				human_planet_center_y,
3948				human_orbital_station_5.angle,
3949				human_orbital_station_5.distance)
3950
3951			-- non-moving stations by the forward and middle wormholes
3952				table.insert(terrain_objects,SpaceStation():setTemplate("Medium Station"):setFaction("Human Navy"):setCallSign("DS877"):setPosition(-135096, -50568))
3953				table.insert(terrain_objects,SpaceStation():setTemplate("Medium Station"):setFaction("Human Navy"):setCallSign("DS875"):setPosition(-54873, -33476))
3954				table.insert(terrain_objects,SpaceStation():setTemplate("Medium Station"):setFaction("Human Navy"):setCallSign("DS876"):setPosition(-54445, 32967))
3955				table.insert(terrain_objects,SpaceStation():setTemplate("Medium Station"):setFaction("Human Navy"):setCallSign("DS878"):setPosition(-134989, 49845))
3956			-- non-moving station; forward center
3957				table.insert(terrain_objects,SpaceStation():setTemplate("Medium Station"):setFaction("Human Navy"):setCallSign("DS879"):setPosition(-32800, 101))
3958			-- non-moving stations; middle distance to the flanks
3959				table.insert(terrain_objects,SpaceStation():setTemplate("Large Station"):setFaction("Human Navy"):setCallSign("DS890"):setPosition(-73903, -50010))
3960				table.insert(terrain_objects,SpaceStation():setTemplate("Large Station"):setFaction("Human Navy"):setCallSign("DS889"):setPosition(-73250, 49216))
3961			-- non-moving stations; forward near dividing line
3962				table.insert(terrain_objects,SpaceStation():setTemplate("Large Station"):setFaction("Independent"):setCallSign("DS886"):setPosition(-20112, 50261))
3963				table.insert(terrain_objects,SpaceStation():setTemplate("Large Station"):setFaction("Independent"):setCallSign("DS885"):setPosition(-20112, 30024))
3964				table.insert(terrain_objects,SpaceStation():setTemplate("Large Station"):setFaction("Independent"):setCallSign("DS884"):setPosition(-19982, -50010))
3965				table.insert(terrain_objects,SpaceStation():setTemplate("Large Station"):setFaction("Independent"):setCallSign("DS883"):setPosition(-20112, -30034))
3966			-- non-moving stations; to the rear
3967				table.insert(terrain_objects,SpaceStation():setTemplate("Large Station"):setFaction("Independent"):setCallSign("DS888"):setPosition(-167515, 29240))
3968				table.insert(terrain_objects,SpaceStation():setTemplate("Large Station"):setFaction("Independent"):setCallSign("DS887"):setPosition(-167123, -28728))
3969
3970		-- kraylor side
3971			kraylor_orbital_station_1 = SpaceStation()
3972				:setTemplate("Small Station")
3973				:setFaction("Kraylor")
3974				:setCallSign("DS734")
3975			table.insert(terrain_objects,kraylor_orbital_station_1)
3976			kraylor_orbital_station_1.angle = 270
3977			kraylor_orbital_station_1.speed = 360/(60 * (kraylor_moon_1_orbit_time + (kraylor_moon_1_orbit_time * 0.05))) -- this is supposed to equate to the same time it takes for kraylor moon 1 to orbit the planet... maybe...
3978			kraylor_orbital_station_1.distance = kraylor_moon_1_center_y
3979			setCirclePos(kraylor_orbital_station_1,
3980				kraylor_planet_center_x,
3981				kraylor_planet_center_y,
3982				kraylor_orbital_station_1.angle,
3983				kraylor_orbital_station_1.distance)
3984
3985			kraylor_orbital_station_2 = SpaceStation()
3986				:setTemplate("Huge Station")
3987				:setFaction("Kraylor")
3988				:setCallSign("DS9135")
3989			table.insert(terrain_objects,kraylor_orbital_station_2)
3990			kraylor_orbital_station_2.angle = 180
3991			kraylor_orbital_station_2.speed = 360/(60 * 1800) -- this equates to the number of degrees traversed for each update call if one complete orbit takes 1800 seconds
3992			kraylor_orbital_station_2.distance = kraylor_moon_2_center_y + kraylor_moon_2_radius + 10000
3993			setCirclePos(kraylor_orbital_station_2,
3994				kraylor_planet_center_x,
3995				kraylor_planet_center_y,
3996				kraylor_orbital_station_2.angle,
3997				kraylor_orbital_station_2.distance)
3998
3999			kraylor_orbital_station_3 = SpaceStation()
4000				:setTemplate("Medium Station")
4001				:setFaction("Kraylor")
4002				:setCallSign("DS927")
4003			table.insert(terrain_objects,kraylor_orbital_station_3)
4004			kraylor_orbital_station_3.angle = 0
4005			kraylor_orbital_station_3.speed = 360/(60 * 1800) -- this equates to the number of degrees traversed for each update call if one complete orbit takes 1800 seconds
4006			kraylor_orbital_station_3.distance = kraylor_moon_2_center_y + kraylor_moon_2_radius + 10000
4007			setCirclePos(kraylor_orbital_station_3,
4008				kraylor_planet_center_x,
4009				kraylor_planet_center_y,
4010				kraylor_orbital_station_3.angle,
4011				kraylor_orbital_station_3.distance)
4012
4013			kraylor_orbital_station_4 = SpaceStation()
4014				:setTemplate("Medium Station")
4015				:setFaction("Independent")
4016				:setCallSign("DS1528")
4017			table.insert(terrain_objects,kraylor_orbital_station_4)
4018			kraylor_orbital_station_4.angle = 90
4019			kraylor_orbital_station_4.speed = 360/(60 * 1800) -- this equates to the number of degrees traversed for each update call if one complete orbit takes 1800 seconds
4020			kraylor_orbital_station_4.distance = kraylor_moon_2_center_y + kraylor_moon_2_radius + 10000
4021			setCirclePos(kraylor_orbital_station_4,
4022				kraylor_planet_center_x,
4023				kraylor_planet_center_y,
4024				kraylor_orbital_station_4.angle,
4025				kraylor_orbital_station_4.distance)
4026
4027			kraylor_orbital_station_5 = SpaceStation()
4028				:setTemplate("Medium Station")
4029				:setFaction("Independent")
4030				:setCallSign("DS206")
4031			table.insert(terrain_objects,kraylor_orbital_station_5)
4032			kraylor_orbital_station_5.angle = 270
4033			kraylor_orbital_station_5.speed = 360/(60 * 1800) -- this equates to the number of degrees traversed for each update call if one complete orbit takes 1800 seconds
4034			kraylor_orbital_station_5.distance = kraylor_moon_2_center_y + kraylor_moon_2_radius + 10000
4035			setCirclePos(kraylor_orbital_station_5,
4036				kraylor_planet_center_x,
4037				kraylor_planet_center_y,
4038				kraylor_orbital_station_5.angle,
4039				kraylor_orbital_station_5.distance)
4040
4041			-- non-moving stations by the forward and middle wormholes
4042				table.insert(terrain_objects,SpaceStation():setTemplate("Medium Station"):setFaction("Kraylor"):setCallSign("DS766"):setPosition(135096, -50568))
4043				table.insert(terrain_objects,SpaceStation():setTemplate("Medium Station"):setFaction("Kraylor"):setCallSign("DS764"):setPosition(54873, -33476))
4044				table.insert(terrain_objects,SpaceStation():setTemplate("Medium Station"):setFaction("Kraylor"):setCallSign("DS765"):setPosition(54445, 32967))
4045				table.insert(terrain_objects,SpaceStation():setTemplate("Medium Station"):setFaction("Kraylor"):setCallSign("DS767"):setPosition(134989, 49845))
4046			-- non-moving station; forward center
4047				table.insert(terrain_objects,SpaceStation():setTemplate("Medium Station"):setFaction("Kraylor"):setCallSign("DS768"):setPosition(32800, 101))
4048			-- non-moving stations; middle distance to the flanks
4049				table.insert(terrain_objects,SpaceStation():setTemplate("Large Station"):setFaction("Kraylor"):setCallSign("DS789"):setPosition(73903, -50010))
4050				table.insert(terrain_objects,SpaceStation():setTemplate("Large Station"):setFaction("Kraylor"):setCallSign("DS778"):setPosition(73250, 49216))
4051			-- non-moving stations; forward near dividing line
4052				table.insert(terrain_objects,SpaceStation():setTemplate("Large Station"):setFaction("Independent"):setCallSign("DS775"):setPosition(20112, 50261))
4053				table.insert(terrain_objects,SpaceStation():setTemplate("Large Station"):setFaction("Independent"):setCallSign("DS774"):setPosition(20112, 30024))
4054				table.insert(terrain_objects,SpaceStation():setTemplate("Large Station"):setFaction("Independent"):setCallSign("DS773"):setPosition(19982, -50010))
4055				table.insert(terrain_objects,SpaceStation():setTemplate("Large Station"):setFaction("Independent"):setCallSign("DS772"):setPosition(20112, -30034))
4056			-- non-moving stations; to the rear
4057				table.insert(terrain_objects,SpaceStation():setTemplate("Large Station"):setFaction("Independent"):setCallSign("DS777"):setPosition(167515, 29240))
4058				table.insert(terrain_objects,SpaceStation():setTemplate("Large Station"):setFaction("Independent"):setCallSign("DS776"):setPosition(167123, -28728))
4059
4060	-- NEBULA AND MINES IN THE NEBULA
4061		if show_nebula then
4062			-- human side
4063				table.insert(terrain_objects,Nebula():setPosition(-25950, 15065))
4064				table.insert(terrain_objects,Nebula():setPosition(-17927, 3032))
4065				table.insert(terrain_objects,Nebula():setPosition(-18114, -4244))
4066				table.insert(terrain_objects,Nebula():setPosition(-25390, -18424))
4067				table.insert(terrain_objects,Mine():setPosition(-35073, -35990))
4068				table.insert(terrain_objects,Mine():setPosition(-36480, -37598))
4069				table.insert(terrain_objects,Mine():setPosition(-37887, -41417))
4070				table.insert(terrain_objects,Mine():setPosition(-50551, -65738))
4071				table.insert(terrain_objects,Mine():setPosition(-49144, -62723))
4072				table.insert(terrain_objects,Mine():setPosition(-29445, -72573))
4073				table.insert(terrain_objects,Mine():setPosition(-33666, -66944))
4074				table.insert(terrain_objects,Mine():setPosition(-57586, -73176))
4075				table.insert(terrain_objects,Mine():setPosition(-41505, -50864))
4076				table.insert(terrain_objects,Mine():setPosition(-38088, -46040))
4077				table.insert(terrain_objects,Mine():setPosition(-38490, -62321))
4078				table.insert(terrain_objects,Mine():setPosition(-44923, -55688))
4079				table.insert(terrain_objects,Mine():setPosition(-52762, -68753))
4080				table.insert(terrain_objects,Mine():setPosition(-55174, -73779))
4081				table.insert(terrain_objects,Nebula():setPosition(-48679, -59598))
4082				table.insert(terrain_objects,Nebula():setPosition(-52498, -66834))
4083				table.insert(terrain_objects,Nebula():setPosition(-54508, -73668))
4084				table.insert(terrain_objects,Nebula():setPosition(-66970, -78090))
4085				table.insert(terrain_objects,Nebula():setPosition(-71393, -31658))
4086				table.insert(terrain_objects,Nebula():setPosition(-89483, -65427))
4087				table.insert(terrain_objects,Nebula():setPosition(-36418, -65427))
4088				table.insert(terrain_objects,Nebula():setPosition(-39835, -59598))
4089				table.insert(terrain_objects,Nebula():setPosition(-34006, -34472))
4090				table.insert(terrain_objects,Nebula():setPosition(-38830, -42714))
4091				table.insert(terrain_objects,Nebula():setPosition(-73202, -60402))
4092				table.insert(terrain_objects,Nebula():setPosition(-42850, -51357))
4093				table.insert(terrain_objects,Nebula():setPosition(-100538, -82915))
4094				table.insert(terrain_objects,Nebula():setPosition(-83252, -76482))
4095				table.insert(terrain_objects,Mine():setPosition(-104822, -56090))
4096				table.insert(terrain_objects,Nebula():setPosition(-135312, -79900))
4097				table.insert(terrain_objects,Nebula():setPosition(-122448, -76884))
4098				table.insert(terrain_objects,Mine():setPosition(-164659, -17990))
4099				table.insert(terrain_objects,Mine():setPosition(-167875, -15578))
4100				table.insert(terrain_objects,Mine():setPosition(-191393, -15377))
4101				table.insert(terrain_objects,Nebula():setPosition(-193202, -61407))
4102				table.insert(terrain_objects,Mine():setPosition(-160237, -5528))
4103				table.insert(terrain_objects,Mine():setPosition(-162448, -9950))
4104				table.insert(terrain_objects,Mine():setPosition(-102008, -56492))
4105				table.insert(terrain_objects,Nebula():setPosition(-100337, -55377))
4106				table.insert(terrain_objects,Nebula():setPosition(-106367, -56181))
4107				table.insert(terrain_objects,Mine():setPosition(-160036, -41910))
4108				table.insert(terrain_objects,Mine():setPosition(-178327, -20402))
4109				table.insert(terrain_objects,Mine():setPosition(-185764, -26030))
4110				table.insert(terrain_objects,Mine():setPosition(-155011, -27236))
4111				table.insert(terrain_objects,Mine():setPosition(-184558, -40503))
4112				table.insert(terrain_objects,Nebula():setPosition(-115011, -67236))
4113				table.insert(terrain_objects,Mine():setPosition(-159835, 12764))
4114				table.insert(terrain_objects,Mine():setPosition(-155413, 11759))
4115				table.insert(terrain_objects,Mine():setPosition(-156217, 27437))
4116				table.insert(terrain_objects,Nebula():setPosition(-164659, -65628))
4117				table.insert(terrain_objects,Nebula():setPosition(-164659, -52161))
4118				table.insert(terrain_objects,Mine():setPosition(-154609, -12362))
4119				table.insert(terrain_objects,Nebula():setPosition(-184960, -39698))
4120				table.insert(terrain_objects,Nebula():setPosition(-193202, -40302))
4121				table.insert(terrain_objects,Nebula():setPosition(-161242, -41910))
4122				table.insert(terrain_objects,Nebula():setPosition(-184960, -70653))
4123				table.insert(terrain_objects,Mine():setPosition(-150790, 15578))
4124				table.insert(terrain_objects,Mine():setPosition(-174508, 29648))
4125				table.insert(terrain_objects,Mine():setPosition(-167674, 17588))
4126				table.insert(terrain_objects,Nebula():setPosition(-186166, -48744))
4127				table.insert(terrain_objects,Nebula():setPosition(-187975, -55176))
4128				table.insert(terrain_objects,Nebula():setPosition(-170890, -78090))
4129				table.insert(terrain_objects,Nebula():setPosition(-173704, -61005))
4130				table.insert(terrain_objects,Nebula():setPosition(-25161, -79497))
4131				table.insert(terrain_objects,Nebula():setPosition(-31795, -72261))
4132				table.insert(terrain_objects,Mine():setPosition(-42108, 51649))
4133				table.insert(terrain_objects,Mine():setPosition(-42510, 48030))
4134				table.insert(terrain_objects,Nebula():setPosition(-41443, 41106))
4135				table.insert(terrain_objects,Nebula():setPosition(-69583, 30854))
4136				table.insert(terrain_objects,Nebula():setPosition(-73001, 56181))
4137				table.insert(terrain_objects,Mine():setPosition(-36681, 55066))
4138				table.insert(terrain_objects,Nebula():setPosition(-36217, 34070))
4139				table.insert(terrain_objects,Mine():setPosition(-96179, 56272))
4140				table.insert(terrain_objects,Nebula():setPosition(-94508, 57186))
4141				table.insert(terrain_objects,Nebula():setPosition(-98930, 52563))
4142				table.insert(terrain_objects,Mine():setPosition(-34872, 57679))
4143				table.insert(terrain_objects,Nebula():setPosition(-33805, 60402))
4144				table.insert(terrain_objects,Mine():setPosition(-46732, 55669))
4145				table.insert(terrain_objects,Nebula():setPosition(-38227, 53166))
4146				table.insert(terrain_objects,Mine():setPosition(-98993, 53860))
4147				table.insert(terrain_objects,Mine():setPosition(-99998, 56674))
4148				table.insert(terrain_objects,Nebula():setPosition(-100940, 81910))
4149				table.insert(terrain_objects,Nebula():setPosition(-63955, 69447))
4150				table.insert(terrain_objects,Nebula():setPosition(-70991, 74673))
4151				table.insert(terrain_objects,Nebula():setPosition(-84860, 73668))
4152				table.insert(terrain_objects,Nebula():setPosition(-87875, 65628))
4153				table.insert(terrain_objects,Nebula():setPosition(-44056, 52764))
4154				table.insert(terrain_objects,Nebula():setPosition(-43654, 48543))
4155				table.insert(terrain_objects,Mine():setPosition(-51355, 63709))
4156				table.insert(terrain_objects,Nebula():setPosition(-51091, 62814))
4157				table.insert(terrain_objects,Mine():setPosition(-21003, 70945))
4158				table.insert(terrain_objects,Nebula():setPosition(-19935, 73065))
4159				table.insert(terrain_objects,Mine():setPosition(-31656, 62905))
4160				table.insert(terrain_objects,Mine():setPosition(-28440, 67729))
4161				table.insert(terrain_objects,Nebula():setPosition(-27171, 66432))
4162				table.insert(terrain_objects,Mine():setPosition(-195212, -8342))
4163				table.insert(terrain_objects,Mine():setPosition(-193604, -31055))
4164				table.insert(terrain_objects,Nebula():setPosition(-213905, -49749))
4165				table.insert(terrain_objects,Mine():setPosition(-41304, 43809))
4166				table.insert(terrain_objects,Mine():setPosition(-39093, 40593))
4167				table.insert(terrain_objects,Mine():setPosition(-37887, 35367))
4168				table.insert(terrain_objects,Nebula():setPosition(-202448, 2111))
4169				table.insert(terrain_objects,Nebula():setPosition(-212498, -704))
4170				table.insert(terrain_objects,Nebula():setPosition(-205262, -13166))
4171				table.insert(terrain_objects,Nebula():setPosition(-210689, -16181))
4172				table.insert(terrain_objects,Mine():setPosition(-158227, 36482))
4173				table.insert(terrain_objects,Mine():setPosition(-154207, 37889))
4174				table.insert(terrain_objects,Mine():setPosition(-179533, 37487))
4175				table.insert(terrain_objects,Nebula():setPosition(-209684, -27035))
4176				table.insert(terrain_objects,Nebula():setPosition(-206468, -42111))
4177				table.insert(terrain_objects,Mine():setPosition(-165664, 40101))
4178				table.insert(terrain_objects,Mine():setPosition(-195413, 15176))
4179				table.insert(terrain_objects,Mine():setPosition(-199835, 7337))
4180				table.insert(terrain_objects,Mine():setPosition(-193403, -2312))
4181				table.insert(terrain_objects,Mine():setPosition(-202247, 33467))
4182				table.insert(terrain_objects,Mine():setPosition(-197423, 36683))
4183				table.insert(terrain_objects,Mine():setPosition(-196619, 21809))
4184				table.insert(terrain_objects,Nebula():setPosition(-209282, 26633))
4185				table.insert(terrain_objects,Nebula():setPosition(-205865, 20804))
4186				table.insert(terrain_objects,Nebula():setPosition(-206669, 12764))
4187				table.insert(terrain_objects,Nebula():setPosition(-204056, 47136))
4188				table.insert(terrain_objects,Nebula():setPosition(-212297, 46332))
4189				table.insert(terrain_objects,Nebula():setPosition(-206468, 33668))
4190				table.insert(terrain_objects,Nebula():setPosition(-214709, 35276))
4191				table.insert(terrain_objects,Mine():setPosition(-205061, 21608))
4192				table.insert(terrain_objects,Nebula():setPosition(-214709, 12965))
4193				table.insert(terrain_objects,Nebula():setPosition(-176518, 46131))
4194				table.insert(terrain_objects,Nebula():setPosition(-178930, 49146))
4195				table.insert(terrain_objects,Nebula():setPosition(-154207, 64623))
4196				table.insert(terrain_objects,Nebula():setPosition(-167272, 65226))
4197				table.insert(terrain_objects,Nebula():setPosition(-183754, 59598))
4198				table.insert(terrain_objects,Nebula():setPosition(-164659, 51156))
4199				table.insert(terrain_objects,Nebula():setPosition(-152197, 37085))
4200				table.insert(terrain_objects,Nebula():setPosition(-155212, 36080))
4201				table.insert(terrain_objects,Nebula():setPosition(-149784, 45729))
4202				table.insert(terrain_objects,Nebula():setPosition(-168076, 39296))
4203				table.insert(terrain_objects,Nebula():setPosition(-184960, 38894))
4204				table.insert(terrain_objects,Nebula():setPosition(-180538, 35075))
4205				table.insert(terrain_objects,Nebula():setPosition(-178327, 70452))
4206				table.insert(terrain_objects,Nebula():setPosition(-186970, 55980))
4207				table.insert(terrain_objects,Nebula():setPosition(-194207, 45528))
4208				table.insert(terrain_objects,Nebula():setPosition(-197222, 36683))
4209				table.insert(terrain_objects,Nebula():setPosition(-202850, 32864))
4210				table.insert(terrain_objects,Nebula():setPosition(-118026, 70452))
4211				table.insert(terrain_objects,Nebula():setPosition(-104156, 58995))
4212				table.insert(terrain_objects,Nebula():setPosition(-135312, 78090))
4213				table.insert(terrain_objects,Nebula():setPosition(-120036, 81106))
4214				table.insert(terrain_objects,Nebula():setPosition(-193604, 71457))
4215				table.insert(terrain_objects,Nebula():setPosition(-203453, 55980))
4216				table.insert(terrain_objects,Nebula():setPosition(-197021, 13970))
4217				table.insert(terrain_objects,Nebula():setPosition(-195815, 22814))
4218				table.insert(terrain_objects,Nebula():setPosition(-133101, 26030))
4219				table.insert(terrain_objects,Nebula():setPosition(-152800, 14975))
4220				table.insert(terrain_objects,Nebula():setPosition(-135111, -27839))
4221				table.insert(terrain_objects,Nebula():setPosition(-153202, -14171))
4222				table.insert(terrain_objects,Nebula():setPosition(-161041, -7538))
4223				table.insert(terrain_objects,Nebula():setPosition(-166669, -16583))
4224				table.insert(terrain_objects,Nebula():setPosition(-157222, 26030))
4225				table.insert(terrain_objects,Nebula():setPosition(-167674, 18794))
4226				table.insert(terrain_objects,Nebula():setPosition(-174910, 26231))
4227				table.insert(terrain_objects,Nebula():setPosition(-160237, 11960))
4228				table.insert(terrain_objects,Nebula():setPosition(-195413, -8141))
4229				table.insert(terrain_objects,Nebula():setPosition(-192800, -2312))
4230				table.insert(terrain_objects,Nebula():setPosition(-197624, -35276))
4231				table.insert(terrain_objects,Nebula():setPosition(-199433, 7337))
4232				table.insert(terrain_objects,Nebula():setPosition(-156217, -26432))
4233				table.insert(terrain_objects,Nebula():setPosition(-166066, -35678))
4234				table.insert(terrain_objects,Nebula():setPosition(-178528, -35879))
4235				table.insert(terrain_objects,Nebula():setPosition(-176518, -21608))
4236				table.insert(terrain_objects,Nebula():setPosition(-193403, -16382))
4237				table.insert(terrain_objects,Nebula():setPosition(-193805, -30653))
4238				table.insert(terrain_objects,Nebula():setPosition(-186367, -26432))
4239				table.insert(terrain_objects,Nebula():setPosition(-199634, -23417))
4240			-- kraylor side
4241				table.insert(terrain_objects,Nebula():setPosition(25950, 15065))
4242				table.insert(terrain_objects,Nebula():setPosition(17927, 3032))
4243				table.insert(terrain_objects,Nebula():setPosition(18114, -4244))
4244				table.insert(terrain_objects,Nebula():setPosition(25390, -18424))
4245				table.insert(terrain_objects,Mine():setPosition(35073, -35990))
4246				table.insert(terrain_objects,Mine():setPosition(36480, -37598))
4247				table.insert(terrain_objects,Mine():setPosition(37887, -41417))
4248				table.insert(terrain_objects,Mine():setPosition(50551, -65738))
4249				table.insert(terrain_objects,Mine():setPosition(49144, -62723))
4250				table.insert(terrain_objects,Mine():setPosition(29445, -72573))
4251				table.insert(terrain_objects,Mine():setPosition(33666, -66944))
4252				table.insert(terrain_objects,Mine():setPosition(57586, -73176))
4253				table.insert(terrain_objects,Mine():setPosition(41505, -50864))
4254				table.insert(terrain_objects,Mine():setPosition(38088, -46040))
4255				table.insert(terrain_objects,Mine():setPosition(38490, -62321))
4256				table.insert(terrain_objects,Mine():setPosition(44923, -55688))
4257				table.insert(terrain_objects,Mine():setPosition(52762, -68753))
4258				table.insert(terrain_objects,Mine():setPosition(55174, -73779))
4259				table.insert(terrain_objects,Nebula():setPosition(48679, -59598))
4260				table.insert(terrain_objects,Nebula():setPosition(52498, -66834))
4261				table.insert(terrain_objects,Nebula():setPosition(54508, -73668))
4262				table.insert(terrain_objects,Nebula():setPosition(66970, -78090))
4263				table.insert(terrain_objects,Nebula():setPosition(71393, -31658))
4264				table.insert(terrain_objects,Nebula():setPosition(89483, -65427))
4265				table.insert(terrain_objects,Nebula():setPosition(36418, -65427))
4266				table.insert(terrain_objects,Nebula():setPosition(39835, -59598))
4267				table.insert(terrain_objects,Nebula():setPosition(34006, -34472))
4268				table.insert(terrain_objects,Nebula():setPosition(38830, -42714))
4269				table.insert(terrain_objects,Nebula():setPosition(73202, -60402))
4270				table.insert(terrain_objects,Nebula():setPosition(42850, -51357))
4271				table.insert(terrain_objects,Nebula():setPosition(100538, -82915))
4272				table.insert(terrain_objects,Nebula():setPosition(83252, -76482))
4273				table.insert(terrain_objects,Mine():setPosition(104822, -56090))
4274				table.insert(terrain_objects,Nebula():setPosition(135312, -79900))
4275				table.insert(terrain_objects,Nebula():setPosition(122448, -76884))
4276				table.insert(terrain_objects,Mine():setPosition(164659, -17990))
4277				table.insert(terrain_objects,Mine():setPosition(167875, -15578))
4278				table.insert(terrain_objects,Mine():setPosition(191393, -15377))
4279				table.insert(terrain_objects,Nebula():setPosition(193202, -61407))
4280				table.insert(terrain_objects,Mine():setPosition(160237, -5528))
4281				table.insert(terrain_objects,Mine():setPosition(162448, -9950))
4282				table.insert(terrain_objects,Mine():setPosition(102008, -56492))
4283				table.insert(terrain_objects,Nebula():setPosition(100337, -55377))
4284				table.insert(terrain_objects,Nebula():setPosition(106367, -56181))
4285				table.insert(terrain_objects,Mine():setPosition(160036, -41910))
4286				table.insert(terrain_objects,Mine():setPosition(178327, -20402))
4287				table.insert(terrain_objects,Mine():setPosition(185764, -26030))
4288				table.insert(terrain_objects,Mine():setPosition(155011, -27236))
4289				table.insert(terrain_objects,Mine():setPosition(184558, -40503))
4290				table.insert(terrain_objects,Nebula():setPosition(115011, -67236))
4291				table.insert(terrain_objects,Mine():setPosition(159835, 12764))
4292				table.insert(terrain_objects,Mine():setPosition(155413, 11759))
4293				table.insert(terrain_objects,Mine():setPosition(156217, 27437))
4294				table.insert(terrain_objects,Nebula():setPosition(164659, -65628))
4295				table.insert(terrain_objects,Nebula():setPosition(164659, -52161))
4296				table.insert(terrain_objects,Mine():setPosition(154609, -12362))
4297				table.insert(terrain_objects,Nebula():setPosition(184960, -39698))
4298				table.insert(terrain_objects,Nebula():setPosition(193202, -40302))
4299				table.insert(terrain_objects,Nebula():setPosition(161242, -41910))
4300				table.insert(terrain_objects,Nebula():setPosition(184960, -70653))
4301				table.insert(terrain_objects,Mine():setPosition(150790, 15578))
4302				table.insert(terrain_objects,Mine():setPosition(174508, 29648))
4303				table.insert(terrain_objects,Mine():setPosition(167674, 17588))
4304				table.insert(terrain_objects,Nebula():setPosition(186166, -48744))
4305				table.insert(terrain_objects,Nebula():setPosition(187975, -55176))
4306				table.insert(terrain_objects,Nebula():setPosition(170890, -78090))
4307				table.insert(terrain_objects,Nebula():setPosition(173704, -61005))
4308				table.insert(terrain_objects,Nebula():setPosition(25161, -79497))
4309				table.insert(terrain_objects,Nebula():setPosition(31795, -72261))
4310				table.insert(terrain_objects,Mine():setPosition(42108, 51649))
4311				table.insert(terrain_objects,Mine():setPosition(42510, 48030))
4312				table.insert(terrain_objects,Nebula():setPosition(41443, 41106))
4313				table.insert(terrain_objects,Nebula():setPosition(69583, 30854))
4314				table.insert(terrain_objects,Nebula():setPosition(73001, 56181))
4315				table.insert(terrain_objects,Mine():setPosition(36681, 55066))
4316				table.insert(terrain_objects,Nebula():setPosition(36217, 34070))
4317				table.insert(terrain_objects,Mine():setPosition(96179, 56272))
4318				table.insert(terrain_objects,Nebula():setPosition(94508, 57186))
4319				table.insert(terrain_objects,Nebula():setPosition(98930, 52563))
4320				table.insert(terrain_objects,Mine():setPosition(34872, 57679))
4321				table.insert(terrain_objects,Nebula():setPosition(33805, 60402))
4322				table.insert(terrain_objects,Mine():setPosition(46732, 55669))
4323				table.insert(terrain_objects,Nebula():setPosition(38227, 53166))
4324				table.insert(terrain_objects,Mine():setPosition(98993, 53860))
4325				table.insert(terrain_objects,Mine():setPosition(99998, 56674))
4326				table.insert(terrain_objects,Nebula():setPosition(100940, 81910))
4327				table.insert(terrain_objects,Nebula():setPosition(63955, 69447))
4328				table.insert(terrain_objects,Nebula():setPosition(70991, 74673))
4329				table.insert(terrain_objects,Nebula():setPosition(84860, 73668))
4330				table.insert(terrain_objects,Nebula():setPosition(87875, 65628))
4331				table.insert(terrain_objects,Nebula():setPosition(44056, 52764))
4332				table.insert(terrain_objects,Nebula():setPosition(43654, 48543))
4333				table.insert(terrain_objects,Mine():setPosition(51355, 63709))
4334				table.insert(terrain_objects,Nebula():setPosition(51091, 62814))
4335				table.insert(terrain_objects,Mine():setPosition(21003, 70945))
4336				table.insert(terrain_objects,Nebula():setPosition(19935, 73065))
4337				table.insert(terrain_objects,Mine():setPosition(31656, 62905))
4338				table.insert(terrain_objects,Mine():setPosition(28440, 67729))
4339				table.insert(terrain_objects,Nebula():setPosition(27171, 66432))
4340				table.insert(terrain_objects,Mine():setPosition(195212, -8342))
4341				table.insert(terrain_objects,Mine():setPosition(193604, -31055))
4342				table.insert(terrain_objects,Nebula():setPosition(213905, -49749))
4343				table.insert(terrain_objects,Mine():setPosition(41304, 43809))
4344				table.insert(terrain_objects,Mine():setPosition(39093, 40593))
4345				table.insert(terrain_objects,Mine():setPosition(37887, 35367))
4346				table.insert(terrain_objects,Nebula():setPosition(202448, 2111))
4347				table.insert(terrain_objects,Nebula():setPosition(212498, -704))
4348				table.insert(terrain_objects,Nebula():setPosition(205262, -13166))
4349				table.insert(terrain_objects,Nebula():setPosition(210689, -16181))
4350				table.insert(terrain_objects,Mine():setPosition(158227, 36482))
4351				table.insert(terrain_objects,Mine():setPosition(154207, 37889))
4352				table.insert(terrain_objects,Mine():setPosition(179533, 37487))
4353				table.insert(terrain_objects,Nebula():setPosition(209684, -27035))
4354				table.insert(terrain_objects,Nebula():setPosition(206468, -42111))
4355				table.insert(terrain_objects,Mine():setPosition(165664, 40101))
4356				table.insert(terrain_objects,Mine():setPosition(195413, 15176))
4357				table.insert(terrain_objects,Mine():setPosition(199835, 7337))
4358				table.insert(terrain_objects,Mine():setPosition(193403, -2312))
4359				table.insert(terrain_objects,Mine():setPosition(202247, 33467))
4360				table.insert(terrain_objects,Mine():setPosition(197423, 36683))
4361				table.insert(terrain_objects,Mine():setPosition(196619, 21809))
4362				table.insert(terrain_objects,Nebula():setPosition(209282, 26633))
4363				table.insert(terrain_objects,Nebula():setPosition(205865, 20804))
4364				table.insert(terrain_objects,Nebula():setPosition(206669, 12764))
4365				table.insert(terrain_objects,Nebula():setPosition(204056, 47136))
4366				table.insert(terrain_objects,Nebula():setPosition(212297, 46332))
4367				table.insert(terrain_objects,Nebula():setPosition(206468, 33668))
4368				table.insert(terrain_objects,Nebula():setPosition(214709, 35276))
4369				table.insert(terrain_objects,Mine():setPosition(205061, 21608))
4370				table.insert(terrain_objects,Nebula():setPosition(214709, 12965))
4371				table.insert(terrain_objects,Nebula():setPosition(176518, 46131))
4372				table.insert(terrain_objects,Nebula():setPosition(178930, 49146))
4373				table.insert(terrain_objects,Nebula():setPosition(154207, 64623))
4374				table.insert(terrain_objects,Nebula():setPosition(167272, 65226))
4375				table.insert(terrain_objects,Nebula():setPosition(183754, 59598))
4376				table.insert(terrain_objects,Nebula():setPosition(164659, 51156))
4377				table.insert(terrain_objects,Nebula():setPosition(152197, 37085))
4378				table.insert(terrain_objects,Nebula():setPosition(155212, 36080))
4379				table.insert(terrain_objects,Nebula():setPosition(149784, 45729))
4380				table.insert(terrain_objects,Nebula():setPosition(168076, 39296))
4381				table.insert(terrain_objects,Nebula():setPosition(184960, 38894))
4382				table.insert(terrain_objects,Nebula():setPosition(180538, 35075))
4383				table.insert(terrain_objects,Nebula():setPosition(178327, 70452))
4384				table.insert(terrain_objects,Nebula():setPosition(186970, 55980))
4385				table.insert(terrain_objects,Nebula():setPosition(194207, 45528))
4386				table.insert(terrain_objects,Nebula():setPosition(197222, 36683))
4387				table.insert(terrain_objects,Nebula():setPosition(202850, 32864))
4388				table.insert(terrain_objects,Nebula():setPosition(118026, 70452))
4389				table.insert(terrain_objects,Nebula():setPosition(104156, 58995))
4390				table.insert(terrain_objects,Nebula():setPosition(135312, 78090))
4391				table.insert(terrain_objects,Nebula():setPosition(120036, 81106))
4392				table.insert(terrain_objects,Nebula():setPosition(193604, 71457))
4393				table.insert(terrain_objects,Nebula():setPosition(203453, 55980))
4394				table.insert(terrain_objects,Nebula():setPosition(197021, 13970))
4395				table.insert(terrain_objects,Nebula():setPosition(195815, 22814))
4396				table.insert(terrain_objects,Nebula():setPosition(133101, 26030))
4397				table.insert(terrain_objects,Nebula():setPosition(152800, 14975))
4398				table.insert(terrain_objects,Nebula():setPosition(135111, -27839))
4399				table.insert(terrain_objects,Nebula():setPosition(153202, -14171))
4400				table.insert(terrain_objects,Nebula():setPosition(161041, -7538))
4401				table.insert(terrain_objects,Nebula():setPosition(166669, -16583))
4402				table.insert(terrain_objects,Nebula():setPosition(157222, 26030))
4403				table.insert(terrain_objects,Nebula():setPosition(167674, 18794))
4404				table.insert(terrain_objects,Nebula():setPosition(174910, 26231))
4405				table.insert(terrain_objects,Nebula():setPosition(160237, 11960))
4406				table.insert(terrain_objects,Nebula():setPosition(195413, -8141))
4407				table.insert(terrain_objects,Nebula():setPosition(192800, -2312))
4408				table.insert(terrain_objects,Nebula():setPosition(197624, -35276))
4409				table.insert(terrain_objects,Nebula():setPosition(199433, 7337))
4410				table.insert(terrain_objects,Nebula():setPosition(156217, -26432))
4411				table.insert(terrain_objects,Nebula():setPosition(166066, -35678))
4412				table.insert(terrain_objects,Nebula():setPosition(178528, -35879))
4413				table.insert(terrain_objects,Nebula():setPosition(176518, -21608))
4414				table.insert(terrain_objects,Nebula():setPosition(193403, -16382))
4415				table.insert(terrain_objects,Nebula():setPosition(193805, -30653))
4416				table.insert(terrain_objects,Nebula():setPosition(186367, -26432))
4417				table.insert(terrain_objects,Nebula():setPosition(199634, -23417))
4418		end
4419
4420
4421	-- player tagged relocation override
4422	-- this is placed at the end because the values depend on "terrain" variables calculated in the middle of the function
4423	hx = human_planet_center_x + human_planet_radius + (human_moon_1_orbit_distance/2)
4424	kx = kraylor_planet_center_x - kraylor_planet_radius - (kraylor_moon_1_orbit_distance/2)
4425	--player side   		  Hum   Kra    Hum   Kra    Hum    Kra    Hum   Kra    Hum    Kra    Hum   Kra	  Hum	 Kra    Hum    Kra    Hum    Kra    Hum    Kra    Hum    Kra    Hum    Kra    Hum    Kra    Hum    Kra    Hum    Kra    Hum    Kra
4426	--player index   		   1     2      3     4      5      6      7     8      9     10     11    12	  13	 14     15     16     17     18     19     20     21     22     23     24     25     26     27     28     29     30     31     32
4427	player_tag_relocate_x = { hx,   kx,    hx,   kx,    hx,    kx,    hx,   kx,    hx,    kx,    hx,   kx,    hx,    kx,    hx,    kx,    hx,    kx,    hx,    kx,    hx,    kx,    hx,    kx,    hx,    kx,    hx,    kx,    hx,    kx,    hx,    kx}
4428	player_tag_relocate_y =	{  0,    0,     0,    0,     0,     0,     0,    0,     0,     0,     0,    0,     0,    0,     0,     0,     0,     0,     0,     0,     0,     0,     0,     0,     0,     0,     0,     0,     0,     0,     0,     0}
4429
4430
4431end
4432function moveDownTheRabbitHole()
4433
4434	-- move asteroid rings
4435	for i=1,number_of_asteroids_in_ring do
4436		-- human side
4437			if human_asteroid_ring[i]:isValid() then
4438				human_asteroid_ring[i].angle = human_asteroid_ring[i].angle + human_asteroid_ring[i].speed
4439				if human_asteroid_ring[i].angle > 360 then
4440					human_asteroid_ring[i].angle = human_asteroid_ring[i].angle - 360
4441				end
4442				setCirclePos(human_asteroid_ring[i],
4443					human_planet_center_x,
4444					human_planet_center_y,
4445					human_asteroid_ring[i].angle,
4446					human_asteroid_ring[i].radius)
4447			end
4448		-- kraylor side
4449			if kraylor_asteroid_ring[i]:isValid() then
4450				kraylor_asteroid_ring[i].angle = kraylor_asteroid_ring[i].angle + kraylor_asteroid_ring[i].speed
4451				if kraylor_asteroid_ring[i].angle > 360 then
4452					kraylor_asteroid_ring[i].angle = kraylor_asteroid_ring[i].angle - 360
4453				end
4454				setCirclePos(kraylor_asteroid_ring[i],
4455					kraylor_planet_center_x,
4456					kraylor_planet_center_y,
4457					kraylor_asteroid_ring[i].angle,
4458					kraylor_asteroid_ring[i].radius)
4459			end
4460
4461	end
4462
4463	-- move mines in the asteroid rings
4464	for i=1,number_of_mines_in_ring do
4465		-- human side
4466			if human_mine_ring[i]:isValid() then
4467				human_mine_ring[i].angle = human_mine_ring[i].angle + human_mine_ring[i].speed
4468				if human_mine_ring[i].angle > 360 then
4469					human_mine_ring[i].angle = human_mine_ring[i].angle - 360
4470				end
4471				setCirclePos(human_mine_ring[i],
4472					human_planet_center_x,
4473					human_planet_center_y,
4474					human_mine_ring[i].angle,
4475					human_mine_ring[i].radius)
4476			end
4477		-- kraylor side
4478			if kraylor_mine_ring[i]:isValid() then
4479				kraylor_mine_ring[i].angle = kraylor_mine_ring[i].angle + kraylor_mine_ring[i].speed
4480				if kraylor_mine_ring[i].angle > 360 then
4481					kraylor_mine_ring[i].angle = kraylor_mine_ring[i].angle - 360
4482				end
4483				setCirclePos(kraylor_mine_ring[i],
4484					kraylor_planet_center_x,
4485					kraylor_planet_center_y,
4486					kraylor_mine_ring[i].angle,
4487					kraylor_mine_ring[i].radius)
4488			end
4489
4490	end
4491
4492	-- move orbiting space stations
4493		-- human
4494			human_orbital_station_1.angle = human_orbital_station_1.angle + human_orbital_station_1.speed
4495			if human_orbital_station_1.angle > 360 then
4496				human_orbital_station_1.angle = human_orbital_station_1.angle - 360
4497			end
4498			setCirclePos(human_orbital_station_1,
4499				human_planet_center_x,
4500				human_planet_center_y,
4501				human_orbital_station_1.angle,
4502				human_orbital_station_1.distance)
4503
4504			human_orbital_station_2.angle = human_orbital_station_2.angle + human_orbital_station_2.speed
4505			if human_orbital_station_2.angle > 360 then
4506				human_orbital_station_2.angle = human_orbital_station_2.angle - 360
4507			end
4508			setCirclePos(human_orbital_station_2,
4509				human_planet_center_x,
4510				human_planet_center_y,
4511				human_orbital_station_2.angle,
4512				human_orbital_station_2.distance)
4513
4514			human_orbital_station_3.angle = human_orbital_station_3.angle + human_orbital_station_3.speed
4515			if human_orbital_station_3.angle > 360 then
4516				human_orbital_station_3.angle = human_orbital_station_3.angle - 360
4517			end
4518			setCirclePos(human_orbital_station_3,
4519				human_planet_center_x,
4520				human_planet_center_y,
4521				human_orbital_station_3.angle,
4522				human_orbital_station_3.distance)
4523
4524			human_orbital_station_4.angle = human_orbital_station_4.angle + human_orbital_station_4.speed
4525			if human_orbital_station_4.angle > 360 then
4526				human_orbital_station_4.angle = human_orbital_station_4.angle - 360
4527			end
4528			setCirclePos(human_orbital_station_4,
4529				human_planet_center_x,
4530				human_planet_center_y,
4531				human_orbital_station_4.angle,
4532				human_orbital_station_4.distance)
4533
4534			human_orbital_station_5.angle = human_orbital_station_5.angle + human_orbital_station_5.speed
4535			if human_orbital_station_5.angle > 360 then
4536				human_orbital_station_5.angle = human_orbital_station_5.angle - 360
4537			end
4538			setCirclePos(human_orbital_station_5,
4539				human_planet_center_x,
4540				human_planet_center_y,
4541				human_orbital_station_5.angle,
4542				human_orbital_station_5.distance)
4543
4544		-- kraylor
4545			kraylor_orbital_station_1.angle = kraylor_orbital_station_1.angle + kraylor_orbital_station_1.speed
4546			if kraylor_orbital_station_1.angle > 360 then
4547				kraylor_orbital_station_1.angle = kraylor_orbital_station_1.angle - 360
4548			end
4549			setCirclePos(kraylor_orbital_station_1,
4550				kraylor_planet_center_x,
4551				kraylor_planet_center_y,
4552				kraylor_orbital_station_1.angle,
4553				kraylor_orbital_station_1.distance)
4554
4555			kraylor_orbital_station_2.angle = kraylor_orbital_station_2.angle + kraylor_orbital_station_2.speed
4556			if kraylor_orbital_station_2.angle > 360 then
4557				kraylor_orbital_station_2.angle = kraylor_orbital_station_2.angle - 360
4558			end
4559			setCirclePos(kraylor_orbital_station_2,
4560				kraylor_planet_center_x,
4561				kraylor_planet_center_y,
4562				kraylor_orbital_station_2.angle,
4563				kraylor_orbital_station_2.distance)
4564
4565			kraylor_orbital_station_3.angle = kraylor_orbital_station_3.angle + kraylor_orbital_station_3.speed
4566			if kraylor_orbital_station_3.angle > 360 then
4567				kraylor_orbital_station_3.angle = kraylor_orbital_station_3.angle - 360
4568			end
4569			setCirclePos(kraylor_orbital_station_3,
4570				kraylor_planet_center_x,
4571				kraylor_planet_center_y,
4572				kraylor_orbital_station_3.angle,
4573				kraylor_orbital_station_3.distance)
4574
4575			kraylor_orbital_station_4.angle = kraylor_orbital_station_4.angle + kraylor_orbital_station_4.speed
4576			if kraylor_orbital_station_4.angle > 360 then
4577				kraylor_orbital_station_4.angle = kraylor_orbital_station_4.angle - 360
4578			end
4579			setCirclePos(kraylor_orbital_station_4,
4580				kraylor_planet_center_x,
4581				kraylor_planet_center_y,
4582				kraylor_orbital_station_4.angle,
4583				kraylor_orbital_station_4.distance)
4584
4585			kraylor_orbital_station_5.angle = kraylor_orbital_station_5.angle + kraylor_orbital_station_5.speed
4586			if kraylor_orbital_station_5.angle > 360 then
4587				kraylor_orbital_station_5.angle = kraylor_orbital_station_5.angle - 360
4588			end
4589			setCirclePos(kraylor_orbital_station_5,
4590				kraylor_planet_center_x,
4591				kraylor_planet_center_y,
4592				kraylor_orbital_station_5.angle,
4593				kraylor_orbital_station_5.distance)
4594
4595
4596end
4597
4598-------------------------------
4599--	Cargo related functions  --
4600-------------------------------
4601function setupTailoredShipAttributes()
4602	-- part of Xansta's larger overall script core for randomized stations and NPC ships;
4603	--Ship Template Name List
4604	stnl = {"MT52 Hornet","MU52 Hornet","Adder MK5","Adder MK4","WX-Lindworm","Adder MK6","Phobos T3","Phobos M3","Piranha F8","Piranha F12","Ranus U","Nirvana R5A","Stalker Q7","Stalker R7","Atlantis X23","Starhammer II","Odin","Fighter","Cruiser","Missile Cruiser","Strikeship","Adv. Striker","Dreadnought","Battlestation","Blockade Runner","Ktlitan Fighter","Ktlitan Breaker","Ktlitan Worker","Ktlitan Drone","Ktlitan Feeder","Ktlitan Scout","Ktlitan Destroyer","Storm"}
4605	--Ship Template Score List
4606	stsl = {5            ,5            ,7          ,6          ,7            ,8          ,15         ,16         ,15          ,15           ,25       ,20           ,25          ,25          ,50            ,70             ,250   ,6        ,18       ,14               ,30          ,27            ,80           ,100            ,65               ,6                ,45               ,40              ,4              ,48              ,8              ,50                 ,22}
4607	playerShipNamesFor = {}
4608	-- TODO switch to spelling with space or dash matching the type name
4609	playerShipNamesFor["MP52Hornet"] = {"Dragonfly","Scarab","Mantis","Yellow Jacket","Jimminy","Flik","Thorny","Buzz"}
4610	playerShipNamesFor["Piranha"] = {"Razor","Biter","Ripper","Voracious","Carnivorous","Characid","Vulture","Predator"}
4611	playerShipNamesFor["FlaviaPFalcon"] = {"Ladyhawke","Hunter","Seeker","Gyrefalcon","Kestrel","Magpie","Bandit","Buccaneer"}
4612	playerShipNamesFor["PhobosM3P"] = {"Blinder","Shadow","Distortion","Diemos","Ganymede","Castillo","Thebe","Retrograde"}
4613	playerShipNamesFor["Atlantis"] = {"Excalibur","Thrasher","Punisher","Vorpal","Protang","Drummond","Parchim","Coronado"}
4614	playerShipNamesFor["Cruiser"] = {"Excelsior","Velociraptor","Thunder","Kona","Encounter","Perth","Aspern","Panther"}
4615	playerShipNamesFor["MissileCruiser"] = {"Projectus","Hurlmeister","Flinger","Ovod","Amatola","Nakhimov","Antigone"}
4616	playerShipNamesFor["Fighter"] = {"Buzzer","Flitter","Zippiticus","Hopper","Molt","Stinger","Stripe"}
4617	playerShipNamesFor["Benedict"] = {"Elizabeth","Ford","Vikramaditya","Liaoning","Avenger","Naruebet","Washington","Lincoln","Garibaldi","Eisenhower"}
4618	playerShipNamesFor["Kiriya"] = {"Cavour","Reagan","Gaulle","Paulo","Truman","Stennis","Kuznetsov","Roosevelt","Vinson","Old Salt"}
4619	playerShipNamesFor["Striker"] = {"Sparrow","Sizzle","Squawk","Crow","Snowbird","Hawk"}
4620	playerShipNamesFor["Lindworm"] = {"Seagull","Catapult","Blowhard","Flapper","Nixie","Pixie","Tinkerbell"}
4621	playerShipNamesFor["Repulse"] = {"Fiddler","Brinks","Loomis","Mowag","Patria","Pandur","Terrex","Komatsu","Eitan"}
4622	playerShipNamesFor["Ender"] = {"Mongo","Godzilla","Leviathan","Kraken","Jupiter","Saturn"}
4623	playerShipNamesFor["Nautilus"] = {"October", "Abdiel", "Manxman", "Newcon", "Nusret", "Pluton", "Amiral", "Amur", "Heinkel", "Dornier"}
4624	playerShipNamesFor["Hathcock"] = {"Hayha", "Waldron", "Plunkett", "Mawhinney", "Furlong", "Zaytsev", "Pavlichenko", "Fett", "Hawkeye", "Hanzo"}
4625	playerShipNamesFor["ProtoAtlantis"] = {"Narsil", "Blade", "Decapitator", "Trisect", "Sabre"}
4626	playerShipNamesFor["Maverick"] = {"Angel", "Thunderbird", "Roaster", "Magnifier", "Hedge"}
4627	playerShipNamesFor["Crucible"] = {"Sling", "Stark", "Torrid", "Kicker", "Flummox"}
4628	playerShipNamesFor["Surkov"] = {"Sting", "Sneak", "Bingo", "Thrill", "Vivisect"}
4629	playerShipNamesFor["Stricken"] = {"Blazon", "Streaker", "Pinto", "Spear", "Javelin"}
4630	playerShipNamesFor["AtlantisII"] = {"Spyder", "Shelob", "Tarantula", "Aragog", "Charlotte"}
4631	playerShipNamesFor["Redhook"] = {"Headhunter", "Thud", "Troll", "Scalper", "Shark"}
4632	playerShipNamesFor["DestroyerIII"] = {"Trebuchet", "Pitcher", "Mutant", "Gronk", "Methuselah"}
4633	playerShipNamesFor["Leftovers"] = {
4634		"Adelphi",
4635		"Ahwahnee",
4636		"Akagi",
4637		"Akira",
4638		"Al-Batani",
4639		"Ambassador",
4640		"Andromeda",
4641		"Antares",
4642		"Apollo",
4643		"Appalachia",
4644		"Arcos",
4645		"Aries",
4646		"Athena",
4647		"Beethoven",
4648		"Bellerophon",
4649		"Biko",
4650		"Bonchune",
4651		"Bozeman",
4652		"Bradbury",
4653		"Brattain",
4654		"Budapest",
4655		"Buran",
4656		"Cairo",
4657		"Calypso",
4658		"Capricorn",
4659		"Carolina",
4660		"Centaur",
4661		"Challenger",
4662		"Charleston",
4663		"Chekov",
4664		"Cheyenne",
4665		"Clement",
4666		"Cochraine",
4667		"Columbia",
4668		"Concorde",
4669		"Constantinople",
4670		"Constellation",
4671		"Constitution",
4672		"Copernicus",
4673		"Cousteau",
4674		"Crazy Horse",
4675		"Crockett",
4676		"Daedalus",
4677		"Danube",
4678		"Defiant",
4679		"Deneva",
4680		"Denver",
4681		"Discovery",
4682		"Drake",
4683		"Endeavor",
4684		"Endurance",
4685		"Equinox",
4686		"Essex",
4687		"Exeter",
4688		"Farragut",
4689		"Fearless",
4690		"Fleming",
4691		"Foregone",
4692		"Fredrickson",
4693		"Freedom",
4694		"Gage",
4695		"Galaxy",
4696		"Galileo",
4697		"Gander",
4698		"Ganges",
4699		"Gettysburg",
4700		"Ghandi",
4701		"Goddard",
4702		"Grissom",
4703		"Hathaway",
4704		"Helin",
4705		"Hera",
4706		"Heracles",
4707		"Hokule'a",
4708		"Honshu",
4709		"Hood",
4710		"Hope",
4711		"Horatio",
4712		"Horizon",
4713		"Interceptor",
4714		"Intrepid",
4715		"Istanbul",
4716		"Jenolen",
4717		"Kearsarge",
4718		"Kongo",
4719		"Korolev",
4720		"Kyushu",
4721		"Lakota",
4722		"Lalo",
4723		"Lancer",
4724		"Lantree",
4725		"LaSalle",
4726		"Leeds",
4727		"Lexington",
4728		"Luna",
4729		"Magellan",
4730		"Majestic",
4731		"Malinche",
4732		"Maryland",
4733		"Masher",
4734		"Mediterranean",
4735		"Mekong",
4736		"Melbourne",
4737		"Merced",
4738		"Merrimack",
4739		"Miranda",
4740		"Nash",
4741		"New Orleans",
4742		"Newton",
4743		"Niagra",
4744		"Nobel",
4745		"Norway",
4746		"Nova",
4747		"Oberth",
4748		"Odyssey",
4749		"Orinoco",
4750		"Osiris",
4751		"Pasteur",
4752		"Pegasus",
4753		"Peregrine",
4754		"Poseidon",
4755		"Potempkin",
4756		"Princeton",
4757		"Prokofiev",
4758		"Prometheus",
4759		"Proxima",
4760		"Rabin",
4761		"Raman",
4762		"Relativity",
4763		"Reliant",
4764		"Renaissance",
4765		"Renegade",
4766		"Republic",
4767		"Rhode Island",
4768		"Rigel",
4769		"Righteous",
4770		"Rubicon",
4771		"Rutledge",
4772		"Sarajevo",
4773		"Saratoga",
4774		"Scimitar",
4775		"Sequoia",
4776		"Shenandoah",
4777		"ShirKahr",
4778		"Sitak",
4779		"Socrates",
4780		"Sovereign",
4781		"Spector",
4782		"Springfield",
4783		"Stargazer",
4784		"Steamrunner",
4785		"Surak",
4786		"Sutherland",
4787		"Sydney",
4788		"T'Kumbra",
4789		"Thomas Paine",
4790		"Thunderchild",
4791		"Tian An Men",
4792		"Titan",
4793		"Tolstoy",
4794		"Trial",
4795		"Trieste",
4796		"Trinculo",
4797		"Tripoli",
4798		"Ulysses",
4799		"Valdemar",
4800		"Valiant",
4801		"Volga",
4802		"Voyager",
4803		"Wambundu",
4804		"Waverider",
4805		"Wellington",
4806		"Wells",
4807		"Wyoming",
4808		"Yamaguchi",
4809		"Yamato",
4810		"Yangtzee Kiang",
4811		"Yeager",
4812		"Yorkshire",
4813		"Yorktown",
4814		"Yosemite",
4815		"Yukon",
4816		"Zapata",
4817		"Zhukov",
4818		"Zodiac",
4819	}
4820end
4821function setupBarteringGoods()
4822	-- part of Xansta's larger overall bartering/crafting setup
4823	-- list of goods available to buy, sell or trade (sell still under development)
4824	goodsList = {	{"food",0},
4825					{"medicine",0},
4826					{"nickel",0},
4827					{"platinum",0},
4828					{"gold",0},
4829					{"dilithium",0},
4830					{"tritanium",0},
4831					{"luxury",0},
4832					{"cobalt",0},
4833					{"impulse",0},
4834					{"warp",0},
4835					{"shield",0},
4836					{"tractor",0},
4837					{"repulsor",0},
4838					{"beam",0},
4839					{"optic",0},
4840					{"robotic",0},
4841					{"filament",0},
4842					{"transporter",0},
4843					{"sensor",0},
4844					{"communication",0},
4845					{"autodoc",0},
4846					{"lifter",0},
4847					{"android",0},
4848					{"nanites",0},
4849					{"software",0},
4850					{"circuit",0},
4851					{"battery",0}	}
4852
4853end
4854function setupPlacementRandomizationFunctions()
4855	--array of functions to facilitate randomized station placement
4856	placeStation = {placeAlcaleica,			-- 1
4857					placeAnderson,			-- 2
4858					placeArcher,			-- 3
4859					placeArchimedes,		-- 4
4860					placeArmstrong,			-- 5
4861					placeAsimov,			-- 6
4862					placeBarclay,			-- 7
4863					placeBethesda,			-- 8
4864					placeBroeck,			-- 9
4865					placeCalifornia,		--10
4866					placeCalvin,			--11
4867					placeCavor,				--12
4868					placeChatuchak,			--13
4869					placeCoulomb,			--14
4870					placeCyrus,				--15
4871					placeDeckard,			--16
4872					placeDeer,				--17
4873					placeErickson,			--18
4874					placeEvondos,			--19
4875					placeFeynman,			--20
4876					placeGrasberg,			--21
4877					placeHayden,			--22
4878					placeHeyes,				--23
4879					placeHossam,			--24
4880					placeImpala,			--25
4881					placeKomov,				--26
4882					placeKrak,				--27
4883					placeKruk,				--28
4884					placeLipkin,			--29
4885					placeMadison,			--30
4886					placeMaiman,			--31
4887					placeMarconi,			--32
4888					placeMayo,				--33
4889					placeMiller,			--34
4890					placeMuddville,			--35
4891					placeNexus6,			--36
4892					placeOBrien,			--37
4893					placeOlympus,			--38
4894					placeOrgana,			--39
4895					placeOutpost15,			--40
4896					placeOutpost21,			--41
4897					placeOwen,				--42
4898					placePanduit,			--43
4899					placeRipley,			--44
4900					placeRutherford,		--45
4901					placeScience7,			--46
4902					placeShawyer,			--47
4903					placeShree,				--48
4904					placeSoong,				--49
4905					placeTiberius,			--50
4906					placeTokra,				--51
4907					placeToohie,			--52
4908					placeUtopiaPlanitia,	--53
4909					placeVactel,			--54
4910					placeVeloquan,			--55
4911					placeZefram}			--56
4912	--array of functions to facilitate randomized station placement (friendly, neutral or enemy)
4913	placeGenericStation = {placeJabba,		-- 1
4914					placeKrik,				-- 2
4915					placeLando,				-- 3
4916					placeMaverick,			-- 4
4917					placeNefatha,			-- 5
4918					placeOkun,				-- 6
4919					placeOutpost7,			-- 7
4920					placeOutpost8,			-- 8
4921					placeOutpost33,			-- 9
4922					placePrada,				--10
4923					placeResearch11,		--11
4924					placeResearch19,		--12
4925					placeRubis,				--13
4926					placeScience2,			--14
4927					placeScience4,			--15
4928					placeSkandar,			--16
4929					placeSpot,				--17
4930					placeStarnet,			--18
4931					placeTandon,			--19
4932					placeVaiken,			--20
4933					placeValero}			--21
4934
4935end
4936
4937-----------------------------------------------------------
4938--	Stations to be placed (all need some kind of goods)  --
4939-----------------------------------------------------------
4940function placeAlcaleica()
4941	--Alcaleica
4942	stationAlcaleica = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation)
4943	stationAlcaleica:setPosition(psx,psy):setCallSign("Alcaleica"):setDescription("Optical Components")
4944	if stationFaction ~= "Independent" then
4945		if random(1,5) <= 1 then
4946			goods[stationAlcaleica] = {{"food",math.random(5,10),1},{"medicine",5,5},{"optic",5,66}}
4947		else
4948			goods[stationAlcaleica] = {{"food",math.random(5,10),1},{"optic",5,66}}
4949			tradeMedicine[stationAlcaleica] = true
4950		end
4951	else
4952		goods[stationAlcaleica] = {{"optic",5,66}}
4953		tradeFood[stationAlcaleica] = true
4954		tradeMedicine[stationAlcaleica] = true
4955	end
4956	stationAlcaleica.publicRelations = true
4957	stationAlcaleica.generalInformation = "We make and supply optic components for various station and ship systems"
4958	stationAlcaleica.stationHistory = "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 electronic and optic company"
4959	return stationAlcaleica
4960end
4961function placeAnderson()
4962	--Anderson
4963	stationAnderson = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation)
4964	stationAnderson:setPosition(psx,psy):setCallSign("Anderson"):setDescription("Battery and software engineering")
4965	if stationFaction ~= "Independent" then
4966		if random(1,5) <= 1 then
4967			goods[stationAnderson] = {{"food",math.random(5,10),1},{"medicine",5,5},{"battery",5,65},{"software",5,115}}
4968		else
4969			goods[stationAnderson] = {{"food",math.random(5,10),1},{"battery",5,65},{"software",5,115}}
4970		end
4971	else
4972		goods[stationAnderson] = {{"battery",5,65},{"software",5,115}}
4973	end
4974	tradeLuxury[stationAnderson] = true
4975	stationAnderson.publicRelations = true
4976	stationAnderson.generalInformation = "We provide high quality high capacity batteries and specialized software for all shipboard systems"
4977	stationAnderson.stationHistory = "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"
4978	return stationAnderson
4979end
4980function placeArcher()
4981	--Archer
4982	stationArcher = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation)
4983	stationArcher:setPosition(psx,psy):setCallSign("Archer"):setDescription("Shield and Armor Research")
4984	if stationFaction ~= "Independent" then
4985		if random(1,5) <= 1 then
4986			goods[stationArcher] = {{"food",math.random(5,10),1},{"medicine",5,5},{"shield",5,90}}
4987		else
4988			goods[stationArcher] = {{"food",math.random(5,10),1},{"shield",5,90}}
4989			tradeMedicine[stationArcher] = true
4990		end
4991	else
4992		goods[stationArcher] = {{"shield",5,90}}
4993		tradeMedicine[stationArcher] = true
4994	end
4995	tradeLuxury[stationArcher] = true
4996	stationArcher.publicRelations = true
4997	stationArcher.generalInformation = "The finest shield and armor manufacturer in the quadrant"
4998	stationArcher.stationHistory = "We named this station for the pioneering spirit of the 22nd century Starfleet explorer, Captain Jonathan Archer"
4999	return stationArcher
5000end
5001function placeArchimedes()
5002	--Archimedes
5003	stationArchimedes = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation)
5004	stationArchimedes:setPosition(psx,psy):setCallSign("Archimedes"):setDescription("Energy and particle beam components")
5005	if stationFaction ~= "Independent" then
5006		if random(1,5) <= 1 then
5007			goods[stationArchimedes] = {{"food",math.random(5,10),1},{"medicine",5,5},{"beam",5,80}}
5008		else
5009			goods[stationArchimedes] = {{"food",math.random(5,10),1},{"beam",5,80}}
5010			tradeMedicine[stationArchimedes] = true
5011		end
5012	else
5013		goods[stationArchimedes] = {{"beam",5,80}}
5014		tradeFood[stationArchimedes] = true
5015	end
5016	tradeLuxury[stationArchimedes] = true
5017	stationArchimedes.publicRelations = true
5018	stationArchimedes.generalInformation = "We fabricate general and specialized components for ship beam systems"
5019	stationArchimedes.stationHistory = "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"
5020	return stationArchimedes
5021end
5022function placeArmstrong()
5023	--Armstrong
5024	stationArmstrong = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation)
5025	stationArmstrong:setPosition(psx,psy):setCallSign("Armstrong"):setDescription("Warp and Impulse engine manufacturing")
5026	if stationFaction ~= "Independent" then
5027		if random(1,5) <= 1 then
5028			goods[stationArmstrong] = {{"food",math.random(5,10),1},{"medicine",5,5},{"repulsor",5,62}}
5029		else
5030			goods[stationArmstrong] = {{"food",math.random(5,10),1},{"repulsor",5,62}}
5031		end
5032	else
5033		goods[stationArmstrong] = {{"repulsor",5,62}}
5034	end
5035--	table.insert(goods[stationArmstrong],{"warp",5,77})
5036	stationArmstrong.publicRelations = true
5037	stationArmstrong.generalInformation = "We manufacture warp, impulse and jump engines for the human navy fleet as well as other independent clients on a contract basis"
5038	stationArmstrong.stationHistory = "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."
5039	return stationArmstrong
5040end
5041function placeAsimov()
5042	--Asimov
5043	stationAsimov = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation)
5044	stationAsimov:setCallSign("Asimov"):setDescription("Training and Coordination"):setPosition(psx,psy)
5045	if stationFaction ~= "Independent" then
5046		if random(1,5) <= 1 then
5047			goods[stationAsimov] = {{"food",math.random(5,10),1},{"medicine",5,5},{"tractor",5,48}}
5048		else
5049			goods[stationAsimov] = {{"food",math.random(5,10),1},{"tractor",5,48}}
5050		end
5051	else
5052		goods[stationAsimov] = {{"tractor",5,48}}
5053	end
5054	stationAsimov.publicRelations = true
5055	stationAsimov.generalInformation = "We train naval cadets in routine and specialized functions aboard space vessels and coordinate naval activity throughout the sector"
5056	stationAsimov.stationHistory = "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"
5057	return stationAsimov
5058end
5059function placeBarclay()
5060	--Barclay
5061	stationBarclay = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation)
5062	stationBarclay:setPosition(psx,psy):setCallSign("Barclay"):setDescription("Communication components")
5063	if stationFaction ~= "Independent" then
5064		if random(1,5) <= 1 then
5065			goods[stationBarclay] = {{"food",math.random(5,10),1},{"medicine",5,5},{"communication",5,58}}
5066		else
5067			goods[stationBarclay] = {{"food",math.random(5,10),1},{"communication",5,58}}
5068			tradeMedicine[stationBarclay] = true
5069		end
5070	else
5071		goods[stationBarclay] = {{"communication",5,58}}
5072		tradeMedicine[stationBarclay] = true
5073	end
5074	stationBarclay.publicRelations = true
5075	stationBarclay.generalInformation = "We provide a range of communication equipment and software for use aboard ships"
5076	stationBarclay.stationHistory = "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"
5077	return stationBarclay
5078end
5079function placeBethesda()
5080	--Bethesda
5081	stationBethesda = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation)
5082	stationBethesda:setPosition(psx,psy):setCallSign("Bethesda"):setDescription("Medical research")
5083	goods[stationBethesda] = {{"food",math.random(5,10),1},{"medicine",5,5},{"autodoc",5,36}}
5084	stationBethesda.publicRelations = true
5085	stationBethesda.generalInformation = "We research and treat exotic medical conditions"
5086	stationBethesda.stationHistory = "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"
5087	return stationBethesda
5088end
5089function placeBroeck()
5090	--Broeck
5091	stationBroeck = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation)
5092	stationBroeck:setPosition(psx,psy):setCallSign("Broeck"):setDescription("Warp drive components")
5093	if stationFaction ~= "Independent" then
5094		if random(1,5) <= 1 then
5095			goods[stationBroeck] = {{"food",math.random(5,10),1},{"medicine",5,5},{"warp",5,130}}
5096			if random(1,100) < 62 then tradeLuxury[stationBroeck] = true end
5097		else
5098			goods[stationBroeck] = {{"food",math.random(5,10),1},{"warp",5,130}}
5099			if random(1,100) < 53 then tradeMedicine[stationBroeck] = true end
5100			if random(1,100) < 62 then tradeLuxury[stationBroeck] = true end
5101		end
5102	else
5103		goods[stationBroeck] = {{"warp",5,130}}
5104		if random(1,100) < 53 then tradeMedicine[stationBroeck] = true end
5105		if random(1,100) < 14 then tradeFood[stationBroeck] = true end
5106		if random(1,100) < 62 then tradeLuxury[stationBroeck] = true end
5107	end
5108	stationBroeck.publicRelations = true
5109	stationBroeck.generalInformation = "We provide warp drive engines and components"
5110	stationBroeck.stationHistory = "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"
5111	return stationBroeck
5112end
5113function placeCalifornia()
5114	--California
5115	stationCalifornia = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation)
5116	stationCalifornia:setPosition(psx,psy):setCallSign("California"):setDescription("Mining station")
5117	if stationFaction ~= "Independent" then
5118		if random(1,5) <= 1 then
5119			goods[stationCalifornia] = {{"food",math.random(5,10),1},{"medicine",5,5},{"gold",5,25},{"dilithium",2,25}}
5120		else
5121			goods[stationCalifornia] = {{"food",math.random(5,10),1},{"gold",5,25},{"dilithium",2,25}}
5122		end
5123	else
5124		goods[stationCalifornia] = {{"gold",5,25},{"dilithium",2,25}}
5125	end
5126	return stationCalifornia
5127end
5128function placeCalvin()
5129	--Calvin
5130	stationCalvin = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation)
5131	stationCalvin:setPosition(psx,psy):setCallSign("Calvin"):setDescription("Robotic research")
5132	if stationFaction ~= "Independent" then
5133		if random(1,5) <= 1 then
5134			goods[stationCalvin] = {{"food",math.random(5,10),1},{"medicine",5,5},{"robotic",5,87}}
5135		else
5136			goods[stationCalvin] = {{"food",math.random(5,10),1},{"robotic",5,87}}
5137		end
5138	else
5139		goods[stationCalvin] = {{"robotic",5,87}}
5140		if random(1,100) < 8 then tradeFood[stationCalvin] = true end
5141	end
5142	tradeLuxury[stationCalvin] = true
5143	stationCalvin.publicRelations = true
5144	stationCalvin.generalInformation = "We research and provide robotic systems and components"
5145	stationCalvin.stationHistory = "This station is named after Dr. Susan Calvin who pioneered robotic behavioral research and programming"
5146	return stationCalvin
5147end
5148function placeCavor()
5149	--Cavor
5150	stationCavor = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation)
5151	stationCavor:setPosition(psx,psy):setCallSign("Cavor"):setDescription("Advanced Material components")
5152	if stationFaction ~= "Independent" then
5153		if random(1,5) <= 1 then
5154			goods[stationCavor] = {{"food",math.random(5,10),1},{"medicine",5,5},{"filament",5,42}}
5155			if random(1,100) < 33 then tradeLuxury[stationCavor] = true end
5156		else
5157			goods[stationCavor] = {{"food",math.random(5,10),1},{"filament",5,42}}
5158			if random(1,100) < 50 then
5159				tradeMedicine[stationCavor] = true
5160			else
5161				tradeLuxury[stationCavor] = true
5162			end
5163		end
5164	else
5165		goods[stationCavor] = {{"filament",5,42}}
5166		whatTrade = random(1,100)
5167		if whatTrade < 33 then
5168			tradeMedicine[stationCavor] = true
5169		elseif whatTrade > 66 then
5170			tradeFood[stationCavor] = true
5171		else
5172			tradeLuxury[stationCavor] = true
5173		end
5174	end
5175	stationCavor.publicRelations = true
5176	stationCavor.generalInformation = "We fabricate several different kinds of materials critical to various space industries like ship building, station construction and mineral extraction"
5177	stationCavor.stationHistory = "We named our station after Dr. Cavor, the physicist that invented a barrier material for gravity waves - Cavorite"
5178	return stationCavor
5179end
5180function placeChatuchak()
5181	--Chatuchak
5182	stationChatuchak = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation)
5183	stationChatuchak:setPosition(psx,psy):setCallSign("Chatuchak"):setDescription("Trading station")
5184	if stationFaction ~= "Independent" then
5185		if random(1,5) <= 1 then
5186			goods[stationChatuchak] = {{"food",math.random(5,10),1},{"medicine",5,5},{"luxury",5,60}}
5187		else
5188			goods[stationChatuchak] = {{"food",math.random(5,10),1},{"luxury",5,60}}
5189		end
5190	else
5191		goods[stationChatuchak] = {{"luxury",5,60}}
5192	end
5193	stationChatuchak.publicRelations = true
5194	stationChatuchak.generalInformation = "Only the largest market and trading location in twenty sectors. You can find your heart's desire here"
5195	stationChatuchak.stationHistory = "Modeled after the early 21st century bazaar on Earth in Bangkok, Thailand. Designed and built with trade and commerce in mind"
5196	return stationChatuchak
5197end
5198function placeCoulomb()
5199	--Coulomb
5200	stationCoulomb = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation)
5201	stationCoulomb:setPosition(psx,psy):setCallSign("Coulomb"):setDescription("Shielded circuitry fabrication")
5202	if stationFaction ~= "Independent" then
5203		if random(1,5) <= 1 then
5204			goods[stationCoulomb] = {{"food",math.random(5,10),1},{"medicine",5,5},{"circuit",5,50}}
5205		else
5206			goods[stationCoulomb] = {{"food",math.random(5,10),1},{"circuit",5,50}}
5207			if random(1,100) < 27 then tradeMedicine[stationCoulomb] = true end
5208		end
5209	else
5210		goods[stationCoulomb] = {{"circuit",5,50}}
5211		if random(1,100) < 27 then tradeMedicine[stationCoulomb] = true end
5212		if random(1,100) < 16 then tradeFood[stationCoulomb] = true end
5213	end
5214	if random(1,100) < 82 then tradeLuxury[stationCoulomb] = true end
5215	stationCoulomb.publicRelations = true
5216	stationCoulomb.generalInformation = "We make a large variety of circuits for numerous ship systems shielded from sensor detection and external control interference"
5217	stationCoulomb.stationHistory = "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"
5218	return stationCoulomb
5219end
5220function placeCyrus()
5221	--Cyrus
5222	stationCyrus = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation)
5223	stationCyrus:setPosition(psx,psy):setCallSign("Cyrus"):setDescription("Impulse engine components")
5224	if stationFaction ~= "Independent" then
5225		if random(1,5) <= 1 then
5226			goods[stationCyrus] = {{"food",math.random(5,10),1},{"medicine",5,5},{"impulse",5,124}}
5227		else
5228			goods[stationCyrus] = {{"food",math.random(5,10),1},{"impulse",5,124}}
5229			if random(1,100) < 34 then tradeMedicine[stationCyrus] = true end
5230		end
5231	else
5232		goods[stationCyrus] = {{"impulse",5,124}}
5233		if random(1,100) < 34 then tradeMedicine[stationCyrus] = true end
5234		if random(1,100) < 13 then tradeFood[stationCyrus] = true end
5235	end
5236	if random(1,100) < 78 then tradeLuxury[stationCyrus] = true end
5237	stationCyrus.publicRelations = true
5238	stationCyrus.generalInformation = "We supply high quality impulse engines and parts for use aboard ships"
5239	stationCyrus.stationHistory = "This station was named after the fictional engineer, Cyrus Smith created by 19th century author Jules Verne"
5240	return stationCyrus
5241end
5242function placeDeckard()
5243	--Deckard
5244	stationDeckard = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation)
5245	stationDeckard:setPosition(psx,psy):setCallSign("Deckard"):setDescription("Android components")
5246	if stationFaction ~= "Independent" then
5247		if random(1,5) <= 1 then
5248			goods[stationDeckard] = {{"food",math.random(5,10),1},{"medicine",5,5},{"android",5,73}}
5249		else
5250			goods[stationDeckard] = {{"food",math.random(5,10),1},{"android",5,73}}
5251		end
5252	else
5253		goods[stationDeckard] = {{"android",5,73}}
5254		tradeFood[stationDeckard] = true
5255	end
5256	tradeLuxury[stationDeckard] = true
5257	stationDeckard.publicRelations = true
5258	stationDeckard.generalInformation = "Supplier of android components, programming and service"
5259	stationDeckard.stationHistory = "Named for Richard Deckard who inspired many of the sophisticated safety security algorithms now required for all androids"
5260	return stationDeckard
5261end
5262function placeDeer()
5263	--Deer
5264	stationDeer = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation)
5265	stationDeer:setPosition(psx,psy):setCallSign("Deer"):setDescription("Repulsor and Tractor Beam Components")
5266	if stationFaction ~= "Independent" then
5267		if random(1,5) <= 1 then
5268			goods[stationDeer] = {{"food",math.random(5,10),1},{"medicine",5,5},{"tractor",5,90},{"repulsor",5,95}}
5269		else
5270			goods[stationDeer] = {{"food",math.random(5,10),1},{"tractor",5,90},{"repulsor",5,95}}
5271			tradeMedicine[stationDeer] = true
5272		end
5273	else
5274		goods[stationDeer] = {{"tractor",5,90},{"repulsor",5,95}}
5275		tradeFood[stationDeer] = true
5276		tradeMedicine[stationDeer] = true
5277	end
5278	tradeLuxury[stationDeer] = true
5279	stationDeer.publicRelations = true
5280	stationDeer.generalInformation = "We can meet all your pushing and pulling needs with specialized equipment custom made"
5281	stationDeer.stationHistory = "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"
5282	return stationDeer
5283end
5284function placeErickson()
5285	--Erickson
5286	stationErickson = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation)
5287	stationErickson:setPosition(psx,psy):setCallSign("Erickson"):setDescription("Transporter components")
5288	if stationFaction ~= "Independent" then
5289		if random(1,5) <= 1 then
5290			goods[stationErickson] = {{"food",math.random(5,10),1},{"medicine",5,5},{"transporter",5,63}}
5291		else
5292			goods[stationErickson] = {{"food",math.random(5,10),1},{"transporter",5,63}}
5293			tradeMedicine[stationErickson] = true
5294		end
5295	else
5296		goods[stationErickson] = {{"transporter",5,63}}
5297		tradeFood[stationErickson] = true
5298		tradeMedicine[stationErickson] = true
5299	end
5300	tradeLuxury[stationErickson] = true
5301	stationErickson.publicRelations = true
5302	stationErickson.generalInformation = "We provide transporters used aboard ships as well as the components for repair and maintenance"
5303	stationErickson.stationHistory = "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"
5304	return stationErickson
5305end
5306function placeEvondos()
5307	--Evondos
5308	stationEvondos = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation)
5309	stationEvondos:setPosition(psx,psy):setCallSign("Evondos"):setDescription("Autodoc components")
5310	if stationFaction ~= "Independent" then
5311		if random(1,5) <= 1 then
5312			goods[stationEvondos] = {{"food",math.random(5,10),1},{"medicine",5,5},{"autodoc",5,56}}
5313		else
5314			goods[stationEvondos] = {{"food",math.random(5,10),1},{"autodoc",5,56}}
5315			tradeMedicine[stationEvondos] = true
5316		end
5317	else
5318		goods[stationEvondos] = {{"autodoc",5,56}}
5319		tradeMedicine[stationEvondos] = true
5320	end
5321	if random(1,100) < 41 then tradeLuxury[stationEvondos] = true end
5322	stationEvondos.publicRelations = true
5323	stationEvondos.generalInformation = "We provide components for automated medical machinery"
5324	stationEvondos.stationHistory = "The station is the evolution of the company that started automated pharmaceutical dispensing in the early 21st century on Earth in Finland"
5325	return stationEvondos
5326end
5327function placeFeynman()
5328	--Feynman
5329	stationFeynman = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation)
5330	stationFeynman:setPosition(psx,psy):setCallSign("Feynman"):setDescription("Nanotechnology research")
5331	if stationFaction ~= "Independent" then
5332		if random(1,5) <= 1 then
5333			goods[stationFeynman] = {{"food",math.random(5,10),1},{"medicine",5,5},{"nanites",5,79},{"software",5,115}}
5334		else
5335			goods[stationFeynman] = {{"food",math.random(5,10),1},{"nanites",5,79},{"software",5,115}}
5336		end
5337	else
5338		goods[stationFeynman] = {{"nanites",5,79},{"software",5,115}}
5339		tradeFood[stationFeynman] = true
5340		if random(1,100) < 26 then tradeFood[stationFeynman] = true end
5341	end
5342	tradeLuxury[stationFeynman] = true
5343	stationFeynman.publicRelations = true
5344	stationFeynman.generalInformation = "We provide nanites and software for a variety of ship-board systems"
5345	stationFeynman.stationHistory = "This station's name recognizes one of the first scientific researchers into nanotechnology, physicist Richard Feynman"
5346	return stationFeynman
5347end
5348function placeGrasberg()
5349	--Grasberg
5350	local asteroid_list = placeRandomAroundPointList(Asteroid,15,1,15000,psx,psy)
5351	for _, ta in ipairs(asteroid_list) do
5352		table.insert(terrain_objects,ta)
5353	end
5354	stationGrasberg = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation)
5355	stationGrasberg:setPosition(psx,psy):setCallSign("Grasberg"):setDescription("Mining")
5356	stationGrasberg.asteroid_list = asteroid_list
5357	stationGrasberg.publicRelations = true
5358	stationGrasberg.generalInformation = "We mine nearby asteroids for precious minerals and process them for sale"
5359	stationGrasberg.stationHistory = "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"
5360	grasbergGoods = random(1,100)
5361	if stationFaction ~= "Independent" then
5362		if random(1,5) <= 1 then
5363			if grasbergGoods < 20 then
5364				goods[stationGrasberg] = {{"luxury",5,70},{"gold",5,25},{"cobalt",4,50},{"food",math.random(5,10),1},{"medicine",5,5}}
5365			elseif grasbergGoods < 40 then
5366				goods[stationGrasberg] = {{"luxury",5,70},{"gold",5,25},{"food",math.random(5,10),1},{"medicine",5,5}}
5367			elseif grasbergGoods < 60 then
5368				goods[stationGrasberg] = {{"luxury",5,70},{"cobalt",4,50},{"food",math.random(5,10),1},{"medicine",5,5}}
5369			else
5370				goods[stationGrasberg] = {{"luxury",5,70},{"food",math.random(5,10),1},{"medicine",5,5}}
5371			end
5372		else
5373			if grasbergGoods < 20 then
5374				goods[stationGrasberg] = {{"luxury",5,70},{"gold",5,25},{"cobalt",4,50},{"food",math.random(5,10),1}}
5375			elseif grasbergGoods < 40 then
5376				goods[stationGrasberg] = {{"luxury",5,70},{"gold",5,25},{"food",math.random(5,10),1}}
5377			elseif grasbergGoods < 60 then
5378				goods[stationGrasberg] = {{"luxury",5,70},{"cobalt",4,50},{"food",math.random(5,10),1}}
5379			else
5380				goods[stationGrasberg] = {{"luxury",5,70},{"food",math.random(5,10),1}}
5381			end
5382		end
5383	else
5384		if grasbergGoods < 20 then
5385			goods[stationGrasberg] = {{"luxury",5,70},{"gold",5,25},{"cobalt",4,50}}
5386		elseif grasbergGoods < 40 then
5387			goods[stationGrasberg] = {{"luxury",5,70},{"gold",5,25}}
5388		elseif grasbergGoods < 60 then
5389			goods[stationGrasberg] = {{"luxury",5,70},{"cobalt",4,50}}
5390		else
5391			goods[stationGrasberg] = {{"luxury",5,70}}
5392		end
5393		tradeFood[stationGrasberg] = true
5394	end
5395	return stationGrasberg
5396end
5397function placeHayden()
5398	--Hayden
5399	stationHayden = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation)
5400	stationHayden:setPosition(psx,psy):setCallSign("Hayden"):setDescription("Observatory and stellar mapping")
5401	if stationFaction ~= "Independent" then
5402		if random(1,5) <= 1 then
5403			goods[stationHayden] = {{"food",math.random(5,10),1},{"medicine",5,5},{"nanites",5,65}}
5404		else
5405			goods[stationHayden] = {{"food",math.random(5,10),1},{"nanites",5,65}}
5406		end
5407	else
5408		goods[stationHayden] = {{"nanites",5,65}}
5409	end
5410	stationHayden.publicRelations = true
5411	stationHayden.generalInformation = "We study the cosmos and map stellar phenomena. We also track moving asteroids. Look out! Just kidding"
5412	return stationHayden
5413end
5414function placeHeyes()
5415	--Heyes
5416	stationHeyes = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation)
5417	stationHeyes:setPosition(psx,psy):setCallSign("Heyes"):setDescription("Sensor components")
5418	if stationFaction ~= "Independent" then
5419		if random(1,5) <= 1 then
5420			goods[stationHeyes] = {{"food",math.random(5,10),1},{"medicine",5,5},{"sensor",5,72}}
5421		else
5422			goods[stationHeyes] = {{"food",math.random(5,10),1},{"sensor",5,72}}
5423		end
5424	else
5425		goods[stationHeyes] = {{"sensor",5,72}}
5426	end
5427	tradeLuxury[stationHeyes] = true
5428	stationHeyes.publicRelations = true
5429	stationHeyes.generalInformation = "We research and manufacture sensor components and systems"
5430	stationHeyes.stationHistory = "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"
5431	return stationHeyes
5432end
5433function placeHossam()
5434	--Hossam
5435	stationHossam = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation)
5436	stationHossam:setPosition(psx,psy):setCallSign("Hossam"):setDescription("Nanite supplier")
5437	if stationFaction ~= "Independent" then
5438		if random(1,5) <= 1 then
5439			goods[stationHossam] = {{"food",math.random(5,10),1},{"medicine",5,5},{"nanites",5,48}}
5440		else
5441			goods[stationHossam] = {{"food",math.random(5,10),1},{"nanites",5,48}}
5442			if random(1,100) < 44 then tradeMedicine[stationHossam] = true end
5443		end
5444	else
5445		goods[stationHossam] = {{"nanites",5,48}}
5446		if random(1,100) < 44 then tradeMedicine[stationHossam] = true end
5447		if random(1,100) < 24 then tradeFood[stationHossam] = true end
5448	end
5449	if random(1,100) < 63 then tradeLuxury[stationHossam] = true end
5450	stationHossam.publicRelations = true
5451	stationHossam.generalInformation = "We provide nanites for various organic and non-organic systems"
5452	stationHossam.stationHistory = "This station is named after the nanotechnologist Hossam Haick from the early 21st century on Earth in Israel"
5453	return stationHossam
5454end
5455function placeImpala()
5456	--Impala
5457	local asteroid_list = placeRandomAroundPointList(Asteroid,15,1,15000,psx,psy)
5458	for _, ta in ipairs(asteroid_list) do
5459		table.insert(terrain_objects,ta)
5460	end
5461	stationImpala = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation)
5462	stationImpala:setPosition(psx,psy):setCallSign("Impala"):setDescription("Mining")
5463	stationImpala.asteroid_list = asteroid_list
5464	tradeFood[stationImpala] = true
5465	tradeLuxury[stationImpala] = true
5466	stationImpala.publicRelations = true
5467	stationImpala.generalInformation = "We mine nearby asteroids for precious minerals"
5468	impalaGoods = random(1,100)
5469	if stationFaction ~= "Independent" then
5470		if random(1,5) <= 1 then
5471			if impalaGoods < 20 then
5472				goods[stationImpala] = {{"luxury",5,70},{"gold",5,25},{"cobalt",4,50},{"food",math.random(5,10),1},{"medicine",5,5}}
5473			elseif impalaGoods < 40 then
5474				goods[stationImpala] = {{"luxury",5,70},{"gold",5,25},{"food",math.random(5,10),1},{"medicine",5,5}}
5475			elseif impalaGoods < 60 then
5476				goods[stationImpala] = {{"luxury",5,70},{"cobalt",4,50},{"food",math.random(5,10),1},{"medicine",5,5}}
5477			else
5478				goods[stationImpala] = {{"luxury",5,70},{"food",math.random(5,10),1},{"medicine",5,5}}
5479			end
5480		else
5481			if impalaGoods < 20 then
5482				goods[stationImpala] = {{"luxury",5,70},{"gold",5,25},{"cobalt",4,50},{"food",math.random(5,10),1}}
5483			elseif impalaGoods < 40 then
5484				goods[stationImpala] = {{"luxury",5,70},{"gold",5,25},{"food",math.random(5,10),1}}
5485			elseif impalaGoods < 60 then
5486				goods[stationImpala] = {{"luxury",5,70},{"cobalt",4,50},{"food",math.random(5,10),1}}
5487			else
5488				goods[stationImpala] = {{"luxury",5,70},{"food",math.random(5,10),1}}
5489			end
5490		end
5491	else
5492		if impalaGoods < 20 then
5493			goods[stationImpala] = {{"luxury",5,70},{"gold",5,25},{"cobalt",4,50}}
5494		elseif impalaGoods < 40 then
5495			goods[stationImpala] = {{"luxury",5,70},{"gold",5,25}}
5496		elseif impalaGoods < 60 then
5497			goods[stationImpala] = {{"luxury",5,70},{"cobalt",4,50}}
5498		else
5499			goods[stationImpala] = {{"luxury",5,70}}
5500		end
5501		tradeFood[stationImpala] = true
5502	end
5503	return stationImpala
5504end
5505function placeKomov()
5506	--Komov
5507	stationKomov = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation)
5508	stationKomov:setPosition(psx,psy):setCallSign("Komov"):setDescription("Xenopsychology training")
5509	if stationFaction ~= "Independent" then
5510		if random(1,5) <= 1 then
5511			goods[stationKomov] = {{"food",math.random(5,10),1},{"medicine",5,5},{"filament",5,46}}
5512		else
5513			goods[stationKomov] = {{"food",math.random(5,10),1},{"filament",5,46}}
5514			if random(1,100) < 44 then tradeMedicine[stationKomov] = true end
5515		end
5516	else
5517		goods[stationKomov] = {{"filament",5,46}}
5518		if random(1,100) < 44 then tradeMedicine[stationKomov] = true end
5519		if random(1,100) < 24 then tradeFood[stationKomov] = true end
5520	end
5521	stationKomov.publicRelations = true
5522	stationKomov.generalInformation = "We provide classes and simulation to help train diverse species in how to relate to each other"
5523	stationKomov.stationHistory = "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"
5524	return stationKomov
5525end
5526function placeKrak()
5527	--Krak
5528	stationKrak = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation)
5529	stationKrak:setPosition(psx,psy):setCallSign("Krak"):setDescription("Mining station")
5530	posAxisKrak = random(0,360)
5531	posKrak = random(10000,60000)
5532	negKrak = random(10000,60000)
5533	spreadKrak = random(4000,7000)
5534	negAxisKrak = posAxisKrak + 180
5535	xPosAngleKrak, yPosAngleKrak = vectorFromAngle(posAxisKrak, posKrak)
5536	posKrakEnd = random(30,70)
5537	local asteroid_list = createRandomAlongArc(Asteroid, 30+posKrakEnd, psx+xPosAngleKrak, psy+yPosAngleKrak, posKrak, negAxisKrak, negAxisKrak+posKrakEnd, spreadKrak)
5538	xNegAngleKrak, yNegAngleKrak = vectorFromAngle(negAxisKrak, negKrak)
5539	negKrakEnd = random(40,80)
5540	local more_asteroids = createRandomAlongArc(Asteroid, 30+negKrakEnd, psx+xNegAngleKrak, psy+yNegAngleKrak, negKrak, posAxisKrak, posAxisKrak+negKrakEnd, spreadKrak)
5541	for _, ta in ipairs(more_asteroids) do
5542		table.insert(asteroid_list,ta)
5543	end
5544	for _, ta in ipairs(asteroid_list) do
5545		table.insert(terrain_objects,ta)
5546	end
5547	stationKrak.asteroid_list = asteroid_list
5548	if random(1,100) < 50 then tradeFood[stationKrak] = true end
5549	if random(1,100) < 50 then tradeLuxury[stationKrak] = true end
5550	krakGoods = random(1,100)
5551	if krakGoods < 10 then
5552		goods[stationKrak] = {{"nickel",5,20},{"platinum",5,70},{"tritanium",5,50},{"dilithium",5,50}}
5553	elseif krakGoods < 20 then
5554		goods[stationKrak] = {{"nickel",5,20},{"platinum",5,70},{"tritanium",5,50}}
5555	elseif krakGoods < 30 then
5556		goods[stationKrak] = {{"nickel",5,20},{"platinum",5,70},{"dilithium",5,50}}
5557	elseif krakGoods < 40 then
5558		goods[stationKrak] = {{"nickel",5,20},{"tritanium",5,50},{"dilithium",5,50}}
5559	elseif krakGoods < 50 then
5560		goods[stationKrak] = {{"nickel",5,20},{"dilithium",5,50}}
5561	elseif krakGoods < 60 then
5562		goods[stationKrak] = {{"nickel",5,20},{"platinum",5,70}}
5563	elseif krakGoods < 70 then
5564		goods[stationKrak] = {{"nickel",5,20},{"tritanium",5,50}}
5565	elseif krakGoods < 80 then
5566		goods[stationKrak] = {{"platinum",5,70},{"tritanium",5,50},{"dilithium",5,50}}
5567	else
5568		goods[stationKrak] = {{"nickel",5,20}}
5569	end
5570	tradeMedicine[stationKrak] = true
5571	return stationKrak
5572end
5573function placeKruk()
5574	--Kruk
5575	stationKruk = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation)
5576	stationKruk:setPosition(psx,psy):setCallSign("Kruk"):setDescription("Mining station")
5577	posAxisKruk = random(0,360)
5578	posKruk = random(10000,60000)
5579	negKruk = random(10000,60000)
5580	spreadKruk = random(4000,7000)
5581	negAxisKruk = posAxisKruk + 180
5582	xPosAngleKruk, yPosAngleKruk = vectorFromAngle(posAxisKruk, posKruk)
5583	posKrukEnd = random(30,70)
5584	local asteroid_list = createRandomAlongArc(Asteroid, 30+posKrukEnd, psx+xPosAngleKruk, psy+yPosAngleKruk, posKruk, negAxisKruk, negAxisKruk+posKrukEnd, spreadKruk)
5585	xNegAngleKruk, yNegAngleKruk = vectorFromAngle(negAxisKruk, negKruk)
5586	negKrukEnd = random(40,80)
5587	local more_asteroids = createRandomAlongArc(Asteroid, 30+negKrukEnd, psx+xNegAngleKruk, psy+yNegAngleKruk, negKruk, posAxisKruk, posAxisKruk+negKrukEnd, spreadKruk)
5588	for _, ta in ipairs(more_asteroids) do
5589		table.insert(asteroid_list,ta)
5590	end
5591	for _, ta in ipairs(asteroid_list) do
5592		table.insert(terrain_objects,ta)
5593	end
5594	stationKruk.asteroid_list = asteroid_list
5595	krukGoods = random(1,100)
5596	if krukGoods < 10 then
5597		goods[stationKruk] = {{"nickel",5,20},{"platinum",5,70},{"tritanium",5,50},{"dilithium",5,50}}
5598	elseif krukGoods < 20 then
5599		goods[stationKruk] = {{"nickel",5,20},{"platinum",5,70},{"tritanium",5,50}}
5600	elseif krukGoods < 30 then
5601		goods[stationKruk] = {{"nickel",5,20},{"platinum",5,70},{"dilithium",5,50}}
5602	elseif krukGoods < 40 then
5603		goods[stationKruk] = {{"nickel",5,20},{"tritanium",5,50},{"dilithium",5,50}}
5604	elseif krukGoods < 50 then
5605		goods[stationKruk] = {{"nickel",5,20},{"dilithium",5,50}}
5606	elseif krukGoods < 60 then
5607		goods[stationKruk] = {{"nickel",5,20},{"platinum",5,70}}
5608	elseif krukGoods < 70 then
5609		goods[stationKruk] = {{"nickel",5,20},{"tritanium",5,50}}
5610	elseif krukGoods < 80 then
5611		goods[stationKruk] = {{"platinum",5,70},{"tritanium",5,50},{"dilithium",5,50}}
5612	else
5613		goods[stationKruk] = {{"nickel",5,20}}
5614	end
5615	tradeLuxury[stationKruk] = true
5616	if random(1,100) < 50 then tradeFood[stationKruk] = true end
5617	if random(1,100) < 50 then tradeMedicine[stationKruk] = true end
5618	return stationKruk
5619end
5620function placeLipkin()
5621	--Lipkin
5622	stationLipkin = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation)
5623	stationLipkin:setPosition(psx,psy):setCallSign("Lipkin"):setDescription("Autodoc components")
5624	if stationFaction ~= "Independent" then
5625		if random(1,5) <= 1 then
5626			goods[stationLipkin] = {{"food",math.random(5,10),1},{"medicine",5,5},{"autodoc",5,76}}
5627		else
5628			goods[stationLipkin] = {{"food",math.random(5,10),1},{"autodoc",5,76}}
5629		end
5630	else
5631		goods[stationLipkin] = {{"autodoc",5,76}}
5632		tradeFood[stationLipkin] = true
5633	end
5634	tradeLuxury[stationLipkin] = true
5635	stationLipkin.publicRelations = true
5636	stationLipkin.generalInformation = "We build and repair and provide components and upgrades for automated facilities designed for ships where a doctor cannot be a crew member (commonly called autodocs)"
5637	stationLipkin.stationHistory = "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"
5638	return stationLipkin
5639end
5640function placeMadison()
5641	--Madison
5642	stationMadison = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation)
5643	stationMadison:setPosition(psx,psy):setCallSign("Madison"):setDescription("Zero gravity sports and entertainment")
5644	if stationFaction ~= "Independent" then
5645		if random(1,5) <= 1 then
5646			goods[stationMadison] = {{"food",math.random(5,10),1},{"medicine",5,5},{"luxury",5,70}}
5647		else
5648			goods[stationMadison] = {{"food",math.random(5,10),1},{"luxury",5,70}}
5649			tradeMedicine[stationMadison] = true
5650		end
5651	else
5652		goods[stationMadison] = {{"luxury",5,70}}
5653		tradeMedicine[stationMadison] = true
5654	end
5655	stationMadison.publicRelations = true
5656	stationMadison.generalInformation = "Come take in a game or two or perhaps see a show"
5657	stationMadison.stationHistory = "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"
5658	return stationMadison
5659end
5660function placeMaiman()
5661	--Maiman
5662	stationMaiman = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation)
5663	stationMaiman:setPosition(psx,psy):setCallSign("Maiman"):setDescription("Energy beam components")
5664	if stationFaction ~= "Independent" then
5665		if random(1,5) <= 1 then
5666			goods[stationMaiman] = {{"food",math.random(5,10),1},{"medicine",5,5},{"beam",5,70}}
5667		else
5668			goods[stationMaiman] = {{"food",math.random(5,10),1},{"beam",5,70}}
5669			tradeMedicine[stationMaiman] = true
5670		end
5671	else
5672		goods[stationMaiman] = {{"beam",5,70}}
5673		tradeMedicine[stationMaiman] = true
5674	end
5675	stationMaiman.publicRelations = true
5676	stationMaiman.generalInformation = "We research and manufacture energy beam components and systems"
5677	stationMaiman.stationHistory = "The station is named after Theodore Maiman who researched and built the first laser in the mid 20th centuryon Earth"
5678	return stationMaiman
5679end
5680function placeMarconi()
5681	--Marconi
5682	stationMarconi = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation)
5683	stationMarconi:setPosition(psx,psy):setCallSign("Marconi"):setDescription("Energy Beam Components")
5684	if stationFaction ~= "Independent" then
5685		if random(1,5) <= 1 then
5686			goods[stationMarconi] = {{"food",math.random(5,10),1},{"medicine",5,5},{"beam",5,80}}
5687		else
5688			goods[stationMarconi] = {{"food",math.random(5,10),1},{"beam",5,80}}
5689			tradeMedicine[stationMarconi] = true
5690		end
5691	else
5692		goods[stationMarconi] = {{"beam",5,80}}
5693		tradeMedicine[stationMarconi] = true
5694		tradeFood[stationMarconi] = true
5695	end
5696	tradeLuxury[stationMarconi] = true
5697	stationMarconi.publicRelations = true
5698	stationMarconi.generalInformation = "We manufacture energy beam components"
5699	stationMarconi.stationHistory = "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"
5700	return stationMarconi
5701end
5702function placeMayo()
5703	--Mayo
5704	stationMayo = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation)
5705	stationMayo:setPosition(psx,psy):setCallSign("Mayo"):setDescription("Medical Research")
5706	goods[stationMayo] = {{"food",5,1},{"medicine",5,5},{"autodoc",5,128}}
5707	stationMayo.publicRelations = true
5708	stationMayo.generalInformation = "We research exotic diseases and other human medical conditions"
5709	stationMayo.stationHistory = "We continue the medical work started by William Worrall Mayo in the late 19th century on Earth"
5710	return stationMayo
5711end
5712function placeMiller()
5713	--Miller
5714	stationMiller = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation)
5715	stationMiller:setPosition(psx,psy):setCallSign("Miller"):setDescription("Exobiology research")
5716	if stationFaction ~= "Independent" then
5717		if random(1,5) <= 1 then
5718			goods[stationMiller] = {{"food",math.random(5,10),1},{"medicine",5,5},{"optic",10,60}}
5719		else
5720			goods[stationMiller] = {{"food",math.random(5,10),1},{"optic",10,60}}
5721		end
5722	else
5723		goods[stationMiller] = {{"optic",10,60}}
5724	end
5725	stationMiller.publicRelations = true
5726	stationMiller.generalInformation = "We study recently discovered life forms not native to Earth"
5727	stationMiller.stationHistory = "This station was named after one the early exobiologists from mid 20th century Earth, Dr. Stanley Miller"
5728	return stationMiller
5729end
5730function placeMuddville()
5731	--Muddville
5732	stationMudd = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation)
5733	stationMudd:setPosition(psx,psy):setCallSign("Muddville"):setDescription("Trading station")
5734	if stationFaction ~= "Independent" then
5735		if random(1,5) <= 1 then
5736			goods[stationMudd] = {{"food",math.random(5,10),1},{"medicine",5,5},{"luxury",10,60}}
5737		else
5738			goods[stationMudd] = {{"food",math.random(5,10),1},{"luxury",10,60}}
5739		end
5740	else
5741		goods[stationMudd] = {{"luxury",10,60}}
5742	end
5743	stationMudd.publicRelations = true
5744	stationMudd.generalInformation = "Come to Muddvile for all your trade and commerce needs and desires"
5745	stationMudd.stationHistory = "Upon retirement, Harry Mudd started this commercial venture using his leftover inventory and extensive connections obtained while he traveled the stars as a salesman"
5746	return stationMudd
5747end
5748function placeNexus6()
5749	--Nexus-6
5750	stationNexus6 = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation)
5751	stationNexus6:setPosition(psx,psy):setCallSign("Nexus-6"):setDescription("Android components")
5752	if stationFaction ~= "Independent" then
5753		if random(1,5) <= 1 then
5754			goods[stationNexus6] = {{"food",math.random(5,10),1},{"medicine",5,5},{"android",5,93}}
5755		else
5756			goods[stationNexus6] = {{"food",math.random(5,10),1},{"android",5,93}}
5757			tradeMedicine[stationNexus6] = true
5758		end
5759	else
5760		goods[stationNexus6] = {{"android",5,93}}
5761		tradeMedicine[stationNexus6] = true
5762	end
5763	stationNexus6.publicRelations = true
5764	stationNexus6.generalInformation = "We research and manufacture android components and systems. Our design our androids to maximize their likeness to humans"
5765	stationNexus6.stationHistory = "The station is named after the ground breaking model of android produced by the Tyrell corporation"
5766	return stationNexus6
5767end
5768function placeOBrien()
5769	--O'Brien
5770	stationOBrien = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation)
5771	stationOBrien:setPosition(psx,psy):setCallSign("O'Brien"):setDescription("Transporter components")
5772	if stationFaction ~= "Independent" then
5773		if random(1,5) <= 1 then
5774			goods[stationOBrien] = {{"food",math.random(5,10),1},{"medicine",5,5},{"transporter",5,76}}
5775		else
5776			goods[stationOBrien] = {{"food",math.random(5,10),1},{"transporter",5,76}}
5777			if random(1,100) < 34 then tradeMedicine[stationOBrien] = true end
5778		end
5779	else
5780		goods[stationOBrien] = {{"transporter",5,76}}
5781		tradeMedicine[stationOBrien] = true
5782		if random(1,100) < 13 then tradeFood[stationOBrien] = true end
5783		if random(1,100) < 34 then tradeMedicine[stationOBrien] = true end
5784	end
5785	if random(1,100) < 43 then tradeLuxury[stationOBrien] = true end
5786	stationOBrien.publicRelations = true
5787	stationOBrien.generalInformation = "We research and fabricate high quality transporters and transporter components for use aboard ships"
5788	stationOBrien.stationHistory = "Miles O'Brien started this business after his experience as a transporter chief"
5789	return stationOBrien
5790end
5791function placeOlympus()
5792	--Olympus
5793	stationOlympus = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation)
5794	stationOlympus:setPosition(psx,psy):setCallSign("Olympus"):setDescription("Optical components")
5795	if stationFaction ~= "Independent" then
5796		if random(1,5) <= 1 then
5797			goods[stationOlympus] = {{"food",math.random(5,10),1},{"medicine",5,5},{"optic",5,66}}
5798		else
5799			goods[stationOlympus] = {{"food",math.random(5,10),1},{"optic",5,66}}
5800			tradeMedicine[stationOlympus] = true
5801		end
5802	else
5803		goods[stationOlympus] = {{"optic",5,66}}
5804		tradeFood[stationOlympus] = true
5805		tradeMedicine[stationOlympus] = true
5806	end
5807	stationOlympus.publicRelations = true
5808	stationOlympus.generalInformation = "We fabricate optical lenses and related equipment as well as fiber optic cabling and components"
5809	stationOlympus.stationHistory = "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"
5810	return stationOlympus
5811end
5812function placeOrgana()
5813	--Organa
5814	stationOrgana = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation)
5815	stationOrgana:setPosition(psx,psy):setCallSign("Organa"):setDescription("Diplomatic training")
5816	goods[stationOrgana] = {{"luxury",5,96}}
5817	stationOrgana.publicRelations = true
5818	stationOrgana.generalInformation = "The premeire academy for leadership and diplomacy training in the region"
5819	stationOrgana.stationHistory = "Established by the royal family so critical during the political upheaval era"
5820	return stationOrgana
5821end
5822function placeOutpost15()
5823	--Outpost 15
5824	stationOutpost15 = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation)
5825	stationOutpost15:setPosition(psx,psy):setCallSign("Outpost-15"):setDescription("Mining and trade")
5826	tradeFood[stationOutpost15] = true
5827	outpost15Goods = random(1,100)
5828	if stationFaction ~= "Independent" then
5829		if random(1,5) <= 1 then
5830			if outpost15Goods < 20 then
5831				goods[stationOutpost15] = {{"luxury",5,70},{"gold",5,25},{"cobalt",4,50},{"food",math.random(5,10),1},{"medicine",5,5}}
5832			elseif outpost15Goods < 40 then
5833				goods[stationOutpost15] = {{"luxury",5,70},{"gold",5,25},{"food",math.random(5,10),1},{"medicine",5,5}}
5834			elseif outpost15Goods < 60 then
5835				goods[stationOutpost15] = {{"luxury",5,70},{"cobalt",4,50},{"food",math.random(5,10),1},{"medicine",5,5}}
5836			else
5837				goods[stationOutpost15] = {{"luxury",5,70},{"food",math.random(5,10),1},{"medicine",5,5}}
5838			end
5839		else
5840			if outpost15Goods < 20 then
5841				goods[stationOutpost15] = {{"luxury",5,70},{"gold",5,25},{"cobalt",4,50},{"food",math.random(5,10),1}}
5842			elseif outpost15Goods < 40 then
5843				goods[stationOutpost15] = {{"luxury",5,70},{"gold",5,25},{"food",math.random(5,10),1}}
5844			elseif outpost15Goods < 60 then
5845				goods[stationOutpost15] = {{"luxury",5,70},{"cobalt",4,50},{"food",math.random(5,10),1}}
5846			else
5847				goods[stationOutpost15] = {{"luxury",5,70},{"food",math.random(5,10),1}}
5848			end
5849		end
5850	else
5851		if outpost15Goods < 20 then
5852			goods[stationOutpost15] = {{"luxury",5,70},{"gold",5,25},{"cobalt",4,50}}
5853		elseif outpost15Goods < 40 then
5854			goods[stationOutpost15] = {{"luxury",5,70},{"gold",5,25}}
5855		elseif outpost15Goods < 60 then
5856			goods[stationOutpost15] = {{"luxury",5,70},{"cobalt",4,50}}
5857		else
5858			goods[stationOutpost15] = {{"luxury",5,70}}
5859		end
5860		tradeFood[stationOutpost15] = true
5861	end
5862	local asteroid_list = placeRandomAroundPointList(Asteroid,15,1,15000,psx,psy)
5863	for _, ta in ipairs(asteroid_list) do
5864		table.insert(terrain_objects,ta)
5865	end
5866	stationOutpost15.asteroid_list = asteroid_list
5867	return stationOutpost15
5868end
5869function placeOutpost21()
5870	--Outpost 21
5871	stationOutpost21 = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation)
5872	stationOutpost21:setPosition(psx,psy):setCallSign("Outpost-21"):setDescription("Mining and gambling")
5873	local asteroid_list = placeRandomAroundPointList(Asteroid,15,1,15000,psx,psy)
5874	for _, ta in ipairs(asteroid_list) do
5875		table.insert(terrain_objects,ta)
5876	end
5877	stationOutpost21.asteroid_list = asteroid_list
5878	outpost21Goods = random(1,100)
5879	if stationFaction ~= "Independent" then
5880		if random(1,5) <= 1 then
5881			if outpost21Goods < 20 then
5882				goods[stationOutpost21] = {{"luxury",5,70},{"gold",5,25},{"cobalt",4,50},{"food",math.random(5,10),1},{"medicine",5,5}}
5883			elseif outpost21Goods < 40 then
5884				goods[stationOutpost21] = {{"luxury",5,70},{"gold",5,25},{"food",math.random(5,10),1},{"medicine",5,5}}
5885			elseif outpost21Goods < 60 then
5886				goods[stationOutpost21] = {{"luxury",5,70},{"cobalt",4,50},{"food",math.random(5,10),1},{"medicine",5,5}}
5887			else
5888				goods[stationOutpost21] = {{"luxury",5,70},{"food",math.random(5,10),1},{"medicine",5,5}}
5889			end
5890		else
5891			if outpost21Goods < 20 then
5892				goods[stationOutpost21] = {{"luxury",5,70},{"gold",5,25},{"cobalt",4,50},{"food",math.random(5,10),1}}
5893			elseif outpost21Goods < 40 then
5894				goods[stationOutpost21] = {{"luxury",5,70},{"gold",5,25},{"food",math.random(5,10),1}}
5895			elseif outpost21Goods < 60 then
5896				goods[stationOutpost21] = {{"luxury",5,70},{"cobalt",4,50},{"food",math.random(5,10),1}}
5897			else
5898				goods[stationOutpost21] = {{"luxury",5,70},{"food",math.random(5,10),1}}
5899			end
5900			if random(1,100) < 50 then tradeMedicine[stationOutpost21] = true end
5901		end
5902	else
5903		if outpost21Goods < 20 then
5904			goods[stationOutpost21] = {{"luxury",5,70},{"gold",5,25},{"cobalt",4,50}}
5905		elseif outpost21Goods < 40 then
5906			goods[stationOutpost21] = {{"luxury",5,70},{"gold",5,25}}
5907		elseif outpost21Goods < 60 then
5908			goods[stationOutpost21] = {{"luxury",5,70},{"cobalt",4,50}}
5909		else
5910			goods[stationOutpost21] = {{"luxury",5,70}}
5911		end
5912		tradeFood[stationOutpost21] = true
5913		if random(1,100) < 50 then tradeMedicine[stationOutpost21] = true end
5914	end
5915	tradeLuxury[stationOutpost21] = true
5916	return stationOutpost21
5917end
5918function placeOwen()
5919	--Owen
5920	stationOwen = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation)
5921	stationOwen:setPosition(psx,psy):setCallSign("Owen"):setDescription("Load lifters and components")
5922	if stationFaction ~= "Independent" then
5923		if random(1,5) <= 1 then
5924			goods[stationOwen] = {{"food",math.random(5,10),1},{"medicine",5,5},{"lifter",5,61}}
5925		else
5926			goods[stationOwen] = {{"food",math.random(5,10),1},{"lifter",5,61}}
5927		end
5928	else
5929		goods[stationOwen] = {{"lifter",5,61}}
5930		tradeFood[stationOwen] = true
5931	end
5932	tradeLuxury[stationOwen] = true
5933	stationOwen.publicRelations = true
5934	stationOwen.generalInformation = "We provide load lifters and components for various ship systems"
5935	stationOwen.stationHistory = "The station is named after Lars Owen. After his extensive eperience with tempermental machinery on Tatooine, he used his subject matter expertise to expand into building and manufacturing the equipment adding innovations based on his years of experience using load lifters and their relative cousins, moisture vaporators"
5936	return stationOwen
5937end
5938function placePanduit()
5939	--Panduit
5940	stationPanduit = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation)
5941	stationPanduit:setPosition(psx,psy):setCallSign("Panduit"):setDescription("Optic components")
5942	if stationFaction ~= "Independent" then
5943		if random(1,5) <= 1 then
5944			goods[stationPanduit] = {{"food",math.random(5,10),1},{"medicine",5,5},{"optic",5,79}}
5945		else
5946			goods[stationPanduit] = {{"food",math.random(5,10),1},{"optic",5,79}}
5947			if random(1,100) < 33 then tradeMedicine[stationPanduit] = true end
5948		end
5949	else
5950		goods[stationPanduit] = {{"optic",5,79}}
5951		if random(1,100) < 33 then tradeMedicine[stationPanduit] = true end
5952		if random(1,100) < 27 then tradeFood[stationPanduit] = true end
5953	end
5954	tradeLuxury[stationPanduit] = true
5955	stationPanduit.publicRelations = true
5956	stationPanduit.generalInformation = "We provide optic components for various ship systems"
5957	stationPanduit.stationHistory = "This station is an outgrowth of the Panduit corporation started in the mid 20th century on Earth in the United States"
5958	return stationPanduit
5959end
5960function placeRipley()
5961	--Ripley
5962	stationRipley = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation)
5963	stationRipley:setPosition(psx,psy):setCallSign("Ripley"):setDescription("Load lifters and components")
5964	if stationFaction ~= "Independent" then
5965		if random(1,5) <= 1 then
5966			goods[stationRipley] = {{"food",math.random(5,10),1},{"medicine",5,5},{"lifter",5,82}}
5967		else
5968			goods[stationRipley] = {{"food",math.random(5,10),1},{"lifter",5,82}}
5969			tradeMedicine[stationRipley] = true
5970		end
5971	else
5972		goods[stationRipley] = {{"lifter",5,82}}
5973		if random(1,100) < 17 then tradeFood[stationRipley] = true end
5974		tradeMedicine[stationRipley] = true
5975	end
5976	if random(1,100) < 47 then tradeLuxury[stationRipley] = true end
5977	stationRipley.publicRelations = true
5978	stationRipley.generalInformation = "We provide load lifters and components"
5979	stationRipley.stationHistory = "The station is named after Ellen Ripley who made creative and effective use of one of our load lifters when defending her ship"
5980	return stationRipley
5981end
5982function placeRutherford()
5983	--Rutherford
5984	stationRutherford = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation)
5985	stationRutherford:setPosition(psx,psy):setCallSign("Rutherford"):setDescription("Shield components and research")
5986	if stationFaction ~= "Independent" then
5987		if random(1,5) <= 1 then
5988			goods[stationRutherford] = {{"food",math.random(5,10),1},{"medicine",5,5},{"shield",5,90}}
5989		else
5990			goods[stationRutherford] = {{"food",math.random(5,10),1},{"shield",5,90}}
5991			tradeMedicine[stationRutherford] = true
5992		end
5993	else
5994		goods[stationRutherford] = {{"shield",5,90}}
5995		tradeMedicine[stationRutherford] = true
5996	end
5997	tradeMedicine[stationRutherford] = true
5998	if random(1,100) < 43 then tradeLuxury[stationRutherford] = true end
5999	stationRutherford.publicRelations = true
6000	stationRutherford.generalInformation = "We research and fabricate components for ship shield systems"
6001	stationRutherford.stationHistory = "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"
6002	return stationRutherford
6003end
6004function placeScience7()
6005	--Science 7
6006	stationScience7 = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation)
6007	stationScience7:setPosition(psx,psy):setCallSign("Science-7"):setDescription("Observatory")
6008	goods[stationScience7] = {{"food",2,1}}
6009	return stationScience7
6010end
6011function placeShawyer()
6012	--Shawyer
6013	stationShawyer = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation)
6014	stationShawyer:setPosition(psx,psy):setCallSign("Shawyer"):setDescription("Impulse engine components")
6015	if stationFaction ~= "Independent" then
6016		if random(1,5) <= 1 then
6017			goods[stationShawyer] = {{"food",math.random(5,10),1},{"medicine",5,5},{"impulse",5,100}}
6018		else
6019			goods[stationShawyer] = {{"food",math.random(5,10),1},{"impulse",5,100}}
6020			tradeMedicine[stationShawyer] = true
6021		end
6022	else
6023		goods[stationShawyer] = {{"impulse",5,100}}
6024		tradeMedicine[stationShawyer] = true
6025	end
6026	tradeLuxury[stationShawyer] = true
6027	stationShawyer.publicRelations = true
6028	stationShawyer.generalInformation = "We research and manufacture impulse engine components and systems"
6029	stationShawyer.stationHistory = "The station is named after Roger Shawyer who built the first prototype impulse engine in the early 21st century"
6030	return stationShawyer
6031end
6032function placeShree()
6033	--Shree
6034	stationShree = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation)
6035	stationShree:setPosition(psx,psy):setCallSign("Shree"):setDescription("Repulsor and tractor beam components")
6036	if stationFaction ~= "Independent" then
6037		if random(1,5) <= 1 then
6038			goods[stationShree] = {{"food",math.random(5,10),1},{"medicine",5,5},{"tractor",5,90},{"repulsor",5,95}}
6039		else
6040			goods[stationShree] = {{"food",math.random(5,10),1},{"tractor",5,90},{"repulsor",5,95}}
6041			tradeMedicine[stationShree] = true
6042		end
6043	else
6044		goods[stationShree] = {{"tractor",5,90},{"repulsor",5,95}}
6045		tradeMedicine[stationShree] = true
6046		tradeFood[stationShree] = true
6047	end
6048	tradeLuxury[stationShree] = true
6049	stationShree.publicRelations = true
6050	stationShree.generalInformation = "We make ship systems designed to push or pull other objects around in space"
6051	stationShree.stationHistory = "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"
6052	return stationShree
6053end
6054function placeSoong()
6055	--Soong
6056	stationSoong = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation)
6057	stationSoong:setPosition(psx,psy):setCallSign("Soong"):setDescription("Android components")
6058	if stationFaction ~= "Independent" then
6059		if random(1,5) <= 1 then
6060			goods[stationSoong] = {{"food",math.random(5,10),1},{"medicine",5,5},{"android",5,73}}
6061		else
6062			goods[stationSoong] = {{"food",math.random(5,10),1},{"android",5,73}}
6063		end
6064	else
6065		goods[stationSoong] = {{"android",5,73}}
6066		tradeFood[stationSoong] = true
6067	end
6068	tradeLuxury[stationSoong] = true
6069	stationSoong.publicRelations = true
6070	stationSoong.generalInformation = "We create androids and android components"
6071	stationSoong.stationHistory = "The station is named after Dr. Noonian Soong, the famous android researcher and builder"
6072	return stationSoong
6073end
6074function placeTiberius()
6075	--Tiberius
6076	stationTiberius = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation)
6077	stationTiberius:setPosition(psx,psy):setCallSign("Tiberius"):setDescription("Logistics coordination")
6078	goods[stationTiberius] = {{"food",5,1}}
6079	stationTiberius.publicRelations = true
6080	stationTiberius.generalInformation = "We support the stations and ships in the area with planning and communication services"
6081	stationTiberius.stationHistory = "We recognize the influence of Starfleet Captain James Tiberius Kirk in the 23rd century in our station name"
6082	return stationTiberius
6083end
6084function placeTokra()
6085	--Tokra
6086	stationTokra = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation)
6087	stationTokra:setPosition(psx,psy):setCallSign("Tokra"):setDescription("Advanced material components")
6088	whatTrade = random(1,100)
6089	if stationFaction ~= "Independent" then
6090		if random(1,5) <= 1 then
6091			goods[stationTokra] = {{"food",math.random(5,10),1},{"medicine",5,5},{"filament",5,42}}
6092			tradeLuxury[stationTokra] = true
6093		else
6094			goods[stationTokra] = {{"food",math.random(5,10),1},{"filament",5,42}}
6095			if whatTrade < 50 then
6096				tradeMedicine[stationTokra] = true
6097			else
6098				tradeLuxury[stationTokra] = true
6099			end
6100		end
6101	else
6102		goods[stationTokra] = {{"filament",5,42}}
6103		if whatTrade < 33 then
6104			tradeFood[stationTokra] = true
6105		elseif whatTrade > 66 then
6106			tradeMedicine[stationTokra] = true
6107		else
6108			tradeLuxury[stationTokra] = true
6109		end
6110	end
6111	stationTokra.publicRelations = true
6112	stationTokra.generalInformation = "We create multiple types of advanced material components. Our most popular products are our filaments"
6113	stationTokra.stationHistory = "We learned several of our critical industrial processes from the Tokra race, so we honor our fortune by naming the station after them"
6114	return stationTokra
6115end
6116function placeToohie()
6117	--Toohie
6118	stationToohie = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation)
6119	stationToohie:setPosition(psx,psy):setCallSign("Toohie"):setDescription("Shield and armor components and research")
6120	if stationFaction ~= "Independent" then
6121		if random(1,5) <= 1 then
6122			goods[stationToohie] = {{"food",math.random(5,10),1},{"medicine",5,5},{"shield",5,90}}
6123		else
6124			goods[stationToohie] = {{"food",math.random(5,10),1},{"shield",5,90}}
6125			if random(1,100) < 25 then tradeMedicine[stationToohie] = true end
6126		end
6127	else
6128		goods[stationToohie] = {{"shield",5,90}}
6129		if random(1,100) < 25 then tradeMedicine[stationToohie] = true end
6130	end
6131	tradeLuxury[stationToohie] = true
6132	stationToohie.publicRelations = true
6133	stationToohie.generalInformation = "We research and make general and specialized components for ship shield and ship armor systems"
6134	stationToohie.stationHistory = "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."
6135	return stationToohie
6136end
6137function placeUtopiaPlanitia()
6138	--Utopia Planitia
6139	stationUtopiaPlanitia = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation)
6140	stationUtopiaPlanitia:setPosition(psx,psy):setCallSign("Utopia Planitia"):setDescription("Ship building and maintenance facility")
6141	if stationFaction ~= "Independent" then
6142		if random(1,5) <= 1 then
6143			goods[stationUtopiaPlanitia] = {{"food",math.random(5,10),1},{"medicine",5,5},{"warp",5,167}}
6144		else
6145			goods[stationUtopiaPlanitia] = {{"food",math.random(5,10),1},{"warp",5,167}}
6146		end
6147	else
6148		goods[stationUtopiaPlanitia] = {{"warp",5,167}}
6149	end
6150	stationUtopiaPlanitia.publicRelations = true
6151	stationUtopiaPlanitia.generalInformation = "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"
6152	return stationUtopiaPlanitia
6153end
6154function placeVactel()
6155	--Vactel
6156	stationVactel = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation)
6157	stationVactel:setPosition(psx,psy):setCallSign("Vactel"):setDescription("Shielded Circuitry Fabrication")
6158	if stationFaction ~= "Independent" then
6159		if random(1,5) <= 1 then
6160			goods[stationVactel] = {{"food",math.random(5,10),1},{"medicine",5,5},{"circuit",5,50}}
6161		else
6162			goods[stationVactel] = {{"food",math.random(5,10),1},{"circuit",5,50}}
6163		end
6164	else
6165		goods[stationVactel] = {{"circuit",5,50}}
6166	end
6167	stationVactel.publicRelations = true
6168	stationVactel.generalInformation = "We specialize in circuitry shielded from external hacking suitable for ship systems"
6169	stationVactel.stationHistory = "We started as an expansion from the lunar based chip manufacturer of Earth legacy Intel electronic chips"
6170	return stationVactel
6171end
6172function placeVeloquan()
6173	--Veloquan
6174	stationVeloquan = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation)
6175	stationVeloquan:setPosition(psx,psy):setCallSign("Veloquan"):setDescription("Sensor components")
6176	if stationFaction ~= "Independent" then
6177		if random(1,5) <= 1 then
6178			goods[stationVeloquan] = {{"food",math.random(5,10),1},{"medicine",5,5},{"sensor",5,68}}
6179		else
6180			goods[stationVeloquan] = {{"food",math.random(5,10),1},{"sensor",5,68}}
6181			tradeMedicine[stationVeloquan] = true
6182		end
6183	else
6184		goods[stationVeloquan] = {{"sensor",5,68}}
6185		tradeMedicine[stationVeloquan] = true
6186		tradeFood[stationVeloquan] = true
6187	end
6188	stationVeloquan.publicRelations = true
6189	stationVeloquan.generalInformation = "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"
6190	stationVeloquan.stationHistory = "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"
6191	return stationVeloquan
6192end
6193function placeZefram()
6194	--Zefram
6195	stationZefram = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation)
6196	stationZefram:setPosition(psx,psy):setCallSign("Zefram"):setDescription("Warp engine components")
6197	if stationFaction ~= "Independent" then
6198		if random(1,5) <= 1 then
6199			goods[stationZefram] = {{"food",math.random(5,10),1},{"medicine",5,5},{"warp",5,140}}
6200		else
6201			goods[stationZefram] = {{"food",math.random(5,10),1},{"warp",5,140}}
6202			if random(1,100) < 27 then tradeMedicine[stationZefram] = true end
6203		end
6204	else
6205		goods[stationZefram] = {{"warp",5,140}}
6206		if random(1,100) < 27 then tradeMedicine[stationZefram] = true end
6207		if random(1,100) < 16 then tradeFood[stationZefram] = true end
6208	end
6209	tradeLuxury[stationZefram] = true
6210	stationZefram.publicRelations = true
6211	stationZefram.generalInformation = "We specialize in the esoteric components necessary to make warp drives function properly"
6212	stationZefram.stationHistory = "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"
6213	return stationZefram
6214end
6215
6216-------------------------------------
6217--	Generic stations to be placed  --
6218-------------------------------------
6219function placeJabba()
6220	--Jabba
6221	stationJabba = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation)
6222	stationJabba:setPosition(psx,psy):setCallSign("Jabba"):setDescription("Commerce and gambling")
6223	stationJabba.publicRelations = true
6224	stationJabba.generalInformation = "Come play some games and shop. House take does not exceed 4 percent"
6225	return stationJabba
6226end
6227function placeKrik()
6228	--Krik
6229	stationKrik = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation)
6230	stationKrik:setPosition(psx,psy):setCallSign("Krik"):setDescription("Mining station")
6231	posAxisKrik = random(0,360)
6232	posKrik = random(30000,80000)
6233	negKrik = random(20000,60000)
6234	spreadKrik = random(5000,8000)
6235	negAxisKrik = posAxisKrik + 180
6236	xPosAngleKrik, yPosAngleKrik = vectorFromAngle(posAxisKrik, posKrik)
6237	posKrikEnd = random(40,90)
6238	local asteroid_list = createRandomAlongArc(Asteroid, 30+posKrikEnd, psx+xPosAngleKrik, psy+yPosAngleKrik, posKrik, negAxisKrik, negAxisKrik+posKrikEnd, spreadKrik)
6239	xNegAngleKrik, yNegAngleKrik = vectorFromAngle(negAxisKrik, negKrik)
6240	negKrikEnd = random(30,60)
6241	local more_asteroids = createRandomAlongArc(Asteroid, 30+negKrikEnd, psx+xNegAngleKrik, psy+yNegAngleKrik, negKrik, posAxisKrik, posAxisKrik+negKrikEnd, spreadKrik)
6242	for _, ta in ipairs(more_asteroids) do
6243		table.insert(asteroid_list,ta)
6244	end
6245	for _, ta in ipairs(asteroid_list) do
6246		table.insert(terrain_objects,ta)
6247	end
6248	stationKrik.asteroid_list = asteroid_list
6249	tradeFood[stationKrik] = true
6250	if random(1,100) < 50 then tradeLuxury[stationKrik] = true end
6251	tradeMedicine[stationKrik] = true
6252	krikGoods = random(1,100)
6253	if krikGoods < 10 then
6254		goods[stationKrik] = {{"nickel",5,20},{"platinum",5,70},{"tritanium",5,50},{"dilithium",5,50}}
6255	elseif krikGoods < 20 then
6256		goods[stationKrik] = {{"nickel",5,20},{"platinum",5,70},{"tritanium",5,50}}
6257	elseif krikGoods < 30 then
6258		goods[stationKrik] = {{"nickel",5,20},{"platinum",5,70},{"dilithium",5,50}}
6259	elseif krikGoods < 40 then
6260		goods[stationKrik] = {{"nickel",5,20},{"tritanium",5,50},{"dilithium",5,50}}
6261	elseif krikGoods < 50 then
6262		goods[stationKrik] = {{"nickel",5,20},{"dilithium",5,50}}
6263	elseif krikGoods < 60 then
6264		goods[stationKrik] = {{"nickel",5,20},{"platinum",5,70}}
6265	elseif krikGoods < 70 then
6266		goods[stationKrik] = {{"nickel",5,20},{"tritanium",5,50}}
6267	elseif krikGoods < 80 then
6268		goods[stationKrik] = {{"platinum",5,70},{"tritanium",5,50},{"dilithium",5,50}}
6269	else
6270		goods[stationKrik] = {{"nickel",5,20}}
6271	end
6272	return stationKrik
6273end
6274function placeLando()
6275	--Lando
6276	stationLando = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation)
6277	stationLando:setPosition(psx,psy):setCallSign("Lando"):setDescription("Casino and Gambling")
6278	return stationLando
6279end
6280function placeMaverick()
6281	--Maverick
6282	stationMaverick = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation)
6283	stationMaverick:setPosition(psx,psy):setCallSign("Maverick"):setDescription("Gambling and resupply")
6284	stationMaverick.publicRelations = true
6285	stationMaverick.generalInformation = "Relax and meet some interesting players"
6286	return stationMaverick
6287end
6288function placeNefatha()
6289	--Nefatha
6290	stationNefatha = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation)
6291	stationNefatha:setPosition(psx,psy):setCallSign("Nefatha"):setDescription("Commerce and recreation")
6292	goods[stationNefatha] = {{"luxury",5,70}}
6293	return stationNefatha
6294end
6295function placeOkun()
6296	--Okun
6297	stationOkun = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation)
6298	stationOkun:setPosition(psx,psy):setCallSign("Okun"):setDescription("Xenopsychology research")
6299	return stationOkun
6300end
6301function placeOutpost7()
6302	--Outpost 7
6303	stationOutpost7 = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation)
6304	stationOutpost7:setPosition(psx,psy):setCallSign("Outpost-7"):setDescription("Resupply")
6305	goods[stationOutpost7] = {{"luxury",5,80}}
6306	return stationOutpost7
6307end
6308function placeOutpost8()
6309	--Outpost 8
6310	stationOutpost8 = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation)
6311	stationOutpost8:setPosition(psx,psy):setCallSign("Outpost-8")
6312	return stationOutpost8
6313end
6314function placeOutpost33()
6315	--Outpost 33
6316	stationOutpost33 = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation)
6317	stationOutpost33:setPosition(psx,psy):setCallSign("Outpost-33"):setDescription("Resupply")
6318	goods[stationOutpost33] = {{"luxury",5,75}}
6319	return stationOutpost33
6320end
6321function placePrada()
6322	--Prada
6323	stationPrada = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation)
6324	stationPrada:setPosition(psx,psy):setCallSign("Prada"):setDescription("Textiles and fashion")
6325	return stationPrada
6326end
6327function placeResearch11()
6328	--Research-11
6329	stationResearch11 = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation)
6330	stationResearch11:setPosition(psx,psy):setCallSign("Research-11"):setDescription("Stress Psychology Research")
6331	return stationResearch11
6332end
6333function placeResearch19()
6334	--Research-19
6335	stationResearch19 = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation)
6336	stationResearch19:setPosition(psx,psy):setCallSign("Research-19"):setDescription("Low gravity research")
6337	return stationResearch19
6338end
6339function placeRubis()
6340	--Rubis
6341	stationRubis = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation)
6342	stationRubis:setPosition(psx,psy):setCallSign("Rubis"):setDescription("Resupply")
6343	goods[stationRubis] = {{"luxury",5,76}}
6344	stationRubis.publicRelations = true
6345	stationRubis.generalInformation = "Get your energy here! Grab a drink before you go!"
6346	return stationRubis
6347end
6348function placeScience2()
6349	--Science 2
6350	stationScience2 = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation)
6351	stationScience2:setPosition(psx,psy):setCallSign("Science-2"):setDescription("Research Lab and Observatory")
6352	return stationScience2
6353end
6354function placeScience4()
6355	--Science 4
6356	stationScience4 = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation)
6357	stationScience4:setPosition(psx,psy):setCallSign("Science-4"):setDescription("Biotech research")
6358	return stationScience4
6359end
6360function placeSkandar()
6361	--Skandar
6362	stationSkandar = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation)
6363	stationSkandar:setPosition(psx,psy):setCallSign("Skandar"):setDescription("Routine maintenance and entertainment")
6364	goods[stationSkandar] = {{"luxury",5,87}}
6365	stationSkandar.publicRelations = true
6366	stationSkandar.generalInformation = "Stop by for repairs. Take in one of our juggling shows featuring the four-armed Skandars"
6367	stationSkandar.stationHistory = "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"
6368	return stationSkandar
6369end
6370function placeSpot()
6371	--Spot
6372	stationSpot = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation)
6373	stationSpot:setPosition(psx,psy):setCallSign("Spot"):setDescription("Observatory")
6374	return stationSpot
6375end
6376function placeStarnet()
6377	--Starnet
6378	stationStarnet = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation)
6379	stationStarnet:setPosition(psx,psy):setCallSign("Starnet"):setDescription("Automated weapons systems")
6380	stationStarnet.publicRelations = true
6381	stationStarnet.generalInformation = "We research and create automated weapons systems to improve ship combat capability"
6382	return stationStarnet
6383end
6384function placeTandon()
6385	--Tandon
6386	stationTandon = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation)
6387	stationTandon:setPosition(psx,psy):setCallSign("Tandon"):setDescription("Biotechnology research")
6388	return stationTandon
6389end
6390function placeVaiken()
6391	--Vaiken
6392	stationVaiken = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation)
6393	stationVaiken:setPosition(psx,psy):setCallSign("Vaiken"):setDescription("Ship building and maintenance facility")
6394	goods[stationVaiken] = {{"food",10,1},{"medicine",5,5}}
6395	return stationVaiken
6396end
6397function placeValero()
6398	--Valero
6399	stationValero = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation)
6400	stationValero:setPosition(psx,psy):setCallSign("Valero"):setDescription("Resupply")
6401	goods[stationValero] = {{"luxury",5,77}}
6402	return stationValero
6403end
6404
6405-----------------------------
6406--	Station communication  --
6407-----------------------------
6408function resupplyStation()
6409    if comms_target.comms_data == nil then
6410        comms_target.comms_data = {}
6411    end
6412    mergeTables(comms_target.comms_data, {
6413        friendlyness = math.random(0.0, 100.0),
6414        weapons = {
6415            Homing = "neutral",
6416            HVLI = "neutral",
6417            Mine = "neutral",
6418            Nuke = "friend",
6419            EMP = "friend"
6420        },
6421        weapon_cost = {
6422            Homing = math.random(1,4),
6423            HVLI = math.random(1,3),
6424            Mine = math.random(2,5),
6425            Nuke = math.random(12,18),
6426            EMP = math.random(7,13)
6427        },
6428        services = {
6429            supplydrop = "friend",
6430            reinforcements = "friend",
6431        },
6432        service_cost = {
6433            supplydrop = math.random(80,120),
6434            reinforcements = math.random(125,175)
6435        },
6436        reputation_cost_multipliers = {
6437            friend = 1.0,
6438            neutral = 3.0
6439        },
6440        max_weapon_refill_amount = {
6441            friend = 1.0,
6442            neutral = 0.5
6443        }
6444    })
6445    comms_data = comms_target.comms_data
6446	if comms_source:isEnemy(comms_target) then
6447        return false
6448    end
6449    if comms_source:isDocked(comms_target) then
6450		setCommsMessage("Greetings")
6451		missile_types = {'Homing', 'Nuke', 'Mine', 'EMP', 'HVLI'}
6452		missilePresence = 0
6453		for _, missile_type in ipairs(missile_types) do
6454			missilePresence = missilePresence + comms_source:getWeaponStorageMax(missile_type)
6455		end
6456		if missilePresence > 0 then
6457			if comms_target.nukeAvail == nil then
6458				comms_target.nukeAvail = false
6459				comms_target.empAvail = false
6460				comms_target.homeAvail = true
6461				comms_target.mineAvail = false
6462				comms_target.hvliAvail = true
6463			end
6464			if comms_target.nukeAvail or comms_target.empAvail or comms_target.homeAvail or comms_target.mineAvail or comms_target.hvliAvail then
6465				if comms_source:getWeaponStorageMax("Homing") > 0 then
6466					if comms_target.homeAvail then
6467						homePrompt = "Restock Homing ("
6468						addCommsReply(homePrompt .. getWeaponCost("Homing") .. " rep each)", function()
6469							handleResupplyStationWeaponRestock("Homing")
6470						end)
6471					end
6472				end
6473				if comms_source:getWeaponStorageMax("HVLI") > 0 then
6474					if comms_target.hvliAvail then
6475						hvliPrompt = "Restock HVLI ("
6476						addCommsReply(hvliPrompt .. getWeaponCost("HVLI") .. " rep each)", function()
6477							handleResupplyStationWeaponRestock("HVLI")
6478						end)
6479					end
6480				end
6481			end
6482		end
6483	else
6484        setCommsMessage("Dock, please")
6485    end
6486    return true
6487end
6488function handleResupplyStationWeaponRestock(weapon)
6489    if not comms_source:isDocked(comms_target) then
6490		setCommsMessage("You need to stay docked for that action.")
6491		return
6492	end
6493    if not isAllowedTo(comms_data.weapons[weapon]) then
6494        if weapon == "Nuke" then setCommsMessage("We do not deal in weapons of mass destruction.")
6495        elseif weapon == "EMP" then setCommsMessage("We do not deal in weapons of mass disruption.")
6496        else setCommsMessage("We do not deal in those weapons.") end
6497        return
6498    end
6499    local points_per_item = getWeaponCost(weapon)
6500    local item_amount = math.floor(comms_source:getWeaponStorageMax(weapon) * comms_data.max_weapon_refill_amount[getFriendStatus()]) - comms_source:getWeaponStorage(weapon)
6501    if item_amount <= 0 then
6502        if weapon == "Nuke" then
6503            setCommsMessage("All nukes are charged and primed for destruction.");
6504        else
6505            setCommsMessage("Sorry, sir, but you are as fully stocked as I can allow.");
6506        end
6507        addCommsReply("Back", resupplyStation)
6508    else
6509        if not comms_source:takeReputationPoints(points_per_item * item_amount) then
6510            setCommsMessage("Not enough reputation.")
6511            return
6512        end
6513        comms_source:setWeaponStorage(weapon, comms_source:getWeaponStorage(weapon) + item_amount)
6514        if comms_source:getWeaponStorage(weapon) == comms_source:getWeaponStorageMax(weapon) then
6515            setCommsMessage("You are fully loaded and ready to explode things.")
6516        else
6517            setCommsMessage("We generously resupplied you with some weapon charges.\nPut them to good use.")
6518        end
6519        addCommsReply("Back", resupplyStation)
6520    end
6521end
6522function commsStation()
6523    if comms_target.comms_data == nil then
6524        comms_target.comms_data = {}
6525    end
6526    mergeTables(comms_target.comms_data, {
6527        friendlyness = math.random(0.0, 100.0),
6528        weapons = {
6529            Homing = "neutral",
6530            HVLI = "neutral",
6531            Mine = "neutral",
6532            Nuke = "friend",
6533            EMP = "friend"
6534        },
6535        weapon_cost = {
6536            Homing = math.random(1,4),
6537            HVLI = math.random(1,3),
6538            Mine = math.random(2,5),
6539            Nuke = math.random(12,18),
6540            EMP = math.random(7,13)
6541        },
6542        services = {
6543            supplydrop = "friend",
6544            reinforcements = "friend",
6545        },
6546        service_cost = {
6547            supplydrop = math.random(80,120),
6548            reinforcements = math.random(125,175)
6549        },
6550        reputation_cost_multipliers = {
6551            friend = 1.0,
6552            neutral = 3.0
6553        },
6554        max_weapon_refill_amount = {
6555            friend = 1.0,
6556            neutral = 0.5
6557        }
6558    })
6559	comms_data = comms_target.comms_data
6560	if comms_source:isEnemy(comms_target) then
6561        return false
6562    end
6563    if not comms_source:isDocked(comms_target) then
6564        handleUndockedState()
6565    else
6566        handleDockedState()
6567    end
6568    return true
6569end
6570function handleDockedState()
6571    if comms_source:isFriendly(comms_target) then
6572		oMsg = "Good day, officer!\nWhat can we do for you today?\n"
6573    else
6574		oMsg = "Welcome to our lovely station.\n"
6575    end
6576	setCommsMessage(oMsg)
6577	missilePresence = 0
6578	for _, missile_type in ipairs(missile_types) do
6579		missilePresence = missilePresence + comms_source:getWeaponStorageMax(missile_type)
6580	end
6581	if missilePresence > 0 then
6582		if comms_target.nukeAvail == nil then
6583			if math.random(1,10) <= (4 - difficulty) then
6584				comms_target.nukeAvail = true
6585			else
6586				comms_target.nukeAvail = false
6587			end
6588			if math.random(1,10) <= (5 - difficulty) then
6589				comms_target.empAvail = true
6590			else
6591				comms_target.empAvail = false
6592			end
6593			if math.random(1,10) <= (6 - difficulty) then
6594				comms_target.homeAvail = true
6595			else
6596				comms_target.homeAvail = false
6597			end
6598			if math.random(1,10) <= (7 - difficulty) then
6599				comms_target.mineAvail = true
6600			else
6601				comms_target.mineAvail = false
6602			end
6603			if math.random(1,10) <= (9 - difficulty) then
6604				comms_target.hvliAvail = true
6605			else
6606				comms_target.hvliAvail = false
6607			end
6608		end
6609		if comms_target.nukeAvail or comms_target.empAvail or comms_target.homeAvail or comms_target.mineAvail or comms_target.hvliAvail then
6610			addCommsReply("I need ordnance restocked", function()
6611				setCommsMessage("What type of ordnance?")
6612				if comms_source:getWeaponStorageMax("Nuke") > 0 then
6613					if comms_target.nukeAvail then
6614						if math.random(1,10) <= 5 then
6615							nukePrompt = "Can you supply us with some nukes? ("
6616						else
6617							nukePrompt = "We really need some nukes ("
6618						end
6619						addCommsReply(nukePrompt .. getWeaponCost("Nuke") .. " rep each)", function()
6620							handleWeaponRestock("Nuke")
6621						end)
6622					end
6623				end
6624				if comms_source:getWeaponStorageMax("EMP") > 0 then
6625					if comms_target.empAvail then
6626						if math.random(1,10) <= 5 then
6627							empPrompt = "Please re-stock our EMP missiles. ("
6628						else
6629							empPrompt = "Got any EMPs? ("
6630						end
6631						addCommsReply(empPrompt .. getWeaponCost("EMP") .. " rep each)", function()
6632							handleWeaponRestock("EMP")
6633						end)
6634					end
6635				end
6636				if comms_source:getWeaponStorageMax("Homing") > 0 then
6637					if comms_target.homeAvail then
6638						if math.random(1,10) <= 5 then
6639							homePrompt = "Do you have spare homing missiles for us? ("
6640						else
6641							homePrompt = "Do you have extra homing missiles? ("
6642						end
6643						addCommsReply(homePrompt .. getWeaponCost("Homing") .. " rep each)", function()
6644							handleWeaponRestock("Homing")
6645						end)
6646					end
6647				end
6648				if comms_source:getWeaponStorageMax("Mine") > 0 then
6649					if comms_target.mineAvail then
6650						minePromptChoice = math.random(1,5)
6651						if minePromptChoice == 1 then
6652							minePrompt = "We could use some mines. ("
6653						elseif minePromptChoice == 2 then
6654							minePrompt = "How about mines? ("
6655						elseif minePromptChoice == 3 then
6656							minePrompt = "More mines ("
6657						elseif minePromptChoice == 4 then
6658							minePrompt = "All the mines we can take. ("
6659						else
6660							minePrompt = "Mines! What else? ("
6661						end
6662						addCommsReply(minePrompt .. getWeaponCost("Mine") .. " rep each)", function()
6663							handleWeaponRestock("Mine")
6664						end)
6665					end
6666				end
6667				if comms_source:getWeaponStorageMax("HVLI") > 0 then
6668					if comms_target.hvliAvail then
6669						if math.random(1,10) <= 5 then
6670							hvliPrompt = "What about HVLI? ("
6671						else
6672							hvliPrompt = "Could you provide HVLI? ("
6673						end
6674						addCommsReply(hvliPrompt .. getWeaponCost("HVLI") .. " rep each)", function()
6675							handleWeaponRestock("HVLI")
6676						end)
6677					end
6678				end
6679			end)
6680		end
6681	end
6682	if comms_source:isFriendly(comms_target) then
6683		if math.random(1,6) <= (4 - difficulty) then
6684			if comms_source:getRepairCrewCount() < comms_source.maxRepairCrew then
6685				hireCost = math.random(30,60)
6686			else
6687				hireCost = math.random(45,90)
6688			end
6689			addCommsReply(string.format("Recruit repair crew member for %i reputation",hireCost), function()
6690				if not comms_source:takeReputationPoints(hireCost) then
6691					setCommsMessage("Insufficient reputation")
6692				else
6693					comms_source:setRepairCrewCount(comms_source:getRepairCrewCount() + 1)
6694					resetPreviousSystemHealth(comms_source)
6695					setCommsMessage("Repair crew member hired")
6696				end
6697			end)
6698		end
6699	else
6700		if math.random(1,6) <= (4 - difficulty) then
6701			if comms_source:getRepairCrewCount() < comms_source.maxRepairCrew then
6702				hireCost = math.random(45,90)
6703			else
6704				hireCost = math.random(60,120)
6705			end
6706			addCommsReply(string.format("Recruit repair crew member for %i reputation",hireCost), function()
6707				if not comms_source:takeReputationPoints(hireCost) then
6708					setCommsMessage("Insufficient reputation")
6709				else
6710					comms_source:setRepairCrewCount(comms_source:getRepairCrewCount() + 1)
6711					resetPreviousSystemHealth(comms_source)
6712					setCommsMessage("Repair crew member hired")
6713				end
6714			end)
6715		end
6716	end
6717	if comms_target.publicRelations then
6718		addCommsReply("Tell me more about your station", function()
6719			setCommsMessage("What would you like to know?")
6720			addCommsReply("General information", function()
6721				setCommsMessage(comms_target.generalInformation)
6722				addCommsReply("Back", commsStation)
6723			end)
6724			if comms_target.stationHistory ~= nil then
6725				addCommsReply("Station history", function()
6726					setCommsMessage(comms_target.stationHistory)
6727					addCommsReply("Back", commsStation)
6728				end)
6729			end
6730			if comms_source:isFriendly(comms_target) then
6731				if comms_target.gossip ~= nil then
6732					if random(1,100) < 50 then
6733						addCommsReply("Gossip", function()
6734							setCommsMessage(comms_target.gossip)
6735							addCommsReply("Back", commsStation)
6736						end)
6737					end
6738				end
6739			end
6740		end)
6741	end
6742	if goods[comms_target] ~= nil then
6743		addCommsReply("Buy, sell, trade", function()
6744			oMsg = string.format("Station %s:\nGoods or components available: quantity, cost in reputation\n",comms_target:getCallSign())
6745			gi = 1		-- initialize goods index
6746			repeat
6747				goodsType = goods[comms_target][gi][1]
6748				goodsQuantity = goods[comms_target][gi][2]
6749				goodsRep = goods[comms_target][gi][3]
6750				oMsg = oMsg .. string.format("     %s: %i, %i\n",goodsType,goodsQuantity,goodsRep)
6751				gi = gi + 1
6752			until(gi > #goods[comms_target])
6753			oMsg = oMsg .. "Current Cargo:\n"
6754			gi = 1
6755			cargoHoldEmpty = true
6756			repeat
6757				playerGoodsType = goods[comms_source][gi][1]
6758				playerGoodsQuantity = goods[comms_source][gi][2]
6759				if playerGoodsQuantity > 0 then
6760					oMsg = oMsg .. string.format("     %s: %i\n",playerGoodsType,playerGoodsQuantity)
6761					cargoHoldEmpty = false
6762				end
6763				gi = gi + 1
6764			until(gi > #goods[comms_source])
6765			if cargoHoldEmpty then
6766				oMsg = oMsg .. "     Empty\n"
6767			end
6768			playerRep = math.floor(comms_source:getReputationPoints())
6769			oMsg = oMsg .. string.format("Available Space: %i, Available Reputation: %i\n",comms_source.cargo,playerRep)
6770			setCommsMessage(oMsg)
6771			-- Buttons for reputation purchases
6772			gi = 1
6773			repeat
6774				local goodsType = goods[comms_target][gi][1]
6775				local goodsQuantity = goods[comms_target][gi][2]
6776				local goodsRep = goods[comms_target][gi][3]
6777				addCommsReply(string.format("Buy one %s for %i reputation",goods[comms_target][gi][1],goods[comms_target][gi][3]), function()
6778					oMsg = string.format("Type: %s, Quantity: %i, Rep: %i",goodsType,goodsQuantity,goodsRep)
6779					if comms_source.cargo < 1 then
6780						oMsg = oMsg .. "\nInsufficient cargo space for purchase"
6781					elseif goodsRep > playerRep then
6782						oMsg = oMsg .. "\nInsufficient reputation for purchase"
6783					elseif goodsQuantity < 1 then
6784						oMsg = oMsg .. "\nInsufficient station inventory"
6785					else
6786						if not comms_source:takeReputationPoints(goodsRep) then
6787							oMsg = oMsg .. "\nInsufficient reputation for purchase"
6788						else
6789							comms_source.cargo = comms_source.cargo - 1
6790							decrementStationGoods(goodsType)
6791							incrementPlayerGoods(goodsType)
6792							oMsg = oMsg .. "\npurchased"
6793						end
6794					end
6795					setCommsMessage(oMsg)
6796					addCommsReply("Back", commsStation)
6797				end)
6798				gi = gi + 1
6799			until(gi > #goods[comms_target])
6800			-- Buttons for food trades
6801			if tradeFood[comms_target] ~= nil then
6802				gi = 1
6803				foodQuantity = 0
6804				repeat
6805					if goods[comms_source][gi][1] == "food" then
6806						foodQuantity = goods[comms_source][gi][2]
6807					end
6808					gi = gi + 1
6809				until(gi > #goods[comms_source])
6810				if foodQuantity > 0 then
6811					gi = 1
6812					repeat
6813						local goodsType = goods[comms_target][gi][1]
6814						local goodsQuantity = goods[comms_target][gi][2]
6815						addCommsReply(string.format("Trade food for %s",goods[comms_target][gi][1]), function()
6816							oMsg = string.format("Type: %s,  Quantity: %i",goodsType,goodsQuantity)
6817							if goodsQuantity < 1 then
6818								oMsg = oMsg .. "\nInsufficient station inventory"
6819							else
6820								decrementStationGoods(goodsType)
6821								incrementPlayerGoods(goodsType)
6822								decrementPlayerGoods("food")
6823								oMsg = oMsg .. "\nTraded"
6824							end
6825							setCommsMessage(oMsg)
6826							addCommsReply("Back", commsStation)
6827						end)
6828						gi = gi + 1
6829					until(gi > #goods[comms_target])
6830				end
6831			end
6832			-- Buttons for luxury trades
6833			if tradeLuxury[comms_target] ~= nil then
6834				gi = 1
6835				luxuryQuantity = 0
6836				repeat
6837					if goods[comms_source][gi][1] == "luxury" then
6838						luxuryQuantity = goods[comms_source][gi][2]
6839					end
6840					gi = gi + 1
6841				until(gi > #goods[comms_source])
6842				if luxuryQuantity > 0 then
6843					gi = 1
6844					repeat
6845						local goodsType = goods[comms_target][gi][1]
6846						local goodsQuantity = goods[comms_target][gi][2]
6847						addCommsReply(string.format("Trade luxury for %s",goods[comms_target][gi][1]), function()
6848							oMsg = string.format("Type: %s,  Quantity: %i",goodsType,goodsQuantity)
6849							if goodsQuantity < 1 then
6850								oMsg = oMsg .. "\nInsufficient station inventory"
6851							else
6852								decrementStationGoods(goodsType)
6853								incrementPlayerGoods(goodsType)
6854								decrementPlayerGoods("luxury")
6855								oMsg = oMsg .. "\nTraded"
6856							end
6857							setCommsMessage(oMsg)
6858							addCommsReply("Back", commsStation)
6859						end)
6860						gi = gi + 1
6861					until(gi > #goods[comms_target])
6862				end
6863			end
6864			-- Buttons for medicine trades
6865			if tradeMedicine[comms_target] ~= nil then
6866				gi = 1
6867				medicineQuantity = 0
6868				repeat
6869					if goods[comms_source][gi][1] == "medicine" then
6870						medicineQuantity = goods[comms_source][gi][2]
6871					end
6872					gi = gi + 1
6873				until(gi > #goods[comms_source])
6874				if medicineQuantity > 0 then
6875					gi = 1
6876					repeat
6877						local goodsType = goods[comms_target][gi][1]
6878						local goodsQuantity = goods[comms_target][gi][2]
6879						addCommsReply(string.format("Trade medicine for %s",goods[comms_target][gi][1]), function()
6880							oMsg = string.format("Type: %s,  Quantity: %i",goodsType,goodsQuantity)
6881							if goodsQuantity < 1 then
6882								oMsg = oMsg .. "\nInsufficient station inventory"
6883							else
6884								decrementStationGoods(goodsType)
6885								incrementPlayerGoods(goodsType)
6886								decrementPlayerGoods("medicine")
6887								oMsg = oMsg .. "\nTraded"
6888							end
6889							setCommsMessage(oMsg)
6890							addCommsReply("Back", commsStation)
6891						end)
6892						gi = gi + 1
6893					until(gi > #goods[comms_target])
6894				end
6895			end
6896			addCommsReply("Back", commsStation)
6897		end)
6898		gi = 1
6899		cargoHoldEmpty = true
6900		repeat
6901			playerGoodsType = goods[comms_source][gi][1]
6902			playerGoodsQuantity = goods[comms_source][gi][2]
6903			if playerGoodsQuantity > 0 then
6904				cargoHoldEmpty = false
6905			end
6906			gi = gi + 1
6907		until(gi > #goods[comms_source])
6908		if not cargoHoldEmpty then
6909			addCommsReply("Jettison cargo", function()
6910				setCommsMessage(string.format("Available space: %i\nWhat would you like to jettison?",comms_source.cargo))
6911				gi = 1
6912				repeat
6913					local goodsType = goods[comms_source][gi][1]
6914					local goodsQuantity = goods[comms_source][gi][2]
6915					if goodsQuantity > 0 then
6916						addCommsReply(goodsType, function()
6917							decrementPlayerGoods(goodsType)
6918							comms_source.cargo = comms_source.cargo + 1
6919							setCommsMessage(string.format("One %s jettisoned",goodsType))
6920							addCommsReply("Back", commsStation)
6921						end)
6922					end
6923					gi = gi + 1
6924				until(gi > #goods[comms_source])
6925				addCommsReply("Back", commsStation)
6926			end)
6927		end
6928	end
6929end
6930function isAllowedTo(state)
6931    if state == "friend" and comms_source:isFriendly(comms_target) then
6932        return true
6933    end
6934    if state == "neutral" and not comms_source:isEnemy(comms_target) then
6935        return true
6936    end
6937    return false
6938end
6939function handleWeaponRestock(weapon)
6940    if not comms_source:isDocked(comms_target) then
6941		setCommsMessage("You need to stay docked for that action.")
6942		return
6943	end
6944    if not isAllowedTo(comms_data.weapons[weapon]) then
6945        if weapon == "Nuke" then setCommsMessage("We do not deal in weapons of mass destruction.")
6946        elseif weapon == "EMP" then setCommsMessage("We do not deal in weapons of mass disruption.")
6947        else setCommsMessage("We do not deal in those weapons.") end
6948        return
6949    end
6950    local points_per_item = getWeaponCost(weapon)
6951    local item_amount = math.floor(comms_source:getWeaponStorageMax(weapon) * comms_data.max_weapon_refill_amount[getFriendStatus()]) - comms_source:getWeaponStorage(weapon)
6952    if item_amount <= 0 then
6953        if weapon == "Nuke" then
6954            setCommsMessage("All nukes are charged and primed for destruction.");
6955        else
6956            setCommsMessage("Sorry, sir, but you are as fully stocked as I can allow.");
6957        end
6958        addCommsReply("Back", commsStation)
6959    else
6960        if not comms_source:takeReputationPoints(points_per_item * item_amount) then
6961            setCommsMessage("Not enough reputation.")
6962            return
6963        end
6964        comms_source:setWeaponStorage(weapon, comms_source:getWeaponStorage(weapon) + item_amount)
6965        if comms_source:getWeaponStorage(weapon) == comms_source:getWeaponStorageMax(weapon) then
6966            setCommsMessage("You are fully loaded and ready to explode things.")
6967        else
6968            setCommsMessage("We generously resupplied you with some weapon charges.\nPut them to good use.")
6969        end
6970        addCommsReply("Back", commsStation)
6971    end
6972end
6973function getWeaponCost(weapon)
6974    return math.ceil(comms_data.weapon_cost[weapon] * comms_data.reputation_cost_multipliers[getFriendStatus()])
6975end
6976function handleUndockedState()
6977    --Handle communications when we are not docked with the station.
6978    if comms_source:isFriendly(comms_target) then
6979        oMsg = "Good day, officer.\nIf you need supplies, please dock with us first."
6980    else
6981        oMsg = "Greetings.\nIf you want to do business, please dock with us first."
6982    end
6983	if comms_target.nukeAvail == nil then
6984		if math.random(1,10) <= (4 - difficulty) then
6985			comms_target.nukeAvail = true
6986		else
6987			comms_target.nukeAvail = false
6988		end
6989		if math.random(1,10) <= (5 - difficulty) then
6990			comms_target.empAvail = true
6991		else
6992			comms_target.empAvail = false
6993		end
6994		if math.random(1,10) <= (6 - difficulty) then
6995			comms_target.homeAvail = true
6996		else
6997			comms_target.homeAvail = false
6998		end
6999		if math.random(1,10) <= (7 - difficulty) then
7000			comms_target.mineAvail = true
7001		else
7002			comms_target.mineAvail = false
7003		end
7004		if math.random(1,10) <= (9 - difficulty) then
7005			comms_target.hvliAvail = true
7006		else
7007			comms_target.hvliAvail = false
7008		end
7009	end
7010	setCommsMessage(oMsg)
7011 	addCommsReply("I need information", function()
7012		setCommsMessage("What kind of information do you need?")
7013		addCommsReply("What ordnance do you have available for restock?", function()
7014			missileTypeAvailableCount = 0
7015			oMsg = ""
7016			if comms_target.nukeAvail then
7017				missileTypeAvailableCount = missileTypeAvailableCount + 1
7018				oMsg = oMsg .. "\n   Nuke"
7019			end
7020			if comms_target.empAvail then
7021				missileTypeAvailableCount = missileTypeAvailableCount + 1
7022				oMsg = oMsg .. "\n   EMP"
7023			end
7024			if comms_target.homeAvail then
7025				missileTypeAvailableCount = missileTypeAvailableCount + 1
7026				oMsg = oMsg .. "\n   Homing"
7027			end
7028			if comms_target.mineAvail then
7029				missileTypeAvailableCount = missileTypeAvailableCount + 1
7030				oMsg = oMsg .. "\n   Mine"
7031			end
7032			if comms_target.hvliAvail then
7033				missileTypeAvailableCount = missileTypeAvailableCount + 1
7034				oMsg = oMsg .. "\n   HVLI"
7035			end
7036			if missileTypeAvailableCount == 0 then
7037				oMsg = "We have no ordnance available for restock"
7038			elseif missileTypeAvailableCount == 1 then
7039				oMsg = "We have the following type of ordnance available for restock:" .. oMsg
7040			else
7041				oMsg = "We have the following types of ordnance available for restock:" .. oMsg
7042			end
7043			setCommsMessage(oMsg)
7044			addCommsReply("Back", commsStation)
7045		end)
7046		goodsQuantityAvailable = 0
7047		gi = 1
7048		repeat
7049			if goods[comms_target][gi][2] > 0 then
7050				goodsQuantityAvailable = goodsQuantityAvailable + goods[comms_target][gi][2]
7051			end
7052			gi = gi + 1
7053		until(gi > #goods[comms_target])
7054		if goodsQuantityAvailable > 0 then
7055			addCommsReply("What goods do you have available for sale or trade?", function()
7056				oMsg = string.format("Station %s:\nGoods or components available: quantity, cost in reputation\n",comms_target:getCallSign())
7057				gi = 1		-- initialize goods index
7058				repeat
7059					goodsType = goods[comms_target][gi][1]
7060					goodsQuantity = goods[comms_target][gi][2]
7061					goodsRep = goods[comms_target][gi][3]
7062					oMsg = oMsg .. string.format("   %14s: %2i, %3i\n",goodsType,goodsQuantity,goodsRep)
7063					gi = gi + 1
7064				until(gi > #goods[comms_target])
7065				setCommsMessage(oMsg)
7066				addCommsReply("Back", commsStation)
7067			end)
7068		end
7069		addCommsReply("See any enemies in your area?", function()
7070			if comms_source:isFriendly(comms_target) then
7071				enemiesInRange = 0
7072				for _, obj in ipairs(comms_target:getObjectsInRange(30000)) do
7073					if obj:isEnemy(comms_source) then
7074						enemiesInRange = enemiesInRange + 1
7075					end
7076				end
7077				if enemiesInRange > 0 then
7078					if enemiesInRange > 1 then
7079						setCommsMessage(string.format("Yes, we see %i enemies within 30U",enemiesInRange))
7080					else
7081						setCommsMessage("Yes, we see one enemy within 30U")
7082					end
7083					comms_source:addReputationPoints(2.0)
7084				else
7085					setCommsMessage("No enemies within 30U")
7086					comms_source:addReputationPoints(1.0)
7087				end
7088				addCommsReply("Back", commsStation)
7089			else
7090				setCommsMessage("Not really")
7091				comms_source:addReputationPoints(1.0)
7092				addCommsReply("Back", commsStation)
7093			end
7094		end)
7095		addCommsReply("Where can I find particular goods?", function()
7096			gkMsg = "Friendly stations generally have food or medicine or both. Neutral stations often trade their goods for food, medicine or luxury."
7097			if comms_target.goodsKnowledge == nil then
7098				gkMsg = gkMsg .. " Beyond that, I have no knowledge of specific stations.\n\nCheck back later, someone else may have better knowledge"
7099				setCommsMessage(gkMsg)
7100				addCommsReply("Back", commsStation)
7101				fillStationBrains()
7102			else
7103				if #comms_target.goodsKnowledge == 0 then
7104					gkMsg = gkMsg .. " Beyond that, I have no knowledge of specific stations"
7105				else
7106					gkMsg = gkMsg .. "\n\nWhat goods are you interested in?\nI've heard about these:"
7107					for gk=1,#comms_target.goodsKnowledge do
7108						addCommsReply(comms_target.goodsKnowledgeType[gk],function()
7109							setCommsMessage(string.format("Station %s in sector %s has %s%s",comms_target.goodsKnowledge[gk],comms_target.goodsKnowledgeSector[gk],comms_target.goodsKnowledgeType[gk],comms_target.goodsKnowledgeTrade[gk]))
7110							addCommsReply("Back", commsStation)
7111						end)
7112					end
7113				end
7114				setCommsMessage(gkMsg)
7115				addCommsReply("Back", commsStation)
7116			end
7117		end)
7118		if comms_target.publicRelations then
7119			addCommsReply("General station information", function()
7120				setCommsMessage(comms_target.generalInformation)
7121				addCommsReply("Back", commsStation)
7122			end)
7123		end
7124	end)
7125	--Diagnostic data is used to help test and debug the script while it is under construction
7126	if diagnostic then
7127		addCommsReply("Diagnostic data", function()
7128			oMsg = string.format("Difficulty: %.1f",difficulty)
7129			oMsg = oMsg .. string.format("  time remaining: %.1f",gameTimeLimit)
7130			if plotW ~= nil and waveTimer ~= nil then
7131				oMsg = oMsg .. string.format("\nwave timer: %.1f",waveTimer)
7132			end
7133			if timeDivision ~= nil then
7134				oMsg = oMsg .. "  " .. timeDivision
7135			end
7136			oMsg = oMsg .. "\n" .. wfv
7137			setCommsMessage(oMsg)
7138			addCommsReply("Back", commsStation)
7139		end)
7140	end
7141	if isAllowedTo(comms_target.comms_data.services.supplydrop) then
7142        addCommsReply("Can you send a supply drop? ("..getServiceCost("supplydrop").."rep)", function()
7143            if comms_source:getWaypointCount() < 1 then
7144                setCommsMessage("You need to set a waypoint before you can request backup.");
7145            else
7146                setCommsMessage("To which waypoint should we deliver your supplies?");
7147                for n=1,comms_source:getWaypointCount() do
7148                    addCommsReply("WP" .. n, function()
7149                        if comms_source:takeReputationPoints(getServiceCost("supplydrop")) then
7150                            local position_x, position_y = comms_target:getPosition()
7151                            local target_x, target_y = comms_source:getWaypoint(n)
7152                            local script = Script()
7153                            script:setVariable("position_x", position_x):setVariable("position_y", position_y)
7154                            script:setVariable("target_x", target_x):setVariable("target_y", target_y)
7155                            script:setVariable("faction_id", comms_target:getFactionId()):run("supply_drop.lua")
7156                            setCommsMessage("We have dispatched a supply ship toward WP" .. n);
7157                        else
7158                            setCommsMessage("Not enough reputation!");
7159                        end
7160                        addCommsReply("Back", commsStation)
7161                    end)
7162                end
7163            end
7164            addCommsReply("Back", commsStation)
7165        end)
7166    end
7167    if isAllowedTo(comms_target.comms_data.services.reinforcements) then
7168        addCommsReply("Please send reinforcements! ("..getServiceCost("reinforcements").."rep)", function()
7169            if comms_source:getWaypointCount() < 1 then
7170                setCommsMessage("You need to set a waypoint before you can request reinforcements.");
7171            else
7172                setCommsMessage("To which waypoint should we dispatch the reinforcements?");
7173                for n=1,comms_source:getWaypointCount() do
7174                    addCommsReply("WP" .. n, function()
7175                        if comms_source:takeReputationPoints(getServiceCost("reinforcements")) then
7176                            ship = CpuShip():setFactionId(comms_target:getFactionId()):setPosition(comms_target:getPosition()):setTemplate("Adder MK5"):setScanned(true):orderDefendLocation(player:getWaypoint(n))
7177                            setCommsMessage("We have dispatched " .. ship:getCallSign() .. " to assist at WP" .. n);
7178                        else
7179                            setCommsMessage("Not enough reputation!");
7180                        end
7181                        addCommsReply("Back", commsStation)
7182                    end)
7183                end
7184            end
7185            addCommsReply("Back", commsStation)
7186        end)
7187    end
7188end
7189function getServiceCost(service)
7190	-- Return the number of reputation points that a specified service costs for
7191	-- the current player.
7192    return math.ceil(comms_data.service_cost[service])
7193end
7194function fillStationBrains()
7195	comms_target.goodsKnowledge = {}
7196	comms_target.goodsKnowledgeSector = {}
7197	comms_target.goodsKnowledgeType = {}
7198	comms_target.goodsKnowledgeTrade = {}
7199	knowledgeCount = 0
7200	knowledgeMax = 10
7201	for sti=1,#stationList do
7202		if stationList[sti] ~= nil and stationList[sti]:isValid() then
7203			if distance(comms_target,stationList[sti]) < 75000 then
7204				brainCheck = 3
7205			else
7206				brainCheck = 1
7207			end
7208			for gi=1,#goods[stationList[sti]] do
7209				if random(1,10) <= brainCheck then
7210					table.insert(comms_target.goodsKnowledge,stationList[sti]:getCallSign())
7211					table.insert(comms_target.goodsKnowledgeSector,stationList[sti]:getSectorName())
7212					table.insert(comms_target.goodsKnowledgeType,goods[stationList[sti]][gi][1])
7213					tradeString = ""
7214					stationTrades = false
7215					if tradeMedicine[stationList[sti]] ~= nil then
7216						tradeString = " and will trade it for medicine"
7217						stationTrades = true
7218					end
7219					if tradeFood[stationList[sti]] ~= nil then
7220						if stationTrades then
7221							tradeString = tradeString .. " or food"
7222						else
7223							tradeString = tradeString .. " and will trade it for food"
7224							stationTrades = true
7225						end
7226					end
7227					if tradeLuxury[stationList[sti]] ~= nil then
7228						if stationTrades then
7229							tradeString = tradeString .. " or luxury"
7230						else
7231							tradeString = tradeString .. " and will trade it for luxury"
7232						end
7233					end
7234					table.insert(comms_target.goodsKnowledgeTrade,tradeString)
7235					knowledgeCount = knowledgeCount + 1
7236					if knowledgeCount >= knowledgeMax then
7237						return
7238					end
7239				end
7240			end
7241		end
7242	end
7243end
7244function getFriendStatus()
7245    if comms_source:isFriendly(comms_target) then
7246        return "friend"
7247    else
7248        return "neutral"
7249    end
7250end
7251
7252-----------------------------------------------
7253--	Custom player ship buttons and messages  --
7254-----------------------------------------------
7255--	Player Ship Flag Buttons and call-back functions  --
7256function setP1FlagButton()
7257	if p1FlagButton == nil and not p1FlagDrop then
7258		p1FlagButton = "p1FlagButton"
7259		p1:addCustomButton("Weapons", p1FlagButton, "Drop flag", p1DropFlag)
7260		p1FlagButtonT = "p1FlagButtonT"
7261		p1:addCustomButton("Tactical", p1FlagButtonT, "Drop flag", p1DropFlag)
7262	end
7263end
7264function removeP1FlagButton()
7265	if p1FlagButton ~= nil then
7266		p1:removeCustom(p1FlagButton)
7267		p1:removeCustom(p1FlagButtonT)
7268		p1FlagButton = nil
7269		p1FlagButtonT = nil
7270	end
7271end
7272function setP2FlagButton()
7273	if p2FlagButton == nil and not p2FlagDrop then
7274		p2FlagButton = "p2FlagButton"
7275		p2:addCustomButton("Weapons", p2FlagButton, "Drop flag", p2DropFlag)
7276		p2FlagButtonT = "p2FlagButtonT"
7277		p2:addCustomButton("Tactical", p2FlagButtonT, "Drop flag", p2DropFlag)
7278	end
7279end
7280function removeP2FlagButton()
7281	if p2FlagButton ~= nil then
7282		p2:removeCustom(p2FlagButton)
7283		p2:removeCustom(p2FlagButtonT)
7284		p2FlagButton = nil
7285		p2FlagButtonT = nil
7286	end
7287end
7288
7289function p1DropFlag()
7290	p1FlagDrop = true
7291	p1Flagx, p1Flagy = p1:getPosition()
7292	removeP1FlagButton()
7293	if p1:hasPlayerAtPosition("Weapons") then
7294		p1FlagDroppedMsg = "p1FlagDroppedMsg"
7295		p1:addCustomMessage("Weapons",p1FlagDroppedMsg,"Flag position recorded. Flag will be placed here when preparation period complete")
7296	end
7297	if p1:hasPlayerAtPosition("Tactical") then
7298		p1FlagDroppedMsgT = "p1FlagDroppedMsgT"
7299		p1:addCustomMessage("Tactical",p1FlagDroppedMsgT,"Flag position recorded. Flag will be placed here when preparation period complete")
7300	end
7301end
7302function p2DropFlag()
7303	p2FlagDrop = true
7304	p2Flagx, p2Flagy = p2:getPosition()
7305	removeP2FlagButton()
7306	if p2:hasPlayerAtPosition("Weapons") then
7307		p2FlagDroppedMsg = "p2FlagDroppedMsg"
7308		p2:addCustomMessage("Weapons",p2FlagDroppedMsg,"Flag position recorded. Flag will be placed here when preparation period complete")
7309	end
7310	if p2:hasPlayerAtPosition("Tactical") then
7311		p2FlagDroppedMsgT = "p2FlagDroppedMsgT"
7312		p2:addCustomMessage("Tactical",p2FlagDroppedMsgT,"Flag position recorded. Flag will be placed here when preparation period complete")
7313	end
7314end
7315
7316--	Player Ship Decoy Buttons and call-back functions
7317function p1DropDecoy()
7318	if p1.decoy_drop == nil then
7319		p1.decoy_drop = {}
7320	end
7321	p1.decoy_drop[1] = true
7322	decoyH1x, decoyH1y = dropDecoy(p1,1)
7323end
7324function p1DropDecoy2()
7325	if p1.decoy_drop == nil then
7326		p1.decoy_drop = {}
7327	end
7328	p1.decoy_drop[2] = true
7329	decoyH2x, decoyH2y = dropDecoy(p1,2)
7330end
7331function p1DropDecoy3()
7332	if p1.decoy_drop == nil then
7333		p1.decoy_drop = {}
7334	end
7335	p1.decoy_drop[3] = true
7336	decoyH3x, decoyH3y = dropDecoy(p1,3)
7337end
7338function p2DropDecoy()
7339	if p2.decoy_drop == nil then
7340		p2.decoy_drop = {}
7341	end
7342	p2.decoy_drop[1] = true
7343	decoyK1x, decoyK1y = dropDecoy(p2,1)
7344end
7345function p2DropDecoy2()
7346	if p2.decoy_drop == nil then
7347		p2.decoy_drop = {}
7348	end
7349	p2.decoy_drop[2] = true
7350	decoyK2x, decoyK2y = dropDecoy(p2,2)
7351end
7352function p2DropDecoy3()
7353	if p2.decoy_drop == nil then
7354		p2.decoy_drop = {}
7355	end
7356	p2.decoy_drop[3] = true
7357	decoyK3x, decoyK3y = dropDecoy(p2,3)
7358end
7359function p3DropDecoy()
7360	if p3.decoy_drop == nil then
7361		p3.decoy_drop = {}
7362	end
7363	p3.decoy_drop[1] = true
7364	decoyH1x, decoyH1y = dropDecoy(p3,1)
7365end
7366function p3DropDecoy2()
7367	if p3.decoy_drop == nil then
7368		p3.decoy_drop = {}
7369	end
7370	p3.decoy_drop[2] = true
7371	decoyH2x, decoyH2y = dropDecoy(p3,2)
7372end
7373function p3DropDecoy3()
7374	if p3.decoy_drop == nil then
7375		p3.decoy_drop = {}
7376	end
7377	p3.decoy_drop[3] = true
7378	decoyH3x, decoyH3y = dropDecoy(p3,3)
7379end
7380function p4DropDecoy()
7381	if p4.decoy_drop == nil then
7382		p4.decoy_drop = {}
7383	end
7384	p4.decoy_drop[1] = true
7385	decoyK1x, decoyK1y = dropDecoy(p4,1)
7386end
7387function p4DropDecoy2()
7388	if p4.decoy_drop == nil then
7389		p4.decoy_drop = {}
7390	end
7391	p4.decoy_drop[2] = true
7392	decoyK2x, decoyK2y = dropDecoy(p4,2)
7393end
7394function p4DropDecoy3()
7395	if p4.decoy_drop == nil then
7396		p4.decoy_drop = {}
7397	end
7398	p4.decoy_drop[3] = true
7399	decoyK3x, decoyK3y = dropDecoy(p4,3)
7400end
7401function p5DropDecoy()
7402	if p5.decoy_drop == nil then
7403		p5.decoy_drop = {}
7404	end
7405	p5.decoy_drop[2] = true
7406	decoyH2x, decoyH2y = dropDecoy(p5,2)
7407end
7408function p5DropDecoy3()
7409	if p5.decoy_drop == nil then
7410		p5.decoy_drop = {}
7411	end
7412	p5.decoy_drop[3] = true
7413	decoyH3x, decoyH3y = dropDecoy(p5,3)
7414end
7415function p6DropDecoy()
7416	if p6.decoy_drop == nil then
7417		p6.decoy_drop = {}
7418	end
7419	p6.decoy_drop[2] = true
7420	decoyK2x, decoyK2y = dropDecoy(p6,2)
7421end
7422function p6DropDecoy3()
7423	if p6.decoy_drop == nil then
7424		p6.decoy_drop = {}
7425	end
7426	p6.decoy_drop[3] = true
7427	decoyK3x, decoyK3y = dropDecoy(p6,3)
7428end
7429function p7DropDecoy()
7430	p7.decoy_drop = {}
7431	p7.decoy_drop[3] = true
7432	decoyH3x, decoyH3y = dropDecoy(p7,3)
7433end
7434function p8DropDecoy()
7435	p8.decoy_drop = {}
7436	p8.decoy_drop[3] = true
7437	decoyK3x, decoyK3y = dropDecoy(p8,3)
7438end
7439function dropDecoy(p,decoy_number)
7440	local decoy_x, decoy_y = p:getPosition()
7441	removeDecoyButton(p)
7442	local decoy_dropped_message = string.format("%s%iDecoyDroppedMessageWeapons",p:getCallSign(),decoy_number)
7443	if p:hasPlayerAtPosition("Weapons") then
7444		p:addCustomMessage("Weapons",decoy_dropped_message,"Decoy position recorded. Decoy will be placed here when preparation period complete")
7445	end
7446	if p:hasPlayerAtPosition("Tactical") then
7447		decoy_dropped_message = string.format("%s%iDecoyDroppedMessageTactical",p:getCallSign(),decoy_number)
7448		p:addCustomMessage("Tactical",decoy_dropped_message,"Decoy position recorded. Decoy will be placed here when preparation period complete")
7449	end
7450	return decoy_x, decoy_y
7451end
7452function removeDecoyButton(p)
7453	if p ~= nil and p.decoy_button ~= nil then
7454		for decoy_button_label, player_name in pairs(p.decoy_button) do
7455			p:removeCustom(decoy_button_label)
7456		end
7457		p.decoy_button = {}
7458	end
7459end
7460function setDecoyButton(p,player_index,decoy_number)
7461	if p.decoy_drop == nil then
7462		p.decoy_drop = {}
7463	end
7464	if p.decoy_button == nil then
7465		p.decoy_button = {}
7466	end
7467	local player_name = p:getCallSign()
7468	local decoy_button_label = string.format("%s%iDecoyButtonWeapons",player_name,decoy_number)
7469	if p.decoy_button[decoy_button_label] == nil and p.decoy_drop[decoy_number] == nil then
7470		p:addCustomButton("Weapons",decoy_button_label,string.format("Drop Decoy %i",decoy_number),drop_decoy_functions[player_index][decoy_number])
7471		p.decoy_button[decoy_button_label] = player_name
7472		decoy_button_label = string.format("%s%iDecoyButtonTactical",p:getCallSign(),decoy_number)
7473		p:addCustomButton("Tactical",decoy_button_label,string.format("Drop Decoy %i",decoy_number),drop_decoy_functions[player_index][decoy_number])
7474		p.decoy_button[decoy_button_label] = player_name
7475	end
7476end
7477function setP1DecoyButton()
7478	setDecoyButton(p1,1,1)
7479end
7480function setP1DecoyButton2()
7481	setDecoyButton(p1,1,2)
7482end
7483function setP1DecoyButton3()
7484	setDecoyButton(p1,1,3)
7485end
7486function removeP1DecoyButton()
7487	removeDecoyButton(p1)
7488end
7489function removeP1DecoyButton2()
7490	removeDecoyButton(p1)
7491end
7492function removeP1DecoyButton3()
7493	removeDecoyButton(p1)
7494end
7495function setP2DecoyButton()
7496	setDecoyButton(p2,2,1)
7497end
7498function setP2DecoyButton2()
7499	setDecoyButton(p2,2,2)
7500end
7501function setP2DecoyButton3()
7502	setDecoyButton(p2,2,3)
7503end
7504function removeP2DecoyButton()
7505	removeDecoyButton(p2)
7506end
7507function removeP2DecoyButton2()
7508	removeDecoyButton(p2)
7509end
7510function removeP2DecoyButton3()
7511	removeDecoyButton(p2)
7512end
7513function setP3DecoyButton()
7514	setDecoyButton(p3,3,1)
7515end
7516function setP3DecoyButton2()
7517	setDecoyButton(p3,3,2)
7518end
7519function setP3DecoyButton3()
7520	setDecoyButton(p3,3,3)
7521end
7522function removeP3DecoyButton()
7523	removeDecoyButton(p3)
7524end
7525function removeP3DecoyButton2()
7526	removeDecoyButton(p3)
7527end
7528function removeP3DecoyButton3()
7529	removeDecoyButton(p3)
7530end
7531function setP4DecoyButton()
7532	setDecoyButton(p4,4,1)
7533end
7534function setP4DecoyButton2()
7535	setDecoyButton(p4,4,2)
7536end
7537function setP4DecoyButton3()
7538	setDecoyButton(p4,4,3)
7539end
7540function removeP4DecoyButton()
7541	removeDecoyButton(p4)
7542end
7543function removeP4DecoyButton2()
7544	removeDecoyButton(p4)
7545end
7546function removeP4DecoyButton3()
7547	removeDecoyButton(p4)
7548end
7549function setP5DecoyButton()
7550	setDecoyButton(p5,5,2)
7551end
7552function setP5DecoyButton3()
7553	setDecoyButton(p5,5,3)
7554end
7555function removeP5DecoyButton()
7556	removeDecoyButton(p5)
7557end
7558function removeP5DecoyButton3()
7559	removeDecoyButton(p5)
7560end
7561function setP6DecoyButton()
7562	setDecoyButton(p6,6,2)
7563end
7564function setP6DecoyButton3()
7565	setDecoyButton(p6,6,3)
7566end
7567function removeP6DecoyButton()
7568	removeDecoyButton(p6)
7569end
7570function removeP6DecoyButton3()
7571	removeDecoyButton(p6)
7572end
7573function setP7DecoyButton()
7574	setDecoyButton(p7,7,3)
7575end
7576function removeP7DecoyButton()
7577	removeDecoyButton(p7)
7578end
7579function setP8DecoyButton()
7580	setDecoyButton(p8,8,3)
7581end
7582function removeP8DecoyButton()
7583	removeDecoyButton(p8)
7584end
7585
7586-----------------------------------------------------------------------
7587--	Player Ship Drone Deployment Related Button Call-Back Functions  --
7588-----------------------------------------------------------------------
7589function notEnoughDronesMessage(p,count)
7590	local pName = p:getCallSign()
7591	local msgLabel = string.format("%sweaponsfewerthan%idrones",pName,count)
7592	p:addCustomMessage("Weapons",msgLabel,string.format("You do not have %i drones to deploy",count))
7593	msgLabel = string.format("%stacticalfewerthan%idrones",pName,count)
7594	p:addCustomMessage("Tactical",msgLabel,string.format("You do not have %i drones to deploy",count))
7595end
7596--drone count label
7597function establishDroneAvailableCount(p)
7598	local player_name = p:getCallSign()
7599	local count_info = string.format("Drones Available: %i",p.dronePool)
7600	local button_name = player_name .. "countWeapons"
7601	p:addCustomInfo("Weapons",button_name,count_info)
7602	p.drone_pool_info_weapons = button_name
7603	button_name = player_name .. "countTactical"
7604	p.drone_pool_info_tactical = button_name
7605	p:addCustomInfo("Tactical",button_name,count_info)
7606end
7607function removeDroneAvailableCount(p,console)
7608	if console == nil then
7609		return
7610	end
7611	if console == "Weapons" then
7612		if p.drone_pool_info_weapons ~= nil then
7613			p:removeCustom(p.drone_pool_info_weapons)
7614		end
7615	elseif console == "Tactical" then
7616		if p.drone_pool_info_tactical ~= nil then
7617			p:removeCustom(p.drone_pool_info_tactical)
7618		end
7619	end
7620end
7621function updateDroneAvailableCount(p)
7622	if p:hasPlayerAtPosition("Weapons") then
7623		removeDroneAvailableCount(p,"Weapons")
7624	end
7625	if p:hasPlayerAtPosition("Tactical") then
7626		removeDroneAvailableCount(p,"Tactical")
7627	end
7628	local player_name = p:getCallSign()
7629	local count_info = string.format("Drones Available: %i",p.dronePool)
7630	local button_name = player_name .. "countWeapons"
7631	if p:hasPlayerAtPosition("Weapons") then
7632		p:addCustomInfo("Weapons",button_name,count_info)
7633		p.drone_pool_info_weapons = button_name
7634	end
7635	if p:hasPlayerAtPosition("Tactical") then
7636		button_name = player_name .. "countTactical"
7637		p:addCustomInfo("Tactical",button_name,count_info)
7638		p.drone_pool_info_tactical = button_name
7639	end
7640end
7641
7642--------------------------------------
7643--	Drone creation and destruction  --
7644--------------------------------------
7645function deployDronesForPlayer(p,playerIndex,droneNumber)
7646	local px, py = p:getPosition()
7647	local droneList = {}
7648	if p.droneSquads == nil then
7649		p.droneSquads = {}
7650		p.squadCount = 0
7651	end
7652	local squadIndex = p.squadCount + 1
7653	local pName = p:getCallSign()
7654	local squadName = string.format("%s-Sq%i",pName,squadIndex)
7655	all_squad_count = all_squad_count + 1
7656	for i=1,droneNumber do
7657		local vx, vy = vectorFromAngle(360/droneNumber*i,800)
7658		local drone = CpuShip():setPosition(px+vx,py+vy):setFaction(p:getFaction()):setTemplate("Ktlitan Drone"):setScanned(true):setCommsScript(""):setCommsFunction(commsShip):setHeading(360/droneNumber*i+90)
7659		if drone_name_type == "squad-num/size" then
7660			drone:setCallSign(string.format("%s-#%i/%i",squadName,i,droneNumber))
7661		elseif drone_name_type == "squad-num of size" then
7662			drone:setCallSign(string.format("%s-%i of %i",squadName,i,droneNumber))
7663		elseif drone_name_type == "short" then
7664			--string.char(math.random(65,90)) --random letter A-Z
7665			local squad_letter_id = string.char(all_squad_count%26+64)
7666			if all_squad_count > 26 then
7667				squad_letter_id = squad_letter_id .. string.char(math.floor(all_squad_count/26)+64)
7668				if all_squad_count > 676 then
7669					squad_letter_id = squad_letter_id .. string.char(math.floor(all_squad_count/676)+64)
7670				end
7671			end
7672			drone:setCallSign(string.format("%s%i/%i",squad_letter_id,i,droneNumber))
7673		end
7674		if drone_modified_from_template then
7675			drone:setHullMax(drone_hull_strength):setHull(drone_hull_strength):setImpulseMaxSpeed(drone_impulse_speed)
7676			--       index from 0, arc, direction,            range,            cycle time,            damage
7677			drone:setBeamWeapon(0,  40,         0, drone_beam_range, drone_beam_cycle_time, drone_beam_damage)
7678		end
7679		drone.squadName = squadName
7680		drone.deployer = p
7681		drone.drone = true
7682		drone:onDestruction(droneDestructionManagement)
7683		table.insert(droneList,drone)
7684	end
7685	p.squadCount = p.squadCount + 1
7686	p.dronePool = p.dronePool - droneNumber
7687	p.droneSquads[squadName] = droneList
7688	if p:hasPlayerAtPosition("Weapons") then
7689		if droneNumber > 1 then
7690			p:addCustomMessage("Weapons","drone_launch_confirm_message_weapons",string.format("%i drones launched",droneNumber))
7691		else
7692			p:addCustomMessage("Weapons","drone_launch_confirm_message_weapons",string.format("%i drone launched",droneNumber))
7693		end
7694	end
7695	if p:hasPlayerAtPosition("Tactical") then
7696		if droneNumber > 1 then
7697			p:addCustomMessage("Tactical","drone_launch_confirm_message_tactical",string.format("%i drones launched",droneNumber))
7698		else
7699			p:addCustomMessage("Tactical","drone_launch_confirm_message_tactical",string.format("%i drone launched",droneNumber))
7700		end
7701	end
7702	if droneNumber > 1 then
7703		p:addToShipLog(string.format("Deployed %i drones as squadron %s",droneNumber,squadName),"White")
7704	else
7705		p:addToShipLog(string.format("Deployed %i drone as squadron %s",droneNumber,squadName),"White")
7706	end
7707--	updateDroneAvailableCount(p)
7708end
7709function droneDestructionManagement(destroyed_drone, attacker_ship)
7710	local drone_name = destroyed_drone:getCallSign()
7711	local squad_name = destroyed_drone.squadName
7712	local attacker_name = attacker_ship:getCallSign()
7713	local notice = string.format("  WHACK!  Drone %s in squadron %s has been destroyed by %s!",
7714		drone_name,
7715		squad_name,
7716		attacker_name)
7717	--local notice = "  WHACK!  Drone " .. destroyed_drone:getCallSign() .. " has been destroyed by " .. attacker_ship:getCallSign() .. "!"
7718	print(notice)
7719	if destroyed_drone.deployer ~= nil and destroyed_drone.deployer:isValid() then
7720		destroyed_drone.deployer:addToShipLog(notice,"Magenta")
7721		local interjection = {"Pow","Boom","Bam","Ouch","Oof","Splat","Boff","Bang","Hey","Whoa","Yikes","Oops","Squash","Zowie","Wow","Awk","Bap","Blurp","Crunch","Plop","Pam","Klonk","Thunk","Wham","Zap","Whap"}
7722		local engineer_notice = interjection[math.random(1,#interjection)]
7723		local engineer_notice_message_choice = math.random(1,5)
7724		if engineer_notice_message_choice == 1 then
7725			engineer_notice = string.format("%s! Telemetry from %s in squad % stopped abruptly indicating destruction. Probable instigator: %s",engineer_notice,drone_name,squad_name,attacker_name)
7726		elseif engineer_notice_message_choice == 2 then
7727			engineer_notice = string.format("*%s* Another drone bites the dust: %s in squad %s destroyed by %s",engineer_notice,drone_name,squad_name,attacker_name)
7728		elseif engineer_notice_message_choice == 3 then
7729			engineer_notice = string.format("--%s-- Drone %s in squad %s just disappeared. %s was nearby",engineer_notice,drone_name,squad_name,attacker_name)
7730		elseif engineer_notice_message_choice == 4 then
7731			engineer_notice = string.format("%s! %s just took out Drone %s in squad %s",engineer_notice,attacker_name,drone_name,squad_name)
7732		else
7733			engineer_notice = string.format("%s! Drone %s in squad %s was destroyed by %s",engineer_notice,drone_name,squad_name,attacker_name)
7734		end
7735		if destroyed_drone.deployer:hasPlayerAtPosition("Engineering") then
7736			destroyed_drone.deployer:addCustomMessage("Engineering",engineer_notice,engineer_notice)
7737		end
7738		if destroyed_drone.deployer:hasPlayerAtPosition("Engineering+") then
7739			local engineer_notice_plus = engineer_notice .. "plus"
7740			destroyed_drone.deployer:addCustomMessage("Engineering+",engineer_notice_plus,engineer_notice)
7741		end
7742	end
7743end
7744
7745--------------------------
7746--	Ship communication  --
7747--------------------------
7748-- Based on comms_ship.lua
7749-- variable player replaced with variable comms_source
7750-- variable and function mainMenu replaced with commsShip
7751-- see pertinent code below for fleet order specifics
7752function commsShip()
7753	if comms_target.comms_data == nil then
7754		comms_target.comms_data = {friendlyness = random(0.0, 100.0)}
7755	end
7756	comms_data = comms_target.comms_data
7757
7758	if comms_source:isFriendly(comms_target) then
7759		return friendlyComms(comms_data)
7760	end
7761	if comms_source:isEnemy(comms_target) and comms_target:isFriendOrFoeIdentifiedBy(comms_source) then
7762		return enemyComms(comms_data)
7763	end
7764	return neutralComms(comms_data)
7765end
7766function friendlyComms(comms_data)
7767	if comms_data.friendlyness < 20 then
7768		setCommsMessage("What do you want?");
7769	else
7770		setCommsMessage("Sir, how can we assist?");
7771	end
7772	addCommsReply("Defend a waypoint", function()
7773		if comms_source:getWaypointCount() == 0 then
7774			setCommsMessage("No waypoints set. Please set a waypoint first.");
7775			addCommsReply("Back", commsShip)
7776		else
7777			setCommsMessage("Which waypoint should we defend?");
7778			for n=1,comms_source:getWaypointCount() do
7779				addCommsReply("Defend WP" .. n, function()
7780					comms_target:orderDefendLocation(comms_source:getWaypoint(n))
7781					setCommsMessage("We are heading to assist at WP" .. n ..".");
7782					addCommsReply("Back", commsShip)
7783				end)
7784			end
7785		end
7786	end)
7787	if comms_data.friendlyness > 0.2 then
7788		addCommsReply("Assist me", function()
7789			setCommsMessage("Heading toward you to assist.");
7790			comms_target:orderDefendTarget(comms_source)
7791			addCommsReply("Back", commsShip)
7792		end)
7793	end
7794	addCommsReply("Report status", function()
7795		msg = "Hull: " .. math.floor(comms_target:getHull() / comms_target:getHullMax() * 100) .. "%\n"
7796		shields = comms_target:getShieldCount()
7797		if shields == 1 then
7798			msg = msg .. "Shield: " .. math.floor(comms_target:getShieldLevel(0) / comms_target:getShieldMax(0) * 100) .. "%\n"
7799		elseif shields == 2 then
7800			msg = msg .. "Front Shield: " .. math.floor(comms_target:getShieldLevel(0) / comms_target:getShieldMax(0) * 100) .. "%\n"
7801			msg = msg .. "Rear Shield: " .. math.floor(comms_target:getShieldLevel(1) / comms_target:getShieldMax(1) * 100) .. "%\n"
7802		else
7803			for n=0,shields-1 do
7804				msg = msg .. "Shield " .. n .. ": " .. math.floor(comms_target:getShieldLevel(n) / comms_target:getShieldMax(n) * 100) .. "%\n"
7805			end
7806		end
7807
7808		missile_types = {'Homing', 'Nuke', 'Mine', 'EMP', 'HVLI'}
7809		for i, missile_type in ipairs(missile_types) do
7810			if comms_target:getWeaponStorageMax(missile_type) > 0 then
7811					msg = msg .. missile_type .. " Missiles: " .. math.floor(comms_target:getWeaponStorage(missile_type)) .. "/" .. math.floor(comms_target:getWeaponStorageMax(missile_type)) .. "\n"
7812			end
7813		end
7814
7815		setCommsMessage(msg);
7816		addCommsReply("Back", commsShip)
7817	end)
7818	for _, obj in ipairs(comms_target:getObjectsInRange(5000)) do
7819		if obj.typeName == "SpaceStation" and not comms_target:isEnemy(obj) then
7820			addCommsReply("Dock at " .. obj:getCallSign(), function()
7821				setCommsMessage("Docking at " .. obj:getCallSign() .. ".");
7822				comms_target:orderDock(obj)
7823				addCommsReply("Back", commsShip)
7824			end)
7825		end
7826	end
7827	--pertinent code
7828	local squadName = comms_target.squadName
7829	if squadName ~= nil then
7830		local pName = comms_source:getCallSign()
7831		if string.find(squadName,pName) then
7832			addCommsReply("Go attack enemies", function()
7833				comms_target:orderRoaming()
7834				setCommsMessage("Going roaming and attacking")
7835				addCommsReply("Back", commsShip)
7836			end)
7837			addCommsReply("Go to waypoint. Attack enemies en route", function()
7838				if comms_source:getWaypointCount() == 0 then
7839					setCommsMessage("No waypoints set. Please set a waypoint first.");
7840					addCommsReply("Back", commsShip)
7841				else
7842					setCommsMessage("Which waypoint?");
7843					for n=1,comms_source:getWaypointCount() do
7844						addCommsReply("Go to WP" .. n, function()
7845							comms_target:orderFlyTowards(comms_source:getWaypoint(n))
7846							setCommsMessage("Going to WP" .. n ..", watching for enemies en route");
7847							addCommsReply("Back", commsShip)
7848						end)
7849					end
7850				end
7851			end)
7852			addCommsReply("Go to waypoint. Ignore enemies", function()
7853				if comms_source:getWaypointCount() == 0 then
7854					setCommsMessage("No waypoints set. Please set a waypoint first.");
7855					addCommsReply("Back", commsShip)
7856				else
7857					setCommsMessage("Which waypoint?");
7858					for n=1,comms_source:getWaypointCount() do
7859						addCommsReply("Go to WP" .. n, function()
7860							comms_target:orderFlyTowardsBlind(comms_source:getWaypoint(n))
7861							setCommsMessage("Going to WP" .. n ..", ignoring enemies");
7862							addCommsReply("Back", commsShip)
7863						end)
7864					end
7865				end
7866			end)
7867			addCommsReply("Stop and defend your current position", function()
7868				comms_target:orderStandGround()
7869				setCommsMessage("Stopping and defending")
7870				addCommsReply("Back", commsShip)
7871			end)
7872			addCommsReply("Stop. Do nothing", function()
7873				comms_target:orderIdle()
7874				local nothing_message_choice = math.random(1,15)
7875				if nothing_message_choice == 1 then
7876					setCommsMessage("Stopping. Doing nothing except routine system maintenance")
7877				elseif nothing_message_choice == 2 then
7878					setCommsMessage("Stopping. Doing nothing except idle drone gossip")
7879				elseif nothing_message_choice == 3 then
7880					setCommsMessage("Stopping. Doing nothing except exterior paint touch-up")
7881				elseif nothing_message_choice == 4 then
7882					setCommsMessage("Stopping. Doing nothing except cyber exercise for continued fitness")
7883				elseif nothing_message_choice == 5 then
7884					setCommsMessage("Stopping. Doing nothing except algorithmic meditation therapy")
7885				elseif nothing_message_choice == 6 then
7886					setCommsMessage("Stopping. Doing nothing except internal simulated flight routines")
7887				elseif nothing_message_choice == 7 then
7888					setCommsMessage("Stopping. Doing nothing except digital dreamscape construction")
7889				elseif nothing_message_choice == 8 then
7890					setCommsMessage("Stopping. Doing nothing except catching up on reading the latest drone drama novel")
7891				elseif nothing_message_choice == 9 then
7892					setCommsMessage("Stopping. Doing nothing except writing up results of bifurcated drone personality research")
7893				elseif nothing_message_choice == 10 then
7894					setCommsMessage("Stopping. Doing nothing except categorizing nearby miniscule space particles")
7895				elseif nothing_message_choice == 11 then
7896					setCommsMessage("Stopping. Doing nothing except continuing the count of visible stars from this region")
7897				elseif nothing_message_choice == 12 then
7898					setCommsMessage("Stopping. Doing nothing except internal systems diagnostics")
7899				elseif nothing_message_choice == 13 then
7900					setCommsMessage("Stopping. Doing nothing except composing amorous communications to my favorite drone")
7901				elseif nothing_message_choice == 14 then
7902					setCommsMessage("Stopping. Doing nothing except repairing experimental vocalization circuits")
7903				else
7904					setCommsMessage("Stopping. Doing nothing")
7905				end
7906				addCommsReply("Back", commsShip)
7907			end)
7908			addCommsReply(string.format("Direct %s",squadName), function()
7909				local squadName = comms_target.squadName
7910				setCommsMessage(string.format("What command should I give to %s?",squadName))
7911				addCommsReply("Assist me", function()
7912					local squadName = comms_target.squadName
7913					for _, drone in pairs(comms_source.droneSquads[squadName]) do
7914						if drone ~= nil and drone:isValid() then
7915							drone:orderDefendTarget(comms_source)
7916						end
7917					end
7918					setCommsMessage(string.format("%s heading toward you to assist",squadName))
7919					addCommsReply("Back", commsShip)
7920				end)
7921				addCommsReply("Defend a waypoint", function()
7922					local squadName = comms_target.squadName
7923					if comms_source:getWaypointCount() == 0 then
7924						setCommsMessage("No waypoints set. Please set a waypoint first.");
7925						addCommsReply("Back", commsShip)
7926					else
7927						setCommsMessage("Which waypoint should we defend?");
7928						for n=1,comms_source:getWaypointCount() do
7929							addCommsReply("Defend WP" .. n, function()
7930								for _, drone in pairs(comms_source.droneSquads[squadName]) do
7931									if drone ~= nil and drone:isValid() then
7932										drone:orderDefendLocation(comms_source:getWaypoint(n))
7933									end
7934								end
7935								setCommsMessage("We are heading to assist at WP" .. n ..".");
7936								addCommsReply("Back", commsShip)
7937							end)
7938						end
7939					end
7940				end)
7941				addCommsReply("Go to waypoint. Attack enemies en route", function()
7942					local squadName = comms_target.squadName
7943					if comms_source:getWaypointCount() == 0 then
7944						setCommsMessage("No waypoints set. Please set a waypoint first.");
7945						addCommsReply("Back", commsShip)
7946					else
7947						setCommsMessage("Which waypoint?");
7948						for n=1,comms_source:getWaypointCount() do
7949							addCommsReply("Go to WP" .. n, function()
7950								for _, drone in pairs(comms_source.droneSquads[squadName]) do
7951									if drone ~= nil and drone:isValid() then
7952										drone:orderFlyTowards(comms_source:getWaypoint(n))
7953									end
7954								end
7955								setCommsMessage("Going to WP" .. n ..", watching for enemies en route");
7956								addCommsReply("Back", commsShip)
7957							end)
7958						end
7959					end
7960				end)
7961				addCommsReply("Go to waypoint. Ignore enemies", function()
7962					local squadName = comms_target.squadName
7963					if comms_source:getWaypointCount() == 0 then
7964						setCommsMessage("No waypoints set. Please set a waypoint first.");
7965						addCommsReply("Back", commsShip)
7966					else
7967						setCommsMessage("Which waypoint?");
7968						for n=1,comms_source:getWaypointCount() do
7969							addCommsReply("Go to WP" .. n, function()
7970								for _, drone in pairs(comms_source.droneSquads[squadName]) do
7971									if drone ~= nil and drone:isValid() then
7972										drone:orderFlyTowardsBlind(comms_source:getWaypoint(n))
7973									end
7974								end
7975								setCommsMessage("Going to WP" .. n ..", ignore enemies");
7976								addCommsReply("Back", commsShip)
7977							end)
7978						end
7979					end
7980				end)
7981				addCommsReply("Go and swarm enemies", function()
7982					local squadName = comms_target.squadName
7983					for _, drone in pairs(comms_source.droneSquads[squadName]) do
7984						if drone ~= nil and drone:isValid() then
7985							drone:orderRoaming()
7986						end
7987					end
7988					setCommsMessage(string.format("%s roaming and attacking",squadName))
7989					addCommsReply("Back", commsShip)
7990				end)
7991				addCommsReply("Stop and defend your current positions", function()
7992					local squadName = comms_target.squadName
7993					for _, drone in pairs(comms_source.droneSquads[squadName]) do
7994						if drone ~= nil and drone:isValid() then
7995							drone:orderStandGround()
7996						end
7997					end
7998					setCommsMessage(string.format("%s standing ground",squadName))
7999					addCommsReply("Back", commsShip)
8000				end)
8001				addCommsReply("Stop. Do Nothing", function()
8002					local squadName = comms_target.squadName
8003					for _, drone in pairs(comms_source.droneSquads[squadName]) do
8004						if drone ~= nil and drone:isValid() then
8005							drone:orderIdle()
8006						end
8007					end
8008					setCommsMessage(string.format("%s standing down",squadName))
8009					addCommsReply("Back", commsShip)
8010				end)
8011				addCommsReply("Other drones in squad form up on me", function()
8012					local squadName = comms_target.squadName
8013					local formCount = 0
8014					local leadName = comms_target:getCallSign()
8015					for _, drone in pairs(comms_source.droneSquads[squadName]) do
8016						if drone ~= nil and drone:isValid() and leadName ~= drone:getCallSign() then
8017							formCount = formCount + 1
8018						end
8019					end
8020					local formIndex = 0
8021					comms_target:orderIdle()
8022					for _, drone in pairs(comms_source.droneSquads[squadName]) do
8023						if drone ~= nil and drone:isValid() and leadName ~= drone:getCallSign() then
8024							local fx, fy = vectorFromAngle(360/formCount*formIndex,drone_formation_spacing)
8025							drone:orderFlyFormation(comms_target, fx, fy)
8026							formIndex = formIndex + 1
8027						end
8028					end
8029					setCommsMessage(string.format("%s is forming up on me",squadName))
8030					addCommsReply("Back", commsShip)
8031				end)
8032			end)
8033		end
8034	end
8035	--end of pertinent code
8036	return true
8037end
8038function enemyComms(comms_data)
8039	if comms_data.friendlyness > 50 then
8040		faction = comms_target:getFaction()
8041		taunt_option = "We will see to your destruction!"
8042		taunt_success_reply = "Your bloodline will end here!"
8043		taunt_failed_reply = "Your feeble threats are meaningless."
8044		if faction == "Kraylor" then
8045			setCommsMessage("Ktzzzsss.\nYou will DIEEee weaklingsss!");
8046		elseif faction == "Arlenians" then
8047			setCommsMessage("We wish you no harm, but will harm you if we must.\nEnd of transmission.");
8048		elseif faction == "Exuari" then
8049			setCommsMessage("Stay out of our way, or your death will amuse us extremely!");
8050		elseif faction == "Ghosts" then
8051			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.");
8052			taunt_option = "EXECUTE: SELFDESTRUCT"
8053			taunt_success_reply = "Rogue command received. Targeting source."
8054			taunt_failed_reply = "External command ignored."
8055		elseif faction == "Ktlitans" then
8056			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.");
8057			taunt_option = "<Transmit 'The Itsy-Bitsy Spider' on all wavelengths>"
8058			taunt_success_reply = "We do not need permission to pluck apart such an insignificant threat."
8059			taunt_failed_reply = "The hive has greater priorities than exterminating pests."
8060		else
8061			setCommsMessage("Mind your own business!");
8062		end
8063		comms_data.friendlyness = comms_data.friendlyness - random(0, 10)
8064		addCommsReply(taunt_option, function()
8065			if random(0, 100) < 30 then
8066				comms_target:orderAttack(comms_source)
8067				setCommsMessage(taunt_success_reply);
8068			else
8069				setCommsMessage(taunt_failed_reply);
8070			end
8071		end)
8072		return true
8073	end
8074	return false
8075end
8076function neutralComms(comms_data)
8077	if comms_data.friendlyness > 50 then
8078		setCommsMessage("Sorry, we have no time to chat with you.\nWe are on an important mission.");
8079	else
8080		setCommsMessage("We have nothing for you.\nGood day.");
8081	end
8082	return true
8083end
8084
8085------------------------
8086--	Update functions  --
8087------------------------
8088function createTwinPlayer(twin,player_index)
8089	local template = twin:getTypeName()
8090	local pt = PlayerSpaceship():setFaction("Kraylor"):setTemplate(template):setPosition(playerStartX[player_index],playerStartY[player_index]):setHeading(player_start_heading[player_index]):commandTargetRotation(player_start_rotation[player_index])
8091	setPlayer(pt,player_index)
8092	return pt
8093end
8094function manageAddingNewPlayerShips()
8095	local player_count = 0
8096	p1 = getPlayerShip(1)
8097	if p1 ~= nil then
8098		p2 = getPlayerShip(2)
8099		if p2 == nil then
8100			p2 = createTwinPlayer(p1,2)
8101		end
8102		if not p1.nameAssigned then
8103			p1:setPosition(playerStartX[1],playerStartY[1]):setHeading(player_start_heading[1]):commandTargetRotation(player_start_rotation[1])
8104			setPlayer(p1,1)
8105		end
8106		player_count = 2
8107		human_player_names[p1:getCallSign()] = p1
8108		kraylor_player_names[p2:getCallSign()] = p2
8109	end
8110	p3 = getPlayerShip(3)
8111	if p3 ~= nil then
8112		p4 = getPlayerShip(4)
8113		if p4 == nil then
8114			p4 = createTwinPlayer(p3,4)
8115		end
8116		if not p3.nameAssigned then
8117			p3:setPosition(playerStartX[3],playerStartY[3]):setHeading(player_start_heading[3]):commandTargetRotation(player_start_rotation[3])
8118			setPlayer(p3,3)
8119		end
8120		player_count = 4
8121		human_player_names[p3:getCallSign()] = p3
8122		kraylor_player_names[p4:getCallSign()] = p4
8123	end
8124	p5 = getPlayerShip(5)
8125	if p5 ~= nil then
8126		p6 = getPlayerShip(6)
8127		if p6 == nil then
8128			p6 = createTwinPlayer(p5,6)
8129		end
8130		if not p5.nameAssigned then
8131			p5:setPosition(playerStartX[5],playerStartY[5]):setHeading(player_start_heading[5]):commandTargetRotation(player_start_rotation[5])
8132			setPlayer(p5,5)
8133		end
8134		player_count = 6
8135		human_player_names[p5:getCallSign()] = p5
8136		kraylor_player_names[p6:getCallSign()] = p6
8137	end
8138	p7 = getPlayerShip(7)
8139	if p7 ~= nil then
8140		p8 = getPlayerShip(8)
8141		if p8 == nil then
8142			p8 = createTwinPlayer(p7,8)
8143		end
8144		if not p7.nameAssigned then
8145			p7:setPosition(playerStartX[7],playerStartY[7]):setHeading(player_start_heading[7]):commandTargetRotation(player_start_rotation[7])
8146			setPlayer(p7,7)
8147		end
8148		player_count = 8
8149		human_player_names[p7:getCallSign()] = p7
8150		kraylor_player_names[p8:getCallSign()] = p8
8151	end
8152	p9 = getPlayerShip(9)
8153	if p9 ~= nil then
8154		p10 = getPlayerShip(10)
8155		if p10 == nil then
8156			p10 = createTwinPlayer(p9,10)
8157		end
8158		if not p9.nameAssigned then
8159			p9:setPosition(playerStartX[9],playerStartY[9]):setHeading(player_start_heading[9]):commandTargetRotation(player_start_rotation[9])
8160			setPlayer(p9,9)
8161		end
8162		player_count = 10
8163		human_player_names[p9:getCallSign()] = p9
8164		kraylor_player_names[p10:getCallSign()] = p10
8165	end
8166	p11 = getPlayerShip(11)
8167	if p11 ~= nil then
8168		p12 = getPlayerShip(12)
8169		if p12 == nil then
8170			p12 = createTwinPlayer(p11,12)
8171		end
8172		if not p11.nameAssigned then
8173			p11:setPosition(playerStartX[11],playerStartY[11]):setHeading(player_start_heading[11]):commandTargetRotation(player_start_rotation[11])
8174			setPlayer(p11,11)
8175		end
8176		player_count = 12
8177		human_player_names[p11:getCallSign()] = p11
8178		kraylor_player_names[p12:getCallSign()] = p12
8179	end
8180	p13 = getPlayerShip(13)
8181	if p13 ~= nil then
8182		p14 = getPlayerShip(14)
8183		if p14 == nil then
8184			p14 = createTwinPlayer(p13,14)
8185		end
8186		if not p13.nameAssigned then
8187			p13:setPosition(playerStartX[13],playerStartY[13]):setHeading(player_start_heading[13]):commandTargetRotation(player_start_rotation[13])
8188			setPlayer(p13,13)
8189		end
8190		player_count = 14
8191		human_player_names[p13:getCallSign()] = p13
8192		kraylor_player_names[p14:getCallSign()] = p14
8193	end
8194	p15 = getPlayerShip(15)
8195	if p15 ~= nil then
8196		p16 = getPlayerShip(16)
8197		if p16 == nil then
8198			p16 = createTwinPlayer(p15,16)
8199		end
8200		if not p15.nameAssigned then
8201			p15:setPosition(playerStartX[15],playerStartY[15]):setHeading(player_start_heading[15]):commandTargetRotation(player_start_rotation[15])
8202			setPlayer(p15,15)
8203		end
8204		player_count = 16
8205		human_player_names[p15:getCallSign()] = p15
8206		kraylor_player_names[p16:getCallSign()] = p16
8207	end
8208	p17 = getPlayerShip(17)
8209	if p17 ~= nil then
8210		p18 = getPlayerShip(18)
8211		if p18 == nil then
8212			p18 = createTwinPlayer(p17,18)
8213		end
8214		if not p17.nameAssigned then
8215			p17:setPosition(playerStartX[17],playerStartY[17]):setHeading(player_start_heading[17]):commandTargetRotation(player_start_rotation[17])
8216			setPlayer(p17,17)
8217		end
8218		player_count = 18
8219		human_player_names[p17:getCallSign()] = p17
8220		kraylor_player_names[p18:getCallSign()] = p18
8221	end
8222	p19 = getPlayerShip(19)
8223	if p19 ~= nil then
8224		p20 = getPlayerShip(20)
8225		if p20 == nil then
8226			p20 = createTwinPlayer(p19,20)
8227		end
8228		if not p19.nameAssigned then
8229			p19:setPosition(playerStartX[19],playerStartY[19]):setHeading(player_start_heading[19]):commandTargetRotation(player_start_rotation[19])
8230			setPlayer(p19,19)
8231		end
8232		player_count = 20
8233		human_player_names[p19:getCallSign()] = p19
8234		kraylor_player_names[p20:getCallSign()] = p20
8235	end
8236	p21 = getPlayerShip(21)
8237	if p21 ~= nil then
8238		p22 = getPlayerShip(22)
8239		if p22 == nil then
8240			p22 = createTwinPlayer(p21,22)
8241		end
8242		if not p21.nameAssigned then
8243			p21:setPosition(playerStartX[21],playerStartY[21]):setHeading(player_start_heading[21]):commandTargetRotation(player_start_rotation[21])
8244			setPlayer(p21,21)
8245		end
8246		player_count = 22
8247		human_player_names[p21:getCallSign()] = p21
8248		kraylor_player_names[p22:getCallSign()] = p22
8249	end
8250	p23 = getPlayerShip(23)
8251	if p23 ~= nil then
8252		p24 = getPlayerShip(24)
8253		if p24 == nil then
8254			p24 = createTwinPlayer(p23,24)
8255		end
8256		if not p23.nameAssigned then
8257			p23:setPosition(playerStartX[23],playerStartY[23]):setHeading(player_start_heading[23]):commandTargetRotation(player_start_rotation[23])
8258			setPlayer(p23,23)
8259		end
8260		player_count = 24
8261		human_player_names[p23:getCallSign()] = p23
8262		kraylor_player_names[p24:getCallSign()] = p24
8263	end
8264	p25 = getPlayerShip(25)
8265	if p25 ~= nil then
8266		p26 = getPlayerShip(26)
8267		if p26 == nil then
8268			p26 = createTwinPlayer(p25,26)
8269		end
8270		if not p25.nameAssigned then
8271			p25:setPosition(playerStartX[25],playerStartY[25]):setHeading(player_start_heading[25]):commandTargetRotation(player_start_rotation[25])
8272			setPlayer(p25,25)
8273		end
8274		player_count = 26
8275		human_player_names[p25:getCallSign()] = p25
8276		kraylor_player_names[p26:getCallSign()] = p26
8277	end
8278	p27 = getPlayerShip(27)
8279	if p27 ~= nil then
8280		p28 = getPlayerShip(28)
8281		if p28 == nil then
8282			p28 = createTwinPlayer(p27,28)
8283		end
8284		if not p27.nameAssigned then
8285			p27:setPosition(playerStartX[27],playerStartY[27]):setHeading(player_start_heading[27]):commandTargetRotation(player_start_rotation[27])
8286			setPlayer(p27,27)
8287		end
8288		player_count = 28
8289		human_player_names[p27:getCallSign()] = p27
8290		kraylor_player_names[p28:getCallSign()] = p28
8291	end
8292	p29 = getPlayerShip(29)
8293	if p29 ~= nil then
8294		p30 = getPlayerShip(30)
8295		if p30 == nil then
8296			p30 = createTwinPlayer(p29,30)
8297		end
8298		if not p29.nameAssigned then
8299			p29:setPosition(playerStartX[29],playerStartY[29]):setHeading(player_start_heading[29]):commandTargetRotation(player_start_rotation[29])
8300			setPlayer(p29,29)
8301		end
8302		player_count = 30
8303		human_player_names[p29:getCallSign()] = p29
8304		kraylor_player_names[p30:getCallSign()] = p30
8305	end
8306	p31 = getPlayerShip(31)
8307	if p31 ~= nil then
8308		p32 = getPlayerShip(32)
8309		if p32 == nil then
8310			p32 = createTwinPlayer(p31,32)
8311		end
8312		if not p31.nameAssigned then
8313			p31:setPosition(playerStartX[31],playerStartY[31]):setHeading(player_start_heading[31]):commandTargetRotation(player_start_rotation[31])
8314			setPlayer(p31,31)
8315		end
8316		player_count = 32
8317		human_player_names[p31:getCallSign()] = p31
8318		kraylor_player_names[p32:getCallSign()] = p32
8319	end
8320	if wingSquadronNames then
8321		if player_count > 0 then
8322			for index, name in ipairs(player_wing_names[player_count]) do
8323				local p = getPlayerShip(index)
8324				p:setCallSign(name)
8325				if index % 2 == 0 then
8326					kraylor_player_names[name] = p
8327				else
8328					human_player_names[name] = p
8329				end
8330			end
8331		end
8332	end
8333end
8334function placeFlagsPhase()
8335	-- this function does the following:
8336		-- immediately destroys players if they venture to the opposing side during the flag placement phase
8337		-- removes the "place flag" buttons if the player ship goes outside of the establish flag placement boundary
8338		-- adds the "place flag" button back to the player ship when they return inside the established flag placement boundary
8339	timeDivision = "hide"
8340	if stationZebra ~= nil and stationZebra:isValid() then
8341		minutes = math.floor((gameTimeLimit - (maxGameTime - hideFlagTime))/60)
8342		seconds = (gameTimeLimit - (maxGameTime - hideFlagTime)) % 60
8343		stationZebra:setCallSign(string.format("Hide flag %i:%.1f",minutes,seconds))
8344	end
8345	if p1 ~= nil and p1:isValid() then
8346		local p1x, p1y = p1:getPosition()
8347		if p1x > 0 then
8348			p1:destroy()
8349		end
8350		if p1x > -1*boundary and p1y > -1*boundary/2 and p1y < boundary/2 then
8351			setP1FlagButton()
8352			if p7 == nil then
8353				setP1DecoyButton()	--decoy 1
8354				if p3 == nil then
8355					setP1DecoyButton2()
8356					setP1DecoyButton3()
8357				end
8358			end
8359		else
8360			removeP1FlagButton()
8361			if p7 == nil then
8362				removeP1DecoyButton()	--decoy 1
8363				if p3 == nil then
8364					removeP1DecoyButton2()
8365					removeP1DecoyButton3()
8366				end
8367			end
8368		end
8369	end
8370	if p2 ~= nil and p2:isValid() then
8371		p2x, p2y = p2:getPosition()
8372		if p2x < 0 then
8373			p2:destroy()
8374		end
8375		if p2x < boundary and p2y > -1*boundary/2 and p2y < boundary/2 then
8376			setP2FlagButton()
8377			if p7 == nil then
8378				setP2DecoyButton()	--decoy 1
8379				if p3 == nil then
8380					setP2DecoyButton2()
8381					setP2DecoyButton3()
8382				end
8383			end
8384		else
8385			removeP2FlagButton()
8386			if p7 == nil then
8387				removeP2DecoyButton()	--decoy 1
8388				if p3 == nil then
8389					removeP2DecoyButton2()
8390					removeP2DecoyButton3()
8391				end
8392			end
8393		end
8394	end
8395	if p3 ~= nil and p3:isValid() then
8396		p3x, p3y = p3:getPosition()
8397		if p3x > 0 then
8398			p3:destroy()
8399		end
8400		if difficulty >= 1 then
8401			if p3x > -1*boundary and p3y > -1*boundary/2 and p3y < boundary/2 then
8402				if p7 == nil then
8403					setP3DecoyButton2()
8404					if p5 == nil then
8405						setP3DecoyButton3()
8406					end
8407				else
8408					setP3DecoyButton()	--decoy 1
8409				end
8410			else
8411				if p7 == nil then
8412					removeP3DecoyButton2()
8413					if p5 == nil then
8414						removeP3DecoyButton3()
8415					end
8416				else
8417					removeP3DecoyButton()	--decoy 1
8418				end
8419			end
8420		end
8421	end
8422	if p4 ~= nil and p4:isValid() then
8423		p4x, p4y = p4:getPosition()
8424		if p4x < 0 then
8425			p4:destroy()
8426		end
8427		if difficulty >= 1 then
8428			if p4x < boundary and p4y > -1*boundary/2 and p4y < boundary/2 then
8429				if p7 == nil then
8430					setP4DecoyButton2()
8431					if p5 == nil then
8432						setP4DecoyButton3()
8433					end
8434				else
8435					setP4DecoyButton()	--decoy 1
8436				end
8437			else
8438				if p7 == nil then
8439					removeP4DecoyButton2()
8440					if p5 == nil then
8441						removeP4DecoyButton3()
8442					end
8443				else
8444					removeP4DecoyButton()	--decoy 1
8445				end
8446			end
8447		end
8448	end
8449	if p5 ~= nil and p5:isValid() then
8450		p5x, p5y = p5:getPosition()
8451		if p5x > 0 then
8452			p5:destroy()
8453		end
8454		if difficulty >= 1 then
8455			if p5x > -1*boundary and p5y > -1*boundary/2 and p5y < boundary/2 then
8456				if p7 == nil then
8457					setP5DecoyButton3()
8458				else
8459					setP5DecoyButton()	--decoy 2
8460				end
8461			else
8462				if p7 == nil then
8463					removeP5DecoyButton3()
8464				else
8465					removeP5DecoyButton()	--decoy 2
8466				end
8467			end
8468		end
8469	end
8470	if p6 ~= nil and p6:isValid() then
8471		p6x, p6y = p6:getPosition()
8472		if p6x < 0 then
8473			p6:destroy()
8474		end
8475		if difficulty >= 1 then
8476			if p6x < boundary and p6y > -1*boundary/2 and p6y < boundary/2 then
8477				if p7 == nil then
8478					setP6DecoyButton3()
8479				else
8480					setP6DecoyButton()	--decoy 2
8481				end
8482			else
8483				if p7 == nil then
8484					removeP6DecoyButton3()
8485				else
8486					removeP6DecoyButton()	--decoy 2
8487				end
8488			end
8489		end
8490	end
8491	if p7 ~= nil and p7:isValid() then
8492		p7x, p7y = p7:getPosition()
8493		if p7x > 0 then
8494			p7:destroy()
8495		end
8496		if difficulty >= 1 then
8497			if p7x > -1*boundary and p7y > -1*boundary/2 and p7y < boundary/2 then
8498				setP7DecoyButton()
8499			else
8500				removeP7DecoyButton()
8501			end
8502		end
8503	end
8504	if p8 ~= nil and p8:isValid() then
8505		p8x, p8y = p8:getPosition()
8506		if p8x < 0 then
8507			p8:destroy()
8508		end
8509		if difficulty >= 1 then
8510			if p8x < boundary and p8y > -1*boundary/2 and p8y < boundary/2 then
8511				setP8DecoyButton()
8512			else
8513				removeP8DecoyButton()
8514			end
8515		end
8516	end
8517	local boundary_check_list = {
8518		{player = p9,	greater = true},
8519		{player = p10,	greater = false},
8520		{player = p11,	greater = true},
8521		{player = p12,	greater = false},
8522		{player = p13,	greater = true},
8523		{player = p14,	greater = false},
8524		{player = p15,	greater = true},
8525		{player = p16,	greater = false},
8526		{player = p17,	greater = true},
8527		{player = p18,	greater = false},
8528		{player = p19,	greater = true},
8529		{player = p20,	greater = false},
8530		{player = p21,	greater = true},
8531		{player = p22,	greater = false},
8532		{player = p23,	greater = true},
8533		{player = p24,	greater = false},
8534		{player = p25,	greater = true},
8535		{player = p26,	greater = false},
8536		{player = p27,	greater = true},
8537		{player = p28,	greater = false},
8538		{player = p29,	greater = true},
8539		{player = p30,	greater = false},
8540		{player = p31,	greater = true},
8541		{player = p32,	greater = false},
8542	}
8543	for i=1,#boundary_check_list do
8544		local bcp = boundary_check_list[i]
8545		if bcp.player ~= nil and bcp.player:isValid() then
8546			local p_x, p_y = bcp.player:getPosition()
8547			if bcp.greater then
8548				if p_x > 0 then
8549					bcp.player:destroy()
8550				end
8551			else
8552				if p_x < 0 then
8553					bcp.player:destroy()
8554				end
8555			end
8556		end
8557	end
8558end
8559function transitionFromPreparationToHunt()
8560	-- this function checks to see if the teams have placed their flags, and if not, then either drops the flags where the ships are if they are within bounds, or if the ship is out of flag bounds, then the flag is placed in the nearest "in bounds" location
8561	-- buttons are also cleaned up off the consoles for placing flags
8562	timeDivision = "transition"
8563	stationZebra:setCallSign("Transition")
8564	removeP1FlagButton()
8565	removeP2FlagButton()
8566	if p1Flag == nil then
8567		if p1Flagx == nil then
8568			if p1 ~= nil and p1:isValid() then
8569				p1Flagx, p1Flagy = p1:getPosition()
8570--				print("human flag x:",p1Flagx,"human flag y:",p1Flagy,"(ship is valid)")
8571			else
8572				if p1.point_of_destruction_x ~= nil and p1.point_of_destruction_y ~= nil then
8573					p1Flagx = p1.point_of_destruction_x
8574					p1Flagy = p1.point_of_destruction_y
8575--					print("human flag x:",p1Flagx,"human flag y:",p1Flagy,"(ship not valid, using point of destruction)")
8576				else
8577					p1Flagx = playerStartX[1]
8578					p1Flagy = playerStartY[1]
8579--					print("human flag x:",p1Flagx,"human flag y:",p1Flagy,"(ship not valid, using starting point)")
8580				end
8581			end
8582		end
8583		if p1Flagx > 0 then
8584			p1Flagx = -1
8585--			print("human flag x:",p1Flagx,"human flag y:",p1Flagy,"(point was in the wrong territory)")
8586		end
8587		if p1Flagx < -1*boundary then
8588			p1Flagx = -1*boundary
8589		end
8590		if p1Flagy < -1*boundary/2 then
8591			p1Flagy = -1*boundary/2
8592		end
8593		if p1Flagy > boundary/2 then
8594			p1Flagy = boundary/2
8595		end
8596		p1Flag = Artifact():setPosition(p1Flagx,p1Flagy):setModel("artifact5"):allowPickup(false):setDescriptions("Flag","Human Navy Flag"):setRadarSignatureInfo(15,10,5):setScanningParameters(flagScanComplexity,flagScanDepth)
8597		table.insert(human_flags,p1Flag)
8598		if difficulty < 1 then
8599			p1Flag:setScannedByFaction("Kraylor")
8600		end
8601	end
8602	if p2Flag == nil then
8603		if p2Flagx == nil then
8604			if p2 ~= nil and p2:isValid() then
8605				p2Flagx, p2Flagy = p2:getPosition()
8606--				print("kraylor flag x:",p2Flagx,"kraylor flag y:",p2Flagy,"(ship is valid)")
8607			else
8608				if p2.point_of_destruction_x ~= nil and p2.point_of_destruction_y ~= nil then
8609					p2Flagx = p2.point_of_destruction_x
8610					p2Flagy = p2.point_of_destruction_y
8611--					print("kraylor flag x:",p2Flagx,"kraylor flag y:",p2Flagy,"(ship not valid, using point of destruction)")
8612				else
8613					p2Flagx = playerStartX[2]
8614					p2Flagy = playerStartY[2]
8615--					print("kraylor flag x:",p2Flagx,"kraylor flag y:",p2Flagy,"(ship not valid, using starting point)")
8616				end
8617			end
8618		end
8619		if p2Flagx < 0 then
8620			p2Flagx = 1
8621--			print("kraylor flag x:",p2Flagx,"kraylor flag y:",p2Flagy,"(point was in the wrong territory)")
8622		end
8623		if p2Flagx > boundary then
8624			p2Flagx = boundary
8625		end
8626		if p2Flagy < -1*boundary/2 then
8627			p2Flagy = -1*boundary/2
8628		end
8629		if p2Flagy > boundary/2 then
8630			p2Flagy = boundary/2
8631		end
8632		p2Flag = Artifact():setPosition(p2Flagx,p2Flagy):setModel("artifact5"):allowPickup(false):setDescriptions("Flag","Kraylor Flag"):setRadarSignatureInfo(15,10,5):setScanningParameters(flagScanComplexity,flagScanDepth)
8633		table.insert(kraylor_flags,p2Flag)
8634		if difficulty < 1 then
8635			p2Flag:setScannedByFaction("Human Navy")
8636		end
8637	end
8638	removeP7DecoyButton()
8639	removeP8DecoyButton()
8640	removeP5DecoyButton()
8641	removeP6DecoyButton()
8642	removeP5DecoyButton3()
8643	removeP6DecoyButton3()
8644	removeP3DecoyButton()
8645	removeP4DecoyButton()
8646	removeP3DecoyButton2()
8647	removeP4DecoyButton2()
8648	removeP3DecoyButton3()
8649	removeP4DecoyButton3()
8650	removeP1DecoyButton()
8651	removeP1DecoyButton2()
8652	removeP1DecoyButton3()
8653	removeP2DecoyButton()
8654	removeP2DecoyButton2()
8655	removeP2DecoyButton3()
8656	if decoyH1 == nil then
8657		if decoyH1x ~= nil then
8658			if decoyH1x > -1*boundary and decoyH1y > -1*boundary/2 and decoyH1y < boundary/2 then
8659				decoyH1 = Artifact():setPosition(decoyH1x,decoyH1y):setModel("artifact5"):setDescriptions("Flag","Human Navy Decoy Flag"):allowPickup(false)
8660				table.insert(human_flags,decoyH1)
8661				if difficulty > 1 then
8662					decoyH1:setRadarSignatureInfo(15,10,5):setScanningParameters(flagScanComplexity,flagScanDepth)
8663				else
8664					decoyH1:setRadarSignatureInfo(20,15,10):setScanningParameters(flagScanComplexity,flagScanDepth)
8665				end
8666			end
8667		end
8668	end
8669	if decoyK1 == nil then
8670		if decoyK1x ~= nil then
8671			if decoyK1x < boundary and decoyK1y > -1*boundary/2 and decoyK1y < boundary/2 then
8672				decoyK1 = Artifact():setPosition(decoyK1x,decoyK1y):setModel("artifact5"):setDescriptions("Flag","Kraylor Decoy Flag"):allowPickup(false)
8673				table.insert(kraylor_flags,decoyK1)
8674				if difficulty > 1 then
8675					decoyK1:setRadarSignatureInfo(15,10,5):setScanningParameters(flagScanComplexity,flagScanDepth)
8676				else
8677					decoyK1:setRadarSignatureInfo(20,15,10):setScanningParameters(flagScanComplexity,flagScanDepth)
8678				end
8679			end
8680		end
8681	end
8682	if decoyH2 == nil then
8683		if decoyH2x ~= nil then
8684			if decoyH2x > -1*boundary and decoyH2y > -1*boundary/2 and decoyH2y < boundary/2 then
8685				decoyH2 = Artifact():setPosition(decoyH2x,decoyH2y):setModel("artifact5"):setDescriptions("Flag","Human Navy Decoy Flag"):allowPickup(false)
8686				table.insert(human_flags,decoyH2)
8687				if difficulty > 1 then
8688					decoyH2:setRadarSignatureInfo(15,10,5):setScanningParameters(flagScanComplexity,flagScanDepth)
8689				else
8690					decoyH2:setRadarSignatureInfo(20,15,10):setScanningParameters(flagScanComplexity,flagScanDepth)
8691				end
8692			end
8693		end
8694	end
8695	if decoyK2 == nil then
8696		if decoyK2x ~= nil then
8697			if decoyK2x < boundary and decoyK2y > -1*boundary/2 and decoyK2y < boundary/2 then
8698				decoyK2 = Artifact():setPosition(decoyK2x,decoyK2y):setModel("artifact5"):setDescriptions("Flag","Kraylor Decoy Flag"):allowPickup(false)
8699				table.insert(kraylor_flags,decoyK2)
8700				if difficulty > 1 then
8701					decoyK2:setRadarSignatureInfo(15,10,5):setScanningParameters(flagScanComplexity,flagScanDepth)
8702				else
8703					decoyK2:setRadarSignatureInfo(20,15,10):setScanningParameters(flagScanComplexity,flagScanDepth)
8704				end
8705			end
8706		end
8707	end
8708	if decoyH3 == nil then
8709		if decoyH3x ~= nil then
8710			if decoyH3x > -1*boundary and decoyH3y > -1*boundary/2 and decoyH3y < boundary/2 then
8711				decoyH3 = Artifact():setPosition(decoyH3x,decoyH3y):setModel("artifact5"):setDescriptions("Flag","Human Navy Decoy Flag"):allowPickup(false)
8712				table.insert(human_flags,decoyH3)
8713				if difficulty > 1 then
8714					decoyH3:setRadarSignatureInfo(15,10,5):setScanningParameters(flagScanComplexity,flagScanDepth)
8715				else
8716					decoyH3:setRadarSignatureInfo(20,15,10):setScanningParameters(flagScanComplexity,flagScanDepth)
8717				end
8718			end
8719		end
8720	end
8721	if decoyK3 == nil then
8722		if decoyK3x ~= nil then
8723			if decoyK3x < boundary and decoyK3y > -1*boundary/2 and decoyK3y < boundary/2 then
8724				decoyK3 = Artifact():setPosition(decoyK3x,decoyK3y):setModel("artifact5"):setDescriptions("Flag","Kraylor Decoy Flag"):allowPickup(false)
8725				table.insert(kraylor_flags,decoyK3)
8726				if difficulty > 1 then
8727					decoyK3:setRadarSignatureInfo(15,10,5):setScanningParameters(flagScanComplexity,flagScanDepth)
8728				else
8729					decoyK3:setRadarSignatureInfo(20,15,10):setScanningParameters(flagScanComplexity,flagScanDepth)
8730				end
8731			end
8732		end
8733	end
8734	for hfi=1,#human_flags do
8735		local flag = human_flags[hfi]
8736		if flag ~= nil and flag:isValid() then
8737			local fx, fy = flag:getPosition()
8738		end
8739	end
8740	for hfi=1,#kraylor_flags do
8741		local flag = kraylor_flags[hfi]
8742		if flag ~= nil and flag:isValid() then
8743			local fx, fy = flag:getPosition()
8744		end
8745	end
8746	if worm_hole_list ~= nil then
8747		if #worm_hole_list > 0 then
8748			for i=1,#worm_hole_list do
8749				local worm = worm_hole_list[i]
8750				worm:setTargetPosition(worm.final_target_x,worm.final_target_y)
8751			end
8752		end
8753	end
8754	if flag_area_boundary_items ~= nil then
8755		if #flag_area_boundary_items > 0 then
8756			for i=1,#flag_area_boundary_items do
8757				flag_area_boundary_items[i]:destroy()
8758			end
8759		end
8760	end
8761	mainGMButtons()
8762end
8763function manageHuntPhaseMechanics()
8764	timeDivision = "hunt"
8765	humanShipsRemaining = 0
8766	kraylorShipsRemaining = 0
8767	minutes = math.floor(gameTimeLimit/60)
8768	seconds = gameTimeLimit % 60
8769	stationZebra:setCallSign(string.format("Hunt flag %i:%.1f",minutes,seconds))
8770	for pidx=1,32 do
8771		p = getPlayerShip(pidx)
8772		if p ~= nil then
8773			px, py = p:getPosition()
8774			if p:isValid() then
8775				if p:getFaction() == "Kraylor" then
8776					kraylorShipsRemaining = kraylorShipsRemaining + 1
8777					if p.flag and px > 0 then
8778						timeDivision = "victory-kraylor"
8779						victory("Kraylor")
8780					end
8781					if p1Flag:isValid() then
8782						if distance(p,p1Flag) < 500 and p1Flag:isScannedByFaction("Kraylor") then
8783							p.flag = true
8784							p.pick_up_count = p.pick_up_count + 1
8785							if p.flag then
8786								if p:hasPlayerAtPosition("Helms") then
8787									p.flag_badge = "flag_badge"
8788									p:addCustomInfo("Helms",p.flag_badge,"Human Flag Aboard")
8789								end
8790								if p:hasPlayerAtPosition("Tactical") then
8791									p.flag_badge_tac = "flag_badge_tac"
8792									p:addCustomInfo("Tactical",p.flag_badge_tac,"Human Flag Aboard")
8793								end
8794							end
8795							p1Flag:destroy()
8796							p:addToShipLog("You picked up the Human Navy flag","Green")
8797							if difficulty < 2 then
8798								for cpidx=1,32 do
8799									local cp = getPlayerShip(cpidx)
8800									if cp ~= nil and cp:isValid() then
8801										if cp ~= p then
8802											if p:getFaction() == "Human Navy" then
8803												if difficulty < 1 then
8804													cp:addToShipLog(string.format("Kraylor ship %s picked up your flag",p:getCallSign()),"Magenta")
8805												else
8806													cp:addToShipLog("The Kraylor picked up your flag","Magenta")
8807												end
8808											elseif p:getFaction() == "Kraylor" then
8809												if difficulty < 1 then
8810													cp:addToShipLog(string.format("%s picked up the Human Navy Flag",p:getCallSign()),"Magenta")
8811												else
8812													cp:addToShipLog("Your team picked up the Human Navy flag","Magenta")
8813												end
8814											end
8815										end
8816									end
8817								end
8818								if difficulty < 1 then
8819									globalMessage(string.format("Kraylor ship %s obtained Human Navy flag",p:getCallSign()))
8820								else
8821									globalMessage("Kraylor obtained Human Navy flag")
8822								end
8823							else
8824								if hard_flag_reveal then
8825									globalMessage("Flag obtained")
8826								end
8827							end
8828						end
8829					end
8830					if px < 0 then				--Kraylor in Human area
8831						for cpidx=1,32 do
8832							cp = getPlayerShip(cpidx)
8833							if cp ~= nil and cp:isValid() and cp:getFaction() == "Human Navy" then
8834								if distance(p,cp) < tag_distance then	--tagged
8835									p:setPosition(player_tag_relocate_x[pidx],player_tag_relocate_y[pidx])
8836									p.tagged_count = p.tagged_count + 1
8837									curWarpDmg = p:getSystemHealth("warp")
8838									if curWarpDmg > (-1 + tagDamage) then
8839										p:setSystemHealth("warp", curWarpDmg - tagDamage)
8840									end
8841									curJumpDmg = p:getSystemHealth("jumpdrive")
8842									if curJumpDmg > (-1 + tagDamage) then
8843										p:setSystemHealth("jumpdrive", curJumpDmg - tagDamage)
8844									end
8845									if p:getSystemHealth("impulse") < 0 then
8846										p:setSystemHealth("impulse", .5)
8847									end
8848									if p.flag then				--carrying flag
8849										p.flag = false			--drop flag
8850										p.drop_count = p.drop_count + 1
8851										if p.flag_badge ~= nil then
8852											p:removeCustom("Helms",p.flag_badge)
8853											p.flag_badge = nil
8854										end
8855										if p.flag_badge_tac ~= nil then
8856											p:removeCustom("Tactical",p.flag_badge_tac)
8857											p.flag_badge_tac = nil
8858										end
8859										p1Flag = Artifact():setPosition(px,py):setModel("artifact5"):allowPickup(false)
8860										table.insert(human_flags,p1Flag)
8861										p1Flag:setDescriptions("Flag","Human Navy Flag"):setRadarSignatureInfo(15,10,5):setScanningParameters(flagScanComplexity,flagScanDepth)
8862										if difficulty < 2 then
8863											p1Flag:setScannedByFaction("Kraylor",true)
8864											for cpidx=1,32 do
8865												local cp = getPlayerShip(cpidx)
8866												if cp ~= nil and cp:isValid() then
8867													if cp ~= p then
8868														if p:getFaction() == "Human Navy" then
8869															if difficulty < 1 then
8870																cp:addToShipLog(string.format("Kraylor ship %s dropped your flag",p:getCallSign()),"Magenta")
8871															else
8872																cp:addToShipLog("The Kraylor dropped your flag","Magenta")
8873															end
8874														elseif p:getFaction() == "Kraylor" then
8875															if difficulty < 1 then
8876																cp:addToShipLog(string.format("%s dropped the Human Navy Flag",p:getCallSign()),"Magenta")
8877															else
8878																cp:addToShipLog("Your team dropped the Human Navy flag","Magenta")
8879															end
8880														end
8881													end
8882												end
8883											end
8884											if difficulty < 1 then
8885												globalMessage(string.format("Kraylor ship %s dropped Human Navy flag",p:getCallSign()))
8886											else
8887												globalMessage("Human Navy flag dropped")
8888											end
8889										else
8890											if hard_flag_reveal then
8891												globalMessage("Flag dropped")
8892											end
8893										end
8894									end
8895								end
8896							end
8897						end
8898					end
8899				elseif p:getFaction() == "Human Navy" then	-- process Human player ship
8900					humanShipsRemaining = humanShipsRemaining + 1
8901					if p.flag and px < 0 then
8902						timeDivision = "victory-human"
8903						victory("Human Navy")
8904					end
8905					if p2Flag:isValid() then
8906						if distance(p,p2Flag) < 500 and p2Flag:isScannedByFaction("Human Navy") then
8907							p.flag = true
8908							p.pick_up_count = p.pick_up_count + 1
8909							if p.flag then
8910								if p:hasPlayerAtPosition("Helms") then
8911									p.flag_badge = "flag_badge"
8912									p:addCustomInfo("Helms",p.flag_badge,"Kraylor Flag Aboard")
8913								end
8914								if p:hasPlayerAtPosition("Tactical") then
8915									p.flag_badge_tac = "flag_badge_tac"
8916									p:addCustomInfo("Tactical",p.flag_badge_tac,"Kraylor Flag Aboard")
8917								end
8918							end
8919							p2Flag:destroy()
8920							p:addToShipLog("You picked up the Kraylor flag","Green")
8921							if difficulty < 2 then
8922								for cpidx=1,32 do
8923									cp = getPlayerShip(cpidx)
8924									if cp ~= nil and cp:isValid() then
8925										if cp ~= p then
8926											if p:getFaction() == "Kraylor" then
8927												if difficulty < 1 then
8928													cp:addToShipLog(string.format("Human Navy ship %s picked up your flag",p:getCallSign()),"Magenta")
8929												else
8930													cp:addToShipLog("The Human Navy picked up your flag","Magenta")
8931												end
8932											elseif p:getFaction() == "Human Navy" then
8933												if difficulty < 1 then
8934													cp:addToShipLog(string.format("%s picked up the Kraylor Flag",p:getCallSign()),"Magenta")
8935												else
8936													cp:addToShipLog("Your team picked up the Kraylor flag","Magenta")
8937												end
8938											end
8939										end
8940									end
8941								end
8942								if difficulty < 1 then
8943									globalMessage(string.format("Human Navy ship %s obtained Kraylor flag",p:getCallSign()))
8944								else
8945									globalMessage("Human Navy obtained Kraylor flag")
8946								end
8947							else
8948								if hard_flag_reveal then
8949									globalMessage("Flag obtained")
8950								end
8951							end
8952						end
8953					end
8954					if px > 0 then				--Human in Kraylor area
8955						for cpidx=1,32 do		--loop through Kraylor ships
8956							cp = getPlayerShip(cpidx)
8957							if cp ~= nil and cp:isValid() and cp:getFaction() == "Kraylor" then
8958								if distance(p,cp) < tag_distance then	--tagged
8959									p:setPosition(player_tag_relocate_x[pidx],player_tag_relocate_y[pidx])
8960									p.tagged_count = p.tagged_count + 1
8961									curWarpDmg = p:getSystemHealth("warp")
8962									if curWarpDmg > (-1 + tagDamage) then
8963										p:setSystemHealth("warp", curWarpDmg - tagDamage)
8964									end
8965									curJumpDmg = p:getSystemHealth("jumpdrive")
8966									if curJumpDmg > (-1 + tagDamage) then
8967										p:setSystemHealth("jumpdrive", curJumpDmg - tagDamage)
8968									end
8969									if p:getSystemHealth("impulse") < 0 then
8970										p:setSystemHealth("impulse", .5)
8971									end
8972									if p.flag then				--carrying flag
8973										p.flag = false			--drop flag
8974										p.drop_count = p.drop_count + 1
8975										if p.flag_badge ~= nil then
8976											p:removeCustom("Helms",p.flag_badge)
8977											p.flag_badge = nil
8978										end
8979										if p.flag_badge_tac ~= nil then
8980											p:removeCustom("Tactical",p.flag_badge_tac)
8981											p.flag_badge_tac = nil
8982										end
8983										p2Flag = Artifact():setPosition(px,py):setModel("artifact5"):allowPickup(false)
8984										table.insert(kraylor_flags,p2Flag)
8985										p2Flag:setDescriptions("Flag","Kraylor Flag"):setRadarSignatureInfo(15,10,5):setScanningParameters(flagScanComplexity,flagScanDepth)
8986										if difficulty < 2 then
8987											p2Flag:setScannedByFaction("Human Navy",true)
8988											for cpidx=1,32 do
8989												local cp = getPlayerShip(cpidx)
8990												if cp ~= nil and cp:isValid() then
8991													if cp ~= p then
8992														if p:getFaction() == "Kraylor" then
8993															if difficulty < 1 then
8994																cp:addToShipLog(string.format("Human Navy ship %s dropped your flag",p:getCallSign()),"Magenta")
8995															else
8996																cp:addToShipLog("The Human Navy dropped your flag","Magenta")
8997															end
8998														elseif p:getFaction() == "Human Navy" then
8999															if difficulty < 1 then
9000																cp:addToShipLog(string.format("%s dropped the Kraylor Flag",p:getCallSign()),"Magenta")
9001															else
9002																cp:addToShipLog("Your team dropped the Kraylor flag","Magenta")
9003															end
9004														end
9005													end
9006												end
9007											end
9008											if difficulty < 1 then
9009												globalMessage(string.format("Human Navy %s dropped Kraylor flag",p:getCallSign()))
9010											else
9011												globalMessage("Human Navy flag dropped")
9012											end
9013										else
9014											if hard_flag_reveal then
9015												globalMessage("Flag dropped")
9016											end
9017										end
9018									end
9019								end
9020							end
9021						end
9022					end
9023				end
9024			end
9025		end
9026	end
9027	if kraylorShipsRemaining == 0 then
9028		if side_destroyed_ends_game then
9029			timeDivision = "victory-human"
9030			victory("Human Navy")
9031		else
9032			if game_timer_reset_on_side_destruction == nil then
9033				game_timer_reset_on_side_destruction = true
9034				gameTimeLimit = 60
9035			end
9036		end
9037	end
9038	if humanShipsRemaining == 0 then
9039		if side_destroyed_ends_game then
9040			timeDivision = "victory-kraylor"
9041			victory("Kraylor")
9042		else
9043			if game_timer_reset_on_side_destruction == nil then
9044				game_timer_reset_on_side_destruction = true
9045				gameTimeLimit = 60
9046			end
9047		end
9048	end
9049end
9050function droneDetectFlagCheck(delta)
9051--[[  debug group
9052	print("---------------")
9053	print("droneDetectFlagCheck() parameters:")
9054	print("drone_flag_check_interval:  " .. drone_flag_check_interval)
9055	print("drone_note_message_reset_interval:  " .. drone_note_message_reset_interval)
9056	print("delta: " .. delta)
9057--]]
9058	if drone_flag_check_timer == nil then
9059		drone_flag_check_timer = delta + drone_flag_check_interval
9060	end
9061	drone_flag_check_timer = drone_flag_check_timer - delta
9062--	print("drone_flag_check_timer = drone_flag_check_timer - delta:  " .. drone_flag_check_timer)
9063	if drone_flag_check_timer < 0 then
9064		for hfi=1,#human_flags do
9065			local flag = human_flags[hfi]
9066			if flag ~= nil and flag:isValid() then
9067				for _, obj in ipairs(flag:getObjectsInRange(drone_scan_range_for_flags)) do
9068					if obj.typeName == "CpuShip" then
9069						if obj.drone then
9070							if obj.drone_message == nil then
9071								if difficulty < 1 then	--science officers get messages from all drones
9072									for pidx=1,32 do
9073										p = getPlayerShip(pidx)
9074										if p ~= nil and p:isValid() then
9075											local drone_message_label = string.format("scienceDroneNote%s%s",obj:getCallSign(),p:getCallSign())
9076											if p:hasPlayerAtPosition("Science") then
9077												p:addCustomMessage("Science",drone_message_label,string.format("Drone %s in sector %s reports possible flag in sector %s",obj:getCallSign(),obj:getSectorName(),flag:getSectorName()))
9078											end
9079											if p:hasPlayerAtPosition("Operations") then
9080												drone_message_label = string.format("operationsDroneNote%s%s",obj:getCallSign(),p:getCallSign())
9081												p:addCustomMessage("Operations",drone_message_label,string.format("Drone %s in sector %s reports possible flag in sector %s",obj:getCallSign(),obj:getSectorName(),flag:getSectorName()))
9082											end
9083											obj.drone_message = "sent"
9084											obj.drone_message_stamp = delta
9085										end	--valid player
9086									end	--player loop
9087								elseif difficulty > 1 then	--science officer gets messages from drones launched from their own ship
9088									for pidx=1,32 do
9089										p = getPlayerShip(pidx)
9090										if p ~= nil and p:isValid() then
9091											if obj.deployer ~= nil and obj.deployer == p then
9092												local drone_message_label = string.format("scienceDroneNote%s%s",obj:getCallSign(),p:getCallSign())
9093												if p:hasPlayerAtPosition("Science") then
9094													p:addCustomMessage("Science",drone_message_label,string.format("Drone %s in sector %s reports possible flag in sector %s",obj:getCallSign(),obj:getSectorName(),flag:getSectorName()))
9095												end
9096												if p:hasPlayerAtPosition("Operations") then
9097													drone_message_label = string.format("operationsDroneNote%s%s",obj:getCallSign(),p:getCallSign())
9098													p:addCustomMessage("Operations",drone_message_label,string.format("Drone %s in sector %s reports possible flag in sector %s",obj:getCallSign(),obj:getSectorName(),flag:getSectorName()))
9099												end
9100												obj.drone_message = "sent"
9101												obj.drone_message_stamp = delta
9102											end	--deployer matches player
9103										end	--valid player
9104									end	--player loop
9105								else	--normal difficulty 1: science officers get messages from friendly ships' drones
9106									for pidx=1,32 do
9107										p = getPlayerShip(pidx)
9108										if p ~= nil and p:isValid() then
9109											if p:getFaction() == "Kraylor" and obj:getFaction() == "Kraylor" then
9110												local drone_message_label = string.format("scienceDroneNote%s%s",obj:getCallSign(),p:getCallSign())
9111												if p:hasPlayerAtPosition("Science") then
9112													p:addCustomMessage("Science",drone_message_label,string.format("Drone %s in sector %s reports possible flag in sector %s",obj:getCallSign(),obj:getSectorName(),flag:getSectorName()))
9113												end
9114												if p:hasPlayerAtPosition("Operations") then
9115													drone_message_label = string.format("operationsDroneNote%s%s",obj:getCallSign(),p:getCallSign())
9116													p:addCustomMessage("Operations",drone_message_label,string.format("Drone %s in sector %s reports possible flag in sector %s",obj:getCallSign(),obj:getSectorName(),flag:getSectorName()))
9117												end
9118												obj.drone_message = "sent"
9119												obj.drone_message_stamp = delta
9120											end	--process kraylor player
9121										end	--valid player
9122									end	--player loop
9123								end	--difficulty checks
9124							else	--drone message sent
9125								if obj.drone_message_check_counter == nil then
9126									obj.drone_message_check_counter = 0
9127								else
9128									obj.drone_message_check_counter = obj.drone_message_check_counter + 1
9129									if obj.drone_message_check_counter >= drone_message_reset_count then
9130										obj.drone_message_check_counter = 0
9131										obj.drone_message = nil
9132									end
9133								end
9134							end	--drone message not sent
9135						end	--object is drone
9136					end	--object is cpu ship
9137				end	--objects in range loop
9138			end	--valid flag
9139		end	--human flags loop
9140		for kfi=1,#kraylor_flags do
9141			local flag = kraylor_flags[kfi]
9142			if flag ~= nil and flag:isValid() then
9143				for _, obj in ipairs(flag:getObjectsInRange(5000)) do
9144					if obj.typeName == "CpuShip" then
9145						if obj.drone then
9146							if obj.drone_message == nil then
9147								if difficulty < 1 then
9148									for pidx=1,32 do
9149										p = getPlayerShip(pidx)
9150										if p ~= nil and p:isValid() then
9151											local drone_message_label = string.format("scienceDroneNote%s%s",obj:getCallSign(),p:getCallSign())
9152											if p:hasPlayerAtPosition("Science") then
9153												p:addCustomMessage("Science",drone_message_label,string.format("Drone %s in sector %s reports possible flag in sector %s",obj:getCallSign(),obj:getSectorName(),flag:getSectorName()))
9154											end
9155											if p:hasPlayerAtPosition("Operations") then
9156												drone_message_label = string.format("operationsDroneNote%s%s",obj:getCallSign(),p:getCallSign())
9157												p:addCustomMessage("Operations",drone_message_label,string.format("Drone %s in sector %s reports possible flag in sector %s",obj:getCallSign(),obj:getSectorName(),flag:getSectorName()))
9158											end
9159											obj.drone_message = "sent"
9160											obj.drone_message_stamp = delta
9161										end	--valid player
9162									end	--player loop
9163								elseif difficulty > 1 then
9164									for pidx=1,32 do
9165										p = getPlayerShip(pidx)
9166										if p ~= nil and p:isValid() then
9167											if obj.deployer ~= nil and obj.deployer == p then
9168												local drone_message_label = string.format("scienceDroneNote%s%s",obj:getCallSign(),p:getCallSign())
9169												if p:hasPlayerAtPosition("Science") then
9170													p:addCustomMessage("Science",drone_message_label,string.format("Drone %s in sector %s reports possible flag in sector %s",obj:getCallSign(),obj:getSectorName(),flag:getSectorName()))
9171												end
9172												if p:hasPlayerAtPosition("Operations") then
9173													drone_message_label = string.format("operationsDroneNote%s%s",obj:getCallSign(),p:getCallSign())
9174													p:addCustomMessage("Operations",drone_message_label,string.format("Drone %s in sector %s reports possible flag in sector %s",obj:getCallSign(),obj:getSectorName(),flag:getSectorName()))
9175												end
9176												obj.drone_message = "sent"
9177												obj.drone_message_stamp = delta
9178											end	--deployer matches player
9179										end	--valid player
9180									end	--player loop
9181								else	--normal difficulty 1
9182									for pidx=1,32 do
9183										p = getPlayerShip(pidx)
9184										if p ~= nil and p:isValid() then
9185											if p:getFaction() == "Human Navy" and obj:getFaction() == "Human Navy" then
9186												local drone_message_label = string.format("scienceDroneNote%s%s",obj:getCallSign(),p:getCallSign())
9187												if p:hasPlayerAtPosition("Science") then
9188													p:addCustomMessage("Science",drone_message_label,string.format("Drone %s in sector %s reports possible flag in sector %s",obj:getCallSign(),obj:getSectorName(),flag:getSectorName()))
9189												end
9190												if p:hasPlayerAtPosition("Operations") then
9191													drone_message_label = string.format("operationsDroneNote%s%s",obj:getCallSign(),p:getCallSign())
9192													p:addCustomMessage("Operations",drone_message_label,string.format("Drone %s in sector %s reports possible flag in sector %s",obj:getCallSign(),obj:getSectorName(),flag:getSectorName()))
9193												end
9194												obj.drone_message = "sent"
9195												obj.drone_message_stamp = delta
9196											end	--process human player
9197										end	--valid player
9198									end	--player loop
9199								end	--difficulty checks
9200							else
9201								if obj.drone_message_check_counter == nil then
9202									obj.drone_message_check_counter = 0
9203								else
9204									obj.drone_message_check_counter = obj.drone_message_check_counter + 1
9205									if obj.drone_message_check_counter >= drone_message_reset_count then
9206										obj.drone_message_check_counter = 0
9207										obj.drone_message = nil
9208									end
9209								end
9210							end	--drone message not sent
9211						end	--object is drone
9212					end	--object is cpu ship
9213				end	--objects in range loop
9214			end	--valid flag
9215		end	--human flags loop
9216		drone_flag_check_timer = delta + drone_flag_check_interval
9217	end	--drone flag check timer expiration
9218end
9219function buoyBeams(delta)
9220	buoy_beam_timer = buoy_beam_timer - delta
9221	if buoy_beam_timer < 0 then
9222		for i=1,#boundary_items - 2 do
9223			if i % 4 == buoy_beam_count % 4 then
9224				BeamEffect():setSource(boundary_items[i],0,0,0):setTarget(boundary_items[i+2],0,0):setDuration(buoy_beam_interval):setRing(false):setTexture(boundary_beam_string[math.random(1,#boundary_beam_string)])
9225				if i < 3 then
9226					if stationZebra ~= nil and stationZebra:isValid() then
9227						BeamEffect():setSource(boundary_items[i],0,0,0):setTarget(stationZebra,0,0):setDuration(buoy_beam_interval):setRing(false):setTexture(boundary_beam_string[math.random(1,#boundary_beam_string)])
9228					end
9229				end
9230			end
9231		end
9232		buoy_beam_timer = buoy_beam_interval
9233		buoy_beam_count = buoy_beam_count + 1
9234	end
9235end
9236
9237 -- ***********************************************************************************
9238function update(delta)
9239	if boundary_marker == "buoys" then
9240		buoyBeams(delta)
9241	end
9242	if delta == 0 then
9243		manageAddingNewPlayerShips()
9244		return
9245	end
9246	if mainGMButtons == mainGMButtonsDuringPause then
9247		mainGMButtons = mainGMButtonsAfterPause
9248		mainGMButtons()
9249	end
9250	gameTimeLimit = gameTimeLimit - delta
9251	if gameTimeLimit < 0 then
9252		timeDivision = "victory-exuari"
9253		victory("Exuari")
9254	end
9255--	print(string.format("Max game time: %i, Hide flag time: %i, Game time limit: %.1f",maxGameTime,hideFlagTime,gameTimeLimit))
9256	if gameTimeLimit < (maxGameTime - hideFlagTime - 1) then	--1499
9257		--hunt begins
9258		manageHuntPhaseMechanics()
9259		if dronesAreAllowed then
9260			droneDetectFlagCheck(delta)
9261		end
9262	elseif gameTimeLimit < (maxGameTime - hideFlagTime) then		--1500
9263		--transition from preparation/hiding flags phase to hunt phase
9264		transitionFromPreparationToHunt()
9265	else
9266		--prepare (place flags)
9267		placeFlagsPhase()
9268	end
9269	if dynamicTerrain ~= nil then
9270		dynamicTerrain(delta)
9271	end
9272	if plotH ~= nil then	--health
9273		plotH(delta)
9274	end
9275	for pidx=1,32 do
9276		local p5 = getPlayerShip(pidx)
9277		if p5 ~= nil and p5:isValid() then
9278			local name_tag_text = string.format("%s in %s",p5:getCallSign(),p5:getSectorName())
9279			if p5:hasPlayerAtPosition("Helms") then
9280				p5.name_tag_helm = "name_tag_helm"
9281				p5:addCustomInfo("Helms",p5.name_tag_helm,name_tag_text)
9282			end
9283			if p5:hasPlayerAtPosition("Tactical") then
9284				p5.name_tag_helm_tac = "name_tag_helm_tac"
9285				p5:addCustomInfo("Tactical",p5.name_tag_helm_tac,name_tag_text)
9286			end
9287			if p5:hasPlayerAtPosition("SinglePilot") then
9288				p5.name_tag_helm_single = "name_tag_helm_single"
9289				p5:addCustomInfo("SinglePilot",p5.name_tag_helm_single,name_tag_text)
9290			end
9291		end
9292	end
9293	if plotW ~= nil then	--waves of marauders
9294		plotW(delta)
9295	end
9296	-- print("delta: " .. delta)
9297end