HVB`{~KzMl(VhV(p7a`swLB#UA+!4a>3Lffla^1)u!0(FJlE!N>
zJbs;Kh}De<;de3tk8)qy420@Ngz!6=fc;a^993f7i~xQo6O{XXp>L-EeP2_xhVqB-
zJDH#=c#i#ak*?4e3(zBo--)y(O;DC%AAgw+y!C3i04>7!-B39jzT$hRGE?~KwWR@bku)qi~Z
zoKDODogSKl8aSO)3J+Zsp!6k&p;r=`pepx2&nK~jdQ#g*9*||2VF_n
zCNGNf`O-AQ5;e``d{#daJoKS}QP&GdVG!5#<$_p(gGhibm%8@X#{v%X0>=EV|G#Is
zw+`>Zni^1Xtv(bm>RJKD1O@IvVSj*bq9coUBfpQ{c7Sde3|(R|Lu~wyU(*a8de;GZ
z5`#o0_@zw&A-;Ow1NxX>0_H2(4KpBT;De_S2}suwPn{4z*XAb-yvRLNHNW{5`Z)d;
z30h^qskeZxr4Iuyau1bFbNuU#{yFk@DbZ%grDF`}DGc&Gv^S0s(zSix5`RCP&!A0L
z=|kb4+(Sj74q7$=EhYpLKb_B@P1oipd=K(HR8`tBOgh}QnE2`RL!e!EETFrGoB#*_61$b9|r&A42dU|Oh6Zie);K|!MPqC
zd`va4`Vo&Y`%0iEaA*viUVmSIq~v!wA}PPiX)p=D%V{tTzsqRQ#^NNiT=Z_mye6C&wh@)OR2~z%e8E@eUTn0!F=)E*Z27o9NOb95uHu3@*TENLHfR8ee
z3;OEIu*9r|OD+SX>&fSGkiL@!6#h!O#@{2{uzf1Y>i@g--
z0CD7V69U?c0yKSe=zmJ!(s9?~VmWZz4IjBjfOwb#M5BPitN>R6r`{6$`B}`Sm$qOc
z?*tMcs<04H6
z8U*>A55N0^27kl&o#<0(eNq}s!0&{tetPSbm~~lNU_AxDo6B`l{T}zY$A3Cp?BwPK
zR&LM@cU0uzgYj^OMGPNw8H|QI2wC`GB7@Oz2O$d|Ok^+`?jU60gK5GK?kvUtcaXd^
zP5EFVgAN0;-+OB>RZ{g;A%ic9mNW((1~^->>DVx+@qfdV2DyQSU&0~{?pSo?T=nef3C
z8Z`Of>I~ZX;7SbI`QTa%TKV8Q3<7*`B?j$$a4iO{`0Z}c&!C+T#v6>{cWyqIz@ek%
cc6{$&;}c%1;q~&52mk;807*qoM6N<$f?`}LzyJUM
diff --git a/goon/icons/obj/power.dmi b/goon/icons/obj/power.dmi
index f70f5b51c19a0642889950c291fbe5956cba5367..bb787c0b3c9fe5e694868b293de1eaa4df5dcd62 100644
GIT binary patch
delta 4057
zcmV;~4<_)B55gdSiBL{Q4GJ0x0000DNk~Le0001>0001h2m=5B0K2`CDF6Tf;ZRIe
zMgM?+EiEko0015m>Y;0FoSO0*3#$r%&k!+EFnWwDa>gNLX8UXW;L2FEdrosRK4tYsL
zK~#90?OF|6;<^$hi`Y~^aBKN!D^SE@U6y-JMb?893c`y2{}0`nq=lBIl*7lK^W3|m
z534&(@@8f-nR#m_^IO(J2>FuDW_LXT>I-=6S0RcD$zA4%MCD|N+3Z!mz#dDP={$RX
zAjRtpF8p7
zY!^PW*-(gFD4iZ)y}$I>k;BK#O#%#p~^8jh>s=O&$dbB@$r$CVX-TJ-plLTdb3?ER+-%5N3mG#H1DckS-#9l)S!S*
z)xeOJ1U8ao!%$n2Bu5Zhu(Bn8muP_|0faQuQkkK}_Uqo>b}dx}fMo;L3;sXNg4uFG
zFO)&x)3U6xuIubK_>2H#rjaEXvTu=m6q~hBvzL#z(fQPt~yJimemD6it*WC
zA20%(kFXEY0Hkdo1Q1rX7>X+qzyLh%BaW|)_#Q0?Yzsm@93yEiObda{BIrAeLGYyr
zV3v8`61f=ek75zf@ory0E8Ow7-K5Ph(9
z$)%)`)HD>apxUZH2nj7{v}i$iilKgKR_lZ#lqD$^AiERs-WFu0fxB2wNHa!D(<_D)
zvmnVRb(kN`_gK&YLS`Fb%2k$n6$T689frk10zg!Oabqz^a@SCQNIpJls#FFe3CEs9
z7(iLm%7z#qs#GWzu%?KNySyxt3c$xQLla&?Cjy9dlw4BFhAIYF(pa&uU2YKqtqhdg
zSf^>)`S4{}B?_lFshW{XB?b`d+NkD>B$X=I%ZLlflL5q99@9*#rHb@eM@RrLUh-$5
z7cA)poYc%Y5wdQ72)a65QiT?znxRtwh`rU8Dw~x6EzLue~di(
z-;k%LJs*r&`PZ2J+iiOP>Wivrx_y57>nm0no#&@AXWlvafc!Ce3O
z<4-3ApWQ8*NaJahHFJ?Im+^OEn#Hb&*TEAG{-rvUqT*sXgpaC5S%-(^Sf=QOWCuRG
z+HE5~NiPH@%t{4aLWFI`F2(U(-rNwVCc(=F-HkARPpJX^g=fjlO*B*Vo}ULV55wWh
z%i#Gr2_fPG2+$p@CTfl5y~zx(L*pv0M;SXr5g)k1yl*z5FB<^hpf_N`eiV$i?CxzB*^^R5kKpqW
z>Xj0bWAIRnzax$Ns)neEpb5#O+TD}j~24LX7zq6srC?9@A+j2A&5W6$CEB|
zAM!^9UE3nM!8n>;kR{1tVGy?=obZlKFuE+5LUdB{R6_0xB9+)3%oP6rKY=ux4g)yo
zqXl2_XQ$ajO=t;z04!=j7}HqFh4cz>D1%yjQb?x*xGh;i7_xxmHCj|g=#p%KB|2+=
zp8TnuYv+{ypB&)eW$9N?&bQ5*3@J*qWE5r8MTs`yq9x+;Bu4~jCXfs7R8
zAp-D3m;D;y-z_#a2q6St0boCh?_}kYkMQr8YXL$oj-cE+UBP)+!Ml;9g7su2d*-l~
zVJ(Rz|EZcDhVX!LBJv2rkVvM2R_aRNDz
zeEL-uJX|g=QXWX-=h7xf8-J`m&BST?r}ph`{gLBSgEUS5luHA6-1y%XJkEk|Z*ODv
z^(NN4?u320u2?_yX6(!J#ClNh2c`+@&!_M3J)I}$LE($|iN#{+%VHrOzgUZSd?4ca
z$J4pz!M8VGcq0A#+_UFQY;XR59@oznuKkmV?Jj2G@h%gw9>@E7;rwsYsg3B}1^goz
z5AYYJ4fs9VTzK(4!bsP&KR|5Lb>lYT=%4?0?~!D<-D9
zi0u*f?=H>N1in`0(v8{3A3uXHq23?Q9uUnx27I2)*I(fVz4-p!_tmF=Gj_(Ge1^y#
z7kvIt2jp`#TW;HE%JC)Y+4xzYkI#?x^St$VciV>k{EmYat>diTw`TD8{A<0rh2V|v
z&vBal`dS}4>n`6P=tJ{|a)po2$vFKwd~h3vcjzr_6UO`O7d&B_cG$?iKEr#Oxc+U*
z$0N7WA94LM3~-#2BP*~+#f0P%!@eFOFjtPFt~0m$^c
z@gMp6kPqHq1<*gk_~A%l`k%|mMn75pM14;g0l@w<>gQ2_3y6=*^J^#9P@w0;C~yOS
zNYS7RXHGLck1_ol0vy+eNP_1&s0V-()LdNPCs^=f<V(Wh`hrB5Tikepo?Ka9s+wEg0w?4
z_7904K~GE=#Y4LNY;ledPw$3BWY=W$WJrtG?A2M!us$jo@1Js
z;VJRcl)aT^(h_l6B7Y0?exja<67_78sLicJJ;j>_g2?d`^#?@AGE&s-b(QV73fFpm
zm5Hyq_59oW!x%z@t51C3a}vk5cQKGyOayvX3?vr|yqFM-_Yk3t<5w#i@l7&YvR^rs
zT#g-EZXrT{+g#3;OVbwN+pi$qRnQ(=u!5HZeayeX9@9$t-7UefB|q~rR@4iT{ZP`H
zqO_)J8Z<>he1I@$suG$aKsaOH3G1W$yW7sp@5cTAz=Hocy_WjtdFSQ_kCi=K_-&{D
z+!XE}had&unMv^97CcI(NY3GR!d13Nxr*FC@0|yK-)w>W+#J5e2zgP77rMCEm@L^%
zFJOL7BXCtSeh&JNX}F;Y>)oYa4hhN)cexD8B_Y3e0(@9%npjrO1zw)G#%DtOUv&IY!pI|NS`na64ngmK53TF_hWvT=kX&+lilXFdqrOk>Y{(xr
z9`ru{2LN$=i2OMQAJStGVzXJ8UIPov=OKE`Tf8H`*Qh-V2g6|<0djimiSd6pKFt3)
zCXAnk|Ge%9fc^qtfiOS#4ldg8gL9;4oqjK;3^2(0&J6iGwgJZfF&9VpKNkQ-{y_16
z2!w%)9Vg%i(Zz1m#S7-*j>#xIaN)+qeEgER*ysOnycdi=i7ePlj!eK0CLWSkJVgD0
zv(4WHhs5Xq*!ZMZf(HVGyf6vzgR6L&!8GzbfIRf<#P~ZLznZQ2zcEWwrvw;Dv>AuL
z>Iw6I{6)){CF&p%dtrd=B3zH(PV~or%Y-B3SJ^E7vTVG0RrUE9!{=Ys>sMW;$LHHH
z{4#IrDt!xH_L+V$u%-9H#YF5XKZW?^(#%|nUx)gyOQ9YUms7kPbKlK`a_uAtS;4u)
zf-|;0^Rf-q?1I&`0zLA3SWz#q;5`FA^zwpL^hu@C+jNfo0KT#p>b(VfpN|1Rcyj;x
z2!p04f!}+Z@}_FXA3cB)zRzMmF8}VfGxNJ~KVJUz7CbvY__yW1eAXO+ubwqn00000
LNkvXXu0mjfL+!pp
delta 1813
zcmV+w2kQ93Ade4hiBL{Q4GJ0x0000DNk~Le0001h0001B2m=5B0OF*IdjJ3cKTu3m
zMgM?+ou{wm>+o4-asS3h{oP$GH%BBWIX^~CLR4cpFn}fh|G*C@3eQWSZ+00Q&@BOte+d6KsK!o0Gs{7;Db&9;Ou<@Yxw{mwBbR97ZCgs2Y~R#1S_gYA_1_J6oIFQ
zuV)wGL7cz_k*5xWB$qZvlu5(@UDuNiFrR+A5#4S!0+6|PJw_*Shyk(^A;4YV^>>Yc
zS14i+*Wcgrq5#0klm`=8<;X^_i-f5{)w!@5TjK<;hSaIZ^Hi_(|~M4-UtLtt+y4GME$bj~{G#smO9!%R2_IvpUb
zK`sZXww>Hr7ksdGf&nkcfsR}R5NfblthpR`4ePW|r!ZAKO^HG0f*3>^5Tf{+LoNr3
z0IF7|DFA~G@X~H6p&p>-9G)gme7`;eFpFTGNlR5dW20Z^&*#(eI7R7y~ENf+*mk}%zO#z(x+5^L+2)yA`Tn~*&e*`TA=4@CG68M?^fv42q
zd%`FEBY*ej|LG#$ys0!T_Fr1WzYic=#HacPztUGQQi1IPr1}TDeT7mqz7$Fozwcka
zme=W$x#n}q08E4Os!1M@=pT6hEFTWgp^FmB`$u`1Iv~|Qm;g|naq*)9)YtU1R^Ng0
zJq?iVA9(nde{DG5hUa5xAvD(}IkDw9>=(Nvz)t_b!;8tvVKLn}Hanr6{oi@VY}MoD
z{sDGl*que2a;_Y_Wol7u%`Mk0VB-`@`>$!}fMBB#zWN8)7WVQAZzqOkOUEij*8~vY
z9@JcS)`J%SB~KG;HTMsATRO-q*c8jQ8Swl9fpSd{e}d5)RDwkSPISe;^bY_y_*c}!
zS=$=znji$eJ|&I7%mVOYj%>bvutYi1z-(>)nh>bO1iT)2L!uBEF92zG!>MRk;vZ?S
zR)AkH@+raBfZ)bOfzt`3X6$^B0`pWiEisNX*eJl2gFhp5(YlA@IOqh#0&xF`t9Ug8
zwo7TSe^r3tlmN&`6FBajaQBFmEn7x|G6iIyde#ZZN#~^IQ>$omu4u5n7)pZX6_@~Y
z0&;^FfKQEg=aB}R{sCX-s7L|dKhOvO;04gpLk)udLDfEqN)&hzM~?6XUI5anqd)ob%Rve*mgVYa~8RQh)^@)jyaS*gD5?A3!Ou
zOdslcuP)q(y&
zn=5})4nAGB%M?Ef@NfJZ+wtkgJ?j5Kr|6Re&AA5zers5i@+j{<)+2v-;FsA%-&4gPv#XotK*|Ywa@;%|7TR?EY|Ec~h&c0sp
zN4MwwbFG5hPsM-gL8SpM1NV2jez=?gsHIp!?%xvr{oJ`x#&OW>sEXK*%1N^q`G;>V
z;ngFYAZ!4!|_`B@Ti8GTiS>K=K3gu{>P)PXUO}4ZxNF
zOV9)K{RD6%1im8Jz4m#Z&P(7l08?{opcjbyP@5wFt;t?{-5i4XkKNYDSisF1f1okx
z8d@dD)m+XepThere is already an ID card inside.")
- return // Quit doing shit so we don't hit the timeclock
- . = ..() // Set our return value to that of the parent proc
-
-/// Handle user clicking
-/obj/machinery/computer/timeclock/attack_hand(var/mob/user as mob)
- if (..()) // If for some reason the parent proc returns true
- return // We won't do anything
- user.set_machine(src) // Otherwise, set the mob's machine to us
- ui_interact(user) // Provide a UI to the user
-
-/// Handle UI interactions with this arcane shit known as tee gee yew eye
-/obj/machinery/computer/timeclock/ui_interact(mob/user, datum/tgui/ui)
- ui = SStgui.try_update_ui(user, src, ui) // Attempt to update the UI
- if (!ui) // If the UI doesn't exist
- ui = new(user, src, "TimeClock", name) // Make a new one
- ui.open() // And open it for the user
-
-/// Handle UI data
-/obj/machinery/computer/timeclock/ui_data(mob/user)
- var/list/data = ..() // Call the parent object's data proc and assign that to the data list
-
- // Data for showing user's own PTO
- if (user.client) // If the client exists
- data["department_hours"] = \
- SANITIZE_LIST(user.client.department_hours) // Add the department hours list into data
- data["user_name"] = "[user]" // Set the username to the user
-
- // Data about the card we put into the timeclock
- data["card"] = null // Add card data,
- data["assignment"] = null // Assignment data,
- data["job_datum"] = null // The job datum,
- data["allow_change_job"] = null // Whether or not we can change jobs,
- data["job_choices"] = null // And the possible jobs
- if (card) // If we have a card
- data["card"] = "[card]" // Set card data,
- data["assignment"] = card.assignment // Assignment data,
- var/datum/job/job = \
- SSjob.GetJob(SSjob.get_job_name(card.assignment)) // Create a new job datum,
- if (job) // If the job exists
- data["job_datum"] = list( // Set job datum to a list with
- "title" = job.title, // The job title,
- "departments" = \
- flags_to_english(job.department_flag, job.flag), // The job department,
- "selection_color" = job.selection_color, // The selection color,
- "timeoff_factor" = job.timeoff_factor, // The timeoff factor,
- "pto_department" = job.pto_type // And the PTO type
- )
- if (CONFIG_GET(flag/time_off) \
- && CONFIG_GET(flag/pto_job_change)) // If we allow timeoff and job changing
- data["allow_change_job"] = TRUE // Add that to the data
- if (job && job.timeoff_factor < 0) // They're off duty so we have to lookup available jobs
- data["job_choices"] = \
- get_open_on_duty_jobs(user, job.pto_type) // Set the job choices
-
- return data // Give back the data list for subprocs
-
-/// The user interacted with me? owo!
-/obj/machinery/computer/timeclock/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state)
- if (..()) // Check if the parent UI had anything to say
- return TRUE // If so, we don't care to do anything
-
- add_fingerprint(usr) // Add the user's fingerprint to the list so sec can find them
-
- switch (action) // Check the action completed
- if ("id") // If the ID slot was clicked
- if (card) // Check if we have an ID already
- usr.put_in_hands(card) // If so, give the user the card
- card = null // And make sure we don't have it
- else // Otherwise
- var/obj/item/I = usr.get_active_held_item() // Get the item in their active hand
- if (istype(I, /obj/item/card/id) && usr.canUnEquip(I)) // Check if it's an ID and they can unequip the ID
- I.forceMove(src) // If so, move it into us
- card = I // And make sure we know we have it
- update_icon() // Update our icon too because we did something
- return TRUE // And stop handling any UI in this run
- if ("switch-to-on-duty-rank") // If they switched to on-duty
- if (check_face()) // Check that their face is visible
- if (check_card_cooldown()) // And their card isn't on cooldown
- make_on_duty(params["switch-to-on-duty-rank"], \
- params["switch-to-on-duty-assignment"]) // Finally make them on-duty with the requested rank+assignment
- usr.put_in_hands(card) // Give them their new card
- card = null // And get it out of us
- update_icon() // Update our icon in case the card was removed
- return TRUE // And stop handling UI in this run
- if ("switch-to-off-duty") // If they switched to off-duty
- if (check_face()) // Check that their face is visible
- if (check_card_cooldown()) // And that their card isn't on cooldown
- make_off_duty() // Finally make them off-duty
- usr.put_in_hands(card) // Shit out their ID into their hand
- card = null // And get rid of that card
- update_icon() // Update our icon in case the card was removed
- return TRUE // And stop handling any UI in this run
-
-/// Gets the open on-duty jobs available to a user in a specified department
-/obj/machinery/computer/timeclock/proc/get_open_on_duty_jobs(var/mob/user, var/department)
- var/list/available_jobs = list() // Make a list of available jobs
- for (var/datum/job/job in SSjob.occupations) // For all jobs in existing occupations
- if (is_open_onduty_job(user, department, job)) // Check if the job is open and on-duty for a user and given department
- available_jobs[job.title] = list(job.title) // If it is, add it to the list of available jobs
- if (job.alt_titles) // If the job has alt-titles (Like Station Engineer->Mechanic)
- for (var/alt_job in job.alt_titles) // Go through all the alt titles
- if (alt_job != job.title) // And if it isn't the current job's title (Station Engineer's alt title of Station Engineer)
- available_jobs[job.title] += alt_job // Add it to the list under that job title
- return available_jobs // Return the newly-filled list of available jobs
-
-/// How does xenobio work again? Oh right, we're checking the user's face here to allow access and prevent ne'er-do-wells from using someone's PTO
-/obj/machinery/computer/timeclock/proc/check_face()
- if (!card) // If no card is inserted (why are we checking their face?)
- to_chat(usr, "No ID is inserted.")
- return FALSE // Face check failed
- var/mob/living/carbon/human/H = usr // Get the usr as a human data type
- if (!(istype(H))) // If they somehow aren't a human??
- to_chat(usr, "Invalid user detected. Access denied.")
- return FALSE // Face check failed
- else if ((H.wear_mask && (H.wear_mask.flags_inv & HIDEFACE)) \
- || (H.head && (H.head.flags_inv & HIDEFACE))) // No, you can't hide your face
- to_chat(usr, "Facial recognition scan failed due to physical obstruction. Access denied.")
- return FALSE // Face check failed
- else if (H.get_face_name() == "Unknown" \
- || !(H.real_name == card.registered_name)) // If they're unknown or their real name isn't the name on the ID
- to_chat(usr, "Facial recognition scan failed. Access denied.")
- return FALSE // Face check failed
- else // Otherwise
- return TRUE // Face check success!
-
-/// Force users to wait 10 minutes between clocking in and out
-/obj/machinery/computer/timeclock/proc/check_card_cooldown()
- if (!card) // If we don't have a card
- return FALSE // We can't check cooldown, fail the check
- var/time_left = 10 MINUTES - (world.time - card.last_job_switch) // Determine how much time is left before the next switch
- if (time_left > 0) // If there's any time left at all
- to_chat(usr, "You need to wait another [round((time_left / 10) / 60, 1)] minute\s before you can switch.")
- return FALSE // Fail the check
- return TRUE // Otherwise pass the check
-
-/// Makes the active card on-duty with a set rank and assignment
-/obj/machinery/computer/timeclock/proc/make_on_duty(var/new_rank, var/new_assignment)
- var/datum/job/old_job = \
- SSjob.GetJob(SSjob.get_job_name(card.assignment)) // Get their old job from the card
- var/datum/job/new_job = SSjob.GetJob(new_rank) // And their new job from the rank
-
- if (!old_job \
- || !is_open_onduty_job(usr, old_job.pto_type, new_job)) // If there's no old job or it's not an open and on-duty job
- return // Do nothing
- if (new_assignment != new_job.title \
- && !(new_assignment in new_job.alt_titles)) // If the new assignment isn't the new job's title or alt-title
- return // Do nothing
- if (new_job) // As long as there's a new job
- card.access = new_job.get_access() // Set the card's access to the new job's access
- card.assignment = new_assignment // And the card's assignment to the new assignment
- card.name = text(\
- "[card.registered_name]'s ID Card ([card.assignment])") // And change the card's name
- GLOB.data_core.manifest_modify(card.registered_name, \
- card.assignment) // Apply the changes to the crew manifest
- card.last_job_switch = world.time // Set the last job switch on the card to the current world time
- new_job.current_positions++ // Add one to the current positions for the new job
- var/mob/living/carbon/human/H = usr // Get the caller as a human data type
- H.mind.assigned_role = card.assignment // Set the assigned role of the caller's mind to the assignment on the card
- if (GLOB.announcement_systems.len) // If there are any announcement systems
- var/obj/machinery/announcement_system/announcer = \
- pick(GLOB.announcement_systems) // Pick an announcer, any announcer!
- announcer.announce("ONDUTY", card.registered_name, \
- card.assignment, list()) // Make the announcement for now on-duty personnel
-
-/// Makes the active card off-duty
-/obj/machinery/computer/timeclock/proc/make_off_duty()
- var/datum/job/found_job = \
- SSjob.GetJob(SSjob.get_job_name(card.assignment)) // Get the current job from the inserted card
- if (!found_job) // If the card somehow doesn't have a job
- return // https://www.youtube.com/watch?v=2k0SmqbBIpQ
- var/new_dept = found_job.pto_type || PTO_CIVILIAN // New department is either the department's PTO type or civilian PTO
- var/datum/job/pto_job = null // Create a new PTO job
- for (var/datum/job/job in SSjob.occupations) // For all jobs in the list of occupations
- if (job.pto_type == new_dept \
- && job.timeoff_factor < 0) // If the job is the department's PTO type and has a negative timeoff factor
- pto_job = job // That's the new PTO job
- break // And stop looking
- if (pto_job) // If a PTO job was found
- // Apparently we aren't using this? I don't fucking know
- // var/old_title = card.assignment
- card.access = pto_job.get_access() // Assign the PTO job's access to the ID
- card.assignment = pto_job.title // And the PTO job's title to the ID
- card.name = text(\
- "[card.registered_name]'s ID Card ([card.assignment])") // Set the card's new name
- GLOB.data_core.manifest_modify(card.registered_name, \
- card.assignment) // And apply that change to the crew manifest
- card.last_job_switch = world.time // Set the last job switch on the card to the world's current time
- var/mob/living/carbon/human/H = usr // Get the caller as a human data type
- H.mind.assigned_role = pto_job.title // Set their mind's assigned role to the PTO job's title
- found_job.current_positions-- // Remove one from the found job's position count since they no longer have that job
- if (GLOB.announcement_systems.len) // If there are any announcement systems
- var/obj/machinery/announcement_system/announcer = \
- pick(GLOB.announcement_systems) // Pick an announcement system, any announcement system!
- announcer.announce("OFFDUTY", card.registered_name, \
- card.assignment, list()) // Make an off-duty announcement with that system
- return // I really don't know why this return exists we always return anyways lol
-
-/// Check if a job is open and on-duty for a given user and department
-/obj/machinery/computer/timeclock/proc/is_open_onduty_job(var/mob/user, var/department, var/datum/job/job)
- return job \
- && job.current_positions <= job.total_positions \
- && !jobban_isbanned(user, SSjob.get_job_name(job.title)) \
- && job.player_old_enough(user.client) \
- && job.pto_type == department \
- && job.timeoff_factor > 0 // I feel like this requires some HEAVY explanation so here we go.
- // First we check if the job exists
- // Then we check that there are enough open slots
- // Then we check if the user is jobbanned or not and negate that because it'll return positive if they're banned
- // Then we have to check that they have enough playtime to actually join as that job
- // Then we have to check that the PTO type matches the department requested (can't join security with a PTO type of medical)
- // Then we have to check that there's a timeoff value so you can actually accrue hours of PTO by playing as that role
-
-/// Convert a department and job flag to an english phrase
-/obj/machinery/computer/timeclock/proc/flags_to_english(var/department,var/flag)
- if (department == ENGSEC) // If the department flag is engineering or security (or silicon apparently?)
- switch (flag) // Switch based on the flag
- if (CAPTAIN, HOS, WARDEN, CHIEF) // Captain, Head of Security, Warden or Chief Engineer
- return "Command" // Are all command
- if (DETECTIVE, OFFICER) // Detectives and Officers
- return "Security" // Are all security
- //if (BRIGDOC) // Brig Docs
- //return "Medsec" // Are medical and science
- if (LAMBENT) // Lambent
- return "Lambent" // Are obviously Lambent. Dunno what you expected fam
- if (ENGINEER, ATMOSTECH) // Engineers and Atmos Technicians
- return "Engineering" // Are engineering
- if (ROBOTICIST) // Roboticist is defined here but I think it was supposed to be with medsci? Just in case.
- return "Science" // They're science
- else // Technically this won't always be silicon
- return "Silicon" // But we're listing your ass as silicon anyways. Cope.
- else if (department == MEDSCI) // Otherwise, if the department flag is medical or science
- switch (flag) // Switch based on the flag (again)
- if (RD_JF, CMO_JF) // Research Director or Chief Medical Officer
- return "Command" // Are both command
- if (SCIENTIST, ROBOTICIST) // Scientists and Roboticists (this is where I think this was meant to be but it's still with ENGSEC just in case)
- return "Science" // Are obviously science
- if (CHEMIST, DOCTOR, VIROLOGIST) // Chemists, Doctors, Virologists and Paramedics
- return "Medical" // Are medical
- if (GENETICIST) // Geneticists
- return "Medsci" // Are kind of a special, middle of the road medical and science case
- else // If you're landing here you're fucked
- return "What the fuck?" // So what the fuck?
- else if (department == CIVILIAN) // Otherwise you must be civilian, right? Right???
- switch (flag) // Once again a switch based on the flag
- if (HOP, QUARTERMASTER) // Head of Personnel and Quartermaster
- return "Command" // Are command
- //if (PRISONER) // Prisoners
- //return "Prisoner" // Are... prisoners? They shouldn't be able to PTO but if they manage to break out they can access a console so no fuck you here
- if (CARGOTECH, MINER) // Cargo Technicians and Miners
- return "Cargo" // Are cargonians
- else // Otherwise
- return "Civilian" // You must be a civilian. You could be an assisstant or a clown or a bartender, I don't really care.
- else // New department combo? Wack.
- return "What the fuck?" // what the fuck?
diff --git a/hyperstation/code/game/objects/effects/landmarks.dm b/hyperstation/code/game/objects/effects/landmarks.dm
deleted file mode 100644
index 5ae0945f4..000000000
--- a/hyperstation/code/game/objects/effects/landmarks.dm
+++ /dev/null
@@ -1,11 +0,0 @@
-/obj/effect/landmark/start/lambent
- name = "Lambent"
- icon_state = "Lambent"
-
-/obj/effect/landmark/start/barber
- name = "Barber"
- icon_state = "Barber"
-
-/obj/effect/landmark/start/barista
- name = "Barista"
- icon_state = "Barista"
diff --git a/hyperstation/code/game/objects/items/cards_ids.dm b/hyperstation/code/game/objects/items/cards_ids.dm
deleted file mode 100644
index 8ea19ec93..000000000
--- a/hyperstation/code/game/objects/items/cards_ids.dm
+++ /dev/null
@@ -1,2 +0,0 @@
-/obj/item/card/id
- var/last_job_switch /// Last job switch for card's owner
diff --git a/hyperstation/code/game/objects/items/circuitboards/computer_circuitboards.dm b/hyperstation/code/game/objects/items/circuitboards/computer_circuitboards.dm
deleted file mode 100644
index c1a843992..000000000
--- a/hyperstation/code/game/objects/items/circuitboards/computer_circuitboards.dm
+++ /dev/null
@@ -1,3 +0,0 @@
-/obj/item/circuitboard/computer/timeclock
- name = "Timeclock (Computer Board)"
- build_path = /obj/machinery/computer/timeclock
diff --git a/hyperstation/code/game/objects/items/devices/radio/radio.dm b/hyperstation/code/game/objects/items/devices/radio/radio.dm
new file mode 100644
index 000000000..67ea054ff
--- /dev/null
+++ b/hyperstation/code/game/objects/items/devices/radio/radio.dm
@@ -0,0 +1,2 @@
+/obj/item/radio
+ var/list/extra_channels = list() //Allows indivudal channels, used for borgs
diff --git a/hyperstation/code/game/objects/items/stacks/tiles/tile_types.dm b/hyperstation/code/game/objects/items/stacks/tiles/tile_types.dm
index 1faa2102b..310dea667 100644
--- a/hyperstation/code/game/objects/items/stacks/tiles/tile_types.dm
+++ b/hyperstation/code/game/objects/items/stacks/tiles/tile_types.dm
@@ -1,4 +1,3 @@
-//Farm things
/turf/open/floor/
var/farm_quality = 0 //all tiles have a farm quality, which is for farm animals to enjoy. 0 = worse 100 = best!
@@ -27,11 +26,3 @@
icon_state = "hay"
farm_quality = 100 //the best for farming!
floor_tile = /obj/item/stack/tile/hay
-
-//Carpets
-/obj/item/stack/tile/carpet/kinaris
- name = "gilded carpet"
- icon = 'hyperstation/icons/obj/tiles.dmi'
- icon_state = "tile-carpet-kinaris"
- turf_type = /turf/open/floor/carpet/kinaris
- tableVariant = /obj/structure/table/wood/fancy/kinaris
diff --git a/hyperstation/code/game/objects/railings.dm b/hyperstation/code/game/objects/railings.dm
index 2c01a1721..8140ad908 100644
--- a/hyperstation/code/game/objects/railings.dm
+++ b/hyperstation/code/game/objects/railings.dm
@@ -16,6 +16,7 @@
var/heat_resistance = 800
var/health = 70
var/maxhealth = 70
+ layer = BELOW_MOB_LAYER
resistance_flags = ACID_PROOF
@@ -164,6 +165,14 @@
usr.visible_message("[user] climbed over \the [src]!")
usr.do_twist(targetangle = 45, timer = 8)
+/obj/structure/railing/Initialize(mapload) //mobs will show under the south railing sprite, thanks Cyanosis for helping with the fix
+ . = ..()
+ if(!mapload)
+ return
+ if(!(dir & SOUTH))
+ return
+ layer = ABOVE_MOB_LAYER
+
/obj/structure/railing/handrail
name = "handrail"
desc = "A waist high handrail, perhaps you could climb over it."
diff --git a/hyperstation/code/game/objects/structures/bench.dm b/hyperstation/code/game/objects/structures/bench.dm
index ee0369d75..ba62136ac 100644
--- a/hyperstation/code/game/objects/structures/bench.dm
+++ b/hyperstation/code/game/objects/structures/bench.dm
@@ -9,15 +9,3 @@
icon_state = "bench_left"
/obj/structure/chair/bench/right
icon_state = "bench_right"
-
-/obj/structure/chair/bench/metal
- name = "bench"
- icon_state = "bench_metal_middle"
- icon = 'hyperstation/icons/obj/bench.dmi'
- buildstackamount = 1
- buildstacktype = /obj/item/stack/sheet/metal
-
-/obj/structure/chair/bench/metal/left
- icon_state = "bench_metal_left"
-/obj/structure/chair/bench/metal/right
- icon_state = "bench_metal_right"
\ No newline at end of file
diff --git a/hyperstation/code/game/objects/structures/ghost_role_spawners.dm b/hyperstation/code/game/objects/structures/ghost_role_spawners.dm
index 1c814b77b..c25c5f9be 100644
--- a/hyperstation/code/game/objects/structures/ghost_role_spawners.dm
+++ b/hyperstation/code/game/objects/structures/ghost_role_spawners.dm
@@ -165,35 +165,3 @@
/obj/effect/mob_spawn/human/villager/special(mob/living/carbon/human/new_spawn)
ADD_TRAIT(new_spawn,TRAIT_EXEMPT_HEALTH_EVENTS,GHOSTROLE_TRAIT)
-
-
-//Prisoner
-/obj/effect/mob_spawn/human/prisoner
- name = "prisoner transfer cryoteleporter"
- mob_name = "prisoner transfer"
- icon = 'icons/obj/machines/sleeper.dmi'
- icon_state = "sleeper"
- job_description = "Prisoner Transfer"
- outfit = /datum/outfit/prisoner
- id_job = "Prisoner Transfer"
- assignedrole = "Prisoner Transfer"
- short_desc = "You are a transferred prisoner to Layenia. Don't break out or otherwise act like an antag."
- flavour_text = "For one reason or another, you are a prisoner. Kinaris has chosen to temporarily hold you within Layenia Station's holding area, \
- until the end of the shift. You do not permanently reside here, but you may end up in this place from shift to shift. It is highly recommended to \
- make a unique character slot for this role. Kinaris would not neuter or otherwise remove identifying features that make you who you are; such as \
- altering your name, features, or physical appearance. As a prisoner, you still uphold a decent amount of rights."
- important_info = "Do NOT attempt to break out, antagonize, or otherwise treat your role as anything to grief with. Should you find a scenario where you want to, AHELP."
- objectives = "Do NOT attempt to break out or act like an antag. Serve your time until end of shift."
- mirrorcanloadappearance = TRUE
- roundstart = FALSE
- death = FALSE
-
-/datum/outfit/prisoner
- name = "Prisoner"
- uniform = /obj/item/clothing/under/rank/prisoner
- shoes = /obj/item/clothing/shoes/sneakers/orange
- id = /obj/item/card/id/prisoner
- implants = list(/obj/item/implant/exile, /obj/item/implant/tracking)
-
-/obj/effect/mob_spawn/human/prisoner/special(mob/living/carbon/human/new_spawn)
- ADD_TRAIT(new_spawn,TRAIT_EXEMPT_HEALTH_EVENTS,GHOSTROLE_TRAIT)
diff --git a/hyperstation/code/game/objects/structures/tables_racks.dm b/hyperstation/code/game/objects/structures/tables_racks.dm
deleted file mode 100644
index 2fa8eadf4..000000000
--- a/hyperstation/code/game/objects/structures/tables_racks.dm
+++ /dev/null
@@ -1,9 +0,0 @@
-/obj/structure/table/wood/fancy/kinaris
- icon = 'hyperstation/icons/obj/structures.dmi'
- icon_state = "fancy_table_kinaris"
- buildstack = /obj/item/stack/tile/carpet/kinaris
- canSmoothWith = list(/obj/structure/table/wood/fancy/kinaris)
-
-/obj/structure/table/wood/fancy/kinaris/New()
- . = ..()
- icon = 'hyperstation/icons/obj/smooth_structures/fancy_table_kinaris.dmi'
diff --git a/hyperstation/code/game/turfs/open.dm b/hyperstation/code/game/turfs/open.dm
deleted file mode 100644
index 3553557f7..000000000
--- a/hyperstation/code/game/turfs/open.dm
+++ /dev/null
@@ -1,14 +0,0 @@
-/turf/open/indestructible/layenia/sand
- name = "\improper crimson sand"
- desc = "A reddish sand."
- icon = 'hyperstation/icons/turf/floors/layeniasand.dmi'
- icon_state = "mapping"
- baseturfs = /turf/open/indestructible/layenia/crystal
- slowdown = 1
- barefootstep = FOOTSTEP_SAND
- clawfootstep = FOOTSTEP_SAND
- heavyfootstep = FOOTSTEP_GENERIC_HEAVY
- initial_gas_mix = FROZEN_ATMOS
- planetary_atmos = TRUE
- smooth = SMOOTH_TRUE | SMOOTH_BORDER | SMOOTH_MORE
- canSmoothWith = list(/turf/open/indestructible/layenia/sand)
diff --git a/hyperstation/code/game/turfs/simulated/floor/fancy_floor.dm b/hyperstation/code/game/turfs/simulated/floor/fancy_floor.dm
deleted file mode 100644
index 2cc8f61fc..000000000
--- a/hyperstation/code/game/turfs/simulated/floor/fancy_floor.dm
+++ /dev/null
@@ -1,4 +0,0 @@
-/turf/open/floor/carpet/kinaris
- icon = 'hyperstation/icons/turf/floors/carpet_kinaris.dmi'
- floor_tile = /obj/item/stack/tile/carpet/kinaris
- canSmoothWith = list(/turf/open/floor/carpet/kinaris)
diff --git a/hyperstation/code/game/turfs/simulated/wall/mineral_walls.dm b/hyperstation/code/game/turfs/simulated/wall/mineral_walls.dm
deleted file mode 100644
index 34e2604ba..000000000
--- a/hyperstation/code/game/turfs/simulated/wall/mineral_walls.dm
+++ /dev/null
@@ -1,78 +0,0 @@
-/turf/closed/wall/mineral/titanium/custom //For spicy custom shuttles
- name = "whoops!"
- desc = "Scream at Dahl please!"
- icon = 'hyperstation/icons/turf/walls/customshuttles.dmi'
- icon_state = "amogus"
- explosion_block = 10
- smooth = SMOOTH_FALSE
- canSmoothWith = null
-
-/turf/closed/wall/mineral/titanium/custom/window
- opacity = FALSE
-
-/turf/closed/wall/mineral/titanium/custom/AfterChange(flags, oldType)
- . = ..()
- // Manually add space underlay, in a way similar to turf_z_transparency,
- // but we actually show the old content of the same z-level, as desired for shuttles
-
- var/turf/underturf_path
-
- // Grab previous turf icon
- if(!ispath(oldType, /turf/closed/wall/mineral/titanium/custom))
- underturf_path = oldType
- else
- // Else use whatever SSmapping tells us, like transparent open tiles do
- underturf_path = SSmapping.level_trait(z, ZTRAIT_BASETURF) || /turf/open/space
-
- var/mutable_appearance/underlay_appearance = mutable_appearance(
- initial(underturf_path.icon),
- initial(underturf_path.icon_state),
- layer = TURF_LAYER - 0.02, plane = initial(underturf_path.plane))
- underlay_appearance.appearance_flags = RESET_ALPHA | RESET_COLOR
- underlays += underlay_appearance
-
-/turf/closed/wall/mineral/titanium/custom/ferry
- name = "\improper ferry wall"
- desc = "A low tech hull for Layenia flight."
- icon_state = "ferry"
-
-/turf/closed/wall/mineral/titanium/custom/window/ferry
- name = "\improper ferry wall"
- desc = "A low tech hull for Layenia flight."
- icon_state = "ferry"
-
-/turf/closed/wall/mineral/titanium/custom/arrivals
- name = "\improper shuttle wall"
- desc = "A low tech hull for Layenia and space-flight"
- icon = 'hyperstation/icons/turf/walls/customarrivals.dmi'
- icon_state = "amogus"
-
-/turf/closed/wall/mineral/titanium/custom/window/arrivals
- name = "\improper shuttle wall"
- desc = "A low tech hull for Layenia and space-flight"
- icon = 'hyperstation/icons/turf/walls/customarrivals.dmi'
- icon_state = "amogus"
-
-/turf/closed/wall/mineral/titanium/custom/pod
- name = "\improper pod wall"
- desc = "A low tech hull for Layenia and space-flight"
- icon = 'hyperstation/icons/turf/walls/custompod.dmi'
- icon_state = "amogus"
-
-/turf/closed/wall/mineral/titanium/custom/window/pod
- name = "\improper pod wall"
- desc = "A low tech hull for Layenia and space-flight"
- icon = 'hyperstation/icons/turf/walls/custompod.dmi'
- icon_state = "amogus"
-
-/turf/closed/wall/mineral/titanium/custom/departures
- name = "\improper pod wall"
- desc = "A low tech hull for Layenia and space-flight"
- icon = 'hyperstation/icons/turf/walls/customdepartures.dmi'
- icon_state = "amogus"
-
-/turf/closed/wall/mineral/titanium/custom/window/departures
- name = "\improper pod wall"
- desc = "A low tech hull for Layenia and space-flight"
- icon = 'hyperstation/icons/turf/walls/customdepartures.dmi'
- icon_state = "amogus"
diff --git a/hyperstation/code/modules/arousal/arousalhud.dm b/hyperstation/code/modules/arousal/arousalhud.dm
index 509438813..318edefd0 100644
--- a/hyperstation/code/modules/arousal/arousalhud.dm
+++ b/hyperstation/code/modules/arousal/arousalhud.dm
@@ -11,7 +11,15 @@
for(var/obj/item/organ/genital/G in U.internal_organs)
if(!G.nochange)
if(!G.dontlist)
- dat += "[G.mode == "hidden" ? "[G.name] (Hidden)" : (G.mode == "clothes" ? "[G.name] (Hidden by Clothes)" : (G.mode == "visable" ? "[G.name] (Visable)" : "[G.name] (Visable)"))]
"
+ var/genital_visibility = "[G.name] (Visible)"
+ switch(G.mode)
+ if(GENITALS_HIDDEN)
+ genital_visibility = "[G.name] (Hidden)"
+ if(GENITALS_CLOTHES)
+ genital_visibility = "[G.name] (Hidden by Clothes)"
+ if(GENITALS_VISIBLE)
+ genital_visibility = "[G.name] (Visible)"
+ dat += "[genital_visibility]
"
dat += {"
Contexual Options
"}
var/obj/item/organ/genital/penis/P = user.getorganslot("penis")
@@ -45,20 +53,17 @@
if(Belly.inflatable)
dat += "Deflate belly"
dat += "(Shrink your belly down a size)
"
-
-
- if(user.pulling)
+
+ if(user.pulling && !isnoncarbon(user.pulling)) // do not fuck animals
dat += "Climax over [user.pulling]" //you can cum on objects if you really want...
dat += "(Orgasm over a person or object.)
"
- if(isliving(user.pulling))
- if(iscarbon(user.pulling))
- dat += "Climax with [user.pulling]"
- dat += {"(Orgasm with another person.)
"}
-
- var/mob/living/carbon/human/H = user.pulling
- if(H.breedable && P && H)
- dat += "Impregnate [U.pulling] ([clamp(U.impregchance,0,100)]%)"
- dat += "(Climax inside another person, and attempt to knock them up.)
"
+ if(iscarbon(user.pulling))
+ dat += "Climax with [user.pulling]"
+ dat += {"(Orgasm with another person.)
"}
+ var/mob/living/carbon/human/H = user.pulling
+ if(H && H.breedable && P)
+ dat += "Impregnate [U.pulling] ([clamp(U.impregchance,0,100)]%)"
+ dat += "(Climax inside another person, and attempt to knock them up.)
"
else
dat += "Climax over"
dat += "(Requires a partner)
"
@@ -81,11 +86,9 @@
dat += "Old Menu"
dat += "Toggle Undergarments "
dat += "
"
-
var/datum/browser/popup = new(user, "arousal", "Arousal Panel")
popup.set_content(dat)
popup.set_title_image(user.browse_rsc_icon(icon, icon_state), 500,600)
-
popup.open()
@@ -140,7 +143,7 @@
T.toggle_visibility(picked_visibility)
if(href_list["masturbate"])
- if (H.arousalloss >= (H.max_arousal / 100) * 33) //requires 33% arousal.
+ if (H.isPercentAroused(33)) //requires 33% arousal.
H.solomasturbate()
return
else
@@ -148,7 +151,7 @@
return
if(href_list["container"])
- if (H.arousalloss >= (H.max_arousal / 100) * 33) //requires 33% arousal.
+ if (H.isPercentAroused(33)) //requires 33% arousal.
H.cumcontainer()
return
else
@@ -156,7 +159,7 @@
return
if(href_list["clothesplosion"])
- if (H.arousalloss >= (H.max_arousal / 100) * 33) //Requires 33% arousal.
+ if (H.isPercentAroused(33)) //Requires 33% arousal.
H.clothesplosion()
return
else
@@ -164,7 +167,7 @@
return
if(href_list["climaxself"])
- if (H.arousalloss >= (H.max_arousal / 100) * 33) //requires 33% arousal.
+ if (H.isPercentAroused(33)) //requires 33% arousal.
H.climaxself()
return
else
@@ -172,7 +175,7 @@
return
if(href_list["climax"])
- if (H.arousalloss >= (H.max_arousal / 100) * 33) //requires 33% arousal.
+ if (H.isPercentAroused(33)) //requires 33% arousal.
H.climaxalone(FALSE)
return
else
@@ -180,7 +183,7 @@
return
if(href_list["climaxover"])
- if (H.arousalloss >= (H.max_arousal / 100) * 33) //requires 33% arousal.
+ if (H.isPercentAroused(33)) //requires 33% arousal.
H.climaxover(usr.pulling)
return
else
@@ -188,7 +191,7 @@
return
if(href_list["climaxwith"])
- if (H.arousalloss >= (H.max_arousal / 100) * 33) //requires 33% arousal.
+ if (H.isPercentAroused(33)) //requires 33% arousal.
H.climaxwith(usr.pulling)
return
else
@@ -196,7 +199,7 @@
return
if(href_list["impreg"])
- if (H.arousalloss >= (H.max_arousal / 100) * 33) //requires 33% arousal.
+ if (H.isPercentAroused(33)) //requires 33% arousal.
H.impregwith(usr.pulling)
return
else
@@ -331,7 +334,7 @@ obj/screen/arousal/proc/kiss()
return
//We got hands, let's pick an organ
var/obj/item/organ/genital/picked_organ
- picked_organ = pick_masturbate_genitals()
+ picked_organ = pick_climax_genitals(masturbation=TRUE, title="Masturbation")
if(picked_organ)
src << browse(null, "window=arousal") //closes the window
mob_masturbate(picked_organ)
@@ -365,55 +368,31 @@ obj/screen/arousal/proc/kiss()
to_chat(src, "You cannot climax without choosing genitals.")
return
-/mob/living/carbon/human/proc/climaxwith(mob/living/T)
-
- var/mob/living/carbon/human/L = pick_partner()
+/mob/living/carbon/human/proc/climaxwith(mob/living/carbon/human/partner)
+ if(!partner)
+ to_chat(src, "You cannot do this alone.")
+ return
var/obj/item/organ/genital/picked_organ
picked_organ = pick_climax_genitals()
- if(picked_organ)
- var/mob/living/partner = L
- if(partner)
- src << browse(null, "window=arousal") //alls fine, we can close the window now.
- var/obj/item/organ/genital/penis/P = picked_organ
- var/spillage = "No" //default to no, just incase player has items on to prevent climax
- if(!P.condom == 1&&!P.sounding == 1) //you cant climax with a condom on or sounding in.
- spillage = input(src, "Would your fluids spill outside?", "Choose overflowing option", "Yes") as anything in list("Yes", "No")
- if(spillage == "Yes")
- mob_climax_partner(picked_organ, partner, TRUE, FALSE, FALSE)
- else
- mob_climax_partner(picked_organ, partner, FALSE, FALSE, FALSE)
- else
- to_chat(src, "You cannot do this alone.")
- return
- else //They either lack organs that can masturbate, or they didn't pick one.
+ if(!picked_organ)
to_chat(src, "You cannot climax without choosing genitals.")
return
+ src << browse(null, "window=arousal") // close arousal window
+ mob_climax_inside_spillage(picked_organ, partner, impreg=FALSE)
-
-/mob/living/carbon/human/proc/climaxover(mob/living/T)
-
- var/mob/living/carbon/human/L = T
+/mob/living/carbon/human/proc/climaxover(atom/partner)
var/obj/item/organ/genital/picked_organ
picked_organ = pick_climax_genitals()
- if(picked_organ)
- src << browse(null, "window=arousal") //alls fine, we can close the window now.
- var/mob/living/partner = L
- if(partner)
- var/obj/item/organ/genital/penis/P = picked_organ
- if(P.condom == 1)
- to_chat(src, "You cannot do this action with a condom on.")
- return
- if(P.sounding == 1)
- to_chat(src, "You cannot do this action with a sounding in.")
- return
- mob_climax_partner(picked_organ, partner, FALSE, FALSE, TRUE)
- else
- to_chat(src, "You cannot do this alone.")
- return
- else //They either lack organs that can masturbate, or they didn't pick one.
+ if(!picked_organ)
to_chat(src, "You cannot climax without choosing genitals.")
return
+ src << browse(null, "window=arousal") //alls fine, we can close the window now.
+ if(!partner || isnoncarbon(partner))
+ to_chat(src, "You cannot do this alone.")
+ return
+ mob_climax_cover(picked_organ, partner)
+
/mob/living/carbon/human/proc/clothesplosion()
if(usr.restrained(TRUE))
@@ -428,39 +407,29 @@ obj/screen/arousal/proc/kiss()
H.visible_message("[H] explodes out of their clothes!'")
-
-/mob/living/carbon/human/proc/impregwith(mob/living/T)
-
- var/mob/living/carbon/human/L = pick_partner()
- var/obj/item/organ/genital/picked_organ
- picked_organ = src.getorganslot("penis") //Impregnation must be done with a penis.
- if(picked_organ)
- var/mob/living/partner = L
- if(partner)
- if(!partner.breedable)//check if impregable.
- to_chat(src, "Your partner cannot be impregnated.")//some fuckary happening, you shouldnt even get to this point tbh.
- return
- var/obj/item/organ/genital/penis/P = picked_organ
- //you cant impreg with a condom on or sounding in.
- if(P.condom == 1)
- to_chat(src, "You cannot do this action with a condom on.")
- return
- if(P.sounding == 1)
- to_chat(src, "You cannot do this action with a sounding in.")
- return
- src << browse(null, "window=arousal") //alls fine, we can close the window now.
- //Keeping this for messy fun
- var/spillage = input(src, "Would your fluids spill outside?", "Choose overflowing option", "Yes") as anything in list("Yes", "No")
- if(spillage == "Yes")
- mob_climax_partner(picked_organ, partner, TRUE, TRUE, FALSE)
- else
- mob_climax_partner(picked_organ, partner, FALSE, TRUE, FALSE)
- else
- to_chat(src, "You cannot do this alone.")
- return
- else //no penis :(
- to_chat(src, "You cannot impregnate without a penis.")
+/mob/living/carbon/human/proc/impregwith(mob/living/carbon/T)
+ var/mob/living/carbon/human/partner = pick_partner()
+ var/obj/item/organ/genital/penis/picked_organ = src.getorganslot("penis")
+ // wow that is a lot of conditionals huh
+ if(!picked_organ) // no penis :(
+ to_chat(src, "You cannot impregnate someone without a penis.")
return
+ if(!partner)
+ to_chat(src, "You cannot do this alone.")
+ return
+ if(!partner.breedable) //check if impregable.
+ to_chat(src, "Your partner cannot be impregnated.")
+ //some fuckery happening, you shouldnt even get to this point tbh.
+ return
+ if(picked_organ.condom)
+ to_chat(src, "You cannot impregnate someone with a condom on.")
+ return
+ if(picked_organ.sounding)
+ to_chat(src, "You cannot impregnate someone with a sounding rod in.")
+ return
+ src << browse(null, "window=arousal") //alls fine, we can close the window now.
+ mob_climax_inside_spillage(picked_organ, partner, impreg=TRUE)
+
/mob/living/carbon/human/proc/cumcontainer(mob/living/T)
//We'll need hands and no restraints.
@@ -500,6 +469,11 @@ obj/screen/arousal/proc/kiss()
cum_splatter_icon.Blend(icon('hyperstation/icons/effects/cumoverlay.dmi', "cum_obj"), ICON_MULTIPLY)
add_overlay(cum_splatter_icon)
+/mob/living/carbon/add_cum_overlay(type="normal")
+ var/mutable_appearance/cumoverlay = mutable_appearance('hyperstation/icons/effects/cumoverlay.dmi')
+ cumoverlay.icon_state = "cum_[type]"
+ add_overlay(cumoverlay)
+
/atom/proc/wash_cum()
cut_overlay(mutable_appearance('hyperstation/icons/effects/cumoverlay.dmi', "cum_normal"))
cut_overlay(mutable_appearance('hyperstation/icons/effects/cumoverlay.dmi', "cum_large"))
@@ -523,7 +497,7 @@ obj/screen/arousal/proc/kiss()
return
//We got hands, let's pick an organ
var/obj/item/organ/genital/picked_organ
- picked_organ = pick_masturbate_genitals()
+ picked_organ = pick_climax_genitals(masturbation=TRUE, title="Masturbation")
if(picked_organ)
src << browse(null, "window=arousal") //closes the window
mob_masturbate(picked_organ, cover = TRUE)
diff --git a/hyperstation/code/modules/arousal/organs/genitals.dm b/hyperstation/code/modules/arousal/organs/genitals.dm
new file mode 100644
index 000000000..9da552021
--- /dev/null
+++ b/hyperstation/code/modules/arousal/organs/genitals.dm
@@ -0,0 +1,6 @@
+/obj/item/organ/genital/proc/get_fluid_source()
+ if(producing)
+ return src.reagents
+ if(linked_organ && linked_organ.producing)
+ return linked_organ.reagents
+ return null
\ No newline at end of file
diff --git a/hyperstation/code/modules/cargo/packs/misc.dm b/hyperstation/code/modules/cargo/packs/misc.dm
index d1b88903f..21eb315b2 100644
--- a/hyperstation/code/modules/cargo/packs/misc.dm
+++ b/hyperstation/code/modules/cargo/packs/misc.dm
@@ -5,3 +5,31 @@
contains = list(/obj/item/polepack/,
/obj/item/wrench/)
crate_name = "stripper pole crate"
+
+/datum/supply_pack/organic/donkpockets
+ name = "Donkpocket Shipment"
+ desc = "We at Donk corp provide a wide five selection of holovid ready dinner pockets for all your dietary needs from extra-cheese to vegan to even mothpeople. Product of Donk co."
+ cost = 1500
+ contains = list()
+ crate_name = "Donk Crate"
+ crate_type = /obj/structure/closet/crate/freezer
+ var/num_contained = 5
+ //Put the types you want to contain inside this list below.
+ var/can_contain = list( /obj/item/storage/box/donkpockets,
+ /obj/item/storage/box/donkpockets/donkpockettaco,
+ /obj/item/storage/box/donkpockets/donkpocketplasma,
+ /obj/item/storage/box/donkpockets/donkpocketbreakfast,
+ /obj/item/storage/box/donkpockets/donkpocketmoth,
+ /obj/item/storage/box/donkpockets/donkpocketvegan,
+ /obj/item/storage/box/donkpockets/donkpocketspicy,
+ /obj/item/storage/box/donkpockets/donkpocketteriyaki,
+ /obj/item/storage/box/donkpockets/donkpocketpizza,
+ /obj/item/storage/box/donkpockets/donkpocketberry,
+ /obj/item/storage/box/donkpockets/donkpockethonk
+ )
+
+/datum/supply_pack/organic/donkpockets/fill(obj/structure/closet/crate/C)
+ contains = list()
+ for(var/i = 0; i < num_contained; i++)
+ contains += pick(can_contain)
+ . = ..()
\ No newline at end of file
diff --git a/hyperstation/code/modules/client/client_defines.dm b/hyperstation/code/modules/client/client_defines.dm
deleted file mode 100644
index 705945fac..000000000
--- a/hyperstation/code/modules/client/client_defines.dm
+++ /dev/null
@@ -1,9 +0,0 @@
-/**
- * Additional client defines. I needed somewhere to put these so here it is!
- */
-/client
- //////////////////////////////////////
- // Things that require the database //
- //////////////////////////////////////
- var/list/department_hours = list() // Track hours of leave accrued for each department
- var/list/play_hours = list() // Tracks total playtime hours for each department
diff --git a/hyperstation/code/modules/client/hyper_pref_savefile.dm b/hyperstation/code/modules/client/hyper_pref_savefile.dm
new file mode 100644
index 000000000..a0a71216b
--- /dev/null
+++ b/hyperstation/code/modules/client/hyper_pref_savefile.dm
@@ -0,0 +1,36 @@
+/datum/preferences/proc/hyper_character_pref_load(savefile/S)
+ S["feature_cosmetic_head"] >> features["cosmetic_head"]
+ S["feature_cosmetic_chest"] >> features["cosmetic_chest"]
+ S["feature_cosmetic_l_arm"] >> features["cosmetic_l_arm"]
+ S["feature_cosmetic_r_arm"] >> features["cosmetic_r_arm"]
+ S["feature_cosmetic_l_leg"] >> features["cosmetic_l_leg"]
+ S["feature_cosmetic_r_leg"] >> features["cosmetic_r_leg"]
+ S["cosmetic_markings"] >> features["cosmetic_markings"]
+ var/cosmetic_head = sanitize_inlist(features["cosmetic_head"], GLOB.cosmetic_heads, "default")
+ var/cosmetic_chest = sanitize_inlist(features["cosmetic_chest"], GLOB.cosmetic_chests, "default")
+ var/cosmetic_l_arm = sanitize_inlist(features["cosmetic_l_arm"], GLOB.cosmetic_arms, "default")
+ var/cosmetic_r_arm = sanitize_inlist(features["cosmetic_r_arm"], GLOB.cosmetic_arms, "default")
+ var/cosmetic_l_leg = sanitize_inlist(features["cosmetic_l_leg"], GLOB.cosmetic_legs, "default")
+ var/cosmetic_r_leg = sanitize_inlist(features["cosmetic_r_leg"], GLOB.cosmetic_legs, "default")
+ features["cosmetic_head"] = GLOB.cosmetic_heads[cosmetic_head]
+ features["cosmetic_chest"] = GLOB.cosmetic_chests[cosmetic_chest]
+ features["cosmetic_l_arm"] = GLOB.cosmetic_arms[cosmetic_l_arm]
+ features["cosmetic_r_arm"] = GLOB.cosmetic_arms[cosmetic_r_arm]
+ features["cosmetic_l_leg"] = GLOB.cosmetic_legs[cosmetic_l_leg]
+ features["cosmetic_r_leg"] = GLOB.cosmetic_legs[cosmetic_r_leg]
+
+
+/datum/preferences/proc/hyper_character_pref_save(savefile/S)
+ var/datum/cosmetic_part/head = features["cosmetic_head"]
+ var/datum/cosmetic_part/chest = features["cosmetic_chest"]
+ var/datum/cosmetic_part/l_arm = features["cosmetic_l_arm"]
+ var/datum/cosmetic_part/r_arm = features["cosmetic_r_arm"]
+ var/datum/cosmetic_part/l_leg = features["cosmetic_l_leg"]
+ var/datum/cosmetic_part/r_leg = features["cosmetic_r_leg"]
+ WRITE_FILE(S["feature_cosmetic_head"], head.id)
+ WRITE_FILE(S["feature_cosmetic_chest"], chest.id)
+ WRITE_FILE(S["feature_cosmetic_l_arm"], l_arm.id)
+ WRITE_FILE(S["feature_cosmetic_r_arm"], r_arm.id)
+ WRITE_FILE(S["feature_cosmetic_l_leg"], l_leg.id)
+ WRITE_FILE(S["feature_cosmetic_r_leg"], r_leg.id)
+ WRITE_FILE(S["cosmetic_markings"], features["cosmetic_markings"])
\ No newline at end of file
diff --git a/hyperstation/code/modules/clothing/gloves.dm b/hyperstation/code/modules/clothing/gloves.dm
index 107126506..c3ecb21fe 100644
--- a/hyperstation/code/modules/clothing/gloves.dm
+++ b/hyperstation/code/modules/clothing/gloves.dm
@@ -10,4 +10,4 @@
strip_delay = 40
equip_delay_other = 20
cold_protection = HANDS
- min_cold_protection_temperature = GLOVES_MIN_TEMP_PROTECT
+ min_cold_protection_temperature = GLOVES_MIN_TEMP_PROTECT
\ No newline at end of file
diff --git a/hyperstation/code/modules/clothing/suits/misc.dm b/hyperstation/code/modules/clothing/suits/misc.dm
index 31ef1643f..0793aaa26 100644
--- a/hyperstation/code/modules/clothing/suits/misc.dm
+++ b/hyperstation/code/modules/clothing/suits/misc.dm
@@ -21,4 +21,43 @@
name = "\improper Hellraider's Vest"
desc = "An open leather vest with battlescarred metal shoulderpads, discovered in a dimensional anomaly. Smells of gunpowder and plasma."
icon_state = "guncaster_alt"
- item_state = "guncaster_alt"
\ No newline at end of file
+ item_state = "guncaster_alt"
+
+/*
+ * Posshim's Corpus atire
+ */
+ //Making this a subset of wintercoats/winterhoods since poss intends it to have wintercoat stats --Archie
+
+/obj/item/clothing/suit/hooded/wintercoat/corpus
+ name = "Standard Voidsuit"
+ desc = "Standard issue voidsuit in the name of Grofit!"
+ icon_state = "corpus"
+ item_state = "armor"
+ body_parts_covered = CHEST|GROIN|LEGS|ARMS|FEET|HANDS
+ hoodtype = /obj/item/clothing/head/hooded/winterhood/corpus
+ flags_inv = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT //"Hide shoes" but digi shoes dont get hidden, too bad!
+ mutantrace_variation = NO_MUTANTRACE_VARIATION //There is no need for a digi variant, it's a costume
+
+/obj/item/clothing/suit/hooded/wintercoat/corpus/sec
+ name = "Enforcer Voidsuit"
+ desc = "Delux issue grofit voidsuit. Let the middle class know You're in charge."
+ icon_state = "corpuss"
+ hoodtype = /obj/item/clothing/head/hooded/winterhood/corpus/sec //Enjoy this nice red outfit Kinaris! There is NO NEED for a pink one! xoxo -VivI Fanteriso
+
+/obj/item/clothing/suit/hooded/wintercoat/corpus/command
+ name = "Commander Voidsuit"
+ desc = "Premium issue correctional worker attire. Grease the gears of production."
+ icon_state = "corpusc"
+ hoodtype = /obj/item/clothing/head/hooded/winterhood/corpus/command
+
+/obj/item/clothing/head/hooded/winterhood/corpus
+ name = "Voidsuit helmet"
+ desc = "galvanized reinforced helm to protect against the elements"
+ icon_state = "corpus"
+ flags_inv = HIDEHAIR|HIDEEARS|HIDEFACIALHAIR|HIDEFACE|HIDEMASK|HIDESNOUT|HIDENECK //hide your ugly face with this one simple trick!
+
+/obj/item/clothing/head/hooded/winterhood/corpus/sec
+ icon_state = "corpuss"
+
+/obj/item/clothing/head/hooded/winterhood/corpus/command
+ icon_state = "corpusc"
\ No newline at end of file
diff --git a/hyperstation/code/modules/jobs/job_types/_job.dm b/hyperstation/code/modules/jobs/job_types/_job.dm
deleted file mode 100644
index 9051523de..000000000
--- a/hyperstation/code/modules/jobs/job_types/_job.dm
+++ /dev/null
@@ -1,3 +0,0 @@
-/datum/job
- var/timeoff_factor = 3
- var/pto_type
diff --git a/hyperstation/code/modules/jobs/job_types/civilian.dm b/hyperstation/code/modules/jobs/job_types/civilian.dm
deleted file mode 100644
index 9ed93fdb2..000000000
--- a/hyperstation/code/modules/jobs/job_types/civilian.dm
+++ /dev/null
@@ -1,52 +0,0 @@
-/datum/job/barista
- title = "Barista"
- flag = BARISTA
- department_head = list("Head of Personnel")
- department_flag = CIVILIAN
- faction = "Station"
- total_positions = 1
- spawn_positions = 1
- supervisors = "the head of personnel"
- selection_color = "#bbe291"
-
- outfit = /datum/outfit/job/barista
-
- access = list(ACCESS_HYDROPONICS, ACCESS_BARISTA, ACCESS_KITCHEN, ACCESS_MINERAL_STOREROOM)
- minimal_access = list(ACCESS_BARISTA, ACCESS_MINERAL_STOREROOM)
-
-/datum/outfit/job/barista
- name = "Barista"
- jobtype = /datum/job/barista
-
- belt = /obj/item/pda/bar
- ears = /obj/item/radio/headset/headset_srv
- uniform = /obj/item/clothing/under/lawyer/blacksuit
- suit = /obj/item/clothing/suit/toggle/lawyer/black
- backpack_contents = list(/obj/item/book/granter/action/drink_fling=1, /obj/item/clothing/accessory/waistcoat)
- shoes = /obj/item/clothing/shoes/laceup
-
-/datum/job/barber
- title = "Barber"
- flag = BARBER
- department_head = list("Head of Personnel")
- department_flag = CIVILIAN
- faction = "Station"
- total_positions = 2
- spawn_positions = 1
- supervisors = "the head of personnel"
- selection_color = "#bbe291"
-
- outfit = /datum/outfit/job/barber
-
- access = list(ACCESS_BARBER)
- minimal_access = list(ACCESS_BARBER)
-
-/datum/outfit/job/barber
- name = "Barber"
- jobtype = /datum/job/barber
-
- glasses = /obj/item/clothing/glasses/sunglasses
- ears = /obj/item/radio/headset/headset_srv
- belt = /obj/item/pda
- uniform = /obj/item/clothing/under/barber
- shoes = /obj/item/clothing/shoes/laceup
diff --git a/hyperstation/code/modules/jobs/job_types/job_alt_titles.dm b/hyperstation/code/modules/jobs/job_types/job_alt_titles.dm
deleted file mode 100644
index 0f20b5e46..000000000
--- a/hyperstation/code/modules/jobs/job_types/job_alt_titles.dm
+++ /dev/null
@@ -1,8 +0,0 @@
-/datum/job/lambent
- alt_titles = list("Kinaris Protectorate", "Hardshield", "Asset Specialist", "Luminal")
-
-/datum/job/barber
- alt_titles = list("Cosmetologist", "Beautician", "Hairdresser", "Hair Stylist")
-
-/datum/job/barista
- alt_titles = list("Cafe Attendant", "Cafe Server")
diff --git a/hyperstation/code/modules/jobs/job_types/security.dm b/hyperstation/code/modules/jobs/job_types/security.dm
deleted file mode 100644
index 0360b5423..000000000
--- a/hyperstation/code/modules/jobs/job_types/security.dm
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
-Lambent
-*/
-/datum/job/lambent
- title = "Lambent"
- flag = LAMBENT
- department_head = list("CentCom")
- department_flag = ENGSEC
- faction = "Station"
- total_positions = 1
- spawn_positions = 1
- supervisors = "Central Command and Kinaris officials"
- selection_color = "#ffedcc"
- req_admin_notify = 1
- minimal_player_age = 30
- exp_requirements = 9000
- exp_type = EXP_TYPE_COMMAND
- exp_type_department = EXP_TYPE_COMMAND
- whitelist_type = "important"
- custom_spawn_text = "You are a Kinaris Lambent; a person hired directly by Kinaris who has a high interest in asset security and the protection of the station. Unlike the station, your gear is official Kinaris items, not replicated Milky-Way Engrams. As such, you should keep them safe due to the power they hold. You answer directly to Central Command and Kinaris, and security matters should not involve you for the most part, unless staffing is low or there is a problem with securing assets. Thankfully, Layenia Station is one of Kinaris's most low-tech stations with hardly anything important to secure; not even the items in the vault are noteworthy due to the falsified, low-tech Engram they're under. Just ensure peace is kept and the station is functioning in a calm manner."
-
- outfit = /datum/outfit/job/lambent
-
- access = list(ACCESS_SECURITY, ACCESS_SEC_DOORS, ACCESS_BRIG, ACCESS_ARMORY, ACCESS_COURT, ACCESS_WEAPONS, ACCESS_ENTER_GENPOP, ACCESS_LEAVE_GENPOP, ACCESS_LAMBENT,
- ACCESS_FORENSICS_LOCKERS, ACCESS_MORGUE, ACCESS_MAINT_TUNNELS, ACCESS_ALL_PERSONAL_LOCKERS, ACCESS_BARISTA, ACCESS_BARBER,
- ACCESS_RESEARCH, ACCESS_ENGINE, ACCESS_MINING, ACCESS_MEDICAL, ACCESS_CONSTRUCTION, ACCESS_MAILSORTING,
- ACCESS_HEADS, ACCESS_HOS, ACCESS_RC_ANNOUNCE, ACCESS_KEYCARD_AUTH, ACCESS_GATEWAY, ACCESS_MAINT_TUNNELS, ACCESS_MINERAL_STOREROOM)
- minimal_access = list(ACCESS_SECURITY, ACCESS_SEC_DOORS, ACCESS_BRIG, ACCESS_ARMORY, ACCESS_COURT, ACCESS_WEAPONS, ACCESS_ENTER_GENPOP, ACCESS_LEAVE_GENPOP, ACCESS_LAMBENT,
- ACCESS_FORENSICS_LOCKERS, ACCESS_MORGUE, ACCESS_MAINT_TUNNELS, ACCESS_ALL_PERSONAL_LOCKERS, ACCESS_BARISTA, ACCESS_BARBER,
- ACCESS_RESEARCH, ACCESS_ENGINE, ACCESS_MINING, ACCESS_MEDICAL, ACCESS_CONSTRUCTION, ACCESS_MAILSORTING,
- ACCESS_HEADS, ACCESS_HOS, ACCESS_RC_ANNOUNCE, ACCESS_KEYCARD_AUTH, ACCESS_GATEWAY, ACCESS_MAINT_TUNNELS, ACCESS_MINERAL_STOREROOM)
-
- mind_traits = list(TRAIT_CAPTAIN_METABOLISM)
-
- blacklisted_quirks = list(/datum/quirk/brainproblems, /datum/quirk/insanity, /datum/quirk/nonviolent)
-
-/datum/outfit/job/lambent
- name = "Lambent"
- jobtype = /datum/job/lambent
-
- id = /obj/item/card/id/silver
- belt = /obj/item/pda/captain
- glasses = /obj/item/clothing/glasses/hud/toggle/zao
- ears = /obj/item/radio/headset/heads/captain/alt
- gloves = /obj/item/clothing/gloves/lambent
- uniform = /obj/item/clothing/under/rank/lambent
- suit = /obj/item/clothing/suit/lambent
- shoes = /obj/item/clothing/shoes/lambent
- backpack_contents = list(/obj/item/melee/classic_baton/telescopic=1, /obj/item/modular_computer/tablet/preset/advanced = 1)
-
- backpack = /obj/item/storage/backpack/lambent
- satchel = /obj/item/storage/backpack/satchel/lambent
- duffelbag = /obj/item/storage/backpack/duffelbag/lambent
- box = /obj/item/storage/box/security
-
- implants = list(/obj/item/implant/mindshield)
diff --git a/hyperstation/code/modules/mob/dead/new_player/cosmetic_parts.dm b/hyperstation/code/modules/mob/dead/new_player/cosmetic_parts.dm
new file mode 100644
index 000000000..a08db8726
--- /dev/null
+++ b/hyperstation/code/modules/mob/dead/new_player/cosmetic_parts.dm
@@ -0,0 +1,154 @@
+/*
+COSMETIC PARTS
+
+this system allows you to change the _base_ appearance of a limb independent
+of species or markings. this, for example, allows us to create "hybrids" like a
+mammal with avian legs.
+
+keep in mind that this does not change the species of a leg! in the above example,
+the mammal's bird-legs are still mammal legs. this matters in some places, like
+body part transplants; mis-matched species will cause extra damage if the surgery
+fails and the part is rejected. so you can't attach mammal-bird legs to avians
+safely.
+*/
+
+/datum/cosmetic_part
+ /** A unique string that is used to identify this part for save files. Allows name changes without breaking saves */
+ var/id
+ /** The name of the cosmetic part. This shows up in the preferences dropdown. */
+ var/name
+ var/icon = 'hyperstation/icons/mob/char_parts.dmi'
+ var/icon_state
+ /** How colors are determined for this part. MUTCOLORS for base color, MATRIXED to allow multiple channels. */
+ var/color_src = MUTCOLORS
+ /** Whether or not this cosmetic part has an alternate form for digitigrade legs. */
+ var/support_digitigrade = TRUE
+ /** Species IDs that support this cosmetic part. Bypassed with "show mismatched markings" option. */
+ var/list/supported_species
+
+/datum/cosmetic_part/head
+/datum/cosmetic_part/chest
+/datum/cosmetic_part/arms
+/datum/cosmetic_part/legs
+
+// HEADS
+// =========================================
+
+/datum/cosmetic_part/head/default
+ id = "default"
+ name = "default"
+ icon = null
+
+/datum/cosmetic_part/head/ipc_round
+ id = "ipc_round"
+ name = "round ipc head"
+ icon_state = "ipc_round"
+ supported_species = list("ipc")
+
+
+// CHESTS
+// =========================================
+
+/datum/cosmetic_part/chest/default
+ id = "default"
+ name = "default"
+ icon = null
+
+/datum/cosmetic_part/chest/ipc_sleek
+ id = "ipc_sleek"
+ name = "sleek ipc chest"
+ icon_state = "ipc_sleek"
+ supported_species = list("ipc")
+ color_src = MATRIXED
+
+/datum/cosmetic_part/chest/ipc_jointed
+ id = "ipc_jointed"
+ name = "jointed ipc chest"
+ icon_state = "ipc_jointed"
+ supported_species = list("ipc")
+ color_src = MATRIXED
+
+
+// ARMS
+// =========================================
+
+/datum/cosmetic_part/arms/default
+ id = "default"
+ name = "default"
+ icon = null
+
+/datum/cosmetic_part/arms/avian_alt
+ id = "avian_alt"
+ name = "avian claws"
+ icon_state = "avian_alt"
+ supported_species = list("mammal", "avian", "aquatic", "insect", "xeno", "synthliz")
+
+/datum/cosmetic_part/arms/insect
+ id = "insect"
+ name = "insect arms"
+ icon = 'modular_citadel/icons/mob/mutant_bodyparts.dmi'
+ icon_state = "insect"
+ supported_species = list("mammal", "avian", "aquatic", "insect", "xeno", "synthliz")
+
+/datum/cosmetic_part/arms/ipc_sleek
+ id = "ipc_sleek"
+ name = "sleek ipc arms"
+ icon_state = "ipc_sleek"
+ supported_species = list("ipc")
+ color_src = MATRIXED
+
+/datum/cosmetic_part/arms/ipc_jointed
+ id = "ipc_jointed"
+ name = "jointed ipc arms"
+ icon_state = "ipc_jointed"
+ supported_species = list("ipc")
+ color_src = MATRIXED
+
+
+// LEGS
+// =========================================
+
+/datum/cosmetic_part/legs/default
+ id = "default"
+ name = "default"
+ icon = null
+
+/datum/cosmetic_part/legs/avian
+ id = "avian"
+ name = "avian legs"
+ icon = 'modular_citadel/icons/mob/mutant_bodyparts.dmi'
+ icon_state = "avian"
+ supported_species = list("mammal", "avian", "aquatic", "insect", "xeno", "synthliz")
+ support_digitigrade = FALSE
+
+/datum/cosmetic_part/legs/mammal
+ id = "mammal"
+ name = "mammal legs"
+ icon = 'modular_citadel/icons/mob/mutant_bodyparts.dmi'
+ icon_state = "mammal"
+ supported_species = list("mammal", "avian", "aquatic", "insect", "xeno", "synthliz")
+ support_digitigrade = TRUE
+
+/datum/cosmetic_part/legs/insect
+ id = "insect"
+ name = "insect legs"
+ icon = 'modular_citadel/icons/mob/mutant_bodyparts.dmi'
+ icon_state = "insect"
+ supported_species = list("mammal", "avian", "aquatic", "insect", "xeno", "synthliz")
+ support_digitigrade = TRUE
+
+/datum/cosmetic_part/legs/ipc_sleek
+ id = "ipc_sleek"
+ name = "sleek ipc legs"
+ icon_state = "ipc_sleek"
+ supported_species = list("ipc")
+ color_src = MATRIXED
+ support_digitigrade = FALSE
+
+/datum/cosmetic_part/legs/ipc_jointed
+ id = "ipc_jointed"
+ name = "jointed ipc legs"
+ icon_state = "ipc_jointed"
+ supported_species = list("ipc")
+ color_src = MATRIXED
+ support_digitigrade = FALSE
\ No newline at end of file
diff --git a/hyperstation/code/modules/mob/dead/new_player/sprite_accessories.dm b/hyperstation/code/modules/mob/dead/new_player/sprite_accessories.dm
index f76d2ddf0..34dc50426 100644
--- a/hyperstation/code/modules/mob/dead/new_player/sprite_accessories.dm
+++ b/hyperstation/code/modules/mob/dead/new_player/sprite_accessories.dm
@@ -87,6 +87,11 @@ SNOUTS
icon_state = "feasterndnw"
icon = 'hyperstation/icons/mob/char_snouts.dmi'
+/datum/sprite_accessory/mam_snouts/knshuttle // Dahlular and Arcstaisia @ hyperstation, april 2022. Feel free to remove comment. Just remember this is snowflakey Kinaris stuff.
+ name = "Kinaris - Shuttle (Hyper)"
+ icon_state = "knshuttle"
+ icon = 'hyperstation/icons/mob/char_snouts.dmi'
+
/datum/sprite_accessory/mam_snouts/fchemlight
name = "RadDog (Top) (Hyper)"
icon_state = "fchemlight"
@@ -143,6 +148,11 @@ EARS
icon_state = "easternd"
icon = 'hyperstation/icons/mob/char_ears.dmi'
+/datum/sprite_accessory/mam_ears/knshuttle // Dahlular and Arcstaisia @ hyperstation, april 2022. Feel free to remove comment. Just remember this is snowflakey Kinaris stuff.
+ name = "Kinaris - Shuttle (Hyper)"
+ icon_state = "knshuttle"
+ icon = 'hyperstation/icons/mob/char_ears.dmi'
+
/datum/sprite_accessory/mam_ears/chemlight
name = "RadDog (Hyper)"
icon_state = "chemlight"
@@ -185,6 +195,13 @@ WINGS
icon_state = "insect"
icon = 'hyperstation/icons/mob/char_wings.dmi'
+/datum/sprite_accessory/deco_wings/knshuttle // Dahlular and Arcstaisia @ hyperstation, april 2022. Feel free to remove comment. Just remember this is snowflakey Kinaris stuff.
+ name = "Kinaris - Shuttle (Hyper)"
+ icon_state = "knshuttle"
+ icon = 'hyperstation/icons/mob/char_wings.dmi'
+ //recommended_species = list("synthliz") need to give synths a deco wing slot
+ color_src = MATRIXED
+
/datum/sprite_accessory/deco_wings/minibat // sarcoph @ hyperstation, march 2022
name = "Mini Bat (Hyper)"
icon_state = "minibat"
@@ -324,6 +341,18 @@ TAILS + ANIMATED TAILS
icon_state = "easternd"
icon = 'hyperstation/icons/mob/char_tails.dmi'
+/datum/sprite_accessory/mam_tails/knshuttle // Dahlular and Arcstaisia @ hyperstation, april 2022. Feel free to remove comment. Just remember this is snowflakey Kinaris stuff.
+ name = "Kinaris - Shuttle (Hyper)"
+ icon_state = "knshuttle"
+ icon = 'hyperstation/icons/mob/char_tails.dmi'
+ recommended_species = list("synthliz")
+
+/datum/sprite_accessory/mam_tails_animated/knshuttle
+ name = "Kinaris - Shuttle (Hyper)"
+ icon_state = "knshuttle"
+ icon = 'hyperstation/icons/mob/char_tails.dmi'
+ recommended_species = list("synthliz")
+
/datum/sprite_accessory/mam_tails/chemlight
name = "RadDog (Hyper)"
icon_state = "chemlight"
@@ -398,6 +427,11 @@ from modular_citadel/code/modules/mob/dead/new_player/sprite_accessories.dm:
icon_state = "easternd"
icon = 'hyperstation/icons/mob/char_markings.dmi'
+/datum/sprite_accessory/mam_body_markings/knshuttle // Dahlular and Arcstaisia @ hyperstation, april 2022. Feel free to remove comment. Just remember this is snowflakey Kinaris stuff.
+ name = "Kinaris - Shuttle (Hyper)"
+ icon_state = "knshuttle"
+ icon = 'hyperstation/icons/mob/char_markings.dmi'
+
//doged was here
/datum/sprite_accessory/mam_body_markings/chemlight
name = "RadDog (Hyper)"
@@ -441,6 +475,92 @@ from modular_citadel/code/modules/mob/dead/new_player/sprite_accessories.dm:
taur_mode = PAW_TAURIC
ckeys_allowed = list("chemlight")
+
+/*
+IPCS
+==========================================================
+*/
+
+/*
+from modular_citadel/code/modules/mob/dead/new_player/sprite_accessories.dm:
+
+/datum/sprite_accessory/antenna
+ icon = 'modular_citadel/icons/mob/ipc_antennas.dmi'
+ color_src = MUTCOLORS3
+ recommended_species = list("ipc")
+
+/datum/sprite_accessory/screen
+ icon = 'modular_citadel/icons/mob/ipc_screens.dmi'
+ color_src = null
+*/
+
+/datum/sprite_accessory/antenna/idog_down
+ name = "Dog, down (Hyper)"
+ icon_state = "idog_down"
+ color_src = MATRIXED
+
+/datum/sprite_accessory/antenna/idog_up
+ name = "Dog, up (Hyper)"
+ icon_state = "idog_up"
+ color_src = MATRIXED
+
+/datum/sprite_accessory/antenna/headset
+ name = "Headphones (Hyper)"
+ icon_state = "headset"
+ color_src = MATRIXED
+
+/datum/sprite_accessory/antenna/aquatic
+ name = "Fins (Hyper)"
+ icon_state = "aquatic"
+ color_src = MATRIXED
+
+/datum/sprite_accessory/screen/ghost
+ name = "Ghost (Hyper)"
+ icon_state = "ghost"
+
+/datum/sprite_accessory/screen/heartbeat
+ name = "Heartbeat (Hyper)"
+ icon_state = "heartbeat"
+
+/datum/sprite_accessory/screen/ocean
+ name = "Ocean (Hyper)"
+ icon_state = "ocean"
+
+/datum/sprite_accessory/antenna/catears
+ name = "Pointy Ears (Hyper)"
+ icon_state = "catears"
+ color_src = MATRIXED
+
+/datum/sprite_accessory/screen/valley
+ name = "Valley (Hyper)"
+ icon_state = "valley"
+
+/datum/sprite_accessory/screen/visor
+ name = "Black Visor (Hyper)"
+ icon = 'hyperstation/icons/mob/ipc_screen_visor.dmi'
+ icon_state = "visor_black"
+
+/datum/sprite_accessory/screen/visor/blue
+ name = "Blue Visor (Hyper)"
+ icon_state = "visor_blue"
+
+/datum/sprite_accessory/screen/visor/green
+ name = "Green Visor (Hyper)"
+ icon_state = "visor_green"
+
+/datum/sprite_accessory/screen/visor/red
+ name = "Red Visor (Hyper)"
+ icon_state = "visor_red"
+
+/datum/sprite_accessory/screen/visor/white
+ name = "White Visor (Hyper)"
+ icon_state = "visor_white"
+
+/datum/sprite_accessory/screen/visor/yellow
+ name = "Yellow Visor (Hyper)"
+ icon_state = "visor_yellow"
+
+
/*
HAIRSTYLES
==========================================================
@@ -480,4 +600,4 @@ from code/modules/mob/dead/new_player/sprite_accessories/hair_head.dm:
/datum/sprite_accessory/hair/emoh
name = "Emo (Hyper)"
- icon_state = "hair_emoh"
\ No newline at end of file
+ icon_state = "hair_emoh"
diff --git a/hyperstation/code/modules/mob/living/carbon/carbon.dm b/hyperstation/code/modules/mob/living/carbon/carbon.dm
index ec2f69c1d..3af2e9447 100644
--- a/hyperstation/code/modules/mob/living/carbon/carbon.dm
+++ b/hyperstation/code/modules/mob/living/carbon/carbon.dm
@@ -13,6 +13,11 @@
/mob/living/carbon/handle_status_effects()
..()
handle_pain()
+
+/mob/living/carbon/has_mouth()
+ var/obj/item/bodypart/head/head = get_bodypart(BODY_ZONE_HEAD)
+ if(head && head.mouth)
+ return TRUE
/mob/living/carbon/proc/handle_pain()
var/pain_amount = 0
diff --git a/hyperstation/code/modules/mob/living/carbon/human/cosmetic_part_handler.dm b/hyperstation/code/modules/mob/living/carbon/human/cosmetic_part_handler.dm
new file mode 100644
index 000000000..25b93526f
--- /dev/null
+++ b/hyperstation/code/modules/mob/living/carbon/human/cosmetic_part_handler.dm
@@ -0,0 +1,17 @@
+/obj/item/bodypart/proc/apply_cosmetic(datum/cosmetic_part/part)
+ if(!is_organic_limb() || animal_origin || !part)
+ return
+ cosmetic_icon = part
+
+
+/mob/living/carbon/human/proc/handle_cosmetic_parts()
+ var/features = dna.features
+ var/list/body_zones = list(BODY_ZONE_HEAD, BODY_ZONE_CHEST, BODY_ZONE_L_ARM, BODY_ZONE_R_ARM, BODY_ZONE_L_LEG, BODY_ZONE_R_LEG)
+ for(var/zone in body_zones)
+ var/datum/cosmetic_part/cosmetic_pref = features["cosmetic_" + zone]
+ if(!istype(cosmetic_pref, /datum/cosmetic_part))
+ continue
+ var/datum/cosmetic_part/part = cosmetic_pref
+ var/obj/item/bodypart/body_part = get_bodypart(zone)
+ if(body_part && part)
+ body_part.apply_cosmetic(part)
\ No newline at end of file
diff --git a/hyperstation/code/modules/mob/living/carbon/human/species_types/ipc.dm b/hyperstation/code/modules/mob/living/carbon/human/species_types/ipc.dm
new file mode 100644
index 000000000..b3e22f9ef
--- /dev/null
+++ b/hyperstation/code/modules/mob/living/carbon/human/species_types/ipc.dm
@@ -0,0 +1,58 @@
+// APC powercord: oracle port
+
+/obj/item/apc_powercord
+ name = "power cord"
+ desc = "An internal power cord hooked up to a battery. Useful if you run on electricity. Not so much otherwise."
+ icon = 'icons/obj/power.dmi'
+ icon_state = "wire1"
+
+
+/obj/item/apc_powercord/afterattack(atom/target, mob/user, proximity_flag, click_parameters)
+ if(!istype(target, /obj/machinery/power/apc) || !ishuman(user) || !proximity_flag)
+ return ..()
+ user.changeNext_move(CLICK_CD_MELEE)
+ var/mob/living/carbon/human/H = user
+ var/obj/item/organ/stomach/cell/battery = H.getorganslot(ORGAN_SLOT_STOMACH)
+ if(!battery)
+ to_chat(H, "You try to siphon energy from \the [target], but your power cell is gone!")
+ return
+
+ if(istype(H) && H.nutrition >= NUTRITION_LEVEL_ALMOST_FULL)
+ to_chat(user, "You are already fully charged!")
+ return
+
+ if(istype(target, /obj/machinery/power/apc))
+ var/obj/machinery/power/apc/A = target
+ if(A.cell && A.cell.charge > A.cell.maxcharge*0.25)
+ powerdraw_loop(A, H)
+ return
+ else
+ to_chat(user, "There is not enough charge to draw from that APC.")
+ return
+
+
+/obj/item/apc_powercord/proc/powerdraw_loop(obj/machinery/power/apc/A, mob/living/carbon/human/H)
+ H.visible_message("[H] inserts a power connector into the [A].", "You begin to draw power from the [A].")
+ while(do_after(H, 10, target = A))
+ if(!istype(A))
+ return
+ if(loc != H)
+ to_chat(H, "You must keep your connector out while charging!")
+ break
+ if(A.cell.charge == 0)
+ to_chat(H, "The [A] doesn't have enough charge to spare.")
+ break
+ A.charging = 1
+ if(A.cell.charge >= 500)
+ H.nutrition += 50
+ A.cell.charge -= 250
+ to_chat(H, "You siphon off some of the stored charge for your own use.")
+ else
+ H.nutrition += A.cell.charge/10
+ A.cell.charge = 0
+ to_chat(H, "You siphon off as much as the [A] can spare.")
+ break
+ if(H.nutrition > NUTRITION_LEVEL_WELL_FED)
+ to_chat(H, "You are now fully charged.")
+ break
+ H.visible_message("[H] unplugs from the [A].", "You unplug from the [A].")
\ No newline at end of file
diff --git a/hyperstation/code/modules/mob/living/silicon/robot/examine_vr.dm b/hyperstation/code/modules/mob/living/silicon/robot/examine_vr.dm
new file mode 100644
index 000000000..f3b04a440
--- /dev/null
+++ b/hyperstation/code/modules/mob/living/silicon/robot/examine_vr.dm
@@ -0,0 +1,8 @@
+/mob/living/silicon/robot/proc/examine_bellies_borg()
+
+ var/message = ""
+ for(var/belly in vore_organs)
+ var/obj/belly/B = belly
+ message += B.get_examine_msg()
+
+ return message
diff --git a/hyperstation/code/modules/mob/living/silicon/robot/robot.dm b/hyperstation/code/modules/mob/living/silicon/robot/robot.dm
index 4752f0c95..20c7e7679 100644
--- a/hyperstation/code/modules/mob/living/silicon/robot/robot.dm
+++ b/hyperstation/code/modules/mob/living/silicon/robot/robot.dm
@@ -1,3 +1,3 @@
//This file is empty right now, but leaves room for people to put shit here in the future for those who are lazy
/mob/living/silicon/robot
- var/datum/action/cyborg_small_sprite/small_sprite_action //This gets replaced every time the cyborg changes modules --Cyanosis
\ No newline at end of file
+ var/datum/action/cyborg_small_sprite/small_sprite_action //This gets replaced every time the cyborg changes modules --Cyanosis
diff --git a/hyperstation/code/modules/mob/living/silicon/robot/robot_modules.dm b/hyperstation/code/modules/mob/living/silicon/robot/robot_modules.dm
index dbef0ad93..d42f3dbeb 100644
--- a/hyperstation/code/modules/mob/living/silicon/robot/robot_modules.dm
+++ b/hyperstation/code/modules/mob/living/silicon/robot/robot_modules.dm
@@ -1,11 +1,60 @@
//This file is empty right now, but leaves room for people to put shit here in the future for those who are lazy
+/obj/item/robot_module
+ var/list/added_channels = list() //Borg radio stuffs
+
+//service
+/obj/item/robot_module/butler
+ added_channels = list(RADIO_CHANNEL_SERVICE = 1)
+
+/obj/item/robot_module/clown
+ added_channels = list(RADIO_CHANNEL_SERVICE = 1)
+
+/obj/item/robot_module/janitor
+ added_channels = list(RADIO_CHANNEL_SERVICE = 1)
+
+//engineering
+/obj/item/robot_module/engineering
+ added_channels = list(RADIO_CHANNEL_ENGINEERING = 1)
+
+//medical
+/obj/item/robot_module/medical
+ added_channels = list(RADIO_CHANNEL_MEDICAL = 1)
+
+//security
+/obj/item/robot_module/peacekeeper
+ added_channels = list(RADIO_CHANNEL_SECURITY = 1)
+
+/obj/item/robot_module/security
+ added_channels = list(RADIO_CHANNEL_SECURITY = 1)
+
+//supply
+/obj/item/robot_module/miner
+ added_channels = list(RADIO_CHANNEL_SUPPLY = 1) // Probably already handled by other code when spawned with pre-set module, but whatever.
+
+//dogborgs
+/obj/item/robot_module/k9
+ added_channels = list(RADIO_CHANNEL_SECURITY = 1)
+
+/obj/item/robot_module/medihound
+ added_channels = list(RADIO_CHANNEL_MEDICAL = 1)
+
+/obj/item/robot_module/scrubpup
+ added_channels = list(RADIO_CHANNEL_SERVICE = 1)
+
+/obj/item/robot_module/borgi
+ added_channels = list(RADIO_CHANNEL_SERVICE = 1)
+
+/obj/item/robot_module/orepup
+ added_channels = list(RADIO_CHANNEL_SUPPLY = 1)
+
+
//This proc gets called whenever a new robot module is being applied --Cyanosis
/obj/item/robot_module/proc/handle_sprite_action(mob/living/silicon/robot/R, is_huge = FALSE)
ASSERT(istype(R))
if(R.small_sprite_action)
QDEL_NULL(R.small_sprite_action)
- if(!is_huge) //only from the expander upgrade. The borg won't have an action if they don't have the expander upgrade
+ if(!is_huge) //only from the expander upgrade. The borg won't have an action if they don't have the expander upgrade
return
for(var/P in typesof(/datum/action/cyborg_small_sprite))
var/datum/action/cyborg_small_sprite/action = P
diff --git a/hyperstation/code/modules/mob/living/simple_animal/friendly/farm_animals.dm b/hyperstation/code/modules/mob/living/simple_animal/friendly/farm_animals.dm
index 3d12f301b..f5c7df2e2 100644
--- a/hyperstation/code/modules/mob/living/simple_animal/friendly/farm_animals.dm
+++ b/hyperstation/code/modules/mob/living/simple_animal/friendly/farm_animals.dm
@@ -241,6 +241,6 @@
/mob/living/simple_animal/chicken/examine()
. = ..()
- . += "this one is [gender]."
+ . += "This one is [gender]."
if(happiness<20)
. += "It looks stressed."
diff --git a/hyperstation/code/modules/mob/mob_helpers.dm b/hyperstation/code/modules/mob/mob_helpers.dm
index 00f9c8631..0a47f7b0a 100644
--- a/hyperstation/code/modules/mob/mob_helpers.dm
+++ b/hyperstation/code/modules/mob/mob_helpers.dm
@@ -27,3 +27,7 @@ mob/proc/checkloadappearance()
else
to_chat(H, "You either took too long or chose not to change. Alrighty. Remember, you have 90 seconds from spawn to get to a mirror and still do it if you wish.")
return
+
+// oracle port
+/mob/proc/has_mouth()
+ return FALSE
\ No newline at end of file
diff --git a/hyperstation/code/modules/power/lighting.dm b/hyperstation/code/modules/power/lighting.dm
deleted file mode 100644
index 9c98912a5..000000000
--- a/hyperstation/code/modules/power/lighting.dm
+++ /dev/null
@@ -1,31 +0,0 @@
-/obj/item/wallframe/light_fixture/fairy
- name = "fairy lights frame"
- icon_state = "fairy-construct-item"
- result_path = /obj/structure/light_construct/fairy
- materials = list(MAT_METAL=MINERAL_MATERIAL_AMOUNT)
-
-/obj/structure/light_construct/fairy
- name = "fairy lights frame"
- icon_state = "fairy-construct-stage1"
- fixture_type = "fairy"
- sheets_refunded = 1
-
-/obj/machinery/light/fairy
- icon_state = "fairy"
- base_state = "fairy"
- fitting = "fairy"
- brightness = 3
- desc = "Small fairy lights."
- //light_type = /obj/item/light/fairy
-
-/obj/machinery/light/fairy/broken
- status = LIGHT_BROKEN
- icon_state = "fairy-broken"
-
-/obj/machinery/light/fairy/built
- icon_state = "bulb-empty"
-
-/obj/machinery/light/fairy/built/Initialize()
- . = ..()
- status = LIGHT_EMPTY
- update(0)
diff --git a/hyperstation/code/modules/research/designs/medical_designs.dm b/hyperstation/code/modules/research/designs/medical_designs.dm
new file mode 100644
index 000000000..825bcd2a2
--- /dev/null
+++ b/hyperstation/code/modules/research/designs/medical_designs.dm
@@ -0,0 +1,69 @@
+/datum/design/ipc_liver
+ name = "IPC Reagent Processor"
+ id = "ipc_liver"
+ build_type = PROTOLATHE
+ materials = list(MAT_METAL = 2000, MAT_GLASS = 1000)
+ build_path = /obj/item/organ/liver/ipc
+ category = list("Medical Designs")
+ departmental_flags = DEPARTMENTAL_FLAG_MEDICAL
+ construction_time = 100
+
+/datum/design/ipc_eyes
+ name = "IPC Eyes"
+ id = "ipc_eyes"
+ build_type = PROTOLATHE
+ materials = list(MAT_METAL = 1000, MAT_GLASS = 2000)
+ build_path = /obj/item/organ/eyes/ipc
+ category = list("Medical Designs")
+ departmental_flags = DEPARTMENTAL_FLAG_MEDICAL
+ construction_time = 100
+
+/datum/design/ipc_tongue
+ name = "Positronic Voicebox"
+ id = "ipc_tongue"
+ build_type = PROTOLATHE
+ materials = list(MAT_METAL = 2000, MAT_GLASS = 1000)
+ build_path = /obj/item/organ/tongue/robot/ipc
+ category = list("Medical Designs")
+ departmental_flags = DEPARTMENTAL_FLAG_MEDICAL
+ construction_time = 100
+
+/datum/design/ipc_stomach
+ name = "Micro-cell"
+ id = "ipc_stomach"
+ build_type = PROTOLATHE
+ materials = list(MAT_METAL = 2000, MAT_GLASS = 1000, MAT_PLASMA = 200)
+ build_path = /obj/item/organ/stomach/cell
+ category = list("Medical Designs")
+ departmental_flags = DEPARTMENTAL_FLAG_MEDICAL
+ construction_time = 100
+
+/datum/design/synthliz_stomach
+ name = "Synthetic Lizardperson Stomach"
+ id = "synthliz_stomach"
+ build_type = PROTOLATHE
+ materials = list(MAT_METAL = 2000, MAT_GLASS = 1000)
+ build_path = /obj/item/organ/stomach/synthliz
+ category = list("Medical Designs")
+ departmental_flags = DEPARTMENTAL_FLAG_MEDICAL
+ construction_time = 100
+
+/datum/design/power_cord
+ name = "IPC Power Cord"
+ id = "power_cord"
+ build_type = PROTOLATHE
+ materials = list(MAT_METAL = 2000, MAT_GLASS = 1000)
+ build_path = /obj/item/organ/cyberimp/arm/power_cord
+ category = list("Medical Designs")
+ departmental_flags = DEPARTMENTAL_FLAG_MEDICAL
+ construction_time = 100
+
+
+/datum/techweb_node/ipc_organs
+ id = "ipc_organs"
+ display_name = "IPC Parts"
+ description = "We have the technology to replace him."
+ prereq_ids = list("cyber_organs","robotics")
+ design_ids = list("ipc_liver", "ipc_eyes", "ipc_tongue", "ipc_stomach", "synthliz_stomach", "power_cord")
+ research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 1500)
+ export_price = 5000
diff --git a/hyperstation/code/modules/salon/barber.dm b/hyperstation/code/modules/salon/barber.dm
deleted file mode 100644
index fe5163150..000000000
--- a/hyperstation/code/modules/salon/barber.dm
+++ /dev/null
@@ -1,541 +0,0 @@
-//Proper modularity to come at a later date
-/obj/structure/chair/barber_chair
- name = "barbers chair"
- desc = "You sit in this, and your hair shall be cut."
- icon = 'icons/obj/chairs.dmi'
- icon_state = "barber_chair"
-
-/obj/structure/closet/secure_closet/barber
- name = "Barber's locker"
- icon_state = "barber"
- icon = 'icons/obj/closet.dmi'
- req_access = list(ACCESS_BARBER)
-
-/obj/structure/closet/secure_closet/barber/PopulateContents()
- new /obj/item/clothing/mask/surgical(src) // These three are here, so the barber can pick and choose what he's painting.
- new /obj/item/clothing/under/rank/medical/blue(src)
- new /obj/item/clothing/suit/apron/surgical(src)
- new /obj/item/clothing/accessory/waistcoat(src)
- //new /obj/item/clothing/under/rank/civilian/lawyer/purpsuit(src)
- new /obj/item/clothing/suit/toggle/lawyer/purple(src)
- new /obj/item/razor(src)
- //new /obj/item/straight_razor(src)
- new /obj/item/hairbrush/comb(src)
- new /obj/item/scissors(src)
- new /obj/item/fur_dyer(src)
- new /obj/item/dyespray(src)
- new /obj/item/storage/box/lipsticks(src)
- new /obj/item/reagent_containers/spray/quantum_hair_dye(src)
- new /obj/item/reagent_containers/spray/barbers_aid(src)
- new /obj/item/reagent_containers/spray/cleaner(src)
- new /obj/item/reagent_containers/rag(src)
- new /obj/item/storage/firstaid/regular(src)
-
-/obj/machinery/vending/barbervend
- name = "Fab-O-Vend"
- desc = "It would seem it vends dyes, and other stuff to make you pretty."
- icon = 'hyperstation/icons/obj/barber.dmi'
- icon_state = "barbervend"
- product_slogans = "Spread the colour, like butter, onto toast... Onto their hair.; Sometimes, I dream about dyes...; Paint 'em up and call me Mr. Painter.; Look brother, I'm a vendomat, I solve practical problems."
- product_ads = "Cut 'em all!; To sheds!; Hair be gone!; Prettify!; Beautify!"
- vend_reply = "Come again!; Buy another!; Dont you love your new look?"
- req_access = list(ACCESS_BARBER)
- refill_canister = /obj/item/vending_refill/barbervend
- products = list(
- /obj/item/reagent_containers/spray/quantum_hair_dye = 3,
- // /obj/item/reagent_containers/spray/baldium = 3,
- /obj/item/reagent_containers/spray/barbers_aid = 3,
- /obj/item/dyespray = 5,
- /obj/item/hairbrush = 3,
- /obj/item/hairbrush/comb = 3,
- /obj/item/fur_dyer = 1,
- )
- premium = list(
- /obj/item/scissors = 3,
- /obj/item/reagent_containers/spray/super_barbers_aid = 3,
- /obj/item/storage/box/lipsticks = 3,
- /obj/item/lipstick/quantum = 1,
- /obj/item/razor = 1,
- // /obj/item/storage/box/perfume = 1,
- )
- refill_canister = /obj/item/vending_refill/barbervend
-
-/obj/item/vending_refill/barbervend
- machine_name = "barber vend resupply"
- icon_state = "refill_snack" //generic item refill because there isnt one sprited yet.
-
-/obj/effect/landmark/start/barber
- name = "Barber"
- icon_state = "Barber"
- //icon = 'modular_skyrat/master_files/icons/mob/landmarks.dmi'
-
-//Brush
-/obj/item/hairbrush
- name = "hairbrush"
- desc = "A small, circular brush with an ergonomic grip for efficient brush application."
- icon = 'hyperstation/icons/obj/barber.dmi'
- icon_state = "brush"
- //Put lefthand and righthand files here
- w_class = WEIGHT_CLASS_TINY
- var/brush_speed = 3 SECONDS
-
-/obj/item/hairbrush/comb
- name = "comb"
- desc = "A rather simple tool, used to straighten out hair and knots in it."
- icon_state = "blackcomb"
-
-/obj/item/hairbrush/attack(mob/target, mob/user)
- if(target.stat == DEAD)
- to_chat(usr, "There isn't much point in brushing someone who can't appreciate it!")
- return
- brush(target, user)
- return COMPONENT_CANCEL_ATTACK_CHAIN
-
-//Brushes someone
-/obj/item/hairbrush/proc/brush(mob/living/target, mob/user)
- if(ishuman(target))
- var/mob/living/carbon/human/human_target = target
- var/obj/item/bodypart/head = human_target.get_bodypart(BODY_ZONE_HEAD)
-
- //Don't brush if you can't reach their head or cancel the action
- if(!head) //No head? No bitches?
- to_chat(usr, "[human_target] has no head!")
- return
- if(human_target.is_mouth_covered(head_only = 1))
- to_chat(usr, "You can't brush [human_target]'s hair while [human_target.p_their()] head is covered!")
- return
- if(!do_after(user, brush_speed, human_target))
- return
-
- // Do 1 brute to their head if they're bald. Should've been more careful.
- if(human_target.hair_style == "Bald" || human_target.hair_style == "Skinhead" && is_species(human_target, /datum/species/human)) //It can be assumed most anthros have hair on them!
- human_target.visible_message("[usr] scrapes the bristles uncomfortably over [human_target]'s scalp.","You scrape the bristles uncomfortably over [human_target]'s scalp.")
- playsound(target, 'hyperstation/sound/misc/bonk.ogg', 100, 1) //Until I fix it
- return
-
- //Brush their hair
- if(human_target == user)
- human_target.visible_message("[usr] brushes [usr.p_their()] hair!","You brush your hair.")
- //SEND_SIGNAL(user, COMSIG_ADD_MOOD_EVENT, "brushed", /datum/mood/brushed/self)
- else
- user.visible_message("[usr] brushes [human_target]'s hair!","You brush [human_target]'s hair.")
- //SEND_SIGNAL(human_target, COMISG_ADD_MOOD_EVENT, "brushed", /datum/mood_event/brushed, user)
-
-
-
-//fur dyer
-#define COLOR_MODE_SPECIFIC "Specific Marking"
-#define COLOR_MODE_GENERAL "General Color"
-
-/obj/item/fur_dyer
- name = "electric fur dyer"
- desc = "Dye that is capable of recoloring fur in a mostly permanent way."
- icon = 'hyperstation/icons/obj/barber.dmi'
- icon_state = "fur_sprayer"
- w_class = WEIGHT_CLASS_TINY
-
- var/mode = COLOR_MODE_GENERAL
-/*
-/obj/item/fur_dyer/Initialize(mapload)
- . = ..()
- AddComponent(/datum/component/cell)
-*/
-/obj/item/fur_dyer/attack_self(mob/user, modifiers)
- . = ..()
- if(mode == COLOR_MODE_SPECIFIC)
- mode = COLOR_MODE_GENERAL
- else
- mode = COLOR_MODE_SPECIFIC
-
- to_chat(user, "Set to [mode]!")
-
-/obj/item/fur_dyer/attack(mob/living/M, mob/living/user, params)
- if(!ishuman(M))
- return ..()
-
- var/mob/living/carbon/human/target_human = M
-
- switch(mode)
- if(COLOR_MODE_SPECIFIC)
- to_chat(user, "The device resonates ominously, and stops. It seems to be interfered by an Engram.")
- //dye_marking(target_human, user)
- if(COLOR_MODE_GENERAL)
- dye_general(target_human, user)
-
-/obj/item/fur_dyer/proc/dye_general(mob/living/carbon/human/target_human, mob/living/user)
- var/selected_mutant_color = tgalert(user, "Please select which mutant color you'd like to change", "Select Color", "One", "Two", "Three")
-
- if(!selected_mutant_color)
- return
-
- var/selected_color = input(
- user,
- "Select marking color",
- null,
- "#FFFFFF"
- ) as color | null
-
- if(!selected_color)
- return
-
- selected_color = sanitize_hexcolor(selected_color)
-
- visible_message("[user] starts to masterfully paint [target_human]!")
-
- if(do_after(user, 20 SECONDS, target_human))
- switch(selected_mutant_color)
- if("One")
- target_human.dna.features["mcolor"] = selected_color
- if("Two")
- target_human.dna.features["mcolor2"] = selected_color
- if("Three")
- target_human.dna.features["mcolor3"] = selected_color
-
- target_human.regenerate_icons()
- //use power
-
- visible_message("[user] finishes painting [target_human]!")
-
- playsound(src.loc, 'sound/effects/spray2.ogg', 50, TRUE)
-
-
-/* We don't have markings that can be colored separately yet, so this is not needed
-/obj/item/fur_dyer/proc/dye_marking(mob/living/carbon/human/target_human, mob/living/user)
-
- var/list/list/current_markings = target_human.dna.body_markings.Copy()
-
- if(!current_markings.len)
- to_chat(user, "[target_human] has no markings!")
- return
-
- //power stuff here
-
- /var/selected_marking_area = user.zone_selected
-
- if(!current_markings[selected_marking_area])
- to_chat(user, "[target_human] has no bodymarkings on this limb!")
- return
-
- var/selected_marking_id = input(user, "Please select which marking you'd like to color!", "Select marking", current_markings[selected_marking_area])
-
- if(!selected_marking_id)
- return
-
- var/selected_color = input(
- user,
- "Select marking color",
- null,
- "#FFFFFF"
- ) as color | null
-
- if(!selected_color)
- return
-
- selected_color = sanitize_hexcolor(selected_color)
-
- visible_message("[user] starts to masterfully paint [target_human]!")
-
- if(do_after(user, 20 SECONDS, target_human))
- current_markings[selected_marking_area][selected_marking_id] = selected_color
-
- target_human.dna.body_markings = current_markings.Copy()
-
- target_human.regenerate_icons()
-
- //item_use_power(power_use_amount, user)
-
- visible_message("[user] finishes painting [target_human]!")
-
- playsound(src.loc, 'sound/effects/spray2.ogg', 50, TRUE)
-*/
-
-/obj/machinery/dryer
- name = "hand dryer"
- desc = "The Breath Of Lizards-3000, an experimental dryer."
- icon = 'hyperstation/icons/obj/dryer.dmi'
- icon_state = "dryer"
- density = FALSE
- anchored = TRUE
- var/busy = FALSE
-
-/obj/machinery/dryer/attack_hand(mob/user)
- if(iscyborg(user) || isAI(user))
- return
-
- if(!can_interact(user))
- return
-
- if(busy)
- to_chat(user, "Someone is already drying here.")
- return
-
- to_chat(user, "You start drying your hands.")
- playsound(src, 'hyperstation/sound/salon/drying.ogg', 50)
- add_fingerprint(user)
- busy = TRUE
- if(do_after(user, 4 SECONDS, src))
- busy = FALSE
- user.visible_message("[user] dried their hands using \the [src].")
- else
- busy = FALSE
-
-/obj/item/reagent_containers/dropper/precision
- name = "pipette"
- desc = "A high precision pippette. Holds 1 unit."
- icon = 'hyperstation/icons/obj/barber.dmi'
- icon_state = "pipette1"
- amount_per_transfer_from_this = 1
- possible_transfer_amounts = list(0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,1)
- volume = 1
- w_class = WEIGHT_CLASS_TINY
-
-/obj/item/storage/box/lipsticks
- name = "lipstick box"
-
-/obj/item/storage/box/lipsticks/PopulateContents()
- ..()
- new /obj/item/lipstick(src)
- new /obj/item/lipstick/purple(src)
- new /obj/item/lipstick/jade(src)
- new /obj/item/lipstick/black(src)
-
-/obj/item/lipstick/quantum
- name = "quantum lipstick"
-
-/obj/item/lipstick/quantum/attack(mob/attacked_mob, mob/user)
- if(!open || !ismob(attacked_mob))
- return
-
- if(!ishuman(attacked_mob))
- to_chat(user, "Where are the lips on that?")
- return
-
- var/new_color = input(
- user,
- "Select lipstick color",
- null,
- "#FFFFFF"
- ) as color | null
-
- var/mob/living/carbon/human/target = attacked_mob
- if(target.is_mouth_covered())
- to_chat(user, "Remove [ target == user ? "your" : "[target.p_their()]" ] mask!")
- return
- if(target.lip_style) //if they already have lipstick on
- to_chat(user, "You need to wipe off the old lipstick first!")
- return
-
- if(target == user)
- visible_message("[user] does [user.p_their()] lips with \the [src].","You take a moment to apply \the [src]. Perfect!")
- target.lip_style = "lipstick"
- target.lip_color = new_color
- target.update_body()
- return
-
- visible_message("[user] begins to do [target]'s lips with \the [src].","You begin to apply \the [src] on [target]'s lips...")
- if(!do_after(user, 2 SECONDS, target = target))
- return
- visible_message("[user] does [target]'s lips with \the [src].","You apply \the [src] on [target]'s lips.")
- target.lip_style = "lipstick"
- target.lip_color = new_color
- target.update_body()
-
-/obj/effect/decal/cleanable/hair
- name = "hair cuttings"
- icon = 'hyperstation/icons/obj/barber.dmi'
- icon_state = "cut_hair"
-
-/obj/item/razor
- name = "electric razor"
- desc = "The latest and greatest power razor born from the science of shaving."
- icon = 'hyperstation/icons/obj/barber.dmi'
- icon_state = "razor"
- flags_1 = CONDUCT_1
- w_class = WEIGHT_CLASS_TINY
- // How long do we take to shave someone's (facial) hair?
- var/shaving_time = 10 SECONDS
-
-/obj/item/razor/proc/shave(mob/living/carbon/human/target_human, location = BODY_ZONE_PRECISE_MOUTH)
- if(location == BODY_ZONE_PRECISE_MOUTH)
- target_human.facial_hair_style = "Shaved"
- else
- target_human.hair_style = "Bald"
-
- target_human.update_hair()
- playsound(loc, 'sound/items/unsheath.ogg', 20, TRUE)
-
-/obj/item/razor/attack(mob/attacked_mob, mob/living/user)
- if(ishuman(attacked_mob))
- var/mob/living/carbon/human/target_human = attacked_mob
- var/location = user.zone_selected
- if(!(location in list(BODY_ZONE_PRECISE_MOUTH, BODY_ZONE_HEAD)))
- to_chat(user, "You stop, look down at what you're currently holding and ponder to yourself, \"This is probably to be used on their hair or their facial hair.\"")
- return
- if((location in list(BODY_ZONE_PRECISE_MOUTH, BODY_ZONE_HEAD)) && !target_human.get_bodypart(BODY_ZONE_HEAD))
- to_chat(user, "[target_human] doesn't have a head!")
- return
-
- if(location == BODY_ZONE_PRECISE_MOUTH)
- if(!(FACEHAIR in target_human.dna.species.species_traits))
- to_chat(user, "There is no facial hair to shave!")
- return
- if(!get_location_accessible(target_human, location))
- to_chat(user, "The mask is in the way!")
- return
- if(target_human.facial_hair_style == "Shaved")
- to_chat(user, "Already clean-shaven!")
- return
-
- var/self_shaving = target_human == user // Shaving yourself?
- visible_message("[user] starts to shave [self_shaving ? user.p_their() : "[target_human]'s"] hair with [src].","You take a moment to shave [self_shaving ? "your" : "[target_human]'s" ] hair with [src]...")
- if(do_after(user, shaving_time, target = target_human))
- visible_message("[user] shaves [self_shaving ? user.p_their() : "[target_human]'s"] hair clean with [src].","You finish shaving [self_shaving ? "your" : " [target_human]'s"] hair with [src]. Fast and clean!")
- shave(target_human, location)
-
- else if(location == BODY_ZONE_HEAD)
- if(!(HAIR in target_human.dna.species.species_traits))
- to_chat(user, "There is no hair to shave!")
- return
- if(!get_location_accessible(target_human, location))
- to_chat(user, "Their headgear is in the way!")
- return
- if(target_human.hair_style == "Bald" || target_human.hair_style == "Balding Hair" || target_human.hair_style == "Skinhead")
- to_chat(user, "There is not enough hair left to shave!")
- return
-
- var/self_shaving = target_human == user // Shaving yourself?
- visible_message("[user] starts to shave [self_shaving ? user.p_their() : "[target_human]'s"] hair with [src].","You take a moment to shave [self_shaving ? "your" : "[target_human]'s" ] hair with [src]...")
- if(do_after(user, shaving_time, target = target_human))
- visible_message("[user] shaves [self_shaving ? user.p_their() : "[target_human]'s"] hair clean with [src].","You finish shaving [self_shaving ? "your" : " [target_human]'s"] hair with [src]. Fast and clean!")
- shave(target_human, location)
- else
- ..()
- else
- ..()
-
-/obj/structure/sign/barber
- name = "barbershop sign"
- desc = "A glowing red-blue-white stripe you won't mistake for any other!"
- icon = 'hyperstation/icons/obj/barber.dmi'
- icon_state = "barber"
- buildable_sign = FALSE // Don't want them removed, they look too jank.
-
-/obj/item/scissors
- name = "barber's scissors"
- desc = "Some say a barbers best tool is his electric razor, that is not the case. These are used to cut hair in a professional way!"
- icon = 'hyperstation/icons/obj/barber.dmi'
- icon_state = "scissors"
- w_class = WEIGHT_CLASS_TINY
- sharpness = TRUE
- // How long does it take to change someone's hairstyle?
- var/haircut_duration = 1 MINUTES
- // How long does it take to change someone's facial hair style?
- var/facial_haircut_duration = 20 SECONDS
-
-/obj/item/scissors/attack(mob/living/attacked_mob, mob/living/user, params)
- if(!ishuman(attacked_mob))
- return
-
- var/mob/living/carbon/human/target_human = attacked_mob
-
- var/location = user.zone_selected
- if(!(location in list(BODY_ZONE_PRECISE_MOUTH, BODY_ZONE_HEAD)))
- to_chat(user, "You stop, look down at what you're currently holding and ponder to yourself, \"This is probably to be used on their hair or their facial hair.\"")
- return
-
- if(target_human.hair_style == "Bald" && target_human.facial_hair_style == "Shaved")
- to_chat(user, "What hair? They have none!")
- return
-
- if(user.zone_selected != BODY_ZONE_HEAD)
- return ..()
-
- var/selected_part = tgalert(user, "Please select which part of [target_human] you would like to sculpt!", "It's sculpting time!", "Hair", "Facial Hair", "Cancel")
-
- if(!selected_part || selected_part == "Cancel")
- return
-
- if(selected_part == "Hair")
- if(!target_human.hair_style == "Bald" && target_human.head)
- to_chat(user, "There is no hair to cut!")
- return
-
- var/hair_id = input(user, "Please select what hairstyle you'd like to sculpt!", "Select masterpiece") as null|anything in GLOB.hair_styles_list //dear god help me please
- if(!hair_id)
- return
-
- if(hair_id == "Bald")
- to_chat(target_human, "[user] seems to be cutting all your hair off!")
-
- to_chat(user, "You begin to masterfully sculpt [target_human]'s hair!")
-
- playsound(target_human, 'hyperstation/sound/salon/haircut.ogg', 100)
-
- if(do_after(user, haircut_duration, target_human))
- target_human.hair_style = hair_id
- target_human.update_hair()
- visible_message("[user] successfully cuts [target_human]'s hair!","You successfully cut [target_human]'s hair!")
- new /obj/effect/decal/cleanable/hair(get_turf(src))
- else
- if(!target_human.facial_hair_style == "Shaved" && target_human.wear_mask)
- to_chat(user, "There is no hair to cut!")
- return
-
- var/facial_hair_id = input(user, "Please select what facial hairstyle you'd like to sculpt!", "Select masterpiece") as null|anything in GLOB.facial_hair_styles_list
- if(!facial_hair_id)
- return
-
- if(facial_hair_id == "Shaved")
- to_chat(target_human, "[user] seems to be cutting all your facial hair off!")
-
- to_chat(user, "You begin to masterfully sculpt [target_human]'s facial hair!")
-
- playsound(target_human, 'hyperstation/sound/salon/haircut.ogg', 100)
-
- if(do_after(user, facial_haircut_duration, target_human))
- target_human.facial_hair_style = facial_hair_id
- target_human.update_hair()
- visible_message("[user] successfully cuts [target_human]'s facial hair!","You successfully cut [target_human]'s facial hair!")
- new /obj/effect/decal/cleanable/hair(get_turf(src))
-
-
-//reagents
-/obj/item/reagent_containers/spray/quantum_hair_dye
- name = "quantum hair dye"
- desc = "Changes hair colour RANDOMLY! Don't forget to read the label!"
- icon = 'hyperstation/icons/obj/barber.dmi'
- icon_state = "hairspraywhite"
- amount_per_transfer_from_this = 1
- possible_transfer_amounts = list(5,10)
- list_reagents = list(/datum/reagent/hair_dye = 30)
- volume = 50
-/*
-/obj/item/reagent_containers/spray/baldium
- name = "baldium spray"
- desc = "Causes baldness, exessive use may cause customer disatisfaction."
- icon = 'hyperstation/icons/obj/barber.dmi'
- icon_state = "hairremoval"
- amount_per_transfer_from_this = 1
- possible_transfer_amounts = list(5,10)
- list_reagents = list(/datum/reagent/baldium = 30)
- volume = 50
-*/
-/obj/item/reagent_containers/spray/barbers_aid
- name = "barber's aid"
- desc = "Causes rapid hair and facial hair growth!"
- icon = 'hyperstation/icons/obj/barber.dmi'
- icon_state = "hairaccelerator"
- amount_per_transfer_from_this = 1
- possible_transfer_amounts = list(5,10)
- list_reagents = list(/datum/reagent/barbers_aid = 50)
- volume = 50
-
-/obj/item/reagent_containers/spray/super_barbers_aid
- name = "super barber's aid"
- desc = "Causes SUPER rapid hair and facial hair growth!"
- icon = 'hyperstation/icons/obj/barber.dmi'
- icon_state = "hairaccelerator"
- amount_per_transfer_from_this = 1
- possible_transfer_amounts = list(5,10)
- list_reagents = list(/datum/reagent/concentrated_barbers_aid = 30)
- volume = 50
diff --git a/hyperstation/code/modules/surgery/organs/augments_arms.dm b/hyperstation/code/modules/surgery/organs/augments_arms.dm
index 8430fcac5..933b584eb 100644
--- a/hyperstation/code/modules/surgery/organs/augments_arms.dm
+++ b/hyperstation/code/modules/surgery/organs/augments_arms.dm
@@ -23,3 +23,11 @@
w_class = WEIGHT_CLASS_BULKY
sharpness = IS_SHARP_ACCURATE
attack_verb = list("slashed", "cut")
+
+
+// oracle port
+/obj/item/organ/cyberimp/arm/power_cord
+ name = "power cord implant"
+ desc = "An internal power cord hooked up to a battery. Useful if you run on volts."
+ contents = newlist(/obj/item/apc_powercord)
+ zone = "l_arm"
\ No newline at end of file
diff --git a/hyperstation/code/modules/vending/teavendomatic.dm b/hyperstation/code/modules/vending/teavendomatic.dm
deleted file mode 100644
index ba71bde81..000000000
--- a/hyperstation/code/modules/vending/teavendomatic.dm
+++ /dev/null
@@ -1,32 +0,0 @@
-/obj/machinery/vending/teavendomatic
- name = "\improper Tea Vend-O-Matic"
- desc = "A technological marvel, supposedly able to mix just the mixture you'd like to drink the moment you ask for one, this one is branded for tea and non-alcoholic beverages... Mostly."
- icon_state = "boozeomat"
- icon_deny = "boozeomat-deny"
- products = list(
- /obj/item/reagent_containers/food/drinks/mug/tea = 30,
- /obj/item/reagent_containers/food/drinks/bottle/wine = 5,
- /obj/item/reagent_containers/food/drinks/bottle/cognac = 5,
- /obj/item/reagent_containers/food/drinks/bottle/grappa = 5,
- /obj/item/reagent_containers/food/drinks/bottle/sake = 5,
- /obj/item/reagent_containers/food/drinks/bottle/orangejuice = 8,
- /obj/item/reagent_containers/food/drinks/bottle/tomatojuice = 8,
- /obj/item/reagent_containers/food/drinks/bottle/limejuice = 8,
- /obj/item/reagent_containers/food/drinks/bottle/grenadine = 4,
- /obj/item/reagent_containers/food/drinks/bottle/cream = 8,
- /obj/item/reagent_containers/food/drinks/soda_cans/tonic = 8,
- /obj/item/reagent_containers/food/drinks/soda_cans/cola = 8,
- /obj/item/reagent_containers/food/drinks/soda_cans/sodawater = 15,
- /obj/item/reagent_containers/food/drinks/drinkingglass = 30,
- /obj/item/reagent_containers/food/drinks/ice = 10,
- /obj/item/reagent_containers/food/drinks/drinkingglass/shotglass = 12,
- /obj/item/reagent_containers/food/drinks/flask = 3)
- contraband = list(/obj/item/reagent_containers/food/drinks/mug/tea = 12,)
- premium = list(/obj/item/reagent_containers/glass/bottle/ethanol = 4,
- /obj/item/reagent_containers/food/drinks/bottle/champagne = 5,
- /obj/item/reagent_containers/food/drinks/bottle/trappist = 5)
- product_slogans = "Keep a clear head and drink on.;It is a quite fine day to sit down and have a drink.;Remember to drink responsibly.;Products are assured to be GMO free."
- product_ads = "Stay Radiant.;Remember to balance your intake.;Radiikist brands are not permitted in sectors 34-A through 59-B.;Keep a level head.;Refreshments are to be taken in modicum.;Let the day's stress melt away.;Please, enjoy.;In-service since the sixth Era."
- req_access = list(ACCESS_BAR)
- //refill_canister = /obj/item/vending_refill/teavendomatic
- free = TRUE
diff --git a/hyperstation/code/obj/Kitchen compliances/reagentblender.dm b/hyperstation/code/obj/Kitchen compliances/reagentblender.dm
deleted file mode 100644
index 5837e7063..000000000
--- a/hyperstation/code/obj/Kitchen compliances/reagentblender.dm
+++ /dev/null
@@ -1,11 +0,0 @@
-/obj/machinery/reagentgrinder/reagentblender
- name = "Stand mixer"
- desc = "a stationary electric mixer for heavy-duty mixing various foods and other reagents."
- icon = 'hyperstation/icons/obj/machinery/reagentblender.dmi'
- icon_state = "mixer1"
-
-/obj/machinery/reagentgrinder/reagentblender/update_icon()
- if(beaker)
- icon_state = "mixer1"
- else
- icon_state = "mixer0"
\ No newline at end of file
diff --git a/hyperstation/code/obj/Lambent/gloves.dm b/hyperstation/code/obj/Lambent/gloves.dm
deleted file mode 100644
index 8cbb2df61..000000000
--- a/hyperstation/code/obj/Lambent/gloves.dm
+++ /dev/null
@@ -1,16 +0,0 @@
-/obj/item/clothing/gloves/lambent
- name = "Lambent's sleeves"
- desc = "An elegant sleeve worn from the shoulder down. Despite missing anything on the palm and fingers, it seems to cast small hardlight protections over the hands, like a glove."
- icon_state = "lambent"
- item_state = "lambent"
- icon = 'hyperstation/icons/obj/clothing/gloves.dmi'
- alternate_worn_icon = 'hyperstation/icons/mobs/gloves.dmi'
- armor = list("melee" = 50, "bullet" = 50, "laser" = 30, "energy" = 30, "bomb" = 30, "bio" = 30, "rad" = 30, "fire" = 20, "acid" = 60)
- resistance_flags = LAVA_PROOF|FIRE_PROOF|UNACIDABLE
- transfer_prints = FALSE
- strip_delay = 40
- body_parts_covered = ARMS|HANDS
- cold_protection = ARMS|HANDS
- min_cold_protection_temperature = FIRE_SUIT_MIN_TEMP_PROTECT
- siemens_coefficient = 0
- permeability_coefficient = 0.05
diff --git a/hyperstation/code/obj/Lambent/shoes.dm b/hyperstation/code/obj/Lambent/shoes.dm
deleted file mode 100644
index aff7e1271..000000000
--- a/hyperstation/code/obj/Lambent/shoes.dm
+++ /dev/null
@@ -1,14 +0,0 @@
-/obj/item/clothing/shoes/lambent
- name = "Lambent's heels"
- desc = "A sleek pair of leggings with high heels, gilded in golden strips. It seems to have an autobalancing matrix installed."
- icon_state = "lambent"
- item_state = "lambent"
- icon = 'hyperstation/icons/obj/clothing/shoes.dmi'
- alternate_worn_icon = 'hyperstation/icons/mobs/feet.dmi'
- body_parts_covered = LEGS|FEET
- cold_protection = LEGS|FEET
- min_cold_protection_temperature = FIRE_SUIT_MIN_TEMP_PROTECT
- strip_delay = 70
- resistance_flags = LAVA_PROOF|FIRE_PROOF|UNACIDABLE
- armor = list("melee" = 50, "bullet" = 50, "laser" = 30, "energy" = 30, "bomb" = 30, "bio" = 30, "rad" = 30, "fire" = 20, "acid" = 60)
- clothing_flags = NOSLIP
diff --git a/hyperstation/code/obj/Lambent/suit.dm b/hyperstation/code/obj/Lambent/suit.dm
deleted file mode 100644
index c9c990bcf..000000000
--- a/hyperstation/code/obj/Lambent/suit.dm
+++ /dev/null
@@ -1,13 +0,0 @@
-/obj/item/clothing/suit/lambent
- name = "Lambent's coat"
- desc = "A regal-esque coat outfitted with inert nanites, waiting to be activated at a moment's notice."
- icon = 'hyperstation/icons/obj/clothing/suits.dmi'
- //alternate_worn_icon = 'hyperstation/icons/mobs/suits.dmi'
- icon_state = "lambent"
- item_state = "lambent"
- body_parts_covered = CHEST|LEGS
- cold_protection = CHEST|GROIN|LEGS|ARMS
- min_cold_protection_temperature = FIRE_SUIT_MIN_TEMP_PROTECT
- strip_delay = 70
- resistance_flags = LAVA_PROOF|FIRE_PROOF|UNACIDABLE
- armor = list("melee" = 50, "bullet" = 50, "laser" = 30, "energy" = 30, "bomb" = 30, "bio" = 30, "rad" = 30, "fire" = 20, "acid" = 60)
diff --git a/hyperstation/code/obj/Lambent/uniform.dm b/hyperstation/code/obj/Lambent/uniform.dm
deleted file mode 100644
index 8fcd48a2b..000000000
--- a/hyperstation/code/obj/Lambent/uniform.dm
+++ /dev/null
@@ -1,14 +0,0 @@
-/obj/item/clothing/under/rank/lambent
- name = "Lambent's outfitting"
- desc = "A Hyperwoven outfitting meant for a Kinaris Lambent. It's gilded colors and ultratech weaving speak highly about status."
- icon = 'hyperstation/icons/obj/clothing/uniforms.dmi'
- //alternate_worn_icon = 'hyperstation/icons/mobs/uniforms.dmi'
- icon_state = "lambent"
- item_state = "lambent"
- armor = list("melee" = 50, "bullet" = 50, "laser" = 30, "energy" = 30, "bomb" = 30, "bio" = 30, "rad" = 30, "fire" = 20, "acid" = 60)
- resistance_flags = LAVA_PROOF|FIRE_PROOF|UNACIDABLE
- strip_delay = 50
- sensor_mode = SENSOR_COORDS
- random_sensor = FALSE
-
-//We'll add more alternative outfits here later. For now this'll be how it is!
diff --git a/hyperstation/code/obj/clothes.dm b/hyperstation/code/obj/clothes.dm
deleted file mode 100644
index da96e29ad..000000000
--- a/hyperstation/code/obj/clothes.dm
+++ /dev/null
@@ -1,7 +0,0 @@
-/obj/item/clothing/under/barber
- name = "barber's uniform"
- desc = "A fancy pink shirt paired with light-catching white pants. Yet to be blood- and puke-stained."
- icon = 'hyperstation/icons/obj/clothing/uniforms.dmi'
- //alternate_worn_icon = 'hyperstation/icons/mobs/uniforms.dmi'
- icon_state = "barber"
- item_state = "barber"
diff --git a/hyperstation/code/obj/condom.dm b/hyperstation/code/obj/condom.dm
index 727ff4739..2c3122fe2 100644
--- a/hyperstation/code/obj/condom.dm
+++ b/hyperstation/code/obj/condom.dm
@@ -115,7 +115,6 @@ obj/item/condom/update_icon()
return
if(!P.condom)
return
-
var/obj/item/condom/filled/C = new
P.linked_organ.reagents.trans_to(C, P.linked_organ.reagents.total_volume)
C.loc = loc
diff --git a/hyperstation/code/obj/farming/farming.dm b/hyperstation/code/obj/farming/farming.dm
index 8c203d78d..ad4671774 100644
--- a/hyperstation/code/obj/farming/farming.dm
+++ b/hyperstation/code/obj/farming/farming.dm
@@ -1,5 +1,5 @@
-/obj/item/reagent_containers/food/snacks/grown/wheat/
- var stacktype = /obj/item/stack/tile/hay
+/obj/item/reagent_containers/food/snacks/grown/wheat
+ var/stacktype = /obj/item/stack/tile/hay
var/tile_coefficient = 0.02 // same as grass
/obj/item/reagent_containers/food/snacks/grown/wheat/attack_self(mob/user)
diff --git a/hyperstation/code/obj/fleshlight.dm b/hyperstation/code/obj/fleshlight.dm
index 125c7ec34..421cfb8f6 100644
--- a/hyperstation/code/obj/fleshlight.dm
+++ b/hyperstation/code/obj/fleshlight.dm
@@ -45,11 +45,9 @@
inuse = 1
if(!(C == user)) //if we are targeting someone else.
C.visible_message("[user] is trying to use [src] on [C]'s penis.", "[user] is trying to use [src] on your penis.")
-
if(!do_mob(user, C, 3 SECONDS)) //3 second delay
inuse = 0
return
-
//checked if not used on yourself, if not, carry on.
playsound(src, 'sound/lewd/slaps.ogg', 30, 1, -1) //slapping sound
inuse = 0
@@ -57,27 +55,22 @@
C.visible_message("[user] pumps [src] on [C]'s penis.", "[user] pumps [src] up and down on your penis.")
else
user.visible_message("[user] pumps [src] on their penis.", "You pump the fleshlight on your penis.")
-
if(prob(30)) //30% chance to make them moan.
C.emote("moan")
-
C.do_jitter_animation()
C.adjustArousalLoss(20) //make the target more aroused.
- if (C.getArousalLoss() >= 100 && ishuman(C) && C.has_dna())
- C.mob_climax(forced_climax=TRUE) //make them cum if they are over the edge.
-
+ if(C.can_orgasm() && ishuman(C))
+ var/mob/living/carbon/human/user_human = C
+ user_human.mob_climax_outside(P, mb_time=0) // instant, because we already did a warmup
return
-
else
to_chat(user, "You don't see anywhere to use this on.")
-
inuse = 0
..()
//Hyperstation 13 portal fleshlight
//kinky!
-
/obj/item/portallight
name = "portal fleshlight"
desc = "A silver love(TM) fleshlight, used to stimulate someones penis, with bluespace tech that allows lovers to hump at a distance."
@@ -95,7 +88,6 @@
var/paired = 0
var/obj/item/portalunderwear
var/useable = FALSE
- var/option = ""
/obj/item/portallight/examine(mob/user)
. = ..()
@@ -104,136 +96,109 @@
else
. += "The device is paired, and awaiting input. "
-/obj/item/portallight/attack(mob/living/carbon/C, mob/living/user) //use portallight! nearly the same as the fleshlight apart from you have a buddy!
- var/obj/item/organ/genital/penis/P = C.getorganslot("penis")
-
+/obj/item/portallight/attack(mob/living/carbon/user, mob/living/holder)
if(inuse) //just to stop stacking and causing people to cum instantly
return
- if(!useable)
- to_chat(user, "It seems the device has failed or your partner is not wearing their device.")
-
- if(C == user)//if your using it on yourself, more options! otherwise, just fuck.
+ if(!UpdateUsability())
+ to_chat(holder, "\The [src] appears to be currently unusable.")
+ return
+ var/option = "Fuck"
+ if(user == holder)
option = input(usr, "Choose action", "Portal Fleshlight", "Fuck") in list("Fuck", "Lick", "Touch")
- else
- option = "Fuck"
-
- var/obj/item/organ/genital/G
- if(istype(portalunderwear.loc, /obj/item/organ/genital)) //Sanity check. Without this it will runtime error.
- G = portalunderwear.loc
- if(!G)
+ var/obj/item/organ/genital/target_genital = portalunderwear.loc
+ var/mob/living/carbon/human/target = target_genital.owner
+ var/obj/item/organ/genital/penis/P = user.getorganslot("penis")
+ if(option == "Fuck" && !P.is_exposed())
+ to_chat(holder, "You don't see anywhere to use this on.")
return
- var/mob/living/carbon/human/M = G.owner
-
- if(option == "Fuck"&&!P.is_exposed()) //we are trying to fuck with no penis!
- to_chat(user, "You don't see anywhere to use this on.")
- return
- else //other options dont need checks
- inuse = 1
- if(!(C == user)) //if we are targeting someone else.
- C.visible_message("[user] is trying to use [src] on [C]'s penis.", "[user] is trying to use [src] on your penis.")
-
- if(!do_mob(user, C, 3 SECONDS)) //3 second delay
- inuse = 0
- return
-
- //checked if not used on yourself, if not, carry on.
- if(option == "Fuck")
- playsound(src, 'sound/lewd/slaps.ogg', 30, 1, -1) //slapping sound for fuck.
-
- inuse = 0
- if(!(C == user))
- C.visible_message("[user] pumps [src] on [C]'s penis.", "[user] pumps [src] up and down on your penis.")
- else
- if(option == "Fuck")
- user.visible_message("[user] pumps [src] on their penis.", "You pump the fleshlight on your penis.")
- if(option == "Lick")
- user.visible_message("[user] licks into [src].", "You lick into [src].")
- if(option == "Touch")
- user.visible_message("[user] touches softly against [src].", "You touch softly on [src].")
-
-
- if(prob(30)) //30% chance to make your partner moan.
- M.emote("moan")
-
- if(option == "Fuck")// normal fuck
- to_chat(M, "You feel a [P.length] inch, [P.shape] shaped penis pumping through the portal into your [G.name].")//message your partner, and kinky!
- if(prob(30)) //30% chance to make them moan.
- C.emote("moan")
- if(prob(30)) //30% chance to make your partner moan.
- M.emote("moan")
- C.adjustArousalLoss(20)
- M.adjustArousalLoss(20)
- M.do_jitter_animation() //make your partner shake too!
-
- if (M.getArousalLoss() >= 100 && ishuman(M) && prob(5))//Why not have a probability to cum when someone's getting nailed with max arousal?~
- if(G.is_exposed()) //Oh yea, if vagina is not exposed, the climax will not cause a spill
- M.mob_climax_outside(G, spillage = TRUE)
- else
- M.mob_climax_outside(G, spillage = FALSE)
-
- if (C.getArousalLoss() >= 100 && ishuman(C) && C.has_dna())
- var/mob/living/carbon/human/O = C
-
- if( (P.condom == 1) || (P.sounding == 1)) //If coundomed and/or sounded, do not fire impreg chance
- O.mob_climax_partner(P, M, FALSE, FALSE, FALSE, TRUE)
- else //Else, fire impreg chance
- if(G.name == "vagina") //no more spontaneous impregnations through the butt!
- O.mob_climax_partner(P, M, FALSE, TRUE, FALSE, TRUE)
- else
- O.mob_climax_partner(P, M, FALSE, FALSE, FALSE, TRUE)
-
- if(option == "Lick")
- to_chat(M, "You feel a tongue lick you through the portal against your [G.name].")
- M.adjustArousalLoss(10)
- if(option == "Touch")
- to_chat(M, "You feel someone touching your [G.name] through the portal.")
- M.adjustArousalLoss(5)
-
+ /*
+ WARMUP START - prevents spam/instant climax
+ */
+ inuse = TRUE
+ if(user != holder)
+ user.visible_message("[holder] is trying to use [src] on [user]'s penis.",\
+ "[holder] is trying to use [src] on your penis.")
+ if(!do_mob(holder, user, 3 SECONDS))
+ inuse = FALSE
return
+ inuse = FALSE
+ /*
+ WARMUP END - proceed with the action
+ */
+ switch(option)
+ if("Fuck")
+ playsound(src, 'sound/lewd/slaps.ogg', 30, 1, -1)
+ if(user == holder)
+ holder.visible_message("[holder] pumps [src] on their penis.",
+ "You pump the fleshlight on your penis.")
+ else
+ user.visible_message("[holder] pumps [src] on [user]'s penis.",\
+ "[holder] pumps [src] up and down on your penis.")
+ to_chat(target, "You feel a [P.length] inch, [P.shape] shaped penis pumping through the portal into your [target_genital.name].")
+ if(prob(30))
+ user.emote("moan")
+ user.adjustArousalLoss(20)
+ target.adjustArousalLoss(20)
+ target.do_jitter_animation()
+ if(target.can_orgasm() && prob(5))
+ target.mob_climax_outside(target_genital, spillage=target_genital.is_exposed())
+ if(user.can_orgasm())
+ var/mob/living/carbon/human/O = user
+ var/impreg_chance = target_genital.name == "vagina" && !P.condom && !P.sounding
+ if(O.mob_climax_in_partner(P, target, spillage=FALSE, remote=TRUE) && impreg_chance)
+ target.impregnate(by=O)
+ if("Lick")
+ holder.visible_message("[holder] licks into [src].",\
+ "You lick into [src].")
+ to_chat(target, "You feel a tongue lick you through the portal against your [target_genital.name].")
+ target.adjustArousalLoss(10)
+ if("Touch")
+ holder.visible_message("[holder] touches softly against [src].",\
+ "You touch softly on [src].")
+ to_chat(target, "You feel someone touching your [target_genital.name] through the portal.")
+ target.adjustArousalLoss(5)
+ if(prob(30))
+ target.emote("moan")
..()
/obj/item/portallight/proc/updatesleeve()
//get their looks and vagina colour!
- cut_overlays()//remove current overlays
-
- var/obj/item/organ/genital/G
- if(istype(portalunderwear.loc, /obj/item/organ/genital)) //Sanity check. Without this it will runtime.
- G = portalunderwear.loc
- if(!G)
- useable = FALSE
+ cut_overlays()
+ if(!UpdateUsability())
return
+ var/obj/item/organ/genital/G = portalunderwear.loc
+ var/mob/living/carbon/human/H = G.owner // H is verified by UpdateUsability()
+ var/sleeve_species = "normal"
+ switch(H.dna.species.name)
+ if("Lizardperson")
+ sleeve_species = "lizard"
+ if("Slimeperson")
+ sleeve_species = "slime"
+ if("Avian")
+ sleeve_species = "avian"
+ sleeve = mutable_appearance('hyperstation/icons/obj/fleshlight.dmi', "portal_sleeve_[sleeve_species]")
+ sleeve.color = "#" + H.dna.features["mcolor"]
+ add_overlay(sleeve)
+ if(G.name == "vagina")
+ organ = mutable_appearance('hyperstation/icons/obj/fleshlight.dmi', "portal_vag")
+ organ.color = portalunderwear.loc.color
+ if(G.name == "anus")
+ organ = mutable_appearance('hyperstation/icons/obj/fleshlight.dmi', "portal_anus")
+ organ.color = "#" + H.dna.features["mcolor"]
+ add_overlay(organ)
- var/mob/living/carbon/human/H = G.owner
+/obj/item/portallight/proc/UpdateUsability()
+ var/useable = FALSE
+ if(portalunderwear && istype(portalunderwear.loc, /obj/item/organ/genital))
+ var/obj/item/organ/genital/loc_genitals = portalunderwear.loc
+ if(loc_genitals.owner && ishuman(loc_genitals.owner))
+ useable = TRUE
+ src.useable = useable
+ return useable
- if(H) //if the portal panties are on someone.
- sleeve = mutable_appearance('hyperstation/icons/obj/fleshlight.dmi', "portal_sleeve_normal")
- if(H.dna.species.name == "Lizardperson") // lizard nerd
- sleeve = mutable_appearance('hyperstation/icons/obj/fleshlight.dmi', "portal_sleeve_lizard")
-
- if(H.dna.species.name == "Slimeperson") // slime nerd
- sleeve = mutable_appearance('hyperstation/icons/obj/fleshlight.dmi', "portal_sleeve_slime")
-
- if(H.dna.species.name == "Avian") // bird nerd
- sleeve = mutable_appearance('hyperstation/icons/obj/fleshlight.dmi', "portal_sleeve_avian")
-
- sleeve.color = "#" + H.dna.features["mcolor"]
- add_overlay(sleeve)
-
- if(G.name == "vagina")
- organ = mutable_appearance('hyperstation/icons/obj/fleshlight.dmi', "portal_vag")
- organ.color = portalunderwear.loc.color
- if(G.name == "anus")
- organ = mutable_appearance('hyperstation/icons/obj/fleshlight.dmi', "portal_anus")
- organ.color = "#" + H.dna.features["mcolor"]
-
- useable = TRUE
- add_overlay(organ)
- else
- useable = FALSE
//Hyperstation 13 portal underwear
//can be attached to vagina or anus, just like the vibrator, still requires pairing with the portallight
-
/obj/item/portalpanties
name = "portal panties"
desc = "A silver love(TM) pair of portal underwear, with bluespace tech allows lovers to hump at a distance. Needs to be paired with a portal fleshlight before use."
@@ -252,7 +217,6 @@
else
. += "The device is paired, and awaiting attachment. "
-
/obj/item/portalpanties/attackby(obj/item/I, mob/living/user) //pairing
if(istype(I, /obj/item/portallight))
var/obj/item/portallight/P = I
@@ -268,11 +232,9 @@
..() //just allows people to hit it with other objects, if they so wished.
/obj/item/portalpanties/attack(mob/living/carbon/C, mob/living/user)
-
if(!portallight) //we arent paired yet! noobie trap, let them know.
to_chat(user, "[src] can only be attached once paired with a portal fleshlight.")
return
-
var/obj/item/organ/genital/picked_organ
var/mob/living/carbon/human/S = user
var/mob/living/carbon/human/T = C
@@ -282,21 +244,17 @@
"[user] is trying to put [src] on you!")
if(!do_mob(user, C, 3 SECONDS))//warn them and have a delay of 5 seconds to apply.
return
-
if((picked_organ.name == "vagina")||(picked_organ.name == "anus")) //only fits on a vagina or anus
-
src.shapetype = picked_organ.name
if(!picked_organ.equipment)
to_chat(user, "You wrap [src] around [T]'s [picked_organ.name].")
else
to_chat(user, "They already have [picked_organ.equipment.name] there.")
return
-
if(!user.transferItemToLoc(src, picked_organ)) //check if you can put it in
return
src.attached = TRUE
picked_organ.equipment = src
-
var/obj/item/portallight/P = portallight
//now we need to send what they look like, but saddly if the person changes colour for what ever reason, it wont update. but dont tell people shh.
if(P) //just to make sure
@@ -312,6 +270,7 @@
var/obj/item/portallight/P = portallight
P.updatesleeve()
+
/obj/item/storage/box/portallight
name = "Portal Fleshlight and Underwear"
icon = 'hyperstation/icons/obj/fleshlight.dmi'
diff --git a/hyperstation/code/obj/items/lorebooks.dm b/hyperstation/code/obj/items/lorebooks.dm
index 07fc09ee1..700089f55 100644
--- a/hyperstation/code/obj/items/lorebooks.dm
+++ b/hyperstation/code/obj/items/lorebooks.dm
@@ -156,7 +156,7 @@
Chapter 4
About Layenia Station
- After reading this far in, it may become apparent that Layenia does not reflect the values of Kinaris in many ways. From the technological progress to the surroundings, it may seem like Layenia Station is far behind its time. And that’s an entirely correct notion, all thanks to the standards of Kinaris Uplifting.
+ After reading this far in, it may become apparent that Layenia does not reflect the values of Kinaris in many ways. From the technological progress to the surroundings, it may seem like Layenia Station is far behind its time. And that’s an entirely correct notion, all thanks to the standards of Kinaris Uplifting.
As it stands right now, Layenia Station uses a fabricated Engram to replicate that of its former employers and owners. The star was previously given to humanity prior to the first attempt at Uplifting, but it was taken back shortly after things went south, and given open borders to the Milky Way. The Engram in particular mimics a lot of Nanotrasen-esque technology, which makes Layenia Station one of the most low-tech Kinaris stations to exist out there to date!
@@ -166,7 +166,7 @@
-
+