mirror of
https://github.com/ParadiseSS13/Paradise.git
synced 2026-07-11 23:23:28 +01:00
Merge remote-tracking branch 'ParadiseSS13/master' into maze-generator
This commit is contained in:
@@ -2194,7 +2194,7 @@
|
||||
switch(punishment)
|
||||
// These smiting types are valid for all living mobs
|
||||
if("Lightning bolt")
|
||||
M.electrocute_act(5, "Lightning Bolt", safety = TRUE, override = TRUE)
|
||||
M.electrocute_act(5, "Lightning Bolt", flags = SHOCK_NOGLOVES)
|
||||
playsound(get_turf(M), 'sound/magic/lightningshock.ogg', 50, 1, -1)
|
||||
M.adjustFireLoss(75)
|
||||
M.Weaken(5)
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
|
||||
|
||||
//This is a list of words which are ignored by the parser when comparing message contents for names. MUST BE IN LOWER CASE!
|
||||
GLOBAL_LIST_INIT(adminhelp_ignored_words, list("unknown","the","a","an","of","monkey","alien","as"))
|
||||
GLOBAL_LIST_INIT(adminhelp_ignored_words, list("unknown", "the", "a", "an", "of", "monkey", "alien", "as"))
|
||||
|
||||
/client/verb/adminhelp()
|
||||
set category = "Admin"
|
||||
@@ -12,27 +10,28 @@ GLOBAL_LIST_INIT(adminhelp_ignored_words, list("unknown","the","a","an","of","mo
|
||||
to_chat(src, "<font color='red'>Error: Admin-PM: You cannot send adminhelps (Muted).</font>")
|
||||
return
|
||||
|
||||
adminhelped = 1 //Determines if they get the message to reply by clicking the name.
|
||||
adminhelped = TRUE //Determines if they get the message to reply by clicking the name.
|
||||
|
||||
var/msg
|
||||
var/list/type = list("Mentorhelp","Adminhelp")
|
||||
var/selected_type = input("Pick a category.", "Admin Help", null, null) as null|anything in type
|
||||
var/list/type = list("Mentorhelp", "Adminhelp")
|
||||
var/selected_type = input("Pick a category.", "Admin Help") as null|anything in type
|
||||
if(selected_type)
|
||||
msg = clean_input("Please enter your message.", "Admin Help", null)
|
||||
msg = clean_input("Please enter your message.", selected_type)
|
||||
|
||||
//clean the input msg
|
||||
if(!msg)
|
||||
return
|
||||
|
||||
if(handle_spam_prevention(msg, MUTE_ADMINHELP, OOC_COOLDOWN))
|
||||
return
|
||||
|
||||
msg = sanitize_simple(copytext(msg,1,MAX_MESSAGE_LEN))
|
||||
if(!msg) return
|
||||
msg = sanitize_simple(copytext(msg, 1, MAX_MESSAGE_LEN))
|
||||
if(!msg) // No message after sanitisation
|
||||
return
|
||||
|
||||
if(selected_type == "Mentorhelp")
|
||||
SSmentor_tickets.newHelpRequest(src, msg)
|
||||
SSmentor_tickets.newHelpRequest(src, msg) // Mhelp
|
||||
else
|
||||
SStickets.newHelpRequest(src, msg)
|
||||
SStickets.newHelpRequest(src, msg) // Ahelp
|
||||
|
||||
//show it to the person adminhelping too
|
||||
to_chat(src, "<span class='boldnotice'>[selected_type]</b>: [msg]</span>")
|
||||
@@ -54,7 +53,7 @@ GLOBAL_LIST_INIT(adminhelp_ignored_words, list("unknown","the","a","an","of","mo
|
||||
var/inactive_mentors = mentorcount[3]
|
||||
|
||||
if(active_mentors <= 0)
|
||||
if(inactive_mentors > 0)
|
||||
if(inactive_mentors)
|
||||
alerttext = " | **ALL MENTORS AFK**"
|
||||
else
|
||||
alerttext = " | **NO MENTORS ONLINE**"
|
||||
|
||||
@@ -743,11 +743,11 @@ GLOBAL_PROTECT(AdminProcCallSpamPrevention)
|
||||
|
||||
for(var/obj/machinery/power/rad_collector/Rad in GLOB.machines)
|
||||
if(Rad.anchored)
|
||||
if(!Rad.P)
|
||||
var/obj/item/tank/plasma/Plasma = new/obj/item/tank/plasma(Rad)
|
||||
if(!Rad.loaded_tank)
|
||||
var/obj/item/tank/internals/plasma/Plasma = new/obj/item/tank/internals/plasma(Rad)
|
||||
Plasma.air_contents.toxins = 70
|
||||
Rad.drainratio = 0
|
||||
Rad.P = Plasma
|
||||
Rad.loaded_tank = Plasma
|
||||
Plasma.loc = Rad
|
||||
|
||||
if(!Rad.active)
|
||||
|
||||
@@ -133,7 +133,7 @@ GLOBAL_VAR_INIT(sent_syndicate_infiltration_team, 0)
|
||||
new_syndicate_infiltrator.mind_initialize()
|
||||
new_syndicate_infiltrator.mind.assigned_role = "Syndicate Infiltrator"
|
||||
new_syndicate_infiltrator.mind.special_role = "Syndicate Infiltrator"
|
||||
new_syndicate_infiltrator.mind.offstation_role = TRUE //they can flee to z2 so make them inelligible as antag targets
|
||||
new_syndicate_infiltrator.mind.offstation_role = TRUE //they can flee to the syndicate base on the admin level so make them inelligible as antag targets
|
||||
SSticker.mode.traitors |= new_syndicate_infiltrator.mind //Adds them to extra antag list
|
||||
new_syndicate_infiltrator.equip_syndicate_infiltrator(syndicate_leader_selected, uplink_tc, is_mgmt)
|
||||
return new_syndicate_infiltrator
|
||||
|
||||
@@ -282,18 +282,14 @@
|
||||
return 1
|
||||
|
||||
/datum/admins/proc/makeAliens()
|
||||
var/datum/event/alien_infestation/E = new /datum/event/alien_infestation
|
||||
|
||||
var/antnum = input(owner, "How many aliens you want to create? Enter 0 to cancel.","Amount:", 0) as num
|
||||
if(!antnum || antnum <= 0)
|
||||
return
|
||||
var/datum/event/alien_infestation/E = new /datum/event/alien_infestation
|
||||
E.spawncount = antnum
|
||||
log_admin("[key_name(owner)] tried making Aliens with One-Click-Antag")
|
||||
message_admins("[key_name_admin(owner)] tried making Aliens with One-Click-Antag")
|
||||
|
||||
E.spawncount = antnum
|
||||
// TODO The fact we have to do this rather than just have events start
|
||||
// when we ask them to, is bad.
|
||||
E.processing = TRUE
|
||||
return TRUE
|
||||
|
||||
/*
|
||||
|
||||
@@ -193,7 +193,7 @@ GLOBAL_VAR_INIT(sent_strike_team, 0)
|
||||
|
||||
equip_to_slot_or_del(new /obj/item/melee/energy/sword/saber(src), slot_l_store)
|
||||
equip_to_slot_or_del(new /obj/item/shield/energy(src), slot_r_store)
|
||||
equip_to_slot_or_del(new /obj/item/tank/emergency_oxygen/double/full(src), slot_s_store)
|
||||
equip_to_slot_or_del(new /obj/item/tank/internals/emergency_oxygen/double(src), slot_s_store)
|
||||
equip_to_slot_or_del(new /obj/item/gun/projectile/revolver/mateba(src), slot_belt)
|
||||
equip_to_slot_or_del(new /obj/item/gun/energy/pulse(src), slot_r_hand)
|
||||
|
||||
|
||||
@@ -49,7 +49,7 @@ GLOBAL_VAR_INIT(vox_tick, 1)
|
||||
equip_to_slot_or_del(new /obj/item/gun/dartgun/vox/medical, slot_r_hand)
|
||||
|
||||
equip_to_slot_or_del(new /obj/item/clothing/mask/breath/vox(src), slot_wear_mask)
|
||||
equip_to_slot_or_del(new /obj/item/tank/nitrogen(src), slot_back)
|
||||
equip_to_slot_or_del(new /obj/item/tank/internals/nitrogen(src), slot_back)
|
||||
equip_to_slot_or_del(new /obj/item/flashlight(src), slot_r_store)
|
||||
|
||||
var/obj/item/card/id/syndicate/vox/W = new(src)
|
||||
|
||||
@@ -1,75 +0,0 @@
|
||||
/**
|
||||
* # Contractor antagonist datum
|
||||
*
|
||||
* A variant of the Traitor, Contractors rely on kidnapping crew members to earn TC.
|
||||
*
|
||||
* Contractors are supplied with some unique items
|
||||
* and three random low cost contraband items to help kickstart their contracts.
|
||||
* A Traitor may become a Contractor if given the chance (random).
|
||||
* They will forfeit all their initial TC and receive the above items.
|
||||
* The opportunity to become a Contractor goes away after some time or if the traitor spends any initial TC.
|
||||
*/
|
||||
/datum/antagonist/traitor/contractor
|
||||
name = "Contractor"
|
||||
// Settings
|
||||
/// How many telecrystals a traitor must forfeit to become a contractor.
|
||||
var/tc_cost = 20
|
||||
/// How long a traitor's chance to become a contractor lasts before going away. In deciseconds.
|
||||
var/offer_duration = 10 MINUTES
|
||||
// Variables
|
||||
/// The associated contractor uplink. Only present if the offer was accepted.
|
||||
var/obj/item/contractor_uplink/contractor_uplink = null
|
||||
/// world.time at which the offer will expire.
|
||||
var/offer_deadline = -1
|
||||
|
||||
/datum/antagonist/traitor/contractor/finalize_traitor()
|
||||
..()
|
||||
// Setup the vars and contractor stuff in the uplink
|
||||
var/obj/item/uplink/hidden/U = owner.find_syndicate_uplink()
|
||||
if(!U)
|
||||
stack_trace("Potential contractor [owner] spawned without a hidden uplink!")
|
||||
return
|
||||
U.contractor = src
|
||||
offer_deadline = world.time + offer_duration
|
||||
|
||||
// Greet them with the unique message
|
||||
var/greet_text = "Contractors forfeit [tc_cost] telecrystals for the privilege of taking on kidnapping contracts for credit and TC payouts that can add up to more than the normal starting amount of TC.<br>"\
|
||||
+ "If you are interested, simply access your hidden uplink and select the \"Contracting Opportunity\" tab for more information.<br>"
|
||||
to_chat(owner.current, "<b><font size=4 color=red>You have been offered a chance to become a Contractor.</font></b><br>")
|
||||
to_chat(owner.current, "<font color=red>[greet_text]</font>")
|
||||
to_chat(owner.current, "<b><i><font color=red>This offer will expire in 10 minutes starting now (expiry time: <u>[station_time_timestamp(time = offer_deadline)]</u>).</font></i></b>")
|
||||
|
||||
/datum/antagonist/traitor/contractor/update_traitor_icons_added(datum/mind/traitor_mind)
|
||||
if(!contractor_uplink)
|
||||
return ..()
|
||||
var/hud_name = "hudcontractor"
|
||||
if(locate(/datum/objective/hijack) in owner.objectives)
|
||||
hud_name = "hudhijackcontractor"
|
||||
var/datum/atom_hud/antag/traitorhud = GLOB.huds[ANTAG_HUD_TRAITOR]
|
||||
traitorhud.join_hud(owner.current, null)
|
||||
set_antag_hud(owner.current, hud_name)
|
||||
|
||||
/**
|
||||
* Accepts the offer to be a contractor if possible.
|
||||
*/
|
||||
/datum/antagonist/traitor/contractor/proc/become_contractor(mob/living/carbon/human/M, obj/item/uplink/U)
|
||||
if(contractor_uplink || !istype(M))
|
||||
return
|
||||
if(U.uses < tc_cost || world.time >= offer_deadline)
|
||||
var/reason = (U.uses < tc_cost) ? \
|
||||
"you have insufficient telecrystals ([tc_cost] needed in total)" : \
|
||||
"the deadline has passed"
|
||||
to_chat(M, "<span class='warning'>You can no longer become a contractor as [reason].</span>")
|
||||
return
|
||||
|
||||
// Give the kit
|
||||
var/obj/item/storage/box/syndie_kit/contractor/B = new(M)
|
||||
M.put_in_hands(B)
|
||||
contractor_uplink = locate(/obj/item/contractor_uplink, B)
|
||||
contractor_uplink.hub = new(M.mind, contractor_uplink)
|
||||
|
||||
// Update AntagHUD icon
|
||||
update_traitor_icons_added(owner)
|
||||
|
||||
// Remove the TC
|
||||
U.uses -= tc_cost
|
||||
@@ -17,7 +17,7 @@
|
||||
EXTRACTION_DIFFICULTY_HARD = 40,
|
||||
)
|
||||
/// Maximum variation a single contract's TC reward can have upon generation.
|
||||
/// In other words: final_reward = CEILING((tc_threshold / num_contracts) * (1 + (rand(-100, 100) / 100) * tc_variation), 1)
|
||||
/// In other words: final_reward = CEILING((tc_threshold / num_contracts) * (1 - (rand(0, 100) / 100) * tc_variation), 1)
|
||||
var/tc_variation = 0.25
|
||||
/// TC reward multiplier if the target was extracted DEAD. Should be a penalty so between 0 and 1.
|
||||
/// The final amount is rounded up.
|
||||
@@ -98,9 +98,6 @@
|
||||
C.reward_tc = list(null, null, null)
|
||||
for(var/difficulty in EXTRACTION_DIFFICULTY_EASY to EXTRACTION_DIFFICULTY_HARD)
|
||||
var/amount_tc = calculate_tc_reward(num_to_generate, difficulty)
|
||||
// Bump up the TC reward a little if it's too close to the lower difficulty's reward
|
||||
if(difficulty > EXTRACTION_DIFFICULTY_EASY)
|
||||
amount_tc = max(amount_tc, C.reward_tc[difficulty - 1] + (difficulty - 1))
|
||||
C.reward_tc[difficulty] = amount_tc
|
||||
total_earnable_tc[difficulty] += amount_tc
|
||||
// Add to lists
|
||||
@@ -111,11 +108,10 @@
|
||||
for(var/difficulty in EXTRACTION_DIFFICULTY_EASY to EXTRACTION_DIFFICULTY_HARD)
|
||||
var/total = total_earnable_tc[difficulty]
|
||||
var/missing = difficulty_tc_thresholds[difficulty] - total
|
||||
if(missing <= 0)
|
||||
continue
|
||||
// Just add the missing TC to a random contract
|
||||
var/datum/syndicate_contract/C = pick(contracts)
|
||||
C.reward_tc[difficulty] += missing
|
||||
// Increment the TC payout of a random contract till we're even
|
||||
while(missing-- > 0)
|
||||
var/datum/syndicate_contract/C = pick(contracts)
|
||||
C.reward_tc[difficulty]++
|
||||
|
||||
/**
|
||||
* Generates an amount of TC to be used as a contract reward for the given difficulty.
|
||||
@@ -126,7 +122,7 @@
|
||||
*/
|
||||
/datum/contractor_hub/proc/calculate_tc_reward(total_contracts, difficulty = EXTRACTION_DIFFICULTY_EASY)
|
||||
ASSERT(total_contracts > 0)
|
||||
return CEILING((difficulty_tc_thresholds[difficulty] / total_contracts) * (1 + (rand(-100, 100) / 100) * tc_variation), 1)
|
||||
return FLOOR((difficulty_tc_thresholds[difficulty] / total_contracts) * (1 - (rand(0, 100) / 100) * tc_variation), 1)
|
||||
|
||||
/**
|
||||
* Called when a [/datum/syndicate_contract] has been completed.
|
||||
@@ -180,4 +176,4 @@
|
||||
* * M - The mob.
|
||||
*/
|
||||
/datum/contractor_hub/proc/is_user_authorized(mob/living/carbon/M)
|
||||
return M.mind.has_antag_datum(/datum/antagonist/traitor/contractor)
|
||||
return LAZYACCESS(GLOB.contractors, M.mind) && M.mind == owner
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
cost = 3
|
||||
// Settings
|
||||
/// How long a contractor must wait before calling another blackout, in deciseconds.
|
||||
var/static/cooldown = 15 MINUTES
|
||||
var/static/cooldown = 45 MINUTES
|
||||
// Variables
|
||||
/// Static cooldown variable for blackouts.
|
||||
var/static/next_blackout = -1
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
/**
|
||||
* # Syndicate Contract
|
||||
*
|
||||
* Describes a contract that can be completed by a [/datum/antagonist/traitor/contractor].
|
||||
* Describes a contract that can be completed by a Contractor.
|
||||
*/
|
||||
/datum/syndicate_contract
|
||||
// Settings
|
||||
@@ -320,6 +320,7 @@
|
||||
*/
|
||||
/datum/syndicate_contract/proc/target_received(mob/living/M, obj/effect/portal/redspace/contractor/P)
|
||||
INVOKE_ASYNC(src, .proc/clean_up)
|
||||
add_attack_logs(owning_hub.owner.current, M, "extracted to Syndicate Jail")
|
||||
complete(M.stat == DEAD)
|
||||
handle_target_experience(M, P)
|
||||
|
||||
@@ -408,13 +409,13 @@
|
||||
|
||||
// Give some species the necessary to survive. Courtesy of the Syndicate.
|
||||
if(istype(H))
|
||||
var/obj/item/tank/emergency_oxygen/tank
|
||||
var/obj/item/tank/internals/emergency_oxygen/tank
|
||||
var/obj/item/clothing/mask/breath/mask
|
||||
if(isvox(H))
|
||||
tank = new /obj/item/tank/emergency_oxygen/nitrogen(H)
|
||||
tank = new /obj/item/tank/internals/emergency_oxygen/nitrogen(H)
|
||||
mask = new /obj/item/clothing/mask/breath/vox(H)
|
||||
else if(isplasmaman(H))
|
||||
tank = new /obj/item/tank/emergency_oxygen/plasma(H)
|
||||
tank = new /obj/item/tank/internals/emergency_oxygen/plasma(H)
|
||||
mask = new /obj/item/clothing/mask/breath(H)
|
||||
|
||||
if(tank)
|
||||
|
||||
@@ -12,8 +12,6 @@
|
||||
var/should_equip = TRUE
|
||||
var/traitor_kind = TRAITOR_HUMAN
|
||||
var/list/assigned_targets = list() // This includes assassinate as well as steal objectives. prevents duplicate objectives
|
||||
/// Whether the traitor can specialize into a contractor.
|
||||
var/is_contractor = FALSE
|
||||
|
||||
/datum/antagonist/traitor/on_gain()
|
||||
if(owner.current && isAI(owner.current))
|
||||
@@ -251,14 +249,15 @@
|
||||
|
||||
|
||||
/datum/antagonist/traitor/proc/update_traitor_icons_added(datum/mind/traitor_mind)
|
||||
var/is_contractor = LAZYACCESS(GLOB.contractors, traitor_mind)
|
||||
if(locate(/datum/objective/hijack) in owner.objectives)
|
||||
var/datum/atom_hud/antag/hijackhud = GLOB.huds[ANTAG_HUD_TRAITOR]
|
||||
hijackhud.join_hud(owner.current, null)
|
||||
set_antag_hud(owner.current, "hudhijack")
|
||||
set_antag_hud(owner.current, is_contractor ? "hudhijackcontractor" : "hudhijack")
|
||||
else
|
||||
var/datum/atom_hud/antag/traitorhud = GLOB.huds[ANTAG_HUD_TRAITOR]
|
||||
traitorhud.join_hud(owner.current, null)
|
||||
set_antag_hud(owner.current, "hudsyndicate")
|
||||
set_antag_hud(owner.current, is_contractor ? "hudcontractor" : "hudsyndicate")
|
||||
|
||||
|
||||
/datum/antagonist/traitor/proc/update_traitor_icons_removed(datum/mind/traitor_mind)
|
||||
@@ -411,8 +410,3 @@
|
||||
<b>The code responses were:</b> <span class='redtext'>[responses]</span><br>"
|
||||
|
||||
return message
|
||||
|
||||
/datum/antagonist/traitor/specialization(datum/mind/new_owner)
|
||||
if(isAI(new_owner?.current) || !is_contractor)
|
||||
return ..()
|
||||
return new /datum/antagonist/traitor/contractor
|
||||
|
||||
@@ -110,7 +110,7 @@
|
||||
var/list/possible_areas = list()
|
||||
//setup, sets all station areas (and subtypes) to weight 1
|
||||
for(var/A in GLOB.the_station_areas)
|
||||
if(A == /area/holodeck) //don't allow holodeck areas as possible spawns since it will allow it to spawn in the holodeck rooms on z2 as well
|
||||
if(A == /area/holodeck) //don't allow holodeck areas as possible spawns since it will allow it to spawn in the holodeck rooms on CC level as well
|
||||
continue
|
||||
if(A in possible_areas)
|
||||
continue
|
||||
|
||||
@@ -479,3 +479,4 @@ GLOBAL_DATUM_INIT(_preloader, /datum/dmm_suite/preloader, new())
|
||||
|
||||
/turf/template_noop
|
||||
name = "Turf Passthrough"
|
||||
icon_state = "noop"
|
||||
|
||||
@@ -27,3 +27,154 @@
|
||||
spawn(1)
|
||||
W.loc = get_step(W, dir)
|
||||
water_timer = addtimer(CALLBACK(src, .proc/drip), water_frequency, TIMER_STOPPABLE)
|
||||
|
||||
/turf/simulated/floor/beach/away
|
||||
name = "Beach"
|
||||
icon = 'icons/misc/beach.dmi'
|
||||
var/water_overlay_image = null
|
||||
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
|
||||
planetary_atmos = TRUE
|
||||
|
||||
/turf/simulated/floor/beach/away/Initialize(mapload)
|
||||
. = ..()
|
||||
if(water_overlay_image)
|
||||
var/image/overlay_image = image('icons/misc/beach.dmi', icon_state = water_overlay_image, layer = ABOVE_MOB_LAYER)
|
||||
overlay_image.plane = GAME_PLANE
|
||||
overlays += overlay_image
|
||||
|
||||
/turf/simulated/floor/beach/away/sand
|
||||
name = "Sand"
|
||||
icon_state = "desert"
|
||||
mouse_opacity = MOUSE_OPACITY_ICON
|
||||
baseturf = /turf/simulated/floor/beach/away/sand
|
||||
|
||||
/turf/simulated/floor/beach/away/sand/Initialize(mapload)
|
||||
. = ..() //adds some aesthetic randomness to the beach sand
|
||||
icon_state = pick("desert", "desert0", "desert1", "desert2", "desert3", "desert4")
|
||||
|
||||
/turf/simulated/floor/beach/away/sand/dense //for boundary "walls"
|
||||
density = TRUE
|
||||
baseturf = /turf/simulated/floor/beach/away/sand/dense
|
||||
|
||||
/turf/simulated/floor/beach/away/coastline
|
||||
name = "Coastline"
|
||||
//icon = 'icons/misc/beach2.dmi'
|
||||
//icon_state = "sandwater"
|
||||
icon_state = "beach"
|
||||
water_overlay_image = "water_coast"
|
||||
baseturf = /turf/simulated/floor/beach/away/coastline
|
||||
|
||||
/turf/simulated/floor/beach/away/coastline/dense //for boundary "walls"
|
||||
density = TRUE
|
||||
baseturf = /turf/simulated/floor/beach/away/coastline/dense
|
||||
|
||||
/turf/simulated/floor/beach/away/water
|
||||
name = "Shallow Water"
|
||||
icon_state = "seashallow"
|
||||
water_overlay_image = "water_shallow"
|
||||
var/obj/machinery/poolcontroller/linkedcontroller = null
|
||||
baseturf = /turf/simulated/floor/beach/away/water
|
||||
|
||||
/turf/simulated/floor/beach/away/water/Entered(atom/movable/AM, atom/OldLoc)
|
||||
. = ..()
|
||||
if(!linkedcontroller)
|
||||
return
|
||||
if(ismob(AM))
|
||||
linkedcontroller.mobinpool += AM
|
||||
|
||||
/turf/simulated/floor/beach/away/water/Exited(atom/movable/AM, atom/newloc)
|
||||
. = ..()
|
||||
if(!linkedcontroller)
|
||||
return
|
||||
if(ismob(AM))
|
||||
linkedcontroller.mobinpool -= AM
|
||||
|
||||
/turf/simulated/floor/beach/away/water/InitializedOn(atom/A)
|
||||
if(!linkedcontroller)
|
||||
return
|
||||
if(istype(A, /obj/effect/decal/cleanable)) // Better a typecheck than looping through thousands of turfs everyday
|
||||
linkedcontroller.decalinpool += A
|
||||
|
||||
/turf/simulated/floor/beach/away/water/dense //for boundary "walls"
|
||||
density = TRUE
|
||||
baseturf = /turf/simulated/floor/beach/away/water/dense
|
||||
|
||||
/turf/simulated/floor/beach/away/water/edge_drop
|
||||
name = "Water"
|
||||
icon_state = "seadrop"
|
||||
water_overlay_image = "water_drop"
|
||||
baseturf = /turf/simulated/floor/beach/away/water/edge_drop
|
||||
|
||||
/turf/simulated/floor/beach/away/water/drop
|
||||
name = "Water"
|
||||
icon = 'icons/turf/floors/seadrop.dmi'
|
||||
icon_state = "seadrop"
|
||||
water_overlay_image = null
|
||||
smooth = SMOOTH_TRUE
|
||||
canSmoothWith = list(
|
||||
/turf/simulated/floor/beach/away/water/drop, /turf/simulated/floor/beach/away/water/drop/dense,
|
||||
/turf/simulated/floor/beach/away/water, /turf/simulated/floor/beach/away/water/dense,
|
||||
/turf/simulated/floor/beach/away/water/edge_drop)
|
||||
var/obj/effect/beach_drop_overlay/water_overlay
|
||||
baseturf = /turf/simulated/floor/beach/away/water/drop
|
||||
|
||||
/turf/simulated/floor/beach/away/water/drop/Initialize(mapload)
|
||||
. = ..()
|
||||
water_overlay = new(src)
|
||||
|
||||
/turf/simulated/floor/beach/away/water/drop/Destroy()
|
||||
QDEL_NULL(water_overlay)
|
||||
return ..()
|
||||
|
||||
/obj/effect/beach_drop_overlay
|
||||
name = "Water"
|
||||
icon = 'icons/turf/floors/seadrop-o.dmi'
|
||||
layer = MOB_LAYER + 0.1
|
||||
smooth = SMOOTH_TRUE
|
||||
anchored = 1
|
||||
canSmoothWith = list(
|
||||
/turf/simulated/floor/beach/away/water/drop, /turf/simulated/floor/beach/away/water/drop/dense,
|
||||
/turf/simulated/floor/beach/away/water, /turf/simulated/floor/beach/away/water/dense,
|
||||
/turf/simulated/floor/beach/away/water/edge_drop)
|
||||
|
||||
/turf/simulated/floor/beach/away/water/drop/dense
|
||||
density = TRUE
|
||||
baseturf = /turf/simulated/floor/beach/away/water/drop/dense
|
||||
|
||||
/turf/simulated/floor/beach/away/water/deep
|
||||
name = "Deep Water"
|
||||
icon_state = "seadeep"
|
||||
water_overlay_image = "water_deep"
|
||||
baseturf = /turf/simulated/floor/beach/away/water/deep
|
||||
|
||||
/turf/simulated/floor/beach/away/water/deep/dense
|
||||
density = TRUE
|
||||
baseturf = /turf/simulated/floor/beach/away/water/deep/dense
|
||||
|
||||
/turf/simulated/floor/beach/away/water/deep/wood_floor
|
||||
name = "Sunken Floor"
|
||||
icon = 'icons/turf/floors.dmi'
|
||||
icon_state = "wood"
|
||||
baseturf = /turf/simulated/floor/beach/away/water/deep/wood_floor
|
||||
|
||||
/turf/simulated/floor/beach/away/water/deep/sand_floor
|
||||
name = "Sea Floor"
|
||||
icon_state = "sand"
|
||||
baseturf = /turf/simulated/floor/beach/away/water/deep/sand_floor
|
||||
|
||||
/turf/simulated/floor/beach/away/water/deep/rock_wall
|
||||
name = "Reef Stone"
|
||||
icon_state = "desert7"
|
||||
density = TRUE
|
||||
opacity = TRUE
|
||||
explosion_block = 2
|
||||
mouse_opacity = MOUSE_OPACITY_ICON
|
||||
baseturf = /turf/simulated/floor/beach/away/water/deep/rock_wall
|
||||
|
||||
/obj/effect/baseturf_helper/beach/away/sand
|
||||
name = "beach away sand baseturf editor"
|
||||
baseturf = /turf/simulated/floor/beach/away/sand
|
||||
|
||||
/obj/effect/baseturf_helper/beach/away/water
|
||||
name = "beach away water baseturf editor"
|
||||
baseturf = /turf/simulated/floor/beach/away/water/deep/sand_floor
|
||||
|
||||
@@ -71,7 +71,7 @@
|
||||
shoes = /obj/item/clothing/shoes/workboots
|
||||
id = /obj/item/card/id/away/old/eng
|
||||
gloves = /obj/item/clothing/gloves/color/fyellow/old
|
||||
l_pocket = /obj/item/tank/emergency_oxygen
|
||||
l_pocket = /obj/item/tank/internals/emergency_oxygen
|
||||
assignedrole = "Ancient Crew"
|
||||
|
||||
/obj/effect/mob_spawn/human/oldeng/Destroy()
|
||||
|
||||
@@ -62,7 +62,7 @@
|
||||
item_state = "void"
|
||||
desc = "A CentCom engineering dark red space suit. Age has degraded the suit making is difficult to move around in."
|
||||
slowdown = 4
|
||||
allowed = list(/obj/item/flashlight, /obj/item/tank, /obj/item/multitool)
|
||||
allowed = list(/obj/item/flashlight, /obj/item/tank/internals, /obj/item/multitool)
|
||||
|
||||
/obj/item/clothing/head/helmet/old
|
||||
name = "degrading helmet"
|
||||
|
||||
@@ -1,279 +0,0 @@
|
||||
#define PAY_INTERVAL 6000 // amount of ticks between payment
|
||||
|
||||
/area/awaymission/spacehotel
|
||||
name = "Deep Space Hotel 419"
|
||||
requires_power = FALSE
|
||||
dynamic_lighting = DYNAMIC_LIGHTING_FORCED
|
||||
|
||||
/area/awaymission/spacehotel/kitchen
|
||||
name = "Hotel Kitchen"
|
||||
icon_state = "kitchen"
|
||||
|
||||
/area/awaymission/spacehotel/reception
|
||||
name = "Hotel Reception"
|
||||
icon_state = "entry"
|
||||
|
||||
// "Directional" map template loader for N or S hotel room
|
||||
/obj/effect/landmark/map_loader/hotel_room
|
||||
icon = 'icons/testing/turf_analysis.dmi'
|
||||
icon_state = "arrow"
|
||||
|
||||
/obj/item/paper/crumpled/hotel_scrap_1
|
||||
name = "paper scrap"
|
||||
info = "I can't believe this shitty hotel assigned me a purple-themed room. <i>Why does the shower dump grape drink everywhere??</i>"
|
||||
|
||||
/obj/item/paper/hotel_scrap_2
|
||||
name = "Journal Entry #2"
|
||||
info = "<h3>Day 7:</h3>Today, I stepped into my bathroom, only to discover that it had become a mountainside wilderness. I tried to wash my hands with snow, but it didn't particularly pan out.<br>I contacting the front desk regarding the issue, but the receptionist just stared at me with dead eyes and spouted unrepeatable curses at me. However, I convinced them to reassign me to an upgraded suite."
|
||||
|
||||
/obj/item/paper/hotel_scrap_3
|
||||
name = "Journal Entry #3"
|
||||
info = "<h3>Day 26:</h3>Well, that sucked royally. The queen-sized bed was nice, but the hottub in my room was, well, my wife described it as \"a portal to hell\". I don't know, I guess the lava and weird blood gave it that impression, but it was pretty nicely warm.<br>However, <i>\"we\"</i> decided to get assigned to a new room. Whatever."
|
||||
|
||||
/obj/item/paper/hotel_scrap_4
|
||||
name = "Diary Page"
|
||||
info = "<b>Day 7 of Bad Vacation</b><br>Thanks Qzxor this shit vacation is ending today. The novelty of the trashy pool wore off 2 days in and I'm not allowed in the bar. The tiny box they called a room that, we had to cram into, just had a poster and a couple of beds. Only one bedsheet to spare. Shower had brown water and sink just dumped its water back out the ceiling, somehow.<br><br>PS: The receptionist isn't paying attention to us when we try to check out. Apparently, we're staying another day."
|
||||
|
||||
/obj/item/paper/hotel_scrap_5
|
||||
name = "Journal Entry #5"
|
||||
info = "<h3>Day 185:</h3>I feel like the restaurant's chef is just making random dishes to mess with me. I request something from the menu, and he throws out something nobody asked for on the counter. The bartender isn't much better. At least both of them can make some nice food and drinks. I would complain to the management... but they never seem to care."
|
||||
|
||||
/obj/item/paper/crumpled/hotel_scrap_6
|
||||
name = "Journal Entry #6"
|
||||
info = "<h3>Day 386:</h3><span style='font-family: wingdings; color: red'>AMBGAT MEZLBNU</span>. Something wrong. Can't stop hugging plushies."
|
||||
|
||||
/obj/item/paper/crumpled/hotel_scrap_7
|
||||
name = "Journal Entry #8"
|
||||
info = "<span style='font-family: wingdings; color: red'>ASGATDHU NAMSPA KER OKS O OKDOFLI OSDSFKO OASKDAFO AOSDKF OINAIS ISJDDEF OSKFEREAODIK OSI ODIFOSA OEKRRO ASODFKAO PSSDOF SDFK OSDKF OSDKFSASPODFIOSASD UHGU DFYG FPO ASDFOS DFOASSD FAPSO FSPDFOIER OPWASDSA PS DODIOF OSDI</span> pizza <span style='font-family: wingdings; color: red'>OKSDFO AL OKEWORK CVBUASO SDFO AOE RAOWEIK SODDFI</span>"
|
||||
|
||||
/obj/item/paper/hotel_scrap_8
|
||||
name = "Mysterious Note"
|
||||
icon_state = "paper_talisman"
|
||||
info = "<div style='text-align: center; color: red; font: 24pt comic sans ms'>There is only one way to leave.</div>"
|
||||
|
||||
/obj/item/paper/pamphlet/hotel
|
||||
name = "space hotel pamphlet"
|
||||
info = "<h3>Welcome to Deep Space Hotel 419!</h3>Thank you for choosing our hotel. Simply hand your credit or debit card to the concierge and get your room key! To check out, hand your credit card back.<small><h4>Conditions:</h4><ul><li>The hotel is not responsible for any losses due to time or space anomalies.<li>The hotel is not responsible for events that occur outside of the hotel station, including, but not limited to, events that occur inside of dimensional pockets.<li>The hotel is not responsible for overcharging your account.<li>The hotel is not responsible for missing persons.<li>The hotel is not responsible for mind-altering effects due to drugs, magic, demons, or space worms.</ul></small>"
|
||||
|
||||
/obj/effect/landmark/map_loader/hotel_room/Initialize()
|
||||
..()
|
||||
// load and randomly assign rooms
|
||||
var/global/list/south_room_templates = list()
|
||||
var/global/list/north_room_templates = list()
|
||||
var/static/path = "_maps/map_files/templates/spacehotel/"
|
||||
var/global/loaded = 0
|
||||
if(!loaded)
|
||||
loaded = 1
|
||||
for(var/map in flist(path))
|
||||
if(cmptext(copytext(map, length(map) - 3), ".dmm"))
|
||||
var/datum/map_template/T = new(path = "[path][map]", rename = "[map]")
|
||||
if(copytext(map, 1, 3) == "n_")
|
||||
north_room_templates += T
|
||||
else if(copytext(map, 1, 3) == "s_")
|
||||
south_room_templates += T
|
||||
else
|
||||
// omnidirectional rooms are randomly assigned
|
||||
if(prob(50))
|
||||
north_room_templates += T
|
||||
else
|
||||
south_room_templates += T
|
||||
|
||||
var/datum/map_template/M = safepick(dir == NORTH ? north_room_templates : south_room_templates)
|
||||
if(M)
|
||||
template = M
|
||||
if(dir == NORTH)
|
||||
north_room_templates -= M
|
||||
else
|
||||
south_room_templates -= M
|
||||
load(M)
|
||||
|
||||
// The door to a hotel room, but also metadata for the room itself
|
||||
/obj/machinery/door/unpowered/hotel_door
|
||||
name = "Room Door"
|
||||
icon = 'icons/obj/doors/doorsand.dmi'
|
||||
icon_state = "door_closed"
|
||||
autoclose = 1
|
||||
var/doorOpen = 'sound/machines/airlock_open.ogg'
|
||||
var/doorClose = 'sound/machines/airlock_close.ogg'
|
||||
var/doorDeni = 'sound/machines/deniedbeep.ogg'
|
||||
var/id // the room number, eg 101
|
||||
var/obj/item/card/hotel_card/card// room's key card
|
||||
var/mob/living/occupant = null // the current room occupant
|
||||
var/datum/money_account/account // Account we're pulling from
|
||||
var/roomtimer // timer PS handle for updating room
|
||||
|
||||
/obj/machinery/door/unpowered/hotel_door/New()
|
||||
..()
|
||||
if(id)
|
||||
name = "Room [id]"
|
||||
|
||||
// in case we spawned after hotel
|
||||
var/obj/effect/hotel_controller/H
|
||||
H = H.controller
|
||||
if(H)
|
||||
H.add_room(src)
|
||||
|
||||
/obj/machinery/door/unpowered/hotel_door/Destroy()
|
||||
if(roomtimer)
|
||||
deltimer(roomtimer)
|
||||
roomtimer = null
|
||||
QDEL_NULL(card)
|
||||
return ..()
|
||||
|
||||
/obj/machinery/door/unpowered/hotel_door/examine(mob/user)
|
||||
. = ..()
|
||||
. += "This room is currently [occupant ? "" : "un"]occupied."
|
||||
|
||||
/obj/machinery/door/unpowered/hotel_door/allowed(mob/living/carbon/user)
|
||||
for(var/obj/item/card/hotel_card/C in user.get_all_slots())
|
||||
if(C == card && occupant)
|
||||
atom_say("Welcome, [occupant.real_name]!")
|
||||
return 1
|
||||
return 0
|
||||
|
||||
/obj/machinery/door/unpowered/hotel_door/update_icon()
|
||||
overlays.Cut()
|
||||
if(density)
|
||||
icon_state = "door_closed"
|
||||
else
|
||||
icon_state = "door_open"
|
||||
|
||||
/obj/machinery/door/unpowered/hotel_door/do_animate(animation)
|
||||
switch(animation)
|
||||
if("opening")
|
||||
playsound(loc, doorOpen, 30, 1)
|
||||
flick("door_opening", src)
|
||||
if("closing")
|
||||
playsound(loc, doorClose, 30, 1)
|
||||
flick("door_closing", src)
|
||||
if("deny")
|
||||
playsound(src.loc, doorDeni, 50, 0, 3)
|
||||
flick("door_deny", src)
|
||||
|
||||
/obj/machinery/door/unpowered/hotel_door/autoclose()
|
||||
if(!density && !operating && autoclose)
|
||||
close()
|
||||
/obj/item/card/hotel_card
|
||||
name = "Key Card"
|
||||
icon_state = "guest"
|
||||
color = "#0CF"
|
||||
var/id
|
||||
|
||||
/obj/item/card/hotel_card/New(loc, ID)
|
||||
..()
|
||||
if(ID)
|
||||
id = ID
|
||||
if(id)
|
||||
name = "Key Card - [id]"
|
||||
desc = "A key card to room [id]. Use it to open the door."
|
||||
|
||||
/obj/item/card/hotel_card/Destroy()
|
||||
var/mob/user = get(loc, /mob)
|
||||
if(user)
|
||||
to_chat(user, "\The [src] suddenly disappears in a flash!")
|
||||
return ..()
|
||||
|
||||
/obj/effect/hotel_controller
|
||||
var/global/obj/effect/hotel_controller/controller
|
||||
|
||||
name = "Deep Space Hotel 419"
|
||||
icon = 'icons/mob/screen_gen.dmi'
|
||||
icon_state = "x"
|
||||
invisibility = 101
|
||||
anchored = 1
|
||||
density = 0
|
||||
opacity = 0
|
||||
var/list/room_doors[0] // assoc list of [room id]=hotel_door
|
||||
var/list/vacant_rooms[0] // list of vacant room doors
|
||||
var/list/guests[0] // assoc list of [guest mob]=room id
|
||||
|
||||
var/obj/item/radio/radio // for shouting at deadbeats
|
||||
|
||||
/obj/effect/hotel_controller/New()
|
||||
..()
|
||||
if(controller)
|
||||
qdel(src)
|
||||
controller = src
|
||||
|
||||
radio = new()
|
||||
radio.broadcasting = 0
|
||||
radio.listening = 0
|
||||
|
||||
// get room doors
|
||||
for(var/obj/machinery/door/unpowered/hotel_door/D in get_area(src))
|
||||
add_room(D)
|
||||
|
||||
/obj/effect/hotel_controller/proc/add_room(obj/machinery/door/unpowered/hotel_door/D)
|
||||
room_doors["[D.id]"] = D
|
||||
vacant_rooms += D
|
||||
|
||||
/obj/effect/hotel_controller/Destroy()
|
||||
room_doors.Cut()
|
||||
vacant_rooms.Cut()
|
||||
guests.Cut()
|
||||
|
||||
QDEL_NULL(radio)
|
||||
|
||||
return ..()
|
||||
|
||||
// to check a person into a room; no financial stuff; returns the keycard
|
||||
/obj/effect/hotel_controller/proc/checkin(roomid, mob/living/carbon/occupant, obj/item/card/id/id)
|
||||
if(!istype(occupant))
|
||||
return null
|
||||
var/obj/machinery/door/unpowered/hotel_door/D = room_doors["[roomid]"]
|
||||
if(!D || D.occupant || (occupant in guests))
|
||||
return null
|
||||
|
||||
D.account = get_card_account(id, occupant)
|
||||
if(!D.account)
|
||||
return null
|
||||
if(!D.account.charge(100, null, "10 minutes hotel stay", "Biesel GalaxyNet Terminal [rand(111,1111)]", "[name]"))
|
||||
return null
|
||||
|
||||
D.occupant = occupant
|
||||
D.roomtimer = addtimer(CALLBACK(src, .proc/process_room, roomid), PAY_INTERVAL, TIMER_STOPPABLE)
|
||||
vacant_rooms -= D
|
||||
guests[occupant] = roomid
|
||||
|
||||
var/obj/item/card/hotel_card/C = new(ID = roomid)
|
||||
D.card = C
|
||||
return C
|
||||
|
||||
/obj/effect/hotel_controller/proc/process_room(roomid)
|
||||
var/obj/machinery/door/unpowered/hotel_door/D = room_doors["[roomid]"]
|
||||
if(!D || !D.occupant)
|
||||
return
|
||||
|
||||
if(D.account.charge(100, null, "10 minutes hotel stay extension", "Biesel GalaxyNet Terminal [rand(111,1111)]", "[name]"))
|
||||
D.roomtimer = addtimer(CALLBACK(src, .proc/process_room, roomid), PAY_INTERVAL, TIMER_STOPPABLE)
|
||||
else
|
||||
force_checkout(roomid)
|
||||
|
||||
// Checks a person out of a room; no financial stuff
|
||||
/obj/effect/hotel_controller/proc/checkout(roomid)
|
||||
var/obj/machinery/door/unpowered/hotel_door/D = room_doors["[roomid]"]
|
||||
if(!D || !D.occupant)
|
||||
return 0
|
||||
|
||||
guests -= D.occupant
|
||||
D.occupant = null
|
||||
D.account = null
|
||||
deltimer(D.roomtimer)
|
||||
D.roomtimer = null
|
||||
qdel(D.card)
|
||||
vacant_rooms += D
|
||||
return 1
|
||||
|
||||
// The person's card bounced mid-stay
|
||||
/obj/effect/hotel_controller/proc/force_checkout(roomid)
|
||||
var/obj/machinery/door/unpowered/hotel_door/D = room_doors["[roomid]"]
|
||||
if(!D || !D.occupant)
|
||||
return 0
|
||||
|
||||
var/mob/deadbeat = D.occupant
|
||||
|
||||
radio.autosay("[deadbeat], your card has been rejected. You have 30 seconds to check out.", name)
|
||||
spawn(300)
|
||||
if(D.occupant == deadbeat)
|
||||
// they still haven't checked out...
|
||||
checkout(roomid)
|
||||
@@ -1,373 +0,0 @@
|
||||
/area/awaymission/upperlevel
|
||||
name = "Open Space"
|
||||
color = "#888"
|
||||
dynamic_lighting = DYNAMIC_LIGHTING_FORCED
|
||||
requires_power = FALSE
|
||||
|
||||
// Used by /turf/unsimulated/floor/upperlevel as a reference for where the other floor is
|
||||
/obj/effect/levelref
|
||||
name = "level reference"
|
||||
icon = 'icons/mob/screen_gen.dmi'
|
||||
icon_state = "x2"
|
||||
invisibility = 101
|
||||
|
||||
var/id = null
|
||||
var/obj/effect/levelref/other = null
|
||||
var/offset_x
|
||||
var/offset_y
|
||||
var/offset_z
|
||||
var/global/list/levels[0]
|
||||
|
||||
/obj/effect/levelref/New()
|
||||
..()
|
||||
levels += src
|
||||
|
||||
/obj/effect/levelref/Initialize()
|
||||
..()
|
||||
for(var/obj/effect/levelref/O in levels)
|
||||
if(id == O.id && O != src)
|
||||
other = O
|
||||
update_offset()
|
||||
O.other = src
|
||||
O.update_offset()
|
||||
for(var/turf/unsimulated/floor/upperlevel/U in get_area(loc))
|
||||
U.init(src)
|
||||
return
|
||||
|
||||
/obj/effect/levelref/Destroy()
|
||||
levels -= src
|
||||
return ..()
|
||||
|
||||
/obj/effect/levelref/proc/update_offset()
|
||||
offset_x = other.x - x
|
||||
offset_y = other.y - y
|
||||
offset_z = other.z - z
|
||||
|
||||
// Used by /turf/unsimulated/floor/upperlevel and /obj/effect/view_portal/visual
|
||||
// to know if the world changed on the remote side
|
||||
/obj/effect/portal_sensor
|
||||
invisibility = 101
|
||||
var/light_hash = -1
|
||||
var/triggered_this_tick = 0
|
||||
var/datum/owner // owner that receive signals
|
||||
var/list/params[0] // what to send to the main object to indicate which sensor
|
||||
var/trigger_limit = 5 // number of time we're allowed to trigger per ptick
|
||||
|
||||
/obj/effect/portal_sensor/New(loc, o, ...)
|
||||
..()
|
||||
owner = o
|
||||
if(args.len >= 3)
|
||||
params = args.Copy(3)
|
||||
START_PROCESSING(SSobj, src)
|
||||
trigger()
|
||||
|
||||
/obj/effect/portal_sensor/Destroy()
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
return ..()
|
||||
|
||||
/obj/effect/portal_sensor/Crossed(A, oldloc)
|
||||
trigger()
|
||||
|
||||
/obj/effect/portal_sensor/Uncrossed(A)
|
||||
trigger()
|
||||
|
||||
/obj/effect/portal_sensor/process()
|
||||
check_light()
|
||||
if(triggered_this_tick >= trigger_limit)
|
||||
call(owner, "trigger")(arglist(params))
|
||||
triggered_this_tick = 0
|
||||
|
||||
/obj/effect/portal_sensor/proc/trigger()
|
||||
triggered_this_tick++
|
||||
if(triggered_this_tick < trigger_limit)
|
||||
call(owner, "trigger")(arglist(params))
|
||||
|
||||
/obj/effect/portal_sensor/proc/check_light()
|
||||
var/turf/T = loc
|
||||
if(istype(T) && T.lighting_object && !T.lighting_object.needs_update)
|
||||
var/atom/movable/lighting_object/O = T.lighting_object
|
||||
var/hash = 0
|
||||
|
||||
for(var/lighting_corner in O)
|
||||
var/datum/lighting_corner/C = lighting_corner
|
||||
hash = hash + C.lum_r + C.lum_g + C.lum_b
|
||||
|
||||
if(hash != light_hash)
|
||||
light_hash = hash
|
||||
trigger()
|
||||
else
|
||||
if(light_hash != -1)
|
||||
light_hash = -1
|
||||
trigger()
|
||||
|
||||
// for second floor showing floor below
|
||||
/turf/unsimulated/floor/upperlevel
|
||||
icon = 'icons/turf/areas.dmi'
|
||||
icon_state = "dark128"
|
||||
layer = AREA_LAYER + 0.5
|
||||
appearance_flags = TILE_BOUND | KEEP_TOGETHER
|
||||
var/turf/lower_turf
|
||||
var/obj/effect/portal_sensor/sensor
|
||||
|
||||
/turf/unsimulated/floor/upperlevel/New()
|
||||
..()
|
||||
var/obj/effect/levelref/R = locate() in get_area(src)
|
||||
if(R && R.other)
|
||||
init(R)
|
||||
|
||||
/turf/unsimulated/floor/upperlevel/Destroy()
|
||||
QDEL_NULL(sensor)
|
||||
return ..()
|
||||
|
||||
/turf/unsimulated/floor/upperlevel/proc/init(var/obj/effect/levelref/R)
|
||||
lower_turf = locate(x + R.offset_x, y + R.offset_y, z + R.offset_z)
|
||||
if(lower_turf)
|
||||
sensor = new(lower_turf, src)
|
||||
|
||||
/turf/unsimulated/floor/upperlevel/Entered(atom/movable/AM, atom/OL, ignoreRest = 0)
|
||||
if(isliving(AM) || istype(AM, /obj))
|
||||
if(isliving(AM))
|
||||
var/mob/living/M = AM
|
||||
M.emote("scream")
|
||||
M.SpinAnimation(5, 1)
|
||||
AM.forceMove(lower_turf)
|
||||
|
||||
/turf/unsimulated/floor/upperlevel/attack_ghost(mob/user)
|
||||
user.forceMove(lower_turf)
|
||||
|
||||
/turf/unsimulated/floor/upperlevel/proc/trigger()
|
||||
name = lower_turf.name
|
||||
desc = lower_turf.desc
|
||||
|
||||
// render each atom
|
||||
underlays.Cut()
|
||||
for(var/X in list(lower_turf) + lower_turf.contents)
|
||||
var/atom/A = X
|
||||
if(A && A.invisibility <= SEE_INVISIBLE_LIVING)
|
||||
var/image/I = image(A, layer = AREA_LAYER + A.layer * 0.01, dir = A.dir)
|
||||
I.pixel_x = A.pixel_x
|
||||
I.pixel_y = A.pixel_y
|
||||
underlays += I
|
||||
|
||||
// remote end of narnia portal
|
||||
/obj/effect/view_portal
|
||||
name = "portal target"
|
||||
icon = 'icons/mob/screen_gen.dmi'
|
||||
icon_state = "x2"
|
||||
invisibility = 101
|
||||
anchored = 1
|
||||
|
||||
var/id = null // id of other portal turf we connect to
|
||||
|
||||
var/obj/effect/view_portal/other = null
|
||||
var/global/list/portals[0]
|
||||
|
||||
/obj/effect/view_portal/New()
|
||||
..()
|
||||
GLOB.portals += src
|
||||
|
||||
/obj/effect/view_portal/Initialize()
|
||||
..()
|
||||
if(id)
|
||||
for(var/obj/effect/view_portal/O in GLOB.portals)
|
||||
if(id == O.id && O != src && can_link(O))
|
||||
other = O
|
||||
O.other = src
|
||||
linkup()
|
||||
O.linkup()
|
||||
if(other)
|
||||
return
|
||||
|
||||
/obj/effect/view_portal/Destroy()
|
||||
GLOB.portals -= src
|
||||
return ..()
|
||||
|
||||
/obj/effect/view_portal/proc/can_link(obj/effect/view_portal/P)
|
||||
return P.type == /obj/effect/view_portal/visual && !P.other
|
||||
|
||||
/obj/effect/view_portal/proc/linkup()
|
||||
// allow it to link to multiple visual nodes
|
||||
other = null
|
||||
|
||||
// near end of nania portal
|
||||
/obj/effect/view_portal/visual
|
||||
name = "???"
|
||||
desc = "You'll have to get closer to clearly see what this is."
|
||||
|
||||
icon = 'icons/turf/floors.dmi'
|
||||
icon_state = "loadingarea"
|
||||
opacity = 1
|
||||
density = 1
|
||||
invisibility = 0
|
||||
appearance_flags = TILE_BOUND | KEEP_TOGETHER
|
||||
var/dist = 6 // dist that we render out
|
||||
var/radius = 3 // dist we render on other axis, in each direction
|
||||
var/frustrum = 0 // if 1, get wider and wider at each step outward
|
||||
var/teleport = 1 // should teleport?
|
||||
|
||||
var/list/render_block
|
||||
var/list/sensors[0]
|
||||
var/list/tiles[0]
|
||||
|
||||
var/list/near_render_block
|
||||
var/turf/near_viewpoint
|
||||
|
||||
/obj/effect/view_portal/visual/Destroy()
|
||||
for(var/T in sensors)
|
||||
qdel(sensors[T])
|
||||
sensors.Cut()
|
||||
sensors = null
|
||||
for(var/T in tiles)
|
||||
qdel(tiles[T])
|
||||
tiles.Cut()
|
||||
tiles = null
|
||||
render_block = null
|
||||
near_render_block = null
|
||||
near_viewpoint = null
|
||||
return ..()
|
||||
|
||||
/obj/effect/view_portal/visual/can_link(obj/effect/view_portal/P)
|
||||
return P.type == /obj/effect/view_portal
|
||||
|
||||
/obj/effect/view_portal/visual/linkup()
|
||||
icon = null
|
||||
icon_state = null
|
||||
var/turf/Tloc = get_turf(loc)
|
||||
if(Tloc)
|
||||
Tloc.icon = null
|
||||
Tloc.icon_state = null
|
||||
Tloc.dynamic_lighting = 0
|
||||
layer = AREA_LAYER + 0.5
|
||||
|
||||
// setup references
|
||||
var/crossdir = angle2dir((dir2angle(dir) + 90) % 360)
|
||||
near_viewpoint = get_step(get_turf(src), GetOppositeDir(dir))
|
||||
|
||||
// setup far turfs
|
||||
var/turf/T1 = get_turf(other)
|
||||
var/turf/T2 = T1
|
||||
|
||||
for(var/i in 1 to radius)
|
||||
T1 = get_step(T1, crossdir)
|
||||
T2 = get_step(T2, GetOppositeDir(crossdir))
|
||||
if(frustrum)
|
||||
// make a trapazoid, with length dist, short end radius*2 long,
|
||||
// and 45 degree angles
|
||||
render_block = block(T1, T2)
|
||||
for(var/i in 1 to dist)
|
||||
T1 = get_step(get_step(T1, dir), crossdir)
|
||||
T2 = get_step(get_step(T2, dir), GetOppositeDir(crossdir))
|
||||
render_block += block(T1, T2)
|
||||
else
|
||||
// else make a box dist x radius*2
|
||||
for(var/i in 1 to dist)
|
||||
T2 = get_step(T2, dir)
|
||||
render_block = block(T1, T2)
|
||||
for(var/turf/T in render_block)
|
||||
sensors[T] = new /obj/effect/portal_sensor(T, src, 0, T)
|
||||
|
||||
// setup turfs on this side of the portal to cover the map streaming
|
||||
// has to be done later for view() to be correct (so it happens when the walls exist)
|
||||
/obj/effect/view_portal/visual/proc/setup_near()
|
||||
var/nvs = dir & (EAST|WEST) ? near_viewpoint.x - x : near_viewpoint.y - y
|
||||
if(nvs)
|
||||
nvs = SIGN(nvs)
|
||||
// need a mob for view() to work correctly
|
||||
var/mob/M = new(near_viewpoint)
|
||||
M.see_invisible = SEE_INVISIBLE_LIVING
|
||||
near_render_block = view(M, world.view)
|
||||
qdel(M)
|
||||
for(var/A in near_render_block)
|
||||
var/turf/T = A
|
||||
if(istype(T))
|
||||
var/ts = dir & (EAST|WEST) ? T.x - x : T.y - y
|
||||
if(ts)
|
||||
ts = SIGN(ts)
|
||||
if(nvs == ts)
|
||||
sensors[T] = new /obj/effect/portal_sensor(T, src, 1, T)
|
||||
else
|
||||
near_render_block -= T
|
||||
else
|
||||
near_render_block -= T
|
||||
|
||||
/obj/effect/view_portal/visual/Bumped(atom/movable/thing)
|
||||
if((istype(thing, /obj) || isliving(thing)) && other && teleport)
|
||||
if(!near_render_block)
|
||||
setup_near()
|
||||
|
||||
var/mob/living/M = thing
|
||||
// make the person glide onto the dest, giving a smooth transition
|
||||
var/ox = thing.x - x
|
||||
var/oy = thing.y - y
|
||||
if(istype(M) && M.client)
|
||||
M.notransform = 1
|
||||
// cover up client-side map loading
|
||||
M.screen_loc = "CENTER"
|
||||
M.client.screen += M
|
||||
for(var/T in tiles)
|
||||
M.client.screen += tiles[T]
|
||||
|
||||
// wait a tick for the screen to replicate across network
|
||||
// or this whole exercise of covering the transition is pointless
|
||||
spawn(1)
|
||||
thing.forceMove(locate(other.x + ox, other.y + oy, other.z))
|
||||
sleep(1)
|
||||
if(istype(M) && M.client)
|
||||
for(var/T in tiles)
|
||||
M.client.screen -= tiles[T]
|
||||
M.client.screen -= M
|
||||
M.screen_loc = initial(M.screen_loc)
|
||||
thing.forceMove(get_turf(other.loc))
|
||||
if(istype(M) && M.client)
|
||||
M.notransform = 0
|
||||
|
||||
/obj/effect/view_portal/visual/attack_ghost(mob/user)
|
||||
user.forceMove(get_turf(other.loc))
|
||||
|
||||
/obj/effect/view_portal/visual/proc/trigger(near, turf/T)
|
||||
var/obj/effect/view_portal_dummy/D = tiles[T]
|
||||
if(D)
|
||||
D.overlays.Cut()
|
||||
else
|
||||
D = new(src, near, T)
|
||||
tiles[T] = D
|
||||
|
||||
// render atoms to overlays of a dummy object
|
||||
if(D.name != T.name)
|
||||
D.name = T.name
|
||||
D.desc = T.desc
|
||||
for(var/AX in list(T) + T.contents)
|
||||
var/atom/A = AX
|
||||
if(A && A.invisibility <= SEE_INVISIBLE_LIVING)
|
||||
var/image/I = image(A, layer = D.layer + A.layer * 0.01, dir = A.dir)
|
||||
I.pixel_x = A.pixel_x
|
||||
I.pixel_y = A.pixel_y
|
||||
D.overlays += I
|
||||
|
||||
// tile of rendered other side for narnia portal
|
||||
/obj/effect/view_portal_dummy
|
||||
var/obj/effect/view_portal/visual/owner
|
||||
|
||||
/obj/effect/view_portal_dummy/New(obj/effect/view_portal/visual/V, near, turf/T)
|
||||
..()
|
||||
if(!near)
|
||||
loc = V.loc
|
||||
owner = V
|
||||
|
||||
var/ox
|
||||
var/oy
|
||||
if(near)
|
||||
ox = (T.x - V.near_viewpoint.x)
|
||||
oy = (T.y - V.near_viewpoint.y)
|
||||
layer = AREA_LAYER + 0.4
|
||||
else
|
||||
ox = T.x - V.other.x + V.x - V.near_viewpoint.x
|
||||
oy = T.y - V.other.y + V.y - V.near_viewpoint.y
|
||||
pixel_x = 32 * (T.x - V.other.x)
|
||||
pixel_y = 32 * (T.y - V.other.y)
|
||||
layer = AREA_LAYER + 0.5
|
||||
if(abs(ox) <= world.view && abs(oy) <= world.view)
|
||||
screen_loc = "CENTER[ox >= 0 ? "+" : ""][ox],CENTER[oy >= 0 ? "+" : ""][oy]"
|
||||
|
||||
/obj/effect/view_portal_dummy/attack_ghost(mob/user)
|
||||
owner.attack_ghost(user)
|
||||
@@ -391,8 +391,13 @@
|
||||
GLOB.panic_bunker_enabled = FALSE
|
||||
message_admins("Panic bunker has been automatically disabled due to playercount dropping below [threshold]")
|
||||
|
||||
// Tell clients about active testmerges
|
||||
if(world.TgsAvailable() && length(GLOB.revision_info.testmerges))
|
||||
to_chat(src, GLOB.revision_info.get_testmerge_chatmessage(TRUE))
|
||||
|
||||
INVOKE_ASYNC(src, .proc/cid_count_check)
|
||||
|
||||
|
||||
/client/proc/is_connecting_from_localhost()
|
||||
var/localhost_addresses = list("127.0.0.1", "::1") // Adresses
|
||||
if(!isnull(address) && (address in localhost_addresses))
|
||||
|
||||
@@ -2114,11 +2114,9 @@ GLOBAL_LIST_INIT(special_role_times, list( //minimum age (in days) for accounts
|
||||
|
||||
if("ambientocclusion")
|
||||
toggles ^= PREFTOGGLE_AMBIENT_OCCLUSION
|
||||
if(parent && parent.screen && parent.screen.len)
|
||||
if(length(parent?.screen))
|
||||
var/obj/screen/plane_master/game_world/PM = locate(/obj/screen/plane_master/game_world) in parent.screen
|
||||
PM.filters -= FILTER_AMBIENT_OCCLUSION
|
||||
if(toggles & PREFTOGGLE_AMBIENT_OCCLUSION)
|
||||
PM.filters += FILTER_AMBIENT_OCCLUSION
|
||||
PM.backdrop(parent.mob)
|
||||
|
||||
if("parallax")
|
||||
var/parallax_styles = list(
|
||||
|
||||
@@ -436,7 +436,7 @@
|
||||
"f_style" = f_style,
|
||||
"markingstyleslist" = markingstyleslist,
|
||||
"ha_style" = ha_style,
|
||||
"alt_head" = alt_head,
|
||||
"alt_head" = alt_head || "",
|
||||
"e_colour" = e_colour,
|
||||
"underwear" = underwear,
|
||||
"undershirt" = undershirt,
|
||||
|
||||
@@ -277,15 +277,15 @@
|
||||
return
|
||||
|
||||
/client/verb/numpad_target()
|
||||
set name = "Toggle Numpad targetting"
|
||||
set name = "Toggle Numpad Targeting"
|
||||
set category = "Preferences"
|
||||
set desc = "This button will allow you to enable or disable Numpad Targetting"
|
||||
set desc = "This button will allow you to enable or disable Numpad Targeting"
|
||||
prefs.toggles ^= PREFTOGGLE_NUMPAD_TARGET
|
||||
prefs.save_preferences(src)
|
||||
if (prefs.toggles & PREFTOGGLE_NUMPAD_TARGET)
|
||||
to_chat(usr, "<span class='notice'>You have enabled Numpad Targetting.")
|
||||
to_chat(usr, "<span class='notice'>You have enabled Numpad Targeting.")
|
||||
else
|
||||
to_chat(usr, "<span class='notice'>You have disabled Numpad Targetting.")
|
||||
to_chat(usr, "<span class='notice'>You have disabled Numpad Targeting.")
|
||||
return
|
||||
|
||||
/client/verb/azerty_toggle()
|
||||
|
||||
@@ -204,7 +204,6 @@
|
||||
var/invis_override = 0
|
||||
var/lighting_alpha
|
||||
|
||||
var/emagged = 0
|
||||
var/list/color_view = null//overrides client.color while worn
|
||||
var/prescription = 0
|
||||
var/prescription_upgradable = 0
|
||||
@@ -513,7 +512,7 @@ BLIND // can't see anything
|
||||
icon = 'icons/obj/clothing/suits.dmi'
|
||||
name = "suit"
|
||||
var/fire_resist = T0C+100
|
||||
allowed = list(/obj/item/tank/emergency_oxygen)
|
||||
allowed = list(/obj/item/tank/internals/emergency_oxygen)
|
||||
armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 0, "acid" = 0)
|
||||
slot_flags = SLOT_OCLOTHING
|
||||
var/blood_overlay_type = "suit"
|
||||
@@ -627,7 +626,7 @@ BLIND // can't see anything
|
||||
permeability_coefficient = 0.02
|
||||
flags = STOPSPRESSUREDMAGE | THICKMATERIAL
|
||||
body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|FEET|ARMS|HANDS
|
||||
allowed = list(/obj/item/flashlight,/obj/item/tank)
|
||||
allowed = list(/obj/item/flashlight, /obj/item/tank/internals)
|
||||
slowdown = 1
|
||||
armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 100, "rad" = 50, "fire" = 80, "acid" = 70)
|
||||
flags_inv = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT|HIDETAIL
|
||||
|
||||
@@ -0,0 +1,120 @@
|
||||
//Engineering Mesons
|
||||
|
||||
#define MODE_NONE ""
|
||||
#define MODE_MESON "meson"
|
||||
#define MODE_TRAY "t-ray"
|
||||
#define MODE_RAD "radiation"
|
||||
|
||||
/obj/item/clothing/glasses/meson/engine
|
||||
name = "engineering scanner goggles"
|
||||
desc = "Goggles used by engineers. The Meson Scanner mode lets you see basic structural and terrain layouts through walls, the T-ray Scanner mode lets you see underfloor objects such as cables and pipes, and the Radiation Scanner mode lets you see objects contaminated by radiation."
|
||||
icon_state = "trayson-meson"
|
||||
item_state = "trayson-meson"
|
||||
actions_types = list(/datum/action/item_action/toggle_mode)
|
||||
origin_tech = "materials=3;magnets=3;engineering=3;plasmatech=3"
|
||||
vision_flags = NONE
|
||||
invis_view = SEE_INVISIBLE_LIVING
|
||||
|
||||
var/list/modes = list(MODE_NONE = MODE_MESON, MODE_MESON = MODE_TRAY, MODE_TRAY = MODE_RAD, MODE_RAD = MODE_NONE)
|
||||
var/mode = MODE_NONE
|
||||
var/range = 1
|
||||
|
||||
/obj/item/clothing/glasses/meson/engine/Initialize(mapload)
|
||||
. = ..()
|
||||
START_PROCESSING(SSobj, src)
|
||||
update_icon()
|
||||
|
||||
/obj/item/clothing/glasses/meson/engine/Destroy()
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
return ..()
|
||||
|
||||
/obj/item/clothing/glasses/meson/engine/proc/toggle_mode(mob/user, voluntary)
|
||||
mode = modes[mode]
|
||||
to_chat(user, "<span class='[voluntary ? "notice" : "warning"]'>[voluntary ? "You turn the goggles" : "The goggles turn"] [mode ? "to [mode] mode" : "off"][voluntary ? "." : "!"]</span>")
|
||||
|
||||
switch(mode)
|
||||
if(MODE_MESON)
|
||||
vision_flags = SEE_TURFS
|
||||
lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_VISIBLE
|
||||
|
||||
if(MODE_TRAY) //undoes the last mode, meson
|
||||
vision_flags = NONE
|
||||
lighting_alpha = null
|
||||
|
||||
if(ishuman(user))
|
||||
var/mob/living/carbon/human/H = user
|
||||
if(H.glasses == src)
|
||||
H.update_sight()
|
||||
|
||||
update_icon()
|
||||
for(var/X in actions)
|
||||
var/datum/action/A = X
|
||||
A.UpdateButtonIcon()
|
||||
|
||||
/obj/item/clothing/glasses/meson/engine/attack_self(mob/user)
|
||||
toggle_mode(user, TRUE)
|
||||
|
||||
/obj/item/clothing/glasses/meson/engine/process()
|
||||
if(!ishuman(loc))
|
||||
return
|
||||
var/mob/living/carbon/human/user = loc
|
||||
if(user.glasses != src || !user.client)
|
||||
return
|
||||
switch(mode)
|
||||
if(MODE_TRAY)
|
||||
t_ray_scan(user, 8, range)
|
||||
if(MODE_RAD)
|
||||
show_rads()
|
||||
|
||||
/obj/item/clothing/glasses/meson/engine/proc/show_rads()
|
||||
var/mob/living/carbon/human/user = loc
|
||||
var/list/rad_places = list()
|
||||
for(var/datum/component/radioactive/thing in SSradiation.processing)
|
||||
var/atom/owner = thing.parent
|
||||
var/turf/place = get_turf(owner)
|
||||
if(rad_places[place])
|
||||
rad_places[place] += thing.strength
|
||||
else
|
||||
rad_places[place] = thing.strength
|
||||
|
||||
for(var/i in rad_places)
|
||||
var/turf/place = i
|
||||
if(get_dist(user, place) >= range * 5) //Rads are easier to see than wires under the floor
|
||||
continue
|
||||
var/strength = round(rad_places[i] / 1000, 0.1)
|
||||
var/image/pic = image(loc = place)
|
||||
var/mutable_appearance/MA = new()
|
||||
MA.maptext = MAPTEXT("[strength]k")
|
||||
MA.color = "#04e604"
|
||||
MA.layer = RAD_TEXT_LAYER
|
||||
MA.plane = GAME_PLANE
|
||||
pic.appearance = MA
|
||||
flick_overlay(pic, list(user.client), 10)
|
||||
|
||||
/obj/item/clothing/glasses/meson/engine/update_icon()
|
||||
icon_state = "trayson-[mode]"
|
||||
update_mob()
|
||||
|
||||
/obj/item/clothing/glasses/meson/engine/proc/update_mob()
|
||||
item_state = icon_state
|
||||
if(isliving(loc))
|
||||
var/mob/living/user = loc
|
||||
if(user.get_item_by_slot(slot_glasses) == src)
|
||||
user.update_inv_glasses()
|
||||
else
|
||||
user.update_inv_l_hand()
|
||||
user.update_inv_r_hand()
|
||||
|
||||
/obj/item/clothing/glasses/meson/engine/tray //atmos techs have lived far too long without tray goggles while those damned engineers get their dual-purpose gogles all to themselves
|
||||
name = "optical t-ray scanner"
|
||||
icon_state = "trayson-t-ray"
|
||||
item_state = "trayson-t-ray"
|
||||
desc = "Used by engineering staff to see underfloor objects such as cables and pipes."
|
||||
range = 2
|
||||
origin_tech = "materials=3;magnets=2;engineering=2"
|
||||
modes = list(MODE_NONE = MODE_TRAY, MODE_TRAY = MODE_NONE)
|
||||
|
||||
#undef MODE_NONE
|
||||
#undef MODE_MESON
|
||||
#undef MODE_TRAY
|
||||
#undef MODE_RAD
|
||||
@@ -49,7 +49,7 @@
|
||||
name = "Optical Meson Scanner"
|
||||
desc = "Used for seeing walls, floors, and stuff through anything."
|
||||
icon_state = "meson"
|
||||
item_state = "glasses"
|
||||
item_state = "meson"
|
||||
origin_tech = "magnets=1;engineering=2"
|
||||
vision_flags = SEE_TURFS
|
||||
lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_VISIBLE
|
||||
@@ -66,7 +66,6 @@
|
||||
name = "Night Vision Optical Meson Scanner"
|
||||
desc = "An Optical Meson Scanner fitted with an amplified visible light spectrum overlay, providing greater visual clarity in darkness."
|
||||
icon_state = "nvgmeson"
|
||||
item_state = "glasses"
|
||||
origin_tech = "magnets=4;engineering=5;plasmatech=4"
|
||||
see_in_dark = 8
|
||||
lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE
|
||||
|
||||
@@ -75,7 +75,7 @@
|
||||
// Can't be equipped by any other species due to bone structure and vox cybernetics.
|
||||
/obj/item/clothing/suit/space/vox
|
||||
w_class = WEIGHT_CLASS_NORMAL
|
||||
allowed = list(/obj/item/gun,/obj/item/ammo_box,/obj/item/ammo_casing,/obj/item/melee/baton,/obj/item/melee/energy/sword/saber,/obj/item/restraints/handcuffs,/obj/item/tank)
|
||||
allowed = list(/obj/item/gun,/obj/item/ammo_box,/obj/item/ammo_casing,/obj/item/melee/baton,/obj/item/melee/energy/sword/saber,/obj/item/restraints/handcuffs, /obj/item/tank/internals)
|
||||
armor = list(melee = 40, bullet = 40, laser = 30, energy = 15, bomb = 30, bio = 30, rad = 30, fire = 80, acid = 85)
|
||||
heat_protection = UPPER_TORSO|LOWER_TORSO|LEGS|FEET|ARMS|HANDS
|
||||
max_heat_protection_temperature = SPACE_SUIT_MAX_TEMP_PROTECT
|
||||
|
||||
@@ -49,9 +49,9 @@
|
||||
icon_state = "ert_commander"
|
||||
item_state = "suit-command"
|
||||
w_class = WEIGHT_CLASS_NORMAL
|
||||
allowed = list(/obj/item/gun,/obj/item/ammo_box,/obj/item/ammo_casing,/obj/item/melee/baton,/obj/item/melee/energy/sword/saber,/obj/item/restraints/handcuffs,/obj/item/tank)
|
||||
allowed = list(/obj/item/gun,/obj/item/ammo_box,/obj/item/ammo_casing,/obj/item/melee/baton,/obj/item/melee/energy/sword/saber,/obj/item/restraints/handcuffs,/obj/item/tank/internals)
|
||||
armor = list(melee = 45, bullet = 25, laser = 30, energy = 10, bomb = 25, bio = 100, rad = 50, fire = 80, acid = 80)
|
||||
allowed = list(/obj/item/flashlight, /obj/item/tank, /obj/item/t_scanner, /obj/item/rcd, /obj/item/crowbar, \
|
||||
allowed = list(/obj/item/flashlight, /obj/item/tank/internals, /obj/item/t_scanner, /obj/item/rcd, /obj/item/crowbar, \
|
||||
/obj/item/screwdriver, /obj/item/weldingtool, /obj/item/wirecutters, /obj/item/wrench, /obj/item/multitool, \
|
||||
/obj/item/radio, /obj/item/analyzer, /obj/item/gun, /obj/item/melee/baton, /obj/item/reagent_containers/spray/pepper, \
|
||||
/obj/item/ammo_box, /obj/item/ammo_casing, /obj/item/restraints/handcuffs)
|
||||
|
||||
@@ -12,7 +12,13 @@
|
||||
var/on = FALSE
|
||||
var/obj/item/clothing/suit/space/hardsuit/suit
|
||||
item_color = "engineering" //Determines used sprites: hardsuit[on]-[color] and hardsuit[on]-[color]2 (lying down sprite)
|
||||
actions_types = list(/datum/action/item_action/toggle_helmet_light)
|
||||
actions_types = list(/datum/action/item_action/toggle_helmet_light, /datum/action/item_action/toggle_geiger_counter)
|
||||
|
||||
var/scanning = TRUE
|
||||
var/current_tick_amount = 0
|
||||
var/radiation_count = 0
|
||||
var/grace = RAD_GEIGER_GRACE_PERIOD
|
||||
var/datum/looping_sound/geiger/soundloop
|
||||
|
||||
//Species-specific stuff.
|
||||
species_restricted = list("exclude","Wryn")
|
||||
@@ -33,6 +39,17 @@
|
||||
"Vulpkanin" = 'icons/obj/clothing/species/vulpkanin/hats.dmi'
|
||||
)
|
||||
|
||||
/obj/item/clothing/head/helmet/space/hardsuit/Initialize(mapload)
|
||||
. = ..()
|
||||
soundloop = new(list(), FALSE, TRUE)
|
||||
soundloop.volume = 5
|
||||
START_PROCESSING(SSobj, src)
|
||||
|
||||
/obj/item/clothing/head/helmet/space/hardsuit/Destroy()
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
QDEL_NULL(soundloop)
|
||||
return ..()
|
||||
|
||||
/obj/item/clothing/head/helmet/space/hardsuit/attack_self(mob/user)
|
||||
toggle_light(user)
|
||||
|
||||
@@ -61,6 +78,7 @@
|
||||
..()
|
||||
if(suit)
|
||||
suit.RemoveHelmet()
|
||||
soundloop.stop(user)
|
||||
|
||||
/obj/item/clothing/head/helmet/space/hardsuit/item_action_slot_check(slot)
|
||||
if(slot == slot_head)
|
||||
@@ -71,14 +89,53 @@
|
||||
if(slot != slot_head)
|
||||
if(suit)
|
||||
suit.RemoveHelmet()
|
||||
soundloop.stop(user)
|
||||
else
|
||||
qdel(src)
|
||||
else if(scanning)
|
||||
soundloop.start(user)
|
||||
|
||||
/obj/item/clothing/head/helmet/space/hardsuit/proc/display_visor_message(var/msg)
|
||||
var/mob/wearer = loc
|
||||
if(msg && ishuman(wearer))
|
||||
wearer.show_message("<b><span class='robot'>[msg]</span></b>", 1)
|
||||
|
||||
/obj/item/clothing/head/helmet/space/hardsuit/rad_act(amount)
|
||||
. = ..()
|
||||
if(amount <= RAD_BACKGROUND_RADIATION)
|
||||
return
|
||||
current_tick_amount += amount
|
||||
|
||||
/obj/item/clothing/head/helmet/space/hardsuit/process()
|
||||
if(scanning)
|
||||
radiation_count -= radiation_count / RAD_GEIGER_MEASURE_SMOOTHING
|
||||
radiation_count += current_tick_amount / RAD_GEIGER_MEASURE_SMOOTHING
|
||||
|
||||
if(current_tick_amount)
|
||||
grace = RAD_GEIGER_GRACE_PERIOD
|
||||
else
|
||||
grace--
|
||||
if(grace <= 0)
|
||||
radiation_count = 0
|
||||
|
||||
current_tick_amount = 0
|
||||
|
||||
if(ishuman(loc))
|
||||
update_sound()
|
||||
|
||||
/obj/item/clothing/head/helmet/space/hardsuit/proc/update_sound()
|
||||
var/datum/looping_sound/geiger/loop = soundloop
|
||||
if(!scanning || !radiation_count)
|
||||
loop.stop(loc)
|
||||
return
|
||||
loop.last_radiation = radiation_count
|
||||
loop.start(loc)
|
||||
|
||||
/obj/item/clothing/head/helmet/space/hardsuit/proc/toggle_geiger_counter()
|
||||
scanning = !scanning
|
||||
if(ishuman(loc))
|
||||
to_chat(loc, "<span class='notice'>You toggle [src]'s internal geiger counter [scanning ? "on" : "off"].</span>")
|
||||
|
||||
/obj/item/clothing/head/helmet/space/hardsuit/emp_act(severity)
|
||||
..()
|
||||
display_visor_message("[severity > 1 ? "Light" : "Strong"] electromagnetic pulse detected!")
|
||||
@@ -90,7 +147,7 @@
|
||||
item_state = "eng_hardsuit"
|
||||
max_integrity = 300
|
||||
armor = list("melee" = 10, "bullet" = 5, "laser" = 10, "energy" = 5, "bomb" = 10, "bio" = 100, "rad" = 75, "fire" = 50, "acid" = 75)
|
||||
allowed = list(/obj/item/flashlight,/obj/item/tank,/obj/item/t_scanner, /obj/item/rcd, /obj/item/rpd)
|
||||
allowed = list(/obj/item/flashlight,/obj/item/tank/internals,/obj/item/t_scanner, /obj/item/rcd, /obj/item/rpd)
|
||||
siemens_coefficient = 0
|
||||
var/obj/item/clothing/head/helmet/space/hardsuit/helmet
|
||||
actions_types = list(/datum/action/item_action/toggle_helmet)
|
||||
@@ -260,7 +317,7 @@
|
||||
max_heat_protection_temperature = FIRE_SUIT_MAX_TEMP_PROTECT
|
||||
resistance_flags = FIRE_PROOF
|
||||
armor = list("melee" = 30, "bullet" = 5, "laser" = 10, "energy" = 5, "bomb" = 50, "bio" = 100, "rad" = 50, "fire" = 50, "acid" = 75)
|
||||
allowed = list(/obj/item/flashlight, /obj/item/tank, /obj/item/storage/bag/ore, /obj/item/pickaxe, /obj/item/resonator, /obj/item/mining_scanner, /obj/item/t_scanner/adv_mining_scanner, /obj/item/gun/energy/kinetic_accelerator)
|
||||
allowed = list(/obj/item/flashlight, /obj/item/tank/internals, /obj/item/storage/bag/ore, /obj/item/pickaxe, /obj/item/resonator, /obj/item/mining_scanner, /obj/item/t_scanner/adv_mining_scanner, /obj/item/gun/energy/kinetic_accelerator)
|
||||
helmettype = /obj/item/clothing/head/helmet/space/hardsuit/mining
|
||||
heat_protection = UPPER_TORSO|LOWER_TORSO|LEGS|FEET|ARMS|HANDS
|
||||
|
||||
@@ -351,7 +408,7 @@
|
||||
var/on = 1
|
||||
actions_types = list(/datum/action/item_action/toggle_hardsuit_mode)
|
||||
armor = list("melee" = 40, "bullet" = 50, "laser" = 30, "energy" = 15, "bomb" = 35, "bio" = 100, "rad" = 50, "fire" = 50, "acid" = 90)
|
||||
allowed = list(/obj/item/gun, /obj/item/ammo_box,/obj/item/ammo_casing, /obj/item/melee/baton, /obj/item/melee/energy/sword, /obj/item/restraints/handcuffs, /obj/item/tank)
|
||||
allowed = list(/obj/item/gun, /obj/item/ammo_box,/obj/item/ammo_casing, /obj/item/melee/baton, /obj/item/melee/energy/sword, /obj/item/restraints/handcuffs, /obj/item/tank/internals)
|
||||
helmettype = /obj/item/clothing/head/helmet/space/hardsuit/syndi
|
||||
jetpack = /obj/item/tank/jetpack/suit
|
||||
|
||||
@@ -422,7 +479,6 @@
|
||||
item_color = "medical"
|
||||
flash_protect = 0
|
||||
armor = list("melee" = 30, "bullet" = 5, "laser" = 10, "energy" = 5, "bomb" = 10, "bio" = 100, "rad" = 60, "fire" = 60, "acid" = 75)
|
||||
flags = STOPSPRESSUREDMAGE | THICKMATERIAL
|
||||
scan_reagents = 1 //Generally worn by the CMO, so they'd get utility off of seeing reagents
|
||||
|
||||
/obj/item/clothing/suit/space/hardsuit/medical
|
||||
@@ -430,7 +486,7 @@
|
||||
name = "medical hardsuit"
|
||||
desc = "A special helmet designed for work in a hazardous, low pressure environment. Built with lightweight materials for extra comfort."
|
||||
item_state = "medical_hardsuit"
|
||||
allowed = list(/obj/item/flashlight,/obj/item/tank,/obj/item/storage/firstaid,/obj/item/healthanalyzer,/obj/item/stack/medical,/obj/item/rad_laser)
|
||||
allowed = list(/obj/item/flashlight,/obj/item/tank/internals,/obj/item/storage/firstaid,/obj/item/healthanalyzer,/obj/item/stack/medical,/obj/item/rad_laser)
|
||||
armor = list("melee" = 30, "bullet" = 5, "laser" = 10, "energy" = 5, "bomb" = 10, "bio" = 100, "rad" = 60, "fire" = 60, "acid" = 75)
|
||||
helmettype = /obj/item/clothing/head/helmet/space/hardsuit/medical
|
||||
slowdown = 0.5
|
||||
@@ -450,7 +506,7 @@
|
||||
desc = "A special suit that protects against hazardous, low pressure environments. Has an additional layer of armor."
|
||||
item_state = "sec_hardsuit"
|
||||
armor = list("melee" = 35, "bullet" = 15, "laser" = 30, "energy" = 10, "bomb" = 10, "bio" = 100, "rad" = 50, "fire" = 75, "acid" = 75)
|
||||
allowed = list(/obj/item/gun,/obj/item/flashlight,/obj/item/tank,/obj/item/melee/baton,/obj/item/reagent_containers/spray/pepper,/obj/item/ammo_box,/obj/item/ammo_casing,/obj/item/restraints/handcuffs)
|
||||
allowed = list(/obj/item/gun,/obj/item/flashlight,/obj/item/tank/internals,/obj/item/melee/baton,/obj/item/reagent_containers/spray/pepper,/obj/item/ammo_box,/obj/item/ammo_casing,/obj/item/restraints/handcuffs)
|
||||
helmettype = /obj/item/clothing/head/helmet/space/hardsuit/security
|
||||
|
||||
/obj/item/clothing/head/helmet/space/hardsuit/security/hos
|
||||
@@ -497,7 +553,7 @@
|
||||
desc = "A hardsuit with built in energy shielding. Will rapidly recharge when not under fire."
|
||||
icon_state = "hardsuit-hos"
|
||||
helmettype = /obj/item/clothing/head/helmet/space/hardsuit/shielded
|
||||
allowed = list(/obj/item/flashlight,/obj/item/tank, /obj/item/gun,/obj/item/reagent_containers/spray/pepper,/obj/item/ammo_box,/obj/item/ammo_casing,/obj/item/melee/baton,/obj/item/restraints/handcuffs)
|
||||
allowed = list(/obj/item/flashlight,/obj/item/tank/internals, /obj/item/gun,/obj/item/reagent_containers/spray/pepper,/obj/item/ammo_box,/obj/item/ammo_casing,/obj/item/melee/baton,/obj/item/restraints/handcuffs)
|
||||
armor = list("melee" = 30, "bullet" = 15, "laser" = 30, "energy" = 10, "bomb" = 10, "bio" = 100, "rad" = 50, "fire" = 100, "acid" = 100)
|
||||
resistance_flags = FIRE_PROOF | ACID_PROOF
|
||||
var/current_charges = 3
|
||||
@@ -557,7 +613,7 @@
|
||||
item_state = "syndie_hardsuit"
|
||||
item_color = "syndi"
|
||||
armor = list("melee" = 40, "bullet" = 50, "laser" = 30, "energy" = 15, "bomb" = 35, "bio" = 100, "rad" = 50, "fire" = 100, "acid" = 100)
|
||||
allowed = list(/obj/item/gun,/obj/item/ammo_box,/obj/item/ammo_casing,/obj/item/melee/baton,/obj/item/melee/energy/sword/saber,/obj/item/restraints/handcuffs,/obj/item/tank)
|
||||
allowed = list(/obj/item/gun,/obj/item/ammo_box,/obj/item/ammo_casing,/obj/item/melee/baton,/obj/item/melee/energy/sword/saber,/obj/item/restraints/handcuffs,/obj/item/tank/internals)
|
||||
slowdown = 0
|
||||
helmettype = /obj/item/clothing/head/helmet/space/hardsuit/shielded/syndi
|
||||
jetpack = /obj/item/tank/jetpack/suit
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
icon_state = "caparmor"
|
||||
item_state = "capspacesuit"
|
||||
w_class = WEIGHT_CLASS_BULKY
|
||||
allowed = list(/obj/item/tank, /obj/item/flashlight,/obj/item/gun/energy, /obj/item/gun/projectile, /obj/item/ammo_box, /obj/item/ammo_casing, /obj/item/melee/baton,/obj/item/restraints/handcuffs)
|
||||
allowed = list(/obj/item/tank/internals, /obj/item/flashlight,/obj/item/gun/energy, /obj/item/gun/projectile, /obj/item/ammo_box, /obj/item/ammo_casing, /obj/item/melee/baton,/obj/item/restraints/handcuffs)
|
||||
armor = list("melee" = 40, "bullet" = 50, "laser" = 50, "energy" = 25, "bomb" = 50, "bio" = 100, "rad" = 50, "fire" = 100, "acid" = 100)
|
||||
species_restricted = list("exclude", "Wryn")
|
||||
|
||||
@@ -57,7 +57,7 @@
|
||||
desc = "A heavily armored, advanced space suit that protects against most forms of damage."
|
||||
icon_state = "deathsquad"
|
||||
item_state = "swat_suit"
|
||||
allowed = list(/obj/item/gun,/obj/item/ammo_box,/obj/item/ammo_casing,/obj/item/melee/baton,/obj/item/restraints/handcuffs,/obj/item/tank,/obj/item/kitchen/knife/combat)
|
||||
allowed = list(/obj/item/gun,/obj/item/ammo_box,/obj/item/ammo_casing,/obj/item/melee/baton,/obj/item/restraints/handcuffs,/obj/item/tank/internals,/obj/item/kitchen/knife/combat)
|
||||
armor = list("melee" = 80, "bullet" = 80, "laser" = 50, "energy" = 50, "bomb" = 100, "bio" = 100, "rad" = 100, "fire" = 100, "acid" = 100)
|
||||
max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT
|
||||
resistance_flags = FIRE_PROOF | ACID_PROOF
|
||||
@@ -70,7 +70,7 @@
|
||||
desc = "Space-proof tactical SWAT armor."
|
||||
icon_state = "heavy"
|
||||
item_state = "swat_suit"
|
||||
allowed = list(/obj/item/gun,/obj/item/ammo_box,/obj/item/ammo_casing,/obj/item/melee/baton,/obj/item/restraints/handcuffs,/obj/item/tank,/obj/item/kitchen/knife/combat)
|
||||
allowed = list(/obj/item/gun,/obj/item/ammo_box,/obj/item/ammo_casing,/obj/item/melee/baton,/obj/item/restraints/handcuffs,/obj/item/tank/internals,/obj/item/kitchen/knife/combat)
|
||||
armor = list("melee" = 40, "bullet" = 30, "laser" = 30,"energy" = 30, "bomb" = 50, "bio" = 90, "rad" = 20, "fire" = 100, "acid" = 100)
|
||||
strip_delay = 120
|
||||
resistance_flags = FIRE_PROOF | ACID_PROOF
|
||||
@@ -150,7 +150,7 @@
|
||||
icon_state = "pirate"
|
||||
item_state = "pirate"
|
||||
w_class = WEIGHT_CLASS_NORMAL
|
||||
allowed = list(/obj/item/gun,/obj/item/ammo_box,/obj/item/ammo_casing,/obj/item/melee/baton,/obj/item/restraints/handcuffs,/obj/item/tank)
|
||||
allowed = list(/obj/item/gun,/obj/item/ammo_box,/obj/item/ammo_casing,/obj/item/melee/baton,/obj/item/restraints/handcuffs,/obj/item/tank/internals)
|
||||
slowdown = 0
|
||||
armor = list("melee" = 30, "bullet" = 50, "laser" = 30,"energy" = 15, "bomb" = 30, "bio" = 30, "rad" = 30, "fire" = 60, "acid" = 75)
|
||||
strip_delay = 40
|
||||
|
||||
@@ -270,3 +270,9 @@
|
||||
armor = list("melee" = 30, "bullet" = 20, "laser" = 20, "energy" = 20, "bomb" = 20, "bio" = 20, "rad" = 20, "fire" = 100, "acid" = 100)
|
||||
resistance_flags = FIRE_PROOF | ACID_PROOF
|
||||
magical = TRUE
|
||||
|
||||
/obj/item/clothing/head/helmet/space/plasmaman/assistant
|
||||
name = "assistant envirosuit helmet"
|
||||
desc = "A plasmaman envirohelm designed for the common, maint-dwelling masses."
|
||||
icon_state = "assistant_envirohelm"
|
||||
item_state = "assistant_envirohelm"
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
item_state = "space_suit_syndicate"
|
||||
desc = "Has a tag on it: Totally not property of a hostile corporation, honest!"
|
||||
w_class = WEIGHT_CLASS_NORMAL
|
||||
allowed = list(/obj/item/gun,/obj/item/ammo_box,/obj/item/ammo_casing,/obj/item/melee/baton,/obj/item/melee/energy/sword/saber,/obj/item/restraints/handcuffs,/obj/item/tank)
|
||||
allowed = list(/obj/item/gun,/obj/item/ammo_box,/obj/item/ammo_casing,/obj/item/melee/baton,/obj/item/melee/energy/sword/saber,/obj/item/restraints/handcuffs,/obj/item/tank/internals)
|
||||
armor = list("melee" = 40, "bullet" = 50, "laser" = 30,"energy" = 15, "bomb" = 30, "bio" = 30, "rad" = 30, "fire" = 80, "acid" = 85)
|
||||
sprite_sheets = list(
|
||||
"Tajaran" = 'icons/mob/species/tajaran/suit.dmi',
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
icon_state = "void-red"
|
||||
item_state = "void"
|
||||
desc = "A high tech, NASA Centcom branch designed space suit. Used for AI satellite maintenance."
|
||||
allowed = list(/obj/item/flashlight,/obj/item/tank,/obj/item/multitool)
|
||||
allowed = list(/obj/item/flashlight,/obj/item/tank/internals,/obj/item/multitool)
|
||||
sprite_sheets = list(
|
||||
"Tajaran" = 'icons/mob/species/tajaran/suit.dmi',
|
||||
"Unathi" = 'icons/mob/species/unathi/suit.dmi',
|
||||
@@ -82,7 +82,7 @@
|
||||
icon_state = "void-syndi"
|
||||
desc = "A high tech, NASA Centcom branch designed space suit. This one looks rather suspicious."
|
||||
w_class = WEIGHT_CLASS_NORMAL
|
||||
allowed = list(/obj/item/gun,/obj/item/ammo_box,/obj/item/ammo_casing,/obj/item/melee/baton,/obj/item/melee/energy/sword/saber,/obj/item/restraints/handcuffs,/obj/item/tank)
|
||||
allowed = list(/obj/item/gun,/obj/item/ammo_box,/obj/item/ammo_casing,/obj/item/melee/baton,/obj/item/melee/energy/sword/saber,/obj/item/restraints/handcuffs,/obj/item/tank/internals)
|
||||
armor = list("melee" = 40, "bullet" = 50, "laser" = 30,"energy" = 15, "bomb" = 30, "bio" = 30, "rad" = 30, "fire" = 80, "acid" = 85)
|
||||
|
||||
//random spawner
|
||||
|
||||
@@ -252,7 +252,7 @@
|
||||
icon_state = "detective-armor"
|
||||
item_state = "armor"
|
||||
blood_overlay_type = "armor"
|
||||
allowed = list(/obj/item/tank/emergency_oxygen,/obj/item/reagent_containers/spray/pepper,/obj/item/flashlight,/obj/item/gun,/obj/item/ammo_box,/obj/item/ammo_casing,/obj/item/melee/baton,/obj/item/restraints/handcuffs,/obj/item/storage/fancy/cigarettes,/obj/item/lighter,/obj/item/detective_scanner,/obj/item/taperecorder)
|
||||
allowed = list(/obj/item/tank/internals/emergency_oxygen,/obj/item/reagent_containers/spray/pepper,/obj/item/flashlight,/obj/item/gun,/obj/item/ammo_box,/obj/item/ammo_casing,/obj/item/melee/baton,/obj/item/restraints/handcuffs,/obj/item/storage/fancy/cigarettes,/obj/item/lighter,/obj/item/detective_scanner,/obj/item/taperecorder)
|
||||
resistance_flags = FLAMMABLE
|
||||
dog_fashion = null
|
||||
|
||||
@@ -395,7 +395,7 @@
|
||||
item_state = "centcom"
|
||||
w_class = WEIGHT_CLASS_BULKY
|
||||
body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|FEET|ARMS|HANDS
|
||||
allowed = list(/obj/item/gun/energy,/obj/item/melee/baton,/obj/item/restraints/handcuffs,/obj/item/tank/emergency_oxygen)
|
||||
allowed = list(/obj/item/gun/energy,/obj/item/melee/baton,/obj/item/restraints/handcuffs,/obj/item/tank/internals/emergency_oxygen)
|
||||
flags = THICKMATERIAL
|
||||
flags_inv = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT
|
||||
cold_protection = UPPER_TORSO | LOWER_TORSO | LEGS | FEET | ARMS | HANDS
|
||||
@@ -485,7 +485,7 @@
|
||||
//same defense as basic sec armor
|
||||
/obj/item/clothing/suit/storage/lawyer/blackjacket/armored
|
||||
desc = "A snappy dress jacket, reinforced with a layer of armor protecting the torso."
|
||||
allowed = list(/obj/item/tank/emergency_oxygen, /obj/item/gun/projectile/revolver, /obj/item/gun/projectile/automatic/pistol)
|
||||
allowed = list(/obj/item/tank/internals/emergency_oxygen, /obj/item/gun/projectile/revolver, /obj/item/gun/projectile/automatic/pistol)
|
||||
body_parts_covered = UPPER_TORSO|LOWER_TORSO
|
||||
cold_protection = UPPER_TORSO|LOWER_TORSO
|
||||
min_cold_protection_temperature = ARMOR_MIN_TEMP_PROTECT
|
||||
@@ -500,7 +500,7 @@
|
||||
icon_state = "dragon"
|
||||
item_state = "dragon"
|
||||
desc = "A suit of armour fashioned from the remains of an ash drake."
|
||||
allowed = list(/obj/item/flashlight, /obj/item/tank, /obj/item/resonator, /obj/item/mining_scanner, /obj/item/t_scanner/adv_mining_scanner, /obj/item/gun/energy/kinetic_accelerator, /obj/item/pickaxe, /obj/item/twohanded/spear)
|
||||
allowed = list(/obj/item/flashlight, /obj/item/tank/internals, /obj/item/resonator, /obj/item/mining_scanner, /obj/item/t_scanner/adv_mining_scanner, /obj/item/gun/energy/kinetic_accelerator, /obj/item/pickaxe, /obj/item/twohanded/spear)
|
||||
armor = list("melee" = 70, "bullet" = 30, "laser" = 50, "energy" = 40, "bomb" = 70, "bio" = 60, "rad" = 50, "fire" = 100, "acid" = 100)
|
||||
hoodtype = /obj/item/clothing/head/hooded/drake
|
||||
heat_protection = UPPER_TORSO|LOWER_TORSO|LEGS|FEET|ARMS|HANDS
|
||||
@@ -525,7 +525,7 @@
|
||||
icon_state = "goliath_cloak"
|
||||
item_state = "goliath_cloak"
|
||||
desc = "A staunch, practical cape made out of numerous monster materials, it is coveted amongst exiles & hermits."
|
||||
allowed = list(/obj/item/flashlight, /obj/item/tank, /obj/item/pickaxe, /obj/item/twohanded/spear, /obj/item/organ/internal/regenerative_core/legion, /obj/item/kitchen/knife/combat/survival)
|
||||
allowed = list(/obj/item/flashlight, /obj/item/tank/internals, /obj/item/pickaxe, /obj/item/twohanded/spear, /obj/item/organ/internal/regenerative_core/legion, /obj/item/kitchen/knife/combat/survival)
|
||||
armor = list("melee" = 35, "bullet" = 10, "laser" = 25, "energy" = 10, "bomb" = 25, "bio" = 0, "rad" = 0, "fire" = 60, "acid" = 60) //a fair alternative to bone armor, requiring alternative materials and gaining a suit slot
|
||||
hoodtype = /obj/item/clothing/head/hooded/goliath
|
||||
body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
flags = THICKMATERIAL
|
||||
body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|FEET|ARMS|HANDS
|
||||
slowdown = 1
|
||||
allowed = list(/obj/item/tank/emergency_oxygen,/obj/item/pen,/obj/item/flashlight/pen)
|
||||
allowed = list(/obj/item/tank/internals/emergency_oxygen,/obj/item/pen,/obj/item/flashlight/pen)
|
||||
armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 100, "rad" = 80, "fire" = 30, "acid" = 100)
|
||||
flags_inv = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT|HIDETAIL
|
||||
strip_delay = 70
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
icon_state = "paramedic-vest"
|
||||
item_state = "paramedic-vest"
|
||||
allowed = list(/obj/item/stack/medical, /obj/item/reagent_containers/dropper, /obj/item/reagent_containers/hypospray, /obj/item/reagent_containers/applicator, /obj/item/reagent_containers/syringe,
|
||||
/obj/item/healthanalyzer, /obj/item/flashlight, /obj/item/radio, /obj/item/tank/emergency_oxygen,/obj/item/rad_laser)
|
||||
/obj/item/healthanalyzer, /obj/item/flashlight, /obj/item/radio, /obj/item/tank/internals/emergency_oxygen,/obj/item/rad_laser)
|
||||
armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 10, rad = 10, fire = 50, acid = 50)
|
||||
|
||||
sprite_sheets = list(
|
||||
@@ -23,7 +23,7 @@
|
||||
item_state = "brigphysician-vest"
|
||||
allowed = list(/obj/item/stack/medical, /obj/item/reagent_containers/dropper, /obj/item/reagent_containers/hypospray, /obj/item/reagent_containers/applicator, /obj/item/reagent_containers/syringe,
|
||||
/obj/item/healthanalyzer, /obj/item/flashlight, \
|
||||
/obj/item/radio, /obj/item/tank/emergency_oxygen,/obj/item/rad_laser)
|
||||
/obj/item/radio, /obj/item/tank/internals/emergency_oxygen,/obj/item/rad_laser)
|
||||
armor = list(melee = 10, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 10, rad = 0, fire = 50, acid = 50)
|
||||
|
||||
sprite_sheets = list(
|
||||
@@ -52,7 +52,7 @@
|
||||
item_state = "bio_suit"
|
||||
body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS
|
||||
flags_inv = HIDEJUMPSUIT
|
||||
allowed = list(/obj/item/disk, /obj/item/stamp, /obj/item/reagent_containers/food/drinks/flask, /obj/item/melee, /obj/item/storage/lockbox/medal, /obj/item/flash, /obj/item/storage/box/matches, /obj/item/lighter, /obj/item/clothing/mask/cigarette, /obj/item/storage/fancy/cigarettes, /obj/item/tank/emergency_oxygen)
|
||||
allowed = list(/obj/item/disk, /obj/item/stamp, /obj/item/reagent_containers/food/drinks/flask, /obj/item/melee, /obj/item/storage/lockbox/medal, /obj/item/flash, /obj/item/storage/box/matches, /obj/item/lighter, /obj/item/clothing/mask/cigarette, /obj/item/storage/fancy/cigarettes, /obj/item/tank/internals/emergency_oxygen)
|
||||
|
||||
sprite_sheets = list(
|
||||
"Vox" = 'icons/mob/species/vox/suit.dmi'
|
||||
@@ -85,7 +85,7 @@
|
||||
item_state = "chaplain_hoodie"
|
||||
body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS
|
||||
hoodtype = /obj/item/clothing/head/hooded/chaplain_hood
|
||||
allowed = list(/obj/item/storage/bible, /obj/item/nullrod, /obj/item/reagent_containers/food/drinks/bottle/holywater, /obj/item/storage/fancy/candle_box, /obj/item/candle, /obj/item/tank/emergency_oxygen)
|
||||
allowed = list(/obj/item/storage/bible, /obj/item/nullrod, /obj/item/reagent_containers/food/drinks/bottle/holywater, /obj/item/storage/fancy/candle_box, /obj/item/candle, /obj/item/tank/internals/emergency_oxygen)
|
||||
|
||||
sprite_sheets = list(
|
||||
"Vox" = 'icons/mob/species/vox/suit.dmi'
|
||||
@@ -100,7 +100,7 @@
|
||||
body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS|HANDS
|
||||
flags_inv = HIDESHOES|HIDEJUMPSUIT
|
||||
hoodtype = /obj/item/clothing/head/hooded/nun_hood
|
||||
allowed = list(/obj/item/storage/bible, /obj/item/nullrod, /obj/item/reagent_containers/food/drinks/bottle/holywater, /obj/item/storage/fancy/candle_box, /obj/item/candle, /obj/item/tank/emergency_oxygen)
|
||||
allowed = list(/obj/item/storage/bible, /obj/item/nullrod, /obj/item/reagent_containers/food/drinks/bottle/holywater, /obj/item/storage/fancy/candle_box, /obj/item/candle, /obj/item/tank/internals/emergency_oxygen)
|
||||
|
||||
sprite_sheets = list(
|
||||
"Vox" = 'icons/mob/species/vox/suit.dmi'
|
||||
@@ -115,7 +115,7 @@
|
||||
body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS|HANDS
|
||||
flags_inv = HIDESHOES|HIDEJUMPSUIT
|
||||
hoodtype = /obj/item/clothing/head/hooded/monk_hood
|
||||
allowed = list(/obj/item/storage/bible, /obj/item/nullrod, /obj/item/reagent_containers/food/drinks/bottle/holywater, /obj/item/storage/fancy/candle_box, /obj/item/candle, /obj/item/tank/emergency_oxygen)
|
||||
allowed = list(/obj/item/storage/bible, /obj/item/nullrod, /obj/item/reagent_containers/food/drinks/bottle/holywater, /obj/item/storage/fancy/candle_box, /obj/item/candle, /obj/item/tank/internals/emergency_oxygen)
|
||||
|
||||
/obj/item/clothing/suit/witchhunter
|
||||
name = "witchhunter garb"
|
||||
@@ -123,7 +123,7 @@
|
||||
icon_state = "witchhunter"
|
||||
item_state = "witchhunter"
|
||||
body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS
|
||||
allowed = list(/obj/item/storage/bible, /obj/item/nullrod, /obj/item/reagent_containers/food/drinks/bottle/holywater, /obj/item/storage/fancy/candle_box, /obj/item/candle, /obj/item/tank/emergency_oxygen)
|
||||
allowed = list(/obj/item/storage/bible, /obj/item/nullrod, /obj/item/reagent_containers/food/drinks/bottle/holywater, /obj/item/storage/fancy/candle_box, /obj/item/candle, /obj/item/tank/internals/emergency_oxygen)
|
||||
|
||||
|
||||
//Chef
|
||||
@@ -162,7 +162,7 @@
|
||||
desc = "A slick, authoritative cloak designed for the Chief Engineer."
|
||||
icon_state = "cemantle"
|
||||
item_state = "cemantle"
|
||||
allowed = list(/obj/item/flashlight, /obj/item/tank, /obj/item/t_scanner, /obj/item/rcd, /obj/item/rpd)
|
||||
allowed = list(/obj/item/flashlight, /obj/item/tank/internals, /obj/item/t_scanner, /obj/item/rcd, /obj/item/rpd)
|
||||
|
||||
//Chief Medical Officer
|
||||
/obj/item/clothing/suit/mantle/labcoat/chief_medical_officer
|
||||
@@ -179,7 +179,7 @@
|
||||
item_state = "det_suit"
|
||||
blood_overlay_type = "coat"
|
||||
body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS
|
||||
allowed = list(/obj/item/tank/emergency_oxygen, /obj/item/reagent_containers/spray/pepper, /obj/item/flashlight, /obj/item/gun, /obj/item/ammo_box, /obj/item/ammo_casing, /obj/item/melee/baton, /obj/item/restraints/handcuffs, /obj/item/storage/fancy/cigarettes, /obj/item/lighter, /obj/item/detective_scanner, /obj/item/taperecorder)
|
||||
allowed = list(/obj/item/tank/internals/emergency_oxygen, /obj/item/reagent_containers/spray/pepper, /obj/item/flashlight, /obj/item/gun, /obj/item/ammo_box, /obj/item/ammo_casing, /obj/item/melee/baton, /obj/item/restraints/handcuffs, /obj/item/storage/fancy/cigarettes, /obj/item/lighter, /obj/item/detective_scanner, /obj/item/taperecorder)
|
||||
armor = list("melee" = 25, "bullet" = 10, "laser" = 25, "energy" = 10, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 0, "acid" = 45)
|
||||
cold_protection = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS
|
||||
heat_protection = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS
|
||||
@@ -231,7 +231,7 @@
|
||||
icon_state = "hazard"
|
||||
item_state = "hazard"
|
||||
blood_overlay_type = "armor"
|
||||
allowed = list (/obj/item/flashlight, /obj/item/t_scanner, /obj/item/tank/emergency_oxygen, /obj/item/rcd, /obj/item/rpd)
|
||||
allowed = list (/obj/item/flashlight, /obj/item/t_scanner, /obj/item/tank/internals/emergency_oxygen, /obj/item/rcd, /obj/item/rpd)
|
||||
resistance_flags = NONE
|
||||
|
||||
sprite_sheets = list(
|
||||
@@ -339,7 +339,7 @@
|
||||
item_state = "fr_jacket_open"
|
||||
blood_overlay_type = "armor"
|
||||
allowed = list(/obj/item/stack/medical, /obj/item/reagent_containers/dropper, /obj/item/reagent_containers/hypospray, /obj/item/reagent_containers/applicator, /obj/item/reagent_containers/syringe,
|
||||
/obj/item/healthanalyzer, /obj/item/flashlight, /obj/item/radio, /obj/item/tank/emergency_oxygen,/obj/item/rad_laser)
|
||||
/obj/item/healthanalyzer, /obj/item/flashlight, /obj/item/radio, /obj/item/tank/internals/emergency_oxygen,/obj/item/rad_laser)
|
||||
ignore_suitadjust = 0
|
||||
suit_adjusted = 1
|
||||
actions_types = list(/datum/action/item_action/button)
|
||||
|
||||
@@ -139,7 +139,7 @@
|
||||
item_state = "syndicate-black-red"
|
||||
desc = "A plastic replica of the syndicate space suit, you'll look just like a real murderous syndicate agent in this! This is a toy, it is not made for use in space!"
|
||||
w_class = WEIGHT_CLASS_NORMAL
|
||||
allowed = list(/obj/item/flashlight,/obj/item/tank/emergency_oxygen,/obj/item/toy)
|
||||
allowed = list(/obj/item/flashlight,/obj/item/tank/internals/emergency_oxygen,/obj/item/toy)
|
||||
flags_inv = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT
|
||||
resistance_flags = NONE
|
||||
|
||||
@@ -160,7 +160,7 @@
|
||||
item_state = "imperium_monk"
|
||||
body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS
|
||||
flags_inv = HIDESHOES|HIDEJUMPSUIT
|
||||
allowed = list(/obj/item/storage/bible, /obj/item/nullrod, /obj/item/reagent_containers/food/drinks/bottle/holywater, /obj/item/storage/fancy/candle_box, /obj/item/candle, /obj/item/tank/emergency_oxygen)
|
||||
allowed = list(/obj/item/storage/bible, /obj/item/nullrod, /obj/item/reagent_containers/food/drinks/bottle/holywater, /obj/item/storage/fancy/candle_box, /obj/item/candle, /obj/item/tank/internals/emergency_oxygen)
|
||||
|
||||
/obj/item/clothing/suit/chickensuit
|
||||
name = "chicken suit"
|
||||
@@ -223,7 +223,7 @@
|
||||
item_state = "holidaypriest"
|
||||
body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS
|
||||
flags_inv = HIDEJUMPSUIT
|
||||
allowed = list(/obj/item/storage/bible, /obj/item/nullrod, /obj/item/reagent_containers/food/drinks/bottle/holywater, /obj/item/storage/fancy/candle_box, /obj/item/candle, /obj/item/tank/emergency_oxygen)
|
||||
allowed = list(/obj/item/storage/bible, /obj/item/nullrod, /obj/item/reagent_containers/food/drinks/bottle/holywater, /obj/item/storage/fancy/candle_box, /obj/item/candle, /obj/item/tank/internals/emergency_oxygen)
|
||||
|
||||
/obj/item/clothing/suit/cardborg
|
||||
name = "cardborg suit"
|
||||
@@ -299,7 +299,7 @@
|
||||
body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS
|
||||
cold_protection = UPPER_TORSO|LOWER_TORSO|ARMS
|
||||
min_cold_protection_temperature = FIRE_SUIT_MIN_TEMP_PROTECT //Space carp like space, so you should too
|
||||
allowed = list(/obj/item/tank/emergency_oxygen)
|
||||
allowed = list(/obj/item/tank/internals/emergency_oxygen)
|
||||
hoodtype = /obj/item/clothing/head/hooded/carp_hood
|
||||
|
||||
/obj/item/clothing/head/hooded/carp_hood
|
||||
@@ -371,7 +371,7 @@
|
||||
cold_protection = UPPER_TORSO|LOWER_TORSO|ARMS
|
||||
min_cold_protection_temperature = FIRE_SUIT_MIN_TEMP_PROTECT
|
||||
armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 10, "rad" = 0, "fire" = 0, "acid" = 0)
|
||||
allowed = list(/obj/item/flashlight, /obj/item/tank/emergency_oxygen, /obj/item/toy, /obj/item/storage/fancy/cigarettes, /obj/item/lighter)
|
||||
allowed = list(/obj/item/flashlight, /obj/item/tank/internals/emergency_oxygen, /obj/item/toy, /obj/item/storage/fancy/cigarettes, /obj/item/lighter)
|
||||
|
||||
sprite_sheets = list("Vox" = 'icons/mob/species/vox/suit.dmi')
|
||||
|
||||
@@ -441,7 +441,7 @@
|
||||
w_class = WEIGHT_CLASS_NORMAL
|
||||
item_state = "coatengineer"
|
||||
armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 20, "fire" = 30, "acid" = 45)
|
||||
allowed = list(/obj/item/flashlight, /obj/item/tank/emergency_oxygen, /obj/item/t_scanner, /obj/item/rcd)
|
||||
allowed = list(/obj/item/flashlight, /obj/item/tank/internals/emergency_oxygen, /obj/item/t_scanner, /obj/item/rcd)
|
||||
hoodtype = /obj/item/clothing/head/hooded/winterhood/engineering
|
||||
|
||||
/obj/item/clothing/head/hooded/winterhood/engineering
|
||||
@@ -480,7 +480,7 @@
|
||||
icon_state = "wintercoat_miner"
|
||||
w_class = WEIGHT_CLASS_NORMAL
|
||||
item_state = "coatminer"
|
||||
allowed = list(/obj/item/pickaxe, /obj/item/flashlight, /obj/item/tank/emergency_oxygen, /obj/item/toy, /obj/item/storage/fancy/cigarettes, /obj/item/lighter)
|
||||
allowed = list(/obj/item/pickaxe, /obj/item/flashlight, /obj/item/tank/internals/emergency_oxygen, /obj/item/toy, /obj/item/storage/fancy/cigarettes, /obj/item/lighter)
|
||||
armor = list("melee" = 10, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 0, "acid" = 0)
|
||||
hoodtype = /obj/item/clothing/head/hooded/winterhood/miner
|
||||
|
||||
@@ -499,7 +499,7 @@
|
||||
icon_state = "black_hoodie"
|
||||
item_state = "blueshieldcoat"
|
||||
body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS
|
||||
allowed = list(/obj/item/flashlight, /obj/item/tank/emergency_oxygen)
|
||||
allowed = list(/obj/item/flashlight, /obj/item/tank/internals/emergency_oxygen)
|
||||
hoodtype = /obj/item/clothing/head/hooded/hood
|
||||
sprite_sheets = list(
|
||||
"Vox" = 'icons/mob/species/vox/suit.dmi'
|
||||
@@ -690,7 +690,7 @@
|
||||
ignore_suitadjust = 1
|
||||
actions_types = list()
|
||||
adjust_flavour = null
|
||||
allowed = list(/obj/item/flashlight,/obj/item/tank/emergency_oxygen,/obj/item/toy,/obj/item/storage/fancy/cigarettes,/obj/item/lighter,/obj/item/gun/projectile/automatic/pistol,/obj/item/gun/projectile/revolver,/obj/item/gun/projectile/revolver/detective)
|
||||
allowed = list(/obj/item/flashlight,/obj/item/tank/internals/emergency_oxygen,/obj/item/toy,/obj/item/storage/fancy/cigarettes,/obj/item/lighter,/obj/item/gun/projectile/automatic/pistol,/obj/item/gun/projectile/revolver,/obj/item/gun/projectile/revolver/detective)
|
||||
|
||||
/obj/item/clothing/suit/jacket/miljacket/navy
|
||||
name = "navy military jacket"
|
||||
@@ -757,7 +757,7 @@
|
||||
gas_transfer_coefficient = 0.01
|
||||
permeability_coefficient = 0.01
|
||||
body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|FEET|ARMS|HANDS
|
||||
allowed = list(/obj/item/tank/emergency_oxygen,/obj/item/pen,/obj/item/flashlight/pen)
|
||||
allowed = list(/obj/item/tank/internals/emergency_oxygen,/obj/item/pen,/obj/item/flashlight/pen)
|
||||
armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 100, rad = 20, fire = 50, acid = 50)
|
||||
flags_inv = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT|HIDETAIL
|
||||
|
||||
@@ -778,7 +778,7 @@
|
||||
icon_state = "bomber"
|
||||
item_state = "bomber"
|
||||
ignore_suitadjust = 0
|
||||
allowed = list(/obj/item/flashlight,/obj/item/tank/emergency_oxygen,/obj/item/toy,/obj/item/storage/fancy/cigarettes,/obj/item/lighter)
|
||||
allowed = list(/obj/item/flashlight,/obj/item/tank/internals/emergency_oxygen,/obj/item/toy,/obj/item/storage/fancy/cigarettes,/obj/item/lighter)
|
||||
body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS
|
||||
cold_protection = UPPER_TORSO|LOWER_TORSO|ARMS
|
||||
min_cold_protection_temperature = FIRE_SUIT_MIN_TEMP_PROTECT
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
gas_transfer_coefficient = 0.90
|
||||
permeability_coefficient = 0.50
|
||||
body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|FEET|ARMS|HANDS
|
||||
allowed = list(/obj/item/flashlight,/obj/item/tank/emergency_oxygen,/obj/item/extinguisher)
|
||||
allowed = list(/obj/item/flashlight,/obj/item/tank/internals/emergency_oxygen,/obj/item/extinguisher)
|
||||
slowdown = 1
|
||||
armor = list("melee" = 15, "bullet" = 5, "laser" = 20, "energy" = 10, "bomb" = 20, "bio" = 10, "rad" = 20, "fire" = 100, "acid" = 50)
|
||||
flags_inv = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT|HIDETAIL
|
||||
@@ -131,7 +131,7 @@
|
||||
strip_delay = 60
|
||||
put_on_delay = 60
|
||||
resistance_flags = NONE
|
||||
|
||||
flags_2 = RAD_PROTECT_CONTENTS_2
|
||||
sprite_sheets = list(
|
||||
"Vox" = 'icons/mob/species/vox/head.dmi',
|
||||
"Grey" = 'icons/mob/species/grey/head.dmi'
|
||||
@@ -147,14 +147,14 @@
|
||||
permeability_coefficient = 0.50
|
||||
flags = THICKMATERIAL
|
||||
body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|FEET|ARMS|HANDS
|
||||
allowed = list(/obj/item/flashlight,/obj/item/tank/emergency_oxygen)
|
||||
allowed = list(/obj/item/flashlight,/obj/item/tank/internals/emergency_oxygen, /obj/item/geiger_counter)
|
||||
slowdown = 1.5
|
||||
armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 60, "rad" = 100, "fire" = 30, "acid" = 30)
|
||||
flags_inv = HIDEJUMPSUIT|HIDETAIL
|
||||
strip_delay = 60
|
||||
put_on_delay = 60
|
||||
resistance_flags = NONE
|
||||
|
||||
flags_2 = RAD_PROTECT_CONTENTS_2
|
||||
sprite_sheets = list(
|
||||
"Vox" = 'icons/mob/species/vox/suit.dmi'
|
||||
)
|
||||
|
||||
@@ -270,7 +270,6 @@
|
||||
item_color = "holobadge"
|
||||
slot_flags = SLOT_BELT | SLOT_TIE
|
||||
|
||||
var/emagged = FALSE //Emagging removes Sec check.
|
||||
var/stored_name = null
|
||||
|
||||
/obj/item/clothing/accessory/holobadge/cord
|
||||
|
||||
@@ -70,6 +70,13 @@
|
||||
item_state = "clown_envirosuit"
|
||||
item_color = "clown_envirosuit"
|
||||
|
||||
/obj/item/clothing/under/plasmaman/assistant
|
||||
name = "Assistant envirosuit"
|
||||
desc = "The finest from the bottom of the plasmamen clothing barrel."
|
||||
icon_state = "assistant_envirosuit"
|
||||
item_state = "assistant_envirosuit"
|
||||
item_color = "assistant_envirosuit"
|
||||
|
||||
/obj/item/clothing/under/plasmaman/clown/Extinguish(mob/living/carbon/human/H)
|
||||
if(!istype(H))
|
||||
return
|
||||
|
||||
@@ -91,6 +91,17 @@
|
||||
var/completion = round(C.get_completion())
|
||||
return completion
|
||||
|
||||
/obj/effect/countdown/supermatter
|
||||
name = "supermatter damage"
|
||||
text_size = 1
|
||||
color = "#00ff80"
|
||||
|
||||
/obj/effect/countdown/supermatter/get_value()
|
||||
var/obj/machinery/power/supermatter_crystal/S = attached_to
|
||||
if(!istype(S))
|
||||
return
|
||||
return "<div align='center' valign='middle' style='position:relative; top:0px; left:0px'>[round(S.get_integrity(), 1)]%</div>"
|
||||
|
||||
/obj/effect/countdown/anomaly
|
||||
name = "anomaly countdown"
|
||||
|
||||
|
||||
@@ -523,6 +523,14 @@
|
||||
tools = list(TOOL_SCREWDRIVER, TOOL_WRENCH, TOOL_WELDER)
|
||||
category = CAT_MISC
|
||||
|
||||
/datum/crafting_recipe/ghettojetpack
|
||||
name = "Improvised Jetpack"
|
||||
result = /obj/item/tank/jetpack/improvised
|
||||
time = 30
|
||||
reqs = list(/obj/item/tank/internals/oxygen = 2, /obj/item/extinguisher = 1, /obj/item/pipe = 3, /obj/item/stack/cable_coil = MAXCOIL)
|
||||
category = CAT_MISC
|
||||
tools = list(TOOL_WRENCH, TOOL_WELDER, TOOL_WIRECUTTER)
|
||||
|
||||
/datum/crafting_recipe/drill
|
||||
name = "Thermal Drill"
|
||||
result = /obj/item/thermal_drill
|
||||
|
||||
@@ -807,7 +807,7 @@
|
||||
item_state = "supplymaster_jacket_open"
|
||||
ignore_suitadjust = 0
|
||||
suit_adjusted = 1
|
||||
allowed = list(/obj/item/flashlight,/obj/item/tank/emergency_oxygen,/obj/item/toy,/obj/item/storage/fancy/cigarettes,/obj/item/lighter)
|
||||
allowed = list(/obj/item/flashlight,/obj/item/tank/internals/emergency_oxygen,/obj/item/toy,/obj/item/storage/fancy/cigarettes,/obj/item/lighter)
|
||||
body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS
|
||||
cold_protection = UPPER_TORSO|LOWER_TORSO|ARMS
|
||||
actions_types = list(/datum/action/item_action/button)
|
||||
@@ -971,7 +971,7 @@
|
||||
icon_state = "xantholne_wintercoat"
|
||||
hoodtype = /obj/item/clothing/head/hooded/hood/fluff/xantholne
|
||||
body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS
|
||||
allowed = list(/obj/item/flashlight, /obj/item/tank/emergency_oxygen, /obj/item/toy, /obj/item/storage/fancy/cigarettes, /obj/item/lighter)
|
||||
allowed = list(/obj/item/flashlight, /obj/item/tank/internals/emergency_oxygen, /obj/item/toy, /obj/item/storage/fancy/cigarettes, /obj/item/lighter)
|
||||
|
||||
|
||||
/obj/item/clothing/head/hooded/hood/fluff/xantholne // Xantholne: Meex Zwichsnicrur
|
||||
@@ -992,7 +992,7 @@
|
||||
hoodtype = /obj/item/clothing/head/hooded/hood/fluff/xydonus
|
||||
body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS
|
||||
cold_protection = UPPER_TORSO|LOWER_TORSO|ARMS
|
||||
allowed = list(/obj/item/flashlight,/obj/item/tank/emergency_oxygen,/obj/item/toy,/obj/item/storage/fancy/cigarettes,/obj/item/lighter)
|
||||
allowed = list(/obj/item/flashlight,/obj/item/tank/internals/emergency_oxygen,/obj/item/toy,/obj/item/storage/fancy/cigarettes,/obj/item/lighter)
|
||||
|
||||
/obj/item/clothing/head/hooded/hood/fluff/xydonus
|
||||
name = "custom fit hood"
|
||||
@@ -1055,7 +1055,7 @@
|
||||
icon_state = "dtxbomber"
|
||||
item_state = "dtxbomber"
|
||||
ignore_suitadjust = 0
|
||||
allowed = list(/obj/item/flashlight,/obj/item/tank/emergency_oxygen,/obj/item/toy,/obj/item/storage/fancy/cigarettes,/obj/item/lighter)
|
||||
allowed = list(/obj/item/flashlight,/obj/item/tank/internals/emergency_oxygen,/obj/item/toy,/obj/item/storage/fancy/cigarettes,/obj/item/lighter)
|
||||
body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS
|
||||
cold_protection = UPPER_TORSO|LOWER_TORSO|ARMS
|
||||
actions_types = list(/datum/action/item_action/zipper)
|
||||
@@ -1213,7 +1213,7 @@
|
||||
icon = 'icons/obj/custom_items.dmi'
|
||||
icon_state = "fox_jacket"
|
||||
item_state = "fox_jacket"
|
||||
allowed = list(/obj/item/flashlight, /obj/item/tank/emergency_oxygen, /obj/item/toy, /obj/item/storage/fancy/cigarettes, /obj/item/lighter, /obj/item/gun/projectile/automatic/pistol, /obj/item/gun/projectile/revolver, /obj/item/gun/projectile/revolver/detective)
|
||||
allowed = list(/obj/item/flashlight, /obj/item/tank/internals/emergency_oxygen, /obj/item/toy, /obj/item/storage/fancy/cigarettes, /obj/item/lighter, /obj/item/gun/projectile/automatic/pistol, /obj/item/gun/projectile/revolver, /obj/item/gun/projectile/revolver/detective)
|
||||
body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS
|
||||
cold_protection = UPPER_TORSO|LOWER_TORSO|ARMS
|
||||
min_cold_protection_temperature = FIRE_SUIT_MIN_TEMP_PROTECT
|
||||
@@ -1583,7 +1583,7 @@
|
||||
item_state = "asmer_accordion"
|
||||
|
||||
|
||||
/obj/item/clothing/head/fluff/pinesalad_horns //Pineapple Salad: Dan Jello
|
||||
/obj/item/clothing/head/fluff/pinesalad_horns //Pineapple Salad: Dan Jello
|
||||
name = "Bluespace Horns"
|
||||
desc = "A pair of fake horns. Now with added bluespace!"
|
||||
icon = 'icons/obj/custom_items.dmi'
|
||||
|
||||
@@ -28,7 +28,7 @@ GLOBAL_LIST_EMPTY(weighted_mundaneevent_locations)
|
||||
|
||||
/datum/trade_destination/anansi
|
||||
name = "NSS Anansi"
|
||||
description = "Medical station ran by Second Red Cross (but owned by NT) for handling emergency cases from nearby colonies."
|
||||
description = "Medical station ran by Second Green Cross (but owned by NT) for handling emergency cases from nearby colonies."
|
||||
distance = 1.7
|
||||
willing_to_buy = list()
|
||||
willing_to_sell = list()
|
||||
@@ -37,7 +37,7 @@ GLOBAL_LIST_EMPTY(weighted_mundaneevent_locations)
|
||||
|
||||
/datum/trade_destination/anansi/get_custom_eventstring(var/event_type)
|
||||
if(event_type == RESEARCH_BREAKTHROUGH)
|
||||
return "Thanks to research conducted on the NSS Anansi, Second Red Cross Society wishes to announce a major breakthough in the field of \
|
||||
return "Thanks to research conducted on the NSS Anansi, Second Green Cross Society wishes to announce a major breakthough in the field of \
|
||||
[pick("mind-machine interfacing","neuroscience","nano-augmentation","genetics")]. Nanotrasen is expected to announce a co-exploitation deal within the fortnight."
|
||||
return null
|
||||
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
/datum/event/abductor
|
||||
|
||||
/datum/event/abductor/start()
|
||||
//spawn abductor team
|
||||
processing = 0 //so it won't fire again in next tick
|
||||
INVOKE_ASYNC(src, .proc/try_makeAbductorTeam)
|
||||
|
||||
/datum/event/abductor/proc/try_makeAbductorTeam()
|
||||
if(!makeAbductorTeam())
|
||||
message_admins("Abductor event failed to find players. Retrying in 30s.")
|
||||
spawn(300)
|
||||
makeAbductorTeam()
|
||||
addtimer(CALLBACK(src, .proc/makeAbductorTeam), 30 SECONDS)
|
||||
|
||||
/datum/event/abductor/proc/makeAbductorTeam()
|
||||
var/list/mob/dead/observer/candidates = SSghost_spawns.poll_candidates("Do you wish to be considered for an Abductor Team?", ROLE_ABDUCTOR, TRUE)
|
||||
@@ -46,7 +46,6 @@
|
||||
|
||||
if(SSticker.mode.config_tag != "abduction")
|
||||
SSticker.mode.abductors |= temp.abductors
|
||||
processing = 1 //So it will get gc'd
|
||||
return 1
|
||||
else
|
||||
return 0
|
||||
|
||||
@@ -15,23 +15,24 @@
|
||||
log_and_message_admins("Warning: Could not spawn any mobs for event Alien Infestation")
|
||||
|
||||
/datum/event/alien_infestation/start()
|
||||
var/list/vents = get_valid_vent_spawns(exclude_mobs_nearby = TRUE, exclude_visible_by_mobs = TRUE)
|
||||
playercount = length(GLOB.clients)//grab playercount when event starts not when game starts
|
||||
if(playercount >= highpop_trigger) //spawn with 4 if highpop
|
||||
spawncount = 4
|
||||
INVOKE_ASYNC(src, .proc/spawn_xenos)
|
||||
|
||||
spawn()
|
||||
var/list/candidates = SSghost_spawns.poll_candidates("Do you want to play as an alien?", ROLE_ALIEN, TRUE, source = /mob/living/carbon/alien/larva)
|
||||
while(spawncount && length(vents) && length(candidates))
|
||||
var/obj/vent = pick_n_take(vents)
|
||||
var/mob/C = pick_n_take(candidates)
|
||||
if(C)
|
||||
GLOB.respawnable_list -= C.client
|
||||
var/mob/living/carbon/alien/larva/new_xeno = new(vent.loc)
|
||||
new_xeno.amount_grown += (0.75 * new_xeno.max_grown) //event spawned larva start off almost ready to evolve.
|
||||
new_xeno.key = C.key
|
||||
if(SSticker && SSticker.mode)
|
||||
SSticker.mode.xenos += new_xeno.mind
|
||||
/datum/event/alien_infestation/proc/spawn_xenos()
|
||||
var/list/candidates = SSghost_spawns.poll_candidates("Do you want to play as an alien?", ROLE_ALIEN, TRUE, source = /mob/living/carbon/alien/larva)
|
||||
var/list/vents = get_valid_vent_spawns(exclude_mobs_nearby = TRUE, exclude_visible_by_mobs = TRUE)
|
||||
while(spawncount && length(vents) && length(candidates))
|
||||
var/obj/vent = pick_n_take(vents)
|
||||
var/mob/C = pick_n_take(candidates)
|
||||
if(C)
|
||||
GLOB.respawnable_list -= C.client
|
||||
var/mob/living/carbon/alien/larva/new_xeno = new(vent.loc)
|
||||
new_xeno.amount_grown += (0.75 * new_xeno.max_grown) //event spawned larva start off almost ready to evolve.
|
||||
new_xeno.key = C.key
|
||||
if(SSticker && SSticker.mode)
|
||||
SSticker.mode.xenos += new_xeno.mind
|
||||
|
||||
spawncount--
|
||||
successSpawn = TRUE
|
||||
spawncount--
|
||||
successSpawn = TRUE
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
/proc/apc_overload_failure(announce=TRUE)
|
||||
var/list/skipped_areas_apc = list(
|
||||
/area/engine/engineering,
|
||||
/area/engine/supermatter,
|
||||
/area/turret_protected/ai)
|
||||
|
||||
if(announce)
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
/proc/power_failure(announce=TRUE)
|
||||
var/list/skipped_areas_apc = list(
|
||||
/area/engine/engineering,
|
||||
/area/engine/supermatter,
|
||||
/area/turret_protected/ai)
|
||||
|
||||
if(announce)
|
||||
|
||||
@@ -10,12 +10,12 @@
|
||||
log_and_message_admins("Warning: Could not spawn any mobs for event Blob")
|
||||
|
||||
/datum/event/blob/start()
|
||||
processing = FALSE //so it won't fire again in next tick
|
||||
|
||||
var/turf/T = pick(GLOB.blobstart)
|
||||
if(!T)
|
||||
return kill()
|
||||
INVOKE_ASYNC(src, .proc/make_blob)
|
||||
|
||||
/datum/event/blob/proc/make_blob()
|
||||
var/list/candidates = SSghost_spawns.poll_candidates("Do you want to play as a blob infested mouse?", ROLE_BLOB, TRUE, source = /mob/living/simple_animal/mouse/blobinfected)
|
||||
if(!length(candidates))
|
||||
return kill()
|
||||
@@ -32,4 +32,3 @@
|
||||
to_chat(B, "<span class='userdanger'>You are now a mouse, infected with blob spores. Find somewhere isolated... before you burst and become the blob! Use ventcrawl (alt-click on vents) to move around.</span>")
|
||||
notify_ghosts("Infected Mouse has appeared in [get_area(B)].", source = B)
|
||||
successSpawn = TRUE
|
||||
processing = TRUE // Let it naturally end, if it runs successfully
|
||||
|
||||
+24
-20
@@ -18,6 +18,7 @@
|
||||
var/strength = 2 //ex_act severity number
|
||||
var/life = 2 //how many things we hit before qdel(src)
|
||||
var/atom/goal = null
|
||||
var/shake_chance = 50
|
||||
|
||||
/obj/effect/space_dust/weak
|
||||
strength = 3
|
||||
@@ -64,30 +65,33 @@
|
||||
src.x = startx
|
||||
src.y = starty
|
||||
src.z = level_name_to_num(MAIN_STATION)
|
||||
spawn(0)
|
||||
walk_towards(src, goal, 1)
|
||||
return
|
||||
walk_towards(src, goal, 1)
|
||||
|
||||
/obj/effect/space_dust/Bump(atom/A)
|
||||
spawn(0)
|
||||
if(prob(50))
|
||||
for(var/mob/M in range(10, src))
|
||||
if(!M.stat && !istype(M, /mob/living/silicon/ai))
|
||||
shake_camera(M, 3, 1)
|
||||
if(A)
|
||||
playsound(src.loc, 'sound/effects/meteorimpact.ogg', 40, 1)
|
||||
if(QDELETED(src))
|
||||
return
|
||||
if(prob(shake_chance))
|
||||
for(var/mob/M in range(10, src))
|
||||
if(!M.stat && !istype(M, /mob/living/silicon/ai))
|
||||
shake_camera(M, 3, 1)
|
||||
playsound(loc, 'sound/effects/meteorimpact.ogg', 40, 1)
|
||||
|
||||
if(ismob(A))
|
||||
A.ex_act(strength)//This should work for now I guess
|
||||
else if(!istype(A,/obj/machinery/power/emitter) && !istype(A,/obj/machinery/field/generator)) //Protect the singularity from getting released every round!
|
||||
A.ex_act(strength) //Changing emitter/field gen ex_act would make it immune to bombs and C4
|
||||
INVOKE_ASYNC(src, .proc/impact_meteor, A) // ex_act can have some sleeps in it
|
||||
|
||||
life--
|
||||
if(life <= 0)
|
||||
walk(src,0)
|
||||
spawn(1)
|
||||
qdel(src)
|
||||
return
|
||||
/obj/effect/space_dust/proc/impact_meteor(atom/A)
|
||||
var/turf/where = get_turf(A)
|
||||
if(ismob(A))
|
||||
A.ex_act(strength)//This should work for now I guess
|
||||
else if(!istype(A, /obj/machinery/power/emitter) && !istype(A, /obj/machinery/field/generator)) //Protect the singularity from getting released every round!
|
||||
A.ex_act(strength) //Changing emitter/field gen ex_act would make it immune to bombs and C4
|
||||
|
||||
life--
|
||||
if(life <= 0)
|
||||
walk(src, 0)
|
||||
on_shatter(where)
|
||||
qdel(src)
|
||||
|
||||
/obj/effect/space_dust/proc/on_shatter(turf/where)
|
||||
return
|
||||
|
||||
/obj/effect/space_dust/Bumped(atom/A)
|
||||
|
||||
@@ -53,7 +53,6 @@
|
||||
/datum/event //NOTE: Times are measured in master controller ticks!
|
||||
/// The human-readable name of the event
|
||||
var/name
|
||||
var/processing = 1
|
||||
/// When in the lifetime to call start().
|
||||
var/startWhen = 0
|
||||
/// When in the lifetime to call announce().
|
||||
@@ -93,6 +92,7 @@
|
||||
*
|
||||
* Allows you to start before announcing or vice versa.
|
||||
* Only called once.
|
||||
* Ensure no sleep is called. Use INVOKE_ASYNC to call procs which do.
|
||||
*/
|
||||
/datum/event/proc/start()
|
||||
return
|
||||
@@ -102,6 +102,7 @@
|
||||
*
|
||||
* Allows you to announce before starting or vice versa.
|
||||
* Only called once.
|
||||
* Ensure no sleep is called. Use INVOKE_ASYNC to call procs which do.
|
||||
*/
|
||||
/datum/event/proc/announce()
|
||||
return
|
||||
@@ -112,6 +113,7 @@
|
||||
* You can include code related to your event or add your own
|
||||
* time stamped events.
|
||||
* Called more than once.
|
||||
* Ensure no sleep is called. Use INVOKE_ASYNC to call procs which do.
|
||||
*/
|
||||
/datum/event/proc/tick()
|
||||
return
|
||||
@@ -124,6 +126,7 @@
|
||||
* the activeFor variable.
|
||||
* For example: if(activeFor == myOwnVariable + 30) doStuff()
|
||||
* Only called once.
|
||||
* Ensure no sleep is called. Use INVOKE_ASYNC to call procs which do.
|
||||
*/
|
||||
/datum/event/proc/end()
|
||||
return
|
||||
@@ -138,11 +141,9 @@
|
||||
* Do not override this proc, instead use the appropiate procs.
|
||||
*
|
||||
* This proc will handle the calls to the appropiate procs.
|
||||
* Ensure none of the code paths have a sleep in them. Use INVOKE_ASYNC to call procs which do.
|
||||
*/
|
||||
/datum/event/process()
|
||||
if(!processing)
|
||||
return
|
||||
|
||||
if(activeFor > startWhen && activeFor < endWhen || noAutoEnd)
|
||||
tick()
|
||||
|
||||
|
||||
@@ -15,8 +15,8 @@ In my current plan for it, 'solid' will be defined as anything with density == 1
|
||||
|
||||
/datum/event/immovable_rod/start()
|
||||
var/startside = pick(GLOB.cardinal)
|
||||
var/turf/startT = spaceDebrisStartLoc(startside, 1)
|
||||
var/turf/endT = spaceDebrisFinishLoc(startside, 1)
|
||||
var/turf/startT = spaceDebrisStartLoc(startside, level_name_to_num(MAIN_STATION))
|
||||
var/turf/endT = spaceDebrisFinishLoc(startside, level_name_to_num(MAIN_STATION))
|
||||
new /obj/effect/immovablerod/event(startT, endT)
|
||||
|
||||
/obj/effect/immovablerod
|
||||
@@ -25,8 +25,8 @@ In my current plan for it, 'solid' will be defined as anything with density == 1
|
||||
icon = 'icons/obj/objects.dmi'
|
||||
icon_state = "immrod"
|
||||
throwforce = 100
|
||||
density = 1
|
||||
anchored = 1
|
||||
density = TRUE
|
||||
anchored = TRUE
|
||||
var/z_original = 0
|
||||
var/destination
|
||||
var/notify = TRUE
|
||||
@@ -41,9 +41,9 @@ In my current plan for it, 'solid' will be defined as anything with density == 1
|
||||
if(notify)
|
||||
notify_ghosts("\A [src] is inbound!",
|
||||
enter_link="<a href=?src=[UID()];follow=1>(Click to follow)</a>",
|
||||
source=src, action=NOTIFY_FOLLOW)
|
||||
source = src, action = NOTIFY_FOLLOW)
|
||||
GLOB.poi_list |= src
|
||||
if(end && end.z==z_original)
|
||||
if(end?.z == z_original)
|
||||
walk_towards(src, destination, move_delay)
|
||||
|
||||
/obj/effect/immovablerod/Topic(href, href_list)
|
||||
@@ -67,21 +67,23 @@ In my current plan for it, 'solid' will be defined as anything with density == 1
|
||||
|
||||
/obj/effect/immovablerod/Bump(atom/clong)
|
||||
if(prob(10))
|
||||
playsound(src, 'sound/effects/bang.ogg', 50, 1)
|
||||
playsound(src, 'sound/effects/bang.ogg', 50, TRUE)
|
||||
audible_message("CLANG")
|
||||
|
||||
if(clong && prob(25))
|
||||
x = clong.x
|
||||
y = clong.y
|
||||
|
||||
if(istype(clong, /turf) || istype(clong, /obj))
|
||||
if(isturf(clong) || isobj(clong))
|
||||
if(clong.density)
|
||||
clong.ex_act(2)
|
||||
|
||||
else if(istype(clong, /mob))
|
||||
if(istype(clong, /mob/living/carbon/human))
|
||||
else if(ismob(clong))
|
||||
if(ishuman(clong))
|
||||
var/mob/living/carbon/human/H = clong
|
||||
H.visible_message("<span class='danger'>[H.name] is penetrated by an immovable rod!</span>" , "<span class='userdanger'>The rod penetrates you!</span>" , "<span class ='danger'>You hear a CLANG!</span>")
|
||||
H.visible_message("<span class='danger'>[H.name] is penetrated by an immovable rod!</span>" ,
|
||||
"<span class='userdanger'>The rod penetrates you!</span>" ,
|
||||
"<span class ='danger'>You hear a CLANG!</span>")
|
||||
H.adjustBruteLoss(160)
|
||||
if(clong.density || prob(10))
|
||||
clong.ex_act(2)
|
||||
|
||||
@@ -80,20 +80,17 @@
|
||||
spawn_types = list(/obj/structure/spider/spiderling)
|
||||
max_number = 3
|
||||
vermstring = "spiders"
|
||||
var/amount_to_spawn = rand(2, max_number)
|
||||
while(length(turfs) && amount_to_spawn > 0)
|
||||
var/turf/simulated/floor/T = pick_n_take(turfs)
|
||||
amount_to_spawn--
|
||||
|
||||
spawn(0)
|
||||
var/num = rand(2,max_number)
|
||||
while(turfs.len > 0 && num > 0)
|
||||
var/turf/simulated/floor/T = pick(turfs)
|
||||
turfs.Remove(T)
|
||||
num--
|
||||
|
||||
if(vermin == VERM_SPIDERS)
|
||||
var/obj/structure/spider/spiderling/S = new(T)
|
||||
S.amount_grown = -1
|
||||
else
|
||||
var/spawn_type = pick(spawn_types)
|
||||
new spawn_type(T)
|
||||
if(vermin == VERM_SPIDERS)
|
||||
var/obj/structure/spider/spiderling/S = new(T)
|
||||
S.amount_grown = -1
|
||||
else
|
||||
var/spawn_type = pick(spawn_types)
|
||||
new spawn_type(T)
|
||||
|
||||
|
||||
/datum/event/infestation/announce()
|
||||
|
||||
@@ -4,14 +4,11 @@
|
||||
/datum/event/meteor_wave/gore/setup()
|
||||
waves = 3
|
||||
|
||||
/datum/event/meteor_wave/gore/get_meteor_count()
|
||||
return rand(5, 8)
|
||||
|
||||
/datum/event/meteor_wave/gore/tick()
|
||||
if(waves && activeFor >= next_meteor)
|
||||
spawn() spawn_meteors(rand(5,8), GLOB.meteors_gore)
|
||||
next_meteor += rand(15, 30)
|
||||
waves--
|
||||
endWhen = (waves ? next_meteor + 1 : activeFor + 15)
|
||||
|
||||
/datum/event/meteor_wave/gore/get_meteors()
|
||||
return GLOB.meteors_gore
|
||||
|
||||
/datum/event/meteor_wave/gore/end()
|
||||
GLOB.event_announcement.Announce("The station has cleared the debris.", "Debris Alert")
|
||||
|
||||
@@ -5,15 +5,11 @@
|
||||
/datum/event/meteor_wave/goreop/setup()
|
||||
waves = 3
|
||||
|
||||
/datum/event/meteor_wave/goreop/get_meteor_count()
|
||||
return 5
|
||||
|
||||
/datum/event/meteor_wave/goreop/tick()
|
||||
if(waves && activeFor >= next_meteor)
|
||||
spawn() spawn_meteors(5, GLOB.meteors_ops)
|
||||
next_meteor += rand(15, 30)
|
||||
waves--
|
||||
endWhen = (waves ? next_meteor + 1 : activeFor + 15)
|
||||
|
||||
|
||||
/datum/event/meteor_wave/goreop/get_meteors()
|
||||
return GLOB.meteors_ops
|
||||
|
||||
/datum/event/meteor_wave/goreop/end()
|
||||
GLOB.event_announcement.Announce("All MeteorOps are dead. Major Station Victory.", "MeteorOps")
|
||||
|
||||
@@ -8,6 +8,9 @@
|
||||
qnty = rand(45,125)
|
||||
|
||||
/datum/event/dust/meaty/start()
|
||||
INVOKE_ASYNC(src, .proc/spawn_meaty_ores)
|
||||
|
||||
/datum/event/dust/meaty/proc/spawn_meaty_ores()
|
||||
while(qnty-- > 0)
|
||||
new /obj/effect/space_dust/meaty()
|
||||
if(prob(10))
|
||||
@@ -19,35 +22,18 @@
|
||||
|
||||
strength = 1
|
||||
life = 3
|
||||
shake_chance = 20
|
||||
|
||||
/obj/effect/space_dust/meaty/Bump(atom/A)
|
||||
if(prob(20))
|
||||
spawn(1)
|
||||
for(var/mob/M in range(10, src))
|
||||
if(!M.stat && !istype(M, /mob/living/silicon/ai))
|
||||
shake_camera(M, 3, 1)
|
||||
if(A)
|
||||
playsound(src.loc, 'sound/effects/meteorimpact.ogg', 40, 1)
|
||||
walk(src,0)
|
||||
invisibility = 101
|
||||
new /obj/effect/decal/cleanable/blood(get_turf(A))
|
||||
if(ismob(A))
|
||||
A.ex_act(strength)
|
||||
else
|
||||
spawn(0)
|
||||
if(A)
|
||||
A.ex_act(strength)
|
||||
if(src)
|
||||
walk_towards(src,goal,1)
|
||||
life--
|
||||
if(!life)
|
||||
if(prob(80))
|
||||
gibs(loc)
|
||||
if(prob(45))
|
||||
new /obj/item/reagent_containers/food/snacks/meat(loc)
|
||||
else if(prob(10))
|
||||
explosion(get_turf(loc), 0, pick(0,1), pick(2,3), 0)
|
||||
else
|
||||
new /mob/living/simple_animal/cow(loc)
|
||||
/obj/effect/space_dust/meaty/impact_meteor(atom/A)
|
||||
new /obj/effect/decal/cleanable/blood(get_turf(A))
|
||||
..()
|
||||
|
||||
qdel(src)
|
||||
/obj/effect/space_dust/meaty/on_shatter(turf/where)
|
||||
if(prob(80))
|
||||
gibs(where)
|
||||
if(prob(45))
|
||||
new /obj/item/reagent_containers/food/snacks/meat(where)
|
||||
else if(prob(10))
|
||||
explosion(where, 0, pick(0,1), pick(2,3), 0)
|
||||
else
|
||||
new /mob/living/simple_animal/cow(where)
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
//meteor showers are lighter and more common,
|
||||
/datum/event/meteor_wave/tick()
|
||||
if(waves && activeFor >= next_meteor)
|
||||
spawn() spawn_meteors(severity * rand(1,2), get_meteors())
|
||||
INVOKE_ASYNC(GLOBAL_PROC, .proc/spawn_meteors, get_meteor_count(), get_meteors())
|
||||
next_meteor += rand(15, 30) / severity
|
||||
waves--
|
||||
endWhen = (waves ? next_meteor + 1 : activeFor + 15)
|
||||
@@ -37,3 +37,6 @@
|
||||
return GLOB.meteors_threatening
|
||||
else
|
||||
return GLOB.meteors_normal
|
||||
|
||||
/datum/event/meteor_wave/proc/get_meteor_count()
|
||||
return severity * rand(1, 2)
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
/datum/event/sentience
|
||||
|
||||
/datum/event/sentience/start()
|
||||
processing = FALSE //so it won't fire again in next tick
|
||||
INVOKE_ASYNC(src, .proc/make_sentient_mob)
|
||||
|
||||
/datum/event/sentience/proc/make_sentient_mob()
|
||||
var/list/candidates = SSghost_spawns.poll_candidates("Do you want to awaken as a sentient being?", ROLE_SENTIENT, TRUE)
|
||||
var/list/potential = list()
|
||||
var/sentience_type = SENTIENCE_ORGANIC
|
||||
@@ -40,7 +41,6 @@
|
||||
SA.del_on_death = FALSE
|
||||
greet_sentient(SA)
|
||||
print_command_report(sentience_report, "[command_name()] Update", FALSE)
|
||||
processing = TRUE // Let it naturally end, if it runs successfully
|
||||
|
||||
/datum/event/sentience/proc/greet_sentient(var/mob/living/carbon/human/M)
|
||||
to_chat(M, "<span class='userdanger'>Hello world!</span>")
|
||||
|
||||
@@ -1,49 +1,48 @@
|
||||
/datum/event/spawn_slaughter
|
||||
var/key_of_slaughter
|
||||
|
||||
/datum/event/spawn_slaughter/proc/get_slaughter(var/end_if_fail = 0)
|
||||
spawn()
|
||||
var/list/candidates = SSghost_spawns.poll_candidates("Do you want to play as a slaughter demon?", ROLE_DEMON, TRUE, source = /mob/living/simple_animal/slaughter)
|
||||
if(!candidates.len)
|
||||
key_of_slaughter = null
|
||||
kill()
|
||||
return
|
||||
var/mob/C = pick(candidates)
|
||||
key_of_slaughter = C.key
|
||||
/datum/event/spawn_slaughter/proc/get_slaughter()
|
||||
var/list/candidates = SSghost_spawns.poll_candidates("Do you want to play as a slaughter demon?", ROLE_DEMON, TRUE, source = /mob/living/simple_animal/slaughter)
|
||||
if(!length(candidates))
|
||||
kill()
|
||||
return
|
||||
|
||||
if(!key_of_slaughter)
|
||||
kill()
|
||||
return
|
||||
var/mob/C = pick(candidates)
|
||||
key_of_slaughter = C.key
|
||||
|
||||
var/datum/mind/player_mind = new /datum/mind(key_of_slaughter)
|
||||
player_mind.active = 1
|
||||
var/list/spawn_locs = list()
|
||||
if(!key_of_slaughter)
|
||||
kill()
|
||||
return
|
||||
|
||||
var/datum/mind/player_mind = new /datum/mind(key_of_slaughter)
|
||||
player_mind.active = TRUE
|
||||
var/list/spawn_locs = list()
|
||||
for(var/thing in GLOB.landmarks_list)
|
||||
var/obj/effect/landmark/L = thing
|
||||
if(isturf(L.loc))
|
||||
switch(L.name)
|
||||
if("revenantspawn")
|
||||
spawn_locs += L.loc
|
||||
if(!spawn_locs) //If we can't find any revenant spawns, try the carp spawns
|
||||
for(var/thing in GLOB.landmarks_list)
|
||||
var/obj/effect/landmark/L = thing
|
||||
if(isturf(L.loc))
|
||||
switch(L.name)
|
||||
if("revenantspawn")
|
||||
if("carpspawn")
|
||||
spawn_locs += L.loc
|
||||
if(!spawn_locs) //If we can't find any revenant spawns, try the carp spawns
|
||||
for(var/thing in GLOB.landmarks_list)
|
||||
var/obj/effect/landmark/L = thing
|
||||
if(isturf(L.loc))
|
||||
switch(L.name)
|
||||
if("carpspawn")
|
||||
spawn_locs += L.loc
|
||||
if(!spawn_locs) //If we can't find either, just spawn the revenant at the player's location
|
||||
spawn_locs += get_turf(player_mind.current)
|
||||
if(!spawn_locs) //If we can't find THAT, then just retry
|
||||
kill()
|
||||
return
|
||||
var/obj/effect/dummy/slaughter/holder = new /obj/effect/dummy/slaughter(pick(spawn_locs))
|
||||
var/mob/living/simple_animal/slaughter/S = new /mob/living/simple_animal/slaughter/(holder)
|
||||
S.holder = holder
|
||||
player_mind.transfer_to(S)
|
||||
player_mind.assigned_role = "Slaughter Demon"
|
||||
player_mind.special_role = SPECIAL_ROLE_SLAUGHTER_DEMON
|
||||
message_admins("[key_name_admin(S)] has been made into a Slaughter Demon by an event.")
|
||||
log_game("[key_name_admin(S)] was spawned as a Slaughter Demon by an event.")
|
||||
if(!spawn_locs) //If we can't find either, just spawn the revenant at the player's location
|
||||
spawn_locs += get_turf(player_mind.current)
|
||||
if(!spawn_locs) //If we can't find THAT, then just retry
|
||||
kill()
|
||||
return
|
||||
var/obj/effect/dummy/slaughter/holder = new /obj/effect/dummy/slaughter(pick(spawn_locs))
|
||||
var/mob/living/simple_animal/slaughter/S = new /mob/living/simple_animal/slaughter/(holder)
|
||||
S.holder = holder
|
||||
player_mind.transfer_to(S)
|
||||
player_mind.assigned_role = "Slaughter Demon"
|
||||
player_mind.special_role = SPECIAL_ROLE_SLAUGHTER_DEMON
|
||||
message_admins("[key_name_admin(S)] has been made into a Slaughter Demon by an event.")
|
||||
log_game("[key_name_admin(S)] was spawned as a Slaughter Demon by an event.")
|
||||
|
||||
/datum/event/spawn_slaughter/start()
|
||||
get_slaughter()
|
||||
INVOKE_ASYNC(src, .proc/get_slaughter)
|
||||
|
||||
@@ -230,9 +230,8 @@
|
||||
if(explosion_severity < 3)
|
||||
qdel(holder)
|
||||
else
|
||||
. = 1
|
||||
spawn(5)
|
||||
holder.wither()
|
||||
addtimer(CALLBACK(holder, /obj/structure/spacevine.proc/wither), 5)
|
||||
return TRUE
|
||||
|
||||
/datum/spacevine_mutation/explosive/on_death(obj/structure/spacevine/holder, mob/hitter, obj/item/I)
|
||||
explosion(holder.loc, 0, 0, severity, 0, 0)
|
||||
|
||||
@@ -34,9 +34,7 @@
|
||||
animation.icon_state = "newtear"
|
||||
animation.icon = 'icons/effects/tear.dmi'
|
||||
animation.master = src
|
||||
spawn(15)
|
||||
if(animation)
|
||||
qdel(animation)
|
||||
QDEL_IN(animation, 15)
|
||||
|
||||
addtimer(CALLBACK(src, .proc/spew_critters), rand(30, 120))
|
||||
|
||||
|
||||
@@ -33,38 +33,39 @@ GLOBAL_LIST_INIT(unused_trade_stations, list("sol"))
|
||||
|
||||
trader_objectives = forge_trader_objectives()
|
||||
|
||||
spawn()
|
||||
var/list/candidates = SSghost_spawns.poll_candidates("Do you want to play as a Sol Trader?", ROLE_TRADER, TRUE)
|
||||
var/index = 1
|
||||
while(spawn_count > 0 && candidates.len > 0)
|
||||
if(index > spawnlocs.len)
|
||||
index = 1
|
||||
INVOKE_ASYNC(src, .proc/spawn_traders, spawnlocs)
|
||||
|
||||
var/turf/picked_loc = spawnlocs[index]
|
||||
index++
|
||||
var/mob/C = pick_n_take(candidates)
|
||||
spawn_count--
|
||||
if(C)
|
||||
GLOB.respawnable_list -= C.client
|
||||
var/mob/living/carbon/human/M = new /mob/living/carbon/human(picked_loc)
|
||||
M.ckey = C.ckey // must be before equipOutfit, or that will runtime due to lack of mind
|
||||
M.equipOutfit(/datum/outfit/admin/sol_trader)
|
||||
M.dna.species.after_equip_job(null, M)
|
||||
M.mind.objectives += trader_objectives
|
||||
M.mind.offstation_role = TRUE
|
||||
greet_trader(M)
|
||||
success_spawn = 1
|
||||
if(success_spawn)
|
||||
GLOB.event_announcement.Announce("A trading shuttle from Jupiter Station has been granted docking permission at [station_name()] arrivals port 4.", "Trader Shuttle Docking Request Accepted")
|
||||
else
|
||||
GLOB.unused_trade_stations += station // Return the station to the list of usable stations.
|
||||
/datum/event/traders/proc/spawn_traders(list/spawnlocs)
|
||||
var/list/candidates = SSghost_spawns.poll_candidates("Do you want to play as a Sol Trader?", ROLE_TRADER, TRUE)
|
||||
var/index = 1
|
||||
while(spawn_count > 0 && length(candidates))
|
||||
if(index > length(spawnlocs))
|
||||
index = 1
|
||||
|
||||
var/turf/picked_loc = spawnlocs[index]
|
||||
index++
|
||||
var/mob/C = pick_n_take(candidates)
|
||||
spawn_count--
|
||||
if(C)
|
||||
GLOB.respawnable_list -= C.client
|
||||
var/mob/living/carbon/human/M = new /mob/living/carbon/human(picked_loc)
|
||||
M.ckey = C.ckey // must be before equipOutfit, or that will runtime due to lack of mind
|
||||
M.equipOutfit(/datum/outfit/admin/sol_trader)
|
||||
M.dna.species.after_equip_job(null, M)
|
||||
M.mind.objectives += trader_objectives
|
||||
M.mind.offstation_role = TRUE
|
||||
greet_trader(M)
|
||||
success_spawn = TRUE
|
||||
if(success_spawn)
|
||||
GLOB.event_announcement.Announce("A trading shuttle from Jupiter Station has been granted docking permission at [station_name()] arrivals port 4.", "Trader Shuttle Docking Request Accepted")
|
||||
else
|
||||
GLOB.unused_trade_stations += station // Return the station to the list of usable stations.
|
||||
|
||||
/datum/event/traders/proc/greet_trader(var/mob/living/carbon/human/M)
|
||||
to_chat(M, "<span class='boldnotice'>You are a trader!</span>")
|
||||
to_chat(M, "<span class='notice'>You are currently docked at [get_area(M)].</span>")
|
||||
to_chat(M, "<span class='notice'>You are about to trade with [station_name()].</span>")
|
||||
spawn(25)
|
||||
show_objectives(M.mind)
|
||||
addtimer(CALLBACK(GLOBAL_PROC, .proc/show_objectives, M.mind), 25)
|
||||
|
||||
/datum/event/traders/proc/forge_trader_objectives()
|
||||
var/list/objs = list()
|
||||
|
||||
@@ -6,26 +6,31 @@
|
||||
GLOB.event_announcement.Announce("Harmful fungi detected on station. Station structures may be contaminated.", "Biohazard Alert")
|
||||
|
||||
/datum/event/wallrot/start()
|
||||
spawn()
|
||||
var/turf/simulated/wall/center = null
|
||||
INVOKE_ASYNC(src, .proc/spawn_wallrot)
|
||||
|
||||
// 100 attempts
|
||||
for(var/i=0, i<100, i++)
|
||||
var/turf/candidate = locate(rand(1, world.maxx), rand(1, world.maxy), 1)
|
||||
if(istype(candidate, /turf/simulated/wall))
|
||||
center = candidate
|
||||
/datum/event/wallrot/proc/spawn_wallrot()
|
||||
var/turf/simulated/wall/center = null
|
||||
|
||||
if(center)
|
||||
// Make sure at least one piece of wall rots!
|
||||
center.rot()
|
||||
// 100 attempts
|
||||
for(var/i in 0 to 100)
|
||||
var/turf/candidate = locate(rand(1, world.maxx), rand(1, world.maxy), level_name_to_num(MAIN_STATION))
|
||||
if(istype(candidate, /turf/simulated/wall))
|
||||
center = candidate
|
||||
break
|
||||
|
||||
// Have a chance to rot lots of other walls.
|
||||
var/rotcount = 0
|
||||
var/actual_severity = severity * rand(5, 10)
|
||||
for(var/turf/simulated/wall/W in range(5, center)) if(prob(50))
|
||||
W.rot()
|
||||
rotcount++
|
||||
if(!center)
|
||||
return
|
||||
// Make sure at least one piece of wall rots!
|
||||
center.rot()
|
||||
|
||||
// Only rot up to severity walls
|
||||
if(rotcount >= actual_severity)
|
||||
break
|
||||
// Have a chance to rot lots of other walls.
|
||||
var/rotcount = 0
|
||||
var/actual_severity = severity * rand(5, 10)
|
||||
for(var/turf/simulated/wall/W in range(5, center))
|
||||
if(prob(50))
|
||||
W.rot()
|
||||
rotcount++
|
||||
|
||||
// Only rot up to severity walls
|
||||
if(rotcount >= actual_severity)
|
||||
break
|
||||
|
||||
@@ -105,15 +105,9 @@
|
||||
/obj/machinery/atmospherics/unary/vent_pump
|
||||
description_info = "This pumps the contents of the attached pipe out into the atmosphere, if needed. It can be controlled from an Air Alarm."
|
||||
|
||||
//Freezers
|
||||
/obj/machinery/atmospherics/unary/cold_sink/freezer
|
||||
description_info = "Cools down the gas of the pipe it is connected to. It uses massive amounts of electricity while on. \
|
||||
It can be upgraded by replacing the capacitors, manipulators, and matter bins. It can be deconstructed by screwing the maintenance panel open with a \
|
||||
screwdriver, and then using a crowbar."
|
||||
|
||||
//Heaters
|
||||
/obj/machinery/atmospherics/unary/heat_reservoir/heater
|
||||
description_info = "Heats up the gas of the pipe it is connected to. It uses massive amounts of electricity while on. \
|
||||
//Freezer and Heater
|
||||
/obj/machinery/atmospherics/unary/thermomachine
|
||||
description_info = "Cools or heats the gas of the pipe it is connected to. It uses massive amounts of electricity while on. \
|
||||
It can be upgraded by replacing the capacitors, manipulators, and matter bins. It can be deconstructed by screwing the maintenance panel open with a \
|
||||
screwdriver, and then using a crowbar."
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/obj/machinery/power/supermatter_shard
|
||||
/obj/machinery/power/supermatter_crystal
|
||||
description_info = "When energized by a laser (or something hitting it), it emits radiation and heat. If the heat reaches above 7000 kelvin, it will send an alert and start taking damage. \
|
||||
After integrity falls to zero percent, it will delaminate, causing a massive explosion, station-wide radiation spikes, and hallucinations. \
|
||||
Supermatter reacts badly to oxygen in the atmosphere. It'll also heat up really quick if it is in vacuum.<br>\
|
||||
|
||||
@@ -705,7 +705,7 @@ GLOBAL_LIST_INIT(non_fakeattack_weapons, list(/obj/item/gun/projectile, /obj/ite
|
||||
/obj/item/hand_tele, /obj/item/rcd, /obj/item/tank/jetpack,\
|
||||
/obj/item/clothing/under/rank/captain, /obj/item/aicard,\
|
||||
/obj/item/clothing/shoes/magboots, /obj/item/areaeditor/blueprints, /obj/item/disk/nuclear,\
|
||||
/obj/item/clothing/suit/space/nasavoid, /obj/item/tank))
|
||||
/obj/item/clothing/suit/space/nasavoid, /obj/item/tank/internals))
|
||||
|
||||
/obj/effect/hallucination/bolts
|
||||
var/list/doors = list()
|
||||
|
||||
@@ -36,12 +36,6 @@
|
||||
if(istype(M, /mob/living/carbon))
|
||||
var/mob/living/carbon/C = M
|
||||
if(C.eat(src, user))
|
||||
if(isrobot(user)) //Cyborg modules that include drinks automatically refill themselves, but drain the borg's cell
|
||||
var/mob/living/silicon/robot/borg = user
|
||||
borg.cell.use(30)
|
||||
var/refill = reagents.get_master_reagent_id()
|
||||
if(refill in GLOB.drinks) // Only synthesize drinks
|
||||
addtimer(CALLBACK(reagents, /datum/reagents.proc/add_reagent, refill, bitesize), 600)
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
@@ -72,24 +66,9 @@
|
||||
to_chat(user, "<span class='warning'> [target] is full.</span>")
|
||||
return FALSE
|
||||
|
||||
var/datum/reagent/refill
|
||||
var/datum/reagent/refillName
|
||||
if(isrobot(user))
|
||||
refill = reagents.get_master_reagent_id()
|
||||
refillName = reagents.get_master_reagent_name()
|
||||
|
||||
var/trans = reagents.trans_to(target, amount_per_transfer_from_this)
|
||||
to_chat(user, "<span class='notice'> You transfer [trans] units of the solution to [target].</span>")
|
||||
|
||||
if(isrobot(user)) //Cyborg modules that include drinks automatically refill themselves, but drain the borg's cell
|
||||
if(refill in GLOB.drinks) // Only synthesize drinks
|
||||
var/mob/living/silicon/robot/bro = user
|
||||
var/chargeAmount = max(30,4*trans)
|
||||
bro.cell.use(chargeAmount)
|
||||
to_chat(user, "<span class='notice'>Now synthesizing [trans] units of [refillName]...</span>")
|
||||
addtimer(CALLBACK(reagents, /datum/reagents.proc/add_reagent, refill, trans), 300)
|
||||
addtimer(CALLBACK(GLOBAL_PROC, .proc/to_chat, user, "<span class='notice'>Cyborg [src] refilled.</span>"), 300)
|
||||
|
||||
else if(target.is_drainable()) //A dispenser. Transfer FROM it TO us.
|
||||
if(!is_refillable())
|
||||
to_chat(user, "<span class='warning'>[src]'s tab isn't open!</span>")
|
||||
|
||||
@@ -53,3 +53,28 @@
|
||||
to_chat(user, "<span class='notice'>You mash [src] into a poultice.</span>")
|
||||
user.drop_item()
|
||||
qdel(src)
|
||||
|
||||
// mint
|
||||
/obj/item/seeds/mint
|
||||
name = "pack of mint seeds"
|
||||
desc = "These seeds grow into mint plants."
|
||||
icon_state = "seed-mint"
|
||||
species = "mint"
|
||||
plantname = "Mint Plant"
|
||||
product = /obj/item/reagent_containers/food/snacks/grown/mint
|
||||
lifespan = 20
|
||||
maturation = 4
|
||||
production = 5
|
||||
yield = 5
|
||||
growthstages = 3
|
||||
icon_dead = "mint-dead"
|
||||
reagents_add = list("mint" = 0.03, "plantmatter" = 0.03)
|
||||
|
||||
/obj/item/reagent_containers/food/snacks/grown/mint
|
||||
seed = /obj/item/seeds/mint
|
||||
name = "mint leaves"
|
||||
desc = "Process for mint. Distill for menthol. No need to experi-mint." //haha
|
||||
icon_state = "mint"
|
||||
tastes = list("mint" = 1)
|
||||
filling_color = "#A7EE9F"
|
||||
distill_reagent = "menthol"
|
||||
|
||||
@@ -224,7 +224,7 @@
|
||||
// Cell recharging trait. Charges all mob's power cells to (potency*rate)% mark when eaten.
|
||||
// Generates sparks on squash.
|
||||
// Small (potency*rate*5) chance to shock squish or slip target for (potency*rate*5) damage.
|
||||
// Multiplies max charge by (rate*1000) when used in potato power cells.
|
||||
// Multiplies max charge by (rate*100) when used in potato power cells.
|
||||
name = "Electrical Activity"
|
||||
rate = 0.2
|
||||
origin_tech = list("powerstorage" = 5)
|
||||
@@ -233,14 +233,14 @@
|
||||
/datum/plant_gene/trait/cell_charge/on_slip(obj/item/reagent_containers/food/snacks/grown/G, mob/living/carbon/C)
|
||||
var/power = G.seed.potency*rate
|
||||
if(prob(power))
|
||||
C.electrocute_act(round(power), G, 1, TRUE)
|
||||
C.electrocute_act(round(power), G, 1, SHOCK_NOGLOVES)
|
||||
|
||||
/datum/plant_gene/trait/cell_charge/on_squash(obj/item/reagent_containers/food/snacks/grown/G, atom/target)
|
||||
if(isliving(target))
|
||||
var/mob/living/carbon/C = target
|
||||
var/power = G.seed.potency*rate
|
||||
if(prob(power))
|
||||
C.electrocute_act(round(power), G, 1, TRUE)
|
||||
C.electrocute_act(round(power), G, 1, SHOCK_NOGLOVES)
|
||||
|
||||
/datum/plant_gene/trait/cell_charge/on_consume(obj/item/reagent_containers/food/snacks/grown/G, mob/living/carbon/target)
|
||||
if(!G.reagents.total_volume)
|
||||
@@ -375,8 +375,8 @@
|
||||
|
||||
// The secret of potato supercells!
|
||||
var/datum/plant_gene/trait/cell_charge/CG = G.seed.get_gene(/datum/plant_gene/trait/cell_charge)
|
||||
if(CG) // 10x charge for deafult cell charge gene - 20 000 with 100 potency.
|
||||
pocell.maxcharge *= CG.rate*1000
|
||||
if(CG) // 20x charge for deafult cell charge gene - 40 000 with 100 potency.
|
||||
pocell.maxcharge *= CG.rate*100
|
||||
pocell.charge = pocell.maxcharge
|
||||
pocell.name = "[G] battery"
|
||||
pocell.desc = "A rechargable plant based power cell. This one has a power rating of [pocell.maxcharge], and you should not swallow it."
|
||||
|
||||
@@ -8,7 +8,8 @@
|
||||
user.do_attack_animation(target, ATTACK_EFFECT_PUNCH)
|
||||
target.visible_message("<span class='warning'>[user] elbow drops [target]!</span>", \
|
||||
"<span class='userdanger'>[user] piledrives you with [user.p_their()] elbow!</span>")
|
||||
target.death() //FINISH HIM!
|
||||
if(target.health <= 0) //so it actually checks for crit now
|
||||
target.death() //FINISH HIM!
|
||||
target.apply_damage(50, BRUTE, "chest")
|
||||
playsound(get_turf(target), 'sound/weapons/punch1.ogg', 75, 1, -1)
|
||||
add_attack_logs(user, target, "Melee attacked with martial-art [src] : Elbow Drop", ATKLOG_ALL)
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
heat_protection = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS
|
||||
hoodtype = /obj/item/clothing/head/hooded/explorer
|
||||
armor = list("melee" = 30, "bullet" = 20, "laser" = 20, "energy" = 20, "bomb" = 50, "bio" = 100, "rad" = 50, "fire" = 50, "acid" = 50)
|
||||
allowed = list(/obj/item/flashlight, /obj/item/tank, /obj/item/resonator, /obj/item/mining_scanner, /obj/item/t_scanner/adv_mining_scanner, /obj/item/gun/energy/kinetic_accelerator, /obj/item/pickaxe)
|
||||
allowed = list(/obj/item/flashlight, /obj/item/tank/internals, /obj/item/resonator, /obj/item/mining_scanner, /obj/item/t_scanner/adv_mining_scanner, /obj/item/gun/energy/kinetic_accelerator, /obj/item/pickaxe)
|
||||
resistance_flags = FIRE_PROOF
|
||||
hide_tail_by_species = list("Vox" , "Vulpkanin" , "Unathi" , "Tajaran")
|
||||
|
||||
@@ -53,7 +53,7 @@
|
||||
resistance_flags = FIRE_PROOF | LAVA_PROOF
|
||||
slowdown = 0
|
||||
armor = list("melee" = 70, "bullet" = 40, "laser" = 10, "energy" = 10, "bomb" = 50, "bio" = 100, "rad" = 100, "fire" = 100, "acid" = 100)
|
||||
allowed = list(/obj/item/flashlight, /obj/item/tank, /obj/item/resonator, /obj/item/mining_scanner, /obj/item/t_scanner/adv_mining_scanner, /obj/item/gun/energy/kinetic_accelerator, /obj/item/pickaxe)
|
||||
allowed = list(/obj/item/flashlight, /obj/item/tank/internals, /obj/item/resonator, /obj/item/mining_scanner, /obj/item/t_scanner/adv_mining_scanner, /obj/item/gun/energy/kinetic_accelerator, /obj/item/pickaxe)
|
||||
|
||||
/obj/item/clothing/suit/space/hostile_environment/New()
|
||||
..()
|
||||
|
||||
@@ -70,23 +70,13 @@
|
||||
//Pod turfs and objects
|
||||
|
||||
//Window
|
||||
/obj/structure/window/shuttle/survival_pod
|
||||
/obj/structure/window/full/shuttle/survival_pod
|
||||
name = "pod window"
|
||||
icon = 'icons/obj/smooth_structures/pod_window.dmi'
|
||||
icon_state = "smooth"
|
||||
dir = FULLTILE_WINDOW_DIR
|
||||
max_integrity = 100
|
||||
fulltile = TRUE
|
||||
flags = PREVENT_CLICK_UNDER
|
||||
reinf = TRUE
|
||||
heat_resistance = 1600
|
||||
armor = list("melee" = 50, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 50, "bio" = 100, "rad" = 100, "fire" = 80, "acid" = 100)
|
||||
smooth = SMOOTH_MORE
|
||||
canSmoothWith = list(/turf/simulated/wall/mineral/titanium/survival, /obj/machinery/door/airlock/survival_pod, /obj/structure/window/shuttle/survival_pod)
|
||||
explosion_block = 3
|
||||
level = 3
|
||||
glass_type = /obj/item/stack/sheet/titaniumglass
|
||||
glass_amount = 2
|
||||
canSmoothWith = list(/turf/simulated/wall/mineral/titanium/survival, /obj/machinery/door/airlock/survival_pod, /obj/structure/window/full/shuttle/survival_pod)
|
||||
|
||||
/obj/structure/window/reinforced/survival_pod
|
||||
name = "pod window"
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
throw_range = 5
|
||||
origin_tech = "bluespace=2"
|
||||
slot_flags = SLOT_BELT
|
||||
var/emagged = FALSE
|
||||
|
||||
/obj/item/wormhole_jaunter/attack_self(mob/user)
|
||||
user.visible_message("<span class='notice'>[user.name] activates the [name]!</span>")
|
||||
@@ -73,7 +72,6 @@
|
||||
icon_state = "bhole3"
|
||||
desc = "A stable hole in the universe made by a wormhole jaunter. Turbulent doesn't even begin to describe how rough passage through one of these is, but at least it will always get you somewhere near a beacon."
|
||||
failchance = 0
|
||||
var/emagged = FALSE
|
||||
|
||||
/obj/effect/portal/jaunt_tunnel/can_teleport(atom/movable/M)
|
||||
if(!emagged && ismegafauna(M))
|
||||
|
||||
@@ -335,7 +335,7 @@
|
||||
if(ishuman(user))
|
||||
var/mobcheck = 0
|
||||
for(var/mob/living/simple_animal/A in range(1, src))
|
||||
if(A.melee_damage_upper > 5 || A.mob_size >= MOB_SIZE_LARGE || A.ckey || A.stat)
|
||||
if(A.melee_damage_upper > 5 || A.mob_size >= MOB_SIZE_LARGE || A.ckey || A.stat || isbot(A))
|
||||
break
|
||||
var/obj/structure/closet/stasis/S = new /obj/structure/closet/stasis(A)
|
||||
user.forceMove(S)
|
||||
|
||||
@@ -440,7 +440,7 @@
|
||||
if(!is_station_level(z))
|
||||
return
|
||||
|
||||
var/msg = "Now available in [get_area_name(src, TRUE) || "Unknown"]:"
|
||||
var/list/msg = list("Now available in [get_area_name(src, TRUE) || "Unknown"]:")
|
||||
var/mats_in_stock = list()
|
||||
var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
|
||||
for(var/MAT in materials.materials)
|
||||
@@ -448,7 +448,7 @@
|
||||
var/mineral_amount = M.amount / MINERAL_MATERIAL_AMOUNT
|
||||
if(mineral_amount)
|
||||
mats_in_stock += M.id
|
||||
msg += "[capitalize(M.name)]: [mineral_amount] sheets"
|
||||
msg.Add("[capitalize(M.name)]: [mineral_amount] sheets")
|
||||
|
||||
// No point sending a message if we're dry
|
||||
if(!length(mats_in_stock))
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
/datum/map_template/shelter/New()
|
||||
. = ..()
|
||||
blacklisted_turfs = typecacheof(list(/turf/simulated/wall, /turf/simulated/mineral, /turf/simulated/shuttle/wall))
|
||||
blacklisted_turfs = typecacheof(list(/turf/simulated/wall, /turf/simulated/mineral))
|
||||
whitelisted_turfs = list()
|
||||
banned_areas = typecacheof(/area/shuttle)
|
||||
|
||||
|
||||
@@ -217,7 +217,8 @@ Des: Removes all infected images from the alien.
|
||||
|
||||
/mob/living/carbon/alien/proc/updatePlasmaDisplay()
|
||||
if(hud_used) //clientless aliens
|
||||
hud_used.alien_plasma_display.maptext = "<div align='center' valign='middle' style='position:relative; top:0px; left:6px'> <font color='magenta'>[getPlasma()]</font></div>"
|
||||
hud_used.alien_plasma_display.maptext = "<div align='center' valign='middle' style='position:relative; top:0px; left:6px'> <font face='Small Fonts' color='magenta'>[getPlasma()]</font></div>"
|
||||
hud_used.alien_plasma_display.maptext_x = -3
|
||||
|
||||
/mob/living/carbon/alien/larva/updatePlasmaDisplay()
|
||||
return
|
||||
|
||||
@@ -1,21 +1,3 @@
|
||||
/mob/living/carbon/brain/handle_mutations_and_radiation()
|
||||
if(radiation)
|
||||
if(radiation > 100)
|
||||
if(!container)
|
||||
to_chat(src, "<span class='danger'>You feel weak.</span>")
|
||||
else
|
||||
to_chat(src, "<span class='danger'>STATUS: CRITICAL AMOUNTS OF RADIATION DETECTED.</span>")
|
||||
|
||||
switch(radiation)
|
||||
|
||||
if(50 to 75)
|
||||
if(prob(5))
|
||||
if(!container)
|
||||
to_chat(src, "<span class='danger'>You feel weak.</span>")
|
||||
else
|
||||
to_chat(src, "<span class='danger'>STATUS: DANGEROUS AMOUNTS OF RADIATION DETECTED.</span>")
|
||||
..()
|
||||
|
||||
/mob/living/carbon/brain/proc/handle_temperature_damage(body_part, exposed_temperature, exposed_intensity)
|
||||
if(status_flags & GODMODE)
|
||||
return
|
||||
|
||||
@@ -144,54 +144,44 @@
|
||||
M.forceMove(drop_location())
|
||||
visible_message("<span class='danger'>[M] bursts out of [src]!</span>")
|
||||
|
||||
/mob/living/carbon/electrocute_act(shock_damage, obj/source, siemens_coeff = 1, safety = FALSE, override = FALSE, tesla_shock = FALSE, illusion = FALSE, stun = TRUE)
|
||||
SEND_SIGNAL(src, COMSIG_LIVING_ELECTROCUTE_ACT, shock_damage)
|
||||
if(status_flags & GODMODE) //godmode
|
||||
return FALSE
|
||||
if(NO_SHOCK in mutations) //shockproof
|
||||
return FALSE
|
||||
if(tesla_shock && tesla_ignore)
|
||||
return FALSE
|
||||
shock_damage *= siemens_coeff
|
||||
if(dna && dna.species)
|
||||
shock_damage *= dna.species.siemens_coeff
|
||||
if(shock_damage < 1 && !override)
|
||||
return FALSE
|
||||
if(reagents.has_reagent("teslium"))
|
||||
shock_damage *= 1.5 //If the mob has teslium in their body, shocks are 50% more damaging!
|
||||
if(illusion)
|
||||
adjustStaminaLoss(shock_damage)
|
||||
else
|
||||
take_overall_damage(0, shock_damage, TRUE, used_weapon = "Electrocution")
|
||||
shock_internal_organs(shock_damage)
|
||||
visible_message(
|
||||
"<span class='danger'>[src] was shocked by \the [source]!</span>",
|
||||
"<span class='userdanger'>You feel a powerful shock coursing through your body!</span>",
|
||||
"<span class='italics'>You hear a heavy electrical crack.</span>")
|
||||
AdjustJitter(1000) //High numbers for violent convulsions
|
||||
///Adds to the parent by also adding functionality to propagate shocks through pulling and doing some fluff effects.
|
||||
/mob/living/carbon/electrocute_act(shock_damage, source, siemens_coeff = 1, flags = NONE)
|
||||
. = ..()
|
||||
if(!.)
|
||||
return
|
||||
//Propagation through pulling
|
||||
if(!(flags & SHOCK_ILLUSION))
|
||||
var/list/shocking_queue = list()
|
||||
if(iscarbon(pulling) && source != pulling)
|
||||
shocking_queue += pulling
|
||||
if(iscarbon(pulledby) && source != pulledby)
|
||||
shocking_queue += pulledby
|
||||
if(iscarbon(buckled) && source != buckled)
|
||||
shocking_queue += buckled
|
||||
for(var/mob/living/carbon/carried in buckled_mobs)
|
||||
if(source != carried)
|
||||
shocking_queue += carried
|
||||
//Found our victims, now lets shock them all
|
||||
for(var/victim in shocking_queue)
|
||||
var/mob/living/carbon/C = victim
|
||||
C.electrocute_act(shock_damage * 0.75, src, 1, flags)
|
||||
//Stun
|
||||
var/should_stun = (!(flags & SHOCK_TESLA) || siemens_coeff > 0.5) && !(flags & SHOCK_NOSTUN)
|
||||
if(should_stun)
|
||||
Stun(2)
|
||||
//Jitter and other fluff.
|
||||
AdjustJitter(1000)
|
||||
do_jitter_animation(jitteriness)
|
||||
AdjustStuttering(2)
|
||||
if((!tesla_shock || (tesla_shock && siemens_coeff > 0.5)) && stun)
|
||||
Stun(2)
|
||||
spawn(20)
|
||||
AdjustJitter(-1000, bound_lower = 10) //Still jittery, but vastly less
|
||||
if((!tesla_shock || (tesla_shock && siemens_coeff > 0.5)) && stun)
|
||||
Stun(3)
|
||||
Weaken(3)
|
||||
if(shock_damage > 200)
|
||||
src.visible_message(
|
||||
"<span class='danger'>[src] was arc flashed by the [source]!</span>",
|
||||
"<span class='userdanger'>The [source] arc flashes and electrocutes you!</span>",
|
||||
"<span class='italics'>You hear a lightning-like crack!</span>")
|
||||
playsound(loc, 'sound/effects/eleczap.ogg', 50, 1, -1)
|
||||
explosion(loc, -1, 0, 2, 2)
|
||||
|
||||
if(override)
|
||||
return override
|
||||
else
|
||||
return shock_damage
|
||||
|
||||
shock_internal_organs(shock_damage)
|
||||
addtimer(CALLBACK(src, .proc/secondary_shock, should_stun), 20)
|
||||
return shock_damage
|
||||
|
||||
///Called slightly after electrocute act to reduce jittering and apply a secondary stun.
|
||||
/mob/living/carbon/proc/secondary_shock(should_stun)
|
||||
AdjustJitter(-1000, bound_lower = 10) //Still jittery, but vastly less
|
||||
if(should_stun)
|
||||
Weaken(3)
|
||||
|
||||
/mob/living/carbon/swap_hand()
|
||||
var/obj/item/item_in_hand = src.get_active_hand()
|
||||
@@ -1225,14 +1215,14 @@ so that different stomachs can handle things in different ways VB*/
|
||||
I.extinguish() //extinguishes our clothes
|
||||
..()
|
||||
|
||||
/mob/living/carbon/clean_blood(clean_hands = TRUE, clean_mask = TRUE, clean_feet = TRUE)
|
||||
/mob/living/carbon/clean_blood(radiation_clean = FALSE, clean_hands = TRUE, clean_mask = TRUE, clean_feet = TRUE)
|
||||
if(head)
|
||||
if(head.clean_blood())
|
||||
if(head.clean_blood(radiation_clean))
|
||||
update_inv_head()
|
||||
if(head.flags_inv & HIDEMASK)
|
||||
clean_mask = FALSE
|
||||
if(wear_suit)
|
||||
if(wear_suit.clean_blood())
|
||||
if(wear_suit.clean_blood(radiation_clean))
|
||||
update_inv_wear_suit()
|
||||
if(wear_suit.flags_inv & HIDESHOES)
|
||||
clean_feet = FALSE
|
||||
|
||||
@@ -412,6 +412,8 @@
|
||||
|
||||
. = list(msg)
|
||||
|
||||
SEND_SIGNAL(src, COMSIG_PARENT_EXAMINE, user, .)
|
||||
|
||||
//Helper procedure. Called by /mob/living/carbon/human/examine() and /mob/living/carbon/human/Topic() to determine HUD access to security and medical records.
|
||||
/proc/hasHUD(mob/M, hudtype)
|
||||
if(istype(M, /mob/living/carbon/human))
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
voice_name = "unknown"
|
||||
icon = 'icons/mob/human.dmi'
|
||||
icon_state = "body_m_s"
|
||||
appearance_flags = KEEP_TOGETHER|TILE_BOUND|PIXEL_SCALE|LONG_GLIDE
|
||||
deathgasp_on_death = TRUE
|
||||
|
||||
/mob/living/carbon/human/New(loc)
|
||||
@@ -580,37 +581,35 @@
|
||||
SEND_SIGNAL(src, COMSIG_MOB_UPDATE_SIGHT)
|
||||
sync_lighting_plane_alpha()
|
||||
|
||||
//Added a safety check in case you want to shock a human mob directly through electrocute_act.
|
||||
/mob/living/carbon/human/electrocute_act(shock_damage, obj/source, siemens_coeff = 1, safety = FALSE, override = FALSE, tesla_shock = FALSE, illusion = FALSE, stun = TRUE)
|
||||
if(tesla_shock)
|
||||
var/total_coeff = 1
|
||||
if(gloves)
|
||||
var/obj/item/clothing/gloves/G = gloves
|
||||
if(G.siemens_coefficient <= 0)
|
||||
total_coeff -= 0.5
|
||||
///Calculates the siemens coeff based on clothing and species, can also restart hearts.
|
||||
/mob/living/carbon/human/electrocute_act(shock_damage, source, siemens_coeff = 1, flags = NONE)
|
||||
//Calculates the siemens coeff based on clothing. Completely ignores the arguments
|
||||
if(flags & SHOCK_TESLA) //I hate this entire block. This gets the siemens_coeff for tesla shocks
|
||||
if(gloves && gloves.siemens_coefficient <= 0)
|
||||
siemens_coeff -= 0.5
|
||||
if(wear_suit)
|
||||
var/obj/item/clothing/suit/S = wear_suit
|
||||
if(S.siemens_coefficient <= 0)
|
||||
total_coeff -= 0.95
|
||||
else if(S.siemens_coefficient == (-1))
|
||||
total_coeff -= 1
|
||||
siemens_coeff = total_coeff
|
||||
if(tesla_ignore)
|
||||
siemens_coeff = 0
|
||||
else if(!safety)
|
||||
var/gloves_siemens_coeff = 1
|
||||
if(wear_suit.siemens_coefficient == -1)
|
||||
siemens_coeff -= 1
|
||||
else if(wear_suit.siemens_coefficient <= 0)
|
||||
siemens_coeff -= 0.95
|
||||
siemens_coeff = max(siemens_coeff, 0)
|
||||
else if(!(flags & SHOCK_NOGLOVES)) //This gets the siemens_coeff for all non tesla shocks
|
||||
if(gloves)
|
||||
var/obj/item/clothing/gloves/G = gloves
|
||||
gloves_siemens_coeff = G.siemens_coefficient
|
||||
siemens_coeff = gloves_siemens_coeff
|
||||
if(undergoing_cardiac_arrest() && !illusion)
|
||||
siemens_coeff *= gloves.siemens_coefficient
|
||||
siemens_coeff *= dna.species.siemens_coeff
|
||||
. = ..()
|
||||
//Don't go further if the shock was blocked/too weak.
|
||||
if(!.)
|
||||
return
|
||||
//Note we both check that the user is in cardiac arrest and can actually heartattack
|
||||
//If they can't, they're missing their heart and this would runtime
|
||||
if(undergoing_cardiac_arrest() && !(flags & SHOCK_ILLUSION))
|
||||
if(shock_damage * siemens_coeff >= 1 && prob(25))
|
||||
set_heartattack(FALSE)
|
||||
if(stat == CONSCIOUS)
|
||||
to_chat(src, "<span class='notice'>You feel your heart beating again!</span>")
|
||||
|
||||
dna.species.spec_electrocute_act(src, shock_damage, source, siemens_coeff, safety, override, tesla_shock, illusion, stun)
|
||||
. = ..(shock_damage, source, siemens_coeff, safety, override, tesla_shock, illusion, stun)
|
||||
dna.species.spec_electrocute_act(src, shock_damage, source, siemens_coeff, flags = NONE)
|
||||
|
||||
/mob/living/carbon/human/Topic(href, href_list)
|
||||
if(!usr.stat && usr.canmove && !usr.restrained() && in_range(src, usr))
|
||||
@@ -1601,13 +1600,18 @@ Eyes need to have significantly high darksight to shine unless the mob has the X
|
||||
if(prob(current_size * 5) && hand.w_class >= ((11-current_size)/2) && unEquip(hand))
|
||||
step_towards(hand, src)
|
||||
to_chat(src, "<span class='warning'>\The [S] pulls \the [hand] from your grip!</span>")
|
||||
apply_effect(current_size * 3, IRRADIATE)
|
||||
rad_act(current_size * 3)
|
||||
|
||||
/mob/living/carbon/human/narsie_act()
|
||||
if(iswizard(src) && iscultist(src)) //Wizard cultists are immune to narsie because it would prematurely end the wiz round that's about to end by the automated shuttle call anyway
|
||||
return
|
||||
..()
|
||||
|
||||
/mob/living/carbon/human/rad_act(amount)
|
||||
if(RADIMMUNE in dna.species.species_traits)
|
||||
return SEND_SIGNAL(src, COMSIG_ATOM_RAD_ACT, amount)
|
||||
. = ..()
|
||||
|
||||
/mob/living/carbon/human/proc/do_cpr(mob/living/carbon/human/H)
|
||||
if(H == src)
|
||||
to_chat(src, "<span class='warning'>You cannot perform CPR on yourself!</span>")
|
||||
|
||||
@@ -193,64 +193,8 @@
|
||||
if(gene_stability < GENETIC_DAMAGE_STAGE_3)
|
||||
gib()
|
||||
|
||||
if(!(RADIMMUNE in dna.species.species_traits))
|
||||
if(radiation)
|
||||
radiation = clamp(radiation, 0, 200)
|
||||
|
||||
var/autopsy_damage = 0
|
||||
switch(radiation)
|
||||
if(1 to 49)
|
||||
radiation = max(radiation-1, 0)
|
||||
if(prob(25))
|
||||
adjustToxLoss(1)
|
||||
adjustFireLoss(1)
|
||||
autopsy_damage = 2
|
||||
|
||||
if(50 to 74)
|
||||
radiation = max(radiation-2, 0)
|
||||
adjustToxLoss(1)
|
||||
adjustFireLoss(1)
|
||||
autopsy_damage = 2
|
||||
if(prob(5))
|
||||
radiation = max(radiation-5, 0)
|
||||
Weaken(3)
|
||||
to_chat(src, "<span class='danger'>You feel weak.</span>")
|
||||
emote("collapse")
|
||||
|
||||
if(75 to 100)
|
||||
radiation = max(radiation-2, 0)
|
||||
adjustToxLoss(2)
|
||||
adjustFireLoss(2)
|
||||
autopsy_damage = 4
|
||||
if(prob(2))
|
||||
to_chat(src, "<span class='danger'>You mutate!</span>")
|
||||
randmutb(src)
|
||||
domutcheck(src, null)
|
||||
|
||||
if(101 to 150)
|
||||
radiation = max(radiation-3, 0)
|
||||
adjustToxLoss(2)
|
||||
adjustFireLoss(3)
|
||||
autopsy_damage = 5
|
||||
if(prob(4))
|
||||
to_chat(src, "<span class='danger'>You mutate!</span>")
|
||||
randmutb(src)
|
||||
domutcheck(src, null)
|
||||
|
||||
if(151 to INFINITY)
|
||||
radiation = max(radiation-3, 0)
|
||||
adjustToxLoss(2)
|
||||
adjustFireLoss(3)
|
||||
autopsy_damage = 5
|
||||
if(prob(6))
|
||||
to_chat(src, "<span class='danger'>You mutate!</span>")
|
||||
randmutb(src)
|
||||
domutcheck(src, null)
|
||||
|
||||
if(autopsy_damage)
|
||||
var/obj/item/organ/external/chest/chest = get_organ("chest")
|
||||
if(chest)
|
||||
chest.add_autopsy_data("Radiation Poisoning", autopsy_damage)
|
||||
if(!dna || !dna.species.handle_mutations_and_radiation(src))
|
||||
..()
|
||||
|
||||
/mob/living/carbon/human/breathe()
|
||||
if(!dna.species.breathe(src))
|
||||
@@ -919,7 +863,7 @@
|
||||
mind.changeling.regenerate(src)
|
||||
if(hud_used)
|
||||
hud_used.lingchemdisplay.invisibility = 0
|
||||
hud_used.lingchemdisplay.maptext = "<div align='center' valign='middle' style='position:relative; top:0px; left:6px'><font color='#dd66dd'>[round(mind.changeling.chem_charges)]</font></div>"
|
||||
hud_used.lingchemdisplay.maptext = "<div align='center' valign='middle' style='position:relative; top:0px; left:6px'><font face='Small Fonts' color='#dd66dd'>[round(mind.changeling.chem_charges)]</font></div>"
|
||||
else
|
||||
if(hud_used)
|
||||
hud_used.lingchemdisplay.invisibility = 101
|
||||
|
||||
@@ -370,7 +370,7 @@
|
||||
/datum/species/proc/spec_stun(mob/living/carbon/human/H,amount)
|
||||
return
|
||||
|
||||
/datum/species/proc/spec_electrocute_act(mob/living/carbon/human/H, shock_damage, obj/source, siemens_coeff = 1, safety = FALSE, override = FALSE, tesla_shock = FALSE, illusion = FALSE, stun = TRUE)
|
||||
/datum/species/proc/spec_electrocute_act(mob/living/carbon/human/H, shock_damage, source, siemens_coeff = 1, flags = NONE)
|
||||
return
|
||||
|
||||
/datum/species/proc/help(mob/living/carbon/human/user, mob/living/carbon/human/target, datum/martial_art/attacker_style)
|
||||
@@ -628,9 +628,9 @@
|
||||
return FALSE
|
||||
var/obj/item/organ/external/O = H.get_organ(BODY_ZONE_CHEST)
|
||||
|
||||
if(!H.w_uniform && !nojumpsuit && (!O || !(O.status & ORGAN_ROBOT)))
|
||||
if(!H.w_uniform && !nojumpsuit && !(O?.status & ORGAN_ROBOT))
|
||||
if(!disable_warning)
|
||||
to_chat(H, "<span class='alert'>You need a jumpsuit before you can attach this [name].</span>")
|
||||
to_chat(H, "<span class='alert'>You need a jumpsuit before you can attach this [I.name].</span>")
|
||||
return FALSE
|
||||
if(!(I.slot_flags & SLOT_BELT))
|
||||
return
|
||||
@@ -650,9 +650,9 @@
|
||||
return FALSE
|
||||
var/obj/item/organ/external/O = H.get_organ(BODY_ZONE_CHEST)
|
||||
|
||||
if(!H.w_uniform && !nojumpsuit && (!O || !(O.status & ORGAN_ROBOT)))
|
||||
if(!H.w_uniform && !nojumpsuit && !(O?.status & ORGAN_ROBOT))
|
||||
if(!disable_warning)
|
||||
to_chat(H, "<span class='alert'>You need a jumpsuit before you can attach this [name].</span>")
|
||||
to_chat(H, "<span class='alert'>You need a jumpsuit before you can attach this [I.name].</span>")
|
||||
return FALSE
|
||||
if(!(I.slot_flags & SLOT_ID))
|
||||
return FALSE
|
||||
@@ -662,9 +662,9 @@
|
||||
return FALSE
|
||||
var/obj/item/organ/external/O = H.get_organ(BODY_ZONE_CHEST)
|
||||
|
||||
if(!H.w_uniform && !nojumpsuit && (!O || !(O.status & ORGAN_ROBOT)))
|
||||
if(!H.w_uniform && !nojumpsuit && !(O?.status & ORGAN_ROBOT))
|
||||
if(!disable_warning)
|
||||
to_chat(H, "<span class='alert'>You need a jumpsuit before you can attach this [name].</span>")
|
||||
to_chat(H, "<span class='alert'>You need a jumpsuit before you can attach this [I.name].</span>")
|
||||
return FALSE
|
||||
if(!(I.slot_flags & SLOT_PDA))
|
||||
return FALSE
|
||||
@@ -676,9 +676,9 @@
|
||||
return FALSE
|
||||
var/obj/item/organ/external/O = H.get_organ(BODY_ZONE_L_LEG)
|
||||
|
||||
if(!H.w_uniform && !nojumpsuit && (!O || !(O.status & ORGAN_ROBOT)))
|
||||
if(!H.w_uniform && !nojumpsuit && !(O?.status & ORGAN_ROBOT))
|
||||
if(!disable_warning)
|
||||
to_chat(H, "<span class='alert'>You need a jumpsuit before you can attach this [name].</span>")
|
||||
to_chat(H, "<span class='alert'>You need a jumpsuit before you can attach this [I.name].</span>")
|
||||
return FALSE
|
||||
if(I.slot_flags & SLOT_DENYPOCKET)
|
||||
return
|
||||
@@ -691,9 +691,9 @@
|
||||
return FALSE
|
||||
var/obj/item/organ/external/O = H.get_organ(BODY_ZONE_R_LEG)
|
||||
|
||||
if(!H.w_uniform && !nojumpsuit && (!O || !(O.status & ORGAN_ROBOT)))
|
||||
if(!H.w_uniform && !nojumpsuit && !(O?.status & ORGAN_ROBOT))
|
||||
if(!disable_warning)
|
||||
to_chat(H, "<span class='alert'>You need a jumpsuit before you can attach this [name].</span>")
|
||||
to_chat(H, "<span class='alert'>You need a jumpsuit before you can attach this [I.name].</span>")
|
||||
return FALSE
|
||||
if(I.slot_flags & SLOT_DENYPOCKET)
|
||||
return FALSE
|
||||
@@ -707,7 +707,7 @@
|
||||
return FALSE
|
||||
if(!H.wear_suit)
|
||||
if(!disable_warning)
|
||||
to_chat(H, "<span class='alert'>You need a suit before you can attach this [name].</span>")
|
||||
to_chat(H, "<span class='alert'>You need a suit before you can attach this [I.name].</span>")
|
||||
return FALSE
|
||||
if(!H.wear_suit.allowed)
|
||||
if(!disable_warning)
|
||||
@@ -715,7 +715,7 @@
|
||||
return FALSE
|
||||
if(I.w_class > WEIGHT_CLASS_BULKY)
|
||||
if(!disable_warning)
|
||||
to_chat(H, "The [name] is too big to attach.")
|
||||
to_chat(H, "<span class='warning'>[I] is too big to attach.</span>")
|
||||
return FALSE
|
||||
if(istype(I, /obj/item/pda) || istype(I, /obj/item/pen) || is_type_in_list(I, H.wear_suit.allowed))
|
||||
return TRUE
|
||||
@@ -733,7 +733,7 @@
|
||||
if(slot_tie)
|
||||
if(!H.w_uniform)
|
||||
if(!disable_warning)
|
||||
to_chat(H, "<span class='warning'>You need a jumpsuit before you can attach this [name].</span>")
|
||||
to_chat(H, "<span class='warning'>You need a jumpsuit before you can attach this [I.name].</span>")
|
||||
return FALSE
|
||||
var/obj/item/clothing/under/uniform = H.w_uniform
|
||||
if(uniform.accessories.len && !uniform.can_attach_accessory(H))
|
||||
@@ -749,6 +749,49 @@
|
||||
/datum/species/proc/update_health_hud(mob/living/carbon/human/H)
|
||||
return FALSE
|
||||
|
||||
/datum/species/proc/handle_mutations_and_radiation(mob/living/carbon/human/H)
|
||||
if(RADIMMUNE in species_traits)
|
||||
H.radiation = 0
|
||||
return TRUE
|
||||
|
||||
. = FALSE
|
||||
var/radiation = H.radiation
|
||||
|
||||
if(radiation > RAD_MOB_KNOCKDOWN && prob(RAD_MOB_KNOCKDOWN_PROB))
|
||||
if(!H.IsWeakened())
|
||||
H.emote("collapse")
|
||||
H.Weaken(RAD_MOB_KNOCKDOWN_AMOUNT)
|
||||
to_chat(H, "<span class='danger'>You feel weak.</span>")
|
||||
|
||||
if(radiation > RAD_MOB_VOMIT && prob(RAD_MOB_VOMIT_PROB))
|
||||
H.vomit(10, TRUE)
|
||||
|
||||
if(radiation > RAD_MOB_MUTATE)
|
||||
if(prob(1))
|
||||
to_chat(H, "<span class='danger'>You mutate!</span>")
|
||||
randmutb(H)
|
||||
H.emote("gasp")
|
||||
domutcheck(H, null)
|
||||
|
||||
if(radiation > RAD_MOB_HAIRLOSS)
|
||||
var/obj/item/organ/external/head/head_organ = H.get_organ("head")
|
||||
if(!head_organ)
|
||||
return
|
||||
if(prob(15) && head_organ.h_style != "Bald")
|
||||
to_chat(H, "<span class='danger'>Your hair starts to fall out in clumps...</span>")
|
||||
addtimer(CALLBACK(src, .proc/go_bald, H), 5 SECONDS)
|
||||
|
||||
/datum/species/proc/go_bald(mob/living/carbon/human/H)
|
||||
if(QDELETED(H)) //may be called from a timer
|
||||
return
|
||||
var/obj/item/organ/external/head/head_organ = H.get_organ("head")
|
||||
if(!head_organ)
|
||||
return
|
||||
head_organ.f_style = "Shaved"
|
||||
head_organ.h_style = "Bald"
|
||||
H.update_hair()
|
||||
H.update_fhair()
|
||||
|
||||
/*
|
||||
Returns the path corresponding to the corresponding organ
|
||||
It'll return null if the organ doesn't correspond, so include null checks when using this!
|
||||
|
||||
@@ -389,13 +389,7 @@
|
||||
special_names = list("Oxide", "Rod", "Meltdown")
|
||||
|
||||
/datum/species/golem/uranium/handle_life(mob/living/carbon/human/H)
|
||||
for(var/mob/living/L in range(2, H))
|
||||
if(ishuman(L))
|
||||
var/mob/living/carbon/human/I = L
|
||||
if(!(RADIMMUNE in I.dna.species.species_traits))
|
||||
L.apply_effect(10, IRRADIATE)
|
||||
if(prob(25)) //reduce spam
|
||||
to_chat(L, "<span class='danger'>You are enveloped by a soft green glow emanating from [H].</span>")
|
||||
radiation_pulse(H, 20)
|
||||
..()
|
||||
|
||||
//Ventcrawler
|
||||
|
||||
@@ -134,6 +134,9 @@
|
||||
if("Blueshield")
|
||||
O = new /datum/outfit/plasmaman/blueshield
|
||||
|
||||
if("Assistant", "Tourist", "Civilian", "Businessman", "Trader")
|
||||
O = new /datum/outfit/plasmaman/assistant
|
||||
|
||||
H.equipOutfit(O, visualsOnly)
|
||||
H.internal = H.r_hand
|
||||
H.update_action_buttons_icon()
|
||||
|
||||
@@ -86,9 +86,9 @@
|
||||
var/tank_pref = H.client && H.client.prefs ? H.client.prefs.speciesprefs : null
|
||||
var/obj/item/tank/internal_tank
|
||||
if(tank_pref)//Diseasel, here you go
|
||||
internal_tank = new /obj/item/tank/nitrogen(H)
|
||||
internal_tank = new /obj/item/tank/internals/nitrogen(H)
|
||||
else
|
||||
internal_tank = new /obj/item/tank/emergency_oxygen/vox(H)
|
||||
internal_tank = new /obj/item/tank/internals/emergency_oxygen/double/vox(H)
|
||||
if(!H.equip_to_appropriate_slot(internal_tank))
|
||||
if(!H.put_in_any_hand_if_possible(internal_tank))
|
||||
H.unEquip(H.l_hand)
|
||||
|
||||
@@ -47,7 +47,7 @@
|
||||
else
|
||||
if(istype(loc, /obj/))
|
||||
var/obj/location_as_object = loc
|
||||
location_as_object.handle_internal_lifeform(src,0)
|
||||
location_as_object.handle_internal_lifeform(src, 0)
|
||||
|
||||
//Second link in a breath chain, calls check_breath()
|
||||
/mob/living/carbon/proc/breathe()
|
||||
@@ -81,7 +81,7 @@
|
||||
|
||||
if(isobj(loc)) //Breathe from loc as object
|
||||
var/obj/loc_as_obj = loc
|
||||
breath = loc_as_obj.handle_internal_lifeform(src, BREATH_MOLES)
|
||||
breath = loc_as_obj.handle_internal_lifeform(src, BREATH_VOLUME)
|
||||
|
||||
else if(isturf(loc)) //Breathe from loc as turf
|
||||
var/breath_moles = 0
|
||||
@@ -92,7 +92,7 @@
|
||||
else //Breathe from loc as obj again
|
||||
if(istype(loc, /obj/))
|
||||
var/obj/loc_as_obj = loc
|
||||
loc_as_obj.handle_internal_lifeform(src,0)
|
||||
loc_as_obj.handle_internal_lifeform(src, 0)
|
||||
|
||||
check_breath(breath)
|
||||
|
||||
@@ -226,29 +226,9 @@
|
||||
return
|
||||
|
||||
/mob/living/carbon/handle_mutations_and_radiation()
|
||||
if(radiation)
|
||||
|
||||
switch(radiation)
|
||||
if(0 to 50)
|
||||
radiation--
|
||||
if(prob(25))
|
||||
adjustToxLoss(1)
|
||||
updatehealth("handle mutations and radiation(0-50)")
|
||||
|
||||
if(50 to 75)
|
||||
radiation -= 2
|
||||
adjustToxLoss(1)
|
||||
if(prob(5))
|
||||
radiation -= 5
|
||||
updatehealth("handle mutations and radiation(50-75)")
|
||||
|
||||
if(75 to 100)
|
||||
radiation -= 3
|
||||
adjustToxLoss(3)
|
||||
updatehealth("handle mutations and radiation(75-100)")
|
||||
|
||||
radiation = clamp(radiation, 0, 100)
|
||||
|
||||
radiation -= min(radiation, RAD_LOSS_PER_TICK)
|
||||
if(radiation > RAD_MOB_SAFE)
|
||||
adjustToxLoss(log(radiation - RAD_MOB_SAFE) * RAD_TOX_COEFFICIENT)
|
||||
|
||||
/mob/living/carbon/handle_chemicals_in_body()
|
||||
reagents.metabolize(src)
|
||||
|
||||
@@ -72,10 +72,10 @@
|
||||
|
||||
|
||||
|
||||
/mob/living/proc/apply_effect(var/effect = 0,var/effecttype = STUN, var/blocked = 0, var/negate_armor = 0)
|
||||
blocked = (100-blocked)/100
|
||||
/mob/living/proc/apply_effect(effect = 0, effecttype = STUN, blocked = 0)
|
||||
blocked = (100 - blocked) / 100
|
||||
if(!effect || (blocked <= 0))
|
||||
return 0
|
||||
return FALSE
|
||||
switch(effecttype)
|
||||
if(STUN)
|
||||
Stun(effect * blocked)
|
||||
@@ -84,10 +84,7 @@
|
||||
if(PARALYZE)
|
||||
Paralyse(effect * blocked)
|
||||
if(IRRADIATE)
|
||||
var/rad_damage = effect
|
||||
if(!negate_armor) // Setting negate_armor overrides radiation armor checks, which are automatic otherwise
|
||||
rad_damage = max(effect * ((100-run_armor_check(null, "rad", "Your clothes feel warm.", "Your clothes feel warm."))/100),0)
|
||||
radiation += rad_damage
|
||||
radiation += max(effect * blocked, 0)
|
||||
if(SLUR)
|
||||
Slur(effect * blocked)
|
||||
if(STUTTER)
|
||||
@@ -100,21 +97,32 @@
|
||||
if(status_flags & CANSTUN)
|
||||
Jitter(effect * blocked)
|
||||
updatehealth("apply effect")
|
||||
return 1
|
||||
return TRUE
|
||||
|
||||
/mob/living/proc/apply_effects(var/stun = 0, var/weaken = 0, var/paralyze = 0, var/irradiate = 0, var/slur = 0, var/stutter = 0, var/eyeblur = 0, var/drowsy = 0, var/blocked = 0, var/stamina = 0, var/jitter = 0)
|
||||
if(blocked >= 100) return 0
|
||||
if(stun) apply_effect(stun, STUN, blocked)
|
||||
if(weaken) apply_effect(weaken, WEAKEN, blocked)
|
||||
if(paralyze) apply_effect(paralyze, PARALYZE, blocked)
|
||||
if(irradiate) apply_effect(irradiate, IRRADIATE, blocked)
|
||||
if(slur) apply_effect(slur, SLUR, blocked)
|
||||
if(stutter) apply_effect(stutter, STUTTER, blocked)
|
||||
if(eyeblur) apply_effect(eyeblur, EYE_BLUR, blocked)
|
||||
if(drowsy) apply_effect(drowsy, DROWSY, blocked)
|
||||
if(stamina) apply_damage(stamina, STAMINA, null, blocked)
|
||||
if(jitter) apply_effect(jitter, JITTER, blocked)
|
||||
return 1
|
||||
/mob/living/proc/apply_effects(stun = 0, weaken = 0, paralyze = 0, irradiate = 0, slur = 0, stutter = 0, eyeblur = 0, drowsy = 0, blocked = 0, stamina = 0, jitter = 0)
|
||||
if(blocked >= 100)
|
||||
return FALSE
|
||||
if(stun)
|
||||
apply_effect(stun, STUN, blocked)
|
||||
if(weaken)
|
||||
apply_effect(weaken, WEAKEN, blocked)
|
||||
if(paralyze)
|
||||
apply_effect(paralyze, PARALYZE, blocked)
|
||||
if(irradiate)
|
||||
apply_effect(irradiate, IRRADIATE, blocked)
|
||||
if(slur)
|
||||
apply_effect(slur, SLUR, blocked)
|
||||
if(stutter)
|
||||
apply_effect(stutter, STUTTER, blocked)
|
||||
if(eyeblur)
|
||||
apply_effect(eyeblur, EYE_BLUR, blocked)
|
||||
if(drowsy)
|
||||
apply_effect(drowsy, DROWSY, blocked)
|
||||
if(stamina)
|
||||
apply_damage(stamina, STAMINA, null, blocked)
|
||||
if(jitter)
|
||||
apply_effect(jitter, JITTER, blocked)
|
||||
return TRUE
|
||||
|
||||
|
||||
/mob/living/proc/getBruteLoss()
|
||||
|
||||
@@ -1033,6 +1033,21 @@
|
||||
return 1
|
||||
return 0
|
||||
|
||||
/mob/living/rad_act(amount)
|
||||
. = ..()
|
||||
|
||||
if(!amount || (amount < RAD_MOB_SKIN_PROTECTION))
|
||||
return
|
||||
|
||||
amount -= RAD_BACKGROUND_RADIATION // This will always be at least 1 because of how skin protection is calculated
|
||||
|
||||
var/blocked = getarmor(null, "rad")
|
||||
|
||||
if(amount > RAD_BURN_THRESHOLD)
|
||||
apply_damage(RAD_BURN_CURVE(amount), BURN, null, blocked)
|
||||
|
||||
apply_effect((amount * RAD_MOB_COEFFICIENT) / max(1, (radiation ** 2) * RAD_OVERDOSE_REDUCTION), IRRADIATE, blocked)
|
||||
|
||||
/mob/living/proc/fakefireextinguish()
|
||||
return
|
||||
|
||||
|
||||
@@ -55,22 +55,35 @@
|
||||
/mob/living/proc/check_projectile_dismemberment(obj/item/projectile/P, def_zone)
|
||||
return 0
|
||||
|
||||
/mob/living/proc/electrocute_act(shock_damage, obj/source, siemens_coeff = 1, safety = FALSE, override = FALSE, tesla_shock = FALSE, illusion = FALSE, stun = TRUE)
|
||||
SEND_SIGNAL(src, COMSIG_LIVING_ELECTROCUTE_ACT, shock_damage)
|
||||
///As the name suggests, this should be called to apply electric shocks.
|
||||
/mob/living/proc/electrocute_act(shock_damage, source, siemens_coeff = 1, flags = NONE)
|
||||
SEND_SIGNAL(src, COMSIG_LIVING_ELECTROCUTE_ACT, shock_damage, source, siemens_coeff, flags)
|
||||
if(status_flags & GODMODE) //godmode
|
||||
return FALSE
|
||||
if((flags & SHOCK_TESLA) && HAS_TRAIT(src, TRAIT_TESLA_SHOCKIMMUNE))
|
||||
return FALSE
|
||||
if(NO_SHOCK in mutations) //shockproof
|
||||
return FALSE
|
||||
if(tesla_shock && tesla_ignore)
|
||||
shock_damage *= siemens_coeff
|
||||
if(shock_damage < 1)
|
||||
return FALSE
|
||||
if(shock_damage > 0)
|
||||
if(!illusion)
|
||||
adjustFireLoss(shock_damage)
|
||||
visible_message(
|
||||
"<span class='danger'>[src] was shocked by \the [source]!</span>",
|
||||
"<span class='userdanger'>You feel a powerful shock coursing through your body!</span>",
|
||||
"<span class='italics'>You hear a heavy electrical crack.</span>")
|
||||
return shock_damage
|
||||
if(!(flags & SHOCK_ILLUSION))
|
||||
take_overall_damage(0, shock_damage, TRUE, used_weapon = "Electrocution")
|
||||
if(shock_damage > 200)
|
||||
visible_message(
|
||||
"<span class='danger'>[src] was arc flashed by the [source]!</span>",
|
||||
"<span class='userdanger'>The [source] arc flashes and electrocutes you!</span>",
|
||||
"<span class='italics'>You hear a lightning-like crack!</span>")
|
||||
playsound(loc, 'sound/effects/eleczap.ogg', 50, 1, -1)
|
||||
explosion(loc, -1, 0, 2, 2)
|
||||
else
|
||||
adjustStaminaLoss(shock_damage)
|
||||
visible_message(
|
||||
"<span class='danger'>[src] was shocked by \the [source]!</span>", \
|
||||
"<span class='userdanger'>You feel a powerful shock coursing through your body!</span>", \
|
||||
"<span class='hear'>You hear a heavy electrical crack.</span>" \
|
||||
)
|
||||
return shock_damage
|
||||
|
||||
/mob/living/emp_act(severity)
|
||||
..()
|
||||
|
||||
@@ -57,9 +57,6 @@
|
||||
var/gene_stability = DEFAULT_GENE_STABILITY
|
||||
var/ignore_gene_stability = 0
|
||||
|
||||
|
||||
var/tesla_ignore = FALSE
|
||||
|
||||
var/list/say_log = list() //a log of what we've said, plain text, no spans or junk, essentially just each individual "message"
|
||||
var/list/emote_log = list() //like say_log but for emotes
|
||||
|
||||
|
||||
@@ -108,7 +108,7 @@ GLOBAL_LIST_EMPTY(channel_to_radio_key)
|
||||
return returns
|
||||
|
||||
|
||||
/mob/living/say(var/message, var/verb = "says", var/sanitize = TRUE, var/ignore_speech_problems = FALSE, var/ignore_atmospherics = FALSE)
|
||||
/mob/living/say(message, verb = "says", sanitize = TRUE, ignore_speech_problems = FALSE, ignore_atmospherics = FALSE, ignore_languages = FALSE)
|
||||
if(client)
|
||||
if(client.prefs.muted & MUTE_IC)
|
||||
to_chat(src, "<span class='danger'>You cannot speak in IC (Muted).</span>")
|
||||
@@ -137,7 +137,12 @@ GLOBAL_LIST_EMPTY(channel_to_radio_key)
|
||||
message = trim_left(message)
|
||||
|
||||
//parse the language code and consume it
|
||||
var/list/message_pieces = parse_languages(message)
|
||||
var/list/message_pieces = list()
|
||||
if(ignore_languages)
|
||||
message_pieces = message_to_multilingual(message)
|
||||
else
|
||||
message_pieces = parse_languages(message)
|
||||
|
||||
if(istype(message_pieces, /datum/multilingual_say_piece)) // Little quirk to just easily deal with HIVEMIND languages
|
||||
var/datum/multilingual_say_piece/S = message_pieces // Yay BYOND's hilarious typecasting
|
||||
S.speaking.broadcast(src, S.message)
|
||||
|
||||
@@ -1142,6 +1142,9 @@ GLOBAL_LIST_INIT(ai_verbs_default, list(
|
||||
set category = "AI Commands"
|
||||
|
||||
var/newmsg = clean_input("What would you like the arrival message to be? List of options: $name, $rank, $species, $gender, $age", "Change Arrival Message", arrivalmsg)
|
||||
if(!newmsg)
|
||||
return
|
||||
newmsg = html_decode(newmsg) // This feels a bit redundant, but sanitisation is (probably) important.
|
||||
if(newmsg != arrivalmsg)
|
||||
arrivalmsg = newmsg
|
||||
to_chat(usr, "The arrival message has been successfully changed.")
|
||||
|
||||
@@ -317,16 +317,17 @@
|
||||
to_chat(usr, "<span class='warning'>You are already hacking that door!</span>")
|
||||
else
|
||||
hacking = TRUE
|
||||
INVOKE_ASYNC(src, /datum/pai_software/door_jack/.proc/hackloop)
|
||||
INVOKE_ASYNC(src, .proc/hackloop)
|
||||
if("cancel")
|
||||
hackdoor = null
|
||||
if("cable")
|
||||
if(cable)
|
||||
to_chat(usr, "<span class='warning'>You already have a cable deployed!</span>")
|
||||
return
|
||||
var/turf/T = get_turf(pai_holder)
|
||||
cable = new /obj/item/pai_cable(T)
|
||||
pai_holder.visible_message("<span class='warning'>A port on [pai_holder] opens to reveal [cable], which promptly falls to the floor.</span>")
|
||||
playsound(pai_holder, 'sound/mecha/mechmove03.ogg', 25, TRUE)
|
||||
if(cable) // Retracting
|
||||
pai_holder.visible_message("<span class='warning'>[cable] is pulled back into [pai_holder] with a quick snap.</span>")
|
||||
QDEL_NULL(cable)
|
||||
else // Extending
|
||||
cable = new /obj/item/pai_cable(get_turf(pai_holder))
|
||||
pai_holder.visible_message("<span class='warning'>A port on [pai_holder] opens to reveal [cable], which promptly falls to the floor.</span>")
|
||||
|
||||
/**
|
||||
* Door jack hack loop
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#define EMAG_TIMER 3000
|
||||
#define EMAG_TIMER 5 MINUTES
|
||||
/mob/living/silicon/robot/drone
|
||||
name = "drone"
|
||||
real_name = "drone"
|
||||
@@ -7,21 +7,19 @@
|
||||
maxHealth = 35
|
||||
health = 35
|
||||
bubble_icon = "machine"
|
||||
universal_speak = 0
|
||||
universal_understand = 1
|
||||
gender = NEUTER
|
||||
pass_flags = PASSTABLE
|
||||
braintype = "Robot"
|
||||
lawupdate = 0
|
||||
density = 0
|
||||
lawupdate = FALSE
|
||||
density = FALSE
|
||||
has_camera = FALSE
|
||||
req_one_access = list(ACCESS_ENGINE, ACCESS_ROBOTICS)
|
||||
ventcrawler = 2
|
||||
magpulse = 1
|
||||
ventcrawler = VENTCRAWLER_ALWAYS
|
||||
magpulse = TRUE
|
||||
mob_size = MOB_SIZE_SMALL
|
||||
pull_force = MOVE_FORCE_VERY_WEAK // Can only drag small items
|
||||
|
||||
modules_break = FALSE
|
||||
/// Cooldown for law syncs
|
||||
var/sync_cooldown = 0
|
||||
|
||||
// We need to keep track of a few module items so we don't need to do list operations
|
||||
// every time we need them. These get set in New() after the module is chosen.
|
||||
@@ -37,7 +35,7 @@
|
||||
|
||||
//Used for self-mailing.
|
||||
var/mail_destination = 0
|
||||
var/reboot_cooldown = 60 // one minute
|
||||
var/reboot_cooldown = 1 MINUTES
|
||||
var/last_reboot
|
||||
var/list/pullable_drone_items = list(
|
||||
/obj/item/pipe,
|
||||
@@ -57,8 +55,8 @@
|
||||
|
||||
remove_language("Robot Talk")
|
||||
remove_language("Galactic Common")
|
||||
add_language("Drone Talk", 1)
|
||||
add_language("Drone", 1)
|
||||
add_language("Drone Talk", TRUE)
|
||||
add_language("Drone", TRUE)
|
||||
|
||||
// Disable the microphone wire on Drones
|
||||
if(radio)
|
||||
@@ -86,13 +84,13 @@
|
||||
radio.recalculateChannels()
|
||||
|
||||
//Grab stacks.
|
||||
stack_metal = locate(/obj/item/stack/sheet/metal/cyborg) in src.module
|
||||
stack_wood = locate(/obj/item/stack/sheet/wood) in src.module
|
||||
stack_glass = locate(/obj/item/stack/sheet/glass/cyborg) in src.module
|
||||
stack_plastic = locate(/obj/item/stack/sheet/plastic) in src.module
|
||||
stack_metal = locate(/obj/item/stack/sheet/metal/cyborg) in module
|
||||
stack_wood = locate(/obj/item/stack/sheet/wood) in module
|
||||
stack_glass = locate(/obj/item/stack/sheet/glass/cyborg) in module
|
||||
stack_plastic = locate(/obj/item/stack/sheet/plastic) in module
|
||||
|
||||
//Grab decompiler.
|
||||
decompiler = locate(/obj/item/matter_decompiler) in src.module
|
||||
decompiler = locate(/obj/item/matter_decompiler) in module
|
||||
|
||||
//Some tidying-up.
|
||||
flavor_text = "It's a tiny little repair drone. The casing is stamped with an NT logo and the subscript: 'Nanotrasen Recursive Repair Systems: Fixing Tomorrow's Problem, Today!'"
|
||||
@@ -103,10 +101,10 @@
|
||||
laws = new /datum/ai_laws/drone()
|
||||
connected_ai = null
|
||||
|
||||
aiCamera = new/obj/item/camera/siliconcam/drone_camera(src)
|
||||
aiCamera = new /obj/item/camera/siliconcam/drone_camera(src)
|
||||
additional_law_channels["Drone"] = ";"
|
||||
|
||||
playsound(src.loc, 'sound/machines/twobeep.ogg', 50, 0)
|
||||
playsound(loc, 'sound/machines/twobeep.ogg', 50)
|
||||
|
||||
//Redefining some robot procs...
|
||||
/mob/living/silicon/robot/drone/rename_character(oldname, newname)
|
||||
@@ -114,7 +112,7 @@
|
||||
return ..(newname, newname)
|
||||
|
||||
/mob/living/silicon/robot/drone/get_default_name()
|
||||
return "maintenance drone ([rand(100,999)])"
|
||||
return "maintenance drone ([rand(100, 999)])"
|
||||
|
||||
/mob/living/silicon/robot/drone/update_icons()
|
||||
overlays.Cut()
|
||||
@@ -126,7 +124,6 @@
|
||||
/mob/living/silicon/robot/drone/choose_icon()
|
||||
return
|
||||
|
||||
|
||||
/mob/living/silicon/robot/drone/pick_module()
|
||||
return
|
||||
|
||||
@@ -136,25 +133,23 @@
|
||||
return FALSE
|
||||
|
||||
//Drones cannot be upgraded with borg modules so we need to catch some items before they get used in ..().
|
||||
/mob/living/silicon/robot/drone/attackby(obj/item/W as obj, mob/user as mob, params)
|
||||
|
||||
if(istype(W, /obj/item/borg/upgrade/))
|
||||
to_chat(user, "<span class='warning'>The maintenance drone chassis not compatible with \the [W].</span>")
|
||||
/mob/living/silicon/robot/drone/attackby(obj/item/I, mob/user, params)
|
||||
if(istype(I, /obj/item/borg/upgrade))
|
||||
to_chat(user, "<span class='warning'>The maintenance drone chassis is not compatible with [I].</span>")
|
||||
return
|
||||
|
||||
else if(istype(W, /obj/item/crowbar))
|
||||
to_chat(user, "The machine is hermetically sealed. You can't open the case.")
|
||||
else if(istype(I, /obj/item/crowbar))
|
||||
to_chat(user, "<span class='warning'>The machine is hermetically sealed. You can't open the case.</span>")
|
||||
return
|
||||
|
||||
else if(istype(W, /obj/item/card/id)||istype(W, /obj/item/pda))
|
||||
|
||||
else if(istype(I, /obj/item/card/id) || istype(I, /obj/item/pda))
|
||||
if(stat == DEAD)
|
||||
|
||||
if(!config.allow_drone_spawn || emagged || health < -35) //It's dead, Dave.
|
||||
// Currently not functional, so commenting out until it's fixed to avoid confusion
|
||||
/*if(!config.allow_drone_spawn || emagged || health < -35) //It's dead, Dave.
|
||||
to_chat(user, "<span class='warning'>The interface is fried, and a distressing burned smell wafts from the robot's interior. You're not rebooting this one.</span>")
|
||||
return
|
||||
|
||||
if(!allowed(W))
|
||||
if(!allowed(I))
|
||||
to_chat(user, "<span class='warning'>Access denied.</span>")
|
||||
return
|
||||
|
||||
@@ -164,25 +159,26 @@
|
||||
to_chat(usr, "<span class='warning'>The reboot system is currently offline. Please wait another [cooldown_time] seconds.</span>")
|
||||
return
|
||||
|
||||
user.visible_message("<span class='warning'>\the [user] swipes [user.p_their()] ID card through [src], attempting to reboot it.</span>", "<span class='warning'>You swipe your ID card through [src], attempting to reboot it.</span>")
|
||||
user.visible_message("<span class='warning'>[user] swipes [user.p_their()] ID card through [src], attempting to reboot it.</span>",
|
||||
"<span class='warning'>You swipe your ID card through [src], attempting to reboot it.</span>")
|
||||
last_reboot = world.time / 10
|
||||
var/drones = 0
|
||||
for(var/mob/living/silicon/robot/drone/D in GLOB.silicon_mob_list)
|
||||
if(D.key && D.client)
|
||||
drones++
|
||||
if(drones < config.max_maint_drones)
|
||||
request_player()
|
||||
request_player()*/
|
||||
return
|
||||
|
||||
else
|
||||
var/confirm = alert("Using your ID on a Maintenance Drone will shut it down, are you sure you want to do this?", "Disable Drone", "Yes", "No")
|
||||
if(confirm == ("Yes") && (user in range(3, src)))
|
||||
user.visible_message("<span class='warning'>\the [user] swipes [user.p_their()] ID card through [src], attempting to shut it down.</span>", "<span class='warning'>You swipe your ID card through \the [src], attempting to shut it down.</span>")
|
||||
user.visible_message("<span class='warning'>[user] swipes [user.p_their()] ID card through [src], attempting to shut it down.</span>",
|
||||
"<span class='warning'>You swipe your ID card through [src], attempting to shut it down.</span>")
|
||||
|
||||
if(emagged)
|
||||
return
|
||||
|
||||
if(allowed(W))
|
||||
if(allowed(I))
|
||||
shut_down()
|
||||
else
|
||||
to_chat(user, "<span class='warning'>Access denied.</span>")
|
||||
@@ -191,7 +187,7 @@
|
||||
|
||||
..()
|
||||
|
||||
/mob/living/silicon/robot/drone/emag_act(user as mob)
|
||||
/mob/living/silicon/robot/drone/emag_act(mob/user)
|
||||
if(!client || stat == DEAD)
|
||||
to_chat(user, "<span class='warning'>There's not much point subverting this heap of junk.</span>")
|
||||
return
|
||||
@@ -210,7 +206,7 @@
|
||||
if(jobban_isbanned(src, ROLE_SYNDICATE))
|
||||
SSticker.mode.replace_jobbanned_player(src, ROLE_SYNDICATE)
|
||||
|
||||
to_chat(src, "<span class='warning'>You feel a sudden burst of malware loaded into your execute-as-root buffer. Your tiny brain methodically parses, loads and executes the script. You sense you have five minutes before the drone server detects this and automatically shuts you down.</span>")
|
||||
to_chat(src, "<span class='warning'>You feel a sudden burst of malware loaded into your execute-as-root buffer. Your tiny brain methodically parses, loads and executes the script. You sense you have <b>five minutes</b> before the drone server detects this and automatically shuts you down.</span>")
|
||||
|
||||
message_admins("[key_name_admin(user)] emagged drone [key_name_admin(src)]. Laws overridden.")
|
||||
log_game("[key_name(user)] emagged drone [key_name(src)]. Laws overridden.")
|
||||
@@ -218,13 +214,12 @@
|
||||
GLOB.lawchanges.Add("[time] <B>:</B> [H.name]([H.key]) emagged [name]([key])")
|
||||
addtimer(CALLBACK(src, .proc/shut_down, TRUE), EMAG_TIMER)
|
||||
|
||||
emagged = 1
|
||||
density = 1
|
||||
emagged = TRUE
|
||||
density = TRUE
|
||||
pass_flags = 0
|
||||
icon_state = "repairbot-emagged"
|
||||
holder_type = /obj/item/holder/drone/emagged
|
||||
update_icons()
|
||||
lawupdate = 0
|
||||
connected_ai = null
|
||||
clear_supplied_laws()
|
||||
clear_inherent_laws()
|
||||
@@ -234,7 +229,6 @@
|
||||
to_chat(src, "<b>Obey these laws:</b>")
|
||||
laws.show_laws(src)
|
||||
to_chat(src, "<span class='boldwarning'>ALERT: [H.real_name] is your new master. Obey your new laws and [H.real_name]'s commands.</span>")
|
||||
return
|
||||
|
||||
//DRONE LIFE/DEATH
|
||||
|
||||
@@ -262,7 +256,7 @@
|
||||
full_law_reset()
|
||||
show_laws()
|
||||
|
||||
/mob/living/silicon/robot/drone/proc/shut_down(force=FALSE)
|
||||
/mob/living/silicon/robot/drone/proc/shut_down(force = FALSE)
|
||||
if(stat == DEAD)
|
||||
return
|
||||
|
||||
@@ -285,32 +279,32 @@
|
||||
for(var/mob/dead/observer/O in GLOB.player_list)
|
||||
if(cannotPossess(O))
|
||||
continue
|
||||
if(jobban_isbanned(O,"nonhumandept") || jobban_isbanned(O,"Drone"))
|
||||
if(jobban_isbanned(O, "nonhumandept") || jobban_isbanned(O, "Drone"))
|
||||
continue
|
||||
if(O.client)
|
||||
if(ROLE_PAI in O.client.prefs.be_special)
|
||||
question(O.client,O)
|
||||
question(O.client, O)
|
||||
|
||||
/mob/living/silicon/robot/drone/proc/question(var/client/C,var/mob/M)
|
||||
/mob/living/silicon/robot/drone/proc/question(client/C, mob/M)
|
||||
spawn(0)
|
||||
if(!C || !M || jobban_isbanned(M,"nonhumandept") || jobban_isbanned(M,"Drone")) return
|
||||
if(!C || !M || jobban_isbanned(M, "nonhumandept") || jobban_isbanned(M, "Drone"))
|
||||
return
|
||||
var/response = alert(C, "Someone is attempting to reboot a maintenance drone. Would you like to play as one?", "Maintenance drone reboot", "Yes", "No")
|
||||
if(!C || ckey)
|
||||
return
|
||||
if(response == "Yes")
|
||||
transfer_personality(C)
|
||||
|
||||
/mob/living/silicon/robot/drone/proc/transfer_personality(var/client/player)
|
||||
/mob/living/silicon/robot/drone/proc/transfer_personality(client/player)
|
||||
if(!player)
|
||||
return
|
||||
|
||||
if(!player) return
|
||||
|
||||
if(player.mob && player.mob.mind)
|
||||
if(player.mob?.mind)
|
||||
player.mob.mind.transfer_to(src)
|
||||
player.mob.mind.assigned_role = "Drone"
|
||||
else
|
||||
ckey = player.ckey
|
||||
|
||||
lawupdate = 0
|
||||
to_chat(src, "<b>Systems rebooted</b>. Loading base pattern maintenance protocol... <b>loaded</b>.")
|
||||
full_law_reset()
|
||||
to_chat(src, "<br><b>You are a maintenance drone, a tiny-brained robotic repair machine</b>.")
|
||||
@@ -358,21 +352,21 @@
|
||||
to_chat(src, "<span class='warning'>You are too small to pull that.</span>")
|
||||
|
||||
/mob/living/silicon/robot/drone/add_robot_verbs()
|
||||
src.verbs |= silicon_subsystems
|
||||
verbs |= silicon_subsystems
|
||||
|
||||
/mob/living/silicon/robot/drone/remove_robot_verbs()
|
||||
src.verbs -= silicon_subsystems
|
||||
verbs -= silicon_subsystems
|
||||
|
||||
/mob/living/silicon/robot/drone/update_canmove(delay_action_updates = 0)
|
||||
/mob/living/silicon/robot/drone/update_canmove(delay_action_updates = FALSE)
|
||||
. = ..()
|
||||
density = emagged //this is reset every canmove update otherwise
|
||||
|
||||
/mob/living/simple_animal/drone/flash_eyes(intensity = 1, override_blindness_check = 0, affect_silicon = 0, visual = 0)
|
||||
/mob/living/silicon/robot/drone/flash_eyes(intensity = 1, override_blindness_check = FALSE, affect_silicon = FALSE, visual = FALSE)
|
||||
if(affect_silicon)
|
||||
return ..()
|
||||
|
||||
/mob/living/silicon/robot/drone/decompile_act(obj/item/matter_decompiler/C, mob/user)
|
||||
if(!client && istype(user, /mob/living/silicon/robot/drone))
|
||||
if(!client && isdrone(user))
|
||||
to_chat(user, "<span class='warning'>You begin decompiling the other drone.</span>")
|
||||
if(!do_after(user, 5 SECONDS, target = loc))
|
||||
to_chat(user, "<span class='warning'>You need to remain still while decompiling such a large object.</span>")
|
||||
@@ -380,7 +374,7 @@
|
||||
if(QDELETED(src) || QDELETED(user))
|
||||
return ..()
|
||||
to_chat(user, "<span class='warning'>You carefully and thoroughly decompile your downed fellow, storing as much of its resources as you can within yourself.</span>")
|
||||
new/obj/effect/decal/cleanable/blood/oil(get_turf(src))
|
||||
new /obj/effect/decal/cleanable/blood/oil(get_turf(src))
|
||||
C.stored_comms["metal"] += 15
|
||||
C.stored_comms["glass"] += 15
|
||||
C.stored_comms["wood"] += 5
|
||||
|
||||
@@ -6,16 +6,18 @@
|
||||
req_access = list(ACCESS_ENGINE_EQUIP)
|
||||
circuit = /obj/item/circuitboard/drone_control
|
||||
|
||||
//Used when pinging drones.
|
||||
var/drone_call_area = "Engineering"
|
||||
//Used to enable or disable drone fabrication.
|
||||
/// The linked fabricator
|
||||
var/obj/machinery/drone_fabricator/dronefab
|
||||
/// Used when pinging drones
|
||||
var/drone_call_area = "Engineering"
|
||||
/// Cooldown for area pings
|
||||
var/ping_cooldown = 0
|
||||
|
||||
/obj/machinery/computer/drone_control/attack_ai(var/mob/user as mob)
|
||||
return src.attack_hand(user)
|
||||
/obj/machinery/computer/drone_control/Initialize(mapload)
|
||||
. = ..()
|
||||
find_fab()
|
||||
|
||||
|
||||
/obj/machinery/computer/drone_control/attack_hand(var/mob/user as mob)
|
||||
/obj/machinery/computer/drone_control/attack_hand(mob/user)
|
||||
if(..())
|
||||
return
|
||||
|
||||
@@ -23,105 +25,112 @@
|
||||
to_chat(user, "<span class='warning'>Access denied.</span>")
|
||||
return
|
||||
|
||||
interact(user)
|
||||
ui_interact(user)
|
||||
|
||||
/obj/machinery/computer/drone_control/attack_ghost(mob/user as mob)
|
||||
interact(user)
|
||||
/obj/machinery/computer/drone_control/attack_ghost(mob/user)
|
||||
ui_interact(user)
|
||||
|
||||
/obj/machinery/computer/drone_control/interact(mob/user)
|
||||
// tgui\packages\tgui\interfaces\DroneConsole.js
|
||||
/obj/machinery/computer/drone_control/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "DroneConsole", "Drone Control Console", 420, 500, master_ui, state)
|
||||
ui.open()
|
||||
|
||||
user.set_machine(src)
|
||||
var/dat
|
||||
dat += "<B>Maintenance Units</B><BR>"
|
||||
/obj/machinery/computer/drone_control/ui_data(mob/user)
|
||||
var/list/data = list()
|
||||
data["drone_fab"] = FALSE
|
||||
data["fab_power"] = null
|
||||
data["drone_prod"] = null
|
||||
data["drone_progress"] = null
|
||||
if(dronefab)
|
||||
data["drone_fab"] = TRUE
|
||||
data["fab_power"] = dronefab.stat & NOPOWER ? FALSE : TRUE
|
||||
data["drone_prod"] = dronefab.produce_drones
|
||||
data["drone_progress"] = dronefab.drone_progress
|
||||
data["selected_area"] = drone_call_area
|
||||
data["ping_cd"] = ping_cooldown > world.time ? TRUE : FALSE
|
||||
|
||||
data["drones"] = list()
|
||||
for(var/mob/living/silicon/robot/drone/D in GLOB.silicon_mob_list)
|
||||
dat += "<BR>[D.real_name] ([D.stat == 2 ? "<font color='red'>INACTIVE" : "<font color='green'>ACTIVE"]</FONT>)"
|
||||
dat += "<font dize = 9><BR>Cell charge: [D.cell.charge]/[D.cell.maxcharge]."
|
||||
dat += "<BR>Currently located in: [get_area(D)]."
|
||||
dat += "<BR><A href='?src=[UID()];resync=\ref[D]'>Resync</A> | <A href='?src=[UID()];shutdown=\ref[D]'>Shutdown</A></font>"
|
||||
var/area/A = get_area(D)
|
||||
var/turf/T = get_turf(D)
|
||||
var/list/drone_data = list(
|
||||
name = D.real_name,
|
||||
uid = D.UID(),
|
||||
stat = D.stat,
|
||||
client = D.client ? TRUE : FALSE,
|
||||
health = round(D.health / D.maxHealth, 0.1),
|
||||
charge = round(D.cell.charge / D.cell.maxcharge, 0.1),
|
||||
location = "[A] ([T.x], [T.y])",
|
||||
sync_cd = D.sync_cooldown > world.time ? TRUE : FALSE
|
||||
)
|
||||
data["drones"] += list(drone_data)
|
||||
return data
|
||||
|
||||
dat += "<BR><BR><B>Request drone presence in area:</B> <A href='?src=[UID()];setarea=1'>[drone_call_area]</A> (<A href='?src=[UID()];ping=1'>Send ping</A>)"
|
||||
/obj/machinery/computer/drone_control/ui_static_data(mob/user)
|
||||
var/list/data = list()
|
||||
data["area_list"] = GLOB.TAGGERLOCATIONS
|
||||
return data
|
||||
|
||||
dat += "<BR><BR><B>Drone fabricator</B>: "
|
||||
dat += "[dronefab ? "<A href='?src=[UID()];toggle_fab=1'>[(dronefab.produce_drones && !(dronefab.stat & NOPOWER)) ? "ACTIVE" : "INACTIVE"]</A>" : "<font color='red'><b>FABRICATOR NOT DETECTED.</b></font> (<A href='?src=[UID()];search_fab=1'>search</a>)"]"
|
||||
user << browse(dat, "window=computer;size=400x500")
|
||||
onclose(user, "computer")
|
||||
return
|
||||
|
||||
|
||||
/obj/machinery/computer/drone_control/Topic(href, href_list)
|
||||
/obj/machinery/computer/drone_control/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state)
|
||||
if(..())
|
||||
return
|
||||
. = TRUE
|
||||
|
||||
if(!allowed(usr) && !usr.can_admin_interact())
|
||||
to_chat(usr, "<span class='warning'>Access denied.</span>")
|
||||
switch(action)
|
||||
if("find_fab")
|
||||
find_fab(usr)
|
||||
|
||||
if("toggle_fab")
|
||||
if(QDELETED(dronefab))
|
||||
dronefab = null
|
||||
return
|
||||
|
||||
dronefab.produce_drones = !dronefab.produce_drones
|
||||
var/toggle = dronefab.produce_drones ? "enable" : "disable"
|
||||
to_chat(usr, "<span class='notice'>You [toggle] drone production in the nearby fabricator.</span>")
|
||||
message_admins("[key_name_admin(usr)] [toggle]d maintenance drone production from the control console.")
|
||||
log_game("[key_name(usr)] [toggle]d maintenance drone production from the control console.")
|
||||
|
||||
if("set_area")
|
||||
drone_call_area = params["area"]
|
||||
|
||||
if("ping")
|
||||
ping_cooldown = world.time + 1 MINUTES // One minute cooldown to prevent chat spam
|
||||
to_chat(usr, "<span class='notice'>You issue a maintenance request for all active drones, highlighting [drone_call_area].</span>")
|
||||
for(var/mob/living/silicon/robot/drone/D in GLOB.silicon_mob_list)
|
||||
if(D.client && D.stat == CONSCIOUS)
|
||||
to_chat(D, "<span class='boldnotice'>-- Maintenance drone presence requested in: [drone_call_area].</span>")
|
||||
|
||||
if("resync")
|
||||
var/mob/living/silicon/robot/drone/D = locateUID(params["uid"])
|
||||
if(D)
|
||||
D.sync_cooldown = world.time + 1 MINUTES // One minute cooldown to prevent chat spam
|
||||
to_chat(usr, "<span class='notice'>You issue a law synchronization directive for the drone.</span>")
|
||||
D.law_resync()
|
||||
|
||||
if("shutdown")
|
||||
var/mob/living/silicon/robot/drone/D = locateUID(params["uid"])
|
||||
if(D)
|
||||
to_chat(usr, "<span class='warning'>You issue a kill command for the unfortunate drone.</span>")
|
||||
message_admins("[key_name_admin(usr)] issued kill order for drone [key_name_admin(D)] from control console.")
|
||||
log_game("[key_name(usr)] issued kill order for [key_name(D)] from control console.")
|
||||
D.shut_down()
|
||||
|
||||
/obj/machinery/computer/drone_control/proc/find_fab(mob/user)
|
||||
if(dronefab)
|
||||
return
|
||||
|
||||
if((usr.contents.Find(src) || (in_range(src, usr) && istype(src.loc, /turf))) || (istype(usr, /mob/living/silicon)))
|
||||
usr.set_machine(src)
|
||||
for(var/obj/machinery/drone_fabricator/fab in get_area(src))
|
||||
|
||||
if(href_list["setarea"])
|
||||
if(fab.stat & NOPOWER)
|
||||
continue
|
||||
|
||||
//Probably should consider using another list, but this one will do.
|
||||
var/t_area = input("Select the area to ping.", "Set Target Area", null) as null|anything in GLOB.TAGGERLOCATIONS
|
||||
dronefab = fab
|
||||
if(user)
|
||||
to_chat(user, "<span class='notice'>Drone fabricator located.</span>")
|
||||
return
|
||||
|
||||
if(!t_area || GLOB.TAGGERLOCATIONS[t_area])
|
||||
return
|
||||
|
||||
drone_call_area = t_area
|
||||
to_chat(usr, "<span class='notice'>You set the area selector to [drone_call_area].</span>")
|
||||
|
||||
else if(href_list["ping"])
|
||||
|
||||
to_chat(usr, "<span class='notice'>You issue a maintenance request for all active drones, highlighting [drone_call_area].</span>")
|
||||
for(var/mob/living/silicon/robot/drone/D in GLOB.silicon_mob_list)
|
||||
if(D.client && D.stat == 0)
|
||||
to_chat(D, "-- Maintenance drone presence requested in: [drone_call_area].")
|
||||
|
||||
else if(href_list["resync"])
|
||||
|
||||
var/mob/living/silicon/robot/drone/D = locate(href_list["resync"])
|
||||
|
||||
if(D.stat != 2)
|
||||
to_chat(usr, "<span class='warning'>You issue a law synchronization directive for the drone.</span>")
|
||||
D.law_resync()
|
||||
|
||||
else if(href_list["shutdown"])
|
||||
|
||||
var/mob/living/silicon/robot/drone/D = locate(href_list["shutdown"])
|
||||
|
||||
if(D.stat != 2)
|
||||
to_chat(usr, "<span class='warning'>You issue a kill command for the unfortunate drone.</span>")
|
||||
message_admins("[key_name_admin(usr)] issued kill order for drone [key_name_admin(D)] from control console.")
|
||||
log_game("[key_name(usr)] issued kill order for [key_name(src)] from control console.")
|
||||
D.shut_down()
|
||||
|
||||
else if(href_list["search_fab"])
|
||||
if(dronefab)
|
||||
return
|
||||
|
||||
for(var/obj/machinery/drone_fabricator/fab in get_area(src))
|
||||
|
||||
if(fab.stat & NOPOWER)
|
||||
continue
|
||||
|
||||
dronefab = fab
|
||||
to_chat(usr, "<span class='notice'>Drone fabricator located.</span>")
|
||||
return
|
||||
|
||||
to_chat(usr, "<span class='warning'>Unable to locate drone fabricator.</span>")
|
||||
|
||||
else if(href_list["toggle_fab"])
|
||||
|
||||
if(!dronefab)
|
||||
return
|
||||
|
||||
if(get_dist(src,dronefab) > 3)
|
||||
dronefab = null
|
||||
to_chat(usr, "<span class='warning'>Unable to locate drone fabricator.</span>")
|
||||
return
|
||||
|
||||
dronefab.produce_drones = !dronefab.produce_drones
|
||||
to_chat(usr, "<span class='notice'>You [dronefab.produce_drones ? "enable" : "disable"] drone production in the nearby fabricator.</span>")
|
||||
|
||||
src.updateUsrDialog()
|
||||
if(user)
|
||||
to_chat(user, "<span class='warning'>Unable to locate drone fabricator.</span>")
|
||||
|
||||
@@ -1,22 +1,18 @@
|
||||
/obj/machinery/drone_fabricator
|
||||
name = "drone fabricator"
|
||||
desc = "A large automated factory for producing maintenance drones."
|
||||
icon = 'icons/obj/machines/drone_fab.dmi'
|
||||
icon_state = "drone_fab_idle"
|
||||
|
||||
density = 1
|
||||
anchored = 1
|
||||
density = TRUE
|
||||
anchored = TRUE
|
||||
use_power = IDLE_POWER_USE
|
||||
idle_power_usage = 20
|
||||
active_power_usage = 5000
|
||||
|
||||
var/drone_progress = 0
|
||||
var/produce_drones = 1
|
||||
var/time_last_drone = 500
|
||||
|
||||
icon = 'icons/obj/machines/drone_fab.dmi'
|
||||
icon_state = "drone_fab_idle"
|
||||
|
||||
/obj/machinery/drone_fabricator/New()
|
||||
..()
|
||||
var/produce_drones = TRUE
|
||||
var/drone_progress = 100
|
||||
var/time_last_drone = 0
|
||||
|
||||
/obj/machinery/drone_fabricator/power_change()
|
||||
if(powered())
|
||||
@@ -31,7 +27,8 @@
|
||||
return
|
||||
|
||||
if(stat & NOPOWER || !produce_drones)
|
||||
if(icon_state != "drone_fab_nopower") icon_state = "drone_fab_nopower"
|
||||
if(icon_state != "drone_fab_nopower")
|
||||
icon_state = "drone_fab_nopower"
|
||||
return
|
||||
|
||||
if(drone_progress >= 100)
|
||||
@@ -40,14 +37,14 @@
|
||||
|
||||
icon_state = "drone_fab_active"
|
||||
var/elapsed = world.time - time_last_drone
|
||||
drone_progress = round((elapsed/config.drone_build_time)*100)
|
||||
drone_progress = round((elapsed / config.drone_build_time) * 100)
|
||||
|
||||
if(drone_progress >= 100)
|
||||
visible_message("\The [src] voices a strident beep, indicating a drone chassis is prepared.")
|
||||
visible_message("[src] voices a strident beep, indicating a drone chassis is prepared.")
|
||||
|
||||
/obj/machinery/drone_fabricator/examine(mob/user)
|
||||
. = ..()
|
||||
if(produce_drones && drone_progress >= 100 && istype(user,/mob/dead) && config.allow_drone_spawn && count_drones() < config.max_maint_drones)
|
||||
if(produce_drones && drone_progress >= 100 && isobserver(user) && config.allow_drone_spawn && count_drones() < config.max_maint_drones)
|
||||
. += "<BR><B>A drone is prepared. Select 'Join As Drone' from the Ghost tab to spawn as a maintenance drone.</B>"
|
||||
|
||||
/obj/machinery/drone_fabricator/proc/count_drones()
|
||||
@@ -57,18 +54,17 @@
|
||||
drones++
|
||||
return drones
|
||||
|
||||
/obj/machinery/drone_fabricator/proc/create_drone(var/client/player)
|
||||
|
||||
/obj/machinery/drone_fabricator/proc/create_drone(client/player)
|
||||
if(stat & NOPOWER)
|
||||
return
|
||||
|
||||
if(!produce_drones || !config.allow_drone_spawn || count_drones() >= config.max_maint_drones)
|
||||
return
|
||||
|
||||
if(!player || !istype(player.mob,/mob/dead))
|
||||
if(!player || !isobserver(player.mob))
|
||||
return
|
||||
|
||||
visible_message("\The [src] churns and grinds as it lurches into motion, disgorging a shiny new drone after a few moments.")
|
||||
visible_message("[src] churns and grinds as it lurches into motion, disgorging a shiny new drone after a few moments.")
|
||||
flick("h_lathe_leave",src)
|
||||
|
||||
time_last_drone = world.time
|
||||
@@ -88,41 +84,40 @@
|
||||
to_chat(src, "<span class='warning'>That verb is not currently permitted.</span>")
|
||||
return
|
||||
|
||||
if(!src.stat)
|
||||
if(stat != DEAD)
|
||||
return
|
||||
|
||||
if(usr != src)
|
||||
return 0 //something is terribly wrong
|
||||
return FALSE //something is terribly wrong
|
||||
|
||||
if(jobban_isbanned(src,"nonhumandept") || jobban_isbanned(src,"Drone"))
|
||||
to_chat(usr, "<span class='warning'>You are banned from playing drones and cannot spawn as a drone.</span>")
|
||||
if(jobban_isbanned(src, "nonhumandept") || jobban_isbanned(src, "Drone"))
|
||||
to_chat(usr, "<span class='warning'>You are banned from playing drones, and cannot spawn as one.</span>")
|
||||
return
|
||||
|
||||
if(!SSticker || SSticker.current_state < 3)
|
||||
if(!SSticker || SSticker.current_state < GAME_STATE_PLAYING)
|
||||
to_chat(src, "<span class='warning'>You can't join as a drone before the game starts!</span>")
|
||||
return
|
||||
|
||||
var/drone_age = 14 // 14 days to play as a drone
|
||||
var/player_age_check = check_client_age(usr.client, drone_age)
|
||||
var/player_age_check = check_client_age(usr.client, 14) // 14 days to play as a drone
|
||||
if(player_age_check && config.use_age_restriction_for_antags)
|
||||
to_chat(usr, "<span class='warning'>This role is not yet available to you. You need to wait another [player_age_check] days.</span>")
|
||||
return
|
||||
|
||||
var/pt_req = role_available_in_playtime(client, ROLE_DRONE)
|
||||
var/pt_req = role_available_in_playtime(client, "Drone")
|
||||
if(pt_req)
|
||||
var/pt_req_string = get_exp_format(pt_req)
|
||||
to_chat(usr, "<span class='warning'>This role is not yet available to you. Play another [pt_req_string] to unlock it.</span>")
|
||||
return
|
||||
|
||||
var/deathtime = world.time - src.timeofdeath
|
||||
var/joinedasobserver = 0
|
||||
if(istype(src,/mob/dead/observer))
|
||||
var/deathtime = world.time - timeofdeath
|
||||
var/joinedasobserver = FALSE
|
||||
if(isobserver(src))
|
||||
var/mob/dead/observer/G = src
|
||||
if(cannotPossess(G))
|
||||
to_chat(usr, "<span class='warning'>Upon using the antagHUD you forfeited the ability to join the round.</span>")
|
||||
return
|
||||
if(G.started_as_observer == 1)
|
||||
joinedasobserver = 1
|
||||
if(G.started_as_observer == TRUE)
|
||||
joinedasobserver = TRUE
|
||||
|
||||
var/deathtimeminutes = round(deathtime / 600)
|
||||
var/pluralcheck = "minute"
|
||||
@@ -132,7 +127,7 @@
|
||||
pluralcheck = " [deathtimeminutes] minute and"
|
||||
else if(deathtimeminutes > 1)
|
||||
pluralcheck = " [deathtimeminutes] minutes and"
|
||||
var/deathtimeseconds = round((deathtime - deathtimeminutes * 600) / 10,1)
|
||||
var/deathtimeseconds = round((deathtime - deathtimeminutes * 600) / 10, 1)
|
||||
|
||||
if(deathtime < 6000 && joinedasobserver == 0)
|
||||
to_chat(usr, "You have been dead for[pluralcheck] [deathtimeseconds] seconds.")
|
||||
@@ -151,7 +146,7 @@
|
||||
return
|
||||
|
||||
if(DF.drone_progress >= 100)
|
||||
DF.create_drone(src.client)
|
||||
DF.create_drone(client)
|
||||
return
|
||||
|
||||
to_chat(src, "<span class='warning'>There are no available drone spawn points, sorry.</span>")
|
||||
|
||||
@@ -474,6 +474,7 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
|
||||
rename_character(real_name, get_default_name("Default"))
|
||||
languages = list()
|
||||
speech_synthesizer_langs = list()
|
||||
radio.recalculateChannels()
|
||||
|
||||
update_icons()
|
||||
update_headlamp()
|
||||
@@ -481,7 +482,7 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
|
||||
speed = 0 // Remove upgrades.
|
||||
ionpulse = FALSE
|
||||
magpulse = FALSE
|
||||
add_language("Robot Talk", 1)
|
||||
add_language("Robot Talk", TRUE)
|
||||
if("lava" in weather_immunities) // Remove the lava-immunity effect given by a printable upgrade
|
||||
weather_immunities -= "lava"
|
||||
|
||||
|
||||
@@ -241,6 +241,7 @@
|
||||
modules += new /obj/item/multitool/cyborg(src)
|
||||
modules += new /obj/item/t_scanner(src)
|
||||
modules += new /obj/item/analyzer(src)
|
||||
modules += new /obj/item/geiger_counter/cyborg(src)
|
||||
modules += new /obj/item/holosign_creator/engineering(src)
|
||||
modules += new /obj/item/gripper(src)
|
||||
modules += new /obj/item/matter_decompiler(src)
|
||||
@@ -337,7 +338,7 @@
|
||||
/obj/item/robot_module/butler/respawn_consumable(var/mob/living/silicon/robot/R)
|
||||
if(emag)
|
||||
var/obj/item/reagent_containers/food/drinks/cans/beer/B = emag
|
||||
B.reagents.add_reagent("beer2", 2)
|
||||
B.reagents.add_reagent("beer2", 5)
|
||||
..()
|
||||
|
||||
/obj/item/robot_module/butler/add_languages(var/mob/living/silicon/robot/R)
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
bubble_icon = "machine"
|
||||
has_unlimited_silicon_privilege = 1
|
||||
weather_immunities = list("ash")
|
||||
flags_2 = RAD_PROTECT_CONTENTS_2 | RAD_NO_CONTAMINATE_2
|
||||
var/syndicate = 0
|
||||
var/const/MAIN_CHANNEL = "Main Frequency"
|
||||
var/lawchannel = MAIN_CHANNEL // Default channel on which to state laws
|
||||
@@ -161,7 +162,7 @@
|
||||
/mob/living/silicon/drop_item()
|
||||
return
|
||||
|
||||
/mob/living/silicon/electrocute_act(shock_damage, obj/source, siemens_coeff = 1, safety = FALSE, override = FALSE, tesla_shock = FALSE, illusion = FALSE, stun = TRUE)
|
||||
/mob/living/silicon/electrocute_act(shock_damage, source, siemens_coeff = 1, flags = NONE)
|
||||
return FALSE //So borgs they don't die trying to fix wiring
|
||||
|
||||
/mob/living/silicon/emp_act(severity)
|
||||
@@ -222,27 +223,9 @@
|
||||
|
||||
return 2
|
||||
|
||||
/mob/living/silicon/apply_effect(var/effect = 0,var/effecttype = STUN, var/blocked = 0, var/negate_armor = 0)
|
||||
return 0//The only effect that can hit them atm is flashes and they still directly edit so this works for now
|
||||
/*
|
||||
if(!effect || (blocked >= 2)) return 0
|
||||
switch(effecttype)
|
||||
if(STUN)
|
||||
Stun(effect / (blocked + 1))
|
||||
if(WEAKEN)
|
||||
Weaken(effect / (blocked + 1))
|
||||
if(PARALYZE)
|
||||
Paralyse(effect / (blocked + 1))
|
||||
if(IRRADIATE)
|
||||
radiation += min((effect - (effect*getarmor(null, "rad"))), 0)//Rads auto check armor
|
||||
if(STUTTER)
|
||||
stuttering = max(stuttering,(effect/(blocked+1)))
|
||||
if(EYE_BLUR)
|
||||
eye_blurry = max(eye_blurry,(effect/(blocked+1)))
|
||||
if(DROWSY)
|
||||
drowsyness = max(drowsyness,(effect/(blocked+1)))
|
||||
updatehealth()
|
||||
return 1*/
|
||||
/mob/living/silicon/apply_effect(effect = 0, effecttype = STUN, blocked = 0)
|
||||
return FALSE //The only effect that can hit them atm is flashes and they still directly edit so this works for now
|
||||
|
||||
|
||||
/proc/islinked(var/mob/living/silicon/robot/bot, var/mob/living/silicon/ai/ai)
|
||||
if(!istype(bot) || !istype(ai))
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user