Merge branch 'master' of https://github.com/ParadiseSS13/Paradise into turfs

# Conflicts:
#	code/game/objects/items.dm
#	code/modules/power/cable.dm
#	icons/mob/inhands/items_lefthand.dmi
#	icons/mob/inhands/items_righthand.dmi
#	icons/obj/lighting.dmi
#	paradise.dme
This commit is contained in:
Mark van Alphen
2019-04-30 19:26:17 +02:00
153 changed files with 1935 additions and 1105 deletions
+2 -5
View File
@@ -78,7 +78,7 @@ var/global/nologevent = 0
body += "<a href='?_src_=vars;Vars=[M.UID()]'>VV</a> - "
body += "[ADMIN_TP(M,"TP")] - "
if(M.client)
body += "<a href='?src=[usr.UID()];priv_msg=[M.UID()]'>PM</a> - "
body += "<a href='?src=[usr.UID()];priv_msg=[M.client.UID()]'>PM</a> - "
body += "[ADMIN_SM(M,"SM")] - "
if(ishuman(M) && M.mind)
body += "<a href='?_src_=holder;HeadsetMessage=[M.UID()]'>HM</a> -"
@@ -950,9 +950,6 @@ var/gamma_ship_location = 1 // 0 = station , 1 = space
for(var/obj/machinery/mech_bay_recharge_port/P in toArea)
P.update_recharge_turf()
for(var/obj/machinery/power/apc/A in toArea)
A.init()
if(gamma_ship_location)
gamma_ship_location = 0
else
@@ -1096,7 +1093,7 @@ var/gamma_ship_location = 1 // 0 = station , 1 = space
dat += "<tr><td><b>" + id + "</b></td>"
dat += "<td>" + ckey + "</td>"
dat += "<td><a href='?src=[UID()];force_discord_unlink=[ckey]'>Unlink</td></tr>"
dat += "</table></body></html>"
usr << browse(dat, "window=duplicates;size=500x480")
+12 -11
View File
@@ -61,7 +61,7 @@
}
function expand(id,job,name,real_name,image,key,ip,antagonist,UID,eyeUID){
function expand(id,job,name,real_name,image,key,ip,antagonist,mobUID,clientUID,eyeUID){
clearAll();
@@ -75,13 +75,13 @@
body += "</td><td align='center'>";
body += "<a href='?src=[UID()];adminplayeropts="+UID+"'>PP</a> - "
body += "<a href='?src=[UID()];adminplayeropts="+mobUID+"'>PP</a> - "
body += "<a href='?src=[UID()];shownoteckey="+key+"'>N</a> - "
body += "<a href='?_src_=vars;Vars="+UID+"'>VV</a> - "
body += "<a href='?src=[UID()];traitor="+UID+"'>TP</a> - "
body += "<a href='?src=[usr.UID()];priv_msg="+UID+"'>PM</a> - "
body += "<a href='?src=[UID()];subtlemessage="+UID+"'>SM</a> - "
body += "<a href='?src=[UID()];adminplayerobservefollow="+UID+"'>FLW</a>"
body += "<a href='?_src_=vars;Vars="+mobUID+"'>VV</a> - "
body += "<a href='?src=[UID()];traitor="+mobUID+"'>TP</a> - "
body += "<a href='?src=[usr.UID()];priv_msg="+clientUID+"'>PM</a> - "
body += "<a href='?src=[UID()];subtlemessage="+mobUID+"'>SM</a> - "
body += "<a href='?src=[UID()];adminplayerobservefollow="+mobUID+"'>FLW</a>"
if(eyeUID)
body += "|<a href='?src=[UID()];adminplayerobservefollow="+eyeUID+"'>EYE</a>"
body += "<br>"
@@ -293,6 +293,7 @@
var/mob/living/silicon/ai/A = M
if(A.client && A.eyeobj) // No point following clientless AI eyes
M_eyeUID = "[A.eyeobj.UID()]"
var/clientUID = M.client ? M.client.UID() : null
//output for each mob
dat += {"
@@ -300,7 +301,7 @@
<td align='center' bgcolor='[color]'>
<span id='notice_span[i]'></span>
<a id='link[i]'
onmouseover='expand("item[i]","[M_job]","[M_name]","[M_rname]","--unused--","[M_key]","[M.lastKnownIP]",[is_antagonist],"[M.UID()]", "[M_eyeUID]")'
onmouseover='expand("item[i]","[M_job]","[M_name]","[M_rname]","--unused--","[M_key]","[M.lastKnownIP]",[is_antagonist],"[M.UID()]","[clientUID]","[M_eyeUID]")'
>
<b id='search[i]'>[M_name] - [M_rname] - [M_key] ([M_job])</b>
</a>
@@ -371,7 +372,7 @@
dat += {"<td>[(M.client ? "[M.client]" : "No client")]</td>
<td align=center><A HREF='?src=[UID()];adminplayeropts=[M.UID()]'>X</A></td>
<td align=center><A href='?src=[usr.UID()];priv_msg=[M.UID()]'>PM</A></td>
<td align=center><A href='?src=[usr.UID()];priv_msg=[M.client ? M.client.UID() : null]'>PM</A></td>
"}
switch(is_special_character(M))
if(0)
@@ -398,7 +399,7 @@
dname = M
return {"<tr><td><a href='?src=[UID()];adminplayeropts=[M.UID()]'>[dname]</a><b>[caption]</b>[logout_status][M.stat == 2 ? " <b><font color=red>(DEAD)</font></b>" : ""]</td>
<td><A href='?src=[usr.UID()];priv_msg=[M.UID()]'>PM</A></td>[close ? "</tr>" : ""]"}
<td><A href='?src=[usr.UID()];priv_msg=[M.client ? M.client.UID() : null]'>PM</A></td>[close ? "</tr>" : ""]"}
/datum/admins/proc/check_antagonists()
if(!check_rights(R_ADMIN)) return
@@ -473,7 +474,7 @@
var/mob/M = blob.current
if(M)
dat += "<tr><td>[ADMIN_PP(M,"[M.real_name]")][M.client ? "" : " <i>(ghost)</i>"][M.stat == 2 ? " <b><font color=red>(DEAD)</font></b>" : ""]</td>"
dat += "<td><A href='?priv_msg=[M.ckey]'>PM</A></td>"
dat += "<td><A href='?priv_msg=[M.client ? M.client.UID() : null]'>PM</A></td>"
else
dat += "<tr><td><i>Blob not found!</i></td></tr>"
dat += "</table>"
+1 -1
View File
@@ -46,7 +46,7 @@
var/received_irc_pm = -99999
var/irc_admin //IRC admin that spoke with them last.
var/mute_irc = 0
var/ssd_warning_acknowledged = FALSE
////////////////////////////////////
//things that require the database//
+18 -3
View File
@@ -9,6 +9,7 @@
#define MIN_CLIENT_VERSION 0 //Just an ambiguously low version for now, I don't want to suddenly stop people playing.
//I would just like the code ready should it ever need to be used.
#define SUGGESTED_CLIENT_VERSION 511 // only integers (e.g: 510, 511) useful here. Does not properly handle minor versions (e.g: 510.58, 511.848)
#define SSD_WARNING_TIMER 30 // cycles, not seconds, so 30=60s
/*
When somebody clicks a link in game, this Topic is called first.
@@ -73,9 +74,7 @@
//Admin PM
if(href_list["priv_msg"])
var/client/C = locate(href_list["priv_msg"])
if(ismob(C)) //Old stuff can feed-in mobs instead of clients
var/mob/M = C
C = M.client
if(!C) // Might be a stealthmin ID, so pass it in straight
C = href_list["priv_msg"]
else if(C.UID() != href_list["priv_msg"])
@@ -227,6 +226,9 @@
vote_on_poll(pollid, optionid, 1)
src << browse(null, "window=playerpoll")
handle_player_polling()
if(href_list["ssdwarning"])
ssd_warning_acknowledged = TRUE
to_chat(src, "<span class='notice'>SSD warning acknowledged.</span>")
switch(href_list["action"])
if("openLink")
@@ -772,3 +774,16 @@
winset(src, "rpane.changelog", "background-color=#40628a;text-color=#FFFFFF")
else
winset(src, "rpane.changelog", "background-color=none;text-color=#000000")
/client/proc/send_ssd_warning(mob/M)
if(!config.ssd_warning)
return FALSE
if(ssd_warning_acknowledged)
return FALSE
if(M && M.player_logged < SSD_WARNING_TIMER)
return FALSE
to_chat(src, "Interacting with SSD players is against server rules unless you've ahelped first for permission. If you have, <a href='byond://?src=[UID()];ssdwarning=accepted'>confirm that</A> and proceed.")
return TRUE
#undef SSD_WARNING_TIMER
-32
View File
@@ -629,38 +629,6 @@ BLIND // can't see anything
..()
/obj/item/clothing/under/attack_hand(mob/user as mob)
//only forward to the attached accessory if the clothing is equipped (not in a storage)
if(accessories.len && src.loc == user)
for(var/obj/item/clothing/accessory/A in accessories)
A.attack_hand(user)
return
if(ishuman(usr) && src.loc == user) //make it harder to accidentally undress yourself
return
..()
/obj/item/clothing/under/MouseDrop(obj/over_object as obj)
if(ishuman(usr))
//makes sure that the clothing is equipped so that we can't drag it into our hand from miles away.
if(!(src.loc == usr))
return
if(!( usr.restrained() ) && !( usr.stat ) && ( over_object ))
if(!usr.canUnEquip(src))
to_chat(usr, "[src] appears stuck on you!")
return
switch(over_object.name)
if("r_hand")
usr.unEquip(src)
usr.put_in_r_hand(src)
if("l_hand")
usr.unEquip(src)
usr.put_in_l_hand(src)
src.add_fingerprint(usr)
return
return
/obj/item/clothing/under/examine(mob/user)
..(user)
switch(src.sensor_mode)
+2 -2
View File
@@ -117,8 +117,8 @@
/datum/crafting_recipe/floorbot
name = "Floorbot"
result = /mob/living/simple_animal/bot/floorbot
reqs = list(/obj/item/storage/toolbox/mechanical = 1,
/obj/item/stack/tile/plasteel = 1,
reqs = list(/obj/item/storage/toolbox = 1,
/obj/item/stack/tile/plasteel = 10,
/obj/item/assembly/prox_sensor = 1,
/obj/item/robot_parts/r_arm = 1)
time = 40
+13 -1
View File
@@ -1773,4 +1773,16 @@
/obj/item/clothing/gloves/ring/fluff/benjaminfallout //Benjaminfallout: Pretzel Brassheart
name = "Pretzel's Ring"
desc = "A small platinum ring with a large light blue diamond. Engraved inside the band are the words: 'To my lovely Pristine Princess. Forever yours, Savinien.'"
icon_state = "benjaminfallout_ring"
icon_state = "benjaminfallout_ring"
/obj/item/clothing/under/fluff/voxbodysuit //Gangelwaefre: Kikeri
name = "Vox Bodysuit"
desc = "A shimmering bodysuit custom-fit to a vox. Has shorts sewn in."
lefthand_file = 'icons/mob/inhands/fluff_lefthand.dmi'
righthand_file = 'icons/mob/inhands/fluff_righthand.dmi'
icon = 'icons/mob/inhands/fluff_righthand.dmi'
icon_state = "voxbodysuit"
item_state = "voxbodysuit"
item_color = "voxbodysuit"
body_parts_covered = HEAD|UPPER_TORSO|LOWER_TORSO|LEGS|ARMS
species_fit = list("Vox")
+3 -1
View File
@@ -6,6 +6,7 @@
event_announcement.Announce("Confirmed outbreak of level 5 biohazard aboard [station_name()]. All personnel must contain the outbreak.", "Biohazard Alert", 'sound/AI/outbreak5.ogg')
/datum/event/blob/start()
processing = FALSE //so it won't fire again in next tick
var/turf/T = pick(blobstart)
if(!T)
return kill()
@@ -23,4 +24,5 @@
B.key = M.key
to_chat(B, "<span class='userdanger'>You are now a mouse, infected with blob spores. Find somewhere isolated... before you burst and become the blob! Use ventcrawl (alt-click on vents) to move around.</span>")
var/image/alert_overlay = image('icons/mob/blob.dmi', "blank_blob")
notify_ghosts("Infected Mouse has appeared in [get_area(B)].", source = B, alert_overlay = alert_overlay)
notify_ghosts("Infected Mouse has appeared in [get_area(B)].", source = B, alert_overlay = alert_overlay)
processing = TRUE // Let it naturally end, if it runs successfully
+2 -2
View File
@@ -15,8 +15,8 @@
var/productivity = 0
var/max_items = 40
var/datum/research/files
var/list/show_categories = list("Food", "Botany Chemicals", "Leather and Cloth")
var/list/timesFiveCategories = list("Food", "Botany Chemicals")
var/list/show_categories = list("Food", "Botany Chemicals", "Organic Materials", "Leather and Cloth")
var/list/timesFiveCategories = list("Food", "Botany Chemicals", "Organic Materials")
/obj/machinery/biogenerator/New()
..()
+4 -5
View File
@@ -397,13 +397,11 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
to_chat(usr, "Not when you're not dead!")
return
usr.verbs -= /mob/dead/observer/proc/dead_tele
spawn(30)
usr.verbs += /mob/dead/observer/proc/dead_tele
var/area/A = input("Area to jump to", "BOOYEA") as null|anything in ghostteleportlocs
var/area/thearea = ghostteleportlocs[A]
if(!thearea) return
if(!thearea)
return
var/list/L = list()
for(var/turf/T in get_area_turfs(thearea.type))
@@ -411,6 +409,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
if(!L || !L.len)
to_chat(usr, "<span class='warning'>No area available.</span>")
return
usr.forceMove(pick(L))
following = null
@@ -38,6 +38,7 @@
regenerate_icons() // Make sure the inventory updates
handle_ghosted()
handle_ssd()
/mob/living/carbon/human/proc/handle_ghosted()
if(player_ghosted > 0 && stat == CONSCIOUS && job && !restrained())
@@ -48,6 +49,22 @@
if(player_ghosted % 150 == 0)
force_cryo_human(src)
/mob/living/carbon/human/proc/handle_ssd()
if(player_logged > 0 && stat != DEAD && job)
player_logged++
if(istype(loc, /obj/machinery/cryopod))
return
if(config.auto_cryo_ssd_mins && (player_logged >= (config.auto_cryo_ssd_mins * 30)) && player_logged % 30 == 0)
var/turf/T = get_turf(src)
if(!is_station_level(T.z))
return
var/area/A = get_area(src)
if(cryo_ssd(src))
var/obj/effect/portal/P = new /obj/effect/portal(T, null, null, 40)
P.name = "NT SSD Teleportation Portal"
if(A.fast_despawn)
force_cryo_human(src)
/mob/living/carbon/human/calculate_affecting_pressure(var/pressure)
..()
var/pressure_difference = abs( pressure - ONE_ATMOSPHERE )
+6
View File
@@ -42,3 +42,9 @@
animation.icon = 'icons/mob/mob.dmi'
animation.master = src
QDEL_IN(animation, 15)
/mob/living/silicon/death(gibbed)
. = ..()
if(!gibbed)
if(death_sound)
playsound(get_turf(src), death_sound, 200, 1)
@@ -28,7 +28,7 @@ var/datum/paiController/paiController // Global handler for pAI candidates
if(candidate)
if(!istype(candidate))
message_admins("Warning: possible href exploit by [key_name(usr)] (paiController/Topic, candidate is not a pAI)")
message_admins("Warning: possible href exploit by [key_name_admin(usr)] (paiController/Topic, candidate is not a pAI)")
log_debug("Warning: possible href exploit by [key_name(usr)] (paiController/Topic, candidate is not a pAI)")
return
@@ -55,7 +55,7 @@ var/datum/paiController/paiController // Global handler for pAI candidates
pai_candidates -= candidate
usr << browse(null, "window=findPai")
return
if("signup" in href_list)
var/mob/dead/observer/O = locate(href_list["signup"])
@@ -71,8 +71,8 @@ var/datum/paiController/paiController // Global handler for pAI candidates
if(candidate)
if(candidate.key && usr.key && candidate.key != usr.key)
message_admins("Warning: possible href exploit by [key_name(usr)] (paiController/Topic, candidate and usr are different mobs)")
log_debug("Warning: possible href exploit by [key_name(usr)] (paiController/Topic, candidate and usr are different mobs)")
message_admins("Warning: possible href exploit by [key_name_admin(usr)] (paiController/Topic, candidate and usr have different keys)")
log_debug("Warning: possible href exploit by [key_name(usr)] (paiController/Topic, candidate and usr have different keys)")
return
if(href_list["new"])
@@ -248,9 +248,9 @@
death()
/mob/living/silicon/robot/drone/proc/full_law_reset()
clear_supplied_laws()
clear_inherent_laws()
clear_ion_laws()
clear_supplied_laws(TRUE)
clear_inherent_laws(TRUE)
clear_ion_laws(TRUE)
laws = new /datum/ai_laws/drone
//Reboot procs.
@@ -19,6 +19,7 @@
var/speak_exclamation = "declares"
var/speak_query = "queries"
var/pose //Yes, now AIs can pose too.
var/death_sound = 'sound/voice/borg_deathsound.ogg'
//var/sensor_mode = 0 //Determines the current HUD.
@@ -210,23 +210,29 @@ var/robot_arm = /obj/item/robot_parts/l_arm
throw_range = 5
w_class = WEIGHT_CLASS_NORMAL
var/created_name = "Floorbot"
var/toolbox = /obj/item/storage/toolbox/mechanical
var/toolbox_color = "" //Blank for blue, r for red, y for yellow, etc.
/obj/item/toolbox_tiles_sensor
/obj/item/toolbox_tiles/sensor
desc = "It's a toolbox with tiles sticking out the top and a sensor attached"
name = "tiles, toolbox and sensor arrangement"
icon = 'icons/obj/aibots.dmi'
icon_state = "toolbox_tiles_sensor"
force = 3
throwforce = 10
throw_speed = 2
throw_range = 5
w_class = WEIGHT_CLASS_NORMAL
var/created_name = "Floorbot"
/obj/item/storage/toolbox/mechanical/attackby(obj/item/stack/tile/plasteel/T, mob/user, params)
/obj/item/storage/toolbox/attackby(obj/item/stack/tile/plasteel/T, mob/user, params)
var/list/allowed_toolbox = list(/obj/item/storage/toolbox/emergency, //which toolboxes can be made into floorbots
/obj/item/storage/toolbox/electrical,
/obj/item/storage/toolbox/mechanical,
/obj/item/storage/toolbox/green,
/obj/item/storage/toolbox/syndicate,
/obj/item/storage/toolbox/fakesyndi)
if(!istype(T, /obj/item/stack/tile/plasteel))
..()
return
if(!is_type_in_list(src, allowed_toolbox))
return
if(type == /obj/item/storage/toolbox/green/memetic)
return
if(contents.len >= 1)
to_chat(user, "<span class='warning'>They won't fit in, as there is already stuff inside.</span>")
return
@@ -234,6 +240,23 @@ var/robot_arm = /obj/item/robot_parts/l_arm
if(user.s_active)
user.s_active.close(user)
var/obj/item/toolbox_tiles/B = new /obj/item/toolbox_tiles
B.toolbox = type
switch(B.toolbox)
if(/obj/item/storage/toolbox/mechanical/old)
B.toolbox_color = "ob"
if(/obj/item/storage/toolbox/emergency)
B.toolbox_color = "r"
if(/obj/item/storage/toolbox/emergency/old)
B.toolbox_color = "or"
if(/obj/item/storage/toolbox/electrical)
B.toolbox_color = "y"
if(/obj/item/storage/toolbox/green)
B.toolbox_color = "g"
if(/obj/item/storage/toolbox/syndicate)
B.toolbox_color = "s"
if(/obj/item/storage/toolbox/fakesyndi)
B.toolbox_color = "s"
B.icon_state = "[B.toolbox_color]toolbox_tiles"
user.put_in_hands(B)
to_chat(user, "<span class='notice'>You add the tiles into the empty toolbox. They protrude from the top.</span>")
user.unEquip(src, 1)
@@ -246,8 +269,10 @@ var/robot_arm = /obj/item/robot_parts/l_arm
..()
if(isprox(W))
qdel(W)
var/obj/item/toolbox_tiles_sensor/B = new /obj/item/toolbox_tiles_sensor()
var/obj/item/toolbox_tiles/sensor/B = new /obj/item/toolbox_tiles/sensor()
B.created_name = created_name
B.toolbox_color = src.toolbox_color
B.icon_state = "[B.toolbox_color]toolbox_tiles_sensor"
user.put_in_hands(B)
to_chat(user, "<span class='notice'>You add the sensor to the toolbox and tiles.</span>")
user.unEquip(src, 1)
@@ -263,12 +288,11 @@ var/robot_arm = /obj/item/robot_parts/l_arm
created_name = t
log_game("[key_name(user)] has renamed a robot to [t]")
/obj/item/toolbox_tiles_sensor/attackby(obj/item/W, mob/user, params)
/obj/item/toolbox_tiles/sensor/attackby(obj/item/W, mob/user, params)
..()
if(istype(W, /obj/item/robot_parts/l_arm) || istype(W, /obj/item/robot_parts/r_arm))
qdel(W)
var/turf/T = get_turf(user.loc)
var/mob/living/simple_animal/bot/floorbot/A = new /mob/living/simple_animal/bot/floorbot(T)
var/mob/living/simple_animal/bot/floorbot/A = new(drop_location(), toolbox_color)
A.name = created_name
A.robot_arm = W.type
to_chat(user, "<span class='notice'>You add the robot arm to the odd looking toolbox assembly. Boop beep!</span>")
@@ -287,10 +311,9 @@ var/robot_arm = /obj/item/robot_parts/l_arm
//Medbot Assembly
/obj/item/storage/firstaid/attackby(obj/item/I, mob/user, params)
if(!istype(I, /obj/item/robot_parts/l_arm) && !istype(I, /obj/item/robot_parts/r_arm))
return ..()
return ..()
else
robot_arm = I.type
//Making a medibot!
if(contents.len)
@@ -298,7 +321,7 @@ var/robot_arm = /obj/item/robot_parts/l_arm
return
var/obj/item/firstaid_arm_assembly/A = new /obj/item/firstaid_arm_assembly(loc, med_bot_skin)
A.req_one_access = req_one_access
A.syndicate_aligned = syndicate_aligned
A.treatment_oxy = treatment_oxy
@@ -492,7 +515,7 @@ var/robot_arm = /obj/item/robot_parts/l_arm
//General Griefsky
else if((istype(I, /obj/item/wrench)) && (build_step == 3))
else if((istype(I, /obj/item/wrench)) && (build_step == 3))
var/obj/item/griefsky_assembly/A = new /obj/item/griefsky_assembly
user.put_in_hands(A)
to_chat(user, "<span class='notice'>You adjust the arm slots for extra weapons!.</span>")
@@ -516,12 +539,12 @@ var/robot_arm = /obj/item/robot_parts/l_arm
build_step++
to_chat(user, "<span class='notice'>You add an energy sword to [src]!.</span>")
qdel(I)
else if((istype(I, /obj/item/melee/energy/sword)) && (build_step == 3))
if(!user.unEquip(I))
return
to_chat(user, "<span class='notice'>You complete General Griefsky!.</span>")
var/mob/living/simple_animal/bot/secbot/griefsky/S = new /mob/living/simple_animal/bot/secbot/griefsky
var/mob/living/simple_animal/bot/secbot/griefsky/S = new /mob/living/simple_animal/bot/secbot/griefsky
S.forceMove(get_turf(src))
qdel(I)
qdel(src)
@@ -537,7 +560,7 @@ var/robot_arm = /obj/item/robot_parts/l_arm
if(!user.unEquip(I))
return
to_chat(user, "<span class='notice'>You complete Genewul Giftskee!.</span>")
var/mob/living/simple_animal/bot/secbot/griefsky/toy/S = new /mob/living/simple_animal/bot/secbot/griefsky/toy
var/mob/living/simple_animal/bot/secbot/griefsky/toy/S = new /mob/living/simple_animal/bot/secbot/griefsky/toy
S.forceMove(get_turf(src))
qdel(I)
qdel(src)
@@ -5,7 +5,7 @@
icon = 'icons/obj/aibots.dmi'
icon_state = "floorbot0"
density = 0
anchored = 0
anchored = FALSE
health = 25
maxHealth = 25
@@ -32,6 +32,7 @@
var/max_targets = 50
var/turf/target
var/oldloc = null
var/toolbox_color = ""
#define HULL_BREACH 1
#define BRIDGE_MODE 2
@@ -40,12 +41,16 @@
#define REPLACE_TILE 5
#define TILE_EMAG 6
/mob/living/simple_animal/bot/floorbot/New()
/mob/living/simple_animal/bot/floorbot/New(mapload, new_toolbox_color)
..()
toolbox_color = new_toolbox_color
update_icon()
var/datum/job/engineer/J = new/datum/job/engineer
access_card.access += J.get_access()
prev_access = access_card.access
if(toolbox_color == "s")
health = 50
maxHealth = 50
/mob/living/simple_animal/bot/floorbot/bot_reset()
..()
@@ -53,7 +58,7 @@
oldloc = null
ignore_list = list()
nagged = 0
anchored = 0
anchored = FALSE
update_icon()
/mob/living/simple_animal/bot/floorbot/set_custom_texts()
@@ -235,7 +240,7 @@
repair(target)
else if(emagged == 2 && istype(target,/turf/simulated/floor))
var/turf/simulated/floor/F = target
anchored = 1
anchored = TRUE
mode = BOT_REPAIRING
if(prob(90))
F.break_tile_to_plating()
@@ -244,7 +249,7 @@
audible_message("<span class='danger'>[src] makes an excited booping sound.</span>")
spawn(50)
amount ++
anchored = 0
anchored = FALSE
mode = BOT_IDLE
target = null
path = list()
@@ -272,11 +277,11 @@
if(HULL_BREACH) //The most common job, patching breaches in the station's hull.
if(is_hull_breach(scan_target)) //Ensure that the targeted space turf is actually part of the station, and not random space.
result = scan_target
anchored = 1 //Prevent the floorbot being blown off-course while trying to reach a hull breach.
anchored = TRUE //Prevent the floorbot being blown off-course while trying to reach a hull breach.
if(BRIDGE_MODE) //Only space turfs in our chosen direction are considered.
if(get_dir(src, scan_target) == targetdirection)
result = scan_target
anchored = 1
anchored = TRUE
if(REPLACE_TILE)
F = scan_target
if(istype(F, /turf/simulated/floor/plating)) //The floor must not already have a tile.
@@ -306,9 +311,10 @@
mode = BOT_IDLE
target = null
return
anchored = 1
icon_state = "floorbot-c"
anchored = TRUE
icon_state = "[toolbox_color]floorbot-c"
if(istype(target_turf, /turf/space/)) //If we are fixing an area not part of pure space, it is
icon_state = "[toolbox_color]floorbot-c"
visible_message("<span class='notice'>[targetdirection ? "[src] begins installing a bridge plating." : "[src] begins to repair the hole."] </span>")
mode = BOT_REPAIRING
spawn(50)
@@ -320,11 +326,12 @@
mode = BOT_IDLE
amount -= 1
update_icon()
anchored = 0
anchored = FALSE
target = null
else
var/turf/simulated/floor/F = target_turf
mode = BOT_REPAIRING
icon_state = "[toolbox_color]floorbot-c"
visible_message("<span class='notice'>[src] begins repairing the floor.</span>")
spawn(50)
if(mode == BOT_REPAIRING)
@@ -334,7 +341,7 @@
mode = BOT_IDLE
amount -= 1
update_icon()
anchored = 0
anchored = FALSE
target = null
/mob/living/simple_animal/bot/floorbot/proc/eattile(obj/item/stack/tile/plasteel/T)
@@ -380,9 +387,9 @@
/mob/living/simple_animal/bot/floorbot/update_icon()
if(amount > 0)
icon_state = "floorbot[on]"
icon_state = "[toolbox_color]floorbot[on]"
else
icon_state = "floorbot[on]e"
icon_state = "[toolbox_color]floorbot[on]e"
/mob/living/simple_animal/bot/floorbot/explode()
on = 0
+2 -2
View File
@@ -19,10 +19,10 @@
spawn() alert("You have logged in already with another key this round, please log out of this one NOW or risk being banned!")
if(matches)
if(M.client)
message_admins("<font color='red'><B>Notice: </B><font color='blue'><A href='?src=[usr.UID()];priv_msg=[src.UID()]'>[key_name_admin(src)]</A> has the same [matches] as <A href='?src=[usr.UID()];priv_msg=[M.UID()]'>[key_name_admin(M)]</A>.</font>", 1)
message_admins("<font color='red'><B>Notice: </B><font color='blue'><A href='?src=[usr.UID()];priv_msg=[src.client.UID()]'>[key_name_admin(src)]</A> has the same [matches] as <A href='?src=[usr.UID()];priv_msg=[M.client.UID()]'>[key_name_admin(M)]</A>.</font>", 1)
log_adminwarn("Notice: [key_name(src)] has the same [matches] as [key_name(M)].")
else
message_admins("<font color='red'><B>Notice: </B><font color='blue'><A href='?src=[usr.UID()];priv_msg=[src.UID()]'>[key_name_admin(src)]</A> has the same [matches] as [key_name_admin(M)] (no longer logged in). </font>", 1)
message_admins("<font color='red'><B>Notice: </B><font color='blue'><A href='?src=[usr.UID()];priv_msg=[src.client.UID()]'>[key_name_admin(src)]</A> has the same [matches] as [key_name_admin(M)] (no longer logged in). </font>", 1)
log_adminwarn("Notice: [key_name(src)] has the same [matches] as [key_name(M)] (no longer logged in).")
/mob/Login()
+9 -4
View File
@@ -901,13 +901,18 @@ var/list/slot_equipment_priority = list( \
/mob/MouseDrop(mob/M as mob)
..()
if(M != usr) return
if(isliving(M)) // Ewww
if(isliving(M))
var/mob/living/L = M
if(L.mob_size <= MOB_SIZE_SMALL)
return // Stops pAI drones and small mobs (borers, parrots, crabs) from stripping people. --DZD
if(!M.can_strip) return
if(usr == src) return
if(!Adjacent(usr)) return
if(!M.can_strip)
return
if(usr == src)
return
if(!Adjacent(usr))
return
if(isLivingSSD(src) && M.client && M.client.send_ssd_warning(src))
return
show_inv(usr)
/mob/proc/can_use_hands()
@@ -13,10 +13,10 @@
if(battery_module && battery_module.battery && battery_module.battery.charge)
var/obj/item/stock_parts/cell/cell = battery_module.battery
if(cell.use(amount * CELLRATE))
if(cell.use(amount * GLOB.CELLRATE))
return TRUE
else // Discharge the cell anyway.
cell.use(min(amount*CELLRATE, cell.charge))
cell.use(min(amount*GLOB.CELLRATE, cell.charge))
return FALSE
return FALSE
@@ -137,18 +137,17 @@
return 1
return -1
/datum/computer_file/program/card_mod/proc/format_jobs(list/jobs)
/datum/computer_file/program/card_mod/proc/format_jobs(list/jobs, targetrank, list/jobformats)
var/obj/item/computer_hardware/card_slot/card_slot = computer.all_components[MC_CARD]
if(!card_slot || !card_slot.stored_card)
return null
var/obj/item/card/id/id_card = card_slot.stored_card
var/list/formatted = list()
for(var/job in jobs)
formatted.Add(list(list(
"display_name" = replacetext(job, "&nbsp", " "),
"target_rank" = id_card && id_card.assignment ? id_card.assignment : "Unassigned",
"job" = job)))
"target_rank" = targetrank,
"job" = job,
"jlinkformat" = jobformats[job] ? jobformats[job] : null)))
return formatted
@@ -225,11 +224,12 @@
var/temp_t = sanitize(copytext(input("Enter a custom job assignment.","Assignment"),1,MAX_MESSAGE_LEN))
//let custom jobs function as an impromptu alt title, mainly for sechuds
if(temp_t && modify)
SSjobs.log_job_transfer(modify.registered_name, modify.getRankAndAssignment(), temp_t, scan.registered_name)
modify.assignment = temp_t
log_game("[key_name(usr)] has given \"[modify.registered_name]\" the custom job title \"[temp_t]\".")
else
var/list/access = list()
if(is_centcom)
if(is_centcom && islist(get_centcom_access(t1)))
access = get_centcom_access(t1)
else
var/datum/job/jobdatum
@@ -249,6 +249,16 @@
if(t1 == "Civilian")
message_admins("[key_name_admin(usr)] has reassigned \"[modify.registered_name]\" from \"[jobnamedata]\" to \"[t1]\".")
SSjobs.log_job_transfer(modify.registered_name, jobnamedata, t1, scan.registered_name)
SSjobs.slot_job_transfer(modify.rank, t1)
var/mob/living/carbon/human/H = modify.getPlayer()
if(istype(H))
if(jobban_isbanned(H, t1))
message_admins("[ADMIN_FULLMONTY(H)] has been assigned the job [t1], in possible violation of their job ban.")
if(H.mind)
H.mind.playtime_role = t1
modify.access = access
modify.assignment = t1
modify.rank = t1
@@ -271,6 +281,18 @@
if("PRG_mode")
mode = text2num(href_list["mode_target"])
if("PRG_wipe_my_logs")
if(is_authenticated(usr) && is_centcom)
var/delcount = SSjobs.delete_log_records(scan.registered_name, FALSE)
if(delcount)
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
if("PRG_wipe_all_logs")
if(is_authenticated(usr))
var/delcount = SSjobs.delete_log_records(scan.registered_name, TRUE)
if(delcount)
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
if("PRG_print")
if(!printing && computer)
printing = 1
@@ -312,6 +334,7 @@
var/jobnamedata = modify.getRankAndAssignment()
log_game("[key_name(usr)] has terminated the employment of \"[modify.registered_name]\" the \"[jobnamedata]\".")
message_admins("[key_name_admin(usr)] has terminated the employment of \"[modify.registered_name]\" the \"[jobnamedata]\".")
SSjobs.log_job_transfer(modify.registered_name, jobnamedata, "Terminated", scan.registered_name)
modify.assignment = "Terminated"
modify.access = list()
callHook("terminate_employee", list(modify))
@@ -398,6 +421,7 @@
data["target_owner"] = modify && modify.registered_name ? modify.registered_name : "-----"
data["target_rank"] = get_target_rank()
data["scan_name"] = scan ? scan.name : "-----"
data["scan_owner"] = scan && scan.registered_name ? scan.registered_name : null
data["authenticated"] = is_authenticated(user)
data["has_modify"] = !!modify
data["account_number"] = modify ? modify.associated_account_number : null
@@ -405,14 +429,17 @@
data["all_centcom_access"] = null
data["regions"] = null
data["engineering_jobs"] = format_jobs(engineering_positions)
data["medical_jobs"] = format_jobs(medical_positions)
data["science_jobs"] = format_jobs(science_positions)
data["security_jobs"] = format_jobs(security_positions)
data["support_jobs"] = format_jobs(support_positions)
data["civilian_jobs"] = format_jobs(civilian_positions)
data["special_jobs"] = format_jobs(whitelisted_positions)
data["centcom_jobs"] = format_jobs(get_all_centcom_jobs())
var/list/job_formats = SSjobs.format_jobs_for_id_computer(modify)
data["top_jobs"] = format_jobs(list("Captain", "Custom"), data["target_rank"], job_formats)
data["engineering_jobs"] = format_jobs(engineering_positions, data["target_rank"], job_formats)
data["medical_jobs"] = format_jobs(medical_positions, data["target_rank"], job_formats)
data["science_jobs"] = format_jobs(science_positions, data["target_rank"], job_formats)
data["security_jobs"] = format_jobs(security_positions, data["target_rank"], job_formats)
data["support_jobs"] = format_jobs(support_positions, data["target_rank"], job_formats)
data["civilian_jobs"] = format_jobs(civilian_positions, data["target_rank"], job_formats)
data["special_jobs"] = format_jobs(whitelisted_positions, data["target_rank"], job_formats)
data["centcom_jobs"] = format_jobs(get_all_centcom_jobs(), data["target_rank"], job_formats)
data["card_skins"] = format_card_skins(get_station_card_skins())
data["job_slots"] = format_job_slots()
@@ -423,6 +450,9 @@
data["cooldown_mins"] = mins
data["cooldown_secs"] = (seconds < 10) ? "0[seconds]" : seconds
if(mode == 3 && is_authenticated(user))
data["id_change_html"] = SSjobs.fetch_transfer_record_html(is_centcom)
if(modify)
data["current_skin"] = modify.icon_state
@@ -39,7 +39,7 @@
data["powermonitor"] = attached ? TRUE : FALSE
if(attached)
var/datum/powernet/powernet = attached.get_powernet()
var/datum/powernet/powernet = attached.powernet
data["poweravail"] = powernet.avail
data["powerload"] = powernet.viewload
data["powerdemand"] = powernet.load
@@ -20,7 +20,7 @@
return
if(use_power(charge_rate, charging=1))
holder.give_power(charge_rate * CELLRATE)
holder.give_power(charge_rate * GLOB.CELLRATE)
/obj/item/computer_hardware/recharger/APC
+3 -3
View File
@@ -131,13 +131,13 @@ obj/item/clipboard/proc/penPlacement(mob/user, obj/item/pen/P, placing)
else
penPlacement(usr, containedpen, FALSE)
else if(href_list["remove"])
var/obj/item/P = locate(href_list["remove"])
var/obj/item/P = locate(href_list["remove"]) in src
if(isPaperwork(P))
usr.put_in_hands(P)
to_chat(usr, "<span class='notice'>You remove [P] from [src].</span>")
checkTopPaper() //So we don't accidentally make the top sheet not be on the clipboard
else if(href_list["viewOrWrite"])
var/obj/item/P = locate(href_list["viewOrWrite"])
var/obj/item/P = locate(href_list["viewOrWrite"]) in src
if(!isPaperwork(P))
return
if(is_pen(I) && isPaperwork(P) != PHOTO) //Because you can't write on photos that aren't in your hand
@@ -148,7 +148,7 @@ obj/item/clipboard/proc/penPlacement(mob/user, obj/item/pen/P, placing)
var/obj/item/photo/Ph = P
Ph.show(usr)
else if(href_list["topPaper"])
var/obj/item/P = locate(href_list["topPaper"])
var/obj/item/P = locate(href_list["topPaper"]) in src
if(P == toppaper)
return
to_chat(usr, "<span class='notice'>You flick the pages so that [P] is on top.</span>")
+38 -42
View File
@@ -46,7 +46,6 @@
name = "area power controller"
desc = "A control terminal for the area electrical systems."
icon_state = "apc0"
anchored = 1
use_power = NO_POWER_USE
req_access = list(access_engine_equip)
siemens_strength = 1
@@ -55,7 +54,7 @@
var/areastring = null
var/obj/item/stock_parts/cell/cell
var/start_charge = 90 // initial cell charge %
var/cell_type = 2500
var/cell_type = 2500 //Base cell has 2500 capacity. Enter the path of a different cell you want to use. cell determines charge rates, max capacity, ect. These can also be changed with other APC vars, but isn't recommended to minimize the risk of accidental usage of dirty editted APCs
var/opened = 0 //0=closed, 1=opened, 2=cover removed
var/shorted = 0
var/lighting = 3
@@ -140,40 +139,35 @@
/obj/machinery/power/apc/connect_to_network()
//Override because the APC does not directly connect to the network; it goes through a terminal.
//The terminal is what the power computer looks for anyway.
if(!terminal)
make_terminal()
if(terminal)
terminal.connect_to_network()
/obj/machinery/power/apc/New(turf/loc, var/ndir, var/building=0)
/obj/machinery/power/apc/New(turf/loc, ndir, building = 0)
if(!armor)
armor = list(melee = 20, bullet = 20, laser = 10, energy = 100, bomb = 30, bio = 100, rad = 100)
..()
GLOB.apcs += src
GLOB.apcs = sortAtom(GLOB.apcs)
wires = new(src)
wires = new(src)
// offset 24 pixels in direction of dir
// this allows the APC to be embedded in a wall, yet still inside an area
if(building)
dir = ndir
src.tdir = dir // to fix Vars bug
dir = SOUTH
setDir(ndir)
tdir = dir // to fix Vars bug
setDir(SOUTH)
pixel_x = (src.tdir & 3)? 0 : (src.tdir == 4 ? 24 : -24)
pixel_y = (src.tdir & 3)? (src.tdir ==1 ? 24 : -24) : 0
if(building==0)
init()
else
if(building)
area = get_area(src)
area.apc |= src
opened = 1
operating = 0
name = "[area.name] APC"
stat |= MAINT
src.update_icon()
spawn(5)
src.update()
update_icon()
addtimer(CALLBACK(src, .proc/update), 5)
/obj/machinery/power/apc/Destroy()
GLOB.apcs -= src
@@ -196,14 +190,17 @@
// create a terminal object at the same position as original turf loc
// wires will attach to this
terminal = new/obj/machinery/power/terminal(src.loc)
terminal.dir = tdir
terminal.setDir(tdir)
terminal.master = src
/obj/machinery/power/apc/proc/init()
/obj/machinery/power/apc/Initialize(mapload)
. = ..()
if(!mapload)
return
has_electronics = 2 //installed and secured
// is starting with a power cell installed, create it and set its charge level
if(cell_type)
src.cell = new/obj/item/stock_parts/cell(src)
cell = new/obj/item/stock_parts/cell(src)
cell.maxcharge = cell_type // cell_type is maximum charge (old default was 1000 or 2500 (values one and two respectively)
cell.charge = start_charge * cell.maxcharge / 100 // (convert percentage to actual value)
@@ -222,12 +219,12 @@
area = get_area_name(areastring)
name = "\improper [area.name] APC"
area.apc |= src
update_icon()
make_terminal()
spawn(5)
src.update()
addtimer(CALLBACK(src, .proc/update), 5)
/obj/machinery/power/apc/examine(mob/user)
if(..(user, 1))
@@ -1087,14 +1084,9 @@
else
return 0
//Returns 1 if the APC should attempt to charge
/obj/machinery/power/apc/proc/attempt_charging()
return (chargemode && charging == 1 && operating)
/obj/machinery/power/apc/draw_power(var/amount)
/obj/machinery/power/apc/add_load(amount)
if(terminal && terminal.powernet)
return terminal.powernet.draw_power(amount)
return 0
terminal.add_load(amount)
/obj/machinery/power/apc/avail()
if(terminal)
@@ -1103,7 +1095,6 @@
return 0
/obj/machinery/power/apc/process()
if(stat & (BROKEN|MAINT))
return
if(!area.requires_power)
@@ -1139,18 +1130,21 @@
if(cell && !shorted)
// draw power from cell as before to power the area
var/cellused = min(cell.charge, CELLRATE * lastused_total) // clamp deduction to a max, amount left in cell
var/cellused = min(cell.charge, GLOB.CELLRATE * lastused_total) // clamp deduction to a max, amount left in cell
cell.use(cellused)
if(excess > lastused_total) // if power excess recharge the cell
// by the same amount just used
var/draw = draw_power(cellused/CELLRATE) // draw the power needed to charge this cell
cell.give(draw * CELLRATE)
cell.give(cellused)
add_load(cellused/GLOB.CELLRATE) // add the load used to recharge the cell
else // no excess, and not enough per-apc
if( (cell.charge/CELLRATE + excess) >= lastused_total) // can we draw enough from cell+grid to cover last usage?
var/draw = draw_power(excess)
cell.charge = min(cell.maxcharge, cell.charge + CELLRATE * draw) //recharge with what we can
if((cell.charge/GLOB.CELLRATE + excess) >= lastused_total) // can we draw enough from cell+grid to cover last usage?
cell.charge = min(cell.maxcharge, cell.charge + GLOB.CELLRATE * excess) //recharge with what we can
add_load(excess) // so draw what we can from the grid
charging = 0
else // not enough power available to run the last tick!
charging = 0
chargecount = 0
@@ -1203,14 +1197,12 @@
autoflag = 0
// now trickle-charge the cell
if(src.attempt_charging())
if(chargemode && charging == 1 && operating)
if(excess > 0) // check to make sure we have enough to charge
// Max charge is capped to % per second constant
var/ch = min(excess*CELLRATE, cell.maxcharge*CHARGELEVEL)
ch = draw_power(ch/CELLRATE) // Removes the power we're taking from the grid
cell.give(ch*CELLRATE) // actually recharge the cell
var/ch = min(excess*GLOB.CELLRATE, cell.maxcharge*GLOB.CHARGELEVEL)
add_load(ch/GLOB.CELLRATE) // Removes the power we're taking from the grid
cell.give(ch) // actually recharge the cell
else
charging = 0 // stop charging
@@ -1223,12 +1215,12 @@
if(chargemode)
if(!charging)
if(excess > cell.maxcharge*CHARGELEVEL)
if(excess > cell.maxcharge*GLOB.CHARGELEVEL)
chargecount++
else
chargecount = 0
if(chargecount >= 10)
if(chargecount == 10)
chargecount = 0
charging = 1
@@ -1295,9 +1287,13 @@
lighting = 0
equipment = 0
environ = 0
update_icon()
update()
spawn(600)
equipment = 3
environ = 3
update_icon()
update()
..()
/obj/machinery/power/apc/ex_act(severity)
+140 -112
View File
@@ -59,17 +59,16 @@ By design, d1 is the smallest direction and d2 is the highest
/obj/structure/cable/white
color = COLOR_WHITE
/obj/structure/cable/New()
..()
/obj/structure/cable/Initialize(mapload)
. = ..()
// ensure d1 & d2 reflect the icon_state for entering and exiting cable
var/dash = findtext(icon_state, "-")
d1 = text2num(copytext(icon_state, 1, dash))
d2 = text2num(copytext(icon_state, dash+1 ))
d1 = text2num(copytext( icon_state, 1, dash ))
d2 = text2num(copytext( icon_state, dash+1 ))
var/turf/T = loc // hide if turf is not intact
if(level == 1)
var/turf/T = get_turf(src) // hide if turf is not intact
if(level == 1)
hide(T.intact)
LAZYADD(GLOB.cable_list, src) //add it to the global cable list
@@ -79,14 +78,22 @@ By design, d1 is the smallest direction and d2 is the highest
LAZYREMOVE(GLOB.cable_list, src) //remove it from global cable list
return ..() // then go ahead and delete the cable
/obj/structure/cable/deconstruct(disassembled = TRUE)
var/turf/T = get_turf(src)
if(d1) // 0-X cables are 1 unit, X-X cables are 2 units long
new/obj/item/stack/cable_coil(T, 2, paramcolor = color)
else
new/obj/item/stack/cable_coil(T, 1, paramcolor = color)
qdel(src)
///////////////////////////////////
// General procedures
///////////////////////////////////
//If underfloor, hide the cable
/obj/structure/cable/hide(var/i)
/obj/structure/cable/hide(i)
if(level == 1 && istype(loc, /turf))
if(level == 1 && isturf(loc))
invisibility = i ? 101 : 0
updateicon()
@@ -97,9 +104,49 @@ By design, d1 is the smallest direction and d2 is the highest
icon_state = "[d1]-[d2]"
// returns the powernet this cable belongs to
/obj/structure/cable/proc/get_powernet() //TODO: remove this as it is obsolete
return powernet
////////////////////////////////////////////
// Power related
///////////////////////////////////////////
// All power generation handled in add_avail()
// Machines should use add_load(), surplus(), avail()
// Non-machines should use add_delayedload(), delayed_surplus(), newavail()
/obj/structure/cable/proc/add_avail(amount)
if(powernet)
powernet.newavail += amount
/obj/structure/cable/proc/add_load(amount)
if(powernet)
powernet.load += amount
/obj/structure/cable/proc/surplus()
if(powernet)
return Clamp(powernet.avail-powernet.load, 0, powernet.avail)
else
return 0
/obj/structure/cable/proc/avail()
if(powernet)
return powernet.avail
else
return 0
/obj/structure/cable/proc/add_delayedload(amount)
if(powernet)
powernet.delayedload += amount
/obj/structure/cable/proc/delayed_surplus()
if(powernet)
return Clamp(powernet.newavail - powernet.delayedload, 0, powernet.newavail)
else
return 0
/obj/structure/cable/proc/newavail()
if(powernet)
return powernet.newavail
else
return 0
//Telekinesis has no effect on a cable
/obj/structure/cable/attack_tk(mob/user)
@@ -116,47 +163,19 @@ By design, d1 is the smallest direction and d2 is the highest
if(T.intact)
return
if(istype(W, /obj/item/wirecutters))
///// Z-Level Stuff
/* if(src.d1 == 12 || src.d2 == 12)
to_chat(user, "<span class='warning'>You must cut this cable from above.</span>")
return */
///// Z-Level Stuff
/* if(breaker_box)
to_chat(user, "<span class='warning'>This cable is connected to nearby breaker box. Use breaker box to interact with it.</span>")
return */
if(iswirecutter(W))
if(shock(user, 50))
return
if(src.d1) // 0-X cables are 1 unit, X-X cables are 2 units long
new/obj/item/stack/cable_coil(T, 2, paramcolor = color)
else
new/obj/item/stack/cable_coil(T, 1, paramcolor = color)
for(var/mob/O in viewers(src, null))
O.show_message("<span class='warning'>[user] cuts the cable.</span>", 1)
///// Z-Level Stuff
/*if(src.d1 == 11 || src.d2 == 11)
var/turf/controllerlocation = locate(1, 1, z)
for(var/obj/effect/landmark/zcontroller/controller in controllerlocation)
if(controller.down)
var/turf/below = locate(src.x, src.y, controller.down_target)
for(var/obj/structure/cable/c in below)
if(c.d1 == 12 || c.d2 == 12)
c.qdel()*/
///// Z-Level Stuff
user.visible_message("[user] cuts the cable.", "<span class='notice'>You cut the cable.</span>")
investigate_log("was cut by [key_name(usr, 1)] in [get_area(user)]([T.x], [T.y], [T.z] - [ADMIN_JMP(T)])","wires")
qdel(src) // qdel
deconstruct()
return
else if(istype(W, /obj/item/stack/cable_coil))
var/obj/item/stack/cable_coil/coil = W
if(coil.get_amount() < 1)
to_chat(user, "Not enough cable")
to_chat(user, "<span class='warning'>Not enough cable!</span>")
return
coil.cable_join(src, user)
@@ -169,11 +188,9 @@ By design, d1 is the smallest direction and d2 is the highest
else if(istype(W, /obj/item/multitool))
if(powernet && (powernet.avail > 0)) // is it powered?
to_chat(user, "<span class='warning'>[powernet.avail]W in power network.</span>")
to_chat(user, "<span class='danger'>Total power: [DisplayPower(powernet.avail)]\nLoad: [DisplayPower(powernet.load)]\nExcess power: [DisplayPower(surplus())]</span>")
else
to_chat(user, "<span class='warning'>The cable is not powered.</span>")
to_chat(user, "<span class='danger'>The cable is not powered.</span>")
shock(user, 5, 0.2)
else if(istype(W, /obj/item/toy/crayon))
@@ -184,7 +201,7 @@ By design, d1 is the smallest direction and d2 is the highest
if(W.flags & CONDUCT)
shock(user, 50, 0.7)
src.add_fingerprint(user)
add_fingerprint(user)
// shock the user with probability prb
/obj/structure/cable/proc/shock(mob/user, prb, siemens_coeff = 1)
@@ -196,21 +213,22 @@ By design, d1 is the smallest direction and d2 is the highest
else
return FALSE
/obj/structure/cable/singularity_pull(S, current_size)
..()
if(current_size >= STAGE_FIVE)
deconstruct()
//explosion handling
/obj/structure/cable/ex_act(severity)
switch(severity)
if(1.0)
if(1)
qdel(src) // qdel
if(2.0)
if(2)
if(prob(50))
new/obj/item/stack/cable_coil(get_turf(src), src.d1 ? 2 : 1, paramcolor = color)
qdel(src) // qdel
if(3.0)
deconstruct()
if(3)
if(prob(25))
new/obj/item/stack/cable_coil(get_turf(src), src.d1 ? 2 : 1, paramcolor = color)
qdel(src) // qdel
return
deconstruct()
obj/structure/cable/proc/cable_color(var/colorC)
if(colorC)
@@ -231,7 +249,7 @@ obj/structure/cable/proc/cable_color(var/colorC)
//handles merging diagonally matching cables
//for info : direction^3 is flipping horizontally, direction^12 is flipping vertically
/obj/structure/cable/proc/mergeDiagonalsNetworks(var/direction)
/obj/structure/cable/proc/mergeDiagonalsNetworks(direction)
//search for and merge diagonally matching cables from the first direction component (north/south)
var/turf/T = get_step(src, direction&3)//go north/south
@@ -275,7 +293,7 @@ obj/structure/cable/proc/cable_color(var/colorC)
C.powernet.add_cable(src) //else, we simply connect to the matching cable powernet
// merge with the powernets of power objects in the given direction
/obj/structure/cable/proc/mergeConnectedNetworks(var/direction)
/obj/structure/cable/proc/mergeConnectedNetworks(direction)
var/fdir = (!direction)? 0 : turn(direction, 180) //flip the direction, to match with the source position on its turf
@@ -313,25 +331,27 @@ obj/structure/cable/proc/cable_color(var/colorC)
//first let's add turf cables to our powernet
//then we'll connect machines on turf with a node cable is present
for(var/AM in loc)
if(istype(AM,/obj/structure/cable))
if(istype(AM, /obj/structure/cable))
var/obj/structure/cable/C = AM
if(C.d1 == d1 || C.d2 == d1 || C.d1 == d2 || C.d2 == d2) //only connected if they have a common direction
if(C.powernet == powernet) continue
if(C.powernet == powernet)
continue
if(C.powernet)
merge_powernets(powernet, C.powernet)
else
powernet.add_cable(C) //the cable was powernetless, let's just add it to our powernet
else if(istype(AM,/obj/machinery/power/apc))
else if(istype(AM, /obj/machinery/power/apc))
var/obj/machinery/power/apc/N = AM
if(!N.terminal) continue // APC are connected through their terminal
if(!N.terminal)
continue // APC are connected through their terminal
if(N.terminal.powernet == powernet)
continue
to_connect += N.terminal //we'll connect the machines after all cables are merged
else if(istype(AM,/obj/machinery/power)) //other power machines
else if(istype(AM, /obj/machinery/power)) //other power machines
var/obj/machinery/power/M = AM
if(M.powernet == powernet)
@@ -349,23 +369,10 @@ obj/structure/cable/proc/cable_color(var/colorC)
//////////////////////////////////////////////
//if powernetless_only = 1, will only get connections without powernet
/obj/structure/cable/proc/get_connections(var/powernetless_only = 0)
/obj/structure/cable/proc/get_connections(powernetless_only = 0)
. = list() // this will be a list of all connected power objects
var/turf/T
///// Z-Level Stuff
/* if(d1 == 11 || d1 == 12)
var/turf/controllerlocation = locate(1, 1, z)
for(var/obj/effect/landmark/zcontroller/controller in controllerlocation)
if(controller.up && d1 == 12)
T = locate(src.x, src.y, controller.up_target)
if(T)
. += power_list(T, src, 11, 1)
if(controller.down && d1 == 11)
T = locate(src.x, src.y, controller.down_target)
if(T)
. += power_list(T, src, 12, 1) */
///// Z-Level Stuff
//get matching cables from the first direction
if(d1) //if not a node cable
T = get_step(src, d1)
@@ -382,20 +389,6 @@ obj/structure/cable/proc/cable_color(var/colorC)
. += power_list(loc, src, d1, powernetless_only) //get on turf matching cables
///// Z-Level Stuff
/*if(d2 == 11 || d2 == 12)
var/turf/controllerlocation = locate(1, 1, z)
for(var/obj/effect/landmark/zcontroller/controller in controllerlocation)
if(controller.up && d2 == 12)
T = locate(src.x, src.y, controller.up_target)
if(T)
. += power_list(T, src, 11, 1)
if(controller.down && d2 == 11)
T = locate(src.x, src.y, controller.down_target)
if(T)
. += power_list(T, src, 12, 1)
///// Z-Level Stuff
else */
//do the same on the second direction (which can't be 0)
T = get_step(src, d2)
if(T)
@@ -416,7 +409,8 @@ obj/structure/cable/proc/cable_color(var/colorC)
//needed as this can, unlike other placements, disconnect cables
/obj/structure/cable/proc/denode()
var/turf/T1 = loc
if(!T1) return
if(!T1)
return
var/list/powerlist = power_list(T1,src,0,0) //find the other cables that ended in the centre of the turf, with or without a powernet
if(powerlist.len>0)
@@ -424,13 +418,19 @@ obj/structure/cable/proc/cable_color(var/colorC)
propagate_network(powerlist[1],PN) //propagates the new powernet beginning at the source cable
if(PN.is_empty()) //can happen with machines made nodeless when smoothing cables
qdel(PN) // qdel
qdel(PN)
/obj/structure/cable/proc/auto_propogate_cut_cable(obj/O)
if(O && !QDELETED(O))
var/datum/powernet/newPN = new()// creates a new powernet...
propagate_network(O, newPN)//... and propagates it to the other side of the cable
// cut the cable's powernet at this cable and updates the powergrid
/obj/structure/cable/proc/cut_cable_from_powernet()
/obj/structure/cable/proc/cut_cable_from_powernet(remove=TRUE)
var/turf/T1 = loc
var/list/P_list
if(!T1) return
if(!T1)
return
if(d1)
T1 = get_step(T1, d1)
P_list = power_list(T1, src, turn(d1,180),0,cable_only = 1) // what adjacently joins on to cut cable...
@@ -448,11 +448,13 @@ obj/structure/cable/proc/cable_color(var/colorC)
var/obj/O = P_list[1]
// remove the cut cable from its turf and powernet, so that it doesn't get count in propagate_network worklist
loc = null
if(remove)
loc = null
powernet.remove_cable(src) //remove the cut cable from its powernet
// queue it to rebuild
SSmachines.deferred_powernet_rebuilds += O
// addtimer(CALLBACK(O, .proc/auto_propogate_cut_cable, O), 0) //so we don't rebuild the network X times when singulo/explosion destroys a line of X cables
// Disconnect machines connected to nodes
if(d1 == 0) // if we cut a node (O-X) cable
@@ -460,6 +462,7 @@ obj/structure/cable/proc/cable_color(var/colorC)
if(!P.connect_to_network()) //can't find a node cable on a the turf to connect to
P.disconnect_from_network() //remove from current network
///////////////////////////////////////////////
// The cable coil object, used for laying cable
///////////////////////////////////////////////
@@ -468,9 +471,7 @@ obj/structure/cable/proc/cable_color(var/colorC)
// Definitions
////////////////////////////////
var/global/list/datum/stack_recipe/cable_coil_recipes = list(
new /datum/stack_recipe/cable_restraints("cable restraints", /obj/item/restraints/handcuffs/cable, 15),
)
GLOBAL_LIST_INIT(cable_coil_recipes, list (new/datum/stack_recipe("cable restraints", /obj/item/restraints/handcuffs/cable, 15)))
/obj/item/stack/cable_coil
name = "cable coil"
@@ -510,7 +511,7 @@ var/global/list/datum/stack_recipe/cable_coil_recipes = list(
pixel_x = rand(-2,2)
pixel_y = rand(-2,2)
update_icon()
recipes = cable_coil_recipes
recipes = GLOB.cable_coil_recipes
update_wclass()
///////////////////////////////////
@@ -653,7 +654,7 @@ var/global/list/datum/stack_recipe/cable_coil_recipes = list(
to_chat(user, "<span class='warning'>You can't lay cable at a place that far away!</span>")
return
var/dirn = null
var/dirn
if(!dirnew) //If we weren't given a direction, come up with one! (Called as null from catwalk.dm and floor.dm)
if(user.loc == T)
dirn = user.dir //If laying on the tile we're on, lay in the direction we're facing
@@ -690,7 +691,7 @@ var/global/list/datum/stack_recipe/cable_coil_recipes = list(
if(C.shock(user, 50))
if(prob(50)) //fail
new /obj/item/stack/cable_coil(get_turf(C), 1, paramcolor = C.color)
qdel(C) // qdel
C.deconstruct()
return C
@@ -707,7 +708,7 @@ var/global/list/datum/stack_recipe/cable_coil_recipes = list(
return
if(get_dist(C, user) > 1) // make sure it's close enough
to_chat(user, "You can't lay cable at a place that far away.")
to_chat(user, "<span class='warning'>You can't lay cable at a place that far away!</span>")
return
@@ -720,13 +721,41 @@ var/global/list/datum/stack_recipe/cable_coil_recipes = list(
// one end of the clicked cable is pointing towards us
if(C.d1 == dirn || C.d2 == dirn)
if(U.intact) // can't place a cable if the floor is complete
to_chat(user, "You can't lay cable there unless the floor tiles are removed.")
to_chat(user, "<span class='warning'>You can't lay cable there unless the floor tiles are removed!</span>")
return
else
// cable is pointing at us, we're standing on an open tile
// so create a stub pointing at the clicked cable on our tile
place_turf(U, user, turn(dirn, 180))
var/fdirn = turn(dirn, 180) // the opposite direction
for(var/obj/structure/cable/LC in U) // check to make sure there's not a cable there already
if(LC.d1 == fdirn || LC.d2 == fdirn)
to_chat(user, "<span class='warning'>There's already a cable at that position!</span>")
return
var/obj/structure/cable/NC = get_new_cable (U)
NC.d1 = 0
NC.d2 = fdirn
NC.add_fingerprint(user)
NC.update_icon()
//create a new powernet with the cable, if needed it will be merged later
var/datum/powernet/newPN = new()
newPN.add_cable(NC)
NC.mergeConnectedNetworks(NC.d2) //merge the powernet with adjacents powernets
NC.mergeConnectedNetworksOnTurf() //merge the powernet with on turf powernets
if(NC.d2 & (NC.d2 - 1))// if the cable is layed diagonally, check the others 2 possible directions
NC.mergeDiagonalsNetworks(NC.d2)
use(1)
if(NC.shock(user, 50))
if(prob(50)) //fail
NC.deconstruct()
return
// exisiting cable doesn't point at our position, so see if it's a stub
@@ -745,7 +774,7 @@ var/global/list/datum/stack_recipe/cable_coil_recipes = list(
if(LC == C) // skip the cable we're interacting with
continue
if((LC.d1 == nd1 && LC.d2 == nd2) || (LC.d1 == nd2 && LC.d2 == nd1) ) // make sure no cable matches either direction
to_chat(user, "There's already a cable at that position.")
to_chat(user, "<span class='warning'>There's already a cable at that position!</span>")
return
@@ -772,8 +801,7 @@ var/global/list/datum/stack_recipe/cable_coil_recipes = list(
if(C.shock(user, 50))
if(prob(50)) //fail
new/obj/item/stack/cable_coil(get_turf(C), 2, paramcolor = C.color)
qdel(C) // qdel
C.deconstruct()
return
C.denode()// this call may have disconnected some cables that terminated on the centre of the turf, if so split the powernets.
@@ -786,8 +814,8 @@ var/global/list/datum/stack_recipe/cable_coil_recipes = list(
/obj/item/stack/cable_coil/cut
item_state = "coil2"
/obj/item/stack/cable_coil/cut/New(loc)
..()
/obj/item/stack/cable_coil/cut/Initialize(mapload)
. = ..()
src.amount = rand(1,2)
pixel_x = rand(-2,2)
pixel_y = rand(-2,2)
+2 -2
View File
@@ -85,8 +85,8 @@ var/const/GRAV_NEEDS_WRENCH = 3
// Generator which spawns with the station.
//
/obj/machinery/gravity_generator/main/station/Initialize()
..()
/obj/machinery/gravity_generator/main/station/Initialize(mapload)
. = ..()
setup_parts()
middle.overlays += "activated"
update_list()
+85 -71
View File
@@ -9,7 +9,7 @@
/obj/machinery/power
name = null
icon = 'icons/obj/power.dmi'
anchored = 1.0
anchored = TRUE
on_blueprints = TRUE
var/datum/powernet/powernet = null
use_power = NO_POWER_USE
@@ -25,18 +25,24 @@
//////////////////////////////
// common helper procs for all power machines
/obj/machinery/power/proc/add_avail(var/amount)
// All power generation handled in add_avail()
// Machines should use add_load(), surplus(), avail()
// Non-machines should use add_delayedload(), delayed_surplus(), newavail()
/obj/machinery/power/proc/add_avail(amount)
if(powernet)
powernet.newavail += amount
return TRUE
else
return FALSE
/obj/machinery/power/proc/draw_power(var/amount)
/obj/machinery/power/proc/add_load(amount)
if(powernet)
return powernet.draw_power(amount)
return 0
powernet.load += amount
/obj/machinery/power/proc/surplus()
if(powernet)
return powernet.avail-powernet.load
return Clamp(powernet.avail-powernet.load, 0, powernet.avail)
else
return 0
@@ -46,9 +52,19 @@
else
return 0
/obj/machinery/power/proc/load()
/obj/machinery/power/proc/add_delayedload(amount)
if(powernet)
return powernet.load
powernet.delayedload += amount
/obj/machinery/power/proc/delayed_surplus()
if(powernet)
return Clamp(powernet.newavail - powernet.delayedload, 0, powernet.newavail)
else
return 0
/obj/machinery/power/proc/newavail()
if(powernet)
return powernet.newavail
else
return 0
@@ -58,21 +74,20 @@
// returns true if the area has power on given channel (or doesn't require power).
// defaults to power_channel
/obj/machinery/proc/powered(var/chan = -1) // defaults to power_channel
if(!loc)
return 0
return FALSE
if(!use_power)
return 1
return TRUE
var/area/A = get_area(src) // make sure it's in an area
if(!A)
return 0 // if not, then not powered
return FALSE // if not, then not powered
if(chan == -1)
chan = power_channel
return A.powered(chan) // return power status of the area
// increment the power usage stats for an area
/obj/machinery/proc/use_power(var/amount, var/chan = -1) // defaults to power_channel
/obj/machinery/proc/use_power(amount, chan = -1) // defaults to power_channel
var/area/A = get_area(src) // make sure it's in an area
if(!A)
return
@@ -103,43 +118,36 @@
/obj/machinery/power/proc/connect_to_network()
var/turf/T = src.loc
if(!T || !istype(T))
return 0
return FALSE
var/obj/structure/cable/C = T.get_cable_node() //check if we have a node cable on the machine turf, the first found is picked
if(!C || !C.powernet)
return 0
return FALSE
C.powernet.add_machine(src)
return 1
return TRUE
// remove and disconnect the machine from its current powernet
/obj/machinery/power/proc/disconnect_from_network()
if(!powernet)
return 0
return FALSE
powernet.remove_machine(src)
return 1
return TRUE
// attach a wire to a power machine - leads from the turf you are standing on
//almost never called, overwritten by all power machines but terminal and generator
/obj/machinery/power/attackby(obj/item/W, mob/user)
if(istype(W, /obj/item/stack/cable_coil))
var/obj/item/stack/cable_coil/coil = W
/obj/machinery/power/attackby(obj/item/I, mob/user, params)
if(istype(I, /obj/item/stack/cable_coil))
var/obj/item/stack/cable_coil/coil = I
var/turf/T = user.loc
if(T.intact || !istype(T, /turf/simulated/floor))
if(T.intact || !isfloorturf(T))
return
if(get_dist(src, user) > 1)
return
coil.place_turf(T, user)
return
else
..()
return
return ..()
///////////////////////////////////////////
// Powernet handling helpers
@@ -159,7 +167,8 @@
cdir = get_dir(T,loc)
for(var/obj/structure/cable/C in T)
if(C.powernet) continue
if(C.powernet)
continue
if(C.d1 == cdir || C.d2 == cdir)
. += C
return .
@@ -186,7 +195,8 @@
/obj/machinery/power/proc/get_indirect_connections()
. = list()
for(var/obj/structure/cable/C in loc)
if(C.powernet) continue
if(C.powernet)
continue
if(C.d1 == 0) // the cable is a node cable
. += C
return .
@@ -199,44 +209,32 @@
// returns a list of all power-related objects (nodes, cable, junctions) in turf,
// excluding source, that match the direction d
// if unmarked==1, only return those with no powernet
/proc/power_list(var/turf/T, var/source, var/d, var/unmarked=0, var/cable_only = 0)
/proc/power_list(turf/T, source, d, unmarked=0, cable_only = 0)
. = list()
var/fdir = (!d)? 0 : turn(d, 180) // the opposite direction to d (or 0 if d==0)
///// Z-Level Stuff
var/Zdir
if(d==11)
Zdir = 11
else if(d==12)
Zdir = 12
else
Zdir = 999
///// Z-Level Stuff
for(var/AM in T)
if(AM == source) continue //we don't want to return source
if(!cable_only && istype(AM,/obj/machinery/power))
for(var/AM in T)
if(AM == source)
continue //we don't want to return source
if(!cable_only && istype(AM, /obj/machinery/power))
var/obj/machinery/power/P = AM
if(P.powernet == 0) continue // exclude APCs which have powernet=0
if(P.powernet == 0)
continue // exclude APCs which have powernet=0
if(!unmarked || !P.powernet) //if unmarked=1 we only return things with no powernet
if(d == 0)
. += P
else if(istype(AM,/obj/structure/cable))
else if(istype(AM, /obj/structure/cable))
var/obj/structure/cable/C = AM
if(!unmarked || !C.powernet)
///// Z-Level Stuff
if(C.d1 == fdir || C.d2 == fdir || C.d1 == Zdir || C.d2 == Zdir)
///// Z-Level Stuff
. += C
else if(C.d1 == d || C.d2 == d)
if(C.d1 == d || C.d2 == d)
. += C
return .
//remove the old powernet and replace it with a new one throughout the network.
/proc/propagate_network(var/obj/O, var/datum/powernet/PN)
//log_world("propagating new network")
/proc/propagate_network(obj/O, datum/powernet/PN)
var/list/worklist = list()
var/list/found_machines = list()
var/index = 1
@@ -248,13 +246,13 @@
P = worklist[index] //get the next power object found
index++
if( istype(P,/obj/structure/cable))
if(istype(P, /obj/structure/cable))
var/obj/structure/cable/C = P
if(C.powernet != PN) //add it to the powernet, if it isn't already there
PN.add_cable(C)
worklist |= C.get_connections() //get adjacents power objects, with or without a powernet
else if(P.anchored && istype(P,/obj/machinery/power))
else if(P.anchored && istype(P, /obj/machinery/power))
var/obj/machinery/power/M = P
found_machines |= M //we wait until the powernet is fully propagates to connect the machines
@@ -268,7 +266,7 @@
//Merge two powernets, the bigger (in cable length term) absorbing the other
/proc/merge_powernets(var/datum/powernet/net1, var/datum/powernet/net2)
/proc/merge_powernets(datum/powernet/net1, datum/powernet/net2)
if(!net1 || !net2) //if one of the powernet doesn't exist, return
return
@@ -285,8 +283,6 @@
for(var/obj/structure/cable/Cable in net2.cables) //merge cables
net1.add_cable(Cable)
if(!net2) return net1
for(var/obj/machinery/power/Node in net2.nodes) //merge power machines
if(!Node.connect_to_network())
Node.disconnect_from_network() //if somehow we can't connect the machine to the new powernet, disconnect it from the old nonetheless
@@ -299,14 +295,12 @@
//source is an object caused electrocuting (airlock, grille, etc)
//No animations will be performed by this proc.
/proc/electrocute_mob(mob/living/M, power_source, obj/source, siemens_coeff = 1, dist_check = FALSE)
if(!istype(M))
return FALSE
if(istype(M.loc,/obj/mecha))
if(!M || ismecha(M.loc))
return FALSE //feckin mechs are dumb
if(dist_check)
if(!in_range(source, M))
return FALSE
if(istype(M,/mob/living/carbon/human))
if(ishuman(M))
var/mob/living/carbon/human/H = M
if(H.gloves)
var/obj/item/clothing/gloves/G = H.gloves
@@ -326,7 +320,7 @@
if(istype(power_source, /datum/powernet))
PN = power_source
else if(istype(power_source,/obj/item/stock_parts/cell))
else if(istype(power_source, /obj/item/stock_parts/cell))
cell = power_source
else if(istype(power_source, /obj/machinery/power/apc))
var/obj/machinery/power/apc/apc = power_source
@@ -357,10 +351,30 @@
var/drained_energy = drained_hp*20
if(source_area)
source_area.use_power(drained_energy/CELLRATE)
else if(istype(power_source,/datum/powernet))
var/drained_power = drained_energy/CELLRATE //convert from "joules" to "watts"
drained_power = PN.draw_power(drained_power)
else if(istype(power_source, /obj/item/stock_parts/cell))
source_area.use_power(drained_energy/GLOB.CELLRATE)
else if(istype(power_source, /datum/powernet))
var/drained_power = drained_energy/GLOB.CELLRATE //convert from "joules" to "watts"
PN.delayedload += (min(drained_power, max(PN.newavail - PN.delayedload, 0)))
else if (istype(power_source, /obj/item/stock_parts/cell))
cell.use(drained_energy)
return drained_energy
////////////////////////////////////////////////
// Misc.
///////////////////////////////////////////////
// return a knot cable (O-X) if one is present in the turf
// null if there's none
/turf/proc/get_cable_node()
if(!can_have_cabling())
return null
for(var/obj/structure/cable/C in src)
if(C.d1 == 0)
return C
return null
/area/proc/get_apc()
for(var/obj/machinery/power/apc/APC in GLOB.apcs)
if(APC.area == src)
return APC
+22 -77
View File
@@ -1,19 +1,19 @@
////////////////////////////////////////////
// POWERNET DATUM
// each contiguous network of cables & nodes
/////////////////////////////////////
/datum/powernet
var/number // unique id
var/list/cables = list() // all cables & junctions
var/list/nodes = list() // all connected machines
var/load = 0 // the current load on the powernet, increased by each machine at processing
var/newavail = 0 // what available power was gathered last tick, then becomes...
var/avail = 0 //...the current available power in the powernet
var/viewavail = 0 // the available power as it appears on the power console (gradually updated)
var/viewload = 0 // the load as it appears on the power console (gradually updated)
var/number = 0 // Unused //TODEL
var/perapc = 0 // per-apc avilability
var/perapc_excess = 0
var/netexcess = 0 // excess power on the powernet (typically avail-load)
var/problem = 0 // If either of these is set to 1 there is some sort of issue at the powernet.
var/netexcess = 0 // excess power on the powernet (typically avail-load)///////
var/delayedload = 0 // load applied to powernet between power ticks.
/datum/powernet/New()
SSmachines.powernets += src
@@ -31,31 +31,21 @@
SSmachines.powernets -= src
return ..()
//Returns the amount of excess power (before refunding to SMESs) from last tick.
//This is for machines that might adjust their power consumption using this data.
/datum/powernet/proc/last_surplus()
return max(avail - load, 0)
/datum/powernet/proc/draw_power(var/amount)
var/draw = between(0, amount, avail - load)
load += draw
return draw
/datum/powernet/proc/is_empty()
return !cables.len && !nodes.len
//remove a cable from the current powernet
//if the powernet is then empty, delete it
//Warning : this proc DON'T check if the cable exists
/datum/powernet/proc/remove_cable(var/obj/structure/cable/C)
/datum/powernet/proc/remove_cable(obj/structure/cable/C)
cables -= C
C.powernet = null
if(is_empty())//the powernet is now empty...
qdel(src)///... delete it - qdel
qdel(src)///... delete it
//add a cable to the current powernet
//Warning : this proc DON'T check if the cable exists
/datum/powernet/proc/add_cable(var/obj/structure/cable/C)
/datum/powernet/proc/add_cable(obj/structure/cable/C)
if(C.powernet)// if C already has a powernet...
if(C.powernet == src)
return
@@ -67,16 +57,16 @@
//remove a power machine from the current powernet
//if the powernet is then empty, delete it
//Warning : this proc DON'T check if the machine exists
/datum/powernet/proc/remove_machine(var/obj/machinery/power/M)
/datum/powernet/proc/remove_machine(obj/machinery/power/M)
nodes -=M
M.powernet = null
if(is_empty())//the powernet is now empty...
qdel(src)///... delete it - qdel
qdel(src)///... delete it
//add a power machine to the current powernet
//Warning : this proc DON'T check if the machine exists
/datum/powernet/proc/add_machine(var/obj/machinery/power/M)
/datum/powernet/proc/add_machine(obj/machinery/power/M)
if(M.powernet)// if M already has a powernet...
if(M.powernet == src)
return
@@ -85,45 +75,23 @@
M.powernet = src
nodes[M] = M
// Triggers warning for certain amount of ticks
/datum/powernet/proc/trigger_warning(var/duration_ticks = 20)
problem = max(duration_ticks, problem)
//handles the power changes in the powernet
//called every ticks by the powernet controller
/datum/powernet/proc/reset()
var/numapc = 0
if(problem > 0)
problem = max(problem - 1, 0)
if(nodes && nodes.len) // Added to fix a bad list bug -- TLE
for(var/obj/machinery/power/terminal/term in nodes)
if( istype( term.master, /obj/machinery/power/apc ) )
numapc++
//see if there's a surplus of power remaining in the powernet and stores unused power in the SMES
netexcess = avail - load
if(numapc)
//very simple load balancing. If there was a net excess this tick then it must have been that some APCs used less than perapc, since perapc*numapc = avail
//Therefore we can raise the amount of power rationed out to APCs on the assumption that those APCs that used less than perapc will continue to do so.
//If that assumption fails, then some APCs will miss out on power next tick, however it will be rebalanced for the tick after.
if(netexcess >= 0)
perapc_excess += min(netexcess/numapc, (avail - perapc) - perapc_excess)
else
perapc_excess = 0
perapc = avail/numapc + perapc_excess
if(netexcess > 100 && nodes && nodes.len) // if there was excess power last cycle
for(var/obj/machinery/power/smes/S in nodes) // find the SMESes in the network
S.restore() // and restore some of the power that was used
//updates the viewed load (as seen on power computers)
viewload = round(load)
// update power consoles
viewavail = round(0.8 * viewavail + 0.2 * avail)
viewload = round(0.8 * viewload + 0.2 * load)
//reset the powernet
load = 0
// reset the powernet
load = delayedload
delayedload = 0
avail = newavail
newavail = 0
@@ -131,27 +99,4 @@
if(avail >= 1000)
return Clamp(20 + round(avail / 25000), 20, 195) + rand(-5, 5)
else
return 0
////////////////////////////////////////////////
// Misc.
///////////////////////////////////////////////
// return a knot cable (O-X) if one is present in the turf
// null if there's none
/turf/proc/get_cable_node()
if(!istype(src, /turf/simulated/floor))
return null
for(var/obj/structure/cable/C in src)
if(C.d1 == 0)
return C
return null
/area/proc/get_apc()
// This was a simple locate() in src, but an unresolved BYOND bug causes trying to locate() in an
// area to take an inconceivably long time, especially for large areas.
// See: http://www.byond.com/forum/?post=1860571
var/obj/machinery/power/apc/FINDME
for(FINDME in src)
return FINDME
return 0
+2 -2
View File
@@ -15,8 +15,8 @@ var/global/list/rad_collectors = list()
var/locked = 0
var/drainratio = 1
/obj/machinery/power/rad_collector/New()
..()
/obj/machinery/power/rad_collector/Initialize(mapload)
. = ..()
rad_collectors += src
/obj/machinery/power/rad_collector/Destroy()
+60 -40
View File
@@ -23,18 +23,25 @@
var/frequency = 0
var/id_tag = null
var/projectile_type = /obj/item/projectile/beam/emitter
var/projectile_sound = 'sound/weapons/emitter.ogg'
var/datum/radio_frequency/radio_connection
var/datum/effect_system/spark_spread/sparks
/obj/machinery/power/emitter/New()
..()
/obj/machinery/power/emitter/Initialize(mapload)
. = ..()
component_parts = list()
component_parts += new /obj/item/circuitboard/emitter(null)
component_parts += new /obj/item/stock_parts/micro_laser(null)
component_parts += new /obj/item/stock_parts/manipulator(null)
RefreshParts()
if(state == 2 && anchored)
connect_to_network()
sparks = new
sparks.attach(src)
sparks.set_up(5, 1, src)
if(frequency)
set_frequency(frequency)
/obj/machinery/power/emitter/RefreshParts()
var/max_firedelay = 120
@@ -79,13 +86,6 @@
return
rotate()
/obj/machinery/power/emitter/Initialize()
..()
if(state == 2 && anchored)
connect_to_network()
if(frequency)
set_frequency(frequency)
/obj/machinery/power/emitter/multitool_menu(var/mob/user,var/obj/item/multitool/P)
return {"
<ul>
@@ -182,10 +182,9 @@
src.active = 0
update_icon()
return
if(((src.last_shot + src.fire_delay) <= world.time) && (src.active == 1))
var/actual_load = draw_power(active_power_usage)
if(actual_load >= active_power_usage) //does the laser have enough power to shoot?
if(active == TRUE)
if(!active_power_usage || surplus() >= active_power_usage)
add_load(active_power_usage)
if(!powered)
powered = 1
update_icon()
@@ -197,36 +196,57 @@
investigate_log("lost power and turned <font color='red'>off</font>","singulo")
return
src.last_shot = world.time
if(src.shot_number < 3)
src.fire_delay = 2
src.shot_number++
else
src.fire_delay = rand(minimum_fire_delay,maximum_fire_delay)
src.shot_number = 0
if(!check_delay())
return FALSE
fire_beam()
var/obj/item/projectile/beam/emitter/A = new /obj/item/projectile/beam/emitter(src.loc)
/obj/machinery/power/emitter/proc/check_delay()
if((last_shot + fire_delay) <= world.time)
return TRUE
return FALSE
A.dir = src.dir
playsound(get_turf(src), 'sound/weapons/emitter.ogg', 25, 1)
if(prob(35))
sparks.start()
switch(dir)
if(NORTH)
A.yo = 20
A.xo = 0
if(EAST)
A.yo = 0
A.xo = 20
if(WEST)
A.yo = 0
A.xo = -20
else // Any other
A.yo = -20
A.xo = 0
A.fire() //TODO: Carn: check this out
/obj/machinery/power/emitter/proc/fire_beam()
var/obj/item/projectile/P = new projectile_type(get_turf(src))
playsound(get_turf(src), projectile_sound, 50, TRUE)
if(prob(35))
sparks.start()
switch(dir)
if(NORTH)
P.yo = 20
P.xo = 0
if(NORTHEAST)
P.yo = 20
P.xo = 20
if(EAST)
P.yo = 0
P.xo = 20
if(SOUTHEAST)
P.yo = -20
P.xo = 20
if(WEST)
P.yo = 0
P.xo = -20
if(SOUTHWEST)
P.yo = -20
P.xo = -20
if(NORTHWEST)
P.yo = 20
P.xo = -20
else // Any other
P.yo = -20
P.xo = 0
last_shot = world.time
if(shot_number < 3)
fire_delay = 20
shot_number ++
else
fire_delay = rand(minimum_fire_delay, maximum_fire_delay)
shot_number = 0
P.setDir(dir)
P.starting = loc
P.fire()
return P
/obj/machinery/power/emitter/attackby(obj/item/W, mob/user, params)
if(istype(W, /obj/item/multitool))
@@ -48,8 +48,8 @@ field_generator power level display
overlays += "+p[power_level]"
/obj/machinery/field/generator/New()
..()
/obj/machinery/field/generator/Initialize(mapload)
. = ..()
fields = list()
connected_gens = list()
@@ -2,11 +2,12 @@
name = "Accelerated Particles"
desc = "Small things moving very fast."
icon = 'icons/obj/machines/particle_accelerator.dmi'
icon_state = "particle"//Need a new icon for this
anchored = 1
density = 1
icon_state = "particle"
anchored = TRUE
density = FALSE
var/movement_range = 10
var/energy = 10
var/speed = 1
/obj/effect/accelerated_particle/weak
movement_range = 8
@@ -21,50 +22,45 @@
energy = 50
/obj/effect/accelerated_particle/New(loc, dir = 2)
src.loc = loc
src.dir = dir
/obj/effect/accelerated_particle/New(loc)
..()
if(movement_range > 20)
movement_range = 20
spawn(0)
move(1)
return
addtimer(CALLBACK(src, .proc/move), 1)
/obj/effect/accelerated_particle/Bump(atom/A)
if(A)
if(ismob(A))
if(isliving(A))
toxmob(A)
if((istype(A,/obj/machinery/the_singularitygen))||(istype(A,/obj/singularity/)))
A:energy += energy
return
else if(istype(A, /obj/machinery/the_singularitygen))
var/obj/machinery/the_singularitygen/S = A
S.energy += energy
else if(istype(A, /obj/singularity))
var/obj/singularity/S = A
S.energy += energy
/obj/effect/accelerated_particle/Bumped(atom/A)
if(ismob(A))
Bump(A)
return
/obj/effect/accelerated_particle/Crossed(atom/A)
if(isliving(A))
toxmob(A)
/obj/effect/accelerated_particle/ex_act(severity)
qdel(src)
/obj/effect/accelerated_particle/singularity_pull()
return
/obj/effect/accelerated_particle/proc/toxmob(var/mob/living/M)
M.apply_effect((energy*6),IRRADIATE,0)
M.updatehealth()
return
/obj/effect/accelerated_particle/proc/toxmob(mob/living/M)
M.apply_effect((energy * 6), IRRADIATE, 0)
/obj/effect/accelerated_particle/proc/move(var/lag)
/obj/effect/accelerated_particle/proc/move()
if(!step(src,dir))
src.loc = get_step(src,dir)
forceMove(get_step(src, dir))
movement_range--
if(movement_range <= 0)
if(movement_range == 0)
qdel(src)
else
sleep(lag)
move(lag)
sleep(speed)
move()
@@ -19,11 +19,11 @@
var/parts = null
var/datum/wires/particle_acc/control_box/wires = null
/obj/machinery/particle_accelerator/control_box/New()
/obj/machinery/particle_accelerator/control_box/Initialize(mapload)
. = ..()
wires = new(src)
connected_parts = list()
update_icon()
..()
/obj/machinery/particle_accelerator/control_box/Destroy()
if(active)
@@ -29,21 +29,20 @@
return 0
/obj/structure/particle_accelerator/particle_emitter/proc/emit_particle(var/strength = 0)
/obj/structure/particle_accelerator/particle_emitter/proc/emit_particle(strength = 0)
if((last_shot + fire_delay) <= world.time)
last_shot = world.time
var/obj/effect/accelerated_particle/A = null
var/turf/T = get_step(src, dir)
var/turf/T = get_turf(src)
var/obj/effect/accelerated_particle/P
switch(strength)
if(0)
A = new/obj/effect/accelerated_particle/weak(T, dir)
P = new/obj/effect/accelerated_particle/weak(T)
if(1)
A = new/obj/effect/accelerated_particle(T, dir)
P = new/obj/effect/accelerated_particle(T)
if(2)
A = new/obj/effect/accelerated_particle/strong(T, dir)
P = new/obj/effect/accelerated_particle/strong(T)
if(3)
A = new/obj/effect/accelerated_particle/powerful(T, dir)
if(A)
A.dir = dir
return 1
return 0
P = new/obj/effect/accelerated_particle/powerful(T)
P.setDir(dir)
return TRUE
return FALSE
@@ -3,8 +3,4 @@
desc_holder = "This part uses electromagnetic waves to focus the Alpha particles."
icon = 'icons/obj/machines/particle_accelerator.dmi'
icon_state = "power_box"
reference = "power_box"
/obj/structure/particle_accelerator/power_box/update_icon()
..()
return
reference = "power_box"
+60 -59
View File
@@ -11,20 +11,20 @@
name = "power storage unit"
desc = "A high-capacity superconducting magnetic energy storage (SMES) unit."
icon_state = "smes"
density = 1
anchored = 1
density = TRUE
use_power = NO_POWER_USE
var/capacity = 5e6 // maximum charge
var/charge = 0 // actual charge
var/input_attempt = 0 // 1 = attempting to charge, 0 = not attempting to charge
var/inputting = 0 // 1 = actually inputting, 0 = not inputting
var/input_attempt = TRUE // 1 = attempting to charge, 0 = not attempting to charge
var/inputting = TRUE // 1 = actually inputting, 0 = not inputting
var/input_level = 50000 // amount of power the SMES attempts to charge by
var/input_level_max = 200000 // cap on input_level
var/input_available = 0 // amount of charge available from input last tick
var/output_attempt = 1 // 1 = attempting to output, 0 = not attempting to output
var/outputting = 1 // 1 = actually outputting, 0 = not outputting
var/output_attempt = TRUE // 1 = attempting to output, 0 = not attempting to output
var/outputting = TRUE // 1 = actually outputting, 0 = not outputting
var/output_level = 50000 // amount of power the SMES attempts to output
var/output_level_max = 200000 // cap on output_level
var/output_used = 0 // amount of power actually outputted. may be less than output_level if the powernet returns excess power
@@ -34,13 +34,11 @@
var/last_input_attempt = 0
var/last_charge = 0
var/open_hatch = 0
var/name_tag = null
var/building_terminal = 0 //Suggestions about how to avoid clickspam building several terminals accepted!
var/obj/machinery/power/terminal/terminal = null
/obj/machinery/power/smes/New()
..()
/obj/machinery/power/smes/Initialize(mapload)
. = ..()
component_parts = list()
component_parts += new /obj/item/circuitboard/smes(null)
component_parts += new /obj/item/stock_parts/cell/high(null)
@@ -52,28 +50,22 @@
component_parts += new /obj/item/stack/cable_coil(null, 5)
RefreshParts()
spawn(5)
if(!powernet)
connect_to_network()
dir_loop:
for(var/d in cardinal)
var/turf/T = get_step(src, d)
for(var/obj/machinery/power/terminal/term in T)
if(term && term.dir == turn(d, 180))
terminal = term
break dir_loop
dir_loop:
for(var/d in cardinal)
var/turf/T = get_step(src, d)
for(var/obj/machinery/power/terminal/term in T)
if(term && term.dir == turn(d, 180))
terminal = term
break dir_loop
if(!terminal)
stat |= BROKEN
return
terminal.master = src
if(!terminal.powernet)
terminal.connect_to_network()
update_icon()
return
if(!terminal)
stat |= BROKEN
return
terminal.master = src
update_icon()
/obj/machinery/power/smes/upgraded/New()
..()
/obj/machinery/power/smes/upgraded/Initialize(mapload)
. = ..()
component_parts = list()
component_parts += new /obj/item/circuitboard/smes(null)
component_parts += new /obj/item/stock_parts/cell/hyper(null)
@@ -222,8 +214,8 @@
return round(5.5*charge/(capacity ? capacity : 5e6))
/obj/machinery/power/smes/process()
if(stat & BROKEN) return
if(stat & BROKEN)
return
//store machine state to see if we need to update the icon overlays
var/last_disp = chargedisplay()
@@ -231,33 +223,46 @@
var/last_onln = outputting
//inputting
if(input_attempt)
var/target_load = min((capacity-charge)/SMESRATE, input_level) // charge at set rate, limited to spare capacity
var/actual_load = draw_power(target_load) // add the load to the terminal side network
charge += actual_load * SMESRATE // increase the charge
if(terminal && input_attempt)
input_available = terminal.surplus()
if(actual_load >= target_load) // Did we charge at full rate?
inputting = 2
else if(actual_load) // If not, did we charge at least partially?
inputting = 1
else // Or not at all?
inputting = 0
if(inputting)
if(input_available > 0) // if there's power available, try to charge
var/load = min(min((capacity-charge)/SMESRATE, input_level), input_available) // charge at set rate, limited to spare capacity
charge += load * SMESRATE // increase the charge
terminal.add_load(load) // add the load to the terminal side network
else // if not enough capcity
inputting = FALSE // stop inputting
else
if(input_attempt && input_available > 0)
inputting = TRUE
else
inputting = FALSE
//outputting
if(outputting)
output_used = min( charge/SMESRATE, output_level) //limit output to that stored
if(output_attempt)
if(outputting)
output_used = min( charge/SMESRATE, output_level) //limit output to that stored
charge -= output_used*SMESRATE // reduce the storage (may be recovered in /restore() if excessive)
if (add_avail(output_used)) // add output to powernet if it exists (smes side)
charge -= output_used*SMESRATE // reduce the storage (may be recovered in /restore() if excessive)
else
outputting = FALSE
add_avail(output_used) // add output to powernet (smes side)
if(output_used < 0.0001) // either from no charge or set to 0
outputting = 0
investigate_log("lost power and turned <font color='red'>off</font>","singulo")
else if(output_attempt && charge > output_level && output_level > 0)
outputting = 1
if(output_used < 0.0001) // either from no charge or set to 0
outputting = FALSE
investigate_log("lost power and turned <font color='red'>off</font>", "singulo")
else if(output_attempt && charge > output_level && output_level > 0)
outputting = TRUE
else
output_used = 0
else
output_used = 0
outputting = FALSE
// only update icon if state changed
if(last_disp != chargedisplay() || last_chrg != inputting || last_onln != outputting)
@@ -333,11 +338,6 @@
return 0
return 1
/obj/machinery/power/smes/draw_power(var/amount)
if(terminal && terminal.powernet)
return terminal.powernet.draw_power(amount)
return 0
/obj/machinery/power/smes/attack_ai(mob/user)
add_hiddenprint(user)
ui_interact(user)
@@ -483,7 +483,8 @@
output_level = 250000
/obj/machinery/power/smes/magical/process()
charge = 5000000
capacity = INFINITY
charge = INFINITY
..()
#undef SMESRATE
+4 -5
View File
@@ -6,8 +6,7 @@
desc = "A solar panel. Generates electricity when in contact with sunlight."
icon = 'icons/obj/power.dmi'
icon_state = "sp_base"
anchored = 1
density = 1
density = TRUE
use_power = NO_POWER_USE
idle_power_usage = 0
active_power_usage = 0
@@ -20,8 +19,8 @@
var/turn_angle = 0
var/obj/machinery/power/solar_control/control = null
/obj/machinery/power/solar/New(var/turf/loc, var/obj/item/solar_assembly/S)
..(loc)
/obj/machinery/power/solar/Initialize(mapload, obj/item/solar_assembly/S)
. = ..()
Make(S)
connect_to_network()
@@ -118,7 +117,7 @@
return
sunfrac = cos(p_angle) ** 2
//isn't the power recieved from the incoming light proportionnal to cos(p_angle) (Lambert's cosine law) rather than cos(p_angle)^2 ?
//isn't the power received from the incoming light proportionnal to cos(p_angle) (Lambert's cosine law) rather than cos(p_angle)^2 ?
/obj/machinery/power/solar/process()//TODO: remove/add this from machines to save on processing as needed ~Carn PRIORITY
if(stat & BROKEN)
-84
View File
@@ -1,84 +0,0 @@
//This is a power switch. When turned on it looks at the cables around the tile that it's on and notes which cables are trying to connect to it.
//After it knows this it creates the number of cables from the center to each of the cables attempting to conenct. These cables cannot be removed
//with wirecutters. When the switch is turned off it removes all the cables on the tile it's on.
//The switch uses a 5s delay to prevent powernet change spamming.
/*
/obj/structure/powerswitch
name = "power switch"
desc = "A switch that controls power."
icon = 'icons/obj/power.dmi'
icon_state = "switch-dbl-up"
var/icon_state_on = "switch-dbl-down"
var/icon_state_off = "switch-dbl-up"
density = 0
anchored = 1
var/on = 0 //up is off, down is on
var/busy = 0 //set to 1 when you start pulling
/obj/structure/powerswitch/simple
icon_state = "switch-up"
icon_state_on = "switch-down"
icon_state_off = "switch-up"
/obj/structure/powerswitch/examine(mob/user)
..(user)
if(on)
to_chat(user, "The switch is in the on position")
else
to_chat(user, "The switch is in the off position")
/obj/structure/powerswitch/attack_ai(mob/user)
to_chat(user, "<span class='warning'>You're an AI. This is a manual switch. It's not going to work.</span>")
return
/obj/structure/powerswitch/attack_hand(mob/user)
if(busy)
to_chat(user, "<span class='warning'>This switch is already being toggled.</span>")
return
..()
busy = 1
for(var/mob/O in viewers(user))
O.show_message(text("<span class='warning'>[user] starts pulling the [src].</span>"), 1)
if(do_after(user, 50, target = src))
set_state(!on)
for(var/mob/O in viewers(user))
O.show_message(text("<span class='warning'>[user] flips the [src] into the [on ? </span>"on": "off"] position."), 1)
busy = 0
/obj/structure/powerswitch/proc/set_state(var/state)
on = state
if(on)
icon_state = icon_state_on
var/list/connection_dirs = list()
for(var/direction in list(1,2,4,8,5,6,9,10))
for(var/obj/structure/cable/C in get_step(src,direction))
if(C.d1 == turn(direction, 180) || C.d2 == turn(direction, 180))
connection_dirs += direction
break
for(var/direction in connection_dirs)
var/obj/structure/cable/C = new/obj/structure/cable(src.loc)
C.d1 = 0
C.d2 = direction
C.icon_state = "[C.d1]-[C.d2]"
C.power_switch = src
var/datum/powernet/PN = new()
PN.number = powernets.len + 1
powernets += PN
C.netnum = PN.number
PN.cables += C
C.mergeConnectedNetworks(C.d2)
C.mergeConnectedNetworksOnTurf()
else
icon_state = icon_state_off
for(var/obj/structure/cable/C in src.loc)
qdel(C)
*/
+9 -10
View File
@@ -8,25 +8,24 @@
icon_state = "term"
desc = "It's an underfloor wiring terminal for power equipment."
level = 1
layer = TURF_LAYER
layer = WIRE_TERMINAL_LAYER //a bit above wires
var/obj/machinery/power/master = null
anchored = 1
layer = 2.6 // a bit above wires
/obj/machinery/power/terminal/New()
..()
var/turf/T = src.loc
if(level==1) hide(T.intact)
return
/obj/machinery/power/terminal/Initialize(mapload)
. = ..()
var/turf/T = get_turf(src)
if(level == 1)
hide(T.intact)
/obj/machinery/power/terminal/Destroy()
if(master)
master.disconnect_terminal()
master = null
return ..()
/obj/machinery/power/terminal/hide(var/i)
/obj/machinery/power/terminal/hide(i)
if(i)
invisibility = 101
icon_state = "term-f"
+5 -5
View File
@@ -12,8 +12,8 @@
var/last_zap = 0
var/datum/wires/tesla_coil/wires = null
/obj/machinery/power/tesla_coil/New()
..()
/obj/machinery/power/tesla_coil/Initialize(mapload)
. = ..()
component_parts = list()
component_parts += new /obj/item/circuitboard/tesla_coil(null)
component_parts += new /obj/item/stock_parts/capacitor(null)
@@ -77,7 +77,7 @@
var/coeff = (20 - ((input_power_multiplier - 1) * 3))
coeff = max(coeff, 10)
var/power = (powernet.avail/2)
draw_power(power)
add_load(power)
playsound(src.loc, 'sound/magic/lightningshock.ogg', 100, 1, extrarange = 5)
tesla_zap(src, 10, power/(coeff/2))
@@ -89,8 +89,8 @@
anchored = 0
density = 1
/obj/machinery/power/grounding_rod/New()
..()
/obj/machinery/power/grounding_rod/Initialize(mapload)
. = ..()
component_parts = list()
component_parts += new /obj/item/circuitboard/grounding_rod(null)
component_parts += new /obj/item/stock_parts/capacitor(null)
+9 -10
View File
@@ -8,16 +8,15 @@
desc = "A solar directional tracker."
icon = 'icons/obj/power.dmi'
icon_state = "tracker"
anchored = 1
density = 1
density = TRUE
use_power = NO_POWER_USE
var/id = 0
var/sun_angle = 0 // sun angle as set by sun datum
var/obj/machinery/power/solar_control/control = null
/obj/machinery/power/tracker/New(var/turf/loc, var/obj/item/solar_assembly/S)
..(loc)
/obj/machinery/power/tracker/Initialize(mapload, obj/item/solar_assembly/S)
. = ..()
Make(S)
connect_to_network()
@@ -26,7 +25,7 @@
return ..()
//set the control of the tracker to a given computer if closer than SOLAR_MAX_DIST
/obj/machinery/power/tracker/proc/set_control(var/obj/machinery/power/solar_control/SC)
/obj/machinery/power/tracker/proc/set_control(obj/machinery/power/solar_control/SC)
if(SC && (get_dist(src, SC) > SOLAR_MAX_DIST))
return 0
control = SC
@@ -39,21 +38,21 @@
control.connected_tracker = null
control = null
/obj/machinery/power/tracker/proc/Make(var/obj/item/solar_assembly/S)
/obj/machinery/power/tracker/proc/Make(obj/item/solar_assembly/S)
if(!S)
S = new /obj/item/solar_assembly(src)
S.glass_type = /obj/item/stack/sheet/glass
S.tracker = 1
S.anchored = 1
S.loc = src
S.anchored = TRUE
S.forceMove(src)
update_icon()
//updates the tracker icon and the facing angle for the control computer
/obj/machinery/power/tracker/proc/set_angle(var/angle)
/obj/machinery/power/tracker/proc/set_angle(angle)
sun_angle = angle
//set icon dir to show sun illumination
dir = turn(NORTH, -angle - 22.5) // 22.5 deg bias ensures, e.g. 67.5-112.5 is EAST
setDir(turn(NORTH, -angle - 22.5)) // 22.5 deg bias ensures, e.g. 67.5-112.5 is EAST
if(powernet && (powernet == control.powernet)) //update if we're still in the same powernet
control.cdir = angle
+4 -5
View File
@@ -7,7 +7,6 @@
name = "treadmill"
desc = "A power-generating treadmill."
layer = 2.2
anchored = 1
use_power = NO_POWER_USE
var/speed = 0
@@ -18,8 +17,8 @@
var/list/mobs_running[0]
var/id = null // for linking to monitor
/obj/machinery/power/treadmill/Initialize()
..()
/obj/machinery/power/treadmill/Initialize(mapload)
. = ..()
if(anchored)
connect_to_network()
@@ -138,8 +137,8 @@
var/frame = 0 // on 0, show labels, on 1 show numbers
var/redeem_immediately = 0 // redeem immediately for holding cell
/obj/machinery/treadmill_monitor/Initialize()
..()
/obj/machinery/treadmill_monitor/Initialize(mapload)
. = ..()
if(id)
for(var/obj/machinery/power/treadmill/T in GLOB.machines)
if(T.id == id)
+4 -12
View File
@@ -64,8 +64,8 @@
// the inlet stage of the gas turbine electricity generator
/obj/machinery/power/compressor/New()
..()
/obj/machinery/power/compressor/Initialize(mapload)
. = ..()
component_parts = list()
component_parts += new /obj/item/circuitboard/power_compressor(null)
component_parts += new /obj/item/stock_parts/manipulator(null)
@@ -80,10 +80,6 @@
gas_contained = new
inturf = get_step(src, dir)
/obj/machinery/power/compressor/Initialize()
..()
locate_machinery()
if(!turbine)
stat |= BROKEN
@@ -185,8 +181,8 @@
#define TURBGENQ 100000
#define TURBGENG 0.5
/obj/machinery/power/turbine/New()
..()
/obj/machinery/power/turbine/Initialize(mapload)
. = ..()
component_parts = list()
component_parts += new /obj/item/circuitboard/power_turbine(src)
component_parts += new /obj/item/stock_parts/capacitor(src)
@@ -200,10 +196,6 @@
// The outlet is pointed at the direction of the turbine component
outturf = get_step(src, dir)
/obj/machinery/power/turbine/Initialize()
..()
locate_machinery()
if(!compressor)
stat |= BROKEN
@@ -229,6 +229,8 @@
if(href_list["ejectBeaker"])
if(beaker)
beaker.forceMove(loc)
if(Adjacent(usr) && !issilicon(usr))
usr.put_in_hands(beaker)
beaker = null
overlays.Cut()
@@ -38,9 +38,11 @@
if(state_change)
SSnanoui.update_uis(src)
/obj/machinery/chem_heater/proc/eject_beaker()
/obj/machinery/chem_heater/proc/eject_beaker(mob/user)
if(beaker)
beaker.forceMove(get_turf(src))
if(Adjacent(user) && !issilicon(user))
user.put_in_hands(beaker)
beaker = null
icon_state = "mixer0b"
on = FALSE
@@ -118,7 +120,7 @@
. = 1
if(href_list["eject_beaker"])
eject_beaker()
eject_beaker(usr)
. = 0 //updated in eject_beaker() already
/obj/machinery/chem_heater/ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null)
@@ -229,6 +229,8 @@
else if(href_list["eject"])
if(beaker)
beaker.forceMove(get_turf(src))
if(Adjacent(usr) && !issilicon(usr))
usr.put_in_hands(beaker)
beaker = null
reagents.clear_reagents()
update_icon()
@@ -447,6 +447,14 @@
build_path = /obj/item/healthanalyzer
category = list("initial", "Medical")
/datum/design/pillbottle
name = "Pill Bottle"
id = "pillbottle"
build_type = AUTOLATHE
materials = list(MAT_METAL = 80, MAT_GLASS = 20)
build_path = /obj/item/storage/pill_bottle
category = list("initial", "Medical")
/datum/design/beanbag_slug
name = "Beanbag Slug"
id = "beanbag_slug"
@@ -113,7 +113,15 @@
build_type = BIOGENERATOR
materials = list(MAT_BIOMASS = 50)
build_path = /obj/item/stack/sheet/cloth
category = list("initial","Leather and Cloth")
category = list("initial", "Organic Materials")
/datum/design/cardboard
name = "Sheet of cardboard"
id = "cardboard"
build_type = BIOGENERATOR
materials = list(MAT_BIOMASS = 25)
build_path = /obj/item/stack/sheet/cardboard
category = list("initial", "Organic Materials")
/datum/design/wallet
name = "Wallet"
@@ -41,6 +41,8 @@
for(var/X in actions)
var/datum/action/A = X
A.Grant(M)
if(vital)
M.update_stat("Vital organ inserted")
// Removes the given organ from its owner.
// Returns the removed object, which is usually just itself