mirror of
https://github.com/PolarisSS13/Polaris.git
synced 2025-12-25 01:22:24 +00:00
Merge pull request #4023 from Zuhayr/feature
Ability skeleton code, basic cryopod functionality.
This commit is contained in:
388
code/game/machinery/cryopod.dm
Normal file
388
code/game/machinery/cryopod.dm
Normal file
@@ -0,0 +1,388 @@
|
||||
/*
|
||||
* Cryogenic refrigeration unit. Basically a despawner.
|
||||
* Stealing a lot of concepts/code from sleepers due to massive laziness.
|
||||
* The despawn tick will only fire if it's been more than time_till_despawned ticks
|
||||
* since time_entered, which is world.time when the occupant moves in.
|
||||
* ~ Zuhayr
|
||||
*/
|
||||
|
||||
//Used for logging people entering cryosleep and important items they are carrying.
|
||||
var/global/list/frozen_crew = list()
|
||||
var/global/list/frozen_items = list()
|
||||
|
||||
//Main cryopod console.
|
||||
|
||||
/obj/machinery/computer/cryopod
|
||||
name = "cryogenic oversight console"
|
||||
desc = "An interface between crew and the cryogenic storage oversight systems."
|
||||
icon = 'icons/obj/Cryogenic2.dmi'
|
||||
icon_state = "cellconsole"
|
||||
circuit = "/obj/item/weapon/circuitboard/cryopodcontrol"
|
||||
var/mode = null
|
||||
|
||||
/obj/machinery/computer/cryopod/attack_paw()
|
||||
src.attack_hand()
|
||||
|
||||
/obj/machinery/computer/cryopod/attack_ai()
|
||||
src.attack_hand()
|
||||
|
||||
obj/machinery/computer/cryopod/attack_hand(mob/user = usr)
|
||||
if(stat & (NOPOWER|BROKEN))
|
||||
return
|
||||
|
||||
user.set_machine(src)
|
||||
src.add_fingerprint(usr)
|
||||
|
||||
var/dat
|
||||
|
||||
if (!( ticker ))
|
||||
return
|
||||
|
||||
dat += "<hr/><br/><b>Cryogenic Oversight Control</b><br/>"
|
||||
dat += "<i>Welcome, [user.real_name].</i><br/><br/><hr/>"
|
||||
dat += "<a href='?src=\ref[src];log=1'>View storage log</a>.<br>"
|
||||
dat += "<a href='?src=\ref[src];item=1'>Recover object</a>.<br>"
|
||||
dat += "<a href='?src=\ref[src];allitems=1'>Recover all objects</a>.<br>"
|
||||
dat += "<a href='?src=\ref[src];crew=1'>Revive crew</a>.<br/><hr/>"
|
||||
|
||||
user << browse(dat, "window=cryopod_console")
|
||||
onclose(user, "cryopod_console")
|
||||
|
||||
obj/machinery/computer/cryopod/Topic(href, href_list)
|
||||
|
||||
if(..())
|
||||
return
|
||||
|
||||
var/mob/user = usr
|
||||
|
||||
src.add_fingerprint(user)
|
||||
|
||||
if(href_list["log"])
|
||||
|
||||
var/dat = "<b>Recently stored crewmembers</b><br/><hr/><br/>"
|
||||
for(var/person in frozen_crew)
|
||||
dat += "[person]<br/>"
|
||||
dat += "<hr/>"
|
||||
|
||||
user << browse(dat, "window=cryolog")
|
||||
|
||||
else if(href_list["item"])
|
||||
|
||||
if(frozen_items.len == 0)
|
||||
user << "\blue There is nothing to recover from storage."
|
||||
return
|
||||
|
||||
var/obj/item/I = input(usr, "Please choose which object to retrieve.","Object recovery",null) as obj in frozen_items
|
||||
|
||||
if(!I || frozen_items.len == 0)
|
||||
user << "\blue There is nothing to recover from storage."
|
||||
return
|
||||
|
||||
visible_message("\blue The console beeps happily as it disgorges \the [I].", 3)
|
||||
|
||||
I.loc = get_turf(src)
|
||||
frozen_items -= I
|
||||
|
||||
else if(href_list["allitems"])
|
||||
|
||||
if(frozen_items.len == 0)
|
||||
user << "\blue There is nothing to recover from storage."
|
||||
return
|
||||
|
||||
visible_message("\blue The console beeps happily as it disgorges the desired objects.", 3)
|
||||
|
||||
for(var/obj/item/I in frozen_items)
|
||||
I.loc = get_turf(src)
|
||||
frozen_items -= I
|
||||
|
||||
else if(href_list["crew"])
|
||||
|
||||
user << "\red Functionality unavailable at this time."
|
||||
|
||||
src.updateUsrDialog()
|
||||
return
|
||||
|
||||
/obj/item/weapon/circuitboard/cryopodcontrol
|
||||
name = "Circuit board (Cryogenic Oversight Console)"
|
||||
build_path = "/obj/machinery/computer/cryopod"
|
||||
origin_tech = "programming=3"
|
||||
|
||||
//Decorative structures to go alongside cryopods.
|
||||
/obj/structure/cryofeed
|
||||
|
||||
name = "\improper cryogenic feed"
|
||||
desc = "A bewildering tangle of machinery and pipes."
|
||||
icon = 'icons/obj/Cryogenic2.dmi'
|
||||
icon_state = "cryo_rear"
|
||||
anchored = 1
|
||||
|
||||
var/orient_right = null //Flips the sprite.
|
||||
|
||||
/obj/structure/cryofeed/right
|
||||
orient_right = 1
|
||||
icon_state = "cryo_rear-r"
|
||||
|
||||
/obj/structure/cryofeed/New()
|
||||
|
||||
if(orient_right)
|
||||
icon_state = "cryo_rear-r"
|
||||
else
|
||||
icon_state = "cryo_rear"
|
||||
..()
|
||||
|
||||
//Cryopods themselves.
|
||||
/obj/machinery/cryopod
|
||||
name = "\improper cryogenic freezer"
|
||||
desc = "A man-sized pod for entering suspended animation."
|
||||
icon = 'icons/obj/Cryogenic2.dmi'
|
||||
icon_state = "body_scanner_0"
|
||||
density = 1
|
||||
anchored = 1
|
||||
|
||||
var/mob/occupant = null // Person waiting to be despawned.
|
||||
var/orient_right = null // Flips the sprite.
|
||||
var/time_till_despawn = 9000 // 15 minutes-ish safe period before being despawned.
|
||||
var/time_entered = 0 // Used to keep track of the safe period.
|
||||
var/obj/item/device/radio/intercom/announce //
|
||||
|
||||
// These items are preserved when the process() despawn proc occurs.
|
||||
var/list/preserve_items = list(
|
||||
/obj/item/weapon/hand_tele,
|
||||
/obj/item/weapon/card/id/captains_spare,
|
||||
/obj/item/device/aicard,
|
||||
/obj/item/device/mmi,
|
||||
/obj/item/device/paicard,
|
||||
/obj/item/weapon/gun,
|
||||
/obj/item/weapon/pinpointer,
|
||||
/obj/item/clothing/suit,
|
||||
/obj/item/clothing/shoes/magboots,
|
||||
/obj/item/blueprints,
|
||||
/obj/item/clothing/head/helmet/space/
|
||||
)
|
||||
|
||||
/obj/machinery/cryopod/right
|
||||
orient_right = 1
|
||||
icon_state = "body_scanner_0-r"
|
||||
|
||||
/obj/machinery/cryopod/New()
|
||||
|
||||
announce = new /obj/item/device/radio/intercom(src)
|
||||
|
||||
if(orient_right)
|
||||
icon_state = "body_scanner_0-r"
|
||||
else
|
||||
icon_state = "body_scanner_0"
|
||||
..()
|
||||
|
||||
//Lifted from Unity stasis.dm and refactored. ~Zuhayr
|
||||
/obj/machinery/cryopod/process()
|
||||
if(occupant)
|
||||
|
||||
//Allow a ten minute gap between entering the pod and actually despawning.
|
||||
if(world.time - time_entered < time_till_despawn)
|
||||
return
|
||||
|
||||
if(!occupant.client && occupant.stat<2) //Occupant is living and has no client.
|
||||
|
||||
//Delete all items not on the preservation list and drop all others into the pod.
|
||||
for(var/obj/item/W in occupant)
|
||||
occupant.drop_from_inventory(W)
|
||||
W.loc = src
|
||||
|
||||
var/preserve = null
|
||||
for(var/T in preserve_items)
|
||||
if(istype(W,T))
|
||||
preserve = 1
|
||||
break
|
||||
|
||||
if(!preserve)
|
||||
del(W)
|
||||
else
|
||||
frozen_items += W
|
||||
|
||||
var/job = occupant.mind.assigned_role
|
||||
var/role = occupant.mind.special_role
|
||||
|
||||
job_master.FreeRole(job)
|
||||
|
||||
if(role == "traitor" || role == "MODE")
|
||||
del(occupant.mind.objectives)
|
||||
occupant.mind.special_role = null
|
||||
else
|
||||
if(ticker.mode.name == "AutoTraitor")
|
||||
var/datum/game_mode/traitor/autotraitor/current_mode = ticker.mode
|
||||
current_mode.possible_traitors.Remove(occupant)
|
||||
|
||||
// Delete them from datacore.
|
||||
for(var/datum/data/record/R in data_core.medical)
|
||||
if ((R.fields["name"] == occupant.real_name))
|
||||
del(R)
|
||||
for(var/datum/data/record/T in data_core.security)
|
||||
if ((T.fields["name"] == occupant.real_name))
|
||||
del(T)
|
||||
for(var/datum/data/record/G in data_core.general)
|
||||
if ((G.fields["name"] == occupant.real_name))
|
||||
del(G)
|
||||
|
||||
if(orient_right)
|
||||
icon_state = "body_scanner_0-r"
|
||||
else
|
||||
icon_state = "body_scanner_0"
|
||||
|
||||
//TODO: Check objectives/mode, update new targets if this mob is the target, spawn new antags?
|
||||
|
||||
//This should guarantee that ghosts don't spawn.
|
||||
occupant.ckey = null
|
||||
|
||||
//Make an announcement and log the person entering storage.
|
||||
frozen_crew += "[occupant.real_name]"
|
||||
|
||||
announce.autosay("[occupant.real_name] has entered long-term storage.", "Cryogenic Oversight")
|
||||
visible_message("\blue The crypod hums and hisses as it moves [occupant.real_name] into storage.", 3)
|
||||
|
||||
// Delete the mob.
|
||||
del(occupant)
|
||||
occupant = null
|
||||
|
||||
|
||||
return
|
||||
|
||||
|
||||
/obj/machinery/cryopod/attackby(var/obj/item/weapon/G as obj, var/mob/user as mob)
|
||||
|
||||
if(istype(G, /obj/item/weapon/grab))
|
||||
|
||||
if(occupant)
|
||||
user << "\blue The cryo pod is in use."
|
||||
return
|
||||
|
||||
if(!ismob(G:affecting))
|
||||
return
|
||||
|
||||
var/willing = null //We don't want to allow people to be forced into despawning.
|
||||
var/mob/M = G:affecting
|
||||
|
||||
if(M.client)
|
||||
if(alert(M,"Would you like to enter cryosleep?",,"Yes","No") == "Yes")
|
||||
if(!M || !G || !G:affecting) return
|
||||
willing = 1
|
||||
else
|
||||
willing = 1
|
||||
|
||||
if(willing)
|
||||
|
||||
visible_message("[user] starts putting [G:affecting:name] into the cryo pod.", 3)
|
||||
|
||||
if(do_after(user, 20))
|
||||
if(!M || !G || !G:affecting) return
|
||||
|
||||
M.loc = src
|
||||
|
||||
if(M.client)
|
||||
M.client.perspective = EYE_PERSPECTIVE
|
||||
M.client.eye = src
|
||||
|
||||
if(orient_right)
|
||||
icon_state = "body_scanner_1-r"
|
||||
else
|
||||
icon_state = "body_scanner_1"
|
||||
|
||||
M << "\blue You feel cool air surround you. You go numb as your senses turn inward."
|
||||
M << "\blue <b>If you ghost, log out or close your client now, your character will shortly be permanently removed from the round.</b>"
|
||||
occupant = M
|
||||
time_entered = world.time
|
||||
|
||||
// Book keeping!
|
||||
log_admin("[key_name_admin(M)] has entered a stasis pod.")
|
||||
message_admins("\blue [key_name_admin(M)] has entered a stasis pod.")
|
||||
|
||||
//Despawning occurs when process() is called with an occupant without a client.
|
||||
src.add_fingerprint(M)
|
||||
|
||||
/obj/machinery/cryopod/verb/eject()
|
||||
set name = "Eject Pod"
|
||||
set category = "Object"
|
||||
set src in oview(1)
|
||||
if(usr.stat != 0)
|
||||
return
|
||||
|
||||
if(orient_right)
|
||||
icon_state = "body_scanner0-r"
|
||||
else
|
||||
icon_state = "body_scanner0"
|
||||
|
||||
src.go_out()
|
||||
add_fingerprint(usr)
|
||||
return
|
||||
|
||||
/obj/machinery/cryopod/verb/move_inside()
|
||||
set name = "Enter Pod"
|
||||
set category = "Object"
|
||||
set src in oview(1)
|
||||
|
||||
if(usr.stat != 0 || !(ishuman(usr) || ismonkey(usr)))
|
||||
return
|
||||
|
||||
if(src.occupant)
|
||||
usr << "\blue <B>The cryo pod is in use.</B>"
|
||||
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
|
||||
|
||||
visible_message("[usr] starts climbing into the cryo pod.", 3)
|
||||
|
||||
if(do_after(usr, 20))
|
||||
|
||||
if(!usr || !usr.client)
|
||||
return
|
||||
|
||||
if(src.occupant)
|
||||
usr << "\blue <B>The cryo pod is in use.</B>"
|
||||
return
|
||||
|
||||
usr.stop_pulling()
|
||||
usr.client.perspective = EYE_PERSPECTIVE
|
||||
usr.client.eye = src
|
||||
usr.loc = src
|
||||
src.occupant = usr
|
||||
|
||||
if(orient_right)
|
||||
icon_state = "body_scanner_1-r"
|
||||
else
|
||||
icon_state = "body_scanner_1"
|
||||
|
||||
usr << "\blue You feel cool air surround you. You go numb as your senses turn inward."
|
||||
usr << "\blue <b>If you ghost, log out or close your client now, your character will shortly be permanently removed from the round.</b>"
|
||||
occupant = usr
|
||||
time_entered = world.time
|
||||
|
||||
src.add_fingerprint(usr)
|
||||
|
||||
return
|
||||
|
||||
/obj/machinery/cryopod/proc/go_out()
|
||||
|
||||
if(!occupant)
|
||||
return
|
||||
|
||||
if(occupant.client)
|
||||
occupant.client.eye = src.occupant.client.mob
|
||||
occupant.client.perspective = MOB_PERSPECTIVE
|
||||
|
||||
occupant.loc = get_turf(src)
|
||||
occupant = null
|
||||
|
||||
if(orient_right)
|
||||
icon_state = "body_scanner_0-r"
|
||||
else
|
||||
icon_state = "body_scanner_0"
|
||||
|
||||
return
|
||||
|
||||
|
||||
//Attacks/effects.
|
||||
/obj/machinery/cryopod/blob_act()
|
||||
return //Sorta gamey, but we don't really want these to be destroyed.
|
||||
35
code/modules/mob/abilities.dm
Normal file
35
code/modules/mob/abilities.dm
Normal file
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
Creature-level abilities.
|
||||
*/
|
||||
|
||||
/var/global/list/ability_verbs = list( )
|
||||
|
||||
/*
|
||||
|
||||
Example ability:
|
||||
|
||||
/client/proc/test_ability()
|
||||
|
||||
set category = "Ability"
|
||||
set name = "Test ability"
|
||||
set desc = "An ability for testing."
|
||||
|
||||
// Check if the client has a mob and if the mob is valid and alive.
|
||||
if(!mob || !istype(mob,/mob/living) || mob.stat)
|
||||
src << "\red You must be corporeal and alive to do that."
|
||||
return 0
|
||||
|
||||
//Handcuff check.
|
||||
if(mob.restrained())
|
||||
src << "\red You cannot do this while restrained."
|
||||
return 0
|
||||
|
||||
if(istype(mob,/mob/living/carbon))
|
||||
var/mob/living/carbon/M = mob
|
||||
if(M.handcuffed)
|
||||
src << "\red You cannot do this while cuffed."
|
||||
return 0
|
||||
|
||||
src << "\blue You perform an ability."
|
||||
|
||||
*/
|
||||
@@ -37,6 +37,8 @@
|
||||
|
||||
var/flags = 0 // Various specific features.
|
||||
|
||||
var/list/abilities = list() // For species-derived or admin-given powers
|
||||
|
||||
/datum/species/human
|
||||
name = "Human"
|
||||
language = "Sol Common"
|
||||
@@ -44,6 +46,9 @@
|
||||
|
||||
flags = HAS_SKIN_TONE | HAS_LIPS | HAS_UNDERWEAR
|
||||
|
||||
//If you wanted to add a species-level ability:
|
||||
/*abilities = list(/client/proc/test_ability)*/
|
||||
|
||||
/datum/species/unathi
|
||||
name = "Unathi"
|
||||
icobase = 'icons/mob/human_races/r_lizard.dmi'
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
log_access("Notice: [key_name(src)] has the same [matches] as [key_name(M)] (no longer logged in).")
|
||||
|
||||
/mob/Login()
|
||||
|
||||
player_list |= src
|
||||
update_Login_details()
|
||||
world.update_status()
|
||||
@@ -44,4 +45,13 @@
|
||||
client.eye = src
|
||||
client.perspective = MOB_PERSPECTIVE
|
||||
|
||||
//Clear ability list and update from mob.
|
||||
client.verbs -= ability_verbs
|
||||
|
||||
if(abilities)
|
||||
client.verbs |= abilities
|
||||
|
||||
if(istype(src,/mob/living/carbon/human))
|
||||
var/mob/living/carbon/human/H = src
|
||||
if(H.species && H.species.abilities)
|
||||
client.verbs |= H.species.abilities
|
||||
@@ -84,10 +84,11 @@
|
||||
var/lastpuke = 0
|
||||
var/unacidable = 0
|
||||
var/small = 0
|
||||
var/list/pinned = list() //List of things pinning this creature to walls (see living_defense.dm)
|
||||
var/list/embedded = list() //Embedded items, since simple mobs don't have organs.
|
||||
var/list/pinned = list() // List of things pinning this creature to walls (see living_defense.dm)
|
||||
var/list/embedded = list() // Embedded items, since simple mobs don't have organs.
|
||||
var/list/languages = list() // For speaking/listening.
|
||||
var/list/speak_emote = list("says") //Verbs used when speaking. Defaults to 'say' if speak_emote is null.
|
||||
var/list/abilities = list() // For species-derived or admin-given powers.
|
||||
var/list/speak_emote = list("says") // Verbs used when speaking. Defaults to 'say' if speak_emote is null.
|
||||
|
||||
var/name_archive //For admin things like possession
|
||||
|
||||
|
||||
@@ -10,10 +10,10 @@
|
||||
icon_state = "dispenser"
|
||||
use_power = 0
|
||||
idle_power_usage = 40
|
||||
var/ui_name = "Chem Dispenser 5000"
|
||||
var/ui_name = "Chem Dispenser 5000"
|
||||
var/energy = 100
|
||||
var/max_energy = 100
|
||||
var/amount = 30
|
||||
var/amount = 30
|
||||
var/accept_glass = 0
|
||||
var/beaker = null
|
||||
var/recharged = 0
|
||||
@@ -434,7 +434,6 @@
|
||||
reagents.clear_reagents()
|
||||
icon_state = "mixer0"
|
||||
else if (href_list["createpill"] || href_list["createpill_multiple"])
|
||||
|
||||
var/count = 1
|
||||
|
||||
if(reagents.total_volume/count < 1) //Sanity checking.
|
||||
@@ -448,12 +447,11 @@
|
||||
|
||||
var/amount_per_pill = reagents.total_volume/count
|
||||
if (amount_per_pill > 50) amount_per_pill = 50
|
||||
|
||||
|
||||
var/name = reject_bad_text(input(usr,"Name:","Name your pill!","[reagents.get_master_reagent_name()] ([amount_per_pill] units)"))
|
||||
|
||||
if(reagents.total_volume/count < 1) //Sanity checking.
|
||||
return
|
||||
|
||||
while (count--)
|
||||
var/obj/item/weapon/reagent_containers/pill/P = new/obj/item/weapon/reagent_containers/pill(src.loc)
|
||||
if(!name) name = reagents.get_master_reagent_name()
|
||||
|
||||
Reference in New Issue
Block a user