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"