/* Overview: Used to create objects that need a per step proc call. Default definition of 'New()' stores a reference to src machine in global 'machines list'. Default definition of 'Del' removes reference to src machine in global 'machines list'. Class Variables: use_power (num) current state of auto power use. Possible Values: 0 -- no auto power use 1 -- machine is using power at its idle power level 2 -- machine is using power at its active power level active_power_usage (num) Value for the amount of power to use when in active power mode idle_power_usage (num) Value for the amount of power to use when in idle power mode power_channel (num) What channel to draw from when drawing power for power mode Possible Values: EQUIP:0 -- Equipment Channel LIGHT:2 -- Lighting Channel ENVIRON:3 -- Environment Channel component_parts (list) A list of component parts of machine used by frame based machines. uid (num) Unique id of machine across all machines. gl_uid (global num) Next uid value in sequence stat (bitflag) Machine status bit flags. Possible bit flags: BROKEN:1 -- Machine is broken NOPOWER:2 -- No power is being supplied to machine. POWEROFF:4 -- tbd MAINT:8 -- machine is currently under going maintenance. EMPED:16 -- temporary broken by EMP pulse manual (num) Currently unused. Class Procs: New() 'game/machinery/machine.dm' Del() 'game/machinery/machine.dm' auto_use_power() 'game/machinery/machine.dm' This proc determines how power mode power is deducted by the machine. 'auto_use_power()' is called by the 'master_controller' game_controller every tick. Return Value: return:1 -- if object is powered return:0 -- if object is not powered. Default definition uses 'use_power', 'power_channel', 'active_power_usage', 'idle_power_usage', 'powered()', and 'use_power()' implement behavior. powered(chan = EQUIP) 'modules/power/power.dm' Checks to see if area that contains the object has power available for power channel given in 'chan'. use_power(amount, chan=EQUIP, autocalled) 'modules/power/power.dm' Deducts 'amount' from the power channel 'chan' of the area that contains the object. If it's autocalled then everything is normal, if something else calls use_power we are going to need to recalculate the power two ticks in a row. power_change() 'modules/power/power.dm' Called by the area that contains the object when ever that area under goes a power state change (area runs out of power, or area channel is turned off). RefreshParts() 'game/machinery/machine.dm' Called to refresh the variables in the machine that are contributed to by parts contained in the component_parts list. (example: glass and material amounts for the autolathe) Default definition does nothing. assign_uid() 'game/machinery/machine.dm' Called by machine to assign a value to the uid variable. process() 'game/machinery/machine.dm' Called by the 'master_controller' once per game tick for each machine that is listed in the 'machines' list. Compiled by Aygar */ /obj/machinery name = "machinery" icon = 'icons/obj/stationobjs.dmi' var/stat = 0 var/emagged = 0 var/use_power = 1 //0 = dont run the auto //1 = run auto, use idle //2 = run auto, use active var/idle_power_usage = 0 var/active_power_usage = 0 var/power_channel = EQUIP //EQUIP,ENVIRON or LIGHT var/list/component_parts = list() //list of all the parts used to build it, if made from certain kinds of frames. var/uid var/manual = 0 var/interact_offline = 0 // Can the machine be interacted with while de-powered. var/global/gl_uid = 1 /obj/machinery/drain_power(var/drain_check) if(drain_check) return 1 if(!powered()) return 0 var/area/area = get_area(src) if(!area) return 0 var/obj/machinery/power/apc/apc = area.get_apc() if(!apc) return 0 return apc.drain_power() /obj/machinery/New() ..() if(!machinery_sort_required && ticker) dd_insertObjectList(machines, src) else machines += src machinery_sort_required = 1 /obj/machinery/Del() machines -= src ..() /obj/machinery/process()//If you dont use process or power why are you here return PROCESS_KILL /obj/machinery/emp_act(severity) if(use_power && stat == 0) use_power(7500/severity) var/obj/effect/overlay/pulse2 = new/obj/effect/overlay ( src.loc ) pulse2.icon = 'icons/effects/effects.dmi' pulse2.icon_state = "empdisable" pulse2.name = "emp sparks" pulse2.anchored = 1 pulse2.set_dir(pick(cardinal)) spawn(10) pulse2.delete() ..() /obj/machinery/ex_act(severity) switch(severity) if(1.0) del(src) return if(2.0) if (prob(50)) del(src) return if(3.0) if (prob(25)) del(src) return else return /obj/machinery/blob_act() if(prob(50)) del(src) //sets the use_power var and then forces an area power update /obj/machinery/proc/update_use_power(var/new_use_power, var/force_update = 0) use_power = new_use_power /obj/machinery/proc/auto_use_power() if(!powered(power_channel)) return 0 if(src.use_power == 1) use_power(idle_power_usage,power_channel, 1) else if(src.use_power >= 2) use_power(active_power_usage,power_channel, 1) return 1 /obj/machinery/proc/operable(var/additional_flags = 0) return !inoperable(additional_flags) /obj/machinery/proc/inoperable(var/additional_flags = 0) return (stat & (NOPOWER|BROKEN|additional_flags)) /obj/machinery/Topic(href, href_list, var/nowindow = 0, var/checkrange = 1) if(..()) return 1 if(!can_be_used_by(usr, be_close = checkrange)) return 1 add_fingerprint(usr) return 0 /obj/machinery/proc/can_be_used_by(mob/user, be_close = 1) if(!interact_offline && stat & (NOPOWER|BROKEN)) return 0 if(!user.canUseTopic(src, be_close)) return 0 return 1 //////////////////////////////////////////////////////////////////////////////////////////// /mob/proc/canUseTopic(atom/movable/M, be_close = 1) return /mob/dead/observer/canUseTopic(atom/movable/M, be_close = 1) if(check_rights(R_ADMIN, 0)) return /mob/living/canUseTopic(atom/movable/M, be_close = 1, no_dextery = 0) if(no_dextery) src << "You don't have the dexterity to do this!" return 0 return be_close && !in_range(M, src) /mob/living/carbon/human/canUseTopic(atom/movable/M, be_close = 1) if(restrained() || lying || stat || stunned || weakened) return if(be_close && !in_range(M, src)) if(TK in mutations) var/mob/living/carbon/human/H = M if(istype(H.l_hand, /obj/item/tk_grab) || istype(H.r_hand, /obj/item/tk_grab)) return 1 return if(!isturf(M.loc) && M.loc != src) return return 1 /mob/living/silicon/ai/canUseTopic(atom/movable/M) if(stat) return //stop AIs from leaving windows open and using then after they lose vision //apc_override is needed here because AIs use their own APC when powerless if(cameranet && !cameranet.checkTurfVis(get_turf(M)) && !apc_override) return return 1 /mob/living/silicon/robot/canUseTopic(atom/movable/M) if(stat || lockcharge || stunned || weakened) return return 1 //////////////////////////////////////////////////////////////////////////////////////////// /obj/machinery/attack_ai(mob/user as mob) if(isrobot(user)) // For some reason attack_robot doesn't work // This is to stop robots from using cameras to remotely control machines. if(user.client && user.client.eye == user) return src.attack_hand(user) else return src.attack_hand(user) /obj/machinery/attack_hand(mob/user as mob) if(inoperable(MAINT)) return 1 if(user.lying || user.stat) return 1 if ( ! (istype(usr, /mob/living/carbon/human) || \ istype(usr, /mob/living/silicon) || \ istype(usr, /mob/living/carbon/monkey)) ) usr << "\red You don't have the dexterity to do this!" return 1 /* //distance checks are made by atom/proc/DblClick if ((get_dist(src, user) > 1 || !istype(src.loc, /turf)) && !istype(user, /mob/living/silicon)) return 1 */ if (ishuman(user)) var/mob/living/carbon/human/H = user if(H.getBrainLoss() >= 60) visible_message("\red [H] stares cluelessly at [src] and drools.") return 1 else if(prob(H.getBrainLoss())) user << "\red You momentarily forget how to use [src]." return 1 src.add_fingerprint(user) return 0 /obj/machinery/proc/RefreshParts() //Placeholder proc for machines that are built using frames. return /obj/machinery/proc/assign_uid() uid = gl_uid gl_uid++ /obj/machinery/proc/state(var/msg) for(var/mob/O in hearers(src, null)) O.show_message("\icon[src] [msg]", 2) /obj/machinery/proc/ping(text=null) if (!text) text = "\The [src] pings." state(text, "blue") playsound(src.loc, 'sound/machines/ping.ogg', 50, 0) /obj/machinery/proc/shock(mob/user, prb) if(inoperable()) return 0 if(!prob(prb)) return 0 var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread s.set_up(5, 1, src) s.start() if (electrocute_mob(user, get_area(src), src, 0.7)) var/area/temp_area = get_area(src) if(temp_area && temp_area.master) var/obj/machinery/power/apc/temp_apc = temp_area.master.get_apc() if(temp_apc && temp_apc.terminal && temp_apc.terminal.powernet) temp_apc.terminal.powernet.trigger_warning() return 1 else return 0 /obj/machinery/proc/dismantle() playsound(loc, 'sound/items/Crowbar.ogg', 50, 1) var/obj/machinery/constructable_frame/machine_frame/M = new /obj/machinery/constructable_frame/machine_frame(loc) M.state = 2 M.icon_state = "box_1" for(var/obj/I in component_parts) if(I.reliability != 100 && crit_fail) I.crit_fail = 1 I.loc = loc del(src) return 1 /obj/machinery/proc/on_assess_perp(mob/living/carbon/human/perp) return 0 /obj/machinery/proc/is_assess_emagged() return emagged /obj/machinery/proc/assess_perp(mob/living/carbon/human/perp, var/auth_weapons, var/check_records, var/check_arrest) var/threatcount = 0 //the integer returned if(is_assess_emagged()) return 10 //if emagged, always return 10. threatcount += on_assess_perp(perp) if(threatcount >= 10) return threatcount //Agent cards lower threatlevel. var/obj/item/weapon/card/id/id = GetIdCard(perp) if(id && istype(id, /obj/item/weapon/card/id/syndicate)) threatcount -= 2 if(auth_weapons && !src.allowed(perp)) if(istype(perp.l_hand, /obj/item/weapon/gun) || istype(perp.l_hand, /obj/item/weapon/melee)) threatcount += 4 if(istype(perp.r_hand, /obj/item/weapon/gun) || istype(perp.r_hand, /obj/item/weapon/melee)) threatcount += 4 if(istype(perp.belt, /obj/item/weapon/gun) || istype(perp.belt, /obj/item/weapon/melee)) threatcount += 2 if(perp.dna && perp.dna.mutantrace && perp.dna.mutantrace != "none") threatcount += 2 if(check_records || check_arrest) var/perpname = perp.name if(id) perpname = id.registered_name var/datum/data/record/R = find_security_record("name", perpname) if(check_records && !R) threatcount += 4 if(check_arrest && R && (R.fields["criminal"] == "*Arrest*")) threatcount += 4 return threatcount