Added proc to imitate movement of stars. Changes icon state and throws all unanchored items in space.

Added var denoting which direction is fore of the ship.
Adjusting speed now applies movement effect on ship's zlevel.

Added working engines system. Only defined type currently is thermal engine.
Acceleration is now based on total thrust and ship's mass.
Added engine control console.

Changed shuttle control console to use custom interface to pick destinations.
Shuttles can now go between any types of sectors, not just ship->sector.
Shuttles cannot return to base if they are too far on overmap.

Moved helm computer to NanoUI.
Helm computer now stores navigation data records instead of polling info from actual overmap objects every time.
Metaobjects now can define if sector is well known, in which case it will be automatically added to helm computer records on creation.
Can add and delete records.
This commit is contained in:
Chinsky
2014-07-03 04:47:50 +04:00
parent 59108f750d
commit 5c7080a774
20 changed files with 1254 additions and 400 deletions

View File

@@ -0,0 +1,99 @@
//Engine control and monitoring console
/obj/machinery/computer/engines
name = "engines control console"
icon_state = "id"
var/state = "status"
var/list/engines = list()
var/obj/effect/map/ship/linked
/obj/machinery/computer/engines/initialize()
linked = map_sectors["[z]"]
if (linked)
if (!linked.eng_control)
linked.eng_control = src
testing("Engines console at level [z] found a corresponding overmap object '[linked.name]'.")
else
testing("Engines console at level [z] was unable to find a corresponding overmap object.")
for(var/datum/ship_engine/E in engines)
if (E.zlevel == z && !(E in engines))
engines += E
/obj/machinery/computer/engines/attack_hand(var/mob/user as mob)
if(..())
user.unset_machine()
return
if(!isAI(user))
user.set_machine(src)
ui_interact(user)
/obj/machinery/computer/engines/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null)
if(!linked)
return
var/data[0]
data["state"] = state
var/list/enginfo[0]
for(var/datum/ship_engine/E in engines)
var/list/rdata[0]
rdata["eng_type"] = E.name
rdata["eng_on"] = E.is_on()
rdata["eng_thrust"] = E.get_thrust()
rdata["eng_thrust_limiter"] = round(E.get_thrust_limit()*100)
rdata["eng_status"] = E.get_status()
rdata["eng_reference"] = "\ref[E]"
enginfo.Add(list(rdata))
data["engines_info"] = enginfo
ui = nanomanager.try_update_ui(user, src, ui_key, ui, data)
if (!ui)
ui = new(user, src, ui_key, "engines_control.tmpl", "[linked.name] Engines Control", 380, 530)
ui.set_initial_data(data)
ui.open()
ui.set_auto_update(1)
/obj/machinery/computer/engines/Topic(href, href_list)
if(..())
return
if(href_list["state"])
state = href_list["state"]
if(href_list["engine"])
if(href_list["set_limit"])
var/datum/ship_engine/E = locate(href_list["engine"])
var/newlim = input("Input new thrust limit (0..100)", "Thrust limit", E.get_thrust_limit()) as num
var/limit = Clamp(newlim/100, 0, 1)
if(E)
E.set_thrust_limit(limit)
if(href_list["limit"])
var/datum/ship_engine/E = locate(href_list["engine"])
var/limit = Clamp(E.get_thrust_limit() + text2num(href_list["limit"]), 0, 1)
if(E)
E.set_thrust_limit(limit)
if(href_list["toggle"])
var/datum/ship_engine/E = locate(href_list["engine"])
if(E)
E.toggle()
add_fingerprint(usr)
updateUsrDialog()
/obj/machinery/computer/engines/proc/burn()
if(engines.len == 0)
return 0
var/res = 0
for(var/datum/ship_engine/E in engines)
res |= E.burn()
return res
/obj/machinery/computer/engines/proc/get_total_thrust()
for(var/datum/ship_engine/E in engines)
. += E.get_thrust()

View File

