diff --git a/_maps/map_files/PubbyStation/PubbyStation.dmm b/_maps/map_files/PubbyStation/PubbyStation.dmm
index 8937961188..aed8a82687 100644
--- a/_maps/map_files/PubbyStation/PubbyStation.dmm
+++ b/_maps/map_files/PubbyStation/PubbyStation.dmm
@@ -36271,7 +36271,7 @@
},
/obj/effect/landmark/blobstart,
/obj/item/weapon/melee/baton/cattleprod{
- bcell = new /obj/item/weapon/stock_parts/cell/high()
+ cell = new /obj/item/weapon/stock_parts/cell/high()
},
/turf/open/floor/plasteel/black,
/area/medical/exam_room)
diff --git a/code/__DEFINES/clockcult.dm b/code/__DEFINES/clockcult.dm
index acc0cdc9ab..ded2c34ef8 100644
--- a/code/__DEFINES/clockcult.dm
+++ b/code/__DEFINES/clockcult.dm
@@ -58,7 +58,7 @@ GLOBAL_LIST_EMPTY(all_scripture) //a list containing scripture instances; not us
//clockcult power defines
#define MIN_CLOCKCULT_POWER 25 //the minimum amount of power clockcult machines will handle gracefully
-#define CLOCKCULT_POWER_UNIT (MIN_CLOCKCULT_POWER*100) //standard power amount for clockwork proselytizer costs
+#define CLOCKCULT_POWER_UNIT (MIN_CLOCKCULT_POWER*100) //standard power amount for replica fabricator costs
#define POWER_STANDARD (CLOCKCULT_POWER_UNIT*0.2) //how much power is in anything else; doesn't matter as much as the following
@@ -76,7 +76,7 @@ GLOBAL_LIST_EMPTY(all_scripture) //a list containing scripture instances; not us
#define POWER_PLASTEEL (CLOCKCULT_POWER_UNIT*0.05) //how much power is in one sheet of plasteel
-#define RATVAR_POWER_CHECK "ratvar?" //when passed into can_use_power(), converts it into a check for if ratvar has woken/the proselytizer is debug
+#define RATVAR_POWER_CHECK "ratvar?" //when passed into can_use_power(), converts it into a check for if ratvar has woken/the fabricator is debug
//Ark defines
#define GATEWAY_SUMMON_RATE 1 //the time amount the Gateway to the Celestial Derelict gets each process tick; defaults to 1 per tick
@@ -99,7 +99,7 @@ GLOBAL_LIST_EMPTY(all_scripture) //a list containing scripture instances; not us
#define SIGIL_ACCESS_RANGE 2 //range at which transmission sigils can access power
-#define PROSELYTIZER_REPAIR_PER_TICK 4 //how much a proselytizer repairs each tick, and also how many deciseconds each tick is
+#define FABRICATOR_REPAIR_PER_TICK 4 //how much a fabricator repairs each tick, and also how many deciseconds each tick is
#define OCULAR_WARDEN_EXCLUSION_RANGE 3 //the range at which ocular wardens cannot be placed near other ocular wardens
diff --git a/code/__DEFINES/misc.dm b/code/__DEFINES/misc.dm
index 6ea8cd64ee..f9de982db6 100644
--- a/code/__DEFINES/misc.dm
+++ b/code/__DEFINES/misc.dm
@@ -430,6 +430,8 @@ GLOBAL_LIST_INIT(ghost_others_options, list(GHOST_OTHERS_SIMPLE, GHOST_OTHERS_DE
#define GIBTONITE_ACTIVE 1
#define GIBTONITE_STABLE 2
#define GIBTONITE_DETONATE 3
+//for obj explosion block calculation
+#define EXPLOSION_BLOCK_PROC -1
//Gangster starting influences
#define GANGSTER_SOLDIER_STARTING_INFLUENCE 5
diff --git a/code/__DEFINES/status_effects.dm b/code/__DEFINES/status_effects.dm
index 6735ef95e9..cf7acfc543 100644
--- a/code/__DEFINES/status_effects.dm
+++ b/code/__DEFINES/status_effects.dm
@@ -49,3 +49,5 @@
#define STATUS_EFFECT_SIGILMARK /datum/status_effect/sigil_mark
#define STATUS_EFFECT_CRUSHERDAMAGETRACKING /datum/status_effect/crusher_damage //tracks total kinetic crusher damage on a target
+
+#define STATUS_EFFECT_SYPHONMARK /datum/status_effect/syphon_mark //tracks kills for the KA death syphon module
diff --git a/code/_onclick/autoclick.dm b/code/_onclick/autoclick.dm
index 7b6e2f108a..23d07e2968 100644
--- a/code/_onclick/autoclick.dm
+++ b/code/_onclick/autoclick.dm
@@ -1,5 +1,10 @@
/client
var/list/atom/selected_target[2]
+ var/obj/item/active_mousedown_item = null
+ var/mouseParams = ""
+ var/mouseLocation = null
+ var/mouseObject = null
+ var/mouseControlObject = null
/client/MouseDown(object, location, control, params)
var/delay = mob.CanMobAutoclick(object, location, params)
@@ -9,14 +14,26 @@
while(selected_target[1])
Click(selected_target[1], location, control, selected_target[2])
sleep(delay)
+ active_mousedown_item = mob.canMobMousedown(object, location, params)
+ if(active_mousedown_item)
+ active_mousedown_item.onMouseDown(object, location, params, mob)
/client/MouseUp(object, location, control, params)
selected_target[1] = null
+ if(active_mousedown_item)
+ active_mousedown_item.onMouseUp(object, location, params, mob)
+ active_mousedown_item = null
/client/MouseDrag(src_object,atom/over_object,src_location,over_location,src_control,over_control,params)
+ mouseParams = params
+ mouseLocation = over_location
+ mouseObject = over_object
+ mouseControlObject = over_control
if(selected_target[1] && over_object && over_object.IsAutoclickable())
selected_target[1] = over_object
selected_target[2] = params
+ if(active_mousedown_item)
+ active_mousedown_item.onMouseDrag(src_object, over_object, src_location, over_location, params, mob)
/mob/proc/CanMobAutoclick(object, location, params)
@@ -27,8 +44,31 @@
if(h)
. = h.CanItemAutoclick(object, location, params)
+/mob/proc/canMobMousedown(object, location, params)
+
+/mob/living/carbon/canMobMousedown(atom/object, location, params)
+ var/obj/item/H = get_active_held_item()
+ if(H)
+ . = H.canItemMouseDown(object, location, params)
+
/obj/item/proc/CanItemAutoclick(object, location, params)
+/obj/item/proc/canItemMouseDown(object, location, params)
+ if(canMouseDown)
+ return src
+
+/obj/item/proc/onMouseDown(object, location, params, mob)
+ return
+
+/obj/item/proc/onMouseUp(object, location, params, mob)
+ return
+
+/obj/item/proc/onMouseDrag(src_object, over_object, src_location, over_location, params, mob)
+ return
+
+/obj/item
+ var/canMouseDown = FALSE
+
/obj/item/weapon/gun
var/automatic = 0 //can gun use it, 0 is no, anything above 0 is the delay between clicks in ds
@@ -42,4 +82,11 @@
. = 0
/obj/screen/click_catcher/IsAutoclickable()
- . = 1
\ No newline at end of file
+ . = 1
+
+//Please don't roast me too hard
+/client/MouseMove(object,location,control,params)
+ mouseParams = params
+ mouseLocation = location
+ mouseObject = object
+ mouseControlObject = control
diff --git a/code/_onclick/hud/alert.dm b/code/_onclick/hud/alert.dm
index 8d074ffa17..c1986f928b 100644
--- a/code/_onclick/hud/alert.dm
+++ b/code/_onclick/hud/alert.dm
@@ -361,7 +361,7 @@ or shoot a gun to move around via Newton's 3rd Law of Motion."
name = "Next Tier Requirements"
desc = "You shouldn't be seeing this description unless you're very fast. If you're very fast, good job!"
icon_state = "no-servants-caches"
- var/static/list/scripture_states = list(SCRIPTURE_DRIVER = TRUE, SCRIPTURE_SCRIPT = FALSE, SCRIPTURE_APPLICATION = FALSE, SCRIPTURE_REVENANT = FALSE, SCRIPTURE_JUDGEMENT = FALSE)
+
/obj/screen/alert/clockwork/scripture_reqs/Initialize()
. = ..()
@@ -374,12 +374,11 @@ or shoot a gun to move around via Newton's 3rd Law of Motion."
/obj/screen/alert/clockwork/scripture_reqs/process()
if(GLOB.clockwork_gateway_activated)
- qdel(src)
+ mob_viewer.clear_alert("scripturereq")
return
var/current_state
- scripture_states = scripture_unlock_check()
- for(var/i in scripture_states)
- if(!scripture_states[i])
+ for(var/i in SSticker.scripture_states)
+ if(!SSticker.scripture_states[i])
current_state = i
break
icon_state = "no"
@@ -459,7 +458,6 @@ or shoot a gun to move around via Newton's 3rd Law of Motion."
var/servants = 0
var/validservants = 0
var/unconverted_ais_exist = get_unconverted_ais()
- var/list/scripture_states = scripture_unlock_check()
var/list/textlist
for(var/mob/living/L in GLOB.living_mob_list)
if(is_servant_of_ratvar(L))
@@ -496,7 +494,7 @@ or shoot a gun to move around via Newton's 3rd Law of Motion."
textlist += "[unconverted_ais_exist] unconverted AIs exist!
"
else
textlist += "An unconverted AI exists!
"
- if(scripture_states[SCRIPTURE_REVENANT])
+ if(SSticker.scripture_states[SCRIPTURE_REVENANT])
var/inathneq_available = GLOB.clockwork_generals_invoked["inath-neq"] <= world.time
var/sevtug_available = GLOB.clockwork_generals_invoked["sevtug"] <= world.time
var/nezbere_available = GLOB.clockwork_generals_invoked["nezbere"] <= world.time
@@ -508,9 +506,9 @@ or shoot a gun to move around via Newton's 3rd Law of Motion."
textlist += "Generals available: NONE
"
else
textlist += "Generals available: NONE
"
- for(var/i in scripture_states)
+ for(var/i in SSticker.scripture_states)
if(i != SCRIPTURE_DRIVER) //ignore the always-unlocked stuff
- textlist += "[i] Scripture: [scripture_states[i] ? "UNLOCKED":"LOCKED"]
"
+ textlist += "[i] Scripture: [SSticker.scripture_states[i] ? "UNLOCKED":"LOCKED"]
"
desc = textlist.Join()
..()
diff --git a/code/datums/explosion.dm b/code/datums/explosion.dm
index b74e4619db..9fb302a63a 100644
--- a/code/datums/explosion.dm
+++ b/code/datums/explosion.dm
@@ -279,16 +279,9 @@ GLOBAL_LIST_EMPTY(explosions)
var/turf/T = affected_turfs[I]
var/current_exp_block = T.density ? T.explosion_block : 0
- for(var/obj/machinery/door/D in T)
- if(D.density)
- current_exp_block += D.explosion_block
-
- for(var/obj/structure/window/W in T)
- if(W.reinf && W.fulltile)
- current_exp_block += W.explosion_block
-
- for(var/obj/structure/blob/B in T)
- current_exp_block += B.explosion_block
+ for(var/obj/O in T)
+ var/the_block = O.explosion_block
+ current_exp_block += the_block == EXPLOSION_BLOCK_PROC ? O.GetExplosionBlock() : the_block
.[T] = current_exp_block
@@ -351,20 +344,12 @@ GLOBAL_LIST_EMPTY(explosions)
var/turf/TT = T
while(TT != epicenter)
TT = get_step_towards(TT,epicenter)
- if(TT.density && TT.explosion_block)
+ if(TT.density)
dist += TT.explosion_block
- for(var/obj/machinery/door/D in TT)
- if(D.density && D.explosion_block)
- dist += D.explosion_block
-
- for(var/obj/structure/window/W in TT)
- if(W.explosion_block && W.fulltile)
- dist += W.explosion_block
-
- for(var/obj/structure/blob/B in T)
- dist += B.explosion_block
-
+ for(var/obj/O in T)
+ var/the_block = O.explosion_block
+ dist += the_block == EXPLOSION_BLOCK_PROC ? O.GetExplosionBlock() : the_block
if(dist < dev)
T.color = "red"
T.maptext = "Dev"
diff --git a/code/datums/helper_datums/getrev.dm b/code/datums/helper_datums/getrev.dm
index ffb5627c6f..42ba4c7b47 100644
--- a/code/datums/helper_datums/getrev.dm
+++ b/code/datums/helper_datums/getrev.dm
@@ -73,9 +73,9 @@
return ""
. = header ? "The following pull requests are currently test merged:
" : ""
for(var/line in testmerge)
- var/cm = testmerge[line]["commit"]
var/details
if(world.RunningService())
+ var/cm = testmerge[line]["commit"]
details = ": '" + html_encode(testmerge[line]["title"]) + "' by " + html_encode(testmerge[line]["author"]) + " at commit " + html_encode(copytext(cm, 1, min(length(cm), 7)))
else if(has_pr_details) //tgs2 support
details = ": '" + html_encode(testmerge[line]["title"]) + "' by " + html_encode(testmerge[line]["user"]["login"])
diff --git a/code/datums/status_effects/neutral.dm b/code/datums/status_effects/neutral.dm
index 0946408323..7adbf4e915 100644
--- a/code/datums/status_effects/neutral.dm
+++ b/code/datums/status_effects/neutral.dm
@@ -16,3 +16,43 @@
status_type = STATUS_EFFECT_UNIQUE
alert_type = null
var/total_damage = 0
+
+/datum/status_effect/syphon_mark/on_apply()
+ if(owner.stat == DEAD)
+ return FALSE
+ return ..()
+
+/datum/status_effect/syphon_mark/proc/get_kill()
+ if(reward_target)
+ reward_target.get_kill(owner)
+
+/datum/status_effect/syphon_mark/tick()
+ if(owner.stat == DEAD)
+ get_kill()
+ qdel(src)
+
+/datum/status_effect/syphon_mark/on_remove()
+ get_kill()
+ . = ..()
+
+/datum/status_effect/syphon_mark
+ id = "syphon_mark"
+ duration = 50
+ status_type = STATUS_EFFECT_MULTIPLE
+ alert_type = null
+ on_remove_on_mob_delete = TRUE
+ var/obj/item/borg/upgrade/modkit/bounty/reward_target
+
+/datum/status_effect/syphon_mark/on_apply()
+ if(owner.stat == DEAD)
+ return FALSE
+ return ..()
+
+/datum/status_effect/syphon_mark/tick()
+ if(owner.stat == DEAD)
+ get_kill()
+ qdel(src)
+
+/datum/status_effect/syphon_mark/on_remove()
+ get_kill()
+ . = ..()
diff --git a/code/datums/verbs.dm b/code/datums/verbs.dm
new file mode 100644
index 0000000000..f2674a631d
--- /dev/null
+++ b/code/datums/verbs.dm
@@ -0,0 +1,101 @@
+/datum/verbs
+ var/name
+ var/list/children
+ var/datum/verbs/parent
+ var/list/verblist
+ var/abstract = FALSE
+
+//returns the master list for verbs of a type
+/datum/verbs/proc/GetList()
+ CRASH("Abstract verblist for [type]")
+
+//modify outlist for each entry in Generate_list
+/datum/verbs/proc/HandleVerb(list/outlist, atom/verb/verbpath, ...)
+
+/datum/verbs/New()
+ var/mainlist = GetList()
+ var/ourentry = mainlist[type]
+ children = list()
+ verblist = list()
+ if (ourentry)
+ if (!islist(ourentry)) //some of our childern already loaded
+ qdel(src)
+ CRASH("Verb double load: [type]")
+ Add_children(ourentry)
+
+ mainlist[type] = src
+
+ Load_verbs(type, typesof("[type]/verb"))
+
+ var/datum/verbs/parent = mainlist[parent_type]
+ if (!parent)
+ mainlist[parent_type] = list(src)
+ else if (islist(parent))
+ parent += src
+ else
+ parent.Add_children(list(src))
+
+/datum/verbs/proc/Set_parent(datum/verbs/_parent)
+ parent = _parent
+ if (abstract)
+ parent.Add_children(children)
+ var/list/verblistoftypes = list()
+ for(var/thing in verblist)
+ LAZYADD(verblistoftypes[verblist[thing]], thing)
+
+ for(var/verbparenttype in verblistoftypes)
+ parent.Load_verbs(verbparenttype, verblistoftypes[verbparenttype])
+
+/datum/verbs/proc/Add_children(list/kids)
+ if (abstract && parent)
+ parent.Add_children(kids)
+ return
+
+ for(var/thing in kids)
+ var/datum/verbs/item = thing
+ item.Set_parent(src)
+ if (!item.abstract)
+ children += item
+
+/datum/verbs/proc/Load_verbs(verb_parent_type, list/verbs)
+ if (abstract && parent)
+ parent.Load_verbs(verb_parent_type, verbs)
+ return
+
+ for (var/verbpath in verbs)
+ verblist[verbpath] = verb_parent_type
+
+/datum/verbs/proc/Generate_list(...)
+ . = list()
+ if (length(children))
+ for (var/thing in children)
+ var/datum/verbs/child = thing
+ var/list/childlist = child.Generate_list(arglist(args))
+ if (childlist)
+ var/childname = "[child]"
+ if (childname == "[child.type]")
+ var/list/tree = splittext(childname, "/")
+ childname = tree[tree.len]
+ .[child.type] = "parent=[url_encode(type)];name=[url_encode(childname)]"
+ . += childlist
+
+ for (var/thing in verblist)
+ var/atom/verb/verbpath = thing
+ if (!verbpath)
+ stack_trace("Bad VERB in [type] verblist: [english_list(verblist)]")
+ var/list/entry = list()
+ entry["parent"] = "[type]"
+ entry["name"] = verbpath.desc
+ if (copytext(verbpath.name,1,2) == "@")
+ entry["command"] = copytext(verbpath.name,2)
+ else
+ entry["command"] = replacetext(verbpath.name, " ", "-")
+
+ HandleVerb(arglist(list(entry, verbpath) + args))
+ .[verbpath] = entry
+
+/world/proc/LoadVerbs(verb_type)
+ if(!ispath(verb_type, /datum/verbs) || verb_type == /datum/verbs)
+ CRASH("Invalid verb_type: [verb_type]")
+ for (var/typepath in subtypesof(verb_type))
+ new typepath()
diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm
index edbb46d7fe..78eaa4d13b 100644
--- a/code/game/atoms_movable.dm
+++ b/code/game/atoms_movable.dm
@@ -679,3 +679,7 @@
set waitfor = FALSE
if(!anchored && has_gravity())
step(src, movedir)
+
+//Returns an atom's power cell, if it has one. Overload for individual items.
+/atom/movable/proc/get_cell()
+ return
diff --git a/code/game/gamemodes/clock_cult/clock_cult.dm b/code/game/gamemodes/clock_cult/clock_cult.dm
index 48e1ff1957..9bb0d89e5c 100644
--- a/code/game/gamemodes/clock_cult/clock_cult.dm
+++ b/code/game/gamemodes/clock_cult/clock_cult.dm
@@ -207,10 +207,9 @@ Credit where due:
text += "
The servants' objective was:
[CLOCKCULT_OBJECTIVE]"
text += "
Ratvar's servants had [GLOB.clockwork_caches] Tinkerer's Caches."
text += "
Construction Value(CV) was: [GLOB.clockwork_construction_value]"
- var/list/scripture_states = scripture_unlock_check()
- for(var/i in scripture_states)
+ for(var/i in SSticker.scripture_states)
if(i != SCRIPTURE_DRIVER)
- text += "
[i] scripture was: [scripture_states[i] ? "UN":""]LOCKED"
+ text += "
[i] scripture was: [SSticker.scripture_states[i] ? "UN":""]LOCKED"
if(servants_of_ratvar.len)
text += "
Ratvar's servants were:"
for(var/datum/mind/M in servants_of_ratvar)
diff --git a/code/game/gamemodes/clock_cult/clock_effects/clock_sigils.dm b/code/game/gamemodes/clock_cult/clock_effects/clock_sigils.dm
index 7d8c3eb1f9..79dd366789 100644
--- a/code/game/gamemodes/clock_cult/clock_effects/clock_sigils.dm
+++ b/code/game/gamemodes/clock_cult/clock_effects/clock_sigils.dm
@@ -204,7 +204,7 @@
else if(!GLOB.ratvar_awakens)
to_chat(user, "Hitting the [sigil_name] with brass sheets will convert them to power at a rate of 1 brass sheet to [POWER_FLOOR]W power.")
if(!GLOB.ratvar_awakens)
- to_chat(user, "You can recharge Clockwork Proselytizers from the [sigil_name].")
+ to_chat(user, "You can recharge Replica Fabricators from the [sigil_name].")
/obj/effect/clockwork/sigil/transmission/attackby(obj/item/I, mob/living/user, params)
if(is_servant_of_ratvar(user) && istype(I, /obj/item/stack/tile/brass) && !GLOB.ratvar_awakens)
diff --git a/code/game/gamemodes/clock_cult/clock_helpers/clock_powerdrain.dm b/code/game/gamemodes/clock_cult/clock_helpers/clock_powerdrain.dm
index 705273876c..cdde45bb4c 100644
--- a/code/game/gamemodes/clock_cult/clock_helpers/clock_powerdrain.dm
+++ b/code/game/gamemodes/clock_cult/clock_helpers/clock_powerdrain.dm
@@ -29,7 +29,7 @@
if(charge)
. = min(charge, 250)
charge = use(.)
- updateicon()
+ update_icon()
/obj/machinery/light/power_drain(clockcult_user)
if(on)
diff --git a/code/game/gamemodes/clock_cult/clock_helpers/fabrication_helpers.dm b/code/game/gamemodes/clock_cult/clock_helpers/fabrication_helpers.dm
new file mode 100644
index 0000000000..1dd976d198
--- /dev/null
+++ b/code/game/gamemodes/clock_cult/clock_helpers/fabrication_helpers.dm
@@ -0,0 +1,372 @@
+//For the clockwork fabricator, this proc exists to make it easy to customize what the fabricator does when hitting something.
+
+//if a valid target, returns an associated list in this format;
+//list("operation_time" = 15, "new_obj_type" = /obj/structure/window/reinforced/clockwork, "power_cost" = 5, "spawn_dir" = dir, "dir_in_new" = TRUE)
+//otherwise, return literally any non-list thing but preferably FALSE
+//returning TRUE won't produce the "cannot be fabricated" message and will still prevent fabrication
+
+/atom/proc/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent)
+ return FALSE
+
+/atom/proc/consume_visual(obj/item/clockwork/replica_fabricator/fabricator, power_amount)
+ if(fabricator.can_use_power(power_amount))
+ var/obj/effect/temp_visual/ratvar/beam/itemconsume/B = new /obj/effect/temp_visual/ratvar/beam/itemconsume(get_turf(src))
+ B.pixel_x = pixel_x
+ B.pixel_y = pixel_y
+
+//Turf conversion
+/turf/closed/wall/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent) //four sheets of metal
+ return list("operation_time" = 50, "new_obj_type" = /turf/closed/wall/clockwork, "power_cost" = POWER_WALL_TOTAL - (POWER_METAL * 4), "spawn_dir" = SOUTH)
+
+/turf/closed/wall/mineral/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent) //two sheets of metal
+ return list("operation_time" = 50, "new_obj_type" = /turf/closed/wall/clockwork, "power_cost" = POWER_WALL_TOTAL - (POWER_METAL * 2), "spawn_dir" = SOUTH)
+
+/turf/closed/wall/mineral/iron/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent) //two sheets of metal, five rods
+ return list("operation_time" = 50, "new_obj_type" = /turf/closed/wall/clockwork, "power_cost" = POWER_WALL_TOTAL - (POWER_METAL * 2) - (POWER_ROD * 5), "spawn_dir" = SOUTH)
+
+/turf/closed/wall/mineral/cult/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent) //no metal
+ return list("operation_time" = 80, "new_obj_type" = /turf/closed/wall/clockwork, "power_cost" = POWER_WALL_TOTAL, "spawn_dir" = SOUTH)
+
+/turf/closed/wall/shuttle/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent) //two sheets of metal
+ return list("operation_time" = 50, "new_obj_type" = /turf/closed/wall/clockwork, "power_cost" = POWER_WALL_TOTAL - (POWER_METAL * 2), "spawn_dir" = SOUTH)
+
+/turf/closed/wall/r_wall/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent)
+ return FALSE
+
+/turf/closed/wall/clockwork/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent)
+ return list("operation_time" = 50, "new_obj_type" = /turf/open/floor/clockwork, "power_cost" = -POWER_WALL_MINUS_FLOOR, "spawn_dir" = SOUTH)
+
+/turf/open/floor/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent)
+ if(floor_tile == /obj/item/stack/tile/plasteel)
+ new floor_tile(src)
+ make_plating()
+ playsound(src, 'sound/items/Crowbar.ogg', 10, 1) //clink
+ return list("operation_time" = 30, "new_obj_type" = /turf/open/floor/clockwork, "power_cost" = POWER_FLOOR, "spawn_dir" = SOUTH)
+
+/turf/open/floor/plating/asteroid/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent)
+ return FALSE
+
+/turf/open/floor/plating/ashplanet/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent)
+ return FALSE
+
+/turf/open/floor/plating/lava/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent)
+ return FALSE
+
+/turf/open/floor/clockwork/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent)
+ if(locate(/obj/structure/table) in src)
+ return FALSE
+ if(locate(/obj/structure/falsewall) in contents)
+ to_chat(user, "There is a false wall in the way, preventing you from fabricating a clockwork wall on [src].")
+ return
+ if(is_blocked_turf(src, TRUE))
+ to_chat(user, "Something is in the way, preventing you from fabricating a clockwork wall on [src].")
+ return TRUE
+ var/operation_time = 100
+ if(!GLOB.ratvar_awakens && fabricator.speed_multiplier > 0) //if ratvar isn't awake, this always takes 10 seconds
+ operation_time /= fabricator.speed_multiplier
+ return list("operation_time" = operation_time, "new_obj_type" = /turf/closed/wall/clockwork, "power_cost" = POWER_WALL_MINUS_FLOOR, "spawn_dir" = SOUTH)
+
+//False wall conversion
+/obj/structure/falsewall/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent)
+ var/cost = POWER_WALL_MINUS_FLOOR
+ if(ispath(mineral, /obj/item/stack/sheet/metal))
+ cost -= (POWER_METAL * (2 + mineral_amount)) //four sheets of metal, plus an assumption that the girder is also two
+ else
+ cost -= (POWER_METAL * 2) //anything that doesn't use metal just has the girder
+ return list("operation_time" = 50, "new_obj_type" = /obj/structure/falsewall/brass, "power_cost" = cost, "spawn_dir" = SOUTH)
+
+/obj/structure/falsewall/iron/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent) //two sheets of metal, two rods; special assumption
+ return list("operation_time" = 50, "new_obj_type" = /obj/structure/falsewall/brass, "power_cost" = POWER_WALL_MINUS_FLOOR - (POWER_METAL * 2) - (POWER_ROD * 2), "spawn_dir" = SOUTH)
+
+/obj/structure/falsewall/reinforced/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent)
+ return FALSE
+
+/obj/structure/falsewall/brass/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent)
+ return FALSE
+
+//Metal conversion
+/obj/item/stack/tile/plasteel/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent)
+ if(source)
+ return FALSE
+ var/amount_temp = get_amount()
+ var/no_delete = FALSE
+ if(amount_temp < 2)
+ to_chat(user, "You need at least 2 floor tiles to convert into power.")
+ return TRUE
+ if(IsOdd(amount_temp))
+ amount_temp--
+ no_delete = TRUE
+ use(amount_temp)
+ amount_temp *= 12.5 //each tile is 12.5 power so this is 2 tiles to 25 power
+ consume_visual(fabricator, amount_temp)
+ return list("operation_time" = 0, "new_obj_type" = null, "power_cost" = -amount_temp, "spawn_dir" = SOUTH, "no_target_deletion" = no_delete)
+
+/obj/item/stack/rods/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent)
+ if(source)
+ return FALSE
+ var/power_amount = -(amount*POWER_ROD)
+ consume_visual(fabricator, power_amount)
+ return list("operation_time" = 0, "new_obj_type" = null, "power_cost" = power_amount, "spawn_dir" = SOUTH)
+
+/obj/item/stack/sheet/metal/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent)
+ if(source)
+ return FALSE
+ var/power_amount = -(amount*POWER_METAL)
+ consume_visual(fabricator, power_amount)
+ return list("operation_time" = 0, "new_obj_type" = null, "power_cost" = power_amount, "spawn_dir" = SOUTH)
+
+/obj/item/stack/sheet/plasteel/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent)
+ if(source)
+ return FALSE
+ var/power_amount = -(amount*POWER_PLASTEEL)
+ consume_visual(fabricator, power_amount)
+ return list("operation_time" = 0, "new_obj_type" = null, "power_cost" = power_amount, "spawn_dir" = SOUTH)
+
+//Brass directly to power
+/obj/item/stack/tile/brass/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent)
+ if(source)
+ return FALSE
+ var/power_amount = -(amount*POWER_FLOOR)
+ consume_visual(fabricator, power_amount)
+ return list("operation_time" = 0, "new_obj_type" = null, "power_cost" = power_amount, "spawn_dir" = SOUTH)
+
+//Airlock conversion
+/obj/machinery/door/airlock/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent)
+ var/doortype = /obj/machinery/door/airlock/clockwork
+ if(glass)
+ doortype = /obj/machinery/door/airlock/clockwork/brass
+ return list("operation_time" = 60, "new_obj_type" = doortype, "power_cost" = POWER_WALL_TOTAL, "spawn_dir" = dir)
+
+/obj/machinery/door/airlock/clockwork/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent)
+ return FALSE
+
+//Table conversion
+/obj/structure/table/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent)
+ var/fabrication_cost = POWER_STANDARD
+ if(framestack == /obj/item/stack/rods)
+ fabrication_cost -= POWER_ROD*framestackamount
+ else if(framestack == /obj/item/stack/tile/brass)
+ fabrication_cost -= POWER_FLOOR*framestackamount
+ if(buildstack == /obj/item/stack/sheet/metal)
+ fabrication_cost -= POWER_METAL*buildstackamount
+ else if(buildstack == /obj/item/stack/sheet/plasteel)
+ fabrication_cost -= POWER_PLASTEEL*buildstackamount
+ return list("operation_time" = 20, "new_obj_type" = /obj/structure/table/reinforced/brass, "power_cost" = fabrication_cost, "spawn_dir" = SOUTH)
+
+/obj/structure/table/reinforced/brass/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent)
+ return FALSE
+
+/obj/structure/table_frame/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent)
+ var/fabrication_cost = POWER_FLOOR
+ if(framestack == /obj/item/stack/rods)
+ fabrication_cost -= POWER_ROD*framestackamount
+ else if(framestack == /obj/item/stack/tile/brass)
+ fabrication_cost -= POWER_FLOOR*framestackamount
+ return list("operation_time" = 10, "new_obj_type" = /obj/structure/table_frame/brass, "power_cost" = fabrication_cost, "spawn_dir" = SOUTH)
+
+/obj/structure/table_frame/brass/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent)
+ return FALSE
+
+//Window conversion
+/obj/structure/window/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent)
+ var/windowtype = /obj/structure/window/reinforced/clockwork
+ var/new_dir = TRUE
+ var/fabrication_time = 15
+ var/fabrication_cost = POWER_FLOOR
+ if(fulltile)
+ windowtype = /obj/structure/window/reinforced/clockwork/fulltile
+ new_dir = FALSE
+ fabrication_time = 30
+ fabrication_cost = POWER_STANDARD
+ if(reinf)
+ fabrication_cost -= POWER_ROD
+ if(reinf)
+ fabrication_cost -= POWER_ROD
+ for(var/obj/structure/grille/G in get_turf(src))
+ INVOKE_ASYNC(fabricator, /obj/item/clockwork/replica_fabricator.proc/fabricate, G, user)
+ return list("operation_time" = fabrication_time, "new_obj_type" = windowtype, "power_cost" = fabrication_cost, "spawn_dir" = dir, "dir_in_new" = new_dir)
+
+/obj/structure/window/reinforced/clockwork/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent)
+ return FALSE
+
+//Windoor conversion
+/obj/machinery/door/window/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent)
+ return list("operation_time" = 30, "new_obj_type" = /obj/machinery/door/window/clockwork, "power_cost" = POWER_STANDARD, "spawn_dir" = dir, "dir_in_new" = TRUE)
+
+/obj/machinery/door/window/clockwork/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent)
+ return FALSE
+
+//Grille conversion
+/obj/structure/grille/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent)
+ var/grilletype = /obj/structure/grille/ratvar
+ var/fabrication_time = 15
+ if(broken)
+ grilletype = /obj/structure/grille/ratvar/broken
+ fabrication_time = 5
+ return list("operation_time" = fabrication_time, "new_obj_type" = grilletype, "power_cost" = 0, "spawn_dir" = dir)
+
+/obj/structure/grille/ratvar/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent)
+ return FALSE
+
+//Lattice conversion
+/obj/structure/lattice/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent)
+ return list("operation_time" = 0, "new_obj_type" = /obj/structure/lattice/clockwork, "power_cost" = 0, "spawn_dir" = SOUTH, "no_target_deletion" = TRUE)
+
+/obj/structure/lattice/clockwork/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent)
+ ratvar_act() //just in case we're the wrong type for some reason??
+ return FALSE
+
+/obj/structure/lattice/catwalk/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent)
+ return list("operation_time" = 0, "new_obj_type" = /obj/structure/lattice/catwalk/clockwork, "power_cost" = 0, "spawn_dir" = SOUTH, "no_target_deletion" = TRUE)
+
+/obj/structure/lattice/catwalk/clockwork/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent)
+ return FALSE
+
+//Girder conversion
+/obj/structure/girder/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent)
+ var/fabrication_cost = POWER_GEAR - (POWER_METAL * 2)
+ if(state == GIRDER_REINF_STRUTS || state == GIRDER_REINF)
+ fabrication_cost -= POWER_PLASTEEL
+ return list("operation_time" = 20, "new_obj_type" = /obj/structure/destructible/clockwork/wall_gear, "power_cost" = fabrication_cost, "spawn_dir" = SOUTH)
+
+//Hitting a clockwork structure will try to repair it.
+/obj/structure/destructible/clockwork/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent)
+ . = TRUE
+ var/list/repair_values = list()
+ if(!fabricator.fabricator_repair_checks(repair_values, src, user))
+ return
+ user.visible_message("[user]'s [fabricator.name] starts covering [src] in glowing orange energy...", \
+ "You start repairing [src]...")
+ fabricator.repairing = src
+ while(fabricator && user && src)
+ if(!do_after(user, repair_values["healing_for_cycle"] * fabricator.speed_multiplier, target = src, \
+ extra_checks = CALLBACK(fabricator, /obj/item/clockwork/replica_fabricator.proc/fabricator_repair_checks, repair_values, src, user, TRUE)))
+ break
+ obj_integrity = Clamp(obj_integrity + repair_values["healing_for_cycle"], 0, max_integrity)
+ fabricator.modify_stored_power(-repair_values["power_required"])
+ playsound(src, 'sound/machines/click.ogg', 50, 1)
+
+ if(fabricator)
+ fabricator.repairing = null
+ if(user)
+ user.visible_message("[user]'s [fabricator.name] stops covering [src] with glowing orange energy.", \
+ "You finish repairing [src]. It is now at [obj_integrity]/[max_integrity] integrity.")
+
+//Hitting a sigil of transmission will try to charge from it.
+/obj/effect/clockwork/sigil/transmission/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent)
+ . = TRUE
+ var/list/charge_values = list()
+ if(!fabricator.sigil_charge_checks(charge_values, src, user))
+ return
+ user.visible_message("[user]'s [fabricator.name] starts draining glowing orange energy from [src]...", \
+ "You start recharging your [fabricator.name]...")
+ fabricator.recharging = src
+ while(fabricator && user && src)
+ if(!do_after(user, 10, target = src, extra_checks = CALLBACK(fabricator, /obj/item/clockwork/replica_fabricator.proc/sigil_charge_checks, charge_values, src, user, TRUE)))
+ break
+ modify_charge(charge_values["power_gain"])
+ fabricator.modify_stored_power(charge_values["power_gain"])
+ playsound(src, 'sound/effects/light_flicker.ogg', charge_values["power_gain"] * 0.1, 1)
+
+ if(fabricator)
+ fabricator.recharging = null
+ if(user)
+ user.visible_message("[user]'s [fabricator.name] stops draining glowing orange energy from [src].", \
+ "You finish recharging your [fabricator.name]. It now contains [fabricator.get_power()]W/[fabricator.get_max_power()]W power.")
+
+//Fabricator mob heal proc, to avoid as much copypaste as possible.
+/mob/living/proc/fabricator_heal(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator)
+ var/list/repair_values = list()
+ if(!fabricator.fabricator_repair_checks(repair_values, src, user))
+ return
+ user.visible_message("[user]'s [fabricator.name] starts coverin[src == user ? "g [user.p_them()]" : "g [src]"] in glowing orange energy...", \
+ "You start repairin[src == user ? "g yourself" : "g [src]"]...")
+ fabricator.repairing = src
+ while(fabricator && user && src)
+ if(!do_after(user, repair_values["healing_for_cycle"] * fabricator.speed_multiplier, target = src, \
+ extra_checks = CALLBACK(fabricator, /obj/item/clockwork/replica_fabricator.proc/fabricator_repair_checks, repair_values, src, user, TRUE)))
+ break
+ fabricator_heal_tick(repair_values["healing_for_cycle"])
+ fabricator.modify_stored_power(-repair_values["power_required"])
+ playsound(src, 'sound/machines/click.ogg', 50, 1)
+
+ if(fabricator)
+ fabricator.repairing = null
+
+ return TRUE
+
+/mob/living/proc/fabricator_heal_tick(amount)
+ var/static/list/damage_heal_order = list(BRUTE, BURN, TOX, OXY)
+ heal_ordered_damage(amount, damage_heal_order)
+
+/mob/living/simple_animal/fabricator_heal_tick(amount)
+ adjustHealth(-amount)
+
+//Hitting a ratvar'd silicon will also try to repair it.
+/mob/living/silicon/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent)
+ . = TRUE
+ if(health == maxHealth) //if we're at maximum health, replace the turf under us
+ return FALSE
+ else if(fabricator_heal(user, fabricator) && user)
+ user.visible_message("[user]'s [fabricator.name] stops coverin[src == user ? "g [user.p_them()]" : "g [src]"] with glowing orange energy.", \
+ "You finish repairin[src == user ? "g yourself. You are":"g [src]. [p_they(TRUE)] [p_are()]"] now at [abs(HEALTH_THRESHOLD_DEAD - health)]/[abs(HEALTH_THRESHOLD_DEAD - maxHealth)] health.")
+
+//Same with clockwork mobs.
+/mob/living/simple_animal/hostile/clockwork/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent)
+ . = TRUE
+ if(health == maxHealth) //if we're at maximum health, replace the turf under us
+ return FALSE
+ else if(fabricator_heal(user, fabricator) && user)
+ user.visible_message("[user]'s [fabricator.name] stops coverin[src == user ? "g [user.p_them()]" : "g [src]"] with glowing orange energy.", \
+ "You finish repairin[src == user ? "g yourself. You are":"g [src]. [p_they(TRUE)] [p_are()]"] now at [health]/[maxHealth] health.")
+
+//Cogscarabs get special interaction because they're drones and have innate self-heals/revives.
+/mob/living/simple_animal/drone/cogscarab/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent)
+ . = TRUE
+ if(stat == DEAD)
+ try_reactivate(user) //if we're dead, try to repair us
+ return
+ if(health == maxHealth)
+ return FALSE
+ else if(!(flags & GODMODE))
+ user.visible_message("[user]'s [fabricator.name] starts coverin[src == user ? "g [user.p_them()]" : "g [src]"] in glowing orange energy...", \
+ "You start repairin[src == user ? "g yourself" : "g [src]"]...")
+ fabricator.repairing = src
+ if(do_after(user, (maxHealth - health)*2, target=src))
+ adjustHealth(-maxHealth)
+ user.visible_message("[user]'s [fabricator.name] stops coverin[src == user ? "g [user.p_them()]" : "g [src]"] with glowing orange energy.", \
+ "You finish repairin[src == user ? "g yourself" : "g [src]"].")
+ if(fabricator)
+ fabricator.repairing = null
+
+//Convert shards and gear bits directly to power
+/obj/item/clockwork/alloy_shards/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent, power_amount)
+ if(!power_amount)
+ power_amount = -POWER_STANDARD
+ consume_visual(fabricator, power_amount)
+ if(!silent) //looper no looping
+ for(var/obj/item/clockwork/alloy_shards/S in get_turf(src)) //convert all other shards in the turf if we can
+ if(S == src)
+ continue //we want the shards to be fabricated after the main shard, thus this delay
+ addtimer(CALLBACK(fabricator, /obj/item/clockwork/replica_fabricator.proc/fabricate, S, user, TRUE), 0)
+ return list("operation_time" = 0, "new_obj_type" = null, "power_cost" = power_amount, "spawn_dir" = SOUTH)
+
+/obj/item/clockwork/alloy_shards/medium/gear_bit/large/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent, power_amount)
+ if(!power_amount)
+ power_amount = -(CLOCKCULT_POWER_UNIT*0.08)
+ return ..()
+
+/obj/item/clockwork/alloy_shards/large/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent, power_amount)
+ if(!power_amount)
+ power_amount = -(CLOCKCULT_POWER_UNIT*0.06)
+ return ..()
+
+/obj/item/clockwork/alloy_shards/medium/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent, power_amount)
+ if(!power_amount)
+ power_amount = -(CLOCKCULT_POWER_UNIT*0.04)
+ return ..()
+
+/obj/item/clockwork/alloy_shards/small/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent, power_amount)
+ if(!power_amount)
+ power_amount = -(CLOCKCULT_POWER_UNIT*0.02)
+ return ..()
diff --git a/code/game/gamemodes/clock_cult/clock_helpers/proselytizer_helpers.dm b/code/game/gamemodes/clock_cult/clock_helpers/proselytizer_helpers.dm
index 3e7d0f3779..56f55a8f80 100644
--- a/code/game/gamemodes/clock_cult/clock_helpers/proselytizer_helpers.dm
+++ b/code/game/gamemodes/clock_cult/clock_helpers/proselytizer_helpers.dm
@@ -49,6 +49,9 @@
/turf/open/floor/clockwork/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer)
if(locate(/obj/structure/table) in src)
return FALSE
+ if(locate(/obj/structure/falsewall) in contents)
+ to_chat(user, "There is a false wall in the way, preventing you from proselytizing [src] into a clockwork wall.")
+ return
if(is_blocked_turf(src, TRUE))
to_chat(user, "Something is in the way, preventing you from proselytizing [src] into a clockwork wall.")
return TRUE
diff --git a/code/game/gamemodes/clock_cult/clock_helpers/scripture_checks.dm b/code/game/gamemodes/clock_cult/clock_helpers/scripture_checks.dm
index 914804185e..3862791f8c 100644
--- a/code/game/gamemodes/clock_cult/clock_helpers/scripture_checks.dm
+++ b/code/game/gamemodes/clock_cult/clock_helpers/scripture_checks.dm
@@ -7,13 +7,17 @@
servants++
. = list(SCRIPTURE_DRIVER = TRUE, SCRIPTURE_SCRIPT = FALSE, SCRIPTURE_APPLICATION = FALSE, SCRIPTURE_REVENANT = FALSE, SCRIPTURE_JUDGEMENT = FALSE)
//Drivers: always unlocked
- .[SCRIPTURE_SCRIPT] = (servants >= SCRIPT_SERVANT_REQ && GLOB.clockwork_caches >= SCRIPT_CACHE_REQ)
+ .[SCRIPTURE_SCRIPT] = (SSticker.scripture_states[SCRIPTURE_SCRIPT] || \
+ (servants >= SCRIPT_SERVANT_REQ && GLOB.clockwork_caches >= SCRIPT_CACHE_REQ))
//Script: SCRIPT_SERVANT_REQ or more non-brain servants and SCRIPT_CACHE_REQ or more clockwork caches
- .[SCRIPTURE_APPLICATION] = (servants >= APPLICATION_SERVANT_REQ && GLOB.clockwork_caches >= APPLICATION_CACHE_REQ && GLOB.clockwork_construction_value >= APPLICATION_CV_REQ)
+ .[SCRIPTURE_APPLICATION] = (SSticker.scripture_states[SCRIPTURE_APPLICATION] || \
+ (servants >= APPLICATION_SERVANT_REQ && GLOB.clockwork_caches >= APPLICATION_CACHE_REQ && GLOB.clockwork_construction_value >= APPLICATION_CV_REQ))
//Application: APPLICATION_SERVANT_REQ or more non-brain servants, APPLICATION_CACHE_REQ or more clockwork caches, and at least APPLICATION_CV_REQ CV
- .[SCRIPTURE_REVENANT] = (servants >= REVENANT_SERVANT_REQ && GLOB.clockwork_caches >= REVENANT_CACHE_REQ && GLOB.clockwork_construction_value >= REVENANT_CV_REQ)
+ .[SCRIPTURE_REVENANT] = (SSticker.scripture_states[SCRIPTURE_REVENANT] || \
+ (servants >= REVENANT_SERVANT_REQ && GLOB.clockwork_caches >= REVENANT_CACHE_REQ && GLOB.clockwork_construction_value >= REVENANT_CV_REQ))
//Revenant: REVENANT_SERVANT_REQ or more non-brain servants, REVENANT_CACHE_REQ or more clockwork caches, and at least REVENANT_CV_REQ CV
- .[SCRIPTURE_JUDGEMENT] = (servants >= JUDGEMENT_SERVANT_REQ && GLOB.clockwork_caches >= JUDGEMENT_CACHE_REQ && GLOB.clockwork_construction_value >= JUDGEMENT_CV_REQ && !unconverted_ai_exists)
+ .[SCRIPTURE_JUDGEMENT] = (SSticker.scripture_states[SCRIPTURE_JUDGEMENT] || \
+ (servants >= JUDGEMENT_SERVANT_REQ && GLOB.clockwork_caches >= JUDGEMENT_CACHE_REQ && GLOB.clockwork_construction_value >= JUDGEMENT_CV_REQ && !unconverted_ai_exists))
//Judgement: JUDGEMENT_SERVANT_REQ or more non-brain servants, JUDGEMENT_CACHE_REQ or more clockwork caches, at least JUDGEMENT_CV_REQ CV, and there are no living, non-servant ais
//reports to servants when scripture is locked or unlocked
diff --git a/code/game/gamemodes/clock_cult/clock_items/clock_components.dm b/code/game/gamemodes/clock_cult/clock_items/clock_components.dm
index f64b361ac1..7550aea74f 100644
--- a/code/game/gamemodes/clock_cult/clock_items/clock_components.dm
+++ b/code/game/gamemodes/clock_cult/clock_items/clock_components.dm
@@ -153,11 +153,11 @@
icon_state = "obelisk_prism"
w_class = WEIGHT_CLASS_NORMAL
-//Shards of Alloy, suitable only for proselytization.
+//Shards of Alloy, suitable only as a source of power for a replica fabricator.
/obj/item/clockwork/alloy_shards
name = "replicant alloy shards"
desc = "Broken shards of some oddly malleable metal. They occasionally move and seem to glow."
- clockwork_desc = "Broken shards of replicant alloy. Can be proselytized for additional power."
+ clockwork_desc = "Broken shards of replicant alloy."
icon_state = "alloy_shards"
resistance_flags = LAVA_PROOF | FIRE_PROOF | ACID_PROOF
var/randomsinglesprite = FALSE
@@ -172,10 +172,15 @@
pixel_x = rand(-sprite_shift, sprite_shift)
pixel_y = rand(-sprite_shift, sprite_shift)
+/obj/item/clockwork/alloy_shards/examine(mob/user)
+ ..()
+ if(is_servant_of_ratvar(user) || isobserver(user))
+ to_chat(user, "Can be consumed by a replica fabricator as a source of power.")
+
/obj/item/clockwork/alloy_shards/proc/replace_name_desc()
name = "replicant alloy shard"
desc = "A broken shard of some oddly malleable metal. It occasionally moves and seems to glow."
- clockwork_desc = "A broken shard of replicant alloy. Can be proselytized for additional power."
+ clockwork_desc = "A broken shard of replicant alloy."
/obj/item/clockwork/alloy_shards/large
w_class = WEIGHT_CLASS_TINY
@@ -197,7 +202,7 @@
/obj/item/clockwork/alloy_shards/medium/gear_bit/replace_name_desc()
name = "gear bit"
desc = "A broken chunk of a gear. You want it."
- clockwork_desc = "A broken chunk of a gear. Can be proselytized for additional power."
+ clockwork_desc = "A broken chunk of a gear."
/obj/item/clockwork/alloy_shards/medium/gear_bit/large //gives more power
@@ -215,5 +220,5 @@
/obj/item/clockwork/alloy_shards/pinion_lock
name = "pinion lock"
desc = "A dented and scratched gear. It's very heavy."
- clockwork_desc = "A broken gear lock for pinion airlocks. Can be proselytized for additional power."
+ clockwork_desc = "A broken gear lock for pinion airlocks"
icon_state = "pinion_lock"
diff --git a/code/game/gamemodes/clock_cult/clock_items/clockwork_slab.dm b/code/game/gamemodes/clock_cult/clock_items/clockwork_slab.dm
index 72dba26bed..38a2cdadc0 100644
--- a/code/game/gamemodes/clock_cult/clock_items/clockwork_slab.dm
+++ b/code/game/gamemodes/clock_cult/clock_items/clockwork_slab.dm
@@ -41,7 +41,7 @@
if(!is_servant_of_ratvar(user))
add_servant_of_ratvar(user)
-/obj/item/clockwork/slab/cyborg //three scriptures, plus a spear and proselytizer
+/obj/item/clockwork/slab/cyborg //three scriptures, plus a spear and fabricator
clockwork_desc = "A divine link to the Celestial Derelict, allowing for limited recital of scripture.\n\
Hitting a slab, a Servant with a slab, or a cache will transfer this slab's components into the target, the target's slab, or the global cache, respectively."
quickbound = list(/datum/clockwork_scripture/ranged_ability/judicial_marker, /datum/clockwork_scripture/ranged_ability/linked_vanguard, \
@@ -49,7 +49,7 @@
maximum_quickbound = 6 //we usually have one or two unique scriptures, so if ratvar is up let us bind one more
actions_types = list()
-/obj/item/clockwork/slab/cyborg/engineer //five scriptures, plus a proselytizer
+/obj/item/clockwork/slab/cyborg/engineer //five scriptures, plus a fabricator
quickbound = list(/datum/clockwork_scripture/create_object/replicant, /datum/clockwork_scripture/create_object/cogscarab, \
/datum/clockwork_scripture/create_object/soul_vessel, /datum/clockwork_scripture/create_object/sigil_of_transmission, /datum/clockwork_scripture/create_object/interdiction_lens)
@@ -65,7 +65,7 @@
quickbound = list(/datum/clockwork_scripture/channeled/belligerent, /datum/clockwork_scripture/ranged_ability/judicial_marker, /datum/clockwork_scripture/channeled/taunting_tirade, \
/datum/clockwork_scripture/channeled/volt_void/cyborg)
-/obj/item/clockwork/slab/cyborg/janitor //five scriptures, plus a proselytizer
+/obj/item/clockwork/slab/cyborg/janitor //five scriptures, plus a fabricator
quickbound = list(/datum/clockwork_scripture/create_object/replicant, /datum/clockwork_scripture/create_object/sigil_of_transgression, \
/datum/clockwork_scripture/create_object/ocular_warden, /datum/clockwork_scripture/create_object/mania_motor, /datum/clockwork_scripture/create_object/tinkerers_daemon)
@@ -283,8 +283,7 @@
return FALSE
var/initial_tier = initial(scripture.tier)
if(initial_tier != SCRIPTURE_PERIPHERAL)
- var/list/tiers_of_scripture = scripture_unlock_check()
- if(!GLOB.ratvar_awakens && !no_cost && !tiers_of_scripture[initial_tier])
+ if(!GLOB.ratvar_awakens && !no_cost && !SSticker.scripture_states[initial_tier])
to_chat(user, "That scripture is not unlocked, and cannot be recited!")
return FALSE
var/datum/clockwork_scripture/scripture_to_recite = new scripture
@@ -403,13 +402,25 @@
if(SCRIPTURE_DRIVER)
data["tier_info"] = "These scriptures are always unlocked."
if(SCRIPTURE_SCRIPT)
- data["tier_info"] = "These scriptures require at least [SCRIPT_SERVANT_REQ] Servants and [SCRIPT_CACHE_REQ] Tinkerer's Cache."
+ if(SSticker.scripture_states[SCRIPTURE_SCRIPT])
+ data["tier_info"] = "These scriptures are permenantly unlocked."
+ else
+ data["tier_info"] = "These scriptures require at least [SCRIPT_SERVANT_REQ] Servants and [SCRIPT_CACHE_REQ] Tinkerer's Cache."
if(SCRIPTURE_APPLICATION)
- data["tier_info"] = "These scriptures require at least [APPLICATION_SERVANT_REQ] Servants, [APPLICATION_CACHE_REQ] Tinkerer's Caches, and [APPLICATION_CV_REQ]CV."
+ if(SSticker.scripture_states[SCRIPTURE_APPLICATION])
+ data["tier_info"] = "These scriptures are permenantly unlocked."
+ else
+ data["tier_info"] = "These scriptures require at least [APPLICATION_SERVANT_REQ] Servants, [APPLICATION_CACHE_REQ] Tinkerer's Caches, and [APPLICATION_CV_REQ]CV."
if(SCRIPTURE_REVENANT)
- data["tier_info"] = "These scriptures require at least [REVENANT_SERVANT_REQ] Servants, [REVENANT_CACHE_REQ] Tinkerer's Caches, and [REVENANT_CV_REQ]CV."
+ if(SSticker.scripture_states[SCRIPTURE_REVENANT])
+ data["tier_info"] = "These scriptures are permenantly unlocked."
+ else
+ data["tier_info"] = "These scriptures require at least [REVENANT_SERVANT_REQ] Servants, [REVENANT_CACHE_REQ] Tinkerer's Caches, and [REVENANT_CV_REQ]CV."
if(SCRIPTURE_JUDGEMENT)
- data["tier_info"] = "This scripture requires at least [JUDGEMENT_SERVANT_REQ] Servants, [JUDGEMENT_CACHE_REQ] Tinkerer's Caches, and [JUDGEMENT_CV_REQ]CV.
In addition, there may not be any active non-Servant AIs."
+ if(SSticker.scripture_states[SCRIPTURE_JUDGEMENT])
+ data["tier_info"] = "This scripture is permenantly unlocked."
+ else
+ data["tier_info"] = "This scripture requires at least [JUDGEMENT_SERVANT_REQ] Servants, [JUDGEMENT_CACHE_REQ] Tinkerer's Caches, and [JUDGEMENT_CV_REQ]CV.
In addition, there may not be any active non-Servant AIs."
data["selected"] = selected_scripture
diff --git a/code/game/gamemodes/clock_cult/clock_items/clockwork_proselytizer.dm b/code/game/gamemodes/clock_cult/clock_items/replica_fabricator.dm
similarity index 54%
rename from code/game/gamemodes/clock_cult/clock_items/clockwork_proselytizer.dm
rename to code/game/gamemodes/clock_cult/clock_items/replica_fabricator.dm
index aa174adcd8..788d581810 100644
--- a/code/game/gamemodes/clock_cult/clock_items/clockwork_proselytizer.dm
+++ b/code/game/gamemodes/clock_cult/clock_items/replica_fabricator.dm
@@ -1,51 +1,48 @@
-//Clockwork proselytizer: Converts applicable objects to Ratvarian variants.
-/obj/item/clockwork/clockwork_proselytizer
- name = "clockwork proselytizer"
+//Replica Fabricator: Converts applicable objects to Ratvarian variants.
+/obj/item/clockwork/replica_fabricator
+ name = "replica fabricator"
desc = "An odd, L-shaped device that hums with energy."
clockwork_desc = "A device that allows the replacing of mundane objects with Ratvarian variants. It requires power to function."
- icon_state = "clockwork_proselytizer"
+ icon_state = "replica_fabricator"
w_class = WEIGHT_CLASS_NORMAL
force = 5
flags = NOBLUDGEON
var/stored_power = 0 //Requires power to function
var/max_power = CLOCKCULT_POWER_UNIT * 10
var/uses_power = TRUE
- var/metal_to_power = FALSE
var/repairing = null //what we're currently repairing, if anything
var/obj/effect/clockwork/sigil/transmission/recharging = null //the sigil we're charging from, if any
- var/speed_multiplier = 1 //how fast this proselytizer works
+ var/speed_multiplier = 1 //how fast this fabricator works
var/charge_rate = MIN_CLOCKCULT_POWER //how much power we gain every two seconds
var/charge_delay = 2 //how many proccess ticks remain before we can start to charge
-/obj/item/clockwork/clockwork_proselytizer/preloaded
+/obj/item/clockwork/replica_fabricator/preloaded
stored_power = POWER_WALL_MINUS_FLOOR+POWER_WALL_TOTAL
-/obj/item/clockwork/clockwork_proselytizer/scarab
- name = "scarab proselytizer"
- clockwork_desc = "A cogscarab's internal proselytizer. It can only be successfully used by a cogscarab and requires power to function."
- metal_to_power = TRUE
+/obj/item/clockwork/replica_fabricator/scarab
+ name = "scarab fabricator"
+ clockwork_desc = "A cogscarab's internal fabricator. It can only be successfully used by a cogscarab and requires power to function."
item_state = "nothing"
w_class = WEIGHT_CLASS_TINY
speed_multiplier = 0.5
charge_rate = MIN_CLOCKCULT_POWER * 2
var/debug = FALSE
-/obj/item/clockwork/clockwork_proselytizer/scarab/proselytize(atom/target, mob/living/user)
+/obj/item/clockwork/replica_fabricator/scarab/fabricate(atom/target, mob/living/user)
if(!debug && !isdrone(user))
return 0
return ..()
-/obj/item/clockwork/clockwork_proselytizer/scarab/debug
- clockwork_desc = "A cogscarab's internal proselytizer. It can convert nearly any object into a Ratvarian variant."
+/obj/item/clockwork/replica_fabricator/scarab/debug
+ clockwork_desc = "A cogscarab's internal fabricator. It can convert nearly any object into a Ratvarian variant."
uses_power = FALSE
debug = TRUE
-/obj/item/clockwork/clockwork_proselytizer/cyborg
- name = "cyborg proselytizer"
- clockwork_desc = "A cyborg's internal proselytizer. It is capable of using the cyborg's power in addition to stored power."
- metal_to_power = TRUE
+/obj/item/clockwork/replica_fabricator/cyborg
+ name = "cyborg fabricator"
+ clockwork_desc = "A cyborg's internal fabricator. It is capable of using the cyborg's power in addition to stored power."
-/obj/item/clockwork/clockwork_proselytizer/cyborg/get_power() //returns power and cyborg's power
+/obj/item/clockwork/replica_fabricator/cyborg/get_power() //returns power and cyborg's power
var/mob/living/silicon/robot/R = get_atom_on_turf(src, /mob/living)
var/borg_power = 0
var/current_charge = 0
@@ -56,14 +53,14 @@
borg_power += MIN_CLOCKCULT_POWER
return ..() + borg_power
-/obj/item/clockwork/clockwork_proselytizer/cyborg/get_max_power()
+/obj/item/clockwork/replica_fabricator/cyborg/get_max_power()
var/mob/living/silicon/robot/R = get_atom_on_turf(src, /mob/living)
var/cell_maxcharge = 0
if(istype(R) && R.cell)
cell_maxcharge = R.cell.maxcharge
return ..() + cell_maxcharge
-/obj/item/clockwork/clockwork_proselytizer/cyborg/can_use_power(amount)
+/obj/item/clockwork/replica_fabricator/cyborg/can_use_power(amount)
if(amount != RATVAR_POWER_CHECK)
var/mob/living/silicon/robot/R = get_atom_on_turf(src, /mob/living)
var/current_charge = 0
@@ -76,7 +73,7 @@
return FALSE
. = ..()
-/obj/item/clockwork/clockwork_proselytizer/cyborg/modify_stored_power(amount)
+/obj/item/clockwork/replica_fabricator/cyborg/modify_stored_power(amount)
var/mob/living/silicon/robot/R = get_atom_on_turf(src, /mob/living)
if(istype(R) && R.cell && amount)
if(amount < 0)
@@ -89,15 +86,15 @@
amount -= MIN_CLOCKCULT_POWER
. = ..()
-/obj/item/clockwork/clockwork_proselytizer/Initialize()
+/obj/item/clockwork/replica_fabricator/Initialize()
. = ..()
START_PROCESSING(SSobj, src)
-/obj/item/clockwork/clockwork_proselytizer/Destroy()
+/obj/item/clockwork/replica_fabricator/Destroy()
STOP_PROCESSING(SSobj, src)
return ..()
-/obj/item/clockwork/clockwork_proselytizer/process()
+/obj/item/clockwork/replica_fabricator/process()
if(!charge_rate)
return
var/mob/living/L = get_atom_on_turf(src, /mob/living)
@@ -106,14 +103,14 @@
charge_delay--
return
modify_stored_power(charge_rate)
- for(var/obj/item/clockwork/clockwork_proselytizer/S in L.GetAllContents()) //no multiple proselytizers
+ for(var/obj/item/clockwork/replica_fabricator/S in L.GetAllContents()) //no multiple fabricators
if(S == src)
continue
S.charge_delay = 2
else
charge_delay = 2
-/obj/item/clockwork/clockwork_proselytizer/ratvar_act()
+/obj/item/clockwork/replica_fabricator/ratvar_act()
if(GLOB.nezbere_invoked)
charge_rate = 1250
else
@@ -125,21 +122,19 @@
uses_power = initial(uses_power)
speed_multiplier = initial(speed_multiplier)
-/obj/item/clockwork/clockwork_proselytizer/examine(mob/living/user)
+/obj/item/clockwork/replica_fabricator/examine(mob/living/user)
..()
if(is_servant_of_ratvar(user) || isobserver(user))
- to_chat(user, "Can be used to convert walls, floors, windows, airlocks, and a variety of other objects to clockwork variants.")
- to_chat(user, "Can also form some objects into Brass sheets, as well as reform Clockwork Walls into Clockwork Floors, and vice versa.")
+ to_chat(user, "Can be used to replace walls, floors, tables, windows, windoors, and airlocks with Clockwork variants.")
+ to_chat(user, "Can construct Clockwork Walls on Clockwork Floors and deconstruct Clockwork Walls to Clockwork Floors.")
if(uses_power)
- if(metal_to_power)
- to_chat(user, "It can convert rods, metal, plasteel, and brass to power at rates of 1:[POWER_ROD]W, 1:[POWER_METAL]W, \
- 1:[POWER_PLASTEEL]W, and 1:[POWER_FLOOR]W, respectively.")
- else
- to_chat(user, "It can convert brass to power at a rate of 1:[POWER_FLOOR]W.")
- to_chat(user, "It is storing [get_power()]W/[get_max_power()]W of power, and is gaining [charge_rate*0.5]W of power per second.")
+ to_chat(user, "It can consume floor tiles, rods, metal, and plasteel for power at rates of 2:[POWER_ROD]W, 1:[POWER_ROD]W, 1:[POWER_METAL]W, \
+ and 1:[POWER_PLASTEEL]W, respectively.")
+ to_chat(user, "It can also consume brass sheets for power at a rate of 1:[POWER_FLOOR]W.")
+ to_chat(user, "It is storing [get_power()]W/[get_max_power()]W of power[charge_rate ? ", and is gaining [charge_rate*0.5]W of power per second":""].")
to_chat(user, "Use it in-hand to produce 5 brass sheets at a cost of [POWER_WALL_TOTAL]W power.")
-/obj/item/clockwork/clockwork_proselytizer/attack_self(mob/living/user)
+/obj/item/clockwork/replica_fabricator/attack_self(mob/living/user)
if(is_servant_of_ratvar(user))
if(uses_power)
if(!can_use_power(POWER_WALL_TOTAL))
@@ -148,24 +143,24 @@
modify_stored_power(-POWER_WALL_TOTAL)
playsound(src, 'sound/items/Deconstruct.ogg', 50, 1)
new/obj/item/stack/tile/brass(user.loc, 5)
- to_chat(user, "You user [stored_power ? "some":"all"] of [src]'s power to produce some brass sheets. It now stores [get_power()]W/[get_max_power()]W of power.")
+ to_chat(user, "You use [stored_power ? "some":"all"] of [src]'s power to produce 5 brass sheets. It now stores [get_power()]W/[get_max_power()]W of power.")
-/obj/item/clockwork/clockwork_proselytizer/pre_attackby(atom/target, mob/living/user, params)
+/obj/item/clockwork/replica_fabricator/pre_attackby(atom/target, mob/living/user, params)
if(!target || !user || !is_servant_of_ratvar(user) || istype(target, /obj/item/weapon/storage))
return TRUE
- return proselytize(target, user)
+ return fabricate(target, user)
-/obj/item/clockwork/clockwork_proselytizer/proc/get_power()
+/obj/item/clockwork/replica_fabricator/proc/get_power()
return stored_power
-/obj/item/clockwork/clockwork_proselytizer/proc/get_max_power()
+/obj/item/clockwork/replica_fabricator/proc/get_max_power()
return max_power
-/obj/item/clockwork/clockwork_proselytizer/proc/modify_stored_power(amount)
+/obj/item/clockwork/replica_fabricator/proc/modify_stored_power(amount)
stored_power = Clamp(stored_power + amount, 0, max_power)
return TRUE
-/obj/item/clockwork/clockwork_proselytizer/proc/can_use_power(amount)
+/obj/item/clockwork/replica_fabricator/proc/can_use_power(amount)
if(amount == RATVAR_POWER_CHECK)
if(GLOB.ratvar_awakens || !uses_power)
return TRUE
@@ -178,7 +173,7 @@
return TRUE
//A note here; return values are for if we CAN BE PUT ON A TABLE, not IF WE ARE SUCCESSFUL, unless no_table_check is TRUE
-/obj/item/clockwork/clockwork_proselytizer/proc/proselytize(atom/target, mob/living/user, silent, no_table_check)
+/obj/item/clockwork/replica_fabricator/proc/fabricate(atom/target, mob/living/user, silent, no_table_check)
if(!target || !user)
return FALSE
if(repairing)
@@ -189,59 +184,77 @@
if(!silent)
to_chat(user, "You are currently recharging [src] from the [recharging.sigil_name]!")
return FALSE
- var/list/proselytize_values = target.proselytize_vals(user, src, silent) //relevant values for proselytizing stuff, given as an associated list
- if(!islist(proselytize_values))
- if(proselytize_values != TRUE) //if we get true, fail, but don't send a message for whatever reason
- if(!isturf(target)) //otherwise, if we didn't get TRUE and the original target wasn't a turf, try to proselytize the turf
- return proselytize(get_turf(target), user, no_table_check)
+ var/list/fabrication_values = target.fabrication_vals(user, src, silent) //relevant values for fabricating stuff, given as an associated list
+ if(!islist(fabrication_values))
+ if(fabrication_values != TRUE) //if we get true, fail, but don't send a message for whatever reason
+ if(!isturf(target)) //otherwise, if we didn't get TRUE and the original target wasn't a turf, try to fabricate the turf
+ return fabricate(get_turf(target), user, no_table_check)
if(!silent)
- to_chat(user, "[target] cannot be proselytized!")
+ to_chat(user, "[target] cannot be fabricated!")
if(!no_table_check)
return TRUE
return FALSE
if(can_use_power(RATVAR_POWER_CHECK))
- proselytize_values["power_cost"] = 0
+ fabrication_values["power_cost"] = 0
var/turf/Y = get_turf(user)
if(!Y || (Y.z != ZLEVEL_STATION && Y.z != ZLEVEL_CENTCOM && Y.z != ZLEVEL_MINING && Y.z != ZLEVEL_LAVALAND))
- proselytize_values["operation_time"] *= 2
- if(proselytize_values["power_cost"] > 0)
- proselytize_values["power_cost"] *= 2
+ fabrication_values["operation_time"] *= 2
+ if(fabrication_values["power_cost"] > 0)
+ fabrication_values["power_cost"] *= 2
var/target_type = target.type
- if(!proselytize_checks(proselytize_values, target, target_type, user, silent))
+ if(!fabricate_checks(fabrication_values, target, target_type, user, silent))
return FALSE
- proselytize_values["operation_time"] *= speed_multiplier
+ fabrication_values["operation_time"] *= speed_multiplier
playsound(target, 'sound/machines/click.ogg', 50, 1)
- if(proselytize_values["operation_time"])
+ if(fabrication_values["operation_time"])
if(!silent)
- user.visible_message("[user]'s [name] begins tearing apart [target]!", "You begin proselytizing [target]...")
- if(!do_after(user, proselytize_values["operation_time"], target = target, extra_checks = CALLBACK(src, .proc/proselytize_checks, proselytize_values, target, target_type, user, TRUE)))
+ var/atom/A = fabrication_values["new_obj_type"]
+ if(A)
+ user.visible_message("[user]'s [name] starts ripping [target] apart!", \
+ "You start fabricating \a [initial(A.name)] from [target]...")
+ else
+ user.visible_message("[user]'s [name] starts consuming [target]!", \
+ "Your [name] starts consuming [target]...")
+ if(!do_after(user, fabrication_values["operation_time"], target = target, extra_checks = CALLBACK(src, .proc/fabricate_checks, fabrication_values, target, target_type, user, TRUE)))
return FALSE
if(!silent)
- user.visible_message("[user]'s [name] covers [target] in golden energy!", "You proselytize [target].")
+ var/atom/A = fabrication_values["new_obj_type"]
+ if(A)
+ user.visible_message("[user]'s [name] replaces [target] with \a [initial(A.name)]!", \
+ "You fabricate \a [initial(A.name)] from [target].")
+ else
+ user.visible_message("[user]'s [name] consumes [target]!", \
+ "Your [name] consumes [target].")
else
if(!silent)
- user.visible_message("[user]'s [name] tears apart [target], covering it in golden energy!", "You proselytize [target].")
+ var/atom/A = fabrication_values["new_obj_type"]
+ if(A)
+ user.visible_message("[user]'s [name] rips apart [target], replacing it with \a [initial(A.name)]!", \
+ "You fabricate \a [initial(A.name)] from [target].")
+ else
+ user.visible_message("[user]'s [name] rapidly consumes [target]!", \
+ "Your [name] consumes [target].")
playsound(target, 'sound/items/Deconstruct.ogg', 50, 1)
- var/new_thing_type = proselytize_values["new_obj_type"]
+ var/new_thing_type = fabrication_values["new_obj_type"]
if(isturf(target)) //if our target is a turf, we're just going to ChangeTurf it and assume it'll work out.
var/turf/T = target
T.ChangeTurf(new_thing_type)
else
if(new_thing_type)
- if(proselytize_values["dir_in_new"])
- new new_thing_type(get_turf(target), proselytize_values["spawn_dir"]) //please verify that your new object actually wants to get a dir in New()
+ if(fabrication_values["dir_in_new"])
+ new new_thing_type(get_turf(target), fabrication_values["spawn_dir"]) //please verify that your new object actually wants to get a dir in New()
else
var/atom/A = new new_thing_type(get_turf(target))
- A.setDir(proselytize_values["spawn_dir"])
- if(!proselytize_values["no_target_deletion"]) //for some cases where proselytize_vals() modifies the object but doesn't want it deleted
+ A.setDir(fabrication_values["spawn_dir"])
+ if(!fabrication_values["no_target_deletion"]) //for some cases where fabrication_vals() modifies the object but doesn't want it deleted
qdel(target)
- modify_stored_power(-proselytize_values["power_cost"])
+ modify_stored_power(-fabrication_values["power_cost"])
if(no_table_check)
return TRUE
return FALSE
@@ -250,28 +263,34 @@
//What these procs do is they take an existing list of values, which they then modify.
//This(modifying an existing object, in this case the list) is the only way to get information OUT of a do_after callback, which this is used as.
-//The proselytize check proc.
-/obj/item/clockwork/clockwork_proselytizer/proc/proselytize_checks(list/proselytize_values, atom/target, expected_type, mob/user, silent) //checked constantly while proselytizing
- if(!islist(proselytize_values) || QDELETED(target) || QDELETED(user))
+//The fabricate check proc.
+/obj/item/clockwork/replica_fabricator/proc/fabricate_checks(list/fabrication_values, atom/target, expected_type, mob/user, silent) //checked constantly while fabricating
+ if(!islist(fabrication_values) || QDELETED(target) || QDELETED(user))
return FALSE
if(repairing || recharging)
return FALSE
if(target.type != expected_type)
return FALSE
if(can_use_power(RATVAR_POWER_CHECK))
- proselytize_values["power_cost"] = 0
- if(!can_use_power(proselytize_values["power_cost"]))
- if(stored_power - proselytize_values["power_cost"] < 0)
+ fabrication_values["power_cost"] = 0
+ if(!can_use_power(fabrication_values["power_cost"]))
+ if(stored_power - fabrication_values["power_cost"] < 0)
if(!silent)
- to_chat(user, "You need [proselytize_values["power_cost"]]W power to proselytize [target]!")
- else if(stored_power - proselytize_values["power_cost"] > max_power)
+ var/atom/A = fabrication_values["new_obj_type"]
+ if(A)
+ to_chat(user, "You need [fabrication_values["power_cost"]]W power to fabricate \a [initial(A.name)] from [target]!")
+ else if(stored_power - fabrication_values["power_cost"] > max_power)
if(!silent)
- to_chat(user, "Your [name] contains too much power to proselytize [target]!")
+ var/atom/A = fabrication_values["new_obj_type"]
+ if(A)
+ to_chat(user, "Your [name] contains too much power to fabricate \a [initial(A.name)] from [target]!")
+ else
+ to_chat(user, "Your [name] contains too much power to consume [target]!")
return FALSE
return TRUE
//The repair check proc.
-/obj/item/clockwork/clockwork_proselytizer/proc/proselytizer_repair_checks(list/repair_values, atom/target, mob/user, silent) //Exists entirely to avoid an otherwise unreadable series of checks.
+/obj/item/clockwork/replica_fabricator/proc/fabricator_repair_checks(list/repair_values, atom/target, mob/user, silent) //Exists entirely to avoid an otherwise unreadable series of checks.
if(!islist(repair_values) || QDELETED(target) || QDELETED(user))
return FALSE
if(isliving(target)) //standard checks for if we can affect the target
@@ -302,7 +321,7 @@
return FALSE
if(repair_values["amount_to_heal"] <= 0) //nothing to heal!
return FALSE
- repair_values["healing_for_cycle"] = min(repair_values["amount_to_heal"], PROSELYTIZER_REPAIR_PER_TICK) //modify the healing for this cycle
+ repair_values["healing_for_cycle"] = min(repair_values["amount_to_heal"], FABRICATOR_REPAIR_PER_TICK) //modify the healing for this cycle
repair_values["power_required"] = round(repair_values["healing_for_cycle"]*MIN_CLOCKCULT_POWER, MIN_CLOCKCULT_POWER) //and get the power cost from that
if(!can_use_power(RATVAR_POWER_CHECK) && !can_use_power(repair_values["power_required"]))
if(!silent)
@@ -312,7 +331,7 @@
return TRUE
//The sigil charge check proc.
-/obj/item/clockwork/clockwork_proselytizer/proc/sigil_charge_checks(list/charge_values, obj/effect/clockwork/sigil/transmission/sigil, mob/user, silent)
+/obj/item/clockwork/replica_fabricator/proc/sigil_charge_checks(list/charge_values, obj/effect/clockwork/sigil/transmission/sigil, mob/user, silent)
if(!islist(charge_values) || QDELETED(sigil) || QDELETED(user))
return FALSE
if(can_use_power(RATVAR_POWER_CHECK))
diff --git a/code/game/gamemodes/clock_cult/clock_scriptures/scripture_revenant.dm b/code/game/gamemodes/clock_cult/clock_scriptures/scripture_revenant.dm
index 25bedd79d3..ae54b903b6 100644
--- a/code/game/gamemodes/clock_cult/clock_scriptures/scripture_revenant.dm
+++ b/code/game/gamemodes/clock_cult/clock_scriptures/scripture_revenant.dm
@@ -105,11 +105,11 @@
descname = "Global Structure Buff"
name = "Invoke Nezbere, the Brass Eidolon"
desc = "Taps the limitless power of Nezbere, one of Ratvar's four generals. The restless toil of the Eidolon will empower a wide variety of clockwork apparatus for a full minute - notably, \
- clockwork proselytizers will charge very rapidly."
+ replica fabricators will charge very rapidly."
invocations = list("I call upon you, Armorer!!", "Let your machinations reign on this miserable station!!", "Let your power flow through the tools of your master!!")
channel_time = 150
consumed_components = list(BELLIGERENT_EYE = 6, VANGUARD_COGWHEEL = 6, GEIS_CAPACITOR = 6, REPLICANT_ALLOY = 10)
- usage_tip = "Ocular wardens will become empowered, clockwork proselytizers will require no alloy, tinkerer's daemons will produce twice as quickly, \
+ usage_tip = "Ocular wardens will become empowered, tinkerer's daemons will produce twice as quickly, \
and interdiction lenses, mania motors, tinkerer's daemons, and clockwork obelisks will all require no power."
tier = SCRIPTURE_REVENANT
primary_component = REPLICANT_ALLOY
diff --git a/code/game/gamemodes/clock_cult/clock_scriptures/scripture_scripts.dm b/code/game/gamemodes/clock_cult/clock_scriptures/scripture_scripts.dm
index 9efb9a8eb2..c6eba3e3c9 100644
--- a/code/game/gamemodes/clock_cult/clock_scriptures/scripture_scripts.dm
+++ b/code/game/gamemodes/clock_cult/clock_scriptures/scripture_scripts.dm
@@ -33,7 +33,7 @@
/datum/clockwork_scripture/create_object/cogscarab
descname = "Constructor Soul Vessel Shell"
name = "Cogscarab"
- desc = "Creates a small shell fitted for soul vessels. Adding an active soul vessel to it results in a small construct with tools and an inbuilt proselytizer."
+ desc = "Creates a small shell fitted for soul vessels. Adding an active soul vessel to it results in a small construct with tools and an inbuilt fabricator."
invocations = list("Call forth...", "...the workers of Armorer.")
channel_time = 60
consumed_components = list(BELLIGERENT_EYE = 2, HIEROPHANT_ANSIBLE = 1)
@@ -221,24 +221,24 @@
quickbind_desc = "Creates a Soul Vessel, which can be placed in construct shells and cyborg bodies once filled."
-//Clockwork Proselytizer: Creates a clockwork proselytizer, used to convert objects and repair clockwork structures.
-/datum/clockwork_scripture/create_object/clockwork_proselytizer
- descname = "Converts Objects to Ratvarian"
- name = "Clockwork Proselytizer"
- desc = "Forms a device that, when used on certain objects, converts them into their Ratvarian equivalents. It requires power to function."
+//Replica Fabricator: Creates a replica fabricator, used to convert objects and repair clockwork structures.
+/datum/clockwork_scripture/create_object/replica_fabricator
+ descname = "Replaces Objects with Ratvarian Versions"
+ name = "Replica Fabricator"
+ desc = "Forms a device that, when used on certain objects, replaces them with their Ratvarian equivalents. It requires power to function."
invocations = list("With this device...", "...his presence shall be made known.")
channel_time = 20
consumed_components = list(GEIS_CAPACITOR = 1, REPLICANT_ALLOY = 2)
whispered = TRUE
- object_path = /obj/item/clockwork/clockwork_proselytizer/preloaded
- creator_message = "You form a clockwork proselytizer."
- usage_tip = "Clockwork Walls cause nearby tinkerer's caches to generate components passively, making them a vital tool. Clockwork Floors heal toxin damage in Servants standing on them."
+ object_path = /obj/item/clockwork/replica_fabricator/preloaded
+ creator_message = "You form a replica fabricator."
+ usage_tip = "Clockwork Walls cause nearby Tinkerer's Caches to generate components passively, making this a vital tool. Clockwork Floors heal toxin damage in Servants standing on them."
tier = SCRIPTURE_SCRIPT
space_allowed = TRUE
primary_component = REPLICANT_ALLOY
sort_priority = 7
quickbind = TRUE
- quickbind_desc = "Creates a Clockwork Proselytizer, which can convert various objects to Ratvarian variants."
+ quickbind_desc = "Creates a Replica Fabricator, which can convert various objects to Ratvarian variants."
//Function Call: Grants the invoker the ability to call forth a Ratvarian spear that deals significant damage to silicons.
diff --git a/code/game/gamemodes/clock_cult/clock_structure.dm b/code/game/gamemodes/clock_cult/clock_structure.dm
index 64c7135971..5cbaa701fa 100644
--- a/code/game/gamemodes/clock_cult/clock_structure.dm
+++ b/code/game/gamemodes/clock_cult/clock_structure.dm
@@ -9,7 +9,7 @@
anchored = 1
density = 1
resistance_flags = FIRE_PROOF | ACID_PROOF
- var/can_be_repaired = TRUE //if a proselytizer can repair it
+ var/can_be_repaired = TRUE //if a fabricator can repair it
break_message = "The frog isn't a meme after all!" //The message shown when a structure breaks
break_sound = 'sound/magic/clockwork/anima_fragment_death.ogg' //The sound played when a structure breaks
debris = list(/obj/item/clockwork/alloy_shards/large = 1, \
diff --git a/code/game/gamemodes/clock_cult/clock_structures/clock_shells.dm b/code/game/gamemodes/clock_cult/clock_structures/clock_shells.dm
index cfcac3b515..e9f02e9e8c 100644
--- a/code/game/gamemodes/clock_cult/clock_structures/clock_shells.dm
+++ b/code/game/gamemodes/clock_cult/clock_structures/clock_shells.dm
@@ -34,7 +34,7 @@
/obj/structure/destructible/clockwork/shell/cogscarab
name = "cogscarab shell"
desc = "A small brass shell with a cube-shaped receptable in its center. It gives off an aura of obsessive perfectionism."
- clockwork_desc = "A dormant receptable that, when powered with a soul vessel, will become a weak construct with an inbuilt proselytizer."
+ clockwork_desc = "A dormant receptable that, when powered with a soul vessel, will become a weak construct with an inbuilt fabricator."
icon_state = "clockdrone_shell"
mobtype = /mob/living/simple_animal/drone/cogscarab
spawn_message = "'s eyes blink open, glowing bright red."
diff --git a/code/game/gamemodes/clock_cult/clock_structures/ratvar_the_clockwork_justicar.dm b/code/game/gamemodes/clock_cult/clock_structures/ratvar_the_clockwork_justicar.dm
index 25f151def5..722ff99c25 100644
--- a/code/game/gamemodes/clock_cult/clock_structures/ratvar_the_clockwork_justicar.dm
+++ b/code/game/gamemodes/clock_cult/clock_structures/ratvar_the_clockwork_justicar.dm
@@ -14,7 +14,7 @@
light_color = "#BE8700"
var/atom/prey //Whatever Ratvar is chasing
var/clashing = FALSE //If Ratvar is FUCKING FIGHTING WITH NAR-SIE
- var/proselytize_range = 10
+ var/convert_range = 10
dangerous_possession = TRUE
/obj/structure/destructible/clockwork/massive/ratvar/Initialize()
@@ -58,10 +58,10 @@
/obj/structure/destructible/clockwork/massive/ratvar/process()
if(clashing) //I'm a bit occupied right now, thanks
return
- for(var/I in circlerangeturfs(src, proselytize_range))
+ for(var/I in circlerangeturfs(src, convert_range))
var/turf/T = I
T.ratvar_act()
- for(var/I in circleviewturfs(src, round(proselytize_range * 0.5)))
+ for(var/I in circleviewturfs(src, round(convert_range * 0.5)))
var/turf/T = I
T.ratvar_act(TRUE)
var/dir_to_step_in = pick(GLOB.cardinal)
diff --git a/code/game/gamemodes/events.dm b/code/game/gamemodes/events.dm
index b44b6b58b6..2b3e945c1f 100644
--- a/code/game/gamemodes/events.dm
+++ b/code/game/gamemodes/events.dm
@@ -9,7 +9,7 @@
S.update_icon()
S.power_change()
- var/list/skipped_areas = list(/area/engine/engineering, /area/ai_monitored/turret_protected/ai)
+ var/list/skipped_areas = list(/area/engine/engineering, /area/engine/supermatter, /area/engine/atmospherics_engine, /area/ai_monitored/turret_protected/ai)
for(var/area/A in world)
if( !A.requires_power || A.always_unpowered )
diff --git a/code/game/gamemodes/gang/gang_items.dm b/code/game/gamemodes/gang/gang_items.dm
index 22b3758379..ddb0ca4608 100644
--- a/code/game/gamemodes/gang/gang_items.dm
+++ b/code/game/gamemodes/gang/gang_items.dm
@@ -250,7 +250,7 @@
name = "Black Market .50cal Sniper Rifle"
id = "sniper"
cost = 40
- item_path = /obj/item/weapon/gun/ballistic/automatic/sniper_rifle
+ item_path = /obj/item/weapon/gun/ballistic/automatic/sniper_rifle/gang
/datum/gang_item/weapon/ammo/sniper_ammo
name = "Smuggled .50cal Sniper Rounds"
diff --git a/code/game/gamemodes/wizard/spellbook.dm b/code/game/gamemodes/wizard/spellbook.dm
index 143d60be91..b55383a38d 100644
--- a/code/game/gamemodes/wizard/spellbook.dm
+++ b/code/game/gamemodes/wizard/spellbook.dm
@@ -106,10 +106,9 @@
name = "Fireball"
spell_type = /obj/effect/proc_holder/spell/aimed/fireball
-/*
/datum/spellbook_entry/rod_form
name = "Rod Form"
- spell_type = /obj/effect/proc_holder/spell/targeted/rod_form */
+ spell_type = /obj/effect/proc_holder/spell/targeted/rod_form
/datum/spellbook_entry/magicm
name = "Magic Missile"
diff --git a/code/game/machinery/cell_charger.dm b/code/game/machinery/cell_charger.dm
index 9f63391c86..8d17831a3b 100644
--- a/code/game/machinery/cell_charger.dm
+++ b/code/game/machinery/cell_charger.dm
@@ -71,7 +71,7 @@
/obj/machinery/cell_charger/proc/removecell()
- charging.updateicon()
+ charging.update_icon()
charging = null
chargelevel = -1
updateicon()
diff --git a/code/game/machinery/doors/door.dm b/code/game/machinery/doors/door.dm
index b71aeaca8d..aacb290d40 100644
--- a/code/game/machinery/doors/door.dm
+++ b/code/game/machinery/doors/door.dm
@@ -12,7 +12,7 @@
max_integrity = 350
armor = list(melee = 30, bullet = 30, laser = 20, energy = 20, bomb = 10, bio = 100, rad = 100, fire = 80, acid = 70)
CanAtmosPass = ATMOS_PASS_DENSITY
- flags = PREVENT_CLICK_UNDER
+ flags = PREVENT_CLICK_UNDER
var/secondsElectrified = 0
var/shockedby = list()
@@ -32,6 +32,7 @@
var/auto_close //TO BE REMOVED, no longer used, it's just preventing a runtime with a map var edit.
var/datum/effect_system/spark_spread/spark_system
var/damage_deflection = 10
+ var/real_explosion_block //ignore this, just use explosion_block
/obj/machinery/door/New()
..()
@@ -45,6 +46,10 @@
spark_system = new /datum/effect_system/spark_spread
spark_system.set_up(2, 1, src)
+ //doors only block while dense though so we have to use the proc
+ real_explosion_block = explosion_block
+ explosion_block = EXPLOSION_BLOCK_PROC
+
/obj/machinery/door/Destroy()
@@ -284,7 +289,7 @@
/obj/machinery/door/proc/crush()
for(var/mob/living/L in get_turf(src))
- L.visible_message("[src] closes on [L], crushing them!", "[src] closes on you and crushes you!")
+ L.visible_message("[src] closes on [L], crushing them!", "[src] closes on you and crushes you!")
if(isalien(L)) //For xenos
L.adjustBruteLoss(DOOR_CRUSH_DAMAGE * 1.5) //Xenos go into crit after aproximately the same amount of crushes as humans.
L.emote("roar")
@@ -346,3 +351,6 @@
//if it blows up a wall it should blow up a door
..(severity ? max(1, severity - 1) : 0, target)
+/obj/machinery/door/GetExplosionBlock()
+ return density ? real_explosion_block : 0
+
diff --git a/code/game/machinery/porta_turret/portable_turret.dm b/code/game/machinery/porta_turret/portable_turret.dm
index 4b2176c603..7f51b4290a 100644
--- a/code/game/machinery/porta_turret/portable_turret.dm
+++ b/code/game/machinery/porta_turret/portable_turret.dm
@@ -87,9 +87,9 @@
if(has_cover)
cover = new /obj/machinery/porta_turret_cover(loc)
cover.parent_turret = src
- var/mutable_appearance/base = mutable_appearance('icons/obj/turrets.dmi', "basedark")
- base.layer = NOT_HIGH_OBJ_LAYER
- underlays += base
+ var/mutable_appearance/base = mutable_appearance('icons/obj/turrets.dmi', "basedark")
+ base.layer = NOT_HIGH_OBJ_LAYER
+ underlays += base
if(!has_cover)
INVOKE_ASYNC(src, .proc/popUp)
@@ -554,7 +554,7 @@
use_power = 0
has_cover = 0
scan_range = 9
- req_access = list(GLOB.access_syndicate)
+ req_access = list(GLOB.access_syndicate)
stun_projectile = /obj/item/projectile/bullet
lethal_projectile = /obj/item/projectile/bullet
lethal_projectile_sound = 'sound/weapons/Gunshot.ogg'
@@ -571,8 +571,8 @@
return 10 //Syndicate turrets shoot everything not in their faction
/obj/machinery/porta_turret/syndicate/pod
- max_integrity = 40
- integrity_failure = 20
+ max_integrity = 40
+ integrity_failure = 20
obj_integrity = 40
stun_projectile = /obj/item/projectile/bullet/weakbullet3
lethal_projectile = /obj/item/projectile/bullet/weakbullet3
@@ -924,182 +924,4 @@
if(istype(P, /obj/item/projectile/beam/lasertag/bluetag))
on = 0
spawn(100)
- on = 1
-
-/////// MANNED TURRET ////////
-
-/obj/machinery/manned_turret
- name = "machine gun turret"
- desc = "While the trigger is held down, this gun will redistribute recoil to allow its user to easily shift targets."
- icon = 'icons/obj/turrets.dmi'
- icon_state = "machinegun"
- can_buckle = TRUE
- density = TRUE
- max_integrity = 100
- obj_integrity = 100
- buckle_lying = 0
- layer = ABOVE_MOB_LAYER
- var/view_range = 10
- var/cooldown = 0
- var/projectile_type = /obj/item/projectile/bullet/weakbullet3
- var/rate_of_fire = 1
- var/number_of_shots = 40
- var/cooldown_duration = 90
- var/atom/target
- var/turf/target_turf
- var/warned = FALSE
- var/mouseparams
-
-//BUCKLE HOOKS
-
-/obj/machinery/manned_turret/unbuckle_mob(mob/living/buckled_mob,force = 0)
- playsound(src,'sound/mecha/mechmove01.ogg', 50, 1)
- for(var/obj/item/I in buckled_mob.held_items)
- if(istype(I, /obj/item/gun_control))
- qdel(I)
- if(istype(buckled_mob))
- buckled_mob.pixel_x = 0
- buckled_mob.pixel_y = 0
- if(buckled_mob.client)
- buckled_mob.client.change_view(world.view)
- anchored = FALSE
- . = ..()
-
-/obj/machinery/manned_turret/user_buckle_mob(mob/living/M, mob/living/carbon/user)
- if(user.incapacitated() || !istype(user))
- return
- M.forceMove(get_turf(src))
- ..()
- for(var/V in M.held_items)
- var/obj/item/I = V
- if(istype(I))
- if(M.dropItemToGround(I))
- var/obj/item/gun_control/TC = new /obj/item/gun_control(src)
- M.put_in_hands(TC)
- else //Entries in the list should only ever be items or null, so if it's not an item, we can assume it's an empty hand
- var/obj/item/gun_control/TC = new /obj/item/gun_control(src)
- M.put_in_hands(TC)
- M.pixel_y = 14
- layer = ABOVE_MOB_LAYER
- setDir(SOUTH)
- playsound(src,'sound/mecha/mechmove01.ogg', 50, 1)
- anchored = TRUE
- if(user.client)
- user.client.change_view(view_range)
-
-/obj/item/gun_control
- name = "turret controls"
- icon = 'icons/obj/weapons.dmi'
- icon_state = "offhand"
- w_class = WEIGHT_CLASS_HUGE
- flags = ABSTRACT | NODROP | NOBLUDGEON
- resistance_flags = FIRE_PROOF | UNACIDABLE | ACID_PROOF
- var/obj/machinery/manned_turret/turret
-
-/obj/item/gun_control/New(obj/machinery/manned_turret/MT)
- if(MT)
- turret = MT
- else
- qdel(src)
-
-/obj/item/gun_control/CanItemAutoclick()
- return 1
-
-/obj/item/gun_control/attack_obj(obj/O, mob/living/user)
- user.changeNext_move(CLICK_CD_MELEE)
- O.attacked_by(src, user)
-
-/obj/item/gun_control/attack(mob/living/M, mob/living/user)
- user.lastattacked = M
- M.lastattacker = user
- M.attacked_by(src, user)
- add_fingerprint(user)
-
-/obj/item/gun_control/afterattack(atom/targeted_atom, mob/user, flag, params)
- ..()
- var/obj/machinery/manned_turret/E = user.buckled
- E.setDir(get_dir(E,targeted_atom))
- user.setDir(E.dir)
- E.mouseparams = params
- switch(E.dir)
- if(NORTH)
- E.layer = BELOW_MOB_LAYER
- user.pixel_x = 0
- user.pixel_y = -14
- if(NORTHEAST)
- E.layer = BELOW_MOB_LAYER
- user.pixel_x = -8
- user.pixel_y = -4
- if(EAST)
- E.layer = ABOVE_MOB_LAYER
- user.pixel_x = -14
- user.pixel_y = 0
- if(SOUTHEAST)
- E.layer = BELOW_MOB_LAYER
- user.pixel_x = -8
- user.pixel_y = 4
- if(SOUTH)
- E.layer = ABOVE_MOB_LAYER
- user.pixel_x = 0
- user.pixel_y = 14
- if(SOUTHWEST)
- E.layer = BELOW_MOB_LAYER
- user.pixel_x = 8
- user.pixel_y = 4
- if(WEST)
- E.layer = ABOVE_MOB_LAYER
- user.pixel_x = 14
- user.pixel_y = 0
- if(NORTHWEST)
- E.layer = BELOW_MOB_LAYER
- user.pixel_x = 8
- user.pixel_y = -4
- E.checkfire(targeted_atom, user)
-
-/obj/machinery/manned_turret/proc/checkfire(atom/targeted_atom, mob/user)
- target = targeted_atom
- if(target == user || target == get_turf(src))
- return
- if(world.time < cooldown)
- if(!warned && world.time > (cooldown - cooldown_duration + rate_of_fire*number_of_shots)) // To capture the window where one is done firing
- warned = TRUE
- playsound(src, 'sound/weapons/sear.ogg', 100, 1)
- return
- else
- cooldown = world.time + cooldown_duration
- warned = FALSE
- volley(user)
-
-/obj/machinery/manned_turret/proc/volley(mob/user)
- target_turf = get_turf(target)
- for(var/i in 1 to number_of_shots)
- addtimer(CALLBACK(src, /obj/machinery/manned_turret/.proc/fire_helper, user), i*rate_of_fire)
-
-
-/obj/machinery/manned_turret/proc/fire_helper(mob/user)
- if(!src)
- return
- var/turf/targets_from = get_turf(src)
- if(QDELETED(target))
- target = target_turf
- var/obj/item/projectile/P = new projectile_type(targets_from)
- P.current = targets_from
- P.starting = targets_from
- P.firer = user
- P.original = target
- playsound(src, 'sound/weapons/Gunshot_smg.ogg', 75, 1)
- P.preparePixelProjectile(target, target_turf, user, mouseparams, rand(-9, 9))
- P.fire()
-
-/obj/machinery/manned_turret/ultimate // Admin-only proof of concept for autoclicker automatics
- name = "Infinity Gun"
- view_range = 12
- projectile_type = /obj/item/projectile/bullet/weakbullet3
-
-
-/obj/machinery/manned_turret/ultimate/checkfire(atom/targeted_atom, mob/user)
- target = targeted_atom
- if(target == user || target == get_turf(src))
- return
- target_turf = get_turf(target)
- fire_helper(user)
+ on = 1
\ No newline at end of file
diff --git a/code/game/machinery/recharger.dm b/code/game/machinery/recharger.dm
index a081e3eb80..ff1887f699 100755
--- a/code/game/machinery/recharger.dm
+++ b/code/game/machinery/recharger.dm
@@ -61,7 +61,7 @@
G.loc = src
charging = G
use_power = 2
- update_icon(scan = TRUE)
+ update_icon(scan = TRUE)
else
to_chat(user, "[src] isn't connected to anything!")
return 1
@@ -108,41 +108,25 @@
var/using_power = 0
if(charging)
- if(istype(charging, /obj/item/weapon/gun/energy))
- var/obj/item/weapon/gun/energy/E = charging
- if(E.power_supply.charge < E.power_supply.maxcharge)
- E.power_supply.give(E.power_supply.chargerate * recharge_coeff)
- E.recharge_newshot()
+ var/obj/item/weapon/stock_parts/cell/C = charging.get_cell()
+ if(C)
+ if(C.charge < C.maxcharge)
+ C.give(C.chargerate * recharge_coeff)
use_power(250 * recharge_coeff)
using_power = 1
-
-
- if(istype(charging, /obj/item/weapon/melee/baton))
- var/obj/item/weapon/melee/baton/B = charging
- if(B.bcell)
- if(B.bcell.give(B.bcell.chargerate * recharge_coeff))
- use_power(200 * recharge_coeff)
- using_power = 1
-
+ update_icon(using_power)
+ if(istype(charging, /obj/item/weapon/gun/energy))
+ var/obj/item/weapon/gun/energy/E = charging
+ E.recharge_newshot()
+ return
if(istype(charging, /obj/item/ammo_box/magazine/recharge))
var/obj/item/ammo_box/magazine/recharge/R = charging
if(R.stored_ammo.len < R.max_ammo)
R.stored_ammo += new R.ammo_type(R)
use_power(200 * recharge_coeff)
using_power = 1
-
- if(istype(charging, /obj/item/device/modular_computer))
- var/obj/item/device/modular_computer/C = charging
- var/obj/item/weapon/computer_hardware/battery/battery_module = C.all_components[MC_CELL]
- if(battery_module)
- var/obj/item/weapon/computer_hardware/battery/B = battery_module
- if(B.battery)
- if(B.battery.charge < B.battery.maxcharge)
- B.battery.give(B.battery.chargerate * recharge_coeff)
- use_power(200 * recharge_coeff)
- using_power = 1
-
- update_icon(using_power)
+ update_icon(using_power)
+ return
/obj/machinery/recharger/power_change()
..()
@@ -152,23 +136,23 @@
if(!(stat & (NOPOWER|BROKEN)) && anchored)
if(istype(charging, /obj/item/weapon/gun/energy))
var/obj/item/weapon/gun/energy/E = charging
- if(E.power_supply)
- E.power_supply.emp_act(severity)
+ if(E.cell)
+ E.cell.emp_act(severity)
else if(istype(charging, /obj/item/weapon/melee/baton))
var/obj/item/weapon/melee/baton/B = charging
- if(B.bcell)
- B.bcell.charge = 0
+ if(B.cell)
+ B.cell.charge = 0
..()
-/obj/machinery/recharger/update_icon(using_power = 0, scan) //we have an update_icon() in addition to the stuff in process to make it feel a tiny bit snappier.
+/obj/machinery/recharger/update_icon(using_power = 0, scan) //we have an update_icon() in addition to the stuff in process to make it feel a tiny bit snappier.
if(stat & (NOPOWER|BROKEN) || !anchored)
icon_state = "rechargeroff"
return
- if(scan)
- icon_state = "rechargeroff"
- return
+ if(scan)
+ icon_state = "rechargeroff"
+ return
if(panel_open)
icon_state = "rechargeropen"
return
diff --git a/code/game/machinery/spaceheater.dm b/code/game/machinery/spaceheater.dm
index df76fef5a9..671dfbbdf2 100644
--- a/code/game/machinery/spaceheater.dm
+++ b/code/game/machinery/spaceheater.dm
@@ -24,6 +24,9 @@
var/settableTemperatureMedian = 30 + T0C
var/settableTemperatureRange = 30
+/obj/machinery/space_heater/get_cell()
+ return cell
+
/obj/machinery/space_heater/New()
..()
cell = new(src)
diff --git a/code/game/mecha/mecha.dm b/code/game/mecha/mecha.dm
index 1e6fd57b1d..c9be720d75 100644
--- a/code/game/mecha/mecha.dm
+++ b/code/game/mecha/mecha.dm
@@ -142,6 +142,9 @@
diag_hud_set_mechstat()
diag_hud_set_mechtracking()
+/obj/mecha/get_cell()
+ return cell
+
/obj/mecha/Destroy()
go_out()
@@ -154,7 +157,7 @@
M.forceMove(loc)
if(prob(30))
- explosion(get_turf(loc), 0, 0, 1, 3)
+ explosion(get_turf(loc), 0, 0, 1, 3)
if(wreckage)
var/obj/structure/mecha_wreckage/WR = new wreckage(loc, AI)
diff --git a/code/game/objects/items/weapons/defib.dm b/code/game/objects/items/weapons/defib.dm
index 886d875edc..d616f4aaa4 100644
--- a/code/game/objects/items/weapons/defib.dm
+++ b/code/game/objects/items/weapons/defib.dm
@@ -19,7 +19,7 @@
var/safety = 1 //if you can zap people with the defibs on harm mode
var/powered = 0 //if there's a cell in the defib with enough power for a revive, blocks paddles from reviving otherwise
var/obj/item/weapon/twohanded/shockpaddles/paddles
- var/obj/item/weapon/stock_parts/cell/high/bcell = null
+ var/obj/item/weapon/stock_parts/cell/high/cell
var/combat = 0 //can we revive through space suits?
var/grab_ghost = FALSE // Do we pull the ghost back into their body?
@@ -29,10 +29,13 @@
update_icon()
return
+/obj/item/weapon/defibrillator/get_cell()
+ return cell
+
/obj/item/weapon/defibrillator/loaded/Initialize() //starts with hicap
. = ..()
paddles = make_paddles()
- bcell = new(src)
+ cell = new(src)
update_icon()
return
@@ -42,8 +45,8 @@
update_charge()
/obj/item/weapon/defibrillator/proc/update_power()
- if(bcell)
- if(bcell.charge < paddles.revivecost)
+ if(cell)
+ if(cell.charge < paddles.revivecost)
powered = 0
else
powered = 1
@@ -56,21 +59,21 @@
add_overlay("[initial(icon_state)]-paddles")
if(powered)
add_overlay("[initial(icon_state)]-powered")
- if(!bcell)
+ if(!cell)
add_overlay("[initial(icon_state)]-nocell")
if(!safety)
add_overlay("[initial(icon_state)]-emagged")
/obj/item/weapon/defibrillator/proc/update_charge()
if(powered) //so it doesn't show charge if it's unpowered
- if(bcell)
- var/ratio = bcell.charge / bcell.maxcharge
+ if(cell)
+ var/ratio = cell.charge / cell.maxcharge
ratio = Ceiling(ratio*4) * 25
add_overlay("[initial(icon_state)]-charge[ratio]")
/obj/item/weapon/defibrillator/CheckParts(list/parts_list)
..()
- bcell = locate(/obj/item/weapon/stock_parts/cell) in contents
+ cell = locate(/obj/item/weapon/stock_parts/cell) in contents
update_icon()
/obj/item/weapon/defibrillator/ui_action_click()
@@ -105,7 +108,7 @@
toggle_paddles()
else if(istype(W, /obj/item/weapon/stock_parts/cell))
var/obj/item/weapon/stock_parts/cell/C = W
- if(bcell)
+ if(cell)
to_chat(user, "[src] already has a cell.")
else
if(C.maxcharge < paddles.revivecost)
@@ -113,15 +116,15 @@
return
if(!user.transferItemToLoc(W, src))
return
- bcell = W
+ cell = W
to_chat(user, "You install a cell in [src].")
update_icon()
else if(istype(W, /obj/item/weapon/screwdriver))
- if(bcell)
- bcell.updateicon()
- bcell.loc = get_turf(src.loc)
- bcell = null
+ if(cell)
+ cell.update_icon()
+ cell.loc = get_turf(src.loc)
+ cell = null
to_chat(user, "You remove the cell from [src].")
update_icon()
else
@@ -136,7 +139,7 @@
to_chat(user, "You silently enable [src]'s safety protocols with the cryptographic sequencer.")
/obj/item/weapon/defibrillator/emp_act(severity)
- if(bcell)
+ if(cell)
deductcharge(1000 / severity)
if(safety)
safety = 0
@@ -200,11 +203,11 @@
update_icon()
/obj/item/weapon/defibrillator/proc/deductcharge(chrgdeductamt)
- if(bcell)
- if(bcell.charge < (paddles.revivecost+chrgdeductamt))
+ if(cell)
+ if(cell.charge < (paddles.revivecost+chrgdeductamt))
powered = 0
update_icon()
- if(bcell.use(chrgdeductamt))
+ if(cell.use(chrgdeductamt))
update_icon()
return 1
else
@@ -213,8 +216,8 @@
/obj/item/weapon/defibrillator/proc/cooldowncheck(mob/user)
spawn(50)
- if(bcell)
- if(bcell.charge >= paddles.revivecost)
+ if(cell)
+ if(cell.charge >= paddles.revivecost)
user.visible_message("[src] beeps: Unit ready.")
playsound(get_turf(src), 'sound/machines/defib_ready.ogg', 50, 0)
else
@@ -240,7 +243,7 @@
/obj/item/weapon/defibrillator/compact/loaded/Initialize()
. = ..()
paddles = make_paddles()
- bcell = new(src)
+ cell = new(src)
update_icon()
/obj/item/weapon/defibrillator/compact/combat
@@ -252,7 +255,7 @@
/obj/item/weapon/defibrillator/compact/combat/loaded/Initialize()
. = ..()
paddles = make_paddles()
- bcell = new /obj/item/weapon/stock_parts/cell/infinite(src)
+ cell = new /obj/item/weapon/stock_parts/cell/infinite(src)
update_icon()
/obj/item/weapon/defibrillator/compact/combat/loaded/attackby(obj/item/weapon/W, mob/user, params)
diff --git a/code/game/objects/items/weapons/inducer.dm b/code/game/objects/items/weapons/inducer.dm
new file mode 100644
index 0000000000..fdd44795ad
--- /dev/null
+++ b/code/game/objects/items/weapons/inducer.dm
@@ -0,0 +1,183 @@
+/obj/item/weapon/inducer
+ name = "inducer"
+ desc = "A tool for inductively charging internal power cells."
+ icon = 'icons/obj/tools.dmi'
+ icon_state = "inducer-engi"
+ item_state = "inducer-engi"
+ origin_tech = "engineering=4;magnets=4;powerstorage=4"
+ force = 7
+ var/powertransfer = 1000
+ var/opened = FALSE
+ var/cell_type = /obj/item/weapon/stock_parts/cell/high
+ var/obj/item/weapon/stock_parts/cell/cell
+ var/recharging = FALSE
+
+/obj/item/weapon/inducer/Initialize()
+ . = ..()
+ if(!cell && cell_type)
+ cell = new cell_type
+
+/obj/item/weapon/inducer/proc/induce(obj/item/weapon/stock_parts/cell/target, coefficient)
+ var/totransfer = min(cell.charge,(powertransfer * coefficient))
+ var/transferred = target.give(totransfer)
+ cell.use(transferred)
+ cell.update_icon()
+ target.update_icon()
+
+/obj/item/weapon/inducer/get_cell()
+ return cell
+
+/obj/item/weapon/inducer/emp_act(severity)
+ ..()
+ if(cell)
+ cell.emp_act()
+
+/obj/item/weapon/inducer/attack_obj(obj/O, mob/living/carbon/user)
+ if(user.a_intent == INTENT_HARM)
+ return ..()
+
+ if(cantbeused(user))
+ return
+
+ if(recharge(O, user))
+ return
+
+ return ..()
+
+/obj/item/weapon/inducer/proc/cantbeused(mob/user)
+ if(!user.IsAdvancedToolUser())
+ to_chat(user, "You don't have the dexterity to use \the [src]!")
+ return TRUE
+
+ if(!cell)
+ to_chat(user, "\The [src] doesn't have a power cell installed!")
+ return TRUE
+
+ if(!cell.charge)
+ to_chat(user, "\The [src]'s battery is dead!")
+ return TRUE
+ return FALSE
+
+
+/obj/item/weapon/inducer/attackby(obj/item/weapon/W, mob/user)
+ if(istype(W,/obj/item/weapon/screwdriver))
+ playsound(src, W.usesound, 50, 1)
+ if(!opened)
+ to_chat(user, "You unscrew the battery compartment.")
+ opened = TRUE
+ update_icon()
+ return
+ else
+ to_chat(user, "You close the battery compartment.")
+ opened = FALSE
+ update_icon()
+ return
+ if(istype(W,/obj/item/weapon/stock_parts/cell))
+ if(opened)
+ if(!cell)
+ if(!user.transferItemToLoc(W, src))
+ return
+ to_chat(user, "You insert \the [W] into \the [src].")
+ cell = W
+ update_icon()
+ return
+ else
+ to_chat(user, "\The [src] already has \a [cell] installed!")
+ return
+
+ if(cantbeused(user))
+ return
+
+ if(recharge(W, user))
+ return
+
+ return ..()
+
+/obj/item/weapon/inducer/proc/recharge(atom/movable/A, mob/user)
+ if(recharging)
+ return TRUE
+ else
+ recharging = TRUE
+ var/obj/item/weapon/stock_parts/cell/C = A.get_cell()
+ var/obj/item/weapon/gun/energy/E
+ var/obj/O
+ var/coefficient = 1
+ if(istype(A, /obj/item/weapon/gun/energy))
+ coefficient = 0.075 // 14 loops to recharge an egun from 0-1000
+ E = A
+ if(istype(A, /obj))
+ O = A
+ if(C)
+ if(C.charge >= C.maxcharge)
+ to_chat(user, "\The [A] is fully charged!")
+ recharging = FALSE
+ return TRUE
+ user.visible_message("[user] starts recharging \the [A] with \the [src]","You start recharging [A] with \the [src]")
+ while(C.charge < C.maxcharge)
+ if(E)
+ E.chambered = null // Prevents someone from firing continuously while recharging the gun.
+ if(do_after(user, 10, target = user) && cell.charge)
+ induce(C, coefficient)
+ do_sparks(1, FALSE, A)
+ if(O)
+ O.update_icon()
+ else
+ break
+ if(E)
+ E.recharge_newshot() //We're done charging, so we'll let someone fire it now.
+ user.visible_message("[user] recharged \the [A]!","You recharged \the [A]!")
+ recharging = FALSE
+ return TRUE
+
+
+/obj/item/weapon/inducer/attack(mob/M, mob/user)
+ if(user.a_intent == INTENT_HARM)
+ return ..()
+
+ if(cantbeused(user))
+ return
+
+ if(recharge(M, user))
+ return
+ return ..()
+
+
+/obj/item/weapon/inducer/attack_self(mob/user)
+ if(opened && cell)
+ user.visible_message("[user] removes \the [cell] from \the [src]!","You remove \the [cell].")
+ cell.update_icon()
+ user.put_in_hands(cell)
+ cell = null
+ update_icon()
+
+
+/obj/item/weapon/inducer/examine(mob/living/M)
+ ..()
+ if(cell)
+ to_chat(M, "It's display shows: [cell.charge]W")
+ else
+ to_chat(M,"It's display is dark.")
+ if(opened)
+ to_chat(M,"It's battery compartment is open.")
+
+/obj/item/weapon/inducer/update_icon()
+ cut_overlays()
+ if(opened)
+ if(!cell)
+ add_overlay("inducer-nobat")
+ else
+ add_overlay("inducer-bat")
+
+/obj/item/weapon/inducer/sci
+ icon_state = "inducer-sci"
+ item_state = "inducer-sci"
+ desc = "A tool for inductively charging internal power cells. This one has a science color scheme, and is less potent than it's engineering counterpart."
+ cell_type = null
+ powertransfer = 500
+ opened = TRUE
+
+/obj/item/weapon/inducer/sci/Initialize()
+ . = ..()
+ update_icon()
+
+
diff --git a/code/game/objects/items/weapons/storage/toolbox.dm b/code/game/objects/items/weapons/storage/toolbox.dm
index d90c42fe4a..31f52a42fc 100644
--- a/code/game/objects/items/weapons/storage/toolbox.dm
+++ b/code/game/objects/items/weapons/storage/toolbox.dm
@@ -21,15 +21,15 @@
if(has_latches)
if(prob(10))
latches = "double_latch"
- if(prob(1))
- latches = "triple_latch"
+ if(prob(1))
+ latches = "triple_latch"
update_icon()
/obj/item/weapon/storage/toolbox/update_icon()
..()
cut_overlays()
if(has_latches)
- add_overlay(latches)
+ add_overlay(latches)
/obj/item/weapon/storage/toolbox/suicide_act(mob/user)
@@ -140,10 +140,10 @@
max_combined_w_class = 28
storage_slots = 28
attack_verb = list("robusted", "crushed", "smashed")
- var/proselytizer_type = /obj/item/clockwork/clockwork_proselytizer/scarab
+ var/fabricator_type = /obj/item/clockwork/replica_fabricator/scarab
/obj/item/weapon/storage/toolbox/brass/prefilled/PopulateContents()
- new proselytizer_type(src)
+ new fabricator_type(src)
new /obj/item/weapon/screwdriver/brass(src)
new /obj/item/weapon/wirecutters/brass(src)
new /obj/item/weapon/wrench/brass(src)
@@ -151,7 +151,7 @@
new /obj/item/weapon/weldingtool/experimental/brass(src)
/obj/item/weapon/storage/toolbox/brass/prefilled/ratvar
- var/slab_type = /obj/item/clockwork/slab
+ var/slab_type = /obj/item/clockwork/slab
/obj/item/weapon/storage/toolbox/brass/prefilled/ratvar/PopulateContents()
..()
@@ -159,7 +159,7 @@
/obj/item/weapon/storage/toolbox/brass/prefilled/ratvar/admin
slab_type = /obj/item/clockwork/slab/debug
- proselytizer_type = /obj/item/clockwork/clockwork_proselytizer/scarab/debug
+ fabricator_type = /obj/item/clockwork/replica_fabricator/scarab/debug
/obj/item/weapon/storage/toolbox/artistic
diff --git a/code/game/objects/items/weapons/stunbaton.dm b/code/game/objects/items/weapons/stunbaton.dm
index c1b932d1bc..390357047a 100644
--- a/code/game/objects/items/weapons/stunbaton.dm
+++ b/code/game/objects/items/weapons/stunbaton.dm
@@ -13,7 +13,7 @@
var/stunforce = 7
var/status = 0
- var/obj/item/weapon/stock_parts/cell/high/bcell = null
+ var/obj/item/weapon/stock_parts/cell/high/cell = null
var/hitcost = 1000
var/throw_hit_chance = 35
@@ -21,8 +21,8 @@
user.visible_message("[user] is putting the live [name] in [user.p_their()] mouth! It looks like [user.p_theyre()] trying to commit suicide!")
return (FIRELOSS)
-/obj/item/weapon/melee/baton/Initialize()
- . = ..()
+/obj/item/weapon/melee/baton/Initialize()
+ . = ..()
update_icon()
/obj/item/weapon/melee/baton/throw_impact(atom/hit_atom)
@@ -31,16 +31,16 @@
if(status && prob(throw_hit_chance) && iscarbon(hit_atom))
baton_stun(hit_atom)
-/obj/item/weapon/melee/baton/loaded/Initialize() //this one starts with a cell pre-installed.
- bcell = new(src)
- . = ..()
+/obj/item/weapon/melee/baton/loaded/Initialize() //this one starts with a cell pre-installed.
+ cell = new(src)
+ . = ..()
/obj/item/weapon/melee/baton/proc/deductcharge(chrgdeductamt)
- if(bcell)
+ if(cell)
//Note this value returned is significant, as it will determine
//if a stun is applied or not
- . = bcell.use(chrgdeductamt)
- if(status && bcell.charge < hitcost)
+ . = cell.use(chrgdeductamt)
+ if(status && cell.charge < hitcost)
//we're below minimum, turn off
status = 0
update_icon()
@@ -50,22 +50,22 @@
/obj/item/weapon/melee/baton/update_icon()
if(status)
icon_state = "[initial(name)]_active"
- else if(!bcell)
+ else if(!cell)
icon_state = "[initial(name)]_nocell"
else
icon_state = "[initial(name)]"
/obj/item/weapon/melee/baton/examine(mob/user)
..()
- if(bcell)
- to_chat(user, "The baton is [round(bcell.percent())]% charged.")
+ if(cell)
+ to_chat(user, "The baton is [round(cell.percent())]% charged.")
else
- to_chat(user, "The baton does not have a power source installed.")
+ to_chat(user, "The baton does not have a power source installed.")
/obj/item/weapon/melee/baton/attackby(obj/item/weapon/W, mob/user, params)
if(istype(W, /obj/item/weapon/stock_parts/cell))
var/obj/item/weapon/stock_parts/cell/C = W
- if(bcell)
+ if(cell)
to_chat(user, "[src] already has a cell.")
else
if(C.maxcharge < hitcost)
@@ -73,15 +73,15 @@
return
if(!user.transferItemToLoc(W, src))
return
- bcell = W
+ cell = W
to_chat(user, "You install a cell in [src].")
update_icon()
else if(istype(W, /obj/item/weapon/screwdriver))
- if(bcell)
- bcell.updateicon()
- bcell.loc = get_turf(src.loc)
- bcell = null
+ if(cell)
+ cell.update_icon()
+ cell.forceMove(get_turf(src))
+ cell = null
to_chat(user, "You remove the cell from [src].")
status = 0
update_icon()
@@ -89,13 +89,13 @@
return ..()
/obj/item/weapon/melee/baton/attack_self(mob/user)
- if(bcell && bcell.charge > hitcost)
+ if(cell && cell.charge > hitcost)
status = !status
to_chat(user, "[src] is now [status ? "on" : "off"].")
playsound(loc, "sparks", 75, 1, -1)
else
status = 0
- if(!bcell)
+ if(!cell)
to_chat(user, "[src] does not have a power source!")
else
to_chat(user, "[src] is out of charge.")
@@ -186,8 +186,8 @@
slot_flags = SLOT_BACK
var/obj/item/device/assembly/igniter/sparkler = 0
-/obj/item/weapon/melee/baton/cattleprod/Initialize()
- . = ..()
+/obj/item/weapon/melee/baton/cattleprod/Initialize()
+ . = ..()
sparkler = new (src)
/obj/item/weapon/melee/baton/cattleprod/baton_stun()
diff --git a/code/game/objects/items/weapons/teleprod.dm b/code/game/objects/items/weapons/teleprod.dm
index 07af7a30c4..d14788e0b1 100644
--- a/code/game/objects/items/weapons/teleprod.dm
+++ b/code/game/objects/items/weapons/teleprod.dm
@@ -28,7 +28,7 @@
/obj/item/weapon/melee/baton/cattleprod/attackby(obj/item/I, mob/user, params)//handles sticking a crystal onto a stunprod to make a teleprod
if(istype(I, /obj/item/weapon/ore/bluespace_crystal))
- if(!bcell)
+ if(!cell)
var/obj/item/weapon/melee/baton/cattleprod/teleprod/S = new /obj/item/weapon/melee/baton/cattleprod/teleprod
remove_item_from_storage(user)
qdel(src)
diff --git a/code/game/objects/obj_defense.dm b/code/game/objects/obj_defense.dm
index 44281fb26f..747fb1b741 100644
--- a/code/game/objects/obj_defense.dm
+++ b/code/game/objects/obj_defense.dm
@@ -259,3 +259,7 @@ GLOBAL_DATUM_INIT(acid_overlay, /mutable_appearance, mutable_appearance('icons/e
obj_break(damage_type)
return TRUE
return FALSE
+
+//returns how much the object blocks an explosion
+/obj/proc/GetExplosionBlock()
+ CRASH("Unimplemented GetExplosionBlock()")
\ No newline at end of file
diff --git a/code/game/objects/objs.dm b/code/game/objects/objs.dm
index 7482b4ca14..9a7376c9eb 100644
--- a/code/game/objects/objs.dm
+++ b/code/game/objects/objs.dm
@@ -23,7 +23,7 @@
var/persistence_replacement //have something WAY too amazing to live to the next round? Set a new path here. Overuse of this var will make me upset.
var/unique_rename = FALSE // can you customize the description/name of the thing?
-
+
var/dangerous_possession = FALSE //Admin possession yes/no
/obj/vv_edit_var(vname, vval)
@@ -37,7 +37,7 @@
..()
/obj/Initialize()
- . = ..()
+ . = ..()
if (!armor)
armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 0, acid = 0)
if(on_blueprints && isturf(loc))
@@ -182,7 +182,10 @@
/obj/proc/check_uplink_validity()
return 1
-/obj/proc/on_mob_move(dir, mob)
+/obj/proc/on_mob_move(dir, mob, oldLoc)
+ return
+
+/obj/proc/on_mob_turn(dir, mob)
return
/obj/vv_get_dropdown()
@@ -193,6 +196,6 @@
..()
if(unique_rename)
to_chat(user, "Use a pen on it to rename it or change its description.")
-
-/obj/proc/gang_contraband_value()
- return 0
+
+/obj/proc/gang_contraband_value()
+ return 0
diff --git a/code/game/objects/structures/crates_lockers/closets/secure/engineering.dm b/code/game/objects/structures/crates_lockers/closets/secure/engineering.dm
index f1c30a0bfb..89273de04e 100644
--- a/code/game/objects/structures/crates_lockers/closets/secure/engineering.dm
+++ b/code/game/objects/structures/crates_lockers/closets/secure/engineering.dm
@@ -26,6 +26,7 @@
new /obj/item/clothing/glasses/meson/engine(src)
new /obj/item/weapon/door_remote/chief_engineer(src)
new /obj/item/weapon/pipe_dispenser(src)
+ new /obj/item/weapon/inducer(src)
/obj/structure/closet/secure_closet/engineering_electrical
name = "electrical supplies locker"
@@ -37,6 +38,8 @@
..()
new /obj/item/clothing/gloves/color/yellow(src)
new /obj/item/clothing/gloves/color/yellow(src)
+ new /obj/item/weapon/inducer(src)
+ new /obj/item/weapon/inducer(src)
for(var/i in 1 to 3)
new /obj/item/weapon/storage/toolbox/electrical(src)
for(var/i in 1 to 3)
diff --git a/code/game/objects/structures/crates_lockers/closets/secure/security.dm b/code/game/objects/structures/crates_lockers/closets/secure/security.dm
index 4934636948..c51c543f26 100644
--- a/code/game/objects/structures/crates_lockers/closets/secure/security.dm
+++ b/code/game/objects/structures/crates_lockers/closets/secure/security.dm
@@ -84,6 +84,7 @@
new /obj/item/device/flashlight/seclite(src)
new /obj/item/weapon/pinpointer(src)
new /obj/item/clothing/under/rank/head_of_security/grey(src)
+ new /obj/item/clothing/under/rank/head_of_security/grey(src)
new /obj/item/weapon/storage/lockbox/secmedal(src)
/obj/structure/closet/secure_closet/warden
diff --git a/code/game/objects/structures/grille.dm b/code/game/objects/structures/grille.dm
index 64d93e914e..4b912923a2 100644
--- a/code/game/objects/structures/grille.dm
+++ b/code/game/objects/structures/grille.dm
@@ -248,6 +248,7 @@
/obj/structure/grille/ratvar
icon_state = "ratvargrille"
+ name = "cog grille"
desc = "A strangely-shaped grille."
broken_type = /obj/structure/grille/ratvar/broken
diff --git a/code/game/objects/structures/lattice.dm b/code/game/objects/structures/lattice.dm
index 2f6b03bef1..4b2017fab6 100644
--- a/code/game/objects/structures/lattice.dm
+++ b/code/game/objects/structures/lattice.dm
@@ -50,7 +50,7 @@
deconstruct()
/obj/structure/lattice/clockwork
- name = "clockwork lattice"
+ name = "cog lattice"
desc = "A lightweight support lattice. These hold the Justicar's station together."
icon = 'icons/obj/smooth_structures/lattice_clockwork.dmi'
diff --git a/code/game/objects/structures/manned_turret.dm b/code/game/objects/structures/manned_turret.dm
new file mode 100644
index 0000000000..f2f767f4e6
--- /dev/null
+++ b/code/game/objects/structures/manned_turret.dm
@@ -0,0 +1,209 @@
+/////// MANNED TURRET ////////
+
+/obj/machinery/manned_turret
+ name = "machine gun turret"
+ desc = "While the trigger is held down, this gun will redistribute recoil to allow its user to easily shift targets."
+ icon = 'icons/obj/turrets.dmi'
+ icon_state = "machinegun"
+ can_buckle = TRUE
+ density = TRUE
+ max_integrity = 100
+ obj_integrity = 100
+ buckle_lying = FALSE
+ layer = ABOVE_MOB_LAYER
+ var/view_range = 10
+ var/cooldown = 0
+ var/projectile_type = /obj/item/projectile/bullet/weakbullet3
+ var/rate_of_fire = 1
+ var/number_of_shots = 40
+ var/cooldown_duration = 90
+ var/atom/target
+ var/turf/target_turf
+ var/warned = FALSE
+ var/list/calculated_projectile_vars
+
+/obj/machinery/manned_turret/Destroy()
+ target = null
+ target_turf = null
+ ..()
+
+//BUCKLE HOOKS
+
+/obj/machinery/manned_turret/unbuckle_mob(mob/living/buckled_mob,force = FALSE)
+ playsound(src,'sound/mecha/mechmove01.ogg', 50, 1)
+ for(var/obj/item/I in buckled_mob.held_items)
+ if(istype(I, /obj/item/gun_control))
+ qdel(I)
+ if(istype(buckled_mob))
+ buckled_mob.pixel_x = 0
+ buckled_mob.pixel_y = 0
+ if(buckled_mob.client)
+ buckled_mob.reset_perspective()
+ anchored = FALSE
+ . = ..()
+ STOP_PROCESSING(SSfastprocess, src)
+
+/obj/machinery/manned_turret/user_buckle_mob(mob/living/M, mob/living/carbon/user)
+ if(user.incapacitated() || !istype(user))
+ return
+ M.forceMove(get_turf(src))
+ ..()
+ for(var/V in M.held_items)
+ var/obj/item/I = V
+ if(istype(I))
+ if(M.dropItemToGround(I))
+ var/obj/item/gun_control/TC = new(src)
+ M.put_in_hands(TC)
+ else //Entries in the list should only ever be items or null, so if it's not an item, we can assume it's an empty hand
+ var/obj/item/gun_control/TC = new(src)
+ M.put_in_hands(TC)
+ M.pixel_y = 14
+ layer = ABOVE_MOB_LAYER
+ setDir(SOUTH)
+ playsound(src,'sound/mecha/mechmove01.ogg', 50, 1)
+ anchored = TRUE
+ if(user.client)
+ user.client.change_view(view_range)
+ START_PROCESSING(SSfastprocess, src)
+
+/obj/machinery/manned_turret/process()
+ if(!LAZYLEN(buckled_mobs))
+ return PROCESS_KILL
+ update_positioning()
+
+/obj/machinery/manned_turret/proc/update_positioning()
+ var/mob/living/controller = buckled_mobs[1]
+ if(!istype(controller))
+ return
+ var/client/C = controller.client
+ if(C)
+ var/atom/A = C.mouseObject
+ var/turf/T = get_turf(A)
+ if(istype(T)) //They're hovering over something in the map.
+ direction_track(controller, T)
+ calculated_projectile_vars = calculate_projectile_angle_and_pixel_offsets(controller, C.mouseParams)
+
+/obj/machinery/manned_turret/proc/direction_track(mob/user, atom/targeted)
+ setDir(get_dir(src,targeted))
+ user.setDir(dir)
+ switch(dir)
+ if(NORTH)
+ layer = BELOW_MOB_LAYER
+ user.pixel_x = 0
+ user.pixel_y = -14
+ if(NORTHEAST)
+ layer = BELOW_MOB_LAYER
+ user.pixel_x = -8
+ user.pixel_y = -4
+ if(EAST)
+ layer = ABOVE_MOB_LAYER
+ user.pixel_x = -14
+ user.pixel_y = 0
+ if(SOUTHEAST)
+ layer = BELOW_MOB_LAYER
+ user.pixel_x = -8
+ user.pixel_y = 4
+ if(SOUTH)
+ layer = ABOVE_MOB_LAYER
+ user.pixel_x = 0
+ user.pixel_y = 14
+ if(SOUTHWEST)
+ layer = BELOW_MOB_LAYER
+ user.pixel_x = 8
+ user.pixel_y = 4
+ if(WEST)
+ layer = ABOVE_MOB_LAYER
+ user.pixel_x = 14
+ user.pixel_y = 0
+ if(NORTHWEST)
+ layer = BELOW_MOB_LAYER
+ user.pixel_x = 8
+ user.pixel_y = -4
+
+/obj/machinery/manned_turret/proc/checkfire(atom/targeted_atom, mob/user)
+ target = targeted_atom
+ if(target == user || target == get_turf(src))
+ return
+ if(world.time < cooldown)
+ if(!warned && world.time > (cooldown - cooldown_duration + rate_of_fire*number_of_shots)) // To capture the window where one is done firing
+ warned = TRUE
+ playsound(src, 'sound/weapons/sear.ogg', 100, 1)
+ return
+ else
+ cooldown = world.time + cooldown_duration
+ warned = FALSE
+ volley(user)
+
+/obj/machinery/manned_turret/proc/volley(mob/user)
+ target_turf = get_turf(target)
+ for(var/i in 1 to number_of_shots)
+ addtimer(CALLBACK(src, /obj/machinery/manned_turret/.proc/fire_helper, user), i*rate_of_fire)
+
+/obj/machinery/manned_turret/proc/fire_helper(mob/user)
+ update_positioning() //REFRESH MOUSE TRACKING!!
+ var/turf/targets_from = get_turf(src)
+ if(QDELETED(target))
+ target = target_turf
+ var/obj/item/projectile/P = new projectile_type(targets_from)
+ P.current = targets_from
+ P.starting = targets_from
+ P.firer = user
+ P.original = target
+ playsound(src, 'sound/weapons/Gunshot_smg.ogg', 75, 1)
+ P.xo = target.x - targets_from.x
+ P.yo = target.y - targets_from.y
+ P.Angle = calculated_projectile_vars[1] + rand(-9, 9)
+ P.p_x = calculated_projectile_vars[2]
+ P.p_y = calculated_projectile_vars[3]
+ P.fire()
+
+/obj/machinery/manned_turret/ultimate // Admin-only proof of concept for autoclicker automatics
+ name = "Infinity Gun"
+ view_range = 12
+ projectile_type = /obj/item/projectile/bullet/weakbullet3
+
+/obj/machinery/manned_turret/ultimate/checkfire(atom/targeted_atom, mob/user)
+ target = targeted_atom
+ if(target == user || target == get_turf(src))
+ return
+ target_turf = get_turf(target)
+ fire_helper(user)
+
+/obj/item/gun_control
+ name = "turret controls"
+ icon = 'icons/obj/weapons.dmi'
+ icon_state = "offhand"
+ w_class = WEIGHT_CLASS_HUGE
+ flags = ABSTRACT | NODROP | NOBLUDGEON
+ resistance_flags = FIRE_PROOF | UNACIDABLE | ACID_PROOF
+ var/obj/machinery/manned_turret/turret
+
+/obj/item/gun_control/Initialize()
+ . = ..()
+ turret = loc
+ if(!istype(turret))
+ return INITIALIZE_HINT_QDEL
+
+/obj/item/gun_control/Destroy()
+ turret = null
+ ..()
+
+/obj/item/gun_control/CanItemAutoclick()
+ return TRUE
+
+/obj/item/gun_control/attack_obj(obj/O, mob/living/user)
+ user.changeNext_move(CLICK_CD_MELEE)
+ O.attacked_by(src, user)
+
+/obj/item/gun_control/attack(mob/living/M, mob/living/user)
+ user.lastattacked = M
+ M.lastattacker = user
+ M.attacked_by(src, user)
+ add_fingerprint(user)
+
+/obj/item/gun_control/afterattack(atom/targeted_atom, mob/user, flag, params)
+ ..()
+ var/obj/machinery/manned_turret/E = user.buckled
+ E.calculated_projectile_vars = calculate_projectile_angle_and_pixel_offsets(user, params)
+ E.direction_track(user, targeted_atom)
+ E.checkfire(targeted_atom, user)
diff --git a/code/game/objects/structures/tables_racks.dm b/code/game/objects/structures/tables_racks.dm
index 73c75e2cc5..febf5ab3af 100644
--- a/code/game/objects/structures/tables_racks.dm
+++ b/code/game/objects/structures/tables_racks.dm
@@ -195,7 +195,7 @@
check_break(M)
/obj/structure/table/glass/proc/check_break(mob/living/M)
- if(M.has_gravity() && M.mob_size > MOB_SIZE_SMALL)
+ if(M.has_gravity() && M.mob_size > MOB_SIZE_SMALL && !M.movement_type & FLYING)
table_shatter(M)
/obj/structure/table/glass/proc/table_shatter(mob/M)
@@ -271,20 +271,20 @@
frame = /obj/structure/table_frame
framestack = /obj/item/stack/rods
buildstack = /obj/item/stack/tile/carpet
- canSmoothWith = list(/obj/structure/table/wood/fancy,/obj/structure/table/wood/fancy/black)
+ canSmoothWith = list(/obj/structure/table/wood/fancy,/obj/structure/table/wood/fancy/black)
/obj/structure/table/wood/fancy/New()
icon = 'icons/obj/smooth_structures/fancy_table.dmi' //so that the tables place correctly in the map editor
..()
-/obj/structure/table/wood/fancy/black
- icon_state = "fancy_table_black"
- buildstack = /obj/item/stack/tile/carpet/black
-
-/obj/structure/table/wood/fancy/black/New()
- ..()
- icon = 'icons/obj/smooth_structures/fancy_table_black.dmi'
-
+/obj/structure/table/wood/fancy/black
+ icon_state = "fancy_table_black"
+ buildstack = /obj/item/stack/tile/carpet/black
+
+/obj/structure/table/wood/fancy/black/New()
+ ..()
+ icon = 'icons/obj/smooth_structures/fancy_table_black.dmi'
+
/*
* Reinforced tables
*/
diff --git a/code/game/objects/structures/watercloset.dm b/code/game/objects/structures/watercloset.dm
index 1e5c16f665..90c26657f5 100644
--- a/code/game/objects/structures/watercloset.dm
+++ b/code/game/objects/structures/watercloset.dm
@@ -480,8 +480,8 @@
if(istype(O, /obj/item/weapon/melee/baton))
var/obj/item/weapon/melee/baton/B = O
- if(B.bcell)
- if(B.bcell.charge > 0 && B.status == 1)
+ if(B.cell)
+ if(B.cell.charge > 0 && B.status == 1)
flick("baton_active", src)
var/stunforce = B.stunforce
user.Stun(stunforce)
diff --git a/code/game/objects/structures/window.dm b/code/game/objects/structures/window.dm
index 0c11418003..247a0a70d4 100644
--- a/code/game/objects/structures/window.dm
+++ b/code/game/objects/structures/window.dm
@@ -24,6 +24,7 @@
resistance_flags = ACID_PROOF
armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 80, acid = 100)
CanAtmosPass = ATMOS_PASS_PROC
+ var/real_explosion_block //ignore this, just use explosion_block
/obj/structure/window/examine(mob/user)
..()
@@ -73,6 +74,10 @@
if(rods)
debris += new /obj/item/stack/rods(src, rods)
+ //windows only block while reinforced and fulltile, so we'll use the proc
+ real_explosion_block = explosion_block
+ explosion_block = EXPLOSION_BLOCK_PROC
+
/obj/structure/window/rcd_vals(mob/user, obj/item/weapon/construction/rcd/the_rcd)
switch(the_rcd.mode)
if(RCD_DECONSTRUCT)
@@ -400,6 +405,10 @@
return 1
+/obj/structure/window/GetExplosionBlock()
+ return reinf && fulltile ? real_explosion_block : 0
+
+
/obj/structure/window/unanchored
anchored = FALSE
diff --git a/code/modules/admin/adminmenu.dm b/code/modules/admin/adminmenu.dm
index 8954244da4..aa654ab252 100644
--- a/code/modules/admin/adminmenu.dm
+++ b/code/modules/admin/adminmenu.dm
@@ -1,8 +1,8 @@
-/datum/menu/Admin/Generate_list(client/C)
+/datum/verbs/menu/Admin/Generate_list(client/C)
if (C.holder)
. = ..()
-/datum/menu/Admin/verb/playerpanel()
+/datum/verbs/menu/Admin/verb/playerpanel()
set name = "Player Panel"
set desc = "Player Panel"
set category = "Admin"
diff --git a/code/modules/admin/verbs/individual_logging.dm b/code/modules/admin/verbs/individual_logging.dm
index d7db82f5b3..ca84d5d759 100644
--- a/code/modules/admin/verbs/individual_logging.dm
+++ b/code/modules/admin/verbs/individual_logging.dm
@@ -14,11 +14,12 @@
if(type == INDIVIDUAL_SHOW_ALL_LOG)
dat += "Displaying all logs of [key_name(M)]
"
for(var/log_type in M.logging)
- var/list/reversed = M.logging[log_type]
- reversed = reverseRange(reversed.Copy())
dat += "[log_type]
"
- for(var/entry in reversed)
- dat += "[entry]: [reversed[entry]]
"
+ var/list/reversed = M.logging[log_type]
+ if(islist(reversed))
+ reversed = reverseRange(reversed.Copy())
+ for(var/entry in reversed)
+ dat += "[entry]: [reversed[entry]]
"
dat += "
"
else
dat += "[type] of [key_name(M)]
"
@@ -26,6 +27,6 @@
if(reversed)
reversed = reverseRange(reversed.Copy())
for(var/entry in reversed)
- dat += "[entry]: [reversed[entry]]
"
+ dat += "[entry]: [reversed[entry]]
"
- usr << browse(dat, "window=invidual_logging;size=600x480")
\ No newline at end of file
+ usr << browse(dat, "window=invidual_logging_[M];size=600x480")
diff --git a/code/modules/atmospherics/machinery/components/trinary_devices/filter.dm b/code/modules/atmospherics/machinery/components/trinary_devices/filter.dm
index 3c6c7b2342..01a5b0da3a 100644
--- a/code/modules/atmospherics/machinery/components/trinary_devices/filter.dm
+++ b/code/modules/atmospherics/machinery/components/trinary_devices/filter.dm
@@ -13,6 +13,14 @@
icon_state = "filter_off_f"
flipped = 1
+// These two filter types have critical_machine flagged to on and thus causes the area they are in to be exempt from the Grid Check event.
+
+/obj/machinery/atmospherics/components/trinary/filter/critical
+ critical_machine = TRUE
+
+/obj/machinery/atmospherics/components/trinary/filter/flipped/critical
+ critical_machine = TRUE
+
/obj/machinery/atmospherics/components/trinary/filter/proc/set_frequency(new_frequency)
SSradio.remove_object(src, frequency)
frequency = new_frequency
diff --git a/code/modules/cargo/packs.dm b/code/modules/cargo/packs.dm
index efda086af5..6c09b82402 100644
--- a/code/modules/cargo/packs.dm
+++ b/code/modules/cargo/packs.dm
@@ -543,6 +543,13 @@
crate_name = "electrical maintenance crate"
crate_type = /obj/structure/closet/crate/engineering/electrical
+/datum/supply_pack/engineering/inducers
+ name = "NT-75 Electromagnetic Power Inducers Crate"
+ cost = 2000
+ contains = list(/obj/item/weapon/inducer/sci {cell_type = /obj/item/weapon/stock_parts/cell/{maxcharge = 5000; charge = 5000};opened = 0},/obj/item/weapon/inducer/sci {cell_type = /obj/item/weapon/stock_parts/cell/{maxcharge = 5000; charge = 5000};opened = 0}) //FALSE doesn't work in modified type paths apparently.
+ crate_name = "inducer crate"
+ crate_type = /obj/structure/closet/crate/engineering/electrical
+
/datum/supply_pack/engineering/engiequipment
name = "Engineering Gear Crate"
cost = 1300
diff --git a/code/modules/client/client_procs.dm b/code/modules/client/client_procs.dm
index b11c1e72a7..6bf27bfdf8 100644
--- a/code/modules/client/client_procs.dm
+++ b/code/modules/client/client_procs.dm
@@ -356,9 +356,9 @@ GLOBAL_LIST(external_rsc_urls)
hook_vr("client_new",list(src))
- var/list/topmenus = GLOB.menulist[/datum/menu]
+ var/list/topmenus = GLOB.menulist[/datum/verbs/menu]
for (var/thing in topmenus)
- var/datum/menu/topmenu = thing
+ var/datum/verbs/menu/topmenu = thing
var/topmenuname = "[topmenu]"
if (topmenuname == "[topmenu.type]")
var/list/tree = splittext(topmenuname, "/")
@@ -367,13 +367,13 @@ GLOBAL_LIST(external_rsc_urls)
var/list/entries = topmenu.Generate_list(src)
for (var/child in entries)
winset(src, "[url_encode(child)]", "[entries[child]]")
- if (!ispath(child, /datum/menu))
+ if (!ispath(child, /datum/verbs/menu))
var/atom/verb/verbpath = child
if (copytext(verbpath.name,1,2) != "@")
new child(src)
for (var/thing in prefs.menuoptions)
- var/datum/menu/menuitem = GLOB.menulist[thing]
+ var/datum/verbs/menu/menuitem = GLOB.menulist[thing]
if (menuitem)
menuitem.Load_checked(src)
diff --git a/code/modules/client/preferences_toggles.dm b/code/modules/client/preferences_toggles.dm
index eb244937e6..943999aecc 100644
--- a/code/modules/client/preferences_toggles.dm
+++ b/code/modules/client/preferences_toggles.dm
@@ -1,29 +1,29 @@
//this works as is to create a single checked item, but has no back end code for toggleing the check yet
#define TOGGLE_CHECKBOX(PARENT, CHILD) PARENT/CHILD/abstract = TRUE;PARENT/CHILD/checkbox = CHECKBOX_TOGGLE;PARENT/CHILD/verb/CHILD
-
-//Example usage TOGGLE_CHECKBOX(datum/menu/Settings/Ghost/chatterbox, toggle_ghost_ears)()
-
+
+//Example usage TOGGLE_CHECKBOX(datum/verbs/menu/Settings/Ghost/chatterbox, toggle_ghost_ears)()
+
//override because we don't want to save preferences twice.
-/datum/menu/Settings/Set_checked(client/C, verbpath)
+/datum/verbs/menu/Settings/Set_checked(client/C, verbpath)
if (checkbox == CHECKBOX_GROUP)
C.prefs.menuoptions[type] = verbpath
else if (checkbox == CHECKBOX_TOGGLE)
var/checked = Get_checked(C)
C.prefs.menuoptions[type] = !checked
winset(C, "[verbpath]", "is-checked = [!checked]")
-
-/datum/menu/Settings/verb/setup_character()
+
+/datum/verbs/menu/Settings/verb/setup_character()
set name = "Game Preferences"
- set category = "Preferences"
+ set category = "Preferences"
set desc = "Open Game Preferences Window"
usr.client.prefs.current_tab = 1
usr.client.prefs.ShowChoices(usr)
//toggles
-/datum/menu/Settings/Ghost/chatterbox
+/datum/verbs/menu/Settings/Ghost/chatterbox
name = "Chat Box Spam"
-
-TOGGLE_CHECKBOX(/datum/menu/Settings/Ghost/chatterbox, toggle_ghost_ears)()
+
+TOGGLE_CHECKBOX(/datum/verbs/menu/Settings/Ghost/chatterbox, toggle_ghost_ears)()
set name = "Show/Hide GhostEars"
set category = "Preferences"
set desc = "See All Speech"
@@ -31,10 +31,10 @@ TOGGLE_CHECKBOX(/datum/menu/Settings/Ghost/chatterbox, toggle_ghost_ears)()
to_chat(usr, "As a ghost, you will now [(usr.client.prefs.chat_toggles & CHAT_GHOSTEARS) ? "see all speech in the world" : "only see speech from nearby mobs"].")
usr.client.prefs.save_preferences()
SSblackbox.add_details("preferences_verb","Toggle Ghost Ears|[usr.client.prefs.chat_toggles & CHAT_GHOSTEARS]") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
-/datum/menu/Settings/Ghost/chatterbox/toggle_ghost_ears/Get_checked(client/C)
+/datum/verbs/menu/Settings/Ghost/chatterbox/toggle_ghost_ears/Get_checked(client/C)
return C.prefs.chat_toggles & CHAT_GHOSTEARS
-TOGGLE_CHECKBOX(/datum/menu/Settings/Ghost/chatterbox, toggle_ghost_sight)()
+TOGGLE_CHECKBOX(/datum/verbs/menu/Settings/Ghost/chatterbox, toggle_ghost_sight)()
set name = "Show/Hide GhostSight"
set category = "Preferences"
set desc = "See All Emotes"
@@ -42,10 +42,10 @@ TOGGLE_CHECKBOX(/datum/menu/Settings/Ghost/chatterbox, toggle_ghost_sight)()
to_chat(usr, "As a ghost, you will now [(usr.client.prefs.chat_toggles & CHAT_GHOSTSIGHT) ? "see all emotes in the world" : "only see emotes from nearby mobs"].")
usr.client.prefs.save_preferences()
SSblackbox.add_details("preferences_verb","Toggle Ghost Sight|[usr.client.prefs.chat_toggles & CHAT_GHOSTSIGHT]") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
-/datum/menu/Settings/Ghost/chatterbox/toggle_ghost_sight/Get_checked(client/C)
+/datum/verbs/menu/Settings/Ghost/chatterbox/toggle_ghost_sight/Get_checked(client/C)
return C.prefs.chat_toggles & CHAT_GHOSTSIGHT
-TOGGLE_CHECKBOX(/datum/menu/Settings/Ghost/chatterbox, toggle_ghost_whispers)()
+TOGGLE_CHECKBOX(/datum/verbs/menu/Settings/Ghost/chatterbox, toggle_ghost_whispers)()
set name = "Show/Hide GhostWhispers"
set category = "Preferences"
set desc = "See All Whispers"
@@ -53,10 +53,10 @@ TOGGLE_CHECKBOX(/datum/menu/Settings/Ghost/chatterbox, toggle_ghost_whispers)()
to_chat(usr, "As a ghost, you will now [(usr.client.prefs.chat_toggles & CHAT_GHOSTWHISPER) ? "see all whispers in the world" : "only see whispers from nearby mobs"].")
usr.client.prefs.save_preferences()
SSblackbox.add_details("preferences_verb","Toggle Ghost Whispers|[usr.client.prefs.chat_toggles & CHAT_GHOSTWHISPER]") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
-/datum/menu/Settings/Ghost/chatterbox/toggle_ghost_whispers/Get_checked(client/C)
+/datum/verbs/menu/Settings/Ghost/chatterbox/toggle_ghost_whispers/Get_checked(client/C)
return C.prefs.chat_toggles & CHAT_GHOSTWHISPER
-TOGGLE_CHECKBOX(/datum/menu/Settings/Ghost/chatterbox, toggle_ghost_radio)()
+TOGGLE_CHECKBOX(/datum/verbs/menu/Settings/Ghost/chatterbox, toggle_ghost_radio)()
set name = "Show/Hide GhostRadio"
set category = "Preferences"
set desc = "See All Radio Chatter"
@@ -64,60 +64,60 @@ TOGGLE_CHECKBOX(/datum/menu/Settings/Ghost/chatterbox, toggle_ghost_radio)()
to_chat(usr, "As a ghost, you will now [(usr.client.prefs.chat_toggles & CHAT_GHOSTRADIO) ? "see radio chatter" : "not see radio chatter"].")
usr.client.prefs.save_preferences()
SSblackbox.add_details("preferences_verb","Toggle Ghost Radio|[usr.client.prefs.chat_toggles & CHAT_GHOSTRADIO]") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! //social experiment, increase the generation whenever you copypaste this shamelessly GENERATION 1
-/datum/menu/Settings/Ghost/chatterbox/toggle_ghost_radio/Get_checked(client/C)
+/datum/verbs/menu/Settings/Ghost/chatterbox/toggle_ghost_radio/Get_checked(client/C)
return C.prefs.chat_toggles & CHAT_GHOSTRADIO
-TOGGLE_CHECKBOX(/datum/menu/Settings/Ghost/chatterbox, toggle_ghost_pda)()
- set name = "Show/Hide GhostPDA"
+TOGGLE_CHECKBOX(/datum/verbs/menu/Settings/Ghost/chatterbox, toggle_ghost_pda)()
+ set name = "Show/Hide GhostPDA"
set category = "Preferences"
set desc = "See All PDA Messages"
usr.client.prefs.chat_toggles ^= CHAT_GHOSTPDA
to_chat(usr, "As a ghost, you will now [(usr.client.prefs.chat_toggles & CHAT_GHOSTPDA) ? "see all pda messages in the world" : "only see pda messages from nearby mobs"].")
usr.client.prefs.save_preferences()
SSblackbox.add_details("preferences_verb","Toggle Ghost PDA|[usr.client.prefs.chat_toggles & CHAT_GHOSTPDA]") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
-/datum/menu/Settings/Ghost/chatterbox/toggle_ghost_pda/Get_checked(client/C)
+/datum/verbs/menu/Settings/Ghost/chatterbox/toggle_ghost_pda/Get_checked(client/C)
return C.prefs.chat_toggles & CHAT_GHOSTPDA
-/datum/menu/Settings/Ghost/chatterbox/Events
+/datum/verbs/menu/Settings/Ghost/chatterbox/Events
name = "Events"
-
-//please be aware that the following two verbs have inverted stat output, so that "Toggle Deathrattle|1" still means you activated it
-TOGGLE_CHECKBOX(/datum/menu/Settings/Ghost/chatterbox/Events, toggle_deathrattle)()
- set name = "Toggle Deathrattle"
+
+//please be aware that the following two verbs have inverted stat output, so that "Toggle Deathrattle|1" still means you activated it
+TOGGLE_CHECKBOX(/datum/verbs/menu/Settings/Ghost/chatterbox/Events, toggle_deathrattle)()
+ set name = "Toggle Deathrattle"
set category = "Preferences"
set desc = "Death"
usr.client.prefs.toggles ^= DISABLE_DEATHRATTLE
usr.client.prefs.save_preferences()
to_chat(usr, "You will [(usr.client.prefs.toggles & DISABLE_DEATHRATTLE) ? "no longer" : "now"] get messages when a sentient mob dies.")
SSblackbox.add_details("preferences_verb", "Toggle Deathrattle|[!(usr.client.prefs.toggles & DISABLE_DEATHRATTLE)]") //If you are copy-pasting this, maybe you should spend some time reading the comments.
-/datum/menu/Settings/Ghost/chatterbox/Events/toggle_deathrattle/Get_checked(client/C)
+/datum/verbs/menu/Settings/Ghost/chatterbox/Events/toggle_deathrattle/Get_checked(client/C)
return !(C.prefs.toggles & DISABLE_DEATHRATTLE)
-TOGGLE_CHECKBOX(/datum/menu/Settings/Ghost/chatterbox/Events, toggle_arrivalrattle)()
- set name = "Toggle Arrivalrattle"
+TOGGLE_CHECKBOX(/datum/verbs/menu/Settings/Ghost/chatterbox/Events, toggle_arrivalrattle)()
+ set name = "Toggle Arrivalrattle"
set category = "Preferences"
set desc = "New Player Arrival"
usr.client.prefs.toggles ^= DISABLE_ARRIVALRATTLE
to_chat(usr, "You will [(usr.client.prefs.toggles & DISABLE_ARRIVALRATTLE) ? "no longer" : "now"] get messages when someone joins the station.")
usr.client.prefs.save_preferences()
SSblackbox.add_details("preferences_verb", "Toggle Arrivalrattle|[!(usr.client.prefs.toggles & DISABLE_ARRIVALRATTLE)]") //If you are copy-pasting this, maybe you should rethink where your life went so wrong.
-/datum/menu/Settings/Ghost/chatterbox/Events/toggle_arrivalrattle/Get_checked(client/C)
+/datum/verbs/menu/Settings/Ghost/chatterbox/Events/toggle_arrivalrattle/Get_checked(client/C)
return !(C.prefs.toggles & DISABLE_ARRIVALRATTLE)
-TOGGLE_CHECKBOX(/datum/menu/Settings/Ghost, togglemidroundantag)()
- set name = "Toggle Midround Antagonist"
+TOGGLE_CHECKBOX(/datum/verbs/menu/Settings/Ghost, togglemidroundantag)()
+ set name = "Toggle Midround Antagonist"
set category = "Preferences"
set desc = "Midround Antagonist"
usr.client.prefs.toggles ^= MIDROUND_ANTAG
usr.client.prefs.save_preferences()
to_chat(usr, "You will [(usr.client.prefs.toggles & MIDROUND_ANTAG) ? "now" : "no longer"] be considered for midround antagonist positions.")
SSblackbox.add_details("preferences_verb","Toggle Midround Antag|[usr.client.prefs.toggles & MIDROUND_ANTAG]") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
-/datum/menu/Settings/Ghost/togglemidroundantag/Get_checked(client/C)
+/datum/verbs/menu/Settings/Ghost/togglemidroundantag/Get_checked(client/C)
return C.prefs.toggles & MIDROUND_ANTAG
-TOGGLE_CHECKBOX(/datum/menu/Settings/Sound, toggletitlemusic)()
- set name = "Hear/Silence LobbyMusic"
- set category = "Preferences"
+TOGGLE_CHECKBOX(/datum/verbs/menu/Settings/Sound, toggletitlemusic)()
+ set name = "Hear/Silence LobbyMusic"
+ set category = "Preferences"
set desc = "Hear Music In Lobby"
usr.client.prefs.toggles ^= SOUND_LOBBY
usr.client.prefs.save_preferences()
@@ -125,33 +125,33 @@ TOGGLE_CHECKBOX(/datum/menu/Settings/Sound, toggletitlemusic)()
to_chat(usr, "You will now hear music in the game lobby.")
if(isnewplayer(usr))
usr.client.playtitlemusic()
- else
+ else
to_chat(usr, "You will no longer hear music in the game lobby.")
usr.stop_sound_channel(CHANNEL_LOBBYMUSIC)
SSblackbox.add_details("preferences_verb","Toggle Lobby Music|[usr.client.prefs.toggles & SOUND_LOBBY]") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
-/datum/menu/Settings/Sound/toggletitlemusic/Get_checked(client/C)
+/datum/verbs/menu/Settings/Sound/toggletitlemusic/Get_checked(client/C)
return C.prefs.toggles & SOUND_LOBBY
-
-TOGGLE_CHECKBOX(/datum/menu/Settings/Sound, togglemidis)()
- set name = "Hear/Silence Midis"
- set category = "Preferences"
+
+TOGGLE_CHECKBOX(/datum/verbs/menu/Settings/Sound, togglemidis)()
+ set name = "Hear/Silence Midis"
+ set category = "Preferences"
set desc = "Hear Admin Triggered Sounds (Midis)"
usr.client.prefs.toggles ^= SOUND_MIDI
usr.client.prefs.save_preferences()
if(usr.client.prefs.toggles & SOUND_MIDI)
to_chat(usr, "You will now hear any sounds uploaded by admins.")
- else
+ else
to_chat(usr, "You will no longer hear sounds uploaded by admins")
usr.stop_sound_channel(CHANNEL_ADMIN)
SSblackbox.add_details("preferences_verb","Toggle Hearing Midis|[usr.client.prefs.toggles & SOUND_MIDI]") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
-/datum/menu/Settings/Sound/togglemidis/Get_checked(client/C)
+/datum/verbs/menu/Settings/Sound/togglemidis/Get_checked(client/C)
return C.prefs.toggles & SOUND_MIDI
-
-
-TOGGLE_CHECKBOX(/datum/menu/Settings/Sound, toggle_instruments)()
+
+
+TOGGLE_CHECKBOX(/datum/verbs/menu/Settings/Sound, toggle_instruments)()
set name = "Hear/Silence Instruments"
- set category = "Preferences"
+ set category = "Preferences"
set desc = "Hear In-game Instruments"
usr.client.prefs.toggles ^= SOUND_INSTRUMENTS
usr.client.prefs.save_preferences()
@@ -160,57 +160,57 @@ TOGGLE_CHECKBOX(/datum/menu/Settings/Sound, toggle_instruments)()
else
to_chat(usr, "You will no longer hear musical instruments.")
SSblackbox.add_details("preferences_verb","Toggle Instruments|[usr.client.prefs.toggles & SOUND_INSTRUMENTS]") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
-/datum/menu/Settings/Sound/toggle_instruments/Get_checked(client/C)
+/datum/verbs/menu/Settings/Sound/toggle_instruments/Get_checked(client/C)
return C.prefs.toggles & SOUND_INSTRUMENTS
-
-TOGGLE_CHECKBOX(/datum/menu/Settings/Sound, Toggle_Soundscape)()
- set name = "Hear/Silence Ambience"
- set category = "Preferences"
+
+TOGGLE_CHECKBOX(/datum/verbs/menu/Settings/Sound, Toggle_Soundscape)()
+ set name = "Hear/Silence Ambience"
+ set category = "Preferences"
set desc = "Hear Ambient Sound Effects"
usr.client.prefs.toggles ^= SOUND_AMBIENCE
usr.client.prefs.save_preferences()
if(usr.client.prefs.toggles & SOUND_AMBIENCE)
to_chat(usr, "You will now hear ambient sounds.")
- else
+ else
to_chat(usr, "You will no longer hear ambient sounds.")
usr << sound(null, repeat = 0, wait = 0, volume = 0, channel = 1)
usr << sound(null, repeat = 0, wait = 0, volume = 0, channel = 2)
SSblackbox.add_details("preferences_verb","Toggle Ambience|[usr.client.prefs.toggles & SOUND_AMBIENCE]") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
-/datum/menu/Settings/Sound/Toggle_Soundscape/Get_checked(client/C)
+/datum/verbs/menu/Settings/Sound/Toggle_Soundscape/Get_checked(client/C)
return C.prefs.toggles & SOUND_AMBIENCE
-
-TOGGLE_CHECKBOX(/datum/menu/Settings/Sound, toggle_ship_ambience)()
+
+TOGGLE_CHECKBOX(/datum/verbs/menu/Settings/Sound, toggle_ship_ambience)()
set name = "Hear/Silence Ship Ambience"
- set category = "Preferences"
+ set category = "Preferences"
set desc = "Hear Ship Ambience Roar"
usr.client.prefs.toggles ^= SOUND_SHIP_AMBIENCE
usr.client.prefs.save_preferences()
if(usr.client.prefs.toggles & SOUND_SHIP_AMBIENCE)
to_chat(usr, "You will now hear ship ambience.")
- else
+ else
to_chat(usr, "You will no longer hear ship ambience.")
usr << sound(null, repeat = 0, wait = 0, volume = 0, channel = 2)
usr.client.ambience_playing = 0
SSblackbox.add_details("preferences_verb", "Toggle Ship Ambience|[usr.client.prefs.toggles & SOUND_SHIP_AMBIENCE]") //If you are copy-pasting this, I bet you read this comment expecting to see the same thing :^)
-/datum/menu/Settings/Sound/toggle_ship_ambience/Get_checked(client/C)
+/datum/verbs/menu/Settings/Sound/toggle_ship_ambience/Get_checked(client/C)
return C.prefs.toggles & SOUND_SHIP_AMBIENCE
-
-TOGGLE_CHECKBOX(/datum/menu/Settings/Sound, toggle_announcement_sound)()
+
+TOGGLE_CHECKBOX(/datum/verbs/menu/Settings/Sound, toggle_announcement_sound)()
set name = "Hear/Silence Announcements"
- set category = "Preferences"
+ set category = "Preferences"
set desc = "Hear Announcement Sound"
usr.client.prefs.toggles ^= SOUND_ANNOUNCEMENTS
to_chat(usr, "You will now [(usr.client.prefs.toggles & SOUND_ANNOUNCEMENTS) ? "hear announcement sounds" : "no longer hear announcements"].")
usr.client.prefs.save_preferences()
SSblackbox.add_details("preferences_verb","Toggle Announcement Sound|[usr.client.prefs.toggles & SOUND_ANNOUNCEMENTS]") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
-/datum/menu/Settings/Sound/toggle_announcement_sound/Get_checked(client/C)
+/datum/verbs/menu/Settings/Sound/toggle_announcement_sound/Get_checked(client/C)
return C.prefs.toggles & SOUND_ANNOUNCEMENTS
-TOGGLE_CHECKBOX(/datum/menu/Settings/Sound, toggleprayersounds)()
+TOGGLE_CHECKBOX(/datum/verbs/menu/Settings/Sound, toggleprayersounds)()
set name = "Hear/Silence Prayer Sounds"
set category = "Preferences"
set desc = "Hear Prayer Sounds"
@@ -218,14 +218,14 @@ TOGGLE_CHECKBOX(/datum/menu/Settings/Sound, toggleprayersounds)()
usr.client.prefs.save_preferences()
if(usr.client.prefs.toggles & SOUND_PRAYERS)
to_chat(usr, "You will now hear prayer sounds.")
- else
+ else
to_chat(usr, "You will no longer prayer sounds.")
SSblackbox.add_details("admin_toggle", "Toggle Prayer Sounds|[usr.client.prefs.toggles & SOUND_PRAYERS]")
-/datum/menu/Settings/Sound/toggleprayersounds/Get_checked(client/C)
+/datum/verbs/menu/Settings/Sound/toggleprayersounds/Get_checked(client/C)
return C.prefs.toggles & SOUND_PRAYERS
-/datum/menu/Settings/Sound/verb/stop_client_sounds()
+/datum/verbs/menu/Settings/Sound/verb/stop_client_sounds()
set name = "Stop Sounds"
set category = "Preferences"
set desc = "Stop Current Sounds"
@@ -233,7 +233,7 @@ TOGGLE_CHECKBOX(/datum/menu/Settings/Sound, toggleprayersounds)()
SSblackbox.add_details("preferences_verb","Stop Self Sounds") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
-TOGGLE_CHECKBOX(/datum/menu/Settings, listen_ooc)()
+TOGGLE_CHECKBOX(/datum/verbs/menu/Settings, listen_ooc)()
set name = "Show/Hide OOC"
set category = "Preferences"
set desc = "Show OOC Chat"
@@ -241,171 +241,171 @@ TOGGLE_CHECKBOX(/datum/menu/Settings, listen_ooc)()
usr.client.prefs.save_preferences()
to_chat(usr, "You will [(usr.client.prefs.chat_toggles & CHAT_OOC) ? "now" : "no longer"] see messages on the OOC channel.")
SSblackbox.add_details("preferences_verb","Toggle Seeing OOC|[usr.client.prefs.chat_toggles & CHAT_OOC]") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
-/datum/menu/Settings/listen_ooc/Get_checked(client/C)
+/datum/verbs/menu/Settings/listen_ooc/Get_checked(client/C)
return C.prefs.chat_toggles & CHAT_OOC
-
-GLOBAL_LIST_INIT(ghost_forms, list("ghost","ghostking","ghostian2","skeleghost","ghost_red","ghost_black", \
- "ghost_blue","ghost_yellow","ghost_green","ghost_pink", \
- "ghost_cyan","ghost_dblue","ghost_dred","ghost_dgreen", \
- "ghost_dcyan","ghost_grey","ghost_dyellow","ghost_dpink", "ghost_purpleswirl","ghost_funkypurp","ghost_pinksherbert","ghost_blazeit",\
- "ghost_mellow","ghost_rainbow","ghost_camo","ghost_fire", "catghost"))
-/client/proc/pick_form()
- if(!is_content_unlocked())
- alert("This setting is for accounts with BYOND premium only.")
- return
- var/new_form = input(src, "Thanks for supporting BYOND - Choose your ghostly form:","Thanks for supporting BYOND",null) as null|anything in GLOB.ghost_forms
- if(new_form)
- prefs.ghost_form = new_form
- prefs.save_preferences()
- if(isobserver(mob))
- var/mob/dead/observer/O = mob
- O.update_icon(new_form)
-
-GLOBAL_LIST_INIT(ghost_orbits, list(GHOST_ORBIT_CIRCLE,GHOST_ORBIT_TRIANGLE,GHOST_ORBIT_SQUARE,GHOST_ORBIT_HEXAGON,GHOST_ORBIT_PENTAGON))
-
-/client/proc/pick_ghost_orbit()
- if(!is_content_unlocked())
- alert("This setting is for accounts with BYOND premium only.")
- return
- var/new_orbit = input(src, "Thanks for supporting BYOND - Choose your ghostly orbit:","Thanks for supporting BYOND",null) as null|anything in GLOB.ghost_orbits
- if(new_orbit)
- prefs.ghost_orbit = new_orbit
- prefs.save_preferences()
- if(isobserver(mob))
- var/mob/dead/observer/O = mob
- O.ghost_orbit = new_orbit
-
-/client/proc/pick_ghost_accs()
- var/new_ghost_accs = alert("Do you want your ghost to show full accessories where possible, hide accessories but still use the directional sprites where possible, or also ignore the directions and stick to the default sprites?",,"full accessories", "only directional sprites", "default sprites")
- if(new_ghost_accs)
- switch(new_ghost_accs)
- if("full accessories")
- prefs.ghost_accs = GHOST_ACCS_FULL
- if("only directional sprites")
- prefs.ghost_accs = GHOST_ACCS_DIR
- if("default sprites")
- prefs.ghost_accs = GHOST_ACCS_NONE
- prefs.save_preferences()
- if(isobserver(mob))
- var/mob/dead/observer/O = mob
- O.update_icon()
-
-/client/verb/pick_ghost_customization()
- set name = "Ghost Customization"
- set category = "Preferences"
- set desc = "Customize your ghastly appearance."
- if(is_content_unlocked())
- switch(alert("Which setting do you want to change?",,"Ghost Form","Ghost Orbit","Ghost Accessories"))
- if("Ghost Form")
- pick_form()
- if("Ghost Orbit")
- pick_ghost_orbit()
- if("Ghost Accessories")
- pick_ghost_accs()
- else
- pick_ghost_accs()
-
-/client/verb/pick_ghost_others()
- set name = "Ghosts of Others"
- set category = "Preferences"
- set desc = "Change display settings for the ghosts of other players."
- var/new_ghost_others = alert("Do you want the ghosts of others to show up as their own setting, as their default sprites or always as the default white ghost?",,"Their Setting", "Default Sprites", "White Ghost")
- if(new_ghost_others)
- switch(new_ghost_others)
- if("Their Setting")
- prefs.ghost_others = GHOST_OTHERS_THEIR_SETTING
- if("Default Sprites")
- prefs.ghost_others = GHOST_OTHERS_DEFAULT_SPRITE
- if("White Ghost")
- prefs.ghost_others = GHOST_OTHERS_SIMPLE
- prefs.save_preferences()
- if(isobserver(mob))
- var/mob/dead/observer/O = mob
- O.update_sight()
-
-/client/verb/toggle_intent_style()
- set name = "Toggle Intent Selection Style"
- set category = "Preferences"
- set desc = "Toggle between directly clicking the desired intent or clicking to rotate through."
- prefs.toggles ^= INTENT_STYLE
- to_chat(src, "[(prefs.toggles & INTENT_STYLE) ? "Clicking directly on intents selects them." : "Clicking on intents rotates selection clockwise."]")
- prefs.save_preferences()
+
+GLOBAL_LIST_INIT(ghost_forms, list("ghost","ghostking","ghostian2","skeleghost","ghost_red","ghost_black", \
+ "ghost_blue","ghost_yellow","ghost_green","ghost_pink", \
+ "ghost_cyan","ghost_dblue","ghost_dred","ghost_dgreen", \
+ "ghost_dcyan","ghost_grey","ghost_dyellow","ghost_dpink", "ghost_purpleswirl","ghost_funkypurp","ghost_pinksherbert","ghost_blazeit",\
+ "ghost_mellow","ghost_rainbow","ghost_camo","ghost_fire", "catghost"))
+/client/proc/pick_form()
+ if(!is_content_unlocked())
+ alert("This setting is for accounts with BYOND premium only.")
+ return
+ var/new_form = input(src, "Thanks for supporting BYOND - Choose your ghostly form:","Thanks for supporting BYOND",null) as null|anything in GLOB.ghost_forms
+ if(new_form)
+ prefs.ghost_form = new_form
+ prefs.save_preferences()
+ if(isobserver(mob))
+ var/mob/dead/observer/O = mob
+ O.update_icon(new_form)
+
+GLOBAL_LIST_INIT(ghost_orbits, list(GHOST_ORBIT_CIRCLE,GHOST_ORBIT_TRIANGLE,GHOST_ORBIT_SQUARE,GHOST_ORBIT_HEXAGON,GHOST_ORBIT_PENTAGON))
+
+/client/proc/pick_ghost_orbit()
+ if(!is_content_unlocked())
+ alert("This setting is for accounts with BYOND premium only.")
+ return
+ var/new_orbit = input(src, "Thanks for supporting BYOND - Choose your ghostly orbit:","Thanks for supporting BYOND",null) as null|anything in GLOB.ghost_orbits
+ if(new_orbit)
+ prefs.ghost_orbit = new_orbit
+ prefs.save_preferences()
+ if(isobserver(mob))
+ var/mob/dead/observer/O = mob
+ O.ghost_orbit = new_orbit
+
+/client/proc/pick_ghost_accs()
+ var/new_ghost_accs = alert("Do you want your ghost to show full accessories where possible, hide accessories but still use the directional sprites where possible, or also ignore the directions and stick to the default sprites?",,"full accessories", "only directional sprites", "default sprites")
+ if(new_ghost_accs)
+ switch(new_ghost_accs)
+ if("full accessories")
+ prefs.ghost_accs = GHOST_ACCS_FULL
+ if("only directional sprites")
+ prefs.ghost_accs = GHOST_ACCS_DIR
+ if("default sprites")
+ prefs.ghost_accs = GHOST_ACCS_NONE
+ prefs.save_preferences()
+ if(isobserver(mob))
+ var/mob/dead/observer/O = mob
+ O.update_icon()
+
+/client/verb/pick_ghost_customization()
+ set name = "Ghost Customization"
+ set category = "Preferences"
+ set desc = "Customize your ghastly appearance."
+ if(is_content_unlocked())
+ switch(alert("Which setting do you want to change?",,"Ghost Form","Ghost Orbit","Ghost Accessories"))
+ if("Ghost Form")
+ pick_form()
+ if("Ghost Orbit")
+ pick_ghost_orbit()
+ if("Ghost Accessories")
+ pick_ghost_accs()
+ else
+ pick_ghost_accs()
+
+/client/verb/pick_ghost_others()
+ set name = "Ghosts of Others"
+ set category = "Preferences"
+ set desc = "Change display settings for the ghosts of other players."
+ var/new_ghost_others = alert("Do you want the ghosts of others to show up as their own setting, as their default sprites or always as the default white ghost?",,"Their Setting", "Default Sprites", "White Ghost")
+ if(new_ghost_others)
+ switch(new_ghost_others)
+ if("Their Setting")
+ prefs.ghost_others = GHOST_OTHERS_THEIR_SETTING
+ if("Default Sprites")
+ prefs.ghost_others = GHOST_OTHERS_DEFAULT_SPRITE
+ if("White Ghost")
+ prefs.ghost_others = GHOST_OTHERS_SIMPLE
+ prefs.save_preferences()
+ if(isobserver(mob))
+ var/mob/dead/observer/O = mob
+ O.update_sight()
+
+/client/verb/toggle_intent_style()
+ set name = "Toggle Intent Selection Style"
+ set category = "Preferences"
+ set desc = "Toggle between directly clicking the desired intent or clicking to rotate through."
+ prefs.toggles ^= INTENT_STYLE
+ to_chat(src, "[(prefs.toggles & INTENT_STYLE) ? "Clicking directly on intents selects them." : "Clicking on intents rotates selection clockwise."]")
+ prefs.save_preferences()
SSblackbox.add_details("preferences_verb","Toggle Intent Selection|[prefs.toggles & INTENT_STYLE]") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
-
-/client/verb/toggle_ghost_hud_pref()
- set name = "Toggle Ghost HUD"
- set category = "Preferences"
- set desc = "Hide/Show Ghost HUD"
-
- prefs.ghost_hud = !prefs.ghost_hud
- to_chat(src, "Ghost HUD will now be [prefs.ghost_hud ? "visible" : "hidden"].")
- prefs.save_preferences()
- if(isobserver(mob))
- mob.hud_used.show_hud()
+
+/client/verb/toggle_ghost_hud_pref()
+ set name = "Toggle Ghost HUD"
+ set category = "Preferences"
+ set desc = "Hide/Show Ghost HUD"
+
+ prefs.ghost_hud = !prefs.ghost_hud
+ to_chat(src, "Ghost HUD will now be [prefs.ghost_hud ? "visible" : "hidden"].")
+ prefs.save_preferences()
+ if(isobserver(mob))
+ mob.hud_used.show_hud()
SSblackbox.add_details("preferences_verb","Toggle Ghost HUD|[prefs.ghost_hud]")
-
-/client/verb/toggle_inquisition() // warning: unexpected inquisition
- set name = "Toggle Inquisitiveness"
- set desc = "Sets whether your ghost examines everything on click by default"
- set category = "Preferences"
-
- prefs.inquisitive_ghost = !prefs.inquisitive_ghost
- prefs.save_preferences()
- if(prefs.inquisitive_ghost)
- to_chat(src, "You will now examine everything you click on.")
- else
- to_chat(src, "You will no longer examine things you click on.")
+
+/client/verb/toggle_inquisition() // warning: unexpected inquisition
+ set name = "Toggle Inquisitiveness"
+ set desc = "Sets whether your ghost examines everything on click by default"
+ set category = "Preferences"
+
+ prefs.inquisitive_ghost = !prefs.inquisitive_ghost
+ prefs.save_preferences()
+ if(prefs.inquisitive_ghost)
+ to_chat(src, "You will now examine everything you click on.")
+ else
+ to_chat(src, "You will no longer examine things you click on.")
SSblackbox.add_details("preferences_verb","Toggle Ghost Inquisitiveness|[prefs.inquisitive_ghost]")
-
-//Admin Preferences
-/client/proc/toggleadminhelpsound()
- set name = "Hear/Silence Adminhelps"
- set category = "Preferences"
- set desc = "Toggle hearing a notification when admin PMs are received"
- if(!holder)
- return
- prefs.toggles ^= SOUND_ADMINHELP
- prefs.save_preferences()
- to_chat(usr, "You will [(prefs.toggles & SOUND_ADMINHELP) ? "now" : "no longer"] hear a sound when adminhelps arrive.")
+
+//Admin Preferences
+/client/proc/toggleadminhelpsound()
+ set name = "Hear/Silence Adminhelps"
+ set category = "Preferences"
+ set desc = "Toggle hearing a notification when admin PMs are received"
+ if(!holder)
+ return
+ prefs.toggles ^= SOUND_ADMINHELP
+ prefs.save_preferences()
+ to_chat(usr, "You will [(prefs.toggles & SOUND_ADMINHELP) ? "now" : "no longer"] hear a sound when adminhelps arrive.")
SSblackbox.add_details("admin_toggle","Toggle Adminhelp Sound|[prefs.toggles & SOUND_ADMINHELP]") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
-
-/client/proc/toggleannouncelogin()
- set name = "Do/Don't Announce Login"
- set category = "Preferences"
- set desc = "Toggle if you want an announcement to admins when you login during a round"
- if(!holder)
- return
- prefs.toggles ^= ANNOUNCE_LOGIN
- prefs.save_preferences()
- to_chat(usr, "You will [(prefs.toggles & ANNOUNCE_LOGIN) ? "now" : "no longer"] have an announcement to other admins when you login.")
+
+/client/proc/toggleannouncelogin()
+ set name = "Do/Don't Announce Login"
+ set category = "Preferences"
+ set desc = "Toggle if you want an announcement to admins when you login during a round"
+ if(!holder)
+ return
+ prefs.toggles ^= ANNOUNCE_LOGIN
+ prefs.save_preferences()
+ to_chat(usr, "You will [(prefs.toggles & ANNOUNCE_LOGIN) ? "now" : "no longer"] have an announcement to other admins when you login.")
SSblackbox.add_details("admin_toggle","Toggle Login Announcement|[prefs.toggles & ANNOUNCE_LOGIN]") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
-
-/client/proc/toggle_hear_radio()
- set name = "Show/Hide Radio Chatter"
- set category = "Preferences"
- set desc = "Toggle seeing radiochatter from nearby radios and speakers"
- if(!holder) return
- prefs.chat_toggles ^= CHAT_RADIO
- prefs.save_preferences()
- to_chat(usr, "You will [(prefs.chat_toggles & CHAT_RADIO) ? "now" : "no longer"] see radio chatter from nearby radios or speakers")
+
+/client/proc/toggle_hear_radio()
+ set name = "Show/Hide Radio Chatter"
+ set category = "Preferences"
+ set desc = "Toggle seeing radiochatter from nearby radios and speakers"
+ if(!holder) return
+ prefs.chat_toggles ^= CHAT_RADIO
+ prefs.save_preferences()
+ to_chat(usr, "You will [(prefs.chat_toggles & CHAT_RADIO) ? "now" : "no longer"] see radio chatter from nearby radios or speakers")
SSblackbox.add_details("admin_toggle","Toggle Radio Chatter|[prefs.chat_toggles & CHAT_RADIO]") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
-
-/client/proc/deadchat()
- set name = "Show/Hide Deadchat"
- set category = "Preferences"
- set desc ="Toggles seeing deadchat"
- prefs.chat_toggles ^= CHAT_DEAD
- prefs.save_preferences()
- to_chat(src, "You will [(prefs.chat_toggles & CHAT_DEAD) ? "now" : "no longer"] see deadchat.")
+
+/client/proc/deadchat()
+ set name = "Show/Hide Deadchat"
+ set category = "Preferences"
+ set desc ="Toggles seeing deadchat"
+ prefs.chat_toggles ^= CHAT_DEAD
+ prefs.save_preferences()
+ to_chat(src, "You will [(prefs.chat_toggles & CHAT_DEAD) ? "now" : "no longer"] see deadchat.")
SSblackbox.add_details("admin_toggle","Toggle Deadchat Visibility|[prefs.chat_toggles & CHAT_DEAD]") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
-
-/client/proc/toggleprayers()
- set name = "Show/Hide Prayers"
- set category = "Preferences"
- set desc = "Toggles seeing prayers"
- prefs.chat_toggles ^= CHAT_PRAYER
- prefs.save_preferences()
- to_chat(src, "You will [(prefs.chat_toggles & CHAT_PRAYER) ? "now" : "no longer"] see prayerchat.")
+
+/client/proc/toggleprayers()
+ set name = "Show/Hide Prayers"
+ set category = "Preferences"
+ set desc = "Toggles seeing prayers"
+ prefs.chat_toggles ^= CHAT_PRAYER
+ prefs.save_preferences()
+ to_chat(src, "You will [(prefs.chat_toggles & CHAT_PRAYER) ? "now" : "no longer"] see prayerchat.")
SSblackbox.add_details("admin_toggle","Toggle Prayer Visibility|[prefs.chat_toggles & CHAT_PRAYER]") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
-
+
diff --git a/code/modules/events/immovable_rod.dm b/code/modules/events/immovable_rod.dm
index 2b46d82df1..5c5fc93e6b 100644
--- a/code/modules/events/immovable_rod.dm
+++ b/code/modules/events/immovable_rod.dm
@@ -21,8 +21,8 @@ In my current plan for it, 'solid' will be defined as anything with density == 1
/datum/round_event/immovable_rod/start()
var/startside = pick(GLOB.cardinal)
- var/turf/startT = spaceDebrisStartLoc(startside, ZLEVEL_STATION)
- var/turf/endT = spaceDebrisFinishLoc(startside, ZLEVEL_STATION)
+ var/turf/startT = spaceDebrisStartLoc(startside, ZLEVEL_STATION)
+ var/turf/endT = spaceDebrisFinishLoc(startside, ZLEVEL_STATION)
new /obj/effect/immovablerod(startT, endT)
/obj/effect/immovablerod
@@ -82,13 +82,8 @@ In my current plan for it, 'solid' will be defined as anything with density == 1
if(clong.density)
clong.ex_act(2)
- else if(ismob(clong))
- if(ishuman(clong))
- var/mob/living/carbon/human/H = clong
- H.visible_message("[H.name] is penetrated by an immovable rod!" , "The rod penetrates you!" , "You hear a CLANG!")
- H.adjustBruteLoss(160)
- if(clong.density || prob(10))
- clong.ex_act(2)
+ else if(isliving(clong))
+ penetrate(clong)
else if(istype(clong, type))
var/obj/effect/immovablerod/other = clong
visible_message("[src] collides with [other]!\
@@ -98,3 +93,11 @@ In my current plan for it, 'solid' will be defined as anything with density == 1
smoke.start()
qdel(src)
qdel(other)
+
+/obj/effect/immovablerod/proc/penetrate(mob/living/L)
+ L.visible_message("[L] is penetrated by an immovable rod!" , "The rod penetrates you!" , "You hear a CLANG!")
+ if(ishuman(L))
+ var/mob/living/carbon/human/H = L
+ H.adjustBruteLoss(160)
+ if(L && (L.density || prob(10)))
+ L.ex_act(2)
diff --git a/code/modules/mapping/map_template.dm b/code/modules/mapping/map_template.dm
index e0588acf2b..2aa2031bbe 100644
--- a/code/modules/mapping/map_template.dm
+++ b/code/modules/mapping/map_template.dm
@@ -71,12 +71,12 @@
if(!bounds)
return
- //initialize things that are normally initialized after map load
- initTemplateBounds(bounds)
-
if(!SSmapping.loading_ruins) //Will be done manually during mapping ss init
repopulate_sorted_areas()
+ //initialize things that are normally initialized after map load
+ initTemplateBounds(bounds)
+
log_game("[name] loaded at at [T.x],[T.y],[T.z]")
return TRUE
diff --git a/code/modules/mining/equipment/kinetic_crusher.dm b/code/modules/mining/equipment/kinetic_crusher.dm
index 6d8a99c1a2..a96e14f802 100644
--- a/code/modules/mining/equipment/kinetic_crusher.dm
+++ b/code/modules/mining/equipment/kinetic_crusher.dm
@@ -21,7 +21,7 @@
sharpness = IS_SHARP
var/list/trophies = list()
var/charged = TRUE
- var/charge_time = 14
+ var/charge_time = 15
/obj/item/weapon/twohanded/required/mining_hammer/Destroy()
for(var/a in trophies)
@@ -92,16 +92,21 @@
for(var/t in trophies)
var/obj/item/crusher_trophy/T = t
T.on_mark_detonation(target, user)
- new /obj/effect/temp_visual/kinetic_blast(get_turf(L))
- var/backstab_dir = get_dir(user, L)
- var/def_check = L.getarmor(type = "bomb")
- if((user.dir & backstab_dir) && (L.dir & backstab_dir))
- L.apply_damage(80, BRUTE, blocked = def_check)
- playsound(user, 'sound/weapons/Kenetic_accel.ogg', 100, 1) //Seriously who spelled it wrong
- else
- L.apply_damage(50, BRUTE, blocked = def_check)
- if(!QDELETED(C) && !QDELETED(L))
- C.total_damage += target_health - L.health //we did some damage, but let's not assume how much we did
+ if(!QDELETED(L))
+ if(!QDELETED(C))
+ C.total_damage += target_health - L.health //we did some damage, but let's not assume how much we did
+ new /obj/effect/temp_visual/kinetic_blast(get_turf(L))
+ var/backstab_dir = get_dir(user, L)
+ var/def_check = L.getarmor(type = "bomb")
+ if((user.dir & backstab_dir) && (L.dir & backstab_dir))
+ if(!QDELETED(C))
+ C.total_damage += 80 //cheat a little and add the total before killing it, so certain mobs don't have much lower chances of giving an item
+ L.apply_damage(80, BRUTE, blocked = def_check)
+ playsound(user, 'sound/weapons/Kenetic_accel.ogg', 100, 1) //Seriously who spelled it wrong
+ else
+ if(!QDELETED(C))
+ C.total_damage += 50
+ L.apply_damage(50, BRUTE, blocked = def_check)
/obj/item/weapon/twohanded/required/mining_hammer/proc/Recharge()
if(!charged)
@@ -185,9 +190,70 @@
/obj/item/crusher_trophy/proc/on_mark_application(mob/living/target, datum/status_effect/crusher_mark/mark, had_mark) //the target, the mark applied, and if the target had a mark before
/obj/item/crusher_trophy/proc/on_mark_detonation(mob/living/target, mob/living/user) //the target and the user
+//goliath
+/obj/item/crusher_trophy/goliath_tentacle
+ name = "goliath tentacle"
+ desc = "A sliced-off goliath tentacle. Suitable as a trophy for a kinetic crusher."
+ icon_state = "goliath_tentacle"
+ denied_type = /obj/item/crusher_trophy/goliath_tentacle
+ bonus_value = 2
+ var/missing_health_ratio = 0.1
+ var/missing_health_desc = 10
+/obj/item/crusher_trophy/goliath_tentacle/effect_desc()
+ return "mark detonation to do [bonus_value] more damage for every [missing_health_desc] health you are missing"
+
+/obj/item/crusher_trophy/goliath_tentacle/on_mark_detonation(mob/living/target, mob/living/user)
+ var/missing_health = user.health - user.maxHealth
+ missing_health *= missing_health_ratio //bonus is active at all times, even if you're above 90 health
+ missing_health *= bonus_value //multiply the remaining amount by bonus_value
+ if(missing_health > 0)
+ target.adjustBruteLoss(missing_health) //and do that much damage
+
+/watcher
+/obj/item/crusher_trophy/watcher_wing
+ name = "watcher wing"
+ desc = "A wing ripped from a watcher. Suitable as a trophy for a kinetic crusher."
+ icon_state = "watcher_wing"
+ denied_type = /obj/item/crusher_trophy/watcher_wing
+ bonus_value = 8
+
+/obj/item/crusher_trophy/watcher_wing/effect_desc()
+ return "mark detonation to prevent certain creatures from using certain attacks for [bonus_value*0.1] second[bonus_value*0.1 == 1 ? "":"s"]"
+
+/obj/item/crusher_trophy/watcher_wing/on_mark_detonation(mob/living/target, mob/living/user)
+ if(ishostile(target))
+ var/mob/living/simple_animal/hostile/H = target
+ if(H.ranged) //briefly delay ranged attacks
+ if(H.ranged_cooldown_time >= world.time)
+ H.ranged_cooldown_time += bonus_value
+ else
+ H.ranged_cooldown_time = bonus_value + world.time
+
+//legion
+/obj/item/crusher_trophy/legion_skull
+ name = "legion skull"
+ desc = "A dead and lifeless legion skull. Suitable as a trophy for a kinetic crusher."
+ icon_state = "legion_skull"
+ denied_type = /obj/item/crusher_trophy/legion_skull
+ bonus_value = 3
+
+/obj/item/crusher_trophy/legion_skull/effect_desc()
+ return "a kinetic crusher to recharge [bonus_value*0.1] second[bonus_value*0.1 == 1 ? "":"s"] faster"
+
+/obj/item/crusher_trophy/legion_skull/add_to(obj/item/weapon/twohanded/required/mining_hammer/H, mob/living/user)
+ . = ..()
+ if(.)
+ H.charge_time -= bonus_value
+
+/obj/item/crusher_trophy/legion_skull/remove_from(obj/item/weapon/twohanded/required/mining_hammer/H, mob/living/user)
+ . = ..()
+ if(.)
+ H.charge_time += bonus_value
+
+
//ash drake
/obj/item/crusher_trophy/tail_spike
- desc = "A spike taken from a ash drake's tail."
+ desc = "A spike taken from a ash drake's tail. Suitable as a trophy for a kinetic crusher."
denied_type = /obj/item/crusher_trophy/tail_spike
bonus_value = 5
@@ -210,7 +276,7 @@
//bubblegum
/obj/item/crusher_trophy/demon_claws
name = "demon claws"
- desc = "A set of blood-drenched claws from a massive demon's hand."
+ desc = "A set of blood-drenched claws from a massive demon's hand. Suitable as a trophy for a kinetic crusher."
icon_state = "demon_claws"
gender = PLURAL
denied_type = /obj/item/crusher_trophy/demon_claws
@@ -244,7 +310,7 @@
//colossus
/obj/item/crusher_trophy/blaster_tubes
name = "blaster tubes"
- desc = "The blaster tubes from a colossus's arm."
+ desc = "The blaster tubes from a colossus's arm. Suitable as a trophy for a kinetic crusher."
icon_state = "blaster_tubes"
gender = PLURAL
denied_type = /obj/item/crusher_trophy/blaster_tubes
@@ -273,7 +339,7 @@
//hierophant
/obj/item/crusher_trophy/vortex_talisman
name = "vortex talisman"
- desc = "A glowing trinket that was originally the Hierophant's beacon."
+ desc = "A glowing trinket that was originally the Hierophant's beacon. Suitable as a trophy for a kinetic crusher."
icon_state = "vortex_talisman"
denied_type = /obj/item/crusher_trophy/vortex_talisman
diff --git a/code/modules/mining/lavaland/necropolis_chests.dm b/code/modules/mining/lavaland/necropolis_chests.dm
index 8b6f43ee25..ceb1ca85b5 100644
--- a/code/modules/mining/lavaland/necropolis_chests.dm
+++ b/code/modules/mining/lavaland/necropolis_chests.dm
@@ -11,7 +11,7 @@
desc = "It's watching you suspiciously."
/obj/structure/closet/crate/necropolis/tendril/PopulateContents()
- var/loot = rand(1,27)
+ var/loot = rand(1,28)
switch(loot)
if(1)
new /obj/item/device/shared_storage/red(src)
@@ -69,6 +69,8 @@
if(27)
new /obj/item/borg/upgrade/modkit/lifesteal(src)
new /obj/item/weapon/bedsheet/cult(src)
+ if(28)
+ new /obj/item/borg/upgrade/modkit/bounty(src)
diff --git a/code/modules/mob/living/carbon/carbon_movement.dm b/code/modules/mob/living/carbon/carbon_movement.dm
index 5b1f43d58c..374ff4bd22 100644
--- a/code/modules/mob/living/carbon/carbon_movement.dm
+++ b/code/modules/mob/living/carbon/carbon_movement.dm
@@ -57,3 +57,13 @@
nutrition -= HUNGER_FACTOR/10
if((disabilities & FAT) && m_intent == MOVE_INTENT_RUN && bodytemperature <= 360)
bodytemperature += 2
+
+/mob/living/carbon/Moved(oldLoc, Dir)
+ . = ..()
+ for(var/obj/O in internal_organs)
+ O.on_mob_move(dir, src, oldLoc)
+
+/mob/living/carbon/setDir(newdir)
+ . = ..()
+ for(var/obj/O in internal_organs)
+ O.on_mob_turn(newdir, src)
diff --git a/code/modules/mob/living/carbon/human/interactive.dm b/code/modules/mob/living/carbon/human/interactive.dm
index 9b4f963d07..c93a79f4fc 100644
--- a/code/modules/mob/living/carbon/human/interactive.dm
+++ b/code/modules/mob/living/carbon/human/interactive.dm
@@ -1540,7 +1540,7 @@
if(stunning && stunCheck.stunned)
shouldFire = 0
if(shouldFire)
- if(P.power_supply.charge <= 10) // can shoot seems to bug out for tasers, using this hacky method instead
+ if(P.cell.charge <= 10) // can shoot seems to bug out for tasers, using this hacky method instead
P.update_icon()
npcDrop(P,1)
else
diff --git a/code/modules/mob/living/carbon/human/status_procs.dm b/code/modules/mob/living/carbon/human/status_procs.dm
index f1ff497a2a..cc32be6f2f 100644
--- a/code/modules/mob/living/carbon/human/status_procs.dm
+++ b/code/modules/mob/living/carbon/human/status_procs.dm
@@ -6,17 +6,20 @@
/mob/living/carbon/human/Weaken(amount, updating = 1, ignore_canstun = 0)
amount = dna.species.spec_stun(src,amount)
return ..()
-
+
/mob/living/carbon/human/Paralyse(amount, updating = 1, ignore_canstun = 0)
amount = dna.species.spec_stun(src,amount)
return ..()
-
+
/mob/living/carbon/human/cure_husk()
. = ..()
if(.)
update_hair()
/mob/living/carbon/human/become_husk()
+ if(istype(dna.species, /datum/species/skeleton)) //skeletons shouldn't be husks.
+ cure_husk()
+ return
. = ..()
if(.)
update_hair()
diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm
index 27cf0c3a82..abb81678bb 100644
--- a/code/modules/mob/living/silicon/robot/robot.dm
+++ b/code/modules/mob/living/silicon/robot/robot.dm
@@ -97,6 +97,9 @@
buckle_lying = FALSE
can_ride_typecache = list(/mob/living/carbon/human)
+/mob/living/silicon/robot/get_cell()
+ return cell
+
/mob/living/silicon/robot/Initialize(mapload)
spark_system = new /datum/effect_system/spark_spread()
spark_system.set_up(5, 0, src)
diff --git a/code/modules/mob/living/silicon/robot/robot_defense.dm b/code/modules/mob/living/silicon/robot/robot_defense.dm
index 01c700768f..96247fa1b1 100644
--- a/code/modules/mob/living/silicon/robot/robot_defense.dm
+++ b/code/modules/mob/living/silicon/robot/robot_defense.dm
@@ -56,7 +56,7 @@
add_fingerprint(user)
if(opened && !wiresexposed && !issilicon(user))
if(cell)
- cell.updateicon()
+ cell.update_icon()
cell.add_fingerprint(user)
user.put_in_active_hand(cell)
to_chat(user, "You remove \the [cell].")
diff --git a/code/modules/mob/living/silicon/robot/robot_modules.dm b/code/modules/mob/living/silicon/robot/robot_modules.dm
index 446b264987..e39cc1672d 100644
--- a/code/modules/mob/living/silicon/robot/robot_modules.dm
+++ b/code/modules/mob/living/silicon/robot/robot_modules.dm
@@ -104,10 +104,10 @@
S.cost = 1
S.source = get_or_create_estorage(/datum/robot_energy_storage/wire)
- else if(istype(S, /obj/item/stack/marker_beacon))
- S.cost = 1
- S.source = get_or_create_estorage(/datum/robot_energy_storage/beacon)
-
+ else if(istype(S, /obj/item/stack/marker_beacon))
+ S.cost = 1
+ S.source = get_or_create_estorage(/datum/robot_energy_storage/beacon)
+
if(S && S.source)
S.materials = list()
S.is_cyborg = 1
@@ -149,8 +149,8 @@
F.update_icon()
else if(istype(I, /obj/item/weapon/melee/baton))
var/obj/item/weapon/melee/baton/B = I
- if(B.bcell)
- B.bcell.charge = B.bcell.maxcharge
+ if(B.cell)
+ B.cell.charge = B.cell.maxcharge
else if(istype(I, /obj/item/weapon/gun/energy))
var/obj/item/weapon/gun/energy/EG = I
if(!EG.chambered)
@@ -202,9 +202,9 @@
/obj/item/weapon/robot_module/proc/do_transform_animation()
var/mob/living/silicon/robot/R = loc
R.notransform = TRUE
- var/obj/effect/temp_visual/decoy/fading/fivesecond/ANM = new /obj/effect/temp_visual/decoy/fading/fivesecond(R.loc, R)
+ var/obj/effect/temp_visual/decoy/fading/fivesecond/ANM = new /obj/effect/temp_visual/decoy/fading/fivesecond(R.loc, R)
ANM.layer = R.layer - 0.01
- new /obj/effect/temp_visual/small_smoke(R.loc)
+ new /obj/effect/temp_visual/small_smoke(R.loc)
if(R.hat)
R.hat.forceMove(get_turf(R))
R.hat = null
@@ -226,7 +226,7 @@
if(R.hud_used)
R.hud_used.update_robot_modules_display()
if(feedback_key && !did_feedback)
- SSblackbox.inc(feedback_key, 1)
+ SSblackbox.inc(feedback_key, 1)
/obj/item/weapon/robot_module/standard
name = "Standard"
@@ -250,7 +250,7 @@
ratvar_modules = list(
/obj/item/clockwork/slab/cyborg,
/obj/item/clockwork/ratvarian_spear/cyborg,
- /obj/item/clockwork/clockwork_proselytizer/cyborg)
+ /obj/item/clockwork/replica_fabricator/cyborg)
moduleselect_icon = "standard"
feedback_key = "cyborg_standard"
hat_offset = -3
@@ -275,7 +275,7 @@
/obj/item/roller/robo,
/obj/item/borg/cyborghug/medical,
/obj/item/stack/medical/gauze/cyborg,
- /obj/item/weapon/organ_storage,
+ /obj/item/weapon/organ_storage,
/obj/item/borg/lollipop)
emag_modules = list(/obj/item/weapon/reagent_containers/borghypo/hacked)
ratvar_modules = list(
@@ -314,7 +314,7 @@
emag_modules = list(/obj/item/borg/stun)
ratvar_modules = list(
/obj/item/clockwork/slab/cyborg/engineer,
- /obj/item/clockwork/clockwork_proselytizer/cyborg)
+ /obj/item/clockwork/replica_fabricator/cyborg)
cyborg_base_icon = "engineer"
moduleselect_icon = "engineer"
feedback_key = "cyborg_engineering"
@@ -395,9 +395,9 @@
..()
var/obj/item/weapon/gun/energy/e_gun/advtaser/cyborg/T = locate(/obj/item/weapon/gun/energy/e_gun/advtaser/cyborg) in basic_modules
if(T)
- if(T.power_supply.charge < T.power_supply.maxcharge)
+ if(T.cell.charge < T.cell.maxcharge)
var/obj/item/ammo_casing/energy/S = T.ammo_type[T.select]
- T.power_supply.give(S.e_cost * coeff)
+ T.cell.give(S.e_cost * coeff)
T.update_icon()
else
T.charge_tick = 0
@@ -411,8 +411,8 @@
/obj/item/weapon/reagent_containers/borghypo/peace,
/obj/item/weapon/holosign_creator/cyborg,
/obj/item/borg/cyborghug/peacekeeper,
- /obj/item/weapon/extinguisher,
- /obj/item/borg/projectile_dampen)
+ /obj/item/weapon/extinguisher,
+ /obj/item/borg/projectile_dampen)
emag_modules = list(/obj/item/weapon/reagent_containers/borghypo/peace/hacked)
ratvar_modules = list(
/obj/item/clockwork/slab/cyborg/peacekeeper,
@@ -444,7 +444,7 @@
emag_modules = list(/obj/item/weapon/reagent_containers/spray/cyborg_lube)
ratvar_modules = list(
/obj/item/clockwork/slab/cyborg/janitor,
- /obj/item/clockwork/clockwork_proselytizer/cyborg)
+ /obj/item/clockwork/replica_fabricator/cyborg)
cyborg_base_icon = "janitor"
moduleselect_icon = "janitor"
feedback_key = "cyborg_janitor"
@@ -542,8 +542,8 @@
/obj/item/weapon/storage/bag/sheetsnatcher/borg,
/obj/item/device/t_scanner/adv_mining_scanner,
/obj/item/weapon/gun/energy/kinetic_accelerator/cyborg,
- /obj/item/device/gps/cyborg,
- /obj/item/stack/marker_beacon)
+ /obj/item/device/gps/cyborg,
+ /obj/item/stack/marker_beacon)
emag_modules = list(/obj/item/borg/stun)
ratvar_modules = list(
/obj/item/clockwork/slab/cyborg/miner,
@@ -639,8 +639,8 @@
max_energy = 2500
recharge_rate = 250
name = "Medical Synthesizer"
-
-/datum/robot_energy_storage/beacon
- max_energy = 30
- recharge_rate = 1
- name = "Marker Beacon Storage"
+
+/datum/robot_energy_storage/beacon
+ max_energy = 30
+ recharge_rate = 1
+ name = "Marker Beacon Storage"
diff --git a/code/modules/mob/living/simple_animal/bot/ed209bot.dm b/code/modules/mob/living/simple_animal/bot/ed209bot.dm
index 4a79476bf0..61586e625c 100644
--- a/code/modules/mob/living/simple_animal/bot/ed209bot.dm
+++ b/code/modules/mob/living/simple_animal/bot/ed209bot.dm
@@ -9,7 +9,7 @@
maxHealth = 100
damage_coeff = list(BRUTE = 0.5, BURN = 0.7, TOX = 0, CLONE = 0, STAMINA = 0, OXY = 0)
obj_damage = 60
- environment_smash = ENVIRONMENT_SMASH_WALLS //Walls can't stop THE LAW
+ environment_smash = ENVIRONMENT_SMASH_WALLS //Walls can't stop THE LAW
mob_size = MOB_SIZE_LARGE
radio_key = /obj/item/device/encryptionkey/headset_sec
@@ -358,21 +358,21 @@ Auto Patrol[]"},
var/obj/item/weapon/ed209_assembly/Sa = new /obj/item/weapon/ed209_assembly(Tsec)
Sa.build_step = 1
- Sa.add_overlay("hs_hole")
+ Sa.add_overlay("hs_hole")
Sa.created_name = name
new /obj/item/device/assembly/prox_sensor(Tsec)
if(!lasercolor)
var/obj/item/weapon/gun/energy/e_gun/advtaser/G = new /obj/item/weapon/gun/energy/e_gun/advtaser(Tsec)
- G.power_supply.charge = 0
+ G.cell.charge = 0
G.update_icon()
else if(lasercolor == "b")
var/obj/item/weapon/gun/energy/laser/bluetag/G = new /obj/item/weapon/gun/energy/laser/bluetag(Tsec)
- G.power_supply.charge = 0
+ G.cell.charge = 0
G.update_icon()
else if(lasercolor == "r")
var/obj/item/weapon/gun/energy/laser/redtag/G = new /obj/item/weapon/gun/energy/laser/redtag(Tsec)
- G.power_supply.charge = 0
+ G.cell.charge = 0
G.update_icon()
if(prob(50))
@@ -390,7 +390,7 @@ Auto Patrol[]"},
if(lasercolor == "r")
new /obj/item/clothing/suit/redtag(Tsec)
- do_sparks(3, TRUE, src)
+ do_sparks(3, TRUE, src)
new /obj/effect/decal/cleanable/oil(loc)
..()
@@ -444,7 +444,7 @@ Auto Patrol[]"},
if(severity==2 && prob(70))
..(severity-1)
else
- new /obj/effect/temp_visual/emp(loc)
+ new /obj/effect/temp_visual/emp(loc)
var/list/mob/living/carbon/targets = new
for(var/mob/living/carbon/C in view(12,src))
if(C.stat==2)
diff --git a/code/modules/mob/living/simple_animal/friendly/drone/extra_drone_types.dm b/code/modules/mob/living/simple_animal/friendly/drone/extra_drone_types.dm
index 1c70ca57e5..11935e7fce 100644
--- a/code/modules/mob/living/simple_animal/friendly/drone/extra_drone_types.dm
+++ b/code/modules/mob/living/simple_animal/friendly/drone/extra_drone_types.dm
@@ -91,6 +91,16 @@
icon_living = icon_state
icon_dead = "[visualAppearence]_dead"
+/obj/item/drone_shell/dusty
+ name = "derelict drone shell"
+ desc = "A long-forgotten drone shell. It seems kind of... Space Russian."
+ drone_type = /mob/living/simple_animal/drone/derelict
+
+/mob/living/simple_animal/drone/derelict
+ name = "derelict drone"
+ default_hatmask = /obj/item/clothing/head/ushanka
+
+
/mob/living/simple_animal/drone/cogscarab
name = "cogscarab"
desc = "A strange, drone-like machine. It constantly emits the hum of gears."
@@ -120,14 +130,14 @@
hacked = TRUE
visualAppearence = CLOCKDRONE
can_be_held = FALSE
- flavortext = "You are a cogscarab, a clockwork creation of Ratvar. As a cogscarab, you have low health, an inbuilt proselytizer that can convert brass \
- to liquified alloy, a set of relatively fast tools, can communicate over the Hierophant Network with :b, and are immune to extreme \
+ flavortext = "You are a cogscarab, a clockwork creation of Ratvar. As a cogscarab, you have low health, an inbuilt fabricator that can convert brass \
+ to power, a set of relatively fast tools, can communicate over the Hierophant Network with :b, and are immune to extreme \
temperatures and pressures. \nYour goal is to serve the Justiciar and his servants by repairing and defending all they create."
-/mob/living/simple_animal/drone/cogscarab/ratvar //a subtype for spawning when ratvar is alive, has a slab that it can use and a normal proselytizer
+/mob/living/simple_animal/drone/cogscarab/ratvar //a subtype for spawning when ratvar is alive, has a slab that it can use and a normal fabricatorlab that it can use and a normal fabricator
default_storage = /obj/item/weapon/storage/toolbox/brass/prefilled/ratvar
-/mob/living/simple_animal/drone/cogscarab/admin //an admin-only subtype of cogscarab with a no-cost proselytizer and slab in its box
+/mob/living/simple_animal/drone/cogscarab/admin //an admin-only subtype of cogscarab with a no-cost fabricator and slab in its box
default_storage = /obj/item/weapon/storage/toolbox/brass/prefilled/ratvar/admin
/mob/living/simple_animal/drone/cogscarab/Initialize()
@@ -167,9 +177,7 @@
..()
/mob/living/simple_animal/drone/cogscarab/can_use_guns(obj/item/weapon/gun/G)
- if(!GLOB.ratvar_awakens)
- changeNext_move(CLICK_CD_RANGE*4) //about as much delay as an unupgraded kinetic accelerator
- return TRUE
+ return GLOB.ratvar_awakens
/mob/living/simple_animal/drone/cogscarab/get_armor_effectiveness()
if(GLOB.ratvar_awakens)
@@ -191,11 +199,41 @@
/mob/living/simple_animal/drone/cogscarab/ratvar_act()
fully_heal(TRUE)
-/obj/item/drone_shell/dusty
- name = "derelict drone shell"
- desc = "A long-forgotten drone shell. It seems kind of... Space Russian."
- drone_type = /mob/living/simple_animal/drone/derelict
+/mob/living/simple_animal/drone/cogscarab/update_icons()
+ if(stat != DEAD)
+ if(incapacitated())
+ icon_state = "[visualAppearence]_flipped"
+ else
+ icon_state = visualAppearence
+ else
+ icon_state = "[visualAppearence]_dead"
-/mob/living/simple_animal/drone/derelict
- name = "derelict drone"
- default_hatmask = /obj/item/clothing/head/ushanka
+/mob/living/simple_animal/drone/cogscarab/Stun(amount, updating = 1, ignore_canstun = 0)
+ . = ..()
+ if(.)
+ update_icons()
+
+/mob/living/simple_animal/drone/cogscarab/SetStunned(amount, updating = 1, ignore_canstun = 0)
+ . = ..()
+ if(.)
+ update_icons()
+
+/mob/living/simple_animal/drone/cogscarab/AdjustStunned(amount, updating = 1, ignore_canstun = 0)
+ . = ..()
+ if(.)
+ update_icons()
+
+/mob/living/simple_animal/drone/cogscarab/Weaken(amount, updating = 1, ignore_canweaken = 0)
+ . = ..()
+ if(.)
+ update_icons()
+
+/mob/living/simple_animal/drone/cogscarab/SetWeakened(amount, updating = 1, ignore_canweaken = 0)
+ . = ..()
+ if(.)
+ update_icons()
+
+/mob/living/simple_animal/drone/cogscarab/AdjustWeakened(amount, updating = 1, ignore_canweaken = 0)
+ . = ..()
+ if(.)
+ update_icons()
diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm
index 6d44df978e..9675ac25b1 100644
--- a/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm
+++ b/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm
@@ -132,6 +132,12 @@ Difficulty: Hard
if(spawned_beacon && loc == spawned_beacon.loc && did_reset)
arena_trap(src)
+/mob/living/simple_animal/hostile/megafauna/hierophant/CanAttack(atom/the_target)
+ . = ..()
+ if(istype(the_target, /mob/living/simple_animal/hostile/asteroid/hivelordbrood)) //ignore temporary targets in favor of more permenant targets
+ return FALSE
+
+
/mob/living/simple_animal/hostile/megafauna/hierophant/adjustHealth(amount, updating_health = TRUE, forced = FALSE)
. = ..()
if(src && . > 0 && !blinking)
diff --git a/code/modules/mob/living/simple_animal/hostile/mimic.dm b/code/modules/mob/living/simple_animal/hostile/mimic.dm
index da45e31d1e..c94557f591 100644
--- a/code/modules/mob/living/simple_animal/hostile/mimic.dm
+++ b/code/modules/mob/living/simple_animal/hostile/mimic.dm
@@ -100,7 +100,7 @@ GLOBAL_LIST_INIT(protected_objects, list(/obj/structure/table, /obj/structure/ca
var/mob/living/creator = null // the creator
var/destroy_objects = 0
var/knockdown_people = 0
- var/static/mutable_appearance/googly_eyes = mutable_appearance('icons/mob/mob.dmi', "googly_eyes")
+ var/static/mutable_appearance/googly_eyes = mutable_appearance('icons/mob/mob.dmi', "googly_eyes")
gold_core_spawnable = 0
/mob/living/simple_animal/hostile/mimic/copy/Initialize(mapload, obj/copy, mob/living/creator, destroy_original = 0)
@@ -203,7 +203,7 @@ GLOBAL_LIST_INIT(protected_objects, list(/obj/structure/table, /obj/structure/ca
if(..())
emote_see = list("aims menacingly")
obj_damage = 0
- environment_smash = ENVIRONMENT_SMASH_NONE //needed? seems weird for them to do so
+ environment_smash = ENVIRONMENT_SMASH_NONE //needed? seems weird for them to do so
ranged = 1
retreat_distance = 1 //just enough to shoot
minimum_distance = 6
@@ -229,10 +229,10 @@ GLOBAL_LIST_INIT(protected_objects, list(/obj/structure/table, /obj/structure/ca
/mob/living/simple_animal/hostile/mimic/copy/ranged/OpenFire(the_target)
if(Zapgun)
- if(Zapgun.power_supply)
+ if(Zapgun.cell)
var/obj/item/ammo_casing/energy/shot = Zapgun.ammo_type[Zapgun.select]
- if(Zapgun.power_supply.charge >= shot.e_cost)
- Zapgun.power_supply.use(shot.e_cost)
+ if(Zapgun.cell.charge >= shot.e_cost)
+ Zapgun.cell.use(shot.e_cost)
Zapgun.update_icon()
..()
else if(Zapstick)
diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/basilisk.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/basilisk.dm
index 19b35b9866..a379b0e8ac 100644
--- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/basilisk.dm
+++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/basilisk.dm
@@ -76,5 +76,9 @@
stat_attack = UNCONSCIOUS
movement_type = FLYING
robust_searching = 1
+ crusher_loot = /obj/item/crusher_trophy/watcher_wing
loot = list()
butcher_results = list(/obj/item/weapon/ore/diamond = 2, /obj/item/stack/sheet/sinew = 2, /obj/item/stack/sheet/bone = 1)
+
+/mob/living/simple_animal/hostile/asteroid/basilisk/watcher/tendril
+ fromtendril = TRUE
diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/goliath.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/goliath.dm
index e95012b519..50f3d7260b 100644
--- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/goliath.dm
+++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/goliath.dm
@@ -85,11 +85,16 @@
icon_dead = "goliath_dead"
throw_message = "does nothing to the tough hide of the"
pre_attack_icon = "goliath2"
+ crusher_loot = /obj/item/crusher_trophy/goliath_tentacle
butcher_results = list(/obj/item/weapon/reagent_containers/food/snacks/meat/slab/goliath = 2, /obj/item/stack/sheet/animalhide/goliath_hide = 1, /obj/item/stack/sheet/bone = 2)
loot = list()
stat_attack = UNCONSCIOUS
robust_searching = 1
+/mob/living/simple_animal/hostile/asteroid/goliath/beast/tendril
+ fromtendril = TRUE
+
+
//tentacles
/obj/effect/goliath_tentacle
name = "Goliath tentacle"
diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/hivelord.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/hivelord.dm
index fbea8d0f79..4bbfb9ab72 100644
--- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/hivelord.dm
+++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/hivelord.dm
@@ -46,6 +46,10 @@
OpenFire()
return TRUE
+/mob/living/simple_animal/hostile/asteroid/hivelord/spawn_crusher_loot()
+ loot += crusher_loot //we don't butcher
+
+
/mob/living/simple_animal/hostile/asteroid/hivelord/death(gibbed)
mouse_opacity = 1
..(gibbed)
@@ -101,6 +105,7 @@
speak_emote = list("echoes")
attack_sound = 'sound/weapons/pierce.ogg'
throw_message = "bounces harmlessly off of"
+ crusher_loot = /obj/item/crusher_trophy/legion_skull
loot = list(/obj/item/organ/regenerative_core/legion)
brood_type = /mob/living/simple_animal/hostile/asteroid/hivelordbrood/legion
del_on_death = 1
@@ -119,6 +124,10 @@
new /obj/effect/mob_spawn/human/corpse/damaged(T)
..(gibbed)
+/mob/living/simple_animal/hostile/asteroid/hivelord/legion/tendril
+ fromtendril = TRUE
+
+
//Legion skull
/mob/living/simple_animal/hostile/asteroid/hivelordbrood/legion
name = "legion"
diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/mining_mobs.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/mining_mobs.dm
index 1e76860267..57e04b1331 100644
--- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/mining_mobs.dm
+++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/mining_mobs.dm
@@ -11,14 +11,21 @@
response_help = "pokes"
response_disarm = "shoves"
response_harm = "strikes"
+ var/crusher_loot
status_flags = 0
a_intent = INTENT_HARM
var/throw_message = "bounces off of"
var/icon_aggro = null // for swapping to when we get aggressive
+ var/fromtendril = FALSE
see_in_dark = 8
lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE
mob_size = MOB_SIZE_LARGE
+/mob/living/simple_animal/hostile/asteroid/Initialize(mapload)
+ . = ..()
+ apply_status_effect(STATUS_EFFECT_CRUSHERDAMAGETRACKING)
+
+
/mob/living/simple_animal/hostile/asteroid/Aggro()
..()
if(vision_range != aggro_vision_range)
@@ -44,14 +51,21 @@
if(!stat)
Aggro()
if(T.throwforce <= 20)
- visible_message("The [T.name] [src.throw_message] [src.name]!")
+ visible_message("The [T.name] [throw_message] [src.name]!")
return
..()
/mob/living/simple_animal/hostile/asteroid/death(gibbed)
SSblackbox.add_details("mobs_killed_mining","[src.type]")
+ var/datum/status_effect/crusher_damage/C = has_status_effect(STATUS_EFFECT_CRUSHERDAMAGETRACKING)
+ if(C && crusher_loot && prob((C.total_damage/maxHealth)) * 5) //on average, you'll need to kill 20 creatures before getting the item
+ spawn_crusher_loot()
..(gibbed)
+/mob/living/simple_animal/hostile/asteroid/proc/spawn_crusher_loot()
+ butcher_results[crusher_loot] = 1
+
+
/mob/living/simple_animal/hostile/asteroid/handle_temperature_damage()
if(bodytemperature < minbodytemp)
adjustBruteLoss(2)
diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/necropolis_tendril.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/necropolis_tendril.dm
index 1ef8dd9f13..02257193ff 100644
--- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/necropolis_tendril.dm
+++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/necropolis_tendril.dm
@@ -17,7 +17,7 @@
maxHealth = 250
max_mobs = 3
spawn_time = 300 //30 seconds default
- mob_type = /mob/living/simple_animal/hostile/asteroid/basilisk/watcher
+ mob_type = /mob/living/simple_animal/hostile/asteroid/basilisk/watcher/tendril
spawn_text = "emerges from"
atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 5, "min_n2" = 0, "max_n2" = 0)
minbodytemp = 0
@@ -28,10 +28,10 @@
var/obj/effect/light_emitter/tendril/emitted_light
/mob/living/simple_animal/hostile/spawner/lavaland/goliath
- mob_type = /mob/living/simple_animal/hostile/asteroid/goliath/beast
+ mob_type = /mob/living/simple_animal/hostile/asteroid/goliath/beast/tendril
/mob/living/simple_animal/hostile/spawner/lavaland/legion
- mob_type = /mob/living/simple_animal/hostile/asteroid/hivelord/legion
+ mob_type = /mob/living/simple_animal/hostile/asteroid/hivelord/legion/tendril
/mob/living/simple_animal/hostile/spawner/lavaland/Initialize()
. = ..()
diff --git a/code/modules/mob/mob_movement.dm b/code/modules/mob/mob_movement.dm
index 43d8a924a1..9d6ab8410c 100644
--- a/code/modules/mob/mob_movement.dm
+++ b/code/modules/mob/mob_movement.dm
@@ -178,11 +178,18 @@
if(mob.throwing)
mob.throwing.finalize(FALSE)
- for(var/obj/O in mob)
- O.on_mob_move(direct, src)
-
return .
+/mob/Moved(oldLoc, dir)
+ . = ..()
+ for(var/obj/O in contents)
+ O.on_mob_move(dir, src, oldLoc)
+
+/mob/setDir(newDir)
+ . = ..()
+ for(var/obj/O in contents)
+ O.on_mob_turn(newDir, src)
+
///Process_Grab()
///Called by client/Move()
@@ -209,10 +216,10 @@
return
var/mob/living/L = mob
switch(L.incorporeal_move)
- if(INCORPOREAL_MOVE_BASIC)
+ if(INCORPOREAL_MOVE_BASIC)
L.loc = get_step(L, direct)
L.setDir(direct)
- if(INCORPOREAL_MOVE_SHADOW)
+ if(INCORPOREAL_MOVE_SHADOW)
if(prob(50))
var/locx
var/locy
@@ -242,15 +249,15 @@
L.loc = locate(locx,locy,mobloc.z)
var/limit = 2//For only two trailing shadows.
for(var/turf/T in getline(mobloc, L.loc))
- new /obj/effect/temp_visual/dir_setting/ninja/shadow(T, L.dir)
+ new /obj/effect/temp_visual/dir_setting/ninja/shadow(T, L.dir)
limit--
if(limit<=0)
break
else
- new /obj/effect/temp_visual/dir_setting/ninja/shadow(mobloc, L.dir)
+ new /obj/effect/temp_visual/dir_setting/ninja/shadow(mobloc, L.dir)
L.loc = get_step(L, direct)
L.setDir(direct)
- if(INCORPOREAL_MOVE_JAUNT) //Incorporeal move, but blocked by holy-watered tiles and salt piles.
+ if(INCORPOREAL_MOVE_JAUNT) //Incorporeal move, but blocked by holy-watered tiles and salt piles.
var/turf/open/floor/stepTurf = get_step(L, direct)
for(var/obj/effect/decal/cleanable/salt/S in stepTurf)
to_chat(L, "[S] bars your passage!")
@@ -295,12 +302,12 @@
return A
else
var/atom/movable/AM = A
- if(AM == buckled)
+ if(AM == buckled)
continue
- if(ismob(AM))
- var/mob/M = AM
- if(M.buckled)
- continue
+ if(ismob(AM))
+ var/mob/M = AM
+ if(M.buckled)
+ continue
if(!AM.CanPass(src) || AM.density)
if(AM.anchored)
return AM
diff --git a/code/modules/modular_computers/computers/item/computer_power.dm b/code/modules/modular_computers/computers/item/computer_power.dm
index c03570c335..c62b0793ad 100644
--- a/code/modules/modular_computers/computers/item/computer_power.dm
+++ b/code/modules/modular_computers/computers/item/computer_power.dm
@@ -26,6 +26,11 @@
return battery_module.battery.give(amount)
return 0
+/obj/item/device/modular_computer/get_cell()
+ var/obj/item/weapon/computer_hardware/battery/battery_module = all_components[MC_CELL]
+ if(battery_module && battery_module.battery)
+ return battery_module.battery
+
// Used in following function to reduce copypaste
/obj/item/device/modular_computer/proc/power_failure()
diff --git a/code/modules/modular_computers/file_system/programs/card.dm b/code/modules/modular_computers/file_system/programs/card.dm
index fb77197c62..dfe2acd252 100644
--- a/code/modules/modular_computers/file_system/programs/card.dm
+++ b/code/modules/modular_computers/file_system/programs/card.dm
@@ -42,6 +42,9 @@
/datum/computer_file/program/card_mod/New()
..()
change_position_cooldown = config.id_console_jobslot_delay
+ addtimer(CALLBACK(src, .proc/SetConfigCooldown), 0)
+
+/datum/computer_file/program/card_mod/proc/SetConfigCooldown()
/datum/computer_file/program/card_mod/event_idremoved(background, slot)
diff --git a/code/modules/ninja/suit/ninjaDrainAct.dm b/code/modules/ninja/suit/ninjaDrainAct.dm
index 7a3e119a56..c75dd1032d 100644
--- a/code/modules/ninja/suit/ninjaDrainAct.dm
+++ b/code/modules/ninja/suit/ninjaDrainAct.dm
@@ -111,7 +111,7 @@ They *could* go in their appropriate files, but this is supposed to be modular
S.cell.charge += charge
charge = 0
corrupt()
- updateicon()
+ update_icon()
//RDCONSOLE//
diff --git a/code/modules/ninja/suit/suit.dm b/code/modules/ninja/suit/suit.dm
index d5811e32c9..b304b3c530 100644
--- a/code/modules/ninja/suit/suit.dm
+++ b/code/modules/ninja/suit/suit.dm
@@ -56,6 +56,8 @@ Contents:
var/s_bombs = 10//Number of starting ninja smoke bombs.
var/a_boost = 3//Number of adrenaline boosters.
+/obj/item/clothing/suit/space/space_ninja/get_cell()
+ return cell
/obj/item/clothing/suit/space/space_ninja/New()
..()
diff --git a/code/modules/ninja/suit/suit_attackby.dm b/code/modules/ninja/suit/suit_attackby.dm
index e54a5e0e85..7903d4c3e7 100644
--- a/code/modules/ninja/suit/suit_attackby.dm
+++ b/code/modules/ninja/suit/suit_attackby.dm
@@ -32,7 +32,7 @@
U.put_in_hands(old_cell)
old_cell.add_fingerprint(U)
old_cell.corrupt()
- old_cell.updateicon()
+ old_cell.update_icon()
cell = CELL
to_chat(U, "Upgrade complete. Maximum capacity: [round(cell.maxcharge/100)]%")
else
diff --git a/code/modules/power/apc.dm b/code/modules/power/apc.dm
index d980591ceb..1ce26fb373 100644
--- a/code/modules/power/apc.dm
+++ b/code/modules/power/apc.dm
@@ -93,6 +93,10 @@
var/update_overlay = -1
var/icon_update_needed = FALSE
+/obj/machinery/power/apc/get_cell()
+ return cell
+
+
/obj/machinery/power/apc/connect_to_network()
//Override because the APC does not directly connect to the network; it goes through a terminal.
//The terminal is what the power computer looks for anyway.
@@ -622,14 +626,10 @@
return
if(usr == user && opened && (!issilicon(user)))
if(cell)
+ user.visible_message("[user] removes \the [cell] from [src]!","You remove \the [cell].")
user.put_in_hands(cell)
- cell.add_fingerprint(user)
- cell.updateicon()
-
+ cell.update_icon()
src.cell = null
- user.visible_message("[user.name] removes the power cell from [src.name]!",\
- "You remove the power cell.")
- //to_chat(user, "You remove the power cell.")
charging = 0
src.update_icon()
return
diff --git a/code/modules/power/cell.dm b/code/modules/power/cell.dm
index a4b994e0cf..1c3d44b7ea 100644
--- a/code/modules/power/cell.dm
+++ b/code/modules/power/cell.dm
@@ -19,13 +19,16 @@
var/ratingdesc = TRUE
var/grown_battery = FALSE // If it's a grown that acts as a battery, add a wire overlay to it.
+/obj/item/weapon/stock_parts/cell/get_cell()
+ return src
+
/obj/item/weapon/stock_parts/cell/New()
..()
START_PROCESSING(SSobj, src)
charge = maxcharge
if(ratingdesc)
desc += " This one has a power rating of [maxcharge], and you should not swallow it."
- updateicon()
+ update_icon()
/obj/item/weapon/stock_parts/cell/Destroy()
STOP_PROCESSING(SSobj, src)
@@ -46,16 +49,16 @@
else
return PROCESS_KILL
-/obj/item/weapon/stock_parts/cell/proc/updateicon()
+/obj/item/weapon/stock_parts/cell/update_icon()
cut_overlays()
if(grown_battery)
- add_overlay("grown_wires")
+ add_overlay("grown_wires")
if(charge < 0.01)
return
else if(charge/maxcharge >=0.995)
- add_overlay("cell-o2")
+ add_overlay("cell-o2")
else
- add_overlay("cell-o1")
+ add_overlay("cell-o1")
/obj/item/weapon/stock_parts/cell/proc/percent() // return % charge of cell
return 100*charge/maxcharge
@@ -69,7 +72,7 @@
return 0
charge = (charge - amount)
if(!istype(loc, /obj/machinery/power/apc))
- SSblackbox.add_details("cell_used","[src.type]")
+ SSblackbox.add_details("cell_used","[src.type]")
return 1
// recharge the cell
@@ -123,7 +126,7 @@
corrupt()
return
//explosion(T, 0, 1, 2, 2)
- explosion(T, devastation_range, heavy_impact_range, light_impact_range, flash_range)
+ explosion(T, devastation_range, heavy_impact_range, light_impact_range, flash_range)
qdel(src)
/obj/item/weapon/stock_parts/cell/proc/corrupt()
diff --git a/code/modules/procedural_mapping/mapGenerators/repair.dm b/code/modules/procedural_mapping/mapGenerators/repair.dm
index e2f658648c..d568b83e80 100644
--- a/code/modules/procedural_mapping/mapGenerators/repair.dm
+++ b/code/modules/procedural_mapping/mapGenerators/repair.dm
@@ -1,9 +1,10 @@
/datum/mapGeneratorModule/bottomLayer/repairFloorPlasteel
spawnableTurfs = list(/turf/open/floor/plasteel = 100)
var/ignore_wall = FALSE
+ allowAtomsOnSpace = TRUE
/datum/mapGeneratorModule/bottomLayer/repairFloorPlasteel/place(turf/T)
- if(isclosedturf(T))
+ if(isclosedturf(T) && !ignore_wall)
return FALSE
return TRUE
@@ -13,6 +14,7 @@
/datum/mapGeneratorModule/border/normalWalls
spawnableAtoms = list()
spawnableTurfs = list(/turf/closed/wall = 100)
+ allowAtomsOnSpace = TRUE
/datum/mapGenerator/repair
modules = list(/datum/mapGeneratorModule/bottomLayer/repairFloorPlasteel,
diff --git a/code/modules/projectiles/guns/energy.dm b/code/modules/projectiles/guns/energy.dm
index a7080bcf57..6031f144a8 100644
--- a/code/modules/projectiles/guns/energy.dm
+++ b/code/modules/projectiles/guns/energy.dm
@@ -4,13 +4,13 @@
desc = "A basic energy-based gun."
icon = 'icons/obj/guns/energy.dmi'
- var/obj/item/weapon/stock_parts/cell/power_supply //What type of power cell this uses
+ var/obj/item/weapon/stock_parts/cell/cell //What type of power cell this uses
var/cell_type = /obj/item/weapon/stock_parts/cell
var/modifystate = 0
var/list/ammo_type = list(/obj/item/ammo_casing/energy)
var/select = 1 //The state of the select fire switch. Determines from the ammo_type list what kind of shot is fired next.
var/can_charge = 1 //Can it be charged in a recharger?
- var/automatic_charge_overlays = TRUE //Do we handle overlays with base update_icon()?
+ var/automatic_charge_overlays = TRUE //Do we handle overlays with base update_icon()?
var/charge_sections = 4
ammo_x_offset = 2
var/shaded_charge = 0 //if this gun uses a stateful charge bar for more detail
@@ -20,19 +20,22 @@
var/use_cyborg_cell = 0 //whether the gun's cell drains the cyborg user's cell to recharge
/obj/item/weapon/gun/energy/emp_act(severity)
- power_supply.use(round(power_supply.charge / severity))
+ cell.use(round(cell.charge / severity))
chambered = null //we empty the chamber
recharge_newshot() //and try to charge a new shot
update_icon()
+/obj/item/weapon/gun/energy/get_cell()
+ return cell
-/obj/item/weapon/gun/energy/Initialize()
- . = ..()
+
+/obj/item/weapon/gun/energy/Initialize()
+ . = ..()
if(cell_type)
- power_supply = new cell_type(src)
+ cell = new cell_type(src)
else
- power_supply = new(src)
- power_supply.give(power_supply.maxcharge)
+ cell = new(src)
+ cell.give(cell.maxcharge)
update_ammo_types()
recharge_newshot(1)
if(selfcharge)
@@ -50,9 +53,7 @@
fire_delay = shot.delay
/obj/item/weapon/gun/energy/Destroy()
- if(power_supply)
- qdel(power_supply)
- power_supply = null
+ QDEL_NULL(cell)
STOP_PROCESSING(SSobj, src)
return ..()
@@ -62,9 +63,9 @@
if(charge_tick < charge_delay)
return
charge_tick = 0
- if(!power_supply)
+ if(!cell)
return
- power_supply.give(100)
+ cell.give(100)
if(!chambered) //if empty chamber we try to charge a new shot
recharge_newshot(1)
update_icon()
@@ -76,10 +77,10 @@
/obj/item/weapon/gun/energy/can_shoot()
var/obj/item/ammo_casing/energy/shot = ammo_type[select]
- return power_supply.charge >= shot.e_cost
+ return cell.charge >= shot.e_cost
/obj/item/weapon/gun/energy/recharge_newshot(no_cyborg_drain)
- if (!ammo_type || !power_supply)
+ if (!ammo_type || !cell)
return
if(use_cyborg_cell && !no_cyborg_drain)
if(iscyborg(loc))
@@ -87,10 +88,10 @@
if(R.cell)
var/obj/item/ammo_casing/energy/shot = ammo_type[select] //Necessary to find cost of shot
if(R.cell.use(shot.e_cost)) //Take power from the borg...
- power_supply.give(shot.e_cost) //... to recharge the shot
+ cell.give(shot.e_cost) //... to recharge the shot
if(!chambered)
var/obj/item/ammo_casing/energy/AC = ammo_type[select]
- if(power_supply.charge >= AC.e_cost) //if there's enough power in the power_supply cell...
+ if(cell.charge >= AC.e_cost) //if there's enough power in the cell cell...
chambered = AC //...prepare a new shot based on the current ammo type selected
if(!chambered.BB)
chambered.newshot()
@@ -98,7 +99,7 @@
/obj/item/weapon/gun/energy/process_chamber()
if(chambered && !chambered.BB) //if BB is null, i.e the shot has been fired...
var/obj/item/ammo_casing/energy/shot = chambered
- power_supply.use(shot.e_cost)//... drain the power_supply cell
+ cell.use(shot.e_cost)//... drain the cell cell
chambered = null //either way, released the prepared shot
recharge_newshot() //try to charge a new shot
@@ -117,10 +118,10 @@
return
/obj/item/weapon/gun/energy/update_icon()
- ..()
- if(!automatic_charge_overlays)
- return
- var/ratio = Ceiling((power_supply.charge / power_supply.maxcharge) * charge_sections)
+ ..()
+ if(!automatic_charge_overlays)
+ return
+ var/ratio = Ceiling((cell.charge / cell.maxcharge) * charge_sections)
var/obj/item/ammo_casing/energy/shot = ammo_type[select]
var/iconState = "[icon_state]_charge"
var/itemState = null
@@ -131,16 +132,16 @@
iconState += "_[shot.select_name]"
if(itemState)
itemState += "[shot.select_name]"
- if(power_supply.charge < shot.e_cost)
+ if(cell.charge < shot.e_cost)
add_overlay("[icon_state]_empty")
else
if(!shaded_charge)
- var/mutable_appearance/charge_overlay = mutable_appearance(icon, iconState)
+ var/mutable_appearance/charge_overlay = mutable_appearance(icon, iconState)
for(var/i = ratio, i >= 1, i--)
- charge_overlay.pixel_x = ammo_x_offset * (i - 1)
- add_overlay(charge_overlay)
+ charge_overlay.pixel_x = ammo_x_offset * (i - 1)
+ add_overlay(charge_overlay)
else
- add_overlay("[icon_state]_charge[ratio]")
+ add_overlay("[icon_state]_charge[ratio]")
if(itemState)
itemState += "[ratio]"
item_state = itemState
@@ -156,7 +157,7 @@
user.visible_message("[user] melts [user.p_their()] face off with [src]!")
playsound(loc, fire_sound, 50, 1, -1)
var/obj/item/ammo_casing/energy/shot = ammo_type[select]
- power_supply.use(shot.e_cost)
+ cell.use(shot.e_cost)
update_icon()
return(FIRELOSS)
else
@@ -191,17 +192,17 @@
user.visible_message("[user] tries to light their [A.name] with [src], but it doesn't do anything. Dumbass.")
playsound(user, E.fire_sound, 50, 1)
playsound(user, BB.hitsound, 50, 1)
- power_supply.use(E.e_cost)
+ cell.use(E.e_cost)
. = ""
else if(BB.damage_type != BURN)
user.visible_message("[user] tries to light their [A.name] with [src], but only succeeds in utterly destroying it. Dumbass.")
playsound(user, E.fire_sound, 50, 1)
playsound(user, BB.hitsound, 50, 1)
- power_supply.use(E.e_cost)
+ cell.use(E.e_cost)
qdel(A)
. = ""
else
playsound(user, E.fire_sound, 50, 1)
playsound(user, BB.hitsound, 50, 1)
- power_supply.use(E.e_cost)
+ cell.use(E.e_cost)
. = "[user] casually lights their [A.name] with [src]. Damn."
diff --git a/code/modules/projectiles/guns/energy/kinetic_accelerator.dm b/code/modules/projectiles/guns/energy/kinetic_accelerator.dm
index 89d81d8418..419a715a32 100644
--- a/code/modules/projectiles/guns/energy/kinetic_accelerator.dm
+++ b/code/modules/projectiles/guns/energy/kinetic_accelerator.dm
@@ -98,7 +98,7 @@
empty()
/obj/item/weapon/gun/energy/kinetic_accelerator/proc/empty()
- power_supply.use(500)
+ cell.use(500)
update_icon()
/obj/item/weapon/gun/energy/kinetic_accelerator/proc/attempt_reload(recharge_time)
@@ -125,7 +125,7 @@
return
/obj/item/weapon/gun/energy/kinetic_accelerator/proc/reload()
- power_supply.give(500)
+ cell.give(500)
recharge_newshot(1)
if(!suppressed)
playsound(src.loc, 'sound/weapons/kenetic_reload.ogg', 60, 1)
@@ -163,6 +163,7 @@
range = 3
log_override = TRUE
+ var/pressure_decrease_active = FALSE
var/pressure_decrease = 0.25
var/obj/item/weapon/gun/energy/kinetic_accelerator/kinetic_gun
@@ -179,6 +180,7 @@
if(pressure > 50)
name = "weakened [name]"
damage = damage * pressure_decrease
+ pressure_decrease_active = TRUE
. = ..()
/obj/item/projectile/kinetic/on_range()
@@ -194,7 +196,10 @@
if(!target_turf)
target_turf = get_turf(src)
if(kinetic_gun) //hopefully whoever shot this was not very, very unfortunate.
- for(var/obj/item/borg/upgrade/modkit/M in kinetic_gun.get_modkits())
+ var/list/mods = kinetic_gun.get_modkits()
+ for(var/obj/item/borg/upgrade/modkit/M in mods)
+ M.projectile_strike_predamage(src, target_turf, target, kinetic_gun)
+ for(var/obj/item/borg/upgrade/modkit/M in mods)
M.projectile_strike(src, target_turf, target, kinetic_gun)
if(ismineralturf(target_turf))
var/turf/closed/mineral/M = target_turf
@@ -210,6 +215,7 @@
icon = 'icons/obj/objects.dmi'
icon_state = "modkit"
origin_tech = "programming=2;materials=2;magnets=4"
+ w_class = WEIGHT_CLASS_SMALL
require_module = 1
module_type = /obj/item/weapon/robot_module/miner
var/denied_type = null
@@ -264,6 +270,10 @@
/obj/item/borg/upgrade/modkit/proc/modify_projectile(obj/item/projectile/kinetic/K)
+//use this one for effects you want to trigger before mods that do damage
+/obj/item/borg/upgrade/modkit/proc/projectile_strike_predamage(obj/item/projectile/kinetic/K, turf/target_turf, atom/target, obj/item/weapon/gun/energy/kinetic_accelerator/KA)
+//and this one for things that don't need to trigger before other damage-dealing mods
+
/obj/item/borg/upgrade/modkit/proc/projectile_strike(obj/item/projectile/kinetic/K, turf/target_turf, atom/target, obj/item/weapon/gun/energy/kinetic_accelerator/KA)
//Range
@@ -370,7 +380,7 @@
modifier = -14 //Makes the cooldown 3 seconds(with no cooldown mods) if you miss. Don't miss.
cost = 50
-/obj/item/borg/upgrade/modkit/cooldown/repeater/projectile_strike(obj/item/projectile/kinetic/K, turf/target_turf, atom/target, obj/item/weapon/gun/energy/kinetic_accelerator/KA)
+/obj/item/borg/upgrade/modkit/cooldown/repeater/projectile_strike_predamage(obj/item/projectile/kinetic/K, turf/target_turf, atom/target, obj/item/weapon/gun/energy/kinetic_accelerator/KA)
var/valid_repeat = FALSE
if(isliving(target))
var/mob/living/L = target
@@ -380,7 +390,7 @@
valid_repeat = TRUE
if(valid_repeat)
KA.overheat = FALSE
- KA.attempt_reload(KA.overheat_time * 0.25) //If you hit, the cooldown drops to 0.75 seconds.
+ KA.attempt_reload(KA.overheat_time * 0.25) //If you hit, the cooldown drops to 0.75 seconds.
/obj/item/borg/upgrade/modkit/lifesteal
name = "lifesteal crystal"
@@ -390,7 +400,7 @@
cost = 20
var/static/list/damage_heal_order = list(BRUTE, BURN, OXY)
-/obj/item/borg/upgrade/modkit/lifesteal/projectile_strike(obj/item/projectile/kinetic/K, turf/target_turf, atom/target, obj/item/weapon/gun/energy/kinetic_accelerator/KA)
+/obj/item/borg/upgrade/modkit/lifesteal/projectile_strike_predamage(obj/item/projectile/kinetic/K, turf/target_turf, atom/target, obj/item/weapon/gun/energy/kinetic_accelerator/KA)
if(isliving(target) && isliving(K.firer))
var/mob/living/L = target
if(L.stat == DEAD)
@@ -414,6 +424,43 @@
return
new /obj/effect/temp_visual/resonance(target_turf, K.firer, null, 30)
+/obj/item/borg/upgrade/modkit/bounty
+ name = "death syphon"
+ desc = "Killing or assisting in killing a creature permenantly increases your damage against that type of creature."
+ denied_type = /obj/item/borg/upgrade/modkit/bounty
+ modifier = 1.25
+ cost = 30
+ var/maximum_bounty = 25
+ var/list/bounties_reaped = list()
+
+/obj/item/borg/upgrade/modkit/bounty/projectile_strike(obj/item/projectile/kinetic/K, turf/target_turf, atom/target, obj/item/weapon/gun/energy/kinetic_accelerator/KA)
+ if(isliving(target))
+ var/mob/living/L = target
+ var/list/existing_marks = L.has_status_effect_list(STATUS_EFFECT_SYPHONMARK)
+ for(var/i in existing_marks)
+ var/datum/status_effect/syphon_mark/SM = i
+ if(SM.reward_target == src) //we want to allow multiple people with bounty modkits to use them, but we need to replace our own marks so we don't multi-reward
+ SM.reward_target = null
+ qdel(SM)
+ var/datum/status_effect/syphon_mark/SM = L.apply_status_effect(STATUS_EFFECT_SYPHONMARK)
+ SM.reward_target = src
+ if(bounties_reaped[L.type])
+ var/kill_modifier = 1
+ if(K.pressure_decrease_active)
+ kill_modifier *= K.pressure_decrease
+ var/armor = L.run_armor_check(K.def_zone, K.flag, "", "", K.armour_penetration)
+ L.apply_damage(bounties_reaped[L.type]*kill_modifier, K.damage_type, K.def_zone, armor)
+
+/obj/item/borg/upgrade/modkit/bounty/proc/get_kill(mob/living/L)
+ var/bonus_mod = 1
+ if(ismegafauna(L)) //megafauna reward
+ bonus_mod = 4
+ if(!bounties_reaped[L.type])
+ bounties_reaped[L.type] = min(modifier * bonus_mod, maximum_bounty)
+ else
+ bounties_reaped[L.type] = min(bounties_reaped[L.type] + (modifier * bonus_mod), maximum_bounty)
+
+
//Indoors
/obj/item/borg/upgrade/modkit/indoors
name = "decrease pressure penalty"
diff --git a/code/modules/projectiles/guns/energy/special.dm b/code/modules/projectiles/guns/energy/special.dm
index a8ae4da97a..f6841d6bf9 100644
--- a/code/modules/projectiles/guns/energy/special.dm
+++ b/code/modules/projectiles/guns/energy/special.dm
@@ -39,7 +39,7 @@
/obj/item/weapon/gun/energy/decloner/update_icon()
..()
var/obj/item/ammo_casing/energy/shot = ammo_type[select]
- if(power_supply.charge > shot.e_cost)
+ if(cell.charge > shot.e_cost)
add_overlay("decloner_spin")
/obj/item/weapon/gun/energy/floragun
@@ -137,19 +137,19 @@
/obj/item/weapon/gun/energy/plasmacutter/examine(mob/user)
..()
- if(power_supply)
- to_chat(user, "[src] is [round(power_supply.percent())]% charged.")
+ if(cell)
+ to_chat(user, "[src] is [round(cell.percent())]% charged.")
/obj/item/weapon/gun/energy/plasmacutter/attackby(obj/item/A, mob/user)
if(istype(A, /obj/item/stack/sheet/mineral/plasma))
var/obj/item/stack/sheet/S = A
S.use(1)
- power_supply.give(1000)
+ cell.give(1000)
recharge_newshot(1)
to_chat(user, "You insert [A] in [src], recharging it.")
else if(istype(A, /obj/item/weapon/ore/plasma))
qdel(A)
- power_supply.give(500)
+ cell.give(500)
recharge_newshot(1)
to_chat(user, "You insert [A] in [src], recharging it.")
else
diff --git a/code/modules/projectiles/projectile.dm b/code/modules/projectiles/projectile.dm
index 8c810155db..d051ec0221 100644
--- a/code/modules/projectiles/projectile.dm
+++ b/code/modules/projectiles/projectile.dm
@@ -78,7 +78,7 @@
return "chest"
/obj/item/projectile/proc/prehit(atom/target)
- return
+ return TRUE
/obj/item/projectile/proc/on_hit(atom/target, blocked = 0)
var/turf/target_loca = get_turf(target)
@@ -142,7 +142,7 @@
if(firer && !ricochets)
if(A == firer || (A == firer.loc && istype(A, /obj/mecha))) //cannot shoot yourself or your mech
loc = A.loc
- return 0
+ return FALSE
var/distance = get_dist(get_turf(A), starting) // Get the distance between the turf shot from and the mob we hit and use that for the calculations.
def_zone = ran_zone(def_zone, max(100-(7*distance), 5)) //Lower accurancy/longer range tradeoff. 7 is a balanced number to use.
@@ -155,13 +155,14 @@
var/turf/target_turf = get_turf(A)
- prehit(A)
+ if(!prehit(A))
+ return FALSE
var/permutation = A.bullet_act(src, def_zone) // searches for return value, could be deleted after run so check A isn't null
if(permutation == -1 || forcedodge)// the bullet passes through a dense object!
loc = target_turf
if(A)
permutated.Add(A)
- return 0
+ return FALSE
else
if(A && A.density && !ismob(A) && !(A.flags & ON_BORDER)) //if we hit a dense non-border obj or dense turf then we also hit one of the mobs on that tile.
var/list/mobs_list = list()
@@ -169,9 +170,11 @@
mobs_list += L
if(mobs_list.len)
var/mob/living/picked_mob = pick(mobs_list)
- prehit(picked_mob)
+ if(!prehit(picked_mob))
+ return FALSE
picked_mob.bullet_act(src, def_zone)
qdel(src)
+ return TRUE
/obj/item/projectile/proc/check_ricochet()
if(prob(ricochet_chance))
@@ -277,46 +280,53 @@
Range()
sleep(config.run_speed * 0.9)
-
/obj/item/projectile/proc/preparePixelProjectile(atom/target, var/turf/targloc, mob/living/user, params, spread)
var/turf/curloc = get_turf(user)
- src.loc = get_turf(user)
- src.starting = get_turf(user)
- src.current = curloc
- src.yo = targloc.y - curloc.y
- src.xo = targloc.x - curloc.x
+ forceMove(get_turf(user))
+ starting = get_turf(user)
+ current = curloc
+ yo = targloc.y - curloc.y
+ xo = targloc.x - curloc.x
- if(params)
- var/list/mouse_control = params2list(params)
- if(mouse_control["icon-x"])
- src.p_x = text2num(mouse_control["icon-x"])
- if(mouse_control["icon-y"])
- src.p_y = text2num(mouse_control["icon-y"])
- if(mouse_control["screen-loc"])
- //Split screen-loc up into X+Pixel_X and Y+Pixel_Y
- var/list/screen_loc_params = splittext(mouse_control["screen-loc"], ",")
+ var/list/calculated = calculate_projectile_angle_and_pixel_offsets(user, params)
+ Angle = calculated[1]
+ p_x = calculated[2]
+ p_y = calculated[3]
- //Split X+Pixel_X up into list(X, Pixel_X)
- var/list/screen_loc_X = splittext(screen_loc_params[1],":")
-
- //Split Y+Pixel_Y up into list(Y, Pixel_Y)
- var/list/screen_loc_Y = splittext(screen_loc_params[2],":")
- // to_chat(world, "X: [screen_loc_X[1]] PixelX: [screen_loc_X[2]] / Y: [screen_loc_Y[1]] PixelY: [screen_loc_Y[2]]")
- var/x = text2num(screen_loc_X[1]) * 32 + text2num(screen_loc_X[2]) - 32
- var/y = text2num(screen_loc_Y[1]) * 32 + text2num(screen_loc_Y[2]) - 32
-
- //Calculate the "resolution" of screen based on client's view and world's icon size. This will work if the user can view more tiles than average.
- var/screenview = (user.client.view * 2 + 1) * world.icon_size //Refer to http://www.byond.com/docs/ref/info.html#/client/var/view for mad maths
-
- var/ox = round(screenview/2) //"origin" x
- var/oy = round(screenview/2) //"origin" y
- // to_chat(world, "Pixel position: [x] [y]")
- var/angle = Atan2(y - oy, x - ox)
- // to_chat(world, "Angle: [angle]")
- src.Angle = angle
if(spread)
src.Angle += spread
+/proc/calculate_projectile_angle_and_pixel_offsets(mob/user, params)
+ var/list/mouse_control = params2list(params)
+ var/p_x = 0
+ var/p_y = 0
+ var/angle = 0
+ if(mouse_control["icon-x"])
+ p_x = text2num(mouse_control["icon-x"])
+ if(mouse_control["icon-y"])
+ p_y = text2num(mouse_control["icon-y"])
+ if(mouse_control["screen-loc"])
+ //Split screen-loc up into X+Pixel_X and Y+Pixel_Y
+ var/list/screen_loc_params = splittext(mouse_control["screen-loc"], ",")
+
+ //Split X+Pixel_X up into list(X, Pixel_X)
+ var/list/screen_loc_X = splittext(screen_loc_params[1],":")
+
+ //Split Y+Pixel_Y up into list(Y, Pixel_Y)
+ var/list/screen_loc_Y = splittext(screen_loc_params[2],":")
+ // to_chat(world, "X: [screen_loc_X[1]] PixelX: [screen_loc_X[2]] / Y: [screen_loc_Y[1]] PixelY: [screen_loc_Y[2]]")
+ var/x = text2num(screen_loc_X[1]) * 32 + text2num(screen_loc_X[2]) - 32
+ var/y = text2num(screen_loc_Y[1]) * 32 + text2num(screen_loc_Y[2]) - 32
+
+ //Calculate the "resolution" of screen based on client's view and world's icon size. This will work if the user can view more tiles than average.
+ var/screenview = (user.client.view * 2 + 1) * world.icon_size //Refer to http://www.byond.com/docs/ref/info.html#/client/var/view for mad maths
+
+ var/ox = round(screenview/2) - user.client.pixel_x //"origin" x
+ var/oy = round(screenview/2) - user.client.pixel_y //"origin" y
+ // to_chat(world, "Pixel position: [x] [y]")
+ angle = Atan2(y - oy, x - ox)
+ // to_chat(world, "Angle: [angle]")
+ return list(angle, p_x, p_y)
/obj/item/projectile/Crossed(atom/movable/AM) //A mob moving on a tile with a projectile is hit by it.
..()
diff --git a/code/modules/reagents/chemistry/machinery/chem_dispenser.dm b/code/modules/reagents/chemistry/machinery/chem_dispenser.dm
index 428d1fc114..1f5085ae09 100644
--- a/code/modules/reagents/chemistry/machinery/chem_dispenser.dm
+++ b/code/modules/reagents/chemistry/machinery/chem_dispenser.dm
@@ -9,8 +9,9 @@
idle_power_usage = 40
interact_offline = 1
resistance_flags = FIRE_PROOF | ACID_PROOF
- var/energy = 100
- var/max_energy = 100
+ var/cell_type = /obj/item/weapon/stock_parts/cell/high
+ var/obj/item/weapon/stock_parts/cell/cell
+ var/powerefficiency = 0.01
var/amount = 30
var/recharged = 0
var/recharge_delay = 5
@@ -54,6 +55,7 @@
/obj/machinery/chem_dispenser/Initialize()
. = ..()
+ cell = new cell_type
recharge()
dispensable_reagents = sortList(dispensable_reagents)
@@ -66,11 +68,8 @@
recharged -= 1
/obj/machinery/chem_dispenser/proc/recharge()
- if(stat & (BROKEN|NOPOWER)) return
- var/addenergy = 1
- var/oldenergy = energy
- energy = min(energy + addenergy, max_energy)
- if(energy != oldenergy)
+ var/usedpower = cell.give( 1 / powerefficiency) //Should always be a gain of one on the UI.
+ if(usedpower)
use_power(2500)
/obj/machinery/chem_dispenser/emag_act(mob/user)
@@ -106,8 +105,8 @@
/obj/machinery/chem_dispenser/ui_data()
var/data = list()
data["amount"] = amount
- data["energy"] = energy
- data["maxEnergy"] = max_energy
+ data["energy"] = cell.charge ? cell.charge * powerefficiency : "0" //To prevent NaN in the UI.
+ data["maxEnergy"] = cell.maxcharge * powerefficiency
data["isBeakerLoaded"] = beaker ? 1 : 0
var beakerContents[0]
@@ -149,10 +148,10 @@
if(beaker && dispensable_reagents.Find(reagent))
var/datum/reagents/R = beaker.reagents
var/free = R.maximum_volume - R.total_volume
- var/actual = min(amount, energy * 10, free)
+ var/actual = min(amount, (cell.charge * powerefficiency)*10, free)
R.add_reagent(reagent, actual)
- energy = max(energy - actual / 10, 0)
+ cell.use((actual / 10) / powerefficiency)
. = TRUE
if("remove")
var/amount = text2num(params["amount"])
@@ -189,15 +188,36 @@
add_overlay(beaker_overlay)
else if(user.a_intent != INTENT_HARM && !istype(I, /obj/item/weapon/card/emag))
to_chat(user, "You can't load \the [I] into the machine!")
+ return ..()
else
return ..()
+/obj/machinery/chem_dispenser/get_cell()
+ return cell
+
+/obj/machinery/chem_dispenser/emp_act(severity)
+ var/list/datum/reagents/R = list()
+ var/total = min(rand(7,15), Floor(cell.charge*powerefficiency))
+ var/datum/reagents/Q = new(total*10)
+ if(beaker && beaker.reagents)
+ R += beaker.reagents
+ for(var/i in 1 to total)
+ Q.add_reagent(pick(dispensable_reagents), 10)
+ R += Q
+ chem_splash(get_turf(src), 3, R)
+ if(beaker && beaker.reagents)
+ beaker.reagents.remove_all()
+ cell.use(total/powerefficiency)
+ cell.emp_act()
+ visible_message(" The [src] malfunctions, spraying chemicals everywhere!")
+ ..()
+
+
/obj/machinery/chem_dispenser/constructable
name = "portable chem dispenser"
icon = 'icons/obj/chemical.dmi'
icon_state = "minidispenser"
- energy = 10
- max_energy = 10
+ powerefficiency = 0.001
amount = 5
recharge_delay = 30
dispensable_reagents = list()
@@ -263,16 +283,13 @@
/obj/machinery/chem_dispenser/constructable/RefreshParts()
var/time = 0
- var/temp_energy = 0
var/i
+ for(var/obj/item/weapon/stock_parts/cell/P in component_parts)
+ cell = P
for(var/obj/item/weapon/stock_parts/matter_bin/M in component_parts)
- temp_energy += M.rating
- temp_energy--
- max_energy = temp_energy * 5 //max energy = (bin1.rating + bin2.rating - 1) * 5, 5 on lowest 25 on highest
+ time += M.rating
for(var/obj/item/weapon/stock_parts/capacitor/C in component_parts)
time += C.rating
- for(var/obj/item/weapon/stock_parts/cell/P in component_parts)
- time += round(P.maxcharge, 10000) / 10000
recharge_delay /= time/2 //delay between recharges, double the usual time on lowest 50% less than usual on highest
for(var/obj/item/weapon/stock_parts/manipulator/M in component_parts)
for(i=1, i<=M.rating, i++)
diff --git a/code/modules/reagents/reagent_containers/pill.dm b/code/modules/reagents/reagent_containers/pill.dm
index b6bc9b2ccf..37a91e6a88 100644
--- a/code/modules/reagents/reagent_containers/pill.dm
+++ b/code/modules/reagents/reagent_containers/pill.dm
@@ -11,8 +11,8 @@
var/roundstart = 0
var/self_delay = 0 //pills are instant, this is because patches inheret their aplication from pills
-/obj/item/weapon/reagent_containers/pill/Initialize()
- . = ..()
+/obj/item/weapon/reagent_containers/pill/Initialize()
+ . = ..()
if(!icon_state)
icon_state = "pill[rand(1,20)]"
if(reagents.total_volume && roundstart)
@@ -142,3 +142,10 @@
icon_state = "pill18"
list_reagents = list("insulin" = 50)
roundstart = 1
+
+/obj/item/weapon/reagent_containers/pill/shadowtoxin
+ name = "black pill"
+ desc = "I wouldn't eat this if I were you."
+ icon_state = "pill9"
+ color = "#454545"
+ list_reagents = list("shadowmutationtoxin" = 1)
diff --git a/code/modules/research/designs/medical_designs.dm b/code/modules/research/designs/medical_designs.dm
index e5b872f5a5..3e06781304 100644
--- a/code/modules/research/designs/medical_designs.dm
+++ b/code/modules/research/designs/medical_designs.dm
@@ -190,6 +190,18 @@
build_path = /obj/item/organ/eyes/robotic/shield
category = list("Misc", "Medical Designs")
+/datum/design/cyberimp_gloweyes
+ name = "Luminescent Eyes"
+ desc = "A pair of cybernetic eyes that can emit multicolored light"
+ id = "ci-gloweyes"
+ req_tech = list("materials" = 3, "biotech" = 3, "engineering" = 4)
+ build_type = PROTOLATHE | MECHFAB
+ construction_time = 40
+ materials = list(MAT_METAL = 600, MAT_GLASS = 1000)
+ build_path = /obj/item/organ/eyes/robotic/glow
+ category = list("Misc", "Medical Designs")
+
+
/datum/design/cyberimp_breather
name = "Breathing Tube Implant"
desc = "This simple implant adds an internals connector to your back, allowing you to use internals without a mask and protecting you from being choked."
diff --git a/code/modules/research/designs/power_designs.dm b/code/modules/research/designs/power_designs.dm
index f03bb8f3e9..393e64bd0d 100644
--- a/code/modules/research/designs/power_designs.dm
+++ b/code/modules/research/designs/power_designs.dm
@@ -68,6 +68,17 @@
build_path = /obj/item/device/lightreplacer
category = list("Power Designs")
+/datum/design/inducer
+ name = "Inducer"
+ desc = "The NT-75 Electromagnetic Power Inducer can wirelessly induce electric charge in an object, allowing you to recharge power cells without having to remove them."
+ id = "inducer"
+ req_tech = list("powerstorage" = 4, "engineering" = 4, "magnets" = 4)
+ build_type = PROTOLATHE
+ materials = list(MAT_METAL = 3000, MAT_GLASS = 1000)
+ build_path = /obj/item/weapon/inducer/sci
+ category = list("Power Designs")
+
+
/datum/design/board/pacman
name = "Machine Design (PACMAN-type Generator Board)"
desc = "The circuit board that for a PACMAN-type portable generator."
diff --git a/code/modules/ruins/lavaland_ruin_code.dm b/code/modules/ruins/lavaland_ruin_code.dm
index 00011729e0..16f7d27df0 100644
--- a/code/modules/ruins/lavaland_ruin_code.dm
+++ b/code/modules/ruins/lavaland_ruin_code.dm
@@ -133,8 +133,8 @@
death = FALSE
icon = 'icons/obj/Cryogenic2.dmi'
icon_state = "sleeper"
- flavour_text = "You are a syndicate agent, employed in a top secret research facility developing biological weapons. Unfortunately, your hated enemy, Nanotrasen, has begun mining in this sector. Continue your research as best you can, and try to keep a low profile. Do not abandon the base without good cause. The base is rigged with explosives should the worst happen, do not let the base fall into enemy hands!"
id_access_list = list(GLOB.access_syndicate)
+ flavour_text = "You are a syndicate agent, employed in a top secret research facility developing biological weapons. Unfortunately, your hated enemy, Nanotrasen, has begun mining in this sector. Continue your research as best you can, and try to keep a low profile. DON'T abandon the base without good cause. The base is rigged with explosives should the worst happen, do not let the base fall into enemy hands!"
faction = list("syndicate")
outfit = /datum/outfit/lavaland_syndicate
@@ -153,7 +153,7 @@
/obj/effect/mob_spawn/human/lavaland_syndicate/comms
name = "Syndicate Comms Agent"
- flavour_text = "You are a syndicate agent, employed in a top secret research facility developing biological weapons. Unfortunately, your hated enemy, Nanotrasen, has begun mining in this sector. Monitor enemy activity as best you can, and try to keep a low profile. Do not abandon the base without good cause. Use the communication equipment to provide support to any field agents, and sow disinformation to throw Nanotrasen off your trail. Do not let the base fall into enemy hands!"
+ flavour_text = "You are a syndicate agent, employed in a top secret research facility developing biological weapons. Unfortunately, your hated enemy, Nanotrasen, has begun mining in this sector. Monitor enemy activity as best you can, and try to keep a low profile. DON'T abandon the base without good cause. Use the communication equipment to provide support to any field agents, and sow disinformation to throw Nanotrasen off your trail. Do not let the base fall into enemy hands!"
outfit = /datum/outfit/lavaland_syndicate/comms
/datum/outfit/lavaland_syndicate/comms
diff --git a/code/modules/spells/spell_types/rod_form.dm b/code/modules/spells/spell_types/rod_form.dm
index a3754e6a7d..8fc3f34fc4 100644
--- a/code/modules/spells/spell_types/rod_form.dm
+++ b/code/modules/spells/spell_types/rod_form.dm
@@ -17,6 +17,7 @@
var/obj/effect/immovablerod/wizard/W = new(start, get_ranged_target_turf(M, M.dir, (15 + spell_level * 3)))
W.wizard = M
W.max_distance += spell_level * 3 //You travel farther when you upgrade the spell
+ W.damage_bonus += spell_level * 20 //You do more damage when you upgrade the spell
W.start_turf = start
M.forceMove(W)
M.notransform = 1
@@ -26,6 +27,7 @@
/obj/effect/immovablerod/wizard
var/max_distance = 13
+ var/damage_bonus = 0
var/mob/living/wizard
var/turf/start_turf
notify = FALSE
@@ -41,3 +43,7 @@
wizard.notransform = 0
wizard.forceMove(get_turf(src))
return ..()
+
+/obj/effect/immovablerod/wizard/penetrate(mob/living/L)
+ L.visible_message("[L] is penetrated by an immovable rod!" , "The rod penetrates you!" , "You hear a CLANG!")
+ L.adjustBruteLoss(70 + damage_bonus)
diff --git a/code/modules/surgery/organs/eyes.dm b/code/modules/surgery/organs/eyes.dm
index 83b70d33d9..f91ef8f547 100644
--- a/code/modules/surgery/organs/eyes.dm
+++ b/code/modules/surgery/organs/eyes.dm
@@ -132,3 +132,176 @@
/obj/item/organ/eyes/robotic/shield/emp_act(severity)
return
+
+#define RGB2EYECOLORSTRING(definitionvar) ("[copytext(definitionvar,2,3)][copytext(definitionvar,4,5)][copytext(definitionvar,6,7)]")
+
+/obj/item/organ/eyes/robotic/glow
+ name = "High Luminosity Eyes"
+ desc = "Special glowing eyes, used by snowflakes who want to be special."
+ origin_tech = "material=3;biotech=3;engineering=3;magnets=4"
+ eye_color = "000"
+ actions_types = list(/datum/action/item_action/organ_action/use, /datum/action/item_action/organ_action/toggle)
+ var/current_color_string = "#ffffff"
+ var/active = FALSE
+ var/max_light_beam_distance = 5
+ var/light_beam_distance = 5
+ var/light_object_range = 1
+ var/light_object_power = 2
+ var/list/obj/effect/abstract/eye_lighting/eye_lighting
+ var/obj/effect/abstract/eye_lighting/on_mob
+ var/image/mob_overlay
+
+/obj/item/organ/eyes/robotic/glow/Initialize()
+ . = ..()
+ mob_overlay = image('icons/mob/human_face.dmi', "eyes_glow_gs")
+
+/obj/item/organ/eyes/robotic/glow/Destroy()
+ terminate_effects()
+ . = ..()
+
+/obj/item/organ/eyes/robotic/glow/Remove()
+ terminate_effects()
+ . = ..()
+
+/obj/item/organ/eyes/robotic/glow/proc/terminate_effects()
+ if(owner && active)
+ deactivate()
+ active = FALSE
+ clear_visuals(TRUE)
+ STOP_PROCESSING(SSfastprocess, src)
+
+/obj/item/organ/eyes/robotic/glow/ui_action_click(owner, action)
+ if(istype(action, /datum/action/item_action/organ_action/toggle))
+ toggle_active()
+ else if(istype(action, /datum/action/item_action/organ_action/use))
+ prompt_for_controls(owner)
+
+/obj/item/organ/eyes/robotic/glow/proc/toggle_active()
+ if(active)
+ deactivate()
+ else
+ activate()
+
+/obj/item/organ/eyes/robotic/glow/proc/prompt_for_controls(mob/user)
+ var/C = input(owner, "Select Color", "Select color", "#ffffff") as null|color
+ if(!C || QDELETED(src) || QDELETED(user) || QDELETED(owner) || owner != user)
+ return
+ var/range = input(user, "Enter range (0 - [max_light_beam_distance])", "Range Select", 0) as null|num
+
+ set_distance(Clamp(range, 0, max_light_beam_distance))
+ assume_rgb(C)
+
+/obj/item/organ/eyes/robotic/glow/proc/assume_rgb(newcolor)
+ current_color_string = newcolor
+ eye_color = RGB2EYECOLORSTRING(current_color_string)
+ sync_light_effects()
+ cycle_mob_overlay()
+ if(!QDELETED(owner) && ishuman(owner)) //Other carbon mobs don't have eye color.
+ owner.dna.species.handle_body(owner)
+
+/obj/item/organ/eyes/robotic/glow/proc/cycle_mob_overlay()
+ remove_mob_overlay()
+ mob_overlay.color = current_color_string
+ add_mob_overlay()
+
+/obj/item/organ/eyes/robotic/glow/proc/add_mob_overlay()
+ if(!QDELETED(owner))
+ owner.add_overlay(mob_overlay)
+
+/obj/item/organ/eyes/robotic/glow/proc/remove_mob_overlay()
+ if(!QDELETED(owner))
+ owner.cut_overlay(mob_overlay)
+
+/obj/item/organ/eyes/robotic/glow/emp_act()
+ if(active)
+ deactivate(silent = TRUE)
+
+/obj/item/organ/eyes/robotic/glow/on_mob_move()
+ if(QDELETED(owner) || !active)
+ return
+ update_visuals()
+
+/obj/item/organ/eyes/robotic/glow/on_mob_turn()
+ if(QDELETED(owner) || !active)
+ return
+ update_visuals()
+
+/obj/item/organ/eyes/robotic/glow/proc/activate(silent = FALSE)
+ start_visuals()
+ if(!silent)
+ to_chat(owner, "Your [src] clicks and makes a whining noise, before shooting out a beam of light!")
+ active = TRUE
+ cycle_mob_overlay()
+
+/obj/item/organ/eyes/robotic/glow/proc/deactivate(silent = FALSE)
+ clear_visuals()
+ if(!silent)
+ to_chat(owner, "Your [src] shuts off!")
+ active = FALSE
+ remove_mob_overlay()
+
+/obj/item/organ/eyes/robotic/glow/proc/update_visuals()
+ if((LAZYLEN(eye_lighting) < light_beam_distance) || !on_mob)
+ regenerate_light_effects()
+ var/turf/scanfrom = get_turf(owner)
+ var/scandir = owner.dir
+ if(!istype(scanfrom))
+ clear_visuals()
+ var/turf/scanning = scanfrom
+ var/stop = FALSE
+ on_mob.forceMove(scanning)
+ for(var/i in 1 to light_beam_distance)
+ scanning = get_step(scanning, scandir)
+ if(scanning.opacity || scanning.has_opaque_atom)
+ stop = TRUE
+ var/obj/effect/abstract/eye_lighting/L = LAZYACCESS(eye_lighting, i)
+ if(stop)
+ L.forceMove(src)
+ else
+ L.forceMove(scanning)
+
+/obj/item/organ/eyes/robotic/glow/proc/clear_visuals(delete_everything = FALSE)
+ if(delete_everything)
+ QDEL_LIST(eye_lighting)
+ QDEL_NULL(on_mob)
+ else
+ for(var/i in eye_lighting)
+ var/obj/effect/abstract/eye_lighting/L = i
+ L.forceMove(src)
+ if(!QDELETED(on_mob))
+ on_mob.forceMove(src)
+
+/obj/item/organ/eyes/robotic/glow/proc/start_visuals()
+ if(!islist(eye_lighting))
+ regenerate_light_effects()
+ if((eye_lighting.len < light_beam_distance) || !on_mob)
+ regenerate_light_effects()
+ sync_light_effects()
+ update_visuals()
+
+/obj/item/organ/eyes/robotic/glow/proc/set_distance(dist)
+ light_beam_distance = dist
+ regenerate_light_effects()
+
+/obj/item/organ/eyes/robotic/glow/proc/regenerate_light_effects()
+ clear_visuals(TRUE)
+ on_mob = new(src)
+ for(var/i in 1 to light_beam_distance)
+ LAZYADD(eye_lighting,new /obj/effect/abstract/eye_lighting(src))
+ sync_light_effects()
+
+/obj/item/organ/eyes/robotic/glow/proc/sync_light_effects()
+ for(var/I in eye_lighting)
+ var/obj/effect/abstract/eye_lighting/L = I
+ L.set_light(light_object_range, light_object_power, current_color_string)
+ if(on_mob)
+ on_mob.set_light(1, 1, current_color_string)
+
+/obj/effect/abstract/eye_lighting
+ var/obj/item/organ/eyes/robotic/glow/parent
+
+/obj/effect/abstract/eye_lighting/Initialize()
+ . = ..()
+ parent = loc
+ if(!istype(parent))
+ return INITIALIZE_HINT_QDEL
diff --git a/code/world.dm b/code/world.dm
index b7beb52d4d..4800975f6b 100644
--- a/code/world.dm
+++ b/code/world.dm
@@ -34,7 +34,7 @@
load_motd()
load_admins()
// load_mentors()
- load_menu()
+ LoadVerbs(/datum/verbs/menu)
if(config.usewhitelist)
load_whitelist()
LoadBans()
diff --git a/icons/mob/actions.dmi b/icons/mob/actions.dmi
index c8fc98d4f5..214bfd744e 100644
Binary files a/icons/mob/actions.dmi and b/icons/mob/actions.dmi differ
diff --git a/icons/mob/human_face.dmi b/icons/mob/human_face.dmi
index e1dbb99158..1d8098c92b 100644
Binary files a/icons/mob/human_face.dmi and b/icons/mob/human_face.dmi differ
diff --git a/icons/mob/inhands/items_lefthand.dmi b/icons/mob/inhands/items_lefthand.dmi
index a20439dea2..d08290d169 100644
Binary files a/icons/mob/inhands/items_lefthand.dmi and b/icons/mob/inhands/items_lefthand.dmi differ
diff --git a/icons/mob/inhands/items_righthand.dmi b/icons/mob/inhands/items_righthand.dmi
index aba22012b2..067b42575e 100644
Binary files a/icons/mob/inhands/items_righthand.dmi and b/icons/mob/inhands/items_righthand.dmi differ
diff --git a/icons/obj/clockwork_objects.dmi b/icons/obj/clockwork_objects.dmi
index a7c80ba536..02e0743593 100644
Binary files a/icons/obj/clockwork_objects.dmi and b/icons/obj/clockwork_objects.dmi differ
diff --git a/icons/obj/lavaland/artefacts.dmi b/icons/obj/lavaland/artefacts.dmi
index 41c1ba56cd..0deead024a 100644
Binary files a/icons/obj/lavaland/artefacts.dmi and b/icons/obj/lavaland/artefacts.dmi differ
diff --git a/icons/obj/tools.dmi b/icons/obj/tools.dmi
index cd0d3f835e..0cff456af6 100644
Binary files a/icons/obj/tools.dmi and b/icons/obj/tools.dmi differ
diff --git a/interface/menu.dm b/interface/menu.dm
index 4bebd5b202..a2220d529f 100644
--- a/interface/menu.dm
+++ b/interface/menu.dm
@@ -1,5 +1,5 @@
/*
-/datum/menu/Example/verb/Example()
+/datum/verbs/menu/Example/verb/Example()
set name = "" //if this starts with @ the verb is not created and name becomes the command to invoke.
set desc = "" //desc is the text given to this entry in the menu
//You can not use src in these verbs. It will be the menu at compile time, but the client at runtime.
@@ -7,126 +7,44 @@
GLOBAL_LIST_EMPTY(menulist)
-/world/proc/load_menu()
- for (var/typepath in subtypesof(/datum/menu))
- new typepath()
-
-/datum/menu
- var/name
- var/list/children
- var/datum/menu/myparent
- var/list/verblist
+/datum/verbs/menu
var/checkbox = CHECKBOX_NONE //checkbox type.
var/default //default checked type.
//Set to true to append our children to our parent,
//Rather then add us as a node (used for having more then one checkgroups in the same menu)
- var/abstract = FALSE
-/datum/menu/New()
- var/ourentry = GLOB.menulist[type]
- children = list()
- verblist = list()
- if (ourentry)
- if (islist(ourentry)) //some of our childern already loaded
- Add_children(ourentry)
- else
- stack_trace("Menu item double load: [type]")
- qdel(src)
- return
+/datum/verbs/menu/GetList()
+ return GLOB.menulist
- GLOB.menulist[type] = src
+/datum/verbs/menu/Generate_list()
+ . = ..()
+ for(var/I in .)
+ .[I] = list2params(.[I])
- Load_verbs(type, typesof("[type]/verb"))
+/datum/verbs/menu/HandleVerb(list/entry, verbpath, client/C)
+ var/datum/verbs/menu/verb_true_parent = GLOB.menulist[verblist[verbpath]]
+ var/true_checkbox = verb_true_parent.checkbox
+ if (true_checkbox != CHECKBOX_NONE)
+ var/checkedverb = verb_true_parent.Get_checked(C)
+ if (true_checkbox == CHECKBOX_GROUP)
+ if (verbpath == checkedverb)
+ entry["is-checked"] = TRUE
+ else
+ entry["is-checked"] = FALSE
+ else if (true_checkbox == CHECKBOX_TOGGLE)
+ entry["is-checked"] = checkedverb
- var/datum/menu/parent = GLOB.menulist[parent_type]
- if (!parent)
- GLOB.menulist[parent_type] = list(src)
- else if (islist(parent))
- parent += src
- else
- parent.Add_children(list(src))
+ entry["command"] = ".updatemenuchecked \"[verb_true_parent.type]\" \"[verbpath]\"\n[entry["command"]]"
+ entry["can-check"] = TRUE
+ entry["group"] = "[verb_true_parent.type]"
-/datum/menu/proc/Set_parent(datum/menu/parent)
- myparent = parent
- if (abstract)
- myparent.Add_children(children)
- var/list/verblistoftypes = list()
- for(var/thing in verblist)
- LAZYADD(verblistoftypes[verblist[thing]], thing)
-
- for(var/verbparenttype in verblistoftypes)
- myparent.Load_verbs(verbparenttype, verblistoftypes[verbparenttype])
-
-/datum/menu/proc/Add_children(list/kids)
- if (abstract && myparent)
- myparent.Add_children(kids)
- return
-
- for(var/thing in kids)
- var/datum/menu/menuitem = thing
- menuitem.Set_parent(src)
- if (!menuitem.abstract)
- children += menuitem
-
-/datum/menu/proc/Load_verbs(verb_parent_type, list/verbs)
- if (abstract && myparent)
- myparent.Load_verbs(verb_parent_type, verbs)
- return
-
- for (var/verbpath in verbs)
- verblist[verbpath] = verb_parent_type
-
-/datum/menu/proc/Generate_list(client/C)
- . = list()
- if (length(children))
- for (var/thing in children)
- var/datum/menu/child = thing
- var/list/childlist = child.Generate_list(C)
- if (childlist)
- var/childname = "[child]"
- if (childname == "[child.type]")
- var/list/tree = splittext(childname, "/")
- childname = tree[tree.len]
- .[child.type] = "parent=[url_encode(type)];name=[url_encode(childname)]"
- . += childlist
-
-
-
- for (var/thing in verblist)
- var/atom/verb/verbpath = thing
- if (!verbpath)
- stack_trace("Bad VERB in [type] verblist: [english_list(verblist)]")
- var/list/entry = list()
- entry["parent"] = "[type]"
- entry["name"] = verbpath.desc
- if (copytext(verbpath.name,1,2) == "@")
- entry["command"] = copytext(verbpath.name,2)
- else
- entry["command"] = replacetext(verbpath.name, " ", "-")
- var/datum/menu/verb_true_parent = GLOB.menulist[verblist[verbpath]]
- var/true_checkbox = verb_true_parent.checkbox
- if (true_checkbox != CHECKBOX_NONE)
- var/checkedverb = verb_true_parent.Get_checked(C)
- if (true_checkbox == CHECKBOX_GROUP)
- if (verbpath == checkedverb)
- entry["is-checked"] = TRUE
- else
- entry["is-checked"] = FALSE
- else if (true_checkbox == CHECKBOX_TOGGLE)
- entry["is-checked"] = checkedverb
-
- entry["command"] = ".updatemenuchecked \"[verb_true_parent.type]\" \"[verbpath]\"\n[entry["command"]]"
- entry["can-check"] = TRUE
- entry["group"] = "[verb_true_parent.type]"
- .[verbpath] = list2params(entry)
-
-/datum/menu/proc/Get_checked(client/C)
+/datum/verbs/menu/proc/Get_checked(client/C)
return C.prefs.menuoptions[type] || default || FALSE
-/datum/menu/proc/Load_checked(client/C) //Loads the checked menu item into a new client. Used by icon menus to invoke the checked item.
+/datum/verbs/menu/proc/Load_checked(client/C) //Loads the checked menu item into a new client. Used by icon menus to invoke the checked item.
return
-/datum/menu/proc/Set_checked(client/C, verbpath)
+/datum/verbs/menu/proc/Set_checked(client/C, verbpath)
if (checkbox == CHECKBOX_GROUP)
C.prefs.menuoptions[type] = verbpath
C.prefs.save_preferences()
@@ -142,7 +60,7 @@ GLOBAL_LIST_EMPTY(menulist)
verbpath = text2path(verbpath)
if (!menutype || !verbpath)
return
- var/datum/menu/M = GLOB.menulist[menutype]
+ var/datum/verbs/menu/M = GLOB.menulist[menutype]
if (!M)
return
if (!(verbpath in typesof("[menutype]/verb")))
@@ -150,7 +68,7 @@ GLOBAL_LIST_EMPTY(menulist)
M.Set_checked(src, verbpath)
-/datum/menu/Icon/Load_checked(client/C) //So we can be lazy, we invoke the "checked" menu item on menu load.
+/datum/verbs/menu/Icon/Load_checked(client/C) //So we can be lazy, we invoke the "checked" menu item on menu load.
var/atom/verb/verbpath = Get_checked(C)
if (!verbpath || !(verbpath in typesof("[type]/verb")))
return
@@ -159,45 +77,45 @@ GLOBAL_LIST_EMPTY(menulist)
else
winset(C, null, "command = [replacetext(verbpath.name, " ", "-")]")
-/datum/menu/Icon/Size
+/datum/verbs/menu/Icon/Size
checkbox = CHECKBOX_GROUP
- default = /datum/menu/Icon/Size/verb/iconstretchtofit
+ default = /datum/verbs/menu/Icon/Size/verb/iconstretchtofit
-/datum/menu/Icon/Size/verb/iconstretchtofit()
+/datum/verbs/menu/Icon/Size/verb/iconstretchtofit()
set name = "@.winset \"mapwindow.map.icon-size=0\""
set desc = "&Auto (stretch-to-fit)"
-/datum/menu/Icon/Size/verb/icon96()
+/datum/verbs/menu/Icon/Size/verb/icon96()
set name = "@.winset \"mapwindow.map.icon-size=96\""
set desc = "&96x96 (3x)"
-/datum/menu/Icon/Size/verb/icon64()
+/datum/verbs/menu/Icon/Size/verb/icon64()
set name = "@.winset \"mapwindow.map.icon-size=64\""
set desc = "&64x64 (2x)"
-/datum/menu/Icon/Size/verb/icon48()
+/datum/verbs/menu/Icon/Size/verb/icon48()
set name = "@.winset \"mapwindow.map.icon-size=48\""
set desc = "&48x48 (1.5x)"
-/datum/menu/Icon/Size/verb/icon32()
+/datum/verbs/menu/Icon/Size/verb/icon32()
set name = "@.winset \"mapwindow.map.icon-size=32\""
set desc = "&32x32 (1x)"
-/datum/menu/Icon/Scaling
+/datum/verbs/menu/Icon/Scaling
checkbox = CHECKBOX_GROUP
name = "Scaling Mode"
- default = /datum/menu/Icon/Scaling/verb/NN
+ default = /datum/verbs/menu/Icon/Scaling/verb/NN
-/datum/menu/Icon/Scaling/verb/NN()
+/datum/verbs/menu/Icon/Scaling/verb/NN()
set name = "@.winset \"mapwindow.map.zoom-mode=distort\""
set desc = "Nearest Neighbor"
-/datum/menu/Icon/Scaling/verb/PS()
+/datum/verbs/menu/Icon/Scaling/verb/PS()
set name = "@.winset \"mapwindow.map.zoom-mode=normal\""
set desc = "Point Sampling"
-/datum/menu/Icon/Scaling/verb/BL()
+/datum/verbs/menu/Icon/Scaling/verb/BL()
set name = "@.winset \"mapwindow.map.zoom-mode=blur\""
set desc = "Bilinear"
diff --git a/tgstation.dme b/tgstation.dme
index 2ef1dca839..11a60bddb3 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -264,6 +264,7 @@
#include "code\datums\ruins.dm"
#include "code\datums\shuttles.dm"
#include "code\datums\soullink.dm"
+#include "code\datums\verbs.dm"
#include "code\datums\votablemap.dm"
#include "code\datums\antagonists\antag_datum.dm"
#include "code\datums\antagonists\datum_clockcult.dm"
@@ -440,17 +441,17 @@
#include "code\game\gamemodes\clock_cult\clock_effects\spatial_gateway.dm"
#include "code\game\gamemodes\clock_cult\clock_helpers\clock_powerdrain.dm"
#include "code\game\gamemodes\clock_cult\clock_helpers\component_helpers.dm"
+#include "code\game\gamemodes\clock_cult\clock_helpers\fabrication_helpers.dm"
#include "code\game\gamemodes\clock_cult\clock_helpers\hierophant_network.dm"
-#include "code\game\gamemodes\clock_cult\clock_helpers\proselytizer_helpers.dm"
#include "code\game\gamemodes\clock_cult\clock_helpers\ratvarian_language.dm"
#include "code\game\gamemodes\clock_cult\clock_helpers\scripture_checks.dm"
#include "code\game\gamemodes\clock_cult\clock_helpers\slab_abilities.dm"
#include "code\game\gamemodes\clock_cult\clock_items\clock_components.dm"
#include "code\game\gamemodes\clock_cult\clock_items\clockwork_armor.dm"
-#include "code\game\gamemodes\clock_cult\clock_items\clockwork_proselytizer.dm"
#include "code\game\gamemodes\clock_cult\clock_items\clockwork_slab.dm"
#include "code\game\gamemodes\clock_cult\clock_items\judicial_visor.dm"
#include "code\game\gamemodes\clock_cult\clock_items\ratvarian_spear.dm"
+#include "code\game\gamemodes\clock_cult\clock_items\replica_fabricator.dm"
#include "code\game\gamemodes\clock_cult\clock_items\soul_vessel.dm"
#include "code\game\gamemodes\clock_cult\clock_items\wraith_spectacles.dm"
#include "code\game\gamemodes\clock_cult\clock_mobs\anima_fragment.dm"
@@ -832,6 +833,7 @@
#include "code\game\objects\items\weapons\his_grace.dm"
#include "code\game\objects\items\weapons\holosign_creator.dm"
#include "code\game\objects\items\weapons\holy_weapons.dm"
+#include "code\game\objects\items\weapons\inducer.dm"
#include "code\game\objects\items\weapons\kitchen.dm"
#include "code\game\objects\items\weapons\manuals.dm"
#include "code\game\objects\items\weapons\miscellaneous.dm"
@@ -933,6 +935,7 @@
#include "code\game\objects\structures\ladders.dm"
#include "code\game\objects\structures\lattice.dm"
#include "code\game\objects\structures\life_candle.dm"
+#include "code\game\objects\structures\manned_turret.dm"
#include "code\game\objects\structures\memorial.dm"
#include "code\game\objects\structures\mineral_doors.dm"
#include "code\game\objects\structures\mirror.dm"