mirror of
https://github.com/vgstation-coders/vgstation13.git
synced 2025-12-09 16:14:13 +00:00
488 lines
16 KiB
Plaintext
488 lines
16 KiB
Plaintext
// honk
|
|
#define DAMAGE 1
|
|
#define FIRE 2
|
|
|
|
/obj/spacepod
|
|
name = "\improper space pod"
|
|
desc = "A space pod meant for space travel."
|
|
icon = 'icons/48x48/pods.dmi'
|
|
density = 1 //Dense. To raise the heat.
|
|
opacity = 0
|
|
anchored = 1
|
|
unacidable = 1
|
|
layer = 3.9
|
|
infra_luminosity = 15
|
|
var/mob/living/carbon/occupant
|
|
var/datum/spacepod/equipment/equipment_system
|
|
var/obj/item/weapon/cell/battery
|
|
var/datum/gas_mixture/cabin_air
|
|
var/obj/machinery/portable_atmospherics/canister/internal_tank
|
|
var/datum/effect/effect/system/trail/space_trail/ion_trail
|
|
var/use_internal_tank = 0
|
|
var/datum/global_iterator/pr_int_temp_processor //normalizes internal air mixture temperature
|
|
var/datum/global_iterator/pr_give_air //moves air from tank to cabin
|
|
var/inertia_dir = 0
|
|
var/hatch_open = 0
|
|
var/next_firetime = 0
|
|
var/list/pod_overlays
|
|
var/health = 400
|
|
|
|
/obj/spacepod/New()
|
|
. = ..()
|
|
if(!pod_overlays)
|
|
pod_overlays = new/list(2)
|
|
pod_overlays[DAMAGE] = image(icon, icon_state="pod_damage")
|
|
pod_overlays[FIRE] = image(icon, icon_state="pod_fire")
|
|
bound_width = 64
|
|
bound_height = 64
|
|
dir = EAST
|
|
battery = new /obj/item/weapon/cell/high()
|
|
add_cabin()
|
|
add_airtank()
|
|
src.ion_trail = new /datum/effect/effect/system/trail/space_trail()
|
|
src.ion_trail.set_up(src)
|
|
src.ion_trail.start()
|
|
src.use_internal_tank = 1
|
|
pr_int_temp_processor = new /datum/global_iterator/pod_preserve_temp(list(src))
|
|
pr_give_air = new /datum/global_iterator/pod_tank_give_air(list(src))
|
|
equipment_system = new(src)
|
|
|
|
/obj/spacepod/proc/update_icons()
|
|
writepanic("[__FILE__].[__LINE__] ([src.type])([usr ? usr.ckey : ""]) \\/obj/spacepod/proc/update_icons() called tick#: [world.time]")
|
|
if(!pod_overlays)
|
|
pod_overlays = new/list(2)
|
|
pod_overlays[DAMAGE] = image(icon, icon_state="pod_damage")
|
|
pod_overlays[FIRE] = image(icon, icon_state="pod_fire")
|
|
|
|
if(health <= round(initial(health)/2))
|
|
overlays += pod_overlays[DAMAGE]
|
|
if(health <= round(initial(health)/4))
|
|
overlays += pod_overlays[FIRE]
|
|
else
|
|
overlays -= pod_overlays[FIRE]
|
|
else
|
|
overlays -= pod_overlays[DAMAGE]
|
|
|
|
/obj/spacepod/bullet_act(var/obj/item/projectile/P)
|
|
if(P.damage && !P.nodamage)
|
|
deal_damage(P.damage)
|
|
|
|
/obj/spacepod/proc/deal_damage(var/damage)
|
|
writepanic("[__FILE__].[__LINE__] ([src.type])([usr ? usr.ckey : ""]) \\/obj/spacepod/proc/deal_damage() called tick#: [world.time]")
|
|
var/oldhealth = health
|
|
health = max(0, health - damage)
|
|
var/percentage = (health / initial(health)) * 100
|
|
if(occupant && oldhealth > health && percentage <= 25 && percentage > 0)
|
|
var/sound/S = sound('sound/effects/engine_alert2.ogg')
|
|
S.wait = 0 //No queue
|
|
S.channel = 0 //Any channel
|
|
S.volume = 50
|
|
occupant << S
|
|
if(occupant && oldhealth > health && !health)
|
|
var/sound/S = sound('sound/effects/engine_alert1.ogg')
|
|
S.wait = 0
|
|
S.channel = 0
|
|
S.volume = 50
|
|
occupant << S
|
|
if(!health)
|
|
spawn(0)
|
|
if(occupant)
|
|
occupant << "<big><span class='warning'>Critical damage to the vessel detected, core explosion imminent!</span></big>"
|
|
for(var/i = 10, i >= 0; --i)
|
|
if(occupant)
|
|
occupant << "<span class='warning'>[i]</span>"
|
|
if(i == 0)
|
|
explosion(loc, 2, 4, 8)
|
|
sleep(10)
|
|
|
|
update_icons()
|
|
|
|
/obj/spacepod/ex_act(severity)
|
|
switch(severity)
|
|
if(1)
|
|
var/mob/living/carbon/human/H = occupant
|
|
if(H)
|
|
H.loc = get_turf(src)
|
|
H.ex_act(severity + 1)
|
|
H << "<span class='warning'>You are forcefully thrown from \the [src]!</span>"
|
|
del(ion_trail)
|
|
del(src)
|
|
if(2)
|
|
deal_damage(100)
|
|
if(3)
|
|
if(prob(40))
|
|
deal_damage(50)
|
|
|
|
/obj/spacepod/attackby(obj/item/W as obj, mob/user as mob)
|
|
if(iscrowbar(W))
|
|
hatch_open = !hatch_open
|
|
user << "<span class='notice'>You [hatch_open ? "open" : "close"] the maintenance hatch.</span>"
|
|
if(istype(W, /obj/item/weapon/cell))
|
|
if(!hatch_open)
|
|
return ..()
|
|
if(battery)
|
|
user << "<span class='notice'>The pod already has a battery.</span>"
|
|
return
|
|
user.drop_item(W, src)
|
|
battery = W
|
|
return
|
|
if(istype(W, /obj/item/device/spacepod_equipment))
|
|
if(!hatch_open)
|
|
return ..()
|
|
if(!equipment_system)
|
|
user << "<span class='warning'>The pod has no equipment datum, yell at pomf</span>"
|
|
return
|
|
if(istype(W, /obj/item/device/spacepod_equipment/weaponry))
|
|
if(equipment_system.weapon_system)
|
|
user << "<span class='notice'>The pod already has a weapon system, remove it first.</span>"
|
|
return
|
|
else
|
|
user << "<span class='notice'>You insert \the [W] into the equipment system.</span>"
|
|
user.drop_item(W, equipment_system)
|
|
equipment_system.weapon_system = W
|
|
equipment_system.weapon_system.my_atom = src
|
|
new/obj/item/device/spacepod_equipment/weaponry/proc/fire_weapon_system(src, equipment_system.weapon_system.verb_name, equipment_system.weapon_system.verb_desc) //Yes, it has to be referenced like that. W.verb_name/desc doesn't compile.
|
|
return
|
|
|
|
|
|
/obj/spacepod/attack_hand(mob/user as mob)
|
|
if(!hatch_open)
|
|
return ..()
|
|
if(!equipment_system || !istype(equipment_system))
|
|
user << "<span class='warning'>The pod has no equipment datum, or is the wrong type, yell at pomf.</span>"
|
|
return
|
|
var/list/possible = list()
|
|
if(battery)
|
|
possible.Add("Energy Cell")
|
|
if(equipment_system.weapon_system)
|
|
possible.Add("Weapon System")
|
|
/* Not yet implemented
|
|
if(equipment_system.engine_system)
|
|
possible.Add("Engine System")
|
|
if(equipment_system.shield_system)
|
|
possible.Add("Shield System")
|
|
*/
|
|
var/obj/item/device/spacepod_equipment/SPE
|
|
switch(input(user, "Remove which equipment?", null, null) as null|anything in possible)
|
|
if("Energy Cell")
|
|
if(user.put_in_any_hand_if_possible(battery))
|
|
user << "<span class='notice'>You remove \the [battery] from the space pod</span>"
|
|
battery = null
|
|
if("Weapon System")
|
|
SPE = equipment_system.weapon_system
|
|
if(user.put_in_any_hand_if_possible(SPE))
|
|
user << "<span class='notice'>You remove \the [SPE] from the equipment system.</span>"
|
|
SPE.my_atom = null
|
|
equipment_system.weapon_system = null
|
|
verbs -= typesof(/obj/item/device/spacepod_equipment/weaponry/proc)
|
|
else
|
|
user << "<span class='warning'>You need an open hand to do that.</span>"
|
|
/*
|
|
if("engine system")
|
|
SPE = equipment_system.engine_system
|
|
if(user.put_in_any_hand_if_possible(SPE))
|
|
user << "<span class='notice'>You remove \the [SPE] from the equipment system.</span>"
|
|
equipment_system.engine_system = null
|
|
else
|
|
user << "<span class='warning'>You need an open hand to do that.</span>"
|
|
if("shield system")
|
|
SPE = equipment_system.shield_system
|
|
if(user.put_in_any_hand_if_possible(SPE))
|
|
user << "<span class='notice'>You remove \the [SPE] from the equipment system.</span>"
|
|
equipment_system.shield_system = null
|
|
else
|
|
user << "<span class='warning'>You need an open hand to do that.</span>"
|
|
*/
|
|
|
|
return
|
|
|
|
/obj/spacepod/civilian
|
|
icon_state = "pod_civ"
|
|
desc = "A sleek civilian space pod."
|
|
/obj/spacepod/random
|
|
icon_state = "pod_civ"
|
|
// placeholder
|
|
/obj/spacepod/random/New()
|
|
..()
|
|
icon_state = pick("pod_civ", "pod_black", "pod_mil", "pod_synd", "pod_gold", "pod_industrial")
|
|
switch(icon_state)
|
|
if("pod_civ")
|
|
desc = "A sleek civilian space pod."
|
|
if("pod_black")
|
|
desc = "An all black space pod with no insignias."
|
|
if("pod_mil")
|
|
desc = "A dark grey space pod brandishing the Nanotrasen Military insignia"
|
|
if("pod_synd")
|
|
desc = "A menacing military space pod with Fuck NT stenciled onto the side"
|
|
if("pod_gold")
|
|
desc = "A civilian space pod with a gold body, must have cost somebody a pretty penny"
|
|
if("pod_industrial")
|
|
desc = "A rough looking space pod meant for industrial work"
|
|
|
|
/obj/spacepod/verb/toggle_internal_tank()
|
|
set name = "Toggle internal airtank usage"
|
|
set category = "Spacepod"
|
|
set src = usr.loc
|
|
set popup_menu = 0
|
|
writepanic("[__FILE__].[__LINE__] ([src.type])([usr ? usr.ckey : ""]) \\/obj/spacepod/verb/toggle_internal_tank() called tick#: [world.time]")
|
|
if(usr!=src.occupant)
|
|
return
|
|
src.use_internal_tank = !src.use_internal_tank
|
|
src.occupant << "<span class='notice'>Now taking air from [use_internal_tank?"internal airtank":"environment"].</span>"
|
|
return
|
|
|
|
/obj/spacepod/proc/add_cabin()
|
|
writepanic("[__FILE__].[__LINE__] ([src.type])([usr ? usr.ckey : ""]) \\/obj/spacepod/proc/add_cabin() called tick#: [world.time]")
|
|
cabin_air = new
|
|
cabin_air.temperature = T20C
|
|
cabin_air.volume = 200
|
|
cabin_air.oxygen = O2STANDARD*cabin_air.volume/(R_IDEAL_GAS_EQUATION*cabin_air.temperature)
|
|
cabin_air.nitrogen = N2STANDARD*cabin_air.volume/(R_IDEAL_GAS_EQUATION*cabin_air.temperature)
|
|
return cabin_air
|
|
|
|
/obj/spacepod/proc/add_airtank()
|
|
writepanic("[__FILE__].[__LINE__] ([src.type])([usr ? usr.ckey : ""]) \\/obj/spacepod/proc/add_airtank() called tick#: [world.time]")
|
|
internal_tank = new /obj/machinery/portable_atmospherics/canister/air(src)
|
|
return internal_tank
|
|
|
|
/obj/spacepod/proc/get_turf_air()
|
|
writepanic("[__FILE__].[__LINE__] ([src.type])([usr ? usr.ckey : ""]) \\/obj/spacepod/proc/get_turf_air() called tick#: [world.time]")
|
|
var/turf/T = get_turf(src)
|
|
if(T)
|
|
. = T.return_air()
|
|
return
|
|
|
|
/obj/spacepod/remove_air(amount)
|
|
if(use_internal_tank)
|
|
return cabin_air.remove(amount)
|
|
else
|
|
var/turf/T = get_turf(src)
|
|
if(T)
|
|
return T.remove_air(amount)
|
|
return
|
|
|
|
/obj/spacepod/return_air()
|
|
if(use_internal_tank)
|
|
return cabin_air
|
|
return get_turf_air()
|
|
|
|
/obj/spacepod/proc/return_pressure()
|
|
writepanic("[__FILE__].[__LINE__] ([src.type])([usr ? usr.ckey : ""]) \\/obj/spacepod/proc/return_pressure() called tick#: [world.time]")
|
|
. = 0
|
|
if(use_internal_tank)
|
|
. = cabin_air.return_pressure()
|
|
else
|
|
var/datum/gas_mixture/t_air = get_turf_air()
|
|
if(t_air)
|
|
. = t_air.return_pressure()
|
|
return
|
|
|
|
/obj/spacepod/proc/return_temperature()
|
|
writepanic("[__FILE__].[__LINE__] ([src.type])([usr ? usr.ckey : ""]) \\/obj/spacepod/proc/return_temperature() called tick#: [world.time]")
|
|
. = 0
|
|
if(use_internal_tank)
|
|
. = cabin_air.return_temperature()
|
|
else
|
|
var/datum/gas_mixture/t_air = get_turf_air()
|
|
if(t_air)
|
|
. = t_air.return_temperature()
|
|
return
|
|
|
|
/obj/spacepod/proc/moved_inside(var/mob/living/carbon/human/H as mob)
|
|
writepanic("[__FILE__].[__LINE__] ([src.type])([usr ? usr.ckey : ""]) \\/obj/spacepod/proc/moved_inside() called tick#: [world.time]")
|
|
if(H && H.client && H in range(1))
|
|
H.reset_view(src)
|
|
/*
|
|
H.client.perspective = EYE_PERSPECTIVE
|
|
H.client.eye = src
|
|
*/
|
|
H.stop_pulling()
|
|
H.forceMove(src)
|
|
src.occupant = H
|
|
src.add_fingerprint(H)
|
|
src.forceMove(src.loc)
|
|
//dir = dir_in
|
|
playsound(src, 'sound/machines/windowdoor.ogg', 50, 1)
|
|
return 1
|
|
else
|
|
return 0
|
|
|
|
/obj/spacepod/MouseDrop_T(mob/M as mob, mob/user as mob)
|
|
if(M != user)
|
|
return
|
|
move_inside(M, user)
|
|
|
|
/obj/spacepod/verb/move_inside()
|
|
set category = "Object"
|
|
set name = "Enter Pod"
|
|
set src in oview(1)
|
|
writepanic("[__FILE__].[__LINE__] ([src.type])([usr ? usr.ckey : ""]) \\/obj/spacepod/verb/move_inside() called tick#: [world.time]")
|
|
|
|
if(usr.restrained() || usr.stat || usr.weakened || usr.stunned || usr.paralysis || usr.resting || (usr.status_flags & FAKEDEATH)) //are you cuffed, dying, lying, stunned or other
|
|
return
|
|
if (usr.stat || !ishuman(usr))
|
|
return
|
|
if (src.occupant)
|
|
usr << "<span class='notice'><B>The [src.name] is already occupied!</B></span>"
|
|
return
|
|
/*
|
|
if (usr.abiotic())
|
|
usr << "<span class='notice'><B>Subject cannot have abiotic items on.</B></span>"
|
|
return
|
|
*/
|
|
for(var/mob/living/carbon/slime/M in range(1,usr))
|
|
if(M.Victim == usr)
|
|
usr << "You're too busy getting your life sucked out of you."
|
|
return
|
|
// usr << "You start climbing into [src.name]"
|
|
|
|
visible_message("<span class='notice'>[usr] starts to climb into [src.name]</span>")
|
|
|
|
if(enter_after(40,usr))
|
|
if(!src.occupant)
|
|
moved_inside(usr)
|
|
else if(src.occupant!=usr)
|
|
usr << "[src.occupant] was faster. Try better next time, loser."
|
|
else
|
|
usr << "You stop entering the exosuit."
|
|
return
|
|
|
|
/obj/spacepod/verb/exit_pod()
|
|
set name = "Exit pod"
|
|
set category = "Spacepod"
|
|
set src = usr.loc
|
|
writepanic("[__FILE__].[__LINE__] ([src.type])([usr ? usr.ckey : ""]) \\/obj/spacepod/verb/exit_pod() called tick#: [world.time]")
|
|
|
|
if(usr != src.occupant)
|
|
return
|
|
src.inertia_dir = 0 // engage reverse thruster and power down pod
|
|
src.occupant.loc = src.loc
|
|
src.occupant = null
|
|
usr << "<span class='notice'>You climb out of the pod</span>"
|
|
return
|
|
|
|
/obj/spacepod/proc/enter_after(delay as num, var/mob/user as mob, var/numticks = 5)
|
|
writepanic("[__FILE__].[__LINE__] ([src.type])([usr ? usr.ckey : ""]) \\/obj/spacepod/proc/enter_after() called tick#: [world.time]")
|
|
var/delayfraction = delay/numticks
|
|
|
|
var/turf/T = user.loc
|
|
|
|
for(var/i = 0, i<numticks, i++)
|
|
sleep(delayfraction)
|
|
if(!src || !user || !user.canmove || !(user.loc == T))
|
|
return 0
|
|
|
|
return 1
|
|
|
|
/datum/global_iterator/pod_preserve_temp //normalizing cabin air temperature to 20 degrees celsium
|
|
delay = 20
|
|
|
|
process(var/obj/spacepod/spacepod)
|
|
if(spacepod.cabin_air && spacepod.cabin_air.return_volume() > 0)
|
|
var/delta = spacepod.cabin_air.temperature - T20C
|
|
spacepod.cabin_air.temperature -= max(-10, min(10, round(delta/4,0.1)))
|
|
return
|
|
|
|
/datum/global_iterator/pod_tank_give_air
|
|
delay = 15
|
|
|
|
process(var/obj/spacepod/spacepod)
|
|
if(spacepod.internal_tank)
|
|
var/datum/gas_mixture/tank_air = spacepod.internal_tank.return_air()
|
|
var/datum/gas_mixture/cabin_air = spacepod.cabin_air
|
|
|
|
var/release_pressure = ONE_ATMOSPHERE
|
|
var/cabin_pressure = cabin_air.return_pressure()
|
|
var/pressure_delta = min(release_pressure - cabin_pressure, (tank_air.return_pressure() - cabin_pressure)/2)
|
|
var/transfer_moles = 0
|
|
if(pressure_delta > 0) //cabin pressure lower than release pressure
|
|
if(tank_air.return_temperature() > 0)
|
|
transfer_moles = pressure_delta*cabin_air.return_volume()/(cabin_air.return_temperature() * R_IDEAL_GAS_EQUATION)
|
|
var/datum/gas_mixture/removed = tank_air.remove(transfer_moles)
|
|
cabin_air.merge(removed)
|
|
else if(pressure_delta < 0) //cabin pressure higher than release pressure
|
|
var/datum/gas_mixture/t_air = spacepod.get_turf_air()
|
|
pressure_delta = cabin_pressure - release_pressure
|
|
if(t_air)
|
|
pressure_delta = min(cabin_pressure - t_air.return_pressure(), pressure_delta)
|
|
if(pressure_delta > 0) //if location pressure is lower than cabin pressure
|
|
transfer_moles = pressure_delta*cabin_air.return_volume()/(cabin_air.return_temperature() * R_IDEAL_GAS_EQUATION)
|
|
var/datum/gas_mixture/removed = cabin_air.remove(transfer_moles)
|
|
if(t_air)
|
|
t_air.merge(removed)
|
|
else //just delete the cabin gas, we're in space or some shit
|
|
del(removed)
|
|
else
|
|
return stop()
|
|
return
|
|
|
|
/obj/spacepod/Move(NewLoc, Dir = 0, step_x = 0, step_y = 0)
|
|
var/oldloc = src.loc
|
|
. = ..()
|
|
if(dir && (oldloc != NewLoc))
|
|
src.loc.Entered(src, oldloc)
|
|
/obj/spacepod/proc/Process_Spacemove(var/check_drift = 0, mob/user)
|
|
writepanic("[__FILE__].[__LINE__] ([src.type])([usr ? usr.ckey : ""]) \\/obj/spacepod/proc/Process_Spacemove() called tick#: [world.time]")
|
|
var/dense_object = 0
|
|
if(!user)
|
|
for(var/direction in list(NORTH, NORTHEAST, EAST))
|
|
var/turf/cardinal = get_step(src, direction)
|
|
if(istype(cardinal, /turf/space))
|
|
continue
|
|
dense_object++
|
|
break
|
|
if(!dense_object)
|
|
return 0
|
|
inertia_dir = 0
|
|
return 1
|
|
|
|
/obj/spacepod/relaymove(mob/user, direction)
|
|
var/moveship = 1
|
|
if(battery && battery.charge >= 3 && health)
|
|
src.dir = direction
|
|
switch(direction)
|
|
if(1)
|
|
if(inertia_dir == 2)
|
|
inertia_dir = 0
|
|
moveship = 0
|
|
if(2)
|
|
if(inertia_dir == 1)
|
|
inertia_dir = 0
|
|
moveship = 0
|
|
if(4)
|
|
if(inertia_dir == 8)
|
|
inertia_dir = 0
|
|
moveship = 0
|
|
if(8)
|
|
if(inertia_dir == 4)
|
|
inertia_dir = 0
|
|
moveship = 0
|
|
if(moveship)
|
|
Move(get_step(src,direction), direction)
|
|
if(istype(src.loc, /turf/space))
|
|
inertia_dir = direction
|
|
else
|
|
if(!battery)
|
|
user << "<span class='warning'>No energy cell detected.</span>"
|
|
else if(battery.charge < 3)
|
|
user << "<span class='warning'>Not enough charge left.</span>"
|
|
else if(!health)
|
|
user << "<span class='warning'>She's dead, Jim</span>"
|
|
else
|
|
user << "<span class='warning'>Unknown error has occurred, yell at pomf.</span>"
|
|
return 0
|
|
battery.charge = max(0, battery.charge - 3)
|
|
|
|
/obj/effect/landmark/spacepod/random
|
|
name = "spacepod spawner"
|
|
invisibility = 101
|
|
icon = 'icons/mob/screen1.dmi'
|
|
icon_state = "x"
|
|
anchored = 1
|
|
|
|
/obj/effect/landmark/spacepod/random/New()
|
|
..()
|
|
|
|
#undef DAMAGE
|
|
#undef FIRE
|