@@ -0,0 +1,174 @@
/obj/machinery/computer/helm
name = "helm control console"
icon_state = "id"
var/state = "status"
var/obj/effect/map/ship/linked //connected overmap object
var/autopilot = 0
var/manual_control = 0
var/list/known_sectors = list()
var/dx //desitnation
var/dy //coordinates
/obj/machinery/computer/helm/initialize()
linked = map_sectors["[z]"]
if (linked)
if(!linked.nav_control)
linked.nav_control = src
testing("Helm console at level [z] found a corresponding overmap object '[linked.name]'.")
else
testing("Helm console at level [z] was unable to find a corresponding overmap object.")
for(var/level in map_sectors)
var/obj/effect/map/sector/S = map_sectors["[level]"]
if (istype(S) && S.always_known)
var/datum/data/record/R = new()
R.fields["name"] = S.name
R.fields["x"] = S.x
R.fields["y"] = S.y
known_sectors += R
/obj/machinery/computer/helm/process()
..()
if (autopilot && dx && dy)
var/turf/T = locate(dx,dy,1)
if(linked.loc == T)
if(linked.is_still())
autopilot = 0
else
linked.decelerate()
var/brake_path = linked.get_brake_path()
if(get_dist(linked.loc, T) > brake_path)
linked.accelerate(get_dir(linked.loc, T))
else
linked.decelerate()
return
/obj/machinery/computer/helm/relaymove(var/mob/user, direction)
if(manual_control && linked)
linked.relaymove(user,direction)
return 1
/obj/machinery/computer/helm/check_eye(var/mob/user as mob)
if (!manual_control)
return null
if (!get_dist(user, src) > 1 || user.blinded || !linked )
return null
user.reset_view(linked)
return 1
/obj/machinery/computer/helm/attack_hand(var/mob/user as mob)
if(..())
user.unset_machine()
manual_control = 0
return
if(!isAI(user))
user.set_machine(src)
ui_interact(user)
/obj/machinery/computer/helm/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null)
if(!linked)
return
var/data[0]
data["state"] = state
data["sector"] = linked.current_sector ? linked.current_sector.name : "Deep Space"
data["sector_info"] = linked.current_sector ? linked.current_sector.desc : "Not Available"
data["s_x"] = linked.x
data["s_y"] = linked.y
data["dest"] = dy && dx
data["d_x"] = dx
data["d_y"] = dy
data["speed"] = linked.get_speed()
data["accel"] = round(linked.get_acceleration())
data["heading"] = linked.get_heading() ? dir2angle(linked.get_heading()) : 0
data["autopilot"] = autopilot
data["manual_control"] = manual_control
var/list/locations[0]
for (var/datum/data/record/R in known_sectors)
var/list/rdata[0]
rdata["name"] = R.fields["name"]
rdata["x"] = R.fields["x"]
rdata["y"] = R.fields["y"]
rdata["reference"] = "\ref[R]"
locations.Add(list(rdata))
data["locations"] = locations
ui = nanomanager.try_update_ui(user, src, ui_key, ui, data)
if (!ui)
ui = new(user, src, ui_key, "helm.tmpl", "[linked.name] Helm Control", 380, 530)
ui.set_initial_data(data)
ui.open()
ui.set_auto_update(1)
/obj/machinery/computer/helm/Topic(href, href_list)
if(..())
return
if (!linked)
return
if (href_list["add"])
var/datum/data/record/R = new()
var/sec_name = input("Input naviation entry name", "New navigation entry", "Sector #[known_sectors.len]") as text
if(!sec_name)
sec_name = "Sector #[known_sectors.len]"
R.fields["name"] = sec_name
switch(href_list["add"])
if("current")
R.fields["x"] = linked.x
R.fields["y"] = linked.y
if("new")
var/newx = input("Input new entry x coordinate", "Coordinate input", linked.x) as num
R.fields["x"] = Clamp(newx, 1, world.maxx)
var/newy = input("Input new entry y coordinate", "Coordinate input", linked.y) as num
R.fields["y"] = Clamp(newy, 1, world.maxy)
known_sectors += R
if (href_list["remove"])
var/datum/data/record/R = locate(href_list["remove"])
known_sectors.Remove(R)
if (href_list["setx"])
var/newx = input("Input new destiniation x coordinate", "Coordinate input", dx) as num|null
if (newx)
dx = Clamp(newx, 1, world.maxx)
if (href_list["sety"])
var/newy = input("Input new destiniation y coordinate", "Coordinate input", dy) as num|null
if (newy)
dy = Clamp(newy, 1, world.maxy)
if (href_list["x"] && href_list["y"])
dx = text2num(href_list["x"])
dy = text2num(href_list["y"])
if (href_list["reset"])
dx = 0
dy = 0
if (href_list["move"])
var/ndir = text2num(href_list["move"])
linked.relaymove(usr, ndir)
if (href_list["brake"])
linked.decelerate()
if (href_list["apilot"])
autopilot = !autopilot
if (href_list["manual"])
manual_control = !manual_control
if (href_list["state"])
state = href_list["state"]
add_fingerprint(usr)
updateUsrDialog()

View File

