Initial Commit

This commit is contained in:
Tobba
2016-03-06 20:52:14 +01:00
commit b181d0b552
4325 changed files with 579453 additions and 0 deletions
+893
View File
@@ -0,0 +1,893 @@
var/datum/action_controller/actions
//See _setup.dm for interrupt and state definitions
/datum/action_controller
var/list/running = list() //Associative list of running actions, format: owner=list of action datums
proc/hasAction(var/atom/owner, var/id) //has this mob an action of a given type running?
if(running.Find(owner))
var/list/actions = running[owner]
for(var/datum/action/A in actions)
if(A.id == id) return 1
return 0
proc/stop_all(var/atom/owner) //Interrupts all actions of a given owner.
if(running.Find(owner))
for(var/datum/action/A in running[owner])
A.interrupt(INTERRUPT_ALWAYS)
return
proc/stop(var/datum/action/A, var/atom/owner) //Manually interrupts a given action of a given owner.
if(running.Find(owner))
var/list/actions = running[owner]
if(actions.Find(A))
A.interrupt(INTERRUPT_ALWAYS)
return
proc/stopId(var/id, var/atom/owner) //Manually interrupts a given action id of a given owner.
if(running.Find(owner))
var/list/actions = running[owner]
for(var/datum/action/A in actions)
if(A.id == id)
A.interrupt(INTERRUPT_ALWAYS)
return
proc/start(var/datum/action/A, var/atom/owner) //Starts a new action.
if(!running.Find(owner))
running.Add(owner)
running[owner] = list(A)
A.owner = owner
A.started = world.time
A.onStart()
else
interrupt(owner, INTERRUPT_ACTION)
running[owner] += A
A.owner = owner
A.started = world.time
A.onStart()
return
proc/interrupt(var/atom/owner, var/flag) //Is called by all kinds of things to check for action interrupts.
if(running.Find(owner))
for(var/datum/action/A in running[owner])
A.interrupt(flag)
return
proc/process() //Handles the action countdowns, updates and deletions.
for(var/X in running)
for(var/datum/action/A in running[X])
if( ((A.duration >= 0 && world.time >= (A.started + A.duration)) && A.state == ACTIONSTATE_RUNNING) || A.state == ACTIONSTATE_FINISH)
A.state = ACTIONSTATE_ENDED
A.onEnd()
//continue //If this is not commented out the deletion will take place the tick after the action ends. This will break things like objects being deleted onEnd with progressbars - the bars will be left behind. But it will look better for things that do not do this.
if(A.state == ACTIONSTATE_DELETE)
A.onDelete()
running[X] -= A
continue
A.onUpdate()
if(length(running[X]) == 0)
running.Remove(X)
return
/datum/action
var/atom/owner = null //Object that owns this action.
var/duration = 1 //How long does this action take in ticks.
var/interrupt_flags = INTERRUPT_MOVE | INTERRUPT_ACT | INTERRUPT_STUNNED | INTERRUPT_ACTION //When and how this action is interrupted.
var/state = ACTIONSTATE_STOPPED //Current state of the action.
var/started = -1 //world.time this action was started at
var/id = "base" //Unique ID for this action. For when you want to remove actions by ID on a person.
proc/interrupt(var/flag) //This is called by the default interrupt actions
if(interrupt_flags & flag || flag == INTERRUPT_ALWAYS)
state = ACTIONSTATE_INTERRUPTED
onInterrupt(flag)
return
proc/onUpdate() //Called every tick this action is running. If you absolutely(!!!) have to you can do manual interrupt checking in here. Otherwise this is mostly used for drawing progress bars and shit.
return
proc/onInterrupt(var/flag = 0) //Called when the action fails / is interrupted.
state = ACTIONSTATE_DELETE
return
proc/onStart() //Called when the action begins
state = ACTIONSTATE_RUNNING
return
proc/onEnd() //Called when the action succesfully ends.
state = ACTIONSTATE_DELETE
return
proc/onDelete() //Called when the action is complete and about to be deleted. Usable for cleanup and such.
return
/datum/action/bar //This subclass has a progressbar that attaches to the owner to show how long we need to wait.
var/obj/actions/bar/bar
var/obj/actions/border/border
onStart()
..()
if(owner != null)
bar = unpool(/obj/actions/bar)
bar.loc = owner.loc
border = unpool(/obj/actions/border)
border.loc = owner.loc
bar.pixel_y = 5
border.pixel_y = 5
owner.attached_objs.Add(bar)
owner.attached_objs.Add(border)
onDelete()
..()
if(owner != null)
owner.attached_objs.Remove(bar)
owner.attached_objs.Remove(border)
if (bar)
pool(bar)
bar = null
if (border)
pool(border)
border = null
onEnd()
bar.color = "#00FF00"
bar.transform = matrix() //Tiny cosmetic fix. Makes it so the bar is completely filled when the action ends.
bar.pixel_x = 0
..()
onInterrupt(var/flag)
if(state != ACTIONSTATE_DELETE)
bar.color = "#FF0000"
..()
onUpdate()
var/done = world.time - started
var/complete = max(min((done / duration), 1), 0)
bar.transform = matrix(complete, 1, MATRIX_SCALE)
bar.color = "#0000FF"
bar.pixel_x = -nround( ((30 - (30 * complete)) / 2) )
..()
/datum/action/bar/blob_health // WOW HACK
onUpdate()
var/obj/blob/B = owner
if (!owner || !istype(owner))
return
if (B.health == B.health_max)
border.invisibility = 101
bar.invisibility = 101
else
border.invisibility = 0
bar.invisibility = 0
var/complete = B.health / B.health_max
bar.color = "#00FF00"
bar.transform = matrix(complete, 1, MATRIX_SCALE)
bar.pixel_x = -nround( ((30 - (30 * complete)) / 2) )
/datum/action/bar/bullethell
var/obj/actions/bar/shield_bar
var/obj/actions/bar/armor_bar
onStart()
..()
if(owner != null)
shield_bar = unpool(/obj/actions/bar)
shield_bar.loc = owner.loc
armor_bar = unpool(/obj/actions/bar)
armor_bar.loc = owner.loc
shield_bar.pixel_y = 5
armor_bar.pixel_y = 5
owner.attached_objs.Add(shield_bar)
owner.attached_objs.Add(armor_bar)
shield_bar.layer = initial(shield_bar.layer) + 2
armor_bar.layer = initial(armor_bar.layer) + 1
onDelete()
..()
shield_bar.invisibility = 0
armor_bar.invisibility = 0
bar.invisibility = 0
border.invisibility = 0
if(owner != null)
owner.attached_objs.Remove(shield_bar)
owner.attached_objs.Remove(armor_bar)
pool(shield_bar)
shield_bar = null
pool(armor_bar)
armor_bar = null
onUpdate()
var/obj/bullethell/B = owner
if (!owner || !istype(owner))
return
var/h_complete = B.health / B.max_health
bar.color = "#00FF00"
bar.transform = matrix(h_complete, 1, MATRIX_SCALE)
bar.pixel_x = -nround( ((30 - (30 * h_complete)) / 2) )
if (B.max_armor && B.armor)
armor_bar.invisibility = 0
var/a_complete = B.armor / B.max_armor
armor_bar.color = "#FF8800"
armor_bar.transform = matrix(a_complete, 1, MATRIX_SCALE)
armor_bar.pixel_x = -nround( ((30 - (30 * a_complete)) / 2) )
else
armor_bar.invisibility = 101
if (B.max_shield && B.shield)
shield_bar.invisibility = 0
var/s_complete = B.shield / B.max_shield
shield_bar.color = "#3333FF"
shield_bar.transform = matrix(s_complete, 1, MATRIX_SCALE)
shield_bar.pixel_x = -nround( ((30 - (30 * s_complete)) / 2) )
else
shield_bar.invisibility = 101
/datum/action/bar/blob_replicator
onUpdate()
var/obj/blob/deposit/replicator/B = owner
if (!owner)
return
if (!B.converting || (B.converting && !B.converting.maximum_volume))
border.invisibility = 101
bar.invisibility = 101
return
else
border.invisibility = 0
bar.invisibility = 0
var/complete = 1 - (B.converting.total_volume / B.converting.maximum_volume)
bar.color = "#0000FF"
bar.transform = matrix(complete, 1, MATRIX_SCALE)
bar.pixel_x = -nround( ((30 - (30 * complete)) / 2) )
onDelete()
bar.invisibility = 0
border.invisibility = 0
..()
/datum/action/bar/icon //Visible to everyone and has an icon.
var/icon
var/icon_state
var/icon_y_off = 20
var/icon_x_off = 0
var/image/icon_image
onStart()
..()
if(icon && icon_state && owner)
icon_image = image(icon, border ,icon_state, 7)
icon_image.pixel_y = icon_y_off
icon_image.pixel_x = icon_x_off
border.overlays += icon_image
onDelete()
bar.overlays.Cut()
del(icon_image)
..()
/datum/action/bar/icon/build
duration = 30
var/obj/item/sheet/sheet
var/objtype
var/cost
var/datum/material/mat
var/amount
var/objname
var/callback = null
New(var/obj/item/sheet/csheet, var/cobjtype, var/ccost, var/datum/material/cmat, var/camount, var/cicon, var/cicon_state, var/cobjname, var/post_action_callback = null)
..()
icon = cicon
icon_state = cicon_state
sheet = csheet
objtype = cobjtype
cost = ccost
mat = cmat
amount = camount
objname = cobjname
callback = post_action_callback
onStart()
..()
if(istype(owner, /mob/living/carbon/human))
var/mob/living/carbon/human/H = owner
if(H.traitHolder.hasTrait("carpenter"))
duration = round(duration / 2)
owner.visible_message("<span style=\"color:blue\">[owner] begins assembling [objname]!</span>")
onEnd()
..()
owner.visible_message("<span style=\"color:blue\">[owner] assembles [objname]!</span>")
var/obj/item/R = new objtype(get_turf(owner))
R.setMaterial(mat)
if (istype(R))
R.amount = amount
R.dir = owner.dir
sheet.consume_sheets(cost)
logTheThing("station", owner, null, "builds [objname] (<b>Material:</b> [mat && istype(mat) && mat.mat_id ? "[mat.mat_id]" : "*UNKNOWN*"]) at [log_loc(owner)].")
if (callback)
call(callback)(src, R)
/datum/action/bar/icon/cruiser_repair
id = "genproc"
interrupt_flags = INTERRUPT_MOVE | INTERRUPT_ACT | INTERRUPT_STUNNED | INTERRUPT_ACTION
duration = 30
icon = 'icons/ui/actions.dmi'
icon_state = "working"
var/obj/machinery/cruiser_destroyable/repairing
var/obj/item/using
New(var/obj/machinery/cruiser_destroyable/D, var/obj/item/U, var/duration_i)
..()
repairing = D
using = U
duration = duration_i
onUpdate()
..()
if(get_dist(owner, repairing) > 1 || repairing == null || owner == null || using == null)
interrupt(INTERRUPT_ALWAYS)
return
var/mob/source = owner
if(using != source.equipped())
interrupt(INTERRUPT_ALWAYS)
onStart()
..()
owner.visible_message("<span style=\"color:blue\">[owner] begins repairing [repairing]!</span>")
onEnd()
..()
owner.visible_message("<span style=\"color:blue\">[owner] successfully repairs [repairing]!</span>")
repairing.adjustHealth(repairing.health_max)
/datum/action/bar/private //This subclass is only visible to the owner of the action
onStart()
..()
bar.icon = null
border.icon = null
owner << bar.img
owner << border.img
onDelete()
bar.icon = 'icons/ui/actions.dmi'
border.icon = 'icons/ui/actions.dmi'
del(bar.img)
del(border.img)
..()
/datum/action/bar/private/icon //Only visible to the owner and has a little icon on the bar.
var/icon
var/icon_state
var/icon_y_off = 25
var/icon_x_off = 0
var/image/icon_image
onStart()
..()
if(icon && icon_state && owner)
icon_image = image(icon ,owner,icon_state,7)
icon_image.pixel_y = icon_y_off
icon_image.pixel_x = icon_x_off
owner << icon_image
onDelete()
del(icon_image)
..()
//ACTIONS
/datum/action/bar/icon/genericProc //Calls a specific proc with the given arguments when the action succeeds. TBI
id = "genproc"
interrupt_flags = INTERRUPT_MOVE | INTERRUPT_ACT | INTERRUPT_STUNNED | INTERRUPT_ACTION
icon = 'icons/mob/screen1.dmi'
icon_state = "grabbed"
/datum/action/bar/icon/otherItem//Putting items on or removing items from others.
id = "otheritem"
interrupt_flags = INTERRUPT_MOVE | INTERRUPT_ACT | INTERRUPT_STUNNED | INTERRUPT_ACTION
icon = 'icons/mob/screen1.dmi'
icon_state = "grabbed"
var/mob/living/carbon/human/source //The person doing the action
var/mob/living/carbon/human/target //The target of the action
var/obj/item/item //The item if any. If theres no item, we tried to remove something from that slot instead of putting an item there.
var/slot //The slot number
New(var/Source, var/Target, var/Item, var/Slot)
source = Source
target = Target
item = Item
slot = Slot
if(item)
if(item.duration_put > 0)
duration = item.duration_put
else
duration = 45
else
var/obj/item/I = target.get_slot(slot)
if(I)
if(I.duration_remove > 0)
duration = I.duration_remove
else
duration = 25
..()
onStart()
..()
target.add_fingerprint(source) // Added for forensics (Convair880).
if(item)
if(!target.can_equip(item, slot))
boutput(source, "<span style=\"color:red\">[item] can not be put there.</span>")
interrupt(INTERRUPT_ALWAYS)
return
logTheThing("combat", source, target, "tries to put \an [item] on %target% at at [log_loc(target)].")
for(var/mob/O in AIviewers(owner))
O.show_message("<span style=\"color:red\"><B>[source] tries to put [item] on [target]!</B></span>", 1)
else
var/obj/item/I = target.get_slot(slot)
if(!I)
boutput(source, "<span style=\"color:red\">There's nothing in that slot.</span>")
interrupt(INTERRUPT_ALWAYS)
return
/* Some things use handle_other_remove to do stuff (ripping out staples, wiz hat probability, etc) should only be called once per removal.
if(!I.handle_other_remove(source, target))
boutput(source, "<span style=\"color:red\">[I] can not be removed.</span>")
interrupt(INTERRUPT_ALWAYS)
return
*/
logTheThing("combat", source, target, "tries to remove \an [I] from %target% at [log_loc(target)].")
for(var/mob/O in AIviewers(owner))
O.show_message("<span style=\"color:red\"><B>[source] tries to remove something from [target]!</B></span>", 1)
onEnd()
..()
if(get_dist(source, target) > 1 || target == null || source == null)
interrupt(INTERRUPT_ALWAYS)
return
var/obj/item/I = target.get_slot(slot)
if(item)
if(item == source.equipped() && !I)
if(target.can_equip(item, slot))
logTheThing("combat", source, target, "successfully puts \an [item] on %target% at at [log_loc(target)].")
for(var/mob/O in AIviewers(owner))
O.show_message("<span style=\"color:red\"><B>[source] puts [item] on [target]!</B></span>", 1)
source.u_equip(item)
target.force_equip(item, slot)
else if (I) //Wire: Fix for Cannot execute null.handle other remove().
if(I.handle_other_remove(source, target))
logTheThing("combat", source, target, "successfully removes \an [I] from %target% at [log_loc(target)].")
for(var/mob/O in AIviewers(owner))
O.show_message("<span style=\"color:red\"><B>[source] removes [I] from [target]!</B></span>", 1)
// Re-added (Convair880).
if (istype(I, /obj/item/mousetrap/))
var/obj/item/mousetrap/MT = I
if (MT && MT.armed)
for (var/mob/O in AIviewers(owner))
O.show_message("<span style=\"color:red\"><B>...and triggers it accidentally!</B></span>", 1)
MT.triggered(source, source.hand ? "l_hand" : "r_hand")
else if (istype(I, /obj/item/mine))
var/obj/item/mine/M = I
if (M.armed && M.used_up != 1)
for (var/mob/O in AIviewers(owner))
O.show_message("<span style=\"color:red\"><B>...and triggers it accidentally!</B></span>", 1)
M.triggered(source)
target.u_equip(I)
I.set_loc(target.loc)
I.dropped(target)
I.layer = initial(I.layer)
I.add_fingerprint(source)
else
boutput(source, "<span style=\"color:red\">You fail to remove [I] from [target].</span>")
onUpdate()
..()
if(get_dist(source, target) > 1 || target == null || source == null)
interrupt(INTERRUPT_ALWAYS)
return
if(item)
if(item != source.equipped() || target.get_slot(slot))
interrupt(INTERRUPT_ALWAYS)
else
if(!target.get_slot(slot=slot))
interrupt(INTERRUPT_ALWAYS)
/datum/action/bar/icon/internalsOther //This is used when you try to set someones internals
duration = 40
interrupt_flags = INTERRUPT_MOVE | INTERRUPT_ACT | INTERRUPT_STUNNED | INTERRUPT_ACTION
id = "internalsother"
icon = 'icons/obj/clothing/item_masks.dmi'
icon_state = "breath"
var/mob/living/carbon/human/target
var/remove_internals
New(Target)
target = Target
..()
onUpdate()
..()
if(get_dist(owner, target) > 1 || target == null || owner == null)
interrupt(INTERRUPT_ALWAYS)
return
onStart()
..()
if(get_dist(owner, target) > 1 || target == null || owner == null)
interrupt(INTERRUPT_ALWAYS)
return
for(var/mob/O in AIviewers(owner))
if(target.internal)
O.show_message("<span style=\"color:red\"><B>[owner] attempts to remove [target]'s internals!</B></span>", 1)
remove_internals = 1
else
O.show_message("<span style=\"color:red\"><B>[owner] attempts to set [target]'s internals!</B></span>", 1)
remove_internals = 0
onEnd()
..()
if(owner && target && get_dist(owner, target) <= 1)
if(remove_internals)
target.internal.add_fingerprint(owner)
for (var/obj/ability_button/tank_valve_toggle/T in target.internal.ability_buttons)
T.icon_state = "airoff"
target.internal = null
for(var/mob/O in AIviewers(owner))
O.show_message("<span style=\"color:red\"><B>[owner] removes [target]'s internals!</B></span>", 1)
else
if (!istype(target.wear_mask, /obj/item/clothing/mask))
interrupt(INTERRUPT_ALWAYS)
return
else
if (istype(target.back, /obj/item/tank))
target.internal = target.back
for (var/obj/ability_button/tank_valve_toggle/T in target.internal.ability_buttons)
T.icon_state = "airon"
for(var/mob/M in AIviewers(target, 1))
M.show_message(text("[] is now running on internals.", src.target), 1)
target.internal.add_fingerprint(owner)
/datum/action/bar/icon/handcuffSet //This is used when you try to handcuff someone.
duration = 40
interrupt_flags = INTERRUPT_MOVE | INTERRUPT_ACT | INTERRUPT_STUNNED | INTERRUPT_ACTION
id = "handcuffsset"
icon = 'icons/obj/items.dmi'
icon_state = "handcuff"
var/mob/living/carbon/human/target
var/obj/item/handcuffs/cuffs
New(Target, Cuffs)
target = Target
cuffs = Cuffs
..()
onUpdate()
..()
if(get_dist(owner, target) > 1 || target == null || owner == null || cuffs == null)
interrupt(INTERRUPT_ALWAYS)
return
if(target.handcuffed)
interrupt(INTERRUPT_ALWAYS)
return
onStart()
..()
if(get_dist(owner, target) > 1 || target == null || owner == null || cuffs == null)
interrupt(INTERRUPT_ALWAYS)
return
for(var/mob/O in AIviewers(owner))
O.show_message("<span style=\"color:red\"><B>[owner] attempts to handcuff [target]!</B></span>", 1)
onEnd()
..()
var/mob/ownerMob = owner
if(owner && ownerMob && target && cuffs && !target.handcuffed && cuffs == ownerMob.equipped() && get_dist(owner, target) <= 1)
var/obj/item/handcuffs/cuffs2
if (issilicon(ownerMob))
cuffs2 = new /obj/item/handcuffs
else
if (cuffs.amount >= 2)
cuffs2 = new /obj/item/handcuffs/tape
cuffs.amount--
boutput(ownerMob, "<span style=\"color:blue\">The [cuffs.name] now has [cuffs.amount] lengths of [istype(cuffs, /obj/item/handcuffs/tape_roll) ? "tape" : "ziptie"] left.</span>")
else if (cuffs.amount == 1 && cuffs.delete_on_last_use == 1)
cuffs2 = new /obj/item/handcuffs/tape
ownerMob.u_equip(cuffs)
boutput(ownerMob, "<span style=\"color:red\">You used up the remaining length of [istype(cuffs, /obj/item/handcuffs/tape_roll) ? "tape" : "ziptie"].</span>")
qdel(cuffs)
else
ownerMob.u_equip(cuffs)
logTheThing("combat", ownerMob, target, "handcuffs %target% with [cuffs2 ? "[cuffs2]" : "[cuffs]"] at [log_loc(ownerMob)].")
if (cuffs2 && istype(cuffs2))
cuffs2.set_loc(target)
target.handcuffed = cuffs2
else
cuffs.set_loc(target)
target.handcuffed = cuffs
target.drop_from_slot(target.r_hand)
target.drop_from_slot(target.l_hand)
target.drop_juggle()
target.update_clothing()
for(var/mob/O in AIviewers(ownerMob))
O.show_message("<span style=\"color:red\"><B>[owner] handcuffs [target]!</B></span>", 1)
/datum/action/bar/icon/handcuffRemovalOther //This is used when you try to remove someone elses handcuffs.
duration = 70
interrupt_flags = INTERRUPT_MOVE | INTERRUPT_ACT | INTERRUPT_STUNNED | INTERRUPT_ACTION
id = "handcuffsother"
icon = 'icons/obj/items.dmi'
icon_state = "handcuff"
var/mob/living/carbon/human/target
New(Target)
target = Target
..()
onUpdate()
..()
if(get_dist(owner, target) > 1 || target == null || owner == null)
interrupt(INTERRUPT_ALWAYS)
return
if(!target.handcuffed)
interrupt(INTERRUPT_ALWAYS)
return
onStart()
..()
if(get_dist(owner, target) > 1 || target == null || owner == null)
interrupt(INTERRUPT_ALWAYS)
return
for(var/mob/O in AIviewers(owner))
O.show_message("<span style=\"color:red\"><B>[owner] attempts to remove [target]'s handcuffs!</B></span>", 1)
onEnd()
..()
if(owner && target && target.handcuffed)
var/mob/living/carbon/human/H = target
H.handcuffed:set_loc(H.loc)
H.handcuffed.unequipped(H)
H.handcuffed = null
H.update_clothing()
for(var/mob/O in AIviewers(H))
O.show_message("<span style=\"color:red\"><B>[owner] manages to remove [target]'s handcuffs!</B></span>", 1)
/datum/action/bar/private/icon/handcuffRemoval //This is used when you try to resist out of handcuffs.
duration = 600
interrupt_flags = INTERRUPT_MOVE | INTERRUPT_ACT | INTERRUPT_STUNNED | INTERRUPT_ACTION
id = "handcuffs"
icon = 'icons/obj/items.dmi'
icon_state = "handcuff"
New(var/dur)
duration = dur
..()
onStart()
..()
for(var/mob/O in AIviewers(owner))
O.show_message(text("<span style=\"color:red\"><B>[] attempts to remove the handcuffs!</B></span>", owner), 1)
onInterrupt(var/flag)
..()
boutput(owner, "<span style=\"color:red\">Your attempt to remove your handcuffs was interrupted!</span>")
onEnd()
..()
if(owner != null && istype(owner, /mob/living/carbon/human) && owner:handcuffed)
var/mob/living/carbon/human/H = owner
H.handcuffed:set_loc(H.loc)
H.handcuffed.unequipped(H)
H.handcuffed = null
H.update_clothing()
if (H.handcuffed)
H.handcuffed.layer = initial(H.handcuffed.layer)
for(var/mob/O in AIviewers(H))
O.show_message("<span style=\"color:red\"><B>[H] manages to remove the handcuffs!</B></span>", 1)
boutput(H, "<span style=\"color:blue\">You successfully remove your handcuffs.</span>")
/datum/action/bar/private/icon/shackles_removal // Resisting out of shackles (Convair880).
duration = 450
interrupt_flags = INTERRUPT_MOVE | INTERRUPT_ACT | INTERRUPT_STUNNED | INTERRUPT_ACTION
id = "shackles"
icon = 'icons/obj/clothing/item_shoes.dmi'
icon_state = "orange1"
New(var/dur)
duration = dur
..()
onStart()
..()
for(var/mob/O in AIviewers(owner))
O.show_message(text("<span style=\"color:red\"><B>[] attempts to remove the shackles!</B></span>", owner), 1)
onInterrupt(var/flag)
..()
boutput(owner, "<span style=\"color:red\">Your attempt to remove the shackles was interrupted!</span>")
onEnd()
..()
if (owner != null && ishuman(owner))
var/mob/living/carbon/human/H = owner
if (H.shoes && H.shoes.chained)
var/obj/item/clothing/shoes/SH = H.shoes
H.u_equip(SH)
SH.set_loc(H.loc)
H.update_clothing()
if (SH)
SH.layer = initial(SH.layer)
for(var/mob/O in AIviewers(H))
O.show_message("<span style=\"color:red\"><B>[H] manages to remove the shackles!</B></span>", 1)
H.show_text("You successfully remove the shackles.", "blue")
//CLASSES & OBJS
/obj/actions //These objects are mostly used for the attached_objs var on mobs to attach progressbars to mobs.
icon = 'icons/ui/actions.dmi'
anchored = 1
density = 0
opacity = 0
layer = 5
name = ""
desc = ""
mouse_opacity = 0
/obj/actions/bar
icon_state = "bar"
layer = 6
var/image/img
New()
img = image('icons/ui/actions.dmi',src,"bar",6)
unpooled()
img = image('icons/ui/actions.dmi',src,"bar",6)
icon = initial(icon)
icon_state = initial(icon_state)
pooled()
loc = null
attached_objs = list()
overlays.len = 0
/obj/actions/border
icon_state = "border"
var/image/img
New()
img = image('icons/ui/actions.dmi',src,"border",5)
unpooled()
img = image('icons/ui/actions.dmi',src,"border",5)
icon = initial(icon)
icon_state = initial(icon_state)
pooled()
loc = null
attached_objs = list()
overlays.len = 0
//Use this to start the action
//actions.start(new/datum/action/bar/private/icon/magPicker(item, picker), usr)
/datum/action/bar/private/icon/magPicker
duration = 30 //How long does this action take in ticks.
interrupt_flags = INTERRUPT_MOVE | INTERRUPT_ACT | INTERRUPT_STUNNED | INTERRUPT_ACTION
id = "magpicker"
icon = 'icons/obj/items.dmi' //In these two vars you can define an icon you want to have on your little progress bar.
icon_state = "magtractor-small"
var/obj/item/target = null //This will contain the object we are trying to pick up.
var/obj/item/magtractor/picker = null //This is the magpicker.
New(Target, Picker)
target = Target
picker = Picker
..()
onUpdate() //check for special conditions that could interrupt the picking-up here.
..()
if(get_dist(owner, target) > 1 || picker == null || target == null || owner == null) //If the thing is suddenly out of range, interrupt the action. Also interrupt if the user or the item disappears.
interrupt(INTERRUPT_ALWAYS)
return
onStart()
..()
if(get_dist(owner, target) > 1 || picker == null || target == null || owner == null || picker.working) //If the thing is out of range, interrupt the action. Also interrupt if the user or the item disappears.
interrupt(INTERRUPT_ALWAYS)
return
else
picker.working = 1
playsound(picker.loc, "sound/machines/whistlebeep.ogg", 50, 1)
out(owner, "<span style='color: blue;'>The [picker.name] whirs and beeps as it charges it's coils. You must hold still...</span>")
onInterrupt(var/flag) //They did something else while picking it up. I guess you dont have to do anything here unless you want to.
..()
picker.working = 0
onEnd()
..()
//Shove the item into the picker here!!!
picker.pickupItem(target, owner)
actions.start(new/datum/action/magPickerHold(picker, picker.highpower), owner)
/datum/action/magPickerHold
duration = 30
interrupt_flags = INTERRUPT_MOVE | INTERRUPT_STUNNED
id = "magpickerhold"
var/obj/item/magtractor/picker = null //This is the magpicker.
New(Picker, hpm)
if (hpm)
src.interrupt_flags &= ~INTERRUPT_MOVE
picker = Picker
picker.holdAction = src
..()
onUpdate() //Again, check here for special conditions that are not normally handled in here. You probably dont need to do anything.
..()
if(picker == null || owner == null) //Interrupt if the user or the magpicker disappears.
interrupt(INTERRUPT_ALWAYS)
return
onStart()
..()
state = ACTIONSTATE_INFINITE //We can hold it indefinitely unless we move.
if(picker == null || owner == null) //Interrupt if the user or the magpicker dont exist.
interrupt(INTERRUPT_ALWAYS)
return
onEnd()
..()
picker.dropItem()
onInterrupt(var/flag)
..()
picker.dropItem()
//DEBUG STUFF
/datum/action/bar/private/bombtest
duration = 100
id = "bombtest"
onEnd()
..()
qdel(owner)
/obj/bombtest
name = "large cartoon bomb"
desc = "It looks like it's gonna blow."
icon = 'icons/obj/weapons.dmi'
icon_state = "dumb_bomb"
density = 1
New()
actions.start(new/datum/action/bar/private/bombtest(), src)
..()
@@ -0,0 +1,349 @@
var/datum/artifact_controller/artifact_controls
/datum/artifact_controller
var/list/artifacts = list()
var/list/artifact_types = list()
var/list/artifact_origins = list()
var/spawner_type = null
var/spawner_cine = 0
New()
..()
for (var/X in typesof(/datum/artifact) - /datum/artifact - /datum/artifact/art)
var/datum/artifact/A = new X
artifact_types += A
for (var/X in typesof(/datum/artifact_origin) - /datum/artifact_origin)
var/datum/artifact_origin/AO = new X
artifact_origins += AO
proc/get_origin_from_string(var/string)
if (!istext(string))
return
for (var/datum/artifact_origin/AO in src.artifact_origins)
if (AO.name == string)
return AO
return null
// Added. Admin actions related to artfacts were not logged at all (Convair880).
proc/log_me(var/mob/user, var/obj/O, var/type_of_action, var/trigger_alert = 0)
if (type_of_action == "spawns")
logTheThing("admin", user, null, "spawns a random artifact at [user && ismob(user) ? "[log_loc(user)]" : "*unknown*"].")
logTheThing("diary", user, null, "spawns a random artifact at [user && ismob(user) ? "[log_loc(user)]" : "*unknown*"].", "admin")
return
if (!O || !istype(O.artifact, /datum/artifact) || !type_of_action)
return
var/datum/artifact/A = O.artifact
logTheThing("admin", user, null, "[type_of_action] an artifact ([A.type]) at [log_loc(O)].")
logTheThing("diary", user, null, "[type_of_action] an artifact ([A.type]) at [log_loc(O)].", "admin")
if (trigger_alert)
message_admins("[key_name(user)] [type_of_action] an artifact ([A.type]) at [log_loc(O)].")
return
proc/config()
var/dat = "<html><body><title>Artifact Controller</title>"
dat += "<b><u>Artifact Controls</u></b><HR><small>"
dat += "<a href='byond://?src=\ref[src];Spawnnew=1'>Spawn a new Artifact on your current tile</b></a><br>"
dat += "<a href='byond://?src=\ref[src];Spawntype=1'>Spawn Type:</a> "
if (!spawner_type)
dat += "Random"
else
dat += "[spawner_type]"
dat += "<br><a href='byond://?src=\ref[src];Spawncine=1'>Cinematic Spawning:</a> "
if (spawner_cine)
dat += "Yes"
else
dat += "No"
dat += "<br><br>"
var/datum/artifact/A = null
var/turf/T = null
for (var/obj/O in src.artifacts)
if (!istype(O.artifact,/datum/artifact/))
continue
A = O.artifact
T = get_turf(O)
dat += "<b>"
if (A.internal_name)
dat += "[A.internal_name] "
else
dat += "Unnamed Artifact "
dat += "</b>"
if (istype(T,/turf/))
dat += "in [T.loc]<br>"
dat += "[O.name], [A.artitype.name], [A.type]<br>"
dat += "<a href='byond://?src=\ref[src];Activate=\ref[O]'>"
if (!A.activated)
dat += "Activate"
else
dat += "Deactivate"
dat += "</a> * "
dat += "<a href='byond://?src=\ref[src];Jumpto=\ref[O]'>Jump To</a> * "
dat += "<a href='byond://?src=\ref[src];Get=\ref[O]'>Get</a> * "
dat += "<a href='byond://?src=\ref[src];Destroy=\ref[O]'>Destroy</a><br><br>"
dat += "</small></body></html>"
usr << browse(dat,"window=artifacts;size=400x600")
Topic(href, href_list[])
if (href_list["Activate"])
var/obj/O = locate(href_list["Activate"]) in src.artifacts
if (!istype(O,/obj/))
return
if (!istype(O.artifact,/datum/artifact/))
return
var/datum/artifact/A = O.artifact
if (A.activated)
O.ArtifactDeactivated()
else
O.ArtifactActivated()
src.log_me(usr, O, A.activated ? "activates" : "deactivates", 1)
else if (href_list["Jumpto"])
var/obj/O = locate(href_list["Jumpto"]) in src.artifacts
if (!istype(O,/obj/))
return
var/turf/T = O.loc
usr.set_loc(T)
src.log_me(usr, O, "jumps to", 0)
else if (href_list["Get"])
var/obj/O = locate(href_list["Get"]) in src.artifacts
if (!istype(O,/obj/))
return
var/turf/T = usr.loc
O.set_loc(T)
src.log_me(usr, O, "teleports", 0)
else if (href_list["Destroy"])
var/obj/O = locate(href_list["Destroy"]) in src.artifacts
if (!istype(O,/obj/))
return
if (!istype(O.artifact,/datum/artifact/))
return
src.log_me(usr, O, "destroys", 1)
O.ArtifactDestroyed()
else if (href_list["Spawnnew"])
var/turf/T = get_turf(usr)
new /obj/artifact_spawner(T,spawner_type,spawner_cine)
src.log_me(usr, null, "spawns", 0)
else if (href_list["Spawntype"])
spawner_type = input("What type of artifact?","Artifact Controls") as null|anything in list("ancient","martian","wizard","eldritch","precursor")
else if (href_list["Spawncine"])
spawner_cine = !spawner_cine
src.config()
// Origins
/datum/artifact_origin
var/name = "unknown"
var/max_sprites = 7
var/impact_reaction_one = 0
var/impact_reaction_two = 0
var/heat_reaction_one = 0
var/fx_red_min = 0
var/fx_red_max = 255
var/fx_green_min = 0
var/fx_green_max = 255
var/fx_blue_min = 0
var/fx_blue_max = 255
var/list/activation_sounds = list()
var/list/fault_types = list("all")
var/list/adjectives = list("strange","unusual","odd","curious","bizarre","weird","abnormal","peculiar")
var/list/nouns_large = list("object","machine","artifact","contraption","structure","edifice")
var/list/nouns_small = list("item","device","relic","widget","utensil","gadget","accessory","gizmo")
var/list/touch_descriptors = list("You can't really tell how it feels.")
New()
..()
if ("all" in fault_types)
fault_types += typesof(/datum/artifact_fault) - /datum/artifact_fault
proc/generate_name()
return "unknown object"
/datum/artifact_origin/ancient
name = "ancient"
fault_types = list(/datum/artifact_fault/burn,/datum/artifact_fault/irradiate,/datum/artifact_fault/shutdown,
/datum/artifact_fault/murder,/datum/artifact_fault/zap)
activation_sounds = list('sound/machines/ArtifactAnc1.ogg')
impact_reaction_one = 1
impact_reaction_two = 0.5
heat_reaction_one = 1.5
fx_red_min = 50
fx_red_max = 255
fx_green_min = 50
fx_green_max = 255
fx_blue_min = 50
fx_blue_max = 255
adjectives = list("dark","cold","smooth","angular","humming","sharp-edged","droning")
nouns_large = list("monolith","slab","obelisk","pylon","menhir","machine","structure")
nouns_small = list("implement","device","instrument","apparatus","appliance","mechanism","tool")
touch_descriptors = list("It feels cold.","It feels smooth.","Touching it makes you feel uneasy.")
generate_name()
return "unit [pick("alpha","sigma","tau","phi","gamma","epsilon")]-[pick("x","z","d","e","k")] [rand(100,999)]"
/datum/artifact_origin/martian
name = "martian"
fault_types = list(/datum/artifact_fault/shutdown,/datum/artifact_fault/zap,/datum/artifact_fault/poison)
activation_sounds = list('sound/machines/ArtifactMar1.ogg','sound/machines/ArtifactMar2.ogg')
impact_reaction_one = 1
impact_reaction_two = 0
heat_reaction_one = 0.99
fx_red_min = 50
fx_red_max = 90
fx_green_min = 70
fx_green_max = 120
fx_blue_min = 50
fx_blue_max = 90
adjectives = list("squishy","gooey","clammy","quivering","twitching","pulpy","fleshy")
nouns_large = list("mass","pile","heap","glob","mound","clump","bulk")
nouns_small = list("lump","chunk","cluster","clod","nugget","giblet","organ")
touch_descriptors = list("It feels warm.","It feels gross.","You can feel a faint pulsing.")
var/list/prefix = list("cardio","neuro","physio","morpho","brachio","bronchi","dermo","ossu")
var/list/thingy = list("cystic","genetic","metabolic","static","vascular","muscular")
var/list/action = list("stimulator","suppressor","regenerator","depressor","mutator")
generate_name()
var/namestring = ""
namestring += "[pick(prefix)]"
namestring += "[pick(thingy)] "
namestring += "[pick(action)]"
return namestring
/datum/artifact_origin/wizard
name = "wizard"
fault_types = list(/datum/artifact_fault/irradiate,/datum/artifact_fault/shutdown,/datum/artifact_fault/murder,
/datum/artifact_fault/warp,/datum/artifact_fault/zap,/datum/artifact_fault/messager/creepy_whispers)
activation_sounds = list('sound/machines/ArtifactWiz1.ogg')
impact_reaction_one = 8
impact_reaction_two = 6
heat_reaction_one = 0.75
fx_red_min = 40
fx_red_max = 125
fx_green_min = 125
fx_green_max = 255
fx_blue_min = 125
fx_blue_max = 255
adjectives = list("ornate","regal","imposing","fancy","elaborate","elegant","ostentatious")
nouns_large = list("jewel","crystal","sculpture","statue","brazier","ornament","edifice")
nouns_small = list("wand","scepter","staff","rod","cane","crozier","trophy")
touch_descriptors = list("It feels warm.","It feels smooth.","It is suprisingly pleasant to touch.")
var/list/material = list("ebon","ivory","pearl","golden","malachite","diamond","ruby","emerald","sapphire","opal")
var/list/object = list("jewel","trophy","favor","boon","token","crown","treaure","sacrament","oath")
var/list/aspect = list("wonder","splendor","power","plenty","mystery","glory","majesty","eminence","grace")
generate_name()
var/namestring = ""
namestring += "[pick(material)] "
namestring += "[pick(object)] of "
namestring += "[pick(aspect)]"
return namestring
/datum/artifact_origin/eldritch
name = "eldritch"
activation_sounds = list('sound/machines/ArtifactEld1.ogg','sound/machines/ArtifactEld2.ogg')
impact_reaction_one = 0.5
impact_reaction_two = 0
heat_reaction_one = 0.25
fx_red_min = 40
fx_red_max = 255
fx_green_min = 40
fx_green_max = 255
fx_blue_min = 40
fx_blue_max = 255
adjectives = list("creepy","unnerving","ominous","threatening","horrid","evil-looking","lurid")
nouns_large = list("edifice","effigy","statue","idol","sculpture","stele","artifact")
nouns_small = list("spike","needle","thorns","relic","carving","figurine","item")
touch_descriptors = list("It feels cold.","It feels gross.","Touching it makes you feel uneasy.")
var/list/general_adjectives = list("dark","cold","horrid","foul","sinister","cruel","rancid","demonic")
var/list/object_nouns = list("hand","eye","finger","blood","breath","thorns","mantle","skin","bane","scourge","wrath",
"favor","will","tentacles","mandible","fangs","maw","flesh","ichor","teeth","heart")
var/list/people = list("master","lord","king","queen","lady","mother","father","master","beast","brute","tyrant")
var/list/person_adjectives = list("dread","great","old","ancient","vile","wicked","majestic","vast","mighty",
"evil","heartless","fierce","ferocious")
var/list/horror_name_start = list("trog","yogg","ta","y","has","shub","az","cth","cha","ul","xel","og","flu","wrk")
var/list/horror_name_mid = list("sog","ran","gon","ni","a","hul","ttur","ay","o","lo","ncac","sin","fel","di")
var/list/horror_name_end = list("dyte","oth","tula","olac","tur","bburath","thoth","hu","dha","aoth","tath","goth","ter")
generate_name()
var/the_horror = src.horror_name()
var/namestring = ""
if (prob(50))
if (prob(20))
namestring += "[pick(general_adjectives)] "
namestring += "[pick(object_nouns)] of "
if (prob(20))
namestring += "[pick(person_adjectives)] "
namestring += "[the_horror]"
else
if (prob(20))
namestring += "[pick(person_adjectives)] "
namestring += "[the_horror]'s "
if (prob(20))
namestring += "[pick(general_adjectives)] "
namestring += "[pick(object_nouns)]"
return namestring
proc/horror_name()
var/fthagn = ""
if (prob(20))
fthagn += "[pick(people)] "
fthagn += "[pick(horror_name_start)]"
if (prob(20))
fthagn += "[pick("'","-")]"
fthagn += "[pick(horror_name_mid)]"
if (prob(20))
fthagn += "[pick("'","-")]"
fthagn += "[pick(horror_name_end)]"
return fthagn // ia ia
/datum/artifact_origin/precursor
name = "precursor"
activation_sounds = list('sound/machines/ArtifactPre1.ogg')
impact_reaction_one = 2
impact_reaction_two = 10
heat_reaction_one = 2
fx_red_min = 155
fx_red_max = 255
fx_green_min = 155
fx_green_max = 255
fx_blue_min = 155
fx_blue_max = 255
adjectives = list("quirky","metallic","janky","bulky","chunky","cumbersome","unwieldy")
nouns_large = list("contraption","machine","object","mechanism","artifact","machinery","structure")
nouns_small = list("widget","thingy","device","appliance","mechanism","accessory","gizmo")
touch_descriptors = list("It feels warm.","It feels cold.","It is suprisingly pleasant to touch.",
"You can feel a faint pulsing.")
var/list/prefixes = list("meta","poly","anti","hyper","hypo","nano","mega","infra","ultra","trans","micro","macro")
var/list/particles = list("quark","tachyon","neutron","positron","photon","neutrino","lepton","baryon","atom","molecule")
var/list/verber = list("stabilizer","synchroniser","generator","coupler","fuser","linker","materializer")
generate_name()
var/namestring = ""
if (prob(40))
namestring += "[pick(prefixes)]"
namestring += "[pick(particles)] "
if (prob(33))
namestring += "de"
namestring += "[pick(verber)]"
return namestring
@@ -0,0 +1,38 @@
var/datum/disease_controller/disease_controls
/datum/disease_controller
var/list/standard_diseases = list()
var/list/custom_diseases = list()
New()
for (var/X in typesof(/datum/ailment))
if (X == /datum/ailment || X == /datum/ailment/disease || X == /datum/ailment/parasite || X == /datum/ailment/disability)
continue
var/datum/ailment/A = new X
standard_diseases += A
/proc/get_disease_from_path(var/disease_path)
if (!ispath(disease_path))
logTheThing("debug", null, null, "<b>Disease:</b> Attempt to find schematic with null path")
return null
if (!disease_controls.standard_diseases.len)
logTheThing("debug", null, null, "<b>Disease:</b> Cant find disease due to empty disease list")
return null
for (var/datum/ailment/A in disease_controls.standard_diseases)
if (disease_path == A.type)
return A
logTheThing("debug", null, null, "<b>Disease:</b> Disease \"[disease_path]\" not found")
return null
/proc/get_disease_from_name(var/disease_name)
if (!istext(disease_name))
logTheThing("debug", null, null, "<b>Disease:</b> Attempt to find disase with non-string")
return null
if (!disease_controls.standard_diseases.len && !disease_controls.custom_diseases.len)
logTheThing("debug", null, null, "<b>Disease:</b> Cant find schematic due to empty disease lists")
return null
for (var/datum/ailment/A in (disease_controls.standard_diseases + disease_controls.custom_diseases))
if (disease_name == A.name)
return A
logTheThing("debug", null, null, "<b>Disease:</b> Disease with name \"[disease_name]\" not found")
return null
+313
View File
@@ -0,0 +1,313 @@
var/datum/event_controller/random_events
/datum/event_controller
var/list/events = list()
var/events_begin = 18000 // 30m
var/time_between_events_lower = 6600 // 11m
var/time_between_events_upper = 12000 // 20m
var/events_enabled = 1
var/announce_events = 1
var/next_event = 0
var/event_cycle_count = 0
var/list/minor_events = list()
var/minor_events_begin = 6000 // 10m
var/time_between_minor_events_lower = 4000 // roughly 8m
var/time_between_minor_events_upper = 8000 // roughly 14m
var/minor_events_enabled = 1
var/next_minor_event = 0
var/minor_event_cycle_count = 0
var/time_lock = 1
var/list/special_events = list()
var/minimum_population = 15 // Minimum amount of players connected for event to occur
New()
for (var/X in typesof(/datum/random_event/major) - /datum/random_event/major)
var/datum/random_event/RE = new X
events += RE
for (var/X in typesof(/datum/random_event/minor) - /datum/random_event/minor)
var/datum/random_event/RE = new X
minor_events += RE
for (var/X in typesof(/datum/random_event/special) - /datum/random_event/special)
var/datum/random_event/RE = new X
special_events += RE
proc/event_cycle()
event_cycle_count++
var/num_players = 0
for(var/mob/players in mobs)
if(players.client) num_players++
if (events_enabled && (num_players >= minimum_population))
do_random_event(events)
else
message_admins("<span style=\"color:blue\">A random event would have happened now, but they are disabled!</span>")
var/event_timer = rand(time_between_events_lower,time_between_events_upper)
next_event = ticker.round_elapsed_ticks + event_timer
message_admins("<span style=\"color:blue\">Next event will occur at [round(next_event / 600)] minutes into the round.</span>")
spawn(event_timer)
event_cycle()
proc/minor_event_cycle()
minor_event_cycle_count++
if (minor_events_enabled)
do_random_event(minor_events)
var/event_timer = rand(time_between_minor_events_lower,time_between_minor_events_upper)
next_minor_event = ticker.round_elapsed_ticks + event_timer
spawn(event_timer)
minor_event_cycle()
proc/do_random_event(var/list/event_bank)
if (!event_bank || event_bank.len < 1)
logTheThing("debug", null, null, "<b>Random Events:</b> do_random_event proc was passed a bad event bank")
return
var/list/eligible = list()
for (var/datum/random_event/RE in event_bank)
if (!RE.is_event_available())
continue
eligible += RE
if (eligible.len > 0)
var/datum/random_event/this = pick(eligible)
this.event_effect()
else
logTheThing("debug", null, null, "<b>Random Events:</b> do_random_event couldn't find any eligible events")
proc/force_event(var/string,var/reason)
if (!string)
return
if (!reason)
reason = "coded instance (undefined)"
var/list/allevents = events | minor_events | special_events
for (var/datum/random_event/RE in allevents)
if (RE.name == string)
RE.event_effect(string,reason)
break
///////////////////
// CONFIGURATION //
///////////////////
proc/event_config()
var/dat = "<html><body><title>Random Events Controller</title>"
dat += "<b><u>Random Event Controls</u></b><HR>"
if (ticker.current_state == GAME_STATE_PREGAME)
dat += "<b>Random Events begin at: <a href='byond://?src=\ref[src];EventBegin=1'>[round(events_begin / 600)] minutes</a><br>"
dat += "<b>Minor Events begin at: <a href='byond://?src=\ref[src];MEventBegin=1'>[round(minor_events_begin / 600)] minutes</a><br>"
else
dat += "Next random event at [round(next_event / 600)] minutes into the round.<br>"
dat += "Next minor event at [round(next_minor_event / 600)] minutes into the round.<br>"
dat += "<b><a href='byond://?src=\ref[src];EnableEvents=1'>Random Events Enabled:</a></b> [events_enabled ? "Yes" : "No"]<br>"
dat += "<b><a href='byond://?src=\ref[src];EnableMEvents=1'>Minor Events Enabled:</a></b> [minor_events_enabled ? "Yes" : "No"]<br>"
dat += "<b><a href='byond://?src=\ref[src];AnnounceEvents=1'>Announce Events to Station:</a></b> [announce_events ? "Yes" : "No"]<br>"
dat += "<b><a href='byond://?src=\ref[src];TimeLocks=1'>Time Locking:</a></b> [time_lock ? "Yes" : "No"]<br>"
dat += "<b>Minimum Population for Events: <a href='byond://?src=\ref[src];MinPop=1'>[minimum_population] players</a><br>"
dat += "<b>Time Between Events:</b> <a href='byond://?src=\ref[src];TimeLower=1'>[round(time_between_events_lower / 600)]m</a> /"
dat += " <a href='byond://?src=\ref[src];TimeUpper=1'>[round(time_between_events_upper / 600)]m</a><br>"
dat += "<b>Time Between Minor Events:</b> <a href='byond://?src=\ref[src];MTimeLower=1'>[round(time_between_minor_events_lower / 600)]m</a> /"
dat += " <a href='byond://?src=\ref[src];MTimeUpper=1'>[round(time_between_minor_events_upper / 600)]m</a>"
dat += "<HR>"
dat += "<b><u>Normal Random Events</u></b><BR>"
for(var/datum/random_event/RE in events)
dat += "<a href='byond://?src=\ref[src];TriggerEvent=\ref[RE]'><b>[RE.name]</b></a>"
dat += " <small><a href='byond://?src=\ref[src];DisableEvent=\ref[RE]'>([RE.disabled ? "Disabled" : "Enabled"])</a>"
if (RE.is_event_available())
dat += " (Active)"
dat += "<br></small>"
dat += "<BR>"
dat += "<b><u>Minor Random Events</u></b><BR>"
for(var/datum/random_event/RE in minor_events)
dat += "<a href='byond://?src=\ref[src];TriggerMEvent=\ref[RE]'><b>[RE.name]</b></a>"
dat += " <small><a href='byond://?src=\ref[src];DisableMEvent=\ref[RE]'>([RE.disabled ? "Disabled" : "Enabled"])</a>"
if (RE.is_event_available())
dat += " (Active)"
dat += "<br></small>"
dat += "<BR>"
dat += "<b><u>Gimmick Events</u></b><BR>"
for(var/datum/random_event/RE in special_events)
dat += "<a href='byond://?src=\ref[src];TriggerSEvent=\ref[RE]'><b>[RE.name]</b></a><br>"
dat += "<HR>"
dat += "</body></html>"
usr << browse(dat,"window=reconfig;size=450x450")
Topic(href, href_list[])
if(href_list["TriggerEvent"])
var/datum/random_event/RE = locate(href_list["TriggerEvent"]) in events
if (!istype(RE,/datum/random_event/))
return
var/choice = alert("Trigger a [RE.name] event?","Random Events","Yes","No")
if (choice == "Yes")
if (RE.customization_available)
var/choice2 = alert("Random or custom variables?","[RE.name]","Random","Custom")
if (choice2 == "Custom")
RE.admin_call(key_name(usr, 1))
else
RE.event_effect("Triggered by [key_name(usr)]")
else
RE.event_effect("Triggered by [key_name(usr)]")
else if(href_list["TriggerMEvent"])
var/datum/random_event/RE = locate(href_list["TriggerMEvent"]) in minor_events
if (!istype(RE,/datum/random_event/))
return
var/choice = alert("Trigger a [RE.name] event?","Random Events","Yes","No")
if (choice == "Yes")
RE.event_effect("Triggered by [key_name(usr)]")
else if(href_list["TriggerSEvent"])
var/datum/random_event/RE = locate(href_list["TriggerSEvent"]) in special_events
if (!istype(RE,/datum/random_event/))
return
var/choice = alert("Trigger a [RE.name] event?","Random Events","Yes","No")
if (choice == "Yes")
if (RE.customization_available)
var/choice2 = alert("Random or custom variables?","[RE.name]","Random","Custom")
if (choice2 == "Custom")
RE.admin_call(key_name(usr, 1))
else
RE.event_effect("Triggered by [key_name(usr)]")
else
RE.event_effect("Triggered by [key_name(usr)]")
else if(href_list["DisableEvent"])
var/datum/random_event/RE = locate(href_list["DisableEvent"]) in events
if (!istype(RE,/datum/random_event/))
return
RE.disabled = !RE.disabled
message_admins("Admin [key_name(usr)] switched [RE.name] event [RE.disabled ? "Off" : "On"]")
logTheThing("admin", usr, null, "switched [RE.name] event [RE.disabled ? "Off" : "On"]")
logTheThing("diary", usr, null, "switched [RE.name] event [RE.disabled ? "Off" : "On"]", "admin")
else if(href_list["DisableMEvent"])
var/datum/random_event/RE = locate(href_list["DisableMEvent"]) in minor_events
if (!istype(RE,/datum/random_event/))
return
RE.disabled = !RE.disabled
message_admins("Admin [key_name(usr)] switched [RE.name] event [RE.disabled ? "Off" : "On"]")
logTheThing("admin", usr, null, "switched [RE.name] event [RE.disabled ? "Off" : "On"]")
logTheThing("diary", usr, null, "switched [RE.name] event [RE.disabled ? "Off" : "On"]", "admin")
else if(href_list["MinPop"])
var/new_min = input("How many players need to be connected before events will occur?","Random Events",minimum_population) as num
if (new_min == minimum_population) return
if (new_min < 1)
boutput(usr, "<span style=\"color:red\">Well that doesn't even make sense.</span>")
return
else
minimum_population = new_min
message_admins("Admin [key_name(usr)] set the minimum population for events to [minimum_population]")
logTheThing("admin", usr, null, "set the minimum population for events to [minimum_population]")
logTheThing("diary", usr, null, "set the minimum population for events to [minimum_population]", "admin")
else if(href_list["EventBegin"])
var/time = input("How many minutes into the round until events begin?","Random Events") as num
events_begin = time * 600
message_admins("Admin [key_name(usr)] set random events to begin at [time] minutes")
logTheThing("admin", usr, null, "set random events to begin at [time] minutes")
logTheThing("diary", usr, null, "set random events to begin at [time] minutes", "admin")
else if(href_list["MEventBegin"])
var/time = input("How many minutes into the round until minor events begin?","Random Events") as num
minor_events_begin = time * 600
message_admins("Admin [key_name(usr)] set minor events to begin at [time] minutes")
logTheThing("admin", usr, null, "set minor events to begin at [time] minutes")
logTheThing("diary", usr, null, "set minor events to begin at [time] minutes", "admin")
else if(href_list["EnableEvents"])
events_enabled = !events_enabled
message_admins("Admin [key_name(usr)] [events_enabled ? "enabled" : "disabled"] random events")
logTheThing("admin", usr, null, "[events_enabled ? "enabled" : "disabled"] random events")
logTheThing("diary", usr, null, "[events_enabled ? "enabled" : "disabled"] random events", "admin")
else if(href_list["EnableMEvents"])
minor_events_enabled = !minor_events_enabled
message_admins("Admin [key_name(usr)] [minor_events_enabled ? "enabled" : "disabled"] minor events")
logTheThing("admin", usr, null, "[minor_events_enabled ? "enabled" : "disabled"] minor events")
logTheThing("diary", usr, null, "[minor_events_enabled ? "enabled" : "disabled"] minor events", "admin")
else if(href_list["AnnounceEvents"])
announce_events = !announce_events
message_admins("Admin [key_name(usr)] [announce_events ? "enabled" : "disabled"] random event announcements")
logTheThing("admin", usr, null, "[announce_events ? "enabled" : "disabled"] random event announcements")
logTheThing("diary", usr, null, "[announce_events ? "enabled" : "disabled"] random event announcements", "admin")
else if(href_list["TimeLocks"])
time_lock = !time_lock
message_admins("Admin [key_name(usr)] [time_lock ? "enabled" : "disabled"] random event time locks")
logTheThing("admin", usr, null, "[time_lock ? "enabled" : "disabled"] random event time locks")
logTheThing("diary", usr, null, "[time_lock ? "enabled" : "disabled"] random event time locks", "admin")
else if(href_list["TimeLower"])
var/time = input("Set the lower bound to how many minutes?","Random Events") as num
if (time < 1)
boutput(usr, "<span style=\"color:red\">The fuck is that supposed to mean???? Knock it off!</span>")
return
time *= 600
if (time > time_between_events_upper)
boutput(usr, "<span style=\"color:red\">You cannot set the lower bound higher than the upper bound.</span>")
else
time_between_events_lower = time
message_admins("Admin [key_name(usr)] set event lower interval bound to [time_between_events_lower / 600] minutes")
logTheThing("admin", usr, null, "set event lower interval bound to [time_between_events_lower / 600] minutes")
logTheThing("diary", usr, null, "set event lower interval bound to [time_between_events_lower / 600] minutes", "admin")
else if(href_list["TimeUpper"])
var/time = input("Set the upper bound to how many minutes?","Random Events") as num
if (time > 100)
boutput(usr, "<span style=\"color:red\">That's a bit much.</span>")
return
time *= 600
if (time < time_between_events_lower)
boutput(usr, "<span style=\"color:red\">You cannot set the upper bound lower than the lower bound.</span>")
else
time_between_events_upper = time
message_admins("Admin [key_name(usr)] set event upper interval bound to [time_between_events_upper / 600] minutes")
logTheThing("admin", usr, null, "set event upper interval bound to [time_between_events_upper / 600] minutes")
logTheThing("diary", usr, null, "set event upper interval bound to [time_between_events_upper / 600] minutes", "admin")
else if(href_list["MTimeLower"])
var/time = input("Set the lower bound to how many minutes?","Random Events") as num
if (time < 1)
boutput(usr, "<span style=\"color:red\">The fuck is that supposed to mean???? Knock it off!</span>")
return
time *= 600
if (time > time_between_minor_events_upper)
boutput(usr, "<span style=\"color:red\">You cannot set the lower bound higher than the upper bound.</span>")
else
time_between_minor_events_lower = time
message_admins("Admin [key_name(usr)] set minor event lower interval bound to [time_between_minor_events_lower / 600] minutes")
logTheThing("admin", usr, null, "set minor event lower interval bound to [time_between_minor_events_lower / 600] minutes")
logTheThing("diary", usr, null, "set minor event lower interval bound to [time_between_minor_events_lower / 600] minutes", "admin")
else if(href_list["MTimeUpper"])
var/time = input("Set the upper bound to how many minutes?","Random Events") as num
if (time > 100)
boutput(usr, "<span style=\"color:red\">That's a bit much.</span>")
return
time *= 600
if (time < time_between_events_lower)
boutput(usr, "<span style=\"color:red\">You cannot set the upper bound lower than the lower bound.</span>")
else
time_between_minor_events_upper = time
message_admins("Admin [key_name(usr)] set minor event upper interval bound to [time_between_minor_events_upper / 600] minutes")
logTheThing("admin", usr, null, "set minor event upper interval bound to [time_between_minor_events_upper / 600] minutes")
logTheThing("diary", usr, null, "set minor event upper interval bound to [time_between_minor_events_upper / 600] minutes", "admin")
src.event_config()
+95
View File
@@ -0,0 +1,95 @@
var/datum/hydroponics_controller/hydro_controls
/datum/hydroponics_controller/
// global variable name is currently "hydro_controls"
var/max_harvest_cap = 10 // How many items can be harvested at once.
var/delay_between_harvests = 300 // How long between harvests, in spawn() ticks.
var/list/plant_species = list()
var/list/mutations = list()
var/list/strains = list()
var/image/pot_death_display = null
var/image/pot_health_display = null
var/image/pot_harvest_display = null
proc/set_up()
pot_death_display = image('icons/obj/hydroponics/hydroponics.dmi', "led-dead")
pot_health_display = image('icons/obj/hydroponics/hydroponics.dmi', "led-health")
pot_harvest_display = image('icons/obj/hydroponics/hydroponics.dmi', "led-harv")
for (var/B in typesof(/datum/plantmutation))
if (B == /datum/plantmutation)
continue
src.mutations += new B(src)
for (var/C in typesof(/datum/plant_gene_strain))
if (C == /datum/plant_gene_strain)
continue
src.strains += new C(src)
// You need to do plants after the others or they won't set up properly due to mutations and strains
// not having been set up yet
for (var/A in typesof(/datum/plant))
if (A == /datum/plant)
continue
src.plant_species += new A(src)
spawn(0)
for (var/datum/plant/P in src.plant_species)
for (var/X in P.mutations)
if (ispath(X))
P.mutations += HY_get_mutation_from_path(X)
P.mutations -= X
for (var/X in P.commuts)
if (ispath(X))
P.commuts += HY_get_strain_from_path(X)
P.commuts -= X
/proc/HY_get_species_from_path(var/species_path)
if (!hydro_controls)
logTheThing("debug", null, null, "<b>Hydro Controller:</b> Attempt to find species before controller setup")
return null
if (!species_path)
logTheThing("debug", null, null, "<b>Hydro Controller:</b> Attempt to find species with null path in controller")
return null
if (!hydro_controls.plant_species.len)
logTheThing("debug", null, null, "<b>Hydro Controller:</b> Cant find species due to empty species list in controller")
return null
for (var/datum/plant/P in hydro_controls.plant_species)
if (species_path == P.type)
return P
logTheThing("debug", null, null, "<b>Hydro Controller:</b> Species \"[species_path]\" not found")
return null
/proc/HY_get_mutation_from_path(var/mutation_path)
if (!hydro_controls)
logTheThing("debug", null, null, "<b>Hydro Controller:</b> Attempt to find mutation before controller setup")
return null
if (!mutation_path)
logTheThing("debug", null, null, "<b>Hydro Controller:</b> Attempt to find mutation with null path in controller")
return null
if (!hydro_controls.mutations.len)
logTheThing("debug", null, null, "<b>Hydro Controller:</b> Cant find mutation due to empty mutation list in controller")
return null
for (var/datum/plantmutation/M in hydro_controls.mutations)
if (mutation_path == M.type)
return M
logTheThing("debug", null, null, "<b>Hydro Controller:</b> Mutation \"[mutation_path]\" not found")
return null
/proc/HY_get_strain_from_path(var/strain_path)
if (!hydro_controls)
logTheThing("debug", null, null, "<b>Hydro Controller:</b> Attempt to find strain before controller setup")
return null
if (!strain_path)
logTheThing("debug", null, null, "<b>Hydro Controller:</b> Attempt to find strain with null path in controller")
return null
if (!hydro_controls.strains.len)
logTheThing("debug", null, null, "<b>Hydro Controller:</b> Cant find strain due to empty strain list in controller")
return null
for (var/datum/plant_gene_strain/S in hydro_controls.strains)
if (strain_path == S.type)
return S
logTheThing("debug", null, null, "<b>Hydro Controller:</b> Strain \"[strain_path]\" not found")
return null
+710
View File
@@ -0,0 +1,710 @@
var/datum/job_controller/job_controls
/datum/job_controller/
var/list/staple_jobs = list()
var/list/special_jobs = list()
var/allow_special_jobs = 1 // hopefully this doesn't break anything!!
var/datum/job/job_creator = null
New()
..()
if (derelict_mode)
src.staple_jobs = list(new /datum/job/command/captain/derelict {limit = 1;name = "NT-SO Commander";} (),
new /datum/job/command/head_of_security/derelict {limit = 1; name = "NT-SO Special Operative";} (),
new /datum/job/command/chief_engineer/derelict {limit = 1; name = "Salvage Chief";} (),
new /datum/job/security/security_officer/derelict {limit = 6; name = "NT-SO Officer";} (),
new /datum/job/research/medical_doctor/derelict {limit = 6; name = "Salvage Medic";} (),
new /datum/job/engineering/engineer/derelict {limit = 6; name = "Salvage Engineer";} (),
new /datum/job/civilian/staff_assistant (),
new /datum/job/civilian/chef (),
new /datum/job/civilian/barman (),
new /datum/job/civilian/chaplain ())
else
for (var/A in typesof(/datum/job/command)) src.staple_jobs += new A(src)
for (var/A in typesof(/datum/job/security)) src.staple_jobs += new A(src)
for (var/A in typesof(/datum/job/research)) src.staple_jobs += new A(src)
for (var/A in typesof(/datum/job/engineering)) src.staple_jobs += new A(src)
for (var/A in typesof(/datum/job/civilian)) src.staple_jobs += new A(src)
for (var/A in typesof(/datum/job/special)) src.special_jobs += new A(src)
job_creator = new /datum/job/created(src)
//Add special daily variety job
var/variety_job_path = text2path("/datum/job/daily/[lowertext(time2text(world.realtime,"Day"))]")
if (variety_job_path)
src.staple_jobs += new variety_job_path(src)
for (var/datum/job/J in src.staple_jobs)
// Cull any of those nasty null jobs from the category heads
if (!J.name)
src.staple_jobs -= J
for (var/datum/job/J in src.special_jobs)
if (!J.name)
src.special_jobs -= J
proc/job_config()
var/dat = "<html><body><title>Job Controller</title>"
dat += "<b><u>Job Controls</u></b><HR>"
dat += "<b>Command & Security Jobs</b><BR>"
for(var/datum/job/command/JOB in src.staple_jobs)
dat += "<a href='byond://?src=\ref[src];AlterCap=\ref[JOB]'>[JOB.name]: [countJob("[JOB.name]")]/[JOB.limit]</A><BR>"
for(var/datum/job/security/JOB in src.staple_jobs)
dat += "<a href='byond://?src=\ref[src];AlterCap=\ref[JOB]'>[JOB.name]: [countJob("[JOB.name]")]/[JOB.limit]</A><BR>"
dat += "<BR>"
dat += "<b>Research Jobs</b><BR>"
for(var/datum/job/research/JOB in src.staple_jobs)
dat += "<a href='byond://?src=\ref[src];AlterCap=\ref[JOB]'>[JOB.name]: [countJob("[JOB.name]")]/[JOB.limit]</A><BR>"
dat += "<BR>"
dat += "<b>Engineering Jobs</b><BR>"
for(var/datum/job/engineering/JOB in src.staple_jobs)
dat += "<a href='byond://?src=\ref[src];AlterCap=\ref[JOB]'>[JOB.name]: [countJob("[JOB.name]")]/[JOB.limit]</A><BR>"
dat += "<BR>"
dat += "<b>Civilian Jobs</b><BR>"
for(var/datum/job/civilian/JOB in src.staple_jobs)
dat += "<a href='byond://?src=\ref[src];AlterCap=\ref[JOB]'>[JOB.name]: [countJob("[JOB.name]")]/[JOB.limit]</A><BR>"
dat += "<BR>"
dat += "<b>Special Jobs</b><BR>"
for(var/datum/job/special/JOB in src.special_jobs)
dat += "<a href='byond://?src=\ref[src];AlterCap=\ref[JOB]'>[JOB.name]: [countJob("[JOB.name]")]/[JOB.limit]</A><BR>"
for(var/datum/job/created/JOB in src.special_jobs)
dat += "<a href='byond://?src=\ref[src];AlterCap=\ref[JOB]'>[JOB.name]: [countJob("[JOB.name]")]/[JOB.limit]</A>"
dat += " <a href='byond://?src=\ref[src];RemoveJob=\ref[JOB]'>(Remove)</A><BR>"
dat += "<BR>"
if (src.allow_special_jobs)
dat += "<A href='?src=\ref[src];SpecialToggle=1'>Special Jobs Enabled</A><BR>"
else
dat += "<A href='?src=\ref[src];SpecialToggle=1'>Special Jobs Disabled</A><BR>"
dat += "<A href='?src=\ref[src];JobCreator=1'>Create New Job</A>"
dat += "</body></html>"
usr << browse(dat,"window=jobconfig;size=300x600")
proc/job_creator()
var/dat = "<html><body><title>Job Creation</title>"
dat += "<b><u>Job Creator</u></b><HR>"
dat += "<A href='?src=\ref[src];EditName=1'>Job Name:</A> [src.job_creator.name]<br>"
dat += "<A href='?src=\ref[src];EditWages=1'>Wages Per Payday:</A> [src.job_creator.wages]<br>"
dat += "<A href='?src=\ref[src];EditLimit=1'>Job Limit:</A> [src.job_creator.limit]<br>"
dat += "<A href='?src=\ref[src];EditMob=1'>Mob Type:</A> [src.job_creator.mob_type]<br>"
if (ispath(src.job_creator.mob_type, /mob/living/carbon/human))
dat += "<A href='?src=\ref[src];EditHeadgear=1'>Starting Headgear:</A> [src.job_creator.slot_head]<br>"
dat += "<A href='?src=\ref[src];EditMask=1'>Starting Mask:</A> [src.job_creator.slot_mask]<br>"
dat += "<A href='?src=\ref[src];EditHeadset=1'>Starting Headset:</A> [src.job_creator.slot_ears]<br>"
dat += "<A href='?src=\ref[src];EditGlasses=1'>Starting Glasses:</A> [src.job_creator.slot_eyes]<br>"
dat += "<A href='?src=\ref[src];EditOvercoat=1'>Starting Overcoat:</A> [src.job_creator.slot_suit]<br>"
dat += "<A href='?src=\ref[src];EditJumpsuit=1'>Starting Jumpsuit:</A> [src.job_creator.slot_jump]<br>"
dat += "<A href='?src=\ref[src];EditIDCard=1'>Starting ID Card:</A> [src.job_creator.slot_card]<br>"
dat += "<A href='?src=\ref[src];EditGloves=1'>Starting Gloves:</A> [src.job_creator.slot_glov]<br>"
dat += "<A href='?src=\ref[src];EditShoes=1'>Starting Shoes:</A> [src.job_creator.slot_foot]<br>"
dat += "<A href='?src=\ref[src];EditBack=1'>Starting Back Item:</A> [src.job_creator.slot_back]<br>"
dat += "<A href='?src=\ref[src];EditBelt=1'>Starting Belt Item:</A> [src.job_creator.slot_belt]<br>"
dat += "<A href='?src=\ref[src];EditPock1=1'>Starting 1st Pocket Item:</A> [src.job_creator.slot_poc1]<br>"
dat += "<A href='?src=\ref[src];EditPock2=1'>Starting 2nd Pocket Item:</A> [src.job_creator.slot_poc2]<br>"
dat += "<A href='?src=\ref[src];EditLhand=1'>Starting Left Hand Item:</A> [src.job_creator.slot_lhan]<br>"
dat += "<A href='?src=\ref[src];EditRhand=1'>Starting Right Hand Item:</A> [src.job_creator.slot_rhan]<br>"
dat += "<A href='?src=\ref[src];GetAccess=1'>Access Permissions:</A><br>"
for(var/X in src.job_creator.access)
dat += "[X], "
dat += "<BR>"
dat += "<A href='?src=\ref[src];CreateJob=1'><b>Create Job</b></A>"
dat += "</body></html>"
usr << browse(dat,"window=jobcreator;size=500x600")
Topic(href, href_list[])
// JOB CONFIG COMMANDS
if(href_list["AlterCap"])
var/list/alljobs = src.staple_jobs | src.special_jobs
var/datum/job/JOB = locate(href_list["AlterCap"]) in alljobs
var/newcap = input("Choose the new cap.","Job Cap Config") as num
JOB.limit = newcap
message_admins("Admin [key_name(usr)] altered [JOB.name] job cap to [newcap]")
logTheThing("admin", usr, null, "altered [JOB.name] job cap to [newcap]")
logTheThing("diary", usr, null, "altered [JOB.name] job cap to [newcap]", "admin")
src.job_config()
if(href_list["RemoveJob"])
var/list/alljobs = src.staple_jobs | src.special_jobs
var/datum/job/JOB = locate(href_list["RemoveJob"]) in alljobs
if (!istype(JOB,/datum/job/created/))
boutput(usr, "<span style=\"color:red\"><b>Removing integral jobs is not allowed. Bad for business, y'know.</b></span>")
return
message_admins("Admin [key_name(usr)] removed special job [JOB.name]")
logTheThing("admin", usr, null, "removed special job [JOB.name]")
logTheThing("diary", usr, null, "removed special job [JOB.name]", "admin")
src.special_jobs -= JOB
src.job_config()
if(href_list["SpecialToggle"])
src.allow_special_jobs = !src.allow_special_jobs
message_admins("Admin [key_name(usr)] toggled Special Jobs [src.allow_special_jobs ? "On" : "Off"]")
logTheThing("admin", usr, null, "toggled Special Jobs [src.allow_special_jobs ? "On" : "Off"]")
logTheThing("diary", usr, null, "toggled Special Jobs [src.allow_special_jobs ? "On" : "Off"]", "admin")
src.job_config()
if(href_list["JobCreator"])
src.job_creator()
// JOB CREATOR COMMANDS
// I tweaked this section a little so you can actual search for certain items.
// Scrolling through a list of ~2600 items wasn't exactly great (Convair880).
if(href_list["EditName"])
var/picker = input("What is this job's name?","Job Creator")
src.job_creator.name = picker
src.job_creator()
if(href_list["EditWages"])
var/picker = input("How much does this job get paid each payday?","Job Creator") as num
src.job_creator.wages = picker
src.job_creator()
if(href_list["EditLimit"])
var/picker = input("How many of this job can there be on the station?","Job Creator") as num
src.job_creator.limit = picker
src.job_creator()
if(href_list["EditMob"])
var/list/L = list()
var/search_for = input(usr, "Search for mob (or leave blank for complete list)", "Select mob") as null|text
if (search_for)
for (var/R in typesof(/mob))
if (findtext("[R]", search_for)) L += R
else
L = typesof(/mob)
var/picker = null
if (L.len == 1)
picker = L[1]
else if (L.len > 1)
picker = input(usr,"Select mob:","Job Creator",null) as null|anything in L
else
usr.show_text("No mob matching that name", "red")
return
src.job_creator.mob_type = picker
src.job_creator()
if(href_list["EditHeadgear"])
switch(alert("Clear or reselect slotted item?","Job Creator","Clear","Reselect"))
if("Clear")
src.job_creator.slot_head = null
if("Reselect")
var/list/L = list()
var/search_for = input(usr, "Search for headgear (or leave blank for complete list)", "Select headgear") as null|text
if (search_for)
for (var/R in typesof(/obj/item/clothing/head))
if (findtext("[R]", search_for)) L += R
else
L = typesof(/obj/item/clothing/head)
var/picker = null
if (L.len == 1)
picker = L[1]
else if (L.len > 1)
picker = input(usr,"Select headgear:","Job Creator",null) as null|anything in L
else
usr.show_text("No headgear matching that name", "red")
return
src.job_creator.slot_head = picker
src.job_creator()
if(href_list["EditMask"])
switch(alert("Clear or reselect slotted item?","Job Creator","Clear","Reselect"))
if("Clear")
src.job_creator.slot_mask = null
if("Reselect")
var/list/L = list()
var/search_for = input(usr, "Search for mask (or leave blank for complete list)", "Select mask") as null|text
if (search_for)
for (var/R in typesof(/obj/item/clothing/mask))
if (findtext("[R]", search_for)) L += R
else
L = typesof(/obj/item/clothing/mask)
var/picker = null
if (L.len == 1)
picker = L[1]
else if (L.len > 1)
picker = input(usr,"Select mask:","Job Creator",null) as null|anything in L
else
usr.show_text("No mask matching that name", "red")
return
src.job_creator.slot_mask = picker
src.job_creator()
if(href_list["EditHeadset"])
switch(alert("Clear or reselect slotted item?","Job Creator","Clear","Reselect"))
if("Clear")
src.job_creator.slot_ears = null
if("Reselect")
var/list/L = list()
var/search_for = input(usr, "Search for headset (or leave blank for complete list)", "Select headset") as null|text
if (search_for)
for (var/R in typesof(/obj/item/device/radio/headset))
if (findtext("[R]", search_for)) L += R
else
L = typesof(/obj/item/device/radio/headset)
var/picker = null
if (L.len == 1)
picker = L[1]
else if (L.len > 1)
picker = input(usr,"Select headset:","Job Creator",null) as null|anything in L
else
usr.show_text("No headset matching that name", "red")
return
src.job_creator.slot_ears = picker
src.job_creator()
if(href_list["EditGlasses"])
switch(alert("Clear or reselect slotted item?","Job Creator","Clear","Reselect"))
if("Clear")
src.job_creator.slot_eyes = null
if("Reselect")
var/list/L = list()
var/search_for = input(usr, "Search for glasses (or leave blank for complete list)", "Select glasses") as null|text
if (search_for)
for (var/R in typesof(/obj/item/clothing/glasses))
if (findtext("[R]", search_for)) L += R
else
L = typesof(/obj/item/clothing/glasses)
var/picker = null
if (L.len == 1)
picker = L[1]
else if (L.len > 1)
picker = input(usr,"Select glasses:","Job Creator",null) as null|anything in L
else
usr.show_text("No glasses matching that name", "red")
return
src.job_creator.slot_eyes = picker
src.job_creator()
if(href_list["EditOvercoat"])
switch(alert("Clear or reselect slotted item?","Job Creator","Clear","Reselect"))
if("Clear")
src.job_creator.slot_suit = null
if("Reselect")
var/list/L = list()
var/search_for = input(usr, "Search for exosuit (or leave blank for complete list)", "Select exosuit") as null|text
if (search_for)
for (var/R in typesof(/obj/item/clothing/suit))
if (findtext("[R]", search_for)) L += R
else
L = typesof(/obj/item/clothing/suit)
var/picker = null
if (L.len == 1)
picker = L[1]
else if (L.len > 1)
picker = input(usr,"Select exosuit:","Job Creator",null) as null|anything in L
else
usr.show_text("No exosuit matching that name", "red")
return
src.job_creator.slot_suit = picker
src.job_creator()
if(href_list["EditJumpsuit"])
switch(alert("Clear or reselect slotted item?","Job Creator","Clear","Reselect"))
if("Clear")
src.job_creator.slot_jump = null
if("Reselect")
var/list/L = list()
var/search_for = input(usr, "Search for jumpsuit (or leave blank for complete list)", "Select jumpsuit") as null|text
if (search_for)
for (var/R in typesof(/obj/item/clothing/under))
if (findtext("[R]", search_for)) L += R
else
L = typesof(/obj/item/clothing/under)
var/picker = null
if (L.len == 1)
picker = L[1]
else if (L.len > 1)
picker = input(usr,"Select jumpsuit:","Job Creator",null) as null|anything in L
else
usr.show_text("No jumpsuit matching that name", "red")
return
src.job_creator.slot_jump = picker
src.job_creator()
if(href_list["EditIDCard"])
switch(alert("Clear or reselect slotted item?","Job Creator","Clear","Reselect"))
if("Clear")
src.job_creator.slot_card = null
if("Reselect")
var/list/L = list()
var/search_for = input(usr, "Search for ID card (or leave blank for complete list)", "Select ID card") as null|text
if (search_for)
for (var/R in (typesof(/obj/item/card) - list(/obj/item/card/emag, /obj/item/card/emag/fake, /obj/item/card/id/gauntlet)))
if (findtext("[R]", search_for)) L += R
else
// These cards can't be worn on the ID slot and they're not compatible with the
// job controller because they don't support access lists (Convair880).
L = (typesof(/obj/item/card) - list(/obj/item/card/emag, /obj/item/card/emag/fake, /obj/item/card/id/gauntlet))
var/picker = null
if (L.len == 1)
picker = L[1]
else if (L.len > 1)
picker = input(usr,"Select ID card:","Job Creator",null) as null|anything in L
else
usr.show_text("No ID card matching that name", "red")
return
src.job_creator.slot_card = picker
src.job_creator()
if(href_list["EditGloves"])
switch(alert("Clear or reselect slotted item?","Job Creator","Clear","Reselect"))
if("Clear")
src.job_creator.slot_glov = null
if("Reselect")
var/list/L = list()
var/search_for = input(usr, "Search for gloves (or leave blank for complete list)", "Select gloves") as null|text
if (search_for)
for (var/R in typesof(/obj/item/clothing/gloves))
if (findtext("[R]", search_for)) L += R
else
L = typesof(/obj/item/clothing/gloves)
var/picker = null
if (L.len == 1)
picker = L[1]
else if (L.len > 1)
picker = input(usr,"Select gloves:","Job Creator",null) as null|anything in L
else
usr.show_text("No gloves matching that name", "red")
return
src.job_creator.slot_glov = picker
src.job_creator()
if(href_list["EditShoes"])
switch(alert("Clear or reselect slotted item?","Job Creator","Clear","Reselect"))
if("Clear")
src.job_creator.slot_foot = null
if("Reselect")
var/list/L = list()
var/search_for = input(usr, "Search for shoes (or leave blank for complete list)", "Select shoes") as null|text
if (search_for)
for (var/R in typesof(/obj/item/clothing/shoes))
if (findtext("[R]", search_for)) L += R
else
L = typesof(/obj/item/clothing/shoes)
var/picker = null
if (L.len == 1)
picker = L[1]
else if (L.len > 1)
picker = input(usr,"Select shoes:","Job Creator",null) as null|anything in L
else
usr.show_text("No shoes matching that name", "red")
return
src.job_creator.slot_foot = picker
src.job_creator()
if(href_list["EditBack"])
switch(alert("Clear or reselect slotted item?","Job Creator","Clear","Reselect"))
if("Clear")
src.job_creator.slot_back = null
if("Reselect")
var/list/L = list()
var/search_for = input(usr, "Search for backslot item (or leave blank for complete list)", "Select backslot item") as null|text
if (search_for)
for (var/R in typesof(/obj/item/))
if (findtext("[R]", search_for)) L += R
else
L = typesof(/obj/item/)
var/picker = null
if (L.len == 1)
picker = L[1]
else if (L.len > 1)
picker = input(usr,"Select backslot item:","Job Creator",null) as null|anything in L
else
usr.show_text("No backslot item matching that name", "red")
return
// I wish there would be a better way to filter this stuff, typesof() just doesn't cut it.
// I suppose this is still slightly more elegant than the fixed (and outdated) list that
// used to be here. Anway, the job controller will not spawn unsuitable items (Convair880).
if (picker)
var/obj/item/check = new picker
if (!(check.flags & ONBACK))
usr.show_text("This item cannot be worn on the back slot.", "red")
qdel(check)
return
qdel(check)
src.job_creator.slot_back = picker
src.job_creator()
if(href_list["EditBelt"])
switch(alert("Clear or reselect slotted item?","Job Creator","Clear","Reselect"))
if("Clear")
src.job_creator.slot_belt = null
if("Reselect")
var/list/L = list()
var/search_for = input(usr, "Search for beltslot item (or leave blank for complete list)", "Select beltslot item") as null|text
if (search_for)
for (var/R in typesof(/obj/item/))
if (findtext("[R]", search_for)) L += R
else
L = typesof(/obj/item/)
var/picker = null
if (L.len == 1)
picker = L[1]
else if (L.len > 1)
picker = input(usr,"Select beltslot item:","Job Creator",null) as null|anything in L
else
usr.show_text("No beltslot item matching that name", "red")
return
// Ditto (Convair880).
if (picker)
var/obj/item/check = new picker
if (!(check.flags & ONBELT))
usr.show_text("This item cannot be worn on the belt slot.", "red")
qdel(check)
return
qdel(check)
src.job_creator.slot_belt = picker
src.job_creator()
if(href_list["EditPock1"])
switch(alert("Clear or reselect slotted item?","Job Creator","Clear","Reselect"))
if("Clear")
src.job_creator.slot_poc1 = null
if("Reselect")
var/list/L = list()
var/search_for = input(usr, "Search for item (or leave blank for complete list)", "Select pocket #1") as null|text
if (search_for)
for (var/R in typesof(/obj/item/))
if (findtext("[R]", search_for)) L += R
else
L = typesof(/obj/item/)
var/picker = null
if (L.len == 1)
picker = L[1]
else if (L.len > 1)
picker = input(usr,"Select item:","Job Creator",null) as null|anything in L
else
usr.show_text("No item matching that name", "red")
return
// Ditto (Convair880).
if (picker)
var/obj/item/check = new picker
if (check.w_class > 2)
usr.show_text("This item is too large to fit in a jumpsuit pocket.", "red")
qdel(check)
return
qdel(check)
src.job_creator.slot_poc1 = picker
src.job_creator()
if(href_list["EditPock2"])
switch(alert("Clear or reselect slotted item?","Job Creator","Clear","Reselect"))
if("Clear")
src.job_creator.slot_poc2 = null
if("Reselect")
var/list/L = list()
var/search_for = input(usr, "Search for item (or leave blank for complete list)", "Select pocket #2") as null|text
if (search_for)
for (var/R in typesof(/obj/item/))
if (findtext("[R]", search_for)) L += R
else
L = typesof(/obj/item/)
var/picker = null
if (L.len == 1)
picker = L[1]
else if (L.len > 1)
picker = input(usr,"Select item:","Job Creator",null) as null|anything in L
else
usr.show_text("No item matching that name", "red")
return
// Ditto (Convair880).
if (picker)
var/obj/item/check = new picker
if (check.w_class > 2)
usr.show_text("This item is too large to fit in a jumpsuit pocket.", "red")
qdel(check)
return
qdel(check)
src.job_creator.slot_poc2 = picker
src.job_creator()
if(href_list["EditLhand"])
switch(alert("Clear or reselect slotted item?","Job Creator","Clear","Reselect"))
if("Clear")
src.job_creator.slot_lhan = null
if("Reselect")
var/list/L = list()
var/search_for = input(usr, "Search for item (or leave blank for complete list)", "Select left hand") as null|text
if (search_for)
for (var/R in typesof(/obj/item/))
if (findtext("[R]", search_for)) L += R
else
L = typesof(/obj/item/)
var/picker = null
if (L.len == 1)
picker = L[1]
else if (L.len > 1)
picker = input(usr,"Select item:","Job Creator",null) as null|anything in L
else
usr.show_text("No item matching that name", "red")
return
src.job_creator.slot_lhan = picker
src.job_creator()
if(href_list["EditRhand"])
switch(alert("Clear or reselect slotted item?","Job Creator","Clear","Reselect"))
if("Clear")
src.job_creator.slot_rhan = null
if("Reselect")
var/list/L = list()
var/search_for = input(usr, "Search for item (or leave blank for complete list)", "Select right hand") as null|text
if (search_for)
for (var/R in typesof(/obj/item/))
if (findtext("[R]", search_for)) L += R
else
L = typesof(/obj/item/)
var/picker = null
if (L.len == 1)
picker = L[1]
else if (L.len > 1)
picker = input(usr,"Select item:","Job Creator",null) as null|anything in L
else
usr.show_text("No item matching that name", "red")
return
src.job_creator.slot_rhan = picker
src.job_creator()
if(href_list["GetAccess"])
var/picker = input("Make this job's access comparable to which job?","Job Creator") in list("Captain","Head of Security",
"Head of Personnel","Chief Engineer","Research Director","Security Officer","Detective","Geneticist","Roboticist","Scientist",
"Medical Doctor","Quartermaster","Miner","Mechanic","Engineer","Chef","Barman","Botanist","Janitor","Chaplain","Staff Assistant","No Access")
src.job_creator.access = get_access(picker)
src.job_creator()
if(href_list["CreateJob"])
var/datum/job/match_check = find_job_in_controller_by_string(src.job_creator.name)
if (match_check)
boutput(usr, "<span style=\"color:red\"><b>A job with this name already exists. It cannot be created.</b></span>")
return
else
var/datum/job/created/JOB = new /datum/job/created(src)
src.special_jobs += JOB
JOB.name = src.job_creator.name
JOB.wages = src.job_creator.wages
JOB.limit = src.job_creator.limit
JOB.mob_type = src.job_creator.mob_type
JOB.slot_head = src.job_creator.slot_head
JOB.slot_mask = src.job_creator.slot_mask
JOB.slot_ears = src.job_creator.slot_ears
JOB.slot_eyes = src.job_creator.slot_eyes
JOB.slot_glov = src.job_creator.slot_glov
JOB.slot_foot = src.job_creator.slot_foot
JOB.slot_card = src.job_creator.slot_card
JOB.slot_jump = src.job_creator.slot_jump
JOB.slot_suit = src.job_creator.slot_suit
JOB.slot_back = src.job_creator.slot_back
JOB.slot_belt = src.job_creator.slot_belt
JOB.slot_poc1 = src.job_creator.slot_poc1
JOB.slot_poc2 = src.job_creator.slot_poc2
JOB.slot_lhan = src.job_creator.slot_lhan
JOB.slot_rhan = src.job_creator.slot_rhan
JOB.access = JOB.access | src.job_creator.access
message_admins("Admin [key_name(usr)] created special job [JOB.name]")
logTheThing("admin", usr, null, "created special job [JOB.name]")
logTheThing("diary", usr, null, "created special job [JOB.name]", "admin")
src.job_creator()
/proc/find_job_in_controller_by_string(var/string,var/staple_only = 0)
if (!string || !istext(string))
logTheThing("debug", null, null, "<b>Job Controller:</b> Attempt to find job with bad string in controller detected")
return null
var/list/excluded_strings = list("Special Respawn","Custom Names","Everything Except Assistant",
"Engineering Department","Security Department","Heads of Staff")
if (string in excluded_strings)
return null
for (var/datum/job/J in job_controls.staple_jobs)
if (J.name == string)
return J
if (!staple_only)
for (var/datum/job/J in job_controls.special_jobs)
if (J.name == string)
return J
logTheThing("debug", null, null, "<b>Job Controller:</b> Attempt to find job by string \"[string]\" in controller failed")
return null
/proc/find_job_in_controller_by_path(var/path)
if (!path || !ispath(path) || !istype(path,/datum/job/))
logTheThing("debug", null, null, "<b>Job Controller:</b> Attempt to find job with bad path in controller detected")
return null
for (var/datum/job/J in job_controls.staple_jobs)
if (J.type == path)
return J
for (var/datum/job/J in job_controls.special_jobs)
if (J.type == path)
return J
logTheThing("debug", null, null, "<b>Job Controller:</b> Attempt to find job by path \"[path]\" in controller failed")
return null
/client/proc/cmd_job_controls()
set category = "Debug"
set name = "Job Controls"
if (job_controls == null) boutput(src, "UH OH! Shit's broken as fuck!")
else src.debug_variables(job_controls)
@@ -0,0 +1,53 @@
var/datum/manufacturing_controller/manuf_controls
/datum/manufacturing_controller
var/list/manufacturing_units = list()
var/list/normal_schematics = list()
var/list/custom_schematics = list()
proc/set_up()
for (var/M in typesof(/datum/manufacture) - /datum/manufacture)
src.normal_schematics += new M
for (var/obj/machinery/manufacturer/M in world)
src.manufacturing_units += M
M.set_up_schematics()
M.claim_free_resources()
/proc/get_schematic_from_path(var/schematic_path)
if (!ispath(schematic_path))
logTheThing("debug", null, null, "<b>Manufacturer:</b> Attempt to find schematic with null path")
return null
if (!manuf_controls.normal_schematics.len)
logTheThing("debug", null, null, "<b>Manufacturer:</b> Cant find schematic due to empty schematic list")
return null
for (var/datum/manufacture/M in manuf_controls.normal_schematics)
if (schematic_path == M.type)
return M
logTheThing("debug", null, null, "<b>Manufacturer:</b> Schematic \"[schematic_path]\" not found")
return null
/proc/get_schematic_from_name(var/schematic_name)
if (!istext(schematic_name))
logTheThing("debug", null, null, "<b>Manufacturer:</b> Attempt to find schematic with non-string")
return null
if (!manuf_controls.normal_schematics.len && !manuf_controls.custom_schematics.len)
logTheThing("debug", null, null, "<b>Manufacturer:</b> Cant find schematic due to empty schematic lists")
return null
for (var/datum/manufacture/M in (manuf_controls.normal_schematics + manuf_controls.custom_schematics))
if (schematic_name == M.name)
return M
logTheThing("debug", null, null, "<b>Manufacturer:</b> Schematic with name \"[schematic_name]\" not found")
return null
/proc/get_schematic_from_name_in_custom(var/schematic_name)
if (!istext(schematic_name))
logTheThing("debug", null, null, "<b>Manufacturer:</b> Attempt to find schematic with non-string")
return null
if (!manuf_controls.custom_schematics.len)
logTheThing("debug", null, null, "<b>Manufacturer:</b> Cant find schematic due to empty schematic lists")
return null
for (var/datum/manufacture/M in manuf_controls.custom_schematics)
if (schematic_name == M.name)
return M
logTheThing("debug", null, null, "<b>Manufacturer:</b> Schematic with name \"[schematic_name]\" not found")
return null
@@ -0,0 +1,73 @@
var/datum/mechanic_controller/mechanic_controls
/datum/mechanic_controller
var/list/scanned_items = list()
var/list/rkit_addresses = list()
proc
scan_in(var/N,var/T,var/M)
var/datum/electronics/scanned_item/S = new/datum/electronics/scanned_item
S.name = N
S.item_type = T
S.item_mats = M
S.create_partslist(M)
S.create_blueprint(M)
src.scanned_items += S
return 1
/datum/electronics/scanned_item
var
name = "Unknown"
item_type = ""
var/list/item_mats
var/finish_time = 0
var/datum/manufacture/mechanics/blueprint = null
proc
create_partslist(var/mats_number = 10)
if (!isnum(mats_number))
mats_number = 10
item_mats = list("battery"=0,"fuse"=0,"switch"=0,"capacitor"=0,"resistor"=0,"bulb"=0,"relay"=0,"board"=0,"keypad"=0,"screen"=0,"buzzer"=0)
var/number_of_parts = mats_number
var/advanced_chance = 20
var/advanced_max = 0
if(number_of_parts >= 6)
advanced_max = round(number_of_parts/6)
advanced_chance = round(20*(number_of_parts/6))
for(var/tracker = 1, tracker <= number_of_parts, tracker ++)
var/part
if(prob(advanced_chance)&&(advanced_max))
part = pick("board","keypad","screen","buzzer")
advanced_max --
else
part = pick("battery","fuse","switch","capacitor","resistor","bulb","relay")
item_mats[part] = item_mats[part] + 1
return
create_blueprint(var/mats_number = 10)
if (istype(src.blueprint,/datum/manufacture/mechanics/))
return
if (get_schematic_from_name_in_custom(src.name))
return
if (!isnum(mats_number))
mats_number = 10
var/datum/manufacture/mechanics/M = new /datum/manufacture/mechanics(manuf_controls)
manuf_controls.custom_schematics += M
M.name = src.name
M.time = mats_number * 2
M.frame_path = src.item_type
if (mats_number > 3)
mats_number -= 3
// to cover the base materials
if (mats_number > 0)
for(var/tracker = 1, tracker <= mats_number, tracker ++)
M.item_amounts[rand(1,3)] += 1
src.blueprint = M
return
+221
View File
@@ -0,0 +1,221 @@
var/datum/mining_controller/mining_controls
var/list/asteroid_blocked_turfs = list()
var/turf_spawn_edge_limit = 5
/datum/mining_controller
var/list/ore_types_common = list()
var/list/ore_types_uncommon = list()
var/list/ore_types_rare = list()
var/list/events = list()
// magnet vars
var/turf/magnetic_center = null
var/area/mining/magnet/magnet_area = null
var/list/magnet_shields = list()
var/max_magnet_spawn_size = 7
var/min_magnet_spawn_size = 4
var/list/mining_encounters_common = list()
var/list/mining_encounters_uncommon = list()
var/list/mining_encounters_rare = list()
var/list/small_encounters = list()
var/list/magnet_do_not_erase = list(/obj/securearea,/obj/forcefield/mining,/obj/grille/catwalk)
New()
..()
for (var/X in typesof(/datum/ore) - /datum/ore - /datum/ore/event)
var/datum/ore/O = new X
ore_types_common += O
for (var/X in typesof(/datum/mining_encounter) - /datum/mining_encounter)
var/datum/mining_encounter/MC = new X
mining_encounters_common += MC
for (var/datum/ore/O in src.ore_types_common)
if (istype(O, /datum/ore/event/))
events += O
ore_types_common -= O
if (O.rarity_tier == 2)
ore_types_uncommon += O
ore_types_common -= O
else if (O.rarity_tier == 3)
ore_types_rare += O
ore_types_common -= O
O.set_up()
for (var/datum/mining_encounter/MC in mining_encounters_common)
if (MC.rarity_tier == 3)
mining_encounters_rare += MC
mining_encounters_common -= MC
else if (MC.rarity_tier == 2)
mining_encounters_uncommon += MC
mining_encounters_common -= MC
else if (MC.rarity_tier == -1)
small_encounters += MC
mining_encounters_common -= MC
else if (MC.rarity_tier != 1)
mining_encounters_common -= MC
qdel(MC)
for (var/obj/landmark/magnet_center/MC in world)
magnetic_center = get_turf(MC)
magnet_area = get_area(MC)
MC.dispose()
break
for (var/obj/landmark/magnet_shield/MS in world)
var/obj/forcefield/mining/S = new /obj/forcefield/mining(get_turf(MS))
magnet_shields += S
MS.dispose()
proc/get_ore_from_string(var/string)
if (!istext(string))
return
for (var/datum/ore/O in ore_types_common + ore_types_uncommon + ore_types_rare)
if (O.name == string)
return O
return null
proc/get_ore_from_path(var/path)
if (!ispath(path))
return
for (var/datum/ore/O in ore_types_common + ore_types_uncommon + ore_types_rare)
if (O.type == path)
return O
return null
proc/select_encounter(var/rarity_mod)
if (!isnum(rarity_mod))
rarity_mod = 0
var/chosen = RarityClassRoll(100,rarity_mod,list(95,70))
var/list/category = mining_controls.mining_encounters_common
switch(chosen)
if (2)
category = mining_controls.mining_encounters_uncommon
if (3)
category = mining_controls.mining_encounters_rare
if (category.len < 1)
category = mining_controls.mining_encounters_common
return pick(category)
proc/select_small_encounter(var/rarity_mod)
return pick(small_encounters)
/area/mining/magnet
name = "Magnet Area"
icon_state = "purple"
RL_Lighting = 0
requires_power = 0
luminosity = 1
proc/check_for_unacceptable_content()
for (var/mob/living/L in src.contents)
return 1
for (var/obj/machinery/vehicle in src.contents)
return 1
return 0
/obj/forcefield/mining
name = "magnetic forcefield"
desc = "A powerful field used by the mining magnet to attract minerals."
icon = 'icons/misc/old_or_unused.dmi'
icon_state = "noise6"
color = "#BF12DE"
alpha = 175
opacity = 0
density = 0
invisibility = 101
anchored = 1
/// *** MISC *** ///
/proc/getOreQualityName(var/quality)
switch(quality)
if(-INFINITY to -101)
return "worthless"
if(-100 to -51)
return "terrible"
if(-50 to -41)
return "awful"
if(-40 to -31)
return "bad"
if(-30 to -21)
return "low-grade"
if(-20 to -11)
return "poor"
if(-10 to -1)
return "impure"
if(0)
return ""
if(1 to 10)
return "decent"
if(11 to 20)
return "fine"
if(21 to 30)
return "good"
if(31 to 40)
return "high-quality"
if(41 to 50)
return "excellent"
if(51 to 60)
return "fantastic"
if(61 to 70)
return "amazing"
if(71 to 80)
return "incredible"
if(81 to 90)
return "supreme"
if(91 to 100)
return "pure"
if(101 to INFINITY)
return "perfect"
else
return "strange"
return
/proc/getGemQualityName(var/quality)
switch(quality)
if(-INFINITY to -101)
return "worthless"
if(-100 to -51)
return "awful"
if(-50 to -41)
return "shattered"
if(-40 to -31)
return "broken"
if(-30 to -21)
return "cracked"
if(-20 to -11)
return "flawed"
if(-10 to -1)
return "dull"
if(0)
return ""
if(1 to 10)
return "pretty"
if(11 to 20)
return "shiny"
if(21 to 30)
return "gleaming"
if(31 to 40)
return "sparkling"
if(41 to 50)
return "glittering"
if(51 to 60)
return "beautiful"
if(61 to 70)
return "lustrous"
if(71 to 80)
return "iridescent"
if(81 to 90)
return "radiant"
if(91 to 100)
return "pristine"
if(101 to INFINITY)
return "perfect"
else
return "strange"
return
@@ -0,0 +1,12 @@
// handles timed player actions
datum/controller/process/actions
var/action_controler
setup()
name = "Actions"
schedule_interval = 5
action_controler = actions
doWork()
actions.process()
@@ -0,0 +1,12 @@
datum/controller/process/ai_tracking
setup()
name = "AI Tracking"
schedule_interval = 10
sleep_interval = 0.1
doWork()
for(var/datum/ai_camera_tracker/T in global.tracking_list)
T.process()
scheck()
@@ -0,0 +1,16 @@
// handles air processing.
datum/controller/process/air_system
setup()
name = "Atmos"
schedule_interval = 25 // 2.5 seconds
if(!air_master)
air_master = new /datum/controller/air_system()
air_master.setup(src)
air_master.set_controller(src)
doWork()
air_master.process()
copyStateFrom(var/datum/controller/process/target)
air_master.set_controller(src)
+16
View File
@@ -0,0 +1,16 @@
datum/controller/process/arena
var/list/arenas = list()
setup()
name = "Arena"
schedule_interval = 8 // 0.8 seconds
arenas += gauntlet_controller
arenas += colosseum_controller
doWork()
for (var/datum/arena/A in arenas)
A.tick()
tickDetail()
boutput(usr, "No statistics available.")
+39
View File
@@ -0,0 +1,39 @@
//Handles blobs without being pissy about it
datum/controller/process/blob
var/list/blobs = list()
var/tmp/list/detailed_count
var/tmp/datum/updateQueue/blobUpdateQueue
setup()
name = "Blob"
schedule_interval = 31 // 3.1 seconds
detailed_count = new
blobUpdateQueue = new
doWork()
for (var/obj/blob/B in blobs)
if (B.runOnLife || B.poison)
B.Life()
scheck()
/*var/currentTick = ticks
for(var/obj/blob/B in blobs)
if (prob (B.life_prob))
B.Life()
detailed_count["[B.type]"]++
scheck(currentTick)*/
tickDetail()
if (detailed_count && detailed_count.len)
var/stats = "<b>Blob Stats:</b><br>"
var/count
for (var/thing in detailed_count)
count = detailed_count[thing]
stats += "[thing] processed [count] times. Total blobs: [blobs.len]<br>"
boutput(usr, "<br>[stats]")
@@ -0,0 +1,9 @@
datum/controller/process/camnets
setup()
name = "Camera Networks"
schedule_interval = 30
sleep_interval = 0.5
doWork()
rebuild_camera_network() //Will only actually do something if it needs to.
@@ -0,0 +1,12 @@
datum/controller/process/chemistry
var/tmp/datum/updateQueue/chemistryUpdateQueue
setup()
name = "Chemistry"
schedule_interval = 10
chemistryUpdateQueue = new
doWork()
for(var/datum/d in active_reagent_holders)
d:process_reactions()
scheck()
@@ -0,0 +1,41 @@
// handles critters
datum/controller/process/critters
var/tmp/list/detailed_count
var/tmp/tick_counter
var/tmp/list/critters
setup()
name = "Critter"
schedule_interval = 16 // 1.6 seconds
detailed_count = new
src.critters = global.critters
doWork()
var/i
for(var/datum/c in global.critters)
c:process()
if (!(i++ % 10))
scheck()
/*var/currentTick = ticks
for(var/obj/critter in critters)
tick_counter = world.timeofday
critter:process()
tick_counter = world.timeofday - tick_counter
if (critter && tick_counter > 0)
detailed_count["[critter.type]"] += tick_counter
scheck(currentTick)*/
tickDetail()
if (detailed_count && detailed_count.len)
var/stats = "<b>[name] ticks:</b>"
var/count
for (var/thing in detailed_count)
count = detailed_count[thing]
if (count > 4)
stats += "[thing] used [count] ticks.<br>"
boutput(usr, "<br>[stats]")
@@ -0,0 +1,101 @@
datum/controller/process/delete_queue
var/tmp/delcount = 0
var/tmp/gccount = 0
var/tmp/deleteChunkSize = MIN_DELETE_CHUNK_SIZE
//var/tmp/delpause = 1
// Timing vars
var/tmp/start = 0
var/tmp/list/timeTaken = new
setup()
name = "DeleteQueue"
schedule_interval = 1
sleep_interval = 1
doWork()
if(!global.delete_queue)
boutput(world, "Error: there is no delete queue!")
return 0
//var/datum/dynamicQueue/queue =
if(global.delete_queue.isEmpty())
return
start = world.timeofday
var/list/toDeleteRefs = delete_queue.dequeueMany(deleteChunkSize)
var/numItems = toDeleteRefs.len
#ifdef DELETE_QUEUE_DEBUG
var/t
#endif
for(var/r in toDeleteRefs)
var/datum/D = locate(r)
if (!istype(D) || !D.qdeled)
// If we can't locate it, it got garbage collected.
// If it isn't disposed, it got garbage collected and then a new thing used its ref.
gccount++
continue
#ifdef DELETE_QUEUE_DEBUG
t = D.type
// If we have been forced to delete the object, we do the following:
detailed_delete_count[t]++
detailed_delete_gc_count[t]--
// Because we have already logged it into the gc count in qdel.
#endif
// Delete that bitch
delcount++
D.qdeled = 0
del(D)
scheck(0)
//if (delpause)
//sleep(delpause)
// The amount of time taken for this run is recorded only if
// the number of items considered is equal to the chunk size
if(numItems == deleteChunkSize)
timeTaken.len++
timeTaken[timeTaken.len] = world.timeofday - start
// If the number of items processed is equal to the chunk size
// and the average time taken by the delete queue is greater than the scheduled interval
if (numItems == deleteChunkSize && averageTimeTaken() > schedule_interval && deleteChunkSize > MIN_DELETE_CHUNK_SIZE)
deleteChunkSize--
else if (numItems == deleteChunkSize && averageTimeTaken() < schedule_interval)
deleteChunkSize++
proc
averageTimeTaken()
var/t = 0
var/c = 0
for(var/time in timeTaken)
t += time
c++
if (timeTaken.len > 10)
timeTaken.Cut(1, 2)
if(c > 0)
return t / c
return c
tickDetail()
#ifdef DELETE_QUEUE_DEBUG
if (detailed_delete_count && detailed_delete_count.len)
var/stats = "<b>Delete Stats:</b><br>"
var/count
for (var/thing in detailed_delete_count)
count = detailed_delete_count[thing]
stats += "[thing] deleted [count] times.<br>"
for (var/thing in detailed_delete_gc_count)
count = detailed_delete_gc_count[thing]
stats += "[thing] gracefully deleted [count] times.<br>"
boutput(usr, "<br>[stats]")
#endif
boutput(usr, "<b>Current Queue Length:</b> [delete_queue.count()]")
boutput(usr, "<b>Total Items Deleted:</b> [delcount] (Explictly) [gccount] (Gracefully GC'd)")
+44
View File
@@ -0,0 +1,44 @@
// handles items
datum/controller/process/items
var/tmp/list/detailed_count
var/tmp/tick_counter
var/tmp/list/processing_items
setup()
name = "Item"
schedule_interval = 29
for(var/obj/object in world)
object.initialize()
detailed_count = new
src.processing_items = global.processing_items
doWork()
var/c
for(var/datum/i in global.processing_items)
i:process()
if (!(c++ % 20))
scheck()
/*for(var/obj/item/item in processing_items)
tick_counter = world.timeofday
item.process()
tick_counter = world.timeofday - tick_counter
if (item && tick_counter > 0)
detailed_count["[item.type]"] += tick_counter
scheck(currentTick)
*/
tickDetail()
if (detailed_count && detailed_count.len)
var/stats = "<b>[name] ticks:</b><br>"
var/count
for (var/thing in detailed_count)
count = detailed_count[thing]
if (count > 4)
stats += "[thing] used [count] ticks.<br>"
boutput(usr, "<br>[stats]")
@@ -0,0 +1,7 @@
datum/controller/process/lighting
setup()
name = "Lighting"
schedule_interval = 22
doWork()
// TODO
@@ -0,0 +1,81 @@
// handles machines
datum/controller/process/machines
var/tmp/list/machines
var/tmp/list/pipe_networks
var/tmp/list/powernets
var/tmp/list/atmos_machines
setup()
name = "Machine"
schedule_interval = 33
Station_VNet = new /datum/v_space/v_space_network()
doWork()
src.atmos_machines = global.atmos_machines
var/c = 0
for(var/obj/machinery/atmospherics/machine in atmos_machines)
#ifdef MACHINE_PROCESSING_DEBUG
var/t = world.time
#endif
machine.process()
#ifdef MACHINE_PROCESSING_DEBUG
register_machine_time(machine, world.time - t)
#endif
if (!(c++ % 100))
scheck()
src.pipe_networks = global.pipe_networks
for(var/datum/pipe_network/network in src.pipe_networks)
#ifdef MACHINE_PROCESSING_DEBUG
var/t = world.time
#endif
network.process()
#ifdef MACHINE_PROCESSING_DEBUG
register_machine_time(network, world.time - t)
#endif
if (!(c++ % 100))
scheck()
src.powernets = global.powernets
for(var/datum/powernet/PN in src.powernets)
#ifdef MACHINE_PROCESSING_DEBUG
var/t = world.time
#endif
PN.reset()
#ifdef MACHINE_PROCESSING_DEBUG
register_machine_time(PN, world.time - t)
#endif
if (!(c++ % 100))
scheck()
src.machines = global.machines
for(var/obj/machinery/machine in src.machines)
#ifdef MACHINE_PROCESSING_DEBUG
var/t = world.time
#endif
machine.process()
#ifdef MACHINE_PROCESSING_DEBUG
register_machine_time(machine, world.time - t)
#endif
if (!(c++ % 100))
scheck()
#ifdef MACHINE_PROCESSING_DEBUG
proc/register_machine_time(var/datum/machine, var/time)
if(!machine) return
var/list/mtl = detailed_machine_timings[machine.type]
if(!mtl)
mtl = list()
mtl.len = 2
mtl[1] = 0 //The amount of time spent processing this machine in total
mtl[2] = 0 //The amount of times this machine has been processed
detailed_machine_timings[machine.type] = mtl
mtl[1] += time
mtl[2]++
#endif
+22
View File
@@ -0,0 +1,22 @@
// handles critters
datum/controller/process/mob_ai
setup()
name = "Mob AI"
schedule_interval = 16 // 1.6 seconds
doWork()
for(var/mob/living/carbon/human/H in mobs)
H.ai_process()
scheck()
/*var/currentTick = ticks
for(var/obj/critter in critters)
tick_counter = world.timeofday
critter:process()
tick_counter = world.timeofday - tick_counter
if (critter && tick_counter > 0)
detailed_count["[critter.type]"] += tick_counter
scheck(currentTick)*/
+66
View File
@@ -0,0 +1,66 @@
// handles mobs
datum/controller/process/mobs
var/tmp/list/detailed_count
var/tmp/tick_counter
var/list/mobs
var/list/living = list()
var/list/wraiths = list()
var/list/adminghosts = list()
setup()
name = "Mob"
schedule_interval = 20
detailed_count = new
src.mobs = global.mobs
copyStateFrom(var/datum/controller/process/mobs/other)
detailed_count = other.detailed_count
doWork()
var/currentTick = ticks
src.mobs = global.mobs
var/c
for(var/mob/living/M in src.mobs)
M.Life(src)
if (!(c++ % 5))
scheck(currentTick)
for(var/mob/wraith/W in src.mobs)
W.Life(src)
scheck(currentTick)
// For periodic antag overlay updates (Convair880).
for (var/mob/dead/G in src.mobs)
if (isadminghost(G))
G:Life(src)
scheck(currentTick)
/*
for(var/mob/living/M in src.mobs)
tick_counter = world.timeofday
M.Life(src)
tick_counter = world.timeofday - tick_counter
if (M && tick_counter > 0)
detailed_count["[M.type]-[M.name]"] += tick_counter
scheck(currentTick)
// a r g h
for (var/mob/wraith/W in src.mobs)
W.Life(src)
scheck(currentTick)
*/
tickDetail()
if (detailed_count && detailed_count.len)
var/stats = "<b>[name] ticks:</b><br>"
var/count
for (var/thing in detailed_count)
count = detailed_count[thing]
if (count > 4)
stats += "[thing] used [count] ticks.<br>"
boutput(usr, "<br>[stats]")
@@ -0,0 +1,17 @@
datum/controller/process/networks
var/tmp/datum/updateQueue/networkUpdateQueue
setup()
name = "Networks"
schedule_interval = 11
networkUpdateQueue = new
doWork()
for(var/datum/n in node_networks)
n:update()
scheck()
/*
var/currentTick = ticks
for (var/datum/node_network/network in node_networks)
network.update()
scheck(currentTick)*/
@@ -0,0 +1,18 @@
datum/controller/process/particles
var/datum/particleMaster/master
setup()
name = "Particles"
schedule_interval = 12
// putting this in a var so main loop varedit can get into the particleMaster
master = particleMaster
doWork()
// TODO roll the "loop" code from particleMaster back into this system
master.Tick()
// regular timing doesn't really apply since particles abuse the shit out of spawn and sleep
tickDetail()
return "particle types: [master.particleTypes.len], particle systems: [master.particleSystems.len]<br>"
+317
View File
@@ -0,0 +1,317 @@
// Process
/datum/controller/process
/**
* State vars
*/
// Main controller ref
var/tmp/datum/controller/processScheduler/main
// 1 if process is not running or queued
var/tmp/idle = 1
// 1 if process is queued
var/tmp/queued = 0
// 1 if process is running
var/tmp/running = 0
// 1 if process is blocked up
var/tmp/hung = 0
// 1 if process was killed
var/tmp/killed = 0
// Status text var
var/tmp/status
// Previous status text var
var/tmp/previousStatus
// 1 if process is disabled
var/tmp/disabled = 0
/**
* Config vars
*/
// Process name
var/name
// Process schedule interval
// This controls how often the process would run under ideal conditions.
// If the process scheduler sees that the process has finished, it will wait until
// this amount of time has elapsed from the start of the previous run to start the
// process running again.
var/tmp/schedule_interval = PROCESS_DEFAULT_SCHEDULE_INTERVAL // run every 50 ticks
// Process sleep interval
// This controls how often the process will yield (call sleep(0)) while it is running.
// Every concurrent process should sleep periodically while running in order to allow other
// processes to execute concurrently.
var/tmp/sleep_interval
// hang_warning_time - this is the time (in 1/10 seconds) after which the server will begin to show "maybe hung" in the context window
var/tmp/hang_warning_time = PROCESS_DEFAULT_HANG_WARNING_TIME
// hang_alert_time - After this much time(in 1/10 seconds), the server will send an admin debug message saying the process may be hung
var/tmp/hang_alert_time = PROCESS_DEFAULT_HANG_ALERT_TIME
// hang_restart_time - After this much time(in 1/10 seconds), the server will automatically kill and restart the process.
var/tmp/hang_restart_time = PROCESS_DEFAULT_HANG_RESTART_TIME
// cpu_threshold - if world.cpu >= cpu_threshold, scheck() will call sleep(1) to defer further work until the next tick. This keeps a process from driving a tick into overtime (causing perceptible lag)
var/tmp/cpu_threshold = PROCESS_DEFAULT_CPU_THRESHOLD
// How many times in the current run has the process deferred work till the next tick?
var/tmp/cpu_defer_count = 0
/**
* recordkeeping vars
*/
// Records the time (1/10s timeofday) at which the process last finished sleeping
var/tmp/last_slept = 0
// Records the time (1/10s timeofday) at which the process last began running
var/tmp/run_start = 0
// Records the number of times this process has been killed and restarted
var/tmp/times_killed
// Tick count
var/tmp/ticks = 0
var/tmp/last_task = ""
var/tmp/last_object
datum/controller/process/New(var/datum/controller/processScheduler/scheduler)
..()
main = scheduler
previousStatus = "idle"
idle()
name = "process"
schedule_interval = 50
sleep_interval = world.tick_lag / PROCESS_DEFAULT_SLEEP_INTERVAL
last_slept = 0
run_start = 0
ticks = 0
last_task = 0
last_object = null
datum/controller/process/proc/started()
// Initialize last_slept so we can know when to sleep
last_slept = TimeOfHour
// Initialize run_start so we can detect hung processes.
run_start = TimeOfHour
// Initialize defer count
cpu_defer_count = 0
running()
main.processStarted(src)
onStart()
datum/controller/process/proc/finished()
ticks++
idle()
main.processFinished(src)
onFinish()
datum/controller/process/proc/doWork()
datum/controller/process/proc/setup()
datum/controller/process/proc/process()
started()
doWork()
finished()
datum/controller/process/proc/running()
idle = 0
queued = 0
running = 1
hung = 0
setStatus(PROCESS_STATUS_RUNNING)
datum/controller/process/proc/idle()
queued = 0
running = 0
idle = 1
hung = 0
setStatus(PROCESS_STATUS_IDLE)
datum/controller/process/proc/queued()
idle = 0
running = 0
queued = 1
hung = 0
setStatus(PROCESS_STATUS_QUEUED)
datum/controller/process/proc/hung()
hung = 1
setStatus(PROCESS_STATUS_HUNG)
datum/controller/process/proc/handleHung()
var/datum/lastObj = last_object
var/lastObjType = "null"
if(istype(lastObj))
lastObjType = lastObj.type
// If world.timeofday has rolled over, then we need to adjust.
if (TimeOfHour < run_start)
run_start -= 36000
var/msg = "[name] process hung at tick #[ticks]. Process was unresponsive for [(TimeOfHour - run_start) / 10] seconds and was restarted. Last task: [last_task]. Last Object Type: [lastObjType]"
logTheThing("debug", null, null, msg)
logTheThing("diary", null, null, msg, "debug")
message_admins(msg)
main.restartProcess(src.name)
datum/controller/process/proc/kill()
if (!killed)
var/msg = "[name] process was killed at tick #[ticks]."
logTheThing("debug", null, null, msg)
logTheThing("diary", null, null, msg, "debug")
//finished()
// Allow inheritors to clean up if needed
onKill()
// This should del
del(src)
datum/controller/process/proc/scheck(var/tickId = 0)
if (killed)
// The kill proc is the only place where killed is set.
// The kill proc should have deleted this datum, and all sleeping procs that are
// owned by it.
CRASH("A killed process is still running somehow...")
if (hung)
// This will only really help if the doWork proc ends up in an infinite loop.
handleHung()
CRASH("Process [name] hung and was restarted.")
// For each tick the process defers, it increments the cpu_defer_count so we don't
// defer indefinitely
if (main.getCurrentTickElapsedTime() > main.timeAllowance)
sleep(world.tick_lag*1)
cpu_defer_count++
last_slept = TimeOfHour
else
var/t = TimeOfHour
// If world.timeofday has rolled over, then we need to adjust.
if (t < last_slept)
last_slept -= 36000
if (t > last_slept + sleep_interval)
// If we haven't slept in sleep_interval deciseconds, sleep to allow other work to proceed.
sleep(0)
last_slept = TimeOfHour
datum/controller/process/proc/update()
// Clear delta
if(previousStatus != status)
setStatus(status)
var/elapsedTime = getElapsedTime()
if (hung)
handleHung()
return
else if (elapsedTime > hang_restart_time)
hung()
else if (elapsedTime > hang_alert_time)
setStatus(PROCESS_STATUS_PROBABLY_HUNG)
else if (elapsedTime > hang_warning_time)
setStatus(PROCESS_STATUS_MAYBE_HUNG)
datum/controller/process/proc/getElapsedTime()
if (TimeOfHour < run_start)
return TimeOfHour - (run_start - 36000)
return TimeOfHour - run_start
datum/controller/process/proc/tickDetail()
return
datum/controller/process/proc/getContext()
return "<tr><td>[name]</td><td>[main.averageRunTime(src)]</td><td>[main.last_run_time[src]]</td><td>[main.highest_run_time[src]]</td><td>[ticks]</td></tr>\n"
datum/controller/process/proc/getContextData()
return list(
"name" = name,
"averageRunTime" = main.averageRunTime(src),
"lastRunTime" = main.last_run_time[src],
"highestRunTime" = main.highest_run_time[src],
"ticks" = ticks,
"schedule" = schedule_interval,
"status" = getStatusText(),
"disabled" = disabled
)
datum/controller/process/proc/getStatus()
return status
datum/controller/process/proc/getStatusText(var/s = 0)
if(!s)
s = status
switch(s)
if(PROCESS_STATUS_IDLE)
return "idle"
if(PROCESS_STATUS_QUEUED)
return "queued"
if(PROCESS_STATUS_RUNNING)
return "running"
if(PROCESS_STATUS_MAYBE_HUNG)
return "maybe hung"
if(PROCESS_STATUS_PROBABLY_HUNG)
return "probably hung"
if(PROCESS_STATUS_HUNG)
return "HUNG"
else
return "UNKNOWN"
datum/controller/process/proc/getPreviousStatus()
return previousStatus
datum/controller/process/proc/getPreviousStatusText()
return getStatusText(previousStatus)
datum/controller/process/proc/setStatus(var/newStatus)
previousStatus = status
status = newStatus
datum/controller/process/proc/setLastTask(var/task, var/object)
last_task = task
last_object = object
datum/controller/process/proc/_copyStateFrom(var/datum/controller/process/target)
main = target.main
name = target.name
schedule_interval = target.schedule_interval
sleep_interval = target.sleep_interval
last_slept = 0
run_start = 0
times_killed = target.times_killed
ticks = target.ticks
last_task = target.last_task
last_object = target.last_object
copyStateFrom(target)
datum/controller/process/proc/copyStateFrom(var/datum/controller/process/target)
datum/controller/process/proc/onKill()
datum/controller/process/proc/onStart()
datum/controller/process/proc/onFinish()
datum/controller/process/proc/disable()
disabled = 1
datum/controller/process/proc/enable()
disabled = 0
@@ -0,0 +1,14 @@
datum/controller/process/railway
var/tmp/list/vehicles
setup()
name = "Railways"
schedule_interval = 5
vehicles = global.railway_vehicles
doWork()
var/c
for(var/obj/railway_vehicle/v in global.railway_vehicles)
v.process()
if (!(c++ % 10))
scheck()
@@ -0,0 +1,19 @@
// handles only materials research right now.
datum/controller/process/research
var/datum/materialResearchHolder/researchMaster
setup()
name = "Research"
schedule_interval = 10
researchMaster = materialsResearch
doWork()
researchMaster = materialsResearch
if(researchMaster)
for(var/x in researchMaster.research)
var/datum/materialResearch/R = researchMaster.research[x]
if(!R.completed)
R.process()
if(R.completed)
researchMaster.completed.Add(R.id)
researchMaster.completed[R.id] = R
@@ -0,0 +1,9 @@
/datum/controller/process/stock_market
setup()
name = "Stock Market"
schedule_interval = 15
doWork()
if (stockExchange)
stockExchange.process()
@@ -0,0 +1,12 @@
// handles telescope signals and whatnot
datum/controller/process/telescope
var/datum/telescope_manager/manager
setup()
name = "Telescope"
schedule_interval = 100
doWork()
if(tele_man)
if(!manager) manager = tele_man
tele_man.tick()
+14
View File
@@ -0,0 +1,14 @@
// handles the game ticker
datum/controller/process/ticker
setup()
name = "Game"
schedule_interval = 5
if(!ticker)
ticker = new /datum/controller/gameticker()
// start the pregame process
spawn(1)
ticker.pregame()
doWork()
ticker.process()
+29
View File
@@ -0,0 +1,29 @@
// handles various global init and the position of the sun.
datum/controller/process/world
var/shuttle
setup()
name = "World"
schedule_interval = 23
setupgenetics()
if(genResearch) genResearch.setup()
setup_radiocodes()
emergency_shuttle = new /datum/shuttle_controller/emergency_shuttle()
src.shuttle = emergency_shuttle
generate_access_name_lookup()
doWork()
sun.calc_position()
if(genResearch) genResearch.progress()
for (var/byondkey in muted_keys)
var/value = muted_keys[byondkey]
if (value > 1)
muted_keys[byondkey] = value - 1
else if (value == 1 || value == 0)
muted_keys -= byondkey
@@ -0,0 +1,354 @@
// Singleton instance of game_controller_new, setup in world.New()
var/global/datum/controller/processScheduler/processScheduler
/datum/controller/processScheduler
// Processes known by the scheduler
var/tmp/datum/controller/process/list/processes = new
// Processes that are currently running
var/tmp/datum/controller/process/list/running = new
// Processes that are idle
var/tmp/datum/controller/process/list/idle = new
// Processes that are queued to run
var/tmp/datum/controller/process/list/queued = new
// Process name -> process object map
var/tmp/datum/controller/process/list/nameToProcessMap = new
// Process last start times
var/tmp/datum/controller/process/list/last_start = new
// Process last run durations
var/tmp/datum/controller/process/list/last_run_time = new
// Per process list of the last 20 durations
var/tmp/datum/controller/process/list/last_twenty_run_times = new
// Process highest run time
var/tmp/datum/controller/process/list/highest_run_time = new
// Sleep 1 tick -- This may be too aggressive.
var/tmp/scheduler_sleep_interval = 1
// Controls whether the scheduler is running or not
var/tmp/isRunning = 0
// Setup for these processes will be deferred until all the other processes are set up.
var/tmp/list/deferredSetupList = new
var/tmp/currentTick = 0
var/tmp/currentTickStart = 0
var/tmp/timeAllowance = 0
var/tmp/cpuAverage = 0
var/tmp/timeAllowanceMax = 0
/datum/controller/processScheduler/New()
..()
scheduler_sleep_interval = world.tick_lag
timeAllowance = world.tick_lag * 0.5
timeAllowanceMax = world.tick_lag
/**
* deferSetupFor
* @param path processPath
* If a process needs to be initialized after everything else, add it to
* the deferred setup list. On goonstation, only the ticker needs to have
* this treatment.
*/
/datum/controller/processScheduler/proc/deferSetupFor(var/processPath)
if (!(processPath in deferredSetupList))
deferredSetupList += processPath
/datum/controller/processScheduler/proc/setup()
// There can be only one
if(processScheduler && (processScheduler != src))
del(src)
return 0
var/process
// Add all the processes we can find, except for the ticker
for (process in typesof(/datum/controller/process) - /datum/controller/process)
if (!(process in deferredSetupList))
addProcess(new process(src))
for (process in deferredSetupList)
addProcess(new process(src))
/datum/controller/processScheduler/proc/start()
isRunning = 1
spawn(0)
process()
/datum/controller/processScheduler/proc/process()
updateCurrentTickData()
for(var/i=world.tick_lag,i<world.tick_lag*50,i+=world.tick_lag)
spawn(i) updateCurrentTickData()
while(isRunning)
// Hopefully spawning this for 50 ticks in the future will make it the first thing in the queue.
spawn(world.tick_lag*50) updateCurrentTickData()
checkRunningProcesses()
queueProcesses()
runQueuedProcesses()
sleep(scheduler_sleep_interval)
/datum/controller/processScheduler/proc/stop()
isRunning = 0
/datum/controller/processScheduler/proc/checkRunningProcesses()
for(var/datum/controller/process/p in running)
p.update()
if (isnull(p)) // Process was killed
continue
var/status = p.getStatus()
var/previousStatus = p.getPreviousStatus()
// Check status changes
if(status != previousStatus)
//Status changed.
switch(status)
if(PROCESS_STATUS_PROBABLY_HUNG)
message_admins("Process '[p.name]' may be hung.")
if(PROCESS_STATUS_HUNG)
message_admins("Process '[p.name]' is hung and will be restarted.")
/datum/controller/processScheduler/proc/queueProcesses()
for(var/datum/controller/process/p in processes)
// Don't double-queue, don't queue running processes
if (p.disabled || p.running || p.queued || !p.idle)
continue
// If world.timeofday has rolled over, then we need to adjust.
if (TimeOfHour < last_start[p])
last_start[p] -= 36000
// If the process should be running by now, go ahead and queue it
if (TimeOfHour > last_start[p] + p.schedule_interval)
setQueuedProcessState(p)
/datum/controller/processScheduler/proc/runQueuedProcesses()
for(var/datum/controller/process/p in queued)
runProcess(p)
/datum/controller/processScheduler/proc/addProcess(var/datum/controller/process/process)
processes.Add(process)
process.idle()
idle.Add(process)
// init recordkeeping vars
last_start.Add(process)
last_start[process] = 0
last_run_time.Add(process)
last_run_time[process] = 0
last_twenty_run_times.Add(process)
last_twenty_run_times[process] = list()
highest_run_time.Add(process)
highest_run_time[process] = 0
// init starts and stops record starts
recordStart(process, 0)
recordEnd(process, 0)
// Set up process
process.setup()
// Save process in the name -> process map
nameToProcessMap[process.name] = process
/datum/controller/processScheduler/proc/replaceProcess(var/datum/controller/process/oldProcess, var/datum/controller/process/newProcess)
processes.Remove(oldProcess)
processes.Add(newProcess)
newProcess.idle()
idle.Remove(oldProcess)
running.Remove(oldProcess)
queued.Remove(oldProcess)
idle.Add(newProcess)
last_start.Remove(oldProcess)
last_start.Add(newProcess)
last_start[newProcess] = 0
last_run_time.Add(newProcess)
last_run_time[newProcess] = last_run_time[oldProcess]
last_run_time.Remove(oldProcess)
last_twenty_run_times.Add(newProcess)
last_twenty_run_times[newProcess] = last_twenty_run_times[oldProcess]
last_twenty_run_times.Remove(oldProcess)
highest_run_time.Add(newProcess)
highest_run_time[newProcess] = highest_run_time[oldProcess]
highest_run_time.Remove(oldProcess)
recordStart(newProcess, 0)
recordEnd(newProcess, 0)
nameToProcessMap[newProcess.name] = newProcess
/datum/controller/processScheduler/proc/runProcess(var/datum/controller/process/process)
spawn(0)
process.process()
/datum/controller/processScheduler/proc/processStarted(var/datum/controller/process/process)
setRunningProcessState(process)
recordStart(process)
/datum/controller/processScheduler/proc/processFinished(var/datum/controller/process/process)
setIdleProcessState(process)
recordEnd(process)
/datum/controller/processScheduler/proc/setIdleProcessState(var/datum/controller/process/process)
if (process in running)
running -= process
if (process in queued)
queued -= process
if (!(process in idle))
idle += process
/datum/controller/processScheduler/proc/setQueuedProcessState(var/datum/controller/process/process)
if (process in running)
running -= process
if (process in idle)
idle -= process
if (!(process in queued))
queued += process
// The other state transitions are handled internally by the process.
process.queued()
/datum/controller/processScheduler/proc/setRunningProcessState(var/datum/controller/process/process)
if (process in queued)
queued -= process
if (process in idle)
idle -= process
if (!(process in running))
running += process
/datum/controller/processScheduler/proc/recordStart(var/datum/controller/process/process, var/time = null)
if (isnull(time))
time = TimeOfHour
last_start[process] = time
/datum/controller/processScheduler/proc/recordEnd(var/datum/controller/process/process, var/time = null)
if (isnull(time))
time = TimeOfHour
// If world.timeofday has rolled over, then we need to adjust.
if (time < last_start[process])
last_start[process] -= 36000
var/lastRunTime = time - last_start[process]
if(lastRunTime < 0)
lastRunTime = 0
recordRunTime(process, lastRunTime)
/**
* recordRunTime
* Records a run time for a process
*/
/datum/controller/processScheduler/proc/recordRunTime(var/datum/controller/process/process, time)
last_run_time[process] = time
if(time > highest_run_time[process])
highest_run_time[process] = time
var/list/lastTwenty = last_twenty_run_times[process]
if (lastTwenty.len == 20)
lastTwenty.Cut(1, 2)
lastTwenty.len++
lastTwenty[lastTwenty.len] = time
/**
* averageRunTime
* returns the average run time (over the last 20) of the process
*/
/datum/controller/processScheduler/proc/averageRunTime(var/datum/controller/process/process)
var/lastTwenty = last_twenty_run_times[process]
var/t = 0
var/c = 0
for(var/time in lastTwenty)
t += time
c++
if(c > 0)
return t / c
return c
/datum/controller/processScheduler/proc/getStatusData()
var/list/data = new
for (var/datum/controller/process/p in processes)
data.len++
data[data.len] = p.getContextData()
return data
/datum/controller/processScheduler/proc/getProcessCount()
return processes.len
/datum/controller/processScheduler/proc/hasProcess(var/processName as text)
if (nameToProcessMap[processName])
return 1
/datum/controller/processScheduler/proc/killProcess(var/processName as text)
restartProcess(processName)
/datum/controller/processScheduler/proc/restartProcess(var/processName as text)
if (hasProcess(processName))
var/datum/controller/process/oldInstance = nameToProcessMap[processName]
var/datum/controller/process/newInstance = new oldInstance.type(src)
newInstance._copyStateFrom(oldInstance)
replaceProcess(oldInstance, newInstance)
oldInstance.kill()
/datum/controller/processScheduler/proc/enableProcess(var/processName as text)
if (hasProcess(processName))
var/datum/controller/process/process = nameToProcessMap[processName]
process.enable()
/datum/controller/processScheduler/proc/disableProcess(var/processName as text)
if (hasProcess(processName))
var/datum/controller/process/process = nameToProcessMap[processName]
process.disable()
/datum/controller/processScheduler/proc/getCurrentTickElapsedTime()
if (world.time > currentTick)
updateCurrentTickData()
return 0
else
return TimeOfHour - currentTickStart
/datum/controller/processScheduler/proc/updateCurrentTickData()
if (world.time > currentTick)
// New tick!
currentTick = world.time
currentTickStart = TimeOfHour
updateTimeAllowance()
cpuAverage = (world.cpu + cpuAverage + cpuAverage) / 3
/datum/controller/processScheduler/proc/updateTimeAllowance()
// Time allowance goes down linearly with world.cpu.
var/tmp/error = cpuAverage - 100
var/tmp/timeAllowanceDelta = sign(error) * -0.5 * world.tick_lag * max(0, 0.01 * abs(error))
//timeAllowance = world.tick_lag * min(1, 0.5 * ((200/max(1,cpuAverage)) - 1))
timeAllowance = min(timeAllowanceMax, max(0, timeAllowance + timeAllowanceDelta))
/datum/controller/processScheduler/proc/sign(var/x)
if (x == 0)
return 1
return x / abs(x)