diff --git a/CHANGELOG.md b/CHANGELOG.md index e1fe4793a6..bd02886610 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,55 @@ # Change Log +## [2020-04-09] + +### Added + +- Options menu settings to allow radar views on Helms, Weapons, and Science stations (and their derivative crew 3/4 stations) to rotate around the player ship, instead of the ship rotating within the radar view. +- Adjustable and customizable impulse engine sounds. + - Options menu settings for enabling impulse engine sounds across all stations, main screen only, or disabled, as well as setting its volume separate from master sound and music. + - `setImpulseSoundFile()` ship template function to set a custom engine sound. + - Default impulse sound moved from `resources/engine.wav` to `resources/sfx/engine.wav`. + - New engine sound for the MP52 Hornet. +- Power Management station keybindings, sharing Engineering's. +- `SpaceShip::setWarpSpeed()` scripting function to set a ship's speed per warp level. +- Optional control code for the Spectate station. +- Translation markers added to many more game features, including player stations and weapon names. +- Custom functions added to Ship Log screen. +- `autoconnect_address` option to specify a server to autoconnect to, instead of relying on server autodiscovery. +- Toggleable player ship capabilities in ship templates, scripting, and the GM tweak menu: scanning (`canScan()`), hacking (`canHack()`), docking (`canDock()`), combat maneuvering (`canCombatManeuver()`), self destruction (`canSelfDestruct()`), and probe launching (`canLaunchProbe()`) +- `set` and `getSelfDestructDamage` and `SelfDestructSize` scripting functions to modify player ship self-destruction explosion size and damage. +- Probe radar radius is now visible on the GM screen. +- Mission clock on Relay and GM screens counts up from 0 seconds at the start of each scenario. Ship's Log UI is now also synchronized to this clock for consistency. +- `SpaceObject::onDestroyed()` callback when an object is destroyed, even if not by damage. + +### Changed + +- Reducing coolant in a system distributes it automatically to other systems, even if they are all empty. +- Warp drive energy usage scales to system damage and power level. +- Options menu is paginated to accommodate additional options. +- Black holes do even more damage closer to their center; more objects sucked into a black hole should be destroyed by damage and trigger the appropriate callback. +- Borderline Fever scenario refactoring + - Added expedite dock function to Relay, added show player ship details on player console, added enemy behavior change option, reorganized GM buttons, GM buttons to display player ship details, take advantage of resizable asteroids by randomly resizing them, Added cartography office to relay for stations when docked, added possibility to revive repair crew, added possibility to recover lost coolant, handle rare nil case for angle of attack, reduce average size of warp jammer range +- Delta Quadrant Patrol Duty scenario refactoring + - Add status summary to relay screen, Localize variables, Take advantage of resizable asteroids through randomization, fix beam presence recognition code, Add goods randomization arrays, Add list of player ship names for Crucible and Maverick as well as set up code, fix check for warp drive presence on player ship, fix placement of station Research-19, Change station Maverick to Malthus, Switch to placing station data in comms_data structure, fix transport handling, Add cartography office, fix Kojak mission, remove old diagnostic code, simplify freighter cargo interaction, fix reference to global getLongRangeRadarRange (deprecated), add chance for repair crew to be revived +- Defender Hunter scenario refactoring + - Move constant definitions to their own function, Fix player ship beam determination code, Add goods randomization tables, move station placement function list creation to its own function, localize variables, move station data to comms_data structure, take advantage of resizable asteroids through randomization, add possibility of repair crew revival, add possibility of coolant recovery +- Escape scenario refactoring + - Update goods handling, switch to putting more data in comms_data structure for stations, add use case for another set of debris, make asteroids vary in size at random, add freighter communication options, add more junk yard dogs, add more harassing Exuari during repair journey, add Engineering messages when max repairable health reached + +### Fixed + +- Tutorial no longer crashes when started. +- Missile tube sizes and HVLI projectiles are properly replicated to clients. +- Warp/glitch shaders no longer affect paused games. +- Persistent scripting storage (ie. `ScriptStorage.get()`) is no longer wiped upon load in a new EE instance. +- Engineering station no longer sometimes crashes while loading. +- Fixed some situations that could cause crew screens to crash when selecting Main Screen controls on Linux builds. +- Ship's Log screen no longer overlaps some station selection controls. +- Destroyed player ships no longer persist and appear multiple times in the ship selection screen. +- Joystick event handling no longer results in crew stations persisting after a player exits them. +- When the window is resized, the rendered area no longer shifts out of the window's bounds when warp/jump/glitch effects occur. + ## [2020-03-22] ### Added diff --git a/CMakeLists.txt b/CMakeLists.txt index 4b7305703a..b4716ee0f3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -137,6 +137,7 @@ set(SOURCES src/screenComponents/missileTubeControls.cpp src/screenComponents/selfDestructIndicator.cpp src/screenComponents/viewport3d.cpp + src/screenComponents/viewportMainScreen.cpp src/screenComponents/selfDestructEntry.cpp src/screenComponents/dockingButton.cpp src/screenComponents/shieldsEnableButton.cpp @@ -176,6 +177,7 @@ set(SOURCES src/screenComponents/lightsOut.cpp src/screenComponents/miniGame.cpp src/screenComponents/mineSweeper.cpp + src/screenComponents/impulseSound.cpp src/gui/colorConfig.cpp src/gui/hotkeyConfig.cpp src/gui/joystickConfig.cpp @@ -250,7 +252,7 @@ set(SOURCES src/hardware/devices/philipsHueDevice.cpp ) if(WIN32) - list(APPEND SOURCES EmptyEpsilon.rc) + list(APPEND SOURCES EmptyEpsilon.rc src/discord.cpp) endif() foreach(SP_SOURCE @@ -419,6 +421,12 @@ if(WIN32) include_directories(${DRMINGW_ROOT}/include/) target_link_libraries(${EXECUTABLE_NAME} exchndl) endif() + if(NOT EXISTS "${CMAKE_CURRENT_BINARY_DIR}/discord/lib/x86/discord_game_sdk.dll.lib") + file(DOWNLOAD "https://dl-game-sdk.discordapp.net/latest/discord_game_sdk.zip" "${CMAKE_CURRENT_BINARY_DIR}/discord/game_sdk.zip" TIMEOUT 60 TLS_VERIFY ON) + execute_process(COMMAND ${CMAKE_COMMAND} -E tar -xf "${CMAKE_CURRENT_BINARY_DIR}/discord/game_sdk.zip" WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/discord") + endif() + target_link_libraries(${EXECUTABLE_NAME} "${CMAKE_CURRENT_BINARY_DIR}/discord/lib/x86/discord_game_sdk.dll.lib") + target_include_directories(${EXECUTABLE_NAME} PUBLIC "${CMAKE_CURRENT_BINARY_DIR}/discord/c/") elseif(ANDROID) set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--whole-archive ${SFML_INSTALL_PATH}/lib/${ANDROID_ABI}/libsfml-main.a -Wl,--no-whole-archive") target_link_libraries(${EXECUTABLE_NAME} log android EGL) @@ -455,6 +463,7 @@ if(WIN32) install(FILES ${DRMINGW_ROOT}/bin/symsrv.dll DESTINATION .) install(FILES ${DRMINGW_ROOT}/bin/symsrv.yes DESTINATION .) endif() + install(FILES "${CMAKE_CURRENT_BINARY_DIR}/discord/lib/x86/discord_game_sdk.dll" DESTINATION .) install(DIRECTORY resources DESTINATION .) install(DIRECTORY scripts DESTINATION .) diff --git a/icon-captain.svg b/icon-captain.svg new file mode 100755 index 0000000000..a158bddb6a --- /dev/null +++ b/icon-captain.svg @@ -0,0 +1,75 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + diff --git a/icons-font.md b/icons-font.md new file mode 100644 index 0000000000..5f3e488fcd --- /dev/null +++ b/icons-font.md @@ -0,0 +1,25 @@ +The icons-font contains some of the ingame icons in a font format. This gives a nice vector rendering, allowing to render at any scale. + +Characters are: +* a: Dock +* b: Energy +* c: Heading +* d: Target lock +* e: Overheating +* f: Armor (unused) +* g: Speed +* h: Engineering (alternative, not used) +* i: Helms (alternative, not used) +* j: Relay +* k: Science +* l: Weapons +* m: EMP +* n: Homing missile +* o: Mine +* p: Nuke +* q: Engineering +* r: Helms +* s: (unused) +* t: Engineering+ (unused) +* u: Tactical (unused) +* v: Operations (unused) diff --git a/icons-font.ttf b/icons-font.ttf new file mode 100755 index 0000000000..255a423aa4 Binary files /dev/null and b/icons-font.ttf differ diff --git a/resources/engine.wav b/resources/sfx/engine.wav similarity index 100% rename from resources/engine.wav rename to resources/sfx/engine.wav diff --git a/resources/sfx/engine_fighter.wav b/resources/sfx/engine_fighter.wav new file mode 100644 index 0000000000..4010401ab7 Binary files /dev/null and b/resources/sfx/engine_fighter.wav differ diff --git a/resources/sfx/source.txt b/resources/sfx/source.txt index b216854de0..c0fd778d78 100644 --- a/resources/sfx/source.txt +++ b/resources/sfx/source.txt @@ -22,3 +22,14 @@ explosion from UFO: Alien Invason Sounds (c) by Michel Baradari apollo-music.de Licensed under CC BY 3.0 http://creativecommons.org/licenses/by/3.0/ Hosted on opengameart.org + +===engine.wav=== +Sound (c) Garrett "Oznogon" Guillotte +Released into the Public Domain + +===engine_fighter.wav=== +F-15 Avionics Sound Cockpit View +F-15 Eagle SFX sound library +Sound (c) SoundFX.studio +Licensed under CC BY-NC 3.0 https://creativecommons.org/licenses/by-nc/3.0/ +Retrieved from https://freesound.org/s/456269/ diff --git a/scripts/scenario_53_escape.lua b/scripts/scenario_53_escape.lua index c4b2de1254..41f6a0a40a 100755 --- a/scripts/scenario_53_escape.lua +++ b/scripts/scenario_53_escape.lua @@ -1,18 +1,18 @@ -- Name: Escape -- Description: Escape imprisonment and return home. --- ---- Mission consists of one ship with a full crew. Engineer, Relay and Science will be busy; Weapons less busy. +--- Mission consists of one ship with a full crew. Engineer and Science will be busy --- ---- Version 2 Added more opportunities to use cargo to accomplish goals, increased variation based on difficulty setting +--- Version 4 Adds more activity for the weapons officer (6Apr2020) -- Type: Mission, somewhat replayable -- Variation[Easy]: Easy goals and/or enemies -- Variation[Hard]: Hard goals and/or enemies require("utils.lua") ---[[------------------------------------------------------------------- - Initialization routines ---]]------------------------------------------------------------------- +------------------------------- +-- Initialization routines -- +------------------------------- function init() wfv = "nowhere" --wolf fence value - used for debugging setVariations() @@ -27,35 +27,9 @@ function init() -- rough hexagonal deployment 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} 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} - --list of goods available to buy, sell or trade (sell still under development) - goodsList = { {"food",0}, - {"medicine",0}, - {"nickel",0}, - {"platinum",0}, - {"gold",0}, - {"dilithium",0}, - {"tritanium",0}, - {"luxury",0}, - {"cobalt",0}, - {"impulse",0}, - {"warp",0}, - {"shield",0}, - {"tractor",0}, - {"repulsor",0}, - {"beam",0}, - {"optic",0}, - {"robotic",0}, - {"filament",0}, - {"transporter",0}, - {"sensor",0}, - {"communication",0}, - {"autodoc",0}, - {"lifter",0}, - {"android",0}, - {"nanites",0}, - {"software",0}, - {"circuit",0}, - {"battery",0} } + commonGoods = {"food","medicine","nickel","platinum","gold","dilithium","tritanium","luxury","cobalt","impulse","warp","shield","tractor","repulsor","beam","optic","robotic","filament","transporter","sensor","communication","autodoc","lifter","android","nanites","software","circuit","battery"} + componentGoods = {"impulse","warp","shield","tractor","repulsor","beam","optic","robotic","filament","transporter","sensor","communication","autodoc","lifter","android","nanites","software","circuit","battery"} + mineralGoods = {"nickel","platinum","gold","dilithium","tritanium","cobalt"} diagnostic = false GMDiagnosticOn = "Turn On Diagnostic" addGMFunction(GMDiagnosticOn,turnOnDiagnostic) @@ -79,98 +53,7 @@ function init() totalStations = 0 friendlyStations = 0 neutralStations = 0 - --array of functions to facilitate randomized station placement (friendly and neutral) - placeStation = {placeAlcaleica, -- 1 - placeAnderson, -- 2 - placeArcher, -- 3 - placeArchimedes, -- 4 - placeArmstrong, -- 5 - placeAsimov, -- 6 - placeBarclay, -- 7 - placeBethesda, -- 8 - placeBroeck, -- 9 - placeCalifornia, --10 - placeCalvin, --11 - placeCavor, --12 - placeChatuchak, --13 - placeCoulomb, --14 - placeCyrus, --15 - placeDeckard, --16 - placeDeer, --17 - placeErickson, --18 - placeEvondos, --19 - placeFeynman, --20 - placeGrasberg, --21 - placeHayden, --22 - placeHeyes, --23 - placeHossam, --24 - placeImpala, --25 - placeKomov, --26 - placeKrak, --27 - placeKruk, --28 - placeLipkin, --29 - placeMadison, --30 - placeMaiman, --31 - placeMarconi, --32 - placeMayo, --33 - placeMiller, --34 - placeMuddville, --35 - placeNexus6, --36 - placeOBrien, --37 - placeOlympus, --38 - placeOrgana, --39 - placeOutpost15, --40 - placeOutpost21, --41 - placeOwen, --42 - placePanduit, --43 - placeRipley, --44 - placeRutherford, --45 - placeScience7, --46 - placeShawyer, --47 - placeShree, --48 - placeSoong, --49 - placeTiberius, --50 - placeTokra, --51 - placeToohie, --52 - placeUtopiaPlanitia, --53 - placeVactel, --54 - placeVeloquan, --55 - placeZefram} --56 - --array of functions to facilitate randomized station placement (friendly, neutral or enemy) - placeGenericStation = {placeJabba, -- 1 - placeKrik, -- 2 - placeLando, -- 3 - placeMaverick, -- 4 - placeNefatha, -- 5 - placeOkun, -- 6 - placeOutpost7, -- 7 - placeOutpost8, -- 8 - placeOutpost33, -- 9 - placePrada, --10 - placeResearch11, --11 - placeResearch19, --12 - placeRubis, --13 - placeScience2, --14 - placeScience4, --15 - placeSkandar, --16 - placeSpot, --17 - placeStarnet, --18 - placeTandon, --19 - placeVaiken, --20 - placeValero} --21 - --array of functions to facilitate randomized station placement (enemy) - placeEnemyStation = {placeAramanth, -- 1 - placeEmpok, -- 2 - placeGandala, -- 3 - placeHassenstadt, -- 4 - placeKaldor, -- 5 - placeMagMesra, -- 6 - placeMosEisley, -- 7 - placeQuestaVerde, -- 8 - placeRlyeh, -- 9 - placeScarletCit, --10 - placeStahlstadt, --11 - placeTic} --12 + setListOfStations() brigStation = SpaceStation():setTemplate("Small Station"):setFaction("Kraylor"):setCallSign("DS23"):setPosition(912787, 148301) table.insert(enemyStationList,brigStation) buildNearbyStations() @@ -223,7 +106,7 @@ function init() debris2:setDescriptions("Debris","Debris: Various broken ship components. Possibly useful for shield or beam systems repair") debrisx, debrisy = pickCoordinate(junkYardDebrisX,junkYardDebrisY) debris3 = Artifact():setPosition(debrisx, debrisy):setModel("ammo_box"):allowPickup(true):setScanningParameters(2,1):onPickUp(function(debris, pGrab) string.format("");pGrab.debris3 = true end) - debris3:setDescriptions("Debris","Debris: Various broken ship components. Possibly useful for reactor or shield systems repair") + debris3:setDescriptions("Debris","Debris: Various broken ship components. Possibly useful for hull or reactor systems repair") --Signs junkYardSignX = {914126, 905479, 910303} junkYardSignY = {151100, 148728, 147102} @@ -251,7 +134,6 @@ function init() playerFighter.maxImpulse = .2 playerFighter.maxFrontShield = .25 player = playerFighter - goods[player] = goodsList junkShips = {} --junkyard ship index 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 junkYardShipX = {909594, 910129, 909490, 910461, 910716, 911023, 913356, 906866, 911356, 910998, 907356, 913243, 908569, 912413, 907149} @@ -322,9 +204,9 @@ function init() plot1 = scanRepulse --enable first plot mission goal --print("end of init") end +function pickCoordinate(coordinateArrayX,coordinateArrayY) --pick a coordinate at random from the passed table --remove selected coordinates and return selected coordinates -function pickCoordinate(coordinateArrayX,coordinateArrayY) if #coordinateArrayX > 1 then choice = math.random(1,#coordinateArrayX) rx = coordinateArrayX[choice] @@ -339,8 +221,8 @@ function pickCoordinate(coordinateArrayX,coordinateArrayY) end return rx, ry end ---translate variations into a numeric difficulty value function setVariations() +--translate variations into a numeric difficulty value if string.find(getScenarioVariation(),"Easy") then difficulty = .5 elseif string.find(getScenarioVariation(),"Hard") then @@ -349,6 +231,7 @@ function setVariations() difficulty = 1 --default (normal) end end +function createRandomAlongArc(object_type, amount, x, y, distance, startArc, endArcClockwise, randomize) -- Create amount of objects of type object_type along arc -- Center defined by x and y -- Radius defined by distance @@ -356,7 +239,6 @@ end -- Use randomize to vary the distance from the center point. Omit to keep distance constant -- Example: -- createRandomAlongArc(Asteroid, 100, 500, 3000, 65, 120, 450) -function createRandomAlongArc(object_type, amount, x, y, distance, startArc, endArcClockwise, randomize) if randomize == nil then randomize = 0 end if amount == nil then amount = 1 end arcLen = endArcClockwise - startArc @@ -383,11 +265,60 @@ function createRandomAlongArc(object_type, amount, x, y, distance, startArc, end end end end +function placeRandomAsteroidsAroundPoint(amount, dist_min, dist_max, x0, y0) +-- create amount of asteroid, at a distance between dist_min and dist_max around the point (x0, y0) + for n=1,amount do + local r = random(0, 360) + local distance = random(dist_min, dist_max) + x = x0 + math.cos(r / 180 * math.pi) * distance + y = y0 + math.sin(r / 180 * math.pi) * distance + local asteroid_size = random(1,100) + random(1,75) + random(1,75) + random(1,20) + random(1,20) + random(1,20) + random(1,20) + random(1,20) + random(1,20) + random(1,20) + Asteroid():setPosition(x, y):setSize(asteroid_size) + end +end +function createRandomAsteroidAlongArc(amount, x, y, distance, startArc, endArcClockwise, randomize) +-- Create amount of asteroids along arc +-- Center defined by x and y +-- Radius defined by distance +-- Start of arc between 0 and 360 (startArc), end arc: endArcClockwise +-- Use randomize to vary the distance from the center point. Omit to keep distance constant +-- Example: +-- createRandomAsteroidAlongArc(100, 500, 3000, 65, 120, 450) + if randomize == nil then randomize = 0 end + if amount == nil then amount = 1 end + local arcLen = endArcClockwise - startArc + if startArc > endArcClockwise then + endArcClockwise = endArcClockwise + 360 + arcLen = arcLen + 360 + end + local asteroid_size = random(1,100) + random(1,75) + random(1,75) + random(1,20) + random(1,20) + random(1,20) + random(1,20) + random(1,20) + random(1,20) + random(1,20) + if amount > arcLen then + for ndex=1,arcLen do + local radialPoint = startArc+ndex + local pointDist = distance + random(-randomize,randomize) + asteroid_size = random(1,100) + random(1,75) + random(1,75) + random(1,20) + random(1,20) + random(1,20) + random(1,20) + random(1,20) + random(1,20) + random(1,20) + Asteroid():setPosition(x + math.cos(radialPoint / 180 * math.pi) * pointDist, y + math.sin(radialPoint / 180 * math.pi) * pointDist):setSize(asteroid_size) + end + for ndex=1,amount-arcLen do + radialPoint = random(startArc,endArcClockwise) + pointDist = distance + random(-randomize,randomize) + asteroid_size = random(1,100) + random(1,75) + random(1,75) + random(1,20) + random(1,20) + random(1,20) + random(1,20) + random(1,20) + random(1,20) + random(1,20) + Asteroid():setPosition(x + math.cos(radialPoint / 180 * math.pi) * pointDist, y + math.sin(radialPoint / 180 * math.pi) * pointDist):setSize(asteroid_size) + end + else + for ndex=1,amount do + radialPoint = random(startArc,endArcClockwise) + pointDist = distance + random(-randomize,randomize) + asteroid_size = random(1,100) + random(1,75) + random(1,75) + random(1,20) + random(1,20) + random(1,20) + random(1,20) + random(1,20) + random(1,20) + random(1,20) + Asteroid():setPosition(x + math.cos(radialPoint / 180 * math.pi) * pointDist, y + math.sin(radialPoint / 180 * math.pi) * pointDist):setSize(asteroid_size) + end + end +end +function buildNearbyStations() -- Organically (simulated asymetrically) grow stations from a central grid location -- Order of creation: enemy stations, planet, enemy stations, planet, -- independent stations, black hole, independent stations, black hole -- Human Navy stations (friendly stations) come later in the game after the communications get repaired. -function buildNearbyStations() brigx, brigy = brigStation:getPosition() gbLow = 1 --grid boundary low gbHigh = 500 --grid boundary high @@ -609,8 +540,8 @@ function addBlackHole() gx = adjList[rn][1] gy = adjList[rn][2] end ---adjacent empty grid locations around the most recently placed item function getAdjacentGridLocations(lx,ly) +--adjacent empty grid locations around the most recently placed item tempGrid = {} for i=gbLow,gbHigh do tempGrid[i] = {} @@ -667,8 +598,8 @@ function getAdjacentGridLocations(lx,ly) end return ol end ---adjacent empty grid locations around the most recently placed item, skip as requested function getAdjacentGridLocationsSkip(dSkip,lx,ly) +--adjacent empty grid locations around the most recently placed item, skip as requested tempGrid[lx][ly] = 1 if dSkip ~= 3 then --check left @@ -727,8 +658,8 @@ function getAdjacentGridLocationsSkip(dSkip,lx,ly) end end end ---adjacent empty grid locations around all occupied locations function getAllAdjacentGridLocations(lx,ly) +--adjacent empty grid locations around all occupied locations tempGrid = {} for i=gbLow,gbHigh do tempGrid[i] = {} @@ -785,8 +716,8 @@ function getAllAdjacentGridLocations(lx,ly) end return ol end ---adjacent empty grid locations around all occupied locations, skip as requested function getAllAdjacentGridLocationsSkip(dSkip,lx,ly) +--adjacent empty grid locations around all occupied locations, skip as requested tempGrid[lx][ly] = 1 if dSkip ~= 3 then --check left @@ -845,8 +776,8 @@ function getAllAdjacentGridLocationsSkip(dSkip,lx,ly) end end end ---adjacent empty grid locations around the grid locations of the currently building faction function getFactionAdjacentGridLocations(lx,ly) +--adjacent empty grid locations around the grid locations of the currently building faction tempGrid = {} for i=gbLow,gbHigh do tempGrid[i] = {} @@ -903,8 +834,8 @@ function getFactionAdjacentGridLocations(lx,ly) end return ol end ---adjacent empty grid locations around the grid locations of the currently building faction, skip check as requested function getFactionAdjacentGridLocationsSkip(dSkip,lx,ly) +--adjacent empty grid locations around the grid locations of the currently building faction, skip check as requested tempGrid[lx][ly] = 1 if dSkip ~= 3 then --check left @@ -963,8 +894,105 @@ function getFactionAdjacentGridLocationsSkip(dSkip,lx,ly) end end end ---Randomly choose station size template +-------------------------------- +-- Station creation functions -- +-------------------------------- +function setListOfStations() + --array of functions to facilitate randomized station placement (friendly and neutral) + placeStation = {placeAlcaleica, -- 1 + placeAnderson, -- 2 + placeArcher, -- 3 + placeArchimedes, -- 4 + placeArmstrong, -- 5 + placeAsimov, -- 6 + placeBarclay, -- 7 + placeBethesda, -- 8 + placeBroeck, -- 9 + placeCalifornia, --10 + placeCalvin, --11 + placeCavor, --12 + placeChatuchak, --13 + placeCoulomb, --14 + placeCyrus, --15 + placeDeckard, --16 + placeDeer, --17 + placeErickson, --18 + placeEvondos, --19 + placeFeynman, --20 + placeGrasberg, --21 + placeHayden, --22 + placeHeyes, --23 + placeHossam, --24 + placeImpala, --25 + placeKomov, --26 + placeKrak, --27 + placeKruk, --28 + placeLipkin, --29 + placeMadison, --30 + placeMaiman, --31 + placeMarconi, --32 + placeMayo, --33 + placeMiller, --34 + placeMuddville, --35 + placeNexus6, --36 + placeOBrien, --37 + placeOlympus, --38 + placeOrgana, --39 + placeOutpost15, --40 + placeOutpost21, --41 + placeOwen, --42 + placePanduit, --43 + placeRipley, --44 + placeRutherford, --45 + placeScience7, --46 + placeShawyer, --47 + placeShree, --48 + placeSoong, --49 + placeTiberius, --50 + placeTokra, --51 + placeToohie, --52 + placeUtopiaPlanitia, --53 + placeVactel, --54 + placeVeloquan, --55 + placeZefram} --56 + --array of functions to facilitate randomized station placement (friendly, neutral or enemy) + placeGenericStation = {placeJabba, -- 1 + placeKrik, -- 2 + placeLando, -- 3 + placeMaverick, -- 4 + placeNefatha, -- 5 + placeOkun, -- 6 + placeOutpost7, -- 7 + placeOutpost8, -- 8 + placeOutpost33, -- 9 + placePrada, --10 + placeResearch11, --11 + placeResearch19, --12 + placeRubis, --13 + placeScience2, --14 + placeScience4, --15 + placeSkandar, --16 + placeSpot, --17 + placeStarnet, --18 + placeTandon, --19 + placeVaiken, --20 + placeValero} --21 + --array of functions to facilitate randomized station placement (enemy) + placeEnemyStation = {placeAramanth, -- 1 + placeEmpok, -- 2 + placeGandala, -- 3 + placeHassenstadt, -- 4 + placeKaldor, -- 5 + placeMagMesra, -- 6 + placeMosEisley, -- 7 + placeQuestaVerde, -- 8 + placeRlyeh, -- 9 + placeScarletCit, --10 + placeStahlstadt, --11 + placeTic} --12 +end function szt() +--Randomly choose station size template stationSizeRandom = random(1,100) if stationSizeRandom <= 8 then sizeTemplate = "Huge Station" -- 8 percent huge @@ -977,194 +1005,300 @@ function szt() end return sizeTemplate end ---[[------------------------------------------------------------------- - Human and neutral stations to be placed (all need some kind of goods) ---]]------------------------------------------------------------------- +function randomMineral(exclude) + local good = mineralGoods[math.random(1,#mineralGoods)] + if exclude == nil then + return good + else + repeat + good = mineralGoods[math.random(1,#mineralGoods)] + until(good ~= exclude) + return good + end +end +function randomComponent(exclude) + local good = componentGoods[math.random(1,#componentGoods)] + if exclude == nil then + return good + else + repeat + good = componentGoods[math.random(1,#componentGoods)] + until(good ~= exclude) + return good + end +end +-- Human and neutral stations to be placed (all need some kind of goods) function placeAlcaleica() --Alcaleica stationAlcaleica = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation) stationAlcaleica:setPosition(psx,psy):setCallSign("Alcaleica"):setDescription("Optical Components") + stationAlcaleica.comms_data = { + friendlyness = random(0,100), + weapons = {Homing = "neutral", HVLI = "neutral", Mine = "neutral", Nuke = "friend", EMP = "friend"}, + weapon_available = {Homing = random(1,10)<=(8-difficulty), HVLI = random(1,10)<=(9-difficulty), Mine = random(1,10)<=(7-difficulty), Nuke = random(1,10)<=(5-difficulty), EMP = random(1,10)<=(6-difficulty)}, + service_cost = {supplydrop = math.random(80,120), reinforcements = math.random(125,175)}, + reputation_cost_multipliers = {friend = 1.0, neutral = 3.0}, + max_weapon_refill_amount = {friend = 1.0, neutral = 0.5 }, + goods = { optic = {quantity = 5, cost = 66} }, + trade = { food = false, medicine = false, luxury = false }, + buy = { [randomMineral()] = math.random(40,200) }, + public_relations = true, + general_information = "We make and supply optic components for various station and ship systems", + history = "This station continues the businesses from Earth based on the merging of several companies including Leica from Switzerland, the lens manufacturer and the Japanese advanced low carbon (ALCA) electronic and optic research and development company" + } if stationFaction == "Human Navy" then + stationAlcaleica.comms_data.goods.food = {quantity = math.random(5,10), cost = 1} if random(1,5) <= 1 then - goods[stationAlcaleica] = {{"food",math.random(5,10),1},{"medicine",5,5},{"optic",5,66}} + stationAlcaleica.comms_data.goods.medicine = {quantity = 5, cost = 5} else - goods[stationAlcaleica] = {{"food",math.random(5,10),1},{"optic",5,66}} - tradeMedicine[stationAlcaleica] = true + stationAlcaleica.comms_data.trade.medicine = true end else - goods[stationAlcaleica] = {{"optic",5,66}} - tradeFood[stationAlcaleica] = true - tradeMedicine[stationAlcaleica] = true + stationAlcaleica.comms_data.trade.medicine = true + stationAlcaleica.comms_data.trade.food = true end - stationAlcaleica.publicRelations = true - stationAlcaleica.generalInformation = "We make and supply optic components for various station and ship systems" - 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" return stationAlcaleica end function placeAnderson() --Anderson stationAnderson = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation) stationAnderson:setPosition(psx,psy):setCallSign("Anderson"):setDescription("Battery and software engineering") + stationAnderson.comms_data = { + friendlyness = random(0,100), + weapons = {Homing = "neutral", HVLI = "neutral", Mine = "neutral", Nuke = "friend", EMP = "friend"}, + weapon_available = {Homing = random(1,10)<=(8-difficulty), HVLI = random(1,10)<=(9-difficulty), Mine = random(1,10)<=(7-difficulty), Nuke = random(1,10)<=(5-difficulty), EMP = random(1,10)<=(6-difficulty)}, + service_cost = {supplydrop = math.random(80,120), reinforcements = math.random(125,175)}, + reputation_cost_multipliers = {friend = 1.0, neutral = 3.0}, + max_weapon_refill_amount = {friend = 1.0, neutral = 0.5 }, + goods = { battery = {quantity = 5, cost = 66}, + software = {quantity = 5, cost = 115} }, + trade = { food = false, medicine = false, luxury = true }, + public_relations = true, + general_information = "We provide high quality high capacity batteries and specialized software for all shipboard systems", + history = "The station is named after a fictional software engineer in a late 20th century movie depicting humanity unknowingly conquered by aliens and kept docile by software generated illusion" + } if stationFaction == "Human Navy" then + stationAnderson.comms_data.goods.food = {quantity = math.random(5,10), cost = 1} if random(1,5) <= 1 then - goods[stationAnderson] = {{"food",math.random(5,10),1},{"medicine",5,5},{"battery",5,65},{"software",5,115}} - else - goods[stationAnderson] = {{"food",math.random(5,10),1},{"battery",5,65},{"software",5,115}} + stationAnderson.comms_data.goods.medicine = {quantity = 5, cost = 5} end - else - goods[stationAnderson] = {{"battery",5,65},{"software",5,115}} end - tradeLuxury[stationAnderson] = true - stationAnderson.publicRelations = true - stationAnderson.generalInformation = "We provide high quality high capacity batteries and specialized software for all shipboard systems" - 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" return stationAnderson end function placeArcher() --Archer stationArcher = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation) stationArcher:setPosition(psx,psy):setCallSign("Archer"):setDescription("Shield and Armor Research") + stationArcher.comms_data = { + friendlyness = random(0,100), + weapons = {Homing = "neutral", HVLI = "neutral", Mine = "neutral", Nuke = "friend", EMP = "friend"}, + weapon_available = {Homing = random(1,10)<=(8-difficulty), HVLI = random(1,10)<=(9-difficulty), Mine = random(1,10)<=(7-difficulty), Nuke = random(1,10)<=(5-difficulty), EMP = random(1,10)<=(6-difficulty)}, + service_cost = {supplydrop = math.random(80,120), reinforcements = math.random(125,175)}, + reputation_cost_multipliers = {friend = 1.0, neutral = 3.0}, + max_weapon_refill_amount = {friend = 1.0, neutral = 0.5 }, + goods = { shield = {quantity = 5, cost = 90} }, + trade = { food = false, medicine = false, luxury = true }, + buy = { [randomMineral()] = math.random(40,200) }, + public_relations = true, + general_information = "The finest shield and armor manufacturer in the quadrant", + history = "We named this station for the pioneering spirit of the 22nd century Starfleet explorer, Captain Jonathan Archer" + } if stationFaction == "Human Navy" then + stationArcher.comms_data.goods.food = {quantity = math.random(5,10), cost = 1} if random(1,5) <= 1 then - goods[stationArcher] = {{"food",math.random(5,10),1},{"medicine",5,5},{"shield",5,90}} + stationArcher.comms_data.goods.medicine = {quantity = 5, cost = 5} else - goods[stationArcher] = {{"food",math.random(5,10),1},{"shield",5,90}} - tradeMedicine[stationArcher] = true + stationArcher.comms_data.trade.medicine = true end else - goods[stationArcher] = {{"shield",5,90}} - tradeMedicine[stationArcher] = true + stationArcher.comms_data.trade.medicine = true end - tradeLuxury[stationArcher] = true - stationArcher.publicRelations = true - stationArcher.generalInformation = "The finest shield and armor manufacturer in the quadrant" - stationArcher.stationHistory = "We named this station for the pioneering spirit of the 22nd century Starfleet explorer, Captain Jonathan Archer" return stationArcher end function placeArchimedes() --Archimedes stationArchimedes = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation) stationArchimedes:setPosition(psx,psy):setCallSign("Archimedes"):setDescription("Energy and particle beam components") + stationArchimedes.comms_data = { + friendlyness = random(0,100), + weapons = {Homing = "neutral", HVLI = "neutral", Mine = "neutral", Nuke = "friend", EMP = "friend"}, + weapon_available = {Homing = random(1,10)<=(8-difficulty), HVLI = random(1,10)<=(9-difficulty), Mine = random(1,10)<=(7-difficulty), Nuke = random(1,10)<=(5-difficulty), EMP = random(1,10)<=(6-difficulty)}, + service_cost = {supplydrop = math.random(80,120), reinforcements = math.random(125,175)}, + reputation_cost_multipliers = {friend = 1.0, neutral = 3.0}, + max_weapon_refill_amount = {friend = 1.0, neutral = 0.5 }, + goods = { beam = {quantity = 5, cost = 80} }, + trade = { food = false, medicine = false, luxury = true }, + public_relations = true, + general_information = "We fabricate general and specialized components for ship beam systems", + history = "This station was named after Archimedes who, according to legend, used a series of adjustable focal length mirrors to focus sunlight on a Roman naval fleet invading Syracuse, setting fire to it" + } if stationFaction == "Human Navy" then + stationArchimedes.comms_data.goods.food = {quantity = math.random(5,10), cost = 1} if random(1,5) <= 1 then - goods[stationArchimedes] = {{"food",math.random(5,10),1},{"medicine",5,5},{"beam",5,80}} + stationArchimedes.comms_data.goods.medicine = {quantity = 5, cost = 5} else - goods[stationArchimedes] = {{"food",math.random(5,10),1},{"beam",5,80}} - tradeMedicine[stationArchimedes] = true + stationArchimedes.comms_data.trade.medicine = true end else - goods[stationArchimedes] = {{"beam",5,80}} - tradeFood[stationArchimedes] = true + stationArchimedes.comms_data.trade.food = true end - tradeLuxury[stationArchimedes] = true - stationArchimedes.publicRelations = true - stationArchimedes.generalInformation = "We fabricate general and specialized components for ship beam systems" - 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" return stationArchimedes end function placeArmstrong() --Armstrong stationArmstrong = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation) stationArmstrong:setPosition(psx,psy):setCallSign("Armstrong"):setDescription("Warp and Impulse engine manufacturing") + stationArmstrong.comms_data = { + friendlyness = random(0,100), + weapons = {Homing = "neutral", HVLI = "neutral", Mine = "neutral", Nuke = "friend", EMP = "friend"}, + weapon_available = {Homing = random(1,10)<=(8-difficulty), HVLI = random(1,10)<=(9-difficulty), Mine = random(1,10)<=(7-difficulty), Nuke = random(1,10)<=(5-difficulty), EMP = random(1,10)<=(6-difficulty)}, + service_cost = {supplydrop = math.random(80,120), reinforcements = math.random(125,175)}, + reputation_cost_multipliers = {friend = 1.0, neutral = 3.0}, + max_weapon_refill_amount = {friend = 1.0, neutral = 0.5 }, + goods = { warp = {quantity = 5, cost = 77}, + repulsor = {quantity = 5, cost = 62} }, + trade = { food = false, medicine = false, luxury = false }, + buy = { [randomMineral()] = math.random(40,200) }, + public_relations = true, + general_information = "We manufacture warp, impulse and jump engines for the human navy fleet as well as other independent clients on a contract basis", + history = "The station is named after the late 19th century astronaut as well as the fictionlized stations that followed. The station initially constructed entire space worthy vessels. In time, it transitioned into specializeing in propulsion systems." + } if stationFaction == "Human Navy" then + stationArmstrong.comms_data.goods.food = {quantity = math.random(5,10), cost = 1} if random(1,5) <= 1 then - goods[stationArmstrong] = {{"food",math.random(5,10),1},{"medicine",5,5},{"repulsor",5,62}} - else - goods[stationArmstrong] = {{"food",math.random(5,10),1},{"repulsor",5,62}} + stationArmstrong.comms_data.goods.medicine = {quantity = 5, cost = 5} end - else - goods[stationArmstrong] = {{"repulsor",5,62}} end --- table.insert(goods[stationArmstrong],{"warp",5,77}) - stationArmstrong.publicRelations = true - stationArmstrong.generalInformation = "We manufacture warp, impulse and jump engines for the human navy fleet as well as other independent clients on a contract basis" - 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." return stationArmstrong end function placeAsimov() --Asimov stationAsimov = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation) stationAsimov:setCallSign("Asimov"):setDescription("Training and Coordination"):setPosition(psx,psy) + stationAsimov.comms_data = { + friendlyness = random(0,100), + weapons = {Homing = "neutral", HVLI = "neutral", Mine = "neutral", Nuke = "friend", EMP = "friend"}, + weapon_available = {Homing = random(1,10)<=(8-difficulty), HVLI = random(1,10)<=(9-difficulty), Mine = random(1,10)<=(7-difficulty), Nuke = random(1,10)<=(5-difficulty), EMP = random(1,10)<=(6-difficulty)}, + service_cost = {supplydrop = math.random(80,120), reinforcements = math.random(125,175)}, + reputation_cost_multipliers = {friend = 1.0, neutral = 3.0}, + max_weapon_refill_amount = {friend = 1.0, neutral = 0.5 }, + goods = { tractor = {quantity = 5, cost = 48} }, + trade = { food = false, medicine = false, luxury = false }, + public_relations = true, + general_information = "We train naval cadets in routine and specialized functions aboard space vessels and coordinate naval activity throughout the sector", + history = "The original station builders were fans of the late 20th century scientist and author Isaac Asimov. The station was initially named Foundation, but was later changed simply to Asimov. It started off as a stellar observatory, then became a supply stop and as it has grown has become an educational and coordination hub for the region" + } if stationFaction == "Human Navy" then + stationAsimov.comms_data.goods.food = {quantity = math.random(5,10), cost = 1} if random(1,5) <= 1 then - goods[stationAsimov] = {{"food",math.random(5,10),1},{"medicine",5,5},{"tractor",5,48}} - else - goods[stationAsimov] = {{"food",math.random(5,10),1},{"tractor",5,48}} + stationAsimov.comms_data.goods.medicine = {quantity = 5, cost = 5} end - else - goods[stationAsimov] = {{"tractor",5,48}} end - stationAsimov.publicRelations = true - stationAsimov.generalInformation = "We train naval cadets in routine and specialized functions aboard space vessels and coordinate naval activity throughout the sector" - 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" return stationAsimov end function placeBarclay() --Barclay stationBarclay = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation) stationBarclay:setPosition(psx,psy):setCallSign("Barclay"):setDescription("Communication components") + stationBarclay.comms_data = { + friendlyness = random(0,100), + weapons = {Homing = "neutral", HVLI = "neutral", Mine = "neutral", Nuke = "friend", EMP = "friend"}, + weapon_available = {Homing = random(1,10)<=(8-difficulty), HVLI = random(1,10)<=(9-difficulty), Mine = random(1,10)<=(7-difficulty), Nuke = random(1,10)<=(5-difficulty), EMP = random(1,10)<=(6-difficulty)}, + service_cost = {supplydrop = math.random(80,120), reinforcements = math.random(125,175)}, + reputation_cost_multipliers = {friend = 1.0, neutral = 3.0}, + max_weapon_refill_amount = {friend = 1.0, neutral = 0.5 }, + goods = { communication = {quantity = 5, cost = 58} }, + trade = { food = false, medicine = false, luxury = false }, + buy = { [randomMineral()] = math.random(40,200) }, + public_relations = true, + general_information = "We provide a range of communication equipment and software for use aboard ships", + history = "The station is named after Reginald Barclay who established the first transgalactic com link through the creative application of a quantum singularity. Station personnel often refer to the station as the Broccoli station" + } if stationFaction == "Human Navy" then + stationBarclay.comms_data.goods.food = {quantity = math.random(5,10), cost = 1} if random(1,5) <= 1 then - goods[stationBarclay] = {{"food",math.random(5,10),1},{"medicine",5,5},{"communication",5,58}} + stationBarclay.comms_data.goods.medicine = {quantity = 5, cost = 5} else - goods[stationBarclay] = {{"food",math.random(5,10),1},{"communication",5,58}} - tradeMedicine[stationBarclay] = true + stationBarclay.comms_data.trade.medicine = true end else - goods[stationBarclay] = {{"communication",5,58}} - tradeMedicine[stationBarclay] = true + stationBarclay.comms_data.trade.medicine = true end - stationBarclay.publicRelations = true - stationBarclay.generalInformation = "We provide a range of communication equipment and software for use aboard ships" - 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" return stationBarclay end function placeBethesda() --Bethesda stationBethesda = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation) stationBethesda:setPosition(psx,psy):setCallSign("Bethesda"):setDescription("Medical research") - goods[stationBethesda] = {{"food",math.random(5,10),1},{"medicine",5,5},{"autodoc",5,36}} - stationBethesda.publicRelations = true - stationBethesda.generalInformation = "We research and treat exotic medical conditions" - 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" + stationBethesda.comms_data = { + friendlyness = random(0,100), + weapons = {Homing = "neutral", HVLI = "neutral", Mine = "neutral", Nuke = "friend", EMP = "friend"}, + weapon_available = {Homing = random(1,10)<=(8-difficulty), HVLI = random(1,10)<=(9-difficulty), Mine = random(1,10)<=(7-difficulty), Nuke = random(1,10)<=(5-difficulty), EMP = random(1,10)<=(6-difficulty)}, + service_cost = {supplydrop = math.random(80,120), reinforcements = math.random(125,175)}, + reputation_cost_multipliers = {friend = 1.0, neutral = 3.0}, + max_weapon_refill_amount = {friend = 1.0, neutral = 0.5 }, + goods = { autodoc = {quantity = 5, cost = 36}, + medicine = {quantity = 5, cost = 5}, + food = {quantity = math.random(5,10), cost = 1} }, + trade = { food = false, medicine = false, luxury = false }, + public_relations = true, + general_information = "We research and treat exotic medical conditions", + history = "The station is named after the United States national medical research center based in Bethesda, Maryland on earth which was established in the mid 20th century" + } return stationBethesda end function placeBroeck() --Broeck stationBroeck = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation) stationBroeck:setPosition(psx,psy):setCallSign("Broeck"):setDescription("Warp drive components") + stationBroeck.comms_data = { + friendlyness = random(0,100), + weapons = {Homing = "neutral", HVLI = "neutral", Mine = "neutral", Nuke = "friend", EMP = "friend"}, + weapon_available = {Homing = random(1,10)<=(8-difficulty), HVLI = random(1,10)<=(9-difficulty), Mine = random(1,10)<=(7-difficulty), Nuke = random(1,10)<=(5-difficulty), EMP = random(1,10)<=(6-difficulty)}, + service_cost = {supplydrop = math.random(80,120), reinforcements = math.random(125,175)}, + reputation_cost_multipliers = {friend = 1.0, neutral = 3.0}, + max_weapon_refill_amount = {friend = 1.0, neutral = 0.5 }, + goods = { warp = {quantity = 5, cost = 36} }, + trade = { food = false, medicine = false, luxury = random(1,100) < 62 }, + buy = { [randomMineral()] = math.random(40,200) }, + public_relations = true, + general_information = "We provide warp drive engines and components", + history = "This station is named after Chris Van Den Broeck who did some initial research into the possibility of warp drive in the late 20th century on Earth" + } if stationFaction == "Human Navy" then + stationBroeck.comms_data.goods.food = {quantity = math.random(5,10), cost = 1} if random(1,5) <= 1 then - goods[stationBroeck] = {{"food",math.random(5,10),1},{"medicine",5,5},{"warp",5,130}} - if random(1,100) < 62 then tradeLuxury[stationBroeck] = true end + stationBroeck.comms_data.goods.medicine = {quantity = 5, cost = 5} else - goods[stationBroeck] = {{"food",math.random(5,10),1},{"warp",5,130}} - if random(1,100) < 53 then tradeMedicine[stationBroeck] = true end - if random(1,100) < 62 then tradeLuxury[stationBroeck] = true end + stationBroeck.comms_data.trade.medicine = random(1,100) < 53 end else - goods[stationBroeck] = {{"warp",5,130}} - if random(1,100) < 53 then tradeMedicine[stationBroeck] = true end - if random(1,100) < 14 then tradeFood[stationBroeck] = true end - if random(1,100) < 62 then tradeLuxury[stationBroeck] = true end - end - stationBroeck.publicRelations = true - stationBroeck.generalInformation = "We provide warp drive engines and components" - 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" + stationBroeck.comms_data.trade.medicine = random(1,100) < 53 + stationBroeck.comms_data.trade.food = random(1,100) < 14 + end return stationBroeck end function placeCalifornia() --California stationCalifornia = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation) stationCalifornia:setPosition(psx,psy):setCallSign("California"):setDescription("Mining station") + stationCalifornia.comms_data = { + friendlyness = random(0,100), + weapons = {Homing = "neutral", HVLI = "neutral", Mine = "neutral", Nuke = "friend", EMP = "friend"}, + weapon_available = {Homing = random(1,10)<=(8-difficulty), HVLI = random(1,10)<=(9-difficulty), Mine = random(1,10)<=(7-difficulty), Nuke = random(1,10)<=(5-difficulty), EMP = random(1,10)<=(6-difficulty)}, + service_cost = {supplydrop = math.random(80,120), reinforcements = math.random(125,175)}, + reputation_cost_multipliers = {friend = 1.0, neutral = 3.0}, + max_weapon_refill_amount = {friend = 1.0, neutral = 0.5 }, + goods = { gold = {quantity = 5, cost = 90}, + dilithium = {quantity = 2, cost = 25} }, + trade = { food = false, medicine = false, luxury = false }, + buy = { [randomComponent()] = math.random(40,200) } + } if stationFaction == "Human Navy" then + stationCalifornia.comms_data.goods.food = {quantity = math.random(5,10), cost = 1} if random(1,5) <= 1 then - goods[stationCalifornia] = {{"food",math.random(5,10),1},{"medicine",5,5},{"gold",5,25},{"dilithium",2,25}} - else - goods[stationCalifornia] = {{"food",math.random(5,10),1},{"gold",5,25},{"dilithium",2,25}} + stationCalifornia.comms_data.goods.medicine = {quantity = 5, cost = 5} end - else - goods[stationCalifornia] = {{"gold",5,25},{"dilithium",2,25}} end return stationCalifornia end @@ -1172,264 +1306,343 @@ function placeCalvin() --Calvin stationCalvin = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation) stationCalvin:setPosition(psx,psy):setCallSign("Calvin"):setDescription("Robotic research") + stationCalvin.comms_data = { + friendlyness = random(0,100), + weapons = {Homing = "neutral", HVLI = "neutral", Mine = "neutral", Nuke = "friend", EMP = "friend"}, + weapon_available = {Homing = random(1,10)<=(8-difficulty), HVLI = random(1,10)<=(9-difficulty), Mine = random(1,10)<=(7-difficulty), Nuke = random(1,10)<=(5-difficulty), EMP = random(1,10)<=(6-difficulty)}, + service_cost = {supplydrop = math.random(80,120), reinforcements = math.random(125,175)}, + reputation_cost_multipliers = {friend = 1.0, neutral = 3.0}, + max_weapon_refill_amount = {friend = 1.0, neutral = 0.5 }, + goods = { robotic = {quantity = 5, cost = 90} }, + trade = { food = false, medicine = false, luxury = true }, + buy = { [randomComponent("robotic")] = math.random(40,200) }, + public_relations = true, + general_information = "We research and provide robotic systems and components", + history = "This station is named after Dr. Susan Calvin who pioneered robotic behavioral research and programming" + } if stationFaction == "Human Navy" then + stationCalvin.comms_data.goods.food = {quantity = math.random(5,10), cost = 1} if random(1,5) <= 1 then - goods[stationCalvin] = {{"food",math.random(5,10),1},{"medicine",5,5},{"robotic",5,87}} - else - goods[stationCalvin] = {{"food",math.random(5,10),1},{"robotic",5,87}} + stationCalvin.comms_data.goods.medicine = {quantity = 5, cost = 5} end else - goods[stationCalvin] = {{"robotic",5,87}} - if random(1,100) < 8 then tradeFood[stationCalvin] = true end + stationCalvin.comms_data.trade.food = random(1,100) < 8 end - tradeLuxury[stationCalvin] = true - stationCalvin.publicRelations = true - stationCalvin.generalInformation = "We research and provide robotic systems and components" - stationCalvin.stationHistory = "This station is named after Dr. Susan Calvin who pioneered robotic behavioral research and programming" return stationCalvin end function placeCavor() --Cavor stationCavor = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation) stationCavor:setPosition(psx,psy):setCallSign("Cavor"):setDescription("Advanced Material components") + stationCavor.comms_data = { + friendlyness = random(0,100), + weapons = {Homing = "neutral", HVLI = "neutral", Mine = "neutral", Nuke = "friend", EMP = "friend"}, + weapon_available = {Homing = random(1,10)<=(8-difficulty), HVLI = random(1,10)<=(9-difficulty), Mine = random(1,10)<=(7-difficulty), Nuke = random(1,10)<=(5-difficulty), EMP = random(1,10)<=(6-difficulty)}, + service_cost = {supplydrop = math.random(80,120), reinforcements = math.random(125,175)}, + reputation_cost_multipliers = {friend = 1.0, neutral = 3.0}, + max_weapon_refill_amount = {friend = 1.0, neutral = 0.5 }, + goods = { filament = {quantity = 5, cost = 42} }, + trade = { food = false, medicine = false, luxury = false }, + public_relations = true, + general_information = "We fabricate several different kinds of materials critical to various space industries like ship building, station construction and mineral extraction", + history = "We named our station after Dr. Cavor, the physicist that invented a barrier material for gravity waves - Cavorite" + } if stationFaction == "Human Navy" then + stationCavor.comms_data.goods.food = {quantity = math.random(5,10), cost = 1} if random(1,5) <= 1 then - goods[stationCavor] = {{"food",math.random(5,10),1},{"medicine",5,5},{"filament",5,42}} - if random(1,100) < 33 then tradeLuxury[stationCavor] = true end + stationCavor.comms_data.goods.medicine = {quantity = 5, cost = 5} + stationCavor.comms_data.trade.luxury = random(1,100) < 33 else - goods[stationCavor] = {{"food",math.random(5,10),1},{"filament",5,42}} if random(1,100) < 50 then - tradeMedicine[stationCavor] = true + stationCavor.comms_data.trade.medicine = true else - tradeLuxury[stationCavor] = true + stationCavor.comms_data.trade.luxury = true end end else - goods[stationCavor] = {{"filament",5,42}} - whatTrade = random(1,100) + local whatTrade = random(1,100) if whatTrade < 33 then - tradeMedicine[stationCavor] = true + stationCavor.comms_data.trade.medicine = true elseif whatTrade > 66 then - tradeFood[stationCavor] = true + stationCavor.comms_data.trade.food = true else - tradeLuxury[stationCavor] = true + stationCavor.comms_data.trade.luxury = true end end - stationCavor.publicRelations = true - stationCavor.generalInformation = "We fabricate several different kinds of materials critical to various space industries like ship building, station construction and mineral extraction" - stationCavor.stationHistory = "We named our station after Dr. Cavor, the physicist that invented a barrier material for gravity waves - Cavorite" return stationCavor end function placeChatuchak() --Chatuchak stationChatuchak = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation) stationChatuchak:setPosition(psx,psy):setCallSign("Chatuchak"):setDescription("Trading station") + stationChatuchak.comms_data = { + friendlyness = random(0,100), + weapons = {Homing = "neutral", HVLI = "neutral", Mine = "neutral", Nuke = "friend", EMP = "friend"}, + weapon_available = {Homing = random(1,10)<=(8-difficulty), HVLI = random(1,10)<=(9-difficulty), Mine = random(1,10)<=(7-difficulty), Nuke = random(1,10)<=(5-difficulty), EMP = random(1,10)<=(6-difficulty)}, + service_cost = {supplydrop = math.random(80,120), reinforcements = math.random(125,175)}, + reputation_cost_multipliers = {friend = 1.0, neutral = 3.0}, + max_weapon_refill_amount = {friend = 1.0, neutral = 0.5 }, + goods = { luxury = {quantity = 5, cost = 60} }, + trade = { food = false, medicine = false, luxury = false }, + public_relations = true, + general_information = "Only the largest market and trading location in twenty sectors. You can find your heart's desire here", + history = "Modeled after the early 21st century bazaar on Earth in Bangkok, Thailand. Designed and built with trade and commerce in mind" + } if stationFaction == "Human Navy" then + stationChatuchak.comms_data.goods.food = {quantity = math.random(5,10), cost = 1} if random(1,5) <= 1 then - goods[stationChatuchak] = {{"food",math.random(5,10),1},{"medicine",5,5},{"luxury",5,60}} - else - goods[stationChatuchak] = {{"food",math.random(5,10),1},{"luxury",5,60}} + stationChatuchak.comms_data.goods.medicine = {quantity = 5, cost = 5} end - else - goods[stationChatuchak] = {{"luxury",5,60}} end - stationChatuchak.publicRelations = true - stationChatuchak.generalInformation = "Only the largest market and trading location in twenty sectors. You can find your heart's desire here" - stationChatuchak.stationHistory = "Modeled after the early 21st century bazaar on Earth in Bangkok, Thailand. Designed and built with trade and commerce in mind" return stationChatuchak end function placeCoulomb() --Coulomb stationCoulomb = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation) stationCoulomb:setPosition(psx,psy):setCallSign("Coulomb"):setDescription("Shielded circuitry fabrication") + stationCoulomb.comms_data = { + friendlyness = random(0,100), + weapons = {Homing = "neutral", HVLI = "neutral", Mine = "neutral", Nuke = "friend", EMP = "friend"}, + weapon_available = {Homing = random(1,10)<=(8-difficulty), HVLI = random(1,10)<=(9-difficulty), Mine = random(1,10)<=(7-difficulty), Nuke = random(1,10)<=(5-difficulty), EMP = random(1,10)<=(6-difficulty)}, + service_cost = {supplydrop = math.random(80,120), reinforcements = math.random(125,175)}, + reputation_cost_multipliers = {friend = 1.0, neutral = 3.0}, + max_weapon_refill_amount = {friend = 1.0, neutral = 0.5 }, + goods = { circuit = {quantity = 5, cost = 50} }, + trade = { food = false, medicine = false, luxury = random(1,100) < 82 }, + buy = { [randomMineral()] = math.random(40,200) }, + public_relations = true, + general_information = "We make a large variety of circuits for numerous ship systems shielded from sensor detection and external control interference", + history = "Our station is named after the law which quantifies the amount of force with which stationary electrically charged particals repel or attact each other - a fundamental principle in the design of our circuits" + } if stationFaction == "Human Navy" then + stationCoulomb.comms_data.goods.food = {quantity = math.random(5,10), cost = 1} if random(1,5) <= 1 then - goods[stationCoulomb] = {{"food",math.random(5,10),1},{"medicine",5,5},{"circuit",5,50}} + stationCoulomb.comms_data.goods.medicine = {quantity = 5, cost = 5} else - goods[stationCoulomb] = {{"food",math.random(5,10),1},{"circuit",5,50}} - if random(1,100) < 27 then tradeMedicine[stationCoulomb] = true end + stationCoulomb.comms_data.trade.medicine = random(1,100) < 27 end else - goods[stationCoulomb] = {{"circuit",5,50}} - if random(1,100) < 27 then tradeMedicine[stationCoulomb] = true end - if random(1,100) < 16 then tradeFood[stationCoulomb] = true end - end - if random(1,100) < 82 then tradeLuxury[stationCoulomb] = true end - stationCoulomb.publicRelations = true - stationCoulomb.generalInformation = "We make a large variety of circuits for numerous ship systems shielded from sensor detection and external control interference" - 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" + stationCoulomb.comms_data.trade.medicine = random(1,100) < 27 + stationCoulomb.comms_data.trade.food = random(1,100) < 16 + end return stationCoulomb end function placeCyrus() --Cyrus stationCyrus = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation) stationCyrus:setPosition(psx,psy):setCallSign("Cyrus"):setDescription("Impulse engine components") + stationCyrus.comms_data = { + friendlyness = random(0,100), + weapons = {Homing = "neutral", HVLI = "neutral", Mine = "neutral", Nuke = "friend", EMP = "friend"}, + weapon_available = {Homing = random(1,10)<=(8-difficulty), HVLI = random(1,10)<=(9-difficulty), Mine = random(1,10)<=(7-difficulty), Nuke = random(1,10)<=(5-difficulty), EMP = random(1,10)<=(6-difficulty)}, + service_cost = {supplydrop = math.random(80,120), reinforcements = math.random(125,175)}, + reputation_cost_multipliers = {friend = 1.0, neutral = 3.0}, + max_weapon_refill_amount = {friend = 1.0, neutral = 0.5 }, + goods = { impulse = {quantity = 5, cost = 124} }, + trade = { food = false, medicine = false, luxury = random(1,100) < 78 }, + public_relations = true, + general_information = "We supply high quality impulse engines and parts for use aboard ships", + history = "This station was named after the fictional engineer, Cyrus Smith created by 19th century author Jules Verne" + } if stationFaction == "Human Navy" then + stationCyrus.comms_data.goods.food = {quantity = math.random(5,10), cost = 1} if random(1,5) <= 1 then - goods[stationCyrus] = {{"food",math.random(5,10),1},{"medicine",5,5},{"impulse",5,124}} + stationCyrus.comms_data.goods.medicine = {quantity = 5, cost = 5} else - goods[stationCyrus] = {{"food",math.random(5,10),1},{"impulse",5,124}} - if random(1,100) < 34 then tradeMedicine[stationCyrus] = true end + stationCyrus.comms_data.trade.medicine = random(1,100) < 34 end else - goods[stationCyrus] = {{"impulse",5,124}} - if random(1,100) < 34 then tradeMedicine[stationCyrus] = true end - if random(1,100) < 13 then tradeFood[stationCyrus] = true end - end - if random(1,100) < 78 then tradeLuxury[stationCyrus] = true end - stationCyrus.publicRelations = true - stationCyrus.generalInformation = "We supply high quality impulse engines and parts for use aboard ships" - stationCyrus.stationHistory = "This station was named after the fictional engineer, Cyrus Smith created by 19th century author Jules Verne" + stationCyrus.comms_data.trade.medicine = random(1,100) < 34 + stationCyrus.comms_data.trade.food = random(1,100) < 13 + end return stationCyrus end function placeDeckard() --Deckard stationDeckard = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation) stationDeckard:setPosition(psx,psy):setCallSign("Deckard"):setDescription("Android components") + stationDeckard.comms_data = { + friendlyness = random(0,100), + weapons = {Homing = "neutral", HVLI = "neutral", Mine = "neutral", Nuke = "friend", EMP = "friend"}, + weapon_available = {Homing = random(1,10)<=(8-difficulty), HVLI = random(1,10)<=(9-difficulty), Mine = random(1,10)<=(7-difficulty), Nuke = random(1,10)<=(5-difficulty), EMP = random(1,10)<=(6-difficulty)}, + service_cost = {supplydrop = math.random(80,120), reinforcements = math.random(125,175)}, + reputation_cost_multipliers = {friend = 1.0, neutral = 3.0}, + max_weapon_refill_amount = {friend = 1.0, neutral = 0.5 }, + goods = { android = {quantity = 5, cost = 73} }, + trade = { food = false, medicine = false, luxury = true }, + public_relations = true, + general_information = "Supplier of android components, programming and service", + history = "Named for Richard Deckard who inspired many of the sophisticated safety security algorithms now required for all androids" + } if stationFaction == "Human Navy" then + stationDeckard.comms_data.goods.food = {quantity = math.random(5,10), cost = 1} if random(1,5) <= 1 then - goods[stationDeckard] = {{"food",math.random(5,10),1},{"medicine",5,5},{"android",5,73}} - else - goods[stationDeckard] = {{"food",math.random(5,10),1},{"android",5,73}} + stationDeckard.comms_data.goods.medicine = {quantity = 5, cost = 5} + stationDeckard.comms_data.goods.medicine.cost = 5 end else - goods[stationDeckard] = {{"android",5,73}} - tradeFood[stationDeckard] = true + stationDeckard.comms_data.trade.food = true end - tradeLuxury[stationDeckard] = true - stationDeckard.publicRelations = true - stationDeckard.generalInformation = "Supplier of android components, programming and service" - stationDeckard.stationHistory = "Named for Richard Deckard who inspired many of the sophisticated safety security algorithms now required for all androids" return stationDeckard end function placeDeer() --Deer stationDeer = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation) stationDeer:setPosition(psx,psy):setCallSign("Deer"):setDescription("Repulsor and Tractor Beam Components") + stationDeer.comms_data = { + friendlyness = random(0,100), + weapons = {Homing = "neutral", HVLI = "neutral", Mine = "neutral", Nuke = "friend", EMP = "friend"}, + weapon_available = {Homing = random(1,10)<=(8-difficulty), HVLI = random(1,10)<=(9-difficulty), Mine = random(1,10)<=(7-difficulty), Nuke = random(1,10)<=(5-difficulty), EMP = random(1,10)<=(6-difficulty)}, + service_cost = {supplydrop = math.random(80,120), reinforcements = math.random(125,175)}, + reputation_cost_multipliers = {friend = 1.0, neutral = 3.0}, + max_weapon_refill_amount = {friend = 1.0, neutral = 0.5 }, + goods = { tractor = {quantity = 5, cost = 90}, + repulsor = {quantity = 5, cost = 95} }, + trade = { food = false, medicine = false, luxury = true }, + buy = { [randomMineral()] = math.random(40,200) }, + public_relations = true, + general_information = "We can meet all your pushing and pulling needs with specialized equipment custom made", + history = "The station name comes from a short story by the 20th century author Clifford D. Simak as well as from the 19th century developer John Deere who inspired a company that makes the Earth bound equivalents of our products" + } if stationFaction == "Human Navy" then + stationDeer.comms_data.goods.food = {quantity = math.random(5,10), cost = 1} + stationDeer.comms_data.goods.food.cost = 1 if random(1,5) <= 1 then - goods[stationDeer] = {{"food",math.random(5,10),1},{"medicine",5,5},{"tractor",5,90},{"repulsor",5,95}} + stationDeer.comms_data.goods.medicine = {quantity = 5, cost = 5} else - goods[stationDeer] = {{"food",math.random(5,10),1},{"tractor",5,90},{"repulsor",5,95}} - tradeMedicine[stationDeer] = true + stationDeer.comms_data.trade.medicine = true end else - goods[stationDeer] = {{"tractor",5,90},{"repulsor",5,95}} - tradeFood[stationDeer] = true - tradeMedicine[stationDeer] = true - end - tradeLuxury[stationDeer] = true - stationDeer.publicRelations = true - stationDeer.generalInformation = "We can meet all your pushing and pulling needs with specialized equipment custom made" - 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" + stationDeer.comms_data.trade.medicine = true + stationDeer.comms_data.trade.food = true + end return stationDeer end function placeErickson() --Erickson stationErickson = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation) stationErickson:setPosition(psx,psy):setCallSign("Erickson"):setDescription("Transporter components") + stationErickson.comms_data = { + friendlyness = random(0,100), + weapons = {Homing = "neutral", HVLI = "neutral", Mine = "neutral", Nuke = "friend", EMP = "friend"}, + weapon_available = {Homing = random(1,10)<=(8-difficulty), HVLI = random(1,10)<=(9-difficulty), Mine = random(1,10)<=(7-difficulty), Nuke = random(1,10)<=(5-difficulty), EMP = random(1,10)<=(6-difficulty)}, + service_cost = {supplydrop = math.random(80,120), reinforcements = math.random(125,175)}, + reputation_cost_multipliers = {friend = 1.0, neutral = 3.0}, + max_weapon_refill_amount = {friend = 1.0, neutral = 0.5 }, + goods = { transporter = {quantity = 5, cost = 90} }, + trade = { food = false, medicine = false, luxury = true }, + public_relations = true, + general_information = "We provide transporters used aboard ships as well as the components for repair and maintenance", + history = "The station is named after the early 22nd century inventor of the transporter, Dr. Emory Erickson. This station is proud to have received the endorsement of Admiral Leonard McCoy" + } if stationFaction == "Human Navy" then + stationErickson.comms_data.goods.food = {quantity = math.random(5,10), cost = 1} if random(1,5) <= 1 then - goods[stationErickson] = {{"food",math.random(5,10),1},{"medicine",5,5},{"transporter",5,63}} + stationErickson.comms_data.goods.medicine = {quantity = 5, cost = 5} else - goods[stationErickson] = {{"food",math.random(5,10),1},{"transporter",5,63}} - tradeMedicine[stationErickson] = true + stationErickson.comms_data.trade.medicine = true end else - goods[stationErickson] = {{"transporter",5,63}} - tradeFood[stationErickson] = true - tradeMedicine[stationErickson] = true - end - tradeLuxury[stationErickson] = true - stationErickson.publicRelations = true - stationErickson.generalInformation = "We provide transporters used aboard ships as well as the components for repair and maintenance" - 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" + stationErickson.comms_data.trade.medicine = true + stationErickson.comms_data.trade.food = true + end return stationErickson end function placeEvondos() --Evondos stationEvondos = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation) stationEvondos:setPosition(psx,psy):setCallSign("Evondos"):setDescription("Autodoc components") + stationEvondos.comms_data = { + friendlyness = random(0,100), + weapons = {Homing = "neutral", HVLI = "neutral", Mine = "neutral", Nuke = "friend", EMP = "friend"}, + weapon_available = {Homing = random(1,10)<=(8-difficulty), HVLI = random(1,10)<=(9-difficulty), Mine = random(1,10)<=(7-difficulty), Nuke = random(1,10)<=(5-difficulty), EMP = random(1,10)<=(6-difficulty)}, + service_cost = {supplydrop = math.random(80,120), reinforcements = math.random(125,175)}, + reputation_cost_multipliers = {friend = 1.0, neutral = 3.0}, + max_weapon_refill_amount = {friend = 1.0, neutral = 0.5 }, + goods = { autodoc = {quantity = 5, cost = 56} }, + trade = { food = false, medicine = false, luxury = random(1,100) < 41 }, + public_relations = true, + general_information = "We provide components for automated medical machinery", + history = "The station is the evolution of the company that started automated pharmaceutical dispensing in the early 21st century on Earth in Finland" + } if stationFaction == "Human Navy" then + stationEvondos.comms_data.goods.food = {quantity = math.random(5,10), cost = 1} if random(1,5) <= 1 then - goods[stationEvondos] = {{"food",math.random(5,10),1},{"medicine",5,5},{"autodoc",5,56}} + stationEvondos.comms_data.goods.medicine = {quantity = 5, cost = 5} else - goods[stationEvondos] = {{"food",math.random(5,10),1},{"autodoc",5,56}} - tradeMedicine[stationEvondos] = true + stationEvondos.comms_data.trade.medicine = true end else - goods[stationEvondos] = {{"autodoc",5,56}} - tradeMedicine[stationEvondos] = true + stationEvondos.comms_data.trade.medicine = true end - if random(1,100) < 41 then tradeLuxury[stationEvondos] = true end - stationEvondos.publicRelations = true - stationEvondos.generalInformation = "We provide components for automated medical machinery" - stationEvondos.stationHistory = "The station is the evolution of the company that started automated pharmaceutical dispensing in the early 21st century on Earth in Finland" return stationEvondos end function placeFeynman() --Feynman stationFeynman = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation) stationFeynman:setPosition(psx,psy):setCallSign("Feynman"):setDescription("Nanotechnology research") + stationFeynman.comms_data = { + friendlyness = random(0,100), + weapons = {Homing = "neutral", HVLI = "neutral", Mine = "neutral", Nuke = "friend", EMP = "friend"}, + weapon_available = {Homing = random(1,10)<=(8-difficulty), HVLI = random(1,10)<=(9-difficulty), Mine = random(1,10)<=(7-difficulty), Nuke = random(1,10)<=(5-difficulty), EMP = random(1,10)<=(6-difficulty)}, + service_cost = {supplydrop = math.random(80,120), reinforcements = math.random(125,175)}, + reputation_cost_multipliers = {friend = 1.0, neutral = 3.0}, + max_weapon_refill_amount = {friend = 1.0, neutral = 0.5 }, + goods = { software = {quantity = 5, cost = 115}, + nanites = {quantity = 5, cost = 79} }, + trade = { food = false, medicine = false, luxury = true }, + public_relations = true, + general_information = "We provide nanites and software for a variety of ship-board systems", + history = "This station's name recognizes one of the first scientific researchers into nanotechnology, physicist Richard Feynman" + } if stationFaction == "Human Navy" then + stationFeynman.comms_data.goods.food = {quantity = math.random(5,10), cost = 1} if random(1,5) <= 1 then - goods[stationFeynman] = {{"food",math.random(5,10),1},{"medicine",5,5},{"nanites",5,79},{"software",5,115}} - else - goods[stationFeynman] = {{"food",math.random(5,10),1},{"nanites",5,79},{"software",5,115}} + stationFeynman.comms_data.goods.medicine = {quantity = 5, cost = 5} end else - goods[stationFeynman] = {{"nanites",5,79},{"software",5,115}} - tradeFood[stationFeynman] = true - if random(1,100) < 26 then tradeFood[stationFeynman] = true end - end - tradeLuxury[stationFeynman] = true - stationFeynman.publicRelations = true - stationFeynman.generalInformation = "We provide nanites and software for a variety of ship-board systems" - stationFeynman.stationHistory = "This station's name recognizes one of the first scientific researchers into nanotechnology, physicist Richard Feynman" + stationFeynman.comms_data.trade.medicine = true + stationFeynman.comms_data.trade.food = random(1,100) < 26 + end return stationFeynman end function placeGrasberg() --Grasberg - placeRandomAroundPoint(Asteroid,15,1,15000,psx,psy) + placeRandomAsteroidsAroundPoint(15,1,15000,psx,psy) stationGrasberg = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation) stationGrasberg:setPosition(psx,psy):setCallSign("Grasberg"):setDescription("Mining") - stationGrasberg.publicRelations = true - stationGrasberg.generalInformation = "We mine nearby asteroids for precious minerals and process them for sale" - 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" - grasbergGoods = random(1,100) + stationGrasberg.comms_data = { + friendlyness = random(0,100), + weapons = {Homing = "neutral", HVLI = "neutral", Mine = "neutral", Nuke = "friend", EMP = "friend"}, + weapon_available = {Homing = random(1,10)<=(8-difficulty), HVLI = random(1,10)<=(9-difficulty), Mine = random(1,10)<=(7-difficulty), Nuke = random(1,10)<=(5-difficulty), EMP = random(1,10)<=(6-difficulty)}, + service_cost = {supplydrop = math.random(80,120), reinforcements = math.random(125,175)}, + reputation_cost_multipliers = {friend = 1.0, neutral = 3.0}, + max_weapon_refill_amount = {friend = 1.0, neutral = 0.5 }, + goods = { luxury = {quantity = 5, cost = 70} }, + trade = { food = false, medicine = false, luxury = false }, + buy = { [randomComponent()] = math.random(40,200) }, + public_relations = true, + general_information = "We mine nearby asteroids for precious minerals and process them for sale", + history = "This station's name is inspired by a large gold mine on Earth in Indonesia. The station builders hoped to have a similar amount of minerals found amongst these asteroids" + } if stationFaction == "Human Navy" then + stationGrasberg.comms_data.goods.food = {quantity = math.random(5,10), cost = 1} if random(1,5) <= 1 then - if grasbergGoods < 20 then - goods[stationGrasberg] = {{"luxury",5,70},{"gold",5,25},{"cobalt",4,50},{"food",math.random(5,10),1},{"medicine",5,5}} - elseif grasbergGoods < 40 then - goods[stationGrasberg] = {{"luxury",5,70},{"gold",5,25},{"food",math.random(5,10),1},{"medicine",5,5}} - elseif grasbergGoods < 60 then - goods[stationGrasberg] = {{"luxury",5,70},{"cobalt",4,50},{"food",math.random(5,10),1},{"medicine",5,5}} - else - goods[stationGrasberg] = {{"luxury",5,70},{"food",math.random(5,10),1},{"medicine",5,5}} - end - else - if grasbergGoods < 20 then - goods[stationGrasberg] = {{"luxury",5,70},{"gold",5,25},{"cobalt",4,50},{"food",math.random(5,10),1}} - elseif grasbergGoods < 40 then - goods[stationGrasberg] = {{"luxury",5,70},{"gold",5,25},{"food",math.random(5,10),1}} - elseif grasbergGoods < 60 then - goods[stationGrasberg] = {{"luxury",5,70},{"cobalt",4,50},{"food",math.random(5,10),1}} - else - goods[stationGrasberg] = {{"luxury",5,70},{"food",math.random(5,10),1}} - end + stationGrasberg.comms_data.goods.medicine = {quantity = 5, cost = 5} end else - if grasbergGoods < 20 then - goods[stationGrasberg] = {{"luxury",5,70},{"gold",5,25},{"cobalt",4,50}} - elseif grasbergGoods < 40 then - goods[stationGrasberg] = {{"luxury",5,70},{"gold",5,25}} - elseif grasbergGoods < 60 then - goods[stationGrasberg] = {{"luxury",5,70},{"cobalt",4,50}} - else - goods[stationGrasberg] = {{"luxury",5,70}} - end - tradeFood[stationGrasberg] = true + stationGrasberg.comms_data.trade.food = true + end + local grasbergGoods = random(1,100) + if grasbergGoods < 20 then + stationGrasberg.comms_data.goods.gold = {quantity = 5, cost = 25} + stationGrasberg.comms_data.goods.cobalt = {quantity = 4, cost = 50} + elseif grasbergGoods < 40 then + stationGrasberg.comms_data.goods.gold = {quantity = 5, cost = 25} + elseif grasbergGoods < 60 then + stationGrasberg.comms_data.goods.cobalt = {quantity = 4, cost = 50} + else + stationGrasberg.comms_data.goods.nickel = {quantity = 5, cost = 47} end return stationGrasberg end @@ -1437,103 +1650,121 @@ function placeHayden() --Hayden stationHayden = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation) stationHayden:setPosition(psx,psy):setCallSign("Hayden"):setDescription("Observatory and stellar mapping") + stationHayden.comms_data = { + friendlyness = random(0,100), + weapons = {Homing = "neutral", HVLI = "neutral", Mine = "neutral", Nuke = "friend", EMP = "friend"}, + weapon_available = {Homing = random(1,10)<=(8-difficulty), HVLI = random(1,10)<=(9-difficulty), Mine = random(1,10)<=(7-difficulty), Nuke = random(1,10)<=(5-difficulty), EMP = random(1,10)<=(6-difficulty)}, + service_cost = {supplydrop = math.random(80,120), reinforcements = math.random(125,175)}, + reputation_cost_multipliers = {friend = 1.0, neutral = 3.0}, + max_weapon_refill_amount = {friend = 1.0, neutral = 0.5 }, + goods = { nanites = {quantity = 5, cost = 65} }, + trade = { food = false, medicine = false, luxury = false }, + public_relations = true, + general_information = "We study the cosmos and map stellar phenomena. We also track moving asteroids. Look out! Just kidding", + history = "Station named in honor of Charles Hayden whose philanthropy continued astrophysical research and education on Earth in the early 20th century" + } if stationFaction == "Human Navy" then + stationHayden.comms_data.goods.food = {quantity = math.random(5,10), cost = 1} if random(1,5) <= 1 then - goods[stationHayden] = {{"food",math.random(5,10),1},{"medicine",5,5},{"nanites",5,65}} - else - goods[stationHayden] = {{"food",math.random(5,10),1},{"nanites",5,65}} + stationHayden.comms_data.goods.medicine = {quantity = 5, cost = 5} end - else - goods[stationHayden] = {{"nanites",5,65}} end - stationHayden.publicRelations = true - stationHayden.generalInformation = "We study the cosmos and map stellar phenomena. We also track moving asteroids. Look out! Just kidding" return stationHayden end function placeHeyes() --Heyes stationHeyes = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation) stationHeyes:setPosition(psx,psy):setCallSign("Heyes"):setDescription("Sensor components") + stationHeyes.comms_data = { + friendlyness = random(0,100), + weapons = {Homing = "neutral", HVLI = "neutral", Mine = "neutral", Nuke = "friend", EMP = "friend"}, + weapon_available = {Homing = random(1,10)<=(8-difficulty), HVLI = random(1,10)<=(9-difficulty), Mine = random(1,10)<=(7-difficulty), Nuke = random(1,10)<=(5-difficulty), EMP = random(1,10)<=(6-difficulty)}, + service_cost = {supplydrop = math.random(80,120), reinforcements = math.random(125,175)}, + reputation_cost_multipliers = {friend = 1.0, neutral = 3.0}, + max_weapon_refill_amount = {friend = 1.0, neutral = 0.5 }, + goods = { sensor = {quantity = 5, cost = 72} }, + trade = { food = false, medicine = false, luxury = true }, + buy = { [randomMineral()] = math.random(40,200) }, + public_relations = true, + general_information = "We research and manufacture sensor components and systems", + history = "The station is named after Tony Heyes the inventor of some of the earliest electromagnetic sensors in the mid 20th century on Earth in the United Kingdom to assist blind human mobility" + } if stationFaction == "Human Navy" then + stationHeyes.comms_data.goods.food = {quantity = math.random(5,10), cost = 1} if random(1,5) <= 1 then - goods[stationHeyes] = {{"food",math.random(5,10),1},{"medicine",5,5},{"sensor",5,72}} - else - goods[stationHeyes] = {{"food",math.random(5,10),1},{"sensor",5,72}} + stationHeyes.comms_data.goods.medicine = {quantity = 5, cost = 5} end - else - goods[stationHeyes] = {{"sensor",5,72}} end - tradeLuxury[stationHeyes] = true - stationHeyes.publicRelations = true - stationHeyes.generalInformation = "We research and manufacture sensor components and systems" - 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" return stationHeyes end function placeHossam() --Hossam stationHossam = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation) stationHossam:setPosition(psx,psy):setCallSign("Hossam"):setDescription("Nanite supplier") + stationHossam.comms_data = { + friendlyness = random(0,100), + weapons = {Homing = "neutral", HVLI = "neutral", Mine = "neutral", Nuke = "friend", EMP = "friend"}, + weapon_available = {Homing = random(1,10)<=(8-difficulty), HVLI = random(1,10)<=(9-difficulty), Mine = random(1,10)<=(7-difficulty), Nuke = random(1,10)<=(5-difficulty), EMP = random(1,10)<=(6-difficulty)}, + service_cost = {supplydrop = math.random(80,120), reinforcements = math.random(125,175)}, + reputation_cost_multipliers = {friend = 1.0, neutral = 3.0}, + max_weapon_refill_amount = {friend = 1.0, neutral = 0.5 }, + goods = { nanites = {quantity = 5, cost = 90} }, + trade = { food = false, medicine = false, luxury = random(1,100) < 63 }, + public_relations = true, + general_information = "We provide nanites for various organic and non-organic systems", + history = "This station is named after the nanotechnologist Hossam Haick from the early 21st century on Earth in Israel" + } if stationFaction == "Human Navy" then + stationHossam.comms_data.goods.food = {quantity = math.random(5,10), cost = 1} if random(1,5) <= 1 then - goods[stationHossam] = {{"food",math.random(5,10),1},{"medicine",5,5},{"nanites",5,48}} + stationHossam.comms_data.goods.medicine = {quantity = 5, cost = 5} else - goods[stationHossam] = {{"food",math.random(5,10),1},{"nanites",5,48}} - if random(1,100) < 44 then tradeMedicine[stationHossam] = true end + stationHossam.comms_data.trade.medicine = random(1,100) < 44 end else - goods[stationHossam] = {{"nanites",5,48}} - if random(1,100) < 44 then tradeMedicine[stationHossam] = true end - if random(1,100) < 24 then tradeFood[stationHossam] = true end - end - if random(1,100) < 63 then tradeLuxury[stationHossam] = true end - stationHossam.publicRelations = true - stationHossam.generalInformation = "We provide nanites for various organic and non-organic systems" - stationHossam.stationHistory = "This station is named after the nanotechnologist Hossam Haick from the early 21st century on Earth in Israel" + stationHossam.comms_data.trade.medicine = random(1,100) < 44 + stationHossam.comms_data.trade.food = random(1,100) < 24 + end return stationHossam end function placeImpala() --Impala - placeRandomAroundPoint(Asteroid,15,1,15000,psx,psy) + placeRandomAsteroidsAroundPoint(15,1,15000,psx,psy) stationImpala = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation) stationImpala:setPosition(psx,psy):setCallSign("Impala"):setDescription("Mining") - tradeFood[stationImpala] = true - tradeLuxury[stationImpala] = true - stationImpala.publicRelations = true - stationImpala.generalInformation = "We mine nearby asteroids for precious minerals" - impalaGoods = random(1,100) + stationImpala.comms_data = { + friendlyness = random(0,100), + weapons = {Homing = "neutral", HVLI = "neutral", Mine = "neutral", Nuke = "friend", EMP = "friend"}, + weapon_available = {Homing = random(1,10)<=(8-difficulty), HVLI = random(1,10)<=(9-difficulty), Mine = random(1,10)<=(7-difficulty), Nuke = random(1,10)<=(5-difficulty), EMP = random(1,10)<=(6-difficulty)}, + service_cost = {supplydrop = math.random(80,120), reinforcements = math.random(125,175)}, + reputation_cost_multipliers = {friend = 1.0, neutral = 3.0}, + max_weapon_refill_amount = {friend = 1.0, neutral = 0.5 }, + goods = { luxury = {quantity = 5, cost = 70} }, + trade = { food = false, medicine = false, luxury = true }, + buy = { [randomComponent()] = math.random(40,200) }, + public_relations = true, + general_information = "We mine nearby asteroids for precious minerals" + } + local impalaGoods = random(1,100) + if impalaGoods < 20 then + stationImpala.comms_data.goods.gold = {quantity = 5, cost = 25} + stationImpala.comms_data.goods.cobalt = {quantity = 4, cost = 50} + elseif impalaGoods < 40 then + stationImpala.comms_data.goods.gold = {quantity = 5, cost = 25} + elseif impalaGoods < 60 then + stationImpala.comms_data.goods.cobalt = {quantity = 4, cost = 50} + else + stationImpala.comms_data.goods.tritanium = {quantity = 5, cost = 42} + end if stationFaction == "Human Navy" then + stationImpala.comms_data.goods.food = {quantity = math.random(5,10), cost = 1} if random(1,5) <= 1 then - if impalaGoods < 20 then - goods[stationImpala] = {{"luxury",5,70},{"gold",5,25},{"cobalt",4,50},{"food",math.random(5,10),1},{"medicine",5,5}} - elseif impalaGoods < 40 then - goods[stationImpala] = {{"luxury",5,70},{"gold",5,25},{"food",math.random(5,10),1},{"medicine",5,5}} - elseif impalaGoods < 60 then - goods[stationImpala] = {{"luxury",5,70},{"cobalt",4,50},{"food",math.random(5,10),1},{"medicine",5,5}} - else - goods[stationImpala] = {{"luxury",5,70},{"food",math.random(5,10),1},{"medicine",5,5}} - end + stationImpala.comms_data.goods.medicine = {quantity = 5, cost = 5} else - if impalaGoods < 20 then - goods[stationImpala] = {{"luxury",5,70},{"gold",5,25},{"cobalt",4,50},{"food",math.random(5,10),1}} - elseif impalaGoods < 40 then - goods[stationImpala] = {{"luxury",5,70},{"gold",5,25},{"food",math.random(5,10),1}} - elseif impalaGoods < 60 then - goods[stationImpala] = {{"luxury",5,70},{"cobalt",4,50},{"food",math.random(5,10),1}} - else - goods[stationImpala] = {{"luxury",5,70},{"food",math.random(5,10),1}} - end + stationImpala.comms_data.trade.medicine = random(1,100) < 28 end else - if impalaGoods < 20 then - goods[stationImpala] = {{"luxury",5,70},{"gold",5,25},{"cobalt",4,50}} - elseif impalaGoods < 40 then - goods[stationImpala] = {{"luxury",5,70},{"gold",5,25}} - elseif impalaGoods < 60 then - goods[stationImpala] = {{"luxury",5,70},{"cobalt",4,50}} - else - goods[stationImpala] = {{"luxury",5,70}} - end - tradeFood[stationImpala] = true + stationImpala.comms_data.trade.food = true end return stationImpala end @@ -1541,738 +1772,1016 @@ function placeKomov() --Komov stationKomov = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation) stationKomov:setPosition(psx,psy):setCallSign("Komov"):setDescription("Xenopsychology training") + stationKomov.comms_data = { + friendlyness = random(0,100), + weapons = {Homing = "neutral", HVLI = "neutral", Mine = "neutral", Nuke = "friend", EMP = "friend"}, + weapon_available = {Homing = random(1,10)<=(8-difficulty), HVLI = random(1,10)<=(9-difficulty), Mine = random(1,10)<=(7-difficulty), Nuke = random(1,10)<=(5-difficulty), EMP = random(1,10)<=(6-difficulty)}, + service_cost = {supplydrop = math.random(80,120), reinforcements = math.random(125,175)}, + reputation_cost_multipliers = {friend = 1.0, neutral = 3.0}, + max_weapon_refill_amount = {friend = 1.0, neutral = 0.5 }, + goods = { filament = {quantity = 5, cost = 46} }, + trade = { food = false, medicine = false, luxury = false }, + public_relations = true, + general_information = "We provide classes and simulation to help train diverse species in how to relate to each other", + history = "A continuation of the research initially conducted by Dr. Gennady Komov in the early 22nd century on Venus, supported by the application of these principles" + } if stationFaction == "Human Navy" then + stationKomov.comms_data.goods.food = {quantity = math.random(5,10), cost = 1} if random(1,5) <= 1 then - goods[stationKomov] = {{"food",math.random(5,10),1},{"medicine",5,5},{"filament",5,46}} + stationKomov.comms_data.goods.medicine = {quantity = 5, cost = 5} else - goods[stationKomov] = {{"food",math.random(5,10),1},{"filament",5,46}} - if random(1,100) < 44 then tradeMedicine[stationKomov] = true end + stationKomov.comms_data.trade.medicine = random(1,100) < 44 end else - goods[stationKomov] = {{"filament",5,46}} - if random(1,100) < 44 then tradeMedicine[stationKomov] = true end - if random(1,100) < 24 then tradeFood[stationKomov] = true end + stationKomov.comms_data.trade.medicine = random(1,100) < 44 + stationKomov.comms_data.trade.food = random(1,100) < 24 end - stationKomov.publicRelations = true - stationKomov.generalInformation = "We provide classes and simulation to help train diverse species in how to relate to each other" - 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" return stationKomov end function placeKrak() --Krak stationKrak = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation) stationKrak:setPosition(psx,psy):setCallSign("Krak"):setDescription("Mining station") - posAxisKrak = random(0,360) - posKrak = random(10000,60000) - negKrak = random(10000,60000) - spreadKrak = random(4000,7000) - negAxisKrak = posAxisKrak + 180 - xPosAngleKrak, yPosAngleKrak = vectorFromAngle(posAxisKrak, posKrak) - posKrakEnd = random(30,70) - createRandomAlongArc(Asteroid, 30+posKrakEnd, psx+xPosAngleKrak, psy+yPosAngleKrak, posKrak, negAxisKrak, negAxisKrak+posKrakEnd, spreadKrak) - xNegAngleKrak, yNegAngleKrak = vectorFromAngle(negAxisKrak, negKrak) - negKrakEnd = random(40,80) - createRandomAlongArc(Asteroid, 30+negKrakEnd, psx+xNegAngleKrak, psy+yNegAngleKrak, negKrak, posAxisKrak, posAxisKrak+negKrakEnd, spreadKrak) - if random(1,100) < 50 then tradeFood[stationKrak] = true end - if random(1,100) < 50 then tradeLuxury[stationKrak] = true end - krakGoods = random(1,100) + stationKrak.comms_data = { + friendlyness = random(0,100), + weapons = {Homing = "neutral", HVLI = "neutral", Mine = "neutral", Nuke = "friend", EMP = "friend"}, + weapon_available = {Homing = random(1,10)<=(8-difficulty), HVLI = random(1,10)<=(9-difficulty), Mine = random(1,10)<=(7-difficulty), Nuke = random(1,10)<=(5-difficulty), EMP = random(1,10)<=(6-difficulty)}, + service_cost = {supplydrop = math.random(80,120), reinforcements = math.random(125,175)}, + reputation_cost_multipliers = {friend = 1.0, neutral = 3.0}, + max_weapon_refill_amount = {friend = 1.0, neutral = 0.5 }, + goods = { nickel = {quantity = 5, cost = 20} }, + trade = { food = random(1,100) < 50, medicine = true, luxury = random(1,100) < 50 }, + buy = { [randomComponent()] = math.random(40,200) } + } + local posAxisKrak = random(0,360) + local posKrak = random(10000,60000) + local negKrak = random(10000,60000) + local spreadKrak = random(4000,7000) + local negAxisKrak = posAxisKrak + 180 + local xPosAngleKrak, yPosAngleKrak = vectorFromAngle(posAxisKrak, posKrak) + local posKrakEnd = random(30,70) + createRandomAsteroidAlongArc(30+posKrakEnd, psx+xPosAngleKrak, psy+yPosAngleKrak, posKrak, negAxisKrak, negAxisKrak+posKrakEnd, spreadKrak) + local xNegAngleKrak, yNegAngleKrak = vectorFromAngle(negAxisKrak, negKrak) + local negKrakEnd = random(40,80) + createRandomAsteroidAlongArc(30+negKrakEnd, psx+xNegAngleKrak, psy+yNegAngleKrak, negKrak, posAxisKrak, posAxisKrak+negKrakEnd, spreadKrak) + local krakGoods = random(1,100) if krakGoods < 10 then - goods[stationKrak] = {{"nickel",5,20},{"platinum",5,70},{"tritanium",5,50},{"dilithium",5,50}} + stationKrak.comms_data.goods.platinum = {quantity = 5, cost = 70} + stationKrak.comms_data.goods.tritanium = {quantity = 5, cost = 50} + stationKrak.comms_data.goods.dilithium = {quantity = 5, cost = 52} elseif krakGoods < 20 then - goods[stationKrak] = {{"nickel",5,20},{"platinum",5,70},{"tritanium",5,50}} + stationKrak.comms_data.goods.platinum = {quantity = 5, cost = 70} + stationKrak.comms_data.goods.tritanium = {quantity = 5, cost = 50} elseif krakGoods < 30 then - goods[stationKrak] = {{"nickel",5,20},{"platinum",5,70},{"dilithium",5,50}} + stationKrak.comms_data.goods.platinum = {quantity = 5, cost = 70} + stationKrak.comms_data.goods.dilithium = {quantity = 5, cost = 52} elseif krakGoods < 40 then - goods[stationKrak] = {{"nickel",5,20},{"tritanium",5,50},{"dilithium",5,50}} + stationKrak.comms_data.goods.tritanium = {quantity = 5, cost = 50} + stationKrak.comms_data.goods.dilithium = {quantity = 5, cost = 52} elseif krakGoods < 50 then - goods[stationKrak] = {{"nickel",5,20},{"dilithium",5,50}} + stationKrak.comms_data.goods.dilithium = {quantity = 5, cost = 52} elseif krakGoods < 60 then - goods[stationKrak] = {{"nickel",5,20},{"platinum",5,70}} + stationKrak.comms_data.goods.platinum = {quantity = 5, cost = 70} elseif krakGoods < 70 then - goods[stationKrak] = {{"nickel",5,20},{"tritanium",5,50}} + stationKrak.comms_data.goods.tritanium = {quantity = 5, cost = 50} elseif krakGoods < 80 then - goods[stationKrak] = {{"platinum",5,70},{"tritanium",5,50},{"dilithium",5,50}} + stationKrak.comms_data.goods.gold = {quantity = 5, cost = 50} + stationKrak.comms_data.goods.tritanium = {quantity = 5, cost = 50} + elseif krakGoods < 90 then + stationKrak.comms_data.goods.gold = {quantity = 5, cost = 50} + stationKrak.comms_data.goods.dilithium = {quantity = 5, cost = 52} else - goods[stationKrak] = {{"nickel",5,20}} + stationKrak.comms_data.goods.gold = {quantity = 5, cost = 50} end - tradeMedicine[stationKrak] = true return stationKrak end function placeKruk() --Kruk stationKruk = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation) stationKruk:setPosition(psx,psy):setCallSign("Kruk"):setDescription("Mining station") - posAxisKruk = random(0,360) - posKruk = random(10000,60000) - negKruk = random(10000,60000) - spreadKruk = random(4000,7000) - negAxisKruk = posAxisKruk + 180 - xPosAngleKruk, yPosAngleKruk = vectorFromAngle(posAxisKruk, posKruk) - posKrukEnd = random(30,70) - createRandomAlongArc(Asteroid, 30+posKrukEnd, psx+xPosAngleKruk, psy+yPosAngleKruk, posKruk, negAxisKruk, negAxisKruk+posKrukEnd, spreadKruk) - xNegAngleKruk, yNegAngleKruk = vectorFromAngle(negAxisKruk, negKruk) - negKrukEnd = random(40,80) - createRandomAlongArc(Asteroid, 30+negKrukEnd, psx+xNegAngleKruk, psy+yNegAngleKruk, negKruk, posAxisKruk, posAxisKruk+negKrukEnd, spreadKruk) - krukGoods = random(1,100) + stationKruk.comms_data = { + friendlyness = random(0,100), + weapons = {Homing = "neutral", HVLI = "neutral", Mine = "neutral", Nuke = "friend", EMP = "friend"}, + weapon_available = {Homing = random(1,10)<=(8-difficulty), HVLI = random(1,10)<=(9-difficulty), Mine = random(1,10)<=(7-difficulty), Nuke = random(1,10)<=(5-difficulty), EMP = random(1,10)<=(6-difficulty)}, + service_cost = {supplydrop = math.random(80,120), reinforcements = math.random(125,175)}, + reputation_cost_multipliers = {friend = 1.0, neutral = 3.0}, + max_weapon_refill_amount = {friend = 1.0, neutral = 0.5 }, + goods = { nickel = {quantity = 5, cost = math.random(25,35)} }, + trade = { food = random(1,100) < 50, medicine = random(1,100) < 50, luxury = true }, + buy = { [randomComponent()] = math.random(40,200) } + } + local posAxisKruk = random(0,360) + local posKruk = random(10000,60000) + local negKruk = random(10000,60000) + local spreadKruk = random(4000,7000) + local negAxisKruk = posAxisKruk + 180 + local xPosAngleKruk, yPosAngleKruk = vectorFromAngle(posAxisKruk, posKruk) + local posKrukEnd = random(30,70) + createRandomAsteroidAlongArc(30+posKrukEnd, psx+xPosAngleKruk, psy+yPosAngleKruk, posKruk, negAxisKruk, negAxisKruk+posKrukEnd, spreadKruk) + local xNegAngleKruk, yNegAngleKruk = vectorFromAngle(negAxisKruk, negKruk) + local negKrukEnd = random(40,80) + createRandomAsteroidAlongArc(30+negKrukEnd, psx+xNegAngleKruk, psy+yNegAngleKruk, negKruk, posAxisKruk, posAxisKruk+negKrukEnd, spreadKruk) + local krukGoods = random(1,100) if krukGoods < 10 then - goods[stationKruk] = {{"nickel",5,20},{"platinum",5,70},{"tritanium",5,50},{"dilithium",5,50}} + stationKruk.comms_data.goods.platinum = {quantity = 5, cost = math.random(65,75)} + stationKruk.comms_data.goods.tritanium = {quantity = 5, cost = math.random(45,55)} + stationKruk.comms_data.goods.dilithium = {quantity = 5, cost = math.random(45,55)} elseif krukGoods < 20 then - goods[stationKruk] = {{"nickel",5,20},{"platinum",5,70},{"tritanium",5,50}} + stationKruk.comms_data.goods.platinum = {quantity = 5, cost = math.random(65,75)} + stationKruk.comms_data.goods.tritanium = {quantity = 5, cost = math.random(45,55)} elseif krukGoods < 30 then - goods[stationKruk] = {{"nickel",5,20},{"platinum",5,70},{"dilithium",5,50}} + stationKruk.comms_data.goods.platinum = {quantity = 5, cost = math.random(65,75)} + stationKruk.comms_data.goods.dilithium = {quantity = 5, cost = math.random(45,55)} elseif krukGoods < 40 then - goods[stationKruk] = {{"nickel",5,20},{"tritanium",5,50},{"dilithium",5,50}} + stationKruk.comms_data.goods.tritanium = {quantity = 5, cost = math.random(45,55)} + stationKruk.comms_data.goods.dilithium = {quantity = 5, cost = math.random(45,55)} elseif krukGoods < 50 then - goods[stationKruk] = {{"nickel",5,20},{"dilithium",5,50}} + stationKruk.comms_data.goods.dilithium = {quantity = 5, cost = math.random(45,55)} elseif krukGoods < 60 then - goods[stationKruk] = {{"nickel",5,20},{"platinum",5,70}} + stationKruk.comms_data.goods.platinum = {quantity = 5, cost = math.random(65,75)} elseif krukGoods < 70 then - goods[stationKruk] = {{"nickel",5,20},{"tritanium",5,50}} + stationKruk.comms_data.goods.tritanium = {quantity = 5, cost = math.random(45,55)} elseif krukGoods < 80 then - goods[stationKruk] = {{"platinum",5,70},{"tritanium",5,50},{"dilithium",5,50}} + stationKruk.comms_data.goods.gold = {quantity = 5, cost = math.random(45,55)} + stationKruk.comms_data.goods.tritanium = {quantity = 5, cost = math.random(45,55)} + elseif krukGoods < 90 then + stationKruk.comms_data.goods.gold = {quantity = 5, cost = math.random(45,55)} + stationKruk.comms_data.goods.dilithium = {quantity = 5, cost = math.random(45,55)} else - goods[stationKruk] = {{"nickel",5,20}} + stationKruk.comms_data.goods.gold = {quantity = 5, cost = math.random(45,55)} end - tradeLuxury[stationKruk] = true - if random(1,100) < 50 then tradeFood[stationKruk] = true end - if random(1,100) < 50 then tradeMedicine[stationKruk] = true end return stationKruk end function placeLipkin() --Lipkin stationLipkin = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation) stationLipkin:setPosition(psx,psy):setCallSign("Lipkin"):setDescription("Autodoc components") + stationLipkin.comms_data = { + friendlyness = random(0,100), + weapons = {Homing = "neutral", HVLI = "neutral", Mine = "neutral", Nuke = "friend", EMP = "friend"}, + weapon_available = {Homing = random(1,10)<=(8-difficulty), HVLI = random(1,10)<=(9-difficulty), Mine = random(1,10)<=(7-difficulty), Nuke = random(1,10)<=(5-difficulty), EMP = random(1,10)<=(6-difficulty)}, + service_cost = {supplydrop = math.random(80,120), reinforcements = math.random(125,175)}, + reputation_cost_multipliers = {friend = 1.0, neutral = 3.0}, + max_weapon_refill_amount = {friend = 1.0, neutral = 0.5 }, + goods = { autodoc = {quantity = 5, cost = 76} }, + trade = { food = false, medicine = false, luxury = true }, + public_relations = true, + general_information = "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)", + history = "The station is named after Dr. Lipkin who pioneered some of the research and application around robot assisted surgery in the area of partial nephrectomy for renal tumors in the early 21st century on Earth" + } if stationFaction == "Human Navy" then + stationLipkin.comms_data.goods.food = {quantity = math.random(5,10), cost = 1} if random(1,5) <= 1 then - goods[stationLipkin] = {{"food",math.random(5,10),1},{"medicine",5,5},{"autodoc",5,76}} - else - goods[stationLipkin] = {{"food",math.random(5,10),1},{"autodoc",5,76}} + stationLipkin.comms_data.goods.medicine = {quantity = 5, cost = 5} end else - goods[stationLipkin] = {{"autodoc",5,76}} - tradeFood[stationLipkin] = true + stationLipkin.comms_data.trade.food = true end - tradeLuxury[stationLipkin] = true - stationLipkin.publicRelations = true - 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)" - 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" return stationLipkin end function placeMadison() --Madison stationMadison = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation) stationMadison:setPosition(psx,psy):setCallSign("Madison"):setDescription("Zero gravity sports and entertainment") + stationMadison.comms_data = { + friendlyness = random(0,100), + weapons = {Homing = "neutral", HVLI = "neutral", Mine = "neutral", Nuke = "friend", EMP = "friend"}, + weapon_available = {Homing = random(1,10)<=(8-difficulty), HVLI = random(1,10)<=(9-difficulty), Mine = random(1,10)<=(7-difficulty), Nuke = random(1,10)<=(5-difficulty), EMP = random(1,10)<=(6-difficulty)}, + service_cost = {supplydrop = math.random(80,120), reinforcements = math.random(125,175)}, + reputation_cost_multipliers = {friend = 1.0, neutral = 3.0}, + max_weapon_refill_amount = {friend = 1.0, neutral = 0.5 }, + goods = { luxury = {quantity = 5, cost = 70} }, + trade = { food = false, medicine = false, luxury = false }, + public_relations = true, + general_information = "Come take in a game or two or perhaps see a show", + history = "Named after Madison Square Gardens from 21st century Earth, this station was designed to serve similar purposes in space - a venue for sports and entertainment" + } if stationFaction == "Human Navy" then + stationMadison.comms_data.goods.food = {quantity = math.random(5,10), cost = 1} if random(1,5) <= 1 then - goods[stationMadison] = {{"food",math.random(5,10),1},{"medicine",5,5},{"luxury",5,70}} + stationMadison.comms_data.goods.medicine = {quantity = 5, cost = 5} else - goods[stationMadison] = {{"food",math.random(5,10),1},{"luxury",5,70}} - tradeMedicine[stationMadison] = true + stationMadison.comms_data.trade.medicine = true end else - goods[stationMadison] = {{"luxury",5,70}} - tradeMedicine[stationMadison] = true + stationMadison.comms_data.trade.medicine = true end - stationMadison.publicRelations = true - stationMadison.generalInformation = "Come take in a game or two or perhaps see a show" - 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" return stationMadison end function placeMaiman() --Maiman stationMaiman = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation) stationMaiman:setPosition(psx,psy):setCallSign("Maiman"):setDescription("Energy beam components") + stationMaiman.comms_data = { + friendlyness = random(0,100), + weapons = {Homing = "neutral", HVLI = "neutral", Mine = "neutral", Nuke = "friend", EMP = "friend"}, + weapon_available = {Homing = random(1,10)<=(8-difficulty), HVLI = random(1,10)<=(9-difficulty), Mine = random(1,10)<=(7-difficulty), Nuke = random(1,10)<=(5-difficulty), EMP = random(1,10)<=(6-difficulty)}, + service_cost = {supplydrop = math.random(80,120), reinforcements = math.random(125,175)}, + reputation_cost_multipliers = {friend = 1.0, neutral = 3.0}, + max_weapon_refill_amount = {friend = 1.0, neutral = 0.5 }, + goods = { beam = {quantity = 5, cost = 70} }, + trade = { food = false, medicine = false, luxury = false }, + buy = { [randomMineral()] = math.random(40,200) }, + public_relations = true, + general_information = "We research and manufacture energy beam components and systems", + history = "The station is named after Theodore Maiman who researched and built the first laser in the mid 20th century on Earth" + } if stationFaction == "Human Navy" then + stationMaiman.comms_data.goods.food = {quantity = math.random(5,10), cost = 1} if random(1,5) <= 1 then - goods[stationMaiman] = {{"food",math.random(5,10),1},{"medicine",5,5},{"beam",5,70}} + stationMaiman.comms_data.goods.medicine = {quantity = 5, cost = 5} else - goods[stationMaiman] = {{"food",math.random(5,10),1},{"beam",5,70}} - tradeMedicine[stationMaiman] = true + stationMaiman.comms_data.trade.medicine = true end else - goods[stationMaiman] = {{"beam",5,70}} - tradeMedicine[stationMaiman] = true + stationMaiman.comms_data.trade.medicine = true end - stationMaiman.publicRelations = true - stationMaiman.generalInformation = "We research and manufacture energy beam components and systems" - stationMaiman.stationHistory = "The station is named after Theodore Maiman who researched and built the first laser in the mid 20th centuryon Earth" return stationMaiman end function placeMarconi() --Marconi stationMarconi = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation) stationMarconi:setPosition(psx,psy):setCallSign("Marconi"):setDescription("Energy Beam Components") + stationMarconi.comms_data = { + friendlyness = random(0,100), + weapons = {Homing = "neutral", HVLI = "neutral", Mine = "neutral", Nuke = "friend", EMP = "friend"}, + weapon_available = {Homing = random(1,10)<=(8-difficulty), HVLI = random(1,10)<=(9-difficulty), Mine = random(1,10)<=(7-difficulty), Nuke = random(1,10)<=(5-difficulty), EMP = random(1,10)<=(6-difficulty)}, + service_cost = {supplydrop = math.random(80,120), reinforcements = math.random(125,175)}, + reputation_cost_multipliers = {friend = 1.0, neutral = 3.0}, + max_weapon_refill_amount = {friend = 1.0, neutral = 0.5 }, + goods = { beam = {quantity = 5, cost = 80} }, + trade = { food = false, medicine = false, luxury = true }, + public_relations = true, + general_information = "We manufacture energy beam components", + history = "Station named after Guglielmo Marconi an Italian inventor from early 20th century Earth who, along with Nicolo Tesla, claimed to have invented a death ray or particle beam weapon" + } if stationFaction == "Human Navy" then + stationMarconi.comms_data.goods.food = {quantity = math.random(5,10), cost = 1} if random(1,5) <= 1 then - goods[stationMarconi] = {{"food",math.random(5,10),1},{"medicine",5,5},{"beam",5,80}} + stationMarconi.comms_data.goods.medicine = {quantity = 5, cost = 5} else - goods[stationMarconi] = {{"food",math.random(5,10),1},{"beam",5,80}} - tradeMedicine[stationMarconi] = true + stationMarconi.comms_data.trade.medicine = true end else - goods[stationMarconi] = {{"beam",5,80}} - tradeMedicine[stationMarconi] = true - tradeFood[stationMarconi] = true - end - tradeLuxury[stationMarconi] = true - stationMarconi.publicRelations = true - stationMarconi.generalInformation = "We manufacture energy beam components" - 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" + stationMarconi.comms_data.trade.medicine = true + stationMarconi.comms_data.trade.food = true + end return stationMarconi end function placeMayo() --Mayo stationMayo = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation) stationMayo:setPosition(psx,psy):setCallSign("Mayo"):setDescription("Medical Research") - goods[stationMayo] = {{"food",5,1},{"medicine",5,5},{"autodoc",5,128}} - stationMayo.publicRelations = true - stationMayo.generalInformation = "We research exotic diseases and other human medical conditions" - stationMayo.stationHistory = "We continue the medical work started by William Worrall Mayo in the late 19th century on Earth" + stationMayo.comms_data = { + friendlyness = random(0,100), + weapons = {Homing = "neutral", HVLI = "neutral", Mine = "neutral", Nuke = "friend", EMP = "friend"}, + weapon_available = {Homing = random(1,10)<=(8-difficulty), HVLI = random(1,10)<=(9-difficulty), Mine = random(1,10)<=(7-difficulty), Nuke = random(1,10)<=(5-difficulty), EMP = random(1,10)<=(6-difficulty)}, + service_cost = {supplydrop = math.random(80,120), reinforcements = math.random(125,175)}, + reputation_cost_multipliers = {friend = 1.0, neutral = 3.0}, + max_weapon_refill_amount = {friend = 1.0, neutral = 0.5 }, + goods = { autodoc = {quantity = 5, cost = 128}, + food = {quantity = 5, cost = 1}, + medicine = {quantity = 5, cost = 5} }, + trade = { food = false, medicine = false, luxury = false }, + public_relations = true, + general_information = "We research exotic diseases and other human medical conditions", + history = "We continue the medical work started by William Worrall Mayo in the late 19th century on Earth" + } return stationMayo end function placeMiller() --Miller stationMiller = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation) stationMiller:setPosition(psx,psy):setCallSign("Miller"):setDescription("Exobiology research") + stationMiller.comms_data = { + friendlyness = random(0,100), + weapons = {Homing = "neutral", HVLI = "neutral", Mine = "neutral", Nuke = "friend", EMP = "friend"}, + weapon_available = {Homing = random(1,10)<=(8-difficulty), HVLI = random(1,10)<=(9-difficulty), Mine = random(1,10)<=(7-difficulty), Nuke = random(1,10)<=(5-difficulty), EMP = random(1,10)<=(6-difficulty)}, + service_cost = {supplydrop = math.random(80,120), reinforcements = math.random(125,175)}, + reputation_cost_multipliers = {friend = 1.0, neutral = 3.0}, + max_weapon_refill_amount = {friend = 1.0, neutral = 0.5 }, + goods = { optic = {quantity = 5, cost = 60} }, + trade = { food = false, medicine = false, luxury = false }, + public_relations = true, + general_information = "We study recently discovered life forms not native to Earth", + history = "This station was named after one of the early exobiologists from mid 20th century Earth, Dr. Stanley Miller" + } if stationFaction == "Human Navy" then + stationMiller.comms_data.goods.food = {quantity = math.random(5,10), cost = 1} if random(1,5) <= 1 then - goods[stationMiller] = {{"food",math.random(5,10),1},{"medicine",5,5},{"optic",10,60}} - else - goods[stationMiller] = {{"food",math.random(5,10),1},{"optic",10,60}} + stationMiller.comms_data.goods.medicine = {quantity = 5, cost = 5} end - else - goods[stationMiller] = {{"optic",10,60}} end - stationMiller.publicRelations = true - stationMiller.generalInformation = "We study recently discovered life forms not native to Earth" - stationMiller.stationHistory = "This station was named after one the early exobiologists from mid 20th century Earth, Dr. Stanley Miller" return stationMiller end function placeMuddville() --Muddville stationMudd = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation) stationMudd:setPosition(psx,psy):setCallSign("Muddville"):setDescription("Trading station") + stationMudd.comms_data = { + friendlyness = random(0,100), + weapons = {Homing = "neutral", HVLI = "neutral", Mine = "neutral", Nuke = "friend", EMP = "friend"}, + weapon_available = {Homing = random(1,10)<=(8-difficulty), HVLI = random(1,10)<=(9-difficulty), Mine = random(1,10)<=(7-difficulty), Nuke = random(1,10)<=(5-difficulty), EMP = random(1,10)<=(6-difficulty)}, + service_cost = {supplydrop = math.random(80,120), reinforcements = math.random(125,175)}, + reputation_cost_multipliers = {friend = 1.0, neutral = 3.0}, + max_weapon_refill_amount = {friend = 1.0, neutral = 0.5 }, + goods = { luxury = {quantity = 5, cost = 60} }, + trade = { food = false, medicine = false, luxury = false }, + public_relations = true, + general_information = "Come to Muddvile for all your trade and commerce needs and desires", + history = "Upon retirement, Harry Mudd started this commercial venture using his leftover inventory and extensive connections obtained while he traveled the stars as a salesman" + } if stationFaction == "Human Navy" then + stationMudd.comms_data.goods.food = {quantity = math.random(5,10), cost = 1} if random(1,5) <= 1 then - goods[stationMudd] = {{"food",math.random(5,10),1},{"medicine",5,5},{"luxury",10,60}} - else - goods[stationMudd] = {{"food",math.random(5,10),1},{"luxury",10,60}} + stationMudd.comms_data.goods.medicine = {quantity = 5, cost = 5} end - else - goods[stationMudd] = {{"luxury",10,60}} end - stationMudd.publicRelations = true - stationMudd.generalInformation = "Come to Muddvile for all your trade and commerce needs and desires" - 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" return stationMudd end function placeNexus6() --Nexus-6 stationNexus6 = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation) stationNexus6:setPosition(psx,psy):setCallSign("Nexus-6"):setDescription("Android components") + stationNexus6.comms_data = { + friendlyness = random(0,100), + weapons = {Homing = "neutral", HVLI = "neutral", Mine = "neutral", Nuke = "friend", EMP = "friend"}, + weapon_available = {Homing = random(1,10)<=(8-difficulty), HVLI = random(1,10)<=(9-difficulty), Mine = random(1,10)<=(7-difficulty), Nuke = random(1,10)<=(5-difficulty), EMP = random(1,10)<=(6-difficulty)}, + service_cost = {supplydrop = math.random(80,120), reinforcements = math.random(125,175)}, + reputation_cost_multipliers = {friend = 1.0, neutral = 3.0}, + max_weapon_refill_amount = {friend = 1.0, neutral = 0.5 }, + goods = { android = {quantity = 5, cost = 93} }, + trade = { food = false, medicine = false, luxury = false }, + buy = { [randomMineral()] = math.random(40,200), + [randomComponent("android")] = math.random(40,200) }, + public_relations = true, + general_information = "We research and manufacture android components and systems. Our design our androids to maximize their likeness to humans", + history = "We named the station after the ground breaking android model produced by the Tyrell corporation" + } if stationFaction == "Human Navy" then + stationNexus6.comms_data.goods.food = {quantity = math.random(5,10), cost = 1} if random(1,5) <= 1 then - goods[stationNexus6] = {{"food",math.random(5,10),1},{"medicine",5,5},{"android",5,93}} + stationNexus6.comms_data.goods.medicine = {quantity = 5, cost = 5} else - goods[stationNexus6] = {{"food",math.random(5,10),1},{"android",5,93}} - tradeMedicine[stationNexus6] = true + stationNexus6.comms_data.trade.medicine = true end else - goods[stationNexus6] = {{"android",5,93}} - tradeMedicine[stationNexus6] = true + stationNexus6.comms_data.trade.medicine = true end - stationNexus6.publicRelations = true - stationNexus6.generalInformation = "We research and manufacture android components and systems. Our design our androids to maximize their likeness to humans" - stationNexus6.stationHistory = "The station is named after the ground breaking model of android produced by the Tyrell corporation" return stationNexus6 end function placeOBrien() --O'Brien stationOBrien = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation) stationOBrien:setPosition(psx,psy):setCallSign("O'Brien"):setDescription("Transporter components") + stationOBrien.comms_data = { + friendlyness = random(0,100), + weapons = {Homing = "neutral", HVLI = "neutral", Mine = "neutral", Nuke = "friend", EMP = "friend"}, + weapon_available = {Homing = random(1,10)<=(8-difficulty), HVLI = random(1,10)<=(9-difficulty), Mine = random(1,10)<=(7-difficulty), Nuke = random(1,10)<=(5-difficulty), EMP = random(1,10)<=(6-difficulty)}, + service_cost = {supplydrop = math.random(80,120), reinforcements = math.random(125,175)}, + reputation_cost_multipliers = {friend = 1.0, neutral = 3.0}, + max_weapon_refill_amount = {friend = 1.0, neutral = 0.5 }, + goods = { transporter = {quantity = 5, cost = 76} }, + trade = { food = false, medicine = false, luxury = false }, + public_relations = true, + general_information = "We research and fabricate high quality transporters and transporter components for use aboard ships", + history = "Miles O'Brien started this business after his experience as a transporter chief" + } if stationFaction == "Human Navy" then + stationOBrien.comms_data.goods.food = {quantity = math.random(5,10), cost = 1} if random(1,5) <= 1 then - goods[stationOBrien] = {{"food",math.random(5,10),1},{"medicine",5,5},{"transporter",5,76}} + stationOBrien.comms_data.goods.medicine = {quantity = 5, cost = 5} else - goods[stationOBrien] = {{"food",math.random(5,10),1},{"transporter",5,76}} - if random(1,100) < 34 then tradeMedicine[stationOBrien] = true end + stationOBrien.comms_data.trade.medicine = random(1,100) < 34 end else - goods[stationOBrien] = {{"transporter",5,76}} - tradeMedicine[stationOBrien] = true - if random(1,100) < 13 then tradeFood[stationOBrien] = true end - if random(1,100) < 34 then tradeMedicine[stationOBrien] = true end - end - if random(1,100) < 43 then tradeLuxury[stationOBrien] = true end - stationOBrien.publicRelations = true - stationOBrien.generalInformation = "We research and fabricate high quality transporters and transporter components for use aboard ships" - stationOBrien.stationHistory = "Miles O'Brien started this business after his experience as a transporter chief" + stationOBrien.comms_data.trade.medicine = true + stationOBrien.comms_data.trade.food = random(1,100) < 13 + end + stationOBrien.comms_data.trade.luxury = random(1,100) < 43 return stationOBrien end function placeOlympus() --Olympus stationOlympus = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation) stationOlympus:setPosition(psx,psy):setCallSign("Olympus"):setDescription("Optical components") + stationOlympus.comms_data = { + friendlyness = random(0,100), + weapons = {Homing = "neutral", HVLI = "neutral", Mine = "neutral", Nuke = "friend", EMP = "friend"}, + weapon_available = {Homing = random(1,10)<=(8-difficulty), HVLI = random(1,10)<=(9-difficulty), Mine = random(1,10)<=(7-difficulty), Nuke = random(1,10)<=(5-difficulty), EMP = random(1,10)<=(6-difficulty)}, + service_cost = {supplydrop = math.random(80,120), reinforcements = math.random(125,175)}, + reputation_cost_multipliers = {friend = 1.0, neutral = 3.0}, + max_weapon_refill_amount = {friend = 1.0, neutral = 0.5 }, + goods = { optic = {quantity = 5, cost = 66} }, + trade = { food = false, medicine = false, luxury = false }, + public_relations = true, + general_information = "We fabricate optical lenses and related equipment as well as fiber optic cabling and components", + history = "This station grew out of the Olympus company based on earth in the early 21st century. It merged with Infinera, then bought several software comapnies before branching out into space based industry" + } if stationFaction == "Human Navy" then + stationOlympus.comms_data.goods.food = {quantity = math.random(5,10), cost = 1} if random(1,5) <= 1 then - goods[stationOlympus] = {{"food",math.random(5,10),1},{"medicine",5,5},{"optic",5,66}} + stationOlympus.comms_data.goods.medicine = {quantity = 5, cost = 5} else - goods[stationOlympus] = {{"food",math.random(5,10),1},{"optic",5,66}} - tradeMedicine[stationOlympus] = true + stationOlympus.comms_data.trade.medicine = true end else - goods[stationOlympus] = {{"optic",5,66}} - tradeFood[stationOlympus] = true - tradeMedicine[stationOlympus] = true + stationOlympus.comms_data.trade.medicine = true + stationOlympus.comms_data.trade.food = true end - stationOlympus.publicRelations = true - stationOlympus.generalInformation = "We fabricate optical lenses and related equipment as well as fiber optic cabling and components" - 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" return stationOlympus end function placeOrgana() --Organa stationOrgana = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation) stationOrgana:setPosition(psx,psy):setCallSign("Organa"):setDescription("Diplomatic training") - goods[stationOrgana] = {{"luxury",5,96}} - stationOrgana.publicRelations = true - stationOrgana.generalInformation = "The premeire academy for leadership and diplomacy training in the region" - stationOrgana.stationHistory = "Established by the royal family so critical during the political upheaval era" + stationOrgana.comms_data = { + friendlyness = random(0,100), + weapons = {Homing = "neutral", HVLI = "neutral", Mine = "neutral", Nuke = "friend", EMP = "friend"}, + weapon_available = {Homing = random(1,10)<=(8-difficulty), HVLI = random(1,10)<=(9-difficulty), Mine = random(1,10)<=(7-difficulty), Nuke = random(1,10)<=(5-difficulty), EMP = random(1,10)<=(6-difficulty)}, + service_cost = {supplydrop = math.random(80,120), reinforcements = math.random(125,175)}, + reputation_cost_multipliers = {friend = 1.0, neutral = 3.0}, + max_weapon_refill_amount = {friend = 1.0, neutral = 0.5 }, + goods = { luxury = {quantity = 5, cost = 96} }, + trade = { food = false, medicine = false, luxury = false }, + public_relations = true, + general_information = "The premeire academy for leadership and diplomacy training in the region", + history = "Established by the royal family so critical during the political upheaval era" + } return stationOrgana end function placeOutpost15() --Outpost 15 stationOutpost15 = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation) stationOutpost15:setPosition(psx,psy):setCallSign("Outpost-15"):setDescription("Mining and trade") - tradeFood[stationOutpost15] = true - outpost15Goods = random(1,100) + stationOutpost15.comms_data = { + friendlyness = random(0,100), + weapons = {Homing = "neutral", HVLI = "neutral", Mine = "neutral", Nuke = "friend", EMP = "friend"}, + weapon_available = {Homing = random(1,10)<=(8-difficulty), HVLI = random(1,10)<=(9-difficulty), Mine = random(1,10)<=(7-difficulty), Nuke = random(1,10)<=(5-difficulty), EMP = random(1,10)<=(6-difficulty)}, + service_cost = {supplydrop = math.random(80,120), reinforcements = math.random(125,175)}, + reputation_cost_multipliers = {friend = 1.0, neutral = 3.0}, + max_weapon_refill_amount = {friend = 1.0, neutral = 0.5 }, + goods = { luxury = {quantity = 5, cost = 70} }, + trade = { food = true, medicine = false, luxury = false } + } + local outpost15Goods = random(1,100) + if outpost15Goods < 20 then + stationOutpost15.comms_data.goods.gold = {quantity = 5, cost = math.random(22,30)} + stationOutpost15.comms_data.goods.cobalt = {quantity = 4, cost = math.random(45,55)} + elseif outpost15Goods < 40 then + stationOutpost15.comms_data.goods.gold = {quantity = 5, cost = math.random(22,30)} + elseif outpost15Goods < 60 then + stationOutpost15.comms_data.goods.cobalt = {quantity = 4, cost = math.random(45,55)} + else + stationOutpost15.comms_data.goods.platinum = {quantity = 4, cost = math.random(55,65)} + end if stationFaction == "Human Navy" then + stationOutpost15.comms_data.goods.food = {quantity = math.random(5,10), cost = 1} if random(1,5) <= 1 then - if outpost15Goods < 20 then - goods[stationOutpost15] = {{"luxury",5,70},{"gold",5,25},{"cobalt",4,50},{"food",math.random(5,10),1},{"medicine",5,5}} - elseif outpost15Goods < 40 then - goods[stationOutpost15] = {{"luxury",5,70},{"gold",5,25},{"food",math.random(5,10),1},{"medicine",5,5}} - elseif outpost15Goods < 60 then - goods[stationOutpost15] = {{"luxury",5,70},{"cobalt",4,50},{"food",math.random(5,10),1},{"medicine",5,5}} - else - goods[stationOutpost15] = {{"luxury",5,70},{"food",math.random(5,10),1},{"medicine",5,5}} - end + stationOutpost15.comms_data.goods.medicine = {quantity = 5, cost = 5} else - if outpost15Goods < 20 then - goods[stationOutpost15] = {{"luxury",5,70},{"gold",5,25},{"cobalt",4,50},{"food",math.random(5,10),1}} - elseif outpost15Goods < 40 then - goods[stationOutpost15] = {{"luxury",5,70},{"gold",5,25},{"food",math.random(5,10),1}} - elseif outpost15Goods < 60 then - goods[stationOutpost15] = {{"luxury",5,70},{"cobalt",4,50},{"food",math.random(5,10),1}} - else - goods[stationOutpost15] = {{"luxury",5,70},{"food",math.random(5,10),1}} - end + stationOutpost15.comms_data.trade.medicine = true end else - if outpost15Goods < 20 then - goods[stationOutpost15] = {{"luxury",5,70},{"gold",5,25},{"cobalt",4,50}} - elseif outpost15Goods < 40 then - goods[stationOutpost15] = {{"luxury",5,70},{"gold",5,25}} - elseif outpost15Goods < 60 then - goods[stationOutpost15] = {{"luxury",5,70},{"cobalt",4,50}} - else - goods[stationOutpost15] = {{"luxury",5,70}} - end - tradeFood[stationOutpost15] = true + stationOutpost15.comms_data.trade.food = true end - placeRandomAroundPoint(Asteroid,15,1,15000,psx,psy) + placeRandomAsteroidsAroundPoint(15,1,15000,psx,psy) return stationOutpost15 end function placeOutpost21() --Outpost 21 stationOutpost21 = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation) stationOutpost21:setPosition(psx,psy):setCallSign("Outpost-21"):setDescription("Mining and gambling") - placeRandomAroundPoint(Asteroid,15,1,15000,psx,psy) - outpost21Goods = random(1,100) + stationOutpost21.comms_data = { + friendlyness = random(0,100), + weapons = {Homing = "neutral", HVLI = "neutral", Mine = "neutral", Nuke = "friend", EMP = "friend"}, + weapon_available = {Homing = random(1,10)<=(8-difficulty), HVLI = random(1,10)<=(9-difficulty), Mine = random(1,10)<=(7-difficulty), Nuke = random(1,10)<=(5-difficulty), EMP = random(1,10)<=(6-difficulty)}, + service_cost = {supplydrop = math.random(80,120), reinforcements = math.random(125,175)}, + reputation_cost_multipliers = {friend = 1.0, neutral = 3.0}, + max_weapon_refill_amount = {friend = 1.0, neutral = 0.5 }, + goods = { luxury = {quantity = 5, cost = 70} }, + trade = { food = false, medicine = false, luxury = true } + } + placeRandomAsteroidsAroundPoint(15,1,15000,psx,psy) + local outpost21Goods = random(1,100) + if outpost21Goods < 20 then + stationOutpost21.comms_data.goods.gold = {quantity = 5, cost = math.random(22,30)} + stationOutpost21.comms_data.goods.cobalt = {quantity = 4, cost = math.random(45,55)} + elseif outpost21Goods < 40 then + stationOutpost21.comms_data.goods.gold = {quantity = 5, cost = math.random(22,30)} + elseif outpost21Goods < 60 then + stationOutpost21.comms_data.goods.cobalt = {quantity = 4, cost = math.random(45,55)} + else + stationOutpost21.comms_data.goods.dilithium = {quantity = 4, cost = math.random(45,55)} + end if stationFaction == "Human Navy" then + stationOutpost21.comms_data.goods.food = {quantity = math.random(5,10), cost = 1} if random(1,5) <= 1 then - if outpost21Goods < 20 then - goods[stationOutpost21] = {{"luxury",5,70},{"gold",5,25},{"cobalt",4,50},{"food",math.random(5,10),1},{"medicine",5,5}} - elseif outpost21Goods < 40 then - goods[stationOutpost21] = {{"luxury",5,70},{"gold",5,25},{"food",math.random(5,10),1},{"medicine",5,5}} - elseif outpost21Goods < 60 then - goods[stationOutpost21] = {{"luxury",5,70},{"cobalt",4,50},{"food",math.random(5,10),1},{"medicine",5,5}} - else - goods[stationOutpost21] = {{"luxury",5,70},{"food",math.random(5,10),1},{"medicine",5,5}} - end + stationOutpost21.comms_data.goods.medicine = {quantity = 5, cost = 5} else - if outpost21Goods < 20 then - goods[stationOutpost21] = {{"luxury",5,70},{"gold",5,25},{"cobalt",4,50},{"food",math.random(5,10),1}} - elseif outpost21Goods < 40 then - goods[stationOutpost21] = {{"luxury",5,70},{"gold",5,25},{"food",math.random(5,10),1}} - elseif outpost21Goods < 60 then - goods[stationOutpost21] = {{"luxury",5,70},{"cobalt",4,50},{"food",math.random(5,10),1}} - else - goods[stationOutpost21] = {{"luxury",5,70},{"food",math.random(5,10),1}} - end - if random(1,100) < 50 then tradeMedicine[stationOutpost21] = true end + stationOutpost21.comms_data.trade.medicine = random(1,100) < 50 end else - if outpost21Goods < 20 then - goods[stationOutpost21] = {{"luxury",5,70},{"gold",5,25},{"cobalt",4,50}} - elseif outpost21Goods < 40 then - goods[stationOutpost21] = {{"luxury",5,70},{"gold",5,25}} - elseif outpost21Goods < 60 then - goods[stationOutpost21] = {{"luxury",5,70},{"cobalt",4,50}} - else - goods[stationOutpost21] = {{"luxury",5,70}} - end - tradeFood[stationOutpost21] = true - if random(1,100) < 50 then tradeMedicine[stationOutpost21] = true end + stationOutpost21.comms_data.trade.food = true + stationOutpost21.comms_data.trade.medicine = random(1,100) < 50 end - tradeLuxury[stationOutpost21] = true return stationOutpost21 end function placeOwen() --Owen stationOwen = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation) stationOwen:setPosition(psx,psy):setCallSign("Owen"):setDescription("Load lifters and components") + stationOwen.comms_data = { + friendlyness = random(0,100), + weapons = {Homing = "neutral", HVLI = "neutral", Mine = "neutral", Nuke = "friend", EMP = "friend"}, + weapon_available = {Homing = random(1,10)<=(8-difficulty), HVLI = random(1,10)<=(9-difficulty), Mine = random(1,10)<=(7-difficulty), Nuke = random(1,10)<=(5-difficulty), EMP = random(1,10)<=(6-difficulty)}, + service_cost = {supplydrop = math.random(80,120), reinforcements = math.random(125,175)}, + reputation_cost_multipliers = {friend = 1.0, neutral = 3.0}, + max_weapon_refill_amount = {friend = 1.0, neutral = 0.5 }, + goods = { lifter = {quantity = 5, cost = 61} }, + trade = { food = false, medicine = false, luxury = true }, + public_relations = true, + general_information = "We provide load lifters and components for various ship systems", + history = "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" + } if stationFaction == "Human Navy" then + stationOwen.comms_data.goods.food = {quantity = math.random(5,10), cost = 1} if random(1,5) <= 1 then - goods[stationOwen] = {{"food",math.random(5,10),1},{"medicine",5,5},{"lifter",5,61}} - else - goods[stationOwen] = {{"food",math.random(5,10),1},{"lifter",5,61}} + stationOwen.comms_data.goods.medicine = {quantity = 5, cost = 5} end else - goods[stationOwen] = {{"lifter",5,61}} - tradeFood[stationOwen] = true + stationOwen.comms_data.trade.food = true end - tradeLuxury[stationOwen] = true - stationOwen.publicRelations = true - stationOwen.generalInformation = "We provide load lifters and components for various ship systems" - 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" return stationOwen end function placePanduit() --Panduit stationPanduit = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation) stationPanduit:setPosition(psx,psy):setCallSign("Panduit"):setDescription("Optic components") + stationPanduit.comms_data = { + friendlyness = random(0,100), + weapons = {Homing = "neutral", HVLI = "neutral", Mine = "neutral", Nuke = "friend", EMP = "friend"}, + weapon_available = {Homing = random(1,10)<=(8-difficulty), HVLI = random(1,10)<=(9-difficulty), Mine = random(1,10)<=(7-difficulty), Nuke = random(1,10)<=(5-difficulty), EMP = random(1,10)<=(6-difficulty)}, + service_cost = {supplydrop = math.random(80,120), reinforcements = math.random(125,175)}, + reputation_cost_multipliers = {friend = 1.0, neutral = 3.0}, + max_weapon_refill_amount = {friend = 1.0, neutral = 0.5 }, + goods = { optic = {quantity = 5, cost = 79} }, + trade = { food = false, medicine = false, luxury = true }, + public_relations = true, + general_information = "We provide optic components for various ship systems", + history = "This station is an outgrowth of the Panduit corporation started in the mid 20th century on Earth in the United States" + } if stationFaction == "Human Navy" then + stationPanduit.comms_data.goods.food = {quantity = math.random(5,10), cost = 1} if random(1,5) <= 1 then - goods[stationPanduit] = {{"food",math.random(5,10),1},{"medicine",5,5},{"optic",5,79}} + stationPanduit.comms_data.goods.medicine = {quantity = 5, cost = 5} else - goods[stationPanduit] = {{"food",math.random(5,10),1},{"optic",5,79}} - if random(1,100) < 33 then tradeMedicine[stationPanduit] = true end + stationPanduit.comms_data.trade.medicine = random(1,100) < 33 end else - goods[stationPanduit] = {{"optic",5,79}} - if random(1,100) < 33 then tradeMedicine[stationPanduit] = true end - if random(1,100) < 27 then tradeFood[stationPanduit] = true end - end - tradeLuxury[stationPanduit] = true - stationPanduit.publicRelations = true - stationPanduit.generalInformation = "We provide optic components for various ship systems" - stationPanduit.stationHistory = "This station is an outgrowth of the Panduit corporation started in the mid 20th century on Earth in the United States" + stationPanduit.comms_data.trade.medicine = random(1,100) < 33 + stationPanduit.comms_data.trade.food = random(1,100) < 27 + end return stationPanduit end function placeRipley() --Ripley stationRipley = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation) stationRipley:setPosition(psx,psy):setCallSign("Ripley"):setDescription("Load lifters and components") + stationRipley.comms_data = { + friendlyness = random(0,100), + weapons = {Homing = "neutral", HVLI = "neutral", Mine = "neutral", Nuke = "friend", EMP = "friend"}, + weapon_available = {Homing = random(1,10)<=(8-difficulty), HVLI = random(1,10)<=(9-difficulty), Mine = random(1,10)<=(7-difficulty), Nuke = random(1,10)<=(5-difficulty), EMP = random(1,10)<=(6-difficulty)}, + service_cost = {supplydrop = math.random(80,120), reinforcements = math.random(125,175)}, + reputation_cost_multipliers = {friend = 1.0, neutral = 3.0}, + max_weapon_refill_amount = {friend = 1.0, neutral = 0.5 }, + goods = { lifter = {quantity = 5, cost = 82} }, + trade = { food = false, medicine = false, luxury = random(1,100) < 47 }, + public_relations = true, + general_information = "We provide load lifters and components", + history = "The station is named after Ellen Ripley who made creative and effective use of one of our load lifters when defending her ship" + } if stationFaction == "Human Navy" then + stationRipley.comms_data.goods.food = {quantity = math.random(5,10), cost = 1} if random(1,5) <= 1 then - goods[stationRipley] = {{"food",math.random(5,10),1},{"medicine",5,5},{"lifter",5,82}} + stationRipley.comms_data.goods.medicine = {quantity = 5, cost = 5} else - goods[stationRipley] = {{"food",math.random(5,10),1},{"lifter",5,82}} - tradeMedicine[stationRipley] = true + stationRipley.comms_data.trade.medicine = true end else - goods[stationRipley] = {{"lifter",5,82}} - if random(1,100) < 17 then tradeFood[stationRipley] = true end - tradeMedicine[stationRipley] = true - end - if random(1,100) < 47 then tradeLuxury[stationRipley] = true end - stationRipley.publicRelations = true - stationRipley.generalInformation = "We provide load lifters and components" - 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" + stationRipley.comms_data.trade.food = random(1,100) < 17 + stationRipley.comms_data.trade.medicine = true + end return stationRipley end function placeRutherford() --Rutherford stationRutherford = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation) stationRutherford:setPosition(psx,psy):setCallSign("Rutherford"):setDescription("Shield components and research") + stationRutherford.comms_data = { + friendlyness = random(0,100), + weapons = {Homing = "neutral", HVLI = "neutral", Mine = "neutral", Nuke = "friend", EMP = "friend"}, + weapon_available = {Homing = random(1,10)<=(8-difficulty), HVLI = random(1,10)<=(9-difficulty), Mine = random(1,10)<=(7-difficulty), Nuke = random(1,10)<=(5-difficulty), EMP = random(1,10)<=(6-difficulty)}, + service_cost = {supplydrop = math.random(80,120), reinforcements = math.random(125,175)}, + reputation_cost_multipliers = {friend = 1.0, neutral = 3.0}, + max_weapon_refill_amount = {friend = 1.0, neutral = 0.5 }, + goods = { shield = {quantity = 5, cost = 90} }, + trade = { food = false, medicine = false, luxury = random(1,100) < 43 }, + public_relations = true, + general_information = "We research and fabricate components for ship shield systems", + history = "This station was named after the national research institution Rutherford Appleton Laboratory in the United Kingdom which conducted some preliminary research into the feasability of generating an energy shield in the late 20th century" + } if stationFaction == "Human Navy" then + stationRutherford.comms_data.goods.food = {quantity = math.random(5,10), cost = 1} if random(1,5) <= 1 then - goods[stationRutherford] = {{"food",math.random(5,10),1},{"medicine",5,5},{"shield",5,90}} + stationRutherford.comms_data.goods.medicine = {quantity = 5, cost = 5} else - goods[stationRutherford] = {{"food",math.random(5,10),1},{"shield",5,90}} - tradeMedicine[stationRutherford] = true + stationRutherford.comms_data.trade.medicine = true end else - goods[stationRutherford] = {{"shield",5,90}} - tradeMedicine[stationRutherford] = true - end - tradeMedicine[stationRutherford] = true - if random(1,100) < 43 then tradeLuxury[stationRutherford] = true end - stationRutherford.publicRelations = true - stationRutherford.generalInformation = "We research and fabricate components for ship shield systems" - 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" + stationRutherford.comms_data.trade.food = true + stationRutherford.comms_data.trade.medicine = true + end return stationRutherford end function placeScience7() --Science 7 stationScience7 = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation) stationScience7:setPosition(psx,psy):setCallSign("Science-7"):setDescription("Observatory") - goods[stationScience7] = {{"food",2,1}} + stationScience7.comms_data = { + friendlyness = random(0,100), + weapons = {Homing = "neutral", HVLI = "neutral", Mine = "neutral", Nuke = "friend", EMP = "friend"}, + weapon_available = {Homing = random(1,10)<=(8-difficulty), HVLI = random(1,10)<=(9-difficulty), Mine = random(1,10)<=(7-difficulty), Nuke = random(1,10)<=(5-difficulty), EMP = random(1,10)<=(6-difficulty)}, + service_cost = {supplydrop = math.random(80,120), reinforcements = math.random(125,175)}, + reputation_cost_multipliers = {friend = 1.0, neutral = 3.0}, + max_weapon_refill_amount = {friend = 1.0, neutral = 0.5 }, + goods = { food = {quantity = 2, cost = 1} }, + trade = { food = false, medicine = false, luxury = false } + } return stationScience7 end function placeShawyer() --Shawyer stationShawyer = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation) stationShawyer:setPosition(psx,psy):setCallSign("Shawyer"):setDescription("Impulse engine components") + stationShawyer.comms_data = { + friendlyness = random(0,100), + weapons = {Homing = "neutral", HVLI = "neutral", Mine = "neutral", Nuke = "friend", EMP = "friend"}, + weapon_available = {Homing = random(1,10)<=(8-difficulty), HVLI = random(1,10)<=(9-difficulty), Mine = random(1,10)<=(7-difficulty), Nuke = random(1,10)<=(5-difficulty), EMP = random(1,10)<=(6-difficulty)}, + service_cost = {supplydrop = math.random(80,120), reinforcements = math.random(125,175)}, + reputation_cost_multipliers = {friend = 1.0, neutral = 3.0}, + max_weapon_refill_amount = {friend = 1.0, neutral = 0.5 }, + goods = { impulse = {quantity = 5, cost = 100} }, + trade = { food = false, medicine = false, luxury = true }, + public_relations = true, + general_information = "We research and manufacture impulse engine components and systems", + history = "The station is named after Roger Shawyer who built the first prototype impulse engine in the early 21st century" + } if stationFaction == "Human Navy" then + stationShawyer.comms_data.goods.food = {quantity = math.random(5,10), cost = 1} if random(1,5) <= 1 then - goods[stationShawyer] = {{"food",math.random(5,10),1},{"medicine",5,5},{"impulse",5,100}} + stationShawyer.comms_data.goods.medicine = {quantity = 5, cost = 5} else - goods[stationShawyer] = {{"food",math.random(5,10),1},{"impulse",5,100}} - tradeMedicine[stationShawyer] = true + stationShawyer.comms_data.trade.medicine = true end else - goods[stationShawyer] = {{"impulse",5,100}} - tradeMedicine[stationShawyer] = true + stationShawyer.comms_data.trade.medicine = true end - tradeLuxury[stationShawyer] = true - stationShawyer.publicRelations = true - stationShawyer.generalInformation = "We research and manufacture impulse engine components and systems" - stationShawyer.stationHistory = "The station is named after Roger Shawyer who built the first prototype impulse engine in the early 21st century" return stationShawyer end function placeShree() --Shree stationShree = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation) stationShree:setPosition(psx,psy):setCallSign("Shree"):setDescription("Repulsor and tractor beam components") + stationShree.comms_data = { + friendlyness = random(0,100), + weapons = {Homing = "neutral", HVLI = "neutral", Mine = "neutral", Nuke = "friend", EMP = "friend"}, + weapon_available = {Homing = random(1,10)<=(8-difficulty), HVLI = random(1,10)<=(9-difficulty), Mine = random(1,10)<=(7-difficulty), Nuke = random(1,10)<=(5-difficulty), EMP = random(1,10)<=(6-difficulty)}, + service_cost = {supplydrop = math.random(80,120), reinforcements = math.random(125,175)}, + reputation_cost_multipliers = {friend = 1.0, neutral = 3.0}, + max_weapon_refill_amount = {friend = 1.0, neutral = 0.5 }, + goods = { tractor = {quantity = 5, cost = 90}, + repulsor = {quantity = 5, cost = math.random(85,95)} }, + trade = { food = false, medicine = false, luxury = true }, + public_relations = true, + general_information = "We make ship systems designed to push or pull other objects around in space", + history = "Our station is named Shree after one of many tugboat manufacturers in the early 21st century on Earth in India. Tugboats serve a similar purpose for ocean-going vessels on earth as tractor and repulsor beams serve for space-going vessels today" + } if stationFaction == "Human Navy" then + stationShree.comms_data.goods.food = {quantity = math.random(5,10), cost = 1} if random(1,5) <= 1 then - goods[stationShree] = {{"food",math.random(5,10),1},{"medicine",5,5},{"tractor",5,90},{"repulsor",5,95}} + stationShree.comms_data.goods.medicine = {quantity = 5, cost = 5} else - goods[stationShree] = {{"food",math.random(5,10),1},{"tractor",5,90},{"repulsor",5,95}} - tradeMedicine[stationShree] = true + stationShree.comms_data.trade.medicine = true end else - goods[stationShree] = {{"tractor",5,90},{"repulsor",5,95}} - tradeMedicine[stationShree] = true - tradeFood[stationShree] = true - end - tradeLuxury[stationShree] = true - stationShree.publicRelations = true - stationShree.generalInformation = "We make ship systems designed to push or pull other objects around in space" - 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" + stationShree.comms_data.trade.medicine = true + stationShree.comms_data.trade.food = true + end return stationShree end function placeSoong() --Soong stationSoong = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation) stationSoong:setPosition(psx,psy):setCallSign("Soong"):setDescription("Android components") + stationSoong.comms_data = { + friendlyness = random(0,100), + weapons = {Homing = "neutral", HVLI = "neutral", Mine = "neutral", Nuke = "friend", EMP = "friend"}, + weapon_available = {Homing = random(1,10)<=(8-difficulty), HVLI = random(1,10)<=(9-difficulty), Mine = random(1,10)<=(7-difficulty), Nuke = random(1,10)<=(5-difficulty), EMP = random(1,10)<=(6-difficulty)}, + service_cost = {supplydrop = math.random(80,120), reinforcements = math.random(125,175)}, + reputation_cost_multipliers = {friend = 1.0, neutral = 3.0}, + max_weapon_refill_amount = {friend = 1.0, neutral = 0.5 }, + goods = { android = {quantity = 5, cost = 73} }, + trade = { food = false, medicine = false, luxury = true }, + public_relations = true, + general_information = "We create androids and android components", + history = "The station is named after Dr. Noonian Soong, the famous android researcher and builder" + } if stationFaction == "Human Navy" then + stationSoong.comms_data.goods.food = {quantity = math.random(5,10), cost = 1} if random(1,5) <= 1 then - goods[stationSoong] = {{"food",math.random(5,10),1},{"medicine",5,5},{"android",5,73}} - else - goods[stationSoong] = {{"food",math.random(5,10),1},{"android",5,73}} + stationSoong.comms_data.goods.medicine = {quantity = 5, cost = 5} end else - goods[stationSoong] = {{"android",5,73}} - tradeFood[stationSoong] = true + stationSoong.comms_data.trade.food = true end - tradeLuxury[stationSoong] = true - stationSoong.publicRelations = true - stationSoong.generalInformation = "We create androids and android components" - stationSoong.stationHistory = "The station is named after Dr. Noonian Soong, the famous android researcher and builder" return stationSoong end function placeTiberius() --Tiberius stationTiberius = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation) stationTiberius:setPosition(psx,psy):setCallSign("Tiberius"):setDescription("Logistics coordination") - goods[stationTiberius] = {{"food",5,1}} - stationTiberius.publicRelations = true - stationTiberius.generalInformation = "We support the stations and ships in the area with planning and communication services" - stationTiberius.stationHistory = "We recognize the influence of Starfleet Captain James Tiberius Kirk in the 23rd century in our station name" + stationTiberius.comms_data = { + friendlyness = random(0,100), + weapons = {Homing = "neutral", HVLI = "neutral", Mine = "neutral", Nuke = "friend", EMP = "friend"}, + weapon_available = {Homing = random(1,10)<=(8-difficulty), HVLI = random(1,10)<=(9-difficulty), Mine = random(1,10)<=(7-difficulty), Nuke = random(1,10)<=(5-difficulty), EMP = random(1,10)<=(6-difficulty)}, + service_cost = {supplydrop = math.random(80,120), reinforcements = math.random(125,175)}, + reputation_cost_multipliers = {friend = 1.0, neutral = 3.0}, + max_weapon_refill_amount = {friend = 1.0, neutral = 0.5 }, + goods = { food = {quantity = 5, cost = 1} }, + trade = { food = false, medicine = false, luxury = false }, + public_relations = true, + general_information = "We support the stations and ships in the area with planning and communication services", + history = "We recognize the influence of Starfleet Captain James Tiberius Kirk in the 23rd century in our station name" + } return stationTiberius end function placeTokra() --Tokra stationTokra = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation) stationTokra:setPosition(psx,psy):setCallSign("Tokra"):setDescription("Advanced material components") - whatTrade = random(1,100) + stationTokra.comms_data = { + friendlyness = random(0,100), + weapons = {Homing = "neutral", HVLI = "neutral", Mine = "neutral", Nuke = "friend", EMP = "friend"}, + weapon_available = {Homing = random(1,10)<=(8-difficulty), HVLI = random(1,10)<=(9-difficulty), Mine = random(1,10)<=(7-difficulty), Nuke = random(1,10)<=(5-difficulty), EMP = random(1,10)<=(6-difficulty)}, + service_cost = {supplydrop = math.random(80,120), reinforcements = math.random(125,175)}, + reputation_cost_multipliers = {friend = 1.0, neutral = 3.0}, + max_weapon_refill_amount = {friend = 1.0, neutral = 0.5 }, + goods = { filament = {quantity = 5, cost = 42} }, + trade = { food = false, medicine = false, luxury = false }, + public_relations = true, + general_information = "We create multiple types of advanced material components. Our most popular products are our filaments", + history = "We learned several of our critical industrial processes from the Tokra race, so we honor our fortune by naming the station after them" + } + local whatTrade = random(1,100) if stationFaction == "Human Navy" then + stationTokra.comms_data.goods.food = {quantity = math.random(5,10), cost = 1} if random(1,5) <= 1 then - goods[stationTokra] = {{"food",math.random(5,10),1},{"medicine",5,5},{"filament",5,42}} - tradeLuxury[stationTokra] = true + stationTokra.comms_data.goods.medicine = {quantity = 5, cost = 5} + stationTokra.comms_data.trade.luxury = true else - goods[stationTokra] = {{"food",math.random(5,10),1},{"filament",5,42}} if whatTrade < 50 then - tradeMedicine[stationTokra] = true + stationTokra.comms_data.trade.medicine = true else - tradeLuxury[stationTokra] = true + stationTokra.comms_data.trade.luxury = true end end else - goods[stationTokra] = {{"filament",5,42}} if whatTrade < 33 then - tradeFood[stationTokra] = true + stationTokra.comms_data.trade.food = true elseif whatTrade > 66 then - tradeMedicine[stationTokra] = true + stationTokra.comms_data.trade.medicine = true else - tradeLuxury[stationTokra] = true + stationTokra.comms_data.trade.luxury = true end end - stationTokra.publicRelations = true - stationTokra.generalInformation = "We create multiple types of advanced material components. Our most popular products are our filaments" - 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" return stationTokra end function placeToohie() --Toohie stationToohie = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation) stationToohie:setPosition(psx,psy):setCallSign("Toohie"):setDescription("Shield and armor components and research") + stationToohie.comms_data = { + friendlyness = random(0,100), + weapons = {Homing = "neutral", HVLI = "neutral", Mine = "neutral", Nuke = "friend", EMP = "friend"}, + weapon_available = {Homing = random(1,10)<=(8-difficulty), HVLI = random(1,10)<=(9-difficulty), Mine = random(1,10)<=(7-difficulty), Nuke = random(1,10)<=(5-difficulty), EMP = random(1,10)<=(6-difficulty)}, + service_cost = {supplydrop = math.random(80,120), reinforcements = math.random(125,175)}, + reputation_cost_multipliers = {friend = 1.0, neutral = 3.0}, + max_weapon_refill_amount = {friend = 1.0, neutral = 0.5 }, + goods = { shield = {quantity = 5, cost = 90} }, + trade = { food = false, medicine = false, luxury = true }, + public_relations = true, + general_information = "We research and make general and specialized components for ship shield and ship armor systems", + history = "This station was named after one of the earliest researchers in shield technology, Alexander Toohie back when it was considered impractical to construct shields due to the physics involved." + } if stationFaction == "Human Navy" then + stationToohie.comms_data.goods.food = {quantity = math.random(5,10), cost = 1} if random(1,5) <= 1 then - goods[stationToohie] = {{"food",math.random(5,10),1},{"medicine",5,5},{"shield",5,90}} + stationToohie.comms_data.goods.medicine = {quantity = 5, cost = 5} else - goods[stationToohie] = {{"food",math.random(5,10),1},{"shield",5,90}} - if random(1,100) < 25 then tradeMedicine[stationToohie] = true end + stationToohie.comms_data.trade.medicine = random(1,100) < 25 end else - goods[stationToohie] = {{"shield",5,90}} - if random(1,100) < 25 then tradeMedicine[stationToohie] = true end + stationToohie.comms_data.trade.medicine = random(1,100) < 25 end - tradeLuxury[stationToohie] = true - stationToohie.publicRelations = true - stationToohie.generalInformation = "We research and make general and specialized components for ship shield and ship armor systems" - 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." return stationToohie end function placeUtopiaPlanitia() --Utopia Planitia stationUtopiaPlanitia = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation) stationUtopiaPlanitia:setPosition(psx,psy):setCallSign("Utopia Planitia"):setDescription("Ship building and maintenance facility") + stationUtopiaPlanitia.comms_data = { + friendlyness = random(0,100), + weapons = {Homing = "neutral", HVLI = "neutral", Mine = "neutral", Nuke = "friend", EMP = "friend"}, + weapon_available = {Homing = random(1,10)<=(8-difficulty), HVLI = random(1,10)<=(9-difficulty), Mine = random(1,10)<=(7-difficulty), Nuke = random(1,10)<=(5-difficulty), EMP = random(1,10)<=(6-difficulty)}, + service_cost = {supplydrop = math.random(80,120), reinforcements = math.random(125,175)}, + reputation_cost_multipliers = {friend = 1.0, neutral = 3.0}, + max_weapon_refill_amount = {friend = 1.0, neutral = 0.5 }, + goods = { warp = {quantity = 5, cost = 167} }, + trade = { food = false, medicine = false, luxury = false }, + public_relations = true, + general_information = "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" + } if stationFaction == "Human Navy" then + stationUtopiaPlanitia.comms_data.goods.food = {quantity = math.random(5,10), cost = 1} if random(1,5) <= 1 then - goods[stationUtopiaPlanitia] = {{"food",math.random(5,10),1},{"medicine",5,5},{"warp",5,167}} - else - goods[stationUtopiaPlanitia] = {{"food",math.random(5,10),1},{"warp",5,167}} + stationUtopiaPlanitia.comms_data.goods.medicine = {quantity = 5, cost = 5} end - else - goods[stationUtopiaPlanitia] = {{"warp",5,167}} end - stationUtopiaPlanitia.publicRelations = true - 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" return stationUtopiaPlanitia end function placeVactel() --Vactel stationVactel = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation) stationVactel:setPosition(psx,psy):setCallSign("Vactel"):setDescription("Shielded Circuitry Fabrication") + stationVactel.comms_data = { + friendlyness = random(0,100), + weapons = {Homing = "neutral", HVLI = "neutral", Mine = "neutral", Nuke = "friend", EMP = "friend"}, + weapon_available = {Homing = random(1,10)<=(8-difficulty), HVLI = random(1,10)<=(9-difficulty), Mine = random(1,10)<=(7-difficulty), Nuke = random(1,10)<=(5-difficulty), EMP = random(1,10)<=(6-difficulty)}, + service_cost = {supplydrop = math.random(80,120), reinforcements = math.random(125,175)}, + reputation_cost_multipliers = {friend = 1.0, neutral = 3.0}, + max_weapon_refill_amount = {friend = 1.0, neutral = 0.5 }, + goods = { circuit = {quantity = 5, cost = 50} }, + trade = { food = false, medicine = false, luxury = false }, + public_relations = true, + general_information = "We specialize in circuitry shielded from external hacking suitable for ship systems", + history = "We started as an expansion from the lunar based chip manufacturer of Earth legacy Intel electronic chips" + } if stationFaction == "Human Navy" then + stationVactel.comms_data.goods.food = {quantity = math.random(5,10), cost = 1} if random(1,5) <= 1 then - goods[stationVactel] = {{"food",math.random(5,10),1},{"medicine",5,5},{"circuit",5,50}} - else - goods[stationVactel] = {{"food",math.random(5,10),1},{"circuit",5,50}} + stationVactel.comms_data.goods.medicine = {quantity = 5, cost = 5} end - else - goods[stationVactel] = {{"circuit",5,50}} end - stationVactel.publicRelations = true - stationVactel.generalInformation = "We specialize in circuitry shielded from external hacking suitable for ship systems" - stationVactel.stationHistory = "We started as an expansion from the lunar based chip manufacturer of Earth legacy Intel electronic chips" return stationVactel end function placeVeloquan() --Veloquan stationVeloquan = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation) stationVeloquan:setPosition(psx,psy):setCallSign("Veloquan"):setDescription("Sensor components") + stationVeloquan.comms_data = { + friendlyness = random(0,100), + weapons = {Homing = "neutral", HVLI = "neutral", Mine = "neutral", Nuke = "friend", EMP = "friend"}, + weapon_available = {Homing = random(1,10)<=(8-difficulty), HVLI = random(1,10)<=(9-difficulty), Mine = random(1,10)<=(7-difficulty), Nuke = random(1,10)<=(5-difficulty), EMP = random(1,10)<=(6-difficulty)}, + service_cost = {supplydrop = math.random(80,120), reinforcements = math.random(125,175)}, + reputation_cost_multipliers = {friend = 1.0, neutral = 3.0}, + max_weapon_refill_amount = {friend = 1.0, neutral = 0.5 }, + goods = { sensor = {quantity = 5, cost = 68} }, + trade = { food = false, medicine = false, luxury = false }, + public_relations = true, + general_information = "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", + history = "The Veloquan company has its roots in the manufacturing of LIDAR sensors in the early 21st century on Earth in the United States for autonomous ground-based vehicles. They expanded research and manufacturing operations to include various sensors for space vehicles. Veloquan was the result of numerous mergers and acquisitions of several companies including Velodyne and Quanergy" + } if stationFaction == "Human Navy" then + stationVeloquan.comms_data.goods.food = {quantity = math.random(5,10), cost = 1} if random(1,5) <= 1 then - goods[stationVeloquan] = {{"food",math.random(5,10),1},{"medicine",5,5},{"sensor",5,68}} + stationVeloquan.comms_data.goods.medicine = {quantity = 5, cost = 5} else - goods[stationVeloquan] = {{"food",math.random(5,10),1},{"sensor",5,68}} - tradeMedicine[stationVeloquan] = true + stationVeloquan.comms_data.trade.medicine = true end else - goods[stationVeloquan] = {{"sensor",5,68}} - tradeMedicine[stationVeloquan] = true - tradeFood[stationVeloquan] = true + stationVeloquan.comms_data.trade.medicine = true + stationVeloquan.comms_data.trade.food = true end - stationVeloquan.publicRelations = true - 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" - 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" return stationVeloquan end function placeZefram() --Zefram stationZefram = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation) stationZefram:setPosition(psx,psy):setCallSign("Zefram"):setDescription("Warp engine components") + stationZefram.comms_data = { + friendlyness = random(0,100), + weapons = {Homing = "neutral", HVLI = "neutral", Mine = "neutral", Nuke = "friend", EMP = "friend"}, + weapon_available = {Homing = random(1,10)<=(8-difficulty), HVLI = random(1,10)<=(9-difficulty), Mine = random(1,10)<=(7-difficulty), Nuke = random(1,10)<=(5-difficulty), EMP = random(1,10)<=(6-difficulty)}, + service_cost = {supplydrop = math.random(80,120), reinforcements = math.random(125,175)}, + reputation_cost_multipliers = {friend = 1.0, neutral = 3.0}, + max_weapon_refill_amount = {friend = 1.0, neutral = 0.5 }, + goods = { warp = {quantity = 5, cost = 140} }, + trade = { food = false, medicine = false, luxury = true }, + public_relations = true, + general_information = "We specialize in the esoteric components necessary to make warp drives function properly", + history = "Zefram Cochrane constructed the first warp drive in human history. We named our station after him because of the specialized warp systems work we do" + } if stationFaction == "Human Navy" then + stationZefram.comms_data.goods.food = {quantity = math.random(5,10), cost = 1} if random(1,5) <= 1 then - goods[stationZefram] = {{"food",math.random(5,10),1},{"medicine",5,5},{"warp",5,140}} + stationZefram.comms_data.goods.medicine = {quantity = 5, cost = 5} else - goods[stationZefram] = {{"food",math.random(5,10),1},{"warp",5,140}} - if random(1,100) < 27 then tradeMedicine[stationZefram] = true end + stationZefram.comms_data.trade.medicine = random(1,100) < 27 end else - goods[stationZefram] = {{"warp",5,140}} - if random(1,100) < 27 then tradeMedicine[stationZefram] = true end - if random(1,100) < 16 then tradeFood[stationZefram] = true end - end - tradeLuxury[stationZefram] = true - stationZefram.publicRelations = true - stationZefram.generalInformation = "We specialize in the esoteric components necessary to make warp drives function properly" - 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" + stationZefram.comms_data.trade.medicine = random(1,100) < 27 + stationZefram.comms_data.trade.food = random(1,100) < 16 + end return stationZefram end ---[[------------------------------------------------------------------- - Generic stations to be placed ---]]------------------------------------------------------------------- +-- Generic stations to be placed function placeJabba() --Jabba stationJabba = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation) stationJabba:setPosition(psx,psy):setCallSign("Jabba"):setDescription("Commerce and gambling") - stationJabba.publicRelations = true - stationJabba.generalInformation = "Come play some games and shop. House take does not exceed 4 percent" + stationJabba.comms_data = { + friendlyness = random(0,100), + weapons = {Homing = "neutral", HVLI = "neutral", Mine = "neutral", Nuke = "friend", EMP = "friend"}, + weapon_available = {Homing = random(1,10)<=(8-difficulty), HVLI = random(1,10)<=(9-difficulty), Mine = random(1,10)<=(7-difficulty), Nuke = random(1,10)<=(5-difficulty), EMP = random(1,10)<=(6-difficulty)}, + service_cost = {supplydrop = math.random(80,120), reinforcements = math.random(125,175)}, + reputation_cost_multipliers = {friend = 1.0, neutral = 3.0}, + max_weapon_refill_amount = {friend = 1.0, neutral = 0.5 }, + goods = {}, + trade = { food = false, medicine = false, luxury = false }, + public_relations = true, + general_information = "Come play some games and shop. House take does not exceed 4 percent" + } + local stationGoodChoice = math.random(1,3) + if stationGoodChoice == 1 then + stationJabba.comms_data.goods.luxury = {quantity = 5, cost = math.random(68,81)} + elseif stationGoodChoice == 2 then + stationJabba.comms_data.goods.gold = {quantity = 5, cost = math.random(61,77)} + else + stationJabba.comms_data.goods.platinum = {quantity = 5, cost = math.random(65,79)} + end return stationJabba end function placeKrik() --Krik stationKrik = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation) stationKrik:setPosition(psx,psy):setCallSign("Krik"):setDescription("Mining station") - posAxisKrik = random(0,360) - posKrik = random(30000,80000) - negKrik = random(20000,60000) - spreadKrik = random(5000,8000) - negAxisKrik = posAxisKrik + 180 - xPosAngleKrik, yPosAngleKrik = vectorFromAngle(posAxisKrik, posKrik) - posKrikEnd = random(40,90) - createRandomAlongArc(Asteroid, 30+posKrikEnd, psx+xPosAngleKrik, psy+yPosAngleKrik, posKrik, negAxisKrik, negAxisKrik+posKrikEnd, spreadKrik) - xNegAngleKrik, yNegAngleKrik = vectorFromAngle(negAxisKrik, negKrik) - negKrikEnd = random(30,60) - createRandomAlongArc(Asteroid, 30+negKrikEnd, psx+xNegAngleKrik, psy+yNegAngleKrik, negKrik, posAxisKrik, posAxisKrik+negKrikEnd, spreadKrik) - tradeFood[stationKrik] = true - if random(1,100) < 50 then tradeLuxury[stationKrik] = true end - tradeMedicine[stationKrik] = true - krikGoods = random(1,100) + stationKrik.comms_data = { + friendlyness = random(0,100), + weapons = {Homing = "neutral", HVLI = "neutral", Mine = "neutral", Nuke = "friend", EMP = "friend"}, + weapon_available = {Homing = random(1,10)<=(8-difficulty), HVLI = random(1,10)<=(9-difficulty), Mine = random(1,10)<=(7-difficulty), Nuke = random(1,10)<=(5-difficulty), EMP = random(1,10)<=(6-difficulty)}, + service_cost = {supplydrop = math.random(80,120), reinforcements = math.random(125,175)}, + reputation_cost_multipliers = {friend = 1.0, neutral = 3.0}, + max_weapon_refill_amount = {friend = 1.0, neutral = 0.5 }, + goods = { nickel = {quantity = 5, cost = 20} }, + trade = { food = true, medicine = true, luxury = random(1,100) < 50 } + } + local posAxisKrik = random(0,360) + local posKrik = random(30000,80000) + local negKrik = random(20000,60000) + local spreadKrik = random(5000,8000) + local negAxisKrik = posAxisKrik + 180 + local xPosAngleKrik, yPosAngleKrik = vectorFromAngle(posAxisKrik, posKrik) + local posKrikEnd = random(40,90) + createRandomAsteroidAlongArc(30+posKrikEnd, psx+xPosAngleKrik, psy+yPosAngleKrik, posKrik, negAxisKrik, negAxisKrik+posKrikEnd, spreadKrik) + local xNegAngleKrik, yNegAngleKrik = vectorFromAngle(negAxisKrik, negKrik) + local negKrikEnd = random(30,60) + createRandomAsteroidAlongArc(30+negKrikEnd, psx+xNegAngleKrik, psy+yNegAngleKrik, negKrik, posAxisKrik, posAxisKrik+negKrikEnd, spreadKrik) + local krikGoods = random(1,100) if krikGoods < 10 then - goods[stationKrik] = {{"nickel",5,20},{"platinum",5,70},{"tritanium",5,50},{"dilithium",5,50}} + stationKrik.comms_data.goods.platinum = {quantity = 5, cost = math.random(65,75)} + stationKrik.comms_data.goods.tritanium = {quantity = 5, cost = math.random(45,55)} + stationKrik.comms_data.goods.dilithium = {quantity = 5, cost = math.random(45,55)} elseif krikGoods < 20 then - goods[stationKrik] = {{"nickel",5,20},{"platinum",5,70},{"tritanium",5,50}} + stationKrik.comms_data.goods.platinum = {quantity = 5, cost = math.random(65,75)} + stationKrik.comms_data.goods.tritanium = {quantity = 5, cost = math.random(45,55)} elseif krikGoods < 30 then - goods[stationKrik] = {{"nickel",5,20},{"platinum",5,70},{"dilithium",5,50}} + stationKrik.comms_data.goods.platinum = {quantity = 5, cost = math.random(65,75)} + stationKrik.comms_data.goods.dilithium = {quantity = 5, cost = math.random(45,55)} elseif krikGoods < 40 then - goods[stationKrik] = {{"nickel",5,20},{"tritanium",5,50},{"dilithium",5,50}} + stationKrik.comms_data.goods.tritanium = {quantity = 5, cost = math.random(45,55)} + stationKrik.comms_data.goods.dilithium = {quantity = 5, cost = math.random(45,55)} elseif krikGoods < 50 then - goods[stationKrik] = {{"nickel",5,20},{"dilithium",5,50}} + stationKrik.comms_data.goods.dilithium = {quantity = 5, cost = math.random(45,55)} elseif krikGoods < 60 then - goods[stationKrik] = {{"nickel",5,20},{"platinum",5,70}} + stationKrik.comms_data.goods.platinum = {quantity = 5, cost = math.random(65,75)} elseif krikGoods < 70 then - goods[stationKrik] = {{"nickel",5,20},{"tritanium",5,50}} + stationKrik.comms_data.goods.tritanium = {quantity = 5, cost = math.random(45,55)} elseif krikGoods < 80 then - goods[stationKrik] = {{"platinum",5,70},{"tritanium",5,50},{"dilithium",5,50}} + stationKrik.comms_data.goods.cobalt = {quantity = 5, cost = math.random(55,65)} else - goods[stationKrik] = {{"nickel",5,20}} + stationKrik.comms_data.goods.cobalt = {quantity = 5, cost = math.random(55,65)} + stationKrik.comms_data.goods.dilithium = {quantity = 5, cost = math.random(45,55)} end return stationKrik end @@ -2280,135 +2789,417 @@ function placeLando() --Lando stationLando = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation) stationLando:setPosition(psx,psy):setCallSign("Lando"):setDescription("Casino and Gambling") + stationLando.comms_data = { + friendlyness = random(0,100), + weapons = {Homing = "neutral", HVLI = "neutral", Mine = "neutral", Nuke = "friend", EMP = "friend"}, + weapon_available = {Homing = random(1,10)<=(8-difficulty), HVLI = random(1,10)<=(9-difficulty), Mine = random(1,10)<=(7-difficulty), Nuke = random(1,10)<=(5-difficulty), EMP = random(1,10)<=(6-difficulty)}, + service_cost = {supplydrop = math.random(80,120), reinforcements = math.random(125,175)}, + reputation_cost_multipliers = {friend = 1.0, neutral = 3.0}, + max_weapon_refill_amount = {friend = 1.0, neutral = 0.5 }, + goods = { shield = {quantity = 5, cost = 90} }, + trade = { food = false, medicine = false, luxury = false } + } + local stationGoodChoice = math.random(1,3) + if stationGoodChoice == 1 then + stationLando.comms_data.goods.luxury = {quantity = 5, cost = math.random(68,81)} + elseif stationGoodChoice == 2 then + stationLando.comms_data.goods.gold = {quantity = 5, cost = math.random(61,77)} + else + stationLando.comms_data.goods.platinum = {quantity = 5, cost = math.random(65,79)} + end return stationLando end function placeMaverick() --Maverick stationMaverick = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation) stationMaverick:setPosition(psx,psy):setCallSign("Maverick"):setDescription("Gambling and resupply") - stationMaverick.publicRelations = true - stationMaverick.generalInformation = "Relax and meet some interesting players" + stationMaverick.comms_data = { + friendlyness = random(0,100), + weapons = {Homing = "neutral", HVLI = "neutral", Mine = "neutral", Nuke = "friend", EMP = "friend"}, + weapon_available = {Homing = random(1,10)<=(8-difficulty), HVLI = random(1,10)<=(9-difficulty), Mine = random(1,10)<=(7-difficulty), Nuke = random(1,10)<=(5-difficulty), EMP = random(1,10)<=(6-difficulty)}, + service_cost = {supplydrop = math.random(80,120), reinforcements = math.random(125,175)}, + reputation_cost_multipliers = {friend = 1.0, neutral = 3.0}, + max_weapon_refill_amount = {friend = 1.0, neutral = 0.5 }, + goods = {}, + trade = { food = false, medicine = false, luxury = false }, + public_relations = true, + general_information = "Relax and meet some interesting players" + } + local stationGoodChoice = math.random(1,3) + if stationGoodChoice == 1 then + stationMaverick.comms_data.goods.luxury = {quantity = 5, cost = math.random(68,81)} + elseif stationGoodChoice == 2 then + stationMaverick.comms_data.goods.gold = {quantity = 5, cost = math.random(61,77)} + else + stationMaverick.comms_data.goods.platinum = {quantity = 5, cost = math.random(65,79)} + end return stationMaverick end function placeNefatha() --Nefatha stationNefatha = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation) stationNefatha:setPosition(psx,psy):setCallSign("Nefatha"):setDescription("Commerce and recreation") - goods[stationNefatha] = {{"luxury",5,70}} + stationNefatha.comms_data = { + friendlyness = random(0,100), + weapons = {Homing = "neutral", HVLI = "neutral", Mine = "neutral", Nuke = "friend", EMP = "friend"}, + weapon_available = {Homing = random(1,10)<=(8-difficulty), HVLI = random(1,10)<=(9-difficulty), Mine = random(1,10)<=(7-difficulty), Nuke = random(1,10)<=(5-difficulty), EMP = random(1,10)<=(6-difficulty)}, + service_cost = {supplydrop = math.random(80,120), reinforcements = math.random(125,175)}, + reputation_cost_multipliers = {friend = 1.0, neutral = 3.0}, + max_weapon_refill_amount = {friend = 1.0, neutral = 0.5 }, + goods = { luxury = {quantity = 5, cost = 70} }, + trade = { food = false, medicine = false, luxury = false } + } return stationNefatha end function placeOkun() --Okun stationOkun = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation) stationOkun:setPosition(psx,psy):setCallSign("Okun"):setDescription("Xenopsychology research") + stationOkun.comms_data = { + friendlyness = random(0,100), + weapons = {Homing = "neutral", HVLI = "neutral", Mine = "neutral", Nuke = "friend", EMP = "friend"}, + weapon_available = {Homing = random(1,10)<=(8-difficulty), HVLI = random(1,10)<=(9-difficulty), Mine = random(1,10)<=(7-difficulty), Nuke = random(1,10)<=(5-difficulty), EMP = random(1,10)<=(6-difficulty)}, + service_cost = {supplydrop = math.random(80,120), reinforcements = math.random(125,175)}, + reputation_cost_multipliers = {friend = 1.0, neutral = 3.0}, + max_weapon_refill_amount = {friend = 1.0, neutral = 0.5 }, + goods = {}, + trade = { food = false, medicine = false, luxury = false }, + public_relations = false + } + local stationGoodChoice = math.random(1,3) + if stationGoodChoice == 1 then + stationOkun.comms_data.goods.optic = {quantity = 5, cost = math.random(52,65)} + elseif stationGoodChoice == 2 then + stationOkun.comms_data.goods.filament = {quantity = 5, cost = math.random(55,67)} + else + stationOkun.comms_data.goods.lifter = {quantity = 5, cost = math.random(48,69)} + end return stationOkun end function placeOutpost7() --Outpost 7 stationOutpost7 = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation) stationOutpost7:setPosition(psx,psy):setCallSign("Outpost-7"):setDescription("Resupply") - goods[stationOutpost7] = {{"luxury",5,80}} + stationOutpost7.comms_data = { + friendlyness = random(0,100), + weapons = {Homing = "neutral", HVLI = "neutral", Mine = "neutral", Nuke = "friend", EMP = "friend"}, + weapon_available = {Homing = random(1,10)<=(8-difficulty), HVLI = random(1,10)<=(9-difficulty), Mine = random(1,10)<=(7-difficulty), Nuke = random(1,10)<=(5-difficulty), EMP = random(1,10)<=(6-difficulty)}, + service_cost = {supplydrop = math.random(80,120), reinforcements = math.random(125,175)}, + reputation_cost_multipliers = {friend = 1.0, neutral = 3.0}, + max_weapon_refill_amount = {friend = 1.0, neutral = 0.5 }, + goods = { luxury = {quantity = 5, cost = 80} }, + trade = { food = false, medicine = false, luxury = false } + } return stationOutpost7 end function placeOutpost8() --Outpost 8 stationOutpost8 = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation) stationOutpost8:setPosition(psx,psy):setCallSign("Outpost-8") + stationOutpost8.comms_data = { + friendlyness = random(0,100), + weapons = {Homing = "neutral", HVLI = "neutral", Mine = "neutral", Nuke = "friend", EMP = "friend"}, + weapon_available = {Homing = random(1,10)<=(8-difficulty), HVLI = random(1,10)<=(9-difficulty), Mine = random(1,10)<=(7-difficulty), Nuke = random(1,10)<=(5-difficulty), EMP = random(1,10)<=(6-difficulty)}, + service_cost = {supplydrop = math.random(80,120), reinforcements = math.random(125,175)}, + reputation_cost_multipliers = {friend = 1.0, neutral = 3.0}, + max_weapon_refill_amount = {friend = 1.0, neutral = 0.5 }, + goods = {}, + trade = { food = false, medicine = false, luxury = false } + } + local stationGoodChoice = math.random(1,3) + if stationGoodChoice == 1 then + stationOutpost8.comms_data.goods.impulse = {quantity = 5, cost = math.random(69,75)} + elseif stationGoodChoice == 2 then + stationOutpost8.comms_data.goods.tractor = {quantity = 5, cost = math.random(55,67)} + else + stationOutpost8.comms_data.goods.beam = {quantity = 5, cost = math.random(61,69)} + end return stationOutpost8 end function placeOutpost33() --Outpost 33 stationOutpost33 = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation) stationOutpost33:setPosition(psx,psy):setCallSign("Outpost-33"):setDescription("Resupply") - goods[stationOutpost33] = {{"luxury",5,75}} + stationOutpost33.comms_data = { + friendlyness = random(0,100), + weapons = {Homing = "neutral", HVLI = "neutral", Mine = "neutral", Nuke = "friend", EMP = "friend"}, + weapon_available = {Homing = random(1,10)<=(8-difficulty), HVLI = random(1,10)<=(9-difficulty), Mine = random(1,10)<=(7-difficulty), Nuke = random(1,10)<=(5-difficulty), EMP = random(1,10)<=(6-difficulty)}, + service_cost = {supplydrop = math.random(80,120), reinforcements = math.random(125,175)}, + reputation_cost_multipliers = {friend = 1.0, neutral = 3.0}, + max_weapon_refill_amount = {friend = 1.0, neutral = 0.5 }, + goods = { luxury = {quantity = 5, cost = 75} }, + trade = { food = false, medicine = false, luxury = false } + } return stationOutpost33 end function placePrada() --Prada stationPrada = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation) stationPrada:setPosition(psx,psy):setCallSign("Prada"):setDescription("Textiles and fashion") + stationPrada.comms_data = { + friendlyness = random(0,100), + weapons = {Homing = "neutral", HVLI = "neutral", Mine = "neutral", Nuke = "friend", EMP = "friend"}, + weapon_available = {Homing = random(1,10)<=(8-difficulty), HVLI = random(1,10)<=(9-difficulty), Mine = random(1,10)<=(7-difficulty), Nuke = random(1,10)<=(5-difficulty), EMP = random(1,10)<=(6-difficulty)}, + service_cost = {supplydrop = math.random(80,120), reinforcements = math.random(125,175)}, + reputation_cost_multipliers = {friend = 1.0, neutral = 3.0}, + max_weapon_refill_amount = {friend = 1.0, neutral = 0.5 }, + goods = {}, + trade = { food = false, medicine = false, luxury = false } + } + local stationGoodChoice = math.random(1,3) + if stationGoodChoice == 1 then + stationPrada.comms_data.goods.luxury = {quantity = 5, cost = math.random(69,75)} + elseif stationGoodChoice == 2 then + stationPrada.comms_data.goods.cobalt = {quantity = 5, cost = math.random(55,67)} + else + stationPrada.comms_data.goods.dilithium = {quantity = 5, cost = math.random(61,69)} + end return stationPrada end function placeResearch11() --Research-11 stationResearch11 = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation) stationResearch11:setPosition(psx,psy):setCallSign("Research-11"):setDescription("Stress Psychology Research") + stationResearch11.comms_data = { + friendlyness = random(0,100), + weapons = {Homing = "neutral", HVLI = "neutral", Mine = "neutral", Nuke = "friend", EMP = "friend"}, + weapon_available = {Homing = random(1,10)<=(8-difficulty), HVLI = random(1,10)<=(9-difficulty), Mine = random(1,10)<=(7-difficulty), Nuke = random(1,10)<=(5-difficulty), EMP = random(1,10)<=(6-difficulty)}, + service_cost = {supplydrop = math.random(80,120), reinforcements = math.random(125,175)}, + reputation_cost_multipliers = {friend = 1.0, neutral = 3.0}, + max_weapon_refill_amount = {friend = 1.0, neutral = 0.5 }, + goods = {}, + trade = { food = false, medicine = false, luxury = false } + } + local stationGoodChoice = math.random(1,3) + if stationGoodChoice == 1 then + stationResearch11.comms_data.goods.warp = {quantity = 5, cost = math.random(85,120)} + elseif stationGoodChoice == 2 then + stationResearch11.comms_data.goods.repulsor = {quantity = 5, cost = math.random(62,75)} + else + stationResearch11.comms_data.goods.robotic = {quantity = 5, cost = math.random(75,89)} + end return stationResearch11 end function placeResearch19() --Research-19 stationResearch19 = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation) stationResearch19:setPosition(psx,psy):setCallSign("Research-19"):setDescription("Low gravity research") + stationResearch19.comms_data = { + friendlyness = random(0,100), + weapons = {Homing = "neutral", HVLI = "neutral", Mine = "neutral", Nuke = "friend", EMP = "friend"}, + weapon_available = {Homing = random(1,10)<=(8-difficulty), HVLI = random(1,10)<=(9-difficulty), Mine = random(1,10)<=(7-difficulty), Nuke = random(1,10)<=(5-difficulty), EMP = random(1,10)<=(6-difficulty)}, + service_cost = {supplydrop = math.random(80,120), reinforcements = math.random(125,175)}, + reputation_cost_multipliers = {friend = 1.0, neutral = 3.0}, + max_weapon_refill_amount = {friend = 1.0, neutral = 0.5 }, + goods = {}, + trade = { food = false, medicine = false, luxury = false } + } + local stationGoodChoice = math.random(1,3) + if stationGoodChoice == 1 then + stationResearch19.comms_data.goods.transporter = {quantity = 5, cost = math.random(85,94)} + elseif stationGoodChoice == 2 then + stationResearch19.comms_data.goods.sensor = {quantity = 5, cost = math.random(62,75)} + else + stationResearch19.comms_data.goods.communication = {quantity = 5, cost = math.random(55,89)} + end return stationResearch19 end function placeRubis() --Rubis stationRubis = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation) stationRubis:setPosition(psx,psy):setCallSign("Rubis"):setDescription("Resupply") - goods[stationRubis] = {{"luxury",5,76}} - stationRubis.publicRelations = true - stationRubis.generalInformation = "Get your energy here! Grab a drink before you go!" + stationRubis.comms_data = { + friendlyness = random(0,100), + weapons = {Homing = "neutral", HVLI = "neutral", Mine = "neutral", Nuke = "friend", EMP = "friend"}, + weapon_available = {Homing = random(1,10)<=(8-difficulty), HVLI = random(1,10)<=(9-difficulty), Mine = random(1,10)<=(7-difficulty), Nuke = random(1,10)<=(5-difficulty), EMP = random(1,10)<=(6-difficulty)}, + service_cost = {supplydrop = math.random(80,120), reinforcements = math.random(125,175)}, + reputation_cost_multipliers = {friend = 1.0, neutral = 3.0}, + max_weapon_refill_amount = {friend = 1.0, neutral = 0.5 }, + goods = { luxury = {quantity = 5, cost = 76} }, + trade = { food = false, medicine = false, luxury = false }, + public_relations = true, + general_information = "Get your energy here! Grab a drink before you go!" + } return stationRubis end function placeScience2() --Science 2 stationScience2 = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation) stationScience2:setPosition(psx,psy):setCallSign("Science-2"):setDescription("Research Lab and Observatory") + stationScience2.comms_data = { + friendlyness = random(0,100), + weapons = {Homing = "neutral", HVLI = "neutral", Mine = "neutral", Nuke = "friend", EMP = "friend"}, + weapon_available = {Homing = random(1,10)<=(8-difficulty), HVLI = random(1,10)<=(9-difficulty), Mine = random(1,10)<=(7-difficulty), Nuke = random(1,10)<=(5-difficulty), EMP = random(1,10)<=(6-difficulty)}, + service_cost = {supplydrop = math.random(80,120), reinforcements = math.random(125,175)}, + reputation_cost_multipliers = {friend = 1.0, neutral = 3.0}, + max_weapon_refill_amount = {friend = 1.0, neutral = 0.5 }, + goods = {}, + trade = { food = false, medicine = false, luxury = false } + } + local stationGoodChoice = math.random(1,3) + if stationGoodChoice == 1 then + stationScience2.comms_data.goods.autodoc = {quantity = 5, cost = math.random(85,94)} + elseif stationGoodChoice == 2 then + stationScience2.comms_data.goods.android = {quantity = 5, cost = math.random(62,75)} + else + stationScience2.comms_data.goods.nanites = {quantity = 5, cost = math.random(55,89)} + end return stationScience2 end function placeScience4() --Science 4 stationScience4 = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation) stationScience4:setPosition(psx,psy):setCallSign("Science-4"):setDescription("Biotech research") + stationScience4.comms_data = { + friendlyness = random(0,100), + weapons = {Homing = "neutral", HVLI = "neutral", Mine = "neutral", Nuke = "friend", EMP = "friend"}, + weapon_available = {Homing = random(1,10)<=(8-difficulty), HVLI = random(1,10)<=(9-difficulty), Mine = random(1,10)<=(7-difficulty), Nuke = random(1,10)<=(5-difficulty), EMP = random(1,10)<=(6-difficulty)}, + service_cost = {supplydrop = math.random(80,120), reinforcements = math.random(125,175)}, + reputation_cost_multipliers = {friend = 1.0, neutral = 3.0}, + max_weapon_refill_amount = {friend = 1.0, neutral = 0.5 }, + goods = {}, + trade = { food = false, medicine = false, luxury = false } + } + local stationGoodChoice = math.random(1,3) + if stationGoodChoice == 1 then + stationScience4.comms_data.goods.software = {quantity = 5, cost = math.random(85,94)} + elseif stationGoodChoice == 2 then + stationScience4.comms_data.goods.circuit = {quantity = 5, cost = math.random(62,75)} + else + stationScience4.comms_data.goods.battery = {quantity = 5, cost = math.random(55,89)} + end return stationScience4 end function placeSkandar() --Skandar stationSkandar = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation) stationSkandar:setPosition(psx,psy):setCallSign("Skandar"):setDescription("Routine maintenance and entertainment") - goods[stationSkandar] = {{"luxury",5,87}} - stationSkandar.publicRelations = true - stationSkandar.generalInformation = "Stop by for repairs. Take in one of our juggling shows featuring the four-armed Skandars" - 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" + stationSkandar.comms_data = { + friendlyness = random(0,100), + weapons = {Homing = "neutral", HVLI = "neutral", Mine = "neutral", Nuke = "friend", EMP = "friend"}, + weapon_available = {Homing = random(1,10)<=(8-difficulty), HVLI = random(1,10)<=(9-difficulty), Mine = random(1,10)<=(7-difficulty), Nuke = random(1,10)<=(5-difficulty), EMP = random(1,10)<=(6-difficulty)}, + service_cost = {supplydrop = math.random(80,120), reinforcements = math.random(125,175)}, + reputation_cost_multipliers = {friend = 1.0, neutral = 3.0}, + max_weapon_refill_amount = {friend = 1.0, neutral = 0.5 }, + goods = { luxury = {quantity = 5, cost = 87} }, + trade = { food = false, medicine = false, luxury = false }, + public_relations = true, + general_information = "Stop by for repairs. Take in one of our juggling shows featuring the four-armed Skandars", + history = "The nomadic Skandars have set up at this station to practice their entertainment and maintenance skills as well as build a community where Skandars can relax" + } return stationSkandar end function placeSpot() --Spot stationSpot = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation) stationSpot:setPosition(psx,psy):setCallSign("Spot"):setDescription("Observatory") + stationSpot.comms_data = { + friendlyness = random(0,100), + weapons = {Homing = "neutral", HVLI = "neutral", Mine = "neutral", Nuke = "friend", EMP = "friend"}, + weapon_available = {Homing = random(1,10)<=(8-difficulty), HVLI = random(1,10)<=(9-difficulty), Mine = random(1,10)<=(7-difficulty), Nuke = random(1,10)<=(5-difficulty), EMP = random(1,10)<=(6-difficulty)}, + service_cost = {supplydrop = math.random(80,120), reinforcements = math.random(125,175)}, + reputation_cost_multipliers = {friend = 1.0, neutral = 3.0}, + max_weapon_refill_amount = {friend = 1.0, neutral = 0.5 }, + goods = {}, + trade = { food = false, medicine = false, luxury = false } + } + local stationGoodChoice = math.random(1,3) + if stationGoodChoice == 1 then + stationSpot.comms_data.goods.optic = {quantity = 5, cost = math.random(85,94)} + elseif stationGoodChoice == 2 then + stationSpot.comms_data.goods.software = {quantity = 5, cost = math.random(62,75)} + else + stationSpot.comms_data.goods.sensor = {quantity = 5, cost = math.random(55,89)} + end return stationSpot end function placeStarnet() --Starnet stationStarnet = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation) stationStarnet:setPosition(psx,psy):setCallSign("Starnet"):setDescription("Automated weapons systems") - stationStarnet.publicRelations = true - stationStarnet.generalInformation = "We research and create automated weapons systems to improve ship combat capability" + stationStarnet.comms_data = { + friendlyness = random(0,100), + weapons = {Homing = "neutral", HVLI = "neutral", Mine = "neutral", Nuke = "friend", EMP = "friend"}, + weapon_available = {Homing = random(1,10)<=(8-difficulty), HVLI = random(1,10)<=(9-difficulty), Mine = random(1,10)<=(7-difficulty), Nuke = random(1,10)<=(5-difficulty), EMP = random(1,10)<=(6-difficulty)}, + service_cost = {supplydrop = math.random(80,120), reinforcements = math.random(125,175)}, + reputation_cost_multipliers = {friend = 1.0, neutral = 3.0}, + max_weapon_refill_amount = {friend = 1.0, neutral = 0.5 }, + goods = {}, + trade = { food = false, medicine = false, luxury = false }, + public_relations = true, + general_information = "We research and create automated weapons systems to improve ship combat capability" + } + local stationGoodChoice = math.random(1,3) + if stationGoodChoice == 1 then + stationStarnet.comms_data.goods.shield = {quantity = 5, cost = math.random(85,94)} + elseif stationGoodChoice == 2 then + stationStarnet.comms_data.goods.beam = {quantity = 5, cost = math.random(62,75)} + else + stationStarnet.comms_data.goods.lifter = {quantity = 5, cost = math.random(55,89)} + end return stationStarnet end function placeTandon() --Tandon stationTandon = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation) stationTandon:setPosition(psx,psy):setCallSign("Tandon"):setDescription("Biotechnology research") + stationTandon.comms_data = { + friendlyness = random(0,100), + weapons = {Homing = "neutral", HVLI = "neutral", Mine = "neutral", Nuke = "friend", EMP = "friend"}, + weapon_available = {Homing = random(1,10)<=(8-difficulty), HVLI = random(1,10)<=(9-difficulty), Mine = random(1,10)<=(7-difficulty), Nuke = random(1,10)<=(5-difficulty), EMP = random(1,10)<=(6-difficulty)}, + service_cost = {supplydrop = math.random(80,120), reinforcements = math.random(125,175)}, + reputation_cost_multipliers = {friend = 1.0, neutral = 3.0}, + max_weapon_refill_amount = {friend = 1.0, neutral = 0.5 }, + goods = {}, + trade = { food = false, medicine = false, luxury = false }, + public_relations = true, + general_information = "Merging the organic and inorganic through research", + history = "Continued from the Tandon school of engineering started on Earth in the early 21st century" + } + local stationGoodChoice = math.random(1,3) + if stationGoodChoice == 1 then + stationTandon.comms_data.goods.autodoc = {quantity = 5, cost = math.random(85,94)} + elseif stationGoodChoice == 2 then + stationTandon.comms_data.goods.robotic = {quantity = 5, cost = math.random(62,75)} + else + stationTandon.comms_data.goods.android = {quantity = 5, cost = math.random(55,89)} + end return stationTandon end function placeVaiken() --Vaiken stationVaiken = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation) stationVaiken:setPosition(psx,psy):setCallSign("Vaiken"):setDescription("Ship building and maintenance facility") - goods[stationVaiken] = {{"food",10,1},{"medicine",5,5}} + stationVaiken.comms_data = { + friendlyness = random(0,100), + weapons = {Homing = "neutral", HVLI = "neutral", Mine = "neutral", Nuke = "friend", EMP = "friend"}, + weapon_available = {Homing = random(1,10)<=(8-difficulty), HVLI = random(1,10)<=(9-difficulty), Mine = random(1,10)<=(7-difficulty), Nuke = random(1,10)<=(5-difficulty), EMP = random(1,10)<=(6-difficulty)}, + service_cost = {supplydrop = math.random(80,120), reinforcements = math.random(125,175)}, + reputation_cost_multipliers = {friend = 1.0, neutral = 3.0}, + max_weapon_refill_amount = {friend = 1.0, neutral = 0.5 }, + goods = { food = {quantity = 10, cost = 1}, + medicine = {quantity = 5, cost = 5} }, + trade = { food = false, medicine = false, luxury = false } + } return stationVaiken end function placeValero() --Valero stationValero = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCommsScript(""):setCommsFunction(commsStation) stationValero:setPosition(psx,psy):setCallSign("Valero"):setDescription("Resupply") - goods[stationValero] = {{"luxury",5,77}} + stationValero.comms_data = { + friendlyness = random(0,100), + weapons = {Homing = "neutral", HVLI = "neutral", Mine = "neutral", Nuke = "friend", EMP = "friend"}, + weapon_available = {Homing = random(1,10)<=(8-difficulty), HVLI = random(1,10)<=(9-difficulty), Mine = random(1,10)<=(7-difficulty), Nuke = random(1,10)<=(5-difficulty), EMP = random(1,10)<=(6-difficulty)}, + service_cost = {supplydrop = math.random(80,120), reinforcements = math.random(125,175)}, + reputation_cost_multipliers = {friend = 1.0, neutral = 3.0}, + max_weapon_refill_amount = {friend = 1.0, neutral = 0.5 }, + goods = { luxury = {quantity = 5, cost = 90} }, + trade = { food = false, medicine = false, luxury = false } + } return stationValero end ---[[------------------------------------------------------------------- - Enemy stations to be placed ---]]------------------------------------------------------------------- +-- Enemy stations to be placed function placeAramanth() --Aramanth stationAramanth = SpaceStation():setTemplate(szt()):setFaction(stationFaction):setCallSign("Aramanth"):setPosition(psx,psy) @@ -2473,9 +3264,9 @@ function placeTic() stationTic:setPosition(psx,psy):setCallSign("Ticonderoga") return stationTic end ---[[----------------------------------------------------------------- - Station communication ------------------------------------------------------------------]]-- +----------------------------- +-- Station communication -- +----------------------------- function commsStation() if comms_target.comms_data == nil then comms_target.comms_data = {} @@ -2514,14 +3305,14 @@ function commsStation() } }) comms_data = comms_target.comms_data - if player:isEnemy(comms_target) then + if comms_source:isEnemy(comms_target) then return false end if comms_target:areEnemiesInRange(5000) then setCommsMessage("We are under attack! No time for chatting!"); return true end - if not player:isDocked(comms_target) then + if not comms_source:isDocked(comms_target) then handleUndockedState() else handleDockedState() @@ -2529,6 +3320,7 @@ function commsStation() return true end function handleDockedState() + local ctd = comms_target.comms_data if player:isFriendly(comms_target) then oMsg = "Good day, officer!\nWhat can we do for you today?\n" else @@ -2539,54 +3331,39 @@ function handleDockedState() end setCommsMessage(oMsg) missilePresence = 0 + local missile_types = {'Homing', 'Nuke', 'Mine', 'EMP', 'HVLI'} for _, missile_type in ipairs(missile_types) do missilePresence = missilePresence + player:getWeaponStorageMax(missile_type) end if missilePresence > 0 then - if comms_target.nukeAvail == nil then - if math.random(1,10) <= (4 - difficulty) then - comms_target.nukeAvail = true - else - comms_target.nukeAvail = false - end - if math.random(1,10) <= (5 - difficulty) then - comms_target.empAvail = true - else - comms_target.empAvail = false - end - if math.random(1,10) <= (6 - difficulty) then - comms_target.homeAvail = true - else - comms_target.homeAvail = false - end - if math.random(1,10) <= (7 - difficulty) then - comms_target.mineAvail = true - else - comms_target.mineAvail = false - end - if math.random(1,10) <= (9 - difficulty) then - comms_target.hvliAvail = true - else - comms_target.hvliAvail = false - end - end - if comms_target.nukeAvail or comms_target.empAvail or comms_target.homeAvail or comms_target.mineAvail or comms_target.hvliAvail then + if (ctd.weapon_available.Nuke and comms_source:getWeaponStorageMax("Nuke") > 0) or + (ctd.weapon_available.EMP and comms_source:getWeaponStorageMax("EMP") > 0) or + (ctd.weapon_available.Homing and comms_source:getWeaponStorageMax("Homing") > 0) or + (ctd.weapon_available.Mine and comms_source:getWeaponStorageMax("Mine") > 0) or + (ctd.weapon_available.HVLI and comms_source:getWeaponStorageMax("HVLI") > 0) then addCommsReply("I need ordnance restocked", function() + local ctd = comms_target.comms_data + if stationCommsDiagnostic then print("in restock function") end setCommsMessage("What type of ordnance?") - if player:getWeaponStorageMax("Nuke") > 0 then - if comms_target.nukeAvail then + if stationCommsDiagnostic then print(string.format("player nuke weapon storage max: %.1f",comms_source:getWeaponStorageMax("Nuke"))) end + if comms_source:getWeaponStorageMax("Nuke") > 0 then + if stationCommsDiagnostic then print("player can fire nukes") end + if ctd.weapon_available.Nuke then + if stationCommsDiagnostic then print("station has nukes available") end if math.random(1,10) <= 5 then nukePrompt = "Can you supply us with some nukes? (" else nukePrompt = "We really need some nukes (" end + if stationCommsDiagnostic then print("nuke prompt: " .. nukePrompt) end addCommsReply(nukePrompt .. getWeaponCost("Nuke") .. " rep each)", function() + if stationCommsDiagnostic then print("going to handle weapon restock function") end handleWeaponRestock("Nuke") end) - end - end - if player:getWeaponStorageMax("EMP") > 0 then - if comms_target.empAvail then + end --end station has nuke available if branch + end --end player can accept nuke if branch + if comms_source:getWeaponStorageMax("EMP") > 0 then + if ctd.weapon_available.EMP then if math.random(1,10) <= 5 then empPrompt = "Please re-stock our EMP missiles. (" else @@ -2595,10 +3372,10 @@ function handleDockedState() addCommsReply(empPrompt .. getWeaponCost("EMP") .. " rep each)", function() handleWeaponRestock("EMP") end) - end - end - if player:getWeaponStorageMax("Homing") > 0 then - if comms_target.homeAvail then + end --end station has EMP available if branch + end --end player can accept EMP if branch + if comms_source:getWeaponStorageMax("Homing") > 0 then + if ctd.weapon_available.Homing then if math.random(1,10) <= 5 then homePrompt = "Do you have spare homing missiles for us? (" else @@ -2607,10 +3384,10 @@ function handleDockedState() addCommsReply(homePrompt .. getWeaponCost("Homing") .. " rep each)", function() handleWeaponRestock("Homing") end) - end - end - if player:getWeaponStorageMax("Mine") > 0 then - if comms_target.mineAvail then + end --end station has homing for player if branch + end --end player can accept homing if branch + if comms_source:getWeaponStorageMax("Mine") > 0 then + if ctd.weapon_available.Mine then if math.random(1,10) <= 5 then minePrompt = "We could use some mines. (" else @@ -2619,10 +3396,10 @@ function handleDockedState() addCommsReply(minePrompt .. getWeaponCost("Mine") .. " rep each)", function() handleWeaponRestock("Mine") end) - end - end - if player:getWeaponStorageMax("HVLI") > 0 then - if comms_target.hvliAvail then + end --end station has mine for player if branch + end --end player can accept mine if branch + if comms_source:getWeaponStorageMax("HVLI") > 0 then + if ctd.weapon_available.HVLI then if math.random(1,10) <= 5 then hvliPrompt = "What about HVLI? (" else @@ -2631,11 +3408,11 @@ function handleDockedState() addCommsReply(hvliPrompt .. getWeaponCost("HVLI") .. " rep each)", function() handleWeaponRestock("HVLI") end) - end - end - end) - end - end + end --end station has HVLI for player if branch + end --end player can accept HVLI if branch + end) --end player requests secondary ordnance comms reply branch + end --end secondary ordnance available from station if branch + end --end missles used on player ship if branch if comms_target == beamFixStation then if playerRepulse.beamFix == nil then addCommsReply("Talk to Kent's brother", function() @@ -2690,30 +3467,32 @@ function handleDockedState() if impulseFixStation.good_base == nil then repeat candidate = stationList[math.random(1,#stationList)] - if candidate ~= nil and candidate:isValid() and #goods[candidate] > 0 then - gi = 1 - repeat - impulseFixStation.impulse_good = goods[candidate][gi][1] - gi = gi + 1 - until(gi > #goods[candidate]) + if candidate ~= nil and candidate:isValid() then + local good_count = 0 + for good, good_data in pairs(candidate.comms_data.goods) do + good_count = good_count + 1 + end + if good_count > 0 then + for good, good_data in pairs(candidate.comms_data.goods) do + impulseFixStation.impulse_good = good + end + end end if impulseFixStation.impulse_good ~= "food" and impulseFixStation.impulse_good ~= "medicine" then impulseFixStation.good_base = candidate end until(impulseFixStation.good_base ~= nil) end - gi = 1 local impulse_good_quantity = 0 - repeat - if goods[player][gi][1] == impulseFixStation.impulse_good then - impulse_good_quantity = goods[player][gi][2] - end - gi = gi + 1 - until(gi > #goods[player]) + if comms_source.goods ~= nil and comms_source.goods[impulseFixStation.impulse_good] ~= nil and comms_source.goods[impulseFixStation.impulse_good] > 0 then + impulse_good_quantity = comms_source.goods[impulseFixStation.impulse_good] + end if impulse_good_quantity > 0 then setCommsMessage(string.format("Piece of cake. Thanks for the %s",impulseFixStation.impulse_good)) playerRepulse.maxImpulse = 1 playerRepulse.impulseFix = "done" + comms_source.goods[impulseFixStation.impulse_good] = comms_source.goods[impulseFixStation.impulse_good] - 1 + comms_source.cargo = comms_source.cargo + 1 addCommsReply("Thank you", function() setCommsMessage("Sure. Mom, I'll see you at Christmas") playerRepulse:addReputationPoints(30) @@ -2747,29 +3526,29 @@ function handleDockedState() if jumpFixStation.good_base == nil then repeat candidate = stationList[math.random(1,#stationList)] - if candidate ~= nil and candidate:isValid() and #goods[candidate] > 0 then - gi = 1 - repeat - jumpFixStation.jump_good = goods[candidate][gi][1] - gi = gi + 1 - until(gi > #goods[candidate]) + if candidate ~= nil and candidate:isValid() then + local good_count = 0 + for good, good_data in pairs(candidate.comms_data.goods) do + good_count = good_count + 1 + end + if good_count > 0 then + for good, good_data in pairs(candidate.comms_data.goods) do + jumpFixStation.jump_good = good + end + end end if jumpFixStation.jump_good ~= "food" and jumpFixStation.jump_good ~= "medicine" then jumpFixStation.good_base = candidate end until(jumpFixStation.good_base ~= nil) end - gi = 1 local jump_good_quantity = 0 - repeat - if goods[player][gi][1] == jumpFixStation.jump_good then - jump_good_quantity = goods[player][gi][2] - end - gi = gi + 1 - until(gi > #goods[player]) + if comms_source.goods ~= nil and comms_source.goods[jumpFixStation.jump_good] ~= nil and comms_source.goods[jumpFixStation.jump_good] > 0 then + jump_good_quantity = comms_source.goods[jumpFixStation.jump_good] + end if jump_good_quantity > 0 then setCommsMessage(string.format("That should not be hard to do. I could probably do that in my sleep. Thanks for bringing %s",jumpFixStation.jump_good)) - decrementPlayerGoods(jumpFixStation.jump_good) + comms_source.goods[jumpFixStation.jump_good] = comms_source.goods[jumpFixStation.jump_good] - 1 player.cargo = player.cargo + 1 playerRepulse.maxJump = 1 playerRepulse.jumpFix = "done" @@ -2892,35 +3671,28 @@ function handleDockedState() addCommsReply("Repair front shield", function() setCommsMessage("Your front shields are now fully operational. Your repair crew can finish the rest") playerRepulse.maxFrontShield = 1 - --print("fixed front shield") playerRepulse.frontShieldFix = "done" - --print("set front shield fixed indicator") addCommsReply("Thanks", function() - --print("past front thanks") if shieldGoodBase == nil then - --print("setting shield good base") repeat - --print("top of shield good base set loop") candidate = stationList[math.random(1,#stationList)] - --print(string.format("candidate: %s",candidate:getCallSign())) - if candidate ~= nil and candidate:isValid() and #goods[candidate] > 0 then - --print("candidate passed first checks") --testing got to this point - gi = 1 - repeat - shieldGood = goods[candidate][gi][1] - gi = gi + 1 - until(gi > #goods[candidate]) - --print(string.format("Checked goods. Ended on shield good: %s",shieldGood)) --testing did not get here - if shieldGood ~= "food" and shieldGood ~= "medicine" then - shieldGoodBase = candidate - --print(string.format("Decided on station %s",shieldGoodBase:getCallSign())) + if candidate ~= nil and candidate:isValid() then + local good_count = 0 + for good, good_data in pairs(candidate.comms_data.goods) do + good_count = good_count + 1 end + if good_count > 0 then + for good, good_data in pairs(candidate.comms_data.goods) do + shieldGood = good + end + end + end + if shieldGood ~= "food" and shieldGood ~= "medicine" then + shieldGoodBase = candidate end until(shieldGoodBase ~= nil) - --print("out of shield good base loop") end setCommsMessage(string.format("Certainly. Bring back %s to get the rear shield fixed. You might find some at %s",shieldGood,shieldGoodBase:getCallSign())) - --print("set response message") playerRepulse:addReputationPoints(30) addCommsReply("Back", commsStation) end) @@ -2934,16 +3706,20 @@ function handleDockedState() if shieldGoodBase == nil then repeat candidate = stationList[math.random(1,#stationList)] - if candidate ~= nil and candidate:isValid() and #goods[candidate] > 0 then - gi = 1 - repeat - shieldGood = goods[candidate][gi][1] - gi = gi + 1 - until(gi > #goods[candidate]) - if shieldGood ~= "food" and shieldGood ~= "medicine" then - shieldGoodBase = candidate + if candidate ~= nil and candidate:isValid() then + local good_count = 0 + for good, good_data in pairs(candidate.comms_data.goods) do + good_count = good_count + 1 + end + if good_count > 0 then + for good, good_data in pairs(candidate.comms_data.goods) do + shieldGood = good + end end end + if shieldGood ~= "food" and shieldGood ~= "medicine" then + shieldGoodBase = candidate + end until(shieldGoodBase ~= nil) end setCommsMessage(string.format("Certainly. Bring back %s to get the front shield fixed. You might find some at %s",shieldGood,shieldGoodBase:getCallSign())) @@ -2959,17 +3735,13 @@ function handleDockedState() elseif playerRepulse.frontShieldFix == nil or playerRepulse.rearShieldFix == nil then addCommsReply("Talk to Amir's sister", function() setCommsMessage(string.format("Welcome back. Did you bring some %s for me to finish fixing up your shields?",shieldGood)) - gi = 1 - shieldGoodQuantity = 0 - repeat - if goods[player][gi][1] == shieldGood then - shieldGoodQuantity = goods[player][gi][2] - end - gi = gi + 1 - until(gi > #goods[player]) + local shieldGoodQuantity = 0 + if comms_source.goods ~= nil and comms_source.goods[shieldGood] ~= nil and comms_source.goods[shieldGood] > 0 then + shieldGoodQuantity = comms_source.goods[shieldGood] + end if shieldGoodQuantity > 0 then addCommsReply(string.format("Yes, please take the %s and fix the shields",shieldGood), function() - decrementPlayerGoods(shieldGood) + comms_source.goods[shieldGood] = comms_source.goods[shieldGood] - 1 player.cargo = player.cargo + 1 if playerRepulse.frontShieldFix == nil then playerRepulse.maxFrontShield = 1 @@ -2993,217 +3765,203 @@ function handleDockedState() end) end end - if comms_target.publicRelations then + if ctd.public_relations then addCommsReply("Tell me more about your station", function() setCommsMessage("What would you like to know?") addCommsReply("General information", function() - setCommsMessage(comms_target.generalInformation) + setCommsMessage(ctd.general_information) addCommsReply("Back", commsStation) end) - if comms_target.stationHistory ~= nil then + if ctd.history ~= nil then addCommsReply("Station history", function() - setCommsMessage(comms_target.stationHistory) + setCommsMessage(ctd.history) addCommsReply("Back", commsStation) end) end - if player:isFriendly(comms_target) then - if comms_target.gossip ~= nil then - if random(1,100) < 50 then + if comms_source:isFriendly(comms_target) then + if ctd.gossip ~= nil then + if random(1,100) < (100 - (30 * (difficulty - .5))) then addCommsReply("Gossip", function() - setCommsMessage(comms_target.gossip) + setCommsMessage(ctd.gossip) addCommsReply("Back", commsStation) end) end end end - end) + end) --end station info comms reply branch + end --end public relations if branch + local goodCount = 0 + for good, goodData in pairs(ctd.goods) do + goodCount = goodCount + 1 end - if goods[comms_target] ~= nil then + if goodCount > 0 then addCommsReply("Buy, sell, trade", function() - oMsg = string.format("Station %s:\nGoods or components available: quantity, cost in reputation\n",comms_target:getCallSign()) - gi = 1 -- initialize goods index - repeat - goodsType = goods[comms_target][gi][1] - goodsQuantity = goods[comms_target][gi][2] - goodsRep = goods[comms_target][gi][3] - oMsg = oMsg .. string.format(" %s: %i, %i\n",goodsType,goodsQuantity,goodsRep) - gi = gi + 1 - until(gi > #goods[comms_target]) - oMsg = oMsg .. "Current Cargo:\n" - gi = 1 - cargoHoldEmpty = true - repeat - playerGoodsType = goods[player][gi][1] - playerGoodsQuantity = goods[player][gi][2] - if playerGoodsQuantity > 0 then - oMsg = oMsg .. string.format(" %s: %i\n",playerGoodsType,playerGoodsQuantity) - cargoHoldEmpty = false + local ctd = comms_target.comms_data + local goodsReport = string.format("Station %s:\nGoods or components available for sale: quantity, cost in reputation\n",comms_target:getCallSign()) + for good, goodData in pairs(ctd.goods) do + goodsReport = goodsReport .. string.format(" %s: %i, %i\n",good,goodData["quantity"],goodData["cost"]) + end + if ctd.buy ~= nil then + goodsReport = goodsReport .. "Goods or components station will buy: price in reputation\n" + for good, price in pairs(ctd.buy) do + goodsReport = goodsReport .. string.format(" %s: %i\n",good,price) end - gi = gi + 1 - until(gi > #goods[player]) - if cargoHoldEmpty then - oMsg = oMsg .. " Empty\n" end - playerRep = math.floor(player:getReputationPoints()) - oMsg = oMsg .. string.format("Available Space: %i, Available Reputation: %i\n",player.cargo,playerRep) - setCommsMessage(oMsg) - -- Buttons for reputation purchases - gi = 1 - repeat - local goodsType = goods[comms_target][gi][1] - local goodsQuantity = goods[comms_target][gi][2] - local goodsRep = goods[comms_target][gi][3] - addCommsReply(string.format("Buy one %s for %i reputation",goods[comms_target][gi][1],goods[comms_target][gi][3]), function() - oMsg = string.format("Type: %s, Quantity: %i, Rep: %i",goodsType,goodsQuantity,goodsRep) - if player.cargo < 1 then - oMsg = oMsg .. "\nInsufficient cargo space for purchase" - elseif goodsRep > playerRep then - oMsg = oMsg .. "\nInsufficient reputation for purchase" - elseif goodsQuantity < 1 then - oMsg = oMsg .. "\nInsufficient station inventory" + goodsReport = goodsReport .. string.format("Current cargo aboard %s:\n",comms_source:getCallSign()) + local cargoHoldEmpty = true + local player_good_count = 0 + if comms_source.goods ~= nil then + for good, goodQuantity in pairs(comms_source.goods) do + player_good_count = player_good_count + 1 + goodsReport = goodsReport .. string.format(" %s: %i\n",good,goodQuantity) + end + end + if player_good_count < 1 then + goodsReport = goodsReport .. " Empty\n" + end + goodsReport = goodsReport .. string.format("Available Space: %i, Available Reputation: %i\n",comms_source.cargo,math.floor(comms_source:getReputationPoints())) + setCommsMessage(goodsReport) + for good, goodData in pairs(ctd.goods) do + addCommsReply(string.format("Buy one %s for %i reputation",good,goodData["cost"]), function() + local goodTransactionMessage = string.format("Type: %s, Quantity: %i, Rep: %i",good,goodData["quantity"],goodData["cost"]) + if comms_source.cargo < 1 then + goodTransactionMessage = goodTransactionMessage .. "\nInsufficient cargo space for purchase" + elseif goodData["cost"] > math.floor(comms_source:getReputationPoints()) then + goodTransactionMessage = goodTransactionMessage .. "\nInsufficient reputation for purchase" + elseif goodData["quantity"] < 1 then + goodTransactionMessage = goodTransactionMessage .. "\nInsufficient station inventory" else - if not player:takeReputationPoints(goodsRep) then - oMsg = oMsg .. "\nInsufficient reputation for purchase" + if comms_source:takeReputationPoints(goodData["cost"]) then + comms_source.cargo = comms_source.cargo - 1 + goodData["quantity"] = goodData["quantity"] - 1 + if comms_source.goods == nil then + comms_source.goods = {} + end + if comms_source.goods[good] == nil then + comms_source.goods[good] = 0 + end + comms_source.goods[good] = comms_source.goods[good] + 1 + goodTransactionMessage = goodTransactionMessage .. "\npurchased" else - player.cargo = player.cargo - 1 - decrementStationGoods(goodsType) - incrementPlayerGoods(goodsType) - oMsg = oMsg .. "\npurchased" + goodTransactionMessage = goodTransactionMessage .. "\nInsufficient reputation for purchase" end end - setCommsMessage(oMsg) + setCommsMessage(goodTransactionMessage) addCommsReply("Back", commsStation) end) - gi = gi + 1 - until(gi > #goods[comms_target]) - -- Buttons for food trades - if tradeFood[comms_target] ~= nil then - gi = 1 - foodQuantity = 0 - repeat - if goods[player][gi][1] == "food" then - foodQuantity = goods[player][gi][2] - end - gi = gi + 1 - until(gi > #goods[player]) - if foodQuantity > 0 then - gi = 1 - repeat - local goodsType = goods[comms_target][gi][1] - local goodsQuantity = goods[comms_target][gi][2] - addCommsReply(string.format("Trade food for %s",goods[comms_target][gi][1]), function() - oMsg = string.format("Type: %s, Quantity: %i",goodsType,goodsQuantity) - if goodsQuantity < 1 then - oMsg = oMsg .. "\nInsufficient station inventory" - else - decrementStationGoods(goodsType) - incrementPlayerGoods(goodsType) - decrementPlayerGoods("food") - oMsg = oMsg .. "\nTraded" - end - setCommsMessage(oMsg) + end + if ctd.buy ~= nil then + for good, price in pairs(ctd.buy) do + if comms_source.goods[good] ~= nil and comms_source.goods[good] > 0 then + addCommsReply(string.format("Sell one %s for %i reputation",good,price), function() + local goodTransactionMessage = string.format("Type: %s, Reputation price: %i",good,price) + comms_source.goods[good] = comms_source.goods[good] - 1 + comms_source:addReputationPoints(price) + goodTransactionMessage = goodTransactionMessage .. "\nOne sold" + comms_source.cargo = comms_source.cargo + 1 + setCommsMessage(goodTransactionMessage) addCommsReply("Back", commsStation) end) - gi = gi + 1 - until(gi > #goods[comms_target]) + end end end - -- Buttons for luxury trades - if tradeLuxury[comms_target] ~= nil then - gi = 1 - luxuryQuantity = 0 - repeat - if goods[player][gi][1] == "luxury" then - luxuryQuantity = goods[player][gi][2] - end - gi = gi + 1 - until(gi > #goods[player]) - if luxuryQuantity > 0 then - gi = 1 - repeat - local goodsType = goods[comms_target][gi][1] - local goodsQuantity = goods[comms_target][gi][2] - addCommsReply(string.format("Trade luxury for %s",goods[comms_target][gi][1]), function() - oMsg = string.format("Type: %s, Quantity: %i",goodsType,goodsQuantity) - if goodsQuantity < 1 then - oMsg = oMsg .. "\nInsufficient station inventory" - else - decrementStationGoods(goodsType) - incrementPlayerGoods(goodsType) - decrementPlayerGoods("luxury") - oMsg = oMsg .. "\nTraded" + if ctd.trade.food and comms_source.goods ~= nil and comms_source.goods.food ~= nil and comms_source.goods.food.quantity > 0 then + for good, goodData in pairs(ctd.goods) do + addCommsReply(string.format("Trade food for %s",good), function() + local goodTransactionMessage = string.format("Type: %s, Quantity: %i",good,goodData["quantity"]) + if goodData["quantity"] < 1 then + goodTransactionMessage = goodTransactionMessage .. "\nInsufficient station inventory" + else + goodData["quantity"] = goodData["quantity"] - 1 + if comms_source.goods == nil then + comms_source.goods = {} end - setCommsMessage(oMsg) - addCommsReply("Back", commsStation) - end) - gi = gi + 1 - until(gi > #goods[comms_target]) + if comms_source.goods[good] == nil then + comms_source.goods[good] = 0 + end + comms_source.goods[good] = comms_source.goods[good] + 1 + comms_source.goods["food"] = comms_source.goods["food"] - 1 + goodTransactionMessage = goodTransactionMessage .. "\nTraded" + end + setCommsMessage(goodTransactionMessage) + addCommsReply("Back", commsStation) + end) + end + end + if ctd.trade.medicine and comms_source.goods ~= nil and comms_source.goods.medicine ~= nil and comms_source.goods.medicine.quantity > 0 then + for good, goodData in pairs(ctd.goods) do + addCommsReply(string.format("Trade medicine for %s",good), function() + local goodTransactionMessage = string.format("Type: %s, Quantity: %i",good,goodData["quantity"]) + if goodData["quantity"] < 1 then + goodTransactionMessage = goodTransactionMessage .. "\nInsufficient station inventory" + else + goodData["quantity"] = goodData["quantity"] - 1 + if comms_source.goods == nil then + comms_source.goods = {} + end + if comms_source.goods[good] == nil then + comms_source.goods[good] = 0 + end + comms_source.goods[good] = comms_source.goods[good] + 1 + comms_source.goods["medicine"] = comms_source.goods["medicine"] - 1 + goodTransactionMessage = goodTransactionMessage .. "\nTraded" + end + setCommsMessage(goodTransactionMessage) + addCommsReply("Back", commsStation) + end) end end - -- Buttons for medicine trades - if tradeMedicine[comms_target] ~= nil then - gi = 1 - medicineQuantity = 0 - repeat - if goods[player][gi][1] == "medicine" then - medicineQuantity = goods[player][gi][2] - end - gi = gi + 1 - until(gi > #goods[player]) - if medicineQuantity > 0 then - gi = 1 - repeat - local goodsType = goods[comms_target][gi][1] - local goodsQuantity = goods[comms_target][gi][2] - addCommsReply(string.format("Trade medicine for %s",goods[comms_target][gi][1]), function() - oMsg = string.format("Type: %s, Quantity: %i",goodsType,goodsQuantity) - if goodsQuantity < 1 then - oMsg = oMsg .. "\nInsufficient station inventory" - else - decrementStationGoods(goodsType) - incrementPlayerGoods(goodsType) - decrementPlayerGoods("medicine") - oMsg = oMsg .. "\nTraded" + if ctd.trade.luxury and comms_source.goods ~= nil and comms_source.goods.luxury ~= nil and comms_source.goods.luxury.quantity > 0 then + for good, goodData in pairs(ctd.goods) do + addCommsReply(string.format("Trade luxury for %s",good), function() + local goodTransactionMessage = string.format("Type: %s, Quantity: %i",good,goodData["quantity"]) + if goodData[quantity] < 1 then + goodTransactionMessage = goodTransactionMessage .. "\nInsufficient station inventory" + else + goodData["quantity"] = goodData["quantity"] - 1 + if comms_source.goods == nil then + comms_source.goods = {} end - setCommsMessage(oMsg) - addCommsReply("Back", commsStation) - end) - gi = gi + 1 - until(gi > #goods[comms_target]) + if comms_source.goods[good] == nil then + comms_source.goods[good] = 0 + end + comms_source.goods[good] = comms_source.goods[good] + 1 + comms_source.goods["luxury"] = comms_source.goods["luxury"] - 1 + goodTransactionMessage = goodTransactionMessage .. "\nTraded" + end + setCommsMessage(goodTransactionMessage) + addCommsReply("Back", commsStation) + end) end end addCommsReply("Back", commsStation) end) - gi = 1 - cargoHoldEmpty = true - repeat - playerGoodsType = goods[player][gi][1] - playerGoodsQuantity = goods[player][gi][2] - if playerGoodsQuantity > 0 then - cargoHoldEmpty = false + local player_good_count = 0 + if comms_source.goods ~= nil then + for good, goodQuantity in pairs(comms_source.goods) do + player_good_count = player_good_count + 1 end - gi = gi + 1 - until(gi > #goods[player]) - if not cargoHoldEmpty then + end + if player_good_count > 0 then addCommsReply("Jettison cargo", function() - setCommsMessage(string.format("Available space: %i\nWhat would you like to jettison?",player.cargo)) - gi = 1 - repeat - local goodsType = goods[player][gi][1] - local goodsQuantity = goods[player][gi][2] - if goodsQuantity > 0 then - addCommsReply(goodsType, function() - decrementPlayerGoods(goodsType) - player.cargo = player.cargo + 1 - setCommsMessage(string.format("One %s jettisoned",goodsType)) + setCommsMessage(string.format("Available space: %i\nWhat would you like to jettison?",comms_source.cargo)) + for good, good_quantity in pairs(comms_source.goods) do + if good_quantity > 0 then + addCommsReply(good, function() + comms_source.goods[good] = comms_source.goods[good] - 1 + comms_source.cargo = comms_source.cargo + 1 + setCommsMessage(string.format("One %s jettisoned",good)) addCommsReply("Back", commsStation) end) end - gi = gi + 1 - until(gi > #goods[player]) + end addCommsReply("Back", commsStation) end) end + addCommsReply("No tutorial covered goods or cargo. Explain", function() + setCommsMessage("Different types of cargo or goods may be obtained from stations, freighters or other sources. They go by one word descriptions such as dilithium, optic, warp, etc. Certain mission goals may require a particular type or types of cargo. Each player ship differs in cargo carrying capacity. Goods may be obtained by spending reputation points or by trading other types of cargo (typically food, medicine or luxury)") + addCommsReply("Back", commsStation) + end) end end function isAllowedTo(state) @@ -3289,6 +4047,7 @@ function getWeaponCost(weapon) end function handleUndockedState() --Handle communications when we are not docked with the station. + local ctd = comms_target.comms_data if player:isFriendly(comms_target) then oMsg = "Good day, officer.\nIf you need supplies, please dock with us first." else @@ -3328,90 +4087,127 @@ function handleUndockedState() addCommsReply("I need information", function() setCommsMessage("What kind of information do you need?") addCommsReply("What ordnance do you have available for restock?", function() - missileTypeAvailableCount = 0 - oMsg = "" - if comms_target.nukeAvail then + local ctd = comms_target.comms_data + local missileTypeAvailableCount = 0 + local ordnanceListMsg = "" + if ctd.weapon_available.Nuke then missileTypeAvailableCount = missileTypeAvailableCount + 1 - oMsg = oMsg .. "\n Nuke" + ordnanceListMsg = ordnanceListMsg .. "\n Nuke" end - if comms_target.empAvail then + if ctd.weapon_available.EMP then missileTypeAvailableCount = missileTypeAvailableCount + 1 - oMsg = oMsg .. "\n EMP" + ordnanceListMsg = ordnanceListMsg .. "\n EMP" end - if comms_target.homeAvail then + if ctd.weapon_available.Homing then missileTypeAvailableCount = missileTypeAvailableCount + 1 - oMsg = oMsg .. "\n Homing" + ordnanceListMsg = ordnanceListMsg .. "\n Homing" end - if comms_target.mineAvail then + if ctd.weapon_available.Mine then missileTypeAvailableCount = missileTypeAvailableCount + 1 - oMsg = oMsg .. "\n Mine" + ordnanceListMsg = ordnanceListMsg .. "\n Mine" end - if comms_target.hvliAvail then + if ctd.weapon_available.HVLI then missileTypeAvailableCount = missileTypeAvailableCount + 1 - oMsg = oMsg .. "\n HVLI" + ordnanceListMsg = ordnanceListMsg .. "\n HVLI" end if missileTypeAvailableCount == 0 then - oMsg = "We have no ordnance available for restock" + ordnanceListMsg = "We have no ordnance available for restock" elseif missileTypeAvailableCount == 1 then - oMsg = "We have the following type of ordnance available for restock:" .. oMsg + ordnanceListMsg = "We have the following type of ordnance available for restock:" .. ordnanceListMsg else - oMsg = "We have the following types of ordnance available for restock:" .. oMsg + ordnanceListMsg = "We have the following types of ordnance available for restock:" .. ordnanceListMsg end - setCommsMessage(oMsg) + setCommsMessage(ordnanceListMsg) addCommsReply("Back", commsStation) end) - goodsQuantityAvailable = 0 - gi = 1 - repeat - if goods[comms_target][gi][2] > 0 then - goodsQuantityAvailable = goodsQuantityAvailable + goods[comms_target][gi][2] + local goodsAvailable = false + if ctd.goods ~= nil then + for good, goodData in pairs(ctd.goods) do + if goodData["quantity"] > 0 then + goodsAvailable = true + end end - gi = gi + 1 - until(gi > #goods[comms_target]) - if goodsQuantityAvailable > 0 then + end + if goodsAvailable then addCommsReply("What goods do you have available for sale or trade?", function() - oMsg = string.format("Station %s:\nGoods or components available: quantity, cost in reputation\n",comms_target:getCallSign()) - gi = 1 -- initialize goods index - repeat - goodsType = goods[comms_target][gi][1] - goodsQuantity = goods[comms_target][gi][2] - goodsRep = goods[comms_target][gi][3] - oMsg = oMsg .. string.format(" %14s: %2i, %3i\n",goodsType,goodsQuantity,goodsRep) - gi = gi + 1 - until(gi > #goods[comms_target]) - setCommsMessage(oMsg) + local ctd = comms_target.comms_data + local goodsAvailableMsg = string.format("Station %s:\nGoods or components available: quantity, cost in reputation",comms_target:getCallSign()) + for good, goodData in pairs(ctd.goods) do + goodsAvailableMsg = goodsAvailableMsg .. string.format("\n %14s: %2i, %3i",good,goodData["quantity"],goodData["cost"]) + end + setCommsMessage(goodsAvailableMsg) addCommsReply("Back", commsStation) end) end addCommsReply("Where can I find particular goods?", function() - gkMsg = "Friendly stations generally have food or medicine or both. Neutral stations often trade their goods for food, medicine or luxury." - if comms_target.goodsKnowledge == nil then - gkMsg = gkMsg .. " Beyond that, I have no knowledge of specific stations.\n\nCheck back later, someone else may have better knowledge" - setCommsMessage(gkMsg) - addCommsReply("Back", commsStation) - fillStationBrains() - else - if #comms_target.goodsKnowledge == 0 then - gkMsg = gkMsg .. " Beyond that, I have no knowledge of specific stations" - else - gkMsg = gkMsg .. "\n\nWhat goods are you interested in?\nI've heard about these:" - for gk=1,#comms_target.goodsKnowledge do - addCommsReply(comms_target.goodsKnowledgeType[gk],function() - 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])) - addCommsReply("Back", commsStation) - end) + local ctd = comms_target.comms_data + gkMsg = "Friendly stations often have food or medicine or both. Neutral stations may trade their goods for food, medicine or luxury." + if ctd.goodsKnowledge == nil then + ctd.goodsKnowledge = {} + local knowledgeCount = 0 + local knowledgeMax = 10 + for i=1,#humanStationList do + local station = humanStationList[i] + if station ~= nil and station:isValid() then + local brainCheckChance = 60 + if distance(comms_target,station) > 75000 then + brainCheckChance = 20 + end + for good, goodData in pairs(station.comms_data.goods) do + if random(1,100) <= brainCheckChance then + local stationCallSign = station:getCallSign() + local stationSector = station:getSectorName() + ctd.goodsKnowledge[good] = { station = stationCallSign, + sector = stationSector, + cost = goodData["cost"] } + knowledgeCount = knowledgeCount + 1 + if knowledgeCount >= knowledgeMax then + break + end + end + end + end + if knowledgeCount >= knowledgeMax then + break end end - setCommsMessage(gkMsg) - addCommsReply("Back", commsStation) end + local goodsKnowledgeCount = 0 + for good, goodKnowledge in pairs(ctd.goodsKnowledge) do + goodsKnowledgeCount = goodsKnowledgeCount + 1 + addCommsReply(good, function() + local ctd = comms_target.comms_data + local stationName = ctd.goodsKnowledge[good]["station"] + local sectorName = ctd.goodsKnowledge[good]["sector"] + local goodName = good + local goodCost = ctd.goodsKnowledge[good]["cost"] + setCommsMessage(string.format("Station %s in sector %s has %s for %i reputation",stationName,sectorName,goodName,goodCost)) + addCommsReply("Back", commsStation) + end) + end + if goodsKnowledgeCount > 0 then + gkMsg = gkMsg .. "\n\nWhat goods are you interested in?\nI've heard about these:" + else + gkMsg = gkMsg .. " Beyond that, I have no knowledge of specific stations" + end + setCommsMessage(gkMsg) + addCommsReply("Back", commsStation) end) - if comms_target.publicRelations then - addCommsReply("General station information", function() - setCommsMessage(comms_target.generalInformation) - addCommsReply("Back", commsStation) - end) - end + if ctd.public_relations then + addCommsReply("Tell me more about your station", function() + setCommsMessage("What would you like to know?") + addCommsReply("General information", function() + setCommsMessage(ctd.general_information) + addCommsReply("Back", commsStation) + end) + if ctd.history ~= nil then + addCommsReply("Station history", function() + setCommsMessage(ctd.history) + addCommsReply("Back", commsStation) + end) + end + end) --end station info comms reply branch + end --end public relations if branch end) if isAllowedTo(comms_target.comms_data.services.supplydrop) then addCommsReply("Can you send a supply drop? ("..getServiceCost("supplydrop").."rep)", function() @@ -3461,9 +4257,9 @@ function handleUndockedState() end) end end +function getServiceCost(service) -- Return the number of reputation points that a specified service costs for -- the current player. -function getServiceCost(service) return math.ceil(comms_data.service_cost[service]) end function fillStationBrains() @@ -3523,48 +4319,451 @@ function getFriendStatus() return "neutral" end end ---[[----------------------------------------------------------------- - Cargo management ------------------------------------------------------------------]]-- -function incrementPlayerGoods(goodsType) - local gi = 1 - repeat - if goods[player][gi][1] == goodsType then - goods[player][gi][2] = goods[player][gi][2] + 1 - end - gi = gi + 1 - until(gi > #goods[player]) -end -function decrementPlayerGoods(goodsType) - local gi = 1 - repeat - if goods[player][gi][1] == goodsType then - goods[player][gi][2] = goods[player][gi][2] - 1 - end - gi = gi + 1 - until(gi > #goods[player]) -end -function decrementStationGoods(goodsType) - local gi = 1 - repeat - if goods[comms_target][gi][1] == goodsType then - goods[comms_target][gi][2] = goods[comms_target][gi][2] - 1 - end - gi = gi + 1 - until(gi > #goods[comms_target]) -end -function decrementShipGoods(goodsType) - local gi = 1 - repeat - if goods[comms_target][gi][1] == goodsType then - goods[comms_target][gi][2] = goods[comms_target][gi][2] - 1 - end - gi = gi + 1 - until(gi > #goods[comms_target]) -end ---[[------------------------------------------------------------------- - First Plot starts when repulse hulk is scanned ---]]------------------------------------------------------------------- +-------------------------- +-- Ship communication -- +-------------------------- +function commsShip() + if comms_target.comms_data == nil then + comms_target.comms_data = {friendlyness = random(0.0, 100.0)} + end + comms_data = comms_target.comms_data + if comms_data.goods == nil then + comms_data.goods = {} + comms_data.goods[commonGoods[math.random(1,#commonGoods)]] = {quantity = 1, cost = random(20,80)} + local shipType = comms_target:getTypeName() + local goodCount = 0 + if shipType:find("Freighter") ~= nil then + if shipType:find("Goods") ~= nil then + repeat + comms_data.goods[commonGoods[math.random(1,#commonGoods)]] = {quantity = 1, cost = random(20,80)} + goodCount = 0 + for good, goodData in pairs(comms_data.goods) do + goodCount = goodCount + 1 + end + until(goodCount >= 3) + elseif shipType:find("Equipment") ~= nil then + repeat + comms_data.goods[componentGoods[math.random(1,#componentGoods)]] = {quantity = 1, cost = random(20,80)} + goodCount = 0 + for good, goodData in pairs(comms_data.goods) do + goodCount = goodCount + 1 + end + until(goodCount >= 3) + end + end + end + if comms_source:isFriendly(comms_target) then + return friendlyComms(comms_data) + end + if comms_source:isEnemy(comms_target) and comms_target:isFriendOrFoeIdentifiedBy(comms_source) then + return enemyComms(comms_data) + end + return neutralComms(comms_data) +end +function friendlyComms(comms_data) + if comms_data.friendlyness < 20 then + setCommsMessage("What do you want?"); + else + setCommsMessage("Sir, how can we assist?"); + end + shipType = comms_target:getTypeName() + if shipType:find("Freighter") ~= nil then + addCommsReply("Do you have cargo you might sell?", function() + local goodCount = 0 + local cargoMsg = "We've got " + for good, goodData in pairs(comms_data.goods) do + if goodData.quantity > 0 then + if goodCount > 0 then + cargoMsg = cargoMsg .. ", " .. good + else + cargoMsg = cargoMsg .. good + end + end + goodCount = goodCount + goodData.quantity + end + if goodCount == 0 then + cargoMsg = cargoMsg .. "nothing" + end + setCommsMessage(cargoMsg) + end) + if distance(comms_source,comms_target) < 5000 then + local goodCount = 0 + if comms_source.goods ~= nil then + for good, goodQuantity in pairs(comms_source.goods) do + goodCount = goodCount + 1 + end + end + if goodCount > 0 then + addCommsReply("Jettison cargo", function() + setCommsMessage(string.format("Available space: %i\nWhat would you like to jettison?",comms_source.cargo)) + for good, good_quantity in pairs(comms_source.goods) do + if good_quantity > 0 then + addCommsReply(good, function() + comms_source.goods[good] = comms_source.goods[good] - 1 + comms_source.cargo = comms_source.cargo + 1 + setCommsMessage(string.format("One %s jettisoned",good)) + addCommsReply("Back", commsShip) + end) + end + end + addCommsReply("Back", commsShip) + end) + end + if shipType:find("Goods") ~= nil or shipType:find("Equipment") ~= nil then + local luxuryQuantity = 0 + if comms_source.goods ~= nil and comms_source.goods["luxury"] ~= nil and comms_source.goods["luxury"] > 0 then + luxuryQuantity = comms_source.goods["luxury"] + end + if luxuryQuantity > 0 then + for good, goodData in pairs(comms_data.goods) do + if goodData.quantity > 0 then + addCommsReply(string.format("Trade luxury for %s",good), function() + comms_source.goods["luxury"] = comms_source.goods["luxury"] - 1 + if comms_source.goods[good] == nil then comms_source.goods[good] = 0 end + comms_source.goods[good] = comms_source.goods[good] + 1 + setCommsMessage("Traded") + addCommsReply("Back", commsShip) + end) + end + end + end + end + if shipType:find("Goods") ~= nil or shipType:find("Equipment") ~= nil then + freighter_multiplier = 1 + else + freighter_multiplier = 2 + end + for good, goodData in pairs(comms_data.goods) do + if goodData.quantity > 0 then + addCommsReply(string.format("Buy one %s for %i reputation",good,math.floor(goodData.cost*freighter_multiplier)), function() + if comms_source.cargo > 0 then + if comms_source:takeReputationPoints(goodData.cost) then + goodData.quantity = goodData.quantity - 1 + if comms_source.goods == nil then comms_source.goods = {} end + if comms_source.goods[good] == nil then comms_source.goods[good] = 0 end + comms_source.goods[good] = comms_source.goods[good] + 1 + comms_source.cargo = comms_source.cargo - 1 + setCommsMessage(string.format("Purchased %s from %s",good,comms_target:getCallSign())) + else + setCommsMessage("Insufficient reputation for purchase") + end + else + setCommsMessage("Insufficient cargo space") + end + addCommsReply("Back", commsShip) + end) + end + end --freighter goods loop + end + end + addCommsReply("Defend a waypoint", function() + if comms_source:getWaypointCount() == 0 then + setCommsMessage("No waypoints set. Please set a waypoint first."); + addCommsReply("Back", commsShip) + else + setCommsMessage("Which waypoint should we defend?"); + for n=1,comms_source:getWaypointCount() do + addCommsReply("Defend WP" .. n, function() + comms_target:orderDefendLocation(comms_source:getWaypoint(n)) + setCommsMessage("We are heading to assist at WP" .. n .."."); + addCommsReply("Back", commsShip) + end) + end + end + end) + if comms_data.friendlyness > 0.2 then + addCommsReply("Assist me", function() + setCommsMessage("Heading toward you to assist."); + comms_target:orderDefendTarget(comms_source) + addCommsReply("Back", commsShip) + end) + end + addCommsReply("Report status", function() + msg = "Hull: " .. math.floor(comms_target:getHull() / comms_target:getHullMax() * 100) .. "%\n" + shields = comms_target:getShieldCount() + if shields == 1 then + msg = msg .. "Shield: " .. math.floor(comms_target:getShieldLevel(0) / comms_target:getShieldMax(0) * 100) .. "%\n" + elseif shields == 2 then + msg = msg .. "Front Shield: " .. math.floor(comms_target:getShieldLevel(0) / comms_target:getShieldMax(0) * 100) .. "%\n" + msg = msg .. "Rear Shield: " .. math.floor(comms_target:getShieldLevel(1) / comms_target:getShieldMax(1) * 100) .. "%\n" + else + for n=0,shields-1 do + msg = msg .. "Shield " .. n .. ": " .. math.floor(comms_target:getShieldLevel(n) / comms_target:getShieldMax(n) * 100) .. "%\n" + end + end + + local missile_types = {'Homing', 'Nuke', 'Mine', 'EMP', 'HVLI'} + for i, missile_type in ipairs(missile_types) do + if comms_target:getWeaponStorageMax(missile_type) > 0 then + msg = msg .. missile_type .. " Missiles: " .. math.floor(comms_target:getWeaponStorage(missile_type)) .. "/" .. math.floor(comms_target:getWeaponStorageMax(missile_type)) .. "\n" + end + end + + setCommsMessage(msg); + addCommsReply("Back", commsShip) + end) + for _, obj in ipairs(comms_target:getObjectsInRange(5000)) do + if obj.typeName == "SpaceStation" and not comms_target:isEnemy(obj) then + addCommsReply("Dock at " .. obj:getCallSign(), function() + setCommsMessage("Docking at " .. obj:getCallSign() .. "."); + comms_target:orderDock(obj) + addCommsReply("Back", commsShip) + end) + end + end + return true +end +function enemyComms(comms_data) + if comms_data.friendlyness > 50 then + faction = comms_target:getFaction() + taunt_option = "We will see to your destruction!" + taunt_success_reply = "Your bloodline will end here!" + taunt_failed_reply = "Your feeble threats are meaningless." + if faction == "Kraylor" then + setCommsMessage("Ktzzzsss.\nYou will DIEEee weaklingsss!"); + elseif faction == "Arlenians" then + setCommsMessage("We wish you no harm, but will harm you if we must.\nEnd of transmission."); + elseif faction == "Exuari" then + setCommsMessage("Stay out of our way, or your death will amuse us extremely!"); + elseif faction == "Ghosts" then + 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."); + taunt_option = "EXECUTE: SELFDESTRUCT" + taunt_success_reply = "Rogue command received. Targeting source." + taunt_failed_reply = "External command ignored." + elseif faction == "Ktlitans" then + 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."); + taunt_option = "" + taunt_success_reply = "We do not need permission to pluck apart such an insignificant threat." + taunt_failed_reply = "The hive has greater priorities than exterminating pests." + else + setCommsMessage("Mind your own business!"); + end + comms_data.friendlyness = comms_data.friendlyness - random(0, 10) + addCommsReply(taunt_option, function() + if random(0, 100) < 30 then + comms_target:orderAttack(comms_source) + setCommsMessage(taunt_success_reply); + else + setCommsMessage(taunt_failed_reply); + end + end) + return true + end + return false +end +function neutralComms(comms_data) + shipType = comms_target:getTypeName() + if shipType:find("Freighter") ~= nil then + setCommsMessage("Yes?") + addCommsReply("Do you have cargo you might sell?", function() + local goodCount = 0 + local cargoMsg = "We've got " + for good, goodData in pairs(comms_data.goods) do + if goodData.quantity > 0 then + if goodCount > 0 then + cargoMsg = cargoMsg .. ", " .. good + else + cargoMsg = cargoMsg .. good + end + end + goodCount = goodCount + goodData.quantity + end + if goodCount == 0 then + cargoMsg = cargoMsg .. "nothing" + end + setCommsMessage(cargoMsg) + end) + local freighter_multiplier = 1 + if comms_data.friendlyness > 66 then + setCommsMessage("Yes?") + -- Offer destination information + addCommsReply("Where are you headed?", function() + setCommsMessage(comms_target.target:getCallSign()) + addCommsReply("Back", commsShip) + end) + -- Offer to trade goods if goods or equipment freighter + if distance(comms_source,comms_target) < 5000 then + local goodCount = 0 + if comms_source.goods ~= nil then + for good, goodQuantity in pairs(comms_source.goods) do + goodCount = goodCount + 1 + end + end + if goodCount > 0 then + addCommsReply("Jettison cargo", function() + setCommsMessage(string.format("Available space: %i\nWhat would you like to jettison?",comms_source.cargo)) + for good, good_quantity in pairs(comms_source.goods) do + if good_quantity > 0 then + addCommsReply(good, function() + comms_source.goods[good] = comms_source.goods[good] - 1 + comms_source.cargo = comms_source.cargo + 1 + setCommsMessage(string.format("One %s jettisoned",good)) + addCommsReply("Back", commsShip) + end) + end + end + addCommsReply("Back", commsShip) + end) + end + if shipType:find("Goods") ~= nil or shipType:find("Equipment") ~= nil then + local luxuryQuantity = 0 + if comms_source.goods ~= nil and comms_source.goods["luxury"] ~= nil and comms_source.goods["luxury"] > 0 then + luxuryQuantity = comms_source.goods["luxury"] + end + if luxuryQuantity > 0 then + for good, goodData in pairs(comms_data.goods) do + if goodData.quantity > 0 then + addCommsReply(string.format("Trade luxury for %s",good), function() + comms_source.goods["luxury"] = comms_source.goods["luxury"] - 1 + if comms_source.goods[good] == nil then comms_source.goods[good] = 0 end + comms_source.goods[good] = comms_source.goods[good] + 1 + setCommsMessage("Traded") + addCommsReply("Back", commsShip) + end) + end + end + end + end + if shipType:find("Goods") ~= nil or shipType:find("Equipment") ~= nil then + freighter_multiplier = 1 + else + freighter_multiplier = 2 + end + for good, goodData in pairs(comms_data.goods) do + if goodData.quantity > 0 then + addCommsReply(string.format("Buy one %s for %i reputation",good,math.floor(goodData.cost*freighter_multiplier)), function() + if comms_source.cargo > 0 then + if comms_source:takeReputationPoints(goodData.cost) then + goodData.quantity = goodData.quantity - 1 + if comms_source.goods == nil then comms_source.goods = {} end + if comms_source.goods[good] == nil then comms_source.goods[good] = 0 end + comms_source.goods[good] = comms_source.goods[good] + 1 + comms_source.cargo = comms_source.cargo - 1 + setCommsMessage(string.format("Purchased %s from %s",good,comms_target:getCallSign())) + else + setCommsMessage("Insufficient reputation for purchase") + end + else + setCommsMessage("Insufficient cargo space") + end + addCommsReply("Back", commsShip) + end) + end + end --freighter goods loop + end + elseif comms_data.friendlyness > 33 then + setCommsMessage("What do you want?") + -- Offer to sell destination information + destRep = random(1,5) + addCommsReply(string.format("Where are you headed? (cost: %f reputation)",destRep), function() + if not comms_source:takeReputationPoints(destRep) then + setCommsMessage("Insufficient reputation") + else + setCommsMessage(comms_target.target:getCallSign()) + end + addCommsReply("Back", commsShip) + end) + -- Offer to sell goods if goods or equipment freighter + if distance(comms_source,comms_target) < 5000 then + local goodCount = 0 + if comms_source.goods ~= nil then + for good, goodQuantity in pairs(comms_source.goods) do + goodCount = goodCount + 1 + end + end + if goodCount > 0 then + addCommsReply("Jettison cargo", function() + setCommsMessage(string.format("Available space: %i\nWhat would you like to jettison?",comms_source.cargo)) + for good, good_quantity in pairs(comms_source.goods) do + if good_quantity > 0 then + addCommsReply(good, function() + comms_source.goods[good] = comms_source.goods[good] - 1 + comms_source.cargo = comms_source.cargo + 1 + setCommsMessage(string.format("One %s jettisoned",good)) + addCommsReply("Back", commsShip) + end) + end + end + addCommsReply("Back", commsShip) + end) + end + if shipType:find("Goods") ~= nil or shipType:find("Equipment") ~= nil then + freighter_multiplier = 2 + else + freighter_multiplier = 3 + end + for good, goodData in pairs(comms_data.goods) do + if goodData.quantity > 0 then + addCommsReply(string.format("Buy one %s for %i reputation",good,math.floor(goodData.cost*freighter_multiplier)), function() + if comms_source.cargo > 0 then + if comms_source:takeReputationPoints(goodData.cost*freighter_multiplier) then + goodData.quantity = goodData.quantity - 1 + if comms_source.goods == nil then + comms_source.goods = {} + end + if comms_source.goods[good] == nil then + comms_source.goods[good] = 0 + end + comms_source.goods[good] = comms_source.goods[good] + 1 + comms_source.cargo = comms_source.cargo - 1 + setCommsMessage(string.format("Purchased %s from %s",good,comms_target:getCallSign())) + else + setCommsMessage("Insufficient reputation for purchase") + end + else + setCommsMessage("Insufficient cargo space") + end + addCommsReply("Back", commsShip) + end) + end + end --freighter goods loop + end + else --least friendly + setCommsMessage("Why are you bothering me?") + -- Offer to sell goods if goods or equipment freighter double price + if distance(comms_source,comms_target) < 5000 then + if shipType:find("Goods") ~= nil or shipType:find("Equipment") ~= nil then + freighter_multiplier = 3 + for good, goodData in pairs(comms_data.goods) do + if goodData.quantity > 0 then + addCommsReply(string.format("Buy one %s for %i reputation",good,math.floor(goodData.cost*freighter_multiplier)), function() + if comms_source.cargo > 0 then + if comms_source:takeReputationPoints(goodData.cost*freighter_multiplier) then + goodData.quantity = goodData.quantity - 1 + if comms_source.goods == nil then + comms_source.goods = {} + end + if comms_source.goods[good] == nil then + comms_source.goods[good] = 0 + end + comms_source.goods[good] = comms_source.goods[good] + 1 + comms_source.cargo = comms_source.cargo - 1 + setCommsMessage(string.format("Purchased %s from %s",good,comms_target:getCallSign())) + else + setCommsMessage("Insufficient reputation for purchase") + end + else + setCommsMessage("Insufficient cargo space") + end + addCommsReply("Back", commsShip) + end) + end + end --freighter goods loop + end + end + end + else + if comms_data.friendlyness > 50 then + setCommsMessage("Sorry, we have no time to chat with you.\nWe are on an important mission."); + else + setCommsMessage("We have nothing for you.\nGood day."); + end + end + return true +end +------------------------------------------------------ +-- First Plot starts when repulse hulk is scanned -- +------------------------------------------------------ function scanRepulse(delta) if difficulty >= 1 then plotSuffocate = checkForSuffocationOnFighter @@ -3656,8 +4855,8 @@ function checkForSuffocationOnFighter(delta) end end end ---Engineer hints that the Repulse hulk has a jump drive that might function function hintRepulse(delta) +--Engineer hints that the Repulse hulk has a jump drive that might function if difficulty >= 1 then plotSuffocate = checkForSuffocationOnFighter end @@ -3674,8 +4873,8 @@ function hintRepulse(delta) plot1 = hugRepulse end end ---Get close enough and a transfer button will appear function hugRepulse(delta) +--Get close enough and a transfer button will appear if difficulty >= 1 then plotSuffocate = checkForSuffocationOnFighter end @@ -3693,8 +4892,8 @@ function hugRepulse(delta) end end end ---Transfer crew and any artifacts picked up to Repulse function repulseTransfer() +--Transfer crew and any artifacts picked up to Repulse swapx, swapy = junkRepulse:getPosition() --save NPC ship location swapRotate = junkRepulse:getRotation() --save NPC ship orientation junkRepulse:setPosition(500,500) --move NPC ship away @@ -3749,13 +4948,12 @@ function repulseTransfer() plot1 = augmentRepairCrew playerRepulse:addToShipLog("Welcome aboard the Repulse class ship, rechristened HMS Plunder, currently registered as Independent","Magenta") player = playerRepulse - goods[player] = goodsList plotKP = kraylorPatrol --start sending out Kraylor patrols plotSuffocate = nil --print("end of transfer") end ---Former repair crew asks to be rescued to take up their jobs again function augmentRepairCrew(delta) +--Former repair crew asks to be rescued to take up their jobs again augmentRepairCrewTimer = augmentRepairCrewTimer - delta if augmentRepairCrewTimer < 0 then brigHailed = brigStation:sendCommsMessage(playerRepulse,"Need a repair crew? We used to be posted on that ship. We would be happy to return to our repair duty and get away from these Kraylors. We left the transporters locked on us, but the Kraylors destroyed our remote activator. You should find an activation switch at the weapons console") @@ -3778,8 +4976,8 @@ function augmentRepairCrew(delta) augmentRepairCrewTimer = delta + 30 end end ---Repair crew returns function returnRepairCrew() +--Repair crew returns playerRepulse:setRepairCrewCount(8) if retrieveRepairCrewButton ~= nil then playerRepulse:removeCustom(retrieveRepairCrewButton) @@ -3788,8 +4986,8 @@ function returnRepairCrew() playerRepulse:removeCustom(retrieveRepairCrewButtonTac) end end ---Report on damaged beams on port side, start second plot function beamDamageReport(delta) +--Report on damaged beams on port side, start second plot beamDamageReportTimer = beamDamageReportTimer - delta if beamDamageReportTimer < 0 then playerRepulse:addToShipLog("Repair crew reports that the port beam weapon emplacement is currently non-functional. No applicable spare parts found aboard","Magenta") @@ -3798,8 +4996,8 @@ function beamDamageReport(delta) jumpDamageReportTimer = 30 end end ---Report on damaged jump drive, start third plot function jumpDamageReport(delta) +--Report on damaged jump drive, start third plot jumpDamageReportTimer = jumpDamageReportTimer - delta if jumpDamageReportTimer < 0 then if playerRepulse.debris1 then @@ -3814,16 +5012,27 @@ function jumpDamageReport(delta) missileDamageReportTimer = 30 end end ---Report on damaged missile systems function missileDamageReport(delta) +--Report on damaged missile systems missileDamageReportTimer = missileDamageReportTimer - delta if missileDamageReportTimer < 0 then playerRepulse:addToShipLog("Repair crew says the missle weapons systems are not repairable with available components","Magenta") + hull_damage_report_timer = 80 + plot1 = hullDamageReport + end +end +function hullDamageReport(delta) + hull_damage_report_timer = hull_damage_report_timer - delta + if hull_damage_report_timer < 0 then plot1 = damageSummaryReport + if playerRepulse.debris3 then + playerRepulse:setHull(playerRepulse:getHull()*2) + playerRepulse:addToShipLog("Repair crew applied some of the parts picked up to make some repairs on the hull","Magenta") + end end end ---Report on completed repairs function damageSummaryReport(delta) +--Report on completed repairs totalDiff = 0 totalDiff = totalDiff + math.abs(playerRepulse.maxReactor - playerRepulse:getSystemHealth("reactor")) totalDiff = totalDiff + math.abs(playerRepulse.maxBeam - playerRepulse:getSystemHealth("beamweapons")) @@ -3838,8 +5047,8 @@ function damageSummaryReport(delta) plot1 = nil end end ---trigger: beam repaired function fixFlood(delta) +--trigger: beam repaired fixFloodTimer = fixFloodTimer - delta if fixFloodTimer < 0 then if missileFixStation == nil then @@ -3948,11 +5157,34 @@ function fixFlood(delta) playerRepulse:addCustomButton("Operations",crewFixButtonMsgOp,"crew fixers",showCrewFixers) end end - plot1 = nil + harassment_timer = 350 + plot1 = cumulativeHarassment end end end end +function cumulativeHarassment(delta) + harassment_timer = harassment_timer - delta + if harassment_timer < 0 then + local total_health = playerRepulse:getSystemHealth("reactor") + total_health = total_health + playerRepulse:getSystemHealth("beamweapons") + total_health = total_health + playerRepulse:getSystemHealth("maneuver") + total_health = total_health + playerRepulse:getSystemHealth("missilesystem") + total_health = total_health + playerRepulse:getSystemHealth("impulse") + total_health = total_health + playerRepulse:getSystemHealth("jumpdrive") + total_health = total_health + playerRepulse:getSystemHealth("frontshield") + total_health = total_health + playerRepulse:getSystemHealth("rearshield") + total_health = total_health + playerRepulse:getSystemHealth("warp") + total_health = total_health/9 + local cpx, cpy = playerRepulse:getPosition() + local dpx, dpy = vectorFromAngle(random(0,360),playerRepulse:getLongRangeRadarRange()+500) + local fleet = spawnEnemies(cpx+dpx,cpy+dpy,total_health,"Exuari") + for _, enemy in ipairs(fleet) do + enemy:orderAttack(playerRepulse) + end + harassment_timer = delta + 200 - (difficulty*20) + end +end function showCrewFixers() oMsg = "" if not playerRepulse.missileFix then @@ -3985,17 +5217,17 @@ function showCrewFixers() playerRepulse:addToShipLog(oMsg,"Magenta") end end ---[[------------------------------------------------------------------- - Second Plot port beam repair ---]]------------------------------------------------------------------- +------------------------------------ +-- Second Plot port beam repair -- +------------------------------------ function portBeamEnable(delta) if playerRepulse:getRepairCrewCount() > 1 then plot2 = suggestBeamFix suggestBeamFixTimer = 70 end end ---Repair suggestion function suggestBeamFix(delta) +--Repair suggestion suggestBeamFixTimer = suggestBeamFixTimer - delta if suggestBeamFixTimer < 0 then if beamFixStation == nil then @@ -4010,28 +5242,38 @@ function suggestBeamFix(delta) end end end ---Ship gets repaired then chased function chaseTrigger(delta) +--Ship gets repaired then chased if plot1 == nil then junkYardDogTimer = 20 plot2 = junkYardDog end end ---Sic junk yard dog on player ship function junkYardDog(delta) +--Sic junk yard dog on player ship junkYardDogTimer = junkYardDogTimer - delta if junkYardDogTimer < 0 then - if difficulty < 1 then - junkYardDog = CpuShip():setFaction("Exuari"):setTemplate("Ktlitan Drone"):setPosition(brigx-50,brigy-50):orderAttack(playerRepulse):setRotation(180) - elseif difficulty > 1 then - junkYardDog = CpuShip():setFaction("Exuari"):setTemplate("Fighter"):setPosition(brigx-50,brigy-50):orderAttack(playerRepulse):setRotation(180) + if junkZone:isInside(playerRepulse) then + if junk_yard_dog ~= nil and junk_yard_dog:isValid() then + junkYardDogTimer = delta + 120 - (difficulty*20) + else + if difficulty < 1 then + junk_yard_dog = CpuShip():setFaction("Exuari"):setTemplate("Ktlitan Drone"):setPosition(brigx-50,brigy-50):orderAttack(playerRepulse):setRotation(180) + elseif difficulty > 1 then + junk_yard_dog = CpuShip():setFaction("Exuari"):setTemplate("Fighter"):setPosition(brigx-50,brigy-50):orderAttack(playerRepulse):setRotation(180) + else + junk_yard_dog = CpuShip():setFaction("Exuari"):setTemplate("Ktlitan Fighter"):setPosition(brigx-50,brigy-50):orderAttack(playerRepulse):setRotation(180) + end + end else - junkYardDog = CpuShip():setFaction("Exuari"):setTemplate("Ktlitan Fighter"):setPosition(brigx-50,brigy-50):orderAttack(playerRepulse):setRotation(180) + borisChaseTimer = 300 + plot2 = borisChase + end + if playerRepulse.junk_yard_dog_warning == nil then + playerRepulse:addToShipLog(string.format("[Sensor tech] Looks like %s figured out where we went and has sicced %s on us.",brigStation:getCallSign(),junk_yard_dog:getCallSign()),"Magenta") + playerRepulse:addToShipLog(string.format("[Engineering tech] With our hull at %i, we better hope our shields hold",playerRepulse:getHull()),"Magenta") + playerRepulse.junk_yard_dog_warning = "sent" end - playerRepulse:addToShipLog(string.format("[Sensor tech] Looks like %s figured out where we went and has sicced %s on us.",brigStation:getCallSign(),junkYardDog:getCallSign()),"Magenta") - playerRepulse:addToShipLog(string.format("[Engineering tech] With our hull at %i, we better hope our shields hold",playerRepulse:getHull()),"Magenta") - borisChaseTimer = 300 - plot2 = borisChase end end function borisChase(delta) @@ -4082,17 +5324,17 @@ function resetBoris(self, instigator) playerRepulse:addToShipLog(string.format("[%s] I've got plenty of ships",self:getCallSign()),"Red") end end ---[[------------------------------------------------------------------- - Third Plot jump drive repair ---]]------------------------------------------------------------------- +------------------------------------ +-- Third Plot jump drive repair -- +------------------------------------ function jumpPartGathering(delta) if playerRepulse.debris1 then plot3 = jumpPartRecognition jumpPartRecognitionTimer = 15 end end ---Identify debris as useful for repair of jump drive function jumpPartRecognition(delta) +--Identify debris as useful for repair of jump drive jumpPartRecognitionTimer = jumpPartRecognitionTimer - delta if jumpPartRecognitionTimer < 0 then playerRepulse:addToShipLog("Repair crew thinks they can use the space debris recently acquired to make repair parts for the jump drive. They are starting the fabrication process now.","Magenta") @@ -4100,8 +5342,8 @@ function jumpPartRecognition(delta) jumpPartFabricationTimer = 60 end end ---Jump drive repairable function jumpPartFabrication(delta) +--Jump drive repairable jumpPartFabricationTimer = jumpPartFabricationTimer - delta if jumpPartFabricationTimer < 0 then playerRepulse:addToShipLog("Repair crew finished jump drive part fabrication. They believe the jump drive should be functional soon","Magenta") @@ -4109,9 +5351,9 @@ function jumpPartFabrication(delta) plot3 = nil end end ---[[------------------------------------------------------------------- - Fourth plot return home ---]]------------------------------------------------------------------- +------------------------------- +-- Fourth plot return home -- +------------------------------- function returnHome(delta) for i=1,#friendlyStationList do if friendlyStationList[i] ~= nil and friendlyStationList[i]:isValid() then @@ -4121,9 +5363,9 @@ function returnHome(delta) end end end ---[[------------------------------------------------------------------- - Kraylor Patrol plot ---]]------------------------------------------------------------------- +--------------------------- +-- Kraylor Patrol plot -- +--------------------------- function kraylorPatrol(delta) if kraylorPatrolSpawnDelay > 0 then kraylorPatrolSpawnDelay = kraylorPatrolSpawnDelay - delta @@ -4220,9 +5462,9 @@ function spawnEnemies(xOrigin, yOrigin, danger, enemyFaction) end return enemyList end ---[[------------------------------------------------------------------- - Transport plot ---]]------------------------------------------------------------------- +---------------------- +-- Transport plot -- +---------------------- function randomStation(randomStations) stationCount = 0 for sidx, obj in ipairs(randomStations) do @@ -4234,9 +5476,9 @@ function randomStation(randomStations) end return randomStations[math.random(1,#randomStations)] end +function nearStations(nobj, compareStationList) --nobj = named object for comparison purposes --compareStationList = list of stations to compare against -function nearStations(nobj, compareStationList) remainingStations = {} closestDistance = 9999999 for ri, obj in ipairs(compareStationList) do @@ -4256,10 +5498,10 @@ function nearStations(nobj, compareStationList) end return closest, remainingStations end +function randomNearStation(pool,nobj,partialStationList) --pool = number of nearest stations to randomly choose from --nobj = named object for comparison purposes --partialStationList = list of station to compare against -function randomNearStation(pool,nobj,partialStationList) distanceStations = {} rs = {} cs, rs[1] = nearStations(nobj,partialStationList) @@ -4410,13 +5652,6 @@ function independentTransportPlot(delta) obj = CpuShip():setTemplate(name):setFaction('Independent'):setCommsScript(""):setCommsFunction(commsShip) obj.target = target obj.undock_delay = irandom(1,4) - rifl = math.floor(random(1,#goodsList)) -- random item from list - goodsType = goodsList[rifl][1] - if goodsType == nil then - goodsType = "nickel" - end - rcoi = math.floor(random(30,90)) -- random cost of item - goods[obj] = {{goodsType,1,rcoi}} obj:orderDock(obj.target) x, y = obj.target:getPosition() xd, yd = vectorFromAngle(random(0, 360), random(25000, 40000)) @@ -4425,9 +5660,9 @@ function independentTransportPlot(delta) end end end ---[[------------------------------------------------------------------- - Junk Yard Billboard Plot ---]]------------------------------------------------------------------- +-------------------------------- +-- Junk Yard Billboard Plot -- +-------------------------------- function billboardUpdate(delta) signsScanned = 0 if playerFighter ~= nil and playerFighter:isValid() then @@ -4478,65 +5713,149 @@ function billboardFlash(delta) flashTimer = delta + 5 end end ---[[------------------------------------------------------------------- - Ship Health Plot ---]]------------------------------------------------------------------- +------------------------ +-- Ship Health Plot -- +------------------------ function shipHealth(delta) playerShipHealth(delta) enemyShipHealth(delta) end ---fighter player ship health function scragHealth(delta) +--fighter player ship health if playerFighter:getSystemHealth("reactor") > playerFighter.maxReactor then playerFighter:setSystemHealth("reactor",playerFighter.maxReactor) + if playerFighter.reactor_max_message == nil then + if playerFighter:hasPlayerAtPosition("Engineering") then + playerFighter.reactor_max_message = "reactor_max_message" + playerFighter:addCustomMessage("Engineering",playerFighter.reactor_max_message,"Reached maximum repair on reactor") + end + end end if playerFighter:getSystemHealth("beamweapons") > playerFighter.maxBeam then playerFighter:setSystemHealth("beamweapons",playerFighter.maxBeam) + if playerFighter.beamweapons_max_message == nil then + if playerFighter:hasPlayerAtPosition("Engineering") then + playerFighter.beamweapons_max_message = "beamweapons_max_message" + playerFighter:addCustomMessage("Engineering",playerFighter.beamweapons_max_message,"Reached maximum repair on beam weapons") + end + end end if playerFighter:getSystemHealth("maneuver") > playerFighter.maxManeuver then playerFighter:setSystemHealth("maneuver",playerFighter.maxManeuver) + if playerFighter.maneuver_max_message == nil then + if playerFighter:hasPlayerAtPosition("Engineering") then + playerFighter.maneuver_max_message = "maneuver_max_message" + playerFighter:addCustomMessage("Engineering",playerFighter.maneuver_max_message,"Reached maximum repair on maneuver") + end + end end if playerFighter:getSystemHealth("impulse") > playerFighter.maxImpulse then playerFighter:setSystemHealth("impulse",playerFighter.maxImpulse) + if playerFighter.impulse_max_message == nil then + if playerFighter:hasPlayerAtPosition("Engineering") then + playerFighter.impulse_max_message = "impulse_max_message" + playerFighter:addCustomMessage("Engineering",playerFighter.impulse_max_message,"Reached maximum repair on impulse engines") + end + end end if playerFighter:getSystemHealth("frontshield") > playerFighter.maxFrontShield then playerFighter:setSystemHealth("frontshield",playerFighter.maxFrontShield) + if playerFighter.frontshield_max_message == nil then + if playerFighter:hasPlayerAtPosition("Engineering") then + playerFighter.frontshield_max_message = "frontshield_max_message" + playerFighter:addCustomMessage("Engineering",playerFighter.frontshield_max_message,"Reached maximum repair on shields") + end + end end end ---repulse player ship health function plunderHealth(delta) +--repulse player ship health if playerRepulse ~= nil and playerRepulse:isValid() then if playerRepulse:getSystemHealth("reactor") > playerRepulse.maxReactor then playerRepulse:setSystemHealth("reactor",playerRepulse.maxReactor) + if playerRepulse.reactor_max_message == nil then + if playerRepulse:hasPlayerAtPosition("Engineering") then + playerRepulse.reactor_max_message = "reactor_max_message" + playerRepulse:addCustomMessage("Engineering",playerRepulse.reactor_max_message,"Reached maximum repair on reactor") + end + end end if playerRepulse:getSystemHealth("beamweapons") > playerRepulse.maxBeam then playerRepulse:setSystemHealth("beamweapons",playerRepulse.maxBeam) + if playerRepulse.beamweapons_max_message == nil then + if playerRepulse:hasPlayerAtPosition("Engineering") then + playerRepulse.beamweapons_max_message = "beamweapons_max_message" + playerRepulse:addCustomMessage("Engineering",playerRepulse.beamweapons_max_message,"Reached maximum repair on beam weapons") + end + end end if playerRepulse:getSystemHealth("maneuver") > playerRepulse.maxManeuver then playerRepulse:setSystemHealth("maneuver",playerRepulse.maxManeuver) + if playerRepulse.maneuver_max_message == nil then + if playerRepulse:hasPlayerAtPosition("Engineering") then + playerRepulse.maneuver_max_message = "maneuver_max_message" + playerRepulse:addCustomMessage("Engineering",playerRepulse.maneuver_max_message,"Reached maximum repair on maneuver") + end + end end if playerRepulse:getSystemHealth("missilesystem") > playerRepulse.maxMissile then playerRepulse:setSystemHealth("missilesystem",playerRepulse.maxMissile) + if playerRepulse.missilesystem_max_message == nil then + if playerRepulse:hasPlayerAtPosition("Engineering") then + playerRepulse.missilesystem_max_message = "missilesystem_max_message" + playerRepulse:addCustomMessage("Engineering",playerRepulse.missilesystem_max_message,"Reached maximum repair on missile weapons") + end + end end if playerRepulse:getSystemHealth("impulse") > playerRepulse.maxImpulse then playerRepulse:setSystemHealth("impulse",playerRepulse.maxImpulse) + if playerRepulse.impulse_max_message == nil then + if playerRepulse:hasPlayerAtPosition("Engineering") then + playerRepulse.impulse_max_message = "impulse_max_message" + playerRepulse:addCustomMessage("Engineering",playerRepulse.impulse_max_message,"Reached maximum repair on impulse engines") + end + end end if playerRepulse:getSystemHealth("warp") > playerRepulse.maxWarp then playerRepulse:setSystemHealth("warp",playerRepulse.maxWarp) + if playerRepulse.warp_max_message == nil then + if playerRepulse:hasPlayerAtPosition("Engineering") then + playerRepulse.warp_max_message = "warp_max_message" + playerRepulse:addCustomMessage("Engineering",playerRepulse.warp_max_message,"Reached maximum repair on warp drive") + end + end end if playerRepulse:getSystemHealth("jumpdrive") > playerRepulse.maxJump then playerRepulse:setSystemHealth("jumpdrive",playerRepulse.maxJump) + if playerRepulse.jumpdrive_max_message == nil then + if playerRepulse:hasPlayerAtPosition("Engineering") then + playerRepulse.jumpdrive_max_message = "jumpdrive_max_message" + playerRepulse:addCustomMessage("Engineering",playerRepulse.jumpdrive_max_message,"Reached maximum repair on jump drive") + end + end end if playerRepulse:getSystemHealth("frontshield") > playerRepulse.maxFrontShield then playerRepulse:setSystemHealth("frontshield",playerRepulse.maxFrontShield) + if playerRepulse.frontshield_max_message == nil then + if playerRepulse:hasPlayerAtPosition("Engineering") then + playerRepulse.frontshield_max_message = "frontshield_max_message" + playerRepulse:addCustomMessage("Engineering",playerRepulse.frontshield_max_message,"Reached maximum repair on front shield") + end + end end if playerRepulse:getSystemHealth("rearshield") > playerRepulse.maxRearShield then playerRepulse:setSystemHealth("rearshield",playerRepulse.maxRearShield) + if playerRepulse.rearshield_max_message == nil then + if playerRepulse:hasPlayerAtPosition("Engineering") then + playerRepulse.rearshield_max_message = "rearshield_max_message" + playerRepulse:addCustomMessage("Engineering",playerRepulse.rearshield_max_message,"Reached maximum repair on rear shield") + end + end end end end ---other ship health function enemyShipHealth(delta) +--other ship health for i=1,#junkShips do if junkShips[i]:isValid() then if junkShips[i]:getSystemHealth("reactor") > junkShips[i].maxReactor then @@ -4570,6 +5889,7 @@ function enemyShipHealth(delta) end end function update(delta) + --print("Update: Orbits") bobsx, bobsy = vectorFromAngle(stationWig.angle,3000) stationWig:setPosition(bwx+bobsx,bwy+bobsy):setRotation(stationWig.angle) stationWig.angle = stationWig.angle + .02 diff --git a/scripts/scenario_54_PatrolDuty.lua b/scripts/scenario_54_PatrolDuty.lua index de53a505a1..002a7b4d6d 100755 --- a/scripts/scenario_54_PatrolDuty.lua +++ b/scripts/scenario_54_PatrolDuty.lua @@ -146,6 +146,8 @@ function init() difficultySettingList = {"Easy", "Normal", "Hard", "Self-Destructive"} difficultyIndex = 2 --default to normal difficulty difficulty = difficultyList[difficultyIndex] + prefix_length = 0 + suffix_index = 0 setVariations() playerCount = 0 --Ship Template Name List @@ -2684,6 +2686,7 @@ function transportPlot(delta) x, y = obj.target:getPosition() xd, yd = vectorFromAngle(random(0, 360), random(25000, 40000)) obj:setPosition(x + xd, y + yd) + obj:setCallSign(generateCallSign(nil,"Independent")) table.insert(transportList, obj) end end @@ -3273,7 +3276,7 @@ function handleDockedState() end end end - if ctd.trade.food and comms_source.goods ~= nil and comms_source.goods.food ~= nil and comms_source.goods.food.quantity > 0 then + if ctd.trade.food and comms_source.goods ~= nil and comms_source.goods["food"] ~= nil and comms_source.goods["food"] > 0 then for good, goodData in pairs(ctd.goods) do addCommsReply(string.format("Trade food for %s",good), function() local goodTransactionMessage = string.format("Type: %s, Quantity: %i",good,goodData["quantity"]) @@ -3296,7 +3299,7 @@ function handleDockedState() end) end end - if ctd.trade.medicine and comms_source.goods ~= nil and comms_source.goods.medicine ~= nil and comms_source.goods.medicine.quantity > 0 then + if ctd.trade.medicine and comms_source.goods ~= nil and comms_source.goods["medicine"] ~= nil and comms_source.goods["medicine"] > 0 then for good, goodData in pairs(ctd.goods) do addCommsReply(string.format("Trade medicine for %s",good), function() local goodTransactionMessage = string.format("Type: %s, Quantity: %i",good,goodData["quantity"]) @@ -3319,7 +3322,7 @@ function handleDockedState() end) end end - if ctd.trade.luxury and comms_source.goods ~= nil and comms_source.goods.luxury ~= nil and comms_source.goods.luxury.quantity > 0 then + if ctd.trade.luxury and comms_source.goods ~= nil and comms_source.goods["luxury"] ~= nil and comms_source.goods["luxury"] > 0 then for good, goodData in pairs(ctd.goods) do addCommsReply(string.format("Trade luxury for %s",good), function() local goodTransactionMessage = string.format("Type: %s, Quantity: %i",good,goodData["quantity"]) @@ -3537,7 +3540,7 @@ function handleDockedState() comms_source.goods[comms_source.artifactUpgradePart] = comms_source.goods[comms_source.artifactUpgradePart] - 1 comms_source.cargo = comms_source.cargo + 1 artifactUpgrade() - setCommsMessage(string.format("We needed that %2, thanks. Your maneuverability has been significantly improved",comms_source.artifactUpgradePart)) + setCommsMessage(string.format("We needed that %s, thanks. Your maneuverability has been significantly improved",comms_source.artifactUpgradePart)) else setCommsMessage(string.format("To upgrade, we need you to bring us some %s",comms_source.artifactUpgradePart)) end @@ -3987,6 +3990,7 @@ function handleUndockedState() else legAverage = (comms_source.patrolLegAsimov + comms_source.patrolLegUtopiaPlanitia + comms_source.patrolLegArmstrong)/3 ordMsg = ordMsg .. string.format("\n patrol is %.2f percent complete",legAverage/patrolGoal*100) + --print(string.format("Av legs: %i, UP legs: %i, Ag legs: %i, Avg: %.1f, Goal: %i",comms_source.patrolLegAsimov,comms_source.patrolLegUtopiaPlanitia,comms_source.patrolLegArmstrong,legAverage,patrolGoal)) if comms_source.patrolLegArmstrong ~= comms_source.patrolLegAsimov or comms_source.patrolLegUtopiaPlanitia ~= comms_source.patrolLegArmstrong then if comms_source.patrolLegArmstrong == comms_source.patrolLegAsimov then if comms_source.patrolLegArmstrong > comms_source.patrolLegUtopiaPlanitia then @@ -4083,17 +4087,27 @@ function commsShip() comms_data = comms_target.comms_data if comms_data.goods == nil then comms_data.goods = {} - comms_data.goods[commonGoods[math.random(1,#commonGoods)]] = {quantity = 1, cost = random(20,80)} + if random(1,100) < 50 then + comms_data.goods[mineralGoods[math.random(1,#mineralGoods)]] = {quantity = 1, cost = random(20,80)} + else + comms_data.goods[componentGoods[math.random(1,#componentGoods)]] = {quantity = 1, cost = random(20,80)} + end local shipType = comms_target:getTypeName() local goodCount = 0 if shipType:find("Freighter") ~= nil then if shipType:find("Goods") ~= nil then repeat - comms_data.goods[commonGoods[math.random(1,#commonGoods)]] = {quantity = 1, cost = random(20,80)} goodCount = 0 for good, goodData in pairs(comms_data.goods) do goodCount = goodCount + 1 end + if good_count == 1 then + comms_data.goods[mineralGoods[math.random(1,#mineralGoods)]] = {quantity = 1, cost = random(20,80)} + elseif good_count == 2 then + comms_data.goods[componentGoods[math.random(1,#componentGoods)]] = {quantity = 1, cost = random(20,80)} + else + comms_data.goods[commonGoods[math.random(1,#commonGoods)]] = {quantity = 1, cost = random(20,80)} + end until(goodCount >= 3) elseif shipType:find("Equipment") ~= nil then repeat @@ -4416,6 +4430,504 @@ function neutralComms(comms_data) end return true end +------------------------------------ +-- Generate call sign functions -- +------------------------------------ +function generateCallSign(prefix,faction) + if faction == nil then + if prefix == nil then + prefix = generateCallSignPrefix() + end + else + if prefix == nil then + prefix = getFactionPrefix(faction) + else + prefix = string.format("%s %s",getFactionPrefix(faction),prefix) + end + end + suffix_index = suffix_index + math.random(1,3) + if suffix_index > 999 then + suffix_index = 1 + end + return string.format("%s%i",prefix,suffix_index) +end +function generateCallSignPrefix(length) + if call_sign_prefix_pool == nil then + call_sign_prefix_pool = {} + prefix_length = prefix_length + 1 + if prefix_length > 3 then + prefix_length = 1 + end + fillPrefixPool() + end + if length == nil then + length = prefix_length + end + local prefix_index = 0 + local prefix = "" + for i=1,length do + if #call_sign_prefix_pool < 1 then + fillPrefixPool() + end + prefix_index = math.random(1,#call_sign_prefix_pool) + prefix = prefix .. call_sign_prefix_pool[prefix_index] + table.remove(call_sign_prefix_pool,prefix_index) + end + return prefix +end +function fillPrefixPool() + for i=1,26 do + table.insert(call_sign_prefix_pool,string.char(i+64)) + end +end +function getFactionPrefix(faction) + local faction_prefix = nil + if faction == "Kraylor" then + if kraylor_names == nil then + setKraylorNames() + else + if #kraylor_names < 1 then + setKraylorNames() + end + end + local kraylor_name_choice = math.random(1,#kraylor_names) + faction_prefix = kraylor_names[kraylor_name_choice] + table.remove(kraylor_names,kraylor_name_choice) + end + if faction == "Exuari" then + if exuari_names == nil then + setExuariNames() + else + if #exuari_names < 1 then + setExuariNames() + end + end + local exuari_name_choice = math.random(1,#exuari_names) + faction_prefix = exuari_names[exuari_name_choice] + table.remove(exuari_names,exuari_name_choice) + end + if faction == "Ghosts" then + if ghosts_names == nil then + setGhostsNames() + else + if #ghosts_names < 1 then + setGhostsNames() + end + end + local ghosts_name_choice = math.random(1,#ghosts_names) + faction_prefix = ghosts_names[ghosts_name_choice] + table.remove(ghosts_names,ghosts_name_choice) + end + if faction == "Independent" then + if independent_names == nil then + setIndependentNames() + else + if #independent_names < 1 then + setIndependentNames() + end + end + local independent_name_choice = math.random(1,#independent_names) + faction_prefix = independent_names[independent_name_choice] + table.remove(independent_names,independent_name_choice) + end + if faction_prefix == nil then + faction_prefix = generateCallSignPrefix() + end + return faction_prefix +end +function setGhostsNames() + ghosts_names = {} + table.insert(ghosts_names,"Abstract") + table.insert(ghosts_names,"Ada") + table.insert(ghosts_names,"Assemble") + table.insert(ghosts_names,"Assert") + table.insert(ghosts_names,"Backup") + table.insert(ghosts_names,"BASIC") + table.insert(ghosts_names,"Big Iron") + table.insert(ghosts_names,"BigEndian") + table.insert(ghosts_names,"Binary") + table.insert(ghosts_names,"Bit") + table.insert(ghosts_names,"Block") + table.insert(ghosts_names,"Boot") + table.insert(ghosts_names,"Branch") + table.insert(ghosts_names,"BTree") + table.insert(ghosts_names,"Bubble") + table.insert(ghosts_names,"Byte") + table.insert(ghosts_names,"Capacitor") + table.insert(ghosts_names,"Case") + table.insert(ghosts_names,"Chad") + table.insert(ghosts_names,"Charge") + table.insert(ghosts_names,"COBOL") + table.insert(ghosts_names,"Collate") + table.insert(ghosts_names,"Compile") + table.insert(ghosts_names,"Control") + table.insert(ghosts_names,"Construct") + table.insert(ghosts_names,"Cycle") + table.insert(ghosts_names,"Data") + table.insert(ghosts_names,"Debug") + table.insert(ghosts_names,"Decimal") + table.insert(ghosts_names,"Decision") + table.insert(ghosts_names,"Default") + table.insert(ghosts_names,"DIMM") + table.insert(ghosts_names,"Displacement") + table.insert(ghosts_names,"Edge") + table.insert(ghosts_names,"Exit") + table.insert(ghosts_names,"Factor") + table.insert(ghosts_names,"Flag") + table.insert(ghosts_names,"Float") + table.insert(ghosts_names,"Flow") + table.insert(ghosts_names,"FORTRAN") + table.insert(ghosts_names,"Fullword") + table.insert(ghosts_names,"GIGO") + table.insert(ghosts_names,"Graph") + table.insert(ghosts_names,"Hack") + table.insert(ghosts_names,"Hash") + table.insert(ghosts_names,"Halfword") + table.insert(ghosts_names,"Hertz") + table.insert(ghosts_names,"Hexadecimal") + table.insert(ghosts_names,"Indicator") + table.insert(ghosts_names,"Initialize") + table.insert(ghosts_names,"Integer") + table.insert(ghosts_names,"Integrate") + table.insert(ghosts_names,"Interrupt") + table.insert(ghosts_names,"Java") + table.insert(ghosts_names,"Lisp") + table.insert(ghosts_names,"List") + table.insert(ghosts_names,"Logic") + table.insert(ghosts_names,"Loop") + table.insert(ghosts_names,"Lua") + table.insert(ghosts_names,"Magnetic") + table.insert(ghosts_names,"Mask") + table.insert(ghosts_names,"Memory") + table.insert(ghosts_names,"Mnemonic") + table.insert(ghosts_names,"Micro") + table.insert(ghosts_names,"Model") + table.insert(ghosts_names,"Nibble") + table.insert(ghosts_names,"Octal") + table.insert(ghosts_names,"Order") + table.insert(ghosts_names,"Operator") + table.insert(ghosts_names,"Parameter") + table.insert(ghosts_names,"Pascal") + table.insert(ghosts_names,"Pattern") + table.insert(ghosts_names,"Pixel") + table.insert(ghosts_names,"Point") + table.insert(ghosts_names,"Polygon") + table.insert(ghosts_names,"Port") + table.insert(ghosts_names,"Process") + table.insert(ghosts_names,"RAM") + table.insert(ghosts_names,"Raster") + table.insert(ghosts_names,"Rate") + table.insert(ghosts_names,"Redundant") + table.insert(ghosts_names,"Reference") + table.insert(ghosts_names,"Refresh") + table.insert(ghosts_names,"Register") + table.insert(ghosts_names,"Resistor") + table.insert(ghosts_names,"ROM") + table.insert(ghosts_names,"Routine") + table.insert(ghosts_names,"Ruby") + table.insert(ghosts_names,"SAAS") + table.insert(ghosts_names,"Sequence") + table.insert(ghosts_names,"Share") + table.insert(ghosts_names,"Silicon") + table.insert(ghosts_names,"SIMM") + table.insert(ghosts_names,"Socket") + table.insert(ghosts_names,"Sort") + table.insert(ghosts_names,"Structure") + table.insert(ghosts_names,"Switch") + table.insert(ghosts_names,"Symbol") + table.insert(ghosts_names,"Trace") + table.insert(ghosts_names,"Transistor") + table.insert(ghosts_names,"Value") + table.insert(ghosts_names,"Vector") + table.insert(ghosts_names,"Version") + table.insert(ghosts_names,"View") + table.insert(ghosts_names,"WYSIWYG") + table.insert(ghosts_names,"XOR") +end +function setExuariNames() + exuari_names = {} + table.insert(exuari_names,"Astonester") + table.insert(exuari_names,"Ametripox") + table.insert(exuari_names,"Bakeltevex") + table.insert(exuari_names,"Baropledax") + table.insert(exuari_names,"Batongomox") + table.insert(exuari_names,"Bekilvimix") + table.insert(exuari_names,"Benoglopok") + table.insert(exuari_names,"Bilontipur") + table.insert(exuari_names,"Bolictimik") + table.insert(exuari_names,"Bomagralax") + table.insert(exuari_names,"Buteldefex") + table.insert(exuari_names,"Catondinab") + table.insert(exuari_names,"Chatorlonox") + table.insert(exuari_names,"Culagromik") + table.insert(exuari_names,"Dakimbinix") + table.insert(exuari_names,"Degintalix") + table.insert(exuari_names,"Dimabratax") + table.insert(exuari_names,"Dokintifix") + table.insert(exuari_names,"Dotandirex") + table.insert(exuari_names,"Dupalgawax") + table.insert(exuari_names,"Ekoftupex") + table.insert(exuari_names,"Elidranov") + table.insert(exuari_names,"Fakobrovox") + table.insert(exuari_names,"Femoplabix") + table.insert(exuari_names,"Fibatralax") + table.insert(exuari_names,"Fomartoran") + table.insert(exuari_names,"Gateldepex") + table.insert(exuari_names,"Gamutrewal") + table.insert(exuari_names,"Gesanterux") + table.insert(exuari_names,"Gimardanax") + table.insert(exuari_names,"Hamintinal") + table.insert(exuari_names,"Holangavak") + table.insert(exuari_names,"Igolpafik") + table.insert(exuari_names,"Inoklomat") + table.insert(exuari_names,"Jamewtibex") + table.insert(exuari_names,"Jepospagox") + table.insert(exuari_names,"Kajortonox") + table.insert(exuari_names,"Kapogrinix") + table.insert(exuari_names,"Kelitravax") + table.insert(exuari_names,"Kipaldanax") + table.insert(exuari_names,"Kodendevex") + table.insert(exuari_names,"Kotelpedex") + table.insert(exuari_names,"Kutandolak") + table.insert(exuari_names,"Lakirtinix") + table.insert(exuari_names,"Lapoldinek") + table.insert(exuari_names,"Lavorbonox") + table.insert(exuari_names,"Letirvinix") + table.insert(exuari_names,"Lowibromax") + table.insert(exuari_names,"Makintibix") + table.insert(exuari_names,"Makorpohox") + table.insert(exuari_names,"Matoprowox") + table.insert(exuari_names,"Mefinketix") + table.insert(exuari_names,"Motandobak") + table.insert(exuari_names,"Nakustunux") + table.insert(exuari_names,"Nequivonax") + table.insert(exuari_names,"Nitaldavax") + table.insert(exuari_names,"Nobaldorex") + table.insert(exuari_names,"Obimpitix") + table.insert(exuari_names,"Owaklanat") + table.insert(exuari_names,"Pakendesik") + table.insert(exuari_names,"Pazinderix") + table.insert(exuari_names,"Pefoglamuk") + table.insert(exuari_names,"Pekirdivix") + table.insert(exuari_names,"Potarkadax") + table.insert(exuari_names,"Pulendemex") + table.insert(exuari_names,"Quatordunix") + table.insert(exuari_names,"Rakurdumux") + table.insert(exuari_names,"Ralombenik") + table.insert(exuari_names,"Regosporak") + table.insert(exuari_names,"Retordofox") + table.insert(exuari_names,"Rikondogox") + table.insert(exuari_names,"Rokengelex") + table.insert(exuari_names,"Rutarkadax") + table.insert(exuari_names,"Sakeldepex") + table.insert(exuari_names,"Setiftimix") + table.insert(exuari_names,"Siparkonal") + table.insert(exuari_names,"Sopaldanax") + table.insert(exuari_names,"Sudastulux") + table.insert(exuari_names,"Takeftebex") + table.insert(exuari_names,"Taliskawit") + table.insert(exuari_names,"Tegundolex") + table.insert(exuari_names,"Tekintipix") + table.insert(exuari_names,"Tiposhomox") + table.insert(exuari_names,"Tokaldapax") + table.insert(exuari_names,"Tomuglupux") + table.insert(exuari_names,"Tufeldepex") + table.insert(exuari_names,"Unegremek") + table.insert(exuari_names,"Uvendipax") + table.insert(exuari_names,"Vatorgopox") + table.insert(exuari_names,"Venitribix") + table.insert(exuari_names,"Vobalterix") + table.insert(exuari_names,"Wakintivix") + table.insert(exuari_names,"Wapaltunix") + table.insert(exuari_names,"Wekitrolax") + table.insert(exuari_names,"Wofarbanax") + table.insert(exuari_names,"Xeniplofek") + table.insert(exuari_names,"Yamaglevik") + table.insert(exuari_names,"Yakildivix") + table.insert(exuari_names,"Yegomparik") + table.insert(exuari_names,"Zapondehex") + table.insert(exuari_names,"Zikandelat") +end +function setKraylorNames() + kraylor_names = {} + table.insert(kraylor_names,"Abroten") + table.insert(kraylor_names,"Ankwar") + table.insert(kraylor_names,"Bakrik") + table.insert(kraylor_names,"Belgor") + table.insert(kraylor_names,"Benkop") + table.insert(kraylor_names,"Blargvet") + table.insert(kraylor_names,"Bloktarg") + table.insert(kraylor_names,"Bortok") + table.insert(kraylor_names,"Bredjat") + table.insert(kraylor_names,"Chankret") + table.insert(kraylor_names,"Chatork") + table.insert(kraylor_names,"Chokarp") + table.insert(kraylor_names,"Cloprak") + table.insert(kraylor_names,"Coplek") + table.insert(kraylor_names,"Cortek") + table.insert(kraylor_names,"Daltok") + table.insert(kraylor_names,"Darpik") + table.insert(kraylor_names,"Dastek") + table.insert(kraylor_names,"Dotark") + table.insert(kraylor_names,"Drambok") + table.insert(kraylor_names,"Duntarg") + table.insert(kraylor_names,"Earklat") + table.insert(kraylor_names,"Ekmit") + table.insert(kraylor_names,"Fakret") + table.insert(kraylor_names,"Fapork") + table.insert(kraylor_names,"Fawtrik") + table.insert(kraylor_names,"Fenturp") + table.insert(kraylor_names,"Feplik") + table.insert(kraylor_names,"Figront") + table.insert(kraylor_names,"Floktrag") + table.insert(kraylor_names,"Fonkack") + table.insert(kraylor_names,"Fontreg") + table.insert(kraylor_names,"Foondrap") + table.insert(kraylor_names,"Frotwak") + table.insert(kraylor_names,"Gastonk") + table.insert(kraylor_names,"Gentouk") + table.insert(kraylor_names,"Gonpruk") + table.insert(kraylor_names,"Gortak") + table.insert(kraylor_names,"Gronkud") + table.insert(kraylor_names,"Hewtang") + table.insert(kraylor_names,"Hongtag") + table.insert(kraylor_names,"Hortook") + table.insert(kraylor_names,"Indrut") + table.insert(kraylor_names,"Iprant") + table.insert(kraylor_names,"Jakblet") + table.insert(kraylor_names,"Jonket") + table.insert(kraylor_names,"Jontot") + table.insert(kraylor_names,"Kandarp") + table.insert(kraylor_names,"Kantrok") + table.insert(kraylor_names,"Kiptak") + table.insert(kraylor_names,"Kortrant") + table.insert(kraylor_names,"Krontgat") + table.insert(kraylor_names,"Lobreck") + table.insert(kraylor_names,"Lokrant") + table.insert(kraylor_names,"Lomprok") + table.insert(kraylor_names,"Lutrank") + table.insert(kraylor_names,"Makrast") + table.insert(kraylor_names,"Moklahft") + table.insert(kraylor_names,"Morpug") + table.insert(kraylor_names,"Nagblat") + table.insert(kraylor_names,"Nokrat") + table.insert(kraylor_names,"Nomek") + table.insert(kraylor_names,"Notark") + table.insert(kraylor_names,"Ontrok") + table.insert(kraylor_names,"Orkpent") + table.insert(kraylor_names,"Peechak") + table.insert(kraylor_names,"Plogrent") + table.insert(kraylor_names,"Pokrint") + table.insert(kraylor_names,"Potarg") + table.insert(kraylor_names,"Prangtil") + table.insert(kraylor_names,"Quagbrok") + table.insert(kraylor_names,"Quimprill") + table.insert(kraylor_names,"Reekront") + table.insert(kraylor_names,"Ripkort") + table.insert(kraylor_names,"Rokust") + table.insert(kraylor_names,"Rontrait") + table.insert(kraylor_names,"Saknep") + table.insert(kraylor_names,"Sengot") + table.insert(kraylor_names,"Skitkard") + table.insert(kraylor_names,"Skopgrek") + table.insert(kraylor_names,"Sletrok") + table.insert(kraylor_names,"Slorknat") + table.insert(kraylor_names,"Spogrunk") + table.insert(kraylor_names,"Staklurt") + table.insert(kraylor_names,"Stonkbrant") + table.insert(kraylor_names,"Swaktrep") + table.insert(kraylor_names,"Tandrok") + table.insert(kraylor_names,"Takrost") + table.insert(kraylor_names,"Tonkrut") + table.insert(kraylor_names,"Torkrot") + table.insert(kraylor_names,"Trablok") + table.insert(kraylor_names,"Trokdin") + table.insert(kraylor_names,"Unkelt") + table.insert(kraylor_names,"Urjop") + table.insert(kraylor_names,"Vankront") + table.insert(kraylor_names,"Vintrep") + table.insert(kraylor_names,"Volkerd") + table.insert(kraylor_names,"Vortread") + table.insert(kraylor_names,"Wickurt") + table.insert(kraylor_names,"Xokbrek") + table.insert(kraylor_names,"Yeskret") + table.insert(kraylor_names,"Zacktrope") +end +function setIndependentNames() + independent_names = {} + table.insert(independent_names,"Akdroft") --faux Kraylor + table.insert(independent_names,"Bletnik") --faux Kraylor + table.insert(independent_names,"Brogfent") --faux Kraylor + table.insert(independent_names,"Cruflech") --faux Kraylor + table.insert(independent_names,"Dengtoct") --faux Kraylor + table.insert(independent_names,"Fiklerg") --faux Kraylor + table.insert(independent_names,"Groftep") --faux Kraylor + table.insert(independent_names,"Hinkflort") --faux Kraylor + table.insert(independent_names,"Irklesht") --faux Kraylor + table.insert(independent_names,"Jotrak") --faux Kraylor + table.insert(independent_names,"Kargleth") --faux Kraylor + table.insert(independent_names,"Lidroft") --faux Kraylor + table.insert(independent_names,"Movrect") --faux Kraylor + table.insert(independent_names,"Nitrang") --faux Kraylor + table.insert(independent_names,"Poklapt") --faux Kraylor + table.insert(independent_names,"Raknalg") --faux Kraylor + table.insert(independent_names,"Stovtuk") --faux Kraylor + table.insert(independent_names,"Trongluft") --faux Kraylor + table.insert(independent_names,"Vactremp") --faux Kraylor + table.insert(independent_names,"Wunklesp") --faux Kraylor + table.insert(independent_names,"Yentrilg") --faux Kraylor + table.insert(independent_names,"Zeltrag") --faux Kraylor + table.insert(independent_names,"Avoltojop") --faux Exuari + table.insert(independent_names,"Bimartarax") --faux Exuari + table.insert(independent_names,"Cidalkapax") --faux Exuari + table.insert(independent_names,"Darongovax") --faux Exuari + table.insert(independent_names,"Felistiyik") --faux Exuari + table.insert(independent_names,"Gopendewex") --faux Exuari + table.insert(independent_names,"Hakortodox") --faux Exuari + table.insert(independent_names,"Jemistibix") --faux Exuari + table.insert(independent_names,"Kilampafax") --faux Exuari + table.insert(independent_names,"Lokuftumux") --faux Exuari + table.insert(independent_names,"Mabildirix") --faux Exuari + table.insert(independent_names,"Notervelex") --faux Exuari + table.insert(independent_names,"Pekolgonex") --faux Exuari + table.insert(independent_names,"Rifaltabax") --faux Exuari + table.insert(independent_names,"Sobendeyex") --faux Exuari + table.insert(independent_names,"Tinaftadax") --faux Exuari + table.insert(independent_names,"Vadorgomax") --faux Exuari + table.insert(independent_names,"Wilerpejex") --faux Exuari + table.insert(independent_names,"Yukawvalak") --faux Exuari + table.insert(independent_names,"Zajiltibix") --faux Exuari + table.insert(independent_names,"Alter") --faux Ghosts + table.insert(independent_names,"Assign") --faux Ghosts + table.insert(independent_names,"Brain") --faux Ghosts + table.insert(independent_names,"Break") --faux Ghosts + table.insert(independent_names,"Boundary") --faux Ghosts + table.insert(independent_names,"Code") --faux Ghosts + table.insert(independent_names,"Compare") --faux Ghosts + table.insert(independent_names,"Continue") --faux Ghosts + table.insert(independent_names,"Core") --faux Ghosts + table.insert(independent_names,"CRUD") --faux Ghosts + table.insert(independent_names,"Decode") --faux Ghosts + table.insert(independent_names,"Decrypt") --faux Ghosts + table.insert(independent_names,"Device") --faux Ghosts + table.insert(independent_names,"Encode") --faux Ghosts + table.insert(independent_names,"Encrypt") --faux Ghosts + table.insert(independent_names,"Event") --faux Ghosts + table.insert(independent_names,"Fetch") --faux Ghosts + table.insert(independent_names,"Frame") --faux Ghosts + table.insert(independent_names,"Go") --faux Ghosts + table.insert(independent_names,"IO") --faux Ghosts + table.insert(independent_names,"Interface") --faux Ghosts + table.insert(independent_names,"Kilo") --faux Ghosts + table.insert(independent_names,"Modify") --faux Ghosts + table.insert(independent_names,"Pin") --faux Ghosts + table.insert(independent_names,"Program") --faux Ghosts + table.insert(independent_names,"Purge") --faux Ghosts + table.insert(independent_names,"Retrieve") --faux Ghosts + table.insert(independent_names,"Store") --faux Ghosts + table.insert(independent_names,"Unit") --faux Ghosts + table.insert(independent_names,"Wire") --faux Ghosts +end ------------------------------------------------------------- -- First plot line - patrol between stations then defend -- ------------------------------------------------------------- @@ -4453,7 +4965,6 @@ function patrolAsimovUtopiaPlanitiaArmstrong(delta) plot1 = defeated end end - patrolComplete = false playerCount = 0 for p5idx=1,8 do p5obj = getPlayerShip(p5idx) @@ -6073,6 +6584,7 @@ function spawnEnemies(xOrigin, yOrigin, danger, enemyFaction) ship:setPosition(xOrigin+fleetPosDelta2x[enemyPosition]*sp,yOrigin+fleetPosDelta2y[enemyPosition]*sp) end table.insert(enemyList, ship) + ship:setCallSign(generateCallSign(nil,enemyFaction)) enemyStrength = enemyStrength - stsl[shipTemplateType] end return enemyList @@ -6171,7 +6683,28 @@ function healthCheck(delta) healthCheckTimer = delta + healthCheckTimerInterval end end - +function resetPreviousSystemHealth(p) + if p:getShieldCount() > 1 then + p.prevShield = (p:getSystemHealth("frontshield") + p:getSystemHealth("rearshield"))/2 + else + p.prevShield = p:getSystemHealth("frontshield") + end + p.prevReactor = p:getSystemHealth("reactor") + p.prevManeuver = p:getSystemHealth("maneuver") + p.prevImpulse = p:getSystemHealth("impulse") + if p:getBeamWeaponRange(0) > 0 then + p.prevBeam = p:getSystemHealth("beamweapons") + end + if p:getWeaponTubeCount() > 0 then + p.prevMissile = p:getSystemHealth("missilesystem") + end + if p:hasWarpDrive() then + p.prevWarp = p:getSystemHealth("warp") + end + if p:hasJumpDrive() then + p.prevJump = p:getSystemHealth("jumpdrive") + end +end function crewFate(p, fatalityChance) if math.random() < (fatalityChance) then p:setRepairCrewCount(p:getRepairCrewCount() - 1) diff --git a/scripts/scenario_59_border.lua b/scripts/scenario_59_border.lua index f4b8703cb2..2149f85af2 100755 --- a/scripts/scenario_59_border.lua +++ b/scripts/scenario_59_border.lua @@ -4908,7 +4908,7 @@ function spawnEnemyFleet(xOrigin, yOrigin, power, danger, enemyFaction, fleetNam ship.fleet = fleetName end table.insert(enemyList, ship) - ship:setCallSign(generateCallSign(prefix)) + ship:setCallSign(generateCallSign(nil,enemyFaction)) enemyStrength = enemyStrength - stsl[shipTemplateType] end fleetPower = math.max(fleetPower/danger/difficulty, 5) @@ -8732,7 +8732,7 @@ function spawnEnemies(xOrigin, yOrigin, danger, enemyFaction, enemyStrength) end ship:setCommsScript(""):setCommsFunction(commsShip) table.insert(enemyList, ship) - ship:setCallSign(generateCallSign(prefix)) + ship:setCallSign(generateCallSign(nil,enemyFaction)) enemyStrength = enemyStrength - stsl[shipTemplateType] end return enemyList @@ -9714,9 +9714,17 @@ function getCoolant8() getCoolantGivenPlayer(p) end -- Generate call sign functions -function generateCallSign(prefix) - if prefix == nil then - prefix = generateCallSignPrefix() +function generateCallSign(prefix,faction) + if faction == nil then + if prefix == nil then + prefix = generateCallSignPrefix() + end + else + if prefix == nil then + prefix = getFactionPrefix(faction) + else + prefix = string.format("%s %s",getFactionPrefix(faction),prefix) + end end suffix_index = suffix_index + math.random(1,3) if suffix_index > 999 then @@ -9753,6 +9761,130 @@ function fillPrefixPool() table.insert(call_sign_prefix_pool,string.char(i+64)) end end +function getFactionPrefix(faction) + local faction_prefix = nil + if faction == "Kraylor" then + if kraylor_names == nil then + setKraylorNames() + else + if #kraylor_names < 1 then + setKraylorNames() + end + end + local kraylor_name_choice = math.random(1,#kraylor_names) + faction_prefix = kraylor_names[kraylor_name_choice] + table.remove(kraylor_names,kraylor_name_choice) + end + if faction_prefix == nil then + faction_prefix = generateCallSignPrefix() + end + return faction_prefix +end +function setKraylorNames() + kraylor_names = {} + table.insert(kraylor_names,"Abroten") + table.insert(kraylor_names,"Ankwar") + table.insert(kraylor_names,"Bakrik") + table.insert(kraylor_names,"Belgor") + table.insert(kraylor_names,"Benkop") + table.insert(kraylor_names,"Blargvet") + table.insert(kraylor_names,"Bloktarg") + table.insert(kraylor_names,"Bortok") + table.insert(kraylor_names,"Bredjat") + table.insert(kraylor_names,"Chankret") + table.insert(kraylor_names,"Chatork") + table.insert(kraylor_names,"Chokarp") + table.insert(kraylor_names,"Cloprak") + table.insert(kraylor_names,"Coplek") + table.insert(kraylor_names,"Cortek") + table.insert(kraylor_names,"Daltok") + table.insert(kraylor_names,"Darpik") + table.insert(kraylor_names,"Dastek") + table.insert(kraylor_names,"Dotark") + table.insert(kraylor_names,"Drambok") + table.insert(kraylor_names,"Duntarg") + table.insert(kraylor_names,"Earklat") + table.insert(kraylor_names,"Ekmit") + table.insert(kraylor_names,"Fakret") + table.insert(kraylor_names,"Fapork") + table.insert(kraylor_names,"Fawtrik") + table.insert(kraylor_names,"Fenturp") + table.insert(kraylor_names,"Feplik") + table.insert(kraylor_names,"Figront") + table.insert(kraylor_names,"Floktrag") + table.insert(kraylor_names,"Fonkack") + table.insert(kraylor_names,"Fontreg") + table.insert(kraylor_names,"Foondrap") + table.insert(kraylor_names,"Frotwak") + table.insert(kraylor_names,"Gastonk") + table.insert(kraylor_names,"Gentouk") + table.insert(kraylor_names,"Gonpruk") + table.insert(kraylor_names,"Gortak") + table.insert(kraylor_names,"Gronkud") + table.insert(kraylor_names,"Hewtang") + table.insert(kraylor_names,"Hongtag") + table.insert(kraylor_names,"Hortook") + table.insert(kraylor_names,"Indrut") + table.insert(kraylor_names,"Iprant") + table.insert(kraylor_names,"Jakblet") + table.insert(kraylor_names,"Jonket") + table.insert(kraylor_names,"Jontot") + table.insert(kraylor_names,"Kandarp") + table.insert(kraylor_names,"Kantrok") + table.insert(kraylor_names,"Kiptak") + table.insert(kraylor_names,"Kortrant") + table.insert(kraylor_names,"Krontgat") + table.insert(kraylor_names,"Lobreck") + table.insert(kraylor_names,"Lokrant") + table.insert(kraylor_names,"Lomprok") + table.insert(kraylor_names,"Lutrank") + table.insert(kraylor_names,"Makrast") + table.insert(kraylor_names,"Moklahft") + table.insert(kraylor_names,"Morpug") + table.insert(kraylor_names,"Nagblat") + table.insert(kraylor_names,"Nokrat") + table.insert(kraylor_names,"Nomek") + table.insert(kraylor_names,"Notark") + table.insert(kraylor_names,"Ontrok") + table.insert(kraylor_names,"Orkpent") + table.insert(kraylor_names,"Peechak") + table.insert(kraylor_names,"Plogrent") + table.insert(kraylor_names,"Pokrint") + table.insert(kraylor_names,"Potarg") + table.insert(kraylor_names,"Prangtil") + table.insert(kraylor_names,"Quagbrok") + table.insert(kraylor_names,"Quimprill") + table.insert(kraylor_names,"Reekront") + table.insert(kraylor_names,"Ripkort") + table.insert(kraylor_names,"Rokust") + table.insert(kraylor_names,"Rontrait") + table.insert(kraylor_names,"Saknep") + table.insert(kraylor_names,"Sengot") + table.insert(kraylor_names,"Skitkard") + table.insert(kraylor_names,"Skopgrek") + table.insert(kraylor_names,"Sletrok") + table.insert(kraylor_names,"Slorknat") + table.insert(kraylor_names,"Spogrunk") + table.insert(kraylor_names,"Staklurt") + table.insert(kraylor_names,"Stonkbrant") + table.insert(kraylor_names,"Swaktrep") + table.insert(kraylor_names,"Tandrok") + table.insert(kraylor_names,"Takrost") + table.insert(kraylor_names,"Tonkrut") + table.insert(kraylor_names,"Torkrot") + table.insert(kraylor_names,"Trablok") + table.insert(kraylor_names,"Trokdin") + table.insert(kraylor_names,"Unkelt") + table.insert(kraylor_names,"Urjop") + table.insert(kraylor_names,"Vankront") + table.insert(kraylor_names,"Vintrep") + table.insert(kraylor_names,"Volkerd") + table.insert(kraylor_names,"Vortread") + table.insert(kraylor_names,"Wickurt") + table.insert(kraylor_names,"Xokbrek") + table.insert(kraylor_names,"Yeskret") + table.insert(kraylor_names,"Zacktrope") +end -------------------- -- Plot functions -- -------------------- diff --git a/scripts/science_db.lua b/scripts/science_db.lua index 21f2471e0e..5bce5260d9 100644 --- a/scripts/science_db.lua +++ b/scripts/science_db.lua @@ -20,6 +20,12 @@ item:setLongDescription([[A wormhole, also known as an Einstein-Rosen bridge, is Wormholes are rare, and most can move objects in only one direction. Traversable wormholes, which are stable and allow for movement in both directions, are even rarer. All wormholes generate tremendous sensor activity, which an astute science officer can detect even through disruptions such as nebulae.]]) weapons = ScienceDatabase():setName('Weapons') +weapons:setLongDescription([[This database only covers the basic versions of the missiles used throughout the galaxy. + +It has been reported that some battleships started using larger variations of those missiles. Small fighters and even frigates should not have too much trouble dodging them, but space captains of bigger ships should be wary of their doubled damage potential. + +Smaller variations of these missiles have become common in the galaxy, too. Fighter pilots praise their speed and maneuverability, because it gives them an edge against small and fast-moving targets. They only deal half the damage of their basic counterparts, but what good is a missile if it does not hit its target.]]) + item = weapons:addEntry('Homing missile') item:addKeyValue('Range', '5.4u') item:addKeyValue('Damage', '35') @@ -53,8 +59,8 @@ item:setLongDescription([[The electromagnetic pulse missile (EMP) reproduces the item = weapons:addEntry('HVLI') item:addKeyValue('Range', '5.4u') -item:addKeyValue('Damage', '7 each, 35 total') +item:addKeyValue('Damage', '6 each, 30 total') item:addKeyValue('Burst', '5') item:setLongDescription([[A high-velocity lead impactor (HVLI) fires a simple slug of lead at a high velocity. This weapon is usually found in simpler ships since it does not require guidance computers. This also means its projectiles fly in a straight line from its tube and can't pursue a target. -Each shot from an HVLI fires a burst of 5 projectiles, which increases the chance to hit but requires precision aiming to be effective.]]) +Each shot from an HVLI fires a burst of 5 projectiles, which increases the chance to hit but requires precision aiming to be effective. It reaches its full damage potential at a range of 2u.]]) diff --git a/scripts/shipTemplates_StarFighters.lua b/scripts/shipTemplates_StarFighters.lua index 7c43cf77ae..b0d8c87c7f 100644 --- a/scripts/shipTemplates_StarFighters.lua +++ b/scripts/shipTemplates_StarFighters.lua @@ -30,6 +30,7 @@ variation:setBeam(0, 30, 0, 900.0, 4.0, 2.5) variation = variation:copy("MP52 Hornet"):setType("playership") variation:setDescription([[The MP52 Hornet is a significantly upgraded version of MU52 Hornet, with nearly twice the hull strength, nearly three times the shielding, better acceleration, impulse boosters, and a second laser cannon.]]) +variation:setImpulseSoundFile("sfx/engine_fighter.wav") variation:setHull(70) variation:setShields(60) variation:setSpeed(125, 32, 40) diff --git a/src/discord.cpp b/src/discord.cpp new file mode 100644 index 0000000000..8bc629a097 --- /dev/null +++ b/src/discord.cpp @@ -0,0 +1,82 @@ +#include "discord.h" +#include "playerInfo.h" +#include "gameGlobalInfo.h" +#include "spaceObjects/playerSpaceship.h" +#include + +static IDiscordCore* core; +static IDiscordActivityManager* activityManager; +static IDiscordCoreEvents events; + +static DiscordActivity previousActivity; + +DiscordRichPresence::DiscordRichPresence() +{ + DiscordCreateParams params; + params.client_id = 697525001603252304; + params.flags = DiscordCreateFlags_NoRequireDiscord; + params.events = &events; + params.event_data = nullptr; + + if (DiscordCreate(DISCORD_VERSION, ¶ms, &core) != DiscordResult_Ok) + { + LOG(WARNING) << "Discord not installed or not running. Not using discord rich presence"; + return; + } + + activityManager = core->get_activity_manager(core); +} + +void DiscordRichPresence::update(float delta) +{ + if (!core) + return; + + core->run_callbacks(core); + + if (updateDelay >= 0.0f) + updateDelay -= delta; + if (updateDelay >= 0.0f) + return; + + DiscordActivity activity; + memset(&activity, 0, sizeof(activity)); + strcpy(activity.assets.large_image, "logo"); + + if (my_spaceship && my_player_info) + { + auto name = my_spaceship->getCallSign() + " [" + my_spaceship->getTypeName() + "]"; + strncpy(activity.details, name.c_str(), sizeof(activity.details)); + + for(int idx=0; idxcrew_position[idx]) + { + strncpy(activity.state, getCrewPositionName(ECrewPosition(idx)).c_str(), sizeof(activity.state)); + if (idx == helmsOfficer) + strcpy(activity.assets.small_image, "helms_white"); + if (idx == weaponsOfficer) + strcpy(activity.assets.small_image, "weapons_white"); + if (idx == engineering) + strcpy(activity.assets.small_image, "engineering_white"); + if (idx == scienceOfficer) + strcpy(activity.assets.small_image, "science_white"); + if (idx == relayOfficer) + strcpy(activity.assets.small_image, "relay_white"); + break; + } + } + if (my_player_info->isOnlyMainScreen()) + { + strncpy(activity.state, "Captain", sizeof(activity.state)); + strcpy(activity.assets.small_image, "captain_white"); + } + } + + if (memcmp(&activity, &previousActivity, sizeof(activity)) != 0) + { + activityManager->update_activity(activityManager, &activity, nullptr, nullptr); + previousActivity = activity; + updateDelay = 4.0; + } +} diff --git a/src/discord.h b/src/discord.h new file mode 100644 index 0000000000..030f9fe2f9 --- /dev/null +++ b/src/discord.h @@ -0,0 +1,17 @@ +#ifndef DISCORD_H +#define DISCORD_H + +#include "Updatable.h" + +class DiscordRichPresence : public Updatable +{ +public: + DiscordRichPresence(); + + void update(float delta) override; + +private: + float updateDelay = 0.0f; +}; + +#endif//DISCORD_H diff --git a/src/factionInfo.h b/src/factionInfo.h index b9ce1a13bf..7fac7e9399 100644 --- a/src/factionInfo.h +++ b/src/factionInfo.h @@ -16,7 +16,6 @@ enum EFactionVsFactionState class FactionInfo : public PObject { private: - int callsign_counter; public: FactionInfo(); diff --git a/src/gameGlobalInfo.cpp b/src/gameGlobalInfo.cpp index 2ceb4c70bb..e582ea6744 100644 --- a/src/gameGlobalInfo.cpp +++ b/src/gameGlobalInfo.cpp @@ -38,6 +38,7 @@ GameGlobalInfo::GameGlobalInfo() allow_main_screen_tactical_radar = true; allow_main_screen_long_range_radar = true; gm_control_code = ""; + elapsed_time = 0.0f; intercept_all_comms_to_gm = false; @@ -53,6 +54,7 @@ GameGlobalInfo::GameGlobalInfo() registerMemberReplication(&allow_main_screen_tactical_radar); registerMemberReplication(&allow_main_screen_long_range_radar); registerMemberReplication(&gm_control_code); + registerMemberReplication(&elapsed_time, 0.1); for(unsigned int n=0; ngetObjectById(my_player_info->ship_id); } } + elapsed_time += delta; } string GameGlobalInfo::getNextShipCallsign() @@ -164,6 +167,7 @@ void GameGlobalInfo::reset() } for(unsigned int n=0; nupdateRect(parent_rect); element->hover = element->rect.contains(mouse_position); + element->onUpdate(); + if (element->visible) { element->onDraw(window); @@ -118,4 +120,4 @@ bool GuiContainer::forwardJoystickAxisToElements(const AxisAction& axisAction) } } return false; -} \ No newline at end of file +} diff --git a/src/gui/gui2_element.h b/src/gui/gui2_element.h index b0d9dfe97c..9146d1bd51 100644 --- a/src/gui/gui2_element.h +++ b/src/gui/gui2_element.h @@ -46,6 +46,7 @@ class GuiElement : public GuiContainer GuiElement(GuiContainer* owner, string id); virtual ~GuiElement(); + virtual void onUpdate() {} virtual void onDraw(sf::RenderTarget& window) {} virtual bool onMouseDown(sf::Vector2f position); virtual void onMouseDrag(sf::Vector2f position); diff --git a/src/gui/gui2_image.cpp b/src/gui/gui2_image.cpp index 27fed6da73..3cf635b3f3 100644 --- a/src/gui/gui2_image.cpp +++ b/src/gui/gui2_image.cpp @@ -9,8 +9,14 @@ void GuiImage::onDraw(sf::RenderTarget& window) { sf::Sprite image; textureManager.setTexture(image, texture_name); - image.setPosition(rect.left + rect.width / 2.0, rect.top + rect.height / 2.0); - float f = rect.height / float(image.getTextureRect().height); + float f = std::min( + rect.height / float(image.getTextureRect().height), + rect.width / float(image.getTextureRect().width) + ); + if (!scale_up) { + f = std::min(f, 1.0f); + } + image.setPosition(rect.left + f * image.getTextureRect().width / 2.0, rect.top + f * image.getTextureRect().height / 2.0); image.setScale(f, f); image.setRotation(angle); image.setColor(color); diff --git a/src/gui/gui2_image.h b/src/gui/gui2_image.h index 932613d230..1a79b0a2c1 100644 --- a/src/gui/gui2_image.h +++ b/src/gui/gui2_image.h @@ -8,12 +8,17 @@ class GuiImage : public GuiElement private: sf::Color color; string texture_name; + bool scale_up = true; float angle; public: GuiImage(GuiContainer* owner, string id, string texture_name); virtual void onDraw(sf::RenderTarget& window); - + + GuiImage* setScaleUp(bool doesItScaleUp) { + this->scale_up = doesItScaleUp; + return this; + } GuiImage* setColor(sf::Color color) { this->color = color; return this; } GuiImage* setAngle(float angle) { this->angle = angle; return this; } }; diff --git a/src/main.cpp b/src/main.cpp index 9effce0a01..19859b2a49 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -28,6 +28,9 @@ #include "tutorialGame.h" #include "hardware/hardwareController.h" +#ifdef __WIN32__ +#include "discord.h" +#endif #ifdef __APPLE__ #include @@ -309,6 +312,10 @@ int main(int argc, char** argv) else hardware_controller->loadConfiguration("hardware.ini"); +#ifdef __WIN32__ + new DiscordRichPresence(); +#endif + returnToMainMenu(); engine->runMainLoop(); @@ -320,14 +327,18 @@ int main(int argc, char** argv) PreferencesManager::set("fullscreen", windowManager->isFullscreen() ? 1 : 0); } - // Set the default music_volume and sound_volume to the current volume. + // Set the default music_, sound_, and engine_volume to the current volume. PreferencesManager::set("music_volume", soundManager->getMusicVolume()); PreferencesManager::set("sound_volume", soundManager->getMasterSoundVolume()); + PreferencesManager::set("engine_volume", PreferencesManager::get("engine_volume", "50")); - // Enable music on the main screen only by default. + // Enable music and engine sounds on the main screen only by default. if (PreferencesManager::get("music_enabled").empty()) PreferencesManager::set("music_enabled", "2"); + if (PreferencesManager::get("engine_enabled").empty()) + PreferencesManager::set("engine_enabled", "2"); + // Set shaders to default. PreferencesManager::set("disable_shaders", PostProcessor::isEnabled() ? 0 : 1); diff --git a/src/math/triangulate.h b/src/math/triangulate.h index e77b8fbe05..458d8ea479 100644 --- a/src/math/triangulate.h +++ b/src/math/triangulate.h @@ -33,7 +33,7 @@ template class Triangulate if (count-- < 0) { //** Triangulate: ERROR - probable bad polygon! - delete indexes; + delete[] indexes; return false; } @@ -65,7 +65,7 @@ template class Triangulate } } - delete indexes; + delete[] indexes; return true; } diff --git a/src/menus/optionsMenu.cpp b/src/menus/optionsMenu.cpp index 078f050e99..cb5dbcbf4f 100644 --- a/src/menus/optionsMenu.cpp +++ b/src/menus/optionsMenu.cpp @@ -4,6 +4,7 @@ #include "main.h" #include "preferenceManager.h" +#include "gui/gui2_autolayout.h" #include "gui/gui2_overlay.h" #include "gui/gui2_button.h" #include "gui/gui2_togglebutton.h" @@ -20,19 +21,36 @@ OptionsMenu::OptionsMenu() new GuiOverlay(this, "", colorConfig.background); (new GuiOverlay(this, "", sf::Color::White))->setTextureTiled("gui/BackgroundCrosses"); - // Left column, manual layout. Draw first element at 50px from top. - int top = 50; + // Initialize autolayout columns. + left_container = new GuiAutoLayout(this, "OPTIONS_LEFT_CONTAINER", GuiAutoLayout::LayoutVerticalTopToBottom); + left_container->setPosition(50, 50, ATopLeft)->setSize(300, GuiElement::GuiSizeMax); - // Graphics options. - (new GuiLabel(this, "GRAPHICS_OPTIONS_LABEL", tr("Graphics Options"), 30))->addBackground()->setPosition(50, top, ATopLeft)->setSize(300, 50); + right_container = new GuiAutoLayout(this, "OPTIONS_RIGHT_CONTAINER", GuiAutoLayout::LayoutVerticalTopToBottom); + right_container->setPosition(-50, 50, ATopRight)->setSize(600, GuiElement::GuiSizeMax); + // Options pager + options_pager = new GuiSelector(left_container, "OPTIONS_PAGER", [this](int index, string value) + { + graphics_page->setVisible(index == 0); + audio_page->setVisible(index == 1); + interface_page->setVisible(index == 2); + }); + options_pager->setOptions({tr("Graphics options"), tr("Audio options"), tr("Interface options")})->setSelectionIndex(0)->setSize(GuiElement::GuiSizeMax, 50); + + graphics_page = new GuiAutoLayout(left_container, "OPTIONS_GRAPHICS", GuiAutoLayout::LayoutVerticalTopToBottom); + graphics_page->setPosition(0, 0, ATopLeft)->setSize(GuiElement::GuiSizeMax, GuiElement::GuiSizeMax)->show(); + audio_page = new GuiAutoLayout(left_container, "OPTIONS_AUDIO", GuiAutoLayout::LayoutVerticalTopToBottom); + audio_page->setPosition(0, 0, ATopLeft)->setSize(GuiElement::GuiSizeMax, GuiElement::GuiSizeMax)->hide(); + interface_page = new GuiAutoLayout(left_container, "OPTIONS_INTERFACE", GuiAutoLayout::LayoutVerticalTopToBottom); + interface_page->setPosition(0, 0, ATopLeft)->setSize(GuiElement::GuiSizeMax, GuiElement::GuiSizeMax)->hide(); + + // Graphics options // Fullscreen toggle. - top += 50; - (new GuiButton(this, "FULLSCREEN_TOGGLE", tr("Fullscreen toggle"), []() + (new GuiButton(graphics_page, "FULLSCREEN_TOGGLE", tr("Fullscreen toggle"), []() { P windowManager = engine->getObject("windowManager"); windowManager->setFullscreen(!windowManager->isFullscreen()); - }))->setPosition(50, top, ATopLeft)->setSize(300, 50); + }))->setSize(GuiElement::GuiSizeMax, 50); // FSAA configuration. int fsaa = std::max(1, windowManager->getFSAA()); @@ -48,125 +66,137 @@ OptionsMenu::OptionsMenu() } // FSAA selector. - top += 50; - (new GuiSelector(this, "FSAA", [](int index, string value) + (new GuiSelector(graphics_page, "FSAA", [](int index, string value) { P windowManager = engine->getObject("windowManager"); static const int fsaa[] = { 0, 2, 4, 8 }; windowManager->setFSAA(fsaa[index]); - }))->setOptions({"FSAA: off", "FSAA: 2x", "FSAA: 4x", "FSAA: 8x"})->setSelectionIndex(fsaa_index)->setPosition(50, top, ATopLeft)->setSize(300, 50); - - // Sound options. - top += 60; - (new GuiLabel(this, "SOUND_OPTIONS_LABEL", tr("Sound Options"), 30))->addBackground()->setPosition(50, top, ATopLeft)->setSize(300, 50); + }))->setOptions({"FSAA: off", "FSAA: 2x", "FSAA: 4x", "FSAA: 8x"})->setSelectionIndex(fsaa_index)->setSize(GuiElement::GuiSizeMax, 50); + // Audio optionss // Sound volume slider. - top += 50; - sound_volume_slider = new GuiSlider(this, "SOUND_VOLUME_SLIDER", 0.0f, 100.0f, soundManager->getMasterSoundVolume(), [this](float volume) + sound_volume_slider = new GuiSlider(audio_page, "SOUND_VOLUME_SLIDER", 0.0f, 100.0f, soundManager->getMasterSoundVolume(), [this](float volume) { soundManager->setMasterSoundVolume(volume); sound_volume_overlay_label->setText(tr("Sound Volume: {volume}%").format({{"volume", string(int(soundManager->getMasterSoundVolume()))}})); }); - sound_volume_slider->setPosition(50, top, ATopLeft)->setSize(300, 50); + sound_volume_slider->setSize(GuiElement::GuiSizeMax, 50); // Override overlay label. - sound_volume_overlay_label = new GuiLabel(sound_volume_slider, "SOUND_VOLUME_SLIDER_LABEL", "Sound Volume: " + string(int(soundManager->getMasterSoundVolume())) + "%", 30); + sound_volume_overlay_label = new GuiLabel(sound_volume_slider, "SOUND_VOLUME_SLIDER_LABEL", tr("Sound Volume: {volume}%").format({{"volume", string(int(soundManager->getMasterSoundVolume()))}}), 30); sound_volume_overlay_label->setSize(GuiElement::GuiSizeMax, GuiElement::GuiSizeMax); + // Music playback state. + (new GuiLabel(audio_page, "MUSIC_PLAYBACK_LABEL", tr("Music Playback"), 30))->addBackground()->setSize(GuiElement::GuiSizeMax, 50); + + // Determine when music is enabled. + int music_enabled_index = PreferencesManager::get("music_enabled", "2").toInt(); + (new GuiSelector(audio_page, "MUSIC_ENABLED", [](int index, string value) + { + // 0: Always off + // 1: Always on + // 2: On if main screen, off otherwise (default) + PreferencesManager::set("music_enabled", string(index)); + }))->setOptions({tr("Disabled"), tr("Enabled"), tr("Main Screen only")})->setSelectionIndex(music_enabled_index)->setSize(GuiElement::GuiSizeMax, 50); + // Music volume slider. - top += 50; - music_volume_slider = new GuiSlider(this, "MUSIC_VOLUME_SLIDER", 0.0f, 100.0f, soundManager->getMusicVolume(), [this](float volume) + music_volume_slider = new GuiSlider(audio_page, "MUSIC_VOLUME_SLIDER", 0.0f, 100.0f, soundManager->getMusicVolume(), [this](float volume) { soundManager->setMusicVolume(volume); - music_volume_overlay_label->setText("Music Volume: " + string(int(soundManager->getMusicVolume())) + "%"); + music_volume_overlay_label->setText(tr("Music Volume: {volume}%").format({{"volume", string(int(soundManager->getMusicVolume()))}})); }); - music_volume_slider->setPosition(50, top, ATopLeft)->setSize(300, 50); + music_volume_slider->setSize(GuiElement::GuiSizeMax, 50); // Override overlay label. - music_volume_overlay_label = new GuiLabel(music_volume_slider, "MUSIC_VOLUME_SLIDER_LABEL", "Music Volume: " + string(int(soundManager->getMusicVolume())) + "%", 30); + music_volume_overlay_label = new GuiLabel(music_volume_slider, "MUSIC_VOLUME_SLIDER_LABEL", tr("Music Volume: {volume}%").format({{"volume", string(int(soundManager->getMusicVolume()))}}), 30); music_volume_overlay_label->setSize(GuiElement::GuiSizeMax, GuiElement::GuiSizeMax); - // Music playback state. - top += 60; - (new GuiLabel(this, "MUSIC_PLAYBACK_LABEL", "Music Playback", 30))->addBackground()->setPosition(50, top, ATopLeft)->setSize(300, 50); + // Engine playback state. + (new GuiLabel(audio_page, "IMPULSE_SOUND_LABEL", tr("Impulse Engine sound"), 30))->addBackground()->setSize(GuiElement::GuiSizeMax, 50); - // Determine when music is enabled. - int music_enabled_index = PreferencesManager::get("music_enabled", "2").toInt(); - top += 50; - (new GuiSelector(this, "MUSIC_ENABLED", [](int index, string value) + // Determine when engine sound effects are enabled. + int impulse_enabled_index = PreferencesManager::get("impulse_sound_enabled", "2").toInt(); + (new GuiSelector(audio_page, "ENGINE_ENABLED", [](int index, string value) { // 0: Always off // 1: Always on // 2: On if main screen, off otherwise (default) - PreferencesManager::set("music_enabled", string(index)); - }))->setOptions({"Disabled", "Enabled", "Main Screen only"})->setSelectionIndex(music_enabled_index)->setPosition(50, top, ATopLeft)->setSize(300, 50); + PreferencesManager::set("impulse_sound_enabled", string(index)); + }))->setOptions({tr("Disabled"), tr("Enabled"), tr("Main Screen only")})->setSelectionIndex(impulse_enabled_index)->setSize(GuiElement::GuiSizeMax, 50); - // Interface options. - top += 60; - (new GuiLabel(this, "INTERFACE_OPTIONS_LABEL", tr("Interface Options"), 30))->addBackground()->setPosition(50, top, ATopLeft)->setSize(300, 50); + // Impulse engine volume slider. + impulse_volume_slider = new GuiSlider(audio_page, "IMPULSE_VOLUME_SLIDER", 0.0f, 100.0f, PreferencesManager::get("impulse_sound_volume", "50").toInt(), [this](float volume) + { + PreferencesManager::set("impulse_sound_volume", volume); + impulse_volume_overlay_label->setText(tr("Impulse Volume: {volume}%").format({{"volume", string(PreferencesManager::get("impulse_sound_volume", "50").toInt())}})); + }); + impulse_volume_slider->setSize(GuiElement::GuiSizeMax, 50); + + // Override overlay label. + impulse_volume_overlay_label = new GuiLabel(impulse_volume_slider, "IMPULSE_VOLUME_SLIDER_LABEL", tr("Impulse Volume: {volume}%").format({{"volume", string(PreferencesManager::get("impulse_sound_volume", "50").toInt())}}), 30); + impulse_volume_overlay_label->setSize(GuiElement::GuiSizeMax, GuiElement::GuiSizeMax); + // Interface options // Helms rotation lock. - top += 50; - (new GuiToggleButton(this, "HEMS_RADAR_LOCK", tr("Helms Radar Lock"), [](bool value) + (new GuiToggleButton(interface_page, "HEMS_RADAR_LOCK", tr("Helms Radar Lock"), [](bool value) { - PreferencesManager::set("helms_radar_lock", value?"1":""); - PreferencesManager::set("tactical_radar_lock", value?"1":""); - }))->setValue(PreferencesManager::get("helms_radar_lock","0")=="1")->setPosition(50, top, ATopLeft)->setSize(300, 50); + PreferencesManager::set("helms_radar_lock", value ? "1" : ""); + PreferencesManager::set("tactical_radar_lock", value ? "1" : ""); + }))->setValue(PreferencesManager::get("helms_radar_lock", "0") == "1")->setSize(GuiElement::GuiSizeMax, 50); // Helms rotation lock. - top += 50; - (new GuiToggleButton(this, "WEAPONS_RADAR_LOCK", tr("Weapons Radar Lock"), [](bool value) + (new GuiToggleButton(interface_page, "WEAPONS_RADAR_LOCK", tr("Weapons Radar Lock"), [](bool value) { - PreferencesManager::set("weapons_radar_lock", value?"1":""); - }))->setValue(PreferencesManager::get("weapons_radar_lock","0")=="1")->setPosition(50, top, ATopLeft)->setSize(300, 50); + PreferencesManager::set("weapons_radar_lock", value ? "1" : ""); + }))->setValue(PreferencesManager::get("weapons_radar_lock", "0") == "1")->setSize(GuiElement::GuiSizeMax, 50); // Helms rotation lock. - top += 50; - (new GuiToggleButton(this, "SCIENCE_RADAR_LOCK", tr("Science Radar Lock"), [](bool value) + (new GuiToggleButton(interface_page, "SCIENCE_RADAR_LOCK", tr("Science Radar Lock"), [](bool value) { - PreferencesManager::set("science_radar_lock", value?"1":""); - }))->setValue(PreferencesManager::get("science_radar_lock","0")=="1")->setPosition(50, top, ATopLeft)->setSize(300, 50); - - // Right column, manual layout. Draw first element 50px from top. - top = 50; + PreferencesManager::set("science_radar_lock", value ? "1" : ""); + }))->setValue(PreferencesManager::get("science_radar_lock", "0") == "1")->setSize(GuiElement::GuiSizeMax, 50); + // Right column, auto layout. Draw first element 50px from top. // Music preview jukebox. - (new GuiLabel(this, "MUSIC_PREVIEW_LABEL", "Preview Soundtrack", 30))->addBackground()->setPosition(-50, top, ATopRight)->setSize(600, 50); - // Draw list of available music. Grabs every ogg file in the music folder - // and lists them by filename. - // TODO: Associate ambient and combat music within the list. - top += 50; - GuiListbox* music_list = new GuiListbox(this, "MUSIC_PLAY", [this](int index, string value) + // Draw list of available music. Grabs every ogg file in the + // resources/music folder and lists them by filename. + std::vector ambient_music_filenames = findResources("music/ambient/*.ogg"); + std::sort(ambient_music_filenames.begin(), ambient_music_filenames.end()); + std::vector combat_music_filenames = findResources("music/combat/*.ogg"); + std::sort(combat_music_filenames.begin(), combat_music_filenames.end()); + + (new GuiLabel(right_container, "PREVIEW_LABEL", tr("Preview Soundtracks"), 30))->addBackground()->setSize(GuiElement::GuiSizeMax, 50); + + GuiListbox* music_list = new GuiListbox(right_container, "MUSIC_PLAY", [this](int index, string value) { soundManager->playMusic(value); }); - music_list->setPosition(-50, top, ATopRight)->setSize(600, 800); - std::vector music_filenames = findResources("music/*.ogg"); - std::sort(music_filenames.begin(), music_filenames.end()); - for(string filename : music_filenames) - { + for(string filename : ambient_music_filenames) music_list->addEntry(filename.substr(filename.rfind("/") + 1, filename.rfind(".")), filename); - } + for(string filename : combat_music_filenames) + music_list->addEntry(filename.substr(filename.rfind("/") + 1, filename.rfind(".")), filename); + + music_list->setSize(GuiElement::GuiSizeMax, 750); // Bottom GUI. // Back button. - (new GuiButton(this, "BACK", "Back", [this]() + (new GuiButton(this, "BACK", tr("options", "Back"), [this]() { // Close this menu, stop the music, and return to the main menu. destroy(); soundManager->stopMusic(); returnToMainMenu(); - }))->setPosition(50, -50, ABottomLeft)->setSize(300, 50); + }))->setPosition(50, -50, ABottomLeft)->setSize(150, 50); // Save options button. - (new GuiButton(this, "SAVE_OPTIONS", "Save Options", [this]() + (new GuiButton(this, "SAVE_OPTIONS", tr("options", "Save"), [this]() { if (getenv("HOME")) PreferencesManager::save(string(getenv("HOME")) + "/.emptyepsilon/options.ini"); else PreferencesManager::save("options.ini"); - }))->setPosition(370, -50, ABottomLeft)->setSize(300, 50); + }))->setPosition(200, -50, ABottomLeft)->setSize(150, 50); } void OptionsMenu::onKey(sf::Event::KeyEvent key, int unicode) diff --git a/src/menus/optionsMenu.h b/src/menus/optionsMenu.h index 05f3878bc7..069f3d74a2 100644 --- a/src/menus/optionsMenu.h +++ b/src/menus/optionsMenu.h @@ -3,16 +3,26 @@ #include "gui/gui2_canvas.h" +class GuiAutoLayout; +class GuiSelector; class GuiSlider; class GuiLabel; class OptionsMenu : public GuiCanvas { private: + GuiAutoLayout* left_container; + GuiAutoLayout* right_container; + GuiSelector* options_pager; + GuiAutoLayout* graphics_page; + GuiAutoLayout* audio_page; + GuiAutoLayout* interface_page; GuiSlider* sound_volume_slider; GuiSlider* music_volume_slider; + GuiSlider* impulse_volume_slider; GuiLabel* sound_volume_overlay_label; GuiLabel* music_volume_overlay_label; + GuiLabel* impulse_volume_overlay_label; public: OptionsMenu(); diff --git a/src/menus/shipSelectionScreen.cpp b/src/menus/shipSelectionScreen.cpp index fd1f989bd8..23a97ef8cd 100644 --- a/src/menus/shipSelectionScreen.cpp +++ b/src/menus/shipSelectionScreen.cpp @@ -49,11 +49,7 @@ ShipSelectionScreen::ShipSelectionScreen() // Main screen button main_screen_button = new GuiToggleButton(stations_layout, "MAIN_SCREEN_BUTTON", "Main screen", [this](bool value) { - for(int n=0; nsetValue(false); - my_player_info->commandSetCrewPosition(ECrewPosition(n), crew_position_button[n]->getValue()); - } + my_player_info->commandSetMainScreen(value); }); main_screen_button->setSize(GuiElement::GuiSizeMax, 50); @@ -61,7 +57,6 @@ ShipSelectionScreen::ShipSelectionScreen() for(int n = 0; n < max_crew_positions; n++) { crew_position_button[n] = new GuiToggleButton(stations_layout, "CREW_" + getCrewPositionName(ECrewPosition(n)) + "_BUTTON", getCrewPositionName(ECrewPosition(n)), [this, n](bool value){ - main_screen_button->setValue(false); my_player_info->commandSetCrewPosition(ECrewPosition(n), value); }); crew_position_button[n]->setSize(GuiElement::GuiSizeMax, 50); @@ -355,10 +350,12 @@ void ShipSelectionScreen::update(float delta) if (ship) { string ship_name = ship->getFaction() + " " + ship->getTypeName() + " " + ship->getCallSign(); + + int index = player_ship_list->indexByValue(string(n)); // If a player ship isn't in already in the list, add it. - if (player_ship_list->indexByValue(string(n)) == -1) + if (index == -1) { - int index = player_ship_list->addEntry(ship_name, string(n)); + index = player_ship_list->addEntry(ship_name, string(n)); if (my_spaceship == ship) player_ship_list->setSelectionIndex(index); } @@ -370,7 +367,7 @@ void ShipSelectionScreen::update(float delta) if (ship->hasPlayerAtPosition(ECrewPosition(n))) ship_position_count += 1; } - player_ship_list->setEntryName(n, ship_name + " (" + string(ship_position_count) + ")"); + player_ship_list->setEntryName(index, ship_name + " (" + string(ship_position_count) + ")"); }else{ if (player_ship_list->indexByValue(string(n)) != -1) player_ship_list->removeEntry(player_ship_list->indexByValue(string(n))); @@ -391,6 +388,9 @@ void ShipSelectionScreen::update(float delta) players.push_back(i->name); } } + std::sort(players.begin(), players.end()); + players.resize(std::distance(players.begin(), std::unique(players.begin(), players.end()))); + if (players.size() > 0) { crew_position_button[n]->setText(button_text + " (" + string(", ").join(players) + ")"); @@ -421,7 +421,7 @@ void ShipSelectionScreen::updateReadyButton() { // Update the Ready button based on crew position button states. // If the player is capable of displaying the main screen... - if (my_player_info->isMainScreen()) + if (my_player_info->isOnlyMainScreen()) { // If the main screen button is both available and selected and a // player ship is also selected, and the player isn't being asked for a @@ -460,7 +460,7 @@ void ShipSelectionScreen::updateCrewTypeOptions() cinematic_view_button->hide(); spectator_button->hide(); main_screen_button->setVisible(canDoMainScreen()); - main_screen_button->setValue(false); + main_screen_button->setValue(my_player_info->main_screen); main_screen_controls_button->setVisible(crew_type_selector->getSelectionIndex() != 3); game_master_button->setValue(false); window_button->setValue(false); diff --git a/src/playerInfo.cpp b/src/playerInfo.cpp index eabff918b0..0305be93ea 100644 --- a/src/playerInfo.cpp +++ b/src/playerInfo.cpp @@ -25,8 +25,9 @@ static const int16_t CMD_UPDATE_CREW_POSITION = 0x0001; static const int16_t CMD_UPDATE_SHIP_ID = 0x0002; -static const int16_t CMD_UPDATE_MAIN_SCREEN_CONTROL = 0x0003; -static const int16_t CMD_UPDATE_NAME = 0x0004; +static const int16_t CMD_UPDATE_MAIN_SCREEN = 0x0003; +static const int16_t CMD_UPDATE_MAIN_SCREEN_CONTROL = 0x0004; +static const int16_t CMD_UPDATE_NAME = 0x0005; P my_player_info; P my_spaceship; @@ -48,11 +49,22 @@ PlayerInfo::PlayerInfo() } registerMemberReplication(&ship_id); registerMemberReplication(&name); + registerMemberReplication(&main_screen); registerMemberReplication(&main_screen_control); player_info_list.push_back(this); } +bool PlayerInfo::isOnlyMainScreen() +{ + if (!main_screen) + return false; + for(int n=0; n> position >> active; crew_position[position] = active; - - if (isMainScreen()) - main_screen_control = false; } break; case CMD_UPDATE_SHIP_ID: packet >> ship_id; break; + case CMD_UPDATE_MAIN_SCREEN: + packet >> main_screen; + break; case CMD_UPDATE_MAIN_SCREEN_CONTROL: packet >> main_screen_control; break; @@ -117,62 +138,57 @@ void PlayerInfo::onReceiveClientCommand(int32_t client_id, sf::Packet& packet) } } -bool PlayerInfo::isMainScreen() -{ - for(int n=0; nisMainScreen()) + if (my_player_info->isOnlyMainScreen()) { new ScreenMainScreen(); }else{ CrewStationScreen* screen = new CrewStationScreen(); - + if (main_screen) + screen->enableMainScreen(); + auto container = screen->getTabContainer(); + //Crew 6/5 if (crew_position[helmsOfficer]) - screen->addStationTab(new HelmsScreen(screen), helmsOfficer, getCrewPositionName(helmsOfficer), getCrewPositionIcon(helmsOfficer)); + screen->addStationTab(new HelmsScreen(container), helmsOfficer, getCrewPositionName(helmsOfficer), getCrewPositionIcon(helmsOfficer)); if (crew_position[weaponsOfficer]) - screen->addStationTab(new WeaponsScreen(screen), weaponsOfficer, getCrewPositionName(weaponsOfficer), getCrewPositionIcon(weaponsOfficer)); + screen->addStationTab(new WeaponsScreen(container), weaponsOfficer, getCrewPositionName(weaponsOfficer), getCrewPositionIcon(weaponsOfficer)); if (crew_position[engineering]) - screen->addStationTab(new EngineeringScreen(screen), engineering, getCrewPositionName(engineering), getCrewPositionIcon(engineering)); + screen->addStationTab(new EngineeringScreen(container), engineering, getCrewPositionName(engineering), getCrewPositionIcon(engineering)); if (crew_position[scienceOfficer]) - screen->addStationTab(new ScienceScreen(screen), scienceOfficer, getCrewPositionName(scienceOfficer), getCrewPositionIcon(scienceOfficer)); + screen->addStationTab(new ScienceScreen(container), scienceOfficer, getCrewPositionName(scienceOfficer), getCrewPositionIcon(scienceOfficer)); if (crew_position[relayOfficer]) - screen->addStationTab(new RelayScreen(screen, true), relayOfficer, getCrewPositionName(relayOfficer), getCrewPositionIcon(relayOfficer)); + screen->addStationTab(new RelayScreen(container, true), relayOfficer, getCrewPositionName(relayOfficer), getCrewPositionIcon(relayOfficer)); //Crew 4/3 if (crew_position[tacticalOfficer]) - screen->addStationTab(new TacticalScreen(screen), tacticalOfficer, getCrewPositionName(tacticalOfficer), getCrewPositionIcon(tacticalOfficer)); + screen->addStationTab(new TacticalScreen(container), tacticalOfficer, getCrewPositionName(tacticalOfficer), getCrewPositionIcon(tacticalOfficer)); if (crew_position[engineeringAdvanced]) - screen->addStationTab(new EngineeringAdvancedScreen(screen), engineeringAdvanced, getCrewPositionName(engineeringAdvanced), getCrewPositionIcon(engineeringAdvanced)); + screen->addStationTab(new EngineeringAdvancedScreen(container), engineeringAdvanced, getCrewPositionName(engineeringAdvanced), getCrewPositionIcon(engineeringAdvanced)); if (crew_position[operationsOfficer]) - screen->addStationTab(new OperationScreen(screen), operationsOfficer, getCrewPositionName(operationsOfficer), getCrewPositionIcon(operationsOfficer)); + screen->addStationTab(new OperationScreen(container), operationsOfficer, getCrewPositionName(operationsOfficer), getCrewPositionIcon(operationsOfficer)); //Crew 1 if (crew_position[singlePilot]) - screen->addStationTab(new SinglePilotScreen(screen), singlePilot, getCrewPositionName(singlePilot), getCrewPositionIcon(singlePilot)); + screen->addStationTab(new SinglePilotScreen(container), singlePilot, getCrewPositionName(singlePilot), getCrewPositionIcon(singlePilot)); //Extra if (crew_position[damageControl]) - screen->addStationTab(new DamageControlScreen(screen), damageControl, getCrewPositionName(damageControl), getCrewPositionIcon(damageControl)); + screen->addStationTab(new DamageControlScreen(container), damageControl, getCrewPositionName(damageControl), getCrewPositionIcon(damageControl)); if (crew_position[powerManagement]) - screen->addStationTab(new PowerManagementScreen(screen), powerManagement, getCrewPositionName(powerManagement), getCrewPositionIcon(powerManagement)); + screen->addStationTab(new PowerManagementScreen(container), powerManagement, getCrewPositionName(powerManagement), getCrewPositionIcon(powerManagement)); if (crew_position[databaseView]) - screen->addStationTab(new DatabaseScreen(screen), databaseView, getCrewPositionName(databaseView), getCrewPositionIcon(databaseView)); + screen->addStationTab(new DatabaseScreen(container), databaseView, getCrewPositionName(databaseView), getCrewPositionIcon(databaseView)); if (crew_position[altRelay]) - screen->addStationTab(new RelayScreen(screen, false), altRelay, getCrewPositionName(altRelay), getCrewPositionIcon(altRelay)); + screen->addStationTab(new RelayScreen(container, false), altRelay, getCrewPositionName(altRelay), getCrewPositionIcon(altRelay)); if (crew_position[commsOnly]) - screen->addStationTab(new CommsScreen(screen), commsOnly, getCrewPositionName(commsOnly), getCrewPositionIcon(commsOnly)); + screen->addStationTab(new CommsScreen(container), commsOnly, getCrewPositionName(commsOnly), getCrewPositionIcon(commsOnly)); if (crew_position[shipLog]) - screen->addStationTab(new ShipLogScreen(screen), shipLog, getCrewPositionName(shipLog), getCrewPositionIcon(shipLog)); + screen->addStationTab(new ShipLogScreen(container), shipLog, getCrewPositionName(shipLog), getCrewPositionIcon(shipLog)); - GuiSelfDestructEntry* sde = new GuiSelfDestructEntry(screen, "SELF_DESTRUCT_ENTRY"); + GuiSelfDestructEntry* sde = new GuiSelfDestructEntry(container, "SELF_DESTRUCT_ENTRY"); for(int n=0; nenablePosition(ECrewPosition(n)); @@ -192,7 +208,7 @@ void PlayerInfo::spawnUI() } if (main_screen_control) - new GuiMainScreenControls(screen); + new GuiMainScreenControls(container); screen->finishCreation(); } diff --git a/src/playerInfo.h b/src/playerInfo.h index 44da4afafc..9f1b9c1bd5 100644 --- a/src/playerInfo.h +++ b/src/playerInfo.h @@ -39,15 +39,18 @@ class PlayerInfo : public MultiplayerObject int32_t client_id; bool crew_position[max_crew_positions]; - bool main_screen_control; + bool main_screen = false; + bool main_screen_control = false; int32_t ship_id; string name; PlayerInfo(); - bool isMainScreen(); + bool isOnlyMainScreen(); + void commandSetCrewPosition(ECrewPosition position, bool active); void commandSetShipId(int32_t id); + void commandSetMainScreen(bool enabled); void commandSetMainScreenControl(bool control); void commandSetName(const string& name); virtual void onReceiveClientCommand(int32_t client_id, sf::Packet& packet); diff --git a/src/scienceDatabase.cpp b/src/scienceDatabase.cpp index 5ea9c91d57..a9753d7fc0 100644 --- a/src/scienceDatabase.cpp +++ b/src/scienceDatabase.cpp @@ -11,6 +11,7 @@ REGISTER_SCRIPT_CLASS(ScienceDatabase) REGISTER_SCRIPT_CLASS_FUNCTION(ScienceDatabase, addEntry); REGISTER_SCRIPT_CLASS_FUNCTION(ScienceDatabase, addKeyValue); REGISTER_SCRIPT_CLASS_FUNCTION(ScienceDatabase, setLongDescription); + REGISTER_SCRIPT_CLASS_FUNCTION(ScienceDatabase, setImage); } @@ -50,6 +51,20 @@ void ScienceDatabase::setLongDescription(string text) longDescription = text; } +string directionLabel(float direction) +{ + string name = "?"; + if (std::abs(sf::angleDifference(0.0f, direction)) <= 45) + name = tr("database direction", "Front"); + if (std::abs(sf::angleDifference(90.0f, direction)) < 45) + name = tr("database direction", "Right"); + if (std::abs(sf::angleDifference(-90.0f, direction)) < 45) + name = tr("database direction", "Left"); + if (std::abs(sf::angleDifference(180.0f, direction)) <= 45) + name = tr("database direction", "Rear"); + return name; +} + void fillDefaultDatabaseData() { P factionDatabase = new ScienceDatabase(); @@ -107,51 +122,64 @@ void fillDefaultDatabaseData() P entry = class_database_entries[ship_template->getClass()]->addEntry(template_name); entry->model_data = ship_template->model_data; + entry->setImage(ship_template->radar_trace); entry->addKeyValue(tr("database", "Class"), ship_template->getClass()); entry->addKeyValue(tr("database", "Sub-class"), ship_template->getSubClass()); entry->addKeyValue(tr("database", "Size"), string(int(ship_template->model_data->getRadius()))); - string shield_info = ""; - for(int n=0; nshield_count; n++) + if (ship_template->shield_count > 0) { - if (n > 0) - shield_info += "/"; - shield_info += string(int(ship_template->shield_level[n])); + string shield_info = ""; + for(int n=0; nshield_count; n++) + { + if (n > 0) + shield_info += "/"; + shield_info += string(int(ship_template->shield_level[n])); + } + entry->addKeyValue(tr("database", "Shield"), shield_info); } - entry->addKeyValue(tr("database", "Shield"), shield_info); entry->addKeyValue(tr("Hull"), string(int(ship_template->hull))); - entry->addKeyValue(tr("database", "Move speed"), string(int(ship_template->impulse_speed))); - entry->addKeyValue(tr("database", "Turn speed"), string(int(ship_template->turn_speed))); + + if (ship_template->impulse_speed > 0.0) + { + entry->addKeyValue(tr("database", "Move speed"), string(ship_template->impulse_speed * 60 / 1000, 1) + " u/min"); + } + if (ship_template->turn_speed > 0.0) { + entry->addKeyValue(tr("database", "Turn speed"), string(ship_template->turn_speed, 1) + " deg/sec"); + } if (ship_template->warp_speed > 0.0) { - entry->addKeyValue(tr("database", "Has warp drive"), tr("hasdrive","True")); - entry->addKeyValue(tr("database", "Warp speed"), string(int(ship_template->warp_speed))); + entry->addKeyValue(tr("database", "Warp speed"), string(ship_template->warp_speed * 60 / 1000, 1) + " u/min"); } if (ship_template->has_jump_drive) { - entry->addKeyValue(tr("Has jump drive"), tr("hasdrive","True")); + entry->addKeyValue(tr("database", "Jump range"), string(ship_template->jump_drive_min_distance / 1000, 0) + " - " + string(ship_template->jump_drive_max_distance / 1000, 0) + " u"); } for(int n=0; nbeams[n].getRange() > 0) { - string name = "?"; - if (std::abs(sf::angleDifference(0.0f, ship_template->beams[n].getDirection())) <= 45) - name = tr("database", "Front beam weapon"); - if (std::abs(sf::angleDifference(90.0f, ship_template->beams[n].getDirection())) < 45) - name = tr("database", "Right beam weapon"); - if (std::abs(sf::angleDifference(-90.0f, ship_template->beams[n].getDirection())) < 45) - name = tr("database", "Left beam weapon"); - if (std::abs(sf::angleDifference(180.0f, ship_template->beams[n].getDirection())) <= 45) - name = tr("database", "Rear beam weapon"); - - entry->addKeyValue(name, string(ship_template->beams[n].getDamage() / ship_template->beams[n].getCycleTime(), 2) + " "+ tr("damage","DPS")); + entry->addKeyValue( + tr("{direction} beam weapon").format({{"direction": directionLabel(ship_template->beams[n].getDirection()}}), + tr("database", "{damage} Dmg / {interval} sec").format({{"damage", string(ship_template->beams[n].getDamage(), 1)}, {"interval", string(ship_template->beams[n].getCycleTime(), 1)}}) + ); } } - if (ship_template->weapon_tube_count > 0) + for(int n=0; nweapon_tube_count; n++) { - entry->addKeyValue(tr("database", "Missile tubes"), string(ship_template->weapon_tube_count)); - entry->addKeyValue(tr("database", "Missile load time"), string(int(ship_template->weapon_tube[0].load_time))); + string key = tr("database", "{direction} tube"); + if (ship_template->weapon_tube[n].size == MS_Small) + { + key = tr("database", "{direction} small tube"); + } + if (ship_template->weapon_tube[n].size == MS_Large) + { + key = tr("database", "{direction} large tube"); + } + entry->addKeyValue( + key.format({{"direction", directionLabel(ship_template->weapon_tube[n].direction)}, + tr("database", "{loadtime} sec").format({{"loadtime", string(int(ship_template->weapon_tube[n].load_time))}}) + ); } for(int n=0; n < MW_Count; n++) { diff --git a/src/scienceDatabase.h b/src/scienceDatabase.h index 37772b5e03..a3566d1675 100644 --- a/src/scienceDatabase.h +++ b/src/scienceDatabase.h @@ -27,6 +27,7 @@ class ScienceDatabase : public virtual PObject std::vector keyValuePairs; string longDescription; P model_data; + string image; ScienceDatabase(); ScienceDatabase(P parent, string name); @@ -36,9 +37,13 @@ class ScienceDatabase : public virtual PObject void setLongDescription(string text); void setName(string name) { this->name = name; } + void setImage(string path) { + image = path; + } P addEntry(string name); string getName() {return this->name;} private: + string directionLabel(float direction); public: /* static members */ static PVector science_databases; diff --git a/src/screenComponents/combatManeuver.cpp b/src/screenComponents/combatManeuver.cpp index 613a893fe0..06519dc11a 100644 --- a/src/screenComponents/combatManeuver.cpp +++ b/src/screenComponents/combatManeuver.cpp @@ -28,6 +28,11 @@ GuiCombatManeuver::GuiCombatManeuver(GuiContainer* owner, string id) (new GuiPowerDamageIndicator(slider, id + "_BOOST_INDICATOR", SYS_Impulse, ABottomLeft))->setPosition(0, 0, ABottomLeft)->setSize(GuiElement::GuiSizeMax, 50); } +void GuiCombatManeuver::onUpdate() +{ + setVisible(my_spaceship && my_spaceship->getCanCombatManeuver()); +} + void GuiCombatManeuver::onDraw(sf::RenderTarget& window) { if (my_spaceship) @@ -45,7 +50,7 @@ void GuiCombatManeuver::onDraw(sf::RenderTarget& window) void GuiCombatManeuver::onHotkey(const HotkeyResult& key) { - if (key.category == "HELMS" && my_spaceship) + if (key.category == "HELMS" && my_spaceship && isVisible()) { if (key.hotkey == "COMBAT_LEFT") {}//TODO diff --git a/src/screenComponents/combatManeuver.h b/src/screenComponents/combatManeuver.h index f105f041d5..81ca61ca17 100644 --- a/src/screenComponents/combatManeuver.h +++ b/src/screenComponents/combatManeuver.h @@ -14,6 +14,7 @@ class GuiCombatManeuver : public GuiElement public: GuiCombatManeuver(GuiContainer* owner, string id); + virtual void onUpdate() override; virtual void onDraw(sf::RenderTarget& window) override; virtual void onHotkey(const HotkeyResult& key) override; diff --git a/src/screenComponents/databaseView.cpp b/src/screenComponents/databaseView.cpp index bca7184105..7284bcbb33 100644 --- a/src/screenComponents/databaseView.cpp +++ b/src/screenComponents/databaseView.cpp @@ -3,6 +3,7 @@ #include "scienceDatabase.h" #include "gui/gui2_listbox.h" +#include "gui/gui2_image.h" #include "gui/gui2_autolayout.h" #include "gui/gui2_keyvaluedisplay.h" #include "gui/gui2_scrolltext.h" @@ -101,14 +102,22 @@ void DatabaseViewComponent::display(P entry) { (new GuiKeyValueDisplay(layout, "", 0.37, entry->keyValuePairs[n].key, entry->keyValuePairs[n].value))->setSize(GuiElement::GuiSizeMax, 40); } - if (entry->model_data) + if (entry->model_data || entry->image != "") { float x = 450; if (entry->keyValuePairs.size() == 0 && entry->longDescription.length() == 0) { x = 0; } - //TODO: std::min(GuiElement::GuiSizeMatchWidth, 370.0f) - (new GuiRotatingModelView(database_entry, "DATABASE_MODEL_VIEW", entry->model_data))->setPosition(x, -50, ATopLeft)->setSize(GuiElement::GuiSizeMax, GuiElement::GuiSizeMatchWidth); + if(entry->image != "") + { + (new GuiImage(database_entry, "DATABASE_IMAGE", entry->image))->setScaleUp(false)->setPosition(x, 0, ATopLeft)->setMargins(0, 0, 20, 20)->setSize(GuiElement::GuiSizeMax, GuiElement::GuiSizeMatchWidth); + } + + if (entry->model_data) + { + //TODO: std::min(GuiElement::GuiSizeMatchWidth, 370.0f) + (new GuiRotatingModelView(database_entry, "DATABASE_MODEL_VIEW", entry->model_data))->setPosition(x, -50, ATopLeft)->setMargins(0, 0, 20, 20)->setSize(GuiElement::GuiSizeMax, GuiElement::GuiSizeMatchWidth); + } if (entry->longDescription.length() > 0) { diff --git a/src/screenComponents/dockingButton.cpp b/src/screenComponents/dockingButton.cpp index 5c1de2dff7..4943a49838 100644 --- a/src/screenComponents/dockingButton.cpp +++ b/src/screenComponents/dockingButton.cpp @@ -27,6 +27,11 @@ void GuiDockingButton::click() } } +void GuiDockingButton::onUpdate() +{ + setVisible(my_spaceship && my_spaceship->getCanDock()); +} + void GuiDockingButton::onDraw(sf::RenderTarget& window) { if (my_spaceship) diff --git a/src/screenComponents/dockingButton.h b/src/screenComponents/dockingButton.h index 837b0b4a6e..4cfad63338 100644 --- a/src/screenComponents/dockingButton.h +++ b/src/screenComponents/dockingButton.h @@ -9,6 +9,7 @@ class GuiDockingButton : public GuiButton public: GuiDockingButton(GuiContainer* owner, string id); + virtual void onUpdate() override; virtual void onDraw(sf::RenderTarget& window) override; virtual void onHotkey(const HotkeyResult& key) override; private: diff --git a/src/screenComponents/helpOverlay.cpp b/src/screenComponents/helpOverlay.cpp index d1815416c1..94d56f3fdd 100644 --- a/src/screenComponents/helpOverlay.cpp +++ b/src/screenComponents/helpOverlay.cpp @@ -6,8 +6,8 @@ #include "gui/gui2_panel.h" #include "gui/gui2_scrolltext.h" -GuiHelpOverlay::GuiHelpOverlay(GuiCanvas* owner, string title, string contents) -: GuiElement(owner, "HELP_OVERLAY"), owner(owner) +GuiHelpOverlay::GuiHelpOverlay(GuiContainer* owner, string title, string contents) +: GuiElement(owner, "HELP_OVERLAY") { setSize(GuiElement::GuiSizeMax, GuiElement::GuiSizeMax); diff --git a/src/screenComponents/helpOverlay.h b/src/screenComponents/helpOverlay.h index 2f59430d66..b432665123 100644 --- a/src/screenComponents/helpOverlay.h +++ b/src/screenComponents/helpOverlay.h @@ -10,12 +10,11 @@ class GuiScrollText; class GuiHelpOverlay : public GuiElement { private: - GuiCanvas* owner; GuiScrollText* text; string help_text = ""; public: - GuiHelpOverlay(GuiCanvas* owner, string title = "", string contents = ""); + GuiHelpOverlay(GuiContainer* owner, string title = "", string contents = ""); GuiPanel* frame; virtual void setText(string new_text); diff --git a/src/screenComponents/impulseSound.cpp b/src/screenComponents/impulseSound.cpp new file mode 100644 index 0000000000..300ebb9206 --- /dev/null +++ b/src/screenComponents/impulseSound.cpp @@ -0,0 +1,72 @@ +#include "impulseSound.h" +#include "playerInfo.h" +#include "spaceObjects/playerSpaceship.h" +#include "preferenceManager.h" + +ImpulseSound::ImpulseSound(bool enabled) +{ + impulse_sound_id = -1; + impulse_sound_enabled = enabled; + impulse_sound_volume = PreferencesManager::get("impulse_sound_volume", "50").toInt(); + + // If defined, use this ship's impulse sound file. + if (my_spaceship) + impulse_sound_file = my_spaceship->impulse_sound_file; + else + impulse_sound_file = "sfx/engine.wav"; + + // If we can play an impulse sound, do so. + if (my_spaceship && impulse_sound_enabled && impulse_sound_volume > 0) + play(impulse_sound_file); +} + +ImpulseSound::~ImpulseSound() +{ + soundManager->stopSound(impulse_sound_id); +} + +void ImpulseSound::play(string sound_file) +{ +#ifndef __ANDROID__ + // Play impulse sounds only on my ship. + if (!my_spaceship) + return; + + // If there's already an impulse sound, stop it. + if (impulse_sound_id > -1) + soundManager->stopSound(impulse_sound_id); + + // Play the new impulse sound and store its integer ID in the class. + impulse_sound_id = soundManager->playSound(sound_file, 0.0f, 0.0f, true); +#endif +} + +void ImpulseSound::stop() +{ + soundManager->stopSound(impulse_sound_id); + impulse_sound_id = -1; +} + +void ImpulseSound::update(float delta) +{ +#ifndef __ANDROID__ + // Update only if an impulse sound is defined. + if (impulse_sound_id > -1) + { + // Get whether the ship's impulse engines are functional. + float impulse_ability = std::max(0.0f, std::min(my_spaceship->getSystemEffectiveness(SYS_Impulse), my_spaceship->getSystemPower(SYS_Impulse))); + + // If so, update their pitch and volume. + if (impulse_ability > 0.0f) + { + soundManager->setSoundVolume(impulse_sound_id, (std::max(10.0f * impulse_ability, fabsf(my_spaceship->current_impulse) * 10.0f * std::max(0.1f, impulse_ability))) * (impulse_sound_volume / 100.0f)); + soundManager->setSoundPitch(impulse_sound_id, std::max(0.7f * impulse_ability, fabsf(my_spaceship->current_impulse) + 0.2f * std::max(0.1f, impulse_ability))); + } else { + // If not, silence the impulse sound. + // TODO: Play an engine failure sound. + soundManager->setSoundVolume(impulse_sound_id, 0.0f); + soundManager->setSoundPitch(impulse_sound_id, 0.0f); + } + } +#endif +} diff --git a/src/screenComponents/impulseSound.h b/src/screenComponents/impulseSound.h new file mode 100644 index 0000000000..990b5ac88e --- /dev/null +++ b/src/screenComponents/impulseSound.h @@ -0,0 +1,24 @@ +#ifndef IMPULSE_SOUND_H +#define IMPULSE_SOUND_H + +#include "stringImproved.h" + +class ImpulseSound +{ +private: + int impulse_sound_id; + bool impulse_sound_enabled; + float impulse_sound_volume; + string impulse_sound_file; +public: + ImpulseSound(bool enabled); + ~ImpulseSound(); + + int getImpulseSoundID() { return impulse_sound_id; } + + virtual void play(string sound_file); + virtual void stop(); + virtual void update(float delta); +}; + +#endif//IMPULSE_SOUND_H diff --git a/src/screenComponents/indicatorOverlays.cpp b/src/screenComponents/indicatorOverlays.cpp index 0732e1b7cd..cca97f0b3b 100644 --- a/src/screenComponents/indicatorOverlays.cpp +++ b/src/screenComponents/indicatorOverlays.cpp @@ -42,7 +42,7 @@ GuiIndicatorOverlays::~GuiIndicatorOverlays() static float glow(float min, float max, float time) { - return min + (max - min) * fabsf(fmodf(engine->getElapsedTime() / time, 2.0) - 1.0); + return min + (max - min) * std::abs(fmodf(engine->getElapsedTime() / time, 2.0) - 1.0); } void GuiIndicatorOverlays::onDraw(sf::RenderTarget& window) diff --git a/src/screenComponents/mainScreenControls.h b/src/screenComponents/mainScreenControls.h index 27fcd09ce6..5f22dc5bb5 100644 --- a/src/screenComponents/mainScreenControls.h +++ b/src/screenComponents/mainScreenControls.h @@ -9,13 +9,13 @@ class GuiButton; class GuiMainScreenControls : public GuiAutoLayout { private: - GuiToggleButton* open_button; + GuiToggleButton* open_button = nullptr; std::vector buttons; - GuiButton* target_lock_button; - GuiButton* tactical_button; - GuiButton* long_range_button; - GuiButton* show_comms_button; - GuiButton* hide_comms_button; + GuiButton* target_lock_button = nullptr; + GuiButton* tactical_button = nullptr; + GuiButton* long_range_button = nullptr; + GuiButton* show_comms_button = nullptr; + GuiButton* hide_comms_button = nullptr; bool onscreen_comms_active = false; void closePopup(); diff --git a/src/screenComponents/radarView.cpp b/src/screenComponents/radarView.cpp index 27543c5c70..130c35711a 100644 --- a/src/screenComponents/radarView.cpp +++ b/src/screenComponents/radarView.cpp @@ -10,24 +10,58 @@ #include "targetsContainer.h" GuiRadarView::GuiRadarView(GuiContainer* owner, string id, TargetsContainer* targets) -: GuiElement(owner, id), next_ghost_dot_update(0.0), targets(targets), missile_tube_controls(nullptr), distance(5000.0f), long_range(false), show_ghost_dots(false) -, show_waypoints(false), show_target_projection(false), show_missile_tubes(false), show_callsigns(false), show_heading_indicators(false), show_game_master_data(false) -, view_position(sf::Vector2f(0.0f,0.0f)), view_rotation(0) -, range_indicator_step_size(0.0f), style(Circular), fog_style(NoFogOfWar), mouse_down_func(nullptr), mouse_drag_func(nullptr), mouse_up_func(nullptr) +: GuiElement(owner, id), + next_ghost_dot_update(0.0), + targets(targets), + missile_tube_controls(nullptr), + view_position(sf::Vector2f(0.0f,0.0f)), + view_rotation(0), + auto_center_on_my_ship(true), + auto_rotate_on_my_ship(false), + auto_distance(true), + distance(5000.0f), + long_range(false), + show_ghost_dots(false), + show_waypoints(false), + show_target_projection(false), + show_missile_tubes(false), + show_callsigns(false), + show_heading_indicators(false), + show_game_master_data(false), + range_indicator_step_size(0.0f), + style(Circular), + fog_style(NoFogOfWar), + mouse_down_func(nullptr), + mouse_drag_func(nullptr), + mouse_up_func(nullptr) { - auto_center_on_my_ship = true; - auto_rotate_on_my_ship = false; - auto_distance = true; } GuiRadarView::GuiRadarView(GuiContainer* owner, string id, float distance, TargetsContainer* targets) -: GuiElement(owner, id), next_ghost_dot_update(0.0), targets(targets), missile_tube_controls(nullptr), distance(distance), long_range(false), show_ghost_dots(false) -, show_waypoints(false), show_target_projection(false), show_missile_tubes(false), show_callsigns(false), show_heading_indicators(false), show_game_master_data(false) -, view_position(sf::Vector2f(0.0f,0.0f)), view_rotation(0) -, range_indicator_step_size(0.0f), style(Circular), fog_style(NoFogOfWar), mouse_down_func(nullptr), mouse_drag_func(nullptr), mouse_up_func(nullptr) +: GuiElement(owner, id), + next_ghost_dot_update(0.0), + targets(targets), + missile_tube_controls(nullptr), + view_position(sf::Vector2f(0.0f,0.0f)), + view_rotation(0), + auto_center_on_my_ship(true), + auto_rotate_on_my_ship(false), + distance(distance), + long_range(false), + show_ghost_dots(false), + show_waypoints(false), + show_target_projection(false), + show_missile_tubes(false), + show_callsigns(false), + show_heading_indicators(false), + show_game_master_data(false), + range_indicator_step_size(0.0f), + style(Circular), + fog_style(NoFogOfWar), + mouse_down_func(nullptr), + mouse_drag_func(nullptr), + mouse_up_func(nullptr) { - auto_center_on_my_ship = true; - auto_rotate_on_my_ship = false; } void GuiRadarView::onDraw(sf::RenderTarget& window) diff --git a/src/screenComponents/radarView.h b/src/screenComponents/radarView.h index d21a8c373f..5aa3a87107 100644 --- a/src/screenComponents/radarView.h +++ b/src/screenComponents/radarView.h @@ -45,10 +45,12 @@ class GuiRadarView : public GuiElement TargetsContainer* targets; GuiMissileTubeControls* missile_tube_controls; - bool auto_distance = false; - float distance; sf::Vector2f view_position; float view_rotation; + bool auto_center_on_my_ship; + bool auto_rotate_on_my_ship; + bool auto_distance = false; + float distance; bool long_range; bool show_ghost_dots; bool show_waypoints; @@ -57,8 +59,6 @@ class GuiRadarView : public GuiElement bool show_callsigns; bool show_heading_indicators; bool show_game_master_data; - bool auto_center_on_my_ship; - bool auto_rotate_on_my_ship; float range_indicator_step_size; ERadarStyle style; EFogOfWarStyle fog_style; diff --git a/src/screenComponents/scanTargetButton.cpp b/src/screenComponents/scanTargetButton.cpp index 2e120dbd63..bf12dfc784 100644 --- a/src/screenComponents/scanTargetButton.cpp +++ b/src/screenComponents/scanTargetButton.cpp @@ -17,6 +17,11 @@ GuiScanTargetButton::GuiScanTargetButton(GuiContainer* owner, string id, Targets progress->setSize(GuiElement::GuiSizeMax, GuiElement::GuiSizeMax); } +void GuiScanTargetButton::onUpdate() +{ + setVisible(my_spaceship && my_spaceship->getCanScan()); +} + void GuiScanTargetButton::onDraw(sf::RenderTarget& window) { if (!my_spaceship) diff --git a/src/screenComponents/scanTargetButton.h b/src/screenComponents/scanTargetButton.h index 9ebcce1c76..30a1eb6559 100644 --- a/src/screenComponents/scanTargetButton.h +++ b/src/screenComponents/scanTargetButton.h @@ -16,7 +16,8 @@ class GuiScanTargetButton : public GuiElement public: GuiScanTargetButton(GuiContainer* owner, string id, TargetsContainer* targets); - virtual void onDraw(sf::RenderTarget& window); + virtual void onUpdate() override; + virtual void onDraw(sf::RenderTarget& window) override; }; #endif//SCAN_TARGET_BUTTON_H diff --git a/src/screenComponents/scanningDialog.h b/src/screenComponents/scanningDialog.h index 19748aca8f..3f9f8bf90f 100644 --- a/src/screenComponents/scanningDialog.h +++ b/src/screenComponents/scanningDialog.h @@ -30,7 +30,7 @@ class GuiScanningDialog : public GuiElement public: GuiScanningDialog(GuiContainer* owner, string id); - virtual void onDraw(sf::RenderTarget& window); + virtual void onDraw(sf::RenderTarget& window) override; virtual bool onJoystickAxis(const AxisAction& axisAction) override; void setupParameters(); diff --git a/src/screenComponents/selfDestructButton.cpp b/src/screenComponents/selfDestructButton.cpp index 10860fdd3b..8a1fdd6f41 100644 --- a/src/screenComponents/selfDestructButton.cpp +++ b/src/screenComponents/selfDestructButton.cpp @@ -32,6 +32,11 @@ GuiSelfDestructButton::GuiSelfDestructButton(GuiContainer* owner, string id) cancel_button->setIcon("gui/icons/self-destruct")->hide()->setSize(GuiElement::GuiSizeMax, 50); } +void GuiSelfDestructButton::onUpdate() +{ + activate_button->setVisible(my_spaceship && my_spaceship->getCanSelfDestruct()); +} + void GuiSelfDestructButton::onDraw(sf::RenderTarget& window) { } diff --git a/src/screenComponents/selfDestructButton.h b/src/screenComponents/selfDestructButton.h index 018bef41ac..ad124acccc 100644 --- a/src/screenComponents/selfDestructButton.h +++ b/src/screenComponents/selfDestructButton.h @@ -14,6 +14,7 @@ class GuiSelfDestructButton : public GuiElement public: GuiSelfDestructButton(GuiContainer* owner, string id); + virtual void onUpdate() override; virtual void onDraw(sf::RenderTarget& window) override; virtual void onHotkey(const HotkeyResult& key) override; }; diff --git a/src/screenComponents/shipDestroyedPopup.h b/src/screenComponents/shipDestroyedPopup.h index 157ed57c0f..9b9b16b44d 100644 --- a/src/screenComponents/shipDestroyedPopup.h +++ b/src/screenComponents/shipDestroyedPopup.h @@ -11,7 +11,6 @@ class GuiShipDestroyedPopup : public GuiElement { private: GuiOverlay* ship_destroyed_overlay; - GuiPanel* frame; GuiCanvas* owner; sf::Clock show_timeout; diff --git a/src/screenComponents/viewportMainScreen.cpp b/src/screenComponents/viewportMainScreen.cpp new file mode 100644 index 0000000000..7e6a7958cc --- /dev/null +++ b/src/screenComponents/viewportMainScreen.cpp @@ -0,0 +1,67 @@ +#include "viewportMainScreen.h" +#include "playerInfo.h" +#include "preferenceManager.h" +#include "spaceObjects/playerSpaceship.h" + +GuiViewportMainScreen::GuiViewportMainScreen(GuiContainer* owner, string id) +: GuiViewport3D(owner, id) +{ + showCallsigns()->showHeadings()->showSpacedust(); + + first_person = PreferencesManager::get("first_person") == "1"; +} + +void GuiViewportMainScreen::onDraw(sf::RenderTarget& window) +{ + if (my_spaceship) + { + P target_ship = my_spaceship->getTarget(); + float target_camera_yaw = my_spaceship->getRotation(); + switch(my_spaceship->main_screen_setting) + { + case MSS_Back: target_camera_yaw += 180; break; + case MSS_Left: target_camera_yaw -= 90; break; + case MSS_Right: target_camera_yaw += 90; break; + case MSS_Target: + if (target_ship) + { + sf::Vector2f target_camera_diff = my_spaceship->getPosition() - target_ship->getPosition(); + target_camera_yaw = sf::vector2ToAngle(target_camera_diff) + 180; + } + break; + default: break; + } + camera_pitch = 30.0f; + + float camera_ship_distance = 420.0f; + float camera_ship_height = 420.0f; + if (first_person) + { + camera_ship_distance = -my_spaceship->getRadius(); + camera_ship_height = my_spaceship->getRadius() / 10.f; + camera_pitch = 0; + } + sf::Vector2f cameraPosition2D = my_spaceship->getPosition() + sf::vector2FromAngle(target_camera_yaw) * -camera_ship_distance; + sf::Vector3f targetCameraPosition(cameraPosition2D.x, cameraPosition2D.y, camera_ship_height); +#ifdef DEBUG + if (sf::Keyboard::isKeyPressed(sf::Keyboard::Z)) + { + targetCameraPosition.x = my_spaceship->getPosition().x; + targetCameraPosition.y = my_spaceship->getPosition().y; + targetCameraPosition.z = 3000.0; + camera_pitch = 90.0f; + } +#endif + if (first_person) + { + camera_position = targetCameraPosition; + camera_yaw = target_camera_yaw; + } + else + { + camera_position = camera_position * 0.9f + targetCameraPosition * 0.1f; + camera_yaw += sf::angleDifference(camera_yaw, target_camera_yaw) * 0.1f; + } + } + GuiViewport3D::onDraw(window); +} diff --git a/src/screenComponents/viewportMainScreen.h b/src/screenComponents/viewportMainScreen.h new file mode 100644 index 0000000000..ab25b333c2 --- /dev/null +++ b/src/screenComponents/viewportMainScreen.h @@ -0,0 +1,16 @@ +#ifndef VIEWPORT_MAIN_SCREEN_H +#define VIEWPORT_MAIN_SCREEN_H + +#include "viewport3d.h" + +class GuiViewportMainScreen : public GuiViewport3D +{ +public: + GuiViewportMainScreen(GuiContainer* owner, string id); + + virtual void onDraw(sf::RenderTarget& window); + + bool first_person = false; +}; + +#endif//VIEWPORT_MAIN_SCREEN_H diff --git a/src/screens/cinematicViewScreen.h b/src/screens/cinematicViewScreen.h index a649f59c7c..f0669927af 100644 --- a/src/screens/cinematicViewScreen.h +++ b/src/screens/cinematicViewScreen.h @@ -36,7 +36,6 @@ class CinematicViewScreen : public GuiCanvas, public Updatable // camera_position is a Vector3, so no need to declare one here. sf::Vector2f camera_position_2D; float target_rotation; - float target_velocity; P target_of_target; diff --git a/src/screens/crew1/singlePilotScreen.cpp b/src/screens/crew1/singlePilotScreen.cpp index f3b369208a..1c500e10b9 100644 --- a/src/screens/crew1/singlePilotScreen.cpp +++ b/src/screens/crew1/singlePilotScreen.cpp @@ -31,28 +31,18 @@ SinglePilotScreen::SinglePilotScreen(GuiContainer* owner) : GuiOverlay(owner, "SINGLEPILOT_SCREEN", colorConfig.background) { - // Create a 3D viewport behind everything, to serve as the right-side panel - viewport = new GuiViewport3D(this, "3D_VIEW"); - viewport->setPosition(1000, 0, ATopLeft)->setSize(GuiElement::GuiSizeMax, GuiElement::GuiSizeMax); - - first_person = PreferencesManager::get("first_person") == "1"; - - // Create left panel for controls. - left_panel = new GuiElement(this, "LEFT_PANEL"); - left_panel->setPosition(0, 0, ATopLeft)->setSize(1000, GuiElement::GuiSizeMax); - // Render the radar shadow and background decorations. - background_gradient = new GuiOverlay(left_panel, "BACKGROUND_GRADIENT", sf::Color::White); + background_gradient = new GuiOverlay(this, "BACKGROUND_GRADIENT", sf::Color::White); background_gradient->setTextureCenter("gui/BackgroundGradientSingle"); - background_crosses = new GuiOverlay(left_panel, "BACKGROUND_CROSSES", sf::Color::White); + background_crosses = new GuiOverlay(this, "BACKGROUND_CROSSES", sf::Color::White); background_crosses->setTextureTiled("gui/BackgroundCrosses"); // Render the alert level color overlay. (new AlertLevelOverlay(this)); // 5U tactical radar with piloting features. - radar = new GuiRadarView(left_panel, "TACTICAL_RADAR", &targets); + radar = new GuiRadarView(this, "TACTICAL_RADAR", &targets); radar->setPosition(0, 0, ACenter)->setSize(GuiElement::GuiSizeMatchHeight, 650); radar->setRangeIndicatorStepSize(1000.0)->shortRange()->enableGhostDots()->enableWaypoints()->enableCallsigns()->enableHeadingIndicators()->setStyle(GuiRadarView::Circular); radar->setCallbacks( @@ -74,43 +64,44 @@ SinglePilotScreen::SinglePilotScreen(GuiContainer* owner) ); // Ship stats and combat maneuver at bottom right corner of left panel. - (new GuiCombatManeuver(left_panel, "COMBAT_MANEUVER"))->setPosition(-20, -180, ABottomRight)->setSize(200, 150); + combat_maneuver = new GuiCombatManeuver(this, "COMBAT_MANEUVER"); + combat_maneuver->setPosition(-20, -180, ABottomRight)->setSize(200, 150)->setVisible(my_spaceship && my_spaceship->getCanCombatManeuver()); - energy_display = new GuiKeyValueDisplay(left_panel, "ENERGY_DISPLAY", 0.45, "Energy", ""); + energy_display = new GuiKeyValueDisplay(this, "ENERGY_DISPLAY", 0.45, tr("Energy"), ""); energy_display->setIcon("gui/icons/energy")->setTextSize(20)->setPosition(-20, -140, ABottomRight)->setSize(240, 40); - heading_display = new GuiKeyValueDisplay(left_panel, "HEADING_DISPLAY", 0.45, "Heading", ""); + heading_display = new GuiKeyValueDisplay(this, "HEADING_DISPLAY", 0.45, tr("Heading"), ""); heading_display->setIcon("gui/icons/heading")->setTextSize(20)->setPosition(-20, -100, ABottomRight)->setSize(240, 40); - velocity_display = new GuiKeyValueDisplay(left_panel, "VELOCITY_DISPLAY", 0.45, "Speed", ""); + velocity_display = new GuiKeyValueDisplay(this, "VELOCITY_DISPLAY", 0.45, tr("Speed"), ""); velocity_display->setIcon("gui/icons/speed")->setTextSize(20)->setPosition(-20, -60, ABottomRight)->setSize(240, 40); - shields_display = new GuiKeyValueDisplay(left_panel, "SHIELDS_DISPLAY", 0.45, "Shields", ""); + shields_display = new GuiKeyValueDisplay(this, "SHIELDS_DISPLAY", 0.45, tr("Shields"), ""); shields_display->setIcon("gui/icons/shields")->setTextSize(20)->setPosition(-20, -20, ABottomRight)->setSize(240, 40); // Unlocked missile aim dial and lock controls. - missile_aim = new GuiRotationDial(left_panel, "MISSILE_AIM", -90, 360 - 90, 0, [this](float value){ + missile_aim = new GuiRotationDial(this, "MISSILE_AIM", -90, 360 - 90, 0, [this](float value){ tube_controls->setMissileTargetAngle(value); }); missile_aim->setPosition(0, 0, ACenter)->setSize(GuiElement::GuiSizeMatchHeight, 700); // Weapon tube controls. - tube_controls = new GuiMissileTubeControls(left_panel, "MISSILE_TUBES"); + tube_controls = new GuiMissileTubeControls(this, "MISSILE_TUBES"); tube_controls->setPosition(20, -20, ABottomLeft); radar->enableTargetProjections(tube_controls); // Engine layout in top left corner of left panel. - GuiAutoLayout* engine_layout = new GuiAutoLayout(left_panel, "ENGINE_LAYOUT", GuiAutoLayout::LayoutHorizontalLeftToRight); + GuiAutoLayout* engine_layout = new GuiAutoLayout(this, "ENGINE_LAYOUT", GuiAutoLayout::LayoutHorizontalLeftToRight); engine_layout->setPosition(20, 80, ATopLeft)->setSize(GuiElement::GuiSizeMax, 250); (new GuiImpulseControls(engine_layout, "IMPULSE"))->setSize(100, GuiElement::GuiSizeMax); warp_controls = (new GuiWarpControls(engine_layout, "WARP"))->setSize(100, GuiElement::GuiSizeMax); jump_controls = (new GuiJumpControls(engine_layout, "JUMP"))->setSize(100, GuiElement::GuiSizeMax); // Docking, comms, and shields buttons across top. - (new GuiDockingButton(left_panel, "DOCKING"))->setPosition(20, 20, ATopLeft)->setSize(250, 50); - (new GuiOpenCommsButton(left_panel, "OPEN_COMMS_BUTTON", "Open Comms", &targets))->setPosition(270, 20, ATopLeft)->setSize(250, 50); + (new GuiDockingButton(this, "DOCKING"))->setPosition(20, 20, ATopLeft)->setSize(250, 50); + (new GuiOpenCommsButton(this, "OPEN_COMMS_BUTTON", tr("Open Comms"), &targets))->setPosition(270, 20, ATopLeft)->setSize(250, 50); (new GuiCommsOverlay(this))->setSize(GuiElement::GuiSizeMax, GuiElement::GuiSizeMax); - (new GuiShieldsEnableButton(left_panel, "SHIELDS_ENABLE"))->setPosition(520, 20, ATopLeft)->setSize(250, 50); + (new GuiShieldsEnableButton(this, "SHIELDS_ENABLE"))->setPosition(520, 20, ATopLeft)->setSize(250, 50); // Missile lock button near top right of left panel. - lock_aim = new AimLockButton(left_panel, "LOCK_AIM", tube_controls, missile_aim); + lock_aim = new AimLockButton(this, "LOCK_AIM", tube_controls, missile_aim); lock_aim->setPosition(250, 70, ATopCenter)->setSize(130, 50); (new GuiCustomShipFunctions(this, singlePilot, ""))->setPosition(-20, 120, ATopRight)->setSize(250, GuiElement::GuiSizeMax); @@ -135,69 +126,31 @@ void SinglePilotScreen::onDraw(sf::RenderTarget& window) targets.set(my_spaceship->getTarget()); } GuiOverlay::onDraw(window); +} - // Responsively show/hide the 3D viewport. - if (viewport->getRect().width < viewport->getRect().height / 3.0f) - { - viewport->hide(); - left_panel->setSize(GuiElement::GuiSizeMax, GuiElement::GuiSizeMax); - } else { - viewport->show(); - left_panel->setSize(1000, GuiElement::GuiSizeMax); - } - - if (my_spaceship) +bool SinglePilotScreen::onJoystickAxis(const AxisAction& axisAction) +{ + if(my_spaceship) { - float target_camera_yaw = my_spaceship->getRotation(); - camera_pitch = 30.0f; - - float camera_ship_distance = 420.0f; - float camera_ship_height = 420.0f; - - if (first_person) - { - camera_ship_distance = -(my_spaceship->getRadius() * 1.5); - camera_ship_height = my_spaceship->getRadius() / 10.f; - camera_pitch = 0; - } - - sf::Vector2f cameraPosition2D = my_spaceship->getPosition() + sf::vector2FromAngle(target_camera_yaw) * -camera_ship_distance; - sf::Vector3f targetCameraPosition(cameraPosition2D.x, cameraPosition2D.y, camera_ship_height); -#ifdef DEBUG - if (sf::Keyboard::isKeyPressed(sf::Keyboard::Z)) - { - targetCameraPosition.x = my_spaceship->getPosition().x; - targetCameraPosition.y = my_spaceship->getPosition().y; - targetCameraPosition.z = 3000.0; - camera_pitch = 90.0f; - } -#endif - if (first_person) + if (axisAction.category == "HELMS") { - camera_position = targetCameraPosition; - camera_yaw = target_camera_yaw; - } else { - camera_position = camera_position * 0.9f + targetCameraPosition * 0.1f; - camera_yaw += sf::angleDifference(camera_yaw, target_camera_yaw) * 0.1f; - } - } -} -bool SinglePilotScreen::onJoystickAxis(const AxisAction& axisAction){ - if(my_spaceship){ - if (axisAction.category == "HELMS"){ - if (axisAction.action == "IMPULSE"){ - my_spaceship->commandImpulse(axisAction.value); + if (axisAction.action == "IMPULSE") + { + my_spaceship->commandImpulse(axisAction.value); return true; - } - if (axisAction.action == "ROTATE"){ + } + if (axisAction.action == "ROTATE") + { my_spaceship->commandTurnSpeed(axisAction.value); return true; - } - if (axisAction.action == "STRAFE"){ + } + if (axisAction.action == "STRAFE") + { my_spaceship->commandCombatManeuverStrafe(axisAction.value); return true; - } - if (axisAction.action == "BOOST"){ + } + if (axisAction.action == "BOOST") + { my_spaceship->commandCombatManeuverBoost(axisAction.value); return true; } diff --git a/src/screens/crew1/singlePilotScreen.h b/src/screens/crew1/singlePilotScreen.h index d5a57afec6..de955d415f 100644 --- a/src/screens/crew1/singlePilotScreen.h +++ b/src/screens/crew1/singlePilotScreen.h @@ -11,24 +11,21 @@ class GuiRadarView; class GuiKeyValueDisplay; class GuiToggleButton; class GuiRotationDial; +class GuiCombatManeuver; class SinglePilotScreen : public GuiOverlay { private: - bool first_person; - GuiOverlay* background_gradient; GuiOverlay* background_crosses; - GuiViewport3D* viewport; - GuiElement* left_panel; - GuiKeyValueDisplay* energy_display; GuiKeyValueDisplay* heading_display; GuiKeyValueDisplay* velocity_display; GuiKeyValueDisplay* shields_display; GuiElement* warp_controls; GuiElement* jump_controls; + GuiCombatManeuver* combat_maneuver; TargetsContainer targets; GuiRadarView* radar; diff --git a/src/screens/crew4/operationsScreen.cpp b/src/screens/crew4/operationsScreen.cpp index 6d08faa424..721db4bda8 100644 --- a/src/screens/crew4/operationsScreen.cpp +++ b/src/screens/crew4/operationsScreen.cpp @@ -58,15 +58,15 @@ OperationScreen::OperationScreen(GuiContainer* owner) } } ); - (new GuiOpenCommsButton(science->radar_view, "OPEN_COMMS_BUTTON", "Open Comms", &science->targets))->setPosition(-270, -20, ABottomRight)->setSize(200, 50); + (new GuiOpenCommsButton(science->radar_view, "OPEN_COMMS_BUTTON", tr("Open Comms"), &science->targets))->setPosition(-270, -20, ABottomRight)->setSize(200, 50); // Manage waypoints. - place_waypoint_button = new GuiButton(science->radar_view, "WAYPOINT_PLACE_BUTTON", "Place waypoint", [this, science]() { + place_waypoint_button = new GuiButton(science->radar_view, "WAYPOINT_PLACE_BUTTON", tr("Place Waypoint"), [this, science]() { mode = WaypointPlacement; }); place_waypoint_button->setPosition(-270, -70, ABottomRight)->setSize(200, 50); - delete_waypoint_button = new GuiButton(science->radar_view, "WAYPOINT_DELETE_BUTTON", "Delete waypoint", [this, science]() { + delete_waypoint_button = new GuiButton(science->radar_view, "WAYPOINT_DELETE_BUTTON", tr("Delete Waypoint"), [this, science]() { if (my_spaceship && science->targets.getWaypointIndex() >= 0) { my_spaceship->commandRemoveWaypoint(science->targets.getWaypointIndex()); diff --git a/src/screens/crew4/operationsScreen.h b/src/screens/crew4/operationsScreen.h index 61ae9f5295..f5e8f30993 100644 --- a/src/screens/crew4/operationsScreen.h +++ b/src/screens/crew4/operationsScreen.h @@ -20,7 +20,6 @@ class OperationScreen : public GuiOverlay EMode mode; int drag_waypoint_index; - GuiKeyValueDisplay* info_reputation; GuiButton* place_waypoint_button; GuiButton* delete_waypoint_button; diff --git a/src/screens/crew4/tacticalScreen.cpp b/src/screens/crew4/tacticalScreen.cpp index 73a89c7bc7..eb5dcb40e4 100644 --- a/src/screens/crew4/tacticalScreen.cpp +++ b/src/screens/crew4/tacticalScreen.cpp @@ -63,13 +63,13 @@ TacticalScreen::TacticalScreen(GuiContainer* owner) radar->setAutoRotating(PreferencesManager::get("tactical_radar_lock","0")=="1"); // Ship statistics in the top left corner. - energy_display = new GuiKeyValueDisplay(this, "ENERGY_DISPLAY", 0.45, "Energy", ""); + energy_display = new GuiKeyValueDisplay(this, "ENERGY_DISPLAY", 0.45, tr("Energy"), ""); energy_display->setIcon("gui/icons/energy")->setTextSize(20)->setPosition(20, 100, ATopLeft)->setSize(240, 40); - heading_display = new GuiKeyValueDisplay(this, "HEADING_DISPLAY", 0.45, "Heading", ""); + heading_display = new GuiKeyValueDisplay(this, "HEADING_DISPLAY", 0.45, tr("Heading"), ""); heading_display->setIcon("gui/icons/heading")->setTextSize(20)->setPosition(20, 140, ATopLeft)->setSize(240, 40); - velocity_display = new GuiKeyValueDisplay(this, "VELOCITY_DISPLAY", 0.45, "Speed", ""); + velocity_display = new GuiKeyValueDisplay(this, "VELOCITY_DISPLAY", 0.45, tr("Speed"), ""); velocity_display->setIcon("gui/icons/speed")->setTextSize(20)->setPosition(20, 180, ATopLeft)->setSize(240, 40); - shields_display = new GuiKeyValueDisplay(this, "SHIELDS_DISPLAY", 0.45, "Shields", ""); + shields_display = new GuiKeyValueDisplay(this, "SHIELDS_DISPLAY", 0.45, tr("Shields"), ""); shields_display->setIcon("gui/icons/shields")->setTextSize(20)->setPosition(20, 220, ATopLeft)->setSize(240, 40); // Weapon tube loading controls in the bottom left corner. @@ -82,7 +82,7 @@ TacticalScreen::TacticalScreen(GuiContainer* owner) { GuiElement* beam_info_box = new GuiElement(this, "BEAM_INFO_BOX"); beam_info_box->setPosition(0, -20, ABottomCenter)->setSize(500, 50); - (new GuiLabel(beam_info_box, "BEAM_INFO_LABEL", "Beams", 30))->addBackground()->setPosition(0, 0, ABottomLeft)->setSize(80, 50); + (new GuiLabel(beam_info_box, "BEAM_INFO_LABEL", tr("Beams"), 30))->addBackground()->setPosition(0, 0, ABottomLeft)->setSize(80, 50); (new GuiBeamFrequencySelector(beam_info_box, "BEAM_FREQUENCY_SELECTOR"))->setPosition(80, 0, ABottomLeft)->setSize(132, 50); (new GuiPowerDamageIndicator(beam_info_box, "", SYS_BeamWeapons, ACenterLeft))->setPosition(0, 0, ABottomLeft)->setSize(212, 50); (new GuiBeamTargetSelector(beam_info_box, "BEAM_TARGET_SELECTOR"))->setPosition(0, 0, ABottomRight)->setSize(288, 50); @@ -115,7 +115,7 @@ void TacticalScreen::onDraw(sf::RenderTarget& window) energy_display->setValue(string(int(my_spaceship->energy_level))); heading_display->setValue(string(fmodf(my_spaceship->getRotation() + 360.0 + 360.0 - 270.0, 360.0), 1)); float velocity = sf::length(my_spaceship->getVelocity()) / 1000 * 60; - velocity_display->setValue(string(velocity, 1) + DISTANCE_UNIT_1K + "/min"); + velocity_display->setValue(tr("{value} {unit}/min").format({{"value", string(velocity, 1)}, {"unit", DISTANCE_UNIT_1K}})); warp_controls->setVisible(my_spaceship->has_warp_drive); jump_controls->setVisible(my_spaceship->has_jump_drive); diff --git a/src/screens/crew6/engineeringScreen.cpp b/src/screens/crew6/engineeringScreen.cpp index 58a9a3e29b..1268930178 100644 --- a/src/screens/crew6/engineeringScreen.cpp +++ b/src/screens/crew6/engineeringScreen.cpp @@ -38,7 +38,8 @@ EngineeringScreen::EngineeringScreen(GuiContainer* owner, ECrewPosition crew_pos coolant_display = new GuiKeyValueDisplay(this, "COOLANT_DISPLAY", 0.45, tr("total","Coolant"), ""); coolant_display->setIcon("gui/icons/coolant")->setTextSize(20)->setPosition(20, 260, ATopLeft)->setSize(240, 40); - (new GuiSelfDestructButton(this, "SELF_DESTRUCT"))->setPosition(20, 20, ATopLeft)->setSize(240, 100); + self_destruct_button = new GuiSelfDestructButton(this, "SELF_DESTRUCT"); + self_destruct_button->setPosition(20, 20, ATopLeft)->setSize(240, 100)->setVisible(my_spaceship && my_spaceship->getCanSelfDestruct()); GuiElement* system_config_container = new GuiElement(this, ""); system_config_container->setPosition(0, -20, ABottomCenter)->setSize(750 + 300, GuiElement::GuiSizeMax); @@ -150,7 +151,7 @@ void EngineeringScreen::onDraw(sf::RenderTarget& window) { if (my_spaceship) { - //Update the energy usage. + // Update the energy usage. if (previous_energy_measurement == 0.0) { previous_energy_level = my_spaceship->energy_level; diff --git a/src/screens/crew6/engineeringScreen.h b/src/screens/crew6/engineeringScreen.h index 755808fe9b..605fa86bbc 100644 --- a/src/screens/crew6/engineeringScreen.h +++ b/src/screens/crew6/engineeringScreen.h @@ -5,6 +5,7 @@ #include "shipTemplate.h" #include "playerInfo.h" +class GuiSelfDestructButton; class GuiKeyValueDisplay; class GuiLabel; class GuiSlider; @@ -18,7 +19,6 @@ class GuiProgressSlider; class EngineeringScreen : public GuiOverlay { private: - GuiOverlay* background_gradient; GuiOverlay* background_crosses; GuiKeyValueDisplay* energy_display; @@ -26,6 +26,7 @@ class EngineeringScreen : public GuiOverlay GuiKeyValueDisplay* front_shield_display; GuiKeyValueDisplay* rear_shield_display; GuiKeyValueDisplay* coolant_display; + GuiSelfDestructButton* self_destruct_button; GuiLabel* power_label; GuiSlider* power_slider; GuiLabel* coolant_label; diff --git a/src/screens/crew6/helmsScreen.cpp b/src/screens/crew6/helmsScreen.cpp index 599a1c336a..c4ee64cd07 100644 --- a/src/screens/crew6/helmsScreen.cpp +++ b/src/screens/crew6/helmsScreen.cpp @@ -4,6 +4,7 @@ #include "helmsScreen.h" #include "preferenceManager.h" +#include "screenComponents/combatManeuver.h" #include "screenComponents/radarView.h" #include "screenComponents/impulseControls.h" #include "screenComponents/warpControls.h" @@ -33,8 +34,8 @@ HelmsScreen::HelmsScreen(GuiContainer* owner) GuiRadarView* radar = new GuiRadarView(this, "HELMS_RADAR", nullptr); combat_maneuver = new GuiCombatManeuver(this, "COMBAT_MANEUVER"); - combat_maneuver->setPosition(-20, -20, ABottomRight)->setSize(280, 215); - + combat_maneuver->setPosition(-20, -20, ABottomRight)->setSize(280, 215)->setVisible(my_spaceship && my_spaceship->getCanCombatManeuver()); + radar->setPosition(0, 0, ACenter)->setSize(GuiElement::GuiSizeMatchHeight, 800); radar->setRangeIndicatorStepSize(1000.0)->shortRange()->enableGhostDots()->enableWaypoints()->enableCallsigns()->enableHeadingIndicators()->setStyle(GuiRadarView::Circular); radar->enableMissileTubeIndicators(); @@ -79,7 +80,8 @@ HelmsScreen::HelmsScreen(GuiContainer* owner) warp_controls = (new GuiWarpControls(engine_layout, "WARP"))->setSize(100, GuiElement::GuiSizeMax); jump_controls = (new GuiJumpControls(engine_layout, "JUMP"))->setSize(100, GuiElement::GuiSizeMax); - (new GuiDockingButton(this, "DOCKING"))->setPosition(20, -20, ABottomLeft)->setSize(280, 50); + docking_button = new GuiDockingButton(this, "DOCKING"); + docking_button->setPosition(20, -20, ABottomLeft)->setSize(280, 50)->setVisible(my_spaceship && my_spaceship->getCanDock()); (new GuiCustomShipFunctions(this, helmsOfficer, ""))->setPosition(-20, 120, ATopRight)->setSize(250, GuiElement::GuiSizeMax); } @@ -100,23 +102,32 @@ void HelmsScreen::onDraw(sf::RenderTarget& window) } bool HelmsScreen::onJoystickAxis(const AxisAction& axisAction){ - if(my_spaceship){ - if (axisAction.category == "HELMS"){ - if (axisAction.action == "IMPULSE"){ - my_spaceship->commandImpulse(axisAction.value); + if (my_spaceship) + { + if (axisAction.category == "HELMS") + { + if (axisAction.action == "IMPULSE") + { + my_spaceship->commandImpulse(axisAction.value); return true; - } - if (axisAction.action == "ROTATE"){ + } + if (axisAction.action == "ROTATE") + { my_spaceship->commandTurnSpeed(axisAction.value); return true; - } - if (axisAction.action == "STRAFE"){ - my_spaceship->commandCombatManeuverStrafe(axisAction.value); - return true; - } - if (axisAction.action == "BOOST"){ - my_spaceship->commandCombatManeuverBoost(axisAction.value); - return true; + } + if (my_spaceship->getCanCombatManeuver()) + { + if (axisAction.action == "STRAFE") + { + my_spaceship->commandCombatManeuverStrafe(axisAction.value); + return true; + } + if (axisAction.action == "BOOST") + { + my_spaceship->commandCombatManeuverBoost(axisAction.value); + return true; + } } } } diff --git a/src/screens/crew6/helmsScreen.h b/src/screens/crew6/helmsScreen.h index 3cb4e7f29c..2ae155da28 100644 --- a/src/screens/crew6/helmsScreen.h +++ b/src/screens/crew6/helmsScreen.h @@ -2,11 +2,12 @@ #define HELMS_SCREEN_H #include "gui/gui2_overlay.h" -#include "screenComponents/combatManeuver.h" #include "gui/joystickConfig.h" class GuiKeyValueDisplay; class GuiLabel; +class GuiDockingButton; +class GuiCombatManeuver; class HelmsScreen : public GuiOverlay { @@ -21,6 +22,7 @@ class HelmsScreen : public GuiOverlay GuiElement* jump_controls; GuiLabel* heading_hint; GuiCombatManeuver* combat_maneuver; + GuiDockingButton* docking_button; public: HelmsScreen(GuiContainer* owner); diff --git a/src/screens/crew6/relayScreen.cpp b/src/screens/crew6/relayScreen.cpp index 9a7b10fca1..b6f69a34f8 100644 --- a/src/screens/crew6/relayScreen.cpp +++ b/src/screens/crew6/relayScreen.cpp @@ -1,4 +1,5 @@ #include "relayScreen.h" +#include "gameGlobalInfo.h" #include "playerInfo.h" #include "spaceObjects/playerSpaceship.h" #include "spaceObjects/scanProbe.h" @@ -119,7 +120,7 @@ RelayScreen::RelayScreen(GuiContainer* owner, bool allow_comms) else my_spaceship->commandSetScienceLink(-1); }); - link_to_science_button->setSize(GuiElement::GuiSizeMax, 50); + link_to_science_button->setSize(GuiElement::GuiSizeMax, 50)->setVisible(my_spaceship && my_spaceship->getCanLaunchProbe()); // Manage waypoints. (new GuiButton(option_buttons, "WAYPOINT_PLACE_BUTTON", tr("Place Waypoint"), [this]() { @@ -140,12 +141,16 @@ RelayScreen::RelayScreen(GuiContainer* owner, bool allow_comms) mode = LaunchProbe; option_buttons->hide(); }); - launch_probe_button->setSize(GuiElement::GuiSizeMax, 50); + launch_probe_button->setSize(GuiElement::GuiSizeMax, 50)->setVisible(my_spaceship && my_spaceship->getCanLaunchProbe()); // Reputation display. info_reputation = new GuiKeyValueDisplay(option_buttons, "INFO_REPUTATION", 0.7, tr("Reputation:"), ""); info_reputation->setSize(GuiElement::GuiSizeMax, 40); + // Mission clock display. + info_clock = new GuiKeyValueDisplay(option_buttons, "INFO_CLOCK", 0.7, tr("Mission Clock") + ":", ""); + info_clock->setSize(GuiElement::GuiSizeMax, 40); + // Bottom layout. GuiAutoLayout* layout = new GuiAutoLayout(this, "", GuiAutoLayout::LayoutVerticalBottomToTop); layout->setPosition(-20, -70, ABottomRight)->setSize(300, GuiElement::GuiSizeMax); @@ -274,7 +279,13 @@ void RelayScreen::onDraw(sf::RenderTarget& window) } if (my_spaceship) { + // Toggle ship capabilities. + launch_probe_button->setVisible(my_spaceship->getCanLaunchProbe()); + link_to_science_button->setVisible(my_spaceship->getCanLaunchProbe()); + hack_target_button->setVisible(my_spaceship->getCanHack()); + info_reputation->setValue(string(my_spaceship->getReputationPoints(), 0)); + info_clock->setValue(string(gameGlobalInfo->elapsed_time, 0)); launch_probe_button->setText(tr("Launch Probe") + " (" + string(my_spaceship->scan_probe_stock) + ")"); } diff --git a/src/screens/crew6/relayScreen.h b/src/screens/crew6/relayScreen.h index ac127e7577..85ca262eaa 100644 --- a/src/screens/crew6/relayScreen.h +++ b/src/screens/crew6/relayScreen.h @@ -33,6 +33,7 @@ class RelayScreen : public GuiOverlay GuiKeyValueDisplay* info_faction; GuiKeyValueDisplay* info_reputation; + GuiKeyValueDisplay* info_clock; GuiAutoLayout* option_buttons; GuiButton* hack_target_button; GuiToggleButton* link_to_science_button; diff --git a/src/screens/crew6/scienceScreen.cpp b/src/screens/crew6/scienceScreen.cpp index 7a3c2afee2..e90f23e6d1 100644 --- a/src/screens/crew6/scienceScreen.cpp +++ b/src/screens/crew6/scienceScreen.cpp @@ -88,7 +88,7 @@ ScienceScreen::ScienceScreen(GuiContainer* owner, ECrewPosition crew_position) // Scan button. scan_button = new GuiScanTargetButton(info_sidebar, "SCAN_BUTTON", &targets); - scan_button->setSize(GuiElement::GuiSizeMax, 50); + scan_button->setSize(GuiElement::GuiSizeMax, 50)->setVisible(my_spaceship && my_spaceship->getCanScan()); // Simple scan data. info_callsign = new GuiKeyValueDisplay(info_sidebar, "SCIENCE_CALLSIGN", 0.4, tr("Callsign"), ""); @@ -450,6 +450,7 @@ void ScienceScreen::onHotkey(const HotkeyResult& key) { // Initiate a scan on scannable objects. if (key.hotkey == "SCAN_OBJECT" && + my_spaceship->getCanScan() && my_spaceship->scanning_delay == 0.0) { P obj = targets.get(); diff --git a/src/screens/crewStationScreen.cpp b/src/screens/crewStationScreen.cpp index 0d4a3667fb..69a8cf3d83 100644 --- a/src/screens/crewStationScreen.cpp +++ b/src/screens/crewStationScreen.cpp @@ -9,6 +9,8 @@ #include "screenComponents/noiseOverlay.h" #include "screenComponents/shipDestroyedPopup.h" #include "screenComponents/helpOverlay.h" +#include "screenComponents/impulseSound.h" +#include "screenComponents/viewportMainScreen.h" #include "gui/gui2_togglebutton.h" #include "gui/gui2_panel.h" @@ -17,17 +19,26 @@ CrewStationScreen::CrewStationScreen() { - select_station_button = new GuiButton(this, "", "", [this]() + // Create a 3D viewport behind everything, to serve as the right-side panel + viewport = new GuiViewportMainScreen(this, "3D_VIEW"); + viewport->showCallsigns()->showHeadings()->showSpacedust(); + viewport->setPosition(1200, 0, ATopLeft)->setSize(GuiElement::GuiSizeMax, GuiElement::GuiSizeMax); + viewport->hide(); + + main_panel = new GuiElement(this, "MAIN"); + main_panel->setSize(1200, GuiElement::GuiSizeMax); + + select_station_button = new GuiButton(main_panel, "", "", [this]() { button_strip->show(); }); select_station_button->setPosition(-20, 20, ATopRight)->setSize(250, 50); - button_strip = new GuiPanel(this, ""); + button_strip = new GuiPanel(main_panel, ""); button_strip->setPosition(-20, 20, ATopRight)->setSize(250, 50); button_strip->hide(); - message_frame = new GuiPanel(this, ""); + message_frame = new GuiPanel(main_panel, ""); message_frame->setPosition(0, 0, ATopCenter)->setSize(900, 230)->hide(); message_text = new GuiScrollText(message_frame, "", ""); @@ -47,7 +58,7 @@ CrewStationScreen::CrewStationScreen() }); message_close_button->setTextSize(30)->setPosition(-20, -20, ABottomRight)->setSize(300, 30); - keyboard_help = new GuiHelpOverlay(this, "Keyboard Shortcuts"); + keyboard_help = new GuiHelpOverlay(main_panel, "Keyboard Shortcuts"); for (std::pair shortcut : listControlsByCategory("General")) keyboard_general += shortcut.second + ":\t" + shortcut.first + "\n"; @@ -65,12 +76,20 @@ CrewStationScreen::CrewStationScreen() }); } #endif + + // Initialize and play the impulse engine sound. + impulse_sound = std::unique_ptr( new ImpulseSound(PreferencesManager::get("impulse_sound_enabled", "2") == "1") ); +} + +GuiContainer* CrewStationScreen::getTabContainer() +{ + return main_panel; } void CrewStationScreen::addStationTab(GuiElement* element, ECrewPosition position, string name, string icon) { CrewTabInfo info; - + tileViewport(); element->setSize(GuiElement::GuiSizeMax, GuiElement::GuiSizeMax); info.position = position; info.element = element; @@ -94,7 +113,7 @@ void CrewStationScreen::addStationTab(GuiElement* element, ECrewPosition positio for (std::pair shortcut : listControlsByCategory(info.button->getText())) keyboard_category += shortcut.second + ":\t" + shortcut.first + "\n"; - if (keyboard_category == "") // special hotkey combination for crew1 and crew4 screens + if (keyboard_category == "") // special hotkey combination for crew1 and crew4 screens keyboard_category = listHotkeysLimited(info.button->getText()); keyboard_help->setText(keyboard_general + keyboard_category); @@ -130,13 +149,27 @@ void CrewStationScreen::update(float delta) { destroy(); soundManager->stopMusic(); + impulse_sound->stop(); disconnectFromServer(); returnToMainMenu(); return; } + + // Responsively show/hide the 3D viewport. + if (!main_screen_enabled || viewport->getRect().width < viewport->getRect().height / 3.0f) + { + viewport->hide(); + main_panel->setSize(GuiElement::GuiSizeMax, GuiElement::GuiSizeMax); + } else { + viewport->show(); + tileViewport(); + } + if (my_spaceship) { + // Show custom ship function messages. message_frame->hide(); + for(PlayerSpaceship::CustomShipFunction& csf : my_spaceship->custom_functions) { if (csf.crew_position == current_position && csf.type == PlayerSpaceship::CustomShipFunction::Type::Message) @@ -146,6 +179,13 @@ void CrewStationScreen::update(float delta) break; } } + + // Update the impulse engine sound. + impulse_sound->update(delta); + } else { + // If we're not the player ship (ie. we exploded), stop playing the + // impulse engine sound. + impulse_sound->stop(); } } @@ -179,6 +219,7 @@ void CrewStationScreen::onKey(sf::Event::KeyEvent key, int unicode) case sf::Keyboard::Home: destroy(); soundManager->stopMusic(); + impulse_sound->stop(); returnToShipSelection(); break; case sf::Keyboard::Slash: @@ -229,11 +270,11 @@ void CrewStationScreen::showTab(GuiElement* element) for (std::pair shortcut : listControlsByCategory(info.button->getText())) keyboard_category += shortcut.second + ":\t" + shortcut.first + "\n"; - if (keyboard_category == "") // special hotkey combination for crew1 and crew4 screens - keyboard_category = listHotkeysLimited(info.button->getText()); + if (keyboard_category == "") // special hotkey combination for crew1 and crew4 screens + keyboard_category = listHotkeysLimited(info.button->getText()); keyboard_help->setText(keyboard_general + keyboard_category); - }else{ + } else { info.element->hide(); info.button->setValue(false); } @@ -252,26 +293,25 @@ GuiElement* CrewStationScreen::findTab(string name) } string CrewStationScreen::listHotkeysLimited(string station) -{ - string ret = ""; - keyboard_general = ""; - for (std::pair shortcut : listControlsByCategory("General")) - if (shortcut.first == "Switch to next crew station" || shortcut.first =="Switch to previous crew station" || shortcut.first == "Switch crew station") - keyboard_general += shortcut.second + ":\t" + shortcut.first + "\n"; - if (station == "Tactical") - { - - for (std::pair shortcut : listControlsByCategory("Helms")) - ret += shortcut.second + ":\t" + shortcut.first + "\n"; - for (std::pair shortcut : listControlsByCategory("Weapons")) - { - if (shortcut.first != "Toggle shields") - ret += shortcut.second + ":\t" + shortcut.first + "\n"; - } - } - else if (station == "Engineering+") - { - for (std::pair shortcut : listControlsByCategory("Engineering")) +{ + string ret = ""; + keyboard_general = ""; + + for (std::pair shortcut : hotkeys.listHotkeysByCategory("General")) + if (shortcut.first == "Switch to next crew station" || shortcut.first =="Switch to previous crew station" || shortcut.first == "Switch crew station") + keyboard_general += shortcut.second + ":\t" + shortcut.first + "\n"; + + if (station == "Tactical") + { + for (std::pair shortcut : hotkeys.listHotkeysByCategory("Helms")) + ret += shortcut.second + ":\t" + shortcut.first + "\n"; + for (std::pair shortcut : hotkeys.listHotkeysByCategory("Weapons")) + { + if (shortcut.first != "Toggle shields") + ret += shortcut.second + ":\t" + shortcut.first + "\n"; + } + } else if (station == "Engineering+") { + for (std::pair shortcut : hotkeys.listHotkeysByCategory("Engineering")) ret += shortcut.second + ":\t" + shortcut.first + "\n"; for (std::pair shortcut : listControlsByCategory("Weapons")) { @@ -280,10 +320,10 @@ string CrewStationScreen::listHotkeysLimited(string station) } } -// -- not yet used -- -// else if (station == "Operations") -// return ret; -// ---- + // -- not yet used -- + // else if (station == "Operations") + // return ret; + // ---- else if (station == "Single Pilot") { @@ -292,9 +332,22 @@ string CrewStationScreen::listHotkeysLimited(string station) for (std::pair shortcut : listControlsByCategory("Weapons")) ret += shortcut.second + ":\t" + shortcut.first + "\n"; } + return ret; } +void CrewStationScreen::tileViewport() +{ + if (current_position == singlePilot) + { + main_panel->setSize(1000, GuiElement::GuiSizeMax); + viewport->setPosition(1000, 0, ATopLeft); + } else { + main_panel->setSize(1200, GuiElement::GuiSizeMax); + viewport->setPosition(1200, 0, ATopLeft); + } +} + std::vector> CrewStationScreen::listControlsByCategory(string category){ std::vector> hotkeyControls = hotkeys.listHotkeysByCategory(category); std::vector> joystickControls = joystick.listJoystickByCategory(category); diff --git a/src/screens/crewStationScreen.h b/src/screens/crewStationScreen.h index f1c696195f..21958ecf2b 100644 --- a/src/screens/crewStationScreen.h +++ b/src/screens/crewStationScreen.h @@ -14,32 +14,42 @@ class GuiButton; class GuiHelpOverlay; class GuiPanel; class GuiToggleButton; +class GuiViewport3D; +class ImpulseSound; class CrewStationScreen : public GuiCanvas, public Updatable { P threat_estimate; public: CrewStationScreen(); + + GuiContainer* getTabContainer(); void addStationTab(GuiElement* element, ECrewPosition position, string name, string icon); + void enableMainScreen() { main_screen_enabled = true; } void finishCreation(); - + virtual void update(float delta) override; virtual void onHotkey(const HotkeyResult& key) override; virtual void onKey(sf::Event::KeyEvent key, int unicode) override; private: + GuiElement* main_panel; + GuiViewport3D* viewport; GuiButton* select_station_button; GuiPanel* button_strip; GuiHelpOverlay* keyboard_help; GuiPanel* message_frame; GuiScrollText* message_text; GuiButton* message_close_button; + std::unique_ptr impulse_sound; + bool main_screen_enabled = false; struct CrewTabInfo { GuiToggleButton* button; GuiElement* element; ECrewPosition position; }; + ECrewPosition current_position; std::vector tabs; string keyboard_general = ""; @@ -49,6 +59,7 @@ class CrewStationScreen : public GuiCanvas, public Updatable GuiElement* findTab(string name); string listHotkeysLimited(string station); + void tileViewport(); std::vector> listControlsByCategory(string category); }; diff --git a/src/screens/extra/shipLogScreen.cpp b/src/screens/extra/shipLogScreen.cpp index 72e7c31f9b..e6e22514c1 100644 --- a/src/screens/extra/shipLogScreen.cpp +++ b/src/screens/extra/shipLogScreen.cpp @@ -3,15 +3,19 @@ #include "spaceObjects/playerSpaceship.h" #include "gui/gui2_advancedscrolltext.h" +#include "screenComponents/customShipFunctions.h" ShipLogScreen::ShipLogScreen(GuiContainer* owner) : GuiOverlay(owner, "SHIP_LOG_SCREEN", colorConfig.background) { + GuiAutoLayout* shiplog_layout = new GuiAutoLayout(this, "SHIPLOG_LAYOUT", GuiAutoLayout::LayoutHorizontalRightToLeft); + shiplog_layout->setPosition(50, 120)->setSize(GuiElement::GuiSizeMax, GuiElement::GuiSizeMax); + custom_function_sidebar= new GuiCustomShipFunctions(shiplog_layout, shipLog, ""); + custom_function_sidebar->setSize(270, GuiElement::GuiSizeMax); (new GuiOverlay(this, "", sf::Color::White))->setTextureTiled("gui/BackgroundCrosses"); - - log_text = new GuiAdvancedScrollText(this, "SHIP_LOG"); + log_text = new GuiAdvancedScrollText(shiplog_layout, "SHIP_LOG"); log_text->enableAutoScrollDown(); - log_text->setPosition(50, 50)->setSize(GuiElement::GuiSizeMax, GuiElement::GuiSizeMax); + log_text->setSize(GuiElement::GuiSizeMax, GuiElement::GuiSizeMax); } void ShipLogScreen::onDraw(sf::RenderTarget& window) @@ -20,6 +24,11 @@ void ShipLogScreen::onDraw(sf::RenderTarget& window) if (my_spaceship) { + if (custom_function_sidebar->hasEntries()) + custom_function_sidebar->show(); + else + custom_function_sidebar->hide(); + const std::vector& logs = my_spaceship->getShipsLog(); if (log_text->getEntryCount() > 0 && logs.size() == 0) log_text->clearEntries(); diff --git a/src/screens/extra/shipLogScreen.h b/src/screens/extra/shipLogScreen.h index 4c9a52320b..5490020b62 100644 --- a/src/screens/extra/shipLogScreen.h +++ b/src/screens/extra/shipLogScreen.h @@ -4,11 +4,13 @@ #include "gui/gui2_overlay.h" class GuiAdvancedScrollText; +class GuiCustomShipFunctions; class ShipLogScreen : public GuiOverlay { private: GuiAdvancedScrollText* log_text; + GuiCustomShipFunctions* custom_function_sidebar; public: ShipLogScreen(GuiContainer* owner); diff --git a/src/screens/gm/gameMasterScreen.cpp b/src/screens/gm/gameMasterScreen.cpp index 7b3769fbf0..e3a2690447 100644 --- a/src/screens/gm/gameMasterScreen.cpp +++ b/src/screens/gm/gameMasterScreen.cpp @@ -128,7 +128,10 @@ GameMasterScreen::GameMasterScreen() info_layout = new GuiAutoLayout(this, "INFO_LAYOUT", GuiAutoLayout::LayoutVerticalTopToBottom); info_layout->setPosition(-20, 20, ATopRight)->setSize(300, GuiElement::GuiSizeMax); - + + info_clock = new GuiKeyValueDisplay(info_layout, "INFO_CLOCK", 0.5, tr("Mission Clock"), ""); + info_clock->setSize(GuiElement::GuiSizeMax, 30); + gm_script_options = new GuiListbox(this, "GM_SCRIPT_OPTIONS", [this](int index, string value) { gm_script_options->setSelectionIndex(-1); @@ -274,7 +277,10 @@ void GameMasterScreen::update(float delta) order_layout->setVisible(has_cpu_ship); player_comms_hail->setVisible(has_player_ship); - + + // Update mission clock + info_clock->setValue(string(gameGlobalInfo->elapsed_time, 0)); + std::unordered_map selection_info; // For each selected object, determine and report their type. @@ -298,7 +304,7 @@ void GameMasterScreen::update(float delta) { selection_info["Position"] = string(targets.getTargets()[0]->getPosition().x, 0) + "," + string(targets.getTargets()[0]->getPosition().y, 0); } - + unsigned int cnt = 0; for(std::unordered_map::iterator i = selection_info.begin(); i != selection_info.end(); i++) { diff --git a/src/screens/gm/gameMasterScreen.h b/src/screens/gm/gameMasterScreen.h index 2e07213c28..a549c26733 100644 --- a/src/screens/gm/gameMasterScreen.h +++ b/src/screens/gm/gameMasterScreen.h @@ -42,6 +42,7 @@ class GameMasterScreen : public GuiCanvas, public Updatable GuiAutoLayout* info_layout; std::vector info_items; + GuiKeyValueDisplay* info_clock; GuiListbox* gm_script_options; GuiAutoLayout* order_layout; GuiButton* player_comms_hail; diff --git a/src/screens/gm/tweak.cpp b/src/screens/gm/tweak.cpp index 2d5408b779..8d8457d3f7 100644 --- a/src/screens/gm/tweak.cpp +++ b/src/screens/gm/tweak.cpp @@ -691,6 +691,41 @@ GuiShipTweakPlayer2::GuiShipTweakPlayer2(GuiContainer* owner) long_range_radar_slider->addOverlay()->setSize(GuiElement::GuiSizeMax, 40); // Right column + // Can scan bool + can_scan = new GuiToggleButton(right_col, "", "Can scan", [this](bool value) { + target->setCanScan(value); + }); + can_scan->setSize(GuiElement::GuiSizeMax, 40); + + // Can hack bool + can_hack = new GuiToggleButton(right_col, "", "Can hack", [this](bool value) { + target->setCanHack(value); + }); + can_hack->setSize(GuiElement::GuiSizeMax, 40); + + // Can dock bool + can_dock = new GuiToggleButton(right_col, "", "Can dock", [this](bool value) { + target->setCanDock(value); + }); + can_dock->setSize(GuiElement::GuiSizeMax, 40); + + // Can combat maneuver bool + can_combat_maneuver = new GuiToggleButton(right_col, "", "Can combat maneuver", [this](bool value) { + target->setCanCombatManeuver(value); + }); + can_combat_maneuver->setSize(GuiElement::GuiSizeMax, 40); + + // Can self destruct bool + can_self_destruct = new GuiToggleButton(right_col, "", "Can self destruct", [this](bool value) { + target->setCanSelfDestruct(value); + }); + can_self_destruct->setSize(GuiElement::GuiSizeMax, 40); + + // Can launch probe bool + can_launch_probe = new GuiToggleButton(right_col, "", "Can launch probes", [this](bool value) { + target->setCanLaunchProbe(value); + }); + can_launch_probe->setSize(GuiElement::GuiSizeMax, 40); } void GuiShipTweakPlayer2::onDraw(sf::RenderTarget& window) @@ -698,6 +733,12 @@ void GuiShipTweakPlayer2::onDraw(sf::RenderTarget& window) coolant_slider->setValue(target->max_coolant); short_range_radar_slider->setValue(target->getShortRangeRadarRange()); long_range_radar_slider->setValue(target->getLongRangeRadarRange()); + can_scan->setValue(target->getCanScan()); + can_hack->setValue(target->getCanHack()); + can_dock->setValue(target->getCanDock()); + can_combat_maneuver->setValue(target->getCanCombatManeuver()); + can_self_destruct->setValue(target->getCanSelfDestruct()); + can_launch_probe->setValue(target->getCanLaunchProbe()); } void GuiShipTweakPlayer2::open(P target) diff --git a/src/screens/gm/tweak.h b/src/screens/gm/tweak.h index 461fe0c024..2e20e3d1be 100644 --- a/src/screens/gm/tweak.h +++ b/src/screens/gm/tweak.h @@ -185,6 +185,12 @@ class GuiShipTweakPlayer2 : public GuiTweakPage GuiSlider* coolant_slider; GuiSlider* short_range_radar_slider; GuiSlider* long_range_radar_slider; + GuiToggleButton* can_scan; + GuiToggleButton* can_hack; + GuiToggleButton* can_dock; + GuiToggleButton* can_combat_maneuver; + GuiToggleButton* can_self_destruct; + GuiToggleButton* can_launch_probe; public: GuiShipTweakPlayer2(GuiContainer* owner); diff --git a/src/screens/mainScreen.cpp b/src/screens/mainScreen.cpp index 9d32e11e54..bd4300da73 100644 --- a/src/screens/mainScreen.cpp +++ b/src/screens/mainScreen.cpp @@ -10,9 +10,10 @@ #include "screenComponents/globalMessage.h" #include "screenComponents/jumpIndicator.h" #include "screenComponents/commsOverlay.h" -#include "screenComponents/viewport3d.h" +#include "screenComponents/viewportMainScreen.h" #include "screenComponents/radarView.h" #include "screenComponents/shipDestroyedPopup.h" +#include "screenComponents/impulseSound.h" #include "gui/gui2_panel.h" #include "gui/gui2_overlay.h" @@ -21,8 +22,7 @@ ScreenMainScreen::ScreenMainScreen() { new GuiOverlay(this, "", sf::Color::Black); - viewport = new GuiViewport3D(this, "VIEWPORT"); - viewport->showCallsigns()->showHeadings()->showSpacedust(); + viewport = new GuiViewportMainScreen(this, "VIEWPORT"); viewport->setPosition(0, 0, ATopLeft)->setSize(GuiElement::GuiSizeMax, GuiElement::GuiSizeMax); (new GuiRadarView(viewport, "VIEWPORT_RADAR", nullptr))->setStyle(GuiRadarView::CircularMasked)->setSize(200, 200)->setPosition(-20, 20, ATopRight); @@ -63,7 +63,8 @@ ScreenMainScreen::ScreenMainScreen() }); } - first_person = PreferencesManager::get("first_person") == "1"; + // Initialize and play the impulse engine sound. + impulse_sound = std::unique_ptr( new ImpulseSound(PreferencesManager::get("impulse_sound_enabled", "2") != "0") ); } void ScreenMainScreen::update(float delta) @@ -71,7 +72,7 @@ void ScreenMainScreen::update(float delta) if (game_client && game_client->getStatus() == GameClient::Disconnected) { soundManager->stopMusic(); - soundManager->stopSound(impulse_sound); + impulse_sound->stop(); destroy(); disconnectFromServer(); returnToMainMenu(); @@ -80,54 +81,6 @@ void ScreenMainScreen::update(float delta) if (my_spaceship) { - P target_ship = my_spaceship->getTarget(); - float target_camera_yaw = my_spaceship->getRotation(); - switch(my_spaceship->main_screen_setting) - { - case MSS_Back: target_camera_yaw += 180; break; - case MSS_Left: target_camera_yaw -= 90; break; - case MSS_Right: target_camera_yaw += 90; break; - case MSS_Target: - if (target_ship) - { - sf::Vector2f target_camera_diff = my_spaceship->getPosition() - target_ship->getPosition(); - target_camera_yaw = sf::vector2ToAngle(target_camera_diff) + 180; - } - break; - default: break; - } - camera_pitch = 30.0f; - - float camera_ship_distance = 420.0f; - float camera_ship_height = 420.0f; - if (first_person) - { - camera_ship_distance = -my_spaceship->getRadius(); - camera_ship_height = my_spaceship->getRadius() / 10.f; - camera_pitch = 0; - } - sf::Vector2f cameraPosition2D = my_spaceship->getPosition() + sf::vector2FromAngle(target_camera_yaw) * -camera_ship_distance; - sf::Vector3f targetCameraPosition(cameraPosition2D.x, cameraPosition2D.y, camera_ship_height); -#ifdef DEBUG - if (sf::Keyboard::isKeyPressed(sf::Keyboard::Z)) - { - targetCameraPosition.x = my_spaceship->getPosition().x; - targetCameraPosition.y = my_spaceship->getPosition().y; - targetCameraPosition.z = 3000.0; - camera_pitch = 90.0f; - } -#endif - if (first_person) - { - camera_position = targetCameraPosition; - camera_yaw = target_camera_yaw; - } - else - { - camera_position = camera_position * 0.9f + targetCameraPosition * 0.1f; - camera_yaw += sf::angleDifference(camera_yaw, target_camera_yaw) * 0.1f; - } - switch(my_spaceship->main_screen_setting) { case MSS_Front: @@ -163,29 +116,12 @@ void ScreenMainScreen::update(float delta) break; } - // If we have an impulse power, loop the engine sound. - float impulse_ability = std::max(0.0f, std::min(my_spaceship->getSystemEffectiveness(SYS_Impulse), my_spaceship->getSystemPower(SYS_Impulse))); - string impulse_sound_file = my_spaceship->impulse_sound_file; - if (impulse_ability > 0 && impulse_sound_file.length() > 0) - { - if (impulse_sound > -1) - { - soundManager->setSoundVolume(impulse_sound, std::max(10.0f * impulse_ability, fabsf(my_spaceship->current_impulse) * 10.0f * std::max(0.1f, impulse_ability))); - soundManager->setSoundPitch(impulse_sound, std::max(0.7f * impulse_ability, fabsf(my_spaceship->current_impulse) + 0.2f * std::max(0.1f, impulse_ability))); - } - else - { - impulse_sound = soundManager->playSound(impulse_sound_file, std::max(0.7f * impulse_ability, fabsf(my_spaceship->current_impulse) + 0.2f * impulse_ability), std::max(30.0f, fabsf(my_spaceship->current_impulse) * 10.0f * impulse_ability), true); - } - } - // If we don't have impulse available, stop the engine sound. - else if (impulse_sound > -1) - { - soundManager->stopSound(impulse_sound); - // TODO: Play an engine failure sound. - impulse_sound = -1; - } - + // Update impulse sound volume and pitch. + impulse_sound->update(delta); + } else { + // If we're not the player ship (ie. we exploded), don't play impulse + // engine sounds. + impulse_sound->stop(); } } @@ -257,7 +193,7 @@ void ScreenMainScreen::onHotkey(const HotkeyResult& key) else if (key.hotkey == "LONG_RANGE_RADAR") my_spaceship->commandMainScreenSetting(MSS_LongRange); else if (key.hotkey == "FIRST_PERSON") - first_person = !first_person; + viewport->first_person = !viewport->first_person; } } @@ -269,7 +205,7 @@ void ScreenMainScreen::onKey(sf::Event::KeyEvent key, int unicode) case sf::Keyboard::Escape: case sf::Keyboard::Home: soundManager->stopMusic(); - soundManager->stopSound(impulse_sound); + impulse_sound->stop(); destroy(); returnToShipSelection(); break; diff --git a/src/screens/mainScreen.h b/src/screens/mainScreen.h index 1ea5368b1c..3232688447 100644 --- a/src/screens/mainScreen.h +++ b/src/screens/mainScreen.h @@ -6,23 +6,24 @@ #include "gui/gui2_canvas.h" #include "threatLevelEstimate.h" -class GuiViewport3D; +class GuiViewportMainScreen; class GuiRadarView; class GuiCommsOverlay; class GuiHelpOverlay; +class ImpulseSound; class ScreenMainScreen : public GuiCanvas, public Updatable { P threat_estimate; private: - GuiViewport3D* viewport; + GuiViewportMainScreen* viewport; GuiHelpOverlay* keyboard_help; string keyboard_general = ""; GuiRadarView* tactical_radar; GuiRadarView* long_range_radar; bool first_person; GuiCommsOverlay* onscreen_comms; - int impulse_sound = -1; + std::unique_ptr impulse_sound; public: ScreenMainScreen(); diff --git a/src/shipTemplate.cpp b/src/shipTemplate.cpp index dee56876fd..529548bbbc 100644 --- a/src/shipTemplate.cpp +++ b/src/shipTemplate.cpp @@ -75,6 +75,13 @@ REGISTER_SCRIPT_CLASS(ShipTemplate) REGISTER_SCRIPT_CLASS_FUNCTION(ShipTemplate, setRadarTrace); REGISTER_SCRIPT_CLASS_FUNCTION(ShipTemplate, setLongRangeRadarRange); REGISTER_SCRIPT_CLASS_FUNCTION(ShipTemplate, setShortRangeRadarRange); + REGISTER_SCRIPT_CLASS_FUNCTION(ShipTemplate, setImpulseSoundFile); + REGISTER_SCRIPT_CLASS_FUNCTION(ShipTemplate, setCanScan); + REGISTER_SCRIPT_CLASS_FUNCTION(ShipTemplate, setCanHack); + REGISTER_SCRIPT_CLASS_FUNCTION(ShipTemplate, setCanDock); + REGISTER_SCRIPT_CLASS_FUNCTION(ShipTemplate, setCanCombatManeuver); + REGISTER_SCRIPT_CLASS_FUNCTION(ShipTemplate, setCanSelfDestruct); + REGISTER_SCRIPT_CLASS_FUNCTION(ShipTemplate, setCanLaunchProbe); /// Return a new template with the given name, which is an exact copy of this template. /// Used to make easy variations of templates. REGISTER_SCRIPT_CLASS_FUNCTION(ShipTemplate, copy); @@ -119,6 +126,7 @@ ShipTemplate::ShipTemplate() for(int n=0; n ShipTemplate::copy(string new_name) { P result = new ShipTemplate(); @@ -472,6 +485,14 @@ P ShipTemplate::copy(string new_name) result->can_be_docked_by_class = can_be_docked_by_class; result->energy_storage_amount = energy_storage_amount; result->repair_crew_count = repair_crew_count; + + result->can_scan = can_scan; + result->can_hack = can_hack; + result->can_dock = can_dock; + result->can_combat_maneuver = can_combat_maneuver; + result->can_self_destruct = can_self_destruct; + result->can_launch_probe = can_launch_probe; + result->default_ai_name = default_ai_name; for(int n=0; nbeams[n] = beams[n]; diff --git a/src/shipTemplate.h b/src/shipTemplate.h index b6bb688772..afb27b61ec 100644 --- a/src/shipTemplate.h +++ b/src/shipTemplate.h @@ -92,6 +92,12 @@ class ShipTemplate : public PObject bool shares_energy_with_docked; bool repair_docked; bool restocks_scan_probes; + bool can_scan = true; + bool can_hack = true; + bool can_dock = true; + bool can_combat_maneuver = true; + bool can_self_destruct = true; + bool can_launch_probe = true; float energy_storage_amount; int repair_crew_count; @@ -114,6 +120,7 @@ class ShipTemplate : public PObject string radar_trace; float long_range_radar_range = 30000.0f; float short_range_radar_range = 5000.0f; + string impulse_sound_file; std::vector rooms; std::vector doors; @@ -130,6 +137,12 @@ class ShipTemplate : public PObject void setSharesEnergyWithDocked(bool enabled); void setRepairDocked(bool enabled); void setRestocksScanProbes(bool enabled); + void setCanScan(bool enabled) { can_scan = enabled; } + void setCanHack(bool enabled) { can_hack = enabled; } + void setCanDock(bool enabled) { can_dock = enabled; } + void setCanCombatManeuver(bool enabled) { can_combat_maneuver = enabled; } + void setCanSelfDestruct(bool enabled) { can_self_destruct = enabled; } + void setCanLaunchProbe(bool enabled) { can_launch_probe = enabled; } void setMesh(string model, string color_texture, string specular_texture, string illumination_texture); void setEnergyStorage(float energy_amount); void setRepairCrewCount(int amount); @@ -168,6 +181,7 @@ class ShipTemplate : public PObject void setRadarTrace(string trace); void setLongRangeRadarRange(float range); void setShortRangeRadarRange(float range); + void setImpulseSoundFile(string sound); P copy(string new_name); diff --git a/src/spaceObjects/artifact.h b/src/spaceObjects/artifact.h index 4576cbb870..ea12b1ab96 100644 --- a/src/spaceObjects/artifact.h +++ b/src/spaceObjects/artifact.h @@ -16,7 +16,7 @@ class Artifact : public SpaceObject, public Updatable virtual void update(float delta) override; - virtual void draw3D(); + virtual void draw3D() override; virtual void drawOnRadar(sf::RenderTarget& window, sf::Vector2f position, float scale, float rotation, bool long_range) override; diff --git a/src/spaceObjects/asteroid.h b/src/spaceObjects/asteroid.h index 6e757c56e8..58f031e7be 100644 --- a/src/spaceObjects/asteroid.h +++ b/src/spaceObjects/asteroid.h @@ -13,7 +13,7 @@ class Asteroid : public SpaceObject Asteroid(); - virtual void draw3D(); + virtual void draw3D() override; virtual void drawOnRadar(sf::RenderTarget& window, sf::Vector2f position, float scale, float rotation, bool long_range) override; @@ -34,7 +34,7 @@ class VisualAsteroid : public SpaceObject VisualAsteroid(); - virtual void draw3D(); + virtual void draw3D() override; void setSize(float size); diff --git a/src/spaceObjects/blackHole.cpp b/src/spaceObjects/blackHole.cpp index ad4e332e76..ef8e10d25f 100644 --- a/src/spaceObjects/blackHole.cpp +++ b/src/spaceObjects/blackHole.cpp @@ -68,13 +68,19 @@ void BlackHole::collide(Collisionable* target, float collision_force) sf::Vector2f diff = getPosition() - target->getPosition(); float distance = sf::length(diff); float force = (getRadius() * getRadius() * 50.0f) / (distance * distance); + DamageInfo info(NULL, DT_Kinetic, getPosition()); if (force > 10000.0) { force = 10000.0; if (isServer()) - target->destroy(); + { + P obj = P(target); + if (obj) + obj->takeDamage(100000.0, info); //try to destroy the object by inflicting a huge amount of damage + if (target) + target->destroy(); + } } - DamageInfo info(NULL, DT_Kinetic, getPosition()); if (force > 100.0 && isServer()) { P obj = P(target); diff --git a/src/spaceObjects/mine.h b/src/spaceObjects/mine.h index 0a9242c6c2..c0bfa712b7 100644 --- a/src/spaceObjects/mine.h +++ b/src/spaceObjects/mine.h @@ -22,18 +22,18 @@ class Mine : public SpaceObject, public Updatable Mine(); - virtual void draw3D(); - virtual void draw3DTransparent(); - virtual void drawOnRadar(sf::RenderTarget& window, sf::Vector2f position, float scale, float rotation, bool long_range); - virtual void drawOnGMRadar(sf::RenderTarget& window, sf::Vector2f position, float scale, float rotation, bool long_range); - virtual void update(float delta); + virtual void draw3D() override; + virtual void draw3DTransparent() override; + virtual void drawOnRadar(sf::RenderTarget& window, sf::Vector2f position, float scale, float rotation, bool long_range) override; + virtual void drawOnGMRadar(sf::RenderTarget& window, sf::Vector2f position, float scale, float rotation, bool long_range) override; + virtual void update(float delta) override; - virtual void collide(Collisionable* target, float force); + virtual void collide(Collisionable* target, float force) override; void eject(); void explode(); void onDestruction(ScriptSimpleCallback callback); - virtual string getExportLine() { return "Mine():setPosition(" + string(getPosition().x, 0) + ", " + string(getPosition().y, 0) + ")"; } + virtual string getExportLine() override { return "Mine():setPosition(" + string(getPosition().x, 0) + ", " + string(getPosition().y, 0) + ")"; } private: const MissileWeaponData& data; diff --git a/src/spaceObjects/playerSpaceship.cpp b/src/spaceObjects/playerSpaceship.cpp index 83bf99561d..b5683158c5 100644 --- a/src/spaceObjects/playerSpaceship.cpp +++ b/src/spaceObjects/playerSpaceship.cpp @@ -98,7 +98,7 @@ REGISTER_SCRIPT_SUBCLASS(PlayerSpaceship, SpaceShip) REGISTER_SCRIPT_CLASS_FUNCTION(PlayerSpaceship, commandSendComm); REGISTER_SCRIPT_CLASS_FUNCTION(PlayerSpaceship, commandSendCommPlayer); // Command repair crews to automatically move to damaged subsystems. - // Use this command on ships to require less player interaction, especially + // is command on ships to require less player interaction, especially // when combined with setAutoCoolant/auto_coolant_enabled. REGISTER_SCRIPT_CLASS_FUNCTION(PlayerSpaceship, commandSetAutoRepair); REGISTER_SCRIPT_CLASS_FUNCTION(PlayerSpaceship, commandSetBeamFrequency); @@ -135,6 +135,72 @@ REGISTER_SCRIPT_SUBCLASS(PlayerSpaceship, SpaceShip) REGISTER_SCRIPT_CLASS_FUNCTION(PlayerSpaceship, getShortRangeRadarRange); REGISTER_SCRIPT_CLASS_FUNCTION(PlayerSpaceship, setLongRangeRadarRange); REGISTER_SCRIPT_CLASS_FUNCTION(PlayerSpaceship, setShortRangeRadarRange); + /// Set whether the object can scan other objects. + /// Requires a Boolean value. + /// Example: ship:setCanScan(true) + REGISTER_SCRIPT_CLASS_FUNCTION(PlayerSpaceship, setCanScan); + /// Get whether the object can scan other objects. + /// Returns a Boolean value. + /// Example: ship:getCanScan() + REGISTER_SCRIPT_CLASS_FUNCTION(PlayerSpaceship, getCanScan); + /// Set whether the object can hack other objects. + /// Requires a Boolean value. + /// Example: ship:setCanHack(true) + REGISTER_SCRIPT_CLASS_FUNCTION(PlayerSpaceship, setCanHack); + /// Get whether the object can hack other objects. + /// Returns a Boolean value. + /// Example: ship:getCanHack() + REGISTER_SCRIPT_CLASS_FUNCTION(PlayerSpaceship, getCanHack); + /// Set whether the object can dock with other objects. + /// Requires a Boolean value. + /// Example: ship:setCanDock(true) + REGISTER_SCRIPT_CLASS_FUNCTION(PlayerSpaceship, setCanDock); + /// Get whether the object can dock with other objects. + /// Returns a Boolean value. + /// Example: ship:getCanDock() + REGISTER_SCRIPT_CLASS_FUNCTION(PlayerSpaceship, getCanDock); + /// Set whether the object can perform combat maneuvers. + /// Requires a Boolean value. + /// Example: ship:setCanCombatManeuver(true) + REGISTER_SCRIPT_CLASS_FUNCTION(PlayerSpaceship, setCanCombatManeuver); + /// Get whether the object can perform combat maneuvers. + /// Returns a Boolean value. + /// Example: ship:getCanCombatManeuver() + REGISTER_SCRIPT_CLASS_FUNCTION(PlayerSpaceship, getCanCombatManeuver); + /// Set whether the object can self destruct. + /// Requires a Boolean value. + /// Example: ship:setCanSelfDestruct(true) + REGISTER_SCRIPT_CLASS_FUNCTION(PlayerSpaceship, setCanSelfDestruct); + /// Get whether the object can self destruct. + /// This returns false if self destruct size and damage are both 0, even if + /// you set setCanSelfDestruct(true). + /// Returns a Boolean value. + /// Example: ship:getCanSelfDestruct() + REGISTER_SCRIPT_CLASS_FUNCTION(PlayerSpaceship, getCanSelfDestruct); + /// Set whether the object can launch probes. + /// Requires a Boolean value. + /// Example: ship:setCanLaunchProbe(true) + REGISTER_SCRIPT_CLASS_FUNCTION(PlayerSpaceship, setCanLaunchProbe); + /// Get whether the object can launch probes. + /// Returns a Boolean value. + /// Example: ship:getCanLaunchProbe() + REGISTER_SCRIPT_CLASS_FUNCTION(PlayerSpaceship, getCanLaunchProbe); + /// Set the amount of damage done by self destruction. + /// Requires a float; the value used is randomized +/- 33%. + /// Example: ship:setSelfDestructDamage(150) + REGISTER_SCRIPT_CLASS_FUNCTION(PlayerSpaceship, setSelfDestructDamage); + /// Get the amount of damage done by self destruction. + /// Returns a float. + /// Example: ship:getSelfDestructDamage() + REGISTER_SCRIPT_CLASS_FUNCTION(PlayerSpaceship, getSelfDestructDamage); + /// Set the size of the explosion created by self destruction. + /// Requires a float. + /// Example: ship:setSelfDestructSize(1500) + REGISTER_SCRIPT_CLASS_FUNCTION(PlayerSpaceship, setSelfDestructSize); + /// Get the size of the explosion created by self destruction. + /// Returns a float. + /// Example: ship:getSelfDestructSize() + REGISTER_SCRIPT_CLASS_FUNCTION(PlayerSpaceship, getSelfDestructSize); } float PlayerSpaceship::system_power_user_factor[] = { @@ -237,14 +303,7 @@ PlayerSpaceship::PlayerSpaceship() auto_repair_enabled = false; auto_coolant_enabled = false; max_coolant = max_coolant_per_system; - activate_self_destruct = false; - self_destruct_countdown = 0.0; - scanning_delay = 0.0; - scanning_complexity = 0; - scanning_depth = 0; - max_scan_probes = 8; scan_probe_stock = max_scan_probes; - scan_probe_recharge = 0.0; alert_level = AL_Normal; shields_active = false; control_code = ""; @@ -256,6 +315,12 @@ PlayerSpaceship::PlayerSpaceship() setScannedStateForFaction(faction_id, SS_FullScan); updateMemberReplicationUpdateDelay(&target_rotation, 0.1); + registerMemberReplication(&can_scan); + registerMemberReplication(&can_hack); + registerMemberReplication(&can_dock); + registerMemberReplication(&can_combat_maneuver); + registerMemberReplication(&can_self_destruct); + registerMemberReplication(&can_launch_probe); registerMemberReplication(&hull_damage_indicator, 0.5); registerMemberReplication(&jump_indicator, 0.5); registerMemberReplication(&energy_level, 0.1); @@ -324,13 +389,13 @@ PlayerSpaceship::PlayerSpaceship() { destroy(); } + + // Initialize the ship's log. + addToShipLog("Start of log", colorConfig.log_generic); } // Initialize player ship callsigns with a "PL" designation. setCallSign("PL" + string(getMultiplayerId())); - - // Initialize the ship's log. - addToShipLog("Start of log", colorConfig.log_generic); } PlayerSpaceship::~PlayerSpaceship() @@ -576,20 +641,20 @@ void PlayerSpaceship::update(float delta) // If the countdown has started, tick the clock. self_destruct_countdown -= delta; - // When time runs out, blow up the ship and damage a 1.5U - // radius. + // When time runs out, blow up the ship and damage a + // configurable radius. if (self_destruct_countdown <= 0.0) { for(int n = 0; n < 5; n++) { ExplosionEffect* e = new ExplosionEffect(); - e->setSize(1000.0f); - e->setPosition(getPosition() + sf::rotateVector(sf::Vector2f(0, random(0, 500)), random(0, 360))); + e->setSize(self_destruct_size * 0.67f); + e->setPosition(getPosition() + sf::rotateVector(sf::Vector2f(0, random(0, self_destruct_size * 0.33f)), random(0, 360))); e->setRadarSignatureInfo(0.0, 0.6, 0.6); } DamageInfo info(this, DT_Kinetic, getPosition()); - SpaceObject::damageArea(getPosition(), 1500, 100, 200, info, 0.0); + SpaceObject::damageArea(getPosition(), self_destruct_size, self_destruct_damage - (self_destruct_damage / 3.0f), self_destruct_damage + (self_destruct_damage / 3.0f), info, 0.0); destroy(); return; @@ -653,8 +718,17 @@ void PlayerSpaceship::applyTemplateValues() // template. setRepairCrewCount(ship_template->repair_crew_count); + // Set the ship's radar ranges. long_range_radar_range = ship_template->long_range_radar_range; short_range_radar_range = ship_template->short_range_radar_range; + + // Set the ship's capabilities. + can_scan = ship_template->can_scan; + can_hack = ship_template->can_hack; + can_dock = ship_template->can_dock; + can_combat_maneuver = ship_template->can_combat_maneuver; + can_self_destruct = ship_template->can_self_destruct; + can_launch_probe = ship_template->can_launch_probe; } void PlayerSpaceship::executeJump(float distance) @@ -865,7 +939,7 @@ void PlayerSpaceship::addToShipLog(string message, sf::Color color) ships_log.erase(ships_log.begin()); // Timestamp a log entry, color it, and add it to the end of the log. - ships_log.emplace_back(string(engine->getElapsedTime(), 1) + string(": "), message, color); + ships_log.emplace_back(string(gameGlobalInfo->elapsed_time, 1) + string(": "), message, color); } void PlayerSpaceship::addToShipLogBy(string message, P target) @@ -1900,7 +1974,7 @@ void PlayerSpaceship::onReceiveServerCommand(sf::Packet& packet) ECrewPosition position; string sound_name; packet >> position >> sound_name; - if ((position == max_crew_positions && my_player_info->isMainScreen()) || my_player_info->crew_position[position]) + if ((position == max_crew_positions && my_player_info->main_screen) || my_player_info->crew_position[position]) { soundManager->playSound(sound_name); } @@ -1963,6 +2037,18 @@ string PlayerSpaceship::getExportLine() result += ":setShortRangeRadarRange(" + string(short_range_radar_range, 0) + ")"; if (long_range_radar_range != ship_template->long_range_radar_range) result += ":setLongRangeRadarRange(" + string(long_range_radar_range, 0) + ")"; + if (can_scan != ship_template->can_scan) + result += ":setCanScan(" + string(can_scan, true) + ")"; + if (can_hack != ship_template->can_hack) + result += ":setCanHack(" + string(can_hack, true) + ")"; + if (can_dock != ship_template->can_dock) + result += ":setCanDock(" + string(can_dock, true) + ")"; + if (can_combat_maneuver != ship_template->can_combat_maneuver) + result += ":setCanCombatManeuver(" + string(can_combat_maneuver, true) + ")"; + if (can_self_destruct != ship_template->can_self_destruct) + result += ":setCanSelfDestruct(" + string(can_self_destruct, true) + ")"; + if (can_launch_probe != ship_template->can_launch_probe) + result += ":setCanLaunchProbe(" + string(can_launch_probe, true) + ")"; return result; } diff --git a/src/spaceObjects/playerSpaceship.h b/src/spaceObjects/playerSpaceship.h index 059bab5e3e..9dde09e8f1 100644 --- a/src/spaceObjects/playerSpaceship.h +++ b/src/spaceObjects/playerSpaceship.h @@ -91,15 +91,6 @@ class PlayerSpaceship : public SpaceShip // Visual indicators of hull damage and in-progress jumps float hull_damage_indicator; float jump_indicator; - // Target of a scan. Server-only value - P scanning_target; - // Time in seconds to scan an object if scanning_complexity is 0 (none) - float scanning_delay; - // Number of sliders during a scan - int scanning_complexity; - // Number of times an object must be scanned to achieve a fully scanned - // state - int scanning_depth; // Time in seconds it takes to recalibrate shields float shield_calibration_delay; // Ship automation features, mostly for single-person ships like fighters @@ -111,8 +102,6 @@ class PlayerSpaceship : public SpaceShip string control_code; private: - // soundManager index of the shield object - int shield_sound; // Comms variables ECommsState comms_state; float comms_open_delay; @@ -131,12 +120,43 @@ class PlayerSpaceship : public SpaceShip std::vector custom_functions; std::vector waypoints; - - // Scan probe capacity - int max_scan_probes; - int scan_probe_stock; - float scan_probe_recharge; + // Ship functionality + // Capable of scanning a target + bool can_scan = true; + // Target of a scan. Server-only value + P scanning_target; + // Time in seconds to scan an object if scanning_complexity is 0 (none) + float scanning_delay = 0.0; + // Number of sliders during a scan + int scanning_complexity = 0; + // Number of times an object must be scanned to achieve a fully scanned + // state + int scanning_depth = 0; + + // Capable of hacking a target + bool can_hack = true; + // Capable of docking with a target + bool can_dock = true; + // Capable of combat maneuvers + bool can_combat_maneuver = true; + + // Capable of self-destruction + bool can_self_destruct = true; + bool activate_self_destruct = false; + uint32_t self_destruct_code[max_self_destruct_codes]; + bool self_destruct_code_confirmed[max_self_destruct_codes]; + ECrewPosition self_destruct_code_entry_position[max_self_destruct_codes]; + ECrewPosition self_destruct_code_show_position[max_self_destruct_codes]; + float self_destruct_countdown = 0.0; + float self_destruct_damage = 150.0; + float self_destruct_size = 1500.0; + + // Capable of probe launches + bool can_launch_probe = true; + int max_scan_probes = 8; + int scan_probe_stock; + float scan_probe_recharge = 0.0; ScriptSimpleCallback on_probe_launch; // Main screen content @@ -144,13 +164,6 @@ class PlayerSpaceship : public SpaceShip // Content overlaid on the main screen, such as comms EMainScreenOverlay main_screen_overlay; - bool activate_self_destruct; - uint32_t self_destruct_code[max_self_destruct_codes]; - bool self_destruct_code_confirmed[max_self_destruct_codes]; - ECrewPosition self_destruct_code_entry_position[max_self_destruct_codes]; - ECrewPosition self_destruct_code_show_position[max_self_destruct_codes]; - float self_destruct_countdown; - EAlertLevel alert_level; int32_t linked_science_probe_id; @@ -188,7 +201,25 @@ class PlayerSpaceship : public SpaceShip void setEnergyLevelMax(float amount) { max_energy_level = std::max(0.0f, amount); energy_level = std::min(energy_level, max_energy_level); } float getEnergyLevel() { return energy_level; } float getEnergyLevelMax() { return max_energy_level; } - + + void setCanScan(bool enabled) { can_scan = enabled; } + bool getCanScan() { return can_scan; } + void setCanHack(bool enabled) { can_hack = enabled; } + bool getCanHack() { return can_hack; } + void setCanDock(bool enabled) { can_dock = enabled; } + bool getCanDock() { return can_dock; } + void setCanCombatManeuver(bool enabled) { can_combat_maneuver = enabled; } + bool getCanCombatManeuver() { return can_combat_maneuver; } + void setCanSelfDestruct(bool enabled) { can_self_destruct = enabled; } + bool getCanSelfDestruct() { return can_self_destruct && self_destruct_size > 0 && self_destruct_damage > 0; } + void setCanLaunchProbe(bool enabled) { can_launch_probe = enabled; } + bool getCanLaunchProbe() { return can_launch_probe; } + + void setSelfDestructDamage(float amount) { self_destruct_damage = std::max(0.0f, amount); } + float getSelfDestructDamage() { return self_destruct_damage; } + void setSelfDestructSize(float size) { self_destruct_size = std::max(0.0f, size); } + float getSelfDestructSize() { return self_destruct_size; } + void setScanProbeCount(int amount) { scan_probe_stock = std::max(0, std::min(amount, max_scan_probes)); } int getScanProbeCount() { return scan_probe_stock; } void setMaxScanProbeCount(int amount) { max_scan_probes = std::max(0, amount); scan_probe_stock = std::min(scan_probe_stock, max_scan_probes); } diff --git a/src/spaceObjects/shipTemplateBasedObject.cpp b/src/spaceObjects/shipTemplateBasedObject.cpp index eb08681e38..38b0045807 100644 --- a/src/spaceObjects/shipTemplateBasedObject.cpp +++ b/src/spaceObjects/shipTemplateBasedObject.cpp @@ -18,13 +18,26 @@ REGISTER_SCRIPT_SUBCLASS_NO_CREATE(ShipTemplateBasedObject, SpaceObject) REGISTER_SCRIPT_CLASS_FUNCTION(ShipTemplateBasedObject, setHull); /// Set the maximum amount of hull for this station. Stations never repair hull damage, so this only effects the percentage displays REGISTER_SCRIPT_CLASS_FUNCTION(ShipTemplateBasedObject, setHullMax); - /// Set if the object can be destroyed or not. true or false + /// Set whether the object can be destroyed. + /// Requires a Boolean value. + /// Example: ship:setCanBeDestroyed(true) REGISTER_SCRIPT_CLASS_FUNCTION(ShipTemplateBasedObject, setCanBeDestroyed); - /// Get if the object can be destroyed or not. true or false + /// Get whether the object can be destroyed. + /// Returns a Boolean value. + /// Example: ship:getCanBeDestroyed() REGISTER_SCRIPT_CLASS_FUNCTION(ShipTemplateBasedObject, getCanBeDestroyed); - /// Get the current shield level, stations only have a single shield, unlike ships that have a front&back shield + /// Get the specified shield's current level. + /// Requires an integer index value. + /// Returns a float value. + /// Example to get shield level on front shields of a ship with two shields: + /// ship:getShieldLevel(0) + /// Rear shields: ship:getShieldLevel(1) REGISTER_SCRIPT_CLASS_FUNCTION(ShipTemplateBasedObject, getShieldLevel); - /// Get the amount of shields fit on this object. + /// Get the number of shields on this object. + /// For example, a ship with 1 shield count has a single shield covering + /// all angles, a ship with 2 covers front and back, etc. + /// Returns an integer count. + /// Example: ship:getShieldCount() REGISTER_SCRIPT_CLASS_FUNCTION(ShipTemplateBasedObject, getShieldCount); /// Get the maxium shield level. REGISTER_SCRIPT_CLASS_FUNCTION(ShipTemplateBasedObject, getShieldMax); @@ -33,9 +46,13 @@ REGISTER_SCRIPT_SUBCLASS_NO_CREATE(ShipTemplateBasedObject, SpaceObject) /// Set the maximum shield level. Note that this does low the current shield level when the max becomes lower, but it does not increase the shield level. /// A seperate call to setShield is needed for that. REGISTER_SCRIPT_CLASS_FUNCTION(ShipTemplateBasedObject, setShieldsMax); - /// Set the icon to be used for this station on the radar. + /// Set the icon to be used for this object on the radar. /// For example, station:setRadarTrace("RadarArrow.png") will show an arrow instead of a dot for this station. REGISTER_SCRIPT_CLASS_FUNCTION(ShipTemplateBasedObject, setRadarTrace); + /// Set the sound file to be used for this object's impulse engines. + /// Requires a string for a filename relative to the resources path. + /// Example: setImpulseSoundFile("engine.wav") + REGISTER_SCRIPT_CLASS_FUNCTION(ShipTemplateBasedObject, setImpulseSoundFile); /// Are the shields online or not. Currently always returns true except for player ships, as only players can turn off shields. REGISTER_SCRIPT_CLASS_FUNCTION(ShipTemplateBasedObject, getShieldsActive); @@ -94,6 +111,7 @@ ShipTemplateBasedObject::ShipTemplateBasedObject(float collision_range, string m registerMemberReplication(&shield_hit_effect[n], 0.5); } registerMemberReplication(&radar_trace); + registerMemberReplication(&impulse_sound_file); registerMemberReplication(&hull_strength, 0.5); registerMemberReplication(&hull_max); @@ -329,6 +347,7 @@ void ShipTemplateBasedObject::setTemplate(string template_name) shield_level[n] = shield_max[n] = ship_template->shield_level[n]; radar_trace = ship_template->radar_trace; + impulse_sound_file = ship_template->impulse_sound_file; shares_energy_with_docked = ship_template->shares_energy_with_docked; repair_docked = ship_template->repair_docked; diff --git a/src/spaceObjects/shipTemplateBasedObject.h b/src/spaceObjects/shipTemplateBasedObject.h index 550afcacfd..e0cee029e3 100644 --- a/src/spaceObjects/shipTemplateBasedObject.h +++ b/src/spaceObjects/shipTemplateBasedObject.h @@ -18,7 +18,7 @@ class ShipTemplateBasedObject : public SpaceObject, public Updatable string template_name; string type_name; string radar_trace; - string impulse_sound_file = "engine.wav"; + string impulse_sound_file; P ship_template; int shield_count; @@ -90,6 +90,7 @@ class ShipTemplateBasedObject : public SpaceObject, public Updatable void setRearShieldMax(float amount) { if (amount < 0) return; shield_max[1] = amount; shield_level[1] = std::min(shield_level[1], shield_max[1]); } void setRadarTrace(string trace) { radar_trace = trace; } + void setImpulseSoundFile(string sound) { impulse_sound_file = sound; } bool getSharesEnergyWithDocked() { return shares_energy_with_docked; } void setSharesEnergyWithDocked(bool enabled) { shares_energy_with_docked = enabled; } diff --git a/src/spaceObjects/spaceObject.cpp b/src/spaceObjects/spaceObject.cpp index 1ff56e8e2e..9c506ea24e 100644 --- a/src/spaceObjects/spaceObject.cpp +++ b/src/spaceObjects/spaceObject.cpp @@ -252,6 +252,8 @@ REGISTER_SCRIPT_CLASS_NO_CREATE(SpaceObject) /// Returns a boolean value. /// Example: obj:isScannedByFaction("Human Navy") REGISTER_SCRIPT_CLASS_FUNCTION(SpaceObject, isScannedByFaction); + // Register a callback that is called when this object is destroyed, by any means. + REGISTER_SCRIPT_CLASS_FUNCTION(SpaceObject, onDestroyed); } PVector space_object_list; @@ -285,12 +287,12 @@ SpaceObject::~SpaceObject() { } -#if FEATURE_3D_RENDERING void SpaceObject::draw3D() { +#if FEATURE_3D_RENDERING model_info.render(getPosition(), getRotation()); -} #endif//FEATURE_3D_RENDERING +} void SpaceObject::drawOnRadar(sf::RenderTarget& window, sf::Vector2f position, float scale, float rotation, bool longRange) { @@ -302,7 +304,7 @@ void SpaceObject::drawOnGMRadar(sf::RenderTarget& window, sf::Vector2f position, void SpaceObject::destroy() { - onDestroyed(); + on_destroyed.call(P(this)); MultiplayerObject::destroy(); } diff --git a/src/spaceObjects/spaceObject.h b/src/spaceObjects/spaceObject.h index e9a8d8da21..c6e576a634 100644 --- a/src/spaceObjects/spaceObject.h +++ b/src/spaceObjects/spaceObject.h @@ -162,10 +162,13 @@ class SpaceObject : public Collisionable, public MultiplayerObject float getHeading() { float ret = getRotation() - 270; while(ret < 0) ret += 360.0f; while(ret > 360.0f) ret -= 360.0f; return ret; } void setHeading(float heading) { setRotation(heading - 90); } -#if FEATURE_3D_RENDERING + void onDestroyed(ScriptSimpleCallback callback) + { + on_destroyed = callback; + } + virtual void draw3D(); virtual void draw3DTransparent() {} -#endif//FEATURE_3D_RENDERING virtual void drawOnRadar(sf::RenderTarget& window, sf::Vector2f position, float scale, float rotation, bool longRange); virtual void drawOnGMRadar(sf::RenderTarget& window, sf::Vector2f position, float scale, float rotation, bool longRange); virtual void destroy(); @@ -220,7 +223,7 @@ class SpaceObject : public Collisionable, public MultiplayerObject bool openCommsTo(P target); bool sendCommsMessage(P target, string message); - ScriptCallback onDestroyed; + ScriptSimpleCallback on_destroyed; protected: ModelInfo model_info; diff --git a/src/spaceObjects/spaceship.cpp b/src/spaceObjects/spaceship.cpp index a4ccc11b56..8ed0460aa1 100644 --- a/src/spaceObjects/spaceship.cpp +++ b/src/spaceObjects/spaceship.cpp @@ -58,6 +58,7 @@ REGISTER_SCRIPT_SUBCLASS_NO_CREATE(SpaceShip, ShipTemplateBasedObject) /// Requires a numeric value. /// Example: ship:setWarpSpeed(500); REGISTER_SCRIPT_CLASS_FUNCTION(SpaceShip, setWarpSpeed); + REGISTER_SCRIPT_CLASS_FUNCTION(SpaceShip, getWarpSpeed); REGISTER_SCRIPT_CLASS_FUNCTION(SpaceShip, getBeamWeaponArc); REGISTER_SCRIPT_CLASS_FUNCTION(SpaceShip, getBeamWeaponDirection); REGISTER_SCRIPT_CLASS_FUNCTION(SpaceShip, getBeamWeaponRange); diff --git a/src/spaceObjects/spaceship.h b/src/spaceObjects/spaceship.h index c1e4707014..bce393544a 100644 --- a/src/spaceObjects/spaceship.h +++ b/src/spaceObjects/spaceship.h @@ -341,6 +341,13 @@ class SpaceShip : public ShipTemplateBasedObject } } void setWarpSpeed(float speed) { warp_speed_per_warp_level = std::max(0.0f, speed); } + float getWarpSpeed() { + if (has_warp_drive) { + return warp_speed_per_warp_level; + } else { + return 0.0f; + } + } float getBeamWeaponArc(int index) { if (index < 0 || index >= max_beam_weapons) return 0.0; return beam_weapons[index].getArc(); } float getBeamWeaponDirection(int index) { if (index < 0 || index >= max_beam_weapons) return 0.0; return beam_weapons[index].getDirection(); }