@@ -0,0 +1,139 @@
//Shuttle controller computer for shuttles going between sectors
/datum/shuttle/ferry/var/range = 0 //how many overmap tiles can shuttle go, for picking destinatiosn and returning.
/obj/machinery/computer/shuttle_control/explore
name = "exploration shuttle console"
shuttle_tag = "Exploration"
req_access = list()
var/landing_type //area for shuttle ship-side
var/obj/effect/map/destination //current destination
var/obj/effect/map/home //current destination
/obj/machinery/computer/shuttle_control/explore/initialize()
..()
home = map_sectors["[z]"]
shuttle_tag = "[shuttle_tag]-[z]"
if(!shuttle_controller.shuttles[shuttle_tag])
var/datum/shuttle/ferry/shuttle = new()
shuttle.warmup_time = 10
shuttle.area_station = locate(landing_type)
shuttle.area_offsite = shuttle.area_station
shuttle_controller.shuttles[shuttle_tag] = shuttle
shuttle_controller.process_shuttles += shuttle
testing("Exploration shuttle '[shuttle_tag]' at zlevel [z] successfully added.")
//Sets destination to new sector. Can be null.
/obj/machinery/computer/shuttle_control/explore/proc/update_destination(var/obj/effect/map/D)
destination = D
if(destination && shuttle_controller.shuttles[shuttle_tag])
var/datum/shuttle/ferry/shuttle = shuttle_controller.shuttles[shuttle_tag]
shuttle.area_offsite = destination.shuttle_landing
testing("Shuttle controller [shuttle_tag] now sends shuttle to [destination]")
shuttle_controller.shuttles[shuttle_tag] = shuttle
//Gets all sectors with landing zones in shuttle's range
/obj/machinery/computer/shuttle_control/explore/proc/get_possible_destinations()
var/list/res = list()
var/datum/shuttle/ferry/shuttle = shuttle_controller.shuttles[shuttle_tag]
for (var/obj/effect/map/S in orange(shuttle.range, home))
if(S.shuttle_landing)
res += S
return res
//Checks if current destination is still reachable
/obj/machinery/computer/shuttle_control/explore/proc/check_destination()
var/datum/shuttle/ferry/shuttle = shuttle_controller.shuttles[shuttle_tag]
return shuttle && destination && get_dist(home, destination) <= shuttle.range
/obj/machinery/computer/shuttle_control/explore/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null)
var/data[0]
var/datum/shuttle/ferry/shuttle = shuttle_controller.shuttles[shuttle_tag]
if (!istype(shuttle))
return
//If we are already there, or can't reach place anymore, reset destination
if(!shuttle.location && !check_destination())
destination = null
//check if shuttle can fly at all
var/can_go = !isnull(destination)
var/current_destination = destination ? destination.name : "None"
//shuttle doesn't need destination set to return home, as long as it's in range.
if(shuttle.location)
current_destination = "Return"
var/area/offsite = shuttle.area_offsite
var/obj/effect/map/cur_loc = map_sectors["[offsite.z]"]
can_go = (get_dist(home,cur_loc) <= shuttle.range)
//disable picking locations if there are none, or shuttle is already off-site
var/list/possible_d = get_possible_destinations()
var/can_pick = !shuttle.location && possible_d.len
var/shuttle_state
switch(shuttle.moving_status)
if(SHUTTLE_IDLE) shuttle_state = "idle"
if(SHUTTLE_WARMUP) shuttle_state = "warmup"
if(SHUTTLE_INTRANSIT) shuttle_state = "in_transit"
var/shuttle_status
switch (shuttle.process_state)
if(IDLE_STATE)
if (shuttle.in_use)
shuttle_status = "Busy."
else if (!shuttle.location)
shuttle_status = "Standing-by at station."
else
shuttle_status = "Standing-by at offsite location."
if(WAIT_LAUNCH)
shuttle_status = "Shuttle has recieved command and will depart shortly."
if(WAIT_ARRIVE)
shuttle_status = "Proceeding to destination."
if(WAIT_FINISH)
shuttle_status = "Arriving at destination now."
data = list(
"destination_name" = current_destination,
"can_pick" = can_pick,
"shuttle_status" = shuttle_status,
"shuttle_state" = shuttle_state,
"has_docking" = shuttle.docking_controller? 1 : 0,
"docking_status" = shuttle.docking_controller? shuttle.docking_controller.get_docking_status() : null,
"docking_override" = shuttle.docking_controller? shuttle.docking_controller.override_enabled : null,
"can_launch" = can_go && shuttle.can_launch(),
"can_cancel" = can_go && shuttle.can_cancel(),
"can_force" = can_go && shuttle.can_force(),
)
ui = nanomanager.try_update_ui(user, src, ui_key, ui, data)
if (!ui)
ui = new(user, src, ui_key, "shuttle_control_console_exploration.tmpl", "[shuttle_tag] Shuttle Control", 470, 310)
ui.set_initial_data(data)
ui.open()
ui.set_auto_update(1)
/obj/machinery/computer/shuttle_control/explore/Topic(href, href_list)
if(..())
return
usr.set_machine(src)
src.add_fingerprint(usr)
var/datum/shuttle/ferry/shuttle = shuttle_controller.shuttles[shuttle_tag]
if (!istype(shuttle))
return
if(href_list["pick"])
var/obj/effect/map/self = map_sectors["[z]"]
if(self)
var/list/possible_d = get_possible_destinations()
var/obj/effect/map/D
if(possible_d.len)
D = input("Choose shuttle destination", "Shuttle Destination") as null|anything in possible_d
update_destination(D)
if(href_list["move"])
shuttle.launch(src)
if(href_list["force"])
shuttle.force_launch(src)
else if(href_list["cancel"])
shuttle.cancel_launch(src)

