Merge branch 'master' into upstream-merge-33627

This commit is contained in:
LetterJay
2017-12-27 04:41:27 -06:00
committed by GitHub
758 changed files with 9514 additions and 7191 deletions
+5 -3
View File
@@ -705,15 +705,17 @@
/datum/admins/proc/output_all_devil_info()
var/devil_number = 0
for(var/D in SSticker.mode.devils)
for(var/datum/mind/D in SSticker.mode.devils)
devil_number++
to_chat(usr, "Devil #[devil_number]:<br><br>" + SSticker.mode.printdevilinfo(D))
var/datum/antagonist/devil/devil = D.has_antag_datum(/datum/antagonist/devil)
to_chat(usr, "Devil #[devil_number]:<br><br>" + devil.printdevilinfo())
if(!devil_number)
to_chat(usr, "<b>No Devils located</b>" )
/datum/admins/proc/output_devil_info(mob/living/M)
if(is_devil(M))
to_chat(usr, SSticker.mode.printdevilinfo(M))
var/datum/antagonist/devil/devil = M.mind.has_antag_datum(/datum/antagonist/devil)
to_chat(usr, devil.printdevilinfo())
else
to_chat(usr, "<b>[M] is not a devil.")
+1
View File
@@ -94,6 +94,7 @@ GLOBAL_LIST(round_end_notifiees)
return "Unable to run query, another admin proc call is in progress. Try again later."
GLOB.AdminProcCaller = "CHAT_[sender]" //_ won't show up in ckeys so it'll never match with a real admin
var/list/results = world.SDQL2_query(params, GLOB.AdminProcCaller, GLOB.AdminProcCaller)
GLOB.AdminProcCaller = null
if(!results)
return "Query produced no output"
var/list/text_res = results.Copy(1, 3)
+4 -3
View File
@@ -384,9 +384,10 @@
dat += "<BR><span class='userdanger'>[other_players] players in invalid state or the statistics code is bugged!</span>"
dat += "<BR>"
if(SSticker.mode.syndicates.len)
var/list/nukeops = get_antagonists(/datum/antagonist/nukeop)
if(nukeops.len)
dat += "<br><table cellspacing=5><tr><td><B>Syndicates</B></td><td></td></tr>"
for(var/datum/mind/N in SSticker.mode.syndicates)
for(var/datum/mind/N in nukeops)
var/mob/M = N.current
if(M)
dat += "<tr><td><a href='?_src_=holder;[HrefToken()];adminplayeropts=[REF(M)]'>[M.real_name]</a>[M.client ? "" : " <i>(No Client)</i>"][M.stat == DEAD ? " <b><font color=red>(DEAD)</font></b>" : ""]</td>"
@@ -523,7 +524,7 @@
if(SSticker.mode.brother_teams.len > 0)
dat += "<br><table cellspacing=5><tr><td><B>Brothers</B></td><td></td><td></td></tr>"
for(var/datum/objective_team/brother_team/team in SSticker.mode.brother_teams)
for(var/datum/team/brother_team/team in SSticker.mode.brother_teams)
for(var/datum/mind/brother in team.members)
var/mob/M = brother.current
if(M)
+2 -2
View File
@@ -92,7 +92,7 @@
var/new_volume = input(user, "Choose a volume.", "Sound Emitter", sound_volume) as null|num
if(isnull(new_volume))
return
new_volume = Clamp(new_volume, 0, 100)
new_volume = CLAMP(new_volume, 0, 100)
sound_volume = new_volume
to_chat(user, "<span class='notice'>Volume set to [sound_volume]%.</span>")
if(href_list["edit_mode"])
@@ -115,7 +115,7 @@
var/new_radius = input(user, "Choose a radius.", "Sound Emitter", sound_volume) as null|num
if(isnull(new_radius))
return
new_radius = Clamp(new_radius, 0, 127)
new_radius = CLAMP(new_radius, 0, 127)
play_radius = new_radius
to_chat(user, "<span class='notice'>Audible radius set to [play_radius].</span>")
if(href_list["play"])
+1 -1
View File
@@ -220,7 +220,7 @@
var/nsd = CONFIG_GET(number/note_stale_days)
var/nfd = CONFIG_GET(number/note_fresh_days)
if (agegate && type == "note" && isnum(nsd) && isnum(nfd) && nsd > nfd)
var/alpha = Clamp(100 - (age - nfd) * (85 / (nsd - nfd)), 15, 100)
var/alpha = CLAMP(100 - (age - nfd) * (85 / (nsd - nfd)), 15, 100)
if (alpha < 100)
if (alpha <= 15)
if (skipped)
+1 -1
View File
@@ -1943,7 +1943,7 @@
return
var/list/offset = splittext(href_list["offset"],",")
var/number = Clamp(text2num(href_list["object_count"]), 1, 100)
var/number = CLAMP(text2num(href_list["object_count"]), 1, 100)
var/X = offset.len > 0 ? text2num(offset[1]) : 0
var/Y = offset.len > 1 ? text2num(offset[2]) : 0
var/Z = offset.len > 2 ? text2num(offset[3]) : 0
+1 -1
View File
@@ -435,7 +435,7 @@
else if(expression[start + 1] == "\[" && islist(v))
var/list/L = v
var/index = SDQL_expression(source, expression[start + 2])
if(isnum(index) && (!IsInteger(index) || L.len < index))
if(isnum(index) && (!ISINTEGER(index) || L.len < index))
to_chat(usr, "<span class='danger'>Invalid list index: [index]</span>")
return null
return L[index]
+11 -4
View File
@@ -107,6 +107,8 @@ GLOBAL_VAR(LastAdminCalledTarget)
GLOBAL_PROTECT(LastAdminCalledTarget)
GLOBAL_VAR(LastAdminCalledProc)
GLOBAL_PROTECT(LastAdminCalledProc)
GLOBAL_LIST_EMPTY(AdminProcCallSpamPrevention)
GLOBAL_PROTECT(AdminProcCallSpamPrevention)
/proc/WrapAdminProcCall(target, procname, list/arguments)
var/current_caller = GLOB.AdminProcCaller
@@ -114,9 +116,14 @@ GLOBAL_PROTECT(LastAdminCalledProc)
if(!ckey)
CRASH("WrapAdminProcCall with no ckey: [target] [procname] [english_list(arguments)]")
if(current_caller && current_caller != ckey)
to_chat(usr, "<span class='adminnotice'>Another set of admin called procs are still running, your proc will be run after theirs finish.</span>")
UNTIL(!GLOB.AdminProcCaller)
to_chat(usr, "<span class='adminnotice'>Running your proc</span>")
if(!GLOB.AdminProcCallSpamPrevention[ckey])
to_chat(usr, "<span class='adminnotice'>Another set of admin called procs are still running, your proc will be run after theirs finish.</span>")
GLOB.AdminProcCallSpamPrevention[ckey] = TRUE
UNTIL(!GLOB.AdminProcCaller)
to_chat(usr, "<span class='adminnotice'>Running your proc</span>")
GLOB.AdminProcCallSpamPrevention -= ckey
else
UNTIL(!GLOB.AdminProcCaller)
GLOB.LastAdminCalledProc = procname
if(target != GLOBAL_PROC)
GLOB.LastAdminCalledTargetRef = "[REF(target)]"
@@ -735,7 +742,7 @@ GLOBAL_PROTECT(LastAdminCalledProc)
if(Rad.anchored)
if(!Rad.loaded_tank)
var/obj/item/tank/internals/plasma/Plasma = new/obj/item/tank/internals/plasma(Rad)
ASSERT_GAS(/datum/gas/plasma, Plasma.air_contents)
Plasma.air_contents.assert_gas(/datum/gas/plasma)
Plasma.air_contents.gases[/datum/gas/plasma][MOLES] = 70
Rad.drainratio = 0
Rad.loaded_tank = Plasma
+30 -1
View File
@@ -45,7 +45,8 @@ GLOBAL_LIST_INIT(admin_verbs_debug_mapping, list(
/client/proc/manipulate_organs,
/client/proc/start_line_profiling,
/client/proc/stop_line_profiling,
/client/proc/show_line_profiling
/client/proc/show_line_profiling,
/client/proc/create_mapping_job_icons
))
/obj/effect/debugging/mapfix_marker
@@ -265,3 +266,31 @@ GLOBAL_VAR_INIT(say_disabled, FALSE)
message_admins("[src.ckey] used 'Disable all communication verbs', killing all communication methods.")
else
message_admins("[src.ckey] used 'Disable all communication verbs', restoring all communication methods.")
//This generates the icon states for job starting location landmarks.
/client/proc/create_mapping_job_icons()
set name = "Generate job landmarks icons"
set category = "Mapping"
var/icon/final = icon()
var/mob/living/carbon/human/dummy/D = new(locate(1,1,1)) //spawn on 1,1,1 so we don't have runtimes when items are deleted
D.setDir(SOUTH)
for(var/job in subtypesof(/datum/job))
var/datum/job/JB = new job
switch(JB.title)
if("AI")
final.Insert(icon('icons/mob/ai.dmi', "ai", SOUTH, 1), "AI")
if("Cyborg")
final.Insert(icon('icons/mob/robots.dmi', "robot", SOUTH, 1), "Cyborg")
else
for(var/obj/item/I in D)
qdel(I)
randomize_human(D)
JB.equip(D, TRUE, FALSE)
COMPILE_OVERLAYS(D)
var/icon/I = icon(getFlatIcon(D), frame = 1)
final.Insert(I, JB.title)
qdel(D)
//Also add the x
for(var/x_number in 1 to 4)
final.Insert(icon('icons/mob/screen_gen.dmi', "x[x_number == 1 ? "" : x_number]"), "x[x_number == 1 ? "" : x_number]")
fcopy(final, "icons/mob/landmarks.dmi")
+10 -3
View File
@@ -213,7 +213,9 @@ GLOBAL_PROTECT(VVpixelmovement)
.["class"] = null
return
.["type"] = type
.["value"] = new type()
var/atom/newguy = new type()
newguy.var_edited = TRUE
.["value"] = newguy
if (VV_NEW_DATUM)
var/type = pick_closest_path(FALSE, get_fancy_list_of_datum_types())
@@ -221,7 +223,9 @@ GLOBAL_PROTECT(VVpixelmovement)
.["class"] = null
return
.["type"] = type
.["value"] = new type()
var/datum/newguy = new type()
newguy.var_edited = TRUE
.["value"] = newguy
if (VV_NEW_TYPE)
var/type = current_value
@@ -237,7 +241,10 @@ GLOBAL_PROTECT(VVpixelmovement)
.["class"] = null
return
.["type"] = type
.["value"] = new type()
var/datum/newguy = new type()
if(istype(newguy))
newguy.var_edited = TRUE
.["value"] = newguy
if (VV_NEW_LIST)
+13 -13
View File
@@ -238,26 +238,17 @@
if(agentcount < 3)
return 0
var/nuke_code = random_nukecode()
var/obj/machinery/nuclearbomb/nuke = locate("syndienuke") in GLOB.nuke_list
if(nuke)
nuke.r_code = nuke_code
//Let's find the spawn locations
var/leader_chosen = FALSE
var/spawnpos = 1 //Decides where they'll spawn. 1=leader.
var/datum/team/nuclear/nuke_team
for(var/mob/c in chosen)
if(spawnpos > GLOB.nukeop_start.len)
spawnpos = 1 //Ran out of spawns. Let's loop back to the first non-leader position
var/mob/living/carbon/human/new_character=makeBody(c)
if(!leader_chosen)
leader_chosen = TRUE
new_character.mind.make_Nuke(pick(GLOB.nukeop_leader_start), nuke_code, TRUE)
var/datum/antagonist/nukeop/N = new_character.mind.add_antag_datum(/datum/antagonist/nukeop/leader)
nuke_team = N.nuke_team
else
new_character.mind.make_Nuke(GLOB.nukeop_start[spawnpos], nuke_code)
spawnpos++
new_character.mind.add_antag_datum(/datum/antagonist/nukeop,nuke_team)
return 1
else
return 0
@@ -317,12 +308,15 @@
//Assign antag status and the mission
SSticker.mode.traitors += Commando.mind
Commando.mind.special_role = "deathsquad"
var/datum/objective/missionobj = new
missionobj.owner = Commando.mind
missionobj.explanation_text = mission
missionobj.completed = 1
Commando.mind.objectives += missionobj
Commando.mind.add_antag_datum(/datum/antagonist/auto_custom)
//Greet the commando
to_chat(Commando, "<B><font size=3 color=red>You are the [numagents==1?"Deathsquad Officer":"Death Commando"].</font></B>")
var/missiondesc = "Your squad is being sent on a mission to [station_name()] by Nanotrasen's Security Division."
@@ -369,12 +363,15 @@
//Assign antag status and the mission
SSticker.mode.traitors += newmob.mind
newmob.mind.special_role = "official"
var/datum/objective/missionobj = new
missionobj.owner = newmob.mind
missionobj.explanation_text = mission
missionobj.completed = 1
newmob.mind.objectives += missionobj
newmob.mind.add_antag_datum(/datum/antagonist/auto_custom)
if(CONFIG_GET(flag/enforce_human_authority))
newmob.set_species(/datum/species/human)
@@ -474,12 +471,15 @@
//Assign antag status and the mission
SSticker.mode.traitors += ERTOperative.mind
ERTOperative.mind.special_role = "ERT"
var/datum/objective/missionobj = new
missionobj.owner = ERTOperative.mind
missionobj.explanation_text = mission
missionobj.completed = 1
ERTOperative.mind.objectives += missionobj
ERTOperative.mind.add_antag_datum(/datum/antagonist/auto_custom)
//Greet the commando
to_chat(ERTOperative, "<B><font size=3 color=red>You are [numagents==1?"the Emergency Response Team Commander":"an Emergency Response Officer"].</font></B>")
var/missiondesc = "Your squad is being sent on a Code [alert] mission to [station_name()] by Nanotrasen's Security Division."
+3
View File
@@ -28,6 +28,7 @@ GLOBAL_VAR_INIT(highlander, FALSE)
/mob/living/carbon/human/proc/make_scottish()
SSticker.mode.traitors += mind
mind.special_role = "highlander"
dna.species.species_traits |= NOGUNS //nice try jackass
var/datum/objective/steal/steal_objective = new
@@ -40,6 +41,8 @@ GLOBAL_VAR_INIT(highlander, FALSE)
hijack_objective.owner = mind
mind.objectives += hijack_objective
mind.add_antag_datum(/datum/antagonist/auto_custom)
mind.announce_objectives()
for(var/obj/item/I in get_equipped_items())
+23 -5
View File
@@ -12,7 +12,7 @@
var/vol = input(usr, "What volume would you like the sound to play at?",, 100) as null|num
if(!vol)
return
vol = Clamp(vol, 1, 100)
vol = CLAMP(vol, 1, 100)
var/sound/admin_sound = new()
admin_sound.file = S
@@ -80,14 +80,32 @@
to_chat(src, "<span class='warning'>For youtube-dl shortcuts like ytsearch: please use the appropriate full url from the website.</span>")
return
var/shell_scrubbed_input = shell_url_scrub(web_sound_input)
var/list/output = world.shelleo("[ytdl] --format \"bestaudio\[ext=mp3]/best\[ext=mp4]\[height<=360]/bestaudio\[ext=m4a]/bestaudio\[ext=aac]\" --get-url \"[shell_scrubbed_input]\"")
var/list/output = world.shelleo("[ytdl] --format \"bestaudio\[ext=mp3]/best\[ext=mp4]\[height<=360]/bestaudio\[ext=m4a]/bestaudio\[ext=aac]\" --dump-single-json --no-playlist -- \"[shell_scrubbed_input]\"")
var/errorlevel = output[SHELLEO_ERRORLEVEL]
var/stdout = output[SHELLEO_STDOUT]
var/stderr = output[SHELLEO_STDERR]
if(!errorlevel)
var/static/regex/content_url_regex = regex("https?://\\S+")
if(content_url_regex.Find(stdout))
web_sound_url = content_url_regex.match
var/list/data
try
data = json_decode(stdout)
catch(var/exception/e)
to_chat(src, "<span class='boldwarning'>Youtube-dl JSON parsing FAILED:</span>")
to_chat(src, "<span class='warning'>[e]: [stdout]</span>")
return
if (data["url"])
web_sound_url = data["url"]
var/title = "[data["title"]]"
var/webpage_url = title
if (data["webpage_url"])
webpage_url = "<a href=\"[data["webpage_url"]]\">[title]</a>"
var/res = alert(usr, "Show the title of and link to this song to the players?\n[title]",, "No", "Yes", "Cancel")
switch(res)
if("Yes")
to_chat(world, "<span class='boldannounce'>An admin played: [webpage_url]</span>")
if("Cancel")
return
if(SSevents.holidays && SSevents.holidays[APRIL_FOOLS])
pitch = pick(0.5, 0.7, 0.8, 0.85, 0.9, 0.95, 1.1, 1.2, 1.4, 1.6, 2.0, 2.5)
+9 -2
View File
@@ -386,7 +386,8 @@ Traitors and the like can also be revived with the previous role mostly intact.
A.equip_wizard()
if("Syndicate")
new_character.forceMove(pick(GLOB.nukeop_start))
call(/datum/game_mode/proc/equip_syndicate)(new_character)
var/datum/antagonist/nukeop/N = new_character.mind.has_antag_datum(/datum/antagonist/nukeop,TRUE)
N.equip_op()
if("Space Ninja")
var/list/ninja_spawn = list()
for(var/obj/effect/landmark/carpspawn/L in GLOB.landmarks_list)
@@ -1206,7 +1207,7 @@ GLOBAL_LIST_EMPTY(custom_outfits) //Admin created outfits
if(!holder)
return
var/list/punishment_list = list(ADMIN_PUNISHMENT_LIGHTNING, ADMIN_PUNISHMENT_BRAINDAMAGE, ADMIN_PUNISHMENT_GIB, ADMIN_PUNISHMENT_BSA, ADMIN_PUNISHMENT_FIREBALL)
var/list/punishment_list = list(ADMIN_PUNISHMENT_LIGHTNING, ADMIN_PUNISHMENT_BRAINDAMAGE, ADMIN_PUNISHMENT_GIB, ADMIN_PUNISHMENT_BSA, ADMIN_PUNISHMENT_FIREBALL, ADMIN_PUNISHMENT_ROD)
var/punishment = input("Choose a punishment", "DIVINE SMITING") as null|anything in punishment_list
@@ -1228,6 +1229,12 @@ GLOBAL_LIST_EMPTY(custom_outfits) //Admin created outfits
bluespace_artillery(target)
if(ADMIN_PUNISHMENT_FIREBALL)
new /obj/effect/temp_visual/target(get_turf(target))
if(ADMIN_PUNISHMENT_ROD)
var/turf/T = get_turf(target)
var/startside = pick(GLOB.cardinals)
var/turf/startT = spaceDebrisStartLoc(startside, T.z)
var/turf/endT = spaceDebrisFinishLoc(startside, T.z)
new /obj/effect/immovablerod(startT, endT,target)
var/msg = "[key_name_admin(usr)] punished [key_name_admin(target)] with [punishment]."
message_admins(msg)
+1 -1
View File
@@ -30,7 +30,7 @@
holder.update_icon()
/obj/item/device/assembly/flash/proc/clown_check(mob/living/carbon/human/user)
if(user.disabilities & CLUMSY && prob(50))
if(user.has_disability(CLUMSY) && prob(50))
flash_carbon(user, user, 15, 0)
return 0
return 1
+142 -142
View File
@@ -1,142 +1,142 @@
/obj/item/device/assembly/mousetrap
name = "mousetrap"
desc = "A handy little spring-loaded trap for catching pesty rodents."
icon_state = "mousetrap"
materials = list(MAT_METAL=100)
attachable = 1
var/armed = 0
/obj/item/device/assembly/mousetrap/examine(mob/user)
..()
if(armed)
to_chat(user, "The mousetrap is armed!")
else
to_chat(user, "The mousetrap is not armed.")
/obj/item/device/assembly/mousetrap/activate()
if(..())
armed = !armed
if(!armed)
if(ishuman(usr))
var/mob/living/carbon/human/user = usr
if((user.getBrainLoss() >= 60) || user.disabilities & CLUMSY && prob(50))
to_chat(user, "<span class='warning'>Your hand slips, setting off the trigger!</span>")
pulse(0)
update_icon()
if(usr)
playsound(usr.loc, 'sound/weapons/handcuffs.ogg', 30, 1, -3)
/obj/item/device/assembly/mousetrap/describe()
return "The pressure switch is [armed?"primed":"safe"]."
/obj/item/device/assembly/mousetrap/update_icon()
if(armed)
icon_state = "mousetraparmed"
else
icon_state = "mousetrap"
if(holder)
holder.update_icon()
/obj/item/device/assembly/mousetrap/proc/triggered(mob/target, type = "feet")
if(!armed)
return
var/obj/item/bodypart/affecting = null
if(ishuman(target))
var/mob/living/carbon/human/H = target
if(PIERCEIMMUNE in H.dna.species.species_traits)
playsound(src.loc, 'sound/effects/snap.ogg', 50, 1)
armed = 0
update_icon()
pulse(0)
return 0
switch(type)
if("feet")
if(!H.shoes)
affecting = H.get_bodypart(pick("l_leg", "r_leg"))
H.Knockdown(60)
if("l_hand", "r_hand")
if(!H.gloves)
affecting = H.get_bodypart(type)
H.Stun(60)
if(affecting)
if(affecting.receive_damage(1, 0))
H.update_damage_overlays()
else if(ismouse(target))
var/mob/living/simple_animal/mouse/M = target
visible_message("<span class='boldannounce'>SPLAT!</span>")
M.splat()
playsound(src.loc, 'sound/effects/snap.ogg', 50, 1)
armed = 0
update_icon()
pulse(0)
/obj/item/device/assembly/mousetrap/attack_self(mob/living/carbon/human/user)
if(!armed)
to_chat(user, "<span class='notice'>You arm [src].</span>")
else
if(((user.getBrainLoss() >= 60) || user.disabilities & CLUMSY) && prob(50))
var/which_hand = "l_hand"
if(!(user.active_hand_index % 2))
which_hand = "r_hand"
triggered(user, which_hand)
user.visible_message("<span class='warning'>[user] accidentally sets off [src], breaking their fingers.</span>", \
"<span class='warning'>You accidentally trigger [src]!</span>")
return
to_chat(user, "<span class='notice'>You disarm [src].</span>")
armed = !armed
update_icon()
playsound(user.loc, 'sound/weapons/handcuffs.ogg', 30, 1, -3)
/obj/item/device/assembly/mousetrap/attack_hand(mob/living/carbon/human/user)
if(armed)
if(((user.getBrainLoss() >= 60) || user.disabilities & CLUMSY) && prob(50))
var/which_hand = "l_hand"
if(!(user.active_hand_index % 2))
which_hand = "r_hand"
triggered(user, which_hand)
user.visible_message("<span class='warning'>[user] accidentally sets off [src], breaking their fingers.</span>", \
"<span class='warning'>You accidentally trigger [src]!</span>")
return
..()
/obj/item/device/assembly/mousetrap/Crossed(atom/movable/AM as mob|obj)
if(armed)
if(ismob(AM))
var/mob/MM = AM
if(!(MM.movement_type & FLYING))
if(ishuman(AM))
var/mob/living/carbon/H = AM
if(H.m_intent == MOVE_INTENT_RUN)
triggered(H)
H.visible_message("<span class='warning'>[H] accidentally steps on [src].</span>", \
"<span class='warning'>You accidentally step on [src]</span>")
else if(ismouse(MM))
triggered(MM)
else if(AM.density) // For mousetrap grenades, set off by anything heavy
triggered(AM)
..()
/obj/item/device/assembly/mousetrap/on_found(mob/finder)
if(armed)
finder.visible_message("<span class='warning'>[finder] accidentally sets off [src], breaking their fingers.</span>", \
"<span class='warning'>You accidentally trigger [src]!</span>")
triggered(finder, (finder.active_hand_index % 2 == 0) ? "r_hand" : "l_hand")
return 1 //end the search!
return 0
/obj/item/device/assembly/mousetrap/hitby(A as mob|obj)
if(!armed)
return ..()
visible_message("<span class='warning'>[src] is triggered by [A].</span>")
triggered(null)
/obj/item/device/assembly/mousetrap/armed
icon_state = "mousetraparmed"
armed = TRUE
/obj/item/device/assembly/mousetrap
name = "mousetrap"
desc = "A handy little spring-loaded trap for catching pesty rodents."
icon_state = "mousetrap"
materials = list(MAT_METAL=100)
attachable = 1
var/armed = 0
/obj/item/device/assembly/mousetrap/examine(mob/user)
..()
if(armed)
to_chat(user, "The mousetrap is armed!")
else
to_chat(user, "The mousetrap is not armed.")
/obj/item/device/assembly/mousetrap/activate()
if(..())
armed = !armed
if(!armed)
if(ishuman(usr))
var/mob/living/carbon/human/user = usr
if((user.has_disability(DUMB) || user.has_disability(CLUMSY)) && prob(50))
to_chat(user, "<span class='warning'>Your hand slips, setting off the trigger!</span>")
pulse(0)
update_icon()
if(usr)
playsound(usr.loc, 'sound/weapons/handcuffs.ogg', 30, 1, -3)
/obj/item/device/assembly/mousetrap/describe()
return "The pressure switch is [armed?"primed":"safe"]."
/obj/item/device/assembly/mousetrap/update_icon()
if(armed)
icon_state = "mousetraparmed"
else
icon_state = "mousetrap"
if(holder)
holder.update_icon()
/obj/item/device/assembly/mousetrap/proc/triggered(mob/target, type = "feet")
if(!armed)
return
var/obj/item/bodypart/affecting = null
if(ishuman(target))
var/mob/living/carbon/human/H = target
if(PIERCEIMMUNE in H.dna.species.species_traits)
playsound(src.loc, 'sound/effects/snap.ogg', 50, 1)
armed = 0
update_icon()
pulse(0)
return 0
switch(type)
if("feet")
if(!H.shoes)
affecting = H.get_bodypart(pick("l_leg", "r_leg"))
H.Knockdown(60)
if("l_hand", "r_hand")
if(!H.gloves)
affecting = H.get_bodypart(type)
H.Stun(60)
if(affecting)
if(affecting.receive_damage(1, 0))
H.update_damage_overlays()
else if(ismouse(target))
var/mob/living/simple_animal/mouse/M = target
visible_message("<span class='boldannounce'>SPLAT!</span>")
M.splat()
playsound(src.loc, 'sound/effects/snap.ogg', 50, 1)
armed = 0
update_icon()
pulse(0)
/obj/item/device/assembly/mousetrap/attack_self(mob/living/carbon/human/user)
if(!armed)
to_chat(user, "<span class='notice'>You arm [src].</span>")
else
if((user.has_disability(DUMB) || user.has_disability(CLUMSY)) && prob(50))
var/which_hand = "l_hand"
if(!(user.active_hand_index % 2))
which_hand = "r_hand"
triggered(user, which_hand)
user.visible_message("<span class='warning'>[user] accidentally sets off [src], breaking their fingers.</span>", \
"<span class='warning'>You accidentally trigger [src]!</span>")
return
to_chat(user, "<span class='notice'>You disarm [src].</span>")
armed = !armed
update_icon()
playsound(user.loc, 'sound/weapons/handcuffs.ogg', 30, 1, -3)
/obj/item/device/assembly/mousetrap/attack_hand(mob/living/carbon/human/user)
if(armed)
if((user.has_disability(DUMB) || user.has_disability(CLUMSY)) && prob(50))
var/which_hand = "l_hand"
if(!(user.active_hand_index % 2))
which_hand = "r_hand"
triggered(user, which_hand)
user.visible_message("<span class='warning'>[user] accidentally sets off [src], breaking their fingers.</span>", \
"<span class='warning'>You accidentally trigger [src]!</span>")
return
..()
/obj/item/device/assembly/mousetrap/Crossed(atom/movable/AM as mob|obj)
if(armed)
if(ismob(AM))
var/mob/MM = AM
if(!(MM.movement_type & FLYING))
if(ishuman(AM))
var/mob/living/carbon/H = AM
if(H.m_intent == MOVE_INTENT_RUN)
triggered(H)
H.visible_message("<span class='warning'>[H] accidentally steps on [src].</span>", \
"<span class='warning'>You accidentally step on [src]</span>")
else if(ismouse(MM))
triggered(MM)
else if(AM.density) // For mousetrap grenades, set off by anything heavy
triggered(AM)
..()
/obj/item/device/assembly/mousetrap/on_found(mob/finder)
if(armed)
finder.visible_message("<span class='warning'>[finder] accidentally sets off [src], breaking their fingers.</span>", \
"<span class='warning'>You accidentally trigger [src]!</span>")
triggered(finder, (finder.active_hand_index % 2 == 0) ? "r_hand" : "l_hand")
return 1 //end the search!
return 0
/obj/item/device/assembly/mousetrap/hitby(A as mob|obj)
if(!armed)
return ..()
visible_message("<span class='warning'>[src] is triggered by [A].</span>")
triggered(null)
/obj/item/device/assembly/mousetrap/armed
icon_state = "mousetraparmed"
armed = 1
@@ -37,14 +37,24 @@ GLOBAL_LIST_INIT(gaslist_cache, init_gaslist_cache())
reaction_results = new
//listmos procs
//use the macros in performance intensive areas. for their definitions, refer to code/__DEFINES/atmospherics.dm
// The following procs used to live here: thermal_energy(), assert_gas() and add_gas(). They have been moved into defines in code/__DEFINES/atmospherics.dm
//assert_gas(gas_id) - used to guarantee that the gas list for this id exists in gas_mixture.gases.
//Must be used before adding to a gas. May be used before reading from a gas.
/datum/gas_mixture/proc/assert_gas(gas_id)
ASSERT_GAS(gas_id, src)
//assert_gases(args) - shorthand for calling ASSERT_GAS() once for each gas type.
/datum/gas_mixture/proc/assert_gases()
for(var/id in args)
ASSERT_GAS(id, src)
//add_gas(gas_id) - similar to assert_gas(), but does not check for an existing
//gas list for this id. This can clobber existing gases.
//Used instead of assert_gas() when you know the gas does not exist. Faster than assert_gas().
/datum/gas_mixture/proc/add_gas(gas_id)
ADD_GAS(gas_id, gases)
//add_gases(args) - shorthand for calling add_gas() once for each gas_type.
/datum/gas_mixture/proc/add_gases()
var/cached_gases = gases
@@ -101,6 +111,9 @@ GLOBAL_LIST_INIT(gaslist_cache, init_gaslist_cache())
/datum/gas_mixture/proc/return_volume() //liters
return max(0, volume)
/datum/gas_mixture/proc/thermal_energy() //joules
return THERMAL_ENERGY(src) //see code/__DEFINES/atmospherics.dm; use the define in performance critical areas
/datum/gas_mixture/proc/archive()
//Update archived versions of variables
//Returns: 1 in all cases
@@ -399,7 +412,7 @@ GLOBAL_LIST_INIT(gaslist_cache, init_gaslist_cache())
return ""
/datum/gas_mixture/react(turf/open/dump_location)
. = 0
. = NO_REACTION
reaction_results = new
@@ -423,6 +436,22 @@ GLOBAL_LIST_INIT(gaslist_cache, init_gaslist_cache())
continue reaction_loop
//at this point, all minimum requirements for the reaction are satisfied.
/* currently no reactions have maximum requirements, so we can leave the checks commented out for a slight performance boost
PLEASE DO NOT REMOVE THIS CODE. the commenting is here only for a performance increase.
enabling these checks should be as easy as possible and the fact that they are disabled should be as clear as possible
var/list/max_reqs = reaction.max_requirements.Copy()
if((max_reqs["TEMP"] && temp > max_reqs["TEMP"]) \
|| (max_reqs["ENER"] && ener > max_reqs["ENER"]))
continue
max_reqs -= "TEMP"
max_reqs -= "ENER"
for(var/id in max_reqs)
if(cached_gases[id] && cached_gases[id][MOLES] > max_reqs[id])
continue reaction_loop
//at this point, all requirements for the reaction are satisfied. we can now react()
*/
. |= reaction.react(src, dump_location)
if (. & STOP_REACTIONS)
break
@@ -184,7 +184,7 @@
//fusion: a terrible idea that was fun but broken. Now reworked to be less broken and more interesting.
/datum/gas_reaction/fusion
exclude = FALSE
exclude = TRUE
priority = 2
name = "Plasmic Fusion"
id = "fusion"
@@ -185,13 +185,13 @@ Acts like a normal vent, but has an input AND output.
pump_direction = 1
if("set_input_pressure" in signal.data)
input_pressure_min = Clamp(text2num(signal.data["set_input_pressure"]),0,ONE_ATMOSPHERE*50)
input_pressure_min = CLAMP(text2num(signal.data["set_input_pressure"]),0,ONE_ATMOSPHERE*50)
if("set_output_pressure" in signal.data)
output_pressure_max = Clamp(text2num(signal.data["set_output_pressure"]),0,ONE_ATMOSPHERE*50)
output_pressure_max = CLAMP(text2num(signal.data["set_output_pressure"]),0,ONE_ATMOSPHERE*50)
if("set_external_pressure" in signal.data)
external_pressure_bound = Clamp(text2num(signal.data["set_external_pressure"]),0,ONE_ATMOSPHERE*50)
external_pressure_bound = CLAMP(text2num(signal.data["set_external_pressure"]),0,ONE_ATMOSPHERE*50)
if("status" in signal.data)
spawn(2)
@@ -127,7 +127,7 @@ Passive gate is similar to the regular pump except:
pressure = text2num(pressure)
. = TRUE
if(.)
target_pressure = Clamp(pressure, 0, MAX_OUTPUT_PRESSURE)
target_pressure = CLAMP(pressure, 0, MAX_OUTPUT_PRESSURE)
investigate_log("was set to [target_pressure] kPa by [key_name(usr)]", INVESTIGATE_ATMOS)
update_icon()
@@ -149,7 +149,7 @@ Passive gate is similar to the regular pump except:
on = !on
if("set_output_pressure" in signal.data)
target_pressure = Clamp(text2num(signal.data["set_output_pressure"]),0,ONE_ATMOSPHERE*50)
target_pressure = CLAMP(text2num(signal.data["set_output_pressure"]),0,ONE_ATMOSPHERE*50)
if(on != old_on)
investigate_log("was turned [on ? "on" : "off"] by a remote signal", INVESTIGATE_ATMOS)
@@ -133,9 +133,8 @@ Thus, the two variables affect pump operation are set in New():
pressure = text2num(pressure)
. = TRUE
if(.)
target_pressure = Clamp(pressure, 0, MAX_OUTPUT_PRESSURE)
investigate_log("Pump, [src.name], was set to [target_pressure] kPa by [key_name(usr)] at [x], [y], [z], [A]", INVESTIGATE_ATMOS)
message_admins("Pump, [src.name], was set to [target_pressure] kPa by [ADMIN_LOOKUPFLW(usr)] at [ADMIN_COORDJMP(T)], [A]")
target_pressure = CLAMP(pressure, 0, MAX_OUTPUT_PRESSURE)
investigate_log("was set to [target_pressure] kPa by [key_name(usr)]", INVESTIGATE_ATMOS)
update_icon()
/obj/machinery/atmospherics/components/binary/pump/atmosinit()
@@ -156,7 +155,7 @@ Thus, the two variables affect pump operation are set in New():
on = !on
if("set_output_pressure" in signal.data)
target_pressure = Clamp(text2num(signal.data["set_output_pressure"]),0,ONE_ATMOSPHERE*50)
target_pressure = CLAMP(text2num(signal.data["set_output_pressure"]),0,ONE_ATMOSPHERE*50)
if(on != old_on)
investigate_log("was turned [on ? "on" : "off"] by a remote signal", INVESTIGATE_ATMOS)
@@ -133,9 +133,8 @@ Thus, the two variables affect pump operation are set in New():
rate = text2num(rate)
. = TRUE
if(.)
transfer_rate = Clamp(rate, 0, MAX_TRANSFER_RATE)
investigate_log("Volume Pump, [src.name], was set to [transfer_rate] L/s by [key_name(usr)] at [x], [y], [z], [A]", INVESTIGATE_ATMOS)
message_admins("Volume Pump, [src.name], was set to [transfer_rate] L/s by [ADMIN_LOOKUPFLW(usr)] at [ADMIN_COORDJMP(T)], [A]")
transfer_rate = CLAMP(rate, 0, MAX_TRANSFER_RATE)
investigate_log("was set to [transfer_rate] L/s by [key_name(usr)]", INVESTIGATE_ATMOS)
update_icon()
/obj/machinery/atmospherics/components/binary/volume_pump/receive_signal(datum/signal/signal)
@@ -152,7 +151,7 @@ Thus, the two variables affect pump operation are set in New():
if("set_transfer_rate" in signal.data)
var/datum/gas_mixture/air1 = AIR1
transfer_rate = Clamp(text2num(signal.data["set_transfer_rate"]),0,air1.volume)
transfer_rate = CLAMP(text2num(signal.data["set_transfer_rate"]),0,air1.volume)
if(on != old_on)
investigate_log("was turned [on ? "on" : "off"] by a remote signal", INVESTIGATE_ATMOS)
@@ -103,7 +103,7 @@
var/datum/gas_mixture/filtered_out = new
filtered_out.temperature = removed.temperature
ASSERT_GAS(filter_type, filtered_out)
filtered_out.add_gas(filter_type)
filtered_out.gases[filter_type][MOLES] = removed.gases[filter_type][MOLES]
removed.gases[filter_type][MOLES] = 0
@@ -162,7 +162,7 @@
pressure = text2num(pressure)
. = TRUE
if(.)
target_pressure = Clamp(pressure, 0, MAX_OUTPUT_PRESSURE)
target_pressure = CLAMP(pressure, 0, MAX_OUTPUT_PRESSURE)
investigate_log("was set to [target_pressure] kPa by [key_name(usr)]", INVESTIGATE_ATMOS)
if("filter")
filter_type = null
@@ -152,7 +152,7 @@
pressure = text2num(pressure)
. = TRUE
if(.)
target_pressure = Clamp(pressure, 0, MAX_OUTPUT_PRESSURE)
target_pressure = CLAMP(pressure, 0, MAX_OUTPUT_PRESSURE)
investigate_log("was set to [target_pressure] kPa by [key_name(usr)]", INVESTIGATE_ATMOS)
if("node1")
var/value = text2num(params["concentration"])
@@ -131,7 +131,7 @@
if("set_volume_rate" in signal.data)
var/number = text2num(signal.data["set_volume_rate"])
var/datum/gas_mixture/air_contents = AIR1
volume_rate = Clamp(number, 0, air_contents.volume)
volume_rate = CLAMP(number, 0, air_contents.volume)
if("status" in signal.data)
spawn(2)
@@ -180,7 +180,7 @@
rate = text2num(rate)
. = TRUE
if(.)
volume_rate = Clamp(rate, 0, MAX_TRANSFER_RATE)
volume_rate = CLAMP(rate, 0, MAX_TRANSFER_RATE)
investigate_log("was set to [volume_rate] L/s by [key_name(usr)]", INVESTIGATE_ATMOS)
update_icon()
broadcast_status()
@@ -17,7 +17,7 @@
air_contents.volume = volume
air_contents.temperature = T20C
if(gas_type)
ASSERT_GAS(gas_type, air_contents)
air_contents.assert_gas(gas_type)
air_contents.gases[gas_type][MOLES] = AIR_CONTENTS
name = "[name] ([air_contents.gases[gas_type][GAS_META][META_GAS_NAME]])"
@@ -153,7 +153,7 @@
target = text2num(target)
. = TRUE
if(.)
target_temperature = Clamp(target, min_temperature, max_temperature)
target_temperature = CLAMP(target, min_temperature, max_temperature)
investigate_log("was set to [target_temperature] K by [key_name(usr)]", INVESTIGATE_ATMOS)
update_icon()
@@ -244,10 +244,10 @@
pump_direction = text2num(signal.data["direction"])
if("set_internal_pressure" in signal.data)
internal_pressure_bound = Clamp(text2num(signal.data["set_internal_pressure"]),0,ONE_ATMOSPHERE*50)
internal_pressure_bound = CLAMP(text2num(signal.data["set_internal_pressure"]),0,ONE_ATMOSPHERE*50)
if("set_external_pressure" in signal.data)
external_pressure_bound = Clamp(text2num(signal.data["set_external_pressure"]),0,ONE_ATMOSPHERE*50)
external_pressure_bound = CLAMP(text2num(signal.data["set_external_pressure"]),0,ONE_ATMOSPHERE*50)
if("reset_external_pressure" in signal.data)
external_pressure_bound = ONE_ATMOSPHERE
@@ -256,10 +256,10 @@
internal_pressure_bound = 0
if("adjust_internal_pressure" in signal.data)
internal_pressure_bound = Clamp(internal_pressure_bound + text2num(signal.data["adjust_internal_pressure"]),0,ONE_ATMOSPHERE*50)
internal_pressure_bound = CLAMP(internal_pressure_bound + text2num(signal.data["adjust_internal_pressure"]),0,ONE_ATMOSPHERE*50)
if("adjust_external_pressure" in signal.data)
external_pressure_bound = Clamp(external_pressure_bound + text2num(signal.data["adjust_external_pressure"]),0,ONE_ATMOSPHERE*50)
external_pressure_bound = CLAMP(external_pressure_bound + text2num(signal.data["adjust_external_pressure"]),0,ONE_ATMOSPHERE*50)
if("init" in signal.data)
name = signal.data["init"]
@@ -179,7 +179,7 @@
filtered_out.temperature = removed.temperature
for(var/gas in filter_types & removed_gases)
ADD_GAS(gas, filtered_gases)
filtered_out.add_gas(gas)
filtered_gases[gas][MOLES] = removed_gases[gas][MOLES]
removed_gases[gas][MOLES] = 0
@@ -132,7 +132,7 @@
if(!isopenturf(O))
return FALSE
var/datum/gas_mixture/merger = new
ASSERT_GAS(spawn_id, merger)
merger.assert_gas(spawn_id)
merger.gases[spawn_id][MOLES] = (spawn_mol)
merger.temperature = spawn_temp
O.assume_air(merger)
@@ -121,7 +121,7 @@
if(initialize_directions & dir)
return ..()
if((NORTH|EAST) & dir)
user.ventcrawl_layer = Clamp(user.ventcrawl_layer + 1, PIPING_LAYER_MIN, PIPING_LAYER_MAX)
user.ventcrawl_layer = CLAMP(user.ventcrawl_layer + 1, PIPING_LAYER_MIN, PIPING_LAYER_MAX)
if((SOUTH|WEST) & dir)
user.ventcrawl_layer = Clamp(user.ventcrawl_layer - 1, PIPING_LAYER_MIN, PIPING_LAYER_MAX)
user.ventcrawl_layer = CLAMP(user.ventcrawl_layer - 1, PIPING_LAYER_MIN, PIPING_LAYER_MAX)
to_chat(user, "You align yourself with the [user.ventcrawl_layer]\th output.")
@@ -196,7 +196,7 @@
/obj/machinery/portable_atmospherics/canister/proc/create_gas()
if(gas_type)
ADD_GAS(gas_type, air_contents.gases)
air_contents.add_gas(gas_type)
if(starter_temp)
air_contents.temperature = starter_temp
air_contents.gases[gas_type][MOLES] = (maximum_pressure * filled) * air_contents.volume / (R_IDEAL_GAS_EQUATION * air_contents.temperature)
@@ -411,7 +411,7 @@
pressure = text2num(pressure)
. = TRUE
if(.)
release_pressure = Clamp(round(pressure), can_min_release_pressure, can_max_release_pressure)
release_pressure = CLAMP(round(pressure), can_min_release_pressure, can_max_release_pressure)
investigate_log("was set to [release_pressure] kPa by [key_name(usr)].", INVESTIGATE_ATMOS)
if("valve")
var/logmsg
@@ -455,7 +455,7 @@
var/N = text2num(user_input)
if(!N)
return
timer_set = Clamp(N,minimum_timer_set,maximum_timer_set)
timer_set = CLAMP(N,minimum_timer_set,maximum_timer_set)
log_admin("[key_name(usr)] has activated a prototype valve timer")
. = TRUE
if("toggle_timer")
@@ -131,7 +131,7 @@
pressure = text2num(pressure)
. = TRUE
if(.)
pump.target_pressure = Clamp(round(pressure), PUMP_MIN_PRESSURE, PUMP_MAX_PRESSURE)
pump.target_pressure = CLAMP(round(pressure), PUMP_MIN_PRESSURE, PUMP_MAX_PRESSURE)
investigate_log("was set to [pump.target_pressure] kPa by [key_name(usr)].", INVESTIGATE_ATMOS)
if("eject")
if(holding)
@@ -45,7 +45,7 @@
filtered.temperature = filtering.temperature
for(var/gas in filtering.gases & scrubbing)
ADD_GAS(gas, filtered.gases)
filtered.add_gas(gas)
filtered.gases[gas][MOLES] = filtering.gases[gas][MOLES] // Shuffle the "bad" gasses to the filtered mixture.
filtering.gases[gas][MOLES] = 0
filtering.garbage_collect() // Now that the gasses are set to 0, clean up the mixture.
@@ -115,9 +115,11 @@
to_chat(user, "The Wish Granter punishes you for your wickedness, claiming your soul and warping your body to match the darkness in your heart.")
SSticker.mode.traitors += user.mind
user.mind.special_role = "traitor"
var/datum/objective/hijack/hijack = new
hijack.owner = user.mind
user.mind.objectives += hijack
user.mind.add_antag_datum(/datum/antagonist/auto_custom)
to_chat(user, "<B>Your inhibitions are swept away, the bonds of loyalty broken, you are free to murder as you please!</B>")
user.mind.announce_objectives()
user.set_species(/datum/species/shadow)
+3 -3
View File
@@ -86,7 +86,7 @@ Credit dupes that require a lot of manual work shouldn't be removed, unless they
/datum/export/process()
..()
cost *= GLOB.E**(k_elasticity * (1/30))
cost *= NUM_E**(k_elasticity * (1/30))
if(cost > init_cost)
cost = init_cost
@@ -94,7 +94,7 @@ Credit dupes that require a lot of manual work shouldn't be removed, unless they
/datum/export/proc/get_cost(obj/O, contr = 0, emag = 0)
var/amount = get_amount(O, contr, emag)
if(k_elasticity!=0)
return round((cost/k_elasticity) * (1 - GLOB.E**(-1 * k_elasticity * amount))) //anti-derivative of the marginal cost function
return round((cost/k_elasticity) * (1 - NUM_E**(-1 * k_elasticity * amount))) //anti-derivative of the marginal cost function
else
return round(cost * amount) //alternative form derived from L'Hopital to avoid division by 0
@@ -131,7 +131,7 @@ Credit dupes that require a lot of manual work shouldn't be removed, unless they
else
total_amount += amount
cost *= GLOB.E**(-1*k_elasticity*amount) //marginal cost modifier
cost *= NUM_E**(-1*k_elasticity*amount) //marginal cost modifier
SSblackbox.record_feedback("nested tally", "export_sold_cost", 1, list("[O.type]", "[the_cost]"))
// Total printout for the cargo console.
+36
View File
@@ -372,3 +372,39 @@ GLOBAL_LIST_EMPTY(asset_datums)
var/meter = icon('icons/obj/atmospherics/pipes/simple.dmi', "meterX", SOUTH, frame, movement_states)
if(meter)
register_asset(sanitize_filename("[prefix].south.meterX.png"), fcopy_rsc(meter))
// Representative icons for each research design
/datum/asset/simple/research_designs/register()
for (var/path in subtypesof(/datum/design))
var/datum/design/D = path
// construct the icon and slap it into the resource cache
var/atom/item = initial(D.build_path)
if (!ispath(item, /atom))
// biogenerator outputs to beakers by default
if (initial(D.build_type) & BIOGENERATOR)
item = /obj/item/reagent_containers/glass/beaker/large
else
continue // shouldn't happen, but just in case
// circuit boards become their resulting machines or computers
if (ispath(item, /obj/item/circuitboard))
var/obj/item/circuitboard/C = item
var/machine = initial(C.build_path)
if (machine)
item = machine
var/icon_file = initial(item.icon)
var/icon/I = icon(icon_file, initial(item.icon_state), SOUTH)
// computers (and snowflakes) get their screen and keyboard sprites
if (ispath(item, /obj/machinery/computer) || ispath(item, /obj/machinery/power/solar_control))
var/obj/machinery/computer/C = item
var/screen = initial(C.icon_screen)
var/keyboard = initial(C.icon_keyboard)
if (screen)
I.Blend(icon(icon_file, screen, SOUTH), ICON_OVERLAY)
if (keyboard)
I.Blend(icon(icon_file, keyboard, SOUTH), ICON_OVERLAY)
assets["design_[initial(D.id)].png"] = I
return ..()
+3
View File
@@ -68,3 +68,6 @@
var/datum/chatOutput/chatOutput
var/list/credits //lazy list of all credit object bound to this client
var/datum/player_details/player_details //these persist between logins/logouts during the same round.
+16 -4
View File
@@ -152,7 +152,7 @@ GLOBAL_LIST(external_rsc_urls)
#if (PRELOAD_RSC == 0)
var/static/next_external_rsc = 0
if(external_rsc_urls && external_rsc_urls.len)
next_external_rsc = Wrap(next_external_rsc+1, 1, external_rsc_urls.len+1)
next_external_rsc = WRAP(next_external_rsc+1, 1, external_rsc_urls.len+1)
preload_rsc = external_rsc_urls[next_external_rsc]
#endif
@@ -199,9 +199,7 @@ GLOBAL_LIST(external_rsc_urls)
prefs.parent = src
prefs.last_ip = address //these are gonna be used for banning
prefs.last_id = computer_id //these are gonna be used for banning
if(world.byond_version >= 511 && byond_version >= 511 && prefs.clientfps)
vars["fps"] = prefs.clientfps
sethotkeys(1) //set hoykeys from preferences (from_pref = 1)
fps = prefs.clientfps
log_access("Login: [key_name(src)] from [address ? address : "localhost"]-[computer_id] || BYOND v[byond_version]")
var/alert_mob_dupe_login = FALSE
@@ -227,6 +225,13 @@ GLOBAL_LIST(external_rsc_urls)
message_admins("<font color='red'><B>Notice: </B><font color='blue'>[key_name_admin(src)] has the same [matches] as [key_name_admin(C)] (no longer logged in). </font>")
log_access("Notice: [key_name(src)] has the same [matches] as [key_name(C)] (no longer logged in).")
if(GLOB.player_details[ckey])
player_details = GLOB.player_details[ckey]
else
player_details = new
GLOB.player_details[ckey] = player_details
. = ..() //calls mob.Login()
chatOutput.start() // Starts the chat
@@ -673,6 +678,13 @@ GLOBAL_LIST(external_rsc_urls)
return TRUE
. = ..()
/client/proc/rescale_view(change, min, max)
var/viewscale = getviewsize(view)
var/x = viewscale[1]
var/y = viewscale[2]
x = CLAMP(x+change, min, max)
y = CLAMP(y+change, min,max)
change_view("[x]x[y]")
/client/proc/change_view(new_size)
if (isnull(new_size))
+2
View File
@@ -0,0 +1,2 @@
/datum/player_details
var/list/player_actions = list()
+4 -10
View File
@@ -1282,16 +1282,10 @@ GLOBAL_LIST_EMPTY(preferences_datums)
preferred_map = maplist[pickedmap]
if ("clientfps")
var/version_message
if (user.client && user.client.byond_version < 511)
version_message = "\nYou need to be using byond version 511 or later to take advantage of this feature, your version of [user.client.byond_version] is too low"
if (world.byond_version < 511)
version_message += "\nThis server does not currently support client side fps. You can set now for when it does."
var/desiredfps = input(user, "Choose your desired fps.[version_message]\n(0 = synced with server tick rate (currently:[world.fps]))", "Character Preference", clientfps) as null|num
var/desiredfps = input(user, "Choose your desired fps. (0 = synced with server tick rate (currently:[world.fps]))", "Character Preference", clientfps) as null|num
if (!isnull(desiredfps))
clientfps = desiredfps
if (world.byond_version >= 511 && user.client && user.client.byond_version >= 511)
user.client.vars["fps"] = clientfps
parent.fps = desiredfps
if("ui")
var/pickedui = input(user, "Choose your UI style.", "Character Preference") as null|anything in list("Midnight", "Plasmafire", "Retro", "Slimecore", "Operative", "Clockwork")
if(pickedui)
@@ -1596,12 +1590,12 @@ GLOBAL_LIST_EMPTY(preferences_datums)
toggles ^= MIDROUND_ANTAG
if("parallaxup")
parallax = Wrap(parallax + 1, PARALLAX_INSANE, PARALLAX_DISABLE + 1)
parallax = WRAP(parallax + 1, PARALLAX_INSANE, PARALLAX_DISABLE + 1)
if (parent && parent.mob && parent.mob.hud_used)
parent.mob.hud_used.update_parallax_pref(parent.mob)
if("parallaxdown")
parallax = Wrap(parallax - 1, PARALLAX_INSANE, PARALLAX_DISABLE + 1)
parallax = WRAP(parallax - 1, PARALLAX_INSANE, PARALLAX_DISABLE + 1)
if (parent && parent.mob && parent.mob.hud_used)
parent.mob.hud_used.update_parallax_pref(parent.mob)
+1 -1
View File
@@ -41,7 +41,7 @@
/obj/item/clothing/glasses/proc/thermal_overload()
if(ishuman(src.loc))
var/mob/living/carbon/human/H = src.loc
if(!(H.disabilities & BLIND))
if(!(H.has_disability(BLIND)))
if(H.glasses == src)
to_chat(H, "<span class='danger'>[src] overloads and blinds you!</span>")
H.flash_act(visual = 1)
+10 -10
View File
@@ -164,7 +164,7 @@
assembled = TRUE
boost_chargerate *= cap
boost_drain -= manip
powersetting_high = Clamp(laser, 0, 3)
powersetting_high = CLAMP(laser, 0, 3)
emp_disable_threshold = bin*1.25
stabilizer_decay_amount = scan*3.5
airbrake_decay_amount = manip*8
@@ -194,15 +194,15 @@
/obj/item/device/flightpack/proc/adjust_momentum(amountx, amounty, reduce_amount_total = 0)
if(reduce_amount_total != 0)
if(momentum_x > 0)
momentum_x = Clamp(momentum_x - reduce_amount_total, 0, momentum_max)
momentum_x = CLAMP(momentum_x - reduce_amount_total, 0, momentum_max)
else if(momentum_x < 0)
momentum_x = Clamp(momentum_x + reduce_amount_total, -momentum_max, 0)
momentum_x = CLAMP(momentum_x + reduce_amount_total, -momentum_max, 0)
if(momentum_y > 0)
momentum_y = Clamp(momentum_y - reduce_amount_total, 0, momentum_max)
momentum_y = CLAMP(momentum_y - reduce_amount_total, 0, momentum_max)
else if(momentum_y < 0)
momentum_y = Clamp(momentum_y + reduce_amount_total, -momentum_max, 0)
momentum_x = Clamp(momentum_x + amountx, -momentum_max, momentum_max)
momentum_y = Clamp(momentum_y + amounty, -momentum_max, momentum_max)
momentum_y = CLAMP(momentum_y + reduce_amount_total, -momentum_max, 0)
momentum_x = CLAMP(momentum_x + amountx, -momentum_max, momentum_max)
momentum_y = CLAMP(momentum_y + amounty, -momentum_max, momentum_max)
calculate_momentum_speed()
/obj/item/device/flightpack/intercept_user_move(dir, mob, newLoc, oldLoc)
@@ -314,7 +314,7 @@
/obj/item/device/flightpack/proc/handle_damage()
if(emp_damage)
emp_damage = Clamp(emp_damage-emp_heal_amount, 0, emp_disable_threshold * 10)
emp_damage = CLAMP(emp_damage-emp_heal_amount, 0, emp_disable_threshold * 10)
if(emp_damage >= emp_disable_threshold)
emp_disabled = TRUE
if(emp_disabled && (emp_damage <= 0.5))
@@ -347,11 +347,11 @@
/obj/item/device/flightpack/proc/handle_boost()
if(boost)
boost_charge = Clamp(boost_charge-boost_drain, 0, boost_maxcharge)
boost_charge = CLAMP(boost_charge-boost_drain, 0, boost_maxcharge)
if(boost_charge < 1)
deactivate_booster()
if(boost_charge < boost_maxcharge)
boost_charge = Clamp(boost_charge+boost_chargerate, 0, boost_maxcharge)
boost_charge = CLAMP(boost_charge+boost_chargerate, 0, boost_maxcharge)
/obj/item/device/flightpack/proc/cycle_power()
powersetting < powersetting_high? (powersetting++) : (powersetting = 1)
+1 -1
View File
@@ -654,7 +654,7 @@
/obj/item/clothing/suit/space/hardsuit/shielded/process()
if(world.time > recharge_cooldown && current_charges < max_charges)
current_charges = Clamp((current_charges + recharge_rate), 0, max_charges)
current_charges = CLAMP((current_charges + recharge_rate), 0, max_charges)
playsound(loc, 'sound/magic/charge.ogg', 50, 1)
if(current_charges == max_charges)
playsound(loc, 'sound/machines/ding.ogg', 50, 1)
+49 -48
View File
@@ -1,48 +1,49 @@
/obj/item/clothing/suit/toggle/labcoat
name = "labcoat"
desc = "A suit that protects against minor chemical spills."
icon_state = "labcoat"
item_state = "labcoat"
blood_overlay_type = "coat"
body_parts_covered = CHEST|ARMS
allowed = list(/obj/item/device/analyzer, /obj/item/stack/medical, /obj/item/dnainjector, /obj/item/reagent_containers/dropper, /obj/item/reagent_containers/syringe, /obj/item/reagent_containers/hypospray, /obj/item/device/healthanalyzer, /obj/item/device/flashlight/pen, /obj/item/reagent_containers/glass/bottle, /obj/item/reagent_containers/glass/beaker, /obj/item/reagent_containers/pill, /obj/item/storage/pill_bottle, /obj/item/paper, /obj/item/melee/classic_baton/telescopic, /obj/item/soap, /obj/item/device/sensor_device, /obj/item/tank/internals/emergency_oxygen)
armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 50, rad = 0, fire = 50, acid = 50)
togglename = "buttons"
/obj/item/clothing/suit/toggle/labcoat/cmo
name = "chief medical officer's labcoat"
desc = "Bluer than the standard model."
icon_state = "labcoat_cmo"
item_state = "labcoat_cmo"
/obj/item/clothing/suit/toggle/labcoat/emt
name = "EMT's jacket"
desc = "A dark blue jacket with reflective strips for emergency medical technicians."
icon_state = "labcoat_emt"
item_state = "labcoat_cmo"
/obj/item/clothing/suit/toggle/labcoat/mad
name = "\improper The Mad's labcoat"
desc = "It makes you look capable of konking someone on the noggin and shooting them into space."
icon_state = "labgreen"
item_state = "labgreen"
/obj/item/clothing/suit/toggle/labcoat/genetics
name = "geneticist labcoat"
desc = "A suit that protects against minor chemical spills. Has a blue stripe on the shoulder."
icon_state = "labcoat_gen"
/obj/item/clothing/suit/toggle/labcoat/chemist
name = "chemist labcoat"
desc = "A suit that protects against minor chemical spills. Has an orange stripe on the shoulder."
icon_state = "labcoat_chem"
/obj/item/clothing/suit/toggle/labcoat/virologist
name = "virologist labcoat"
desc = "A suit that protects against minor chemical spills. Offers slightly more protection against biohazards than the standard model. Has a green stripe on the shoulder."
icon_state = "labcoat_vir"
/obj/item/clothing/suit/toggle/labcoat/science
name = "scientist labcoat"
desc = "A suit that protects against minor chemical spills. Has a purple stripe on the shoulder."
icon_state = "labcoat_tox"
/obj/item/clothing/suit/toggle/labcoat
name = "labcoat"
desc = "A suit that protects against minor chemical spills."
icon_state = "labcoat"
item_state = "labcoat"
blood_overlay_type = "coat"
body_parts_covered = CHEST|ARMS
allowed = list(/obj/item/device/analyzer, /obj/item/stack/medical, /obj/item/dnainjector, /obj/item/reagent_containers/dropper, /obj/item/reagent_containers/syringe, /obj/item/reagent_containers/hypospray, /obj/item/device/healthanalyzer, /obj/item/device/flashlight/pen, /obj/item/reagent_containers/glass/bottle, /obj/item/reagent_containers/glass/beaker, /obj/item/reagent_containers/pill, /obj/item/storage/pill_bottle, /obj/item/paper, /obj/item/melee/classic_baton/telescopic, /obj/item/soap, /obj/item/device/sensor_device, /obj/item/tank/internals/emergency_oxygen, /obj/item/tank/internals/plasmaman)
armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 50, rad = 0, fire = 50, acid = 50)
togglename = "buttons"
species_exception = list(/datum/species/golem)
/obj/item/clothing/suit/toggle/labcoat/cmo
name = "chief medical officer's labcoat"
desc = "Bluer than the standard model."
icon_state = "labcoat_cmo"
item_state = "labcoat_cmo"
/obj/item/clothing/suit/toggle/labcoat/emt
name = "EMT's jacket"
desc = "A dark blue jacket with reflective strips for emergency medical technicians."
icon_state = "labcoat_emt"
item_state = "labcoat_cmo"
/obj/item/clothing/suit/toggle/labcoat/mad
name = "\improper The Mad's labcoat"
desc = "It makes you look capable of konking someone on the noggin and shooting them into space."
icon_state = "labgreen"
item_state = "labgreen"
/obj/item/clothing/suit/toggle/labcoat/genetics
name = "geneticist labcoat"
desc = "A suit that protects against minor chemical spills. Has a blue stripe on the shoulder."
icon_state = "labcoat_gen"
/obj/item/clothing/suit/toggle/labcoat/chemist
name = "chemist labcoat"
desc = "A suit that protects against minor chemical spills. Has an orange stripe on the shoulder."
icon_state = "labcoat_chem"
/obj/item/clothing/suit/toggle/labcoat/virologist
name = "virologist labcoat"
desc = "A suit that protects against minor chemical spills. Offers slightly more protection against biohazards than the standard model. Has a green stripe on the shoulder."
icon_state = "labcoat_vir"
/obj/item/clothing/suit/toggle/labcoat/science
name = "scientist labcoat"
desc = "A suit that protects against minor chemical spills. Has a purple stripe on the shoulder."
icon_state = "labcoat_tox"
+1 -1
View File
@@ -135,7 +135,7 @@
"<span class='notice'>You pin \the [src] on [M]'s chest.</span>")
if(input)
SSblackbox.record_feedback("associative", "commendation", 1, list("commender" = "[user.real_name]", "commendee" = "[M.real_name]", "medal" = "[src]", "reason" = input))
GLOB.commendations += "[user.real_name] awarded <b>[M.real_name]</b> the <font color='blue'>[name]</font>! \n- [input]"
GLOB.commendations += "[user.real_name] awarded <b>[M.real_name]</b> the <span class='medaltext'>[name]</span>! \n- [input]"
commended = TRUE
log_game("<b>[key_name(M)]</b> was given the following commendation by <b>[key_name(user)]</b>: [input]")
message_admins("<b>[key_name(M)]</b> was given the following commendation by <b>[key_name(user)]</b>: [input]")
+1 -1
View File
@@ -98,7 +98,7 @@
else
if(istype(I, /obj/item/reagent_containers))
var/obj/item/reagent_containers/RC = I
if(RC.container_type & OPENCONTAINER_1)
if(RC.is_drainable())
for(var/datum/reagent/A in RC.reagents.reagent_list)
.[A.type] += A.volume
.[I.type] += 1
@@ -13,7 +13,7 @@
icon = 'icons/obj/toy.dmi'
icon_state = "rag"
flags_1 = NOBLUDGEON_1
container_type = OPENCONTAINER_1
container_type = OPENCONTAINER
amount_per_transfer_from_this = 5
possible_transfer_amounts = list()
volume = 5
+2 -2
View File
@@ -29,8 +29,8 @@
/datum/round_event_control/New()
if(config && !wizardevent) // Magic is unaffected by configs
earliest_start = Ceiling(earliest_start * CONFIG_GET(number/events_min_time_mul))
min_players = Ceiling(min_players * CONFIG_GET(number/events_min_players_mul))
earliest_start = CEILING(earliest_start * CONFIG_GET(number/events_min_time_mul), 1)
min_players = CEILING(min_players * CONFIG_GET(number/events_min_players_mul), 1)
/datum/round_event_control/wizard
wizardevent = 1
+2 -2
View File
@@ -67,12 +67,12 @@
kill()
return
if(IsMultiple(activeFor, 4))
if(ISMULTIPLE(activeFor, 4))
var/obj/machinery/vending/rebel = pick(vendingMachines)
vendingMachines.Remove(rebel)
infectedMachines.Add(rebel)
rebel.shut_up = 0
rebel.shoot_inventory = 1
if(IsMultiple(activeFor, 8))
if(ISMULTIPLE(activeFor, 8))
originMachine.speak(pick(rampant_speeches))
+51 -11
View File
@@ -10,6 +10,8 @@
var/virus_type
var/max_severity = 3
/datum/round_event/disease_outbreak/announce(fake)
priority_announce("Confirmed outbreak of level 7 viral biohazard aboard [station_name()]. All personnel must contain the outbreak.", "Biohazard Alert", 'sound/ai/outbreak7.ogg')
@@ -17,8 +19,14 @@
/datum/round_event/disease_outbreak/setup()
announceWhen = rand(15, 30)
/datum/round_event/disease_outbreak/start()
if(!virus_type)
var/advanced_virus = FALSE
max_severity = 3 + max(FLOOR((world.time - control.earliest_start)/6000, 1),0) //3 symptoms at 20 minutes, plus 1 per 10 minutes
if(prob(20 + (10 * max_severity)))
advanced_virus = TRUE
if(!virus_type && !advanced_virus)
virus_type = pick(/datum/disease/dnaspread, /datum/disease/advance/flu, /datum/disease/advance/cold, /datum/disease/brainrot, /datum/disease/magnitis)
for(var/mob/living/carbon/human/H in shuffle(GLOB.alive_mob_list))
@@ -41,16 +49,48 @@
continue
var/datum/disease/D
if(virus_type == /datum/disease/dnaspread) //Dnaspread needs strain_data set to work.
if(!H.dna || (H.disabilities & BLIND)) //A blindness disease would be the worst.
continue
D = new virus_type()
var/datum/disease/dnaspread/DS = D
DS.strain_data["name"] = H.real_name
DS.strain_data["UI"] = H.dna.uni_identity
DS.strain_data["SE"] = H.dna.struc_enzymes
if(!advanced_virus)
if(virus_type == /datum/disease/dnaspread) //Dnaspread needs strain_data set to work.
if(!H.dna || (H.has_disability(BLIND))) //A blindness disease would be the worst.
continue
D = new virus_type()
var/datum/disease/dnaspread/DS = D
DS.strain_data["name"] = H.real_name
DS.strain_data["UI"] = H.dna.uni_identity
DS.strain_data["SE"] = H.dna.struc_enzymes
else
D = new virus_type()
else
D = new virus_type()
D = make_virus(max_severity, max_severity)
D.carrier = TRUE
H.AddDisease(D)
break
if(advanced_virus)
var/datum/disease/advance/A = D
var/list/name_symptoms = list() //for feedback
for(var/datum/symptom/S in A.symptoms)
name_symptoms += S.name
message_admins("An event has triggered a random advanced virus outbreak on [key_name_admin(H)]! It has these symptoms: [english_list(name_symptoms)]")
log_game("An event has triggered a random advanced virus outbreak on [key_name(H)]! It has these symptoms: [english_list(name_symptoms)]")
break
/datum/round_event/disease_outbreak/proc/make_virus(max_symptoms, max_level)
if(max_symptoms > SYMPTOM_LIMIT)
max_symptoms = SYMPTOM_LIMIT
var/datum/disease/advance/A = new(FALSE, null)
A.symptoms = list()
var/list/datum/symptom/possible_symptoms = list()
for(var/symptom in subtypesof(/datum/symptom))
var/datum/symptom/S = symptom
if(initial(S.level) > max_level)
continue
if(initial(S.level) <= 0) //unobtainable symptoms
continue
possible_symptoms += S
for(var/i in 1 to max_symptoms)
var/datum/symptom/chosen_symptom = pick_n_take(possible_symptoms)
if(chosen_symptom)
var/datum/symptom/S = new chosen_symptom
A.symptoms += S
A.Refresh() //just in case someone already made and named the same disease
return A
+7
View File
@@ -45,19 +45,26 @@
to_chat(L, "<span class='warning'><B>You didn't get a date! They're all having fun without you! you'll show them though...</B></span>")
var/datum/objective/martyr/normiesgetout = new
normiesgetout.owner = L.mind
L.mind.special_role = "heartbreaker"
SSticker.mode.traitors |= L.mind
L.mind.objectives += normiesgetout
L.mind.add_antag_datum(/datum/antagonist/auto_custom)
/proc/forge_valentines_objective(mob/living/lover,mob/living/date)
SSticker.mode.traitors |= lover.mind
lover.mind.special_role = "valentine"
var/datum/objective/protect/protect_objective = new /datum/objective/protect
protect_objective.owner = lover.mind
protect_objective.target = date.mind
protect_objective.explanation_text = "Protect [date.real_name], your date."
lover.mind.objectives += protect_objective
lover.mind.add_antag_datum(/datum/antagonist/auto_custom)
to_chat(lover, "<span class='warning'><B>You're on a date with [date]! Protect them at all costs. This takes priority over all other loyalties.</B></span>")
+4 -21
View File
@@ -1,19 +1,3 @@
/datum/round_event_control/treevenge
name = "Treevenge (Christmas)"
holidayID = CHRISTMAS
typepath = /datum/round_event/treevenge
max_occurrences = 1
weight = 20
/datum/round_event/treevenge/start()
for(var/obj/structure/flora/tree/pine/xmas in world)
var/mob/living/simple_animal/hostile/tree/evil_tree = new /mob/living/simple_animal/hostile/tree(xmas.loc)
evil_tree.icon_state = xmas.icon_state
evil_tree.icon_living = evil_tree.icon_state
evil_tree.icon_dead = evil_tree.icon_state
evil_tree.icon_gib = evil_tree.icon_state
qdel(xmas) //b-but I don't want to delete xmas...
//this is an example of a possible round-start event
/datum/round_event_control/presents
name = "Presents under Trees (Christmas)"
@@ -24,12 +8,11 @@
earliest_start = 0
/datum/round_event/presents/start()
for(var/obj/structure/flora/tree/pine/xmas in world)
for(var/obj/structure/flora/tree/pine/xmas/xmas in world)
if(!(xmas.z in GLOB.station_z_levels))
continue
for(var/turf/open/floor/T in orange(1,xmas))
for(var/i=1,i<=rand(1,5),i++)
new /obj/item/a_gift(T)
xmas.icon_state = "pinepresents"
xmas.gifts_under_tree = TRUE
for(var/mob/living/simple_animal/pet/dog/corgi/Ian/Ian in GLOB.mob_living_list)
Ian.place_on_head(new /obj/item/clothing/head/helmet/space/santahat(Ian))
for(var/obj/machinery/computer/security/telescreen/entertainment/Monitor in GLOB.machines)
@@ -98,7 +81,7 @@
name = "Santa is coming to town! (Christmas)"
holidayID = CHRISTMAS
typepath = /datum/round_event/santa
weight = 150
weight = 20
max_occurrences = 1
earliest_start = 20000
+37 -4
View File
@@ -12,6 +12,16 @@ In my current plan for it, 'solid' will be defined as anything with density == 1
typepath = /datum/round_event/immovable_rod
min_players = 15
max_occurrences = 5
var/atom/special_target
/datum/round_event_control/immovable_rod/admin_setup()
if(!check_rights(R_FUN))
return
var/aimed = alert("Aimed at current location?","Sniperod", "Yes", "No")
if(aimed == "Yes")
special_target = get_turf(usr)
/datum/round_event/immovable_rod
announceWhen = 5
@@ -20,10 +30,11 @@ In my current plan for it, 'solid' will be defined as anything with density == 1
priority_announce("What the fuck was that?!", "General Alert")
/datum/round_event/immovable_rod/start()
var/datum/round_event_control/immovable_rod/C = control
var/startside = pick(GLOB.cardinals)
var/turf/startT = spaceDebrisStartLoc(startside, ZLEVEL_STATION_PRIMARY)
var/turf/endT = spaceDebrisFinishLoc(startside, ZLEVEL_STATION_PRIMARY)
new /obj/effect/immovablerod(startT, endT)
new /obj/effect/immovablerod(startT, endT, C.special_target)
/obj/effect/immovablerod
name = "immovable rod"
@@ -36,18 +47,28 @@ In my current plan for it, 'solid' will be defined as anything with density == 1
var/z_original = 0
var/destination
var/notify = TRUE
var/atom/special_target
/obj/effect/immovablerod/New(atom/start, atom/end)
/obj/effect/immovablerod/New(atom/start, atom/end, aimed_at)
..()
SSaugury.register_doom(src, 2000)
z_original = z
destination = end
special_target = aimed_at
if(notify)
notify_ghosts("\A [src] is inbound!",
enter_link="<a href=?src=[REF(src)];orbit=1>(Click to orbit)</a>",
source=src, action=NOTIFY_ORBIT)
GLOB.poi_list += src
if(end && end.z==z_original)
var/special_target_valid = FALSE
if(special_target)
var/turf/T = get_turf(special_target)
if(T.z == z_original)
special_target_valid = TRUE
if(special_target_valid)
walk_towards(src, special_target, 1)
else if(end && end.z==z_original)
walk_towards(src, destination, 1)
/obj/effect/immovablerod/Topic(href, href_list)
@@ -60,11 +81,20 @@ In my current plan for it, 'solid' will be defined as anything with density == 1
GLOB.poi_list -= src
. = ..()
/obj/effect/immovablerod/Move()
/obj/effect/immovablerod/Moved()
if((z != z_original) || (loc == destination))
qdel(src)
if(special_target && loc == get_turf(special_target))
complete_trajectory()
return ..()
/obj/effect/immovablerod/proc/complete_trajectory()
//We hit what we wanted to hit, time to go
special_target = null
destination = get_edge_target_turf(src, dir)
walk(src,0)
walk_towards(src, destination, 1)
/obj/effect/immovablerod/ex_act(severity, target)
return 0
@@ -83,6 +113,9 @@ In my current plan for it, 'solid' will be defined as anything with density == 1
x = clong.x
y = clong.y
if(special_target && clong == special_target)
complete_trajectory()
if(isturf(clong) || isobj(clong))
if(clong.density)
clong.ex_act(EXPLODE_HEAVY)
+1 -1
View File
@@ -49,7 +49,7 @@
priority_announce("Meteors have been detected on collision course with the station.", "Meteor Alert", 'sound/ai/meteors.ogg')
/datum/round_event/meteor_wave/tick()
if(IsMultiple(activeFor, 3))
if(ISMULTIPLE(activeFor, 3))
spawn_meteors(5, wave_type) //meteor list types defined in gamemode/meteor/meteors.dm
/datum/round_event_control/meteor_wave/threatening
+1
View File
@@ -35,6 +35,7 @@
player_mind.assigned_role = "Nightmare"
player_mind.special_role = "Nightmare"
SSticker.mode.traitors += player_mind
player_mind.add_antag_datum(/datum/antagonist/auto_custom)
S.set_species(/datum/species/shadow/nightmare)
playsound(S, 'sound/magic/ethereal_exit.ogg', 50, 1, -1)
message_admins("[key_name_admin(S)] has been made into a Nightmare by an event.")
+1 -19
View File
@@ -27,31 +27,13 @@
A.copy_to(operative)
operative.dna.update_dna_identity()
operative.equipOutfit(/datum/outfit/syndicate/full)
var/datum/mind/Mind = new /datum/mind(selected.key)
Mind.assigned_role = "Lone Operative"
Mind.special_role = "Lone Operative"
SSticker.mode.traitors |= Mind
Mind.active = 1
var/obj/machinery/nuclearbomb/selfdestruct/nuke = locate() in GLOB.machines
if(nuke)
var/nuke_code
if(!nuke.r_code || nuke.r_code == "ADMIN")
nuke_code = random_nukecode()
nuke.r_code = nuke_code
else
nuke_code = nuke.r_code
Mind.store_memory("<B>Station Self-Destruct Device Code</B>: [nuke_code]", 0, 0)
to_chat(Mind.current, "The nuclear authorization code is: <B>[nuke_code]</B>")
var/datum/objective/nuclear/O = new()
O.owner = Mind
Mind.objectives += O
Mind.transfer_to(operative)
Mind.add_antag_datum(/datum/antagonist/nukeop/lone)
message_admins("[key_name_admin(operative)] has been made into lone operative by an event.")
log_game("[key_name(operative)] was spawned as a lone operative by an event.")
+3 -3
View File
@@ -64,7 +64,7 @@
T = safepick(get_area_turfs(pick(station_areas)))
hostiles_spawn += T
next_boss_spawn = startWhen + Ceiling(2 * number_of_hostiles / number_of_bosses)
next_boss_spawn = startWhen + CEILING(2 * number_of_hostiles / number_of_bosses, 1)
/datum/round_event/portal_storm/announce(fake)
set waitfor = 0
@@ -117,14 +117,14 @@
/datum/round_event/portal_storm/proc/spawn_hostile()
if(!hostile_types || !hostile_types.len)
return 0
return IsMultiple(activeFor, 2)
return ISMULTIPLE(activeFor, 2)
/datum/round_event/portal_storm/proc/spawn_boss()
if(!boss_types || !boss_types.len)
return 0
if(activeFor == next_boss_spawn)
next_boss_spawn += Ceiling(number_of_hostiles / number_of_bosses)
next_boss_spawn += CEILING(number_of_hostiles / number_of_bosses, 1)
return 1
/datum/round_event/portal_storm/proc/time_to_end()
@@ -44,6 +44,7 @@
citizens += H
SSticker.mode.traitors += M
M.special_role = "separatist"
M.add_antag_datum(/datum/antagonist/auto_custom)
H.log_message("<font color='red'>Was made into a separatist, long live [nation]!</font>", INDIVIDUAL_ATTACK_LOG)
to_chat(H, "<B>You are a separatist! [nation] forever! Protect the sovereignty of your newfound land with your comrades in arms!</B>")
if(citizens.len)
+1
View File
@@ -67,6 +67,7 @@
O.completed = 1 //YES!
O.owner = new_holder.mind
new_holder.mind.objectives += O
new_holder.mind.add_antag_datum(/datum/antagonist/auto_custom)
new_holder.log_message("<font color='green'>Won with greentext!!!</font>", INDIVIDUAL_ATTACK_LOG)
color_altered_mobs -= new_holder
resistance_flags |= ON_FIRE
+1
View File
@@ -80,6 +80,7 @@ GLOBAL_LIST_INIT(hallucinations_major, list(
/obj/effect/hallucination
invisibility = INVISIBILITY_OBSERVER
anchored = TRUE
var/mob/living/carbon/target = null
/obj/effect/hallucination/simple
+31 -30
View File
@@ -8,7 +8,7 @@
icon_state = null
lefthand_file = 'icons/mob/inhands/misc/food_lefthand.dmi'
righthand_file = 'icons/mob/inhands/misc/food_righthand.dmi'
container_type = OPENCONTAINER_1
container_type = OPENCONTAINER
var/gulp_size = 5 //This is now officially broken ... need to think of a nice way to fix it.
possible_transfer_amounts = list(5,10,15,20,25,30,50)
volume = 50
@@ -30,7 +30,7 @@
if(!canconsume(M, user))
return 0
if (!is_open_container())
if (!is_drainable())
to_chat(user, "<span class='warning'>[src]'s lid hasn't been opened!</span>")
return 0
@@ -44,7 +44,7 @@
if(!reagents || !reagents.total_volume)
return // The drink might be empty after the delay, such as by spam-feeding
M.visible_message("<span class='danger'>[user] feeds the contents of [src] to [M].</span>", "<span class='userdanger'>[user] feeds the contents of [src] to [M].</span>")
add_logs(user, M, "fed", reagentlist(src))
add_logs(user, M, "fed", reagents.log_list())
var/fraction = min(gulp_size/reagents.total_volume, 1)
checkLiked(fraction, M)
@@ -56,31 +56,16 @@
/obj/item/reagent_containers/food/drinks/afterattack(obj/target, mob/user , proximity)
if(!proximity)
return
if(istype(target, /obj/structure/reagent_dispensers)) //A dispenser. Transfer FROM it TO us.
if (!is_open_container())
to_chat(user, "<span class='warning'>[target]'s tab isn't open!</span>")
return
if(!target.reagents.total_volume)
to_chat(user, "<span class='warning'>[target] is empty.</span>")
return
if(reagents.total_volume >= reagents.maximum_volume)
to_chat(user, "<span class='warning'>[src] is full.</span>")
return
var/trans = target.reagents.trans_to(src, amount_per_transfer_from_this)
to_chat(user, "<span class='notice'>You fill [src] with [trans] units of the contents of [target].</span>")
else if(target.is_open_container()) //Something like a glass. Player probably wants to transfer TO it.
if(target.is_refillable()) //Something like a glass. Player probably wants to transfer TO it.
if(!reagents.total_volume)
to_chat(user, "<span class='warning'>[src] is empty.</span>")
return
if(target.reagents.total_volume >= target.reagents.maximum_volume)
if(target.reagents.holder_full())
to_chat(user, "<span class='warning'>[target] is full.</span>")
return
var/refill = reagents.get_master_reagent_id()
var/trans = src.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>")
@@ -90,13 +75,29 @@
bro.cell.use(30)
addtimer(CALLBACK(reagents, /datum/reagents.proc/add_reagent, refill, trans), 600)
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>")
return
if(!target.reagents.total_volume)
to_chat(user, "<span class='warning'>[target] is empty.</span>")
return
if(reagents.holder_full())
to_chat(user, "<span class='warning'>[src] is full.</span>")
return
var/trans = target.reagents.trans_to(src, amount_per_transfer_from_this)
to_chat(user, "<span class='notice'>You fill [src] with [trans] units of the contents of [target].</span>")
else
/obj/item/reagent_containers/food/drinks/attackby(obj/item/I, mob/user, params)
if(I.is_hot())
var/added_heat = (I.is_hot() / 100) //ishot returns a temperature
if(reagents)
reagents.chem_temp += added_heat
to_chat(user, "<span class='notice'>You heat [src] with [I].</span>")
reagents.handle_reactions()
var/hotness = I.is_hot()
if(hotness && reagents)
reagents.expose_temperature(hotness)
to_chat(user, "<span class='notice'>You heat [name] with [I]!</span>")
..()
/obj/item/reagent_containers/food/drinks/throw_impact(atom/target, mob/thrower)
@@ -142,7 +143,7 @@
possible_transfer_amounts = list()
volume = 5
flags_1 = CONDUCT_1
container_type = OPENCONTAINER_1
container_type = OPENCONTAINER
spillable = TRUE
resistance_flags = FIRE_PROOF
isGlass = FALSE
@@ -406,9 +407,9 @@
/obj/item/reagent_containers/food/drinks/soda_cans/attack_self(mob/user)
if(!is_open_container())
if(!is_drainable())
to_chat(user, "You pull back the tab of \the [src] with a satisfying pop.") //Ahhhhhhhh
container_type = OPENCONTAINER_1
container_type = OPENCONTAINER
playsound(src, "can_open", 50, 1)
spillable = TRUE
return
+1 -1
View File
@@ -4,7 +4,7 @@
/obj/item/reagent_containers/food
possible_transfer_amounts = list()
volume = 50 //Sets the default container amount for all food items.
container_type = INJECTABLE_1
container_type = INJECTABLE
resistance_flags = FLAMMABLE
var/foodtype = NONE
var/last_check_time
@@ -10,7 +10,7 @@
desc = "Just your average condiment container."
icon = 'icons/obj/food/containers.dmi'
icon_state = "emptycondiment"
container_type = OPENCONTAINER_1
container_type = OPENCONTAINER
possible_transfer_amounts = list(1, 5, 10, 15, 20, 25, 30, 50)
volume = 50
//Possible_states has the reagent id as key and a list of, in order, the icon_state, the name and the desc as values. Used in the on_reagent_change(changetype) to change names, descs and sprites.
@@ -45,7 +45,7 @@
if(!reagents || !reagents.total_volume)
return // The condiment might be empty after the delay.
user.visible_message("<span class='warning'>[user] feeds [M] from [src].</span>")
add_logs(user, M, "fed", reagentlist(src))
add_logs(user, M, "fed", reagents.log_list())
var/fraction = min(10/reagents.total_volume, 1)
reagents.reaction(M, INGEST, fraction)
@@ -70,7 +70,7 @@
to_chat(user, "<span class='notice'>You fill [src] with [trans] units of the contents of [target].</span>")
//Something like a glass or a food item. Player probably wants to transfer TO it.
else if(target.is_open_container() || istype(target, /obj/item/reagent_containers/food/snacks))
else if(target.is_drainable() || istype(target, /obj/item/reagent_containers/food/snacks))
if(!reagents.total_volume)
to_chat(user, "<span class='warning'>[src] is empty!</span>")
return
@@ -291,7 +291,7 @@
desc = "A simple bowl, used for soups and salads."
icon = 'icons/obj/food/soupsalad.dmi'
icon_state = "bowl"
container_type = OPENCONTAINER_1
container_type = OPENCONTAINER
materials = list(MAT_GLASS = 500)
w_class = WEIGHT_CLASS_NORMAL
+1 -1
View File
@@ -94,7 +94,7 @@
if(!do_mob(user, M))
return
add_logs(user, M, "fed", reagentlist(src))
add_logs(user, M, "fed", reagents.log_list())
M.visible_message("<span class='danger'>[user] forces [M] to eat [src].</span>", \
"<span class='userdanger'>[user] forces [M] to eat [src].</span>")
@@ -27,6 +27,7 @@
list_reagents = list("nutriment" = 6, "banana" = 5, "vitamin" = 2)
tastes = list("pie" = 1)
foodtype = GRAIN | DAIRY | SUGAR
var/stunning = TRUE
/obj/item/reagent_containers/food/snacks/pie/cream/throw_impact(atom/hit_atom)
. = ..()
@@ -46,15 +47,18 @@
creamoverlay.icon_state = "creampie_lizard"
else
creamoverlay.icon_state = "creampie_human"
H.Knockdown(20) //splat!
if(stunning)
H.Knockdown(20) //splat!
H.adjust_blurriness(1)
H.visible_message("<span class='warning'>[H] is creamed by [src]!</span>", "<span class='userdanger'>You've been creamed by [src]!</span>")
playsound(H, "desceration", 50, TRUE)
if (!H.creamed) // one layer at a time
if(!H.creamed) // one layer at a time
H.add_overlay(creamoverlay)
H.creamed = TRUE
qdel(src)
/obj/item/reagent_containers/food/snacks/pie/cream/nostun
stunning = FALSE
/obj/item/reagent_containers/food/snacks/pie/berryclafoutis
name = "berry clafoutis"
@@ -29,7 +29,7 @@ God bless America.
anchored = TRUE
use_power = IDLE_POWER_USE
idle_power_usage = 5
container_type = OPENCONTAINER_1
container_type = OPENCONTAINER
var/obj/item/reagent_containers/food/snacks/deepfryholder/frying //What's being fried RIGHT NOW?
var/cook_time = 0
var/oil_use = 0.05 //How much cooking oil is used per tick
@@ -15,7 +15,7 @@
var/portion = 10
var/selected_drink
var/list/stored_food = list()
container_type = OPENCONTAINER_1
container_type = OPENCONTAINER
var/obj/item/reagent_containers/mixer
/obj/machinery/food_cart/Initialize()
@@ -100,7 +100,7 @@
stored_food[sanitize(S.name)]++
else
stored_food[sanitize(S.name)] = 1
else if(O.is_open_container())
else if(O.is_drainable())
return
else
. = ..()
@@ -123,7 +123,7 @@
break
if(href_list["portion"])
portion = Clamp(input("How much drink do you want to dispense per glass?") as num, 0, 50)
portion = CLAMP(input("How much drink do you want to dispense per glass?") as num, 0, 50)
if(href_list["pour"] || href_list["m_pour"])
if(glasses-- <= 0)
@@ -1,4 +1,3 @@
/obj/machinery/gibber
name = "gibber"
desc = "The name isn't descriptive enough?"
@@ -12,10 +11,10 @@
circuit = /obj/item/circuitboard/machine/gibber
var/operating = FALSE //Is it on?
var/dirty = 0 // Does it need cleaning?
var/dirty = FALSE // Does it need cleaning?
var/gibtime = 40 // Time from starting until meat appears
var/meat_produced = 0
var/ignore_clothing = 0
var/ignore_clothing = FALSE
/obj/machinery/gibber/Initialize()
@@ -30,7 +29,7 @@
gib_time -= 5 * M.rating
gibtime = gib_time
if(M.rating >= 2)
ignore_clothing = 1
ignore_clothing = TRUE
/obj/machinery/gibber/update_icon()
cut_overlays()
@@ -61,6 +60,10 @@
to_chat(user, "<span class='danger'>It's locked and running.</span>")
return
if(!anchored)
to_chat(user, "<span class='notice'>[src] cannot be used unless bolted to the ground.</span>")
return
if(user.pulling && user.a_intent == INTENT_GRAB && isliving(user.pulling))
var/mob/living/L = user.pulling
if(!iscarbon(L))
@@ -70,12 +73,17 @@
if(C.buckled ||C.has_buckled_mobs())
to_chat(user, "<span class='warning'>[C] is attached to something!</span>")
return
if(C.abiotic(1) && !ignore_clothing)
to_chat(user, "<span class='danger'>Subject may not have abiotic items on.</span>")
return
if(!ignore_clothing)
for(var/obj/item/I in C.held_items + C.get_equipped_items())
if(!(I.flags_1 & NODROP_1))
to_chat(user, "<span class='danger'>Subject may not have abiotic items on.</span>")
return
user.visible_message("<span class='danger'>[user] starts to put [C] into the gibber!</span>")
src.add_fingerprint(user)
add_fingerprint(user)
if(do_after(user, gibtime, target = src))
if(C && user.pulling == C && !C.buckled && !C.has_buckled_mobs() && !occupant)
user.visible_message("<span class='danger'>[user] stuffs [C] into the gibber!</span>")
@@ -14,7 +14,7 @@
anchored = FALSE
use_power = NO_POWER_USE
layer = BELOW_OBJ_LAYER
container_type = OPENCONTAINER_1
container_type = OPENCONTAINER
max_integrity = 300
var/list/product_types = list()
var/dispense_flavour = ICECREAM_VANILLA
@@ -112,7 +112,7 @@
else
to_chat(user, "<span class='notice'>[O] already has ice cream in it.</span>")
return 1
else if(O.is_open_container())
else if(O.is_drainable())
return
else
return ..()
@@ -81,7 +81,7 @@
src.icon_state = "mw"
src.broken = 0 // Fix it!
src.dirty = 0 // just to be sure
src.container_type = OPENCONTAINER_1
src.container_type = OPENCONTAINER
return 0 //to use some fuel
else
to_chat(user, "<span class='warning'>It's broken!</span>")
@@ -98,7 +98,7 @@
src.dirty = 0 // It's clean!
src.broken = 0 // just to be sure
src.icon_state = "mw"
src.container_type = OPENCONTAINER_1
src.container_type = OPENCONTAINER
src.updateUsrDialog()
return 1 // Disables the after-attack so we don't spray the floor/user.
else
@@ -119,7 +119,7 @@
src.dirty = 0 // It's clean!
src.broken = 0 // just to be sure
src.icon_state = "mw"
src.container_type = OPENCONTAINER_1
src.container_type = OPENCONTAINER
else if(src.dirty==100) // The microwave is all dirty so can't be used!
to_chat(user, "<span class='warning'>It's dirty!</span>")
+1 -1
View File
@@ -124,7 +124,7 @@
return
else
bomb_timer = input(user, "Set the [bomb] timer from [BOMB_TIMER_MIN] to [BOMB_TIMER_MAX].", bomb, bomb_timer) as num
bomb_timer = Clamp(Ceiling(bomb_timer / 2), BOMB_TIMER_MIN, BOMB_TIMER_MAX)
bomb_timer = CLAMP(CEILING(bomb_timer / 2, 1), BOMB_TIMER_MIN, BOMB_TIMER_MAX)
bomb_defused = FALSE
var/message = "[ADMIN_LOOKUPFLW(user)] has trapped a [src] with [bomb] set to [bomb_timer * 2] seconds."
+1 -1
View File
@@ -132,7 +132,7 @@ GLOBAL_DATUM_INIT(iconCache, /savefile, new("data/iconCache.sav")) //Cache of ic
/datum/chatOutput/proc/setMusicVolume(volume = "")
if(volume)
adminMusicVolume = Clamp(text2num(volume), 0, 100)
adminMusicVolume = CLAMP(text2num(volume), 0, 100)
//Sends client connection details to the chat to handle and save
/datum/chatOutput/proc/sendClientData()
@@ -13,7 +13,7 @@ body {
background: #fff;
font-family: Verdana, sans-serif;
font-size: 9pt;
line-height: 1.4;
line-height: 1.2;
overflow-x: hidden;
overflow-y: scroll;
word-wrap: break-word;
@@ -399,6 +399,9 @@ h1.alert, h2.alert {color: #000000;}
.love {color: #FF69Bf;}
.lovebold {color: #FF69Bf; font-weight: bold;}
.monkeyhive {color: #774704;}
.monkeylead {color: #774704; font-size: 2;}
.connectionClosed, .fatalError {background: red; color: white; padding: 5px;}
.connectionClosed.restored {background: green;}
@@ -36,6 +36,8 @@
<div class="sub" id="subOptions">
<a href="#" class="subCell decreaseFont topCell" id="decreaseFont"><span>Decrease font size</span> <i class="icon-font">-</i></a>
<a href="#" class="subCell increaseFont" id="increaseFont"><span>Increase font size</span> <i class="icon-font">+</i></a>
<a href="#" class="subCell decreaseLineHeight" id="decreaseLineHeight"><span>Decrease line height</span> <i class="icon-text-height">-</i></a>
<a href="#" class="subCell increaseLineHeight" id="increaseLineHeight"><span>Increase line height</span> <i class="icon-text-height">+</i></a>
<a href="#" class="subCell togglePing" id="togglePing"><span>Toggle ping display</span> <i class="icon-circle"></i></a>
<a href="#" class="subCell highlightTerm" id="highlightTerm"><span>Highlight string</span> <i class="icon-tag"></i></a>
<a href="#" class="subCell saveLog" id="saveLog"><span>Save chat log</span> <i class="icon-save"></i></a>
@@ -593,6 +593,7 @@ $(function() {
******************************************/
var savedConfig = {
'sfontSize': getCookie('fontsize'),
'slineHeight': getCookie('lineheight'),
'spingDisabled': getCookie('pingdisabled'),
'shighlightTerms': getCookie('highlightterms'),
'shighlightColor': getCookie('highlightcolor'),
@@ -604,6 +605,10 @@ $(function() {
$messages.css('font-size', savedConfig.sfontSize);
internalOutput('<span class="internal boldnshit">Loaded font size setting of: '+savedConfig.sfontSize+'</span>', 'internal');
}
if (savedConfig.slineHeight) {
$("body").css('line-height', savedConfig.slineHeight);
internalOutput('<span class="internal boldnshit">Loaded line height setting of: '+savedConfig.slineHeight+'</span>', 'internal');
}
if (savedConfig.spingDisabled) {
if (savedConfig.spingDisabled == 'true') {
opts.pingDisabled = true;
@@ -843,6 +848,28 @@ $(function() {
internalOutput('<span class="internal boldnshit">Font size set to '+fontSize+'</span>', 'internal');
});
$('#decreaseLineHeight').click(function(e) {
var Heightline = parseFloat($("body").css('line-height'));
var Sizefont = parseFloat($("body").css('font-size'));
var lineheightvar = Heightline / Sizefont
lineheightvar -= 0.1;
lineheightvar = lineheightvar.toFixed(1)
$("body").css({'line-height': lineheightvar});
setCookie('lineheight', lineheightvar, 365);
internalOutput('<span class="internal boldnshit">Line height set to '+lineheightvar+'</span>', 'internal');
});
$('#increaseLineHeight').click(function(e) {
var Heightline = parseFloat($("body").css('line-height'));
var Sizefont = parseFloat($("body").css('font-size'));
var lineheightvar = Heightline / Sizefont
lineheightvar += 0.1;
lineheightvar = lineheightvar.toFixed(1)
$("body").css({'line-height': lineheightvar});
setCookie('lineheight', lineheightvar, 365);
internalOutput('<span class="internal boldnshit">Line height set to '+lineheightvar+'</span>', 'internal');
});
$('#togglePing').click(function(e) {
if (opts.pingDisabled) {
$('#ping').slideDown('fast');
+13 -2
View File
@@ -9,6 +9,8 @@
var/begin_weekday = FALSE //If set to a weekday, then this will trigger the holiday on the above week
var/always_celebrate = FALSE // for christmas neverending, or testing.
var/obj/item/drone_hat //If this is defined, drones without a default hat will spawn with this one during the holiday; check drones_as_items.dm to see this used
// This proc gets run before the game starts when the holiday is activated. Do festive shit here.
/datum/holiday/proc/celebrate()
return
@@ -172,11 +174,13 @@
name = "Labor Day"
begin_day = 1
begin_month = MAY
drone_hat = /obj/item/clothing/head/hardhat
/datum/holiday/firefighter
name = "Firefighter's Day"
begin_day = 4
begin_month = MAY
drone_hat = /obj/item/clothing/head/hardhat/red
/datum/holiday/firefighter/getStationPrefix()
return pick("Burning","Blazing","Plasma","Fire")
@@ -190,6 +194,7 @@
name = "Doctor's Day"
begin_day = 1
begin_month = JULY
drone_hat = /obj/item/clothing/head/nursehat
/datum/holiday/UFO
name = "UFO Day"
@@ -221,6 +226,7 @@
name = "Talk-Like-a-Pirate Day"
begin_day = 19
begin_month = SEPTEMBER
drone_hat = /obj/item/clothing/head/pirate
/datum/holiday/pirate/greet()
return "Ye be talkin' like a pirate today or else ye'r walkin' tha plank, matey!"
@@ -321,6 +327,7 @@
begin_week = 4
begin_month = NOVEMBER
begin_weekday = THURSDAY
drone_hat = /obj/item/clothing/head/that //This is the closest we can get to a pilgrim's hat
/datum/holiday/thanksgiving/canada
name = "Thanksgiving in Canada"
@@ -384,12 +391,14 @@ Since Ramadan is an entire month that lasts 29.5 days on average, the start and
name = "Mayan Doomsday Anniversary"
begin_day = 21
begin_month = DECEMBER
drone_hat = /obj/item/clothing/mask/rat/tribal
/datum/holiday/xmas
name = CHRISTMAS
begin_day = 23
begin_day = 22
begin_month = DECEMBER
end_day = 25
end_day = 27
drone_hat = /obj/item/clothing/head/santa
/datum/holiday/xmas/greet()
return "Have a merry Christmas!"
@@ -399,6 +408,7 @@ Since Ramadan is an entire month that lasts 29.5 days on average, the start and
begin_day = 1
begin_month = DECEMBER
end_day = 31
drone_hat = /obj/item/clothing/head/santa
/datum/holiday/festive_season/greet()
return "Have a nice festive season!"
@@ -421,6 +431,7 @@ Since Ramadan is an entire month that lasts 29.5 days on average, the start and
/datum/holiday/easter
name = EASTER
drone_hat = /obj/item/clothing/head/rabbitears
var/const/days_early = 1 //to make editing the holiday easier
var/const/days_extra = 1
+1 -1
View File
@@ -42,7 +42,7 @@
for(var/obj/item/stock_parts/micro_laser/ML in component_parts)
var/wratemod = ML.rating * 2.5
min_wrate = Floor(10-wratemod,1) // 7,5,2,0 Clamps at 0 and 10 You want this low
min_wrate = FLOOR(10-wratemod,1) // 7,5,2,0 Clamps at 0 and 10 You want this low
min_wchance = 67-(ML.rating*16) // 48,35,19,3 Clamps at 0 and 67 You want this low
for(var/obj/item/circuitboard/machine/plantgenes/vaultcheck in component_parts)
if(istype(vaultcheck, /obj/item/circuitboard/machine/plantgenes/vault)) // DUMB BOTANY TUTS
+3 -3
View File
@@ -37,7 +37,7 @@
for(var/datum/plant_gene/trait/T in seed.genes)
T.on_new(src, loc)
seed.prepare_result(src)
transform *= TransformUsingVariable(seed.potency, 100, 0.5) //Makes the resulting produce's sprite larger or smaller based on potency!
transform *= TRANSFORM_USING_VARIABLE(seed.potency, 100) + 0.5 //Makes the resulting produce's sprite larger or smaller based on potency!
add_juice()
@@ -146,7 +146,7 @@
/obj/item/reagent_containers/food/snacks/grown/on_grind()
var/nutriment = reagents.get_reagent_amount("nutriment")
if(grind_results.len)
if(grind_results&&grind_results.len)
for(var/i in 1 to grind_results.len)
grind_results[grind_results[i]] = nutriment
reagents.del_reagent("nutriment")
@@ -154,7 +154,7 @@
/obj/item/reagent_containers/food/snacks/grown/on_juice()
var/nutriment = reagents.get_reagent_amount("nutriment")
if(juice_results.len)
if(juice_results&&juice_results.len)
for(var/i in 1 to juice_results.len)
juice_results[juice_results[i]] = nutriment
reagents.del_reagent("nutriment")
+2 -2
View File
@@ -154,8 +154,8 @@
if(!click_params || !click_params["icon-x"] || !click_params["icon-y"])
return
//Clamp it so that the icon never moves more than 16 pixels in either direction (thus leaving the table turf)
W.pixel_x = Clamp(text2num(click_params["icon-x"]) - 16, -(world.icon_size/2), world.icon_size/2)
W.pixel_y = Clamp(text2num(click_params["icon-y"]) - 16, -(world.icon_size/2), world.icon_size/2)
W.pixel_x = CLAMP(text2num(click_params["icon-x"]) - 16, -(world.icon_size/2), world.icon_size/2)
W.pixel_y = CLAMP(text2num(click_params["icon-y"]) - 16, -(world.icon_size/2), world.icon_size/2)
else
return ..()
+1 -1
View File
@@ -28,7 +28,7 @@
if(istype(src, seed.product)) // no adding reagents if it is just a trash item
seed.prepare_result(src)
transform *= TransformUsingVariable(seed.potency, 100, 0.5)
transform *= TRANSFORM_USING_VARIABLE(seed.potency, 100) + 0.5
add_juice()
@@ -24,12 +24,6 @@
lefthand_file = 'icons/mob/inhands/equipment/hydroponics_lefthand.dmi'
righthand_file = 'icons/mob/inhands/equipment/hydroponics_righthand.dmi'
volume = 100
container_type = OPENCONTAINER_1
slot_flags = SLOT_BELT
throwforce = 0
w_class = WEIGHT_CLASS_SMALL
throw_speed = 3
throw_range = 10
/obj/item/reagent_containers/spray/weedspray/Initialize()
. = ..()
@@ -48,12 +42,6 @@
lefthand_file = 'icons/mob/inhands/equipment/hydroponics_lefthand.dmi'
righthand_file = 'icons/mob/inhands/equipment/hydroponics_righthand.dmi'
volume = 100
container_type = OPENCONTAINER_1
slot_flags = SLOT_BELT
throwforce = 0
w_class = WEIGHT_CLASS_SMALL
throw_speed = 3
throw_range = 10
/obj/item/reagent_containers/spray/pestspray/Initialize()
. = ..()
+8 -8
View File
@@ -712,8 +712,8 @@
else if(transfer_amount) // Droppers, cans, beakers, what have you.
visi_msg="[user] uses [reagent_source] on [target]"
irrigate = 1
// Beakers, bottles, buckets, etc. Can't use is_open_container though.
if(istype(reagent_source, /obj/item/reagent_containers/glass/))
// Beakers, bottles, buckets, etc.
if(reagent_source.is_drainable())
playsound(loc, 'sound/effects/slosh.ogg', 25, 1)
if(irrigate && transfer_amount > 30 && reagent_source.reagents.total_volume >= 30 && using_irrigation)
@@ -881,26 +881,26 @@
/// Tray Setters - The following procs adjust the tray or plants variables, and make sure that the stat doesn't go out of bounds.///
/obj/machinery/hydroponics/proc/adjustNutri(adjustamt)
nutrilevel = Clamp(nutrilevel + adjustamt, 0, maxnutri)
nutrilevel = CLAMP(nutrilevel + adjustamt, 0, maxnutri)
/obj/machinery/hydroponics/proc/adjustWater(adjustamt)
waterlevel = Clamp(waterlevel + adjustamt, 0, maxwater)
waterlevel = CLAMP(waterlevel + adjustamt, 0, maxwater)
if(adjustamt>0)
adjustToxic(-round(adjustamt/4))//Toxicity dilutation code. The more water you put in, the lesser the toxin concentration.
/obj/machinery/hydroponics/proc/adjustHealth(adjustamt)
if(myseed && !dead)
plant_health = Clamp(plant_health + adjustamt, 0, myseed.endurance)
plant_health = CLAMP(plant_health + adjustamt, 0, myseed.endurance)
/obj/machinery/hydroponics/proc/adjustToxic(adjustamt)
toxic = Clamp(toxic + adjustamt, 0, 100)
toxic = CLAMP(toxic + adjustamt, 0, 100)
/obj/machinery/hydroponics/proc/adjustPests(adjustamt)
pestlevel = Clamp(pestlevel + adjustamt, 0, 10)
pestlevel = CLAMP(pestlevel + adjustamt, 0, 10)
/obj/machinery/hydroponics/proc/adjustWeeds(adjustamt)
weedlevel = Clamp(weedlevel + adjustamt, 0, 10)
weedlevel = CLAMP(weedlevel + adjustamt, 0, 10)
/obj/machinery/hydroponics/proc/spawnplant() // why would you put strange reagent in a hydro tray you monster I bet you also feed them blood
var/list/livingplants = list(/mob/living/simple_animal/hostile/tree, /mob/living/simple_animal/hostile/killertomato)
+14 -14
View File
@@ -170,7 +170,7 @@
/// Setters procs ///
/obj/item/seeds/proc/adjust_yield(adjustamt)
if(yield != -1) // Unharvestable shouldn't suddenly turn harvestable
yield = Clamp(yield + adjustamt, 0, 10)
yield = CLAMP(yield + adjustamt, 0, 10)
if(yield <= 0 && get_gene(/datum/plant_gene/trait/plant_type/fungal_metabolism))
yield = 1 // Mushrooms always have a minimum yield of 1.
@@ -179,39 +179,39 @@
C.value = yield
/obj/item/seeds/proc/adjust_lifespan(adjustamt)
lifespan = Clamp(lifespan + adjustamt, 10, 100)
lifespan = CLAMP(lifespan + adjustamt, 10, 100)
var/datum/plant_gene/core/C = get_gene(/datum/plant_gene/core/lifespan)
if(C)
C.value = lifespan
/obj/item/seeds/proc/adjust_endurance(adjustamt)
endurance = Clamp(endurance + adjustamt, 10, 100)
endurance = CLAMP(endurance + adjustamt, 10, 100)
var/datum/plant_gene/core/C = get_gene(/datum/plant_gene/core/endurance)
if(C)
C.value = endurance
/obj/item/seeds/proc/adjust_production(adjustamt)
if(yield != -1)
production = Clamp(production + adjustamt, 1, 10)
production = CLAMP(production + adjustamt, 1, 10)
var/datum/plant_gene/core/C = get_gene(/datum/plant_gene/core/production)
if(C)
C.value = production
/obj/item/seeds/proc/adjust_potency(adjustamt)
if(potency != -1)
potency = Clamp(potency + adjustamt, 0, 100)
potency = CLAMP(potency + adjustamt, 0, 100)
var/datum/plant_gene/core/C = get_gene(/datum/plant_gene/core/potency)
if(C)
C.value = potency
/obj/item/seeds/proc/adjust_weed_rate(adjustamt)
weed_rate = Clamp(weed_rate + adjustamt, 0, 10)
weed_rate = CLAMP(weed_rate + adjustamt, 0, 10)
var/datum/plant_gene/core/C = get_gene(/datum/plant_gene/core/weed_rate)
if(C)
C.value = weed_rate
/obj/item/seeds/proc/adjust_weed_chance(adjustamt)
weed_chance = Clamp(weed_chance + adjustamt, 0, 67)
weed_chance = CLAMP(weed_chance + adjustamt, 0, 67)
var/datum/plant_gene/core/C = get_gene(/datum/plant_gene/core/weed_chance)
if(C)
C.value = weed_chance
@@ -220,7 +220,7 @@
/obj/item/seeds/proc/set_yield(adjustamt)
if(yield != -1) // Unharvestable shouldn't suddenly turn harvestable
yield = Clamp(adjustamt, 0, 10)
yield = CLAMP(adjustamt, 0, 10)
if(yield <= 0 && get_gene(/datum/plant_gene/trait/plant_type/fungal_metabolism))
yield = 1 // Mushrooms always have a minimum yield of 1.
@@ -229,39 +229,39 @@
C.value = yield
/obj/item/seeds/proc/set_lifespan(adjustamt)
lifespan = Clamp(adjustamt, 10, 100)
lifespan = CLAMP(adjustamt, 10, 100)
var/datum/plant_gene/core/C = get_gene(/datum/plant_gene/core/lifespan)
if(C)
C.value = lifespan
/obj/item/seeds/proc/set_endurance(adjustamt)
endurance = Clamp(adjustamt, 10, 100)
endurance = CLAMP(adjustamt, 10, 100)
var/datum/plant_gene/core/C = get_gene(/datum/plant_gene/core/endurance)
if(C)
C.value = endurance
/obj/item/seeds/proc/set_production(adjustamt)
if(yield != -1)
production = Clamp(adjustamt, 1, 10)
production = CLAMP(adjustamt, 1, 10)
var/datum/plant_gene/core/C = get_gene(/datum/plant_gene/core/production)
if(C)
C.value = production
/obj/item/seeds/proc/set_potency(adjustamt)
if(potency != -1)
potency = Clamp(adjustamt, 0, 100)
potency = CLAMP(adjustamt, 0, 100)
var/datum/plant_gene/core/C = get_gene(/datum/plant_gene/core/potency)
if(C)
C.value = potency
/obj/item/seeds/proc/set_weed_rate(adjustamt)
weed_rate = Clamp(adjustamt, 0, 10)
weed_rate = CLAMP(adjustamt, 0, 10)
var/datum/plant_gene/core/C = get_gene(/datum/plant_gene/core/weed_rate)
if(C)
C.value = weed_rate
/obj/item/seeds/proc/set_weed_chance(adjustamt)
weed_chance = Clamp(adjustamt, 0, 67)
weed_chance = CLAMP(adjustamt, 0, 67)
var/datum/plant_gene/core/C = get_gene(/datum/plant_gene/core/weed_chance)
if(C)
C.value = weed_chance
@@ -20,6 +20,8 @@
var/charge_tick = FALSE
var/charge_delay = 4
var/use_cyborg_cell = TRUE
max_integrity = 50
armor = list(melee = 50, bullet = 70, laser = 70, energy = 100, bomb = 10, bio = 100, rad = 100, fire = 0, acid = 0)
/obj/item/device/electronic_assembly/proc/check_interactivity(mob/user)
return user.canUseTopic(src,be_close = TRUE)
@@ -30,8 +32,6 @@
START_PROCESSING(SScircuit, src)
materials[MAT_METAL] = round((max_complexity + max_components) / 4) * SScircuit.cost_multiplier
/obj/item/device/electronic_assembly/Destroy()
STOP_PROCESSING(SScircuit, src)
return ..()
@@ -273,22 +273,9 @@
/obj/item/device/electronic_assembly/afterattack(atom/target, mob/user, proximity)
for(var/obj/item/integrated_circuit/input/sensor/S in assembly_components)
if(!proximity)
if(istype(S,/obj/item/integrated_circuit/input/sensor/ranged)||(!user))
if(user.client)
if(!(target in view(user.client)))
continue
else
if(!(target in view(user)))
continue
else
continue
S.set_pin_data(IC_OUTPUT, 1, WEAKREF(target))
S.check_then_do_work()
S.scan(target)
visible_message("<span class='notice'> [user] waves [src] around [target].</span>")
for(var/obj/item/integrated_circuit/input/S in assembly_components)
if(S.sense(target,user,proximity))
visible_message("<span class='notice'> [user] waves [src] around [target].</span>")
/obj/item/device/electronic_assembly/screwdriver_act(mob/living/user, obj/item/S)
@@ -326,8 +313,11 @@
interact(user)
return TRUE
else
for(var/obj/item/integrated_circuit/input/S in assembly_components)
S.attackby_react(I,user,user.a_intent)
return ..()
/obj/item/device/electronic_assembly/attack_self(mob/user)
if(!check_interactivity(user))
return
@@ -391,7 +381,6 @@
/obj/item/device/electronic_assembly/proc/get_object()
return src
// Returns the location to be used for dropping items.
// Same as the regular drop_location(), but with checks being run on acting_object if necessary.
/obj/item/integrated_circuit/drop_location()
@@ -406,6 +395,7 @@
/obj/item/device/electronic_assembly/default //The /default electronic_assemblys are to allow the introduction of the new naming scheme without breaking old saves.
name = "type-a electronic assembly"
/obj/item/device/electronic_assembly/calc
name = "type-b electronic assembly"
icon_state = "setup_small_calc"
@@ -507,4 +497,4 @@
/obj/item/device/electronic_assembly/drone/arms
name = "type-b electronic drone"
icon_state = "setup_drone_arms"
desc = "It's a case, for building mobile electronics with. This one is armed and dangerous."
desc = "It's a case, for building mobile electronics with. This one is armed and dangerous."
@@ -56,7 +56,7 @@
data_to_show = A.name
to_chat(user, "<span class='notice'>You write '[data_to_write ? data_to_show : "NULL"]' to the '[io]' pin of \the [io.holder].</span>")
else if(io.io_type == PULSE_CHANNEL)
io.holder.check_then_do_work(ignore_power = TRUE)
io.holder.check_then_do_work(io.ord,ignore_power = TRUE)
to_chat(user, "<span class='notice'>You pulse \the [io.holder]'s [io].</span>")
io.holder.interact(user) // This is to update the UI.
@@ -15,9 +15,9 @@
io_type_override = io_list_copy[io_entry]
if(io_type_override)
io_list.Add(new io_type_override(src, io_entry, default_data, pin_type))
io_list.Add(new io_type_override(src, io_entry, default_data, pin_type,i))
else
io_list.Add(new io_type(src, io_entry, default_data, pin_type))
io_list.Add(new io_type(src, io_entry, default_data, pin_type,i))
/obj/item/integrated_circuit/proc/set_pin_data(pin_type, pin_number, datum/new_data)
@@ -58,6 +58,12 @@ a creative player the means to solve many problems. Circuits are held inside an
/obj/item/integrated_circuit/proc/any_examine(mob/user)
return
/obj/item/integrated_circuit/proc/attackby_react(var/atom/movable/A,mob/user)
return
/obj/item/integrated_circuit/proc/sense(var/atom/movable/A,mob/user,prox)
return
/obj/item/integrated_circuit/proc/check_interactivity(mob/user)
if(assembly)
return assembly.check_interactivity(user)
@@ -291,17 +297,18 @@ a creative player the means to solve many problems. Circuits are held inside an
return TRUE // Battery has enough.
return FALSE // Not enough power.
/obj/item/integrated_circuit/proc/check_then_do_work(var/ignore_power = FALSE)
/obj/item/integrated_circuit/proc/check_then_do_work(ord,var/ignore_power = FALSE)
if(world.time < next_use) // All intergrated circuits have an internal cooldown, to protect from spam.
return
return FALSE
if(power_draw_per_use && !ignore_power)
if(!check_power())
power_fail()
return
return FALSE
next_use = world.time + cooldown_per_use
do_work()
do_work(ord)
return TRUE
/obj/item/integrated_circuit/proc/do_work()
/obj/item/integrated_circuit/proc/do_work(ord)
return
/obj/item/integrated_circuit/proc/disconnect_all()
@@ -369,4 +376,3 @@ a creative player the means to solve many problems. Circuits are held inside an
return TRUE
return FALSE
@@ -25,14 +25,16 @@ D [1]/ ||
var/list/linked = list()
var/io_type = DATA_CHANNEL
var/pin_type // IC_INPUT, IC_OUTPUT, IC_ACTIVATOR - used in saving assembly wiring
var/ord
/datum/integrated_io/New(loc, _name, _data, _pin_type)
/datum/integrated_io/New(loc, _name, _data, _pin_type,_ord)
name = _name
if(_data)
data = _data
if(_pin_type)
pin_type = _pin_type
if(_ord)
ord = _ord
holder = loc
@@ -148,7 +150,7 @@ D [1]/ ||
/datum/integrated_io/activate/push_data()
for(var/k in 1 to linked.len)
var/datum/integrated_io/io = linked[k]
io.holder.check_then_do_work()
io.holder.check_then_do_work(io.ord)
/datum/integrated_io/proc/pull_data()
for(var/k in 1 to linked.len)
@@ -207,7 +209,7 @@ D [1]/ ||
write_data_to_pin(new_data)
/datum/integrated_io/activate/ask_for_pin_data(mob/user) // This just pulses the pin.
holder.check_then_do_work(ignore_power = TRUE)
holder.check_then_do_work(ord,ignore_power = TRUE)
to_chat(user, "<span class='notice'>You pulse \the [holder]'s [src] pin.</span>")
/datum/integrated_io/activate
@@ -1,4 +1,4 @@
// These pins can only contain integer numbers between 1 and IC_MAX_LIST_LENGTH. Null is not allowed.
// These pins can only contain integer numbers between 0 and IC_MAX_LIST_LENGTH. Null is allowed.
/datum/integrated_io/index
name = "index pin"
data = 1
@@ -11,10 +11,10 @@
/datum/integrated_io/index/write_data_to_pin(new_data)
if(isnull(new_data))
new_data = 1
new_data = 0
if(isnum(new_data))
data = Clamp(round(new_data), 1, IC_MAX_LIST_LENGTH)
data = CLAMP(round(new_data), 0, IC_MAX_LIST_LENGTH)
holder.on_data_written()
/datum/integrated_io/index/display_pin_type()
@@ -90,7 +90,7 @@
icon_state = "chemical_cell"
extended_desc = "This is effectively an internal beaker. It will consume and produce power from plasma, slime jelly, welding fuel, carbon,\
ethanol, nutriments and blood , in order of decreasing efficiency. It will consume fuel only if the battery can take more energy."
container_type = OPENCONTAINER_1
container_type = OPENCONTAINER
complexity = 4
inputs = list()
outputs = list("volume used" = IC_PINTYPE_NUMBER, "self reference" = IC_PINTYPE_REF)
@@ -30,10 +30,9 @@
/obj/item/integrated_circuit/arithmetic/addition/do_work()
var/result = 0
for(var/k in 1 to inputs.len)
var/datum/integrated_io/I = inputs[k]
I.pull_data()
if(isnum(I.data))
result = result + I.data
var/I = get_pin_data(IC_INPUT, k)
if(isnum(I))
result += I
set_pin_data(IC_OUTPUT, 1, result)
push_data()
@@ -56,13 +55,10 @@
return
var/result = A.data
for(var/k in 1 to inputs.len)
var/datum/integrated_io/I = inputs[k]
if(I == A)
continue
I.pull_data()
if(isnum(I.data))
result = result - I.data
for(var/k in 2 to inputs.len)
var/I = get_pin_data(IC_INPUT, k)
if(isnum(I))
result -= I
set_pin_data(IC_OUTPUT, 1, result)
push_data()
@@ -85,13 +81,10 @@
if(!isnum(A.data))
return
var/result = A.data
for(var/k in 1 to inputs.len)
var/datum/integrated_io/I = inputs[k]
if(I == A)
continue
I.pull_data()
if(isnum(I.data))
result = result * I.data
for(var/k in 2 to inputs.len)
var/I = get_pin_data(IC_INPUT, k)
if(isnum(I))
result *= I
set_pin_data(IC_OUTPUT, 1, result)
push_data()
@@ -114,13 +107,12 @@
return
var/result = A.data
for(var/k in 1 to inputs.len)
var/datum/integrated_io/I = inputs[k]
if(I == A)
continue
I.pull_data()
if(isnum(I.data) && I.data != 0) //No runtimes here.
result = result / I.data
for(var/k in 2 to inputs.len)
var/I = get_pin_data(IC_INPUT, k)
if(isnum(I) && (I != 0))
result /= I
set_pin_data(IC_OUTPUT, 1, result)
push_data()
@@ -228,12 +220,11 @@
/obj/item/integrated_circuit/arithmetic/average/do_work()
var/result = 0
var/inputs_used = 0
for(var/k in 1 to inputs.len)
var/datum/integrated_io/I = inputs[k]
I.pull_data()
if(isnum(I.data))
for(var/k in 2 to inputs.len)
var/I = get_pin_data(IC_INPUT, k)
if(isnum(I))
inputs_used++
result = result + I.data
result += I
if(inputs_used)
result = result / inputs_used
@@ -288,11 +279,10 @@
/obj/item/integrated_circuit/arithmetic/square_root/do_work()
var/result = 0
for(var/k in 1 to inputs.len)
var/datum/integrated_io/I = inputs[k]
I.pull_data()
if(isnum(I.data))
result = sqrt(I.data)
for(var/k in 2 to inputs.len)
var/I = get_pin_data(IC_INPUT, k)
if(isnum(I))
result += sqrt(I)
set_pin_data(IC_OUTPUT, 1, result)
push_data()
@@ -160,10 +160,10 @@
/obj/item/integrated_circuit/converter/concatenator/do_work()
var/result = null
for(var/datum/integrated_io/I in inputs)
I.pull_data()
if(!isnull(I.data))
result = result + I.data
for(var/k in 1 to inputs.len)
var/I = get_pin_data(IC_INPUT, k)
if(!isnull(I))
result = result + I
set_pin_data(IC_OUTPUT, 1, result)
push_data()
@@ -265,7 +265,7 @@
pull_data()
var/incoming = get_pin_data(IC_INPUT, 1)
if(!isnull(incoming))
result = ToDegrees(incoming)
result = TODEGREES(incoming)
set_pin_data(IC_OUTPUT, 1, result)
push_data()
@@ -283,7 +283,7 @@
pull_data()
var/incoming = get_pin_data(IC_INPUT, 1)
if(!isnull(incoming))
result = ToRadians(incoming)
result = TORADIANS(incoming)
set_pin_data(IC_OUTPUT, 1, result)
push_data()
@@ -123,7 +123,7 @@
/obj/item/integrated_circuit/transfer/pulsedemultiplexer/do_work()
var/output_index = get_pin_data(IC_INPUT, 1)
if(output_index == Clamp(output_index, 1, number_of_pins))
if(output_index == CLAMP(output_index, 1, number_of_pins))
activate_pin(round(output_index + 1 ,1))
/obj/item/integrated_circuit/transfer/pulsedemultiplexer/medium
@@ -128,7 +128,7 @@
var/mob/living/carbon/human/H = get_pin_data_as_type(IC_INPUT, 1, /mob/living/carbon/human)
if(!istype(H)) //Invalid input
return
if(H in view(get_turf(H))) // Like medbot's analyzer it can be used in range..
if(H in view(get_turf(src))) // Like medbot's analyzer it can be used in range..
var/total_health = round(H.health/H.getMaxHealth(), 0.01)*100
var/missing_health = H.getMaxHealth() - H.health
@@ -143,6 +143,49 @@
push_data()
activate_pin(2)
/obj/item/integrated_circuit/input/slime_scanner
name = "slime_scanner"
desc = "A very small version of the xenobio analyser. This allows the machine to know every needed properties of slime."
icon_state = "medscan_adv"
complexity = 12
inputs = list("\<REF\> target")
outputs = list(
"colour" = IC_PINTYPE_STRING,
"adult" = IC_PINTYPE_BOOLEAN,
"nutrition" = IC_PINTYPE_NUMBER,
"charge" = IC_PINTYPE_NUMBER,
"health" = IC_PINTYPE_NUMBER,
"possible mutation" = IC_PINTYPE_LIST,
"genetic destability"= IC_PINTYPE_NUMBER,
"slime core amount" = IC_PINTYPE_NUMBER,
"Growth progress" = IC_PINTYPE_NUMBER,
)
activators = list("scan" = IC_PINTYPE_PULSE_IN, "on scanned" = IC_PINTYPE_PULSE_OUT)
spawn_flags = IC_SPAWN_RESEARCH
power_draw_per_use = 80
/obj/item/integrated_circuit/input/slime_scanner/do_work()
var/mob/living/simple_animal/slime/T = get_pin_data_as_type(IC_INPUT, 1, /mob/living/simple_animal/slime)
if(!isslime(T)) //Invalid input
return
if(T in view(get_turf(src))) // Like medbot's analyzer it can be used in range..
set_pin_data(IC_OUTPUT, 1, T.colour)
set_pin_data(IC_OUTPUT, 2, T.is_adult)
set_pin_data(IC_OUTPUT, 3, T.nutrition/T.get_max_nutrition())
set_pin_data(IC_OUTPUT, 4, T.powerlevel)
set_pin_data(IC_OUTPUT, 5, round(T.health/T.maxHealth,0.01)*100)
set_pin_data(IC_OUTPUT, 6, uniqueList(T.slime_mutation))
set_pin_data(IC_OUTPUT, 7, T.mutation_chance)
set_pin_data(IC_OUTPUT, 8, T.cores)
set_pin_data(IC_OUTPUT, 9, T.amount_grown/SLIME_EVOLUTION_THRESHOLD)
push_data()
activate_pin(2)
/obj/item/integrated_circuit/input/plant_scanner
name = "integrated plant analyzer"
desc = "A very small version of the plant analyser. This allows the machine to know all valuable params of plants in trays. \
@@ -180,7 +223,7 @@
return
for(var/i=1, i<=outputs.len, i++)
set_pin_data(IC_OUTPUT, i, null)
if(H in view(get_turf(H))) // Like medbot's analyzer it can be used in range..
if(H in view(get_turf(src))) // Like medbot's analyzer it can be used in range..
if(H.myseed)
set_pin_data(IC_OUTPUT, 1, H.myseed.plantname)
set_pin_data(IC_OUTPUT, 2, H.age)
@@ -228,7 +271,7 @@
return
for(var/i=1, i<=outputs.len, i++)
set_pin_data(IC_OUTPUT, i, null)
if(H in view(get_turf(H))) // Like medbot's analyzer it can be used in range..
if(H in view(get_turf(src))) // Like medbot's analyzer it can be used in range..
if(H.myseed)
for(var/datum/plant_gene/reagent/G in H.myseed.genes)
greagents.Add(G.get_name())
@@ -373,7 +416,7 @@
var/rad = get_pin_data(IC_INPUT, 2)
if(isnum(rad))
rad = Clamp(rad, 0, 8)
rad = CLAMP(rad, 0, 8)
radius = rad
/obj/item/integrated_circuit/input/advanced_locator_list/do_work()
@@ -426,7 +469,7 @@
/obj/item/integrated_circuit/input/advanced_locator/on_data_written()
var/rad = get_pin_data(IC_INPUT, 2)
if(isnum(rad))
rad = Clamp(rad, 0, 8)
rad = CLAMP(rad, 0, 8)
radius = rad
/obj/item/integrated_circuit/input/advanced_locator/do_work()
@@ -671,12 +714,15 @@
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
power_draw_per_use = 120
/obj/item/integrated_circuit/input/sensor/proc/scan(var/atom/A)
/obj/item/integrated_circuit/input/sensor/sense(var/atom/A,mob/user,prox)
if(!prox)
return FALSE
if(!check_then_do_work())
return FALSE
var/ignore_bags = get_pin_data(IC_INPUT, 1)
if(ignore_bags)
if(istype(A, /obj/item/storage))
return FALSE
set_pin_data(IC_OUTPUT, 1, WEAKREF(A))
push_data()
activate_pin(1)
@@ -694,6 +740,52 @@
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
power_draw_per_use = 120
/obj/item/integrated_circuit/input/sensor/ranged/sense(var/atom/A,mob/user)
if(!user)
return FALSE
if(user.client)
if(!(A in view(user.client)))
return FALSE
else
if(!(A in view(user)))
return FALSE
if(!check_then_do_work())
return FALSE
var/ignore_bags = get_pin_data(IC_INPUT, 1)
if(ignore_bags)
if(istype(A, /obj/item/storage))
return FALSE
set_pin_data(IC_OUTPUT, 1, WEAKREF(A))
push_data()
activate_pin(1)
return TRUE
/obj/item/integrated_circuit/input/objscaner
name = "scaner"
desc = "Scans and obtains a reference for any objects you use on assembly."
extended_desc = "If 'put down' pin is set to true, assembly will take scanned object from your hands to it's location.\
useful for interaction with grabber. Scaner works only with help intent."
icon_state = "recorder"
complexity = 4
inputs = list("put down" = IC_PINTYPE_BOOLEAN)
outputs = list("scanned" = IC_PINTYPE_REF)
activators = list("on scanned" = IC_PINTYPE_PULSE_OUT)
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
power_draw_per_use = 20
/obj/item/integrated_circuit/input/objscaner/attackby_react(var/atom/A,var/mob/user,intent)
if(intent!=INTENT_HELP)
return FALSE
if(!check_then_do_work())
return FALSE
var/pu = get_pin_data(IC_INPUT, 1)
if(pu)
user.transferItemToLoc(A,drop_location())
set_pin_data(IC_OUTPUT, 1, WEAKREF(A))
push_data()
activate_pin(1)
return TRUE
/obj/item/integrated_circuit/input/internalbm
name = "internal battery monitor"
desc = "This monitors the charge level of an internal battery."
@@ -760,3 +852,38 @@
activate_pin(2)
push_data()
return
/obj/item/integrated_circuit/input/ntnetsc
name = "NTnet scaner"
desc = "This can return NTnet id of component insi given object, if there is any."
icon_state = "signalsc"
w_class = WEIGHT_CLASS_TINY
complexity = 2
inputs = list("target" = IC_PINTYPE_REF)
outputs = list(
"id" = IC_PINTYPE_STRING
)
activators = list("read" = IC_PINTYPE_PULSE_IN, "found" = IC_PINTYPE_PULSE_OUT,"not found" = IC_PINTYPE_PULSE_OUT)
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
power_draw_per_use = 1
/obj/item/integrated_circuit/input/ntnetsc/do_work()
var/atom/AM = get_pin_data_as_type(IC_INPUT, 1, /atom)
var/list/processing_list = list(AM)
var/datum/component/ntnet_interface/net = null
set_pin_data(IC_OUTPUT, 1, null)
while(processing_list.len && !net)
var/atom/A = processing_list[1]
processing_list.Cut(1, 2)
//Byond does not allow things to be in multiple contents, or double parent-child hierarchies, so only += is needed
//This is also why we don't need to check against assembled as we go along
processing_list += A.contents
net = A.GetComponent(/datum/component/ntnet_interface)
if(net)
set_pin_data(IC_OUTPUT, 1, net.hardware_id)
activate_pin(2)
else
activate_pin(3)
push_data()
return
@@ -2,7 +2,7 @@
name = "logic gate"
desc = "This tiny chip will decide for you!"
extended_desc = "Logic circuits will treat a null, 0, and a \"\" string value as FALSE and anything else as TRUE."
complexity = 3
complexity = 1
outputs = list("result")
activators = list("compare" = IC_PINTYPE_PULSE_IN)
category_text = "Logic"
@@ -93,8 +93,8 @@
yo.data = round(yo.data, 1)
var/turf/T = get_turf(assembly)
var/target_x = Clamp(T.x + xo.data, 0, world.maxx)
var/target_y = Clamp(T.y + yo.data, 0, world.maxy)
var/target_x = CLAMP(T.x + xo.data, 0, world.maxx)
var/target_y = CLAMP(T.y + yo.data, 0, world.maxy)
shootAt(locate(target_x, target_y, T.z))
@@ -155,9 +155,11 @@
if(isnum(wanted_dir.data))
if(step(assembly, wanted_dir.data))
activate_pin(2)
return
else
activate_pin(3)
return FALSE
return FALSE
/obj/item/integrated_circuit/manipulation/grenade
name = "grenade primer"
@@ -210,7 +212,7 @@
var/datum/integrated_io/detonation_time = inputs[1]
var/dt
if(isnum(detonation_time.data) && detonation_time.data > 0)
dt = Clamp(detonation_time.data, 1, 12)*10
dt = CLAMP(detonation_time.data, 1, 12)*10
else
dt = 15
addtimer(CALLBACK(attached_grenade, /obj/item/grenade.proc/prime), dt)
@@ -247,9 +249,14 @@
/obj/item/integrated_circuit/manipulation/plant_module/do_work()
..()
var/turf/T = get_turf(src)
var/obj/machinery/hydroponics/AM = get_pin_data_as_type(IC_INPUT, 1, /obj/machinery/hydroponics)
if(!istype(AM)) //Invalid input
var/obj/OM = get_pin_data_as_type(IC_INPUT, 1, /obj)
if(istype(OM,/obj/structure/spacevine) && get_pin_data(IC_INPUT, 2) == 2)
qdel(OM)
activate_pin(2)
return
var/obj/machinery/hydroponics/AM = OM
if(!istype(AM)) //Invalid input
return FALSE
var/mob/living/M = get_turf(AM)
if(!M.Adjacent(T))
return //Can't reach
@@ -276,6 +283,7 @@
qdel(AM.myseed)
AM.myseed = null
AM.weedlevel = 0 //Has a side effect of cleaning up those nasty weeds
AM.dead = 0
AM.update_icon()
else
activate_pin(2)
@@ -284,7 +292,7 @@
/obj/item/integrated_circuit/manipulation/grabber
name = "grabber"
desc = "A circuit with it's own inventory for small/medium items, used to grab and store things."
desc = "A circuit with it's own inventory for tiny/small items, used to grab and store things."
icon_state = "grabber"
extended_desc = "The circuit accepts a reference to thing to be grabbed. It can store up to 10 things. Modes: 1 for grab. 0 for eject the first thing. -1 for eject all."
w_class = WEIGHT_CLASS_SMALL
@@ -307,7 +315,7 @@
var/mode = get_pin_data(IC_INPUT, 2)
if(mode == 1)
if(check_target(AM, exclude_contents = TRUE))
if(check_target(AM))
if((contents.len < max_items) && (!max_w_class || AM.w_class <= max_w_class))
AM.forceMove(src)
if(mode == 0)
@@ -389,9 +397,9 @@
if(!M.temporarilyRemoveItemFromInventory(A))
return
var/x_abs = Clamp(T.x + target_x_rel, 0, world.maxx)
var/y_abs = Clamp(T.y + target_y_rel, 0, world.maxy)
var/range = round(Clamp(sqrt(target_x_rel*target_x_rel+target_y_rel*target_y_rel),0,8),1)
var/x_abs = CLAMP(T.x + target_x_rel, 0, world.maxx)
var/y_abs = CLAMP(T.y + target_y_rel, 0, world.maxy)
var/range = round(CLAMP(sqrt(target_x_rel*target_x_rel+target_y_rel*target_y_rel),0,8),1)
A.forceMove(drop_location())
A.throw_at(locate(x_abs, y_abs, T.z), range, 3)
@@ -88,7 +88,7 @@
var/brightness = get_pin_data(IC_INPUT, 2)
if(new_color && isnum(brightness))
brightness = Clamp(brightness, 0, 6)
brightness = CLAMP(brightness, 0, 6)
light_rgb = new_color
light_brightness = brightness
@@ -146,7 +146,7 @@
var/selected_sound = sounds[ID]
if(!selected_sound)
return
vol = Clamp(vol ,0 , 100)
vol = CLAMP(vol ,0 , 100)
playsound(get_turf(src), selected_sound, vol, freq, -1)
/obj/item/integrated_circuit/output/sound/on_data_written()
@@ -1,3 +1,5 @@
#define IC_SMOKE_REAGENTS_MINIMUM_UNITS 10
/obj/item/integrated_circuit/reagent
category_text = "Reagent"
resistance_flags = UNACIDABLE | FIRE_PROOF
@@ -7,8 +9,11 @@
. = ..()
if(volume)
create_reagents(volume)
push_vol()
/obj/item/integrated_circuit/reagent/proc/push_vol()
set_pin_data(IC_OUTPUT, 1, reagents.total_volume)
push_data()
/obj/item/integrated_circuit/reagent/smoke
name = "smoke generator"
@@ -17,7 +22,7 @@
extended_desc = "This smoke generator creates clouds of smoke on command. It can also hold liquids inside, which will go \
into the smoke clouds when activated. The reagents are consumed when smoke is made."
container_type = OPENCONTAINER_1
container_type = OPENCONTAINER
volume = 100
complexity = 20
@@ -29,7 +34,8 @@
)
activators = list(
"create smoke" = IC_PINTYPE_PULSE_IN,
"on smoked" = IC_PINTYPE_PULSE_OUT
"on smoked" = IC_PINTYPE_PULSE_OUT,
"push ref" = IC_PINTYPE_PULSE_IN
)
spawn_flags = IC_SPAWN_RESEARCH
power_draw_per_use = 20
@@ -40,24 +46,27 @@
//reset warning only if we have reagents now
if(changetype == ADD_REAGENT)
notified = FALSE
set_pin_data(IC_OUTPUT, 1, reagents.total_volume)
push_data()
/obj/item/integrated_circuit/reagent/smoke/do_work()
var/location = get_turf(src)
var/datum/effect_system/smoke_spread/chem/S = new
S.attach(location)
playsound(location, 'sound/effects/smoke.ogg', 50, 1, -3)
if(S)
S.set_up(reagents, smoke_radius, location, notified)
if(!notified)
notified = TRUE
S.start()
if(reagents)
reagents.clear_reagents()
activate_pin(2)
push_vol()
/obj/item/integrated_circuit/reagent/smoke/do_work(ord)
switch(ord)
if(1)
if(!reagents || (reagents.total_volume < IC_SMOKE_REAGENTS_MINIMUM_UNITS))
return
var/location = get_turf(src)
var/datum/effect_system/smoke_spread/chem/S = new
S.attach(location)
playsound(location, 'sound/effects/smoke.ogg', 50, 1, -3)
if(S)
S.set_up(reagents, smoke_radius, location, notified)
if(!notified)
notified = TRUE
S.start()
reagents.clear_reagents()
activate_pin(2)
if(3)
set_pin_data(IC_OUTPUT, 2, WEAKREF(src))
push_data()
/obj/item/integrated_circuit/reagent/injector
name = "integrated hypo-injector"
@@ -66,7 +75,7 @@
extended_desc = "This autoinjector can push reagents into another container or someone else outside of the machine. The target \
must be adjacent to the machine, and if it is a person, they cannot be wearing thick clothing. Negative given amount makes injector suck out reagents."
container_type = OPENCONTAINER_1
container_type = OPENCONTAINER
volume = 30
complexity = 20
@@ -85,7 +94,9 @@
activators = list(
"inject" = IC_PINTYPE_PULSE_IN,
"on injected" = IC_PINTYPE_PULSE_OUT,
"on fail" = IC_PINTYPE_PULSE_OUT
"on fail" = IC_PINTYPE_PULSE_OUT,
"push ref" = IC_PINTYPE_PULSE_IN
)
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
power_draw_per_use = 15
@@ -93,15 +104,8 @@
var/transfer_amount = 10
var/busy = FALSE
/obj/item/integrated_circuit/reagent/injector/interact(mob/user)
set_pin_data(IC_OUTPUT, 2, WEAKREF(src))
push_data()
..()
/obj/item/integrated_circuit/reagent/injector/on_reagent_change(changetype)
set_pin_data(IC_OUTPUT, 1, reagents.total_volume)
push_data()
push_vol()
/obj/item/integrated_circuit/reagent/injector/on_data_written()
var/new_amount = get_pin_data(IC_INPUT, 2)
@@ -111,7 +115,7 @@
else
direction_mode = SYRINGE_INJECT
if(isnum(new_amount))
new_amount = Clamp(new_amount, 0, volume)
new_amount = CLAMP(new_amount, 0, volume)
transfer_amount = new_amount
// Hydroponics trays have no reagents holder and handle reagents in their own snowflakey way.
@@ -127,7 +131,15 @@
temp_reagents.clear_reagents()
qdel(temp_reagents)
/obj/item/integrated_circuit/reagent/injector/do_work()
/obj/item/integrated_circuit/reagent/injector/do_work(ord)
switch(ord)
if(1)
inject()
if(4)
set_pin_data(IC_OUTPUT, 2, WEAKREF(src))
push_data()
/obj/item/integrated_circuit/reagent/injector/proc/inject()
set waitfor = FALSE // Don't sleep in a proc that is called by a processor without this set, otherwise it'll delay the entire thing
var/atom/movable/AM = get_pin_data_as_type(IC_INPUT, 1, /atom/movable)
var/atom/movable/acting_object = get_object()
@@ -145,7 +157,7 @@
return
if(direction_mode == SYRINGE_INJECT)
if(!reagents.total_volume || !AM.is_injectable() || AM.reagents.total_volume >= AM.reagents.maximum_volume)
if(!reagents.total_volume || !AM.is_injectable() || AM.reagents.holder_full())
activate_pin(3)
return
@@ -156,12 +168,8 @@
return
//Always log attemped injections for admins
var/list/rinject = list()
for(var/datum/reagent/R in reagents.reagent_list)
rinject += R.name
var/contained = english_list(rinject)
add_logs(src, L, "attemped to inject", addition="which had [contained]") //TODO: proper logging (maybe last touched and assembled)
var/contained = reagents.log_list()
add_logs(src, L, "attemped to inject", addition="which had [contained]")
L.visible_message("<span class='danger'>[acting_object] is trying to inject [L]!</span>", \
"<span class='userdanger'>[acting_object] is trying to inject you!</span>")
busy = TRUE
@@ -169,6 +177,7 @@
var/fraction = min(transfer_amount/reagents.total_volume, 1)
reagents.reaction(L, INJECT, fraction)
reagents.trans_to(L, transfer_amount)
add_logs(src, L, "injected", addition="which had [contained]")
L.visible_message("<span class='danger'>[acting_object] injects [L] with its needle!</span>", \
"<span class='userdanger'>[acting_object] injects you with its needle!</span>")
else
@@ -184,7 +193,7 @@
activate_pin(3)
return
var/tramount = Clamp(transfer_amount, 0, reagents.total_volume)
var/tramount = CLAMP(transfer_amount, 0, reagents.total_volume)
if(isliving(AM))
var/mob/living/L = AM
@@ -235,7 +244,7 @@
else
direction_mode = SYRINGE_INJECT
if(isnum(new_amount))
new_amount = Clamp(new_amount, 0, 50)
new_amount = CLAMP(new_amount, 0, 50)
transfer_amount = new_amount
/obj/item/integrated_circuit/reagent/pump/do_work()
@@ -263,8 +272,7 @@
activate_pin(2)
return
// FALSE in those procs makes mobs invalid targets.
if(!source.is_drawable(FALSE) || !target.is_injectable(FALSE))
if(!source.is_drainable() || !target.is_refillable())
return
source.reagents.trans_to(target, transfer_amount)
@@ -276,7 +284,7 @@
icon_state = "reagent_storage"
extended_desc = "This is effectively an internal beaker."
container_type = OPENCONTAINER_1
container_type = OPENCONTAINER
volume = 60
complexity = 4
@@ -285,17 +293,15 @@
"volume used" = IC_PINTYPE_NUMBER,
"self reference" = IC_PINTYPE_REF
)
activators = list()
activators = list("push ref" = IC_PINTYPE_PULSE_OUT)
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/reagent/storage/interact(mob/user)
/obj/item/integrated_circuit/reagent/storage/do_work()
set_pin_data(IC_OUTPUT, 2, WEAKREF(src))
push_data()
..()
/obj/item/integrated_circuit/reagent/storage/on_reagent_change(changetype)
set_pin_data(IC_OUTPUT, 1, reagents.total_volume)
push_data()
push_vol()
/obj/item/integrated_circuit/reagent/storage/cryo
name = "cryo reagent storage"
@@ -310,6 +316,7 @@
. = ..()
reagents.set_reacting(FALSE)
/obj/item/integrated_circuit/reagent/storage/big
name = "big reagent storage"
desc = "Stores liquid inside, and away from electrical components. Can store up to 180u."
@@ -321,6 +328,99 @@
complexity = 16
spawn_flags = IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/reagent/storage/grinder
name = "reagent grinder"
desc = "This is reagent grinder.It accepts ref to something and refines it into reagents. Can store up to 100u."
icon_state = "blender"
extended_desc = ""
inputs = list(
"target" = IC_PINTYPE_REF,
)
outputs = list(
"volume used" = IC_PINTYPE_NUMBER,
"self reference" = IC_PINTYPE_REF
)
activators = list(
"grind" = IC_PINTYPE_PULSE_IN,
"on grind" = IC_PINTYPE_PULSE_OUT,
"on fail" = IC_PINTYPE_PULSE_OUT,
"push ref" = IC_PINTYPE_PULSE_IN
)
volume = 100
power_draw_per_use = 150
complexity = 16
spawn_flags = IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/reagent/storage/grinder/do_work(ord)
switch(ord)
if(1)
grind()
if(4)
set_pin_data(IC_OUTPUT, 2, WEAKREF(src))
push_data()
/obj/item/integrated_circuit/reagent/storage/grinder/proc/grind()
if(reagents.total_volume >= reagents.maximum_volume)
activate_pin(3)
return FALSE
var/obj/item/I = get_pin_data_as_type(IC_INPUT, 1, /obj/item)
if(istype(I)&&(I.grind_results)&&check_target(I)&&(I.on_grind(src) != -1))
reagents.add_reagent_list(I.grind_results)
if(I.reagents)
I.reagents.trans_to(src, I.reagents.total_volume)
qdel(I)
activate_pin(2)
return TRUE
activate_pin(3)
return FALSE
obj/item/integrated_circuit/reagent/storage/juicer
name = "reagent juicer"
desc = "This is reagent juicer.It accepts ref to something and refines it into reagents. Can store up to 100u."
icon_state = "blender"
extended_desc = ""
inputs = list(
"target" = IC_PINTYPE_REF,
)
outputs = list(
"volume used" = IC_PINTYPE_NUMBER,
"self reference" = IC_PINTYPE_REF
)
activators = list(
"juice" = IC_PINTYPE_PULSE_IN,
"on juice" = IC_PINTYPE_PULSE_OUT,
"on fail" = IC_PINTYPE_PULSE_OUT,
"push ref" = IC_PINTYPE_PULSE_IN
)
volume = 100
power_draw_per_use = 150
complexity = 16
spawn_flags = IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/reagent/storage/juicer/do_work(ord)
switch(ord)
if(1)
juice()
if(4)
set_pin_data(IC_OUTPUT, 2, WEAKREF(src))
push_data()
/obj/item/integrated_circuit/reagent/storage/juicer/proc/juice()
if(reagents.total_volume >= reagents.maximum_volume)
activate_pin(3)
return FALSE
var/obj/item/I = get_pin_data_as_type(IC_INPUT, 1, /obj/item)
if(istype(I)&&check_target(I)&&(I.juice_results)&&(I.on_juice() != -1))
reagents.add_reagent_list(I.juice_results)
qdel(I)
activate_pin(2)
return TRUE
activate_pin(3)
return FALSE
/obj/item/integrated_circuit/reagent/storage/scan
name = "reagent scanner"
desc = "Stores liquid inside, and away from electrical components. Can store up to 60u. On pulse this beaker will send list of contained reagents."
@@ -334,17 +434,22 @@
"list of reagents" = IC_PINTYPE_LIST
)
activators = list(
"scan" = IC_PINTYPE_PULSE_IN
"scan" = IC_PINTYPE_PULSE_IN,
"push ref" = IC_PINTYPE_PULSE_IN
)
spawn_flags = IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/reagent/storage/scan/do_work()
var/cont[0]
for(var/datum/reagent/RE in reagents.reagent_list)
cont += RE.id
set_pin_data(IC_OUTPUT, 3, cont)
push_data()
/obj/item/integrated_circuit/reagent/storage/scan/do_work(ord)
switch(ord)
if(1)
var/cont[0]
for(var/datum/reagent/RE in reagents.reagent_list)
cont += RE.id
set_pin_data(IC_OUTPUT, 3, cont)
push_data()
if(2)
set_pin_data(IC_OUTPUT, 2, WEAKREF(src))
push_data()
/obj/item/integrated_circuit/reagent/filter
name = "reagent filter"
@@ -383,7 +488,7 @@
else
direction_mode = SYRINGE_INJECT
if(isnum(new_amount))
new_amount = Clamp(new_amount, 0, 50)
new_amount = CLAMP(new_amount, 0, 50)
transfer_amount = new_amount
/obj/item/integrated_circuit/reagent/filter/do_work()
@@ -415,3 +520,45 @@
activate_pin(2)
push_data()
/obj/item/integrated_circuit/reagent/storage/heater
name = "chemical heater"
desc = "Stores liquid inside, and away from electrical components. Can store up to 60u. Will heat or freeze reagents \
to target temperature, when turned on."
icon_state = "heater"
container_type = OPENCONTAINER
complexity = 8
inputs = list(
"target temperature" = IC_PINTYPE_NUMBER,
"on" = IC_PINTYPE_BOOLEAN
)
inputs_default = list("1" = 300)
outputs = list("volume used" = IC_PINTYPE_NUMBER,"self reference" = IC_PINTYPE_REF,"temperature" = IC_PINTYPE_NUMBER)
spawn_flags = IC_SPAWN_RESEARCH
var/heater_coefficient = 0.1
/obj/item/integrated_circuit/reagent/storage/heater/on_data_written()
if(get_pin_data(IC_INPUT, 2))
power_draw_idle = 30
else
power_draw_idle = 0
/obj/item/integrated_circuit/reagent/storage/heater/Initialize()
.=..()
START_PROCESSING(SScircuit, src)
/obj/item/integrated_circuit/reagent/storage/heater/Destroy()
STOP_PROCESSING(SScircuit, src)
return ..()
/obj/item/integrated_circuit/reagent/storage/heater/process()
if(power_draw_idle)
var/target_temperature = get_pin_data(IC_INPUT, 1)
if(reagents.chem_temp > target_temperature)
reagents.chem_temp += min(-1, (target_temperature - reagents.chem_temp) * heater_coefficient)
if(reagents.chem_temp < target_temperature)
reagents.chem_temp += max(1, (target_temperature - reagents.chem_temp) * heater_coefficient)
reagents.chem_temp = round(reagents.chem_temp)
reagents.handle_reactions()
set_pin_data(IC_OUTPUT, 3, reagents.chem_temp)
push_data()

Some files were not shown because too many files have changed in this diff Show More