View File

@@ -0,0 +1,60 @@
//Engine component object
var/list/ship_engines = list()
/datum/ship_engine
var/name = "ship engine"
var/obj/machinery/engine //actual engine object
var/zlevel = 0
/datum/ship_engine/New(var/obj/machinery/holder)
engine = holder
zlevel = holder.z
for(var/obj/machinery/computer/engines/E in machines)
if (E.z == zlevel && !(src in E.engines))
E.engines += src
break
//Tries to fire the engine. If successfull, returns 1
/datum/ship_engine/proc/burn()
if(!engine)
die()
return 1
//Returns status string for this engine
/datum/ship_engine/proc/get_status()
if(!engine)
die()
return "All systems nominal"
/datum/ship_engine/proc/get_thrust()
if(!engine)
die()
return 100
//Sets thrust limiter, a number between 0 and 1
/datum/ship_engine/proc/set_thrust_limit(var/new_limit)
if(!engine)
die()
return 1
/datum/ship_engine/proc/get_thrust_limit()
if(!engine)
die()
return 1
/datum/ship_engine/proc/is_on()
if(!engine)
die()
return 1
/datum/ship_engine/proc/toggle()
if(!engine)
die()
return 1
/datum/ship_engine/proc/die()
for(var/obj/machinery/computer/engines/E in machines)
if (E.z == zlevel)
E.engines -= src
break
del(src)

View File

@@ -0,0 +1,99 @@
//Thermal nozzle engine
/datum/ship_engine/thermal
name = "thermal engine"
/datum/ship_engine/thermal/get_status()
..()
var/obj/machinery/atmospherics/unary/engine/E = engine
return "Fuel pressure: [E.air_contents.return_pressure()]"
/datum/ship_engine/thermal/get_thrust()
..()
var/obj/machinery/atmospherics/unary/engine/E = engine
if(!is_on())
return 0
var/pressurized_coef = E.air_contents.return_pressure()/E.effective_pressure
return round(E.thrust_limit * E.nominal_thrust * pressurized_coef)
/datum/ship_engine/thermal/burn()
..()
var/obj/machinery/atmospherics/unary/engine/E = engine
return E.burn()
/datum/ship_engine/thermal/set_thrust_limit(var/new_limit)
..()
var/obj/machinery/atmospherics/unary/engine/E = engine
E.thrust_limit = new_limit
/datum/ship_engine/thermal/get_thrust_limit()
..()
var/obj/machinery/atmospherics/unary/engine/E = engine
return E.thrust_limit
/datum/ship_engine/thermal/is_on()
..()
var/obj/machinery/atmospherics/unary/engine/E = engine
return E.on
/datum/ship_engine/thermal/toggle()
..()
var/obj/machinery/atmospherics/unary/engine/E = engine
E.on = !E.on
//Actual thermal nozzle engine object
/obj/machinery/atmospherics/unary/engine
name = "engine nozzle"
desc = "Simple thermal nozzle, uses heated gast to propell the ship."
icon = 'icons/obj/ship_engine.dmi'
icon_state = "nozzle"
var/on = 1
var/thrust_limit = 1 //Value between 1 and 0 to limit the resulting thrust
var/nominal_thrust = 3000
var/effective_pressure = 3000
var/datum/ship_engine/thermal/controller
/obj/machinery/atmospherics/unary/engine/initialize()
..()
controller = new(src)
/obj/machinery/atmospherics/unary/engine/Del()
..()
controller.die()
/obj/machinery/atmospherics/unary/engine/proc/burn()
if (!on)
return
if(air_contents.temperature > 0)
var/transfer_moles = 100 * air_contents.volume/max(air_contents.temperature * R_IDEAL_GAS_EQUATION, 0,01)
transfer_moles = round(thrust_limit * transfer_moles, 0.01)
if(transfer_moles > air_contents.total_moles)
on = !on
return 0
var/datum/gas_mixture/removed = air_contents.remove(transfer_moles)
loc.assume_air(removed)
if(air_contents.temperature > PHORON_MINIMUM_BURN_TEMPERATURE)
var/exhaust_dir = reverse_direction(dir)
var/turf/T = get_step(src,exhaust_dir)
if(T)
new/obj/effect/engine_exhaust(T,exhaust_dir,air_contents.temperature)
return 1
//Exhaust effect
/obj/effect/engine_exhaust
name = "engine exhaust"
icon = 'icons/effects/effects.dmi'
icon_state = "exhaust"
anchored = 1
New(var/turf/nloc, var/ndir, var/temp)
dir = ndir
..(nloc)
if(nloc)
nloc.hotspot_expose(temp,125)
spawn(20)
loc = null

View File

@@ -0,0 +1,105 @@
/obj/effect/map/ship
name = "generic ship"
desc = "Space faring vessel."
icon_state = "sheet-sandstone"
var/vessel_mass = 9000 //tonnes, random number
var/default_delay = 60
var/list/speed = list(0,0)
var/last_burn = 0
var/list/last_movement = list(0,0)
var/fore_dir = NORTH
var/obj/effect/map/current_sector
var/obj/machinery/computer/helm/nav_control
var/obj/machinery/computer/engines/eng_control
/obj/effect/map/ship/initialize()
for(var/obj/machinery/computer/engines/E in machines)
if (E.z == map_z)
eng_control = E
break
for(var/obj/machinery/computer/helm/H in machines)
if (H.z == map_z)
nav_control = H
break
processing_objects.Add(src)
/obj/effect/map/ship/relaymove(mob/user, direction)
accelerate(direction)
/obj/effect/map/ship/proc/is_still()
return !(speed[1] || speed[2])
/obj/effect/map/ship/proc/get_acceleration()
return eng_control.get_total_thrust()/vessel_mass
/obj/effect/map/ship/proc/get_speed()
return round(sqrt(speed[1]*speed[1] + speed[2]*speed[2]))
/obj/effect/map/ship/proc/get_heading()
var/res = 0
if(speed[1])
if(speed[1] > 0)
res |= EAST
else
res |= WEST
if(speed[2])
if(speed[2] > 0)
res |= NORTH
else
res |= SOUTH
return res
/obj/effect/map/ship/proc/adjust_speed(n_x, n_y)
speed[1] = Clamp(speed[1] + n_x, -default_delay, default_delay)
speed[2] = Clamp(speed[2] + n_y, -default_delay, default_delay)
if(is_still())
toggle_move_stars(map_z)
else
toggle_move_stars(map_z, fore_dir)
/obj/effect/map/ship/proc/can_burn()
if (!eng_control)
return 0
if (world.time < last_burn + 10)
return 0
if (!eng_control.burn())
return 0
return 1
/obj/effect/map/ship/proc/get_brake_path()
if(!get_acceleration())
return INFINITY
return max(abs(speed[1]),abs(speed[2]))/get_acceleration()
/obj/effect/map/ship/proc/decelerate()
if(!is_still() && can_burn())
if (speed[1])
adjust_speed(-SIGN(speed[1]) * min(get_acceleration(),speed[1]), 0)
if (speed[2])
adjust_speed(0, -SIGN(speed[2]) * min(get_acceleration(),speed[2]))
last_burn = world.time
/obj/effect/map/ship/proc/accelerate(direction)
if(can_burn())
last_burn = world.time
if(direction & EAST)
adjust_speed(get_acceleration(), 0)
if(direction & WEST)
adjust_speed(-get_acceleration(), 0)
if(direction & NORTH)
adjust_speed(0, get_acceleration())
if(direction & SOUTH)
adjust_speed(0, -get_acceleration())
/obj/effect/map/ship/process()
if(!is_still())
var/list/deltas = list(0,0)
for(var/i=1, i<=2, i++)
if(speed[i] && world.time > last_movement[i] + default_delay - speed[i])
deltas[i] = speed[i] > 0 ? 1 : -1
last_movement[i] = world.time
var/turf/newloc = locate(x + deltas[1], y + deltas[2], z)
if(newloc)
Move(newloc)